Merge branch 'main' into feat/door-improvement

# Conflicts:
#	packages/core/src/events/bus.ts
#	packages/viewer/src/systems/door/door-system.tsx
This commit is contained in:
sudhir
2026-05-07 10:40:51 +05:30
46 changed files with 6391 additions and 860 deletions
+3
View File
@@ -4,6 +4,7 @@ import type { Object3D } from 'three'
import type {
BuildingNode,
CeilingNode,
ColumnNode,
DoorNode,
FenceNode,
GuideNode,
@@ -57,6 +58,7 @@ export type ZoneEvent = NodeEvent<ZoneNode>
export type SlabEvent = NodeEvent<SlabNode>
export type SpawnEvent = NodeEvent<SpawnNode>
export type CeilingEvent = NodeEvent<CeilingNode>
export type ColumnEvent = NodeEvent<ColumnNode>
export type RoofEvent = NodeEvent<RoofNode>
export type RoofSegmentEvent = NodeEvent<RoofSegmentNode>
export type StairEvent = NodeEvent<StairNode>
@@ -176,6 +178,7 @@ type EditorEvents = GridEvents &
NodeEvents<'slab', SlabEvent> &
NodeEvents<'spawn', SpawnEvent> &
NodeEvents<'ceiling', CeilingEvent> &
NodeEvents<'column', ColumnEvent> &
NodeEvents<'roof', RoofEvent> &
NodeEvents<'roof-segment', RoofSegmentEvent> &
NodeEvents<'stair', StairEvent> &
@@ -13,6 +13,7 @@ export const sceneRegistry = {
site: new Set<string>(),
building: new Set<string>(),
ceiling: new Set<string>(),
column: new Set<string>(),
level: new Set<string>(),
wall: new Set<string>(),
fence: new Set<string>(),
+1
View File
@@ -3,6 +3,7 @@ export type {
CameraControlEvent,
CameraControlFitSceneEvent,
CeilingEvent,
ColumnEvent,
DoorEvent,
EventSuffix,
FenceEvent,
+15 -1
View File
@@ -26,6 +26,20 @@ export {
} from './material'
export { BuildingNode } from './nodes/building'
export { CeilingNode } from './nodes/ceiling'
export {
COLUMN_PRESETS,
ColumnBaseStyle,
ColumnCapitalStyle,
ColumnCarvingPlacement,
ColumnCrossSection,
ColumnNode,
ColumnPanelShape,
type ColumnPresetId,
ColumnRingPlacement,
ColumnShaftDetail,
ColumnShaftProfile,
ColumnStyle,
} from './nodes/column'
export { DoorNode, DoorSegment } from './nodes/door'
export { FenceBaseStyle, FenceNode, FenceStyle } from './nodes/fence'
export { GuideNode, GuideScaleReference } from './nodes/guide'
@@ -50,8 +64,8 @@ export { ScanNode } from './nodes/scan'
// Nodes
export { SiteNode } from './nodes/site'
export { SlabNode } from './nodes/slab'
export type { StairSurfaceMaterialRole, StairSurfaceMaterialSpec } from './nodes/stair'
export { SpawnNode } from './nodes/spawn'
export type { StairSurfaceMaterialRole, StairSurfaceMaterialSpec } from './nodes/stair'
export {
getEffectiveStairSurfaceMaterial,
StairNode,
+1
View File
@@ -46,6 +46,7 @@ export const MaterialTarget = z.enum([
'stair',
'stair-segment',
'fence',
'column',
'slab',
'ceiling',
'door',
+410
View File
@@ -0,0 +1,410 @@
import dedent from 'dedent'
import { z } from 'zod'
import { BaseNode, nodeType, objectId } from '../base'
import { MaterialSchema } from '../material'
export const ColumnStyle = z.enum([
'plain',
'faceted',
'fluted',
'lathe-turned',
'dravidian-carved',
'cluster',
])
export const ColumnCrossSection = z.enum([
'round',
'square',
'rectangular',
'octagonal',
'sixteen-sided',
])
export const ColumnShaftProfile = z.enum(['straight', 'tapered', 'bulged', 'baluster', 'hourglass'])
export const ColumnShaftDetail = z.enum(['none', 'fluted', 'spiral', 'panelled', 'lathe-turned'])
export const ColumnPanelShape = z.enum(['rectangle', 'arched', 'diamond'])
export const ColumnBaseStyle = z.enum([
'none',
'simple-square',
'round-rings',
'square-plinth',
'stepped-square',
'lotus',
'ribbed-lotus',
'panelled-pedestal',
])
export const ColumnCapitalStyle = z.enum([
'none',
'simple',
'simple-slab',
'rounded',
'stepped',
'doric',
'volute',
'ionic-volute',
'leaf-carved',
'corinthian-leaf',
'south-indian-bracket',
'wood-bracket',
])
export const ColumnRingPlacement = z.enum(['ends', 'even', 'top', 'bottom'])
export const ColumnCarvingPlacement = z.enum(['shaft', 'base', 'capital', 'all'])
export type ColumnStyle = z.infer<typeof ColumnStyle>
export type ColumnCrossSection = z.infer<typeof ColumnCrossSection>
export type ColumnShaftProfile = z.infer<typeof ColumnShaftProfile>
export type ColumnShaftDetail = z.infer<typeof ColumnShaftDetail>
export type ColumnPanelShape = z.infer<typeof ColumnPanelShape>
export type ColumnBaseStyle = z.infer<typeof ColumnBaseStyle>
export type ColumnCapitalStyle = z.infer<typeof ColumnCapitalStyle>
export type ColumnRingPlacement = z.infer<typeof ColumnRingPlacement>
export type ColumnCarvingPlacement = z.infer<typeof ColumnCarvingPlacement>
export const ColumnNode = BaseNode.extend({
id: objectId('column'),
type: nodeType('column'),
position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
rotation: z.number().default(0),
style: ColumnStyle.default('plain'),
crossSection: ColumnCrossSection.default('round'),
height: z.number().positive().default(2.8),
radius: z.number().positive().default(0.22),
width: z.number().positive().default(0.44),
depth: z.number().positive().default(0.44),
edgeSoftness: z.number().min(0).max(0.12).default(0.025),
baseHeight: z.number().min(0).default(0.18),
capitalHeight: z.number().min(0).default(0.18),
shaftProfile: ColumnShaftProfile.default('straight'),
shaftTaper: z.number().min(0).max(0.85).default(0),
shaftBulge: z.number().min(-0.5).max(0.8).default(0),
shaftStartScale: z.number().min(0.2).max(2).default(0.72),
shaftEndScale: z.number().min(0.2).max(2).default(0.72),
shaftSegmentCount: z.number().int().min(1).max(64).default(24),
shaftTwistStep: z.number().min(-90).max(90).default(0),
shaftCornerRadius: z.number().min(0).max(0.3).default(0.035),
shaftDetail: ColumnShaftDetail.default('none'),
baseStyle: ColumnBaseStyle.default('round-rings'),
baseWidthScale: z.number().min(0.4).max(3).default(1.24),
baseDepthScale: z.number().min(0.4).max(3).default(1.24),
baseTierCount: z.number().int().min(1).max(8).default(3),
baseStepSpread: z.number().min(0).max(1).default(0.42),
basePlinthHeightRatio: z.number().min(0.2).max(0.7).default(0.44),
baseRoundBandScale: z.number().min(0.5).max(1.2).default(0.92),
baseNeckScale: z.number().min(0.35).max(1).default(0.72),
baseRoundBandCount: z.number().int().min(0).max(16).default(3),
baseRibCount: z.number().int().min(0).max(48).default(0),
baseCarvingLevel: z.number().int().min(0).max(4).default(0),
basePanelInset: z.number().min(0).max(0.1).default(0.02),
capitalStyle: ColumnCapitalStyle.default('simple'),
capitalWidthScale: z.number().min(0.4).max(3).default(1.46),
capitalDepthScale: z.number().min(0.4).max(3).default(1.46),
capitalTierCount: z.number().int().min(1).max(8).default(3),
capitalStepSpread: z.number().min(0).max(1).default(0.42),
capitalBandCount: z.number().int().min(0).max(16).default(2),
voluteSize: z.number().min(0.02).max(0.3).default(0.08),
voluteCount: z.number().int().min(0).max(8).default(4),
leafCount: z.number().int().min(0).max(48).default(18),
leafRows: z.number().int().min(0).max(4).default(2),
bracketDepth: z.number().min(0).max(1.5).default(0.35),
bracketTierCount: z.number().int().min(0).max(8).default(3),
pendantCount: z.number().int().min(0).max(16).default(0),
capitalCarvingLevel: z.number().int().min(0).max(4).default(0),
ringCount: z.number().int().min(0).max(16).default(0),
ringPlacement: ColumnRingPlacement.default('ends'),
ringThickness: z.number().min(0.01).max(0.14).default(0.055),
ringSpread: z.number().min(0.04).max(0.45).default(0.16),
fluteCount: z.number().int().min(0).max(32).default(0),
fluteDepth: z.number().min(0.005).max(0.08).default(0.02),
fluteWidth: z.number().min(0.005).max(0.1).default(0.02),
spiralTwist: z.number().min(-3).max(3).default(0),
spiralRibCount: z.number().int().min(0).max(32).default(0),
panelCount: z.number().int().min(0).max(24).default(0),
panelInsetDepth: z.number().min(0).max(0.1).default(0.02),
panelShape: ColumnPanelShape.default('rectangle'),
latheRingCount: z.number().int().min(0).max(32).default(0),
latheRingSpacing: ColumnRingPlacement.default('ends'),
carvingLevel: z.number().int().min(0).max(4).default(0),
carvingPlacement: ColumnCarvingPlacement.default('capital'),
lowerBandEnabled: z.boolean().default(false),
lowerBandHeight: z.number().min(0).max(1).default(0.24),
lowerBandCarvingLevel: z.number().int().min(0).max(4).default(0),
dentilCount: z.number().int().min(0).max(48).default(0),
beadCount: z.number().int().min(0).max(64).default(0),
material: MaterialSchema.optional(),
materialPreset: z.string().optional(),
}).describe(dedent`
Column node - used to represent structural or decorative pillars/columns.
- style: visual approach such as plain, lathe-turned, carved, or cluster
- crossSection: plan shape used by the procedural renderer
- height/radius/width/depth: primary dimensions in meters
- edgeSoftness: bevel radius for square/plinth/block edges
- shaftProfile/shaftDetail: profile and surface treatment of the shaft
- shaftTwistStep: per-segment shaft rotation in degrees
- shaftCornerRadius: rounded-corner radius for square/rectangular shaft cross-sections
- baseStyle/capitalStyle: procedural base and top treatment with tier/detail controls
- baseHeight/capitalHeight: bottom and top block proportions
- ring/flute/spiral/panel/lathe/carving fields: procedural detail controls
`)
export const COLUMN_PRESETS = {
basicPillar: {
label: 'Straight Round',
style: 'plain',
crossSection: 'round',
height: 2.9,
radius: 0.22,
width: 0.44,
depth: 0.44,
edgeSoftness: 0.025,
baseHeight: 0.22,
capitalHeight: 0.2,
shaftProfile: 'straight',
shaftTaper: 0,
shaftBulge: 0,
shaftStartScale: 0.72,
shaftEndScale: 0.72,
shaftSegmentCount: 1,
shaftTwistStep: 0,
shaftCornerRadius: 0.035,
shaftDetail: 'none',
baseStyle: 'square-plinth',
baseWidthScale: 1.26,
baseDepthScale: 1.26,
baseTierCount: 1,
baseStepSpread: 0.34,
basePlinthHeightRatio: 0.44,
baseRoundBandScale: 0.92,
baseNeckScale: 0.72,
baseRoundBandCount: 0,
baseRibCount: 0,
baseCarvingLevel: 0,
capitalStyle: 'simple-slab',
capitalWidthScale: 1.22,
capitalDepthScale: 1.22,
capitalTierCount: 1,
capitalStepSpread: 0.34,
capitalBandCount: 0,
capitalCarvingLevel: 0,
ringCount: 0,
ringSpread: 0.16,
fluteCount: 0,
spiralTwist: 0,
spiralRibCount: 0,
panelCount: 0,
latheRingCount: 0,
carvingLevel: 0,
lowerBandEnabled: false,
dentilCount: 0,
beadCount: 0,
},
squarePillar: {
label: 'Square Block',
style: 'faceted',
crossSection: 'square',
height: 2.9,
radius: 0.24,
width: 0.48,
depth: 0.48,
edgeSoftness: 0.035,
baseHeight: 0.22,
capitalHeight: 0.2,
shaftProfile: 'straight',
shaftTaper: 0,
shaftBulge: 0,
shaftStartScale: 0.72,
shaftEndScale: 0.72,
shaftSegmentCount: 1,
shaftTwistStep: 0,
shaftCornerRadius: 0.045,
shaftDetail: 'none',
baseStyle: 'simple-square',
baseWidthScale: 1.18,
baseDepthScale: 1.18,
baseTierCount: 1,
baseStepSpread: 0.34,
basePlinthHeightRatio: 0.44,
baseRoundBandScale: 0.92,
baseNeckScale: 0.72,
baseRoundBandCount: 0,
baseRibCount: 0,
baseCarvingLevel: 0,
capitalStyle: 'simple-slab',
capitalWidthScale: 1.18,
capitalDepthScale: 1.18,
capitalTierCount: 1,
capitalStepSpread: 0.34,
capitalBandCount: 0,
capitalCarvingLevel: 0,
ringCount: 0,
ringSpread: 0.16,
fluteCount: 0,
spiralTwist: 0,
spiralRibCount: 0,
panelCount: 0,
latheRingCount: 0,
carvingLevel: 0,
lowerBandEnabled: false,
dentilCount: 0,
beadCount: 0,
},
taperedPillar: {
label: 'Tapered Round',
style: 'plain',
crossSection: 'round',
height: 3,
radius: 0.23,
width: 0.46,
depth: 0.46,
edgeSoftness: 0.025,
baseHeight: 0.23,
capitalHeight: 0.2,
shaftProfile: 'tapered',
shaftTaper: 0.14,
shaftBulge: 0,
shaftStartScale: 0.82,
shaftEndScale: 0.72,
shaftSegmentCount: 32,
shaftTwistStep: 0,
shaftCornerRadius: 0.035,
shaftDetail: 'none',
baseStyle: 'square-plinth',
baseWidthScale: 1.26,
baseDepthScale: 1.26,
baseTierCount: 1,
baseStepSpread: 0.34,
basePlinthHeightRatio: 0.44,
baseRoundBandScale: 0.92,
baseNeckScale: 0.72,
baseRoundBandCount: 0,
baseRibCount: 0,
baseCarvingLevel: 0,
capitalStyle: 'simple-slab',
capitalWidthScale: 1.22,
capitalDepthScale: 1.22,
capitalTierCount: 1,
capitalStepSpread: 0.34,
capitalBandCount: 0,
capitalCarvingLevel: 0,
ringCount: 0,
ringSpread: 0.16,
fluteCount: 0,
spiralTwist: 0,
spiralRibCount: 0,
panelCount: 0,
latheRingCount: 0,
carvingLevel: 0,
lowerBandEnabled: false,
dentilCount: 0,
beadCount: 0,
},
bulgedPillar: {
label: 'Soft Bulged',
style: 'plain',
crossSection: 'round',
height: 2.9,
radius: 0.22,
width: 0.44,
depth: 0.44,
edgeSoftness: 0.025,
baseHeight: 0.22,
capitalHeight: 0.2,
shaftProfile: 'bulged',
shaftTaper: 0,
shaftBulge: 0.12,
shaftStartScale: 0.68,
shaftEndScale: 0.68,
shaftSegmentCount: 32,
shaftTwistStep: 0,
shaftCornerRadius: 0.035,
shaftDetail: 'none',
baseStyle: 'square-plinth',
baseWidthScale: 1.24,
baseDepthScale: 1.24,
baseTierCount: 1,
baseStepSpread: 0.34,
basePlinthHeightRatio: 0.44,
baseRoundBandScale: 0.92,
baseNeckScale: 0.72,
baseRoundBandCount: 0,
baseRibCount: 0,
baseCarvingLevel: 0,
capitalStyle: 'simple-slab',
capitalWidthScale: 1.2,
capitalDepthScale: 1.2,
capitalTierCount: 1,
capitalStepSpread: 0.34,
capitalBandCount: 0,
capitalCarvingLevel: 0,
ringCount: 0,
ringSpread: 0.16,
fluteCount: 0,
spiralTwist: 0,
spiralRibCount: 0,
panelCount: 0,
latheRingCount: 0,
carvingLevel: 0,
lowerBandEnabled: false,
dentilCount: 0,
beadCount: 0,
},
hourglassPillar: {
label: 'Hourglass',
style: 'plain',
crossSection: 'round',
height: 2.9,
radius: 0.22,
width: 0.44,
depth: 0.44,
edgeSoftness: 0.025,
baseHeight: 0.22,
capitalHeight: 0.2,
shaftProfile: 'hourglass',
shaftTaper: 0,
shaftBulge: 0.12,
shaftStartScale: 0.84,
shaftEndScale: 0.84,
shaftSegmentCount: 32,
shaftTwistStep: 0,
shaftCornerRadius: 0.035,
shaftDetail: 'none',
baseStyle: 'square-plinth',
baseWidthScale: 1.24,
baseDepthScale: 1.24,
baseTierCount: 1,
baseStepSpread: 0.34,
basePlinthHeightRatio: 0.44,
baseRoundBandScale: 0.92,
baseNeckScale: 0.72,
baseRoundBandCount: 0,
baseRibCount: 0,
baseCarvingLevel: 0,
capitalStyle: 'simple-slab',
capitalWidthScale: 1.2,
capitalDepthScale: 1.2,
capitalTierCount: 1,
capitalStepSpread: 0.34,
capitalBandCount: 0,
capitalCarvingLevel: 0,
ringCount: 0,
ringSpread: 0.16,
fluteCount: 0,
spiralTwist: 0,
spiralRibCount: 0,
panelCount: 0,
latheRingCount: 0,
carvingLevel: 0,
lowerBandEnabled: false,
dentilCount: 0,
beadCount: 0,
},
} as const satisfies Record<string, { label: string } & Partial<z.input<typeof ColumnNode>>>
export type ColumnPresetId = keyof typeof COLUMN_PRESETS
export type ColumnNode = z.infer<typeof ColumnNode>
+2
View File
@@ -2,6 +2,7 @@ import dedent from 'dedent'
import { z } from 'zod'
import { BaseNode, nodeType, objectId } from '../base'
import { CeilingNode } from './ceiling'
import { ColumnNode } from './column'
import { FenceNode } from './fence'
import { GuideNode } from './guide'
import { ItemNode } from './item'
@@ -21,6 +22,7 @@ export const LevelNode = BaseNode.extend({
z.union([
WallNode.shape.id,
FenceNode.shape.id,
ColumnNode.shape.id,
ItemNode.shape.id,
ZoneNode.shape.id,
SlabNode.shape.id,
+2
View File
@@ -1,6 +1,7 @@
import z from 'zod'
import { BuildingNode } from './nodes/building'
import { CeilingNode } from './nodes/ceiling'
import { ColumnNode } from './nodes/column'
import { DoorNode } from './nodes/door'
import { FenceNode } from './nodes/fence'
import { GuideNode } from './nodes/guide'
@@ -22,6 +23,7 @@ export const AnyNode = z.discriminatedUnion('type', [
SiteNode,
BuildingNode,
LevelNode,
ColumnNode,
WallNode,
FenceNode,
ItemNode,