@needle-tools/engine 4.10.0-beta.1 → 4.10.0-beta.3

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 (51) hide show
  1. package/dist/needle-engine.bundle-CLzMgxkO.min.js +1650 -0
  2. package/dist/{needle-engine.bundle-6so_os_w.umd.cjs → needle-engine.bundle-Ckr5KE6m.umd.cjs} +132 -132
  3. package/dist/{needle-engine.bundle-Dj2DYdMY.js → needle-engine.bundle-Ddybtee9.js} +7082 -7021
  4. package/dist/needle-engine.js +15 -14
  5. package/dist/needle-engine.min.js +1 -1
  6. package/dist/needle-engine.umd.cjs +1 -1
  7. package/lib/engine/engine_camera.js +2 -2
  8. package/lib/engine/engine_camera.js.map +1 -1
  9. package/lib/engine/engine_lightdata.d.ts +3 -3
  10. package/lib/engine/engine_lightdata.js +10 -10
  11. package/lib/engine/engine_lightdata.js.map +1 -1
  12. package/lib/engine/engine_physics_rapier.js +4 -0
  13. package/lib/engine/engine_physics_rapier.js.map +1 -1
  14. package/lib/engine/engine_scenelighting.d.ts +1 -1
  15. package/lib/engine/engine_scenelighting.js +4 -5
  16. package/lib/engine/engine_scenelighting.js.map +1 -1
  17. package/lib/engine/engine_utils.d.ts +3 -1
  18. package/lib/engine/engine_utils.js +11 -0
  19. package/lib/engine/engine_utils.js.map +1 -1
  20. package/lib/engine/extensions/NEEDLE_lightmaps.js +1 -1
  21. package/lib/engine/extensions/NEEDLE_lightmaps.js.map +1 -1
  22. package/lib/engine/webcomponents/needle-engine.js +22 -0
  23. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  24. package/lib/engine-components/CameraUtils.js +2 -1
  25. package/lib/engine-components/CameraUtils.js.map +1 -1
  26. package/lib/engine-components/Renderer.js +2 -0
  27. package/lib/engine-components/Renderer.js.map +1 -1
  28. package/lib/engine-components/Skybox.js +22 -4
  29. package/lib/engine-components/Skybox.js.map +1 -1
  30. package/lib/engine-components/utils/LookAt.js +1 -1
  31. package/lib/engine-components/utils/LookAt.js.map +1 -1
  32. package/lib/engine-components/web/ScrollFollow.js +80 -70
  33. package/lib/engine-components/web/ScrollFollow.js.map +1 -1
  34. package/lib/engine-components/web/ViewBox.d.ts +0 -1
  35. package/lib/engine-components/web/ViewBox.js +79 -36
  36. package/lib/engine-components/web/ViewBox.js.map +1 -1
  37. package/package.json +1 -1
  38. package/src/engine/engine_camera.ts +2 -2
  39. package/src/engine/engine_lightdata.ts +11 -11
  40. package/src/engine/engine_physics_rapier.ts +3 -0
  41. package/src/engine/engine_scenelighting.ts +5 -6
  42. package/src/engine/engine_utils.ts +12 -0
  43. package/src/engine/extensions/NEEDLE_lightmaps.ts +1 -1
  44. package/src/engine/webcomponents/needle-engine.ts +33 -6
  45. package/src/engine-components/CameraUtils.ts +1 -1
  46. package/src/engine-components/Renderer.ts +2 -0
  47. package/src/engine-components/Skybox.ts +26 -7
  48. package/src/engine-components/utils/LookAt.ts +1 -1
  49. package/src/engine-components/web/ScrollFollow.ts +82 -70
  50. package/src/engine-components/web/ViewBox.ts +82 -37
  51. package/dist/needle-engine.bundle-Djy6H4lx.min.js +0 -1650
@@ -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 } from "../engine/engine_utils.js";
11
+ import { addAttributeChangeCallback, getParam, PromiseAllWithErrors, removeAttributeChangeCallback, toSourceId } 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,15 +27,34 @@ function createRemoteSkyboxComponent(context: IContext, url: string, skybox: boo
27
27
  }
28
28
 
29
29
  const remote = new RemoteSkybox();
30
+ remote.sourceId = toSourceId(url);
30
31
  remote.allowDrop = false;
31
32
  remote.allowNetworking = false;
