From 0fdfd8bdcb70e56d52f49167b515307f5e052c68 Mon Sep 17 00:00:00 2001 From: Dydzio Date: Sun, 29 Jan 2023 16:49:47 +0100 Subject: [PATCH] Configurable interface for game settings, change sound/music sliders --- client/windows/GUIClasses.cpp | 200 +++++++++--------- client/windows/GUIClasses.h | 43 +--- config/widgets/optionsMenu.json | 348 ++++++++++++++++++++++++++++++++ 3 files changed, 449 insertions(+), 142 deletions(-) create mode 100644 config/widgets/optionsMenu.json diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 2b9521c68..cf83c8195 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -443,119 +443,99 @@ static std::string resolutionToString(int w, int h) } CSystemOptionsWindow::CSystemOptionsWindow() - : CWindowObject(PLAYER_COLORED, "SysOpBck"), + : InterfaceObjectConfigurable(), onFullscreenChanged(settings.listen["video"]["fullscreen"]) { - OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - title = std::make_shared(242, 32, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[568]); + OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; - //left window section - leftGroup = std::make_shared(FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW); - leftGroup->add(122, 64, CGI->generaltexth->allTexts[569]); - leftGroup->add(122, 130, CGI->generaltexth->allTexts[570]); - leftGroup->add(122, 196, CGI->generaltexth->allTexts[571]); - leftGroup->add(122, 262, CGI->generaltexth->translate("vcmi.systemOptions.resolutionButton.hover")); - leftGroup->add(122, 347, CGI->generaltexth->allTexts[394]); - leftGroup->add(122, 412, CGI->generaltexth->allTexts[395]); + const JsonNode config(ResourceID("config/widgets/optionsMenu.json")); + addCallback("loadGame", [this](int) { loadGameButtonCallback(); }); + addCallback("saveGame", [this](int) { saveGameButtonCallback(); }); + addCallback("restartGame", [this](int) { restartGameButtonCallback(); }); + addCallback("quitGame", [this](int) { quitGameButtonCallback(); }); + addCallback("returnToMainMenu", [this](int) { mainMenuButtonCallback(); }); + addCallback("closeWindow", [this](int) { backButtonCallback(); }); + addCallback("playerHeroSpeedChanged", std::bind(&setIntSetting, "adventure", "heroSpeed", _1)); + addCallback("enemyHeroSpeedChanged", std::bind(&setIntSetting, "adventure", "enemySpeed", _1)); + addCallback("mapScrollSpeedChanged", std::bind(&setIntSetting, "adventure", "scrollSpeed", _1)); + addCallback("heroReminderChanged", std::bind(&setBoolSetting, "adventure", "heroReminder", _1)); + addCallback("quickCombatChanged", std::bind(&setBoolSetting, "adventure", "quickCombat", _1)); + addCallback("spellbookAnimationChanged", std::bind(&setBoolSetting, "video", "spellbookAnimation", _1)); + addCallback("fullscreenChanged", std::bind(&setBoolSetting, "video", "fullscreen", _1)); + addCallback("setGameResolution", std::bind(&CSystemOptionsWindow::selectGameResolution, this)); + addCallback("setMusic", [this](int value) { setIntSetting("general", "music", value); widget("musicSlider")->redraw(); }); + addCallback("setVolume", [this](int value) { setIntSetting("general", "sound", value); widget("soundVolumeSlider")->redraw(); }); + build(config); - //right section - rightGroup = std::make_shared(FONT_MEDIUM, ETextAlignment::TOPLEFT, Colors::WHITE); - rightGroup->add(282, 57, CGI->generaltexth->allTexts[572]); - rightGroup->add(282, 89, CGI->generaltexth->allTexts[573]); - rightGroup->add(282, 121, CGI->generaltexth->allTexts[574]); - rightGroup->add(282, 153, CGI->generaltexth->allTexts[577]); - rightGroup->add(282, 217, CGI->generaltexth->translate("vcmi.systemOptions.fullscreenButton.hover")); + std::shared_ptr background = widget("background"); + pos.w = background->pos.w; + pos.h = background->pos.h; + pos = center(); - //setting up buttons - load = std::make_shared(Point(246, 298), "SOLOAD.DEF", CGI->generaltexth->zelp[321], [&](){ bloadf(); }, SDLK_l); - load->setImageOrder(1, 0, 2, 3); + std::shared_ptr resolutionLabel = widget("resolutionLabel"); + const auto & currentResolution = settings["video"]["screenRes"]; + resolutionLabel->setText(resolutionToString(currentResolution["width"].Integer(), currentResolution["height"].Integer())); - save = std::make_shared(Point(357, 298), "SOSAVE.DEF", CGI->generaltexth->zelp[322], [&](){ bsavef(); }, SDLK_s); - save->setImageOrder(1, 0, 2, 3); - restart = std::make_shared(Point(246, 357), "SORSTRT", CGI->generaltexth->zelp[323], [&](){ brestartf(); }, SDLK_r); - restart->setImageOrder(1, 0, 2, 3); + std::shared_ptr playerHeroSpeedToggle = widget("heroMovementSpeedPicker"); + playerHeroSpeedToggle->setSelected((int)settings["adventure"]["heroSpeed"].Float()); + + std::shared_ptr enemyHeroSpeedToggle = widget("enemyMovementSpeedPicker"); + enemyHeroSpeedToggle->setSelected((int)settings["adventure"]["enemySpeed"].Float()); + + std::shared_ptr mapScrollSpeedToggle = widget("mapScrollSpeedPicker"); + mapScrollSpeedToggle->setSelected((int)settings["adventure"]["scrollSpeed"].Float()); + + + std::shared_ptr heroReminderCheckbox = widget("heroReminderCheckbox"); + heroReminderCheckbox->setSelected((bool)settings["adventure"]["heroReminder"].Bool()); + + std::shared_ptr quickCombatCheckbox = widget("quickCombatCheckbox"); + quickCombatCheckbox->setSelected((bool)settings["adventure"]["quickCombat"].Bool()); + + std::shared_ptr spellbookAnimationCheckbox = widget("spellbookAnimationCheckbox"); + spellbookAnimationCheckbox->setSelected((bool)settings["video"]["spellbookAnimation"].Bool()); + + std::shared_ptr fullscreenCheckbox = widget("fullscreenCheckbox"); + fullscreenCheckbox->setSelected((bool)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 musicSlider = widget("musicSlider"); + musicSlider->moveTo(CCS->musich->getVolume()); + + std::shared_ptr volumeSlider = widget("soundVolumeSlider"); + volumeSlider->moveTo(CCS->soundh->getVolume()); + + + std::shared_ptr loadButton = widget("loadButton"); + assert(loadButton); + + std::shared_ptr saveButton = widget("saveButton"); + assert(saveButton); + + std::shared_ptr restartButton = widget("restartButton"); + assert(restartButton); if(CSH->isGuest()) { - load->block(true); - save->block(true); - restart->block(true); + loadButton->block(true); + saveButton->block(true); + restartButton->block(true); } - - mainMenu = std::make_shared(Point(357, 357), "SOMAIN.DEF", CGI->generaltexth->zelp[320], [&](){ bmainmenuf(); }, SDLK_m); - mainMenu->setImageOrder(1, 0, 2, 3); - - quitGame = std::make_shared(Point(246, 415), "soquit.def", CGI->generaltexth->zelp[324], [&](){ bquitf(); }, SDLK_q); - quitGame->setImageOrder(1, 0, 2, 3); - - backToMap = std::make_shared( Point(357, 415), "soretrn.def", CGI->generaltexth->zelp[325], [&](){ breturnf(); }, SDLK_RETURN); - backToMap->setImageOrder(1, 0, 2, 3); - backToMap->assignedKeys.insert(SDLK_ESCAPE); - - heroMoveSpeed = std::make_shared(0); - enemyMoveSpeed = std::make_shared(0); - mapScrollSpeed = std::make_shared(0); - - heroMoveSpeed->addToggle(1, std::make_shared(Point( 28, 77), "sysopb1.def", CGI->generaltexth->zelp[349])); - heroMoveSpeed->addToggle(2, std::make_shared(Point( 76, 77), "sysopb2.def", CGI->generaltexth->zelp[350])); - heroMoveSpeed->addToggle(4, std::make_shared(Point(124, 77), "sysopb3.def", CGI->generaltexth->zelp[351])); - heroMoveSpeed->addToggle(8, std::make_shared(Point(172, 77), "sysopb4.def", CGI->generaltexth->zelp[352])); - heroMoveSpeed->setSelected((int)settings["adventure"]["heroSpeed"].Float()); - heroMoveSpeed->addCallback(std::bind(&setIntSetting, "adventure", "heroSpeed", _1)); - - enemyMoveSpeed->addToggle(2, std::make_shared(Point( 28, 144), "sysopb5.def", CGI->generaltexth->zelp[353])); - enemyMoveSpeed->addToggle(4, std::make_shared(Point( 76, 144), "sysopb6.def", CGI->generaltexth->zelp[354])); - enemyMoveSpeed->addToggle(8, std::make_shared(Point(124, 144), "sysopb7.def", CGI->generaltexth->zelp[355])); - enemyMoveSpeed->addToggle(0, std::make_shared(Point(172, 144), "sysopb8.def", CGI->generaltexth->zelp[356])); - enemyMoveSpeed->setSelected((int)settings["adventure"]["enemySpeed"].Float()); - enemyMoveSpeed->addCallback(std::bind(&setIntSetting, "adventure", "enemySpeed", _1)); - - mapScrollSpeed->addToggle(1, std::make_shared(Point( 28, 210), "sysopb9.def", CGI->generaltexth->zelp[357])); - mapScrollSpeed->addToggle(2, std::make_shared(Point( 92, 210), "sysob10.def", CGI->generaltexth->zelp[358])); - mapScrollSpeed->addToggle(4, std::make_shared(Point(156, 210), "sysob11.def", CGI->generaltexth->zelp[359])); - mapScrollSpeed->setSelected((int)settings["adventure"]["scrollSpeed"].Float()); - mapScrollSpeed->addCallback(std::bind(&setIntSetting, "adventure", "scrollSpeed", _1)); - - musicVolume = std::make_shared(Point(29, 359), "syslb.def", CCS->musich->getVolume(), CVolumeSlider::MUSIC); - musicVolume->addCallback(std::bind(&setIntSetting, "general", "music", _1)); - - effectsVolume = std::make_shared(Point(29, 425), "syslb.def", CCS->soundh->getVolume(), CVolumeSlider::SOUND); - effectsVolume->addCallback(std::bind(&setIntSetting, "general", "sound", _1)); - - showReminder = std::make_shared(Point(246, 87), "sysopchk.def", CGI->generaltexth->zelp[361], [&](bool value) - { - setBoolSetting("adventure", "heroReminder", value); - }); - showReminder->setSelected(settings["adventure"]["heroReminder"].Bool()); - - quickCombat = std::make_shared(Point(246, 87+32), "sysopchk.def", CGI->generaltexth->zelp[362], [&](bool value) - { - setBoolSetting("adventure", "quickCombat", value); - }); - quickCombat->setSelected(settings["adventure"]["quickCombat"].Bool()); - - spellbookAnim = std::make_shared(Point(246, 87+64), "sysopchk.def", CGI->generaltexth->zelp[364], [&](bool value) - { - setBoolSetting("video", "spellbookAnimation", value); - }); - spellbookAnim->setSelected(settings["video"]["spellbookAnimation"].Bool()); - - fullscreen = std::make_shared(Point(246, 215), "sysopchk.def", CButton::tooltipLocalized("vcmi.systemOptions.fullscreenButton"), [&](bool value) - { - setBoolSetting("video", "fullscreen", value); - }); - fullscreen->setSelected(settings["video"]["fullscreen"].Bool()); - - onFullscreenChanged([&](const JsonNode &newState){ fullscreen->setSelected(newState.Bool());}); - - gameResButton = std::make_shared(Point(28, 275),"buttons/resolution", CButton::tooltipLocalized("vcmi.systemOptions.resolutionButton"), std::bind(&CSystemOptionsWindow::selectGameRes, this), SDLK_g); - - const auto & screenRes = settings["video"]["screenRes"]; - gameResLabel = std::make_shared(170, 292, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW, resolutionToString(screenRes["width"].Integer(), screenRes["height"].Integer())); } -void CSystemOptionsWindow::selectGameRes() +void CSystemOptionsWindow::close() +{ + if(GH.topInt().get() != this) + logGlobal->error("Only top interface must be closed"); + GH.popInts(1); +} + +void CSystemOptionsWindow::selectGameResolution() { std::vector items; @@ -575,7 +555,7 @@ void CSystemOptionsWindow::selectGameRes() #endif auto resolutionStr = resolutionToString(resolution.first, resolution.second); - if(gameResLabel->getText() == resolutionStr) + if(widget("resolutionLabel")->getText() == resolutionStr) currentResolutionIndex = i; items.push_back(std::move(resolutionStr)); ++i; @@ -584,11 +564,11 @@ void CSystemOptionsWindow::selectGameRes() GH.pushIntT(items, nullptr, CGI->generaltexth->translate("vcmi.systemOptions.resolutionMenu.hover"), CGI->generaltexth->translate("vcmi.systemOptions.resolutionMenu.help"), - std::bind(&CSystemOptionsWindow::setGameRes, this, _1), + std::bind(&CSystemOptionsWindow::setGameResolution, this, _1), currentResolutionIndex); } -void CSystemOptionsWindow::setGameRes(int index) +void CSystemOptionsWindow::setGameResolution(int index) { auto iter = conf.guiOptions.begin(); std::advance(iter, index); @@ -604,37 +584,37 @@ void CSystemOptionsWindow::setGameRes(int index) resText += boost::lexical_cast(iter->first.first); resText += "x"; resText += boost::lexical_cast(iter->first.second); - gameResLabel->setText(resText); + widget("resolutionLabel")->setText(resText); } -void CSystemOptionsWindow::bquitf() +void CSystemOptionsWindow::quitGameButtonCallback() { LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[578], [this](){ closeAndPushEvent(SDL_USEREVENT, EUserEvent::FORCE_QUIT); }, 0); } -void CSystemOptionsWindow::breturnf() +void CSystemOptionsWindow::backButtonCallback() { close(); } -void CSystemOptionsWindow::bmainmenuf() +void CSystemOptionsWindow::mainMenuButtonCallback() { LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[578], [this](){ closeAndPushEvent(SDL_USEREVENT, EUserEvent::RETURN_TO_MAIN_MENU); }, 0); } -void CSystemOptionsWindow::bloadf() +void CSystemOptionsWindow::loadGameButtonCallback() { close(); LOCPLINT->proposeLoadingGame(); } -void CSystemOptionsWindow::bsavef() +void CSystemOptionsWindow::saveGameButtonCallback() { close(); GH.pushIntT(); } -void CSystemOptionsWindow::brestartf() +void CSystemOptionsWindow::restartGameButtonCallback() { LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[67], [this](){ closeAndPushEvent(SDL_USEREVENT, EUserEvent::RESTART_GAME); }, 0); } diff --git a/client/windows/GUIClasses.h b/client/windows/GUIClasses.h index 8e2efad6b..d4f25694a 100644 --- a/client/windows/GUIClasses.h +++ b/client/windows/GUIClasses.h @@ -17,6 +17,7 @@ #include "../widgets/CArtifactHolder.h" #include "../widgets/CGarrisonInt.h" #include "../widgets/Images.h" +#include "gui/InterfaceObjectConfigurable.h" VCMI_LIB_NAMESPACE_BEGIN @@ -196,44 +197,22 @@ public: void keyPressed (const SDL_KeyboardEvent & key) override; }; -class CSystemOptionsWindow : public CWindowObject +class CSystemOptionsWindow : public InterfaceObjectConfigurable { private: - std::shared_ptr title; - std::shared_ptr leftGroup; - std::shared_ptr rightGroup; - std::shared_ptr load; - std::shared_ptr save; - std::shared_ptr restart; - std::shared_ptr mainMenu; - std::shared_ptr quitGame; - std::shared_ptr backToMap; //load and restart are not used yet - std::shared_ptr heroMoveSpeed; - std::shared_ptr enemyMoveSpeed; - std::shared_ptr mapScrollSpeed; - std::shared_ptr musicVolume; - std::shared_ptr effectsVolume; - - std::shared_ptr showReminder; - std::shared_ptr quickCombat; - std::shared_ptr spellbookAnim; - std::shared_ptr fullscreen; - - std::shared_ptr gameResButton; - std::shared_ptr gameResLabel; - SettingsListener onFullscreenChanged; //functions bound to buttons - void bloadf(); //load game - void bsavef(); //save game - void bquitf(); //quit game - void breturnf(); //return to game - void brestartf(); //restart game - void bmainmenuf(); //return to main menu + void loadGameButtonCallback(); //load game + void saveGameButtonCallback(); //save game + void quitGameButtonCallback(); //quit game + void backButtonCallback(); //return to game + void restartGameButtonCallback(); //restart game + void mainMenuButtonCallback(); //return to main menu - void selectGameRes(); - void setGameRes(int index); + void close(); //TODO: copypaste of WindowBase::close(), consider changing Windowbase to IWindowbase with default close() implementation and changing WindowBase inheritance to CIntObject + IWindowBase + void selectGameResolution(); + void setGameResolution(int index); void closeAndPushEvent(int eventType, int code = 0); public: diff --git a/config/widgets/optionsMenu.json b/config/widgets/optionsMenu.json new file mode 100644 index 000000000..6334a0e33 --- /dev/null +++ b/config/widgets/optionsMenu.json @@ -0,0 +1,348 @@ +{ + "items": + [ + { + "name": "background", + "type": "picture", + "playerColored" : true, + "position": {"x": 0, "y": 0}, + "image": "SysOpBck" + }, + + { + "name": "title", + "type": "label", + "font": "big", + "alignment": "center", + "color": "yellow", + "text": "core.genrltxt.568", + "position": {"x": 242, "y": 32} + }, + + { + "name": "leftSettingsLabels", + "type": "labelGroup", + "font": "medium", + "alignment": "center", + "color": "yellow", + "items": + [ + { + "position": {"x": 122, "y": 64}, + "text": "core.genrltxt.569" + }, + { + "position": {"x": 122, "y": 130}, + "text": "core.genrltxt.570" + }, + { + "position": {"x": 122, "y": 196}, + "text": "core.genrltxt.571" + }, + { + "position": {"x": 122, "y": 262}, + "text": "vcmi.systemOptions.resolutionButton.hover" + }, + { + "position": {"x": 122, "y": 347}, + "text": "core.genrltxt.394" + }, + { + "position": {"x": 122, "y": 412}, + "text": "core.genrltxt.395" + } + ] + }, + + { + "name": "rightSideCheckboxesLabels", + "type": "labelGroup", + "font": "medium", + "alignment": "left", + "color": "white", + "items": + [ + { + "position": {"x": 282, "y": 57}, + "text": "core.genrltxt.572" + }, + { + "position": {"x": 282, "y": 89}, + "text": "core.genrltxt.573" + }, + { + "position": {"x": 282, "y": 121}, + "text": "core.genrltxt.574" + }, + { + "position": {"x": 282, "y": 153}, + "text": "core.genrltxt.577" + }, + { + "position": {"x": 282, "y": 217}, + "text": "vcmi.systemOptions.fullscreenButton.hover" + } + ] + }, + + { + "name": "loadButton", + "type": "button", + "position": {"x": 246, "y": 298}, + "image": "SOLOAD.DEF", + "imageOrder": [1, 0, 2, 3], + "help": "core.help.321", + "callback": "loadGame", + "hotkey": "l" + }, + + { + "name": "saveButton", + "type": "button", + "position": {"x": 357, "y": 298}, + "image": "SOSAVE.DEF", + "imageOrder": [1, 0, 2, 3], + "help": "core.help.322", + "callback": "saveGame", + "hotkey": "s" + }, + + { + "name": "restartButton", + "type": "button", + "position": {"x": 246, "y": 357}, + "image": "SORSTRT.DEF", + "imageOrder": [1, 0, 2, 3], + "help": "core.help.323", + "callback": "restartGame", + "hotkey": "r" + }, + + { + "name": "mainMenuButton", + "type": "button", + "position": {"x": 357, "y": 357}, + "image": "SOMAIN.DEF", + "imageOrder": [1, 0, 2, 3], + "help": "core.help.320", + "callback": "returnToMainMenu", + "hotkey": "m" + }, + + { + "name": "quitButton", + "type": "button", + "position": {"x": 246, "y": 415}, + "image": "soquit.def", + "imageOrder": [1, 0, 2, 3], + "help": "core.help.324", + "callback": "quitGame", + "hotkey": "q" + }, + + { + "name": "closeSettingsButton", + "type": "button", + "position": {"x": 357, "y": 415}, + "image": "soretrn.def", + "imageOrder": [1, 0, 2, 3], + "help": "core.help.325", + "callback": "closeWindow", + "hotkey": ["esc", "backspace"] + }, + + { + "name": "heroMovementSpeedPicker", + "type": "toggleGroup", + "position": {"x": 28, "y": 77}, + "items": + [ + { + "index": 1, + "type": "toggleButton", + "image": "sysopb1", + "help": "core.help.349", + "position": {"x": 0, "y": 0} + }, + + { + "index": 2, + "type": "toggleButton", + "image": "sysopb2", + "help": "core.help.350", + "position": {"x": 48, "y": 0} + }, + + { + "index": 4, + "type": "toggleButton", + "image": "sysopb3", + "help": "core.help.351", + "position": {"x": 96, "y": 0} + }, + + { + "index": 8, + "type": "toggleButton", + "image": "sysopb4", + "help": "core.help.352", + "position": {"x": 144, "y": 0} + } + ], + "callback": "playerHeroSpeedChanged" + }, + + { + "name": "enemyMovementSpeedPicker", + "type": "toggleGroup", + "position": {"x": 28, "y": 144}, + "items": + [ + { + "index": 2, + "type": "toggleButton", + "image": "sysopb5", + "help": "core.help.353", + "position": {"x": 0, "y": 0} + }, + + { + "index": 4, + "type": "toggleButton", + "image": "sysopb6", + "help": "core.help.354", + "position": {"x": 48, "y": 0} + }, + + { + "index": 8, + "type": "toggleButton", + "image": "sysopb7", + "help": "core.help.355", + "position": {"x": 96, "y": 0} + }, + + { + "index": 0, + "type": "toggleButton", + "image": "sysopb8", + "help": "core.help.356", + "position": {"x": 144, "y": 0} + } + ], + "callback": "enemyHeroSpeedChanged" + }, + + { + "name": "mapScrollSpeedPicker", + "type": "toggleGroup", + "position": {"x": 28, "y": 210}, + "items": + [ + { + "index": 1, + "type": "toggleButton", + "image": "sysopb9", + "help": "core.help.357", + "position": {"x": 0, "y": 0} + }, + + { + "index": 2, + "type": "toggleButton", + "image": "sysob10", + "help": "core.help.358", + "position": {"x": 64, "y": 0} + }, + + { + "index": 4, + "type": "toggleButton", + "image": "sysob11", + "help": "core.help.359", + "position": {"x": 128, "y": 0} + } + ], + "callback": "mapScrollSpeedChanged" + }, + + { + "name": "heroReminderCheckbox", + "type": "toggleButton", + "image": "sysopchk.def", + "help": "core.help.361", + "position": {"x": 246, "y": 87}, + "callback": "heroReminderChanged" + }, + + { + "name": "quickCombatCheckbox", + "type": "toggleButton", + "image": "sysopchk.def", + "help": "core.help.362", + "position": {"x": 246, "y": 119}, + "callback": "quickCombatChanged" + }, + + { + "name": "spellbookAnimationCheckbox", + "type": "toggleButton", + "image": "sysopchk.def", + "help": "core.help.364", + "position": {"x": 246, "y": 151}, + "callback": "spellbookAnimationChanged" + }, + + { + "name": "fullscreenCheckbox", + "type": "toggleButton", + "image": "sysopchk.def", + "help": "vcmi.systemOptions.fullscreenButton", + "position": {"x": 246, "y": 215}, + "callback": "fullscreenChanged" + }, + + { + "name": "resolutionButton", + "type": "button", + "position": {"x": 28, "y": 275}, + "image": "buttons/resolution", + "help": "vcmi.systemOptions.resolutionButton", + "callback": "setGameResolution", + "hotkey": "g" + }, + + { + "name": "resolutionLabel", + "type": "label", + "font": "medium", + "alignment": "center", + "color": "yellow", + "position": {"x": 170, "y": 292} + }, + + { + "name": "musicSlider", + "type": "slider", + "position": {"x": 29, "y": 359}, + "size": 190, + "style": "brown", + "orientation": "horizontal", + "itemsVisible": 0, + "itemsTotal": 100, + "callback": "setMusic" + }, + + { + "name": "soundVolumeSlider", + "type": "slider", + "position": {"x": 29, "y": 425}, + "size": 190, + "style": "brown", + "orientation": "horizontal", + "itemsVisible": 0, + "itemsTotal": 100, + "callback": "setVolume" + } + ] +}