@needle-tools/engine 2.52.0-pre → 2.54.2-pre
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 +36 -0
- package/dist/needle-engine.d.ts +3018 -2680
- package/dist/needle-engine.js +439 -439
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +41 -41
- package/dist/needle-engine.min.js.map +4 -4
- package/dist/needle-engine.tsbuildinfo +1 -0
- package/lib/engine/codegen/register_types.d.ts +1 -0
- package/lib/engine/codegen/register_types.js +346 -0
- package/lib/engine/codegen/register_types.js.map +1 -0
- package/lib/engine/debug/debug.d.ts +1 -0
- package/lib/engine/debug/debug.js +4 -0
- package/lib/engine/debug/debug.js.map +1 -1
- package/lib/engine/debug/debug_console.js +2 -1
- package/lib/engine/debug/debug_console.js.map +1 -1
- package/lib/engine/debug/debug_overlay.js +3 -1
- package/lib/engine/debug/debug_overlay.js.map +1 -1
- package/lib/engine/engine_components.js +2 -2
- package/lib/engine/engine_components.js.map +1 -1
- package/lib/engine/engine_default_parameters.d.ts +2 -2
- package/lib/engine/engine_element.js +4 -2
- package/lib/engine/engine_element.js.map +1 -1
- package/lib/engine/engine_element_loading.d.ts +1 -0
- package/lib/engine/engine_element_loading.js +17 -6
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_element_overlay.js +4 -2
- package/lib/engine/engine_element_overlay.js.map +1 -1
- package/lib/engine/engine_fileloader.d.ts +3 -0
- package/lib/engine/engine_fileloader.js +8 -0
- package/lib/engine/engine_fileloader.js.map +1 -0
- package/lib/engine/engine_generic_utils.d.ts +1 -0
- package/lib/engine/engine_generic_utils.js +14 -0
- package/lib/engine/engine_generic_utils.js.map +1 -0
- package/lib/engine/engine_input.js +4 -0
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_networking_instantiate.d.ts +1 -1
- package/lib/engine/engine_networking_instantiate.js +3 -0
- package/lib/engine/engine_networking_instantiate.js.map +1 -1
- package/lib/engine/engine_networking_websocket.d.ts +1 -0
- package/lib/engine/engine_networking_websocket.js +1 -1
- package/lib/engine/engine_networking_websocket.js.map +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.d.ts +6 -0
- package/lib/engine/engine_serialization_builtin_serializer.js +35 -7
- 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 +6 -0
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_setup.js +2 -2
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_texture.d.ts +3 -0
- package/lib/engine/engine_texture.js +4 -0
- package/lib/engine/engine_texture.js.map +1 -0
- package/lib/engine/engine_utils.d.ts +1 -1
- package/lib/engine/engine_utils.js +3 -0
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_components.d.ts +1 -1
- package/lib/engine/extensions/NEEDLE_progressive.d.ts +40 -0
- package/lib/engine/extensions/NEEDLE_progressive.js +322 -0
- package/lib/engine/extensions/NEEDLE_progressive.js.map +1 -0
- package/lib/engine/extensions/extensions.js +2 -2
- package/lib/engine/extensions/extensions.js.map +1 -1
- package/lib/engine-components/Camera.js +17 -2
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/GroundProjection.d.ts +2 -1
- package/lib/engine-components/GroundProjection.js +19 -12
- package/lib/engine-components/GroundProjection.js.map +1 -1
- package/lib/engine-components/Light.js +1 -0
- package/lib/engine-components/Light.js.map +1 -1
- package/lib/engine-components/OrbitControls.js +6 -2
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/ParticleSystemModules.d.ts +1 -1
- package/lib/engine-components/ParticleSystemModules.js +48 -44
- package/lib/engine-components/ParticleSystemModules.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.d.ts +1 -1
- package/lib/engine-components/Renderer.d.ts +1 -1
- package/lib/engine-components/Renderer.js +4 -9
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/Voip.js +13 -4
- package/lib/engine-components/Voip.js.map +1 -1
- package/lib/engine-components/Volume.js +8 -1
- package/lib/engine-components/Volume.js.map +1 -1
- package/lib/engine-components/WebXR.d.ts +2 -2
- package/lib/engine-components/WebXRAvatar.d.ts +1 -1
- package/lib/engine-components/codegen/components.d.ts +99 -95
- package/lib/engine-components/codegen/components.js +99 -95
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/export/{GltfExport.d.ts → gltf/GltfExport.d.ts} +2 -2
- package/lib/engine-components/export/{GltfExport.js → gltf/GltfExport.js} +7 -7
- package/lib/engine-components/export/gltf/GltfExport.js.map +1 -0
- package/lib/engine-components/export/usdz/Extension.d.ts +9 -0
- package/lib/engine-components/export/usdz/Extension.js +2 -0
- package/lib/engine-components/export/usdz/Extension.js.map +1 -0
- package/lib/engine-components/export/usdz/USDZExporter.d.ts +26 -0
- package/lib/engine-components/export/usdz/USDZExporter.js +209 -0
- package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -0
- package/lib/engine-components/export/usdz/extensions/Animation.d.ts +44 -0
- package/lib/engine-components/export/usdz/extensions/Animation.js +264 -0
- package/lib/engine-components/export/usdz/extensions/Animation.js.map +1 -0
- package/lib/engine-components/export/usdz/types.d.ts +34 -0
- package/lib/engine-components/export/usdz/types.js +2 -0
- package/lib/engine-components/export/usdz/types.js.map +1 -0
- package/lib/engine-components/export/usdz/utils/animationutils.d.ts +3 -0
- package/lib/engine-components/export/usdz/utils/animationutils.js +46 -0
- package/lib/engine-components/export/usdz/utils/animationutils.js.map +1 -0
- package/lib/engine-components/export/usdz/utils/quicklook.d.ts +2 -0
- package/lib/engine-components/export/usdz/utils/quicklook.js +36 -0
- package/lib/engine-components/export/usdz/utils/quicklook.js.map +1 -0
- package/lib/engine-components/export/usdz/utils/timeutils.d.ts +1 -0
- package/lib/engine-components/export/usdz/utils/timeutils.js +15 -0
- package/lib/engine-components/export/usdz/utils/timeutils.js.map +1 -0
- package/lib/engine-components/ui/Button.js +30 -0
- package/lib/engine-components/ui/Button.js.map +1 -1
- package/lib/engine-components/ui/Graphic.d.ts +2 -0
- package/lib/engine-components/ui/Graphic.js +15 -0
- package/lib/engine-components/ui/Graphic.js.map +1 -1
- package/lib/engine-components/ui/InputField.d.ts +2 -0
- package/lib/engine-components/ui/InputField.js +23 -1
- package/lib/engine-components/ui/InputField.js.map +1 -1
- package/lib/engine-components/ui/Utils.d.ts +4 -1
- package/lib/engine-components/ui/Utils.js +15 -12
- package/lib/engine-components/ui/Utils.js.map +1 -1
- package/lib/engine-components-experimental/Presentation.d.ts +6 -0
- package/lib/engine-components-experimental/Presentation.js +11 -0
- package/lib/engine-components-experimental/Presentation.js.map +1 -0
- package/lib/engine-components-experimental/annotation/LineDrawer.d.ts +18 -0
- package/lib/engine-components-experimental/annotation/LineDrawer.js +175 -0
- package/lib/engine-components-experimental/annotation/LineDrawer.js.map +1 -0
- package/lib/engine-components-experimental/annotation/LinesManager.d.ts +54 -0
- package/lib/engine-components-experimental/annotation/LinesManager.js +155 -0
- package/lib/engine-components-experimental/annotation/LinesManager.js.map +1 -0
- package/lib/engine-components-experimental/networking/PlayerSync.d.ts +26 -0
- package/lib/engine-components-experimental/networking/PlayerSync.js +121 -0
- package/lib/engine-components-experimental/networking/PlayerSync.js.map +1 -0
- package/lib/engine-schemes/vec2.d.ts +10 -0
- package/lib/engine-schemes/vec2.js +26 -0
- package/lib/engine-schemes/vec2.js.map +1 -0
- package/lib/include/three/ARButton.d.ts +3 -0
- package/lib/include/three/ARButton.js +158 -0
- package/lib/include/three/ARButton.js.map +1 -0
- package/lib/include/three/EXT_mesh_gpu_instancing_exporter.d.ts +6 -0
- package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js +46 -0
- package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js.map +1 -0
- package/lib/include/three/VRButton.d.ts +5 -0
- package/lib/include/three/VRButton.js +122 -0
- package/lib/include/three/VRButton.js.map +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +2 -2
- package/src/engine/codegen/register_types.js +212 -204
- package/src/engine/debug/debug.ts +5 -0
- package/src/engine/debug/debug_console.ts +3 -2
- package/src/engine/debug/debug_overlay.ts +3 -1
- package/src/engine/engine_components.ts +2 -2
- package/src/engine/engine_element.ts +4 -2
- package/src/engine/engine_element_loading.ts +13 -6
- package/src/engine/engine_element_overlay.ts +4 -2
- package/src/engine/engine_input.ts +4 -0
- package/src/engine/engine_networking_instantiate.ts +4 -1
- package/src/engine/engine_networking_websocket.ts +3 -1
- package/src/engine/engine_serialization_builtin_serializer.ts +39 -8
- package/src/engine/engine_serialization_core.ts +7 -1
- package/src/engine/engine_setup.ts +2 -2
- package/src/engine/engine_texture.ts +6 -0
- package/src/engine/engine_utils.ts +3 -1
- package/src/engine/extensions/NEEDLE_progressive.ts +357 -0
- package/src/engine/extensions/extensions.ts +2 -2
- package/src/engine-components/Camera.ts +17 -3
- package/src/engine-components/GroundProjection.ts +18 -12
- package/src/engine-components/Light.ts +3 -1
- package/src/engine-components/OrbitControls.ts +7 -3
- package/src/engine-components/ParticleSystemModules.ts +50 -47
- package/src/engine-components/Renderer.ts +6 -10
- package/src/engine-components/Voip.ts +14 -4
- package/src/engine-components/Volume.ts +8 -1
- package/src/engine-components/WebXR.ts +2 -2
- package/src/engine-components/codegen/components.ts +99 -95
- package/src/engine-components/export/{GltfExport.ts → gltf/GltfExport.ts} +7 -7
- package/src/engine-components/export/usdz/Extension.ts +12 -0
- package/src/engine-components/export/usdz/USDZExporter.ts +233 -0
- package/src/engine-components/export/usdz/extensions/Animation.ts +306 -0
- package/src/engine-components/export/usdz/types.ts +39 -0
- package/src/engine-components/export/usdz/utils/animationutils.ts +60 -0
- package/src/engine-components/export/usdz/utils/quicklook.ts +43 -0
- package/src/engine-components/export/usdz/utils/timeutils.ts +20 -0
- package/src/engine-components/ui/Button.ts +8 -8
- package/src/engine-components/ui/Graphic.ts +15 -1
- package/src/engine-components/ui/InputField.ts +25 -2
- package/src/engine-components/ui/Utils.ts +17 -14
- package/src/engine-components-experimental/annotation/LineDrawer.ts +10 -7
- package/src/engine-components-experimental/annotation/LinesManager.ts +6 -6
- package/src/engine-components-experimental/networking/PlayerSync.ts +1 -1
- package/lib/engine/engine_caching.d.ts +0 -0
- package/lib/engine/engine_caching.js +0 -2
- package/lib/engine/engine_caching.js.map +0 -1
- package/lib/engine/extensions/NEEDLE_deferred_texture.d.ts +0 -18
- package/lib/engine/extensions/NEEDLE_deferred_texture.js +0 -194
- package/lib/engine/extensions/NEEDLE_deferred_texture.js.map +0 -1
- package/lib/engine/tests/simulate_avatars.d.ts +0 -0
- package/lib/engine/tests/simulate_avatars.js +0 -3
- package/lib/engine/tests/simulate_avatars.js.map +0 -1
- package/lib/engine-components/NavMesh.d.ts +0 -0
- package/lib/engine-components/NavMesh.js +0 -101
- package/lib/engine-components/NavMesh.js.map +0 -1
- package/lib/engine-components/ParticleSystemBehaviours.d.ts +0 -0
- package/lib/engine-components/ParticleSystemBehaviours.js +0 -2
- package/lib/engine-components/ParticleSystemBehaviours.js.map +0 -1
- package/lib/engine-components/SpringJoint.d.ts +0 -0
- package/lib/engine-components/SpringJoint.js +0 -43
- package/lib/engine-components/SpringJoint.js.map +0 -1
- package/lib/engine-components/export/GltfExport.js.map +0 -1
- package/lib/engine-components/ui/CanvasScaler.d.ts +0 -0
- package/lib/engine-components/ui/CanvasScaler.js +0 -17
- package/lib/engine-components/ui/CanvasScaler.js.map +0 -1
- package/src/engine/dist/engine_three_utils.js +0 -279
- package/src/engine/engine_caching.ts +0 -0
- package/src/engine/extensions/NEEDLE_deferred_texture.ts +0 -217
- package/src/engine/tests/simulate_avatars.ts +0 -2
- package/src/engine-components/NavMesh.ts +0 -117
- package/src/engine-components/ParticleSystemBehaviours.ts +0 -0
- package/src/engine-components/SpringJoint.ts +0 -45
- package/src/engine-components/ui/CanvasScaler.ts +0 -21
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { GameObject } from "../../../Component";
|
|
2
|
+
import { getParam } from "../../../../engine/engine_utils";
|
|
3
|
+
import { Object3D, Color, Matrix4, MeshStandardMaterial, Vector3, Quaternion, Interpolant } from "three";
|
|
4
|
+
//@ts-ignore
|
|
5
|
+
import { USDZObject, buildMatrix } from "three/examples/jsm/exporters/USDZExporter"
|
|
6
|
+
import { IUSDZExporterExtension } from "../Extension";
|
|
7
|
+
|
|
8
|
+
const debug = getParam("debugusdzanimation");
|
|
9
|
+
|
|
10
|
+
export interface UsdzAnimation {
|
|
11
|
+
createAnimation(ext: AnimationExtension, model: USDZObject, context);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type AnimationClipCollection = Array<{ root: Object3D, clips: Array<THREE.AnimationClip> }>;
|
|
15
|
+
|
|
16
|
+
export class RegisteredAnimationInfo {
|
|
17
|
+
|
|
18
|
+
get start(): number { return this.ext.getStartTime01(this.root, this.clip); }
|
|
19
|
+
get duration(): number { return this.clip.duration; }
|
|
20
|
+
|
|
21
|
+
private ext: AnimationExtension;
|
|
22
|
+
private root: Object3D;
|
|
23
|
+
private clip: THREE.AnimationClip;
|
|
24
|
+
|
|
25
|
+
constructor(ext: AnimationExtension, root: THREE.Object3D, clip: THREE.AnimationClip) {
|
|
26
|
+
this.ext = ext;
|
|
27
|
+
this.root = root;
|
|
28
|
+
this.clip = clip;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class TransformData {
|
|
33
|
+
clip: THREE.AnimationClip;
|
|
34
|
+
pos?: THREE.KeyframeTrack;
|
|
35
|
+
rot?: THREE.KeyframeTrack;
|
|
36
|
+
scale?: THREE.KeyframeTrack;
|
|
37
|
+
get frameRate(): number { return 60; }
|
|
38
|
+
|
|
39
|
+
private ext: AnimationExtension;
|
|
40
|
+
private root: Object3D;
|
|
41
|
+
private target: Object3D;
|
|
42
|
+
|
|
43
|
+
constructor(ext: AnimationExtension, root: Object3D, target: Object3D, clip: THREE.AnimationClip) {
|
|
44
|
+
this.ext = ext;
|
|
45
|
+
this.root = root;
|
|
46
|
+
this.target = target;
|
|
47
|
+
this.clip = clip;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
addTrack(track) {
|
|
51
|
+
if (track.name.endsWith("position")) this.pos = track;
|
|
52
|
+
if (track.name.endsWith("quaternion")) this.rot = track;
|
|
53
|
+
if (track.name.endsWith("scale")) this.scale = track;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
getFrames(): number {
|
|
57
|
+
return Math.max(this.pos?.times?.length ?? 0, this.rot?.times?.length ?? 0, this.scale?.times?.length ?? 0);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
getDuration(): number {
|
|
61
|
+
const times = this.pos?.times ?? this.rot?.times ?? this.scale?.times;
|
|
62
|
+
if (!times) return 0;
|
|
63
|
+
return times[times.length - 1];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getStartTime(arr: TransformData[]): number {
|
|
67
|
+
let sum = 0;
|
|
68
|
+
for (let i = 0; i < arr.length; i++) {
|
|
69
|
+
const entry = arr[i];
|
|
70
|
+
if (entry === this) {
|
|
71
|
+
return sum;
|
|
72
|
+
}
|
|
73
|
+
else sum += entry.getDuration();
|
|
74
|
+
}
|
|
75
|
+
return sum;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
declare type AnimationDict = Map<Object3D, Array<TransformData>>;
|
|
80
|
+
|
|
81
|
+
export class AnimationExtension implements IUSDZExporterExtension {
|
|
82
|
+
|
|
83
|
+
get extensionName(): string { return "animation" }
|
|
84
|
+
private dict: AnimationDict = new Map();
|
|
85
|
+
// private rootTargetMap: Map<Object3D, Object3D[]> = new Map();
|
|
86
|
+
private rootTargetMap: Map<Object3D, Object3D[]> = new Map();
|
|
87
|
+
|
|
88
|
+
getStartTime01(root: Object3D, clip: THREE.AnimationClip) {
|
|
89
|
+
const targets = this.rootTargetMap.get(root);
|
|
90
|
+
if (!targets) return Infinity;
|
|
91
|
+
let longestStartTime: number = -1;
|
|
92
|
+
for (const target of targets) {
|
|
93
|
+
const data = this.dict.get(target);
|
|
94
|
+
let startTimeInSeconds = 0;
|
|
95
|
+
if (data?.length) {
|
|
96
|
+
for (const entry of data) {
|
|
97
|
+
if (entry.clip === clip) {
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
startTimeInSeconds += entry.getDuration();
|
|
101
|
+
}
|
|
102
|
+
longestStartTime = Math.max(longestStartTime, startTimeInSeconds);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
console.warn("No animation found on root", root, clip, data);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return longestStartTime;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
registerAnimation(root: Object3D, clip: THREE.AnimationClip): RegisteredAnimationInfo | null {
|
|
112
|
+
if (!clip || !root) return null;
|
|
113
|
+
if (!this.rootTargetMap.has(root)) this.rootTargetMap.set(root, []);
|
|
114
|
+
// this.rootTargetMap.get(root)?.push(clip);
|
|
115
|
+
|
|
116
|
+
for (const track of clip.tracks) {
|
|
117
|
+
const trackName = track.name.split(".")[2];
|
|
118
|
+
const animationTarget = root.getObjectByName(trackName); // object name
|
|
119
|
+
if (!animationTarget) {
|
|
120
|
+
console.warn("no object found for track", track.name, "using " + root.name + " instead");
|
|
121
|
+
continue;
|
|
122
|
+
// // if no object was found it might be that we have a component that references an animation clip but wants to target another object
|
|
123
|
+
// // in that case UnityGLTF writes the name of the component as track targets because it doesnt know of the intented target
|
|
124
|
+
// animationTarget = root;
|
|
125
|
+
}
|
|
126
|
+
if (!this.dict.has(animationTarget)) {
|
|
127
|
+
this.dict.set(animationTarget, []);
|
|
128
|
+
}
|
|
129
|
+
const arr = this.dict.get(animationTarget);
|
|
130
|
+
if (!arr) continue;
|
|
131
|
+
|
|
132
|
+
let model = arr.find(x => x.clip === clip);
|
|
133
|
+
if (!model) {
|
|
134
|
+
model = new TransformData(this, root, animationTarget, clip);
|
|
135
|
+
arr.push(model);
|
|
136
|
+
}
|
|
137
|
+
model.addTrack(track);
|
|
138
|
+
|
|
139
|
+
const targets = this.rootTargetMap.get(root);
|
|
140
|
+
if (!targets?.includes(animationTarget)) targets?.push(animationTarget);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// get the entry for this object.
|
|
144
|
+
// This doesnt work if we have clips animating multiple objects
|
|
145
|
+
const info = new RegisteredAnimationInfo(this, root, clip);
|
|
146
|
+
return info;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
onAfterHierarchy(_context) {
|
|
150
|
+
if (debug)
|
|
151
|
+
console.log(this.dict);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private serializers: SerializeAnimation[] = [];
|
|
155
|
+
|
|
156
|
+
onAfterBuildDocument(_context: any) {
|
|
157
|
+
for (const ser of this.serializers) {
|
|
158
|
+
const parent = ser.model?.parent;
|
|
159
|
+
const isEmptyParent = parent?.isDynamic === true;
|
|
160
|
+
if (debug)
|
|
161
|
+
console.log(isEmptyParent, ser.model?.parent);
|
|
162
|
+
if (isEmptyParent) {
|
|
163
|
+
ser.registerCallback(parent);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
onExportObject(object, model: USDZObject, _context) {
|
|
169
|
+
|
|
170
|
+
GameObject.foreachComponent(object, (comp) => {
|
|
171
|
+
const c = comp as unknown as UsdzAnimation;
|
|
172
|
+
if (typeof c.createAnimation === "function") {
|
|
173
|
+
c.createAnimation(this, model, _context);
|
|
174
|
+
}
|
|
175
|
+
}, false);
|
|
176
|
+
|
|
177
|
+
// we need to be able to retarget serialization to empty parents before actually serializing (we do that in another callback)
|
|
178
|
+
const ser = new SerializeAnimation(object, this.dict);
|
|
179
|
+
this.serializers.push(ser);
|
|
180
|
+
ser.registerCallback(model);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class SerializeAnimation {
|
|
187
|
+
|
|
188
|
+
object: Object3D;
|
|
189
|
+
dict: AnimationDict;
|
|
190
|
+
model: USDZObject;
|
|
191
|
+
|
|
192
|
+
private callback?: Function;
|
|
193
|
+
|
|
194
|
+
constructor(object: Object3D, dict: AnimationDict) {
|
|
195
|
+
this.object = object;
|
|
196
|
+
this.dict = dict;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
registerCallback(model: USDZObject) {
|
|
200
|
+
if (this.model && this.callback) {
|
|
201
|
+
this.model.removeEventListener("serialize", this.callback);
|
|
202
|
+
}
|
|
203
|
+
if (!this.callback)
|
|
204
|
+
this.callback = this.onSerialize.bind(this);
|
|
205
|
+
if (debug)
|
|
206
|
+
console.log("REPARENT", model);
|
|
207
|
+
this.model = model;
|
|
208
|
+
this.model.addEventListener("serialize", this.callback);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
onSerialize(writer, _context) {
|
|
212
|
+
if (debug)
|
|
213
|
+
console.log("SERIALIZE", this.model.name, this.object.type);
|
|
214
|
+
// do we have a track for this?
|
|
215
|
+
const object = this.object;
|
|
216
|
+
const arr = this.dict.get(object);
|
|
217
|
+
if (!arr) return;
|
|
218
|
+
|
|
219
|
+
// console.log("found data for", object, "exporting animation now");
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
// assumption: all tracks have the same time values
|
|
224
|
+
// TODO collect all time values and then use the interpolator to access
|
|
225
|
+
|
|
226
|
+
const composedTransform = new Matrix4();
|
|
227
|
+
const translation = new Vector3();
|
|
228
|
+
const rotation = new Quaternion();
|
|
229
|
+
const scale = new Vector3(1, 1, 1);
|
|
230
|
+
|
|
231
|
+
// TODO doesn't support individual time arrays right now
|
|
232
|
+
// could use these in case we don't have time values that are identical
|
|
233
|
+
/*
|
|
234
|
+
const translationInterpolant = o.pos?.createInterpolant() as THREE.Interpolant;
|
|
235
|
+
const rotationInterpolant = o.rot?.createInterpolant() as THREE.Interpolant;
|
|
236
|
+
const scaleInterpolant = o.scale?.createInterpolant() as THREE.Interpolant;
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
writer.appendLine("matrix4d xformOp:transform.timeSamples = {");
|
|
240
|
+
writer.indent++;
|
|
241
|
+
|
|
242
|
+
for (const transformData of arr) {
|
|
243
|
+
let timesArray = transformData.pos?.times;
|
|
244
|
+
if (!timesArray || transformData.rot && transformData.rot.times?.length > timesArray?.length) timesArray = transformData.rot?.times;
|
|
245
|
+
if (!timesArray || transformData.scale && transformData.scale.times?.length > timesArray?.length) timesArray = transformData.scale?.times;
|
|
246
|
+
if (!timesArray) {
|
|
247
|
+
console.error("got an animated object but no time values??", object, transformData);
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
const startTime = transformData.getStartTime(arr);
|
|
251
|
+
|
|
252
|
+
if (debug)
|
|
253
|
+
writer.appendLine(transformData.clip.name + ": start=" + startTime.toFixed(3) + ", length=" + transformData.getDuration().toFixed(3) + ", frames=" + transformData.getFrames());
|
|
254
|
+
|
|
255
|
+
// ignore until https://github.com/three-types/three-ts-types/pull/293 gets merged
|
|
256
|
+
//@ts-ignore
|
|
257
|
+
const positionInterpolant: Interpolant | undefined = transformData.pos?.createInterpolant();
|
|
258
|
+
//@ts-ignore
|
|
259
|
+
const rotationInterpolant: Interpolant | undefined = transformData.rot?.createInterpolant();
|
|
260
|
+
//@ts-ignore
|
|
261
|
+
const scaleInterpolant: Interpolant | undefined = transformData.scale?.createInterpolant();
|
|
262
|
+
|
|
263
|
+
if (!positionInterpolant) translation.set(object.position.x, object.position.y, object.position.z);
|
|
264
|
+
if (!rotationInterpolant) rotation.set(object.quaternion.x, object.quaternion.y, object.quaternion.z, object.quaternion.w);
|
|
265
|
+
if (!scaleInterpolant) scale.set(object.scale.x, object.scale.y, object.scale.z);
|
|
266
|
+
|
|
267
|
+
for (let index = 0; index < timesArray.length; index++) {
|
|
268
|
+
const time = timesArray[index];
|
|
269
|
+
|
|
270
|
+
if (positionInterpolant) {
|
|
271
|
+
const pos = positionInterpolant.evaluate(time);
|
|
272
|
+
translation.set(pos[0], pos[1], pos[2]);
|
|
273
|
+
}
|
|
274
|
+
if (rotationInterpolant) {
|
|
275
|
+
const quat = rotationInterpolant.evaluate(time);
|
|
276
|
+
rotation.set(quat[0], quat[1], quat[2], quat[3]);
|
|
277
|
+
}
|
|
278
|
+
if (scaleInterpolant) {
|
|
279
|
+
const scale = scaleInterpolant.evaluate(time);
|
|
280
|
+
scale.set(scale[0], scale[1], scale[2]);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
composedTransform.compose(translation, rotation, scale);
|
|
284
|
+
|
|
285
|
+
let line = `${(startTime + time) * transformData.frameRate}: ${buildMatrix(composedTransform)},`;
|
|
286
|
+
if (debug) line = "#" + index + "\t" + line;
|
|
287
|
+
writer.appendLine(line);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
}
|
|
291
|
+
writer.indent--;
|
|
292
|
+
writer.appendLine("}");
|
|
293
|
+
|
|
294
|
+
/*
|
|
295
|
+
let transform3 = new Matrix4();
|
|
296
|
+
transform3.compose(0.2,0,0);
|
|
297
|
+
const transform = buildMatrix(model.matrix);
|
|
298
|
+
const transform2 = buildMatrix(transform3.multiply(model.matrix));
|
|
299
|
+
|
|
300
|
+
writer.appendLine(`matrix4d xformOp:transform.timeSamples = {
|
|
301
|
+
0: ${transform},
|
|
302
|
+
30: ${transform2}
|
|
303
|
+
}`);
|
|
304
|
+
*/
|
|
305
|
+
}
|
|
306
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Object3D, Matrix4, Material, BufferGeometry } from "three";
|
|
2
|
+
|
|
3
|
+
// keep in sync with USDZExporter.js
|
|
4
|
+
|
|
5
|
+
/** implementation is in three */
|
|
6
|
+
export declare class USDZDocument {
|
|
7
|
+
name: string;
|
|
8
|
+
get isDocumentRoot(): boolean;
|
|
9
|
+
add(obj: USDZObject);
|
|
10
|
+
remove(obj: USDZObject);
|
|
11
|
+
traverse(callback: (obj: USDZObject) => void);
|
|
12
|
+
findById(uuid: string): USDZObject | undefined;
|
|
13
|
+
get isDynamic(): boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
/** implementation is in three */
|
|
19
|
+
export declare class USDZObject {
|
|
20
|
+
static createEmptyParent(parent: USDZObject);
|
|
21
|
+
uuid: string;
|
|
22
|
+
name: string;
|
|
23
|
+
matrix: Matrix4;
|
|
24
|
+
material: Material;
|
|
25
|
+
geometry: BufferGeometry;
|
|
26
|
+
parent: USDZObject | USDZDocument | null;
|
|
27
|
+
children: USDZObject[];
|
|
28
|
+
_eventListeners: { [event: string]: Function[] };
|
|
29
|
+
isDynamic: boolean;
|
|
30
|
+
|
|
31
|
+
is(obj: Object3D): boolean;
|
|
32
|
+
isEmpty(): boolean;
|
|
33
|
+
clone();
|
|
34
|
+
getPath();
|
|
35
|
+
add(child: USDZObject);
|
|
36
|
+
remove(child: USDZObject);
|
|
37
|
+
addEventListener(evt: string, listener: Function);
|
|
38
|
+
removeEventListener(evt: string, listener: Function);
|
|
39
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Animator } from "../../../Animator";
|
|
2
|
+
import { Object3D, Color, AnimationClip, KeyframeTrack } from "three";
|
|
3
|
+
import { AnimationExtension } from "../extensions/Animation";
|
|
4
|
+
import { GameObject } from "../../../Component";
|
|
5
|
+
import { getParam } from "../../../../engine/engine_utils";
|
|
6
|
+
|
|
7
|
+
const debug = getParam("debugusdz");
|
|
8
|
+
|
|
9
|
+
export function registerAnimatorsImplictly(root: Object3D, ext: AnimationExtension) {
|
|
10
|
+
|
|
11
|
+
// collect animators and their clips
|
|
12
|
+
const animationClips: { root: Object3D, clips: THREE.AnimationClip[] }[] = [];
|
|
13
|
+
const animators = GameObject.getComponentsInChildren(root, Animator);
|
|
14
|
+
|
|
15
|
+
// insert rest pose clip
|
|
16
|
+
let injectedRestPose = false;
|
|
17
|
+
|
|
18
|
+
if (debug)
|
|
19
|
+
console.log(animators);
|
|
20
|
+
|
|
21
|
+
for (const animator of animators) {
|
|
22
|
+
if (!animator || !animator.runtimeAnimatorController) continue;
|
|
23
|
+
|
|
24
|
+
if (debug)
|
|
25
|
+
console.log(animator);
|
|
26
|
+
|
|
27
|
+
const clips: THREE.AnimationClip[] = [];
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
for (const action of animator.runtimeAnimatorController.enumerateActions()) {
|
|
31
|
+
if (debug)
|
|
32
|
+
console.log(action);
|
|
33
|
+
const clip = action.getClip();
|
|
34
|
+
|
|
35
|
+
// we need to inject a rest pose clip so that the animation position is correct
|
|
36
|
+
// e.g. when the animation starts in the air and animates down we dont want the object to move under the ground
|
|
37
|
+
if (!injectedRestPose && clip.tracks.length > 0) {
|
|
38
|
+
injectedRestPose = true;
|
|
39
|
+
const track = clip.tracks[0];
|
|
40
|
+
const trackBaseName = track.name.substring(0, track.name.lastIndexOf("."));
|
|
41
|
+
const currentPositionTrack = new KeyframeTrack(trackBaseName + ".position", [0, .01], [0, 0, 0, 0, 0, 0]);
|
|
42
|
+
const currentRotationTrack = new KeyframeTrack(trackBaseName + ".quaternion", [0, .01], [0, 0, 0, 1, 0, 0, 0, 1]);
|
|
43
|
+
clips.push(new AnimationClip("rest", .01, [currentPositionTrack, currentRotationTrack]));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!clips.includes(clip))
|
|
47
|
+
clips.push(clip);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
animationClips.push({ root: animator.gameObject, clips: clips });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (debug)
|
|
54
|
+
console.log(animationClips);
|
|
55
|
+
|
|
56
|
+
for (const pair of animationClips) {
|
|
57
|
+
for (const clip of pair.clips)
|
|
58
|
+
ext.registerAnimation(pair.root, clip);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Context } from "../../../../engine/engine_setup";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export function ensureQuicklookLinkIsCreated(context: Context) : HTMLAnchorElement {
|
|
5
|
+
const existingLink = context.domElement.querySelector("link[rel='ar']");
|
|
6
|
+
if(existingLink) return existingLink as HTMLAnchorElement;
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
generating this:
|
|
10
|
+
<div class="menu">
|
|
11
|
+
<button id="open-in-ar">Open in QuickLook</button>
|
|
12
|
+
<a style="display:none;" id="link" rel="ar" href="" download="asset.usdz">
|
|
13
|
+
<img id="button" width="100" src="files/arkit.png">
|
|
14
|
+
</a>
|
|
15
|
+
</div>
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const div = document.createElement("div");
|
|
19
|
+
div.classList.add("menu");
|
|
20
|
+
div.classList.add("quicklook-menu");
|
|
21
|
+
div.style.display = "none";
|
|
22
|
+
div.style.visibility = "hidden";
|
|
23
|
+
|
|
24
|
+
const button = document.createElement("button");
|
|
25
|
+
button.id = "open-in-ar";
|
|
26
|
+
button.innerText = "Open in QuickLook";
|
|
27
|
+
div.appendChild(button);
|
|
28
|
+
|
|
29
|
+
const link = document.createElement("a");
|
|
30
|
+
link.id = "needle-usdz-link";
|
|
31
|
+
link.style.display = "none";
|
|
32
|
+
link.rel = "ar";
|
|
33
|
+
link.href = "";
|
|
34
|
+
div.appendChild(link);
|
|
35
|
+
|
|
36
|
+
const img = document.createElement("img");
|
|
37
|
+
img.id = "button";
|
|
38
|
+
// img.src = "files/arkit.png";
|
|
39
|
+
link.appendChild(img);
|
|
40
|
+
|
|
41
|
+
context.domElement.appendChild(div);
|
|
42
|
+
return link as HTMLAnchorElement;
|
|
43
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export function getFormattedDate() {
|
|
5
|
+
var date = new Date();
|
|
6
|
+
|
|
7
|
+
const month = date.getMonth() + 1;
|
|
8
|
+
const day = date.getDate();
|
|
9
|
+
const hour = date.getHours();
|
|
10
|
+
const min = date.getMinutes();
|
|
11
|
+
const sec = date.getSeconds();
|
|
12
|
+
|
|
13
|
+
const s_month = (month < 10 ? "0" : "") + month;
|
|
14
|
+
const s_day = (day < 10 ? "0" : "") + day;
|
|
15
|
+
const s_hour = (hour < 10 ? "0" : "") + hour;
|
|
16
|
+
const s_min = (min < 10 ? "0" : "") + min;
|
|
17
|
+
const s_sec = (sec < 10 ? "0" : "") + sec;
|
|
18
|
+
|
|
19
|
+
return date.getFullYear() + s_month + s_day + "-" + s_hour + s_min + s_sec;
|
|
20
|
+
}
|
|
@@ -31,21 +31,21 @@ export enum Transition {
|
|
|
31
31
|
Animation
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
class ButtonColors {
|
|
35
35
|
@serializable()
|
|
36
|
-
colorMultiplier
|
|
36
|
+
colorMultiplier!: 1;
|
|
37
37
|
@serializable(RGBAColor)
|
|
38
|
-
disabledColor
|
|
38
|
+
disabledColor!: RGBAColor;
|
|
39
39
|
@serializable()
|
|
40
|
-
fadeDuration
|
|
40
|
+
fadeDuration!: number;
|
|
41
41
|
@serializable(RGBAColor)
|
|
42
|
-
highlightedColor
|
|
42
|
+
highlightedColor!: RGBAColor;
|
|
43
43
|
@serializable(RGBAColor)
|
|
44
|
-
normalColor
|
|
44
|
+
normalColor!: RGBAColor;
|
|
45
45
|
@serializable(RGBAColor)
|
|
46
|
-
pressedColor
|
|
46
|
+
pressedColor!: RGBAColor;
|
|
47
47
|
@serializable(RGBAColor)
|
|
48
|
-
selectedColor
|
|
48
|
+
selectedColor!: RGBAColor;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
declare type AnimationTriggers = {
|
|
@@ -3,7 +3,7 @@ import * as ThreeMeshUI from 'three-mesh-ui'
|
|
|
3
3
|
import { RGBAColor } from "../js-extensions/RGBAColor"
|
|
4
4
|
import { BaseUIComponent } from "./BaseUIComponent";
|
|
5
5
|
import { serializable } from '../../engine/engine_serialization_decorator';
|
|
6
|
-
import { Color, Texture } from 'three';
|
|
6
|
+
import { Color, LinearEncoding, sRGBEncoding, Texture } from 'three';
|
|
7
7
|
import { RectTransform } from './RectTransform';
|
|
8
8
|
import { onChange, scheduleAction } from "./Utils"
|
|
9
9
|
import { GameObject } from '../Component';
|
|
@@ -126,10 +126,24 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
126
126
|
}
|
|
127
127
|
protected onAfterCreated() { }
|
|
128
128
|
|
|
129
|
+
/** used internally to ensure textures assigned to UI use linear encoding */
|
|
130
|
+
static textureCache: Map<Texture, Texture> = new Map();
|
|
131
|
+
|
|
129
132
|
protected async setTexture(tex: Texture | null | undefined) {
|
|
130
133
|
if (!tex) return;
|
|
131
134
|
this.setOptions({ backgroundOpacity: 0 });
|
|
132
135
|
if (tex) {
|
|
136
|
+
// workaround for https://github.com/needle-tools/needle-engine-support/issues/109
|
|
137
|
+
if(tex.encoding === sRGBEncoding) {
|
|
138
|
+
if(Graphic.textureCache.has(tex)) {
|
|
139
|
+
tex = Graphic.textureCache.get(tex)!;
|
|
140
|
+
} else {
|
|
141
|
+
const clone = tex.clone();
|
|
142
|
+
clone.encoding = LinearEncoding;
|
|
143
|
+
Graphic.textureCache.set(tex, clone);
|
|
144
|
+
tex = clone;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
133
147
|
this.setOptions({ backgroundTexture: tex, borderRadius: 0, backgroundOpacity: this.color.alpha, backgroundSize: "stretch" });
|
|
134
148
|
}
|
|
135
149
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { Behaviour, GameObject } from "../Component";
|
|
2
|
-
import { IPointerClickHandler, IPointerEventHandler } from "./PointerEvents";
|
|
2
|
+
import { IPointerClickHandler, IPointerEventHandler, PointerEventData } from "./PointerEvents";
|
|
3
3
|
import { FrameEvent } from "../../engine/engine_setup";
|
|
4
4
|
import { serializable } from "../../engine/engine_serialization_decorator";
|
|
5
5
|
import { Text } from "./Text";
|
|
6
|
-
import { getParam } from "../../engine/engine_utils";
|
|
6
|
+
import { getParam, isiOS } from "../../engine/engine_utils";
|
|
7
7
|
import { EventList } from "../EventList";
|
|
8
|
+
import { showBalloonMessage } from "../../engine/debug/debug";
|
|
9
|
+
import { Physics } from "../../engine/engine_physics";
|
|
10
|
+
import { tryGetUIComponent } from "./Utils";
|
|
8
11
|
|
|
9
12
|
const debug = getParam("debuginputfield");
|
|
10
13
|
|
|
@@ -36,6 +39,7 @@ export class InputField extends Behaviour implements IPointerEventHandler {
|
|
|
36
39
|
private static htmlField: HTMLInputElement | null = null;
|
|
37
40
|
|
|
38
41
|
private inputEventFn: any;
|
|
42
|
+
private _iosEventFn: any;
|
|
39
43
|
|
|
40
44
|
start() {
|
|
41
45
|
if (debug)
|
|
@@ -45,6 +49,7 @@ export class InputField extends Behaviour implements IPointerEventHandler {
|
|
|
45
49
|
onEnable() {
|
|
46
50
|
if (!InputField.htmlField) {
|
|
47
51
|
InputField.htmlField = document.createElement("input");
|
|
52
|
+
InputField.htmlField.style.caretColor = "transparent";
|
|
48
53
|
InputField.htmlField.classList.add("ar");
|
|
49
54
|
document.body.appendChild(InputField.htmlField);
|
|
50
55
|
}
|
|
@@ -57,6 +62,10 @@ export class InputField extends Behaviour implements IPointerEventHandler {
|
|
|
57
62
|
if (this.placeholder && this.textComponent?.text.length) {
|
|
58
63
|
GameObject.setActive(this.placeholder.gameObject, false);
|
|
59
64
|
}
|
|
65
|
+
if (isiOS()) {
|
|
66
|
+
this._iosEventFn = this.processInputOniOS.bind(this);
|
|
67
|
+
window.addEventListener("touchend", this._iosEventFn);
|
|
68
|
+
}
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
onDisable() {
|
|
@@ -64,6 +73,9 @@ export class InputField extends Behaviour implements IPointerEventHandler {
|
|
|
64
73
|
InputField.htmlField?.removeEventListener("keyup", this.inputEventFn);
|
|
65
74
|
// InputField.htmlField?.removeEventListener("change", this.inputEventFn);
|
|
66
75
|
this.onDeselected();
|
|
76
|
+
if (this._iosEventFn) {
|
|
77
|
+
window.removeEventListener("touchend", this._iosEventFn);
|
|
78
|
+
}
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
onPointerClick(_args) {
|
|
@@ -187,6 +199,17 @@ export class InputField extends Behaviour implements IPointerEventHandler {
|
|
|
187
199
|
}
|
|
188
200
|
}
|
|
189
201
|
|
|
202
|
+
private processInputOniOS() {
|
|
203
|
+
// focus() on safari ios doesnt open the keyboard when not processed from dom event
|
|
204
|
+
// so we try in a touch end event if this is hit
|
|
205
|
+
const hits = this.context.physics.raycast();
|
|
206
|
+
if (!hits.length) return;
|
|
207
|
+
const hit = hits[0];
|
|
208
|
+
const obj = hit.object;
|
|
209
|
+
const component = tryGetUIComponent(obj);
|
|
210
|
+
if (component?.gameObject === this.gameObject || component?.gameObject.parent === this.gameObject)
|
|
211
|
+
this.selectInputField();
|
|
212
|
+
}
|
|
190
213
|
|
|
191
214
|
|
|
192
215
|
// private static _lastDeletionTime: number = 0;
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
|
|
2
2
|
import { FrontSide, DoubleSide, BackSide, TetrahedronGeometry } from "three"
|
|
3
3
|
import { FrameEvent } from "../../engine/engine_setup";
|
|
4
|
-
import { Behaviour
|
|
5
|
-
import { $shadowDomOwner } from "./BaseUIComponent";
|
|
4
|
+
import { Behaviour } from "../Component";
|
|
5
|
+
import { $shadowDomOwner, BaseUIComponent } from "./BaseUIComponent";
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
export function tryGetUIComponent(obj: THREE.Object3D): BaseUIComponent | null {
|
|
8
|
+
const owner = obj[$shadowDomOwner];
|
|
9
|
+
if (owner) {
|
|
10
|
+
return owner;
|
|
11
|
+
}
|
|
12
|
+
if(obj.parent) {
|
|
13
|
+
return tryGetUIComponent(obj.parent);
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
16
17
|
|
|
17
18
|
export function isUIObject(obj: THREE.Object3D) {
|
|
18
19
|
return obj["isUI"] === true || typeof obj[$shadowDomOwner] === "object";
|
|
@@ -54,6 +55,7 @@ export declare type RevocableProxy = {
|
|
|
54
55
|
|
|
55
56
|
// TODO: change to use utils Watch since a revocable proxy makes a object completely useless once it is revoked
|
|
56
57
|
/** internal method to proxy a field to detect changes */
|
|
58
|
+
/**@deprecated use watcher instead */
|
|
57
59
|
export function onChange<T extends object>(caller: T, field: string, callback: (newValue: any, oldValue: any) => void): RevocableProxy {
|
|
58
60
|
|
|
59
61
|
if (caller[field] === undefined) {
|
|
@@ -84,12 +86,13 @@ export function onChange<T extends object>(caller: T, field: string, callback: (
|
|
|
84
86
|
|
|
85
87
|
|
|
86
88
|
declare type ScheduleCache = { [key: number]: { [key: string]: Generator | null } };
|
|
89
|
+
const $scheduledActionKey = Symbol("Scheduled action");
|
|
87
90
|
|
|
88
91
|
// use to schedule a callback at a specific moment in the frame
|
|
89
|
-
/** internal method to
|
|
92
|
+
/** internal method to schedule a function at a specific moment in the update loop */
|
|
90
93
|
export function scheduleAction(caller: Behaviour, action: Function, timing: FrameEvent = FrameEvent.OnBeforeRender) {
|
|
91
|
-
let cache: ScheduleCache = caller[
|
|
92
|
-
if (!cache) cache = caller[
|
|
94
|
+
let cache: ScheduleCache = caller[$scheduledActionKey];
|
|
95
|
+
if (!cache) cache = caller[$scheduledActionKey] = {};
|
|
93
96
|
|
|
94
97
|
const key = action.name;
|
|
95
98
|
if (!cache[timing]) cache[timing] = {};
|