diff --git a/packages/entity/list.js b/packages/entity/list.js index 5e3da39..6852053 100644 --- a/packages/entity/list.js +++ b/packages/entity/list.js @@ -62,12 +62,14 @@ class EntityListBase { list: this, }, }); - entity.on('destroyed', () => { - this.removeEntity(entity); - }); - entity.on('positionChanged', () => { + const onEntityPositionChanged = () => { this.quadTree_PRIVATE.remove(this.quadTreePoint(entity)); this.quadTree_PRIVATE.add(this.recomputeQuadTreePoint(entity)); + }; + entity.on('positionChanged', onEntityPositionChanged); + entity.once('destroyed', () => { + this.removeEntity(entity); + entity.off('positionChanged', onEntityPositionChanged); }); this.emit('entityAdded', entity); this.quadTree_PRIVATE.add(this.recomputeQuadTreePoint(entity)); diff --git a/packages/entity/traits.js b/packages/entity/traits.js index 8b0b5ff..620dd81 100644 --- a/packages/entity/traits.js +++ b/packages/entity/traits.js @@ -33,9 +33,9 @@ export class Traits { this.properties_PRIVATE = {}; this.state_PRIVATE = I.Map(); this.traits_PRIVATE = {}; - entity.on('destroyed', () => { + entity.once('destroyed', () => { this.removeAllTraits(); - }) + }); } acceptStateChange(change) { diff --git a/packages/entity/traits/animated.js b/packages/entity/traits/animated.js index 2dbdbcf..66f6332 100644 --- a/packages/entity/traits/animated.js +++ b/packages/entity/traits/animated.js @@ -31,6 +31,7 @@ class AnimatedBase extends Trait { initialize() { this.animations = {}; + this.animationListeners = {}; this.animationViews = undefined; this.animationsPromise = undefined; } @@ -43,6 +44,11 @@ class AnimatedBase extends Trait { animationView.destroy(); } } + for (const key in this.animations) { + const animation = this.animations[key]; + animation.off('indexChanged', this.animationListeners[key]); + animation.destroy(); + } } hideAnimation(key) { @@ -80,11 +86,12 @@ class AnimatedBase extends Trait { // Set direction upfront. animation.direction = this.entity.direction; // Listen for index changes. - animation.on('indexChanged', () => { + this.animationListeners[key] = () => { if (this.entity.currentAnimation === key) { this.entity.currentFrame = animation.index; } - }); + }; + animation.on('indexChanged', this.animationListeners[key]); }); }); } diff --git a/packages/graphics/animation-view.js b/packages/graphics/animation-view.js index 9902b83..b3aef30 100644 --- a/packages/graphics/animation-view.js +++ b/packages/graphics/animation-view.js @@ -10,21 +10,25 @@ export class AnimationView extends Renderable { super(); this.animation = animation; this.container = new Container(); + this.onAnimationChanged = this.onAnimationChanged.bind(this); if (hasGraphics) { Image.load(this.animation.imageUri).then((image) => { this.sprite = new Sprite(image); this.container.addChild(this.sprite); this.resetSourceRectangle(); }); - animation.on(['directionChanged', 'indexChanged'], () => { - if (this.sprite) { - this.resetSourceRectangle(); - } - }); } + animation.on( + ['directionChanged', 'indexChanged'], + this.onAnimationChanged + ); } destroy() { + animation.off( + ['directionChanged', 'indexChanged'], + this.onAnimationChanged + ); if (this.sprite) { this.sprite.destroy(); } @@ -34,6 +38,12 @@ export class AnimationView extends Renderable { return this.container.internal; } + onAnimationChanged() { + if (this.sprite) { + this.resetSourceRectangle(); + } + } + reset() { this.animation.reset(); } diff --git a/packages/graphics/image.js b/packages/graphics/image.js index 9ce42dd..df47880 100644 --- a/packages/graphics/image.js +++ b/packages/graphics/image.js @@ -27,10 +27,10 @@ export class Image extends Resource { } return new Promise((resolve, reject) => { const baseTexture = PIXI.BaseTexture.fromImage(uri); - baseTexture.on('error', () => { + baseTexture.once('error', () => { reject(new Error(`Couldn't load image "${uri}"`)); }); - baseTexture.on('loaded', () => { + baseTexture.once('loaded', () => { resolve(this.baseTextureCache[uri] = baseTexture); }); }); diff --git a/packages/mixins/lfo/modulated-property.js b/packages/mixins/lfo/modulated-property.js index 969c516..b5996af 100644 --- a/packages/mixins/lfo/modulated-property.js +++ b/packages/mixins/lfo/modulated-property.js @@ -64,9 +64,8 @@ class ModulatedProperty { this.median = median; - this.on('magnitudeChanged', () => { - this.magnitude2 = this.magnitude() * 2; - }); + this.onMagnitudeChanged = this.onMagnitudeChanged.bind(this); + this.on('magnitudeChanged', this.onMagnitudeChanged); this.setFrequency(frequency); this.setLocation(location || 0); @@ -104,6 +103,14 @@ class ModulatedProperty { this.transitions = []; } + destroy() { + this.off('magnitudeChanged', this.onMagnitudeChanged); + } + + onMagnitudeChanged() { + this.magnitude2 = this.magnitude() * 2; + } + tick(elapsed) { this.transitions.forEach((transition) => { diff --git a/packages/mixins/lfo/result.js b/packages/mixins/lfo/result.js index 2916b5b..fe4740a 100644 --- a/packages/mixins/lfo/result.js +++ b/packages/mixins/lfo/result.js @@ -27,6 +27,13 @@ export default class LfoResult { } } + destroy() { + for (const key in this.properties) { + const property = this.properties[key]; + property.destroy(); + } + } + property(key) { return this.properties[key]; } diff --git a/packages/mixins/transition/result.js b/packages/mixins/transition/result.js index 0fadd88..c9a64c4 100644 --- a/packages/mixins/transition/result.js +++ b/packages/mixins/transition/result.js @@ -40,7 +40,7 @@ class TransitionResult { // Set up the transition object. this.promise = new Promise((resolve, reject) => { - this.on('stopped', () => resolve()); + this.once('stopped', () => resolve()); }); } diff --git a/packages/timing/timed-index.js b/packages/timing/timed-index.js index 795572f..af65b40 100644 --- a/packages/timing/timed-index.js +++ b/packages/timing/timed-index.js @@ -30,13 +30,15 @@ export function TimedIndexMixin (indexName = 'index') { this.ticker = new Ticker(); this.ticker.frequency = this[_indexRate]; - this.ticker.on('tick', () => { - const index = this.index + 1; - if (index >= this[_indexCount]) { - this.emit('rollingOver'); - } - this.index = index; - }); + this.onTick = this.onTick.bind(this); + this.ticker.on('tick', this.onTick); + } + + destroy() { + if (super.destroy) { + super.destroy(); + } + this.ticker.off('tick', this.onTick); } get index() { @@ -47,6 +49,14 @@ export function TimedIndexMixin (indexName = 'index') { super.index = 0 === this[_indexCount] ? 0 : index % this[_indexCount]; } + onTick() { + const index = this.index + 1; + if (index >= this[_indexCount]) { + this.emit('rollingOver'); + } + this.index = index; + } + reset() { this.ticker.reset(); }