Browse Source

[csharp] Port of commit f4f22cd. Added bone transform inheritance timeline. Renamed TransformMode to Inherit.

Harald Csaszar 1 year ago
parent
commit
e630d1bda7

+ 48 - 1
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 {
 		}
 	}
 
+	/// <summary>Changes a bone's <see cref="Bone.Inherit"/>.</summary>
+
+	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; }
+		}
+
+		/// <summary>Sets the transform mode for the specified frame.</summary>
+		/// <param name="frame">Between 0 and <code>frameCount</code>, inclusive.</param>
+		/// <param name="time">The frame time in seconds.</param>
+		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<Event> 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]];
+		}
+	}
+
 	/// <summary>Changes a slot's <see cref="Slot.Color"/>.</summary>
 	public class RGBATimeline : CurveTimeline, ISlotTimeline {
 		public const int ENTRIES = 5;

+ 19 - 14
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 {
 		/// <summary>The local shearY.</summary>
 		public float ShearY { get { return shearY; } set { shearY = value; } }
 
+		/// <summary>Controls how parent world transforms affect this bone.</summary>
+		public Inherit Inherit { get { return inherit; } set { inherit = value; } }
+
 		/// <summary>The rotation, as calculated by any constraints.</summary>
 		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;
 		}
 
 		/// <summary>Computes the world transform using the parent bone and this bone's local applied transform.</summary>
@@ -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;
 		}
 
 		/// <summary>
@@ -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;

+ 19 - 11
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;
 
 		/// <summary>The index of the bone in Skeleton.Bones</summary>
@@ -71,8 +71,8 @@ namespace Spine {
 		/// <summary>Local shearY.</summary>
 		public float ShearY { get { return shearY; } set { shearY = value; } }
 
-		/// <summary>The transform mode for how parent world transforms affect this bone.</summary>
-		public TransformMode TransformMode { get { return transformMode; } set { transformMode = value; } }
+		/// <summary>Determines how parent world transforms affect this bone.</summary>
+		public Inherit Inherit { get { return inherit; } set { inherit = value; } }
 
 		/// <summary>When true, <see cref="Skeleton.UpdateWorldTransform(Skeleton.Physics)"/> only updates this bone if the <see cref="Skeleton.Skin"/> contains
 		/// this bone.</summary>
@@ -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
+		};
 	}
 }

+ 7 - 6
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) {

+ 11 - 10
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
-		};
-
 		/// <summary>Returns the version string of binary skeleton data.</summary>
 		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);

+ 15 - 3
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<string, object> keyMap = (Dictionary<string, Object>)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 + ")");
 					}
 				}

+ 5 - 5
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);

+ 3 - 3
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) {

+ 12 - 14
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
 	}