Needle Engine

Changes between version 3.45.1-beta and 3.45.1-beta.1
Files changed (7) hide show
  1. plugins/vite/poster-client.js +0 -1
  2. src/engine-components/webxr/Avatar.ts +1 -1
  3. src/engine/engine_gizmos.ts +1 -0
  4. src/engine/engine_serialization_builtin_serializer.ts +1 -1
  5. src/engine/engine_three_utils.ts +1 -0
  6. src/engine-components/GroundProjection.ts +23 -2
  7. src/engine-components/OrbitControls.ts +2 -3
plugins/vite/poster-client.js CHANGED
@@ -17,7 +17,6 @@
17
17
  await new Promise((resolve) => setTimeout(resolve, 200));
18
18
 
19
19
  const mimeType = "image/webp";
20
- console.log("Generating poster...");
21
20
  const dataUrl = screenshot(context, width, height, mimeType);
22
21
 
23
22
  return dataUrl;
src/engine-components/webxr/Avatar.ts CHANGED
@@ -5,13 +5,13 @@
5
5
  import { serializable } from "../../engine/engine_serialization_decorator.js";
6
6
  import type { IGameObject } from "../../engine/engine_types.js";
7
7
  import { getParam, PromiseAllWithErrors } from "../../engine/engine_utils.js";
8
+ import { setCustomVisibility } from "../../engine/js-extensions/Layers.js";
8
9
  import { NeedleXRController, type NeedleXREventArgs, NeedleXRSession, NeedleXRUtils } from "../../engine/xr/api.js";
9
10
  import { PlayerState } from "../../engine-components-experimental/networking/PlayerSync.js";
10
11
  import { Behaviour, GameObject } from "../Component.js";
11
12
  import { SyncedTransform } from "../SyncedTransform.js";
12
13
  import { AvatarMarker } from "./WebXRAvatar.js";
13
14
  import { XRFlag } from "./XRFlag.js";
14
- import { setCustomVisibility } from "../../engine/js-extensions/Layers.js";
15
15
 
16
16
  const debug = getParam("debugwebxr");
17
17
 
src/engine/engine_gizmos.ts CHANGED
@@ -379,6 +379,7 @@
379
379
 
380
380
  object.renderOrder = 999999;
381
381
  object[$cacheSymbol] = cache;
382
+ object["isGizmo"] = true;
382
383
  this.timedObjectsBuffer.push(object);
383
384
 
384
385
  // Ensure if duration is 0 it is rendered for one frame only
src/engine/engine_serialization_builtin_serializer.ts CHANGED
@@ -60,7 +60,7 @@
60
60
  super([Euler], "EulerSerializer");
61
61
  }
62
62
  onDeserialize(data: any, _context: SerializationContext) {
63
- if (data === undefined || data === null) return;
63
+ if (data === undefined || data === null) return undefined;
64
64
  if (data.order) {
65
65
  return new Euler(data.x, data.y, data.z, data.order);
66
66
  }
src/engine/engine_three_utils.ts CHANGED
@@ -504,6 +504,7 @@
504
504
  if (obj instanceof GridHelper) allowExpanding = false;
505
505
  // ignore GroundProjectedEnv
506
506
  if (obj instanceof GroundedSkybox) allowExpanding = false;
507
+ if ((obj as any).isGizmo === true) allowExpanding = false;
507
508
  // // Ignore shadow catcher geometry
508
509
  if ((obj as Mesh).material instanceof ShadowMaterial) allowExpanding = false;
509
510
  // ONLY fit meshes
src/engine-components/GroundProjection.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { Texture } from "three";
1
+ import { Texture, Vector3 } from "three";
2
2
  import { GroundedSkybox as GroundProjection } from 'three/examples/jsm/objects/GroundedSkybox.js';
3
3
 
4
4
  import { serializable } from "../engine/engine_serialization_decorator.js";
5
5
  import { getParam, Watch as Watch } from "../engine/engine_utils.js";
6
6
  import { Behaviour } from "./Component.js";
7
+ import { getBoundingBox, getWorldPosition, setWorldPosition } from "../engine/engine_three_utils.js";
7
8
 
8
9
  const debug = getParam("debuggroundprojection");
9
10
 
@@ -16,6 +17,12 @@
16
17
  applyOnAwake: boolean = false;
17
18
 
18
19
  /**
20
+ * When enabled the position of the projected environment will be adjusted to be centered in the scene (and ground level).
21
+ */
22
+ @serializable()
23
+ autoFit: boolean = true;
24
+
25
+ /**
19
26
  * Radius of the projection sphere. Set it large enough so the camera stays inside (make sure the far plane is also large enough)
20
27
  */
21
28
  @serializable()
@@ -93,19 +100,33 @@
93
100
  this._projection?.removeFromParent();
94
101
  return;
95
102
  }
