@needle-tools/engine 5.0.0 → 5.1.0-experimental.0

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 (183) hide show
  1. package/components.needle.json +1 -1
  2. package/dist/generateMeshBVH.worker-DT9A2Hrc.js +1 -0
  3. package/dist/gltf-progressive-3BwW4ETO.min.js +10 -0
  4. package/dist/gltf-progressive-ByD1UX0A.umd.cjs +10 -0
  5. package/dist/{gltf-progressive-Cl167Vjx.js → gltf-progressive-DwWaVr0o.js} +412 -394
  6. package/dist/gltf-progressive.worker-DpfUjn1n.js +3 -0
  7. package/dist/{materialx-qPScBWhj.min.js → materialx-9KHBidZa.min.js} +1 -1
  8. package/dist/{materialx-4ApD6Vz5.js → materialx-BBDu8W5P.js} +1 -1
  9. package/dist/{materialx-D0XUnhBY.umd.cjs → materialx-hLP3E8AA.umd.cjs} +2 -2
  10. package/dist/{needle-engine.bundle-BAYLGumK.umd.cjs → needle-engine.bundle-BOAJ6UPK.umd.cjs} +123 -123
  11. package/dist/{needle-engine.bundle-CoEvMwYM.min.js → needle-engine.bundle-CVsBkUR2.min.js} +110 -110
  12. package/dist/{needle-engine.bundle-BDIyvCV6.js → needle-engine.bundle-TgPY0fGG.js} +2143 -2088
  13. package/dist/needle-engine.d.ts +80 -22
  14. package/dist/needle-engine.js +480 -476
  15. package/dist/needle-engine.min.js +1 -1
  16. package/dist/needle-engine.umd.cjs +1 -1
  17. package/dist/{postprocessing-B_9sKVU7.min.js → postprocessing-BZfyAdCY.min.js} +1 -1
  18. package/dist/{postprocessing-WDc9WwI3.js → postprocessing-CXlA3QA6.js} +1 -1
  19. package/dist/{postprocessing-B2wb6pzI.umd.cjs → postprocessing-Dwy7Hz_T.umd.cjs} +38 -38
  20. package/dist/three-examples.js +4760 -3641
  21. package/dist/three-examples.min.js +17 -35
  22. package/dist/three-examples.umd.cjs +16 -34
  23. package/dist/three.js +48533 -28562
  24. package/dist/three.min.js +716 -502
  25. package/dist/three.umd.cjs +720 -506
  26. package/dist/{vendor-CntUvmJu.umd.cjs → vendor-BI4TX0aC.umd.cjs} +9 -9
  27. package/dist/{vendor-DPbfJJ4d.min.js → vendor-BgzAK9of.min.js} +1 -1
  28. package/dist/{vendor-vHLk8sXu.js → vendor-CwL-uvVy.js} +1 -1
  29. package/lib/engine/engine_animation.js +1 -1
  30. package/lib/engine/engine_animation.js.map +1 -1
  31. package/lib/engine/engine_audio.js.map +1 -1
  32. package/lib/engine/engine_context.js +3 -6
  33. package/lib/engine/engine_context.js.map +1 -1
  34. package/lib/engine/engine_create_objects.js +0 -1
  35. package/lib/engine/engine_create_objects.js.map +1 -1
  36. package/lib/engine/engine_element.d.ts +113 -0
  37. package/lib/engine/engine_element.js +833 -0
  38. package/lib/engine/engine_element.js.map +1 -0
  39. package/lib/engine/engine_element_attributes.d.ts +72 -0
  40. package/lib/engine/engine_element_attributes.js +2 -0
  41. package/lib/engine/engine_element_attributes.js.map +1 -0
  42. package/lib/engine/engine_element_extras.d.ts +6 -0
  43. package/lib/engine/engine_element_extras.js +14 -0
  44. package/lib/engine/engine_element_extras.js.map +1 -0
  45. package/lib/engine/engine_element_loading.d.ts +44 -0
  46. package/lib/engine/engine_element_loading.js +350 -0
  47. package/lib/engine/engine_element_loading.js.map +1 -0
  48. package/lib/engine/engine_element_overlay.d.ts +21 -0
  49. package/lib/engine/engine_element_overlay.js +167 -0
  50. package/lib/engine/engine_element_overlay.js.map +1 -0
  51. package/lib/engine/engine_license.js.map +1 -1
  52. package/lib/engine/engine_pmrem.js +2 -2
  53. package/lib/engine/engine_pmrem.js.map +1 -1
  54. package/lib/engine/engine_scenetools.d.ts +62 -0
  55. package/lib/engine/engine_scenetools.js +337 -0
  56. package/lib/engine/engine_scenetools.js.map +1 -0
  57. package/lib/engine/engine_serialization_builtin_serializer.d.ts +1 -1
  58. package/lib/engine/engine_test_utils.d.ts +39 -0
  59. package/lib/engine/engine_test_utils.js +84 -0
  60. package/lib/engine/engine_test_utils.js.map +1 -0
  61. package/lib/engine/engine_three_utils.js.map +1 -1
  62. package/lib/engine/engine_time.js +4 -3
  63. package/lib/engine/engine_time.js.map +1 -1
  64. package/lib/engine/engine_ui.d.ts +25 -0
  65. package/lib/engine/engine_ui.dummy_canvas.d.ts +2 -0
  66. package/lib/engine/engine_ui.dummy_canvas.js +55 -0
  67. package/lib/engine/engine_ui.dummy_canvas.js.map +1 -0
  68. package/lib/engine/engine_ui.js +168 -0
  69. package/lib/engine/engine_ui.js.map +1 -0
  70. package/lib/engine/extensions/NEEDLE_lightmaps.js +2 -2
  71. package/lib/engine/extensions/NEEDLE_lightmaps.js.map +1 -1
  72. package/lib/engine/extensions/NEEDLE_pmrem.d.ts +1 -1
  73. package/lib/engine/webcomponents/icons.js +3 -2
  74. package/lib/engine/webcomponents/icons.js.map +1 -1
  75. package/lib/engine/webcomponents/needle-engine.attributes.d.ts +69 -0
  76. package/lib/engine/webcomponents/needle-engine.attributes.js +2 -0
  77. package/lib/engine/webcomponents/needle-engine.attributes.js.map +1 -0
  78. package/lib/engine-components/AudioSource.js +1 -1
  79. package/lib/engine-components/AudioSource.js.map +1 -1
  80. package/lib/engine-components/Light.d.ts +3 -0
  81. package/lib/engine-components/Light.js +39 -31
  82. package/lib/engine-components/Light.js.map +1 -1
  83. package/lib/engine-components/OrbitControls.js +2 -1
  84. package/lib/engine-components/OrbitControls.js.map +1 -1
  85. package/lib/engine-components/SpriteRenderer.d.ts +1 -1
  86. package/lib/engine-components/VideoPlayer.d.ts +1 -1
  87. package/lib/engine-components/export/usdz/ThreeUSDZExporter.js.map +1 -1
  88. package/lib/engine-components/export/usdz/extensions/Animation.js +1 -0
  89. package/lib/engine-components/export/usdz/extensions/Animation.js.map +1 -1
  90. package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.d.ts +1 -1
  91. package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js.map +1 -1
  92. package/lib/engine-components/particlesystem/ParticleSystem.d.ts +1 -1
  93. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
  94. package/lib/engine-components/postprocessing/PostProcessingHandler.js.map +1 -1
  95. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  96. package/lib/engine-components/ui/BaseUIComponent_Uikit.d.ts +54 -0
  97. package/lib/engine-components/ui/BaseUIComponent_Uikit.js +114 -0
  98. package/lib/engine-components/ui/BaseUIComponent_Uikit.js.map +1 -0
  99. package/lib/engine-components/ui/BaseUikitComponent.d.ts +54 -0
  100. package/lib/engine-components/ui/BaseUikitComponent.js +114 -0
  101. package/lib/engine-components/ui/BaseUikitComponent.js.map +1 -0
  102. package/lib/engine-components/ui/Button.legacy.d.ts +68 -0
  103. package/lib/engine-components/ui/Button.legacy.js +320 -0
  104. package/lib/engine-components/ui/Button.legacy.js.map +1 -0
  105. package/lib/engine-components/ui/ButtonUikit.d.ts +51 -0
  106. package/lib/engine-components/ui/ButtonUikit.js +187 -0
  107. package/lib/engine-components/ui/ButtonUikit.js.map +1 -0
  108. package/lib/engine-components/ui/Canvas.js +2 -2
  109. package/lib/engine-components/ui/Canvas.js.map +1 -1
  110. package/lib/engine-components/ui/Canvas.legacy.d.ts +76 -0
  111. package/lib/engine-components/ui/Canvas.legacy.js +409 -0
  112. package/lib/engine-components/ui/Canvas.legacy.js.map +1 -0
  113. package/lib/engine-components/ui/CanvasUikit.d.ts +68 -0
  114. package/lib/engine-components/ui/CanvasUikit.js +289 -0
  115. package/lib/engine-components/ui/CanvasUikit.js.map +1 -0
  116. package/lib/engine-components/ui/Graphic.d.ts +3 -3
  117. package/lib/engine-components/ui/Graphic.js +6 -2
  118. package/lib/engine-components/ui/Graphic.js.map +1 -1
  119. package/lib/engine-components/ui/Graphic.legacy.d.ts +55 -0
  120. package/lib/engine-components/ui/Graphic.legacy.js +268 -0
  121. package/lib/engine-components/ui/Graphic.legacy.js.map +1 -0
  122. package/lib/engine-components/ui/GraphicUikit.d.ts +21 -0
  123. package/lib/engine-components/ui/GraphicUikit.js +65 -0
  124. package/lib/engine-components/ui/GraphicUikit.js.map +1 -0
  125. package/lib/engine-components/ui/Image.js.map +1 -1
  126. package/lib/engine-components/ui/Image.legacy.d.ts +39 -0
  127. package/lib/engine-components/ui/Image.legacy.js +121 -0
  128. package/lib/engine-components/ui/Image.legacy.js.map +1 -0
  129. package/lib/engine-components/ui/ImageUikit.d.ts +22 -0
  130. package/lib/engine-components/ui/ImageUikit.js +97 -0
  131. package/lib/engine-components/ui/ImageUikit.js.map +1 -0
  132. package/lib/engine-components/ui/RenderMode.d.ts +14 -0
  133. package/lib/engine-components/ui/RenderMode.js +16 -0
  134. package/lib/engine-components/ui/RenderMode.js.map +1 -0
  135. package/lib/engine-components/ui/Text.d.ts +64 -11
  136. package/lib/engine-components/ui/Text.js +154 -45
  137. package/lib/engine-components/ui/Text.js.map +1 -1
  138. package/lib/engine-components/ui/Text.legacy.d.ts +81 -0
  139. package/lib/engine-components/ui/Text.legacy.js +548 -0
  140. package/lib/engine-components/ui/Text.legacy.js.map +1 -0
  141. package/lib/engine-components/ui/TextUikit.d.ts +42 -0
  142. package/lib/engine-components/ui/TextUikit.js +164 -0
  143. package/lib/engine-components/ui/TextUikit.js.map +1 -0
  144. package/lib/engine-components/ui/index.d.ts +1 -0
  145. package/lib/engine-components/ui/index.js +1 -0
  146. package/lib/engine-components/ui/index.js.map +1 -1
  147. package/lib/engine-components/webxr/WebARCameraBackground.d.ts +1 -1
  148. package/lib/include/three/EXT_mesh_gpu_instancing_exporter.d.ts +6 -0
  149. package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js +46 -0
  150. package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js.map +1 -0
  151. package/package.json +4 -4
  152. package/plugins/common/buildinfo.d.ts +6 -0
  153. package/plugins/vite/ai.d.ts +7 -8
  154. package/plugins/vite/ai.js +95 -20
  155. package/plugins/vite/alias.js +6 -0
  156. package/plugins/vite/dependencies.js +7 -0
  157. package/src/engine/engine_animation.ts +1 -1
  158. package/src/engine/engine_audio.ts +1 -1
  159. package/src/engine/engine_context.ts +3 -6
  160. package/src/engine/engine_create_objects.ts +0 -1
  161. package/src/engine/engine_license.ts +0 -2
  162. package/src/engine/engine_pmrem.ts +3 -3
  163. package/src/engine/engine_three_utils.ts +2 -2
  164. package/src/engine/engine_time.ts +4 -3
  165. package/src/engine/extensions/NEEDLE_lightmaps.ts +3 -3
  166. package/src/engine/webcomponents/icons.ts +3 -2
  167. package/src/engine-components/AudioSource.ts +1 -1
  168. package/src/engine-components/Light.ts +39 -31
  169. package/src/engine-components/OrbitControls.ts +2 -2
  170. package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +2 -2
  171. package/src/engine-components/export/usdz/extensions/Animation.ts +6 -5
  172. package/src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +1 -1
  173. package/src/engine-components/postprocessing/PostProcessingHandler.ts +3 -3
  174. package/src/engine-components/timeline/TimelineTracks.ts +2 -2
  175. package/src/engine-components/ui/Canvas.ts +2 -2
  176. package/src/engine-components/ui/Graphic.ts +7 -3
  177. package/src/engine-components/ui/Image.ts +1 -1
  178. package/src/engine-components/ui/Text.ts +170 -52
  179. package/src/engine-components/ui/index.ts +2 -1
  180. package/dist/generateMeshBVH.worker-DiCnZlf3.js +0 -21
  181. package/dist/gltf-progressive-BryRjllq.min.js +0 -10
  182. package/dist/gltf-progressive-DJBMx-zB.umd.cjs +0 -10
  183. package/dist/gltf-progressive.worker-BqODMeeW.js +0 -23
