@woosh/meep-engine 2.48.1 → 2.48.5
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/package.json +1 -1
- package/src/core/binary/32BitEncoder.js +11 -3
- package/src/core/binary/BinaryBuffer.js +80 -59
- package/src/core/binary/int32_to_binary_string.js +32 -7
- package/src/core/binary/to_half_float_uint16.js +6 -4
- package/src/core/bvh2/visual/convert_bvh_to_dot_format_string.js +1 -1
- package/src/core/collection/list/List.js +3 -0
- package/src/core/geom/3d/CircleMath.js +13 -2
- package/src/core/geom/3d/matrix/m4_make_translation.js +15 -0
- package/src/core/geom/3d/triangle/computeTrianglePlaneSide.js +4 -13
- package/src/core/geom/Vector3.spec.js +10 -0
- package/src/core/graph/convertGraphToDotString.js +13 -3
- package/src/core/graph/v2/Graph.js +17 -1
- package/src/core/graph/v2/NodeContainer.js +58 -0
- package/src/core/model/ModuleRegistry.js +44 -10
- package/src/core/model/ResourceAccessKind.js +11 -0
- package/src/core/model/ResourceAccessSpecification.js +41 -0
- package/src/engine/Engine.js +1 -1
- package/src/engine/ecs/EntityEventBinding.js +74 -0
- package/src/engine/ecs/EntityManager.js +143 -0
- package/src/engine/ecs/System.js +53 -5
- package/src/engine/ecs/animation/InverseKinematicsSystem.js +6 -0
- package/src/engine/ecs/attachment/AttachmentSystem.js +8 -0
- package/src/engine/ecs/dynamic_actions/DynamicActorSystem.js +5 -0
- package/src/engine/ecs/fow/FogOfWarRevealerSystem.js +7 -3
- package/src/engine/ecs/fow/FogOfWarSystem.js +6 -0
- package/src/engine/ecs/gui/GUIElementSystem.js +1 -1
- package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +8 -0
- package/src/engine/ecs/gui/position/ViewportPositionSystem.js +6 -0
- package/src/engine/ecs/speaker/VoiceSystem.js +13 -0
- package/src/engine/ecs/storage/binary/object/BinaryObjectSerializationAdapter2.js +451 -12
- package/src/engine/ecs/storage/binary/object/BinaryObjectSerializationAdapter2.spec.js +123 -0
- package/src/engine/ecs/system/computeSystemComponentDependencyGraph.js +71 -0
- package/src/engine/ecs/systems/RenderSystem.js +6 -0
- package/src/engine/ecs/terrain/ecs/Terrain.js +26 -44
- package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +9 -0
- package/src/engine/ecs/terrain/tiles/TerrainTile.js +5 -0
- package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +26 -6
- package/src/engine/ecs/tooltip/TooltipComponentSystem.js +7 -0
- package/src/engine/graphics/ecs/animation/animator/AnimationGraphSystem.js +6 -0
- package/src/engine/graphics/ecs/camera/CameraSystem.js +6 -0
- package/src/engine/graphics/ecs/camera/pp/PerfectPanner.js +4 -0
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +5 -0
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraLanderSystem.js +6 -0
- package/src/engine/graphics/ecs/light/LightSystem.js +8 -0
- package/src/engine/graphics/ecs/mesh/MeshSystem.js +8 -1
- package/src/engine/graphics/ecs/path/PathDisplaySystem.js +7 -1
- package/src/engine/graphics/ecs/trail2d/Trail2DSystem.js +7 -0
- package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.js +34 -7
- package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.js +6 -0
- package/src/engine/grid/systems/GridPosition2TransformSystem.js +6 -0
- package/src/engine/grid/transform2grid/Transform2GridPositionSystem.js +6 -0
- package/src/engine/intelligence/behavior/Behavior.js +11 -0
- package/src/engine/intelligence/behavior/composite/CompositeBehavior.js +10 -4
- package/src/engine/intelligence/behavior/decorator/AbstractDecoratorBehavior.js +1 -0
- package/src/engine/intelligence/behavior/util/behavior_traverse_tree.js +8 -0
- package/src/engine/navigation/ecs/path_following/PathFollowingSystem.js +8 -0
- package/src/engine/network/RemoteController.js +60 -84
- package/src/engine/network/remoteEditor.js +108 -2
- package/src/engine/sound/SoundEngine.js +81 -79
- package/src/engine/sound/ecs/SoundControllerSystem.js +8 -0
- package/src/engine/sound/ecs/SoundListenerSystem.js +7 -0
- package/src/engine/sound/ecs/emitter/SoundEmitterComponentContext.js +42 -46
- package/src/engine/sound/ecs/emitter/SoundEmitterSystem.js +15 -2
- package/src/engine/sound/ecs/emitter/SoundTrack.js +137 -35
- package/src/engine/sound/ecs/emitter/SoundTrackFlags.js +17 -1
- package/src/engine/sound/ecs/emitter/SoundTrackNodes.js +2 -4
- package/src/engine/sound/ecs/emitter/loadSoundTrackAsset.js +1 -2
- package/src/generation/theme/ThemeEngine.js +20 -3
- package/src/view/{elements/image → common}/HTMLElementCacheKey.js +5 -5
- package/src/view/elements/button/ButtonView.js +10 -2
- package/src/view/elements/image/ImageView.js +1 -1
- package/src/view/elements/video/VideoView.js +1 -1
- package/src/view/interaction/CommandButtonView.js +16 -153
- package/src/view/interaction/createInterfaceCommandButton.js +124 -0
|
@@ -118,61 +118,21 @@ export class SoundEmitterComponentContext {
|
|
|
118
118
|
//connect to target
|
|
119
119
|
nodes.volume.connect(targetNode);
|
|
120
120
|
|
|
121
|
-
nodes.source.loop = soundTrack.getFlag(SoundTrackFlags.Loop);
|
|
122
121
|
nodes.volume.gain.setValueAtTime(soundTrack.volume, 0);
|
|
123
122
|
|
|
124
123
|
loadSoundTrackAsset(soundTrack, assetManager, function (asset) {
|
|
125
|
-
/**
|
|
126
|
-
*
|
|
127
|
-
* @type {AudioBuffer}
|
|
128
|
-
*/
|
|
129
|
-
const buffer = asset.create();
|
|
130
124
|
|
|
131
|
-
|
|
132
|
-
if (nodes.source.buffer !== buffer) {
|
|
133
|
-
nodes.source.buffer = buffer;
|
|
134
|
-
}
|
|
125
|
+
soundTrack.buffer = asset.create();
|
|
135
126
|
|
|
136
127
|
if (soundTrack.getFlag(SoundTrackFlags.StartWhenReady)) {
|
|
137
|
-
//TODO: figure out a way to use AudioBuffer.playbackRate.value to control speed of playback
|
|
138
|
-
|
|
139
|
-
if (soundTrack.time < 0) {
|
|
140
|
-
// playback will start in the future
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* @type {AudioContext}
|
|
144
|
-
*/
|
|
145
|
-
const audioContext = targetNode.context;
|
|
146
|
-
|
|
147
|
-
let when = -soundTrack.time;
|
|
148
|
-
|
|
149
|
-
if (audioContext !== undefined) {
|
|
150
|
-
when += audioContext.currentTime;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
nodes.source.start(when, 0);
|
|
154
|
-
} else {
|
|
155
|
-
// playback will start from within the track's duration (already playing)
|
|
156
128
|
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
soundTrack.setFlag(SoundTrackFlags.Playing);
|
|
129
|
+
soundTrack.start(context.currentTime);
|
|
161
130
|
}
|
|
162
131
|
|
|
163
|
-
}, console.error);
|
|
164
|
-
|
|
165
132
|
|
|
166
|
-
|
|
167
|
-
if (!nodes.source.loop) {
|
|
168
|
-
soundTrack.clearFlag(SoundTrackFlags.Playing);
|
|
169
|
-
|
|
170
|
-
soundTrack.on.ended.dispatch();
|
|
133
|
+
}, console.error);
|
|
171
134
|
|
|
172
|
-
|
|
173
|
-
emitter.tracks.removeOneOf(soundTrack);
|
|
174
|
-
}
|
|
175
|
-
};
|
|
135
|
+
soundTrack.on.ended.add(emitter.tracks.removeOneOf, emitter.tracks);
|
|
176
136
|
}
|
|
177
137
|
|
|
178
138
|
/**
|
|
@@ -187,6 +147,30 @@ export class SoundEmitterComponentContext {
|
|
|
187
147
|
const volume = track.nodes.volume;
|
|
188
148
|
|
|
189
149
|
volume.disconnect();
|
|
150
|
+
|
|
151
|
+
const emitter = this.emitter;
|
|
152
|
+
|
|
153
|
+
track.on.ended.remove(emitter.tracks.removeOneOf, emitter.tracks);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* @param {SoundTrack} t
|
|
158
|
+
*/
|
|
159
|
+
suspendTrack(t) {
|
|
160
|
+
if (t.getFlag(SoundTrackFlags.Playing)) {
|
|
161
|
+
t.suspend();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
*
|
|
167
|
+
* @param {SoundTrack} t
|
|
168
|
+
*/
|
|
169
|
+
resumeTrack(t) {
|
|
170
|
+
|
|
171
|
+
if (t.getFlag(SoundTrackFlags.Playing)) {
|
|
172
|
+
t.start();
|
|
173
|
+
}
|
|
190
174
|
}
|
|
191
175
|
|
|
192
176
|
connect() {
|
|
@@ -194,10 +178,14 @@ export class SoundEmitterComponentContext {
|
|
|
194
178
|
return;
|
|
195
179
|
}
|
|
196
180
|
|
|
197
|
-
const
|
|
181
|
+
const emitter = this.emitter;
|
|
182
|
+
const targetNode = emitter.getTargetNode();
|
|
198
183
|
|
|
199
184
|
targetNode.connect(this.targetNode);
|
|
200
185
|
|
|
186
|
+
// update all track times
|
|
187
|
+
emitter.tracks.forEach(this.resumeTrack);
|
|
188
|
+
|
|
201
189
|
this.__isConnected = true;
|
|
202
190
|
}
|
|
203
191
|
|
|
@@ -206,12 +194,20 @@ export class SoundEmitterComponentContext {
|
|
|
206
194
|
return;
|
|
207
195
|
}
|
|
208
196
|
|
|
209
|
-
const
|
|
197
|
+
const emitter = this.emitter;
|
|
198
|
+
const targetNode = emitter.getTargetNode();
|
|
210
199
|
|
|
211
200
|
if (targetNode !== null) {
|
|
212
201
|
targetNode.disconnect();
|
|
213
202
|
}
|
|
214
203
|
|
|
204
|
+
/*
|
|
205
|
+
The reason we suspend all tracks is to be able to track progression of a track after it is disconnected
|
|
206
|
+
From experiments it appears that at least on Chrome v111 disconnected sources do not advance time, which leads to dis-synchronization when we later reconnected
|
|
207
|
+
To circumvent this issue we introduced "Suspended" flag to keep track of timing on disconnected tracks
|
|
208
|
+
*/
|
|
209
|
+
emitter.tracks.forEach(this.suspendTrack, this)
|
|
210
|
+
|
|
215
211
|
this.__isConnected = false;
|
|
216
212
|
}
|
|
217
213
|
|
|
@@ -21,6 +21,7 @@ import { SoundEmitterFlags } from "./SoundEmitterFlags.js";
|
|
|
21
21
|
import { SoundEmitterChannel } from "./SoundEmitterChannel.js";
|
|
22
22
|
import { invokeObjectCompare } from "../../../../core/model/object/invokeObjectCompare.js";
|
|
23
23
|
import { tryRotateSingleNode } from "../../../../core/bvh2/transform/tryRotateSingleNode.js";
|
|
24
|
+
import { SoundTrackFlags } from "./SoundTrackFlags.js";
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* @readonly
|
|
@@ -88,7 +89,6 @@ export class SoundEmitterSystem extends System {
|
|
|
88
89
|
|
|
89
90
|
assetManager.registerLoader(GameAssetType.Sound, new SoundAssetLoader(context));
|
|
90
91
|
|
|
91
|
-
|
|
92
92
|
/**
|
|
93
93
|
*
|
|
94
94
|
* @type {SoundEmitterComponentContext[]}
|
|
@@ -352,7 +352,7 @@ export class SoundEmitterSystem extends System {
|
|
|
352
352
|
*/
|
|
353
353
|
const tracks = emitter.tracks;
|
|
354
354
|
|
|
355
|
-
|
|
355
|
+
let trackCount = tracks.length;
|
|
356
356
|
|
|
357
357
|
|
|
358
358
|
//update play time
|
|
@@ -360,6 +360,19 @@ export class SoundEmitterSystem extends System {
|
|
|
360
360
|
const soundTrack = tracks.get(i);
|
|
361
361
|
|
|
362
362
|
soundTrack.time += timeDelta;
|
|
363
|
+
|
|
364
|
+
if (
|
|
365
|
+
soundTrack.setFlag(SoundTrackFlags.Suspended | SoundTrackFlags.Playing)
|
|
366
|
+
&& !soundTrack.getFlag(SoundTrackFlags.Loop)
|
|
367
|
+
&& soundTrack.time > soundTrack.duration
|
|
368
|
+
) {
|
|
369
|
+
// track is suspended, but should have ended, trigger this state manually
|
|
370
|
+
emitter.endTrack(soundTrack);
|
|
371
|
+
|
|
372
|
+
// update cursors
|
|
373
|
+
trackCount--;
|
|
374
|
+
i--;
|
|
375
|
+
}
|
|
363
376
|
}
|
|
364
377
|
|
|
365
378
|
}
|
|
@@ -10,51 +10,149 @@ import { compareNumbers } from "../../../../core/primitives/numbers/compareNumbe
|
|
|
10
10
|
const DEFAULT_FLAGS = SoundTrackFlags.StartWhenReady;
|
|
11
11
|
|
|
12
12
|
export class SoundTrack {
|
|
13
|
+
|
|
13
14
|
/**
|
|
14
15
|
*
|
|
15
|
-
* @
|
|
16
|
+
* @type {AudioBuffer|null}
|
|
16
17
|
*/
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
*
|
|
20
|
-
* @type {String|null}
|
|
21
|
-
*/
|
|
22
|
-
this.url = null;
|
|
18
|
+
#buffer = null;
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
* @type {String|null}
|
|
23
|
+
*/
|
|
24
|
+
url = null;
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
/**
|
|
27
|
+
*
|
|
28
|
+
* @type {number}
|
|
29
|
+
*/
|
|
30
|
+
time = 0;
|
|
35
31
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated Not used
|
|
34
|
+
* @type {String|null}
|
|
35
|
+
*/
|
|
36
|
+
channel = "";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @private
|
|
40
|
+
* @type {number}
|
|
41
|
+
*/
|
|
42
|
+
__volume = 1;
|
|
41
43
|
|
|
44
|
+
/**
|
|
45
|
+
* In seconds
|
|
46
|
+
* Obtained once clip is loaded
|
|
47
|
+
* @type {number}
|
|
48
|
+
*/
|
|
49
|
+
duration = -1;
|
|
42
50
|
|
|
43
|
-
/**
|
|
44
|
-
*
|
|
45
|
-
* @type {number|SoundTrackFlags}
|
|
46
|
-
*/
|
|
47
|
-
this.flags = DEFAULT_FLAGS;
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
* @type {number|SoundTrackFlags}
|
|
55
|
+
*/
|
|
56
|
+
flags = DEFAULT_FLAGS;
|
|
52
57
|
|
|
58
|
+
on = {
|
|
53
59
|
/**
|
|
54
|
-
* @
|
|
55
|
-
* @type {SoundTrackNodes}
|
|
60
|
+
* @type {Signal<this>}
|
|
56
61
|
*/
|
|
57
|
-
|
|
62
|
+
ended: new Signal()
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @private
|
|
67
|
+
* @type {SoundTrackNodes}
|
|
68
|
+
*/
|
|
69
|
+
nodes = null;
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
*
|
|
74
|
+
* @param {AudioBuffer} v
|
|
75
|
+
*/
|
|
76
|
+
set buffer(v) {
|
|
77
|
+
this.#buffer = v;
|
|
78
|
+
|
|
79
|
+
this.duration = v.duration;
|
|
80
|
+
|
|
81
|
+
this.setFlag(SoundTrackFlags.Ready);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get buffer() {
|
|
85
|
+
return this.#buffer;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
*
|
|
90
|
+
* @returns {BaseAudioContext}
|
|
91
|
+
*/
|
|
92
|
+
get #context() {
|
|
93
|
+
return this.nodes.volume.context;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
start(startTime = 0) {
|
|
97
|
+
//TODO: figure out a way to use AudioBuffer.playbackRate.value to control speed of playback
|
|
98
|
+
const nodes = this.nodes;
|
|
99
|
+
|
|
100
|
+
if (nodes.source !== null) {
|
|
101
|
+
|
|
102
|
+
/*
|
|
103
|
+
source is already used up, need to create a new one
|
|
104
|
+
NOTE: AudioBufferSourceNode can only be used once, if we want to start playback again - we have to create a new one
|
|
105
|
+
see https://stackoverflow.com/questions/59815825/how-to-skip-ahead-n-seconds-while-playing-track-using-web-audio-api
|
|
106
|
+
*/
|
|
107
|
+
this.suspend();
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
nodes.source = this.#context.createBufferSource();
|
|
112
|
+
|
|
113
|
+
//connect source to output
|
|
114
|
+
nodes.source.connect(nodes.volume);
|
|
115
|
+
|
|
116
|
+
const looping = this.getFlag(SoundTrackFlags.Loop);
|
|
117
|
+
|
|
118
|
+
nodes.source.loop = looping;
|
|
119
|
+
|
|
120
|
+
// Make the sound source use the buffer and start playing it.
|
|
121
|
+
nodes.source.buffer = this.#buffer;
|
|
122
|
+
|
|
123
|
+
nodes.source.onended = ()=> {
|
|
124
|
+
if(!looping){
|
|
125
|
+
this.clearFlag(SoundTrackFlags.Playing);
|
|
126
|
+
this.on.ended.send1(this);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let when = startTime;
|
|
131
|
+
|
|
132
|
+
if (this.time < 0) {
|
|
133
|
+
// playback will start in the future
|
|
134
|
+
when = -this.time;
|
|
135
|
+
|
|
136
|
+
nodes.source.start(when, 0);
|
|
137
|
+
} else {
|
|
138
|
+
// playback will start from within the track's duration (already playing)
|
|
139
|
+
|
|
140
|
+
nodes.source.start(when, this.time);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
this.setFlag(SoundTrackFlags.Playing);
|
|
144
|
+
this.clearFlag(SoundTrackFlags.Suspended);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
suspend() {
|
|
148
|
+
const nodes = this.nodes;
|
|
149
|
+
|
|
150
|
+
nodes.source.stop();
|
|
151
|
+
nodes.source.disconnect();
|
|
152
|
+
|
|
153
|
+
nodes.source = null;
|
|
154
|
+
|
|
155
|
+
this.setFlag(SoundTrackFlags.Suspended);
|
|
58
156
|
}
|
|
59
157
|
|
|
60
158
|
/**
|
|
@@ -310,7 +408,8 @@ export class SoundTrack {
|
|
|
310
408
|
volume: this.volume,
|
|
311
409
|
playing: this.getFlag(SoundTrackFlags.Playing),
|
|
312
410
|
startWhenReady: this.getFlag(SoundTrackFlags.StartWhenReady),
|
|
313
|
-
usingAssetAlias: this.getFlag(SoundTrackFlags.UsingAliasURL)
|
|
411
|
+
usingAssetAlias: this.getFlag(SoundTrackFlags.UsingAliasURL),
|
|
412
|
+
synchronized: this.getFlag(SoundTrackFlags.Synchronized)
|
|
314
413
|
};
|
|
315
414
|
}
|
|
316
415
|
|
|
@@ -322,7 +421,8 @@ export class SoundTrack {
|
|
|
322
421
|
volume = 1,
|
|
323
422
|
playing = false,
|
|
324
423
|
startWhenReady = true,
|
|
325
|
-
usingAssetAlias = false
|
|
424
|
+
usingAssetAlias = false,
|
|
425
|
+
synchronized = false
|
|
326
426
|
}
|
|
327
427
|
) {
|
|
328
428
|
assert.typeOf(url, 'string', 'url');
|
|
@@ -340,6 +440,8 @@ export class SoundTrack {
|
|
|
340
440
|
this.writeFlag(SoundTrackFlags.Playing, playing);
|
|
341
441
|
|
|
342
442
|
this.writeFlag(SoundTrackFlags.StartWhenReady, startWhenReady);
|
|
443
|
+
|
|
444
|
+
this.writeFlag(SoundTrackFlags.Synchronized, synchronized);
|
|
343
445
|
}
|
|
344
446
|
|
|
345
447
|
static fromJSON(json) {
|
|
@@ -9,5 +9,21 @@ export const SoundTrackFlags = {
|
|
|
9
9
|
/**
|
|
10
10
|
* URL field is not a path to actual resource, but instead an alias that needs to be resolved
|
|
11
11
|
*/
|
|
12
|
-
UsingAliasURL: 8
|
|
12
|
+
UsingAliasURL: 8,
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* If set, this flag will result in track being scheduled instead of starting immediately, this will result in pore precise time synchronization
|
|
16
|
+
* as a trade-off, there will be a delay until next system update tick
|
|
17
|
+
*/
|
|
18
|
+
Synchronized: 16,
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Track is not actually playing, only time is being advanced
|
|
22
|
+
*/
|
|
23
|
+
Suspended: 32,
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Track is loaded and ready to play
|
|
27
|
+
*/
|
|
28
|
+
Ready: 64
|
|
13
29
|
};
|
|
@@ -8,13 +8,11 @@ export class SoundTrackNodes {
|
|
|
8
8
|
*
|
|
9
9
|
* @type {AudioBufferSourceNode}
|
|
10
10
|
*/
|
|
11
|
-
this.source =
|
|
11
|
+
this.source = null;
|
|
12
12
|
/**
|
|
13
13
|
*
|
|
14
14
|
* @type {GainNode}
|
|
15
15
|
*/
|
|
16
16
|
this.volume = context.createGain();
|
|
17
|
-
//connect volume to source
|
|
18
|
-
this.source.connect(this.volume);
|
|
19
17
|
}
|
|
20
|
-
}
|
|
18
|
+
}
|
|
@@ -4,10 +4,9 @@ import { noop } from "../../../../core/function/Functions.js";
|
|
|
4
4
|
import { assert } from "../../../../core/assert.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
7
|
* @param {SoundTrack} track
|
|
9
8
|
* @param {AssetManager} assetManager
|
|
10
|
-
* @param {function} [resolve]
|
|
9
|
+
* @param {function(Asset<AudioBuffer>)} [resolve]
|
|
11
10
|
* @param {function} [reject]
|
|
12
11
|
*/
|
|
13
12
|
export function loadSoundTrackAsset(track, assetManager, resolve = noop, reject = noop) {
|
|
@@ -366,7 +366,7 @@ export class ThemeEngine {
|
|
|
366
366
|
* @param {number} seed
|
|
367
367
|
* @returns {Task|TaskGroup}
|
|
368
368
|
*/
|
|
369
|
-
applyNodes(grid, ecd, seed=0) {
|
|
369
|
+
applyNodes(grid, ecd, seed = 0) {
|
|
370
370
|
/**
|
|
371
371
|
*
|
|
372
372
|
* @type {MarkerNode[]}
|
|
@@ -579,10 +579,27 @@ export class ThemeEngine {
|
|
|
579
579
|
// build terrain tiles
|
|
580
580
|
const tTerrainGeometry = futureTask(new Future((resolve, reject) => {
|
|
581
581
|
|
|
582
|
-
terrain.
|
|
582
|
+
const is_linked = terrain.getFlag(TerrainFlags.Linked);
|
|
583
|
+
|
|
584
|
+
if (!is_linked) {
|
|
585
|
+
terrain.startBuildService();
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
if (!terrain.getFlag(TerrainFlags.Built)) {
|
|
589
|
+
terrain.buildNonVisual();
|
|
590
|
+
}
|
|
591
|
+
|
|
583
592
|
terrain.__tiles.rebuild();
|
|
584
593
|
|
|
585
|
-
terrain.promiseAllTiles()
|
|
594
|
+
terrain.promiseAllTiles()
|
|
595
|
+
.then(resolve, reject)
|
|
596
|
+
.finally(() => {
|
|
597
|
+
if (!is_linked && !terrain.getFlag(TerrainFlags.Linked)) {
|
|
598
|
+
// cleanup after ourselves
|
|
599
|
+
terrain.stopBuildService();
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
|
|
586
603
|
}), 'Wait for terrain tiles');
|
|
587
604
|
|
|
588
605
|
const tInitializeThemes = this.initializeThemes(this.random(), ecd, grid);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { KeyValuePair } from "
|
|
2
|
-
import { computeStringHash } from "
|
|
3
|
-
import { computeHashArray } from "
|
|
4
|
-
import { computeHashIntegerArray } from "
|
|
5
|
-
import { isArrayEqual } from "
|
|
1
|
+
import { KeyValuePair } from "../../core/collection/KeyValuePair.js";
|
|
2
|
+
import { computeStringHash } from "../../core/primitives/strings/computeStringHash.js";
|
|
3
|
+
import { computeHashArray } from "../../core/collection/array/computeHashArray.js";
|
|
4
|
+
import { computeHashIntegerArray } from "../../core/collection/array/computeHashIntegerArray.js";
|
|
5
|
+
import { isArrayEqual } from "../../core/collection/array/isArrayEqual.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
*
|
|
@@ -10,6 +10,7 @@ import domify from "../../DOM.js";
|
|
|
10
10
|
class ButtonView extends View {
|
|
11
11
|
/**
|
|
12
12
|
*
|
|
13
|
+
* @param {string} [tag]
|
|
13
14
|
* @param {function} action
|
|
14
15
|
* @param {string|ObservedString} [name]
|
|
15
16
|
* @param {string} [icon] URL
|
|
@@ -17,14 +18,21 @@ class ButtonView extends View {
|
|
|
17
18
|
* @param {object} [css]
|
|
18
19
|
* @constructor
|
|
19
20
|
*/
|
|
20
|
-
constructor({
|
|
21
|
+
constructor({
|
|
22
|
+
tag = 'div',
|
|
23
|
+
action,
|
|
24
|
+
name,
|
|
25
|
+
icon = undefined,
|
|
26
|
+
classList = [],
|
|
27
|
+
css
|
|
28
|
+
}) {
|
|
21
29
|
super();
|
|
22
30
|
|
|
23
31
|
if (typeof action !== "function") {
|
|
24
32
|
throw new Error("Action must be a function");
|
|
25
33
|
}
|
|
26
34
|
|
|
27
|
-
const dRoot = domify();
|
|
35
|
+
const dRoot = domify(tag);
|
|
28
36
|
|
|
29
37
|
this.el = dRoot.el;
|
|
30
38
|
//add background and foreground elements for styling purposes
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import View from "../../View.js";
|
|
6
6
|
import { noop } from "../../../core/function/Functions.js";
|
|
7
|
-
import { HTMLElementCacheKey } from "
|
|
7
|
+
import { HTMLElementCacheKey } from "../../common/HTMLElementCacheKey.js";
|
|
8
8
|
import { KeyValuePair } from "../../../core/collection/KeyValuePair.js";
|
|
9
9
|
import { ObjectPoolFactory } from "../../../core/model/object/ObjectPoolFactory.js";
|
|
10
10
|
import { ImmutableObjectPool } from "../../../core/model/object/ImmutableObjectPool.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HTMLElementCacheKey } from "
|
|
1
|
+
import { HTMLElementCacheKey } from "../../common/HTMLElementCacheKey.js";
|
|
2
2
|
import { KeyValuePair } from "../../../core/collection/KeyValuePair.js";
|
|
3
3
|
import { Cache } from "../../../core/cache/Cache.js";
|
|
4
4
|
import { noop } from "../../../core/function/Functions.js";
|