// MassBuilderSaveTool // Copyright (C) 2021-2024 Guillaume Jacquemin // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include #include "../Configuration/Configuration.h" #include "../FontAwesome/IconsFontAwesome5.h" #include "../FontAwesome/IconsFontAwesome5Brands.h" #include "Application.h" namespace mbst { void Application::drawMainMenu() { if(!ImGui::BeginMainMenuBar()) { return; } if(ImGui::BeginMenu("Save Tool##SaveToolMenu")) { if(ImGui::BeginMenu(ICON_FA_FOLDER_OPEN " Open game data directory")) { if(ImGui::MenuItem(ICON_FA_COG " Configuration", nullptr, false, Utility::Path::exists(conf().directories().gameConfig))) { openUri(Utility::Path::toNativeSeparators(conf().directories().gameConfig)); } if(ImGui::MenuItem(ICON_FA_SAVE " Saves", nullptr, false, Utility::Path::exists(conf().directories().gameSaves))) { openUri(Utility::Path::toNativeSeparators(conf().directories().gameSaves)); } if(ImGui::MenuItem(ICON_FA_IMAGE " Screenshots", nullptr, false, Utility::Path::exists(conf().directories().gameScreenshots))) { openUri(Utility::Path::toNativeSeparators(conf().directories().gameScreenshots)); } ImGui::EndMenu(); } if(ImGui::BeginMenu(ICON_FA_FOLDER_OPEN " Open manager directory")) { if(ImGui::MenuItem(ICON_FA_FILE_ARCHIVE " Profile backups", nullptr, false, Utility::Path::exists(conf().directories().backups))) { openUri(Utility::Path::toNativeSeparators(conf().directories().backups)); } if(ImGui::MenuItem(ICON_FA_EXCHANGE_ALT " Staging area", nullptr, false, Utility::Path::exists(conf().directories().staging))) { openUri(Utility::Path::toNativeSeparators(conf().directories().staging)); } ImGui::EndMenu(); } ImGui::Separator(); if(ImGui::BeginMenu(ICON_FA_COG " Settings")) { ImGui::BeginGroup(); drawAlignedText("Vertical sync:"); if(conf().swapInterval() == 0) { drawAlignedText("FPS cap:"); } ImGui::EndGroup(); ImGui::SameLine(); ImGui::BeginGroup(); static const char* framelimit_labels[] = { "Off", "Every VBLANK", "Every second VBLANK", "Every third VBLANK", }; ImGui::PushItemWidth(300.0f); if(ImGui::BeginCombo("##FrameLimit", framelimit_labels[conf().swapInterval()])) { for(int i = 0; i <= 3; i++) { if(ImGui::Selectable(framelimit_labels[i], conf().swapInterval() == i)) { conf().setSwapInterval(i); setSwapInterval(i); if(i == 0) { setMinimalLoopPeriod(0); } } } ImGui::EndCombo(); } if(conf().swapInterval() == 0) { static float fps_cap = conf().fpsCap(); if(ImGui::SliderFloat("##FpsCapSlider", &fps_cap, 15.0f, 301.0f, conf().fpsCap() != 301.0f ? "%.0f" : "Uncapped", ImGuiSliderFlags_AlwaysClamp)) { conf().setFpsCap(fps_cap); } } ImGui::PopItemWidth(); ImGui::EndGroup(); if(drawCheckbox("Cheat mode", conf().cheatMode())) { conf().setCheatMode(!conf().cheatMode()); } ImGui::SameLine(); ImGui::AlignTextToFramePadding(); drawHelpMarker("This gives access to save edition features that can be considered cheats.", float(windowSize().x()) * 0.4f); if(drawCheckbox("Advanced mode", conf().advancedMode())) { conf().setAdvancedMode(!conf().advancedMode()); } ImGui::SameLine(); ImGui::AlignTextToFramePadding(); drawHelpMarker("This gives access to editing values that have unknown purposes or are undocumented.", float(windowSize().x()) * 0.4f); if(drawCheckbox("Check for updates on startup", conf().checkUpdatesOnStartup())) { conf().setCheckUpdatesOnStartup(!conf().checkUpdatesOnStartup()); } ImGui::SameLine(); if(ImGui::Button(ICON_FA_SYNC_ALT " Check now")) { _queue.addToast(Toast::Type::Default, "Checking for updates..."); _updateThread = std::thread{[this]{ checkForUpdates(); }}; } if(_checker && _checkerMutex.try_lock()) { if(_checker->updateAvailable()) { drawAlignedText("Version %s is available.", Containers::String{_checker->version()}.data()); if(ImGui::Button(ICON_FA_FILE_SIGNATURE " Release notes")) { openUri("https://williamjcm.ovh/mbst"); } ImGui::SameLine(); if(ImGui::Button(ICON_FA_DOWNLOAD " Download now")) { openUri(_checker->downloadLink()); } } _checkerMutex.unlock(); } if(drawCheckbox("Skip disclaimer", conf().skipDisclaimer())) { conf().setSkipDisclaimer(!conf().skipDisclaimer()); } ImGui::EndMenu(); } ImGui::Separator(); if(ImGui::MenuItem(ICON_FA_SIGN_OUT_ALT " Quit##QuitMenuItem")) { exit(EXIT_SUCCESS); } ImGui::EndMenu(); } ImGui::BeginDisabled(conf().isRunningInWine()); if(ImGui::BeginMenu("Game##GameMenu")) { if(ImGui::MenuItem(ICON_FA_PLAY " Run demo##RunDemoMenuItem")) { openUri("steam://run/1048390"); } drawTooltip("Will not work if you have the full game."); if(ImGui::MenuItem(ICON_FA_PLAY " Run full game##RunFullGameMenuItem")) { openUri("steam://run/956680"); } ImGui::Separator(); if(ImGui::BeginMenu(ICON_FA_DISCORD " Discord communities")) { if(ImGui::MenuItem("Official server")) { openUri("https://discord.gg/sekai-project"); } if(ImGui::MenuItem("Community server")) { openUri("https://discord.gg/massbuildercommunity"); } ImGui::EndMenu(); } ImGui::EndMenu(); } ImGui::EndDisabled(); if(conf().isRunningInWine() && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) { ImGui::SetTooltip("Not available when running in Wine."); } #ifdef SAVETOOL_DEBUG_BUILD if(ImGui::BeginMenu("Debug tools")) { ImGui::MenuItem("ImGui demo window", nullptr, &_demoWindow); ImGui::MenuItem("ImGui style editor", nullptr, &_styleEditor); ImGui::MenuItem("ImGui metrics window", nullptr, &_metricsWindow); ImGui::EndMenu(); } #endif if(ImGui::BeginMenu("Help")) { if(ImGui::BeginMenu(ICON_FA_KEYBOARD " Keyboard shortcuts")) { ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text."); ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields."); ImGui::BulletText("While inputing text:\n"); ImGui::Indent(); ImGui::BulletText("CTRL+Left/Right to word jump."); ImGui::BulletText("CTRL+A or double-click to select all."); ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste."); ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo."); ImGui::BulletText("ESCAPE to revert."); ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract."); ImGui::Unindent(); ImGui::EndMenu(); } ImGui::MenuItem(ICON_FA_INFO_CIRCLE " About", nullptr, &_aboutPopup); ImGui::EndMenu(); } if(_gameCheckTimerId != 0) { if(ImGui::BeginTable("##MainMenuLayout", 2)) { ImGui::TableSetupColumn("##Dummy", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("##GameState", ImGuiTableColumnFlags_WidthFixed); ImGui::TableNextRow(); ImGui::TableSetColumnIndex(1); drawGameState(); ImGui::EndTable(); } } ImGui::EndMainMenuBar(); } }