@@ -0,0 +1,42 @@
1
+ import { type ContainerProperties } from "@pmndrs/uikit";
2
+ import { RGBAColor } from "../../engine/js-extensions/index.js";
3
+ import { BaseUikitComponent } from "./BaseUikitComponent.js";
4
+ export declare enum TextAnchor {
5
+ UpperLeft = 0,
6
+ UpperCenter = 1,
7
+ UpperRight = 2,
8
+ MiddleLeft = 3,
9
+ MiddleCenter = 4,
10
+ MiddleRight = 5,
11
+ LowerLeft = 6,
12
+ LowerCenter = 7,
13
+ LowerRight = 8
14
+ }
15
+ /**
16
+ * TextUikit is a UI component that displays text using pmndrs/uikit.
17
+ * It's the uikit equivalent of the Text component.
18
+ *
19
+ * @summary Display text in the UI using uikit
20
+ * @category User Interface
21
+ * @group Components
22
+ */
23
+ export declare class TextUikit extends BaseUikitComponent {
24
+ alignment: TextAnchor;
25
+ get text(): string;
26
+ set text(val: string);
27
+ get fontSize(): number;
28
+ set fontSize(val: number);
29
+ get color(): RGBAColor;
30
+ set color(col: RGBAColor);
31
+ private _text;
32
+ private _fontSize;
33
+ private _color;
34
+ private _sRGBColor;
35
+ private _uikitTextElement;
36
+ protected createUikitElement(): void;
37
+ protected getUikitProperties(): ContainerProperties;
38
+ private updateTextContent;
39
+ private onColorChanged;
40
+ private updateColorForUikit;
41
+ onDestroy(): void;
42
+ }
@@ -0,0 +1,164 @@
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 { Color } from "three";
8
+ import { Container, Text as UikitText } from "@pmndrs/uikit";
9
+ import { serializable } from "../../engine/engine_serialization_decorator.js";
10
+ import { RGBAColor } from "../../engine/js-extensions/index.js";
11
+ import { BaseUikitComponent } from "./BaseUikitComponent.js";
12
+ export var TextAnchor;
13
+ (function (TextAnchor) {
14
+ TextAnchor[TextAnchor["UpperLeft"] = 0] = "UpperLeft";
15
+ TextAnchor[TextAnchor["UpperCenter"] = 1] = "UpperCenter";
16
+ TextAnchor[TextAnchor["UpperRight"] = 2] = "UpperRight";
17
+ TextAnchor[TextAnchor["MiddleLeft"] = 3] = "MiddleLeft";
18
+ TextAnchor[TextAnchor["MiddleCenter"] = 4] = "MiddleCenter";
19
+ TextAnchor[TextAnchor["MiddleRight"] = 5] = "MiddleRight";
20
+ TextAnchor[TextAnchor["LowerLeft"] = 6] = "LowerLeft";
21
+ TextAnchor[TextAnchor["LowerCenter"] = 7] = "LowerCenter";
22
+ TextAnchor[TextAnchor["LowerRight"] = 8] = "LowerRight";
23
+ })(TextAnchor || (TextAnchor = {}));
24
+ /**
25
+ * TextUikit is a UI component that displays text using pmndrs/uikit.
26
+ * It's the uikit equivalent of the Text component.
27
+ *
28
+ * @summary Display text in the UI using uikit
29
+ * @category User Interface
30
+ * @group Components
31
+ */
32
+ export class TextUikit extends BaseUikitComponent {
33
+ alignment = TextAnchor.UpperLeft;
34
+ get text() {
35
+ return this._text;
36
+ }
37
+ set text(val) {
38
+ if (val !== this._text) {
39
+ this._text = val;
40
+ this.updateTextContent();
41
+ }
42
+ }
43
+ get fontSize() {
44
+ return this._fontSize;
45
+ }
46
+ set fontSize(val) {
47
+ this._fontSize = val;
48
+ this.updateUikitProperties({ fontSize: val });
49
+ }
50
+ get color() {
51
+ if (!this._color)
52
+ this._color = new RGBAColor(1, 1, 1, 1);
53
+ return this._color;
54
+ }
55
+ set color(col) {
56
+ const changed = !this._color || this._color.r !== col.r || this._color.g !== col.g || this._color.b !== col.b || this._color.alpha !== col.alpha;
57
+ if (!changed)
58
+ return;
59
+ if (!this._color) {
60
+ this._color = new RGBAColor(1, 1, 1, 1);
61
+ }
62
+ this._color.copy(col);
63
+ this.onColorChanged();
64
+ }
65
+ _text = "";
66
+ _fontSize = 16;
67
+ _color = null;
68
+ _sRGBColor = new Color();
69
+ _uikitTextElement = null;
70
+ createUikitElement() {
71
+ if (this.uikitElement)
72
+ return;
73
+ // Create container for the text
74
+ const properties = this.getUikitProperties();
75
+ this.uikitElement = new Container(properties);
76
+ this.uikitElement.name = this.name || "TextUikit";
77
+ // Create and add text element
78
+ this.updateColorForUikit();
79
+ this._uikitTextElement = new UikitText({
80
+ text: this._text,
81
+ fontSize: this._fontSize,
82
+ color: `#${this._sRGBColor.getHexString()}`,
83
+ });
84
+ this.uikitElement.add(this._uikitTextElement);
85
+ }
86
+ getUikitProperties() {
87
+ const props = {};
88
+ // Map alignment to flexbox properties
89
+ switch (this.alignment) {
90
+ case TextAnchor.UpperLeft:
91
+ case TextAnchor.MiddleLeft:
92
+ case TextAnchor.LowerLeft:
93
+ props.alignItems = "flex-start";
94
+ break;
95
+ case TextAnchor.UpperCenter:
96
+ case TextAnchor.MiddleCenter:
97
+ case TextAnchor.LowerCenter:
98
+ props.alignItems = "center";
99
+ break;
100
+ case TextAnchor.UpperRight:
101
+ case TextAnchor.MiddleRight:
102
+ case TextAnchor.LowerRight:
103
+ props.alignItems = "flex-end";
104
+ break;
105
+ }
106
+ switch (this.alignment) {
107
+ case TextAnchor.UpperLeft:
108
+ case TextAnchor.UpperCenter:
109
+ case TextAnchor.UpperRight:
110
+ props.justifyContent = "flex-start";
111
+ break;
112
+ case TextAnchor.MiddleLeft:
113
+ case TextAnchor.MiddleCenter:
114
+ case TextAnchor.MiddleRight:
115
+ props.justifyContent = "center";
116
+ break;
117
+ case TextAnchor.LowerLeft:
118
+ case TextAnchor.LowerCenter:
119
+ case TextAnchor.LowerRight:
120
+ props.justifyContent = "flex-end";
121
+ break;
122
+ }
123
+ return props;
124
+ }
125
+ updateTextContent() {
126
+ if (this._uikitTextElement) {
127
+ this._uikitTextElement.setProperties({ text: this._text });
128
+ }
129
+ }
130
+ onColorChanged() {
131
+ this.updateColorForUikit();
132
+ if (this._uikitTextElement) {
133
+ this._uikitTextElement.setProperties({
134
+ color: `#${this._sRGBColor.getHexString()}`,
135
+ });
136
+ }
137
+ }
138
+ updateColorForUikit() {
139
+ if (this._color) {
140
+ this._sRGBColor.copy(this._color);
141
+ this._sRGBColor.convertLinearToSRGB();
142
+ }
143
+ }
144
+ onDestroy() {
145
+ if (this._uikitTextElement) {
146
+ this._uikitTextElement.removeFromParent();
147
+ this._uikitTextElement = null;
148
+ }
149
+ super.onDestroy();
150
+ }
151
+ }
152
+ __decorate([
153
+ serializable()
154
+ ], TextUikit.prototype, "alignment", void 0);
155
+ __decorate([
156
+ serializable()
157
+ ], TextUikit.prototype, "text", null);
158
+ __decorate([
159
+ serializable()
160
+ ], TextUikit.prototype, "fontSize", null);
161
+ __decorate([
162
+ serializable(RGBAColor)
163
+ ], TextUikit.prototype, "color", null);
164
+ //# sourceMappingURL=TextUikit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextUikit.js","sourceRoot":"","sources":["../../../src/engine-components/ui/TextUikit.ts"],"names":[],"mappings":"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"}
@@ -1 +1,2 @@
1
1
  export * from "./PointerEvents.js";
