diff --git a/application/editormode.cpp b/application/editormode.cpp index 389d3b58..952697fa 100644 --- a/application/editormode.cpp +++ b/application/editormode.cpp @@ -1450,7 +1450,7 @@ bool editor_mode::update() signal_move_update(); draw_signal_overlay(); } - draw_parallel_preview(); + m_parallel.draw_overlay(); if (m_track_tab == track_tab::lineside) { m_hekto.draw_overlay(); diff --git a/application/editormode.h b/application/editormode.h index c9881b6c..ea8a680a 100644 --- a/application/editormode.h +++ b/application/editormode.h @@ -17,6 +17,7 @@ http://mozilla.org/MPL/2.0/. #include "application/editormodegauge.h" #include "application/editormodejoints.h" #include "application/editormodelineside.h" +#include "application/editormodeparallel.h" #include "application/editormodespeed.h" #include "application/editormodevehicle.h" #include "application/editortool.h" @@ -715,6 +716,8 @@ class editor_mode : public application_mode, private editor_track::observer, pri std::size_t history_size() const override; glm::dvec3 camera_position() const override; track_hover const &hovered_track() const override; + std::vector const &track_set() const override; + editor_track_tab current_track_tab() const override; void render_path_ui(); void draw_track_overlay() const; editor_track::point_ref track_handle_hit() const; @@ -910,7 +913,7 @@ class editor_mode : public application_mode, private editor_track::observer, pri void record_slip(std::vector const &Parts, std::string const &Kind, std::string const &Type, double const Radius, double const Angle, std::string const &Base, double const Middle = 0.0); void render_switch_record(TTrack const &Track) const; void route_store(); - bool digitize_drawn(std::vector const &Created, bool const Alone = true); + bool digitize_drawn(std::vector const &Created, bool const Alone = true) override; bool digitize_chain(editor_track::chain const &Chain, std::string *Reason = nullptr, TTrack **Culprit = nullptr); int digitize_parts(editor_track::chain const &Chain, std::string *Reason, int &Skipped); // the lines kept, the paths left out @@ -1016,7 +1019,7 @@ class editor_mode : public application_mode, private editor_track::observer, pri void apply_straight_tool(); double straight_tool_radius(editor_track::straight const &Line) const; void straight_reshape(editor_track::straight const &Line, double const From, double const To, std::function const &Tail, double const Radius); - void straight_refresh(); + void straight_refresh() override; bool start_curve_fit(editor_track::straight const &Line, int const Handle); void update_curve_fit(glm::dvec3 const &Start, glm::dvec3 const &End); void add_detour_point(); @@ -1736,40 +1739,6 @@ class editor_mode : public application_mode, private editor_track::observer, pri std::vector> m_track_similar; TTrack const *m_track_list_hover{nullptr}; // in the list of the selected tracks int m_track_list_hover_frame{-1}; - // second track alongside the selected path or the line through it, at a spacing, curves included - struct parallel_tool - { - bool open{false}; - bool expand{false}; - double spacing{4.0}; - int side{1}; // 1: to the right, -1: to the left, of the direction of the line - int scope{1}; // 0: the selected path, 1: the line through it, up to the switches - TTrack *built_for{nullptr}; - double built_spacing{0.0}; - int built_side{0}; - int built_scope{-1}; - std::size_t built_history{0}; - TTrack *pair_src{nullptr}; - TTrack *pair_dst{nullptr}; - double measured{0.0}; - std::vector pieces; - std::vector styles; - double length{0.0}; - std::string error; - std::string status; - }; - parallel_tool m_parallel; - TTrack *parallel_source() const; - TTrack *parallel_target() const; - void parallel_update(); - void render_parallel_controls(bool const Scope = true); - void render_parallel_ui(); - void render_parallel_set_ui(); - void parallel_build(); - void parallel_apply(); - bool parallel_preview_visible() const; - void draw_parallel_preview() const; - using template_item = ::template_item; using standing_template = ::standing_template; // includes of the templates whose file names the test accepts, with the location in p2..p4 and the rotation in p5 @@ -2273,7 +2242,8 @@ class editor_mode : public application_mode, private editor_track::observer, pri vehicle_tool m_vehicle{*this}; hekto_tool m_hekto{*this}; fouling_tool m_fouling{*this}; - std::vector m_tools{&m_gauge, &m_speed, &m_joints, &m_vehicle, &m_hekto, &m_fouling}; + parallel_tool m_parallel{*this}; + std::vector m_tools{&m_gauge, &m_speed, &m_joints, &m_vehicle, &m_hekto, &m_fouling, &m_parallel}; void infra_rebase(); void render_infra_search(); diff --git a/application/editormodeparallel.cpp b/application/editormodeparallel.cpp index 7fb5b893..5180560c 100644 --- a/application/editormodeparallel.cpp +++ b/application/editormodeparallel.cpp @@ -8,8 +8,7 @@ http://mozilla.org/MPL/2.0/. */ #include "stdafx.h" -#include "application/editormode.h" -#include "application/editoruilayer.h" +#include "application/editormodeparallel.h" #include "application/editorprojection.h" #include "application/editormodeshared.h" #include "editor/editorFormat.hpp" @@ -209,21 +208,23 @@ double lateral_of(TTrack const &Src, TTrack const &Dst) } // namespace -TTrack *editor_mode::parallel_source() const +TTrack *parallel_tool::parallel_source() const { - if (m_track_set.size() >= 2) - return m_track_set.front(); - return selected_track(); + auto const &set{m_services.track_set()}; + if (set.size() >= 2) + return set.front(); + return m_services.selected_track(); } -TTrack *editor_mode::parallel_target() const +TTrack *parallel_tool::parallel_target() const { - if (m_track_set.size() != 2) + auto const &set{m_services.track_set()}; + if (set.size() != 2) return nullptr; - return m_track_set.back() != m_track_set.front() ? m_track_set.back() : nullptr; + return set.back() != set.front() ? set.back() : nullptr; } -void editor_mode::parallel_update() +void parallel_tool::parallel_update() { auto &tool{m_parallel}; auto *track{parallel_source()}; @@ -244,13 +245,13 @@ void editor_mode::parallel_update() else if (track != nullptr && target != nullptr) tool.measured = std::abs(lateral_of(*track, *target)); - if (track == tool.built_for && tool.spacing == tool.built_spacing && tool.side == tool.built_side && tool.scope == tool.built_scope && m_history.size() == tool.built_history) + if (track == tool.built_for && tool.spacing == tool.built_spacing && tool.side == tool.built_side && tool.scope == tool.built_scope && m_services.history_size() == tool.built_history) return; tool.built_for = track; tool.built_spacing = tool.spacing; tool.built_side = tool.side; tool.built_scope = tool.scope; - tool.built_history = m_history.size(); + tool.built_history = m_services.history_size(); tool.pieces.clear(); tool.styles.clear(); tool.length = 0.0; @@ -319,7 +320,7 @@ void editor_mode::parallel_update() } } -void editor_mode::parallel_build() +void parallel_tool::parallel_build() { auto &tool{m_parallel}; parallel_update(); @@ -329,8 +330,8 @@ void editor_mode::parallel_build() for (std::size_t i = 0; i < tool.pieces.size(); ++i) created.push_back(editor_track::create_path(*tool.styles[i], tool.pieces[i])); editor_track::commit(created); - digitize_drawn(created); - push_track_snapshot({}, created); + m_services.digitize_drawn(created); + m_services.push_track_snapshot({}, created); tool.status = format(STR_C("Parallel track of %zu paths, %.1f m, %.2f m away; Ctrl+Z takes it back"), created.size(), tool.length, tool.spacing); if (scene::Layers.active() == null_handle) tool.status += "\n" + std::string{STR_C("The scenery isn't opened for editing, the new track won't be saved")}; @@ -338,7 +339,7 @@ void editor_mode::parallel_build() tool.built_for = nullptr; } -void editor_mode::parallel_apply() +void parallel_tool::parallel_apply() { auto &tool{m_parallel}; auto *target{parallel_target()}; @@ -375,14 +376,14 @@ void editor_mode::parallel_apply() if (joint.other != nullptr) committed.push_back(joint.other); editor_track::commit(committed); - push_track_snapshot(std::move(states)); + m_services.push_track_snapshot(std::move(states)); tool.status = format(STR_C("%s set parallel to %s, %.2f m away; Ctrl+Z takes it back"), name_of(*target).c_str(), name_of(*parallel_source()).c_str(), tool.spacing); WriteLog("Editor: " + tool.status, logtype::generic); tool.built_for = nullptr; - straight_refresh(); + m_services.straight_refresh(); } -void editor_mode::render_parallel_controls(bool const Scope) +void parallel_tool::render_parallel_controls(bool const Scope) { auto &tool{m_parallel}; if (Scope) @@ -396,7 +397,7 @@ void editor_mode::render_parallel_controls(bool const Scope) value_chips("spacings", tool.spacing, {kSpacings[0], kSpacings[1], kSpacings[2], kSpacings[3], kSpacings[4], kSpacings[5]}, "%.2f"); } -void editor_mode::render_parallel_ui() +void parallel_tool::render_options() { auto &tool{m_parallel}; ImGui::PushTextWrapPos(0.0f); @@ -426,7 +427,7 @@ void editor_mode::render_parallel_ui() ImGui::TextWrapped("%s", tool.status.c_str()); } -void editor_mode::render_parallel_set_ui() +void parallel_tool::render_set_options() { auto &tool{m_parallel}; auto *source{parallel_source()}; @@ -450,16 +451,16 @@ void editor_mode::render_parallel_set_ui() ImGui::TextWrapped("%s", tool.status.c_str()); } -bool editor_mode::parallel_preview_visible() const +bool parallel_tool::parallel_preview_visible() const { if (m_parallel.pieces.empty() || parallel_source() != m_parallel.built_for) return false; - if (m_track_tab == track_tab::parallel) + if (m_services.current_track_tab() == editor_track_tab::parallel) return true; - return m_track_tab == track_tab::path && parallel_target() != nullptr; + return m_services.current_track_tab() == editor_track_tab::path && parallel_target() != nullptr; } -void editor_mode::draw_parallel_preview() const +void parallel_tool::draw_overlay() const { if (false == parallel_preview_visible()) return; @@ -488,3 +489,17 @@ void editor_mode::draw_parallel_preview() const drawlist->AddText(ImVec2(screen.x + 12.0f, screen.y - 8.0f), IM_COL32(90, 255, 120, 255), label.c_str()); } } + +editor_selftest_result parallel_tool::selftest(std::string const &Command, std::istringstream &Words) +{ + if (Command == "parallel") + { + Words >> m_parallel.spacing >> m_parallel.side; + m_parallel.scope = 1; + m_parallel.built_for = nullptr; + parallel_build(); + WriteLog("SELFTEST parallel: " + m_parallel.status + " " + m_parallel.error); + return editor_selftest_result::handled; + } + return editor_selftest_result::unhandled; +} diff --git a/application/editormodeparallel.h b/application/editormodeparallel.h new file mode 100644 index 00000000..f221c6f4 --- /dev/null +++ b/application/editormodeparallel.h @@ -0,0 +1,58 @@ +/* +This Source Code Form is subject to the +terms of the Mozilla Public License, v. +2.0. If a copy of the MPL was not +distributed with this file, You can +obtain one at +http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +#include "application/editortool.h" + +#include +#include + +// second track alongside the selected path or the line through it, at a spacing, curves included +class parallel_tool final : public editor_tool +{ + public: + explicit parallel_tool(editor_services &Services) : m_services{Services} {} + void draw_overlay() const override; + void render_options() override; + editor_selftest_result selftest(std::string const &Command, std::istringstream &Words) override; + tool_tab &tab() { return m_tab; } + void render_set_options(); + + private: + editor_services &m_services; + tool_tab m_tab; + struct parallel_state + { + double spacing{4.0}; + int side{1}; // 1: to the right, -1: to the left, of the direction of the line + int scope{1}; // 0: the selected path, 1: the line through it, up to the switches + TTrack *built_for{nullptr}; + double built_spacing{0.0}; + int built_side{0}; + int built_scope{-1}; + std::size_t built_history{0}; + TTrack *pair_src{nullptr}; + TTrack *pair_dst{nullptr}; + double measured{0.0}; + std::vector pieces; + std::vector styles; + double length{0.0}; + std::string error; + std::string status; + }; + parallel_state m_parallel; + TTrack *parallel_source() const; + TTrack *parallel_target() const; + void parallel_update(); + void render_parallel_controls(bool const Scope = true); + void parallel_build(); + void parallel_apply(); + bool parallel_preview_visible() const; +}; diff --git a/application/editormodeselftestsweep.cpp b/application/editormodeselftestsweep.cpp index fd37edb9..38289631 100644 --- a/application/editormodeselftestsweep.cpp +++ b/application/editormodeselftestsweep.cpp @@ -284,7 +284,7 @@ editor_mode::selftest_result editor_mode::selftest_sweep(std::string const &comm std::string tab; words >> tab; show_track_tab(tab == "parallel" ? track_tab::parallel : track_tab::lineside); - (tab == "vehicle" ? m_vehicle.tab().expand : tab == "hekto" ? m_hekto.tab().expand : tab == "fouling" ? m_fouling.tab().expand : m_parallel.expand) = true; + (tab == "vehicle" ? m_vehicle.tab().expand : tab == "hekto" ? m_hekto.tab().expand : tab == "fouling" ? m_fouling.tab().expand : m_parallel.tab().expand) = true; return selftest_result::handled; } if (command == "bendpanel") diff --git a/application/editormodeselftesttrack.cpp b/application/editormodeselftesttrack.cpp index 7c1c5eac..c1182d20 100644 --- a/application/editormodeselftesttrack.cpp +++ b/application/editormodeselftesttrack.cpp @@ -141,7 +141,7 @@ editor_mode::selftest_result editor_mode::selftest_track(std::string const &comm m_sweep.expand = tab == 0; m_hekto.tab().expand = tab == 1; m_fouling.tab().expand = tab == 2; - m_parallel.expand = tab == 3; + m_parallel.tab().expand = tab == 3; m_vehicle.tab().expand = tab == 4; return selftest_result::handled; } @@ -782,14 +782,5 @@ editor_mode::selftest_result editor_mode::selftest_track(std::string const &comm WriteLog(format("SELFTEST digitize %s: %d", nearest != nullptr ? nearest->name().c_str() : "-", kept ? 1 : 0)); return selftest_result::handled; } - if (command == "parallel") - { - words >> m_parallel.spacing >> m_parallel.side; - m_parallel.scope = 1; - m_parallel.built_for = nullptr; - parallel_build(); - WriteLog("SELFTEST parallel: " + m_parallel.status + " " + m_parallel.error); - return selftest_result::handled; - } return selftest_result::unhandled; } diff --git a/application/editormodetrack.cpp b/application/editormodetrack.cpp index c1a4fcf3..e9ada20f 100644 --- a/application/editormodetrack.cpp +++ b/application/editormodetrack.cpp @@ -72,6 +72,16 @@ editor_mode::track_hover const &editor_mode::hovered_track() const return m_hover; } +std::vector const &editor_mode::track_set() const +{ + return m_track_set; +} + +editor_track_tab editor_mode::current_track_tab() const +{ + return m_track_tab; +} + void editor_mode::set_current_node(scene::basic_node *Node) { m_node = Node; @@ -558,7 +568,7 @@ void editor_mode::render_track_inspector() m_sweep.open = false; m_hekto.tab().open = false; m_fouling.tab().open = false; - m_parallel.open = false; + m_parallel.tab().open = false; m_vehicle.tab().open = false; } ui()->set_track(m_track_window_open); @@ -611,7 +621,7 @@ void editor_mode::render_track_tool_options() render_lay_ui(); break; case track_tab::parallel: - render_parallel_ui(); + m_parallel.render_options(); break; case track_tab::turnout: if (track != nullptr && track->eType == tt_Switch) diff --git a/application/editormodetrackux.cpp b/application/editormodetrackux.cpp index 21629482..238b0cfe 100644 --- a/application/editormodetrackux.cpp +++ b/application/editormodetrackux.cpp @@ -1355,7 +1355,7 @@ void editor_mode::render_track_set_ui() ImGui::PushTextWrapPos(0.0f); ImGui::TextDisabled("%s", STR_C("Their properties are in the inspector, the gizmo moves them together")); ImGui::PopTextWrapPos(); - render_parallel_set_ui(); + m_parallel.render_set_options(); ImGui::Separator(); } diff --git a/application/editortool.h b/application/editortool.h index 791d7424..fd110f91 100644 --- a/application/editortool.h +++ b/application/editortool.h @@ -92,6 +92,8 @@ class editor_services virtual std::size_t history_size() const = 0; virtual glm::dvec3 camera_position() const = 0; virtual track_hover const &hovered_track() const = 0; + virtual std::vector const &track_set() const = 0; + virtual editor_track_tab current_track_tab() const = 0; virtual void first_step_done(editor_first_step const Step) = 0; virtual void show_track_tab(editor_track_tab const Wanted) = 0; virtual glm::dvec3 placement_on_ground(glm::dvec3 Location) = 0; @@ -109,6 +111,8 @@ class editor_services virtual std::size_t place_templates(std::vector const &Items, std::string &Error) = 0; virtual std::size_t move_templates(std::vector> const &Moves) = 0; virtual std::size_t remove_templates(std::vector const &Instances) = 0; + virtual bool digitize_drawn(std::vector const &Created, bool const Alone = true) = 0; + virtual void straight_refresh() = 0; virtual void push_track_snapshot(std::vector> States, std::vector Created = {}, std::vector Removed = {}) = 0; protected: