Needle Engine

Changes between version 3.38.0-alpha.2 and 3.38.0-alpha.3
Files changed (7) hide show
  1. plugins/vite/meta.js +4 -1
  2. src/engine-components/export/usdz/extensions/Animation.ts +5 -3
  3. src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +6 -1
  4. src/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.ts +32 -2
  5. src/engine/webcomponents/needle menu/needle-menu.ts +1 -0
  6. src/engine-components/export/usdz/USDZExporter.ts +2 -6
  7. src/engine-components/webxr/WebXR.ts +5 -2
plugins/vite/meta.js CHANGED
@@ -12,7 +12,7 @@
12
12
  export const needleMeta = (command, config, userSettings) => {
13
13
 
14
14
  // we can check if this is a build
15
- // const isBuild = command === 'build';
15
+ const isBuild = command === 'build';
16
16
 
17
17
  async function updateConfig() {
18
18
  config = await loadConfig();
@@ -70,6 +70,9 @@
70
70
  tags.push({ tag: 'meta', attrs: { name: 'og:image:width', content: 1080 } });
71
71
  tags.push({ tag: 'meta', attrs: { name: 'og:image:height', content: 1080 } });
72
72
  }
73
+ else if (isBuild) {
74
+ console.warn(`Needle: meta.image is set but absolutePath is ${config.absolutePath} in userSettings. Skipping meta.image.`);
75
+ }
73
76
  }
74
77
 
75
78
  if (config.absolutePath?.length) {
src/engine-components/export/usdz/extensions/Animation.ts CHANGED
@@ -455,9 +455,11 @@
455
455
  data = datas[i];
456
456
  }
457
457
 
458
- if (!durations[i]) durations[i] = data.getDuration();
459
- else if (durations[i] !== data.getDuration()) {
460
- console.error("Different durations for targets – please report a bug!", datas);
458
+ const duration = data.getDuration();
459
+ if (durations[i] === undefined) durations[i] = duration;
460
+ else if (durations[i] !== duration) {
461
+ console.error("Error during UDSZ export: Encountered different animation durations for animated targets. Please report a bug!", {datas, target});
462
+ durations[i] = duration;
461
463
  continue;
462
464
  }
463
465
  }
src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts CHANGED
@@ -895,7 +895,12 @@
895
895
 
