@needle-tools/engine 3.34.3-alpha.1 → 3.34.4-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.
@@ -155,46 +155,18 @@ export class OrbitControls extends Behaviour implements ICameraController {
155
155
  private _camera: Camera | null = null;
156
156
  private _syncedTransform?: SyncedTransform;
157
157
  private _didStart = false;
158
+ private _didSetTarget = false;
158
159
 
159
160
  targetElement: HTMLElement | null = null;
160
161
 
161
162
  awake(): void {
162
163
  this._didStart = false;
164
+ this._didSetTarget = false;
163
165
  this._startedListeningToKeyEvents = false;
164
166
  }
165
167
 
166
168
  start() {
167
169
  this._didStart = true;
168
- if (this.autoTarget) {
169
- if (this._controls) {
170
- const camGo = GameObject.getComponent(this.gameObject, Camera);
171
- if (camGo && !this.setLookTargetFromConstraint()) {
172
- if (this.debugLog)
173
- console.log("NO TARGET");
174
- const worldPosition = getWorldPosition(camGo.cam);
175
- const distanceToCenter = worldPosition.length();
176
- const forward = new Vector3(0, 0, -distanceToCenter).applyMatrix4(camGo.cam.matrixWorld);
177
- this.setLookTargetPosition(forward, true);
178
- }
179
- // we need to wait one frame for the scene be fully populated. E.g. when we added progressive meshes and a heavy scene this was necessary
180
- delayForFrames(0).then(() => {
181
- if (this.autoTarget && !this.autoFit && !this.setLookTargetFromConstraint()) {
182
- const opts = new RaycastOptions();
183
- // center of the screen:
184
- opts.screenPoint = new Vector2(0, 0);
185
- opts.lineThreshold = 0.1;
186
- const hits = this.context.physics.raycast(opts);
187
- if (hits.length > 0) {
188
- this.setLookTargetPosition(hits[0].point, true);
189
- }
190
- if (debugCameraFit)
191
- console.log("OrbitControls hits", ...hits);
192
- }
193
- if (this.autoFit) this.fitCamera()
194
- });
195
- }
196
- }
197
-
198
170
  this._eventSystem = EventSystem.get(this.context) ?? undefined;
199
171
  if (this._eventSystem) {
200
172
  this._afterHandleInputFn = this.afterHandleInput.bind(this);
@@ -211,15 +183,13 @@ export class OrbitControls extends Behaviour implements ICameraController {
211
183
  this._enableTime = this.context.time.time;
212
184
  const cameraComponent = GameObject.getComponent(this.gameObject, Camera);
213
185
  this._camera = cameraComponent;
214
- const cam = cameraComponent?.cam;
186
+ let cam = cameraComponent?.cam;
187
+ if (!cam && this.gameObject instanceof PerspectiveCamera) {
188
+ cam = this.gameObject;
189
+ }
215
190
  if (cam) setCameraController(cam, this, true);
216
- if (!this._controls) {
217
- if (!cam) {
218
- console.warn("OrbitControls: Requires a Camera component on the same object as this component.");
219
- return;
220
- }
221
- if (cam)
222
- this._cameraObject = cam;
191
+ if (!this._controls && cam instanceof PerspectiveCamera) {
192
+ this._cameraObject = cam;
223
193
  // Using the parent if possible to make it possible to disable input on the canvas
224
194
  // for having HTML content behind it and still receive input
225
195
  const element = this.targetElement ?? this.context.renderer.domElement;
@@ -306,6 +276,8 @@ export class OrbitControls extends Behaviour implements ICameraController {
306
276
  onBeforeRender() {
307
277
  if (!this._controls) return;
308
278
  if (this._cameraObject !== this.context.mainCamera) return;
279
+
280
+ this.__handleSetTargetWhenBecomingActiveTheFirstTime();
309
281
 
310
282
  if (this.context.input.getPointerDown(1) || this.context.input.getPointerDown(2) || this.context.input.mouseWheelChanged || (this.context.input.getPointerPressed(0) && this.context.input.getPointerPositionDelta(0)?.length() || 0 > .1)) {
311
283
  this._inputs += 1;
@@ -406,6 +378,36 @@ export class OrbitControls extends Behaviour implements ICameraController {
406
378
 
407
379
  }
408
380
 
381
+ private __handleSetTargetWhenBecomingActiveTheFirstTime() {
382
+ if (this._didSetTarget) return;
383
+ this._didSetTarget = true;
384
+ if (this.autoTarget) {
385
+
386
+ const camGo = GameObject.getComponent(this.gameObject, Camera);
387
+ if (camGo && !this.setLookTargetFromConstraint()) {
388
+ if (this.debugLog)
389
+ console.log("NO TARGET");
390
+ const worldPosition = getWorldPosition(camGo.cam);
391
+ const distanceToCenter = worldPosition.length();
392
+ const forward = new Vector3(0, 0, -distanceToCenter).applyMatrix4(camGo.cam.matrixWorld);
393
+ this.setLookTargetPosition(forward, true);
394
+ }
395
+ if (!this.autoFit && !this.setLookTargetFromConstraint()) {
396
+ const opts = new RaycastOptions();
397
+ // center of the screen:
398
+ opts.screenPoint = new Vector2(0, 0);
399
+ opts.lineThreshold = 0.1;
400
+ const hits = this.context.physics.raycast(opts);
401
+ if (hits.length > 0) {
402
+ this.setLookTargetPosition(hits[0].point, true);
403
+ }
404
+ if (debugCameraFit)
405
+ console.log("OrbitControls hits", ...hits);
406
+ }
407
+ if (this.autoFit) this.fitCamera()
408
+ }
409
+ }
410
+
409
411
 
410
412
  /**
411
413
  * Sets camera target position and look direction. Does perform a raycast in the forward direction of the passed in object to find an orbit point
@@ -279,19 +279,16 @@ export class WebXR extends Behaviour {
279
279
  if ((isiOS() && isSafari()) || debugQuicklook) {
280
280
  if (this.useQuicklookExport) {
281
281
  const button = this.getButtonsFactory().createQuicklookButton();
282
- button.prepend(getIconElement("view_in_ar"));
283
282
  this.addButton(button, xrButtonsPriority);
284
283
  }
285
284
  }
286
285
  // WebXR
287
286
  if (this.createARButton) {
288
287
  const arbutton = this.getButtonsFactory().createARButton();
289
- arbutton.prepend(getIconElement("view_in_ar"))
290
288
  this.addButton(arbutton, xrButtonsPriority);
291
289
  }
292
290
  if (this.createVRButton) {
293
291
  const vrbutton = this.getButtonsFactory().createVRButton();
294
- vrbutton.prepend(getIconElement("panorama_photosphere"));
295
292
  this.addButton(vrbutton, xrButtonsPriority);
296
293
  }
297
294
  }
@@ -300,7 +297,6 @@ export class WebXR extends Behaviour {
300
297
  NeedleXRSession.isVRSupported().then(supported => {
301
298
  if (!supported) {
302
299
  const button = this.getButtonsFactory().createSendToQuestButton();
303
- button.prepend(getIconElement("share_windows"));
304
300
  this.addButton(button, xrButtonsPriority);
305
301
  }
306
302
  });
@@ -310,7 +306,6 @@ export class WebXR extends Behaviour {
310
306
  NeedleXRSession.isXRSupported().then(supported => {
311
307
  if (isDesktop() || !supported) {
312
308
  const qrCode = this.getButtonsFactory().createQRCode();
313
- qrCode.prepend(getIconElement("qr_code"));
314
309
  this.addButton(qrCode, xrButtonsPriority);
315
310
  }
316
311
  });
@@ -2,6 +2,7 @@ import { isDevEnvironment } from "../../engine/debug/index.js";
2
2
  import { generateQRCode } from "../../engine/engine_utils.js";
3
3
  import { isMozillaXR } from "../../engine/engine_utils.js";
4
4
  import { NeedleXRSession } from "../../engine/engine_xr.js";
5
+ import { getIconElement } from "../../engine/webcomponents/icons.js";
5
6
  import { GameObject } from "../Component.js";
6
7
  import { USDZExporter } from "../export/usdz/USDZExporter.js";
7
8
 
@@ -49,9 +50,9 @@ export class WebXRButtonFactory {
49
50
 
50
51
  const button = document.createElement("button");
51
52
  this._quicklookButton = button;
52
-
53
53
  button.dataset["needle"] = "quicklook-button";
54
54
  button.innerText = "Open in Quicklook";
55
+ button.prepend(getIconElement("view_in_ar"));
55
56
  button.addEventListener("click", () => {
56
57
  const usdzExporter = GameObject.findObjectOfType(USDZExporter);
57
58
  if (usdzExporter) {
@@ -87,6 +88,7 @@ export class WebXRButtonFactory {
87
88
  button.classList.add("webxr-button");
88
89
  button.dataset["needle"] = "webxr-ar-button";
89
90
  button.innerText = "Enter AR";
91
+ button.prepend(getIconElement("view_in_ar"))
90
92
  button.title = "Click to start an AR session";
91
93
  button.addEventListener("click", () => NeedleXRSession.start(mode, init));
92
94
  this.updateSessionSupported(button, mode);
@@ -120,6 +122,7 @@ export class WebXRButtonFactory {
120
122
  button.classList.add("webxr-button");
121
123
  button.dataset["needle"] = "webxr-vr-button";
122
124
  button.innerText = "Enter VR";
125
+ button.prepend(getIconElement("panorama_photosphere"));
123
126
  button.title = "Click to start a VR session";
124
127
  button.addEventListener("click", () => NeedleXRSession.start(mode, init));
125
128
  this.updateSessionSupported(button, mode);
@@ -148,6 +151,7 @@ export class WebXRButtonFactory {
148
151
  this._sendToQuestButton = button;
149
152
  button.dataset["needle"] = "webxr-sendtoquest-button";
150
153
  button.innerText = "Open on Quest";
154
+ button.prepend(getIconElement("share_windows"));
151
155
  button.title = "Click to send this page to the Oculus Browser on your Quest";
152
156
  button.addEventListener("click", () => {
153
157
  const urlParameter = encodeURIComponent(window.location.href);
@@ -175,6 +179,7 @@ export class WebXRButtonFactory {
175
179
  const qrCodeButton = document.createElement("button");
176
180
  this._qrButton = qrCodeButton;
177
181
  qrCodeButton.innerText = "QR Code";
182
+ qrCodeButton.prepend(getIconElement("qr_code"));
178
183
  qrCodeButton.title = "Scan this QR code with your phone to open this page";
179
184
  this.hideElementDuringXRSession(qrCodeButton);
180
185