@needle-tools/engine 4.1.0-beta.6 → 4.1.0-beta.9

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.
Files changed (114) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/gltf-progressive.js +148 -150
  3. package/dist/gltf-progressive.light.js +148 -150
  4. package/dist/gltf-progressive.light.min.js +6 -6
  5. package/dist/gltf-progressive.light.umd.cjs +7 -7
  6. package/dist/gltf-progressive.min.js +6 -6
  7. package/dist/gltf-progressive.umd.cjs +7 -7
  8. package/dist/needle-engine.bundle.js +4782 -4769
  9. package/dist/needle-engine.bundle.light.js +4783 -4770
  10. package/dist/needle-engine.bundle.light.min.js +112 -112
  11. package/dist/needle-engine.bundle.light.umd.cjs +113 -113
  12. package/dist/needle-engine.bundle.min.js +112 -112
  13. package/dist/needle-engine.bundle.umd.cjs +113 -113
  14. package/dist/needle-engine.d.ts +4 -0
  15. package/dist/needle-engine.js +2 -2
  16. package/dist/needle-engine.light.d.ts +13 -9
  17. package/dist/needle-engine.light.js +2 -2
  18. package/dist/needle-engine.light.min.js +1 -1
  19. package/dist/needle-engine.min.js +1 -1
  20. package/dist/postprocessing.js +1 -1
  21. package/dist/postprocessing.light.js +1 -1
  22. package/dist/postprocessing.light.min.js +1 -1
  23. package/dist/postprocessing.min.js +1 -1
  24. package/dist/three-examples.js +1 -1
  25. package/dist/three-examples.light.js +1 -1
  26. package/dist/three-examples.light.min.js +1 -1
  27. package/dist/three-examples.min.js +1 -1
  28. package/dist/three-mesh-ui.js +1 -1
  29. package/dist/three-mesh-ui.light.js +1 -1
  30. package/dist/three-mesh-ui.light.min.js +1 -1
  31. package/dist/three-mesh-ui.min.js +1 -1
  32. package/dist/three.js +14 -14
  33. package/dist/three.light.js +14 -14
  34. package/dist/three.light.min.js +1 -1
  35. package/dist/three.min.js +1 -1
  36. package/dist/vendor.js +174 -174
  37. package/dist/vendor.light.js +174 -174
  38. package/dist/vendor.light.min.js +12 -12
  39. package/dist/vendor.light.umd.cjs +13 -13
  40. package/dist/vendor.min.js +12 -12
  41. package/dist/vendor.umd.cjs +13 -13
  42. package/lib/engine/engine_addressables.d.ts +6 -4
  43. package/lib/engine/engine_addressables.js +8 -1
  44. package/lib/engine/engine_addressables.js.map +1 -1
  45. package/lib/engine/engine_context.js +2 -0
  46. package/lib/engine/engine_context.js.map +1 -1
  47. package/lib/engine/engine_gameobject.d.ts +2 -12
  48. package/lib/engine/engine_gameobject.js +5 -15
  49. package/lib/engine/engine_gameobject.js.map +1 -1
  50. package/lib/engine/engine_input.d.ts +19 -6
  51. package/lib/engine/engine_input.js +0 -10
  52. package/lib/engine/engine_input.js.map +1 -1
  53. package/lib/engine/engine_license.js +1 -1
  54. package/lib/engine/engine_license.js.map +1 -1
  55. package/lib/engine/engine_networking_instantiate.d.ts +1 -1
  56. package/lib/engine/engine_types.d.ts +5 -0
  57. package/lib/engine/engine_types.js +6 -0
  58. package/lib/engine/engine_types.js.map +1 -1
  59. package/lib/engine/export/gltf/Writers.js.map +1 -1
  60. package/lib/engine/export/gltf/index.js +11 -1
  61. package/lib/engine/export/gltf/index.js.map +1 -1
  62. package/lib/engine/export/utils.d.ts +2 -0
  63. package/lib/engine/export/utils.js +8 -0
  64. package/lib/engine/export/utils.js.map +1 -0
  65. package/lib/engine/extensions/NEEDLE_gameobject_data.js +1 -1
  66. package/lib/engine/extensions/NEEDLE_gameobject_data.js.map +1 -1
  67. package/lib/engine/js-extensions/Object3D.d.ts +5 -1
  68. package/lib/engine/js-extensions/Object3D.js.map +1 -1
  69. package/lib/engine/webcomponents/needle menu/needle-menu.js +8 -2
  70. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  71. package/lib/engine-components/AvatarLoader.js.map +1 -1
  72. package/lib/engine-components/Component.d.ts +4 -3
  73. package/lib/engine-components/Component.js +6 -7
  74. package/lib/engine-components/Component.js.map +1 -1
  75. package/lib/engine-components/ContactShadows.d.ts +1 -1
  76. package/lib/engine-components/ContactShadows.js +7 -0
  77. package/lib/engine-components/ContactShadows.js.map +1 -1
  78. package/lib/engine-components/SceneSwitcher.d.ts +1 -1
  79. package/lib/engine-components/SceneSwitcher.js +1 -1
  80. package/lib/engine-components/SceneSwitcher.js.map +1 -1
  81. package/lib/engine-components/export/gltf/GltfExport.js +23 -4
  82. package/lib/engine-components/export/gltf/GltfExport.js.map +1 -1
  83. package/lib/engine-components/webxr/Avatar.js +3 -3
  84. package/lib/engine-components/webxr/Avatar.js.map +1 -1
  85. package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
  86. package/lib/engine-components-experimental/networking/PlayerSync.js +2 -1
  87. package/lib/engine-components-experimental/networking/PlayerSync.js.map +1 -1
  88. package/package.json +2 -2
  89. package/plugins/common/config.cjs +22 -6
  90. package/plugins/common/config.js +27 -11
  91. package/plugins/next/next.js +47 -4
  92. package/src/engine/codegen/register_types.ts +2 -2
  93. package/src/engine/engine_addressables.ts +19 -12
  94. package/src/engine/engine_context.ts +2 -0
  95. package/src/engine/engine_gameobject.ts +12 -16
  96. package/src/engine/engine_input.ts +12 -5
  97. package/src/engine/engine_license.ts +2 -1
  98. package/src/engine/engine_networking_instantiate.ts +1 -1
  99. package/src/engine/engine_types.ts +6 -0
  100. package/src/engine/export/gltf/Writers.ts +0 -1
  101. package/src/engine/export/gltf/index.ts +13 -3
  102. package/src/engine/export/index.ts +1 -1
  103. package/src/engine/export/utils.ts +10 -0
  104. package/src/engine/extensions/NEEDLE_gameobject_data.ts +1 -2
  105. package/src/engine/js-extensions/Object3D.ts +6 -1
  106. package/src/engine/webcomponents/needle menu/needle-menu.ts +16 -10
  107. package/src/engine-components/AvatarLoader.ts +1 -1
  108. package/src/engine-components/Component.ts +13 -7
  109. package/src/engine-components/ContactShadows.ts +11 -2
  110. package/src/engine-components/SceneSwitcher.ts +1 -1
  111. package/src/engine-components/export/gltf/GltfExport.ts +26 -6
  112. package/src/engine-components/webxr/Avatar.ts +3 -3
  113. package/src/engine-components/webxr/WebXRImageTracking.ts +5 -4
  114. package/src/engine-components-experimental/networking/PlayerSync.ts +1 -1