896
896
  if (animation) {
897
897
  const anim = ext.registerAnimation(target, animation.clip);
898
- if (anim) animationLoopAfterSequence.push(anim);
898
+ if (anim) {
899
+ if (animation.loop)
900
+ animationLoopAfterSequence.push(anim);
901
+ else
902
+ animationSequence.push(anim);
903
+ }
899
904
  return {
900
905
  animationSequence,
901
906
  animationLoopAfterSequence
src/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { Object3D, Vector3 } from "three";
1
+ import { Object3D } from "three";
2
2
 
3
- import { EnumToPrimitiveUnion, getParam } from "../../../../../engine/engine_utils.js";
3
+ import { getParam } from "../../../../../engine/engine_utils.js";
4
4
  import { makeNameSafeForUSD,USDDocument, USDObject, USDWriter } from "../../ThreeUSDZExporter.js";
5
5
  import { BehaviorExtension } from "./Behaviour.js";
6
6
 
@@ -29,6 +29,31 @@
29
29
  this.id = "Behavior_" + makeNameSafeForUSD(id) + "_" + BehaviorModel.global_id++;
30
30
  this.trigger = trigger;
31
31
  this.action = action;
32
+
33
+ // Special case: SceneTransition enter triggers should never run multiple times, even if the stage loops.
34
+ // There seems to have been a change in behavior in iOS, where SceneTransition enter runs even
35
+ // when the stage length is reached...
36
+ // BUT unfortunately it looks like child groups are also ignored then, and their own loops stop working
37
+ // once any parent is set to "ignore", which is different than what's in the documentation.
38
+ /*
39
+ if (trigger instanceof TriggerModel) {
40
+ if (trigger.tokenId === "SceneTransition" && trigger.type === "enter") {
41
+ const wrapper = ActionBuilder.sequence(action);
42
+ wrapper.multiplePerformOperation = "ignore";
43
+ this.action = wrapper;
44
+ }
45
+ }
46
+ */
47
+ // Another idea: we let actions run forever by appending a waitAction to them
48
+ // Also doesn't seem to work... the scene start action still runs again
49
+ /*
50
+ if (trigger instanceof TriggerModel) {
51
+ if (trigger.tokenId === "SceneTransition" && trigger.type === "enter") {
52
+ const wrapper = ActionBuilder.sequence(action, ActionBuilder.waitAction(9999999999));
53
+ this.action = wrapper;
54
+ }
55
+ }
56
+ */
32
57
  }
33
58
 
34
59
  writeTo(_ext: BehaviorExtension, document: USDDocument, writer: USDWriter) {
@@ -191,6 +216,7 @@
191
216
  loops: number = 0;
192
217
  performCount: number = 1;
193
218
  type: string = "serial";
219
+ multiplePerformOperation: MultiplePerformOperation | undefined = undefined;
194
220
 
195
221
  constructor(id: string, actions: IBehaviorElement[]) {
196
222
  this.id = id;
@@ -238,6 +264,10 @@
238
264
  writer.appendLine(`bool loops = ${this.loops}`);
239
265
  writer.appendLine(`int performCount = ${this.loops > 0 ? 0 : Math.max(0, this.performCount)}`);
240
266
  writer.appendLine(`token type = "${this.type}"`);
267
+ if (typeof this.multiplePerformOperation === "string") {
268
+ writer.appendLine(`token multiplePerformOperation = "${this.multiplePerformOperation}"`);
269
+ }
270
+
241
271
  writer.appendLine();
242
272
 
243
273
  for (const act of this.actions) {
src/engine/webcomponents/needle menu/needle-menu.ts CHANGED
@@ -234,6 +234,7 @@
234
234
  overflow: clip;
235
235
  box-shadow: 0px 7px 0.5rem 0px rgb(0 0 0 / 6%), inset 0px 0px 1.3rem rgba(0,0,0,.05);
236
236
  backdrop-filter: blur(16px);
237
+ -webkit-backdrop-filter: blur(16px);
237
238
  pointer-events: all;
238
239
  z-index: 1000;
239
240
  }
src/engine-components/export/usdz/USDZExporter.ts CHANGED
@@ -399,9 +399,8 @@
399
399
  });
400
400
  }
401
401
 
402
- const behaviorExt = this.extensions.find(ext => ext.extensionName === "Behaviour");
403
- if (this.interactive && behaviorExt) {
404
- //@ts-ignore
402
+ const behaviorExt = this.extensions.find(ext => ext.extensionName === "Behaviour") as BehaviorExtension | undefined;
403
+ if (this.interactive && behaviorExt && objectsToDisableAtSceneStart.length > 0) {
405
404
  behaviorExt.addBehavior(disableObjectsAtStart(objectsToDisableAtSceneStart));
406
405
  }
407
406
 
@@ -585,8 +584,6 @@
585
584
  let sessionRoot = GameObject.getComponentInParent(this.objectToExport, WebARSessionRoot);
586
585
  if(!sessionRoot) sessionRoot = GameObject.getComponentInChildren(this.objectToExport, WebARSessionRoot);
587
586
 
588
- if (debug) console.log("applyWebARSessionRoot", sessionRoot, sessionRoot?.arScale);
589
-
590
587
  let arScale = 1;
591
588
  let _invertForward = false;
592
589
  const target = this.objectToExport;
@@ -602,7 +599,6 @@
602
599
 
603
600
  const scale = 1 / arScale;
604
601
  const result = { scale, _invertForward, target, sessionRoot: sessionRoot?.gameObject ?? null };
605
- console.log("getARScaleAndTarget", result);
606
602
  return result;
607
603
  }
608
604
 
src/engine-components/webxr/WebXR.ts CHANGED
@@ -287,8 +287,11 @@
287
287
  // Quicklook / iOS
288
288
  if ((isiOS() && isSafari()) || debugQuicklook) {
289
289
  if (this.useQuicklookExport) {
290
- const button = this.getButtonsFactory().createQuicklookButton();
291
- this.addButton(button, xrButtonsPriority);
290
+ const usdzExporter = GameObject.findObjectOfType(USDZExporter);
291
+ if (!usdzExporter || (usdzExporter && usdzExporter.allowCreateQuicklookButton)) {
292
+ const button = this.getButtonsFactory().createQuicklookButton();
293
+ this.addButton(button, xrButtonsPriority);
294
+ }
292
295
  }
293
296
  }
294
297
  // WebXR