@3driseai/3drise-viewer 0.1.25 → 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 (116) 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 +56 -17
  32. package/dist/api/sceneHandle.d.ts.map +1 -1
  33. package/dist/api/sceneHandle.js +154 -77
  34. package/dist/components/CameraController.d.ts.map +1 -1
  35. package/dist/components/CameraController.js +0 -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.js +1 -1
  41. package/dist/components/ObjectsRenderer.d.ts +4 -1
  42. package/dist/components/ObjectsRenderer.d.ts.map +1 -1
  43. package/dist/components/ObjectsRenderer.js +23 -3
  44. package/dist/components/Ocean.d.ts.map +1 -1
  45. package/dist/components/Ocean.js +0 -63
  46. package/dist/components/SceneBuilder.d.ts.map +1 -1
  47. package/dist/components/SceneBuilder.js +19 -4
  48. package/dist/components/SkyController.d.ts.map +1 -1
  49. package/dist/components/SkyController.js +0 -39
  50. package/dist/components/Stars.d.ts.map +1 -1
  51. package/dist/components/Stars.js +3 -47
  52. package/dist/components/terrain/TerrainSurface.d.ts.map +1 -1
  53. package/dist/components/terrain/TerrainSurface.js +0 -5
  54. package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts.map +1 -1
  55. package/dist/components/volumetricClouds/VolumetricCloudsPass.js +0 -6
  56. package/dist/hooks/index.d.ts +0 -2
  57. package/dist/hooks/index.d.ts.map +1 -1
  58. package/dist/hooks/index.js +0 -2
  59. package/dist/hooks/useInteraction.d.ts +6 -7
  60. package/dist/hooks/useInteraction.d.ts.map +1 -1
  61. package/dist/hooks/useInteraction.js +87 -268
  62. package/dist/hooks/useObjectAnimation.d.ts.map +1 -1
  63. package/dist/hooks/useObjectAnimation.js +0 -2
  64. package/dist/hooks/useOceanMaterial.d.ts.map +1 -1
  65. package/dist/hooks/useOceanMaterial.js +0 -5
  66. package/dist/hooks/useRuntimeSettings.d.ts +1 -1
  67. package/dist/hooks/useRuntimeSettings.js +1 -1
  68. package/dist/index.d.ts +5 -2
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +3 -0
  71. package/dist/interactions/index.d.ts +3 -0
  72. package/dist/interactions/index.d.ts.map +1 -0
  73. package/dist/interactions/index.js +1 -0
  74. package/dist/interactions/runner.d.ts +9 -0
  75. package/dist/interactions/runner.d.ts.map +1 -0
  76. package/dist/interactions/runner.js +23 -0
  77. package/dist/operations/catalogue/displayImage.d.ts +3 -0
  78. package/dist/operations/catalogue/displayImage.d.ts.map +1 -0
  79. package/dist/operations/catalogue/displayImage.js +39 -0
  80. package/dist/operations/catalogue/fade.d.ts +3 -0
  81. package/dist/operations/catalogue/fade.d.ts.map +1 -0
  82. package/dist/operations/catalogue/fade.js +44 -0
  83. package/dist/operations/catalogue/focus.d.ts +3 -0
  84. package/dist/operations/catalogue/focus.d.ts.map +1 -0
  85. package/dist/operations/catalogue/focus.js +22 -0
  86. package/dist/operations/catalogue/glow.d.ts +3 -0
  87. package/dist/operations/catalogue/glow.d.ts.map +1 -0
  88. package/dist/operations/catalogue/glow.js +49 -0
  89. package/dist/operations/catalogue/materialFx.d.ts +6 -0
  90. package/dist/operations/catalogue/materialFx.d.ts.map +1 -0
  91. package/dist/operations/catalogue/materialFx.js +13 -0
  92. package/dist/operations/catalogue/moveToFront.d.ts +3 -0
  93. package/dist/operations/catalogue/moveToFront.d.ts.map +1 -0
  94. package/dist/operations/catalogue/moveToFront.js +25 -0
  95. package/dist/operations/catalogue/visibility.d.ts +3 -0
  96. package/dist/operations/catalogue/visibility.d.ts.map +1 -0
  97. package/dist/operations/catalogue/visibility.js +24 -0
  98. package/dist/operations/catalogue/zoom.d.ts +3 -0
  99. package/dist/operations/catalogue/zoom.d.ts.map +1 -0
  100. package/dist/operations/catalogue/zoom.js +32 -0
  101. package/dist/operations/index.d.ts +5 -0
  102. package/dist/operations/index.d.ts.map +1 -0
  103. package/dist/operations/index.js +4 -0
  104. package/dist/operations/registry.d.ts +11 -0
  105. package/dist/operations/registry.d.ts.map +1 -0
  106. package/dist/operations/registry.js +21 -0
  107. package/dist/operations/runtime.d.ts +22 -0
  108. package/dist/operations/runtime.d.ts.map +1 -0
  109. package/dist/operations/runtime.js +161 -0
  110. package/dist/operations/types.d.ts +96 -0
  111. package/dist/operations/types.d.ts.map +1 -0
  112. package/dist/operations/types.js +3 -0
  113. package/dist/operations/useOperationsRuntime.d.ts +3 -0
  114. package/dist/operations/useOperationsRuntime.d.ts.map +1 -0
  115. package/dist/operations/useOperationsRuntime.js +31 -0
  116. package/package.json +2 -2
