@needle-tools/engine 4.17.0-alpha.4 → 4.17.0-alpha.6

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 (50) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/components.needle.json +1 -1
  3. package/dist/{gltf-progressive-Ck_bXBr_.umd.cjs → gltf-progressive-BBIL1q1j.umd.cjs} +1 -1
  4. package/dist/{gltf-progressive-BJ9OrddA.js → gltf-progressive-BbHl9z0v.js} +1 -1
  5. package/dist/{gltf-progressive-CqZYu6Hx.min.js → gltf-progressive-Clq_N7Zx.min.js} +1 -1
  6. package/dist/{needle-engine.bundle-CK9xKTOH.umd.cjs → needle-engine.bundle-C1xcWOZy.umd.cjs} +127 -127
  7. package/dist/{needle-engine.bundle-BymlzaH_.js → needle-engine.bundle-Cw8eM4ZI.js} +4653 -4681
  8. package/dist/{needle-engine.bundle-D-7jnOxH.min.js → needle-engine.bundle-D5FX_w-u.min.js} +127 -127
  9. package/dist/needle-engine.d.ts +12 -49
  10. package/dist/needle-engine.js +3 -3
  11. package/dist/needle-engine.min.js +1 -1
  12. package/dist/needle-engine.umd.cjs +1 -1
  13. package/lib/engine-components/AlignmentConstraint.d.ts +0 -1
  14. package/lib/engine-components/AlignmentConstraint.js +0 -1
  15. package/lib/engine-components/AlignmentConstraint.js.map +1 -1
  16. package/lib/engine-components/BasicIKConstraint.d.ts +0 -1
  17. package/lib/engine-components/BasicIKConstraint.js +0 -1
  18. package/lib/engine-components/BasicIKConstraint.js.map +1 -1
  19. package/lib/engine-components/LookAtConstraint.d.ts +1 -38
  20. package/lib/engine-components/LookAtConstraint.js +1 -58
  21. package/lib/engine-components/LookAtConstraint.js.map +1 -1
  22. package/lib/engine-components/OffsetConstraint.d.ts +0 -1
  23. package/lib/engine-components/OffsetConstraint.js +0 -1
  24. package/lib/engine-components/OffsetConstraint.js.map +1 -1
  25. package/lib/engine-components/OrbitControls.d.ts +11 -7
  26. package/lib/engine-components/OrbitControls.js +35 -25
  27. package/lib/engine-components/OrbitControls.js.map +1 -1
  28. package/lib/engine-components/SmoothFollow.d.ts +0 -1
  29. package/lib/engine-components/SmoothFollow.js +0 -1
  30. package/lib/engine-components/SmoothFollow.js.map +1 -1
  31. package/lib/engine-components/web/CursorFollow.d.ts +0 -1
  32. package/lib/engine-components/web/CursorFollow.js +0 -1
  33. package/lib/engine-components/web/CursorFollow.js.map +1 -1
  34. package/lib/engine-components/web/ViewBox.d.ts +0 -1
  35. package/lib/engine-components/web/ViewBox.js +0 -1
  36. package/lib/engine-components/web/ViewBox.js.map +1 -1
  37. package/package.json +2 -2
  38. package/plugins/vite/asap.js +4 -0
  39. package/plugins/vite/build-pipeline.js +13 -0
  40. package/plugins/vite/dependencies.js +1 -1
  41. package/plugins/vite/poster-client.js +1 -1
  42. package/src/engine-components/AlignmentConstraint.ts +0 -1
  43. package/src/engine-components/BasicIKConstraint.ts +0 -1
  44. package/src/engine-components/LookAtConstraint.ts +2 -53
  45. package/src/engine-components/OffsetConstraint.ts +0 -1
  46. package/src/engine-components/OrbitControls.ts +30 -23
  47. package/src/engine-components/SmoothFollow.ts +0 -1
  48. package/src/engine-components/web/CursorFollow.ts +0 -1
  49. package/src/engine-components/web/ViewBox.ts +0 -2
  50. /package/dist/{loader.worker-CCrD-Ycm.js → gltf-progressive.worker-CCrD-Ycm.js} +0 -0
