diff --git a/Src/OSD/SDL/Gui.cpp b/Src/OSD/SDL/Gui.cpp index a584b428..33c19237 100644 --- a/Src/OSD/SDL/Gui.cpp +++ b/Src/OSD/SDL/Gui.cpp @@ -52,6 +52,35 @@ static Util::Config::Node NodeDiff(Util::Config::Node& config1, const Util::Conf } */ +static void PersistStartupScreenSelection(const std::string& configPath, const std::string& startupValue) +{ + Util::Config::Node diskConfig("Global"); + bool loaded = false; + + if (std::filesystem::exists(configPath)) + { + if (!Util::Config::FromINIFile(&diskConfig, configPath)) + { + loaded = true; + } + } + else + { + diskConfig = DefaultConfig(); + loaded = true; + } + + if (!loaded) + { + return; + } + + // Persist StartupScreen in the Interface section with the same definition as default config + diskConfig.Set("StartupScreen", startupValue, "Interface", std::string(""), std::string(""), { std::string("Games"), std::string("Settings") }); + + Util::Config::WriteINIFile(configPath, diskConfig, ""); +} + static void UpdateTempValues(Util::Config::Node& config, const std::string group, bool init) { for (auto it = config.begin(); it != config.end(); ++it) @@ -570,7 +599,7 @@ static Game GetGame(const std::map& games, int selectedGameIn return game; } -static void GUI(const ImGuiIO& io, Util::Config::Node& config, const std::map& games, int& selectedGameIndex, bool& exit, bool& saveSettings, SDL_Window* window, std::shared_ptr& inputs, KeyBindState& kb) +static void GUI(const ImGuiIO& io, Util::Config::Node& config, const std::map& games, int& selectedGameIndex, bool& exit, bool& saveSettings, SDL_Window* window, std::shared_ptr& inputs, KeyBindState& kb, bool& startupPreferenceChanged) { ImVec4 clear_color = ImVec4(0.0f, 0.5f, 192/255.f, 1.00f); @@ -579,140 +608,201 @@ static void GUI(const ImGuiIO& io, Util::Config::Node& config, const std::map(); + } + else + { + startupTabPreference = "Games"; + } + } + ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(0, 0)); ImGui::SetNextWindowSize(ImGui::GetIO().DisplaySize); ImGui::Begin("Custom Window", nullptr, ImGuiWindowFlags_NoTitleBar); // Explicitly set a window name - ImGui::BeginChild("TableRegion", ImVec2(0.0f, 200.0f), true, ImGuiWindowFlags_HorizontalScrollbar); + ImGuiTabItemFlags gamesTabFlags = 0; + ImGuiTabItemFlags settingsTabFlags = 0; - if (ImGui::BeginTable("Games", 5, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit)) + if (startupTabPreferenceNeedsApply) { - ImGui::TableSetupColumn("Title"); - ImGui::TableSetupColumn("Rom Name"); - ImGui::TableSetupColumn("Version"); - ImGui::TableSetupColumn("Year"); - ImGui::TableSetupColumn("Stepping"); + if (startupTabPreference == "Settings") + { + settingsTabFlags |= ImGuiTabItemFlags_SetSelected; + } + else + { + gamesTabFlags |= ImGuiTabItemFlags_SetSelected; + } + } - ImGui::TableHeadersRow(); + if (ImGui::BeginTabBar("MainViewTabs", ImGuiTabBarFlags_FittingPolicyResizeDown)) + { + if (startupTabPreferenceNeedsApply) + { + startupTabPreferenceNeedsApply = false; + } - int row = 0; - for (const auto& g : games) { + if (ImGui::BeginTabItem("Games", nullptr, gamesTabFlags)) + { + ImGui::BeginChild("TableRegion", ImVec2(0.0f, 0.0f), true, ImGuiWindowFlags_HorizontalScrollbar); - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::Text("%s", g.second.title.c_str()); - ImGui::TableSetColumnIndex(1); - if (ImGui::Selectable(g.second.name.c_str(), selectedGameIndex == row, ImGuiSelectableFlags_SpanAllColumns)) { - selectedGameIndex = row; - } + if (ImGui::BeginTable("Games", 5, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit)) + { + ImGui::TableSetupColumn("Title"); + ImGui::TableSetupColumn("Rom Name"); + ImGui::TableSetupColumn("Version"); + ImGui::TableSetupColumn("Year"); + ImGui::TableSetupColumn("Stepping"); - if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) { - exit = true; - } + ImGui::TableHeadersRow(); - ImGui::TableSetColumnIndex(2); - ImGui::Text("%s", g.second.version.c_str()); - ImGui::TableSetColumnIndex(3); - ImGui::Text("%d", g.second.year); - ImGui::TableSetColumnIndex(4); - ImGui::Text("%s", g.second.stepping.c_str()); + int row = 0; + for (const auto& g : games) { - row++; - } + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Text("%s", g.second.title.c_str()); + ImGui::TableSetColumnIndex(1); + if (ImGui::Selectable(g.second.name.c_str(), selectedGameIndex == row, ImGuiSelectableFlags_SpanAllColumns)) { + selectedGameIndex = row; + } - ImGui::EndTable(); - } + if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) { + exit = true; + } - ImGui::EndChild(); + ImGui::TableSetColumnIndex(2); + ImGui::Text("%s", g.second.version.c_str()); + ImGui::TableSetColumnIndex(3); + ImGui::Text("%d", g.second.year); + ImGui::TableSetColumnIndex(4); + ImGui::Text("%s", g.second.stepping.c_str()); - // draw button options - DrawButtonOptions(config, selectedGameIndex, exit, saveSettings); + row++; + } - // create a space - ImGui::Dummy(ImVec2(0.0f, 20.0f)); + ImGui::EndTable(); + } - // draw the tabbed options - if (ImGui::BeginTabBar("MyTabBar", ImGuiTabBarFlags_FittingPolicyResizeDown)) { - if (ImGui::BeginTabItem("Core")) { - UpdateTempValues(config, "Core", true); - CreateControls(config, "Core"); - UpdateTempValues(config, "Core", false); + ImGui::EndChild(); + ImGui::Dummy(ImVec2(0.0f, 20.0f)); + DrawButtonOptions(config, selectedGameIndex, exit, saveSettings); ImGui::EndTabItem(); - inputs = nullptr; } - if (ImGui::BeginTabItem("Video")) { - UpdateTempValues(config, "Video", true); - CreateControls(config, "Video"); - UpdateTempValues(config, "Video", false); - ImGui::EndTabItem(); - inputs = nullptr; - } - if (ImGui::BeginTabItem("Audio")) { - UpdateTempValues(config, "Sound", true); - CreateControls(config, "Sound"); - UpdateTempValues(config, "Sound", false); - ImGui::EndTabItem(); - inputs = nullptr; - } - if (ImGui::BeginTabItem("Networking")) { - UpdateTempValues(config, "Network", true); - CreateControls(config, "Network"); - UpdateTempValues(config, "Network", false); - ImGui::EndTabItem(); - inputs = nullptr; - } - if (ImGui::BeginTabItem("Misc")) { - UpdateTempValues(config, "Misc", true); - CreateControls(config, "Misc"); - UpdateTempValues(config, "Misc", false); - ImGui::EndTabItem(); - inputs = nullptr; - } - if (ImGui::BeginTabItem("ForceFeedback")) { - UpdateTempValues(config, "ForceFeedback", true); - CreateControls(config, "ForceFeedback"); - UpdateTempValues(config, "ForceFeedback", false); - ImGui::EndTabItem(); - inputs = nullptr; - } - if (ImGui::BeginTabItem("Sensitivity")) { - UpdateTempValues(config, "Sensitivity", true); - CreateControls(config, "Sensitivity"); - UpdateTempValues(config, "Sensitivity", false); - if (ImGui::Button("Joystick calibration")) { - if (inputs == nullptr) { + + if (ImGui::BeginTabItem("Settings", nullptr, settingsTabFlags)) + { + if (ImGui::BeginTabBar("MyTabBar", ImGuiTabBarFlags_FittingPolicyResizeDown)) { + if (ImGui::BeginTabItem("Core")) { + UpdateTempValues(config, "Core", true); + CreateControls(config, "Core"); + UpdateTempValues(config, "Core", false); + ImGui::EndTabItem(); + inputs = nullptr; + } + if (ImGui::BeginTabItem("Video")) { + UpdateTempValues(config, "Video", true); + CreateControls(config, "Video"); + UpdateTempValues(config, "Video", false); + ImGui::EndTabItem(); + inputs = nullptr; + } + if (ImGui::BeginTabItem("Audio")) { + UpdateTempValues(config, "Sound", true); + CreateControls(config, "Sound"); + UpdateTempValues(config, "Sound", false); + ImGui::EndTabItem(); + inputs = nullptr; + } + if (ImGui::BeginTabItem("Networking")) { + UpdateTempValues(config, "Network", true); + CreateControls(config, "Network"); + UpdateTempValues(config, "Network", false); + ImGui::EndTabItem(); + inputs = nullptr; + } + if (ImGui::BeginTabItem("Interface")) { + const char* startupOptions[] = { "Games", "Settings" }; + std::string startupScreenValue = config["StartupScreen"].ValueAs(); + int startupSelection = (startupScreenValue == "Settings") ? 1 : 0; + + if (ImGui::Combo("Startup screen", &startupSelection, startupOptions, IM_ARRAYSIZE(startupOptions))) { + const std::string newValue = startupOptions[startupSelection]; + config.Set("StartupScreen", newValue); + startupTabPreference = newValue; + startupTabPreferenceNeedsApply = true; + startupPreferenceChanged = true; + } + + ImGui::EndTabItem(); + inputs = nullptr; + } + if (ImGui::BeginTabItem("Misc")) { + UpdateTempValues(config, "Misc", true); + CreateControls(config, "Misc"); + UpdateTempValues(config, "Misc", false); + ImGui::EndTabItem(); + inputs = nullptr; + } + if (ImGui::BeginTabItem("ForceFeedback")) { + UpdateTempValues(config, "ForceFeedback", true); + CreateControls(config, "ForceFeedback"); + UpdateTempValues(config, "ForceFeedback", false); + ImGui::EndTabItem(); + inputs = nullptr; + } + if (ImGui::BeginTabItem("Sensitivity")) { + UpdateTempValues(config, "Sensitivity", true); + CreateControls(config, "Sensitivity"); + UpdateTempValues(config, "Sensitivity", false); + if (ImGui::Button("Joystick calibration")) { + if (inputs == nullptr) { + if (inputs == nullptr) { + inputs = GetInputSystem(config, window); + } + } + inputs->CalibrateJoysticks(); + inputs->StoreToConfig(&config); + } + ImGui::EndTabItem(); + inputs = nullptr; + } + if (ImGui::BeginTabItem("Key bindings")) { + if (inputs == nullptr) { inputs = GetInputSystem(config, window); } - } - inputs->CalibrateJoysticks(); - inputs->StoreToConfig(&config); - } - ImGui::EndTabItem(); - inputs = nullptr; - } - if (ImGui::BeginTabItem("Key bindings")) { - if (inputs == nullptr) { - inputs = GetInputSystem(config, window); - } + auto inputList = inputs->GetGameInputs(GetGame(games,selectedGameIndex)); - auto inputList = inputs->GetGameInputs(GetGame(games,selectedGameIndex)); + if (ImGui::BeginTable("KeyTable", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { - if (ImGui::BeginTable("KeyTable", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + ImGui::TableSetupColumn("Group"); + ImGui::TableSetupColumn("Action"); + ImGui::TableSetupColumn("Keys"); + ImGui::TableHeadersRow(); - ImGui::TableSetupColumn("Group"); - ImGui::TableSetupColumn("Action"); - ImGui::TableSetupColumn("Keys"); - ImGui::TableHeadersRow(); + AddKeys(config, kb, inputList); - AddKeys(config, kb, inputList); + ImGui::EndTable(); + } + + ImGui::EndTabItem(); + } - ImGui::EndTable(); + ImGui::EndTabBar(); } - + ImGui::EndTabItem(); } @@ -817,6 +907,7 @@ std::vector RunGUI(const std::string& configPath, Util::Config::Nod KeyBindState kb{}; bool exit = false; SDL_Event event{}; + bool startupPreferenceChanged = false; while (running) { @@ -825,11 +916,13 @@ std::vector RunGUI(const std::string& configPath, Util::Config::Nod ImGui_ImplSDL2_ProcessEvent(&event); if (event.type == SDL_QUIT) { - goto exitNoSave; + // Treat window close like a normal exit so settings (including StartupScreen) + // get a chance to be written out. + exit = true; } } - GUI(io, config, games, selectedGame, exit, saveSettings, window, inputs, kb); + GUI(io, config, games, selectedGame, exit, saveSettings, window, inputs, kb, startupPreferenceChanged); std::this_thread::sleep_for(std::chrono::milliseconds(5)); @@ -848,6 +941,9 @@ std::vector RunGUI(const std::string& configPath, Util::Config::Nod if (saveSettings) { Util::Config::WriteINIFile(configPath, config, ""); } + else if (startupPreferenceChanged) { + PersistStartupScreenSelection(configPath, config["StartupScreen"].ValueAs()); + } exitNoSave: diff --git a/Src/OSD/SDL/Main.cpp b/Src/OSD/SDL/Main.cpp index 9bb806c3..4c9a3eda 100644 --- a/Src/OSD/SDL/Main.cpp +++ b/Src/OSD/SDL/Main.cpp @@ -1524,6 +1524,7 @@ Util::Config::Node DefaultConfig() config.Set("ForceFeedback", false, "ForceFeedback"); // Platform-specific/UI + config.Set("StartupScreen", std::string("Games"), "Interface", std::string(""), std::string(""), { std::string("Games"), std::string("Settings") }); config.Set("New3DEngine", true, "Video"); config.Set("QuadRendering", false, "Video"); config.Set("XResolution", 496, "Video");