import DomlessGlimmerComponent from 'ember-ecsy-babylon/components/domless-glimmer';
import { assert } from '@ember/debug';
import BabylonCore from 'ecsy-babylon/components/babylon-core';
import {
EcsyBabylonContext,
EcsyBabylonDomlessGlimmerArgs,
} from 'ember-ecsy-babylon/components/ecsy-babylon';
import { Color3 } from '@babylonjs/core/Maths/math.color';
import { CubeTexture } from '@babylonjs/core/Materials/Textures/cubeTexture';
import { HDRCubeTexture } from '@babylonjs/core/Materials/Textures/hdrCubeTexture';
import { Matrix } from '@babylonjs/core/Maths/math.vector';
import { Scene } from '@babylonjs/core/scene';
export interface EcsyBabylonSceneArgs extends EcsyBabylonDomlessGlimmerArgs {
clearColor?: Color3;
ambientColor?: Color3;
environmentTexture?: string;
environmentRotation?: number;
}
export default class EcsyBabylonScene extends DomlessGlimmerComponent<
EcsyBabylonContext,
EcsyBabylonSceneArgs
> {
scene: Scene;
constructor(owner: unknown, args: EcsyBabylonSceneArgs) {
super(owner, args);
const { environmentTexture, environmentRotation, ...restArgs } = args;
assert('No ECSY context found.', this.context);
const { world, rootEntity } = this.context!;
assert(
'EcsyBabylon entity not found. Make sure to use the yielded version of ',
!!rootEntity
);
assert(
'EcsyBabylon world not found. Make sure to use the yielded version of ',
!!world
);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const core = rootEntity.getComponent(BabylonCore);
assert('BabylonCore could not be found', !!core);
assert('BabylonCore does not contain a scene', !!core!.scene);
this.scene = core!.scene;
Object.assign(this.scene, restArgs);
this.updateEnvironmentTexture(environmentTexture);
this.rotateEnvironmentTexture(environmentRotation);
}
didUpdate(changedArgs: Partial) {
super.didUpdate(changedArgs);
const { environmentTexture, environmentRotation, ...restArgs } =
changedArgs;
if (Object.keys(restArgs).length) {
Object.assign(this.scene, changedArgs);
}
if (environmentTexture) {
this.updateEnvironmentTexture(environmentTexture);
}
if (environmentRotation) {
this.rotateEnvironmentTexture(environmentRotation);
}
}
updateEnvironmentTexture(environmentTexture?: string) {
const oldTexture = this.scene.environmentTexture;
this.scene.environmentTexture = environmentTexture
? new CubeTexture(environmentTexture, this.scene)
: null;
if (oldTexture) {
oldTexture.dispose();
}
}
rotateEnvironmentTexture(angle = 0) {
const texture = this.scene.environmentTexture;
if (
texture &&
(texture instanceof CubeTexture || texture instanceof HDRCubeTexture)
) {
texture.setReflectionTextureMatrix(Matrix.RotationY(angle));
}
}
willDestroy() {
if (this.scene.environmentTexture) {
this.scene.environmentTexture.dispose();
this.scene.environmentTexture = null;
}
super.willDestroy();
}
}