@needle-tools/engine 4.11.5-next.ca8b86d → 4.11.5

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.
@@ -37,7 +37,7 @@ import { RendererData as SceneLighting } from './engine_scenelighting.js';
37
37
  import { getTempColor, logHierarchy } from './engine_three_utils.js';
38
38
  import { Time } from './engine_time.js';
39
39
  import { patchTonemapping } from './engine_tonemapping.js';
40
- import type { CoroutineData, ICamera, IComponent, IContext, ILight, LoadedModel, Model, Vec2 } from "./engine_types.js";
40
+ import type { CoroutineData, ICamera, IComponent, IContext, ILight, LoadedModel, Model, SourceIdentifier, Vec2 } from "./engine_types.js";
41
41
  import { deepClone, delay, DeviceUtilities, getParam } from './engine_utils.js';
42
42
  import type { INeedleXRSessionEventReceiver, NeedleXRSession } from './engine_xr.js';
43
43
  import { NeedleMenu } from './webcomponents/needle menu/needle-menu.js';
@@ -372,6 +372,7 @@ export class Context implements IContext {
372
372
  */
373
373
  composer: EffectComposer | ThreeEffectComposer | null = null;
374
374
 
375
+ // #region internal script lists
375
376
  /**
376
377
  * @internal All known components. Don't use directly
377
378
  */
@@ -439,6 +440,9 @@ export class Context implements IContext {
439
440
  /** @internal */
440
441
  readonly new_scripts_xr: INeedleXRSessionEventReceiver[] = [];
441
442
 
443
+ // #endregion
444
+ // #region Properties
445
+
442
446
  /**
443
447
  * The **main camera component** of the scene - this camera is used for rendering.
444
448
  * Use `setCurrentCamera` for updating the main camera.
@@ -483,25 +487,36 @@ export class Context implements IContext {
483
487
  physics: Physics;
484
488
  /** access networking methods (use it to send or listen to messages or join a networking backend) */
485
489
  connection: NetworkConnection;
486
- /**
487
- * @deprecated AssetDataBase is deprecated
488
- */
490
+ /** @deprecated AssetDatabase is deprecated */
489
491
  assets: AssetDatabase;
490
492
  /** The main light in the scene */
491
493
  mainLight: ILight | null = null;
492
494
  /** @deprecated Use sceneLighting */
493
495
  get rendererData() { return this.sceneLighting }
496
+ /** Access the scene lighting manager to control lighting settings in the context */
494
497
  sceneLighting: SceneLighting;
495
498
  addressables: Addressables;
496
499
  lightmaps: ILightDataRegistry;
497
500
  players: PlayerViewManager;
501
+
502
+ /** Access the LODs manager to control LOD behavior in the context */
498
503
  readonly lodsManager: LODsManager;
499
504
  /** Access the needle menu to add or remove buttons to the menu element */
500
505
  readonly menu: NeedleMenu;
501
506
 
502
- /** @returns true if the context is fully created and ready */
507
+ /**
508
+ * Checks if the context is fully created and ready
509
+ * @returns true if the context is fully created and ready
510
+ */
503
511
  get isCreated() { return this._isCreated; }
504
512
 
513
+ /**
514
+ * The source identifier(s) of the root scene(s) loaded into this context.
515
+ * When using `<needle-engine>` web component this will be the `src` attribute(s).
516
+ * @returns The source identifier for of the root scene
517
+ */
518
+ get rootSourceId(): SourceIdentifier | undefined { return this.rootSceneSourceIdentifiers[0] || undefined; }
519
+
505
520
  private _needsUpdateSize: boolean = false;
506
521
  private _isCreated: boolean = false;
507
522
  private _isCreating: boolean = false;
@@ -556,6 +571,7 @@ export class Context implements IContext {
556
571
  ContextRegistry.register(this);
557
572
  }
558
573
 
574
+ // #region Renderer
559
575
  /**
560
576
  * Calling this function will dispose the current renderer and create a new one which will then be assigned to the context. It can be used to create a new renderer with custom WebGLRendererParameters.
561
577
  * **Note**: Instead you can also modify the static `Context.DefaultWebGlRendererParameters` before the context is created.
@@ -909,6 +925,7 @@ export class Context implements IContext {
909
925
  }
910
926
  }
911
927
 
928
+ // #region onBeforeRender / onAfterRender listeners
912
929
  private readonly _onBeforeRenderListeners = new Map<string, OnRenderCallback[]>();
913
930
  private readonly _onAfterRenderListeners = new Map<string, OnRenderCallback[]>();
914
931
 
@@ -1006,6 +1023,8 @@ export class Context implements IContext {
1006
1023
  private _lastStyleComputedResult: boolean | undefined = undefined;
1007
1024
 
1008
1025
  private _createId: number = 0;
1026
+
1027
+ // #region internal create
1009
1028
  private async internalOnCreate(opts?: ContextCreateArgs): Promise<boolean> {
1010
1029
  const createId = ++this._createId;
1011
1030
 
@@ -1215,6 +1234,11 @@ export class Context implements IContext {
1215
1234
  if (opts?.abortSignal?.aborted) {
1216
1235
  return false;
1217
1236
  }
1237
+
1238
+
1239
+ const mainIdentifier = this.rootSourceId;
1240
+ if (mainIdentifier) this.sceneLighting.enable(mainIdentifier);
1241
+
1218
1242
  invokeLifecycleFunctions(this, ContextEvent.ContextCreated);
1219
1243
  if (debug) console.log("Context Created...", this.renderer, this.renderer.domElement)
1220
1244
 
@@ -1224,13 +1248,18 @@ export class Context implements IContext {
1224
1248
  return true;
1225
1249
  }
1226
1250
 
1251
+
1252
+ private readonly rootSceneSourceIdentifiers: SourceIdentifier[] = [];
1227
1253
  private async internalLoadInitialContent(createId: number, args: ContextCreateArgs): Promise<Array<LoadedModel>> {
1254
+ this.rootSceneSourceIdentifiers.length = 0;
1255
+
1228
1256
  const results = new Array<LoadedModel>();
1229
1257
  // early out if we dont have any files to load
1230
1258
  if (args.files.length === 0) return results;
1231
1259
 
1232
-
1233
1260
  const files = [...args.files];
1261
+ this.rootSceneSourceIdentifiers.push(...files);
1262
+
1234
1263
  const progressArg: LoadingProgressArgs = {
1235
1264
  name: "",
1236
1265
  progress: null!,
@@ -1238,6 +1267,7 @@ export class Context implements IContext {
1238
1267
  count: files.length
1239
1268
  }
1240
1269
 
1270
+
1241
1271
  const loader = getLoader();
1242
1272
  // this hash should be constant since it is used to initialize the UIDProvider per initially loaded scene
1243
1273
  const loadingHash = 0;
@@ -1,4 +1,4 @@
1
- import { EquirectangularReflectionMapping, LightProbe, SphericalHarmonics3, SRGBColorSpace,Texture, Vector4, WebGLCubeRenderTarget } from "three";
1
+ import { EquirectangularReflectionMapping, LightProbe, Source, SphericalHarmonics3, SRGBColorSpace, Texture, Vector4, WebGLCubeRenderTarget } from "three";
2
2
 
3
3
  import { AssetReference } from "./engine_addressables.js";
4
4
  import { Context } from "./engine_setup.js";
@@ -44,9 +44,16 @@ export class RendererData {
44
44
  this.context.pre_update_callbacks.push(this.preUpdate.bind(this))
45
45
  }
46
46
 
47
+ /**
48
+ * The id of the currently active scene light settings (source identifier).
49
+ */
47
50
  private _currentLightSettingsId?: SourceIdentifier;
48
51
  private _sceneLightSettings?: Map<SourceIdentifier, SceneLightSettings>;
49
52
 
53
+ get currentLightSettingsId(): SourceIdentifier | undefined {
54
+ return this._currentLightSettingsId;
55
+ }
56
+
50
57
  private preUpdate() {
51
58
  const time = this.context.time;
52
59
  this._timevec4.x = time.time;
@@ -82,11 +89,11 @@ export class RendererData {
82
89
 
83
90
  /** set the scene lighting from a specific scene. Will disable any previously enabled lighting settings */
84
91
  enable(sourceId: SourceIdentifier | AssetReference) {
85
- if(sourceId instanceof AssetReference)
92
+ if (sourceId instanceof AssetReference)
86
93
  sourceId = sourceId.url;
87
94
  const settings = this._sceneLightSettings?.get(sourceId);
88
95
  if (!settings) {
89
- if(debug) console.warn("No light settings found for", sourceId);
96
+ if (debug) console.warn("No light settings found for", sourceId);
90
97
  return false;
91
98
  }
92
99
  if (debug) console.log("Enable scene light settings", sourceId, settings);
@@ -100,7 +107,7 @@ export class RendererData {
100
107
 
101
108
  /** disable the lighting of a specific scene, will only have any effect if it is currently active */
102
109
  disable(sourceId: SourceIdentifier | AssetReference) {
103
- if(sourceId instanceof AssetReference)
110
+ if (sourceId instanceof AssetReference)
104
111
  sourceId = sourceId.url;
105
112
  if (sourceId === null || sourceId === undefined) return false;
106
113
  const settings = this._sceneLightSettings?.get(sourceId);
@@ -112,8 +119,22 @@ export class RendererData {
112
119
  return true;
113
120
  }
114
121
 
115
- /** Disables the currently active scene lighting (if any), returns the id of the previously active lighting */
116
- disableCurrent() : SourceIdentifier | null {
122
+ /**
123
+ * Enables the currently active scene lighting (if any), returns the id of the enabled lighting.
124
+ * @returns The id of the enabled lighting, or null if no lighting is currently active.
125
+ */
126
+ enableCurrent(): SourceIdentifier | null {
127
+ if (this._currentLightSettingsId) {
128
+ this.enable(this._currentLightSettingsId);
129
+ return this._currentLightSettingsId ?? null;
130
+ }
131
+ return null;
132
+ }
133
+
134
+ /** Disables the currently active scene lighting (if any), returns the id of the previously active lighting
135
+ * @returns The id of the previously active lighting, or null if no lighting was active.
136
+ */
137
+ disableCurrent(): SourceIdentifier | null {
117
138
  if (this._currentLightSettingsId) {
118
139
  const prev = this._currentLightSettingsId;
119
140
  this.disable(this._currentLightSettingsId);
@@ -162,7 +183,7 @@ export class RendererData {
162
183
  private __currentReflectionId: SourceIdentifier | null = null;
163
184
 
164
185
  /** @internal */
165
- internalEnableReflection(sourceId: SourceIdentifier) : Texture | null {
186
+ internalEnableReflection(sourceId: SourceIdentifier): Texture | null {
166
187
  this.__currentReflectionId = sourceId;
167
188
  const settings = this._sceneLightSettings?.get(sourceId);
168
189
 
@@ -181,6 +202,7 @@ export class RendererData {
181
202
  const tex = existing.Source;
182
203
  tex.mapping = EquirectangularReflectionMapping;
183
204
  scene.environment = tex;
205
+ scene.environmentIntensity = this.environmentIntensity || 1;
184
206
  return tex;
185
207
  }
186
208
  else if (debug) console.warn("Could not find reflection for source", sourceId);
@@ -216,7 +238,7 @@ export class RendererData {
216
238
  /** @internal */
217
239
  internalDisableReflection(sourceId?: SourceIdentifier) {
218
240
  if (sourceId && sourceId !== this.__currentReflectionId) {
219
- if(debug) console.log("Not disabling reflection for", sourceId, "because it is not the current light settings id", this.__currentReflectionId)
241
+ if (debug) console.log("Not disabling reflection for", sourceId, "because it is not the current light settings id", this.__currentReflectionId)
220
242
  return;
221
243
  }
222
244
  if (debug) console.log("Disable reflection", sourceId)
@@ -1,4 +1,4 @@
1
- import { EquirectangularReflectionMapping, LinearSRGBColorSpace, Material, MeshBasicMaterial, Object3D, SRGBColorSpace, Texture, Vector3 } from "three";
1
+ import { CubeReflectionMapping, CubeTexture, EquirectangularReflectionMapping, LinearSRGBColorSpace, Material, MeshBasicMaterial, Object3D, SRGBColorSpace, Texture, Vector3 } from "three";
2
2
 
3
3
  import { isDevEnvironment, showBalloonWarning } from "../engine/debug/index.js";
4
4
  import { serializable } from "../engine/engine_serialization.js";
@@ -63,13 +63,19 @@ export class ReflectionProbe extends Behaviour {
63
63
 
64
64
  // @serializable(Texture)
65
65
  set texture(tex: Texture) {
66
- if (tex && !(tex instanceof Texture)) {
67
- console.error("ReflectionProbe.texture must be a Texture", tex);
68
- return;
69
- }
66
+
67
+ if (this._texture === tex) return;
70
68
  this._texture = tex;
69
+
70
+ if (debug) console.debug("[ReflectionProbe] Set reflection probe texture " + (tex?.name || "(removed)"));
71
+
71
72
  if (tex) {
72
- tex.mapping = EquirectangularReflectionMapping;
73
+ if (tex instanceof CubeTexture) {
74
+ // cube textures use CubeReflectionMapping by default
75
+ }
76
+ else if (tex.mapping !== EquirectangularReflectionMapping) {
77
+ tex.mapping = EquirectangularReflectionMapping;
78
+ }
73
79
  tex.colorSpace = LinearSRGBColorSpace;
74
80
  tex.needsUpdate = true;
75
81
  }
@@ -110,9 +116,8 @@ export class ReflectionProbe extends Behaviour {
110
116
  }
111
117
  }
112
118
  start(): void {
113
- if (!this._texture && isDevEnvironment()) {
119
+ if (!this._texture) {
114
120
  console.warn(`[ReflectionProbe] Missing texture. Please assign a custom cubemap texture. To use reflection probes assign them to your renderer's "anchor" property.`);
115
- showBalloonWarning("ReflectionProbe configuration hint: See browser console for details")
116
121
  }
117
122
  }
118
123
 
@@ -206,8 +211,11 @@ export class ReflectionProbe extends Behaviour {
206
211
  /** this is the material that we copied and that has the reflection probe */
207
212
  const copy = cached?.copy;
208
213
 
209
- // make sure the reflection probe is assigned
210
- copy["envMap"] = this.texture;
214
+ if ("envMap" in copy) {
215
+ // make sure the reflection probe is assigned
216
+ copy.envMap = this.texture;
217
+ copy.needsUpdate = true;
218
+ }
211
219
 
212
220
  _rend.sharedMaterials[i] = copy;
213
221
  }
@@ -702,7 +702,6 @@ export class Renderer extends Behaviour implements IRenderer {
702
702
  // If the material has a envMap and is NOT using a reflection probe we set the envMap to the scene environment
703
703
  if (mat && "envMap" in mat && "envMapIntensity" in mat && !ReflectionProbe.isUsingReflectionProbe(mat)) {
704
704
  mat.envMap = this.context.scene.environment;
705
- mat.envMapIntensity = this.context.scene.environmentIntensity;
706
705
  mat.envMapRotation = this.context.scene.environmentRotation;
707
706
  }
708
707
  }
@@ -713,8 +712,9 @@ export class Renderer extends Behaviour implements IRenderer {
713
712
  private onBeforeRenderThree = (_renderer, _scene, _camera, _geometry, material, _group) => {
714
713
  if (material.envMapIntensity !== undefined) {
715
714
  const factor = this.hasLightmap ? Math.PI : 1;
716
- const environmentIntensity = this.context.mainCameraComponent?.environmentIntensity ?? 1;
715
+ const environmentIntensity = this.context.scene.environmentIntensity;
717
716
  material.envMapIntensity = Math.max(0, environmentIntensity * this.context.sceneLighting.environmentIntensity / factor);
717
+ // console.log(this.context.sceneLighting.environmentIntensity);
718
718
  }
719
719
  if (this._lightmaps) {
720
720
  for (const lm of this._lightmaps) {