@3driseai/3drise-viewer 0.1.24 → 0.1.26

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 (133) hide show
  1. package/dist/animationsV2/ClipPlayer.d.ts +13 -0
  2. package/dist/animationsV2/ClipPlayer.d.ts.map +1 -0
  3. package/dist/animationsV2/ClipPlayer.js +140 -0
  4. package/dist/animationsV2/ClipsRuntime.d.ts +111 -0
  5. package/dist/animationsV2/ClipsRuntime.d.ts.map +1 -0
  6. package/dist/animationsV2/ClipsRuntime.js +476 -0
  7. package/dist/animationsV2/appliers.d.ts +16 -0
  8. package/dist/animationsV2/appliers.d.ts.map +1 -0
  9. package/dist/animationsV2/appliers.js +204 -0
  10. package/dist/animationsV2/clipUtils.d.ts +33 -0
  11. package/dist/animationsV2/clipUtils.d.ts.map +1 -0
  12. package/dist/animationsV2/clipUtils.js +164 -0
  13. package/dist/animationsV2/elementSettings.d.ts +15 -0
  14. package/dist/animationsV2/elementSettings.d.ts.map +1 -0
  15. package/dist/animationsV2/elementSettings.js +16 -0
  16. package/dist/animationsV2/index.d.ts +16 -0
  17. package/dist/animationsV2/index.d.ts.map +1 -0
  18. package/dist/animationsV2/index.js +12 -0
  19. package/dist/animationsV2/nodeTracks.d.ts +13 -0
  20. package/dist/animationsV2/nodeTracks.d.ts.map +1 -0
  21. package/dist/animationsV2/nodeTracks.js +165 -0
  22. package/dist/animationsV2/normalize.d.ts +4 -0
  23. package/dist/animationsV2/normalize.d.ts.map +1 -0
  24. package/dist/animationsV2/normalize.js +49 -0
  25. package/dist/animationsV2/sequenceUtils.d.ts +57 -0
  26. package/dist/animationsV2/sequenceUtils.d.ts.map +1 -0
  27. package/dist/animationsV2/sequenceUtils.js +120 -0
  28. package/dist/animationsV2/types.d.ts +95 -0
  29. package/dist/animationsV2/types.d.ts.map +1 -0
  30. package/dist/animationsV2/types.js +8 -0
  31. package/dist/api/sceneHandle.d.ts +102 -0
  32. package/dist/api/sceneHandle.d.ts.map +1 -0
  33. package/dist/api/sceneHandle.js +237 -0
  34. package/dist/components/CameraController.d.ts.map +1 -1
  35. package/dist/components/CameraController.js +3 -44
  36. package/dist/components/Clouds.d.ts.map +1 -1
  37. package/dist/components/Clouds.js +0 -34
  38. package/dist/components/CreatedObject.d.ts.map +1 -1
  39. package/dist/components/CreatedObject.js +19 -1
  40. package/dist/components/EnvironmentManager.d.ts.map +1 -1
  41. package/dist/components/EnvironmentManager.js +6 -4
  42. package/dist/components/ObjectNode.d.ts.map +1 -1
  43. package/dist/components/ObjectNode.js +5 -1
  44. package/dist/components/ObjectsRenderer.d.ts +5 -1
  45. package/dist/components/ObjectsRenderer.d.ts.map +1 -1
  46. package/dist/components/ObjectsRenderer.js +24 -3
  47. package/dist/components/Ocean.d.ts.map +1 -1
  48. package/dist/components/Ocean.js +0 -63
  49. package/dist/components/ProjectLoader.d.ts +9 -3
  50. package/dist/components/ProjectLoader.d.ts.map +1 -1
  51. package/dist/components/ProjectLoader.js +5 -4
  52. package/dist/components/SceneBuilder.d.ts +9 -1
  53. package/dist/components/SceneBuilder.d.ts.map +1 -1
  54. package/dist/components/SceneBuilder.js +30 -5
  55. package/dist/components/SkyController.d.ts.map +1 -1
  56. package/dist/components/SkyController.js +0 -39
  57. package/dist/components/Stars.d.ts.map +1 -1
  58. package/dist/components/Stars.js +3 -46
  59. package/dist/components/terrain/TerrainSurface.d.ts.map +1 -1
  60. package/dist/components/terrain/TerrainSurface.js +0 -5
  61. package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts.map +1 -1
  62. package/dist/components/volumetricClouds/VolumetricCloudsPass.js +0 -6
  63. package/dist/hooks/index.d.ts +2 -2
  64. package/dist/hooks/index.d.ts.map +1 -1
  65. package/dist/hooks/index.js +2 -2
  66. package/dist/hooks/useInteraction.d.ts +7 -7
  67. package/dist/hooks/useInteraction.d.ts.map +1 -1
  68. package/dist/hooks/useInteraction.js +87 -233
  69. package/dist/hooks/useLightConfig.d.ts.map +1 -1
  70. package/dist/hooks/useLightConfig.js +7 -0
  71. package/dist/hooks/useLightLive.d.ts.map +1 -1
  72. package/dist/hooks/useLightLive.js +2 -0
  73. package/dist/hooks/useLightTargets.d.ts +7 -0
  74. package/dist/hooks/useLightTargets.d.ts.map +1 -0
  75. package/dist/hooks/useLightTargets.js +132 -0
  76. package/dist/hooks/useObjectAnimation.d.ts.map +1 -1
  77. package/dist/hooks/useObjectAnimation.js +0 -2
  78. package/dist/hooks/useOceanMaterial.d.ts.map +1 -1
  79. package/dist/hooks/useOceanMaterial.js +0 -5
  80. package/dist/hooks/useRuntimeSettings.d.ts +15 -0
  81. package/dist/hooks/useRuntimeSettings.d.ts.map +1 -0
  82. package/dist/hooks/useRuntimeSettings.js +22 -0
  83. package/dist/hooks/useSequenceAnimation.d.ts.map +1 -1
  84. package/dist/hooks/useSequenceAnimation.js +27 -9
  85. package/dist/index.d.ts +6 -1
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +5 -0
  88. package/dist/interactions/index.d.ts +3 -0
  89. package/dist/interactions/index.d.ts.map +1 -0
  90. package/dist/interactions/index.js +1 -0
  91. package/dist/interactions/runner.d.ts +9 -0
  92. package/dist/interactions/runner.d.ts.map +1 -0
  93. package/dist/interactions/runner.js +23 -0
  94. package/dist/operations/catalogue/displayImage.d.ts +3 -0
  95. package/dist/operations/catalogue/displayImage.d.ts.map +1 -0
  96. package/dist/operations/catalogue/displayImage.js +39 -0
  97. package/dist/operations/catalogue/fade.d.ts +3 -0
  98. package/dist/operations/catalogue/fade.d.ts.map +1 -0
  99. package/dist/operations/catalogue/fade.js +44 -0
  100. package/dist/operations/catalogue/focus.d.ts +3 -0
  101. package/dist/operations/catalogue/focus.d.ts.map +1 -0
  102. package/dist/operations/catalogue/focus.js +22 -0
  103. package/dist/operations/catalogue/glow.d.ts +3 -0
  104. package/dist/operations/catalogue/glow.d.ts.map +1 -0
  105. package/dist/operations/catalogue/glow.js +49 -0
  106. package/dist/operations/catalogue/materialFx.d.ts +6 -0
  107. package/dist/operations/catalogue/materialFx.d.ts.map +1 -0
  108. package/dist/operations/catalogue/materialFx.js +13 -0
  109. package/dist/operations/catalogue/moveToFront.d.ts +3 -0
  110. package/dist/operations/catalogue/moveToFront.d.ts.map +1 -0
  111. package/dist/operations/catalogue/moveToFront.js +25 -0
  112. package/dist/operations/catalogue/visibility.d.ts +3 -0
  113. package/dist/operations/catalogue/visibility.d.ts.map +1 -0
  114. package/dist/operations/catalogue/visibility.js +24 -0
  115. package/dist/operations/catalogue/zoom.d.ts +3 -0
  116. package/dist/operations/catalogue/zoom.d.ts.map +1 -0
  117. package/dist/operations/catalogue/zoom.js +32 -0
  118. package/dist/operations/index.d.ts +5 -0
  119. package/dist/operations/index.d.ts.map +1 -0
  120. package/dist/operations/index.js +4 -0
  121. package/dist/operations/registry.d.ts +11 -0
  122. package/dist/operations/registry.d.ts.map +1 -0
  123. package/dist/operations/registry.js +21 -0
  124. package/dist/operations/runtime.d.ts +22 -0
  125. package/dist/operations/runtime.d.ts.map +1 -0
  126. package/dist/operations/runtime.js +161 -0
  127. package/dist/operations/types.d.ts +96 -0
  128. package/dist/operations/types.d.ts.map +1 -0
  129. package/dist/operations/types.js +3 -0
  130. package/dist/operations/useOperationsRuntime.d.ts +3 -0
  131. package/dist/operations/useOperationsRuntime.d.ts.map +1 -0
  132. package/dist/operations/useOperationsRuntime.js +31 -0
  133. package/package.json +2 -2
@@ -0,0 +1,237 @@
1
+ // =============================================================================
2
+ // SceneHandle — control a loaded 3drise project from outside it
3
+ // =============================================================================
4
+ //
5
+ // What a developer extending a project gets from <ProjectLoader ref={…} /> or
6
+ // onSceneReady(handle): trigger the project's actions, clips and sequences from
7
+ // their own UI, and hear when they run.
8
+ //
9
+ // scene.current?.actions.toggle('open-door');
10
+ // scene.current?.clips.play('spin'); // one clip, its own loop / yoyo / end
11
+ // scene.current?.sequences.play('intro', { speed: 1.5 });
12
+ // const off = scene.current?.on('animationEnd', (e) => console.log(e.kind, e.key));
13
+ //
14
+ // Addressing (`ref`): the item's `key` first (stable across renames and project
15
+ // copies — prefer it), then its id, then its exact name. An ambiguous name warns
16
+ // and uses the first match. Clip and sequence keys are separate namespaces.
17
+ //
18
+ // This is a thin layer: object clicks go through the same SceneActions /
19
+ // ClipsRuntime calls, so a button and a click behave identically.
20
+ //
21
+ import { SceneActions } from '@3driseai/3drise-core';
22
+ import ClipsRuntime from '../animationsV2/ClipsRuntime.js';
23
+ import { clipMap, resolveSequence } from '../animationsV2/sequenceUtils.js';
24
+ function resolve(items, ref, kind) {
25
+ if (!ref)
26
+ return undefined;
27
+ const byKey = items.find(i => i.key === ref);
28
+ if (byKey)
29
+ return byKey;
30
+ const byId = items.find(i => i.id === ref);
31
+ if (byId)
32
+ return byId;
33
+ const byName = items.filter(i => i.name === ref);
34
+ if (byName.length > 1) {
35
+ console.warn(`[3drise] ${byName.length} ${kind}s are named "${ref}"; using the first. Address it by its key instead.`);
36
+ }
37
+ if (byName.length === 0) {
38
+ console.warn(`[3drise] No ${kind} "${ref}" in this project. Known: ${items.map(i => i.key || i.name).join(', ') || 'none'}`);
39
+ }
40
+ return byName[0];
41
+ }
42
+ const clamp01 = (n) => Math.min(1, Math.max(0, Number.isFinite(n) ? n : 0));
43
+ /**
44
+ * Build a handle over one project's actions, clips and sequences. `getSource` is
45
+ * read on every call, so the handle stays valid if the project data is replaced.
46
+ */
47
+ export function createSceneHandle(getSource) {
48
+ const actions = () => getSource().actions ?? [];
49
+ const clips = () => getSource().clips ?? [];
50
+ const sequences = () => getSource().sequences ?? [];
51
+ const clipsById = () => clipMap(clips());
52
+ const findAction = (ref) => resolve(actions(), ref, 'action');
53
+ const findClip = (ref) => resolve(clips(), ref, 'clip');
54
+ const findSequence = (ref) => resolve(sequences(), ref, 'sequence');
55
+ const sequenceDuration = (s) => resolveSequence(s, clipsById()).duration;
56
+ const clipControls = {
57
+ list: () => clips().map(c => ({
58
+ id: c.id, key: c.key, name: c.name, description: c.description,
59
+ duration: c.duration, loop: c.loop, yoyo: c.yoyo, endMode: c.endMode,
60
+ playing: ClipsRuntime.isPlaying(c.id),
61
+ })),
62
+ play(ref, options = {}) {
63
+ const c = findClip(ref);
64
+ if (!c)
65
+ return false;
66
+ ClipsRuntime.play(c, {
67
+ speed: options.speed,
68
+ reverse: options.reverse,
69
+ from: options.from !== undefined ? clamp01(options.from) * c.duration : undefined,
70
+ });
71
+ return true;
72
+ },
73
+ pause(ref) {
74
+ const c = findClip(ref);
75
+ if (!c)
76
+ return false;
77
+ ClipsRuntime.pause(c.id);
78
+ return true;
79
+ },
80
+ resume(ref) {
81
+ const c = findClip(ref);
82
+ if (!c)
83
+ return false;
84
+ ClipsRuntime.resume(c.id);
85
+ return true;
86
+ },
87
+ stop(ref) {
88
+ const c = findClip(ref);
89
+ if (!c)
90
+ return false;
91
+ ClipsRuntime.stop(c.id);
92
+ return true;
93
+ },
94
+ seek(ref, progress) {
95
+ const c = findClip(ref);
96
+ if (!c)
97
+ return false;
98
+ ClipsRuntime.pose(c, clamp01(progress) * c.duration);
99
+ return true;
100
+ },
101
+ isPlaying(ref) {
102
+ const c = findClip(ref);
103
+ return c ? ClipsRuntime.isPlaying(c.id) : false;
104
+ },
105
+ };
106
+ const sequenceControls = {
107
+ list: () => sequences().map(s => ({
108
+ id: s.id, key: s.key, name: s.name, description: s.description,
109
+ duration: sequenceDuration(s), steps: s.steps.length,
110
+ loop: s.loop, yoyo: s.yoyo, reverse: s.reverse, endMode: s.endMode,
111
+ driver: s.driver, autoplay: s.autoplay,
112
+ playing: ClipsRuntime.isSequencePlaying(s.id),
113
+ })),
114
+ play(ref, options = {}) {
115
+ const s = findSequence(ref);
116
+ if (!s)
117
+ return false;
118
+ ClipsRuntime.playSequence(s, clipsById(), {
119
+ speed: options.speed,
120
+ reverse: options.reverse,
121
+ from: options.from !== undefined ? clamp01(options.from) * sequenceDuration(s) : undefined,
122
+ });
123
+ return true;
124
+ },
125
+ pause(ref) {
126
+ const s = findSequence(ref);
127
+ if (!s)
128
+ return false;
129
+ ClipsRuntime.pauseSequence(s.id);
130
+ return true;
131
+ },
132
+ resume(ref) {
133
+ const s = findSequence(ref);
134
+ if (!s)
135
+ return false;
136
+ ClipsRuntime.resumeSequence(s.id);
137
+ return true;
138
+ },
139
+ stop(ref) {
140
+ const s = findSequence(ref);
141
+ if (!s)
142
+ return false;
143
+ ClipsRuntime.stopSequence(s.id);
144
+ return true;
145
+ },
146
+ seek(ref, progress) {
147
+ const s = findSequence(ref);
148
+ if (!s)
149
+ return false;
150
+ const lookup = clipsById();
151
+ ClipsRuntime.poseSequence(s, lookup, clamp01(progress) * resolveSequence(s, lookup).duration);
152
+ return true;
153
+ },
154
+ isPlaying(ref) {
155
+ const s = findSequence(ref);
156
+ return s ? ClipsRuntime.isSequencePlaying(s.id) : false;
157
+ },
158
+ setProgress(ref, progress) {
159
+ const s = findSequence(ref);
160
+ if (!s)
161
+ return false;
162
+ if (ClipsRuntime.isSequenceActive(s.id))
163
+ return ClipsRuntime.setSequenceProgress(s.id, progress);
164
+ const lookup = clipsById();
165
+ const total = resolveSequence(s, lookup).duration;
166
+ const p = clamp01(progress);
167
+ ClipsRuntime.poseSequence(s, lookup, (s.reverse ? 1 - p : p) * total);
168
+ return true;
169
+ },
170
+ getProgress(ref) {
171
+ const s = findSequence(ref);
172
+ return s ? ClipsRuntime.getSequenceProgress(s.id) : 0;
173
+ },
174
+ };
175
+ return {
176
+ actions: {
177
+ list: () => actions().map(a => ({
178
+ id: a.id,
179
+ key: a.key,
180
+ name: a.name,
181
+ description: a.description,
182
+ applied: SceneActions.isActionApplied(a.id),
183
+ })),
184
+ apply(ref) {
185
+ const a = findAction(ref);
186
+ if (!a)
187
+ return false;
188
+ SceneActions.applyAction(a);
189
+ return true;
190
+ },
191
+ revert(ref) {
192
+ const a = findAction(ref);
193
+ if (!a)
194
+ return false;
195
+ SceneActions.revertAction(a);
196
+ return true;
197
+ },
198
+ toggle(ref) {
199
+ const a = findAction(ref);
200
+ return a ? SceneActions.toggleAction(a) : false;
201
+ },
202
+ isApplied(ref) {
203
+ const a = findAction(ref);
204
+ return a ? SceneActions.isActionApplied(a.id) : false;
205
+ },
206
+ reset() {
207
+ // Only this project's actions — another scene on the page keeps its state.
208
+ for (const a of actions())
209
+ SceneActions.revertAction(a.id);
210
+ },
211
+ },
212
+ clips: clipControls,
213
+ sequences: sequenceControls,
214
+ on(type, listener) {
215
+ if (type === 'actionApplied' || type === 'actionReverted') {
216
+ return SceneActions.onEvent((e) => {
217
+ if (e.type === 'reset')
218
+ return;
219
+ if ((type === 'actionApplied') !== (e.type === 'applied'))
220
+ return;
221
+ const a = actions().find(x => x.id === e.actionId);
222
+ if (a)
223
+ listener({ type, kind: 'action', id: a.id, key: a.key, name: a.name });
224
+ });
225
+ }
226
+ const wanted = type === 'animationStart' ? 'start' : type === 'animationEnd' ? 'end' : 'loop';
227
+ return ClipsRuntime.on((e) => {
228
+ if (e.type !== wanted)
229
+ return;
230
+ // Only this project's items — another scene on the page shares the runtime.
231
+ const item = e.kind === 'clip' ? clips().find(c => c.id === e.id) : sequences().find(s => s.id === e.id);
232
+ if (item)
233
+ listener({ type, kind: e.kind, id: item.id, key: item.key, name: item.name });
234
+ });
235
+ },
236
+ };
237
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"CameraController.d.ts","sourceRoot":"","sources":["../../src/components/CameraController.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAQ7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,UAAU,qBAAsB,SAAQ,gBAAgB;IACpD,QAAQ,EAAE,WAAW,CAAC;IACtB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;CAC/C;AAGD,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAwJ5D,CAAC;AACF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"CameraController.d.ts","sourceRoot":"","sources":["../../src/components/CameraController.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAQ7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,UAAU,qBAAsB,SAAQ,gBAAgB;IACpD,QAAQ,EAAE,WAAW,CAAC;IACtB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;CAC/C;AAGD,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA+G5D,CAAC;AACF,eAAe,gBAAgB,CAAC"}
@@ -4,10 +4,12 @@ import { useEffect, useRef } from 'react';
4
4
  import { useFrame, useThree } from '@react-three/fiber';
5
5
  import { useCameraAnimation } from '../hooks/useCameraAnimation.js';
6
6
  import { cameraManager } from '../utils/CameraSingleton.js';
7
- import { useAnimationEvents } from '../hooks/useAnimationEvents.js';
8
7
  import { usePathAnimation } from '../hooks/usePathAnimation.js';
9
8
  import { OrbitControls } from "@react-three/drei";
9
+ import { useRuntimeSettings } from '../hooks/useRuntimeSettings.js';
10
10
  export const CameraController = ({ enableAutoAnimation = true, animationDuration = 1, animationEase = "power2.out", settings, onObjectReady, onObjectDispose, onControlsReady, onControlsDispose, }) => {
11
+ // Authored camera + any applied action patch ('camera').
12
+ settings = useRuntimeSettings('camera', settings);
11
13
  const { camera, set } = useThree();
12
14
  const cameraRef = useRef(camera);
13
15
  const transformAnimationProgress = useRef(0);
@@ -100,49 +102,6 @@ export const CameraController = ({ enableAutoAnimation = true, animationDuration
100
102
  cam.updateProjectionMatrix();
101
103
  }
102
104
  }, [fov, near, far]);
103
- // Handle animation events (step-based animations)
104
- useAnimationEvents({
105
- onStepStart: (event) => {
106
- if (event.step?.transitions) {
107
- const stepDuration = event.step.duration || 1;
108
- event.step.transitions.forEach((transition) => {
109
- const { state, properties, pathId } = transition;
110
- if (state === 'camera') {
111
- isInAnimatedTransition.current = true;
112
- if (pathId) {
113
- const offset = camera
114
- ? [camera.position.x, camera.position.y, camera.position.z]
115
- : [0, 0, 0];
116
- startPathAnimation(pathId, stepDuration, {
117
- offset,
118
- applyRotation: false
119
- });
120
- transformAnimationProgress.current = 0;
121
- }
122
- const startSettings = properties.from ?
123
- {
124
- position: properties.from.position,
125
- // orientation: properties.from.orientation,
126
- } : {
127
- position: camera.position,
128
- // orientation: camera.rotation,
129
- };
130
- const targetSettings = properties.to;
131
- // startSettings.position && camera.position.set(startSettings.position[0], startSettings.position[1], startSettings.position[2]);
132
- // camera.rotation.set(startSettings.orientation[0], startSettings.orientation[1], startSettings.orientation[2]);
133
- animateCamera(targetSettings, stepDuration, event.step?.ease, properties.to.target)
134
- .then(() => {
135
- isInAnimatedTransition.current = false;
136
- if (properties.to.target) {
137
- controlsRef.current?.target.set(properties.to.target[0], properties.to.target[1], properties.to.target[2]);
138
- }
139
- ;
140
- });
141
- }
142
- });
143
- }
144
- }
145
- });
146
105
  // Frame loop for path animations and mouse handlers
147
106
  useFrame((state, delta) => {
148
107
  if (isPathAnimating()) {
@@ -1 +1 @@
1
- {"version":3,"file":"Clouds.d.ts","sourceRoot":"","sources":["../../src/components/Clouds.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAQ7D,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,MAAM,WAAW,WAAY,SAAQ,gBAAgB;IACjD,QAAQ,EAAE,qBAAqB,CAAC;IAChC,YAAY,CAAC,EAAE,YAAY,CAAC;CAC/B;AAmFD,QAAA,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAqLjC,CAAC;AACF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"Clouds.d.ts","sourceRoot":"","sources":["../../src/components/Clouds.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAO7D,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,MAAM,WAAW,WAAY,SAAQ,gBAAgB;IACjD,QAAQ,EAAE,qBAAqB,CAAC;IAChC,YAAY,CAAC,EAAE,YAAY,CAAC;CAC/B;AAmFD,QAAA,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAoJjC,CAAC;AACF,eAAe,MAAM,CAAC"}
@@ -4,7 +4,6 @@ import { useRef, useCallback } from 'react';
4
4
  import * as THREE from 'three';
5
5
  import { useThree, useFrame } from '@react-three/fiber';
6
6
  import { useSkySystem } from '../hooks/useSkySystem.js';
7
- import { useAnimationEvents } from '../hooks/useAnimationEvents.js';
8
7
  import { useNumericAnimation } from '../hooks/useNumericAnimation.js';
9
8
  import { calculateTimeProgress, applyEasing, gsapEasingMap, interpolateValue, interpolateMouseMoveProperty, } from '@3driseai/3drise-core';
10
9
  const CLOUD_COLORS = {
@@ -142,39 +141,6 @@ const Clouds = ({ settings, timeSettings = defaultTimeSettings, onObjectReady, o
142
141
  onTimeUpdate: handleTimeUpdate,
143
142
  enabled: visible,
144
143
  });
145
- // Legacy sequence-driven `speed`/`scale` anims via `useAnimationEvents`
146
- useAnimationEvents({
147
- onStepStart: (event) => {
148
- if (!event.step?.transitions)
149
- return;
150
- for (const transition of event.step.transitions) {
151
- if (transition.state !== 'clouds' || !meshRef.current)
152
- continue;
153
- const toProps = transition.properties.to || {};
154
- const fromProps = transition.properties.from || {};
155
- if (toProps.visible !== undefined)
156
- meshRef.current.visible = toProps.visible;
157
- const KEYS = ['speed', 'scale'];
158
- const from = {};
159
- const to = {};
160
- for (const k of KEYS) {
161
- const toVal = toProps[k];
162
- if (toVal === undefined)
163
- continue;
164
- to[k] = toVal;
165
- const sourceFallback = k === 'speed' ? baseSpeed : scale;
166
- from[k] = fromProps[k] ?? sourceFallback;
167
- }
168
- if (Object.keys(to).length > 0) {
169
- animateNumeric(from, to, (updated) => {
170
- numericOverrideRef.current = { ...numericOverrideRef.current, ...updated };
171
- }, () => {
172
- numericOverrideRef.current = null;
173
- }, event.step?.duration);
174
- }
175
- }
176
- },
177
- });
178
144
  useFrame((state) => {
179
145
  const mesh = meshRef.current;
180
146
  if (!mesh || !mesh.visible || !mesh.material)
@@ -1 +1 @@
1
- {"version":3,"file":"CreatedObject.d.ts","sourceRoot":"","sources":["../../src/components/CreatedObject.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAWnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,UAAU,kBAAmB,SAAQ,gBAAgB;IACjD,aAAa,EAAE,qBAAqB,CAAC;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CACpH;AAGD,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAuF9C,CAAC;AAEH,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"CreatedObject.d.ts","sourceRoot":"","sources":["../../src/components/CreatedObject.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAWnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,UAAU,kBAAmB,SAAQ,gBAAgB;IACjD,aAAa,EAAE,qBAAqB,CAAC;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CACpH;AAKD,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAsG9C,CAAC;AAEH,eAAe,aAAa,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useRef, useEffect, useState, useReducer, memo } from "react";
2
+ import { useRef, useEffect, useState, useReducer, memo, useContext } from "react";
3
+ import { ObjectHoverContext } from "../interactions/runner.js";
3
4
  import { ModelMaterialPassContext } from "./ModelMaterialPassContext.js";
4
5
  import { DEFAULT_EDGES_SETTINGS } from "@3driseai/3drise-core";
5
6
  import { useMaterialApplication } from "../hooks/useMaterialApplication.js";
@@ -12,11 +13,16 @@ import AnimatedObject from "./AnimatedObject.js";
12
13
  import { useFrameEffects } from "../hooks/useFrameEffects.js";
13
14
  import { useObjectEdges } from "../hooks/useObjectEdges.js";
14
15
  import { useObjectReady } from "../hooks/useObjectReady.js";
16
+ /** One hovered part of an object: the intersected mesh (+ instance). */
17
+ const hoverKey = (e) => `${e.object?.uuid}/${e.instanceId ?? ''}`;
15
18
  const CreatedObject = memo(({ createdObject, children, shouldApply3driseMaterial = true, onObjectReady, onObjectDispose, handleObjectClick, }) => {
16
19
  const isSelected = false;
17
20
  // const isSelected = useObjectSelection(createdObject.id);
18
21
  // const { handleObjectClick: contextHandleObjectClick } = useSceneClick();
19
22
  const meshRef = useRef(null);
23
+ // 'mouseEnter' / 'mouseLeave' interactions (ObjectsRenderer).
24
+ const onHover = useContext(ObjectHoverContext);
25
+ const hoveredPartsRef = useRef(new Set());
20
26
  const transformRef = useRef(null);
21
27
  // const baseColorRef = useRef<string>(("color" in createdObject.materialSettings && createdObject.materialSettings.color) || '#ffffff');
22
28
  // const [hovered, setHovered] = useState(false);
@@ -67,6 +73,14 @@ const CreatedObject = memo(({ createdObject, children, shouldApply3driseMaterial
67
73
  // Only handle if this is the actual mesh group, not a child
68
74
  if (e.eventObject !== meshRef.current)
69
75
  return;
76
+ // R3F fires enter / leave on this group once per hovered DESCENDANT (and per
77
+ // intersection), so a model with overlapping meshes fires several at once.
78
+ // Track the hovered parts and report only the first enter / last leave —
79
+ // otherwise two-state effects (glow, fade…) toggle on and straight back off.
80
+ const wasHovered = hoveredPartsRef.current.size > 0;
81
+ hoveredPartsRef.current.add(hoverKey(e));
82
+ if (!wasHovered)
83
+ onHover?.(createdObject, meshRef.current, 'mouseEnter');
70
84
  if (createdObject.type === 'particles' || createdObject.type === 'gallery')
71
85
  return;
72
86
  // e.stopPropagation();
@@ -79,6 +93,10 @@ const CreatedObject = memo(({ createdObject, children, shouldApply3driseMaterial
79
93
  // Only handle if this is the actual mesh group, not a child
80
94
  if (e.eventObject !== meshRef.current)
81
95
  return;
96
+ hoveredPartsRef.current.delete(hoverKey(e));
97
+ if (hoveredPartsRef.current.size > 0)
98
+ return; // still over another part of this object
99
+ onHover?.(createdObject, meshRef.current, 'mouseLeave');
82
100
  if (createdObject.type === 'particles' || createdObject.type === 'gallery')
83
101
  return;
84
102
  handlePointerLeave();
@@ -1 +1 @@
1
- {"version":3,"file":"EnvironmentManager.d.ts","sourceRoot":"","sources":["../../src/components/EnvironmentManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAGhF,OAAO,KAAK,EACR,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAIhE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;;;;;;;;;iFAWiF;AACjF,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG;IAChF,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAClC,OAAO,CAAC,EAAE,yBAAyB,CAAC;IACpC,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,KAAK,CAAC,EAAE,kBAAkB,CAAC;CAC9B,CAAC;AAEF,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC7D,YAAY,EAAE,YAAY,CAAC;IAC3B,iFAAiF;IACjF,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,cAAc,CAAC,EAAE,wBAAwB,CAAC;IAC1C,eAAe,CAAC,EAAE,yBAAyB,CAAC;IAC5C,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,cAAc,CAAC,mBAAmB,CAAC,CAAC;IACxD,YAAY,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;IAC9C;sEACkE;IAClE,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAoBD,QAAA,MAAM,kBAAkB,8FAwGtB,CAAC;AAGH,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"EnvironmentManager.d.ts","sourceRoot":"","sources":["../../src/components/EnvironmentManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAGhF,OAAO,KAAK,EACR,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAIhE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;;;;;;;;;iFAWiF;AACjF,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG;IAChF,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAClC,OAAO,CAAC,EAAE,yBAAyB,CAAC;IACpC,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,KAAK,CAAC,EAAE,kBAAkB,CAAC;CAC9B,CAAC;AAEF,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC7D,YAAY,EAAE,YAAY,CAAC;IAC3B,iFAAiF;IACjF,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,cAAc,CAAC,EAAE,wBAAwB,CAAC;IAC1C,eAAe,CAAC,EAAE,yBAAyB,CAAC;IAC5C,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,cAAc,CAAC,mBAAmB,CAAC,CAAC;IACxD,YAAY,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;IAC9C;sEACkE;IAClE,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAoBD,QAAA,MAAM,kBAAkB,8FAyGtB,CAAC;AAGH,eAAe,kBAAkB,CAAC"}
@@ -7,6 +7,7 @@ import { useEnvironmentProbe } from '../hooks/useEnvironmentProbe.js';
7
7
  import TerrainBuilder from './TerrainBuilder.js';
8
8
  import LandscapeBuilder from './LandscapeBuilder.js';
9
9
  import OceanBuilder from './OceanBuilder.js';
10
+ import { useRuntimeSettings } from '../hooks/useRuntimeSettings.js';
10
11
  const DEFAULT_HDR = {
11
12
  visible: false,
12
13
  name: null,
@@ -25,11 +26,12 @@ const DEFAULT_HDR = {
25
26
  const ORIGIN = new Vector3(0, 0, 0);
26
27
  const EnvironmentManager = forwardRef(({ timeSettings, environment, hdrSettings, skySettings, cloudsSettings, terrainSettings, landscapeSettings, oceanSettings, fogSettings, cubeCameraResolution = 512, skyboxScale = 100000, playerPosition = ORIGIN, onTimeOfDayChange, onTimeUpdate, driveTime = true, onObjectReady, onObjectDispose, }, ref) => {
27
28
  const hdr = hdrSettings ?? environment?.hdr ?? DEFAULT_HDR;
28
- const sky = skySettings ?? environment?.sky;
29
- const clouds = cloudsSettings ?? environment?.clouds;
30
- const terrain = terrainSettings ?? environment?.terrain;
29
+ // Authored settings + applied action patches (runtime only).
30
+ const sky = useRuntimeSettings('sky', skySettings ?? environment?.sky);
31
+ const clouds = useRuntimeSettings('clouds', cloudsSettings ?? environment?.clouds);
32
+ const terrain = useRuntimeSettings('terrain', terrainSettings ?? environment?.terrain);
31
33
  const landscape = landscapeSettings ?? environment?.landscape;
32
- const ocean = oceanSettings ?? environment?.ocean;
34
+ const ocean = useRuntimeSettings('ocean', oceanSettings ?? environment?.ocean);
33
35
  const fog = fogSettings ?? environment?.fog;
34
36
  const sunSystemVisible = !!sky?.sunSystem?.visible;
35
37
  // Previously hardcoded true, which kept a cube camera alive — and re-captured
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectNode.d.ts","sourceRoot":"","sources":["../../src/components/ObjectNode.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAe,qBAAqB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAiBrD,KAAK,eAAe,GAAG,gBAAgB,GAAG;IACtC,IAAI,EAAE,cAAc,CAAC;IACrB,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAC7G,CAAC;AAkBF,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAsIzC,CAAC;AACF,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"ObjectNode.d.ts","sourceRoot":"","sources":["../../src/components/ObjectNode.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAe,qBAAqB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAiBrD,KAAK,eAAe,GAAG,gBAAgB,GAAG;IACtC,IAAI,EAAE,cAAc,CAAC;IACrB,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAC7G,CAAC;AAkBF,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAyIzC,CAAC;AACF,eAAe,UAAU,CAAC"}
@@ -15,6 +15,7 @@ import GridGenerator from "./GridsGenerator.js";
15
15
  import OceanBuilder from "./OceanBuilder.js";
16
16
  import LandscapeObject from "./LandscapeObject.js";
17
17
  import LayoutInstances from "./LayoutInstances.js";
18
+ import { useRuntimeSettings } from "../hooks/useRuntimeSettings.js";
18
19
  import { SELF_MANAGED_MATERIAL } from "../constants.js";
19
20
  import { LAYOUT_CAPABLE_TYPES, getObjectLayoutSupport, normalizeObjectLayout, isGenerativeParticlesConfig } from "@3driseai/3drise-core";
20
21
  // Slots after the first render with no ready callbacks: one object reports once.
@@ -47,7 +48,10 @@ const GroupWithChildren = ({ createdObject, children, onObjectReady, onObjectDis
47
48
  return (_jsxs(CreatedObject, { createdObject: createdObject, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose, handleObjectClick: handleObjectClick, shouldApply3driseMaterial: !isGroup && !selfManagedMaterial, children: [!isGroup && renderObject(createdObject, handleObjectClick), children.map(childNode => (_jsx(ObjectNode, { node: childNode, handleObjectClick: handleObjectClick, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }, childNode.objectId)))] }, createdObject.id));
48
49
  };
49
50
  const ObjectNode = ({ node, onObjectReady, onObjectDispose, handleObjectClick }) => {
50
- const { children, createdObject } = node;
51
+ const { children } = node;
52
+ // Authored settings + any applied action patches (runtime only). Every renderer
53
+ // below sees the patched object, so an action can change anything an edit can.
54
+ const createdObject = useRuntimeSettings(node.createdObject?.id, node.createdObject);
51
55
  // Children describe themselves with their own settings; the scene above
52
56
  // knows them by the node's createdObject, so relabel on the way up.
53
57
  const relabel = useCallback((obj) => ({
@@ -1,4 +1,5 @@
1
- import type { AnimationSequence, GeneralObjectSettings, CameraState, CreatedObjectSettings } from '@3driseai/3drise-core';
1
+ import type { ActionSequence, GeneralObjectSettings, CameraState, CreatedObjectSettings } from '@3driseai/3drise-core';
2
+ import type { AnimationClip, AnimationSequence } from '../animationsV2/types';
2
3
  import type { ObjectReadyProps } from '../types/objectReady';
3
4
  import React from "react";
4
5
  import { Object3D } from "three";
@@ -9,7 +10,10 @@ interface ObjectsRendererProps extends ObjectReadyProps {
9
10
  createdObjects: CreatedObjectSettings[];
10
11
  onObjectsReady?: () => void;
11
12
  handleObjectClick?: (object: CreatedObjectSettings, ref: Object3D, event: ThreeEvent<MouseEvent>) => void;
13
+ /** Animations V2 sequences and clips, for interaction triggers. */
12
14
  sequences?: AnimationSequence[];
15
+ clips?: AnimationClip[];
16
+ actionSequences?: ActionSequence[];
13
17
  }
14
18
  declare const ObjectsRenderer: React.FC<ObjectsRendererProps>;
15
19
  export default ObjectsRenderer;
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectsRenderer.d.ts","sourceRoot":"","sources":["../../src/components/ObjectsRenderer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAI1H,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,UAAU,oBAAqB,SAAQ,gBAAgB;IACnD,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;CACnC;AAGD,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA0ClD,CAAC;AAEH,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"ObjectsRenderer.d.ts","sourceRoot":"","sources":["../../src/components/ObjectsRenderer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACvH,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAM9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,UAAU,oBAAqB,SAAQ,gBAAgB;IACnD,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,mEAAmE;IACnE,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChC,KAAK,CAAC,EAAE,aAAa,EAAE,CAAC;IACxB,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;CACtC;AAGD,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA4DlD,CAAC;AAEH,eAAe,eAAe,CAAC"}
@@ -1,10 +1,12 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { memo, useRef, useCallback, useMemo } from 'react';
2
+ import { memo, useRef, useCallback, useMemo, useEffect } from 'react';
3
3
  import { buildObjectTree } from '@3driseai/3drise-core';
4
4
  import ObjectNode from './ObjectNode.js';
5
5
  import useInteraction from '../hooks/useInteraction.js';
6
+ import { ObjectHoverContext, setInteractionRunner } from '../interactions/runner.js';
7
+ import { findById } from '../utils/sceneQuery.js';
6
8
  import { useObjectReady } from '../hooks/useObjectReady.js';
7
- const ObjectsRenderer = memo(({ cameraSettings, createdObjects, generalObjectSettings, onObjectsReady, onObjectReady, onObjectDispose, handleObjectClick, sequences = [], }) => {
9
+ const ObjectsRenderer = memo(({ cameraSettings, createdObjects, generalObjectSettings, onObjectsReady, onObjectReady, onObjectDispose, handleObjectClick, sequences = [], clips = [], actionSequences = [], }) => {
8
10
  const groupRef = useRef(null);
9
11
  const objectsTree = useMemo(() => buildObjectTree(createdObjects), [createdObjects]);
10
12
  const readyObjectsCount = useRef(0);
@@ -32,7 +34,26 @@ const ObjectsRenderer = memo(({ cameraSettings, createdObjects, generalObjectSet
32
34
  const { executeInteraction } = useInteraction({
33
35
  cameraSettings,
34
36
  sequences,
37
+ clips,
38
+ actionSequences,
35
39
  });
40
+ // Hover triggers: CreatedObject reports enter / leave through ObjectHoverContext.
41
+ const handleObjectHover = useCallback((createdObject, ref, trigger) => {
42
+ filterInteractionsByEvent(createdObject.actions, trigger).forEach((interaction) => {
43
+ executeInteraction({ interaction, ref, createdObject });
44
+ });
45
+ }, [executeInteraction]);
46
+ // "Try it" in the studio: run an interaction as if its trigger fired.
47
+ const objectsRef = useRef(createdObjects);
48
+ objectsRef.current = createdObjects;
49
+ useEffect(() => setInteractionRunner((objectId, interaction) => {
50
+ const ref = findById(objectId);
51
+ const createdObject = objectsRef.current?.find(o => o.id === objectId);
52
+ if (!ref || !createdObject)
53
+ return false;
54
+ executeInteraction({ interaction, ref, createdObject });
55
+ return true;
56
+ }), [executeInteraction]);
36
57
  const handleObjectClickHandler = (createdObject, ref, event) => {
37
58
  const clickInteractions = filterInteractionsByEvent(createdObject.actions, "click");
38
59
  clickInteractions.forEach((interaction) => {
@@ -42,7 +63,7 @@ const ObjectsRenderer = memo(({ cameraSettings, createdObjects, generalObjectSet
42
63
  handleObjectClick(createdObject, ref, event);
43
64
  }
44
65
  };
45
- 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, onObjectReady: handleObjectReady, onObjectDispose: handleObjectDispose, handleObjectClick: handleObjectClickHandler }, node.objectId))) }));
66
+ return (_jsx(ObjectHoverContext.Provider, { value: handleObjectHover, children: _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, onObjectReady: handleObjectReady, onObjectDispose: handleObjectDispose, handleObjectClick: handleObjectClickHandler }, node.objectId))) }) }));
46
67
  });
47
68
  ObjectsRenderer.displayName = 'ObjectsRenderer';
48
69
  export default ObjectsRenderer;
@@ -1 +1 @@
1
- {"version":3,"file":"Ocean.d.ts","sourceRoot":"","sources":["../../src/components/Ocean.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAU7D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,MAAM,WAAW,UAAW,SAAQ,gBAAgB;IAChD,QAAQ,EAAE,qBAAqB,CAAC;CACnC;AAGD,QAAA,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA6J/B,CAAC;AACF,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"Ocean.d.ts","sourceRoot":"","sources":["../../src/components/Ocean.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAS7D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,MAAM,WAAW,UAAW,SAAQ,gBAAgB;IAChD,QAAQ,EAAE,qBAAqB,CAAC;CACnC;AAGD,QAAA,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA+F/B,CAAC;AACF,eAAe,KAAK,CAAC"}
@@ -6,7 +6,6 @@ import { useFrame } from '@react-three/fiber';
6
6
  import { useMaterialApplication } from '../hooks/useMaterialApplication.js';
7
7
  import { useWaterEnvironment } from '../hooks/useWaterEnvironment.js';
8
8
  import { useWaterReflections } from '../hooks/useWaterReflections.js';
9
- import { useAnimationEvents } from '../hooks/useAnimationEvents.js';
10
9
  import { useNumericAnimation } from '../hooks/useNumericAnimation.js';
11
10
  import { handleTransformAnimations, handleMaterialAnimations, handleTransformMouseMove, handleMaterialMouseMove, } from '@3driseai/3drise-core';
12
11
  const Ocean = ({ settings, onObjectReady, onObjectDispose }) => {
@@ -34,68 +33,6 @@ const Ocean = ({ settings, onObjectReady, onObjectDispose }) => {
34
33
  updateFrequency: 1,
35
34
  enabled: meshSettings.visible,
36
35
  });
37
- useAnimationEvents({
38
- onStepStart: (event) => {
39
- if (!event.step?.transitions)
40
- return;
41
- for (const transition of event.step.transitions) {
42
- if (transition.state !== 'ocean' || !meshRef.current)
43
- continue;
44
- const toProps = transition.properties.to || {};
45
- const fromProps = transition.properties.from || {};
46
- // visible — update state so JSX visible prop re-renders
47
- if (toProps.visible !== undefined) {
48
- setMeshVisible(toProps.visible);
49
- }
50
- // numeric uniforms: animate any key in `to` that maps to a shader uniform
51
- const material = meshRef.current.material;
52
- const uniforms = material?.uniforms;
53
- if (!uniforms)
54
- continue;
55
- const from = {};
56
- const to = {};
57
- for (const key of Object.keys(toProps)) {
58
- if (key === 'visible')
59
- continue;
60
- const toVal = toProps[key];
61
- if (toVal === undefined)
62
- continue;
63
- to[key] = toVal;
64
- const fromExplicit = fromProps[key];
65
- if (fromExplicit !== undefined) {
66
- from[key] = fromExplicit;
67
- }
68
- else if (uniforms[key]?.value !== undefined) {
69
- const liveVal = uniforms[key].value;
70
- if (typeof liveVal === 'number') {
71
- from[key] = liveVal;
72
- }
73
- else if (liveVal?.toArray) {
74
- from[key] = liveVal.toArray();
75
- }
76
- else if (Array.isArray(liveVal)) {
77
- from[key] = [...liveVal];
78
- }
79
- else {
80
- from[key] = toVal;
81
- }
82
- }
83
- else {
84
- from[key] = toVal;
85
- }
86
- }
87
- if (Object.keys(to).length > 0) {
88
- animateNumeric(from, to, (updated) => {
89
- uniformOverrideRef.current = { ...uniformOverrideRef.current, ...updated };
90
- }, () => {
91
- uniformOverrideRef.current = null;
92
- if (toProps.visible !== undefined)
93
- setMeshVisible(null);
94
- }, event.step?.duration);
95
- }
96
- }
97
- },
98
- });
99
36
  useFrame((state) => {
100
37
  const mesh = meshRef.current;
101
38
  if (!mesh?.material || !(meshVisible ?? meshSettings.visible))