Needle Engine

Changes between version 3.34.3-alpha.1 and 3.34.4-alpha
Files changed (4) hide show
  1. src/engine-components/Camera.ts +1 -1
  2. src/engine-components/OrbitControls.ts +40 -38
  3. src/engine-components/webxr/WebXR.ts +0 -5
  4. src/engine-components/webxr/WebXRButtons.ts +6 -1
src/engine-components/Camera.ts CHANGED
@@ -335,7 +335,7 @@
335
335
 
336
336
  if (debug) {
337
337
  const msg = `Camera \"${this.name}\" clear flags: ${ClearFlags[this._clearFlags]}`;
338
- console.log(msg);
338
+ console.debug(msg);
339
339
  }
340
340
  switch (this._clearFlags) {
341
341
  case ClearFlags.Skybox:
src/engine-components/OrbitControls.ts CHANGED
@@ -155,46 +155,18 @@
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 @@
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 @@
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,7 +378,37 @@
406
378
 
407
379
  }
408
380
 
381
+ private __handleSetTargetWhenBecomingActiveTheFirstTime() {
382
+ if (this._didSetTarget) return;
383
+ this._didSetTarget = true;
384
+ if (this.autoTarget) {
409
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
+
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
412
414
  */
src/engine-components/webxr/WebXR.ts CHANGED
@@ -279,19 +279,16 @@
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 @@
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 @@
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
  });
src/engine-components/webxr/WebXRButtons.ts CHANGED
@@ -2,6 +2,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);