diff --git a/Event.cpp b/Event.cpp index 30acbe10..55cc31c9 100644 --- a/Event.cpp +++ b/Event.cpp @@ -1197,6 +1197,14 @@ multi_event::init() { } } +std::vector multi_event::dump_children_names() const { + std::vector result; + for (auto const &childevent : m_children) { + result.push_back(std::get(childevent)); + } + return result; +} + // event type string std::string multi_event::type() const { diff --git a/Event.h b/Event.h index 50cd6e0c..41631efc 100644 --- a/Event.h +++ b/Event.h @@ -330,6 +330,8 @@ public: // prepares event for use void init() override; + std::vector dump_children_names() const; + private: // types // wrapper for binding between editor-supplied name, event, and execution conditional flag diff --git a/Segment.h b/Segment.h index 6df2a463..d9b06575 100644 --- a/Segment.h +++ b/Segment.h @@ -18,6 +18,7 @@ struct map_colored_paths { std::vector switches; std::vector occupied; std::vector future; + std::vector highlighted; }; struct segment_data { diff --git a/Track.cpp b/Track.cpp index dfdf05ec..39f38ec7 100644 --- a/Track.cpp +++ b/Track.cpp @@ -1209,6 +1209,14 @@ void TTrack::get_map_active_paths(map_colored_paths &handles) } } +void TTrack::get_map_paths_for_state(map_colored_paths &handles, int state) +{ + if (iCategoryFlag != 1 || eType != tt_Switch) + return; + + handles.highlighted.push_back(SwitchExtension->map_geometry[state]); +} + void TTrack::get_map_future_paths(map_colored_paths &handles) { if (iCategoryFlag != 1) return; diff --git a/Track.h b/Track.h index a69575d2..93e26865 100644 --- a/Track.h +++ b/Track.h @@ -286,6 +286,7 @@ public: void create_geometry( gfx::geometrybank_handle const &Bank ); // wypełnianie VBO void create_map_geometry(std::vector &Bank, const gfx::geometrybank_handle Extra); void get_map_active_paths(map_colored_paths &handles); + void get_map_paths_for_state(map_colored_paths &handles, int state); void get_map_future_paths(map_colored_paths &handles); glm::vec3 get_nearest_point(const glm::dvec3 &point) const; void RenderDynSounds(); // odtwarzanie dźwięków pojazdów jest niezależne od ich wyświetlania diff --git a/scenenodegroups.cpp b/scenenodegroups.cpp index 5c9ceb45..01a83818 100644 --- a/scenenodegroups.cpp +++ b/scenenodegroups.cpp @@ -53,11 +53,55 @@ node_groups::close() return handle(); } +bool node_groups::assign_cross_switch(map::track_switch& sw, TTrack* track, std::string const &id, size_t idx) +{ + std::string sw_name = track->name(); + sw_name.pop_back(); + + sw.action[idx] = simulation::Events.FindEvent(sw_name + ":" + id); + + if (!sw.action[idx]) + return false; + + multi_event *multi = dynamic_cast(sw.action[idx]); + + if (!multi) + return false; + + auto names = multi->dump_children_names(); + for (auto it = names.begin(); it != names.end(); it++) { + int pos_a = it->find_last_of('a'); + int pos_b = it->find_last_of('b'); + int pos_c = it->find_last_of('c'); + int pos_d = it->find_last_of('d'); + + int pos_0 = it->find_last_of('0'); + int pos_1 = it->find_last_of('1'); + + int pos; + + if (pos_a > pos_b && pos_a > pos_c && pos_a > pos_d) + pos = 0; + else if (pos_b > pos_a && pos_b > pos_c && pos_b > pos_d) + pos = 1; + else if (pos_c > pos_a && pos_c > pos_b && pos_c > pos_d) + pos = 2; + else + pos = 3; + + sw.preview[idx][pos] = ((pos_0 > pos_1) ? '0' : '1'); + } + + return true; +} + void node_groups::update_map() { map::Objects.entries.clear(); + std::shared_ptr last_switch; + for (auto const &pair : m_groupmap) { auto const &group = pair.second; @@ -92,22 +136,60 @@ node_groups::update_map() if (track->eType != tt_Switch) continue; - basic_event *sw_straight = simulation::Events.FindEvent(track->name() + "+"); - basic_event *sw_divert = simulation::Events.FindEvent(track->name() + "-"); + basic_event *sw_p = simulation::Events.FindEvent(track->name() + "+"); + basic_event *sw_m = simulation::Events.FindEvent(track->name() + "-"); - if (sw_straight && sw_divert) { - auto map_launcher = std::make_shared(); + if (sw_p && sw_m) { + auto map_launcher = std::make_shared(); map::Objects.entries.push_back(map_launcher); map_launcher->location = node->location(); map_launcher->name = node->name(); - map_launcher->first_event = sw_straight; - map_launcher->second_event = sw_divert; - if (map_launcher->name.empty()) - map_launcher->name = sw_straight->name(); + map_launcher->action[0] = sw_p; + map_launcher->action[1] = sw_m; + map_launcher->track[0] = track; + map_launcher->preview[0][0] = '0'; + map_launcher->preview[1][0] = '1'; - map_launcher->type = map::launcher::track_switch; + continue; } + + std::string sw_name = track->name(); + if (sw_name.size() <= 2) + continue; + + char lastc = sw_name.back(); + sw_name.pop_back(); + + if (!simulation::Events.FindEvent(sw_name + ":ac")) + continue; + + if (!last_switch || last_switch->name != sw_name) { + last_switch = std::make_shared(); + last_switch->name = sw_name; + } + + if (lastc < 'a' || lastc > 'd') + continue; + + last_switch->track[lastc - 'a'] = track; + for (auto trk : last_switch->track) + if (!trk) + goto skip_e; + + if (!assign_cross_switch(*last_switch, track, "ac", 0)) + skip_e: continue; + if (!assign_cross_switch(*last_switch, track, "ad", 1)) + continue; + if (!assign_cross_switch(*last_switch, track, "bc", 2)) + continue; + if (!assign_cross_switch(*last_switch, track, "bd", 3)) + continue; + + last_switch->location = (last_switch->track[0]->location() + last_switch->track[1]->location() + last_switch->track[2]->location() + last_switch->track[3]->location()) / 4.0; + map::Objects.entries.push_back(last_switch); + + last_switch.reset(); } } else { if (TEventLauncher *launcher = dynamic_cast(node)) { diff --git a/scenenodegroups.h b/scenenodegroups.h index 1847ec56..f4ad3d11 100644 --- a/scenenodegroups.h +++ b/scenenodegroups.h @@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/. #pragma once #include "scenenode.h" +#include "widgets/map_objects.h" namespace scene { @@ -63,6 +64,8 @@ private: // creates handle for a new group group_handle create_handle(); + bool + assign_cross_switch(map::track_switch&sw, TTrack *track, const std::string &id, size_t idx); // members group_map m_groupmap; // map of established node groups std::stack m_activegroup; // helper, group to be assigned to newly created nodes diff --git a/widgets/map.cpp b/widgets/map.cpp index 1a5e95ff..94c6362c 100644 --- a/widgets/map.cpp +++ b/widgets/map.cpp @@ -89,6 +89,7 @@ void ui::map_panel::render_map_texture(glm::mat4 transform, glm::vec2 surface_si m_colored_paths.switches.clear(); m_colored_paths.occupied.clear(); m_colored_paths.future.clear(); + m_colored_paths.highlighted.clear(); m_section_handles.clear(); for (int row = 0; row < scene::EU07_REGIONSIDESECTIONCOUNT; row++) @@ -112,6 +113,11 @@ void ui::map_panel::render_map_texture(glm::mat4 transform, glm::vec2 surface_si track->get_map_future_paths(m_colored_paths); } + for (std::pair &entry : highlighted_switches) { + if (entry.first) + entry.first->get_map_paths_for_state(m_colored_paths, entry.second); + } + glDisable(GL_DEPTH_TEST); if (Global.iMultisampling) { @@ -138,6 +144,12 @@ void ui::map_panel::render_map_texture(glm::mat4 transform, glm::vec2 surface_si gl33->Draw_Geometry(m_section_handles.begin(), m_section_handles.end()); + glLineWidth(4.0f); + scene_ubs.cascade_end = glm::vec4(0.3f, 0.3f, 1.0f, 0.0f); + scene_ubo->update(scene_ubs); + gl33->Draw_Geometry(m_colored_paths.highlighted.begin(), m_colored_paths.highlighted.end()); + + glLineWidth(1.5f); scene_ubs.cascade_end = glm::vec4(0.7f, 0.7f, 0.0f, 0.0f); scene_ubo->update(scene_ubs); gl33->Draw_Geometry(m_colored_paths.future.begin(), m_colored_paths.future.end()); @@ -349,6 +361,10 @@ void ui::handle_map_object_click(ui_panel &parent, std::shared_ptr(parent, std::move(track))); } + else if (auto track_switch = std::dynamic_pointer_cast(obj)) + { + parent.register_popup(std::make_unique(parent, std::move(track_switch))); + } else if (auto obstacle = std::dynamic_pointer_cast(obj)) { parent.register_popup(std::make_unique(parent, std::move(obstacle))); @@ -506,6 +522,34 @@ void ui::launcher_window::render_content() } } +ui::track_switch_window::track_switch_window(ui_panel &panel, std::shared_ptr &&sw) : popup(panel), m_switch(sw) {} + +void ui::track_switch_window::render_content() +{ + auto &highlight = dynamic_cast(m_parent).highlighted_switches; + + ImGui::TextUnformatted(m_switch->name.c_str()); + + highlight.clear(); + + std::array names = { "ac", "ad", "bc", "bd" }; + + for (size_t i = 0; i < 4; i++) { + if (m_switch->action[i]) { + if (ImGui::Button(names[i].c_str())) + m_relay.post(user_command::queueevent, 0.0, 0.0, GLFW_PRESS, 0, glm::vec3(0.0f), &m_switch->action[i]->name()); + if (ImGui::IsItemHovered()) { + for (size_t j = 0; j < 4; j++) { + if ((names[i][0] - 'a') != j && (names[i][1] - 'a') != j) + continue; + highlight.push_back(std::make_pair(m_switch->track[j], m_switch->preview[i][j] == '1' ? 1 : 0)); + } + } + ImGui::SameLine(); + } + } +} + ui::obstacle_insert_window::obstacle_insert_window(ui_panel &panel, glm::dvec3 const &pos) : popup(panel), m_position(pos) { std::ifstream file; diff --git a/widgets/map.h b/widgets/map.h index b9c44b6a..e89e4a0c 100644 --- a/widgets/map.h +++ b/widgets/map.h @@ -46,6 +46,17 @@ class launcher_window : public popup virtual void render_content() override; }; +class track_switch_window : public popup +{ + std::shared_ptr m_switch; + command_relay m_relay; + + public: + track_switch_window(ui_panel &panel, std::shared_ptr &&sw); + + virtual void render_content() override; +}; + class obstacle_insert_window : public popup { glm::dvec3 m_position; @@ -86,6 +97,8 @@ class vehicle_click_window : public popup class map_panel : public ui_panel { + friend class track_switch_window; + std::unique_ptr m_track_shader; std::unique_ptr m_poi_shader; std::unique_ptr m_msaa_fb; @@ -101,7 +114,7 @@ class map_panel : public ui_panel std::vector m_section_handles; map_colored_paths m_colored_paths; - const int fb_size = 1024; + const int fb_size = 1024; glm::vec2 translate; float zoom = 1.0f / 1000.0f; @@ -113,7 +126,7 @@ class map_panel : public ui_panel bool init_done = false; - std::optional active; + std::vector> highlighted_switches; public: map_panel(); diff --git a/widgets/map_objects.h b/widgets/map_objects.h index a6c807cc..44deb371 100644 --- a/widgets/map_objects.h +++ b/widgets/map_objects.h @@ -53,6 +53,18 @@ struct launcher : public map_object } }; +// switch description (only for minimap purposes) +struct track_switch : public map_object +{ + std::array action = { nullptr }; + std::array preview; + std::array track = { nullptr }; + + virtual gfx::basic_vertex vertex() { + return gfx::basic_vertex(location, glm::vec3(), glm::vec2(0.4f, 0.6f)); + } +}; + // training obstacle description struct obstacle : public map_object {