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

feat(editor): add orthographic top view toggle

This commit is contained in:
maj00r
2026-10-02 22:47:29 +02:00
parent b19f3de0d4
commit 78c4b9f6df
5 changed files with 77 additions and 19 deletions

View File

@@ -1431,9 +1431,8 @@ void editor_mode::draw_orthophoto()
Camera.SetMatrix(viewmatrix);
glm::mat4 const view = glm::mat4(glm::mat3(viewmatrix));
ImGuiIO const &io = ImGui::GetIO();
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;
m_orthophoto.draw(glm::perspective(fovy, aspect, 0.1f, 10000.0f) * view, Camera.Pos, io.DisplaySize.x, io.DisplaySize.y);
m_orthophoto.draw(editor_mode::projection_matrix(aspect) * view, Camera.Pos, io.DisplaySize.x, io.DisplaySize.y);
}
editor_terrain *editor_mode::terrain_at(double X, double Z)
@@ -2107,9 +2106,8 @@ void editor_mode::draw_area_fill_outline() const
ImGuiIO const &io = ImGui::GetIO();
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 viewprojection = glm::perspective(fovy, aspect, 0.1f, 10000.0f) * view;
glm::mat4 const viewprojection = editor_mode::projection_matrix(aspect) * view;
auto const to_clip = [&](glm::dvec3 const &Point) { return viewprojection * glm::vec4(glm::vec3(Point - camerapos), 1.0f); };
auto const to_screen = [&](glm::vec4 const &Clip) {
@@ -2198,6 +2196,14 @@ void editor_mode::render_area_fill()
void editor_mode::render_gizmo_options()
{
if (ImGui::Button(Global.EditorOrtho ? "3D view (O)" : "Top view, orthographic (O)"))
toggle_ortho();
if (Global.EditorOrtho)
{
ImGui::SameLine();
ImGui::SetNextItemWidth(120.0f);
ImGui::SliderFloat("Extent (m), wheel", &Global.EditorOrthoExtent, 5.0f, 5000.0f, "%.0f", 3.0f);
}
ImGui::Checkbox("Enabled", &m_gizmo_enabled);
if (!m_gizmo_enabled)
return;
@@ -2265,7 +2271,7 @@ void editor_mode::render_gizmo()
}
ImGuizmo::BeginFrame();
ImGuizmo::SetOrthographic(false);
ImGuizmo::SetOrthographic(Global.EditorOrtho);
ImGuiIO const &io = ImGui::GetIO();
ImGuizmo::SetRect(0.0f, 0.0f, io.DisplaySize.x, io.DisplaySize.y);
@@ -2278,9 +2284,8 @@ void editor_mode::render_gizmo()
// the engine's own projection bakes in reverse-Z (and screen orientation), which ImGuizmo
// doesn't expect; rebuild a clean, standard perspective that matches the rendered view.
// for the main viewport the engine uses a symmetric frustum with this exact fov/aspect.
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);
glm::mat4 const projection = editor_mode::projection_matrix(aspect);
if (!m_node)
{
@@ -2462,9 +2467,46 @@ void editor_mode::render_include_gizmo(glm::mat4 const &View, glm::mat4 const &P
apply_include();
}
glm::mat4 editor_mode::projection_matrix(float const Aspect)
{
if (Global.EditorOrtho)
{
auto const height{Global.EditorOrthoExtent};
return glm::ortho(-height * Aspect, height * Aspect, -height, height, -10000.0f, 10000.0f);
}
return glm::perspective(glm::radians(Global.FieldOfView / Global.ZoomFactor), Aspect, 0.1f, 10000.0f);
}
void editor_mode::toggle_ortho()
{
Global.EditorOrtho = !Global.EditorOrtho;
if (Global.EditorOrtho)
{
m_ortho_pitch = Camera.Angle.x;
Camera.Angle.x = -M_PI_2;
Camera.Angle.z = 0.0;
}
else
{
Camera.Angle.x = m_ortho_pitch;
}
}
void editor_mode::on_scroll(double const Xoffset, double const Yoffset)
{
if (false == Global.EditorOrtho || ImGui::GetIO().WantCaptureMouse)
return;
Global.EditorOrthoExtent = std::clamp(Global.EditorOrthoExtent * static_cast<float>(std::pow(0.85, Yoffset)), 5.0f, 5000.0f);
}
void editor_mode::update_camera(double const Deltatime)
{
Camera.Update();
if (Global.EditorOrtho)
{
Camera.Angle.x = -M_PI_2;
Camera.Angle.z = 0.0;
}
// focus animation runs after Camera.Update() so it overrides any residual velocity/rotation;
// it smoothly drives both position and orientation toward the framed object
@@ -2544,6 +2586,8 @@ void editor_mode::exit()
m_track_point = {};
m_route = {};
m_route_gizmo_using = false;
if (Global.EditorOrtho)
toggle_ortho();
g_redo.clear();
m_history.clear();
@@ -2588,6 +2632,7 @@ void editor_mode::on_key(int const Key, int const Scancode, int const Action, in
bool handled = true;
switch (Key)
{
case GLFW_KEY_O: toggle_ortho(); break;
case GLFW_KEY_Q: m_gizmo_op = gizmo_operation::translate; break;
case GLFW_KEY_W: m_gizmo_op = gizmo_operation::rotate; break;
case GLFW_KEY_E: m_gizmo_op = gizmo_operation::scale; break;

View File

@@ -50,10 +50,7 @@ class editor_mode : public application_mode
void on_key(int Key, int Scancode, int Action, int Mods) override;
void on_cursor_pos(double Horizontal, double Vertical) override;
void on_mouse_button(int Button, int Action, int Mods) override;
void on_scroll(double const Xoffset, double const Yoffset) override
{
;
}
void on_scroll(double const Xoffset, double const Yoffset) override;
void on_window_resize(int w, int h) override
{
;
@@ -64,6 +61,8 @@ class editor_mode : public application_mode
static bool focus_active();
static void set_focus_active(bool isActive);
static TCamera& get_camera() { return Camera; }
static glm::mat4 projection_matrix(float const Aspect);
void toggle_ortho();
static bool change_history() { return m_change_history; }
static void set_change_history(bool enabled) { m_change_history = enabled; }
static bool settings_open() { return m_settings_open; }
@@ -148,6 +147,7 @@ class editor_mode : public application_mode
static bool m_change_history;
static bool m_settings_open;
double m_ortho_pitch{0.0};
// camera fly-mode (right mouse button held); used to flush motion when it's released
command_relay m_camera_relay;
bool m_camera_flying{false};

View File

@@ -36,9 +36,8 @@ class screen_projection
ImGuiIO const &io = ImGui::GetIO();
m_size = io.DisplaySize;
m_camera = GfxRenderer->Camera_Position();
float const fovy = glm::radians(Global.FieldOfView / Global.ZoomFactor);
float const aspect = m_size.y > 0.0f ? m_size.x / m_size.y : 1.0f;
m_viewprojection = glm::perspective(fovy, aspect, 0.1f, 10000.0f) * GfxRenderer->Camera_View_Matrix();
m_viewprojection = editor_mode::projection_matrix(aspect) * GfxRenderer->Camera_View_Matrix();
}
glm::vec4 clip(glm::dvec3 const &Point) const
@@ -244,15 +243,14 @@ 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());
ImGuizmo::BeginFrame();
ImGuizmo::SetOrthographic(false);
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 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);
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;
@@ -869,14 +867,13 @@ void editor_mode::render_route_gizmo()
}
ImGuizmo::BeginFrame();
ImGuizmo::SetOrthographic(false);
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 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);
glm::mat4 const projection = editor_mode::projection_matrix(aspect);
auto const position{route_vertex_position(route.vertex)};
if (false == m_route_gizmo_using)