From b19977cd0902aedda5c95e1ed5317f6439c86ca2 Mon Sep 17 00:00:00 2001 From: Brett Jephson Date: Wed, 4 Sep 2013 13:54:12 +0100 Subject: [PATCH] Fix component removal from entity in nodelist, fix memory leak in NodePool, remove entity.clone() --- build/ash.js | 123 +++++++++++++++--------- build/ash.min.js | 2 +- src/ash/core/componentmatchingfamily.js | 12 +-- src/ash/core/entity.js | 49 ++++------ src/ash/core/node.js | 2 +- src/ash/core/nodepool.js | 14 ++- test/spec/componentmatchingfamily.js | 29 +++++- test/spec/engine.js | 3 +- test/spec/entity.js | 30 +----- 9 files changed, 141 insertions(+), 123 deletions(-) diff --git a/build/ash.js b/build/ash.js index 964072e..d805868 100644 --- a/build/ash.js +++ b/build/ash.js @@ -518,9 +518,11 @@ define('ash-core/nodepool',[ tail: null, cacheTail: null, nodeClass: null, - - constructor: function (nodeClass) { + components : null, + + constructor: function (nodeClass, components) { this.nodeClass = nodeClass; + this.components = components; }, get: function() { @@ -535,6 +537,10 @@ define('ash-core/nodepool',[ }, dispose: function( node ) { + this.components.forEach(function(componentClass, componentName) { + node[componentName] = null; + }); + node.entity = null; node.next = null; node.previous = this.tail; this.tail = node; @@ -549,9 +555,7 @@ define('ash-core/nodepool',[ while( this.cacheTail ) { var node = this.cacheTail; this.cacheTail = node.previous; - node.next = null; - node.previous = this.tail; - this.tail = node; + this.dispose( node ); } } }); @@ -1301,14 +1305,14 @@ define('ash-core/componentmatchingfamily',[ return this.nodes; }); - var nodePool = this.nodePool = new NodePool(nodeClass); this.nodes = new NodeList(); - this.entities = new Dictionary(); - this.components = new Dictionary(); - - nodePool.dispose(nodePool.get()); + this.entities = new Dictionary(); + this.components = new Dictionary(); + this.nodePool = new NodePool( this.nodeClass, this.components ); + + this.nodePool.dispose( this.nodePool.get() ); - var nodeClassPrototype = nodeClass.prototype; + var nodeClassPrototype = this.nodeClass.prototype; for(var property in nodeClassPrototype) { ///TODO - tidy this up... @@ -1686,31 +1690,32 @@ define('ash-core/entity',[ this.componentRemoved = new signals.Signal(); }, - add: function (component, componentObject) { - componentObject = componentObject || component.constructor; - componentObject = componentObject.prototype; - - if ( this.components.has( componentObject ) ) { - this.remove( componentObject ); - } - this.components.add(componentObject, component); - this.componentAdded.dispatch( this, componentObject ); + add: function (component, componentClass ) { + if( typeof componentClass === "undefined" ) + { + componentClass = component.constructor; + } + if ( this.components.has( componentClass ) ) + { + this.remove( componentClass ); + } + this.components.add(componentClass, component); + this.componentAdded.dispatch( this, componentClass ); return this; }, - remove: function (componentObject) { - componentObject = componentObject.prototype; - var component = this.components.retrieve( componentObject ); + remove: function ( componentClass ) { + var component = this.components.retrieve( componentClass ); if ( component ) { - this.components.remove( componentObject ); - this.componentRemoved.dispatch( this, componentObject ); + this.components.remove( componentClass ); + this.componentRemoved.dispatch( this, componentClass ); return component; } return null; }, - get: function (componentObject) { - return this.components.retrieve( componentObject.prototype ); + get: function (componentClass) { + return this.components.retrieve( componentClass ); }, /** @@ -1725,22 +1730,8 @@ define('ash-core/entity',[ return componentArray; }, - has: function (componentObject) { - return this.components.has( componentObject.prototype ); - }, - - clone: function () { - var copy = new Entity(); - this.components.forEach( function( componentObject, component ) { - var newComponent = new componentObject.constructor(); - for( var property in component ) { - if( component.hasOwnProperty( property ) ) { - newComponent[property] = component[property]; - } - } - copy.add( newComponent ); - } ); - return copy; + has: function (componentClass) { + return this.components.has( componentClass ); } }); @@ -1759,10 +1750,52 @@ define('ash-core/node',[ entity: null, previous: null, next: null, - + constructor: function () { } }); + /** + * A simpler way to create a node. + * + * Example: creating a node for component classes Point & energy: + * + * var PlayerNode = Ash.Node.create({ + * point: Point, + * energy: Energy + * }); + * + * This is the simpler version from: + * + * var PlayerNode = Ash.Node.extend({ + * point: null, + * energy: null, + * + * types: { + * point: Point, + * energy: Energy + * } + * }); + */ + Node.create = function (schema) { + var processedSchema = { + types: {}, + constructor: function () { } + }; + + // process schema + for (var propertyName in schema) { + if (schema.hasOwnProperty(propertyName)) { + var propertyType = schema[propertyName]; + if (propertyType) { + processedSchema.types[propertyName] = propertyType; + } + processedSchema[propertyName] = null; + } + } + + return Node.extend(processedSchema); + }; + return Node; }); @@ -1808,7 +1841,7 @@ define('ash-core/system',[ */ define('ash/ash-framework',['require','ash-core/engine','ash-core/componentmatchingfamily','ash-core/entity','ash-core/entitylist','ash-core/family','ash-core/node','ash-core/nodelist','ash-core/nodepool','ash-core/system','ash-core/systemlist','brejep/class','signals'],function (require) { var core = { - VERSION: '0.1.0' + VERSION: '0.2.0' }; core.Engine = require('ash-core/engine'); diff --git a/build/ash.min.js b/build/ash.min.js index 64fe6fa..533febd 100644 --- a/build/ash.min.js +++ b/build/ash.min.js @@ -11,4 +11,4 @@ * Version: 0.7.4 - Build: 252 (2012/02/24 10:30 PM) */ -(function(e,t){var n=e.define,r,i,t;(function(e){function d(e,t){return h.call(e,t)}function v(e,t){var n,r,i,s,o,u,a,f,c,h,p=t&&t.split("/"),d=l.map,v=d&&d["*"]||{};if(e&&e.charAt(0)===".")if(t){p=p.slice(0,p.length-1),e=p.concat(e.split("/"));for(f=0;f0&&(e.splice(f-1,2),f-=2)}}e=e.join("/")}else e.indexOf("./")===0&&(e=e.substring(2));if((p||v)&&d){n=e.split("/");for(f=n.length;f>0;f-=1){r=n.slice(0,f).join("/");if(p)for(c=p.length;c>0;c-=1){i=d[p.slice(0,c).join("/")];if(i){i=i[r];if(i){s=i,o=f;break}}}if(s)break;!u&&v&&v[r]&&(u=v[r],a=f)}!s&&u&&(s=u,o=a),s&&(n.splice(0,o,s),e=n.join("/"))}return e}function m(t,n){return function(){return s.apply(e,p.call(arguments,0).concat([t,n]))}}function g(e){return function(t){return v(t,e)}}function y(e){return function(t){a[e]=t}}function b(t){if(d(f,t)){var r=f[t];delete f[t],c[t]=!0,n.apply(e,r)}if(!d(a,t)&&!d(c,t))throw new Error("No "+t);return a[t]}function w(e){var t,n=e?e.indexOf("!"):-1;return n>-1&&(t=e.substring(0,n),e=e.substring(n+1,e.length)),[t,e]}function E(e){return function(){return l&&l.config&&l.config[e]||{}}}var n,s,o,u,a={},f={},l={},c={},h=Object.prototype.hasOwnProperty,p=[].slice;o=function(e,t){var n,r=w(e),i=r[0];return e=r[1],i&&(i=v(i,t),n=b(i)),i?n&&n.normalize?e=n.normalize(e,g(t)):e=v(e,t):(e=v(e,t),r=w(e),i=r[0],e=r[1],i&&(n=b(i))),{f:i?i+"!"+e:e,n:e,pr:i,p:n}},u={require:function(e){return m(e)},exports:function(e){var t=a[e];return typeof t!="undefined"?t:a[e]={}},module:function(e){return{id:e,uri:"",exports:a[e],config:E(e)}}},n=function(t,n,r,i){var s,l,h,p,v,g=[],w;i=i||t;if(typeof r=="function"){n=!n.length&&r.length?["require","exports","module"]:n;for(v=0;v=0){n!=r.next&&(this.tail==n&&(this.tail=n.previous),n.previous.next=n.next,n.next&&(n.next.previous=n.previous),n.next=r.next,n.previous=r,n.next.previous=n,r.next=n);break}r||(this.tail==n&&(this.tail=n.previous),n.previous.next=n.next,n.next&&(n.next.previous=n.previous),n.next=this.head,this.head.previous=n,n.previous=null,this.head=n)}},mergeSort:function(e){if(this.head==this.tail)return;var t=[],n=this.head,r;while(n){r=n;while(r.next&&e(r,r.next)<=0)r=r.next;var i=r.next;n.previous=r.next=null,t.push(n),n=i}while(t.length>1)t.push(this.merge(t.shift(),t.shift(),e));this.tail=this.head=t[0];while(this.tail.next)this.tail=this.tail.next},merge:function(e,t,n){var r,i;n(e,t)<=0?(i=r=e,e=e.next):(i=r=t,t=t.next);while(e&&t)n(e,t)<=0?(r.next=e,e.previous=r,r=e,e=e.next):(r.next=t,t.previous=r,r=t,t=t.next);return e?(r.next=e,e.previous=r):(r.next=t,t.previous=r),i}});return n}),t("brejep/dictionary",["brejep/class"],function(e){var t=e.extend({VERSION:"0.1.0",keys:null,values:null,constructor:function(){return this.keys=[],this.values=[],this},add:function(e,t){var n=this.getIndex(e);n>=0?this.values[n]=t:(this.keys.push(e),this.values.push(t))},remove:function(e){var t=this.getIndex(e);if(!(t>=0))throw"Key does not exist";this.keys.splice(t,1),this.values.splice(t,1)},retrieve:function(e){var t=null,n=this.getIndex(e);return n>=0&&(t=this.values[n]),t},getIndex:function(e){var t=0,n=this.keys.length,r;for(;t0&&(e.splice(f-1,2),f-=2)}}e=e.join("/")}else e.indexOf("./")===0&&(e=e.substring(2));if((p||v)&&d){n=e.split("/");for(f=n.length;f>0;f-=1){r=n.slice(0,f).join("/");if(p)for(c=p.length;c>0;c-=1){i=d[p.slice(0,c).join("/")];if(i){i=i[r];if(i){s=i,o=f;break}}}if(s)break;!u&&v&&v[r]&&(u=v[r],a=f)}!s&&u&&(s=u,o=a),s&&(n.splice(0,o,s),e=n.join("/"))}return e}function m(t,n){return function(){return s.apply(e,p.call(arguments,0).concat([t,n]))}}function g(e){return function(t){return v(t,e)}}function y(e){return function(t){a[e]=t}}function b(t){if(d(f,t)){var r=f[t];delete f[t],c[t]=!0,n.apply(e,r)}if(!d(a,t)&&!d(c,t))throw new Error("No "+t);return a[t]}function w(e){var t,n=e?e.indexOf("!"):-1;return n>-1&&(t=e.substring(0,n),e=e.substring(n+1,e.length)),[t,e]}function E(e){return function(){return l&&l.config&&l.config[e]||{}}}var n,s,o,u,a={},f={},l={},c={},h=Object.prototype.hasOwnProperty,p=[].slice;o=function(e,t){var n,r=w(e),i=r[0];return e=r[1],i&&(i=v(i,t),n=b(i)),i?n&&n.normalize?e=n.normalize(e,g(t)):e=v(e,t):(e=v(e,t),r=w(e),i=r[0],e=r[1],i&&(n=b(i))),{f:i?i+"!"+e:e,n:e,pr:i,p:n}},u={require:function(e){return m(e)},exports:function(e){var t=a[e];return typeof t!="undefined"?t:a[e]={}},module:function(e){return{id:e,uri:"",exports:a[e],config:E(e)}}},n=function(t,n,r,i){var s,l,h,p,v,g=[],w;i=i||t;if(typeof r=="function"){n=!n.length&&r.length?["require","exports","module"]:n;for(v=0;v=0){n!=r.next&&(this.tail==n&&(this.tail=n.previous),n.previous.next=n.next,n.next&&(n.next.previous=n.previous),n.next=r.next,n.previous=r,n.next.previous=n,r.next=n);break}r||(this.tail==n&&(this.tail=n.previous),n.previous.next=n.next,n.next&&(n.next.previous=n.previous),n.next=this.head,this.head.previous=n,n.previous=null,this.head=n)}},mergeSort:function(e){if(this.head==this.tail)return;var t=[],n=this.head,r;while(n){r=n;while(r.next&&e(r,r.next)<=0)r=r.next;var i=r.next;n.previous=r.next=null,t.push(n),n=i}while(t.length>1)t.push(this.merge(t.shift(),t.shift(),e));this.tail=this.head=t[0];while(this.tail.next)this.tail=this.tail.next},merge:function(e,t,n){var r,i;n(e,t)<=0?(i=r=e,e=e.next):(i=r=t,t=t.next);while(e&&t)n(e,t)<=0?(r.next=e,e.previous=r,r=e,e=e.next):(r.next=t,t.previous=r,r=t,t=t.next);return e?(r.next=e,e.previous=r):(r.next=t,t.previous=r),i}});return n}),t("brejep/dictionary",["brejep/class"],function(e){var t=e.extend({VERSION:"0.1.0",keys:null,values:null,constructor:function(){return this.keys=[],this.values=[],this},add:function(e,t){var n=this.getIndex(e);n>=0?this.values[n]=t:(this.keys.push(e),this.values.push(t))},remove:function(e){var t=this.getIndex(e);if(!(t>=0))throw"Key does not exist";this.keys.splice(t,1),this.values.splice(t,1)},retrieve:function(e){var t=null,n=this.getIndex(e);return n>=0&&(t=this.values[n]),t},getIndex:function(e){var t=0,n=this.keys.length,r;for(;t