Skip to content

feat(nodes): steel i-beam profile and slanted columns support - #1005

Open
ovurrsl wants to merge 2 commits into
pascalorg:mainfrom
ovurrsl:feat/column-enhancements
Open

ovurrsl wants to merge 2 commits into
pascalorg:mainfrom
ovurrsl:feat/column-enhancements

Conversation

@ovurrsl

@ovurrsl ovurrsl commented Oct 6, 2026 •

Copy link
Copy Markdown

What does this PR do?

This PR brings highly requested architectural features to the column system:

  1. Steel Construction Profiles (i-beam): Adds a new cross-section type for standard H/I-Beam steel structural columns. The renderer generates the beam automatically by computing proportional flange and web thicknesses based on the column's overall width and depth.
  2. Slanted/Leaning Columns (Tilt X, Tilt Z): Introduces tiltX and tiltZ properties to the ColumnNode schema, allowing columns to organically lean off the vertical Y-axis.

Both features are fully integrated into the editor UI and the 2D floorplan projection.

How to test

  1. Steel Columns: Select a column, go to Dimensions, and change the Cross Section to "I-Beam". It should instantly render as a steel beam. Switch to the 2D Floorplan view (Tab/F) and verify that the column footprint renders as a bounding rectangle rather than defaulting to a 32-segment circle.
  2. Slanted Columns: Select a column. In the right panel, use the new "Tilt X" and "Tilt Z" sliders under the "Tilt (Eğim)" section. Ensure the column tilts and updates the ghost preview properly.

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

Co-Authored-By: AI


Note

Medium Risk
Touches column schema, 3D rendering, floorplan/collision semantics, hosted-child moves, and IFC import/export—wide but covered by new tests; lean changes plan footprint without lifting the base for slab overlap.

Overview
Adds i-beam as a column cross-section and optional tiltX / tiltZ lean (±45°, degrees in tools/UI, radians on the node). Lean is modeled as shear (base fixed, top level), with shared helpers in column-geometry for i-beam outlines, lean offsets, and swept plan footprints.

3D / editor: Renders i-beams as flange + web boxes; applies a lean shear matrix on the column body while hosted children stay on the shifted, level top surface. Floorplan and scene-view bounds use the swept footprint; the panel adds I-Beam and tilt sliders (shaft controls hidden for i-beam).

Agents / schema / IFC: add_column and ColumnNode accept the new fields; IFC export uses IfcIShapeProfileDef and oblique extrusions for lean, with import round-trip coverage in tests.

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

@pascal

