[csharp] Ported commit 4f73fbb, "Fixed applying a constraint reverting changes from other constraints.", see #1896.

This commit is contained in:
Harald Csaszar 2021-05-27 18:35:52 +02:00
parent e6a14ff532
commit 7b1469c32b
6 changed files with 48 additions and 37 deletions

View File

@ -47,7 +47,6 @@ namespace Spine {
internal ExposedList<Bone> children = new ExposedList<Bone>(); internal ExposedList<Bone> children = new ExposedList<Bone>();
internal float x, y, rotation, scaleX, scaleY, shearX, shearY; internal float x, y, rotation, scaleX, scaleY, shearX, shearY;
internal float ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY; internal float ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY;
internal bool appliedValid;
internal float a, b, worldX; internal float a, b, worldX;
internal float c, d, worldY; internal float c, d, worldY;
@ -101,13 +100,19 @@ namespace Spine {
/// <summary>The applied local shearY.</summary> /// <summary>The applied local shearY.</summary>
public float AShearY { get { return ashearY; } set { ashearY = value; } } public float AShearY { get { return ashearY; } set { ashearY = value; } }
public float A { get { return a; } } /// <summary>Part of the world transform matrix for the X axis. If changed, <see cref="UpdateAppliedTransform()"/> should be called.</summary>
public float B { get { return b; } } public float A { get { return a; } set { a = value; } }
public float C { get { return c; } } /// <summary>Part of the world transform matrix for the Y axis. If changed, <see cref="UpdateAppliedTransform()"/> should be called.</summary>
public float D { get { return d; } } public float B { get { return b; } set { b = value; } }
/// <summary>Part of the world transform matrix for the X axis. If changed, <see cref="UpdateAppliedTransform()"/> should be called.</summary>
public float C { get { return c; } set { c = value; } }
/// <summary>Part of the world transform matrix for the Y axis. If changed, <see cref="UpdateAppliedTransform()"/> should be called.</summary>
public float D { get { return d; } set { d = value; } }
public float WorldX { get { return worldX; } } /// <summary>The world X position. If changed, <see cref="UpdateAppliedTransform()"/> should be called.</summary>
public float WorldY { get { return worldY; } } public float WorldX { get { return worldX; } set { worldX = value; } }
/// <summary>The world Y position. If changed, <see cref="UpdateAppliedTransform()"/> should be called.</summary>
public float WorldY { get { return worldY; } set { worldY = value; } }
public float WorldRotationX { get { return MathUtils.Atan2(c, a) * MathUtils.RadDeg; } } public float WorldRotationX { get { return MathUtils.Atan2(c, a) * MathUtils.RadDeg; } }
public float WorldRotationY { get { return MathUtils.Atan2(d, b) * MathUtils.RadDeg; } } public float WorldRotationY { get { return MathUtils.Atan2(d, b) * MathUtils.RadDeg; } }
@ -127,9 +132,9 @@ namespace Spine {
SetToSetupPose(); SetToSetupPose();
} }
/// <summary>Same as <see cref="UpdateWorldTransform"/>. This method exists for Bone to implement <see cref="Spine.IUpdatable"/>.</summary> /// <summary>Computes the world transform using the parent bone and this bone's local applied transform.</summary>
public void Update () { public void Update () {
UpdateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY); UpdateWorldTransform(ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY);
} }
/// <summary>Computes the world transform using the parent bone and this bone's local transform.</summary> /// <summary>Computes the world transform using the parent bone and this bone's local transform.</summary>
@ -137,7 +142,11 @@ namespace Spine {
UpdateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY); UpdateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY);
} }
/// <summary>Computes the world transform using the parent bone and the specified local transform.</summary> /// <summary>Computes the world transform using the parent bone and the specified local transform. The applied transform is set to the
/// specified local transform. Child bones are not updated.
/// <para>
/// See <a href="http://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
/// Runtimes Guide.</para></summary>
public void UpdateWorldTransform (float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { public void UpdateWorldTransform (float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) {
ax = x; ax = x;
ay = y; ay = y;
@ -146,8 +155,6 @@ namespace Spine {
ascaleY = scaleY; ascaleY = scaleY;
ashearX = shearX; ashearX = shearX;
ashearY = shearY; ashearY = shearY;
appliedValid = true;
Skeleton skeleton = this.skeleton;
Bone parent = this.parent; Bone parent = this.parent;
if (parent == null) { // Root bone. if (parent == null) { // Root bone.
@ -258,13 +265,16 @@ namespace Spine {
} }
/// <summary> /// <summary>
/// Computes the individual applied transform values from the world transform. This can be useful to perform processing using /// Computes the applied transform values from the world transform.
/// the applied transform after the world transform has been modified directly (eg, by a constraint).. /// <para>
/// /// If the world transform is modified (by a constraint, <see cref="RotateWorld(float)"/>, etc) then this method should be called so
/// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. /// the applied transform matches the world transform. The applied transform may be needed by other code (eg to apply another
/// </summary> /// constraint).
/// </para><para>
/// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The applied transform after
/// calling this method is equivalent to the local transform used to compute the world transform, but may not be identical.
/// </para></summary>
internal void UpdateAppliedTransform () { internal void UpdateAppliedTransform () {
appliedValid = true;
Bone parent = this.parent; Bone parent = this.parent;
if (parent == null) { if (parent == null) {
ax = worldX; ax = worldX;
@ -347,9 +357,11 @@ namespace Spine {
} }
/// <summary> /// <summary>
/// Rotates the world transform the specified amount and sets isAppliedValid to false. /// Rotates the world transform the specified amount.
/// </summary> /// <para>
/// <param name="degrees">Degrees.</param> /// After changes are made to the world transform, <see cref="UpdateAppliedTransform()"/> should be called and <see cref="Update()"/> will
/// need to be called on any child bones, recursively.
/// </para></summary>
public void RotateWorld (float degrees) { public void RotateWorld (float degrees) {
float a = this.a, b = this.b, c = this.c, d = this.d; float a = this.a, b = this.b, c = this.c, d = this.d;
float cos = MathUtils.CosDeg(degrees), sin = MathUtils.SinDeg(degrees); float cos = MathUtils.CosDeg(degrees), sin = MathUtils.SinDeg(degrees);
@ -357,7 +369,6 @@ namespace Spine {
this.b = cos * b - sin * d; this.b = cos * b - sin * d;
this.c = sin * a + cos * c; this.c = sin * a + cos * c;
this.d = sin * b + cos * d; this.d = sin * b + cos * d;
appliedValid = false;
} }
override public string ToString () { override public string ToString () {

View File

@ -160,7 +160,6 @@ namespace Spine {
static public void Apply (Bone bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, static public void Apply (Bone bone, float targetX, float targetY, bool compress, bool stretch, bool uniform,
float alpha) { float alpha) {
if (bone == null) throw new ArgumentNullException("bone", "bone cannot be null."); if (bone == null) throw new ArgumentNullException("bone", "bone cannot be null.");
if (!bone.appliedValid) bone.UpdateAppliedTransform();
Bone p = bone.parent; Bone p = bone.parent;
float pa = p.a, pb = p.b, pc = p.c, pd = p.d; float pa = p.a, pb = p.b, pc = p.c, pd = p.d;
@ -222,8 +221,6 @@ namespace Spine {
float softness, float alpha) { float softness, float alpha) {
if (parent == null) throw new ArgumentNullException("parent", "parent cannot be null."); if (parent == null) throw new ArgumentNullException("parent", "parent cannot be null.");
if (child == null) throw new ArgumentNullException("child", "child cannot be null."); if (child == null) throw new ArgumentNullException("child", "child cannot be null.");
if (!parent.appliedValid) parent.UpdateAppliedTransform();
if (!child.appliedValid) child.UpdateAppliedTransform();
float px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX; float px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX;
int os1, os2, s2; int os1, os2, s2;
if (psx < 0) { if (psx < 0) {

View File

@ -216,7 +216,7 @@ namespace Spine {
bone.c = sin * a + cos * c; bone.c = sin * a + cos * c;
bone.d = sin * b + cos * d; bone.d = sin * b + cos * d;
} }
bone.appliedValid = false; bone.UpdateAppliedTransform();
} }
} }

View File

@ -316,6 +316,18 @@ namespace Spine {
/// Runtimes Guide.</para> /// Runtimes Guide.</para>
/// </summary> /// </summary>
public void UpdateWorldTransform () { public void UpdateWorldTransform () {
Object[] bones = this.bones.Items;
for (int i = 0, n = this.bones.Count; i < n; i++) {
Bone bone = (Bone)bones[i];
bone.ax = bone.x;
bone.ay = bone.y;
bone.arotation = bone.rotation;
bone.ascaleX = bone.scaleX;
bone.ascaleY = bone.scaleY;
bone.ashearX = bone.shearX;
bone.ashearY = bone.shearY;
}
var updateCache = this.updateCache.Items; var updateCache = this.updateCache.Items;
for (int i = 0, n = this.updateCache.Count; i < n; i++) for (int i = 0, n = this.updateCache.Count; i < n; i++)
updateCache[i].Update(); updateCache[i].Update();

View File

@ -157,7 +157,7 @@ namespace Spine {
bone.d = MathUtils.Sin(r) * s; bone.d = MathUtils.Sin(r) * s;
} }
bone.appliedValid = false; bone.UpdateAppliedTransform();
} }
} }
@ -221,7 +221,7 @@ namespace Spine {
bone.d = MathUtils.Sin(r) * s; bone.d = MathUtils.Sin(r) * s;
} }
bone.appliedValid = false; bone.UpdateAppliedTransform();
} }
} }
@ -230,12 +230,10 @@ namespace Spine {
mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
Bone target = this.target; Bone target = this.target;
if (!target.appliedValid) target.UpdateAppliedTransform();
var bones = this.bones.Items; var bones = this.bones.Items;
for (int i = 0, n = this.bones.Count; i < n; i++) { for (int i = 0, n = this.bones.Count; i < n; i++) {
Bone bone = bones[i]; Bone bone = bones[i];
if (!bone.appliedValid) bone.UpdateAppliedTransform();
float rotation = bone.arotation; float rotation = bone.arotation;
if (mixRotate != 0) { if (mixRotate != 0) {
@ -270,12 +268,10 @@ namespace Spine {
mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
Bone target = this.target; Bone target = this.target;
if (!target.appliedValid) target.UpdateAppliedTransform();
var bones = this.bones.Items; var bones = this.bones.Items;
for (int i = 0, n = this.bones.Count; i < n; i++) { for (int i = 0, n = this.bones.Count; i < n; i++) {
Bone bone = bones[i]; Bone bone = bones[i];
if (!bone.appliedValid) bone.UpdateAppliedTransform();
float rotation = bone.arotation + (target.arotation + data.offsetRotation) * mixRotate; float rotation = bone.arotation + (target.arotation + data.offsetRotation) * mixRotate;
float x = bone.ax + (target.ax + data.offsetX) * mixX; float x = bone.ax + (target.ax + data.offsetX) * mixX;

View File

@ -148,11 +148,6 @@ namespace Spine.Unity {
break; break;
case UpdatePhase.World: case UpdatePhase.World:
case UpdatePhase.Complete: case UpdatePhase.Complete:
// Use Applied transform values (ax, ay, AppliedRotation, ascale) if world values were modified by constraints.
if (!bone.appliedValid) {
bone.UpdateAppliedTransform();
}
if (position) if (position)
thisTransform.localPosition = new Vector3(bone.ax * positionScale, bone.ay * positionScale, 0); thisTransform.localPosition = new Vector3(bone.ax * positionScale, bone.ay * positionScale, 0);