From 555d69b835dd4357405fbb451455dcf04a212812 Mon Sep 17 00:00:00 2001 From: milek7 Date: Sun, 25 Aug 2019 00:41:03 +0200 Subject: [PATCH] further WIP on launcher --- Globals.h | 2 +- launcher/scenery_list.cpp | 388 +++++++++++++++++++++------------- launcher/scenery_list.h | 26 ++- simulationstateserializer.cpp | 9 +- uilayer.cpp | 2 +- 5 files changed, 269 insertions(+), 158 deletions(-) diff --git a/Globals.h b/Globals.h index d128408c..5fd3f3e4 100644 --- a/Globals.h +++ b/Globals.h @@ -239,7 +239,7 @@ struct global_settings { std::vector> network_servers; std::optional> network_client; - std::vector> trainset_overrides; + std::unordered_map trainset_overrides; // methods void LoadIniFile( std::string asFileName ); diff --git a/launcher/scenery_list.cpp b/launcher/scenery_list.cpp index 6f0ebed2..0a753e72 100644 --- a/launcher/scenery_list.cpp +++ b/launcher/scenery_list.cpp @@ -13,180 +13,173 @@ ui::scenerylist_panel::scenerylist_panel(scenery_scanner &scanner) { } -void ui::scenerylist_panel::render() +void ui::scenerylist_panel::render_contents() { - if (!is_open) - return; + ImGui::Columns(3); - auto const panelname{(title.empty() ? m_name : title) + "###" + m_name}; + if (ImGui::BeginChild("child1", ImVec2(0, -200))) { + std::string prev_prefix; + bool collapse_open = false; - if (ImGui::Begin(panelname.c_str(), &is_open)) { - ImGui::Columns(3); + for (auto &desc : scanner.scenarios) { + std::string name = desc.path.stem().string(); + std::string prefix = name.substr(0, name.find_first_of("-_")); + if (prefix.empty()) + prefix = name; - if (ImGui::BeginChild("child1", ImVec2(0, -200))) { - std::string prev_prefix; - bool collapse_open = false; - - for (auto &desc : scanner.scenarios) { - std::string name = desc.path.stem().string(); - std::string prefix = name.substr(0, name.find_first_of("-_")); - 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); - } + bool just_opened = false; + if (prefix != prev_prefix) { + collapse_open = ImGui::CollapsingHeader(prefix.c_str()); + just_opened = ImGui::IsItemDeactivated(); + prev_prefix = prefix; } - } ImGui::EndChild(); - ImGui::NextColumn(); + if (collapse_open) { + if (just_opened) + selected_scenery = &desc; - if (ImGui::BeginChild("child2", ImVec2(0, -200))) { - if (selected_scenery) { - ImGui::TextWrapped("%s", selected_scenery->name.c_str()); - ImGui::TextWrapped("%s", selected_scenery->description.c_str()); - - ImGui::Separator(); - - for (auto const &link : selected_scenery->links) { - if (ImGui::Button(link.second.c_str(), ImVec2(-1, 0))) { - std::string file = ToLower(link.first); -#ifdef _WIN32 - system(("start \"" + file + "\"").c_str()); -#elif __linux__ - system(("xdg-open \"" + file + "\"").c_str()); -#elif __APPLE__ - system(("open \"" + file + "\"").c_str()); -#endif - } + ImGui::Indent(10.0f); + if (ImGui::Selectable(name.c_str(), &desc == selected_scenery)) { + selected_scenery = &desc; + selected_trainset = nullptr; } + ImGui::Unindent(10.0f); } - } ImGui::EndChild(); - - ImGui::NextColumn(); - - if (selected_scenery) { - if (ImGui::BeginChild("child3", ImVec2(0, -200), false, ImGuiWindowFlags_NoScrollbar)) { - if (!selected_scenery->image_path.empty()) { - scenery_desc *desc = const_cast(selected_scenery); - desc->image = GfxRenderer.Fetch_Texture(selected_scenery->image_path, true); - desc->image_path.clear(); - } - - if (selected_scenery->image != null_handle) { - opengl_texture &tex = GfxRenderer.Texture(selected_scenery->image); - tex.create(); - - if (tex.is_ready) { - float avail_width = ImGui::GetContentRegionAvailWidth(); - float height = avail_width / tex.width() * tex.height(); - - ImGui::Image(reinterpret_cast(tex.id), ImVec2(avail_width, height), ImVec2(0, 1), ImVec2(1, 0)); - } - } - } ImGui::EndChild(); } - ImGui::Columns(); - ImGui::Separator(); + } ImGui::EndChild(); - if (ImGui::BeginChild("child4")) { - if (selected_scenery) { - if (selected_trainset) - ImGui::Columns(2); + ImGui::NextColumn(); - if (ImGui::BeginChild("child5", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar)) { - ImGuiListClipper clipper(selected_scenery->trainsets.size()); - while (clipper.Step()) for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { - auto &trainset = selected_scenery->trainsets[i]; - ImGui::PushID(i); - if (ImGui::Selectable("##set", selected_trainset == &trainset, 0, ImVec2(0, 30))) - selected_trainset = &trainset; - ImGui::SameLine(); - draw_trainset(trainset); - ImGui::NewLine(); - ImGui::PopID(); - //ImGui::Selectable(z.c_str(), false); - } - } ImGui::EndChild(); + if (ImGui::BeginChild("child2", ImVec2(0, -200))) { + if (selected_scenery) { + ImGui::TextWrapped("%s", selected_scenery->name.c_str()); + ImGui::TextWrapped("%s", selected_scenery->description.c_str()); - if (selected_trainset) { - ImGui::NextColumn(); + ImGui::Separator(); - ImGui::TextWrapped(selected_trainset->description.c_str()); + for (auto const &link : selected_scenery->links) { + if (ImGui::Button(link.second.c_str(), ImVec2(-1, 0))) { + std::string file = ToLower(link.first); +#ifdef _WIN32 + system(("start \"" + file + "\"").c_str()); +#elif __linux__ + system(("xdg-open \"" + file + "\"").c_str()); +#elif __APPLE__ + system(("open \"" + file + "\"").c_str()); +#endif + } + } + } + } ImGui::EndChild(); - if (ImGui::Button(STR_C("Launch"), ImVec2(-1, 0))) { - bool found = false; - for (auto &veh : selected_trainset->vehicles) { - if (veh.drivertype.size() > 0 && veh.drivertype != "nobody") { - Global.local_start_vehicle = ToLower(veh.name); - Global.SceneryFile = selected_scenery->path; + ImGui::NextColumn(); - std::string set = "trainset "; - set += selected_trainset->name + " "; - set += selected_trainset->track + " "; - set += std::to_string(selected_trainset->offset) + " "; - set += std::to_string(selected_trainset->velocity) + " "; - for (const auto &veh : selected_trainset->vehicles) { - set += "node -1 0 " + veh.name + " dynamic "; - set += veh.vehicle->path.parent_path().generic_string() + " "; - set += veh.skin->skin + " "; - set += veh.vehicle->path.stem().generic_string() + " "; - set += std::to_string(veh.offset) + " " + veh.drivertype + " "; - set += std::to_string(veh.coupling); - if (veh.params.size() > 0) - set += "." + veh.params; - set += " " + std::to_string(veh.loadcount) + " "; - if (veh.loadcount > 0) - set += veh.loadtype + " "; - set += "enddynamic "; - } - set += "endtrainset"; - WriteLog(set); + if (selected_scenery) { + if (ImGui::BeginChild("child3", ImVec2(0, -200), false, ImGuiWindowFlags_NoScrollbar)) { + if (!selected_scenery->image_path.empty()) { + scenery_desc *desc = const_cast(selected_scenery); + desc->image = GfxRenderer.Fetch_Texture(selected_scenery->image_path, true); + desc->image_path.clear(); + } - Global.trainset_overrides.push_back(std::make_pair(selected_trainset->file_bounds.first, set)); + if (selected_scenery->image != null_handle) { + opengl_texture &tex = GfxRenderer.Texture(selected_scenery->image); + tex.create(); - Application.pop_mode(); - Application.push_mode(eu07_application::mode::scenarioloader); + if (tex.is_ready) { + float avail_width = ImGui::GetContentRegionAvailWidth(); + float height = avail_width / tex.width() * tex.height(); - found = true; - break; - } - } - if (!found) - ImGui::OpenPopup("missing_driver"); - } - - if (ImGui::BeginPopup("missing_driver")) { - ImGui::TextUnformatted(STR_C("Trainset not occupied")); - if (ImGui::Button(STR_C("OK"), ImVec2(-1, 0))) - ImGui::CloseCurrentPopup(); - ImGui::EndPopup(); - } + ImGui::Image(reinterpret_cast(tex.id), ImVec2(avail_width, height), ImVec2(0, 1), ImVec2(1, 0)); } } } ImGui::EndChild(); } + ImGui::Columns(); + ImGui::Separator(); - ImGui::End(); + if (ImGui::BeginChild("child4")) { + if (selected_scenery) { + if (selected_trainset) + ImGui::Columns(2); + + if (ImGui::BeginChild("child5", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar)) { + ImGuiListClipper clipper(selected_scenery->trainsets.size()); + while (clipper.Step()) for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { + auto &trainset = selected_scenery->trainsets[i]; + ImGui::PushID(i); + if (ImGui::Selectable("##set", selected_trainset == &trainset, 0, ImVec2(0, 30))) + selected_trainset = &trainset; + ImGui::SameLine(); + draw_trainset(trainset); + ImGui::NewLine(); + ImGui::PopID(); + //ImGui::Selectable(z.c_str(), false); + } + } ImGui::EndChild(); + + if (selected_trainset) { + ImGui::NextColumn(); + + ImGui::TextWrapped(selected_trainset->description.c_str()); + + if (ImGui::Button(STR_C("Launch"), ImVec2(-1, 0))) { + bool found = false; + for (auto &veh : selected_trainset->vehicles) { + if (veh.drivertype.size() > 0 && veh.drivertype != "nobody") { + Global.local_start_vehicle = ToLower(veh.name); + Global.SceneryFile = selected_scenery->path; + + std::string set = "trainset "; + set += selected_trainset->name + " "; + set += selected_trainset->track + " "; + set += std::to_string(selected_trainset->offset) + " "; + set += std::to_string(selected_trainset->velocity) + "\n"; + for (const auto &veh : selected_trainset->vehicles) { + set += "node -1 0 " + veh.name + " dynamic "; + set += veh.vehicle->path.parent_path().generic_string() + " "; + set += veh.skin->skin + " "; + set += veh.vehicle->path.stem().generic_string() + " "; + set += std::to_string(veh.offset) + " " + veh.drivertype + " "; + set += std::to_string(veh.coupling); + if (veh.params.size() > 0) + set += "." + veh.params; + set += " " + std::to_string(veh.loadcount) + " "; + if (veh.loadcount > 0) + set += veh.loadtype + " "; + set += "enddynamic\n"; + } + set += "endtrainset\n"; + WriteLog(set); + + Global.trainset_overrides.emplace(selected_trainset->file_bounds.first, set); + + Application.pop_mode(); + Application.push_mode(eu07_application::mode::scenarioloader); + + found = true; + break; + } + } + if (!found) + ImGui::OpenPopup("missing_driver"); + } + + if (ImGui::BeginPopup("missing_driver")) { + ImGui::TextUnformatted(STR_C("Trainset not occupied")); + if (ImGui::Button(STR_C("OK"), ImVec2(-1, 0))) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + } + } + } ImGui::EndChild(); } void ui::scenerylist_panel::draw_trainset(trainset_desc &trainset) { + ImGui::SetItemAllowOverlap(); + static std::unordered_map coupling_names = { { coupling::faux, STRN("faux") }, @@ -206,7 +199,7 @@ void ui::scenerylist_panel::draw_trainset(trainset_desc &trainset) draw_droptarget(trainset, position++); ImGui::SameLine(15.0f); - for (auto const &dyn_desc : trainset.vehicles) { + for (auto &dyn_desc : trainset.vehicles) { deferred_image *mini = nullptr; if (dyn_desc.skin && dyn_desc.skin->mini.get() != -1) @@ -220,7 +213,10 @@ void ui::scenerylist_panel::draw_trainset(trainset_desc &trainset) float width = 30.0f / size.y * size.x; ImGui::Image(reinterpret_cast(mini->get()), ImVec2(width, 30), ImVec2(0, 1), ImVec2(1, 0)); - if (ImGui::IsItemHovered()) { + if (ImGui::IsItemClicked(1)) { + register_popup(std::make_unique(*this, dyn_desc)); + } + else if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); std::string name = (dyn_desc.vehicle->path.parent_path() / dyn_desc.vehicle->path.stem()).string(); std::string skin = dyn_desc.skin->skin; @@ -267,7 +263,6 @@ void ui::scenerylist_panel::draw_trainset(trainset_desc &trainset) } } -#include "Logs.h" void ui::scenerylist_panel::draw_droptarget(trainset_desc &trainset, int position) { ImGui::Dummy(ImVec2(15, 30)); @@ -291,3 +286,98 @@ void ui::scenerylist_panel::draw_droptarget(trainset_desc &trainset, int positio ImGui::EndDragDropTarget(); } } + +ui::dynamic_edit_popup::dynamic_edit_popup(ui_panel &panel, dynamic_desc &dynamic) + : popup(panel), dynamic(dynamic) +{ + prepare_str(dynamic.name, name_buf); + prepare_str(dynamic.loadtype, load_buf); + prepare_str(dynamic.params, param_buf); +} + +void ui::dynamic_edit_popup::render_content() +{ + static std::unordered_map coupling_names = + { + { coupling::faux, STRN("faux") }, + { coupling::coupler, STRN("coupler") }, + { coupling::brakehose, STRN("brake hose") }, + { coupling::control, STRN("control") }, + { coupling::highvoltage, STRN("high voltage") }, + { coupling::gangway, STRN("gangway") }, + { coupling::mainhose, STRN("main hose") }, + { coupling::heating, STRN("heating") }, + { coupling::permanent, STRN("permanent") }, + { coupling::uic, STRN("uic") } + }; + + static std::vector occupancy_names = { + STRN("headdriver"), + STRN("reardriver"), + STRN("passenger"), + STRN("nobody") + }; + + std::string name = (dynamic.vehicle->path.parent_path() / dynamic.vehicle->path.stem()).string(); + + ImGui::Text(STR_C("Type: %s"), name.c_str()); + ImGui::NewLine(); + + if (ImGui::InputText(STR_C("Name"), name_buf.data(), name_buf.size())) + dynamic.name = name_buf.data(); + + if (ImGui::BeginCombo(STR_C("Skin"), dynamic.skin->skin.c_str(), ImGuiComboFlags_HeightLargest)) + { + for (auto const &skin : dynamic.vehicle->matching_skinsets) { + bool is_selected = (skin == dynamic.skin); + if (ImGui::Selectable(skin->skin.c_str(), is_selected)) + dynamic.skin = skin; + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + if (ImGui::BeginCombo(STR_C("Occupancy"), Translations.lookup_c(dynamic.drivertype.c_str()))) + { + for (auto const &str : occupancy_names) { + bool is_selected = (str == dynamic.drivertype); + if (ImGui::Selectable(Translations.lookup_c(str.c_str()), is_selected)) + dynamic.drivertype = str; + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + if (ImGui::InputText(STR_C("Load type"), load_buf.data(), load_buf.size())) { + dynamic.loadtype = load_buf.data(); + if (!load_buf[0]) + dynamic.loadtype = "none"; + } + + if (dynamic.loadtype != "none") + ImGui::InputInt(STR_C("Load count"), &dynamic.loadcount, 1, 10); + else + dynamic.loadcount = 0; + + if (dynamic.loadcount < 0) + dynamic.loadcount = 0; + + if (ImGui::InputText(STR_C("Parameters"), param_buf.data(), param_buf.size())) + dynamic.params = param_buf.data(); + + ImGui::NewLine(); + ImGui::TextUnformatted(STR_C("Coupling:")); + + for (int i = 1; i <= 0x100; i <<= 1) { + bool selected = dynamic.coupling & i; + + std::string label = STRN("unknown"); + auto it = coupling_names.find(static_cast(i)); + if (it != coupling_names.end()) + label = it->second; + if (ImGui::Checkbox(Translations.lookup_c(label.c_str()), &selected)) + dynamic.coupling ^= i; + } +} diff --git a/launcher/scenery_list.h b/launcher/scenery_list.h index d32e1f47..e7c4b00a 100644 --- a/launcher/scenery_list.h +++ b/launcher/scenery_list.h @@ -2,15 +2,39 @@ #include "uilayer.h" #include "scenery_scanner.h" +#include "widgets/popup.h" namespace ui { +class dynamic_edit_popup : public popup +{ + dynamic_desc &dynamic; + + std::array name_buf; + std::array load_buf; + std::array param_buf; + + template + void prepare_str(std::string &str, std::array &array) { + if (str.size() > array.size() - 1) + str.resize(array.size() - 1); + + std::copy(str.begin(), str.end(), array.data()); + array[str.size()] = 0; + } + + public: + dynamic_edit_popup(ui_panel &panel, dynamic_desc &dynamic); + + virtual void render_content() override; +}; + class scenerylist_panel : public ui_panel { public: scenerylist_panel(scenery_scanner &scanner); - void render() override; + void render_contents() override; private: scenery_scanner &scanner; diff --git a/simulationstateserializer.cpp b/simulationstateserializer.cpp index 287ffa6a..241c76b3 100644 --- a/simulationstateserializer.cpp +++ b/simulationstateserializer.cpp @@ -645,13 +645,10 @@ state_serializer::deserialize_trainset( cParser &Input, scene::scratch_data &Scr int line = Input.LineMain(); if (line != -1) { - for (const std::pair &entry : Global.trainset_overrides) { - if (line != entry.first) - continue; - + auto it = Global.trainset_overrides.find(line); + if (it != Global.trainset_overrides.end()) { skip_until(Input, "endtrainset"); - Input.injectString(entry.second); - + Input.injectString(it->second); return; } } diff --git a/uilayer.cpp b/uilayer.cpp index 1affc01e..d0b33a89 100644 --- a/uilayer.cpp +++ b/uilayer.cpp @@ -44,7 +44,7 @@ void ui_panel::render() if (size.x > 0) ImGui::SetNextWindowSize(ImVec2(size.x, size.y)); else if (size_min.x == -1) - ImGui::SetNextWindowSize(ImVec2(0, 0)); + ImGui::SetNextWindowSize(ImVec2(0, 0), ImGuiCond_FirstUseEver); if (size_min.x > 0) ImGui::SetNextWindowSizeConstraints(ImVec2(size_min.x, size_min.y), ImVec2(size_max.x, size_max.y));