@@ -57,6 +57,8 @@
|
|
57
57
|
}
|
58
58
|
if (debug) {
|
59
59
|
const outputFilePath = path.resolve(projectDir, 'node_modules/.vite/needle.alias.log');
|
60
|
+
const outputDirectory = path.dirname(outputFilePath);
|
61
|
+
if (!existsSync(outputDirectory)) mkdirSync(outputDirectory, { recursive: true });
|
60
62
|
outputDebugFile = createWriteStream(outputFilePath, { flags: "a" });
|
61
63
|
const timestamp = new Date().toISOString();
|
62
64
|
outputDebugFile.write("\n\n\n--------------------------\n");
|
@@ -68,7 +70,7 @@
|
|
68
70
|
const aliasPlugin = {
|
69
71
|
name: "needle-alias",
|
70
72
|
config(config) {
|
71
|
-
if (debug)
|
73
|
+
if (debug) console.log('[needle-alias] ProjectDirectory: ' + projectDir);
|
72
74
|
if (!config.resolve) config.resolve = {};
|
73
75
|
if (!config.resolve.alias) config.resolve.alias = {};
|
74
76
|
const aliasDict = config.resolve.alias;
|
@@ -97,6 +99,7 @@
|
|
97
99
|
let lastImporter = "";
|
98
100
|
/** This plugin logs all imports. This helps to find cases where incorrect folders are found/resolved. */
|
99
101
|
|
102
|
+
/** @type {import("vite").Plugin} */
|
100
103
|
const debuggingPlugin = {
|
101
104
|
name: "needle:alias-debug",
|
102
105
|
// needs to run before regular resolver
|
@@ -115,9 +118,9 @@
|
|
115
118
|
// verbose logging for all imports
|
116
119
|
if (lastImporter !== importer) {
|
117
120
|
lastImporter = importer;
|
118
|
-
log(
|
121
|
+
log(`[needle-alias] Resolving: ${importer} (file${options?.ssr ? ", SSR" : ""})`);
|
119
122
|
}
|
120
|
-
log(
|
123
|
+
log(`[needle-alias] → ${id}`);
|
121
124
|
return;
|
122
125
|
},
|
123
126
|
}
|
@@ -164,6 +164,11 @@
|
|
164
164
|
return this._url;
|
165
165
|
}
|
166
166
|
|
167
|
+
/** The name of the assigned url. This name is deduced from the url and might not reflect the actual name of the asset */
|
168
|
+
get urlName(): string {
|
169
|
+
return this._urlName;
|
170
|
+
};
|
171
|
+
|
167
172
|
/**
|
168
173
|
* @returns true if the uri is a valid URL (http, https, blob)
|
169
174
|
*/
|
@@ -180,6 +185,7 @@
|
|
180
185
|
private _asset: any;
|
181
186
|
private _glbRoot?: Object3D | null;
|
182
187
|
private _url: string;
|
188
|
+
private _urlName: string;
|
183
189
|
private _progressListeners: ProgressCallback[] = [];
|
184
190
|
|
185
191
|
private _hash?: string;
|
@@ -191,12 +197,27 @@
|
|
191
197
|
/** @internal */
|
192
198
|
constructor(uri: string, hash?: string, asset: any = null) {
|
193
199
|
this._url = uri;
|
200
|
+
|
201
|
+
const lastUriPart = uri.lastIndexOf("/");
|
202
|
+
if (lastUriPart >= 0) {
|
203
|
+
this._urlName = uri.substring(lastUriPart + 1);
|
204
|
+
// remove file extension
|
205
|
+
const lastDot = this._urlName.lastIndexOf(".");
|
206
|
+
if (lastDot >= 0) {
|
207
|
+
this._urlName = this._urlName.substring(0, lastDot);
|
208
|
+
}
|
209
|
+
}
|
210
|
+
else {
|
211
|
+
this._urlName = uri;
|
212
|
+
}
|
213
|
+
|
194
214
|
this._hash = hash;
|
195
215
|
if (uri.includes("?v="))
|
196
216
|
this._hashedUri = uri;
|
197
217
|
else
|
198
218
|
this._hashedUri = hash ? uri + "?v=" + hash : uri;
|
199
219
|
if (asset !== null) this.asset = asset;
|
220
|
+
|
200
221
|
registerPrefabProvider(this._url, this.onResolvePrefab.bind(this));
|
201
222
|
}
|
202
223
|
|
@@ -255,7 +255,26 @@
|
|
255
255
|
/** Adds an event listener for the specified event type. The callback will be called when the event is triggered.
|
256
256
|
* @param type The event type to listen for
|
257
257
|
* @param callback The callback to call when the event is triggered
|
258
|
-
* @param options The options for adding the event listener
|
258
|
+
* @param options The options for adding the event listener.
|
259
|
+
* @example Basic usage:
|
260
|
+
* ```ts
|
261
|
+
* input.addEventListener("pointerdown", (evt) => {
|
262
|
+
* console.log("Pointer down", evt.pointerId, evt.pointerType);
|
263
|
+
* });
|
264
|
+
* ```
|
265
|
+
* @example Adding a listener that is called after all other listeners
|
266
|
+
* By using a higher value for the queue the listener will be called after other listeners (default queue is 0).
|
267
|
+
* ```ts
|
268
|
+
* input.addEventListener("pointerdown", (evt) => {
|
269
|
+
* console.log("Pointer down", evt.pointerId, evt.pointerType);
|
270
|
+
* }, { queue: 10 });
|
271
|
+
* ```
|
272
|
+
* @example Adding a listener that is only called once
|
273
|
+
* ```ts
|
274
|
+
* input.addEventListener("pointerdown", (evt) => {
|
275
|
+
* console.log("Pointer down", evt.pointerId, evt.pointerType);
|
276
|
+
* }, { once: true });
|
277
|
+
* ```
|
259
278
|
*/
|
260
279
|
addEventListener(type: PointerEventNames, callback: PointerEventListener, options?: EventListenerOptions);
|
261
280
|
addEventListener(type: KeyboardEventNames, callback: KeyboardEventListener, options?: EventListenerOptions);
|
@@ -59,6 +59,7 @@
|
|
59
59
|
return ctx.scene.getComponent(EventSystem);
|
60
60
|
}
|
61
61
|
|
62
|
+
/** Get the currently active event system */
|
62
63
|
static get instance(): EventSystem | null {
|
63
64
|
return this.get(Context.Current);
|
64
65
|
}
|
@@ -75,7 +76,10 @@
|
|
75
76
|
}
|
76
77
|
}
|
77
78
|
|
78
|
-
get hasActiveUI() {
|
79
|
+
get hasActiveUI() {
|
80
|
+
return this.currentActiveMeshUIComponents.length > 0;
|
81
|
+
}
|
82
|
+
|
79
83
|
get isHoveringObjects() { return this.hoveredByID.size > 0; }
|
80
84
|
|
81
85
|
awake(): void {
|
@@ -424,7 +428,6 @@
|
|
424
428
|
const res = UIRaycastUtils.isInteractable(actualGo, this.out);
|
425
429
|
if (!res) return false;
|
426
430
|
canvasGroup = this.out.canvasGroup ?? null;
|
427
|
-
|
428
431
|
const handled = this.handleMeshUIIntersection(object, pressedOrClicked);
|
429
432
|
if (!clicked && handled) {
|
430
433
|
// return true;
|
@@ -753,7 +756,6 @@
|
|
753
756
|
}
|
754
757
|
|
755
758
|
private resetMeshUIStates() {
|
756
|
-
|
757
759
|
if (this.context.input.getPointerPressedCount() > 0) {
|
758
760
|
MeshUIHelper.resetLastSelected();
|
759
761
|
}
|
@@ -816,7 +818,7 @@
|
|
816
818
|
let foundBlock: Object3D | null = null;
|
817
819
|
|
818
820
|
if (intersect) {
|
819
|
-
foundBlock = this.
|
821
|
+
foundBlock = this.findBlockOrTextInParent(intersect);
|
820
822
|
// console.log(intersect, "-- found block:", foundBlock)
|
821
823
|
if (foundBlock && foundBlock !== this.lastSelected) {
|
822
824
|
const interactable = foundBlock["interactable"];
|
@@ -840,13 +842,13 @@
|
|
840
842
|
this.needsUpdate = true;
|
841
843
|
}
|
842
844
|
|
843
|
-
static
|
845
|
+
static findBlockOrTextInParent(elem: any): Object3D | null {
|
844
846
|
if (!elem) return null;
|
845
|
-
if (elem.isBlock) {
|
847
|
+
if (elem.isBlock || (elem.isText)) {
|
846
848
|
// @TODO : Replace states managements
|
847
849
|
// if (Object.keys(elem.states).length > 0)
|
848
850
|
return elem;
|
849
851
|
}
|
850
|
-
return this.
|
852
|
+
return this.findBlockOrTextInParent(elem.parent);
|
851
853
|
}
|
852
854
|
}
|
@@ -46,6 +46,10 @@
|
|
46
46
|
index: number;
|
47
47
|
}
|
48
48
|
|
49
|
+
export type LoadSceneProgressEvent = LoadSceneEvent & {
|
50
|
+
progress: number,
|
51
|
+
}
|
52
|
+
|
49
53
|
/**
|
50
54
|
* The ISceneEventListener is called by the {@link SceneSwitcher} when a scene is loaded or unloaded.
|
51
55
|
* It must be added to the root object of your scene (that is being loaded) or on the same object as the SceneSwitcher
|
@@ -226,6 +230,15 @@
|
|
226
230
|
get currentlyLoadedScene() { return this._currentScene; }
|
227
231
|
|
228
232
|
/**
|
233
|
+
* Called when a scene starts loading
|
234
|
+
*/
|
235
|
+
@serializable(EventList)
|
236
|
+
sceneLoadingStart: EventList<LoadSceneEvent> = new EventList();
|
237
|
+
|
238
|
+
@serializable(EventList)
|
239
|
+
sceneLoadingProgress: EventList<ProgressEvent> = new EventList();
|
240
|
+
|
241
|
+
/**
|
229
242
|
* The sceneLoaded event is called when a scene/glTF is loaded and added to the scene
|
230
243
|
*/
|
231
244
|
@serializable(EventList)
|
@@ -281,7 +294,7 @@
|
|
281
294
|
this._preloadScheduler.maxLoadAhead = this.preloadNext;
|
282
295
|
this._preloadScheduler.maxLoadBehind = this.preloadPrevious;
|
283
296
|
this._preloadScheduler.maxConcurrent = this.preloadConcurrent;
|
284
|
-
this._preloadScheduler.begin();
|
297
|
+
this._preloadScheduler.begin(2000);
|
285
298
|
|
286
299
|
// Begin loading the loading scene
|
287
300
|
if (this.autoLoadFirstScene && this._currentIndex === -1 && !await this.tryLoadFromQueryParam()) {
|
@@ -602,11 +615,13 @@
|
|
602
615
|
|
603
616
|
const loadStartEvt = new CustomEvent<LoadSceneEvent>("loadscene-start", { detail: { scene: scene, switcher: this, index: index } })
|
604
617
|
this.dispatchEvent(loadStartEvt);
|
618
|
+
this.sceneLoadingStart?.invoke(loadStartEvt.detail);
|
605
619
|
await this.onStartLoading();
|
606
620
|
// start loading and wait for the scene to be loaded
|
607
621
|
await scene.loadAssetAsync((_, prog) => {
|
608
622
|
this._currentLoadingProgress = prog;
|
609
623
|
this.dispatchEvent(prog);
|
624
|
+
this.sceneLoadingProgress?.invoke(prog);
|
610
625
|
}).catch(console.error);
|
611
626
|
await this.onEndLoading();
|
612
627
|
const finishedEvt = new CustomEvent<LoadSceneEvent>("loadscene-finished", { detail: { scene: scene, switcher: this, index: index } });
|
@@ -859,26 +874,30 @@
|
|
859
874
|
this.maxConcurrent = maxConcurrent;
|
860
875
|
}
|
861
876
|
|
862
|
-
begin() {
|
877
|
+
begin(delay: number) {
|
863
878
|
if (this._isRunning) return;
|
864
|
-
if (debug) console.log("Preload begin")
|
879
|
+
if (debug) console.log("Preload begin", { delay })
|
865
880
|
this._isRunning = true;
|
866
|
-
let lastRoom: number = -
|
881
|
+
let lastRoom: number = -10;
|
867
882
|
let searchDistance: number;
|
868
883
|
let searchCall: number;
|
869
884
|
const array = this._switcher.scenes;
|
885
|
+
const startTime = Date.now() + delay;
|
870
886
|
const interval = setInterval(() => {
|
871
887
|
if (this.allLoaded()) {
|
872
888
|
if (debug)
|
873
|
-
console.log("All scenes loaded");
|
889
|
+
console.log("All scenes (pre-)loaded");
|
874
890
|
this.stop();
|
875
891
|
}
|
876
892
|
if (!this._isRunning) {
|
877
893
|
clearInterval(interval);
|
878
894
|
return;
|
879
895
|
}
|
896
|
+
|
897
|
+
if (Date.now() < startTime) return;
|
898
|
+
|
880
899
|
if (this.canLoadNewScene() === false) return;
|
881
|
-
if (lastRoom !== this._switcher.currentIndex) {
|
900
|
+
if (lastRoom === -10 || lastRoom !== this._switcher.currentIndex) {
|
882
901
|
lastRoom = this._switcher.currentIndex;
|
883
902
|
searchCall = 0;
|
884
903
|
searchDistance = 0;
|
@@ -892,8 +911,11 @@
|
|
892
911
|
if (roomIndex < 0) return;
|
893
912
|
// if (roomIndex < 0) roomIndex = array.length + roomIndex;
|
894
913
|
if (roomIndex < 0 || roomIndex >= array.length) return;
|
895
|
-
|
896
|
-
|
914
|
+
if (!this._loadTasks.some(t => t.index === roomIndex)) {
|
915
|
+
const scene = array[roomIndex];
|
916
|
+
if (debug) console.log("Preload scene", { roomIndex, searchForward, lastRoom, currentIndex: this._switcher.currentIndex, tasks: this._loadTasks.length }, scene?.url);
|
917
|
+
new LoadTask(roomIndex, scene, this._loadTasks);
|
918
|
+
}
|
897
919
|
}, 200);
|
898
920
|
}
|