@needle-tools/engine 3.30.0 → 3.31.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.
@@ -1,5 +1,5 @@
1
- import { getParam, resolveUrl } from "../engine/engine_utils.js";
2
- import { SerializationContext, TypeSerializer } from "./engine_serialization_core.js";
1
+ import { deepClone, getParam, resolveUrl } from "../engine/engine_utils.js";
2
+ import { SerializationContext, TypeSerializer, assign } from "./engine_serialization_core.js";
3
3
  import { Context } from "./engine_setup.js";
4
4
  import { Group, Object3D, Texture, TextureLoader } from "three";
5
5
  import { processNewScripts } from "./engine_mainloop_utils.js";
@@ -7,7 +7,7 @@ import { registerPrefabProvider, syncInstantiate } from "./engine_networking_ins
7
7
  import { download } from "./engine_web_api.js";
8
8
  import { getLoader } from "./engine_gltf.js";
9
9
  import type { IComponent, IGameObject, SourceIdentifier } from "./engine_types.js";
10
- import { destroy, instantiate, InstantiateOptions, isDestroyed } from "./engine_gameobject.js";
10
+ import { destroy, IInstantiateOptions, instantiate, InstantiateOptions, isDestroyed } from "./engine_gameobject.js";
11
11
 
12
12
  const debug = getParam("debugaddressables");
13
13
 
@@ -245,12 +245,12 @@ export class AssetReference {
245
245
  }
246
246
 
247
247
  /** loads and returns a new instance of `asset` */