2
+ export * from "./Text.js";
@@ -1,2 +1,3 @@
1
1
  export * from "./PointerEvents.js";
2
+ export * from "./Text.js";
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/engine-components/ui/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/engine-components/ui/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC"}
@@ -31,7 +31,7 @@ export declare class WebARCameraBackground extends Behaviour {
31
31
  * The tint color of the camera feed
32
32
  */
33
33
  backgroundTint: RGBAColor;
34
- get background(): Mesh<import("three").BufferGeometry<import("three").NormalBufferAttributes>, import("three").Material | import("three").Material[], import("three").Object3DEventMap> | undefined;
34
+ get background(): Mesh<import("three").BufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>, import("three").Material | import("three").Material[], import("three").Object3DEventMap> | undefined;
35
35
  private backgroundPlane?;
36
36
  private threeTexture?;
37
37
  private forceTextureInitialization;
@@ -0,0 +1,6 @@
1
+ export default class GLTFMeshGPUInstancingExtension {
2
+ constructor(writer: any);
3
+ writer: any;
4
+ name: string;
5
+ writeNode(node: any, nodeDef: any): void;
6
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Mesh GPU Instancing extension
3
+ *
4
+ * Specification: https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_mesh_gpu_instancing
5
+ */
6
+ import { BufferAttribute, Matrix4, Vector3, Quaternion, } from 'three';
7
+ export default class GLTFMeshGPUInstancingExtension {
8
+ constructor(writer) {
9
+ this.writer = writer;
10
+ this.name = 'EXT_mesh_gpu_instancing';
11
+ }
12
+ writeNode(node, nodeDef) {
13
+ if (node.constructor.name !== "InstancedMesh")
14
+ return;
15
+ const writer = this.writer;
16
+ const extensionsUsed = writer.extensionsUsed;
17
+ const extensionDef = {};
18
+ nodeDef.extensions = nodeDef.extensions || {};
19
+ nodeDef.extensions[this.name] = extensionDef;
20
+ let mat = new Matrix4();
21
+ const pos0 = new Array();
22
+ const rot0 = new Array();
23
+ const scl0 = new Array();
24
+ for (let i = 0; i < node.count; i++) {
25
+ node.getMatrixAt(i, mat);
26
+ let p = new Vector3();
27
+ let r = new Quaternion();
28
+ let s = new Vector3();
29
+ mat.decompose(p, r, s);
30
+ pos0.push(p.x, p.y, p.z);
31
+ rot0.push(r.x, r.y, r.z, r.w);
32
+ scl0.push(s.x, s.y, s.z);
33
+ }
34
+ ;
35
+ const pos = new Float32Array(pos0);
36
+ const rot = new Float32Array(rot0);
37
+ const scl = new Float32Array(scl0);
38
+ extensionDef.attributes = {
39
+ "TRANSLATION": writer.processAccessor(new BufferAttribute(pos, 3)),
40
+ "ROTATION": writer.processAccessor(new BufferAttribute(rot, 4)),
41
+ "SCALE": writer.processAccessor(new BufferAttribute(scl, 3)),
42
+ };
43
+ extensionsUsed[this.name] = true;
44
+ }
45
+ }
46
+ //# sourceMappingURL=EXT_mesh_gpu_instancing_exporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EXT_mesh_gpu_instancing_exporter.js","sourceRoot":"","sources":["../../../src/include/three/EXT_mesh_gpu_instancing_exporter.js"],"names":[],"mappings":"AAAA;;;;GAIG;AAEF,OAAO,EACP,eAAe,EACf,OAAO,EACP,OAAO,EACP,UAAU,GACV,MAAM,OAAO,CAAC;AAEf,MAAM,CAAC,OAAO,OAAO,8BAA8B;IAElD,YAAa,MAAM;QAElB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IAEvC,CAAC;IAED,SAAS,CAAE,IAAI,EAAE,OAAO;QAEvB,IAAG,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,eAAe;YAAE,OAAO;QAErD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QAC7C,MAAM,YAAY,GAAG,EAAE,CAAC;QAExB,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;QAC9C,OAAO,CAAC,UAAU,CAAE,IAAI,CAAC,IAAI,CAAE,GAAG,YAAY,CAAC;QAE/C,IAAI,GAAG,GAAG,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QAEzB,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAClC;YACC,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YAEzB,IAAI,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;YACtB,IAAI,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC;YACzB,IAAI,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;YAEtB,GAAG,CAAC,SAAS,CAAC,CAAC,EAAC,CAAC,EAAC,CAAC,CAAC,CAAC;YAErB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACvB;QAAA,CAAC;QAEF,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QAEnC,YAAY,CAAC,UAAU,GAAG;YACzB,aAAa,EAAG,MAAM,CAAC,eAAe,CAAE,IAAI,eAAe,CAAE,GAAG,EAAE,CAAC,CAAE,CAAE;YACvE,UAAU,EAAG,MAAM,CAAC,eAAe,CAAE,IAAI,eAAe,CAAE,GAAG,EAAE,CAAC,CAAE,CAAE;YACpE,OAAO,EAAG,MAAM,CAAC,eAAe,CAAE,IAAI,eAAe,CAAE,GAAG,EAAE,CAAC,CAAE,CAAE;SACjE,CAAC;QAEF,cAAc,CAAE,IAAI,CAAC,IAAI,CAAE,GAAG,IAAI,CAAC;IAEpC,CAAC;CACD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/engine",
3
- "version": "5.0.0",
3
+ "version": "5.1.0-experimental.0",
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": {
@@ -121,7 +121,7 @@
121
121
  ],
122
122
  "dependencies": {
123
123
  "@dimforge/rapier3d-compat": "0.19.3",
124
- "@needle-tools/gltf-progressive": "3.4.0-beta.3",
124
+ "@needle-tools/gltf-progressive": "4.0.0-alpha",
125
125
  "@needle-tools/materialx": "1.5.1",
126
126
  "@needle-tools/three-animation-pointer": "1.0.7",
127
127
  "@webxr-input-profiles/motion-controllers": "1.0.0",
@@ -133,7 +133,7 @@
133
133
  "scroll-timeline-polyfill": "1.1.0",
134
134
  "simplex-noise": "4.0.3",
135
135
  "stats.js": "0.17.0",
136
- "three": "npm:@needle-tools/three@0.169.19",
136
+ "three": "npm:@needle-tools/three@0.183.2-canary.0",
137
137
  "three-mesh-bvh": "0.9.7",
138
138
  "three-mesh-ui": "npm:@needle-tools/three-mesh-ui@7.1.5-alpha.5",
139
139
  "three.quarks": "0.15.6",
@@ -147,7 +147,7 @@
147
147
  "@needle-tools/helper": "2.0.0-next.faf57e6",
148
148
  "@needle-tools/needle-component-compiler": "3.0.0-alpha.1.999f08a",
149
149
  "@types/node": "^20.14.8",
150
- "@types/three": "0.169.0",
150
+ "@types/three": "0.183.1",
151
151
  "@typescript-eslint/eslint-plugin": "^8.0.0",
152
152
  "@typescript-eslint/parser": "^8.0.0",
153
153
  "esbuild": "^0.15.10",
@@ -0,0 +1,6 @@
1
+
2
+ export type BuildInfo = {
3
+ fileCount: number;
4
+ totalSizeBytes: number;
5
+ totalSizeInMB: number;
6
+ }
@@ -1,15 +1,14 @@
1
1
  /**
2
2
  * Needle Engine AI skill installer.
3
3
  *
4
- * Writes a Needle Engine skill to `<dir>/skills/needle-engine/SKILL.md`
5
- * for each supported AI agent directory (`.claude/`, `.github/`, `.agents/`).
6
- * Both Claude Code and GitHub Copilot auto-load skills based on their
7
- * description frontmatter, so the AI agent will automatically have Needle
8
- * Engine context when working in the project.
4
+ * Auto-detects AI coding agents by checking for their config directories
5
+ * in the project root, then writes the Needle Engine skill in each agent's
6
+ * native format.
9
7
  *
10
- * The skill is only written if at least one of the supported directories
11
- * already exists in the project root (i.e. the developer is already using
12
- * an AI coding agent).
8
+ * Supported agents: Claude Code, GitHub Copilot, Cursor, Codex / universal.
9
+ *
10
+ * The skill is only written if at least one agent directory already exists
11
+ * (i.e. the developer is already using an AI coding agent).
13
12
  * Old skill files are always overwritten so the skill stays up to date with
14
13
  * the engine version.
15
14
  *
@@ -8,18 +8,47 @@ const __dirname = dirname(__filename);
8
8
 
9
9
  const pluginName = "needle-ai";
10
10
 
11
+ /**
12
+ * Supported AI coding agents.
13
+ * Each entry defines how to detect the agent and how to write its skill file.
14
+ * `detect` is the directory that must exist in the project root.
15
+ * `write(cwd, content)` writes the skill in the agent's native format and returns the written path.
16
+ */
17
+ const agents = [
18
+ {
19
+ name: "Claude Code",
20
+ detect: ".claude",
21
+ write: (cwd, content) => writeSkillMd(join(cwd, ".claude"), content),
22
+ },
23
+ {
24
+ name: "GitHub Copilot",
25
+ detect: ".github",
26
+ write: (cwd, content) => writeSkillMd(join(cwd, ".github"), content),
27
+ },
28
+ {
29
+ name: "Cursor",
30
+ detect: ".cursor",
31
+ write: (cwd, content) => writeCursorRule(cwd, content),
32
+ },
33
+ {
34
+ // Universal .agents/ dir (Codex, Gemini CLI, OpenCode, and others)
35
+ name: "Codex / Universal",
36
+ detect: ".agents",
37
+ write: (cwd, content) => writeSkillMd(join(cwd, ".agents"), content),
38
+ },
39
+ ];
40
+
11
41
  /**
12
42
  * Needle Engine AI skill installer.
13
43
  *
14
- * Writes a Needle Engine skill to `<dir>/skills/needle-engine/SKILL.md`
15
- * for each supported AI agent directory (`.claude/`, `.github/`, `.agents/`).
16
- * Both Claude Code and GitHub Copilot auto-load skills based on their
17
- * description frontmatter, so the AI agent will automatically have Needle
18
- * Engine context when working in the project.
44
+ * Auto-detects AI coding agents by checking for their config directories
45
+ * in the project root, then writes the Needle Engine skill in each agent's
46
+ * native format.
19
47
  *
20
- * The skill is only written if at least one of the supported directories
21
- * already exists in the project root (i.e. the developer is already using
22
- * an AI coding agent).
48
+ * Supported agents: Claude Code, GitHub Copilot, Cursor, Codex / universal.
49
+ *
50
+ * The skill is only written if at least one agent directory already exists
51
+ * (i.e. the developer is already using an AI coding agent).
23
52
  * Old skill files are always overwritten so the skill stays up to date with
24
53
  * the engine version.
25
54
  *
@@ -33,33 +62,79 @@ export function needleAI(command, config, userSettings) {
33
62
  name: pluginName,
34
63
  enforce: "pre",
35
64
  buildStart() {
36
- installClaudeSkill();
65
+ installSkills();
37
66
  },
38
67
  configureServer() {
39
- installClaudeSkill();
68
+ installSkills();
40
69
  },
41
70
  };
42
71
  }
43
72
 
44
- function writeSkill(claudeDir) {
45
- const skillDir = join(claudeDir, "skills", "needle-engine");
73
+ /** Read the SKILL.md template shipped with the engine. */
74
+ function getSkillContent() {
75
+ const templatePath = join(__dirname, "../../SKILL.md");
76
+ return readFileSync(templatePath, "utf8");
77
+ }
78
+
79
+ /**
80
+ * Extract the body of a SKILL.md file (everything after the YAML frontmatter).
81
+ * Returns the full content if no frontmatter is found.
82
+ */
83
+ function stripFrontmatter(content) {
84
+ const match = content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n([\s\S]*)$/);
85
+ return match ? match[1].trimStart() : content;
86
+ }
87
+
88
+ /**
89
+ * Write a SKILL.md file into `<agentDir>/skills/needle-engine/SKILL.md`.
90
+ * Used by Claude Code, GitHub Copilot, and the universal .agents/ directory.
91
+ */
92
+ function writeSkillMd(agentDir, content) {
93
+ const skillDir = join(agentDir, "skills", "needle-engine");
46
94
  if (!existsSync(skillDir)) {
47
95
  mkdirSync(skillDir, { recursive: true });
48
96
  }
49
97
  const skillPath = join(skillDir, "SKILL.md");
50
- const templatePath = join(__dirname, "../../SKILL.md");
51
- const content = readFileSync(templatePath, "utf8");
52
98
  writeFileSync(skillPath, content, "utf8");
53
99
  return skillPath;
54
100
  }
55
101
 
56
- function installClaudeSkill() {
102
+ /**
103
+ * Write a Cursor rule file at `.cursor/rules/needle-engine.mdc`.
104
+ * Cursor uses its own frontmatter format (description, globs, alwaysApply).
105
+ */
106
+ function writeCursorRule(cwd, content) {
107
+ const rulesDir = join(cwd, ".cursor", "rules");
108
+ if (!existsSync(rulesDir)) {
109
+ mkdirSync(rulesDir, { recursive: true });
110
+ }
111
+ const rulePath = join(rulesDir, "needle-engine.mdc");
112
+ const body = stripFrontmatter(content);
113
+ const cursorContent = `---
114
+ description: Needle Engine context — use when editing TypeScript components, Vite config, GLB assets, or anything related to @needle-tools/engine.
115
+ globs:
116
+ alwaysApply: false
117
+ ---
118
+ ${body}`;
119
+ writeFileSync(rulePath, cursorContent, "utf8");
120
+ return rulePath;
121
+ }
122
+
123
+ /** Detect agents and install the Needle Engine skill for each. */
124
+ function installSkills() {
57
125
  const cwd = process.cwd();
58
- const dirs = [".claude", ".github", ".agents"].map(d => join(cwd, d)).filter(d => existsSync(d));
59
- if (dirs.length === 0) return; // only install if developer uses an AI coding agent
126
+ const detected = agents.filter(a => existsSync(join(cwd, a.detect)));
127
+ if (detected.length === 0) return;
128
+
129
+ const content = getSkillContent();
130
+ const names = [];
131
+
132
+ for (const agent of detected) {
133
+ const path = agent.write(cwd, content);
134
+ if (path) names.push(agent.name);
135
+ }
60
136
 
61
- for (const dir of dirs) {
62
- const path = writeSkill(dir);
63
- if (path) needleLog(`[${pluginName}] Installed Needle Engine skill → ${path}`);
137
+ if (names.length > 0) {
138
+ needleLog(`[${pluginName}] Detected ${names.length} agent${names.length === 1 ? "" : "s"}: ${names.join(", ")}`);
64
139
  }
65
140
  }
@@ -25,6 +25,12 @@ const packages_to_resolve = {
25
25
  'three/nodes': (res, packageName, index, importPath) => {
26
26
  return "three/examples/jsm/nodes/Nodes.js";
27
27
  },
28
+ 'three/tsl': (res, packageName, index, importPath) => {
29
+ return "three/src/nodes/TSL.js";
30
+ },
31
+ 'three/webgpu': (res, packageName, index, importPath) => {
32
+ return "three/src/Three.WebGPU.js";
33
+ },
28
34
  'three': "auto-resolve",
29
35
 
30
36
  // Handle all previous imports where users did import using @needle-engine/src
@@ -158,6 +158,13 @@ function handleOptimizeDeps(config) {
158
158
  config.optimizeDeps.exclude.push('@needle-tools/engine');
159
159
  needleLog("needle-dependencies", 'Detected local @needle-tools/engine package → will exclude it from optimization');
160
160
  }
161
+ // When engine is excluded from optimizeDeps, three must also be excluded
162
+ // to prevent vite from pre-bundling a second copy → "Multiple instances of Three.js"
163
+ if (!config.optimizeDeps.include?.includes('three') &&
164
+ !config.optimizeDeps.exclude.includes('three')) {
165
+ config.optimizeDeps.exclude.push('three');
166
+ needleLog("needle-dependencies", 'Detected local @needle-tools/engine package → will also exclude three from optimization');
167
+ }
161
168
  // When engine is excluded from optimizeDeps, three-mesh-bvh must also be excluded.
162
169
  // The BVH worker (generateMeshBVH.worker.js) uses bare imports like `import 'three'`
163
170
  // which only resolve correctly when served through Vite's dev server module system.
@@ -130,7 +130,7 @@ export class AnimationUtils {
130
130
  const objectName = track["__objectName"] ?? track.name.substring(0, track.name.indexOf("."));
131
131
  // let obj = gltf.scene.getObjectByName(objectName);
132
132
  // this finds unnamed objects that still have tracks targeting them
133
- obj = scene.getObjectByProperty('uuid', objectName);
133
+ obj = scene.getObjectByProperty('uuid', objectName) ?? null;
134
134
 
135
135
  if (!obj) {
136
136
  // console.warn("could not find " + objectName, animation, gltf.scene);
@@ -8,7 +8,7 @@ import { Application } from "./engine_application.js";
8
8
  export function ensureAudioContextIsResumed() {
9
9
  Application.registerWaitForInteraction(() => {
10
10
  // this is a fix for https://github.com/mrdoob/three.js/issues/27779 & https://linear.app/needle/issue/NE-4257
11
- const ctx = AudioContext.getContext();
11
+ const ctx = AudioContext.getContext() as unknown as globalThis.AudioContext;
12
12
  ctx.addEventListener("statechange", () => {
13
13
  setTimeout(() => {
14
14
  // on iOS the audiocontext can be interrupted: https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/state#resuming_interrupted_play_states_in_ios_safari
@@ -8,7 +8,7 @@ import {
8
8
  Texture, WebGLRenderer, type WebGLRendererParameters, WebGLRenderTarget, type WebXRArrayCamera
9
9
  } from 'three';
10
10
  /** @ts-ignore (not yet in types?) */
11
- import { BasicNodeLibrary } from "three";
11
+ import BasicNodeLibrary from "three/src/renderers/webgpu/nodes/BasicNodeLibrary.js";
12
12
  import * as Stats from 'three/examples/jsm/libs/stats.module.js';
13
13
  import type { EffectComposer as ThreeEffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
14
14
  import { nodeFrame } from "three/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodeBuilder.js";
@@ -637,12 +637,9 @@ export class Context implements IContext {
637
637
  this.renderer.outputColorSpace = SRGBColorSpace;
638
638
 
639
639
  // Injecting the core nodes library here, like WebGPURenderer backends do
640
+ // In r183, three.js reads renderer.library directly (not renderer.nodes.library)
640
641
  //@ts-ignore
641
- this.renderer.nodes = {
642
- library: new BasicNodeLibrary(),
643
- modelViewMatrix: null,
644
- modelNormalViewMatrix: null,
645
- };
642
+ this.renderer.library = new BasicNodeLibrary();
646
643
  // this.renderer.toneMapping = AgXToneMapping;
647
644
  this.lodsManager.setRenderer(this.renderer);
648
645
 
@@ -134,7 +134,6 @@ export class ObjectUtils {
134
134
  font,
135
135
  size: 1,
136
136
  depth: depth,
137
- height: depth,
138
137
  bevelEnabled: opts?.bevel || false,
139
138
  bevelThickness: .01,
140
139
  bevelOffset: .01,
@@ -1,5 +1,3 @@
1
- import { dof } from "three/src/nodes/TSL.js";
2
-
3
1
  import { isDevEnvironment } from "./debug/index.js";
4
2
  import { BUILD_TIME, GENERATOR, PUBLIC_KEY, VERSION } from "./engine_constants.js";
5
3
  import { ContextEvent, ContextRegistry } from "./engine_context_registry.js";
@@ -2,7 +2,7 @@ import { createLoaders } from "@needle-tools/gltf-progressive";
2
2
  import { CubeUVReflectionMapping, EquirectangularRefractionMapping, SRGBColorSpace, Texture, TextureLoader, WebGLRenderer } from "three";
3
3
  import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader";
4
4
  import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader";
5
- import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
5
+ import { HDRLoader } from "three/examples/jsm/loaders/HDRLoader";
6
6
 
7
7
  const running: Map<string, Promise<Texture | null>> = new Map();
8
8
 
@@ -41,13 +41,13 @@ async function internalLoadPMREM(url: URL, renderer: WebGLRenderer) {
41
41
  const isHdr = pathname.endsWith(".hdr");
42
42
  const isKtx2 = pathname.endsWith(".ktx2");
43
43
 
44
- let loader: RGBELoader | EXRLoader | TextureLoader | KTX2Loader;
44
+ let loader: HDRLoader | EXRLoader | TextureLoader | KTX2Loader;
45
45
 
46
46
  if (isEXR) {
47
47
  loader = new EXRLoader();
48
48
  }
49
49
  else if (isHdr) {
50
- loader = new RGBELoader();
50
+ loader = new HDRLoader();
51
51
  }
52
52
  else if (isKtx2) {
53
53
  const { ktx2Loader } = createLoaders(renderer);
@@ -533,7 +533,7 @@ export class Graphics {
533
533
  mesh.frustumCulled = false;
534
534
  this.scene.children.length = 0;
535
535
  this.scene.add(mesh);
536
- this.renderer.setSize(texture.image.width, texture.image.height);
536
+ this.renderer.setSize((texture.image as any).width, (texture.image as any).height);
537
537
  this.renderer.clear();
538
538
  this.renderer.render(this.scene, this.perspectiveCam);
539
539
  const tex = new Texture(this.renderer.domElement);
@@ -618,7 +618,7 @@ export class Graphics {
618
618
  if (force === true || texture["isCompressedTexture"] === true) {
619
619
  texture = copyTexture(texture);
620
620
  }
621
- const image = texture.image;
621
+ const image = texture.image as any;
622
622
  if (isImageBitmap(image)) {
623
623
  const canvas = document.createElement('canvas');
624
624
  canvas.width = image.width;