feat(editor): river/road tool supports multi-point polylines
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run

Path capture replaced with std::vector<glm::vec3> pathPoints_. The
flow is now: click "Click Start Point" → click terrain for first
point → keep clicking for additional waypoints → press Apply when
done, or Cancel to scrap. Apply iterates each consecutive pair as a
segment, calling carveRiver + paintAlongPath + fillWaterAlongPath
(or flattenRoad for road mode) per segment.

Hard-capped at 64 captured points so a runaway click handler can't
unboundedly grow the polyline. Toast at end reports the segment
count so users see the polyline took.

PathCapture states extended: None / WaitingStart / WaitingEnd /
WaitingMore. Backwards-compatible getPathStart()/getPathEnd()
return first/last points so the existing path-preview wiring keeps
working.
This commit is contained in:
Kelsi 2026-05-07 10:32:19 -07:00
parent 158ab192f0
commit 4e4102bf4a
2 changed files with 68 additions and 39 deletions

View file

@ -24,15 +24,23 @@ public:
PaintMode getPaintMode() const { return paintMode_; }
// Path point capture: when active, next terrain click sets the point
enum class PathCapture { None, WaitingStart, WaitingEnd };
// Path point capture: when active, next terrain click appends a
// point. WaitingStart for the first, WaitingMore for any subsequent
// (the user can keep clicking until they hit Apply or Finish).
enum class PathCapture { None, WaitingStart, WaitingEnd, WaitingMore };
PathCapture getPathCapture() const { return pathCapture_; }
void setPathPoint(const glm::vec3& pos);
glm::vec3 getPathStart() const { return pathStart_; }
glm::vec3 getPathEnd() const { return pathEnd_; }
bool isPathReady() const { return pathStartSet_ && pathEndSet_; }
// Backwards-compatible getters: start = first point, end = last.
glm::vec3 getPathStart() const {
return pathPoints_.empty() ? glm::vec3(0) : pathPoints_.front();
}
glm::vec3 getPathEnd() const {
return pathPoints_.empty() ? glm::vec3(0) : pathPoints_.back();
}
const std::vector<glm::vec3>& getPathPoints() const { return pathPoints_; }
bool isPathReady() const { return pathPoints_.size() >= 2; }
float getPathWidth() const { return pathWidth_; }
void clearPath() { pathStartSet_ = false; pathEndSet_ = false; pathCapture_ = PathCapture::None; }
void clearPath() { pathPoints_.clear(); pathCapture_ = PathCapture::None; }
private:
void renderMenuBar(EditorApp& app);
@ -86,8 +94,7 @@ private:
// Path point capture
PathCapture pathCapture_ = PathCapture::None;
glm::vec3 pathStart_{0}, pathEnd_{0};
bool pathStartSet_ = false, pathEndSet_ = false;
std::vector<glm::vec3> pathPoints_;
int pathMode_ = 0; // 0=river, 1=road
float pathWidth_ = 8.0f, pathDepth_ = 5.0f;
};