17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-02 12:49:13 +01:00

feat(editor): track editor driven by what the cursor is over: the outline and a label show what a click or a drag does, snapping to free ends on the screen, handles and ends dragged directly, no rotation gizmo; laying from a free end the same in every mode, straight with Shift, the curve of a switch going on past its diverging end; height 0 where there's no terrain; placed switch leaves the switch mode, double slips listed apart, a drive of the switch placed with it by the //$e switch description of its template; compound curves of any number of radii; dragged end of a straight fits the curve beside it; name of a path, followed by the memory cells and the includes taking it; turntable placed from a template described as one, tracks led out of it and the tracks around fitted to it, its positions written to the include; infrastructure bound to the path whose events read its memory cell; terrain made where the route has none and shaped to the formation under the ballast; models along the track over the selected path and on along the joined ones while dragged, rarely used settings folded; vehicles and trainsets placed on any path, switches included, facing the way the arrow shows; joined paths spread into the selection; New scenery in the File menu starts the editor again with the wizard; ortho zoom towards the cursor; scripted self tests; Polish translation

This commit is contained in:
maj00r
2026-10-06 22:19:54 +02:00
parent 0a3cd55e59
commit 24923dd472
26 changed files with 9991 additions and 468 deletions

View File

@@ -76,6 +76,31 @@ class screen_projection
auto const &mouse{ImGui::GetIO().MousePos};
return (position.x - mouse.x) * (position.x - mouse.x) + (position.y - mouse.y) * (position.y - mouse.y);
}
// world space ray through the point of the screen
void ray(ImVec2 const &Screen, glm::dvec3 &Origin, glm::dvec3 &Direction) const
{
auto const inverse{glm::inverse(m_viewprojection)};
glm::vec2 const ndc{m_size.x > 0.0f ? Screen.x / m_size.x * 2.0f - 1.0f : 0.0f, m_size.y > 0.0f ? 1.0f - Screen.y / m_size.y * 2.0f : 0.0f};
auto nearpoint{inverse * glm::vec4(ndc, -1.0f, 1.0f)};
auto farpoint{inverse * glm::vec4(ndc, 1.0f, 1.0f)};
nearpoint /= nearpoint.w;
farpoint /= farpoint.w;
Origin = m_camera + glm::dvec3(glm::vec3(nearpoint));
Direction = glm::normalize(glm::dvec3(glm::vec3(farpoint - nearpoint)));
}
// where the ray through the point of the screen crosses the level of the height; false if it runs along it or away
bool on_level(ImVec2 const &Screen, double const Height, glm::dvec3 &Point) const
{
glm::dvec3 origin, direction;
ray(Screen, origin, direction);
if (std::abs(direction.y) < 1e-6)
return false;
auto const distance{(Height - origin.y) / direction.y};
if (distance < 0.0)
return false;
Point = origin + direction * distance;
return true;
}
private:
static constexpr float kNear{0.1f};
@@ -87,6 +112,9 @@ class screen_projection
// starts a gizmo frame over the whole display, the view and the projection are those of the current camera
struct gizmo_frame
{
static inline int drawn{-1};
// the cursor is over a gizmo shown in this frame, ImGuizmo alone tells it of the last one shown even when it's gone
static bool over() { return ImGui::GetFrameCount() - drawn <= 1 && ImGuizmo::IsOver(); }
glm::mat4 view;
glm::mat4 projection;
glm::dvec3 camera;
@@ -106,6 +134,7 @@ struct gizmo_frame
{
glm::vec3 snapvalue(Snap);
float const *snap = Global.ctrlState && Snap > 0.0f ? &snapvalue.x : nullptr;
drawn = ImGui::GetFrameCount();
return ImGuizmo::Manipulate(&view[0][0], &projection[0][0], Operation, ImGuizmo::WORLD, &Gizmo[0][0], Delta != nullptr ? &(*Delta)[0][0] : nullptr, snap);
}
};