From 175e7259dfdec49872132716da7ef43a76c65d1e Mon Sep 17 00:00:00 2001 From: Alan Grgic Date: Fri, 3 Aug 2018 20:21:48 -0500 Subject: [PATCH] [#979] Prevent removal of actors that are killed and readded during the same frame (#1016) Closes #979 ## Changes: - Add check to ensure Actor is still killed before removing it from drawing tree. --- CHANGELOG.md | 5 ++++- package-lock.json | 2 +- src/engine/Scene.ts | 18 ++++++++++++++---- src/spec/SceneSpec.ts | 13 +++++++++++++ 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90ade01c1..e65f713a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,13 +9,16 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added +- Add `Scene.isActorInDrawTree` method to determine if an actor is in the scene's draw tree. + ### Changed ### Deprecated ### Fixed -- Fixed missing `exitviewport/enterviewport` events on Actors.on/once/off signatures. ([#978](https://github.com/excaliburjs/Excalibur/issues/978)) +- Fixed missing `exitviewport/enterviewport` events on Actors.on/once/off signatures ([#978](https://github.com/excaliburjs/Excalibur/issues/978)) +- Fix issue where Actors would not be properly added to a scene if they were removed from that scene during the same frame ([#979](https://github.com/excaliburjs/Excalibur/issues/979)) diff --git a/package-lock.json b/package-lock.json index 29d5a7c88..24cc7b7f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "excalibur", - "version": "0.0.0", + "version": "0.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/engine/Scene.ts b/src/engine/Scene.ts index fce52072c..aad556b77 100644 --- a/src/engine/Scene.ts +++ b/src/engine/Scene.ts @@ -390,10 +390,13 @@ export class Scene extends Class implements ICanInitialize, ICanActivate, ICanDe // Remove actors from scene graph after being killed var actorIndex: number; for (let killed of killQueue) { - actorIndex = collection.indexOf(killed); - if (actorIndex > -1) { - this._sortedDrawingTree.removeByComparable(killed); - collection.splice(actorIndex, 1); + //don't remove actors that were readded during the same frame they were killed + if (killed.isKilled()) { + actorIndex = collection.indexOf(killed); + if (actorIndex > -1) { + this._sortedDrawingTree.removeByComparable(killed); + collection.splice(actorIndex, 1); + } } } killQueue.length = 0; @@ -737,6 +740,13 @@ export class Scene extends Class implements ICanInitialize, ICanActivate, ICanDe this._sortedDrawingTree.add(actor); } + /** + * Checks if an actor is in this scene's sorted draw tree + */ + public isActorInDrawTree(actor: Actor): boolean { + return this._sortedDrawingTree.find(actor); + } + public isCurrentScene(): boolean { if (this.engine) { return this.engine.currentScene === this; diff --git a/src/spec/SceneSpec.ts b/src/spec/SceneSpec.ts index 836f29772..517e2fa52 100644 --- a/src/spec/SceneSpec.ts +++ b/src/spec/SceneSpec.ts @@ -225,6 +225,19 @@ describe('A scene', () => { expect(scene.actors.length).toBe(1); }); + it('will still be in the draw tree if it is killed and then added in the same frame', () => { + var actor = new ex.Actor(); + scene.add(actor); + actor.kill(); + scene.add(actor); + + scene.update(engine, 10); //call _processKillQueue + + expect(scene.actors.indexOf(actor)).toBe(0); + expect(scene.actors.length).toBe(1); + expect(scene.isActorInDrawTree(actor)).toBe(true); + }); + it('will update Actors that were added in a Timer callback', () => { var updated = false; var initialized = false;