Skip to content

Commit

Permalink
Add facility to release a family if it is no longer needed. Add remov…
Browse files Browse the repository at this point in the history
…eAll to all the linked lists.
  • Loading branch information
richardlord committed Jan 11, 2012
1 parent 999f090 commit 59f170a
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 8 deletions.
9 changes: 9 additions & 0 deletions README.textile
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,21 @@ h3. Source Code

* "Ash":http://github.com/richardlord/Ash

h3. Examples

* "Asteroids":http://github.com/richardlord/Ash/tree/master/examples

h3. Developers

* "Richard Lord":http://www.richardlord.net/
** "Richard on Twitter":http://twitter.com/Richard_Lord
** "Richard on Github":http://github.com/richardlord

h3. Thank you

* Tom Davies, for "Ember":https://github.com/tdavies/Ember and "Ember2":https://github.com/tdavies/Ember2 and for the many discussions we've had about entity systems.
* Alec McEachran, for "Xember":https://github.com/alecmce/xember and the discussions we've had about entity systems, particularly at "try{harder}":http://www.tryharder.org.uk/

h2. License

Ash - an entity framework for Actionscript games
Expand Down
12 changes: 12 additions & 0 deletions src/net/richardlord/ash/core/EntityList.as
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,17 @@ package net.richardlord.ash.core
entity.next.previous = entity.previous;
}
}

internal function removeAll() : void
{
while( entity )
{
var entity : Entity = entity;
head = head.next;
entity.previous = null;
entity.next = null;
}
tail = null;
}
}
}
10 changes: 10 additions & 0 deletions src/net/richardlord/ash/core/Family.as
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ package net.richardlord.ash.core
}
}

internal function cleanUp() : void
{
for( var node : Node = nodes.head; node; node = node.next )
{
node.entity.componentRemoved.remove( componentRemoved );
delete entities[node.entity];
}
nodes.removeAll();
}

private function componentRemoved( entity : Entity, componentClass : Class ) : void
{
if( components[componentClass] )
Expand Down
9 changes: 9 additions & 0 deletions src/net/richardlord/ash/core/Game.as
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ package net.richardlord.ash.core
return family.nodes;
}

public function releaseFamily( nodeClass : Class ) : void
{
if( families[nodeClass] )
{
families[nodeClass].cleanUp();
}
delete families[nodeClass];
}

public function addSystemWithPriority( system : System, priority : int ) : void
{
system.priority = priority;
Expand Down
17 changes: 15 additions & 2 deletions src/net/richardlord/ash/core/NodeList.as
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ package net.richardlord.ash.core
nodeRemoved = new Signal1( Node );
}

public function add( node : Node ) : void
internal function add( node : Node ) : void
{
if( ! head )
{
Expand All @@ -31,7 +31,7 @@ package net.richardlord.ash.core
nodeAdded.dispatch( node );
}

public function remove( node : Node ) : void
internal function remove( node : Node ) : void
{
if ( head == node)
{
Expand All @@ -54,6 +54,19 @@ package net.richardlord.ash.core
nodeRemoved.dispatch( node );
}

internal function removeAll() : void
{
while( head )
{
var node : Node = head;
head = node.next;
node.previous = null;
node.next = null;
nodeRemoved.dispatch( node );
}
tail = null;
}

public function get empty() : Boolean
{
return head == null;
Expand Down
12 changes: 12 additions & 0 deletions src/net/richardlord/ash/core/SystemList.as
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,17 @@ package net.richardlord.ash.core
system.next.previous = system.previous;
}
}

internal function removeAll() : void
{
while( head )
{
var system : System = head;
head = head.next;
system.previous = null;
system.next = null;
}
tail = null;
}
}
}
12 changes: 12 additions & 0 deletions src/net/richardlord/ash/signals/SignalBase.as
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,17 @@ package net.richardlord.ash.signals
delete( nodes[ listener ] );
}
}

public function removeAll() : void
{
while( head )
{
var listener : ListenerNode = head;
head = head.next;
listener.previous = null;
listener.next = null;
}
tail = null;
}
}
}
32 changes: 32 additions & 0 deletions test/src/net/richardlord/ash/core/FamilyTests.as
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,38 @@ package net.richardlord.ash.core
{
assertThat( signalNode, sameInstance( tempNode ) );
}

[Test]
public function releaseFamilyEmptiesNodeList() : void
{
var entity : Entity = new Entity();
entity.add( new Point() );
entity.add( new Matrix() );
game.addEntity( entity );
game.removeEntity( entity );
var nodes : NodeList = game.getFamily( MockNode );
game.releaseFamily( MockNode );
assertThat( nodes.head, nullValue() );
}

[Test]
public function releaseFamilySetsNextNodeToNull() : void
{
var entities : Array = new Array();
for( var i : int = 0; i < 5; ++i )
{
var entity : Entity = new Entity();
entity.add( new Point() );
entity.add( new Matrix() );
entities.push( entity );
game.addEntity( entity );
}

var nodes : NodeList = game.getFamily( MockNode );
var node : MockNode = nodes.head.next;
game.releaseFamily( MockNode );
assertThat( node.next, nullValue() );
}
}
}
import net.richardlord.ash.core.Node;
Expand Down
48 changes: 42 additions & 6 deletions test/src/net/richardlord/ash/signals/SignalTest.as
Original file line number Diff line number Diff line change
Expand Up @@ -128,26 +128,62 @@ package net.richardlord.ash.signals
dispatchSignal();
}

private function addListenerDuringDispatch( e : * = null ) : void
private function addListenerDuringDispatch() : void
{
signal.add( failIfCalled );
}

protected function dispatchSignal() : void
[Test]
public function dispatch2Listeners2ndListenerRemoves1stThen1stListenerIsNotCalled() : void
{
signal.dispatch();
//fail( 'Test should override dispatchSignal method' );
signal.add( failIfCalled );
signal.add( async.add( removeFailListener, 10 ) );
dispatchSignal();
}

private function removeFailListener( ...args ) : void
{
signal.remove( failIfCalled );
}

[Test]
public function add2ListenersThenRemoveAllShouldLeaveNoListeners():void
{
signal.add( newEmptyHandler() );
signal.add( newEmptyHandler() );
signal.removeAll();
assertThat( signal.head, nullValue() );
}

[Test]
public function removeAllDuringDispatchShouldStopAll():void
{
signal.add( newEmptyHandler() );
signal.add( failIfCalled );
signal.add( removeAllListeners );
dispatchSignal();
}

private function removeAllListeners( ...args ) : void
{
signal.removeAll();
}

// //// UTILITY METHODS // ////
protected static function newEmptyHandler() : Function

private function dispatchSignal() : void
{
signal.dispatch();
}

private static function newEmptyHandler() : Function
{
return function( ...args ) : void
{
};
}

protected static function failIfCalled( ...args ) : void
private static function failIfCalled( ...args ) : void
{
fail( 'This function should not have been called.' );
}
Expand Down

0 comments on commit 59f170a

Please sign in to comment.