@@ -0,0 +1,3 @@
1
+ declare const _default: import("..").OperationDefinition;
2
+ export default _default;
3
+ //# sourceMappingURL=focus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focus.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/focus.ts"],"names":[],"mappings":";AAGA,wBAmBG"}
@@ -0,0 +1,22 @@
1
+ import { Vector3 } from 'three';
2
+ import { DEFAULT_EASE, defineOperation } from '../types.js';
3
+ export default defineOperation({
4
+ value: 'focus',
5
+ label: 'Look at',
6
+ description: 'Turn the camera to face the target, without moving it',
7
+ multi: false,
8
+ toggles: true,
9
+ usableIn: ['interaction', 'action'],
10
+ exclusive: { group: 'camera', release: 'handover' },
11
+ params: {
12
+ duration: { type: 'number', label: 'Duration', default: 1, min: 0, max: 10, step: 0.05, unit: 's' },
13
+ },
14
+ apply(target, p, ctx) {
15
+ ctx.saveCameraHome();
16
+ const at = target.getWorldPosition(new Vector3());
17
+ void ctx.tools.animateCamera({}, Number(p.duration), DEFAULT_EASE, [at.x, at.y, at.z]);
18
+ },
19
+ revert(_target, p, ctx) {
20
+ ctx.restoreCameraHome(Number(p.duration), DEFAULT_EASE);
21
+ },
22
+ });
@@ -0,0 +1,3 @@
1
+ declare const _default: import("..").OperationDefinition;
2
+ export default _default;
3
+ //# sourceMappingURL=glow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glow.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/glow.ts"],"names":[],"mappings":";AAMA,wBAyCG"}
@@ -0,0 +1,49 @@
1
+ import { gsap } from 'gsap';
2
+ import { defineOperation } from '../types.js';
3
+ import { forEachMaterial, isLit, toColor } from './materialFx.js';
4
+ const KEY = '__opGlow';
5
+ export default defineOperation({
6
+ value: 'glow',
7
+ label: 'Glow',
8
+ description: 'Light the targets up with an emissive glow',
9
+ multi: true,
10
+ toggles: true,
11
+ usableIn: ['interaction', 'action'],
12
+ params: {
13
+ color: { type: 'color', label: 'Colour', default: '#3380ff' },
14
+ intensity: { type: 'number', label: 'Intensity', default: 3, min: 0, max: 20, step: 0.1 },
15
+ duration: { type: 'number', label: 'Duration', default: 0.4, min: 0, max: 10, step: 0.05, unit: 's' },
16
+ },
17
+ apply(target, p) {
18
+ const color = toColor(String(p.color));
19
+ forEachMaterial(target, (mat) => {
20
+ if (!isLit(mat))
21
+ return;
22
+ if (!mat.userData[KEY]) {
23
+ mat.userData[KEY] = { emissive: mat.emissive.getHex(), intensity: mat.emissiveIntensity, toneMapped: mat.toneMapped };
24
+ }
25
+ mat.toneMapped = false;
26
+ gsap.killTweensOf(mat);
27
+ gsap.killTweensOf(mat.emissive);
28
+ gsap.to(mat, { emissiveIntensity: Number(p.intensity), duration: Number(p.duration), ease: 'power2.out' });
29
+ gsap.to(mat.emissive, { r: color.r, g: color.g, b: color.b, duration: Number(p.duration), ease: 'power2.out' });
30
+ });
31
+ },
32
+ revert(target, p) {
33
+ forEachMaterial(target, (mat) => {
34
+ if (!isLit(mat))
35
+ return;
36
+ const orig = mat.userData[KEY];
37
+ if (!orig)
38
+ return;
39
+ const c = toColor('#000000').setHex(orig.emissive);
40
+ gsap.killTweensOf(mat);
41
+ gsap.killTweensOf(mat.emissive);
42
+ gsap.to(mat, {
43
+ emissiveIntensity: orig.intensity, duration: Number(p.duration), ease: 'power2.in',
44
+ onComplete: () => { mat.toneMapped = orig.toneMapped; delete mat.userData[KEY]; },
45
+ });
46
+ gsap.to(mat.emissive, { r: c.r, g: c.g, b: c.b, duration: Number(p.duration), ease: 'power2.in' });
47
+ });
48
+ },
49
+ });
@@ -0,0 +1,6 @@
1
+ import { Color, MeshStandardMaterial } from 'three';
2
+ import type { Material, Object3D } from 'three';
3
+ export declare function forEachMaterial(root: Object3D, fn: (mat: Material) => void): void;
4
+ export declare const isLit: (m: Material) => m is MeshStandardMaterial;
5
+ export declare const toColor: (hex: string) => Color;
6
+ //# sourceMappingURL=materialFx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"materialFx.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/materialFx.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAwB,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEhD,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,QAM1E;AAED,eAAO,MAAM,KAAK,GAAI,GAAG,QAAQ,KAAG,CAAC,IAAI,oBACiC,CAAC;AAE3E,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,UAAmB,CAAC"}
@@ -0,0 +1,13 @@
1
+ // Material helpers shared by glow / fade. Originals are kept on the material's
2
+ // userData under op-specific keys, so glow and fade can stack and revert exactly.
3
+ import { Color, MeshPhysicalMaterial, MeshStandardMaterial } from 'three';
4
+ export function forEachMaterial(root, fn) {
5
+ root.traverse((child) => {
6
+ if (!child.isMesh && !child.isPoints && !child.isLine)
7
+ return;
8
+ const mats = Array.isArray(child.material) ? child.material : [child.material];
9
+ mats.forEach((m) => m && fn(m));
10
+ });
11
+ }
12
+ export const isLit = (m) => m instanceof MeshStandardMaterial || m instanceof MeshPhysicalMaterial;
13
+ export const toColor = (hex) => new Color(hex);
@@ -0,0 +1,3 @@
1
+ declare const _default: import("..").OperationDefinition;
2
+ export default _default;
3
+ //# sourceMappingURL=moveToFront.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moveToFront.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/moveToFront.ts"],"names":[],"mappings":";AAEA,wBAuBG"}
@@ -0,0 +1,25 @@
1
+ import { DEFAULT_EASE, defineOperation } from '../types.js';
2
+ export default defineOperation({
3
+ value: 'moveToFront',
4
+ label: 'Bring to front',
5
+ description: 'Bring the target in front of the camera',
6
+ multi: false,
7
+ toggles: true,
8
+ usableIn: ['interaction', 'action'],
9
+ exclusive: { group: 'front', release: 'revert' },
10
+ params: {
11
+ distance: { type: 'number', label: 'Distance', default: 2, min: 0.1, max: 100, step: 0.1 },
12
+ width: { type: 'number', label: 'Scale X', default: 6, min: 0.01, max: 100, step: 0.1 },
13
+ height: { type: 'number', label: 'Scale Y', default: 4, min: 0.01, max: 100, step: 0.1 },
14
+ duration: { type: 'number', label: 'Duration', default: 1, min: 0, max: 10, step: 0.05, unit: 's' },
15
+ },
16
+ apply(target, p, ctx) {
17
+ ctx.tools.moveToFront(target, {
18
+ distance: Number(p.distance), scale: [Number(p.width), Number(p.height)],
19
+ duration: Number(p.duration), ease: DEFAULT_EASE,
20
+ });
21
+ },
22
+ revert(target, p, ctx) {
23
+ ctx.tools.restoreTransform(target, { duration: Number(p.duration), ease: DEFAULT_EASE });
24
+ },
25
+ });
@@ -0,0 +1,3 @@
1
+ declare const _default: import("..").OperationDefinition;
2
+ export default _default;
3
+ //# sourceMappingURL=visibility.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/visibility.ts"],"names":[],"mappings":";AAIA,wBAmBG"}
@@ -0,0 +1,24 @@
1
+ import { defineOperation } from '../types.js';
2
+ const KEY = '__opVisible';
3
+ export default defineOperation({
4
+ value: 'visibility',
5
+ label: 'Show / hide',
6
+ description: 'Hide (or show) the targets instantly',
7
+ multi: true,
8
+ toggles: true,
9
+ usableIn: ['interaction', 'action'],
10
+ params: {
11
+ mode: { type: 'select', label: 'Make it', default: 'hide', options: [{ value: 'hide', label: 'Hidden' }, { value: 'show', label: 'Visible' }] },
12
+ },
13
+ apply(target, p) {
14
+ if (target.userData[KEY] === undefined)
15
+ target.userData[KEY] = target.visible;
16
+ target.visible = p.mode === 'show';
17
+ },
18
+ revert(target) {
19
+ if (target.userData[KEY] === undefined)
20
+ return;
21
+ target.visible = target.userData[KEY];
22
+ delete target.userData[KEY];
23
+ },
24
+ });
@@ -0,0 +1,3 @@
1
+ declare const _default: import("..").OperationDefinition;
2
+ export default _default;
3
+ //# sourceMappingURL=zoom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zoom.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/zoom.ts"],"names":[],"mappings":";AAGA,wBA2BG"}
@@ -0,0 +1,32 @@
1
+ import { Quaternion, Vector3 } from 'three';
2
+ import { DEFAULT_EASE, defineOperation } from '../types.js';
3
+ export default defineOperation({
4
+ value: 'zoom',
5
+ label: 'Zoom to',
6
+ description: 'Fly the camera close to the target, facing it',
7
+ multi: false,
8
+ toggles: true,
9
+ usableIn: ['interaction', 'action'],
10
+ exclusive: { group: 'camera', release: 'handover' },
11
+ params: {
12
+ distance: { type: 'number', label: 'Distance', default: 2, min: 0.1, max: 100, step: 0.1 },
13
+ duration: { type: 'number', label: 'Duration', default: 1, min: 0, max: 10, step: 0.05, unit: 's' },
14
+ },
15
+ apply(target, p, ctx) {
16
+ const pose = ctx.tools.cameraPose();
17
+ if (!pose)
18
+ return;
19
+ ctx.saveCameraHome();
20
+ const camPos = new Vector3(...pose.position);
21
+ const at = target.getWorldPosition(new Vector3());
22
+ // Stand in front of the target, on the side the camera is already on.
23
+ const forward = new Vector3(0, 0, 1).applyQuaternion(target.getWorldQuaternion(new Quaternion()));
24
+ if (forward.dot(camPos.clone().sub(at).normalize()) < 0)
25
+ forward.negate();
26
+ const to = at.clone().add(forward.multiplyScalar(Number(p.distance)));
27
+ void ctx.tools.animateCamera({ position: [to.x, to.y, to.z] }, Number(p.duration), DEFAULT_EASE, [at.x, at.y, at.z]);
28
+ },
29
+ revert(_target, p, ctx) {
30
+ ctx.restoreCameraHome(Number(p.duration), DEFAULT_EASE);
31
+ },
32
+ });
@@ -0,0 +1,5 @@
1
+ export * from './types';
2
+ export { OPERATIONS, getOperation, operationsFor, resolveParams } from './registry';
3
+ export { runEffect, applyOperation, revertOperation, isOperationOn, resolveEffectTargets, runActionEffects, areActionEffectsOn, subscribeActionEffects, registerOperationTools, } from './runtime';
4
+ export { useOperationsRuntime } from './useOperationsRuntime';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/operations/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,EACH,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,oBAAoB,EAC/E,gBAAgB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,sBAAsB,GACvF,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './types.js';
2
+ export { OPERATIONS, getOperation, operationsFor, resolveParams } from './registry.js';
3
+ export { runEffect, applyOperation, revertOperation, isOperationOn, resolveEffectTargets, runActionEffects, areActionEffectsOn, subscribeActionEffects, registerOperationTools, } from './runtime.js';
4
+ export { useOperationsRuntime } from './useOperationsRuntime.js';
@@ -0,0 +1,11 @@
1
+ import type { OperationName } from '@3driseai/3drise-core';
2
+ import type { OperationDefinition, OperationParams, OperationSource } from './types';
3
+ export declare const OPERATIONS: OperationDefinition[];
4
+ export declare const getOperation: (name: OperationName) => OperationDefinition | undefined;
5
+ /** Operations offered in a context (gallery-only ones only on gallery objects). */
6
+ export declare const operationsFor: (source: OperationSource, opts?: {
7
+ gallery?: boolean;
8
+ }) => OperationDefinition[];
9
+ /** Defaults overlaid with the effect's own values (unknown keys dropped). */
10
+ export declare function resolveParams(def: OperationDefinition, overrides?: OperationParams): OperationParams;
11
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/operations/registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AASrF,eAAO,MAAM,UAAU,EAAE,mBAAmB,EAAqE,CAAC;AAIlH,eAAO,MAAM,YAAY,GAAI,MAAM,aAAa,KAAG,mBAAmB,GAAG,SAA6B,CAAC;AAEvG,mFAAmF;AACnF,eAAO,MAAM,aAAa,GAAI,QAAQ,eAAe,EAAE,OAAM;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,KAAG,mBAAmB,EAClB,CAAC;AAE5F,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,GAAG,EAAE,mBAAmB,EAAE,SAAS,CAAC,EAAE,eAAe,GAAG,eAAe,CAOpG"}
@@ -0,0 +1,21 @@
1
+ import glow from './catalogue/glow.js';
2
+ import fade from './catalogue/fade.js';
3
+ import visibility from './catalogue/visibility.js';
4
+ import zoom from './catalogue/zoom.js';
5
+ import focus from './catalogue/focus.js';
6
+ import moveToFront from './catalogue/moveToFront.js';
7
+ import displayImage from './catalogue/displayImage.js';
8
+ export const OPERATIONS = [glow, fade, visibility, zoom, focus, moveToFront, displayImage];
9
+ const byName = new Map(OPERATIONS.map(o => [o.value, o]));
10
+ export const getOperation = (name) => byName.get(name);
11
+ /** Operations offered in a context (gallery-only ones only on gallery objects). */
12
+ export const operationsFor = (source, opts = {}) => OPERATIONS.filter(o => o.usableIn.includes(source) && (!o.galleryOnly || opts.gallery));
13
+ /** Defaults overlaid with the effect's own values (unknown keys dropped). */
14
+ export function resolveParams(def, overrides) {
15
+ const out = {};
16
+ for (const [key, spec] of Object.entries(def.params ?? {})) {
17
+ const v = overrides?.[key];
18
+ out[key] = v === undefined || v === null ? spec.default : v;
19
+ }
20
+ return out;
21
+ }
@@ -0,0 +1,22 @@
1
+ import type { Object3D } from 'three';
2
+ import type { ActionSequence, OperationEffect, OperationName } from '@3driseai/3drise-core';
3
+ import type { OperationDefinition, OperationParams, OperationTools } from './types';
4
+ /** Register the mounted scene's tools. Returns the unregister. */
5
+ export declare function registerOperationTools(t: OperationTools): () => void;
6
+ export declare function isOperationOn(op: OperationName, target: Object3D): boolean;
7
+ export declare function applyOperation(def: OperationDefinition, target: Object3D, params: OperationParams, self?: Object3D | null): boolean;
8
+ export declare function revertOperation(def: OperationDefinition, target: Object3D): boolean;
9
+ /** The objects an effect acts on: 'self', object ids, narrowed to model nodes. */
10
+ export declare function resolveEffectTargets(effect: OperationEffect, self?: Object3D | null): Object3D[];
11
+ /**
12
+ * Run one effect.
13
+ * trigger interactions: toggle when the operation toggles, else apply
14
+ * apply / revert / toggle explicit
15
+ */
16
+ export declare function runEffect(effect: OperationEffect, mode: 'trigger' | 'apply' | 'revert' | 'toggle', self?: Object3D | null): void;
17
+ /** Apply or undo an action's effects directly (the editor's "Try it"). */
18
+ export declare function runActionEffects(action: ActionSequence, mode: 'apply' | 'revert'): void;
19
+ export declare const areActionEffectsOn: (actionId: string) => boolean;
20
+ /** Subscribe to action-effects on/off changes (studio badges). */
21
+ export declare function subscribeActionEffects(fn: () => void): () => void;
22
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/operations/runtime.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEtC,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAgB,MAAM,uBAAuB,CAAC;AAG1G,OAAO,KAAK,EAAoB,mBAAmB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AA2BtG,kEAAkE;AAClE,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,IAAI,CAQpE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAE1E;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,mBAAmB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,CAkBnI;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,mBAAmB,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CASnF;AAED,kFAAkF;AAClF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,GAAG,QAAQ,EAAE,CAahG;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,GAAG,IAAI,CAWhI;AAQD,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAQvF;AAED,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,YAAkC,CAAC;AAEtF,kEAAkE;AAClE,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAGjE"}
@@ -0,0 +1,161 @@
1
+ import { SceneActions, findNodesByName } from '@3driseai/3drise-core';
2
+ import { findById } from '../utils/sceneQuery.js';
3
+ import { getOperation, resolveParams } from './registry.js';
4
+ const active = new Map(); // `${op}:${uuid}`
5
+ const slots = new Map(); // exclusive group → active key
6
+ const toolsStack = [];
7
+ let cameraHome = null;
8
+ const keyOf = (op, target) => `${op}:${target.uuid}`;
9
+ const tools = () => toolsStack[toolsStack.length - 1];
10
+ function context(self) {
11
+ const t = tools();
12
+ if (!t)
13
+ return null;
14
+ return {
15
+ tools: t,
16
+ self,
17
+ saveCameraHome: () => { if (!cameraHome)
18
+ cameraHome = t.cameraPose(); },
19
+ restoreCameraHome: (duration, ease) => {
20
+ const home = cameraHome;
21
+ cameraHome = null;
22
+ if (home)
23
+ void t.animateCamera({ position: home.position }, duration, ease, home.target);
24
+ },
25
+ };
26
+ }
27
+ /** Register the mounted scene's tools. Returns the unregister. */
28
+ export function registerOperationTools(t) {
29
+ toolsStack.push(t);
30
+ ensureActionsSubscription();
31
+ return () => {
32
+ const i = toolsStack.lastIndexOf(t);
33
+ if (i >= 0)
34
+ toolsStack.splice(i, 1);
35
+ if (toolsStack.length === 0) {
36
+ active.clear();
37
+ slots.clear();
38
+ cameraHome = null;
39
+ }
40
+ };
41
+ }
42
+ export function isOperationOn(op, target) {
43
+ return active.has(keyOf(op, target));
44
+ }
45
+ export function applyOperation(def, target, params, self) {
46
+ const ctx = context(self);
47
+ if (!ctx)
48
+ return false;
49
+ const key = keyOf(def.value, target);
50
+ if (def.exclusive) {
51
+ const prevKey = slots.get(def.exclusive.group);
52
+ if (prevKey && prevKey !== key) {
53
+ const prev = active.get(prevKey);
54
+ active.delete(prevKey);
55
+ const prevDef = prev && getOperation(prev.op);
56
+ // `revert` puts the previous one back; `handover` leaves it to the new one.
57
+ if (prev && prevDef?.revert && def.exclusive.release === 'revert')
58
+ prevDef.revert(prev.target, prev.params, ctx);
59
+ }
60
+ slots.set(def.exclusive.group, key);
61
+ }
62
+ void def.apply(target, params, ctx);
63
+ if (def.revert)
64
+ active.set(key, { op: def.value, target, params });
65
+ return true;
66
+ }
67
+ export function revertOperation(def, target) {
68
+ const key = keyOf(def.value, target);
69
+ const entry = active.get(key);
70
+ const ctx = context();
71
+ if (!entry || !ctx || !def.revert)
72
+ return false;
73
+ active.delete(key);
74
+ if (def.exclusive && slots.get(def.exclusive.group) === key)
75
+ slots.delete(def.exclusive.group);
76
+ def.revert(target, entry.params, ctx);
77
+ return true;
78
+ }
79
+ /** The objects an effect acts on: 'self', object ids, narrowed to model nodes. */
80
+ export function resolveEffectTargets(effect, self) {
81
+ const out = [];
82
+ for (const t of effect.targets ?? []) {
83
+ const root = t === 'self' ? self : findById(t);
84
+ if (!root)
85
+ continue;
86
+ const names = t === 'self' ? undefined : effect.meshNames?.[t];
87
+ if (names?.length) {
88
+ for (const name of names)
89
+ out.push(...findNodesByName(root, name).filter(n => n !== root));
90
+ }
91
+ else {
92
+ out.push(root);
93
+ }
94
+ }
95
+ return out;
96
+ }
97
+ /**
98
+ * Run one effect.
99
+ * trigger interactions: toggle when the operation toggles, else apply
100
+ * apply / revert / toggle explicit
101
+ */
102
+ export function runEffect(effect, mode, self) {
103
+ const def = getOperation(effect.operation);
104
+ if (!def)
105
+ return;
106
+ const targets = resolveEffectTargets(effect, self);
107
+ const params = resolveParams(def, effect.params);
108
+ for (const target of def.multi ? targets : targets.slice(0, 1)) {
109
+ const on = isOperationOn(def.value, target);
110
+ const m = mode === 'trigger' ? (def.toggles ? 'toggle' : 'apply') : mode;
111
+ if (m === 'revert' || (m === 'toggle' && on))
112
+ revertOperation(def, target);
113
+ else if (m === 'apply' || m === 'toggle')
114
+ applyOperation(def, target, params, self);
115
+ }
116
+ }
117
+ // ---------------------------------------------------------------- actions
118
+ const actionEffectsOn = new Set();
119
+ const listeners = new Set();
120
+ const notify = () => listeners.forEach(l => { try {
121
+ l();
122
+ }
123
+ catch { /* listener error */ } });
124
+ /** Apply or undo an action's effects directly (the editor's "Try it"). */
125
+ export function runActionEffects(action, mode) {
126
+ const on = actionEffectsOn.has(action.id);
127
+ if (mode === 'apply' && on)
128
+ return;
129
+ if (mode === 'revert' && !on)
130
+ return;
131
+ for (const effect of action.effects ?? [])
132
+ runEffect(effect, mode);
133
+ if (mode === 'apply')
134
+ actionEffectsOn.add(action.id);
135
+ else
136
+ actionEffectsOn.delete(action.id);
137
+ notify();
138
+ }
139
+ export const areActionEffectsOn = (actionId) => actionEffectsOn.has(actionId);
140
+ /** Subscribe to action-effects on/off changes (studio badges). */
141
+ export function subscribeActionEffects(fn) {
142
+ listeners.add(fn);
143
+ return () => { listeners.delete(fn); };
144
+ }
145
+ let unsubscribeActions = null;
146
+ function ensureActionsSubscription() {
147
+ if (unsubscribeActions)
148
+ return;
149
+ unsubscribeActions = SceneActions.onEvent((e) => {
150
+ if (e.type === 'applied') {
151
+ if (e.runEffects)
152
+ runActionEffects(e.action, 'apply');
153
+ }
154
+ else if (e.type === 'reverted') {
155
+ runActionEffects(e.action, 'revert');
156
+ }
157
+ else if (e.type === 'reset') {
158
+ e.actions.forEach(a => runActionEffects(a, 'revert'));
159
+ }
160
+ });
161
+ }
@@ -0,0 +1,96 @@
1
+ import type { Object3D } from 'three';
2
+ import type { OperationName, OperationParamValue, Vector3Array } from '@3driseai/3drise-core';
3
+ /** A parameter the studio shows under the effect, with its default. */
4
+ export type OperationParamSpec = {
5
+ type: 'number';
6
+ label: string;
7
+ default: number;
8
+ min?: number;
9
+ max?: number;
10
+ step?: number;
11
+ unit?: string;
12
+ hint?: string;
13
+ } | {
14
+ type: 'color';
15
+ label: string;
16
+ default: string;
17
+ hint?: string;
18
+ } | {
19
+ type: 'select';
20
+ label: string;
21
+ default: string;
22
+ options: Array<{
23
+ value: string;
24
+ label: string;
25
+ }>;
26
+ hint?: string;
27
+ } | {
28
+ type: 'boolean';
29
+ label: string;
30
+ default: boolean;
31
+ hint?: string;
32
+ };
33
+ export type OperationParams = Record<string, OperationParamValue>;
34
+ export type OperationSource = 'interaction' | 'action';
35
+ /** Scene tools the runtime hands an operation (built from the viewer's hooks). */
36
+ export interface OperationTools {
37
+ /** Animate the camera; `lookAt` moves the orbit target. */
38
+ animateCamera: (to: {
39
+ position?: Vector3Array;
40
+ }, duration: number, ease: string, lookAt?: Vector3Array) => Promise<void>;
41
+ /** Where the camera is and looks right now. */
42
+ cameraPose: () => {
43
+ position: Vector3Array;
44
+ target: Vector3Array;
45
+ } | null;
46
+ moveToFront: (object: Object3D, options: {
47
+ distance: number;
48
+ scale: [number, number];
49
+ duration: number;
50
+ ease: string;
51
+ }) => void;
52
+ restoreTransform: (object: Object3D, options: {
53
+ duration: number;
54
+ ease: string;
55
+ }) => void;
56
+ }
57
+ export interface OperationContext {
58
+ tools: OperationTools;
59
+ /** The object an interaction is on (interactions only). */
60
+ self?: Object3D | null;
61
+ /** Remember the camera pose once, before the first camera operation. */
62
+ saveCameraHome: () => void;
63
+ /** Fly back to the remembered pose and forget it. */
64
+ restoreCameraHome: (duration: number, ease: string) => void;
65
+ }
66
+ export interface OperationDefinition {
67
+ value: OperationName;
68
+ label: string;
69
+ /** One line for the studio (tooltip). */
70
+ description: string;
71
+ /** More than one target allowed. */
72
+ multi: boolean;
73
+ /** An interaction triggered again undoes it. */
74
+ toggles: boolean;
75
+ /** Where the operation can be used. */
76
+ usableIn: OperationSource[];
77
+ /** Only on gallery objects. */
78
+ galleryOnly?: boolean;
79
+ /**
80
+ * One target of this group is "on" at a time, scene-wide. Applying another:
81
+ * `revert` undoes the previous one first (bring to front), `handover` just
82
+ * takes over (camera moves — the remembered home pose stays).
83
+ */
84
+ exclusive?: {
85
+ group: string;
86
+ release: 'revert' | 'handover';
87
+ };
88
+ params?: Record<string, OperationParamSpec>;
89
+ apply: (target: Object3D, params: OperationParams, ctx: OperationContext) => void | Promise<void>;
90
+ /** No revert = one-way (applies only). */
91
+ revert?: (target: Object3D, params: OperationParams, ctx: OperationContext) => void;
92
+ }
93
+ /** Type helper for catalogue files. */
94
+ export declare const defineOperation: (def: OperationDefinition) => OperationDefinition;
95
+ export declare const DEFAULT_EASE = "power2.out";
96
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/operations/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Type helper for catalogue files. */
2
+ export const defineOperation = (def) => def;
3
+ export const DEFAULT_EASE = 'power2.out';
@@ -0,0 +1,3 @@
1
+ import type { CameraState } from '@3driseai/3drise-core';
2
+ export declare function useOperationsRuntime(cameraSettings: CameraState): void;
3
+ //# sourceMappingURL=useOperationsRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useOperationsRuntime.d.ts","sourceRoot":"","sources":["../../src/operations/useOperationsRuntime.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAgB,MAAM,uBAAuB,CAAC;AAQvE,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,WAAW,QAuB/D"}
@@ -0,0 +1,31 @@
1
+ // Mounts the operations runtime on the scene: builds the scene tools from the
2
+ // viewer's hooks and registers them. Called once, in ObjectsRenderer.
3
+ import { useEffect, useRef } from 'react';
4
+ import cameraManager from '../utils/CameraSingleton.js';
5
+ import useCameraAnimation from '../hooks/useCameraAnimation.js';
6
+ import { useFrameAnimations } from '../hooks/useFrameAnimations.js';
7
+ import { useOrbitControls } from '../hooks/useOrbitControls.js';
8
+ import { registerOperationTools } from './runtime.js';
9
+ export function useOperationsRuntime(cameraSettings) {
10
+ const { animateCamera } = useCameraAnimation({ autoAnimate: false, defaultDuration: 1, defaultEase: 'power2.out' });
11
+ const { moveToFront, restoreOriginalTransform } = useFrameAnimations(cameraSettings);
12
+ const controls = useOrbitControls();
13
+ // Latest hook functions, read at call time (the registration itself is stable).
14
+ const latest = useRef({ animateCamera, moveToFront, restoreOriginalTransform, controls, cameraSettings });
15
+ latest.current = { animateCamera, moveToFront, restoreOriginalTransform, controls, cameraSettings };
16
+ useEffect(() => registerOperationTools({
17
+ animateCamera: (to, duration, ease, lookAt) => latest.current.animateCamera(to, duration, ease, lookAt),
18
+ cameraPose: () => {
19
+ const pos = cameraManager.getPosition();
20
+ if (!pos)
21
+ return null;
22
+ const t = latest.current.controls?.target;
23
+ const target = t
24
+ ? [t.x, t.y, t.z]
25
+ : latest.current.cameraSettings?.controls?.target ?? [0, 0, 0];
26
+ return { position: [pos.x, pos.y, pos.z], target };
27
+ },
28
+ moveToFront: (object, o) => latest.current.moveToFront(object, o),
29
+ restoreTransform: (object, o) => latest.current.restoreOriginalTransform(object, o),
30
+ }), []);
31
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@3driseai/3drise-viewer",
3
- "version": "0.1.25",
3
+ "version": "0.1.26",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -39,6 +39,6 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@3driseai/3drise-common": "^1.0.1",
42
- "@3driseai/3drise-core": "^1.0.18"
42
+ "@3driseai/3drise-core": "^1.0.19"
43
43
  }
44
44
  }