@volter/threejs-runtime 0.5.65 → 0.5.66
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/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@volter/threejs-runtime",
|
|
3
3
|
"author": "Volter AI, Inc.",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
|
-
"version": "0.5.
|
|
5
|
+
"version": "0.5.66",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@dimforge/rapier3d-compat": "^0.14.0",
|
|
44
44
|
"@recast-navigation/three": "^0.43.0",
|
|
45
45
|
"@sparkjsdev/spark": "^2.1.0",
|
|
46
|
-
"@volter/editor-project": "0.5.
|
|
46
|
+
"@volter/editor-project": "0.5.66",
|
|
47
47
|
"n8ao": "^1.10.1",
|
|
48
48
|
"postprocessing": "^6.38.0",
|
|
49
49
|
"quarks.core": "0.16.0",
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { SystemFn, SystemOptions, SystemPhaseName } from '@volter/editor-project/core/system-phase';
|
|
2
2
|
import * as THREE from 'three';
|
|
3
3
|
import type { AnyStateMachine } from 'xstate';
|
|
4
|
-
import { deleteUserData, getUserData, setUserData } from '../ecs/user-data';
|
|
5
|
-
import { attachAnimationRuntimeInspection } from './runtime-inspection';
|
|
6
4
|
import {
|
|
7
5
|
type AnimationBoneMask,
|
|
8
6
|
type AnimationMetaStateNodeLike,
|
|
@@ -67,7 +65,7 @@ export interface XStateAnimationSnapshot {
|
|
|
67
65
|
* compare `Actor<StateMachine<…>>` from one copy against `AnyActorRef` from
|
|
68
66
|
* the other — structurally, through `system`, `src`, `_parent` and a generic
|
|
69
67
|
* `select`, until it gives up with `TS2321: Excessive stack depth`. Measured
|
|
70
|
-
* on a fresh scaffold
|
|
68
|
+
* on a fresh scaffold with a second xstate copy, where every in-repo gate
|
|
71
69
|
* stayed green because the monorepo resolves exactly one copy. A shape this
|
|
72
70
|
* shallow cannot blow that budget however many copies are in play.
|
|
73
71
|
*
|
|
@@ -113,8 +111,6 @@ export interface XStateAnimationBindingOptions {
|
|
|
113
111
|
selectParameters?: (context: unknown) => Record<string, number | boolean>;
|
|
114
112
|
/** Root whose named Bone/Object3D hierarchy is used by `boneMask`. Defaults to mixer root. */
|
|
115
113
|
root?: THREE.Object3D;
|
|
116
|
-
/** Entity that exposes this binding to editor/runtime inspection. Defaults to `root`. */
|
|
117
|
-
owner?: THREE.Object3D;
|
|
118
114
|
/**
|
|
119
115
|
* Engine runner used to register `tick` in the canonical animation phase.
|
|
120
116
|
* Pass `ctx.systems`; disposal removes the callback automatically. When
|
|
@@ -144,29 +140,10 @@ export interface XStateAnimationBinding {
|
|
|
144
140
|
getParameters: () => ReadonlyMap<string, number | boolean>;
|
|
145
141
|
/** Current native composition, useful to the editor and game diagnostics. */
|
|
146
142
|
getActiveLayers: () => readonly XStateAnimationLayerState[];
|
|
147
|
-
/** Unsubscribe
|
|
143
|
+
/** Unsubscribe and stop/uncache actions. Idempotent. */
|
|
148
144
|
dispose: () => void;
|
|
149
145
|
}
|
|
150
146
|
|
|
151
|
-
let inspectionVersion = 0;
|
|
152
|
-
const inspectionListeners = new Set<() => void>();
|
|
153
|
-
|
|
154
|
-
/** React/useSyncExternalStore-compatible lifecycle signal for live editor inspection. */
|
|
155
|
-
export function subscribeXStateAnimationBindings(listener: () => void): () => void {
|
|
156
|
-
inspectionListeners.add(listener);
|
|
157
|
-
return () => inspectionListeners.delete(listener);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/** Monotonic snapshot changed whenever a binding is attached or disposed. */
|
|
161
|
-
export function getXStateAnimationBindingsVersion(): number {
|
|
162
|
-
return inspectionVersion;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
function notifyInspectionLifecycle(): void {
|
|
166
|
-
inspectionVersion++;
|
|
167
|
-
for (const listener of inspectionListeners) listener();
|
|
168
|
-
}
|
|
169
|
-
|
|
170
147
|
interface WeightedClip {
|
|
171
148
|
clip: string;
|
|
172
149
|
actionKey: string;
|
|
@@ -288,7 +265,6 @@ export function bindXStateAnimation(
|
|
|
288
265
|
'[bindXStateAnimation] a THREE.Object3D `root` option is required when the mixer uses AnimationObjectGroup',
|
|
289
266
|
);
|
|
290
267
|
}
|
|
291
|
-
const owner = options.owner ?? root;
|
|
292
268
|
const machineRoot = machineOfXStateActor(actor).root as unknown as AnimationMetaStateNodeLike;
|
|
293
269
|
const entries: MachineAnimationMetaEntry[] = collectMachineAnimationMeta(machineRoot);
|
|
294
270
|
const metaByStateId = new Map(entries.map((entry) => [entry.stateId, entry.meta]));
|
|
@@ -379,7 +355,6 @@ export function bindXStateAnimation(
|
|
|
379
355
|
|
|
380
356
|
const activeLayers = new Map<string, ActiveState>();
|
|
381
357
|
let disposed = false;
|
|
382
|
-
let detachRuntimeInspection = () => {};
|
|
383
358
|
function silence(weights: WeightedClip[], except: string | undefined, duration: number): void {
|
|
384
359
|
for (const weighted of weights) {
|
|
385
360
|
if (weighted.actionKey === except) continue;
|
|
@@ -514,7 +489,6 @@ export function bindXStateAnimation(
|
|
|
514
489
|
dispose(): void {
|
|
515
490
|
if (disposed) return;
|
|
516
491
|
disposed = true;
|
|
517
|
-
detachRuntimeInspection();
|
|
518
492
|
options.systems?.remove('animation', tick);
|
|
519
493
|
subscription.unsubscribe();
|
|
520
494
|
for (const { action, clip } of actionCache.values()) {
|
|
@@ -523,15 +497,8 @@ export function bindXStateAnimation(
|
|
|
523
497
|
}
|
|
524
498
|
actionCache.clear();
|
|
525
499
|
activeLayers.clear();
|
|
526
|
-
if (getUserData(owner, '_xstateAnimation') === binding) {
|
|
527
|
-
deleteUserData(owner, '_xstateAnimation');
|
|
528
|
-
notifyInspectionLifecycle();
|
|
529
|
-
}
|
|
530
500
|
},
|
|
531
501
|
};
|
|
532
|
-
detachRuntimeInspection = attachAnimationRuntimeInspection(owner, { mixer, clips });
|
|
533
|
-
setUserData(owner, '_xstateAnimation', binding);
|
|
534
|
-
notifyInspectionLifecycle();
|
|
535
502
|
options.systems?.add('animation', tick);
|
|
536
503
|
return binding;
|
|
537
504
|
}
|
package/src/ecs/user-data.ts
CHANGED
|
@@ -42,16 +42,8 @@
|
|
|
42
42
|
*
|
|
43
43
|
* Animation (load-bearing — ED5 disposal contract):
|
|
44
44
|
* - `_animMixer` — THREE.AnimationMixer driving this subtree's clips.
|
|
45
|
-
* - `_animClips` — Map<string, AnimationClip> discovered on the GLTF (E5 —
|
|
46
|
-
* lets game code build its own XState-driven
|
|
47
|
-
* binding via `bindXStateAnimation` over the SAME
|
|
48
|
-
* mixer; see xstate-animation-binding.ts).
|
|
49
45
|
* - `_availableClips` — string[] of clip names discovered on the GLTF
|
|
50
|
-
* (inspector dropdown
|
|
51
|
-
* - `_animationRuntime` — format-neutral live native mixer/action inspection.
|
|
52
|
-
* - `_xstateBehavior` — optional live XState behavior actor inspection.
|
|
53
|
-
* - `_xstateAnimation` — compatibility handle for the optional XState→Three
|
|
54
|
-
* bridge; animation UI never discovers through it.
|
|
46
|
+
* (inspector dropdown).
|
|
55
47
|
*
|
|
56
48
|
* Disposal contract:
|
|
57
49
|
* - `__sharedGeometry` — `true` when a mesh's geometry is shared/cached and MUST
|
|
@@ -132,9 +124,6 @@ import type { Object3DAuthoringSubjectMark } from '../adapter/object3d-authoring
|
|
|
132
124
|
import type { RapierEditableBody } from '../adapter/rapier-physics-adapter';
|
|
133
125
|
import type { ReflectionProbeMark } from '../adapter/reflection-probe';
|
|
134
126
|
import type { TriggerVolumeMark } from '../adapter/trigger-volume';
|
|
135
|
-
import type { AnimationRuntimeInspection } from '../animation/runtime-inspection';
|
|
136
|
-
import type { XStateAnimationBinding } from '../animation/xstate-animation-binding';
|
|
137
|
-
import type { XStateBehaviorInspection } from '../behavior/xstate-inspection';
|
|
138
127
|
import { ObjectMarkKeys, type ObjectMarkSchema } from './object-marks';
|
|
139
128
|
|
|
140
129
|
export type { EditorHelperType } from './object-marks';
|
|
@@ -156,11 +145,7 @@ export interface UserDataSchema extends ObjectMarkSchema {
|
|
|
156
145
|
_particleSystem: ParticleSystem;
|
|
157
146
|
gaussianSplat: { src: string; numSplats: number };
|
|
158
147
|
_animMixer: THREE.AnimationMixer;
|
|
159
|
-
_animClips: Map<string, THREE.AnimationClip>;
|
|
160
148
|
_availableClips: string[];
|
|
161
|
-
_animationRuntime: AnimationRuntimeInspection;
|
|
162
|
-
_xstateBehavior: XStateBehaviorInspection;
|
|
163
|
-
_xstateAnimation: XStateAnimationBinding;
|
|
164
149
|
__sharedGeometry: boolean;
|
|
165
150
|
__shadeOrig: THREE.Material | THREE.Material[];
|
|
166
151
|
__shadeUnlit: THREE.Material[];
|
|
@@ -213,11 +198,7 @@ export const UserDataKeys = {
|
|
|
213
198
|
_particleSystem: '_particleSystem',
|
|
214
199
|
gaussianSplat: 'gaussianSplat',
|
|
215
200
|
_animMixer: '_animMixer',
|
|
216
|
-
_animClips: '_animClips',
|
|
217
201
|
_availableClips: '_availableClips',
|
|
218
|
-
_animationRuntime: '_animationRuntime',
|
|
219
|
-
_xstateBehavior: '_xstateBehavior',
|
|
220
|
-
_xstateAnimation: '_xstateAnimation',
|
|
221
202
|
__sharedGeometry: '__sharedGeometry',
|
|
222
203
|
__shadeOrig: '__shadeOrig',
|
|
223
204
|
__shadeUnlit: '__shadeUnlit',
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type * as THREE from 'three';
|
|
2
|
-
import { deleteUserData, getUserData, setUserData } from '../ecs/user-data';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Live native animation playback for editor tools, READ-ONLY. A world states
|
|
6
|
-
* what it is playing; nothing here moves it. Time on an editor stage belongs
|
|
7
|
-
* to the stage transport (`@editor/animation/stage-transport`, WORK.md §The
|
|
8
|
-
* stage transport and the animation door), and the transport writes time by
|
|
9
|
-
* seeking a SUBJECT, never through this inspection door.
|
|
10
|
-
* This is instrumentation, not an animation asset or graph format.
|
|
11
|
-
*/
|
|
12
|
-
export interface AnimationRuntimeInspection {
|
|
13
|
-
readonly mixer: THREE.AnimationMixer;
|
|
14
|
-
readonly clips: ReadonlyMap<string, THREE.AnimationClip>;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
let version = 0;
|
|
18
|
-
const listeners = new Set<() => void>();
|
|
19
|
-
|
|
20
|
-
function notify(): void {
|
|
21
|
-
version++;
|
|
22
|
-
for (const listener of listeners) listener();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function subscribeAnimationRuntimeInspections(listener: () => void): () => void {
|
|
26
|
-
listeners.add(listener);
|
|
27
|
-
return () => listeners.delete(listener);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function animationRuntimeInspectionsVersion(): number {
|
|
31
|
-
return version;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function attachAnimationRuntimeInspection(
|
|
35
|
-
owner: THREE.Object3D,
|
|
36
|
-
inspection: AnimationRuntimeInspection,
|
|
37
|
-
): () => void {
|
|
38
|
-
setUserData(owner, '_animationRuntime', inspection);
|
|
39
|
-
notify();
|
|
40
|
-
return () => {
|
|
41
|
-
if (getUserData(owner, '_animationRuntime') !== inspection) return;
|
|
42
|
-
deleteUserData(owner, '_animationRuntime');
|
|
43
|
-
notify();
|
|
44
|
-
};
|
|
45
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type * as THREE from 'three';
|
|
2
|
-
import type { AnyStateMachine } from 'xstate';
|
|
3
|
-
import { deleteUserData, getUserData, setUserData } from '../ecs/user-data';
|
|
4
|
-
|
|
5
|
-
/** Minimal structural actor surface needed by the live behavior debugger. */
|
|
6
|
-
export interface InspectableXStateActor {
|
|
7
|
-
readonly getSnapshot: () => {
|
|
8
|
-
readonly value: unknown;
|
|
9
|
-
readonly context: unknown;
|
|
10
|
-
readonly machine?: AnyStateMachine;
|
|
11
|
-
};
|
|
12
|
-
readonly subscribe: (next: (snapshot: { readonly value: unknown }) => void) => {
|
|
13
|
-
unsubscribe: () => void;
|
|
14
|
-
};
|
|
15
|
-
readonly logic?: AnyStateMachine;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface XStateBehaviorInspection {
|
|
19
|
-
readonly actor: InspectableXStateActor;
|
|
20
|
-
readonly machine: AnyStateMachine;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
let version = 0;
|
|
24
|
-
const listeners = new Set<() => void>();
|
|
25
|
-
|
|
26
|
-
function notify(): void {
|
|
27
|
-
version++;
|
|
28
|
-
for (const listener of listeners) listener();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function subscribeXStateBehaviorInspections(listener: () => void): () => void {
|
|
32
|
-
listeners.add(listener);
|
|
33
|
-
return () => listeners.delete(listener);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function xstateBehaviorInspectionsVersion(): number {
|
|
37
|
-
return version;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function attachXStateBehaviorInspection(
|
|
41
|
-
owner: THREE.Object3D,
|
|
42
|
-
inspection: XStateBehaviorInspection,
|
|
43
|
-
): () => void {
|
|
44
|
-
setUserData(owner, '_xstateBehavior', inspection);
|
|
45
|
-
notify();
|
|
46
|
-
return () => {
|
|
47
|
-
if (getUserData(owner, '_xstateBehavior') !== inspection) return;
|
|
48
|
-
deleteUserData(owner, '_xstateBehavior');
|
|
49
|
-
notify();
|
|
50
|
-
};
|
|
51
|
-
}
|