248
- async instantiate(parent?: Object3D | InstantiateOptions) {
248
+ async instantiate(parent?: Object3D | IInstantiateOptions) {
249
249
  return this.onInstantiate(parent, false);
250
250
  }
251
251
 
252
252
  /** loads and returns a new instance of `asset` - this call is networked so an instance will be created on all connected users */
253
- async instantiateSynced(parent?: Object3D | InstantiateOptions, saveOnServer: boolean = true) {
253
+ async instantiateSynced(parent?: Object3D | IInstantiateOptions, saveOnServer: boolean = true) {
254
254
  return this.onInstantiate(parent, true, saveOnServer);
255
255
  }
256
256
 
@@ -272,32 +272,30 @@ export class AssetReference {
272
272
  }
273
273
  }
274
274
 
275
- private async onInstantiate(parent?: Object3D | InstantiateOptions, networked: boolean = false, saveOnServer?: boolean) {
275
+ private async onInstantiate(opts?: Object3D | IInstantiateOptions, networked: boolean = false, saveOnServer?: boolean) {
276
276
  const context = Context.Current;
277
+
278
+ // clone the instantiate options immediately
279
+ // in case the user is not awaiting this call and already modifying the options
280
+ const options = new InstantiateOptions();
281
+ if (opts instanceof Object3D) {
282
+ options.parent = opts;
283
+ }
284
+ else if (opts) {
285
+ options.cloneAssign(opts);
286
+ }
287
+ if (!options.parent) options.parent = context.scene;
288
+
289
+ // ensure the asset is loaded
277
290
  if (this.mustLoad) {
278
291
  await this.loadAssetAsync();
279
292
  }
280
293
  if (debug)
281
- console.log("Instantiate", this.uri, "parent:", parent);
294
+ console.log("Instantiate", this.uri, "parent:", opts);
282
295
 
283
296
  if (this.asset) {
284
297
  if (debug) console.log("Add to scene", this.asset);
285
298
 
286
- let options = parent instanceof InstantiateOptions ? parent : null;
287
- if (!options) {
288
- options = new InstantiateOptions();
289
- }
290
-
291
- if (typeof parent === "object") {
292
- if (parent instanceof Object3D) {
293
- options.parent = parent;
294
- }
295
- else {
296
- Object.assign(options, parent);
297
- }
298
- }
299
- if (!options.parent) options.parent = context.scene;
300
-
301
299
  let count = AssetReference.currentlyInstantiating.get(this.uri);
302
300
  // allow up to 10000 instantiations of the same prefab in the same frame
303
301
  if (count !== undefined && count >= 10000) {
@@ -28,21 +28,50 @@ export enum HideFlags {
28
28
  HideAndDontSave = DontSave | NotEditable | HideInHierarchy, // 0x0000003D
29
29
  }
30
30
 
31
+ export type IInstantiateOptions = {
32
+ idProvider?: UIDProvider;
33
+ //** parent guid or object */
34
+ parent?: string | Object3D;
35
+ position?: Vector3;
36
+ /** for duplicatable parenting */
37
+ keepWorldPosition?: boolean;
38
+ rotation?: Quaternion;
39
+ scale?: Vector3;
40
+ /** if the instantiated object should be visible */
41
+ visible?: boolean;
42
+ context?: Context;
43
+ }
31
44
 
32
- export class InstantiateOptions {
45
+ export class InstantiateOptions implements IInstantiateOptions {
33
46
  idProvider?: UIDProvider | undefined;
34
-
35
- //** parent guid */
36
47
  parent?: string | undefined | Object3D;
37
- /** for duplicatable parenting */
38
48
  keepWorldPosition?: boolean
39
49
  position?: Vector3 | undefined;
40
50
  rotation?: Quaternion | undefined;
41
51
  scale?: Vector3 | undefined;
42
-
43
52
  visible?: boolean | undefined;
44
-
45
53
  context?: Context | undefined;
54
+
55
+ clone(){
56
+ const clone = new InstantiateOptions();
57
+ clone.idProvider = this.idProvider;
58
+ clone.parent = this.parent;
59
+ clone.keepWorldPosition = this.keepWorldPosition;
60
+ clone.position = this.position?.clone();
61
+ clone.rotation = this.rotation?.clone();
62
+ clone.scale = this.scale?.clone();
63
+ return clone;
64
+ }
65
+
66
+ /** Copy fields from another object, clone field references */
67
+ cloneAssign(other: InstantiateOptions | IInstantiateOptions){
68
+ this.idProvider = other.idProvider;
69
+ this.parent = other.parent;
70
+ this.keepWorldPosition = other.keepWorldPosition;
71
+ this.position = other.position?.clone();
72
+ this.rotation = other.rotation?.clone();
73
+ this.scale = other.scale?.clone();
74
+ }
46
75
  }
47
76
 
48
77
 
@@ -237,7 +266,7 @@ declare class NewGameObjectReferenceInfo {
237
266
  clone: Object3D;
238
267
  }
239
268
 
240
- export function instantiate(instance: GameObject | Object3D | null, opts: InstantiateOptions | null = null): GameObject | null {
269
+ export function instantiate(instance: GameObject | Object3D | null, opts: IInstantiateOptions | null = null): GameObject | null {
241
270
  if (instance === null) return null;
242
271
 
243
272
  let options: InstantiateOptions | null = null;
@@ -256,6 +285,7 @@ export function instantiate(instance: GameObject | Object3D | null, opts: Instan
256
285
  // }
257
286
  }
258
287
  }
288
+ console.log(options?.position)
259
289
 
260
290
  let context = Context.Current;
261
291
  if (options?.context) context = options.context;
@@ -311,7 +341,7 @@ export function instantiate(instance: GameObject | Object3D | null, opts: Instan
311
341
 
312
342
 
313
343
  function internalInstantiate(
314
- context: Context, instance: GameObject | Object3D, opts: InstantiateOptions | null,
344
+ context: Context, instance: GameObject | Object3D, opts: IInstantiateOptions | InstantiateOptions | null,
315
345
  componentsList: Array<Component>,
316
346
  newGameObjectsMap: { [key: string]: NewGameObjectReferenceInfo },
317
347
  skinnedMeshesMap: { [key: string]: NewGameObjectReferenceInfo }
@@ -11,7 +11,7 @@ import { v5 } from 'uuid';
11
11
  import type { UIDProvider } from "./engine_types.js";
12
12
  import type { IModel } from "./engine_networking_types.js";
13
13
  import { SendQueue } from "./engine_networking_types.js";
14
- import { destroy, findByGuid, instantiate } from "./engine_gameobject.js";
14
+ import { IInstantiateOptions, destroy, findByGuid, instantiate } from "./engine_gameobject.js";
15
15
  import { Object3D } from "three";
16
16
  import { InstantiateOptions } from "./engine_gameobject.js";
17
17
  import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry.js";
@@ -182,7 +182,7 @@ class NewInstanceModel implements IModel {
182
182
  }
183
183
  }
184
184
 
185
- export function syncInstantiate(object: GameObject | Object3D, opts: InstantiateOptions, hostData?: HostData, save?: boolean): GameObject | null {
185
+ export function syncInstantiate(object: GameObject | Object3D, opts: IInstantiateOptions, hostData?: HostData, save?: boolean): GameObject | null {
186
186
 
187
187
  const obj: GameObject = object as GameObject;
188
188
 
@@ -285,7 +285,7 @@ export function beginListenInstantiate(context: Context) {
285
285
 
286
286
  }
287
287
 
288
- function instantiateSeeded(obj: GameObject, opts: InstantiateOptions | null): { instance: GameObject | null, seed: number } {
288
+ function instantiateSeeded(obj: GameObject, opts: IInstantiateOptions | null): { instance: GameObject | null, seed: number } {
289
289
  const seed = generateSeed();
290
290
  const options = opts ?? new InstantiateOptions();
291
291
  options.idProvider = new InstantiateIdProvider(seed);
@@ -440,9 +440,9 @@ export function unwatchWrite(vec: Vector, cb: Function) {
440
440
  /** Is MacOS or Windows (and not hololens) */
441
441
  export function isDesktop() {
442
442
  const ua = window.navigator.userAgent;
443
- const standalone = /Windows|MacOS/.test(ua);
443
+ const standalone = /Windows|MacOS|Mac OS/.test(ua);
444
444
  const isHololens = /Windows NT/.test(ua) && /Edg/.test(ua) && !/Win64/.test(ua);
445
- return standalone && !isHololens;
445
+ return standalone && !isHololens && !isiOS();
446
446
  }
447
447
 
448
448
  export function isMobileDevice() {
@@ -6,7 +6,7 @@ import * as main from "../engine/engine_mainloop_utils.js";
6
6
  import { syncDestroy, syncInstantiate } from "../engine/engine_networking_instantiate.js";
7
7
  import type { ConstructorConcrete, SourceIdentifier, IComponent, IGameObject, Constructor, GuidsMap, Collision, ICollider } from "../engine/engine_types.js";
8
8
  import { addNewComponent, destroyComponentInstance, findObjectOfType, findObjectsOfType, getComponent, getComponentInChildren, getComponentInParent, getComponents, getComponentsInChildren, getComponentsInParent, getOrAddComponent, moveComponentInstance, removeComponent } from "../engine/engine_components.js";
9
- import { findByGuid, destroy, InstantiateOptions, instantiate, HideFlags, foreachComponent, markAsInstancedRendered, isActiveInHierarchy, isActiveSelf, isUsingInstancing, setActive, isDestroyed } from "../engine/engine_gameobject.js";
9
+ import { findByGuid, destroy, InstantiateOptions, instantiate, HideFlags, foreachComponent, markAsInstancedRendered, isActiveInHierarchy, isActiveSelf, isUsingInstancing, setActive, isDestroyed, IInstantiateOptions } from "../engine/engine_gameobject.js";
10
10
 
11
11
  import { Euler, Object3D, Quaternion, Scene, Vector3 } from "three";
12
12
  import { showBalloonWarning, isDevEnvironment } from "../engine/debug/index.js";
@@ -72,7 +72,7 @@ export abstract class GameObject extends Object3D implements Object3D, IGameObje
72
72
  * @param instance object to instantiate
73
73
  * @param opts options for the instantiation
74
74
  */
75
- public static instantiateSynced(instance: GameObject | Object3D | null, opts: InstantiateOptions): GameObject | null {
75
+ public static instantiateSynced(instance: GameObject | Object3D | null, opts: IInstantiateOptions): GameObject | null {
76
76
  if (!instance) return null;
77
77
  return syncInstantiate(instance as any, opts) as GameObject | null;
78
78
  }
@@ -81,7 +81,7 @@ export abstract class GameObject extends Object3D implements Object3D, IGameObje
81
81
  * @param instance object to instantiate
82
82
  * @param opts options for the instantiation (e.g. with what parent, position, etc.)
83
83
  */
84
- public static instantiate(instance: GameObject | Object3D | null, opts: InstantiateOptions | null = null): GameObject | null {
84
+ public static instantiate(instance: GameObject | Object3D | null, opts: IInstantiateOptions | null = null): GameObject | null {
85
85
  return instantiate(instance, opts) as GameObject | null;
86
86
  }
87
87