From c3f0f9491a2c422b15fb5dacdbe4b7cef77ee0ab Mon Sep 17 00:00:00 2001 From: narzoul Date: Mon, 23 May 2022 23:57:31 +0200 Subject: [PATCH] Added export/import/reset buttons to config overlay --- DDrawCompat/Config/Parser.cpp | 19 +++ DDrawCompat/Config/Parser.h | 1 + DDrawCompat/Config/Setting.cpp | 10 ++ DDrawCompat/Config/Setting.h | 6 + DDrawCompat/Overlay/ButtonControl.cpp | 5 + DDrawCompat/Overlay/ComboBoxDropDown.cpp | 2 +- DDrawCompat/Overlay/ConfigWindow.cpp | 145 +++++++++++++++++++++-- DDrawCompat/Overlay/ConfigWindow.h | 23 +++- DDrawCompat/Overlay/Control.cpp | 28 ++++- DDrawCompat/Overlay/Control.h | 3 + DDrawCompat/Overlay/LabelControl.cpp | 4 +- DDrawCompat/Overlay/SettingControl.cpp | 10 ++ DDrawCompat/Overlay/SettingControl.h | 3 + 13 files changed, 243 insertions(+), 16 deletions(-) diff --git a/DDrawCompat/Config/Parser.cpp b/DDrawCompat/Config/Parser.cpp index 7c6ba37..18aebad 100644 --- a/DDrawCompat/Config/Parser.cpp +++ b/DDrawCompat/Config/Parser.cpp @@ -9,6 +9,8 @@ namespace { + std::filesystem::path g_overlayConfigPath; + void setConfig(const std::string& name, const std::string& value, const std::string& source); auto& getSettings() @@ -88,6 +90,11 @@ namespace Config { namespace Parser { + std::filesystem::path getOverlayConfigPath() + { + return g_overlayConfigPath; + } + void loadAllConfigFiles(const std::filesystem::path& processPath) { for (auto& setting : getSettings()) { @@ -103,9 +110,21 @@ namespace Config { processConfigPath.replace_extension(); } + g_overlayConfigPath = processConfigPath; processConfigPath.replace_filename(L"DDrawCompat-" + processConfigPath.filename().native() + L".ini"); loadConfigFile("process", processConfigPath); + for (auto& setting : getSettings()) { + setting.second.setBaseValue(); + } + + g_overlayConfigPath.replace_filename(L"DDrawCompatOverlay-" + g_overlayConfigPath.filename().native() + L".ini"); + loadConfigFile("overlay", g_overlayConfigPath); + + for (auto& setting : getSettings()) { + setting.second.setExportedValue(); + } + std::size_t maxNameLength = 0; std::size_t maxSourceLength = 0; for (const auto& setting : getSettings()) diff --git a/DDrawCompat/Config/Parser.h b/DDrawCompat/Config/Parser.h index f427816..f43d518 100644 --- a/DDrawCompat/Config/Parser.h +++ b/DDrawCompat/Config/Parser.h @@ -18,6 +18,7 @@ namespace Config namespace Parser { + std::filesystem::path getOverlayConfigPath(); void loadAllConfigFiles(const std::filesystem::path& processPath); SIZE parseResolution(const std::string& value); int parseInt(const std::string& value, int min, int max); diff --git a/DDrawCompat/Config/Setting.cpp b/DDrawCompat/Config/Setting.cpp index e47e02e..d41d2be 100644 --- a/DDrawCompat/Config/Setting.cpp +++ b/DDrawCompat/Config/Setting.cpp @@ -60,6 +60,16 @@ namespace Config m_source = source; } + void Setting::setBaseValue() + { + m_baseValue = getValueStr(); + } + + void Setting::setExportedValue() + { + m_exportedValue = getValueStr(); + } + void Setting::setParam(const std::string& param) { const auto paramInfo = getParamInfo(); diff --git a/DDrawCompat/Config/Setting.h b/DDrawCompat/Config/Setting.h index 56a9c63..e472d7a 100644 --- a/DDrawCompat/Config/Setting.h +++ b/DDrawCompat/Config/Setting.h @@ -28,6 +28,8 @@ namespace Config virtual ParamInfo getParamInfo() const { return {}; } virtual std::string getValueStr() const = 0; + const std::string& getBaseValue() const { return m_baseValue; } + const std::string& getExportedValue() const { return m_exportedValue; } const std::string& getName() const { return m_name; } int getParam() const { return m_param; } const std::string& getSource() const { return m_source; } @@ -35,6 +37,8 @@ namespace Config void reset(); void set(const std::string& value); void set(const std::string& value, const std::string& source); + void setBaseValue(); + void setExportedValue(); protected: virtual void setValue(const std::string& value) = 0; @@ -47,5 +51,7 @@ namespace Config std::string m_name; std::string m_default; std::string m_source; + std::string m_baseValue; + std::string m_exportedValue; }; } diff --git a/DDrawCompat/Overlay/ButtonControl.cpp b/DDrawCompat/Overlay/ButtonControl.cpp index f2ab0b8..80b62be 100644 --- a/DDrawCompat/Overlay/ButtonControl.cpp +++ b/DDrawCompat/Overlay/ButtonControl.cpp @@ -13,6 +13,11 @@ namespace Overlay void ButtonControl::onLButtonDown(POINT pos) { + if (m_style & WS_DISABLED) + { + return; + } + Input::setCapture(this); onMouseMove(pos); } diff --git a/DDrawCompat/Overlay/ComboBoxDropDown.cpp b/DDrawCompat/Overlay/ComboBoxDropDown.cpp index 23b142a..48cb678 100644 --- a/DDrawCompat/Overlay/ComboBoxDropDown.cpp +++ b/DDrawCompat/Overlay/ComboBoxDropDown.cpp @@ -51,7 +51,7 @@ namespace Overlay void ComboBoxDropDown::onNotify(Control& control) { m_parent.setValue(static_cast(control).getLabel()); - m_parent.getParent()->onNotify(*m_parent.getParent()); + m_parent.getParent()->onNotify(m_parent); } void ComboBoxDropDown::select(const std::string& value) diff --git a/DDrawCompat/Overlay/ConfigWindow.cpp b/DDrawCompat/Overlay/ConfigWindow.cpp index f296ca0..b541880 100644 --- a/DDrawCompat/Overlay/ConfigWindow.cpp +++ b/DDrawCompat/Overlay/ConfigWindow.cpp @@ -1,4 +1,8 @@ +#include +#include + #include +#include #include #include #include @@ -13,14 +17,16 @@ namespace namespace Overlay { ConfigWindow::ConfigWindow() - : Window(nullptr, { 0, 0, SettingControl::TOTAL_WIDTH, 330 }, Config::configHotKey.get()) - , m_caption(*this, { 0, 0, SettingControl::TOTAL_WIDTH - CAPTION_HEIGHT + 1, CAPTION_HEIGHT }, - "DDrawCompat Config Overlay", 0, WS_BORDER | WS_VISIBLE) - , m_closeButton(*this, - { SettingControl::TOTAL_WIDTH - CAPTION_HEIGHT, 0, SettingControl::TOTAL_WIDTH, CAPTION_HEIGHT }, - "X", onClose) + : Window(nullptr, { 0, 0, SettingControl::TOTAL_WIDTH, 350 }, Config::configHotKey.get()) + , m_buttonCount(0) , m_focus(nullptr) { + RECT r = { 0, 0, m_rect.right - CAPTION_HEIGHT + 1, CAPTION_HEIGHT }; + m_caption.reset(new LabelControl(*this, r, "DDrawCompat Config Overlay", 0, WS_BORDER | WS_VISIBLE)); + + r = { m_rect.right - CAPTION_HEIGHT, 0, m_rect.right, CAPTION_HEIGHT }; + m_captionCloseButton.reset(new ButtonControl(*this, r, "X", onClose)); + addControl(Config::alternatePixelCenter); addControl(Config::bltFilter); addControl(Config::antialiasing); @@ -32,16 +38,36 @@ namespace Overlay addControl(Config::spriteTexCoord); addControl(Config::textureFilter); addControl(Config::vSync); + + m_closeButton = addButton("Close", onClose); + m_exportButton = addButton("Export", onExport); + m_importButton = addButton("Import", onImport); + m_resetAllButton = addButton("Reset all", onResetAll); + + std::ifstream f(Config::Parser::getOverlayConfigPath()); + std::ostringstream oss; + oss << f.rdbuf(); + m_fileContent = oss.str(); + + updateButtons(); + } + + std::unique_ptr ConfigWindow::addButton(const std::string& label, ButtonControl::ClickHandler clickHandler) + { + ++m_buttonCount; + RECT r = { 0, 0, 80, 22 }; + OffsetRect(&r, m_rect.right - m_buttonCount * (r.right + BORDER), m_rect.bottom - (r.bottom + BORDER)); + return std::make_unique(*this, r, label, clickHandler); } void ConfigWindow::addControl(Config::Setting& setting) { - const int index = m_controls.size(); + const int index = m_settingControls.size(); const int rowHeight = 25; RECT rect = { 0, index * rowHeight + BORDER / 2, m_rect.right, (index + 1) * rowHeight + BORDER / 2 }; - OffsetRect(&rect, 0, m_caption.getRect().bottom); - m_controls.emplace_back(*this, rect, setting); + OffsetRect(&rect, 0, CAPTION_HEIGHT); + m_settingControls.emplace_back(*this, rect, setting); } RECT ConfigWindow::calculateRect(const RECT& monitorRect) const @@ -52,11 +78,81 @@ namespace Overlay return r; } + std::string ConfigWindow::constructFileContent() + { + std::ostringstream oss; + for (auto& settingControl : m_settingControls) + { + const auto& setting = settingControl.getSetting(); + const auto value = setting.getValueStr(); + if (value == setting.getBaseValue()) + { + oss << "# "; + } + oss << setting.getName() << " = " << value << std::endl; + } + return oss.str(); + } + + void ConfigWindow::exportSettings() + { + auto path(Config::Parser::getOverlayConfigPath()); + std::ofstream f(path); + if (f.fail()) + { + LOG_ONCE("ERROR: Failed to open overlay config file for writing: " << path.u8string()); + return; + } + + m_fileContent = constructFileContent(); + f.write(m_fileContent.c_str(), m_fileContent.length()); + + for (auto& settingControl : m_settingControls) + { + settingControl.getSetting().setExportedValue(); + } + + updateButtons(); + } + + void ConfigWindow::importSettings() + { + for (auto& settingControl : m_settingControls) + { + settingControl.set(settingControl.getSetting().getExportedValue()); + } + updateButtons(); + } + void ConfigWindow::onClose(Control& control) { static_cast(control.getParent())->setVisible(false); } + void ConfigWindow::onExport(Control& control) + { + static_cast(control.getParent())->exportSettings(); + } + + void ConfigWindow::onImport(Control& control) + { + static_cast(control.getParent())->importSettings(); + } + + void ConfigWindow::onResetAll(Control& control) + { + static_cast(control.getParent())->resetSettings(); + } + + void ConfigWindow::resetSettings() + { + for (auto& settingControl : m_settingControls) + { + settingControl.set(settingControl.getSetting().getBaseValue()); + } + updateButtons(); + } + void ConfigWindow::setFocus(SettingControl* control) { if (m_focus == control) @@ -90,4 +186,35 @@ namespace Overlay setFocus(nullptr); } } + + void ConfigWindow::updateButtons() + { + if (!m_exportButton) + { + return; + } + + bool enableImport = false; + bool enableReset = false; + + for (auto& settingControl : m_settingControls) + { + const auto& setting = settingControl.getSetting(); + const auto value = setting.getValueStr(); + + if (value != setting.getBaseValue()) + { + enableReset = true; + } + + if (value != setting.getExportedValue()) + { + enableImport = true; + } + } + + m_exportButton->setEnabled(m_fileContent != constructFileContent()); + m_importButton->setEnabled(enableImport); + m_resetAllButton->setEnabled(enableReset); + } } diff --git a/DDrawCompat/Overlay/ConfigWindow.h b/DDrawCompat/Overlay/ConfigWindow.h index 753fcfc..aa6aa18 100644 --- a/DDrawCompat/Overlay/ConfigWindow.h +++ b/DDrawCompat/Overlay/ConfigWindow.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include #include @@ -17,17 +19,32 @@ namespace Overlay virtual void setVisible(bool isVisible) override; void setFocus(SettingControl* control); + void updateButtons(); private: static void onClose(Control& control); + static void onExport(Control& control); + static void onImport(Control& control); + static void onResetAll(Control& control); virtual RECT calculateRect(const RECT& monitorRect) const override; + std::unique_ptr addButton(const std::string& label, ButtonControl::ClickHandler clickHandler); void addControl(Config::Setting& setting); + std::string constructFileContent(); + void exportSettings(); + void importSettings(); + void resetSettings(); - LabelControl m_caption; - ButtonControl m_closeButton; - std::list m_controls; + unsigned m_buttonCount; + std::unique_ptr m_caption; + std::unique_ptr m_captionCloseButton; + std::unique_ptr m_closeButton; + std::unique_ptr m_exportButton; + std::unique_ptr m_importButton; + std::unique_ptr m_resetAllButton; + std::list m_settingControls; SettingControl* m_focus; + std::string m_fileContent; }; } diff --git a/DDrawCompat/Overlay/Control.cpp b/DDrawCompat/Overlay/Control.cpp index 0d13191..abfaa1e 100644 --- a/DDrawCompat/Overlay/Control.cpp +++ b/DDrawCompat/Overlay/Control.cpp @@ -39,10 +39,12 @@ namespace Overlay { OffsetRect(&r, -r.left, -r.top); } + SetDCPenColor(dc, isEnabled() ? FOREGROUND_COLOR : DISABLED_COLOR); CALL_ORIG_FUNC(Rectangle)(dc, r.left, r.top, r.right, r.bottom); + SetDCPenColor(dc, FOREGROUND_COLOR); } - if (m_highlightedChild) + if (m_highlightedChild && m_highlightedChild->isEnabled()) { RECT r = m_highlightedChild->getHighlightRect(); SetDCPenColor(dc, HIGHLIGHT_COLOR); @@ -112,6 +114,20 @@ namespace Overlay } } + bool Control::isEnabled() const + { + return !(m_style & WS_DISABLED) && (!m_parent || m_parent->isEnabled()); + } + + void Control::setEnabled(bool isEnabled) + { + if (!(m_style & WS_DISABLED) != isEnabled) + { + m_style = isEnabled ? (m_style & ~WS_DISABLED) : (m_style | WS_DISABLED); + invalidate(); + } + } + void Control::onLButtonDown(POINT pos) { propagateMouseEvent(&Control::onLButtonDown, pos); @@ -124,6 +140,11 @@ namespace Overlay void Control::onMouseMove(POINT pos) { + if (m_style & WS_DISABLED) + { + return; + } + auto prevHighlightedChild = m_highlightedChild; m_highlightedChild = nullptr; propagateMouseEvent(&Control::onMouseMove, pos); @@ -140,6 +161,11 @@ namespace Overlay void Control::propagateMouseEvent(void(Control::* onEvent)(POINT), POINT pos) { + if (m_style & WS_DISABLED) + { + return; + } + for (auto child : m_children) { if (PtInRect(&child->m_rect, pos)) diff --git a/DDrawCompat/Overlay/Control.h b/DDrawCompat/Overlay/Control.h index 31bb720..2785a75 100644 --- a/DDrawCompat/Overlay/Control.h +++ b/DDrawCompat/Overlay/Control.h @@ -34,9 +34,12 @@ namespace Overlay RECT getRect() const { return m_rect; } const Control& getRoot() const; Control& getRoot(); + bool isEnabled() const; bool isVisible() const { return m_style & WS_VISIBLE; } + void setEnabled(bool isEnabled); protected: + static const COLORREF DISABLED_COLOR = RGB(128, 128, 128); static const COLORREF FOREGROUND_COLOR = RGB(0, 255, 0); static const COLORREF HIGHLIGHT_COLOR = RGB(255, 255, 0); diff --git a/DDrawCompat/Overlay/LabelControl.cpp b/DDrawCompat/Overlay/LabelControl.cpp index 75c43b3..ae10a1a 100644 --- a/DDrawCompat/Overlay/LabelControl.cpp +++ b/DDrawCompat/Overlay/LabelControl.cpp @@ -14,10 +14,10 @@ namespace Overlay void LabelControl::draw(HDC dc) { RECT r = { m_rect.left + BORDER, m_rect.top, m_rect.right - BORDER, m_rect.bottom }; - SetTextColor(dc, m_color); + auto prevColor = SetTextColor(dc, (FOREGROUND_COLOR == m_color && !isEnabled()) ? DISABLED_COLOR : m_color ); CALL_ORIG_FUNC(DrawTextA)(dc, m_label.c_str(), m_label.size(), &r, m_format | DT_NOCLIP | DT_SINGLELINE | DT_VCENTER); - SetTextColor(dc, FOREGROUND_COLOR); + SetTextColor(dc, prevColor); } void LabelControl::onLButtonDown(POINT /*pos*/) diff --git a/DDrawCompat/Overlay/SettingControl.cpp b/DDrawCompat/Overlay/SettingControl.cpp index 521cbc3..b35946f 100644 --- a/DDrawCompat/Overlay/SettingControl.cpp +++ b/DDrawCompat/Overlay/SettingControl.cpp @@ -59,6 +59,7 @@ namespace Overlay } else { + configWindow->updateButtons(); configWindow->setFocus(nullptr); configWindow->onMouseMove(pos); } @@ -121,4 +122,13 @@ namespace Overlay m_paramControl->setPos(m_setting.getParam()); } } + + void SettingControl::set(const std::string& value) + { + if (m_setting.getValueStr() != value) + { + getValueComboBox().setValue(value); + onNotify(*m_valueControl); + } + } } diff --git a/DDrawCompat/Overlay/SettingControl.h b/DDrawCompat/Overlay/SettingControl.h index 1ffa553..d37459e 100644 --- a/DDrawCompat/Overlay/SettingControl.h +++ b/DDrawCompat/Overlay/SettingControl.h @@ -31,6 +31,9 @@ namespace Overlay virtual void onLButtonDown(POINT pos) override; virtual void onNotify(Control& control) override; + Config::Setting& getSetting() const { return m_setting; } + void set(const std::string& value); + private: ComboBoxControl& getValueComboBox() const; void onParamChanged();