Skip to content

editor: add lean-to roof extensions and automatic drainage - #651

Open
sudhir9297 wants to merge 45 commits into
pascalorg:mainfrom
sudhir9297:t3code/add-shed-roof-extensions
Open

editor: add lean-to roof extensions and automatic drainage#651
sudhir9297 wants to merge 45 commits into
pascalorg:mainfrom
sudhir9297:t3code/add-shed-roof-extensions

Conversation

@sudhir9297

@sudhir9297 sudhir9297 commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

  • Adds configurable wall-hosted lean-to roof extensions with 2D/3D placement, movement, snapping, collision validation, roof attachment, flashing, framing, supports, paint slots, and parametric controls.
  • Adds automatic roof gutters, outlets, and terrain-aware downspouts, including segmented-eave coordination, attached-extension suppression, and manual adjustment support.
  • Keeps derived drainage and extension assemblies synchronized within scene commits using mutation-scoped reconciliation, and defaults ridge vents off for newly created roof segments.

How to test

  1. Run bun dev, open the editor, create a building, and place a lean-to extension from the Build panel against a straight exterior wall; verify the preview snaps to the wall and the extension is selected after placement.
  2. Move and resize the extension in both 3D and floorplan views; switch snapping modes and dependency locks, and verify the high edge, low edge, pitch, overhangs, framing, flashing, supports, and drainage update consistently.
  3. Enable automatic gutters on simple and segmented roofs; verify gutters stop or split at intersecting roof extensions, do not cross attached shed-roof edges, and generated downspouts reach the resolved slab/terrain ground.
  4. Move or resize a generated outlet/downspout manually and verify the adjustment persists after another roof or extension edit.
  5. Run bun run check-types, bun run check, bun run test, and bun run build.

Screenshots / screen recording

Recording to be added — this is a visual and interactive change.

Checklist

  • I've tested this locally with bun dev
  • My code follows the existing code style (run bun check to verify)
  • I've updated relevant documentation (if applicable)
  • This PR targets the main branch

Note

High Risk
Large cross-cutting changes to core scene mutations, roof drainage derivation, and a new multi-child lean-to assembly with host-roof coordination—bugs could corrupt scene graphs or silently wrong gutter/downspout placement.

Overview
Introduces lean-to roof extensions as a wall-hosted structure kind: placement and editing in 3D and floorplan, roof-edge attachment, managed child roof/columns/gutter/downspout assembly, and a Features & extensions Build tab group (with registry-ready gating).

Adds automatic perimeter gutters and downspouts for roof segments (autoGutter): eave runs respect trim, sibling segments, and lean-to edge exclusions; outlets and default downspouts are planned by connected gutter length, with to-ground length that follows building/terrain context.

Scene plumbing grows batch mutations (createMany, applyChanges, subscribeNodes), registry tools receive sceneApi / level context, and node create/update/delete paths reconcile derived drainage; downspout and lean-to system modules react to scoped node changes. Smaller UX fixes: resize snap fallbacks, snap HUD during handle drags, dedicated roof-accessory icons, and manual downspout/gutter edits clearing “generated” metadata.

Reviewed by Cursor Bugbot for commit d91c414. Bugbot is set up for automated code reviews on this repo. Configure here.

sudhir9297 and others added 30 commits May 19, 2026 02:59
Items (e.g. solar panels) can now be placed on sloped roof surfaces.
The placement system computes euler rotation from the roof surface
normal so items sit flush on the slope instead of going inside.

- Add roofStrategy to placement-strategies with enter/move/click/leave
- Wire roof:enter/move/click/leave events in the placement coordinator
- Add calculateRoofRotation in placement-math using surface normals
- Support full 3D cursor rotation for sloped surfaces
- Items on roofs are parented to the level with world-space rotation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
: wallSpanningLeanTo
: attachment
? applyLeanToRoofAttachment(leanTo, attachment)
: clearLeanToRoofAttachment(wallSpanningLeanTo)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Manual mode reattaches automatically

High Severity

In resolveEffectiveLeanTo, a lean-to left in connectionMode: 'manual' is still magnetically reattached whenever a nearby roof edge is within ROOF_EDGE_REATTACH_TOLERANCE. That path calls applyLeanToRoofAttachment, which forces connectionMode back to auto and restores host roof fields. Inspector-driven manual mode therefore cannot stick under a typical eave, so host gutter suppression and attachment locks flip back on after the next sync.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b840058. Configure here.

const levelElevations = getLevelElevations(nodes)
const wallLevel = wall.parentId ? levelElevations.get(wall.parentId) : undefined
const halfSpan =
leanTo.span / 2 + Math.max(Math.max(0, leanTo.leftOverhang), Math.max(0, leanTo.rightOverhang))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Asymmetric overhangs skew edge exclusion

Low Severity

Attachment overlap and hostRoofEdgeRange are computed with a symmetric halfSpan that uses the larger of leftOverhang and rightOverhang on both sides, while layout offsets the roof with roofCenterX for true asymmetric overhangs. Uneven side overhangs therefore claim the wrong portion of the host eave and can suppress or keep host gutters incorrectly.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9709342. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d91c414. Configure here.

const parent = leanTo.parentId ? nodes[leanTo.parentId as AnyNodeId] : undefined
const hostRoof = resolveLeanToHostRoof(effectiveLeanTo, nodes)
const signature = extensionSignature(effectiveLeanTo, hostRoof, nodes)
if (signatures.get(id) === signature) continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Posts skip terrain ground updates

High Severity

extensionSignature omits terrain and slab ground inputs, so after the first reconcile a site sculpt or slab change can leave the signature unchanged. reconcile then early-returns and never re-runs resolveLeanToPostBaseY, leaving managed posts floating or buried while automatic downspout lengths still update.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d91c414. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant