@ntalmagor/3drize-viewer 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/components/AnimatedObject.d.ts.map +1 -1
  2. package/dist/components/AnimatedObject.js +73 -72
  3. package/dist/components/CreatedObject.d.ts.map +1 -1
  4. package/dist/components/CreatedObject.js +0 -1
  5. package/dist/components/CustomPrimitive.d.ts +1 -3
  6. package/dist/components/CustomPrimitive.d.ts.map +1 -1
  7. package/dist/components/CustomPrimitive.js +1 -1
  8. package/dist/components/ObjectNode.d.ts.map +1 -1
  9. package/dist/components/ObjectNode.js +3 -3
  10. package/dist/components/ObjectNodeApi.d.ts +13 -0
  11. package/dist/components/ObjectNodeApi.d.ts.map +1 -0
  12. package/dist/components/ObjectNodeApi.js +18 -0
  13. package/dist/components/ObjectsRenderer.d.ts +2 -1
  14. package/dist/components/ObjectsRenderer.d.ts.map +1 -1
  15. package/dist/components/ObjectsRenderer.js +21 -2
  16. package/dist/components/ProductionScene.d.ts.map +1 -1
  17. package/dist/components/ProductionScene.js +2 -28
  18. package/dist/components/ProjectLoader.d.ts.map +1 -1
  19. package/dist/components/ProjectLoader.js +26 -2
  20. package/dist/components/SceneBuilder.d.ts.map +1 -1
  21. package/dist/components/SceneBuilder.js +13 -11
  22. package/dist/constants.d.ts +1 -1
  23. package/dist/constants.d.ts.map +1 -1
  24. package/dist/constants.js +7 -1
  25. package/dist/hooks/useAnimationEvents.d.ts.map +1 -1
  26. package/dist/hooks/useAnimationEvents.js +22 -1
  27. package/dist/hooks/useObjectAnimation.d.ts.map +1 -1
  28. package/dist/hooks/useObjectAnimation.js +16 -0
  29. package/dist/hooks/useSequenceAnimation.d.ts +14 -0
  30. package/dist/hooks/useSequenceAnimation.d.ts.map +1 -0
  31. package/dist/hooks/useSequenceAnimation.js +258 -0
  32. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AnimatedObject.d.ts","sourceRoot":"","sources":["../../src/components/AnimatedObject.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAEpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAQvG,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,iBAAiB,CAAC;IACtC,aAAa,EAAE,qBAAqB,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACtC,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IACjH,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;IACvD,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;IACvD,MAAM,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;CAE3B;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA6JvD,CAAC;AAGH,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"AnimatedObject.d.ts","sourceRoot":"","sources":["../../src/components/AnimatedObject.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAEpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAQvG,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,iBAAiB,CAAC;IACtC,aAAa,EAAE,qBAAqB,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACtC,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IACjH,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;IACvD,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;IACvD,MAAM,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;CAE3B;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA+JvD,CAAC;AAGH,eAAe,cAAc,CAAC"}
@@ -1,10 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useRef, useEffect, useCallback, memo } from 'react';
3
- import { useFrame } from '@react-three/fiber';
4
- import { useAnimationEvents } from '../hooks/useAnimationEvents.js';
5
3
  import { usePathAnimation } from '../hooks/usePathAnimation.js';
6
- import { AnimationsManager } from '@ntalmagor/3drize-core';
7
- import { applyAnchorSettings } from '../utils/anchorUtils.js';
8
4
  import EffectsGroup from './EffectsGroup.js';
9
5
  import { useObjectAnimation } from '../hooks/useObjectAnimation.js';
10
6
  export const AnimatedObject = memo(({ stateKey, transitionSettings, createdObject,
@@ -47,74 +43,79 @@ visible = true, children, parentRef, handleObjectClick, onPointerEnter, onPointe
47
43
  animProgress.current = 0;
48
44
  }, [position, scale, rotation, targetPosition, targetScale, targetRotation]);
49
45
  useEffect(() => { syncTransform(); }, [position, scale, rotation, targetPosition, targetScale, targetRotation]);
50
- useAnimationEvents({
51
- onStepStart: (event) => {
52
- if (!event.step?.transitions)
53
- return;
54
- const d = event.step.duration || 1;
55
- for (const { state, properties, pathId } of event.step.transitions) {
56
- if (state !== stateKey)
57
- continue;
58
- if (properties.to.visible === false) {
59
- if (groupRef.current)
60
- groupRef.current.visible = false;
61
- }
62
- else {
63
- if (groupRef.current)
64
- groupRef.current.visible = true;
65
- stepDuration.current = d;
66
- stepEase.current = event.step.ease || 'linear';
67
- animationStartTime.current = performance.now();
68
- animProgress.current = 0;
69
- if (pathId) {
70
- startPathAnimation(pathId, d, { ease: stepEase.current });
71
- }
72
- else {
73
- const cur = targetRef.current;
74
- baseRef.current = {
75
- position: (properties.from?.position ? [...properties.from.position] : cur.position),
76
- rotation: (properties.from?.rotation ? [...properties.from.rotation] : cur.rotation),
77
- scale: (properties.from?.scale ? [...properties.from.scale] : cur.scale),
78
- };
79
- targetRef.current = {
80
- position: (properties.to?.position ? [...properties.to.position] : cur.position),
81
- rotation: (properties.to?.rotation ? [...properties.to.rotation] : cur.rotation),
82
- scale: (properties.to?.scale ? [...properties.to.scale] : cur.scale),
83
- };
84
- }
85
- }
86
- }
87
- },
88
- });
89
- const applyTransformProgress = useCallback(() => {
90
- const obj = groupRef.current;
91
- if (!obj || animationStartTime.current === null)
92
- return;
93
- const p = AnimationsManager.getProgressFromTime(animationStartTime.current, stepDuration.current, stepEase.current);
94
- animProgress.current = p;
95
- const b = baseRef.current, t = targetRef.current;
96
- obj.position.set(b.position[0] + (t.position[0] - b.position[0]) * p, b.position[1] + (t.position[1] - b.position[1]) * p, b.position[2] + (t.position[2] - b.position[2]) * p);
97
- obj.scale.set(b.scale[0] + (t.scale[0] - b.scale[0]) * p, b.scale[1] + (t.scale[1] - b.scale[1]) * p, b.scale[2] + (t.scale[2] - b.scale[2]) * p);
98
- obj.rotation.set(b.rotation[0] + (t.rotation[0] - b.rotation[0]) * p, b.rotation[1] + (t.rotation[1] - b.rotation[1]) * p, b.rotation[2] + (t.rotation[2] - b.rotation[2]) * p);
99
- }, []);
100
- useFrame((_state, delta) => {
101
- if (!visible || !groupRef.current)
102
- return;
103
- if (animProgress.current < 1) {
104
- if (isPathAnimating()) {
105
- const still = updatePathAnimation(delta, groupRef.current);
106
- if (!still) {
107
- animProgress.current = 1;
108
- animationStartTime.current = null;
109
- }
110
- }
111
- else if (animationStartTime.current !== null) {
112
- applyTransformProgress();
113
- }
114
- }
115
- if (anchor)
116
- applyAnchorSettings(anchor, groupRef.current, rotation);
117
- });
46
+ // useAnimationEvents({
47
+ // onStepStart: (event) => {
48
+ // console.log('Received animation event:', event);
49
+ // if (!event.step?.transitions) return;
50
+ // const d = event.step.duration || 1;
51
+ // for (const { state, properties, pathId } of event.step.transitions) {
52
+ // console.log(`Animation event for state: ${state}, object stateKey: ${stateKey}`);
53
+ // if (state !== stateKey) continue;
54
+ // if (properties.to.visible === false) {
55
+ // if (groupRef.current) groupRef.current.visible = false;
56
+ // } else {
57
+ // if (groupRef.current) groupRef.current.visible = true;
58
+ // stepDuration.current = d;
59
+ // stepEase.current = event.step.ease || 'linear';
60
+ // animationStartTime.current = performance.now();
61
+ // animProgress.current = 0;
62
+ // if (pathId) {
63
+ // startPathAnimation(pathId, d, { ease: stepEase.current });
64
+ // } else {
65
+ // const cur = targetRef.current;
66
+ // baseRef.current = {
67
+ // position: (properties.from?.position ? [...properties.from.position] : cur.position) as [number, number, number],
68
+ // rotation: (properties.from?.rotation ? [...properties.from.rotation] : cur.rotation) as [number, number, number],
69
+ // scale: (properties.from?.scale ? [...properties.from.scale] : cur.scale) as [number, number, number],
70
+ // };
71
+ // targetRef.current = {
72
+ // position: (properties.to?.position ? [...properties.to.position] : cur.position) as [number, number, number],
73
+ // rotation: (properties.to?.rotation ? [...properties.to.rotation] : cur.rotation) as [number, number, number],
74
+ // scale: (properties.to?.scale ? [...properties.to.scale] : cur.scale) as [number, number, number],
75
+ // };
76
+ // }
77
+ // }
78
+ // }
79
+ // },
80
+ // });
81
+ // const applyTransformProgress = useCallback(() => {
82
+ // const obj = groupRef.current;
83
+ // if (!obj || animationStartTime.current === null) return;
84
+ // const p = AnimationsManager.getProgressFromTime(
85
+ // animationStartTime.current,
86
+ // stepDuration.current,
87
+ // stepEase.current,
88
+ // );
89
+ // animProgress.current = p;
90
+ // const b = baseRef.current, t = targetRef.current;
91
+ // obj.position.set(
92
+ // b.position[0] + (t.position[0] - b.position[0]) * p,
93
+ // b.position[1] + (t.position[1] - b.position[1]) * p,
94
+ // b.position[2] + (t.position[2] - b.position[2]) * p,
95
+ // );
96
+ // obj.scale.set(
97
+ // b.scale[0] + (t.scale[0] - b.scale[0]) * p,
98
+ // b.scale[1] + (t.scale[1] - b.scale[1]) * p,
99
+ // b.scale[2] + (t.scale[2] - b.scale[2]) * p,
100
+ // );
101
+ // obj.rotation.set(
102
+ // b.rotation[0] + (t.rotation[0] - b.rotation[0]) * p,
103
+ // b.rotation[1] + (t.rotation[1] - b.rotation[1]) * p,
104
+ // b.rotation[2] + (t.rotation[2] - b.rotation[2]) * p,
105
+ // );
106
+ // }, []);
107
+ // useFrame((_state, delta) => {
108
+ // if (!visible || !groupRef.current) return;
109
+ // if (animProgress.current < 1) {
110
+ // if (isPathAnimating()) {
111
+ // const still = updatePathAnimation(delta, groupRef.current);
112
+ // if (!still) { animProgress.current = 1; animationStartTime.current = null; }
113
+ // } else if (animationStartTime.current !== null) {
114
+ // applyTransformProgress();
115
+ // }
116
+ // }
117
+ // if (anchor) applyAnchorSettings(anchor, groupRef.current, rotation);
118
+ // });
118
119
  const onClick = (e) => {
119
120
  if (handleObjectClick && groupRef.current) {
120
121
  handleObjectClick(createdObject, groupRef.current, e);
@@ -1 +1 @@
1
- {"version":3,"file":"CreatedObject.d.ts","sourceRoot":"","sources":["../../src/components/CreatedObject.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4C,MAAM,OAAO,CAAC;AAEjE,OAAO,KAAK,EAAe,qBAAqB,EAAkC,MAAM,wBAAwB,CAAC;AAOjH,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAMjC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAWrD,UAAU,kBAAkB;IAC1B,aAAa,EAAE,qBAAqB,CAAC;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvE,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAElH;AAED,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAiK9C,CAAC;AAIH,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"CreatedObject.d.ts","sourceRoot":"","sources":["../../src/components/CreatedObject.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4C,MAAM,OAAO,CAAC;AAEjE,OAAO,KAAK,EAAG,qBAAqB,EAAkC,MAAM,wBAAwB,CAAC;AAOrG,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAMjC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAWrD,UAAU,kBAAkB;IAC1B,aAAa,EAAE,qBAAqB,CAAC;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvE,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAElH;AAED,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAiK9C,CAAC;AAIH,eAAe,aAAa,CAAC"}
@@ -7,7 +7,6 @@ import { RigidBody } from '@react-three/rapier';
7
7
  import { cameraManager } from "../utils/CameraSingleton.js";
8
8
  import AnimatedObject from "./AnimatedObject.js";
9
9
  import { useFrameEffects } from "../hooks/useFrameEffects.js";
10
- // import { useSceneClick } from "~/contextProviders/SceneClickContext";
11
10
  import { useObjectEdges } from "../hooks/useObjectEdges.js";
12
11
  const CreatedObject = memo(({ createdObject, children, shouldApply3driseMaterial = true, onObjectReady, handleObjectClick, }) => {
13
12
  const isSelected = false;
@@ -1,11 +1,9 @@
1
1
  import React from "react";
2
- import { type CameraState, type CreatedObjectSettings } from "@ntalmagor/3drize-core";
2
+ import { type CreatedObjectSettings } from "@ntalmagor/3drize-core";
3
3
  import { Object3D } from "three";
4
4
  import { type ThreeEvent } from '@react-three/fiber';
5
5
  interface CustomPrimitiveProps {
6
6
  createdObject: CreatedObjectSettings;
7
- cameraSettings: CameraState;
8
- updateObjectSettings?: (updatedSettings: CreatedObjectSettings) => void;
9
7
  onObjectReady?: (object: CreatedObjectSettings, ref: Object3D) => void;
10
8
  handleObjectClick?: (createdObject: CreatedObjectSettings, ref: Object3D, event: ThreeEvent<MouseEvent>) => void;
11
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CustomPrimitive.d.ts","sourceRoot":"","sources":["../../src/components/CustomPrimitive.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4C,MAAM,OAAO,CAAC;AAEjE,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,qBAAqB,EAI5B,MAAM,wBAAwB,CAAC;AAIxD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAMjC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAOrD,UAAU,oBAAoB;IAC5B,aAAa,EAAE,qBAAqB,CAAC;IACrC,cAAc,EAAE,WAAW,CAAA;IAC3B,oBAAoB,CAAC,EAAE,CAAC,eAAe,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACxE,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvE,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAClH;AAED,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAuHlD,CAAC;AAIH,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"CustomPrimitive.d.ts","sourceRoot":"","sources":["../../src/components/CustomPrimitive.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4C,MAAM,OAAO,CAAC;AAEjE,OAAO,EAAoB,KAAK,qBAAqB,EAI5B,MAAM,wBAAwB,CAAC;AAIxD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAMjC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAOrD,UAAU,oBAAoB;IAC5B,aAAa,EAAE,qBAAqB,CAAC;IACrC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvE,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAClH;AAED,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAqHlD,CAAC;AAIH,eAAe,eAAe,CAAC"}
@@ -8,7 +8,7 @@ import MaterialLibrary from "./MaterialLibrary.js";
8
8
  // import type { AnimatedTransform } from "~/types/mesh";
9
9
  import CreatedObject from "./CreatedObject.js";
10
10
  import { useFrameEffects } from "../hooks/useFrameEffects.js";
11
- const CustomPrimitive = memo(({ createdObject, cameraSettings, updateObjectSettings, onObjectReady, handleObjectClick, }) => {
11
+ const CustomPrimitive = memo(({ createdObject, onObjectReady, handleObjectClick, }) => {
12
12
  // const { handleObjectClick } = useSceneClick();
13
13
  // console.log("Rendering CustomPrimitive with settings:", createdObject.name, createdObject);
14
14
  const meshRef = useRef(null);
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectNode.d.ts","sourceRoot":"","sources":["../../src/components/ObjectNode.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+B,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAA6D,cAAc,EAA0B,MAAM,wBAAwB,CAAC;AAEpL,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAWrD,KAAK,eAAe,GAAG;IACnB,IAAI,EAAE,cAAc,CAAC;IACrB,cAAc,EAAE,WAAW,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvE,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAC7G,CAAC;AAkDF,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAyJzC,CAAC;AAEF,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"ObjectNode.d.ts","sourceRoot":"","sources":["../../src/components/ObjectNode.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+B,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAA6D,cAAc,EAA0B,MAAM,wBAAwB,CAAC;AAEpL,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAWrD,KAAK,eAAe,GAAG;IACnB,IAAI,EAAE,cAAc,CAAC;IACrB,cAAc,EAAE,WAAW,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvE,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAC7G,CAAC;AAkDF,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAsJzC,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -23,9 +23,9 @@ const ObjectNode = ({ node, cameraSettings, onObjectReady, handleObjectClick })
23
23
  // Specialized renderers for each object type
24
24
  const renderers = useMemo(() => ({
25
25
  group: () => null,
26
- mesh: (obj, cameraSettings, onObjectReady) => (_jsx(CustomPrimitive, { createdObject: obj, cameraSettings: cameraSettings, onObjectReady: onObjectReady, handleObjectClick: handleObjectClick }, obj.id)),
27
- model: (obj, cameraSettings, onObjectReady) => (_jsx(CustomPrimitive, { createdObject: obj, cameraSettings: cameraSettings, onObjectReady: onObjectReady, handleObjectClick: handleObjectClick }, obj.id)),
28
- custom_primitive: (obj, cameraSettings, onObjectReady) => (_jsx(CustomPrimitive, { createdObject: obj, cameraSettings: cameraSettings, onObjectReady: onObjectReady, handleObjectClick: handleObjectClick }, obj.id)),
26
+ mesh: (obj, cameraSettings, onObjectReady) => (_jsx(CustomPrimitive, { createdObject: obj, onObjectReady: onObjectReady, handleObjectClick: handleObjectClick }, obj.id)),
27
+ model: (obj, cameraSettings, onObjectReady) => (_jsx(CustomPrimitive, { createdObject: obj, onObjectReady: onObjectReady, handleObjectClick: handleObjectClick }, obj.id)),
28
+ custom_primitive: (obj, cameraSettings, onObjectReady) => (_jsx(CustomPrimitive, { createdObject: obj, onObjectReady: onObjectReady, handleObjectClick: handleObjectClick }, obj.id)),
29
29
  text: (obj, cameraSettings, onObjectReady) => {
30
30
  const renderMode = obj.config?.renderMode ?? 'bitmap';
31
31
  return (_jsx(CreatedObject, { createdObject: obj, onObjectReady: onObjectReady, handleObjectClick: handleObjectClick, children: renderMode === 'text3d'
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import { Object3D } from 'three';
3
+ import type { CameraState, CreatedObjectSettings } from '@ntalmagor/3drize-core';
4
+ import { type ThreeEvent } from '@react-three/fiber';
5
+ type ObjectNodeApiProps = {
6
+ objectId: string;
7
+ cameraSettings: CameraState;
8
+ onObjectReady?: (object: CreatedObjectSettings, ref: Object3D) => void;
9
+ handleObjectClick?: (object: CreatedObjectSettings, ref: Object3D, event: ThreeEvent<MouseEvent>) => void;
10
+ };
11
+ declare const ObjectNodeApi: React.FC<ObjectNodeApiProps>;
12
+ export default ObjectNodeApi;
13
+ //# sourceMappingURL=ObjectNodeApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObjectNodeApi.d.ts","sourceRoot":"","sources":["../../src/components/ObjectNodeApi.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAkB,MAAM,wBAAwB,CAAC;AACjG,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAKrD,KAAK,kBAAkB,GAAG;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,WAAW,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvE,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAC7G,CAAC;AAEF,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAoB/C,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ // import { apiFetch } from '../utils/apiFetch';
4
+ import ObjectNode from './ObjectNode.js';
5
+ import { dataCenterServer } from '../constants.js';
6
+ const ObjectNodeApi = ({ objectId, cameraSettings, onObjectReady, handleObjectClick }) => {
7
+ const [node, setNode] = useState(null);
8
+ useEffect(() => {
9
+ fetch(`${dataCenterServer}scene-objects/${objectId}/tree`)
10
+ .then(res => res.ok ? res.json() : Promise.reject(res.status))
11
+ .then(({ tree }) => setNode(tree))
12
+ .catch(err => console.error('Failed to fetch scene object tree:', err));
13
+ }, [objectId]);
14
+ if (!node)
15
+ return null;
16
+ return (_jsx(ObjectNode, { node: node, cameraSettings: cameraSettings, onObjectReady: onObjectReady, handleObjectClick: handleObjectClick }));
17
+ };
18
+ export default ObjectNodeApi;
@@ -1,13 +1,14 @@
1
1
  import React from 'react';
2
2
  import { Object3D } from 'three';
3
3
  import { type ThreeEvent } from '@react-three/fiber';
4
- import { GeneralObjectSettings, type CameraState, type CreatedObjectSettings } from '@ntalmagor/3drize-core';
4
+ import { AnimationSequence, GeneralObjectSettings, type CameraState, type CreatedObjectSettings } from '@ntalmagor/3drize-core';
5
5
  interface ObjectsRendererProps {
6
6
  cameraSettings: CameraState;
7
7
  generalObjectSettings: GeneralObjectSettings;
8
8
  createdObjects: CreatedObjectSettings[];
9
9
  onObjectsReady?: () => void;
10
10
  handleObjectClick?: (object: CreatedObjectSettings, ref: Object3D, event: ThreeEvent<MouseEvent>) => void;
11
+ sequences?: AnimationSequence[];
11
12
  }
12
13
  declare const ObjectsRenderer: React.FC<ObjectsRendererProps>;
13
14
  export default ObjectsRenderer;
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectsRenderer.d.ts","sourceRoot":"","sources":["../../src/components/ObjectsRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6C,MAAM,OAAO,CAAC;AAClE,OAAO,EAAS,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAmB,qBAAqB,EAAE,KAAK,WAAW,EAAE,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAO9H,UAAU,oBAAoB;IAC5B,cAAc,EAAE,WAAW,CAAC;IAC5B,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C,cAAc,EAAE,qBAAqB,EAAE,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAC3G;AAED,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAgClD,CAAC;AAIH,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"ObjectsRenderer.d.ts","sourceRoot":"","sources":["../../src/components/ObjectsRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6C,MAAM,OAAO,CAAC;AAClE,OAAO,EAAS,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAmB,qBAAqB,EAAe,KAAK,WAAW,EAAE,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAQ9J,UAAU,oBAAoB;IAC5B,cAAc,EAAE,WAAW,CAAC;IAC5B,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C,cAAc,EAAE,qBAAqB,EAAE,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IAC1G,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;CACjC;AAED,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA4DlD,CAAC;AAIH,eAAe,eAAe,CAAC"}
@@ -2,7 +2,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { memo, useRef, useCallback, useMemo } from 'react';
3
3
  import { buildObjectTree } from '@ntalmagor/3drize-core';
4
4
  import ObjectNode from './ObjectNode.js';
5
- const ObjectsRenderer = memo(({ cameraSettings, createdObjects, generalObjectSettings, onObjectsReady, handleObjectClick }) => {
5
+ import useInteraction from '../hooks/useInteraction.js';
6
+ const ObjectsRenderer = memo(({ cameraSettings, createdObjects, generalObjectSettings, onObjectsReady, handleObjectClick, sequences = [], }) => {
6
7
  const groupRef = useRef(null);
7
8
  const objectsTree = useMemo(() => buildObjectTree(createdObjects), [createdObjects]);
8
9
  const readyObjectsCount = useRef(0);
@@ -13,7 +14,25 @@ const ObjectsRenderer = memo(({ cameraSettings, createdObjects, generalObjectSet
13
14
  onObjectsReady && onObjectsReady();
14
15
  }
15
16
  }, [objectsTree.length, onObjectsReady]);
16
- return (_jsx("group", { ref: groupRef, name: "main-objects", position: generalObjectSettings.meshSettings.position, rotation: generalObjectSettings.meshSettings.rotation, scale: generalObjectSettings.meshSettings.scale, children: objectsTree.map(node => (_jsx(ObjectNode, { node: node, cameraSettings: cameraSettings, onObjectReady: onObjectReady, handleObjectClick: handleObjectClick }, node.objectId))) }));
17
+ function filterInteractionsByEvent(interactions, mouseEvent) {
18
+ if (!interactions)
19
+ return [];
20
+ return interactions.filter((interaction) => interaction.mouseEvent === mouseEvent);
21
+ }
22
+ const { executeInteraction } = useInteraction({
23
+ cameraSettings,
24
+ sequences,
25
+ });
26
+ const handleObjectClickHandler = (createdObject, ref, event) => {
27
+ const clickInteractions = filterInteractionsByEvent(createdObject.interactions?.actions, "click");
28
+ clickInteractions.forEach((interaction) => {
29
+ executeInteraction({ interaction, ref, createdObject });
30
+ });
31
+ if (handleObjectClick) {
32
+ handleObjectClick(createdObject, ref, event);
33
+ }
34
+ };
35
+ return (_jsx("group", { ref: groupRef, name: "main-objects", position: generalObjectSettings.meshSettings.position, rotation: generalObjectSettings.meshSettings.rotation, scale: generalObjectSettings.meshSettings.scale, children: objectsTree.map(node => (_jsx(ObjectNode, { node: node, cameraSettings: cameraSettings, onObjectReady: onObjectReady, handleObjectClick: handleObjectClickHandler }, node.objectId))) }));
17
36
  });
18
37
  ObjectsRenderer.displayName = 'ObjectsRenderer';
19
38
  export default ObjectsRenderer;
@@ -1 +1 @@
1
- {"version":3,"file":"ProductionScene.d.ts","sourceRoot":"","sources":["../../src/components/ProductionScene.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EAAsC,oBAAoB,EAAG,MAAM,wBAAwB,CAAC;AAexG,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA2HnD,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"ProductionScene.d.ts","sourceRoot":"","sources":["../../src/components/ProductionScene.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EAAsC,oBAAoB,EAAG,MAAM,wBAAwB,CAAC;AAUxG,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAkCnD,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -2,34 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { OrbitControls } from "@react-three/drei";
3
3
  import { Physics } from "@react-three/rapier";
4
4
  import { Vector3 } from "three";
5
- import LightsManager from "./LightsManager.js";
6
- import EnvironmentManager from "./EnvironmentManager.js";
7
- import CameraController from "./CameraController.js";
8
- import Ocean from "./Ocean.js";
9
- import ObjectsRenderer from "./ObjectsRenderer.js";
10
- import { useInteraction } from "../hooks/useInteraction.js";
11
- const ProductionScene = ({ onObjectsReady, onObjectClick, gridSettings, hdr, physicsSettings, generalObjectSettings, ocean, cameraSettings, selectedLight, objects, lighting, controls, geometry, structure, sky, timeSettings, starsSettings, clouds, rainSettings, fogSettings, animationSequences, }) => {
12
- const sunSystem = sky.sunSystem;
13
- const mode = 'default';
14
- // console.log({animationSequences})
5
+ const ProductionScene = ({ physicsSettings, controls, children, }) => {
15
6
  // Interaction hook
16
- const { executeInteraction, currentAnimatedRef, glowingObjects, vanishedObjects } = useInteraction({
17
- cameraSettings,
18
- sequences: animationSequences,
19
- });
20
- function filterInteractionsByEvent(interactions, mouseEvent) {
21
- if (!interactions)
22
- return [];
23
- return interactions.filter((interaction) => interaction.mouseEvent === mouseEvent);
24
- }
25
- const handleObjectClick = (createdObject, ref, event) => {
26
- console.log('[ProductionScene] handleObjectClick:', createdObject.id);
27
- const clickInteractions = filterInteractionsByEvent(createdObject.interactions?.actions, 'click');
28
- clickInteractions.forEach((interaction) => {
29
- executeInteraction({ interaction, ref, createdObject });
30
- });
31
- onObjectClick && onObjectClick(createdObject, ref, event);
32
- };
33
- return (_jsxs(Physics, { gravity: physicsSettings.gravity, paused: !physicsSettings.enabled, debug: physicsSettings.debug, children: [_jsx(LightsManager, { lights: lighting, selectedLight: selectedLight }), _jsx(EnvironmentManager, { hdrSettings: hdr, timeSettings: timeSettings, visible: true, sunSystemVisible: sunSystem.visible, sunSize: sunSystem.sunSize, moonSize: sunSystem.moonSize, sunIntensity: sunSystem.intensity, castShadow: sunSystem.castShadow, shadowMapSize: sunSystem.shadowMapSize, starsSettings: starsSettings, skyControllerSettings: sky.visible && !sunSystem.visible ? sky : undefined, cloudsSettings: clouds, cloudsMaterialSettings: clouds.materialSettings, rainSettings: rainSettings, fogSettings: fogSettings }), _jsx(CameraController, { settings: cameraSettings }), _jsx(Ocean, { settings: ocean }), _jsx(ObjectsRenderer, { cameraSettings: cameraSettings, generalObjectSettings: generalObjectSettings, createdObjects: objects, onObjectsReady: onObjectsReady, handleObjectClick: handleObjectClick }), _jsx(OrbitControls, { makeDefault: true, enabled: controls.enabled, target: new Vector3(...controls.target), enablePan: controls.enablePan, enableRotate: controls.enableRotate, autoRotate: controls.autoRotate, autoRotateSpeed: controls.autoRotateSpeed, zoomSpeed: controls.zoomSpeed, panSpeed: controls.panSpeed, rotateSpeed: controls.rotateSpeed, minDistance: controls.minDistance, maxDistance: controls.maxDistance, minPolarAngle: controls.minPolarAngle ? controls.minPolarAngle : -Infinity, maxPolarAngle: controls.maxPolarAngle ? controls.maxPolarAngle : Infinity, minAzimuthAngle: controls.minAzimuthAngle ? controls.minAzimuthAngle : -Infinity, maxAzimuthAngle: controls.maxAzimuthAngle ? controls.maxAzimuthAngle : Infinity })] }));
7
+ return (_jsxs(Physics, { gravity: physicsSettings.gravity, paused: !physicsSettings.enabled, debug: physicsSettings.debug, children: [children, _jsx(OrbitControls, { makeDefault: true, enabled: controls.enabled, target: new Vector3(...controls.target), enablePan: controls.enablePan, enableRotate: controls.enableRotate, autoRotate: controls.autoRotate, autoRotateSpeed: controls.autoRotateSpeed, zoomSpeed: controls.zoomSpeed, panSpeed: controls.panSpeed, rotateSpeed: controls.rotateSpeed, minDistance: controls.minDistance, maxDistance: controls.maxDistance, minPolarAngle: controls.minPolarAngle ? controls.minPolarAngle : -Infinity, maxPolarAngle: controls.maxPolarAngle ? controls.maxPolarAngle : Infinity, minAzimuthAngle: controls.minAzimuthAngle ? controls.minAzimuthAngle : -Infinity, maxAzimuthAngle: controls.maxAzimuthAngle ? controls.maxAzimuthAngle : Infinity })] }));
34
8
  };
35
9
  export default ProductionScene;
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectLoader.d.ts","sourceRoot":"","sources":["../../src/components/ProjectLoader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,OAAQ,EAAE,KAAK,qBAAqB,EAAkB,KAAK,WAAW,EAA2C,MAAM,wBAAwB,CAAC;AAIhJ,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,KAAK,YAAY,GAAG;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IACtG,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvE,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IAChD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IACvD,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;CACnC,CAAC;AAEF,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAyFzC,CAAC;AAEF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"ProjectLoader.d.ts","sourceRoot":"","sources":["../../src/components/ProjectLoader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,OAAQ,EAAE,KAAK,qBAAqB,EAAkB,KAAK,WAAW,EAA2C,MAAM,wBAAwB,CAAC;AAIhJ,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAMrD,KAAK,YAAY,GAAG;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IACtG,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvE,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IAChD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IACvD,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;CACnC,CAAC;AAEF,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAiHzC,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -8,6 +8,9 @@ import { loadAssets } from "@ntalmagor/3drize-core";
8
8
  import { buildQueryString } from "@ntalmagor/3drize-core";
9
9
  import useMeshController from '../hooks/useMeshController.js';
10
10
  import LoadingIndicator from "./LoadingIndicator.js";
11
+ // import type { HtmlElement } from "~/types/uiController";
12
+ const PROJECT_LOADER_SOURCE = 'projectLoader';
13
+ const PROJECT_LOADER_DEBUG_PREFIX = '[ProjectLoaderDebug]';
11
14
  const ProjectLoader = ({ projectId, onObjectClick, onObjectHover, onElementClick, onElementHover, onSceneInitialized }) => {
12
15
  const [project, setProject] = useState(null);
13
16
  const meshController = useMeshController();
@@ -25,13 +28,26 @@ const ProjectLoader = ({ projectId, onObjectClick, onObjectHover, onElementClick
25
28
  const loadProject = async (projectId, queryParams) => {
26
29
  try {
27
30
  const queryString = buildQueryString(queryParams);
28
- const url = `${dataCenterServer}projects/${projectId}${queryString ? `?${queryString}` : ''}`;
31
+ const searchParams = new URLSearchParams(queryString);
32
+ searchParams.set('source', PROJECT_LOADER_SOURCE);
33
+ const url = `${dataCenterServer}projects/${projectId}?${searchParams.toString()}`;
34
+ console.log(PROJECT_LOADER_DEBUG_PREFIX, 'Fetching project', {
35
+ projectId,
36
+ queryParams,
37
+ url,
38
+ });
29
39
  const response = await fetch(url, {
30
40
  method: "GET",
31
41
  headers: {
32
42
  "Content-Type": "application/json",
33
43
  },
34
44
  });
45
+ console.log(PROJECT_LOADER_DEBUG_PREFIX, 'Received project response', {
46
+ projectId,
47
+ status: response.status,
48
+ ok: response.ok,
49
+ url,
50
+ });
35
51
  if (!response.ok) {
36
52
  if (response.status === 404) {
37
53
  throw new Error("Project not found");
@@ -39,6 +55,11 @@ const ProjectLoader = ({ projectId, onObjectClick, onObjectHover, onElementClick
39
55
  throw new Error(`HTTP error! status: ${response.status}`);
40
56
  }
41
57
  const responseData = await response.json();
58
+ console.log(PROJECT_LOADER_DEBUG_PREFIX, 'Parsed project payload', {
59
+ projectId,
60
+ sceneObjectsCount: responseData.sceneObjects?.length || 0,
61
+ projectName: responseData.name,
62
+ });
42
63
  console.log("Loaded project:", responseData);
43
64
  const sceneObjects = responseData.sceneObjects || [];
44
65
  const modelObjects = sceneObjects.filter(obj => obj.type === 'model');
@@ -65,7 +86,10 @@ const ProjectLoader = ({ projectId, onObjectClick, onObjectHover, onElementClick
65
86
  setProject(responseData);
66
87
  }
67
88
  catch (error) {
68
- console.error("Error fetching project:", error);
89
+ console.error(PROJECT_LOADER_DEBUG_PREFIX, 'Error fetching project', {
90
+ projectId,
91
+ error,
92
+ });
69
93
  }
70
94
  };
71
95
  if (!project) {
@@ -1 +1 @@
1
- {"version":3,"file":"SceneBuilder.d.ts","sourceRoot":"","sources":["../../src/components/SceneBuilder.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,OAAO,KAAK,EAAa,iBAAiB,EAAe,MAAM,wBAAwB,CAAC;AAQxF,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAyK7C,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"SceneBuilder.d.ts","sourceRoot":"","sources":["../../src/components/SceneBuilder.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,OAAO,KAAK,EAEV,iBAAiB,EAIlB,MAAM,wBAAwB,CAAC;AAWhC,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA0K7C,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -1,14 +1,16 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from "react";
3
3
  import { Canvas } from "@react-three/fiber";
4
- // import type { SceneBuilderProps } from "~/types/types";
5
4
  import useMeshController from "../hooks/useMeshController.js";
6
5
  import { loadAssets } from "@ntalmagor/3drize-core";
7
6
  import { NoToneMapping } from "three";
8
7
  import ProductionScene from "./ProductionScene.js";
9
- // import UiController from "./UiController";
10
- // import type { HtmlElement } from "~/types/uiController";
11
- const SceneBuilder = ({ project, width = "100%", height = "100vh", style = {}, className = '', onSceneInitialized, onUiElementClick, onObjectClick, }) => {
8
+ import LightsManager from "./LightsManager.js";
9
+ import EnvironmentManager from "./EnvironmentManager.js";
10
+ import CameraController from "./CameraController.js";
11
+ import Ocean from "./Ocean.js";
12
+ import ObjectsRenderer from "./ObjectsRenderer.js";
13
+ const SceneBuilder = ({ project, width = "100%", height = "100vh", style = {}, className = "", onSceneInitialized, onUiElementClick, onObjectClick, }) => {
12
14
  const sceneSettings = (project.sceneSettingsData || {});
13
15
  const meshController = useMeshController();
14
16
  const [isThreeJsMounted, setIsThreeJsMounted] = useState(false);
@@ -45,13 +47,13 @@ const SceneBuilder = ({ project, width = "100%", height = "100vh", style = {}, c
45
47
  minAzimuthAngle: -Infinity,
46
48
  maxAzimuthAngle: Infinity,
47
49
  };
48
- const { shadows, antialias, dpr, gl, backgroundColor, } = sceneCanvas;
49
- const { position, orientation, fov, near, far, } = camera;
50
+ const { shadows, antialias, dpr, gl, backgroundColor } = sceneCanvas;
51
+ const { position, orientation, fov, near, far } = camera;
50
52
  const containerStyle = {
51
53
  width,
52
54
  height,
53
- position: 'relative',
54
- overflow: 'hidden',
55
+ position: "relative",
56
+ overflow: "hidden",
55
57
  ...style,
56
58
  };
57
59
  useEffect(() => {
@@ -86,7 +88,7 @@ const SceneBuilder = ({ project, width = "100%", height = "100vh", style = {}, c
86
88
  }, shadows: shadows, dpr: dpr, gl: {
87
89
  antialias,
88
90
  alpha: true,
89
- powerPreference: 'high-performance',
91
+ powerPreference: "high-performance",
90
92
  ...gl,
91
93
  }, camera: {
92
94
  fov,
@@ -100,6 +102,6 @@ const SceneBuilder = ({ project, width = "100%", height = "100vh", style = {}, c
100
102
  if (onSceneInitialized) {
101
103
  onSceneInitialized();
102
104
  }
103
- }, children: _jsx(ProductionScene, { device: "desktop", onObjectsReady: undefined, gridSettings: environment.grid, hdr: environment.hdr, physicsSettings: physicsSettings, generalObjectSettings: generalObjectSettings, ocean: environment.ocean, cameraSettings: camera, selectedLight: null, objects: sceneObjects, lighting: project.lights || [], controls: controls, geometry: project.settings?.materialCreator?.geometry || null, structure: project.settings?.structure || null, sky: environment.sky, timeSettings: timeSettings, starsSettings: environment.stars, clouds: environment.clouds, rainSettings: environment.rain, fogSettings: environment.fog, onObjectClick: onObjectClick, animationSequences: animationSequences }) }) }));
105
+ }, children: _jsxs(ProductionScene, { physicsSettings: physicsSettings, controls: controls, children: [_jsx(LightsManager, { lights: project.lights || [] }), _jsx(EnvironmentManager, { hdrSettings: environment.hdr, timeSettings: timeSettings, visible: true, sunSystemVisible: environment.sky.sunSystem.visible, sunSize: environment.sky.sunSystem.sunSize, moonSize: environment.sky.sunSystem.moonSize, sunIntensity: environment.sky.sunSystem.intensity, castShadow: environment.sky.sunSystem.castShadow, shadowMapSize: environment.sky.sunSystem.shadowMapSize, starsSettings: environment.stars, skyControllerSettings: environment.sky.visible && !environment.sky.sunSystem.visible ? environment.sky : undefined, cloudsSettings: environment.clouds, cloudsMaterialSettings: environment.clouds.materialSettings, rainSettings: environment.rain, fogSettings: environment.fog }), _jsx(CameraController, { settings: camera }), _jsx(Ocean, { settings: environment.ocean }), _jsx(ObjectsRenderer, { cameraSettings: camera, generalObjectSettings: generalObjectSettings, createdObjects: sceneObjects, onObjectsReady: undefined, sequences: animationSequences, handleObjectClick: onObjectClick ? (object, ref, event) => onObjectClick(object, ref, event) : undefined })] }) }) }));
104
106
  };
105
107
  export default SceneBuilder;
@@ -1,2 +1,2 @@
1
- export declare const dataCenterServer = "https://3d-rise.com/api/data/";
1
+ export declare const dataCenterServer: string;
2
2
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,kCAAkC,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,gBAAgB,QAEG,CAAC"}
package/dist/constants.js CHANGED
@@ -1 +1,7 @@
1
- export const dataCenterServer = 'https://3d-rise.com/api/data/';
1
+ const LOCAL_DATA_CENTER_SERVER = 'http://localhost:3001/api/data/';
2
+ const PRODUCTION_DATA_CENTER_SERVER = 'https://3d-rise.com/api/data/';
3
+ const isLocalHostRuntime = typeof window !== 'undefined' &&
4
+ (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1');
5
+ export const dataCenterServer = isLocalHostRuntime
6
+ ? LOCAL_DATA_CENTER_SERVER
7
+ : PRODUCTION_DATA_CENTER_SERVER;
@@ -1 +1 @@
1
- {"version":3,"file":"useAnimationEvents.d.ts","sourceRoot":"","sources":["../../src/hooks/useAnimationEvents.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEhF,UAAU,sBAAsB;IAC9B,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,aAAa,CAAC,EAAI,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,WAAW,CAAC,EAAM,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,SAAS,CAAC,EAAQ,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAED,eAAO,MAAM,kBAAkB,GAAI,UAAU,sBAAsB,SA0BlE,CAAC"}
1
+ {"version":3,"file":"useAnimationEvents.d.ts","sourceRoot":"","sources":["../../src/hooks/useAnimationEvents.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAUhF,UAAU,sBAAsB;IAC9B,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,aAAa,CAAC,EAAI,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,WAAW,CAAC,EAAM,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,SAAS,CAAC,EAAQ,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAED,eAAO,MAAM,kBAAkB,GAAI,UAAU,sBAAsB,SA0ClE,CAAC"}
@@ -1,10 +1,30 @@
1
1
  import { useEffect, useRef } from 'react';
2
2
  import { AnimationsManager } from '@ntalmagor/3drize-core';
3
+ const DEBUG_ANIMATION_EVENTS = false;
4
+ const debugLog = (...args) => {
5
+ if (DEBUG_ANIMATION_EVENTS) {
6
+ console.log('[useAnimationEvents]', ...args);
7
+ }
8
+ };
3
9
  export const useAnimationEvents = (handlers) => {
4
10
  const ref = useRef(handlers);
5
11
  ref.current = handlers;
6
12
  useEffect(() => {
7
- const wrap = (key) => (event) => ref.current[key]?.(event);
13
+ debugLog('subscribing', {
14
+ sequenceStart: !!handlers.onSequenceStart,
15
+ sequenceEnd: !!handlers.onSequenceEnd,
16
+ stepStart: !!handlers.onStepStart,
17
+ stepEnd: !!handlers.onStepEnd,
18
+ });
19
+ const wrap = (key) => (event) => {
20
+ debugLog('event received', {
21
+ key,
22
+ sequenceId: event.sequenceId,
23
+ stepIndex: event.stepIndex,
24
+ transitionCount: event.step?.transitions?.length ?? 0,
25
+ });
26
+ ref.current[key]?.(event);
27
+ };
8
28
  const ss = wrap('onSequenceStart');
9
29
  const se = wrap('onSequenceEnd');
10
30
  const ts = wrap('onStepStart');
@@ -18,6 +38,7 @@ export const useAnimationEvents = (handlers) => {
18
38
  if (handlers.onStepEnd)
19
39
  AnimationsManager.on('stepEnd', te);
20
40
  return () => {
41
+ debugLog('unsubscribing');
21
42
  AnimationsManager.off('sequenceStart', ss);
22
43
  AnimationsManager.off('sequenceEnd', se);
23
44
  AnimationsManager.off('stepStart', ts);
@@ -1 +1 @@
1
- {"version":3,"file":"useObjectAnimation.d.ts","sourceRoot":"","sources":["../../src/hooks/useObjectAnimation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,KAAK,qBAAqB,EAAY,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAwB,KAAK,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAC/F,OAAO,EAAyB,KAAK,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAGlG,UAAU,yBAAyB;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,wBAAyB,SAAQ,0BAA0B,EAAE,2BAA2B;CAAG;AAErG,eAAO,MAAM,kBAAkB,GAC7B,gBAAgB,qBAAqB,GAAG,IAAI,EAC5C,iBAAiB,OAAO,EACxB,UAAS,yBAA8B,EACvC,MAAM,QAAQ,KACb,wBAAwB,GAAG,IAQ7B,CAAC"}
1
+ {"version":3,"file":"useObjectAnimation.d.ts","sourceRoot":"","sources":["../../src/hooks/useObjectAnimation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,KAAK,qBAAqB,EAAY,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAwB,KAAK,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAC/F,OAAO,EAAyB,KAAK,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAYlG,UAAU,yBAAyB;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,wBAAyB,SAAQ,0BAA0B,EAAE,2BAA2B;CAAG;AAErG,eAAO,MAAM,kBAAkB,GAC7B,gBAAgB,qBAAqB,GAAG,IAAI,EAC5C,iBAAiB,OAAO,EACxB,UAAS,yBAA8B,EACvC,MAAM,QAAQ,KACb,wBAAwB,GAAG,IAiB7B,CAAC"}
@@ -1,11 +1,27 @@
1
1
  import { findById } from '@ntalmagor/3drize-core';
2
2
  import { useContinuousEffects } from "./useContinuousEffects.js";
3
3
  import { useInteractionEffects } from "./useInteractionEffects.js";
4
+ import { useSequenceAnimation } from "./useSequenceAnimation.js";
5
+ const DEBUG_OBJECT_ANIMATION = false;
6
+ const debugLog = (...args) => {
7
+ if (DEBUG_OBJECT_ANIMATION) {
8
+ console.log('[useObjectAnimation]', ...args);
9
+ }
10
+ };
4
11
  export const useObjectAnimation = (objectSettings, animateMaterial, options = {}, ref) => {
5
12
  const { enabled = true, hovered = false } = options;
6
13
  const objectRef = ref || findById(objectSettings?.id);
14
+ debugLog('hook run', {
15
+ objectId: objectSettings?.id,
16
+ hasRefArg: !!ref,
17
+ resolvedObject: objectRef ? { name: objectRef.name, id: objectRef.userData?.id } : null,
18
+ enabled,
19
+ hovered,
20
+ animateMaterial,
21
+ });
7
22
  // console.log(objectRef)
8
23
  const continuousResult = useContinuousEffects(objectSettings, { enabled, animateMaterial, hovered }, objectRef);
9
24
  const interactionResult = useInteractionEffects(objectSettings, { enabled, animateMaterial }, objectRef);
25
+ useSequenceAnimation(objectSettings?.id, objectRef);
10
26
  return { ...continuousResult, ...interactionResult };
11
27
  };
@@ -0,0 +1,14 @@
1
+ import type { Object3D } from 'three';
2
+ /**
3
+ * useSequenceAnimation
4
+ *
5
+ * Subscribes to AnimationsManager step events and, for each frame while a step
6
+ * is active, interpolates both transform AND material properties on the given
7
+ * object. Path-based transitions are delegated to usePathAnimation.
8
+ *
9
+ * Designed to be called inside useObjectAnimation so that AnimatedObject stays
10
+ * a thin group wrapper.
11
+ */
12
+ export declare const useSequenceAnimation: (objectId: string | undefined, objectRef: Object3D | null | undefined) => void;
13
+ export default useSequenceAnimation;
14
+ //# sourceMappingURL=useSequenceAnimation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSequenceAnimation.d.ts","sourceRoot":"","sources":["../../src/hooks/useSequenceAnimation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AA0HtC;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,GAC/B,UAAU,MAAM,GAAG,SAAS,EAC5B,WAAW,QAAQ,GAAG,IAAI,GAAG,SAAS,SAuLvC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
@@ -0,0 +1,258 @@
1
+ import { useRef } from 'react';
2
+ import { useFrame } from '@react-three/fiber';
3
+ import { AnimationsManager, applySingleProperty, findById } from '@ntalmagor/3drize-core';
4
+ import { useAnimationEvents } from './useAnimationEvents.js';
5
+ import { usePathAnimation } from './usePathAnimation.js';
6
+ const DEBUG_SEQUENCE_ANIMATION = true;
7
+ const debugLog = (...args) => {
8
+ if (DEBUG_SEQUENCE_ANIMATION) {
9
+ console.log('[useSequenceAnimation]', ...args);
10
+ }
11
+ };
12
+ // ─────────────────────────────────────────────────────────────────────────────
13
+ // Helpers
14
+ // ─────────────────────────────────────────────────────────────────────────────
15
+ const TRANSFORM_KEYS = new Set(['position', 'rotation', 'scale', 'visible']);
16
+ function lerp(a, b, t) {
17
+ return a + (b - a) * t;
18
+ }
19
+ function lerpVec3(a, b, t) {
20
+ return [lerp(a[0], b[0], t), lerp(a[1], b[1], t), lerp(a[2], b[2], t)];
21
+ }
22
+ /** Parse a hex color string to [r, g, b] 0-1 */
23
+ function hexToRgb(hex) {
24
+ const h = hex.replace('#', '');
25
+ const n = parseInt(h.length === 3 ? h.split('').map(c => c + c).join('') : h, 16);
26
+ return [(n >> 16) / 255, ((n >> 8) & 0xff) / 255, (n & 0xff) / 255];
27
+ }
28
+ /** Lerp two hex color strings, returns a hex string */
29
+ function lerpColor(a, b, t) {
30
+ if (typeof a !== 'string' || typeof b !== 'string')
31
+ return b;
32
+ const [ar, ag, ab] = hexToRgb(a);
33
+ const [br, bg, bb] = hexToRgb(b);
34
+ const r = Math.round(lerp(ar, br, t) * 255);
35
+ const g = Math.round(lerp(ag, bg, t) * 255);
36
+ const bl = Math.round(lerp(ab, bb, t) * 255);
37
+ return `#${[r, g, bl].map(v => v.toString(16).padStart(2, '0')).join('')}`;
38
+ }
39
+ function lerpValue(a, b, t) {
40
+ if (Array.isArray(a) && Array.isArray(b)) {
41
+ return a.map((v, i) => typeof v === 'number' ? lerp(v, b[i] ?? v, t) : b[i]);
42
+ }
43
+ if (typeof a === 'number' && typeof b === 'number')
44
+ return lerp(a, b, t);
45
+ if (typeof a === 'string' && typeof b === 'string' && a.startsWith('#') && b.startsWith('#')) {
46
+ return lerpColor(a, b, t);
47
+ }
48
+ // Non-lerp-able — snap at t=1
49
+ return t >= 1 ? b : a;
50
+ }
51
+ /** Get material-related properties from a transition properties record */
52
+ function extractMaterialProps(props) {
53
+ if (!props)
54
+ return {};
55
+ return Object.fromEntries(Object.entries(props).filter(([k]) => !TRANSFORM_KEYS.has(k)));
56
+ }
57
+ /** Apply a material property to all materials on an object */
58
+ function applyMaterialProp(object, key, value) {
59
+ let appliedCount = 0;
60
+ object.traverse((child) => {
61
+ if (!child.material)
62
+ return;
63
+ const mats = Array.isArray(child.material) ? child.material : [child.material];
64
+ for (const mat of mats) {
65
+ if (!(key in mat) && !mat.uniforms?.[key])
66
+ continue;
67
+ if (key === 'opacity' && typeof value === 'number') {
68
+ // Opacity has no visible effect on many materials unless transparency is enabled.
69
+ if ('transparent' in mat) {
70
+ mat.transparent = value < 1;
71
+ }
72
+ }
73
+ applySingleProperty(mat, key, value);
74
+ appliedCount += 1;
75
+ }
76
+ });
77
+ debugLog('material property applied', { key, value, appliedCount, objectName: object.name, objectId: object.userData?.id });
78
+ }
79
+ // ─────────────────────────────────────────────────────────────────────────────
80
+ // Hook
81
+ // ─────────────────────────────────────────────────────────────────────────────
82
+ /**
83
+ * useSequenceAnimation
84
+ *
85
+ * Subscribes to AnimationsManager step events and, for each frame while a step
86
+ * is active, interpolates both transform AND material properties on the given
87
+ * object. Path-based transitions are delegated to usePathAnimation.
88
+ *
89
+ * Designed to be called inside useObjectAnimation so that AnimatedObject stays
90
+ * a thin group wrapper.
91
+ */
92
+ export const useSequenceAnimation = (objectId, objectRef) => {
93
+ const { startPathAnimation, updatePathAnimation, stopPathAnimation, isAnimating: isPathAnimating } = usePathAnimation();
94
+ const resolveObject = () => {
95
+ const resolved = objectRef ?? (objectId ? findById(objectId) : null);
96
+ return resolved;
97
+ };
98
+ // Active step state. Null = no sequence step currently animating.
99
+ const stepRef = useRef(null);
100
+ // Progress 0-1; flips to 1 when done so useFrame short-circuits
101
+ const progressRef = useRef(1);
102
+ // ── Event listener ──────────────────────────────────────────────────────────
103
+ useAnimationEvents({
104
+ onStepStart: (event) => {
105
+ if (!objectId || !event.step?.transitions) {
106
+ debugLog('stepStart ignored: missing objectId or transitions', {
107
+ objectId,
108
+ hasTransitions: !!event.step?.transitions,
109
+ sequenceId: event.sequenceId,
110
+ stepIndex: event.stepIndex,
111
+ });
112
+ return;
113
+ }
114
+ const resolvedObject = resolveObject();
115
+ debugLog('stepStart received', {
116
+ objectId,
117
+ sequenceId: event.sequenceId,
118
+ stepIndex: event.stepIndex,
119
+ transitionStates: event.step.transitions.map(t => t.state),
120
+ resolvedObject: resolvedObject ? {
121
+ name: resolvedObject.name,
122
+ id: resolvedObject.userData?.id,
123
+ } : null,
124
+ });
125
+ // Find the transition targeting this object
126
+ const transition = event.step.transitions.find(t => t.state === objectId);
127
+ if (!transition) {
128
+ debugLog('no matching transition for objectId', {
129
+ objectId,
130
+ availableStates: event.step.transitions.map(t => t.state),
131
+ });
132
+ return;
133
+ }
134
+ const d = event.step.duration || 1;
135
+ const ease = event.step.ease || 'linear';
136
+ const { properties, pathId = null } = transition;
137
+ debugLog('matched transition', {
138
+ objectId,
139
+ pathId,
140
+ duration: d,
141
+ ease,
142
+ fromKeys: Object.keys(properties.from || {}),
143
+ toKeys: Object.keys(properties.to || {}),
144
+ });
145
+ // Visibility shortcut
146
+ if (properties.to?.visible === false) {
147
+ if (resolvedObject)
148
+ resolvedObject.visible = false;
149
+ stepRef.current = null;
150
+ progressRef.current = 1;
151
+ return;
152
+ }
153
+ if (resolvedObject)
154
+ resolvedObject.visible = true;
155
+ // Snapshot current object transform as defaults
156
+ const cur = resolvedObject;
157
+ const curPos = cur
158
+ ? [cur.position.x, cur.position.y, cur.position.z]
159
+ : [0, 0, 0];
160
+ const curRot = cur
161
+ ? [cur.rotation.x, cur.rotation.y, cur.rotation.z]
162
+ : [0, 0, 0];
163
+ const curSca = cur
164
+ ? [cur.scale.x, cur.scale.y, cur.scale.z]
165
+ : [1, 1, 1];
166
+ const fp = properties.from;
167
+ const tp = properties.to;
168
+ stepRef.current = {
169
+ startTime: performance.now(),
170
+ duration: d,
171
+ ease,
172
+ fromPosition: (fp?.position ?? curPos),
173
+ toPosition: (tp?.position ?? curPos),
174
+ fromRotation: (fp?.rotation ?? curRot),
175
+ toRotation: (tp?.rotation ?? curRot),
176
+ fromScale: (fp?.scale ?? curSca),
177
+ toScale: (tp?.scale ?? curSca),
178
+ materialFrom: extractMaterialProps(fp),
179
+ materialTo: extractMaterialProps(tp),
180
+ visibilityOverride: null,
181
+ pathId,
182
+ };
183
+ progressRef.current = 0;
184
+ if (pathId) {
185
+ debugLog('starting path animation', { objectId, pathId, duration: d, ease });
186
+ startPathAnimation(pathId, d, { ease });
187
+ }
188
+ else {
189
+ stopPathAnimation();
190
+ }
191
+ },
192
+ onStepEnd: (event) => {
193
+ debugLog('stepEnd received', {
194
+ objectId,
195
+ sequenceId: event.sequenceId,
196
+ stepIndex: event.stepIndex,
197
+ });
198
+ // Let useFrame finish the last frame at p=1 naturally; just clear step
199
+ // after a microtask so the final interpolated position is applied.
200
+ Promise.resolve().then(() => {
201
+ stepRef.current = null;
202
+ progressRef.current = 1;
203
+ });
204
+ },
205
+ });
206
+ // ── Per-frame interpolation ─────────────────────────────────────────────────
207
+ useFrame((_state, delta) => {
208
+ const resolvedObject = resolveObject();
209
+ if (progressRef.current >= 1 || !stepRef.current || !resolvedObject)
210
+ return;
211
+ const step = stepRef.current;
212
+ // Time-based progress drives property interpolation regardless of transform mode.
213
+ const p = AnimationsManager.getProgressFromTime(step.startTime, step.duration, step.ease);
214
+ progressRef.current = p;
215
+ // Path-based: delegate to usePathAnimation
216
+ if (step.pathId) {
217
+ const still = updatePathAnimation(delta, resolvedObject);
218
+ if (!still) {
219
+ progressRef.current = 1;
220
+ stepRef.current = null;
221
+ }
222
+ // Keep scale interpolation active while path controls position/rotation.
223
+ const sca = lerpVec3(step.fromScale, step.toScale, p);
224
+ resolvedObject.scale.set(...sca);
225
+ }
226
+ else {
227
+ // — Transform —
228
+ const pos = lerpVec3(step.fromPosition, step.toPosition, p);
229
+ const rot = lerpVec3(step.fromRotation, step.toRotation, p);
230
+ const sca = lerpVec3(step.fromScale, step.toScale, p);
231
+ resolvedObject.position.set(...pos);
232
+ resolvedObject.rotation.set(...rot);
233
+ resolvedObject.scale.set(...sca);
234
+ }
235
+ if (p === 0 || p >= 0.99) {
236
+ debugLog('frame progress', {
237
+ objectId,
238
+ progress: p,
239
+ materialKeys: Object.keys(step.materialTo),
240
+ pathId: step.pathId,
241
+ });
242
+ }
243
+ // — Material properties —
244
+ for (const key of Object.keys(step.materialTo)) {
245
+ const fromVal = step.materialFrom[key];
246
+ const toVal = step.materialTo[key];
247
+ if (fromVal === undefined && toVal === undefined)
248
+ continue;
249
+ const interpolated = lerpValue(fromVal ?? toVal, toVal, p);
250
+ applyMaterialProp(resolvedObject, key, interpolated);
251
+ }
252
+ if (p >= 1) {
253
+ progressRef.current = 1;
254
+ stepRef.current = null;
255
+ }
256
+ });
257
+ };
258
+ export default useSequenceAnimation;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ntalmagor/3drize-viewer",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",