@needle-tools/engine 4.10.0-next.2abafea → 4.10.0-next.4f9d92a

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.
Files changed (31) hide show
  1. package/dist/{needle-engine.bundle-p_i5rc9e.js → needle-engine.bundle-BeZ_xmJa.js} +5346 -5375
  2. package/dist/{needle-engine.bundle-COzW_KEf.min.js → needle-engine.bundle-C3bpSNYu.min.js} +132 -132
  3. package/dist/{needle-engine.bundle-7QhMyR9L.umd.cjs → needle-engine.bundle-D4dO0t5I.umd.cjs} +128 -128
  4. package/dist/needle-engine.js +14 -15
  5. package/dist/needle-engine.min.js +1 -1
  6. package/dist/needle-engine.umd.cjs +1 -1
  7. package/lib/engine/engine_lightdata.d.ts +3 -3
  8. package/lib/engine/engine_lightdata.js +10 -10
  9. package/lib/engine/engine_lightdata.js.map +1 -1
  10. package/lib/engine/engine_physics_rapier.js +0 -4
  11. package/lib/engine/engine_physics_rapier.js.map +1 -1
  12. package/lib/engine/engine_scenelighting.d.ts +1 -1
  13. package/lib/engine/engine_scenelighting.js +5 -4
  14. package/lib/engine/engine_scenelighting.js.map +1 -1
  15. package/lib/engine/engine_utils.d.ts +1 -3
  16. package/lib/engine/engine_utils.js +0 -11
  17. package/lib/engine/engine_utils.js.map +1 -1
  18. package/lib/engine/webcomponents/needle-engine.js +0 -4
  19. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  20. package/lib/engine-components/Skybox.js +4 -22
  21. package/lib/engine-components/Skybox.js.map +1 -1
  22. package/lib/engine-components/web/ScrollFollow.js +70 -80
  23. package/lib/engine-components/web/ScrollFollow.js.map +1 -1
  24. package/package.json +1 -1
  25. package/src/engine/engine_lightdata.ts +11 -11
  26. package/src/engine/engine_physics_rapier.ts +0 -3
  27. package/src/engine/engine_scenelighting.ts +6 -5
  28. package/src/engine/engine_utils.ts +0 -12
  29. package/src/engine/webcomponents/needle-engine.ts +0 -4
  30. package/src/engine-components/Skybox.ts +7 -26
  31. package/src/engine-components/web/ScrollFollow.ts +70 -82
@@ -381,14 +381,6 @@ export function resolveUrl(source: SourceIdentifier | undefined, uri: string): s
381
381
  }
382
382
  return uri;
383
383
  }
384
-
385
- export function toSourceId(src: string | null): SourceIdentifier | undefined {
386
- if (!src) return undefined;
387
- src = src.trim();
388
- src = src.split("?")[0]?.split("#")[0];
389
- return src;
390
- }
391
-
392
384
  // export function getPath(glbLocation: SourceIdentifier | undefined, path: string) {
393
385
  // if (path && glbLocation && !path.includes("/")) {
394
386
  // // get directory of glb and prepend it to the audio file path
@@ -801,7 +793,6 @@ const mutationObserverMap = new WeakMap<HTMLElement, HtmlElementExtra>();
801
793
  /**
802
794
  * Register a callback when an {@link HTMLElement} attribute changes.
803
795
  * This is used, for example, by the Skybox component to watch for changes to the environment-* and skybox-* attributes.
804
- * @returns A function that can be used to unregister the callback
805
796
  */
