mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 23:34:53 +08:00
Flip timelines for spine-as3 and spine-starling.
This commit is contained in:
parent
322d8ed0ab
commit
efae035f18
@ -42,6 +42,8 @@ public class Bone {
|
||||
public var rotationIK:Number;
|
||||
public var scaleX:Number
|
||||
public var scaleY:Number;
|
||||
public var flipX:Boolean;
|
||||
public var flipY:Boolean;
|
||||
|
||||
internal var _m00:Number;
|
||||
internal var _m01:Number;
|
||||
@ -52,6 +54,8 @@ public class Bone {
|
||||
internal var _worldRotation:Number;
|
||||
internal var _worldScaleX:Number;
|
||||
internal var _worldScaleY:Number;
|
||||
internal var _worldFlipX:Boolean;
|
||||
internal var _worldFlipY:Boolean;
|
||||
|
||||
/** @param parent May be null. */
|
||||
public function Bone (data:BoneData, skeleton:Skeleton, parent:Bone) {
|
||||
@ -77,24 +81,29 @@ public class Bone {
|
||||
_worldScaleY = scaleY;
|
||||
}
|
||||
_worldRotation = _data.inheritRotation ? parent._worldRotation + rotationIK : rotationIK;
|
||||
_worldFlipX = parent._worldFlipX != flipX;
|
||||
_worldFlipY = parent._worldFlipY != flipY;
|
||||
} else {
|
||||
_worldX = _skeleton.flipX ? -x : x;
|
||||
_worldY = _skeleton.flipY != yDown ? -y : y;
|
||||
var skeletonFlipX:Boolean = _skeleton.flipX, skeletonFlipY:Boolean = _skeleton.flipY;
|
||||
_worldX = skeletonFlipX ? -x : x;
|
||||
_worldY = skeletonFlipY != yDown ? -y : y;
|
||||
_worldScaleX = scaleX;
|
||||
_worldScaleY = scaleY;
|
||||
_worldRotation = rotationIK;
|
||||
_worldFlipX = skeletonFlipX != flipX;
|
||||
_worldFlipY = skeletonFlipY != flipY;
|
||||
}
|
||||
var radians:Number = _worldRotation * (Math.PI / 180);
|
||||
var cos:Number = Math.cos(radians);
|
||||
var sin:Number = Math.sin(radians);
|
||||
if (skeleton.flipX) {
|
||||
if (_worldFlipX) {
|
||||
_m00 = -cos * _worldScaleX;
|
||||
_m01 = sin * _worldScaleY;
|
||||
} else {
|
||||
_m00 = cos * _worldScaleX;
|
||||
_m01 = -sin * _worldScaleY;
|
||||
}
|
||||
if (_skeleton.flipY != yDown) {
|
||||
if (_worldFlipY != yDown) {
|
||||
_m10 = -sin * _worldScaleX;
|
||||
_m11 = -cos * _worldScaleY;
|
||||
} else {
|
||||
@ -110,6 +119,8 @@ public class Bone {
|
||||
rotationIK = rotation;
|
||||
scaleX = _data.scaleX;
|
||||
scaleY = _data.scaleY;
|
||||
flipX = _data.flipX;
|
||||
flipY = _data.flipY;
|
||||
}
|
||||
|
||||
public function get data () : BoneData {
|
||||
@ -159,11 +170,19 @@ public class Bone {
|
||||
public function get worldScaleY () : Number {
|
||||
return _worldScaleY;
|
||||
}
|
||||
|
||||
public function get worldFlipX () : Boolean {
|
||||
return _worldFlipX;
|
||||
}
|
||||
|
||||
public function get worldFlipY () : Boolean {
|
||||
return _worldFlipY;
|
||||
}
|
||||
|
||||
public function worldToLocal (world:Vector.<Number>) : void {
|
||||
var dx:Number = world[0] - _worldX, dy:Number = world[1] - _worldY;
|
||||
var m00:Number = _m00, m10:Number = _m10, m01:Number = _m01, m11:Number = _m11;
|
||||
if (_skeleton.flipX != (_skeleton.flipY != yDown)) {
|
||||
if (_worldFlipX != (_worldFlipY != yDown)) {
|
||||
m00 = -m00;
|
||||
m11 = -m11;
|
||||
}
|
||||
|
||||
@ -41,6 +41,8 @@ public class BoneData {
|
||||
public var scaleY:Number = 1;
|
||||
public var inheritScale:Boolean = true;
|
||||
public var inheritRotation:Boolean = true;
|
||||
public var flipX:Boolean;
|
||||
public var flipY:Boolean;
|
||||
|
||||
/** @param parent May be null. */
|
||||
public function BoneData (name:String, parent:BoneData) {
|
||||
|
||||
@ -38,6 +38,8 @@ import spine.animation.CurveTimeline;
|
||||
import spine.animation.DrawOrderTimeline;
|
||||
import spine.animation.EventTimeline;
|
||||
import spine.animation.FfdTimeline;
|
||||
import spine.animation.FlipXTimeline;
|
||||
import spine.animation.FlipYTimeline;
|
||||
import spine.animation.IkConstraintTimeline;
|
||||
import spine.animation.RotateTimeline;
|
||||
import spine.animation.ScaleTimeline;
|
||||
@ -52,12 +54,6 @@ import spine.attachments.RegionAttachment;
|
||||
import spine.attachments.SkinnedMeshAttachment;
|
||||
|
||||
public class SkeletonJson {
|
||||
static public const TIMELINE_SCALE:String = "scale";
|
||||
static public const TIMELINE_ROTATE:String = "rotate";
|
||||
static public const TIMELINE_TRANSLATE:String = "translate";
|
||||
static public const TIMELINE_ATTACHMENT:String = "attachment";
|
||||
static public const TIMELINE_COLOR:String = "color";
|
||||
|
||||
public var attachmentLoader:AttachmentLoader;
|
||||
public var scale:Number = 1;
|
||||
|
||||
@ -107,6 +103,8 @@ public class SkeletonJson {
|
||||
boneData.rotation = (boneMap["rotation"] || 0);
|
||||
boneData.scaleX = boneMap.hasOwnProperty("scaleX") ? boneMap["scaleX"] : 1;
|
||||
boneData.scaleY = boneMap.hasOwnProperty("scaleY") ? boneMap["scaleY"] : 1;
|
||||
boneData.flipX = boneMap.hasOwnProperty("flipX") ? boneMap["flipX"] : false;
|
||||
boneData.flipY = boneMap.hasOwnProperty("flipY") ? boneMap["flipY"] : false;
|
||||
boneData.inheritScale = boneMap.hasOwnProperty("inheritScale") ? boneMap["inheritScale"] : true;
|
||||
boneData.inheritRotation = boneMap.hasOwnProperty("inheritRotation") ? boneMap["inheritRotation"] : true;
|
||||
skeletonData.bones[skeletonData.bones.length] = boneData;
|
||||
@ -312,7 +310,7 @@ public class SkeletonJson {
|
||||
|
||||
for (timelineName in slotMap) {
|
||||
values = slotMap[timelineName];
|
||||
if (timelineName == TIMELINE_COLOR) {
|
||||
if (timelineName == "color") {
|
||||
var colorTimeline:ColorTimeline = new ColorTimeline(values.length);
|
||||
colorTimeline.slotIndex = slotIndex;
|
||||
|
||||
@ -330,7 +328,7 @@ public class SkeletonJson {
|
||||
timelines[timelines.length] = colorTimeline;
|
||||
duration = Math.max(duration, colorTimeline.frames[colorTimeline.frameCount * 5 - 5]);
|
||||
|
||||
} else if (timelineName == TIMELINE_ATTACHMENT) {
|
||||
} else if (timelineName == "attachment") {
|
||||
var attachmentTimeline:AttachmentTimeline = new AttachmentTimeline(values.length);
|
||||
attachmentTimeline.slotIndex = slotIndex;
|
||||
|
||||
@ -339,7 +337,7 @@ public class SkeletonJson {
|
||||
attachmentTimeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]);
|
||||
timelines[timelines.length] = attachmentTimeline;
|
||||
duration = Math.max(duration, attachmentTimeline.frames[attachmentTimeline.frameCount - 1]);
|
||||
|
||||
|
||||
} else
|
||||
throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")");
|
||||
}
|
||||
@ -353,7 +351,7 @@ public class SkeletonJson {
|
||||
|
||||
for (timelineName in boneMap) {
|
||||
values = boneMap[timelineName];
|
||||
if (timelineName == TIMELINE_ROTATE) {
|
||||
if (timelineName == "rotate") {
|
||||
var rotateTimeline:RotateTimeline = new RotateTimeline(values.length);
|
||||
rotateTimeline.boneIndex = boneIndex;
|
||||
|
||||
@ -366,10 +364,10 @@ public class SkeletonJson {
|
||||
timelines[timelines.length] = rotateTimeline;
|
||||
duration = Math.max(duration, rotateTimeline.frames[rotateTimeline.frameCount * 2 - 2]);
|
||||
|
||||
} else if (timelineName == TIMELINE_TRANSLATE || timelineName == TIMELINE_SCALE) {
|
||||
} else if (timelineName == "translate" || timelineName == "scale") {
|
||||
var timeline:TranslateTimeline;
|
||||
var timelineScale:Number = 1;
|
||||
if (timelineName == TIMELINE_SCALE)
|
||||
if (timelineName == "scale")
|
||||
timeline = new ScaleTimeline(values.length);
|
||||
else {
|
||||
timeline = new TranslateTimeline(values.length);
|
||||
@ -388,6 +386,20 @@ public class SkeletonJson {
|
||||
timelines[timelines.length] = timeline;
|
||||
duration = Math.max(duration, timeline.frames[timeline.frameCount * 3 - 3]);
|
||||
|
||||
} else if (timelineName == "flipX" || timelineName == "flipY") {
|
||||
var flipX:Boolean = timelineName == "flipX";
|
||||
var flipTimeline:FlipXTimeline = flipX ? new FlipXTimeline(values.length) : new FlipYTimeline(values.length);
|
||||
flipTimeline.boneIndex = boneIndex;
|
||||
|
||||
var field:String = flipX ? "x" : "y";
|
||||
frameIndex = 0;
|
||||
for each (valueMap in values) {
|
||||
flipTimeline.setFrame(frameIndex, valueMap["time"], valueMap.hasOwnProperty(field) ? valueMap[field] : false);
|
||||
frameIndex++;
|
||||
}
|
||||
timelines[timelines.length] = flipTimeline;
|
||||
duration = Math.max(duration, flipTimeline.frames[flipTimeline.frameCount * 3 - 3]);
|
||||
|
||||
} else
|
||||
throw new Error("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
|
||||
}
|
||||
|
||||
73
spine-as3/spine-as3/src/spine/animation/FlipXTimeline.as
Normal file
73
spine-as3/spine-as3/src/spine/animation/FlipXTimeline.as
Normal file
@ -0,0 +1,73 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes Software License
|
||||
* Version 2.1
|
||||
*
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* You are granted a perpetual, non-exclusive, non-sublicensable and
|
||||
* non-transferable license to install, execute and perform the Spine Runtimes
|
||||
* Software (the "Software") solely for internal use. Without the written
|
||||
* permission of Esoteric Software (typically granted by licensing Spine), you
|
||||
* may not (a) modify, translate, adapt or otherwise create derivative works,
|
||||
* improvements of the Software or develop new applications using the Software
|
||||
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
|
||||
* trademark, patent or other intellectual property or proprietary rights
|
||||
* notices on or in the Software, including any copy thereof. Redistributions
|
||||
* in binary or source form must include this license and terms.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation {
|
||||
import spine.Bone;
|
||||
import spine.Event;
|
||||
import spine.Skeleton;
|
||||
|
||||
public class FlipXTimeline implements Timeline {
|
||||
public var boneIndex:int;
|
||||
public var frames:Vector.<Number>; // time, flip, ...
|
||||
|
||||
public function FlipXTimeline (frameCount:int) {
|
||||
frames = new Vector.<Number>(frameCount * 2, true);
|
||||
}
|
||||
|
||||
public function get frameCount () : int {
|
||||
return frames.length / 2;
|
||||
}
|
||||
|
||||
/** Sets the time and angle of the specified keyframe. */
|
||||
public function setFrame (frameIndex:int, time:Number, flip:Boolean) : void {
|
||||
frameIndex *= 2;
|
||||
frames[frameIndex] = time;
|
||||
frames[int(frameIndex + 1)] = flip ? 1 : 0;
|
||||
}
|
||||
|
||||
public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
|
||||
if (time < frames[0]) {
|
||||
if (lastTime > time) apply(skeleton, lastTime, int.MAX_VALUE, null, 0);
|
||||
return;
|
||||
} else if (lastTime > time) //
|
||||
lastTime = -1;
|
||||
|
||||
var frameIndex:int = (time >= frames[frames.length - 2] ? frames.length : Animation.binarySearch(frames, time, 2)) - 2;
|
||||
if (frames[frameIndex] < lastTime) return;
|
||||
|
||||
setFlip(skeleton.bones[boneIndex], frames[frameIndex + 1] != 0);
|
||||
}
|
||||
|
||||
protected function setFlip (bone:Bone, flip:Boolean) : void {
|
||||
bone.flipX = flip;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
44
spine-as3/spine-as3/src/spine/animation/FlipYTimeline.as
Normal file
44
spine-as3/spine-as3/src/spine/animation/FlipYTimeline.as
Normal file
@ -0,0 +1,44 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes Software License
|
||||
* Version 2.1
|
||||
*
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* You are granted a perpetual, non-exclusive, non-sublicensable and
|
||||
* non-transferable license to install, execute and perform the Spine Runtimes
|
||||
* Software (the "Software") solely for internal use. Without the written
|
||||
* permission of Esoteric Software (typically granted by licensing Spine), you
|
||||
* may not (a) modify, translate, adapt or otherwise create derivative works,
|
||||
* improvements of the Software or develop new applications using the Software
|
||||
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
|
||||
* trademark, patent or other intellectual property or proprietary rights
|
||||
* notices on or in the Software, including any copy thereof. Redistributions
|
||||
* in binary or source form must include this license and terms.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
package spine.animation {
|
||||
import spine.Bone;
|
||||
|
||||
public class FlipYTimeline extends FlipXTimeline {
|
||||
public function FlipYTimeline (frameCount:int) {
|
||||
super(frameCount);
|
||||
}
|
||||
|
||||
override protected function setFlip (bone:Bone, flip:Boolean) : void {
|
||||
bone.flipY = flip;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -97,6 +97,7 @@ public class SkeletonSprite extends Sprite {
|
||||
bitmap.rotation = -regionAttachment.rotation;
|
||||
bitmap.scaleX = regionAttachment.scaleX * (regionAttachment.width / region.width);
|
||||
bitmap.scaleY = regionAttachment.scaleY * (regionAttachment.height / region.height);
|
||||
|
||||
|
||||
// Position using attachment translation, shifted as if scale and rotation were at image center.
|
||||
var radians:Number = -regionAttachment.rotation * Math.PI / 180;
|
||||
@ -127,10 +128,12 @@ public class SkeletonSprite extends Sprite {
|
||||
colorTransform.alphaMultiplier = skeleton.a * slot.a * regionAttachment.a;
|
||||
wrapper.transform.colorTransform = colorTransform;
|
||||
|
||||
var bone:Bone = slot.bone;
|
||||
var flipX:int = skeleton.flipX ? -1 : 1;
|
||||
var flipY:int = skeleton.flipY ? -1 : 1;
|
||||
if (bone.worldFlipX) flipX = -flipX;
|
||||
if (bone.worldFlipY) flipY = -flipY;
|
||||
|
||||
var bone:Bone = slot.bone;
|
||||
wrapper.x = bone.worldX;
|
||||
wrapper.y = bone.worldY;
|
||||
wrapper.rotation = -bone.worldRotation * flipX * flipY;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user