From c83c1235969e2676169b75c968d9cf49e404e04e Mon Sep 17 00:00:00 2001 From: jakubg1 <24206305+jakubg1@users.noreply.github.com> Date: Thu, 4 Sep 2025 18:01:48 +0200 Subject: [PATCH] Add scenery category detection, launcher category list parity with Starter --- launcher/scenery_list.cpp | 43 +++++++++++++++++++----------------- launcher/scenery_scanner.cpp | 15 +++++++++++++ launcher/scenery_scanner.h | 3 +++ 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/launcher/scenery_list.cpp b/launcher/scenery_list.cpp index 3db32ac0..fec28925 100644 --- a/launcher/scenery_list.cpp +++ b/launcher/scenery_list.cpp @@ -3,7 +3,6 @@ #include "imgui/imgui.h" #include "utilities.h" #include "renderer.h" -#include "McZapkie/MOVER.h" #include "application.h" #include "Logs.h" #include @@ -15,32 +14,36 @@ ui::scenerylist_panel::scenerylist_panel(scenery_scanner &scanner) void ui::scenerylist_panel::draw_scenery_list() { - std::string prev_prefix; - bool collapse_open = false; - + // Draw all the scenarios which are not assigned to any category. for (auto &desc : scanner.scenarios) { std::string name = desc.path.stem().string(); - std::string prefix = name.substr(0, name.find_first_of("-_")); + std::string prefix = desc.category; if (prefix.empty()) - prefix = name; - - bool just_opened = false; - if (prefix != prev_prefix) { - collapse_open = ImGui::CollapsingHeader(prefix.c_str()); - just_opened = ImGui::IsItemDeactivated(); - prev_prefix = prefix; - } - - if (collapse_open) { - if (just_opened) - selected_scenery = &desc; - - ImGui::Indent(10.0f); + { if (ImGui::Selectable(name.c_str(), &desc == selected_scenery)) { selected_scenery = &desc; selected_trainset = nullptr; } - ImGui::Unindent(10.0f); + } + } + + // Render all aggregated scenarios inside categories. + bool collapse_open = false; + for (auto category : scanner.categories) + { + collapse_open = ImGui::CollapsingHeader(category.first.c_str()); + if (collapse_open) { + for (auto desc : category.second) + { + std::string name = desc->path.stem().string(); + + ImGui::Indent(10.0f); + if (ImGui::Selectable(name.c_str(), desc == selected_scenery)) { + selected_scenery = desc; + selected_trainset = nullptr; + } + ImGui::Unindent(10.0f); + } } } } diff --git a/launcher/scenery_scanner.cpp b/launcher/scenery_scanner.cpp index 2f5a5ad4..22007035 100644 --- a/launcher/scenery_scanner.cpp +++ b/launcher/scenery_scanner.cpp @@ -22,6 +22,8 @@ void scenery_scanner::scan() std::sort(scenarios.begin(), scenarios.end(), [](const scenery_desc &a, const scenery_desc &b) { return a.path < b.path; }); + + build_categories(); } void scenery_scanner::scan_scn(std::filesystem::path path) @@ -57,6 +59,8 @@ void scenery_scanner::scan_scn(std::filesystem::path path) desc.name = win1250_to_utf8(line.substr(5)); else if (line[3] == 'd') desc.description += win1250_to_utf8(line.substr(5)) + '\n'; + else if (line[3] == 'l') + desc.category = win1250_to_utf8(line.substr(5)); else if (line[3] == 'f') { std::string lang; std::string file; @@ -154,3 +158,14 @@ void scenery_scanner::parse_trainset(cParser &parser) trainset.file_bounds.second = parser.Line(); } + +void scenery_scanner::build_categories() +{ + for (auto &desc : scenarios) { + std::string name = desc.path.stem().string(); + std::string prefix = desc.category; + // If the scenario does have a category, add it to the list so we can render it later in a group. + if (!prefix.empty()) + categories[prefix].push_back(&desc); + } +} diff --git a/launcher/scenery_scanner.h b/launcher/scenery_scanner.h index 67648e7f..ebde6062 100644 --- a/launcher/scenery_scanner.h +++ b/launcher/scenery_scanner.h @@ -39,6 +39,7 @@ struct scenery_desc { std::filesystem::path path; std::string name; std::string description; + std::string category; std::string image_path; texture_handle image = 0; @@ -58,12 +59,14 @@ public: scenery_scanner(ui::vehicles_bank &bank); std::vector scenarios; + std::map> categories; void scan(); private: void scan_scn(std::filesystem::path path); void parse_trainset(cParser &parser); + void build_categories(); ui::vehicles_bank &bank; };