diff --git a/src/dragonBones/Armature.as b/src/dragonBones/Armature.as index cf24e70..89d39f4 100644 --- a/src/dragonBones/Armature.as +++ b/src/dragonBones/Armature.as @@ -1,138 +1,94 @@ -package dragonBones +package dragonBones { - - /** - * Copyright 2012-2013. DragonBones. All Rights Reserved. - * @playerversion Flash 10.0, Flash 10 - * @langversion 3.0 - * @version 2.0 - */ - import dragonBones.animation.Animation; + import dragonBones.animation.AnimationState; import dragonBones.animation.IAnimatable; + import dragonBones.animation.TimelineState; + import dragonBones.core.DBObject; + import dragonBones.core.dragonBones_internal; import dragonBones.events.ArmatureEvent; - import dragonBones.utils.dragonBones_internal; + import dragonBones.events.FrameEvent; + import dragonBones.events.SoundEvent; + import dragonBones.events.SoundEventManager; + import dragonBones.objects.DBTransform; + import dragonBones.objects.Frame; import flash.events.EventDispatcher; import flash.geom.ColorTransform; use namespace dragonBones_internal; + + /** + * Dispatched when a bone of the armature enters a frame. + */ + [Event(name="zOrderUpdated", type="dragonBones.events.ArmatureEvent")] /** - * Dispatched when the movement of animation is changed. + * Dispatched when an animation state of the animation begins fade in. */ - [Event(name="movementChange", type="dragonBones.events.AnimationEvent")] + [Event(name="fadeIn", type="dragonBones.events.AnimationEvent")] /** - * Dispatched when the playback of a animation starts. + * Dispatched when an animation state of the animation begins fade out. + */ + [Event(name="fadeOut", type="dragonBones.events.AnimationEvent")] + + /** + * Dispatched when an animation state of the animation starts. */ [Event(name="start", type="dragonBones.events.AnimationEvent")] /** - * Dispatched when the playback of a animation stops. + * Dispatched when an animation state of the animation completes. */ [Event(name="complete", type="dragonBones.events.AnimationEvent")] /** - * Dispatched when the playback of a animation completes a loop. + * Dispatched when an animation state of the animation completes a loop. */ [Event(name="loopComplete", type="dragonBones.events.AnimationEvent")] /** - * Dispatched when the animation of the armature enter a frame. + * Dispatched when an animation state of the animation completes fade in. */ - [Event(name="movementFrameEvent", type="dragonBones.events.FrameEvent")] + [Event(name="fadeInComplete", type="dragonBones.events.AnimationEvent")] /** - * Dispatched when a bone of the armature enters a frame. + * Dispatched when an animation state of the animation completes fade out. */ - [Event(name="boneFrameEvent", type="dragonBones.events.FrameEvent")] + [Event(name="fadeOutComplete", type="dragonBones.events.AnimationEvent")] + + /** + * Dispatched when an animation state of the animation enters a frame. + */ + [Event(name="animationFrameEvent", type="dragonBones.events.FrameEvent")] /** - * A Armature instance is the core of the skeleton animation system. It contains the object to display, all sub-bones and the object animation(s). - * @example - *

Download the example files here:

- *

This example builds an Armature instance called "dragon" and stores it into the member varaible called 'armature'.

- * - * package - * { - * import dragonBones.Armature; - * import dragonBones.factorys.BaseFactory; - * import flash.display.Sprite; - * import flash.events.Event; - * - * public class DragonAnimation extends Sprite - * { - * [Embed(source = "Dragon1.swf", mimeType = "application/octet-stream")] - * private static const ResourcesData:Class; - * - * private var factory:BaseFactory; - * private var armature:Armature; - * - * public function DragonAnimation() - * { - * factory = new BaseFactory(); - * factory.addEventListener(Event.COMPLETE, handleParseData); - * factory.parseData(new ResourcesData(), 'Dragon'); - * } - * - * private function handleParseData(e:Event):void - * { - * armature = factory.buildArmature('Dragon'); - * addChild(armature.display as Sprite); - * armature.animation.play(); - * addEventListener(Event.ENTER_FRAME, updateAnimation); - * } - * - * private function updateAnimation(e:Event):void - * { - * armature.advanceTime(1 / stage.frameRate); - * } - * } - * } - * - * @see dragonBones.Bone - * @see dragonBones.animation.Animation + * Dispatched when a bone of the armature enters a frame. */ + [Event(name="boneFrameEvent", type="dragonBones.events.FrameEvent")] + public class Armature extends EventDispatcher implements IAnimatable { + private static const _soundManager:SoundEventManager = SoundEventManager.getInstance(); + + private const _helpArray:Array = []; + /** - * The name of the Armature. + * The name of this DBObject instance's Armature instance. */ public var name:String; /** - * An object containing user data. + * An object that can contain any user extra data. */ public var userData:Object; /** @private */ - dragonBones_internal var _bonesIndexChanged:Boolean; + dragonBones_internal var _slotsZOrderChanged:Boolean; /** @private */ - dragonBones_internal var _boneDepthList:Vector.; - /** @private */ - protected var _rootBoneList:Vector.; - - /** @private */ - dragonBones_internal var _colorTransformChange:Boolean; - - /** @private */ - protected var _colorTransform:ColorTransform; - - + dragonBones_internal var _slotList:Vector.; /** @private */ - public function set colorTransform(value:ColorTransform):void - { - _colorTransform = value; - _colorTransformChange = true; - } - /** - * The ColorTransform instance assiociated with this instance. - * @param The ColorTransform instance assiociated with this Armature instance. - */ - public function get colorTransform():ColorTransform - { - return _colorTransform; - } + dragonBones_internal var _boneList:Vector.; /** @private */ protected var _display:Object; @@ -154,7 +110,6 @@ package dragonBones { return _animation; } - /** * Creates a Armature blank instance. @@ -162,79 +117,151 @@ package dragonBones */ public function Armature(display:Object) { - super(); + super(this); _display = display; - _boneDepthList = new Vector.; - _rootBoneList = new Vector.; - _animation = new Animation(this); - _bonesIndexChanged = false; + _slotsZOrderChanged = false; + + _slotList = new Vector.; + _slotList.fixed = true; + _boneList = new Vector.; + _boneList.fixed = true; } /** - * Cleans up resources used by this Armature instance. + * Cleans up any resources used by this DBObject instance. */ public function dispose():void { - for each(var bone:Bone in _rootBoneList) + if(!_animation) { - bone.dispose(); + return; } - _boneDepthList.length = 0; - _rootBoneList.length = 0; + userData = null; _animation.dispose(); + + for each(var slot:Slot in _slotList) + { + slot.dispose(); + } + + for each(var bone:Bone in _boneList) + { + bone.dispose(); + } + + _slotList.fixed = false; + _slotList.length = 0; + _boneList.fixed = false; + _boneList.length = 0; + _animation = null; + _slotList = null; + _boneList = null; //_display = null; + } + + /** + * Update the animation using this method typically in an ENTERFRAME Event or with a Timer. + * @param The amount of second to move the playhead ahead. + */ + public function advanceTime(passedTime:Number):void + { + _animation.advanceTime(passedTime); - userData = null; + var i:int = _boneList.length; + while(i --) + { + _boneList[i].update(); + } + + i = _slotList.length; + var slot:Slot; + while(i --) + { + slot = _slotList[i]; + slot.update(); + if(slot._isDisplayOnStage) + { + var childArmature:Armature = slot.childArmature; + if(childArmature) + { + childArmature.advanceTime(passedTime); + } + } + } - if(_colorTransform) + if(_slotsZOrderChanged) { - _colorTransform = null; + updateSlotsZOrder(); + + if(this.hasEventListener(ArmatureEvent.Z_ORDER_UPDATED)) + { + this.dispatchEvent(new ArmatureEvent(ArmatureEvent.Z_ORDER_UPDATED)); + } } } - + /** - * Retreives a Bone by name - * @param The name of the Bone to retreive. - * @return A Bone instance or null if no Bone with that name exist. + * Get all Slot instance associated with this armature. + * @return A Vector.<Slot> instance. + * @see dragonBones.Slot + */ + public function getSlots(returnCopy:Boolean = true):Vector. + { + return returnCopy?_slotList.concat():_slotList; + } + + /** + * Get all Bone instance associated with this armature. + * @return A Vector.<Bone> instance. * @see dragonBones.Bone */ - public function getBone(name:String):Bone + public function getBones(returnCopy:Boolean = true):Vector. + { + return returnCopy?_boneList.concat():_boneList; + } + + /** + * Retrieves a Slot by name + * @param The name of the Bone to retrieve. + * @return A Slot instance or null if no Slot with that name exist. + * @see dragonBones.Slot + */ + public function getSlot(slotName:String):Slot { - if(name) + var i:int = _slotList.length; + while(i --) { - for each(var bone:Bone in _boneDepthList) + if(_slotList[i].name == slotName) { - if(bone.name == name) - { - return bone; - } + return _slotList[i]; } } return null; } /** - * Gets the Bone assiociated with this DisplayObject. + * Gets the Slot associated with this DisplayObject. * @param Instance type of this object varies from flash.display.DisplayObject to startling.display.DisplayObject and subclasses. - * @return A bone instance. - * @see dragonBones.Bone + * @return A Slot instance. + * @see dragonBones.Slot */ - public function getBoneByDisplay(display:Object):Bone + public function getSlotByDisplay(display:Object):Slot { if(display) { - for each(var bone:Bone in _boneDepthList) + var i:int = _slotList.length; + while(i --) { - if(bone.display == display) + if(_slotList[i].display == display) { - return bone; + return _slotList[i]; } } } @@ -242,55 +269,99 @@ package dragonBones } /** - * Get all Bone instance assiociated with this armature. - * @return A Vector.<Bone> instance. - * @see dragonBones.Bone + * Remove a Slot instance from this Armature instance. + * @param The Slot instance to remove. + * @see dragonBones.Slot */ - public function getBones():Vector. + public function removeSlot(slot:Slot):void { - return _boneDepthList.concat(); + if(!slot) + { + throw new ArgumentError(); + } + + if(_slotList.indexOf(slot) >= 0) + { + slot.parent.removeChild(slot); + } + else + { + throw new ArgumentError(); + } } + /** - * Add a Bone instance to this Armature instance. - * @param A Bone instance - * @param (optional) The parent's name of this Bone instance. + * Remove a Slot instance from this Armature instance. + * @param The name of the Slot instance to remove. + * @see dragonBones.Slot + */ + public function removeSlotByName(slotName:String):void + { + if(!slotName) + { + return; + } + + var slot:Slot = getSlot(slotName); + if(slot) + { + removeSlot(slot); + } + } + + /** + * Retrieves a Bone by name + * @param The name of the Bone to retrieve. + * @return A Bone instance or null if no Bone with that name exist. * @see dragonBones.Bone */ - public function addBone(bone:Bone, parentName:String = null):void + public function getBone(boneName:String):Bone { - if (bone) + var i:int = _boneList.length; + while(i --) { - var boneParent:Bone = getBone(parentName); - if (boneParent) + if(_boneList[i].name == boneName) { - boneParent.addChild(bone); - } - else - { - bone.removeFromParent(); - addToBones(bone, true); + return _boneList[i]; } } + return null; } + /** - * Remove a Bone instance from this Armature instance. - * @param A Bone instance + * Gets the Bone associated with this DisplayObject. + * @param Instance type of this object varies from flash.display.DisplayObject to startling.display.DisplayObject and subclasses. + * @return A Bone instance. * @see dragonBones.Bone */ + public function getBoneByDisplay(display:Object):Bone + { + var slot:Slot = getSlotByDisplay(display); + return slot?slot.parent:null; + } + + /** + * Remove a Bone instance from this Armature instance. + * @param The Bone instance to remove. + * @see dragonBones.Bone + */ public function removeBone(bone:Bone):void { - if (bone) + if(!bone) { - if(bone.parent) - { - bone.removeFromParent(); - } - else - { - removeFromBones(bone); - } + throw new ArgumentError(); + } + + if(_boneList.indexOf(bone) >= 0) + { + bone.parent.removeChild(bone); + } + else + { + throw new ArgumentError(); } } + /** * Remove a Bone instance from this Armature instance. * @param The name of the Bone instance to remove. @@ -298,128 +369,205 @@ package dragonBones */ public function removeBoneByName(boneName:String):void { + if(!boneName) + { + return; + } + var bone:Bone = getBone(boneName); - removeBone(bone); + if(bone) + { + removeBone(bone); + } } + + /** - * Update the animation using this method typically in an ENTERFRAME Event or with a Timer. - * @param The amount of second to move the playhead ahead. + * Add a DBObject instance to this Armature instance. + * @param A DBObject instance + * @param (optional) The parent's name of this DBObject instance. + * @see dragonBones.core.DBObject */ - public function advanceTime(passedTime:Number):void + public function addChild(object:DBObject, parentName:String = null):void { - var i:int = _boneDepthList.length; - while(i --) + if(!object) { - var bone:Bone = _boneDepthList[i]; - if(bone._isOnStage) + throw new ArgumentError(); + } + + if(parentName) + { + var boneParent:Bone = getBone(parentName); + if (boneParent) { - var childArmature:Armature = bone.childArmature; - if(childArmature) - { - childArmature.advanceTime(passedTime); - } + boneParent.addChild(object); + } + else + { + throw new ArgumentError(); + } + } + else + { + if(object.parent) + { + object.parent.removeChild(object); } + object.setArmature(this); } - animation.advanceTime(passedTime); - update(); + } + + /** + * Add a Bone instance to this Armature instance. + * @param A Bone instance + * @param (optional) The parent's name of this Bone instance. + * @see dragonBones.Bone + */ + public function addBone(bone:Bone, parentName:String = null):void + { + addChild(bone, parentName); } /** * Update the z-order of the display. */ - public function updateBonesZ():void + public function updateSlotsZOrder():void { - _boneDepthList.sort(sortBoneZIndex); - for each(var bone:Bone in _boneDepthList) + _slotList.fixed = false; + _slotList.sort(sortSlot); + _slotList.fixed = true; + var i:int = _slotList.length; + var slot:Slot; + while(i --) { - if(bone._isOnStage) + slot = _slotList[i]; + if(slot._isDisplayOnStage) { - bone._displayBridge.addDisplay(_display); + slot._displayBridge.addDisplay(display); } } - _bonesIndexChanged = false; - if(hasEventListener(ArmatureEvent.Z_ORDER_UPDATED)) - { - dispatchEvent(new ArmatureEvent(ArmatureEvent.Z_ORDER_UPDATED)); - } + _slotsZOrderChanged = false; } /** @private */ - dragonBones_internal function update():void + dragonBones_internal function addDBObject(object:DBObject):void { - var i:int = _rootBoneList.length; - while(i --) + if(object is Slot) { - _rootBoneList[i].update(); + var slot:Slot = object as Slot; + if(_slotList.indexOf(slot) < 0) + { + _slotList.fixed = false; + _slotList[_slotList.length] = slot; + _slotList.fixed = true; + } } - - _colorTransformChange = false; - - if(_bonesIndexChanged) + else if(object is Bone) { - updateBonesZ(); + var bone:Bone = object as Bone; + if(_boneList.indexOf(bone) < 0) + { + _boneList.fixed = false; + _boneList[_boneList.length] = bone; + sortBoneList(); + _boneList.fixed = true; + } } } /** @private */ - dragonBones_internal function addToBones(bone:Bone, _root:Boolean = false):void + dragonBones_internal function removeDBObject(object:DBObject):void { - var boneIndex:int = _boneDepthList.indexOf(bone); - if(boneIndex < 0) + if(object is Slot) { - _boneDepthList.push(bone); + var slot:Slot = object as Slot; + var index:int = _slotList.indexOf(slot); + if(index >= 0) + { + _slotList.fixed = false; + _slotList.splice(index, 1); + _slotList.fixed = true; + } } - - boneIndex = _rootBoneList.indexOf(bone); - if(_root) + else if(object is Bone) { - if(boneIndex < 0) + var bone:Bone = object as Bone; + index = _boneList.indexOf(bone); + if(index >= 0) { - _rootBoneList.push(bone); + _boneList.fixed = false; + _boneList.splice(index, 1); + _boneList.fixed = true; } } - else if(boneIndex >= 0) + } + + /** @private */ + dragonBones_internal function sortBoneList():void + { + var i:int = _boneList.length; + if(i == 0) + { + return; + } + _helpArray.length = 0; + var level:int; + var bone:Bone; + var boneParent:Bone; + while(i --) { - _rootBoneList.splice(boneIndex, 1); + level = 0; + bone = _boneList[i]; + boneParent = bone; + while(boneParent) + { + level ++; + boneParent = boneParent.parent; + } + _helpArray[i] = {level:level, bone:bone}; } - bone._armature = this; - bone._displayBridge.addDisplay(_display, bone.global.z); - for each(var child:Bone in bone._children) + _helpArray.sortOn("level", Array.NUMERIC|Array.DESCENDING); + + i = _helpArray.length; + while(i --) { - addToBones(child); + _boneList[i] = _helpArray[i].bone; } - _bonesIndexChanged = true; + _helpArray.length = 0; } /** @private */ - dragonBones_internal function removeFromBones(bone:Bone):void + dragonBones_internal function arriveAtFrame(frame:Frame, timelineState:TimelineState, animationState:AnimationState, isCross:Boolean):void { - var boneIndex:int = _boneDepthList.indexOf(bone); - if(boneIndex >= 0) + if(frame.event && this.hasEventListener(FrameEvent.ANIMATION_FRAME_EVENT)) { - _boneDepthList.splice(boneIndex, 1); + var frameEvent:FrameEvent = new FrameEvent(FrameEvent.ANIMATION_FRAME_EVENT); + frameEvent.animationState = animationState; + frameEvent.frameLabel = frame.event; + this.dispatchEvent(frameEvent); } - boneIndex = _rootBoneList.indexOf(bone); - if(boneIndex >= 0) + if(frame.sound && _soundManager.hasEventListener(SoundEvent.SOUND)) { - _rootBoneList.splice(boneIndex, 1); + var soundEvent:SoundEvent = new SoundEvent(SoundEvent.SOUND); + soundEvent.armature = this; + soundEvent.animationState = animationState; + soundEvent.sound = frame.sound; + _soundManager.dispatchEvent(soundEvent); } - bone._armature = null; - bone._displayBridge.removeDisplay(); - for each(var child:Bone in bone._children) + if(frame.action && animationState.isPlaying) { - removeFromBones(child); + animation.gotoAndPlay(frame.action); } - _bonesIndexChanged = true; } - private function sortBoneZIndex(bone1:Bone, bone2:Bone):int + private function sortSlot(slot1:Slot, slot2:Slot):int { - return bone1.global.z >= bone2.global.z?1: -1; + return slot1.zOrder < slot2.zOrder?1: -1; } + } } \ No newline at end of file diff --git a/src/dragonBones/Bone.as b/src/dragonBones/Bone.as index ecbd321..26bafb2 100644 --- a/src/dragonBones/Bone.as +++ b/src/dragonBones/Bone.as @@ -1,477 +1,329 @@ package dragonBones { - /** - * Copyright 2012-2013. DragonBones. All Rights Reserved. - * @playerversion Flash 10.0 - * @langversion 3.0 - * @version 2.0 - */ + import dragonBones.animation.AnimationState; + import dragonBones.animation.TimelineState; + import dragonBones.core.DBObject; + import dragonBones.core.dragonBones_internal; + import dragonBones.events.FrameEvent; + import dragonBones.events.SoundEvent; + import dragonBones.events.SoundEventManager; + import dragonBones.objects.Frame; + import dragonBones.objects.TransformFrame; - import dragonBones.animation.Tween; - import dragonBones.display.IDisplayBridge; - import dragonBones.objects.BoneTransform; - import dragonBones.utils.dragonBones_internal; - - import flash.events.EventDispatcher; - import flash.geom.ColorTransform; - import flash.geom.Matrix; + import flash.geom.Point; use namespace dragonBones_internal; - - /** - * A Bone instance represents a single joint in an Armature instance. An Armature instance can be made up of many Bone instances. - * @example - *

Download the example files here:

- *

This example retrieves the Bone instance assiociated with the character's head and apply to its Display property an 0.5 alpha.

- * - * package - * { - * import dragonBones.Armature; - * import dragonBones.factorys.BaseFactory; - * import flash.display.Sprite; - * import flash.events.Event; - * - * public class DragonAnimation extends Sprite - * { - * [Embed(source = "Dragon1.swf", mimeType = "application/octet-stream")] - * private static const ResourcesData:Class; - * - * private var factory:BaseFactory; - * private var armature:Armature; - * - * public function DragonAnimation() - * { - * factory = new BaseFactory(); - * factory.addEventListener(Event.COMPLETE, handleParseData); - * factory.parseData(new ResourcesData(), 'Dragon'); - * } - * - * private function handleParseData(e:Event):void - * { - * armature = factory.buildArmature('Dragon'); - * addChild(armature.display as Sprite); - * armature.animation.play(); - * var bone:Bone = armature.getBone("head"); - * bone.display.alpha = 0.5;//make the DisplayObject belonging to this bone semi transparent. - * addEventListener(Event.ENTER_FRAME, updateAnimation); - * } - * - * private function updateAnimation(e:Event):void - * { - * armature.advanceTime(1 / stage.frameRate); - * } - * } - * } - * - * @see dragonBones.Bone - * @see dragonBones.animation.Animation - */ - public class Bone extends EventDispatcher + + public class Bone extends DBObject { - /** - * The name of this Bone instance's Armature instance. - */ - public var name:String; - /** - * An object that can contain any user extra data. - */ - public var userData:Object; - /** - * This Bone instance global Node instance. - * @see dragonBones.objects.Node - */ - public var global:BoneTransform; - /** - * This Bone instance origin Node Instance. - * @see dragonBones.objects.Node - */ - public var origin:BoneTransform; - /** - * This Bone instance Node Instance. - * @see dragonBones.objects.Node - */ - public var node:BoneTransform; + private static const _soundManager:SoundEventManager = SoundEventManager.getInstance(); + //0/1/2 + public var scaleMode:int; /** @private */ - dragonBones_internal var _tween:Tween; - /** @private */ - dragonBones_internal var _tweenNode:BoneTransform; - /** @private */ - dragonBones_internal var _tweenColorTransform:ColorTransform; - /** @private */ - dragonBones_internal var _visible:Boolean; - /** @private */ - dragonBones_internal var _children:Vector.; - /** @private */ - dragonBones_internal var _displayBridge:IDisplayBridge; - /** @private */ - dragonBones_internal var _isOnStage:Boolean; - /** @private */ - dragonBones_internal var _armature:Armature; - - private var _globalTransformMatrix:Matrix; - private var _displayList:Array; - private var _displayIndex:int; - private var _parent:Bone; - - private var _colorTransformChange:Boolean; - private var _colorTransform:ColorTransform; - private var _boneVisible:Object; - - /** - * @private - */ - public function set visible(value:Object):void - { - if(value == null) - { - _boneVisible = value; - } - else - { - _boneVisible = Boolean(value); - } - } - - /** - * Whether this Bone instance and its associated DisplayObject are visible or not (true/false/null). null means that the visible will be controled by animation data. - * - */ - public function get visible():Object - { - return _boneVisible; - } + dragonBones_internal var _tweenPivot:Point; - /** - * @private - */ - public function set colorTransform(value:ColorTransform):void - { - _colorTransform = value; - _colorTransformChange = true; - } + private var _children:Vector.; + private var _slot:Slot; /** - * The ColorTransform instance assiociated with this Bone instance. null means that the ColorTransform will be controled by animation data. + * The default Slot of this Bone instance. */ - public function get colorTransform():ColorTransform + public function get slot():Slot { - return _colorTransform; + return _slot; } /** - * The armature this Bone instance belongs to. - */ - public function get armature():Armature - { - return _armature; - } - - /** - * The sub-armature of this Bone instance. + * The sub-armature of default Slot of this Bone instance. */ public function get childArmature():Armature { - return _displayList[_displayIndex] as Armature; - } - - /** - * Indicates the Bone instance that directly contains this Bone instance if any. - */ - public function get parent():Bone - { - return _parent; + return _slot?_slot.childArmature:null; } /** - * The DisplayObject belonging to this Bone instance. Instance type of this object varies from flash.display.DisplayObject to startling.display.DisplayObject and subclasses. + * The DisplayObject of default Slot of this Bone instance. */ public function get display():Object { - return _displayBridge.display; + return _slot?_slot.display:null; } public function set display(value:Object):void { - if(_displayBridge.display == value) + if(_slot) { - return; - } - _displayList[_displayIndex] = value; - if(value is Armature) - { - value = (value as Armature).display; + _slot.display = value; } - _displayBridge.display = value; } - - /** - * The DisplayObject list belonging to this Bone instance. - */ - public function get displayList():Array + private var _displayController:String; + public function get displayController():String + { + return _displayController; + } + public function set displayController(value:String):void { - return _displayList; + _displayController = value; } - /** @private */ - dragonBones_internal function changeDisplay(displayIndex:int):void + /** + * @inheritDoc + */ + override public function set visible(value:Boolean):void { - var childArmature:Armature = this.childArmature; - if(displayIndex < 0) + if(this._visible != value) { - if(_isOnStage) + this._visible = value; + var i:int = _children.length; + while(i --) { - _isOnStage = false; - //removeFromStage - _displayBridge.removeDisplay(); - - if(childArmature) + var slot:Slot = _children[i] as Slot; + if(slot) { - childArmature.animation.stop(); - childArmature.animation.clearMovement(); + slot.updateVisible(this._visible); } } } - else + } + + /** @private */ + override dragonBones_internal function setArmature(value:Armature):void + { + super.setArmature(value); + var i:int = _children.length; + while(i --) { - if(!_isOnStage) - { - _isOnStage = true; - //addToStage - if(_armature) - { - _displayBridge.addDisplay(_armature.display, global.z); - _armature._bonesIndexChanged = true; - } - } - if(_displayIndex != displayIndex) - { - var length:uint = _displayList.length; - if(displayIndex >= length && length > 0) - { - displayIndex = length - 1; - } - _displayIndex = displayIndex; - - //change - display = _displayList[_displayIndex]; - } - - if(childArmature) - { - childArmature.animation.play(); - } + _children[i].setArmature(this._armature); } } - /** - * Creates a new Bone instance and attaches to it a IDisplayBridge instance. - * @param dragonBones.display.IDisplayBridge - */ - public function Bone(displayBrideg:IDisplayBridge) + public function Bone() { - origin = new BoneTransform(); - origin.scaleX = 1; - origin.scaleY = 1; - global = new BoneTransform(); - node = new BoneTransform(); - _displayBridge = displayBrideg; - _children = new Vector.; - _globalTransformMatrix = new Matrix(); - _displayList = []; - _displayIndex = -1; - _visible = true; - _tweenNode = new BoneTransform(); - _tweenColorTransform = new ColorTransform(); - _tween = new Tween(this); + super(); + _children = new Vector.(0, true); + _scaleType = 2; + + _tweenPivot = new Point(); + + scaleMode = 1; } + /** - * Change all DisplayObject attached to this Bone instance. - * @param displayList An array of valid DisplayObject to attach to this Bone. + * @inheritDoc */ - public function changeDisplayList(displayList:Array):void + override public function dispose():void { - var indexBackup:int = _displayIndex; - var length:uint = displayList.length; - _displayList.length = length; - for(var i:int = 0;i < length;i ++) + if(!_children) + { + return; + } + super.dispose(); + + var i:int = _children.length; + while(i --) { - changeDisplay(i); - display = displayList[i]; - } - changeDisplay(indexBackup); + _children[i].dispose(); + } + _children.fixed = false; + _children.length = 0; + + _children = null; + _slot = null; + _tweenPivot = null; } - /** - * Cleans up any resources used by this Bone instance. - */ - public function dispose():void + public function contains(child:DBObject):Boolean { - for each(var _child:Bone in _children) + if(!child) { - _child.dispose(); - } - _displayList.length = 0; - _children.length = 0; - _armature = null; - _parent = null; - userData = null; - } - /** - * Returns true if the passed Bone Instance is a child of this Bone instance (deepLevel false) or true if the passed Bone instance is in the child hierarchy of this Bone instance (deepLevel true) false otherwise. - * @param deepLevel Check against child heirarchy. - * @return - */ - public function contains(bone:Bone, deepLevel:Boolean = false):Boolean - { - if(deepLevel) + throw new ArgumentError(); + } + if(child == this) { - var ancestor:Bone = this; - while (ancestor != bone && ancestor != null) - { - ancestor = ancestor.parent; - } - if (ancestor == bone) - { - return true; - } return false; - } - return bone.parent == this; + } + var ancestor:DBObject = child; + while (!(ancestor == this || ancestor == null)) + { + ancestor = ancestor.parent; + } + return ancestor == this; } - /** @private */ - public function addChild(child:Bone):void + public function addChild(child:DBObject):void { - if (_children.length > 0?(_children.indexOf(child) < 0):true) + if(!child) { - child.removeFromParent(); - - _children.push(child); - child.setParent(this); - - if (_armature) - { - _armature.addToBones(child); - } + throw new ArgumentError(); + } + + var bone:Bone = child as Bone; + if(child == this || (bone && bone.contains(this))) + { + throw new ArgumentError("An Bone cannot be added as a child to itself or one of its children (or children's children, etc.)"); + } + + if(child.parent) + { + child.parent.removeChild(child); + } + _children.fixed = false; + _children[_children.length] = child; + _children.fixed = true; + child.setParent(this); + child.setArmature(this._armature); + + if(!_slot && child is Slot) + { + _slot = child as Slot; } } - /** @private */ - public function removeChild(child:Bone):void + public function removeChild(child:DBObject):void { + if(!child) + { + throw new ArgumentError(); + } + var index:int = _children.indexOf(child); if (index >= 0) { - if (_armature) + _children.fixed = false; + _children.splice(index, 1); + _children.fixed = true; + child.setParent(null); + child.setArmature(null); + + if(_slot && child == _slot) { - _armature.removeFromBones(child); + _slot = null; } - child.setParent(null); - _children.splice(index, 1); + + if(this._armature) + { + this._armature.removeDBObject(child); + } + } + else + { + throw new ArgumentError(); } } - /** @private */ - public function removeFromParent():void + /** + * Get all Slot instance associated with this bone. + * @return A Vector.<Slot> instance. + * @see dragonBones.Slot + */ + public function getSlots():Vector. { - if(_parent) + var slotList:Vector. = new Vector.; + var i:int = _children.length; + while(i --) { - _parent.removeChild(this); + if(_children[i] is Slot) + { + slotList.unshift(_children[i]); + } } + return slotList; } /** @private */ - dragonBones_internal function update():void + dragonBones_internal function arriveAtFrame(frame:Frame, timelineState:TimelineState, animationState:AnimationState, isCross:Boolean):void { - //transform - if(_parent) - { - var x:Number = origin.x + node.x + _tweenNode.x; - var y:Number = origin.y + node.y + _tweenNode.y; - var parentMatrix:Matrix = _parent._globalTransformMatrix; - _globalTransformMatrix.tx = global.x = parentMatrix.a * x + parentMatrix.c * y + parentMatrix.tx; - _globalTransformMatrix.ty = global.y = parentMatrix.d * y + parentMatrix.b * x + parentMatrix.ty; - global.skewX = _parent.global.skewX + origin.skewX + node.skewX + _tweenNode.skewX; - global.skewY = _parent.global.skewY + origin.skewY + node.skewY + _tweenNode.skewY; - } - else - { - _globalTransformMatrix.tx = global.x = origin.x + node.x + _tweenNode.x; - _globalTransformMatrix.ty = global.y = origin.y + node.y + _tweenNode.y; - global.skewX = origin.skewX + node.skewX + _tweenNode.skewX; - global.skewY = origin.skewY + node.skewY + _tweenNode.skewY; - } - - //update global - global.scaleX = origin.scaleX + node.scaleX + _tweenNode.scaleX; - global.scaleY = origin.scaleY + node.scaleY + _tweenNode.scaleY; - global.pivotX = origin.pivotX + node.pivotX + _tweenNode.pivotX; - global.pivotY = origin.pivotY + node.pivotY + _tweenNode.pivotY; - global.z = origin.z + node.z + _tweenNode.z; - - //Note: this formula of transform is defined by Flash pro - _globalTransformMatrix.a = global.scaleX * Math.cos(global.skewY); - _globalTransformMatrix.b = global.scaleX * Math.sin(global.skewY); - _globalTransformMatrix.c = -global.scaleY * Math.sin(global.skewX); - _globalTransformMatrix.d = global.scaleY * Math.cos(global.skewX); - - //update children - if (_children.length > 0) + if(frame) { - var i:int = _children.length; - while(i --) + var mixingType:int = animationState.getMixingTransform(name); + if(animationState.displayControl && (mixingType == 2 || mixingType == -1)) { - _children[i].update(); + if( + !_displayController || _displayController == animationState.name + ) + { + var tansformFrame:TransformFrame = frame as TransformFrame; + if(_slot) + { + var displayIndex:int = tansformFrame.displayIndex; + if(displayIndex >= 0) + { + if(!isNaN(tansformFrame.zOrder) && tansformFrame.zOrder != _slot._tweenZorder) + { + _slot._tweenZorder = tansformFrame.zOrder; + this._armature._slotsZOrderChanged = true; + } + } + _slot.changeDisplay(displayIndex); + _slot.updateVisible(tansformFrame.visible); + } + } } - } - - var childArmature:Armature = this.childArmature; - if(childArmature) - { - childArmature.update(); - } - - var currentDisplay:Object = _displayBridge.display; - //update display - if(currentDisplay) - { - //currentColorTransform - var currentColorTransform:ColorTransform; - if(_tween._differentColorTransform) + if(frame.event && this._armature.hasEventListener(FrameEvent.BONE_FRAME_EVENT)) { - if(_colorTransform) - { - _tweenColorTransform.concat(_colorTransform); - } - if(_armature.colorTransform) + var frameEvent:FrameEvent = new FrameEvent(FrameEvent.BONE_FRAME_EVENT); + frameEvent.bone = this; + frameEvent.animationState = animationState; + frameEvent.frameLabel = frame.event; + this._armature.dispatchEvent(frameEvent); + } + + if(frame.sound && _soundManager.hasEventListener(SoundEvent.SOUND)) + { + var soundEvent:SoundEvent = new SoundEvent(SoundEvent.SOUND); + soundEvent.armature = this._armature; + soundEvent.animationState = animationState; + soundEvent.sound = frame.sound; + _soundManager.dispatchEvent(soundEvent); + } + + if(frame.action) + { + var childArmature:Armature = this.childArmature; + if(childArmature) { - _tweenColorTransform.concat(_armature.colorTransform); + childArmature.animation.gotoAndPlay(frame.action); } - currentColorTransform = _tweenColorTransform; } - else if(_armature._colorTransformChange || _colorTransformChange) + } + else + { + if(_slot) { - currentColorTransform = _colorTransform || _armature.colorTransform; - _colorTransformChange = false; + _slot.changeDisplay(-1); } - _displayBridge.update(_globalTransformMatrix, global, currentColorTransform, (_boneVisible != null)?_boneVisible:_visible); } } - private function setParent(parent:Bone):void + /** @private */ + dragonBones_internal function updateColor( + aOffset:Number, + rOffset:Number, + gOffset:Number, + bOffset:Number, + aMultiplier:Number, + rMultiplier:Number, + gMultiplier:Number, + bMultiplier:Number, + isColorChanged:Boolean + ):void { - if (parent && parent.contains(this, true)) + if(isColorChanged || _isColorChanged) { - throw new ArgumentError("An Bone cannot be added as a child to itself or one of its children (or children's children, etc.)"); + _slot._displayBridge.updateColor( + aOffset, + rOffset, + gOffset, + bOffset, + aMultiplier, + rMultiplier, + gMultiplier, + bMultiplier + ); } - _parent = parent; - - if(_parent) - { - _isOnStage = _parent._isOnStage; - } + _isColorChanged = isColorChanged; } } -} +} \ No newline at end of file diff --git a/src/dragonBones/Slot.as b/src/dragonBones/Slot.as new file mode 100644 index 0000000..31ebed1 --- /dev/null +++ b/src/dragonBones/Slot.as @@ -0,0 +1,326 @@ +package dragonBones +{ + import dragonBones.core.DBObject; + import dragonBones.core.dragonBones_internal; + import dragonBones.display.IDisplayBridge; + import dragonBones.objects.DisplayData; + + import flash.geom.Matrix; + + use namespace dragonBones_internal; + + public class Slot extends DBObject + { + /** @private */ + dragonBones_internal var _dislayDataList:Vector.; + /** @private */ + dragonBones_internal var _displayBridge:IDisplayBridge; + /** @private */ + dragonBones_internal var _originZOrder:Number; + /** @private */ + dragonBones_internal var _tweenZorder:Number; + /** @private */ + dragonBones_internal var _isDisplayOnStage:Boolean; + + private var _isHideDisplay:Boolean; + private var _offsetZOrder:Number; + private var _displayIndex:int; + + public function get zOrder():Number + { + return _originZOrder + _tweenZorder + _offsetZOrder; + } + + public function set zOrder(value:Number):void + { + if(zOrder != value) + { + _offsetZOrder = value - _originZOrder - _tweenZorder; + if(this._armature) + { + this._armature._slotsZOrderChanged = true; + } + } + } + + /** + * The DisplayObject belonging to this Bone instance. Instance type of this object varies from flash.display.DisplayObject to startling.display.DisplayObject and subclasses. + */ + public function get display():Object + { + var display:Object = _displayList[_displayIndex]; + if(display is Armature) + { + return display.display; + } + return display; + } + public function set display(value:Object):void + { + _displayList[_displayIndex] = value; + setDisplay(value); + } + + /** + * The sub-armature of this Slot instance. + */ + public function get childArmature():Armature + { + return _displayList[_displayIndex] as Armature; + } + public function set childArmature(value:Armature):void + { + _displayList[_displayIndex] = value; + if(value) + { + setDisplay(value.display); + } + } + + private var _displayList:Array; + /** + * The DisplayObject list belonging to this Slot instance. + */ + public function get displayList():Array + { + return _displayList; + } + public function set displayList(value:Array):void + { + if(!value) + { + throw new ArgumentError(); + } + var i:int = _displayList.length = value.length; + while(i --) + { + _displayList[i] = value[i]; + } + + if(_displayIndex >= 0) + { + _displayIndex = -1; + changeDisplay(_displayIndex); + } + } + + private function setDisplay(display:Object):void + { + if(_displayBridge.display) + { + _displayBridge.display = display; + } + else + { + _displayBridge.display = display; + if(this._armature) + { + _displayBridge.addDisplay(this._armature.display); + this._armature._slotsZOrderChanged = true; + } + } + + updateChildArmatureAnimation(); + + if(!_isHideDisplay && _displayBridge.display) + { + _isDisplayOnStage = true; + } + else + { + _isDisplayOnStage = false; + } + } + + /** @private */ + dragonBones_internal function changeDisplay(displayIndex:int):void + { + if(displayIndex < 0) + { + if(!_isHideDisplay) + { + _isHideDisplay = true; + _displayBridge.removeDisplay(); + updateChildArmatureAnimation(); + } + } + else + { + if(_isHideDisplay) + { + _isHideDisplay = false; + var changeShowState:Boolean = true; + if(this._armature) + { + _displayBridge.addDisplay(this._armature.display); + this._armature._slotsZOrderChanged = true; + } + } + + var length:uint = _displayList.length; + if(displayIndex >= length && length > 0) + { + displayIndex = length - 1; + } + if(_displayIndex != displayIndex) + { + _displayIndex = displayIndex; + + var content:Object = _displayList[_displayIndex]; + if(content is Armature) + { + setDisplay((content as Armature).display); + } + else + { + setDisplay(content); + } + + if(_dislayDataList && _displayIndex <= _dislayDataList.length) + { + this._origin.copy(_dislayDataList[_displayIndex].transform); + } + } + else if(changeShowState) + { + updateChildArmatureAnimation(); + } + } + + if(!_isHideDisplay && _displayBridge.display) + { + _isDisplayOnStage = true; + } + else + { + _isDisplayOnStage = false; + } + } + + /** + * @inheritDoc + */ + override public function set visible(value:Boolean):void + { + if(value != this._visible) + { + this._visible = value; + updateVisible(this._visible); + } + } + + /** @private */ + override dragonBones_internal function setArmature(value:Armature):void + { + super.setArmature(value); + if(this._armature) + { + this._armature._slotsZOrderChanged = true; + _displayBridge.addDisplay(this._armature.display); + } + else + { + _displayBridge.removeDisplay(); + } + } + + public function Slot(displayBrideg:IDisplayBridge) + { + super(); + _displayBridge = displayBrideg; + _displayList = []; + _displayIndex = -1; + _scaleType = 1; + + _originZOrder = 0; + _tweenZorder = 0; + _offsetZOrder = 0; + + _isDisplayOnStage = false; + _isHideDisplay = false; + } + + /** + * @inheritDoc + */ + override public function dispose():void + { + if(!_displayBridge) + { + return; + } + super.dispose(); + + _displayBridge.dispose(); + _displayList.length = 0; + + _displayBridge = null; + _displayList = null; + _dislayDataList = null; + } + + /** @private */ + override dragonBones_internal function update():void + { + super.update(); + + if(_isDisplayOnStage) + { + var pivotX:Number = _parent._tweenPivot.x; + var pivotY:Number = _parent._tweenPivot.y; + if(pivotX || pivotY) + { + var parentMatrix:Matrix = _parent._globalTransformMatrix; + this._globalTransformMatrix.tx += parentMatrix.a * pivotX + parentMatrix.c * pivotY; + this._globalTransformMatrix.ty += parentMatrix.b * pivotX + parentMatrix.d * pivotY; + } + + _displayBridge.updateTransform(this._globalTransformMatrix, this._global); + } + } + + /** @private */ + dragonBones_internal function updateVisible(value:Boolean):void + { + _displayBridge.visible = this._parent.visible && this._visible && value; + } + + private function updateChildArmatureAnimation():void + { + var childArmature:Armature = this.childArmature; + + if(childArmature) + { + if(_isHideDisplay) + { + childArmature.animation.stop(); + childArmature.animation._lastAnimationState = null; + } + else + { + if( + this._armature && + this._armature.animation.lastAnimationState && + childArmature.animation.hasAnimation(this._armature.animation.lastAnimationState.name) + ) + { + childArmature.animation.gotoAndPlay(this._armature.animation.lastAnimationState.name); + } + else + { + childArmature.animation.play(); + } + } + } + } + + /** + * Change all DisplayObject attached to this Bone instance. + * @param displayList An array of valid DisplayObject to attach to this Bone. + */ + public function changeDisplayList(displayList:Array):void + { + this.displayList = displayList; + } + } +} \ No newline at end of file diff --git a/src/dragonBones/animation/Animation.as b/src/dragonBones/animation/Animation.as index 0ad177c..9b6cfc6 100644 --- a/src/dragonBones/animation/Animation.as +++ b/src/dragonBones/animation/Animation.as @@ -1,22 +1,18 @@ package dragonBones.animation { /** - * Copyright 2012-2013. DragonBones. All Rights Reserved. - * @playerversion Flash 10.0 - * @langversion 3.0 - * @version 2.0 - */ + * Copyright 2012-2013. DragonBones. All Rights Reserved. + * @playerversion Flash 10.0 + * @langversion 3.0 + * @version 2.0 + */ import dragonBones.Armature; import dragonBones.Bone; - import dragonBones.events.AnimationEvent; - import dragonBones.events.FrameEvent; - import dragonBones.events.SoundEvent; - import dragonBones.events.SoundEventManager; + import dragonBones.core.dragonBones_internal; import dragonBones.objects.AnimationData; - import dragonBones.objects.MovementBoneData; - import dragonBones.objects.MovementData; - import dragonBones.objects.MovementFrameData; - import dragonBones.utils.dragonBones_internal; + import dragonBones.objects.DBTransform; + + import flash.geom.Point; use namespace dragonBones_internal; @@ -28,21 +24,21 @@ * package * { * import dragonBones.Armature; - * import dragonBones.factorys.BaseFactory; + * import dragonBones.factorys.NativeFactory; * import flash.display.Sprite; * import flash.events.Event; - * + * * public class DragonAnimation extends Sprite * { * [Embed(source = "Dragon1.swf", mimeType = "application/octet-stream")] * private static const ResourcesData:Class; * - * private var factory:BaseFactory; + * private var factory:NativeFactory; * private var armature:Armature; * * public function DragonAnimation() * { - * factory = new BaseFactory(); + * factory = new NativeFactory(); * factory.addEventListener(Event.COMPLETE, handleParseData); * factory.parseData(new ResourcesData(), 'Dragon'); * } @@ -57,122 +53,123 @@ * * private function updateAnimation(e:Event):void * { - * armature.advanceTime(1 / stage.frameRate); + * armature.advanceTime(stage.frameRate / 1000); * } * } * } * - * @see dragonBones.Bone * @see dragonBones.Armature + * @see dragonBones.animation.Animation + * @see dragonBones.animation.AnimationState */ - final public class Animation - {/** - * @private - */ - internal static const SINGLE:int = 0; - /** - * @private - */ - internal static const LIST_START:int = 1; - /** - * @private - */ - internal static const LOOP_START:int = 2; - /** - * @private - */ - internal static const LIST:int = 3; - /** - * @private - */ - internal static const LOOP:int = 4; - private static var _soundManager:SoundEventManager = SoundEventManager.getInstance(); + public class Animation + { + public static const NONE:String = "none"; + public static const SAME_LAYER:String = "sameLayer"; + public static const SAME_GROUP:String = "sameGroup"; + public static const SAME_LAYER_AND_GROUP:String = "sameLayerAndGroup"; + public static const ALL:String = "all"; + /** * Whether animation tweening is enabled or not. */ - public var tweenEnabled:Boolean = true; + public var tweenEnabled:Boolean; + + /** @private */ + dragonBones_internal var _animationLayer:Vector.>; - private var _playType:int; - private var _duration:Number; - private var _rawDuration:Number; - private var _nextFrameDataTimeEdge:Number; - private var _nextFrameDataID:int; - private var _loop:int; - private var _breakFrameWhile:Boolean; private var _armature:Armature; - private var _movementData:MovementData; - private var _animationData:AnimationData; + private var _isPlaying:Boolean; /** - * The AnimationData assiociated with this Animation instance. + * An vector containing all AnimationData names the Animation can play. * @see dragonBones.objects.AnimationData. */ - public function get animationData():AnimationData + public function get movementList():Vector. { - return _animationData; + return _animationList; } + /** - * @private + * The name of the last AnimationData played. + * @see dragonBones.objects.AnimationData. */ - public function set animationData(value:AnimationData):void + public function get movementID():String { - if (value) - { - stop(); - _animationData = value; - } + return _lastAnimationState?_lastAnimationState.name:null; } - private var _currentTime:Number; + dragonBones_internal var _lastAnimationState:AnimationState; /** - * Get the current playhead time in seconds. + * The last AnimationData this Animation played. + * @see dragonBones.objects.AnimationData. */ - public function get currentTime():Number + public function get lastAnimationState():AnimationState { - return _currentTime; + return _lastAnimationState; } - private var _totalTime:Number; + private var _animationList:Vector.; /** - * Get the total elapsed time in second. + * An vector containing all AnimationData names the Animation can play. + * @see dragonBones.objects.AnimationData. */ - public function get totalTime():Number + public function get animationList():Vector. { - return _totalTime; + return _animationList; } - private var _isPlaying:Boolean; - - /** - * Indicates whether the animation is playing or not. - */ public function get isPlaying():Boolean { - if (_isPlaying) + return _isPlaying && !isComplete; + } + + public function get isComplete():Boolean + { + if(_lastAnimationState) { - return _loop >= 0 || _currentTime < _totalTime; + if(!_lastAnimationState.isComplete) + { + return false; + } + var j:int = _animationLayer.length; + while(j --) + { + var animationStateList:Vector. = _animationLayer[j]; + var i:int = animationStateList.length; + while(i --) + { + if(!animationStateList[i].isComplete) + { + return false; + } + } + } + return true; } return false; } + private var _animationDataList:Vector.; /** - * Indicates whether the animation has completed or not. + * The AnimationData list associated with this Animation instance. + * @see dragonBones.objects.AnimationData. */ - public function get isComplete():Boolean + public function get animationDataList():Vector. { - return _loop < 0 && _currentTime >= _totalTime; + return _animationDataList; } - - /** - * Indicates whether the animation is paused or not. - */ - public function get isPause():Boolean + public function set animationDataList(value:Vector.):void { - return !_isPlaying; + _animationDataList = value; + _animationList.length = 0; + for each(var animationData:AnimationData in _animationDataList) + { + _animationList[_animationList.length] = animationData.name; + } } private var _timeScale:Number = 1; - /** * The amount by which passed time should be scaled. Used to slow down or speed up animations. Defaults to 1. */ @@ -180,9 +177,6 @@ { return _timeScale; } - /** - * @private - */ public function set timeScale(value:Number):void { if (value < 0) @@ -190,153 +184,195 @@ value = 0; } _timeScale = value; - - for each (var bone:Bone in _armature._boneDepthList) - { - if (bone.childArmature) - { - bone.childArmature.animation.timeScale = _timeScale; - } - } - } - - private var _movementID:String; - - /** - * The name ID of the current MovementData. - * @see dragonBones.objects.MovementData. - */ - public function get movementID():String - { - return _movementID; - } - - /** - * An vector containing all MovementData names the animation can play. - * @see dragonBones.objects.MovementData. - */ - public function get movementList():Vector. - { - return _animationData ? _animationData.movementList : null; } /** - * Creates a new Animation instance and attaches it to the passed Arnature. + * Creates a new Animation instance and attaches it to the passed Armature. * @param An Armature to attach this Animation instance to. */ public function Animation(armature:Armature) { _armature = armature; + _animationLayer = new Vector.>; + _animationList = new Vector.; + + tweenEnabled = true; } + /** * Qualifies all resources used by this Animation instance for garbage collection. */ public function dispose():void { + if(!_armature) + { + return; + } stop(); - _animationData = null; - _movementData = null; + var i:int = _animationLayer.length; + while(i --) + { + var animationStateList:Vector. = _animationLayer[i]; + var j:int = animationStateList.length; + while(j --) + { + AnimationState.returnObject(animationStateList[j]); + } + animationStateList.length = 0; + } + _animationLayer.length = 0; + _animationList.length = 0; + _armature = null; + _animationLayer = null; + _animationDataList = null; + _animationList = null; } + /** - * Move the playhead to that MovementData id - * @param The id of the MovementData to play. - * @param A tween time to apply (> 0) - * @param The duration in seconds of that MovementData. - * @param Whether that MovementData should loop or play only once (true/false). - * @see dragonBones.objects.MovementData. + * Move the playhead to that AnimationData + * @param animationName The name of the AnimationData to play. + * @param fadeInTime A fade time to apply (> 0) + * @param duration The duration of that AnimationData. + * @param loop Loop(0:loop forever, 1~+∞:loop times, -1~-∞:will fade animation after loop complete). + * @param layer The layer of the animation. + * @param fadeOutMode Fade out mode. + * @param displayControl Display control. + * @param pauseFadeOut Pause other animation playing. + * @param pauseFadeIn Pause this animation playing before fade in complete. + * @see dragonBones.objects.AnimationData. + * @see dragonBones.animation.AnimationState. */ - public function gotoAndPlay(movementID:String, tweenTime:Number = -1, duration:Number = -1, loop:* = null):void + public function gotoAndPlay( + animationName:String, + fadeInTime:Number = -1, + duration:Number = -1, + loop:Number = NaN, + layer:uint = 0, + group:String = null, + fadeOutMode:String = SAME_LAYER_AND_GROUP, + displayControl:Boolean = true, + pauseFadeOut:Boolean = true, + pauseFadeIn:Boolean = true + ):AnimationState { - if (!_animationData) + if (!_animationDataList) { - return; + return null; } - var movementData:MovementData = _animationData.getMovementData(movementID as String); - if (!movementData) + var i:int = _animationDataList.length; + var animationData:AnimationData; + while(i --) { - return; + if(_animationDataList[i].name == animationName) + { + animationData = _animationDataList[i]; + break; + } + } + if (!animationData) + { + return null; } - _movementData = movementData; + _isPlaying = true; - _currentTime = 0; - _breakFrameWhile = true; - var exMovementID:String = _movementID; - _movementID = movementID as String; + // + fadeInTime = fadeInTime < 0?(animationData.fadeInTime < 0?0.3:animationData.fadeInTime):fadeInTime; - if (tweenTime >= 0) - { - _totalTime = tweenTime; - } - else if (tweenEnabled && exMovementID) + var durationScale:Number; + if(duration < 0) { - _totalTime = _movementData.durationTo; + durationScale = animationData.scale < 0?1:animationData.scale; } else { - _totalTime = 0; + durationScale = duration / animationData.duration; } - if (_totalTime < 0) - { - _totalTime = 0; - } + loop = isNaN(loop)?animationData.loop:loop; + layer = addLayer(layer); - _duration = duration >= 0 ? duration : _movementData.durationTween; - if (_duration < 0) + //autoSync = autoSync && !pauseFadeOut && !pauseFadeIn; + var animationState:AnimationState; + var animationStateList:Vector.; + switch(fadeOutMode) { - _duration = 0; + case NONE: + break; + case SAME_LAYER: + animationStateList = _animationLayer[layer]; + i = animationStateList.length; + while(i --) + { + animationState = animationStateList[i]; + animationState.fadeOut(fadeInTime, pauseFadeOut); + } + break; + case SAME_GROUP: + j = _animationLayer.length; + while(j --) + { + animationStateList = _animationLayer[j]; + i = animationStateList.length; + while(i --) + { + animationState = animationStateList[i]; + if(animationState.group == group) + { + animationState.fadeOut(fadeInTime, pauseFadeOut); + } + } + } + break; + case ALL: + var j:int = _animationLayer.length; + while(j --) + { + animationStateList = _animationLayer[j]; + i = animationStateList.length; + while(i --) + { + animationState = animationStateList[i]; + animationState.fadeOut(fadeInTime, pauseFadeOut); + } + } + break; + case SAME_LAYER_AND_GROUP: + default: + animationStateList = _animationLayer[layer]; + i = animationStateList.length; + while(i --) + { + animationState = animationStateList[i]; + if(animationState.group == group) + { + animationState.fadeOut(fadeInTime, pauseFadeOut); + } + } + break; } - loop = Boolean(loop === null ? _movementData.loop : loop); - _rawDuration = _movementData.duration; + _lastAnimationState = AnimationState.borrowObject(); + _lastAnimationState.group = group; + _lastAnimationState.tweenEnabled = tweenEnabled; + _lastAnimationState.fadeIn(_armature, animationData, fadeInTime, 1 / durationScale, loop, layer, displayControl, pauseFadeIn); - _loop = loop ? 0 : -1; - if (_rawDuration == 0) - { - _playType = SINGLE; - } - else - { - _nextFrameDataTimeEdge = 0; - _nextFrameDataID = 0; - if (loop) - { - _playType = LOOP_START; - } - else - { - _playType = LIST_START; - } - } - - var tweenEasing:Number = _movementData.tweenEasing; + addState(_lastAnimationState); - for each (var bone:Bone in _armature._boneDepthList) + var boneList:Vector. = _armature._boneList; + var bone:Bone; + i = boneList.length; + while(i --) { - var movementBoneData:MovementBoneData = _movementData.getMovementBoneData(bone.name); - if (movementBoneData) - { - bone._tween.gotoAndPlay(movementBoneData, _rawDuration, loop, tweenEasing); - if (bone.childArmature) - { - bone.childArmature.animation.gotoAndPlay(movementID); - } - } - else + bone = boneList[i]; + if(bone.childArmature) { - bone._tween.stop(); + bone.childArmature.animation.gotoAndPlay(animationName, fadeInTime); } } - if (_armature.hasEventListener(AnimationEvent.MOVEMENT_CHANGE)) - { - var event:AnimationEvent = new AnimationEvent(AnimationEvent.MOVEMENT_CHANGE); - event.exMovementID = exMovementID; - event.movementID = _movementID; - _armature.dispatchEvent(event); - } + return _lastAnimationState; } /** @@ -344,201 +380,233 @@ */ public function play():void { - if (!_animationData) + if (!_animationDataList || _animationDataList.length == 0) { return; } - - if (!_movementID) + if(!_lastAnimationState) { - if (movementList) - { - gotoAndPlay(movementList[0]); - } - return; - } - - if (isComplete) - { - gotoAndPlay(_movementID); + gotoAndPlay(_animationDataList[0].name); } else if (!_isPlaying) { _isPlaying = true; - for each(var bone:Bone in _armature._boneDepthList) - { - if (bone.childArmature) - { - bone.childArmature.animation.play(); - } - } + } + else + { + gotoAndPlay(_lastAnimationState.name); } } - /** @private */ - dragonBones_internal function clearMovement():void + public function stop():void { - _movementID = null; + _isPlaying = false; } /** - * Stop the playhead. + * Returns the AnimationState named name. + * @return A AnimationState instance. + * @see dragonBones.animation.AnimationState. */ - public function stop():void + public function getState(name:String, layer:uint = 0):AnimationState { - _isPlaying = false; + var l:int = _animationLayer.length; + if(l == 0) + { + return null; + } + else if(layer >= l) + { + layer = l - 1; + } - for each(var bone:Bone in _armature._boneDepthList) + var animationStateList:Vector. = _animationLayer[layer]; + if(!animationStateList) + { + return null; + } + var i:int = animationStateList.length; + while(i --) { - if (bone.childArmature) + if(animationStateList[i].name == name) { - bone.childArmature.animation.stop(); + return animationStateList[i]; } } + + return null; } - /** @private */ - dragonBones_internal function advanceTime(passedTime:Number):void + public function hasAnimation(animationName:String):Boolean { - if (_isPlaying && (_loop > 0 || _currentTime < _totalTime || _totalTime == 0)) + var i:int = _animationDataList.length; + while(i --) { - var progress:Number; - if (_totalTime > 0) + if(_animationDataList[i].name == animationName) { - _currentTime += passedTime * _timeScale; - progress = _currentTime / _totalTime; - } - else - { - _currentTime = 1; - _totalTime = 1; - progress = 1; + return true; } + } + + return false; + } + + public function advanceTime(passedTime:Number):void + { + if(!_isPlaying) + { + return; + } + passedTime *= _timeScale; + + var l:int = _armature._boneList.length; + var i:int; + var j:int; + var k:int = l; + var bone:Bone; + var boneName:String; + var weigthLeft:Number; + + var x:Number; + var y:Number; + var skewX:Number; + var skewY:Number; + var scaleX:Number; + var scaleY:Number; + var pivotX:Number; + var pivotY:Number; + + var layerTotalWeight:Number; + var animationStateList:Vector.; + var animationState:AnimationState; + var timelineState:TimelineState; + var weight:Number; + var transform:DBTransform; + var pivot:Point; + + l --; + while(k --) + { + bone = _armature._boneList[k]; + boneName = bone.name; + weigthLeft = 1; + + x = 0; + y = 0; + skewX = 0; + skewY = 0; + scaleX = 0; + scaleY = 0; + pivotX = 0; + pivotY = 0; - var event:AnimationEvent; - if (_playType == LOOP) + i = _animationLayer.length; + while(i --) { - var loop:int = progress; - if (loop != _loop) + layerTotalWeight = 0; + animationStateList = _animationLayer[i]; + j = animationStateList.length; + while(j --) { - _loop = loop; - _nextFrameDataTimeEdge = 0; - if (_armature.hasEventListener(AnimationEvent.LOOP_COMPLETE)) + animationState = animationStateList[j]; + if(k == l) + { + if(animationState.advanceTime(passedTime)) + { + removeState(animationState); + continue; + } + } + + timelineState = animationState._timelineStates[boneName]; + + if(timelineState) { - event = new AnimationEvent(AnimationEvent.LOOP_COMPLETE); - event.movementID = _movementID; + weight = animationState._fadeWeight * animationState.weight * weigthLeft; + transform = timelineState.transform; + pivot = timelineState.pivot; + x += transform.x * weight; + y += transform.y * weight; + skewX += transform.skewX * weight; + skewY += transform.skewY * weight; + scaleX += transform.scaleX * weight; + scaleY += transform.scaleY * weight; + pivotX += pivot.x * weight; + pivotY += pivot.y * weight; + + layerTotalWeight += weight; } } - } - else if (progress >= 1) - { - switch (_playType) + + if(layerTotalWeight >= weigthLeft) { - case SINGLE: - case LIST: - progress = 1; - if (_armature.hasEventListener(AnimationEvent.COMPLETE)) - { - event = new AnimationEvent(AnimationEvent.COMPLETE); - event.movementID = _movementID; - } - break; - case LIST_START: - progress = 0; - _playType = LIST; - _currentTime = 0; - _totalTime = _duration; - if (_armature.hasEventListener(AnimationEvent.START)) - { - event = new AnimationEvent(AnimationEvent.START); - event.movementID = _movementID; - } - break; - case LOOP_START: - progress = 0; - _playType = LOOP; - _currentTime = 0; - _totalTime = _duration; - if (_armature.hasEventListener(AnimationEvent.START)) - { - event = new AnimationEvent(AnimationEvent.START); - event.movementID = _movementID; - } - break; + break; } - } - - var i:int = _armature._boneDepthList.length; - while(i --) - { - _armature._boneDepthList[i]._tween.advanceTime(progress, _playType); - } - - if ((_playType == LIST || _playType == LOOP) && _movementData._movementFrameList.length > 0) - { - if (_loop > 0) + else { - progress -= _loop; + weigthLeft -= layerTotalWeight; } - updateFrameData(progress); } + transform = bone._tween; + pivot = bone._tweenPivot; - if (event) - { - _armature.dispatchEvent(event); - } + transform.x = x; + transform.y = y; + transform.skewX = skewX; + transform.skewY = skewY; + transform.scaleX = scaleX; + transform.scaleY = scaleY; + pivot.x = pivotX; + pivot.y = pivotY; } } - private function updateFrameData(progress:Number):void + /** @private */ + /*dragonBones_internal function setStatesDisplayControl(animationState:AnimationState):void { - var playedTime:Number = _rawDuration * progress; - if (playedTime >= _nextFrameDataTimeEdge) + var i:int = _animationLayer.length; + var animationStateList:Vector. = _animationLayer[i]; + var j:int; + while(i --) { - _breakFrameWhile = false; - var length:uint = _movementData._movementFrameList.length; - do + animationStateList = _animationLayer[i]; + j = animationStateList.length; + while(j --) { - var currentFrameDataID:int = _nextFrameDataID; - var currentFrameData:MovementFrameData = _movementData._movementFrameList[currentFrameDataID]; - var frameDuration:Number = currentFrameData.duration; - _nextFrameDataTimeEdge += frameDuration; - if (++_nextFrameDataID >= length) - { - _nextFrameDataID = 0; - } - arriveFrameData(currentFrameData); - if (_breakFrameWhile) - { - break; - } - } while (playedTime >= _nextFrameDataTimeEdge); + animationStateList[j].displayControl = animationStateList[j] == animationState; + } } - } + }*/ - private function arriveFrameData(movementFrameData:MovementFrameData):void + private function addLayer(layer:uint):uint { - //Tracer.reveal(movementFrameData) - if (movementFrameData.event && _armature.hasEventListener(FrameEvent.MOVEMENT_FRAME_EVENT)) - { - var frameEvent:FrameEvent = new FrameEvent(FrameEvent.MOVEMENT_FRAME_EVENT); - frameEvent.movementID = _movementID; - frameEvent.frameLabel = movementFrameData.event; - _armature.dispatchEvent(frameEvent); - } - if (movementFrameData.sound && _soundManager.hasEventListener(SoundEvent.SOUND)) + if(layer >= _animationLayer.length) { - var soundEvent:SoundEvent = new SoundEvent(SoundEvent.SOUND); - soundEvent.movementID = _movementID; - soundEvent.sound = movementFrameData.sound; - soundEvent._armature = _armature; - _soundManager.dispatchEvent(soundEvent); + layer = _animationLayer.length; + _animationLayer[layer] = new Vector.; } - if (movementFrameData.movement) + return layer; + } + + private function addState(animationState:AnimationState):void + { + var animationStateList:Vector. = _animationLayer[animationState.layer]; + animationStateList[animationStateList.length] = animationState; + } + + private function removeState(animationState:AnimationState):void + { + var layer:int = animationState.layer; + var animationStateList:Vector. = _animationLayer[layer]; + animationStateList.splice(animationStateList.indexOf(animationState), 1); + + AnimationState.returnObject(animationState); + + if(animationStateList.length == 0 && layer == _animationLayer.length - 1) { - gotoAndPlay(movementFrameData.movement); + _animationLayer.length --; } } } - + } \ No newline at end of file diff --git a/src/dragonBones/animation/AnimationState.as b/src/dragonBones/animation/AnimationState.as new file mode 100644 index 0000000..fd2e436 --- /dev/null +++ b/src/dragonBones/animation/AnimationState.as @@ -0,0 +1,641 @@ +package dragonBones.animation +{ + import dragonBones.Armature; + import dragonBones.Bone; + import dragonBones.Slot; + import dragonBones.core.dragonBones_internal; + import dragonBones.events.AnimationEvent; + import dragonBones.objects.AnimationData; + import dragonBones.objects.DBTransform; + import dragonBones.objects.Frame; + import dragonBones.objects.TransformTimeline; + + use namespace dragonBones_internal; + + final public class AnimationState + { + private static var _pool:Vector. = new Vector.; + + /** @private */ + dragonBones_internal static function borrowObject():AnimationState + { + if(_pool.length == 0) + { + return new AnimationState(); + } + return _pool.pop(); + } + + /** @private */ + dragonBones_internal static function returnObject(animationState:AnimationState):void + { + animationState.clear(); + + if(_pool.indexOf(animationState) < 0) + { + _pool[_pool.length] = animationState; + } + } + + /** @private */ + dragonBones_internal static function clear():void + { + var i:int = _pool.length; + while(i --) + { + _pool[i].clear(); + } + _pool.length = 0; + + TimelineState.clear(); + } + + public var enabled:Boolean; + public var tweenEnabled:Boolean; + public var blend:Boolean; + public var group:String; + public var weight:Number; + + /** @private */ + dragonBones_internal var _timelineStates:Object; + /** @private */ + dragonBones_internal var _fadeWeight:Number; + + private var _armature:Armature; + private var _currentFrame:Frame; + private var _mixingTransforms:Object; + private var _fadeState:int; + private var _fadeInTime:Number; + private var _fadeOutTime:Number; + private var _fadeOutBeginTime:Number; + private var _fadeOutWeight:Number; + private var _fadeIn:Boolean; + private var _fadeOut:Boolean; + private var _pauseBeforeFadeInComplete:Boolean; + + private var _name:String; + public function get name():String + { + return _name; + } + + private var _clip:AnimationData; + public function get clip():AnimationData + { + return _clip; + } + + private var _loopCount:int; + public function get loopCount():int + { + return _loopCount; + } + + private var _loop:int; + public function get loop():int + { + return _loop; + } + + private var _layer:uint; + public function get layer():uint + { + return _layer; + } + + private var _isPlaying:Boolean; + public function get isPlaying():Boolean + { + return _isPlaying && !_isComplete; + } + + private var _isComplete:Boolean; + public function get isComplete():Boolean + { + return _isComplete; + } + + public function get fadeInTime():Number + { + return _fadeInTime; + } + + private var _totalTime:Number; + public function get totalTime():Number + { + return _totalTime; + } + + private var _currentTime:Number; + public function get currentTime():Number + { + return _currentTime; + } + public function set currentTime(value:Number):void + { + if(value < 0 || isNaN(value)) + { + value = 0; + } + // + _currentTime = value; + } + + private var _timeScale:Number; + public function get timeScale():Number + { + return _timeScale; + } + public function set timeScale(value:Number):void + { + if(value < 0) + { + value = 0; + } + else if(isNaN(value)) + { + value = 1; + } + else if(_timeScale == Infinity) + { + //* + _timeScale = 1; + } + _timeScale = value; + } + + private var _displayControl:Boolean; + public function get displayControl():Boolean + { + return _displayControl; + } + public function set displayControl(value:Boolean):void + { + if(_displayControl != value) + { + _displayControl = value; + /*if(_displayControl) + { + _armature.animation.setStatesDisplayControl(this); + }*/ + } + } + + public function AnimationState() + { + _timelineStates = {}; + } + + /** @private */ + dragonBones_internal function fadeIn(armature:Armature, clip:AnimationData, fadeInTime:Number, timeScale:Number, loop:int, layer:uint, displayControl:Boolean, pauseBeforeFadeInComplete:Boolean):void + { + _armature = armature; + _clip = clip; + _name = _clip.name; + _layer = layer; + + _totalTime = _clip.duration; + if(Math.round(_clip.duration * _clip.frameRate) < 2 || timeScale == Infinity) + { + _timeScale = 1; + _currentTime = _totalTime; + if(_loop >= 0) + { + _loop = 1; + } + else + { + _loop = -1; + } + _pauseBeforeFadeInComplete = false; + } + else + { + _timeScale = timeScale; + _currentTime = 0; + _loop = loop; + _pauseBeforeFadeInComplete = pauseBeforeFadeInComplete; + } + + _fadeInTime = fadeInTime * _timeScale; + + + _loopCount = -1; + _fadeState = 1; + _fadeOutBeginTime = 0; + _fadeOutWeight = NaN; + _fadeWeight = 0; + _displayControl = displayControl; + _isPlaying = true; + _isComplete = false; + _fadeIn = true; + _fadeOut = false; + + weight = 1; + blend = true; + enabled = true; + tweenEnabled = true; + + updateTimelineStates(); + } + + public function fadeOut(fadeOutTime:Number, pause:Boolean = false):void + { + if(!isNaN(_fadeOutWeight)) + { + return; + } + _fadeState = -1; + _fadeOutWeight = _fadeWeight; + _fadeOutTime = fadeOutTime * _timeScale; + _fadeOutBeginTime = _currentTime; + _isPlaying = !pause; + _fadeOut = true; + _displayControl = false; + + for each(var timelineState:TimelineState in _timelineStates) + { + timelineState.fadeOut(); + } + + enabled = true; + } + + public function play():void + { + _isPlaying = true; + } + + public function stop():void + { + _isPlaying = false; + } + + public function getMixingTransform(timelineName:String):int + { + if(_mixingTransforms) + { + return int(_mixingTransforms[timelineName]); + } + return -1; + } + + public function addMixingTransform(timelineName:String, type:int = 2, recursive:Boolean = true):void + { + if(_clip && _clip.getTimeline(timelineName)) + { + if(!_mixingTransforms) + { + _mixingTransforms = {}; + } + if(recursive) + { + var i:int = _armature._boneList.length; + var bone:Bone; + var currentBone:Bone; + while(i --) + { + bone = _armature._boneList[i]; + if(bone.name == timelineName) + { + currentBone = bone; + } + if(currentBone && (currentBone == bone || currentBone.contains(bone))) + { + _mixingTransforms[bone.name] = type; + } + } + } + else + { + _mixingTransforms[timelineName] = type; + } + + updateTimelineStates(); + } + else + { + throw new ArgumentError(); + } + } + + public function removeMixingTransform(timelineName:String = null, recursive:Boolean = true):void + { + if(timelineName) + { + if(recursive) + { + var i:int = _armature._boneList.length; + var bone:Bone; + var currentBone:Bone; + while(i --) + { + bone = _armature._boneList[i]; + if(bone.name == timelineName) + { + currentBone = bone; + } + if(currentBone && (currentBone == bone || currentBone.contains(bone))) + { + delete _mixingTransforms[bone.name]; + } + } + } + else + { + delete _mixingTransforms[timelineName]; + } + + for each(timelineName in _mixingTransforms) + { + var hasMixing:Boolean = true; + break; + } + if(!hasMixing) + { + _mixingTransforms = null; + } + } + else + { + _mixingTransforms = null; + } + + updateTimelineStates(); + } + + public function advanceTime(passedTime:Number):Boolean + { + if(!enabled) + { + return false; + } + + if(_fadeIn) + { + _fadeIn = false; + if(_armature.hasEventListener(AnimationEvent.FADE_IN)) + { + var event:AnimationEvent = new AnimationEvent(AnimationEvent.FADE_IN); + event.animationState = this; + _armature.dispatchEvent(event); + event = null; + }; + } + + if(_fadeOut) + { + _fadeOut = false; + if(_armature.hasEventListener(AnimationEvent.FADE_OUT)) + { + event = new AnimationEvent(AnimationEvent.FADE_OUT); + event.animationState = this; + _armature.dispatchEvent(event); + event = null; + } + } + + _currentTime += passedTime * _timeScale; + + if(_isPlaying && !_isComplete) + { + if(_pauseBeforeFadeInComplete) + { + _pauseBeforeFadeInComplete = false; + _isPlaying = false; + var progress:Number = 0; + var currentLoopCount:int = progress; + } + else + { + progress = _currentTime / _totalTime; + + //update loopCount + currentLoopCount = progress; + if(currentLoopCount != _loopCount) + { + if(_loopCount == -1) + { + if(_armature.hasEventListener(AnimationEvent.START)) + { + event = new AnimationEvent(AnimationEvent.START); + event.animationState = this; + _armature.dispatchEvent(event); + event = null; + } + } + _loopCount = currentLoopCount; + if(_loopCount) + { + if(_loop && _loopCount * _loopCount >= _loop * _loop - 1) + { + _isComplete = true; + _isPlaying = false; + progress = 1; + currentLoopCount = 0; + if(_armature.hasEventListener(AnimationEvent.COMPLETE)) + { + event = new AnimationEvent(AnimationEvent.COMPLETE); + event.animationState = this; + } + } + else + { + if(_armature.hasEventListener(AnimationEvent.LOOP_COMPLETE)) + { + event = new AnimationEvent(AnimationEvent.LOOP_COMPLETE); + event.animationState = this; + } + } + } + } + } + + + for each(var timeline:TimelineState in _timelineStates) + { + timeline.update(progress); + } + + // + if(_clip.frameList.length > 0) + { + var playedTime:Number = _totalTime * (progress - currentLoopCount); + var isArrivedFrame:Boolean = false; + var frameIndex:int; + while(!_currentFrame || playedTime > _currentFrame.position + _currentFrame.duration || playedTime < _currentFrame.position) + { + if(isArrivedFrame) + { + _armature.arriveAtFrame(_currentFrame, null, this, true); + } + isArrivedFrame = true; + if(_currentFrame) + { + frameIndex = _clip.frameList.indexOf(_currentFrame); + frameIndex ++; + if(frameIndex >= _clip.frameList.length) + { + frameIndex = 0; + } + _currentFrame = _clip.frameList[frameIndex]; + } + else + { + _currentFrame = _clip.frameList[0]; + } + } + + if(isArrivedFrame) + { + _armature.arriveAtFrame(_currentFrame, null, this, false); + } + } + + if(event) + { + _armature.dispatchEvent(event); + } + } + + //update weight and fadeState + if(_fadeState > 0) + { + if(_fadeInTime == 0) + { + _fadeWeight = 1; + _fadeState = 0; + _isPlaying = true; + if(_armature.hasEventListener(AnimationEvent.FADE_IN_COMPLETE)) + { + event = new AnimationEvent(AnimationEvent.FADE_IN_COMPLETE); + event.animationState = this; + _armature.dispatchEvent(event); + } + } + else + { + _fadeWeight = _currentTime / _fadeInTime; + if(_fadeWeight >= 1) + { + _fadeWeight = 1; + _fadeState = 0; + if(!_isPlaying) + { + _currentTime -= _fadeInTime; + } + _isPlaying = true; + if(_armature.hasEventListener(AnimationEvent.FADE_IN_COMPLETE)) + { + event = new AnimationEvent(AnimationEvent.FADE_IN_COMPLETE); + event.animationState = this; + _armature.dispatchEvent(event); + } + } + } + } + else if(_fadeState < 0) + { + if(_fadeOutTime == 0) + { + _fadeWeight = 0; + _fadeState = 0; + if(_armature.hasEventListener(AnimationEvent.FADE_OUT_COMPLETE)) + { + event = new AnimationEvent(AnimationEvent.FADE_OUT_COMPLETE); + event.animationState = this; + _armature.dispatchEvent(event); + } + return true; + } + else + { + _fadeWeight = (1 - (_currentTime - _fadeOutBeginTime) / _fadeOutTime) * _fadeOutWeight; + if(_fadeWeight <= 0) + { + _fadeWeight = 0; + _fadeState = 0; + if(_armature.hasEventListener(AnimationEvent.FADE_OUT_COMPLETE)) + { + event = new AnimationEvent(AnimationEvent.FADE_OUT_COMPLETE); + event.animationState = this; + _armature.dispatchEvent(event); + } + return true; + } + } + } + + if(_isComplete && _loop < 0) + { + fadeOut((_fadeOutWeight || _fadeInTime) / _timeScale, true); + } + + return false; + } + + private function updateTimelineStates():void + { + if(_mixingTransforms) + { + for(var timelineName:String in _timelineStates) + { + if(_mixingTransforms[timelineName] == null) + { + removeTimelineState(timelineName); + } + } + + for(timelineName in _mixingTransforms) + { + if(!_timelineStates[timelineName]) + { + addTimelineState(timelineName); + } + } + } + else + { + for(timelineName in _clip.timelines) + { + if(!_timelineStates[timelineName]) + { + addTimelineState(timelineName); + } + } + } + } + + private function addTimelineState(timelineName:String):void + { + var bone:Bone = _armature.getBone(timelineName); + if(bone) + { + var timelineState:TimelineState = TimelineState.borrowObject(); + var timeline:TransformTimeline = _clip.getTimeline(timelineName); + timelineState.fadeIn(bone, this, timeline); + _timelineStates[timelineName] = timelineState; + } + } + + private function removeTimelineState(timelineName:String):void + { + TimelineState.returnObject(_timelineStates[timelineName] as TimelineState); + delete _timelineStates[timelineName]; + } + + private function clear():void + { + _armature = null; + _currentFrame = null; + _clip = null; + _mixingTransforms = null; + enabled = false; + + for(var timelineName:String in _timelineStates) + { + removeTimelineState(timelineName); + } + } + } +} \ No newline at end of file diff --git a/src/dragonBones/animation/TimelineState.as b/src/dragonBones/animation/TimelineState.as new file mode 100644 index 0000000..f3cfa3a --- /dev/null +++ b/src/dragonBones/animation/TimelineState.as @@ -0,0 +1,535 @@ +package dragonBones.animation +{ + import dragonBones.Bone; + import dragonBones.core.dragonBones_internal; + import dragonBones.objects.DBTransform; + import dragonBones.objects.TransformFrame; + import dragonBones.objects.TransformTimeline; + import dragonBones.utils.TransformUtil; + + import flash.geom.ColorTransform; + import flash.geom.Point; + + use namespace dragonBones_internal; + + /** @private */ + public final class TimelineState + { + private static const HALF_PI:Number = Math.PI * 0.5; + private static const DOUBLE_PI:Number = Math.PI * 2; + + private static var _pool:Vector. = new Vector.; + + /** @private */ + dragonBones_internal static function borrowObject():TimelineState + { + if(_pool.length == 0) + { + return new TimelineState(); + } + return _pool.pop(); + } + + /** @private */ + dragonBones_internal static function returnObject(timeline:TimelineState):void + { + if(_pool.indexOf(timeline) < 0) + { + _pool[_pool.length] = timeline; + } + + timeline.clear(); + } + + /** @private */ + dragonBones_internal static function clear():void + { + var i:int = _pool.length; + while(i --) + { + _pool[i].clear(); + } + _pool.length = 0; + } + + public static function getEaseValue(value:Number, easing:Number):Number + { + if (easing > 1) + { + var valueEase:Number = 0.5 * (1 - Math.cos(value * Math.PI )) - value; + easing -= 1; + } + else if (easing > 0) + { + valueEase = Math.sin(value * HALF_PI) - value; + } + else if (easing < 0) + { + valueEase = 1 - Math.cos(value * HALF_PI) - value; + easing *= -1; + } + return valueEase * easing + value; + } + + public var transform:DBTransform; + public var pivot:Point; + + public var update:Function; + + private var _animationState:AnimationState; + private var _bone:Bone; + private var _timeline:TransformTimeline; + private var _currentFrame:TransformFrame; + private var _currentFramePosition:Number; + private var _currentFrameDuration:Number; + private var _durationTransform:DBTransform; + private var _durationPivot:Point; + private var _durationColor:ColorTransform; + private var _originTransform:DBTransform; + private var _originPivot:Point; + + private var _tweenEasing:Number; + private var _tweenTransform:Boolean; + private var _tweenColor:Boolean; + + private var _totalTime:Number; + + public function TimelineState() + { + transform = new DBTransform(); + pivot = new Point(); + + //_originTransform = new DBTransform(); + + _durationTransform = new DBTransform(); + _durationPivot = new Point(); + _durationColor = new ColorTransform(); + } + + public function fadeIn(bone:Bone, animationState:AnimationState, timeline:TransformTimeline):void + { + _bone = bone; + _animationState = animationState; + _timeline = timeline; + + _originTransform = _timeline.originTransform; + _originPivot = _timeline.originPivot; + //_originTransform.copy(_timeline.originTransform); + + /* + var bLRX:Number = _bone.origin.skewX + _bone.offset.skewX + _bone._tween.skewX; + var bLRY:Number = _bone.origin.skewY + _bone.offset.skewY + _bone._tween.skewY; + + _originTransform.skewX = bLRX + TransformUtils.formatRadian(_originTransform.skewX - bLRX); + _originTransform.skewY = bLRY + TransformUtils.formatRadian(_originTransform.skewY - bLRY); + */ + + _totalTime = _animationState.totalTime; + + transform.x = 0; + transform.y = 0; + transform.scaleX = 0; + transform.scaleY = 0; + transform.skewX = 0; + transform.skewY = 0; + pivot.x = 0; + pivot.y = 0; + + _durationTransform.x = 0; + _durationTransform.y = 0; + _durationTransform.scaleX = 0; + _durationTransform.scaleY = 0; + _durationTransform.skewX = 0; + _durationTransform.skewY = 0; + _durationPivot.x = 0; + _durationPivot.y = 0; + + switch(_timeline.frameList.length) + { + case 0: + _bone.arriveAtFrame(null, this, _animationState, false); + update = updateNothing; + break; + case 1: + update = updateSingle; + break; + default: + update = updateList; + break; + } + } + + public function fadeOut():void + { + transform.skewX = TransformUtil.formatRadian(transform.skewX); + transform.skewY = TransformUtil.formatRadian(transform.skewY); + //_originTransform.skewX = TransformUtil.formatRadian(_originTransform.skewX); + //_originTransform.skewY = TransformUtil.formatRadian(_originTransform.skewY); + } + + private function updateNothing(progress:Number):void + { + + } + + private function updateSingle(progress:Number):void + { + update = updateNothing; + + if(_animationState.blend) + { + transform.copy(_originTransform); + + pivot.x = _originPivot.x; + pivot.y = _originPivot.y; + } + else + { + transform.x = + transform.y = + transform.skewX = + transform.skewY = + transform.scaleX = + transform.scaleY = 0; + + pivot.x = 0; + pivot.y = 0; + } + + _currentFrame = _timeline.frameList[0] as TransformFrame; + + if(_currentFrame.color) + { + _bone.updateColor( + _currentFrame.color.alphaOffset, + _currentFrame.color.redOffset, + _currentFrame.color.greenOffset, + _currentFrame.color.blueOffset, + _currentFrame.color.alphaMultiplier, + _currentFrame.color.redMultiplier, + _currentFrame.color.greenMultiplier, + _currentFrame.color.blueMultiplier, + true + ); + } + else + { + _bone.updateColor(0, 0, 0, 0, 1, 1, 1, 1, false); + } + + + _bone.arriveAtFrame(_currentFrame, this, _animationState, false); + } + + private function updateList(progress:Number):void + { + if(_timeline.scale == 0) + { + progress = 1; + } + else + { + progress /= _timeline.scale; + } + + if(progress == 1) + { + progress = 0.99999999; + } + + progress += _timeline.offset; + var loopCount:int = progress; + progress -= loopCount; + + // + var playedTime:Number = _totalTime * progress; + var isArrivedFrame:Boolean = false; + var frameIndex:int; + while (!_currentFrame || playedTime > _currentFramePosition + _currentFrameDuration || playedTime < _currentFramePosition) + { + if(isArrivedFrame) + { + _bone.arriveAtFrame(_currentFrame, this, _animationState, true); + } + isArrivedFrame = true; + if(_currentFrame) + { + frameIndex = _timeline.frameList.indexOf(_currentFrame) + 1; + if(frameIndex >= _timeline.frameList.length) + { + frameIndex = 0; + } + _currentFrame = _timeline.frameList[frameIndex] as TransformFrame; + } + else + { + frameIndex = 0; + _currentFrame = _timeline.frameList[0] as TransformFrame; + } + _currentFrameDuration = _currentFrame.duration; + _currentFramePosition = _currentFrame.position; + } + + if(isArrivedFrame) + { + frameIndex ++; + if(frameIndex >= _timeline.frameList.length) + { + frameIndex = 0; + } + var nextFrame:TransformFrame = _timeline.frameList[frameIndex] as TransformFrame; + + if(frameIndex == 0 && _animationState.loop && _animationState.loopCount >= Math.abs(_animationState.loop) - 1 && ((_currentFramePosition + _currentFrameDuration) / _totalTime + loopCount - _timeline.offset) * _timeline.scale > 0.999999)// >= 1 + { + update = updateNothing; + _tweenEasing = NaN; + } + else if(nextFrame.displayIndex < 0 || !_animationState.tweenEnabled) + { + _tweenEasing = NaN; + } + else if(isNaN(_animationState.clip.tweenEasing)) + { + _tweenEasing = _currentFrame.tweenEasing; + } + else + { + _tweenEasing = _animationState.clip.tweenEasing; + } + + if(isNaN(_tweenEasing)) + { + _tweenTransform = false; + _tweenColor = false; + } + else + { + _durationTransform.x = nextFrame.transform.x - _currentFrame.transform.x; + _durationTransform.y = nextFrame.transform.y - _currentFrame.transform.y; + _durationTransform.skewX = nextFrame.transform.skewX - _currentFrame.transform.skewX; + _durationTransform.skewY = nextFrame.transform.skewY - _currentFrame.transform.skewY; + _durationTransform.scaleX = nextFrame.transform.scaleX - _currentFrame.transform.scaleX; + _durationTransform.scaleY = nextFrame.transform.scaleY - _currentFrame.transform.scaleY; + + if(frameIndex == 0) + { + _durationTransform.skewX = TransformUtil.formatRadian(_durationTransform.skewX); + _durationTransform.skewY = TransformUtil.formatRadian(_durationTransform.skewY); + } + + _durationPivot.x = nextFrame.pivot.x - _currentFrame.pivot.x; + _durationPivot.y = nextFrame.pivot.y - _currentFrame.pivot.y; + + if( + _durationTransform.x != 0 || + _durationTransform.y != 0 || + _durationTransform.skewX != 0 || + _durationTransform.skewY != 0 || + _durationTransform.scaleX != 0 || + _durationTransform.scaleY != 0 || + _durationPivot.x != 0 || + _durationPivot.y != 0 + ) + { + _tweenTransform = true; + } + else + { + _tweenTransform = false; + } + + if(_currentFrame.color && nextFrame.color) + { + _durationColor.alphaOffset = nextFrame.color.alphaOffset - _currentFrame.color.alphaOffset; + _durationColor.redOffset = nextFrame.color.redOffset - _currentFrame.color.redOffset; + _durationColor.greenOffset = nextFrame.color.greenOffset - _currentFrame.color.greenOffset; + _durationColor.blueOffset = nextFrame.color.blueOffset - _currentFrame.color.blueOffset; + + _durationColor.alphaMultiplier = nextFrame.color.alphaMultiplier - _currentFrame.color.alphaMultiplier; + _durationColor.redMultiplier = nextFrame.color.redMultiplier - _currentFrame.color.redMultiplier; + _durationColor.greenMultiplier = nextFrame.color.greenMultiplier - _currentFrame.color.greenMultiplier; + _durationColor.blueMultiplier = nextFrame.color.blueMultiplier - _currentFrame.color.blueMultiplier; + + if( + _durationColor.alphaOffset != 0 || + _durationColor.redOffset != 0 || + _durationColor.greenOffset != 0 || + _durationColor.blueOffset != 0 || + _durationColor.alphaMultiplier != 0 || + _durationColor.redMultiplier != 0 || + _durationColor.greenMultiplier != 0 || + _durationColor.blueMultiplier != 0 + ) + { + _tweenColor = true; + } + else + { + _tweenColor = false; + } + } + else if(_currentFrame.color) + { + _tweenColor = true; + _durationColor.alphaOffset = -_currentFrame.color.alphaOffset; + _durationColor.redOffset = -_currentFrame.color.redOffset; + _durationColor.greenOffset = -_currentFrame.color.greenOffset; + _durationColor.blueOffset = -_currentFrame.color.blueOffset; + + _durationColor.alphaMultiplier = 1 - _currentFrame.color.alphaMultiplier; + _durationColor.redMultiplier = 1 - _currentFrame.color.redMultiplier; + _durationColor.greenMultiplier = 1 - _currentFrame.color.greenMultiplier; + _durationColor.blueMultiplier = 1 - _currentFrame.color.blueMultiplier; + } + else if(nextFrame.color) + { + _tweenColor = true; + _durationColor.alphaOffset = nextFrame.color.alphaOffset; + _durationColor.redOffset = nextFrame.color.redOffset; + _durationColor.greenOffset = nextFrame.color.greenOffset; + _durationColor.blueOffset = nextFrame.color.blueOffset; + + _durationColor.alphaMultiplier = nextFrame.color.alphaMultiplier - 1; + _durationColor.redMultiplier = nextFrame.color.redMultiplier - 1; + _durationColor.greenMultiplier = nextFrame.color.greenMultiplier - 1; + _durationColor.blueMultiplier = nextFrame.color.blueMultiplier - 1; + } + else + { + _tweenColor = false; + } + } + + if(!_tweenTransform) + { + if(_animationState.blend) + { + transform.x = _originTransform.x + _currentFrame.transform.x; + transform.y = _originTransform.y + _currentFrame.transform.y; + transform.skewX = _originTransform.skewX + _currentFrame.transform.skewX; + transform.skewY = _originTransform.skewY + _currentFrame.transform.skewY; + transform.scaleX = _originTransform.scaleX + _currentFrame.transform.scaleX; + transform.scaleY = _originTransform.scaleY + _currentFrame.transform.scaleY; + + pivot.x = _originPivot.x + _currentFrame.pivot.x; + pivot.y = _originPivot.y + _currentFrame.pivot.y; + } + else + { + transform.x = _currentFrame.transform.x; + transform.y = _currentFrame.transform.y; + transform.skewX = _currentFrame.transform.skewX; + transform.skewY = _currentFrame.transform.skewY; + transform.scaleX = _currentFrame.transform.scaleX; + transform.scaleY = _currentFrame.transform.scaleY; + + pivot.x = _currentFrame.pivot.x; + pivot.y = _currentFrame.pivot.y; + } + } + + if(!_tweenColor) + { + if(_currentFrame.color) + { + _bone.updateColor( + _currentFrame.color.alphaOffset, + _currentFrame.color.redOffset, + _currentFrame.color.greenOffset, + _currentFrame.color.blueOffset, + _currentFrame.color.alphaMultiplier, + _currentFrame.color.redMultiplier, + _currentFrame.color.greenMultiplier, + _currentFrame.color.blueMultiplier, + true + ); + } + else if(_bone._isColorChanged) + { + _bone.updateColor(0, 0, 0, 0, 1, 1, 1, 1, false); + } + } + _bone.arriveAtFrame(_currentFrame, this, _animationState, false); + } + + if(_tweenTransform) + { + progress = (playedTime - _currentFramePosition) / _currentFrameDuration; + if(_tweenEasing) + { + progress = getEaseValue(progress, _tweenEasing); + } + var currentTransform:DBTransform = _currentFrame.transform; + var currentPivot:Point = _currentFrame.pivot; + if(_animationState.blend) + { + transform.x = _originTransform.x + currentTransform.x + _durationTransform.x * progress; + transform.y = _originTransform.y + currentTransform.y + _durationTransform.y * progress; + transform.skewX = _originTransform.skewX + currentTransform.skewX + _durationTransform.skewX * progress; + transform.skewY = _originTransform.skewY + currentTransform.skewY + _durationTransform.skewY * progress; + transform.scaleX = _originTransform.scaleX + currentTransform.scaleX + _durationTransform.scaleX * progress; + transform.scaleY = _originTransform.scaleY + currentTransform.scaleY + _durationTransform.scaleY * progress; + + pivot.x = _originPivot.x + currentPivot.x + _durationPivot.x * progress; + pivot.y = _originPivot.y + currentPivot.y + _durationPivot.y * progress; + } + else + { + transform.x = currentTransform.x + _durationTransform.x * progress; + transform.y = currentTransform.y + _durationTransform.y * progress; + transform.skewX = currentTransform.skewX + _durationTransform.skewX * progress; + transform.skewY = currentTransform.skewY + _durationTransform.skewY * progress; + transform.scaleX = currentTransform.scaleX + _durationTransform.scaleX * progress; + transform.scaleY = currentTransform.scaleY + _durationTransform.scaleY * progress; + + pivot.x = currentPivot.x + _durationPivot.x * progress; + pivot.y = currentPivot.y + _durationPivot.y * progress; + } + } + + if(_tweenColor) + { + if(_currentFrame.color) + { + _bone.updateColor( + _currentFrame.color.alphaOffset + _durationColor.alphaOffset * progress, + _currentFrame.color.redOffset + _durationColor.redOffset * progress, + _currentFrame.color.greenOffset + _durationColor.greenOffset * progress, + _currentFrame.color.blueOffset + _durationColor.blueOffset * progress, + _currentFrame.color.alphaMultiplier + _durationColor.alphaMultiplier * progress, + _currentFrame.color.redMultiplier + _durationColor.redMultiplier * progress, + _currentFrame.color.greenMultiplier + _durationColor.greenMultiplier * progress, + _currentFrame.color.blueMultiplier + _durationColor.blueMultiplier * progress, + true + ); + } + else + { + _bone.updateColor( + _durationColor.alphaOffset * progress, + _durationColor.redOffset * progress, + _durationColor.greenOffset * progress, + _durationColor.blueOffset * progress, + 1 + _durationColor.alphaMultiplier * progress, + 1 + _durationColor.redMultiplier * progress, + 1 + _durationColor.greenMultiplier * progress, + 1 + _durationColor.blueMultiplier * progress, + false + ); + } + } + } + + private function clear():void + { + update = updateNothing; + + _bone = null; + _animationState = null; + _timeline = null; + _currentFrame = null; + _originTransform = null; + _originPivot = null; + } + } +} \ No newline at end of file diff --git a/src/dragonBones/animation/Tween.as b/src/dragonBones/animation/Tween.as deleted file mode 100644 index 2841ce3..0000000 --- a/src/dragonBones/animation/Tween.as +++ /dev/null @@ -1,406 +0,0 @@ -package dragonBones.animation -{ - import dragonBones.Armature; - import dragonBones.Bone; - import dragonBones.events.FrameEvent; - import dragonBones.events.SoundEvent; - import dragonBones.events.SoundEventManager; - import dragonBones.objects.BoneTransform; - import dragonBones.objects.FrameData; - import dragonBones.objects.MovementBoneData; - import dragonBones.utils.TransformUtils; - import dragonBones.utils.dragonBones_internal; - - import flash.geom.ColorTransform; - - use namespace dragonBones_internal; - - /** @private */ - final public class Tween - { - private static const HALF_PI:Number = Math.PI * 0.5; - - private static var _soundManager:SoundEventManager = SoundEventManager.getInstance(); - - //NaN: no tweens; -1: ease out; 0: linear; 1: ease in; 2: ease in&out - public static function getEaseValue(value:Number, easing:Number):Number - { - var valueEase:Number = 0; - if(isNaN(easing)) - { - return valueEase; - } - else if (easing > 1) - { - valueEase = 0.5 * (1 - Math.cos(value * Math.PI )) - value; - easing -= 1; - } - else if (easing > 0) - { - valueEase = Math.sin(value * HALF_PI) - value; - } - else if (easing < 0) - { - valueEase = 1 - Math.cos(value * HALF_PI) - value; - easing *= -1; - } - return valueEase * easing + value; - } - - private var _bone:Bone; - - private var _movementBoneData:MovementBoneData; - - private var _node:BoneTransform; - private var _colorTransform:ColorTransform; - - private var _currentNode:BoneTransform; - private var _currentColorTransform:ColorTransform; - - private var _offSetNode:BoneTransform; - private var _offSetColorTransform:ColorTransform; - - private var _currentFrameData:FrameData; - private var _tweenEasing:Number; - private var _frameTweenEasing:Number; - - private var _isPause:Boolean; - private var _rawDuration:Number; - private var _nextFrameDataTimeEdge:Number; - private var _frameDuration:Number; - private var _nextFrameDataID:int; - private var _loop:int; - - dragonBones_internal var _differentColorTransform:Boolean; - - /** - * Creates a new Tween - * @param bone - */ - public function Tween(bone:Bone) - { - super(); - - _bone = bone; - _node = _bone._tweenNode; - _colorTransform = _bone._tweenColorTransform; - - _currentNode = new BoneTransform(); - _currentColorTransform = new ColorTransform(); - - _offSetNode = new BoneTransform(); - _offSetColorTransform = new ColorTransform(); - } - - /** @private */ - internal function gotoAndPlay(movementBoneData:MovementBoneData, rawDuration:Number, loop:Boolean, tweenEasing:Number):void - { - if(!movementBoneData) - { - return; - } - _movementBoneData = movementBoneData; - var totalFrames:uint = _movementBoneData._frameList.length; - if(totalFrames == 0) - { - _bone.changeDisplay(-1); - stop(); - return; - } - - _node.skewX %= Math.PI * 2; - _node.skewY %= Math.PI * 2; - _isPause = false; - _currentFrameData = null; - _loop = loop?0:-1; - - _nextFrameDataTimeEdge = 0; - _nextFrameDataID = 0; - _rawDuration = rawDuration; - _tweenEasing = tweenEasing; - - var nextFrameData:FrameData; - if (totalFrames == 1) - { - _frameTweenEasing = 1; - _rawDuration = 0; - nextFrameData = _movementBoneData._frameList[0]; - setOffset(_bone._isOnStage?_node:nextFrameData.node, _colorTransform, nextFrameData.node, nextFrameData.colorTransform); - } - else if (loop && _movementBoneData.delay != 0) - { - getLoopListNode(); - setOffset(_bone._isOnStage?_node:_offSetNode, _colorTransform, _offSetNode, _offSetColorTransform); - //nextFrameData = _movementBoneData._frameList[0]; - } - else - { - _frameTweenEasing = 1; - nextFrameData = _movementBoneData._frameList[0]; - setOffset(_bone._isOnStage?_node:nextFrameData.node, _colorTransform, nextFrameData.node, nextFrameData.colorTransform); - } - - if(nextFrameData) - { - updateBoneDisplayIndex(nextFrameData); - } - } - - private function getLoopListNode():void - { - var playedTime:Number = _rawDuration * _movementBoneData.delay; - var length:int = _movementBoneData._frameList.length; - var nextFrameDataID:int = 0; - var nextFrameDataTimeEdge:Number = 0; - do - { - var currentFrameDataID:int = nextFrameDataID; - var frameDuration:Number = _movementBoneData._frameList[currentFrameDataID].duration; - nextFrameDataTimeEdge += frameDuration; - if (++ nextFrameDataID >= length) - { - nextFrameDataID = 0; - } - } - while (playedTime >= nextFrameDataTimeEdge); - - var currentFrameData:FrameData = _movementBoneData._frameList[currentFrameDataID]; - var nextFrameData:FrameData = _movementBoneData._frameList[nextFrameDataID]; - - - if(nextFrameData.displayIndex >= 0 && _bone.armature.animation.tweenEnabled) - { - _frameTweenEasing = currentFrameData.tweenEasing; - } - else - { - _frameTweenEasing = NaN; - } - - setOffset(currentFrameData.node, currentFrameData.colorTransform, nextFrameData.node, nextFrameData.colorTransform); - - var progress:Number = 1 - (nextFrameDataTimeEdge - playedTime) / frameDuration; - - var tweenEasing:Number = isNaN(_tweenEasing)?currentFrameData.tweenEasing:_tweenEasing; - if (tweenEasing) - { - progress = getEaseValue(progress, tweenEasing); - } - - TransformUtils.setOffSetNode(currentFrameData.node, nextFrameData.node, _offSetNode); - TransformUtils.setTweenNode(_currentNode, _offSetNode, _offSetNode, progress); - - TransformUtils.setOffSetColorTransform(currentFrameData.colorTransform, nextFrameData.colorTransform, _offSetColorTransform); - TransformUtils.setTweenColorTransform(_currentColorTransform, _offSetColorTransform, _offSetColorTransform, progress); - - } - - /** @private */ - internal function stop():void - { - _isPause = true; - } - - /** @private */ - internal function advanceTime(progress:Number, playType:int):void - { - if(_isPause || !_movementBoneData) - { - return; - } - - if(_rawDuration == 0) - { - playType = Animation.SINGLE; - if(progress == 0) - { - progress = 1; - } - } - - if(playType == Animation.LOOP) - { - progress /= _movementBoneData.scale; - progress += _movementBoneData.delay; - var loop:int = progress; - if(_loop != loop) - { - _nextFrameDataTimeEdge = 0; - _nextFrameDataID = 0; - _loop = loop; - } - progress -= loop; - progress = updateFrameData(progress); - } - else if (playType == Animation.LIST) - { - progress = updateFrameData(progress, true); - } - else if (playType == Animation.SINGLE && progress == 1) - { - _currentFrameData = _movementBoneData._frameList[0]; - _isPause = true; - } - else - { - progress = Math.sin(progress * HALF_PI); - } - - - if (!isNaN(_frameTweenEasing) || _currentFrameData) - { - TransformUtils.setTweenNode(_currentNode, _offSetNode, _node, progress); - - if(_differentColorTransform) - { - TransformUtils.setTweenColorTransform(_currentColorTransform, _offSetColorTransform, _colorTransform, progress); - } - } - - if(_currentFrameData) - { - arriveFrameData(_currentFrameData); - _currentFrameData = null; - } - } - - private function setOffset(currentNode:BoneTransform, currentColorTransform:ColorTransform, nextNode:BoneTransform, nextColorTransform:ColorTransform, tweenRotate:int = 0):void - { - _currentNode.copy(currentNode); - TransformUtils.setOffSetNode(_currentNode, nextNode, _offSetNode, tweenRotate); - - _currentColorTransform.alphaOffset = currentColorTransform.alphaOffset; - _currentColorTransform.redOffset = currentColorTransform.redOffset; - _currentColorTransform.greenOffset = currentColorTransform.greenOffset; - _currentColorTransform.blueOffset = currentColorTransform.blueOffset; - _currentColorTransform.alphaMultiplier = currentColorTransform.alphaMultiplier; - _currentColorTransform.redMultiplier = currentColorTransform.redMultiplier; - _currentColorTransform.greenMultiplier = currentColorTransform.greenMultiplier; - _currentColorTransform.blueMultiplier = currentColorTransform.blueMultiplier; - - TransformUtils.setOffSetColorTransform(_currentColorTransform, nextColorTransform, _offSetColorTransform); - - if( - _offSetColorTransform.alphaOffset != 0 || - _offSetColorTransform.redOffset != 0 || - _offSetColorTransform.greenOffset != 0 || - _offSetColorTransform.blueOffset != 0 || - _offSetColorTransform.alphaMultiplier != 0 || - _offSetColorTransform.redMultiplier != 0 || - _offSetColorTransform.greenMultiplier != 0 || - _offSetColorTransform.blueMultiplier != 0 - ) - { - _differentColorTransform = true; - } - else - { - _differentColorTransform = false; - } - } - - private function updateBoneDisplayIndex(frameData:FrameData):void - { - var displayIndex:int = frameData.displayIndex; - if(displayIndex >= 0) - { - if(_node.z != frameData.node.z) - { - _node.z = frameData.node.z; - if(_bone.armature) - { - _bone.armature._bonesIndexChanged = true; - } - } - } - _bone.changeDisplay(displayIndex); - } - - private function arriveFrameData(frameData:FrameData):void - { - updateBoneDisplayIndex(frameData); - _bone._visible = frameData.visible; - - if(frameData.event && _bone._armature.hasEventListener(FrameEvent.BONE_FRAME_EVENT)) - { - var frameEvent:FrameEvent = new FrameEvent(FrameEvent.BONE_FRAME_EVENT, false, _bone); - frameEvent.movementID = _bone._armature.animation.movementID; - frameEvent.frameLabel = frameData.event; - _bone._armature.dispatchEvent(frameEvent); - } - if(frameData.sound && _soundManager.hasEventListener(SoundEvent.SOUND)) - { - var soundEvent:SoundEvent = new SoundEvent(SoundEvent.SOUND); - soundEvent.movementID = _bone._armature.animation.movementID; - soundEvent.sound = frameData.sound; - soundEvent._armature = _bone._armature; - soundEvent._bone = _bone; - _soundManager.dispatchEvent(soundEvent); - } - if(frameData.movement) - { - var childArmature:Armature = _bone.childArmature; - if(childArmature) - { - childArmature.animation.gotoAndPlay(frameData.movement); - } - } - } - - private function updateFrameData(progress:Number, isList:Boolean= false):Number - { - var playedTime:Number = _rawDuration * progress; - if (playedTime >= _nextFrameDataTimeEdge) - { - var length:int = _movementBoneData._frameList.length; - do - { - var currentFrameDataID:int = _nextFrameDataID; - _frameDuration = _movementBoneData._frameList[currentFrameDataID].duration; - _nextFrameDataTimeEdge += _frameDuration; - if (++ _nextFrameDataID >= length) - { - _nextFrameDataID = 0; - } - } - while (playedTime >= _nextFrameDataTimeEdge); - - var currentFrameData:FrameData = _movementBoneData._frameList[currentFrameDataID]; - var nextFrameData:FrameData = _movementBoneData._frameList[_nextFrameDataID]; - - if(nextFrameData.displayIndex >= 0 && _bone.armature.animation.tweenEnabled) - { - _frameTweenEasing = currentFrameData.tweenEasing; - } - else - { - _frameTweenEasing = NaN; - } - - setOffset(currentFrameData.node, currentFrameData.colorTransform, nextFrameData.node, nextFrameData.colorTransform, nextFrameData.tweenRotate); - - _currentFrameData = currentFrameData; - - if(isList && _nextFrameDataID == 0) - { - _isPause = true; - return 0; - } - } - - progress = 1 - (_nextFrameDataTimeEdge - playedTime) / _frameDuration; - - var tweenEasing:Number = isNaN(_tweenEasing)?_frameTweenEasing:_tweenEasing; - if (isNaN(tweenEasing)) - { - return 0; - } - else if(tweenEasing) - { - return getEaseValue(progress, tweenEasing); - } - - return progress; - } - } -} \ No newline at end of file diff --git a/src/dragonBones/animation/WorldClock.as b/src/dragonBones/animation/WorldClock.as index 01f08e0..a65f006 100644 --- a/src/dragonBones/animation/WorldClock.as +++ b/src/dragonBones/animation/WorldClock.as @@ -6,7 +6,8 @@ * @langversion 3.0 * @version 2.0 */ - import dragonBones.Armature; + import dragonBones.Armature; + import flash.utils.getTimer; /** * A WorldClock instance lets you conveniently update many number of Armature instances at once. You can add/remove Armature instance and set a global timescale that will apply to all registered Armature instance animations. @@ -48,7 +49,7 @@ * * private function updateAnimation(e:Event):void * { - * WorldClock.clock.advanceTime(1 / stage.frameRate); + * WorldClock.clock.advanceTime(stage.frameRate / 1000); * } * } * } @@ -150,7 +151,7 @@ */ public function advanceTime(passedTime:Number):void { - if (passedTime < 0) + if(passedTime < 0) { var currentTime:Number = getTimer() * 0.001; passedTime = currentTime - _time; @@ -160,33 +161,33 @@ passedTime *= _timeScale; var length:int = animatableList.length; - if (length == 0) + if(length == 0) { return; } var currentIndex:int = 0; - for (var i:int = 0; i < length; i++) + for(var i:int = 0;i < length;i ++) { var animatable:IAnimatable = animatableList[i]; - if (animatable) + if(animatable) { - if (currentIndex != i) + if(currentIndex != i) { animatableList[currentIndex] = animatable; animatableList[i] = null; } animatable.advanceTime(passedTime); - currentIndex++; + currentIndex ++; } } if (currentIndex != i) { length = animatableList.length; - while (i < length) + while(i < length) { - animatableList[currentIndex++] = animatableList[i++]; + animatableList[currentIndex ++] = animatableList[i ++]; } animatableList.length = currentIndex; } diff --git a/src/dragonBones/core/DBObject.as b/src/dragonBones/core/DBObject.as new file mode 100644 index 0000000..222829e --- /dev/null +++ b/src/dragonBones/core/DBObject.as @@ -0,0 +1,207 @@ +package dragonBones.core +{ + import dragonBones.Armature; + import dragonBones.Bone; + import dragonBones.animation.AnimationState; + import dragonBones.animation.TimelineState; + import dragonBones.core.dragonBones_internal; + import dragonBones.objects.DBTransform; + import dragonBones.objects.Frame; + + import flash.events.EventDispatcher; + import flash.geom.Matrix; + + use namespace dragonBones_internal; + + public class DBObject extends EventDispatcher + { + /** + * The name of this DBObject instance's Armature instance. + */ + public var name:String; + + /** + * An object that can contain any user extra data. + */ + public var userData:Object; + + /** + * + */ + public var fixedRotation:Boolean; + + /** @private */ + dragonBones_internal var _globalTransformMatrix:Matrix; + /** @private */ + protected var _scaleType:int; + /** @private */ + dragonBones_internal var _isColorChanged:Boolean; + + /** @private */ + protected var _global:DBTransform; + /** + * This DBObject instance global transform instance. + * @see dragonBones.objects.DBTransform + */ + public function get global():DBTransform + { + return _global; + } + + /** @private */ + protected var _origin:DBTransform; + /** + * This DBObject instance origin transform instance. + * @see dragonBones.objects.DBTransform + */ + public function get origin():DBTransform + { + return _origin; + } + + /** @private */ + protected var _offset:DBTransform; + /** + * This DBObject instance offset transform instance. + * @see dragonBones.objects.DBTransform + */ + public function get offset():DBTransform + { + return _offset; + } + public function get node():DBTransform + { + return _offset; + } + + /** @private */ + dragonBones_internal var _tween:DBTransform; + + /** @private */ + protected var _visible:Boolean; + public function get visible():Boolean + { + return _visible; + } + public function set visible(value:Boolean):void + { + _visible = value; + } + + /** @private */ + protected var _parent:Bone; + + /** + * Indicates the Bone instance that directly contains this DBObject instance if any. + */ + public function get parent():Bone + { + return _parent; + } + /** @private */ + dragonBones_internal function setParent(value:Bone):void + { + _parent = value; + } + + /** @private */ + protected var _armature:Armature; + /** + * The armature this DBObject instance belongs to. + */ + public function get armature():Armature + { + return _armature; + } + /** @private */ + dragonBones_internal function setArmature(value:Armature):void + { + if(_armature) + { + _armature.removeDBObject(this); + } + _armature = value; + if(_armature) + { + _armature.addDBObject(this); + } + } + + public function DBObject() + { + super(this); + + _global = new DBTransform(); + _origin = new DBTransform(); + _offset = new DBTransform(); + _tween = new DBTransform(); + _tween.scaleX = _tween.scaleY = 0; + + _globalTransformMatrix = new Matrix(); + + _visible = true; + } + + /** + * Cleans up any resources used by this DBObject instance. + */ + public function dispose():void + { + userData = null; + _parent = null; + _armature = null; + _global = null; + _origin = null; + _offset = null; + _tween = null; + _globalTransformMatrix = null; + } + + /** @private */ + dragonBones_internal function update():void + { + _global.scaleX = (_origin.scaleX + _tween.scaleX) * _offset.scaleX; + _global.scaleY = (_origin.scaleY + _tween.scaleY) * _offset.scaleY; + + if(_parent) + { + var x:Number = _origin.x + _offset.x + _tween.x; + var y:Number = _origin.y + _offset.y + _tween.y; + var parentMatrix:Matrix = _parent._globalTransformMatrix; + + _globalTransformMatrix.tx = _global.x = parentMatrix.a * x + parentMatrix.c * y + parentMatrix.tx; + _globalTransformMatrix.ty = _global.y = parentMatrix.d * y + parentMatrix.b * x + parentMatrix.ty; + + if(fixedRotation) + { + _global.skewX = _origin.skewX + _offset.skewX + _tween.skewX; + _global.skewY = _origin.skewY + _offset.skewY + _tween.skewY; + } + else + { + _global.skewX = _origin.skewX + _offset.skewX + _tween.skewX + _parent._global.skewX; + _global.skewY = _origin.skewY + _offset.skewY + _tween.skewY + _parent._global.skewY; + } + + if(_parent.scaleMode >= _scaleType) + { + _global.scaleX *= _parent._global.scaleX; + _global.scaleY *= _parent._global.scaleY; + } + } + else + { + _globalTransformMatrix.tx = _global.x = _origin.x + _offset.x + _tween.x; + _globalTransformMatrix.ty = _global.y = _origin.y + _offset.y + _tween.y; + + _global.skewX = _origin.skewX + _offset.skewX + _tween.skewX; + _global.skewY = _origin.skewY + _offset.skewY + _tween.skewY; + } + + _globalTransformMatrix.a = _global.scaleX * Math.cos(_global.skewY); + _globalTransformMatrix.b = _global.scaleX * Math.sin(_global.skewY); + _globalTransformMatrix.c = -_global.scaleY * Math.sin(_global.skewX); + _globalTransformMatrix.d = _global.scaleY * Math.cos(_global.skewX); + } + } +} \ No newline at end of file diff --git a/src/dragonBones/core/DragonBones.as b/src/dragonBones/core/DragonBones.as new file mode 100644 index 0000000..16db641 --- /dev/null +++ b/src/dragonBones/core/DragonBones.as @@ -0,0 +1,13 @@ +package dragonBones.core +{ + public final class DragonBones + { + public static const DATA_VERSION:String = "2.3"; + public static const VERSION:String = "2.3"; + public static const VERSION_NUMBER:int = 2305; + + public function DragonBones() + { + } + } +} \ No newline at end of file diff --git a/src/dragonBones/utils/dragonBones_internal.as b/src/dragonBones/core/dragonBones_internal.as similarity index 70% rename from src/dragonBones/utils/dragonBones_internal.as rename to src/dragonBones/core/dragonBones_internal.as index e84002c..44d9c34 100644 --- a/src/dragonBones/utils/dragonBones_internal.as +++ b/src/dragonBones/core/dragonBones_internal.as @@ -1,4 +1,4 @@ -package dragonBones.utils +package dragonBones.core { /** @private */ diff --git a/src/dragonBones/display/IDisplayBridge.as b/src/dragonBones/display/IDisplayBridge.as index 88c7e04..952d8b5 100644 --- a/src/dragonBones/display/IDisplayBridge.as +++ b/src/dragonBones/display/IDisplayBridge.as @@ -7,35 +7,67 @@ package dragonBones.display * @version 2.0 */ - import dragonBones.objects.BoneTransform; + import dragonBones.objects.DBTransform; + import flash.geom.ColorTransform; import flash.geom.Matrix; /** - * Provides an interface for display classes that can be used in this skeleton animation system. + * Provides an interface for display classes that can be used in this DragonBones animation system. * */ public interface IDisplayBridge { + function get visible():Boolean; + function set visible(value:Boolean):void; + /** * Indicates the original display object relative to specific display engine. */ function get display():Object; function set display(value:Object):void; + + /** + * Cleans up resources used by this IDisplayBridge instance. + */ + function dispose():void; + /** * Updates the transform of the display object * @param matrix - * @param node - * @param colorTransform - * @param visible + * @param transform + */ + function updateTransform(matrix:Matrix, transform:DBTransform):void; + + /** + * Updates the color of the display object + * @param a + * @param r + * @param g + * @param b + * @param aM + * @param rM + * @param gM + * @param bM */ - function update(matrix:Matrix, node:BoneTransform, colorTransform:ColorTransform, visible:Boolean):void; + function updateColor( + aOffset:Number, + rOffset:Number, + gOffset:Number, + bOffset:Number, + aMultiplier:Number, + rMultiplier:Number, + gMultiplier:Number, + bMultiplier:Number + ):void; + /** * Adds the original display object to another display object. * @param container * @param index */ function addDisplay(container:Object, index:int = -1):void; + /** * remove the original display object from its parent. */ diff --git a/src/dragonBones/display/NativeDisplayBridge.as b/src/dragonBones/display/NativeDisplayBridge.as index bf4de3c..2e7542f 100644 --- a/src/dragonBones/display/NativeDisplayBridge.as +++ b/src/dragonBones/display/NativeDisplayBridge.as @@ -8,7 +8,8 @@ package dragonBones.display */ - import dragonBones.objects.BoneTransform; + import dragonBones.objects.DBTransform; + import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; import flash.display.Shape; @@ -21,10 +22,8 @@ package dragonBones.display */ public class NativeDisplayBridge implements IDisplayBridge { - /** - * @private - */ - protected var _display:DisplayObject; + private var _display:DisplayObject; + private var _colorTransform:ColorTransform; /** * @inheritDoc @@ -33,9 +32,6 @@ package dragonBones.display { return _display; } - /** - * @private - */ public function set display(value:Object):void { if (_display == value) @@ -55,6 +51,21 @@ package dragonBones.display addDisplay(parent, index); } + /** + * @inheritDoc + */ + public function get visible():Boolean + { + return _display?_display.visible:false; + } + public function set visible(value:Boolean):void + { + if(_display) + { + _display.visible = value; + } + } + /** * Creates a new NativeDisplayBridge instance. */ @@ -65,19 +76,49 @@ package dragonBones.display /** * @inheritDoc */ - public function update(matrix:Matrix, node:BoneTransform, colorTransform:ColorTransform, visible:Boolean):void + public function dispose():void + { + _display = null; + _colorTransform = null; + } + + /** + * @inheritDoc + */ + public function updateTransform(matrix:Matrix, transform:DBTransform):void { - var pivotX:Number = node.pivotX; - var pivotY:Number = node.pivotY; - matrix.tx -= matrix.a * pivotX + matrix.c * pivotY; - matrix.ty -= matrix.b * pivotX + matrix.d * pivotY; - _display.transform.matrix = matrix; - if (colorTransform) + } + + /** + * @inheritDoc + */ + public function updateColor( + aOffset:Number, + rOffset:Number, + gOffset:Number, + bOffset:Number, + aMultiplier:Number, + rMultiplier:Number, + gMultiplier:Number, + bMultiplier:Number + ):void + { + if(!_colorTransform) { - _display.transform.colorTransform = colorTransform; + _colorTransform = _display.transform.colorTransform; } - _display.visible = visible; + _colorTransform.alphaOffset = aOffset; + _colorTransform.redOffset = rOffset; + _colorTransform.greenOffset = gOffset; + _colorTransform.blueOffset = bOffset; + + _colorTransform.alphaMultiplier = aMultiplier; + _colorTransform.redMultiplier = rMultiplier; + _colorTransform.greenMultiplier = gMultiplier; + _colorTransform.blueMultiplier = bMultiplier; + + _display.transform.colorTransform = _colorTransform; } /** diff --git a/src/dragonBones/display/StarlingDisplayBridge.as b/src/dragonBones/display/StarlingDisplayBridge.as index fbd66b9..28cdab7 100644 --- a/src/dragonBones/display/StarlingDisplayBridge.as +++ b/src/dragonBones/display/StarlingDisplayBridge.as @@ -8,14 +8,16 @@ */ - import dragonBones.objects.BoneTransform; + import dragonBones.objects.DBTransform; + import flash.geom.ColorTransform; import flash.geom.Matrix; import starling.display.DisplayObject; import starling.display.DisplayObjectContainer; - import starling.display.Quad; import starling.display.Image; + import starling.display.Quad; + import starling.textures.Texture; /** * The StarlingDisplayBridge class is an implementation of the IDisplayBridge interface for starling.display.DisplayObject. @@ -23,10 +25,12 @@ */ public class StarlingDisplayBridge implements IDisplayBridge { - /** - * @private - */ - protected var _display:Object; + private var _imageBackup:Image; + private var _textureBackup:Texture; + private var _pivotXBackup:Number; + private var _pivotYBackup:Number; + + private var _display:Object; /** * @inheritDoc */ @@ -34,34 +38,36 @@ { return _display; } - /** - * @private - */ public function set display(value:Object):void { - if (_display == value) - { - return; - } - - //Thanks Jian - //bug replace image.texture will lost displayList[0].texture - /*if (_display is Image && value is Image) + if (_display is Image && value is Image) { var from:Image = _display as Image; var to:Image = value as Image; if (from.texture == to.texture) { + if(from == _imageBackup) + { + from.texture = _textureBackup; + from.pivotX = _pivotXBackup; + from.pivotY = _pivotYBackup; + from.readjustSize(); + } return; } - + from.texture = to.texture; //update pivot from.pivotX = to.pivotX; from.pivotY = to.pivotY; from.readjustSize(); return; - }*/ + } + + if (_display == value) + { + return; + } if (_display) { @@ -72,10 +78,29 @@ } removeDisplay(); } + else if(value is Image && !_imageBackup) + { + _imageBackup = value as Image; + _textureBackup = _imageBackup.texture; + _pivotXBackup = _imageBackup.pivotX; + _pivotYBackup = _imageBackup.pivotY; + } _display = value; addDisplay(parent, index); } + public function get visible():Boolean + { + return _display?_display.visible:false; + } + public function set visible(value:Boolean):void + { + if(_display) + { + _display.visible = value; + } + } + /** * Creates a new StarlingDisplayBridge instance. */ @@ -86,29 +111,51 @@ /** * @inheritDoc */ - public function update(matrix:Matrix, node:BoneTransform, colorTransform:ColorTransform, visible:Boolean):void + public function dispose():void { - var pivotX:Number = node.pivotX + _display.pivotX; - var pivotY:Number = node.pivotY + _display.pivotY; + _display = null; + _imageBackup = null; + _textureBackup = null; + } + + /** + * @inheritDoc + */ + public function updateTransform(matrix:Matrix, transform:DBTransform):void + { + var pivotX:Number = _display.pivotX; + var pivotY:Number = _display.pivotY; matrix.tx -= matrix.a * pivotX + matrix.c * pivotY; matrix.ty -= matrix.b * pivotX + matrix.d * pivotY; - //if(updateStarlingDisplay) //{ - //_display.transformationMatrix = matrix; + // _display.transformationMatrix = matrix; //} //else //{ - _display.transformationMatrix.copyFrom(matrix); + _display.transformationMatrix.copyFrom(matrix); //} - - if (colorTransform && _display is Quad) + } + + /** + * @inheritDoc + */ + public function updateColor( + aOffset:Number, + rOffset:Number, + gOffset:Number, + bOffset:Number, + aMultiplier:Number, + rMultiplier:Number, + gMultiplier:Number, + bMultiplier:Number + ):void + { + if (_display is Quad) { - (_display as Quad).alpha = colorTransform.alphaMultiplier; - (_display as Quad).color = (uint(colorTransform.redMultiplier * 0xff) << 16) + (uint(colorTransform.greenMultiplier * 0xff) << 8) + uint(colorTransform.blueMultiplier * 0xff); + (_display as Quad).alpha = aMultiplier; + (_display as Quad).color = (uint(rMultiplier * 0xff) << 16) + (uint(gMultiplier * 0xff) << 8) + uint(bMultiplier * 0xff); } - // - _display.visible = visible; } /** @@ -140,4 +187,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/dragonBones/errors/UnknownDataError.as b/src/dragonBones/errors/UnknownDataError.as deleted file mode 100644 index 7333ff6..0000000 --- a/src/dragonBones/errors/UnknownDataError.as +++ /dev/null @@ -1,20 +0,0 @@ -package dragonBones.errors -{ - /** - * Copyright 2012-2013. DragonBones. All Rights Reserved. - * @playerversion Flash 10.0, Flash 10 - * @langversion 3.0 - * @version 2.0 - */ - - /** - * Thrown when dragonBones encounters an unknow error. - */ - public final class UnknownDataError extends Error - { - public function UnknownDataError(message:* = "", id:* = 0) - { - super(message, id); - } - } -} \ No newline at end of file diff --git a/src/dragonBones/events/AnimationEvent.as b/src/dragonBones/events/AnimationEvent.as index 7d8a1d0..110d969 100644 --- a/src/dragonBones/events/AnimationEvent.as +++ b/src/dragonBones/events/AnimationEvent.as @@ -7,6 +7,7 @@ * @version 2.0 */ import dragonBones.Armature; + import dragonBones.animation.AnimationState; import flash.events.Event; @@ -19,9 +20,22 @@ public class AnimationEvent extends Event { /** - * Dispatched when the movement of animation is changed. + * Dispatched when the playback of an animation fade in. */ - public static const MOVEMENT_CHANGE:String = "movementChange"; + public static function get MOVEMENT_CHANGE():String + { + return FADE_IN; + } + + /** + * Dispatched when the playback of an animation fade in. + */ + public static const FADE_IN:String = "fadeIn"; + + /** + * Dispatched when the playback of an animation fade out. + */ + public static const FADE_OUT:String = "fadeOut"; /** * Dispatched when the playback of an animation starts. @@ -29,22 +43,29 @@ public static const START:String = "start"; /** - * Dispatched when the playback of a movement stops. + * Dispatched when the playback of a animation stops. */ public static const COMPLETE:String = "complete"; /** - * Dispatched when the playback of a movement completes a loop. + * Dispatched when the playback of a animation completes a loop. */ public static const LOOP_COMPLETE:String = "loopComplete"; + + /** + * Dispatched when the playback of an animation fade in complete. + */ + public static const FADE_IN_COMPLETE:String = "fadeInComplete"; + /** - * The preceding MovementData id. + * Dispatched when the playback of an animation fade out complete. */ - public var exMovementID:String; + public static const FADE_OUT_COMPLETE:String = "fadeOutComplete"; + /** - * The current MovementData id. + * The animationState instance. */ - public var movementID:String; + public var animationState:AnimationState; /** * The armature that is the taget of this event. @@ -54,6 +75,11 @@ return target as Armature; } + public function get movementID():String + { + return animationState.name; + } + /** * Creates a new AnimationEvent instance. * @param type @@ -71,8 +97,7 @@ override public function clone():Event { var event:AnimationEvent = new AnimationEvent(type, cancelable); - event.exMovementID = exMovementID; - event.movementID = movementID; + event.animationState = animationState; return event; } } diff --git a/src/dragonBones/events/ArmatureEvent.as b/src/dragonBones/events/ArmatureEvent.as index aab0024..7578fe5 100644 --- a/src/dragonBones/events/ArmatureEvent.as +++ b/src/dragonBones/events/ArmatureEvent.as @@ -7,7 +7,7 @@ package dragonBones.events * @version 2.0 */ import flash.events.Event; -/** + /** * The ArmatureEvent provides and defines all events dispatched directly by an Armature instance. * * @@ -16,15 +16,16 @@ package dragonBones.events public class ArmatureEvent extends Event { - /** - * Dispatched after a successful z order update. - */ + /** + * Dispatched after a successful z order update. + */ public static const Z_ORDER_UPDATED:String = "zOrderUpdated"; public function ArmatureEvent(type:String) { super(type, false, false); } + /** * @private * @return diff --git a/src/dragonBones/events/FrameEvent.as b/src/dragonBones/events/FrameEvent.as index 78a7706..d2bec61 100644 --- a/src/dragonBones/events/FrameEvent.as +++ b/src/dragonBones/events/FrameEvent.as @@ -8,6 +8,8 @@ package dragonBones.events */ import dragonBones.Armature; import dragonBones.Bone; + import dragonBones.animation.AnimationState; + import dragonBones.core.DBObject; import flash.events.Event; @@ -19,23 +21,28 @@ package dragonBones.events */ public class FrameEvent extends Event { + public static function get MOVEMENT_FRAME_EVENT():String + { + return ANIMATION_FRAME_EVENT; + } + /** * Dispatched when the animation of the armatrue enter a frame. */ - public static const MOVEMENT_FRAME_EVENT:String = "movementFrameEvent"; - /** - * Dispatched when a bone of the armature enter a frame. - */ - public static const BONE_FRAME_EVENT:String = "boneFrameEvent"; + public static const ANIMATION_FRAME_EVENT:String = "animationFrameEvent"; + /** - * The id of the MovementData instance. + * */ - public var movementID:String; + public static const BONE_FRAME_EVENT:String ="boneFrameEvent"; + /** * The entered frame label. */ public var frameLabel:String; + public var bone:Bone; + /** * The armature that is the target of this event. */ @@ -44,26 +51,19 @@ package dragonBones.events return target as Armature; } - /** @private */ - private var _bone:Bone; - /** - * The bone that is the target of this event. + * The animationState instance. */ - public function get bone():Bone - { - return _bone; - } + public var animationState:AnimationState; /** * Creates a new FrameEvent instance. * @param type * @param cancelable */ - public function FrameEvent(type:String, cancelable:Boolean = false, bone:Bone = null) + public function FrameEvent(type:String, cancelable:Boolean = false) { super(type, false, cancelable); - _bone = bone; } /** @@ -74,9 +74,9 @@ package dragonBones.events override public function clone():Event { var event:FrameEvent = new FrameEvent(type, cancelable); - event.movementID = movementID; + event.animationState = animationState; + event.bone = bone; event.frameLabel = frameLabel; - event._bone = _bone; return event; } } diff --git a/src/dragonBones/events/SoundEvent.as b/src/dragonBones/events/SoundEvent.as index 518e719..9a6cba8 100644 --- a/src/dragonBones/events/SoundEvent.as +++ b/src/dragonBones/events/SoundEvent.as @@ -7,12 +7,10 @@ package dragonBones.events * @version 2.0 */ import dragonBones.Armature; - import dragonBones.Bone; - import dragonBones.utils.dragonBones_internal; + import dragonBones.animation.AnimationState; import flash.events.Event; - - use namespace dragonBones_internal; + /** * The SoundEvent provides and defines all sound related events dispatched during an animation. * @@ -26,32 +24,14 @@ package dragonBones.events */ public static const SOUND:String = "sound"; - public var movementID:String; - - public var sound:String; - public var soundEffect:String; - - /** @private */ - dragonBones_internal var _armature:Armature; - /** * The armature that is the target of this event. */ - public function get armature():Armature - { - return _armature; - } + public var armature:Armature; - /** @private */ - dragonBones_internal var _bone:Bone; + public var animationState:AnimationState; - /** - * The bone that is the target of this event. - */ - public function get bone():Bone - { - return _bone; - } + public var sound:String; /** * Creates a new SoundEvent instance. @@ -69,11 +49,9 @@ package dragonBones.events override public function clone():Event { var event:SoundEvent = new SoundEvent(type, cancelable); - event.movementID = movementID; + event.armature = armature; + event.animationState = animationState; event.sound = sound; - event.soundEffect = soundEffect; - event._armature = _armature; - event._bone = _bone; return event; } } diff --git a/src/dragonBones/factorys/BaseFactory.as b/src/dragonBones/factorys/BaseFactory.as index 35e3021..b7c3a37 100644 --- a/src/dragonBones/factorys/BaseFactory.as +++ b/src/dragonBones/factorys/BaseFactory.as @@ -1,37 +1,31 @@ package dragonBones.factorys { - - /** - * Copyright 2012-2013. DragonBones. All Rights Reserved. - * @playerversion Flash 10.0, Flash 10 - * @langversion 3.0 - * @version 2.0 - */ - import dragonBones.Armature; import dragonBones.Bone; - import dragonBones.display.NativeDisplayBridge; + import dragonBones.Slot; + import dragonBones.core.dragonBones_internal; import dragonBones.objects.AnimationData; import dragonBones.objects.ArmatureData; import dragonBones.objects.BoneData; + import dragonBones.objects.DataParser; import dragonBones.objects.DecompressedData; import dragonBones.objects.DisplayData; import dragonBones.objects.SkeletonData; - import dragonBones.objects.XMLDataParser; + import dragonBones.objects.SkinData; + import dragonBones.objects.SlotData; import dragonBones.textures.ITextureAtlas; - import dragonBones.textures.NativeTextureAtlas; - import dragonBones.textures.SubTextureData; import dragonBones.utils.BytesType; - import dragonBones.utils.dragonBones_internal; import flash.display.Bitmap; import flash.display.Loader; import flash.display.MovieClip; - import flash.display.Shape; import flash.display.Sprite; + import flash.errors.IllegalOperationError; import flash.events.Event; import flash.events.EventDispatcher; import flash.geom.Matrix; + import flash.geom.Point; + import flash.system.ApplicationDomain; import flash.system.LoaderContext; import flash.utils.ByteArray; @@ -40,54 +34,33 @@ package dragonBones.factorys /** Dispatched after a sucessful call to parseData(). */ [Event(name="complete", type="flash.events.Event")] - /** - * A BaseFactory instance manages the set of armature resources for the tranditional Flash DisplayList. It parses the raw data (ByteArray), stores the armature resources and creates armature instances. - *

Create an instance of the BaseFactory class that way:

- * - * import flash.events.Event; - * import dragonBones.factorys.BaseFactory; - * - * [Embed(source = "../assets/Dragon1.swf", mimeType = "application/octet-stream")] - * private static const ResourcesData:Class; - * var factory:BaseFactory = new BaseFactory(); - * factory.addEventListener(Event.COMPLETE, textureCompleteHandler); - * factory.parseData(new ResourcesData()); - * - * @see dragonBones.Armature - */ public class BaseFactory extends EventDispatcher { - private static var _loaderContext:LoaderContext = new LoaderContext(false); /** @private */ - protected static var _helpMatirx:Matrix = new Matrix(); + protected static const _helpMatirx:Matrix = new Matrix(); + private static const _loaderContext:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain); + /** @private */ - protected var _skeletonDataDic:Object; + protected var _dataDic:Object; /** @private */ protected var _textureAtlasDic:Object; /** @private */ protected var _textureAtlasLoadingDic:Object; /** @private */ - protected var _currentSkeletonData:SkeletonData; - /** @private */ - protected var _currentTextureAtlas:Object; - /** @private */ - protected var _currentSkeletonName:String; + protected var _currentDataName:String; /** @private */ protected var _currentTextureAtlasName:String; - /** - * Create a Basefactory instance. - * - * @example - * - * import dragonBones.factorys.BaseFactory; - * var factory:BaseFactory = new BaseFactory(); - * - */ - public function BaseFactory() + public function BaseFactory(self:BaseFactory) { - super(); - _skeletonDataDic = {}; + super(this); + + if(self != this) + { + throw new IllegalOperationError("Abstract class can not be instantiated!"); + } + + _dataDic = {}; _textureAtlasDic = {}; _textureAtlasLoadingDic = {}; _loaderContext.allowCodeImport = true; @@ -100,65 +73,77 @@ package dragonBones.factorys * import flash.events.Event; * import dragonBones.factorys.BaseFactory; * - * [Embed(source = "../assets/Dragon1.swf", mimeType = "application/octet-stream")] + * [Embed(source = "../assets/Dragon1.swf", mimeType = "application/octet-stream")] * private static const ResourcesData:Class; * var factory:BaseFactory = new BaseFactory(); * factory.addEventListener(Event.COMPLETE, textureCompleteHandler); * factory.parseData(new ResourcesData()); * - * @param ByteArray. Represents the raw data for the whole skeleton system. + * @param ByteArray. Represents the raw data for the whole DragonBones system. * @param String. (optional) The SkeletonData instance name. * @return A SkeletonData instance. */ - public function parseData(bytes:ByteArray, skeletonName:String = null):SkeletonData + public function parseData(bytes:ByteArray, dataName:String = null):SkeletonData { - var decompressedData:DecompressedData = XMLDataParser.decompressData(bytes); - var skeletonData:SkeletonData = XMLDataParser.parseSkeletonData(decompressedData.skeletonXML); - skeletonName = skeletonName || skeletonData.name; - addSkeletonData(skeletonData, skeletonName); + if(!bytes) + { + throw new ArgumentError(); + } + var decompressedData:DecompressedData = DataParser.decompressData(bytes); + + var data:SkeletonData = DataParser.parseData(decompressedData.dragonBonesData); + + dataName = dataName || data.name; + addSkeletonData(data, dataName); var loader:Loader = new Loader(); - loader.name = skeletonName; - _textureAtlasLoadingDic[skeletonName] = decompressedData.textureAtlasXML; + loader.name = dataName; + _textureAtlasLoadingDic[dataName] = decompressedData.textureAtlasData; loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleteHandler); - loader.loadBytes(decompressedData.textureBytes, _loaderContext); + loader.loadBytes(decompressedData.textureBytes, _loaderContext); decompressedData.dispose(); - return skeletonData; + return data; } + /** * Returns a SkeletonData instance. * @example * - * var skeleton:SkeletonData = factory.getSkeletonData('dragon'); + * var data:SkeletonData = factory.getSkeletonData('dragon'); * * @param The name of an existing SkeletonData instance. * @return A SkeletonData instance with given name (if exist). */ public function getSkeletonData(name:String):SkeletonData { - return _skeletonDataDic[name]; + return _dataDic[name]; } /** * Add a SkeletonData instance to this BaseFactory instance. * @example * - * factory.addSkeletonData(skeletondata, 'dragon'); + * factory.addSkeletonData(data, 'dragon'); * - * @param A skeletonData instance. + * @param A SkeletonData instance. * @param (optional) A name for this SkeletonData instance. */ - public function addSkeletonData(skeletonData:SkeletonData, name:String = null):void + public function addSkeletonData(data:SkeletonData, name:String = null):void { - name = name || skeletonData.name; + if(!data) + { + throw new ArgumentError(); + } + name = name || data.name; if(!name) { throw new ArgumentError("Unnamed data!"); } - if(skeletonData) + if(_dataDic[name]) { - _skeletonDataDic[name] = skeletonData; + } + _dataDic[name] = data; } /** @@ -171,7 +156,7 @@ package dragonBones.factorys */ public function removeSkeletonData(name:String):void { - delete _skeletonDataDic[name]; + delete _dataDic[name]; } /** @@ -199,19 +184,23 @@ package dragonBones.factorys */ public function addTextureAtlas(textureAtlas:Object, name:String = null):void { + if(!textureAtlas) + { + throw new ArgumentError(); + } if(!name && textureAtlas is ITextureAtlas) { name = textureAtlas.name; } - if(!name) { throw new ArgumentError("Unnamed data!"); } - if(textureAtlas) + if(_textureAtlasDic[name]) { - _textureAtlasDic[name] = textureAtlas; + } + _textureAtlasDic[name] = textureAtlas; } /** @@ -227,112 +216,173 @@ package dragonBones.factorys delete _textureAtlasDic[name]; } - - - /** - * Cleans up resources used by this BaseFactory instance. + /** + * Cleans up resources used by this BaseFactory instance. * @example * * factory.dispose(); * - * @param (optional) Destroy all internal references. - */ + * @param (optional) Destroy all internal references. + */ public function dispose(disposeData:Boolean = true):void { if(disposeData) { - for each(var skeletonData:SkeletonData in _skeletonDataDic) + for each(var data:SkeletonData in _dataDic) { - skeletonData.dispose(); + data.dispose(); } for each(var textureAtlas:Object in _textureAtlasDic) { textureAtlas.dispose(); } } - _skeletonDataDic = {}; - _textureAtlasDic = {}; - _textureAtlasLoadingDic = {}; - _currentSkeletonData = null; - _currentTextureAtlas = null; - _currentSkeletonName = null; + _dataDic = null + _textureAtlasDic = null; + _textureAtlasLoadingDic = null; + _currentDataName = null; _currentTextureAtlasName = null; } - /** - * Build and returns a new Armature instance. + /** + * Build and returns a new Armature instance. * @example * * var armature:Armature = factory.buildArmature('dragon'); * - * @param The name of this Armature instance. - * @param The name of this animation. - * @param The name of this skeleton. - * @param The name of this textureAtlas. - * @return A Armature instance. - */ - public function buildArmature(armatureName:String, animationName:String = null, skeletonName:String = null, textureAtlasName:String = null):Armature + * @param armatureName The name of this Armature instance. + * @param The name of this animation. + * @param The name of this SkeletonData. + * @param The name of this textureAtlas. + * @param The name of this skin. + * @return A Armature instance. + */ + public function buildArmature(armatureName:String, animationName:String = null, skeletonName:String = null, textureAtlasName:String = null, skinName:String = null):Armature { - animationName = animationName || armatureName; - var skeletonData:SkeletonData; - var armatureData:ArmatureData; if(skeletonName) { - skeletonData = _skeletonDataDic[skeletonName]; - if(skeletonData) + var data:SkeletonData = _dataDic[skeletonName]; + if(data) { - armatureData = skeletonData.getArmatureData(armatureName); + var armatureData:ArmatureData = data.getArmatureData(armatureName); } } else { - for (skeletonName in _skeletonDataDic) + for (skeletonName in _dataDic) { - skeletonData = _skeletonDataDic[skeletonName]; - armatureData = skeletonData.getArmatureData(armatureName); + data = _dataDic[skeletonName]; + armatureData = data.getArmatureData(armatureName); if(armatureData) { break; } } } + if(!armatureData) { return null; } - _currentSkeletonName = skeletonName; - _currentSkeletonData = skeletonData; + + _currentDataName = skeletonName; _currentTextureAtlasName = textureAtlasName || skeletonName; - _currentTextureAtlas = _textureAtlasDic[_currentTextureAtlasName]; - var animationData:AnimationData = _currentSkeletonData.getAnimationData(animationName); - if(!animationData) + + var armature:Armature = generateArmature(); + armature.name = armatureName; + var bone:Bone; + for each(var boneData:BoneData in armatureData.boneDataList) + { + bone = new Bone(); + bone.name = boneData.name; + bone.origin.copy(boneData.transform); + if(armatureData.getBoneData(boneData.parent)) + { + armature.addBone(bone, boneData.parent); + } + else + { + armature.addBone(bone); + } + } + + if(animationName && animationName != armatureName) { - for (skeletonName in _skeletonDataDic) + var animationArmatureData:ArmatureData = data.getArmatureData(animationName); + if(!animationArmatureData) { - skeletonData = _skeletonDataDic[skeletonName]; - animationData = skeletonData.getAnimationData(animationName); - if(animationData) + for (skeletonName in _dataDic) { - break; + data = _dataDic[skeletonName]; + animationArmatureData = data.getArmatureData(animationName); + if(animationArmatureData) + { + break; + } } } - } - var armature:Armature = generateArmature(); - armature.name = armatureName; - armature.animation.animationData = animationData; - var boneNames:Vector. = armatureData.boneNames; - for each(var boneName:String in boneNames) + } + + if(animationArmatureData) + { + armature.animation.animationDataList = animationArmatureData.animationDataList; + } + else { - var boneData:BoneData = armatureData.getBoneData(boneName); - if(boneData) + armature.animation.animationDataList = armatureData.animationDataList; + } + + var skinData:SkinData = armatureData.getSkinData(skinName); + if(!skinData) + { + throw new ArgumentError(); + } + + var slot:Slot; + var displayData:DisplayData; + var childArmature:Armature; + var i:int; + var helpArray:Array = []; + for each(var slotData:SlotData in skinData.slotDataList) + { + bone = armature.getBone(slotData.parent); + if(!bone) { - var bone:Bone = buildBone(boneData); - bone.name = boneName; - armature.addBone(bone, boneData.parent); + continue; } + slot = generateSlot(); + slot.name = slotData.name; + slot._originZOrder = slotData.zOrder; + slot._dislayDataList = slotData.displayDataList; + + helpArray.length = 0; + i = slotData.displayDataList.length; + while(i --) + { + displayData = slotData.displayDataList[i]; + + switch(displayData.type) + { + case DisplayData.ARMATURE: + childArmature = buildArmature(displayData.name, null, _currentDataName, _currentTextureAtlasName); + if(childArmature) + { + helpArray[i] = childArmature; + } + break; + case DisplayData.IMAGE: + default: + helpArray[i] = generateDisplay(_textureAtlasDic[_currentTextureAtlasName], displayData.name, displayData.pivot.x, displayData.pivot.y); + break; + + } + } + slot.displayList = helpArray; + slot.changeDisplay(0); + bone.addChild(slot); } - armature._bonesIndexChanged = true; - armature.update(); + armature._slotsZOrderChanged = true; + armature.advanceTime(0); return armature; } @@ -350,12 +400,11 @@ package dragonBones.factorys */ public function getTextureDisplay(textureName:String, textureAtlasName:String = null, pivotX:Number = NaN, pivotY:Number = NaN):Object { - var textureAtlas:Object; if(textureAtlasName) { - textureAtlas = _textureAtlasDic[textureAtlasName]; + var textureAtlas:Object = _textureAtlasDic[textureAtlasName]; } - else + if(!textureAtlas && !textureAtlasName) { for (textureAtlasName in _textureAtlasDic) { @@ -371,50 +420,23 @@ package dragonBones.factorys { if(isNaN(pivotX) || isNaN(pivotY)) { - var skeletonData:SkeletonData = _skeletonDataDic[textureAtlasName]; - if(skeletonData) + var data:SkeletonData = _dataDic[textureAtlasName]; + if(data) { - var displayData:DisplayData = skeletonData.getDisplayData(textureName); - if(displayData) + var pivot:Point = data.getSubTexturePivot(textureName); + if(pivot) { - pivotX = pivotX || displayData.pivotX; - pivotY = pivotY || displayData.pivotY; + pivotX = pivot.x; + pivotY = pivot.y; } } } - return generateTextureDisplay(textureAtlas, textureName, pivotX, pivotY); + return generateDisplay(textureAtlas, textureName, pivotX, pivotY); } return null; } - /** @private */ - protected function buildBone(boneData:BoneData):Bone - { - var bone:Bone = generateBone(); - bone.origin.copy(boneData.node); - - var displayData:DisplayData; - for(var i:int = boneData._displayNames.length - 1;i >= 0;i --) - { - var displayName:String = boneData._displayNames[i]; - displayData = _currentSkeletonData.getDisplayData(displayName); - bone.changeDisplay(i); - if (displayData.isArmature) - { - var childArmature:Armature = buildArmature(displayName, null, _currentSkeletonName, _currentTextureAtlasName); - if(childArmature) - { - childArmature.animation.play(); - bone.display = childArmature; - } - } - else - { - bone.display = generateTextureDisplay(_currentTextureAtlas, displayName, displayData.pivotX, displayData.pivotY); - } - } - return bone; - } + /** @private */ protected function loaderCompleteHandler(e:Event):void { @@ -423,10 +445,10 @@ package dragonBones.factorys var content:Object = e.target.content; loader.unloadAndStop(); - var skeletonName:String = loader.name; - var textureAtlasXML:XML = _textureAtlasLoadingDic[skeletonName]; - delete _textureAtlasLoadingDic[skeletonName]; - if(skeletonName && textureAtlasXML) + var name:String = loader.name; + var textureAtlasRawData:Object = _textureAtlasLoadingDic[name]; + delete _textureAtlasLoadingDic[name]; + if(name && textureAtlasRawData) { if (content is Bitmap) { @@ -441,88 +463,56 @@ package dragonBones.factorys // } - var textureAtlas:Object = generateTextureAtlas(content, textureAtlasXML); - addTextureAtlas(textureAtlas, skeletonName); + var textureAtlas:Object = generateTextureAtlas(content, textureAtlasRawData); + addTextureAtlas(textureAtlas, name); - skeletonName = null; - for(skeletonName in _textureAtlasLoadingDic) + name = null; + for(name in _textureAtlasLoadingDic) { break; } // - if(!skeletonName && hasEventListener(Event.COMPLETE)) + if(!name && this.hasEventListener(Event.COMPLETE)) { - dispatchEvent(new Event(Event.COMPLETE)); + this.dispatchEvent(new Event(Event.COMPLETE)); } } } + /** @private */ - protected function generateTextureAtlas(content:Object, textureAtlasXML:XML):Object + protected function generateTextureAtlas(content:Object, textureAtlasRawData:Object):ITextureAtlas { - var textureAtlas:NativeTextureAtlas = new NativeTextureAtlas(content, textureAtlasXML); - return textureAtlas; + return null; } - /** @private */ + + /** + * Generates an Armature instance. + * @return Armature An Armature instance. + */ protected function generateArmature():Armature { - var display:Sprite = new Sprite(); - var armature:Armature = new Armature(display); - return armature; + return null; } - /** @private */ - protected function generateBone():Bone + + /** + * Generates an Slot instance. + * @return Slot An Slot instance. + */ + protected function generateSlot():Slot { - var bone:Bone = new Bone(new NativeDisplayBridge()); - return bone; + return null; } - protected function generateTextureDisplay(textureAtlas:Object, fullName:String, pivotX:Number, pivotY:Number):Object + /** + * Generates a DisplayObject + * @param textureAtlas The TextureAtlas. + * @param fullName A qualified name. + * @param pivotX A pivot x based value. + * @param pivotY A pivot y based value. + * @return + */ + protected function generateDisplay(textureAtlas:Object, fullName:String, pivotX:Number, pivotY:Number):Object { - var nativeTextureAtlas:NativeTextureAtlas = textureAtlas as NativeTextureAtlas; - if(nativeTextureAtlas){ - var movieClip:MovieClip = nativeTextureAtlas.movieClip; - if (movieClip && movieClip.totalFrames >= 3) - { - movieClip.gotoAndStop(movieClip.totalFrames); - movieClip.gotoAndStop(fullName); - if (movieClip.numChildren > 0) - { - try - { - var displaySWF:Object = movieClip.getChildAt(0); - displaySWF.x = 0; - displaySWF.y = 0; - return displaySWF; - } - catch(e:Error) - { - throw "Can not get the movie clip, please make sure the version of the resource compatible with app version!"; - } - } - } - else if(nativeTextureAtlas.bitmapData) - { - var subTextureData:SubTextureData = nativeTextureAtlas.getRegion(fullName) as SubTextureData; - if (subTextureData) - { - var displayShape:Shape = new Shape(); - //1.4 - pivotX = pivotX || subTextureData.pivotX; - pivotY = pivotY || subTextureData.pivotY; - _helpMatirx.a = 1; - _helpMatirx.b = 0; - _helpMatirx.c = 0; - _helpMatirx.d = 1; - _helpMatirx.scale(nativeTextureAtlas.scale, nativeTextureAtlas.scale); - _helpMatirx.tx = -subTextureData.x - pivotX; - _helpMatirx.ty = -subTextureData.y - pivotY; - - displayShape.graphics.beginBitmapFill(nativeTextureAtlas.bitmapData, _helpMatirx, false, true); - displayShape.graphics.drawRect(-pivotX, -pivotY, subTextureData.width, subTextureData.height); - return displayShape; - } - } - } return null; } } diff --git a/src/dragonBones/factorys/NativeFactory.as b/src/dragonBones/factorys/NativeFactory.as new file mode 100644 index 0000000..6d27dbb --- /dev/null +++ b/src/dragonBones/factorys/NativeFactory.as @@ -0,0 +1,106 @@ +package dragonBones.factorys +{ + import dragonBones.Armature; + import dragonBones.Slot; + import dragonBones.display.NativeDisplayBridge; + import dragonBones.textures.ITextureAtlas; + import dragonBones.textures.NativeTextureAtlas; + + import flash.display.MovieClip; + import flash.display.Shape; + import flash.display.Sprite; + import flash.geom.Rectangle; + + /** + * Copyright 2012-2013. DragonBones. All Rights Reserved. + * @playerversion Flash 10.0, Flash 10 + * @langversion 3.0 + * @version 2.0 + */ + + public class NativeFactory extends BaseFactory + { + public var fillBitmapSmooth:Boolean; + + public function NativeFactory() + { + super(this); + } + + /** @private */ + override protected function generateTextureAtlas(content:Object, textureAtlasRawData:Object):ITextureAtlas + { + var textureAtlas:NativeTextureAtlas = new NativeTextureAtlas(content, textureAtlasRawData, 1, false); + return textureAtlas; + } + + /** @private */ + override protected function generateArmature():Armature + { + var display:Sprite = new Sprite(); + var armature:Armature = new Armature(display); + return armature; + } + + /** @private */ + override protected function generateSlot():Slot + { + var slot:Slot = new Slot(new NativeDisplayBridge()); + return slot; + } + + /** @private */ + override protected function generateDisplay(textureAtlas:Object, fullName:String, pivotX:Number, pivotY:Number):Object + { + var nativeTextureAtlas:NativeTextureAtlas = textureAtlas as NativeTextureAtlas; + if(nativeTextureAtlas) + { + var movieClip:MovieClip = nativeTextureAtlas.movieClip; + if (movieClip && movieClip.totalFrames >= 3) + { + movieClip.gotoAndStop(movieClip.totalFrames); + movieClip.gotoAndStop(fullName); + if (movieClip.numChildren > 0) + { + try + { + var displaySWF:Object = movieClip.getChildAt(0); + displaySWF.x = 0; + displaySWF.y = 0; + return displaySWF; + } + catch(e:Error) + { + throw new Error("Can not get the movie clip, please make sure the version of the resource compatible with app version!"); + } + } + } + else if(nativeTextureAtlas.bitmapData) + { + var subTextureData:Rectangle = nativeTextureAtlas.getRegion(fullName); + if (subTextureData) + { + var displayShape:Shape = new Shape(); + _helpMatirx.a = 1; + _helpMatirx.b = 0; + _helpMatirx.c = 0; + _helpMatirx.d = 1; + _helpMatirx.scale(nativeTextureAtlas.scale, nativeTextureAtlas.scale); + _helpMatirx.tx = -pivotX - subTextureData.x; + _helpMatirx.ty = -pivotY - subTextureData.y; + + displayShape.graphics.beginBitmapFill(nativeTextureAtlas.bitmapData, _helpMatirx, false, fillBitmapSmooth); + displayShape.graphics.drawRect(-pivotX, -pivotY, subTextureData.width, subTextureData.height); + + return displayShape; + } + } + else + { + throw new Error(); + } + } + return null; + } + } +} \ No newline at end of file diff --git a/src/dragonBones/factorys/StarlingFactory.as b/src/dragonBones/factorys/StarlingFactory.as index d1f059e..3c30eb3 100644 --- a/src/dragonBones/factorys/StarlingFactory.as +++ b/src/dragonBones/factorys/StarlingFactory.as @@ -8,26 +8,26 @@ */ import dragonBones.Armature; import dragonBones.Bone; + import dragonBones.Slot; + import dragonBones.core.dragonBones_internal; import dragonBones.display.StarlingDisplayBridge; import dragonBones.textures.ITextureAtlas; import dragonBones.textures.StarlingTextureAtlas; - import dragonBones.textures.SubTextureData; - import dragonBones.utils.ConstValues; - import dragonBones.utils.dragonBones_internal; + import flash.display.BitmapData; import flash.display.MovieClip; - import flash.geom.Rectangle; - import flash.utils.ByteArray; + import starling.core.Starling; import starling.display.Image; import starling.display.Sprite; import starling.textures.SubTexture; import starling.textures.Texture; - import starling.textures.TextureAtlas; + import starling.textures.TextureAtlas; + use namespace dragonBones_internal; /** - * A object managing the set of armature resources for Starling engine. It parses the raw data, stores the armature resources and creates armature instrances. + * A object managing the set of armature resources for Starling engine. It parses the raw data, stores the armature resources and creates armature instances. * @see dragonBones.Armature */ @@ -66,60 +66,12 @@ */ public function StarlingFactory() { - super(); + super(this); scaleForTexture = 1; } - /** - * Generates an Armature instance. - * @return Armature An Armature instance. - */ - override protected function generateArmature():Armature - { - var armature:Armature = new Armature(new Sprite()); - return armature; - } - /** - * Generates a Bone instance. - * @return Bone A Bone instance. - */ - override protected function generateBone():Bone - { - var bone:Bone = new Bone(new StarlingDisplayBridge()); - return bone; - } - /** - * Generates a starling DisplayObject - * @param textureAtlas The TextureAtlas. - * @param fullName A qualified name. - * @param pivotX A pivot x based value. - * @param pivotY A pivot y based value. - * @return - */ - override protected function generateTextureDisplay(textureAtlas:Object, fullName:String, pivotX:Number, pivotY:Number):Object - { - var starlingTextureAtlas:StarlingTextureAtlas = textureAtlas as StarlingTextureAtlas; - if (starlingTextureAtlas) - { - //1.4 - var subTextureData:SubTextureData = starlingTextureAtlas.getRegion(fullName) as SubTextureData; - if (subTextureData) - { - pivotX = pivotX || subTextureData.pivotX; - pivotY = pivotY || subTextureData.pivotY; - } - } - var subTexture:SubTexture = (textureAtlas as TextureAtlas).getTexture(fullName) as SubTexture; - if (subTexture) - { - var image:Image = new Image(subTexture); - image.pivotX = pivotX; - image.pivotY = pivotY; - return image; - } - return null; - } - override protected function generateTextureAtlas(content:Object, textureAtlasXML:XML):Object + /** @private */ + override protected function generateTextureAtlas(content:Object, textureAtlasRawData:Object):ITextureAtlas { var texture:Texture; var bitmapData:BitmapData; @@ -130,8 +82,9 @@ } else if (content is MovieClip) { - var width:int = int(textureAtlasXML.attribute(ConstValues.A_WIDTH)) * scaleForTexture; - var height:int = int(textureAtlasXML.attribute(ConstValues.A_HEIGHT)) * scaleForTexture; + var width:int = getNearest2N(content.width) * scaleForTexture; + var height:int = getNearest2N(content.height) * scaleForTexture; + _helpMatirx.a = 1; _helpMatirx.b = 0; _helpMatirx.c = 0; @@ -148,9 +101,9 @@ } else { - // + throw new Error(); } - var textureAtlas:StarlingTextureAtlas = new StarlingTextureAtlas(texture, textureAtlasXML); + var textureAtlas:StarlingTextureAtlas = new StarlingTextureAtlas(texture, textureAtlasRawData, false); if (Starling.handleLostContext) { textureAtlas._bitmapData = bitmapData; @@ -161,5 +114,38 @@ } return textureAtlas; } + + /** @private */ + override protected function generateArmature():Armature + { + var armature:Armature = new Armature(new Sprite()); + return armature; + } + + /** @private */ + override protected function generateSlot():Slot + { + var slot:Slot = new Slot(new StarlingDisplayBridge()); + return slot; + } + + /** @private */ + override protected function generateDisplay(textureAtlas:Object, fullName:String, pivotX:Number, pivotY:Number):Object + { + var subTexture:SubTexture = (textureAtlas as TextureAtlas).getTexture(fullName) as SubTexture; + if (subTexture) + { + var image:Image = new Image(subTexture); + image.pivotX = pivotX; + image.pivotY = pivotY; + return image; + } + return null; + } + + private function getNearest2N(_n:uint):uint + { + return _n & _n - 1?1 << _n.toString(2).length:_n; + } } } \ No newline at end of file diff --git a/src/dragonBones/objects/AnimationData.as b/src/dragonBones/objects/AnimationData.as index f5a53d3..381f7f0 100644 --- a/src/dragonBones/objects/AnimationData.as +++ b/src/dragonBones/objects/AnimationData.as @@ -1,39 +1,67 @@ package dragonBones.objects { - import dragonBones.utils.dragonBones_internal; - - use namespace dragonBones_internal; - - /** @private */ - public class AnimationData + final public class AnimationData extends Timeline { - dragonBones_internal var _movementDataList:DataList; + public var frameRate:uint; + public var name:String; + public var loop:int; + public var tweenEasing:Number; - public function get movementList():Vector. + private var _timelines:Object; + public function get timelines():Object { - return _movementDataList.dataNames.concat(); + return _timelines; + } + + private var _fadeTime:Number; + public function get fadeInTime():Number + { + return _fadeTime; + } + public function set fadeInTime(value:Number):void + { + if(isNaN(value)) + { + value = 0; + } + _fadeTime = value; } public function AnimationData() { - _movementDataList = new DataList(); + super(); + loop = 0; + tweenEasing = NaN; + + _timelines = {}; + + _fadeTime = 0; } - public function dispose():void + override public function dispose():void { - for each(var movementName:String in _movementDataList.dataNames) + super.dispose(); + + for(var timelineName:String in _timelines) { - var movementData:MovementData = _movementDataList.getData(movementName) as MovementData; - movementData.dispose(); + (_timelines[timelineName] as TransformTimeline).dispose(); } - - _movementDataList.dispose(); + _timelines = null; + } + + public function getTimeline(timelineName:String):TransformTimeline + { + return _timelines[timelineName] as TransformTimeline; } - public function getMovementData(name:String):MovementData + public function addTimeline(timeline:TransformTimeline, timelineName:String):void { - return _movementDataList.getData(name) as MovementData; + if(!timeline) + { + throw new ArgumentError(); + } + + _timelines[timelineName] = timeline; } } - } \ No newline at end of file diff --git a/src/dragonBones/objects/ArmatureData.as b/src/dragonBones/objects/ArmatureData.as index d2b77c5..316258f 100644 --- a/src/dragonBones/objects/ArmatureData.as +++ b/src/dragonBones/objects/ArmatureData.as @@ -1,70 +1,187 @@ package dragonBones.objects { - import dragonBones.utils.dragonBones_internal; - - use namespace dragonBones_internal; - - /** @private */ - public class ArmatureData + final public class ArmatureData { - dragonBones_internal var _boneDataList:DataList; + public var name:String; - public function get boneNames():Vector. + private var _boneDataList:Vector.; + public function get boneDataList():Vector. { - return _boneDataList.dataNames.concat(); + return _boneDataList; + } + + private var _skinDataList:Vector.; + public function get skinDataList():Vector. + { + return _skinDataList; + } + + private var _animationDataList:Vector.; + public function get animationDataList():Vector. + { + return _animationDataList; } public function ArmatureData() { - _boneDataList = new DataList(); + _boneDataList = new Vector.(0, true); + _skinDataList = new Vector.(0, true); + _animationDataList = new Vector.(0, true); } public function dispose():void { - for each(var boneName:String in _boneDataList.dataNames) + var i:int = _boneDataList.length; + while(i --) + { + _boneDataList[i].dispose(); + } + i = _skinDataList.length; + while(i --) + { + _skinDataList[i].dispose(); + } + i = _animationDataList.length; + while(i --) + { + _animationDataList[i].dispose(); + } + _boneDataList.fixed = false; + _boneDataList.length = 0; + _skinDataList.fixed = false; + _skinDataList.length = 0; + _animationDataList.fixed = false; + _animationDataList.length = 0; + _boneDataList = null; + _skinDataList = null; + _animationDataList = null; + } + + public function getBoneData(boneName:String):BoneData + { + var i:int = _boneDataList.length; + while(i --) + { + if(_boneDataList[i].name == boneName) + { + return _boneDataList[i]; + } + } + return null; + } + + public function getSkinData(skinName:String):SkinData + { + if(!skinName) + { + return _skinDataList[0]; + } + var i:int = _skinDataList.length; + while(i --) { - var boneData:BoneData = _boneDataList.getData(boneName) as BoneData; - boneData.dispose(); + if(_skinDataList[i].name == skinName) + { + return _skinDataList[i]; + } } - _boneDataList.dispose(); + return null; } - public function getBoneData(name:String):BoneData + public function getAnimationData(animationName:String):AnimationData { - return _boneDataList.getData(name) as BoneData; + var i:int = _animationDataList.length; + while(i --) + { + if(_animationDataList[i].name == animationName) + { + return _animationDataList[i]; + } + } + return null; } - public function updateBoneList():void + public function addBoneData(boneData:BoneData):void { - var boneNames:Vector. = _boneDataList.dataNames; + if(!boneData) + { + throw new ArgumentError(); + } - var sortList:Array = []; - for each(var boneName:String in boneNames) + if (_boneDataList.indexOf(boneData) < 0) { - var boneData:BoneData = _boneDataList.getData(boneName) as BoneData; - var levelValue:int = boneData.node.z; + _boneDataList.fixed = false; + _boneDataList[_boneDataList.length] = boneData; + _boneDataList.fixed = true; + } + else + { + throw new ArgumentError(); + } + } + + public function addSkinData(skinData:SkinData):void + { + if(!skinData) + { + throw new ArgumentError(); + } + + if(_skinDataList.indexOf(skinData) < 0) + { + _skinDataList.fixed = false; + _skinDataList[_skinDataList.length] = skinData; + _skinDataList.fixed = true; + } + else + { + throw new ArgumentError(); + } + } + + public function addAnimationData(animationData:AnimationData):void + { + if(!animationData) + { + throw new ArgumentError(); + } + + if(_animationDataList.indexOf(animationData) < 0) + { + _animationDataList.fixed = false; + _animationDataList[_animationDataList.length] = animationData; + _animationDataList.fixed = true; + } + } + + public function sortBoneDataList():void + { + var i:int = _boneDataList.length; + if(i == 0) + { + return; + } + + var helpArray:Array = []; + while(i --) + { + var boneData:BoneData = _boneDataList[i]; var level:int = 0; - while(boneData) + var parentData:BoneData = boneData; + while(parentData && parentData.parent) { level ++; - levelValue += 1000 * level; - boneData = getBoneData(boneData.parent); + parentData = getBoneData(parentData.parent); } - sortList.push({level:levelValue, boneName:boneName}); + helpArray[i] = {level:level, boneData:boneData}; } - var length:int = sortList.length; - if(length > 0) + helpArray.sortOn("level", Array.NUMERIC); + + i = helpArray.length; + while(i --) { - sortList.sortOn("level", Array.NUMERIC); - boneNames.length = 0; - var i:int = 0; - while(i < length) - { - boneNames[i] = sortList[i].boneName; - i ++; - } + _boneDataList[i] = helpArray[i].boneData; } } } diff --git a/src/dragonBones/objects/BoneData.as b/src/dragonBones/objects/BoneData.as index 5fa3538..49c90c1 100644 --- a/src/dragonBones/objects/BoneData.as +++ b/src/dragonBones/objects/BoneData.as @@ -1,32 +1,27 @@ package dragonBones.objects { - import dragonBones.utils.dragonBones_internal; - - use namespace dragonBones_internal; - - /** @private */ + import flash.geom.Point; + final public class BoneData { - dragonBones_internal var _displayNames:Vector.; + public var name:String; + public var parent:String; + public var length:Number; - dragonBones_internal var _parent:String; - - public function get parent():String - { - return _parent; - } - - public var node:BoneTransform; + public var global:DBTransform; + public var transform:DBTransform; public function BoneData() { - _displayNames = new Vector.; - node = new BoneTransform(); + length = 0; + global = new DBTransform(); + transform = new DBTransform(); } public function dispose():void { - _displayNames.length = 0; + global = null; + transform = null; } } } \ No newline at end of file diff --git a/src/dragonBones/objects/BoneTransform.as b/src/dragonBones/objects/BoneTransform.as deleted file mode 100644 index 515c45f..0000000 --- a/src/dragonBones/objects/BoneTransform.as +++ /dev/null @@ -1,169 +0,0 @@ -package dragonBones.objects -{ - /** - * Copyright 2012-2013. DragonBones. All Rights Reserved. - * @playerversion Flash 10.0 - * @langversion 3.0 - * @version 2.0 - */ - - /** - * The BoneTransform class provides transformation properties and methods for Bone instances. - * @example - *

Download the example files here:

- *

This example gets the BoneTransform of the head bone and adjust the x and y registration by 60 pixels.

- * - * package - * { - * import dragonBones.Armature; - * import dragonBones.factorys.BaseFactory; - * import flash.display.Sprite; - * import flash.events.Event; - * - * public class DragonAnimation extends Sprite - * { - * [Embed(source = "Dragon1.swf", mimeType = "application/octet-stream")] - * private static const ResourcesData:Class; - * - * private var factory:BaseFactory; - * private var armature:Armature; - * - * public function DragonAnimation() - * { - * factory = new BaseFactory(); - * factory.addEventListener(Event.COMPLETE, handleParseData); - * factory.parseData(new ResourcesData(), 'Dragon'); - * } - * - * private function handleParseData(e:Event):void - * { - * armature = factory.buildArmature('Dragon'); - * addChild(armature.display as Sprite); - * armature.animation.play(); - * var bone:Bone = armature.getBone("head"); - * bone.origin.pivotX = 60;//origin BoneTransform - * bone.origin.pivotY = 60;//origin BoneTransform - * addEventListener(Event.ENTER_FRAME, updateAnimation); - * } - * - * private function updateAnimation(e:Event):void - * { - * armature.advanceTime(1 / stage.frameRate); - * } - * } - * } - * - * @see dragonBones.Bone - * @see dragonBones.animation.Animation - */ - public class BoneTransform - { - /** - * Position on the x axis. - */ - public var x:Number; - /** - * Position on the y axis. - */ - public var y:Number; - /** - * Scale on the x axis. - */ - public var scaleX:Number; - /** - * Scale on the y axis. - */ - public var scaleY:Number; - /** - * Skew on the x axis. - */ - public var skewX:Number; - /** - * skew on the y axis. - */ - public var skewY:Number; - /** - * pivot point on the x axis (registration) - */ - public var pivotX:Number; - /** - * pivot point on the y axis (registration) - */ - public var pivotY:Number; - /** - * Z order. - */ - public var z:Number; - - /** - * The rotation of that BoneTransform instance. - */ - public function get rotation():Number - { - return skewX; - } - /** - * @private - */ - public function set rotation(value:Number):void - { - skewX = skewY = value; - } - /** - * Creat a new BoneTransform instance. - */ - public function BoneTransform() - { - setValues(); - } - /** - * Sets all properties at once. - * @param x The x position. - * @param y The y position. - * @param skewX The skew value on x axis. - * @param skewY The skew value on y axis. - * @param scaleX The scale on x axis. - * @param scaleY The scale on y axis. - * @param pivotX The pivot value on x axis (registration) - * @param pivotY The pivot valule on y axis (registration) - * @param z The z order. - */ - public function setValues(x:Number = 0, y:Number = 0, skewX:Number = 0, skewY:Number = 0, scaleX:Number = 0, scaleY:Number = 0, pivotX:Number = 0, pivotY:Number = 0, z:int = 0):void - { - this.x = x || 0; - this.y = y || 0; - this.skewX = skewX || 0; - this.skewY = skewY || 0; - this.scaleX = scaleX || 0; - this.scaleY = scaleY || 0; - this.pivotX = pivotX || 0; - this.pivotY = pivotY || 0; - this.z = z; - } - /** - * Copy all properties from this BoneTransform instance to the passed BoneTransform instance. - * @param node - */ - public function copy(node:BoneTransform):void - { - x = node.x; - y = node.y; - scaleX = node.scaleX; - scaleY = node.scaleY; - skewX = node.skewX; - skewY = node.skewY; - pivotX = node.pivotX; - pivotY = node.pivotY; - z = node.z; - } - /** - * Get a string representing all BoneTransform property values. - * @return String All property values in a formatted string. - */ - public function toString():String - { - var string:String = "x:" + x + " y:" + y + " skewX:" + skewX + " skewY:" + skewY + " scaleX:" + scaleX + " scaleY:" + scaleY; - return string; - } - } -} \ No newline at end of file diff --git a/src/dragonBones/objects/DBTransform.as b/src/dragonBones/objects/DBTransform.as new file mode 100644 index 0000000..d7d1583 --- /dev/null +++ b/src/dragonBones/objects/DBTransform.as @@ -0,0 +1,81 @@ +package dragonBones.objects +{ + /** + * Copyright 2012-2013. DragonBones. All Rights Reserved. + * @playerversion Flash 10.0 + * @langversion 3.0 + * @version 2.0 + */ + public class DBTransform + { + /** + * Position on the x axis. + */ + public var x:Number; + /** + * Position on the y axis. + */ + public var y:Number; + /** + * Skew on the x axis. + */ + public var skewX:Number; + /** + * skew on the y axis. + */ + public var skewY:Number; + /** + * Scale on the x axis. + */ + public var scaleX:Number; + /** + * Scale on the y axis. + */ + public var scaleY:Number; + /** + * The rotation of that DBTransform instance. + */ + public function get rotation():Number + { + return skewX; + } + public function set rotation(value:Number):void + { + skewX = skewY = value; + } + /** + * Creat a new DBTransform instance. + */ + public function DBTransform() + { + x = 0; + y = 0; + skewX = 0; + skewY = 0; + scaleX = 1 + scaleY = 1; + } + /** + * Copy all properties from this DBTransform instance to the passed DBTransform instance. + * @param node + */ + public function copy(transform:DBTransform):void + { + x = transform.x; + y = transform.y; + skewX = transform.skewX; + skewY = transform.skewY; + scaleX = transform.scaleX; + scaleY = transform.scaleY; + } + /** + * Get a string representing all DBTransform property values. + * @return String All property values in a formatted string. + */ + public function toString():String + { + var string:String = "x:" + x + " y:" + y + " skewX:" + skewX + " skewY:" + skewY + " scaleX:" + scaleX + " scaleY:" + scaleY; + return string; + } + } +} \ No newline at end of file diff --git a/src/dragonBones/objects/DataList.as b/src/dragonBones/objects/DataList.as deleted file mode 100644 index 81d26cc..0000000 --- a/src/dragonBones/objects/DataList.as +++ /dev/null @@ -1,67 +0,0 @@ -package dragonBones.objects -{ - internal final class DataList - { - private var _dataDic:Object; - public var dataNames:Vector.; - - public function DataList() - { - _dataDic = {}; - dataNames = new Vector.; - } - - public function dispose():void - { - _dataDic = {}; - dataNames.length = 0; - } - - public function getData(dataName:String):Object - { - return _dataDic[dataName]; - } - - public function getDataAt(index:int):Object - { - return _dataDic[dataNames[index]]; - } - - public function addData(data:Object, dataName:String):void - { - if(data && dataName) - { - _dataDic[dataName] = data; - if(dataNames.indexOf(dataName) < 0) - { - dataNames.push(dataName); - } - } - } - - public function removeData(data:Object):void - { - if(data) - { - for(var dataName:String in _dataDic) - { - if(_dataDic[dataName] == data) - { - removeDataByName(dataName); - return; - } - } - } - } - - public function removeDataByName(dataName:String):void - { - var data:Object = _dataDic[dataName]; - if(data) - { - delete _dataDic[dataName]; - dataNames.splice(dataNames.indexOf(dataName), 1); - } - } - } -} \ No newline at end of file diff --git a/src/dragonBones/objects/DataParser.as b/src/dragonBones/objects/DataParser.as new file mode 100644 index 0000000..83bb4b9 --- /dev/null +++ b/src/dragonBones/objects/DataParser.as @@ -0,0 +1,140 @@ +package dragonBones.objects +{ + import dragonBones.objects.ObjectDataParser; + import dragonBones.objects.SkeletonData; + import dragonBones.objects.XMLDataParser; + import dragonBones.utils.BytesType; + import dragonBones.utils.checkBytesTailisXML; + + import flash.utils.ByteArray; + + public final class DataParser + { + /** + * Compress all data into a ByteArray for serialization. + * @param The DragonBones data. + * @param The TextureAtlas data. + * @param The ByteArray representing the map. + * @return ByteArray. A DragonBones compatible ByteArray. + */ + public static function compressData(dragonBonesData:Object, textureAtlasData:Object, textureDataBytes:ByteArray):ByteArray + { + var retult:ByteArray = new ByteArray(); + retult.writeBytes(textureDataBytes); + + var dataBytes:ByteArray = new ByteArray(); + dataBytes.writeObject(textureAtlasData); + dataBytes.compress(); + + retult.position = retult.length; + retult.writeBytes(dataBytes); + retult.writeInt(dataBytes.length); + + dataBytes.length = 0; + dataBytes.writeObject(dragonBonesData); + dataBytes.compress(); + + retult.position = retult.length; + retult.writeBytes(dataBytes); + retult.writeInt(dataBytes.length); + + return retult; + } + + /** + * Decompress a compatible DragonBones data. + * @param compressedByteArray The ByteArray to decompress. + * @return A DecompressedData instance. + */ + public static function decompressData(bytes:ByteArray):DecompressedData + { + var dataType:String = BytesType.getType(bytes); + switch (dataType) + { + case BytesType.SWF: + case BytesType.PNG: + case BytesType.JPG: + case BytesType.ATF: + try + { + bytes.position = bytes.length - 4; + var strSize:int = bytes.readInt(); + var position:uint = bytes.length - 4 - strSize; + + var dataBytes:ByteArray = new ByteArray(); + dataBytes.writeBytes(bytes, position, strSize); + dataBytes.uncompress(); + bytes.length = position; + + var dragonBonesData:Object; + if(checkBytesTailisXML(dataBytes)) + { + dragonBonesData = XML(dataBytes.readUTFBytes(dataBytes.length)); + } + else + { + dragonBonesData = dataBytes.readObject(); + } + + bytes.position = bytes.length - 4; + strSize = bytes.readInt(); + position = bytes.length - 4 - strSize; + + dataBytes.length = 0; + dataBytes.writeBytes(bytes, position, strSize); + dataBytes.uncompress(); + bytes.length = position; + + var textureAtlasData:Object; + if(checkBytesTailisXML(dataBytes)) + { + textureAtlasData = XML(dataBytes.readUTFBytes(dataBytes.length)); + } + else + { + textureAtlasData = dataBytes.readObject(); + } + } + catch (e:Error) + { + throw new Error("Data error!"); + } + + var decompressedData:DecompressedData = new DecompressedData(dragonBonesData, textureAtlasData, bytes); + decompressedData.textureBytesDataType = dataType; + return decompressedData; + case BytesType.ZIP: + throw new Error("Can not decompress zip!"); + default: + throw new Error("Nonsupport data!"); + } + return null; + } + + public static function parseTextureAtlas(rawData:Object, scale:Number = 1):Object + { + if(rawData is XML) + { + return XMLDataParser.parseTextureAtlasData(rawData as XML, scale); + } + else + { + return ObjectDataParser.parseTextureAtlasData(rawData, scale); + } + return null; + } + + public static function parseData(rawData:Object):SkeletonData + { + if(rawData is XML) + { + return XMLDataParser.parseSkeletonData(rawData as XML); + } + else + { + return ObjectDataParser.parseSkeletonData(rawData); + } + return null; + } + } +} \ No newline at end of file diff --git a/src/dragonBones/objects/DecompressedData.as b/src/dragonBones/objects/DecompressedData.as index 02c43b4..3b72d79 100644 --- a/src/dragonBones/objects/DecompressedData.as +++ b/src/dragonBones/objects/DecompressedData.as @@ -8,20 +8,21 @@ package dragonBones.objects */ import flash.utils.ByteArray; /** - * The DecompressedData is a convenient class for storing animation related data (skeleton, atlas, object). + * The DecompressedData is a convenient class for storing animation related data (data, atlas, object). * * @see dragonBones.Armature */ public final class DecompressedData { + public var textureBytesDataType:String; /** - * A xml for Skeleton data. + * A xml for DragonBones data. */ - public var skeletonXML:XML; + public var dragonBonesData:Object; /** * A xml for atlas data. */ - public var textureAtlasXML:XML; + public var textureAtlasData:Object; /** * The non parsed data map. */ @@ -29,21 +30,21 @@ package dragonBones.objects /** * Creates a new DecompressedData instance. - * @param skeletonXML A xml for Skeleton data. + * @param xml A xml for DragonBones data. * @param textureAtlasXML A xml for atlas data. * @param textureBytes The non parsed data map. */ - public function DecompressedData(skeletonXML:XML, textureAtlasXML:XML, textureBytes:ByteArray) + public function DecompressedData(dragonBonesData:Object, textureAtlasData:Object, textureBytes:ByteArray) { - this.skeletonXML = skeletonXML; - this.textureAtlasXML = textureAtlasXML; + this.dragonBonesData = dragonBonesData; + this.textureAtlasData = textureAtlasData; this.textureBytes = textureBytes; } public function dispose():void { - skeletonXML = null; - textureAtlasXML = null; + dragonBonesData = null; + textureAtlasData = null; textureBytes = null; } } diff --git a/src/dragonBones/objects/DisplayData.as b/src/dragonBones/objects/DisplayData.as index 6c45f8c..1a6b152 100644 --- a/src/dragonBones/objects/DisplayData.as +++ b/src/dragonBones/objects/DisplayData.as @@ -1,26 +1,27 @@ package dragonBones.objects { - import dragonBones.utils.dragonBones_internal; - - use namespace dragonBones_internal; + import flash.geom.Point; /** @private */ - public class DisplayData + final public class DisplayData { - public var pivotX:Number; - public var pivotY:Number; + public static const ARMATURE:String = "armature"; + public static const IMAGE:String = "image"; - dragonBones_internal var _isArmature:Boolean; + public var name:String; + public var type:String; + public var transform:DBTransform; + public var pivot:Point; - public function get isArmature():Boolean + public function DisplayData() { - return _isArmature; + transform = new DBTransform(); } - public function DisplayData() + public function dispose():void { - pivotX = 0; - pivotY = 0; + transform = null; + pivot = null; } } } \ No newline at end of file diff --git a/src/dragonBones/objects/Frame.as b/src/dragonBones/objects/Frame.as new file mode 100644 index 0000000..e4709ab --- /dev/null +++ b/src/dragonBones/objects/Frame.as @@ -0,0 +1,23 @@ +package dragonBones.objects +{ + /** @private */ + public class Frame + { + public var position:Number; + public var duration:Number; + + public var action:String; + public var event:String; + public var sound:String; + + public function Frame() + { + position = 0; + duration = 0; + } + + public function dispose():void + { + } + } +} \ No newline at end of file diff --git a/src/dragonBones/objects/FrameData.as b/src/dragonBones/objects/FrameData.as deleted file mode 100644 index 2e738a9..0000000 --- a/src/dragonBones/objects/FrameData.as +++ /dev/null @@ -1,30 +0,0 @@ -package dragonBones.objects -{ - import flash.geom.ColorTransform; - - /** @private */ - final public class FrameData - { - public var duration:Number; - public var tweenEasing:Number; - public var tweenRotate:int; - public var displayIndex:int; - public var movement:String; - public var visible:Boolean; - public var event:String; - public var sound:String; - public var soundEffect:String; - public var node:BoneTransform; - public var colorTransform:ColorTransform; - - public function FrameData() - { - duration = 0; - //NaN: no tweens; -1: ease out; 0: linear; 1: ease in; 2: ease in&out - tweenEasing = 0; - node = new BoneTransform(); - colorTransform = new ColorTransform(); - } - } - -} \ No newline at end of file diff --git a/src/dragonBones/objects/MovementBoneData.as b/src/dragonBones/objects/MovementBoneData.as deleted file mode 100644 index 943f0e4..0000000 --- a/src/dragonBones/objects/MovementBoneData.as +++ /dev/null @@ -1,42 +0,0 @@ -package dragonBones.objects -{ - import dragonBones.utils.dragonBones_internal; - - use namespace dragonBones_internal; - - /** @private */ - public class MovementBoneData - { - dragonBones_internal static const HIDE_DATA:MovementBoneData = new MovementBoneData(); - - dragonBones_internal var _frameList:Vector.; - - public var scale:Number; - public var delay:Number; - - public function MovementBoneData() - { - scale = 1; - delay = 0; - - _frameList = new Vector.; - } - - public function dispose():void - { - _frameList.length = 0; - } - - public function setValues(scale:Number = 1, delay:Number = 0):void - { - this.scale = scale > 0?scale:1; - this.delay = (delay || 0) % 1; - if (this.delay > 0) - { - this.delay -= 1; - } - this.delay *= -1; - } - } - -} \ No newline at end of file diff --git a/src/dragonBones/objects/MovementData.as b/src/dragonBones/objects/MovementData.as deleted file mode 100644 index bf75c43..0000000 --- a/src/dragonBones/objects/MovementData.as +++ /dev/null @@ -1,47 +0,0 @@ -package dragonBones.objects -{ - import dragonBones.utils.dragonBones_internal; - - use namespace dragonBones_internal; - - /** @private */ - public class MovementData - { - dragonBones_internal var _movementBoneDataList:DataList; - dragonBones_internal var _movementFrameList:Vector.; - - public var duration:Number; - public var durationTo:Number; - public var durationTween:Number; - public var loop:Boolean; - public var tweenEasing:Number; - - public function MovementData() - { - duration = 0; - durationTo = 0; - durationTween = 0; - - _movementBoneDataList = new DataList(); - _movementFrameList = new Vector.; - } - - public function dispose():void - { - for each(var movementBoneName:String in _movementBoneDataList.dataNames) - { - var movementBoneData:MovementBoneData = _movementBoneDataList.getData(movementBoneName) as MovementBoneData; - movementBoneData.dispose(); - } - - _movementBoneDataList.dispose(); - _movementFrameList.length = 0; - } - - public function getMovementBoneData(name:String):MovementBoneData - { - return _movementBoneDataList.getData(name) as MovementBoneData; - } - } - -} \ No newline at end of file diff --git a/src/dragonBones/objects/MovementFrameData.as b/src/dragonBones/objects/MovementFrameData.as deleted file mode 100644 index 3ce0100..0000000 --- a/src/dragonBones/objects/MovementFrameData.as +++ /dev/null @@ -1,24 +0,0 @@ -package dragonBones.objects -{ - /** @private */ - public class MovementFrameData - { - public var duration:Number; - public var movement:String; - public var event:String; - public var sound:String; - public var soundEffect:String; - - public function MovementFrameData() - { - } - - public function setValues(duration:Number, movement:String, event:String, sound:String):void - { - this.duration = duration; - this.movement = movement; - this.event = event; - this.sound = sound; - } - } -} \ No newline at end of file diff --git a/src/dragonBones/objects/ObjectDataParser.as b/src/dragonBones/objects/ObjectDataParser.as new file mode 100644 index 0000000..ece2cd0 --- /dev/null +++ b/src/dragonBones/objects/ObjectDataParser.as @@ -0,0 +1,285 @@ +package dragonBones.objects +{ + import dragonBones.core.DragonBones; + import dragonBones.core.dragonBones_internal; + import dragonBones.objects.AnimationData; + import dragonBones.objects.ArmatureData; + import dragonBones.objects.BoneData; + import dragonBones.objects.DBTransform; + import dragonBones.objects.DisplayData; + import dragonBones.objects.Frame; + import dragonBones.objects.SkeletonData; + import dragonBones.objects.SkinData; + import dragonBones.objects.SlotData; + import dragonBones.objects.Timeline; + import dragonBones.objects.TransformFrame; + import dragonBones.objects.TransformTimeline; + import dragonBones.utils.ConstValues; + import dragonBones.utils.DBDataUtil; + + import flash.geom.ColorTransform; + import flash.geom.Point; + import flash.geom.Rectangle; + + use namespace dragonBones_internal; + + public final class ObjectDataParser + { + public static function parseTextureAtlasData(rawData:Object, scale:Number = 1):Object + { + var textureAtlasData:Object = {}; + textureAtlasData.__name = rawData[ConstValues.A_NAME]; + for each (var subTextureObject:Object in rawData[ConstValues.SUB_TEXTURE]) + { + var subTextureName:String = subTextureObject[ConstValues.A_NAME]; + var subTextureData:Rectangle = new Rectangle(); + subTextureData.x = int(subTextureObject[ConstValues.A_X]) / scale; + subTextureData.y = int(subTextureObject[ConstValues.A_Y]) / scale; + subTextureData.width = int(subTextureObject[ConstValues.A_WIDTH]) / scale; + subTextureData.height = int(subTextureObject[ConstValues.A_HEIGHT]) / scale; + textureAtlasData[subTextureName] = subTextureData; + } + + return textureAtlasData; + } + + public static function parseSkeletonData(rawData:Object):SkeletonData + { + if(!rawData) + { + throw new ArgumentError(); + } + + var version:String = rawData[ConstValues.A_VERSION]; + switch (version) + { + case DragonBones.DATA_VERSION: + break; + default: + throw new Error("Nonsupport version!"); + } + + var frameRate:uint = int(rawData[ConstValues.A_FRAME_RATE]); + + var data:SkeletonData = new SkeletonData(); + data.name = rawData[ConstValues.A_NAME]; + + for each(var armatureObject:Object in rawData[ConstValues.ARMATURE]) + { + data.addArmatureData(parseArmatureData(armatureObject, data, frameRate)); + } + + return data; + } + + private static function parseArmatureData(armatureObject:Object, data:SkeletonData, frameRate:uint):ArmatureData + { + var armatureData:ArmatureData = new ArmatureData(); + armatureData.name = armatureObject[ConstValues.A_NAME]; + + for each(var boneObject:Object in armatureObject[ConstValues.BONE]) + { + armatureData.addBoneData(parseBoneData(boneObject)); + } + + for each(var skinObject:Object in armatureObject[ConstValues.SKIN]) + { + armatureData.addSkinData(parseSkinData(skinObject, data)); + } + + DBDataUtil.transformArmatureData(armatureData); + armatureData.sortBoneDataList(); + + for each(var animationObject:Object in armatureObject[ConstValues.ANIMATION]) + { + armatureData.addAnimationData(parseAnimationData(animationObject, armatureData, frameRate)); + } + + return armatureData; + } + + private static function parseBoneData(boneObject:Object):BoneData + { + var boneData:BoneData = new BoneData(); + boneData.name = boneObject[ConstValues.A_NAME]; + boneData.parent = boneObject[ConstValues.A_PARENT]; + boneData.length = Number(boneObject[ConstValues.A_LENGTH]) || 0; + + parseTransform(boneObject[ConstValues.TRANSFORM], boneData.global); + boneData.transform.copy(boneData.global); + + return boneData; + } + + private static function parseSkinData(skinObject:Object, data:SkeletonData):SkinData + { + var skinData:SkinData = new SkinData(); + skinData.name = skinObject[ConstValues.A_NAME]; + + for each(var slotObject:Object in skinObject[ConstValues.SLOT]) + { + skinData.addSlotData(parseSlotData(slotObject, data)); + } + + return skinData; + } + + private static function parseSlotData(slotObject:Object, data:SkeletonData):SlotData + { + var slotData:SlotData = new SlotData(); + slotData.name = slotObject[ConstValues.A_NAME]; + slotData.parent = slotObject[ConstValues.A_PARENT]; + slotData.zOrder = Number(slotObject[ConstValues.A_Z_ORDER]); + for each(var displayObject:Object in slotObject[ConstValues.DISPLAY]) + { + slotData.addDisplayData(parseDisplayData(displayObject, data)); + } + + return slotData; + } + + private static function parseDisplayData(displayObject:Object, data:SkeletonData):DisplayData + { + var displayData:DisplayData = new DisplayData(); + displayData.name = displayObject[ConstValues.A_NAME]; + displayData.type = displayObject[ConstValues.A_TYPE]; + + displayData.pivot = data.addSubTexturePivot( + 0, + 0, + displayData.name + ); + + parseTransform(displayObject[ConstValues.TRANSFORM], displayData.transform, displayData.pivot); + + return displayData; + } + + private static function parseAnimationData(animationObject:Object, armatureData:ArmatureData, frameRate:uint):AnimationData + { + var animationData:AnimationData = new AnimationData(); + animationData.name = animationObject[ConstValues.A_NAME]; + animationData.frameRate = frameRate; + animationData.loop = int(animationObject[ConstValues.A_LOOP]); + animationData.fadeInTime = Number(animationObject[ConstValues.A_FADE_IN_TIME]); + animationData.duration = Number(animationObject[ConstValues.A_DURATION]) / frameRate; + animationData.scale = Number(animationObject[ConstValues.A_SCALE]); + animationData.tweenEasing = Number(animationObject[ConstValues.A_TWEEN_EASING]); + + parseTimeline(animationObject, animationData, parseMainFrame, frameRate); + + var timeline:TransformTimeline; + var timelineName:String; + for each(var timelineObject:Object in animationObject[ConstValues.TIMELINE]) + { + timeline = parseTransformTimeline(timelineObject, animationData.duration, frameRate); + timelineName = timelineObject[ConstValues.A_NAME]; + animationData.addTimeline(timeline, timelineName); + } + + DBDataUtil.addHideTimeline(animationData, armatureData); + DBDataUtil.transformAnimationData(animationData, armatureData); + + return animationData; + } + + private static function parseTimeline(timelineObject:Object, timeline:Timeline, frameParser:Function, frameRate:uint):void + { + var position:Number = 0; + var frame:Frame; + for each(var frameObject:Object in timelineObject[ConstValues.FRAME]) + { + frame = frameParser(frameObject, frameRate); + frame.position = position; + timeline.addFrame(frame); + position += frame.duration; + } + if(frame) + { + frame.duration = timeline.duration - frame.position; + } + } + + private static function parseTransformTimeline(timelineObject:Object, duration:Number, frameRate:uint):TransformTimeline + { + var timeline:TransformTimeline = new TransformTimeline(); + timeline.duration = duration; + + parseTimeline(timelineObject, timeline, parseTransformFrame, frameRate); + + timeline.scale = Number(timelineObject[ConstValues.A_SCALE]); + timeline.offset = Number(timelineObject[ConstValues.A_OFFSET]); + + return timeline; + } + + private static function parseFrame(frameObject:Object, frame:Frame, frameRate:uint):void + { + frame.duration = Number(frameObject[ConstValues.A_DURATION]) / frameRate; + frame.action = frameObject[ConstValues.A_ACTION]; + frame.event = frameObject[ConstValues.A_EVENT]; + frame.sound = frameObject[ConstValues.A_SOUND]; + } + + private static function parseMainFrame(frameObject:Object, frameRate:uint):Frame + { + var frame:Frame = new Frame(); + parseFrame(frameObject, frame, frameRate); + return frame; + } + + private static function parseTransformFrame(frameObject:Object, frameRate:uint):TransformFrame + { + var frame:TransformFrame = new TransformFrame(); + parseFrame(frameObject, frame, frameRate); + + frame.visible = uint(frameObject[ConstValues.A_HIDE]) != 1; + frame.tweenEasing = Number(frameObject[ConstValues.A_TWEEN_EASING]); + frame.tweenRotate = Number(frameObject[ConstValues.A_TWEEN_ROTATE]); + frame.displayIndex = Number(frameObject[ConstValues.A_DISPLAY_INDEX]); + // + frame.zOrder = Number(frameObject[ConstValues.A_Z_ORDER]); + + parseTransform(frameObject[ConstValues.TRANSFORM], frame.global, frame.pivot); + frame.transform.copy(frame.global); + + var colorTransformObject:Object = frameObject[ConstValues.COLOR_TRANSFORM]; + if(colorTransformObject) + { + frame.color = new ColorTransform(); + frame.color.alphaOffset = Number(colorTransformObject[ConstValues.A_ALPHA_OFFSET]); + frame.color.redOffset = Number(colorTransformObject[ConstValues.A_RED_OFFSET]); + frame.color.greenOffset = Number(colorTransformObject[ConstValues.A_GREEN_OFFSET]); + frame.color.blueOffset = Number(colorTransformObject[ConstValues.A_BLUE_OFFSET]); + + frame.color.alphaMultiplier = Number(colorTransformObject[ConstValues.A_ALPHA_MULTIPLIER]) * 0.01; + frame.color.redMultiplier = Number(colorTransformObject[ConstValues.A_RED_MULTIPLIER]) * 0.01; + frame.color.greenMultiplier = Number(colorTransformObject[ConstValues.A_GREEN_MULTIPLIER]) * 0.01; + frame.color.blueMultiplier = Number(colorTransformObject[ConstValues.A_BLUE_MULTIPLIER]) * 0.01; + } + + return frame; + } + + private static function parseTransform(transformObject:Object, transform:DBTransform, pivot:Point = null):void + { + if(transformObject) + { + if(transform) + { + transform.x = Number(transformObject[ConstValues.A_X]); + transform.y = Number(transformObject[ConstValues.A_Y]); + transform.skewX = Number(transformObject[ConstValues.A_SKEW_X]) * ConstValues.ANGLE_TO_RADIAN; + transform.skewY = Number(transformObject[ConstValues.A_SKEW_Y]) * ConstValues.ANGLE_TO_RADIAN; + transform.scaleX = Number(transformObject[ConstValues.A_SCALE_X]); + transform.scaleY = Number(transformObject[ConstValues.A_SCALE_Y]); + } + if(pivot) + { + pivot.x = Number(transformObject[ConstValues.A_PIVOT_X]); + pivot.y = Number(transformObject[ConstValues.A_PIVOT_Y]); + } + } + } + } +} \ No newline at end of file diff --git a/src/dragonBones/objects/SkeletonData.as b/src/dragonBones/objects/SkeletonData.as index 5c00d07..00bcfca 100644 --- a/src/dragonBones/objects/SkeletonData.as +++ b/src/dragonBones/objects/SkeletonData.as @@ -1,140 +1,140 @@ -package dragonBones.objects +package dragonBones.objects { - /** - * Copyright 2012-2013. DragonBones. All Rights Reserved. - * @playerversion Flash 10.0, Flash 10 - * @langversion 3.0 - * @version 2.0 - */ - import dragonBones.utils.dragonBones_internal; - use namespace dragonBones_internal; - + import flash.geom.Point; - - /** - * A SkeletonData instance holds all data related to an Armature instance. - * @example - *

Download the example files here:

- *

This example parse the 'Dragon1.swf' data and stores its SkeletonData into the local variable named skeleton.

- * - * package - * { - * import dragonBones.Armature; - * import dragonBones.factorys.BaseFactory; - * import flash.display.Sprite; - * import flash.events.Event; - * import dragonBones.objects.SkeletonData; - * - * public class DragonAnimation extends Sprite - * { - * [Embed(source = "Dragon1.swf", mimeType = "application/octet-stream")] - * private static const ResourcesData:Class; - * - * private var factory:BaseFactory; - * private var armature:Armature; - * - * public function DragonAnimation() - * { - * factory = new BaseFactory(); - * factory.addEventListener(Event.COMPLETE, handleParseData); - * var skeleton:SkeletonData = factory.parseData(new ResourcesData(), 'Dragon'); - * } - * } - * } - * - * @see dragonBones.Bone - * @see dragonBones.animation.Animation - */ public class SkeletonData { - dragonBones_internal var _armatureDataList:DataList; - dragonBones_internal var _animationDataList:DataList; - dragonBones_internal var _displayDataList:DataList; - dragonBones_internal var _name:String; - /** - * the name of this Skeletondata instance. - */ - public function get name():String - { - return _name; - } + public var name:String; + + private var _subTexturePivots:Object; - dragonBones_internal var _frameRate:uint; - /** - * The frameRate of this Skeltondata instance. - */ - public function get frameRate():uint - { - return _frameRate; - } - /** - * All Armature instance names belonging to this Skeletondata instance. - */ public function get armatureNames():Vector. { - return _armatureDataList.dataNames.concat(); + var nameList:Vector. = new Vector.; + for each(var armatureData:ArmatureData in _armatureDataList) + { + nameList[nameList.length] = armatureData.name; + } + return nameList; } - /** - * All Animation instance names belonging to this Skeletondata instance. - */ - public function get animationNames():Vector. + + private var _armatureDataList:Vector.; + public function get armatureDataList():Vector. { - return _animationDataList.dataNames.concat(); + return _armatureDataList; } - /** - * Creates a new SkeletonData instance. - */ + public function SkeletonData() { - _armatureDataList = new DataList(); - _animationDataList = new DataList(); - _displayDataList = new DataList(); + _armatureDataList = new Vector.(0, true); + _subTexturePivots = {}; } - /** - * Clean up all resources used by this SkeletonData instance. - */ + public function dispose():void { - for each (var armatureName:String in _armatureDataList.dataNames) + for each(var armatureData:ArmatureData in _armatureDataList) { - var armatureData:ArmatureData = _armatureDataList.getData(armatureName) as ArmatureData; armatureData.dispose(); } - for each (var animationName:String in _animationDataList.dataNames) + _armatureDataList.fixed = false; + _armatureDataList.length = 0; + + _armatureDataList = null; + _subTexturePivots = null; + } + + public function getArmatureData(armatureName:String):ArmatureData + { + var i:int = _armatureDataList.length; + while(i --) { - var animationData:AnimationData = _animationDataList.getData(animationName) as AnimationData; - animationData.dispose(); + if(_armatureDataList[i].name == armatureName) + { + return _armatureDataList[i]; + } } - _armatureDataList.dispose(); - _animationDataList.dispose(); - _displayDataList.dispose(); + + return null; } - /** - * Get the ArmatureData instance with this name. - * @param name The name of the ArmatureData instance to retreive. - * @return ArmatureData The ArmatureData instance by that name. - */ - public function getArmatureData(name:String):ArmatureData + + public function addArmatureData(armatureData:ArmatureData):void { - return _armatureDataList.getData(name) as ArmatureData; + if(!armatureData) + { + throw new ArgumentError(); + } + + if(_armatureDataList.indexOf(armatureData) < 0) + { + _armatureDataList.fixed = false; + _armatureDataList[_armatureDataList.length] = armatureData; + _armatureDataList.fixed = true; + } + else + { + throw new ArgumentError(); + } } - /** - * Get the AnimationData instance with this name. - * @param name The name of the AnimationData instance to retreive. - * @return AnimationData The AnimationData instance by that name. - */ - public function getAnimationData(name:String):AnimationData + + public function removeArmatureData(armatureData:ArmatureData):void { - return _animationDataList.getData(name) as AnimationData; + var index:int = _armatureDataList.indexOf(armatureData); + if(index >= 0) + { + _armatureDataList.fixed = false; + _armatureDataList.splice(index, 1); + _armatureDataList.fixed = true; + } } - /** - * Get the DisplayData instance with this name. - * @param name The name of the DisplayData instance to retreive. - * @return AnimationData The DisplayData instance by that name. - */ - public function getDisplayData(name:String):DisplayData + + public function removeArmatureDataByName(armatureName:String):void { - return _displayDataList.getData(name) as DisplayData; + var i:int = _armatureDataList.length; + while(i --) + { + if(_armatureDataList[i].name == armatureName) + { + _armatureDataList.fixed = false; + _armatureDataList.splice(i, 1); + _armatureDataList.fixed = true; + } + } + } + + public function getSubTexturePivot(subTextureName:String):Point + { + return _subTexturePivots[subTextureName]; + } + + public function addSubTexturePivot(x:Number, y:Number, subTextureName:String):Point + { + var point:Point = _subTexturePivots[subTextureName]; + if(point) + { + point.x = x; + point.y = y; + } + else + { + _subTexturePivots[subTextureName] = point = new Point(x, y); + } + + return point; + } + + public function removeSubTexturePivot(subTextureName:String):void + { + if(subTextureName) + { + delete _subTexturePivots[subTextureName]; + } + else + { + for(subTextureName in _subTexturePivots) + { + delete _subTexturePivots[subTextureName]; + } + } } } } \ No newline at end of file diff --git a/src/dragonBones/objects/SkinData.as b/src/dragonBones/objects/SkinData.as new file mode 100644 index 0000000..e29766b --- /dev/null +++ b/src/dragonBones/objects/SkinData.as @@ -0,0 +1,63 @@ +package dragonBones.objects +{ + /** @private */ + final public class SkinData + { + public var name:String; + + private var _slotDataList:Vector.; + public function get slotDataList():Vector. + { + return _slotDataList; + } + + public function SkinData() + { + _slotDataList = new Vector.(0, true); + } + + public function dispose():void + { + var i:int = _slotDataList.length; + while(i --) + { + _slotDataList[i].dispose(); + } + _slotDataList.fixed = false; + _slotDataList.length = 0; + _slotDataList = null; + } + + public function getSlotData(slotName:String):SlotData + { + var i:int = _slotDataList.length; + while(i --) + { + if(_slotDataList[i].name == slotName) + { + return _slotDataList[i]; + } + } + return null; + } + + public function addSlotData(slotData:SlotData):void + { + if(!slotData) + { + throw new ArgumentError(); + } + + if (_slotDataList.indexOf(slotData) < 0) + { + _slotDataList.fixed = false; + _slotDataList[_slotDataList.length] = slotData; + _slotDataList.fixed = true; + } + else + { + throw new ArgumentError(); + } + } + } +} \ No newline at end of file diff --git a/src/dragonBones/objects/SlotData.as b/src/dragonBones/objects/SlotData.as new file mode 100644 index 0000000..fa16ed8 --- /dev/null +++ b/src/dragonBones/objects/SlotData.as @@ -0,0 +1,66 @@ +package dragonBones.objects +{ + /** @private */ + public final class SlotData + { + public var name:String; + public var parent:String; + public var zOrder:Number; + + private var _displayDataList:Vector.; + public function get displayDataList():Vector. + { + return _displayDataList; + } + + public function SlotData() + { + _displayDataList = new Vector.(0, true); + zOrder = 0; + } + + public function dispose():void + { + var i:int = _displayDataList.length; + while(i --) + { + _displayDataList[i].dispose(); + } + _displayDataList.fixed = false; + _displayDataList.length = 0; + _displayDataList = null; + } + + public function addDisplayData(displayData:DisplayData):void + { + if(!displayData) + { + throw new ArgumentError(); + } + if (_displayDataList.indexOf(displayData) < 0) + { + _displayDataList.fixed = false; + _displayDataList[_displayDataList.length] = displayData; + _displayDataList.fixed = true; + } + else + { + throw new ArgumentError(); + } + } + + public function getDisplayData(displayName:String):DisplayData + { + var i:int = _displayDataList.length; + while(i --) + { + if(_displayDataList[i].name == displayName) + { + return _displayDataList[i]; + } + } + + return null; + } + } +} \ No newline at end of file diff --git a/src/dragonBones/objects/Timeline.as b/src/dragonBones/objects/Timeline.as new file mode 100644 index 0000000..7efb7f0 --- /dev/null +++ b/src/dragonBones/objects/Timeline.as @@ -0,0 +1,70 @@ +package dragonBones.objects +{ + public class Timeline + { + private var _frameList:Vector.; + public function get frameList():Vector. + { + return _frameList; + } + + private var _duration:Number; + public function get duration():Number + { + return _duration; + } + public function set duration(value:Number):void + { + _duration = value >= 0?value:0; + } + + private var _scale:Number; + public function get scale():Number + { + return _scale; + } + public function set scale(value:Number):void + { + _scale = value >= 0?value:1; + } + + public function Timeline() + { + _frameList = new Vector.(0, true); + _duration = 0; + _scale = 1; + } + + public function dispose():void + { + var i:int = _frameList.length; + while(i --) + { + _frameList[i].dispose(); + } + _frameList.fixed = false; + _frameList.length = 0; + _frameList = null; + } + + public function addFrame(frame:Frame):void + { + if(!frame) + { + throw new ArgumentError(); + } + + if(_frameList.indexOf(frame) < 0) + { + _frameList.fixed = false; + _frameList[_frameList.length] = frame; + _frameList.fixed = true; + } + else + { + throw new ArgumentError(); + } + } + } + +} \ No newline at end of file diff --git a/src/dragonBones/objects/TransformFrame.as b/src/dragonBones/objects/TransformFrame.as new file mode 100644 index 0000000..4b84527 --- /dev/null +++ b/src/dragonBones/objects/TransformFrame.as @@ -0,0 +1,47 @@ +package dragonBones.objects +{ + import flash.geom.ColorTransform; + import flash.geom.Point; + + /** @private */ + final public class TransformFrame extends Frame + { + public var tweenEasing:Number; + public var tweenRotate:int; + public var displayIndex:int; + public var visible:Boolean; + public var zOrder:Number; + + public var global:DBTransform; + public var transform:DBTransform; + public var pivot:Point; + public var color:ColorTransform; + + + public function TransformFrame() + { + super(); + + tweenEasing = 0; + tweenRotate = 0; + displayIndex = 0; + visible = true; + zOrder = NaN; + + global = new DBTransform(); + transform = new DBTransform(); + pivot = new Point(); + } + + override public function dispose():void + { + super.dispose(); + global = null; + transform = null; + //SkeletonData pivots + pivot = null; + color = null; + } + } + +} \ No newline at end of file diff --git a/src/dragonBones/objects/TransformTimeline.as b/src/dragonBones/objects/TransformTimeline.as new file mode 100644 index 0000000..57eca8e --- /dev/null +++ b/src/dragonBones/objects/TransformTimeline.as @@ -0,0 +1,48 @@ +package dragonBones.objects +{ + import flash.geom.Point; + + public final class TransformTimeline extends Timeline + { + public static const HIDE_TIMELINE:TransformTimeline = new TransformTimeline(); + + public var transformed:Boolean; + + public var originTransform:DBTransform; + public var originPivot:Point; + + private var _offset:Number; + public function get offset():Number + { + return _offset; + } + public function set offset(value:Number):void + { + _offset = (value || 0) % 1; + if(_offset < 0) + { + _offset += 1; + } + } + + public function TransformTimeline() + { + super(); + + originTransform = new DBTransform(); + originPivot = new Point(); + _offset = 0; + } + + override public function dispose():void + { + if(this == HIDE_TIMELINE) + { + return; + } + super.dispose(); + originTransform = null; + originPivot = null; + } + } +} \ No newline at end of file diff --git a/src/dragonBones/objects/XMLDataParser.as b/src/dragonBones/objects/XMLDataParser.as index cef6938..784868f 100644 --- a/src/dragonBones/objects/XMLDataParser.as +++ b/src/dragonBones/objects/XMLDataParser.as @@ -6,488 +6,303 @@ * @langversion 3.0 * @version 2.0 */ - import dragonBones.animation.Tween; - import dragonBones.errors.UnknownDataError; - import dragonBones.utils.BytesType; + + import dragonBones.core.DragonBones; + import dragonBones.core.dragonBones_internal; + import dragonBones.objects.AnimationData; + import dragonBones.objects.ArmatureData; + import dragonBones.objects.BoneData; + import dragonBones.objects.DBTransform; + import dragonBones.objects.DisplayData; + import dragonBones.objects.Frame; + import dragonBones.objects.SkeletonData; + import dragonBones.objects.SkinData; + import dragonBones.objects.SlotData; + import dragonBones.objects.Timeline; + import dragonBones.objects.TransformFrame; + import dragonBones.objects.TransformTimeline; import dragonBones.utils.ConstValues; - import dragonBones.utils.TransformUtils; - import dragonBones.utils.dragonBones_internal; + import dragonBones.utils.DBDataUtil; + import dragonBones.utils.parseOldXMLData; + import flash.geom.ColorTransform; - import flash.utils.ByteArray; + import flash.geom.Point; + import flash.geom.Rectangle; + use namespace dragonBones_internal; + /** - * The XMLDataParser xlass creates and parses xml data from dragonBones generated maps. + * The XMLDataParser class parses xml data from dragonBones generated maps. */ - public class XMLDataParser + final public class XMLDataParser { - private static const ANGLE_TO_RADIAN:Number = Math.PI / 180; - private static const HALF_PI:Number = Math.PI * 0.5; - private static var _currentSkeletonData:SkeletonData; - private static var _helpNode:BoneTransform = new BoneTransform(); - private static var _helpFrameData:FrameData = new FrameData(); + public static function parseTextureAtlasData(rawData:XML, scale:Number = 1):Object + { + var textureAtlasData:Object = {}; + textureAtlasData.__name = rawData.@[ConstValues.A_NAME]; + for each (var subTextureXML:XML in rawData[ConstValues.SUB_TEXTURE]) + { + var subTextureName:String = subTextureXML.@[ConstValues.A_NAME]; + var subTextureData:Rectangle = new Rectangle(); + subTextureData.x = int(subTextureXML.@[ConstValues.A_X]) / scale; + subTextureData.y = int(subTextureXML.@[ConstValues.A_Y]) / scale; + subTextureData.width = int(subTextureXML.@[ConstValues.A_WIDTH]) / scale; + subTextureData.height = int(subTextureXML.@[ConstValues.A_HEIGHT]) / scale; + + textureAtlasData[subTextureName] = subTextureData; + } + + return textureAtlasData; + } - private static function checkSkeletonXMLVersion(skeletonXML:XML):void + /** + * Parse the SkeletonData. + * @param xml The SkeletonData xml to parse. + * @return A SkeletonData instance. + */ + public static function parseSkeletonData(rawData:XML):SkeletonData { - var version:String = skeletonXML.attribute(ConstValues.A_VERSION); + if(!rawData) + { + throw new ArgumentError(); + } + var version:String = rawData.@[ConstValues.A_VERSION]; switch (version) { - case "1.4": case "1.5": case "2.0": case "2.1": case "2.1.1": case "2.1.2": - case ConstValues.VERSION: + case "2.2": + return parseOldXMLData(rawData as XML); + case DragonBones.DATA_VERSION: break; - default: - throw new Error("Nonsupport data version!"); + default: + throw new Error("Nonsupport version!"); } - } - - /** @private */ - public static function getElementsByAttribute(xmlList:XMLList, attribute:String, value:String):XMLList - { - var result:XMLList = new XMLList(); - var length:uint = xmlList.length(); - for (var i:int = 0; i < length; i++) + + var frameRate:uint = int(rawData.@[ConstValues.A_FRAME_RATE]); + + var data:SkeletonData = new SkeletonData(); + data.name = rawData.@[ConstValues.A_NAME]; + for each(var armatureXML:XML in rawData[ConstValues.ARMATURE]) { - var xml:XML = xmlList[i]; - if (xml.@[attribute].toString() == value) - { - result[result.length()] = xmlList[i]; - } + data.addArmatureData(parseArmatureData(armatureXML, data, frameRate)); } - return result; - } - /** - * Compress all data into a ByteArray for serialization. - * @param skeletonXML The Skeleton data. - * @param textureAtlasXML The TextureAtlas data. - * @param byteArray The ByteArray representing the map. - * @return ByteArray. A DragonBones compatible ByteArray. - */ - public static function compressData(skeletonXML:XML, textureAtlasXML:XML, byteArray:ByteArray):ByteArray - { - var byteArrayCopy:ByteArray = new ByteArray(); - byteArrayCopy.writeBytes(byteArray); - var xmlBytes:ByteArray = new ByteArray(); - xmlBytes.writeUTFBytes(textureAtlasXML.toXMLString()); - xmlBytes.compress(); - byteArrayCopy.position = byteArrayCopy.length; - byteArrayCopy.writeBytes(xmlBytes); - byteArrayCopy.writeInt(xmlBytes.length); - xmlBytes.length = 0; - xmlBytes.writeUTFBytes(skeletonXML.toXMLString()); - xmlBytes.compress(); - byteArrayCopy.position = byteArrayCopy.length; - byteArrayCopy.writeBytes(xmlBytes); - byteArrayCopy.writeInt(xmlBytes.length); - return byteArrayCopy; + + return data; } - /** - * Decompress a compatible DragonBones data. - * @param compressedByteArray The ByteArray to decompress. - * @return A DecompressedData instance. - */ - public static function decompressData(compressedByteArray:ByteArray):DecompressedData + + private static function parseArmatureData(armatureXML:XML, data:SkeletonData, frameRate:uint):ArmatureData { - var dataType:String = BytesType.getType(compressedByteArray); - switch (dataType) + var armatureData:ArmatureData = new ArmatureData(); + armatureData.name = armatureXML.@[ConstValues.A_NAME]; + + for each(var boneXML:XML in armatureXML[ConstValues.BONE]) { - case BytesType.SWF: - case BytesType.PNG: - case BytesType.JPG: - try - { - compressedByteArray.position = compressedByteArray.length - 4; - var strSize:int = compressedByteArray.readInt(); - var position:uint = compressedByteArray.length - 4 - strSize; - var xmlBytes:ByteArray = new ByteArray(); - xmlBytes.writeBytes(compressedByteArray, position, strSize); - xmlBytes.uncompress(); - compressedByteArray.length = position; - var skeletonXML:XML = XML(xmlBytes.readUTFBytes(xmlBytes.length)); - compressedByteArray.position = compressedByteArray.length - 4; - strSize = compressedByteArray.readInt(); - position = compressedByteArray.length - 4 - strSize; - xmlBytes.length = 0; - xmlBytes.writeBytes(compressedByteArray, position, strSize); - xmlBytes.uncompress(); - compressedByteArray.length = position; - var textureAtlasXML:XML = XML(xmlBytes.readUTFBytes(xmlBytes.length)); - } - catch (e:Error) - { - throw new Error("Decompress error!"); - } - var decompressedData:DecompressedData = new DecompressedData(skeletonXML, textureAtlasXML, compressedByteArray); - return decompressedData; - case BytesType.ZIP: - throw new Error("Can not decompress zip!"); - default: - throw new UnknownDataError(); + armatureData.addBoneData(parseBoneData(boneXML)); } - return null; - } - /** - * Parse the SkeletonData. - * @param skeletonXML The Skeleton xml to parse. - * @return A SkeletonData instance. - */ - public static function parseSkeletonData(skeletonXML:XML):SkeletonData - { - checkSkeletonXMLVersion(skeletonXML); - var skeletonData:SkeletonData = new SkeletonData(); - skeletonData._name = skeletonXML.attribute(ConstValues.A_NAME); - skeletonData._frameRate = int(skeletonXML.attribute(ConstValues.A_FRAME_RATE)); - _currentSkeletonData = skeletonData; - for each (var armatureXML:XML in skeletonXML.elements(ConstValues.ARMATURES).elements(ConstValues.ARMATURE)) + + for each(var skinXML:XML in armatureXML[ConstValues.SKIN]) { - var armatureName:String = armatureXML.attribute(ConstValues.A_NAME); - var armatureData:ArmatureData = skeletonData.getArmatureData(armatureName); - if (armatureData) - { - parseArmatureData(armatureXML, armatureData); - } - else - { - armatureData = new ArmatureData(); - parseArmatureData(armatureXML, armatureData); - skeletonData._armatureDataList.addData(armatureData, armatureName); - } + armatureData.addSkinData(parseSkinData(skinXML, data)); } - for each (var animationXML:XML in skeletonXML.elements(ConstValues.ANIMATIONS).elements(ConstValues.ANIMATION)) + DBDataUtil.transformArmatureData(armatureData); + armatureData.sortBoneDataList(); + + for each(var animationXML:XML in armatureXML[ConstValues.ANIMATION]) { - var animationName:String = animationXML.attribute(ConstValues.A_NAME); - armatureData = skeletonData.getArmatureData(animationName); - var animationData:AnimationData = skeletonData.getAnimationData(animationName); - if (animationData) - { - parseAnimationData(animationXML, animationData, armatureData); - } - else - { - animationData = new AnimationData(); - parseAnimationData(animationXML, animationData, armatureData); - skeletonData._animationDataList.addData(animationData, animationName); - } + armatureData.addAnimationData(parseAnimationData(animationXML, armatureData, frameRate)); } - _currentSkeletonData = null; - return skeletonData; + + return armatureData; } - private static function parseArmatureData(armatureXML:XML, armatureData:ArmatureData):void + private static function parseBoneData(boneXML:XML):BoneData { - var boneXMLList:XMLList = armatureXML.elements(ConstValues.BONE); - for each (var boneXML:XML in boneXMLList) - { - var boneName:String = boneXML.attribute(ConstValues.A_NAME); - var parentName:String = boneXML.attribute(ConstValues.A_PARENT); - var parentXML:XML = getElementsByAttribute(boneXMLList, ConstValues.A_NAME, parentName)[0]; - var boneData:BoneData = armatureData.getBoneData(boneName); - if (boneData) - { - parseBoneData(boneXML, parentXML, boneData); - } - else - { - boneData = new BoneData(); - parseBoneData(boneXML, parentXML, boneData); - armatureData._boneDataList.addData(boneData, boneName); - } - } + var boneData:BoneData = new BoneData(); + boneData.name = boneXML.@[ConstValues.A_NAME]; + boneData.parent = boneXML.@[ConstValues.A_PARENT]; + boneData.length = Number(boneXML.@[ConstValues.A_LENGTH]); - armatureData.updateBoneList(); + parseTransform(boneXML[ConstValues.TRANSFORM][0], boneData.global); + boneData.transform.copy(boneData.global); + + return boneData; } - /** @private */ - dragonBones_internal static function parseBoneData(boneXML:XML, parentXML:XML, boneData:BoneData):void + private static function parseSkinData(skinXML:XML, data:SkeletonData):SkinData { - parseNode(boneXML, boneData.node); - if (parentXML) - { - boneData._parent = parentXML.attribute(ConstValues.A_NAME); - parseNode(parentXML, _helpNode); - TransformUtils.transformPointWithParent(boneData.node, _helpNode); - } - else + var skinData:SkinData = new SkinData(); + skinData.name = skinXML.@[ConstValues.A_NAME]; + + for each(var slotXML:XML in skinXML[ConstValues.SLOT]) { - boneData._parent = null; + skinData.addSlotData(parseSlotData(slotXML, data)); } - if (_currentSkeletonData) + + return skinData; + } + + private static function parseSlotData(slotXML:XML, data:SkeletonData):SlotData + { + var slotData:SlotData = new SlotData(); + slotData.name = slotXML.@[ConstValues.A_NAME]; + slotData.parent = slotXML.@[ConstValues.A_PARENT]; + slotData.zOrder = Number(slotXML.@[ConstValues.A_Z_ORDER]); + for each(var displayXML:XML in slotXML[ConstValues.DISPLAY]) { - var displayXMLList:XMLList = boneXML.elements(ConstValues.DISPLAY); - var length:uint = displayXMLList.length(); - for (var i:int = 0; i < length; i++) - { - var displayXML:XML = displayXMLList[i]; - var displayName:String = displayXML.attribute(ConstValues.A_NAME); - boneData._displayNames[i] = displayName; - var displayData:DisplayData = _currentSkeletonData.getDisplayData(displayName); - if (displayData) - { - parseDisplayData(displayXML, displayData); - } - else - { - displayData = new DisplayData(); - parseDisplayData(displayXML, displayData); - _currentSkeletonData._displayDataList.addData(displayData, displayName); - } - } + slotData.addDisplayData(parseDisplayData(displayXML, data)); } + + return slotData; } - private static function parseDisplayData(displayXML:XML, displayData:DisplayData):void + private static function parseDisplayData(displayXML:XML, data:SkeletonData):DisplayData { - displayData._isArmature = Boolean(int(displayXML.attribute(ConstValues.A_IS_ARMATURE))); - displayData.pivotX = Number(displayXML.attribute(ConstValues.A_PIVOT_X)); - displayData.pivotY = Number(displayXML.attribute(ConstValues.A_PIVOT_Y)); + var displayData:DisplayData = new DisplayData(); + displayData.name = displayXML.@[ConstValues.A_NAME]; + displayData.type = displayXML.@[ConstValues.A_TYPE]; + + displayData.pivot = data.addSubTexturePivot( + 0, + 0, + displayData.name + ); + + parseTransform(displayXML[ConstValues.TRANSFORM][0], displayData.transform, displayData.pivot); + + return displayData; } /** @private */ - dragonBones_internal static function parseAnimationData(animationXML:XML, animationData:AnimationData, armatureData:ArmatureData):void + dragonBones_internal static function parseAnimationData(animationXML:XML, armatureData:ArmatureData, frameRate:uint):AnimationData { - for each (var movementXML:XML in animationXML.elements(ConstValues.MOVEMENT)) + var animationData:AnimationData = new AnimationData(); + animationData.name = animationXML.@[ConstValues.A_NAME]; + animationData.frameRate = frameRate; + animationData.loop = int(animationXML.@[ConstValues.A_LOOP]); + animationData.fadeInTime = Number(animationXML.@[ConstValues.A_FADE_IN_TIME]); + animationData.duration = Number(animationXML.@[ConstValues.A_DURATION]) / frameRate; + animationData.scale = Number(animationXML.@[ConstValues.A_SCALE]); + animationData.tweenEasing = Number(animationXML.@[ConstValues.A_TWEEN_EASING]); + + parseTimeline(animationXML, animationData, parseMainFrame, frameRate); + + var timeline:TransformTimeline; + var timelineName:String; + for each(var timelineXML:XML in animationXML[ConstValues.TIMELINE]) { - var movementName:String = movementXML.attribute(ConstValues.A_NAME); - var movementData:MovementData = animationData.getMovementData(movementName); - if (movementData) - { - parseMovementData(movementXML, armatureData, movementData); - } - else - { - movementData = new MovementData(); - parseMovementData(movementXML, armatureData, movementData); - animationData._movementDataList.addData(movementData, movementName); - } + timeline = parseTransformTimeline(timelineXML, animationData.duration, frameRate); + timelineName = timelineXML.@[ConstValues.A_NAME]; + animationData.addTimeline(timeline, timelineName); } + + DBDataUtil.addHideTimeline(animationData, armatureData); + DBDataUtil.transformAnimationData(animationData, armatureData); + + return animationData; } - private static function parseMovementData(movementXML:XML, armatureData:ArmatureData, movementData:MovementData):void + private static function parseTimeline(timelineXML:XML, timeline:Timeline, frameParser:Function, frameRate:uint):void { - if (_currentSkeletonData) + var position:Number = 0; + var frame:Frame; + for each(var frameXML:XML in timelineXML[ConstValues.FRAME]) { - var frameRate:uint = _currentSkeletonData._frameRate; - var duration:int = int(movementXML.attribute(ConstValues.A_DURATION)); - movementData.duration = (duration > 1) ? (duration / frameRate) : 0; - movementData.durationTo = int(movementXML.attribute(ConstValues.A_DURATION_TO)) / frameRate; - movementData.durationTween = int(movementXML.attribute(ConstValues.A_DURATION_TWEEN)) / frameRate; - movementData.loop = Boolean(int(movementXML.attribute(ConstValues.A_LOOP)) == 1); - movementData.tweenEasing = Number(movementXML.attribute(ConstValues.A_TWEEN_EASING)[0]); + frame = frameParser(frameXML, frameRate); + frame.position = position; + timeline.addFrame(frame); + position += frame.duration; } - var boneNames:Vector. = armatureData.boneNames; - var movementBoneXMLList:XMLList = movementXML.elements(ConstValues.BONE); - for each (var movementBoneXML:XML in movementBoneXMLList) + if(frame) { - var boneName:String = movementBoneXML.attribute(ConstValues.A_NAME); - var boneData:BoneData = armatureData.getBoneData(boneName); - var parentMovementBoneXML:XML = getElementsByAttribute(movementBoneXMLList, ConstValues.A_NAME, boneData.parent)[0]; - var movementBoneData:MovementBoneData = movementData.getMovementBoneData(boneName); - if (movementBoneXML) - { - if (movementBoneData) - { - parseMovementBoneData(movementBoneXML, parentMovementBoneXML, boneData, movementBoneData); - } - else - { - movementBoneData = new MovementBoneData(); - parseMovementBoneData(movementBoneXML, parentMovementBoneXML, boneData, movementBoneData); - movementData._movementBoneDataList.addData(movementBoneData, boneName); - } - } - var index:int = boneNames.indexOf(boneName); - if (index >= 0) - { - boneNames.splice(index, 1); - } - } - for each (boneName in boneNames) - { - movementData._movementBoneDataList.addData(MovementBoneData.HIDE_DATA, boneName); - } - var movementFrameXMLList:XMLList = movementXML.elements(ConstValues.FRAME); - var length:uint = movementFrameXMLList.length(); - var movementFrameList:Vector. = movementData._movementFrameList; - for (var i:int = 0; i < length; i++) - { - var movementFrameXML:XML = movementFrameXMLList[i]; - var movementFrameData:MovementFrameData = movementFrameList.length > i ? movementFrameList[i] : null; - if (movementFrameData) - { - parseMovementFrameData(movementFrameXML, movementFrameData); - } - else - { - movementFrameData = new MovementFrameData(); - parseMovementFrameData(movementFrameXML, movementFrameData) - if (movementFrameList.indexOf(movementFrameData) < 0) - { - movementFrameList.push(movementFrameData); - } - } + frame.duration = timeline.duration - frame.position; } } - private static function parseMovementBoneData(movementBoneXML:XML, parentMovementBoneXML:XML, boneData:BoneData, movementBoneData:MovementBoneData):void + private static function parseTransformTimeline(timelineXML:XML, duration:Number, frameRate:uint):TransformTimeline { - movementBoneData.setValues( - Number(movementBoneXML.attribute(ConstValues.A_MOVEMENT_SCALE)), - Number(movementBoneXML.attribute(ConstValues.A_MOVEMENT_DELAY)) - ); + var timeline:TransformTimeline = new TransformTimeline(); + timeline.duration = duration; - var i:uint = 0; - var parentTotalDuration:uint = 0; - var totalDuration:uint = 0; - var currentDuration:uint = 0; - if (parentMovementBoneXML) - { - var parentFrameXMLList:XMLList = parentMovementBoneXML.elements(ConstValues.FRAME); - var parentFrameCount:uint = parentFrameXMLList.length(); - var parentFrameXML:XML; - } - var frameXMLList:XMLList = movementBoneXML.elements(ConstValues.FRAME); - var frameCount:uint = frameXMLList.length(); - var frameList:Vector. = movementBoneData._frameList; - for (var j:int = 0; j < frameCount; j++) - { - var frameXML:XML = frameXMLList[j]; - var frameData:FrameData = frameList.length > j ? frameList[j] : null; - - if (frameData) - { - parseFrameData(frameXML, frameData); - } - else - { - frameData = new FrameData(); - parseFrameData(frameXML, frameData); - if (frameList.indexOf(frameData) < 0) - { - frameList.push(frameData); - } - } - if (parentMovementBoneXML) - { - while (i < parentFrameCount && (parentFrameXML ? (totalDuration < parentTotalDuration || totalDuration >= parentTotalDuration + currentDuration) : true)) - { - parentFrameXML = parentFrameXMLList[i]; - parentTotalDuration += currentDuration; - currentDuration = int(parentFrameXML.attribute(ConstValues.A_DURATION)); - i++; - } - parseFrameData(parentFrameXML, _helpFrameData); - var tweenFrameXML:XML = parentFrameXMLList[i]; - var progress:Number; - if (tweenFrameXML) - { - progress = (totalDuration - parentTotalDuration) / currentDuration; - } - else - { - tweenFrameXML = parentFrameXML; - progress = 0; - } - if (isNaN(_helpFrameData.tweenEasing)) - { - progress = 0; - } - else - { - progress = Tween.getEaseValue(progress, _helpFrameData.tweenEasing); - } - parseNode(tweenFrameXML, _helpNode); - TransformUtils.setOffSetNode(_helpFrameData.node, _helpNode, _helpNode, _helpFrameData.tweenRotate); - - _helpNode.setValues( - _helpFrameData.node.x + progress * _helpNode.x, - _helpFrameData.node.y + progress * _helpNode.y, - _helpFrameData.node.skewX + progress * _helpNode.skewX, - _helpFrameData.node.skewY + progress * _helpNode.skewY, - _helpFrameData.node.scaleX + progress * _helpNode.scaleX, - _helpFrameData.node.scaleY + progress * _helpNode.scaleY, - _helpFrameData.node.pivotX + progress * _helpNode.pivotX, - _helpFrameData.node.pivotY + progress * _helpNode.pivotY - ); - - TransformUtils.transformPointWithParent(frameData.node, _helpNode); - } - totalDuration += int(frameXML.attribute(ConstValues.A_DURATION)); - frameData.node.x -= boneData.node.x; - frameData.node.y -= boneData.node.y; - frameData.node.skewX -= boneData.node.skewX; - frameData.node.skewY -= boneData.node.skewY; - frameData.node.scaleX -= boneData.node.scaleX; - frameData.node.scaleY -= boneData.node.scaleY; - frameData.node.pivotX -= boneData.node.pivotX; - frameData.node.pivotY -= boneData.node.pivotY; - frameData.node.z -= boneData.node.z; - } + parseTimeline(timelineXML, timeline, parseTransformFrame, frameRate); + + timeline.scale = Number(timelineXML.@[ConstValues.A_SCALE]); + timeline.offset = Number(timelineXML.@[ConstValues.A_OFFSET]); + + return timeline; } - private static function parseMovementFrameData(movementFrameXML:XML, movementFrameData:MovementFrameData):void + private static function parseFrame(frameXML:XML, frame:Frame, frameRate:uint):void { - if(_currentSkeletonData) - { - movementFrameData.setValues( - Number(movementFrameXML.attribute(ConstValues.A_DURATION)) / _currentSkeletonData._frameRate, - movementFrameXML.attribute(ConstValues.A_MOVEMENT), - movementFrameXML.attribute(ConstValues.A_EVENT), - movementFrameXML.attribute(ConstValues.A_SOUND) - ); - } + frame.duration = Number(frameXML.@[ConstValues.A_DURATION]) / frameRate; + frame.action = frameXML.@[ConstValues.A_ACTION]; + frame.event = frameXML.@[ConstValues.A_EVENT]; + frame.sound = frameXML.@[ConstValues.A_SOUND]; } - /** @private */ - dragonBones_internal static function parseFrameData(frameXML:XML, frameData:FrameData):void + private static function parseMainFrame(frameXML:XML, frameRate:uint):Frame { - parseNode(frameXML, frameData.node); - if (_currentSkeletonData) - { - var colorTransformXML:XML = frameXML.elements(ConstValues.COLOR_TRANSFORM)[0]; - if (colorTransformXML) - { - parseColorTransform(colorTransformXML, frameData.colorTransform); - } - frameData.duration = int(frameXML.attribute(ConstValues.A_DURATION)) / _currentSkeletonData._frameRate; - frameData.tweenEasing = Number(frameXML.attribute(ConstValues.A_TWEEN_EASING)); - frameData.tweenRotate = int(frameXML.attribute(ConstValues.A_TWEEN_ROTATE)); - frameData.displayIndex = int(frameXML.attribute(ConstValues.A_DISPLAY_INDEX)); - frameData.movement = String(frameXML.attribute(ConstValues.A_MOVEMENT)); - frameData.event = String(frameXML.attribute(ConstValues.A_EVENT)); - frameData.sound = String(frameXML.attribute(ConstValues.A_SOUND)); - frameData.soundEffect = String(frameXML.attribute(ConstValues.A_SOUND_EFFECT)); - var visibleStr:String = String(frameXML.attribute(ConstValues.A_VISIBLE)); - frameData.visible = (visibleStr == "1" || visibleStr == ""); - } + var frame:Frame = new Frame(); + parseFrame(frameXML, frame, frameRate); + return frame; } - private static function parseNode(xml:XML, node:BoneTransform):void + private static function parseTransformFrame(frameXML:XML, frameRate:uint):TransformFrame { - node.x = Number(xml.attribute(ConstValues.A_X)); - node.y = Number(xml.attribute(ConstValues.A_Y)); - node.skewX = Number(xml.attribute(ConstValues.A_SKEW_X)) * ANGLE_TO_RADIAN; - node.skewY = Number(xml.attribute(ConstValues.A_SKEW_Y)) * ANGLE_TO_RADIAN; - node.scaleX = Number(xml.attribute(ConstValues.A_SCALE_X)); - node.scaleY = Number(xml.attribute(ConstValues.A_SCALE_Y)); - node.pivotX = Number(xml.attribute(ConstValues.A_PIVOT_X)); - node.pivotY = Number(xml.attribute(ConstValues.A_PIVOT_Y)); - node.z = int(xml.attribute(ConstValues.A_Z)); + var frame:TransformFrame = new TransformFrame(); + parseFrame(frameXML, frame, frameRate); + + frame.visible = uint(frameXML.@[ConstValues.A_HIDE]) != 1; + frame.tweenEasing = Number(frameXML.@[ConstValues.A_TWEEN_EASING]); + frame.tweenRotate = Number(frameXML.@[ConstValues.A_TWEEN_ROTATE]); + frame.displayIndex = Number(frameXML.@[ConstValues.A_DISPLAY_INDEX]); + // + frame.zOrder = Number(frameXML.@[ConstValues.A_Z_ORDER][0]); + + parseTransform(frameXML[ConstValues.TRANSFORM][0], frame.global, frame.pivot); + frame.transform.copy(frame.global); + + var colorTransformXML:XML = frameXML[ConstValues.COLOR_TRANSFORM][0]; + if(colorTransformXML) + { + frame.color = new ColorTransform(); + frame.color.alphaOffset = Number(colorTransformXML.@[ConstValues.A_ALPHA_OFFSET]); + frame.color.redOffset = Number(colorTransformXML.@[ConstValues.A_RED_OFFSET]); + frame.color.greenOffset = Number(colorTransformXML.@[ConstValues.A_GREEN_OFFSET]); + frame.color.blueOffset = Number(colorTransformXML.@[ConstValues.A_BLUE_OFFSET]); + + frame.color.alphaMultiplier = Number(colorTransformXML.@[ConstValues.A_ALPHA_MULTIPLIER]) * 0.01; + frame.color.redMultiplier = Number(colorTransformXML.@[ConstValues.A_RED_MULTIPLIER]) * 0.01; + frame.color.greenMultiplier = Number(colorTransformXML.@[ConstValues.A_GREEN_MULTIPLIER]) * 0.01; + frame.color.blueMultiplier = Number(colorTransformXML.@[ConstValues.A_BLUE_MULTIPLIER]) * 0.01; + } + + return frame; } - private static function parseColorTransform(xml:XML, colorTransform:ColorTransform):void + private static function parseTransform(transformXML:XML, transform:DBTransform, pivot:Point = null):void { - colorTransform.alphaOffset = int(xml.attribute(ConstValues.A_ALPHA)); - colorTransform.redOffset = int(xml.attribute(ConstValues.A_RED)); - colorTransform.greenOffset = int(xml.attribute(ConstValues.A_GREEN)); - colorTransform.blueOffset = int(xml.attribute(ConstValues.A_BLUE)); - colorTransform.alphaMultiplier = int(xml.attribute(ConstValues.A_ALPHA_MULTIPLIER)) * 0.01; - colorTransform.redMultiplier = int(xml.attribute(ConstValues.A_RED_MULTIPLIER)) * 0.01; - colorTransform.greenMultiplier = int(xml.attribute(ConstValues.A_GREEN_MULTIPLIER)) * 0.01; - colorTransform.blueMultiplier = int(xml.attribute(ConstValues.A_BLUE_MULTIPLIER)) * 0.01; + if(transformXML) + { + if(transform) + { + transform.x = Number(transformXML.@[ConstValues.A_X]); + transform.y = Number(transformXML.@[ConstValues.A_Y]); + transform.skewX = Number(transformXML.@[ConstValues.A_SKEW_X]) * ConstValues.ANGLE_TO_RADIAN; + transform.skewY = Number(transformXML.@[ConstValues.A_SKEW_Y]) * ConstValues.ANGLE_TO_RADIAN; + transform.scaleX = Number(transformXML.@[ConstValues.A_SCALE_X]); + transform.scaleY = Number(transformXML.@[ConstValues.A_SCALE_Y]); + } + if(pivot) + { + pivot.x = Number(transformXML.@[ConstValues.A_PIVOT_X]); + pivot.y = Number(transformXML.@[ConstValues.A_PIVOT_Y]); + } + } } } -} +} \ No newline at end of file diff --git a/src/dragonBones/textures/ITextureAtlas.as b/src/dragonBones/textures/ITextureAtlas.as index 6719daa..9d9a6d1 100644 --- a/src/dragonBones/textures/ITextureAtlas.as +++ b/src/dragonBones/textures/ITextureAtlas.as @@ -10,7 +10,6 @@ package dragonBones.textures /** * The ITextureAtlas interface defines the methods used by all ITextureAtlas within the dragonBones system (flash or starling DisplayObject based). * @see dragonBones.Armature - * @see dragonBones.animation.WorldClock */ public interface ITextureAtlas { diff --git a/src/dragonBones/textures/NativeTextureAtlas.as b/src/dragonBones/textures/NativeTextureAtlas.as index 40dc394..22e7604 100644 --- a/src/dragonBones/textures/NativeTextureAtlas.as +++ b/src/dragonBones/textures/NativeTextureAtlas.as @@ -6,11 +6,11 @@ package dragonBones.textures * @langversion 3.0 * @version 2.0 */ - import dragonBones.textures.SubTextureData; - import dragonBones.utils.ConstValues; - import dragonBones.utils.dragonBones_internal; - import flash.display.MovieClip; + import dragonBones.core.dragonBones_internal; + import dragonBones.objects.DataParser; + import flash.display.BitmapData; + import flash.display.MovieClip; import flash.geom.Rectangle; use namespace dragonBones_internal; @@ -20,14 +20,6 @@ package dragonBones.textures */ public class NativeTextureAtlas implements ITextureAtlas { - /** - * @private - */ - protected var _width:int; - /** - * @private - */ - protected var _height:int; /** * @private */ @@ -81,11 +73,10 @@ package dragonBones.textures * @param textureScale A scale value (x and y axis) * @param isDifferentXML */ - public function NativeTextureAtlas(texture:Object, textureAtlasXML:XML, textureScale:Number = 1, isDifferentXML:Boolean = false) + public function NativeTextureAtlas(texture:Object, textureAtlasRawData:Object, textureScale:Number = 1, isDifferentXML:Boolean = false) { _scale = textureScale; _isDifferentXML = isDifferentXML; - _subTextureDataDic = {}; if (texture is BitmapData) { _bitmapData = texture as BitmapData; @@ -95,7 +86,7 @@ package dragonBones.textures _movieClip = texture as MovieClip; _movieClip.stop(); } - parseData(textureAtlasXML); + parseData(textureAtlasRawData); } /** * Clean up all resources used by this NativeTextureAtlas instance. @@ -108,7 +99,6 @@ package dragonBones.textures _bitmapData.dispose(); } _bitmapData = null; - _subTextureDataDic = {}; } /** * The area occupied by all assets related to that name. @@ -120,25 +110,12 @@ package dragonBones.textures return _subTextureDataDic[name]; } - protected function parseData(textureAtlasXML:XML):void + protected function parseData(textureAtlasRawData:Object):void { - _name = textureAtlasXML.attribute(ConstValues.A_NAME); - _width = int(textureAtlasXML.attribute(ConstValues.A_WIDTH)); - _height = int(textureAtlasXML.attribute(ConstValues.A_HEIGHT)); - var scale:Number = _isDifferentXML ? _scale : 1; - for each (var subTextureXML:XML in textureAtlasXML.elements(ConstValues.SUB_TEXTURE)) - { - var subTextureName:String = subTextureXML.attribute(ConstValues.A_NAME); - var subTextureData:SubTextureData = new SubTextureData(); - subTextureData.x = int(subTextureXML.attribute(ConstValues.A_X)) / scale; - subTextureData.y = int(subTextureXML.attribute(ConstValues.A_Y)) / scale; - subTextureData.width = int(subTextureXML.attribute(ConstValues.A_WIDTH)) / scale; - subTextureData.height = int(subTextureXML.attribute(ConstValues.A_HEIGHT)) / scale; - //1.4 - subTextureData.pivotX = int(subTextureXML.attribute(ConstValues.A_PIVOT_X)); - subTextureData.pivotY = int(subTextureXML.attribute(ConstValues.A_PIVOT_Y)); - _subTextureDataDic[subTextureName] = subTextureData; - } + _subTextureDataDic = DataParser.parseTextureAtlas(textureAtlasRawData, _isDifferentXML ? _scale : 1); + _name = _subTextureDataDic.__name; + + delete _subTextureDataDic.__name; } dragonBones_internal function movieClipToBitmapData():void @@ -146,10 +123,15 @@ package dragonBones.textures if (!_bitmapData && _movieClip) { _movieClip.gotoAndStop(1); - _bitmapData = new BitmapData(_width, _height, true, 0xFF00FF); + _bitmapData = new BitmapData(getNearest2N(_movieClip.width), getNearest2N(_movieClip.height), true, 0xFF00FF); _bitmapData.draw(_movieClip); _movieClip.gotoAndStop(_movieClip.totalFrames); } } + + private function getNearest2N(_n:uint):uint + { + return _n & _n - 1?1 << _n.toString(2).length:_n; + } } } \ No newline at end of file diff --git a/src/dragonBones/textures/StarlingTextureAtlas.as b/src/dragonBones/textures/StarlingTextureAtlas.as index 775c941..a984946 100644 --- a/src/dragonBones/textures/StarlingTextureAtlas.as +++ b/src/dragonBones/textures/StarlingTextureAtlas.as @@ -6,10 +6,11 @@ * @langversion 3.0 * @version 2.0 */ - import dragonBones.utils.ConstValues; - import dragonBones.utils.dragonBones_internal; + import dragonBones.core.dragonBones_internal; + import dragonBones.objects.DataParser; + import flash.display.BitmapData; - import flash.geom.Rectangle; + import starling.textures.SubTexture; import starling.textures.Texture; import starling.textures.TextureAtlas; @@ -50,19 +51,16 @@ * @param textureAtlasXML A textureAtlas xml * @param isDifferentXML */ - public function StarlingTextureAtlas(texture:Texture, textureAtlasXML:XML, isDifferentXML:Boolean = false) + public function StarlingTextureAtlas(texture:Texture, textureAtlasRawData:Object, isDifferentXML:Boolean = false) { + super(texture, null); if (texture) { _scale = texture.scale; _isDifferentXML = isDifferentXML; - } - super(texture, textureAtlasXML); - if (textureAtlasXML) - { - _name = textureAtlasXML.attribute(ConstValues.A_NAME); } _subTextureDic = {}; + parseData(textureAtlasRawData); } /** * Clean up all resources used by this StarlingTextureAtlas instance. @@ -74,7 +72,7 @@ { subTexture.dispose(); } - _subTextureDic = {}; + _subTextureDic = null; if (_bitmapData) { @@ -102,29 +100,15 @@ } /** * @private - * @param atlasXml */ - override protected function parseAtlasXml(atlasXml:XML):void + protected function parseData(textureAtlasRawData:Object):void { - var scale:Number = _isDifferentXML ? _scale : 1; - - for each (var subTexture:XML in atlasXml.SubTexture) + var textureAtlasData:Object = DataParser.parseTextureAtlas(textureAtlasRawData, _isDifferentXML ? _scale : 1); + _name = textureAtlasData.__name; + delete textureAtlasData.__name; + for(var subTextureName:String in textureAtlasData) { - var name:String = subTexture.attribute("name"); - var x:Number = parseFloat(subTexture.attribute("x")) / scale; - var y:Number = parseFloat(subTexture.attribute("y")) / scale; - var width:Number = parseFloat(subTexture.attribute("width")) / scale; - var height:Number = parseFloat(subTexture.attribute("height")) / scale; - var frameX:Number = parseFloat(subTexture.attribute("frameX")) / scale; - var frameY:Number = parseFloat(subTexture.attribute("frameY")) / scale; - var frameWidth:Number = parseFloat(subTexture.attribute("frameWidth")) / scale; - var frameHeight:Number = parseFloat(subTexture.attribute("frameHeight")) / scale; - //1.4 - var region:SubTextureData = new SubTextureData(x, y, width, height); - region.pivotX = int(subTexture.attribute(ConstValues.A_PIVOT_X)); - region.pivotY = int(subTexture.attribute(ConstValues.A_PIVOT_Y)); - var frame:Rectangle = frameWidth > 0 && frameHeight > 0 ? new Rectangle(frameX, frameY, frameWidth, frameHeight) : null; - addRegion(name, region, frame); + this.addRegion(subTextureName, textureAtlasData[subTextureName], null); } } } diff --git a/src/dragonBones/textures/SubTextureData.as b/src/dragonBones/textures/SubTextureData.as deleted file mode 100644 index d8a9a0f..0000000 --- a/src/dragonBones/textures/SubTextureData.as +++ /dev/null @@ -1,19 +0,0 @@ -package dragonBones.textures -{ - import flash.geom.Rectangle; - - //1.4 - /** @private */ - public class SubTextureData extends Rectangle - { - public var pivotX:Number; - public var pivotY:Number; - - public function SubTextureData(x:Number = 0, y:Number = 0, width:Number = 0, height:Number = 0) - { - super(x, y, width, height); - pivotX = 0; - pivotY = 0; - } - } -} \ No newline at end of file diff --git a/src/dragonBones/utils/ConstValues.as b/src/dragonBones/utils/ConstValues.as index a4cb408..57cf6af 100644 --- a/src/dragonBones/utils/ConstValues.as +++ b/src/dragonBones/utils/ConstValues.as @@ -4,64 +4,61 @@ /** @private */ final public class ConstValues { - public static const VERSION:String = "2.2"; - public static const SKELETON:String = "skeleton"; - public static const ARMATURES:String = "armatures"; + public static const ANGLE_TO_RADIAN:Number = Math.PI / 180; + + public static const DRAGON_BONES:String = "dragonBones"; public static const ARMATURE:String = "armature"; - public static const BONE:String = "b"; - public static const DISPLAY:String = "d"; - public static const ANIMATIONS:String = "animations"; + public static const SKIN:String = "skin"; + public static const BONE:String = "bone"; + public static const SLOT:String = "slot"; + public static const DISPLAY:String = "display"; public static const ANIMATION:String = "animation"; - public static const MOVEMENT:String = "mov"; - public static const FRAME:String = "f"; + public static const TIMELINE:String = "timeline"; + public static const FRAME:String = "frame"; + public static const TRANSFORM:String = "transform"; public static const COLOR_TRANSFORM:String = "colorTransform"; + public static const TEXTURE_ATLAS:String = "TextureAtlas"; public static const SUB_TEXTURE:String = "SubTexture"; - public static const AT:String = "@"; + public static const A_VERSION:String = "version"; + public static const A_IMAGE_PATH:String = "imagePath"; public static const A_FRAME_RATE:String = "frameRate"; public static const A_NAME:String = "name"; - public static const A_DURATION:String = "dr"; - public static const A_DURATION_TO:String = "to"; - public static const A_DURATION_TWEEN:String = "drTW"; - public static const A_LOOP:String = "lp"; - public static const A_MOVEMENT_SCALE:String = "sc"; - public static const A_MOVEMENT_DELAY:String = "dl"; public static const A_PARENT:String = "parent"; - public static const A_SKEW_X:String = "kX"; - public static const A_SKEW_Y:String = "kY"; - public static const A_SCALE_X:String = "cX"; - public static const A_SCALE_Y:String = "cY"; - public static const A_Z:String = "z"; - public static const A_DISPLAY_INDEX:String = "dI"; - public static const A_EVENT:String = "evt"; - public static const A_SOUND:String = "sd"; - public static const A_SOUND_EFFECT:String = "sdE"; - public static const A_TWEEN_EASING:String = "twE"; - public static const A_TWEEN_ROTATE:String = "twR"; - public static const A_IS_ARMATURE:String = "isArmature"; - public static const A_MOVEMENT:String = "mov"; - public static const A_VISIBLE:String = "visible"; - public static const A_X:String = "x"; - public static const A_Y:String = "y"; + public static const A_LENGTH:String = "length"; + public static const A_TYPE:String = "type"; + public static const A_FADE_IN_TIME:String = "fadeInTime"; + public static const A_DURATION:String = "duration"; + public static const A_SCALE:String = "scale"; + public static const A_OFFSET:String = "offset"; + public static const A_LOOP:String = "loop"; + public static const A_EVENT:String = "event"; + public static const A_SOUND:String = "sound"; + public static const A_ACTION:String = "action"; + public static const A_HIDE:String = "hide"; + public static const A_TWEEN_EASING:String = "tweenEasing"; + public static const A_TWEEN_ROTATE:String = "tweenRotate"; + public static const A_DISPLAY_INDEX:String = "displayIndex"; + public static const A_Z_ORDER:String = "z"; public static const A_WIDTH:String = "width"; public static const A_HEIGHT:String = "height"; + public static const A_X:String = "x"; + public static const A_Y:String = "y"; + public static const A_SKEW_X:String = "skX"; + public static const A_SKEW_Y:String = "skY"; + public static const A_SCALE_X:String = "scX"; + public static const A_SCALE_Y:String = "scY"; public static const A_PIVOT_X:String = "pX"; public static const A_PIVOT_Y:String = "pY"; - public static const A_ALPHA:String = "a"; - public static const A_RED:String = "r"; - public static const A_GREEN:String = "g"; - public static const A_BLUE:String = "b"; + public static const A_ALPHA_OFFSET:String = "aO"; + public static const A_RED_OFFSET:String = "rO"; + public static const A_GREEN_OFFSET:String = "gO"; + public static const A_BLUE_OFFSET:String = "bO"; public static const A_ALPHA_MULTIPLIER:String = "aM"; public static const A_RED_MULTIPLIER:String = "rM"; public static const A_GREEN_MULTIPLIER:String = "gM"; public static const A_BLUE_MULTIPLIER:String = "bM"; - public static const V_SOUND_LEFT:String = "l"; - public static const V_SOUND_RIGHT:String = "r"; - public static const V_SOUND_LEFT_TO_RIGHT:String = "lr"; - public static const V_SOUND_RIGHT_TO_LEFT:String = "rl"; - public static const V_SOUND_FADE_IN:String = "in"; - public static const V_SOUND_FADE_OUT:String = "out"; } -} +} \ No newline at end of file diff --git a/src/dragonBones/utils/DBDataUtil.as b/src/dragonBones/utils/DBDataUtil.as new file mode 100644 index 0000000..0be8159 --- /dev/null +++ b/src/dragonBones/utils/DBDataUtil.as @@ -0,0 +1,263 @@ +package dragonBones.utils +{ + import dragonBones.animation.TimelineState; + import dragonBones.objects.AnimationData; + import dragonBones.objects.ArmatureData; + import dragonBones.objects.BoneData; + import dragonBones.objects.DBTransform; + import dragonBones.objects.DisplayData; + import dragonBones.objects.Frame; + import dragonBones.objects.SkinData; + import dragonBones.objects.SlotData; + import dragonBones.objects.TransformFrame; + import dragonBones.objects.TransformTimeline; + + import flash.geom.Point; + + /** @private */ + public final class DBDataUtil + { + private static const _helpTransform1:DBTransform = new DBTransform(); + private static const _helpTransform2:DBTransform = new DBTransform(); + + public static function transformArmatureData(armatureData:ArmatureData):void + { + var i:int = armatureData.boneDataList.length; + var boneData:BoneData; + var parentBoneData:BoneData; + while(i --) + { + boneData = armatureData.boneDataList[i]; + if(boneData.parent) + { + parentBoneData = armatureData.getBoneData(boneData.parent); + if(parentBoneData) + { + boneData.transform.copy(boneData.global); + TransformUtil.transformPointWithParent(boneData.transform, parentBoneData.global); + } + } + } + } + + public static function transformArmatureDataAnimations(armatureData:ArmatureData):void + { + var animationDataList:Vector. = armatureData.animationDataList; + var i:int = animationDataList.length; + while(i --) + { + transformAnimationData(animationDataList[i], armatureData); + } + } + + public static function transformAnimationData(animationData:AnimationData, armatureData:ArmatureData):void + { + var skinData:SkinData = armatureData.getSkinData(null); + var i:int = armatureData.boneDataList.length; + + var boneData:BoneData; + var timeline:TransformTimeline; + var slotData:SlotData; + var displayData:DisplayData + var parentTimeline:TransformTimeline; + var frameList:Vector.; + var originTransform:DBTransform; + var originPivot:Point; + var prevFrame:TransformFrame; + var frameListLength:uint; + var frame:TransformFrame; + + while(i --) + { + boneData = armatureData.boneDataList[i]; + timeline = animationData.getTimeline(boneData.name); + if(!timeline) + { + continue; + } + + slotData = null; + for each(slotData in skinData.slotDataList) + { + if(slotData.parent == boneData.name) + { + break; + } + } + + parentTimeline = boneData.parent?animationData.getTimeline(boneData.parent):null; + + frameList = timeline.frameList; + + originTransform = null; + originPivot = null; + prevFrame = null; + frameListLength = frameList.length; + for(var j:int = 0;j < frameListLength;j ++) + { + frame = frameList[j] as TransformFrame; + if(parentTimeline) + { + //tweenValues to transform. + _helpTransform1.copy(frame.global); + + //get transform from parent timeline. + getTimelineTransform(parentTimeline, frame.position, _helpTransform2); + TransformUtil.transformPointWithParent(_helpTransform1, _helpTransform2); + + //transform to tweenValues. + frame.transform.copy(_helpTransform1); + } + else + { + frame.transform.copy(frame.global); + } + + frame.transform.x -= boneData.transform.x; + frame.transform.y -= boneData.transform.y; + frame.transform.skewX -= boneData.transform.skewX; + frame.transform.skewY -= boneData.transform.skewY; + frame.transform.scaleX -= boneData.transform.scaleX; + frame.transform.scaleY -= boneData.transform.scaleY; + + if(!timeline.transformed) + { + if(slotData) + { + frame.zOrder -= slotData.zOrder; + } + } + + if(!originTransform) + { + originTransform = timeline.originTransform; + originTransform.copy(frame.transform); + originTransform.skewX = TransformUtil.formatRadian(originTransform.skewX); + originTransform.skewY = TransformUtil.formatRadian(originTransform.skewY); + originPivot = timeline.originPivot; + originPivot.x = frame.pivot.x; + originPivot.y = frame.pivot.y; + } + + frame.transform.x -= originTransform.x; + frame.transform.y -= originTransform.y; + frame.transform.skewX = TransformUtil.formatRadian(frame.transform.skewX - originTransform.skewX); + frame.transform.skewY = TransformUtil.formatRadian(frame.transform.skewY - originTransform.skewY); + frame.transform.scaleX -= originTransform.scaleX; + frame.transform.scaleY -= originTransform.scaleY; + + if(!timeline.transformed) + { + frame.pivot.x -= originPivot.x; + frame.pivot.y -= originPivot.y; + } + + if(prevFrame) + { + var dLX:Number = frame.transform.skewX - prevFrame.transform.skewX; + + if(prevFrame.tweenRotate) + { + + if(prevFrame.tweenRotate > 0) + { + if(dLX < 0) + { + frame.transform.skewX += Math.PI * 2; + frame.transform.skewY += Math.PI * 2; + } + + if(prevFrame.tweenRotate > 1) + { + frame.transform.skewX += Math.PI * 2 * (prevFrame.tweenRotate - 1); + frame.transform.skewY += Math.PI * 2 * (prevFrame.tweenRotate - 1); + } + } + else + { + if(dLX > 0) + { + frame.transform.skewX -= Math.PI * 2; + frame.transform.skewY -= Math.PI * 2; + } + + if(prevFrame.tweenRotate < 1) + { + frame.transform.skewX += Math.PI * 2 * (prevFrame.tweenRotate + 1); + frame.transform.skewY += Math.PI * 2 * (prevFrame.tweenRotate + 1); + } + } + } + else + { + frame.transform.skewX = prevFrame.transform.skewX + TransformUtil.formatRadian(frame.transform.skewX - prevFrame.transform.skewX); + frame.transform.skewY = prevFrame.transform.skewY + TransformUtil.formatRadian(frame.transform.skewY - prevFrame.transform.skewY); + } + } + + prevFrame = frame; + } + timeline.transformed = true; + } + } + + public static function getTimelineTransform(timeline:TransformTimeline, position:Number, retult:DBTransform):void + { + var frameList:Vector. = timeline.frameList; + var i:int = frameList.length; + + var currentFrame:TransformFrame; + var tweenEasing:Number; + var progress:Number; + var nextFrame:TransformFrame; + while(i --) + { + currentFrame = frameList[i] as TransformFrame; + if(currentFrame.position <= position && currentFrame.position + currentFrame.duration > position) + { + tweenEasing = currentFrame.tweenEasing; + if(i == frameList.length - 1 || isNaN(tweenEasing) || position == currentFrame.position) + { + retult.copy(currentFrame.global); + } + else + { + progress = (position - currentFrame.position) / currentFrame.duration; + if(tweenEasing) + { + progress = TimelineState.getEaseValue(progress, tweenEasing); + } + + nextFrame = timeline.frameList[i + 1] as TransformFrame; + + retult.x = currentFrame.global.x + (nextFrame.global.x - currentFrame.global.x) * progress; + retult.y = currentFrame.global.y + (nextFrame.global.y - currentFrame.global.y) * progress; + retult.skewX = TransformUtil.formatRadian(currentFrame.global.skewX + (nextFrame.global.skewX - currentFrame.global.skewX) * progress); + retult.skewY = TransformUtil.formatRadian(currentFrame.global.skewY + (nextFrame.global.skewY - currentFrame.global.skewY) * progress); + retult.scaleX = currentFrame.global.scaleX + (nextFrame.global.scaleX - currentFrame.global.scaleX) * progress; + retult.scaleY = currentFrame.global.scaleY + (nextFrame.global.scaleY - currentFrame.global.scaleY) * progress; + } + break; + } + } + } + + public static function addHideTimeline(animationData:AnimationData, armatureData:ArmatureData):void + { + var boneDataList:Vector. =armatureData.boneDataList; + var i:int = boneDataList.length; + + var boneData:BoneData; + var boneName:String; + while(i --) + { + boneData = boneDataList[i]; + boneName = boneData.name; + if(!animationData.getTimeline(boneName)) + { + animationData.addTimeline(TransformTimeline.HIDE_TIMELINE, boneName); + } + } + } + } +} \ No newline at end of file diff --git a/src/dragonBones/utils/TransformUtil.as b/src/dragonBones/utils/TransformUtil.as new file mode 100644 index 0000000..c8239b6 --- /dev/null +++ b/src/dragonBones/utils/TransformUtil.as @@ -0,0 +1,55 @@ +package dragonBones.utils +{ + import dragonBones.objects.DBTransform; + + import flash.geom.Matrix; + + /** @private */ + final public class TransformUtil + { + private static const HALF_PI:Number = Math.PI * 0.5; + private static const DOUBLE_PI:Number = Math.PI * 2; + + private static const _helpMatrix:Matrix = new Matrix(); + + public static function transformPointWithParent(transform:DBTransform, parent:DBTransform):void + { + transformToMatrix(parent, _helpMatrix); + _helpMatrix.invert(); + + var x:Number = transform.x; + var y:Number = transform.y; + + transform.x = _helpMatrix.a * x + _helpMatrix.c * y + _helpMatrix.tx; + transform.y = _helpMatrix.d * y + _helpMatrix.b * x + _helpMatrix.ty; + + transform.skewX = formatRadian(transform.skewX - parent.skewX); + transform.skewY = formatRadian(transform.skewY - parent.skewY); + } + + public static function transformToMatrix(transform:DBTransform, matrix:Matrix):void + { + matrix.a = transform.scaleX * Math.cos(transform.skewY) + matrix.b = transform.scaleX * Math.sin(transform.skewY) + matrix.c = -transform.scaleY * Math.sin(transform.skewX); + matrix.d = transform.scaleY * Math.cos(transform.skewX); + matrix.tx = transform.x; + matrix.ty = transform.y; + } + + public static function formatRadian(radian:Number):Number + { + radian %= DOUBLE_PI; + if (radian > Math.PI) + { + radian -= DOUBLE_PI; + } + if (radian < -Math.PI) + { + radian += DOUBLE_PI; + } + return radian; + } + } + +} \ No newline at end of file diff --git a/src/dragonBones/utils/TransformUtils.as b/src/dragonBones/utils/TransformUtils.as deleted file mode 100644 index 6642855..0000000 --- a/src/dragonBones/utils/TransformUtils.as +++ /dev/null @@ -1,107 +0,0 @@ -package dragonBones.utils -{ - - import dragonBones.objects.BoneTransform; - import flash.geom.ColorTransform; - import flash.geom.Matrix; - import flash.geom.Point; - - /** @private */ - public class TransformUtils - { - private static const DOUBLE_PI:Number = Math.PI * 2; - private static var _helpMatrix:Matrix = new Matrix(); - private static var _helpPoint:Point = new Point(); - - public static function transformPointWithParent(bone:BoneTransform, parent:BoneTransform):void - { - nodeToMatrix(parent, _helpMatrix); - _helpPoint.x = bone.x; - _helpPoint.y = bone.y; - _helpMatrix.invert(); - _helpPoint = _helpMatrix.transformPoint(_helpPoint); - bone.x = _helpPoint.x; - bone.y = _helpPoint.y; - bone.skewX -= parent.skewX; - bone.skewY -= parent.skewY; - } - - public static function nodeToMatrix(node:BoneTransform, matrix:Matrix):void - { - matrix.a = node.scaleX * Math.cos(node.skewY) - matrix.b = node.scaleX * Math.sin(node.skewY) - matrix.c = -node.scaleY * Math.sin(node.skewX); - matrix.d = node.scaleY * Math.cos(node.skewX); - matrix.tx = node.x; - matrix.ty = node.y; - } - - public static function setOffSetColorTransform(from:ColorTransform, to:ColorTransform, offSet:ColorTransform):void - { - offSet.alphaOffset = to.alphaOffset - from.alphaOffset; - offSet.redOffset = to.redOffset - from.redOffset; - offSet.greenOffset = to.greenOffset - from.greenOffset; - offSet.blueOffset = to.blueOffset - from.blueOffset; - offSet.alphaMultiplier = to.alphaMultiplier - from.alphaMultiplier; - offSet.redMultiplier = to.redMultiplier - from.redMultiplier; - offSet.greenMultiplier = to.greenMultiplier - from.greenMultiplier; - offSet.blueMultiplier = to.blueMultiplier - from.blueMultiplier; - } - - public static function setTweenColorTransform(current:ColorTransform, offSet:ColorTransform, tween:ColorTransform, progress:Number):void - { - tween.alphaOffset = current.alphaOffset + progress * offSet.alphaOffset; - tween.redOffset = current.redOffset + progress * offSet.redOffset; - tween.greenOffset = current.greenOffset + progress * offSet.greenOffset; - tween.blueOffset = current.blueOffset + progress * offSet.blueOffset; - tween.alphaMultiplier = current.alphaMultiplier + progress * offSet.alphaMultiplier; - tween.redMultiplier = current.redMultiplier + progress * offSet.redMultiplier; - tween.greenMultiplier = current.greenMultiplier + progress * offSet.greenMultiplier; - tween.blueMultiplier = current.blueMultiplier + progress * offSet.blueMultiplier; - } - - public static function setOffSetNode(from:BoneTransform, to:BoneTransform, offSet:BoneTransform, tweenRotate:int = 0):void - { - offSet.x = to.x - from.x; - offSet.y = to.y - from.y; - offSet.skewX = to.skewX - from.skewX; - offSet.skewY = to.skewY - from.skewY; - offSet.scaleX = to.scaleX - from.scaleX; - offSet.scaleY = to.scaleY - from.scaleY; - offSet.pivotX = to.pivotX - from.pivotX; - offSet.pivotY = to.pivotY - from.pivotY; - - offSet.skewX %= DOUBLE_PI; - if (offSet.skewX > Math.PI) - { - offSet.skewX -= DOUBLE_PI; - } - if (offSet.skewX < -Math.PI) - { - offSet.skewX += DOUBLE_PI; - } - - offSet.skewY %= DOUBLE_PI; - if (offSet.skewY > Math.PI) - { - offSet.skewY -= DOUBLE_PI; - } - if (offSet.skewY < -Math.PI) - { - offSet.skewY += DOUBLE_PI; - } - - if (tweenRotate) - { - offSet.skewX += tweenRotate * DOUBLE_PI; - offSet.skewY += tweenRotate * DOUBLE_PI; - } - } - - public static function setTweenNode(current:BoneTransform, offSet:BoneTransform, tween:BoneTransform, progress:Number):void - { - tween.setValues(current.x + progress * offSet.x, current.y + progress * offSet.y, current.skewX + progress * offSet.skewX, current.skewY + progress * offSet.skewY, current.scaleX + progress * offSet.scaleX, current.scaleY + progress * offSet.scaleY, current.pivotX + progress * offSet.pivotX, current.pivotY + progress * offSet.pivotY, tween.z); - } - } - -} \ No newline at end of file diff --git a/src/dragonBones/utils/checkBytesTailisXML.as b/src/dragonBones/utils/checkBytesTailisXML.as new file mode 100644 index 0000000..0edeb69 --- /dev/null +++ b/src/dragonBones/utils/checkBytesTailisXML.as @@ -0,0 +1,51 @@ +package dragonBones.utils +{ + import flash.utils.ByteArray; + + public function checkBytesTailisXML(bytes:ByteArray):Boolean + { + var offset:int = bytes.length; + + var count1:int = 20; + while(count1 --) + { + if(offset --) + { + switch(bytes[offset]) + { + case charCodes[" "]: + case charCodes["\t"]: + case charCodes["\r"]: + case charCodes["\n"]: + // + break; + case charCodes[">"]: + var count2:int = 20; + while(count2 --) + { + if(offset --) + { + if(bytes[offset] == charCodes["<"]) + { + return true; + } + } + else + { + break; + } + } + return false; + break; + } + } + } + return false; + } +} + +const charCodes:Object = new Object(); +for each(var c:String in " \t\r\n<>".split("")) +{ + charCodes[c] = c.charCodeAt(0); +} \ No newline at end of file diff --git a/src/dragonBones/utils/parseOldXMLData.as b/src/dragonBones/utils/parseOldXMLData.as new file mode 100644 index 0000000..0bba45d --- /dev/null +++ b/src/dragonBones/utils/parseOldXMLData.as @@ -0,0 +1,356 @@ +package dragonBones.utils +{ + import dragonBones.objects.SkeletonData; + import dragonBones.objects.ArmatureData; + + public function parseOldXMLData(rawData:XML):SkeletonData + { + var frameRate:uint = int(rawData.@[A_FRAME_RATE]); + + var data:SkeletonData = new SkeletonData(); + data.name = rawData.@[A_NAME]; + + for each(var armatureXML:XML in rawData[ARMATURES][ARMATURE]) + { + data.addArmatureData(parseArmatureData(armatureXML, data)); + } + + for each(var animationsXML:XML in rawData[ANIMATIONS][ANIMATION]) + { + var armatureData:ArmatureData = data.getArmatureData(animationsXML.@[A_NAME]); + if(armatureData) + { + for each(var animationXML:XML in animationsXML[MOVEMENT]) + { + armatureData.addAnimationData(parseAnimationData(animationXML, armatureData, frameRate)); + } + } + } + + return data; + } +} + +import dragonBones.objects.AnimationData; +import dragonBones.objects.ArmatureData; +import dragonBones.objects.BoneData; +import dragonBones.objects.DBTransform; +import dragonBones.objects.DisplayData; +import dragonBones.objects.Frame; +import dragonBones.objects.SkeletonData; +import dragonBones.objects.SkinData; +import dragonBones.objects.SlotData; +import dragonBones.objects.Timeline; +import dragonBones.objects.TransformFrame; +import dragonBones.objects.TransformTimeline; +import dragonBones.utils.ConstValues; +import dragonBones.utils.DBDataUtil; + +import flash.geom.ColorTransform; +import flash.geom.Point; + +const ARMATURES:String = "armatures"; +const ANIMATIONS:String = "animations"; +const ARMATURE:String = "armature"; +const BONE:String = "b"; +const DISPLAY:String = "d"; +const ANIMATION:String = "animation"; +const MOVEMENT:String = "mov"; +const FRAME:String = "f"; +const COLOR_TRANSFORM:String = "colorTransform"; + +const A_VERSION:String = "version"; +const A_FRAME_RATE:String = "frameRate"; +const A_NAME:String = "name"; +const A_PARENT:String = "parent"; +const A_TYPE:String = "isArmature"; +const A_DURATION:String = "dr"; +const A_FADE_IN_TIME:String = "to"; +const A_DURATION_TWEEN:String = "drTW"; +const A_LOOP:String = "lp"; +const A_SCALE:String = "sc"; +const A_OFFSET:String = "dl"; +const A_EVENT:String = "evt"; +const A_SOUND:String = "sd"; +const A_TWEEN_EASING:String = "twE"; +const A_TWEEN_ROTATE:String = "twR"; +const A_ACTION:String = "mov"; +const A_VISIBLE:String = "visible"; +const A_DISPLAY_INDEX:String = "dI"; +const A_Z_ORDER:String = "z"; +const A_X:String = "x"; +const A_Y:String = "y"; +const A_SKEW_X:String = "kX"; +const A_SKEW_Y:String = "kY"; +const A_SCALE_X:String = "cX"; +const A_SCALE_Y:String = "cY"; +const A_PIVOT_X:String = "pX"; +const A_PIVOT_Y:String = "pY"; + +const A_ALPHA_OFFSET:String = "a"; +const A_RED_OFFSET:String = "r"; +const A_GREEN_OFFSET:String = "g"; +const A_BLUE_OFFSET:String = "b"; +const A_ALPHA_MULTIPLIER:String = "aM"; +const A_RED_MULTIPLIER:String = "rM"; +const A_GREEN_MULTIPLIER:String = "gM"; +const A_BLUE_MULTIPLIER:String = "bM"; + +function parseArmatureData(armatureXML:XML, data:SkeletonData):ArmatureData +{ + var armatureData:ArmatureData = new ArmatureData(); + armatureData.name = armatureXML.@[A_NAME]; + + for each(var boneXML:XML in armatureXML[BONE]) + { + armatureData.addBoneData(parseBoneData(boneXML)); + } + + armatureData.addSkinData(parseSkinData(armatureXML, data)); + + DBDataUtil.transformArmatureData(armatureData); + armatureData.sortBoneDataList(); + return armatureData; +} + +function parseBoneData(boneXML:XML):BoneData +{ + var boneData:BoneData = new BoneData(); + boneData.name = boneXML.@[A_NAME]; + boneData.parent = boneXML.@[A_PARENT]; + + parseTransform(boneXML, boneData.global); + boneData.transform.copy(boneData.global); + + return boneData; +} + +function parseSkinData(armatureXML:XML, data:SkeletonData):SkinData +{ + var skinData:SkinData = new SkinData(); + //skinData.name + for each(var boneXML:XML in armatureXML[BONE]) + { + skinData.addSlotData(parseSlotData(boneXML, data)); + } + + return skinData; +} + +function parseSlotData(boneXML:XML, data:SkeletonData):SlotData +{ + var slotData:SlotData = new SlotData(); + slotData.name = boneXML.@[A_NAME]; + slotData.parent = slotData.name; + slotData.zOrder = boneXML.@[A_Z_ORDER]; + + for each(var displayXML:XML in boneXML[DISPLAY]) + { + var displayData:DisplayData = parseDisplayData(displayXML, data); + slotData.addDisplayData(displayData); + } + + return slotData; +} + +function parseDisplayData(displayXML:XML, data:SkeletonData):DisplayData +{ + var displayData:DisplayData = new DisplayData(); + displayData.name = displayXML.@[A_NAME]; + if(uint(displayXML.@[A_TYPE]) == 1) + { + displayData.type = DisplayData.ARMATURE; + } + else + { + displayData.type = DisplayData.IMAGE; + } + + // + //displayData.transform.x = -Number(frameXML.@[A_PIVOT_X]); + //displayData.transform.y = -Number(frameXML.@[A_PIVOT_Y]); + displayData.transform.x = NaN; + displayData.transform.y = NaN; + displayData.transform.skewX = 0; + displayData.transform.skewY = 0; + displayData.transform.scaleX = 1; + displayData.transform.scaleY = 1; + + displayData.pivot = data.addSubTexturePivot( + Number(displayXML.@[A_PIVOT_X]), + Number(displayXML.@[A_PIVOT_Y]), + displayData.name + ); + + return displayData; +} + +function parseAnimationData(animationXML:XML, armatureData:ArmatureData, frameRate:uint):AnimationData +{ + var animationData:AnimationData = new AnimationData(); + animationData.name = animationXML.@[A_NAME]; + animationData.frameRate = frameRate; + animationData.loop = uint(animationXML.@[A_LOOP]) == 1?0:1; + animationData.fadeInTime = uint(animationXML.@[A_FADE_IN_TIME]) / frameRate; + animationData.duration = uint(animationXML.@[A_DURATION]) / frameRate; + var durationTween:Number = Number(animationXML.@[A_DURATION_TWEEN][0]); + if(isNaN(durationTween)) + { + animationData.scale = 1; + } + else + { + animationData.scale = durationTween / frameRate / animationData.duration; + } + animationData.tweenEasing = Number(animationXML.@[A_TWEEN_EASING][0]); + + parseTimeline(animationXML, animationData, parseMainFrame, frameRate); + + var skinData:SkinData = armatureData.skinDataList[0]; + var slotData:SlotData; + + var timeline:TransformTimeline; + var timelineName:String; + for each(var timelineXML:XML in animationXML[BONE]) + { + timeline = parseTransformTimeline(timelineXML, animationData.duration, frameRate); + timelineName = timelineXML.@[A_NAME]; + animationData.addTimeline(timeline, timelineName); + if(skinData) + { + slotData = skinData.getSlotData(timelineName); + formatDisplayTransformXYAndTimelinePivot(slotData, timeline); + } + } + + DBDataUtil.addHideTimeline(animationData, armatureData); + DBDataUtil.transformAnimationData(animationData, armatureData); + + return animationData; +} + + +function parseTimeline(timelineXML:XML, timeline:Timeline, frameParser:Function, frameRate:uint):void +{ + var position:Number = 0; + var frame:Frame; + for each(var frameXML:XML in timelineXML[FRAME]) + { + frame = frameParser(frameXML, frameRate); + frame.position = position; + timeline.addFrame(frame); + position += frame.duration; + } + if(frame) + { + frame.duration = timeline.duration - frame.position; + } +} + +function parseTransformTimeline(timelineXML:XML, duration:Number, frameRate:uint):TransformTimeline +{ + var timeline:TransformTimeline = new TransformTimeline(); + timeline.duration = duration; + + parseTimeline(timelineXML, timeline, parseTransformFrame, frameRate); + + timeline.scale = Number(timelineXML.@[A_SCALE]); + timeline.offset = (1 - Number(timelineXML.@[A_OFFSET])) % 1; + + return timeline; +} + +function parseFrame(frameXML:XML, frame:Frame, frameRate:uint):void +{ + frame.duration = uint(frameXML.@[A_DURATION]) / frameRate; + frame.action = frameXML.@[A_ACTION]; + frame.event = frameXML.@[A_EVENT]; + frame.sound = frameXML.@[A_SOUND]; +} + +function parseMainFrame(frameXML:XML, frameRate:uint):Frame +{ + var frame:Frame = new Frame(); + parseFrame(frameXML, frame, frameRate); + return frame; +} + +function parseTransformFrame(frameXML:XML, frameRate:uint):TransformFrame +{ + var frame:TransformFrame = new TransformFrame(); + parseFrame(frameXML, frame, frameRate); + + frame.visible = frameXML.@[A_VISIBLE][0]?uint(frameXML.@[A_VISIBLE]) == 1:true; + frame.tweenEasing = Number(frameXML.@[A_TWEEN_EASING]); + frame.tweenRotate = int(frameXML.@[A_TWEEN_ROTATE]); + frame.displayIndex = int(frameXML.@[A_DISPLAY_INDEX]); + frame.zOrder = int(frameXML.@[A_Z_ORDER]); + + parseTransform(frameXML, frame.global, frame.pivot); + frame.transform.copy(frame.global); + + frame.pivot.x *= -1; + frame.pivot.y *= -1; + + var colorTransformXML:XML = frameXML[COLOR_TRANSFORM][0]; + if(colorTransformXML) + { + frame.color = new ColorTransform(); + frame.color.alphaOffset = int(colorTransformXML.@[A_ALPHA_OFFSET]); + frame.color.redOffset = int(colorTransformXML.@[A_RED_OFFSET]); + frame.color.greenOffset = int(colorTransformXML.@[A_GREEN_OFFSET]); + frame.color.blueOffset = int(colorTransformXML.@[A_BLUE_OFFSET]); + + frame.color.alphaMultiplier = int(colorTransformXML.@[A_ALPHA_MULTIPLIER]) * 0.01; + frame.color.redMultiplier = int(colorTransformXML.@[A_RED_MULTIPLIER]) * 0.01; + frame.color.greenMultiplier = int(colorTransformXML.@[A_GREEN_MULTIPLIER]) * 0.01; + frame.color.blueMultiplier = int(colorTransformXML.@[A_BLUE_MULTIPLIER]) * 0.01; + } + + return frame; +} + +function parseTransform(transformXML:XML, transform:DBTransform, pivot:Point = null):void +{ + if(transformXML) + { + if(transform) + { + transform.x = Number(transformXML.@[A_X]); + transform.y = Number(transformXML.@[A_Y]); + transform.skewX = Number(transformXML.@[A_SKEW_X]) * ConstValues.ANGLE_TO_RADIAN; + transform.skewY = Number(transformXML.@[A_SKEW_Y]) * ConstValues.ANGLE_TO_RADIAN; + transform.scaleX = Number(transformXML.@[A_SCALE_X]); + transform.scaleY = Number(transformXML.@[A_SCALE_Y]); + } + if(pivot) + { + pivot.x = Number(transformXML.@[A_PIVOT_X]); + pivot.y = Number(transformXML.@[A_PIVOT_Y]); + } + } +} + +function formatDisplayTransformXYAndTimelinePivot(slotData:SlotData, timeline:TransformTimeline):void +{ + if(!slotData) + { + return; + } + + var displayData:DisplayData; + for each(var frame:TransformFrame in timeline.frameList) + { + if(frame.displayIndex >= 0) + { + displayData = slotData.displayDataList[frame.displayIndex]; + if(isNaN(displayData.transform.x)) + { + displayData.transform.x = frame.pivot.x; + displayData.transform.y = frame.pivot.y; + } + frame.pivot.x -= displayData.transform.x; + frame.pivot.y -= displayData.transform.y; + } + } +} \ No newline at end of file