diff --git a/spine-csharp/src/Animation.cs b/spine-csharp/src/Animation.cs index 1af9614e4..3087dc60b 100644 --- a/spine-csharp/src/Animation.cs +++ b/spine-csharp/src/Animation.cs @@ -176,7 +176,7 @@ namespace Spine { } public enum Property { - Rotate = 0, X, Y, ScaleX, ScaleY, ShearX, ShearY, // + Rotate = 0, X, Y, ScaleX, ScaleY, ShearX, ShearY, Inherit, // RGB, Alpha, RGB2, // Attachment, Deform, // Event, DrawOrder, // @@ -980,6 +980,53 @@ namespace Spine { } } + /// Changes a bone's . + + public class InheritTimeline : Timeline, IBoneTimeline { + public const int ENTRIES = 2; + public const int INHERIT = 1; + + readonly int boneIndex; + + public InheritTimeline (int frameCount, int boneIndex) + : base(frameCount, (int)Property.Inherit + "|" + boneIndex) { + this.boneIndex = boneIndex; + } + + public int BoneIndex { + get { + return boneIndex; + } + } + + public override int FrameEntries { + get { return ENTRIES; } + } + + /// Sets the transform mode for the specified frame. + /// Between 0 and frameCount, inclusive. + /// The frame time in seconds. + public void SetFrame (int frame, float time, Inherit inherit) { + frame *= ENTRIES; + frames[frame] = time; + frames[frame + INHERIT] = (int)inherit; + } + + override public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList firedEvents, float alpha, MixBlend blend, + MixDirection direction) { + + Bone bone = skeleton.bones.Items[boneIndex]; + if (!bone.active) return; + + float[] frames = this.frames; + if (time < frames[0]) { + if (blend == MixBlend.Setup || blend == MixBlend.First) bone.inherit = bone.data.inherit; + return; + } + bone.inherit = InheritEnum.Values[(int)frames[Search(frames, time, ENTRIES) + INHERIT]]; + } + } + /// Changes a slot's . public class RGBATimeline : CurveTimeline, ISlotTimeline { public const int ENTRIES = 5; diff --git a/spine-csharp/src/Bone.cs b/spine-csharp/src/Bone.cs index f35fb0cd2..c090e706f 100644 --- a/spine-csharp/src/Bone.cs +++ b/spine-csharp/src/Bone.cs @@ -52,6 +52,7 @@ namespace Spine { internal float a, b, worldX; internal float c, d, worldY; + internal Inherit inherit; internal bool sorted, active; @@ -79,6 +80,9 @@ namespace Spine { /// The local shearY. public float ShearY { get { return shearY; } set { shearY = value; } } + /// Controls how parent world transforms affect this bone. + public Inherit Inherit { get { return inherit; } set { inherit = value; } } + /// The rotation, as calculated by any constraints. public float AppliedRotation { get { return arotation; } set { arotation = value; } } @@ -147,6 +151,7 @@ namespace Spine { scaleY = bone.scaleY; shearX = bone.shearX; shearY = bone.shearY; + inherit = bone.inherit; } /// Computes the world transform using the parent bone and this bone's local applied transform. @@ -192,8 +197,8 @@ namespace Spine { worldX = pa * x + pb * y + parent.worldX; worldY = pc * x + pd * y + parent.worldY; - switch (data.transformMode) { - case TransformMode.Normal: { + switch (inherit) { + case Inherit.Normal: { float rx = (rotation + shearX) * MathUtils.DegRad; float ry = (rotation + 90 + shearY) * MathUtils.DegRad; float la = (float)Math.Cos(rx) * scaleX; @@ -206,7 +211,7 @@ namespace Spine { d = pc * lb + pd * ld; return; } - case TransformMode.OnlyTranslation: { + case Inherit.OnlyTranslation: { float rx = (rotation + shearX) * MathUtils.DegRad; float ry = (rotation + 90 + shearY) * MathUtils.DegRad; a = (float)Math.Cos(rx) * scaleX; @@ -215,7 +220,7 @@ namespace Spine { d = (float)Math.Sin(ry) * scaleY; break; } - case TransformMode.NoRotationOrReflection: { + case Inherit.NoRotationOrReflection: { float s = pa * pa + pc * pc, prx; if (s > 0.0001f) { s = Math.Abs(pa * pd - pb * pc) / s; @@ -241,8 +246,8 @@ namespace Spine { d = pc * lb + pd * ld; break; } - case TransformMode.NoScale: - case TransformMode.NoScaleOrReflection: { + case Inherit.NoScale: + case Inherit.NoScaleOrReflection: { rotation *= MathUtils.DegRad; float cos = (float)Math.Cos(rotation), sin = (float)Math.Sin(rotation); float za = (pa * cos + pb * sin) / skeleton.scaleX; @@ -252,8 +257,7 @@ namespace Spine { za *= s; zc *= s; s = (float)Math.Sqrt(za * za + zc * zc); - if (data.transformMode == TransformMode.NoScale - && (pa * pd - pb * pc < 0) != (skeleton.scaleX < 0 != skeleton.scaleY < 0)) s = -s; + if (inherit == Inherit.NoScale && (pa * pd - pb * pc < 0) != (skeleton.scaleX < 0 != skeleton.scaleY < 0)) s = -s; rotation = MathUtils.PI / 2 + MathUtils.Atan2(zc, za); float zb = (float)Math.Cos(rotation) * s; float zd = (float)Math.Sin(rotation) * s; @@ -286,6 +290,7 @@ namespace Spine { scaleY = data.scaleY; shearX = data.shearX; shearY = data.shearY; + inherit = data.inherit; } /// @@ -320,14 +325,14 @@ namespace Spine { ay = (dy * id - dx * ic); float ra, rb, rc, rd; - if (data.transformMode == TransformMode.OnlyTranslation) { + if (inherit == Inherit.OnlyTranslation) { ra = a; rb = b; rc = c; rd = d; } else { - switch (data.transformMode) { - case TransformMode.NoRotationOrReflection: { + switch (inherit) { + case Inherit.NoRotationOrReflection: { float s = Math.Abs(pa * pd - pb * pc) / (pa * pa + pc * pc); float sa = pa / skeleton.scaleX; float sc = pc / skeleton.scaleY; @@ -338,8 +343,8 @@ namespace Spine { ib = pb * pid; break; } - case TransformMode.NoScale: - case TransformMode.NoScaleOrReflection: { + case Inherit.NoScale: + case Inherit.NoScaleOrReflection: { float r = rotation * MathUtils.DegRad, cos = (float)Math.Cos(r), sin = (float)Math.Sin(r); pa = (pa * cos + pb * sin) / skeleton.scaleX; pc = (pc * cos + pd * sin) / skeleton.scaleY; @@ -348,7 +353,7 @@ namespace Spine { pa *= s; pc *= s; s = (float)Math.Sqrt(pa * pa + pc * pc); - if (data.transformMode == TransformMode.NoScale && pid < 0 != (skeleton.scaleX < 0 != skeleton.scaleY < 0)) s = -s; + if (inherit == Inherit.NoScale && pid < 0 != (skeleton.scaleX < 0 != skeleton.scaleY < 0)) s = -s; r = MathUtils.PI / 2 + MathUtils.Atan2(pc, pa); pb = (float)Math.Cos(r) * s; pd = (float)Math.Sin(r) * s; diff --git a/spine-csharp/src/BoneData.cs b/spine-csharp/src/BoneData.cs index 203643c0b..53a6c5166 100644 --- a/spine-csharp/src/BoneData.cs +++ b/spine-csharp/src/BoneData.cs @@ -36,7 +36,7 @@ namespace Spine { internal BoneData parent; internal float length; internal float x, y, rotation, scaleX = 1, scaleY = 1, shearX, shearY; - internal TransformMode transformMode = TransformMode.Normal; + internal Inherit inherit = Inherit.Normal; internal bool skinRequired; /// The index of the bone in Skeleton.Bones @@ -71,8 +71,8 @@ namespace Spine { /// Local shearY. public float ShearY { get { return shearY; } set { shearY = value; } } - /// The transform mode for how parent world transforms affect this bone. - public TransformMode TransformMode { get { return transformMode; } set { transformMode = value; } } + /// Determines how parent world transforms affect this bone. + public Inherit Inherit { get { return inherit; } set { inherit = value; } } /// When true, only updates this bone if the contains /// this bone. @@ -93,13 +93,21 @@ namespace Spine { } } - [Flags] - public enum TransformMode { - //0000 0 Flip Scale Rotation - Normal = 0, // 0000 - OnlyTranslation = 7, // 0111 - NoRotationOrReflection = 1, // 0001 - NoScale = 2, // 0010 - NoScaleOrReflection = 6, // 0110 + public enum Inherit { + Normal, + OnlyTranslation, + NoRotationOrReflection, + NoScale, + NoScaleOrReflection + } + + public class InheritEnum { + public static readonly Inherit[] Values = { + Inherit.Normal, + Inherit.OnlyTranslation, + Inherit.NoRotationOrReflection, + Inherit.NoScale, + Inherit.NoScaleOrReflection + }; } } diff --git a/spine-csharp/src/IkConstraint.cs b/spine-csharp/src/IkConstraint.cs index 94659ef55..8122208a9 100644 --- a/spine-csharp/src/IkConstraint.cs +++ b/spine-csharp/src/IkConstraint.cs @@ -175,12 +175,12 @@ namespace Spine { float rotationIK = -bone.ashearX - bone.arotation; float tx = 0, ty = 0; - switch (bone.data.transformMode) { - case TransformMode.OnlyTranslation: + switch (bone.inherit) { + case Inherit.OnlyTranslation: tx = (targetX - bone.worldX) * Math.Sign(bone.skeleton.ScaleX); ty = (targetY - bone.worldY) * Math.Sign(bone.skeleton.ScaleY); break; - case TransformMode.NoRotationOrReflection: { + case Inherit.NoRotationOrReflection: { float s = Math.Abs(pa * pd - pb * pc) / Math.Max(0.0001f, pa * pa + pc * pc); float sa = pa / bone.skeleton.scaleX; float sc = pc / bone.skeleton.scaleY; @@ -212,9 +212,9 @@ namespace Spine { float sx = bone.ascaleX, sy = bone.ascaleY; if (compress || stretch) { - switch (bone.data.transformMode) { - case TransformMode.NoScale: - case TransformMode.NoScaleOrReflection: + switch (bone.inherit) { + case Inherit.NoScale: + case Inherit.NoScaleOrReflection: tx = targetX - bone.worldX; ty = targetY - bone.worldY; break; @@ -238,6 +238,7 @@ namespace Spine { float softness, float alpha) { if (parent == null) throw new ArgumentNullException("parent", "parent cannot be null."); if (child == null) throw new ArgumentNullException("child", "child cannot be null."); + if (parent.inherit != Inherit.Normal || child.inherit != Inherit.Normal) return; float px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX; int os1, os2, s2; if (psx < 0) { diff --git a/spine-csharp/src/SkeletonBinary.cs b/spine-csharp/src/SkeletonBinary.cs index f9f0f503e..c66d0270c 100644 --- a/spine-csharp/src/SkeletonBinary.cs +++ b/spine-csharp/src/SkeletonBinary.cs @@ -53,6 +53,7 @@ namespace Spine { public const int BONE_SHEAR = 7; public const int BONE_SHEARX = 8; public const int BONE_SHEARY = 9; + public const int BONE_INHERIT = 10; public const int SLOT_ATTACHMENT = 0; public const int SLOT_RGBA = 1; @@ -118,14 +119,6 @@ namespace Spine { } #endif // WINDOWS_STOREAPP - public static readonly TransformMode[] TransformModeValues = { - TransformMode.Normal, - TransformMode.OnlyTranslation, - TransformMode.NoRotationOrReflection, - TransformMode.NoScale, - TransformMode.NoScaleOrReflection - }; - /// Returns the version string of binary skeleton data. public static string GetVersionString (Stream file) { if (file == null) throw new ArgumentNullException("file"); @@ -187,7 +180,7 @@ namespace Spine { data.shearX = input.ReadFloat(); data.shearY = input.ReadFloat(); data.Length = input.ReadFloat() * scale; - data.transformMode = TransformModeValues[input.ReadInt(true)]; + data.inherit = InheritEnum.Values[input.ReadInt(true)]; data.skinRequired = input.ReadBoolean(); if (nonessential) { // discard non-essential data input.ReadInt(); // Color.rgba8888ToColor(data.color, input.readInt()); @@ -844,7 +837,15 @@ namespace Spine { for (int i = 0, n = input.ReadInt(true); i < n; i++) { int boneIndex = input.ReadInt(true); for (int ii = 0, nn = input.ReadInt(true); ii < nn; ii++) { - int type = input.ReadUByte(), frameCount = input.ReadInt(true), bezierCount = input.ReadInt(true); + int type = input.ReadUByte(), frameCount = input.ReadInt(true); + if (type == BONE_INHERIT) { + InheritTimeline timeline = new InheritTimeline(frameCount, boneIndex); + for (int frame = 0; frame < frameCount; frame++) + timeline.SetFrame(frame, input.ReadFloat(), InheritEnum.Values[input.ReadUByte()]); + timelines.Add(timeline); + continue; + } + int bezierCount = input.ReadInt(true); switch (type) { case BONE_ROTATE: ReadTimeline(input, timelines, new RotateTimeline(frameCount, bezierCount, boneIndex), 1); diff --git a/spine-csharp/src/SkeletonJson.cs b/spine-csharp/src/SkeletonJson.cs index bd166bfb8..852e9b369 100644 --- a/spine-csharp/src/SkeletonJson.cs +++ b/spine-csharp/src/SkeletonJson.cs @@ -133,8 +133,8 @@ namespace Spine { data.shearX = GetFloat(boneMap, "shearX", 0); data.shearY = GetFloat(boneMap, "shearY", 0); - string tm = GetString(boneMap, "transform", TransformMode.Normal.ToString()); - data.transformMode = (TransformMode)Enum.Parse(typeof(TransformMode), tm, true); + string inheritString = GetString(boneMap, "inherit", Inherit.Normal.ToString()); + data.inherit = (Inherit)Enum.Parse(typeof(Inherit), inheritString, true); data.skinRequired = GetBoolean(boneMap, "skin", false); skeletonData.bones.Add(data); @@ -874,7 +874,19 @@ namespace Spine { timelines.Add(ReadTimeline(ref keyMapEnumerator, new ShearXTimeline(frames, frames, boneIndex), 0, 1)); else if (timelineName == "sheary") timelines.Add(ReadTimeline(ref keyMapEnumerator, new ShearYTimeline(frames, frames, boneIndex), 0, 1)); - else + else if (timelineName == "inherit") { + InheritTimeline timeline = new InheritTimeline(frames, boneIndex); + for (int frame = 0; ; frame++) { + Dictionary keyMap = (Dictionary)keyMapEnumerator.Current; + float time = GetFloat(keyMap, "time", 0); + Inherit inherit = (Inherit)Enum.Parse(typeof(Inherit), GetString(keyMap, "inherit", Inherit.Normal.ToString()), true); + timeline.SetFrame(frame, time, inherit); + if (!keyMapEnumerator.MoveNext()) { + break; + } + } + timelines.Add(timeline); + } else throw new Exception("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"); } } diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs index 58168f661..455f4743b 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs @@ -329,13 +329,13 @@ namespace Spine.Unity.Editor { boneTransform.parent = parentTransform; boneTransform.localPosition = new Vector3(boneData.X, boneData.Y, 0); - TransformMode tm = boneData.TransformMode; - if (tm.InheritsRotation()) + Inherit inherit = boneData.Inherit; + if (inherit.InheritsRotation()) boneTransform.localRotation = Quaternion.Euler(0, 0, boneData.Rotation); else boneTransform.rotation = Quaternion.Euler(0, 0, boneData.Rotation); - if (tm.InheritsScale()) + if (inherit.InheritsScale()) boneTransform.localScale = new Vector3(boneData.ScaleX, boneData.ScaleY, 1); } @@ -774,7 +774,7 @@ namespace Spine.Unity.Editor { } foreach (Bone b in skeleton.Bones) { - if (!b.Data.TransformMode.InheritsRotation()) { + if (!b.Data.Inherit.InheritsRotation()) { int index = b.Data.Index; if (ignoreRotateTimelineIndexes.Contains(index) == false) { ignoreRotateTimelineIndexes.Add(index); @@ -832,7 +832,7 @@ namespace Spine.Unity.Editor { static void BakeBoneConstraints (Bone bone, Spine.Animation animation, AnimationClip clip) { Skeleton skeleton = bone.Skeleton; - bool inheritRotation = bone.Data.TransformMode.InheritsRotation(); + bool inheritRotation = bone.Data.Inherit.InheritsRotation(); animation.Apply(skeleton, 0, 0, false, null, 1f, MixBlend.Setup, MixDirection.In); skeleton.UpdateWorldTransform(Skeleton.Physics.Update); diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonUtility/SkeletonUtilityBone.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonUtility/SkeletonUtilityBone.cs index 246502bef..74da6287c 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonUtility/SkeletonUtilityBone.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonUtility/SkeletonUtilityBone.cs @@ -134,7 +134,7 @@ namespace Spine.Unity { zPosition ? 0 : thisTransform.localPosition.z); if (rotation) { - if (bone.Data.TransformMode.InheritsRotation()) { + if (bone.Data.Inherit.InheritsRotation()) { thisTransform.localRotation = Quaternion.Euler(0, 0, bone.Rotation); } else { Vector3 euler = skeletonTransform.rotation.eulerAngles; @@ -154,7 +154,7 @@ namespace Spine.Unity { zPosition ? 0 : thisTransform.localPosition.z); if (rotation) { - if (bone.Data.TransformMode.InheritsRotation()) { + if (bone.Data.Inherit.InheritsRotation()) { thisTransform.localRotation = Quaternion.Euler(0, 0, bone.AppliedRotation); } else { Vector3 euler = skeletonTransform.rotation.eulerAngles; @@ -222,7 +222,7 @@ namespace Spine.Unity { } public static bool BoneTransformModeIncompatible (Bone bone) { - return !bone.Data.TransformMode.InheritsScale(); + return !bone.Data.Inherit.InheritsScale(); } public void AddBoundingBox (string skinName, string slotName, string attachmentName) { diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkeletonExtensions.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkeletonExtensions.cs index fc5f6fa55..f32ed5e40 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkeletonExtensions.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkeletonExtensions.cs @@ -325,8 +325,8 @@ namespace Spine { result.x = pa * boneData.X + pb * boneData.Y + parentMatrix.x; result.y = pc * boneData.X + pd * boneData.Y + parentMatrix.y; - switch (boneData.TransformMode) { - case TransformMode.Normal: { + switch (boneData.Inherit) { + case Inherit.Normal: { float rotationY = boneData.Rotation + 90 + boneData.ShearY; float la = MathUtils.CosDeg(boneData.Rotation + boneData.ShearX) * boneData.ScaleX; float lb = MathUtils.CosDeg(rotationY) * boneData.ScaleY; @@ -338,7 +338,7 @@ namespace Spine { result.d = pc * lb + pd * ld; break; } - case TransformMode.OnlyTranslation: { + case Inherit.OnlyTranslation: { float rotationY = boneData.Rotation + 90 + boneData.ShearY; result.a = MathUtils.CosDeg(boneData.Rotation + boneData.ShearX) * boneData.ScaleX; result.b = MathUtils.CosDeg(rotationY) * boneData.ScaleY; @@ -346,7 +346,7 @@ namespace Spine { result.d = MathUtils.SinDeg(rotationY) * boneData.ScaleY; break; } - case TransformMode.NoRotationOrReflection: { + case Inherit.NoRotationOrReflection: { float s = pa * pa + pc * pc, prx; if (s > 0.0001f) { s = Math.Abs(pa * pd - pb * pc) / s; @@ -370,8 +370,8 @@ namespace Spine { result.d = pc * lb + pd * ld; break; } - case TransformMode.NoScale: - case TransformMode.NoScaleOrReflection: { + case Inherit.NoScale: + case Inherit.NoScaleOrReflection: { float cos = MathUtils.CosDeg(boneData.Rotation), sin = MathUtils.SinDeg(boneData.Rotation); float za = pa * cos + pb * sin; float zc = pc * cos + pd * sin; @@ -388,7 +388,7 @@ namespace Spine { float lb = MathUtils.CosDeg(90 + boneData.ShearY) * boneData.ScaleY; float lc = MathUtils.SinDeg(boneData.ShearX) * boneData.ScaleX; float ld = MathUtils.SinDeg(90 + boneData.ShearY) * boneData.ScaleY; - if (boneData.TransformMode != TransformMode.NoScaleOrReflection ? pa * pd - pb * pc < 0 : false) { + if (boneData.Inherit != Inherit.NoScaleOrReflection ? pa * pd - pb * pc < 0 : false) { zb = -zb; zd = -zd; } @@ -446,15 +446,13 @@ namespace Spine { return va.Bones != null && va.Bones.Length > 0; } - #region Transform Modes - public static bool InheritsRotation (this TransformMode mode) { - const int RotationBit = 0; - return ((int)mode & (1U << RotationBit)) == 0; + #region Inherit Modes + public static bool InheritsRotation (this Inherit mode) { + return mode == Inherit.Normal || mode == Inherit.NoScale || mode == Inherit.NoScaleOrReflection; } - public static bool InheritsScale (this TransformMode mode) { - const int ScaleBit = 1; - return ((int)mode & (1U << ScaleBit)) == 0; + public static bool InheritsScale (this Inherit mode) { + return mode == Inherit.Normal || mode == Inherit.NoRotationOrReflection; } #endregion }