Skip to content

Add barrel roofs and glazed roof construction - #1055

Merged
wass08 merged 6 commits into
pascalorg:mainfrom
sudhir9297:t3code/review-roof-code
Oct 15, 2026
Merged

wass08 merged 6 commits into
pascalorg:mainfrom
sudhir9297:t3code/review-roof-code

Conversation

@sudhir9297

@sudhir9297 sudhir9297 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds barrel roofs in standard and glazed construction, and glazed construction for gable and straight shed roofs. The roof inspector exposes supported construction choices, arch rise and divisions, glazing grids, framing, glass appearance, end infill and individual panel overrides. Frame, glass and solid panels have independent paint slots. The geometry fixes overlapping corner faces, preserves barrel rise consistently during 2D and 3D resizing, respects wall-only accessory cuts, and follows palette and debug display settings. Roof creation and glazing paint use shared agent contracts and operations; floor plans, accessory hosting, shadows and printable solids follow the new roof geometry. Existing scenes retain standard construction by default.

How to test

  1. Run bun dev, open a project, create a roof and choose Barrel. Switch between Standard and Glazed. Adjust rise and arch divisions; inspect the end-wall corners for overlapping faces. Resize the span in both 2D and 3D: the rise stays fixed until a smaller span requires clamping it to half the span.
  2. Try Glazed on gable and straight shed roofs. Inspect unsupported roof shapes: Glazed should be visibly disabled. Adjust glazing grids, framing and glass controls; change individual panels to solid or empty. Cancel a preview and undo a committed edit. Paint frame and glass separately, then change palette, texture and debug display settings.
  3. Add skylights and roof-wall openings: skylights cut the covering, while wall openings leave it intact. Exercise create_roof with roofSystem: "glazed" and barrel parameters, then paint with glazing-frame, glazing-glass or glazing-solid. Invalid shapes and excessive barrel rise should refuse without creating nodes.
  4. Automated verification completed: bun run ci passed, including style checks, skill validation, type checks, tests and production builds. bun run check-types also passed again before opening this PR. Browser smoke check confirmed the glazing inspector and canvas load without an error overlay.

Screenshots / screen recording

Not added yet.

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

Medium Risk
Broad changes across schema, rendering, CSG merge behavior, paint routing, and agent APIs; backward compatibility relies on defaulting existing segments to standard construction.

Overview
Introduces barrel as a roof shape and a glazed roof system for gable, straight shed, and barrel segments, with schema fields (roofSystem, glazing, barrelRise, segment slots) and a large glazing layout/geometry pipeline (grids, panes, walls, trim, accessory support).

create_roof and agent tools accept glazing and barrel parameters with validation (unsupported glazed shapes, barrel rise capped at half span). Paint routes glazing roles to segment slots and standard roof roles to the parent roof when targets are mixed.

Editor and nodes packages add inspector panels, per-segment glazed rendering (shadow-only mesh for glass), floor-plan mullion lines, printable solids, and registry-based segment paint instead of legacy roof-segment paint in the selection manager. Gutter/eave math uses shape-specific overhang (barrel arch springs at eaves; overhang lengthens ends). Ridge vents skip glazed and barrel segments.

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

Add framing, glazing, barrel arch controls, floor-plan grids, painting, print solids, and MCP authoring while preserving existing scenes. Resolve overlapping barrel corner faces and polish the glazing inspector with shape-aware availability, unit display, and individual panel overrides.

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/core/src/agent-operations/paint.ts
Comment thread packages/nodes/src/shared/roof-segment-hit.ts

@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.

Stale Bugbot comment from a previous run.

Comment thread packages/nodes/src/shared/roof-segment-hit.ts
Comment thread packages/nodes/src/roof/glazing-panel.tsx
wass08 and others added 2 commits October 15, 2026 09:49
Resolve against main's roof rework (pascalorg#1082 deck reach and gable overhang,
pascalorg#1057 seated roof edits, pascalorg#1076 slot registry paint, pascalorg#1079 one notation):

- getRoofSegmentDeckReach answers for a barrel: its ends reach out by the
  overhang, unsloped, and its arch springs from the eaves, so the plan,
  hit test and visible bounds follow its geometry.
- create_roof keeps a barrel's overhang in plan rather than dividing it
  by a slope; its glazing lengths read through measurement().
- The segment panel shows a barrel's overhang as its end overhang.
- Floor-plan resize keeps the crown-preserving patch, committed seated.
- Paint keeps glazed segment defaults on main's slot registry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Glazed gable and shed end infill fits below the covering's frame depth,
  as the barrel's did: it no longer shares the covering's top plane.
- A glazed segment stands on its own walls up to the wall top (glazing-solid),
  instead of floating over an open band; wallShell 'omit' still drops them.
- Barrel walls are centred on the footprint like every roof's, and the wall
  faces doors and windows place on match them. Below the wall top a barrel
  has no covering, so only its arched ends fit under the arch.
- A roof with glazed and standard segments paints its glazing roles on the
  glazed segments and its own roles on the roof; a role neither has refuses.
- The viewer knows which segments build from their own pieces
  (isIndependentRoofSegment); the roof geometry adapter only syncs shadows.
- The roof-segment branch of the legacy paint arm is gone: segments paint
  through their definition. curtainGridPositions is imported from core.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@wass08

