@makefully/platypus 4.1.5 → 4.1.8

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 (136) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +3 -3
  3. package/lib/platypus.js +1 -1
  4. package/package.json +7 -6
  5. package/src/AABB.js +685 -0
  6. package/src/ActionState.js +121 -0
  7. package/src/AssetManager.js +206 -0
  8. package/src/CollisionData.js +96 -0
  9. package/src/CollisionDataContainer.js +127 -0
  10. package/src/CollisionShape.js +315 -0
  11. package/src/Component.js +231 -0
  12. package/src/Data.js +64 -0
  13. package/src/DataMap.js +204 -0
  14. package/src/Entity.js +404 -0
  15. package/src/EntityLinker.js +113 -0
  16. package/src/EventHandler.js +115 -0
  17. package/src/EventHandlerList.js +251 -0
  18. package/src/Game.js +840 -0
  19. package/src/Gamepad.js +175 -0
  20. package/src/ID3CaptionPlayer.js +61 -0
  21. package/src/Messenger.js +365 -0
  22. package/src/PIXIAnimation.js +622 -0
  23. package/src/RandomSet.js +140 -0
  24. package/src/SFXPlayer.js +120 -0
  25. package/src/StateMap.js +252 -0
  26. package/src/Storage.js +152 -0
  27. package/src/TickerClient.js +48 -0
  28. package/src/TickerServer.js +23 -0
  29. package/src/TimeEvent.js +50 -0
  30. package/src/TimeEventList.js +100 -0
  31. package/src/VOPlayer.js +684 -0
  32. package/src/Vector.js +702 -0
  33. package/src/components/AIChaser.js +161 -0
  34. package/src/components/AIPacer.js +107 -0
  35. package/src/components/AudioMusic.js +151 -0
  36. package/src/components/AudioSFX.js +673 -0
  37. package/src/components/AudioVO.js +301 -0
  38. package/src/components/CollisionBasic.js +826 -0
  39. package/src/components/CollisionFilter.js +74 -0
  40. package/src/components/CollisionGroup.js +448 -0
  41. package/src/components/CollisionTiles.js +608 -0
  42. package/src/components/ComponentSwitcher.js +173 -0
  43. package/src/components/ControllerInput.js +65 -0
  44. package/src/components/Counter.js +165 -0
  45. package/src/components/EntityCamera.js +215 -0
  46. package/src/components/EntityContainer.js +549 -0
  47. package/src/components/EntityController.js +541 -0
  48. package/src/components/HandlerCamera.js +1052 -0
  49. package/src/components/HandlerCollision.js +1318 -0
  50. package/src/components/HandlerController.js +291 -0
  51. package/src/components/HandlerLogic.js +394 -0
  52. package/src/components/HandlerRender.js +217 -0
  53. package/src/components/Interactive.js +502 -0
  54. package/src/components/LevelBuilder.js +524 -0
  55. package/src/components/LogicAngularMovement.js +154 -0
  56. package/src/components/LogicAttachment.js +265 -0
  57. package/src/components/LogicButton.js +466 -0
  58. package/src/components/LogicCarrier.js +39 -0
  59. package/src/components/LogicDestroyMe.js +58 -0
  60. package/src/components/LogicDirectionalMovement.js +325 -0
  61. package/src/components/LogicDragDrop.js +371 -0
  62. package/src/components/LogicImpactLaunch.js +144 -0
  63. package/src/components/LogicPacingPlatform.js +64 -0
  64. package/src/components/LogicPortable.js +112 -0
  65. package/src/components/LogicPortal.js +115 -0
  66. package/src/components/LogicPushable.js +98 -0
  67. package/src/components/LogicRebounder.js +136 -0
  68. package/src/components/LogicRegionSpawner.js +139 -0
  69. package/src/components/LogicRotationalMovement.js +205 -0
  70. package/src/components/LogicSpawner.js +159 -0
  71. package/src/components/LogicStateMachine.js +382 -0
  72. package/src/components/LogicSwitch.js +77 -0
  73. package/src/components/LogicTeleportee.js +68 -0
  74. package/src/components/LogicTeleporter.js +93 -0
  75. package/src/components/LogicTimer.js +178 -0
  76. package/src/components/LogicWindUpRacer.js +179 -0
  77. package/src/components/Motion.js +371 -0
  78. package/src/components/Mover.js +566 -0
  79. package/src/components/Node.js +289 -0
  80. package/src/components/NodeMap.js +295 -0
  81. package/src/components/NodeResident.js +636 -0
  82. package/src/components/Orientation.js +697 -0
  83. package/src/components/RandomEvents.js +73 -0
  84. package/src/components/RelativePosition.js +204 -0
  85. package/src/components/RelayFamily.js +106 -0
  86. package/src/components/RelayGame.js +53 -0
  87. package/src/components/RelayLinker.js +94 -0
  88. package/src/components/RelayParent.js +57 -0
  89. package/src/components/RelaySelf.js +55 -0
  90. package/src/components/Render.js +178 -0
  91. package/src/components/RenderAnimator.js +275 -0
  92. package/src/components/RenderContainer.js +646 -0
  93. package/src/components/RenderDebug.js +319 -0
  94. package/src/components/RenderDestroyMe.js +59 -0
  95. package/src/components/RenderLottie.js +149 -0
  96. package/src/components/RenderProgress.js +120 -0
  97. package/src/components/RenderSpine.js +840 -0
  98. package/src/components/RenderSprite.js +527 -0
  99. package/src/components/RenderText.js +147 -0
  100. package/src/components/RenderTiles.js +1440 -0
  101. package/src/components/SceneChanger.js +128 -0
  102. package/src/components/TiledLoader.js +1459 -0
  103. package/src/components/Timeline.js +314 -0
  104. package/src/components/Tutorial.js +267 -0
  105. package/src/components/Tween.js +296 -0
  106. package/src/components/VoiceOver.js +373 -0
  107. package/src/components/XHR.js +129 -0
  108. package/src/components/index.js +79 -0
  109. package/src/factory.js +305 -0
  110. package/src/index.js +159 -0
  111. package/src/mixins/PIXI.Graphics.js +41 -0
  112. package/src/platypus.css +68 -0
  113. package/src/sayHello.js +50 -0
  114. package/src/shapes/Capsule.js +74 -0
  115. package/src/shapes/Circle.js +43 -0
  116. package/src/shapes/Ellipse.js +117 -0
  117. package/src/shapes/Point.js +191 -0
  118. package/src/shapes/Polygon.js +112 -0
  119. package/src/shapes/Polyline.js +97 -0
  120. package/src/shapes/Rectangle.js +78 -0
  121. package/src/shapes/RoundedRectangle.js +33 -0
  122. package/src/shapes/Segment.js +346 -0
  123. package/src/shapes/adjustedXY.js +19 -0
  124. package/src/shapes/castFromBox2D.js +92 -0
  125. package/src/shapes/castFromObject.js +53 -0
  126. package/src/shapes/castFromPixiGraphics.js +6 -0
  127. package/src/shapes/castFromPixiShape.js +89 -0
  128. package/src/shapes/castToBox2D.js +190 -0
  129. package/src/shapes/castToPixiGraphics.js +100 -0
  130. package/src/shapes/castToPixiShape.js +61 -0
  131. package/src/shapes/checkPointsMap.js +313 -0
  132. package/src/shapes/index.js +35 -0
  133. package/src/utils/array.js +73 -0
  134. package/src/utils/string.js +39 -0
  135. package/lib/243.platypus.mjs +0 -1
  136. package/lib/platypus.mjs +0 -1
