#include "StarGraphicsMenu.hpp" #include "StarRoot.hpp" #include "StarAssets.hpp" #include "StarConfiguration.hpp" #include "StarGuiReader.hpp" #include "StarListWidget.hpp" #include "StarLabelWidget.hpp" #include "StarSliderBar.hpp" #include "StarButtonWidget.hpp" #include "StarOrderedSet.hpp" #include "StarJsonExtra.hpp" namespace Star { GraphicsMenu::GraphicsMenu() { GuiReader reader; reader.registerCallback("cancel", [&](Widget*) { dismiss(); }); reader.registerCallback("accept", [&](Widget*) { apply(); applyWindowSettings(); }); reader.registerCallback("resSlider", [=](Widget*) { Vec2U res = m_resList[fetchChild("resSlider")->val()]; m_localChanges.set("fullscreenResolution", jsonFromVec2U(res)); syncGui(); }); reader.registerCallback("interfaceScaleSlider", [=](Widget*) { auto interfaceScaleSlider = fetchChild("interfaceScaleSlider"); m_localChanges.set("interfaceScale", (uint64_t)m_interfaceScaleList[interfaceScaleSlider->val()]); syncGui(); }); reader.registerCallback("zoomSlider", [=](Widget*) { auto zoomSlider = fetchChild("zoomSlider"); m_localChanges.set("zoomLevel", m_zoomList[zoomSlider->val()]); Root::singleton().configuration()->set("zoomLevel", m_zoomList[zoomSlider->val()]); syncGui(); }); reader.registerCallback("cameraSpeedSlider", [=](Widget*) { auto cameraSpeedSlider = fetchChild("cameraSpeedSlider"); m_localChanges.set("cameraSpeedFactor", m_cameraSpeedList[cameraSpeedSlider->val()]); Root::singleton().configuration()->set("cameraSpeedFactor", m_cameraSpeedList[cameraSpeedSlider->val()]); syncGui(); }); reader.registerCallback("speechBubbleCheckbox", [=](Widget*) { auto button = fetchChild("speechBubbleCheckbox"); m_localChanges.set("speechBubbles", button->isChecked()); Root::singleton().configuration()->set("speechBubbles", button->isChecked()); syncGui(); }); reader.registerCallback("interactiveHighlightCheckbox", [=](Widget*) { auto button = fetchChild("interactiveHighlightCheckbox"); m_localChanges.set("interactiveHighlight", button->isChecked()); Root::singleton().configuration()->set("interactiveHighlight", button->isChecked()); syncGui(); }); reader.registerCallback("fullscreenCheckbox", [=](Widget*) { bool checked = fetchChild("fullscreenCheckbox")->isChecked(); m_localChanges.set("fullscreen", checked); if (checked) m_localChanges.set("borderless", !checked); syncGui(); }); reader.registerCallback("borderlessCheckbox", [=](Widget*) { bool checked = fetchChild("borderlessCheckbox")->isChecked(); m_localChanges.set("borderless", checked); if (checked) m_localChanges.set("fullscreen", !checked); syncGui(); }); reader.registerCallback("textureLimitCheckbox", [=](Widget*) { m_localChanges.set("limitTextureAtlasSize", fetchChild("textureLimitCheckbox")->isChecked()); syncGui(); }); reader.registerCallback("multiTextureCheckbox", [=](Widget*) { m_localChanges.set("useMultiTexturing", fetchChild("multiTextureCheckbox")->isChecked()); syncGui(); }); reader.registerCallback("antiAliasingCheckbox", [=](Widget*) { bool checked = fetchChild("antiAliasingCheckbox")->isChecked(); m_localChanges.set("antiAliasing", checked); Root::singleton().configuration()->set("antiAliasing", checked); syncGui(); }); reader.registerCallback("hardwareCursorCheckbox", [=](Widget*) { bool checked = fetchChild("hardwareCursorCheckbox")->isChecked(); m_localChanges.set("hardwareCursor", checked); Root::singleton().configuration()->set("hardwareCursor", checked); GuiContext::singleton().applicationController()->setCursorHardware(checked); }); reader.registerCallback("monochromeCheckbox", [=](Widget*) { bool checked = fetchChild("monochromeCheckbox")->isChecked(); m_localChanges.set("monochromeLighting", checked); Root::singleton().configuration()->set("monochromeLighting", checked); syncGui(); }); reader.registerCallback("objectLightingCheckbox", [=](Widget*) { bool checked = fetchChild("objectLightingCheckbox")->isChecked(); m_localChanges.set("newObjectLighting", checked); Root::singleton().configuration()->set("newObjectLighting", checked); syncGui(); }); auto assets = Root::singleton().assets(); Json paneLayout = assets->json("/interface/windowconfig/graphicsmenu.config:paneLayout"); m_interfaceScaleList = jsonToIntList(assets->json("/interface/windowconfig/graphicsmenu.config:interfaceScaleList")); m_resList = jsonToVec2UList(assets->json("/interface/windowconfig/graphicsmenu.config:resolutionList")); m_zoomList = jsonToFloatList(assets->json("/interface/windowconfig/graphicsmenu.config:zoomList")); m_cameraSpeedList = jsonToFloatList(assets->json("/interface/windowconfig/graphicsmenu.config:cameraSpeedList")); reader.construct(paneLayout, this); fetchChild("interfaceScaleSlider")->setRange(0, m_interfaceScaleList.size() - 1, 1); fetchChild("resSlider")->setRange(0, m_resList.size() - 1, 1); fetchChild("zoomSlider")->setRange(0, m_zoomList.size() - 1, 1); fetchChild("cameraSpeedSlider")->setRange(0, m_cameraSpeedList.size() - 1, 1); initConfig(); syncGui(); } void GraphicsMenu::show() { Pane::show(); initConfig(); syncGui(); } void GraphicsMenu::dismissed() { Pane::dismissed(); } void GraphicsMenu::toggleFullscreen() { bool fullscreen = m_localChanges.get("fullscreen").toBool(); bool borderless = m_localChanges.get("borderless").toBool(); m_localChanges.set("fullscreen", !(fullscreen || borderless)); Root::singleton().configuration()->set("fullscreen", !(fullscreen || borderless)); m_localChanges.set("borderless", false); Root::singleton().configuration()->set("borderless", false); applyWindowSettings(); syncGui(); } StringList const GraphicsMenu::ConfigKeys = { "fullscreenResolution", "interfaceScale", "zoomLevel", "cameraSpeedFactor", "speechBubbles", "interactiveHighlight", "fullscreen", "borderless", "limitTextureAtlasSize", "useMultiTexturing", "antiAliasing", "hardwareCursor", "monochromeLighting", "newObjectLighting" }; void GraphicsMenu::initConfig() { auto configuration = Root::singleton().configuration(); for (auto key : ConfigKeys) { m_localChanges.set(key, configuration->get(key)); } } void GraphicsMenu::syncGui() { Vec2U res = jsonToVec2U(m_localChanges.get("fullscreenResolution")); auto resSlider = fetchChild("resSlider"); auto resIt = std::lower_bound(m_resList.begin(), m_resList.end(), res, [&](Vec2U const& a, Vec2U const& b) { return a[0] * a[1] < b[0] * b[1]; // sort by number of pixels }); if (resIt != m_resList.end()) { size_t resIndex = resIt - m_resList.begin(); resIndex = std::min(resIndex, m_resList.size() - 1); resSlider->setVal(resIndex, false); } else { resSlider->setVal(m_resList.size() - 1); } fetchChild("resValueLabel")->setText(strf("{}x{}", res[0], res[1])); auto interfaceScaleSlider = fetchChild("interfaceScaleSlider"); auto interfaceScale = m_localChanges.get("interfaceScale").optUInt().value(); auto interfaceScaleIt = std::lower_bound(m_interfaceScaleList.begin(), m_interfaceScaleList.end(), interfaceScale); if (interfaceScaleIt != m_interfaceScaleList.end()) { size_t scaleIndex = interfaceScaleIt - m_interfaceScaleList.begin(); interfaceScaleSlider->setVal(std::min(scaleIndex, m_interfaceScaleList.size() - 1), false); } else { interfaceScaleSlider->setVal(m_interfaceScaleList.size() - 1); } fetchChild("interfaceScaleValueLabel")->setText(interfaceScale ? toString(interfaceScale) : "AUTO"); auto zoomSlider = fetchChild("zoomSlider"); auto zoomLevel = m_localChanges.get("zoomLevel").toFloat(); auto zoomIt = std::lower_bound(m_zoomList.begin(), m_zoomList.end(), zoomLevel); if (zoomIt != m_zoomList.end()) { size_t zoomIndex = zoomIt - m_zoomList.begin(); zoomSlider->setVal(std::min(zoomIndex, m_zoomList.size() - 1), false); } else { zoomSlider->setVal(m_zoomList.size() - 1); } fetchChild("zoomValueLabel")->setText(strf("{}x", zoomLevel)); auto cameraSpeedSlider = fetchChild("cameraSpeedSlider"); auto cameraSpeedFactor = m_localChanges.get("cameraSpeedFactor").toFloat(); auto speedIt = std::lower_bound(m_cameraSpeedList.begin(), m_cameraSpeedList.end(), cameraSpeedFactor); if (speedIt != m_cameraSpeedList.end()) { size_t speedIndex = speedIt - m_cameraSpeedList.begin(); cameraSpeedSlider->setVal(std::min(speedIndex, m_cameraSpeedList.size() - 1), false); } else { cameraSpeedSlider->setVal(m_cameraSpeedList.size() - 1); } fetchChild("cameraSpeedValueLabel")->setText(strf("{}x", cameraSpeedFactor)); fetchChild("speechBubbleCheckbox")->setChecked(m_localChanges.get("speechBubbles").toBool()); fetchChild("interactiveHighlightCheckbox")->setChecked(m_localChanges.get("interactiveHighlight").toBool()); fetchChild("fullscreenCheckbox")->setChecked(m_localChanges.get("fullscreen").toBool()); fetchChild("borderlessCheckbox")->setChecked(m_localChanges.get("borderless").toBool()); fetchChild("textureLimitCheckbox")->setChecked(m_localChanges.get("limitTextureAtlasSize").toBool()); fetchChild("multiTextureCheckbox")->setChecked(m_localChanges.get("useMultiTexturing").optBool().value(true)); fetchChild("antiAliasingCheckbox")->setChecked(m_localChanges.get("antiAliasing").toBool()); fetchChild("monochromeCheckbox")->setChecked(m_localChanges.get("monochromeLighting").toBool()); fetchChild("objectLightingCheckbox")->setChecked(m_localChanges.get("newObjectLighting").optBool().value(true)); fetchChild("hardwareCursorCheckbox")->setChecked(m_localChanges.get("hardwareCursor").toBool()); } void GraphicsMenu::apply() { auto configuration = Root::singleton().configuration(); for (auto p : m_localChanges) { configuration->set(p.first, p.second); } } void GraphicsMenu::applyWindowSettings() { auto configuration = Root::singleton().configuration(); auto appController = GuiContext::singleton().applicationController(); if (configuration->get("fullscreen").toBool()) appController->setFullscreenWindow(jsonToVec2U(configuration->get("fullscreenResolution"))); else if (configuration->get("borderless").toBool()) appController->setBorderlessWindow(); else if (configuration->get("maximized").toBool()) appController->setMaximizedWindow(); else appController->setNormalWindow(jsonToVec2U(configuration->get("windowedResolution"))); } }