diff --git a/application/editormode.h b/application/editormode.h index ea8a680a..86e8b72d 100644 --- a/application/editormode.h +++ b/application/editormode.h @@ -2236,13 +2236,13 @@ class editor_mode : public application_mode, private editor_track::observer, pri void infra_attach(EditorSnapshot &Snapshot); void render_infra_body(); - gauge_tool m_gauge{*this}; - speed_tool m_speed{*this}; - joints_tool m_joints{*this}; - vehicle_tool m_vehicle{*this}; - hekto_tool m_hekto{*this}; - fouling_tool m_fouling{*this}; - parallel_tool m_parallel{*this}; + gauge_tool m_gauge{*this, *this, *this, *this}; + speed_tool m_speed{*this, *this, *this, *this}; + joints_tool m_joints{*this, *this, *this, *this}; + vehicle_tool m_vehicle{*this, *this}; + hekto_tool m_hekto{*this, *this, *this, *this, *this, *this}; + fouling_tool m_fouling{*this, *this, *this, *this, *this}; + parallel_tool m_parallel{*this, *this, *this, *this}; std::vector m_tools{&m_gauge, &m_speed, &m_joints, &m_vehicle, &m_hekto, &m_fouling, &m_parallel}; void infra_rebase(); diff --git a/application/editormodegauge.cpp b/application/editormodegauge.cpp index 4c2f2187..4260033f 100644 --- a/application/editormodegauge.cpp +++ b/application/editormodegauge.cpp @@ -591,9 +591,9 @@ void gauge_tool::update() m_gauge.published = false; return; } - auto *track{m_gauge.enabled ? m_services.selected_track() : nullptr}; + auto *track{m_gauge.enabled ? m_selection.selected_track() : nullptr}; // the geometry is rescanned once the edit ends - if (ImGui::IsMouseDown(0) || m_services.track_editing()) + if (ImGui::IsMouseDown(0) || m_design.track_editing()) m_gauge.pending = true; else if (track == nullptr) { @@ -604,15 +604,15 @@ void gauge_tool::update() m_gauge.published = false; } } - else if (track != m_gauge.track || m_services.history_size() != m_gauge.history || m_gauge.pending) + else if (track != m_gauge.track || m_history.history_size() != m_gauge.history || m_gauge.pending) { m_gauge.track = track; - m_gauge.history = m_services.history_size(); + m_gauge.history = m_history.history_size(); m_gauge.pending = false; scan_gauge(*track); m_gauge.published = false; } - if (false == m_gauge.published || glm::distance(m_services.camera_position(), EditorOverlay.origin) > gauge_origin_range) + if (false == m_gauge.published || glm::distance(m_view.camera_position(), EditorOverlay.origin) > gauge_origin_range) gauge_publish(); } @@ -645,7 +645,7 @@ void gauge_tool::scan_gauge_map() scan->space.emplace(scan->lines); m_gauge.map = {}; m_gauge.map.scanned = true; - m_gauge.map.history = m_services.history_size(); + m_gauge.map.history = m_history.history_size(); auto const name{[](gauge::profile const *Profile) { return Profile != nullptr ? Profile->name : std::string{"-"}; }}; m_gauge.map.profile = name(chosen.railway) + ", " + name(chosen.road); m_gauge.current = -1; @@ -695,7 +695,7 @@ void gauge_tool::gauge_publish() { m_gauge.published = true; EditorOverlay.clear(); - EditorOverlay.origin = m_services.camera_position(); + EditorOverlay.origin = m_view.camera_position(); auto const batch{[](glm::vec4 const &Color, unsigned int const Type, std::vector const &Points) { gfx::editor_overlay::batch result{Color, Type}; result.points.reserve(Points.size()); @@ -730,9 +730,9 @@ void gauge_tool::gauge_focus(int const Index) // along the track, tangent to the gauge at the height of the place, from the end nearer to the camera glm::dvec3 look{hit.direction.x, 0.0, hit.direction.y}; look = glm::length(look) > 1e-6 ? glm::normalize(look) : glm::dvec3(0.0, 0.0, 1.0); - if (glm::dot(m_services.camera_position() - hit.point, look) > 0.0) + if (glm::dot(m_view.camera_position() - hit.point, look) > 0.0) look = -look; - m_services.fly_to(hit.point, look, gauge_view_distance); + m_view.fly_to(hit.point, look, gauge_view_distance); } void gauge_tool::gauge_spot(gauge_hit const &Hit) @@ -799,7 +799,7 @@ void gauge_tool::render_windows() m_gauge.current = -1; m_gauge.published = false; } - else if (m_gauge.map.history != m_services.history_size()) + else if (m_gauge.map.history != m_history.history_size()) ImGui::TextColored(ImVec4(1.0f, 0.75f, 0.3f, 1.0f), STR_C("The scenery changed since the scan (%s)"), m_gauge.map.profile.c_str()); } render_gauge_hits(); diff --git a/application/editormodegauge.h b/application/editormodegauge.h index 7e39d8d1..0f0507bb 100644 --- a/application/editormodegauge.h +++ b/application/editormodegauge.h @@ -29,7 +29,7 @@ class gauge_tool final : public editor_tool int path{0}; glm::dvec2 direction{0.0, 1.0}; // of the track there, in the plan }; - explicit gauge_tool(editor_services &Services) : m_services{Services} {} + gauge_tool(editor_selection &Selection, editor_view &View, editor_history &History, editor_track_design &Design) : m_selection{Selection}, m_view{View}, m_history{History}, m_design{Design} {} void update() override; void render_windows() override; editor_selftest_result selftest(std::string const &Command, std::istringstream &Words) override; @@ -37,7 +37,10 @@ class gauge_tool final : public editor_tool void toggle() { m_gauge.open = !m_gauge.open; } private: - editor_services &m_services; + editor_selection &m_selection; + editor_view &m_view; + editor_history &m_history; + editor_track_design &m_design; // structure gauge along the line of the selected path, shown in the 3d view struct gauge_state { diff --git a/application/editormodejoints.cpp b/application/editormodejoints.cpp index 5177de0e..a9afd279 100644 --- a/application/editormodejoints.cpp +++ b/application/editormodejoints.cpp @@ -164,7 +164,7 @@ void joints_tool::joints_start() continue; state.queue.push_back(track); } - state.history = m_services.history_size(); + state.history = m_history.history_size(); state.places.clear(); state.runs.clear(); state.run_next = 0; @@ -174,14 +174,14 @@ void joints_tool::joints_start() state.model_unplaced = false; if (false == state.model_check || state.queue.empty()) return; - m_services.nmt_locate(); - if (false == m_services.terrain_model().placed()) + m_ground.nmt_locate(); + if (false == m_ground.terrain_model().placed()) { state.model_unplaced = true; return; } std::set const queued(state.queue.begin(), state.queue.end()); - for (auto const &place : m_services.nmt_track_places(kModelStep)) + for (auto const &place : m_ground.nmt_track_places(kModelStep)) if (place.shapes && queued.count(place.track) > 0) { if (state.places.empty() || state.places.back().track != place.track || state.places.back().path != place.path || state.places.size() - state.runs.back().first >= kModelRun) @@ -216,27 +216,27 @@ bool joints_tool::joints_model() for (auto const &run : state.runs) { box(run, low, high); - m_services.terrain_model().request(low, high); + m_ground.terrain_model().request(low, high); } state.model_asked = true; } while (state.run_next < state.runs.size()) { box(state.runs[state.run_next], low, high); - if (false == m_services.terrain_model().request(low, high)) + if (false == m_ground.terrain_model().request(low, high)) return false; ++state.run_next; } std::vector differences(state.places.size(), std::numeric_limits::quiet_NaN()); std::vector known; for (std::size_t i = 0; i < state.places.size(); ++i) - if (double height; m_services.terrain_model().height(state.places[i].position.x, state.places[i].position.z, height)) + if (double height; m_ground.terrain_model().height(state.places[i].position.x, state.places[i].position.z, height)) { - differences[i] = state.places[i].crown - (height + m_services.terrain_model_offset()); + differences[i] = state.places[i].crown - (height + m_ground.terrain_model_offset()); known.push_back(differences[i]); } auto shift{0.0}; - if (false == m_services.terrain_model_fitted() && false == known.empty()) + if (false == m_ground.terrain_model_fitted() && false == known.empty()) { std::nth_element(known.begin(), known.begin() + known.size() / 2, known.end()); if (std::abs(known[known.size() / 2]) > kUnfitted) @@ -411,9 +411,9 @@ void joints_tool::joints_focus(int const Index) auto const &paths{simulation::Paths.sequence()}; if (std::find(paths.begin(), paths.end(), issue.track) == paths.end() || issue.track->m_editorremoved) return; - m_services.set_current_node(issue.track); - m_services.clear_track_point(); - m_services.focus_track(*issue.track, issue.point.path, issue.position); + m_selection.set_current_node(issue.track); + m_selection.clear_track_point(); + m_view.focus_track(*issue.track, issue.point.path, issue.position); } bool joints_tool::joint_fix(joint_issue &Issue, std::vector> &States, std::vector &Changed) @@ -498,11 +498,11 @@ void joints_tool::joints_fix(std::vector const &Indices) state.status = STR_C("Nothing could be fixed: the paths are switches or in the files which can't be changed"); return; } - m_services.push_track_snapshot(std::move(states)); + m_history.push_track_snapshot(std::move(states)); editor_track::commit(changed); for (auto *track : changed) track->mark_dirty(); - state.history = m_services.history_size(); + state.history = m_history.history_size(); state.status = format(STR_C("%zu joints fixed, Ctrl+Z takes them back"), count); WriteLog("Editor: joints check - " + state.status, logtype::generic); } @@ -580,7 +580,7 @@ void joints_tool::render_options() ImGui::TextWrapped("%s", state.status.c_str()); if (state.issues.empty()) return; - if (state.history != m_services.history_size()) + if (state.history != m_history.history_size()) ImGui::TextColored(ImVec4(1.0f, 0.75f, 0.3f, 1.0f), "%s", STR_C("The scenery changed since the check")); int filter{state.filter + 1}; ImGui::SetNextItemWidth(150.0f); diff --git a/application/editormodejoints.h b/application/editormodejoints.h index 34dc5cbe..626846e7 100644 --- a/application/editormodejoints.h +++ b/application/editormodejoints.h @@ -31,7 +31,7 @@ class joints_tool final : public editor_tool double value{0.0}; // m, deg, mm, per mille; m of the track over the terrain model bool fixed{false}; }; - explicit joints_tool(editor_services &Services) : m_services{Services} {} + joints_tool(editor_selection &Selection, editor_view &View, editor_history &History, editor_ground &Ground) : m_selection{Selection}, m_view{View}, m_history{History}, m_ground{Ground} {} void update() override; void draw_overlay() const override; void render_options() override; @@ -40,7 +40,10 @@ class joints_tool final : public editor_tool double kink_angle() const { return m_joints.angle; } private: - editor_services &m_services; + editor_selection &m_selection; + editor_view &m_view; + editor_history &m_history; + editor_ground &m_ground; // joints of the paths: ends which almost meet, steps, kinks, jumps of the cant and of the grade struct joints_state { diff --git a/application/editormodelineside.cpp b/application/editormodelineside.cpp index f6de2967..56e93528 100644 --- a/application/editormodelineside.cpp +++ b/application/editormodelineside.cpp @@ -421,10 +421,10 @@ void hekto_tool::hekto_read_kilometrage() void hekto_tool::hekto_update() { auto &tool{m_hekto}; - if (false == tool.dirty && tool.history == m_services.history_size()) + if (false == tool.dirty && tool.history == m_history.history_size()) return; tool.dirty = false; - tool.history = m_services.history_size(); + tool.history = m_history.history_size(); tool.posts.clear(); tool.found.clear(); tool.error.clear(); @@ -449,7 +449,7 @@ void hekto_tool::hekto_update() double distance; tool.origin = project(tool.samples, tool.point, distance); auto const length{tool.samples.back().chainage}; - for (auto const &standing : m_services.standing_templates([](std::string const &File) { return File.find("hekto") != std::string::npos; })) + for (auto const &standing : m_templates.standing_templates([](std::string const &File) { return File.find("hekto") != std::string::npos; })) { hekto_found post; post.post = standing; @@ -488,7 +488,7 @@ void hekto_tool::hekto_update() // alternately: the even hectometres on the right, the odd ones on the left of the growing kilometrage auto const side{tool.side != 0 ? tool.side : (hectometres % 2 == 0 ? 1 : -1)}; auto const planar{plan_of(axis) + left * (side * tool.offset)}; - post.position = m_services.placement_on_ground({planar.x, axis.y, planar.y}); + post.position = m_ground.placement_on_ground({planar.x, axis.y, planar.y}); post.yaw = std::fmod(heading_of(growing) + tool.turn, 360.0); // of the posts with this number the one nearest to the place stands for it, the others are duplicates. it stands wrong // when it's farther from the place than allowed: along the line, across it, or on the other side @@ -526,7 +526,7 @@ void hekto_tool::hekto_remove_duplicates() for (auto const &found : tool.found) if (found.duplicate) instances.push_back(found.post.instance); - auto const removed{m_services.remove_templates(instances)}; + auto const removed{m_templates.remove_templates(instances)}; tool.status = format(STR_P("%zu duplicate hectometre post removed, Ctrl+Z brings it back", "%zu duplicate hectometre posts removed, Ctrl+Z brings them back", static_cast(removed)), removed); WriteLog("Editor: " + tool.status); tool.dirty = true; @@ -549,10 +549,10 @@ void hekto_tool::hekto_place() items.push_back(std::move(item)); } std::string error; - auto const placed{m_services.place_templates(items, error)}; + auto const placed{m_templates.place_templates(items, error)}; tool.status = placed > 0 ? format(STR_P("%zu hectometre post placed, Ctrl+Z takes it back", "%zu hectometre posts placed, Ctrl+Z takes them back", static_cast(placed)), placed) : error; if (placed > 0) - m_services.first_step_done(editor_first_step::posts); + m_guide.first_step_done(editor_first_step::posts); WriteLog("Editor: " + tool.status, logtype::generic); tool.dirty = true; } @@ -571,7 +571,7 @@ void hekto_tool::hekto_fix() item.yaw = post.yaw; moves.emplace_back(tool.found[post.standing].post, item); } - auto const moved{m_services.move_templates(moves)}; + auto const moved{m_templates.move_templates(moves)}; tool.status = format(STR_P("%zu hectometre post moved to its place, Ctrl+Z takes it back", "%zu hectometre posts moved to their places, Ctrl+Z takes it back", static_cast(moved)), moved); WriteLog("Editor: " + tool.status, logtype::generic); tool.dirty = true; @@ -580,7 +580,7 @@ void hekto_tool::hekto_fix() void hekto_tool::render_options() { auto &tool{m_hekto}; - auto *selected{m_services.selected_track()}; + auto *selected{m_selection.selected_track()}; if (tool.track == nullptr || (selected != nullptr && selected != tool.track && ImGui::SmallButton(STR_C("Along the line of the selected path")))) { if (selected == nullptr) @@ -679,7 +679,7 @@ void hekto_tool::render_options() auto const label{post.duplicate ? format(STR_C("km %s duplicate##%u"), km_text(post.hectometres).c_str(), post.post.instance) : format(STR_C("km %s stands %.1f m from its place##%u"), km_text(post.hectometres).c_str(), post.distance, post.post.instance)}; if (ImGui::Selectable(label.c_str())) { - m_services.fly_to(post.post.location, glm::normalize(glm::dvec3{-1.0, -0.8, -1.0}), 20.0); + m_view.fly_to(post.post.location, glm::normalize(glm::dvec3{-1.0, -0.8, -1.0}), 20.0); } } ImGui::EndChild(); @@ -735,13 +735,13 @@ void hekto_tool::draw_overlay() const void fouling_tool::fouling_update() { auto &tool{m_fouling}; - auto *selected{m_services.selected_track()}; + auto *selected{m_selection.selected_track()}; if (tool.scope == 0 && selected != tool.selected) tool.dirty = true; - if (false == tool.dirty && tool.history == m_services.history_size()) + if (false == tool.dirty && tool.history == m_history.history_size()) return; tool.dirty = false; - tool.history = m_services.history_size(); + tool.history = m_history.history_size(); tool.selected = selected; tool.points.clear(); tool.found.clear(); @@ -792,7 +792,7 @@ void fouling_tool::fouling_update() point.track = track; auto const middle{(onbranch + onmain) * 0.5}; // the points of the paths are at the rail foot, the heads of the rails are the height of the rail over them - point.position = tool.height_mode == 1 ? glm::dvec3{middle.x, 0.5 * (onbranch.y + onmain.y) + kRailHeight + tool.height, middle.z} : m_services.placement_on_ground({middle.x, std::max(onbranch.y, onmain.y), middle.z}); + point.position = tool.height_mode == 1 ? glm::dvec3{middle.x, 0.5 * (onbranch.y + onmain.y) + kRailHeight + tool.height, middle.z} : m_ground.placement_on_ground({middle.x, std::max(onbranch.y, onmain.y), middle.z}); auto const back{plan_of(previous - branch[i])}; point.yaw = std::fmod(heading_of(glm::length(back) > 1e-9 ? glm::normalize(back) : glm::dvec2{0.0, 1.0}) + tool.turn, 360.0); tool.points.push_back(point); @@ -800,7 +800,7 @@ void fouling_tool::fouling_update() } } // markers standing: each goes to the nearest fouling point, the others are left alone - auto const markers{m_services.standing_templates([](std::string const &File) { return File.find("w17") != std::string::npos || File.find("ukres") != std::string::npos; })}; + auto const markers{m_templates.standing_templates([](std::string const &File) { return File.find("w17") != std::string::npos || File.find("ukres") != std::string::npos; })}; for (auto const &marker : markers) { int nearest{-1}; @@ -857,7 +857,7 @@ void fouling_tool::place(int const Only) items.push_back(std::move(item)); } std::string error; - auto const placed{m_services.place_templates(items, error)}; + auto const placed{m_templates.place_templates(items, error)}; tool.status = placed > 0 ? format(STR_P("%zu fouling point marker placed, Ctrl+Z takes it back", "%zu fouling point markers placed, Ctrl+Z takes them back", static_cast(placed)), placed) : error; WriteLog("Editor: " + tool.status, logtype::generic); tool.dirty = true; @@ -888,7 +888,7 @@ void fouling_tool::fix(int const Only) } moves.emplace_back(found.marker, item); } - auto const moved{m_services.move_templates(moves)}; + auto const moved{m_templates.move_templates(moves)}; tool.status = format(STR_P("%zu fouling point marker moved to its place, Ctrl+Z takes it back", "%zu fouling point markers moved to their places, Ctrl+Z takes it back", static_cast(moved)), moved); WriteLog("Editor: " + tool.status, logtype::generic); tool.dirty = true; @@ -971,7 +971,7 @@ void fouling_tool::render_options() place(i); ImGui::SameLine(); if (ImGui::Selectable(format(STR_C("%s: no W17"), point.track->name().c_str()).c_str())) - m_services.fly_to(point.position, look, 25.0); + m_view.fly_to(point.position, look, 25.0); ImGui::PopID(); } for (int i = 0; i < static_cast(tool.found.size()); ++i) @@ -984,7 +984,7 @@ void fouling_tool::render_options() fix(i); ImGui::SameLine(); if (ImGui::Selectable(format(STR_C("%s: W17 %.1f m off, %+.2f m high"), tool.points[found.point].track->name().c_str(), found.error, found.height_error).c_str())) - m_services.fly_to(found.marker.location, look, 25.0); + m_view.fly_to(found.marker.location, look, 25.0); ImGui::PopID(); } ImGui::EndChild(); @@ -1146,7 +1146,7 @@ editor_selftest_result fouling_tool::selftest(std::string const &Command, std::i auto &tool{m_fouling}; if (values["show"] == "1") { - m_services.show_track_tab(editor_track_tab::lineside); + m_view.show_track_tab(editor_track_tab::lineside); m_tab.expand = true; } tool.scope = std::stoi(values.count("scope") ? values["scope"] : "2"); diff --git a/application/editormodelineside.h b/application/editormodelineside.h index d007cd54..d7b23606 100644 --- a/application/editormodelineside.h +++ b/application/editormodelineside.h @@ -20,7 +20,7 @@ http://mozilla.org/MPL/2.0/. class hekto_tool final : public editor_tool { public: - explicit hekto_tool(editor_services &Services) : m_services{Services} {} + hekto_tool(editor_selection &Selection, editor_view &View, editor_history &History, editor_templates &Templates, editor_ground &Ground, editor_guide &Guide) : m_selection{Selection}, m_view{View}, m_history{History}, m_templates{Templates}, m_ground{Ground}, m_guide{Guide} {} void draw_overlay() const override; void render_options() override; editor_selftest_result selftest(std::string const &Command, std::istringstream &Words) override; @@ -28,7 +28,12 @@ class hekto_tool final : public editor_tool void start(TTrack &Track, glm::dvec3 const &Point); private: - editor_services &m_services; + editor_selection &m_selection; + editor_view &m_view; + editor_history &m_history; + editor_templates &m_templates; + editor_ground &m_ground; + editor_guide &m_guide; tool_tab m_tab; struct hekto_post { @@ -85,7 +90,7 @@ class hekto_tool final : public editor_tool class fouling_tool final : public editor_tool { public: - explicit fouling_tool(editor_services &Services) : m_services{Services} {} + fouling_tool(editor_selection &Selection, editor_view &View, editor_history &History, editor_templates &Templates, editor_ground &Ground) : m_selection{Selection}, m_view{View}, m_history{History}, m_templates{Templates}, m_ground{Ground} {} void draw_overlay() const override; void render_options() override; editor_selftest_result selftest(std::string const &Command, std::istringstream &Words) override; @@ -101,7 +106,11 @@ class fouling_tool final : public editor_tool void check_selected_switch(); private: - editor_services &m_services; + editor_selection &m_selection; + editor_view &m_view; + editor_history &m_history; + editor_templates &m_templates; + editor_ground &m_ground; tool_tab m_tab; struct fouling_point { diff --git a/application/editormodeparallel.cpp b/application/editormodeparallel.cpp index 5180560c..f5ac7c5d 100644 --- a/application/editormodeparallel.cpp +++ b/application/editormodeparallel.cpp @@ -210,15 +210,15 @@ double lateral_of(TTrack const &Src, TTrack const &Dst) TTrack *parallel_tool::parallel_source() const { - auto const &set{m_services.track_set()}; + auto const &set{m_selection.track_set()}; if (set.size() >= 2) return set.front(); - return m_services.selected_track(); + return m_selection.selected_track(); } TTrack *parallel_tool::parallel_target() const { - auto const &set{m_services.track_set()}; + auto const &set{m_selection.track_set()}; if (set.size() != 2) return nullptr; return set.back() != set.front() ? set.back() : nullptr; @@ -245,13 +245,13 @@ void parallel_tool::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_services.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_history.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_services.history_size(); + tool.built_history = m_history.history_size(); tool.pieces.clear(); tool.styles.clear(); tool.length = 0.0; @@ -330,8 +330,8 @@ void parallel_tool::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); - m_services.digitize_drawn(created); - m_services.push_track_snapshot({}, created); + m_design.digitize_drawn(created); + m_history.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")}; @@ -376,11 +376,11 @@ void parallel_tool::parallel_apply() if (joint.other != nullptr) committed.push_back(joint.other); editor_track::commit(committed); - m_services.push_track_snapshot(std::move(states)); + m_history.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; - m_services.straight_refresh(); + m_design.straight_refresh(); } void parallel_tool::render_parallel_controls(bool const Scope) @@ -455,9 +455,9 @@ bool parallel_tool::parallel_preview_visible() const { if (m_parallel.pieces.empty() || parallel_source() != m_parallel.built_for) return false; - if (m_services.current_track_tab() == editor_track_tab::parallel) + if (m_view.current_track_tab() == editor_track_tab::parallel) return true; - return m_services.current_track_tab() == editor_track_tab::path && parallel_target() != nullptr; + return m_view.current_track_tab() == editor_track_tab::path && parallel_target() != nullptr; } void parallel_tool::draw_overlay() const diff --git a/application/editormodeparallel.h b/application/editormodeparallel.h index f221c6f4..d10ef41b 100644 --- a/application/editormodeparallel.h +++ b/application/editormodeparallel.h @@ -18,7 +18,7 @@ http://mozilla.org/MPL/2.0/. class parallel_tool final : public editor_tool { public: - explicit parallel_tool(editor_services &Services) : m_services{Services} {} + parallel_tool(editor_selection &Selection, editor_view &View, editor_history &History, editor_track_design &Design) : m_selection{Selection}, m_view{View}, m_history{History}, m_design{Design} {} void draw_overlay() const override; void render_options() override; editor_selftest_result selftest(std::string const &Command, std::istringstream &Words) override; @@ -26,7 +26,10 @@ class parallel_tool final : public editor_tool void render_set_options(); private: - editor_services &m_services; + editor_selection &m_selection; + editor_view &m_view; + editor_history &m_history; + editor_track_design &m_design; tool_tab m_tab; struct parallel_state { diff --git a/application/editormodespeed.cpp b/application/editormodespeed.cpp index 583c489f..c033d9cd 100644 --- a/application/editormodespeed.cpp +++ b/application/editormodespeed.cpp @@ -51,14 +51,14 @@ void speed_tool::speed_start() state.results.clear(); state.selected = -1; state.status.clear(); - state.options.norms = m_services.route_norms(); + state.options.norms = m_design.route_norms(); auto const add = [&](TTrack *Track) { for (int i = 0; i < static_cast(Track->m_paths.size()); ++i) state.queue.emplace_back(Track, i); }; if (state.scope == 0) { - auto *track{m_services.selected_track()}; + auto *track{m_selection.selected_track()}; if (track == nullptr || false == rail(*track)) { state.status = STR_C("Select a track first"); @@ -87,7 +87,7 @@ void speed_tool::speed_start() if (track != nullptr && rail(*track)) add(track); } - state.history = m_services.history_size(); + state.history = m_history.history_size(); } void speed_tool::update() @@ -145,8 +145,8 @@ void speed_tool::speed_focus(int const Index) auto const &paths{simulation::Paths.sequence()}; if (std::find(paths.begin(), paths.end(), verdict.track) == paths.end() || verdict.track->m_editorremoved) return; - m_services.set_current_node(verdict.track); - m_services.focus_track(*verdict.track, verdict.path, verdict.position); + m_selection.set_current_node(verdict.track); + m_view.focus_track(*verdict.track, verdict.path, verdict.position); } void speed_tool::speed_apply(std::vector const &Indices, bool const Branches) @@ -189,7 +189,7 @@ void speed_tool::speed_apply(std::vector const &Indices, bool const Branche state.status = STR_C("Nothing changed") + skipped; return; } - m_services.push_track_snapshot(std::move(states)); + m_history.push_track_snapshot(std::move(states)); for (auto const &entry : changes) { auto const velocity{entry.track->eType == tt_Switch ? speed_check::switch_velocity(entry.limits[0], entry.limits[1]) : entry.limits[0]}; @@ -198,7 +198,7 @@ void speed_tool::speed_apply(std::vector const &Indices, bool const Branche } for (auto &verdict : state.results) verdict.set = speed_check::path_velocity(*verdict.track, verdict.path); - state.history = m_services.history_size(); + state.history = m_history.history_size(); state.status = format(STR_C("Speed limits of %zu paths lowered to the safe ones, Ctrl+Z brings them back"), changes.size()) + skipped; WriteLog("Editor: speed check - " + state.status, logtype::generic); } @@ -262,7 +262,7 @@ void speed_tool::render_options() ImGui::TextWrapped("%s", state.status.c_str()); if (state.results.empty()) return; - if (state.history != m_services.history_size()) + if (state.history != m_history.history_size()) ImGui::TextColored(ImVec4(1.0f, 0.75f, 0.3f, 1.0f), STR_C("The scenery changed since the check")); auto const *const within{STR_C("Within their limits too")}; auto const checkbox{ImGui::GetFrameHeight() + ImGui::GetStyle().ItemInnerSpacing.x + ImGui::CalcTextSize(within).x}; diff --git a/application/editormodespeed.h b/application/editormodespeed.h index a477f59a..cafb8d21 100644 --- a/application/editormodespeed.h +++ b/application/editormodespeed.h @@ -19,7 +19,7 @@ http://mozilla.org/MPL/2.0/. class speed_tool final : public editor_tool { public: - explicit speed_tool(editor_services &Services) : m_services{Services} {} + speed_tool(editor_selection &Selection, editor_view &View, editor_history &History, editor_track_design &Design) : m_selection{Selection}, m_view{View}, m_history{History}, m_design{Design} {} void update() override; void draw_overlay() const override; void render_options() override; @@ -28,7 +28,10 @@ class speed_tool final : public editor_tool void check_line(); private: - editor_services &m_services; + editor_selection &m_selection; + editor_view &m_view; + editor_history &m_history; + editor_track_design &m_design; // speed limits of the paths checked against what their geometry allows struct speed_state { diff --git a/application/editormodevehicle.cpp b/application/editormodevehicle.cpp index daf22ceb..e83353f2 100644 --- a/application/editormodevehicle.cpp +++ b/application/editormodevehicle.cpp @@ -209,7 +209,7 @@ bool vehicle_tool::place() return false; } tool.placed = head; - m_services.first_step_done(editor_first_step::drive); + m_guide.first_step_done(editor_first_step::drive); auto const trackname{tool.track->name().empty() ? std::string{STR("(no name)")} : tool.track->name()}; auto const behind{static_cast(vehicles.size()) - 1}; tool.status = behind > 0 ? format(STR_P("%s and %d vehicle behind it stand on %s", "%s and %d vehicles behind it stand on %s", behind), head.c_str(), behind, trackname.c_str()) : format(STR_C("%s stands on %s"), head.c_str(), trackname.c_str()); @@ -240,8 +240,8 @@ bool vehicle_tool::place() void vehicle_tool::render_options() { auto &tool{m_vehicle}; - auto *selected{m_services.selected_track()}; - auto const &hover{m_services.hovered_track()}; + auto *selected{m_selection.selected_track()}; + auto const &hover{m_selection.hovered_track()}; if (selected != nullptr && selected == tool.track && hover.track == selected && ImGui::IsMouseClicked(0) && false == ImGui::GetIO().WantCaptureMouse) start(*selected, hover.point); else if (selected != nullptr && selected != tool.track) diff --git a/application/editormodevehicle.h b/application/editormodevehicle.h index 15b74c13..dabde1ce 100644 --- a/application/editormodevehicle.h +++ b/application/editormodevehicle.h @@ -27,7 +27,7 @@ struct skin_set; class vehicle_tool final : public editor_tool { public: - explicit vehicle_tool(editor_services &Services) : m_services{Services} {} + vehicle_tool(editor_selection &Selection, editor_guide &Guide) : m_selection{Selection}, m_guide{Guide} {} void draw_overlay() const override; void render_options() override; editor_selftest_result selftest(std::string const &Command, std::istringstream &Words) override; @@ -38,7 +38,8 @@ class vehicle_tool final : public editor_tool void trainsets_written(); private: - editor_services &m_services; + editor_selection &m_selection; + editor_guide &m_guide; tool_tab m_tab; struct vehicle_state { diff --git a/application/editortool.h b/application/editortool.h index fd110f91..19e301bf 100644 --- a/application/editortool.h +++ b/application/editortool.h @@ -84,37 +84,91 @@ struct nmt_place bool shapes{true}; // not a bridge nor a tunnel }; -class editor_services +class editor_selection { public: virtual TTrack *selected_track() const = 0; - virtual bool track_editing() const = 0; - 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; + virtual track_hover const &hovered_track() const = 0; + virtual void set_current_node(scene::basic_node *Node) = 0; + virtual void clear_track_point() = 0; + + protected: + ~editor_selection() = default; +}; + +class editor_view +{ + public: + virtual glm::dvec3 camera_position() const = 0; virtual void fly_to(glm::dvec3 const &Target, glm::dvec3 const &Look, double const Distance, double const Duration = 0.6) = 0; virtual void focus_track(TTrack &Track, int const Path, glm::dvec3 const &Point) = 0; - virtual void set_current_node(scene::basic_node *Node) = 0; - virtual alignment::limits const &route_norms() const = 0; - virtual void clear_track_point() = 0; + virtual editor_track_tab current_track_tab() const = 0; + virtual void show_track_tab(editor_track_tab const Wanted) = 0; + + protected: + ~editor_view() = default; +}; + +class editor_history +{ + public: + virtual std::size_t history_size() const = 0; + virtual void push_track_snapshot(std::vector> States, std::vector Created = {}, std::vector Removed = {}) = 0; + + protected: + ~editor_history() = default; +}; + +class editor_templates +{ + public: + virtual std::vector standing_templates(std::function const &Accept) const = 0; + 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; + + protected: + ~editor_templates() = default; +}; + +class editor_ground +{ + public: + virtual glm::dvec3 placement_on_ground(glm::dvec3 Location) = 0; virtual void nmt_locate() = 0; virtual std::vector nmt_track_places(double const Step) const = 0; virtual editor_nmt &terrain_model() = 0; virtual double terrain_model_offset() const = 0; virtual bool terrain_model_fitted() const = 0; - virtual std::vector standing_templates(std::function const &Accept) const = 0; - 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; + + protected: + ~editor_ground() = default; +}; + +class editor_track_design +{ + public: + virtual bool track_editing() const = 0; + virtual alignment::limits const &route_norms() const = 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: + ~editor_track_design() = default; +}; + +class editor_guide +{ + public: + virtual void first_step_done(editor_first_step const Step) = 0; + + protected: + ~editor_guide() = default; +}; + +class editor_services : public editor_selection, public editor_view, public editor_history, public editor_templates, public editor_ground, public editor_track_design, public editor_guide +{ protected: ~editor_services() = default; };