diff --git a/application/editormode.h b/application/editormode.h index 10d20e32..19114605 100644 --- a/application/editormode.h +++ b/application/editormode.h @@ -1593,6 +1593,16 @@ class editor_mode : public application_mode, private editor_track::observer, pri void draw_track_intent() const; editor_track::snap_target snap_free_end(glm::dvec3 const &Near, glm::vec2 const &Screen, TTrack const *Self, int const Category, std::vector const &Exclude) const; void draw_free_ends(TTrack const *Self, int const Category, std::vector const &Exclude) const; + // the free ends of the rail tracks around the camera, looked for again after an edit or once the camera leaves the place + struct free_end_cache + { + int edits{-1}; + glm::dvec3 centre{0.0}; + double reach{0.0}; + std::vector points; + }; + mutable free_end_cache m_free_end_cache; + std::vector const &free_end_points(glm::dvec3 const &Centre, double const Reach) const; struct point_drag { bool active{false}; diff --git a/application/editormodelay.cpp b/application/editormodelay.cpp index 8dd852d2..e6943593 100644 --- a/application/editormodelay.cpp +++ b/application/editormodelay.cpp @@ -219,6 +219,21 @@ editor_track::snap_target editor_mode::snap_free_end(glm::dvec3 const &Near, glm return result; } +std::vector const &editor_mode::free_end_points(glm::dvec3 const &Centre, double const Reach) const +{ + auto &cache{m_free_end_cache}; + if (cache.edits != m_track_edits || glm::distance(cache.centre, Centre) > cache.reach * 0.25 || Reach > cache.reach * 1.01 || Reach < cache.reach * 0.5) + { + cache.edits = m_track_edits; + cache.centre = Centre; + cache.reach = Reach * 1.25; + cache.points.clear(); + for (auto const &end : editor_track::free_ends(nullptr, kRailCategory, Centre, cache.reach, {})) + cache.points.push_back(end.position); + } + return cache.points; +} + void editor_mode::draw_free_ends(TTrack const *Self, int const Category, std::vector const &Exclude) const { screen_projection const projection; diff --git a/application/editormodetrack.cpp b/application/editormodetrack.cpp index b7e01380..fa749cda 100644 --- a/application/editormodetrack.cpp +++ b/application/editormodetrack.cpp @@ -2122,6 +2122,16 @@ void editor_mode::draw_build_overlay() const drawlist->AddCircleFilled(screen, 3.5f, kJointColor); } } + // the ends joined to nothing, where a train would run off + for (auto const &point : free_end_points(eye, Global.EditorOrtho ? std::max(kDotsRange, static_cast(Global.EditorOrthoExtent) * 2.0) : kDotsRange)) + { + ImVec2 screen; + if (in_reach(point) && projection.project(point, screen) && screen.x >= 0.0f && screen.y >= 0.0f && screen.x <= display.x && screen.y <= display.y) + { + drawlist->AddCircleFilled(screen, 5.0f, kFreeEndColor); + drawlist->AddCircle(screen, 5.0f, IM_COL32(0, 0, 0, 160), 12, 1.0f); + } + } if (m_extend.active) { if (m_extend.track != nullptr) diff --git a/application/editormodetrackshared.h b/application/editormodetrackshared.h index 9e60c62f..a3278716 100644 --- a/application/editormodetrackshared.h +++ b/application/editormodetrackshared.h @@ -151,6 +151,7 @@ double const kDrawnReach{100000.0}; double const kJointRange{400.0}; // the ends of the paths are drawn for the tracks this close to the camera double const kDotsRange{500.0}; // m, the dots of the ends of the tracks are drawn this close to the camera in the 3D view ImU32 const kJointColor{IM_COL32(255, 255, 255, 200)}; +ImU32 const kFreeEndColor{IM_COL32(240, 60, 60, 235)}; int const kRailCategory{1}; inline editor_track::branch_end branch_start(segment_data const &Diverging)