From e2de931aa7b0e17e851d26258ed893c31b6c80be Mon Sep 17 00:00:00 2001 From: wass08 Date: Thu, 5 Mar 2026 13:02:17 +0100 Subject: [PATCH] adjust fan anim --- .../editor/public/items/ceiling-fan/model.glb | Bin 6124 -> 5168 bytes .../renderers/item/item-renderer.tsx | 19 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/apps/editor/public/items/ceiling-fan/model.glb b/apps/editor/public/items/ceiling-fan/model.glb index 4e6c0ab066132fa2c2b5a8b00a98ef7fcde94b18..f439d400ae6e1aea953bb555ae3018a5110b635d 100644 GIT binary patch delta 2902 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 diff --git a/packages/viewer/src/components/renderers/item/item-renderer.tsx b/packages/viewer/src/components/renderers/item/item-renderer.tsx index 7c53748f..a825d7aa 100644 --- a/packages/viewer/src/components/renderers/item/item-renderer.tsx +++ b/packages/viewer/src/components/renderers/item/item-renderer.tsx @@ -1,12 +1,19 @@ -import { type AnimationEffect, type AnyNodeId, type ItemNode, useInteractive, useRegistry, useScene } from '@pascal-app/core' +import { + type AnimationEffect, + type AnyNodeId, + type ItemNode, + useInteractive, + useRegistry, + useScene, +} from '@pascal-app/core' import { useAnimations } from '@react-three/drei' import { Clone } from '@react-three/drei/core/Clone' import { useGLTF } from '@react-three/drei/core/Gltf' import { Suspense, useEffect, useMemo, useRef } from 'react' -import { useShallow } from 'zustand/react/shallow' import type { Group, Material, Mesh } from 'three' import { positionLocal, smoothstep, time } from 'three/tsl' import { DoubleSide, MeshStandardNodeMaterial } from 'three/webgpu' +import { useShallow } from 'zustand/react/shallow' import { useNodeEvents } from '../../../hooks/use-node-events' import { resolveCdnUrl } from '../../../lib/asset-url' import { NodeRenderer } from '../node-renderer' @@ -88,13 +95,13 @@ const ModelRenderer = ({ node }: { node: ItemNode }) => { const interactiveRef = useRef(node.asset.interactive) // Subscribe only to this node's control values — useShallow prevents re-renders from other nodes' changes - const controlValues = useInteractive( - useShallow((state) => state.items[node.id]?.controlValues), - ) + const controlValues = useInteractive(useShallow((state) => state.items[node.id]?.controlValues)) useEffect(() => { const interactive = interactiveRef.current - const animEffect = interactive?.effects.find((e): e is AnimationEffect => e.kind === 'animation') + const animEffect = interactive?.effects.find( + (e): e is AnimationEffect => e.kind === 'animation', + ) if (!animEffect) { // Non-interactive: play first available animation as default