@needle-tools/engine 3.2.11-alpha → 3.2.13-alpha

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 (46) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/needle-engine.js +9274 -9206
  3. package/dist/needle-engine.min.js +273 -273
  4. package/dist/needle-engine.umd.cjs +271 -271
  5. package/lib/engine/codegen/register_types.js +2 -0
  6. package/lib/engine/codegen/register_types.js.map +1 -1
  7. package/lib/engine/engine_context.js +3 -0
  8. package/lib/engine/engine_context.js.map +1 -1
  9. package/lib/engine/engine_mainloop_utils.js +1 -1
  10. package/lib/engine/engine_mainloop_utils.js.map +1 -1
  11. package/lib/engine/engine_serialization_core.js +2 -0
  12. package/lib/engine/engine_serialization_core.js.map +1 -1
  13. package/lib/engine/engine_types.d.ts +2 -2
  14. package/lib/engine/engine_utils.d.ts +2 -2
  15. package/lib/engine/engine_utils.js +4 -4
  16. package/lib/engine/engine_utils.js.map +1 -1
  17. package/lib/engine-components/Component.d.ts +2 -2
  18. package/lib/engine-components/Component.js +9 -4
  19. package/lib/engine-components/Component.js.map +1 -1
  20. package/lib/engine-components/SceneSwitcher.d.ts +5 -0
  21. package/lib/engine-components/SceneSwitcher.js +32 -4
  22. package/lib/engine-components/SceneSwitcher.js.map +1 -1
  23. package/lib/engine-components/codegen/components.d.ts +1 -0
  24. package/lib/engine-components/codegen/components.js +1 -0
  25. package/lib/engine-components/codegen/components.js.map +1 -1
  26. package/lib/engine-components/export/usdz/USDZExporter.d.ts +9 -4
  27. package/lib/engine-components/export/usdz/USDZExporter.js +77 -25
  28. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  29. package/lib/tsconfig.tsbuildinfo +1 -1
  30. package/package.json +1 -1
  31. package/plugins/vite/alias.js +1 -4
  32. package/plugins/vite/copyfiles.js +46 -40
  33. package/plugins/vite/index.js +2 -0
  34. package/plugins/vite/meta.js +5 -2
  35. package/plugins/vite/peer.js +28 -0
  36. package/plugins/vite/reload.js +17 -13
  37. package/src/engine/codegen/register_types.js +2 -0
  38. package/src/engine/engine_context.ts +2 -0
  39. package/src/engine/engine_mainloop_utils.ts +1 -1
  40. package/src/engine/engine_serialization_core.ts +1 -1
  41. package/src/engine/engine_types.ts +2 -2
  42. package/src/engine/engine_utils.ts +7 -7
  43. package/src/engine-components/Component.ts +9 -4
  44. package/src/engine-components/SceneSwitcher.ts +38 -5
  45. package/src/engine-components/codegen/components.ts +1 -0
  46. package/src/engine-components/export/usdz/USDZExporter.ts +73 -28
@@ -10,16 +10,23 @@ import { IUSDZExporterExtension } from "./Extension";
10
10
  import { Behaviour, GameObject } from "../../Component";
11
11
  import { WebXR } from "../../webxr/WebXR"
12
12
  import { serializable } from "../../../engine/engine_serialization";
13
- import { showBalloonWarning } from "../../../engine/debug/debug";
13
+ import { isDevEnvironment, showBalloonMessage, showBalloonWarning } from "../../../engine/debug/debug";
14
14
  import { Context } from "../../../engine/engine_setup";
15
15
  import { WebARSessionRoot } from "../../webxr/WebARSessionRoot";
16
16
 
17
17
  const debug = getParam("debugusdz");
18
18
 
