@needle-tools/engine 4.9.2 → 4.9.3-next.0facab6

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 (105) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/components.needle.json +1 -1
  3. package/dist/{gltf-progressive-DhE1A6hX.min.js → gltf-progressive-CoZbSfPR.min.js} +1 -1
  4. package/dist/{gltf-progressive-egsMzRdv.js → gltf-progressive-DUR9TuAH.js} +3 -3
  5. package/dist/{gltf-progressive-DWiyqrwB.umd.cjs → gltf-progressive-Iy7aSAPk.umd.cjs} +1 -1
  6. package/dist/{needle-engine.bundle-WLYWw5OF.umd.cjs → needle-engine.bundle-DAo7BPxQ.umd.cjs} +149 -127
  7. package/dist/needle-engine.bundle-DP2gYtOQ.min.js +1638 -0
  8. package/dist/{needle-engine.bundle-XBRfMDwo.js → needle-engine.bundle-TvT7wv7z.js} +7567 -7380
  9. package/dist/needle-engine.js +446 -444
  10. package/dist/needle-engine.min.js +1 -1
  11. package/dist/needle-engine.umd.cjs +1 -1
  12. package/dist/{postprocessing-B_FzkwDz.min.js → postprocessing-BHMVuZQ1.min.js} +53 -53
  13. package/dist/{postprocessing-DTX5VXrj.umd.cjs → postprocessing-BsnRNRRS.umd.cjs} +76 -76
  14. package/dist/{postprocessing-DP1U_BpT.js → postprocessing-DQ2pynXW.js} +213 -191
  15. package/dist/{three-BK56xWDs.umd.cjs → three-B-jwTHao.umd.cjs} +11 -11
  16. package/dist/{three-CsHK73Zc.js → three-CJSAehtG.js} +1 -0
  17. package/dist/{three-examples-Bph291U2.min.js → three-examples-BivkhnvN.min.js} +1 -1
  18. package/dist/{three-examples-C9WfZu-X.umd.cjs → three-examples-Deqc1bNw.umd.cjs} +1 -1
  19. package/dist/{three-examples-BvMpKSun.js → three-examples-Doq0rvFU.js} +1 -1
  20. package/dist/{three-mesh-ui-CN6aRT7i.js → three-mesh-ui-CktOi6oI.js} +1 -1
  21. package/dist/{three-mesh-ui-DnxkZWNA.umd.cjs → three-mesh-ui-CsHwj9cJ.umd.cjs} +1 -1
  22. package/dist/{three-mesh-ui-n_qS2BM-.min.js → three-mesh-ui-DhYXcXZe.min.js} +1 -1
  23. package/dist/{three-TNFQHSFa.min.js → three-qw28ZtTy.min.js} +10 -10
  24. package/dist/{vendor-BtJpSuCj.umd.cjs → vendor-D0Yvltn9.umd.cjs} +1 -1
  25. package/dist/{vendor-k9i6CeGi.js → vendor-DU8tJyl_.js} +1 -1
  26. package/dist/{vendor-XJ9xiwrv.min.js → vendor-JyrX4DVM.min.js} +1 -1
  27. package/lib/engine/api.d.ts +1 -0
  28. package/lib/engine/api.js +1 -0
  29. package/lib/engine/api.js.map +1 -1
  30. package/lib/engine/codegen/register_types.js +2 -0
  31. package/lib/engine/codegen/register_types.js.map +1 -1
  32. package/lib/engine/engine_animation.d.ts +21 -1
  33. package/lib/engine/engine_animation.js +32 -1
  34. package/lib/engine/engine_animation.js.map +1 -1
  35. package/lib/engine/engine_camera.fit.d.ts +68 -0
  36. package/lib/engine/engine_camera.fit.js +193 -0
  37. package/lib/engine/engine_camera.fit.js.map +1 -0
  38. package/lib/engine/engine_gizmos.d.ts +2 -2
  39. package/lib/engine/engine_gizmos.js +2 -2
  40. package/lib/engine/engine_physics.js +6 -3
  41. package/lib/engine/engine_physics.js.map +1 -1
  42. package/lib/engine/webcomponents/needle-engine.d.ts +1 -0
  43. package/lib/engine/webcomponents/needle-engine.js +6 -0
  44. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  45. package/lib/engine/webcomponents/needle-engine.loading.js +59 -23
  46. package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
  47. package/lib/engine/xr/NeedleXRSession.d.ts +1 -0
  48. package/lib/engine/xr/NeedleXRSession.js +25 -11
  49. package/lib/engine/xr/NeedleXRSession.js.map +1 -1
  50. package/lib/engine-components/AnimatorController.js +16 -0
  51. package/lib/engine-components/AnimatorController.js.map +1 -1
  52. package/lib/engine-components/CameraUtils.js +8 -9
  53. package/lib/engine-components/CameraUtils.js.map +1 -1
  54. package/lib/engine-components/OrbitControls.d.ts +4 -47
  55. package/lib/engine-components/OrbitControls.js +30 -178
  56. package/lib/engine-components/OrbitControls.js.map +1 -1
  57. package/lib/engine-components/Renderer.js +9 -5
  58. package/lib/engine-components/Renderer.js.map +1 -1
  59. package/lib/engine-components/SpriteRenderer.js +4 -1
  60. package/lib/engine-components/SpriteRenderer.js.map +1 -1
  61. package/lib/engine-components/api.d.ts +0 -1
  62. package/lib/engine-components/api.js.map +1 -1
  63. package/lib/engine-components/codegen/components.d.ts +1 -0
  64. package/lib/engine-components/codegen/components.js +1 -0
  65. package/lib/engine-components/codegen/components.js.map +1 -1
  66. package/lib/engine-components/web/Clickthrough.d.ts +3 -0
  67. package/lib/engine-components/web/Clickthrough.js +3 -0
  68. package/lib/engine-components/web/Clickthrough.js.map +1 -1
  69. package/lib/engine-components/web/CursorFollow.d.ts +3 -0
  70. package/lib/engine-components/web/CursorFollow.js +3 -0
  71. package/lib/engine-components/web/CursorFollow.js.map +1 -1
  72. package/lib/engine-components/web/HoverAnimation.d.ts +44 -0
  73. package/lib/engine-components/web/HoverAnimation.js +105 -0
  74. package/lib/engine-components/web/HoverAnimation.js.map +1 -0
  75. package/lib/engine-components/web/ScrollFollow.d.ts +4 -0
  76. package/lib/engine-components/web/ScrollFollow.js +4 -0
  77. package/lib/engine-components/web/ScrollFollow.js.map +1 -1
  78. package/lib/engine-components/web/index.d.ts +1 -0
  79. package/lib/engine-components/web/index.js +1 -0
  80. package/lib/engine-components/web/index.js.map +1 -1
  81. package/package.json +2 -2
  82. package/plugins/vite/alias.js +5 -3
  83. package/plugins/vite/poster-client.js +22 -21
  84. package/src/engine/api.ts +2 -1
  85. package/src/engine/codegen/register_types.ts +2 -0
  86. package/src/engine/engine_animation.ts +69 -1
  87. package/src/engine/engine_camera.fit.ts +288 -0
  88. package/src/engine/engine_gizmos.ts +2 -2
  89. package/src/engine/engine_physics.ts +6 -3
  90. package/src/engine/webcomponents/needle-engine.loading.ts +63 -24
  91. package/src/engine/webcomponents/needle-engine.ts +6 -1
  92. package/src/engine/xr/NeedleXRSession.ts +25 -10
  93. package/src/engine-components/AnimatorController.ts +21 -2
  94. package/src/engine-components/CameraUtils.ts +8 -9
  95. package/src/engine-components/OrbitControls.ts +30 -239
  96. package/src/engine-components/Renderer.ts +9 -6
  97. package/src/engine-components/SpriteRenderer.ts +3 -1
  98. package/src/engine-components/api.ts +0 -1
  99. package/src/engine-components/codegen/components.ts +1 -0
  100. package/src/engine-components/web/Clickthrough.ts +3 -0
  101. package/src/engine-components/web/CursorFollow.ts +3 -0
  102. package/src/engine-components/web/HoverAnimation.ts +99 -0
  103. package/src/engine-components/web/ScrollFollow.ts +4 -0
  104. package/src/engine-components/web/index.ts +1 -0
  105. package/dist/needle-engine.bundle-DwspSk2O.min.js +0 -1616
