增加scaleX和scaleY

This commit is contained in:
ww-rm
2025-04-19 14:32:56 +08:00
parent 027d3af619
commit 304af805cb
3 changed files with 53 additions and 92 deletions

View File

@@ -152,27 +152,13 @@ namespace SpineRuntime36 {
Bone parent = this.parent; Bone parent = this.parent;
if (parent == null) { // Root bone. if (parent == null) { // Root bone.
float rotationY = rotation + 90 + shearY; float rotationY = rotation + 90 + shearY, sx = skeleton.scaleX, sy = skeleton.scaleY;
float la = MathUtils.CosDeg(rotation + shearX) * scaleX; a = MathUtils.CosDeg(rotation + shearX) * scaleX * sx;
float lb = MathUtils.CosDeg(rotationY) * scaleY; b = MathUtils.CosDeg(rotationY) * scaleY * sx;
float lc = MathUtils.SinDeg(rotation + shearX) * scaleX; c = MathUtils.SinDeg(rotation + shearX) * scaleX * sy;
float ld = MathUtils.SinDeg(rotationY) * scaleY; d = MathUtils.SinDeg(rotationY) * scaleY * sy;
if (skeleton.flipX) { worldX = x * sx + skeleton.x;
x = -x; worldY = y * sy + skeleton.y;
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;
return; return;
} }
@@ -228,13 +214,16 @@ namespace SpineRuntime36 {
case TransformMode.NoScale: case TransformMode.NoScale:
case TransformMode.NoScaleOrReflection: { case TransformMode.NoScaleOrReflection: {
float cos = MathUtils.CosDeg(rotation), sin = MathUtils.SinDeg(rotation); float cos = MathUtils.CosDeg(rotation), sin = MathUtils.SinDeg(rotation);
float za = pa * cos + pb * sin; float za = (pa * cos + pb * sin) / skeleton.scaleX;
float zc = pc * cos + pd * sin; float zc = (pc * cos + pd * sin) / skeleton.scaleY;
float s = (float)Math.Sqrt(za * za + zc * zc); float s = (float)Math.Sqrt(za * za + zc * zc);
if (s > 0.00001f) s = 1 / s; if (s > 0.00001f) s = 1 / s;
za *= s; za *= s;
zc *= s; zc *= s;
s = (float)Math.Sqrt(za * za + zc * zc); 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 r = MathUtils.PI / 2 + MathUtils.Atan2(zc, za);
float zb = MathUtils.Cos(r) * s; float zb = MathUtils.Cos(r) * s;
float zd = MathUtils.Sin(r) * s; float zd = MathUtils.Sin(r) * s;
@@ -242,26 +231,18 @@ namespace SpineRuntime36 {
float lb = MathUtils.CosDeg(90 + shearY) * scaleY; float lb = MathUtils.CosDeg(90 + shearY) * scaleY;
float lc = MathUtils.SinDeg(shearX) * scaleX; float lc = MathUtils.SinDeg(shearX) * scaleX;
float ld = MathUtils.SinDeg(90 + shearY) * scaleY; 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; a = za * la + zb * lc;
b = za * lb + zb * ld; b = za * lb + zb * ld;
c = zc * la + zd * lc; c = zc * la + zd * lc;
d = zc * lb + zd * ld; d = zc * lb + zd * ld;
return; break;
} }
} }
if (skeleton.flipX) { a *= skeleton.scaleX;
a = -a; b *= skeleton.scaleX;
b = -b; c *= skeleton.scaleY;
} d *= skeleton.scaleY;
if (skeleton.flipY != Bone.yDown) {
c = -c;
d = -d;
}
} }
public void SetToSetupPose () { public void SetToSetupPose () {

View File

@@ -45,8 +45,8 @@ namespace SpineRuntime36 {
internal Skin skin; internal Skin skin;
internal float r = 1, g = 1, b = 1, a = 1; internal float r = 1, g = 1, b = 1, a = 1;
internal float time; internal float time;
internal bool flipX, flipY; internal float scaleX = 1, scaleY = 1;
internal float x, y; internal float x, y;
public SkeletonData Data { get { return data; } } public SkeletonData Data { get { return data; } }
public ExposedList<Bone> Bones { get { return bones; } } public ExposedList<Bone> Bones { get { return bones; } }
@@ -64,10 +64,16 @@ namespace SpineRuntime36 {
public float Time { get { return time; } set { time = value; } } public float Time { get { return time; } set { time = value; } }
public float X { get { return x; } set { x = value; } } public float X { get { return x; } set { x = value; } }
public float Y { get { return y; } set { y = value; } } public float Y { get { return y; } set { y = value; } }
public bool FlipX { get { return flipX; } set { flipX = value; } } public float ScaleX { get { return scaleX; } set { scaleX = value; } }
public bool FlipY { get { return flipY; } set { flipY = 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]; } get { return bones.Count == 0 ? null : bones.Items[0]; }
} }

View File

@@ -122,68 +122,42 @@ namespace SpineViewer.Spine.Implementations.SpineObject
protected override float scale protected override float scale
{ {
get get => Math.Abs(skeleton.ScaleX);
{
if (skeletonBinary is not null)
return skeletonBinary.Scale;
else if (skeletonJson is not null)
return skeletonJson.Scale;
else
return 1f;
}
set set
{ {
// 保存状态 skeleton.ScaleX = Math.Sign(skeleton.ScaleX) * value;
var pos = position; skeleton.ScaleY = Math.Sign(skeleton.ScaleY) * value;
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]);
} }
} }
protected override PointF position protected override PointF position
{ {
get => new(skeleton.X, skeleton.Y); get => new(skeleton.X, skeleton.Y);
set set
{ {
skeleton.X = value.X; skeleton.X = value.X;
skeleton.Y = value.Y; skeleton.Y = value.Y;
} }
} }
protected override bool flipX protected override bool flipX
{ {
get => skeleton.FlipX; get => skeleton.ScaleX < 0;
set => skeleton.FlipX = value; set
{
if (skeleton.ScaleX > 0 && value || skeleton.ScaleX < 0 && !value)
skeleton.ScaleX *= -1;
}
} }
protected override bool flipY protected override bool flipY
{ {
get => skeleton.FlipY; get => skeleton.ScaleY < 0;
set => skeleton.FlipY = value; 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; 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 maxDuration = 0f;
var tmpSkeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; var tmpSkeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) };
var tmpAnimationState = new AnimationState(animationStateData); var tmpAnimationState = new AnimationState(animationStateData);
tmpSkeleton.FlipX = skeleton.FlipX; tmpSkeleton.ScaleX = skeleton.ScaleX;
tmpSkeleton.FlipY = skeleton.FlipY; tmpSkeleton.ScaleY = skeleton.ScaleY;
tmpSkeleton.X = skeleton.X; tmpSkeleton.X = skeleton.X;
tmpSkeleton.Y = skeleton.Y; tmpSkeleton.Y = skeleton.Y;
foreach (var (name, _) in skinLoadStatus.Where(e => e.Value)) foreach (var (name, _) in skinLoadStatus.Where(e => e.Value))