@needle-tools/engine 5.1.0-alpha.3 → 5.1.0-alpha.5
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 +68 -0
- package/SKILL.md +4 -1
- package/components.needle.json +1 -1
- package/dist/{needle-engine.bundle-DF01sSGQ.js → needle-engine.bundle-C-LG00ZZ.js} +10681 -10100
- package/dist/needle-engine.bundle-D7tzaiYE.min.js +1733 -0
- package/dist/{needle-engine.bundle-C-ixARur.umd.cjs → needle-engine.bundle-OPkPmdUM.umd.cjs} +161 -161
- package/dist/needle-engine.d.ts +1349 -317
- package/dist/needle-engine.js +556 -555
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/three.js +1 -0
- package/dist/three.min.js +21 -21
- package/dist/three.umd.cjs +16 -16
- package/lib/engine/api.d.ts +5 -0
- package/lib/engine/api.js +4 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/codegen/register_types.js +10 -18
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/engine_camera.fit.js +16 -4
- package/lib/engine/engine_camera.fit.js.map +1 -1
- package/lib/engine/engine_context.d.ts +20 -7
- package/lib/engine/engine_context.js +31 -15
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_context_eventbus.d.ts +47 -0
- package/lib/engine/engine_context_eventbus.js +47 -0
- package/lib/engine/engine_context_eventbus.js.map +1 -0
- 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_input.d.ts +23 -4
- package/lib/engine/engine_input.js +2 -1
- package/lib/engine/engine_input.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 +21 -3
- package/lib/engine/engine_physics_rapier.js +94 -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 +29 -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/AnimationBuilder.d.ts +158 -0
- package/lib/engine-components/AnimationBuilder.js +305 -0
- package/lib/engine-components/AnimationBuilder.js.map +1 -0
- package/lib/engine-components/Animator.d.ts +6 -0
- package/lib/engine-components/Animator.js +23 -13
- package/lib/engine-components/Animator.js.map +1 -1
- package/lib/engine-components/AnimatorController.builder.d.ts +191 -0
- package/lib/engine-components/AnimatorController.builder.js +263 -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 +33 -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/ContactShadows.d.ts +1 -0
- package/lib/engine-components/ContactShadows.js +14 -1
- package/lib/engine-components/ContactShadows.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/DropListener.js +3 -0
- package/lib/engine-components/DropListener.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/OrbitControls.d.ts +0 -2
- package/lib/engine-components/OrbitControls.js +14 -1
- package/lib/engine-components/OrbitControls.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/SceneSwitcher.js +3 -0
- package/lib/engine-components/SceneSwitcher.js.map +1 -1
- package/lib/engine-components/api.d.ts +2 -1
- package/lib/engine-components/api.js +2 -1
- package/lib/engine-components/api.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +7 -13
- package/lib/engine-components/codegen/components.js +7 -13
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
- package/lib/engine-components/timeline/PlayableDirector.d.ts +21 -11
- package/lib/engine-components/timeline/PlayableDirector.js +75 -67
- 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 +413 -0
- package/lib/engine-components/timeline/TimelineBuilder.js +506 -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 +37 -6
- package/lib/engine-components/timeline/TimelineTracks.js +92 -26
- 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/lib/engine-components/web/CursorFollow.d.ts +0 -1
- package/lib/engine-components/web/CursorFollow.js +0 -1
- package/lib/engine-components/web/CursorFollow.js.map +1 -1
- package/package.json +2 -83
- package/plugins/common/cloud.js +6 -1
- 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/license.js +19 -1
- package/plugins/vite/reload.js +1 -1
- package/plugins/vite/server.js +2 -1
- package/src/engine/api.ts +7 -0
- package/src/engine/codegen/register_types.ts +10 -18
- package/src/engine/engine_camera.fit.ts +15 -4
- package/src/engine/engine_context.ts +32 -16
- package/src/engine/engine_context_eventbus.ts +73 -0
- 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_input.ts +27 -6
- 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 +102 -33
- 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 +46 -27
- package/src/engine/engine_util_decorator.ts +7 -2
- package/src/engine/engine_utils.ts +16 -5
- package/src/engine-components/AnimationBuilder.ts +472 -0
- package/src/engine-components/Animator.ts +24 -12
- package/src/engine-components/AnimatorController.builder.ts +387 -0
- package/src/engine-components/AnimatorController.ts +20 -291
- package/src/engine-components/Collider.ts +66 -18
- package/src/engine-components/Component.ts +118 -20
- package/src/engine-components/ContactShadows.ts +15 -1
- package/src/engine-components/DragControls.ts +0 -9
- package/src/engine-components/DropListener.ts +3 -0
- 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/OrbitControls.ts +16 -5
- package/src/engine-components/RigidBody.ts +18 -4
- package/src/engine-components/SceneSwitcher.ts +3 -0
- package/src/engine-components/api.ts +2 -1
- package/src/engine-components/codegen/components.ts +7 -13
- package/src/engine-components/timeline/PlayableDirector.ts +83 -81
- package/src/engine-components/timeline/SignalAsset.ts +4 -1
- package/src/engine-components/timeline/TimelineBuilder.ts +824 -0
- package/src/engine-components/timeline/TimelineModels.ts +5 -1
- package/src/engine-components/timeline/TimelineTracks.ts +96 -27
- package/src/engine-components/timeline/index.ts +2 -1
- package/src/engine-components/web/CursorFollow.ts +0 -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
|
@@ -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
|
}
|
|
@@ -343,14 +343,33 @@ export class Input implements IInput {
|
|
|
343
343
|
private readonly _eventListeners: Record<string, RegisteredEventListenerValue> = {};
|
|
344
344
|
|
|
345
345
|
/** Adds an event listener for the specified event type. The callback will be called when the event is triggered.
|
|
346
|
+
*
|
|
347
|
+
* Returns an unsubscribe function — call it to remove the listener.
|
|
348
|
+
* Pass it to {@link Behaviour.autoCleanup} for automatic lifecycle management.
|
|
349
|
+
*
|
|
346
350
|
* @param type The event type to listen for
|
|
347
351
|
* @param callback The callback to call when the event is triggered
|
|
348
352
|
* @param options The options for adding the event listener.
|
|
349
|
-
* @
|
|
353
|
+
* @returns A function that removes the event listener when called.
|
|
354
|
+
*
|
|
355
|
+
* @example With autoCleanup (recommended)
|
|
350
356
|
* ```ts
|
|
351
|
-
*
|
|
357
|
+
* export class MyComponent extends Behaviour {
|
|
358
|
+
* onEnable() {
|
|
359
|
+
* this.autoCleanup(this.context.input.addEventListener("pointerdown", (evt) => {
|
|
360
|
+
* console.log("Pointer down", evt.pointerId, evt.pointerType);
|
|
361
|
+
* }));
|
|
362
|
+
* }
|
|
363
|
+
* // Listener is automatically removed on disable — no manual cleanup needed!
|
|
364
|
+
* }
|
|
365
|
+
* ```
|
|
366
|
+
* @example Manual unsubscribe
|
|
367
|
+
* ```ts
|
|
368
|
+
* const off = input.addEventListener("pointerdown", (evt) => {
|
|
352
369
|
* console.log("Pointer down", evt.pointerId, evt.pointerType);
|
|
353
370
|
* });
|
|
371
|
+
* // later
|
|
372
|
+
* off();
|
|
354
373
|
* ```
|
|
355
374
|
* @example Adding a listener that is called after all other listeners
|
|
356
375
|
* By using a higher value for the queue the listener will be called after other listeners (default queue is 0).
|
|
@@ -366,14 +385,14 @@ export class Input implements IInput {
|
|
|
366
385
|
* }, { once: true });
|
|
367
386
|
* ```
|
|
368
387
|
*/
|
|
369
|
-
addEventListener(type: PointerEventNames, callback: PointerEventListener, options?: EventListenerOptions);
|
|
370
|
-
addEventListener(type: KeyboardEventNames, callback: KeyboardEventListener, options?: EventListenerOptions);
|
|
371
|
-
addEventListener(type: InputEvents | InputEventNames, callback: InputEventListener, options?: EventListenerOptions): void {
|
|
388
|
+
addEventListener(type: PointerEventNames, callback: PointerEventListener, options?: EventListenerOptions): () => void;
|
|
389
|
+
addEventListener(type: KeyboardEventNames, callback: KeyboardEventListener, options?: EventListenerOptions): () => void;
|
|
390
|
+
addEventListener(type: InputEvents | InputEventNames, callback: InputEventListener, options?: EventListenerOptions): () => void {
|
|
372
391
|
if (!this._eventListeners[type]) this._eventListeners[type] = [];
|
|
373
392
|
|
|
374
393
|
if (!callback || typeof callback !== "function") {
|
|
375
394
|
console.error("Invalid call to addEventListener: callback is required and must be a function!");
|
|
376
|
-
return;
|
|
395
|
+
return () => {};
|
|
377
396
|
}
|
|
378
397
|
|
|
379
398
|
if (!options) options = {};
|
|
@@ -392,6 +411,8 @@ export class Input implements IInput {
|
|
|
392
411
|
} else {
|
|
393
412
|
queueListeners.listeners.push({ callback, options });
|
|
394
413
|
}
|
|
414
|
+
|
|
415
|
+
return () => this.removeEventListener(type as any, callback as any, options);
|
|
395
416
|
}
|
|
396
417
|
/** Removes the event listener from the specified event type. If no queue is specified the listener will be removed from all queues.
|
|
397
418
|
* @param type The event type to remove the listener from
|