@@ -56,11 +56,11 @@
|
|
56
56
|
/** Snap dragged objects to a XYZ grid – 0 means: no snapping. */
|
57
57
|
@serializable()
|
58
58
|
public snapGridResolution: number = 0.0;
|
59
|
-
|
59
|
+
|
60
60
|
/** Keep the original rotation of the dragged object. */
|
61
61
|
@serializable()
|
62
62
|
public keepRotation: boolean = true;
|
63
|
-
|
63
|
+
|
64
64
|
/** How and where the object is dragged along while dragging in XR. */
|
65
65
|
@serializable()
|
66
66
|
public xrDragMode: DragMode = DragMode.Attached;
|
@@ -82,7 +82,7 @@
|
|
82
82
|
|
83
83
|
public static get HasAnySelected(): boolean { return this._active > 0; }
|
84
84
|
private static _active: number = 0;
|
85
|
-
|
85
|
+
|
86
86
|
/** The object to be dragged – we pass this to handlers when they are created */
|
87
87
|
private targetObject: GameObject | null = null;
|
88
88
|
private orbit: OrbitControls | null = null;
|
@@ -167,10 +167,10 @@
|
|
167
167
|
}
|
168
168
|
|
169
169
|
DragControls._active += 1;
|
170
|
-
|
170
|
+
|
171
171
|
const newDragHandler = new DragPointerHandler(this, this.targetObject || this.gameObject);
|
172
172
|
this._dragHandlers.set(args.event.space, newDragHandler);
|
173
|
-
|
173
|
+
|
174
174
|
// We need to turn off OrbitControls immediately, otherwise they still get data for a short moment
|
175
175
|
// and they don't properly handle being disabled while already processing data (smoothing happens when enabling again)
|
176
176
|
if (this.orbit) this.orbit.enabled = false;
|
@@ -197,8 +197,8 @@
|
|
197
197
|
|
198
198
|
onPointerUp(args: PointerEventData) {
|
199
199
|
|
200
|
-
if(debug) Gizmos.DrawLabel(args.point ?? this.gameObject.worldPosition, "POINTERUP:" + args.pointerId + ", " + args.button, .03, 3);
|
201
|
-
|
200
|
+
if (debug) Gizmos.DrawLabel(args.point ?? this.gameObject.worldPosition, "POINTERUP:" + args.pointerId + ", " + args.button, .03, 3);
|
201
|
+
|
202
202
|
if (!this.allowEdit(this.gameObject)) return;
|
203
203
|
if (args.button !== 0) return;
|
204
204
|
this._potentialDragStartEvt = null;
|
@@ -214,10 +214,10 @@
|
|
214
214
|
if (handler) {
|
215
215
|
if (DragControls._active > 0)
|
216
216
|
DragControls._active -= 1;
|
217
|
-
|
217
|
+
|
218
218
|
if (handler.onDragEnd) handler.onDragEnd(args);
|
219
219
|
this._dragHandlers.delete(args.event.space);
|
220
|
-
|
220
|
+
|
221
221
|
if (this._dragHandlers.size === 0) {
|
222
222
|
this.onLastDragEnd(args);
|
223
223
|
}
|
@@ -254,7 +254,7 @@
|
|
254
254
|
|
255
255
|
for (const handler of this._dragHandlers.values())
|
256
256
|
if (handler.onDragUpdate) handler.onDragUpdate(this._dragHandlers.size);
|
257
|
-
|
257
|
+
|
258
258
|
if (this._dragHelper && this._dragHelper.hasSelected)
|
259
259
|
this.onAnyDragUpdate();
|
260
260
|
}
|
@@ -312,7 +312,7 @@
|
|
312
312
|
}
|
313
313
|
|
314
314
|
const object = this.targetObject || this.gameObject;
|
315
|
-
|
315
|
+
|
316
316
|
InstancingUtil.markDirty(object);
|
317
317
|
}
|
318
318
|
|
@@ -347,7 +347,7 @@
|
|
347
347
|
getTotalMovement?(): Vector3;
|
348
348
|
/** Target object can change mid-flight (e.g. in Duplicatable), handlers should react properly to that */
|
349
349
|
setTargetObject(obj: Object3D | null): void;
|
350
|
-
|
350
|
+
|
351
351
|
/** Prewarms the drag – can already move internal points around here but should not move the object itself */
|
352
352
|
collectMovementInfo?(): void;
|
353
353
|
onDragStart?(args: PointerEventData): void;
|
@@ -382,7 +382,7 @@
|
|
382
382
|
|
383
383
|
this._followObject = new Object3D() as GameObject;
|
384
384
|
this._manipulatorObject = new Object3D() as GameObject;
|
385
|
-
|
385
|
+
|
386
386
|
this.context.scene.add(this._manipulatorObject);
|
387
387
|
|
388
388
|
const rig = NeedleXRSession.active?.rig?.gameObject;
|
@@ -401,7 +401,7 @@
|
|
401
401
|
rig.worldToLocal(this._tempVec2);
|
402
402
|
}
|
403
403
|
this._initialDistance = this._tempVec1.distanceTo(this._tempVec2);
|
404
|
-
|
404
|
+
|
405
405
|
if (this._initialDistance < 0.02) {
|
406
406
|
if (debug) {
|
407
407
|
console.log("Finding alternative drag attachment points since initial distance is too low: " + this._initialDistance.toFixed(2));
|
@@ -464,7 +464,7 @@
|
|
464
464
|
console.error("onDragEnd called on MultiTouchDragHandler without valid handlers. This is likely a bug.");
|
465
465
|
return;
|
466
466
|
}
|
467
|
-
|
467
|
+
|
468
468
|
// we want to initialize the drag points for these handlers again.
|
469
469
|
// one of them will be removed, but we don't know here which one
|
470
470
|
this.handlerA.recenter();
|
@@ -493,7 +493,7 @@
|
|
493
493
|
console.error("alignManipulator called on MultiTouchDragHandler without valid handlers. This is likely a bug.", this);
|
494
494
|
return;
|
495
495
|
}
|
496
|
-
|
496
|
+
|
497
497
|
if (!this.handlerA.followObject || !this.handlerB.followObject) {
|
498
498
|
console.error("alignManipulator called on MultiTouchDragHandler without valid follow objects. This is likely a bug.", this.handlerA, this.handlerB);
|
499
499
|
return;
|
@@ -520,7 +520,7 @@
|
|
520
520
|
this._manipulatorObject.updateMatrixWorld(true);
|
521
521
|
|
522
522
|
if (debug) {
|
523
|
-
Gizmos.DrawLabel(this._tempVec3.clone().add(new Vector3(0,0.2,0)), "A:B " + dist.toFixed(2), 0.03);
|
523
|
+
Gizmos.DrawLabel(this._tempVec3.clone().add(new Vector3(0, 0.2, 0)), "A:B " + dist.toFixed(2), 0.03);
|
524
524
|
Gizmos.DrawLine(this._tempVec1, this._tempVec2, 0x00ff00, 0, false);
|
525
525
|
|
526
526
|
// const wp = this._manipulatorObject.worldPosition;
|
@@ -585,7 +585,7 @@
|
|
585
585
|
const rot = draggedObject.worldQuaternion;
|
586
586
|
rot.slerp(targetObject.worldQuaternion, t);
|
587
587
|
draggedObject.worldQuaternion = rot;
|
588
|
-
|
588
|
+
|
589
589
|
const scl = draggedObject.worldScale;
|
590
590
|
scl.lerp(targetObject.worldScale, t);
|
591
591
|
draggedObject.worldScale = scl;
|
@@ -614,7 +614,7 @@
|
|
614
614
|
private _lastRig: IGameObject | undefined = undefined;
|
615
615
|
|
616
616
|
/** This object is placed at the pivot of the dragged object, and parented to the control space. */
|
617
|
-
private _followObject: GameObject;
|
617
|
+
private _followObject: GameObject;
|
618
618
|
private _totalMovement: Vector3 = new Vector3();
|
619
619
|
/** Motion along the pointer ray. On screens this doesn't change. In XR it can be used to determine how much
|
620
620
|
* effort someone is putting into moving an object closer or further away. */
|
@@ -663,7 +663,7 @@
|
|
663
663
|
|
664
664
|
this.gameObject.add(this._followObject);
|
665
665
|
this._followObject.matrixAutoUpdate = false;
|
666
|
-
|
666
|
+
|
667
667
|
this._followObject.position.set(0, 0, 0);
|
668
668
|
this._followObject.quaternion.set(0, 0, 0, 1);
|
669
669
|
this._followObject.scale.set(1, 1, 1);
|
@@ -690,20 +690,19 @@
|
|
690
690
|
this._totalMovementAlongRayDirection = 0;
|
691
691
|
this._lastDragPosRigSpace = undefined;
|
692
692
|
|
693
|
-
if (debug)
|
694
|
-
{
|
693
|
+
if (debug) {
|
695
694
|
Gizmos.DrawLine(hitPointWP, p.worldPosition, 0x00ff00, 0.5, false);
|
696
|
-
Gizmos.DrawLabel(p.worldPosition.add(new Vector3(0,0.1,0)), this._grabStartDistance.toFixed(2), 0.03, 0.5);
|
695
|
+
Gizmos.DrawLabel(p.worldPosition.add(new Vector3(0, 0.1, 0)), this._grabStartDistance.toFixed(2), 0.03, 0.5);
|
697
696
|
}
|
698
697
|
}
|
699
698
|
|
700
699
|
onDragStart(args: PointerEventData) {
|
701
|
-
|
700
|
+
|
702
701
|
args.event.space.add(this._followObject);
|
703
702
|
|
704
703
|
// prepare for drag, we will start dragging after an object has been dragged for a few centimeters
|
705
704
|
this._lastDragPosRigSpace = undefined;
|
706
|
-
|
705
|
+
|
707
706
|
if (args.point && args.normal) {
|
708
707
|
this._hitPointInLocalSpace.copy(args.point);
|
709
708
|
this.gameObject.worldToLocal(this._hitPointInLocalSpace);
|
@@ -741,7 +740,7 @@
|
|
741
740
|
|
742
741
|
switch (dragMode) {
|
743
742
|
case DragMode.XZPlane:
|
744
|
-
const up = new Vector3(0,1,0);
|
743
|
+
const up = new Vector3(0, 1, 0);
|
745
744
|
if (this.gameObject.parent) {
|
746
745
|
// TODO in this case _dragPlane should be in parent space, not world space,
|
747
746
|
// otherwise dragging the parent and this object at the same time doesn't keep the plane constrained
|
@@ -757,16 +756,11 @@
|
|
757
756
|
case DragMode.Attached:
|
758
757
|
this._dragPlane.setFromNormalAndCoplanarPoint(rayDirection, hitWP);
|
759
758
|
break;
|
759
|
+
case DragMode.DynamicViewAngle: // At start (when nothing is hit yet) the drag plane should be aligned to the view
|
760
|
+
this.setPlaneViewAligned(hitWP, true);
|
761
|
+
break;
|
760
762
|
case DragMode.SnapToSurfaces: // At start (when nothing is hit yet) the drag plane should be aligned to the view
|
761
|
-
|
762
|
-
const v0 = new Vector3(0, 1, 0);
|
763
|
-
const v1 = rayDirection;
|
764
|
-
const angle = v0.angleTo(v1);
|
765
|
-
const angleThreshold = 0.5;
|
766
|
-
if (angle > Math.PI / 2 + angleThreshold || angle < Math.PI / 2 - angleThreshold)
|
767
|
-
this._dragPlane.setFromNormalAndCoplanarPoint(new Vector3(0, 1, 0), hitWP);
|
768
|
-
else
|
769
|
-
this._dragPlane.setFromNormalAndCoplanarPoint(rayDirection, hitWP);
|
763
|
+
this.setPlaneViewAligned(hitWP, false);
|
770
764
|
break;
|
771
765
|
case DragMode.None:
|
772
766
|
break;
|
@@ -797,7 +791,7 @@
|
|
797
791
|
bbox.getCenter(bboxCenter);
|
798
792
|
const bboxSize = new Vector3();
|
799
793
|
bbox.getSize(bboxSize);
|
800
|
-
|
794
|
+
|
801
795
|
// attachment points for dragging
|
802
796
|
this._bottomCenter.copy(bboxCenter.clone().add(new Vector3(0, -bboxSize.y / 2, 0)));
|
803
797
|
this._backCenter.copy(bboxCenter.clone().add(new Vector3(0, 0, bboxSize.z / 2)));
|
@@ -917,10 +911,9 @@
|
|
917
911
|
currentDist = Math.max(0.0, factor);
|
918
912
|
currentDist = currentDist * currentDist * currentDist;
|
919
913
|
}
|
920
|
-
else if (this._grabStartDistance <= 0.5)
|
921
|
-
{
|
914
|
+
else if (this._grabStartDistance <= 0.5) {
|
922
915
|
// TODO there's still a frame delay between dragged objects and the hand models
|
923
|
-
lerpFactor = 3.0;
|
916
|
+
lerpFactor = 3.0;
|
924
917
|
}
|
925
918
|
|
926
919
|
// reset _followObject to its original position and rotation
|
@@ -935,6 +928,8 @@
|
|
935
928
|
this._followObject.position.multiplyScalar(currentDist);
|
936
929
|
this._followObject.updateMatrix();
|
937
930
|
|
931
|
+
const didHaveSurfaceHitPointLastFrame = this._hasLastSurfaceHitPoint;
|
932
|
+
this._hasLastSurfaceHitPoint = false;
|
938
933
|
const ray = new Ray(dragSourceWP, rayDirection);
|
939
934
|
let didHit = false;
|
940
935
|
|
@@ -964,6 +959,9 @@
|
|
964
959
|
|
965
960
|
if (hit.face) {
|
966
961
|
didHit = true;
|
962
|
+
this._hasLastSurfaceHitPoint = true;
|
963
|
+
this._lastSurfaceHitPoint.copy(hit.point);
|
964
|
+
|
967
965
|
const dragTimeThreshold = 0.15;
|
968
966
|
const dragTimeSatisfied = this._draggedOverObjectDuration >= dragTimeThreshold;
|
969
967
|
const dragDistance = 0.001;
|
@@ -972,7 +970,7 @@
|
|
972
970
|
// or if the surface normal changed
|
973
971
|
if ((dragTimeSatisfied || dragDistanceSatisfied) &&
|
974
972
|
(this._draggedOverObjectLastSetUp !== this._draggedOverObject
|
975
|
-
|| this._draggedOverObjectLastNormal.dot(hit.face.normal) < 0.999999
|
973
|
+
|| this._draggedOverObjectLastNormal.dot(hit.face.normal) < 0.999999
|
976
974
|
// if we're dragging on a flat surface with different levels (like the sandbox floor)
|
977
975
|
|| this.context.time.frame % 60 === 0
|
978
976
|
)
|
@@ -988,7 +986,7 @@
|
|
988
986
|
center.sub(size.multiplyScalar(0.5).multiply(hit.face.normal));
|
989
987
|
this._hitPointInLocalSpace.copy(center);
|
990
988
|
this._hitNormalInLocalSpace.copy(hit.face.normal);
|
991
|
-
|
989
|
+
|
992
990
|
// ensure plane is far enough up that we don't drag into the surface
|
993
991
|
// Which offset we use here depends on the face normal direction we hit
|
994
992
|
// If we hit the bottom, we want to use the top, and vice versa
|
@@ -1014,6 +1012,9 @@
|
|
1014
1012
|
}
|
1015
1013
|
}
|
1016
1014
|
}
|
1015
|
+
else if (didHaveSurfaceHitPointLastFrame) {
|
1016
|
+
this.setPlaneViewAligned(this.gameObject.worldPosition, false)
|
1017
|
+
}
|
1017
1018
|
}
|
1018
1019
|
|
1019
1020
|
// if(dragMode === DragMode.SnapToSurfaces){
|
@@ -1034,12 +1035,12 @@
|
|
1034
1035
|
|
1035
1036
|
const newWP = this._hitPointInLocalSpace.clone();
|
1036
1037
|
this._followObject.localToWorld(newWP);
|
1037
|
-
|
1038
|
+
|
1038
1039
|
if (debug) {
|
1039
1040
|
Gizmos.DrawLine(newWP, this._tempVec, 0x00ffff, 0, false);
|
1040
1041
|
}
|
1041
|
-
|
1042
|
-
this._followObject.worldPosition
|
1042
|
+
|
1043
|
+
this._followObject.worldPosition = this._tempVec.multiplyScalar(2).sub(newWP);
|
1043
1044
|
this._followObject.updateMatrix();
|
1044
1045
|
|
1045
1046
|
/*
|
@@ -1069,11 +1070,11 @@
|
|
1069
1070
|
this._followObject.worldQuaternion = this._followObjectStartWorldQuaternion;
|
1070
1071
|
this._followObject.updateMatrix();
|
1071
1072
|
}
|
1072
|
-
|
1073
|
+
|
1073
1074
|
// TODO refactor to a common place
|
1074
1075
|
// TODO should use unscaled time here // some test for lerp speed depending on distance
|
1075
1076
|
const t = Mathf.clamp01(this.context.time.deltaTime * lerpStrength * lerpFactor);// / (currentDist - 1 + 0.01));
|
1076
|
-
|
1077
|
+
|
1077
1078
|
const wp = draggedObject.worldPosition;
|
1078
1079
|
wp.lerp(this._followObject.worldPosition, t);
|
1079
1080
|
draggedObject.worldPosition = wp;
|
@@ -1083,8 +1084,7 @@
|
|
1083
1084
|
draggedObject.worldQuaternion = rot;
|
1084
1085
|
|
1085
1086
|
|
1086
|
-
if (debug)
|
1087
|
-
{
|
1087
|
+
if (debug) {
|
1088
1088
|
const hitPointWP = this._hitPointInLocalSpace.clone();
|
1089
1089
|
draggedObject.localToWorld(hitPointWP);
|
1090
1090
|
// draw grab attachment point and normal. They are in grabbed object space
|
@@ -1094,7 +1094,7 @@
|
|
1094
1094
|
Gizmos.DrawRay(hitPointWP, hitNormalWP, 0xff0000);
|
1095
1095
|
|
1096
1096
|
// debug info
|
1097
|
-
Gizmos.DrawLabel(wp.add(new Vector3(0, 0.25, 0)),
|
1097
|
+
Gizmos.DrawLabel(wp.add(new Vector3(0, 0.25, 0)),
|
1098
1098
|
`Distance: ${this._totalMovement.length().toFixed(2)}\n
|
1099
1099
|
Along Ray: ${this._totalMovementAlongRayDirection.toFixed(2)}\n
|
1100
1100
|
Session: ${!!NeedleXRSession.active}\n
|
@@ -1124,6 +1124,27 @@
|
|
1124
1124
|
this._followObject.destroy();
|
1125
1125
|
this._lastDragPosRigSpace = undefined;
|
1126
1126
|
}
|
1127
|
+
|
1128
|
+
|
1129
|
+
private _hasLastSurfaceHitPoint: boolean = false;
|
1130
|
+
private readonly _lastSurfaceHitPoint: Vector3 = new Vector3();
|
1131
|
+
|
1132
|
+
private setPlaneViewAligned(worldPoint: Vector3, useUpAngle: boolean) {
|
1133
|
+
if (!this._followObject.parent) {
|
1134
|
+
return false;
|
1135
|
+
}
|
1136
|
+
const viewDirection = (this._followObject.parent as IGameObject).worldForward;;
|
1137
|
+
const v0 = getTempVector(0, 1, 0);
|
1138
|
+
const v1 = viewDirection;
|
1139
|
+
const angle = v0.angleTo(v1);
|
1140
|
+
const angleThreshold = 0.5;
|
1141
|
+
if (useUpAngle && (angle > Math.PI / 2 + angleThreshold || angle < Math.PI / 2 - angleThreshold))
|
1142
|
+
this._dragPlane.setFromNormalAndCoplanarPoint(v0, worldPoint);
|
1143
|
+
else
|
1144
|
+
this._dragPlane.setFromNormalAndCoplanarPoint(viewDirection, worldPoint);
|
1145
|
+
return true;
|
1146
|
+
|
1147
|
+
}
|
1127
1148
|
}
|
1128
1149
|
|
1129
1150
|
/** Currently does _only_ provide visuals support for DragControls operations.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Object3D } from "three";
|
1
|
+
import { EquirectangularReflectionMapping, Object3D, Scene, Texture } from "three";
|
2
2
|
|
3
3
|
import { Addressables, AssetReference } from "../engine/engine_addressables.js";
|
4
4
|
import { registerObservableAttribute } from "../engine/engine_element_extras.js";
|
@@ -7,8 +7,10 @@
|
|
7
7
|
import { serializable } from "../engine/engine_serialization.js";
|
8
8
|
import { delay, getParam, setParamWithoutReload } from "../engine/engine_utils.js";
|
9
9
|
import { Behaviour, GameObject } from "./Component.js";
|
10
|
+
import { destroy } from "../engine/engine_gameobject.js";
|
10
11
|
|
11
12
|
const debug = getParam("debugsceneswitcher");
|
13
|
+
const experimental_clearSceneOnLoad = getParam("sceneswitcher:clearscene");
|
12
14
|
|
13
15
|
const ENGINE_ELEMENT_SCENE_ATTRIBUTE_NAME = "scene";
|
14
16
|
registerObservableAttribute(ENGINE_ELEMENT_SCENE_ATTRIBUTE_NAME);
|
@@ -103,58 +105,94 @@
|
|
103
105
|
*/
|
104
106
|
export class SceneSwitcher extends Behaviour {
|
105
107
|
|
106
|
-
/** When enabled the first scene will be loaded when the SceneSwitcher becomes active
|
108
|
+
/** When enabled the first scene will be loaded when the SceneSwitcher becomes active
|
109
|
+
* @default true
|
110
|
+
*/
|
107
111
|
@serializable()
|
108
112
|
autoLoadFirstScene: boolean = true;
|
109
113
|
|
110
114
|
/**
|
111
115
|
* The scenes that can be loaded by the SceneSwitcher.
|
116
|
+
* @default []
|
112
117
|
*/
|
113
118
|
@serializable(AssetReference)
|
114
119
|
scenes: AssetReference[] = [];
|
115
120
|
|
121
|
+
/**
|
122
|
+
* The scene that is displayed while a scene is loading.
|
123
|
+
* @default undefined
|
124
|
+
*/
|
116
125
|
@serializable(AssetReference)
|
117
126
|
loadingScene?: AssetReference;
|
118
127
|
|
119
|
-
/** the url parameter that is set/used to store the currently loaded scene in, set to "" to disable
|
128
|
+
/** the url parameter that is set/used to store the currently loaded scene in, set to "" to disable
|
129
|
+
* @default "scene"
|
130
|
+
*/
|
120
131
|
@serializable()
|
121
132
|
queryParameterName: string = "scene";
|
122
133
|
|
123
134
|
/**
|
124
135
|
* when enabled the scene name will be used as the query parameter (otherwise the scene index will be used)
|
125
136
|
* Needs `queryParameterName` set
|
126
|
-
*
|
137
|
+
* @default true
|
138
|
+
*/
|
127
139
|
@serializable()
|
128
140
|
useSceneName: boolean = true;
|
129
141
|
|
142
|
+
/**
|
143
|
+
* When enabled the current scene index will be clamped to the scenes array bounds.
|
144
|
+
* For example when the last scene is loaded and `clamp` is true then trying to load the `next()` scene will not change the scene.
|
145
|
+
* When `clamp` is false and the last scene is loaded then the first scene will be loaded instead.
|
146
|
+
* @default true
|
147
|
+
*/
|
130
148
|
@serializable()
|
131
149
|
clamp: boolean = true;
|
132
150
|
|
133
|
-
/** when enabled the new scene is pushed to the browser navigation history, only works with a valid query parameter set
|
151
|
+
/** when enabled the new scene is pushed to the browser navigation history, only works with a valid query parameter set
|
152
|
+
* @default true
|
153
|
+
*/
|
134
154
|
@serializable()
|
135
155
|
useHistory: boolean = true;
|
136
156
|
|
137
|
-
/** when enabled you can switch between scenes using keyboard left, right, A and D or number keys
|
157
|
+
/** when enabled you can switch between scenes using keyboard left, right, A and D or number keys
|
158
|
+
* @default true
|
159
|
+
*/
|
138
160
|
@serializable()
|
139
161
|
useKeyboard: boolean = true;
|
140
162
|
|
141
|
-
/** when enabled you can switch between scenes using swipe (mobile only)
|
163
|
+
/** when enabled you can switch between scenes using swipe (mobile only)
|
164
|
+
* @default true
|
165
|
+
*/
|
142
166
|
@serializable()
|
143
167
|
useSwipe: boolean = true;
|
144
168
|
|
145
|
-
/** when enabled will automatically apply the environment scene lights
|
169
|
+
/** when enabled will automatically apply the environment scene lights
|
170
|
+
* @default true
|
171
|
+
*/
|
146
172
|
@serializable()
|
147
173
|
useSceneLighting: boolean = true;
|
148
174
|
|
149
|
-
/**
|
175
|
+
/** When enabled will automatically apply the skybox from the loaded scene
|
176
|
+
* @default true
|
177
|
+
*/
|
150
178
|
@serializable()
|
179
|
+
useSceneBackground: boolean = true;
|
180
|
+
|
181
|
+
/** how many scenes after the currently active scene should be preloaded
|
182
|
+
* @default 1
|
183
|
+
*/
|
184
|
+
@serializable()
|
151
185
|
preloadNext: number = 1;
|
152
186
|
|
153
|
-
/** how many scenes before the currently active scene should be preloaded
|
187
|
+
/** how many scenes before the currently active scene should be preloaded
|
188
|
+
* @default 1
|
189
|
+
*/
|
154
190
|
@serializable()
|
155
191
|
preloadPrevious: number = 1;
|
156
192
|
|
157
|
-
/** how many scenes can be loaded in parallel
|
193
|
+
/** how many scenes can be loaded in parallel
|
194
|
+
* @default 2
|
195
|
+
*/
|
158
196
|
@serializable()
|
159
197
|
preloadConcurrent: number = 2;
|
160
198
|
|
@@ -516,9 +554,38 @@
|
|
516
554
|
if (this._currentIndex === index) {
|
517
555
|
if (debug) console.log("ADD", scene.uri);
|
518
556
|
this._currentScene = scene;
|
557
|
+
|
558
|
+
|
559
|
+
// Experimental: replace the whole content of the scene
|
560
|
+
if (experimental_clearSceneOnLoad) {
|
561
|
+
const camera = this.context.mainCameraComponent?.gameObject || this.context.mainCamera;
|
562
|
+
camera?.removeFromParent();
|
563
|
+
const self = this.gameObject.removeFromParent();
|
564
|
+
destroy(this.context.scene, true, true)
|
565
|
+
this.context.scene = new Scene();
|
566
|
+
this.context.scene.add(self);
|
567
|
+
if (camera) {
|
568
|
+
this.context.scene.add(camera);
|
569
|
+
}
|
570
|
+
}
|
571
|
+
|
519
572
|
GameObject.add(scene.asset, this.gameObject);
|
573
|
+
|
520
574
|
if (this.useSceneLighting)
|
521
575
|
this.context.sceneLighting.enable(scene);
|
576
|
+
// Set the background texture from the loaded scene
|
577
|
+
if (this.useSceneBackground) {
|
578
|
+
const skybox = this.context.lightmaps.tryGetSkybox(scene.url) as Texture;
|
579
|
+
if (skybox) {
|
580
|
+
skybox.mapping = EquirectangularReflectionMapping;
|
581
|
+
this.context.scene.background = skybox;
|
582
|
+
}
|
583
|
+
else if (debug) {
|
584
|
+
console.warn("SceneSwitcher: Can't find skybox for scene " + scene.url);
|
585
|
+
}
|
586
|
+
}
|
587
|
+
|
588
|
+
|
522
589
|
if (this.useHistory && index >= 0) {
|
523
590
|
// take the index as the query parameter value
|
524
591
|
let queryParameterValue = index.toString();
|