806
797
  export function addAttributeChangeCallback(domElement: HTMLElement, name: string, callback: AttributeChangeCallback) {
807
798
  if (!mutationObserverMap.get(domElement)) {
@@ -820,9 +811,6 @@ export function addAttributeChangeCallback(domElement: HTMLElement, name: string
820
811
  listeners.set(name, []);
821
812
  }
822
813
  listeners.get(name)!.push(callback);
823
- return () => {
824
- removeAttributeChangeCallback(domElement, name, callback);
825
- }
826
814
  };
827
815
 
828
816
  /**
@@ -570,10 +570,6 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
570
570
  this._context.renderer.setClearColor(rgbaColor, rgbaColor.alpha);
571
571
  this.context.scene.background = null;
572
572
  }
573
- // HACK: if we set background-color to a color and then back to null we want the background-image attribute to re-apply
574
- else if(this.getAttribute("background-image")) {
575
- this.setAttribute("background-image", this.getAttribute("background-image")!);
576
- }
577
573
  }
578
574
  }
579
575
 
@@ -8,7 +8,7 @@ import { syncField } from "../engine/engine_networking_auto.js";
8
8
  import { loadPMREM } from "../engine/engine_pmrem.js";
9
9
  import { serializable } from "../engine/engine_serialization_decorator.js";
10
10
  import { type IContext } from "../engine/engine_types.js";
11
- import { addAttributeChangeCallback, getParam, PromiseAllWithErrors, removeAttributeChangeCallback, toSourceId } from "../engine/engine_utils.js";
11
+ import { addAttributeChangeCallback, getParam, PromiseAllWithErrors, removeAttributeChangeCallback } from "../engine/engine_utils.js";
12
12
  import { registerObservableAttribute } from "../engine/webcomponents/needle-engine.extras.js";
13
13
  import { Camera, ClearFlags } from "./Camera.js";
14
14
  import { Behaviour, GameObject } from "./Component.js";
@@ -27,34 +27,15 @@ function createRemoteSkyboxComponent(context: IContext, url: string, skybox: boo
27
27
  }
28
28
 
29
29
  const remote = new RemoteSkybox();
30
- remote.sourceId = toSourceId(url);
31
30
  remote.allowDrop = false;
32
31
  remote.allowNetworking = false;
33
32
  remote.background = skybox;
34
33
  remote.environment = environment;
35
34
  GameObject.addComponent(context.scene, remote);
36
35
  const urlChanged = newValue => {
37
- if (debug) console.log(attribute, "CHANGED TO", newValue);
38
- if (newValue) {
39
- if (typeof newValue !== "string") {
40
- console.warn("Invalid attribute value for " + attribute);
41
- return;
42
- }
43
- remote.setSkybox(newValue);
44
- }
45
- else {
46
- if (remote.sourceId) {
47
- if (environment) {
48
- if (!context.sceneLighting.internalEnableReflection(remote.sourceId)) {
49
- context.scene.environment = null;
50
- }
51
- }
52
- if (skybox) {
53
- const skybox = context.lightmaps.tryGetSkybox(remote.sourceId);
54
- context.scene.background = skybox;
55
- }
56
- }
57
- }
36
+ if (typeof newValue !== "string") return;
37
+ if (debug) console.log(attribute, "CHANGED TO", newValue)
38
+ remote.setSkybox(newValue);
58
39
  };
59
40
  addAttributeChangeCallback(context.domElement, attribute, urlChanged);
60
41
  remote.addEventListener("destroy", () => {
@@ -69,7 +50,7 @@ ContextRegistry.registerCallback(ContextEvent.ContextCreationStart, (args) => {
69
50
  const context = args.context;
70
51
  const backgroundImage = context.domElement.getAttribute("background-image");
71
52
  const environmentImage = context.domElement.getAttribute("environment-image");
72
-
53
+
73
54
  if (backgroundImage) {
74
55
  if (debug) console.log("Creating RemoteSkybox to load background " + backgroundImage);
75
56
  // if the user is loading a GLB without a camera then the CameraUtils (which creates the default camera)
@@ -265,8 +246,8 @@ export class RemoteSkybox extends Behaviour {
265
246
  envMap.needsUpdate = true;
266
247
  }
267
248
 
268
- if (this.destroyed) return;
269
- if (!this.context) {
249
+ if(this.destroyed) return;
250
+ if(!this.context) {
270
251
  console.warn("RemoteSkybox: Context is not available - can not apply skybox.");
271
252
  return;
272
253
  }
@@ -4,11 +4,10 @@ import { element } from "three/src/nodes/TSL.js";
4
4
  import { Context } from "../../engine/engine_context.js";
5
5
  import { Mathf } from "../../engine/engine_math.js";
6
6
  import { serializable } from "../../engine/engine_serialization.js";
7
- import { getBoundingBox, setVisibleInCustomShadowRendering } from "../../engine/engine_three_utils.js";
7
+ import { getBoundingBox } from "../../engine/engine_three_utils.js";
8
8
  import { getParam } from "../../engine/engine_utils.js";
9
9
  import { Animation } from "../Animation.js";
10
10
  import { Animator } from "../Animator.js";
11
- import { MarkerTrackHandler } from "../api.js";
12
11
  import { AudioSource } from "../AudioSource.js";
13
12
  import { Behaviour } from "../Component.js";
14
13
  import { EventList } from "../EventList.js";
@@ -309,17 +308,17 @@ export class ScrollFollow extends Behaviour {
309
308
  try {
310
309
  marker.element = tryGetElementsForSelector(index, marker.name) as HTMLElement | null;
311
310
  if (debug) console.debug("ScrollMarker found on page", marker.element, marker.name);
312
- if (!marker.element) {
313
- marker.timeline = undefined;
314
- continue;
315
- }
316
- else {
317
- /** @ts-ignore */
318
- marker.timeline = new ViewTimeline({
319
- subject: marker.element,
320
- axis: 'block', // https://drafts.csswg.org/scroll-animations/#scroll-notation
321
- });
322
- }
311
+ // if (!marker.element) {
312
+ // marker.timeline = undefined;
313
+ // continue;
314
+ // }
315
+ // else {
316
+ // /** @ts-ignore */
317
+ // marker.timeline = new ViewTimeline({
318
+ // subject: marker.element,
319
+ // axis: 'block', // https://drafts.csswg.org/scroll-animations/#scroll-notation
320
+ // });
321
+ // }
323
322
  }
