Skip to content

Commit

Permalink
refactor: align Looder & world scenes models
Browse files Browse the repository at this point in the history
  • Loading branch information
Neosoulink committed Dec 26, 2023
1 parent 59d5d6e commit 23cc6a4
Show file tree
Hide file tree
Showing 11 changed files with 764 additions and 386 deletions.
131 changes: 99 additions & 32 deletions src/experiences/blueprints/Scene.blueprint.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,57 @@
import { Group, type CatmullRomCurve3, Mesh } from "three";
import {
Group,
type CatmullRomCurve3,
Mesh,
Object3D,
type Object3DEventMap,
Material,
} from "three";
import type { GLTF } from "three/examples/jsm/loaders/GLTFLoader";
import EventEmitter from "events";

// EXPERIENCES
import HomeExperience from "@/experiences/pages/Home";

// EVENTS
import { CONSTRUCTED, DESTRUCTED, LOADED } from "../common/Event.model";

// ERRORS
import { ErrorFactory } from "../errors/Error.factory";
import { WRONG_PARAM } from "../common/error.model";

// INTERFACES
import { type ExperienceBase } from "@interfaces/experienceBase";
import { LOADED } from "../common/Event.model";
import type {
Materials,
ModelChildrenMaterials,
} from "~/interfaces/experienceWorld";

// TODO: Link with the names of assets in the `app.loader` assets names
export interface ModelChildrenTextures {
childName: string;
linkedTextureName: string;
}

export interface SceneBlueprintProps {
cameraPath: CatmullRomCurve3;
modelName: string;
modelChildrenTextures: ModelChildrenTextures[];
childrenMaterials: ModelChildrenMaterials;
onTraverseModelScene?: (child: Object3D<Object3DEventMap>) => unknown;
}

export abstract class SceneBlueprint
extends EventEmitter
implements ExperienceBase
{
/**
* Called each time the model scene is traversed.
*
* @param child Model scene child
*/
private _onTraverseModelScene?: SceneBlueprintProps["onTraverseModelScene"];

protected readonly _experience = new HomeExperience();
protected readonly _appCamera = this._experience.app.camera;
protected readonly _Loader = this._experience.loader;
protected readonly _modelMeshes: { [name: string]: Mesh | undefined } = {};
protected readonly _loader = this._experience.loader;
protected readonly _childrenMaterials: ModelChildrenMaterials;

protected _modelChildrenTextures: ModelChildrenTextures[];
protected _world = this._experience.world;
protected _availableMaterials: Materials = {};
protected _model?: GLTF;

public modelScene?: Group;
Expand All @@ -39,39 +60,85 @@ export abstract class SceneBlueprint
constructor(_: SceneBlueprintProps) {
super();
this.cameraPath = _.cameraPath;
this._modelChildrenTextures = _.modelChildrenTextures;

this._childrenMaterials = _.childrenMaterials;

this._experience.loader?.on(LOADED, () => {
const _MODEL = this._experience.app.resources.items[_.modelName] as
| GLTF
| undefined;
if (_MODEL?.scene) this._model = _MODEL;
});

this._onTraverseModelScene = _.onTraverseModelScene;
}

public abstract construct(): unknown;
public abstract destruct(): unknown;
public abstract update(): unknown;
public abstract intro(): unknown;
public abstract outro(): unknown;
/** Protected method that serve to set scene textures. */
protected _setModelMaterials() {
const TEXTURES_MESH_BASIC_MATERIALS =
this._Loader?.texturesMeshBasicMaterials;
protected abstract _getAvailableMaterials(): Materials;

/**
* Initialize the model scene
*
* > 🚧 Must be called before other initializers.
*/
protected _initModelScene() {
this.modelScene = this._model?.scene.clone();
}

if (!TEXTURES_MESH_BASIC_MATERIALS) return;
/**
* Initialize model materials
*
* > 🚧 Must be called after `{@link SceneBlueprintProps.modelScene}` has been initialized.
*/
protected _initModelMaterials() {
if (!Object.keys(this._availableMaterials).length) return;

this.modelScene?.traverse((child) => {
this._modelChildrenTextures?.forEach((item) => {
const CHILD_TEXTURE =
TEXTURES_MESH_BASIC_MATERIALS[item.linkedTextureName];
if (
child instanceof Mesh &&
child.name === item.childName &&
CHILD_TEXTURE
)
~(child.material = CHILD_TEXTURE.clone());
});
this._onTraverseModelScene && this._onTraverseModelScene(child);

if (
!this._childrenMaterials[child.name] ||
!(
this._availableMaterials[
this._childrenMaterials[child.name]
] instanceof Material
) ||
!(child instanceof Mesh)
)
return;

~(child.material =
this._availableMaterials[this._childrenMaterials[child.name]]);
});
}

public construct(callback?: () => void) {
this._world = this._experience.world;
this._initModelScene();

if (!this.modelScene)
throw new ErrorFactory(
new Error("No model scene founded", { cause: WRONG_PARAM })
);

if (typeof callback === "function") callback();

this._availableMaterials = {
...this._world?.commonMaterials,
...this._getAvailableMaterials(),
};
this._initModelMaterials();
this.emit(CONSTRUCTED);
}

public destruct() {
this.modelScene?.clear();
this.modelScene?.removeFromParent();
this.emit(DESTRUCTED);
}

public intro(): void {}

public outro(): void {}

public update(): void {}
}
Loading

0 comments on commit 23cc6a4

Please sign in to comment.