import { AssetManager, RenderData } from './AssetManager';
import { Model, Controller, Object3D } from '@ud-viz/game_shared';
import * as THREE from 'three';
export class RenderController extends Controller {
/**
* Render component controller
*
* @param {Model} model - model of component controller
* @param {Object3D} object3D - object3D of controller
* @param {AssetManager} assetManager - asset manager
*/
constructor(model, object3D, assetManager) {
super(model, object3D);
/** @type {AssetManager}*/
this.assetManager = assetManager;
/**
* animation mixer only instanciated if there is animations in render data
*
@type {THREE.AnimationMixer|null} */
this.animationMixer = null;
/** @type {RenderData} */
this.renderData = null;
/** @type {THREE.AnimationMixer} */
this.animationMixer = null;
this.setIdRenderData(this.model.idRenderData);
// update color
this.setColor(this.model.getColor());
}
dispose() {
this.renderData.dispose();
}
setIdRenderData(idRenderData) {
// change model
this.model.idRenderData = idRenderData;
// remove old one
if (this.renderData) {
this.renderData.dispose();
this.renderData = null;
}
if (this.model.idRenderData) {
this.renderData = this.assetManager.createRenderData(
this.model.idRenderData
);
const animations = this.renderData.animations;
if (animations && animations.length) {
this.animationMixer = new THREE.AnimationMixer(
this.renderData.object3D
);
animations.forEach((animClip) => {
const action = this.animationMixer.clipAction(animClip);
action.play(); // Play action is default behaviour
});
}
} else {
this.renderData = new RenderData(new THREE.Object3D());
}
// register in parent
this.object3D.add(this.renderData.object3D);
this.renderData.object3D.name = 'RENDER_OBJECT_3D_' + this.object3D.name;
this.setColor(this.model.color); // update color
}
/**
* Add object 3D
*
* @param {THREE.Object3D} obj - object3D to add
*/
addObject3D(obj) {
this.renderData.object3D.add(obj);
this.setColor(this.model.getColor());
}
/**
*
* @returns {THREE.Object3D} - object3D controller
*/
getObject3D() {
return this.renderData.object3D;
}
/**
*
* @param {Array<number>} color - new value color controller rgba
*/
setColor(color) {
if (color.length != 4) throw new Error('color format should be rgba');
const alpha = color[3];
// only change color
this.model.setColor(color);
// update color in the controller attributes
const threeColor = new THREE.Color().fromArray(color);
this.renderData.object3D.traverse((child) => {
if (child.material) {
child.material.color = threeColor;
if (alpha < 1) {
// handle opacity
child.material.opacity = alpha;
child.material.transparent = true;
child.renderOrder = 1;
} else {
child.material.transparent = false;
}
child.material.needsUpdate = true;
}
});
}
/**
*
* @param {number} dt - delta time to update animations
*/
tick(dt) {
if (this.animationMixer) {
this.animationMixer.update(dt * 0.001);
}
}
}