wass08 commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

Pushed two commits on top of this branch:

06da9bb63 Merge main. Resolves the 10 conflicts against main's roof rework (#1082 deck reach and gable overhang, #1057 seated roof edits, #1076 slot-registry paint, #1079 one notation):

  • Barrel's reach lives in getRoofSegmentDeckReach: ends reach out by the overhang, eaves by nothing.
  • create_roof keeps a barrel's overhang in plan.
  • Glazing lengths in create_roof read through measurement(); otherwise notation.test.ts fails on main.
  • The segment panel shows "End overhang" for a barrel.
  • Floor-plan resize keeps your crown-preserving patch, committed through commitSeatedRoofEdit.

5389bb63c Review fixes:

  • Glazed gable and shed end infill now stops below the covering's frame depth. Before, it shared the covering's top plane along the rakes and z-fought.
  • Glazed segments stand on their own walls (glazing-solid) up to wallHeight instead of floating over an open band. wallShell: 'omit' still drops them.
  • Barrel walls are centred on the footprint like other roofs', and the wall faces for doors and windows match. Only the arched ends fit under the arch.
  • A mixed glazed and standard roof paints glazing roles on the glazed segments and roof roles on the roof. A role neither has is refused.
  • New core isIndependentRoofSegment, used by the viewer and renderer. The geometry adapter now only syncs shadows; its pass-through buildGeometry and independent are removed.
  • Removed the dead roof-segment branch of the legacy paint arm in selection-manager.tsx, and the curtainGridPositions re-export.

There are tests for each fix. Check-types, tests, Biome, skills validation and the build all pass locally.

🤖 Generated with Claude Code

@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.

Stale Bugbot comment from a previous run.

/>
<SliderControl
label="Depth"
label={node.roofType === 'barrel' ? 'Span' : 'Depth'}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Span slider skips barrel rise clamp

Medium Severity

The inspector span control writes depth alone. Unlike 2D and 3D resize, it never clamps stored barrelRise to half the new span, so a later wider span can restore a rise the smaller span had already ruled out.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5389bb6. Configure here.

/>
</ActionGroup>
{node.roofType !== 'shed' && node.roofType !== 'flat' && (
{node.roofType !== 'shed' && node.roofType !== 'flat' && node.roofType !== 'barrel' && (

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Glazed gables still offer ridge vents

Medium Severity

Auto ridge vent is hidden for barrels but still shown on glazed gables, while getRidgeVentLinesForSegment returns no lines whenever roofSystem is glazed. The control can look enabled and does not create vents.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5389bb6. Configure here.


const ROOF_TYPE_OPTIONS_3: { label: string; value: RoofType }[] = [
{ label: 'Conical', value: 'conical' },
{ label: 'Barrel', value: 'barrel' },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unsupported type keeps glazed system

Medium Severity

Changing a glazed segment to hip, mansard, or another unsupported shape leaves roofSystem as glazed. The inspector then shows Standard because isGlazedRoofSegment is false, so switching back to gable, shed, or barrel silently restores glazing.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5389bb6. Configure here.

unit="m"
value={node.shingleThickness}
/>
)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Fascia ignored on independent roofs

Medium Severity

Deck and shingle thickness are hidden for glazed segments, but fascia remains editable. getGlazedRoofPieces and getBarrelRoofSolidPieces never emit fascia, so the toggle and height have no effect on barrel or glazed roofs in the viewport or print solids.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5389bb6. Configure here.

- The barrel end wall's placeable profile stays convex: the wall's outer
  half above the wall top was a notch the opening clamp read as a ceiling
  at the wall top, so no window fit the arched end.
- Gutters and downspouts read the eave overhang through
  getRoofShapeEaveOverhang: a barrel's arch springs from its eaves, so its
  overhang reaches out at its ends only and no longer pushes its eave
  gutters out (or down).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@wass08

wass08 commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

Pushed 5eeb85788 with two fixes found while testing in the app:

  • Windows fit on a barrel's arched end walls again. After centring the barrel walls, the end-wall outline had a 5 cm notch at wall height, which the opening clamp read as a ceiling at 0.5 m. The outline is convex again.
  • Gutters and downspouts read the eave overhang through getRoofShapeEaveOverhang. A barrel's overhang only reaches out at its ends, so it no longer pushes the eave gutters outward or down. It only lengthens them.

There's a regression test for each.

🤖 Generated with Claude Code

@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 5 total unresolved issues (including 4 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.

Reviewed by Cursor Bugbot for commit 5eeb857. Configure here.

...profile
.reverse()
.map(([z, y]): [number, number] => [z + length / 2, y + node.wallHeight]),
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Barrel ends reject default openings

High Severity

The barrel end-wall profile keeps outer base corners at u = 0 and u = length and then steps to the arch springs. When wallHeight is 0 — the create_roof default and the usual storey-capping case — those springs also sit at v = 0, so the connecting edge runs backward along the baseline. Opening clamp treats that edge as a v <= 0 ceiling, so doors and windows cannot sit in the arch. A high rise makes the same corner reflex, so the convex clamp can fail there too.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5eeb857. Configure here.

@wass08
wass08 merged commit 683ce0c into pascalorg:main Oct 15, 2026
5 checks passed
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.

2 participants