mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-06 00:53:52 +00:00
fix(editor): Clear All, New Terrain reset, right-click menu, gizmo drag
- Clear All now actually removes all objects and NPCs (was only clearing selections before). Uses new ObjectPlacer::clearAll() method. - New Terrain clears all objects/NPCs and resets viewport before creating fresh terrain. Fixes stale state from previous session. - Right-click context menu works on both objects AND NPCs with appropriate options for each (Move/Rotate/Scale for objects, Fly To/Duplicate for NPCs) - Gizmo drag: left-click now confirms the transform (ends drag) instead of requiring mouse-up. Right-click cancels. Camera no longer steals mouse events while gizmo is active. - Right-click on unselected area passes through to camera correctly
This commit is contained in:
parent
d9ed7be36c
commit
befa12f9e6
3 changed files with 64 additions and 30 deletions
|
|
@ -281,26 +281,32 @@ void EditorApp::processEvents() {
|
|||
}
|
||||
|
||||
if ((event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) && !io.WantCaptureMouse) {
|
||||
// Right-click context menu on selected objects
|
||||
// Right-click on selected objects = context menu
|
||||
if (event.button.button == SDL_BUTTON_RIGHT && event.type == SDL_MOUSEBUTTONDOWN) {
|
||||
auto& giz = viewport_.getGizmo();
|
||||
if (giz.isDragging()) {
|
||||
giz.endDrag();
|
||||
giz.setMode(TransformMode::None);
|
||||
} else if (objectPlacer_.getSelected()) {
|
||||
} else if (objectPlacer_.getSelected() || npcSpawner_.getSelected()) {
|
||||
openContextMenu_ = true;
|
||||
} else {
|
||||
camera_.processMouseButton(event.button);
|
||||
}
|
||||
} else if (event.button.button == SDL_BUTTON_RIGHT && event.type == SDL_MOUSEBUTTONUP) {
|
||||
if (!objectPlacer_.getSelected() && !npcSpawner_.getSelected())
|
||||
camera_.processMouseButton(event.button);
|
||||
} else {
|
||||
camera_.processMouseButton(event.button);
|
||||
// Only pass to camera if gizmo not active
|
||||
auto& giz = viewport_.getGizmo();
|
||||
if (!giz.isDragging())
|
||||
camera_.processMouseButton(event.button);
|
||||
}
|
||||
|
||||
// Left click
|
||||
if (event.button.button == SDL_BUTTON_LEFT && terrain_.isLoaded()) {
|
||||
// End gizmo drag on click release
|
||||
auto& giz = viewport_.getGizmo();
|
||||
if (giz.isDragging() && event.type == SDL_MOUSEBUTTONUP) {
|
||||
// End gizmo drag on left click
|
||||
if (giz.isDragging() && event.type == SDL_MOUSEBUTTONDOWN) {
|
||||
giz.endDrag();
|
||||
giz.setMode(TransformMode::None);
|
||||
} else if (event.type == SDL_MOUSEBUTTONDOWN) {
|
||||
|
|
@ -540,6 +546,12 @@ void EditorApp::loadADT(const std::string& mapName, int tileX, int tileY) {
|
|||
|
||||
void EditorApp::createNewTerrain(const std::string& mapName, int tileX, int tileY, float baseHeight, Biome biome) {
|
||||
terrain_ = TerrainEditor::createBlankTerrain(tileX, tileY, baseHeight, biome);
|
||||
// Clear previous state
|
||||
objectPlacer_.clearAll();
|
||||
npcSpawner_.clearSelection();
|
||||
npcSpawner_.getSpawns().clear();
|
||||
viewport_.clearObjects();
|
||||
|
||||
terrainEditor_.setTerrain(&terrain_);
|
||||
terrainEditor_.history().clear();
|
||||
texturePainter_.setTerrain(&terrain_);
|
||||
|
|
@ -552,6 +564,8 @@ void EditorApp::createNewTerrain(const std::string& mapName, int tileX, int tile
|
|||
loadedMap_ = mapName;
|
||||
loadedTileX_ = tileX;
|
||||
loadedTileY_ = tileY;
|
||||
lastObjectCount_ = 0;
|
||||
objectsDirty_ = false;
|
||||
|
||||
float centerX = (32.0f - tileY) * 533.33333f - 8.0f * 533.33333f / 16.0f;
|
||||
float centerY = (32.0f - tileX) * 533.33333f - 8.0f * 533.33333f / 16.0f;
|
||||
|
|
|
|||
|
|
@ -100,10 +100,13 @@ void EditorUI::renderMenuBar(EditorApp& app) {
|
|||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::MenuItem("Clear All", nullptr, false, app.hasTerrainLoaded())) {
|
||||
app.getTerrainEditor().history().clear();
|
||||
app.getObjectPlacer().clearSelection();
|
||||
if (ImGui::MenuItem("Clear All Objects/NPCs", nullptr, false, app.hasTerrainLoaded())) {
|
||||
app.getObjectPlacer().clearAll();
|
||||
app.getNpcSpawner().clearSelection();
|
||||
app.getNpcSpawner().getSpawns().clear();
|
||||
app.getTerrainEditor().history().clear();
|
||||
app.markObjectsDirty();
|
||||
app.showToast("All objects and NPCs cleared");
|
||||
}
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Quick Save", "Ctrl+S", false, app.hasTerrainLoaded()))
|
||||
|
|
@ -900,38 +903,54 @@ void EditorUI::renderContextMenu(EditorApp& app) {
|
|||
app.clearContextMenuFlag();
|
||||
}
|
||||
if (ImGui::BeginPopup("ObjectContextMenu")) {
|
||||
auto* sel = app.getObjectPlacer().getSelected();
|
||||
if (!sel) { ImGui::EndPopup(); return; }
|
||||
auto* objSel = app.getObjectPlacer().getSelected();
|
||||
auto* npcSel = app.getNpcSpawner().getSelected();
|
||||
if (!objSel && !npcSel) { ImGui::EndPopup(); return; }
|
||||
|
||||
std::string display = sel->path;
|
||||
auto slash = display.rfind('\\');
|
||||
if (slash != std::string::npos) display = display.substr(slash + 1);
|
||||
ImGui::TextColored(ImVec4(1, 0.9f, 0.3f, 1), "%s", display.c_str());
|
||||
if (objSel) {
|
||||
std::string display = objSel->path;
|
||||
auto slash = display.rfind('\\');
|
||||
if (slash != std::string::npos) display = display.substr(slash + 1);
|
||||
ImGui::TextColored(ImVec4(1, 0.9f, 0.3f, 1), "%s", display.c_str());
|
||||
} else {
|
||||
ImGui::TextColored(ImVec4(1, 0.9f, 0.3f, 1), "%s (NPC)", npcSel->name.c_str());
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Move (left-drag)"))
|
||||
app.startGizmoMode(TransformMode::Move);
|
||||
if (ImGui::MenuItem("Rotate (left-drag)"))
|
||||
app.startGizmoMode(TransformMode::Rotate);
|
||||
if (ImGui::MenuItem("Scale (left-drag)"))
|
||||
app.startGizmoMode(TransformMode::Scale);
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginMenu("Constrain Axis")) {
|
||||
if (ImGui::MenuItem("All Axes")) app.setGizmoAxis(TransformAxis::All);
|
||||
if (ImGui::MenuItem("X (Red)")) app.setGizmoAxis(TransformAxis::X);
|
||||
if (ImGui::MenuItem("Y (Green)")) app.setGizmoAxis(TransformAxis::Y);
|
||||
if (ImGui::MenuItem("Z (Blue)")) app.setGizmoAxis(TransformAxis::Z);
|
||||
ImGui::EndMenu();
|
||||
if (objSel) {
|
||||
if (ImGui::MenuItem("Move (G)"))
|
||||
app.startGizmoMode(TransformMode::Move);
|
||||
if (ImGui::MenuItem("Rotate (R)"))
|
||||
app.startGizmoMode(TransformMode::Rotate);
|
||||
if (ImGui::MenuItem("Scale (T)"))
|
||||
app.startGizmoMode(TransformMode::Scale);
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Snap to Ground"))
|
||||
app.snapSelectedToGround();
|
||||
if (ImGui::MenuItem("Fly To"))
|
||||
app.flyToSelected();
|
||||
}
|
||||
if (npcSel) {
|
||||
if (ImGui::MenuItem("Fly To"))
|
||||
app.flyToSelected();
|
||||
if (ImGui::MenuItem("Duplicate")) {
|
||||
CreatureSpawn copy = *npcSel;
|
||||
copy.position += glm::vec3(10, 10, 0);
|
||||
app.getNpcSpawner().placeCreature(copy);
|
||||
app.markObjectsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Delete")) {
|
||||
app.getObjectPlacer().deleteSelected();
|
||||
if (objSel) { app.getObjectPlacer().deleteSelected(); }
|
||||
else { app.getNpcSpawner().removeCreature(app.getNpcSpawner().getSelectedIndex()); }
|
||||
app.markObjectsDirty();
|
||||
}
|
||||
if (ImGui::MenuItem("Deselect"))
|
||||
if (ImGui::MenuItem("Deselect")) {
|
||||
app.getObjectPlacer().clearSelection();
|
||||
app.getNpcSpawner().clearSelection();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ public:
|
|||
bool loadFromFile(const std::string& path);
|
||||
|
||||
const std::vector<PlacedObject>& getObjects() const { return objects_; }
|
||||
void clearAll() { objects_.clear(); undoStack_.clear(); selectedIdx_ = -1; }
|
||||
size_t objectCount() const { return objects_.size(); }
|
||||
|
||||
float getPlacementRotationY() const { return placementRotY_; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue