mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 03:59:19 +02:00
refactor(editor): shared gizmo frame, screen picking and history trimming
This commit is contained in:
@@ -289,7 +289,8 @@ class editor_mode : public application_mode, private editor_track::observer
|
|||||||
void select_track(scene::basic_node *Node);
|
void select_track(scene::basic_node *Node);
|
||||||
void render_track_gizmo();
|
void render_track_gizmo();
|
||||||
void commit_track_drag(bool const Force);
|
void commit_track_drag(bool const Force);
|
||||||
void push_track_snapshot(std::vector<std::pair<TTrack *, editor_track::state>> States, std::vector<TTrack *> Created = {});
|
void push_track_snapshot(std::vector<std::pair<TTrack *, editor_track::state>> States, std::vector<TTrack *> Created = {}, std::vector<TTrack *> Removed = {});
|
||||||
|
void trim_history();
|
||||||
void restore_track_snapshot(EditorSnapshot const &Snapshot, std::vector<EditorSnapshot> &Opposite, bool const Undo);
|
void restore_track_snapshot(EditorSnapshot const &Snapshot, std::vector<EditorSnapshot> &Opposite, bool const Undo);
|
||||||
editor_track::point_ref m_track_point;
|
editor_track::point_ref m_track_point;
|
||||||
std::vector<TTrack *> m_track_drag;
|
std::vector<TTrack *> m_track_drag;
|
||||||
|
|||||||
@@ -869,6 +869,11 @@ void editor_mode::render_profile_canvas()
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto const curves{profile::curves(line)};
|
auto const curves{profile::curves(line)};
|
||||||
|
auto const mouse_distance2 = [&](double Chainage, double Elevation) {
|
||||||
|
auto const dx{x_of(Chainage) - mouse.x};
|
||||||
|
auto const dy{y_of(Elevation) - mouse.y};
|
||||||
|
return dx * dx + dy * dy;
|
||||||
|
};
|
||||||
auto const hit_point = [&]() {
|
auto const hit_point = [&]() {
|
||||||
int hit{-1};
|
int hit{-1};
|
||||||
float best{64.0f};
|
float best{64.0f};
|
||||||
@@ -876,11 +881,9 @@ void editor_mode::render_profile_canvas()
|
|||||||
{
|
{
|
||||||
if (points[i].joint)
|
if (points[i].joint)
|
||||||
continue;
|
continue;
|
||||||
auto const dx{x_of(points[i].chainage) - mouse.x};
|
if (auto const distance{mouse_distance2(points[i].chainage, points[i].elevation)}; distance < best)
|
||||||
auto const dy{y_of(points[i].elevation) - mouse.y};
|
|
||||||
if (dx * dx + dy * dy < best)
|
|
||||||
{
|
{
|
||||||
best = dx * dx + dy * dy;
|
best = distance;
|
||||||
hit = i;
|
hit = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -892,9 +895,7 @@ void editor_mode::render_profile_canvas()
|
|||||||
if (points[c.point].joint)
|
if (points[c.point].joint)
|
||||||
continue;
|
continue;
|
||||||
auto const chainage{points[c.point].chainage};
|
auto const chainage{points[c.point].chainage};
|
||||||
auto const dx{x_of(chainage) - mouse.x};
|
if (mouse_distance2(chainage, profile::elevation(line, chainage)) < 64.0f)
|
||||||
auto const dy{y_of(profile::elevation(line, chainage)) - mouse.y};
|
|
||||||
if (dx * dx + dy * dy < 64.0f)
|
|
||||||
return static_cast<int>(c.point);
|
return static_cast<int>(c.point);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ bool editor_mode::pick_track_handle()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
screen_projection const projection;
|
screen_projection const projection;
|
||||||
ImVec2 const mouse = ImGui::GetIO().MousePos;
|
|
||||||
float best = kHandleRadius * kHandleRadius;
|
float best = kHandleRadius * kHandleRadius;
|
||||||
editor_track::point_ref hit;
|
editor_track::point_ref hit;
|
||||||
for (int i = 0; i < static_cast<int>(track->m_paths.size()); ++i)
|
for (int i = 0; i < static_cast<int>(track->m_paths.size()); ++i)
|
||||||
@@ -116,12 +115,7 @@ bool editor_mode::pick_track_handle()
|
|||||||
for (auto const kind : kPointKinds)
|
for (auto const kind : kPointKinds)
|
||||||
{
|
{
|
||||||
editor_track::point_ref const point{i, kind};
|
editor_track::point_ref const point{i, kind};
|
||||||
ImVec2 screen;
|
float const distance = projection.mouse_distance2(editor_track::point_position(*track, point)) * (editor_track::is_end(kind) ? 0.5f : 1.0f);
|
||||||
if (false == projection.project(editor_track::point_position(*track, point), screen))
|
|
||||||
continue;
|
|
||||||
float const dx = screen.x - mouse.x;
|
|
||||||
float const dy = screen.y - mouse.y;
|
|
||||||
float const distance = (dx * dx + dy * dy) * (editor_track::is_end(kind) ? 0.5f : 1.0f);
|
|
||||||
if (distance < best)
|
if (distance < best)
|
||||||
{
|
{
|
||||||
best = distance;
|
best = distance;
|
||||||
@@ -208,28 +202,18 @@ void editor_mode::render_track_gizmo()
|
|||||||
}
|
}
|
||||||
bool const pointmode = ui()->mode() == nodebank_panel::TRACK && m_track_point.valid() && m_track_point.path < static_cast<int>(track->m_paths.size());
|
bool const pointmode = ui()->mode() == nodebank_panel::TRACK && m_track_point.valid() && m_track_point.path < static_cast<int>(track->m_paths.size());
|
||||||
|
|
||||||
ImGuizmo::BeginFrame();
|
gizmo_frame const frame;
|
||||||
ImGuizmo::SetOrthographic(Global.EditorOrtho);
|
|
||||||
ImGuiIO const &io = ImGui::GetIO();
|
|
||||||
ImGuizmo::SetRect(0.0f, 0.0f, io.DisplaySize.x, io.DisplaySize.y);
|
|
||||||
|
|
||||||
glm::mat4 const view = GfxRenderer->Camera_View_Matrix();
|
|
||||||
glm::dvec3 const camerapos = GfxRenderer->Camera_Position();
|
|
||||||
float const aspect = io.DisplaySize.y > 0.0f ? io.DisplaySize.x / io.DisplaySize.y : 1.0f;
|
|
||||||
glm::mat4 const projection = editor_mode::projection_matrix(aspect);
|
|
||||||
|
|
||||||
ImGuizmo::OPERATION const operation = (false == pointmode && m_gizmo_op == gizmo_operation::rotate) ? ImGuizmo::ROTATE_Y : ImGuizmo::TRANSLATE;
|
ImGuizmo::OPERATION const operation = (false == pointmode && m_gizmo_op == gizmo_operation::rotate) ? ImGuizmo::ROTATE_Y : ImGuizmo::TRANSLATE;
|
||||||
|
|
||||||
if (false == m_track_gizmo_using)
|
if (false == m_track_gizmo_using)
|
||||||
{
|
{
|
||||||
auto const anchor = pointmode ? editor_track::point_position(*track, m_track_point) : editor_track::pivot(*track);
|
auto const anchor = pointmode ? editor_track::point_position(*track, m_track_point) : editor_track::pivot(*track);
|
||||||
m_track_gizmo = glm::translate(glm::mat4(1.0f), glm::vec3(anchor - camerapos));
|
m_track_gizmo = glm::translate(glm::mat4(1.0f), glm::vec3(anchor - frame.camera));
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 snapvalue(operation == ImGuizmo::ROTATE_Y ? 5.0f : m_gizmo_snap);
|
|
||||||
float const *snap = Global.ctrlState && snapvalue.x > 0.0f ? glm::value_ptr(snapvalue) : nullptr;
|
|
||||||
glm::mat4 delta(1.0f);
|
glm::mat4 delta(1.0f);
|
||||||
ImGuizmo::Manipulate(glm::value_ptr(view), glm::value_ptr(projection), operation, ImGuizmo::WORLD, glm::value_ptr(m_track_gizmo), glm::value_ptr(delta), snap);
|
frame.manipulate(operation, m_track_gizmo, operation == ImGuizmo::ROTATE_Y ? 5.0f : m_gizmo_snap, &delta);
|
||||||
|
|
||||||
if (ImGuizmo::IsUsing())
|
if (ImGuizmo::IsUsing())
|
||||||
{
|
{
|
||||||
@@ -269,7 +253,7 @@ void editor_mode::render_track_gizmo()
|
|||||||
}
|
}
|
||||||
else if (pointmode)
|
else if (pointmode)
|
||||||
{
|
{
|
||||||
glm::dvec3 const position = camerapos + glm::dvec3(m_track_gizmo[3]);
|
glm::dvec3 const position = frame.camera + glm::dvec3(m_track_gizmo[3]);
|
||||||
editor_track::move_point(*track, m_track_point, position);
|
editor_track::move_point(*track, m_track_point, position);
|
||||||
for (auto const &connection : m_track_drag_points)
|
for (auto const &connection : m_track_drag_points)
|
||||||
editor_track::move_point(*connection.first, connection.second, position);
|
editor_track::move_point(*connection.first, connection.second, position);
|
||||||
@@ -318,15 +302,19 @@ void editor_mode::commit_track_drag(bool const Force)
|
|||||||
m_track_last_commit = now;
|
m_track_last_commit = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_mode::push_track_snapshot(std::vector<std::pair<TTrack *, editor_track::state>> States, std::vector<TTrack *> Created)
|
void editor_mode::trim_history()
|
||||||
{
|
{
|
||||||
if (States.empty() && Created.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_max_history_size >= 0 && (int)m_history.size() >= m_max_history_size)
|
if (m_max_history_size >= 0 && (int)m_history.size() >= m_max_history_size)
|
||||||
m_history.erase(m_history.begin(), m_history.begin() + ((int)m_history.size() - m_max_history_size + 1));
|
m_history.erase(m_history.begin(), m_history.begin() + ((int)m_history.size() - m_max_history_size + 1));
|
||||||
|
}
|
||||||
|
|
||||||
auto *track = States.empty() ? Created.front() : States.front().first;
|
void editor_mode::push_track_snapshot(std::vector<std::pair<TTrack *, editor_track::state>> States, std::vector<TTrack *> Created, std::vector<TTrack *> Removed)
|
||||||
|
{
|
||||||
|
if (States.empty() && Created.empty() && Removed.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
trim_history();
|
||||||
|
auto *track = false == States.empty() ? States.front().first : false == Created.empty() ? Created.front() : Removed.front();
|
||||||
EditorSnapshot snap;
|
EditorSnapshot snap;
|
||||||
snap.action = EditorSnapshot::Action::TrackEdit;
|
snap.action = EditorSnapshot::Action::TrackEdit;
|
||||||
snap.node_name = track->name();
|
snap.node_name = track->name();
|
||||||
@@ -336,6 +324,7 @@ void editor_mode::push_track_snapshot(std::vector<std::pair<TTrack *, editor_tra
|
|||||||
snap.tracks = std::move(States);
|
snap.tracks = std::move(States);
|
||||||
snap.created = std::move(Created);
|
snap.created = std::move(Created);
|
||||||
infra_attach(snap);
|
infra_attach(snap);
|
||||||
|
snap.removed = std::move(Removed);
|
||||||
m_history.push_back(std::move(snap));
|
m_history.push_back(std::move(snap));
|
||||||
g_redo.clear();
|
g_redo.clear();
|
||||||
}
|
}
|
||||||
@@ -1019,33 +1008,22 @@ bool editor_mode::pick_route_vertex()
|
|||||||
if (false == route_active())
|
if (false == route_active())
|
||||||
return false;
|
return false;
|
||||||
screen_projection const projection;
|
screen_projection const projection;
|
||||||
ImVec2 const mouse = ImGui::GetIO().MousePos;
|
|
||||||
float best = kHandleRadius * kHandleRadius;
|
float best = kHandleRadius * kHandleRadius;
|
||||||
int hit{-1};
|
int hit{-1};
|
||||||
for (int i = 0; i < static_cast<int>(m_route.design.vertices.size()); ++i)
|
for (int i = 0; i < static_cast<int>(m_route.design.vertices.size()); ++i)
|
||||||
{
|
{
|
||||||
ImVec2 screen;
|
if (auto const distance{projection.mouse_distance2(route_vertex_position(i))}; distance < best)
|
||||||
if (false == projection.project(route_vertex_position(i), screen))
|
|
||||||
continue;
|
|
||||||
float const dx = screen.x - mouse.x;
|
|
||||||
float const dy = screen.y - mouse.y;
|
|
||||||
if (dx * dx + dy * dy < best)
|
|
||||||
{
|
{
|
||||||
best = dx * dx + dy * dy;
|
best = distance;
|
||||||
hit = i;
|
hit = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int griphit{-1};
|
int griphit{-1};
|
||||||
for (int i = 0; i < static_cast<int>(m_route.result.vertex_chainages.size()) && m_route.result.length > 0.0; ++i)
|
for (int i = 0; i < static_cast<int>(m_route.result.vertex_chainages.size()) && m_route.result.length > 0.0; ++i)
|
||||||
{
|
{
|
||||||
ImVec2 screen;
|
if (auto const distance{projection.mouse_distance2(alignment::evaluate(m_route.result, m_route.result.vertex_chainages[i]).position)}; distance < best)
|
||||||
if (false == projection.project(alignment::evaluate(m_route.result, m_route.result.vertex_chainages[i]).position, screen))
|
|
||||||
continue;
|
|
||||||
float const dx = screen.x - mouse.x;
|
|
||||||
float const dy = screen.y - mouse.y;
|
|
||||||
if (dx * dx + dy * dy < best)
|
|
||||||
{
|
{
|
||||||
best = dx * dx + dy * dy;
|
best = distance;
|
||||||
griphit = i;
|
griphit = i;
|
||||||
hit = -1;
|
hit = -1;
|
||||||
}
|
}
|
||||||
@@ -1135,21 +1113,12 @@ void editor_mode::render_route_gizmo()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuizmo::BeginFrame();
|
gizmo_frame const frame;
|
||||||
ImGuizmo::SetOrthographic(Global.EditorOrtho);
|
|
||||||
ImGuiIO const &io = ImGui::GetIO();
|
|
||||||
ImGuizmo::SetRect(0.0f, 0.0f, io.DisplaySize.x, io.DisplaySize.y);
|
|
||||||
glm::mat4 const view = GfxRenderer->Camera_View_Matrix();
|
|
||||||
glm::dvec3 const camerapos = GfxRenderer->Camera_Position();
|
|
||||||
float const aspect = io.DisplaySize.y > 0.0f ? io.DisplaySize.x / io.DisplaySize.y : 1.0f;
|
|
||||||
glm::mat4 const projection = editor_mode::projection_matrix(aspect);
|
|
||||||
|
|
||||||
auto const position{grip ? alignment::evaluate(route.result, route.result.vertex_chainages[route.grip]).position : route_vertex_position(route.vertex)};
|
auto const position{grip ? alignment::evaluate(route.result, route.result.vertex_chainages[route.grip]).position : route_vertex_position(route.vertex)};
|
||||||
if (false == m_route_gizmo_using)
|
if (false == m_route_gizmo_using)
|
||||||
m_route_gizmo = glm::translate(glm::mat4(1.0f), glm::vec3(position - camerapos));
|
m_route_gizmo = glm::translate(glm::mat4(1.0f), glm::vec3(position - frame.camera));
|
||||||
glm::vec3 snapvalue(m_gizmo_snap);
|
frame.manipulate(ImGuizmo::TRANSLATE, m_route_gizmo, m_gizmo_snap);
|
||||||
float const *snap = Global.ctrlState && snapvalue.x > 0.0f ? glm::value_ptr(snapvalue) : nullptr;
|
|
||||||
ImGuizmo::Manipulate(glm::value_ptr(view), glm::value_ptr(projection), ImGuizmo::TRANSLATE, ImGuizmo::WORLD, glm::value_ptr(m_route_gizmo), nullptr, snap);
|
|
||||||
|
|
||||||
if (false == ImGuizmo::IsUsing())
|
if (false == ImGuizmo::IsUsing())
|
||||||
{
|
{
|
||||||
@@ -1161,7 +1130,7 @@ void editor_mode::render_route_gizmo()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_route_gizmo_using = true;
|
m_route_gizmo_using = true;
|
||||||
glm::dvec3 const moved{camerapos + glm::dvec3(m_route_gizmo[3])};
|
glm::dvec3 const moved{frame.camera + glm::dvec3(m_route_gizmo[3])};
|
||||||
if (grip)
|
if (grip)
|
||||||
{
|
{
|
||||||
auto &vertex{route.design.vertices[route.grip]};
|
auto &vertex{route.design.vertices[route.grip]};
|
||||||
@@ -1812,19 +1781,13 @@ bool editor_mode::pick_straight_handle()
|
|||||||
auto const &line{current_straight()};
|
auto const &line{current_straight()};
|
||||||
glm::dvec3 const handles[] = {line.start, line.end, (line.start + line.end) * 0.5};
|
glm::dvec3 const handles[] = {line.start, line.end, (line.start + line.end) * 0.5};
|
||||||
screen_projection const projection;
|
screen_projection const projection;
|
||||||
ImVec2 const mouse = ImGui::GetIO().MousePos;
|
|
||||||
float best = kHandleRadius * kHandleRadius;
|
float best = kHandleRadius * kHandleRadius;
|
||||||
int hit{-1};
|
int hit{-1};
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
ImVec2 screen;
|
if (auto const distance{projection.mouse_distance2(handles[i])}; distance < best)
|
||||||
if (false == projection.project(handles[i], screen))
|
|
||||||
continue;
|
|
||||||
float const dx = screen.x - mouse.x;
|
|
||||||
float const dy = screen.y - mouse.y;
|
|
||||||
if (dx * dx + dy * dy < best)
|
|
||||||
{
|
{
|
||||||
best = dx * dx + dy * dy;
|
best = distance;
|
||||||
hit = i;
|
hit = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1897,22 +1860,13 @@ void editor_mode::render_straight_gizmo()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuizmo::BeginFrame();
|
gizmo_frame const frame;
|
||||||
ImGuizmo::SetOrthographic(Global.EditorOrtho);
|
|
||||||
ImGuiIO const &io = ImGui::GetIO();
|
|
||||||
ImGuizmo::SetRect(0.0f, 0.0f, io.DisplaySize.x, io.DisplaySize.y);
|
|
||||||
glm::mat4 const view = GfxRenderer->Camera_View_Matrix();
|
|
||||||
glm::dvec3 const camerapos = GfxRenderer->Camera_Position();
|
|
||||||
float const aspect = io.DisplaySize.y > 0.0f ? io.DisplaySize.x / io.DisplaySize.y : 1.0f;
|
|
||||||
glm::mat4 const projection = editor_mode::projection_matrix(aspect);
|
|
||||||
|
|
||||||
glm::dvec3 const anchors[] = {line.start, line.end, (line.start + line.end) * 0.5};
|
glm::dvec3 const anchors[] = {line.start, line.end, (line.start + line.end) * 0.5};
|
||||||
auto const anchor{anchors[state.handle]};
|
auto const anchor{anchors[state.handle]};
|
||||||
if (false == state.dragging)
|
if (false == state.dragging)
|
||||||
state.gizmo = glm::translate(glm::mat4(1.0f), glm::vec3(anchor - camerapos));
|
state.gizmo = glm::translate(glm::mat4(1.0f), glm::vec3(anchor - frame.camera));
|
||||||
glm::vec3 snapvalue(m_gizmo_snap);
|
frame.manipulate(ImGuizmo::TRANSLATE, state.gizmo, m_gizmo_snap);
|
||||||
float const *snap = Global.ctrlState && snapvalue.x > 0.0f ? glm::value_ptr(snapvalue) : nullptr;
|
|
||||||
ImGuizmo::Manipulate(glm::value_ptr(view), glm::value_ptr(projection), ImGuizmo::TRANSLATE, ImGuizmo::WORLD, glm::value_ptr(state.gizmo), nullptr, snap);
|
|
||||||
|
|
||||||
if (ImGuizmo::IsUsing())
|
if (ImGuizmo::IsUsing())
|
||||||
{
|
{
|
||||||
@@ -1944,7 +1898,7 @@ void editor_mode::render_straight_gizmo()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto const &grabbed{state.drag_line};
|
auto const &grabbed{state.drag_line};
|
||||||
glm::dvec3 moved{camerapos + glm::dvec3(state.gizmo[3])};
|
glm::dvec3 moved{frame.camera + glm::dvec3(state.gizmo[3])};
|
||||||
std::function<glm::dvec3(glm::dvec3 const &)> transform;
|
std::function<glm::dvec3(glm::dvec3 const &)> transform;
|
||||||
if (state.handle == 2)
|
if (state.handle == 2)
|
||||||
{
|
{
|
||||||
@@ -2250,21 +2204,14 @@ bool editor_mode::place_straight_tool()
|
|||||||
void editor_mode::render_straight_tool_gizmo()
|
void editor_mode::render_straight_tool_gizmo()
|
||||||
{
|
{
|
||||||
auto &state{m_straights};
|
auto &state{m_straights};
|
||||||
ImGuizmo::BeginFrame();
|
gizmo_frame const frame;
|
||||||
ImGuizmo::SetOrthographic(Global.EditorOrtho);
|
|
||||||
ImGuiIO const &io = ImGui::GetIO();
|
|
||||||
ImGuizmo::SetRect(0.0f, 0.0f, io.DisplaySize.x, io.DisplaySize.y);
|
|
||||||
glm::mat4 const view = GfxRenderer->Camera_View_Matrix();
|
|
||||||
glm::dvec3 const camerapos = GfxRenderer->Camera_Position();
|
|
||||||
float const aspect = io.DisplaySize.y > 0.0f ? io.DisplaySize.x / io.DisplaySize.y : 1.0f;
|
|
||||||
glm::mat4 const projection = editor_mode::projection_matrix(aspect);
|
|
||||||
if (false == state.tool_dragging)
|
if (false == state.tool_dragging)
|
||||||
state.tool_gizmo = glm::translate(glm::mat4(1.0f), glm::vec3(state.tool_handle - camerapos));
|
state.tool_gizmo = glm::translate(glm::mat4(1.0f), glm::vec3(state.tool_handle - frame.camera));
|
||||||
ImGuizmo::Manipulate(glm::value_ptr(view), glm::value_ptr(projection), ImGuizmo::TRANSLATE, ImGuizmo::WORLD, glm::value_ptr(state.tool_gizmo), nullptr, nullptr);
|
frame.manipulate(ImGuizmo::TRANSLATE, state.tool_gizmo, 0.0f);
|
||||||
if (ImGuizmo::IsUsing())
|
if (ImGuizmo::IsUsing())
|
||||||
{
|
{
|
||||||
state.tool_dragging = true;
|
state.tool_dragging = true;
|
||||||
auto const moved{camerapos + glm::dvec3(state.tool_gizmo[3])};
|
auto const moved{frame.camera + glm::dvec3(state.tool_gizmo[3])};
|
||||||
state.tool_handle = {moved.x, state.tool_handle.y, moved.z};
|
state.tool_handle = {moved.x, state.tool_handle.y, moved.z};
|
||||||
}
|
}
|
||||||
else if (state.tool_dragging)
|
else if (state.tool_dragging)
|
||||||
@@ -2365,8 +2312,7 @@ void editor_mode::delete_selected_track()
|
|||||||
snap.node_name = track->name();
|
snap.node_name = track->name();
|
||||||
snap.position = track->location();
|
snap.position = track->location();
|
||||||
snap.removed = {track};
|
snap.removed = {track};
|
||||||
if (m_max_history_size >= 0 && (int)m_history.size() >= m_max_history_size)
|
trim_history();
|
||||||
m_history.erase(m_history.begin(), m_history.begin() + ((int)m_history.size() - m_max_history_size + 1));
|
|
||||||
m_history.push_back(std::move(snap));
|
m_history.push_back(std::move(snap));
|
||||||
g_redo.clear();
|
g_redo.clear();
|
||||||
editor_track::retire(*track);
|
editor_track::retire(*track);
|
||||||
@@ -2422,7 +2368,6 @@ bool editor_mode::start_extend()
|
|||||||
if (track == nullptr || (track->eType != tt_Normal && track->eType != tt_Switch) || false == editor_track::is_supported(*track))
|
if (track == nullptr || (track->eType != tt_Normal && track->eType != tt_Switch) || false == editor_track::is_supported(*track))
|
||||||
return false;
|
return false;
|
||||||
screen_projection const projection;
|
screen_projection const projection;
|
||||||
ImVec2 const mouse = ImGui::GetIO().MousePos;
|
|
||||||
for (int i = 0; i < static_cast<int>(track->m_paths.size()); ++i)
|
for (int i = 0; i < static_cast<int>(track->m_paths.size()); ++i)
|
||||||
{
|
{
|
||||||
auto const &path{track->m_paths[i]};
|
auto const &path{track->m_paths[i]};
|
||||||
@@ -2432,10 +2377,7 @@ bool editor_mode::start_extend()
|
|||||||
if (editor_track::is_connected(*track, point))
|
if (editor_track::is_connected(*track, point))
|
||||||
continue;
|
continue;
|
||||||
auto const position{editor_track::point_position(*track, point)};
|
auto const position{editor_track::point_position(*track, point)};
|
||||||
ImVec2 screen;
|
if (projection.mouse_distance2(position) > kHandleRadius * kHandleRadius * 1.5f)
|
||||||
if (false == projection.project(position, screen))
|
|
||||||
continue;
|
|
||||||
if ((screen.x - mouse.x) * (screen.x - mouse.x) + (screen.y - mouse.y) * (screen.y - mouse.y) > kHandleRadius * kHandleRadius * 1.5f)
|
|
||||||
continue;
|
continue;
|
||||||
auto const &start{path.points[segment_data::point::start]};
|
auto const &start{path.points[segment_data::point::start]};
|
||||||
auto const &end{path.points[segment_data::point::end]};
|
auto const &end{path.points[segment_data::point::end]};
|
||||||
@@ -2576,8 +2518,7 @@ void editor_mode::finish_extend()
|
|||||||
editor_track::commit({insert});
|
editor_track::commit({insert});
|
||||||
created.push_back(insert);
|
created.push_back(insert);
|
||||||
}
|
}
|
||||||
push_track_snapshot(std::move(states), std::move(created));
|
push_track_snapshot(std::move(states), std::move(created), std::move(removed));
|
||||||
m_history.back().removed = std::move(removed);
|
|
||||||
straight_refresh();
|
straight_refresh();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2692,8 +2633,7 @@ void editor_mode::insert_switch(editor_track::straight const &Line, double const
|
|||||||
std::vector<TTrack *> removed;
|
std::vector<TTrack *> removed;
|
||||||
if (false == place_switch_on_straight(Line, m_switch.templates[m_switch.armed], nullptr, Along, Direction, Side, true, states, created, removed))
|
if (false == place_switch_on_straight(Line, m_switch.templates[m_switch.armed], nullptr, Along, Direction, Side, true, states, created, removed))
|
||||||
return;
|
return;
|
||||||
push_track_snapshot(std::move(states), std::move(created));
|
push_track_snapshot(std::move(states), std::move(created), std::move(removed));
|
||||||
m_history.back().removed = std::move(removed);
|
|
||||||
straight_refresh();
|
straight_refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3408,8 +3348,7 @@ bool editor_mode::insert_double_slip(editor_track::straight const &Line, glm::dv
|
|||||||
auto const parts{build_double_slip(pointA, pointB, pointC, pointD, crossing, heightfirst(alongfirst), first, direction, angle, radius, style != nullptr ? *style : *Line.tracks.front())};
|
auto const parts{build_double_slip(pointA, pointB, pointC, pointD, crossing, heightfirst(alongfirst), first, direction, angle, radius, style != nullptr ? *style : *Line.tracks.front())};
|
||||||
editor_track::commit(parts);
|
editor_track::commit(parts);
|
||||||
created.insert(created.end(), parts.begin(), parts.end());
|
created.insert(created.end(), parts.begin(), parts.end());
|
||||||
push_track_snapshot(std::move(states), std::move(created));
|
push_track_snapshot(std::move(states), std::move(created), std::move(removed));
|
||||||
m_history.back().removed = std::move(removed);
|
|
||||||
straight_refresh();
|
straight_refresh();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -3548,8 +3487,7 @@ bool editor_mode::replace_double_slip(TTrack &Part, editor_track::switch_templat
|
|||||||
commitlist.push_back(track);
|
commitlist.push_back(track);
|
||||||
editor_track::commit(commitlist);
|
editor_track::commit(commitlist);
|
||||||
created.insert(created.end(), parts2.begin(), parts2.end());
|
created.insert(created.end(), parts2.begin(), parts2.end());
|
||||||
push_track_snapshot(std::move(states), std::move(created));
|
push_track_snapshot(std::move(states), std::move(created), std::move(removed));
|
||||||
m_history.back().removed = std::move(removed);
|
|
||||||
straight_refresh();
|
straight_refresh();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -3729,7 +3667,6 @@ void editor_mode::insert_curved_switch(int const Direction, int const Side)
|
|||||||
editor_track::commit({track});
|
editor_track::commit({track});
|
||||||
created.push_back(track);
|
created.push_back(track);
|
||||||
}
|
}
|
||||||
push_track_snapshot(std::move(states), std::move(created));
|
push_track_snapshot(std::move(states), std::move(created), std::move(removed));
|
||||||
m_history.back().removed = std::move(removed);
|
|
||||||
straight_refresh();
|
straight_refresh();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,11 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
#include "application/editormode.h"
|
#include "application/editormode.h"
|
||||||
#include "rendering/renderer.h"
|
#include "rendering/renderer.h"
|
||||||
|
#include "utilities/Globals.h"
|
||||||
#include "imgui/imgui.h"
|
#include "imgui/imgui.h"
|
||||||
|
#include "imgui/ImGuizmo.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
// world to screen projection of the current camera, for overlays drawn with ImGui
|
// world to screen projection of the current camera, for overlays drawn with ImGui
|
||||||
class screen_projection
|
class screen_projection
|
||||||
@@ -54,6 +58,15 @@ class screen_projection
|
|||||||
b = glm::mix(b, a, (kNear - b.w) / (a.w - b.w));
|
b = glm::mix(b, a, (kNear - b.w) / (a.w - b.w));
|
||||||
Drawlist->AddLine(screen(a), screen(b), Color, Thickness);
|
Drawlist->AddLine(screen(a), screen(b), Color, Thickness);
|
||||||
}
|
}
|
||||||
|
// squared distance on the screen from the mouse cursor to the point, the largest float for points behind the camera
|
||||||
|
float mouse_distance2(glm::dvec3 const &Point) const
|
||||||
|
{
|
||||||
|
ImVec2 position;
|
||||||
|
if (false == project(Point, position))
|
||||||
|
return std::numeric_limits<float>::max();
|
||||||
|
auto const &mouse{ImGui::GetIO().MousePos};
|
||||||
|
return (position.x - mouse.x) * (position.x - mouse.x) + (position.y - mouse.y) * (position.y - mouse.y);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr float kNear{0.1f};
|
static constexpr float kNear{0.1f};
|
||||||
@@ -61,3 +74,29 @@ class screen_projection
|
|||||||
glm::dvec3 m_camera;
|
glm::dvec3 m_camera;
|
||||||
glm::mat4 m_viewprojection;
|
glm::mat4 m_viewprojection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// starts a gizmo frame over the whole display, the view and the projection are those of the current camera
|
||||||
|
struct gizmo_frame
|
||||||
|
{
|
||||||
|
glm::mat4 view;
|
||||||
|
glm::mat4 projection;
|
||||||
|
glm::dvec3 camera;
|
||||||
|
|
||||||
|
gizmo_frame()
|
||||||
|
{
|
||||||
|
ImGuizmo::BeginFrame();
|
||||||
|
ImGuizmo::SetOrthographic(Global.EditorOrtho);
|
||||||
|
ImGuiIO const &io = ImGui::GetIO();
|
||||||
|
ImGuizmo::SetRect(0.0f, 0.0f, io.DisplaySize.x, io.DisplaySize.y);
|
||||||
|
view = GfxRenderer->Camera_View_Matrix();
|
||||||
|
camera = GfxRenderer->Camera_Position();
|
||||||
|
projection = editor_mode::projection_matrix(io.DisplaySize.y > 0.0f ? io.DisplaySize.x / io.DisplaySize.y : 1.0f);
|
||||||
|
}
|
||||||
|
// moves the gizmo, placed at the point given in world space, with snapping to the step when ctrl is held
|
||||||
|
bool manipulate(ImGuizmo::OPERATION const Operation, glm::mat4 &Gizmo, float const Snap, glm::mat4 *Delta = nullptr) const
|
||||||
|
{
|
||||||
|
glm::vec3 snapvalue(Snap);
|
||||||
|
float const *snap = Global.ctrlState && Snap > 0.0f ? &snapvalue.x : nullptr;
|
||||||
|
return ImGuizmo::Manipulate(&view[0][0], &projection[0][0], Operation, ImGuizmo::WORLD, &Gizmo[0][0], Delta != nullptr ? &(*Delta)[0][0] : nullptr, snap);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user