@needle-tools/engine 4.10.0-beta → 4.10.0-beta.2

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-Dj6faVbC.js → needle-engine.bundle-BTgC7uAm.js} +7236 -7012
  3. package/dist/{needle-engine.bundle-42AmEGfk.umd.cjs → needle-engine.bundle-OTBqjiCd.umd.cjs} +152 -141
  4. package/dist/{needle-engine.bundle-C6zhyLF5.min.js → needle-engine.bundle-g2_JEHcF.min.js} +170 -159
  5. package/dist/needle-engine.js +259 -257
  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 +2 -0
  9. package/lib/engine/codegen/register_types.js.map +1 -1
  10. package/lib/engine/engine_camera.d.ts +7 -1
  11. package/lib/engine/engine_camera.fit.d.ts +1 -1
  12. package/lib/engine/engine_camera.fit.js +3 -30
  13. package/lib/engine/engine_camera.fit.js.map +1 -1
  14. package/lib/engine/engine_camera.js +46 -6
  15. package/lib/engine/engine_camera.js.map +1 -1
  16. package/lib/engine/engine_context.d.ts +6 -0
  17. package/lib/engine/engine_context.js +48 -9
  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 +4 -0
  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 +4 -5
  26. package/lib/engine/engine_scenelighting.js.map +1 -1
  27. package/lib/engine/engine_utils.d.ts +3 -1
  28. package/lib/engine/engine_utils.js +11 -0
  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 +29 -5
  34. package/lib/engine/webcomponents/logo-element.js.map +1 -1
  35. package/lib/engine/webcomponents/needle menu/needle-menu.js +4 -3
  36. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  37. package/lib/engine/webcomponents/needle-engine.js +22 -0
  38. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  39. package/lib/engine/webcomponents/needle-engine.loading.d.ts +0 -1
  40. package/lib/engine/webcomponents/needle-engine.loading.js +3 -36
  41. package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
  42. package/lib/engine-components/OrbitControls.d.ts +4 -1
  43. package/lib/engine-components/OrbitControls.js +30 -6
  44. package/lib/engine-components/OrbitControls.js.map +1 -1
  45. package/lib/engine-components/Renderer.js +6 -1
  46. package/lib/engine-components/Renderer.js.map +1 -1
  47. package/lib/engine-components/Skybox.js +22 -4
  48. package/lib/engine-components/Skybox.js.map +1 -1
  49. package/lib/engine-components/codegen/components.d.ts +1 -0
  50. package/lib/engine-components/codegen/components.js +1 -0
  51. package/lib/engine-components/codegen/components.js.map +1 -1
  52. package/lib/engine-components/timeline/PlayableDirector.d.ts +7 -0
  53. package/lib/engine-components/timeline/PlayableDirector.js +7 -0
  54. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  55. package/lib/engine-components/timeline/TimelineModels.d.ts +9 -1
  56. package/lib/engine-components/timeline/TimelineTracks.js +4 -2
  57. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  58. package/lib/engine-components/utils/LookAt.js +5 -1
  59. package/lib/engine-components/utils/LookAt.js.map +1 -1
  60. package/lib/engine-components/web/Clickthrough.js +10 -2
  61. package/lib/engine-components/web/Clickthrough.js.map +1 -1
  62. package/lib/engine-components/web/ScrollFollow.d.ts +22 -0
  63. package/lib/engine-components/web/ScrollFollow.js +159 -38
  64. package/lib/engine-components/web/ScrollFollow.js.map +1 -1
  65. package/lib/engine-components/web/ViewBox.d.ts +16 -0
  66. package/lib/engine-components/web/ViewBox.js +186 -0
  67. package/lib/engine-components/web/ViewBox.js.map +1 -0
  68. package/lib/engine-components/web/index.d.ts +1 -0
  69. package/lib/engine-components/web/index.js +1 -0
  70. package/lib/engine-components/web/index.js.map +1 -1
  71. package/package.json +1 -1
  72. package/src/engine/codegen/register_types.ts +2 -0
  73. package/src/engine/engine_camera.fit.ts +2 -32
  74. package/src/engine/engine_camera.ts +62 -8
  75. package/src/engine/engine_context.ts +50 -10
  76. package/src/engine/engine_lightdata.ts +11 -11
  77. package/src/engine/engine_physics_rapier.ts +3 -0
  78. package/src/engine/engine_scenelighting.ts +5 -6
  79. package/src/engine/engine_utils.ts +12 -0
  80. package/src/engine/extensions/NEEDLE_lightmaps.ts +1 -1
  81. package/src/engine/webcomponents/logo-element.ts +29 -4
  82. package/src/engine/webcomponents/needle menu/needle-menu.ts +4 -3
  83. package/src/engine/webcomponents/needle-engine.loading.ts +32 -32
  84. package/src/engine/webcomponents/needle-engine.ts +33 -6
  85. package/src/engine-components/OrbitControls.ts +40 -1
  86. package/src/engine-components/Renderer.ts +6 -1
  87. package/src/engine-components/Skybox.ts +26 -7
  88. package/src/engine-components/codegen/components.ts +1 -0
  89. package/src/engine-components/timeline/PlayableDirector.ts +9 -0
  90. package/src/engine-components/timeline/TimelineModels.ts +9 -1
  91. package/src/engine-components/timeline/TimelineTracks.ts +4 -2
  92. package/src/engine-components/utils/LookAt.ts +5 -1
  93. package/src/engine-components/web/Clickthrough.ts +11 -2
  94. package/src/engine-components/web/ScrollFollow.ts +190 -44
  95. package/src/engine-components/web/ViewBox.ts +202 -0
  96. package/src/engine-components/web/index.ts +2 -1
