mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-06 00:53:52 +00:00
fix(editor): terrain raycast on rough terrain, keyboard shortcuts, context menu
- Raycast AABB now uses actual min/max vertex heights per chunk instead of fixed ±200 padding (fixes misses on sculpted terrain) - Right-click context menu opens correctly (deferred popup via flag since ImGui::OpenPopup must be called within ImGui frame) - Keyboard shortcuts: G=Move, R=Rotate, T=Scale, X/Y=axis lock, Escape=deselect, Delete works in any mode for objects/NPCs - Delete key now removes selected NPC in NPC mode too
This commit is contained in:
parent
f38884856f
commit
ace6173401
4 changed files with 40 additions and 7 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue