@needle-tools/engine 4.10.0-next.2abafea → 4.10.0-next.55c0bf9

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 (96) hide show
  1. package/components.needle.json +1 -1
  2. package/dist/{needle-engine.bundle-p_i5rc9e.js → needle-engine.bundle-CUo74dPe.js} +7011 -7222
  3. package/dist/{needle-engine.bundle-7QhMyR9L.umd.cjs → needle-engine.bundle-Cf5H9Zy9.umd.cjs} +141 -152
  4. package/dist/{needle-engine.bundle-COzW_KEf.min.js → needle-engine.bundle-DlAVTipB.min.js} +159 -170
  5. package/dist/needle-engine.js +257 -259
  6. package/dist/needle-engine.min.js +1 -1
  7. package/dist/needle-engine.umd.cjs +1 -1
  8. package/lib/engine/codegen/register_types.js +0 -2
  9. package/lib/engine/codegen/register_types.js.map +1 -1
  10. package/lib/engine/engine_camera.d.ts +1 -7
  11. package/lib/engine/engine_camera.fit.d.ts +1 -1
  12. package/lib/engine/engine_camera.fit.js +30 -3
  13. package/lib/engine/engine_camera.fit.js.map +1 -1
  14. package/lib/engine/engine_camera.js +6 -46
  15. package/lib/engine/engine_camera.js.map +1 -1
  16. package/lib/engine/engine_context.d.ts +0 -6
  17. package/lib/engine/engine_context.js +9 -48
  18. package/lib/engine/engine_context.js.map +1 -1
  19. package/lib/engine/engine_lightdata.d.ts +3 -3
  20. package/lib/engine/engine_lightdata.js +10 -10
  21. package/lib/engine/engine_lightdata.js.map +1 -1
  22. package/lib/engine/engine_physics_rapier.js +0 -4
  23. package/lib/engine/engine_physics_rapier.js.map +1 -1
  24. package/lib/engine/engine_scenelighting.d.ts +1 -1
  25. package/lib/engine/engine_scenelighting.js +5 -4
  26. package/lib/engine/engine_scenelighting.js.map +1 -1
  27. package/lib/engine/engine_utils.d.ts +1 -3
  28. package/lib/engine/engine_utils.js +0 -11
  29. package/lib/engine/engine_utils.js.map +1 -1
  30. package/lib/engine/extensions/NEEDLE_lightmaps.js +1 -1
  31. package/lib/engine/extensions/NEEDLE_lightmaps.js.map +1 -1
  32. package/lib/engine/webcomponents/logo-element.d.ts +1 -1
  33. package/lib/engine/webcomponents/logo-element.js +5 -29
  34. package/lib/engine/webcomponents/logo-element.js.map +1 -1
  35. package/lib/engine/webcomponents/needle menu/needle-menu.js +3 -4
  36. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  37. package/lib/engine/webcomponents/needle-engine.js +0 -4
  38. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  39. package/lib/engine/webcomponents/needle-engine.loading.d.ts +1 -0
  40. package/lib/engine/webcomponents/needle-engine.loading.js +36 -3
  41. package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
  42. package/lib/engine-components/OrbitControls.d.ts +1 -4
  43. package/lib/engine-components/OrbitControls.js +6 -30
  44. package/lib/engine-components/OrbitControls.js.map +1 -1
  45. package/lib/engine-components/Renderer.js +1 -6
  46. package/lib/engine-components/Renderer.js.map +1 -1
  47. package/lib/engine-components/Skybox.js +4 -22
  48. package/lib/engine-components/Skybox.js.map +1 -1
  49. package/lib/engine-components/codegen/components.d.ts +0 -1
  50. package/lib/engine-components/codegen/components.js +0 -1
  51. package/lib/engine-components/codegen/components.js.map +1 -1
  52. package/lib/engine-components/timeline/PlayableDirector.d.ts +0 -7
  53. package/lib/engine-components/timeline/PlayableDirector.js +0 -7
  54. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  55. package/lib/engine-components/timeline/TimelineModels.d.ts +1 -9
  56. package/lib/engine-components/timeline/TimelineTracks.js +2 -4
  57. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  58. package/lib/engine-components/utils/LookAt.js +1 -5
  59. package/lib/engine-components/utils/LookAt.js.map +1 -1
  60. package/lib/engine-components/web/Clickthrough.js +2 -10
  61. package/lib/engine-components/web/Clickthrough.js.map +1 -1
  62. package/lib/engine-components/web/ScrollFollow.d.ts +0 -22
  63. package/lib/engine-components/web/ScrollFollow.js +38 -159
  64. package/lib/engine-components/web/ScrollFollow.js.map +1 -1
  65. package/lib/engine-components/web/index.d.ts +0 -1
  66. package/lib/engine-components/web/index.js +0 -1
  67. package/lib/engine-components/web/index.js.map +1 -1
  68. package/package.json +1 -1
  69. package/src/engine/codegen/register_types.ts +0 -2
  70. package/src/engine/engine_camera.fit.ts +32 -2
  71. package/src/engine/engine_camera.ts +8 -62
  72. package/src/engine/engine_context.ts +10 -50
  73. package/src/engine/engine_lightdata.ts +11 -11
  74. package/src/engine/engine_physics_rapier.ts +0 -3
  75. package/src/engine/engine_scenelighting.ts +6 -5
  76. package/src/engine/engine_utils.ts +0 -12
  77. package/src/engine/extensions/NEEDLE_lightmaps.ts +1 -1
  78. package/src/engine/webcomponents/logo-element.ts +4 -29
  79. package/src/engine/webcomponents/needle menu/needle-menu.ts +3 -4
  80. package/src/engine/webcomponents/needle-engine.loading.ts +32 -32
  81. package/src/engine/webcomponents/needle-engine.ts +0 -4
  82. package/src/engine-components/OrbitControls.ts +1 -40
  83. package/src/engine-components/Renderer.ts +1 -6
  84. package/src/engine-components/Skybox.ts +7 -26
  85. package/src/engine-components/codegen/components.ts +0 -1
  86. package/src/engine-components/timeline/PlayableDirector.ts +0 -9
  87. package/src/engine-components/timeline/TimelineModels.ts +1 -9
  88. package/src/engine-components/timeline/TimelineTracks.ts +2 -4
  89. package/src/engine-components/utils/LookAt.ts +1 -5
  90. package/src/engine-components/web/Clickthrough.ts +2 -11
  91. package/src/engine-components/web/ScrollFollow.ts +44 -190
  92. package/src/engine-components/web/index.ts +1 -2
  93. package/lib/engine-components/web/ViewBox.d.ts +0 -16
  94. package/lib/engine-components/web/ViewBox.js +0 -186
  95. package/lib/engine-components/web/ViewBox.js.map +0 -1
  96. package/src/engine-components/web/ViewBox.ts +0 -202