@@ -0,0 +1,186 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var ViewBox_1;
8
+ import { PerspectiveCamera } from "three";
9
+ import { isDevEnvironment } from "../../engine/debug/debug.js";
10
+ import { Gizmos } from "../../engine/engine_gizmos.js";
11
+ import { serializable } from "../../engine/engine_serialization_decorator.js";
12
+ import { getTempVector } from "../../engine/engine_three_utils.js";
13
+ import { registerType } from "../../engine/engine_typestore.js";
14
+ import { getParam } from "../../engine/engine_utils.js";
15
+ import { Behaviour } from "../Component.js";
16
+ const debugParam = getParam("debugviewbox");
17
+ let ViewBox = ViewBox_1 = class ViewBox extends Behaviour {
18
+ static instances = [];
19
+ referenceFieldOfView = 60;
20
+ debug = false;
21
+ awake() {
22
+ // this.referenceFieldOfView = (this.context.mainCamera as PerspectiveCamera)?.fov || 60;
23
+ // setInterval(()=>{
24
+ // this.enabled = !this.enabled
25
+ // }, 1000)
26
+ }
27
+ onEnable() {
28
+ if (debugParam || this.debug || isDevEnvironment())
29
+ console.debug("[ViewBox] Using camera fov:", this.referenceFieldOfView);
30
+ ViewBox_1.instances.push(this);
31
+ }
32
+ onDisable() {
33
+ const idx = ViewBox_1.instances.indexOf(this);
34
+ if (idx !== -1)
35
+ ViewBox_1.instances.splice(idx, 1);
36
+ }
37
+ onBeforeRender() {
38
+ if (this.context.isInXR)
39
+ return;
40
+ const isActive = ViewBox_1.instances[ViewBox_1.instances.length - 1] === this;
41
+ if (!isActive) {
42
+ if (debugParam || this.debug)
43
+ Gizmos.DrawWireBox(this.gameObject.worldPosition, this.gameObject.worldScale, 0x333333);
44
+ return;
45
+ }
46
+ if (debugParam || this.debug)
47
+ Gizmos.DrawWireBox(this.gameObject.worldPosition, this.gameObject.worldScale, 0xdddd00);
48
+ // calculate box size to fit the camera frustrum size at the current position (just scale)
49
+ const camera = this.context.mainCamera;
50
+ if (!camera)
51
+ return;
52
+ if (!(camera instanceof PerspectiveCamera)) {
53
+ // TODO: support orthographic camera
54
+ return;
55
+ }
56
+ if (this.referenceFieldOfView === undefined || this.referenceFieldOfView <= 0) {
57
+ if (debugParam || this.debug)
58
+ console.warn("[ViewBox] No valid referenceFieldOfView set, cannot adjust box size:", this.referenceFieldOfView);
59
+ return;
60
+ }
61
+ const domWidth = this.context.domWidth;
62
+ const domHeight = this.context.domHeight;
63
+ let rectPosX = 0;
64
+ let rectPosY = 0;
65
+ let rectWidth = domWidth;
66
+ let rectHeight = domHeight;
67
+ let diffWidth = 1;
68
+ let diffHeight = 1;
69
+ // use focus rect if available
70
+ const focusRectSize = this.context.focusRectSize;
71
+ if (focusRectSize) {
72
+ // console.log(focusRectSize)
73
+ rectPosX = focusRectSize.x;
74
+ rectPosY = focusRectSize.y;
75
+ rectWidth = focusRectSize.width;
76
+ rectHeight = focusRectSize.height;
77
+ diffWidth = domWidth / rectWidth;
78
+ diffHeight = domHeight / rectHeight;
79
+ }
80
+ // const view = camera.view;
81
+ const view = camera.view;
82
+ const zoom = camera.zoom;
83
+ const aspect = camera.aspect;
84
+ const fov = camera.fov;
85
+ camera.view = null;
86
+ camera.zoom = 1;
87
+ // camera.aspect = rectWidth / rectHeight;
88
+ camera.fov = this.referenceFieldOfView;
89
+ camera.updateProjectionMatrix();
90
+ const boxPosition = this.gameObject.worldPosition;
91
+ const boxScale = this.gameObject.worldScale;
92
+ // const fov = this.referenceFieldOfView
93
+ const distance = camera.worldPosition.distanceTo(boxPosition);
94
+ const vFOV = this.referenceFieldOfView * Math.PI / 180; // convert vertical fov to radians
95
+ const height = 2 * Math.tan(vFOV / 2) * distance; // visible height
96
+ const width = height * camera.aspect; // visible width
97
+ const projectedBox = this.projectBoxIntoCamera(boxPosition, boxScale, camera, height * .5);
98
+ const boxWidth = (projectedBox.maxX - projectedBox.minX);
99
+ const boxHeight = (projectedBox.maxY - projectedBox.minY);
100
+ // TODO: take the rect size different into account
101
+ const scale = this.fit(boxWidth * camera.aspect, boxHeight, width / diffWidth, height / diffHeight);
102
+ const vec = getTempVector(boxPosition);
103
+ vec.project(camera);
104
+ this.context.focusRectSettings.offsetX = vec.x;
105
+ this.context.focusRectSettings.offsetY = vec.y;
106
+ this.context.focusRectSettings.zoom = scale;
107
+ // if we don't have a focus rect yet, set it to the dom element
108
+ if (!this.context.focusRect)
109
+ this.context.setCameraFocusRect(this.context.domElement);
110
+ // Reset values
111
+ camera.view = view;
112
+ camera.zoom = zoom;
113
+ camera.aspect = aspect;
114
+ camera.fov = fov;
115
+ // camera.updateProjectionMatrix();
116
+ // BACKLOG: some code for box scale of an object (different component)
117
+ // this.gameObject.worldScale = getTempVector(width, height, worldscale.z);
118
+ // this.gameObject.scale.multiplyScalar(.98)
119
+ // const minscale = Math.min(width, height);
120
+ // console.log(width, height);
121
+ // this.gameObject.worldScale = getTempVector(scale, scale, scale);
122
+ }
123
+ /**
124
+ * Cover fit
125
+ */
126
+ fit(width1, height1, width2, height2) {
127
+ const scaleX = width2 / width1;
128
+ const scaleY = height2 / height1;
129
+ return Math.min(scaleX, scaleY);
130
+ }
131
+ projectBoxIntoCamera(position, scale, camera, diff) {
132
+ const factor = .5 * diff;
133
+ const corners = [
134
+ getTempVector(-scale.x * factor, -scale.y * factor, -scale.z * factor),
135
+ getTempVector(scale.x * factor, -scale.y * factor, -scale.z * factor),
136
+ getTempVector(-scale.x * factor, scale.y * factor, -scale.z * factor),
137
+ getTempVector(scale.x * factor, scale.y * factor, -scale.z * factor),
138
+ getTempVector(-scale.x * factor, -scale.y * factor, scale.z * factor),
139
+ getTempVector(scale.x * factor, -scale.y * factor, scale.z * factor),
140
+ getTempVector(-scale.x * factor, scale.y * factor, scale.z * factor),
141
+ getTempVector(scale.x * factor, scale.y * factor, scale.z * factor),
142
+ ];
143
+ let minX = Number.POSITIVE_INFINITY;
144
+ let maxX = Number.NEGATIVE_INFINITY;
145
+ let minY = Number.POSITIVE_INFINITY;
146
+ let maxY = Number.NEGATIVE_INFINITY;
147
+ for (let i = 0; i < corners.length; i++) {
148
+ const c = corners[i];
149
+ c.add(position);
150
+ c.project(camera);
151
+ if (c.x < minX)
152
+ minX = c.x;
153
+ if (c.x > maxX)
154
+ maxX = c.x;
155
+ if (c.y < minY)
156
+ minY = c.y;
157
+ if (c.y > maxY)
158
+ maxY = c.y;
159
+ }
160
+ // if(!this._projectedBoxElement) {
161
+ // this._projectedBoxElement = document.createElement("div");
162
+ // this.context.domElement.appendChild(this._projectedBoxElement);
163
+ // }
164
+ // this._projectedBoxElement.style.position = "fixed";
165
+ // this._projectedBoxElement.style.outline = "10px solid red";
166
+ // this._projectedBoxElement.style.left = ((minX * .5 + .5) * this.context.domWidth) + "px";
167
+ // this._projectedBoxElement.style.top = ((-maxY * .5 + .5) * this.context.domHeight) + "px";
168
+ // this._projectedBoxElement.style.width = ((maxX - minX) * .5 * this.context.domWidth) + "px";
169
+ // this._projectedBoxElement.style.height = ((maxY - minY) * .5 * this.context.domHeight) + "px";
170
+ // this._projectedBoxElement.style.pointerEvents = "none";
171
+ // this._projectedBoxElement.style.zIndex = "1000";
172
+ return { minX, maxX, minY, maxY };
173
+ }
174
+ _projectedBoxElement = null;
175
+ };
176
+ __decorate([
177
+ serializable()
178
+ ], ViewBox.prototype, "referenceFieldOfView", void 0);
179
+ __decorate([
180
+ serializable()
181
+ ], ViewBox.prototype, "debug", void 0);
182
+ ViewBox = ViewBox_1 = __decorate([
183
+ registerType
184
+ ], ViewBox);
185
+ export { ViewBox };
186
+ //# sourceMappingURL=ViewBox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ViewBox.js","sourceRoot":"","sources":["../../../src/engine-components/web/ViewBox.ts"],"names":[],"mappings":"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"}
@@ -2,3 +2,4 @@ export * from "./Clickthrough.js";
2
2
  export * from "./CursorFollow.js";
