import { AssetManager } from './AssetManager';
import { Model, Object3D, Controller } from '@ud-viz/game_shared';
import { Howl } from 'howler';
import * as THREE from 'three';
/** @class */
export class AudioController extends Controller {
/**
* Audio component controller
*
* @param {Model} model - component model
* @param {Object3D} object3D - object3D of component
* @param {AssetManager} assetManager - asset manager
*/
constructor(model, object3D, assetManager) {
super(model, object3D);
/**
* asset manager
*
@type {AssetManager}*/
this.assetManager = assetManager;
/**
* sounds of controller
*
@type {Object<string,Howl>} */
this.sounds = {};
// initialize this.sounds with asset manager
this.model.getSoundsJSON().forEach((idS) => {
this.sounds[idS] = this.assetManager.createSound(
idS,
this.model.getConf()
);
});
}
/**
*
* @param {string} id - id of the sound to play
*/
play(id) {
this.sounds[id].play();
}
/**
*
* @returns {Object<string,Howl>} - sounds controller
*/
getSounds() {
return this.sounds;
}
/**
* Unload all Howl sounds
*/
dispose() {
for (const key in this.sounds) {
if (this.sounds[key]._state == 'loaded') {
this.sounds[key].unload();
}
delete this.sounds[key];
}
}
/**
* Tick controller
*
* @param {THREE.Matrix4} cameraMatrixWorldInverse - camera matrix world inverse
*/
tick(cameraMatrixWorldInverse) {
for (const key in this.sounds) {
const sound = this.sounds[key];
if (sound.state() != 'loaded') continue;
if (this.model.getConf().autoplay && !sound.playing()) sound.play();
if (!isNaN(this.model.getConf().volume))
sound.volume(this.model.getConf().volume);
// https://github.com/goldfire/howler.js#documentation
if (this.model.getConf().spatialized) {
const worldPosition = new THREE.Vector3();
this.object3D.matrixWorld.decompose(
worldPosition,
new THREE.Quaternion(),
new THREE.Vector3()
);
// in camera referential
const positionAudio = worldPosition.applyMatrix4(
cameraMatrixWorldInverse
);
sound.pos(positionAudio.x, positionAudio.y, positionAudio.z);
}
}
}
}