@needle-tools/engine 4.8.8-next.7387ba3 → 4.8.8-next.937fc15
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 +4 -5
- package/README.md +1 -3
- package/dist/{needle-engine.bundle-Dm2TtQhy.min.js → needle-engine.bundle--r19rtjt.min.js} +82 -82
- package/dist/{needle-engine.bundle-fg_vGCYe.umd.cjs → needle-engine.bundle-CAvlLwYK.umd.cjs} +104 -104
- package/dist/{needle-engine.bundle-D47vIqsQ.js → needle-engine.bundle-Dao6Iztd.js} +687 -689
- package/dist/needle-engine.js +2 -2
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/lib/engine/engine_loaders.callbacks.d.ts +1 -0
- package/lib/engine/engine_loaders.callbacks.js +1 -0
- package/lib/engine/engine_loaders.callbacks.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.d.ts +2 -2
- package/lib/engine/webcomponents/needle-engine.js +11 -18
- package/lib/engine/webcomponents/needle-engine.js.map +1 -1
- package/lib/engine-components/Camera.d.ts +2 -0
- package/lib/engine-components/Camera.js +5 -1
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/DropListener.d.ts +4 -3
- package/lib/engine-components/DropListener.js +4 -3
- package/lib/engine-components/DropListener.js.map +1 -1
- package/lib/engine-components/OrbitControls.d.ts +29 -6
- package/lib/engine-components/OrbitControls.js +41 -3
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/Skybox.js +8 -9
- package/lib/engine-components/Skybox.js.map +1 -1
- package/lib/engine-components/api.d.ts +1 -0
- package/lib/engine-components/api.js.map +1 -1
- package/package.json +1 -1
- package/plugins/common/files.js +6 -3
- package/plugins/vite/editor-connection.js +4 -4
- package/src/engine/engine_loaders.callbacks.ts +1 -0
- package/src/engine/webcomponents/needle-engine.ts +10 -17
- package/src/engine-components/Camera.ts +7 -1
- package/src/engine-components/DropListener.ts +4 -3
- package/src/engine-components/OrbitControls.ts +63 -10
- package/src/engine-components/Skybox.ts +9 -10
- package/src/engine-components/api.ts +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/engine",
|
|
3
|
-
"version": "4.8.8-next.
|
|
3
|
+
"version": "4.8.8-next.937fc15",
|
|
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": {
|
package/plugins/common/files.js
CHANGED
|
@@ -24,9 +24,12 @@ export function copyFilesSync(src, dest, override = true, ctx = undefined) {
|
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
else if (override || !existsSync(dest)) {
|
|
27
|
-
if (
|
|
28
|
-
ctx
|
|
27
|
+
if (exists) {
|
|
28
|
+
if (ctx) {
|
|
29
|
+
ctx.count += 1;
|
|
30
|
+
}
|
|
31
|
+
copyFileSync(src, dest);
|
|
29
32
|
}
|
|
30
|
-
|
|
33
|
+
else console.warn(`[needle-copy] - File at ${src} does not exist`);
|
|
31
34
|
}
|
|
32
35
|
};
|
|
@@ -63,16 +63,16 @@ function createPlugin(isInstalled) {
|
|
|
63
63
|
name: "needle-editor-connection",
|
|
64
64
|
// Setup HMR port for connecting to the editor
|
|
65
65
|
config(config) {
|
|
66
|
-
if (
|
|
66
|
+
if (isInstalled) {
|
|
67
67
|
if (!config.server) config.server = {};
|
|
68
68
|
if (!config.server.hmr) config.server.hmr = {};
|
|
69
69
|
if (config.server.hmr === false) {
|
|
70
|
-
setTimeout(() => console.log("HMR is disabled, not initializing Needle Editor"));
|
|
70
|
+
setTimeout(() => console.log("[needle-editor-sync] HMR is disabled, not initializing Needle Editor"));
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
|
-
if (config.server.hmr.port
|
|
73
|
+
if (config.server.hmr.port === undefined) {
|
|
74
74
|
config.server.hmr.port = 1107;
|
|
75
|
-
setTimeout(() => console.log("Update HMR port to " + config.server.hmr.port));
|
|
75
|
+
setTimeout(() => console.log("[needle-editor-sync] Update HMR port to " + config.server.hmr.port));
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -98,6 +98,7 @@ export namespace NeedleEngineModelLoader {
|
|
|
98
98
|
* }
|
|
99
99
|
* return null;
|
|
100
100
|
* });
|
|
101
|
+
* ```
|
|
101
102
|
*/
|
|
102
103
|
export function onCreateCustomModelLoader(callback: CustomLoaderCallback, opts?: CustomLoaderOptions) {
|
|
103
104
|
const entry = { name: opts?.name, priority: opts?.priority ?? 0, callback };
|
|
@@ -55,8 +55,8 @@ const observedAttributes = [
|
|
|
55
55
|
* The needle engine web component creates and manages a needle engine context which is responsible for rendering a 3D scene using threejs.
|
|
56
56
|
* The needle engine context is created when the src attribute is set and disposed when the needle engine is removed from the document (you can prevent this by setting the keep-alive attribute to true).
|
|
57
57
|
* The needle engine context is accessible via the context property on the needle engine element (e.g. document.querySelector("needle-engine").context).
|
|
58
|
-
* @link https://engine.needle.tools/docs/reference/needle-engine-attributes
|
|
59
|
-
*
|
|
58
|
+
* See {@link https://engine.needle.tools/docs/reference/needle-engine-attributes}
|
|
59
|
+
*
|
|
60
60
|
* @example
|
|
61
61
|
* <needle-engine src="https://example.com/scene.glb"></needle-engine>
|
|
62
62
|
* @example
|
|
@@ -65,7 +65,7 @@ const observedAttributes = [
|
|
|
65
65
|
export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngineComponent {
|
|
66
66
|
|
|
67
67
|
static get observedAttributes() {
|
|
68
|
-
return observedAttributes
|
|
68
|
+
return observedAttributes;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
public get loadingProgress01(): number { return this._loadingProgress01; }
|
|
@@ -95,7 +95,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
95
95
|
/**
|
|
96
96
|
* Get the current context for this web component instance. The context is created when the src attribute is set and the loading has finished.
|
|
97
97
|
* The context is disposed when the needle engine is removed from the document (you can prevent this by setting the keep-alive attribute to true).
|
|
98
|
-
* @returns
|
|
98
|
+
* @returns a promise that resolves to the context when the loading has finished
|
|
99
99
|
*/
|
|
100
100
|
public getContext(): Promise<Context> {
|
|
101
101
|
return new Promise((res, _rej) => {
|
|
@@ -328,19 +328,12 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
328
328
|
break;
|
|
329
329
|
|
|
330
330
|
case "tonemapping":
|
|
331
|
-
case "tone-mapping":
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
case "
|
|
336
|
-
|
|
337
|
-
break;
|
|
338
|
-
}
|
|
339
|
-
case "background-blurriness": {
|
|
340
|
-
this.applyAttributes();
|
|
341
|
-
break;
|
|
342
|
-
}
|
|
343
|
-
case "environment-intensity": {
|
|
331
|
+
case "tone-mapping":
|
|
332
|
+
case "tone-mapping-exposure":
|
|
333
|
+
case "background-blurriness":
|
|
334
|
+
case "background-color":
|
|
335
|
+
case "environment-intensity":
|
|
336
|
+
{
|
|
344
337
|
this.applyAttributes();
|
|
345
338
|
break;
|
|
346
339
|
}
|
|
@@ -10,6 +10,7 @@ import { getTempColor, getWorldPosition } from "../engine/engine_three_utils.js"
|
|
|
10
10
|
import type { ICamera } from "../engine/engine_types.js"
|
|
11
11
|
import { getParam } from "../engine/engine_utils.js";
|
|
12
12
|
import { RGBAColor } from "../engine/js-extensions/index.js";
|
|
13
|
+
import { NeedleXREventArgs } from "../engine/engine_xr.js";
|
|
13
14
|
import { Behaviour, GameObject } from "./Component.js";
|
|
14
15
|
import { OrbitControls } from "./OrbitControls.js";
|
|
15
16
|
|
|
@@ -446,6 +447,11 @@ export class Camera extends Behaviour implements ICamera {
|
|
|
446
447
|
this.context.removeCamera(this);
|
|
447
448
|
}
|
|
448
449
|
|
|
450
|
+
onLeaveXR(_args: NeedleXREventArgs): void {
|
|
451
|
+
// Restore previous FOV
|
|
452
|
+
this.fieldOfView = this._fov;
|
|
453
|
+
}
|
|
454
|
+
|
|
449
455
|
|
|
450
456
|
/** @internal */
|
|
451
457
|
onBeforeRender() {
|
|
@@ -553,7 +559,7 @@ export class Camera extends Behaviour implements ICamera {
|
|
|
553
559
|
}
|
|
554
560
|
|
|
555
561
|
// restore previous fov (e.g. when user was in VR or AR and the camera's fov has changed)
|
|
556
|
-
this.fieldOfView = this.
|
|
562
|
+
this.fieldOfView = this.fieldOfView;
|
|
557
563
|
|
|
558
564
|
if (debug) {
|
|
559
565
|
const msg = `[Camera] Apply ClearFlags: ${ClearFlags[this._clearFlags]} - \"${this.name}\"`;
|
|
@@ -399,10 +399,11 @@ export class DropListener extends Behaviour {
|
|
|
399
399
|
private _abort: AbortController | null = null;
|
|
400
400
|
|
|
401
401
|
/**
|
|
402
|
-
* Processes dropped files
|
|
403
|
-
*
|
|
402
|
+
* Processes dropped files and loads them as 3D models.
|
|
403
|
+
* When enabled, it also handles network drops (sending files between clients).
|
|
404
|
+
* Automatically handles cancelling previous uploads if new files are dropped.
|
|
404
405
|
* @param fileList Array of dropped files
|
|
405
|
-
* @param ctx Context information about where the drop occurred
|
|
406
|
+
* @param ctx Context information about where on the screen or in 3D space the drop occurred
|
|
406
407
|
*/
|
|
407
408
|
private async addFromFiles(fileList: Array<File>, ctx: DropContext) {
|
|
408
409
|
if (debug) console.log("Add files", fileList)
|
|
@@ -889,6 +889,8 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
889
889
|
}
|
|
890
890
|
else this._fovLerpDuration = this.targetLerpDuration;
|
|
891
891
|
}
|
|
892
|
+
|
|
893
|
+
// if (this.context.mainCameraComponent) this.context.mainCameraComponent.fieldOfView = fov;
|
|
892
894
|
}
|
|
893
895
|
|
|
894
896
|
/** Moves the camera look-at target to a position smoothly.
|
|
@@ -984,10 +986,11 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
984
986
|
*/
|
|
985
987
|
fitCamera(options?: FitCameraOptions);
|
|
986
988
|
fitCamera(objects?: Object3D | Array<Object3D>, options?: Omit<FitCameraOptions, "objects">);
|
|
987
|
-
fitCamera(objectsOrOptions?: Object3D | Array<Object3D> | FitCameraOptions, options?: FitCameraOptions) {
|
|
989
|
+
fitCamera(objectsOrOptions?: Object3D | Array<Object3D> | FitCameraOptions, options?: FitCameraOptions): void {
|
|
988
990
|
|
|
989
991
|
if (this.context.isInXR) {
|
|
990
992
|
// camera fitting in XR is not supported
|
|
993
|
+
console.warn('[OrbitControls] Can not fit camera while XR session is active');
|
|
991
994
|
return;
|
|
992
995
|
}
|
|
993
996
|
|
|
@@ -1032,7 +1035,7 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
1032
1035
|
return;
|
|
1033
1036
|
}
|
|
1034
1037
|
if (!options) options = {}
|
|
1035
|
-
const { immediate = false, centerCamera
|
|
1038
|
+
const { immediate = false, centerCamera, cameraNearFar = "auto", fitOffset = 1.1, fov = camera?.fov } = options;
|
|
1036
1039
|
const size = new Vector3();
|
|
1037
1040
|
const center = new Vector3();
|
|
1038
1041
|
// TODO would be much better to calculate the bounds in camera space instead of world space -
|
|
@@ -1078,9 +1081,18 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
1078
1081
|
this.minZoom = distance * 0.01;
|
|
1079
1082
|
|
|
1080
1083
|
const verticalOffset = 0.05;
|
|
1081
|
-
|
|
1082
1084
|
const lookAt = center.clone();
|
|
1083
1085
|
lookAt.y -= size.y * verticalOffset;
|
|
1086
|
+
if (options.targetOffset) {
|
|
1087
|
+
if (options.targetOffset.x !== undefined) lookAt.x += options.targetOffset.x;
|
|
1088
|
+
if (options.targetOffset.y !== undefined) lookAt.y += options.targetOffset.y;
|
|
1089
|
+
if (options.targetOffset.z !== undefined) lookAt.z += options.targetOffset.z;
|
|
1090
|
+
}
|
|
1091
|
+
if (options.relativeTargetOffset) {
|
|
1092
|
+
if (options.relativeTargetOffset.x !== undefined) lookAt.x += options.relativeTargetOffset.x * size.x;
|
|
1093
|
+
if (options.relativeTargetOffset.y !== undefined) lookAt.y += options.relativeTargetOffset.y * size.y;
|
|
1094
|
+
if (options.relativeTargetOffset.z !== undefined) lookAt.z += options.relativeTargetOffset.z * size.z;
|
|
1095
|
+
}
|
|
1084
1096
|
this.setLookTargetPosition(lookAt, immediate);
|
|
1085
1097
|
this.setFieldOfView(options.fov, immediate);
|
|
1086
1098
|
|
|
@@ -1107,9 +1119,13 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
1107
1119
|
camera.updateMatrixWorld();
|
|
1108
1120
|
camera.updateProjectionMatrix();
|
|
1109
1121
|
|
|
1110
|
-
const cameraWp = getWorldPosition(camera);
|
|
1111
1122
|
const direction = center.clone();
|
|
1112
|
-
|
|
1123
|
+
if (options.fitDirection) {
|
|
1124
|
+
direction.sub(new Vector3().copy(options.fitDirection).multiplyScalar(1_000_000));
|
|
1125
|
+
}
|
|
1126
|
+
else {
|
|
1127
|
+
direction.sub(camera.worldPosition);
|
|
1128
|
+
}
|
|
1113
1129
|
if (centerCamera === "y")
|
|
1114
1130
|
direction.y = 0;
|
|
1115
1131
|
direction.normalize();
|
|
@@ -1118,6 +1134,16 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
1118
1134
|
direction.y += -verticalOffset * 4 * distance;
|
|
1119
1135
|
|
|
1120
1136
|
let cameraLocalPosition = center.clone().sub(direction);
|
|
1137
|
+
if (options.cameraOffset) {
|
|
1138
|
+
if (options.cameraOffset.x !== undefined) cameraLocalPosition.x += options.cameraOffset.x;
|
|
1139
|
+
if (options.cameraOffset.y !== undefined) cameraLocalPosition.y += options.cameraOffset.y;
|
|
1140
|
+
if (options.cameraOffset.z !== undefined) cameraLocalPosition.z += options.cameraOffset.z;
|
|
1141
|
+
}
|
|
1142
|
+
if (options.relativeCameraOffset) {
|
|
1143
|
+
if (options.relativeCameraOffset.x !== undefined) cameraLocalPosition.x += options.relativeCameraOffset.x * size.x;
|
|
1144
|
+
if (options.relativeCameraOffset.y !== undefined) cameraLocalPosition.y += options.relativeCameraOffset.y * size.y;
|
|
1145
|
+
if (options.relativeCameraOffset.z !== undefined) cameraLocalPosition.z += options.relativeCameraOffset.z * size.z;
|
|
1146
|
+
}
|
|
1121
1147
|
if (camera.parent) {
|
|
1122
1148
|
cameraLocalPosition = camera.parent.worldToLocal(cameraLocalPosition);
|
|
1123
1149
|
}
|
|
@@ -1154,7 +1180,7 @@ export class OrbitControls extends Behaviour implements ICameraController {
|
|
|
1154
1180
|
/**
|
|
1155
1181
|
* Options for fitting the camera to the scene. Used in {@link OrbitControls.fitCamera}
|
|
1156
1182
|
*/
|
|
1157
|
-
|
|
1183
|
+
export type FitCameraOptions = {
|
|
1158
1184
|
/** When enabled debug rendering will be shown */
|
|
1159
1185
|
debug?: boolean,
|
|
1160
1186
|
/**
|
|
@@ -1166,14 +1192,41 @@ declare type FitCameraOptions = {
|
|
|
1166
1192
|
*/
|
|
1167
1193
|
immediate?: boolean,
|
|
1168
1194
|
|
|
1195
|
+
/** Fit offset: A factor to multiply the distance to the objects by
|
|
1196
|
+
* @default 1.1
|
|
1197
|
+
*/
|
|
1198
|
+
fitOffset?: number,
|
|
1199
|
+
|
|
1200
|
+
/** The direction from which the camera should be fitted in worldspace. If not defined the current camera's position will be used */
|
|
1201
|
+
fitDirection?: Vector3Like,
|
|
1202
|
+
|
|
1169
1203
|
/** If set to "y" the camera will be centered in the y axis */
|
|
1170
1204
|
centerCamera?: "none" | "y",
|
|
1205
|
+
/** Set to 'auto' to update the camera near or far plane based on the fitted-objects bounds */
|
|
1171
1206
|
cameraNearFar?: "keep" | "auto",
|
|
1172
1207
|
|
|
1173
|
-
|
|
1208
|
+
/**
|
|
1209
|
+
* Offset the camera position in world space
|
|
1210
|
+
*/
|
|
1211
|
+
cameraOffset?: Partial<Vector3Like>,
|
|
1212
|
+
/**
|
|
1213
|
+
* Offset the camera position relative to the size of the objects being focused on (e.g. x: 0.5).
|
|
1214
|
+
* Value range: -1 to 1
|
|
1215
|
+
*/
|
|
1216
|
+
relativeCameraOffset?: Partial<Vector3Like>,
|
|
1174
1217
|
|
|
1175
|
-
/**
|
|
1176
|
-
*
|
|
1218
|
+
/**
|
|
1219
|
+
* Offset the camera target position in world space
|
|
1177
1220
|
*/
|
|
1178
|
-
|
|
1221
|
+
targetOffset?: Partial<Vector3Like>,
|
|
1222
|
+
/**
|
|
1223
|
+
* Offset the camera target position relative to the size of the objects being focused on.
|
|
1224
|
+
* Value range: -1 to 1
|
|
1225
|
+
*/
|
|
1226
|
+
relativeTargetOffset?: Partial<Vector3Like>,
|
|
1227
|
+
|
|
1228
|
+
/**
|
|
1229
|
+
* Field of view (FOV) for the camera
|
|
1230
|
+
*/
|
|
1231
|
+
fov?: number,
|
|
1179
1232
|
}
|
|
@@ -48,21 +48,20 @@ function createRemoteSkyboxComponent(context: IContext, url: string, skybox: boo
|
|
|
48
48
|
const promises = new Array<Promise<any>>();
|
|
49
49
|
ContextRegistry.registerCallback(ContextEvent.ContextCreationStart, (args) => {
|
|
50
50
|
const context = args.context;
|
|
51
|
-
const
|
|
51
|
+
const backgroundImage = context.domElement.getAttribute("background-image");
|
|
52
52
|
const environmentImage = context.domElement.getAttribute("environment-image");
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (debug) console.log("Creating remote skybox to load " + skyboxImage);
|
|
53
|
+
|
|
54
|
+
if (backgroundImage) {
|
|
55
|
+
if (debug) console.log("Creating RemoteSkybox to load background " + backgroundImage);
|
|
57
56
|
// if the user is loading a GLB without a camera then the CameraUtils (which creates the default camera)
|
|
58
57
|
// checks if we have this attribute set and then sets the skybox clearflags accordingly
|
|
59
58
|
// if the user has a GLB with a camera but set to solid color then the skybox image is not visible -> we will just warn then and not override the camera settings
|
|
60
|
-
const promise = createRemoteSkyboxComponent(context,
|
|
59
|
+
const promise = createRemoteSkyboxComponent(context, backgroundImage, true, false, "background-image");
|
|
61
60
|
if (promise) promises.push(promise);
|
|
62
61
|
}
|
|
63
62
|
if (environmentImage) {
|
|
64
|
-
if (debug) console.log("Creating
|
|
65
|
-
const promise = createRemoteSkyboxComponent(context, environmentImage,
|
|
63
|
+
if (debug) console.log("Creating RemoteSkybox to load environment " + environmentImage);
|
|
64
|
+
const promise = createRemoteSkyboxComponent(context, environmentImage, false, true, "environment-image");
|
|
66
65
|
if (promise) promises.push(promise);
|
|
67
66
|
}
|
|
68
67
|
});
|
|
@@ -200,7 +199,7 @@ export class RemoteSkybox extends Behaviour {
|
|
|
200
199
|
console.warn("Potentially invalid skybox URL: \"" + name + "\" on " + (this.name || this.gameObject?.name || "context"));
|
|
201
200
|
}
|
|
202
201
|
|
|
203
|
-
if (debug) console.log("Set
|
|
202
|
+
if (debug) console.log("Set RemoteSkybox url: " + url);
|
|
204
203
|
|
|
205
204
|
if (this._prevUrl === url && this._prevLoadedEnvironment) {
|
|
206
205
|
this.apply();
|
|
@@ -258,7 +257,7 @@ export class RemoteSkybox extends Behaviour {
|
|
|
258
257
|
this._prevBackground = this.context.scene.background;
|
|
259
258
|
if (this.context.scene.environment !== envMap)
|
|
260
259
|
this._prevEnvironment = this.context.scene.environment;
|
|
261
|
-
if (debug) console.log("Set
|
|
260
|
+
if (debug) console.log("Set RemoteSkybox (" + ((this.environment && this.background) ? "environment and background" : this.environment ? "environment" : this.background ? "background" : "none") + ")", this.url, !Camera.backgroundShouldBeTransparent(this.context));
|
|
262
261
|
if (this.environment)
|
|
263
262
|
this.context.scene.environment = envMap;
|
|
264
263
|
if (this.background && !Camera.backgroundShouldBeTransparent(this.context))
|
|
@@ -51,7 +51,8 @@ import "./CameraUtils.js"
|
|
|
51
51
|
import "./AnimationUtils.js"
|
|
52
52
|
import "./AnimationUtilsAutoplay.js"
|
|
53
53
|
|
|
54
|
-
export { DragMode } from "./DragControls.js"
|
|
54
|
+
export { DragMode } from "./DragControls.js";
|
|
55
|
+
export { type FitCameraOptions } from "./OrbitControls.js";
|
|
55
56
|
export type { DropListenerNetworkEventArguments, DropListenerOnDropArguments } from "./DropListener.js";
|
|
56
57
|
export * from "./particlesystem/api.js"
|
|
57
58
|
|