@@ -0,0 +1,105 @@
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
+ import { AnimationClip } from "three";
8
+ import { AnimationUtils } from "../../engine/engine_animation.js";
9
+ import { serializable } from "../../engine/engine_serialization_decorator.js";
10
+ import { registerType } from "../../engine/engine_typestore.js";
11
+ import { Animation } from "../Animation.js";
12
+ import { Behaviour } from "../Component.js";
13
+ /**
14
+ * @category Web
15
+ * @group Components
16
+ * @component
17
+ */
18
+ let HoverAnimation = class HoverAnimation extends Behaviour {
19
+ /**
20
+ * Default hover animation type if no custom clip is provided.
21
+ * **Node**: This is only used if no custom hover animation clip is provided.
22
+ * @default "linear"
23
+ */
24
+ type = "linear";
25
+ /**
26
+ * Duration of the hover animation in seconds.
27
+ * **Node**: This is only used if no custom hover animation clip is provided.
28
+ * @default 0.1
29
+ */
30
+ duration = 0.1;
31
+ /**
32
+ * Scale factor to apply when hovering.
33
+ * **Node**: This is only used if no custom hover animation clip is provided.
34
+ * @default 1.1
35
+ */
36
+ scaleFactor = 1.1;
37
+ /**
38
+ * Animation clip to play when hovering. If null, a default scale-up animation is used.
39
+ */
40
+ hovered = null;
41
+ /**
42
+ * Animation clip to play when not hovering. If null, an empty clip is used.
43
+ */
44
+ idle = null;
45
+ animation = null;
46
+ start() {
47
+ if (!this.idle)
48
+ this.idle = AnimationUtils.emptyClip();
49
+ if (!this.hovered) {
50
+ this.hovered = AnimationUtils.createScaleClip({
51
+ type: "linear",
52
+ duration: this.duration || 0.1,
53
+ scale: this.gameObject.scale,
54
+ scaleFactor: this.scaleFactor || 1.1,
55
+ });
56
+ }
57
+ this.animation ??= this.gameObject.addComponent(Animation);
58
+ this.animation.playAutomatically = false;
59
+ this.playIdle();
60
+ }
61
+ onEnable() {
62
+ if (this.animation)
63
+ this.animation.enabled = true;
64
+ this.playIdle();
65
+ }
66
+ onDisable() {
67
+ if (this.animation)
68
+ this.animation.enabled = false;
69
+ this.playIdle();
70
+ }
71
+ onPointerEnter() {
72
+ this.playHover();
73
+ }
74
+ onPointerExit() {
75
+ this.playIdle();
76
+ }
77
+ playIdle() {
78
+ if (this.idle)
79
+ this.animation?.play(this.idle, { exclusive: true, fadeDuration: .1, loop: true });
80
+ }
81
+ playHover() {
82
+ if (this.hovered)
83
+ this.animation?.play(this.hovered, { exclusive: true, fadeDuration: .1, loop: false, clampWhenFinished: true });
84
+ }
85
+ };
86
+ __decorate([
87
+ serializable()
88
+ ], HoverAnimation.prototype, "type", void 0);
89
+ __decorate([
90
+ serializable()
91
+ ], HoverAnimation.prototype, "duration", void 0);
92
+ __decorate([
93
+ serializable()
94
+ ], HoverAnimation.prototype, "scaleFactor", void 0);
95
+ __decorate([
96
+ serializable(AnimationClip)
97
+ ], HoverAnimation.prototype, "hovered", void 0);
98
+ __decorate([
99
+ serializable(AnimationClip)
100
+ ], HoverAnimation.prototype, "idle", void 0);
101
+ HoverAnimation = __decorate([
102
+ registerType
103
+ ], HoverAnimation);
104
+ export { HoverAnimation };
105
+ //# sourceMappingURL=HoverAnimation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HoverAnimation.js","sourceRoot":"","sources":["../../../src/engine-components/web/HoverAnimation.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,gDAAgD,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C;;;;GAIG;AAEI,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,SAAS;IAEzC;;;;OAIG;IAEH,IAAI,GAAkB,QAAQ,CAAC;IAE/B;;;;OAIG;IAEH,QAAQ,GAAW,GAAG,CAAC;IAEvB;;;;OAIG;IAEH,WAAW,GAAW,GAAG,CAAC;IAG1B;;OAEG;IAEH,OAAO,GAAyB,IAAI,CAAC;IAErC;;OAEG;IAEH,IAAI,GAAyB,IAAI,CAAC;IAE1B,SAAS,GAAqB,IAAI,CAAC;IAE3C,KAAK;QACD,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC,SAAS,EAAE,CAAC;QAEvD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YACf,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC,eAAe,CAAC;gBAC1C,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,GAAG;gBAC9B,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK;gBAC5B,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,GAAG;aACvC,CAAC,CAAC;SACN;QAED,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC3D,IAAI,CAAC,SAAS,CAAC,iBAAiB,GAAG,KAAK,CAAC;QACzC,IAAI,CAAC,QAAQ,EAAE,CAAC;IACpB,CAAC;IAED,QAAQ;QACJ,IAAI,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;QAClD,IAAI,CAAC,QAAQ,EAAE,CAAC;IACpB,CAAC;IACD,SAAS;QACL,IAAI,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,SAAS,CAAC,OAAO,GAAG,KAAK,CAAC;QACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;IACpB,CAAC;IAED,cAAc;QACV,IAAI,CAAC,SAAS,EAAE,CAAC;IACrB,CAAC;IAED,aAAa;QACT,IAAI,CAAC,QAAQ,EAAE,CAAC;IACpB,CAAC;IAEO,QAAQ;QACZ,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACtG,CAAC;IACO,SAAS;QACb,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC;IACtI,CAAC;CAEJ,CAAA;AA1EG;IADC,YAAY,EAAE;4CACgB;AAQ/B;IADC,YAAY,EAAE;gDACQ;AAQvB;IADC,YAAY,EAAE;mDACW;AAO1B;IADC,YAAY,CAAC,aAAa,CAAC;+CACS;AAMrC;IADC,YAAY,CAAC,aAAa,CAAC;4CACM;AArCzB,cAAc;IAD1B,YAAY;GACA,cAAc,CAkF1B;SAlFY,cAAc"}
@@ -31,6 +31,10 @@ type ScrollFollowEvent = {
31
31
  * 2. Add a ScrollFollow component to the same GameObject or another GameObject in the scene.
32
32
  * 3. Assign the PlayableDirector component to the ScrollFollow's target property.
33
33
  * 4. The timeline will now scrub based on the scroll position of the page.
34
+ *
35
+ * @category Web
36
+ * @group Components
37
+ * @component
34
38
  */
35
39
  export declare class ScrollFollow extends Behaviour {
36
40
  /**
@@ -36,6 +36,10 @@ import { PlayableDirector } from "../timeline/PlayableDirector.js";
36
36
  * 2. Add a ScrollFollow component to the same GameObject or another GameObject in the scene.
37
37
  * 3. Assign the PlayableDirector component to the ScrollFollow's target property.
38
38
  * 4. The timeline will now scrub based on the scroll position of the page.
39
+ *
40
+ * @category Web
41
+ * @group Components
42
+ * @component
39
43
  */
40
44
  export class ScrollFollow extends Behaviour {
41
45
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ScrollFollow.js","sourceRoot":"","sources":["../../../src/engine-components/web/ScrollFollow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ScrollFollow.js","sourceRoot":"","sources":["../../../src/engine-components/web/ScrollFollow.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAQ,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAcnE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,OAAO,YAAa,SAAQ,SAAS;IAEvC;;;;;;;;;;;;OAYG;IAEH,MAAM,GAA6B,IAAI,CAAC;IAExC;;;OAGG;IAEH,OAAO,GAAW,CAAC,CAAC;IAEpB;;;OAGG;IAEH,MAAM,GAAY,KAAK,CAAC;IAExB;;;;OAIG;IAEH,YAAY,GAAkB,IAAI,CAAC;IAG3B,IAAI,GAAa,QAAQ,CAAC;IAElC;;OAEG;IAEH,OAAO,GAAiC,IAAI,SAAS,EAAqB,CAAC;IAE3E;;OAEG;IACH,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,aAAa,CAAC;IAC9B,CAAC;IAEO,aAAa,GAAW,CAAC,CAAC;IAC1B,YAAY,GAAW,CAAC,CAAC;IACzB,aAAa,GAAW,CAAC,CAAC,CAAC;IAEnC,gBAAgB;IAChB,QAAQ;QACJ,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,wBAAwB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;IAC5B,CAAC;IAED,gBAAgB;IAChB,SAAS;QACL,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACvE,CAAC;IAED,gBAAgB;IAChB,UAAU;QAEN,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAEhC,uBAAuB;QACvB,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,EAAE;YAClB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;SACtH;aACI;YACD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC;SAC1C;QAED,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,CAAC,aAAa,EAAE;YAC3C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;YAExC,IAAI,gBAAgB,GAAG,KAAK,CAAC;YAC7B,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,GAAG,CAAC,EAAE;gBAChC,oBAAoB;gBACpB,MAAM,KAAK,GAAsB;oBAC7B,IAAI,EAAE,QAAQ;oBACd,KAAK,EAAE,IAAI,CAAC,aAAa;oBACzB,SAAS,EAAE,IAAI;oBACf,cAAc,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC,CAAC;oBACxD,gBAAgB,EAAE,KAAK;iBAC1B,CAAC;gBACF,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC3B,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,CAAC;aAC7C;YAED,gCAAgC;YAChC,IAAI,CAAC,gBAAgB,EAAE;gBAEnB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC;gBAExE,4BAA4B;gBAC5B,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;oBAC5B,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,YAAY,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;iBACrE;qBACI,IAAI,IAAI,CAAC,MAAM,EAAE;oBAClB,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;iBAChD;aACJ;SACJ;IACL,CAAC;IAEO,kBAAkB,GAAkB,IAAI,CAAC;IACzC,oBAAoB,GAAmB,IAAI,CAAC;IAE5C,wBAAwB,GAAG,GAAG,EAAE;QAEpC,QAAQ,IAAI,CAAC,IAAI,EAAE;YACf,KAAK,QAAQ;gBACT,IAAI,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE;oBAC3B,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC,kBAAkB,EAAE;wBAC/C,IAAI,CAAC,oBAAoB,GAAG,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;wBACtE,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,YAAY,CAAC;qBAC/C;oBACD,IAAI,IAAI,CAAC,oBAAoB,EAAE;wBAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,oBAAoB,CAAC,qBAAqB,EAAE,CAAC;wBAC/D,IAAI,CAAC,YAAY,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;wBACnE,IAAI,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC;4BAAE,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;wBACpF,MAAM;qBACT;iBACJ;qBACI;oBACD,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;iBAC1F;gBACD,IAAI,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC;oBAAE,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;gBACpF,MAAM;SACb;IAEL,CAAC,CAAA;IAGO,MAAM,CAAC,WAAW,CAAC,MAAc,EAAE,KAAa;QAEpD,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,IAAI,MAAM,YAAY,gBAAgB,EAAE;YACpC,MAAM,CAAC,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC;YACtC,IAAI,CAAC,MAAM,CAAC,SAAS;gBAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;SAC5C;aACI,IAAI,MAAM,YAAY,QAAQ,EAAE;YACjC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;SACpC;aACI,IAAI,MAAM,YAAY,SAAS,EAAE;YAClC,MAAM,CAAC,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC;SACzC;aACI,IAAI,MAAM,YAAY,WAAW,EAAE;YACpC,IAAI,CAAC,MAAM,CAAC,QAAQ;gBAAE,OAAO;YAC7B,MAAM,CAAC,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC;SACzC;aACI,IAAI,MAAM,YAAY,YAAY,EAAE;YACrC,MAAM,CAAC,UAAU,GAAG,KAAK,CAAC;SAC7B;aACI,IAAI,MAAM,YAAY,KAAK,EAAE;YAC9B,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC;SAC5B;aACI,IAAI,MAAM,YAAY,QAAQ,EAAE;YACjC,gFAAgF;YAChF,IAAI,MAAM,CAAC,qBAAqB,CAAC,KAAK,SAAS,EAAE;gBAC7C,MAAM,CAAC,qBAAqB,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;aAClE;YACD,MAAM,MAAM,GAAG,MAAM,CAAC,qBAAqB,CAAS,CAAC;YACrD,IAAI,MAAM,EAAE;gBACR,iFAAiF;gBACjF,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;aAC7E;SACJ;aACI,IAAI,QAAQ,IAAI,MAAM,EAAE;YACzB,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE;gBACnC,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC;aACzB;iBACI,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE;gBAC1C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;aACxB;SACJ;IACL,CAAC;CAEJ;AA/KG;IADC,YAAY,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;4CACI;AAOxC;IADC,YAAY,EAAE;6CACK;AAOpB;IADC,YAAY,EAAE;4CACS;AAQxB;IADC,YAAY,EAAE;kDACoB;AAGnC;IADC,YAAY,EAAE;0CACmB;AAMlC;IADC,YAAY,CAAC,SAAS,CAAC;6CACmD"}
@@ -1,3 +1,4 @@
1
1
  export * from "./Clickthrough.js";
2
2
  export * from "./CursorFollow.js";
3
+ export * from "./HoverAnimation.js";
3
4
  export * from "./ScrollFollow.js";
@@ -1,4 +1,5 @@
1
1
  export * from "./Clickthrough.js";
2
2
  export * from "./CursorFollow.js";
3
+ export * from "./HoverAnimation.js";
3
4
  export * from "./ScrollFollow.js";
4
5
  //# 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,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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/engine",
3
- "version": "4.9.2",
3
+ "version": "4.9.3-next.0facab6",
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": {
@@ -168,4 +168,4 @@
168
168
  "module": "lib/needle-engine.js",
169
169
  "typings": "lib/needle-engine.d.ts",
170
170
  "types": "lib/needle-engine.d.ts"
171
- }
171
+ }
@@ -113,12 +113,14 @@ export const needleViteAlias = (command, config, userSettings) => {
113
113
 
114
114
  // is needle engine a local package?
115
115
  // This will cause local changes to not be reflected anymore...
116
- const localEnginePath = path.resolve(projectDir, 'node_modules/', '@needle-tools/engine', 'node_modules');
116
+ const localEnginePath = path.resolve(projectDir, 'node_modules/', '@needle-tools/engine', 'node_modules', '.package-lock.json');
117
117
  if (existsSync(localEnginePath)) {
118
118
  config.optimizeDeps ??= {};
119
119
  config.optimizeDeps.exclude ??= [];
120
- config.optimizeDeps.exclude.push('@needle-tools/engine');
121
- log("[needle-alias] Detected local @needle-tools/engine package: will exclude it from optimization");
120
+ if (!config.optimizeDeps.include?.includes('@needle-tools/engine')) {
121
+ config.optimizeDeps.exclude.push('@needle-tools/engine');
122
+ log("[needle-alias] Detected local @needle-tools/engine package → will exclude it from optimization");
123
+ }
122
124
  }
123
125
 
124
126
 
@@ -10,32 +10,33 @@ async function generatePoster() {
10
10
  const height = 1080;
11
11
 
12
12
  return new Promise(res => {
13
- onStart(async context => {
13
+ /** @ts-ignore */
14
+ onStart(async (context) => {
14
15
 
15
16
  if (context.lodsManager.manager) {
16
17
  await context.lodsManager.manager.awaitLoading({ frames: 5, maxPromisesPerObject: 2, waitForFirstCapture: true });
17
18
  }
18
19
 
19
- const mimeType = "image/webp";
20
-
21
- // We're reading back as a blob here because that's async, and doesn't seem
22
- // to stress the GPU so much on memory-constrained devices.
23
- const blob = await screenshot2({ context, width, height, mimeType, type: "blob" });
24
-
25
- // We can only send a DataURL, so we need to convert it back here.
26
- const dataUrl = await new Promise((resolve, reject) => {
27
- const reader = new FileReader();
28
- reader.onload = function () {
29
- resolve(reader.result);
30
- };
31
- reader.onloadend = function () {
32
- resolve(null);
33
- };
34
- reader.readAsDataURL(blob);
35
- });
36
-
37
-
38
- res(dataUrl);
20
+ onStart(() => {
21
+ const mimeType = "image/webp";
22
+ // We're reading back as a blob here because that's async, and doesn't seem
23
+ // to stress the GPU so much on memory-constrained devices.
24
+ screenshot2({ context, width, height, mimeType, type: "blob" })
25
+ // @ts-ignore
26
+ .then(blob => {
27
+ const reader = new FileReader();
28
+ reader.onload = function () {
29
+ res(reader.result);
30
+ };
31
+ reader.onloadend = function () {
32
+ res(null);
33
+ };
34
+ reader.readAsDataURL(blob);
35
+
36
+ })
37
+
38
+
39
+ }, { once: true });
39
40
 
40
41
 
41
42
  }, { once: true });
package/src/engine/api.ts CHANGED
@@ -24,7 +24,8 @@ export * from "./engine_addressables.js";
24
24
  export { AnimationUtils } from "./engine_animation.js";
25
25
  export { Application } from "./engine_application.js";
26
26
  export * from "./engine_assetdatabase.js";
27
- export { getCameraController, setAutoFitEnabled, setCameraController, useForAutoFit } from "./engine_camera.js"
27
+ export * from "./engine_camera.fit.js";
28
+ export { getCameraController, setAutoFitEnabled, setCameraController, useForAutoFit } from "./engine_camera.js";
28
29
  export * from "./engine_components.js";
29
30
  export * from "./engine_components_internal.js";
30
31
  export * from "./engine_components_internal.js";
@@ -139,6 +139,7 @@ import { VideoPlayer } from "../../engine-components/VideoPlayer.js";
139
139
  import { Voip } from "../../engine-components/Voip.js";
140
140
  import { ClickThrough } from "../../engine-components/web/Clickthrough.js";
141
141
  import { CursorFollow } from "../../engine-components/web/CursorFollow.js";
142
+ import { HoverAnimation } from "../../engine-components/web/HoverAnimation.js";
142
143
  import { ScrollFollow } from "../../engine-components/web/ScrollFollow.js";
143
144
  import { Avatar } from "../../engine-components/webxr/Avatar.js";
144
145
  import { XRControllerFollow } from "../../engine-components/webxr/controllers/XRControllerFollow.js";
@@ -295,6 +296,7 @@ TypeStore.add("VideoPlayer", VideoPlayer);
295
296
  TypeStore.add("Voip", Voip);
296
297
  TypeStore.add("ClickThrough", ClickThrough);
297
298
  TypeStore.add("CursorFollow", CursorFollow);
299
+ TypeStore.add("HoverAnimation", HoverAnimation);
298
300
  TypeStore.add("ScrollFollow", ScrollFollow);
299
301
  TypeStore.add("Avatar", Avatar);
300
302
  TypeStore.add("XRControllerFollow", XRControllerFollow);
@@ -1,4 +1,4 @@
1
- import { AnimationAction, AnimationClip, AnimationMixer, Object3D, PropertyBinding } from "three";
1
+ import { AnimationAction, AnimationClip, AnimationMixer, KeyframeTrack, Object3D, PropertyBinding, Vector3Like } from "three";
2
2
 
3
3
  import type { Context } from "./engine_context.js";
4
4
  import { GLTF, IAnimationComponent, Model } from "./engine_types.js";
@@ -151,4 +151,72 @@ export class AnimationUtils {
151
151
  return findAnimationComponentInParent(obj.parent);
152
152
  }
153
153
  }
154
+
155
+
156
+ static emptyClip(): AnimationClip {
157
+ return new AnimationClip("empty", 0, []);
158
+ }
159
+
160
+ static createScaleClip(options?: ScaleClipOptions): AnimationClip {
161
+ const duration = options?.duration ?? 0.3;
162
+
163
+ let baseScale: Vector3Like = { x: 1, y: 1, z: 1 };
164
+ if (options?.scale !== undefined) {
165
+ if (typeof options.scale === "number") {
166
+ baseScale = { x: options.scale, y: options.scale, z: options.scale };
167
+ }
168
+ else {
169
+ baseScale = options.scale;
170
+ }
171
+ }
172
+ const type = options?.type ?? "linear";
173
+ const scale = options?.scaleFactor ?? 1.2;
174
+
175
+ const times = new Array<number>();
176
+ const values = new Array<number>();
177
+ switch (type) {
178
+ case "linear":
179
+ times.push(0, duration);
180
+ values.push(
181
+ baseScale.x, baseScale.y, baseScale.z,
182
+ baseScale.x * scale, baseScale.y * scale, baseScale.z * scale
183
+ );
184
+ break;
185
+
186
+ case "spring":
187
+ times.push(0, duration * 0.3, duration * 0.5, duration * 0.7, duration * 0.9, duration);
188
+ values.push(
189
+ baseScale.x, baseScale.y, baseScale.z,
190
+ baseScale.x * scale, baseScale.y * scale, baseScale.z * scale,
191
+ baseScale.x * 0.9, baseScale.y * 0.9, baseScale.z * 0.9,
192
+ baseScale.x * 1.05, baseScale.y * 1.05, baseScale.z * 1.05,
193
+ baseScale.x * 0.98, baseScale.y * 0.98, baseScale.z * 0.98,
194
+ baseScale.x, baseScale.y, baseScale.z
195
+ );
196
+ break;
197
+
198
+ }
199
+
200
+ const track = new KeyframeTrack(".scale", times, values);
201
+ return new AnimationClip("scale", times[times.length - 1], [track]);
202
+ }
203
+ }
204
+
205
+ /**
206
+ * Type of scale animation to create.
207
+ * - "linear": Simple linear scale up animation.
208
+ * - "spring": Spring-like scale animation with overshoot and settling.
209
+ */
210
+ export type ScaleClipType = "linear" | "spring";
211
+
212
+ type ScaleClipOptions = {
213
+ /**
214
+ * Type of scale animation to create.
215
+ * - "linear": Simple linear scale up animation.
216
+ * - "spring": Spring-like scale animation with overshoot and settling.
217
+ */
218
+ type?: ScaleClipType,
219
+ duration?: number,
220
+ scale?: number | Vector3Like,
221
+ scaleFactor?: number
154
222
  }
@@ -0,0 +1,288 @@
1
+ import { Camera, Object3D, PerspectiveCamera, Vector3, Vector3Like } from "three";
2
+
3
+ import { GroundProjectedEnv } from "../engine-components/GroundProjection.js";
4
+ import { findObjectOfType } from "./engine_components.js";
5
+ import { Context } from "./engine_context.js";
6
+ import { Gizmos } from "./engine_gizmos.js";
7
+ import { getBoundingBox } from "./engine_three_utils.js";
8
+ import { NeedleXRSession } from "./xr/NeedleXRSession.js";
9
+
10
+
11
+ /**
12
+ * Options for fitting the camera to the scene. Used in {@link OrbitControls.fitCamera}
13
+ */
14
+ export type FitCameraOptions = {
15
+ /** When enabled debug rendering will be shown */
16
+ debug?: boolean,
17
+
18
+ /**
19
+ * If true the camera position and target will be applied immediately
20
+ * @default true
21
+ */
22
+ autoApply?: boolean,
23
+
24
+ /**
25
+ * The context to use. If not provided the current context will be used
26
+ */
27
+ context?: Context,
28
+
29
+ /**
30
+ * The camera to fit. If not provided the current camera will be used
31
+ */
32
+ camera?: Camera,
33
+
34
+ currentZoom?: number,
35
+ minZoom?: number,
36
+ maxZoom?: number,
37
+
38
+ /**
39
+ * The objects to fit the camera to. If not provided the scene children will be used
40
+ */
41
+ objects?: Object3D[] | Object3D;
42
+
43
+ /** Fit offset: A factor to multiply the distance to the objects by
44
+ * @default 1.1
45
+ */
46
+ fitOffset?: number,
47
+
48
+ /** The direction from which the camera should be fitted in worldspace. If not defined the current camera's position will be used */
49
+ fitDirection?: Vector3Like,
50
+
51
+ /** If set to "y" the camera will be centered in the y axis */
52
+ centerCamera?: "none" | "y",
53
+ /** Set to 'auto' to update the camera near or far plane based on the fitted-objects bounds */
54
+ cameraNearFar?: "keep" | "auto",
55
+
56
+ /**
57
+ * Offset the camera position in world space
58
+ */
59
+ cameraOffset?: Partial<Vector3Like>,
60
+ /**
61
+ * Offset the camera position relative to the size of the objects being focused on (e.g. x: 0.5).
62
+ * Value range: -1 to 1
63
+ */
64
+ relativeCameraOffset?: Partial<Vector3Like>,
65
+
66
+ /**
67
+ * Offset the camera target position in world space
68
+ */
69
+ targetOffset?: Partial<Vector3Like>,
70
+ /**
71
+ * Offset the camera target position relative to the size of the objects being focused on.
72
+ * Value range: -1 to 1
73
+ */
74
+ relativeTargetOffset?: Partial<Vector3Like>,
75
+
76
+ /**
77
+ * Field of view (FOV) for the camera
78
+ */
79
+ fov?: number,
80
+ }
81
+
82
+ export type FitCameraReturnType = {
83
+ camera: Camera,
84
+ position: Vector3,
85
+ lookAt: Vector3,
86
+ fov: number | undefined
87
+ }
88
+
89
+
90
+ export function fitCamera(objectsOrOptions?: Object3D | Array<Object3D> | FitCameraOptions, options?: FitCameraOptions): null | FitCameraReturnType {
91
+
92
+ if (NeedleXRSession.active) {
93
+ // camera fitting in XR is not supported
94
+ console.warn('[OrbitControls] Can not fit camera while XR session is active');
95
+ return null;
96
+ }
97
+
98
+ const context = Context.Current;
99
+ if (!context) {
100
+ console.warn('[OrbitControls] No context found');
101
+ return null;
102
+ }
103
+ const camera = options?.camera || context.mainCamera;
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
+ // const controls = this._controls as ThreeOrbitControls | null;
137
+
138
+ if (!camera) {
139
+ console.warn("No camera or controls found to fit camera to objects...");
140
+ return null;
141
+ }
142
+
143
+ if (!options) options = {}
144
+ options.autoApply = options.autoApply !== false; // default to true
145
+ options.minZoom ||= 0;
146
+ options.maxZoom ||= Infinity;
147
+
148
+ const {
149
+ centerCamera,
150
+ cameraNearFar = "auto",
151
+ fitOffset = 1.1,
152
+ fov = camera instanceof PerspectiveCamera ? camera?.fov : -1
153
+ } = options;
154
+
155
+ const size = new Vector3();
156
+ const center = new Vector3();
157
+ const aspect = camera instanceof PerspectiveCamera ? camera.aspect : 1;
158
+ // TODO would be much better to calculate the bounds in camera space instead of world space -
159
+ // we would get proper view-dependant fit.
160
+ // Right now it's independent from where the camera is actually looking from,
161
+ // and thus we're just getting some maximum that will work for sure.
162
+ const box = getBoundingBox(objects, undefined, camera?.layers);
163
+ const boxCopy = box.clone();
164
+ box.getCenter(center);
165
+
166
+ const box_size = new Vector3();
167
+ box.getSize(box_size);
168
+
169
+ // project this box into camera space
170
+ if (camera instanceof PerspectiveCamera) camera.updateProjectionMatrix();
171
+ camera.updateMatrixWorld();
172
+ box.applyMatrix4(camera.matrixWorldInverse);
173
+
174
+ box.getSize(size);
175
+ box.setFromCenterAndSize(center, size);
176
+ if (Number.isNaN(size.x) || Number.isNaN(size.y) || Number.isNaN(size.z)) {
177
+ console.warn("Camera fit size resultet in NaN", camera, box);
178
+ return null;
179
+ }
180
+ if (size.length() <= 0.0000000001) {
181
+ console.warn("Camera fit size is zero", box);
182
+ return null;
183
+ }
184
+
185
+ const verticalFov = fov;
186
+ const horizontalFov = 2 * Math.atan(Math.tan(verticalFov * Math.PI / 360 / 2) * aspect) / Math.PI * 360;
187
+ const fitHeightDistance = size.y / (2 * Math.atan(Math.PI * verticalFov / 360));
188
+ const fitWidthDistance = size.x / (2 * Math.atan(Math.PI * horizontalFov / 360));
189
+
190
+ const distance = fitOffset * Math.max(fitHeightDistance, fitWidthDistance) + size.z / 2;
191
+ options.maxZoom = distance * 10;
192
+ options.minZoom = distance * 0.01;
193
+
194
+ if (options.debug === true) {
195
+ console.log("Fit camera to objects", { fitHeightDistance, fitWidthDistance, distance, verticalFov, horizontalFov });
196
+ }
197
+
198
+ const verticalOffset = 0.05;
199
+ const lookAt = center.clone();
200
+ lookAt.y -= size.y * verticalOffset;
201
+ if (options.targetOffset) {
202
+ if (options.targetOffset.x !== undefined) lookAt.x += options.targetOffset.x;
203
+ if (options.targetOffset.y !== undefined) lookAt.y += options.targetOffset.y;
204
+ if (options.targetOffset.z !== undefined) lookAt.z += options.targetOffset.z;
205
+ }
206
+ if (options.relativeTargetOffset) {
207
+ if (options.relativeTargetOffset.x !== undefined) lookAt.x += options.relativeTargetOffset.x * size.x;
208
+ if (options.relativeTargetOffset.y !== undefined) lookAt.y += options.relativeTargetOffset.y * size.y;
209
+ if (options.relativeTargetOffset.z !== undefined) lookAt.z += options.relativeTargetOffset.z * size.z;
210
+ }
211
+ // this.setLookTargetPosition(lookAt, immediate);
212
+ // this.setFieldOfView(options.fov, immediate);
213
+
214
+ if (cameraNearFar == undefined || cameraNearFar == "auto") {
215
+ // Check if the scene has a GroundProjectedEnv and include the scale to the far plane so that it doesnt cut off
216
+ const groundprojection = findObjectOfType(GroundProjectedEnv);
217
+ const groundProjectionRadius = groundprojection ? groundprojection.radius : 0;
218
+ const boundsMax = Math.max(box_size.x, box_size.y, box_size.z, groundProjectionRadius);
219
+ // TODO: this doesnt take the Camera component nearClipPlane into account
220
+ if (camera instanceof PerspectiveCamera) {
221
+ camera.near = (distance / 100);
222
+ camera.far = boundsMax + distance * 10;
223
+ camera.updateProjectionMatrix();
224
+ }
225
+
226
+ // adjust maxZoom so that the ground projection radius is always inside
227
+ if (groundprojection) {
228
+ options.maxZoom = Math.max(Math.min(options.maxZoom, groundProjectionRadius * 0.5), distance);
229
+ }
230
+ }
231
+
232
+ // ensure we're not clipping out of the current zoom level just because we're fitting
233
+ if (options.currentZoom !== undefined) {
234
+ if (options.currentZoom < options.minZoom) options.minZoom = options.currentZoom * 0.9;
235
+ if (options.currentZoom > options.maxZoom) options.maxZoom = options.currentZoom * 1.1;
236
+ }
237
+
238
+ const direction = center.clone();
239
+ if (options.fitDirection) {
240
+ direction.sub(new Vector3().copy(options.fitDirection).multiplyScalar(1_000_000));
241
+ }
242
+ else {
243
+ direction.sub(camera.worldPosition);
244
+ }
245
+ if (centerCamera === "y")
246
+ direction.y = 0;
247
+ direction.normalize();
248
+ direction.multiplyScalar(distance);
249
+ if (centerCamera === "y")
250
+ direction.y += -verticalOffset * 4 * distance;
251
+
252
+ let cameraLocalPosition = center.clone().sub(direction);
253
+ if (options.cameraOffset) {
254
+ if (options.cameraOffset.x !== undefined) cameraLocalPosition.x += options.cameraOffset.x;
255
+ if (options.cameraOffset.y !== undefined) cameraLocalPosition.y += options.cameraOffset.y;
256
+ if (options.cameraOffset.z !== undefined) cameraLocalPosition.z += options.cameraOffset.z;
257
+ }
258
+ if (options.relativeCameraOffset) {
259
+ if (options.relativeCameraOffset.x !== undefined) cameraLocalPosition.x += options.relativeCameraOffset.x * size.x;
260
+ if (options.relativeCameraOffset.y !== undefined) cameraLocalPosition.y += options.relativeCameraOffset.y * size.y;
261
+ if (options.relativeCameraOffset.z !== undefined) cameraLocalPosition.z += options.relativeCameraOffset.z * size.z;
262
+ }
263
+ if (camera.parent) {
264
+ cameraLocalPosition = camera.parent.worldToLocal(cameraLocalPosition);
265
+ }
266
+ // this.setCameraTargetPosition(cameraLocalPosition, immediate);
267
+
268
+ if (options.debug) {
269
+ Gizmos.DrawWireBox3(box, 0xffff33, 10);
270
+ Gizmos.DrawWireBox3(boxCopy, 0x00ff00, 10);
271
+ }
272
+
273
+ if (options.autoApply) {
274
+ camera.position.copy(cameraLocalPosition);
275
+ camera.lookAt(lookAt);
276
+ if (fov > 0 && camera instanceof PerspectiveCamera) {
277
+ camera.fov = fov;
278
+ camera.updateProjectionMatrix();
279
+ }
280
+ }
281
+
282
+ return {
283
+ camera: camera,
284
+ position: cameraLocalPosition,
285
+ lookAt: lookAt,
286
+ fov: options.fov,
287
+ }
288
+ }