mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-08 18:13:52 +00:00
fix(editor): crater button now click-to-place on terrain
The "Create Crater at Cursor" button used the brush's last hover position, which was stale by the time the user clicked the button — the cursor had to move onto the button itself, dragging the brush position along with it. Result: crater spawned somewhere between where the user wanted and the button. New flow: button arms a "click on terrain to place crater" mode (captures the user's chosen radius/depth/rim at arm time). The next left-click anywhere on terrain spawns the crater at the actual click position, regardless of brush state. Button label changes to "ARMED — click on terrain to place" while waiting, with a Cancel button + Esc to dismiss. Misses on terrain leave the mode armed so the user can retry without re-pressing the button.
This commit is contained in:
parent
b35c9341ec
commit
0e2b55f9fd
3 changed files with 64 additions and 4 deletions
|
|
@ -351,6 +351,10 @@ void EditorApp::processEvents() {
|
|||
objectPlacer_.clearSelection();
|
||||
npcSpawner_.clearSelection();
|
||||
ui_.clearPath();
|
||||
if (pendingCrater_.active) {
|
||||
pendingCrater_.active = false;
|
||||
showToast("Crater placement cancelled");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sc == SDL_SCANCODE_DELETE) {
|
||||
|
|
@ -531,6 +535,31 @@ void EditorApp::processEvents() {
|
|||
giz.endDrag();
|
||||
giz.setMode(TransformMode::None);
|
||||
} else if (event.type == SDL_MOUSEBUTTONDOWN) {
|
||||
// Pending crater placement: take precedence over the
|
||||
// mode-based click handling below so the next click
|
||||
// anywhere on terrain spawns the crater instead of
|
||||
// doing whatever the current mode does.
|
||||
if (pendingCrater_.active) {
|
||||
auto ext = window_->getVkContext()->getSwapchainExtent();
|
||||
rendering::Ray ray = camera_.getCamera().screenToWorldRay(
|
||||
static_cast<float>(event.button.x),
|
||||
static_cast<float>(event.button.y),
|
||||
static_cast<float>(ext.width),
|
||||
static_cast<float>(ext.height));
|
||||
glm::vec3 hitPos;
|
||||
if (terrainEditor_.raycastTerrain(ray, hitPos)) {
|
||||
terrainEditor_.createCrater(hitPos,
|
||||
pendingCrater_.radius,
|
||||
pendingCrater_.depth,
|
||||
pendingCrater_.rim);
|
||||
showToast("Crater placed");
|
||||
pendingCrater_.active = false;
|
||||
}
|
||||
// If the click missed terrain, leave the mode armed
|
||||
// so the user can try again without re-pressing the
|
||||
// button.
|
||||
continue;
|
||||
}
|
||||
// Path point capture (river/road tool)
|
||||
// Alt+click eyedropper in paint mode
|
||||
if (mode_ == EditorMode::Paint && (SDL_GetModState() & KMOD_ALT)) {
|
||||
|
|
|
|||
|
|
@ -191,6 +191,22 @@ private:
|
|||
// reads this so subsequent generations honor the active biome instead of
|
||||
// reapplying the same hardcoded heightband textures every time.
|
||||
Biome activeBiome_ = Biome::Grassland;
|
||||
|
||||
// "Click on terrain to place crater" mode. The Crater button arms this
|
||||
// with the user's chosen radius/depth/rim; the next left-click on
|
||||
// terrain consumes it and creates the crater at the actual click
|
||||
// position. Solves the UX problem where pressing the button used a
|
||||
// stale brush position because the cursor was on the button itself.
|
||||
public:
|
||||
struct PendingCrater {
|
||||
bool active = false;
|
||||
float radius = 30.0f;
|
||||
float depth = 10.0f;
|
||||
float rim = 3.0f;
|
||||
};
|
||||
PendingCrater& pendingCrater() { return pendingCrater_; }
|
||||
private:
|
||||
PendingCrater pendingCrater_;
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
|
|
|
|||
|
|
@ -1236,10 +1236,25 @@ void EditorUI::renderBrushPanel(EditorApp& app) {
|
|||
ImGui::SliderFloat("Radius##crater", &craterRadius, 5.0f, 100.0f);
|
||||
ImGui::SliderFloat("Depth##crater", &craterDepth, 2.0f, 50.0f);
|
||||
ImGui::SliderFloat("Rim Height##crater", &craterRim, 0.0f, 15.0f);
|
||||
auto& brush5 = app.getTerrainEditor().brush();
|
||||
if (ImGui::Button("Create Crater at Cursor", ImVec2(-1, 0)) ) {
|
||||
app.getTerrainEditor().createCrater(brush5.getPosition(), craterRadius, craterDepth, craterRim);
|
||||
app.showToast("Crater created");
|
||||
// Click-to-place: arm pendingCrater so the next left-click on
|
||||
// terrain spawns the crater there, not at the (stale) brush
|
||||
// position that was last set before the cursor moved onto the
|
||||
// button.
|
||||
auto& pc = app.pendingCrater();
|
||||
if (pc.active) {
|
||||
ImGui::TextColored(ImVec4(0.9f, 0.7f, 0.3f, 1),
|
||||
"ARMED — click on terrain to place");
|
||||
if (ImGui::Button("Cancel##crater", ImVec2(-1, 0))) {
|
||||
pc.active = false;
|
||||
}
|
||||
} else {
|
||||
if (ImGui::Button("Click on terrain to place crater", ImVec2(-1, 0))) {
|
||||
pc.active = true;
|
||||
pc.radius = craterRadius;
|
||||
pc.depth = craterDepth;
|
||||
pc.rim = craterRim;
|
||||
app.showToast("Click on terrain to place crater (Esc to cancel)");
|
||||
}
|
||||
}
|
||||
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1), "Bowl with raised rim. Fill with water for a lake.");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue