@3driseai/3drise-viewer 0.1.23 → 0.1.25

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 (62) hide show
  1. package/dist/api/sceneHandle.d.ts +63 -0
  2. package/dist/api/sceneHandle.d.ts.map +1 -0
  3. package/dist/api/sceneHandle.js +160 -0
  4. package/dist/components/CameraController.d.ts.map +1 -1
  5. package/dist/components/CameraController.js +4 -1
  6. package/dist/components/EnvironmentManager.d.ts.map +1 -1
  7. package/dist/components/EnvironmentManager.js +5 -3
  8. package/dist/components/LightObject.d.ts.map +1 -1
  9. package/dist/components/LightObject.js +4 -0
  10. package/dist/components/ObjectNode.d.ts.map +1 -1
  11. package/dist/components/ObjectNode.js +5 -1
  12. package/dist/components/ObjectsRenderer.d.ts +2 -1
  13. package/dist/components/ObjectsRenderer.d.ts.map +1 -1
  14. package/dist/components/ObjectsRenderer.js +2 -1
  15. package/dist/components/ProjectLoader.d.ts +9 -3
  16. package/dist/components/ProjectLoader.d.ts.map +1 -1
  17. package/dist/components/ProjectLoader.js +5 -4
  18. package/dist/components/SceneBuilder.d.ts +9 -1
  19. package/dist/components/SceneBuilder.d.ts.map +1 -1
  20. package/dist/components/SceneBuilder.js +14 -4
  21. package/dist/components/Stars.d.ts.map +1 -1
  22. package/dist/components/Stars.js +2 -1
  23. package/dist/components/candle/Candle.d.ts +14 -0
  24. package/dist/components/candle/Candle.d.ts.map +1 -0
  25. package/dist/components/candle/Candle.js +249 -0
  26. package/dist/components/candle/candleGeometry.d.ts +23 -0
  27. package/dist/components/candle/candleGeometry.d.ts.map +1 -0
  28. package/dist/components/candle/candleGeometry.js +73 -0
  29. package/dist/components/candle/candleMaterials.d.ts +24 -0
  30. package/dist/components/candle/candleMaterials.d.ts.map +1 -0
  31. package/dist/components/candle/candleMaterials.js +433 -0
  32. package/dist/components/candle/flameMotion.d.ts +64 -0
  33. package/dist/components/candle/flameMotion.d.ts.map +1 -0
  34. package/dist/components/candle/flameMotion.js +138 -0
  35. package/dist/components/candle/index.d.ts +9 -0
  36. package/dist/components/candle/index.d.ts.map +1 -0
  37. package/dist/components/candle/index.js +6 -0
  38. package/dist/components/index.d.ts +1 -0
  39. package/dist/components/index.d.ts.map +1 -1
  40. package/dist/components/index.js +1 -0
  41. package/dist/hooks/index.d.ts +2 -0
  42. package/dist/hooks/index.d.ts.map +1 -1
  43. package/dist/hooks/index.js +2 -0
  44. package/dist/hooks/useInteraction.d.ts +3 -2
  45. package/dist/hooks/useInteraction.d.ts.map +1 -1
  46. package/dist/hooks/useInteraction.js +43 -8
  47. package/dist/hooks/useLightConfig.d.ts.map +1 -1
  48. package/dist/hooks/useLightConfig.js +7 -0
  49. package/dist/hooks/useLightLive.d.ts.map +1 -1
  50. package/dist/hooks/useLightLive.js +5 -0
  51. package/dist/hooks/useLightTargets.d.ts +7 -0
  52. package/dist/hooks/useLightTargets.d.ts.map +1 -0
  53. package/dist/hooks/useLightTargets.js +132 -0
  54. package/dist/hooks/useRuntimeSettings.d.ts +15 -0
  55. package/dist/hooks/useRuntimeSettings.d.ts.map +1 -0
  56. package/dist/hooks/useRuntimeSettings.js +22 -0
  57. package/dist/hooks/useSequenceAnimation.d.ts.map +1 -1
  58. package/dist/hooks/useSequenceAnimation.js +27 -9
  59. package/dist/index.d.ts +2 -0
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +2 -0
  62. package/package.json +2 -2
@@ -0,0 +1,63 @@
1
+ import type { ActionSequence, AnimationSequence } from '@3driseai/3drise-core';
2
+ export interface SceneActionInfo {
3
+ id: string;
4
+ key?: string;
5
+ name: string;
6
+ description?: string;
7
+ applied: boolean;
8
+ }
9
+ export interface SceneAnimationInfo {
10
+ id: string;
11
+ name: string;
12
+ description?: string;
13
+ /** Seconds, one forward pass: Σ(delay + duration) over steps */
14
+ duration: number;
15
+ loop: boolean;
16
+ yoyo: boolean;
17
+ playing: boolean;
18
+ }
19
+ export interface ScenePlayOptions {
20
+ speed?: number;
21
+ reverse?: boolean;
22
+ }
23
+ export type SceneHandleEventType = 'actionApplied' | 'actionReverted' | 'animationStart' | 'animationEnd';
24
+ export interface SceneHandleEvent {
25
+ type: SceneHandleEventType;
26
+ id: string;
27
+ key?: string;
28
+ name: string;
29
+ }
30
+ export interface SceneHandle {
31
+ actions: {
32
+ list(): SceneActionInfo[];
33
+ apply(ref: string): boolean;
34
+ revert(ref: string): boolean;
35
+ /** Returns true when it applied, false when it reverted (or the action was not found). */
36
+ toggle(ref: string): boolean;
37
+ isApplied(ref: string): boolean;
38
+ /** Revert every applied action of this project — back to the authored scene. */
39
+ reset(): void;
40
+ };
41
+ animations: {
42
+ list(): SceneAnimationInfo[];
43
+ play(ref: string, options?: ScenePlayOptions): boolean;
44
+ pause(ref: string): boolean;
45
+ resume(ref: string): boolean;
46
+ stop(ref: string): boolean;
47
+ /** Jump to a point in the animation, 0–1. */
48
+ seek(ref: string, progress: number): boolean;
49
+ isPlaying(ref: string): boolean;
50
+ };
51
+ /** Subscribe to this project's action / animation events. Returns the unsubscribe. */
52
+ on(type: SceneHandleEventType, listener: (event: SceneHandleEvent) => void): () => void;
53
+ }
54
+ export interface SceneHandleSource {
55
+ actions: ActionSequence[];
56
+ animations: AnimationSequence[];
57
+ }
58
+ /**
59
+ * Build a handle over one project's actions and animations. `getSource` is read on
60
+ * every call, so the handle stays valid if the project data is replaced.
61
+ */
62
+ export declare function createSceneHandle(getSource: () => SceneHandleSource): SceneHandle;
63
+ //# sourceMappingURL=sceneHandle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sceneHandle.d.ts","sourceRoot":"","sources":["../../src/api/sceneHandle.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,cAAc,EAAkB,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/F,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,oBAAoB,GAAG,eAAe,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,cAAc,CAAC;AAE1G,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE;QACL,IAAI,IAAI,eAAe,EAAE,CAAC;QAC1B,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAC5B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAC7B,0FAA0F;QAC1F,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAC7B,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAChC,gFAAgF;QAChF,KAAK,IAAI,IAAI,CAAC;KACjB,CAAC;IACF,UAAU,EAAE;QACR,IAAI,IAAI,kBAAkB,EAAE,CAAC;QAC7B,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC;QACvD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAC5B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAC7B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAC3B,6CAA6C;QAC7C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAC7C,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACnC,CAAC;IACF,sFAAsF;IACtF,EAAE,CAAC,IAAI,EAAE,oBAAoB,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAC3F;AAED,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,UAAU,EAAE,iBAAiB,EAAE,CAAC;CACnC;AA0BD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,iBAAiB,GAAG,WAAW,CAuGjF"}
@@ -0,0 +1,160 @@
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 and animations from their
7
+ // own UI, and hear when they run.
8
+ //
9
+ // scene.current?.actions.toggle('open-door');
10
+ // scene.current?.animations.play('intro', { speed: 1.5 });
11
+ // const off = scene.current?.on('actionApplied', (e) => console.log(e.key));
12
+ //
13
+ // Addressing (`ref`): an action's `key` first (stable across renames and project
14
+ // copies — prefer it), then its id, then its exact name. Animations have no key
15
+ // yet, so id, then name. An ambiguous name warns and uses the first match.
16
+ //
17
+ // This is a thin layer: object clicks go through the same SceneActions /
18
+ // AnimationsManager calls, so a button and a click behave identically.
19
+ //
20
+ import { AnimationsManager, SceneActions } from '@3driseai/3drise-core';
21
+ function resolve(items, ref, kind) {
22
+ if (!ref)
23
+ return undefined;
24
+ const byKey = items.find(i => i.key === ref);
25
+ if (byKey)
26
+ return byKey;
27
+ const byId = items.find(i => i.id === ref);
28
+ if (byId)
29
+ return byId;
30
+ const byName = items.filter(i => i.name === ref);
31
+ if (byName.length > 1) {
32
+ console.warn(`[3drise] ${byName.length} ${kind}s are named "${ref}"; using the first.${kind === 'action' ? ' Address it by its key instead.' : ''}`);
33
+ }
34
+ if (byName.length === 0) {
35
+ console.warn(`[3drise] No ${kind} "${ref}" in this project. Known: ${items.map(i => i.key ?? i.name).join(', ') || 'none'}`);
36
+ }
37
+ return byName[0];
38
+ }
39
+ function animationDuration(seq) {
40
+ return (seq.steps ?? []).reduce((sum, s) => sum + (s.delay || 0) + (s.duration || 0), 0);
41
+ }
42
+ /**
43
+ * Build a handle over one project's actions and animations. `getSource` is read on
44
+ * every call, so the handle stays valid if the project data is replaced.
45
+ */
46
+ export function createSceneHandle(getSource) {
47
+ const actions = () => getSource().actions ?? [];
48
+ const animations = () => getSource().animations ?? [];
49
+ const findAction = (ref) => resolve(actions(), ref, 'action');
50
+ const findAnimation = (ref) => resolve(animations(), ref, 'animation');
51
+ return {
52
+ actions: {
53
+ list: () => actions().map(a => ({
54
+ id: a.id,
55
+ key: a.key,
56
+ name: a.name,
57
+ description: a.description,
58
+ applied: SceneActions.isActionApplied(a.id),
59
+ })),
60
+ apply(ref) {
61
+ const a = findAction(ref);
62
+ if (!a)
63
+ return false;
64
+ SceneActions.applyAction(a);
65
+ return true;
66
+ },
67
+ revert(ref) {
68
+ const a = findAction(ref);
69
+ if (!a)
70
+ return false;
71
+ SceneActions.revertAction(a);
72
+ return true;
73
+ },
74
+ toggle(ref) {
75
+ const a = findAction(ref);
76
+ return a ? SceneActions.toggleAction(a) : false;
77
+ },
78
+ isApplied(ref) {
79
+ const a = findAction(ref);
80
+ return a ? SceneActions.isActionApplied(a.id) : false;
81
+ },
82
+ reset() {
83
+ // Only this project's actions — another scene on the page keeps its state.
84
+ for (const a of actions())
85
+ SceneActions.revertAction(a.id);
86
+ },
87
+ },
88
+ animations: {
89
+ list: () => animations().map(s => ({
90
+ id: s.id,
91
+ name: s.name,
92
+ description: s.description,
93
+ duration: animationDuration(s),
94
+ loop: !!s.loop,
95
+ yoyo: !!s.yoyo,
96
+ playing: AnimationsManager.isSequencePlaying(s.id),
97
+ })),
98
+ play(ref, options = {}) {
99
+ const s = findAnimation(ref);
100
+ if (!s)
101
+ return false;
102
+ AnimationsManager.playSequence(s, { speed: options.speed, reverse: options.reverse });
103
+ return true;
104
+ },
105
+ pause(ref) {
106
+ const s = findAnimation(ref);
107
+ if (!s)
108
+ return false;
109
+ AnimationsManager.pauseSequence(s.id);
110
+ return true;
111
+ },
112
+ resume(ref) {
113
+ const s = findAnimation(ref);
114
+ if (!s)
115
+ return false;
116
+ AnimationsManager.resumeSequence(s.id);
117
+ return true;
118
+ },
119
+ stop(ref) {
120
+ const s = findAnimation(ref);
121
+ if (!s)
122
+ return false;
123
+ AnimationsManager.stopSequence(s.id);
124
+ return true;
125
+ },
126
+ seek(ref, progress) {
127
+ const s = findAnimation(ref);
128
+ if (!s)
129
+ return false;
130
+ AnimationsManager.seekToProgress(s.id, progress);
131
+ return true;
132
+ },
133
+ isPlaying(ref) {
134
+ const s = findAnimation(ref);
135
+ return s ? AnimationsManager.isSequencePlaying(s.id) : false;
136
+ },
137
+ },
138
+ on(type, listener) {
139
+ if (type === 'actionApplied' || type === 'actionReverted') {
140
+ return SceneActions.onEvent((e) => {
141
+ if (e.type === 'reset')
142
+ return;
143
+ if ((type === 'actionApplied') !== (e.type === 'applied'))
144
+ return;
145
+ const a = actions().find(x => x.id === e.actionId);
146
+ if (a)
147
+ listener({ type, id: a.id, key: a.key, name: a.name });
148
+ });
149
+ }
150
+ const managerEvent = type === 'animationStart' ? 'sequenceStart' : 'sequenceEnd';
151
+ const handler = (e) => {
152
+ const s = animations().find(x => x.id === e.sequenceId);
153
+ if (s)
154
+ listener({ type, id: s.id, name: s.name });
155
+ };
156
+ AnimationsManager.on(managerEvent, handler);
157
+ return () => AnimationsManager.off(managerEvent, handler);
158
+ },
159
+ };
160
+ }
@@ -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;AAS7D,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,CA0J5D,CAAC;AACF,eAAe,gBAAgB,CAAC"}
@@ -7,7 +7,10 @@ import { cameraManager } from '../utils/CameraSingleton.js';
7
7
  import { useAnimationEvents } from '../hooks/useAnimationEvents.js';
8
8
  import { usePathAnimation } from '../hooks/usePathAnimation.js';
9
9
  import { OrbitControls } from "@react-three/drei";
10
+ import { useRuntimeSettings } from '../hooks/useRuntimeSettings.js';
10
11
  export const CameraController = ({ enableAutoAnimation = true, animationDuration = 1, animationEase = "power2.out", settings, onObjectReady, onObjectDispose, onControlsReady, onControlsDispose, }) => {
12
+ // Authored camera + any applied action patch ('camera').
13
+ settings = useRuntimeSettings('camera', settings);
11
14
  const { camera, set } = useThree();
12
15
  const cameraRef = useRef(camera);
13
16
  const transformAnimationProgress = useRef(0);
@@ -104,7 +107,7 @@ export const CameraController = ({ enableAutoAnimation = true, animationDuration
104
107
  useAnimationEvents({
105
108
  onStepStart: (event) => {
106
109
  if (event.step?.transitions) {
107
- const stepDuration = event.step.duration || 1;
110
+ const stepDuration = event.step.duration ?? 1; // 0 = instant (actions)
108
111
  event.step.transitions.forEach((transition) => {
109
112
  const { state, properties, pathId } = transition;
110
113
  if (state === 'camera') {
@@ -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;
29
+ // Authored settings + applied action patches (runtime only).
30
+ const sky = useRuntimeSettings('sky', skySettings ?? environment?.sky);
31
+ const clouds = useRuntimeSettings('clouds', cloudsSettings ?? environment?.clouds);
30
32
  const 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":"LightObject.d.ts","sourceRoot":"","sources":["../../src/components/LightObject.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAK7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAQnE,KAAK,gBAAgB,GAAG,gBAAgB,GAAG;IACvC,aAAa,EAAE,qBAAqB,CAAC;CACxC,CAAC;AA+CF,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA4B3C,CAAC;AACF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"LightObject.d.ts","sourceRoot":"","sources":["../../src/components/LightObject.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAK7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAUnE,KAAK,gBAAgB,GAAG,gBAAgB,GAAG;IACvC,aAAa,EAAE,qBAAqB,CAAC;CACxC,CAAC;AA+CF,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA+B3C,CAAC;AACF,eAAe,WAAW,CAAC"}
@@ -8,6 +8,7 @@ import LightBulb from './lightBulb/LightBulb.js';
8
8
  import SpotBeam from './spotBeam/SpotBeam.js';
9
9
  import LedArray from './ledArray/LedArray.js';
10
10
  import FluorescentTube from './fluorescentTube/FluorescentTube.js';
11
+ import Candle from './candle/Candle.js';
11
12
  const DirectionalLightR3F = ({ config, animations, mouseMove, settings, onObjectReady, onObjectDispose }) => {
12
13
  const lightRef = useRef(null);
13
14
  useObjectReady(lightRef, settings, onObjectReady, onObjectDispose);
@@ -65,6 +66,9 @@ const LightObject = ({ createdObject, onObjectReady, onObjectDispose }) => {
65
66
  return _jsx(SpotLightR3F, { config: config, animations: animations, mouseMove: mouseMove, settings: createdObject, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose });
66
67
  case 'point':
67
68
  return _jsx(PointLightR3F, { config: config, animations: animations, mouseMove: mouseMove, settings: createdObject, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose });
69
+ // A raymarched flame with its own physics, and the wax under it.
70
+ case 'candle':
71
+ return _jsx(Candle, { id: createdObject.id, config: config, animations: animations, mouseMove: mouseMove, settings: createdObject, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose });
68
72
  // An array of LED dies: instant on, PWM ripple, optional diffuser.
69
73
  case 'ledArray':
70
74
  return _jsx(LedArray, { id: createdObject.id, config: config, animations: animations, mouseMove: mouseMove, settings: createdObject, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose });
@@ -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,4 @@
1
- import type { AnimationSequence, GeneralObjectSettings, CameraState, CreatedObjectSettings } from '@3driseai/3drise-core';
1
+ import type { ActionSequence, AnimationSequence, GeneralObjectSettings, CameraState, CreatedObjectSettings } from '@3driseai/3drise-core';
2
2
  import type { ObjectReadyProps } from '../types/objectReady';
3
3
  import React from "react";
4
4
  import { Object3D } from "three";
@@ -10,6 +10,7 @@ interface ObjectsRendererProps extends ObjectReadyProps {
10
10
  onObjectsReady?: () => void;
11
11
  handleObjectClick?: (object: CreatedObjectSettings, ref: Object3D, event: ThreeEvent<MouseEvent>) => void;
12
12
  sequences?: AnimationSequence[];
13
+ actionSequences?: ActionSequence[];
13
14
  }
14
15
  declare const ObjectsRenderer: React.FC<ObjectsRendererProps>;
15
16
  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,iBAAiB,EAAE,qBAAqB,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAI1I,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;IAChC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;CACtC;AAGD,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA2ClD,CAAC;AAEH,eAAe,eAAe,CAAC"}
@@ -4,7 +4,7 @@ import { buildObjectTree } from '@3driseai/3drise-core';
4
4
  import ObjectNode from './ObjectNode.js';
5
5
  import useInteraction from '../hooks/useInteraction.js';
6
6
  import { useObjectReady } from '../hooks/useObjectReady.js';
7
- const ObjectsRenderer = memo(({ cameraSettings, createdObjects, generalObjectSettings, onObjectsReady, onObjectReady, onObjectDispose, handleObjectClick, sequences = [], }) => {
7
+ const ObjectsRenderer = memo(({ cameraSettings, createdObjects, generalObjectSettings, onObjectsReady, onObjectReady, onObjectDispose, handleObjectClick, sequences = [], actionSequences = [], }) => {
8
8
  const groupRef = useRef(null);
9
9
  const objectsTree = useMemo(() => buildObjectTree(createdObjects), [createdObjects]);
10
10
  const readyObjectsCount = useRef(0);
@@ -32,6 +32,7 @@ const ObjectsRenderer = memo(({ cameraSettings, createdObjects, generalObjectSet
32
32
  const { executeInteraction } = useInteraction({
33
33
  cameraSettings,
34
34
  sequences,
35
+ actionSequences,
35
36
  });
36
37
  const handleObjectClickHandler = (createdObject, ref, event) => {
37
38
  const clickInteractions = filterInteractionsByEvent(createdObject.actions, "click");
@@ -1,9 +1,10 @@
1
+ import type { SceneHandle } from "../api/sceneHandle";
1
2
  import type { CreatedObjectSettings, HtmlElement } from '@3driseai/3drise-core';
2
3
  import React from "react";
3
4
  import { Object3D } from "three";
4
5
  import { type ThreeEvent } from "@react-three/fiber";
5
6
  import type { ObjectReadyProps } from "../types/objectReady";
6
- type ProjectProps = ObjectReadyProps & {
7
+ declare const ProjectLoader: React.ForwardRefExoticComponent<ObjectReadyProps & {
7
8
  projectId: string;
8
9
  loadingIndicator?: React.ReactNode;
9
10
  onObjectClick?: (object: CreatedObjectSettings, ref: Object3D, event: ThreeEvent<MouseEvent>) => void;
@@ -11,7 +12,12 @@ type ProjectProps = ObjectReadyProps & {
11
12
  onElementClick?: (element: HtmlElement) => void;
12
13
  onElementHover?: (element: HtmlElement | null) => void;
13
14
  onSceneInitialized?: () => void;
14
- };
15
- declare const ProjectLoader: React.FC<ProjectProps>;
15
+ /**
16
+ * Called once the project is loaded and its canvas exists, with the handle for
17
+ * driving its actions and animations from your own UI. The same handle is also
18
+ * available through `ref`.
19
+ */
20
+ onSceneReady?: (scene: SceneHandle) => void;
21
+ } & React.RefAttributes<SceneHandle>>;
16
22
  export default ProjectLoader;
17
23
  //# sourceMappingURL=ProjectLoader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectLoader.d.ts","sourceRoot":"","sources":["../../src/components/ProjectLoader.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGhF,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,KAAK,YAAY,GAAG,gBAAgB,GAAG;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACnC,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;AAGF,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAsDzC,CAAC;AACF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"ProjectLoader.d.ts","sourceRoot":"","sources":["../../src/components/ProjectLoader.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItD,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGhF,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAkB7D,QAAA,MAAM,aAAa;eAhBJ,MAAM;uBACE,KAAK,CAAC,SAAS;oBAClB,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI;oBACrF,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,KAAK,IAAI;qBACrD,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI;qBAC9B,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI;yBACjC,MAAM,IAAI;IAC/B;;;;OAIG;mBACY,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI;qCA0D7C,CAAC;AAEH,eAAe,aAAa,CAAC"}
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useState } from "react";
2
+ import { forwardRef, useEffect, useState } from "react";
3
3
  import { dataCenterServer } from '../constants.js';
4
4
  import SceneBuilder from "./SceneBuilder.js";
5
5
  import { loadAssets, } from "@3driseai/3drise-core";
6
6
  import LoadingIndicator from "./LoadingIndicator.js";
7
7
  import { useMeshController } from "../hooks/useMeshController.js";
8
- const ProjectLoader = ({ projectId, onObjectClick, onObjectHover, onElementClick, onElementHover, onSceneInitialized, onObjectReady, onObjectDispose, loadingIndicator = _jsx(LoadingIndicator, { text: "Loading project...", fullScreen: true, animate: true }) }) => {
8
+ const ProjectLoader = forwardRef(({ projectId, onObjectClick, onObjectHover, onElementClick, onElementHover, onSceneInitialized, onSceneReady, onObjectReady, onObjectDispose, loadingIndicator = _jsx(LoadingIndicator, { text: "Loading project...", fullScreen: true, animate: true }) }, ref) => {
9
9
  const [project, setProject] = useState(null);
10
10
  const meshController = useMeshController();
11
11
  useEffect(() => {
@@ -56,6 +56,7 @@ const ProjectLoader = ({ projectId, onObjectClick, onObjectHover, onElementClick
56
56
  flexDirection: 'column', gap: '1rem'
57
57
  }, children: loadingIndicator });
58
58
  }
59
- return _jsx(_Fragment, { children: _jsx(SceneBuilder, { project: project, onSceneInitialized: onSceneInitialized, onUiElementClick: onElementClick, onUiElementHover: onElementHover, onObjectClick: onObjectClick, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }) });
60
- };
59
+ return _jsx(_Fragment, { children: _jsx(SceneBuilder, { ref: ref, project: project, onSceneReady: onSceneReady, onSceneInitialized: onSceneInitialized, onUiElementClick: onElementClick, onUiElementHover: onElementHover, onObjectClick: onObjectClick, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }) });
60
+ });
61
+ ProjectLoader.displayName = 'ProjectLoader';
61
62
  export default ProjectLoader;
@@ -1,6 +1,14 @@
1
+ import { type SceneHandle } from "../api/sceneHandle";
1
2
  import type { SceneBuilderProps } from '@3driseai/3drise-core';
2
3
  import React from "react";
3
4
  import type { ObjectReadyProps } from "../types/objectReady";
4
- declare const SceneBuilder: React.FC<SceneBuilderProps & ObjectReadyProps>;
5
+ export type SceneBuilderViewerProps = SceneBuilderProps & ObjectReadyProps & {
6
+ /** Called once the canvas exists, with the handle for driving this project's actions and animations. */
7
+ onSceneReady?: (scene: SceneHandle) => void;
8
+ };
9
+ declare const SceneBuilder: React.ForwardRefExoticComponent<SceneBuilderProps & ObjectReadyProps & {
10
+ /** Called once the canvas exists, with the handle for driving this project's actions and animations. */
11
+ onSceneReady?: (scene: SceneHandle) => void;
12
+ } & React.RefAttributes<SceneHandle>>;
5
13
  export default SceneBuilder;
6
14
  //# sourceMappingURL=SceneBuilder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SceneBuilder.d.ts","sourceRoot":"","sources":["../../src/components/SceneBuilder.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAQ/D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,GAAG,gBAAgB,CAuIhE,CAAC;AACF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"SceneBuilder.d.ts","sourceRoot":"","sources":["../../src/components/SceneBuilder.tsx"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,WAAW,EAA0B,MAAM,oBAAoB,CAAC;AAGjG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAQ/D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,GAAG,gBAAgB,GAAG;IACzE,wGAAwG;IACxG,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;CAC/C,CAAC;AAEF,QAAA,MAAM,YAAY;IAJd,wGAAwG;mBACzF,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI;qCAkJ7C,CAAC;AAEH,eAAe,YAAY,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState } from "react";
2
+ import { forwardRef, useImperativeHandle, useMemo, useRef, useState } from "react";
3
+ import { createSceneHandle } from "../api/sceneHandle.js";
3
4
  import { Canvas } from "@react-three/fiber";
4
5
  import { LIGHTING_PRESETS, SceneStore } from "@3driseai/3drise-core";
5
6
  import { NoToneMapping } from "three";
@@ -9,7 +10,7 @@ import CameraController from "./CameraController.js";
9
10
  import ObjectsRenderer from "./ObjectsRenderer.js";
10
11
  import CursorController from "./cursor/CursorController.js";
11
12
  import { Physics } from "@react-three/rapier";
12
- const SceneBuilder = ({ project, width = "100%", height = "100vh", style = {}, className = "", onSceneInitialized, onUiElementClick, onObjectClick, onObjectReady, onObjectDispose, }) => {
13
+ const SceneBuilder = forwardRef(({ project, width = "100%", height = "100vh", style = {}, className = "", onSceneInitialized, onSceneReady, onUiElementClick, onObjectClick, onObjectReady, onObjectDispose, }, ref) => {
13
14
  const sceneSettings = (project.sceneSettingsData || {});
14
15
  // const meshController = useMeshController();
15
16
  const [isThreeJsMounted, setIsThreeJsMounted] = useState(false);
@@ -41,6 +42,13 @@ const SceneBuilder = ({ project, width = "100%", height = "100vh", style = {}, c
41
42
  }
42
43
  });
43
44
  const animationSequences = project.animationSequences || [];
45
+ const actionSequences = project.actionSequences || [];
46
+ // The external control handle (see api/sceneHandle). Built once; reads the
47
+ // current project lists through a ref, so it never goes stale.
48
+ const handleSource = useRef({ actions: actionSequences, animations: animationSequences });
49
+ handleSource.current = { actions: actionSequences, animations: animationSequences };
50
+ const sceneHandle = useMemo(() => createSceneHandle(() => handleSource.current), []);
51
+ useImperativeHandle(ref, () => sceneHandle, [sceneHandle]);
44
52
  const sceneObjects = project.sceneObjects || sceneSettings.scene?.objectSettings || [];
45
53
  const modelObjects = sceneObjects.filter((obj) => obj.type === "model");
46
54
  const meshObjects = sceneObjects.filter((obj) => obj.type === "mesh");
@@ -131,6 +139,8 @@ const SceneBuilder = ({ project, width = "100%", height = "100vh", style = {}, c
131
139
  if (onSceneInitialized) {
132
140
  onSceneInitialized();
133
141
  }
134
- }, children: _jsxs(Physics, { gravity: physicsSettings.gravity, paused: !physicsSettings.enabled, debug: physicsSettings.debug, children: [_jsx(LightsManager, { config: lighting[0], onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }), environment && _jsx(EnvironmentManager, { environment: environment, timeSettings: timeSettings, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }), _jsx(CameraController, { settings: camera, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }), _jsx(ObjectsRenderer, { cameraSettings: camera, generalObjectSettings: generalObjectSettings, createdObjects: sceneObjects, onObjectsReady: undefined, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose, sequences: animationSequences, handleObjectClick: onObjectClick ? (object, ref, event) => onObjectClick(object, ref, event) : undefined }), _jsx(CursorController, { effects: project.cursor?.effects, clickActions: project.cursor?.clickActions, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose })] }) }) }));
135
- };
142
+ onSceneReady?.(sceneHandle);
143
+ }, children: _jsxs(Physics, { gravity: physicsSettings.gravity, paused: !physicsSettings.enabled, debug: physicsSettings.debug, children: [_jsx(LightsManager, { config: lighting[0], onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }), environment && _jsx(EnvironmentManager, { environment: environment, timeSettings: timeSettings, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }), _jsx(CameraController, { settings: camera, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }), _jsx(ObjectsRenderer, { cameraSettings: camera, generalObjectSettings: generalObjectSettings, createdObjects: sceneObjects, onObjectsReady: undefined, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose, sequences: animationSequences, actionSequences: actionSequences, handleObjectClick: onObjectClick ? (object, ref, event) => onObjectClick(object, ref, event) : undefined }), _jsx(CursorController, { effects: project.cursor?.effects, clickActions: project.cursor?.clickActions, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose })] }) }) }));
144
+ });
145
+ SceneBuilder.displayName = 'SceneBuilder';
136
146
  export default SceneBuilder;
@@ -1 +1 @@
1
- {"version":3,"file":"Stars.d.ts","sourceRoot":"","sources":["../../src/components/Stars.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EAAE,cAAc,EAA4C,MAAM,OAAO,CAAC;AAQjF,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,MAAM,WAAW,UAAW,SAAQ,gBAAgB;IAChD,QAAQ,EAAE,qBAAqB,CAAC;IAChC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAOD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAuDnE;AAYD,QAAA,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA2K/B,CAAC;AACF,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"Stars.d.ts","sourceRoot":"","sources":["../../src/components/Stars.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EAAE,cAAc,EAA4C,MAAM,OAAO,CAAC;AAQjF,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,MAAM,WAAW,UAAW,SAAQ,gBAAgB;IAChD,QAAQ,EAAE,qBAAqB,CAAC;IAChC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAOD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAuDnE;AAYD,QAAA,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA4K/B,CAAC;AACF,eAAe,KAAK,CAAC"}
@@ -135,7 +135,8 @@ const Stars = ({ settings, timeSettings, sunSystemEnabled = false, onObjectReady
135
135
  pointsRef.current.visible = toProps.visible;
136
136
  }
137
137
  // color — existing path
138
- setDuration(event.step.duration);
138
+ // speed = 1 / duration below; keep an instant (0) step finite.
139
+ setDuration(Math.max(event.step.duration ?? 1, 0.001));
139
140
  if (toProps.color !== undefined) {
140
141
  setColors({
141
142
  baseColor: fromProps.color,
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import type { AnimationOptions, CreatedObjectSettings, MouseMoveDomain } from '@3driseai/3drise-core';
3
+ import type { ObjectReadyProps } from '../../types/objectReady';
4
+ export type CandleProps = ObjectReadyProps & {
5
+ /** Scene object id: the light controller finds the live-edit handle by it. */
6
+ id?: string;
7
+ config: Record<string, any>;
8
+ animations?: AnimationOptions[];
9
+ mouseMove?: MouseMoveDomain;
10
+ settings: CreatedObjectSettings | Record<string, any>;
11
+ };
12
+ declare const Candle: React.FC<CandleProps>;
13
+ export default Candle;
14
+ //# sourceMappingURL=Candle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Candle.d.ts","sourceRoot":"","sources":["../../../src/components/candle/Candle.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAItG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAQhE,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG;IACzC,8EAA8E;IAC9E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAChC,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,QAAQ,EAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACzD,CAAC;AAYF,QAAA,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CA+RjC,CAAC;AAKF,eAAe,MAAM,CAAC"}