Merge branch 'master' of somewhatlurker/PD-Loader into master

This commit is contained in:
nastys
2019-09-01 10:54:42 +00:00
committed by Gogs
14 changed files with 1038 additions and 93 deletions
+2 -1
View File
@@ -158,7 +158,8 @@ void FindFiles(WIN32_FIND_DATAW* fd)
if (fd->cFileName[pos - 4] == '.' &&
(fd->cFileName[pos - 3] == 'd' || fd->cFileName[pos - 3] == 'D') &&
(fd->cFileName[pos - 2] == 'v' || fd->cFileName[pos - 2] == 'V') &&
(fd->cFileName[pos - 1] == 'a' || fd->cFileName[pos - 1] == 'A'))
(fd->cFileName[pos - 1] == 'a' || fd->cFileName[pos - 1] == 'A') &&
GetPrivateProfileIntW(L"plugins", fd->cFileName, TRUE, iniPaths))
{
auto path = dir + L'\\' + fd->cFileName;
@@ -82,6 +82,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\framework.h" />
<ClInclude Include="src\PluginConfigApi.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
@@ -23,5 +23,8 @@
<ClInclude Include="src\framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\PluginConfigApi.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
@@ -0,0 +1,168 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <vector>
// resolution class to store and sort the width and height easily
class resolution
{
public:
unsigned int width;
unsigned int height;
resolution()
{
width = 0;
height = 0;
}
resolution(unsigned int width, unsigned int height)
{
resolution::width = width;
resolution::height = height;
}
bool operator ==(const resolution &res2)
{
return width == res2.width && height == res2.height;
}
// in comparisons width takes priority because it's usually displayed first
bool operator <(const resolution &res2)
{
if (width == res2.width)
return height < res2.height;
else
return width < res2.width;
}
bool operator >(const resolution &res2)
{
if (width == res2.width)
return height > res2.height;
else
return width > res2.width;
}
};
namespace PluginConfig
{
#pragma pack(push, 1)
enum ConfigType {
CONFIG_BOOLEAN,
CONFIG_NUMERIC,
CONFIG_STRING,
CONFIG_DROPDOWN_INDEX,
CONFIG_DROPDOWN_TEXT,
CONFIG_DROPDOWN_NUMBER,
CONFIG_RESOLUTION,
CONFIG_GROUP_START,
CONFIG_GROUP_END,
CONFIG_BUTTON,
CONFIG_SPACER
};
struct PluginConfigBooleanData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
bool defaultVal;
bool saveAsString;
};
struct PluginConfigNumericData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
int defaultVal;
int minVal;
int maxVal;
};
struct PluginConfigStringData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
LPCWSTR defaultVal;
bool useUtf8;
};
struct PluginConfigDropdownIndexData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
int defaultVal;
std::vector<LPCWSTR> valueStrings;
};
struct PluginConfigDropdownTextData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
LPCWSTR defaultVal;
std::vector<LPCWSTR> valueStrings;
bool editable;
bool useUtf8;
};
struct PluginConfigDropdownNumberData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
int defaultVal;
std::vector<int> valueInts;
bool editable;
};
struct PluginConfigResolutionData {
LPCWSTR iniVarName;
LPCWSTR iniVarName2;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
resolution defaultVal;
std::vector<resolution> valueResolutions;
bool editable;
};
struct PluginConfigGroupData
{
LPCWSTR name;
int height;
};
struct PluginConfigButtonData {
LPCWSTR friendlyName;
LPCWSTR description;
void(*func)();
};
struct PluginConfigSpacerData {
int height;
};
struct PluginConfigOption
{
ConfigType cfgType;
void* data;
};
struct PluginConfigArray
{
int len;
PluginConfigOption* options;
};
#pragma pack(pop)
}
@@ -1,4 +1,5 @@
#include "framework.h"
#include "PluginConfigApi.h"
#include <detours.h>
#pragma comment(lib, "detours.lib")
@@ -7,6 +8,7 @@
#include <vector>
#include <strsafe.h>
#include <bassasio.h>
#include <shellapi.h>
void InjectCode(void* address, const std::vector<uint8_t> data)
{
@@ -410,3 +412,37 @@ BOOL APIENTRY DllMain(HMODULE hModule,
return TRUE;
}
using namespace PluginConfig;
void OpenWiki()
{
ShellExecuteW(NULL, L"open", L"https://github.com/somewhatlurker/DivaSound/wiki", NULL, NULL, SW_SHOW);
}
PluginConfigOption config[] = {
{ CONFIG_DROPDOWN_TEXT, new PluginConfigDropdownTextData{L"backend", L"general", CONFIG_FILE, L"Backend:", L"Sets the audio output protocol.", L"WASAPI", std::vector<LPCWSTR>({ L"WASAPI", L"WASAPI_Exclusive" }), true, false } },
{ CONFIG_DROPDOWN_NUMBER, new PluginConfigDropdownNumberData{ L"channels", L"general", CONFIG_FILE, L"Channels:", L"Sets the number of channels.", 2, std::vector<int>({ 2, 4 }), false } },
{ CONFIG_DROPDOWN_NUMBER, new PluginConfigDropdownNumberData{ L"bit_depth", L"general", CONFIG_FILE, L"Bit Depth:", L"Sets the audio sample format.\n(32 uses floating point samples)", 16, std::vector<int>({ 16, 24, 32 }), false } },
{ CONFIG_NUMERIC, new PluginConfigNumericData{ L"buffer_size", L"buffer", CONFIG_FILE, L"Target Buffer Size:", L"Sets the target buffer size in ms.\nWASAPI will often ignore this and adapt to your hardware config automatically.", 10, 1, 100 } },
{ CONFIG_NUMERIC, new PluginConfigNumericData{ L"periods", L"buffer", CONFIG_FILE, L"Buffer Periods:", L"Sets how often the buffer should be filled.\nFewer periods usually allows for lower latency, but lowering this may cause issues.", 2, 1, 8 } },
{ CONFIG_BOOLEAN, new PluginConfigBooleanData{ L"alternate_init", L"general", CONFIG_FILE, L"Use new init", L"Use the full initialisation replacement.\nTry unchecking this if DivaSound seems to cause crashes.", true } },
{ CONFIG_SPACER, new PluginConfigSpacerData{ 8 } },
{ CONFIG_BUTTON, new PluginConfigButtonData{ L"Help", L"Get help on the DivaSound wiki.", OpenWiki } },
{ CONFIG_SPACER, new PluginConfigSpacerData{ 8 } },
};
extern "C" __declspec(dllexport) LPCWSTR GetPluginName(void)
{
return L"DivaSound";
}
extern "C" __declspec(dllexport) LPCWSTR GetPluginDescription(void)
{
return L"DivaSound Plugin by somewhatlurker\n\nDivaSound replaces the game's original audio output,\nimproving device support and adding configurable options.";
}
extern "C" __declspec(dllexport) PluginConfigArray GetPluginOptions(void)
{
return PluginConfigArray{ _countof(config), config };
}
@@ -9,6 +9,8 @@
#include <msclr\marshal_cppstd.h>
#include "PluginConfigApi.h"
using namespace System;
using namespace System::Windows::Forms;
@@ -16,6 +18,7 @@ float BaseScaleSize = 96;
int Col1Width = 110;
int Col2Left = 114;
int Col2Width = 110;
int ConfigBtnLeft = 160;
int ControlSpacing = 6;
// Custom function. Works like GetPrivateProfileIntW but returns bool. Can detect a numeric value or string.
@@ -39,46 +42,9 @@ bool GetPrivateProfileBoolW(LPCWSTR lpAppName, LPCWSTR lpKeyName, bool default,
return out;
}
// resolution class to store and sort the width and height easily
class resolution
{
public:
unsigned int width;
unsigned int height;
resolution()
{
width = 0;
height = 0;
}
resolution(unsigned int width, unsigned int height)
{
resolution::width = width;
resolution::height = height;
}
bool operator ==(const resolution &res2)
{
return width == res2.width && height == res2.height;
}
// in comparisons width takes priority because it's usually displayed first
bool operator <(const resolution &res2)
{
if (width == res2.width)
return height < res2.height;
else
return width < res2.width;
}
bool operator >(const resolution &res2)
{
if (width == res2.width)
return height > res2.height;
else
return width > res2.width;
}
};
// declare this early (actual definitions below)
class ConfigOptionBase;
Panel^ MakePanel(int width, int height, std::vector<ConfigOptionBase*> &cfg, ToolTip^ tooltip, bool* hasChanged);
ref class ComboboxValidation
@@ -178,7 +144,78 @@ public:
};
static ref class ChangeHandler
ref class PluginConfigHandler
{
public:
Form^ form;
PluginConfigHandler(Panel^ optspanel, String^ title)
{
form = gcnew Form();
form->Text = title;
form->FormBorderStyle = FormBorderStyle::FixedDialog;
form->StartPosition = FormStartPosition::CenterScreen;
form->MaximizeBox = false;
form->MinimizeBox = false;
form->ShowInTaskbar = false;
form->ShowIcon = false;
//form->TopMost = true;
form->BackColor = Drawing::Color::FromArgb(64, 64, 64);
form->ForeColor = Drawing::Color::White;
optspanel->Left = 0;
optspanel->Top = 0;
Button^ OkBtn = gcnew Button();
OkBtn->Text = L"OK";
OkBtn->Left = 4;
OkBtn->Top = optspanel->Bottom + 4;
OkBtn->AutoSize = true;
OkBtn->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
form->ClientSize = Drawing::Size(optspanel->Width, OkBtn->Bottom + 4);
form->Controls->Add(optspanel);
form->Controls->Add(OkBtn);
form->AcceptButton = OkBtn;
form->FormClosing += gcnew System::Windows::Forms::FormClosingEventHandler(this, &PluginConfigHandler::FormClosing);
OkBtn->Click += gcnew EventHandler(this, &PluginConfigHandler::OkClick);
}
System::Void OpenForm(System::Object^ sender, System::EventArgs^ e)
{
// ShowDialog seems to prevent disposal by copying the panel...
// which would be fine if I didn't rely on using the control handles
// MessageBox::Show(form->Controls[0]->Handle.ToString());
//Application::OpenForms[0]->Enabled = false;
form->Owner = Application::OpenForms[0];
if (form->Visible)
form->Hide();
form->Show();
}
System::Void FormClosing(System::Object^ sender, FormClosingEventArgs^ e)
{
if (e->CloseReason == CloseReason::UserClosing)
{
form->Hide();
//Application::OpenForms[0]->Enabled = true;
e->Cancel = true;
}
}
System::Void OkClick(System::Object^ sender, System::EventArgs^ e)
{
form->Close();
}
};
ref class ChangeHandler
{
public:
bool* changebool;
@@ -194,6 +231,22 @@ public:
}
};
ref class CustomFuncHandler
{
public:
void(*_func)();
CustomFuncHandler(void(*func)())
{
_func = func;
}
System::Void RunFunc(System::Object^ sender, System::EventArgs^ e)
{
_func();
}
};
class ConfigOptionBase
{
@@ -220,6 +273,42 @@ public:
};
class OptionMetaGroupStart : public ConfigOptionBase
{
public:
int _height;
OptionMetaGroupStart(LPCWSTR friendlyName, int height)
{
_friendlyName = friendlyName;
_height = height;
}
};
class OptionMetaGroupEnd : public ConfigOptionBase
{
public:
OptionMetaGroupEnd()
{
}
};
class OptionMetaSpacer : public ConfigOptionBase
{
public:
int _height;
OptionMetaSpacer(int height)
{
_height = height;
}
virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
{
return _height;
}
};
class BooleanOption : public ConfigOptionBase
{
public:
@@ -252,15 +341,20 @@ public:
cb->BackColor = System::Drawing::Color::FromArgb(0, 0, 0, 0);
Form^ RootForm = panel->FindForm();
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
float ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
float ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
float ScaleWidth = 1.0f;
float ScaleHeight = 1.0f;
if (RootForm)
{
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
}
cb->Scale(ScaleWidth, ScaleHeight);
tooltip->SetToolTip(cb, gcnew String(_description));
if (hasChanged == nullptr)
hasChanged = new bool;
hasChanged = new bool(false);
ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
cb->CheckedChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
@@ -325,9 +419,14 @@ public:
numberbox->AutoSize = true;
Form^ RootForm = panel->FindForm();
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
float ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
float ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
float ScaleWidth = 1.0f;
float ScaleHeight = 1.0f;
if (RootForm)
{
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
}
label->Scale(ScaleWidth, ScaleHeight);
numberbox->Scale(ScaleWidth, ScaleHeight);
@@ -335,7 +434,7 @@ public:
tooltip->SetToolTip(numberbox, gcnew String(_description));
if (hasChanged == nullptr)
hasChanged = new bool;
hasChanged = new bool(false);
ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
numberbox->ValueChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
@@ -404,9 +503,14 @@ public:
textbox->AutoSize = true;
Form^ RootForm = panel->FindForm();
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
float ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
float ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
float ScaleWidth = 1.0f;
float ScaleHeight = 1.0f;
if (RootForm)
{
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
}
label->Scale(ScaleWidth, ScaleHeight);
textbox->Scale(ScaleWidth, ScaleHeight);
@@ -419,7 +523,7 @@ public:
tooltip->SetToolTip(textbox, gcnew String(_description));
if (hasChanged == nullptr)
hasChanged = new bool;
hasChanged = new bool(false);
ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
textbox->TextChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
@@ -498,9 +602,14 @@ public:
combobox->DropDownStyle = ComboBoxStyle::DropDownList;
Form^ RootForm = panel->FindForm();
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
float ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
float ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
float ScaleWidth = 1.0f;
float ScaleHeight = 1.0f;
if (RootForm)
{
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
}
label->Scale(ScaleWidth, ScaleHeight);
combobox->Scale(ScaleWidth, ScaleHeight);
@@ -508,7 +617,7 @@ public:
tooltip->SetToolTip(combobox, gcnew String(_description));
if (hasChanged == nullptr)
hasChanged = new bool;
hasChanged = new bool(false);
ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
combobox->SelectedIndexChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
@@ -532,14 +641,15 @@ public:
};
class EditableDropdownOption : public ConfigOptionBase
class DropdownTextOption : public ConfigOptionBase
{
public:
LPCWSTR _defaultVal;
std::vector<LPCWSTR> _valueStrings;
bool _editable;
bool _useUtf8;
EditableDropdownOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, LPCWSTR defaultVal, std::vector<LPCWSTR> valueStrings, bool useUtf8)
DropdownTextOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, LPCWSTR defaultVal, std::vector<LPCWSTR> valueStrings, bool editable, bool useUtf8)
{
_iniVarName = iniVarName;
_iniSectionName = iniSectionName;
@@ -548,6 +658,7 @@ public:
_description = description;
_defaultVal = defaultVal;
_valueStrings = valueStrings;
_editable = editable;
_useUtf8 = useUtf8;
}
@@ -582,12 +693,21 @@ public:
combobox->Width = Col2Width;
combobox->AutoSize = true;
combobox->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
combobox->DropDownStyle = ComboBoxStyle::DropDown;
if (_editable)
combobox->DropDownStyle = ComboBoxStyle::DropDown;
else
combobox->DropDownStyle = ComboBoxStyle::DropDownList;
Form^ RootForm = panel->FindForm();
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
float ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
float ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
float ScaleWidth = 1.0f;
float ScaleHeight = 1.0f;
if (RootForm)
{
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
}
label->Scale(ScaleWidth, ScaleHeight);
combobox->Scale(ScaleWidth, ScaleHeight);
@@ -601,9 +721,12 @@ public:
tooltip->SetToolTip(combobox, gcnew String(_description));
if (hasChanged == nullptr)
hasChanged = new bool;
hasChanged = new bool(false);
ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
combobox->TextChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
if (_editable)
combobox->TextChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
else
combobox->SelectedIndexChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
panel->Controls->Add(label);
panel->Controls->Add(combobox);
@@ -639,13 +762,14 @@ public:
};
class EditableDropdownNumberOption : public ConfigOptionBase
class DropdownNumberOption : public ConfigOptionBase
{
public:
int _defaultVal;
std::vector<int> _valueInts;
bool _editable;
EditableDropdownNumberOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, int defaultVal, std::vector<int> valueInts)
DropdownNumberOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, int defaultVal, std::vector<int> valueInts, bool editable)
{
_iniVarName = iniVarName;
_iniSectionName = iniSectionName;
@@ -654,6 +778,7 @@ public:
_description = description;
_defaultVal = defaultVal;
_valueInts = valueInts;
_editable = editable;
}
virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
@@ -682,12 +807,21 @@ public:
combobox->Width = Col2Width;
combobox->AutoSize = true;
combobox->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
combobox->DropDownStyle = ComboBoxStyle::DropDown;
if (_editable)
combobox->DropDownStyle = ComboBoxStyle::DropDown;
else
combobox->DropDownStyle = ComboBoxStyle::DropDownList;
Form^ RootForm = panel->FindForm();
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
float ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
float ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
float ScaleWidth = 1.0f;
float ScaleHeight = 1.0f;
if (RootForm)
{
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
}
label->Scale(ScaleWidth, ScaleHeight);
combobox->Scale(ScaleWidth, ScaleHeight);
@@ -698,9 +832,12 @@ public:
combobox->Leave += gcnew System::EventHandler(validation, &ComboboxValidation::CheckNumberLeave);
if (hasChanged == nullptr)
hasChanged = new bool;
hasChanged = new bool(false);
ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
combobox->TextChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
if (_editable)
combobox->TextChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
else
combobox->SelectedIndexChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
panel->Controls->Add(label);
panel->Controls->Add(combobox);
@@ -729,8 +866,9 @@ public:
LPCWSTR _iniVarName2;
resolution _defaultVal;
std::vector<resolution> _valueResolutions;
bool _editable;
ResolutionOption(LPCWSTR iniVarName, LPCWSTR iniVarName2, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, resolution defaultVal, std::vector<resolution> valueResolutions)
ResolutionOption(LPCWSTR iniVarName, LPCWSTR iniVarName2, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, resolution defaultVal, std::vector<resolution> valueResolutions, bool editable)
{
_iniVarName = iniVarName;
_iniVarName2 = iniVarName2;
@@ -740,6 +878,7 @@ public:
_description = description;
_defaultVal = defaultVal;
_valueResolutions = valueResolutions;
_editable = editable;
}
virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
@@ -777,12 +916,21 @@ public:
combobox->Width = Col2Width;
combobox->AutoSize = true;
combobox->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
combobox->DropDownStyle = ComboBoxStyle::DropDown;
if (_editable)
combobox->DropDownStyle = ComboBoxStyle::DropDown;
else
combobox->DropDownStyle = ComboBoxStyle::DropDownList;
Form^ RootForm = panel->FindForm();
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
float ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
float ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
float ScaleWidth = 1.0f;
float ScaleHeight = 1.0f;
if (RootForm)
{
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
}
label->Scale(ScaleWidth, ScaleHeight);
combobox->Scale(ScaleWidth, ScaleHeight);
@@ -790,9 +938,12 @@ public:
tooltip->SetToolTip(combobox, gcnew String(_description));
if (hasChanged == nullptr)
hasChanged = new bool;
hasChanged = new bool(false);
ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
combobox->TextChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
if (_editable)
combobox->TextChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
else
combobox->SelectedIndexChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
ComboboxValidation^ validation = gcnew ComboboxValidation(combobox);
combobox->Leave += gcnew System::EventHandler(validation, &ComboboxValidation::CheckResolutionLeave);
@@ -823,4 +974,209 @@ public:
WritePrivateProfileStringW(_iniSectionName, _iniVarName2, tempWStr.c_str(), _iniFilePath);
}
};
};
class ButtonOption : public ConfigOptionBase
{
public:
void(*_func)();
ButtonOption(LPCWSTR friendlyName, LPCWSTR description, void(*func)())
{
_friendlyName = friendlyName;
_description = description;
_func = func;
}
virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
{
Button^ button = gcnew Button();
button->Text = gcnew String(_friendlyName);
button->Left = left;
button->Top = top;
button->AutoSize = true;
button->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
Form^ RootForm = panel->FindForm();
float ScaleWidth = 1.0f;
float ScaleHeight = 1.0f;
if (RootForm)
{
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
}
button->Scale(ScaleWidth, ScaleHeight);
tooltip->SetToolTip(button, gcnew String(_description));
CustomFuncHandler^ funchandler = gcnew CustomFuncHandler(_func);
button->Click += gcnew System::EventHandler(funchandler, &CustomFuncHandler::RunFunc);
panel->Controls->Add(button);
int ControlHeight = button->Height / ScaleHeight;
return ControlHeight + ControlSpacing;
}
};
class PluginOption : public ConfigOptionBase
{
public:
bool _defaultVal;
std::vector<ConfigOptionBase*> _configopts;
PluginOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, bool defaultVal, std::vector<ConfigOptionBase*> configopts)
{
_iniVarName = iniVarName;
_iniSectionName = iniSectionName;
_iniFilePath = iniFilePath;
_friendlyName = friendlyName;
_description = description;
_defaultVal = defaultVal;
_configopts = configopts;
}
virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
{
CheckBox^ cb = gcnew CheckBox();
Button^ button = gcnew Button();
cb->Text = gcnew String(_friendlyName);
cb->Checked = GetPrivateProfileBoolW(_iniSectionName, _iniVarName, _defaultVal, _iniFilePath);
cb->Left = left + 2;
cb->Top = top + 3;
cb->AutoSize = true;
cb->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
// hack to ensure high contrast
cb->BackColor = System::Drawing::Color::FromArgb(0, 0, 0, 0);
button->Text = L"Config";
button->Left = left + ConfigBtnLeft;
button->Top = top;
button->AutoSize = true;
button->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
Form^ RootForm = panel->FindForm();
float ScaleWidth = 1.0f;
float ScaleHeight = 1.0f;
if (RootForm)
{
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
}
cb->Scale(ScaleWidth, ScaleHeight);
button->Scale(ScaleWidth, ScaleHeight);
tooltip->SetToolTip(cb, gcnew String(_description));
if (hasChanged == nullptr)
hasChanged = new bool(false);
ChangeHandler^ changehandler = gcnew ChangeHandler(hasChanged);
cb->CheckedChanged += gcnew System::EventHandler(changehandler, &ChangeHandler::SetChanged);
panel->Controls->Add(cb);
mainControlHandle = cb->Handle;
if (_configopts.size() > 0)
{
ToolTip^ paneltooltip = gcnew ToolTip();
Panel^ configPanel = MakePanel((Col2Left + Col2Width + 64), 250, _configopts, paneltooltip, hasChanged);
configPanel->Scale(ScaleWidth, ScaleHeight);
PluginConfigHandler^ confighandler = gcnew PluginConfigHandler(configPanel, gcnew String(_friendlyName) + " Options");
button->Click += gcnew System::EventHandler(confighandler, &PluginConfigHandler::OpenForm);
panel->Controls->Add(button);
}
int ControlHeight = button->Height / ScaleHeight;
return ControlHeight + ControlSpacing;
}
virtual void SaveOption()
{
bool boolEnabled = ((CheckBox^)CheckBox::FromHandle(mainControlHandle))->Checked;
WritePrivateProfileStringW(_iniSectionName, _iniVarName, boolEnabled ? L"1" : L"0", _iniFilePath);
for (ConfigOptionBase* opt : _configopts)
{
opt->SaveOption();
}
}
};
Panel^ MakePanel(int width, int height, std::vector<ConfigOptionBase*> &cfg, ToolTip^ tooltip, bool* hasChanged)
{
Panel^ outpanel = gcnew Panel();
outpanel->Width = width;
outpanel->Height = height;
outpanel->AutoScroll = true;
Form^ RootForm = outpanel->FindForm();
float ScaleWidth = 1.0f;
float ScaleHeight = 1.0f;
if (RootForm)
{
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
}
int curX = 12;
int curY = 3;
for (int i = 0; i < cfg.size(); i++)
{
if (typeid(*cfg[i]).hash_code() == typeid(OptionMetaGroupEnd).hash_code())
continue;
if (typeid(*cfg[i]).hash_code() == typeid(OptionMetaGroupStart).hash_code())
{
OptionMetaGroupStart* groupData = (OptionMetaGroupStart*)(cfg[i]);
GroupBox^ groupbox = gcnew GroupBox();
groupbox->Width = width - (ScaleWidth * 8);
groupbox->Height = ScaleHeight * groupData->_height;
groupbox->Left = ScaleWidth * 4;
groupbox->Top = ScaleHeight * curY;
groupbox->Text = gcnew String(groupData->_friendlyName);
// find the end of this group by simple iteration keeping track of indent level
int level = 1;
int endidx;
for (endidx = i + 1; endidx < cfg.size(); endidx++)
{
if (typeid(*cfg[endidx]).hash_code() == typeid(OptionMetaGroupStart).hash_code())
level++;
if (typeid(*cfg[endidx]).hash_code() == typeid(OptionMetaGroupEnd).hash_code())
level--;
if (level == 0)
break;
}
Panel^ groupPanel = MakePanel(groupbox->Width - (ScaleWidth * 8), groupbox->Height - (ScaleHeight * 10), std::vector<ConfigOptionBase*>(&(cfg[i + 1]), &(cfg[endidx])), tooltip, hasChanged);
groupPanel->Left = ScaleWidth * 12;
groupPanel->Top = ScaleHeight * (curY + 8);
groupbox->Controls->Add(groupPanel);
outpanel->Controls->Add(groupbox);
i = endidx;
curY += groupData->_height;
}
else
{
cfg[i]->hasChanged = hasChanged;
curY += cfg[i]->AddToPanel(outpanel, curX, curY, tooltip);
}
}
return outpanel;
}
@@ -167,6 +167,8 @@
<ItemGroup>
<ClInclude Include="ConfigOption.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="PluginConfig.h" />
<ClInclude Include="PluginConfigApi.h" />
<ClInclude Include="SkinnedMessageBox.h" />
<ClInclude Include="TabPadding.h" />
<ClInclude Include="ui.h">
@@ -0,0 +1,71 @@
#pragma once
#include "ConfigOption.h"
#include "PluginConfigApi.h"
namespace PluginConfig
{
ConfigOptionBase* GetConfigOption(PluginConfigOption cfg)
{
PluginConfigBooleanData* boolData = (PluginConfigBooleanData*)(cfg.data);
PluginConfigNumericData* numericData = (PluginConfigNumericData*)(cfg.data);
PluginConfigStringData* stringData = (PluginConfigStringData*)(cfg.data);
PluginConfigDropdownIndexData* ddIdxData = (PluginConfigDropdownIndexData*)(cfg.data);
PluginConfigDropdownTextData* ddTextData = (PluginConfigDropdownTextData*)(cfg.data);
PluginConfigDropdownNumberData* ddNumberData = (PluginConfigDropdownNumberData*)(cfg.data);
PluginConfigResolutionData* resData = (PluginConfigResolutionData*)(cfg.data);
PluginConfigGroupData* groupData = (PluginConfigGroupData*)(cfg.data);
PluginConfigButtonData* btnData = (PluginConfigButtonData*)(cfg.data);
PluginConfigSpacerData* spacerData = (PluginConfigSpacerData*)(cfg.data);
switch (cfg.cfgType)
{
case CONFIG_BOOLEAN:
return new BooleanOption(boolData->iniVarName, boolData->iniSectionName, boolData->iniFilePath, boolData->friendlyName, boolData->description, boolData->defaultVal, boolData->saveAsString);
case CONFIG_NUMERIC:
return new NumericOption(numericData->iniVarName, numericData->iniSectionName, numericData->iniFilePath, numericData->friendlyName, numericData->description, numericData->defaultVal, numericData->minVal, numericData->maxVal);
case CONFIG_STRING:
return new StringOption(stringData->iniVarName, stringData->iniSectionName, stringData->iniFilePath, stringData->friendlyName, stringData->description, stringData->defaultVal, stringData->useUtf8);
case CONFIG_DROPDOWN_INDEX:
return new DropdownOption(ddIdxData->iniVarName, ddIdxData->iniSectionName, ddIdxData->iniFilePath, ddIdxData->friendlyName, ddIdxData->description, ddIdxData->defaultVal, ddIdxData->valueStrings);
case CONFIG_DROPDOWN_TEXT:
return new DropdownTextOption(ddTextData->iniVarName, ddTextData->iniSectionName, ddTextData->iniFilePath, ddTextData->friendlyName, ddTextData->description, ddTextData->defaultVal, ddTextData->valueStrings, ddTextData->editable, ddTextData->useUtf8);
case CONFIG_DROPDOWN_NUMBER:
return new DropdownNumberOption(ddNumberData->iniVarName, ddNumberData->iniSectionName, ddNumberData->iniFilePath, ddNumberData->friendlyName, ddNumberData->description, ddNumberData->defaultVal, ddNumberData->valueInts, ddNumberData->editable);
case CONFIG_RESOLUTION:
return new ResolutionOption(resData->iniVarName, resData->iniVarName2, resData->iniSectionName, resData->iniFilePath, resData->friendlyName, resData->description, resData->defaultVal, resData->valueResolutions, resData->editable);
case CONFIG_GROUP_START:
return new OptionMetaGroupStart(groupData->name, groupData->height);
case CONFIG_GROUP_END:
return new OptionMetaGroupEnd();
case CONFIG_BUTTON:
return new ButtonOption(btnData->friendlyName, btnData->description, btnData->func);
case CONFIG_SPACER:
return new OptionMetaSpacer(spacerData->height);
default:
return new ConfigOptionBase();
}
}
std::vector<ConfigOptionBase*> GetConfigOptionVec(PluginConfigArray &in)
{
std::vector<ConfigOptionBase*> outvec;
for (int i = 0; i < in.len; i++)
{
// basic check for validity
if (in.options[i].data == nullptr)
break;
outvec.push_back(GetConfigOption(in.options[i]));
}
return outvec;
}
/*std::vector<PluginConfigOption> testcfg =
{
PluginConfigOption{ CONFIG_GROUP_START, new PluginConfigGroupData{L"Screen Resolution", 400 } },
PluginConfigOption{ CONFIG_DROPDOWN_INDEX, new PluginConfigDropdownIndexData{ L"display", RESOLUTION_SECTION, CONFIG_FILE, L"Display:", L"Sets the window/screen mode.", 0, std::vector<LPCWSTR>({ L"Windowed", L"Borderless", L"Fullscreen" }) } },
PluginConfigOption{ CONFIG_RESOLUTION, new PluginConfigResolutionData{ L"width", L"height", RESOLUTION_SECTION, CONFIG_FILE, L"Resolution:", L"Sets the display resolution.", resolution(1280, 720), getScreenResolutionsVec(screenModes) } }
};*/
//std::vector<ConfigOptionBase*> testcfgconfigopts = GetConfigOptionVec(testcfg);
};
@@ -0,0 +1,168 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <vector>
// resolution class to store and sort the width and height easily
class resolution
{
public:
unsigned int width;
unsigned int height;
resolution()
{
width = 0;
height = 0;
}
resolution(unsigned int width, unsigned int height)
{
resolution::width = width;
resolution::height = height;
}
bool operator ==(const resolution &res2)
{
return width == res2.width && height == res2.height;
}
// in comparisons width takes priority because it's usually displayed first
bool operator <(const resolution &res2)
{
if (width == res2.width)
return height < res2.height;
else
return width < res2.width;
}
bool operator >(const resolution &res2)
{
if (width == res2.width)
return height > res2.height;
else
return width > res2.width;
}
};
namespace PluginConfig
{
#pragma pack(push, 1)
enum ConfigType {
CONFIG_BOOLEAN,
CONFIG_NUMERIC,
CONFIG_STRING,
CONFIG_DROPDOWN_INDEX,
CONFIG_DROPDOWN_TEXT,
CONFIG_DROPDOWN_NUMBER,
CONFIG_RESOLUTION,
CONFIG_GROUP_START,
CONFIG_GROUP_END,
CONFIG_BUTTON,
CONFIG_SPACER
};
struct PluginConfigBooleanData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
bool defaultVal;
bool saveAsString;
};
struct PluginConfigNumericData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
int defaultVal;
int minVal;
int maxVal;
};
struct PluginConfigStringData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
LPCWSTR defaultVal;
bool useUtf8;
};
struct PluginConfigDropdownIndexData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
int defaultVal;
std::vector<LPCWSTR> valueStrings;
};
struct PluginConfigDropdownTextData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
LPCWSTR defaultVal;
std::vector<LPCWSTR> valueStrings;
bool editable;
bool useUtf8;
};
struct PluginConfigDropdownNumberData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
int defaultVal;
std::vector<int> valueInts;
bool editable;
};
struct PluginConfigResolutionData {
LPCWSTR iniVarName;
LPCWSTR iniVarName2;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
resolution defaultVal;
std::vector<resolution> valueResolutions;
bool editable;
};
struct PluginConfigGroupData
{
LPCWSTR name;
int height;
};
struct PluginConfigButtonData {
LPCWSTR friendlyName;
LPCWSTR description;
void(*func)();
};
struct PluginConfigSpacerData {
int height;
};
struct PluginConfigOption
{
ConfigType cfgType;
void* data;
};
struct PluginConfigArray
{
int len;
PluginConfigOption* options;
};
#pragma pack(pop)
}
@@ -9,6 +9,7 @@
#include <algorithm>
#include "ConfigOption.h"
#include "PluginConfig.h"
int (__cdecl* divaMain)(int argc, const char** argv, const char** envp) = (int(__cdecl*)(int argc, const char** argv, const char** envp))0x140194D90;
@@ -34,13 +35,15 @@ LPCWSTR DIVA_EXECUTABLE = DIVA_EXECUTABLE_STRING.c_str();
wstring DIVA_EXECUTABLE_LAUNCH_STRING = DIVA_EXECUTABLE_STRING + L" --launch";
LPWSTR DIVA_EXECUTABLE_LAUNCH = const_cast<WCHAR*>(DIVA_EXECUTABLE_LAUNCH_STRING.c_str());
wstring CONFIG_FILE_STRING = DirPath() + L"\\plugins\\config.ini";
wstring PLUGINS_DIR = DirPath() + L"\\plugins";
wstring CONFIG_FILE_STRING = PLUGINS_DIR + L"\\config.ini";
LPCWSTR CONFIG_FILE = CONFIG_FILE_STRING.c_str();
wstring COMPONENTS_FILE_STRING = DirPath() + L"\\plugins\\components.ini";
wstring COMPONENTS_FILE_STRING = PLUGINS_DIR + L"\\components.ini";
LPCWSTR COMPONENTS_FILE = COMPONENTS_FILE_STRING.c_str();
wstring PLAYERDATA_FILE_STRING = DirPath() + L"\\plugins\\playerdata.ini";
wstring PLAYERDATA_FILE_STRING = PLUGINS_DIR + L"\\playerdata.ini";
LPCWSTR PLAYERDATA_FILE = PLAYERDATA_FILE_STRING.c_str();
LPCWSTR PATCHES_SECTION = L"patches";
@@ -124,17 +127,17 @@ std::vector<DEVMODEW> screenModes = getScreenModes();
DropdownOption* DisplayModeDropdown = new DropdownOption(L"display", RESOLUTION_SECTION, CONFIG_FILE, L"Display:", L"Sets the window/screen mode.", 0, std::vector<LPCWSTR>({ L"Windowed", L"Borderless", L"Fullscreen" }));
ResolutionOption* DisplayResolutionOption = new ResolutionOption(L"width", L"height", RESOLUTION_SECTION, CONFIG_FILE, L"Resolution:", L"Sets the display resolution.", resolution(1280, 720), getScreenResolutionsVec(screenModes));
ResolutionOption* DisplayResolutionOption = new ResolutionOption(L"width", L"height", RESOLUTION_SECTION, CONFIG_FILE, L"Resolution:", L"Sets the display resolution.", resolution(1280, 720), getScreenResolutionsVec(screenModes), true);
ConfigOptionBase* screenResolutionArray[] = {
DisplayModeDropdown,
DisplayResolutionOption,
//new EditableDropdownNumberOption(L"bitdepth", RESOLUTION_SECTION, CONFIG_FILE, L"Bit Depth:", L"Sets the display bit depth.", 32, getScreenDepthsVec(screenModes)),
new EditableDropdownNumberOption(L"refreshrate", RESOLUTION_SECTION, CONFIG_FILE, L"Refresh Rate:", L"Sets the display refresh rate.", 60, getScreenRatesVec(screenModes)),
//new DropdownNumberOption(L"bitdepth", RESOLUTION_SECTION, CONFIG_FILE, L"Bit Depth:", L"Sets the display bit depth.", 32, getScreenDepthsVec(screenModes), true),
new DropdownNumberOption(L"refreshrate", RESOLUTION_SECTION, CONFIG_FILE, L"Refresh Rate:", L"Sets the display refresh rate.", 60, getScreenRatesVec(screenModes), true),
};
BooleanOption* InternalResolutionCheckbox = new BooleanOption(L"r.enable", RESOLUTION_SECTION, CONFIG_FILE, L"Enable", L"Enable or disable custom internal resolution.", false, false);
ResolutionOption* InternalResolutionOption = new ResolutionOption(L"r.width", L"r.height", RESOLUTION_SECTION, CONFIG_FILE, L"Resolution:", L"Sets the internal resolution.", resolution(1280, 720), std::vector<resolution>({ resolution(640,480), resolution(800,600), resolution(960,720), resolution(1280,720), resolution(1600,900), resolution(1920,1080), resolution(2560,1440), resolution(3200,1800), resolution(3840,2160), resolution(5120,2880), resolution(6400,3600), resolution(7680,4320) }));
ResolutionOption* InternalResolutionOption = new ResolutionOption(L"r.width", L"r.height", RESOLUTION_SECTION, CONFIG_FILE, L"Resolution:", L"Sets the internal resolution.", resolution(1280, 720), std::vector<resolution>({ resolution(640,480), resolution(800,600), resolution(960,720), resolution(1280,720), resolution(1600,900), resolution(1920,1080), resolution(2560,1440), resolution(3200,1800), resolution(3840,2160), resolution(5120,2880), resolution(6400,3600), resolution(7680,4320) }), true);
ConfigOptionBase* internalResolutionArray[] = {
InternalResolutionCheckbox,
@@ -181,6 +184,7 @@ ConfigOptionBase* playerdataArray[] = {
new NumericOption(L"btn_se_equip", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Button Sound:", L"Sets the sound effect for buttons.\n-1 = song default", -1, -1, INT_MAX),
new NumericOption(L"slide_se_equip", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Slide Sound:", L"Sets the sound effect for slides.\n-1 = song default", -1, -1, INT_MAX),
new NumericOption(L"chainslide_se_equip", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Chainslide Sound:", L"Sets the sound effect for chain slides.\n-1 = song default", -1, -1, INT_MAX),
new BooleanOption(L"act_toggle", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Button SE", L"Enables button/slider sounds.", true, true),
new BooleanOption(L"border_great", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Clear Border (Great)", L"Shows the clear border for a great rating on the progress bar.", true, true),
new BooleanOption(L"border_excellent", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Clear Border (Excellent)", L"Shows the clear border for an excellent rating on the progress bar.", true, true),
@@ -265,6 +269,87 @@ void PrependFile(LPCSTR newStr, LPCWSTR fileName)
}
struct PluginInfo {
HMODULE handle;
std::wstring filename;
std::wstring name;
std::wstring description;
std::vector<ConfigOptionBase*> configopts;
};
std::vector<PluginInfo> LoadPlugins()
{
std::vector<PluginInfo> outvec;
HANDLE hFind;
WIN32_FIND_DATAW ffd;
hFind = FindFirstFileW((PLUGINS_DIR + L"\\*.dva").c_str(), &ffd);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
auto pos = wcslen(ffd.cFileName);
if (ffd.cFileName[pos - 4] == '.' &&
(ffd.cFileName[pos - 3] == 'd' || ffd.cFileName[pos - 3] == 'D') &&
(ffd.cFileName[pos - 2] == 'v' || ffd.cFileName[pos - 2] == 'V') &&
(ffd.cFileName[pos - 1] == 'a' || ffd.cFileName[pos - 1] == 'A'))
{
PluginInfo thisplugin;
thisplugin.handle = LoadLibraryW((PLUGINS_DIR + L"\\" + ffd.cFileName).c_str());
thisplugin.filename = ffd.cFileName;
if (thisplugin.handle == NULL)
continue;
auto nameFunc = (LPCWSTR(*)())GetProcAddress(thisplugin.handle, "GetPluginName");
auto descFunc = (LPCWSTR(*)())GetProcAddress(thisplugin.handle, "GetPluginDescription");
auto optsFunc = (PluginConfig::PluginConfigArray(*)())GetProcAddress(thisplugin.handle, "GetPluginOptions");
if (nameFunc != NULL)
thisplugin.name = nameFunc();
else
thisplugin.name = thisplugin.filename;
if (descFunc != NULL)
thisplugin.description = descFunc();
else
thisplugin.description = (thisplugin.filename + L" Plugin").c_str();
if (optsFunc != NULL)
thisplugin.configopts = PluginConfig::GetConfigOptionVec(optsFunc());
// sometimes this might screw with custom button config, so let's just not free stuff
// FreeLibrary(thisplugin.handle);
outvec.push_back(thisplugin);
}
}
} while (FindNextFileW(hFind, &ffd));
FindClose(hFind);
}
return outvec;
}
// don't load until actually needed to avoid loading disabled plugins
std::vector<PluginInfo> AllPlugins; // = LoadPlugins();
std::vector<PluginOption*> GetPluginOptions(std::vector<PluginInfo>* plugins)
{
std::vector<PluginOption*> outvec;
for (PluginInfo &pi : *plugins)
{
PluginOption* opt = new PluginOption(pi.filename.c_str(), L"plugins", CONFIG_FILE, pi.name.c_str(), pi.description.c_str(), true, pi.configopts);
outvec.push_back(opt);
}
return outvec;
}
// don't load until actually needed to avoid loading disabled plugins
std::vector<PluginOption*> AllPluginOpts; // = GetPluginOptions(&AllPlugins);
// used to trick Optimus into switching to the NVIDIA GPU
HMODULE nvcudaModule = LoadLibraryW(L"nvcuda.dll");
// cuInit actually returns a CUresult, but we don't really care about it
+50
View File
@@ -6,6 +6,7 @@
#include <GL\freeglut.h>
#include <GL\GL.h>
#include "SkinnedMessageBox.h"
#include "PluginConfig.h"
namespace Launcher {
@@ -90,6 +91,7 @@ namespace Launcher {
this->panel_Patches->PerformLayout();
this->panel_Playerdata->SuspendLayout();
// populate playerdata options from array in framework
@@ -118,6 +120,20 @@ namespace Launcher {
this->panel_Components->PerformLayout();
AllPlugins = LoadPlugins();
AllPluginOpts = GetPluginOptions(&AllPlugins);
this->panel_Plugins->SuspendLayout();
int pluginsY = 3;
for (ConfigOptionBase* option : AllPluginOpts)
{
option->hasChanged = ConfigHasChanged;
pluginsY += option->AddToPanel(panel_Plugins, 12, pluginsY, toolTip1);
}
this->panel_Plugins->ResumeLayout(false);
this->panel_Plugins->PerformLayout();
// trick Optimus into switching to the NVIDIA GPU
if (cuInit != NULL) cuInit(0);
@@ -176,6 +192,8 @@ namespace Launcher {
private: System::Windows::Forms::Panel^ panel_Components;
private: System::Windows::Forms::TabPage^ tabPage_Patches;
private: System::Windows::Forms::Panel^ panel_Patches;
private: System::Windows::Forms::TabPage^ tabPage_Plugins;
private: System::Windows::Forms::Panel^ panel_Plugins;
private: System::Windows::Forms::Button^ button_Discord;
private: System::Windows::Forms::Button^ button_github;
private: System::Windows::Forms::TabPage^ tabPage_Playerdata;
@@ -231,6 +249,8 @@ namespace Launcher {
this->panel_Playerdata = (gcnew System::Windows::Forms::Panel());
this->tabPage_Components = (gcnew System::Windows::Forms::TabPage());
this->panel_Components = (gcnew System::Windows::Forms::Panel());
this->tabPage_Plugins = (gcnew System::Windows::Forms::TabPage());
this->panel_Plugins = (gcnew System::Windows::Forms::Panel());
this->button_Discord = (gcnew System::Windows::Forms::Button());
this->button_github = (gcnew System::Windows::Forms::Button());
this->toolTip1 = (gcnew System::Windows::Forms::ToolTip(this->components));
@@ -242,6 +262,7 @@ namespace Launcher {
this->tabPage_Patches->SuspendLayout();
this->tabPage_Playerdata->SuspendLayout();
this->tabPage_Components->SuspendLayout();
this->tabPage_Plugins->SuspendLayout();
this->SuspendLayout();
//
// button_Launch
@@ -299,6 +320,7 @@ namespace Launcher {
this->tabControl->Controls->Add(this->tabPage_Patches);
this->tabControl->Controls->Add(this->tabPage_Playerdata);
this->tabControl->Controls->Add(this->tabPage_Components);
this->tabControl->Controls->Add(this->tabPage_Plugins);
this->tabControl->Location = System::Drawing::Point(0, 0);
this->tabControl->Margin = System::Windows::Forms::Padding(4);
this->tabControl->Name = L"tabControl";
@@ -420,6 +442,28 @@ namespace Launcher {
this->panel_Components->Size = System::Drawing::Size(429, 425);
this->panel_Components->TabIndex = 0;
//
// tabPage_Plugins
//
this->tabPage_Plugins->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)),
static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64)));
this->tabPage_Plugins->Controls->Add(this->panel_Plugins);
this->tabPage_Plugins->Location = System::Drawing::Point(4, 32);
this->tabPage_Plugins->Margin = System::Windows::Forms::Padding(4);
this->tabPage_Plugins->Name = L"tabPage_Plugins";
this->tabPage_Plugins->Padding = System::Windows::Forms::Padding(4);
this->tabPage_Plugins->Size = System::Drawing::Size(433, 429);
this->tabPage_Plugins->TabIndex = 3;
this->tabPage_Plugins->Text = L"Plugins";
//
// panel_Plugins
//
this->panel_Plugins->AutoScroll = true;
this->panel_Plugins->Location = System::Drawing::Point(0, 0);
this->panel_Plugins->Margin = System::Windows::Forms::Padding(4);
this->panel_Plugins->Name = L"panel_Plugins";
this->panel_Plugins->Size = System::Drawing::Size(429, 425);
this->panel_Plugins->TabIndex = 0;
//
// button_Discord
//
this->button_Discord->BackColor = System::Drawing::Color::Transparent;
@@ -504,6 +548,7 @@ namespace Launcher {
this->tabPage_Patches->ResumeLayout(false);
this->tabPage_Playerdata->ResumeLayout(false);
this->tabPage_Components->ResumeLayout(false);
this->tabPage_Plugins->ResumeLayout(false);
this->ResumeLayout(false);
}
@@ -533,6 +578,11 @@ private: System::Void SaveSettings() {
{
component->SaveOption();
}
for (ConfigOptionBase* option : AllPluginOpts)
{
option->SaveOption();
}
}
private: System::Void Ui_Load(System::Object^ sender, System::EventArgs^ e){
}
@@ -16,5 +16,6 @@ namespace TLAC::Components
bool ShowExcellentClearBorder;
bool UseCard;
bool GameModifierOptions;
bool ActionSE;
};
}
@@ -237,6 +237,7 @@ namespace TLAC::Components
customPlayerData->ShowGreatClearBorder = config.GetBooleanValue("border_great");
customPlayerData->UseCard = config.GetBooleanValue("use_card");
customPlayerData->GameModifierOptions = config.GetBooleanValue("gamemode_options");
customPlayerData->ActionSE = config.GetBooleanValue("act_toggle");
moduleCardWorkaround = config.GetBooleanValue("module_card_workaround");
if (moduleCardWorkaround) {
@@ -313,15 +314,14 @@ namespace TLAC::Components
setIfNotEqual(&playerData->btn_se_equip, customPlayerData->BtnSeEquip, -1);
setIfNotEqual(&playerData->slide_se_equip, customPlayerData->SlideSeEquip, -1);
setIfNotEqual(&playerData->chainslide_se_equip, customPlayerData->ChainslideSeEquip, -1);
setIfNotEqual(&playerData->act_toggle, customPlayerData->ActionSE, 1);
// Display clear borders on the progress bar
*(byte*)(PLAYER_DATA_ADDRESS + 0xD94) = (customPlayerData->ShowExcellentClearBorder << 1) | (customPlayerData->ShowGreatClearBorder);
if (customPlayerData->UseCard)
playerData->use_card = 1; // required to allow for module selection
playerData->use_card = customPlayerData->UseCard; // required to allow for module selection
if (customPlayerData->GameModifierOptions)
playerData->game_opts = 1; // hi-speed, etc..
playerData->game_opts = customPlayerData->GameModifierOptions; // hi-speed, etc..
memset((void*)MODULE_TABLE_START, 0xFF, 128);
memset((void*)ITEM_TABLE_START, 0xFF, 128);