@needle-tools/engine 5.0.3 → 5.1.0-alpha.1
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 +31 -4
- package/README.md +6 -7
- package/components.needle.json +1 -1
- package/dist/{needle-engine.bundle-BXk8jYW3.js → needle-engine.bundle-BGyKqxBH.js} +12394 -11786
- package/dist/needle-engine.bundle-CiYtOO2O.min.js +1732 -0
- package/dist/needle-engine.bundle-DzVx9Z8D.umd.cjs +1732 -0
- package/dist/needle-engine.d.ts +660 -63
- package/dist/needle-engine.js +579 -566
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{vendor-vHLk8sXu.js → vendor-CAcsI0eU.js} +116 -115
- package/dist/{vendor-CntUvmJu.umd.cjs → vendor-CEM38hLE.umd.cjs} +2 -2
- package/dist/{vendor-DPbfJJ4d.min.js → vendor-HRlxIBga.min.js} +2 -2
- package/lib/engine/api.d.ts +2 -0
- package/lib/engine/api.js +2 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/engine_addressables.js +5 -1
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_animation.d.ts +14 -7
- package/lib/engine/engine_animation.js +49 -9
- package/lib/engine/engine_animation.js.map +1 -1
- package/lib/engine/engine_components.js +33 -4
- package/lib/engine/engine_components.js.map +1 -1
- package/lib/engine/engine_context.d.ts +7 -2
- package/lib/engine/engine_context.js +10 -2
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_gameobject.d.ts +4 -0
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_init.js +4 -0
- package/lib/engine/engine_init.js.map +1 -1
- package/lib/engine/engine_input.js +4 -1
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_materialpropertyblock.js +0 -19
- package/lib/engine/engine_materialpropertyblock.js.map +1 -1
- package/lib/engine/engine_networking.d.ts +11 -8
- package/lib/engine/engine_networking.js +43 -26
- package/lib/engine/engine_networking.js.map +1 -1
- package/lib/engine/engine_networking_instantiate.d.ts +100 -5
- package/lib/engine/engine_networking_instantiate.js +150 -16
- package/lib/engine/engine_networking_instantiate.js.map +1 -1
- package/lib/engine/engine_networking_prefabs.d.ts +59 -0
- package/lib/engine/engine_networking_prefabs.js +67 -0
- package/lib/engine/engine_networking_prefabs.js.map +1 -0
- package/lib/engine/engine_physics_rapier.d.ts +3 -0
- package/lib/engine/engine_physics_rapier.js +13 -9
- package/lib/engine/engine_physics_rapier.js.map +1 -1
- package/lib/engine/engine_utils.js +2 -2
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/postprocessing/api.d.ts +2 -0
- package/lib/engine/postprocessing/api.js +2 -0
- package/lib/engine/postprocessing/api.js.map +1 -0
- package/lib/engine/postprocessing/index.d.ts +2 -0
- package/lib/engine/postprocessing/index.js +2 -0
- package/lib/engine/postprocessing/index.js.map +1 -0
- package/lib/engine/postprocessing/postprocessing.d.ts +83 -0
- package/lib/engine/postprocessing/postprocessing.js +280 -0
- package/lib/engine/postprocessing/postprocessing.js.map +1 -0
- package/lib/engine/postprocessing/types.d.ts +39 -0
- package/lib/engine/postprocessing/types.js +2 -0
- package/lib/engine/postprocessing/types.js.map +1 -0
- package/lib/engine/webcomponents/WebXRButtons.js +17 -3
- package/lib/engine/webcomponents/WebXRButtons.js.map +1 -1
- package/lib/engine/xr/NeedleXRSession.d.ts +2 -0
- package/lib/engine/xr/NeedleXRSession.js +47 -14
- package/lib/engine/xr/NeedleXRSession.js.map +1 -1
- package/lib/engine/xr/events.d.ts +30 -3
- package/lib/engine/xr/events.js +38 -0
- package/lib/engine/xr/events.js.map +1 -1
- package/lib/engine/xr/init.d.ts +4 -0
- package/lib/engine/xr/init.js +43 -0
- package/lib/engine/xr/init.js.map +1 -0
- package/lib/engine-components/AnimationUtils.d.ts +4 -1
- package/lib/engine-components/AnimationUtils.js +7 -19
- package/lib/engine-components/AnimationUtils.js.map +1 -1
- package/lib/engine-components/AnimatorController.d.ts +135 -2
- package/lib/engine-components/AnimatorController.js +216 -13
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/SeeThrough.d.ts +0 -2
- package/lib/engine-components/SeeThrough.js +0 -89
- package/lib/engine-components/SeeThrough.js.map +1 -1
- package/lib/engine-components/SyncedRoom.d.ts +4 -0
- package/lib/engine-components/SyncedRoom.js +23 -8
- package/lib/engine-components/SyncedRoom.js.map +1 -1
- package/lib/engine-components/SyncedTransform.js +5 -5
- package/lib/engine-components/SyncedTransform.js.map +1 -1
- package/lib/engine-components/Voip.d.ts +46 -0
- package/lib/engine-components/Voip.js +126 -2
- package/lib/engine-components/Voip.js.map +1 -1
- package/lib/engine-components/api.d.ts +1 -0
- package/lib/engine-components/api.js +1 -0
- package/lib/engine-components/api.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +1 -0
- package/lib/engine-components/codegen/components.js +1 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/Tonemapping.d.ts +5 -2
- package/lib/engine-components/postprocessing/Effects/Tonemapping.js +11 -18
- package/lib/engine-components/postprocessing/Effects/Tonemapping.js.map +1 -1
- package/lib/engine-components/postprocessing/PostProcessingEffect.d.ts +3 -4
- package/lib/engine-components/postprocessing/PostProcessingEffect.js +6 -15
- package/lib/engine-components/postprocessing/PostProcessingEffect.js.map +1 -1
- package/lib/engine-components/postprocessing/PostProcessingHandler.d.ts +2 -1
- package/lib/engine-components/postprocessing/PostProcessingHandler.js.map +1 -1
- package/lib/engine-components/postprocessing/Volume.d.ts +18 -11
- package/lib/engine-components/postprocessing/Volume.js +61 -140
- package/lib/engine-components/postprocessing/Volume.js.map +1 -1
- package/lib/engine-components/postprocessing/index.d.ts +1 -0
- package/lib/engine-components/postprocessing/index.js +1 -0
- package/lib/engine-components/postprocessing/index.js.map +1 -1
- package/lib/engine-components/postprocessing/utils.d.ts +2 -0
- package/lib/engine-components/postprocessing/utils.js +2 -0
- package/lib/engine-components/postprocessing/utils.js.map +1 -1
- package/lib/engine-components/ui/Canvas.js +2 -2
- package/lib/engine-components/ui/Canvas.js.map +1 -1
- package/lib/engine-components/ui/Graphic.d.ts +3 -3
- package/lib/engine-components/ui/Graphic.js +6 -2
- package/lib/engine-components/ui/Graphic.js.map +1 -1
- package/lib/engine-components/ui/Text.d.ts +64 -11
- package/lib/engine-components/ui/Text.js +154 -45
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/engine-components/ui/index.d.ts +1 -0
- package/lib/engine-components/ui/index.js +1 -0
- package/lib/engine-components/ui/index.js.map +1 -1
- package/lib/engine-components-experimental/networking/PlayerSync.d.ts +25 -3
- package/lib/engine-components-experimental/networking/PlayerSync.js +60 -11
- package/lib/engine-components-experimental/networking/PlayerSync.js.map +1 -1
- package/package.json +5 -4
- package/plugins/common/logger.js +42 -19
- package/plugins/vite/ai.d.ts +11 -10
- package/plugins/vite/ai.js +305 -31
- package/plugins/vite/logger.client.js +4 -3
- package/src/engine/api.ts +3 -0
- package/src/engine/engine_addressables.ts +4 -1
- package/src/engine/engine_animation.ts +47 -9
- package/src/engine/engine_components.ts +36 -7
- package/src/engine/engine_context.ts +11 -2
- package/src/engine/engine_gameobject.ts +5 -0
- package/src/engine/engine_init.ts +4 -0
- package/src/engine/engine_input.ts +2 -1
- package/src/engine/engine_materialpropertyblock.ts +0 -19
- package/src/engine/engine_networking.ts +46 -23
- package/src/engine/engine_networking_instantiate.ts +160 -18
- package/src/engine/engine_networking_prefabs.ts +80 -0
- package/src/engine/engine_physics_rapier.ts +14 -9
- package/src/engine/engine_utils.ts +2 -2
- package/src/engine/postprocessing/api.ts +2 -0
- package/src/engine/postprocessing/index.ts +2 -0
- package/src/engine/postprocessing/postprocessing.ts +322 -0
- package/src/engine/postprocessing/types.ts +43 -0
- package/src/engine/webcomponents/WebXRButtons.ts +21 -4
- package/src/engine/xr/NeedleXRSession.ts +55 -20
- package/src/engine/xr/events.ts +44 -1
- package/src/engine/xr/init.ts +49 -0
- package/src/engine-components/AnimationUtils.ts +7 -17
- package/src/engine-components/AnimatorController.ts +288 -18
- package/src/engine-components/SeeThrough.ts +0 -116
- package/src/engine-components/SyncedRoom.ts +28 -9
- package/src/engine-components/SyncedTransform.ts +5 -5
- package/src/engine-components/Voip.ts +129 -2
- package/src/engine-components/api.ts +1 -0
- package/src/engine-components/codegen/components.ts +1 -0
- package/src/engine-components/postprocessing/Effects/Tonemapping.ts +16 -24
- package/src/engine-components/postprocessing/PostProcessingEffect.ts +9 -16
- package/src/engine-components/postprocessing/PostProcessingHandler.ts +2 -1
- package/src/engine-components/postprocessing/Volume.ts +72 -163
- package/src/engine-components/postprocessing/index.ts +1 -0
- package/src/engine-components/postprocessing/utils.ts +2 -0
- package/src/engine-components/ui/Canvas.ts +2 -2
- package/src/engine-components/ui/Graphic.ts +7 -3
- package/src/engine-components/ui/Text.ts +170 -52
- package/src/engine-components/ui/index.ts +2 -1
- package/src/engine-components-experimental/networking/PlayerSync.ts +64 -11
- package/dist/needle-engine.bundle-CNH61kLA.umd.cjs +0 -1730
- package/dist/needle-engine.bundle-Dvh1jROn.min.js +0 -1730
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { DeviceUtilities, setParamWithoutReload } from "../engine_utils.js";
|
|
2
|
+
import { NeedleXRSession } from "./NeedleXRSession.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Initialize XR subsystem. Called from `initEngine()`
|
|
6
|
+
*/
|
|
7
|
+
export function initXR() {
|
|
8
|
+
// Prewarm AR support check
|
|
9
|
+
NeedleXRSession.isARSupported();
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if (DeviceUtilities.isiOS()) {
|
|
14
|
+
|
|
15
|
+
// Prefetch
|
|
16
|
+
const url = new URL("https://appclip.apple.com/id?p=tools.needle.launch-app.Clip");
|
|
17
|
+
url.searchParams.set("url", location.href);
|
|
18
|
+
const urlStr = url.toString();
|
|
19
|
+
fetch(urlStr, { method: "HEAD", mode: "no-cors" }).catch(() => {
|
|
20
|
+
// appclip prefetch - to get metadata faster on iOS devices, this seems to fix the double tap issue when opening the appclip for AR sessions.
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
// We add the meta tag here to preload app clip card data for iOS.
|
|
25
|
+
const meta = window.top?.document.querySelector('meta[name="apple-itunes-app"]');
|
|
26
|
+
if(!meta) {
|
|
27
|
+
const metaTag = document.createElement("meta");
|
|
28
|
+
metaTag.name = "apple-itunes-app";
|
|
29
|
+
metaTag.content = "app-id=6757205152, app-clip-bundle-id=tools.needle.launch-app.Clip, app-clip-display=card";
|
|
30
|
+
window.top?.document.head.appendChild(metaTag);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
console.warn("Error adding apple-itunes-app meta tag for appclip support\n", e);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
// We preconnect to apple here to speed up the appclip meta request for the first click. NOT sure if necessary and working but can't hurt either?
|
|
39
|
+
const topWindow = window.top || window;
|
|
40
|
+
const preconnectMeta = topWindow.document.createElement("link");
|
|
41
|
+
preconnectMeta.rel = "preconnect";
|
|
42
|
+
preconnectMeta.href = url.toString();
|
|
43
|
+
topWindow.document.head.appendChild(preconnectMeta);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
console.warn("Error adding preconnect link for appclip.apple.com\n", e);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -1,29 +1,19 @@
|
|
|
1
1
|
import { Object3D } from "three";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { AnimationUtils } from "../engine/engine_animation.js";
|
|
4
4
|
|
|
5
5
|
/** Internal method - This marks an object as being animated. Make sure to always call isAnimated=false if you stop animating the object
|
|
6
6
|
* @param obj The object to mark
|
|
7
7
|
* @param isAnimated Whether the object is animated or not
|
|
8
|
+
* @deprecated Use {@link AnimationUtils.setObjectAnimated} instead
|
|
8
9
|
*/
|
|
9
10
|
export function setObjectAnimated(obj: Object3D, animatedBy: object, isAnimated: boolean) {
|
|
10
|
-
|
|
11
|
-
if (obj[$objectAnimationKey] === undefined) {
|
|
12
|
-
if (!isAnimated) return;
|
|
13
|
-
obj[$objectAnimationKey] = new Set<object>();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const set = obj[$objectAnimationKey] as Set<object>;
|
|
17
|
-
if (isAnimated) {
|
|
18
|
-
set.add(animatedBy);
|
|
19
|
-
}
|
|
20
|
-
else if (set.has(animatedBy))
|
|
21
|
-
set.delete(animatedBy);
|
|
11
|
+
return AnimationUtils.setObjectAnimated(obj, animatedBy, isAnimated);
|
|
22
12
|
}
|
|
23
13
|
|
|
24
|
-
/** Get is the object is currently animated. Currently used by the Animator to check if a timeline animationtrack is actively animating an object
|
|
14
|
+
/** Get is the object is currently animated. Currently used by the Animator to check if a timeline animationtrack is actively animating an object
|
|
15
|
+
* @deprecated Use {@link AnimationUtils.getObjectAnimated} instead
|
|
16
|
+
*/
|
|
25
17
|
export function getObjectAnimated(obj: Object3D): boolean {
|
|
26
|
-
|
|
27
|
-
const set = obj[$objectAnimationKey] as Set<object>;
|
|
28
|
-
return set !== undefined && set.size > 0;
|
|
18
|
+
return AnimationUtils.getObjectAnimated(obj) || false;
|
|
29
19
|
}
|
|
@@ -9,27 +9,13 @@ import { Context } from "../engine/engine_setup.js";
|
|
|
9
9
|
import { isAnimationAction } from "../engine/engine_three_utils.js";
|
|
10
10
|
import { TypeStore } from "../engine/engine_typestore.js";
|
|
11
11
|
import { deepClone, getParam } from "../engine/engine_utils.js";
|
|
12
|
-
import type { AnimatorControllerModel, Condition, State, Transition } from "../engine/extensions/NEEDLE_animator_controller_model.js";
|
|
12
|
+
import type { AnimatorControllerModel, Condition, Parameter, State, Transition } from "../engine/extensions/NEEDLE_animator_controller_model.js";
|
|
13
13
|
import { AnimatorConditionMode, AnimatorControllerParameterType, AnimatorStateInfo, createMotion, StateMachineBehaviour } from "../engine/extensions/NEEDLE_animator_controller_model.js";
|
|
14
14
|
import type { Animator } from "./Animator.js";
|
|
15
15
|
|
|
16
16
|
const debug = getParam("debuganimatorcontroller");
|
|
17
17
|
const debugRootMotion = getParam("debugrootmotion");
|
|
18
18
|
|
|
19
|
-
/**
|
|
20
|
-
* Generates a hash code for a string
|
|
21
|
-
* @param str - The string to hash
|
|
22
|
-
* @returns A numeric hash value
|
|
23
|
-
*/
|
|
24
|
-
function stringToHash(str): number {
|
|
25
|
-
let hash = 0;
|
|
26
|
-
for (let i = 0; i < str.length; i++) {
|
|
27
|
-
const char = str.charCodeAt(i);
|
|
28
|
-
hash = ((hash << 5) - hash) + char;
|
|
29
|
-
hash = hash & hash;
|
|
30
|
-
}
|
|
31
|
-
return hash;
|
|
32
|
-
}
|
|
33
19
|
|
|
34
20
|
/**
|
|
35
21
|
* Configuration options for creating an AnimatorController
|
|
@@ -43,15 +29,275 @@ declare type CreateAnimatorControllerOptions = {
|
|
|
43
29
|
transitionDuration?: number,
|
|
44
30
|
}
|
|
45
31
|
|
|
46
|
-
|
|
32
|
+
|
|
33
|
+
// #region AnimatorControllerBuilder
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Configuration for an animation state in the builder
|
|
37
|
+
*/
|
|
38
|
+
export declare type StateOptions = {
|
|
39
|
+
/** The animation clip for this state */
|
|
40
|
+
clip: AnimationClip;
|
|
41
|
+
/** Whether the animation should loop (default: false) */
|
|
42
|
+
loop?: boolean;
|
|
43
|
+
/** Base speed multiplier (default: 1) */
|
|
44
|
+
speed?: number;
|
|
45
|
+
/** Name of a float parameter to multiply with speed */
|
|
46
|
+
speedParameter?: string;
|
|
47
|
+
/** Normalized cycle offset 0-1 (default: 0) */
|
|
48
|
+
cycleOffset?: number;
|
|
49
|
+
/** Name of a float parameter to use as cycle offset */
|
|
50
|
+
cycleOffsetParameter?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Configuration for a transition in the builder
|
|
55
|
+
*/
|
|
56
|
+
export declare type TransitionOptions = {
|
|
57
|
+
/** Duration of the crossfade in seconds (default: 0) */
|
|
58
|
+
duration?: number;
|
|
59
|
+
/** Normalized exit time 0-1 (default: 1). Only used when hasExitTime is true */
|
|
60
|
+
exitTime?: number;
|
|
61
|
+
/** Whether the transition waits for exitTime before transitioning (default: false) */
|
|
62
|
+
hasExitTime?: boolean;
|
|
63
|
+
/** Normalized offset into the destination state's animation (default: 0) */
|
|
64
|
+
offset?: number;
|
|
65
|
+
/** Whether duration is in seconds (true) or normalized (false) (default: false) */
|
|
66
|
+
hasFixedDuration?: boolean;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** String condition modes for the builder, mapped to {@link AnimatorConditionMode} */
|
|
70
|
+
export type ConditionMode = "if" | "ifNot" | "greater" | "less" | "equals" | "notEqual";
|
|
71
|
+
|
|
72
|
+
function conditionModeToEnum(mode: ConditionMode): AnimatorConditionMode {
|
|
73
|
+
switch (mode) {
|
|
74
|
+
case "if": return AnimatorConditionMode.If;
|
|
75
|
+
case "ifNot": return AnimatorConditionMode.IfNot;
|
|
76
|
+
case "greater": return AnimatorConditionMode.Greater;
|
|
77
|
+
case "less": return AnimatorConditionMode.Less;
|
|
78
|
+
case "equals": return AnimatorConditionMode.Equals;
|
|
79
|
+
case "notEqual": return AnimatorConditionMode.NotEqual;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
type BuilderTransition = {
|
|
84
|
+
to: string;
|
|
85
|
+
options: TransitionOptions;
|
|
86
|
+
conditions: Array<{ parameter: string; mode: ConditionMode; threshold: number }>;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
type BuilderState = {
|
|
90
|
+
name: string;
|
|
91
|
+
options: StateOptions;
|
|
92
|
+
transitions: BuilderTransition[];
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* A fluent builder for creating {@link AnimatorController} instances from code.
|
|
97
|
+
*
|
|
98
|
+
* Use {@link AnimatorController.build} to create a new builder.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* const controller = AnimatorController.build("CharacterController")
|
|
103
|
+
* .floatParameter("Speed", 0)
|
|
104
|
+
* .triggerParameter("Jump")
|
|
105
|
+
* .state("Idle", { clip: idleClip, loop: true })
|
|
106
|
+
* .state("Walk", { clip: walkClip, loop: true })
|
|
107
|
+
* .state("Jump", { clip: jumpClip })
|
|
108
|
+
* .transition("Idle", "Walk", { duration: 0.25 })
|
|
109
|
+
* .condition("Speed", "greater", 0.1)
|
|
110
|
+
* .transition("Walk", "Idle", { duration: 0.25 })
|
|
111
|
+
* .condition("Speed", "less", 0.1)
|
|
112
|
+
* .transition("*", "Jump", { duration: 0.1 })
|
|
113
|
+
* .condition("Jump", "if")
|
|
114
|
+
* .transition("Jump", "Idle", { hasExitTime: true, exitTime: 0.9, duration: 0.25 })
|
|
115
|
+
* .build();
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* @category Animation and Sequencing
|
|
119
|
+
* @group Utilities
|
|
120
|
+
*/
|
|
121
|
+
export class AnimatorControllerBuilder {
|
|
122
|
+
private _name: string;
|
|
123
|
+
private _parameters: Parameter[] = [];
|
|
124
|
+
private _states: BuilderState[] = [];
|
|
125
|
+
private _anyStateTransitions: BuilderTransition[] = [];
|
|
126
|
+
private _defaultStateName: string | null = null;
|
|
127
|
+
private _lastTransition: BuilderTransition | null = null;
|
|
128
|
+
|
|
129
|
+
constructor(name?: string) {
|
|
130
|
+
this._name = name ?? "AnimatorController";
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Adds a float parameter */
|
|
134
|
+
floatParameter(name: string, defaultValue: number = 0): this {
|
|
135
|
+
this._parameters.push({ name, hash: this._parameters.length, type: AnimatorControllerParameterType.Float, value: defaultValue });
|
|
136
|
+
return this;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Adds an integer parameter */
|
|
140
|
+
intParameter(name: string, defaultValue: number = 0): this {
|
|
141
|
+
this._parameters.push({ name, hash: this._parameters.length, type: AnimatorControllerParameterType.Int, value: defaultValue });
|
|
142
|
+
return this;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Adds a boolean parameter */
|
|
146
|
+
boolParameter(name: string, defaultValue: boolean = false): this {
|
|
147
|
+
this._parameters.push({ name, hash: this._parameters.length, type: AnimatorControllerParameterType.Bool, value: defaultValue });
|
|
148
|
+
return this;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Adds a trigger parameter */
|
|
152
|
+
triggerParameter(name: string): this {
|
|
153
|
+
this._parameters.push({ name, hash: this._parameters.length, type: AnimatorControllerParameterType.Trigger, value: false });
|
|
154
|
+
return this;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Adds a state to the controller. The first state added becomes the default state.
|
|
159
|
+
* @param name - Unique name for the state
|
|
160
|
+
* @param options - State configuration including clip, loop, speed
|
|
161
|
+
*/
|
|
162
|
+
state(name: string, options: StateOptions): this {
|
|
163
|
+
this._states.push({ name, options, transitions: [] });
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Adds a transition between two states.
|
|
169
|
+
* Use `"*"` as the source to create a transition from any state.
|
|
170
|
+
* Chain `.condition()` calls after this to add conditions.
|
|
171
|
+
* @param from - Source state name, or `"*"` for any-state transition
|
|
172
|
+
* @param to - Destination state name
|
|
173
|
+
* @param options - Transition configuration
|
|
174
|
+
*/
|
|
175
|
+
transition(from: string, to: string, options?: TransitionOptions): this {
|
|
176
|
+
const t: BuilderTransition = { to, options: options ?? {}, conditions: [] };
|
|
177
|
+
if (from === "*") {
|
|
178
|
+
this._anyStateTransitions.push(t);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
const state = this._states.find(s => s.name === from);
|
|
182
|
+
if (!state) throw new Error(`AnimatorControllerBuilder: source state "${from}" not found. Add it with .state() first.`);
|
|
183
|
+
state.transitions.push(t);
|
|
184
|
+
}
|
|
185
|
+
this._lastTransition = t;
|
|
186
|
+
return this;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Adds a condition to the most recently added transition.
|
|
191
|
+
* Multiple conditions on the same transition are AND-ed together.
|
|
192
|
+
* @param parameter - Name of the parameter to evaluate
|
|
193
|
+
* @param mode - Condition mode: `"if"`, `"ifNot"`, `"greater"`, `"less"`, `"equals"`, `"notEqual"`
|
|
194
|
+
* @param threshold - Comparison threshold for numeric conditions (default: 0)
|
|
195
|
+
*/
|
|
196
|
+
condition(parameter: string, mode: ConditionMode, threshold: number = 0): this {
|
|
197
|
+
if (!this._lastTransition) throw new Error("AnimatorControllerBuilder: .condition() must be called after .transition()");
|
|
198
|
+
this._lastTransition.conditions.push({ parameter, mode, threshold });
|
|
199
|
+
return this;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Sets which state is the default/entry state.
|
|
204
|
+
* If not called, the first added state is used.
|
|
205
|
+
* @param name - Name of the state
|
|
206
|
+
*/
|
|
207
|
+
defaultState(name: string): this {
|
|
208
|
+
this._defaultStateName = name;
|
|
209
|
+
return this;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Builds and returns the {@link AnimatorController}.
|
|
214
|
+
* Resolves all state name references to indices.
|
|
215
|
+
*/
|
|
216
|
+
build(): AnimatorController {
|
|
217
|
+
const stateIndexMap = new Map<string, number>();
|
|
218
|
+
this._states.forEach((s, i) => stateIndexMap.set(s.name, i));
|
|
219
|
+
|
|
220
|
+
let defaultStateIndex = 0;
|
|
221
|
+
if (this._defaultStateName !== null) {
|
|
222
|
+
const idx = stateIndexMap.get(this._defaultStateName);
|
|
223
|
+
if (idx === undefined) throw new Error(`AnimatorControllerBuilder: default state "${this._defaultStateName}" not found`);
|
|
224
|
+
defaultStateIndex = idx;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const resolveTransition = (t: BuilderTransition): Transition => {
|
|
228
|
+
const destIndex = stateIndexMap.get(t.to);
|
|
229
|
+
if (destIndex === undefined) throw new Error(`AnimatorControllerBuilder: transition target "${t.to}" not found`);
|
|
230
|
+
return {
|
|
231
|
+
exitTime: t.options.exitTime ?? 1,
|
|
232
|
+
hasExitTime: t.options.hasExitTime ?? false,
|
|
233
|
+
duration: t.options.duration ?? 0,
|
|
234
|
+
offset: t.options.offset ?? 0,
|
|
235
|
+
hasFixedDuration: t.options.hasFixedDuration ?? false,
|
|
236
|
+
destinationState: destIndex,
|
|
237
|
+
conditions: t.conditions.map(c => ({
|
|
238
|
+
parameter: c.parameter,
|
|
239
|
+
mode: conditionModeToEnum(c.mode),
|
|
240
|
+
threshold: c.threshold,
|
|
241
|
+
})),
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
const states: State[] = this._states.map((s, index) => {
|
|
246
|
+
const transitions: Transition[] = s.transitions.map(resolveTransition);
|
|
247
|
+
|
|
248
|
+
// Replicate any-state transitions onto every state (except self-targeting)
|
|
249
|
+
for (const anyT of this._anyStateTransitions) {
|
|
250
|
+
const destIndex = stateIndexMap.get(anyT.to);
|
|
251
|
+
if (destIndex === index) continue;
|
|
252
|
+
transitions.push(resolveTransition(anyT));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return {
|
|
256
|
+
name: s.name,
|
|
257
|
+
hash: index,
|
|
258
|
+
motion: {
|
|
259
|
+
name: s.options.clip.name,
|
|
260
|
+
clip: s.options.clip,
|
|
261
|
+
isLooping: s.options.loop ?? false,
|
|
262
|
+
},
|
|
263
|
+
transitions,
|
|
264
|
+
behaviours: [],
|
|
265
|
+
speed: s.options.speed,
|
|
266
|
+
speedParameter: s.options.speedParameter,
|
|
267
|
+
cycleOffset: s.options.cycleOffset,
|
|
268
|
+
cycleOffsetParameter: s.options.cycleOffsetParameter,
|
|
269
|
+
};
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
const model: AnimatorControllerModel = {
|
|
273
|
+
name: this._name,
|
|
274
|
+
guid: new InstantiateIdProvider(Date.now()).generateUUID(),
|
|
275
|
+
parameters: this._parameters,
|
|
276
|
+
layers: [{
|
|
277
|
+
name: "Base Layer",
|
|
278
|
+
stateMachine: {
|
|
279
|
+
defaultState: defaultStateIndex,
|
|
280
|
+
states,
|
|
281
|
+
}
|
|
282
|
+
}],
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
return new AnimatorController(model);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// #endregion
|
|
289
|
+
|
|
290
|
+
// #region AnimatorController
|
|
291
|
+
/**
|
|
47
292
|
* Controls the playback of animations using a state machine architecture.
|
|
48
293
|
*
|
|
49
294
|
* The AnimatorController manages animation states, transitions between states,
|
|
50
295
|
* and parameters that affect those transitions. It is used by the {@link Animator}
|
|
51
296
|
* component to control animation behavior on 3D models.
|
|
52
297
|
*
|
|
53
|
-
* Use
|
|
54
|
-
*
|
|
298
|
+
* Use {@link AnimatorController.build} to fluently create a controller with parameters,
|
|
299
|
+
* states, transitions, and conditions. For simple sequential playback,
|
|
300
|
+
* use {@link AnimatorController.createFromClips}.
|
|
55
301
|
*
|
|
56
302
|
* @category Animation and Sequencing
|
|
57
303
|
* @group Utilities
|
|
@@ -119,6 +365,30 @@ export class AnimatorController {
|
|
|
119
365
|
return controller;
|
|
120
366
|
}
|
|
121
367
|
|
|
368
|
+
/**
|
|
369
|
+
* Creates a new {@link AnimatorControllerBuilder} for fluently constructing a controller with
|
|
370
|
+
* parameters, states, transitions, and conditions.
|
|
371
|
+
*
|
|
372
|
+
* @param name - Optional name for the controller
|
|
373
|
+
* @returns A new builder instance
|
|
374
|
+
*
|
|
375
|
+
* @example
|
|
376
|
+
* ```ts
|
|
377
|
+
* const ctrl = AnimatorController.build("MyController")
|
|
378
|
+
* .floatParameter("Speed")
|
|
379
|
+
* .state("Idle", { clip: idleClip, loop: true })
|
|
380
|
+
* .state("Walk", { clip: walkClip, loop: true })
|
|
381
|
+
* .transition("Idle", "Walk", { duration: 0.25 })
|
|
382
|
+
* .condition("Speed", "greater", 0.1)
|
|
383
|
+
* .transition("Walk", "Idle", { duration: 0.25 })
|
|
384
|
+
* .condition("Speed", "less", 0.1)
|
|
385
|
+
* .build();
|
|
386
|
+
* ```
|
|
387
|
+
*/
|
|
388
|
+
static build(name?: string): AnimatorControllerBuilder {
|
|
389
|
+
return new AnimatorControllerBuilder(name);
|
|
390
|
+
}
|
|
391
|
+
|
|
122
392
|
/**
|
|
123
393
|
* Plays an animation state by name or hash.
|
|
124
394
|
*
|
|
@@ -176,26 +176,6 @@ export class SeeThrough extends Behaviour {
|
|
|
176
176
|
onEnable() {
|
|
177
177
|
this._needsUpdate = true;
|
|
178
178
|
this._renderer = null;
|
|
179
|
-
// SeeThroughUsdzExporterPlugin.components.push(this);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/** @internal */
|
|
183
|
-
onDisable() {
|
|
184
|
-
// this._renderer?.forEach(r => {
|
|
185
|
-
// const original = this.rendererMaterialsOriginal.get(r);
|
|
186
|
-
// for (let i = 0; i < r.sharedMaterials.length; i++) {
|
|
187
|
-
// const mat = r.sharedMaterials[i];
|
|
188
|
-
// if (!mat) continue;
|
|
189
|
-
// if (original && original[i]) {
|
|
190
|
-
// r.sharedMaterials[i] = original[i];
|
|
191
|
-
// }
|
|
192
|
-
// }
|
|
193
|
-
// this.rendererMaterials.delete(r);
|
|
194
|
-
// this.rendererMaterialsOriginal.delete(r);
|
|
195
|
-
// });
|
|
196
|
-
|
|
197
|
-
// const index = SeeThroughUsdzExporterPlugin.components.indexOf(this);
|
|
198
|
-
// if (index !== -1) SeeThroughUsdzExporterPlugin.components.splice(index, 1);
|
|
199
179
|
}
|
|
200
180
|
|
|
201
181
|
/**
|
|
@@ -207,7 +187,6 @@ export class SeeThrough extends Behaviour {
|
|
|
207
187
|
if (this._needsUpdate) {
|
|
208
188
|
this._needsUpdate = false;
|
|
209
189
|
this._renderer = this.gameObject.getComponentsInChildren(Renderer);
|
|
210
|
-
|
|
211
190
|
// NOTE: instead of using the object's anchor (gameObject.worldPosition) we could also get the object's bounding box center:
|
|
212
191
|
// getBoundingBox(this.gameObject); // < import { getBoundingBox } from "@needle-tools/engine";
|
|
213
192
|
this.updateDirection();
|
|
@@ -216,12 +195,9 @@ export class SeeThrough extends Behaviour {
|
|
|
216
195
|
this.updateDirection();
|
|
217
196
|
}
|
|
218
197
|
|
|
219
|
-
|
|
220
|
-
|
|
221
198
|
if (!this.autoUpdate) return;
|
|
222
199
|
if (!this.referencePoint) return;
|
|
223
200
|
|
|
224
|
-
|
|
225
201
|
const dot = this._referencePointDir.dot(this.context.mainCamera.worldForward);
|
|
226
202
|
const shouldHide = dot > .2;
|
|
227
203
|
|
|
@@ -272,38 +248,10 @@ export class SeeThrough extends Behaviour {
|
|
|
272
248
|
renderer.gameObject.raycastAllowed = true;
|
|
273
249
|
}
|
|
274
250
|
|
|
275
|
-
// if (!this.rendererMaterials.has(renderer)) {
|
|
276
|
-
// const originalMaterials = new Array<Material>();
|
|
277
|
-
// const clonedMaterials = new Array<MaterialWithState>();
|
|
278
|
-
|
|
279
|
-
// // We clone the materials once and store them, so we can modify the opacity without affecting other objects using the same material. This could potentially be optimized further to re-use materials between renderers if multiple renderers use the same material.
|
|
280
|
-
// for (let i = 0; i < renderer.sharedMaterials.length; i++) {
|
|
281
|
-
// const mat = renderer.sharedMaterials[i];
|
|
282
|
-
// if (!mat) continue;
|
|
283
|
-
// originalMaterials.push(mat);
|
|
284
|
-
// const matClone = mat.clone() as MaterialWithState;
|
|
285
|
-
// // @ts-ignore
|
|
286
|
-
// matClone.userData = mat.userData || {};
|
|
287
|
-
// matClone.userData.seeThrough = {
|
|
288
|
-
// initial: {
|
|
289
|
-
// opacity: matClone.opacity,
|
|
290
|
-
// transparent: matClone.transparent,
|
|
291
|
-
// alphaHash: matClone.alphaHash
|
|
292
|
-
// }
|
|
293
|
-
// }
|
|
294
|
-
// clonedMaterials.push(matClone);
|
|
295
|
-
// // renderer.sharedMaterials[i] = matClone;
|
|
296
|
-
// }
|
|
297
|
-
|
|
298
|
-
// this.rendererMaterials.set(renderer, clonedMaterials);
|
|
299
|
-
// this.rendererMaterialsOriginal.set(renderer, originalMaterials);
|
|
300
|
-
// }
|
|
301
|
-
|
|
302
251
|
const materials = renderer.sharedMaterials;// : this.rendererMaterials.get(renderer);
|
|
303
252
|
if (!materials) return;
|
|
304
253
|
|
|
305
254
|
const block = MaterialPropertyBlock.get(renderer.gameObject);
|
|
306
|
-
|
|
307
255
|
const currentOpacity = (block.getOverride("opacity")?.value ?? materials[0].opacity ?? 1);
|
|
308
256
|
|
|
309
257
|
let newAlpha = Mathf.lerp(currentOpacity, targetAlpha, duration <= 0 ? 1 : this.context.time.deltaTime / duration);;
|
|
@@ -315,72 +263,8 @@ export class SeeThrough extends Behaviour {
|
|
|
315
263
|
block.setOverride("alphaHash", this.useAlphaHash);
|
|
316
264
|
block.setOverride("opacity", newAlpha);
|
|
317
265
|
block.setOverride("transparent", newAlpha >= 0.99999 ? false : !this.useAlphaHash);
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
// for (const mat of materials) {
|
|
321
|
-
// if (!mat) continue;
|
|
322
|
-
|
|
323
|
-
// let newAlpha = Mathf.lerp(mat.opacity, targetAlpha, duration <= 0 ? 1 : this.context.time.deltaTime / duration);;
|
|
324
|
-
// if (newAlpha >= 0.99) newAlpha = 1;
|
|
325
|
-
// else if (newAlpha <= 0.01) newAlpha = 0;
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
// const wasTransparent = mat.transparent;
|
|
329
|
-
// const wasAlphaHash = mat.alphaHash;
|
|
330
|
-
// const previousOpacity = mat.opacity;
|
|
331
|
-
|
|
332
|
-
// mat.alphaHash = this.useAlphaHash;
|
|
333
|
-
|
|
334
|
-
// if (mat.userData && "seeThrough" in mat.userData) {
|
|
335
|
-
// const initial = mat.userData.seeThrough.initial as MaterialState;
|
|
336
|
-
// mat.opacity = initial.opacity * newAlpha;
|
|
337
|
-
// mat.transparent = mat.opacity >= 1 ? initial.transparent : !this.useAlphaHash;
|
|
338
|
-
// }
|
|
339
|
-
// else {
|
|
340
|
-
// mat.transparent = mat.opacity >= 1 ? false : !this.useAlphaHash;
|
|
341
|
-
// }
|
|
342
|
-
|
|
343
|
-
// if (wasTransparent !== mat.transparent
|
|
344
|
-
// || wasAlphaHash !== mat.alphaHash
|
|
345
|
-
// || mat.opacity !== previousOpacity // MeshPhysicsMaterial needs that and maybe other materials too...
|
|
346
|
-
// ) {
|
|
347
|
-
// mat.needsUpdate = true;
|
|
348
|
-
// }
|
|
349
|
-
// }
|
|
350
266
|
});
|
|
351
267
|
}
|
|
352
268
|
|
|
353
269
|
}
|
|
354
270
|
|
|
355
|
-
|
|
356
|
-
;
|
|
357
|
-
// class SeeThroughUsdzExporterPlugin implements IUSDExporterExtension {
|
|
358
|
-
|
|
359
|
-
// static readonly components: SeeThrough[] = [];
|
|
360
|
-
|
|
361
|
-
// get extensionName() {
|
|
362
|
-
// return "SeeThrough";
|
|
363
|
-
// }
|
|
364
|
-
|
|
365
|
-
// // onExportObject(object: Object3D<Object3DEventMap>, model: USDObject, context: USDZExporterContext) {
|
|
366
|
-
// // const component = SeeThroughUsdzExporterPlugin.components.find(c => c.gameObject === object);
|
|
367
|
-
// // if(!component) return;
|
|
368
|
-
// // console.log("OH MY GOD SEE THROUGH USDZ EXPORTER", component, model);
|
|
369
|
-
|
|
370
|
-
// // model.materialName = "AlphaHashMaterialInstance"; // we could make this unique per object if needed
|
|
371
|
-
|
|
372
|
-
// // model.addEventListener("serialize", (writer, context) => {
|
|
373
|
-
// // writer.appendLine(`# SeeThrough component on ${object.name}`);
|
|
374
|
-
// // });
|
|
375
|
-
// // }
|
|
376
|
-
|
|
377
|
-
// }
|
|
378
|
-
|
|
379
|
-
// const seeThroughUsdzExporterPlugin = new SeeThroughUsdzExporterPlugin();
|
|
380
|
-
|
|
381
|
-
// USDZExporter.beforeExport.addEventListener(args => {
|
|
382
|
-
// if (SeeThroughUsdzExporterPlugin.components.length === 0) return;
|
|
383
|
-
// if (args.exporter.extensions.includes(seeThroughUsdzExporterPlugin) === false) {
|
|
384
|
-
// args.exporter.extensions.push(seeThroughUsdzExporterPlugin);
|
|
385
|
-
// }
|
|
386
|
-
// });
|
|
@@ -121,8 +121,36 @@ export class SyncedRoom extends Behaviour {
|
|
|
121
121
|
if (debug) console.log(`SyncedRoom roomName:${this.roomName}, urlParamName:${this.urlParameterName}, joinRandomRoom:${this.joinRandomRoom}`);
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
private _hasConnectedBefore: boolean = false;
|
|
125
|
+
|
|
124
126
|
/** @internal */
|
|
125
127
|
onEnable() {
|
|
128
|
+
if (this.createJoinButton) {
|
|
129
|
+
const button = this.createRoomButton();
|
|
130
|
+
this.context.menu.appendChild(button);
|
|
131
|
+
}
|
|
132
|
+
if (this.createViewOnlyButton) {
|
|
133
|
+
this.onEnableViewOnlyButton()
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// On re-enable (after disable), reconnect immediately
|
|
137
|
+
if (this._hasConnectedBefore) {
|
|
138
|
+
this._connectToRoom();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** @internal */
|
|
143
|
+
start() {
|
|
144
|
+
// Defer initial connection to start() so other components added in the same frame
|
|
145
|
+
// have time to register their listeners in awake/onEnable (e.g. PlayerSync)
|
|
146
|
+
if (!this._hasConnectedBefore) {
|
|
147
|
+
this._connectToRoom();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private _connectToRoom() {
|
|
152
|
+
this._hasConnectedBefore = true;
|
|
153
|
+
|
|
126
154
|
// if the url contains a view parameter override room and join in view mode
|
|
127
155
|
const viewId = utils.getParam(viewParamName);
|
|
128
156
|
if (viewId && typeof viewId === "string" && viewId.length > 0) {
|
|
@@ -130,16 +158,7 @@ export class SyncedRoom extends Behaviour {
|
|
|
130
158
|
this.context.connection.joinRoom(viewId, true);
|
|
131
159
|
return;
|
|
132
160
|
}
|
|
133
|
-
// If setup to join a random room
|
|
134
161
|
this.tryJoinRoom();
|
|
135
|
-
|
|
136
|
-
if (this.createJoinButton) {
|
|
137
|
-
const button = this.createRoomButton();
|
|
138
|
-
this.context.menu.appendChild(button);
|
|
139
|
-
}
|
|
140
|
-
if (this.createViewOnlyButton) {
|
|
141
|
-
this.onEnableViewOnlyButton()
|
|
142
|
-
}
|
|
143
162
|
}
|
|
144
163
|
|
|
145
164
|
/** @internal */
|
|
@@ -145,7 +145,7 @@ export class SyncedTransform extends Behaviour {
|
|
|
145
145
|
*/
|
|
146
146
|
public requestOwnership() {
|
|
147
147
|
if (debug)
|
|
148
|
-
console.log("Request ownership");
|
|
148
|
+
console.log("[SyncedTransform] Request ownership");
|
|
149
149
|
if (!this._model) {
|
|
150
150
|
this._shouldRequestOwnership = true;
|
|
151
151
|
this._needsUpdate = true;
|
|
@@ -189,7 +189,7 @@ export class SyncedTransform extends Behaviour {
|
|
|
189
189
|
/** @internal */
|
|
190
190
|
awake() {
|
|
191
191
|
if (debug)
|
|
192
|
-
console.log("new instance", this.guid, this);
|
|
192
|
+
console.log("[SyncedTransform] new instance", this.guid, this);
|
|
193
193
|
this._receivedDataBefore = false;
|
|
194
194
|
this._targetPosition = new Vector3();
|
|
195
195
|
this._targetRotation = new Quaternion();
|
|
@@ -245,7 +245,7 @@ export class SyncedTransform extends Behaviour {
|
|
|
245
245
|
if (this.destroyed) return;
|
|
246
246
|
if (typeof data.guid === "function" && data.guid() === this.guid) {
|
|
247
247
|
if (debug)
|
|
248
|
-
console.log("new data", this.context.connection.connectionId, this.context.time.frameCount, this.guid, data);
|
|
248
|
+
console.log("[SyncedTransform] new data", this.context.connection.connectionId, this.context.time.frameCount, this.guid, data);
|
|
249
249
|
this.receivedUpdate = true;
|
|
250
250
|
this._receivedFastUpdate = data.fast();
|
|
251
251
|
const transform = data.transform();
|
|
@@ -323,7 +323,7 @@ export class SyncedTransform extends Behaviour {
|
|
|
323
323
|
|
|
324
324
|
if (!this.context.connection.isInRoom || !this._model) {
|
|
325
325
|
if (debug)
|
|
326
|
-
console.log("no model or room", this.name, this.guid, this.context.connection.isInRoom);
|
|
326
|
+
console.log("[SyncedTransform] no model or room", this.name, this.guid, this.context.connection.isInRoom);
|
|
327
327
|
return;
|
|
328
328
|
}
|
|
329
329
|
|
|
@@ -409,7 +409,7 @@ export class SyncedTransform extends Behaviour {
|
|
|
409
409
|
if (this.rb && this.overridePhysics) {
|
|
410
410
|
if (this._wasKinematic !== undefined) {
|
|
411
411
|
if (debug)
|
|
412
|
-
console.log("reset kinematic", this.rb.name, this._wasKinematic);
|
|
412
|
+
console.log("[SyncedTransform] reset kinematic", this.rb.name, this._wasKinematic);
|
|
413
413
|
this.rb.isKinematic = this._wasKinematic;
|
|
414
414
|
}
|
|
415
415
|
|