@@ -358,11 +358,8 @@ export class Renderer extends Behaviour implements IRenderer {
358
358
  //@ts-ignore
359
359
  get sharedMaterials(): SharedMaterialArray {
360
360
 
361
- // @ts-ignore (original materials will be set during deserialization)
362
- if(this._originalMaterials === undefined) return null;
363
-
364
361
  // @ts-ignore during deserialization code might access this property *before* the setter and then create an empty array
365
- if (this.__isDeserializing === true) return null;
362
+ if (!this.__didAwake) return null;
366
363
 
367
364
  if (!this._sharedMaterials || !this._sharedMaterials.is(this)) {
368
365
  if (!this._originalMaterials) this._originalMaterials = [];
@@ -728,8 +725,6 @@ export class Renderer extends Behaviour implements IRenderer {
728
725
  // If the material has a envMap and is NOT using a reflection probe we set the envMap to the scene environment
729
726
  if (mat && "envMap" in mat && "envMapIntensity" in mat && !ReflectionProbe.isUsingReflectionProbe(mat)) {
730
727
  mat.envMap = this.context.scene.environment;
731
- mat.envMapIntensity = this.context.scene.environmentIntensity;
732
- mat.envMapRotation = this.context.scene.environmentRotation;
733
728
  }
734
729
  }
735
730
  }
@@ -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
  }
@@ -208,7 +208,6 @@ export { ClickThrough } from "../web/Clickthrough.js";
208
208
  export { CursorFollow } from "../web/CursorFollow.js";
209
209
  export { HoverAnimation } from "../web/HoverAnimation.js";
210
210
  export { ScrollFollow } from "../web/ScrollFollow.js";
211
- export { ViewBox } from "../web/ViewBox.js";
212
211
  export { Avatar } from "../webxr/Avatar.js";
213
212
  export { XRControllerFollow } from "../webxr/controllers/XRControllerFollow.js";
214
213
  export { XRControllerModel } from "../webxr/controllers/XRControllerModel.js";
@@ -66,19 +66,10 @@ export class PlayableDirector extends Behaviour {
66
66
  this.createTrackFunctions[type] = fn;
67
67
  }
68
68
 
69
- /**
70
- * The timeline asset that is played by this director.
71
- */
72
69
  playableAsset?: Models.TimelineAssetModel;
73
-
74
70
  /** Set to true to start playing the timeline when the scene starts */
75
71
  @serializable()
76
72
  playOnAwake?: boolean;
77
-
78
- /**
79
- * Determines how the timeline behaves when it reaches the end of its duration.
80
- * @default DirectorWrapMode.Loop
81
- */
82
73
  @serializable()
83
74
  extrapolationMode: DirectorWrapMode = DirectorWrapMode.Loop;
84
75
 
@@ -92,12 +92,4 @@ export declare class SignalMarkerModel extends MarkerModel {
92
92
  asset: string;
93
93
  }
94
94
 
95
- /**
96
- * Marker with a name, used for scroll-driven timelines. It is used together with elements in your HTML to define what time in the timeline should be active when the element is in the scroll view.
97
- *
98
- * @example Mark html elements to define scroll positions
99
- * ```html
100
- * <div data-timeline-marker>...</div>
101
- * ```
102
- */
103
- export type ScrollMarkerModel = MarkerModel & { name: string };
95
+ export type ScrollMarkerModel = MarkerModel & { selector: string };
@@ -175,10 +175,8 @@ export class AnimationTrackHandler extends TrackHandler {
175
175
  // which means we want to notify the object that it's not animated anymore
176
176
  // and the animator can then take over
177
177
  onStateChanged() {
178
- if (this._animator) {
179
- // We can not check the *isPlaying* state here because the timeline might be paused and evaluated by e.g. ScrollFollow
180
- setObjectAnimated(this._animator.gameObject, this, this.director.enabled && this.director.weight > 0);
181
- }
178
+ if (this._animator)
179
+ setObjectAnimated(this._animator.gameObject, this, this.director.isPlaying);
182
180
  }
183
181
 
184
182
  createHooks(clipModel: Models.AnimationClipModel, clip) {
@@ -1,6 +1,5 @@
1
1
  import { Matrix4, Object3D, Quaternion, Vector3 } from "three";
2
2
 
3
- import { isDevEnvironment } from "../../engine/debug/index.js";
4
3
  import { serializable } from "../../engine/engine_serialization.js";
5
4
  import { lookAtObject } from "../../engine/engine_three_utils.js";
6
5
  import { type UsdzBehaviour } from "../../engine-components/export/usdz/extensions/behavior/Behaviour.js";
@@ -43,10 +42,7 @@ export class LookAt extends Behaviour implements UsdzBehaviour {
43
42
  /** @internal */
44
43
  onBeforeRender(): void {
45
44
  let target: Object3D | null | undefined = this.target;
46
- if (!target) {
47
- target = this.context.mainCamera;
48
- if (isDevEnvironment()) console.warn(`[LookAt] No target set on ${this.name}, using main camera as target.`);
49
- }
45
+ if (!target) target = this.context.mainCamera;
50
46
  if (!target) return;
51
47
 
52
48
  let copyTargetRotation = this.copyTargetRotation;
@@ -1,21 +1,12 @@
1
1
  import { NEPointerEvent } from "../../engine/engine_input.js";
2
2
  import { onStart } from "../../engine/engine_lifecycle_api.js";
3
- import { addAttributeChangeCallback } from "../../engine/engine_utils.js";
4
3
  import { Behaviour } from "../Component.js";
5
4
 
6
5
  // Automatically add ClickThrough component if "clickthrough" attribute is present on the needle-engine element
7
6
  onStart(ctx => {
8
7
  const attribute = ctx.domElement.getAttribute("clickthrough");
9
- if (clickthroughEnabled(attribute)) {
10
- const comp = ctx.scene.addComponent(ClickThrough);
11
- addAttributeChangeCallback(ctx.domElement, "clickthrough", () => {
12
- const attribute = ctx.domElement.getAttribute("clickthrough");
13
- comp.enabled = clickthroughEnabled(attribute);
14
- });
15
- }
16
-
17
- function clickthroughEnabled(val: string | null) {
18
- return val !== null && val !== "0" && val !== "false";
8
+ if (attribute !== null && attribute !== "0" && attribute !== "false") {
9
+ ctx.scene.addComponent(ClickThrough);
19
10
  }
20
11
  });
21
12
 
@@ -1,14 +1,13 @@
1
1
  import { Box3, Object3D } from "three";
2
2
  import { element } from "three/src/nodes/TSL.js";
3
-
4
3
  import { Context } from "../../engine/engine_context.js";
4
+
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";
@@ -151,8 +150,7 @@ export class ScrollFollow extends Behaviour {
151
150
  }
152
151
  }
153
152
 
154
- // if (this._current_value !== this._appliedValue)
155
- {
153
+ if (this._current_value !== this._appliedValue) {
156
154
  this._appliedValue = this._current_value;
157
155
 
158
156
  let defaultPrevented = false;
@@ -244,8 +242,7 @@ export class ScrollFollow extends Behaviour {
244
242
 
245
243
  if (target instanceof PlayableDirector) {
246
244
  this.handleTimelineTarget(target, value);
247
- if (target.isPlaying) target.pause();
248
- target.evaluate();
245
+ if (!target.isPlaying) target.evaluate();
249
246
  }
250
247
  else if (target instanceof Animator) {
251
248
  target.setFloat("scroll", value);
@@ -295,35 +292,18 @@ export class ScrollFollow extends Behaviour {
295
292
  let scrollRegionEnd = 0;
296
293
  markersArray.length = 0;
297
294
 
298
- // querySelectorResults.length = 0;
299
- let markerIndex = 0;
300
-
301
- // https://scroll-driven-animations.style/tools/view-timeline/ranges
302
- for (const marker of director.foreachMarker<ScrollMarkerModel & { element?: HTMLElement | null, needsUpdate?: boolean, timeline?: ViewTimeline }>("ScrollMarker")) {
303
-
304
- const index = markerIndex++;
295
+ for (const marker of director.foreachMarker<ScrollMarkerModel & { element?: HTMLElement | null, needsUpdate?: boolean }>("ScrollMarker")) {
305
296
 
306
297
  // Get marker elements from DOM
307
- if ((marker.element === undefined || marker.needsUpdate === true || /** element is not in DOM anymore? */ (!marker.element?.parentNode))) {
298
+ if (marker.selector?.length && (marker.element === undefined || marker.needsUpdate === true || /** element is not in DOM anymore? */ (!marker.element?.parentNode))) {
308
299
  marker.needsUpdate = false;
309
300
  try {
310
- marker.element = tryGetElementsForSelector(index, marker.name) as HTMLElement | null;
311
- 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
- }
301
+ marker.element = document.querySelector<HTMLElement>(marker.selector) || null;
302
+ if (debug) console.debug("ScrollMarker found on page", marker.element, marker.selector);
323
303
  }
324
304
  catch (error) {
325
305
  marker.element = null;
326
- console.error("ScrollMarker selector is not valid: " + marker.name + "\n", error);
306
+ console.error("ScrollMarker selector is not valid: " + marker.selector + "\n", error);
327
307
  }
328
308
  }
329
309
 
@@ -350,74 +330,41 @@ export class ScrollFollow extends Behaviour {
350
330
 
351
331
  weightsArray.length = 0;
352
332
  let sum = 0;
353
- const oneFrameTime = 1 / 60;
354
333
 
355
- // 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
334
  let markerCount = 0;
357
- for (let i = 0; i < markersArray.length; i++) {
358
- const marker = markersArray[i];
335
+ for (const marker of markersArray) {
336
+
359
337
  if (!marker.element) continue;
360
- const nextMarker = markersArray[i + 1];
361
338
 
362
- const nextTime = nextMarker
363
- ? (nextMarker.time - oneFrameTime)
364
- : duration;
339
+ const top = marker.element.offsetTop;
340
+ const height = marker.element.offsetHeight;
341
+ const bottom = top + height;
342
+ let overlap = 0;
343
+
344
+ // 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
345
+
346
+ if (bottom < currentTop) {
347
+ // marker is above scroll region
348
+ overlap = 0;
349
+ }
350
+ else if (top > currentBottom) {
351
+ // marker is below scroll region
352
+ overlap = 0;
353
+ }
354
+ else {
355
+ // calculate overlap in pixels
356
+ const overlapTop = Math.max(top, currentTop);
357
+ const overlapBottom = Math.min(bottom, currentBottom);
358
+ overlap = Math.max(0, overlapBottom - overlapTop);
359
+ // console.log(marker.element.className, overlap)
360
+ }
365
361
 
366
362
  markerCount += 1;
367
363
 
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
- }
364
+ if (overlap > 0) {
365
+ weightsArray.push({ time: marker.time, weight: overlap });
366
+ sum += overlap;
388
367
  }
389
- continue;
390
- // if(this.context.time.frame % 10 === 0) console.log(marker.element?.className, timeline, calculateTimelinePositionNormalized(timeline!));
391
-
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;
396
-
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
398
-
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
- // }
414
-
415
- // // if(this.context.time.frame % 20 === 0) console.log(overlap)
416
-
417
- // if (overlap > 0) {
418
- // weightsArray.push({ time: marker.time, weight: overlap });
419
- // sum += overlap;
420
- // }
421
368
  }
422
369
 
423
370
  if (weightsArray.length <= 0 && markerCount <= 0) {
@@ -425,118 +372,25 @@ export class ScrollFollow extends Behaviour {
425
372
  }
426
373
  else if (weightsArray.length > 0) {
427
374
  // 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
- }
437
- }
438
- if (this.context.time.frame % 20 === 0) console.log(time.toFixed(3), [...weightsArray])
439
- if (this.damping <= 0) {
440
- director.time = time;
441
- }
442
- else {
443
- director.time = Mathf.lerp(director.time, time, this.context.time.deltaTime / this.damping);
375
+ let time = weightsArray[0].time;
376
+ for (const o of weightsArray) {
377
+ const weight = o.weight / Math.max(0.00001, sum);
378
+ // lerp time based on weight
379
+ const diff = Math.abs(o.time - time);
380
+ time += diff * weight;
444
381
  }
382
+ director.time = time;
445
383
  }
446
384
  }
447
385
 
448
386
  }
449
387
 
450
-
451
-
452
388
  const weightsArray: OverlapInfo[] = [];
453
- const markersArray: (ScrollMarkerModel & { element?: HTMLElement | null, timeline?: ViewTimeline })[] = [];
389
+ const markersArray: (ScrollMarkerModel & { element?: HTMLElement | null })[] = [];
454
390
 
455
391
  type OverlapInfo = {
456
392
  /** Marker time */
457
393
  time: number,
458
394
  /** Overlap in pixels */
459
395
  weight: number,
460
- }
461
-
462
-
463
- // type SelectorCache = {
464
- // /** The selector used to query the *elements */
465
- // selector: string,
466
- // elements: Element[] | null,
467
- // usedElementCount: number,
468
- // }
469
- // const querySelectorResults: Array<SelectorCache> = [];
470
-
471
- const needleScrollMarkerCacheKey = "data-timeline-marker";
472
- const needleScrollMarkerIndexCache = new Map<number, Element | null>();
473
- const needleScrollMarkerNameCache = new Map<string, Element | null>();
474
- let needsScrollMarkerRefresh = true;
475
-
476
- function tryGetElementsForSelector(index: number, name: string): Element | null {
477
-
478
- if (!needsScrollMarkerRefresh) {
479
- let element = name?.length ? needleScrollMarkerNameCache.get(name) : null;
480
- if (element) return element;
481
- element = needleScrollMarkerIndexCache.get(index) || null;
482
- return element;
483
- }
484
- needsScrollMarkerRefresh = false;
485
- needleScrollMarkerIndexCache.clear();
486
- const markers = document.querySelectorAll(`[data-timeline-marker]`);
487
- markers.forEach((m, i) => {
488
- needleScrollMarkerIndexCache.set(i, m);
489
- const name = m.getAttribute("data-timeline-marker");
490
- if (name?.length) needleScrollMarkerNameCache.set(name, m);
491
- });
492
- const element = needleScrollMarkerIndexCache.get(index) || null;
493
- return element;
494
-
495
-
496
- /* e.g.
497
- <div class="section behind start" data-needle-scroll-marker>
498
- */
499
- // console.log(index, element)
500
- if (element) return element;
501
-
502
- // for (const entry of querySelectorResults) {
503
- // if (entry.selector === selector) {
504
- // const index = entry.usedElementCount++;
505
- // return entry.elements && index < entry.elements.length ? entry.elements[index] : null;
506
- // }
507
- // }
508
- // const elements = document.querySelectorAll(selector);
509
- // querySelectorResults.push({ selector, elements: Array.from(elements), usedElementCount: 1 });
510
- // if (elements.length > 0) return elements[0];
511
- return null;
512
- }
513
-
514
-
515
- // #region ScrollTimeline
516
-
517
- function calculateTimelinePositionNormalized(timeline: ViewTimeline) {
518
- if (!timeline.source) return 0;
519
- const currentTime = timeline.currentTime;
520
- const duration = timeline.duration;
521
- let durationValue = 1;
522
- if (duration.unit === "seconds") {
523
- durationValue = duration.value;
524
- }
525
- else if (duration.unit === "percent") {
526
- durationValue = duration.value;
527
- }
528
- const t01 = currentTime.unit === "seconds" ? (currentTime.value / durationValue) : (currentTime.value / 100);
529
- return t01;
530
- }
531
-
532
-
533
- declare global {
534
- interface ViewTimeline {
535
- axis: 'block' | 'inline';
536
- currentTime: { unit: 'seconds' | 'percent', value: number };
537
- duration: { unit: 'seconds' | 'percent', value: number };
538
- source: Element | null;
539
- startOffset: { unit: 'px', value: number };
540
- endOffset: { unit: 'px', value: number };
541
- }
542
396
  }
@@ -1,5 +1,4 @@
1
1
  export * from "./Clickthrough.js";
2
2
  export * from "./CursorFollow.js";
3
3
  export * from "./HoverAnimation.js";
4
- export * from "./ScrollFollow.js";
5
- export * from "./ViewBox.js";
4
+ export * from "./ScrollFollow.js";
@@ -1,16 +0,0 @@
1
- import { Behaviour } from "../Component.js";
2
- export declare class ViewBox extends Behaviour {
3
- static instances: ViewBox[];
4
- referenceFieldOfView: number;
5
- debug: boolean;
6
- awake(): void;
7
- onEnable(): void;
8
- onDisable(): void;
9
- onBeforeRender(): void;
10
- /**
11
- * Cover fit
12
- */
13
- private fit;
14
- private projectBoxIntoCamera;
15
- private _projectedBoxElement;
16
- }