@needle-tools/engine 3.9.1-alpha → 3.10.0-beta
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 +14 -0
- package/dist/needle-engine.js +1 -1
- package/dist/needle-engine.light.js +1 -1
- package/dist/needle-engine.light.min.js +1 -1
- package/dist/needle-engine.light.umd.cjs +1 -1
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/lib/engine/engine_element_overlay.d.ts +2 -5
- package/lib/engine/engine_element_overlay.js +18 -30
- package/lib/engine/engine_element_overlay.js.map +1 -1
- package/lib/engine/engine_input.js +10 -5
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_mainloop_utils.js +6 -1
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_networking_auto.d.ts +4 -1
- package/lib/engine/engine_networking_auto.js +43 -12
- package/lib/engine/engine_networking_auto.js.map +1 -1
- package/lib/engine/engine_types.d.ts +4 -2
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine-components/DragControls.d.ts +5 -1
- package/lib/engine-components/DragControls.js +32 -3
- package/lib/engine-components/DragControls.js.map +1 -1
- package/lib/engine-components/timeline/TimelineTracks.js +31 -14
- package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
- package/lib/engine-components/ui/Canvas.js +6 -1
- package/lib/engine-components/ui/Canvas.js.map +1 -1
- package/lib/engine-components/ui/Text.js +2 -1
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/engine-components/webxr/WebXR.js +6 -0
- package/lib/engine-components/webxr/WebXR.js.map +1 -1
- package/package.json +1 -1
- package/src/engine/engine_element_overlay.ts +17 -30
- package/src/engine/engine_input.ts +9 -4
- package/src/engine/engine_mainloop_utils.ts +8 -3
- package/src/engine/engine_networking_auto.ts +48 -22
- package/src/engine/engine_types.ts +6 -3
- package/src/engine-components/DragControls.ts +24 -3
- package/src/engine-components/timeline/TimelineTracks.ts +30 -13
- package/src/engine-components/ui/Canvas.ts +9 -1
- package/src/engine-components/ui/Text.ts +3 -1
- package/src/engine-components/webxr/WebXR.ts +6 -0
|
@@ -5,6 +5,7 @@ import { CubeCamera, Object3D, Scene, WebGLCubeRenderTarget } from 'three';
|
|
|
5
5
|
import { IComponent, IContext } from './engine_types';
|
|
6
6
|
import { isActiveSelf } from './engine_gameobject';
|
|
7
7
|
import { ContextRegistry } from "./engine_context_registry";
|
|
8
|
+
import { showBalloonWarning, isDevEnvironment, showBalloonMessage, LogType } from "./debug";
|
|
8
9
|
|
|
9
10
|
const debug = getParam("debugnewscripts");
|
|
10
11
|
const debugHierarchy = getParam("debughierarchy");
|
|
@@ -171,8 +172,7 @@ export function processStart(context: IContext, object?: Object3D) {
|
|
|
171
172
|
// keep them in queue until script has started
|
|
172
173
|
// call awake if the script was inactive before
|
|
173
174
|
utils.safeInvoke(script.__internalAwake.bind(script));
|
|
174
|
-
if(script.enabled)
|
|
175
|
-
{
|
|
175
|
+
if (script.enabled) {
|
|
176
176
|
utils.safeInvoke(script.__internalEnable.bind(script));
|
|
177
177
|
// now call start
|
|
178
178
|
utils.safeInvoke(script.__internalStart.bind(script));
|
|
@@ -232,8 +232,13 @@ export function updateIsActive(obj?: Object3D) {
|
|
|
232
232
|
const activeSelf = isActiveSelf(obj);
|
|
233
233
|
const wasSuccessful = updateIsActiveInHierarchyRecursiveRuntime(obj, activeSelf, true);
|
|
234
234
|
if (!wasSuccessful) {
|
|
235
|
-
|
|
235
|
+
if (debug || isDevEnvironment()) {
|
|
236
|
+
console.error("Error updating hierarchy\nDo you have circular references in your project? <a target=\"_blank\" href=\"https://docs.needle.tools/circular-reference\"> Click here for more information.", obj)
|
|
237
|
+
}
|
|
238
|
+
else
|
|
239
|
+
console.error("Failed to update active state in hierarchy of \"" + obj.name + "\"", obj);
|
|
236
240
|
console.warn(" ↑ this error might be caused by circular references. Please make sure you don't have files with circular references (e.g. one GLB 1 is loading GLB 2 which is then loading GLB 1 again).")
|
|
241
|
+
|
|
237
242
|
}
|
|
238
243
|
}
|
|
239
244
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getParam } from "./engine_utils";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { isDevEnvironment } from "./debug";
|
|
3
|
+
import { IComponent } from "./engine_types";
|
|
4
4
|
|
|
5
5
|
const debug = getParam("debugautosync");
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ const $syncerId = Symbol("syncerId");
|
|
|
8
8
|
class ComponentsSyncerManager {
|
|
9
9
|
private _syncers: { [key: string]: ComponentPropertiesSyncer } = {};
|
|
10
10
|
|
|
11
|
-
getOrCreateSyncer(comp:
|
|
11
|
+
getOrCreateSyncer(comp: IComponent): ComponentPropertiesSyncer | null {
|
|
12
12
|
if (!comp.guid) return null;
|
|
13
13
|
if (this._syncers[comp.guid]) return this._syncers[comp.guid];
|
|
14
14
|
const syncer = new ComponentPropertiesSyncer(comp);
|
|
@@ -28,9 +28,9 @@ const syncerHandler = new ComponentsSyncerManager();
|
|
|
28
28
|
*/
|
|
29
29
|
class ComponentPropertiesSyncer {
|
|
30
30
|
|
|
31
|
-
comp:
|
|
31
|
+
comp: IComponent;
|
|
32
32
|
|
|
33
|
-
constructor(comp:
|
|
33
|
+
constructor(comp: IComponent) {
|
|
34
34
|
// console.log("CREATE NEW SYNC", comp.name, comp.guid);
|
|
35
35
|
this.comp = comp;
|
|
36
36
|
}
|
|
@@ -115,8 +115,7 @@ class ComponentPropertiesSyncer {
|
|
|
115
115
|
if (!this.comp) return;
|
|
116
116
|
const guid = val.guid;
|
|
117
117
|
if (guid && guid !== this.comp.guid) return;
|
|
118
|
-
if (debug)
|
|
119
|
-
console.log("RECEIVED", this.comp.name, this.comp.guid, val);
|
|
118
|
+
if (debug) console.log("RECEIVED", this.comp.name, this.comp.guid, val);
|
|
120
119
|
try {
|
|
121
120
|
this._isReceiving = true;
|
|
122
121
|
for (const key in val) {
|
|
@@ -124,6 +123,7 @@ class ComponentPropertiesSyncer {
|
|
|
124
123
|
// TODO: maybe use serializable here?!
|
|
125
124
|
const value = val[key];
|
|
126
125
|
this.comp[key] = value;
|
|
126
|
+
if(debug) console.log("SET", key, value);
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
catch (err) {
|
|
@@ -164,13 +164,16 @@ function testValueChanged(newValue, previousValue): boolean {
|
|
|
164
164
|
// }
|
|
165
165
|
}
|
|
166
166
|
else if (typeof newValue === "object" && typeof previousValue === "object") {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
167
|
+
valueChanged = true;
|
|
168
|
+
// The following code doesnt work because the object is a reference type
|
|
169
|
+
// To properly detect changes we would have to detect assignments for each property #
|
|
170
|
+
// OR keep a copy of the previous object
|
|
171
|
+
// for (const key of Object.keys(newValue)) {
|
|
172
|
+
// if (newValue[key] !== previousValue[key]) {
|
|
173
|
+
// valueChanged = true;
|
|
174
|
+
// break;
|
|
175
|
+
// }
|
|
176
|
+
// }
|
|
174
177
|
}
|
|
175
178
|
}
|
|
176
179
|
return valueChanged;
|
|
@@ -203,14 +206,17 @@ export declare type SyncFieldOptions = {
|
|
|
203
206
|
export declare type FieldChangedCallbackFn = (newValue: any, previousValue: any) => void | boolean;
|
|
204
207
|
|
|
205
208
|
/**
|
|
206
|
-
* Decorate a field to be automatically networked synced
|
|
209
|
+
* **Decorate a field to be automatically networked synced**
|
|
210
|
+
* *Primitive* values are all automatically synced (like string, boolean, number).
|
|
211
|
+
* For *arrays or objects* make sure to re-assign them (e.g. `this.mySyncField = this.mySyncField`) to trigger an update
|
|
212
|
+
*
|
|
207
213
|
* @param onFieldChanged name of a callback function that will be called when the field is changed.
|
|
208
214
|
* You can also pass in a function like so: syncField(myClass.prototype.myFunctionToBeCalled)
|
|
209
215
|
* This function may return false to prevent notifyChanged from being called
|
|
210
216
|
* (for example a networked color is sent as a number and may be converted to a color in the receiver again)
|
|
211
217
|
* Parameters: (newValue, previousValue)
|
|
212
218
|
*/
|
|
213
|
-
export const syncField = function(onFieldChanged?: string | FieldChangedCallbackFn) {
|
|
219
|
+
export const syncField = function (onFieldChanged?: string | FieldChangedCallbackFn) {
|
|
214
220
|
|
|
215
221
|
return function (target: any, propertyKey: string) {
|
|
216
222
|
|
|
@@ -225,6 +231,11 @@ export const syncField = function(onFieldChanged?: string | FieldChangedCallback
|
|
|
225
231
|
|
|
226
232
|
const t = target;
|
|
227
233
|
const internalAwake = t.__internalAwake;
|
|
234
|
+
if (typeof internalAwake !== "function") {
|
|
235
|
+
if (debug || isDevEnvironment())
|
|
236
|
+
console.error("@syncField can currently only used on Needle Engine Components, custom object of type \"" + target?.constructor?.name + "\" is not supported", target);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
228
239
|
if (debug)
|
|
229
240
|
console.log(propertyKey);
|
|
230
241
|
const backingFieldName = Symbol(propertyKey);
|
|
@@ -234,19 +245,34 @@ export const syncField = function(onFieldChanged?: string | FieldChangedCallback
|
|
|
234
245
|
return;
|
|
235
246
|
}
|
|
236
247
|
this[backingFieldName] = this[propertyKey];
|
|
237
|
-
internalAwake.call(this);
|
|
238
248
|
|
|
239
249
|
syncer = syncerHandler.getOrCreateSyncer(this);
|
|
240
250
|
|
|
241
251
|
const desc = Object.getOwnPropertyDescriptor(this, propertyKey);
|
|
242
252
|
if (desc?.set === undefined) {
|
|
253
|
+
let invokingCallback = false;
|
|
243
254
|
Object.defineProperty(this, propertyKey, {
|
|
244
255
|
set: function (value) {
|
|
245
256
|
const oldValue = this[backingFieldName];
|
|
246
257
|
this[backingFieldName] = value;
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
258
|
+
// Prevent recursive calls when object is assigned in callback
|
|
259
|
+
if (invokingCallback) {
|
|
260
|
+
if (isDevEnvironment())
|
|
261
|
+
console.warn("Recursive call detected", propertyKey);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
invokingCallback = true;
|
|
265
|
+
try {
|
|
266
|
+
const valueChanged = testValueChanged(value, oldValue);
|
|
267
|
+
if (debug) console.log("SyncField assignment", propertyKey, "changed?", valueChanged, value);
|
|
268
|
+
if (valueChanged) {
|
|
269
|
+
if (fn?.call(this, value, oldValue) !== false) {
|
|
270
|
+
getSyncer(this)?.notifyChanged(propertyKey, value);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
finally {
|
|
275
|
+
invokingCallback = false;
|
|
250
276
|
}
|
|
251
277
|
},
|
|
252
278
|
get: function () {
|
|
@@ -258,7 +284,7 @@ export const syncField = function(onFieldChanged?: string | FieldChangedCallback
|
|
|
258
284
|
}
|
|
259
285
|
|
|
260
286
|
syncer?.init(this);
|
|
261
|
-
|
|
287
|
+
internalAwake.call(this);
|
|
262
288
|
}
|
|
263
289
|
|
|
264
290
|
const internalDestroy = t.__internalDestroy;
|
|
@@ -281,7 +307,7 @@ export const sync = function (_options?: SyncOptions) {
|
|
|
281
307
|
|
|
282
308
|
return function <T>(target: any, _propertyKey: string, descriptor: PropertyDescriptor) {
|
|
283
309
|
// override awake
|
|
284
|
-
const comp = target as
|
|
310
|
+
const comp = target as IComponent;
|
|
285
311
|
let syncer: ComponentPropertiesSyncer | null;
|
|
286
312
|
const internalAwake = comp.__internalAwake.bind(comp);
|
|
287
313
|
comp.__internalAwake = function () {
|
|
@@ -123,12 +123,15 @@ export declare interface IGameObject extends Object3D {
|
|
|
123
123
|
getComponentsInParent<T>(type: Constructor<T>, arr?: T[]): Array<T>;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
export interface
|
|
127
|
-
|
|
126
|
+
export interface IHasGuid {
|
|
127
|
+
guid: string;
|
|
128
|
+
}
|
|
128
129
|
|
|
130
|
+
export interface IComponent extends IHasGuid {
|
|
131
|
+
get isComponent(): boolean;
|
|
129
132
|
|
|
130
133
|
gameObject: IGameObject;
|
|
131
|
-
guid: string;
|
|
134
|
+
// guid: string;
|
|
132
135
|
enabled: boolean;
|
|
133
136
|
sourceId?: SourceIdentifier;
|
|
134
137
|
|
|
@@ -13,6 +13,8 @@ import { nameofFactory } from "../engine/engine_utils";
|
|
|
13
13
|
import { InstancingUtil } from "../engine/engine_instancing";
|
|
14
14
|
import { OrbitControls } from "./OrbitControls";
|
|
15
15
|
import { BufferGeometry, Camera, Color, Line, LineBasicMaterial, Matrix4, Mesh, MeshBasicMaterial, Object3D, Plane, Ray, Raycaster, SphereGeometry, Vector2, Vector3 } from "three";
|
|
16
|
+
import { ObjectRaycaster } from "./ui/Raycaster";
|
|
17
|
+
import { serializable } from "../engine/engine_serialization_decorator";
|
|
16
18
|
|
|
17
19
|
const debug = false;
|
|
18
20
|
|
|
@@ -37,6 +39,13 @@ export class DragControls extends Interactable implements IPointerDownHandler, I
|
|
|
37
39
|
private static _active: number = 0;
|
|
38
40
|
public static get HasAnySelected(): boolean { return this._active > 0; }
|
|
39
41
|
|
|
42
|
+
/** Show's drag gizmos when enabled */
|
|
43
|
+
@serializable()
|
|
44
|
+
public showGizmo: boolean = true;
|
|
45
|
+
|
|
46
|
+
/** When enabled DragControls will drag vertically when the object is viewed from a low angle */
|
|
47
|
+
@serializable()
|
|
48
|
+
public useViewAngle: boolean = true;
|
|
40
49
|
|
|
41
50
|
public transformSelf: boolean = true;
|
|
42
51
|
// public transformGroup: boolean = true;
|
|
@@ -47,6 +56,7 @@ export class DragControls extends Interactable implements IPointerDownHandler, I
|
|
|
47
56
|
|
|
48
57
|
private selectStartEventListener: ((controls: DragControls, args: SelectArgs) => void)[] = [];
|
|
49
58
|
private selectEndEventListener: Array<Function> = [];
|
|
59
|
+
private _dragHelper: DragHelper | null = null;
|
|
50
60
|
|
|
51
61
|
constructor() {
|
|
52
62
|
super();
|
|
@@ -66,11 +76,13 @@ export class DragControls extends Interactable implements IPointerDownHandler, I
|
|
|
66
76
|
}
|
|
67
77
|
}
|
|
68
78
|
|
|
69
|
-
private _dragHelper: DragHelper | null = null;
|
|
70
79
|
|
|
71
80
|
|
|
72
81
|
start() {
|
|
73
82
|
this.orbit = GameObject.findObjectOfType(OrbitControls, this.context);
|
|
83
|
+
if (!this.gameObject.getComponentInParent(ObjectRaycaster)) {
|
|
84
|
+
this.gameObject.addNewComponent(ObjectRaycaster);
|
|
85
|
+
}
|
|
74
86
|
}
|
|
75
87
|
|
|
76
88
|
private static lastHovered: Object3D;
|
|
@@ -234,6 +246,8 @@ export class DragControls extends Interactable implements IPointerDownHandler, I
|
|
|
234
246
|
|
|
235
247
|
private onUpdateDrag() {
|
|
236
248
|
if (!this._dragHelper) return;
|
|
249
|
+
this._dragHelper.showGizmo = this.showGizmo;
|
|
250
|
+
this._dragHelper.useViewAngle = this.useViewAngle;
|
|
237
251
|
|
|
238
252
|
this._dragHelper.onUpdate(this.context);
|
|
239
253
|
for (const rb of this._draggingRigidbodies) {
|
|
@@ -279,6 +293,9 @@ export class DragControls extends Interactable implements IPointerDownHandler, I
|
|
|
279
293
|
|
|
280
294
|
class DragHelper {
|
|
281
295
|
|
|
296
|
+
showGizmo: boolean = true;
|
|
297
|
+
useViewAngle: boolean = true;
|
|
298
|
+
|
|
282
299
|
public get hasSelected(): boolean {
|
|
283
300
|
return this._selected !== null && this._selected !== undefined;
|
|
284
301
|
}
|
|
@@ -416,7 +433,10 @@ class DragHelper {
|
|
|
416
433
|
const lookDot = Math.abs(lookDirection.dot(this._groundOffsetVector));
|
|
417
434
|
|
|
418
435
|
const switchModeKeyPressed = this._context?.input.isKeyPressed(mainKey) || this._context?.input.isKeyPressed(secondaryKey);
|
|
419
|
-
|
|
436
|
+
let dragOnGroundPlane = !this.useViewAngle || lookDot > .2;
|
|
437
|
+
if (isRotating || switchModeKeyPressed || this._context!.input.getPointerPressedCount() > 1) {
|
|
438
|
+
dragOnGroundPlane = false;
|
|
439
|
+
}
|
|
420
440
|
const changed = this._didDragOnGroundPlaneLastFrame !== dragOnGroundPlane;
|
|
421
441
|
this._didDragOnGroundPlaneLastFrame = dragOnGroundPlane;
|
|
422
442
|
|
|
@@ -477,8 +497,9 @@ class DragHelper {
|
|
|
477
497
|
this._groundLine.scale.y = this._groundDistance;
|
|
478
498
|
}
|
|
479
499
|
else this._groundLine.scale.y = 1000;
|
|
500
|
+
this._groundLine.visible = this.showGizmo;
|
|
480
501
|
|
|
481
|
-
this._groundMarker.visible = pointOnPlane !== null;
|
|
502
|
+
this._groundMarker.visible = pointOnPlane !== null && this.showGizmo;
|
|
482
503
|
if (pointOnPlane) {
|
|
483
504
|
const s = getWorldPosition(this._camera).distanceTo(pointOnPlane) * .01;
|
|
484
505
|
this._groundMarker.scale.set(s, s, s);
|
|
@@ -331,9 +331,19 @@ export class AnimationTrackHandler extends TrackHandler {
|
|
|
331
331
|
|
|
332
332
|
let handleLoop = isInTimeRange;
|
|
333
333
|
if (doPreExtrapolate) {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
334
|
+
switch (preExtrapolation) {
|
|
335
|
+
case Models.ClipExtrapolation.Hold:
|
|
336
|
+
// Nothing to do
|
|
337
|
+
break;
|
|
338
|
+
case Models.ClipExtrapolation.Loop:
|
|
339
|
+
// TODO: this is not correct yet
|
|
340
|
+
time += model.start;
|
|
341
|
+
handleLoop = true;
|
|
342
|
+
break;
|
|
343
|
+
default:
|
|
344
|
+
time += model.start;
|
|
345
|
+
handleLoop = true;
|
|
346
|
+
break;
|
|
337
347
|
}
|
|
338
348
|
}
|
|
339
349
|
|
|
@@ -341,6 +351,8 @@ export class AnimationTrackHandler extends TrackHandler {
|
|
|
341
351
|
let t = this.getClipTime(time, model);
|
|
342
352
|
let loops = 0;
|
|
343
353
|
const duration = clipModel.duration;
|
|
354
|
+
// This is the actual duration of the clip in the timeline (with clipping and scale)
|
|
355
|
+
// const clipDuration = (model.end - model.start) * model.timeScale;
|
|
344
356
|
|
|
345
357
|
if (doPreExtrapolate) {
|
|
346
358
|
if (preExtrapolation === Models.ClipExtrapolation.Hold) {
|
|
@@ -358,16 +370,21 @@ export class AnimationTrackHandler extends TrackHandler {
|
|
|
358
370
|
}
|
|
359
371
|
}
|
|
360
372
|
else if (!isInTimeRange) {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
373
|
+
if (didPostExtrapolate) {
|
|
374
|
+
switch (postExtrapolation) {
|
|
375
|
+
case Models.ClipExtrapolation.Hold:
|
|
376
|
+
t = this.getClipTime(model.end, model);
|
|
377
|
+
break;
|
|
378
|
+
case Models.ClipExtrapolation.Loop:
|
|
379
|
+
t %= duration;
|
|
380
|
+
break;
|
|
381
|
+
case Models.ClipExtrapolation.PingPong:
|
|
382
|
+
const loops = Math.floor(t / duration);
|
|
383
|
+
const invert = loops % 2 !== 0;
|
|
384
|
+
t %= duration;
|
|
385
|
+
if (invert) t = duration - t;
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
371
388
|
}
|
|
372
389
|
}
|
|
373
390
|
|
|
@@ -190,7 +190,15 @@ export class Canvas extends UIRootComponent implements ICanvas {
|
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
onBeforeRenderRoutine = () => {
|
|
193
|
-
|
|
193
|
+
|
|
194
|
+
if (this.context.isInVR) {
|
|
195
|
+
// TODO TMUI @swingingtom - For VR this is so we don't have text clipping
|
|
196
|
+
this.shadowComponent?.updateMatrixWorld(true);
|
|
197
|
+
this.shadowComponent?.updateWorldMatrix(true, true);
|
|
198
|
+
EventSystem.ensureUpdateMeshUI(ThreeMeshUI, this.context);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
194
202
|
this.previousParent = this.gameObject.parent;
|
|
195
203
|
// console.log(this.previousParent?.name + "/" + this.gameObject.name);
|
|
196
204
|
|
|
@@ -103,7 +103,9 @@ export class Text extends Graphic implements IHasAlphaFactor {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
onBeforeRender(): void {
|
|
106
|
-
|
|
106
|
+
// TODO TMUI @swingingtom this is so we don't have text clipping
|
|
107
|
+
if (this.uiObject && (this.Canvas?.screenspace || this.context.isInVR))
|
|
108
|
+
{
|
|
107
109
|
this.updateOverflow();
|
|
108
110
|
}
|
|
109
111
|
}
|
|
@@ -604,6 +604,12 @@ export class WebAR {
|
|
|
604
604
|
|
|
605
605
|
if (!this.sessionRoot || this.sessionRoot.destroyed || !this.sessionRoot.activeAndEnabled)
|
|
606
606
|
this.sessionRoot = GameObject.findObjectOfType(WebARSessionRoot, context);
|
|
607
|
+
if (!this.sessionRoot) {
|
|
608
|
+
// TODO: adding it on the scene directly doesnt work (probably because then everything in the scene is disabled including this component). See code a bit furhter below where we add this component to a temporary object inside the scene
|
|
609
|
+
const obj = this.webxr.gameObject;
|
|
610
|
+
this.sessionRoot = GameObject.addNewComponent(obj, WebARSessionRoot);
|
|
611
|
+
console.warn("WebAR: No ARSessionRoot found, creating one automatically on the WebXR object");
|
|
612
|
+
}
|
|
607
613
|
|
|
608
614
|
this.previousBackground = context.scene.background;
|
|
609
615
|
this.previousEnvironment = context.scene.environment;
|