@3driseai/3drise-viewer 0.1.32 → 0.1.34
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.
- package/dist/animationsV2/ClipsRuntime.d.ts.map +1 -1
- package/dist/animationsV2/ClipsRuntime.js +11 -1
- package/dist/animationsV2/animationLive.d.ts +7 -0
- package/dist/animationsV2/animationLive.d.ts.map +1 -0
- package/dist/animationsV2/animationLive.js +26 -0
- package/dist/animationsV2/appliers.d.ts +8 -0
- package/dist/animationsV2/appliers.d.ts.map +1 -1
- package/dist/animationsV2/appliers.js +61 -0
- package/dist/animationsV2/index.d.ts +1 -0
- package/dist/animationsV2/index.d.ts.map +1 -1
- package/dist/animationsV2/index.js +1 -0
- package/dist/components/AnimatedObject.d.ts.map +1 -1
- package/dist/components/AnimatedObject.js +2 -0
- package/dist/components/CameraController.d.ts.map +1 -1
- package/dist/components/CameraController.js +9 -0
- package/dist/components/CreatedObject.d.ts.map +1 -1
- package/dist/components/CreatedObject.js +4 -1
- package/dist/components/GroupMaterialContext.d.ts +25 -0
- package/dist/components/GroupMaterialContext.d.ts.map +1 -0
- package/dist/components/GroupMaterialContext.js +21 -0
- package/dist/components/ObjectNode.d.ts.map +1 -1
- package/dist/components/ObjectNode.js +13 -2
- package/dist/components/ObjectsRenderer.d.ts.map +1 -1
- package/dist/components/ObjectsRenderer.js +26 -19
- package/dist/components/SceneBuilder.d.ts.map +1 -1
- package/dist/components/SceneBuilder.js +7 -4
- package/dist/components/land/LandPatch.d.ts.map +1 -1
- package/dist/components/land/LandPatch.js +15 -1
- package/dist/hooks/useContinuousEffects.d.ts.map +1 -1
- package/dist/hooks/useContinuousEffects.js +24 -3
- package/dist/hooks/useMaterialApplication.d.ts.map +1 -1
- package/dist/hooks/useMaterialApplication.js +2 -1
- package/dist/hooks/useMaterialUniforms.d.ts +2 -8
- package/dist/hooks/useMaterialUniforms.d.ts.map +1 -1
- package/dist/hooks/useMaterialUniforms.js +18 -6
- package/dist/hooks/useOrbitTargetFollow.d.ts.map +1 -1
- package/dist/hooks/useOrbitTargetFollow.js +6 -4
- package/dist/operations/bake.d.ts +36 -0
- package/dist/operations/bake.d.ts.map +1 -0
- package/dist/operations/bake.js +113 -0
- package/dist/operations/catalogue/physicalHeld.d.ts.map +1 -1
- package/dist/operations/catalogue/physicalHeld.js +6 -0
- package/dist/operations/catalogue/shaderLayers.js +2 -2
- package/dist/operations/catalogue/warmup.d.ts +23 -1
- package/dist/operations/catalogue/warmup.d.ts.map +1 -1
- package/dist/operations/catalogue/warmup.js +200 -12
- package/dist/operations/index.d.ts +3 -1
- package/dist/operations/index.d.ts.map +1 -1
- package/dist/operations/index.js +3 -1
- package/dist/operations/objectEffects.d.ts +15 -1
- package/dist/operations/objectEffects.d.ts.map +1 -1
- package/dist/operations/objectEffects.js +49 -1
- package/dist/operations/runtime.d.ts +17 -9
- package/dist/operations/runtime.d.ts.map +1 -1
- package/dist/operations/runtime.js +71 -18
- package/dist/operations/types.d.ts +5 -0
- package/dist/operations/types.d.ts.map +1 -1
- package/dist/triggers/readiness.d.ts +2 -0
- package/dist/triggers/readiness.d.ts.map +1 -1
- package/dist/triggers/readiness.js +28 -3
- package/dist/utils/stallLog.d.ts +4 -0
- package/dist/utils/stallLog.d.ts.map +1 -0
- package/dist/utils/stallLog.js +88 -0
- package/package.json +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useRef, useEffect } from "react";
|
|
2
|
+
import { animationLiveReader } from "../animationsV2/animationLive.js";
|
|
2
3
|
import { useFrame } from "@react-three/fiber";
|
|
3
|
-
import { animateUniforms, cacheChildrenWithMaterials, handleEdgesAnimations, handleMaterialAnimations, handleMaterialEffects, handleTransformAnimations } from "@3driseai/3drise-core";
|
|
4
|
+
import { AnimationTargetState, animateUniforms, cacheChildrenWithMaterials, handleEdgesAnimations, handleMaterialAnimations, handleMaterialEffects, handleTransformAnimations, targetRootKind } from "@3driseai/3drise-core";
|
|
4
5
|
import usePathAnimation from "./usePathAnimation.js";
|
|
5
6
|
import { resolveObject3D } from "../utils/resolveObject3D.js";
|
|
6
7
|
export const useContinuousEffects = (
|
|
@@ -19,6 +20,9 @@ objectSettings, options = {}, objectSource) => {
|
|
|
19
20
|
const startValuesRef = useRef({});
|
|
20
21
|
// Cache start values for edges animations
|
|
21
22
|
const edgesStartValuesRef = useRef({});
|
|
23
|
+
// Groups / models: rows scoped each / targets (core animationTargets.ts) — one state per object.
|
|
24
|
+
const targetsRef = useRef(null);
|
|
25
|
+
useEffect(() => () => { targetsRef.current?.dispose(); targetsRef.current = null; }, []);
|
|
22
26
|
// Transform keyframes. Effects that move the object (float, sway, spin…) are object
|
|
23
27
|
// effects now (CreatedObject.effects, the operations catalogue) and ride on top of these.
|
|
24
28
|
const transformAnimations = objectSettings?.animations?.transform?.animations || [];
|
|
@@ -74,8 +78,15 @@ objectSettings, options = {}, objectSource) => {
|
|
|
74
78
|
}, [enabled, objectSettings?.animations?.transform?.animations, objectSource, startPathAnimation, stopPathAnimation]);
|
|
75
79
|
useFrame((state, delta) => {
|
|
76
80
|
const object = resolveObject3D(objectSource);
|
|
77
|
-
if (!enabled || !object || !objectSettings)
|
|
81
|
+
if (!enabled || !object || !objectSettings) {
|
|
82
|
+
// Off: the parts the rows moved go back to their rest.
|
|
83
|
+
if (targetsRef.current) {
|
|
84
|
+
targetsRef.current.dispose();
|
|
85
|
+
targetsRef.current = null;
|
|
86
|
+
lastObjectRef.current = null;
|
|
87
|
+
}
|
|
78
88
|
return;
|
|
89
|
+
}
|
|
79
90
|
// Cache the object's materials the first frame we actually see it, and
|
|
80
91
|
// again if the caller swaps the object underneath us.
|
|
81
92
|
if (object !== lastObjectRef.current) {
|
|
@@ -83,7 +94,11 @@ objectSettings, options = {}, objectSource) => {
|
|
|
83
94
|
childrenWithMaterialsRef.current = cacheChildrenWithMaterials(object);
|
|
84
95
|
startValuesRef.current = {};
|
|
85
96
|
edgesStartValuesRef.current = {};
|
|
97
|
+
targetsRef.current?.dispose();
|
|
98
|
+
targetsRef.current = targetRootKind(object) ? new AnimationTargetState(object) : null;
|
|
86
99
|
}
|
|
100
|
+
const targets = targetsRef.current;
|
|
101
|
+
targets?.beginFrame();
|
|
87
102
|
const time = state.clock.getElapsedTime();
|
|
88
103
|
const mouse = state.pointer;
|
|
89
104
|
const currentTime = Date.now();
|
|
@@ -97,7 +112,10 @@ objectSettings, options = {}, objectSource) => {
|
|
|
97
112
|
object,
|
|
98
113
|
meshSettings: objectSettings.meshSettings || {},
|
|
99
114
|
pathIsActive,
|
|
100
|
-
|
|
115
|
+
targets: targets ?? undefined,
|
|
116
|
+
// a timeline clip driving a row's value (live, while it runs)
|
|
117
|
+
liveTo: animationLiveReader(objectSettings.id),
|
|
118
|
+
}, activeTransformAnimations, currentTime, hovered, delta);
|
|
101
119
|
}
|
|
102
120
|
if (hasEdgesAnimations) {
|
|
103
121
|
handleEdgesAnimations({ object, startValuesCache: edgesStartValuesRef.current }, edgesAnimations, currentTime, hovered);
|
|
@@ -109,6 +127,7 @@ objectSettings, options = {}, objectSource) => {
|
|
|
109
127
|
object,
|
|
110
128
|
materialSettings: objectSettings.materialSettings || {},
|
|
111
129
|
startValuesCache: startValuesRef.current,
|
|
130
|
+
targets: targets ?? undefined,
|
|
112
131
|
}, activeMaterialAnimations, currentTime, hovered);
|
|
113
132
|
}
|
|
114
133
|
// Handle material effects (color effects)
|
|
@@ -116,6 +135,8 @@ objectSettings, options = {}, objectSource) => {
|
|
|
116
135
|
handleMaterialEffects(object, enabledMaterialEffects, time, delta, effectStateRef, applyToChildren);
|
|
117
136
|
}
|
|
118
137
|
}
|
|
138
|
+
// Targets the rows stopped driving go back to their rest.
|
|
139
|
+
targets?.endFrame();
|
|
119
140
|
animateUniforms(childrenWithMaterialsRef.current, time * speed, mouse, state.camera.position);
|
|
120
141
|
});
|
|
121
142
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMaterialApplication.d.ts","sourceRoot":"","sources":["../../src/hooks/useMaterialApplication.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D,eAAO,MAAM,sBAAsB,GAAI,QAAQ,cAAc,EAAE,kBAAkB,gBAAgB,EAAE,4BAA4B,OAAO,EAAE,YAAY,MAAM,IAAI,KAAG,
|
|
1
|
+
{"version":3,"file":"useMaterialApplication.d.ts","sourceRoot":"","sources":["../../src/hooks/useMaterialApplication.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D,eAAO,MAAM,sBAAsB,GAAI,QAAQ,cAAc,EAAE,kBAAkB,gBAAgB,EAAE,4BAA4B,OAAO,EAAE,YAAY,MAAM,IAAI,KAAG,IAyIhK,CAAC"}
|
|
@@ -96,11 +96,12 @@ export const useMaterialApplication = (source, materialSettings, shouldApply3dri
|
|
|
96
96
|
onApplied?.();
|
|
97
97
|
return;
|
|
98
98
|
}
|
|
99
|
+
// Stops at child scene objects: they apply their own material.
|
|
99
100
|
traverseSkippingEdgesAndEffects(obj, true, (child) => {
|
|
100
101
|
if (child && child.material) {
|
|
101
102
|
applyMaterialToChild(child, variant, resolvedSettings);
|
|
102
103
|
}
|
|
103
|
-
});
|
|
104
|
+
}, true);
|
|
104
105
|
}
|
|
105
106
|
// traverseSkippingEdges(originObject!, true, (child: any) => {
|
|
106
107
|
// if (child && child.material) {
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import type { Material, Object3D } from "three";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Usage pattern (like SkyControllerUi):
|
|
6
|
-
* - On slider drag → updateProperty(key, value) — instant visual feedback, no Redux
|
|
7
|
-
* - On slider end → updateProperty(key, value) + dispatch to Redux
|
|
8
|
-
* - On color change → updateColor(key, hex) + dispatch to Redux
|
|
9
|
-
* - On variant change → changeMaterial(variant, settings) + dispatch to Redux
|
|
3
|
+
* `object` may be several objects (a group's Material tab edits the children it applies to).
|
|
10
4
|
*/
|
|
11
|
-
export declare function useMaterialUniforms(object: Object3D | null | undefined): {
|
|
5
|
+
export declare function useMaterialUniforms(object: Object3D | Object3D[] | null | undefined): {
|
|
12
6
|
getMaterial: () => Material | null;
|
|
13
7
|
updateProperty: (key: string, value: any) => void;
|
|
14
8
|
updateColor: (key: string, hexValue: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMaterialUniforms.d.ts","sourceRoot":"","sources":["../../src/hooks/useMaterialUniforms.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useMaterialUniforms.d.ts","sourceRoot":"","sources":["../../src/hooks/useMaterialUniforms.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAmBhD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG;IAC/E,WAAW,EAAE,MAAM,QAAQ,GAAG,IAAI,CAAC;IACnC,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAClD,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,gBAAgB,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IAC1D,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;CAC5E,CAoFJ"}
|
|
@@ -9,6 +9,18 @@ import { applySingleProperty, applyColorProperty, createAndApplyMaterial, MATERI
|
|
|
9
9
|
* - On color change → updateColor(key, hex) + dispatch to Redux
|
|
10
10
|
* - On variant change → changeMaterial(variant, settings) + dispatch to Redux
|
|
11
11
|
*/
|
|
12
|
+
/** Every material-bearing node of the object(s) — never inside child scene objects (they have their own material). */
|
|
13
|
+
function eachNode(object, cb) {
|
|
14
|
+
if (!object)
|
|
15
|
+
return;
|
|
16
|
+
for (const root of Array.isArray(object) ? object : [object]) {
|
|
17
|
+
if (root)
|
|
18
|
+
traverseSkippingEdgesAndEffects(root, true, cb, true);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* `object` may be several objects (a group's Material tab edits the children it applies to).
|
|
23
|
+
*/
|
|
12
24
|
export function useMaterialUniforms(object) {
|
|
13
25
|
/**
|
|
14
26
|
* Get the material from the first non-edges child mesh that has one.
|
|
@@ -16,10 +28,10 @@ export function useMaterialUniforms(object) {
|
|
|
16
28
|
const getMaterial = useCallback(() => {
|
|
17
29
|
if (!object)
|
|
18
30
|
return null;
|
|
19
|
-
if (object.material)
|
|
31
|
+
if (!Array.isArray(object) && object.material)
|
|
20
32
|
return object.material;
|
|
21
33
|
let found = null;
|
|
22
|
-
|
|
34
|
+
eachNode(object, (child) => {
|
|
23
35
|
if (!found && child.material) {
|
|
24
36
|
found = child.material;
|
|
25
37
|
}
|
|
@@ -33,7 +45,7 @@ export function useMaterialUniforms(object) {
|
|
|
33
45
|
const updateProperty = useCallback((key, value) => {
|
|
34
46
|
if (!object)
|
|
35
47
|
return;
|
|
36
|
-
|
|
48
|
+
eachNode(object, (child) => {
|
|
37
49
|
if (child.material) {
|
|
38
50
|
applySingleProperty(child.material, key, value);
|
|
39
51
|
}
|
|
@@ -45,7 +57,7 @@ export function useMaterialUniforms(object) {
|
|
|
45
57
|
const updateColor = useCallback((key, hexValue) => {
|
|
46
58
|
if (!object)
|
|
47
59
|
return;
|
|
48
|
-
|
|
60
|
+
eachNode(object, (child) => {
|
|
49
61
|
if (child.material) {
|
|
50
62
|
applyColorProperty(child.material, key, hexValue);
|
|
51
63
|
}
|
|
@@ -58,7 +70,7 @@ export function useMaterialUniforms(object) {
|
|
|
58
70
|
const applyAllSettings = useCallback((settings) => {
|
|
59
71
|
if (!object)
|
|
60
72
|
return;
|
|
61
|
-
|
|
73
|
+
eachNode(object, (child) => {
|
|
62
74
|
if (child.material) {
|
|
63
75
|
MaterialRegistryAPI.applySettings(child.material, settings);
|
|
64
76
|
}
|
|
@@ -71,7 +83,7 @@ export function useMaterialUniforms(object) {
|
|
|
71
83
|
const changeMaterial = useCallback((variant, settings) => {
|
|
72
84
|
if (!object)
|
|
73
85
|
return;
|
|
74
|
-
|
|
86
|
+
eachNode(object, (child) => {
|
|
75
87
|
if (child.material) {
|
|
76
88
|
const oldInstance = child.userData[MATERIAL_INSTANCE_KEY];
|
|
77
89
|
if (oldInstance) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOrbitTargetFollow.d.ts","sourceRoot":"","sources":["../../src/hooks/useOrbitTargetFollow.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useOrbitTargetFollow.d.ts","sourceRoot":"","sources":["../../src/hooks/useOrbitTargetFollow.ts"],"names":[],"mappings":"AAgDA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAsE/E,wBAAgB,oBAAoB,CAChC,WAAW,EAAE,KAAK,CAAC,gBAAgB,CAAC,GAAG,CAAC,EACxC,YAAY,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,EAClD,YAAY,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS;AAClD,+EAA+E;AAC/E,YAAY,EAAE,MAAM,OAAO;AAC3B,4FAA4F;AAC5F,QAAQ,EAAE,OAAO;AACjB,gFAAgF;AAChF,QAAQ,EAAE,cAAc,QAsE3B;AAED,eAAe,oBAAoB,CAAC"}
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
// So while looking at an object, the limits are widened each frame just enough to hold
|
|
35
35
|
// where the camera is now: the object can take the view outside the authored range,
|
|
36
36
|
// the user still can't rotate / zoom further out of it, and moving back in tightens
|
|
37
|
-
// them to the authored values again. The authored values
|
|
37
|
+
// them to the authored values again. The authored values are `controls.authoredLimits` on
|
|
38
|
+
// the live instance (CameraController sets them, controllers drag them), else the config.
|
|
38
39
|
//
|
|
39
40
|
// Height limits (controls.minHeight / maxHeight) are world Y, not relative to the target,
|
|
40
41
|
// and are applied after everything else in the frame.
|
|
@@ -173,8 +174,9 @@ authored) {
|
|
|
173
174
|
}
|
|
174
175
|
// HEIGHT LIMITS (world Y): last, so nothing — user, target, follow, a clip — ends
|
|
175
176
|
// the frame under the floor or over the ceiling. The camera keeps facing the target.
|
|
176
|
-
const
|
|
177
|
-
const
|
|
177
|
+
const lim = controls?.authoredLimits ?? auth;
|
|
178
|
+
const minH = typeof lim.minHeight === 'number' ? lim.minHeight : -Infinity;
|
|
179
|
+
const maxH = typeof lim.maxHeight === 'number' ? lim.maxHeight : Infinity;
|
|
178
180
|
const y = Math.min(maxH, Math.max(minH, camera.position.y));
|
|
179
181
|
if (y !== camera.position.y) {
|
|
180
182
|
camera.position.y = y;
|
|
@@ -186,7 +188,7 @@ authored) {
|
|
|
186
188
|
camera.updateMatrixWorld();
|
|
187
189
|
// Limits hold the camera where the moving target left it (see the header).
|
|
188
190
|
if (tObj && controls && a.locked)
|
|
189
|
-
widenLimits(controls, camera.position, auth);
|
|
191
|
+
widenLimits(controls, camera.position, controls.authoredLimits ?? auth);
|
|
190
192
|
};
|
|
191
193
|
return () => { scene.onBeforeRender = prev; };
|
|
192
194
|
}, [scene, camera, controlsRef]);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ActionSequence, SceneCommand } from '@3driseai/3drise-core';
|
|
2
|
+
import type { OperationParams } from './types';
|
|
3
|
+
/** What a project holds (the lists SceneBuilder / the studio render with). */
|
|
4
|
+
export interface BakeSource {
|
|
5
|
+
objects?: ReadonlyArray<any>;
|
|
6
|
+
actions?: ReadonlyArray<ActionSequence>;
|
|
7
|
+
clips?: ReadonlyArray<{
|
|
8
|
+
cues?: ReadonlyArray<{
|
|
9
|
+
command?: SceneCommand | null;
|
|
10
|
+
}>;
|
|
11
|
+
}>;
|
|
12
|
+
sequences?: ReadonlyArray<{
|
|
13
|
+
cues?: ReadonlyArray<{
|
|
14
|
+
command?: SceneCommand | null;
|
|
15
|
+
}>;
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
/** One thing to warm: an operation with its parameters on target ids ('self' already resolved). */
|
|
19
|
+
interface BakeJob {
|
|
20
|
+
op: string;
|
|
21
|
+
params: OperationParams;
|
|
22
|
+
targets: string[];
|
|
23
|
+
meshNames?: Record<string, string[]>;
|
|
24
|
+
}
|
|
25
|
+
/** Every warm job of a project. */
|
|
26
|
+
export declare function collectBakeJobs(src: BakeSource): BakeJob[];
|
|
27
|
+
/** The project the scene renders (ObjectsRenderer keeps it current). */
|
|
28
|
+
export declare const setBakeSource: (src: BakeSource) => void;
|
|
29
|
+
export interface BakeReport {
|
|
30
|
+
jobs: number;
|
|
31
|
+
ms: number;
|
|
32
|
+
}
|
|
33
|
+
/** Bake the current project now (queued behind a bake that is running). Resolves when done. */
|
|
34
|
+
export declare function bakeProject(src?: BakeSource): Promise<BakeReport>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=bake.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bake.d.ts","sourceRoot":"","sources":["../../src/operations/bake.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,cAAc,EAA6C,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAKrH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACvB,OAAO,CAAC,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IACxC,KAAK,CAAC,EAAE,aAAa,CAAC;QAAE,IAAI,CAAC,EAAE,aAAa,CAAC;YAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAC;IACnF,SAAS,CAAC,EAAE,aAAa,CAAC;QAAE,IAAI,CAAC,EAAE,aAAa,CAAC;YAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAC;CAC1F;AAED,mGAAmG;AACnG,UAAU,OAAO;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACxC;AASD,mCAAmC;AACnC,wBAAgB,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,EAAE,CAyC1D;AAiBD,wEAAwE;AACxE,eAAO,MAAM,aAAa,GAAI,KAAK,UAAU,SAAsB,CAAC;AAIpE,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE;AAExD,+FAA+F;AAC/F,wBAAgB,WAAW,CAAC,GAAG,GAAE,UAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CAkBzE"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { findNodesByName, objectEffectClipOf } from '@3driseai/3drise-core';
|
|
2
|
+
import { findById } from '../utils/sceneQuery.js';
|
|
3
|
+
import { getOperation, resolveParams } from './registry.js';
|
|
4
|
+
import { getEffectClipTemplate, isWarmable, warmEffectOn } from './runtime.js';
|
|
5
|
+
import { objectEffectParams } from './objectEffects.js';
|
|
6
|
+
const commandsOfInteraction = (ix) => (Array.isArray(ix?.commands) ? ix.commands : []);
|
|
7
|
+
const commandsOfAction = (a) => (Array.isArray(a?.commands) ? a.commands : []);
|
|
8
|
+
/** The effects of an effect clip (template or an object's own): Base and every step. */
|
|
9
|
+
const clipEffects = (clip) => [...(clip?.effects ?? []), ...(clip?.steps ?? []).flatMap(s => s?.effects ?? [])].filter(e => e && typeof e.operation === 'string');
|
|
10
|
+
/** Every warm job of a project. */
|
|
11
|
+
export function collectBakeJobs(src) {
|
|
12
|
+
const jobs = new Map();
|
|
13
|
+
const add = (op, params, targets, meshNames) => {
|
|
14
|
+
if (!targets.length)
|
|
15
|
+
return;
|
|
16
|
+
const k = JSON.stringify([op, params, targets, meshNames ?? null]);
|
|
17
|
+
if (!jobs.has(k))
|
|
18
|
+
jobs.set(k, { op, params, targets, ...(meshNames ? { meshNames } : {}) });
|
|
19
|
+
};
|
|
20
|
+
const objectRow = (e, targets, meshNames) => {
|
|
21
|
+
const def = getOperation(e.operation);
|
|
22
|
+
if (!isWarmable(def))
|
|
23
|
+
return;
|
|
24
|
+
add(def.value, objectEffectParams(def, e), targets, meshNames);
|
|
25
|
+
};
|
|
26
|
+
const fromCommand = (c, selfId) => {
|
|
27
|
+
if (!c)
|
|
28
|
+
return;
|
|
29
|
+
const ids = (list) => (list ?? []).map(t => (t === 'self' ? selfId : t)).filter((t) => !!t);
|
|
30
|
+
if (c.kind === 'effect') {
|
|
31
|
+
const e = c.effect;
|
|
32
|
+
if (!e || e.enabled === false)
|
|
33
|
+
return;
|
|
34
|
+
const def = getOperation(e.operation);
|
|
35
|
+
if (!isWarmable(def))
|
|
36
|
+
return;
|
|
37
|
+
add(def.value, resolveParams(def, e.params), ids(e.targets), e.meshNames);
|
|
38
|
+
}
|
|
39
|
+
else if (c.kind === 'effectClip') {
|
|
40
|
+
const use = c.use;
|
|
41
|
+
const clip = use && getEffectClipTemplate(use.clip);
|
|
42
|
+
if (!clip)
|
|
43
|
+
return;
|
|
44
|
+
for (const e of clipEffects(clip))
|
|
45
|
+
objectRow(e, ids(use.targets), use.meshNames);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
for (const o of src.objects ?? []) {
|
|
49
|
+
if (!o?.id)
|
|
50
|
+
continue;
|
|
51
|
+
for (const ix of (Array.isArray(o.actions) ? o.actions : [])) {
|
|
52
|
+
if (ix?.enabled === false)
|
|
53
|
+
continue;
|
|
54
|
+
for (const c of commandsOfInteraction(ix))
|
|
55
|
+
fromCommand(c, o.id);
|
|
56
|
+
}
|
|
57
|
+
const own = objectEffectClipOf(o);
|
|
58
|
+
const parts = own.parts?.length ? { [o.id]: own.parts } : undefined;
|
|
59
|
+
for (const e of clipEffects(own))
|
|
60
|
+
objectRow(e, [o.id], parts);
|
|
61
|
+
}
|
|
62
|
+
for (const a of src.actions ?? [])
|
|
63
|
+
for (const c of commandsOfAction(a))
|
|
64
|
+
fromCommand(c, null);
|
|
65
|
+
for (const t of [...(src.clips ?? []), ...(src.sequences ?? [])])
|
|
66
|
+
for (const cue of t?.cues ?? [])
|
|
67
|
+
fromCommand(cue?.command, null);
|
|
68
|
+
return [...jobs.values()];
|
|
69
|
+
}
|
|
70
|
+
function targetsOf(job) {
|
|
71
|
+
const out = [];
|
|
72
|
+
for (const id of job.targets) {
|
|
73
|
+
const root = findById(id);
|
|
74
|
+
if (!root)
|
|
75
|
+
continue;
|
|
76
|
+
const names = job.meshNames?.[id];
|
|
77
|
+
if (names?.length)
|
|
78
|
+
for (const n of names)
|
|
79
|
+
out.push(...findNodesByName(root, n).filter((x) => x !== root));
|
|
80
|
+
else
|
|
81
|
+
out.push(root);
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
// ---------------------------------------------------------------- running it
|
|
86
|
+
let source = {};
|
|
87
|
+
/** The project the scene renders (ObjectsRenderer keeps it current). */
|
|
88
|
+
export const setBakeSource = (src) => { source = src; };
|
|
89
|
+
let running = null;
|
|
90
|
+
/** Bake the current project now (queued behind a bake that is running). Resolves when done. */
|
|
91
|
+
export function bakeProject(src = source) {
|
|
92
|
+
if (running)
|
|
93
|
+
return running.then(() => bakeProject(src));
|
|
94
|
+
const run = (async () => {
|
|
95
|
+
const t0 = performance.now();
|
|
96
|
+
const jobs = collectBakeJobs(src);
|
|
97
|
+
for (const job of jobs) {
|
|
98
|
+
const def = getOperation(job.op);
|
|
99
|
+
if (!def)
|
|
100
|
+
continue;
|
|
101
|
+
const targets = targetsOf(job);
|
|
102
|
+
if (targets.length)
|
|
103
|
+
await warmEffectOn(def, targets, job.params);
|
|
104
|
+
// let a frame through between jobs (the studio is live while it bakes)
|
|
105
|
+
await new Promise(r => setTimeout(r, 0));
|
|
106
|
+
}
|
|
107
|
+
return { jobs: jobs.length, ms: Math.round(performance.now() - t0) };
|
|
108
|
+
})();
|
|
109
|
+
running = run;
|
|
110
|
+
void run.finally(() => { if (running === run)
|
|
111
|
+
running = null; });
|
|
112
|
+
return run;
|
|
113
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"physicalHeld.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/physicalHeld.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AACzF,OAAO,EAAqB,KAAK,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAE9E,MAAM,WAAW,SAAS,CAAC,CAAC;IACxB,6CAA6C;IAC7C,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnB,gEAAgE;IAChE,CAAC,EAAE,eAAe,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,8CAA8C;IAC9C,GAAG,EAAE,CAAC,CAAC;IACP,oCAAoC;IACpC,GAAG,EAAE,OAAO,CAAC;IACb,kFAAkF;IAClF,CAAC,EAAE,MAAM,CAAC;IACV,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC3C,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iGAAiG;IACjG,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,eAAe,KAAK,CAAC,CAAC;IACjD,oHAAoH;IACpH,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,qDAAqD;IACrD,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;CACtC;AAED,gCAAgC;AAChC,eAAO,MAAM,QAAQ,EAAE,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAgL,CAAC;AAEtP,gGAAgG;AAChG,eAAO,MAAM,YAAY,GAAI,UAAU,MAAM,WAAgD,CAAC;AAE9F,wBAAgB,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,mBAAmB,
|
|
1
|
+
{"version":3,"file":"physicalHeld.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/physicalHeld.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AACzF,OAAO,EAAqB,KAAK,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAE9E,MAAM,WAAW,SAAS,CAAC,CAAC;IACxB,6CAA6C;IAC7C,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnB,gEAAgE;IAChE,CAAC,EAAE,eAAe,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,8CAA8C;IAC9C,GAAG,EAAE,CAAC,CAAC;IACP,oCAAoC;IACpC,GAAG,EAAE,OAAO,CAAC;IACb,kFAAkF;IAClF,CAAC,EAAE,MAAM,CAAC;IACV,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC3C,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iGAAiG;IACjG,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,eAAe,KAAK,CAAC,CAAC;IACjD,oHAAoH;IACpH,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,qDAAqD;IACrD,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;CACtC;AAED,gCAAgC;AAChC,eAAO,MAAM,QAAQ,EAAE,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAgL,CAAC;AAEtP,gGAAgG;AAChG,eAAO,MAAM,YAAY,GAAI,UAAU,MAAM,WAAgD,CAAC;AAE9F,wBAAgB,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAwD9E"}
|
|
@@ -62,6 +62,12 @@ export function heldPhysical(spec) {
|
|
|
62
62
|
st.out = false;
|
|
63
63
|
return run(target, st, 1, easeTime(p));
|
|
64
64
|
},
|
|
65
|
+
// a motion reads its params every frame: a new speed / height just takes over
|
|
66
|
+
live(target, p) {
|
|
67
|
+
const st = target.userData[KEY];
|
|
68
|
+
if (st)
|
|
69
|
+
st.p = { ...p, __backward: st.p.__backward };
|
|
70
|
+
},
|
|
65
71
|
revert(target, p) {
|
|
66
72
|
const st = target.userData[KEY];
|
|
67
73
|
if (!st)
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
// three keeps covers every cached program.
|
|
35
35
|
//
|
|
36
36
|
import { Color, Group, InstancedMesh, Material as ThreeMaterial, Mesh, SkinnedMesh } from 'three';
|
|
37
|
-
import { compileInBackground, warmContext } from './warmup.js';
|
|
37
|
+
import { asInFrame, compileInBackground, warmContext } from './warmup.js';
|
|
38
38
|
/** material → uniform name → the live uniform object of the current layer */
|
|
39
39
|
const liveUniforms = new WeakMap();
|
|
40
40
|
/** material → uniform name → the stable proxy handed to the compiled program */
|
|
@@ -170,7 +170,7 @@ export async function commitPendingLayers(root) {
|
|
|
170
170
|
if (ctx) {
|
|
171
171
|
// let the live materials take the cached programs before the clones let go of them
|
|
172
172
|
try {
|
|
173
|
-
ctx.gl.compile(root, ctx.cam, ctx.scene);
|
|
173
|
+
asInFrame(ctx, () => ctx.gl.compile(root, ctx.cam, ctx.scene));
|
|
174
174
|
}
|
|
175
175
|
catch { /* next frame will */ }
|
|
176
176
|
setTimeout(() => clones.forEach(c => c.dispose()), 1500);
|
|
@@ -5,12 +5,34 @@ export interface WarmContext {
|
|
|
5
5
|
cam: any;
|
|
6
6
|
}
|
|
7
7
|
export declare function warmContext(): WarmContext | null;
|
|
8
|
+
/** Run a compile with the render target the scene is drawn into bound (see the header). */
|
|
9
|
+
export declare function asInFrame<T>(ctx: WarmContext, fn: () => T): T;
|
|
8
10
|
/** compileAsync with a safety timeout (a driver that never reports ready must not hang an effect). */
|
|
9
|
-
export declare function compileInBackground(root: Object3D, timeoutMs?: number): Promise<void>;
|
|
11
|
+
export declare function compileInBackground(root: Object3D, timeoutMs?: number, given?: WarmContext | null): Promise<void>;
|
|
12
|
+
/** The whole scene, as the frame draws it (the published scene's load: see triggers/readiness). */
|
|
13
|
+
export declare function compileScene(three?: {
|
|
14
|
+
gl: any;
|
|
15
|
+
scene: any;
|
|
16
|
+
camera: any;
|
|
17
|
+
} | null, timeoutMs?: number): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Upload every texture of `root` to the GPU now. three uploads a texture the first time
|
|
20
|
+
* something using it is drawn — in that frame: an object hidden at load and shown later
|
|
21
|
+
* (a cue, an action, visibility) would stall the frame it appears in.
|
|
22
|
+
*/
|
|
23
|
+
export declare function uploadTextures(root?: Object3D): number;
|
|
10
24
|
/** Keep a freshly created helper off screen until its shaders are compiled (see warmHelpers). */
|
|
11
25
|
export declare function hideUntilWarm(obj: Object3D): void;
|
|
12
26
|
/** Compile every helper under `root` that is waiting, in the background, then show it. */
|
|
13
27
|
export declare function warmHelpers(root: Object3D): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* The shadow pass draws a shadow caster with three's own depth material — a program
|
|
30
|
+
* compileAsync never builds, so a new kind of caster (an instanced helper) compiled it
|
|
31
|
+
* in the first frame that drew its shadow. Build it here: a stand-in of the same kind
|
|
32
|
+
* with an equivalent depth material, compiled into a render target as the shadow map is.
|
|
33
|
+
* The stand-ins are kept (never drawn) so the programs stay cached.
|
|
34
|
+
*/
|
|
35
|
+
export declare function warmShadowPass(root: Object3D): Promise<void>;
|
|
14
36
|
/**
|
|
15
37
|
* Warm-only runs (pre-warming): while this is on, an effect's runProgress compiles
|
|
16
38
|
* everything it needs and then stops — nothing animates. See runtime.prewarmEffect.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"warmup.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/warmup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"warmup.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/warmup.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAY,QAAQ,EAAW,MAAM,OAAO,CAAC;AAGzD,MAAM,WAAW,WAAW;IAAG,EAAE,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC;IAAC,GAAG,EAAE,GAAG,CAAA;CAAE;AAE9D,wBAAgB,WAAW,IAAI,WAAW,GAAG,IAAI,CAIhD;AA4BD,2FAA2F;AAC3F,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAO7D;AAED,sGAAsG;AACtG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,SAAO,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ/G;AAED,mGAAmG;AACnG,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE;IAAE,EAAE,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,GAAG,IAAI,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAOjH;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAatD;AAWD,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,GAAG,EAAE,QAAQ,QAI1C;AAED,0FAA0F;AAC1F,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAQzD;AAsBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAK5D;AAyCD;;;GAGG;AACH,eAAO,MAAM,QAAQ;;CAAgB,CAAC;AAStC,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,QAqB5C"}
|