3
3
  export * from "./HoverAnimation.js";
4
4
  export * from "./ScrollFollow.js";
5
+ export * from "./ViewBox.js";
@@ -2,4 +2,5 @@ export * from "./Clickthrough.js";
2
2
  export * from "./CursorFollow.js";
3
3
  export * from "./HoverAnimation.js";
4
4
  export * from "./ScrollFollow.js";
5
+ export * from "./ViewBox.js";
5
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/engine-components/web/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/engine-components/web/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/engine",
3
- "version": "4.10.0-beta",
3
+ "version": "4.10.0-beta.2",
4
4
  "description": "Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.",
5
5
  "main": "dist/needle-engine.min.js",
6
6
  "exports": {
@@ -142,6 +142,7 @@ import { ClickThrough } from "../../engine-components/web/Clickthrough.js";
142
142
  import { CursorFollow } from "../../engine-components/web/CursorFollow.js";
143
143
  import { HoverAnimation } from "../../engine-components/web/HoverAnimation.js";
144
144
  import { ScrollFollow } from "../../engine-components/web/ScrollFollow.js";
145
+ import { ViewBox } from "../../engine-components/web/ViewBox.js";
145
146
  import { Avatar } from "../../engine-components/webxr/Avatar.js";
146
147
  import { XRControllerFollow } from "../../engine-components/webxr/controllers/XRControllerFollow.js";
147
148
  import { XRControllerModel } from "../../engine-components/webxr/controllers/XRControllerModel.js";
@@ -300,6 +301,7 @@ TypeStore.add("ClickThrough", ClickThrough);
300
301
  TypeStore.add("CursorFollow", CursorFollow);
301
302
  TypeStore.add("HoverAnimation", HoverAnimation);
302
303
  TypeStore.add("ScrollFollow", ScrollFollow);
304
+ TypeStore.add("ViewBox", ViewBox);
303
305
  TypeStore.add("Avatar", Avatar);
304
306
  TypeStore.add("XRControllerFollow", XRControllerFollow);
305
307
  TypeStore.add("XRControllerModel", XRControllerModel);
@@ -87,7 +87,7 @@ export type FitCameraReturnType = {
87
87
  }
88
88
 
89
89
 
90
- export function fitCamera(objectsOrOptions?: Object3D | Array<Object3D> | FitCameraOptions, options?: FitCameraOptions): null | FitCameraReturnType {
90
+ export function fitCamera(options?: FitCameraOptions): null | FitCameraReturnType {
91
91
 
92
92
  if (NeedleXRSession.active) {
93
93
  // camera fitting in XR is not supported
@@ -102,37 +102,6 @@ export function fitCamera(objectsOrOptions?: Object3D | Array<Object3D> | FitCam
102
102
  }
103
103
  const camera = options?.camera || context.mainCamera;
104
104
 
105
- let objects: Object3D | Array<Object3D> | undefined = undefined;
106
- // If the user passed in an array as first argument
107
- if (Array.isArray(objectsOrOptions)) {
108
- objects = objectsOrOptions;
109
- }
110
- // If the user passed in an object as first argument
111
- else if (objectsOrOptions && "type" in objectsOrOptions) {
112
- objects = objectsOrOptions;
113
- }
114
- // If the user passed in an object as first argument and options as second argument
115
- else if (objectsOrOptions && typeof objectsOrOptions === "object") {
116
- if (!(objectsOrOptions instanceof Object3D) && !Array.isArray(objectsOrOptions)) {
117
- options = objectsOrOptions;
118
- objects = options.objects;
119
- }
120
- }
121
- // Ensure objects are setup correctly
122
- if (objects && !Array.isArray(objects)) {
123
- objects = [objects];
124
- }
125
- if (!Array.isArray(objects) || objects && objects.length <= 0) {
126
- objects = context.scene.children;
127
- }
128
-
129
- // Make sure there's anything to fit to
130
- if (!Array.isArray(objects) || objects.length <= 0) {
131
- console.warn("No objects to fit camera to...");
132
- return null;
133
- }
134
-
135
-
136
105
  // const controls = this._controls as ThreeOrbitControls | null;
137
106
 
138
107
  if (!camera) {
@@ -155,6 +124,7 @@ export function fitCamera(objectsOrOptions?: Object3D | Array<Object3D> | FitCam
155
124
  const size = new Vector3();
156
125
  const center = new Vector3();
157
126
  const aspect = camera instanceof PerspectiveCamera ? camera.aspect : 1;
127
+ const objects = options.objects || context.scene;
158
128
  // TODO would be much better to calculate the bounds in camera space instead of world space -
159
129
  // we would get proper view-dependant fit.
160
130
  // Right now it's independent from where the camera is actually looking from,
@@ -52,15 +52,23 @@ export type FocusRectSettings = {
52
52
  /** Lower values will result in faster alignment with the rect (value ~= seconds to reach target)
53
53
  * Minimum value is 0.
54
54
  */
55
- damping: number
55
+ damping: number,
56
+
57
+ /** X offset in camera coordinates. Used by ViewBox component */
58
+ offsetX: number,
59
+ /** Y offset in camera coordinates. Used by ViewBox component */
60
+ offsetY: number,
61
+ /** Zoom factor. Used by ViewBox component */
62
+ zoom: number,
56
63
  }
57
64
  export type FocusRect = DOMRect | Element | { x: number, y: number, width: number, height: number };
58
65
 
59
66
  let rendererRect: DOMRect | undefined = undefined;
60
67
  const overlapRect = { x: 0, y: 0, width: 0, height: 0 };
68
+ const _testTime = 1;
61
69
 
62
70
  /** Used internally by the Needle Engine context via 'setFocusRect(<rect>)' */
63
- export function updateCameraFocusRect(focusRect: FocusRect, dt: number, camera: PerspectiveCamera, renderer: WebGLRenderer) {
71
+ export function updateCameraFocusRect(focusRect: FocusRect, settings: FocusRectSettings, dt: number, camera: PerspectiveCamera, renderer: WebGLRenderer) {
64
72
 
65
73
  if (focusRect instanceof Element) {
66
74
  focusRect = focusRect.getBoundingClientRect();
@@ -76,16 +84,62 @@ export function updateCameraFocusRect(focusRect: FocusRect, dt: number, camera:
76
84
  rect.x -= rendererRect.x;
77
85
  rect.y -= rendererRect.y;
78
86
 
79
- const targetX = rect.width / -2 - (rect.x - (rendererRect.width / 2));
80
- const targetY = rect.height / -2 - (rect.y - (rendererRect.height / 2));
87
+ const sourceWidth = rendererRect.width;
88
+ const sourceHeight = rendererRect.height;
81
89
 
82
- const view = camera.view;
90
+ const view = camera.view as PerspectiveCamera["view"];
83
91
 
92
+ // Apply zoom
93
+ const zoom = settings.zoom;
84
94
  let offsetX = view?.offsetX || 0;
85
95
  let offsetY = view?.offsetY || 0;
86
- offsetX = Mathf.lerp(offsetX, targetX, dt);
87
- offsetY = Mathf.lerp(offsetY, targetY, dt);
88
96
 
89
- camera.setViewOffset(rendererRect.width, rendererRect.height, offsetX, offsetY, rendererRect.width, rendererRect.height);
97
+ let width = rendererRect.width;
98
+ let height = rendererRect.height;
99
+ width /= zoom;
100
+ height /= zoom;
101
+ offsetX = width * (zoom - 1) * .5;
102
+ offsetY = height * (zoom - 1) * .5;
103
+
104
+ const focusRectCenterX = rect.x + rect.width * .5;
105
+ const focusRectCenterY = rect.y + rect.height * .5;
106
+ const rendererCenterX = rendererRect.width * .5;
107
+ const rendererCenterY = rendererRect.height * .5;
108
+
109
+ const diffx = focusRectCenterX - rendererCenterX;
110
+ const diffy = focusRectCenterY - rendererCenterY;
111
+ offsetX -= diffx / zoom;
112
+ offsetY -= diffy / zoom;
113
+ if (settings.offsetX !== undefined) {
114
+ offsetX += settings.offsetX * (rendererRect.width * .5);
115
+ }
116
+ if (settings.offsetY !== undefined) {
117
+ offsetY -= settings.offsetY * (rendererRect.height * .5);
118
+ }
119
+
120
+
121
+ const currentOffsetX = view?.offsetX || offsetX;
122
+ const currentOffsetY = view?.offsetY || offsetY;
123
+ offsetX = Mathf.lerp(currentOffsetX, offsetX, dt);
124
+ offsetY = Mathf.lerp(currentOffsetY, offsetY, dt);
125
+ const currentWidth = view?.width || sourceWidth;
126
+ const currentHeight = view?.height || sourceHeight;
127
+ width = Mathf.lerp(currentWidth, width, dt);
128
+ height = Mathf.lerp(currentHeight, height, dt);
129
+
130
+ camera.setViewOffset(sourceWidth, sourceHeight, offsetX, offsetY, width, height);
90
131
  camera.updateProjectionMatrix();
132
+
133
+ if (settings.damping > 0) {
134
+ settings.damping *= (1.0 - dt);
135
+ if (settings.damping < 0.01) settings.damping = 0;
136
+ settings.damping = Math.max(0, settings.damping);
137
+ }
138
+ }
139
+
140
+
141
+ function fit(width1: number, height1: number, width2: number, height2: number) {
142
+ const scaleX = width2 / width1;
143
+ const scaleY = height2 / height1;
144
+ return Math.max(scaleX, scaleY);
91
145
  }
@@ -1382,21 +1382,61 @@ export class Context implements IContext {
1382
1382
  * @param settings Optional settings for the focus rect. These will override the `focusRectSettings` property
1383
1383
  */
1384
1384
  public setCameraFocusRect(rect: FocusRect | null, settings?: Partial<FocusRectSettings>) {
1385
+ const oldRect = this._focusRect;
1385
1386
  this._focusRect = rect;
1386
1387
  if (settings) {
1387
1388
  Object.assign(this.focusRectSettings, settings);
1388
1389
  }
1390
+ if (settings?.damping === undefined) {
1391
+ // if the new rect is on screen then set damping
1392
+ if (oldRect) {
1393
+ let domRect = oldRect as DOMRect;
1394
+ if (oldRect instanceof HTMLElement) {
1395
+ domRect = oldRect.getBoundingClientRect();
1396
+ }
1397
+ if (domRect && "top" in domRect) {
1398
+ const allowedDistance = 100;
1399
+ const isVisible = domRect.bottom >= -allowedDistance && domRect.right >= -allowedDistance && domRect.top <= window.innerHeight + allowedDistance && domRect.left <= window.innerWidth + allowedDistance;
1400
+ if (isVisible) this.focusRectSettings.damping = .2;
1401
+ }
1402
+ }
1403
+ }
1404
+
1389
1405
  }
1390
1406
  get focusRect() { return this._focusRect; }
1407
+ get focusRectSize(): null | { x: number, y: number, width: number, height: number } {
1408
+ const rect = this._focusRect;
1409
+ if (rect && (rect instanceof DOMRect || ("width" in rect && "height" in rect && "x" in rect && "y" in rect))) {
1410
+ return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };
1411
+ }
1412
+ else if (rect instanceof HTMLElement) {
1413
+ const r = rect.getBoundingClientRect();
1414
+ return { x: r.x, y: r.y, width: r.width, height: r.height };
1415
+ }
1416
+ return null;
1417
+ }
1391
1418
  /** Settings when a focus rect is set. Use `setCameraFocusRect(...)` to do so.
1392
1419
  * This can be used to offset the renderer center e.g. to a specific DOM element.
1393
1420
  */
1394
1421
  readonly focusRectSettings: FocusRectSettings = {
1395
1422
  /** Controls how fast the rect is centered. Smaller values mean the rect is centered faster.
1396
1423
  * A minimum value of 0 means the rect is centered instantly.
1397
- * @default .05
1424
+ * @default 0
1398
1425
  */
1399
- damping: .05
1426
+ damping: 0,
1427
+
1428
+ /**
1429
+ * Zoom factor when a focus rect is set.
1430
+ */
1431
+ zoom: 1,
1432
+ /**
1433
+ * Additional offset in pixels from the center of the rect
1434
+ */
1435
+ offsetX: 0,
1436
+ /**
1437
+ * Additional offset in pixels from the center of the rect
1438
+ */
1439
+ offsetY: 0,
1400
1440
  };
1401
1441
  private _focusRect: FocusRect | null = null;
1402
1442
 
@@ -1528,14 +1568,6 @@ export class Context implements IContext {
1528
1568
 
1529
1569
  if (this.isVisibleToUser || this.runInBackground) {
1530
1570
 
1531
- if (this._focusRect) {
1532
- if (this.mainCamera instanceof PerspectiveCamera) {
1533
- const settings = this.focusRectSettings;
1534
- const dt = settings.damping > 0 ? this.time.deltaTime / settings.damping : 1;
1535
- updateCameraFocusRect(this._focusRect, dt, this.mainCamera, this.renderer);
1536
- }
1537
- }
1538
-
1539
1571
  this._currentFrameEvent = FrameEvent.OnBeforeRender;
1540
1572
 
1541
1573
  // should we move these callbacks in the regular three onBeforeRender events?
@@ -1552,6 +1584,14 @@ export class Context implements IContext {
1552
1584
  this.executeCoroutines(FrameEvent.OnBeforeRender);
1553
1585
  invokeLifecycleFunctions(this, FrameEvent.OnBeforeRender);
1554
1586
 
1587
+ if (this._focusRect) {
1588
+ if (this.mainCamera instanceof PerspectiveCamera) {
1589
+ const settings = this.focusRectSettings;
1590
+ const dt = settings.damping > 0 ? this.time.deltaTime / settings.damping : 1;
1591
+ updateCameraFocusRect(this._focusRect, this.focusRectSettings, dt, this.mainCamera, this.renderer);
1592
+ }
1593
+ }
1594
+
1555
1595
  if (this._needsUpdateSize)
1556
1596
  this.updateSize();
1557
1597
 
@@ -1,7 +1,7 @@
1
1
  import { ShaderChunk, Texture, UniformsLib, Vector4 } from "three";
2
2
 
3
3
  import { setDisposable } from "./engine_assetdatabase.js";
4
- import { Context } from "./engine_setup.js";
4
+ import type { Context } from "./engine_setup.js";
5
5
  import type { SourceIdentifier } from "./engine_types.js";
6
6
  import { getParam } from "./engine_utils.js";
7
7
  import { LightmapType } from "./extensions/NEEDLE_lightmaps.js";
@@ -27,22 +27,22 @@ export interface ILightDataRegistry {
27
27
 
28
28
  export class LightDataRegistry implements ILightDataRegistry {
29
29
 
30
- private _context: Context;
31
- private _lightmaps: Map<SourceIdentifier, Map<LightmapType, Texture[]>> = new Map();
30
+ private readonly context: Context;
31
+ private readonly map: Map<SourceIdentifier, Map<LightmapType, Texture[]>> = new Map();
32
32
 
33
33
  clear() {
34
- this._lightmaps.clear();
34
+ this.map.clear();
35
35
  }
36
36
 
37
37
  constructor(context: Context) {
38
- this._context = context;
38
+ this.context = context;
39
39
  }
40
40
 
41
41
  registerTexture(sourceId: SourceIdentifier, type: LightmapType, tex: Texture, index: number) {
42
42
  if (debugLightmap) console.log("Registering ", LightmapType[type] + " \"" + sourceId + "\"", tex);
43
- if (!this._lightmaps.has(sourceId))
44
- this._lightmaps.set(sourceId, new Map());
45
- const map = this._lightmaps.get(sourceId);
43
+ if (!this.map.has(sourceId))
44
+ this.map.set(sourceId, new Map());
45
+ const map = this.map.get(sourceId);
46
46
  const arr = map?.get(type) ?? [];
47
47
  if (arr.length < index) arr.length = index + 1;
48
48
  setDisposable(tex, false);
@@ -55,12 +55,12 @@ export class LightDataRegistry implements ILightDataRegistry {
55
55
  }
56
56
 
57
57
  tryGetSkybox(sourceId?: SourceIdentifier | null): Texture | null {
58
- if (debugLightmap) console.log("[Get Skybox]", sourceId, this._lightmaps)
58
+ if (debugLightmap) console.log("[Get Skybox]", sourceId, this.map)
59
59
  return this.tryGet(sourceId, LightmapType.Skybox, 0);
60
60
  }
61
61
 
62
62
  tryGetReflection(sourceId?: SourceIdentifier | null): Texture | null {
63
- if (debugLightmap) console.log("[Get Reflection]", sourceId, this._lightmaps)
63
+ if (debugLightmap) console.log("[Get Reflection]", sourceId, this.map)
64
64
  return this.tryGet(sourceId, LightmapType.Reflection, 0);
65
65
  }
66
66
 
@@ -69,7 +69,7 @@ export class LightDataRegistry implements ILightDataRegistry {
69
69
  if (debugLightmap) console.warn("Missing source id");
70
70
  return null;
71
71
  }
72
- const entry = this._lightmaps.get(sourceId);
72
+ const entry = this.map.get(sourceId);
73
73
  if (!entry) {
74
74
  if (debugLightmap) console.warn(`[Lighting] No ${LightmapType[type]} texture entry for`, sourceId);
75
75
  return null;
@@ -67,6 +67,7 @@ export class RapierPhysics implements IPhysicsEngine {
67
67
  debugRenderRaycasts: boolean = false;
68
68
 
69
69
  removeBody(obj: IComponent) {
70
+ if(debugPhysics) console.log("REMOVE BODY", obj?.name, obj[$bodyKey]);
70
71
  if (!obj) return;
71
72
  this.validate();
72
73
  const body = obj[$bodyKey];
@@ -901,6 +902,8 @@ export class RapierPhysics implements IPhysicsEngine {
901
902
  // set the collider layers
902
903
  this.updateColliderCollisionGroups(collider);
903
904
 
905
+ if (debugPhysics) console.log("Created collider", collider.name, col);
906
+
904
907
  return col;
905
908
  }
906
909
  catch (e) {
@@ -162,7 +162,7 @@ export class RendererData {
162
162
  private __currentReflectionId: SourceIdentifier | null = null;
163
163
 
164
164
  /** @internal */
165
- internalEnableReflection(sourceId: SourceIdentifier) {
165
+ internalEnableReflection(sourceId: SourceIdentifier) : Texture | null {
166
166
  this.__currentReflectionId = sourceId;
167
167
  const settings = this._sceneLightSettings?.get(sourceId);
168
168
 
@@ -181,7 +181,7 @@ export class RendererData {
181
181
  const tex = existing.Source;
182
182
  tex.mapping = EquirectangularReflectionMapping;
183
183
  scene.environment = tex;
184
- return;
184
+ return tex;
185
185
  }
186
186
  else if (debug) console.warn("Could not find reflection for source", sourceId);
187
187
  break;
@@ -196,22 +196,21 @@ export class RendererData {
196
196
  tex.colorSpace = SRGBColorSpace;
197
197
  tex.mapping = EquirectangularReflectionMapping;
198
198
  this.context.scene.environment = tex;
199
+ return tex;
199
200
  }
200
201
  else console.error("Missing ambient trilight", settings.sourceId);
201
- return;
202
202
  case AmbientMode.Flat:
203
203
  if (settings.ambientLight) {
204
204
  const tex = createFlatTexture(settings.ambientLight, 64);
205
205
  tex.colorSpace = SRGBColorSpace;
206
206
  tex.mapping = EquirectangularReflectionMapping;
207
207
  this.context.scene.environment = tex;
208
+ return tex;
208
209
  }
209
210
  else console.error("Missing ambientlight", settings.sourceId);
210
- return;
211
- default:
212
- return;
213
211
  }
214
212
  }
213
+ return null;
215
214
  }
216
215
 
217
216
  /** @internal */
@@ -381,6 +381,14 @@ 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
+
384
392
  // export function getPath(glbLocation: SourceIdentifier | undefined, path: string) {
385
393
  // if (path && glbLocation && !path.includes("/")) {
386
394
  // // get directory of glb and prepend it to the audio file path
@@ -793,6 +801,7 @@ const mutationObserverMap = new WeakMap<HTMLElement, HtmlElementExtra>();
793
801
  /**
794
802
  * Register a callback when an {@link HTMLElement} attribute changes.
795
803
  * 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
796
805
  */
797
806
  export function addAttributeChangeCallback(domElement: HTMLElement, name: string, callback: AttributeChangeCallback) {
798
807
  if (!mutationObserverMap.get(domElement)) {
@@ -811,6 +820,9 @@ export function addAttributeChangeCallback(domElement: HTMLElement, name: string
811
820
  listeners.set(name, []);
812
821
  }
813
822
  listeners.get(name)!.push(callback);
823
+ return () => {
824
+ removeAttributeChangeCallback(domElement, name, callback);
825
+ }
814
826
  };
815
827
 
816
828
  /**
@@ -107,7 +107,7 @@ export class NEEDLE_lightmaps implements GLTFLoaderPlugin {
107
107
 
108
108
  private resolveTexture(entry: LightmapInfo, res: any) {
109
109
  const tex: Texture = res as unknown as Texture;
110
- if (debug) console.log("Lightmap loaded:", tex);
110
+ if (debug) console.log("Light Texture loaded:", tex);
111
111
  if (tex?.isTexture) {
112
112
  if (!this.registry)
113
113
  console.log(LightmapType[entry.type], entry.pointer, tex);