@needle-tools/engine 3.0.1-alpha.4 → 3.1.0-alpha
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 +51 -0
- package/dist/needle-engine.js +13110 -12429
- package/dist/needle-engine.min.js +378 -365
- package/dist/needle-engine.umd.cjs +366 -353
- package/lib/engine/api.d.ts +2 -1
- package/lib/engine/api.js +2 -1
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/codegen/register_types.js +8 -0
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/debug/debug_overlay.js +3 -0
- package/lib/engine/debug/debug_overlay.js.map +1 -1
- package/lib/engine/engine_addressables.d.ts +21 -1
- package/lib/engine/engine_addressables.js +83 -7
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_context.d.ts +2 -0
- package/lib/engine/engine_context.js +3 -0
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_element.d.ts +1 -1
- package/lib/engine/engine_element.js +2 -2
- package/lib/engine/engine_element.js.map +1 -1
- package/lib/engine/engine_element_loading.d.ts +7 -2
- package/lib/engine/engine_element_loading.js +67 -22
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_license.d.ts +1 -1
- package/lib/engine/engine_license.js +6 -19
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_networking.d.ts +1 -0
- package/lib/engine/engine_networking.js +3 -0
- package/lib/engine/engine_networking.js.map +1 -1
- package/lib/engine/engine_serialization.d.ts +2 -2
- package/lib/engine/engine_serialization.js +2 -3
- package/lib/engine/engine_serialization.js.map +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.d.ts +5 -0
- package/lib/engine/engine_serialization_builtin_serializer.js +16 -0
- package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
- package/lib/engine/engine_serialization_core.d.ts +1 -0
- package/lib/engine/engine_serialization_core.js +26 -20
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +9 -0
- package/lib/engine/engine_utils.js +33 -13
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_animator_controller_model.d.ts +1 -0
- package/lib/engine/extensions/NEEDLE_animator_controller_model.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_progressive.js +2 -2
- package/lib/engine/extensions/NEEDLE_progressive.js.map +1 -1
- package/lib/engine-components/AnimatorController.js +22 -3
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/AudioSource.d.ts +2 -3
- package/lib/engine-components/AudioSource.js +28 -32
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/CameraUtils.js.map +1 -1
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/ParticleSystem.d.ts +5 -2
- package/lib/engine-components/ParticleSystem.js +49 -10
- package/lib/engine-components/ParticleSystem.js.map +1 -1
- package/lib/engine-components/ParticleSystemModules.d.ts +2 -0
- package/lib/engine-components/ParticleSystemModules.js +23 -12
- package/lib/engine-components/ParticleSystemModules.js.map +1 -1
- package/lib/engine-components/ScreenCapture.d.ts +1 -0
- package/lib/engine-components/ScreenCapture.js +145 -46
- package/lib/engine-components/ScreenCapture.js.map +1 -1
- package/lib/engine-components/Skybox.js +2 -2
- package/lib/engine-components/Skybox.js.map +1 -1
- package/lib/engine-components/SyncedRoom.js +1 -2
- package/lib/engine-components/SyncedRoom.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +4 -2
- package/lib/engine-components/VideoPlayer.js +35 -12
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/WebXR.d.ts +4 -1
- package/lib/engine-components/WebXR.js +10 -2
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRController.js +2 -2
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/WebXRImageTracking.d.ts +39 -0
- package/lib/engine-components/WebXRImageTracking.js +173 -0
- package/lib/engine-components/WebXRImageTracking.js.map +1 -0
- package/lib/engine-components/codegen/components.d.ts +4 -0
- package/lib/engine-components/codegen/components.js +4 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/DepthOfField.d.ts +2 -0
- package/lib/engine-components/postprocessing/Effects/DepthOfField.js +19 -1
- package/lib/engine-components/postprocessing/Effects/DepthOfField.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.d.ts +13 -0
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.js +63 -0
- package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.js.map +1 -0
- package/lib/engine-components/postprocessing/VolumeParameter.d.ts +1 -0
- package/lib/engine-components/postprocessing/VolumeParameter.js +4 -0
- package/lib/engine-components/postprocessing/VolumeParameter.js.map +1 -1
- package/lib/engine-components/timeline/PlayableDirector.d.ts +3 -1
- package/lib/engine-components/timeline/PlayableDirector.js +40 -2
- package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
- package/lib/engine-components/timeline/TimelineTracks.d.ts +2 -2
- package/lib/engine-components/timeline/TimelineTracks.js +14 -16
- package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
- package/lib/engine-components/ui/Text.js +7 -8
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/include/three/ARButton.d.ts +1 -1
- package/lib/include/three/ARButton.js +2 -1
- package/lib/include/three/ARButton.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -4
- package/plugins/vite/config.js +8 -0
- package/plugins/vite/copyfiles.js +12 -3
- package/plugins/vite/drop.js +1 -0
- package/plugins/vite/index.js +4 -0
- package/plugins/vite/license.js +24 -0
- package/plugins/vite/transform-codegen.js +45 -0
- package/src/engine/api.ts +2 -2
- package/src/engine/codegen/register_types.js +10 -2
- package/src/engine/debug/debug_overlay.ts +2 -0
- package/src/engine/engine_addressables.ts +102 -8
- package/src/engine/engine_context.ts +4 -1
- package/src/engine/engine_element.ts +2 -2
- package/src/engine/engine_element_loading.ts +68 -22
- package/src/engine/engine_license.ts +6 -17
- package/src/engine/engine_networking.ts +4 -0
- package/src/engine/engine_serialization.ts +5 -4
- package/src/engine/engine_serialization_builtin_serializer.ts +23 -3
- package/src/engine/engine_serialization_core.ts +27 -20
- package/src/engine/engine_utils.ts +35 -14
- package/src/engine/extensions/NEEDLE_animator_controller_model.ts +1 -0
- package/src/engine/extensions/NEEDLE_progressive.ts +2 -2
- package/src/engine-components/AnimatorController.ts +18 -3
- package/src/engine-components/AudioSource.ts +29 -38
- package/src/engine-components/CameraUtils.ts +2 -2
- package/src/engine-components/Component.ts +1 -1
- package/src/engine-components/ParticleSystem.ts +52 -10
- package/src/engine-components/ParticleSystemModules.ts +24 -12
- package/src/engine-components/ScreenCapture.ts +149 -49
- package/src/engine-components/Skybox.ts +2 -2
- package/src/engine-components/SyncedRoom.ts +1 -2
- package/src/engine-components/VideoPlayer.ts +33 -11
- package/src/engine-components/WebXR.ts +11 -2
- package/src/engine-components/WebXRController.ts +2 -2
- package/src/engine-components/WebXRImageTracking.ts +192 -0
- package/src/engine-components/codegen/components.ts +4 -0
- package/src/engine-components/postprocessing/Effects/DepthOfField.ts +21 -6
- package/src/engine-components/postprocessing/Effects/TiltShiftEffect.ts +56 -0
- package/src/engine-components/postprocessing/VolumeParameter.ts +5 -0
- package/src/engine-components/timeline/PlayableDirector.ts +38 -2
- package/src/engine-components/timeline/TimelineTracks.ts +15 -18
- package/src/engine-components/ui/Text.ts +7 -8
- package/src/include/three/ARButton.js +2 -2
- package/lib/engine/codegen/license.json +0 -1
- package/license-2447137e.js +0 -4
- package/src/engine/codegen/license.json +0 -1
|
@@ -5,21 +5,12 @@ import { logoSVG } from "./assets";
|
|
|
5
5
|
|
|
6
6
|
const debug = getParam("debuglicense");
|
|
7
7
|
|
|
8
|
+
// This is modified by a bundler (e.g. vite)
|
|
9
|
+
// Do not edit manually
|
|
10
|
+
const HAS_LICENSE = false;
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
let licenseImportPromise: Promise<any> | null = null;
|
|
12
|
-
try {
|
|
13
|
-
licenseImportPromise = import("./codegen/license.json");
|
|
14
|
-
licenseImportPromise.then(res => {
|
|
15
|
-
licenseInformation = res.default;
|
|
16
|
-
licenseImportPromise = null;
|
|
17
|
-
if (debug) console.log("License imported via dynamic import", licenseInformation)
|
|
18
|
-
}).catch(err => { if (debug) console.error("Error on dynamic license import", err) });
|
|
19
|
-
}
|
|
20
|
-
catch (err) {
|
|
21
|
-
if (debug)
|
|
22
|
-
console.log("Importing license failed", err)
|
|
12
|
+
export function hasProLicense() {
|
|
13
|
+
return HAS_LICENSE;
|
|
23
14
|
}
|
|
24
15
|
|
|
25
16
|
|
|
@@ -29,9 +20,7 @@ ContextRegistry.registerCallback(ContextEvent.ContextCreated, evt => {
|
|
|
29
20
|
|
|
30
21
|
async function showLicenseInfo(ctx: IContext) {
|
|
31
22
|
try {
|
|
32
|
-
|
|
33
|
-
//@ts-ignore
|
|
34
|
-
if (!licenseInformation || licenseInformation.hasLicense !== true || debug) return onNonCommercialVersionDetected(ctx);
|
|
23
|
+
if (hasProLicense() !== true) return onNonCommercialVersionDetected(ctx);
|
|
35
24
|
}
|
|
36
25
|
catch (err) {
|
|
37
26
|
if (debug) console.log("License check failed", err)
|
|
@@ -274,6 +274,10 @@ export class NetworkConnection implements INetworkConnection {
|
|
|
274
274
|
return this._currentDelay;
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
+
public sendPing() {
|
|
278
|
+
this.send("ping", { time: this.context.time.time });
|
|
279
|
+
}
|
|
280
|
+
|
|
277
281
|
public userIsInRoom(id: string): boolean {
|
|
278
282
|
return this._currentInRoom.indexOf(id) !== -1;
|
|
279
283
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { serializeObject, deserializeObject } from "./engine_serialization_core";
|
|
2
|
-
import * as builtin from "./engine_serialization_builtin_serializer";
|
|
3
|
-
// export builtin so it will be called and registered
|
|
4
|
-
export { serializeObject, deserializeObject, builtin };
|
|
5
2
|
|
|
6
|
-
export {
|
|
3
|
+
export { serializeObject, deserializeObject };
|
|
4
|
+
|
|
5
|
+
export { serializable, serializeable } from "./engine_serialization_decorator"
|
|
6
|
+
|
|
7
|
+
export * from "./engine_serialization_builtin_serializer";
|
|
@@ -7,6 +7,7 @@ import { CallInfo, EventList } from "../engine-components/EventList";
|
|
|
7
7
|
import { Color, Object3D, Texture, WebGLRenderTarget } from "three";
|
|
8
8
|
import { RenderTexture } from "./engine_texture";
|
|
9
9
|
import { isDevEnvironment } from "../engine/debug/debug";
|
|
10
|
+
import { resolveUrl } from "./engine_utils";
|
|
10
11
|
|
|
11
12
|
// export class SourcePath {
|
|
12
13
|
// src?:string
|
|
@@ -300,8 +301,8 @@ class EventListSerializer extends TypeSerializer {
|
|
|
300
301
|
return undefined;
|
|
301
302
|
}
|
|
302
303
|
|
|
303
|
-
private createEventMethod(target
|
|
304
|
-
|
|
304
|
+
private createEventMethod(target: object, methodName: string, args?: any): Function | undefined {
|
|
305
|
+
|
|
305
306
|
return (...forwardedArgs) => {
|
|
306
307
|
const method = target[methodName];
|
|
307
308
|
if (typeof method === "function") {
|
|
@@ -339,4 +340,23 @@ export class RenderTextureSerializer extends TypeSerializer {
|
|
|
339
340
|
return undefined;
|
|
340
341
|
}
|
|
341
342
|
}
|
|
342
|
-
new RenderTextureSerializer();
|
|
343
|
+
new RenderTextureSerializer();
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
export class UriSerializer extends TypeSerializer {
|
|
347
|
+
constructor() {
|
|
348
|
+
super([URL]);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
onSerialize(_data: string, _context: SerializationContext) {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
onDeserialize(data: string, _context: SerializationContext) {
|
|
356
|
+
if (typeof data === "string") {
|
|
357
|
+
return resolveUrl(_context.gltfId, data);
|
|
358
|
+
}
|
|
359
|
+
return undefined;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
new UriSerializer();
|
|
@@ -173,6 +173,7 @@ export class SerializationContext {
|
|
|
173
173
|
root: THREE.Object3D;
|
|
174
174
|
|
|
175
175
|
gltf?: GLTF;
|
|
176
|
+
/** the url of the glb that is currently being loaded */
|
|
176
177
|
gltfId?: SourceIdentifier;
|
|
177
178
|
object!: THREE.Object3D;
|
|
178
179
|
target?: object;
|
|
@@ -290,16 +291,21 @@ export function deserializeObject(obj: ISerializable, serializedData: object, co
|
|
|
290
291
|
context.type = undefined;
|
|
291
292
|
context.path = key;
|
|
292
293
|
|
|
294
|
+
if (obj.onBeforeDeserializeMember !== undefined) {
|
|
295
|
+
// callback to the instance, if it returns true assume it's done all the things itself
|
|
296
|
+
if (obj.onBeforeDeserializeMember(key, data, context) === true) continue;
|
|
297
|
+
}
|
|
298
|
+
|
|
293
299
|
if (serializedEntryInfo === null) {
|
|
294
300
|
obj[key] = data;
|
|
301
|
+
// if(typeof data === "string"){
|
|
302
|
+
// const serializer = helper.getSerializerForConstructor(String);
|
|
303
|
+
// const res = serializer?.onDeserialize(data, context);
|
|
304
|
+
// if(res !== undefined) obj[key] = res;
|
|
305
|
+
// }
|
|
295
306
|
}
|
|
296
307
|
else {
|
|
297
308
|
|
|
298
|
-
if (obj.onBeforeDeserializeMember !== undefined) {
|
|
299
|
-
// callback to the instance, if it returns true assume it's done all the things itself
|
|
300
|
-
if (obj.onBeforeDeserializeMember(key, data, context) === true) continue;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
309
|
if (Array.isArray(serializedEntryInfo)) {
|
|
304
310
|
for (let i = 0; i < serializedEntryInfo.length; i++) {
|
|
305
311
|
const typeInfoOrConstructor = serializedEntryInfo[i];
|
|
@@ -314,24 +320,25 @@ export function deserializeObject(obj: ISerializable, serializedData: object, co
|
|
|
314
320
|
obj[key] = tryResolve(serializedEntryInfo);
|
|
315
321
|
}
|
|
316
322
|
|
|
317
|
-
function tryResolve(typeInfoOrConstructor) {
|
|
318
|
-
const typeInformationOrConstructor = typeInfoOrConstructor as ITypeInformation;
|
|
319
|
-
// if the entry does specify an object of type ITypeInformation and has the type field set
|
|
320
|
-
const type = typeInformationOrConstructor.type;
|
|
321
|
-
if (type) {
|
|
322
|
-
return deserializeObjectWithType(data, type, context, undefined, obj[key]);
|
|
323
|
-
}
|
|
324
|
-
// it can also just contain a constructor
|
|
325
|
-
else {
|
|
326
|
-
const constructor = typeInfoOrConstructor as Constructor<any>;
|
|
327
|
-
return deserializeObjectWithType(data, constructor, context, undefined, obj[key]);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
323
|
|
|
331
324
|
buffer.length = 0;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (obj.onAfterDeserializeMember !== undefined) {
|
|
328
|
+
obj.onAfterDeserializeMember(key, data, context);
|
|
329
|
+
}
|
|
332
330
|
|
|
333
|
-
|
|
334
|
-
|
|
331
|
+
function tryResolve(typeInfoOrConstructor) {
|
|
332
|
+
const typeInformationOrConstructor = typeInfoOrConstructor as ITypeInformation;
|
|
333
|
+
// if the entry does specify an object of type ITypeInformation and has the type field set
|
|
334
|
+
const type = typeInformationOrConstructor.type;
|
|
335
|
+
if (type) {
|
|
336
|
+
return deserializeObjectWithType(data, type, context, undefined, obj[key]);
|
|
337
|
+
}
|
|
338
|
+
// it can also just contain a constructor
|
|
339
|
+
else {
|
|
340
|
+
const constructor = typeInfoOrConstructor as Constructor<any>;
|
|
341
|
+
return deserializeObjectWithType(data, constructor, context, undefined, obj[key]);
|
|
335
342
|
}
|
|
336
343
|
}
|
|
337
344
|
}
|
|
@@ -203,30 +203,51 @@ export function delay(milliseconds: number): Promise<void> {
|
|
|
203
203
|
});
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
// if a timeline is exported via menu item the audio clip path is relative to the glb (same folder)
|
|
206
|
+
// 1) if a timeline is exported via menu item the audio clip path is relative to the glb (same folder)
|
|
207
207
|
// we need to detect that here and build the new audio source path relative to the new glb location
|
|
208
208
|
// the same is/might be true for any file that is/will be exported via menu item
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
209
|
+
// 2) if the needle.config assetDirectory is modified (from e.g. /assets to /needle/assets) when building a distributable our vite transform and copy plugin will move the files to dist/assets hence we cannot use project-relative paths (because the path changes). What we do instead if make all paths serialized in a glb relative to the glb. The rel: prefix is used to detect urls that need to be resolved.
|
|
210
|
+
const debugGetPath = getParam("debugresolveurl");
|
|
211
|
+
|
|
212
|
+
export const relativePathPrefix = "rel:";
|
|
213
|
+
|
|
214
|
+
/** @deprecated use resolveUrl instead */
|
|
215
|
+
export function getPath(source:SourceIdentifier|undefined, uri:string) : string {
|
|
216
|
+
return resolveUrl(source, uri);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Use to resolve a url serialized in a glTF file
|
|
220
|
+
* @param source The uri of the loading file
|
|
221
|
+
* @param uri The uri of the file to resolve, can be absolute or relative
|
|
222
|
+
* @returns The resolved uri
|
|
223
|
+
*/
|
|
224
|
+
export function resolveUrl(source: SourceIdentifier | undefined, uri: string): string {
|
|
225
|
+
if (uri === undefined) {
|
|
226
|
+
if (debugGetPath) console.warn("getPath: uri is undefined, returning uri", uri);
|
|
227
|
+
return uri;
|
|
228
|
+
}
|
|
229
|
+
if(uri.startsWith("./")) {
|
|
213
230
|
return uri;
|
|
214
231
|
}
|
|
215
232
|
if (uri.startsWith("http")) {
|
|
216
233
|
if (debugGetPath) console.warn("getPath: uri is absolute, returning uri", uri);
|
|
217
234
|
return uri;
|
|
218
235
|
}
|
|
236
|
+
if (source === undefined) {
|
|
237
|
+
if (debugGetPath) console.warn("getPath: source is undefined, returning uri", uri);
|
|
238
|
+
return uri;
|
|
239
|
+
}
|
|
240
|
+
if(uri.startsWith(relativePathPrefix)){
|
|
241
|
+
uri = uri.substring(4);
|
|
242
|
+
}
|
|
219
243
|
const pathIndex = source.lastIndexOf("/");
|
|
220
244
|
if (pathIndex >= 0) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
newUri += uri;
|
|
228
|
-
}
|
|
229
|
-
if (debugGetPath) console.log("getPath:", source, " - changed uri from\n", uri, "\n→ ", newUri);
|
|
245
|
+
// Take the source uri as the base path
|
|
246
|
+
const basePath = source.substring(0, pathIndex + 1);
|
|
247
|
+
// Append the relative uri
|
|
248
|
+
let newUri = basePath + uri;
|
|
249
|
+
// newUri = new URL(newUri, globalThis.location.href).href;
|
|
250
|
+
if (debugGetPath) console.log("source:", source, "- changed uri \nfrom", uri, "\n→ ", newUri, "\n" + basePath);
|
|
230
251
|
return newUri;
|
|
231
252
|
}
|
|
232
253
|
return uri;
|
|
@@ -3,7 +3,7 @@ import { GLTF, GLTFLoader, GLTFLoaderPlugin, GLTFParser } from "three/examples/j
|
|
|
3
3
|
import { SourceIdentifier } from "../engine_types";
|
|
4
4
|
import { Context } from "../engine_setup";
|
|
5
5
|
import { addDracoAndKTX2Loaders } from "../engine_loaders";
|
|
6
|
-
import { delay, getParam,
|
|
6
|
+
import { delay, getParam, resolveUrl } from "../engine_utils";
|
|
7
7
|
|
|
8
8
|
export const EXTENSION_NAME = "NEEDLE_progressive";
|
|
9
9
|
|
|
@@ -130,7 +130,7 @@ export class NEEDLE_progressive implements GLTFLoaderPlugin {
|
|
|
130
130
|
if (progressiveInfo) {
|
|
131
131
|
if (debug)
|
|
132
132
|
console.log(key, progressiveInfo.uri, progressiveInfo.guid);
|
|
133
|
-
const uri =
|
|
133
|
+
const uri = resolveUrl(source, progressiveInfo.uri);
|
|
134
134
|
if (uri.endsWith(".glb") || uri.endsWith(".gltf")) {
|
|
135
135
|
if (!progressiveInfo.guid) {
|
|
136
136
|
console.warn("missing pointer for glb/gltf texture", progressiveInfo);
|
|
@@ -249,9 +249,16 @@ export class AnimatorController {
|
|
|
249
249
|
|
|
250
250
|
if (action) {
|
|
251
251
|
const dur = state.motion.clip!.duration;
|
|
252
|
-
const normalizedTime = dur <= 0 ? 1 : action.time / dur;
|
|
253
|
-
|
|
254
|
-
|
|
252
|
+
const normalizedTime = dur <= 0 ? 1 : Math.abs(action.time / dur);
|
|
253
|
+
let makeTransition = false;
|
|
254
|
+
if (transition.hasExitTime) {
|
|
255
|
+
if (action.timeScale > 0) makeTransition = normalizedTime >= transition.exitTime;
|
|
256
|
+
// When the animation is playing backwards we need to check exit time inverted
|
|
257
|
+
else if(action.timeScale < 0) makeTransition = 1 - normalizedTime >= transition.exitTime;
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
makeTransition = true;
|
|
261
|
+
}
|
|
255
262
|
if (makeTransition) {
|
|
256
263
|
// if (transition.hasExitTime && transition.exitTime >= .9999)
|
|
257
264
|
action.clampWhenFinished = true;
|
|
@@ -283,6 +290,12 @@ export class AnimatorController {
|
|
|
283
290
|
action.time = 0;
|
|
284
291
|
action.play();
|
|
285
292
|
}
|
|
293
|
+
else if (action.time <= 0 && action.timeScale < 0) {
|
|
294
|
+
didTriggerLooping = true;
|
|
295
|
+
action.reset();
|
|
296
|
+
action.time = action.getClip().duration;
|
|
297
|
+
action.play();
|
|
298
|
+
}
|
|
286
299
|
}
|
|
287
300
|
|
|
288
301
|
// call update state behaviours:
|
|
@@ -367,9 +380,11 @@ export class AnimatorController {
|
|
|
367
380
|
action.stop();
|
|
368
381
|
action.reset();
|
|
369
382
|
action.timeScale = this._speed;
|
|
383
|
+
if (state.speed !== undefined) action.timeScale *= state.speed;
|
|
370
384
|
action.enabled = true;
|
|
371
385
|
const duration = state.motion.clip!.duration;
|
|
372
386
|
action.time = offsetNormalized * duration;
|
|
387
|
+
if(action.timeScale < 0) action.time = duration - action.time;
|
|
373
388
|
action.clampWhenFinished = true;
|
|
374
389
|
action.setLoop(LoopOnce, 0);
|
|
375
390
|
if (durationInSec > 0)
|
|
@@ -82,7 +82,7 @@ export class AudioSource extends Behaviour {
|
|
|
82
82
|
document.addEventListener('touchstart', fn);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
@serializable()
|
|
85
|
+
@serializable(URL)
|
|
86
86
|
clip: string = "";
|
|
87
87
|
|
|
88
88
|
@serializable()
|
|
@@ -168,48 +168,11 @@ export class AudioSource extends Behaviour {
|
|
|
168
168
|
public get ShouldPlay(): boolean { return this.shouldPlay; }
|
|
169
169
|
|
|
170
170
|
|
|
171
|
-
private _focusCallback: any;
|
|
172
|
-
private _muteChangedCallback: any;
|
|
173
|
-
|
|
174
171
|
awake() {
|
|
175
172
|
this.audioLoader = new THREE.AudioLoader();
|
|
176
173
|
if (this.playOnAwake) this.shouldPlay = true;
|
|
177
|
-
|
|
178
|
-
window.addEventListener('visibilitychange', _evt => {
|
|
179
|
-
switch (document.visibilityState) {
|
|
180
|
-
case "hidden":
|
|
181
|
-
this.wasPlaying = this.isPlaying;
|
|
182
|
-
this.pause();
|
|
183
|
-
break;
|
|
184
|
-
case "visible":
|
|
185
|
-
if (this.wasPlaying) this.play();
|
|
186
|
-
break;
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
this._focusCallback = () => {
|
|
191
|
-
if (this.enabled && this.playOnAwake && !this.isPlaying && AudioSource._userInteractionRegistered) {
|
|
192
|
-
this.play();
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
this._muteChangedCallback = () => {
|
|
197
|
-
if (this.context.application.muted)
|
|
198
|
-
this.sound?.setVolume(0);
|
|
199
|
-
else
|
|
200
|
-
this.sound?.setVolume(this.volume);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
this.context.application.addEventListener(ApplicationEvents.Visible, this._focusCallback);
|
|
204
|
-
this.context.application.addEventListener(ApplicationEvents.MuteChanged, this._muteChangedCallback);
|
|
205
174
|
}
|
|
206
175
|
|
|
207
|
-
onDestroy() {
|
|
208
|
-
this.context.application.removeEventListener(ApplicationEvents.Visible, this._focusCallback);
|
|
209
|
-
this.context.application.removeEventListener(ApplicationEvents.MuteChanged, this._muteChangedCallback);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
176
|
onEnable(): void {
|
|
214
177
|
if (!AudioSource._userInteractionRegistered) {
|
|
215
178
|
AudioSource._beginWaitForUserInteraction(() => {
|
|
@@ -220,12 +183,40 @@ export class AudioSource extends Behaviour {
|
|
|
220
183
|
else if (this.playOnAwake && this.context.application.isVisible) {
|
|
221
184
|
this.play();
|
|
222
185
|
}
|
|
186
|
+
globalThis.addEventListener('visibilitychange', this.onVisibilityChanged);
|
|
187
|
+
this.context.application.addEventListener(ApplicationEvents.MuteChanged, this.onApplicationMuteChanged);
|
|
223
188
|
}
|
|
224
189
|
|
|
225
190
|
onDisable() {
|
|
191
|
+
globalThis.removeEventListener('visibilitychange', this.onVisibilityChanged);
|
|
192
|
+
this.context.application.removeEventListener(ApplicationEvents.MuteChanged, this.onApplicationMuteChanged);
|
|
226
193
|
this.stop();
|
|
227
194
|
}
|
|
228
195
|
|
|
196
|
+
private onVisibilityChanged = () => {
|
|
197
|
+
switch (document.visibilityState) {
|
|
198
|
+
case "hidden":
|
|
199
|
+
this.wasPlaying = this.isPlaying;
|
|
200
|
+
if (this.isPlaying) {
|
|
201
|
+
this.pause();
|
|
202
|
+
}
|
|
203
|
+
break;
|
|
204
|
+
case "visible":
|
|
205
|
+
if (debug) console.log("visible", this.enabled, this.playOnAwake, !this.isPlaying, AudioSource._userInteractionRegistered, this.wasPlaying);
|
|
206
|
+
if (this.enabled && this.playOnAwake && !this.isPlaying && AudioSource._userInteractionRegistered && this.wasPlaying) {
|
|
207
|
+
this.play();
|
|
208
|
+
}
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
private onApplicationMuteChanged = () => {
|
|
214
|
+
if (this.context.application.muted)
|
|
215
|
+
this.sound?.setVolume(0);
|
|
216
|
+
else
|
|
217
|
+
this.sound?.setVolume(this.volume);
|
|
218
|
+
}
|
|
219
|
+
|
|
229
220
|
private lerp = (x, y, a) => x * (1 - a) + y * a;
|
|
230
221
|
|
|
231
222
|
private onLoaded(buffer) {
|
|
@@ -6,7 +6,7 @@ import { RGBAColor } from "./js-extensions/RGBAColor";
|
|
|
6
6
|
import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry";
|
|
7
7
|
import { getCameraController } from "../engine/engine_camera";
|
|
8
8
|
import { Camera } from "./Camera";
|
|
9
|
-
import {
|
|
9
|
+
import { NeedleEngineHTMLElement } from "../engine/engine_element";
|
|
10
10
|
|
|
11
11
|
ContextRegistry.registerCallback(ContextEvent.MissingCamera, (evt) => {
|
|
12
12
|
const scene = evt.context.scene;
|
|
@@ -31,7 +31,7 @@ ContextRegistry.registerCallback(ContextEvent.ContextCreated, (evt) => {
|
|
|
31
31
|
if (!evt.context.mainCamera) return;
|
|
32
32
|
|
|
33
33
|
// check if the <needle-engine controls> is not set to false
|
|
34
|
-
const engineElement = evt.context.domElement as
|
|
34
|
+
const engineElement = evt.context.domElement as NeedleEngineHTMLElement
|
|
35
35
|
|
|
36
36
|
if (engineElement?.cameraControls === true) {
|
|
37
37
|
|
|
@@ -9,6 +9,7 @@ import { syncDestroy, syncInstantiate } from "../engine/engine_networking_instan
|
|
|
9
9
|
import { ConstructorConcrete, SourceIdentifier, IComponent, IGameObject, Constructor, GuidsMap, UIDProvider, Collision, ICollider } from "../engine/engine_types";
|
|
10
10
|
import { addNewComponent, destroyComponentInstance, findObjectOfType, findObjectsOfType, getComponent, getComponentInChildren, getComponentInParent, getComponents, getComponentsInChildren, getComponentsInParent, getOrAddComponent, moveComponentInstance, removeComponent } from "../engine/engine_components";
|
|
11
11
|
import { findByGuid, destroy, InstantiateOptions, instantiate, HideFlags, foreachComponent, markAsInstancedRendered, isActiveInHierarchy, isActiveSelf, isUsingInstancing, setActive, isDestroyed } from "../engine/engine_gameobject";
|
|
12
|
+
import { resolveUrl } from "../engine/engine_utils";
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
// export interface ISerializationCallbackReceiver {
|
|
@@ -641,7 +642,6 @@ class Component implements IComponent, EventTarget {
|
|
|
641
642
|
|
|
642
643
|
return false;
|
|
643
644
|
}
|
|
644
|
-
|
|
645
645
|
}
|
|
646
646
|
|
|
647
647
|
class Behaviour extends Component {
|
|
@@ -52,6 +52,7 @@ export class ParticleSystemRenderer extends Behaviour {
|
|
|
52
52
|
@serializable()
|
|
53
53
|
minParticleSize!: number;
|
|
54
54
|
|
|
55
|
+
|
|
55
56
|
start() {
|
|
56
57
|
if (this.maxParticleSize !== .5 && this.minParticleSize !== 0) {
|
|
57
58
|
if (isDevEnvironment()) {
|
|
@@ -192,6 +193,7 @@ class ParticleSystemEmissionOverTime extends BaseValueGenerator {
|
|
|
192
193
|
}
|
|
193
194
|
|
|
194
195
|
genValue(): number {
|
|
196
|
+
if (!this.system.isPlaying) return 0;
|
|
195
197
|
if (!this.system.emission.enabled) return 0;
|
|
196
198
|
if (this.system.currentParticles >= this.system.maxParticles) return 0;
|
|
197
199
|
// emission over time
|
|
@@ -219,6 +221,7 @@ class ParticleSystemEmissionOverTime extends BaseValueGenerator {
|
|
|
219
221
|
class ParticleSystemEmissionOverDistance extends BaseValueGenerator {
|
|
220
222
|
|
|
221
223
|
genValue(): number {
|
|
224
|
+
if (!this.system.isPlaying) return 0;
|
|
222
225
|
// this seems not be called yet
|
|
223
226
|
return 0;
|
|
224
227
|
// if (this.system.currentParticles >= this.system.maxParticles) return 0;
|
|
@@ -250,14 +253,19 @@ abstract class ParticleSystemBaseBehaviour implements Behavior {
|
|
|
250
253
|
clone(): Behavior { throw new Error("Method not implemented."); }
|
|
251
254
|
}
|
|
252
255
|
|
|
256
|
+
const $startFrame = Symbol("startFrame")
|
|
253
257
|
class TextureSheetAnimationBehaviour extends ParticleSystemBaseBehaviour {
|
|
254
258
|
type: string = "NeedleTextureSheet"
|
|
255
259
|
|
|
260
|
+
// initialize(_particle: Particle): void {
|
|
261
|
+
// _particle[$startFrame] = this.system.textureSheetAnimation.getStartIndex();
|
|
262
|
+
// }
|
|
263
|
+
|
|
256
264
|
update(particle: Particle, _delta: number) {
|
|
257
265
|
const sheet = this.system.textureSheetAnimation;
|
|
258
266
|
if (sheet.enabled) {
|
|
259
267
|
const t01 = particle.age / particle.life;
|
|
260
|
-
const index = sheet.evaluate(t01)
|
|
268
|
+
const index = sheet.evaluate(t01);
|
|
261
269
|
if (index !== undefined)
|
|
262
270
|
particle.uvTile = index;
|
|
263
271
|
}
|
|
@@ -325,8 +333,9 @@ class SizeBehaviour extends ParticleSystemBaseBehaviour {
|
|
|
325
333
|
size *= this.system.sizeOverLifetime.evaluate(age01, undefined, particle[$sizeLerpFactor]).x;
|
|
326
334
|
const scaleFactor = this.system.worldScale.x / this.system.cameraScale;
|
|
327
335
|
particle.size = particle.startSize * size * scaleFactor;
|
|
328
|
-
// in Unity this is viewport size
|
|
329
|
-
|
|
336
|
+
// in Unity this is viewport size, we don't really support this yet (and the renderer is logging a warning)
|
|
337
|
+
// so for now it's disabled again
|
|
338
|
+
// particle.size = Mathf.clamp(particle.size, this._minSize, this._maxSize);
|
|
330
339
|
}
|
|
331
340
|
}
|
|
332
341
|
}
|
|
@@ -378,6 +387,7 @@ class TrailBehaviour extends ParticleSystemBaseBehaviour {
|
|
|
378
387
|
|
|
379
388
|
const $startVelocity = Symbol("startVelocity");
|
|
380
389
|
const $gravityFactor = Symbol("gravityModifier");
|
|
390
|
+
const $gravitySpeed = Symbol("gravitySpeed");
|
|
381
391
|
const $velocityLerpFactor = Symbol("velocity lerp factor");
|
|
382
392
|
const temp3 = new Vector3();
|
|
383
393
|
const temp4 = new Quaternion();
|
|
@@ -401,6 +411,7 @@ class VelocityBehaviour extends ParticleSystemBaseBehaviour {
|
|
|
401
411
|
|
|
402
412
|
const gravityFactor = this.system.main.gravityModifier.evaluate(Math.random(), Math.random()) / (9.81 * 2);
|
|
403
413
|
particle[$gravityFactor] = gravityFactor * simulationSpeed;
|
|
414
|
+
particle[$gravitySpeed] = 1;
|
|
404
415
|
|
|
405
416
|
particle[$velocityLerpFactor] = Math.random();
|
|
406
417
|
|
|
@@ -417,7 +428,8 @@ class VelocityBehaviour extends ParticleSystemBaseBehaviour {
|
|
|
417
428
|
let gravityFactor = particle[$gravityFactor];
|
|
418
429
|
if (gravityFactor !== 0) {
|
|
419
430
|
// gravityFactor *= -1;
|
|
420
|
-
temp3.copy(this._gravityDirection).multiplyScalar(gravityFactor);
|
|
431
|
+
temp3.copy(this._gravityDirection).multiplyScalar(gravityFactor * particle[$gravitySpeed]);
|
|
432
|
+
particle[$gravitySpeed] += delta;
|
|
421
433
|
if (debug) Gizmos.DrawDirection(particle.position, temp3, 0x0000ff, 0, false, 10);
|
|
422
434
|
baseVelocity.add(temp3);
|
|
423
435
|
}
|
|
@@ -537,7 +549,7 @@ class ParticleSystemInterface implements ParticleSystemParameters {
|
|
|
537
549
|
}
|
|
538
550
|
switch (this.system.renderer.renderMode) {
|
|
539
551
|
case ParticleSystemRenderMode.Billboard: return RenderMode.BillBoard;
|
|
540
|
-
|
|
552
|
+
case ParticleSystemRenderMode.Stretch: return RenderMode.StretchedBillBoard;
|
|
541
553
|
case ParticleSystemRenderMode.HorizontalBillboard: return RenderMode.LocalSpace;
|
|
542
554
|
case ParticleSystemRenderMode.VerticalBillboard: return RenderMode.LocalSpace;
|
|
543
555
|
case ParticleSystemRenderMode.Mesh: return RenderMode.LocalSpace;
|
|
@@ -587,8 +599,8 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
|
|
|
587
599
|
}
|
|
588
600
|
}, true)
|
|
589
601
|
}
|
|
602
|
+
|
|
590
603
|
this._isPlaying = true;
|
|
591
|
-
this._time = 0;
|
|
592
604
|
|
|
593
605
|
// https://github.com/Alchemist0823/three.quarks/pull/35
|
|
594
606
|
if (this._particleSystem) {
|
|
@@ -598,12 +610,40 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
|
|
|
598
610
|
this.emission?.reset();
|
|
599
611
|
}
|
|
600
612
|
|
|
601
|
-
pause() {
|
|
613
|
+
pause(includeChildren = true) {
|
|
614
|
+
if (includeChildren) {
|
|
615
|
+
GameObject.foreachComponent(this.gameObject, comp => {
|
|
616
|
+
if (comp instanceof ParticleSystem && comp !== this) {
|
|
617
|
+
comp.pause(false);
|
|
618
|
+
}
|
|
619
|
+
}, true)
|
|
620
|
+
}
|
|
602
621
|
this._isPlaying = false;
|
|
603
622
|
}
|
|
604
|
-
|
|
623
|
+
|
|
624
|
+
/** clear=true removes all emitted particles */
|
|
625
|
+
stop(includeChildren = true, clear: boolean = false) {
|
|
626
|
+
if (includeChildren) {
|
|
627
|
+
GameObject.foreachComponent(this.gameObject, comp => {
|
|
628
|
+
if (comp instanceof ParticleSystem && comp !== this) {
|
|
629
|
+
comp.stop(false, clear);
|
|
630
|
+
}
|
|
631
|
+
}, true)
|
|
632
|
+
}
|
|
605
633
|
this._isPlaying = false;
|
|
606
634
|
this._time = 0;
|
|
635
|
+
if (clear) this.reset();
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/** remove emitted particles and reset time */
|
|
639
|
+
reset() {
|
|
640
|
+
this._time = 0;
|
|
641
|
+
if (this._particleSystem) {
|
|
642
|
+
this._particleSystem.particleNum = 0;
|
|
643
|
+
this._particleSystem["emissionState"].time = 0;
|
|
644
|
+
this._particleSystem["emitEnded"] = false;
|
|
645
|
+
this.emission?.reset();
|
|
646
|
+
}
|
|
607
647
|
}
|
|
608
648
|
|
|
609
649
|
private _state?: ParticlesEmissionState;
|
|
@@ -872,8 +912,10 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
|
|
|
872
912
|
console.log(`Particles ${this.name} - Prewarm for ${framesToSimulate} frames (${timeToSimulate} sec). Duration: ${duration}, Lifetime: ${lifetime}`);
|
|
873
913
|
for (let i = 0; i < framesToSimulate; i++) {
|
|
874
914
|
if (this.currentParticles >= this.maxParticles) break;
|
|
875
|
-
|
|
876
|
-
|
|
915
|
+
const timePassed = Date.now() - startTime;
|
|
916
|
+
if (timePassed > 2000) {
|
|
917
|
+
console.warn(`Particles ${this.name} - Prewarm took too long. Aborting: ${timePassed}`);
|
|
918
|
+
break;
|
|
877
919
|
}
|
|
878
920
|
this.onUpdate();
|
|
879
921
|
this.onSimulate(dt);
|