@needle-tools/engine 5.1.0-alpha.3 → 5.1.0-alpha.4
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/CHANGELOG.md +39 -0
- package/SKILL.md +4 -1
- package/components.needle.json +1 -1
- package/dist/needle-engine.bundle-AjVIot3d.min.js +1733 -0
- package/dist/{needle-engine.bundle-DF01sSGQ.js → needle-engine.bundle-B7cqsI4c.js} +9149 -8867
- package/dist/{needle-engine.bundle-C-ixARur.umd.cjs → needle-engine.bundle-DQCuBTVp.umd.cjs} +154 -154
- package/dist/needle-engine.d.ts +754 -199
- package/dist/needle-engine.js +583 -584
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/lib/engine/api.d.ts +3 -0
- package/lib/engine/api.js +2 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/codegen/register_types.js +2 -10
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/engine_context.js +2 -1
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_disposable.d.ts +172 -0
- package/lib/engine/engine_disposable.js +136 -0
- package/lib/engine/engine_disposable.js.map +1 -0
- package/lib/engine/engine_gameobject.d.ts +1 -10
- package/lib/engine/engine_gameobject.js +20 -118
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_gltf_builtin_components.js +7 -69
- package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
- package/lib/engine/engine_instantiate_resolve.d.ts +42 -0
- package/lib/engine/engine_instantiate_resolve.js +372 -0
- package/lib/engine/engine_instantiate_resolve.js.map +1 -0
- package/lib/engine/engine_mainloop_utils.js +2 -2
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_networking.d.ts +51 -37
- package/lib/engine/engine_networking.js +132 -82
- package/lib/engine/engine_networking.js.map +1 -1
- package/lib/engine/engine_networking.transport.websocket.d.ts +15 -0
- package/lib/engine/engine_networking.transport.websocket.js +38 -0
- package/lib/engine/engine_networking.transport.websocket.js.map +1 -0
- package/lib/engine/engine_networking_instantiate.js +2 -2
- package/lib/engine/engine_networking_instantiate.js.map +1 -1
- package/lib/engine/engine_networking_types.d.ts +39 -1
- package/lib/engine/engine_networking_types.js +7 -0
- package/lib/engine/engine_networking_types.js.map +1 -1
- package/lib/engine/engine_physics_rapier.d.ts +11 -3
- package/lib/engine/engine_physics_rapier.js +88 -25
- package/lib/engine/engine_physics_rapier.js.map +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.js +1 -5
- package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
- package/lib/engine/engine_serialization_core.d.ts +1 -0
- package/lib/engine/engine_serialization_core.js +7 -0
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_types.d.ts +19 -11
- package/lib/engine/engine_types.js +1 -1
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_util_decorator.js +7 -2
- package/lib/engine/engine_util_decorator.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +1 -1
- package/lib/engine/engine_utils.js +19 -5
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine-components/Animator.d.ts +6 -0
- package/lib/engine-components/Animator.js +17 -12
- package/lib/engine-components/Animator.js.map +1 -1
- package/lib/engine-components/AnimatorController.builder.d.ts +113 -0
- package/lib/engine-components/AnimatorController.builder.js +195 -0
- package/lib/engine-components/AnimatorController.builder.js.map +1 -0
- package/lib/engine-components/AnimatorController.d.ts +2 -119
- package/lib/engine-components/AnimatorController.js +31 -232
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/Collider.d.ts +18 -9
- package/lib/engine-components/Collider.js +61 -14
- package/lib/engine-components/Collider.js.map +1 -1
- package/lib/engine-components/Component.d.ts +72 -9
- package/lib/engine-components/Component.js +114 -10
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/DragControls.js +0 -7
- package/lib/engine-components/DragControls.js.map +1 -1
- package/lib/engine-components/EventList.d.ts +31 -9
- package/lib/engine-components/EventList.js +37 -76
- package/lib/engine-components/EventList.js.map +1 -1
- package/lib/engine-components/Joints.d.ts +4 -2
- package/lib/engine-components/Joints.js +19 -3
- package/lib/engine-components/Joints.js.map +1 -1
- package/lib/engine-components/Light.js +9 -1
- package/lib/engine-components/Light.js.map +1 -1
- package/lib/engine-components/RigidBody.d.ts +12 -4
- package/lib/engine-components/RigidBody.js +18 -4
- package/lib/engine-components/RigidBody.js.map +1 -1
- package/lib/engine-components/api.d.ts +1 -1
- package/lib/engine-components/api.js +1 -1
- package/lib/engine-components/api.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +3 -9
- package/lib/engine-components/codegen/components.js +3 -9
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/timeline/PlayableDirector.d.ts +16 -6
- package/lib/engine-components/timeline/PlayableDirector.js +70 -62
- package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
- package/lib/engine-components/timeline/SignalAsset.d.ts +3 -1
- package/lib/engine-components/timeline/SignalAsset.js +1 -0
- package/lib/engine-components/timeline/SignalAsset.js.map +1 -1
- package/lib/engine-components/timeline/TimelineBuilder.d.ts +247 -0
- package/lib/engine-components/timeline/TimelineBuilder.js +400 -0
- package/lib/engine-components/timeline/TimelineBuilder.js.map +1 -0
- package/lib/engine-components/timeline/TimelineModels.d.ts +2 -1
- package/lib/engine-components/timeline/TimelineModels.js +3 -0
- package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
- package/lib/engine-components/timeline/TimelineTracks.d.ts +23 -0
- package/lib/engine-components/timeline/TimelineTracks.js +71 -13
- package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
- package/lib/engine-components/timeline/index.d.ts +2 -1
- package/lib/engine-components/timeline/index.js +2 -0
- package/lib/engine-components/timeline/index.js.map +1 -1
- package/package.json +2 -83
- package/plugins/common/license.js +5 -2
- package/plugins/common/worker.js +9 -4
- package/plugins/vite/dependencies.js +1 -11
- package/plugins/vite/dependency-watcher.js +2 -2
- package/plugins/vite/editor-connection.js +3 -3
- package/plugins/vite/reload.js +1 -1
- package/plugins/vite/server.js +2 -1
- package/src/engine/api.ts +4 -0
- package/src/engine/codegen/register_types.ts +2 -10
- package/src/engine/engine_context.ts +2 -1
- package/src/engine/engine_disposable.ts +214 -0
- package/src/engine/engine_gameobject.ts +52 -157
- package/src/engine/engine_gltf_builtin_components.ts +7 -76
- package/src/engine/engine_instantiate_resolve.ts +407 -0
- package/src/engine/engine_mainloop_utils.ts +2 -2
- package/src/engine/engine_networking.transport.websocket.ts +45 -0
- package/src/engine/engine_networking.ts +161 -137
- package/src/engine/engine_networking_instantiate.ts +2 -2
- package/src/engine/engine_networking_types.ts +41 -1
- package/src/engine/engine_physics_rapier.ts +82 -27
- package/src/engine/engine_serialization_builtin_serializer.ts +1 -6
- package/src/engine/engine_serialization_core.ts +9 -0
- package/src/engine/engine_types.ts +24 -15
- package/src/engine/engine_util_decorator.ts +7 -2
- package/src/engine/engine_utils.ts +16 -5
- package/src/engine-components/Animator.ts +18 -11
- package/src/engine-components/AnimatorController.builder.ts +261 -0
- package/src/engine-components/AnimatorController.ts +19 -291
- package/src/engine-components/Collider.ts +66 -18
- package/src/engine-components/Component.ts +118 -20
- package/src/engine-components/DragControls.ts +0 -9
- package/src/engine-components/EventList.ts +45 -83
- package/src/engine-components/Joints.ts +20 -4
- package/src/engine-components/Light.ts +10 -2
- package/src/engine-components/RigidBody.ts +18 -4
- package/src/engine-components/api.ts +1 -1
- package/src/engine-components/codegen/components.ts +3 -9
- package/src/engine-components/timeline/PlayableDirector.ts +67 -65
- package/src/engine-components/timeline/SignalAsset.ts +4 -1
- package/src/engine-components/timeline/TimelineBuilder.ts +564 -0
- package/src/engine-components/timeline/TimelineModels.ts +5 -1
- package/src/engine-components/timeline/TimelineTracks.ts +74 -13
- package/src/engine-components/timeline/index.ts +2 -1
- package/dist/needle-engine.bundle-CHmXdnE1.min.js +0 -1733
- package/lib/engine-components/AvatarLoader.d.ts +0 -80
- package/lib/engine-components/AvatarLoader.js +0 -232
- package/lib/engine-components/AvatarLoader.js.map +0 -1
- package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +0 -11
- package/lib/engine-components/avatar/AvatarBlink_Simple.js +0 -77
- package/lib/engine-components/avatar/AvatarBlink_Simple.js.map +0 -1
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +0 -14
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +0 -69
- package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js.map +0 -1
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +0 -29
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +0 -122
- package/lib/engine-components/avatar/Avatar_Brain_LookAt.js.map +0 -1
- package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +0 -15
- package/lib/engine-components/avatar/Avatar_MouthShapes.js +0 -80
- package/lib/engine-components/avatar/Avatar_MouthShapes.js.map +0 -1
- package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +0 -9
- package/lib/engine-components/avatar/Avatar_MustacheShake.js +0 -30
- package/lib/engine-components/avatar/Avatar_MustacheShake.js.map +0 -1
- package/src/engine-components/AvatarLoader.ts +0 -264
- package/src/engine-components/avatar/AvatarBlink_Simple.ts +0 -70
- package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +0 -64
- package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +0 -140
- package/src/engine-components/avatar/Avatar_MouthShapes.ts +0 -84
- package/src/engine-components/avatar/Avatar_MustacheShake.ts +0 -32
|
@@ -7,11 +7,6 @@ import { Animation } from "../../engine-components/Animation.js";
|
|
|
7
7
|
import { Animator } from "../../engine-components/Animator.js";
|
|
8
8
|
import { AudioListener } from "../../engine-components/AudioListener.js";
|
|
9
9
|
import { AudioSource } from "../../engine-components/AudioSource.js";
|
|
10
|
-
import { Avatar_Brain_LookAt } from "../../engine-components/avatar/Avatar_Brain_LookAt.js";
|
|
11
|
-
import { Avatar_MouthShapes } from "../../engine-components/avatar/Avatar_MouthShapes.js";
|
|
12
|
-
import { Avatar_MustacheShake } from "../../engine-components/avatar/Avatar_MustacheShake.js";
|
|
13
|
-
import { AvatarBlink_Simple } from "../../engine-components/avatar/AvatarBlink_Simple.js";
|
|
14
|
-
import { AvatarEyeLook_Rotation } from "../../engine-components/avatar/AvatarEyeLook_Rotation.js";
|
|
15
10
|
import { AxesHelper } from "../../engine-components/AxesHelper.js";
|
|
16
11
|
import { BasicIKConstraint } from "../../engine-components/BasicIKConstraint.js";
|
|
17
12
|
import { BoxHelperComponent } from "../../engine-components/BoxHelperComponent.js";
|
|
@@ -110,6 +105,7 @@ import { AnimationTrackHandler } from "../../engine-components/timeline/Timeline
|
|
|
110
105
|
import { AudioTrackHandler } from "../../engine-components/timeline/TimelineTracks.js";
|
|
111
106
|
import { MarkerTrackHandler } from "../../engine-components/timeline/TimelineTracks.js";
|
|
112
107
|
import { SignalTrackHandler } from "../../engine-components/timeline/TimelineTracks.js";
|
|
108
|
+
import { ActivationTrackHandler } from "../../engine-components/timeline/TimelineTracks.js";
|
|
113
109
|
import { ControlTrackHandler } from "../../engine-components/timeline/TimelineTracks.js";
|
|
114
110
|
import { TransformGizmo } from "../../engine-components/TransformGizmo.js";
|
|
115
111
|
import { BaseUIComponent } from "../../engine-components/ui/BaseUIComponent.js";
|
|
@@ -167,11 +163,6 @@ export function initBuiltinTypes() {
|
|
|
167
163
|
TypeStore.add("Animator", Animator);
|
|
168
164
|
TypeStore.add("AudioListener", AudioListener);
|
|
169
165
|
TypeStore.add("AudioSource", AudioSource);
|
|
170
|
-
TypeStore.add("Avatar_Brain_LookAt", Avatar_Brain_LookAt);
|
|
171
|
-
TypeStore.add("Avatar_MouthShapes", Avatar_MouthShapes);
|
|
172
|
-
TypeStore.add("Avatar_MustacheShake", Avatar_MustacheShake);
|
|
173
|
-
TypeStore.add("AvatarBlink_Simple", AvatarBlink_Simple);
|
|
174
|
-
TypeStore.add("AvatarEyeLook_Rotation", AvatarEyeLook_Rotation);
|
|
175
166
|
TypeStore.add("AxesHelper", AxesHelper);
|
|
176
167
|
TypeStore.add("BasicIKConstraint", BasicIKConstraint);
|
|
177
168
|
TypeStore.add("BoxHelperComponent", BoxHelperComponent);
|
|
@@ -270,6 +261,7 @@ export function initBuiltinTypes() {
|
|
|
270
261
|
TypeStore.add("AudioTrackHandler", AudioTrackHandler);
|
|
271
262
|
TypeStore.add("MarkerTrackHandler", MarkerTrackHandler);
|
|
272
263
|
TypeStore.add("SignalTrackHandler", SignalTrackHandler);
|
|
264
|
+
TypeStore.add("ActivationTrackHandler", ActivationTrackHandler);
|
|
273
265
|
TypeStore.add("ControlTrackHandler", ControlTrackHandler);
|
|
274
266
|
TypeStore.add("TransformGizmo", TransformGizmo);
|
|
275
267
|
TypeStore.add("BaseUIComponent", BaseUIComponent);
|
|
@@ -863,7 +863,7 @@ export class Context implements IContext {
|
|
|
863
863
|
this.scene = new Scene();
|
|
864
864
|
this.addressables?.dispose();
|
|
865
865
|
this.lightmaps?.clear();
|
|
866
|
-
this.physics?.engine?.
|
|
866
|
+
this.physics?.engine?.dispose();
|
|
867
867
|
this.lodsManager.disable();
|
|
868
868
|
this.accessibility?.clear();
|
|
869
869
|
|
|
@@ -912,6 +912,7 @@ export class Context implements IContext {
|
|
|
912
912
|
this.scene = null!;
|
|
913
913
|
this.renderer = null!;
|
|
914
914
|
this.input.dispose();
|
|
915
|
+
this.connection.dispose();
|
|
915
916
|
this.menu.onDestroy();
|
|
916
917
|
this.animations.onDestroy();
|
|
917
918
|
for (const cb of this._disposeCallbacks) {
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/** A function that performs cleanup when called */
|
|
2
|
+
export type DisposeFn = () => void;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Interface for objects that hold resources and can be disposed.
|
|
6
|
+
* Implement this interface on any object that needs deterministic cleanup.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* class MyResource implements IDisposable {
|
|
11
|
+
* dispose() { /* release resources *\/ }
|
|
12
|
+
* }
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @category Utilities
|
|
16
|
+
* @group Lifecycle
|
|
17
|
+
*/
|
|
18
|
+
export interface IDisposable {
|
|
19
|
+
dispose(): void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Type guard to check if an object implements {@link IDisposable}.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* if (isDisposable(obj)) {
|
|
28
|
+
* obj.dispose(); // safe to call
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function isDisposable(value: unknown): value is IDisposable {
|
|
33
|
+
return value !== null
|
|
34
|
+
&& typeof value === "object"
|
|
35
|
+
&& "dispose" in (value as object)
|
|
36
|
+
&& typeof (value as IDisposable).dispose === "function";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @experimental
|
|
41
|
+
* Subscribe to a DOM event on any {@link EventTarget} (window, document, HTML elements, etc.)
|
|
42
|
+
* and return an {@link IDisposable} that removes the listener when disposed.
|
|
43
|
+
*
|
|
44
|
+
* Provides full TypeScript event type inference — the callback parameter
|
|
45
|
+
* is automatically typed based on the event name (e.g. `"resize"` → `UIEvent`,
|
|
46
|
+
* `"click"` → `MouseEvent`).
|
|
47
|
+
*
|
|
48
|
+
* Use with {@link DisposableStore.add} for automatic lifecycle cleanup in components.
|
|
49
|
+
*
|
|
50
|
+
* @param target The EventTarget to listen on (window, document, an element, etc.)
|
|
51
|
+
* @param type The event name (e.g. `"resize"`, `"click"`, `"keydown"`)
|
|
52
|
+
* @param listener The event handler callback
|
|
53
|
+
* @param options Optional addEventListener options (passive, capture, once, signal)
|
|
54
|
+
* @returns An {@link IDisposable} that removes the event listener when disposed
|
|
55
|
+
*
|
|
56
|
+
* @example Standalone usage
|
|
57
|
+
* ```ts
|
|
58
|
+
* import { on } from "@needle-tools/engine";
|
|
59
|
+
*
|
|
60
|
+
* const sub = on(window, "resize", (ev) => {
|
|
61
|
+
* // ev is typed as UIEvent
|
|
62
|
+
* console.log("resized", ev.target);
|
|
63
|
+
* });
|
|
64
|
+
*
|
|
65
|
+
* // Later: clean up
|
|
66
|
+
* sub.dispose();
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* @example With autoCleanup in a component
|
|
70
|
+
* ```ts
|
|
71
|
+
* import { Behaviour, on } from "@needle-tools/engine";
|
|
72
|
+
*
|
|
73
|
+
* export class MyComponent extends Behaviour {
|
|
74
|
+
* onEnable() {
|
|
75
|
+
* this.autoCleanup(on(window, "resize", (ev) => { /* UIEvent *\/ }));
|
|
76
|
+
* this.autoCleanup(on(document, "keydown", (ev) => { /* KeyboardEvent *\/ }));
|
|
77
|
+
* this.autoCleanup(on(this.context.domElement, "click", (ev) => { /* MouseEvent *\/ }));
|
|
78
|
+
* }
|
|
79
|
+
* // All listeners removed automatically on disable!
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* @category Utilities
|
|
84
|
+
* @group Lifecycle
|
|
85
|
+
*/
|
|
86
|
+
// #region on
|
|
87
|
+
export function on<K extends keyof WindowEventMap>(target: Window, type: K, listener: (ev: WindowEventMap[K]) => void, options?: boolean | AddEventListenerOptions): IDisposable;
|
|
88
|
+
export function on<K extends keyof DocumentEventMap>(target: Document, type: K, listener: (ev: DocumentEventMap[K]) => void, options?: boolean | AddEventListenerOptions): IDisposable;
|
|
89
|
+
export function on<K extends keyof HTMLElementEventMap>(target: HTMLElement, type: K, listener: (ev: HTMLElementEventMap[K]) => void, options?: boolean | AddEventListenerOptions): IDisposable;
|
|
90
|
+
export function on(target: EventTarget, type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): IDisposable;
|
|
91
|
+
export function on(target: EventTarget, type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): IDisposable {
|
|
92
|
+
target.addEventListener(type, listener, options);
|
|
93
|
+
return {
|
|
94
|
+
dispose() {
|
|
95
|
+
target.removeEventListener(type, listener, options);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* A store for managing disposable resources (event subscriptions, listeners, callbacks)
|
|
103
|
+
* that should be cleaned up together.
|
|
104
|
+
*
|
|
105
|
+
* DisposableStore collects disposables and disposes them all at once when
|
|
106
|
+
* {@link dispose} is called. After disposal, the store can be reused — new items
|
|
107
|
+
* can be added and a subsequent {@link dispose} call will clean those up.
|
|
108
|
+
*
|
|
109
|
+
* This is the same pattern used internally by VSCode for lifecycle-bound resource management.
|
|
110
|
+
*
|
|
111
|
+
* @example Basic usage
|
|
112
|
+
* ```ts
|
|
113
|
+
* import { DisposableStore, on } from "@needle-tools/engine";
|
|
114
|
+
*
|
|
115
|
+
* const store = new DisposableStore();
|
|
116
|
+
*
|
|
117
|
+
* // Register a DOM event listener (typed!)
|
|
118
|
+
* store.add(on(window, "resize", (ev) => console.log(ev)));
|
|
119
|
+
*
|
|
120
|
+
* // Register the return value of EventList.on()
|
|
121
|
+
* store.add(myEventList.on(data => console.log(data)));
|
|
122
|
+
*
|
|
123
|
+
* // Register a raw cleanup function
|
|
124
|
+
* store.add(() => someSDK.off("event", handler));
|
|
125
|
+
*
|
|
126
|
+
* // Later: dispose everything at once
|
|
127
|
+
* store.dispose();
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* @example Use with Needle Engine components
|
|
131
|
+
* ```ts
|
|
132
|
+
* import { Behaviour, serializable, EventList, on } from "@needle-tools/engine";
|
|
133
|
+
*
|
|
134
|
+
* export class MyComponent extends Behaviour {
|
|
135
|
+
* @serializable(EventList)
|
|
136
|
+
* onClick?: EventList;
|
|
137
|
+
*
|
|
138
|
+
* onEnable() {
|
|
139
|
+
* // DOM events — fully typed
|
|
140
|
+
* this.autoCleanup(on(window, "resize", (ev) => this.onResize(ev)));
|
|
141
|
+
*
|
|
142
|
+
* // EventList — .on() returns a function, autoCleanup accepts it
|
|
143
|
+
* this.autoCleanup(this.onClick?.on(() => console.log("clicked!")));
|
|
144
|
+
* }
|
|
145
|
+
* // No onDisable needed — cleaned up automatically!
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* @category Utilities
|
|
150
|
+
* @group Lifecycle
|
|
151
|
+
*/
|
|
152
|
+
// #region DisposableStore
|
|
153
|
+
export class DisposableStore implements IDisposable {
|
|
154
|
+
|
|
155
|
+
private _disposables: Array<DisposeFn> = [];
|
|
156
|
+
|
|
157
|
+
/** The number of registered disposables */
|
|
158
|
+
get size() { return this._disposables.length; }
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Register a disposable resource. Accepts:
|
|
162
|
+
* - An {@link IDisposable} object (has a `dispose()` method) — e.g. from {@link on}
|
|
163
|
+
* - A cleanup function (e.g. return value of `EventList.on()`)
|
|
164
|
+
* - `null` or `undefined` (safe no-op for conditional subscriptions)
|
|
165
|
+
*
|
|
166
|
+
* When {@link dispose} is called, all registered resources are cleaned up.
|
|
167
|
+
*
|
|
168
|
+
* @param disposable The resource to register for disposal
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* const store = new DisposableStore();
|
|
173
|
+
*
|
|
174
|
+
* // IDisposable object from on()
|
|
175
|
+
* store.add(on(window, "resize", handler));
|
|
176
|
+
*
|
|
177
|
+
* // Function returned by EventList.on()
|
|
178
|
+
* store.add(myEvent.on(handler));
|
|
179
|
+
*
|
|
180
|
+
* // Raw cleanup function
|
|
181
|
+
* store.add(() => connection.close());
|
|
182
|
+
*
|
|
183
|
+
* // Conditional — safe with undefined
|
|
184
|
+
* store.add(this.maybeEvent?.on(handler));
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
add(disposable: IDisposable | DisposeFn | Function | null | undefined): void {
|
|
188
|
+
if (!disposable) return;
|
|
189
|
+
if (typeof disposable === "function") {
|
|
190
|
+
this._disposables.push(disposable as DisposeFn);
|
|
191
|
+
}
|
|
192
|
+
else if (typeof disposable === "object" && "dispose" in disposable) {
|
|
193
|
+
this._disposables.push(() => disposable.dispose());
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Dispose all registered resources. Each registered disposable is cleaned up,
|
|
199
|
+
* then the internal list is cleared. The store can be reused after disposal.
|
|
200
|
+
*
|
|
201
|
+
* Called automatically by the engine when a component's `onDisable` lifecycle fires.
|
|
202
|
+
*/
|
|
203
|
+
dispose(): void {
|
|
204
|
+
for (let i = this._disposables.length - 1; i >= 0; i--) {
|
|
205
|
+
try {
|
|
206
|
+
this._disposables[i]();
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
console.error("Error disposing resource", err);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
this._disposables.length = 0;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -10,10 +10,11 @@ import { $isUsingInstancing, InstancingUtil } from "./engine_instancing.js";
|
|
|
10
10
|
import { processNewScripts } from "./engine_mainloop_utils.js";
|
|
11
11
|
import type { syncInstantiate } from "./engine_networking_instantiate.js";
|
|
12
12
|
import { InstantiateIdProvider } from "./engine_networking_instantiate.js";
|
|
13
|
-
import {
|
|
13
|
+
import { resolveInstanceReferences, type InstantiateReferenceMap, type InstantiateContext, type ObjectCloneReference } from "./engine_instantiate_resolve.js";
|
|
14
|
+
import { assign } from "./engine_serialization_core.js";
|
|
14
15
|
import { Context, registerComponent } from "./engine_setup.js";
|
|
15
16
|
import { getTempQuaternion, logHierarchy, setWorldPosition, setWorldQuaternion } from "./engine_three_utils.js";
|
|
16
|
-
import { type Constructor, type GuidsMap, type IComponent as Component, type IComponent,
|
|
17
|
+
import { type Constructor, type GuidsMap, type IComponent as Component, type IComponent, type IGameObject as GameObject, type UIDProvider, isComponent } from "./engine_types.js";
|
|
17
18
|
import { deepClone, getParam, tryFindObject } from "./engine_utils.js";
|
|
18
19
|
import { apply } from "./js-extensions/index.js";
|
|
19
20
|
|
|
@@ -324,19 +325,8 @@ function internalForEachComponent(instance: Object3D, cb: ForEachComponentCallba
|
|
|
324
325
|
|
|
325
326
|
}
|
|
326
327
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
readonly clone: object;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
declare type InstantiateReferenceMap = Record<string, ObjectCloneReference>;
|
|
334
|
-
declare type NewObjectReferenceMap = Record<string, { target: object, key: string }>;
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* Provides access to the instantiated object and its clone
|
|
338
|
-
*/
|
|
339
|
-
export declare type InstantiateContext = Readonly<InstantiateReferenceMap>;
|
|
328
|
+
// Re-export types from the unified resolution module
|
|
329
|
+
export type { InstantiateContext, InstantiateReferenceMap, ObjectCloneReference } from "./engine_instantiate_resolve.js";
|
|
340
330
|
|
|
341
331
|
/**
|
|
342
332
|
* Creates a copy (clone) of a GameObject or loads and instantiates an AssetReference.
|
|
@@ -410,7 +400,7 @@ export function instantiate(instance: AssetReference | GameObject | Object3D, op
|
|
|
410
400
|
const clone = internalInstantiate(context, instance, options, components, referencemap, skinnedMeshes);
|
|
411
401
|
|
|
412
402
|
if (clone) {
|
|
413
|
-
|
|
403
|
+
resolveInstanceReferences(referencemap);
|
|
414
404
|
resolveAndBindSkinnedMeshBones(skinnedMeshes, referencemap);
|
|
415
405
|
}
|
|
416
406
|
|
|
@@ -420,6 +410,18 @@ export function instantiate(instance: AssetReference | GameObject | Object3D, op
|
|
|
420
410
|
}
|
|
421
411
|
|
|
422
412
|
const guidsMap: GuidsMap = {};
|
|
413
|
+
|
|
414
|
+
// Cloned object guids
|
|
415
|
+
for (const ref in referencemap) {
|
|
416
|
+
const val = referencemap[ref];
|
|
417
|
+
const original = val.original;
|
|
418
|
+
const clone = val.clone;
|
|
419
|
+
if (original instanceof Object3D && clone instanceof Object3D) {
|
|
420
|
+
guidsMap[original.guid || original.uuid] = clone.guid || clone.uuid;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Cloned component guids (generate new guids for components that dont have one and add them to the map)
|
|
423
425
|
if (options?.components !== false) {
|
|
424
426
|
for (const i in components) {
|
|
425
427
|
const copy = components[i];
|
|
@@ -427,8 +429,7 @@ export function instantiate(instance: AssetReference | GameObject | Object3D, op
|
|
|
427
429
|
if (options && options.idProvider) {
|
|
428
430
|
copy.guid = options.idProvider.generateUUID();
|
|
429
431
|
guidsMap[oldGuid] = copy.guid;
|
|
430
|
-
if (debug)
|
|
431
|
-
console.log(copy.name, copy.guid)
|
|
432
|
+
if (debug) console.log(copy.name, copy.guid)
|
|
432
433
|
}
|
|
433
434
|
registerComponent(copy, context);
|
|
434
435
|
if (copy.__internalNewInstanceCreated)
|
|
@@ -436,8 +437,6 @@ export function instantiate(instance: AssetReference | GameObject | Object3D, op
|
|
|
436
437
|
}
|
|
437
438
|
for (const i in components) {
|
|
438
439
|
const copy = components[i];
|
|
439
|
-
if (copy.resolveGuids)
|
|
440
|
-
copy.resolveGuids(guidsMap);
|
|
441
440
|
if (copy.enabled === false) continue;
|
|
442
441
|
else copy.enabled = true;
|
|
443
442
|
}
|
|
@@ -478,7 +477,12 @@ function internalInstantiate(
|
|
|
478
477
|
instance.children = children;
|
|
479
478
|
|
|
480
479
|
// make reference from old id to new object
|
|
481
|
-
|
|
480
|
+
const ref: ObjectCloneReference = { original: instance, clone: clone };
|
|
481
|
+
objectsMap[instance.uuid] = ref;
|
|
482
|
+
// Also key by guid so string guid references (e.g. PlayableDirector track.outputs) can be resolved
|
|
483
|
+
if ((instance).guid && (instance).guid !== instance.uuid) {
|
|
484
|
+
objectsMap[(instance).guid] = ref;
|
|
485
|
+
}
|
|
482
486
|
if (debugInstantiate) console.log("ADD", instance, clone)
|
|
483
487
|
|
|
484
488
|
if (instance.type === "SkinnedMesh") {
|
|
@@ -612,32 +616,32 @@ function internalInstantiate(
|
|
|
612
616
|
function onAssignComponent(source: any, target: any, _newObjectsMap: InstantiateReferenceMap) {
|
|
613
617
|
assign(target, source, undefined, {
|
|
614
618
|
// onAssigned: (target, key, _oldValue, value) => {
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
619
|
+
// if (value !== null && typeof value === "object") {
|
|
620
|
+
// const serializable = target as ISerializable;
|
|
621
|
+
// if (serializable?.$serializedTypes?.[key]) {
|
|
622
|
+
// if (!(value instanceof Object3D)) {
|
|
623
|
+
// // let clone = null;
|
|
624
|
+
// // if ("clone" in value) {
|
|
625
|
+
// // if (canClone(value)) clone = (value as any).clone();
|
|
626
|
+
// // }
|
|
627
|
+
// // else {
|
|
628
|
+
// // clone = Object.assign(Object.create(Object.getPrototypeOf(value)), value);
|
|
629
|
+
// // }
|
|
630
|
+
// // if (clone) {
|
|
631
|
+
// // console.debug(key, { target, value, clone })
|
|
632
|
+
// // target[key] = clone;
|
|
633
|
+
// // findNestedReferences(clone, objectsMap);
|
|
634
|
+
// // }
|
|
635
|
+
// // else console.debug("Could not clone value for key", key, value);
|
|
636
|
+
// }
|
|
637
|
+
// else {
|
|
638
|
+
// console.log("ASSIGNED", value)
|
|
639
|
+
// }
|
|
640
|
+
|
|
641
|
+
// recursiveAssign(target, target[key], newObjectsMap);
|
|
642
|
+
// }
|
|
643
|
+
|
|
644
|
+
// }
|
|
641
645
|
// }
|
|
642
646
|
});
|
|
643
647
|
}
|
|
@@ -742,113 +746,4 @@ function resolveAndBindSkinnedMeshBones(
|
|
|
742
746
|
|
|
743
747
|
// }
|
|
744
748
|
|
|
745
|
-
|
|
746
|
-
// for every object that is newly created we want to update references to their newly created counterparts
|
|
747
|
-
// e.g. a collider instance referencing a rigidbody instance should be updated so that
|
|
748
|
-
// the cloned collider does not reference the cloned rigidbody (instead of the original rigidbody)
|
|
749
|
-
for (const key in newObjectsMap) {
|
|
750
|
-
const val = newObjectsMap[key];
|
|
751
|
-
const clone = val.clone as Object3D | null;
|
|
752
|
-
// resolve references
|
|
753
|
-
if (clone?.isObject3D && clone?.userData?.components) {
|
|
754
|
-
for (let i = 0; i < clone.userData.components.length; i++) {
|
|
755
|
-
const copy = clone.userData.components[i];
|
|
756
|
-
// find referenced within a cloned gameobject
|
|
757
|
-
const entries = Object.entries(copy);
|
|
758
|
-
// console.log(copy, entries);
|
|
759
|
-
for (const [key, value] of entries) {
|
|
760
|
-
if (Array.isArray(value)) {
|
|
761
|
-
const clonedArray: Array<any> = [];
|
|
762
|
-
copy[key] = clonedArray;
|
|
763
|
-
// console.log(copy, key, value, copy[key]);
|
|
764
|
-
for (let i = 0; i < value.length; i++) {
|
|
765
|
-
const entry = value[i];
|
|
766
|
-
// push value types into new array
|
|
767
|
-
if (typeof entry !== "object") {
|
|
768
|
-
clonedArray.push(entry);
|
|
769
|
-
continue;
|
|
770
|
-
}
|
|
771
|
-
const res: any = postProcessNewInstance(copy, key, entry, newObjectsMap);
|
|
772
|
-
if (res !== undefined) {
|
|
773
|
-
if (debugInstantiate) console.log("Found new instance for", key, entry, "->", res);
|
|
774
|
-
clonedArray.push(res);
|
|
775
|
-
}
|
|
776
|
-
else {
|
|
777
|
-
if (debugInstantiate) console.warn("Could not find new instance for", key, entry);
|
|
778
|
-
clonedArray.push(entry);
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
// console.log(copy[key])
|
|
782
|
-
}
|
|
783
|
-
else if (typeof value === "object") {
|
|
784
|
-
const res = postProcessNewInstance(copy, key, value as IComponent | Object3D, newObjectsMap);
|
|
785
|
-
if (res !== undefined) {
|
|
786
|
-
copy[key] = res;
|
|
787
|
-
}
|
|
788
|
-
else {
|
|
789
|
-
if (debugInstantiate) console.warn("Could not find new instance for", key, value);
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
function postProcessNewInstance(copy: Object3D, key: string, value: IComponent | Object3D | any, newObjectsMap: InstantiateReferenceMap) {
|
|
800
|
-
if (value === null || value === undefined) return;
|
|
801
|
-
if ((value as IComponent).isComponent === true) {
|
|
802
|
-
const originalGameObjectReference = value["gameObject"];
|
|
803
|
-
// console.log(key, value, originalGameObjectReference);
|
|
804
|
-
if (originalGameObjectReference) {
|
|
805
|
-
const id = originalGameObjectReference.uuid;
|
|
806
|
-
const newGameObject = newObjectsMap[id]?.clone;
|
|
807
|
-
if (!newGameObject) {
|
|
808
|
-
// reference has not changed!
|
|
809
|
-
if (debugInstantiate)
|
|
810
|
-
console.log("reference did not change", key, copy, value);
|
|
811
|
-
return;
|
|
812
|
-
}
|
|
813
|
-
const index = originalGameObjectReference.userData.components.indexOf(value);
|
|
814
|
-
if (index >= 0 && (newGameObject as Object3D).isObject3D) {
|
|
815
|
-
if (debugInstantiate)
|
|
816
|
-
console.log(key, id);
|
|
817
|
-
const found = (newGameObject as Object3D).userData.components[index];
|
|
818
|
-
return found;
|
|
819
|
-
}
|
|
820
|
-
else {
|
|
821
|
-
console.warn("could not find component", key, value);
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
} else if ((value as Object3D).isObject3D === true) {
|
|
825
|
-
// console.log(value);
|
|
826
|
-
if (key === "gameObject") return;
|
|
827
|
-
const originalGameObjectReference = value as Object3D;
|
|
828
|
-
if (originalGameObjectReference) {
|
|
829
|
-
const id = originalGameObjectReference.uuid;
|
|
830
|
-
const newGameObject = newObjectsMap[id]?.clone;
|
|
831
|
-
if (newGameObject) {
|
|
832
|
-
if (debugInstantiate)
|
|
833
|
-
console.log(key, "old", value, "new", newGameObject);
|
|
834
|
-
return newGameObject;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
else {
|
|
839
|
-
// create new instances for some types that we know should usually not be shared and can safely be cloned
|
|
840
|
-
if (value.isVector4 || value.isVector3 || value.isVector2 || value.isQuaternion || value.isEuler) {
|
|
841
|
-
return value.clone();
|
|
842
|
-
}
|
|
843
|
-
else if (value.isColor === true) {
|
|
844
|
-
return value.clone();
|
|
845
|
-
}
|
|
846
|
-
else if ((value as IEventList).isEventList === true) {
|
|
847
|
-
// create a new instance of the object
|
|
848
|
-
const copy = (value as IEventList).__internalOnInstantiate(newObjectsMap);
|
|
849
|
-
return copy;
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
// const canClone = (value: any) => value.isVector4 || value.isVector3 || value.isVector2 || value.isQuaternion || value.isEuler || value.isColor === true;
|
|
749
|
+
// Reference resolution is now handled by the unified module: engine_instantiate_resolve.ts
|
|
@@ -5,6 +5,7 @@ import { LogType, showBalloonMessage } from "./debug/index.js";
|
|
|
5
5
|
import { addNewComponent } from "./engine_components.js";
|
|
6
6
|
import { builtinComponentKeyName, editorGuidKeyName } from "./engine_constants.js";
|
|
7
7
|
import { debugExtension } from "./engine_default_parameters.js";
|
|
8
|
+
import { generateGuidsForHierarchy, resolveStringGuidsInHierarchy, originalComponentNameKey } from "./engine_instantiate_resolve.js";
|
|
8
9
|
import { InstantiateIdProvider } from "./engine_networking_instantiate.js"
|
|
9
10
|
import { isLocalNetwork } from "./engine_networking_utils.js";
|
|
10
11
|
import { deserializeObject, serializeObject } from "./engine_serialization.js";
|
|
@@ -98,88 +99,18 @@ export async function createBuiltinComponents(context: Context, gltfId: SourceId
|
|
|
98
99
|
// doing it here at the end of resolving of references should ensure that
|
|
99
100
|
// and this should run before awake and onenable of newly created components
|
|
100
101
|
if (idProvider) {
|
|
101
|
-
// TODO: should we do this after setup callbacks now?
|
|
102
102
|
const guidsMap: GuidsMap = {};
|
|
103
|
-
|
|
104
|
-
// TODO: when is the gltf here an object3d?
|
|
105
|
-
recursiveCreateGuids(gltf as any, idProvider, guidsMap, resolveGuids);
|
|
103
|
+
generateGuidsForHierarchy(gltf as any, idProvider, guidsMap);
|
|
106
104
|
for (const scene of gltf.scenes)
|
|
107
|
-
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
105
|
+
generateGuidsForHierarchy(scene, idProvider, guidsMap);
|
|
106
|
+
// Resolve string guid references in component fields (e.g. PlayableDirector track.outputs)
|
|
107
|
+
resolveStringGuidsInHierarchy(gltf as any, guidsMap);
|
|
108
|
+
for (const scene of gltf.scenes)
|
|
109
|
+
resolveStringGuidsInHierarchy(scene, guidsMap);
|
|
112
110
|
}
|
|
113
111
|
});
|
|
114
112
|
}
|
|
115
113
|
|
|
116
|
-
declare type IHasResolveGuids = {
|
|
117
|
-
resolveGuids: (guidsMap: GuidsMap) => void;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const originalComponentNameKey = Symbol("original-component-name");
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* We want to create one id provider per component
|
|
124
|
-
* If a component is used multiple times we want to create a new id provider for each instance
|
|
125
|
-
* That way the order of components in the scene doesnt affect the result GUID
|
|
126
|
-
*/
|
|
127
|
-
// TODO: clear this when re-loading the context
|
|
128
|
-
const idProviderCache = new Map<string, InstantiateIdProvider>();
|
|
129
|
-
|
|
130
|
-
function recursiveCreateGuids(obj: Object3D, idProvider: UIDProvider | null, guidsMap: GuidsMap, resolveGuids: IHasResolveGuids[]) {
|
|
131
|
-
if (idProvider === null) return;
|
|
132
|
-
if (!obj) return;
|
|
133
|
-
const prev = obj.guid;
|
|
134
|
-
|
|
135
|
-
// we also want to use the idproviderCache for objects because they might be removed or re-ordered in the scene hierarchy
|
|
136
|
-
// in which case we dont want to e.g. change the syncedInstantiate objects that get created because suddenly another object has that guid
|
|
137
|
-
const idProviderKey = obj.guid;
|
|
138
|
-
if (idProviderKey?.length) {
|
|
139
|
-
if (!idProviderCache.has(idProviderKey)) {
|
|
140
|
-
if (debug) console.log("Creating InstanceIdProvider with key \"" + idProviderKey + "\" for object " + obj.name);
|
|
141
|
-
idProviderCache.set(idProviderKey, new InstantiateIdProvider(idProviderKey));
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
const objectIdProvider = idProviderKey && idProviderCache.get(idProviderKey) || idProvider;
|
|
145
|
-
|
|
146
|
-
obj.guid = objectIdProvider.generateUUID();
|
|
147
|
-
if (prev && prev !== "invalid")
|
|
148
|
-
guidsMap[prev] = obj.guid;
|
|
149
|
-
|
|
150
|
-
// console.log(obj);
|
|
151
|
-
if (obj && obj.userData && obj.userData.components) {
|
|
152
|
-
for (const comp of obj.userData.components) {
|
|
153
|
-
if (comp === null) continue;
|
|
154
|
-
|
|
155
|
-
// by default we use the component guid as a key - order of the components in the scene doesnt matter with this approach
|
|
156
|
-
// this is to prevent cases where multiple GLBs are loaded with the same component guid
|
|
157
|
-
const idProviderKey = comp.guid;
|
|
158
|
-
if (idProviderKey) {
|
|
159
|
-
if (!idProviderCache.has(idProviderKey)) {
|
|
160
|
-
if (debug) console.log("Creating InstanceIdProvider with key \"" + idProviderKey + "\" for component " + comp[originalComponentNameKey]);
|
|
161
|
-
idProviderCache.set(idProviderKey, new InstantiateIdProvider(idProviderKey));
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
else if (debug) console.warn("Can not create IdProvider: component " + comp[originalComponentNameKey] + " has no guid", comp.guid);
|
|
165
|
-
const componentIdProvider = idProviderCache.get(idProviderKey) || idProvider
|
|
166
|
-
|
|
167
|
-
const prev = comp.guid;
|
|
168
|
-
comp.guid = componentIdProvider.generateUUID();
|
|
169
|
-
if (prev && prev !== "invalid")
|
|
170
|
-
guidsMap[prev] = comp.guid;
|
|
171
|
-
if (comp.resolveGuids)
|
|
172
|
-
resolveGuids.push(comp);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
if (obj.children) {
|
|
177
|
-
for (const child of obj.children) {
|
|
178
|
-
recursiveCreateGuids(child as IGameObject, idProvider, guidsMap, resolveGuids);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
114
|
declare interface IGltfbuiltinComponent {
|
|
184
115
|
name: string;
|
|
185
116
|
}
|