Merge remote-tracking branch 'origin/main' into chore/deps-2026-06
This commit is contained in:
@@ -126,9 +126,8 @@ export const MoveCeilingTool: React.FC<{ node: CeilingNode }> = ({ node }) => {
|
||||
deltaRef.current = [deltaX, deltaZ]
|
||||
setMeshOffset(ceilingId as AnyNodeId, deltaX, deltaZ, height)
|
||||
// Aligned with slab/fence: the delta matches the direct mesh
|
||||
// mutation. CeilingRenderer doesn't bind position via React, so
|
||||
// this entry isn't consumed for rendering, but kept consistent
|
||||
// in case other systems read it.
|
||||
// mutation. CeilingRenderer also consumes this store so external
|
||||
// movers can preview ceilings without rebuilding the polygon.
|
||||
useLiveTransforms.getState().set(ceilingId, {
|
||||
position: [deltaX, 0, deltaZ],
|
||||
rotation: 0,
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
type CeilingNode,
|
||||
getMaterialPresetByRef,
|
||||
resolveMaterial,
|
||||
useLiveTransforms,
|
||||
useRegistry,
|
||||
useScene,
|
||||
} from '@pascal-app/core'
|
||||
@@ -79,6 +80,13 @@ export const CeilingRenderer = ({ node }: { node: CeilingNode }) => {
|
||||
const textures = useViewer((s) => s.textures)
|
||||
const colorPreset = useViewer((s) => s.colorPreset)
|
||||
const sceneTheme = useViewer((s) => s.sceneTheme)
|
||||
const liveTransform = useLiveTransforms((s) => s.get(node.id))
|
||||
const ceilingY = (node.height ?? 2.5) - 0.01 + (liveTransform?.position[1] ?? 0)
|
||||
const position: [number, number, number] = [
|
||||
liveTransform?.position[0] ?? 0,
|
||||
ceilingY,
|
||||
liveTransform?.position[2] ?? 0,
|
||||
]
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
@@ -124,7 +132,12 @@ export const CeilingRenderer = ({ node }: { node: CeilingNode }) => {
|
||||
])
|
||||
|
||||
return (
|
||||
<mesh geometry={placeholderGeometry} material={materials.bottomMaterial} ref={ref}>
|
||||
<mesh
|
||||
geometry={placeholderGeometry}
|
||||
material={materials.bottomMaterial}
|
||||
position={position}
|
||||
ref={ref}
|
||||
>
|
||||
<mesh
|
||||
geometry={gridPlaceholderGeometry}
|
||||
material={materials.topMaterial}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import {
|
||||
type AnimationEffect,
|
||||
type AnyNodeId,
|
||||
getScaledDimensions,
|
||||
type Interactive,
|
||||
type ItemNode,
|
||||
type LightEffect,
|
||||
@@ -91,17 +92,25 @@ export const ItemRenderer = ({ node: storeNode }: { node: ItemNode }) => {
|
||||
() => (liveOverrides ? ({ ...storeNode, ...liveOverrides } as ItemNode) : storeNode),
|
||||
[storeNode, liveOverrides],
|
||||
)
|
||||
const roomClearPreview =
|
||||
(node as ItemNode & { roomClearPreview?: unknown }).roomClearPreview === true
|
||||
|
||||
return (
|
||||
<group position={node.position} ref={ref} rotation={node.rotation} visible={node.visible}>
|
||||
<ErrorBoundary fallback={<BrokenItemFallback node={node} />}>
|
||||
<Suspense fallback={<PreviewModel node={node} />}>
|
||||
<ModelRenderer node={node} />
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
{node.children?.map((childId) => (
|
||||
<NodeRenderer key={childId} nodeId={childId} />
|
||||
))}
|
||||
{roomClearPreview ? (
|
||||
<ClearPreviewModel node={node} />
|
||||
) : (
|
||||
<>
|
||||
<ErrorBoundary fallback={<BrokenItemFallback node={node} />}>
|
||||
<Suspense fallback={<PreviewModel node={node} />}>
|
||||
<ModelRenderer node={node} />
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
{node.children?.map((childId) => (
|
||||
<NodeRenderer key={childId} nodeId={childId} />
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</group>
|
||||
)
|
||||
}
|
||||
@@ -133,6 +142,26 @@ const PreviewModel = ({ node }: { node: ItemNode }) => {
|
||||
)
|
||||
}
|
||||
|
||||
const ClearPreviewModel = ({ node }: { node: ItemNode }) => {
|
||||
const shading = useViewer((s) => s.shading)
|
||||
const [w, h, d] = getScaledDimensions(node)
|
||||
const material = useMemo(() => {
|
||||
const next = createDefaultMaterial('#ef4444', 1, shading) as MutableMaterial
|
||||
next.depthTest = false
|
||||
next.opacity = 0.35
|
||||
next.transparent = true
|
||||
next.wireframe = true
|
||||
next.needsUpdate = true
|
||||
return next
|
||||
}, [shading])
|
||||
|
||||
return (
|
||||
<mesh material={material} position-y={h / 2}>
|
||||
<boxGeometry args={[w, h, d]} />
|
||||
</mesh>
|
||||
)
|
||||
}
|
||||
|
||||
const multiplyScales = (
|
||||
a: [number, number, number],
|
||||
b: [number, number, number],
|
||||
|
||||
Reference in New Issue
Block a user