@needle-tools/engine 2.67.15-pre → 2.67.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/needle-engine.js +3605 -3574
  3. package/dist/needle-engine.min.js +76 -76
  4. package/dist/needle-engine.umd.cjs +74 -74
  5. package/lib/engine-components/postprocessing/Effects/DepthOfField.d.ts +1 -0
  6. package/lib/engine-components/postprocessing/Effects/DepthOfField.js +15 -1
  7. package/lib/engine-components/postprocessing/Effects/DepthOfField.js.map +1 -1
  8. package/lib/engine-components/postprocessing/VolumeParameter.d.ts +1 -0
  9. package/lib/engine-components/postprocessing/VolumeParameter.js +4 -0
  10. package/lib/engine-components/postprocessing/VolumeParameter.js.map +1 -1
  11. package/lib/engine-components/timeline/PlayableDirector.d.ts +3 -1
  12. package/lib/engine-components/timeline/PlayableDirector.js +21 -2
  13. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  14. package/lib/engine-components/timeline/TimelineTracks.d.ts +1 -0
  15. package/lib/engine-components/timeline/TimelineTracks.js +9 -1
  16. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  17. package/lib/engine-components/ui/Text.js +0 -1
  18. package/lib/engine-components/ui/Text.js.map +1 -1
  19. package/lib/tsconfig.tsbuildinfo +1 -1
  20. package/package.json +1 -1
  21. package/plugins/generate-font.js +1 -1
  22. package/src/engine/codegen/register_types.js +2 -2
  23. package/src/engine-components/postprocessing/Effects/DepthOfField.ts +18 -6
  24. package/src/engine-components/postprocessing/VolumeParameter.ts +5 -0
  25. package/src/engine-components/timeline/PlayableDirector.ts +19 -2
  26. package/src/engine-components/timeline/TimelineTracks.ts +9 -2
  27. package/src/engine-components/ui/Text.ts +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/engine",
3
- "version": "2.67.15-pre",
3
+ "version": "2.67.16",
4
4
  "description": "Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development, and can be deployed anywhere. It is flexible, extensible, and collaboration and XR come naturally.",
5
5
  "main": "dist/needle-engine.umd.cjs",
6
6
  "module": "lib/needle-engine.js",
@@ -60,7 +60,7 @@ generateBMFont(fontPath, opts,
60
60
  });
61
61
 
62
62
  const fileName = path.parse(font.filename).name;
63
- const name = outputDir + "/" + fileName.toLocaleLowerCase() + "-msdf.json";
63
+ const name = outputDir + "/" + fileName + "-msdf.json";
64
64
  fs.writeFile(name, font.data, (err) => {
65
65
  if (err) throw err;
66
66
  });
@@ -1,5 +1,5 @@
1
1
  import { TypeStore } from "./../engine_typestore"
2
-
2
+
3
3
  // Import types
4
4
  import { __Ignore } from "../../engine-components/codegen/components";
5
5
  import { AlignmentConstraint } from "../../engine-components/AlignmentConstraint";
@@ -179,7 +179,7 @@ import { XRGrabModel } from "../../engine-components/WebXRGrabRendering";
179
179
  import { XRGrabRendering } from "../../engine-components/WebXRGrabRendering";
180
180
  import { XRRig } from "../../engine-components/WebXRRig";
181
181
  import { XRState } from "../../engine-components/XRFlag";
182
-
182
+
183
183
  // Register types
184
184
  TypeStore.add("__Ignore", __Ignore);
185
185
  TypeStore.add("AlignmentConstraint", AlignmentConstraint);
@@ -1,11 +1,10 @@
1
1
  import { DepthOfFieldEffect } from "postprocessing";
2
- import { PerspectiveCamera, Vector3 } from "three";
3
- import { getWorldPosition } from "../../../engine/engine_three_utils";
4
2
  import { serializable } from "../../../engine/engine_serialization";
