Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ export {
} from './store/use-interactive'
export {
default as useLiveNodeOverrides,
type LiveNodeOverrides,
getEffectiveNode,
type LiveNodeOverrides,
} from './store/use-live-node-overrides'
export { default as useLiveTransforms, type LiveTransform } from './store/use-live-transforms'
export { clearSceneHistory, default as useScene } from './store/use-scene'
Expand Down
6 changes: 1 addition & 5 deletions packages/core/src/registry/handles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,7 @@ export type EndpointMoveHandle<N> = {
endpoint: 'start' | 'end'
placement: HandlePlacement<N>
/** Called with the world-space hit on the ground plane. */
apply: (
node: N,
worldPoint: readonly [number, number, number],
sceneApi: SceneApi,
) => Partial<N>
apply: (node: N, worldPoint: readonly [number, number, number], sceneApi: SceneApi) => Partial<N>
portal?: HandlePortal
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,7 @@ export function FloorplanRegistryActionMenu() {
return
}

const el = sceneEl.querySelector(
`[data-node-id="${selectedId}"]`,
) as SVGGElement | null
const el = sceneEl.querySelector(`[data-node-id="${selectedId}"]`) as SVGGElement | null
if (el) {
const rect = el.getBoundingClientRect()
setPosition({ left: rect.left + rect.width / 2, top: rect.top })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,7 @@ export const FloorplanRegistryLayer = memo(function FloorplanRegistryLayer() {
(editorPhase === 'structure' &&
editorMode === 'build' &&
(editorTool === 'door' || editorTool === 'window')) ||
(movingNode != null &&
!!nodeRegistry.get(movingNode.type)?.capabilities?.wallOpeningPlacement)
(movingNode != null && !!nodeRegistry.get(movingNode.type)?.capabilities?.wallOpeningPlacement)
// Subscribe to the live-transforms map ref so the layer re-renders
// whenever a 3D mover publishes a per-frame position (see
// `usePlacementCoordinator`). Without this the 2D floor plan only
Expand Down Expand Up @@ -376,8 +375,7 @@ export const FloorplanRegistryLayer = memo(function FloorplanRegistryLayer() {
const hovered = hoveredId === cid
const moving = movingNode?.id === cid
const ctx: GeometryContext = {
resolve: <N = AnyNode>(rid: AnyNodeId): N | undefined =>
nodes[rid] as N | undefined,
resolve: <N = AnyNode>(rid: AnyNodeId): N | undefined => nodes[rid] as N | undefined,
children: [],
siblings: [],
parent: activeLevelNode,
Expand All @@ -391,9 +389,10 @@ export const FloorplanRegistryLayer = memo(function FloorplanRegistryLayer() {
}
: undefined,
}
const geometry = (
builder as (n: AnyNode, c: GeometryContext) => FloorplanGeometry | null
)(node, ctx)
const geometry = (builder as (n: AnyNode, c: GeometryContext) => FloorplanGeometry | null)(
node,
ctx,
)
if (geometry) {
const { base, overlay } = splitFloorplanOverlay(geometry)
out.push({ id: cid, node, base, overlay, selected, highlighted })
Expand Down Expand Up @@ -1101,11 +1100,7 @@ function InteractiveGeometry({
fill="transparent"
onPointerDown={(e) => {
if (affordance) {
onHandlePointerDown(
affordance,
payload,
e as ReactPointerEvent<SVGGElement>,
)
onHandlePointerDown(affordance, payload, e as ReactPointerEvent<SVGGElement>)
} else {
onMoveHandlePointerDown(e as ReactPointerEvent<SVGGElement>)
}
Expand Down
4 changes: 2 additions & 2 deletions packages/editor/src/components/editor/editor-layout-v2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { EditorLayoutMobile } from './editor-layout-mobile'
const SIDEBAR_MIN_WIDTH = 300
const SIDEBAR_MAX_WIDTH = 800
const SIDEBAR_COLLAPSE_THRESHOLD = 220
// Matches the `w-12` rail in <IconRail>; the resize math is relative to it.
const RAIL_WIDTH = 48
// Matches the `w-14` rail in <IconRail>; the resize math is relative to it.
const RAIL_WIDTH = 56

// ── Left column: resizable panel with tab bar ────────────────────────────────

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,7 @@ const MENU_Y_OFFSETS: Record<string, number> = {
function getMenuYOffset(node: AnyNode | null): number {
if (!node) return MENU_Y_OFFSET_DEFAULT + EXTRA_MENU_LIFT
if (node.type === 'stair-segment') {
return (
(MENU_Y_OFFSETS[`stair-${node.segmentType}`] ?? MENU_Y_OFFSET_DEFAULT) + EXTRA_MENU_LIFT
)
return (MENU_Y_OFFSETS[`stair-${node.segmentType}`] ?? MENU_Y_OFFSET_DEFAULT) + EXTRA_MENU_LIFT
}
return (MENU_Y_OFFSETS[node.type] ?? MENU_Y_OFFSET_DEFAULT) + EXTRA_MENU_LIFT
}
Expand Down Expand Up @@ -181,7 +179,6 @@ export function FloatingActionMenu() {
// in-world chrome (height-resize arrows, measurement labels).
groupRef.current.position.set(center.x, box.max.y + getMenuYOffset(node), center.z)
}

}
})

Expand Down
4 changes: 3 additions & 1 deletion packages/editor/src/components/editor/floorplan-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5045,7 +5045,9 @@ export function FloorplanPanel() {
// space. Length renders at the segment midpoint; angle arcs sit at
// each endpoint that meets an existing wall.
const draftWallMeasurement = useMemo(() => {
if (!(isWallBuildActive && draftStart && draftEnd && isSegmentLongEnough(draftStart, draftEnd))) {
if (
!(isWallBuildActive && draftStart && draftEnd && isSegmentLongEnough(draftStart, draftEnd))
) {
return null
}

Expand Down
21 changes: 8 additions & 13 deletions packages/editor/src/components/editor/node-arrow-handles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,7 @@ export function NodeArrowHandles() {
rawNode ? s.overrides.get(rawNode.id) : undefined,
)
const node = useMemo<AnyNode | null>(
() =>
rawNode && liveOverride ? ({ ...rawNode, ...liveOverride } as AnyNode) : rawNode,
() => (rawNode && liveOverride ? ({ ...rawNode, ...liveOverride } as AnyNode) : rawNode),
[rawNode, liveOverride],
)

Expand All @@ -251,10 +250,7 @@ export function NodeArrowHandles() {
}, [node, def])

const shouldRender =
Boolean(node && descriptors?.length) &&
!isFloorplanHovered &&
mode !== 'delete' &&
!movingNode
Boolean(node && descriptors?.length) && !isFloorplanHovered && mode !== 'delete' && !movingNode

if (!shouldRender || !node || !descriptors) return null
return <NodeArrowHandlesForNode descriptors={descriptors} node={node} />
Expand Down Expand Up @@ -436,7 +432,10 @@ function pickCursor(descriptor: LinearResizeHandle<AnyNode> | RadialResizeHandle
}

function resolveBound(
bound: number | ((node: AnyNode, sceneApi: ReturnType<typeof createSceneApi>) => number) | undefined,
bound:
| number
| ((node: AnyNode, sceneApi: ReturnType<typeof createSceneApi>) => number)
| undefined,
fallback: number,
node: AnyNode,
sceneApi: ReturnType<typeof createSceneApi>,
Expand Down Expand Up @@ -572,10 +571,7 @@ function LinearArrow({
? intersectionLocal.y
: intersectionLocal.z
const delta = currentPointer - initialPointer
const next = Math.min(
maxBound,
Math.max(minBound, initialValue + delta * factor),
)
const next = Math.min(maxBound, Math.max(minBound, initialValue + delta * factor))
// apply sees the node-at-drag-start so it can compute anchors from
// pre-drag geometry (door-width re-centers on the opposite edge).
const patch = descriptor.apply(initialNode as never, next, sceneApi)
Expand Down Expand Up @@ -928,8 +924,7 @@ function TapActionArrow({
const position = descriptor.placement.position(node, placementSceneApi)
const rotationY = descriptor.placement.rotationY?.(node, placementSceneApi) ?? 0
const shape = descriptor.shape ?? 'arrow'
const cursor: Cursor =
descriptor.cursor ?? (shape === 'corner-picker' ? 'move' : 'ew-resize')
const cursor: Cursor = descriptor.cursor ?? (shape === 'corner-picker' ? 'move' : 'ew-resize')

const onActivate = (event: ThreeEvent<PointerEvent>) => {
event.stopPropagation()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,6 @@ function FenceMoveArrowHandle({ fence, handle }: { fence: FenceNode; handle: Wal
frustumCulled={false}
geometry={arrowGeometry}
material={arrowMaterial}

onPointerDown={activateFenceMove}
onPointerEnter={(event) => {
event.stopPropagation()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -514,9 +514,7 @@ export const PolygonEditor: React.FC<PolygonEditorProps> = ({
position={[x!, editY + height / 2, z!]}
>
<cylinderGeometry args={[radius, radius, height, 16]} />
<meshBasicMaterial
color={isDragging ? '#22c55e' : isHovered ? '#60a5fa' : '#3b82f6'}
/>
<meshBasicMaterial color={isDragging ? '#22c55e' : isHovered ? '#60a5fa' : '#3b82f6'} />
</mesh>
)
})}
Expand Down
68 changes: 1 addition & 67 deletions packages/editor/src/components/ui/action-menu/control-modes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,7 @@ import { cn } from './../../../lib/utils'
import useEditor from './../../../store/use-editor'
import { ActionButton } from './action-button'

type ControlId =
| 'select'
| 'box-select'
| 'site-edit'
| 'build'
| 'material-paint'
| 'furnish'
| 'zone'
| 'delete'
type ControlId = 'select' | 'box-select' | 'site-edit' | 'zone' | 'delete'

type ControlConfig = {
id: ControlId
Expand Down Expand Up @@ -54,30 +46,6 @@ const controls: ControlConfig[] = [
color: 'hover:bg-white/5',
activeColor: 'bg-white/10 hover:bg-white/10',
},
{
id: 'build',
imageSrc: '/icons/build.png',
label: 'Build',
shortcut: 'B',
color: 'hover:bg-green-500/20 hover:text-green-400',
activeColor: 'bg-green-500/20 text-green-400',
},
{
id: 'material-paint',
imageSrc: '/icons/paint.png',
label: 'Material Paint',
shortcut: 'P',
color: 'hover:bg-amber-500/20 hover:text-amber-400',
activeColor: 'bg-amber-500/20 text-amber-400',
},
{
id: 'furnish',
imageSrc: '/icons/couch.png',
label: 'Furnish',
shortcut: 'F',
color: 'hover:bg-green-500/20 hover:text-green-400',
activeColor: 'bg-green-500/20 text-green-400',
},
{
id: 'zone',
imageSrc: '/icons/zone.png',
Expand All @@ -104,9 +72,6 @@ export function ControlModes() {
const setPhase = useEditor((state) => state.setPhase)
const setStructureLayer = useEditor((state) => state.setStructureLayer)
const setSelectionTool = useEditor((state) => state.setFloorplanSelectionTool)
const primeMaterialPaintFromSelection = useEditor(
(state) => state.primeMaterialPaintFromSelection,
)
const levelId = useViewer((s) => s.selection.levelId)

// Only subscribe to the primitive `level` number — when walls are added to
Expand All @@ -129,10 +94,6 @@ export function ControlModes() {
if (id === 'select') return mode === 'select' && selectionTool === 'click'
if (id === 'box-select') return mode === 'select' && selectionTool === 'marquee'
if (id === 'site-edit') return false
if (id === 'build')
return mode === 'build' && phase === 'structure' && structureLayer === 'elements'
if (id === 'material-paint') return mode === 'material-paint'
if (id === 'furnish') return mode === 'build' && phase === 'furnish'
if (id === 'zone')
return mode === 'build' && phase === 'structure' && structureLayer === 'zones'
return mode === id
Expand Down Expand Up @@ -168,33 +129,6 @@ export function ControlModes() {
} else if (id === 'box-select') {
setMode('select')
setSelectionTool('marquee')
} else if (id === 'build') {
// Toggle: if already in structure build, go back to select
if (getIsActive('build')) {
setMode('select')
} else {
setPhase('structure')
setStructureLayer('elements')
setMode('build')
}
} else if (id === 'material-paint') {
if (getIsActive('material-paint')) {
setMode('select')
} else {
primeMaterialPaintFromSelection()
setPhase('structure')
setStructureLayer('elements')
setMode('material-paint')
}
} else if (id === 'furnish') {
if (getIsActive('furnish')) {
setMode('select')
} else {
setPhase('furnish')
setMode('build')
// Auto-switch sidebar to the items panel so the user can pick furniture
useEditor.getState().setActiveSidebarPanel('items')
}
} else if (id === 'zone') {
if (getIsActive('zone')) {
setMode('select')
Expand Down
Loading
Loading