diff --git a/SpineRuntimes/SpineRuntime36/Bone.cs b/SpineRuntimes/SpineRuntime36/Bone.cs index d21cce8..7695eab 100644 --- a/SpineRuntimes/SpineRuntime36/Bone.cs +++ b/SpineRuntimes/SpineRuntime36/Bone.cs @@ -152,27 +152,13 @@ namespace SpineRuntime36 { Bone parent = this.parent; if (parent == null) { // Root bone. - float rotationY = rotation + 90 + shearY; - float la = MathUtils.CosDeg(rotation + shearX) * scaleX; - float lb = MathUtils.CosDeg(rotationY) * scaleY; - float lc = MathUtils.SinDeg(rotation + shearX) * scaleX; - float ld = MathUtils.SinDeg(rotationY) * scaleY; - if (skeleton.flipX) { - x = -x; - la = -la; - lb = -lb; - } - if (skeleton.flipY != yDown) { - y = -y; - lc = -lc; - ld = -ld; - } - a = la; - b = lb; - c = lc; - d = ld; - worldX = x + skeleton.x; - worldY = y + skeleton.y; + float rotationY = rotation + 90 + shearY, sx = skeleton.scaleX, sy = skeleton.scaleY; + a = MathUtils.CosDeg(rotation + shearX) * scaleX * sx; + b = MathUtils.CosDeg(rotationY) * scaleY * sx; + c = MathUtils.SinDeg(rotation + shearX) * scaleX * sy; + d = MathUtils.SinDeg(rotationY) * scaleY * sy; + worldX = x * sx + skeleton.x; + worldY = y * sy + skeleton.y; return; } @@ -228,13 +214,16 @@ namespace SpineRuntime36 { case TransformMode.NoScale: case TransformMode.NoScaleOrReflection: { float cos = MathUtils.CosDeg(rotation), sin = MathUtils.SinDeg(rotation); - float za = pa * cos + pb * sin; - float zc = pc * cos + pd * sin; + float za = (pa * cos + pb * sin) / skeleton.scaleX; + float zc = (pc * cos + pd * sin) / skeleton.scaleY; float s = (float)Math.Sqrt(za * za + zc * zc); if (s > 0.00001f) s = 1 / s; 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; + float r = MathUtils.PI / 2 + MathUtils.Atan2(zc, za); float zb = MathUtils.Cos(r) * s; float zd = MathUtils.Sin(r) * s; @@ -242,26 +231,18 @@ namespace SpineRuntime36 { float lb = MathUtils.CosDeg(90 + shearY) * scaleY; float lc = MathUtils.SinDeg(shearX) * scaleX; float ld = MathUtils.SinDeg(90 + shearY) * scaleY; - if (data.transformMode != TransformMode.NoScaleOrReflection? pa * pd - pb* pc< 0 : skeleton.flipX != skeleton.flipY) { - zb = -zb; - zd = -zd; - } a = za * la + zb * lc; b = za * lb + zb * ld; c = zc * la + zd * lc; - d = zc * lb + zd * ld; - return; + d = zc * lb + zd * ld; + break; } } - if (skeleton.flipX) { - a = -a; - b = -b; - } - if (skeleton.flipY != Bone.yDown) { - c = -c; - d = -d; - } + a *= skeleton.scaleX; + b *= skeleton.scaleX; + c *= skeleton.scaleY; + d *= skeleton.scaleY; } public void SetToSetupPose () { diff --git a/SpineRuntimes/SpineRuntime36/Skeleton.cs b/SpineRuntimes/SpineRuntime36/Skeleton.cs index 638a0c8..637f6c1 100644 --- a/SpineRuntimes/SpineRuntime36/Skeleton.cs +++ b/SpineRuntimes/SpineRuntime36/Skeleton.cs @@ -45,8 +45,8 @@ namespace SpineRuntime36 { internal Skin skin; internal float r = 1, g = 1, b = 1, a = 1; internal float time; - internal bool flipX, flipY; - internal float x, y; + internal float scaleX = 1, scaleY = 1; + internal float x, y; public SkeletonData Data { get { return data; } } public ExposedList Bones { get { return bones; } } @@ -64,10 +64,16 @@ namespace SpineRuntime36 { public float Time { get { return time; } set { time = value; } } public float X { get { return x; } set { x = value; } } public float Y { get { return y; } set { y = value; } } - public bool FlipX { get { return flipX; } set { flipX = value; } } - public bool FlipY { get { return flipY; } set { flipY = value; } } + public float ScaleX { get { return scaleX; } set { scaleX = value; } } + public float ScaleY { get { return scaleY; } set { scaleY = value; } } - public Bone RootBone { + [Obsolete("Use ScaleX instead. FlipX is when ScaleX is negative.")] + public bool FlipX { get { return scaleX < 0; } set { scaleX = value ? -1f : 1f; } } + + [Obsolete("Use ScaleY instead. FlipY is when ScaleY is negative.")] + public bool FlipY { get { return scaleY < 0; } set { scaleY = value ? -1f : 1f; } } + + public Bone RootBone { get { return bones.Count == 0 ? null : bones.Items[0]; } } diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs index 293d67d..aa7f1aa 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs @@ -122,68 +122,42 @@ namespace SpineViewer.Spine.Implementations.SpineObject protected override float scale { - get - { - if (skeletonBinary is not null) - return skeletonBinary.Scale; - else if (skeletonJson is not null) - return skeletonJson.Scale; - else - return 1f; - } + get => Math.Abs(skeleton.ScaleX); set { - // 保存状态 - var pos = position; - var fX = flipX; - var fY = flipY; - var animations = animationState.Tracks.Where(te => te is not null).Select(te => te.Animation.Name).ToArray(); - - if (skeletonBinary is not null) - { - skeletonBinary.Scale = value; - skeletonData = skeletonBinary.ReadSkeletonData(SkelPath); - } - else if (skeletonJson is not null) - { - skeletonJson.Scale = value; - skeletonData = skeletonJson.ReadSkeletonData(SkelPath); - } - - // reload skel-dependent data - skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; - animationStateData = new AnimationStateData(skeletonData) { DefaultMix = animationStateData.DefaultMix }; - animationState = new AnimationState(animationStateData); - - // 恢复状态 - position = pos; - flipX = fX; - flipY = fY; - reloadSkins(); - for (int i = 0; i < animations.Length; i++) setAnimation(i, animations[i]); + skeleton.ScaleX = Math.Sign(skeleton.ScaleX) * value; + skeleton.ScaleY = Math.Sign(skeleton.ScaleY) * value; } } - protected override PointF position - { - get => new(skeleton.X, skeleton.Y); - set - { - skeleton.X = value.X; + protected override PointF position + { + get => new(skeleton.X, skeleton.Y); + set + { + skeleton.X = value.X; skeleton.Y = value.Y; - } + } } protected override bool flipX { - get => skeleton.FlipX; - set => skeleton.FlipX = value; + get => skeleton.ScaleX < 0; + set + { + if (skeleton.ScaleX > 0 && value || skeleton.ScaleX < 0 && !value) + skeleton.ScaleX *= -1; + } } protected override bool flipY { - get => skeleton.FlipY; - set => skeleton.FlipY = value; + get => skeleton.ScaleY < 0; + set + { + if (skeleton.ScaleY > 0 && value || skeleton.ScaleY < 0 && !value) + skeleton.ScaleY *= -1; + } } protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment?.Name ?? EMPTY_ATTACHMENT; @@ -243,8 +217,8 @@ namespace SpineViewer.Spine.Implementations.SpineObject var maxDuration = 0f; var tmpSkeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; var tmpAnimationState = new AnimationState(animationStateData); - tmpSkeleton.FlipX = skeleton.FlipX; - tmpSkeleton.FlipY = skeleton.FlipY; + tmpSkeleton.ScaleX = skeleton.ScaleX; + tmpSkeleton.ScaleY = skeleton.ScaleY; tmpSkeleton.X = skeleton.X; tmpSkeleton.Y = skeleton.Y; foreach (var (name, _) in skinLoadStatus.Where(e => e.Value))