@@ -0,0 +1,673 @@
1
+ /* global platypus */
2
+ import {arrayCache, greenSplice} from '../utils/array.js';
3
+ import Data from '../Data.js';
4
+ import {Sound} from '@pixi/sound';
5
+ import StateMap from '../StateMap.js';
6
+ import createComponentClass from '../factory.js';
7
+
8
+ const
9
+ formatPath = (path) => {
10
+ if (path.indexOf('.mp3') === -1) {
11
+ return `${path}.mp3`;
12
+ } else {
13
+ return path;
14
+ }
15
+ },
16
+ defaultSettings = {
17
+ interrupt: 0,
18
+ delay: 0,
19
+ start: 0,
20
+ loop: 0,
21
+ volume: 1,
22
+ pan: 0,
23
+ muted: false,
24
+ speed: 1,
25
+ playthrough: false
26
+ },
27
+ playSound = function (soundDefinition) {
28
+ let sound = '',
29
+ attributes = null;
30
+
31
+ if (typeof soundDefinition === 'string') {
32
+ sound = soundDefinition;
33
+ attributes = {};
34
+ } else {
35
+ sound = soundDefinition.sound;
36
+ attributes = {
37
+ ...soundDefinition
38
+ };
39
+ delete attributes.sound;
40
+ }
41
+
42
+ sound = platypus.assetCache.getFileId(sound);
43
+
44
+ return function (value) {
45
+ const
46
+ soundInstance = platypus.assetCache.get(sound),
47
+ data = Data.setUp({
48
+ ...defaultSettings,
49
+ ...attributes,
50
+ ...value
51
+ });
52
+
53
+ if (!soundInstance) {
54
+ platypus.debug.warn(`The sound "${sound}" is not a loaded asset.`);
55
+ } else {
56
+ data.volume *= this.volume;
57
+ if (data.loop && typeof data.loop === 'number') { // pixi sound doesn't handle loop counts.
58
+ if (data.loop > 1) {
59
+ data.loopCount = data.loop;
60
+ }
61
+ data.loop = data.loop > 1 || data.loop < 0;
62
+ }
63
+
64
+ if (data.pan) {
65
+ if (soundInstance.panFilter) {
66
+ soundInstance.panFilter.pan = data.pan;
67
+ } else {
68
+ soundInstance.panFilter = new Sound.filters.StereoFilter(data.pan);
69
+ }
70
+ }
71
+ if (soundInstance.panFilter || this.autoPanFilter) {
72
+ const
73
+ filters = [];
74
+
75
+ if (soundInstance.panFilter) {
76
+ filters.push(soundInstance.panFilter);
77
+ }
78
+ if (this.autoPanFilter) {
79
+ filters.push(this.autoPanFilter);
80
+ }
81
+ soundInstance.filters = filters;
82
+ }
83
+ data.audio = this.player.play(soundInstance, data);
84
+ //if (data.volume) {
85
+ // data.audio.volume = data.volume;
86
+ //}
87
+ if (data.speed) {
88
+ data.audio.speed = data.speed;
89
+ }
90
+ if (data.playthrough && !data.loop) {
91
+ data.audio.playthrough = true;
92
+ } else {
93
+ data.audio.playthrough = false;
94
+ }
95
+ if (data.loopCount) {
96
+ let p = -1;
97
+
98
+ data.audio.on('progress', (progress) => {
99
+ if (progress < p) {
100
+ console.log('LOOPED?', data.loopCount--);
101
+ if (data.loopCount === 1) {
102
+ data.audio.set('loop', false);
103
+ }
104
+ }
105
+ p = progress;
106
+ });
107
+ }
108
+ data.audio.on('end', () => {
109
+ if (data.audio && !this.owner.destroyed && this.activeAudioClips) {
110
+ //clean up active clips
111
+ this.removeClip(data.audio);
112
+
113
+ /**
114
+ * When a sound effect is finished playing, this event is triggered.
115
+ *
116
+ * @event platypus.Entity#clip-complete
117
+ */
118
+ this.owner.triggerEvent('clip-complete');
119
+ }
120
+ data.recycle();
121
+ });
122
+
123
+ data.audio.soundId = sound;
124
+ this.activeAudioClips.push(data.audio);
125
+
126
+ if (data.audio.playState === 'playFailed') {
127
+ // Let's try again - maybe it was a loading issue.
128
+ const
129
+ wait = function (event) {
130
+ if (event.id === sound) {
131
+ data.audio.play(data);
132
+ Sound.off('fileload', wait);
133
+ }
134
+ };
135
+
136
+ Sound.on('fileload', wait);
137
+ }
138
+ }
139
+ };
140
+ };
141
+
142
+ export default createComponentClass(/** @lends platypus.components.AudioSFX.prototype */{
143
+ id: 'AudioSFX',
144
+
145
+ properties: {
146
+ /**
147
+ * Use the audioMap property object to map messages triggered with audio clips to play. At least one audio mapping should be included for audio to play. Here is an example audioMap object:
148
+ *
149
+ * {
150
+ * "message-triggered": "audio-id",
151
+ * // This simple form is useful to listen for "message-triggered" and play "audio-id" using default audio properties.
152
+ *
153
+ * "another-message": {
154
+ * // To specify audio properties, instead of mapping the message to an audio id string, map it to an object with one or more of the properties shown below. Many of these properties directly correspond to SoundJS play parameters.
155
+ *
156
+ * "sound": "another-audio-id",
157
+ * // Required. This is the audio clip to play when "another-message" is triggered.
158
+ *
159
+ * "interrupt": "none",
160
+ * // Optional. Can be "any", "early", "late", or "none". Determines how to handle the audio when it's already playing but a new play request is received. Default is "any".
161
+ *
162
+ * "delay": 500,
163
+ * // Optional. Time in milliseconds to wait before playing audio once the message is received. Default is 0.
164
+ *
165
+ * "start": 1.5,
166
+ * // Optional. Time in seconds determining where in the audio clip to begin playback. Default is 0.
167
+ *
168
+ * "length": 2500,
169
+ * // Optional. Time in milliseconds to play audio before stopping it. If 0 or not specified, play continues to the end of the audio clip.
170
+ *
171
+ * "loop": 4,
172
+ * // Optional. Determines how many more times to play the audio clip once it finishes. Set to -1 for an infinite loop. Default is 0.
173
+ *
174
+ * "muted": false,
175
+ * // Whether clip should start muted.
176
+ *
177
+ * "volume": 0.75,
178
+ * // Optional. Used to specify how loud to play audio on a range from 0 (mute) to 1 (full volume). Default is 1.
179
+ *
180
+ * "speed": 0.75,
181
+ * // Optional. Used to specify how fast to play audio. Default is 1 (100% speed).
182
+ *
183
+ * "pan": -0.25,
184
+ * // Optional. Used to specify the pan of audio on a range of -1 (left) to 1 (right). Default is 0.
185
+ *
186
+ * "playthrough": false
187
+ * // Whether SFX should force completion of sound even when stopped prematurely.
188
+ * }
189
+ * }
190
+ *
191
+ * @property audioMap
192
+ * @type Object
193
+ * @default null
194
+ */
195
+ audioMap: null,
196
+
197
+ /**
198
+ * Sets whether this component should track camera position to affect its playback.
199
+ *
200
+ * If set to `true`, will use default values. Otherwise specify as shown below:
201
+ *
202
+ * {
203
+ * "minimum": 0, // Minimum volume
204
+ * "maximum": 1, // Maximum volume
205
+ * "range": cameraWidth, // Distance from pan -1 to pan 0 and pan 0 to pan 1
206
+ * "buffer": 0 // Distance on each side of entity before panning should begin.
207
+ * }
208
+ *
209
+ * @property autoPan
210
+ * @type boolean|Object
211
+ * @default false
212
+ */
213
+ autoPan: false,
214
+
215
+ /**
216
+ * Determines whether a sound that's started should play through completely regardless of entity state changes.
217
+ *
218
+ * @property forcePlayThrough
219
+ * @type boolean
220
+ * @default true
221
+ */
222
+ forcePlayThrough: true,
223
+
224
+ /**
225
+ * Optional. Specifies whether this component should listen to events matching the animationMap to animate. Set this to true if the component should animate for on events.
226
+ *
227
+ * @property eventBased
228
+ * @type Boolean
229
+ * @default true
230
+ */
231
+ eventBased: true,
232
+
233
+ /**
234
+ * Optional. Specifies whether this component should listen to changes in the entity's state that match the animationMap to animate. Set this to true if the component should animate based on this.owner.state.
235
+ *
236
+ * @property stateBased
237
+ * @type Boolean
238
+ * @default false
239
+ */
240
+ stateBased: false
241
+ },
242
+
243
+ /**
244
+ * This component plays audio using the SpringRoll Sound instance. Audio is played in one of two ways, by triggering specific messages defined in the audio component definition or using an audio map which plays sounds when the entity enters specified states.
245
+ *
246
+ * @memberof platypus.components
247
+ * @uses platypus.Component
248
+ * @constructs
249
+ * @listens platypus.Entity#camera-update
250
+ * @listens platypus.Entity#handle-render
251
+ * @listens platypus.Entity#mute-audio
252
+ * @listens platypus.Entity#pause-audio
253
+ * @listens platypus.Entity#set-pan
254
+ * @listens platypus.Entity#set-volume
255
+ * @listens platypus.Entity#set-speed
256
+ * @listens platypus.Entity#state-changed
257
+ * @listens platypus.Entity#stop-audio
258
+ * @listens platypus.Entity#toggle-mute
259
+ * @listens platypus.Entity#unmute-audio
260
+ * @listens platypus.Entity#unpause-audio
261
+ * @fires platypus.Entity#clip-complete
262
+ * @fires platypus.Entity#set-volume
263
+ */
264
+ initialize: function () {
265
+ const
266
+ audioMap = this.audioMap;
267
+
268
+ this.activeAudioClips = arrayCache.setUp();
269
+
270
+ this.state = this.owner.state;
271
+ this.stateChange = false;
272
+
273
+ this.player = platypus.game.sfxPlayer;
274
+
275
+ this.volume = 1;
276
+
277
+ if (audioMap) {
278
+ const
279
+ keys = Object.keys(audioMap),
280
+ {length} = keys;
281
+
282
+ if (this.stateBased) {
283
+ this.checkStates = arrayCache.setUp();
284
+ }
285
+
286
+ for (let i = 0; i < length; i++) {
287
+ const
288
+ key = keys[i],
289
+ sound = audioMap[key],
290
+ playClip = playSound(sound);
291
+
292
+ if (this.eventBased) {
293
+ this.addEventListener(key, playClip);
294
+ }
295
+ if (this.stateBased) {
296
+ this.addStateCheck(key, sound.sound ?? sound, playClip);
297
+ }
298
+ }
299
+ }
300
+
301
+ if (this.autoPan) {
302
+ const
303
+ autoPan = {
304
+ "minimum": this.autoPan.minimum || 0,
305
+ "maximum": this.autoPan.maximum || 1,
306
+ "range": this.autoPan.range || -1,
307
+ "buffer": this.autoPan.buffer || 0
308
+ };
309
+ let lastPan = 0;
310
+
311
+ this.volume = autoPan.maximum;
312
+
313
+ this.autoPanFilter = new Sound.filters.StereoFilter(lastPan);
314
+
315
+ this.addEventListener("camera-update", function (camera) {
316
+ const
317
+ delta = this.owner.x - camera.viewport.x,
318
+ distance = Math.abs(delta),
319
+ direction = delta / distance,
320
+ range = autoPan.range === -1 ? camera.viewport.width : autoPan.range;
321
+ let pan = 0,
322
+ volume = 1;
323
+
324
+ if (distance <= autoPan.buffer) {
325
+ pan = 0;
326
+ volume = autoPan.maximum;
327
+ } else if (distance > autoPan.buffer + range) {
328
+ pan = direction;
329
+ volume = Math.max(autoPan.minimum, Math.min(autoPan.maximum, (autoPan.buffer + range * 2 - distance) / range));
330
+ } else {
331
+ pan = direction * (distance - autoPan.buffer) / range;
332
+ volume = autoPan.maximum;
333
+ }
334
+
335
+ if (pan !== lastPan) {
336
+ this.autoPanFilter.pan = pan;
337
+ lastPan = pan;
338
+ }
339
+ if (volume !== this.volume) {
340
+ /**
341
+ * This message sets the volume of playing audio.
342
+ *
343
+ * @event platypus.Entity#set-volume
344
+ * @param volume {Number} A number from 0 to 1 that sets the volume.
345
+ * @param [soundId] {String} If an soundId is provided, that particular sound instance's volume is set. Otherwise all audio volume is changed.
346
+ */
347
+ this.owner.triggerEvent('set-volume', volume);
348
+ }
349
+ });
350
+ }
351
+
352
+ this.paused = false;
353
+ },
354
+
355
+ events: {
356
+ "handle-render": function () {
357
+ const
358
+ state = this.state;
359
+
360
+ if (this.paused) {
361
+ return;
362
+ }
363
+
364
+ if (this.stateBased && this.stateChange) {
365
+ const
366
+ cs = this.checkStates;
367
+ let i = cs.length;
368
+
369
+ while (i--) {
370
+ cs[i].check(state);
371
+ }
372
+ this.stateChange = false;
373
+ }
374
+ },
375
+
376
+ "state-changed": function () {
377
+ this.stateChange = true;
378
+ },
379
+
380
+ /**
381
+ * On receiving this message, the audio will mute if unmuted, and unmute if muted.
382
+ *
383
+ * @event platypus.Entity#toggle-mute
384
+ * @param audioId {String} If an audioId is provided, that particular sound instance is toggled. Otherwise all audio is toggled from mute to unmute or vice versa.
385
+ */
386
+ "toggle-mute": function (audioId) {
387
+ this.handleClip(audioId, function (clip) {
388
+ if (clip) {
389
+ if (clip.unmuted) {
390
+ clip.volume = clip.unmuted;
391
+ delete clip.unmuted;
392
+ } else {
393
+ clip.unmuted = clip.volume;
394
+ clip.volume = 0;
395
+ }
396
+ }
397
+ });
398
+ },
399
+
400
+ "stop-audio": function (audioId) {
401
+ if (!audioId) {
402
+ this.stopAudio();
403
+ } else if (typeof audioId === 'string') {
404
+ this.stopAudio(audioId);
405
+ } else {
406
+ this.stopAudio(audioId.audioId || false, audioId.playthrough || false);
407
+ }
408
+ },
409
+
410
+ /**
411
+ * On receiving this message all audio will mute, or a particular sound instance will mute if an id is specified.
412
+ *
413
+ * @event platypus.Entity#mute-audio
414
+ * @param audioId {String} If an audioId is provided, that particular sound instance will mute. Otherwise all audio is muted.
415
+ */
416
+ "mute-audio": function (audioId) {
417
+ this.handleClip(audioId, function (clip) {
418
+ if (clip) {
419
+ clip.unmuted = clip.volume;
420
+ clip.volume = 0;
421
+ }
422
+ });
423
+ },
424
+
425
+ /**
426
+ * On receiving this message all audio will unmute, or a particular sound instance will unmute if an id is specified.
427
+ *
428
+ * @event platypus.Entity#unmute-audio
429
+ * @param audioId {String} If an audioId is provided, that particular sound instance will unmute. Otherwise all audio is unmuted.
430
+ */
431
+ "unmute-audio": function (audioId) {
432
+ this.handleClip(audioId, function (clip) {
433
+ if (clip) {
434
+ clip.volume = clip.unmuted;
435
+ delete clip.unmuted;
436
+ }
437
+ });
438
+ },
439
+
440
+ /**
441
+ * On receiving this message all audio will pause, or a particular sound instance will pause if an id is specified.
442
+ *
443
+ * @event platypus.Entity#pause-audio
444
+ * @param audioId {String} If an audioId is provided, that particular sound instance will pause. Otherwise all audio is paused.
445
+ */
446
+ "pause-audio": function (audioId) {
447
+ this.handleClip(audioId, function (clip) {
448
+ if (clip) {
449
+ clip.pause();
450
+ }
451
+ });
452
+ },
453
+
454
+ /**
455
+ * On receiving this message all audio will unpause, or a particular sound instance will unpause if an id is specified.
456
+ *
457
+ * @event platypus.Entity#unpause-audio
458
+ * @param audioId {String} If an audioId is provided, that particular sound instance will unpause. Otherwise all audio is unpaused.
459
+ */
460
+ "unpause-audio": function (audioId) {
461
+ this.handleClip(audioId, function (clip) {
462
+ if (clip) {
463
+ clip.unpause();
464
+ }
465
+ });
466
+ },
467
+
468
+ /**
469
+ * This message sets the pan of playing audio.
470
+ *
471
+ * @event platypus.Entity#set-pan
472
+ * @param pan {Number} A number from -1 to 1 that sets the pan.
473
+ * @param [soundId] {String} If an soundId is provided, that particular sound instance's pan is set.
474
+ */
475
+ "set-pan": function (pan, soundId = '') {
476
+ const
477
+ handler = (clip) => {
478
+ if (clip) {
479
+ clip.pan = pan;
480
+ }
481
+ };
482
+
483
+ if (soundId) {
484
+ this.handleClip(soundId, handler);
485
+ } else {
486
+ this.getAllClips(handler);
487
+ }
488
+ },
489
+
490
+ "set-volume": function (volume, soundId = '') {
491
+ const
492
+ handler = (clip) => {
493
+ if (clip) {
494
+ clip.volume = volume * this.player.volume;
495
+ }
496
+ };
497
+
498
+ if (soundId) {
499
+ this.handleClip(soundId, handler);
500
+ } else {
501
+ this.volume = volume;
502
+ this.getAllClips(handler);
503
+ }
504
+ },
505
+
506
+ /**
507
+ * This message sets the speed of playing audio.
508
+ *
509
+ * @event platypus.Entity#set-speed
510
+ * @param speed {Number} A number that sets the speed.
511
+ * @param [soundId] {String} If an soundId is provided, that particular sound instance's speed is set. Otherwise all audio speed is changed.
512
+ */
513
+ "set-speed": function (speed, soundId = '') {
514
+ const
515
+ handler = function (clip) {
516
+ if (clip) {
517
+ clip.speed = speed;
518
+ }
519
+ };
520
+
521
+ if (soundId) {
522
+ this.handleClip(soundId, handler);
523
+ } else {
524
+ this.getAllClips(handler);
525
+ }
526
+ }
527
+ },
528
+
529
+ methods: {
530
+ handleClip: function (audioId, handler) {
531
+ if (typeof audioId === 'string') {
532
+ this.getClipById(audioId, handler);
533
+ } else {
534
+ this.getAllClips(handler);
535
+ }
536
+ },
537
+
538
+ getClipById: function (id, onGet = () => {}) {
539
+ const
540
+ clips = this.activeAudioClips;
541
+
542
+ for (let i = 0; i < clips.length; i++) {
543
+ if (clips[i].soundId === id) {
544
+ onGet(clips[i]);
545
+ return clips[i];
546
+ }
547
+ }
548
+
549
+ onGet(null);
550
+
551
+ return null;
552
+ },
553
+
554
+ getAllClips: function (onGet = () => {}) {
555
+ const
556
+ clips = this.activeAudioClips;
557
+
558
+ for (let i = 0; i < clips.length; i++) {
559
+ onGet(clips[i]);
560
+ }
561
+
562
+ return clips;
563
+ },
564
+
565
+ stopAudio: function (audioId, playthrough) {
566
+ const
567
+ clips = this.activeAudioClips;
568
+ let i = clips.length;
569
+
570
+ if (audioId) {
571
+ while (i--) {
572
+ if (clips[i].soundId === audioId) {
573
+ if (clips[i].playthrough ?? playthrough) {
574
+ } else {
575
+ this.player.stop(clips[i]);
576
+ greenSplice(clips, i);
577
+ }
578
+ }
579
+ }
580
+ } else {
581
+ while (i--) {
582
+ if (clips[i].playthrough ?? playthrough) {
583
+ } else {
584
+ this.player.stop(clips[i]);
585
+ }
586
+ }
587
+ clips.length = 0;
588
+ }
589
+ },
590
+
591
+ removeClip: function (audioClip) {
592
+ const
593
+ i = this.activeAudioClips.indexOf(audioClip);
594
+
595
+ if (i >= 0) {
596
+ greenSplice(this.activeAudioClips, i);
597
+ }
598
+ },
599
+
600
+ addStateCheck: function (key, audioId, play) {
601
+ const
602
+ states = StateMap.setUp(key),
603
+ checkData = Data.setUp(
604
+ "states", states,
605
+ "playing", false
606
+ );
607
+
608
+ checkData.check = (state) => {
609
+ const
610
+ active = state.includes(checkData.states);
611
+
612
+ if (active !== checkData.playing) {
613
+ if (active) {
614
+ play.call(this);
615
+ } else {
616
+ this.stopAudio(audioId, this.forcePlaythrough);
617
+ }
618
+ checkData.playing = active;
619
+ }
620
+ };
621
+ this.checkStates.push(checkData);
622
+ },
623
+
624
+ destroy: function () {
625
+ const
626
+ c = this.checkStates;
627
+
628
+ this.stopAudio();
629
+ arrayCache.recycle(this.activeAudioClips);
630
+ this.activeAudioClips = null;
631
+
632
+ this.state = null;
633
+
634
+ if (c) {
635
+ let i = c.length;
636
+
637
+ while (i--) {
638
+ const
639
+ ci = c[i];
640
+
641
+ ci.states.recycle();
642
+ ci.recycle();
643
+ }
644
+ arrayCache.recycle(c);
645
+ this.checkStates = null;
646
+ }
647
+ }
648
+ },
649
+
650
+ getAssetList: function (component, props, defaultProps) {
651
+ const
652
+ preload = arrayCache.setUp(),
653
+ audioMap = component?.audioMap ?? props?.audioMap ?? defaultProps?.audioMap;
654
+
655
+ if (audioMap) {
656
+ const
657
+ keys = Object.keys(audioMap),
658
+ {length} = keys;
659
+
660
+ for (let i = 0; i < length; i++) {
661
+ const
662
+ audio = audioMap[keys[i]],
663
+ item = formatPath(audio.sound ?? audio);
664
+
665
+ if (preload.indexOf(item) === -1) {
666
+ preload.push(item);
667
+ }
668
+ }
669
+ }
670
+
671
+ return preload;
672
+ }
673
+ });