@needle-tools/engine 4.13.1-beta → 4.13.1-next.9fc3e64
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.
- package/CHANGELOG.md +6 -0
- package/components.needle.json +1 -1
- package/dist/gltf-progressive-CaUGGjVL.umd.cjs +10 -0
- package/dist/gltf-progressive-Dbi_Tfhb.js +1528 -0
- package/dist/gltf-progressive-DuAR0MQR.min.js +10 -0
- package/dist/{needle-engine.bundle-CGtsEhyJ.js → needle-engine.bundle-BZRE5G6O.js} +335 -312
- package/dist/{needle-engine.bundle-fbFZTOKP.umd.cjs → needle-engine.bundle-Dqrh7aWw.umd.cjs} +29 -29
- package/dist/{needle-engine.bundle-6774fXoY.min.js → needle-engine.bundle-DwybonUg.min.js} +47 -47
- package/dist/needle-engine.d.ts +446 -39
- package/dist/needle-engine.js +3 -3
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/lib/engine/engine_context.js +12 -2
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_physics.d.ts +2 -0
- package/lib/engine/engine_physics.js +2 -0
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_physics_rapier.d.ts +2 -0
- package/lib/engine/engine_physics_rapier.js +2 -0
- package/lib/engine/engine_physics_rapier.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +1 -0
- package/lib/engine/engine_utils.js +1 -0
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/engine_utils_screenshot.d.ts +171 -14
- package/lib/engine/engine_utils_screenshot.js +65 -0
- package/lib/engine/engine_utils_screenshot.js.map +1 -1
- package/lib/engine/engine_utils_screenshot.xr.d.ts +1 -1
- package/lib/engine/engine_utils_screenshot.xr.js +1 -1
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js +3 -0
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
- package/lib/engine/xr/NeedleXRSession.d.ts +5 -0
- package/lib/engine/xr/NeedleXRSession.js +5 -0
- package/lib/engine/xr/NeedleXRSession.js.map +1 -1
- package/lib/engine-components/ContactShadows.d.ts +2 -0
- package/lib/engine-components/ContactShadows.js +2 -0
- package/lib/engine-components/ContactShadows.js.map +1 -1
- package/lib/engine-components/EventList.js +2 -2
- package/lib/engine-components/EventList.js.map +1 -1
- package/lib/engine-components/Renderer.d.ts +4 -3
- package/lib/engine-components/Renderer.js +4 -3
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/RigidBody.d.ts +57 -5
- package/lib/engine-components/RigidBody.js +57 -5
- package/lib/engine-components/RigidBody.js.map +1 -1
- package/lib/engine-components/ScreenCapture.d.ts +1 -0
- package/lib/engine-components/ScreenCapture.js +1 -0
- package/lib/engine-components/ScreenCapture.js.map +1 -1
- package/lib/engine-components/SeeThrough.d.ts +70 -5
- package/lib/engine-components/SeeThrough.js +70 -5
- package/lib/engine-components/SeeThrough.js.map +1 -1
- package/lib/engine-components/ShadowCatcher.d.ts +56 -4
- package/lib/engine-components/ShadowCatcher.js +56 -4
- package/lib/engine-components/ShadowCatcher.js.map +1 -1
- package/lib/engine-components/Skybox.d.ts +43 -7
- package/lib/engine-components/Skybox.js +43 -7
- package/lib/engine-components/Skybox.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +1 -1
- package/lib/engine-components/VideoPlayer.js +7 -1
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/timeline/PlayableDirector.d.ts +4 -0
- package/lib/engine-components/timeline/PlayableDirector.js +4 -0
- package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
- package/lib/engine-components/timeline/TimelineModels.d.ts +14 -0
- package/lib/engine-components/timeline/TimelineModels.js +4 -0
- package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
- package/lib/engine-components/utils/OpenURL.d.ts +1 -0
- package/lib/engine-components/utils/OpenURL.js +1 -0
- package/lib/engine-components/utils/OpenURL.js.map +1 -1
- package/lib/engine-components/web/CursorFollow.d.ts +1 -0
- package/lib/engine-components/web/CursorFollow.js +1 -0
- package/lib/engine-components/web/CursorFollow.js.map +1 -1
- package/lib/engine-components/web/ScrollFollow.d.ts +1 -0
- package/lib/engine-components/web/ScrollFollow.js +1 -0
- package/lib/engine-components/web/ScrollFollow.js.map +1 -1
- package/lib/engine-components/webxr/WebARCameraBackground.d.ts +9 -0
- package/lib/engine-components/webxr/WebARCameraBackground.js +9 -0
- package/lib/engine-components/webxr/WebARCameraBackground.js.map +1 -1
- package/lib/engine-components/webxr/WebXR.d.ts +1 -0
- package/lib/engine-components/webxr/WebXR.js +1 -0
- package/lib/engine-components/webxr/WebXR.js.map +1 -1
- package/package.json +3 -3
- package/plugins/vite/build-pipeline.js +16 -2
- package/src/engine/engine_context.ts +17 -3
- package/src/engine/engine_physics.ts +4 -0
- package/src/engine/engine_physics_rapier.ts +8 -4
- package/src/engine/engine_utils.ts +1 -0
- package/src/engine/engine_utils_screenshot.ts +241 -17
- package/src/engine/engine_utils_screenshot.xr.ts +1 -1
- package/src/engine/extensions/NEEDLE_techniques_webgl.ts +3 -0
- package/src/engine/xr/NeedleXRSession.ts +5 -0
- package/src/engine-components/ContactShadows.ts +6 -1
- package/src/engine-components/EventList.ts +2 -2
- package/src/engine-components/Renderer.ts +14 -13
- package/src/engine-components/RigidBody.ts +64 -8
- package/src/engine-components/ScreenCapture.ts +1 -0
- package/src/engine-components/SeeThrough.ts +76 -9
- package/src/engine-components/ShadowCatcher.ts +61 -6
- package/src/engine-components/Skybox.ts +48 -12
- package/src/engine-components/VideoPlayer.ts +7 -1
- package/src/engine-components/timeline/PlayableDirector.ts +5 -1
- package/src/engine-components/timeline/SignalAsset.ts +1 -1
- package/src/engine-components/timeline/TimelineModels.ts +18 -2
- package/src/engine-components/utils/OpenURL.ts +1 -0
- package/src/engine-components/web/CursorFollow.ts +1 -0
- package/src/engine-components/web/ScrollFollow.ts +1 -0
- package/src/engine-components/webxr/WebARCameraBackground.ts +12 -3
- package/src/engine-components/webxr/WebXR.ts +1 -0
- package/dist/gltf-progressive-BURrJW0U.umd.cjs +0 -8
- package/dist/gltf-progressive-DHLDFNvQ.min.js +0 -8
- package/dist/gltf-progressive-eiJCrjLb.js +0 -1400
- package/src/include/three/DragControls.js +0 -232
|
@@ -32,6 +32,7 @@ declare type ScreenshotImageMimeType = "image/webp" | "image/png" | "image/jpeg"
|
|
|
32
32
|
* const dataUrl = screenshot();
|
|
33
33
|
* saveImage(dataUrl, "screenshot.png");
|
|
34
34
|
* ```
|
|
35
|
+
*
|
|
35
36
|
*/
|
|
36
37
|
export function screenshot(context?: Context, width?: number, height?: number, mimeType: ScreenshotImageMimeType = "image/webp", camera?: Camera | null): string | null {
|
|
37
38
|
return screenshot2({ context, width, height, mimeType, camera });
|
|
@@ -106,12 +107,30 @@ export declare type ScreenshotOptionsBlob = ScreenshotOptions & {
|
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
export declare type ScreenshotOptionsShare = ScreenshotOptions & {
|
|
110
|
+
/**
|
|
111
|
+
* Set `{ type: "share" }` to share the screenshot using the Web Share API. The promise will resolve with the blob of the screenshot and whether it was shared successfully or not. Note that the Web Share API is only available in secure contexts (HTTPS) and on some platforms.
|
|
112
|
+
*/
|
|
109
113
|
type: "share",
|
|
114
|
+
/**
|
|
115
|
+
* The filename to use when sharing the screenshot. If not provided, a default filename will be used.
|
|
116
|
+
*/
|
|
110
117
|
filename?: string,
|
|
118
|
+
/**
|
|
119
|
+
* The mime type of the shared file. If not provided, the mime type will be inferred from the screenshot options or default to "image/png".
|
|
120
|
+
*/
|
|
111
121
|
file_type?: ScreenshotImageMimeType,
|
|
112
122
|
|
|
123
|
+
/**
|
|
124
|
+
* The title to use when sharing the screenshot. This is optional and may not be supported by all platforms.
|
|
125
|
+
*/
|
|
113
126
|
title?: string,
|
|
127
|
+
/**
|
|
128
|
+
* The text to use when sharing the screenshot. This is optional and may not be supported by all platforms.
|
|
129
|
+
*/
|
|
114
130
|
text?: string,
|
|
131
|
+
/**
|
|
132
|
+
* The URL to use when sharing the screenshot. This is optional and may not be supported by all platforms.
|
|
133
|
+
*/
|
|
115
134
|
url?: string,
|
|
116
135
|
}
|
|
117
136
|
|
|
@@ -120,36 +139,241 @@ declare type ScreenshotOptionsShareReturnType = {
|
|
|
120
139
|
shared: boolean,
|
|
121
140
|
}
|
|
122
141
|
|
|
123
|
-
/**
|
|
124
|
-
* Take a screenshot from the current scene and return a {@link Texture}. This can applied to a surface in 3D space.
|
|
125
|
-
* @param opts Provide `{ type: "texture" }` to get a texture instead of a data url.
|
|
142
|
+
/**
|
|
143
|
+
* Take a screenshot from the current scene and return a {@link Texture}. This can be applied to a surface in 3D space.
|
|
144
|
+
* @param opts Provide `{ type: "texture" }` to get a texture instead of a data url.
|
|
126
145
|
* @returns The texture of the screenshot. Returns null if the screenshot could not be taken.
|
|
146
|
+
* @category Utilities
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* // Create a texture from the current view
|
|
150
|
+
* const screenshotTexture = screenshot2({ type: "texture", width: 512, height: 512 });
|
|
151
|
+
* if (screenshotTexture) {
|
|
152
|
+
* myMaterial.map = screenshotTexture;
|
|
153
|
+
* myMaterial.needsUpdate = true;
|
|
154
|
+
* }
|
|
155
|
+
*
|
|
156
|
+
* // Update an existing texture
|
|
157
|
+
* const existingTexture = new Texture();
|
|
158
|
+
* screenshot2({ type: "texture", target: existingTexture, transparent: true });
|
|
159
|
+
* ```
|
|
127
160
|
*/
|
|
128
161
|
export function screenshot2(opts: ScreenshotOptionsTexture): Texture | null;
|
|
162
|
+
|
|
129
163
|
/**
|
|
130
|
-
* Take a screenshot from the current scene.
|
|
131
|
-
*
|
|
132
|
-
* @
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
164
|
+
* Take a screenshot from the current scene and return a data URL string.
|
|
165
|
+
*
|
|
166
|
+
* @param opts Screenshot options. All properties are optional.
|
|
167
|
+
* @returns The data URL of the screenshot (e.g., "data:image/png;base64,..."). Returns null if the screenshot could not be taken.
|
|
168
|
+
* @category Utilities
|
|
169
|
+
*
|
|
170
|
+
* @example Basic screenshot
|
|
171
|
+
* ```ts
|
|
172
|
+
* // Take a simple screenshot with default settings
|
|
173
|
+
* const dataUrl = screenshot2({});
|
|
174
|
+
* console.log(dataUrl); // "data:image/webp;base64,..."
|
|
175
|
+
* ```
|
|
176
|
+
*
|
|
177
|
+
* @example High-resolution screenshot with transparent background
|
|
178
|
+
* ```ts
|
|
179
|
+
* const dataUrl = screenshot2({
|
|
180
|
+
* width: 2048,
|
|
181
|
+
* height: 2048,
|
|
182
|
+
* mimeType: "image/png",
|
|
183
|
+
* transparent: true,
|
|
184
|
+
* trim: true, // Remove transparent edges
|
|
185
|
+
* });
|
|
186
|
+
* ```
|
|
187
|
+
*
|
|
188
|
+
* @example Screenshot with custom background color
|
|
189
|
+
* ```ts
|
|
190
|
+
* import { Color } from "three";
|
|
191
|
+
*
|
|
192
|
+
* const dataUrl = screenshot2({
|
|
193
|
+
* width: 1024,
|
|
194
|
+
* height: 1024,
|
|
195
|
+
* background: new Color(0x00ff00), // Green background
|
|
196
|
+
* });
|
|
197
|
+
* ```
|
|
198
|
+
*
|
|
199
|
+
* @example Download screenshot automatically
|
|
200
|
+
* ```ts
|
|
201
|
+
* screenshot2({
|
|
202
|
+
* width: 1920,
|
|
203
|
+
* height: 1080,
|
|
204
|
+
* mimeType: "image/jpeg",
|
|
205
|
+
* download_filename: "my-scene.jpg",
|
|
206
|
+
* });
|
|
207
|
+
* ```
|
|
208
|
+
*
|
|
209
|
+
* @example Manual download using saveImage
|
|
210
|
+
* ```ts
|
|
211
|
+
* const dataUrl = screenshot2({
|
|
212
|
+
* width: 1024,
|
|
213
|
+
* height: 1024,
|
|
214
|
+
* mimeType: "image/webp",
|
|
215
|
+
* transparent: true,
|
|
216
|
+
* });
|
|
217
|
+
* if (dataUrl) {
|
|
218
|
+
* saveImage(dataUrl, "screenshot.webp");
|
|
219
|
+
* }
|
|
220
|
+
* ```
|
|
221
|
+
*
|
|
222
|
+
* @example Screenshot from specific camera
|
|
223
|
+
* ```ts
|
|
224
|
+
* const myCamera = this.gameObject.getComponent(Camera);
|
|
225
|
+
* const dataUrl = screenshot2({
|
|
226
|
+
* camera: myCamera,
|
|
227
|
+
* width: 1024,
|
|
136
228
|
* height: 1024,
|
|
137
|
-
*
|
|
138
|
-
* transparent: true,
|
|
139
|
-
* })
|
|
140
|
-
* // use saveImage to download the image
|
|
141
|
-
* saveImage(res, "screenshot.webp");
|
|
229
|
+
* });
|
|
142
230
|
* ```
|
|
143
231
|
*/
|
|
144
232
|
export function screenshot2(opts: ScreenshotOptionsDataUrl): string | null;
|
|
145
233
|
|
|
146
234
|
/**
|
|
147
|
-
* Take a screenshot asynchronously
|
|
148
|
-
*
|
|
149
|
-
* @param
|
|
235
|
+
* Take a screenshot asynchronously and return a Blob. This is useful when you need to process or upload the image data.
|
|
236
|
+
*
|
|
237
|
+
* @param opts Set `{ type: "blob" }` to get a blob instead of a data url. All other {@link ScreenshotOptions} are also available.
|
|
238
|
+
* @returns A Promise that resolves with the Blob of the screenshot. Returns null if the screenshot could not be taken.
|
|
239
|
+
* @category Utilities
|
|
240
|
+
*
|
|
241
|
+
* @example Upload screenshot to server
|
|
242
|
+
* ```ts
|
|
243
|
+
* const blob = await screenshot2({ type: "blob", mimeType: "image/png" });
|
|
244
|
+
* if (blob) {
|
|
245
|
+
* const formData = new FormData();
|
|
246
|
+
* formData.append("screenshot", blob, "screenshot.png");
|
|
247
|
+
* await fetch("/api/upload", { method: "POST", body: formData });
|
|
248
|
+
* }
|
|
249
|
+
* ```
|
|
250
|
+
*
|
|
251
|
+
* @example Save blob to file (browser download)
|
|
252
|
+
* ```ts
|
|
253
|
+
* const blob = await screenshot2({
|
|
254
|
+
* type: "blob",
|
|
255
|
+
* width: 1920,
|
|
256
|
+
* height: 1080,
|
|
257
|
+
* transparent: true
|
|
258
|
+
* });
|
|
259
|
+
* if (blob) {
|
|
260
|
+
* const url = URL.createObjectURL(blob);
|
|
261
|
+
* saveImage(url, "screenshot.png");
|
|
262
|
+
* URL.revokeObjectURL(url); // Clean up
|
|
263
|
+
* }
|
|
264
|
+
* ```
|
|
150
265
|
*/
|
|
151
266
|
export function screenshot2(opts: ScreenshotOptionsBlob): Promise<Blob | null>;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Take a screenshot and share it using the Web Share API (mobile-friendly).
|
|
270
|
+
*
|
|
271
|
+
* **Note**: The Web Share API is only available in secure contexts (HTTPS) and may not be supported on all platforms/browsers.
|
|
272
|
+
*
|
|
273
|
+
* @param opts Set `{ type: "share" }` to share the screenshot. Additional options like `filename`, `title`, `text`, and `url` can be provided.
|
|
274
|
+
* @returns A Promise that resolves with an object containing the blob and whether it was successfully shared.
|
|
275
|
+
* @category Utilities
|
|
276
|
+
*
|
|
277
|
+
* @example Share screenshot on mobile
|
|
278
|
+
* ```ts
|
|
279
|
+
* const result = await screenshot2({
|
|
280
|
+
* type: "share",
|
|
281
|
+
* filename: "my-creation.png",
|
|
282
|
+
* title: "Check out my 3D scene!",
|
|
283
|
+
* text: "I created this with Needle Engine",
|
|
284
|
+
* url: "https://engine.needle.tools",
|
|
285
|
+
* mimeType: "image/png",
|
|
286
|
+
* });
|
|
287
|
+
*
|
|
288
|
+
* if (result.shared) {
|
|
289
|
+
* console.log("Screenshot shared successfully!");
|
|
290
|
+
* } else {
|
|
291
|
+
* console.log("User cancelled or sharing not supported");
|
|
292
|
+
* }
|
|
293
|
+
* ```
|
|
294
|
+
*
|
|
295
|
+
* @example Share with fallback
|
|
296
|
+
* ```ts
|
|
297
|
+
* const result = await screenshot2({
|
|
298
|
+
* type: "share",
|
|
299
|
+
* filename: "screenshot.webp",
|
|
300
|
+
* file_type: "image/webp",
|
|
301
|
+
* });
|
|
302
|
+
*
|
|
303
|
+
* if (!result.shared && result.blob) {
|
|
304
|
+
* // Fallback: download the image instead
|
|
305
|
+
* const url = URL.createObjectURL(result.blob);
|
|
306
|
+
* saveImage(url, "screenshot.webp");
|
|
307
|
+
* URL.revokeObjectURL(url);
|
|
308
|
+
* }
|
|
309
|
+
* ```
|
|
310
|
+
*/
|
|
152
311
|
export function screenshot2(opts: ScreenshotOptionsShare): Promise<ScreenshotOptionsShareReturnType>;
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Take a screenshot from the current scene with advanced options.
|
|
315
|
+
*
|
|
316
|
+
* This is the main screenshot function in Needle Engine with support for multiple output formats:
|
|
317
|
+
* - **Data URL** (default): Returns a base64-encoded string suitable for img src attributes
|
|
318
|
+
* - **Texture**: Returns a Three.js Texture that can be applied to materials
|
|
319
|
+
* - **Blob**: Returns a Blob for uploading or processing (async)
|
|
320
|
+
* - **Share**: Uses the Web Share API to share the screenshot (async, mobile-friendly)
|
|
321
|
+
*
|
|
322
|
+
* @param opts Screenshot options. Use the `type` property to specify output format. See {@link ScreenshotOptions} for all available options.
|
|
323
|
+
* @returns Depending on the `type` option:
|
|
324
|
+
* - Data URL (string) when `type` is undefined or not specified
|
|
325
|
+
* - Texture when `type: "texture"`
|
|
326
|
+
* - Promise<Blob | null> when `type: "blob"`
|
|
327
|
+
* - Promise<{blob, shared}> when `type: "share"`
|
|
328
|
+
*
|
|
329
|
+
* Returns null (or Promise resolving to null) if the screenshot could not be taken.
|
|
330
|
+
*
|
|
331
|
+
* @category Utilities
|
|
332
|
+
*
|
|
333
|
+
* @example WebXR / AR Screenshots
|
|
334
|
+
* ```ts
|
|
335
|
+
* // Screenshots work automatically in WebXR sessions
|
|
336
|
+
* // The camera feed will be composited with your 3D content
|
|
337
|
+
* const dataUrl = screenshot2({
|
|
338
|
+
* width: 1920,
|
|
339
|
+
* height: 1080
|
|
340
|
+
* });
|
|
341
|
+
* ```
|
|
342
|
+
*
|
|
343
|
+
* **Note for AR Screenshots**: To include the device camera feed in AR screenshots, you need to request camera access.
|
|
344
|
+
* This is done automatically when you use {@link WebARCameraBackground} component in your scene.
|
|
345
|
+
* If you're not using WebARCameraBackground, you can request camera access manually:
|
|
346
|
+
* ```ts
|
|
347
|
+
* export class MyComponent extends Behaviour {
|
|
348
|
+
* onBeforeXR(mode: XRSessionMode, args: XRSessionInit): void {
|
|
349
|
+
* if (mode === "immersive-ar") {
|
|
350
|
+
* args.optionalFeatures = args.optionalFeatures || [];
|
|
351
|
+
* args.optionalFeatures.push('camera-access');
|
|
352
|
+
* }
|
|
353
|
+
* }
|
|
354
|
+
* }
|
|
355
|
+
* ```
|
|
356
|
+
* Without camera access, AR screenshots will only show your 3D content without the real-world background.
|
|
357
|
+
*
|
|
358
|
+
* @example Combining multiple options
|
|
359
|
+
* ```ts
|
|
360
|
+
* // High-res transparent screenshot with custom camera
|
|
361
|
+
* const myCamera = this.gameObject.getComponent(Camera);
|
|
362
|
+
* const texture = screenshot2({
|
|
363
|
+
* type: "texture",
|
|
364
|
+
* camera: myCamera,
|
|
365
|
+
* width: 2048,
|
|
366
|
+
* height: 2048,
|
|
367
|
+
* transparent: true,
|
|
368
|
+
* trim: true,
|
|
369
|
+
* render_events: true, // Ensure reflection probes are updated
|
|
370
|
+
* });
|
|
371
|
+
* ```
|
|
372
|
+
*
|
|
373
|
+
* @see {@link screenshot} for a simpler alternative with fewer options
|
|
374
|
+
* @see {@link saveImage} for downloading data URLs
|
|
375
|
+
* @see {@link ScreenshotOptions} for all available options
|
|
376
|
+
*/
|
|
153
377
|
export function screenshot2(opts: ScreenshotOptionsDataUrl | ScreenshotOptionsTexture | ScreenshotOptionsBlob | ScreenshotOptionsShare)
|
|
154
378
|
: Texture | string | null | Promise<Blob | null> | Promise<ScreenshotOptionsShareReturnType> {
|
|
155
379
|
|
|
@@ -5,7 +5,7 @@ import { isDevEnvironment, showBalloonError } from "./debug/index.js";
|
|
|
5
5
|
// Adapted from WebARCameraBackground
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Assigns the camera feed to a texture - this must be called during the render loop
|
|
8
|
+
* Assigns the camera feed to a texture - this must be called during the render loop.
|
|
9
9
|
*/
|
|
10
10
|
export function updateTextureFromXRFrame(renderer: WebGLRenderer, target: Texture): boolean {
|
|
11
11
|
|
|
@@ -621,6 +621,9 @@ function createUniformProperties(material: CustomShader) {
|
|
|
621
621
|
case "_Color":
|
|
622
622
|
defineProperty("color", key);
|
|
623
623
|
break;
|
|
624
|
+
case "_map":
|
|
625
|
+
defineProperty("map", key);
|
|
626
|
+
break;
|
|
624
627
|
// case "_Metallic":
|
|
625
628
|
// defineProperty("metalness", key);
|
|
626
629
|
// break;
|
|
@@ -279,7 +279,12 @@ const $initialFov = Symbol("initial-fov");
|
|
|
279
279
|
* The XRRig can be accessed via the `rig` property
|
|
280
280
|
* Set a custom XRRig via `NeedleXRSession.addRig(...)` or `NeedleXRSession.removeRig(...)`
|
|
281
281
|
* By default the active XRRig with the highest priority in the scene is used
|
|
282
|
+
*
|
|
283
|
+
* ### Screenshots in XR
|
|
284
|
+
* Screenshots work automatically during XR sessions, including AR camera feed compositing. See {@link screenshot2} for more information.
|
|
285
|
+
*
|
|
282
286
|
* @category XR
|
|
287
|
+
* @see {@link screenshot2} for taking screenshots in XR sessions
|
|
283
288
|
*/
|
|
284
289
|
export class NeedleXRSession implements INeedleXRSession {
|
|
285
290
|
|
|
@@ -13,6 +13,9 @@ import { HideFlags, IGameObject, Vec3 } from "../engine/engine_types.js";
|
|
|
13
13
|
import { getParam } from "../engine/engine_utils.js"
|
|
14
14
|
import { setCustomVisibility } from "../engine/js-extensions/Layers.js";
|
|
15
15
|
import { Behaviour, GameObject } from "./Component.js";
|
|
16
|
+
import type { Light } from "./Light.js";
|
|
17
|
+
import type { Renderer } from "./Renderer.js";
|
|
18
|
+
import type { ShadowCatcher } from "./ShadowCatcher.js";
|
|
16
19
|
|
|
17
20
|
const debug = getParam("debugcontactshadows");
|
|
18
21
|
|
|
@@ -45,7 +48,8 @@ type FitParameters = {
|
|
|
45
48
|
|
|
46
49
|
/**
|
|
47
50
|
* [ContactShadows](https://engine.needle.tools/docs/api/ContactShadows) renders proximity-based soft shadows on flat surfaces.
|
|
48
|
-
* Ideal for products or objects that need visual grounding without real-time shadows.
|
|
51
|
+
* Ideal for products or objects that need visual grounding without real-time shadows.
|
|
52
|
+
* Produces soft, blurred shadows that hug the ground, giving a sense of contact and depth.
|
|
49
53
|
*
|
|
50
54
|
* 
|
|
51
55
|
*
|
|
@@ -72,6 +76,7 @@ type FitParameters = {
|
|
|
72
76
|
* @summary Display contact shadows on the ground
|
|
73
77
|
* @category Rendering
|
|
74
78
|
* @group Components
|
|
79
|
+
* @see {@link ShadowCatcher} for real-time shadows from lights (more accurate, higher performance cost)
|
|
75
80
|
* @see {@link Light} for real-time shadow casting
|
|
76
81
|
* @see {@link Renderer} for material/rendering control
|
|
77
82
|
* @link https://engine.needle.tools/samples/contact-shadows for a demo of contact shadows
|
|
@@ -175,10 +175,10 @@ export class EventList<TArgs extends any = any> implements IEventList {
|
|
|
175
175
|
// remap the arguments to the new instance (e.g. if an object is passed as an argument to the event list and this object has been cloned we want to remap it to the clone)
|
|
176
176
|
const newArguments = method.arguments?.map(arg => {
|
|
177
177
|
if (arg instanceof Object && arg.uuid) {
|
|
178
|
-
return ctx[arg.uuid];
|
|
178
|
+
return ctx[arg.uuid].clone;
|
|
179
179
|
}
|
|
180
180
|
else if ((arg as IComponent)?.isComponent) {
|
|
181
|
-
return ctx[(arg as IComponent).guid];
|
|
181
|
+
return ctx[(arg as IComponent).guid].clone;
|
|
182
182
|
}
|
|
183
183
|
return arg;
|
|
184
184
|
});
|
|
@@ -200,22 +200,24 @@ class SharedMaterialArray implements ISharedMaterials {
|
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
/**
|
|
203
|
-
* [Renderer](https://engine.needle.tools/docs/api/Renderer) controls rendering properties of meshes including materials,
|
|
204
|
-
* lightmaps, reflection probes, and GPU instancing.
|
|
203
|
+
* The [Renderer](https://engine.needle.tools/docs/api/Renderer) component controls rendering properties of meshes including materials,
|
|
204
|
+
* lightmaps, reflection probes, and GPU instancing.
|
|
205
205
|
*
|
|
206
|
-
* **Materials:**
|
|
207
|
-
* Access materials via `sharedMaterials` array. Changes affect all instances.
|
|
208
|
-
* Use material cloning for per-instance variations.
|
|
206
|
+
* **Materials:**
|
|
207
|
+
* Access materials via `sharedMaterials` array. Changes affect all instances.
|
|
208
|
+
* Use material cloning for per-instance variations.
|
|
209
209
|
*
|
|
210
|
-
* **Instancing:**
|
|
211
|
-
* Enable GPU instancing for improved performance with many identical objects.
|
|
212
|
-
* Use `Renderer.setInstanced(obj, true)` or `enableInstancing` property.
|
|
210
|
+
* **Instancing:**
|
|
211
|
+
* Enable GPU instancing for improved performance with many identical objects.
|
|
212
|
+
* Use `Renderer.setInstanced(obj, true)` or `enableInstancing` property.
|
|
213
213
|
*
|
|
214
|
-
* **Lightmaps:**
|
|
215
|
-
* Baked lighting is automatically applied when exported from Unity.
|
|
216
|
-
* Access via the associated {@link RendererLightmap} component.
|
|
214
|
+
* **Lightmaps:**
|
|
215
|
+
* Baked lighting is automatically applied when exported from Unity or Blender.
|
|
216
|
+
* Access via the associated {@link RendererLightmap} component.
|
|
217
|
+
*
|
|
218
|
+
* [](https://engine.needle.tools/samples/multiple-lightmaps/)
|
|
217
219
|
*
|
|
218
|
-
* **Debug options:**
|
|
220
|
+
* **Debug options:**
|
|
219
221
|
* - `?debugrenderer` - Log renderer info
|
|
220
222
|
* - `?wireframe` - Show wireframe rendering
|
|
221
223
|
* - `?noinstancing` - Disable GPU instancing
|
|
@@ -235,7 +237,6 @@ class SharedMaterialArray implements ISharedMaterials {
|
|
|
235
237
|
* @group Components
|
|
236
238
|
* @see {@link ReflectionProbe} for environment reflections
|
|
237
239
|
* @see {@link Light} for scene lighting
|
|
238
|
-
* @see {@link LODGroup} for level of detail
|
|
239
240
|
*/
|
|
240
241
|
export class Renderer extends Behaviour implements IRenderer {
|
|
241
242
|
|
|
@@ -2,14 +2,18 @@ import { Matrix4, Object3D, Quaternion, Vector3, Vector3Like } from "three";
|
|
|
2
2
|
|
|
3
3
|
import { isDevEnvironment } from "../engine/debug/index.js";
|
|
4
4
|
import { MODULES } from "../engine/engine_modules.js";
|
|
5
|
+
import type { Physics } from "../engine/engine_physics.js";
|
|
5
6
|
import { CollisionDetectionMode, RigidbodyConstraints } from "../engine/engine_physics.types.js";
|
|
7
|
+
import type { RapierPhysics } from "../engine/engine_physics_rapier.js";
|
|
6
8
|
import { serializable } from "../engine/engine_serialization_decorator.js";
|
|
7
9
|
import { Context, FrameEvent } from "../engine/engine_setup.js";
|
|
8
|
-
import { getWorldPosition } from "../engine/engine_three_utils.js";
|
|
9
10
|
import type { IRigidbody, Vec3 } from "../engine/engine_types.js";
|
|
10
11
|
import { validate } from "../engine/engine_util_decorator.js";
|
|
11
12
|
import { delayForFrames, Watch } from "../engine/engine_utils.js";
|
|
13
|
+
import type { CharacterController } from "./CharacterController.js";
|
|
14
|
+
import type { BoxCollider, CapsuleCollider, Collider,MeshCollider, SphereCollider } from "./Collider.js";
|
|
12
15
|
import { Behaviour } from "./Component.js";
|
|
16
|
+
import type { Joint } from "./Joints.js";
|
|
13
17
|
|
|
14
18
|
class TransformWatch {
|
|
15
19
|
|
|
@@ -134,15 +138,67 @@ class TransformWatch {
|
|
|
134
138
|
}
|
|
135
139
|
|
|
136
140
|
/**
|
|
137
|
-
*
|
|
141
|
+
* Rigidbody component for realistic physics simulation and dynamic interactions.
|
|
142
|
+
* Used together with a {@link Collider} to enable physical behavior like gravity, collisions,
|
|
143
|
+
* forces, and constraints. Powered by the Rapier physics engine.
|
|
138
144
|
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
+
* 
|
|
146
|
+
*
|
|
147
|
+
* **Key features:**
|
|
148
|
+
* - Dynamic, kinematic, or static body types
|
|
149
|
+
* - Automatic or manual mass calculation
|
|
150
|
+
* - Gravity, drag, and angular drag control
|
|
151
|
+
* - Position and rotation constraints (locking axes)
|
|
152
|
+
* - Force, impulse, and velocity manipulation
|
|
153
|
+
* - Sleep/wake optimization for performance
|
|
154
|
+
* - Continuous collision detection (CCD) support
|
|
155
|
+
*
|
|
156
|
+
* @example Basic dynamic rigidbody
|
|
157
|
+
* ```ts
|
|
158
|
+
* const rb = this.gameObject.getComponent(Rigidbody);
|
|
159
|
+
* rb.useGravity = true;
|
|
160
|
+
* rb.mass = 2.0;
|
|
161
|
+
* rb.drag = 0.5;
|
|
162
|
+
* ```
|
|
163
|
+
*
|
|
164
|
+
* @example Apply force to move object
|
|
165
|
+
* ```ts
|
|
166
|
+
* const rb = this.gameObject.getComponent(Rigidbody);
|
|
167
|
+
* rb.applyForce(new Vector3(0, 10, 0)); // Upward force
|
|
168
|
+
* rb.applyImpulse(new Vector3(5, 0, 0)); // Instant velocity change
|
|
169
|
+
* ```
|
|
170
|
+
*
|
|
171
|
+
* @example Kinematic rigidbody (manually controlled)
|
|
172
|
+
* ```ts
|
|
173
|
+
* const rb = this.gameObject.getComponent(Rigidbody);
|
|
174
|
+
* rb.isKinematic = true; // Not affected by forces
|
|
175
|
+
* rb.teleport({ x: 0, y: 5, z: 0 }); // Move without physics
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
* @example Lock rotation on Y axis (useful for characters)
|
|
179
|
+
* ```ts
|
|
180
|
+
* const rb = this.gameObject.getComponent(Rigidbody);
|
|
181
|
+
* rb.lockRotationY = true;
|
|
182
|
+
* // Or use constraints for multiple axes:
|
|
183
|
+
* rb.constraints = RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezePositionZ;
|
|
184
|
+
* ```
|
|
185
|
+
*
|
|
186
|
+
* @summary Enables physics simulation with forces, gravity, and collisions
|
|
187
|
+
* @category Physics
|
|
145
188
|
* @group Components
|
|
189
|
+
* @see {@link BoxCollider} for box-shaped colliders
|
|
190
|
+
* @see {@link SphereCollider} for sphere-shaped colliders
|
|
191
|
+
* @see {@link CapsuleCollider} for capsule-shaped colliders
|
|
192
|
+
* @see {@link MeshCollider} for mesh-based colliders
|
|
193
|
+
* @see {@link Collider} for collider base class
|
|
194
|
+
* @see {@link CharacterController} for character movement
|
|
195
|
+
* @see {@link Joint} for connecting bodies
|
|
196
|
+
* @see {@link RapierPhysics} for physics engine implementation
|
|
197
|
+
* @see {@link Physics} for raycasting and physics utilities
|
|
198
|
+
* @link https://engine.needle.tools/samples/physics-basic/
|
|
199
|
+
* @link https://engine.needle.tools/samples/physics-playground/
|
|
200
|
+
* @link https://engine.needle.tools/samples/physics-&-animation/
|
|
201
|
+
* @link https://rapier.rs/docs/user_guides/javascript/rigid_bodies
|
|
146
202
|
*/
|
|
147
203
|
export class Rigidbody extends Behaviour implements IRigidbody {
|
|
148
204
|
|
|
@@ -100,6 +100,7 @@ export declare type ScreenCaptureOptions = {
|
|
|
100
100
|
*
|
|
101
101
|
* @summary Share screen, camera or microphone in a networked room
|
|
102
102
|
* @category Networking
|
|
103
|
+
* @category Multimedia
|
|
103
104
|
* @group Components
|
|
104
105
|
* @see {@link VideoPlayer} for displaying the received stream
|
|
105
106
|
* @see {@link Voip} for voice-only communication
|
|
@@ -6,9 +6,11 @@ import { serializable } from "../engine/engine_serialization_decorator.js";
|
|
|
6
6
|
import { getTempVector } from "../engine/engine_three_utils.js";
|
|
7
7
|
import { getParam } from "../engine/engine_utils.js";
|
|
8
8
|
import { USDObject, USDZExporterContext } from "./api.js";
|
|
9
|
+
import type { Camera } from "./Camera.js";
|
|
9
10
|
import { Behaviour } from "./Component.js";
|
|
10
11
|
import { IUSDExporterExtension } from "./export/usdz/Extension.js";
|
|
11
12
|
import { USDZExporter } from "./export/usdz/USDZExporter.js";
|
|
13
|
+
import type { OrbitControls } from "./OrbitControls.js";
|
|
12
14
|
import { Renderer } from "./Renderer.js";
|
|
13
15
|
|
|
14
16
|
const debugSeeThrough = getParam("debugseethrough");
|
|
@@ -32,17 +34,82 @@ let i = 0;
|
|
|
32
34
|
|
|
33
35
|
|
|
34
36
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
37
|
+
* Automatically fades objects to transparent when they obscure a reference point from the camera's view.
|
|
38
|
+
* Perfect for architectural visualization, third-person games, or any scenario where objects should
|
|
39
|
+
* become see-through when blocking the view of important content.
|
|
40
|
+
*
|
|
41
|
+
* [](https://engine.needle.tools/samples/see-through)
|
|
42
|
+
*
|
|
43
|
+
* **How it works:**
|
|
44
|
+
* - Monitors the angle between the camera, this object, and a reference point
|
|
45
|
+
* - When the object blocks the view to the reference point, it fades out
|
|
46
|
+
* - Automatically affects all {@link Renderer} components on this object and children
|
|
47
|
+
* - Supports both transparent fading and alpha hash (dithered) fading
|
|
48
|
+
*
|
|
49
|
+
* **Key Features:**
|
|
50
|
+
* - Smooth fade transitions with configurable duration
|
|
51
|
+
* - Optional alpha hash for maintaining opaque rendering (better performance)
|
|
52
|
+
* - Automatic or manual update modes
|
|
53
|
+
* - Disables raycasting when faded (objects become click-through)
|
|
54
|
+
* - Preserves original material properties when re-enabled
|
|
55
|
+
*
|
|
56
|
+
* **Configuration:**
|
|
57
|
+
* - `referencePoint` - Object to keep visible (defaults to scene root)
|
|
58
|
+
* - `fadeDuration` - Transition speed (default: 0.05 seconds)
|
|
59
|
+
* - `minAlpha` - Minimum opacity when faded (default: 0 = fully transparent)
|
|
60
|
+
* - `useAlphaHash` - Use dithered transparency instead of true transparency (default: true)
|
|
61
|
+
*
|
|
62
|
+
* **Performance:**
|
|
63
|
+
* - Materials are cloned once per renderer to avoid affecting shared materials
|
|
64
|
+
* - Updates direction calculation every 20 frames by default (configurable via `autoUpdate`)
|
|
65
|
+
* - Use `needsUpdate = true` to force immediate recalculation
|
|
66
|
+
*
|
|
67
|
+
* **Requirements:**
|
|
68
|
+
* Requires at least one {@link Renderer} component on the same object or child objects.
|
|
69
|
+
*
|
|
70
|
+
* @example Make walls transparent when blocking view
|
|
71
|
+
* ```ts
|
|
72
|
+
* // Add to walls or obstacles
|
|
73
|
+
* const seeThrough = wall.addComponent(SeeThrough);
|
|
74
|
+
* seeThrough.referencePoint = player; // Keep player visible
|
|
75
|
+
* seeThrough.fadeDuration = 0.2; // Smooth fade
|
|
76
|
+
* seeThrough.minAlpha = 0.2; // Slightly visible when faded
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* @example Third-person camera with see-through objects
|
|
80
|
+
* ```ts
|
|
81
|
+
* const character = GameObject.findByName("Character");
|
|
82
|
+
* const obstacles = GameObject.findByTag("Obstacle");
|
|
83
|
+
*
|
|
84
|
+
* for (const obstacle of obstacles) {
|
|
85
|
+
* const st = obstacle.addComponent(SeeThrough);
|
|
86
|
+
* st.referencePoint = character;
|
|
87
|
+
* st.useAlphaHash = true; // Better performance
|
|
88
|
+
* }
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @example Manual control of see-through effect
|
|
92
|
+
* ```ts
|
|
93
|
+
* const seeThrough = this.gameObject.getComponent(SeeThrough);
|
|
94
|
+
* if (seeThrough) {
|
|
95
|
+
* seeThrough.autoUpdate = false; // Disable automatic fading
|
|
96
|
+
*
|
|
97
|
+
* // Manually control transparency
|
|
98
|
+
* seeThrough.updateAlpha(0.5, 0.3); // Fade to 50% over 0.3 seconds
|
|
99
|
+
*
|
|
100
|
+
* // Or use override for precise control
|
|
101
|
+
* seeThrough.overrideAlpha = 0.8; // Force 80% opacity
|
|
102
|
+
* }
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @summary Fades objects when they obscure the camera's view of a reference point
|
|
44
106
|
* @category Rendering
|
|
45
107
|
* @group Components
|
|
108
|
+
* @see {@link Renderer} for material/rendering control (required)
|
|
109
|
+
* @see {@link Camera} for camera setup and configuration
|
|
110
|
+
* @see {@link OrbitControls} for camera controls in similar use cases
|
|
111
|
+
* @link https://see-through-walls-z23hmxbz1kjfjn.needle.run/ for live demo
|
|
112
|
+
* @link https://engine.needle.tools/samples/see-through for sample project
|
|
46
113
|
*/
|
|
47
114
|
export class SeeThrough extends Behaviour {
|
|
48
115
|
|