pascal Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Two features for columns, plus some unrelated fixes that rode along. The column work adds an i-beam cross section (rendered as two flanges and a web sized proportionally from the column's width and depth) and tiltX/tiltZ properties so a column can lean off the Y axis. Both reach the schema, the 3D renderer, the preview, the right-hand panel, and the 2D floorplan footprint, which now treats an I-beam as a rotated rectangle instead of falling through to the round-column path. The other three files are separate: one reworks the drag bounding box to share module-level unit geometry and cached materials rather than rebuilding and disposing them per dimension change, and two surface the underlying error when adding a guide image fails instead of swallowing it.

File Change What changed
packages/core/src/schema/nodes/column.ts modified Adds i-beam to ColumnCrossSection and tiltX/tiltZ to ColumnNode, both defaulting to 0
packages/nodes/src/column/renderer.tsx modified New IBeamBlock (two flanges + web), dispatch for i-beam in ColumnBlock, tilt applied to the rotation of ColumnPreview and ColumnRenderer
packages/nodes/src/column/panel.tsx modified I-Beam entry in the cross-section picker (grid widened to 4, "Rectangular" shortened to "Rect.") and a new tilt section with two sliders, ±π/4
packages/nodes/src/column/floorplan.ts modified i-beam joins square/rectangular in returning a rotated-rectangle plan footprint
packages/editor/src/components/tools/shared/drag-bounding-box.tsx modified Shared unit box/plane geometry and colour-keyed material caches replace per-frame construction and disposal; size now comes from scale
packages/editor/src/components/ui/action-menu/view-toggles.tsx modified Guide image upload failures are logged and the error message is shown to the user
packages/editor/src/components/ui/sidebar/panels/site-panel/index.tsx modified Same error handling for guide images added from the level references list

Start with the schema change in column.ts, then read renderer.tsx against it; the drag bounding box rewrite is independent and can be read on its own.

@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/column/renderer.tsx Outdated

@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/editor/src/components/tools/shared/drag-bounding-box.tsx Outdated
Comment thread packages/nodes/src/column/renderer.tsx Outdated
Comment thread packages/nodes/src/column/renderer.tsx Outdated
Comment thread packages/nodes/src/column/floorplan.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.

const handleTypeClick = useCallback(
(type: BuildType) => {
setMepOpen(type.id === 'mep')
if (type.id === 'fence' && selectedFence) return

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Fence selection hijacks other build tools

Medium Severity

fenceContext becomes true from selection alone, so a selected fence keeps the Fence tile lit, blocks re-arming the fence tool, and replaces the kitchen, MEP, and wand secondary panels even while another build tool is active.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1d42ed9. Configure here.

Comment thread apps/editor/lib/build-panel-model.ts Outdated
onSelect: () =>
activateBuildTool(tool === 'pipe-fitting' ? 'pipe-segment' : 'pipe-fitting'),
},
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Wand fence tiles stay inactive

Low Severity

XR wand gate and opening actions always pass active: false, so the wand never shows which fence feature is armed. The desktop tiles compare against placingFenceFeature.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1d42ed9. Configure here.

Comment thread packages/core/src/agent-tools/columns.ts
Comment thread packages/nodes/src/column/renderer.tsx Outdated
Comment thread packages/core/src/lib/object-cuts.ts
ovurrsl and others added 2 commits October 8, 2026 14:54
Columns gain an `i-beam` cross-section: two flanges spanning the width at
the front and back faces, joined by a web along the depth. Plate
thicknesses come from one core helper (`columnIBeamSection`) shared by
the renderer, the top-surface region, the plan outline and IFC export.

- Capitals, bands and carvings treat the section as a box, so caps are
  plates; a bare i-beam's top support region is its I outline.
- The plan draws a bare i-beam as its true section, in the nodes
  floorplan and the editor's reference-floor footprint; with plates it
  draws the plate rectangle.
- `add_column` accepts `crossSection: 'i-beam'`.
- IFC export writes an IfcIShapeProfileDef extrusion and import reads one
  back as an i-beam column.
- The panel offers I-Beam beside Round / Square / Rectangular (2×2 grid)
  and shows Depth for it; shaft profile controls are hidden for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FX8vGAP5g43AHR1jixUeXr
Columns gain optional `tiltX` / `tiltZ` (radians, ±45°). Absent fields
keep older scenes round-tripping unchanged.

The lean is one shear in the column's local frame (x += −tan(tiltZ)·y,
z += tan(tiltX)·y): the base stays planted, the height is unchanged and
the top stays level. A single `ColumnLean` wrapper applies it under the
yaw in both the renderer and the placement ghost, which now applies the
node's yaw itself so it matches the committed column.

- The top surface stays level and slides with the lean; objects on top
  follow a tilt or height change (`followsSurfacePlan` on the column
  hosted-edit policy).
- 2D: the footprint is the base swept along the lean, with the leaned
  top outlined dashed; the reference floor uses the same sweep.
- The agent scene-view box covers the lean. The floor-placement
  footprint stays on the planted base, which is what stands on a slab.
- `add_column` takes tiltX / tiltZ in degrees.
- IFC: a plain tilted column exports as an oblique extrusion and is read
  back with its tilt.
- Panel: Tilt X / Tilt Z in degrees under Transform (not for lean-to
  posts, whose layout the lean-to owns).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FX8vGAP5g43AHR1jixUeXr
@ovurrsl
ovurrsl force-pushed the feat/column-enhancements branch from 1d42ed9 to 949fac4 Compare October 8, 2026 16:40

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

Reviewed by Cursor Bugbot for commit 949fac4. Configure here.

if (floorPlanUrl && node.source) {
const { min, max } = node.source.manifest.bounds
const [cx, cz] = points
const [cx, cz] = base

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Scripted image uses swept vertex count

Medium Severity

The scripted floor-plan image now averages base vertices but still divides by points.length (the swept hull). When a scripted column leans, those counts diverge, so the image is scaled toward the origin and no longer sits on the column.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 949fac4. Configure here.

This branch has not been deployed

No deployments
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