From fba82eb1a7fca59420f69577224116d093ae4567 Mon Sep 17 00:00:00 2001 From: uramer Date: Tue, 25 Jan 2022 21:53:00 +0100 Subject: [PATCH] Script settings tab --- apps/openmw/mwgui/settingswindow.cpp | 85 +++++++++++++++++++++-- apps/openmw/mwgui/settingswindow.hpp | 10 +++ apps/openmw/mwlua/uibindings.cpp | 17 ++++- components/CMakeLists.txt | 2 +- components/lua_ui/scriptsettings.cpp | 37 ++++++++++ components/lua_ui/scriptsettings.hpp | 25 +++++++ components/lua_ui/util.cpp | 2 + files/mygui/openmw_settings_window.layout | 13 ++++ 8 files changed, 183 insertions(+), 8 deletions(-) create mode 100644 components/lua_ui/scriptsettings.cpp create mode 100644 components/lua_ui/scriptsettings.hpp diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 69d09f7260..8c3740d15d 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -1,18 +1,20 @@ #include "settingswindow.hpp" +#include +#include +#include +#include + #include #include #include #include #include #include +#include #include -#include -#include -#include - #include #include #include @@ -21,6 +23,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -33,7 +36,6 @@ namespace { - std::string textureMipmappingToStr(const std::string& val) { if (val == "linear") return "Trilinear"; @@ -236,6 +238,10 @@ namespace MWGui getWidget(mLightingMethodButton, "LightingMethodButton"); getWidget(mLightsResetButton, "LightsResetButton"); getWidget(mMaxLights, "MaxLights"); + getWidget(mScriptFilter, "ScriptFilter"); + getWidget(mScriptList, "ScriptList"); + getWidget(mScriptView, "ScriptView"); + getWidget(mScriptDisabled, "ScriptDisabled"); #ifndef WIN32 // hide gamma controls since it currently does not work under Linux @@ -321,9 +327,12 @@ namespace MWGui mKeyboardSwitch->setStateSelected(true); mControllerSwitch->setStateSelected(false); + + mScriptFilter->eventEditTextChange += MyGUI::newDelegate(this, &SettingsWindow::onScriptFilterChange); + mScriptList->eventListMouseItemActivate += MyGUI::newDelegate(this, &SettingsWindow::onScriptListSelection); } - void SettingsWindow::onTabChanged(MyGUI::TabControl* /*_sender*/, size_t /*index*/) + void SettingsWindow::onTabChanged(MyGUI::TabControl* /*_sender*/, size_t index) { resetScrollbars(); } @@ -699,6 +708,67 @@ namespace MWGui mControlsBox->setVisibleVScroll(true); } + void SettingsWindow::resizeScriptSettings() + { + static int minListWidth = 150; + static float relativeListWidth = 0.2f; + MyGUI::IntSize parentSize = mScriptFilter->getParent()->getClientCoord().size(); + int listWidth = std::max(minListWidth, static_cast(parentSize.width * relativeListWidth)); + int filterHeight = mScriptFilter->getSize().height; + int listBorder = (mScriptList->getSize().height - mScriptList->getClientCoord().height) / 2; + int listHeight = parentSize.height - listBorder - mScriptList->getPosition().top; + mScriptFilter->setSize({ listWidth, filterHeight }); + mScriptList->setSize({ listWidth, listHeight }); + mScriptView->setPosition({ listWidth, 0 }); + mScriptView->setSize({ parentSize.width - listWidth, parentSize.height }); + mScriptDisabled->setPosition({0, 0}); + mScriptDisabled->setSize(parentSize); + } + + void SettingsWindow::renderScriptSettings() + { + while (mScriptView->getChildCount() > 0) + mScriptView->getChildAt(0)->detachFromWidget(); + mScriptList->removeAllItems(); + + std::string filter(".*"); + filter += mScriptFilter->getCaption(); + filter += ".*"; + auto flags = std::regex_constants::icase; + std::regex filterRegex(filter, flags); + + auto scriptSettings = LuaUi::scriptSettings(); + for (size_t i = 0; i < scriptSettings.size(); ++i) + { + LuaUi::ScriptSettings script = scriptSettings[i]; + if (std::regex_match(script.mName, filterRegex) || std::regex_match(script.mSearchHints, filterRegex)) + mScriptList->addItem(script.mName, i); + } + + // Hide script settings tab when the game world isn't loaded and scripts couldn't add their settings + bool disabled = scriptSettings.empty(); + mScriptDisabled->setVisible(disabled); + mScriptFilter->setVisible(!disabled); + mScriptList->setVisible(!disabled); + mScriptView->setVisible(!disabled); + } + + void SettingsWindow::onScriptFilterChange(MyGUI::Widget*) + { + renderScriptSettings(); + } + + void SettingsWindow::onScriptListSelection(MyGUI::Widget*, size_t index) + { + while (mScriptView->getChildCount() > 0) + mScriptView->getChildAt(0)->detachFromWidget(); + if (index >= mScriptList->getItemCount()) + return; + size_t scriptIndex = *mScriptList->getItemDataAt(index); + LuaUi::ScriptSettings script = LuaUi::scriptSettings()[scriptIndex]; + LuaUi::attachToWidget(script, mScriptView); + } + void SettingsWindow::onRebindAction(MyGUI::Widget* _sender) { int actionId = *_sender->getUserData(); @@ -744,12 +814,15 @@ namespace MWGui updateControlsBox(); updateLightSettings(); resetScrollbars(); + renderScriptSettings(); + resizeScriptSettings(); MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mOkButton); } void SettingsWindow::onWindowResize(MyGUI::Window *_sender) { layoutControlsBox(); + resizeScriptSettings(); } void SettingsWindow::computeMinimumWindowSize() diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index d58e94e84a..f002a67306 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -44,6 +44,11 @@ namespace MWGui MyGUI::Button* mControllerSwitch; bool mKeyboardMode; //if true, setting up the keyboard. Otherwise, it's controller + MyGUI::EditBox* mScriptFilter; + MyGUI::ListBox* mScriptList; + MyGUI::Widget* mScriptView; + MyGUI::EditBox* mScriptDisabled; + void onTabChanged(MyGUI::TabControl* _sender, size_t index); void onOkButtonClicked(MyGUI::Widget* _sender); void onTextureFilteringChanged(MyGUI::ComboBox* _sender, size_t pos); @@ -71,12 +76,17 @@ namespace MWGui void onWindowResize(MyGUI::Window* _sender); + void onScriptFilterChange(MyGUI::Widget*); + void onScriptListSelection(MyGUI::Widget*, size_t index); + void apply(); void configureWidgets(MyGUI::Widget* widget, bool init); void updateSliderLabel(MyGUI::ScrollBar* scroller, const std::string& value); void layoutControlsBox(); + void resizeScriptSettings(); + void renderScriptSettings(); void computeMinimumWindowSize(); diff --git a/apps/openmw/mwlua/uibindings.cpp b/apps/openmw/mwlua/uibindings.cpp index 61e7c471c1..5fe54a4d35 100644 --- a/apps/openmw/mwlua/uibindings.cpp +++ b/apps/openmw/mwlua/uibindings.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "context.hpp" #include "actions.hpp" @@ -43,7 +44,7 @@ namespace MWLua break; } } - catch (std::exception& e) + catch (std::exception&) { // prevent any actions on a potentially corrupted widget mElement->mRoot = nullptr; @@ -238,6 +239,20 @@ namespace MWLua typeTable.set(it.second, it.first); api["TYPE"] = LuaUtil::makeReadOnly(typeTable); + api["registerSettings"] = [](sol::table options) + { + LuaUi::ScriptSettings script; + script.mName = options.get_or("name", std::string()); + if (script.mName.empty()) + throw std::logic_error("No name provided for script settings"); + script.mSearchHints = options.get_or("searchHints", std::string()); + auto element = options.get_or>("element", nullptr); + if (!element) + throw std::logic_error("No UI element provided for script settings"); + script.mElement = element.get(); + LuaUi::registerSettings(script); + }; + return LuaUtil::makeReadOnly(api); } } diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 2d986660bc..3526386e69 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -165,7 +165,7 @@ add_component_dir (queries ) add_component_dir (lua_ui - properties widget element util layers content + properties widget element util layers content scriptsettings text textedit window image ) diff --git a/components/lua_ui/scriptsettings.cpp b/components/lua_ui/scriptsettings.cpp new file mode 100644 index 0000000000..071ded1b5d --- /dev/null +++ b/components/lua_ui/scriptsettings.cpp @@ -0,0 +1,37 @@ +#include "scriptsettings.hpp" + +#include + +#include "element.hpp" + +namespace LuaUi +{ + namespace + { + std::vector allSettings; + } + + const std::vector& scriptSettings() + { + return allSettings; + } + + void registerSettings(const ScriptSettings& script) + { + allSettings.push_back(script); + } + + void clearSettings() + { + allSettings.clear(); + } + + void attachToWidget(const ScriptSettings& script, MyGUI::Widget* widget) + { + WidgetExtension* root = script.mElement->mRoot; + if (!root) + return; + root->widget()->attachToWidget(widget); + root->updateCoord(); + } +} diff --git a/components/lua_ui/scriptsettings.hpp b/components/lua_ui/scriptsettings.hpp new file mode 100644 index 0000000000..eadcec430f --- /dev/null +++ b/components/lua_ui/scriptsettings.hpp @@ -0,0 +1,25 @@ +#ifndef OPENMW_LUAUI_SCRIPTSETTINGS +#define OPENMW_LUAUI_SCRIPTSETTINGS + +#include +#include +#include + +#include + +namespace LuaUi +{ + class Element; + struct ScriptSettings + { + std::string mName; + std::string mSearchHints; + Element* mElement; // TODO: figure out if this can lead to use after free + }; + const std::vector& scriptSettings(); + void registerSettings(const ScriptSettings& script); + void clearSettings(); + void attachToWidget(const ScriptSettings& script, MyGUI::Widget* widget); +} + +#endif // !OPENMW_LUAUI_SCRIPTSETTINGS diff --git a/components/lua_ui/util.cpp b/components/lua_ui/util.cpp index 1e13c97a80..3987765617 100644 --- a/components/lua_ui/util.cpp +++ b/components/lua_ui/util.cpp @@ -9,6 +9,7 @@ #include "image.hpp" #include "element.hpp" +#include "scriptsettings.hpp" namespace LuaUi { @@ -37,6 +38,7 @@ namespace LuaUi void clearUserInterface() { + clearSettings(); while (!Element::sAllElements.empty()) Element::sAllElements.begin()->second->destroy(); } diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 8e81764f60..6a276ddd22 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -656,6 +656,19 @@ --> + + + + + + + + + + + + +