5
3
  import { Mathf } from "../../../engine/engine_math";
6
4
  import { PostProcessingEffect } from "../PostProcessingEffect";
7
5
  import { VolumeParameter } from "../VolumeParameter";
8
6
  import { registerCustomEffectType } from "../VolumeProfile";
7
+ import { isMobileDevice } from "../../../engine/engine_utils";
9
8
 
10
9
  export enum DepthOfFieldMode {
11
10
  Off = 0,
@@ -20,7 +19,7 @@ export class DepthOfField extends PostProcessingEffect {
20
19
  }
21
20
 
22
21
  @serializable()
23
- mode! : DepthOfFieldMode;
22
+ mode!: DepthOfFieldMode;
24
23
 
25
24
  @serializable(VolumeParameter)
26
25
  focusDistance!: VolumeParameter;
@@ -34,13 +33,16 @@ export class DepthOfField extends PostProcessingEffect {
34
33
  @serializable(VolumeParameter)
35
34
  gaussianMaxRadius!: VolumeParameter;
36
35
 
36
+ @serializable(VolumeParameter)
37
+ resolutionScale?: VolumeParameter;
38
+
37
39
  init() {
38
40
  this.focalLength.valueProcessor = v => {
39
41
  const t = v / 300;
40
42
  const max = 2;// this.context.mainCameraComponent?.farClipPlane ?? 10;
41
43
  return Mathf.lerp(max, .01, t);
42
44
  };
43
-
45
+
44
46
  const maxBokehScale = 20;
45
47
  this.aperture.valueProcessor = v => {
46
48
  const t = 1 - v / 32;
@@ -49,7 +51,16 @@ export class DepthOfField extends PostProcessingEffect {
49
51
  }
50
52
 
51
53
  onCreateEffect() {
52
- if(this.mode === DepthOfFieldMode.Off) return undefined;
54
+ if (this.mode === DepthOfFieldMode.Off) return undefined;
55
+
56
+ const factor = 1 / window.devicePixelRatio;
57
+
58
+ if (this.resolutionScale === undefined) {
59
+ let defaultValue = 1;
60
+ if(isMobileDevice()) defaultValue = .6;
61
+ this.resolutionScale = new VolumeParameter(defaultValue * factor);
62
+ }
63
+
53
64
  // console.log(this.focusDistance.overrideState, this.focusDistance.value);
54
65
  // const depth = new DepthEffect({
55
66
  // inverted: true,
@@ -59,7 +70,7 @@ export class DepthOfField extends PostProcessingEffect {
59
70
  worldFocusRange: .2,
60
71
  focalLength: 1,
61
72
  bokehScale: 20,
62
- resolutionScale: 1,
73
+ resolutionScale: this.resolutionScale.value,
63
74
  });
64
75
 
65
76
  this.focusDistance.onValueChanged = v => {
@@ -68,6 +79,7 @@ export class DepthOfField extends PostProcessingEffect {
68
79
  this.focalLength.onValueChanged = v => dof.circleOfConfusionMaterial.worldFocusRange = v;
69
80
  this.aperture.onValueChanged = v => dof.bokehScale = v;
70
81
 
82
+ if (this.resolutionScale) this.resolutionScale.onValueChanged = v => dof.resolution.scale = v;
71
83
 
72
84
  return [dof];
73
85
  }
@@ -5,6 +5,11 @@ export declare type VolumeParameterValueProcessor = (value: any) => any;
5
5
 
6
6
  export class VolumeParameter {
7
7
 
8
+ constructor(value?: any) {
9
+ this._value = value;
10
+ this._defaultValue = value;
11
+ }
12
+
8
13
  @serializable()
9
14
  get overrideState(): boolean {
10
15
  return this._active;
@@ -6,7 +6,7 @@ import { AudioSource } from '../AudioSource';
6
6
  import { SignalReceiver } from './SignalAsset';
7
7
  import * as Models from "./TimelineModels";
8
8
  import * as Tracks from "./TimelineTracks";
9
- import { deepClone, getParam } from '../../engine/engine_utils';
9
+ import { deepClone, delay, getParam } from '../../engine/engine_utils';
10
10
  import { GuidsMap } from '../../engine/engine_types';
11
11
  import { Object3D } from 'three';
12
12
  import { isLocalNetwork } from '../../engine/engine_networking_utils';
@@ -87,6 +87,8 @@ export class PlayableDirector extends Behaviour {
87
87
  get speed(): number { return this._speed; }
88
88
  set speed(value: number) { this._speed = value; }
89
89
 
90
+ /** When enabled the timeline will wait for audio tracks to load at the current time before starting to play */
91
+ waitForAudio: boolean = true;
90
92
 
91
93
  private _visibilityChangeEvt?: any;
92
94
  private _clonedPlayableAsset: boolean = false;
@@ -151,13 +153,28 @@ export class PlayableDirector extends Behaviour {
151
153
  this.setupAndCreateTrackHandlers();
152
154
  }
153
155
 
154
- play() {
156
+ async play() {
155
157
  if (!this.isValid()) return;
156
158
  const pauseChanged = this._isPaused == true;
157
159
  this._isPaused = false;
158
160
  if (pauseChanged) this.invokePauseChangedMethodsOnTracks();
159
161
  if (this._isPlaying) return;
160
162
  this._isPlaying = true;
163
+ if (this.waitForAudio) {
164
+ // Make sure audio tracks have loaded at the current time
165
+ const promises: Array<Promise<any>> = [];
166
+ for (const track of this._audioTracks) {
167
+ const promise = track.loadAudio(this._time, 1, 0);
168
+ if (promise)
169
+ promises.push(promise);
170
+ }
171
+ if (promises.length > 0) {
172
+ await Promise.all(promises);
173
+ if (!this._isPlaying) return;
174
+ }
175
+ while(this._audioTracks.length > 0 && this._isPlaying && !AudioSource.userInteractionRegistered && this.waitForAudio)
176
+ await delay(200);
177
+ }
161
178
  this._internalUpdateRoutine = this.startCoroutine(this.internalUpdate());
162
179
  }
163
180
 
@@ -657,6 +657,9 @@ export class AudioTrackHandler extends TrackHandler {
657
657
  }
658
658
 
659
659
  private static _currentlyLoading: Map<string, Promise<AudioBuffer | null>> = new Map();
660
+ public static dispose() {
661
+ AudioTrackHandler._currentlyLoading.clear();
662
+ }
660
663
 
661
664
  private handleAudioLoading(model: Models.ClipModel, audio: THREE.Audio): Promise<AudioBuffer | null> | null {
662
665
  if (!this._audioLoader) {
@@ -665,8 +668,12 @@ export class AudioTrackHandler extends TrackHandler {
665
668
  // TODO: maybe we should cache the loaders / buffers here by path
666
669
  const path = this.getAudioFilePath(model.asset.clip);
667
670
 
668
- if(AudioTrackHandler._currentlyLoading.get(path)) {
669
- return AudioTrackHandler._currentlyLoading.get(path)!;
671
+ if (AudioTrackHandler._currentlyLoading.get(path)) {
672
+ const promise = AudioTrackHandler._currentlyLoading.get(path)!
673
+ promise.then((buffer) => {
674
+ if (buffer) audio.setBuffer(buffer);
675
+ });
676
+ return promise;
670
677
  }
671
678
 
672
679
  if (debug) console.warn("LOAD audio track", path, this.director.sourceId);
@@ -176,7 +176,6 @@ export class Text extends Graphic {
176
176
  fontSize: fontSize,
177
177
  fontKerning: "normal",
178
178
  };
179
- this.font = this.font?.toLocaleLowerCase();
180
179
  this.setFont(textOpts, this.fontStyle);
181
180
  return textOpts;
182
181
  }