19
- export type QuickLookOverlay = {
19
+ export class QuickLookOverlay {
20
+ @serializable()
20
21
  callToAction?: string;
22
+ @serializable()
21
23
  checkoutTitle?: string;
24
+ @serializable()
22
25
  checkoutSubtitle?: string;
26
+
27
+ /** if assigned the call to action button in quicklook will open the URL. Otherwise it will just close quicklook. */
28
+ @serializable()
29
+ callToActionURL?: string;
23
30
  }
24
31
 
25
32
  export class USDZExporter extends Behaviour {
@@ -30,6 +37,9 @@ export class USDZExporter extends Behaviour {
30
37
  @serializable()
31
38
  autoExportAnimations: boolean = false;
32
39
 
40
+ @serializable(QuickLookOverlay)
41
+ overlay?: QuickLookOverlay;
42
+
33
43
  extensions: IUSDZExporterExtension[] = [];
34
44
 
35
45
  private link!: HTMLAnchorElement;
@@ -39,6 +49,8 @@ export class USDZExporter extends Behaviour {
39
49
 
40
50
  start() {
41
51
  if (debug) {
52
+ console.log(this);
53
+ console.log("Debug USDZ, press 't' to export")
42
54
  window.addEventListener("keydown", (evt) => {
43
55
  switch (evt.key) {
44
56
  case "t":
@@ -58,6 +70,12 @@ export class USDZExporter extends Behaviour {
58
70
  });
59
71
 
60
72
  if (!this.objectToExport) this.objectToExport = this.gameObject;
73
+
74
+
75
+ if (isDevEnvironment() && (!this.objectToExport || this.objectToExport.children.length <= 0)) {
76
+ showBalloonWarning("USDZ Exporter has nothing to export");
77
+ console.warn("USDZExporter has no objects to export assigned:", this)
78
+ }
61
79
  }
62
80
 
63
81
 
@@ -66,16 +84,25 @@ export class USDZExporter extends Behaviour {
66
84
  const ios = isiOS()
67
85
  const safari = isSafari();
68
86
  if (debug || (ios && safari)) {
69
- this.createQuicklookButton();
87
+ this.addQuicklookButton();
70
88
  this.webARSessionRoot = GameObject.findObjectOfType(WebARSessionRoot) ?? undefined;
71
89
  this.lastCallback = this.quicklookCallback.bind(this);
72
90
  this.link = ensureQuicklookLinkIsCreated(this.context);
73
91
  this.link.addEventListener('message', this.lastCallback);
74
92
  }
93
+ if (debug)
94
+ showBalloonMessage("USDZ Exporter enabled: " + this.name);
75
95
  }
76
96
 
77
97
  onDisable() {
78
98
  this.link?.removeEventListener('message', this.lastCallback);
99
+ const ios = isiOS()
100
+ const safari = isSafari();
101
+ if (debug || (ios && safari)) {
102
+ this.removeQuicklookButton();
103
+ }
104
+ if (debug)
105
+ showBalloonMessage("USDZ Exporter disabled: " + this.name);
79
106
  }
80
107
 
81
108
  async exportAsync() {
@@ -125,14 +152,15 @@ export class USDZExporter extends Behaviour {
125
152
 
126
153
  // see https://developer.apple.com/documentation/arkit/adding_an_apple_pay_button_or_a_custom_action_in_ar_quick_look
127
154
  const overlay = this.buildQuicklookOverlay();
155
+ console.log(overlay);
128
156
  const callToAction = overlay.callToAction ? encodeURIComponent(overlay.callToAction) : "";
129
157
  const checkoutTitle = overlay.checkoutTitle ? encodeURIComponent(overlay.checkoutTitle) : "";
130
158
  const checkoutSubtitle = overlay.checkoutSubtitle ? encodeURIComponent(overlay.checkoutSubtitle) : "";
131
- this.link.href = URL.createObjectURL(blob) + `#callToAction=${callToAction}&checkoutTitle=${checkoutTitle}&checkoutSubtitle=${checkoutSubtitle}&`;
159
+ this.link.href = URL.createObjectURL(blob) + `#callToAction=${callToAction}&checkoutTitle=${checkoutTitle}&checkoutSubtitle=${checkoutSubtitle}&callToActionURL=${overlay.callToActionURL}`;
132
160
 
133
161
 
134
162
  if (!this.lastCallback) {
135
- this.lastCallback = this.quicklookCallback.bind(this);
163
+ this.lastCallback = this.quicklookCallback.bind(this)
136
164
  this.link.addEventListener('message', this.lastCallback);
137
165
  }
138
166
 
@@ -146,24 +174,44 @@ export class USDZExporter extends Behaviour {
146
174
 
147
175
  private lastCallback?: any;
148
176
 
149
- private quicklookCallback(event) {
177
+ private quicklookCallback(event: Event) {
150
178
  if ((event as any)?.data == '_apple_ar_quicklook_button_tapped') {
151
179
  if (debug) showBalloonWarning("Quicklook closed via call to action button");
152
- this.dispatchEvent(new CustomEvent("quicklook-button-tapped", { detail: this }));
180
+ var evt = new CustomEvent("quicklook-button-tapped", { detail: this });
181
+ this.dispatchEvent(evt);
182
+ if (!evt.defaultPrevented) {
183
+ const url = new URLSearchParams(this.link.href);
184
+ if (url) {
185
+ const callToActionURL = url.get("callToActionURL");
186
+ if (debug)
187
+ showBalloonMessage("Quicklook url: " + callToActionURL);
188
+ if (callToActionURL) {
189
+ globalThis.open(callToActionURL, "_blank");
190
+ }
191
+ }
192
+ }
153
193
  }
154
194
  }
155
195
 
156
196
  private buildQuicklookOverlay(): QuickLookOverlay {
157
197
  const obj: QuickLookOverlay = {};
158
- obj.callToAction = "Close";
159
- obj.checkoutTitle = "🌵 Made with Needle";
160
- obj.checkoutSubtitle = "_";
198
+ if (this.overlay) Object.assign(obj, this.overlay);
199
+ if (!obj.callToAction?.length)
200
+ obj.callToAction = "Close";
201
+ if (!obj.checkoutTitle?.length)
202
+ obj.checkoutTitle = "🌵 Made with Needle";
203
+ if (!obj.checkoutSubtitle?.length)
204
+ obj.checkoutSubtitle = "_";
161
205
  // Use the quicklook-overlay event to customize the overlay
162
206
  this.dispatchEvent(new CustomEvent("quicklook-overlay", { detail: obj }));
163
207
  return obj;
164
208
  }
165
209
 
166
- private _arButton?: HTMLElement;
210
+
211
+
212
+
213
+ private _quicklookButton?: HTMLElement;
214
+
167
215
  private async createQuicklookButton() {
168
216
  if (!this.webxr) {
169
217
  await delay(1);
@@ -171,8 +219,8 @@ export class USDZExporter extends Behaviour {
171
219
  if (this.webxr) {
172
220
  if (this.webxr.VRButton) this.webxr.VRButton.parentElement?.removeChild(this.webxr.VRButton);
173
221
  // check if we have an AR button already and re-use that
174
- if (this.webxr.ARButton && this._arButton !== this.webxr.ARButton) {
175
- this._arButton = this.webxr.ARButton;
222
+ if (this.webxr.ARButton && this._quicklookButton !== this.webxr.ARButton) {
223
+ this._quicklookButton = this.webxr.ARButton;
176
224
  // Hack to remove the immersiveweb link
177
225
  const linkInButton = this.webxr.ARButton.parentElement?.querySelector("a");
178
226
  if (linkInButton) {
@@ -185,6 +233,7 @@ export class USDZExporter extends Behaviour {
185
233
  this.exportAsync();
186
234
  });
187
235
  this.webxr.ARButton.classList.add("quicklook-ar-button");
236
+ this._quicklookButtonContainer = this.webxr.ARButton.parentElement;
188
237
  this.dispatchEvent(new CustomEvent("created-button", { detail: this.webxr.ARButton }))
189
238
  }
190
239
  // create a button if WebXR didnt create one yet
@@ -205,6 +254,7 @@ export class USDZExporter extends Behaviour {
205
254
  button.classList.add('webxr-button');
206
255
  button.classList.add("quicklook-ar-button");
207
256
  container.appendChild(button);
257
+ this._quicklookButtonContainer = container;
208
258
  this.dispatchEvent(new CustomEvent("created-button", { detail: button }))
209
259
  }
210
260
  }
@@ -214,20 +264,15 @@ export class USDZExporter extends Behaviour {
214
264
  }
215
265
  }
216
266
 
217
- private resetStyles(el: HTMLElement) {
218
- el.style.position = "";
219
- el.style.top = "";
220
- el.style.left = "";
221
- el.style.width = "";
222
- el.style.height = "";
223
- el.style.margin = "";
224
- el.style.padding = "";
225
- el.style.border = "";
226
- el.style.background = "";
227
- el.style.color = "";
228
- el.style.font = "";
229
- el.style.textAlign = "";
230
- el.style.opacity = "";
231
- el.style.zIndex = "";
267
+
268
+ private _quicklookButtonContainer: Element | null = null;
269
+ private async addQuicklookButton() {
270
+ await this.createQuicklookButton();
271
+ if (this._quicklookButton && this._quicklookButtonContainer) {
272
+ this._quicklookButtonContainer.appendChild(this._quicklookButton);
273
+ }
274
+ }
275
+ private removeQuicklookButton() {
276
+ this._quicklookButton?.remove();
232
277
  }
233
278
  }