@@ -6,6 +6,7 @@ import { AnimationUtils } from "../../engine_animation.js";
6
6
  import type { Context } from "../../engine_setup.js";
7
7
  import { registerExportExtensions } from "../../extensions/index.js";
8
8
  import { __isExporting } from "../state.js";
9
+ import { shouldExport_HideFlags } from "../utils.js";
9
10
  import { GizmoWriter as GLTFGizmoWriter, RenderTextureWriter as GLTFRenderTextureWriter } from "./Writers.js";
10
11
 
11
12
  declare type ExportOptions = {
@@ -49,8 +50,7 @@ export async function exportAsGLTF(_opts: ExportOptions): Promise<ArrayBuffer |
49
50
  animations: collectAnimations(context, opts.scene, []),
50
51
  }
51
52
  const state = new ExporterState();
52
-
53
- console.log("Exporting GLTF", exporterOptions);
53
+ console.debug("Exporting GLTF", exporterOptions);
54
54
  state.onBeforeExport(opts);
55
55
  __isExporting(true);
56
56
  const res = await exporter.parseAsync(opts.scene, exporterOptions).catch((e) => {
@@ -108,7 +108,17 @@ class ExporterState {
108
108
  }
109
109
  }
110
110
  mixer.update(0);
111
- })
111
+ });
112
+
113
+ opts.context.scene.traverse(obj => {
114
+ if(!shouldExport_HideFlags(obj)) {
115
+ const parent = obj.parent;
116
+ if(parent) {
117
+ obj.removeFromParent();
118
+ this._undo.push(() => parent.add(obj));
119
+ }
120
+ }
121
+ });
112
122
  }
