17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 10:59:20 +02:00

chore(editor): cleanup comments

This commit is contained in:
maj00r
2026-10-02 22:28:45 +02:00
parent 8f2a34b3cf
commit 7ede96df5f
12 changed files with 84 additions and 283 deletions

View File

@@ -4,10 +4,9 @@ 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/.
http:
*/
// path (track) editing part of the editor mode
#include "stdafx.h"
#include "application/editormode.h"
@@ -29,7 +28,6 @@ http://mozilla.org/MPL/2.0/.
namespace
{
// projects world points onto the screen, with the same camera-relative view and clean perspective the gizmo uses
class screen_projection
{
public:
@@ -51,7 +49,6 @@ class screen_projection
{
return ImVec2((Clip.x / Clip.w * 0.5f + 0.5f) * m_size.x, (0.5f - Clip.y / Clip.w * 0.5f) * m_size.y);
}
// returns: true if the point is in front of the camera
bool project(glm::dvec3 const &Point, ImVec2 &Screen) const
{
auto const c = clip(Point);
@@ -60,7 +57,6 @@ class screen_projection
Screen = screen(c);
return true;
}
// draws a line, clipped against the near plane so points behind the camera don't flip across the screen
void line(ImDrawList *Drawlist, glm::dvec3 const &A, glm::dvec3 const &B, ImU32 const Color, float const Thickness) const
{
glm::vec4 a = clip(A);
@@ -81,7 +77,6 @@ class screen_projection
glm::mat4 m_viewprojection;
};
// point on the course of a path, matching the curve TSegment builds from the same data
glm::dvec3 path_point(segment_data const &Path, double const T)
{
auto const &p0 = Path.points[segment_data::point::start];
@@ -114,10 +109,9 @@ bool is_end(editor_track::point_kind const Kind)
editor_track::point_kind const kPointKinds[] = {editor_track::point_kind::start, editor_track::point_kind::control1, editor_track::point_kind::control2, editor_track::point_kind::end};
// screen distance within which a click grabs a point handle
float const kHandleRadius{10.0f};
} // namespace
}
TTrack *editor_mode::selected_track() const
{
@@ -129,11 +123,9 @@ void editor_mode::select_track(scene::basic_node *Node)
auto *track = dynamic_cast<TTrack *>(Node);
if (track == nullptr)
{
// a click beside the selected path releases its point handle
m_track_point = {};
return;
}
// paths are long, so the distance is measured to the nearest point of the path rather than its centre
glm::dvec3 const camera{Global.pCamera.Pos};
if (glm::distance(glm::dvec3(track->get_nearest_point(camera)), camera) > static_cast<double>(kMaxPlacementDistance))
return;
@@ -164,7 +156,6 @@ bool editor_mode::pick_track_handle()
continue;
float const dx = screen.x - mouse.x;
float const dy = screen.y - mouse.y;
// end points take precedence over control points placed at the same spot
float const distance = (dx * dx + dy * dy) * (is_end(kind) ? 0.5f : 1.0f);
if (distance < best)
{
@@ -189,7 +180,6 @@ void editor_mode::draw_track_overlay() const
ImDrawList *drawlist = ImGui::GetBackgroundDrawList();
bool const trackmode = ui()->mode() == nodebank_panel::TRACK;
// course of the path, from its source data so it follows the edits before the path is rebuilt
ImU32 const coursecolor = IM_COL32(40, 220, 255, 220);
int constexpr samples{32};
for (auto const &path : track->m_paths)
@@ -205,14 +195,12 @@ void editor_mode::draw_track_overlay() const
if (false == trackmode || m_route_tab || false == editor_track::is_supported(*track))
return;
// control vectors
ImU32 const vectorcolor = IM_COL32(200, 200, 200, 160);
for (int i = 0; i < static_cast<int>(track->m_paths.size()); ++i)
{
projection.line(drawlist, editor_track::point_position(*track, {i, editor_track::point_kind::start}), editor_track::point_position(*track, {i, editor_track::point_kind::control1}), vectorcolor, 1.0f);
projection.line(drawlist, editor_track::point_position(*track, {i, editor_track::point_kind::end}), editor_track::point_position(*track, {i, editor_track::point_kind::control2}), vectorcolor, 1.0f);
}
// handles: end points coloured by connection state (green: connected, red: free), control points as squares
for (int i = 0; i < static_cast<int>(track->m_paths.size()); ++i)
{
for (auto const kind : kPointKinds)
@@ -235,7 +223,6 @@ void editor_mode::draw_track_overlay() const
drawlist->AddCircle(screen, 10.0f, IM_COL32(255, 220, 40, 255), 16, 2.5f);
}
}
// connection to be made when the ongoing drag ends
if (m_track_snap.track != nullptr)
{
ImVec2 screen;
@@ -261,14 +248,12 @@ void editor_mode::render_track_gizmo()
ImGuiIO const &io = ImGui::GetIO();
ImGuizmo::SetRect(0.0f, 0.0f, io.DisplaySize.x, io.DisplaySize.y);
// same camera-relative view and clean perspective as the transform gizmo of the other nodes
glm::mat4 const view = GfxRenderer->Camera_View_Matrix();
glm::dvec3 const camerapos = GfxRenderer->Camera_Position();
float const fovy = glm::radians(Global.FieldOfView / Global.ZoomFactor);
float const aspect = io.DisplaySize.y > 0.0f ? io.DisplaySize.x / io.DisplaySize.y : 1.0f;
glm::mat4 const projection = glm::perspective(fovy, aspect, 0.1f, 10000.0f);
// point handles only move; the whole path moves or turns around the vertical axis
ImGuizmo::OPERATION const operation = (false == pointmode && m_gizmo_op == gizmo_operation::rotate) ? ImGuizmo::ROTATE_Y : ImGuizmo::TRANSLATE;
if (false == m_track_gizmo_using)
@@ -286,7 +271,6 @@ void editor_mode::render_track_gizmo()
{
if (false == m_track_gizmo_using)
{
// drag start: gather the paths it modifies and record their state for undo
m_track_gizmo_using = true;
m_track_pivot = editor_track::pivot(*track);
m_track_drag = {track};
@@ -326,7 +310,6 @@ void editor_mode::render_track_gizmo()
for (auto const &connection : m_track_drag_points)
editor_track::move_point(*connection.first, connection.second, position);
m_track_dirty = true;
// a free end point can be connected with another path; a joint moved as a whole stays as it is
if (is_end(m_track_point.kind) && m_track_drag_points.empty())
{
std::vector<TTrack const *> const exclude(m_track_drag.begin(), m_track_drag.end());
@@ -346,7 +329,6 @@ void editor_mode::render_track_gizmo()
}
else if (m_track_gizmo_using)
{
// drag end: make the offered connection and rebuild everything for good
if (m_track_snap.track != nullptr && pointmode)
{
editor_track::snap_point(*track, m_track_point, m_track_snap, m_track_align_tangent);
@@ -364,7 +346,6 @@ void editor_mode::commit_track_drag(bool const Force)
{
if (false == m_track_dirty || m_track_drag.empty())
return;
// each rebuild re-uploads geometry of the affected sections, so it isn't done on every frame of a drag
auto const now = std::chrono::steady_clock::now();
if (false == Force && now - m_track_last_commit < std::chrono::milliseconds(100))
return;
@@ -399,11 +380,9 @@ void editor_mode::restore_track_snapshot(EditorSnapshot const &Snapshot, std::ve
if (Snapshot.tracks.empty())
return;
// paths restored by this step; paths added by the change exist only on its redo side
std::vector<TTrack *> tracks;
for (auto const &entry : Snapshot.tracks)
tracks.emplace_back(entry.first);
// current state goes to the opposite stack, including paths added by the change when it's being undone
EditorSnapshot current{Snapshot};
current.tracks.clear();
auto involved{tracks};
@@ -426,7 +405,6 @@ void editor_mode::restore_track_snapshot(EditorSnapshot const &Snapshot, std::ve
for (auto const &entry : Snapshot.tracks)
editor_track::apply(*entry.first, entry.second);
editor_track::commit(tracks);
// the designed route refers to the chain, which might have changed
if (false == m_route.chain.tracks.empty())
{
std::string error;
@@ -486,7 +464,6 @@ void editor_mode::render_path_ui()
ImGui::TextColored(ImVec4(1.0f, 0.6f, 0.2f, 1.0f), "Geometry locked: %s", reason.c_str());
auto const before = editor_track::capture(*track);
// records undo state when a field edit starts, and rebuilds the path once it's finished
enum class rebuild { none, parameters, geometry };
auto const finish_edit = [&](rebuild const Rebuild) {
if (ImGui::IsItemActivated())
@@ -502,7 +479,6 @@ void editor_mode::render_path_ui()
}
}
};
// applies a change made with a widget which reports it at once, like a combo box
auto const apply_now = [&](rebuild const Rebuild) {
push_track_snapshot({{track, before}});
if (Rebuild == rebuild::parameters)
@@ -545,7 +521,6 @@ void editor_mode::render_path_ui()
if (track->m_visible)
{
// material names are edited in local buffers, refreshed from the path whenever no field is being edited
material_handle *materials[] = {&track->m_material1, &track->m_material2, track->SwitchExtension ? &track->SwitchExtension->m_material3 : nullptr};
char const *labels[] = {"Texture 1 (rails/surface)", "Texture 2 (trackbed/side)", "Trackbed (switch)"};
if (false == ImGui::IsAnyItemActive())
@@ -602,7 +577,6 @@ void editor_mode::render_path_ui()
ImGui::PushID(i);
if (track->m_paths.size() > 1)
ImGui::Text("Path %d", i + 1);
// point selection, same as clicking the handle in the viewport
for (auto const kind : kPointKinds)
{
editor_track::point_ref const point{i, kind};
@@ -623,7 +597,7 @@ void editor_mode::render_path_ui()
{
auto position = path.points[kind == editor_track::point_kind::start ? segment_data::point::start : segment_data::point::end];
if (ImGui::InputScalarN(point_label(kind), ImGuiDataType_Double, glm::value_ptr(position), 3, nullptr, nullptr, "%.3f"))
editor_track::move_point(*track, {i, kind}, position); // keeps the common start of a switch together
editor_track::move_point(*track, {i, kind}, position);
finish_edit(rebuild::geometry);
}
ImGui::InputScalarN("Control 1 (relative)", ImGuiDataType_Double, glm::value_ptr(path.points[segment_data::point::control1]), 3, nullptr, nullptr, "%.3f");
@@ -655,7 +629,6 @@ void editor_mode::render_path_ui()
}
}
// route design
bool editor_mode::route_active() const
{
@@ -686,7 +659,6 @@ void editor_mode::route_reset()
auto const &chain{route.chain};
alignment::design design;
// limits and the curve type are the user's choice, they carry over to the next fragment
design.norms = route.design.norms;
design.shape = route.design.shape;
design.start = chain.start;
@@ -702,7 +674,6 @@ void editor_mode::route_reset()
design.speed = chain.velocity > 0.0 ? chain.velocity : 100.0;
route.design = design;
// initial layout: a straight, a single curve at the intersection of the end tangents, or a pair of curves
glm::dvec2 intersection;
if (false == alignment::collinear(design))
{
@@ -730,7 +701,6 @@ void editor_mode::route_apply()
route.status.clear();
if (false == route.result.valid || route.chain.tracks.empty())
return;
// the paths might have changed since the fragment was selected
editor_track::chain chain;
if (false == editor_track::find_chain(route.from, route.to, chain, route.error))
return;
@@ -829,7 +799,6 @@ void editor_mode::draw_route_overlay() const
screen_projection const projection;
ImDrawList *drawlist = ImGui::GetBackgroundDrawList();
// polygon of tangents
std::vector<glm::dvec3> polygon{design.start};
for (int i = 0; i < static_cast<int>(design.vertices.size()); ++i)
polygon.push_back(route_vertex_position(i));
@@ -837,7 +806,6 @@ void editor_mode::draw_route_overlay() const
for (std::size_t i = 0; i + 1 < polygon.size(); ++i)
projection.line(drawlist, polygon[i], polygon[i + 1], IM_COL32(255, 210, 60, 150), 1.5f);
// designed alignment, coloured by element: straight white, transition orange, circular curve green
if (result.length > 0.0 && result.profile.size() >= 2)
{
for (auto const &e : result.elements)
@@ -857,7 +825,6 @@ void editor_mode::draw_route_overlay() const
}
}
// fixed ends with their directions, and the vertices
for (auto const atend : {false, true})
{
auto const &point{atend ? design.end : design.start};
@@ -918,7 +885,6 @@ void editor_mode::render_route_gizmo()
glm::dvec3 const moved{camerapos + glm::dvec3(m_route_gizmo[3])};
auto &vertex{route.design.vertices[route.vertex]};
glm::dvec2 const point{moved.x, moved.z};
// the first and the last vertex slide along the tangents of the fixed ends; a single vertex stays at their intersection
if (count >= 2)
{
if (route.vertex == 0)
@@ -1010,7 +976,6 @@ void editor_mode::render_route_ui()
ImGui::TreePop();
}
// vertices
auto &vertices{design.vertices};
if (ImGui::Button("Add vertex"))
{
@@ -1020,7 +985,6 @@ void editor_mode::render_route_ui()
auto const distance{glm::distance(glm::dvec2{design.start.x, design.start.z}, glm::dvec2{design.end.x, design.end.z})};
if (vertices.size() == 1)
{
// a single vertex sits at the intersection of the tangents; two vertices slide along them
vertices.front().offset = distance / 3.0;
vertex.offset = distance / 3.0;
vertices.push_back(vertex);
@@ -1031,12 +995,10 @@ void editor_mode::render_route_ui()
}
else
{
// new vertex between the selected one (or the last but one) and the next
auto const index{std::clamp(route.vertex, 0, static_cast<int>(vertices.size()) - 2)};
auto const a{route_vertex_position(index)};
auto const b{route_vertex_position(index + 1)};
vertex.position = glm::dvec2{(a.x + b.x) * 0.5, (a.z + b.z) * 0.5};
// the moved vertices keep their place, so the former first/last vertex positions become free positions
for (int i = 0; i < static_cast<int>(vertices.size()); ++i)
{
auto const p{route_vertex_position(i)};
@@ -1113,7 +1075,6 @@ void editor_mode::render_route_ui()
if (changed)
route_update();
// outcome
ImGui::Separator();
auto const &result{route.result};
if (result.length > 0.0)