@@ -227,6 +227,10 @@ function insertPreloadLink(tags, href, type) {
227
227
  attrs: {
228
228
  rel: "preload",
229
229
  as: "fetch",
230
+ // Use low priority so glTF/GLB downloads don't compete with JS chunks
231
+ // for bandwidth. The engine JS must load first to render anything;
232
+ // the GLB still starts downloading early but yields bandwidth to scripts.
233
+ fetchpriority: "low",
230
234
  href: href,
231
235
  type: type,
232
236
  crossorigin: true,
@@ -210,6 +210,19 @@ export async function needleBuildPipeline(command, config, userSettings) {
210
210
  const moved = getDirectoryStats(buildPipelineTaskResults.tempDirectory);
211
211
  const ctx = { count: 0, bytes: 0 }
212
212
  copyFilesSync(buildPipelineTaskResults.tempDirectory, buildPipelineTaskResults.outputDirectory, true, ctx);
213
+ // Clean up source files that were replaced by the build pipeline
214
+ // (e.g. .exr files that now have .pmrem.ktx2 replacements)
215
+ const outputDir = buildPipelineTaskResults.outputDirectory;
216
+ try {
217
+ for (const file of readdirSync(outputDir)) {
218
+ if (file.endsWith('.exr')) {
219
+ const replacement = file.replace(/\.exr$/i, '.pmrem.ktx2');
220
+ if (existsSync(outputDir + '/' + replacement)) {
221
+ rmSync(outputDir + '/' + file);
222
+ }
223
+ }
224
+ }
225
+ } catch { /* silent */ }
213
226
  lines.push(`${key("Copying compressed results")}: "${outputPath}" — ${moved.fileCount} file${moved.fileCount !== 1 ? 's' : ''}, ${formatBytes(moved.totalBytes)}`);
214
227
  }
215
228
  else {
@@ -131,7 +131,7 @@ function handleManualChunks(config) {
131
131
  isVite8 = parseInt(JSON.parse(readFileSync(vitePkgPath, 'utf8')).version) >= 8;
132
132
  }
133
133
  } catch { }
134
- needleLog("needle-dependencies", `Vite 8+ detected: ${isVite8}`);
134
+ if (isVite8) needleLog("needle-dependencies", `Vite 8+ detected`);
135
135
 
136
136
  if (Array.isArray(rollupOutput)) {
137
137
  // append the manualChunks function to the array
@@ -7,7 +7,7 @@ async function generatePoster() {
7
7
  // Keep in sync with og:image:width meta tags
8
8
  // https://developers.facebook.com/docs/sharing/best-practices/
9
9
  const width = 1080;
10
- const height = 1080;
10
+ const height = width * (9 / 16);
11
11
 
12
12
  return new Promise(res => {
13
13
  /** @ts-ignore */
@@ -29,7 +29,6 @@ import { Behaviour, GameObject } from "./Component.js";
29
29
  * @summary Aligns and scales object between two targets
30
30
  * @category Constraints
31
31
  * @group Components
32
- * @see {@link LookAtConstraint} for rotation-only constraints
33
32
  * @see {@link SmoothFollow} for following with smoothing
34
33
  **/
35
34
  export class AlignmentConstraint extends Behaviour {
@@ -31,7 +31,6 @@ import { Behaviour, GameObject } from "./Component.js";
31
31
  * @summary Two-bone inverse kinematics constraint
32
32
  * @category Animation and Sequencing
33
33
  * @group Components
34
- * @see {@link LookAtConstraint} for aim constraints
35
34
  * @see {@link AlignmentConstraint} for simpler alignment
36
35
  */
37
36
  export class BasicIKConstraint extends Behaviour {
@@ -1,58 +1,7 @@
1
- import { Object3D, Vector3 } from "three";
2
-
3
- import { serializable } from "../engine/engine_serialization_decorator.js";
4
- import type { LookAt } from "./api.js";
5
1
  import { Behaviour } from "./Component.js";
6
- import type { OrbitControls } from "./OrbitControls.js";
7
2
 
8
3
  /**
9
- * The [LookAtConstraint](https://engine.needle.tools/docs/api/LookAtConstraint) component is primarely used by {@link OrbitControls} to set the camera's focus point.
10
- * It does not have its own logic to update the look-at position.
11
- *
12
- * The constraint uses a list of source objects - the look-at target is
13
- * calculated from the first source in the `sources` array.
14
- *
15
- * **Integration with OrbitControls:**
16
- * When attached to the same GameObject as OrbitControls, this constraint
17
- * controls where the camera orbits around and looks at.
18
- *
19
- * @summary Look At Constraint for camera targeting
20
- * @category Camera and Controls
21
- * @group Components
22
- * @see {@link OrbitControls} for camera orbit controls
23
- * @see {@link SmoothFollow} for smooth position/rotation following
24
- * @see {@link LookAt} for directly making an object look at a target without using a constraint
4
+ * @deprecated LookAtConstraint has been removed. Use a plain Object3D/Transform reference on OrbitControls instead.
25
5
  */
26
6
  export class LookAtConstraint extends Behaviour {
27
-
28
- /**
29
- * When true, the constraint is active and affects the target.
30
- * Set to false to temporarily disable without removing sources.
31
- */
32
- @serializable()
33
- constraintActive: boolean = true;
34
-
35
- /**
36
- * When true, the look-at position is locked and won't update
37
- * even if source objects move.
38
- */
39
- @serializable()
40
- locked: boolean = false;
41
-
42
- /**
43
- * Objects to look at. The first object in the array is used
44
- * as the primary look-at target.
45
- */
46
- @serializable(Object3D)
47
- sources: Object3D[] = [];
48
-
49
- /**
50
- * Sets the world position that the constraint should look at.
51
- * Updates the first source object's position.
52
- * @param worldPosition The world-space position to look at
53
- */
54
- setConstraintPosition(worldPosition: Vector3) {
55
- const source = this.sources[0];
56
- if (source) source.worldPosition = worldPosition;
57
- }
58
- }
7
+ }
@@ -32,7 +32,6 @@ import { Behaviour, GameObject } from "./Component.js";
32
32
  * @category Constraints
33
33
  * @group Components
34
34
  * @see {@link SmoothFollow} for smoothed following
35
- * @see {@link LookAtConstraint} for aim constraints
36
35
  * @see {@link AlignmentConstraint} for alignment between two objects
37
36
  */
38
37
  export class OffsetConstraint extends Behaviour {
@@ -15,7 +15,6 @@ import { DeviceUtilities, getParam } from "../engine/engine_utils.js";
15
15
  import { NeedleEngineWebComponent } from "../engine/webcomponents/needle-engine.js";
16
16
  import { Camera } from "./Camera.js";
17
17
  import { Behaviour, GameObject } from "./Component.js";
18
- import { LookAtConstraint } from "./LookAtConstraint.js";
19
18
  import { SyncedTransform } from "./SyncedTransform.js";
20
19
  import { type AfterHandleInputEvent, EventSystem, EventSystemEvents } from "./ui/EventSystem.js";
21
20
  import { tryGetUIComponent } from "./ui/Utils.js";
@@ -99,7 +98,6 @@ declare module 'three/examples/jsm/controls/OrbitControls.js' {
99
98
  * @summary Camera controller using three.js OrbitControls
100
99
  * @category Camera and Controls
101
100
  * @group Components
102
- * @see {@link LookAtConstraint} for setting the look-at target
103
101
  * @see {@link SmoothFollow} for smooth camera following
104
102
  * @see {@link Camera} for camera configuration
105
103
  * @link https://threejs.org/docs/#examples/en/controls/OrbitControls
@@ -228,12 +226,19 @@ export class OrbitControls extends Behaviour implements ICameraController {
228
226
  */
229
227
  @serializable()
230
228
  enablePan: boolean = true;
231
- /** Assigning a {@link LookAtConstraint} will make the camera look at the constraint source
229
+ /** Assigning an Object3D will make the camera look at this target's position.
230
+ * The camera will orbit around this target.
232
231
  * @default null
233
232
  */
234
- @serializable(LookAtConstraint)
235
- lookAtConstraint: LookAtConstraint | null = null;
236
- /** The weight of the first lookAtConstraint source
233
+ @serializable(Object3D)
234
+ lookAtTarget: Object3D | null = null;
235
+ /** When enabled the camera will continuously follow the lookAtTarget's position every frame.
236
+ * When disabled the target is only used for the initial look direction.
237
+ * @default true
238
+ */
239
+ @serializable()
240
+ lockLookAtTarget: boolean = true;
241
+ /** The weight for the lookAtTarget interpolation
237
242
  * @default 1
238
243
  */
239
244
  @serializable()
@@ -392,11 +397,13 @@ export class OrbitControls extends Behaviour implements ICameraController {
392
397
  private _camera: Camera | null = null;
393
398
  private _syncedTransform?: SyncedTransform;
394
399
  private _didSetTarget = 0;
400
+ private _didApplyLookAtTarget = false;
395
401
 
396
402
  /** @internal */
397
403
  awake(): void {
398
404
  if (debug) console.debug("OrbitControls", this);
399
405
  this._didSetTarget = 0;
406
+ this._didApplyLookAtTarget = false;
400
407
  this._startedListeningToKeyEvents = false;
401
408
  if ((this.context.domElement as NeedleEngineWebComponent).cameraControls === false) {
402
409
  this.enabled = false;
@@ -421,6 +428,7 @@ export class OrbitControls extends Behaviour implements ICameraController {
421
428
  /** @internal */
422
429
  onEnable() {
423
430
  this._didSetTarget = 0;
431
+ this._didApplyLookAtTarget = false;
424
432
  this._enableTime = this.context.time.time;
425
433
  const cameraComponent = GameObject.getComponent(this.gameObject, Camera);
426
434
  this._camera = cameraComponent;
@@ -565,6 +573,7 @@ export class OrbitControls extends Behaviour implements ICameraController {
565
573
  };
566
574
 
567
575
  private updateTargetNow(options?: IRaycastOptions) {
576
+ if(debug) console.warn("OrbitControls: updateTargetNow is using raycasting to update the target immediately. This can be expensive and should be used with caution.", options);
568
577
  const ray = new Ray(this._cameraObject?.worldPosition, this._cameraObject?.worldForward.multiplyScalar(-1));
569
578
  const hits = this.context.physics.raycastFromRay(ray, options);
570
579
  const hit = hits.length > 0 ? hits[0] : undefined;
@@ -807,8 +816,14 @@ export class OrbitControls extends Behaviour implements ICameraController {
807
816
 
808
817
  // this._controls.zoomToCursor = this.zoomToCursor;
809
818
  if (!this.context.isInXR) {
810
- if (!freeCam && this.lookAtConstraint?.locked && !this._lookTargetLerpActive) {
811
- this.setLookTargetFromConstraint(0, this.lookAtConstraint01);
819
+ if (!freeCam && this.lookAtTarget && !this._lookTargetLerpActive) {
820
+ if (this.lockLookAtTarget) {
821
+ this.setLookTargetFromConstraint(this.lookAtConstraint01);
822
+ }
823
+ else if (!this._didApplyLookAtTarget) {
824
+ this._didApplyLookAtTarget = true;
825
+ this.setLookTargetFromConstraint(1);
826
+ }
812
827
  }
813
828
  this._controls.update(this.context.time.deltaTime);
814
829
 
@@ -1011,30 +1026,22 @@ export class OrbitControls extends Behaviour implements ICameraController {
1011
1026
  this._lookTargetLerpActive = false;
1012
1027
  }
1013
1028
 
1014
- /** Sets the look at target from an assigned lookAtConstraint source by index
1015
- * @param index The index of the source to use
1029
+ /** Sets the look at target from the assigned lookAtTarget Object3D
1016
1030
  * @param t The interpolation factor between the current look at target and the new target
1017
1031
  */
1018
- private setLookTargetFromConstraint(index: number = 0, t: number = 1): boolean {
1032
+ private setLookTargetFromConstraint(t: number = 1): boolean {
1019
1033
  if (!this._controls) return false;
1020
- if (this.lookAtConstraint?.enabled === false) return false;
1021
- const sources = this.lookAtConstraint?.sources;
1022
- if (sources && sources.length > 0) {
1023
- const target = sources[index];
1024
- if (target) {
1025
- target.getWorldPosition(this._lookTargetEndPosition);
1026
- this.lerpLookTarget(this._controls.target, this._lookTargetEndPosition, t);
1027
- return true;
1028
- }
1029
- }
1030
- return false;
1034
+ if (!this.lookAtTarget) return false;
1035
+ this.lookAtTarget.getWorldPosition(this._lookTargetEndPosition);
1036
+ this.lerpLookTarget(this._controls.target, this._lookTargetEndPosition, t);
1037
+ return true;
1031
1038
  }
1032
1039
 
1033
1040
  private lerpLookTarget(start: Vector3, position: Vector3, t: number) {
1034
1041
  if (!this._controls) return;
1035
1042
  if (t >= 1) this._controls.target.copy(position);
1036
1043
  else this._controls.target.lerpVectors(start, position, t);
1037
- if (this.lookAtConstraint) this.lookAtConstraint.setConstraintPosition(this._controls.target);
1044
+ if (this.lookAtTarget && this.lockLookAtTarget) this.lookAtTarget.worldPosition = this._controls.target;
1038
1045
  }
1039
1046
 
1040
1047
  private setTargetFromRaycast(ray?: Ray, immediateOrDuration: number | boolean = false): boolean {
@@ -54,7 +54,6 @@ import { Behaviour } from "./Component.js";
54
54
  * @summary Smoothly follows a target object's position and/or rotation
55
55
  * @category Interactivity
56
56
  * @group Components
57
- * @see {@link LookAtConstraint} for making an object look at a target (different from rotation following)
58
57
  * @see {@link Mathf} for the interpolation used
59
58
  */
60
59
  export class SmoothFollow extends Behaviour {
@@ -78,7 +78,6 @@ const debug = getParam("debugcursor");
78
78
  *
79
79
  * - Example: [Look At Cursor sample](https://engine.needle.tools/samples/look-at-cursor-interactive-3d-header/) - Combines CursorFollow with LookAt for an interactive 3D header
80
80
  *
81
- * @see {@link LookAtConstraint} - Commonly combined with CursorFollow for look-at effects
82
81
  * @see {@link PointerEvents} - For more complex pointer interaction handling
83
82
  * @see {@link DragControls} - For dragging objects in 3D space
84
83
  * @see {@link OrbitControls} - For camera controls that work alongside CursorFollow
@@ -12,7 +12,6 @@ import { RGBAColor } from "../../engine/js-extensions/RGBAColor.js";
12
12
  import type { Camera as CameraComponent } from "../Camera.js";
13
13
  import { Behaviour } from "../Component.js";
14
14
  import type { DragControls } from "../DragControls.js";
15
- import type { LookAtConstraint } from "../LookAtConstraint.js";
16
15
  import type { OrbitControls } from "../OrbitControls.js";
17
16
  import type { SceneSwitcher } from "../SceneSwitcher.js";
18
17
 
@@ -93,7 +92,6 @@ export type ViewBoxMode = "continuous" | "once";
93
92
  * @see {@link CameraComponent} - The camera component that ViewBox controls
94
93
  * @see {@link OrbitControls} - Camera controls that work alongside ViewBox
95
94
  * @see {@link DragControls} - Alternative camera controls compatible with ViewBox
96
- * @see {@link LookAtConstraint} - Another way to control camera targeting
97
95
  * @see {@link SceneSwitcher} - Can be combined with ViewBox for scene transitions
98
96
  * @see {@link Context.setCameraFocusRect} - The underlying focus rect API used by ViewBox
99
97
  * @see {@link Context.focusRectSettings} - Manual control of focus rect settings