From 7cd898a87a83dbb1a6b932665d30ac239c6317a0 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 15 May 2023 00:53:26 +0300 Subject: [PATCH 1/6] Implemented "customTypes" in UI json to reduce duplicated definitions --- client/gui/InterfaceObjectConfigurable.cpp | 22 ++ client/gui/InterfaceObjectConfigurable.h | 2 + .../widgets/settings/generalOptionsTab.json | 255 ++++++++---------- 3 files changed, 132 insertions(+), 147 deletions(-) diff --git a/client/gui/InterfaceObjectConfigurable.cpp b/client/gui/InterfaceObjectConfigurable.cpp index 5196df21c..889cd04cb 100644 --- a/client/gui/InterfaceObjectConfigurable.cpp +++ b/client/gui/InterfaceObjectConfigurable.cpp @@ -65,14 +65,36 @@ void InterfaceObjectConfigurable::deleteWidget(const std::string & name) widgets.erase(iter); } +void InterfaceObjectConfigurable::loadCustomBuilders(const JsonNode & config) +{ + for(auto & item : config.Struct()) + { + std::string typeName = item.first; + JsonNode baseConfig = item.second; + + auto const & functor = [this, baseConfig](const JsonNode & widgetConfig) -> std::shared_ptr + { + JsonNode actualConfig = widgetConfig; + JsonUtils::mergeCopy(actualConfig, baseConfig); + + return this->buildWidget(actualConfig); + }; + + registerBuilder(typeName, functor); + } +} + void InterfaceObjectConfigurable::build(const JsonNode &config) { OBJ_CONSTRUCTION; + logGlobal->debug("Building configurable interface object"); auto * items = &config; if(config.getType() == JsonNode::JsonType::DATA_STRUCT) { + loadCustomBuilders(config["customTypes"]); + for(auto & item : config["variables"].Struct()) { logGlobal->debug("Read variable named %s", item.first); diff --git a/client/gui/InterfaceObjectConfigurable.h b/client/gui/InterfaceObjectConfigurable.h index e99c2f4d6..39e9797bc 100644 --- a/client/gui/InterfaceObjectConfigurable.h +++ b/client/gui/InterfaceObjectConfigurable.h @@ -45,6 +45,8 @@ protected: using BuilderFunction = std::function(const JsonNode &)>; void registerBuilder(const std::string &, BuilderFunction); + + void loadCustomBuilders(const JsonNode & config); //must be called after adding callbacks void build(const JsonNode & config); diff --git a/config/widgets/settings/generalOptionsTab.json b/config/widgets/settings/generalOptionsTab.json index 42a1544c9..17aae72fc 100644 --- a/config/widgets/settings/generalOptionsTab.json +++ b/config/widgets/settings/generalOptionsTab.json @@ -1,4 +1,51 @@ { + "customTypes" : { + "labelTitle" : { + "type": "label", + "font": "medium", + "alignment": "left", + "color": "yellow" + }, + "labelAudio" : { + "type": "label", + "font": "medium", + "alignment": "center", + "color": "yellow" + }, + "labelDescription" : { + "type": "label", + "font": "medium", + "alignment": "left", + "color": "white" + }, + "checkbox" : { + "type": "toggleButton", + "image": "sysopchk.def", + }, + "buttonGear" : { + "type": "button", + "image": "settingsWindow/button32", + "items": + [ + { + "name": "gearIcon", + "type": "picture", + "image": "settingsWindow/gear", + "position": {"x": 0, "y": 0 } + } + ] + }, + "audioSlider" : { + "type": "slider", + "scrollBounds" : { "x" : -4, "y" : -34, "w" : 208, "h" : 52 }, + "size": 200, + "style": "brown", + "orientation": "horizontal", + "itemsVisible": 0, + "itemsTotal": 100, + } + }, + "items": [ { @@ -9,151 +56,95 @@ }, { - "name": "settingGroupTitles", - "type": "labelGroup", - "font": "medium", - "alignment": "left", - "color": "yellow", - "items": - [ - { - "position": {"x": 10, "y": 55}, - "text": "vcmi.systemOptions.videoGroup" - }, - { - "position": {"x": 380, "y": 55}, - "text": "vcmi.systemOptions.audioGroup" - }, - { - "position": {"x": 10, "y": 295}, - "text": "vcmi.systemOptions.townsGroup" - } - ] + "type" : "labelTitle", + "position": {"x": 10, "y": 55}, + "text": "vcmi.systemOptions.videoGroup" + }, + { + "type" : "labelTitle", + "position": {"x": 380, "y": 55}, + "text": "vcmi.systemOptions.audioGroup" + }, + { + "type" : "labelTitle", + "position": {"x": 10, "y": 295}, + "text": "vcmi.systemOptions.townsGroup" }, /////////////////////////////////////// Left section - Video Settings { "name": "resolutionLabel", - "type": "label", - "font": "medium", - "alignment": "left", - "color": "white", + "type": "labelDescription", "position": {"x": 45, "y": 85}, "text": "vcmi.systemOptions.resolutionButton.hover" }, { "name": "resolutionButton", - "type": "button", + "type": "buttonGear", "position": {"x": 10, "y": 83}, - "image": "settingsWindow/button32", "help": "vcmi.systemOptions.resolutionButton", "callback": "setGameResolution", - "items": - [ - { - "name": "gearIcon", - "type": "picture", - "image": "settingsWindow/gear", - "position": {"x": 0, "y": 0 } - } - ] }, { "name": "scalingLabel", - "type": "label", - "font": "medium", - "alignment": "left", - "color": "white", + "type": "labelDescription", "position": {"x": 45, "y": 115}, "text": "vcmi.systemOptions.scalingButton.hover" }, { "name": "scalingButton", - "type": "button", + "type": "buttonGear", "position": {"x": 10, "y": 113}, - "image": "settingsWindow/button32", "help": "vcmi.systemOptions.scalingButton", "callback": "setGameScaling", - "items": - [ - { - "name": "gearIcon", - "type": "picture", - "image": "settingsWindow/gear", - "position": {"x": 0, "y": 0 } - } - ] }, - { - "name": "topCheckboxesLabels", - "type": "labelGroup", - "font": "medium", - "alignment": "left", - "color": "white", - "items": - [ - { - "position": {"x": 45, "y": 145}, - "text": "vcmi.systemOptions.fullscreenButton.hover" - }, - { - "position": {"x": 45, "y": 175}, - "text": "vcmi.systemOptions.framerateButton.hover" - }, - { - "position": {"x": 45, "y": 205}, - "text": "core.genrltxt.577" - }, - - ] + "type" : "labelDescription", + "position": {"x": 45, "y": 145}, + "text": "vcmi.systemOptions.fullscreenButton.hover" + }, + { + "type" : "labelDescription", + "position": {"x": 45, "y": 175}, + "text": "vcmi.systemOptions.framerateButton.hover" + }, + { + "type" : "labelDescription", + "position": {"x": 45, "y": 205}, + "text": "core.genrltxt.577" }, { "name": "fullscreenCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", + "type": "checkbox", "help": "vcmi.systemOptions.fullscreenButton", "position": {"x": 10, "y": 143}, "callback": "fullscreenChanged" }, { "name": "framerateCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", + "type": "checkbox", "help": "vcmi.systemOptions.framerateButton", "position": {"x": 10, "y": 173}, "callback": "framerateChanged" }, - { "name": "spellbookAnimationCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", + "type": "checkbox", "help": "core.help.364", "position": {"x": 10, "y": 203}, "callback": "spellbookAnimationChanged" }, - /////////////////////////////////////// Right section - Audio Settings { - "name": "settingAudioTitles", - "type": "labelGroup", - "font": "medium", - "alignment": "center", - "color": "yellow", - "items": - [ - { - "position": {"x": 460, "y": 98}, - "text": "core.genrltxt.394" // Music Volume - }, - { - "position": {"x": 460, "y": 158}, - "text": "core.genrltxt.395" // Effects volume - } - ] + "type" : "labelAudio", + "position": {"x": 460, "y": 98}, + "text": "core.genrltxt.394" // Music Volume + }, + { + "type" : "labelAudio", + "position": {"x": 460, "y": 158}, + "text": "core.genrltxt.395" // Effects volume }, - { "name": "frameMusic", "type": "picture", @@ -162,74 +153,47 @@ }, { "name": "musicSlider", - "type": "slider", + "type": "audioSlider", "position": {"x": 385, "y": 115}, - "scrollBounds" : { "x" : -4, "y" : -34, "w" : 208, "h" : 52 }, - "size": 200, - "style": "brown", - "orientation": "horizontal", - "itemsVisible": 0, - "itemsTotal": 100, "callback": "setMusic" }, { "name": "musicValueLabel", - "type": "label", - "font": "medium", - "alignment": "center", - "color": "yellow", + "type": "labelAudio", "position": {"x": 565, "y": 98} }, - { "name": "frameSound", "type": "picture", "image": "settingsWindow/frameAudio", "position": {"x": 380, "y": 140 } }, - { "name": "soundVolumeSlider", - "type": "slider", + "type": "audioSlider", "position": {"x": 385, "y": 175}, - "scrollBounds" : { "x" : -4, "y" : -34, "w" : 208, "h" : 52 }, - "size": 200, - "style": "brown", - "orientation": "horizontal", - "itemsVisible": 0, - "itemsTotal": 100, "callback": "setVolume" }, { "name": "soundValueLabel", - "type": "label", - "font": "medium", - "alignment": "center", - "color": "yellow", + "type": "labelAudio", "position": {"x": 565, "y": 158} }, /////////////////////////////////////// Bottom section - Towns Settings { - "name": "townCheckboxesLabels", - "type": "labelGroup", - "font": "medium", - "alignment": "left", - "color": "white", - "items": - [ - { - "text": "vcmi.otherOptions.creatureGrowthAsDwellingLabel.hover", - "position": {"x": 45, "y": 325} - }, - { - "text": "vcmi.otherOptions.availableCreaturesAsDwellingLabel.hover", - "position": {"x": 45, "y": 355} - }, - { - "text": "vcmi.otherOptions.compactTownCreatureInfo.hover", - "position": {"x": 45, "y": 385} - } - ] + "type" : "labelDescription", + "text": "vcmi.otherOptions.creatureGrowthAsDwellingLabel.hover", + "position": {"x": 45, "y": 325} + }, + { + "type" : "labelDescription", + "text": "vcmi.otherOptions.availableCreaturesAsDwellingLabel.hover", + "position": {"x": 45, "y": 355} + }, + { + "type" : "labelDescription", + "text": "vcmi.otherOptions.compactTownCreatureInfo.hover", + "position": {"x": 45, "y": 385} }, { @@ -240,15 +204,13 @@ [ { "index": 0, - "type": "toggleButton", - "image": "sysopchk.def", + "type": "checkbox", "help": "vcmi.otherOptions.creatureGrowthAsDwellingLabel", "position": {"x": 0, "y": 0} }, { "index": 1, - "type": "toggleButton", - "image": "sysopchk.def", + "type": "checkbox", "help": "vcmi.otherOptions.availableCreaturesAsDwellingLabel", "position": {"x": 0, "y": 30} }, @@ -258,8 +220,7 @@ { "name": "compactTownCreatureInfoCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", + "type": "checkbox", "help": "vcmi.otherOptions.compactTownCreatureInfo", "position": {"x": 10, "y": 383}, "callback": "compactTownCreatureInfoChanged" From 7cbfd8117ebfd3c99d3556199ce66f9b330ef901 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 15 May 2023 12:48:58 +0300 Subject: [PATCH 2/6] Implemented simple layout to simplify widget json definitions --- client/gui/InterfaceObjectConfigurable.cpp | 49 +++++ client/gui/InterfaceObjectConfigurable.h | 1 + .../widgets/settings/generalOptionsTab.json | 181 +++++++++--------- 3 files changed, 140 insertions(+), 91 deletions(-) diff --git a/client/gui/InterfaceObjectConfigurable.cpp b/client/gui/InterfaceObjectConfigurable.cpp index 889cd04cb..a7e1b4d73 100644 --- a/client/gui/InterfaceObjectConfigurable.cpp +++ b/client/gui/InterfaceObjectConfigurable.cpp @@ -46,6 +46,7 @@ InterfaceObjectConfigurable::InterfaceObjectConfigurable(int used, Point offset) REGISTER_BUILDER("button", &InterfaceObjectConfigurable::buildButton); REGISTER_BUILDER("labelGroup", &InterfaceObjectConfigurable::buildLabelGroup); REGISTER_BUILDER("slider", &InterfaceObjectConfigurable::buildSlider); + REGISTER_BUILDER("layout", &InterfaceObjectConfigurable::buildLayout); } void InterfaceObjectConfigurable::registerBuilder(const std::string & type, BuilderFunction f) @@ -468,6 +469,54 @@ std::shared_ptr InterfaceObjectConfigurable::buildTexture(const return std::make_shared(image, rect); } +/// Small helper class that provides ownership for shared_ptr's of child elements +class InterfaceLayoutWidget : public CIntObject +{ +public: + std::vector> ownedChildren; +}; + +std::shared_ptr InterfaceObjectConfigurable::buildLayout(const JsonNode & config) +{ + logGlobal->debug("Building widget Layout"); + bool vertical = config["vertical"].Bool(); + bool horizontal = config["horizontal"].Bool(); + bool dynamic = config["dynamic"].Bool(); + int distance = config["distance"].Integer(); + std::string customType = config["customType"].String(); + auto position = readPosition(config["position"]); + + auto result = std::make_shared(); + result->moveBy(position); + Point layoutPosition; + + for(auto item : config["items"].Vector()) + { + if (item["type"].String().empty()) + item["type"].String() = customType; + + auto widget = buildWidget(item); + + addWidget(item["name"].String(), widget); + result->ownedChildren.push_back(widget); + result->addChild(widget.get(), false); + + widget->moveBy(position + layoutPosition); + + if (dynamic && vertical) + layoutPosition.y += widget->pos.h; + if (dynamic && horizontal) + layoutPosition.x += widget->pos.w; + + if (vertical) + layoutPosition.y += distance; + if (horizontal) + layoutPosition.x += distance; + } + + return result; +} + std::shared_ptr InterfaceObjectConfigurable::buildAnimation(const JsonNode & config) const { logGlobal->debug("Building widget CShowableAnim"); diff --git a/client/gui/InterfaceObjectConfigurable.h b/client/gui/InterfaceObjectConfigurable.h index 39e9797bc..f744336cd 100644 --- a/client/gui/InterfaceObjectConfigurable.h +++ b/client/gui/InterfaceObjectConfigurable.h @@ -93,6 +93,7 @@ protected: std::shared_ptr buildImage(const JsonNode &) const; std::shared_ptr buildAnimation(const JsonNode &) const; std::shared_ptr buildTexture(const JsonNode &) const; + std::shared_ptr buildLayout(const JsonNode &); //composite widgets std::shared_ptr buildWidget(JsonNode config) const; diff --git a/config/widgets/settings/generalOptionsTab.json b/config/widgets/settings/generalOptionsTab.json index 17aae72fc..c3b48cde5 100644 --- a/config/widgets/settings/generalOptionsTab.json +++ b/config/widgets/settings/generalOptionsTab.json @@ -43,9 +43,15 @@ "orientation": "horizontal", "itemsVisible": 0, "itemsTotal": 100, + }, + "verticalLayout" : { + "type" : "layout", + "vertical" : true, + "dynamic" : false, + "distance" : 30 } }, - + "items": [ { @@ -54,7 +60,6 @@ "image": "settingsWindow/lineHorizontal", "rect": { "x" : 5, "y" : 289, "w": 365, "h": 3} }, - { "type" : "labelTitle", "position": {"x": 10, "y": 55}, @@ -72,67 +77,62 @@ }, /////////////////////////////////////// Left section - Video Settings { - "name": "resolutionLabel", - "type": "labelDescription", - "position": {"x": 45, "y": 85}, - "text": "vcmi.systemOptions.resolutionButton.hover" + "type" : "verticalLayout", + "customType" : "labelDescription", + "position" : {"x": 45, "y": 85}, + "items" : [ + { + "name": "resolutionLabel", + "text": "vcmi.systemOptions.resolutionButton.hover" + }, + { + "name": "scalingLabel", + "text": "vcmi.systemOptions.scalingButton.hover" + }, + { + "text": "vcmi.systemOptions.fullscreenButton.hover" + }, + { + "text": "vcmi.systemOptions.framerateButton.hover" + }, + { + "text": "core.genrltxt.577" + } + ] }, { - "name": "resolutionButton", - "type": "buttonGear", - "position": {"x": 10, "y": 83}, - "help": "vcmi.systemOptions.resolutionButton", - "callback": "setGameResolution", - }, - - { - "name": "scalingLabel", - "type": "labelDescription", - "position": {"x": 45, "y": 115}, - "text": "vcmi.systemOptions.scalingButton.hover" - }, - { - "name": "scalingButton", - "type": "buttonGear", - "position": {"x": 10, "y": 113}, - "help": "vcmi.systemOptions.scalingButton", - "callback": "setGameScaling", - }, - { - "type" : "labelDescription", - "position": {"x": 45, "y": 145}, - "text": "vcmi.systemOptions.fullscreenButton.hover" - }, - { - "type" : "labelDescription", - "position": {"x": 45, "y": 175}, - "text": "vcmi.systemOptions.framerateButton.hover" - }, - { - "type" : "labelDescription", - "position": {"x": 45, "y": 205}, - "text": "core.genrltxt.577" - }, - { - "name": "fullscreenCheckbox", - "type": "checkbox", - "help": "vcmi.systemOptions.fullscreenButton", - "position": {"x": 10, "y": 143}, - "callback": "fullscreenChanged" - }, - { - "name": "framerateCheckbox", - "type": "checkbox", - "help": "vcmi.systemOptions.framerateButton", - "position": {"x": 10, "y": 173}, - "callback": "framerateChanged" - }, - { - "name": "spellbookAnimationCheckbox", - "type": "checkbox", - "help": "core.help.364", - "position": {"x": 10, "y": 203}, - "callback": "spellbookAnimationChanged" + "type" : "verticalLayout", + "customType" : "checkbox", + "position" : {"x": 10, "y": 83}, + "items" : [ + { + "name": "resolutionButton", + "type": "buttonGear", + "help": "vcmi.systemOptions.resolutionButton", + "callback": "setGameResolution", + }, + { + "name": "scalingButton", + "type": "buttonGear", + "help": "vcmi.systemOptions.scalingButton", + "callback": "setGameScaling", + }, + { + "name": "fullscreenCheckbox", + "help": "vcmi.systemOptions.fullscreenButton", + "callback": "fullscreenChanged" + }, + { + "name": "framerateCheckbox", + "help": "vcmi.systemOptions.framerateButton", + "callback": "framerateChanged" + }, + { + "name": "spellbookAnimationCheckbox", + "help": "core.help.364", + "callback": "spellbookAnimationChanged" + }, + ] }, /////////////////////////////////////// Right section - Audio Settings { @@ -181,49 +181,48 @@ }, /////////////////////////////////////// Bottom section - Towns Settings { - "type" : "labelDescription", - "text": "vcmi.otherOptions.creatureGrowthAsDwellingLabel.hover", - "position": {"x": 45, "y": 325} + "type" : "verticalLayout", + "customType" : "labelDescription", + "position": {"x": 45, "y": 325}, + "items" : [ + { + "text": "vcmi.otherOptions.creatureGrowthAsDwellingLabel.hover", + }, + { + "text": "vcmi.otherOptions.availableCreaturesAsDwellingLabel.hover", + }, + { + "text": "vcmi.otherOptions.compactTownCreatureInfo.hover", + } + ] }, - { - "type" : "labelDescription", - "text": "vcmi.otherOptions.availableCreaturesAsDwellingLabel.hover", - "position": {"x": 45, "y": 355} - }, - { - "type" : "labelDescription", - "text": "vcmi.otherOptions.compactTownCreatureInfo.hover", - "position": {"x": 45, "y": 385} - }, - { "name": "availableCreaturesAsDwellingPicker", "type": "toggleGroup", + "callback": "availableCreaturesAsDwellingChanged" + }, + { + "type" : "verticalLayout", + "customType" : "checkbox", "position": {"x": 10, "y": 323}, "items": [ { - "index": 0, - "type": "checkbox", "help": "vcmi.otherOptions.creatureGrowthAsDwellingLabel", - "position": {"x": 0, "y": 0} + "group" : "availableCreaturesAsDwellingPicker", + "index": 0 }, { - "index": 1, - "type": "checkbox", "help": "vcmi.otherOptions.availableCreaturesAsDwellingLabel", - "position": {"x": 0, "y": 30} + "group" : "availableCreaturesAsDwellingPicker", + "index": 1 }, - ], - "callback": "availableCreaturesAsDwellingChanged" - }, - - { - "name": "compactTownCreatureInfoCheckbox", - "type": "checkbox", - "help": "vcmi.otherOptions.compactTownCreatureInfo", - "position": {"x": 10, "y": 383}, - "callback": "compactTownCreatureInfoChanged" + { + "name": "compactTownCreatureInfoCheckbox", + "help": "vcmi.otherOptions.compactTownCreatureInfo", + "callback": "compactTownCreatureInfoChanged" + } + ] } ] } From f2dfd6de42f589101632dc345144a9086c57d10b Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 15 May 2023 14:00:52 +0300 Subject: [PATCH 3/6] Updated settings window to use new layouts & library --- client/gui/InterfaceObjectConfigurable.cpp | 10 +- .../widgets/settings/adventureOptionsTab.json | 191 ++++++--------- config/widgets/settings/battleOptionsTab.json | 222 +++++++----------- .../widgets/settings/generalOptionsTab.json | 90 ++----- config/widgets/settings/library.json | 62 +++++ 5 files changed, 249 insertions(+), 326 deletions(-) create mode 100644 config/widgets/settings/library.json diff --git a/client/gui/InterfaceObjectConfigurable.cpp b/client/gui/InterfaceObjectConfigurable.cpp index a7e1b4d73..a107222d5 100644 --- a/client/gui/InterfaceObjectConfigurable.cpp +++ b/client/gui/InterfaceObjectConfigurable.cpp @@ -26,6 +26,7 @@ #include "../windows/InfoWindows.h" #include "../../lib/CGeneralTextHandler.h" +#include "../../lib/filesystem/ResourceID.h" InterfaceObjectConfigurable::InterfaceObjectConfigurable(const JsonNode & config, int used, Point offset): InterfaceObjectConfigurable(used, offset) @@ -80,7 +81,6 @@ void InterfaceObjectConfigurable::loadCustomBuilders(const JsonNode & config) return this->buildWidget(actualConfig); }; - registerBuilder(typeName, functor); } } @@ -94,6 +94,12 @@ void InterfaceObjectConfigurable::build(const JsonNode &config) if(config.getType() == JsonNode::JsonType::DATA_STRUCT) { + if (!config["library"].isNull()) + { + const JsonNode library(ResourceID(config["library"].String())); + loadCustomBuilders(library); + } + loadCustomBuilders(config["customTypes"]); for(auto & item : config["variables"].Struct()) @@ -101,7 +107,7 @@ void InterfaceObjectConfigurable::build(const JsonNode &config) logGlobal->debug("Read variable named %s", item.first); variables[item.first] = item.second; } - + items = &config["items"]; } diff --git a/config/widgets/settings/adventureOptionsTab.json b/config/widgets/settings/adventureOptionsTab.json index 1184d9069..40751131a 100644 --- a/config/widgets/settings/adventureOptionsTab.json +++ b/config/widgets/settings/adventureOptionsTab.json @@ -1,4 +1,6 @@ { + "library" : "config/widgets/settings/library.json", + "items": [ { @@ -28,37 +30,39 @@ }, { - "name": "topSettingsLabels", - "type": "labelGroup", - "font": "medium", - "alignment": "center", - "color": "yellow", + "type" : "verticalLayout60", + "customType" : "labelCentered", + "position": {"x": 150, "y": 62}, "items": [ { - "position": {"x": 150, "y": 62}, "text": "core.genrltxt.569" // Hero Speed }, { - "position": {"x": 150, "y": 122}, "text": "core.genrltxt.570" // Enemy Speed }, { - "position": {"x": 150, "y": 182}, "text": "core.genrltxt.571" // Scrolling Speed } ] }, - { - "name": "heroSpeedValueLabel", - "type": "label", - "font": "medium", - "alignment": "center", - "color": "yellow", - "position": {"x": 324, "y": 90} + "type" : "verticalLayout60", + "customType" : "labelCentered", + "position": {"x": 324, "y": 90}, + "items": + [ + { + "name": "heroSpeedValueLabel", + }, + { + "name": "enemySpeedValueLabel", + }, + { + "name": "mapScrollingValueLabel", + } + ] }, - { "name": "heroMovementSpeedPicker", "type": "toggleGroup", @@ -110,16 +114,6 @@ ], "callback": "playerHeroSpeedChanged" }, - - { - "name": "enemySpeedValueLabel", - "type": "label", - "font": "medium", - "alignment": "center", - "color": "yellow", - "position": {"x": 324, "y": 150} - }, - { "name": "enemyMovementSpeedPicker", "type": "toggleGroup", @@ -176,15 +170,6 @@ ], "callback": "enemyHeroSpeedChanged" }, - - { - "name": "mapScrollingValueLabel", - "type": "label", - "font": "medium", - "alignment": "center", - "color": "yellow", - "position": {"x": 324, "y": 210} - }, { "name": "mapScrollSpeedPicker", "type": "toggleGroup", @@ -296,120 +281,100 @@ /////////////////////////////////////// Right section - Original H3 options { - "name": "rightCheckboxesLabels", - "type": "labelGroup", - "font": "medium", - "alignment": "left", - "color": "white", + "type" : "verticalLayout", + "customType" : "labelDescription", + "position": {"x": 415, "y": 55}, "items": [ { - "position": {"x": 415, "y": 55}, "text": "core.genrltxt.572" // TODO: show move path }, { - "position": {"x": 415, "y": 85}, "text": "core.genrltxt.573" // show hero reminder }, { - "position": {"x": 415, "y": 115}, "text": "core.genrltxt.574" // quick combat } ] }, { - "name": "showMovePathPlaceholder", - "type": "picture", - "image": "settingsWindow/checkBoxEmpty", + "type" : "verticalLayout", + "customType" : "checkbox", "position": {"x": 380, "y": 53}, - }, - { - "name": "heroReminderCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", - "help": "core.help.361", - "position": {"x": 380, "y": 83}, - "callback": "heroReminderChanged" - }, - { - "name": "quickCombatCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", - "help": "core.help.362", - "position": {"x": 380, "y": 113}, - "callback": "quickCombatChanged" - }, - -/////////////////////////////////////// Bottom section - VCMI Options - { - "name": "bottomCheckboxesLabels", - "type": "labelGroup", - "font": "medium", - "alignment": "left", - "color": "white", "items": [ { - "position": {"x": 45, "y": 295}, + "name": "showMovePathPlaceholder", + "type": "checkboxFake", + }, + { + "name": "heroReminderCheckbox", + "help": "core.help.361", + "callback": "heroReminderChanged" + }, + { + "name": "quickCombatCheckbox", + "help": "core.help.362", + "callback": "quickCombatChanged" + }, + ] + }, +/////////////////////////////////////// Bottom section - VCMI Options + { + "type": "verticalLayout", + "customType": "labelDescription", + "position": {"x": 45, "y": 295}, + "items": + [ + { "text": "vcmi.adventureOptions.numericQuantities.hover" }, { - "position": {"x": 45, "y": 325}, "text": "vcmi.adventureOptions.forceMovementInfo.hover" }, { - "position": {"x": 45, "y": 355}, "text": "vcmi.adventureOptions.showGrid.hover" }, { - "position": {"x": 45, "y": 385}, "text": "vcmi.adventureOptions.mapSwipe.hover" }, { - "position": {"x": 45, "y": 415}, "text": "vcmi.adventureOptions.infoBarPick.hover" } ] }, { - "name": "numericQuantitiesCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", - "help": "vcmi.adventureOptions.numericQuantities", + "type": "verticalLayout", + "customType": "checkbox", "position": {"x": 10, "y": 293}, - "callback": "numericQuantitiesChanged" - }, - { - "name": "forceMovementInfoCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", - "help": "vcmi.adventureOptions.forceMovementInfo", - "position": {"x": 10, "y": 323}, - "callback": "forceMovementInfoChanged" - }, - { - "name": "showGridCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", - "help": "vcmi.adventureOptions.showGrid", - "position": {"x": 10, "y": 353}, - "callback": "showGridChanged" - }, - { - "name": "mapSwipeCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", - "help": "vcmi.adventureOptions.mapSwipe", - "position": {"x": 10, "y": 383}, - "callback": "mapSwipeChanged" - }, - { - "name": "infoBarPickCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", - "help": "vcmi.adventureOptions.infoBarPick", - "position": {"x": 10, "y": 413}, - "callback": "infoBarPickChanged" + "items": + [ + { + "name": "numericQuantitiesCheckbox", + "help": "vcmi.adventureOptions.numericQuantities", + "callback": "numericQuantitiesChanged" + }, + { + "name": "forceMovementInfoCheckbox", + "help": "vcmi.adventureOptions.forceMovementInfo", + "callback": "forceMovementInfoChanged" + }, + { + "name": "showGridCheckbox", + "help": "vcmi.adventureOptions.showGrid", + "callback": "showGridChanged" + }, + { + "name": "mapSwipeCheckbox", + "help": "vcmi.adventureOptions.mapSwipe", + "callback": "mapSwipeChanged" + }, + { + "name": "infoBarPickCheckbox", + "help": "vcmi.adventureOptions.infoBarPick", + "callback": "infoBarPickChanged" + } + ] } ] } diff --git a/config/widgets/settings/battleOptionsTab.json b/config/widgets/settings/battleOptionsTab.json index 8854271a4..f4f1b8b4b 100644 --- a/config/widgets/settings/battleOptionsTab.json +++ b/config/widgets/settings/battleOptionsTab.json @@ -1,4 +1,6 @@ { + "library" : "config/widgets/settings/library.json", + "items": [ { @@ -13,200 +15,140 @@ "image": "settingsWindow/lineHorizontal", "rect": { "x" : 5, "y" : 319, "w": 365, "h": 3} }, - { - "name": "titlesLabels", - "type": "labelGroup", - "font": "medium", - "alignment": "left", - "color": "yellow", - "items": - [ - { - "text": "core.genrltxt.396", // Auto-combat options - "position": {"x": 380, "y": 55} - }, - { - "text": "core.genrltxt.397", // Creature info - "position": {"x": 10, "y": 235} - } - ] + "type" : "labelTitle", + "text": "core.genrltxt.396", // Auto-combat options + "position": {"x": 380, "y": 55} + }, + { + "type" : "labelTitle", + "text": "core.genrltxt.397", // Creature info + "position": {"x": 10, "y": 235} }, /////////////////////////////////////// Right section - Auto-combat settings (NOT IMPLEMENTED) { "name": "autoCombatLabels", - "type": "labelGroup", - "font": "medium", - "alignment": "left", - "color": "white", + "type" : "verticalLayout", + "customType" : "labelDescription", + "position": {"x": 415, "y": 85}, "items": [ { - "text": "core.genrltxt.398", // Creatures - "position": {"x": 415, "y": 85} + "text": "core.genrltxt.398" // Creatures }, { - "text": "core.genrltxt.399", // Spells - "position": {"x": 415, "y": 115} + "text": "core.genrltxt.399" // Spells }, { - "text": "core.genrltxt.400", // Catapult - "position": {"x": 415, "y": 145} + "text": "core.genrltxt.400" // Catapult }, { - "text": "core.genrltxt.151", // Ballista - "position": {"x": 415, "y": 175} + "text": "core.genrltxt.151" // Ballista }, { - "text": "core.genrltxt.401", // First Aid Tent - "position": {"x": 415, "y": 205} + "text": "core.genrltxt.401" // First Aid Tent } ] }, { - "name": "autoCombatCreaturesPlaceholder", - "type": "picture", - "image": "settingsWindow/checkBoxEmpty", + "name": "autoCombatCheckboxes", + "type" : "verticalLayout", + "customType" : "checkboxFake", "position": {"x": 380, "y": 83}, - }, - { - "name": "autoCombatSpellsPlaceholder", - "type": "picture", - "image": "settingsWindow/checkBoxEmpty", - "position": {"x": 380, "y": 113}, - }, - { - "name": "autoCombatCatapultPlaceholder", - "type": "picture", - "image": "settingsWindow/checkBoxEmpty", - "position": {"x": 380, "y": 143}, - }, - { - "name": "autoCombatBallistaPlaceholder", - "type": "picture", - "image": "settingsWindow/checkBoxEmpty", - "position": {"x": 380, "y": 173}, - }, - { - "name": "autoCombatFirstAidTentPlaceholder", - "type": "picture", - "image": "settingsWindow/checkBoxEmpty", - "position": {"x": 380, "y": 203}, + "items": + [ + {}, + {}, + {}, + {}, + {} + ] }, /////////////////////////////////////// Left section - checkboxes { - "name": "creatureInfoLabels", - "type": "labelGroup", - "font": "medium", - "alignment": "left", - "color": "white", - "items": - [ - { - "text": "core.genrltxt.402", // All Stats - "position": {"x": 45, "y": 265} - }, - { - "text": "core.genrltxt.403", // Spells only - "position": {"x": 45, "y": 295} - } - ] + "type": "labelDescription", + "text": "core.genrltxt.402", // All Stats + "position": {"x": 45, "y": 265} + }, + { + "type": "labelDescription", + "text": "core.genrltxt.403", // Spells only + "position": {"x": 45, "y": 295} }, { "name": "creatureInfoAllPlaceholder", - "type": "picture", - "image": "settingsWindow/checkBoxEmpty", + "type": "checkboxFake", "position": {"x": 10, "y": 263}, }, { "name": "creatureInfoSpellsPlaceholder", - "type": "picture", - "image": "settingsWindow/checkBoxEmpty", + "type": "checkboxFake", "position": {"x": 10, "y": 293}, }, - { "name": "generalOptionsLabels", - "type": "labelGroup", - "font": "medium", - "alignment": "left", - "color": "white", + "type" : "verticalLayout", + "customType" : "labelDescription", + "position": {"x": 45, "y": 55}, "items": [ { "text": "core.genrltxt.404", - "position": {"x": 45, "y": 55} }, { "text": "core.genrltxt.405", - "position": {"x": 45, "y": 85} }, { "text": "vcmi.battleOptions.movementHighlightOnHover.hover", - "position": {"x": 45, "y": 115} }, { "text": "core.genrltxt.406", - "position": {"x": 45, "y": 145} }, { "text": "vcmi.battleOptions.skipBattleIntroMusic.hover", - "position": {"x": 45, "y": 175} }, { "text": "vcmi.battleOptions.touchscreenMode.hover", - "position": {"x": 45, "y": 205} } ] }, - { - "name": "viewGridCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", - "help": "core.help.427", + "type" : "verticalLayout", + "customType" : "checkbox", "position": {"x": 10, "y": 53}, - "callback": "viewGridChanged" - }, - { - "name": "movementShadowCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", - "help": "core.help.428", - "position": {"x": 10, "y": 83}, - "callback": "movementShadowChanged" - }, - { - "name": "movementHighlightOnHoverCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", - "help": "vcmi.battleOptions.movementHighlightOnHover", - "position": {"x": 10, "y": 113}, - "callback": "movementHighlightOnHoverChanged" - }, - { - "name": "mouseShadowCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", - "help": "core.help.429", - "position": {"x": 10, "y": 143}, - "callback": "mouseShadowChanged" - }, - { - "name": "skipBattleIntroMusicCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", - "help": "vcmi.battleOptions.skipBattleIntroMusic", - "position": {"x": 10, "y": 173}, - "callback": "skipBattleIntroMusicChanged" - }, - { - "name": "touchscreenModeCheckbox", - "type": "toggleButton", - "image": "sysopchk.def", - "help": "vcmi.battleOptions.touchscreenMode", - "position": {"x": 10, "y": 203}, - "callback": "touchscreenModeChanged" + "items": + [ + { + "name": "viewGridCheckbox", + "help": "core.help.427", + "callback": "viewGridChanged" + }, + { + "name": "movementShadowCheckbox", + "help": "core.help.428", + "callback": "movementShadowChanged" + }, + { + "name": "movementHighlightOnHoverCheckbox", + "help": "vcmi.battleOptions.movementHighlightOnHover", + "callback": "movementHighlightOnHoverChanged" + }, + { + "name": "mouseShadowCheckbox", + "help": "core.help.429", + "callback": "mouseShadowChanged" + }, + { + "name": "skipBattleIntroMusicCheckbox", + "help": "vcmi.battleOptions.skipBattleIntroMusic", + "callback": "skipBattleIntroMusicChanged" + }, + { + "name": "touchscreenModeCheckbox", + "help": "vcmi.battleOptions.touchscreenMode", + "callback": "touchscreenModeChanged" + }, + ] }, /////////////////////////////////////// Bottom section - Animation Speed and Turn Order { @@ -217,19 +159,13 @@ }, { "name": "animationSpeedLabel", - "type": "label", - "font": "medium", - "alignment": "center", - "color": "yellow", + "type": "labelCentered", "text": "core.genrltxt.393", "position": {"x": 150, "y": 362} }, { "name": "animationSpeedValueLabel", - "type": "label", - "font": "medium", - "alignment": "center", - "color": "yellow", + "type": "labelCentered", "position": {"x": 324, "y": 390} }, { diff --git a/config/widgets/settings/generalOptionsTab.json b/config/widgets/settings/generalOptionsTab.json index c3b48cde5..5a87015d8 100644 --- a/config/widgets/settings/generalOptionsTab.json +++ b/config/widgets/settings/generalOptionsTab.json @@ -1,56 +1,5 @@ { - "customTypes" : { - "labelTitle" : { - "type": "label", - "font": "medium", - "alignment": "left", - "color": "yellow" - }, - "labelAudio" : { - "type": "label", - "font": "medium", - "alignment": "center", - "color": "yellow" - }, - "labelDescription" : { - "type": "label", - "font": "medium", - "alignment": "left", - "color": "white" - }, - "checkbox" : { - "type": "toggleButton", - "image": "sysopchk.def", - }, - "buttonGear" : { - "type": "button", - "image": "settingsWindow/button32", - "items": - [ - { - "name": "gearIcon", - "type": "picture", - "image": "settingsWindow/gear", - "position": {"x": 0, "y": 0 } - } - ] - }, - "audioSlider" : { - "type": "slider", - "scrollBounds" : { "x" : -4, "y" : -34, "w" : 208, "h" : 52 }, - "size": 200, - "style": "brown", - "orientation": "horizontal", - "itemsVisible": 0, - "itemsTotal": 100, - }, - "verticalLayout" : { - "type" : "layout", - "vertical" : true, - "dynamic" : false, - "distance" : 30 - } - }, + "library" : "config/widgets/settings/library.json", "items": [ @@ -136,12 +85,12 @@ }, /////////////////////////////////////// Right section - Audio Settings { - "type" : "labelAudio", + "type" : "labelCentered", "position": {"x": 460, "y": 98}, "text": "core.genrltxt.394" // Music Volume }, { - "type" : "labelAudio", + "type" : "labelCentered", "position": {"x": 460, "y": 158}, "text": "core.genrltxt.395" // Effects volume }, @@ -159,7 +108,7 @@ }, { "name": "musicValueLabel", - "type": "labelAudio", + "type": "labelCentered", "position": {"x": 565, "y": 98} }, { @@ -176,7 +125,7 @@ }, { "name": "soundValueLabel", - "type": "labelAudio", + "type": "labelCentered", "position": {"x": 565, "y": 158} }, /////////////////////////////////////// Bottom section - Towns Settings @@ -202,27 +151,32 @@ "callback": "availableCreaturesAsDwellingChanged" }, { - "type" : "verticalLayout", - "customType" : "checkbox", + "name": "availableCreaturesAsDwellingPicker", + "type": "toggleGroup", "position": {"x": 10, "y": 323}, "items": [ { + "index": 0, + "type": "checkbox", "help": "vcmi.otherOptions.creatureGrowthAsDwellingLabel", - "group" : "availableCreaturesAsDwellingPicker", - "index": 0 + "position": {"x": 0, "y": 0} }, { + "index": 1, + "type": "checkbox", "help": "vcmi.otherOptions.availableCreaturesAsDwellingLabel", - "group" : "availableCreaturesAsDwellingPicker", - "index": 1 + "position": {"x": 0, "y": 30} }, - { - "name": "compactTownCreatureInfoCheckbox", - "help": "vcmi.otherOptions.compactTownCreatureInfo", - "callback": "compactTownCreatureInfoChanged" - } - ] + ], + "callback": "availableCreaturesAsDwellingChanged" + }, + { + "name": "compactTownCreatureInfoCheckbox", + "type": "checkbox", + "help": "vcmi.otherOptions.compactTownCreatureInfo", + "position": {"x": 10, "y": 383}, + "callback": "compactTownCreatureInfoChanged" } ] } diff --git a/config/widgets/settings/library.json b/config/widgets/settings/library.json new file mode 100644 index 000000000..c5ea07f95 --- /dev/null +++ b/config/widgets/settings/library.json @@ -0,0 +1,62 @@ +{ + "labelTitle" : { + "type": "label", + "font": "medium", + "alignment": "left", + "color": "yellow" + }, + "labelCentered" : { + "type": "label", + "font": "medium", + "alignment": "center", + "color": "yellow" + }, + "labelDescription" : { + "type": "label", + "font": "medium", + "alignment": "left", + "color": "white" + }, + "checkbox" : { + "type": "toggleButton", + "image": "sysopchk.def", + }, + "buttonGear" : { + "type": "button", + "image": "settingsWindow/button32", + "items": + [ + { + "name": "gearIcon", + "type": "picture", + "image": "settingsWindow/gear", + "position": {"x": 0, "y": 0 } + } + ] + }, + "checkboxFake" : { + "type": "picture", + "image": "settingsWindow/checkBoxEmpty" + }, + "audioSlider" : { + "type": "slider", + "scrollBounds" : { "x" : -4, "y" : -34, "w" : 208, "h" : 52 }, + "size": 200, + "style": "brown", + "orientation": "horizontal", + "itemsVisible": 0, + "itemsTotal": 100, + }, + "verticalLayout" : { + "type" : "layout", + "vertical" : true, + "dynamic" : false, + "distance" : 30 + }, + "verticalLayout60" : { + "type" : "layout", + "vertical" : true, + "dynamic" : false, + "distance" : 60 + } +} From d18b240d6d608e0285a8a57b4f389c5ba2519d6d Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 15 May 2023 19:44:02 +0300 Subject: [PATCH 4/6] Added separate borderless & exclusive fullscreen options --- Mods/vcmi/config/vcmi/english.json | 6 ++- Mods/vcmi/config/vcmi/german.json | 2 - Mods/vcmi/config/vcmi/polish.json | 3 -- Mods/vcmi/config/vcmi/russian.json | 3 -- Mods/vcmi/config/vcmi/spanish.json | 3 -- Mods/vcmi/config/vcmi/ukrainian.json | 9 ++-- client/gui/InterfaceObjectConfigurable.cpp | 3 +- client/windows/settings/GeneralOptionsTab.cpp | 46 +++++++++++-------- client/windows/settings/GeneralOptionsTab.h | 2 +- .../widgets/settings/generalOptionsTab.json | 24 ++++++++-- 10 files changed, 58 insertions(+), 43 deletions(-) diff --git a/Mods/vcmi/config/vcmi/english.json b/Mods/vcmi/config/vcmi/english.json index f604b2cc6..cb05adf4c 100644 --- a/Mods/vcmi/config/vcmi/english.json +++ b/Mods/vcmi/config/vcmi/english.json @@ -46,8 +46,10 @@ "vcmi.systemOptions.otherGroup" : "Other Settings", // unused right now "vcmi.systemOptions.townsGroup" : "Town Screen", - "vcmi.systemOptions.fullscreenButton.hover" : "Fullscreen", - "vcmi.systemOptions.fullscreenButton.help" : "{Fullscreen}\n\nIf selected, VCMI will run in fullscreen mode, otherwise it will run in windowed mode", + "vcmi.systemOptions.fullscreenBorderless.hover" : "Fullscreen (borderless)", + "vcmi.systemOptions.fullscreenBorderless.help" : "{Borderless Fullscreen}\n\nIf selected, VCMI will run in borderless fullscreen mode. In this mode, game will always use same resolution as desktop, ignoring selected resolution.", + "vcmi.systemOptions.fullscreenExclusive.hover" : "Fullscreen (exclusive)", + "vcmi.systemOptions.fullscreenExclusive.help" : "{Fullscreen}\n\nIf selected, VCMI will run in exclusive fullscreen mode. In this mode, game will change resolution of monitor to selected resolution.", "vcmi.systemOptions.resolutionButton.hover" : "Resolution: %wx%h", "vcmi.systemOptions.resolutionButton.help" : "{Select Resolution}\n\nChange in-game screen resolution.", "vcmi.systemOptions.resolutionMenu.hover" : "Select Resolution", diff --git a/Mods/vcmi/config/vcmi/german.json b/Mods/vcmi/config/vcmi/german.json index 105af9ab8..3f17d3910 100644 --- a/Mods/vcmi/config/vcmi/german.json +++ b/Mods/vcmi/config/vcmi/german.json @@ -46,8 +46,6 @@ "vcmi.systemOptions.otherGroup" : "Andere Einstellungen", // unused right now "vcmi.systemOptions.townsGroup" : "Stadt-Bildschirm", - "vcmi.systemOptions.fullscreenButton.hover" : "Vollbild", - "vcmi.systemOptions.fullscreenButton.help" : "{Vollbild}\n\n Wenn ausgewählt wird VCMI im Vollbildmodus laufen, ansonsten im Fenstermodus", "vcmi.systemOptions.resolutionButton.hover" : "Auflösung: %wx%h", "vcmi.systemOptions.resolutionButton.help" : "{Wähle Auflösung}\n\n Ändert die Spielauflösung. Spielneustart ist erforderlich um neue Auflösung zu übernehmen.", "vcmi.systemOptions.resolutionMenu.hover" : "Wähle Auflösung", diff --git a/Mods/vcmi/config/vcmi/polish.json b/Mods/vcmi/config/vcmi/polish.json index a33d2f5a2..8d07deb36 100644 --- a/Mods/vcmi/config/vcmi/polish.json +++ b/Mods/vcmi/config/vcmi/polish.json @@ -37,13 +37,10 @@ "vcmi.systemOptions.otherGroup" : "Inne ustawienia", // unused right now "vcmi.systemOptions.townsGroup" : "Ekran miasta", - "vcmi.systemOptions.fullscreenButton.hover" : "Pełny ekran", - "vcmi.systemOptions.fullscreenButton.help" : "{Pełny ekran}\n\n Po wybraniu VCMI uruchomi się w trybie pełnoekranowym, w przeciwnym wypadku uruchomi się w oknie", "vcmi.systemOptions.resolutionButton.hover" : "Rozdzielczość: %wx%h", "vcmi.systemOptions.resolutionButton.help" : "{Wybierz rozdzielczość}\n\n Zmień rozdzielczość ekranu w grze. Restart gry jest wymagany, by zmiany zostały uwzględnione.", "vcmi.systemOptions.resolutionMenu.hover" : "Wybierz rozdzielczość", "vcmi.systemOptions.resolutionMenu.help" : "Zmień rozdzielczość ekranu w grze.", - "vcmi.systemOptions.fullscreenFailed" : "{Pełny ekran}\n\n Nieudane przełączenie w tryb pełnoekranowy! Obecna rozdzielczość nie jest wspierana przez wyświetlacz!", "vcmi.systemOptions.framerateButton.hover" : "Pokaż FPS", "vcmi.systemOptions.framerateButton.help" : "{Pokaż FPS}\n\n Przełącza widoczność licznika klatek na sekundę (FPS) w rogu okna gry.", diff --git a/Mods/vcmi/config/vcmi/russian.json b/Mods/vcmi/config/vcmi/russian.json index 1996637ee..36c45cf84 100644 --- a/Mods/vcmi/config/vcmi/russian.json +++ b/Mods/vcmi/config/vcmi/russian.json @@ -37,13 +37,10 @@ "vcmi.systemOptions.otherGroup" : "Иное", // unused right now "vcmi.systemOptions.townsGroup" : "Экран города", - "vcmi.systemOptions.fullscreenButton.hover" : "Полный экран", - "vcmi.systemOptions.fullscreenButton.help" : "{Полный экран}\n\n Если выбрано, то VCMI будет работать в полноэкранном режиме, если нет - в окне", "vcmi.systemOptions.resolutionButton.hover" : "Разрешение %wx%h", "vcmi.systemOptions.resolutionButton.help" : "{Разрешение экрана}\n\n Изменение разрешения экрана. Для применения нового разрешения требуется перезапуск игры.", "vcmi.systemOptions.resolutionMenu.hover" : "Выбрать разрешения экрана", "vcmi.systemOptions.resolutionMenu.help" : "Изменение разрешения экрана в игре.", - "vcmi.systemOptions.fullscreenFailed" : "{Полный экран}\n\n Невозможно переключиться в полноэкранный режим - выбранное разрешение не поддерживается дисплеем!", "vcmi.systemOptions.framerateButton.hover" : "Показывать частоту кадров", "vcmi.systemOptions.framerateButton.help" : "{Показывать частоту кадров}\n\n Включить счетчик частоты кадров в углу игрового клиента", diff --git a/Mods/vcmi/config/vcmi/spanish.json b/Mods/vcmi/config/vcmi/spanish.json index 2d6e5e32c..2e98760a1 100644 --- a/Mods/vcmi/config/vcmi/spanish.json +++ b/Mods/vcmi/config/vcmi/spanish.json @@ -46,13 +46,10 @@ "vcmi.systemOptions.otherGroup" : "Otras configuraciones", // actualmente no utilizada "vcmi.systemOptions.townsGroup" : "Pantalla de la ciudad", - "vcmi.systemOptions.fullscreenButton.hover" : "Pantalla completa", - "vcmi.systemOptions.fullscreenButton.help" : "{Pantalla completa}\n\n Si se selecciona, VCMI se ejecutará en modo de pantalla completa, de lo contrario se ejecutará en ventana", "vcmi.systemOptions.resolutionButton.hover" : "Resolución: %wx%h", "vcmi.systemOptions.resolutionButton.help" : "{Seleccionar resolución}\n\n Cambia la resolución de la pantalla del juego. Se requiere reiniciar el juego para aplicar la nueva resolución.", "vcmi.systemOptions.resolutionMenu.hover" : "Seleccionar resolución", "vcmi.systemOptions.resolutionMenu.help" : "Cambia la resolución de la pantalla del juego.", - "vcmi.systemOptions.fullscreenFailed" : "{Pantalla completa}\n\n ¡Fallo al cambiar a modo de pantalla completa! ¡La resolución actual no es compatible con la pantalla!", "vcmi.systemOptions.framerateButton.hover" : "Mostrar FPS", "vcmi.systemOptions.framerateButton.help" : "{Mostrar FPS}\n\n Muestra el contador de Frames Por Segundo en la esquina de la ventana del juego.", diff --git a/Mods/vcmi/config/vcmi/ukrainian.json b/Mods/vcmi/config/vcmi/ukrainian.json index 9723d9fca..bc33ddb0b 100644 --- a/Mods/vcmi/config/vcmi/ukrainian.json +++ b/Mods/vcmi/config/vcmi/ukrainian.json @@ -38,15 +38,18 @@ "vcmi.systemOptions.otherGroup" : "Інші налаштування", "vcmi.systemOptions.townsGroup" : "Екран міста", - "vcmi.adventureOptions.infoBarPick.help" : "{Повідомлення у панелі статусу}\n\nЗа можливості, повідомлення про відвідування об'єктів карти пригод будуть відображені у панелі статусу замість окремого вікна", - "vcmi.adventureOptions.infoBarPick.hover" : "Повідомлення у панелі статусу", + "vcmi.systemOptions.fullscreenBorderless.hover" : "На весь екран (безрамкове вікно)", + "vcmi.systemOptions.fullscreenBorderless.help" : "{На весь екран (безрамкове вікно)}\n\nЯкщо обрано, VCMI працюватиме у режимі безрамкового вікна на весь екран. У цьому режимі гра завжди використовує ту саму роздільну здатність, що й робочий стіл, ігноруючи вибрану роздільну здатність", + "vcmi.systemOptions.fullscreenExclusive.hover" : "На весь екран (ексклюзивний режим)", + "vcmi.systemOptions.fullscreenExclusive.help" : "{На весь екран (ексклюзивний режим)}\n\nnЯкщо вибрано, VCMI працюватиме у ексклюзивному повноекранному режимі. У цьому режимі гра змінюватиме роздільну здатність монітора на вибрану роздільну здатність", + "vcmi.adventureOptions.infoBarPick.help" : "{Повідомлення у панелі статусу}\n\nЗа можливості, повідомлення про відвідування об'єктів карти пригод будуть відображені у панелі статусу замість окремого вікна", + "vcmi.adventureOptions.infoBarPick.hover" : "Повідомлення у панелі статусу", "vcmi.systemOptions.fullscreenButton.hover" : "Повноекранний режим", "vcmi.systemOptions.fullscreenButton.help" : "{Повноекранний режим}\n\n Якщо обрано, VCMI буде запускатися в режимі на весь екран, інакше — віконний режим", "vcmi.systemOptions.resolutionButton.hover" : "Роздільна здатність: %wx%h", "vcmi.systemOptions.resolutionButton.help" : "{Роздільна здатність}\n\n Зміна розширення екрану в грі. Аби зміни набули чинності необхідно перезавантажити гру.", "vcmi.systemOptions.resolutionMenu.hover" : "Обрати роздільну здатність", "vcmi.systemOptions.resolutionMenu.help" : "Змінити роздільну здатність екрану в грі.", - "vcmi.systemOptions.fullscreenFailed" : "{Повноекранний режим}\n\n Не вдалося перейти в повноекранний режим! Поточна роздільна здатність не підтримується дисплеєм!", "vcmi.systemOptions.framerateButton.hover" : "Лічильник кадрів", "vcmi.systemOptions.framerateButton.help" : "{Лічильник кадрів}\n\n Перемикає видимість лічильника кадрів на секунду у кутку ігрового вікна", diff --git a/client/gui/InterfaceObjectConfigurable.cpp b/client/gui/InterfaceObjectConfigurable.cpp index a107222d5..273f5fd3d 100644 --- a/client/gui/InterfaceObjectConfigurable.cpp +++ b/client/gui/InterfaceObjectConfigurable.cpp @@ -297,7 +297,8 @@ std::shared_ptr InterfaceObjectConfigurable::buildToggleGroup(cons for(const auto & item : config["items"].Vector()) { itemIdx = item["index"].isNull() ? itemIdx + 1 : item["index"].Integer(); - group->addToggle(itemIdx, std::dynamic_pointer_cast(buildWidget(item))); + auto newToggle = std::dynamic_pointer_cast(buildWidget(item)); + group->addToggle(itemIdx, newToggle); } } if(!config["selected"].isNull()) diff --git a/client/windows/settings/GeneralOptionsTab.cpp b/client/windows/settings/GeneralOptionsTab.cpp index ff80b29a9..d34c152a3 100644 --- a/client/windows/settings/GeneralOptionsTab.cpp +++ b/client/windows/settings/GeneralOptionsTab.cpp @@ -102,9 +102,13 @@ GeneralOptionsTab::GeneralOptionsTab() targetLabel->setText(std::to_string(value) + "%"); }); //settings that do not belong to base game: - addCallback("fullscreenChanged", [this](bool value) + addCallback("fullscreenBorderlessChanged", [this](bool value) { - setFullscreenMode(value); + setFullscreenMode(value, false); + }); + addCallback("fullscreenExclusiveChanged", [this](bool value) + { + setFullscreenMode(value, true); }); addCallback("setGameResolution", [this](int dummyValue) { @@ -135,7 +139,8 @@ GeneralOptionsTab::GeneralOptionsTab() const auto & currentResolution = settings["video"]["resolution"]; std::shared_ptr resolutionLabel = widget("resolutionLabel"); - resolutionLabel->setText(resolutionToLabelString(currentResolution["width"].Integer(), currentResolution["height"].Integer())); + if (resolutionLabel) + resolutionLabel->setText(resolutionToLabelString(currentResolution["width"].Integer(), currentResolution["height"].Integer())); std::shared_ptr scalingLabel = widget("scalingLabel"); scalingLabel->setText(scalingToLabelString(currentResolution["scaling"].Integer())); @@ -143,12 +148,13 @@ GeneralOptionsTab::GeneralOptionsTab() std::shared_ptr spellbookAnimationCheckbox = widget("spellbookAnimationCheckbox"); spellbookAnimationCheckbox->setSelected(settings["video"]["spellbookAnimation"].Bool()); - std::shared_ptr fullscreenCheckbox = widget("fullscreenCheckbox"); - fullscreenCheckbox->setSelected(settings["video"]["fullscreen"].Bool()); - onFullscreenChanged([&](const JsonNode &newState) //used when pressing F4 etc. to change fullscreen checkbox state - { - widget("fullscreenCheckbox")->setSelected(newState.Bool()); - }); + std::shared_ptr fullscreenBorderlessCheckbox = widget("fullscreenBorderlessCheckbox"); + if (fullscreenBorderlessCheckbox) + fullscreenBorderlessCheckbox->setSelected(settings["video"]["fullscreen"].Bool() && !settings["video"]["realFullscreen"].Bool()); + + std::shared_ptr fullscreenExclusiveCheckbox = widget("fullscreenExclusiveCheckbox"); + if (fullscreenExclusiveCheckbox) + fullscreenExclusiveCheckbox->setSelected(settings["video"]["fullscreen"].Bool() && settings["video"]["realFullscreen"].Bool()); std::shared_ptr framerateCheckbox = widget("framerateCheckbox"); framerateCheckbox->setSelected(settings["video"]["showfps"].Bool()); @@ -170,16 +176,6 @@ GeneralOptionsTab::GeneralOptionsTab() std::shared_ptr soundVolumeLabel = widget("soundValueLabel"); soundVolumeLabel->setText(std::to_string(CCS->soundh->getVolume()) + "%"); - -#ifdef VCMI_MOBILE - // On mobile platforms, VCMI always uses OS screen resolutions - // Players can control UI size via "Interface Scaling" option instead - std::shared_ptr resolutionButton = widget("resolutionButton"); - - resolutionButton->disable(); - resolutionLabel->disable(); - fullscreenCheckbox->block(true); -#endif } void GeneralOptionsTab::selectGameResolution() @@ -224,9 +220,19 @@ void GeneralOptionsTab::setGameResolution(int index) widget("resolutionLabel")->setText(resolutionToLabelString(resolution.x, resolution.y)); } -void GeneralOptionsTab::setFullscreenMode(bool on) +void GeneralOptionsTab::setFullscreenMode(bool on, bool exclusive) { + setBoolSetting("video", "realFullscreen", exclusive); setBoolSetting("video", "fullscreen", on); + + std::shared_ptr fullscreenExclusiveCheckbox = widget("fullscreenExclusiveCheckbox"); + std::shared_ptr fullscreenBorderlessCheckbox = widget("fullscreenBorderlessCheckbox"); + + if (fullscreenBorderlessCheckbox) + fullscreenBorderlessCheckbox->setSelected(on && !exclusive); + + if (fullscreenExclusiveCheckbox) + fullscreenExclusiveCheckbox->setSelected(on && exclusive); } void GeneralOptionsTab::selectGameScaling() diff --git a/client/windows/settings/GeneralOptionsTab.h b/client/windows/settings/GeneralOptionsTab.h index 907957753..b7cb75b42 100644 --- a/client/windows/settings/GeneralOptionsTab.h +++ b/client/windows/settings/GeneralOptionsTab.h @@ -21,7 +21,7 @@ private: std::vector supportedResolutions; std::vector supportedScaling; - void setFullscreenMode( bool on); + void setFullscreenMode( bool on, bool exclusive); void selectGameResolution(); void setGameResolution(int index); diff --git a/config/widgets/settings/generalOptionsTab.json b/config/widgets/settings/generalOptionsTab.json index 5a87015d8..30612b188 100644 --- a/config/widgets/settings/generalOptionsTab.json +++ b/config/widgets/settings/generalOptionsTab.json @@ -32,14 +32,20 @@ "items" : [ { "name": "resolutionLabel", - "text": "vcmi.systemOptions.resolutionButton.hover" + "text": "vcmi.systemOptions.resolutionButton.hover", + "created" : "desktop" }, { "name": "scalingLabel", "text": "vcmi.systemOptions.scalingButton.hover" }, { - "text": "vcmi.systemOptions.fullscreenButton.hover" + "text": "vcmi.systemOptions.fullscreenBorderless.hover", + "created" : "desktop" + }, + { + "text": "vcmi.systemOptions.fullscreenExclusive.hover", + "created" : "desktop" }, { "text": "vcmi.systemOptions.framerateButton.hover" @@ -59,6 +65,7 @@ "type": "buttonGear", "help": "vcmi.systemOptions.resolutionButton", "callback": "setGameResolution", + "created" : "desktop" }, { "name": "scalingButton", @@ -67,9 +74,16 @@ "callback": "setGameScaling", }, { - "name": "fullscreenCheckbox", - "help": "vcmi.systemOptions.fullscreenButton", - "callback": "fullscreenChanged" + "name": "fullscreenBorderlessCheckbox", + "help": "vcmi.systemOptions.fullscreenBorderless", + "callback": "fullscreenBorderlessChanged" + "created" : "desktop" + }, + { + "name": "fullscreenExclusiveCheckbox", + "help": "vcmi.systemOptions.fullscreenExclusive", + "callback": "fullscreenExclusiveChanged" + "created" : "desktop" }, { "name": "framerateCheckbox", From 20ec747440a86c574a81817e30716f72be609b4e Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 19 May 2023 23:19:43 +0300 Subject: [PATCH 5/6] Do not show desktop-only options on mobile systems --- client/gui/InterfaceObjectConfigurable.cpp | 20 +++++++++++++++++++ client/gui/InterfaceObjectConfigurable.h | 3 +++ client/windows/settings/GeneralOptionsTab.cpp | 7 +++++++ 3 files changed, 30 insertions(+) diff --git a/client/gui/InterfaceObjectConfigurable.cpp b/client/gui/InterfaceObjectConfigurable.cpp index 273f5fd3d..d0eaaede3 100644 --- a/client/gui/InterfaceObjectConfigurable.cpp +++ b/client/gui/InterfaceObjectConfigurable.cpp @@ -115,6 +115,11 @@ void InterfaceObjectConfigurable::build(const JsonNode &config) addWidget(item["name"].String(), buildWidget(item)); } +void InterfaceObjectConfigurable::addConditional(const std::string & name, bool active) +{ + conditionals[name] = active; +} + void InterfaceObjectConfigurable::addWidget(const std::string & namePreferred, std::shared_ptr widget) { static const std::string unnamedObjectPrefix = "__widget_"; @@ -502,6 +507,21 @@ std::shared_ptr InterfaceObjectConfigurable::buildLayout(const JsonN if (item["type"].String().empty()) item["type"].String() = customType; + if (!item["created"].isNull()) + { + std::string name = item["created"].String(); + + if (conditionals.count(name) != 0) + { + if (!conditionals.at(name)) + continue; + } + else + { + logMod->warn("Unknown condition %s in widget!", name); + } + } + auto widget = buildWidget(item); addWidget(item["name"].String(), widget); diff --git a/client/gui/InterfaceObjectConfigurable.h b/client/gui/InterfaceObjectConfigurable.h index f744336cd..790f1709c 100644 --- a/client/gui/InterfaceObjectConfigurable.h +++ b/client/gui/InterfaceObjectConfigurable.h @@ -51,6 +51,8 @@ protected: //must be called after adding callbacks void build(const JsonNode & config); + void addConditional(const std::string & name, bool active); + void addWidget(const std::string & name, std::shared_ptr widget); void addCallback(const std::string & callbackName, std::function callback); @@ -110,5 +112,6 @@ private: std::map builders; std::map> widgets; std::map> callbacks; + std::map conditionals; std::map shortcuts; }; diff --git a/client/windows/settings/GeneralOptionsTab.cpp b/client/windows/settings/GeneralOptionsTab.cpp index d34c152a3..5efd5868d 100644 --- a/client/windows/settings/GeneralOptionsTab.cpp +++ b/client/windows/settings/GeneralOptionsTab.cpp @@ -78,6 +78,13 @@ GeneralOptionsTab::GeneralOptionsTab() OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; type |= REDRAW_PARENT; + addConditional("mobile", false); + addConditional("desktop", true); +#ifdef VCMI_MOBILE + addConditional("mobile", true); + addConditional("desktop", false); +#endif + const JsonNode config(ResourceID("config/widgets/settings/generalOptionsTab.json")); addCallback("spellbookAnimationChanged", [](bool value) { From 06b6f5910728f31e567c943f859888ea671d7510 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 19 May 2023 23:54:43 +0300 Subject: [PATCH 6/6] Resolution selector will now correctly update in borderless window mode --- client/windows/settings/GeneralOptionsTab.cpp | 39 ++++++++++++++++--- client/windows/settings/GeneralOptionsTab.h | 2 + .../windows/settings/SettingsMainWindow.cpp | 10 +++++ client/windows/settings/SettingsMainWindow.h | 3 +- 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/client/windows/settings/GeneralOptionsTab.cpp b/client/windows/settings/GeneralOptionsTab.cpp index 5efd5868d..5573e0830 100644 --- a/client/windows/settings/GeneralOptionsTab.cpp +++ b/client/windows/settings/GeneralOptionsTab.cpp @@ -145,10 +145,6 @@ GeneralOptionsTab::GeneralOptionsTab() const auto & currentResolution = settings["video"]["resolution"]; - std::shared_ptr resolutionLabel = widget("resolutionLabel"); - if (resolutionLabel) - resolutionLabel->setText(resolutionToLabelString(currentResolution["width"].Integer(), currentResolution["height"].Integer())); - std::shared_ptr scalingLabel = widget("scalingLabel"); scalingLabel->setText(scalingToLabelString(currentResolution["scaling"].Integer())); @@ -183,6 +179,34 @@ GeneralOptionsTab::GeneralOptionsTab() std::shared_ptr soundVolumeLabel = widget("soundValueLabel"); soundVolumeLabel->setText(std::to_string(CCS->soundh->getVolume()) + "%"); + + updateResolutionSelector(); +} + +void GeneralOptionsTab::updateResolutionSelector() +{ + std::shared_ptr resolutionButton = widget("resolutionButton"); + std::shared_ptr resolutionLabel = widget("resolutionLabel"); + + if (settings["video"]["fullscreen"].Bool() && !settings["video"]["realFullscreen"].Bool()) + { + if (resolutionButton) + resolutionButton->disable(); + + if (resolutionLabel) + resolutionLabel->setText(resolutionToLabelString(GH.screenDimensions().x, GH.screenDimensions().y)); + } + else + { + const auto & currentResolution = settings["video"]["resolution"]; + + if (resolutionButton) + resolutionButton->enable(); + + if (resolutionLabel) + resolutionLabel->setText(resolutionToLabelString(currentResolution["width"].Integer(), currentResolution["height"].Integer())); + } + } void GeneralOptionsTab::selectGameResolution() @@ -240,14 +264,19 @@ void GeneralOptionsTab::setFullscreenMode(bool on, bool exclusive) if (fullscreenExclusiveCheckbox) fullscreenExclusiveCheckbox->setSelected(on && exclusive); + + updateResolutionSelector(); } void GeneralOptionsTab::selectGameScaling() { supportedScaling.clear(); + // generate list of all possible scaling values, with 10% step + // also add one value over maximum, so if player can use scaling up to 123.456% he will be able to select 130% + // and let screen handler clamp that value to actual maximum auto [minimalScaling, maximalScaling] = GH.screenHandler().getSupportedScalingRange(); - for (int i = 0; i <= maximalScaling; i += 10) + for (int i = 0; i <= maximalScaling + 10 - 1; i += 10) { if (i >= minimalScaling) supportedScaling.push_back(i); diff --git a/client/windows/settings/GeneralOptionsTab.h b/client/windows/settings/GeneralOptionsTab.h index b7cb75b42..2f5603248 100644 --- a/client/windows/settings/GeneralOptionsTab.h +++ b/client/windows/settings/GeneralOptionsTab.h @@ -31,4 +31,6 @@ private: public: GeneralOptionsTab(); + + void updateResolutionSelector(); }; diff --git a/client/windows/settings/SettingsMainWindow.cpp b/client/windows/settings/SettingsMainWindow.cpp index 2235bcb89..20f7a7bb3 100644 --- a/client/windows/settings/SettingsMainWindow.cpp +++ b/client/windows/settings/SettingsMainWindow.cpp @@ -156,3 +156,13 @@ void SettingsMainWindow::showAll(SDL_Surface *to) CIntObject::showAll(to); CMessage::drawBorder(color, to, pos.w+28, pos.h+29, pos.x-14, pos.y-15); } + +void SettingsMainWindow::onScreenResize() +{ + InterfaceObjectConfigurable::onScreenResize(); + + auto tab = std::dynamic_pointer_cast(tabContentArea->getItem()); + + if (tab) + tab->updateResolutionSelector(); +} diff --git a/client/windows/settings/SettingsMainWindow.h b/client/windows/settings/SettingsMainWindow.h index c0ce3ed8c..69539a67c 100644 --- a/client/windows/settings/SettingsMainWindow.h +++ b/client/windows/settings/SettingsMainWindow.h @@ -41,6 +41,7 @@ private: public: SettingsMainWindow(BattleInterface * parentBattleInterface = nullptr); - void showAll(SDL_Surface * to); + void showAll(SDL_Surface * to) override; + void onScreenResize() override; };