17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-30 17:50:29 +01:00

feat(editor): with the gizmo hidden a track is changed by its ends only: its control vectors are neither drawn nor caught until Q, W, E or the buttons above the view bring the gizmo out, so a track selected won't bend by chance; the hints say what dragging an end does (a joint: the neighbours follow, a free end: a new track out of it, with Ctrl it moves). The tutorial has a lesson of its own for editing with the gizmo, after the one of selecting and fixing, which no longer speaks of it: the arrows, the rings, the handles, the control vectors, a point clicked, Ctrl and Esc, ticked off when the gizmo is out and a track bent or moved with it; thirteen lessons. Also puts back in place two lines of the band of the curvature which dd64b821 committed out of their place (the arc declared inside the loop, so that commit didn't compile)

This commit is contained in:
maj00r
2026-10-25 12:33:19 +01:00
parent 97b6a84d1b
commit a312fd9935
6 changed files with 85 additions and 25 deletions

View File

@@ -4759,7 +4759,7 @@ void editor_mode::render_help_menu()
ImGui::SetTooltip("%s", STR_C("The keys of the editor, for each field of work"));
ImGui::MenuItem(STR_C("Tutorial"), nullptr, &m_first_steps_open);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C("Twelve short lessons with clips and drawings: the camera, laying track, curves, correcting a curve, joining, switches, signals and posts, fixing, the grade line, terrain, older sceneries, saving and driving"));
ImGui::SetTooltip("%s", STR_C("Thirteen short lessons with clips and drawings: the camera, laying track, curves, correcting a curve, joining, switches, signals and posts, fixing, the gizmo, the grade line, terrain, older sceneries, saving and driving"));
ImGui::EndMenu();
}
@@ -5107,6 +5107,10 @@ void editor_mode::render_first_steps()
first_step_done(first_step::terrain);
if (ui()->mode() == nodebank_panel::TRACK && m_track_tab == track_tab::route && false == m_route.chain.tracks.empty())
first_step_done(first_step::plan);
if (ui()->mode() == nodebank_panel::TRACK && m_track_gizmo_on)
first_step_done(first_step::gizmo);
if (m_track_gizmo_using || (m_point_drag.moved && m_track_point.valid() && false == editor_track::is_end(m_track_point.kind)))
first_step_done(first_step::vector);
enum class trial { none, top, lay, turnout, select, profile, terrain, plan, trainset, signals };
struct input
{
@@ -5198,14 +5202,25 @@ void editor_mode::render_first_steps()
{"Selecting and fixing",
"edit",
{{"Esc", "The select tool"},
{"LMB", "Click a track: it is selected, with its points"},
{"LMB + move", "Drag a point: the end or the curve follows"},
{"Q W E", "The gizmo on the selected track: move, turn, lengthen. Hidden until then, so the track won't move by chance; the arrow above the view hides it again"},
{"LMB", "Click a track: it is selected, with its ends"},
{"LMB + move", "Drag an end: at a joint the neighbours follow, from a free end a new track goes out, with Ctrl the end moves"},
{"RMB", "A click on a track: what can be done with it"},
{"Del", "Deletes the selected"},
{"Ctrl + Z", "Takes the last change back; Ctrl+Y brings it back again"}},
{"Ctrl + Z", "Takes the last change back; Ctrl+Y brings it back again"},
{"Q W E", "The gizmo, to move, turn or bend the track: the next lesson"}},
{{first_step::select, "Select a track"}, {first_step::undo, "Take a change back"}},
trial::select},
{"Editing with the gizmo",
"gizmo",
{{"Q", "The gizmo on the selected track, hidden until then: arrows which move it"},
{"W", "Rings which turn it: its direction, its grade and its cant; the tracks joined to it follow"},
{"E", "Handles which lengthen it at its free end, the curve keeping its radius"},
{"LMB + move", "With the gizmo out the control vectors are there too: drag one, the curve follows it"},
{"LMB", "A click on a point of the track: the gizmo goes to it, that point alone is moved or turned"},
{"Ctrl", "Held while dragging: the gizmo goes by its step"},
{"Esc", "Releases the point; the arrow above the view hides the gizmo again"}},
{{first_step::gizmo, "Bring out the gizmo with Q, W or E"}, {first_step::vector, "Bend a track by a control vector, or move it with the gizmo"}},
trial::select},
{"The grade line",
nullptr,
{{"P", "The profile tool: a click on a track opens the grade line of its whole line in the strip below"},

View File

@@ -1741,12 +1741,12 @@ bool editor_mode::render_route_band()
// ones of no length yet
int under{-1};
int part{0};
int arc{0};
if (hovered && false == dragging)
{
for (int i = 0; i < count; ++i)
{
auto const &element{result.elements[i]};
int arc{0};
if (mouse.x < x_of(element.chainage) || mouse.x >= x_of(element.chainage + element.length))
continue;
under = i;
@@ -1810,12 +1810,12 @@ bool editor_mode::render_route_band()
}
else
{
// the transition in grows to the left, from where it starts; the others to the right
auto const shift{(mouse.x - band.press.x) / std::max(1e-6f, metres)};
wanted = std::max(0.0, std::round(band.value + (band.part == 2 ? -shift : shift)));
}
if (wanted != value)
{
// the transition in grows to the left, from where it starts; the others to the right
value = wanted;
changed = true;
}

View File

@@ -177,6 +177,9 @@ editor_track::point_ref editor_mode::track_handle_hit() const
{
for (auto const kind : kPointKinds)
{
// the control vectors only with the gizmo out: hidden, a track is changed by its ends and won't bend by chance
if (false == m_track_gizmo_on && false == editor_track::is_end(kind))
continue;
editor_track::point_ref const point{i, kind};
float const distance = projection.mouse_distance2(editor_track::point_position(*track, point)) * (editor_track::is_end(kind) ? 0.5f : 1.0f);
if (distance < best)
@@ -217,8 +220,9 @@ void editor_mode::draw_track_overlay() const
if (false == trackmode || m_route_tab || false == editor_track::is_supported(*track))
return;
// the control vectors are drawn, and dragged, only with the gizmo out
ImU32 const vectorcolor = IM_COL32(200, 200, 200, 160);
for (int i = 0; i < static_cast<int>(track->m_paths.size()); ++i)
for (int i = 0; m_track_gizmo_on && 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);
@@ -227,6 +231,8 @@ void editor_mode::draw_track_overlay() const
{
for (auto const kind : kPointKinds)
{
if (false == m_track_gizmo_on && false == editor_track::is_end(kind))
continue;
editor_track::point_ref const point{i, kind};
ImVec2 screen;
if (false == projection.project(editor_track::point_position(*track, point), screen))
@@ -1809,12 +1815,15 @@ std::vector<editor_mode::key_hint> editor_mode::track_key_hints(bool const All)
auto const handles{std::find_if(hints.begin(), hints.end(), named("Gizmo"))};
if (auto const keys{std::find_if(hints.begin(), hints.end(), named("Q W E"))}; keys != hints.end())
{
keys->action = "bring out the gizmo: move, turn, lengthen";
keys->action = "bring out the gizmo: move, turn, lengthen, bend by the control vectors";
if (handles != hints.end())
hints.erase(handles);
}
else if (handles != hints.end())
*handles = {"Q W E", "bring out the gizmo: move, turn, lengthen"};
*handles = {"Q W E", "bring out the gizmo: move, turn, lengthen, bend by the control vectors"};
// with it hidden only the ends of the track are there to drag, the control vectors come out with it
if (auto const points{std::find_if(hints.begin(), hints.end(), named("Drag a point"))}; points != hints.end())
*points = {"Drag an end", "a joint: the neighbours follow; a free end: a new track out of it, with Ctrl it moves"};
gizmo = false;
}
if (auto const *meaning{typed_meaning()}; meaning != nullptr)

View File

@@ -425,7 +425,7 @@ void editor_mode::render_viewport_gizmo()
};
std::vector<tool_button> buttons;
if (tracks)
buttons.push_back({icon::select, STR_C("No gizmo"), nullptr, STR_C("The gizmo hidden: a track is changed by dragging its points, and won't move by chance"), false == on, [this]() { m_track_gizmo_on = false; }});
buttons.push_back({icon::select, STR_C("No gizmo"), nullptr, STR_C("The gizmo hidden: a track is changed by dragging its ends, and won't move nor bend by chance; its control vectors come out with the gizmo"), false == on, [this]() { m_track_gizmo_on = false; }});
buttons.push_back({icon::translate, STR_C("Translate"), "Q", tooltip, on && m_gizmo_op == gizmo_operation::translate, [choose]() { choose(gizmo_operation::translate); }, tracks});
buttons.push_back({icon::rotate, STR_C("Rotate"), "W", tooltip, on && m_gizmo_op == gizmo_operation::rotate, [choose]() { choose(gizmo_operation::rotate); }});
buttons.push_back({icon::scale, STR_C("Scale"), "E", tooltip, on && m_gizmo_op == gizmo_operation::scale, [choose]() { choose(gizmo_operation::scale); }});

View File

@@ -34,7 +34,7 @@ enum class editor_selftest_result
again
};
enum class editor_first_step { tracks, lay, laid, wheel, join, turnout, undo, save, drive, look, top, select, shape, profile, profile_point, profile_apply, terrain, nmt, plan, plan_band, plan_apply, signal, posts, bend, trace, count };
enum class editor_first_step { tracks, lay, laid, wheel, join, turnout, undo, save, drive, look, top, select, shape, profile, profile_point, profile_apply, terrain, nmt, plan, plan_band, plan_apply, signal, posts, bend, trace, gizmo, vector, count };
enum class editor_track_tab { straights, route, path, turnout, profile, speed, joints, infra, lay, lineside, turntable, parallel, srk, kilometrage };