Skip to content

Commit

Permalink
Merge pull request #179 from MageStudio/better-dispose
Browse files Browse the repository at this point in the history
handling dispose of elements better
  • Loading branch information
marco-ponds authored May 27, 2022
2 parents 5206139 + 102b236 commit 31b131a
Show file tree
Hide file tree
Showing 16 changed files with 117 additions and 63 deletions.
Binary file modified examples/animations/assets/skeleton_animation.fbx
Binary file not shown.
13 changes: 8 additions & 5 deletions examples/animations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default class Intro extends Level {

// const animated = Models.getModel('animated');
const skeleton = Models.get('skeleton');
const duck = Models.get('duck');
// const duck = Models.get('duck');
const eyeballs = [
Particles.addParticleEmitter(PARTICLES.FIRE, {
texture: 'fire',
Expand Down Expand Up @@ -88,18 +88,21 @@ export default class Intro extends Level {
leftEyeball.emit(Infinity);
leftEyeball.setPosition({x: 0.2, y: 0.35, z: 0.3});

skeleton.playAnimation(skeleton.getAvailableAnimations()[5])
skeleton.playAnimation('Root|Interact');
console.log(skeleton.getAvailableAnimations());

skeleton.setMaterialFromName(constants.MATERIALS.STANDARD, { roughness: .5, metalness: 0 });
duck.setMaterialFromName(constants.MATERIALS.STANDARD, { roughness: .5, metalness: 0 });
// duck.setMaterialFromName(constants.MATERIALS.STANDARD, { roughness: .5, metalness: 0 });

// setTimeout(() => {
// skeleton.dispose();
// }, 2000);
}
}

const assets = {
'/': {
models: {
'animated': 'assets/animated.fbx',
'duck': 'assets/duck_animation.fbx',
'skeleton': 'assets/skeleton_animation.fbx',
},
textures: {
Expand Down
1 change: 1 addition & 0 deletions examples/particles_fire/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export default class Intro extends Level {
fire.setPosition({ y: 1 });

window.cube = cube;
window.fire = fire;
}

onKeyDown({ event }) {
Expand Down
12 changes: 7 additions & 5 deletions src/core/universe.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,17 @@ export class Universe {
}

forEach = (callback) => {
const keys = Object.keys(this.reality);

keys.forEach(k => callback(this.reality[k]));
Object
.keys(this.reality)
.forEach(k => callback(this.reality[k], k));
};

forEachAsync = (callback) => {
const keys = Object.keys(this.reality);

return new Promise(resolve => {
Promise
.all(keys.map(k => callback(this.reality[k])))
.all(keys.map(k => callback(this.reality[k], k)))
.then(resolve);
});
};
Expand All @@ -86,7 +86,9 @@ export class Universe {
}

bigfreeze = () => {
this.forEach(o => o.dispose());
this.forEach((o) => {
o && o.dispose && o.dispose()
});
this.reset();
}

Expand Down
27 changes: 12 additions & 15 deletions src/entities/Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ export default class Element extends Entity {
return new Promise((resolve) =>
new Between(this.opacity, opacity)
.time(time)
.on('update', value => this.setOpacity(value))
.on('update', value => !this.isDisposed() && this.setOpacity(value))
.on('complete', resolve)
);
}
Expand Down Expand Up @@ -626,19 +626,21 @@ export default class Element extends Entity {
}

disposeBody() {
if (hasMaterial(this.body)) {
super.disposeBody();

if (hasMaterial(this.getBody())) {
disposeTextures(this.getBody());
disposeMaterial(this.getBody());
disposeGeometry(this.getBody());
} else {
this.body.traverse(child => {
if (hasMaterial(child)) {
disposeTextures(child);
disposeMaterial(child);
disposeGeometry(child);
}
});
}

this.getBody().traverse(child => {
if (hasMaterial(child)) {
disposeTextures(child);
disposeMaterial(child);
disposeGeometry(child);
}
});
}

update(dt) {
Expand All @@ -657,10 +659,6 @@ export default class Element extends Entity {
dispose() {
super.dispose();

if (this.hasBody()) {
Scene.remove(this.getBody());
this.disposeBody();
}
if (this.hasAnimationHandler()) {
this.removeAnimationHandlerListeners();
}
Expand All @@ -673,7 +671,6 @@ export default class Element extends Entity {
return {
...super.toJSON(),
body: this.body.toJSON(),
scripts: this.mapScriptsToJSON(),
textures: this.textures,
...this.options
}
Expand Down
58 changes: 47 additions & 11 deletions src/entities/Entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ import {
KEY_IS_MISSING,
KEY_VALUE_IS_MISSING,
ENTITY_CANT_ADD_NOT_ENTITY,
ENTITY_CHILD_IS_NOT_ENTITY,
ENTITY_NOT_SET
} from '../lib/messages';
import Scripts from '../scripts/Scripts';
import Scene from '../core/Scene';

import {
isScene
} from '../lib/meshUtils';

import {
DEFAULT_TAG,
Expand All @@ -33,6 +37,7 @@ export default class Entity extends EventDispatcher {
this.children = [];
this.isMage = true;
this.parent = false;
this.disposed = false;

this.addTags([ DEFAULT_TAG, tag, ...tags ]);
this.serializable = serializable;
Expand All @@ -46,6 +51,10 @@ export default class Entity extends EventDispatcher {
return !!this.serializable;
}

isDisposed() {
return this.disposed;
}

reset() {
this.scripts = [];
this.children = [];
Expand Down Expand Up @@ -149,6 +158,10 @@ export default class Entity extends EventDispatcher {
}
}

hasChildren() {
return this.children.length > 0;
}

getHierarchy() {
return {
element: this,
Expand Down Expand Up @@ -197,14 +210,18 @@ export default class Entity extends EventDispatcher {
return this.tags;
}

stopScripts() {
disposeScripts() {
if (this.hasScripts()) {
this.scripts.forEach(({ script, enabled }) => {
const length = this.scripts.length;
for (let i = 0; i < length; i++) {
const { script, enabled } = this.scripts[i];
if (enabled) {
script.onDispose();
script.__hasStarted(false);
script.__setStartedFlag(false);
}
});

delete this.scripts[i];
}
}
}

Expand All @@ -213,7 +230,7 @@ export default class Entity extends EventDispatcher {
this.scripts.forEach(({ script, enabled, options }) => {
if (enabled) {
script.start(this, options);
script.__hasStarted(true);
script.__setStartedFlag(true);
}
});
}
Expand All @@ -239,16 +256,34 @@ export default class Entity extends EventDispatcher {
}
}

disposeBody() {
this.getBody().clear();
if (this.getBody().dispose && !isScene(this.getBody())) {
this.getBody().dispose();
}
}

dispose() {
if (this.hasChildren()) {
this.children.forEach(child => {
child.dispose();
});
}

if (this.hasBody()) {
this.stopStateMachine();
this.stopScripts();
this.reset();
this.disposeScripts();

Scene.remove(this.getBody());
this.disposeBody();
}


this.dispatchEvent({
type: ENTITY_EVENTS.DISPOSE
})
});

this.reset();
}

hasStateMachine = () => !!this.stateMachine;
Expand Down Expand Up @@ -527,7 +562,7 @@ export default class Entity extends EventDispatcher {
return new Promise((resolve) =>
new Between({ x, y, z}, rotation)
.time(time)
.on('update', value => this.setRotation(value))
.on('update', value => !this.isDisposed() && this.setRotation(value))
.on('complete', resolve)
);
}
Expand All @@ -538,7 +573,7 @@ export default class Entity extends EventDispatcher {
return new Promise((resolve) =>
new Between({ x, y, z}, position)
.time(time)
.on('update', value => this.setPosition(value))
.on('update', value => !this.isDisposed() && this.setPosition(value))
.on('complete', resolve)
);
}
Expand Down Expand Up @@ -621,6 +656,7 @@ export default class Entity extends EventDispatcher {
rotation: this.getRotation(),
scale: this.getScale(),
entityType: this.getEntityType(),
scripts: this.mapScriptsToJSON(),
tags: this.getTags()
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/fx/particles/ParticleEmitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,14 @@ export default class ParticleEmitter extends Entity {
}
}

dispose() {
super.dispose();
}

update(dt) {
super.update(dt);

if (this.hasSystem()) {
if (this.hasSystem() && !this.isSystemDead()) {
this.system.update(dt);
}

Expand Down
10 changes: 7 additions & 3 deletions src/fx/particles/Particles.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Trail from './Trail';

import Scene from '../../core/Scene';
import Proton from 'three.proton.js';
import { INVALID_EMITTER_ID } from '../../lib/messages';
import { DEPRECATIONS, INVALID_EMITTER_ID } from '../../lib/messages';
import { PARTICLE_EMITTER_TYPES } from './constants';
import ParticleEmitter from './ParticleEmitter';
import ParticleEmitterGroup from './ParticleEmitterGroup';
Expand Down Expand Up @@ -62,8 +62,12 @@ export class Particles {
emitter instanceof ProtonParticleEmitter;
}

addParticleEmitter(_emitter, options = {}) {
addParticleEmitter(emitter, options = {}) {
console.warn(DEPRECATIONS.PARTICLES_ADD_PARTICLE_EMITTER);
return this.add(emitter, options);
}

add(_emitter, options = {}) {
let emitter;
if (this.isRegisteredEmitter(_emitter)) {
const Emitter = this.get(_emitter);
Expand Down Expand Up @@ -122,7 +126,7 @@ export class Particles {
}

if (emitter.isSystemDead()) {
this.toDispose.push(emitter.uuid);
this.toDispose.push(emitter.uuid());
}
}

Expand Down
13 changes: 10 additions & 3 deletions src/fx/particles/ProtonParticleEmitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Images from '../../images/Images';
import PALETTES from '../../lib/palettes';

const DEFAULT_PARTICLE_COLOR = PALETTES.BASE.BLACK;
const SYSTEM_DISPOSE_TIMEOUT = 700;

export default class ProtonParticleEmitter extends ParticleEmitter {

Expand Down Expand Up @@ -95,10 +96,16 @@ export default class ProtonParticleEmitter extends ParticleEmitter {
this.system.p.z = position.z;
}

disposeSystem = () => {
if (this.hasSystem()) {
this.system.removeAllParticles();
this.system.destroy();
}
}

dispose() {
super.dispose();

this.system.stopEmit();
this.system.destroy();
this.stop();
setTimeout(this.disposeSystem, SYSTEM_DISPOSE_TIMEOUT);
}
}
4 changes: 3 additions & 1 deletion src/lib/math.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { Vector3, MathUtils } from 'three';
export const PI = Math.PI;
export const PI_2 = PI/2;

export const pickRandom = list => list.length && list[Math.floor(Math.random() * list.length)];
export const identity = a => a;

export const pickRandom = (list = []) => list[Math.floor(Math.random() * list.length)];

export const degToRad = (angle) => {
return angle * (PI / 180);
Expand Down
Loading

0 comments on commit 31b131a

Please sign in to comment.