diff --git a/tools/editor/editor_app.cpp b/tools/editor/editor_app.cpp index 12c975bb..ec67b694 100644 --- a/tools/editor/editor_app.cpp +++ b/tools/editor/editor_app.cpp @@ -189,9 +189,27 @@ void EditorApp::processEvents() { if (event.type == SDL_KEYDOWN) { auto sc = event.key.keysym.scancode; if (sc == SDL_SCANCODE_F3) setWireframe(!isWireframe()); - if (sc == SDL_SCANCODE_DELETE && mode_ == EditorMode::PlaceObject) { - objectPlacer_.deleteSelected(); - objectsDirty_ = true; + // Transform shortcuts (Blender-style) + if (objectPlacer_.getSelected()) { + if (sc == SDL_SCANCODE_G) startGizmoMode(TransformMode::Move); + if (sc == SDL_SCANCODE_R) startGizmoMode(TransformMode::Rotate); + if (sc == SDL_SCANCODE_T) startGizmoMode(TransformMode::Scale); + if (sc == SDL_SCANCODE_X) setGizmoAxis(TransformAxis::X); + if (sc == SDL_SCANCODE_Y) setGizmoAxis(TransformAxis::Y); + if (sc == SDL_SCANCODE_ESCAPE) { + viewport_.getGizmo().endDrag(); + viewport_.getGizmo().setMode(TransformMode::None); + objectPlacer_.clearSelection(); + } + } + if (sc == SDL_SCANCODE_DELETE) { + if (objectPlacer_.getSelected()) { + objectPlacer_.deleteSelected(); + objectsDirty_ = true; + } else if (npcSpawner_.getSelected()) { + npcSpawner_.removeCreature(npcSpawner_.getSelectedIndex()); + objectsDirty_ = true; + } } if (sc == SDL_SCANCODE_Z && (event.key.keysym.mod & KMOD_CTRL)) { if (event.key.keysym.mod & KMOD_SHIFT) @@ -242,7 +260,7 @@ void EditorApp::processEvents() { giz.endDrag(); giz.setMode(TransformMode::None); } else if (objectPlacer_.getSelected()) { - ImGui::OpenPopup("ObjectContextMenu"); + openContextMenu_ = true; } else { camera_.processMouseButton(event.button); } diff --git a/tools/editor/editor_app.hpp b/tools/editor/editor_app.hpp index 51bd1803..3519ef95 100644 --- a/tools/editor/editor_app.hpp +++ b/tools/editor/editor_app.hpp @@ -62,6 +62,8 @@ public: void startGizmoMode(TransformMode mode); void setGizmoAxis(TransformAxis axis); TransformGizmo& getGizmo() { return viewport_.getGizmo(); } + bool shouldOpenContextMenu() const { return openContextMenu_; } + void clearContextMenuFlag() { openContextMenu_ = false; } float getWaterHeight() const { return waterHeight_; } void setWaterHeight(float h) { waterHeight_ = h; } @@ -92,6 +94,7 @@ private: bool imguiInitialized_ = false; bool painting_ = false; bool objectsDirty_ = false; + bool openContextMenu_ = false; size_t lastObjectCount_ = 0; EditorMode mode_ = EditorMode::Sculpt; float waterHeight_ = 100.0f; diff --git a/tools/editor/editor_ui.cpp b/tools/editor/editor_ui.cpp index bd3f5989..b5f866ce 100644 --- a/tools/editor/editor_ui.cpp +++ b/tools/editor/editor_ui.cpp @@ -592,6 +592,10 @@ void EditorUI::renderWaterPanel(EditorApp& app) { } void EditorUI::renderContextMenu(EditorApp& app) { + if (app.shouldOpenContextMenu()) { + ImGui::OpenPopup("ObjectContextMenu"); + app.clearContextMenuFlag(); + } if (ImGui::BeginPopup("ObjectContextMenu")) { auto* sel = app.getObjectPlacer().getSelected(); if (!sel) { ImGui::EndPopup(); return; } diff --git a/tools/editor/terrain_editor.cpp b/tools/editor/terrain_editor.cpp index 7cf624bb..0d8f74a6 100644 --- a/tools/editor/terrain_editor.cpp +++ b/tools/editor/terrain_editor.cpp @@ -133,11 +133,19 @@ bool TerrainEditor::raycastTerrain(const rendering::Ray& ray, glm::vec3& hitPos) const auto& chunk = terrain_->chunks[chunkIdx]; if (!chunk.hasHeightMap()) continue; - // Quick AABB check: compute chunk bounds in render space + // Quick AABB check using actual vertex extent glm::vec3 corner0 = chunkVertexWorldPos(chunkIdx, 0); glm::vec3 corner1 = chunkVertexWorldPos(chunkIdx, 144); - glm::vec3 minB = glm::min(corner0, corner1) - glm::vec3(0, 0, 200); - glm::vec3 maxB = glm::max(corner0, corner1) + glm::vec3(0, 0, 200); + glm::vec3 minB = glm::min(corner0, corner1); + glm::vec3 maxB = glm::max(corner0, corner1); + // Expand Z by actual height range in chunk + float minH = chunk.heightMap.heights[0], maxH = minH; + for (int h = 1; h < 145; h++) { + minH = std::min(minH, chunk.heightMap.heights[h]); + maxH = std::max(maxH, chunk.heightMap.heights[h]); + } + minB.z = chunk.position[2] + minH - 10.0f; + maxB.z = chunk.position[2] + maxH + 10.0f; // Simple AABB-ray test float tmin = -1e30f, tmax = 1e30f;