103
+ const offset = .01;
96
104
  if (!this._projection || this.context.scene.environment !== this._lastEnvironment || this._height !== this._lastHeight || this._radius !== this._lastRadius) {
97
105
  if (debug)
98
106
  console.log("Create/Update Ground Projection", this.context.scene.environment.name);
99
107
  this._projection?.removeFromParent();
100
108
  this._projection = new GroundProjection(this.context.scene.environment, this._height, this.radius);
101
- this._projection.position.y = this._height - .0001;
109
+ this._projection.position.y = this._height - offset;
102
110
  }
111
+
103
112
  this._lastEnvironment = this.context.scene.environment;
104
113
  this._lastHeight = this._height;
105
114
  this._lastRadius = this._radius;
106
115
  if (!this._projection.parent)
107
116
  this.gameObject.add(this._projection);
108
117
 
118
+ if (this.autoFit) {
119
+ // TODO: should also update the radius (?)
120
+ this._projection.updateWorldMatrix(true, true);
121
+ const scenebounds = getBoundingBox(this.context.scene.children, [this._projection]);
122
+ let floor_y = scenebounds.min.y;
123
+ const wp = getWorldPosition(this._projection);
124
+ wp.x = scenebounds.min.x + (scenebounds.max.x - scenebounds.min.x) * .5;
125
+ wp.y = floor_y + this._height - offset;
126
+ wp.z = scenebounds.min.z + (scenebounds.max.z - scenebounds.min.z) * .5;
127
+ setWorldPosition(this._projection, wp);
128
+ }
129
+
109
130
  /* TODO realtime adjustments aren't possible anymore with GroundedSkybox (mesh generation)
110
131
  this.env.scale.setScalar(this._scale);
111
132
  this.env.radius = this._radius;
src/engine-components/OrbitControls.ts CHANGED
@@ -243,21 +243,18 @@
243
243
  private _afterHandleInputFn?: any;
244
244
  private _camera: Camera | null = null;
245
245
  private _syncedTransform?: SyncedTransform;
246
- private _didStart = false;
247
246
  private _didSetTarget = 0;
248
247
 
249
248
  targetElement: HTMLElement | null = null;
250
249
 
251
250
  /** @internal */
252
251
  awake(): void {
253
- this._didStart = false;
254
252
  this._didSetTarget = 0;
255
253
  this._startedListeningToKeyEvents = false;
256
254
  }
257
255
 
258
256
  /** @internal */
259
257
  start() {
260
- this._didStart = true;
261
258
  this._eventSystem = EventSystem.get(this.context) ?? undefined;
262
259
  if (this._eventSystem) {
263
260
  this._afterHandleInputFn = this.afterHandleInput.bind(this);
@@ -547,6 +544,8 @@
547
544
  }
548
545
 
549
546
  if (this.autoFit) {
547
+ // we don't want to autofit again if the component is disabled and re-enabled
548
+ this.autoFit = false;
550
549
  this.fitCamera(this.scene.children, {
551
550
  centerCamera: "y",
552
551
  immediate: true,