Skip to content

Commit

Permalink
feat(map): dispose of model animations when removing area doodads
Browse files Browse the repository at this point in the history
  • Loading branch information
fallenoak committed Jan 24, 2024
1 parent a80ed39 commit bcd6b0d
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 8 deletions.
47 changes: 42 additions & 5 deletions src/lib/map/DoodadManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import TextureManager from '../texture/TextureManager.js';
import { AssetHost } from '../asset.js';
import { MapAreaSpec } from './loader/types.js';
import MapLight from './light/MapLight.js';
import ModelMesh from '../model/ModelMesh.js';

type DoodadManagerOptions = {
host: AssetHost;
Expand All @@ -15,6 +16,9 @@ class DoodadManager {
#host: AssetHost;
#modelManager: ModelManager;

#loadedAreas = new Map<number, THREE.Group>();
#loadingAreas = new Map<number, Promise<THREE.Group>>();

constructor(options: DoodadManagerOptions) {
this.#host = options.host;

Expand All @@ -25,7 +29,41 @@ class DoodadManager {
});
}

async getArea(area: MapAreaSpec) {
getArea(areaId: number, area: MapAreaSpec): Promise<THREE.Group> {
const loaded = this.#loadedAreas.get(areaId);
if (loaded) {
return Promise.resolve(loaded);
}

const alreadyLoading = this.#loadingAreas.get(areaId);
if (alreadyLoading) {
return alreadyLoading;
}

const loading = this.#loadArea(areaId, area);
this.#loadingAreas.set(areaId, loading);

return loading;
}

removeArea(areaId: number) {
const group = this.#loadedAreas.get(areaId);
if (!group) {
return;
}

for (const model of group.children) {
(model as ModelMesh).dispose();
}

this.#loadedAreas.delete(areaId);
}

update(deltaTime: number) {
this.#modelManager.update(deltaTime);
}

async #loadArea(areaId: number, area: MapAreaSpec) {
const group = new THREE.Group();
group.name = 'doodads';

Expand All @@ -50,11 +88,10 @@ class DoodadManager {
group.add(model);
}

return group;
}
this.#loadedAreas.set(areaId, group);
this.#loadingAreas.delete(areaId);

update(deltaTime: number) {
this.#modelManager.update(deltaTime);
return group;
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/lib/map/MapManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ class MapManager extends EventTarget {
if (doodadGroup) {
this.#root.remove(doodadGroup);
this.#doodadGroups.delete(areaId);
this.#doodadManager.removeArea(areaId);
}

this.#loadedAreas.delete(areaId);
Expand Down Expand Up @@ -313,7 +314,7 @@ class MapManager extends EventTarget {

const [terrainGroup, doodadGroup] = await Promise.all([
this.#terrainManager.getArea(areaId, newArea),
this.#doodadManager.getArea(newArea),
this.#doodadManager.getArea(areaId, newArea),
]);

const terrainBoundingSphere = new THREE.Box3()
Expand Down
5 changes: 5 additions & 0 deletions src/lib/model/ModelAnimator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class ModelAnimator {
return this.#sequences;
}

clearAction(action: THREE.AnimationAction) {
action.stop();
this.#mixer.uncacheAction(action.getClip());
}

update(deltaTime: number) {
this.#mixer.update(deltaTime);
}
Expand Down
16 changes: 14 additions & 2 deletions src/lib/model/ModelMesh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ type ModelTextureTransform = {

class ModelMesh extends THREE.Mesh {
#animator: ModelAnimator;
#animationActions: Set<THREE.AnimationAction> = new Set();

#diffuseColor: THREE.Color;
#emissiveColor: THREE.Color;
#alpha: 1.0;
Expand Down Expand Up @@ -51,15 +53,17 @@ class ModelMesh extends THREE.Mesh {

// Automatically play all loops
for (let i = 0; i < this.#animator.loops.length; i++) {
this.#animator.getLoop(this, i).play();
const action = this.#animator.getLoop(this, i).play();
this.#animationActions.add(action);
}

// Automatically play flagged sequences
for (let i = 0; i < this.#animator.sequences.length; i++) {
const sequence = this.#animator.sequences[i];

if (sequence.flags & 0x20) {
this.#animator.getSequence(this, i).play();
const action = this.#animator.getSequence(this, i).play();
this.#animationActions.add(action);
}
}
}
Expand All @@ -84,6 +88,14 @@ class ModelMesh extends THREE.Mesh {
material.setTextureTransform(i, translation, rotation, scaling);
}
}

dispose() {
for (const action of this.#animationActions.values()) {
this.#animator.clearAction(action);
}

this.#animationActions.clear();
}
}

export default ModelMesh;
Expand Down

0 comments on commit bcd6b0d

Please sign in to comment.