324
323
  catch (error) {
325
324
  marker.element = null;
@@ -350,74 +349,57 @@ export class ScrollFollow extends Behaviour {
350
349
 
351
350
  weightsArray.length = 0;
352
351
  let sum = 0;
353
- const oneFrameTime = 1 / 60;
354
352
 
355
353
  // We keep a separate count here in case there are some markers that could not be resolved so point to *invalid* elements - the timeline should fallback to 0-1 scroll behaviour then
356
354
  let markerCount = 0;
357
- for (let i = 0; i < markersArray.length; i++) {
358
- const marker = markersArray[i];
359
- if (!marker.element) continue;
360
- const nextMarker = markersArray[i + 1];
355
+ for (const marker of markersArray) {
361
356
 
362
- const nextTime = nextMarker
363
- ? (nextMarker.time - oneFrameTime)
364
- : duration;
357
+ if (!marker.element) continue;
365
358
 
366
359
  markerCount += 1;
367
360
 
368
- const timeline = marker.timeline;
369
- if (timeline) {
370
- const time01 = calculateTimelinePositionNormalized(timeline);
371
- // remap 0-1 to 0 - 1 - 0 (full weight at center)
372
- const weight = 1 - Math.abs(time01 - 0.5) * 2;
373
- if (time01 > 0 && time01 <= 1) {
374
- const lerpTime = marker.time + (nextTime - marker.time) * time01;
375
- weightsArray.push({ time: lerpTime, weight: weight });
376
- sum += weight;
377
- }
378
- // Before the first marker is reached
379
- else if (i === 0 && time01 <= 0) {
380
- weightsArray.push({ time: 0, weight: 1 });
381
- sum += 1;
382
- }
383
- // After the last marker is reached
384
- else if (i === markersArray.length - 1 && time01 >= 1) {
385
- weightsArray.push({ time: duration, weight: 1 });
386
- sum += 1;
387
- }
388
- }
389
- continue;
361
+ // const timeline = marker.timeline;
362
+ // if (timeline) {
363
+ // const time01 = calculateTimelinePositionNormalized(timeline);
364
+ // if (time01 > 0 && time01 <= 1) {
365
+ // const overlap = calculateTimelinePositionNormalized(timeline!);
366
+ // const weight = overlap;
367
+ // // console.log(marker.element.className, time01)
368
+ // weightsArray.push({ time: marker.time, weight: weight });
369
+ // sum += weight;
370
+ // }
371
+ // }
372
+ // continue;
390
373
  // if(this.context.time.frame % 10 === 0) console.log(marker.element?.className, timeline, calculateTimelinePositionNormalized(timeline!));
391
374
 
392
- // const top = marker.element.offsetTop - this._scrollContainerHeight;
393
- // const height = marker.element.offsetHeight + this._scrollContainerHeight;
394
- // const bottom = top + height;
395
- // let overlap = 0;
375
+ const top = marker.element.offsetTop;
376
+ const height = marker.element.offsetHeight;
377
+ const bottom = top + height;
378
+ let overlap = 0;
396
379
 
397
- // // TODO: if we have two marker sections where no HTML overlaps (vor example because some large section is between them) we probably want to still virtually interpolate between them slowly in that region
380
+ // TODO: if we have two marker sections where no HTML overlaps (vor example because some large section is between them) we probably want to still virtually interpolate between them slowly in that region
398
381
 
399
- // if (bottom < currentTop) {
400
- // // marker is above scroll region
401
- // overlap = 0;
402
- // }
403
- // else if (top > currentBottom) {
404
- // // marker is below scroll region
405
- // overlap = 0;
406
- // }
407
- // else {
408
- // // calculate overlap in pixels
409
- // const overlapTop = Math.max(top, currentTop);
410
- // const overlapBottom = Math.min(bottom, currentBottom);
411
- // const height = Math.max(1, currentBottom - currentTop);
412
- // overlap = Math.max(0, overlapBottom - overlapTop);
413
- // }
382
+ if (bottom < currentTop) {
383
+ // marker is above scroll region
384
+ overlap = 0;
385
+ }
386
+ else if (top > currentBottom) {
387
+ // marker is below scroll region
388
+ overlap = 0;
389
+ }
390
+ else {
391
+ // calculate overlap in pixels
392
+ const overlapTop = Math.max(top, currentTop);
393
+ const overlapBottom = Math.min(bottom, currentBottom);
394
+ overlap = Math.max(0, overlapBottom - overlapTop);
395
+ }
414
396
 
415
- // // if(this.context.time.frame % 20 === 0) console.log(overlap)
397
+ markerCount += 1;
416
398
 
417
- // if (overlap > 0) {
418
- // weightsArray.push({ time: marker.time, weight: overlap });
419
- // sum += overlap;
420
- // }
399
+ if (overlap > 0) {
400
+ weightsArray.push({ time: marker.time, weight: overlap });
401
+ sum += overlap;
402
+ }
421
403
  }
422
404
 
423
405
  if (weightsArray.length <= 0 && markerCount <= 0) {
@@ -425,23 +407,19 @@ export class ScrollFollow extends Behaviour {
425
407
  }
426
408
  else if (weightsArray.length > 0) {
427
409
  // normalize and calculate weighted time
428
- let time = weightsArray[0].time; // fallback to first time
429
- if (weightsArray.length > 1) {
430
- for (const entry of weightsArray) {
431
- const weight = entry.weight / Math.max(0.00001, sum);
432
- // console.log(weight.toFixed(2))
433
- // lerp time based on weight
434
- const diff = Math.abs(entry.time - time);
435
- time += diff * weight;
436
- }
410
+ let time = 0;
411
+ for (const entry of weightsArray) {
412
+ const weight = entry.weight / Math.max(0.00001, sum);
413
+ // console.log(weight.toFixed(2))
414
+ // lerp time based on weight
415
+ const diff = Math.abs(entry.time - time);
416
+ time += diff * weight;
437
417
  }
438
- if (this.context.time.frame % 20 === 0) console.log(time.toFixed(3), [...weightsArray])
439
- if (this.damping <= 0) {
418
+ // console.log(time.toFixed(2), [...weightsArray])
419
+ if (this.damping <= 0)
440
420
  director.time = time;
441
- }
442
- else {
421
+ else
443
422
  director.time = Mathf.lerp(director.time, time, this.context.time.deltaTime / this.damping);
444
- }
445
423
  }
446
424
  }
447
425
 
@@ -528,6 +506,16 @@ function calculateTimelinePositionNormalized(timeline: ViewTimeline) {
528
506
  const t01 = currentTime.unit === "seconds" ? (currentTime.value / durationValue) : (currentTime.value / 100);
529
507
  return t01;
530
508
  }
509
+ function calculateNormalizedOverlap(timeline: ViewTimeline) {
510
+ if (!timeline.source) return 0;
511
+ const start = timeline.startOffset;
512
+ const end = timeline.endOffset;
513
+ const total = start.value + end.value;
514
+ if (total <= 0) return 1;
515
+ const startNorm = start.value / total;
516
+ const endNorm = end.value / total;
517
+ return 1 - (startNorm + endNorm);
518
+ }
531
519
 
532
520
 
533
521
  declare global {