32
33
  remote.background = skybox;
33
34
  remote.environment = environment;
34
35
  GameObject.addComponent(context.scene, remote);
35
36
  const urlChanged = newValue => {
36
- if (typeof newValue !== "string") return;
37
- if (debug) console.log(attribute, "CHANGED TO", newValue)
38
- remote.setSkybox(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
+ }
39
58
  };
40
59
  addAttributeChangeCallback(context.domElement, attribute, urlChanged);
41
60
  remote.addEventListener("destroy", () => {
@@ -50,7 +69,7 @@ ContextRegistry.registerCallback(ContextEvent.ContextCreationStart, (args) => {
50
69
  const context = args.context;
51
70
  const backgroundImage = context.domElement.getAttribute("background-image");
52
71
  const environmentImage = context.domElement.getAttribute("environment-image");
53
-
72
+
54
73
  if (backgroundImage) {
55
74
  if (debug) console.log("Creating RemoteSkybox to load background " + backgroundImage);
56
75
  // if the user is loading a GLB without a camera then the CameraUtils (which creates the default camera)
@@ -246,8 +265,8 @@ export class RemoteSkybox extends Behaviour {
246
265
  envMap.needsUpdate = true;
247
266
  }
248
267
 
249
- if(this.destroyed) return;
250
- if(!this.context) {
268
+ if (this.destroyed) return;
269
+ if (!this.context) {
251
270
  console.warn("RemoteSkybox: Context is not available - can not apply skybox.");
252
271
  return;
253
272
  }
@@ -1,12 +1,12 @@
1
1
  import { Matrix4, Object3D, Quaternion, Vector3 } from "three";
2
2
 
3
+ import { isDevEnvironment } from "../../engine/debug/index.js";
3
4
  import { serializable } from "../../engine/engine_serialization.js";
4
5
  import { lookAtObject } from "../../engine/engine_three_utils.js";
5
6
  import { type UsdzBehaviour } from "../../engine-components/export/usdz/extensions/behavior/Behaviour.js";
6
7
  import { ActionBuilder, BehaviorModel, TriggerBuilder, USDVec3 } from "../../engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js";
7
8
  import { USDObject } from "../../engine-components/export/usdz/ThreeUSDZExporter.js";
8
9
  import { Behaviour } from "../Component.js";
9
- import { isDevEnvironment } from "../../engine/debug/index.js";
10
10
 
11
11
  /**
12
12
  * LookAt behaviour makes the object look at a target object or the camera.
@@ -4,10 +4,11 @@ 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 } from "../../engine/engine_three_utils.js";
7
+ import { getBoundingBox, setVisibleInCustomShadowRendering } 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";
11
12
  import { AudioSource } from "../AudioSource.js";
12
13
  import { Behaviour } from "../Component.js";
13
14
  import { EventList } from "../EventList.js";
@@ -308,17 +309,17 @@ export class ScrollFollow extends Behaviour {
308
309
  try {
309
310
  marker.element = tryGetElementsForSelector(index, marker.name) as HTMLElement | null;
310
311
  if (debug) console.debug("ScrollMarker found on page", marker.element, marker.name);
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
- // }
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
+ }
322
323
  }
323
324
  catch (error) {
324
325
  marker.element = null;
@@ -349,57 +350,74 @@ export class ScrollFollow extends Behaviour {
349
350
 
350
351
  weightsArray.length = 0;
351
352
  let sum = 0;
353
+ const oneFrameTime = 1 / 60;
352
354
 
353
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
354
356
  let markerCount = 0;
355
- for (const marker of markersArray) {
356
-
357
+ for (let i = 0; i < markersArray.length; i++) {
358
+ const marker = markersArray[i];
357
359
  if (!marker.element) continue;
360
+ const nextMarker = markersArray[i + 1];
361
+
362
+ const nextTime = nextMarker
363
+ ? (nextMarker.time - oneFrameTime)
364
+ : duration;
358
365
 
359
366
  markerCount += 1;
360
367
 
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;
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;
373
390
  // if(this.context.time.frame % 10 === 0) console.log(marker.element?.className, timeline, calculateTimelinePositionNormalized(timeline!));
374
391
 
375
- const top = marker.element.offsetTop;
376
- const height = marker.element.offsetHeight;
377
- const bottom = top + height;
378
- let overlap = 0;
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;
379
396
 
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
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
381
398
 
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
- }
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
+ // }
396
414
 
397
- markerCount += 1;
415
+ // // if(this.context.time.frame % 20 === 0) console.log(overlap)
398
416
 
399
- if (overlap > 0) {
400
- weightsArray.push({ time: marker.time, weight: overlap });
401
- sum += overlap;
402
- }
417
+ // if (overlap > 0) {
418
+ // weightsArray.push({ time: marker.time, weight: overlap });
419
+ // sum += overlap;
420
+ // }
403
421
  }
404
422
 
405
423
  if (weightsArray.length <= 0 && markerCount <= 0) {
@@ -407,19 +425,23 @@ export class ScrollFollow extends Behaviour {
407
425
  }
408
426
  else if (weightsArray.length > 0) {
409
427
  // normalize and calculate weighted time
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;
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
+ }
417
437
  }
418
- // console.log(time.toFixed(2), [...weightsArray])
419
- if (this.damping <= 0)
438
+ if (debug && this.context.time.frame % 20 === 0) console.log(time.toFixed(3), [...weightsArray])
439
+ if (this.damping <= 0) {
420
440
  director.time = time;
421
- else
441
+ }
442
+ else {
422
443
  director.time = Mathf.lerp(director.time, time, this.context.time.deltaTime / this.damping);
444
+ }
423
445
  }
424
446
  }
425
447
 
@@ -506,16 +528,6 @@ function calculateTimelinePositionNormalized(timeline: ViewTimeline) {
506
528
  const t01 = currentTime.unit === "seconds" ? (currentTime.value / durationValue) : (currentTime.value / 100);
507
529
  return t01;
508
530
  }
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
- }
519
531
 
520
532
 
521
533
  declare global {
@@ -1,10 +1,12 @@
1
1
  import { Camera, PerspectiveCamera, Vector2, Vector3 } from "three";
2
+
3
+ import { isDevEnvironment } from "../../engine/debug/debug.js";
4
+ import { Gizmos } from "../../engine/engine_gizmos.js";
2
5
  import { serializable } from "../../engine/engine_serialization_decorator.js";
6
+ import { getTempQuaternion, getTempVector } from "../../engine/engine_three_utils.js";
3
7
  import { registerType } from "../../engine/engine_typestore.js";
4
- import { getTempVector } from "../../engine/engine_three_utils.js";
5
- import { Behaviour } from "../Component.js";
6
- import { isDevEnvironment } from "../../engine/debug/debug.js";
7
8
  import { getParam } from "../../engine/engine_utils.js";
9
+ import { Behaviour } from "../Component.js";
8
10
 
9
11
  const debugParam = getParam("debugviewbox");
10
12
 
@@ -19,26 +21,34 @@ export class ViewBox extends Behaviour {
19
21
  @serializable()
20
22
  debug: boolean = false;
21
23
 
22
- awake() {
23
- // this.referenceFieldOfView = (this.context.mainCamera as PerspectiveCamera)?.fov || 60;
24
- // setInterval(()=>{
25
- // this.enabled = !this.enabled
26
- // }, 1000)
27
- }
24
+ // awake() {
25
+ // // this.referenceFieldOfView = (this.context.mainCamera as PerspectiveCamera)?.fov || 60;
26
+ // setInterval(()=>{
27
+ // if(Math.random() > .5)
28
+ // this.enabled = !this.enabled
29
+ // }, 1000)
30
+ // }
31
+
28
32
  onEnable(): void {
29
33
  if (debugParam || this.debug || isDevEnvironment()) console.debug("[ViewBox] Using camera fov:", this.referenceFieldOfView);
30
34
  ViewBox.instances.push(this);
31
35
  }
32
36
 
33
37
  onDisable(): void {
38
+ if (debugParam || this.debug) console.debug("[ViewBox] Disabled");
34
39
  const idx = ViewBox.instances.indexOf(this);
35
40
  if (idx !== -1) ViewBox.instances.splice(idx, 1);
41
+ this._projectedBoxElement?.remove();
36
42
  }
37
43
 
38
44
  onBeforeRender() {
39
45
  if (this.context.isInXR) return;
40
46
  const isActive = ViewBox.instances[ViewBox.instances.length - 1] === this;
41
- if (!isActive) return;
47
+ if (!isActive) {
48
+ if (debugParam || this.debug) Gizmos.DrawWireBox(this.gameObject.worldPosition, this.gameObject.worldScale, 0x333333);
49
+ return;
50
+ }
51
+ if (debugParam || this.debug) Gizmos.DrawWireBox(this.gameObject.worldPosition, this.gameObject.worldScale, 0xdddd00);
42
52
 
43
53
  // calculate box size to fit the camera frustrum size at the current position (just scale)
44
54
  const camera = this.context.mainCamera;
@@ -53,11 +63,8 @@ export class ViewBox extends Behaviour {
53
63
  return;
54
64
  }
55
65
 
56
- const domRect = this.context.domElement.getBoundingClientRect();
57
- const domX = domRect.x;
58
- const domY = domRect.y;
59
- const domWidth = domRect.width;
60
- const domHeight = domRect.height;
66
+ const domWidth = this.context.domWidth;
67
+ const domHeight = this.context.domHeight;
61
68
 
62
69
  let rectPosX = 0;
63
70
  let rectPosY = 0;
@@ -77,44 +84,80 @@ export class ViewBox extends Behaviour {
77
84
  diffHeight = domHeight / rectHeight;
78
85
  }
79
86
 
80
- // const view = camera.view;
87
+
81
88
  const view = camera.view;
82
89
  const zoom = camera.zoom;
83
90
  const aspect = camera.aspect;
84
91
  const fov = camera.fov;
85
92
  camera.view = null;
86
93
  camera.zoom = 1;
87
- // camera.aspect = rectWidth / rectHeight;
88
94
  camera.fov = this.referenceFieldOfView;
89
95
  camera.updateProjectionMatrix();
90
96
 
91
97
  const boxPosition = this.gameObject.worldPosition;
92
98
  const boxScale = this.gameObject.worldScale;
93
99
 
100
+ const cameraPosition = camera.worldPosition;
101
+ const distance = cameraPosition.distanceTo(boxPosition);
102
+
103
+
104
+ // #region camera fixes
105
+ // If the camera is inside the box, move it out
106
+ const boxSizeMax = Math.max(boxScale.x, boxScale.y, boxScale.z);
107
+ const direction = getTempVector(cameraPosition).sub(boxPosition);
108
+ if (distance < boxSizeMax) {
109
+ // move camera out of bounds
110
+ if (this.debug || debugParam) console.warn("[ViewBox] Moving camera out of bounds", distance, "<", boxSizeMax);
111
+ const positionDirection = getTempVector(direction);
112
+ positionDirection.y *= .00000001; // stay on horizontal plane mostly
113
+ positionDirection.normalize();
114
+ const lengthToMove = (boxSizeMax - distance) * 10; // move a bit more than needed
115
+ const newPosition = cameraPosition.add(positionDirection.multiplyScalar(lengthToMove));
116
+ camera.worldPosition = newPosition.lerp(cameraPosition, 1 - this.context.time.deltaTime);
117
+ }
118
+
119
+ // Ensure the camera looks at the ViewBox
120
+ // TOOD: smooth lookat over multiple frames if we have multiple viewboxes
121
+ // const dot = direction.normalize().dot(camera.worldForward);
122
+ // if (dot < .9) {
123
+ // console.log(dot);
124
+ // const targetRotation = direction;
125
+ // const rotation = getTempQuaternion();
126
+ // rotation.setFromUnitVectors(camera.worldForward.multiplyScalar(-1), targetRotation);
127
+ // camera.worldQuaternion = rotation;
128
+ // camera.updateMatrixWorld();
129
+ // }
130
+ const boxPositionInCameraSpace = getTempVector(boxPosition);
131
+ camera.worldToLocal(boxPositionInCameraSpace);
132
+ camera.lookAt(boxPosition);
133
+ camera.updateMatrixWorld();
94
134
 
95
135
 
96
- // const fov = this.referenceFieldOfView
97
- const distance = camera.worldPosition.distanceTo(boxPosition);
136
+ // #region calculate fit
98
137
  const vFOV = this.referenceFieldOfView * Math.PI / 180; // convert vertical fov to radians
99
138
  const height = 2 * Math.tan(vFOV / 2) * distance; // visible height
100
139
  const width = height * camera.aspect; // visible width
101
140
 
102
- const projectedBox = this.projectBoxIntoCamera(boxPosition, boxScale, camera, height * .5);
141
+ const projectedBox = this.projectBoxIntoCamera(boxPosition, boxScale, camera, 1);
142
+ // return
103
143
  const boxWidth = (projectedBox.maxX - projectedBox.minX);
104
144
  const boxHeight = (projectedBox.maxY - projectedBox.minY);
105
145
 
106
- // TODO: take the rect size different into account
107
146
  const scale = this.fit(
108
147
  boxWidth * camera.aspect,
109
148
  boxHeight,
110
149
  width / diffWidth,
111
150
  height / diffHeight
112
151
  );
152
+ // console.log({ scale, width, height, boxWidth: boxWidth * camera.aspect, boxHeight, diffWidth, diffHeight, aspect: camera.aspect, distance })
153
+ // this.context.focusRectSettings.zoom = 1.39;
154
+ // if (!this.context.focusRect) this.context.setCameraFocusRect(this.context.domElement);
155
+ // return
113
156
  const vec = getTempVector(boxPosition);
114
157
  vec.project(camera);
115
158
  this.context.focusRectSettings.offsetX = vec.x;
116
159
  this.context.focusRectSettings.offsetY = vec.y;
117
- this.context.focusRectSettings.zoom = scale;
160
+ this.context.focusRectSettings.zoom = scale / (height * .5);
118
161
  // if we don't have a focus rect yet, set it to the dom element
119
162
  if (!this.context.focusRect) this.context.setCameraFocusRect(this.context.domElement);
120
163
 
@@ -146,9 +189,8 @@ export class ViewBox extends Behaviour {
146
189
 
147
190
 
148
191
 
149
- private projectBoxIntoCamera(position: Vector3, scale: Vector3, camera: Camera, diff: number) {
150
-
151
- const factor = .5 * diff;
192
+ private projectBoxIntoCamera(position: Vector3, scale: Vector3, camera: Camera, _factor: number) {
193
+ const factor = .5 * _factor;
152
194
 
153
195
  const corners = [
154
196
  getTempVector(-scale.x * factor, -scale.y * factor, -scale.z * factor),
@@ -174,18 +216,21 @@ export class ViewBox extends Behaviour {
174
216
  if (c.y > maxY) maxY = c.y;
175
217
  }
176
218
 
177
- // if(!this._projectedBoxElement) {
178
- // this._projectedBoxElement = document.createElement("div");
179
- // this.context.domElement.appendChild(this._projectedBoxElement);
180
- // }
181
- // this._projectedBoxElement.style.position = "fixed";
182
- // this._projectedBoxElement.style.outline = "10px solid red";
183
- // this._projectedBoxElement.style.left = ((minX * .5 + .5) * this.context.domWidth) + "px";
184
- // this._projectedBoxElement.style.top = ((-maxY * .5 + .5) * this.context.domHeight) + "px";
185
- // this._projectedBoxElement.style.width = ((maxX - minX) * .5 * this.context.domWidth) + "px";
186
- // this._projectedBoxElement.style.height = ((maxY - minY) * .5 * this.context.domHeight) + "px";
187
- // this._projectedBoxElement.style.pointerEvents = "none";
188
- // this._projectedBoxElement.style.zIndex = "1000";
219
+ if (debugParam) {
220
+ if (!this._projectedBoxElement) {
221
+ this._projectedBoxElement = document.createElement("div");
222
+ }
223
+ if (this._projectedBoxElement.parentElement !== this.context.domElement)
224
+ this.context.domElement.appendChild(this._projectedBoxElement);
225
+ this._projectedBoxElement.style.position = "fixed";
226
+ this._projectedBoxElement.style.outline = "5px dotted red";
227
+ this._projectedBoxElement.style.left = ((minX * .5 + .5) * this.context.domWidth) + "px";
228
+ this._projectedBoxElement.style.top = ((-maxY * .5 + .5) * this.context.domHeight) + "px";
229
+ this._projectedBoxElement.style.width = ((maxX - minX) * .5 * this.context.domWidth) + "px";
230
+ this._projectedBoxElement.style.height = ((maxY - minY) * .5 * this.context.domHeight) + "px";
231
+ this._projectedBoxElement.style.pointerEvents = "none";
232
+ this._projectedBoxElement.style.zIndex = "1000";
233
+ }
189
234
 
190
235
 
191
236
  return { minX, maxX, minY, maxY };