@needle-tools/engine 4.1.0-beta.1 → 4.1.0-beta.3
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 +10 -0
- package/dist/needle-engine.bundle.js +1878 -1875
- package/dist/needle-engine.bundle.light.js +1853 -1850
- package/dist/needle-engine.bundle.light.min.js +92 -93
- package/dist/needle-engine.bundle.light.umd.cjs +97 -98
- package/dist/needle-engine.bundle.min.js +92 -93
- package/dist/needle-engine.bundle.umd.cjs +97 -98
- package/lib/engine/engine_networking_auto.js +6 -11
- package/lib/engine/engine_networking_auto.js.map +1 -1
- package/lib/engine/xr/NeedleXRSession.js +3 -0
- package/lib/engine/xr/NeedleXRSession.js.map +1 -1
- package/lib/engine-components/GroundProjection.d.ts +1 -1
- package/lib/engine-components/GroundProjection.js +39 -32
- package/lib/engine-components/GroundProjection.js.map +1 -1
- package/lib/engine-components/SpatialTrigger.d.ts +2 -2
- package/lib/engine-components/SpatialTrigger.js +4 -4
- package/lib/engine-components/SpatialTrigger.js.map +1 -1
- package/lib/engine-components/TransformGizmo.d.ts +7 -1
- package/lib/engine-components/TransformGizmo.js +39 -32
- package/lib/engine-components/TransformGizmo.js.map +1 -1
- package/lib/engine-components/VideoPlayer.js +0 -1
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/webxr/WebXRRig.d.ts +11 -1
- package/lib/engine-components/webxr/WebXRRig.js +13 -1
- package/lib/engine-components/webxr/WebXRRig.js.map +1 -1
- package/lib/engine-components-experimental/networking/PlayerSync.d.ts +4 -1
- package/lib/engine-components-experimental/networking/PlayerSync.js +16 -29
- package/lib/engine-components-experimental/networking/PlayerSync.js.map +1 -1
- package/package.json +1 -1
- package/plugins/vite/transform.js +3 -3
- package/src/engine/engine_networking_auto.ts +7 -22
- package/src/engine/xr/NeedleXRSession.ts +3 -0
- package/src/engine-components/GroundProjection.ts +46 -38
- package/src/engine-components/SpatialTrigger.ts +6 -6
- package/src/engine-components/TransformGizmo.ts +41 -33
- package/src/engine-components/VideoPlayer.ts +0 -1
- package/src/engine-components/webxr/WebXRRig.ts +15 -2
- package/src/engine-components-experimental/networking/PlayerSync.ts +17 -36
|
@@ -32,15 +32,12 @@ class ComponentPropertiesSyncer {
|
|
|
32
32
|
comp: IComponent;
|
|
33
33
|
|
|
34
34
|
constructor(comp: IComponent) {
|
|
35
|
-
// console.log("CREATE NEW SYNC", comp.name, comp.guid);
|
|
36
35
|
this.comp = comp;
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
// private getters: { [key: string]: Function } = {};
|
|
40
39
|
private hasChanges: boolean = false;
|
|
41
40
|
private changedProperties: { [key: string]: any } = {};
|
|
42
|
-
// private data = {};
|
|
43
|
-
|
|
44
41
|
|
|
45
42
|
get networkingKey(): string {
|
|
46
43
|
return this.comp.guid;
|
|
@@ -89,27 +86,24 @@ class ComponentPropertiesSyncer {
|
|
|
89
86
|
return;
|
|
90
87
|
}
|
|
91
88
|
for (const name in this.changedProperties) {
|
|
92
|
-
const guid = this.comp.guid + "/" + name;
|
|
93
89
|
const value = this.changedProperties[name];
|
|
94
|
-
if (debug) console.log("SEND", this.comp.
|
|
95
|
-
net.send(this.networkingKey, { guid, data: value }, SendQueue.Queued);
|
|
90
|
+
if (debug) console.log("SEND", this.comp.guid, this.networkingKey);
|
|
91
|
+
net.send(this.networkingKey, { guid: this.comp.guid, property: name, data: value }, SendQueue.Queued);
|
|
92
|
+
delete this.changedProperties[name];
|
|
96
93
|
}
|
|
97
94
|
}
|
|
98
95
|
|
|
99
|
-
private onHandleReceiving = (val: { guid: string, data: any }) => {
|
|
100
|
-
if (debug)
|
|
101
|
-
console.log("RECEIVE", this.comp.name, this.comp.guid, val);
|
|
96
|
+
private onHandleReceiving = (val: { guid: string, property: string, data: any }) => {
|
|
97
|
+
if (debug) console.log("SYNCFIELD RECEIVE", this.comp.name, this.comp.guid, val);
|
|
102
98
|
if (!this._isInit) return;
|
|
103
99
|
if (!this.comp) return;
|
|
104
100
|
// check if this change belongs to this component
|
|
105
|
-
if (val.guid
|
|
101
|
+
if (val.guid !== this.comp.guid) {
|
|
106
102
|
return;
|
|
107
103
|
}
|
|
108
|
-
const [_guid, key] = val.guid.split("/");
|
|
109
|
-
if (debug) console.log("RECEIVED", this.comp.name, this.comp.guid, val);
|
|
110
104
|
try {
|
|
111
105
|
this._isReceiving = true;
|
|
112
|
-
this.comp[
|
|
106
|
+
this.comp[val.property] = val.data;
|
|
113
107
|
}
|
|
114
108
|
catch (err) {
|
|
115
109
|
console.error(err);
|
|
@@ -118,15 +112,6 @@ class ComponentPropertiesSyncer {
|
|
|
118
112
|
this._isReceiving = false;
|
|
119
113
|
}
|
|
120
114
|
}
|
|
121
|
-
|
|
122
|
-
// private _seen: Set<any> = new Set();
|
|
123
|
-
// private uniqBy(a, key) {
|
|
124
|
-
// this._seen.clear();
|
|
125
|
-
// return a.filter(item => {
|
|
126
|
-
// let k = key(item);
|
|
127
|
-
// return this._seen.has(k) ? false : this._seen.add(k);
|
|
128
|
-
// });
|
|
129
|
-
// }
|
|
130
115
|
}
|
|
131
116
|
|
|
132
117
|
function testValueChanged(newValue, previousValue): boolean {
|
|
@@ -712,8 +712,11 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
712
712
|
/** Sets a XRRig to be active which will parent the camera to this rig */
|
|
713
713
|
setRigActive(rig: IXRRig) {
|
|
714
714
|
const i = this._rigs.indexOf(rig);
|
|
715
|
+
const currentlyActive = this._rigs[0];
|
|
715
716
|
this._rigs.splice(i, 1);
|
|
716
717
|
this._rigs.unshift(rig);
|
|
718
|
+
// if there's another rig currently active we need to make sure we have at least the same priority
|
|
719
|
+
rig.priority = currentlyActive?.priority ?? 0;
|
|
717
720
|
this.updateActiveXRRig();
|
|
718
721
|
}
|
|
719
722
|
/**
|
|
@@ -3,7 +3,7 @@ import { GroundedSkybox as GroundProjection } from 'three/examples/jsm/objects/G
|
|
|
3
3
|
|
|
4
4
|
import { Gizmos } from "../engine/engine_gizmos.js";
|
|
5
5
|
import { serializable } from "../engine/engine_serialization_decorator.js";
|
|
6
|
-
import { getBoundingBox, getTempVector, getWorldScale, Graphics, setVisibleInCustomShadowRendering,setWorldPosition } from "../engine/engine_three_utils.js";
|
|
6
|
+
import { getBoundingBox, getTempVector, getWorldScale, Graphics, setVisibleInCustomShadowRendering, setWorldPosition } from "../engine/engine_three_utils.js";
|
|
7
7
|
import { delayForFrames, getParam, Watch as Watch } from "../engine/engine_utils.js";
|
|
8
8
|
import { Behaviour } from "./Component.js";
|
|
9
9
|
|
|
@@ -37,7 +37,7 @@ export class GroundProjectedEnv extends Behaviour {
|
|
|
37
37
|
@serializable()
|
|
38
38
|
set radius(val: number) {
|
|
39
39
|
this._radius = val;
|
|
40
|
-
this.updateProjection();
|
|
40
|
+
if (this._projection) this.updateProjection();
|
|
41
41
|
}
|
|
42
42
|
get radius(): number { return this._radius; }
|
|
43
43
|
private _radius: number = 50;
|
|
@@ -49,7 +49,7 @@ export class GroundProjectedEnv extends Behaviour {
|
|
|
49
49
|
@serializable()
|
|
50
50
|
set height(val: number) {
|
|
51
51
|
this._height = val;
|
|
52
|
-
this.updateProjection();
|
|
52
|
+
if (this._projection) this.updateProjection();
|
|
53
53
|
}
|
|
54
54
|
get height(): number { return this._height; }
|
|
55
55
|
private _height: number = 3;
|
|
@@ -68,7 +68,7 @@ export class GroundProjectedEnv extends Behaviour {
|
|
|
68
68
|
get arBlending(): number { return this._arblending; }
|
|
69
69
|
private _arblending = 0;
|
|
70
70
|
|
|
71
|
-
private
|
|
71
|
+
private _lastBackground?: Texture;
|
|
72
72
|
private _lastRadius?: number;
|
|
73
73
|
private _lastHeight?: number;
|
|
74
74
|
private _projection?: GroundProjection;
|
|
@@ -88,9 +88,10 @@ export class GroundProjectedEnv extends Behaviour {
|
|
|
88
88
|
this.updateAndCreate();
|
|
89
89
|
}
|
|
90
90
|
if (!this._watcher) {
|
|
91
|
-
this._watcher = new Watch(this.context.scene, "
|
|
91
|
+
this._watcher = new Watch(this.context.scene, "background");
|
|
92
92
|
this._watcher.subscribeWrite(_ => {
|
|
93
|
-
this.
|
|
93
|
+
if (debug) console.log("Background changed", this.context.scene.background);
|
|
94
|
+
this._needsTextureUpdate = true;
|
|
94
95
|
});
|
|
95
96
|
}
|
|
96
97
|
}
|
|
@@ -101,13 +102,13 @@ export class GroundProjectedEnv extends Behaviour {
|
|
|
101
102
|
}
|
|
102
103
|
/** @internal */
|
|
103
104
|
onEnterXR(): void {
|
|
104
|
-
if(!this.activeAndEnabled) return;
|
|
105
|
+
if (!this.activeAndEnabled) return;
|
|
105
106
|
this._needsTextureUpdate = true;
|
|
106
107
|
this.updateProjection();
|
|
107
108
|
}
|
|
108
109
|
/** @internal */
|
|
109
110
|
async onLeaveXR() {
|
|
110
|
-
if(!this.activeAndEnabled) return;
|
|
111
|
+
if (!this.activeAndEnabled) return;
|
|
111
112
|
await delayForFrames(1);
|
|
112
113
|
this.updateProjection();
|
|
113
114
|
}
|
|
@@ -121,8 +122,8 @@ export class GroundProjectedEnv extends Behaviour {
|
|
|
121
122
|
if (blurrinessChanged) {
|
|
122
123
|
this.updateProjection();
|
|
123
124
|
}
|
|
124
|
-
else if (this._needsTextureUpdate) {
|
|
125
|
-
this.updateBlurriness();
|
|
125
|
+
else if (this._needsTextureUpdate && this.context.scene.background instanceof Texture) {
|
|
126
|
+
this.updateBlurriness(this.context.scene.background, this.context.scene.backgroundBlurriness);
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
129
|
|
|
@@ -138,10 +139,16 @@ export class GroundProjectedEnv extends Behaviour {
|
|
|
138
139
|
* Updates the ground projection. This is called automatically when the environment or settings change.
|
|
139
140
|
*/
|
|
140
141
|
updateProjection() {
|
|
141
|
-
if (!this.context.scene.
|
|
142
|
+
if (!this.context.scene.background) {
|
|
143
|
+
this._projection?.removeFromParent();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const backgroundTexture = this.context.scene.background;
|
|
147
|
+
if (!(backgroundTexture instanceof Texture)) {
|
|
142
148
|
this._projection?.removeFromParent();
|
|
143
149
|
return;
|
|
144
150
|
}
|
|
151
|
+
|
|
145
152
|
if (this.context.xr?.isPassThrough || this.context.xr?.isAR) {
|
|
146
153
|
if (this.arBlending === 0) {
|
|
147
154
|
this._projection?.removeFromParent();
|
|
@@ -152,25 +159,25 @@ export class GroundProjectedEnv extends Behaviour {
|
|
|
152
159
|
if (!this.gameObject || this.destroyed) {
|
|
153
160
|
return;
|
|
154
161
|
}
|
|
155
|
-
|
|
162
|
+
|
|
156
163
|
let needsNewAutoFit = true;
|
|
157
164
|
// offset here must be zero (and not .01) because the plane occlusion (when mesh tracking is active) is otherwise not correct
|
|
158
165
|
const offset = 0;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
166
|
+
|
|
167
|
+
const hasChanged = backgroundTexture !== this._lastBackground || this._height !== this._lastHeight || this._radius !== this._lastRadius;
|
|
168
|
+
|
|
169
|
+
if (!this._projection || hasChanged) {
|
|
170
|
+
if (debug) console.log("Create/Update Ground Projection", backgroundTexture.name);
|
|
171
|
+
|
|
162
172
|
this._projection?.removeFromParent();
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
this._projection = new GroundProjection(backgroundTexture, this._height, this._radius, 64);
|
|
176
|
+
}
|
|
177
|
+
catch (e) {
|
|
178
|
+
console.error("Error creating three GroundProjection", e);
|
|
179
|
+
return;
|
|
171
180
|
}
|
|
172
|
-
else
|
|
173
|
-
needsNewAutoFit = false;
|
|
174
181
|
this._projection.position.y = this._height - offset;
|
|
175
182
|
this._projection.name = "GroundProjection";
|
|
176
183
|
setVisibleInCustomShadowRendering(this._projection, false);
|
|
@@ -205,35 +212,35 @@ export class GroundProjectedEnv extends Behaviour {
|
|
|
205
212
|
this.env.radius = this._radius;
|
|
206
213
|
this.env.height = this._height;
|
|
207
214
|
*/
|
|
208
|
-
|
|
215
|
+
|
|
209
216
|
if (this.context.scene.backgroundBlurriness > 0.001 && this._needsTextureUpdate) {
|
|
210
|
-
this.updateBlurriness();
|
|
217
|
+
this.updateBlurriness(backgroundTexture, this.context.scene.backgroundBlurriness);
|
|
211
218
|
}
|
|
212
219
|
|
|
213
|
-
this.
|
|
220
|
+
this._lastBackground = backgroundTexture;
|
|
214
221
|
this._lastHeight = this._height;
|
|
215
222
|
this._lastRadius = this._radius;
|
|
216
|
-
|
|
217
223
|
this._needsTextureUpdate = false;
|
|
218
224
|
}
|
|
219
225
|
|
|
220
226
|
private _blurrynessShader: ShaderMaterial | null = null;
|
|
221
227
|
private _lastBlurriness: number = -1;
|
|
222
228
|
|
|
223
|
-
private updateBlurriness() {
|
|
229
|
+
private updateBlurriness(texture: Texture, blurriness: number) {
|
|
224
230
|
if (!this._projection) {
|
|
225
231
|
return;
|
|
226
232
|
}
|
|
227
|
-
else if (!
|
|
233
|
+
else if (!texture) {
|
|
228
234
|
return;
|
|
229
235
|
}
|
|
236
|
+
|
|
230
237
|
this._needsTextureUpdate = false;
|
|
231
|
-
if (debug) console.log("Update Blurriness",
|
|
238
|
+
if (debug) console.log("Update Blurriness", blurriness);
|
|
232
239
|
this._blurrynessShader ??= new ShaderMaterial({
|
|
233
240
|
name: "GroundProjectionBlurriness",
|
|
234
241
|
uniforms: {
|
|
235
|
-
map: { value:
|
|
236
|
-
blurriness: { value:
|
|
242
|
+
map: { value: texture },
|
|
243
|
+
blurriness: { value: blurriness },
|
|
237
244
|
blending: { value: 0 },
|
|
238
245
|
alphaFactor: { value: 1 }
|
|
239
246
|
},
|
|
@@ -241,9 +248,10 @@ export class GroundProjectedEnv extends Behaviour {
|
|
|
241
248
|
fragmentShader: blurFragmentShader
|
|
242
249
|
});
|
|
243
250
|
this._blurrynessShader.depthWrite = false;
|
|
244
|
-
this._blurrynessShader.uniforms.
|
|
245
|
-
this.
|
|
246
|
-
this.
|
|
251
|
+
this._blurrynessShader.uniforms.map.value = texture;
|
|
252
|
+
this._blurrynessShader.uniforms.blurriness.value = 1;//blurriness;
|
|
253
|
+
this._lastBlurriness = blurriness;
|
|
254
|
+
texture.needsUpdate = true;
|
|
247
255
|
|
|
248
256
|
const wasTransparent = this._projection.material.transparent;
|
|
249
257
|
this._projection.material.transparent = (this.context.xr?.isAR === true && this.arBlending > 0.000001) ?? false;
|
|
@@ -266,7 +274,7 @@ export class GroundProjectedEnv extends Behaviour {
|
|
|
266
274
|
}
|
|
267
275
|
|
|
268
276
|
// Update the texture
|
|
269
|
-
this._projection.material.map = Graphics.copyTexture(
|
|
277
|
+
this._projection.material.map = Graphics.copyTexture(texture, this._blurrynessShader);
|
|
270
278
|
this._projection.material.depthTest = true;
|
|
271
279
|
this._projection.material.depthWrite = false;
|
|
272
280
|
}
|
|
@@ -62,23 +62,23 @@ export class SpatialTriggerReceiver extends Behaviour {
|
|
|
62
62
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
currentIntersected: SpatialTrigger[] = [];
|
|
66
|
-
lastIntersected: SpatialTrigger[] = [];
|
|
65
|
+
readonly currentIntersected: SpatialTrigger[] = [];
|
|
66
|
+
readonly lastIntersected: SpatialTrigger[] = [];
|
|
67
67
|
|
|
68
68
|
onEnterTrigger(trigger: SpatialTrigger): void {
|
|
69
69
|
if(debug) console.log("ENTER TRIGGER", this.name, trigger.name, this, trigger);
|
|
70
70
|
trigger.raiseOnEnterEvent(this);
|
|
71
|
-
this.onEnter?.invoke(
|
|
71
|
+
this.onEnter?.invoke();
|
|
72
72
|
}
|
|
73
73
|
onExitTrigger(trigger: SpatialTrigger): void {
|
|
74
|
-
if(debug) console.log("EXIT TRIGGER", this.name, trigger.name,
|
|
74
|
+
if(debug) console.log("EXIT TRIGGER", this.name, trigger.name, );
|
|
75
75
|
trigger.raiseOnExitEvent(this);
|
|
76
|
-
this.onExit?.invoke(
|
|
76
|
+
this.onExit?.invoke();
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
onStayTrigger(trigger: SpatialTrigger): void {
|
|
80
80
|
trigger.raiseOnStayEvent(this);
|
|
81
|
-
this.onStay?.invoke(
|
|
81
|
+
this.onStay?.invoke();
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MathUtils,Mesh, MeshBasicMaterial, Object3D } from "three";
|
|
1
|
+
import { MathUtils, Mesh, MeshBasicMaterial, Object3D } from "three";
|
|
2
2
|
import { TransformControls } from "three/examples/jsm/controls/TransformControls.js";
|
|
3
3
|
|
|
4
4
|
import * as params from "../engine/engine_default_parameters.js";
|
|
@@ -26,7 +26,15 @@ export class TransformGizmo extends Behaviour {
|
|
|
26
26
|
@serializable()
|
|
27
27
|
public scaleSnap: number = .25;
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Get the underlying three.js TransformControls instance.
|
|
31
|
+
* @returns The TransformControls instance.
|
|
32
|
+
*/
|
|
33
|
+
get control() {
|
|
34
|
+
return this._control;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private _control?: TransformControls;
|
|
30
38
|
private orbit?: OrbitControls;
|
|
31
39
|
|
|
32
40
|
/** @internal */
|
|
@@ -35,12 +43,12 @@ export class TransformGizmo extends Behaviour {
|
|
|
35
43
|
|
|
36
44
|
if (!this.context.mainCamera) return;
|
|
37
45
|
|
|
38
|
-
if (!this.
|
|
39
|
-
this.
|
|
40
|
-
this.
|
|
41
|
-
this.
|
|
42
|
-
this.
|
|
43
|
-
const obj = ("_root" in this.
|
|
46
|
+
if (!this._control) {
|
|
47
|
+
this._control = new TransformControls(this.context.mainCamera, this.context.renderer.domElement);
|
|
48
|
+
this._control.enabled = true;
|
|
49
|
+
this._control.getRaycaster().layers.set(2);
|
|
50
|
+
this._control.size = 1;
|
|
51
|
+
const obj = ("_root" in this._control ? this._control._root : this._control) as Object3D;
|
|
44
52
|
obj.traverse(x => {
|
|
45
53
|
const mesh = x as Mesh;
|
|
46
54
|
mesh.layers.set(2);
|
|
@@ -54,12 +62,12 @@ export class TransformGizmo extends Behaviour {
|
|
|
54
62
|
this.orbit = GameObject.getComponentInParent(this.context.mainCamera, OrbitControls) ?? undefined;
|
|
55
63
|
}
|
|
56
64
|
|
|
57
|
-
if (this.
|
|
58
|
-
const obj = this.
|
|
65
|
+
if (this._control) {
|
|
66
|
+
const obj = this._control.getHelper();
|
|
59
67
|
this.context.scene.add(obj);
|
|
60
|
-
this.
|
|
68
|
+
this._control.attach(this.gameObject);
|
|
61
69
|
|
|
62
|
-
this.
|
|
70
|
+
this._control?.addEventListener('dragging-changed', this.onControlChangedEvent);
|
|
63
71
|
window.addEventListener('keydown', this.windowKeyDownListener);
|
|
64
72
|
window.addEventListener('keyup', this.windowKeyUpListener);
|
|
65
73
|
}
|
|
@@ -67,25 +75,25 @@ export class TransformGizmo extends Behaviour {
|
|
|
67
75
|
|
|
68
76
|
/** @internal */
|
|
69
77
|
onDisable() {
|
|
70
|
-
this.
|
|
71
|
-
this.
|
|
78
|
+
this._control?.getHelper()?.removeFromParent();
|
|
79
|
+
this._control?.removeEventListener('dragging-changed', this.onControlChangedEvent);
|
|
72
80
|
window.removeEventListener('keydown', this.windowKeyDownListener);
|
|
73
81
|
window.removeEventListener('keyup', this.windowKeyUpListener);
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
enableSnapping() {
|
|
77
|
-
if (this.
|
|
78
|
-
this.
|
|
79
|
-
this.
|
|
80
|
-
this.
|
|
85
|
+
if (this._control) {
|
|
86
|
+
this._control.setTranslationSnap(this.translationSnap);
|
|
87
|
+
this._control.setRotationSnap(MathUtils.degToRad(this.rotationSnapAngle));
|
|
88
|
+
this._control.setScaleSnap(this.scaleSnap);
|
|
81
89
|
}
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
disableSnapping() {
|
|
85
|
-
if (this.
|
|
86
|
-
this.
|
|
87
|
-
this.
|
|
88
|
-
this.
|
|
93
|
+
if (this._control) {
|
|
94
|
+
this._control.setTranslationSnap(null);
|
|
95
|
+
this._control.setRotationSnap(null);
|
|
96
|
+
this._control.setScaleSnap(null);
|
|
89
97
|
}
|
|
90
98
|
}
|
|
91
99
|
|
|
@@ -104,11 +112,11 @@ export class TransformGizmo extends Behaviour {
|
|
|
104
112
|
|
|
105
113
|
private windowKeyDownListener = (event) => {
|
|
106
114
|
if (!this.enabled) return;
|
|
107
|
-
if (!this.
|
|
115
|
+
if (!this._control) return;
|
|
108
116
|
switch (event.keyCode) {
|
|
109
117
|
|
|
110
118
|
case 81: // Q
|
|
111
|
-
this.
|
|
119
|
+
this._control.setSpace(this._control.space === 'local' ? 'world' : 'local');
|
|
112
120
|
break;
|
|
113
121
|
|
|
114
122
|
case 16: // Shift
|
|
@@ -116,40 +124,40 @@ export class TransformGizmo extends Behaviour {
|
|
|
116
124
|
break;
|
|
117
125
|
|
|
118
126
|
case 87: // W
|
|
119
|
-
this.
|
|
127
|
+
this._control.setMode('translate');
|
|
120
128
|
break;
|
|
121
129
|
|
|
122
130
|
case 69: // E
|
|
123
|
-
this.
|
|
131
|
+
this._control.setMode('rotate');
|
|
124
132
|
break;
|
|
125
133
|
|
|
126
134
|
case 82: // R
|
|
127
|
-
this.
|
|
135
|
+
this._control.setMode('scale');
|
|
128
136
|
break;
|
|
129
137
|
case 187:
|
|
130
138
|
case 107: // +, =, num+
|
|
131
|
-
this.
|
|
139
|
+
this._control.setSize(this._control.size + 0.1);
|
|
132
140
|
break;
|
|
133
141
|
|
|
134
142
|
case 189:
|
|
135
143
|
case 109: // -, _, num-
|
|
136
|
-
this.
|
|
144
|
+
this._control.setSize(Math.max(this._control.size - 0.1, 0.1));
|
|
137
145
|
break;
|
|
138
146
|
|
|
139
147
|
case 88: // X
|
|
140
|
-
this.
|
|
148
|
+
this._control.showX = !this._control.showX;
|
|
141
149
|
break;
|
|
142
150
|
|
|
143
151
|
case 89: // Y
|
|
144
|
-
this.
|
|
152
|
+
this._control.showY = !this._control.showY;
|
|
145
153
|
break;
|
|
146
154
|
|
|
147
155
|
case 90: // Z
|
|
148
|
-
this.
|
|
156
|
+
this._control.showZ = !this._control.showZ;
|
|
149
157
|
break;
|
|
150
158
|
|
|
151
159
|
case 32: // Spacebar
|
|
152
|
-
this.
|
|
160
|
+
this._control.enabled = !this._control.enabled;
|
|
153
161
|
break;
|
|
154
162
|
}
|
|
155
163
|
}
|
|
@@ -23,11 +23,21 @@ export class XRRig extends Behaviour implements IXRRig {
|
|
|
23
23
|
|
|
24
24
|
get isActive() { return this.activeAndEnabled && this.gameObject.visible; }
|
|
25
25
|
|
|
26
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Sets this rig to be the active XR rig (needs to be called during an active XR session)
|
|
28
|
+
* Note that this might modify the priority of this rig to be the highest.
|
|
29
|
+
*/
|
|
27
30
|
setAsActiveXRRig() {
|
|
28
31
|
NeedleXRSession.active?.setRigActive(this);
|
|
29
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Sets the priority of the rig.
|
|
35
|
+
*/
|
|
36
|
+
setPriority(value: number) {
|
|
37
|
+
this.priority = value;
|
|
38
|
+
}
|
|
30
39
|
|
|
40
|
+
/** @internal */
|
|
31
41
|
awake(): void {
|
|
32
42
|
if (debug) {
|
|
33
43
|
const gizmoObj = new Object3D() as IGameObject;
|
|
@@ -51,15 +61,18 @@ export class XRRig extends Behaviour implements IXRRig {
|
|
|
51
61
|
|
|
52
62
|
private _startScale?: Vector3;
|
|
53
63
|
|
|
64
|
+
/** @internal */
|
|
54
65
|
onEnterXR(args: NeedleXREventArgs): void {
|
|
55
66
|
this._startScale = this.gameObject.scale.clone();
|
|
56
67
|
args.xr.addRig(this);
|
|
57
|
-
if(debug) console.log("WebXR: add Rig", this.name, this.priority);
|
|
68
|
+
if (debug) console.log("WebXR: add Rig", this.name, this.priority);
|
|
58
69
|
}
|
|
70
|
+
/** @internal */
|
|
59
71
|
onLeaveXR(args: NeedleXREventArgs): void {
|
|
60
72
|
args.xr.removeRig(this);
|
|
61
73
|
if (this._startScale && this.gameObject)
|
|
62
74
|
this.gameObject.scale.copy(this._startScale);
|
|
63
75
|
}
|
|
64
76
|
|
|
77
|
+
|
|
65
78
|
}
|
|
@@ -20,7 +20,7 @@ declare type PlayerSyncWithAsset = PlayerSync & Required<Pick<PlayerSync, "asset
|
|
|
20
20
|
* @category Networking
|
|
21
21
|
*/
|
|
22
22
|
export class PlayerSync extends Behaviour {
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
/**
|
|
25
25
|
* This API is experimental and may change or be removed in the future.
|
|
26
26
|
* Create a PlayerSync instance at runtime from a given URL
|
|
@@ -103,6 +103,7 @@ export class PlayerSync extends Behaviour {
|
|
|
103
103
|
const instance = await this._localInstance;
|
|
104
104
|
if (instance) {
|
|
105
105
|
const pl = GameObject.getComponentsInChildren(instance, PlayerState);
|
|
106
|
+
if (debug) console.log(`PlayerSync.createInstance: found ${pl?.length} PlayerState components. Owner: ${this.context.connection.connectionId}`);
|
|
106
107
|
if (pl?.length) {
|
|
107
108
|
for (const state of pl)
|
|
108
109
|
state.owner = this.context.connection.connectionId!;
|
|
@@ -226,7 +227,7 @@ export class PlayerState extends Behaviour {
|
|
|
226
227
|
}
|
|
227
228
|
|
|
228
229
|
private onOwnerChange(newOwner: string, oldOwner: string) {
|
|
229
|
-
if (debug) console.log(
|
|
230
|
+
if (debug) console.log(`PlayerSync.onOwnerChange: ${oldOwner} → ${newOwner} (me: ${this.context.connection.connectionId})`);
|
|
230
231
|
|
|
231
232
|
// Remove from local owner array if it was local before
|
|
232
233
|
const index = PlayerState._local.indexOf(this);
|
|
@@ -259,6 +260,7 @@ export class PlayerState extends Behaviour {
|
|
|
259
260
|
PlayerState.dispatchEvent(PlayerStateEvent.OwnerChanged, evt);
|
|
260
261
|
}
|
|
261
262
|
|
|
263
|
+
/** @internal */
|
|
262
264
|
awake(): void {
|
|
263
265
|
PlayerState.all.push(this);
|
|
264
266
|
if (debug) console.log("Registered new PlayerState", this.guid, PlayerState.all.length - 1, PlayerState.all)
|
|
@@ -266,31 +268,10 @@ export class PlayerState extends Behaviour {
|
|
|
266
268
|
this.context.connection.beginListen(RoomEvents.UserLeftRoom, this.onUserLeftRoom);
|
|
267
269
|
}
|
|
268
270
|
|
|
269
|
-
|
|
270
|
-
if (model.userId === this.owner) {
|
|
271
|
-
if (debug)
|
|
272
|
-
console.log("PLAYERSYNC LEFT", this.owner)
|
|
273
|
-
this.doDestroy();
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
|
|
271
|
+
/** @internal */
|
|
279
272
|
async start() {
|
|
280
273
|
if (debug) console.log("PLAYERSTATE.START, owner: " + this.owner, this.context.connection.usersInRoom([]))
|
|
281
274
|
|
|
282
|
-
// generate number from owner
|
|
283
|
-
// if (this.owner) {
|
|
284
|
-
// // string to number
|
|
285
|
-
// let num = 0;
|
|
286
|
-
// for (let i = 0; i < this.owner.length; i++) {
|
|
287
|
-
// num += this.owner.charCodeAt(i);
|
|
288
|
-
// }
|
|
289
|
-
// console.log(num)
|
|
290
|
-
// num = num / 1000
|
|
291
|
-
// this.gameObject.position.y = num;
|
|
292
|
-
// }
|
|
293
|
-
|
|
294
275
|
// If a player is spawned but not in the room anymore we want to destroy it
|
|
295
276
|
// this might happen in a case where all users get disconnected at once and the server
|
|
296
277
|
// still has the syncInstantiate messages that are sent to all clients
|
|
@@ -314,29 +295,20 @@ export class PlayerState extends Behaviour {
|
|
|
314
295
|
}
|
|
315
296
|
else if (debug) console.warn("PlayerState.start → owner is still undefined but dontDestroy is set to true", this.name);
|
|
316
297
|
}
|
|
317
|
-
else if(debug) console.log("PlayerState.start → owner is assigned", this.owner);
|
|
298
|
+
else if (debug) console.log("PlayerState.start → owner is assigned", this.owner);
|
|
318
299
|
}, 2000);
|
|
319
300
|
}
|
|
320
301
|
}
|
|
321
302
|
|
|
322
|
-
// onEnable() {
|
|
323
|
-
// if (debug) this.startCoroutine(this.debugRoutine());
|
|
324
|
-
// }
|
|
325
|
-
|
|
326
|
-
// *debugRoutine() {
|
|
327
|
-
// while (!this.destroyed && this.activeAndEnabled) {
|
|
328
|
-
// Gizmos.DrawLabel(this.gameObject.worldPosition, this.owner ?? "no owner");
|
|
329
|
-
// yield;
|
|
330
|
-
// }
|
|
331
|
-
// }
|
|
332
|
-
|
|
333
303
|
/** this tells the server that this client has been destroyed and the networking message for the instantiate will be removed */
|
|
334
304
|
doDestroy() {
|
|
335
305
|
if (debug) console.log("PlayerSync.doDestroy → syncDestroy", this.name);
|
|
336
306
|
syncDestroy(this.gameObject, this.context.connection, true, { saveInRoom: false });
|
|
337
307
|
}
|
|
338
308
|
|
|
309
|
+
/** @internal */
|
|
339
310
|
onDestroy() {
|
|
311
|
+
if(debug) console.warn("PlayerState.onDestroy", this.owner);
|
|
340
312
|
this.context.connection.stopListen(RoomEvents.UserLeftRoom, this.onUserLeftRoom);
|
|
341
313
|
PlayerState.all.splice(PlayerState.all.indexOf(this), 1);
|
|
342
314
|
|
|
@@ -346,4 +318,13 @@ export class PlayerState extends Behaviour {
|
|
|
346
318
|
PlayerState._local.splice(index, 1);
|
|
347
319
|
}
|
|
348
320
|
}
|
|
321
|
+
|
|
322
|
+
private onUserLeftRoom = (model: { userId: string }) => {
|
|
323
|
+
if (model.userId === this.owner) {
|
|
324
|
+
if (debug)
|
|
325
|
+
console.log("PLAYERSYNC LEFT", this.owner)
|
|
326
|
+
this.doDestroy();
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
349
330
|
}
|