From 9bdcaa0195ed8fe862026ec0d62296c44b30f376 Mon Sep 17 00:00:00 2001 From: somewhatlurker <52014015+somewhatlurker@users.noreply.github.com> Date: Thu, 22 Aug 2019 04:17:59 +1000 Subject: [PATCH] launcher: work on plugin enumeration --- .../source/plugins/Launcher/ConfigOption.h | 45 +----- .../source/plugins/Launcher/Launcher.vcxproj | 2 + .../source/plugins/Launcher/PluginConfig.h | 107 +------------ .../source/plugins/Launcher/PluginConfigApi.h | 145 ++++++++++++++++++ .../source/plugins/Launcher/framework.h | 73 ++++++++- source-code/source/plugins/Launcher/ui.h | 53 ++++++- 6 files changed, 275 insertions(+), 150 deletions(-) create mode 100644 source-code/source/plugins/Launcher/PluginConfigApi.h diff --git a/source-code/source/plugins/Launcher/ConfigOption.h b/source-code/source/plugins/Launcher/ConfigOption.h index 386a1e5..d35690a 100644 --- a/source-code/source/plugins/Launcher/ConfigOption.h +++ b/source-code/source/plugins/Launcher/ConfigOption.h @@ -9,6 +9,8 @@ #include +#include "PluginConfigApi.h" + using namespace System; using namespace System::Windows::Forms; @@ -39,47 +41,6 @@ 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; - } -}; - ref class ComboboxValidation { @@ -881,7 +842,7 @@ public: }; -Panel^ MakePanel(int width, int height, std::vector cfg, ToolTip^ tooltip) +Panel^ MakePanel(int width, int height, std::vector &cfg, ToolTip^ tooltip) { Panel^ outpanel = gcnew Panel(); outpanel->Width = width; diff --git a/source-code/source/plugins/Launcher/Launcher.vcxproj b/source-code/source/plugins/Launcher/Launcher.vcxproj index d4e6170..f8c2f87 100644 --- a/source-code/source/plugins/Launcher/Launcher.vcxproj +++ b/source-code/source/plugins/Launcher/Launcher.vcxproj @@ -167,6 +167,8 @@ + + diff --git a/source-code/source/plugins/Launcher/PluginConfig.h b/source-code/source/plugins/Launcher/PluginConfig.h index 76badf0..ff0853f 100644 --- a/source-code/source/plugins/Launcher/PluginConfig.h +++ b/source-code/source/plugins/Launcher/PluginConfig.h @@ -1,106 +1,9 @@ #pragma once #include "ConfigOption.h" -#include "framework.h" +#include "PluginConfigApi.h" namespace PluginConfig { - 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 - }; - - 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 valueStrings; - }; - - struct PluginConfigDropdownTextData { - LPCWSTR iniVarName; - LPCWSTR iniSectionName; - LPCWSTR iniFilePath; - LPCWSTR friendlyName; - LPCWSTR description; - LPCWSTR defaultVal; - std::vector valueStrings; - bool useUtf8; - }; - - struct PluginConfigDropdownNumberData { - LPCWSTR iniVarName; - LPCWSTR iniSectionName; - LPCWSTR iniFilePath; - LPCWSTR friendlyName; - LPCWSTR description; - int defaultVal; - std::vector valueInts; - }; - - struct PluginConfigResolutionData { - LPCWSTR iniVarName; - LPCWSTR iniVarName2; - LPCWSTR iniSectionName; - LPCWSTR iniFilePath; - LPCWSTR friendlyName; - LPCWSTR description; - resolution defaultVal; - std::vector valueResolutions; - }; - - struct PluginConfigGroupData - { - LPCWSTR name; - int height; - }; - - struct PluginConfigOption - { - ConfigType cfgType; - void* data; - }; - ConfigOptionBase* GetConfigOption(PluginConfigOption cfg) { PluginConfigBooleanData* boolData = (PluginConfigBooleanData*)(cfg.data); @@ -137,7 +40,7 @@ namespace PluginConfig } } - std::vector GetConfigOptionVec(std::vector in) + std::vector GetConfigOptionVec(std::vector &in) { std::vector outvec; for (PluginConfigOption &opt : in) @@ -147,12 +50,12 @@ namespace PluginConfig return outvec; } - std::vector testcfg = + /*std::vector 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({ 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 testcfgconfigopts = GetConfigOptionVec(testcfg); + //std::vector testcfgconfigopts = GetConfigOptionVec(testcfg); }; \ No newline at end of file diff --git a/source-code/source/plugins/Launcher/PluginConfigApi.h b/source-code/source/plugins/Launcher/PluginConfigApi.h new file mode 100644 index 0000000..aeb69ec --- /dev/null +++ b/source-code/source/plugins/Launcher/PluginConfigApi.h @@ -0,0 +1,145 @@ +#pragma once +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include +#include + +// 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 +{ + 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 + }; + + 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 valueStrings; + }; + + struct PluginConfigDropdownTextData { + LPCWSTR iniVarName; + LPCWSTR iniSectionName; + LPCWSTR iniFilePath; + LPCWSTR friendlyName; + LPCWSTR description; + LPCWSTR defaultVal; + std::vector valueStrings; + bool useUtf8; + }; + + struct PluginConfigDropdownNumberData { + LPCWSTR iniVarName; + LPCWSTR iniSectionName; + LPCWSTR iniFilePath; + LPCWSTR friendlyName; + LPCWSTR description; + int defaultVal; + std::vector valueInts; + }; + + struct PluginConfigResolutionData { + LPCWSTR iniVarName; + LPCWSTR iniVarName2; + LPCWSTR iniSectionName; + LPCWSTR iniFilePath; + LPCWSTR friendlyName; + LPCWSTR description; + resolution defaultVal; + std::vector valueResolutions; + }; + + struct PluginConfigGroupData + { + LPCWSTR name; + int height; + }; + + struct PluginConfigOption + { + ConfigType cfgType; + void* data; + }; +} \ No newline at end of file diff --git a/source-code/source/plugins/Launcher/framework.h b/source-code/source/plugins/Launcher/framework.h index 4d575e3..84bb05d 100644 --- a/source-code/source/plugins/Launcher/framework.h +++ b/source-code/source/plugins/Launcher/framework.h @@ -9,6 +9,7 @@ #include #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(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"; @@ -265,6 +268,70 @@ void PrependFile(LPCSTR newStr, LPCWSTR fileName) } +struct PluginInfo { + HMODULE handle; + std::wstring filename; + std::wstring name; + std::wstring description; + std::vector configopts; +}; +std::vector LoadPlugins() +{ + std::vector 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(ffd.cFileName); + 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 = (std::vector(*)())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 = optsFunc(); + + FreeLibrary(thisplugin.handle); + + outvec.push_back(thisplugin); + } + } + } while (FindNextFileW(hFind, &ffd)); + FindClose(hFind); + } + + return outvec; +} +std::vector AllPlugins = LoadPlugins(); + + // 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 diff --git a/source-code/source/plugins/Launcher/ui.h b/source-code/source/plugins/Launcher/ui.h index 2251521..f764e41 100644 --- a/source-code/source/plugins/Launcher/ui.h +++ b/source-code/source/plugins/Launcher/ui.h @@ -114,16 +114,34 @@ namespace Launcher { for (ConfigOptionBase* component : componentsArray) { component->hasChanged = ConfigHasChanged; - //componentsY += component->AddToPanel(panel_Components, 12, componentsY, toolTip1); + componentsY += component->AddToPanel(panel_Components, 12, componentsY, toolTip1); } this->panel_Components->ResumeLayout(false); this->panel_Components->PerformLayout(); + this->panel_Plugins->SuspendLayout(); + + int pluginsY = 3; + for (PluginInfo &plugin : AllPlugins) + { + Label^ lbl = gcnew Label; + lbl->AutoSize = true; + lbl->Text = gcnew String(plugin.name.c_str()); + lbl->Left = 12; + lbl->Top = pluginsY; + panel_Plugins->Controls->Add(lbl); + toolTip1->SetToolTip(lbl, gcnew String(plugin.description.c_str())); + pluginsY += lbl->Font->Height + 6; + } + this->panel_Plugins->ResumeLayout(false); + this->panel_Plugins->PerformLayout(); + + using namespace PluginConfig; //tabPage_Components->Controls->Add(MakePanel(256, 256, testcfgconfigopts, toolTip1)); - tabPage_Components->Controls->Add(MakePanel(256, 100, std::vector(&componentsArray[0], &componentsArray[12]), toolTip1)); + //tabPage_Components->Controls->Add(MakePanel(256, 100, std::vector(&componentsArray[0], &componentsArray[13]), toolTip1)); // trick Optimus into switching to the NVIDIA GPU @@ -183,6 +201,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; @@ -238,6 +258,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)); @@ -249,6 +271,7 @@ namespace Launcher { this->tabPage_Patches->SuspendLayout(); this->tabPage_Playerdata->SuspendLayout(); this->tabPage_Components->SuspendLayout(); + this->tabPage_Plugins->SuspendLayout(); this->SuspendLayout(); // // button_Launch @@ -306,6 +329,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"; @@ -409,7 +433,7 @@ namespace Launcher { // this->tabPage_Components->BackColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), static_cast(static_cast(64)), static_cast(static_cast(64))); - //this->tabPage_Components->Controls->Add(this->panel_Components); + this->tabPage_Components->Controls->Add(this->panel_Components); this->tabPage_Components->Location = System::Drawing::Point(4, 32); this->tabPage_Components->Margin = System::Windows::Forms::Padding(4); this->tabPage_Components->Name = L"tabPage_Components"; @@ -427,6 +451,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(static_cast(64)), + static_cast(static_cast(64)), static_cast(static_cast(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; @@ -511,6 +557,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); }