113
123
 
114
124
  onAfterExport(_opts: Required<ExportOptions>) {
@@ -1,2 +1,2 @@
1
1
  export * from "./gltf/index.js";
2
- export { isExporting } from "./state.js";
2
+ export { isExporting } from "./state.js";
@@ -0,0 +1,10 @@
1
+ import { Object3D } from "three";
2
+
3
+ import { HideFlags } from "../engine_types.js";
4
+
5
+
6
+ export function shouldExport_HideFlags(obj: Object3D) {
7
+ const dontExport = HideFlags.DontExport;
8
+ if (obj.hideFlags & dontExport) return false;
9
+ return true;
10
+ }
@@ -7,7 +7,6 @@ declare type GameObjectData = {
7
7
  layers: number,
8
8
  visible: boolean,
9
9
  tag: string,
10
- hideFlags: number,
11
10
  static: boolean,
12
11
  activeSelf: boolean,
13
12
  guid: string
@@ -71,7 +70,7 @@ export class NEEDLE_gameobject_data implements GLTFLoaderPlugin {
71
70
 
72
71
  node.userData.tag = ext.tag ?? "none";
73
72
 
74
- node.userData.hideFlags = ext.hideFlags ?? 0;
73
+ node.hideFlags = 0;
75
74
 
76
75
  node.userData.static = ext.static ?? false;
77
76
 
@@ -15,7 +15,7 @@ import {
15
15
  setWorldScale
16
16
  }
17
17
  from "../../engine/engine_three_utils.js";
18
- import type { ComponentInit, Constructor, ConstructorConcrete, IComponent as Component, IComponent } from "../../engine/engine_types.js";
18
+ import type { ComponentInit, Constructor, ConstructorConcrete, HideFlags,IComponent as Component, IComponent } from "../../engine/engine_types.js";
19
19
  import { applyPrototypeExtensions, registerPrototypeExtensions } from "./ExtensionUtils.js";
20
20
 
21
21
 
@@ -26,6 +26,11 @@ declare module 'three' {
26
26
  get guid(): string | undefined;
27
27
  set guid(value: string | undefined);
28
28
 
29
+ /**
30
+ * Allows to control e.g. if an object should be exported
31
+ */
32
+ hideFlags: HideFlags;
33
+
29
34
  /**
30
35
  * Add a Needle Engine component to the {@link Object3D}.
31
36
  * @param comp The component instance or constructor to add.
@@ -1,7 +1,7 @@
1
1
  import type { Context } from "../../engine_context.js";
2
2
  import { hasCommercialLicense, onLicenseCheckResultChanged } from "../../engine_license.js";
3
3
  import { isLocalNetwork } from "../../engine_networking_utils.js";
4
- import { DeviceUtilities,getParam } from "../../engine_utils.js";
4
+ import { DeviceUtilities, getParam } from "../../engine_utils.js";
5
5
  import { onXRSessionStart, XRSessionEventArgs } from "../../xr/events.js";
6
6
  import { ButtonsFactory } from "../buttons.js";
7
7
  import { ensureFonts, iconFontUrl, loadFont } from "../fonts.js";
@@ -256,7 +256,12 @@ export class NeedleMenuElement extends HTMLElement {
256
256
  if (!element && domElement.shadowRoot) {
257
257
  element = domElement.shadowRoot.querySelector(elementName);
258
258
  }
259
+ // if no needle-menu was found in the domelement then we search the document body
259
260
  if (!element) {
261
+ element = window.document.body.querySelector(elementName) as NeedleMenuElement | null;
262
+ }
263
+ if (!element) {
264
+ // OK no menu element exists yet anywhere
260
265
  element = NeedleMenuElement.create() as NeedleMenuElement;
261
266
  if (domElement.shadowRoot)
262
267
  domElement.shadowRoot.appendChild(element);
@@ -682,14 +687,15 @@ export class NeedleMenuElement extends HTMLElement {
682
687
  });
683
688
 
684
689
  try {
685
- // if the user has a license then we CAN hide the needle logo
686
- onLicenseCheckResultChanged(res => {
687
- if (res == true && hasCommercialLicense() && !debugNonCommercial) {
688
- let visible = this._userRequestedLogoVisible;
689
- if(visible === undefined) visible = false;
690
- this.#onSetLogoVisible(visible);
691
- }
692
- });
690
+ // if the user has a license then we CAN hide the needle logo
691
+ // calling this method immediately will cause an issue with vite bundling tho
692
+ window.requestAnimationFrame(() => onLicenseCheckResultChanged(res => {
693
+ if (res == true && hasCommercialLicense() && !debugNonCommercial) {
694
+ let visible = this._userRequestedLogoVisible;
695
+ if (visible === undefined) visible = false;
696
+ this.#onSetLogoVisible(visible);
697
+ }
698
+ }));
693
699
  } catch (e) {
694
700
  console.error("[Needle Menu] License check failed.", e);
695
701
  }
@@ -824,7 +830,7 @@ export class NeedleMenuElement extends HTMLElement {
824
830
  this.logoContainer.style.display = "";
825
831
  this.logoContainer.style.opacity = "1";
826
832
  this.logoContainer.style.visibility = "visible";
827
- if(visible) {
833
+ if (visible) {
828
834
  this.root.classList.remove("logo-hidden");
829
835
  this.root.classList.add("logo-visible");
830
836
  }
@@ -52,7 +52,7 @@ export class AvatarLoader {
52
52
  if (!root) {
53
53
  const opts = new InstantiateOptions();
54
54
  // opts.parent = context.scene.uuid;
55
- root = GameObject.instantiate(utils.tryFindObject(avatarId, context.scene), opts);
55
+ root = GameObject.instantiate(utils.tryFindObject(avatarId, context.scene) as Object3D, opts);
56
56
  }
57
57
  }
58
58
  else root = avatarId;
@@ -1,9 +1,10 @@
1
1
  import { Euler, Object3D, Quaternion, Scene, Vector3 } from "three";
2
2
 
3
3
  import { isDevEnvironment } from "../engine/debug/index.js";
4
+ import { type AssetReference } from "../engine/engine_addressables.js";
4
5
  import { addComponent, destroyComponentInstance, findObjectOfType, findObjectsOfType, getComponent, getComponentInChildren, getComponentInParent, getComponents, getComponentsInChildren, getComponentsInParent, getOrAddComponent, removeComponent } from "../engine/engine_components.js";
5
6
  import { activeInHierarchyFieldName } from "../engine/engine_constants.js";
6
- import { destroy, findByGuid, foreachComponent, HideFlags, type IInstantiateOptions, instantiate, isActiveInHierarchy, isActiveSelf, isDestroyed, isUsingInstancing, markAsInstancedRendered, setActive } from "../engine/engine_gameobject.js";
7
+ import { destroy, findByGuid, foreachComponent, type IInstantiateOptions, instantiate, isActiveInHierarchy, isActiveSelf, isDestroyed, isUsingInstancing, markAsInstancedRendered, setActive } from "../engine/engine_gameobject.js";
7
8
  import * as main from "../engine/engine_mainloop_utils.js";
8
9
  import { syncDestroy, syncInstantiate, SyncInstantiateOptions } from "../engine/engine_networking_instantiate.js";
9
10
  import { Context, FrameEvent } from "../engine/engine_setup.js";
@@ -117,15 +118,20 @@ export abstract class GameObject extends Object3D implements Object3D, IGameObje
117
118
  */
118
119
  public static instantiateSynced(instance: GameObject | Object3D | null, opts: SyncInstantiateOptions): GameObject | null {
119
120
  if (!instance) return null;
120
- return syncInstantiate(instance as any, opts) as GameObject | null;
121
+ return syncInstantiate(instance, opts) as GameObject | null;
121
122
  }
122
123
 
123
124
  /** Creates a new instance of the provided object (like cloning it including all components and children)
124
125
  * @param instance object to instantiate
125
126
  * @param opts options for the instantiation (e.g. with what parent, position, etc.)
126
127
  */
127
- public static instantiate(instance: GameObject | Object3D, opts: IInstantiateOptions | null = null): GameObject {
128
- return instantiate(instance, opts) as GameObject;
128
+ public static instantiate(instance: AssetReference, opts?: IInstantiateOptions | null | undefined): Promise<Object3D | null>
129
+ public static instantiate(instance: GameObject | Object3D, opts?: IInstantiateOptions | null | undefined): GameObject
130
+ public static instantiate(instance: AssetReference | GameObject | Object3D, opts: IInstantiateOptions | null | undefined = null): GameObject | Promise<Object3D | null> {
131
+ if ('isAssetReference' in instance) {
132
+ return instantiate(instance as AssetReference, opts);
133
+ }
134
+ return instantiate(instance as GameObject | Object3D, opts) as GameObject;
129
135
  }
130
136
 
131
137
  /** Destroys a object on all connected clients (if you are in a networked session)
@@ -398,9 +404,9 @@ export abstract class Component implements IComponent, EventTarget,
398
404
  this.gameObject.userData.static = value;
399
405
  }
400
406
  }
401
- get hideFlags(): HideFlags {
402
- return this.gameObject?.userData.hideFlags;
403
- }
407
+ // get hideFlags(): HideFlags {
408
+ // return this.gameObject?.hideFlags;
409
+ // }
404
410
 
405
411
  /** @returns true if the object is enabled and active in the hierarchy */
406
412
  get activeAndEnabled(): boolean {
@@ -9,7 +9,7 @@ import { Gizmos } from "../engine/engine_gizmos.js";
9
9
  import { onStart } from "../engine/engine_lifecycle_api.js";
10
10
  import { serializable } from "../engine/engine_serialization_decorator.js";
11
11
  import { getBoundingBox, getVisibleInCustomShadowRendering } from "../engine/engine_three_utils.js";
12
- import { IGameObject, Vec3 } from "../engine/engine_types.js";
12
+ import { HideFlags, IGameObject, Vec3 } from "../engine/engine_types.js";
13
13
  import { getParam } from "../engine/engine_utils.js"
14
14
  import { setCustomVisibility } from "../engine/js-extensions/Layers.js";
15
15
  import { Behaviour, GameObject } from "./Component.js";
@@ -37,7 +37,7 @@ onStart(ctx => {
37
37
  */
38
38
  export class ContactShadows extends Behaviour {
39
39
 
40
- private static _instances: Map<Context, ContactShadows> = new Map();
40
+ private static readonly _instances: Map<Context, ContactShadows> = new Map();
41
41
  /**
42
42
  * Create contact shadows for the scene. Automatically fits the shadows to the scene.
43
43
  * The instance of contact shadows will be created only once.
@@ -162,10 +162,14 @@ export class ContactShadows extends Behaviour {
162
162
 
163
163
  /** @internal */
164
164
  awake() {
165
+ ContactShadows._instances.set(this.context, this);
166
+ this.shadowsRoot.hideFlags = HideFlags.DontExport;
167
+
165
168
  // ignore self for autofitting
166
169
  setAutoFitEnabled(this.shadowsRoot, false);
167
170
  }
168
171
 
172
+
169
173
  /** @internal */
170
174
  start(): void {
171
175
  if (debug) console.log("Create ContactShadows on " + this.gameObject.name, this)
@@ -280,6 +284,11 @@ export class ContactShadows extends Behaviour {
280
284
 
281
285
  /** @internal */
282
286
  onDestroy(): void {
287
+ const instance = ContactShadows._instances.get(this.context);
288
+ if (instance === this) {
289
+ ContactShadows._instances.delete(this.context);
290
+ }
291
+
283
292
  // dispose the render targets
284
293
  this.renderTarget?.dispose();
285
294
  this.renderTargetBlur?.dispose();
@@ -760,7 +760,7 @@ export class SceneSwitcher extends Behaviour {
760
760
  }
761
761
  this._lastLoadingScene = this.loadingScene;
762
762
  if (!this._loadingScenePromise) {
763
- this._loadingScenePromise = this.loadingScene?.loadAssetAsync();
763
+ this._loadingScenePromise = this.loadingScene?.loadAssetAsync().then(res => res != null);
764
764
  }
765
765
  await this._loadingScenePromise;
766
766
  if (this._isCurrentlyLoading && this.loadingScene?.asset) {
@@ -6,6 +6,8 @@ import { SerializationContext } from "../../../engine/engine_serialization_core.
6
6
  import { serializable } from "../../../engine/engine_serialization_decorator.js";
7
7
  import { getWorldPosition } from "../../../engine/engine_three_utils.js";
8
8
  import { getParam } from "../../../engine/engine_utils.js";
9
+ import { RenderTextureWriter } from "../../../engine/export/gltf/Writers.js";
10
+ import { shouldExport_HideFlags } from "../../../engine/export/utils.js";
9
11
  import { registerExportExtensions } from "../../../engine/extensions/index.js";
10
12
  import { NEEDLE_components } from "../../../engine/extensions/NEEDLE_components.js";
11
13
  import GLTFMeshGPUInstancingExtension from '../../../include/three/EXT_mesh_gpu_instancing_exporter.js';
@@ -48,8 +50,8 @@ export class GltfExport extends Behaviour {
48
50
  if (!this.objects || this.objects.length <= 0)
49
51
  this.objects = [this.context.scene];
50
52
 
51
- const options = {
52
- binary: this.binary,
53
+ const options = {
54
+ binary: this.binary,
53
55
  pivot: GltfExport.calculateCenter(this.objects),
54
56
  ...opts
55
57
  };
@@ -74,6 +76,15 @@ export class GltfExport extends Behaviour {
74
76
 
75
77
  async export(objectsToExport: Object3D[], opts?: ExportOptions): Promise<any> {
76
78
 
79
+ // -----------------------
80
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
81
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
82
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
83
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
84
+ // TODO: refactor this to use ../engine/export/index exportAsGLTF function
85
+
86
+ // TODO add filtering / tags for what to export and what not < this is implemented in exportAsGLTF, see TODO above
87
+
77
88
  if (!objectsToExport || objectsToExport.length <= 0) {
78
89
  console.warn("No objects set to export");
79
90
  return;
@@ -82,12 +93,11 @@ export class GltfExport extends Behaviour {
82
93
  // Instantiate a exporter
83
94
  const exporter = new GLTFExporter();
84
95
  exporter.register(writer => new GLTFMeshGPUInstancingExtension(writer));
96
+ exporter.register(writer => new RenderTextureWriter(writer));
85
97
  registerExportExtensions(exporter, this.context);
86
98
 
87
99
  GltfExport.filterTopmostParent(objectsToExport);
88
100
 
89
- // TODO export only worldglb BUT exclude "World" child which contains all build tools
90
- // TODO add filtering / tags for what to export and what not
91
101
 
92
102
  // https://threejs.org/docs/#examples/en/exporters/GLTFExporter
93
103
  const options = {
@@ -102,7 +112,7 @@ export class GltfExport extends Behaviour {
102
112
  ...opts
103
113
  };
104
114
 
105
- // hide objects that we don't want to export
115
+ const undo = new Array<() => void>();
106
116
 
107
117
  const exportScene = new Object3D();
108
118
  // set the pivot position
@@ -112,7 +122,7 @@ export class GltfExport extends Behaviour {
112
122
  // add objects for export
113
123
  if (debugExport) console.log("EXPORT", objectsToExport);
114
124
  objectsToExport.forEach(obj => {
115
- if (obj) {
125
+ if (obj && shouldExport_HideFlags(obj)) {
116
126
  // adding directly does not require us to change parents and mess with the hierarchy actually
117
127
  exportScene.children.push(obj);
118
128
  // TODO: we should probably be doing this before writing nodes?? apply world scale, position, rotation etc for export only
@@ -122,6 +132,15 @@ export class GltfExport extends Behaviour {
122
132
  GameObject.getComponentsInChildren(obj, Renderer).forEach(r => {
123
133
  if (GameObject.isActiveInHierarchy(r.gameObject)) r.setInstancingEnabled(false)
124
134
  });
135
+ obj.traverse(o => {
136
+ if (!shouldExport_HideFlags(o)) {
137
+ const parent = o.parent;
138
+ o.removeFromParent();
139
+ undo.push(() => {
140
+ if (parent) parent.add(o);
141
+ });
142
+ }
143
+ })
125
144
  }
126
145
  });
127
146
 
@@ -159,6 +178,7 @@ export class GltfExport extends Behaviour {
159
178
  reject(err);
160
179
  }
161
180
  finally {
181
+ undo.forEach(u => u());
162
182
  if (debugExport) console.log("Finished glTF export.");
163
183
  }
164
184
  });
@@ -101,7 +101,7 @@ export class Avatar extends Behaviour {
101
101
  headObj.quaternion.x *= -1;
102
102
 
103
103
  // HACK: XRFlag limitation workaround to make sure first person user head is never rendered
104
- if (this.context.time.frameCount % 10 === 0) {
104
+ if (this.context.time.frameCount % 10 === 0 && this.head.asset) {
105
105
  const xrflags = GameObject.getComponentsInChildren(this.head.asset, XRFlag);
106
106
  for (const flag of xrflags) {
107
107
  flag.enabled = false;
@@ -242,9 +242,9 @@ export class Avatar extends Behaviour {
242
242
  await this.loadAvatarObjects(this.head, this.leftHand, this.rightHand);
243
243
 
244
244
  this._leftHandMeshes = [];
245
- this.leftHand.asset.traverse((obj) => { if ((obj as Mesh)?.isMesh) this._leftHandMeshes!.push(obj); });
245
+ this.leftHand.asset?.traverse((obj) => { if ((obj as Mesh)?.isMesh) this._leftHandMeshes!.push(obj as Mesh); });
246
246
  this._rightHandMeshes = [];
247
- this.rightHand.asset.traverse((obj) => { if ((obj as Mesh)?.isMesh) this._rightHandMeshes!.push(obj); });
247
+ this.rightHand.asset?.traverse((obj) => { if ((obj as Mesh)?.isMesh) this._rightHandMeshes!.push(obj as Mesh); });
248
248
 
249
249
  if (PlayerState.isLocalPlayer(this.gameObject)) {
250
250
  this._syncTransforms = GameObject.getComponentsInChildren(this.gameObject, SyncedTransform);
@@ -4,6 +4,7 @@ import { Object3DEventMap } from "three";
4
4
  import { isDevEnvironment, showBalloonWarning } from "../../engine/debug/index.js";
5
5
  import { AssetReference } from "../../engine/engine_addressables.js";
6
6
  import { serializable } from "../../engine/engine_serialization.js";
7
+ import { IGameObject } from "../../engine/engine_types.js";
7
8
  import { CircularBuffer, DeviceUtilities, getParam } from "../../engine/engine_utils.js";
8
9
  import { type NeedleXREventArgs, NeedleXRSession } from "../../engine/xr/api.js";
9
10
  import { IUSDExporterExtension } from "../../engine-components/export/usdz/Extension.js";
@@ -355,7 +356,7 @@ export class WebXRImageTracking extends Behaviour {
355
356
  }
356
357
  }
357
358
 
358
- private readonly imageToObjectMap = new Map<WebXRImageTrackingModel, { object: GameObject | null, frames: number, lastTrackingTime: number }>();
359
+ private readonly imageToObjectMap = new Map<WebXRImageTrackingModel, { object: Object3D | null, frames: number, lastTrackingTime: number }>();
359
360
  private readonly currentImages: WebXRTrackedImage[] = [];
360
361
 
361
362
 
@@ -456,7 +457,7 @@ export class WebXRImageTracking extends Behaviour {
456
457
  trackedData = { object: null, frames: 0, lastTrackingTime: Date.now() };
457
458
  this.imageToObjectMap.set(model, trackedData);
458
459
 
459
- model.object.loadAssetAsync().then((asset: GameObject | null) => {
460
+ model.object.loadAssetAsync().then((asset: Object3D | null) => {
460
461
  if (model.createObjectInstance && asset) {
461
462
  asset = GameObject.instantiate(asset);
462
463
  }
@@ -475,7 +476,7 @@ export class WebXRImageTracking extends Behaviour {
475
476
  if (xr.rig) {
476
477
  xr.rig.gameObject.add(asset);
477
478
  image.applyToObject(asset);
478
- if (!asset.activeSelf)
479
+ if (!(asset as IGameObject).activeSelf)
479
480
  GameObject.setActive(asset, true);
480
481
  // InstancingUtil.markDirty(asset);
481
482
  }
@@ -503,7 +504,7 @@ export class WebXRImageTracking extends Behaviour {
503
504
  xr.rig.gameObject.add(trackedData.object);
504
505
 
505
506
  image.applyToObject(trackedData.object, this.smooth ? this.context.time.deltaTimeUnscaled * 3 : undefined);
506
- if (!trackedData.object.activeSelf) {
507
+ if (!(trackedData.object as IGameObject).activeSelf) {
507
508
  GameObject.setActive(trackedData.object, true);
508
509
  }
509
510
  // InstancingUtil.markDirty(trackedData.object);
@@ -36,7 +36,7 @@ export class PlayerSync extends Behaviour {
36
36
  const assetReference = AssetReference.getOrCreateFromUrl(url);
37
37
  if (!assetReference.asset) {
38
38
  const i = await assetReference.loadAssetAsync();
39
- GameObject.getOrAddComponent(i, PlayerState);
39
+ if(i) GameObject.getOrAddComponent(i, PlayerState);
40
40
  }
41
41
  const ps = new PlayerSync();
42
42
  ps._internalInit(init);