From 7c506f582a792252f48acd170097510d97261dfd Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 6 May 2026 02:04:50 -0700 Subject: [PATCH] feat(editor): flyToSelected places camera with proper aim and offset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously just teleported camera 30u directly above the target — the user still had to manually look down to see anything. Now positions the camera back along the current view direction, slightly elevated, and aims it at the selection so the target is visible immediately. Removes the round-trip through manual rotation after every Fly To. --- tools/editor/editor_app.cpp | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/tools/editor/editor_app.cpp b/tools/editor/editor_app.cpp index e51c7cbc..ead6ccef 100644 --- a/tools/editor/editor_app.cpp +++ b/tools/editor/editor_app.cpp @@ -1455,15 +1455,34 @@ void EditorApp::addAdjacentTile(int offsetX, int offsetY) { } void EditorApp::flyToSelected() { - auto* sel = objectPlacer_.getSelected(); - if (sel) { - camera_.setPosition(sel->position + glm::vec3(0, 0, 30)); - return; - } - auto* npc = npcSpawner_.getSelected(); - if (npc) { - camera_.setPosition(npc->position + glm::vec3(0, 0, 30)); + glm::vec3 target; + bool have = false; + if (auto* sel = objectPlacer_.getSelected()) { + target = sel->position; + have = true; + } else if (auto* npc = npcSpawner_.getSelected()) { + target = npc->position; + have = true; } + if (!have) return; + + // Place camera back-and-up from the target along the current view direction + // and aim it at the target. Distance scales with camera speed so it works + // both for tight spawn lists and for far-flung WMOs. + glm::vec3 fwd = camera_.getCamera().getForward(); + if (glm::length(fwd) < 0.001f) fwd = glm::vec3(1, 0, 0); + glm::vec3 back = -glm::normalize(glm::vec3(fwd.x, fwd.y, 0.0f)); + if (glm::length(back) < 0.001f) back = glm::vec3(-1, 0, 0); + + glm::vec3 cam = target + back * 25.0f + glm::vec3(0, 0, 15); + camera_.setPosition(cam); + + // Aim at target — yaw is atan2(toX, toY) in editor convention; pitch from height delta. + glm::vec3 to = target - cam; + float yaw = glm::degrees(std::atan2(to.x, to.y)); + float horiz = std::sqrt(to.x * to.x + to.y * to.y); + float pitch = glm::degrees(std::atan2(to.z, horiz)); + camera_.setYawPitch(yaw, pitch); } void EditorApp::generateCompleteZone() {