diff --git a/spriter/definitions/ScmlObject.hx b/spriter/definitions/ScmlObject.hx index 15b92b8..97414a0 100644 --- a/spriter/definitions/ScmlObject.hx +++ b/spriter/definitions/ScmlObject.hx @@ -226,7 +226,7 @@ class ScmlObject implements IScml return newFolders; } - public function copy():ScmlObject + public function copy(?id:String):ScmlObject { var newSCML:ScmlObject = new ScmlObject(); newSCML.folders = copyFolders(); @@ -238,6 +238,7 @@ class ScmlObject implements IScml newSCML.currentEntity = Std.string(currentEntity); newSCML.currentAnimation = Std.string(currentAnimation); newSCML.currentTime = 0; + newSCML.spriterName = id; return newSCML; } @@ -248,5 +249,8 @@ class ScmlObject implements IScml entities = null; entitiesName = null; tags = null; + endAnimCallback = null; + tagCallback = null; + varChangeCallback = null; } } \ No newline at end of file diff --git a/spriter/definitions/SpatialInfo.hx b/spriter/definitions/SpatialInfo.hx index e45650d..92174ff 100644 --- a/spriter/definitions/SpatialInfo.hx +++ b/spriter/definitions/SpatialInfo.hx @@ -1,11 +1,13 @@ package spriter.definitions; +import spriter.interfaces.ISpriterPooled; +import spriter.util.SpriterPool; import spriter.util.SpriterUtil; /** * ... * @author Loudo */ -class SpatialInfo +class SpatialInfo implements ISpriterPooled { public var x:Float=0; public var y:Float=0; @@ -16,7 +18,25 @@ class SpatialInfo * Alpha */ public var a:Float=1; - public var spin:Int=1; + public var spin:Int = 1; + + private static var _pool = new SpriterPool(SpatialInfo); + private var _inPool:Bool = false; + + /** + * Recycle or create a new SpatialInfo. + * Be sure to put() them back into the pool after you're done with them! + * + * @param X The X-coordinate of the point in space. + * @param Y The Y-coordinate of the point in space. + * @return This point. + */ + public static inline function get(x:Float = 0, y:Float = 0, angle:Float = 0, scaleX:Float = 1, scaleY:Float = 1, a:Float = 1, spin:Int = 1):SpatialInfo + { + var pooledInfo = _pool.get().init(x, y, angle, scaleX, scaleY, a, spin); + pooledInfo._inPool = false; + return pooledInfo; + } public function new(x:Float = 0, y:Float = 0, angle:Float = 0, scaleX:Float = 1, scaleY:Float = 1, a:Float = 1, spin:Int = 1) { @@ -29,6 +49,32 @@ class SpatialInfo this.spin = spin; } + public function init(x:Float = 0, y:Float = 0, angle:Float = 0, scaleX:Float = 1, scaleY:Float = 1, a:Float = 1, spin:Int = 1):SpatialInfo + { + this.x = x; + this.y = y; + this.angle = angle; + this.scaleX = scaleX; + this.scaleY = scaleY; + this.a = a; + this.spin = spin; + return this; + } + + public function setPos(x:Float = 0, y:Float = 0):SpatialInfo + { + this.x = x; + this.y = y; + return this; + } + + public function setScale(scale:Float):SpatialInfo + { + this.scaleX = scale; + this.scaleY = scale; + return this; + } + public function unmapFromParent(parentInfo:SpatialInfo):SpatialInfo { var unmapped_x : Float; @@ -55,13 +101,12 @@ class SpatialInfo unmapped_y = parentInfo.y; } - return new SpatialInfo(unmapped_x, unmapped_y, unmapped_angle, unmapped_scaleX, unmapped_scaleY, unmapped_alpha, spin); + return SpatialInfo.get(unmapped_x, unmapped_y, unmapped_angle, unmapped_scaleX, unmapped_scaleY, unmapped_alpha, spin); } public function copy():SpatialInfo { - var c:SpatialInfo = new SpatialInfo(x, y, angle, scaleX, scaleY, a, spin); - return c; + return SpatialInfo.get(x, y, angle, scaleX, scaleY, a, spin); } /*public function linear(infoA:SpatialInfo, infoB:SpatialInfo, spin:Int, t:Float):SpatialInfo @@ -74,5 +119,20 @@ class SpatialInfo resultInfo.scaleY = linear(infoA.scaleY,infoB.scaleY,t); resultInfo.a = linear(infoA.a,infoB.a,t); }*/ + /** + * Add this SpatialInfo to the recycling pool. + */ + public function put():Void + { + if (!_inPool) + { + _inPool = true; + _pool.putUnsafe(this); + } + } + public function destroy():Void + { + + } } \ No newline at end of file diff --git a/spriter/definitions/SpatialTimelineKey.hx b/spriter/definitions/SpatialTimelineKey.hx index 19ba072..3e246e0 100644 --- a/spriter/definitions/SpatialTimelineKey.hx +++ b/spriter/definitions/SpatialTimelineKey.hx @@ -31,7 +31,7 @@ class SpatialTimelineKey extends TimelineKey var scale_y = fast.has.scale_y ? Std.parseFloat(fast.att.scale_y) : 1; var alpha = fast.has.a ? Std.parseFloat(fast.att.a) : 1; - info = new SpatialInfo(x, y, angle, scale_x, scale_y, alpha, spin); + info = new SpatialInfo(x, y, angle, scale_x, scale_y, alpha, spin);//we don't get from pool here because a macro use this constructor :/ } } @@ -43,7 +43,7 @@ class SpatialTimelineKey extends TimelineKey override public function clone (clone:TimelineKey):TimelineKey { - super.clone(clone); + super.clone(clone);//TODO instead of cloning we should only manipulate SpatialInfo from linearSpatialInfo(); var c:SpatialTimelineKey = cast clone; c.info = info.copy(); @@ -72,5 +72,10 @@ class SpatialTimelineKey extends TimelineKey { return new PivotInfo(pivotX,pivotY); } + public function destroy():Void + { + info.put();//add too pool + info = null; + } } \ No newline at end of file diff --git a/spriter/definitions/SpriterAnimation.hx b/spriter/definitions/SpriterAnimation.hx index 7776b1e..c9b3ae0 100644 --- a/spriter/definitions/SpriterAnimation.hx +++ b/spriter/definitions/SpriterAnimation.hx @@ -145,7 +145,7 @@ class SpriterAnimation } //var objectKeys:Array; - points = []; + points = [];//TODO back to pool? boxes = []; len = mainKey.objectRefs.length; for(o in 0...len) @@ -244,6 +244,16 @@ class SpriterAnimation } } } + //clean nup + spatialInfo.put();//back to pool + spatialInfo = null; + len = transformedBoneKeys.length; + for(p in 0...len) + { + spatialInfo = transformedBoneKeys[p]; + spatialInfo.put();//back to pool + spatialInfo = null; + } } public function mainlineKeyFromTime(time:Int):MainlineKey diff --git a/spriter/engine/Spriter.hx b/spriter/engine/Spriter.hx index c36c35d..5fdedd1 100644 --- a/spriter/engine/Spriter.hx +++ b/spriter/engine/Spriter.hx @@ -255,12 +255,24 @@ class Spriter { timeMS = 0; } + /** + * Set positions of the Spriter + * @param x + * @param y (spriter uses inverted y, so it will automatically inverted in this function) + */ + public function set(x:Float, y:Float):Void + { + //-y because use inverted y coordinates + info.setPos(x, -y); + } public function destroy():Void { scml.destroy(); + info.put(); info = null; //don't destroy library here since library is shared between all Spriter in the engine + library = null; } } \ No newline at end of file diff --git a/spriter/engine/SpriterEngine.hx b/spriter/engine/SpriterEngine.hx index 0933250..304e96e 100644 --- a/spriter/engine/SpriterEngine.hx +++ b/spriter/engine/SpriterEngine.hx @@ -125,26 +125,17 @@ class SpriterEngine * @param x * @param y * @param ?index if null same result as addChild, else same result as addChildAt(index). Spriters at and after the replaced index move up. You can use index out of range but negative means 0. - * @param copySCML if false, you can use a same SCML for multiple Spriter entity, allow you to have * @param autoRemoval if true, the Spriter will be removed after the animation is ended * @return the Spriter created */ - public function addEntity(id:String, x:Float = 0, y:Float = 0, ?index:Null, autoRemoval:Bool = false, copySCML:Bool = true):Spriter + public function addEntity(id:String, x:Float = 0, y:Float = 0, ?index:Null, autoRemoval:Bool = false):Spriter { //create spatial info for the current Spriter - var info:SpatialInfo = new SpatialInfo(x, -y);//-y because use inverted y coordinates + var info:SpatialInfo = SpatialInfo.get(x, -y);//-y because use inverted y coordinates - //select scmlObject - var currentSCML:ScmlObject; - if (copySCML) { - currentSCML = scml.copy(); - currentSCML.spriterName = id; - }else { - currentSCML = scml; - } //create the Spriter - var spriter:Spriter = new Spriter(id, currentSCML, _lib, info); + var spriter:Spriter = new Spriter(id, scml.copy(id), _lib, info); if (autoRemoval) { spriter.playAnim(removeSpriterEntity, true); } diff --git a/spriter/interfaces/ISpriterDestroyable.hx b/spriter/interfaces/ISpriterDestroyable.hx new file mode 100644 index 0000000..bf4541f --- /dev/null +++ b/spriter/interfaces/ISpriterDestroyable.hx @@ -0,0 +1,10 @@ +package spriter.interfaces; + +/** + * ... + * @author Loudo + */ +interface ISpriterDestroyable +{ + public function destroy():Void; +} \ No newline at end of file diff --git a/spriter/interfaces/ISpriterPooled.hx b/spriter/interfaces/ISpriterPooled.hx new file mode 100644 index 0000000..5863128 --- /dev/null +++ b/spriter/interfaces/ISpriterPooled.hx @@ -0,0 +1,12 @@ +package spriter.interfaces; + +import spriter.interfaces.ISpriterDestroyable; + +/** + * @flixel + */ +interface ISpriterPooled extends ISpriterDestroyable +{ + public function put():Void; + private var _inPool:Bool; +} \ No newline at end of file diff --git a/spriter/library/AbstractLibrary.hx b/spriter/library/AbstractLibrary.hx index 08d7a1f..7625c82 100644 --- a/spriter/library/AbstractLibrary.hx +++ b/spriter/library/AbstractLibrary.hx @@ -60,7 +60,7 @@ class AbstractLibrary var x2 = (preX - pivotX) * c - (preY - pivotY) * s + pivotX; var y2 = (preX - pivotX) * s + (preY - pivotY) * c + pivotY; - return new SpatialInfo(x2, -y2, degreesUnder360, info.scaleX, info.scaleY, info.a, info.spin);//TODO pool? + return SpatialInfo.get(x2, -y2, degreesUnder360, info.scaleX, info.scaleY, info.a, info.spin);//TODO pool? } public function computeRectCoordinates(info:SpatialInfo, pivots:PivotInfo, width:Float, height:Float):Quadrilateral diff --git a/spriter/library/TilelayerLibrary.hx b/spriter/library/TilelayerLibrary.hx index 8c8d63f..74f062d 100644 --- a/spriter/library/TilelayerLibrary.hx +++ b/spriter/library/TilelayerLibrary.hx @@ -62,18 +62,18 @@ class TilelayerLibrary extends AbstractLibrary var sprite:TileSprite = getFile(name); _layer.addChild(sprite); - var spatialResult:SpatialInfo = compute(info, pivots, sprite.width, sprite.height); + _currentSpatialResult = compute(info, pivots, sprite.width, sprite.height); //sprite.offset = getPivotsRelativeToCenter(info, pivots, sprite.width, sprite.height);//TOFIX tilelayer seems buggy - sprite.x = spatialResult.x; - sprite.y = spatialResult.y; - sprite.rotation = SpriterUtil.toRadians(SpriterUtil.fixRotation(spatialResult.angle)); - sprite.scaleX = spatialResult.scaleX; - sprite.scaleY = spatialResult.scaleY; - sprite.alpha = spatialResult.a; + sprite.x = _currentSpatialResult.x; + sprite.y = _currentSpatialResult.y; + sprite.rotation = SpriterUtil.toRadians(SpriterUtil.fixRotation(_currentSpatialResult.angle)); + sprite.scaleX = _currentSpatialResult.scaleX; + sprite.scaleY = _currentSpatialResult.scaleY; + sprite.alpha = _currentSpatialResult.a; - sprite.visible = true; + _currentSpatialResult.put();//back to pool } private function getPivotsRelativeToCenter(info:SpatialInfo, pivots:PivotInfo, width:Float, height:Float):Point @@ -100,7 +100,7 @@ class TilelayerLibrary extends AbstractLibrary var x2 = (preX - pivotX) * c - (preY - pivotY) * s + pivotX; var y2 = (preX - pivotX) * s + (preY - pivotY) * c + pivotY; - return new SpatialInfo(x2, -y2, degreesUnder360, info.scaleX, info.scaleY, info.a, info.spin); + return SpatialInfo.get(x2, -y2, degreesUnder360, info.scaleX, info.scaleY, info.a, info.spin); } override public function render():Void diff --git a/spriter/util/SpriterPool.hx b/spriter/util/SpriterPool.hx new file mode 100644 index 0000000..ef61555 --- /dev/null +++ b/spriter/util/SpriterPool.hx @@ -0,0 +1,84 @@ +package spriter.util; +import spriter.interfaces.ISpriterDestroyable; + +/** + * ... + * @author Loudo + * @author flixel + */ + /* +#if flixel +typedef TSpriterPool = flixel.util.FlxPool; +#elseif openfl +typedef TSpriterPool = SpriterPool +#elseif flambe + +#end +*/ + +/** + * A generic container that facilitates pooling and recycling of objects. + * WARNING: Pooled objects must have parameterless constructors: function new() + */ +class SpriterPool +{ + private var _pool:Array; + private var _class:Class; + + public var length(get, never):Int; + + public function new(classObj:Class) + { + _pool = []; + _class = classObj; + } + + public function get():T + { + var obj:T = _pool.pop(); + if (obj == null) + { + obj = Type.createInstance(_class, []); + } + return obj; + } + + public function put(obj:T):Void + { + // we don't want to have the same object in pool twice + if (obj != null && _pool.indexOf(obj) < 0) + { + obj.destroy(); + _pool.push(obj); + } + } + + public function putUnsafe(obj:T):Void + { + if (obj != null) + { + obj.destroy(); + _pool.push(obj); + } + } + + public function preAllocate(numObjects:Int):Void + { + for (i in 0...numObjects) + { + _pool.push(Type.createInstance(_class, [])); + } + } + + public function clear():Array + { + var oldPool = _pool; + _pool = []; + return oldPool; + } + + private inline function get_length():Int + { + return _pool.length; + } +} \ No newline at end of file