1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Added export/import/reset buttons to config overlay

This commit is contained in:
narzoul 2022-05-23 23:57:31 +02:00
parent 9a37aa6e24
commit c3f0f9491a
13 changed files with 243 additions and 16 deletions

View File

@ -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())

View File

@ -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);

View File

@ -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();

View File

@ -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;
};
}

View File

@ -13,6 +13,11 @@ namespace Overlay
void ButtonControl::onLButtonDown(POINT pos)
{
if (m_style & WS_DISABLED)
{
return;
}
Input::setCapture(this);
onMouseMove(pos);
}

View File

@ -51,7 +51,7 @@ namespace Overlay
void ComboBoxDropDown::onNotify(Control& control)
{
m_parent.setValue(static_cast<LabelControl&>(control).getLabel());
m_parent.getParent()->onNotify(*m_parent.getParent());
m_parent.getParent()->onNotify(m_parent);
}
void ComboBoxDropDown::select(const std::string& value)

View File

@ -1,4 +1,8 @@
#include <fstream>
#include <sstream>
#include <Common/Hook.h>
#include <Common/Log.h>
#include <Config/Config.h>
#include <Gdi/GuiThread.h>
#include <Input/Input.h>
@ -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<ButtonControl> 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<ButtonControl>(*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<ConfigWindow*>(control.getParent())->setVisible(false);
}
void ConfigWindow::onExport(Control& control)
{
static_cast<ConfigWindow*>(control.getParent())->exportSettings();
}
void ConfigWindow::onImport(Control& control)
{
static_cast<ConfigWindow*>(control.getParent())->importSettings();
}
void ConfigWindow::onResetAll(Control& control)
{
static_cast<ConfigWindow*>(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);
}
}

View File

@ -1,6 +1,8 @@
#pragma once
#include <list>
#include <memory>
#include <string>
#include <Overlay/ButtonControl.h>
#include <Overlay/LabelControl.h>
@ -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<ButtonControl> 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<SettingControl> m_controls;
unsigned m_buttonCount;
std::unique_ptr<LabelControl> m_caption;
std::unique_ptr<ButtonControl> m_captionCloseButton;
std::unique_ptr<ButtonControl> m_closeButton;
std::unique_ptr<ButtonControl> m_exportButton;
std::unique_ptr<ButtonControl> m_importButton;
std::unique_ptr<ButtonControl> m_resetAllButton;
std::list<SettingControl> m_settingControls;
SettingControl* m_focus;
std::string m_fileContent;
};
}

View File

@ -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))

View File

@ -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);

View File

@ -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*/)

View File

@ -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);
}
}
}

View File

@ -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();