@esotericsoftware/spine-webgl 4.3.0 → 4.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -114,6 +114,8 @@ var Color = class _Color {
114
114
  }
115
115
  };
116
116
  var MathUtils = class _MathUtils {
117
+ static epsilon = 1e-5;
118
+ static epsilon2 = _MathUtils.epsilon * _MathUtils.epsilon;
117
119
  // biome-ignore lint/suspicious/noApproximativeNumericConstant: reference runtime
118
120
  static PI = 3.1415927;
119
121
  static PI2 = _MathUtils.PI * 2;
@@ -5911,73 +5913,70 @@ var BonePose = class {
5911
5913
  return;
5912
5914
  }
5913
5915
  case 1 /* OnlyTranslation */: {
5916
+ const sx = skeleton.scaleX, sy = skeleton.scaleY;
5914
5917
  const rx = (rotation + shearX) * MathUtils.degRad;
5915
5918
  const ry = (rotation + 90 + shearY) * MathUtils.degRad;
5916
- this.a = Math.cos(rx) * scaleX;
5917
- this.b = Math.cos(ry) * scaleY;
5918
- this.c = Math.sin(rx) * scaleX;
5919
- this.d = Math.sin(ry) * scaleY;
5919
+ this.a = Math.cos(rx) * scaleX * sx;
5920
+ this.b = Math.cos(ry) * scaleY * sx;
5921
+ this.c = Math.sin(rx) * scaleX * sy;
5922
+ this.d = Math.sin(ry) * scaleY * sy;
5920
5923
  break;
5921
5924
  }
5922
5925
  case 2 /* NoRotationOrReflection */: {
5923
- const sx = 1 / skeleton.scaleX, sy = 1 / skeleton.scaleY;
5924
- pa *= sx;
5925
- pc *= sy;
5926
+ const sx = skeleton.scaleX, sy = skeleton.scaleY, sxi = 1 / sx, syi = 1 / sy;
5927
+ pa *= sxi;
5928
+ pc *= syi;
5926
5929
  let s = pa * pa + pc * pc;
5927
- let prx = 0;
5928
- if (s > 1e-4) {
5929
- s = Math.abs(pa * pd * sy - pb * sx * pc) / s;
5930
+ let r = 0;
5931
+ if (s > MathUtils.epsilon2) {
5932
+ s = Math.abs(pa * pd * syi - pb * sxi * pc) / s;
5930
5933
  pb = pc * s;
5931
5934
  pd = pa * s;
5932
- prx = MathUtils.atan2Deg(pc, pa);
5935
+ r = rotation - MathUtils.atan2Deg(pc, pa);
5933
5936
  } else {
5934
5937
  pa = 0;
5935
5938
  pc = 0;
5936
- prx = 90 - MathUtils.atan2Deg(pd, pb);
5939
+ r = rotation - 90 + MathUtils.atan2Deg(pd, pb);
5937
5940
  }
5938
- const rx = (rotation + shearX - prx) * MathUtils.degRad;
5939
- const ry = (rotation + shearY - prx + 90) * MathUtils.degRad;
5941
+ const rx = (r + shearX) * MathUtils.degRad;
5942
+ const ry = (r + shearY + 90) * MathUtils.degRad;
5940
5943
  const la = Math.cos(rx) * scaleX;
5941
5944
  const lb = Math.cos(ry) * scaleY;
5942
5945
  const lc = Math.sin(rx) * scaleX;
5943
5946
  const ld = Math.sin(ry) * scaleY;
5944
- this.a = pa * la - pb * lc;
5945
- this.b = pa * lb - pb * ld;
5946
- this.c = pc * la + pd * lc;
5947
- this.d = pc * lb + pd * ld;
5947
+ this.a = (pa * la - pb * lc) * sx;
5948
+ this.b = (pa * lb - pb * ld) * sx;
5949
+ this.c = (pc * la + pd * lc) * sy;
5950
+ this.d = (pc * lb + pd * ld) * sy;
5948
5951
  break;
5949
5952
  }
5950
5953
  case 3 /* NoScale */:
5951
5954
  case 4 /* NoScaleOrReflection */: {
5952
- let r = rotation * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r);
5953
- let za = (pa * cos + pb * sin) / skeleton.scaleX;
5954
- let zc = (pc * cos + pd * sin) / skeleton.scaleY;
5955
- let s = Math.sqrt(za * za + zc * zc);
5956
- if (s > 1e-5) s = 1 / s;
5955
+ const sx = skeleton.scaleX, sy = skeleton.scaleY, sxi = 1 / sx, syi = 1 / sy;
5956
+ const r = rotation * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r);
5957
+ let za = (pa * cos + pb * sin) * sxi;
5958
+ let zc = (pc * cos + pd * sin) * syi;
5959
+ const s = 1 / Math.sqrt(za * za + zc * zc);
5957
5960
  za *= s;
5958
5961
  zc *= s;
5959
- s = Math.sqrt(za * za + zc * zc);
5960
- if (this.inherit === 3 /* NoScale */ && pa * pd - pb * pc < 0 !== (skeleton.scaleX < 0 !== skeleton.scaleY < 0)) s = -s;
5961
- r = Math.PI / 2 + Math.atan2(zc, za);
5962
- const zb = Math.cos(r) * s;
5963
- const zd = Math.sin(r) * s;
5962
+ let zb = -zc, zd = za;
5963
+ if (this.inherit === 3 /* NoScale */ && pa * pd - pb * pc < 0 !== (sx < 0 !== sy < 0)) {
5964
+ zb = -zb;
5965
+ zd = -zd;
5966
+ }
5964
5967
  const rx = shearX * MathUtils.degRad;
5965
5968
  const ry = (90 + shearY) * MathUtils.degRad;
5966
5969
  const la = Math.cos(rx) * scaleX;
5967
5970
  const lb = Math.cos(ry) * scaleY;
5968
5971
  const lc = Math.sin(rx) * scaleX;
5969
5972
  const ld = Math.sin(ry) * scaleY;
5970
- this.a = za * la + zb * lc;
5971
- this.b = za * lb + zb * ld;
5972
- this.c = zc * la + zd * lc;
5973
- this.d = zc * lb + zd * ld;
5973
+ this.a = (za * la + zb * lc) * sx;
5974
+ this.b = (za * lb + zb * ld) * sx;
5975
+ this.c = (zc * la + zd * lc) * sy;
5976
+ this.d = (zc * lb + zd * ld) * sy;
5974
5977
  break;
5975
5978
  }
5976
5979
  }
5977
- this.a *= skeleton.scaleX;
5978
- this.b *= skeleton.scaleX;
5979
- this.c *= skeleton.scaleY;
5980
- this.d *= skeleton.scaleY;
5981
5980
  }
5982
5981
  /** Computes the local transform values from the world transform.
5983
5982
  *
@@ -5990,79 +5989,118 @@ var BonePose = class {
5990
5989
  updateLocalTransform(skeleton) {
5991
5990
  this.local = 0;
5992
5991
  this.world = skeleton._update;
5992
+ const sx = skeleton.scaleX, sy = skeleton.scaleY;
5993
5993
  if (!this.bone.parent) {
5994
- this.x = this.worldX - skeleton.x;
5995
- this.y = this.worldY - skeleton.y;
5996
- const a = this.a, b = this.b, c = this.c, d = this.d;
5997
- this.rotation = MathUtils.atan2Deg(c, a);
5998
- this.scaleX = Math.sqrt(a * a + c * c);
5999
- this.scaleY = Math.sqrt(b * b + d * d);
6000
- this.shearX = 0;
6001
- this.shearY = MathUtils.atan2Deg(a * b + c * d, a * d - b * c);
5994
+ const sxi = 1 / sx, syi = 1 / sy;
5995
+ this.x = (this.worldX - skeleton.x) * sxi;
5996
+ this.y = (this.worldY - skeleton.y) * syi;
5997
+ this.set5(this.a * sxi, this.b * sxi, this.c * syi, this.d * syi, 0);
6002
5998
  return;
6003
5999
  }
6004
6000
  const parent = this.bone.parent.appliedPose;
6005
6001
  let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
6006
- let pid = 1 / (pa * pd - pb * pc);
6007
- let ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid;
6002
+ const pad = pa * pd - pb * pc, pid = 1 / (pa * pd - pb * pc);
6003
+ const ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid;
6008
6004
  const dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY;
6009
6005
  this.x = dx * ia - dy * ib;
6010
6006
  this.y = dy * id - dx * ic;
6011
- let ra, rb, rc, rd;
6012
- if (this.inherit === 1 /* OnlyTranslation */) {
6013
- ra = this.a;
6014
- rb = this.b;
6015
- rc = this.c;
6016
- rd = this.d;
6007
+ switch (this.inherit) {
6008
+ case 0 /* Normal */:
6009
+ this.set5(ia * this.a - ib * this.c, ia * this.b - ib * this.d, id * this.c - ic * this.a, id * this.d - ic * this.b, 0);
6010
+ break;
6011
+ case 1 /* OnlyTranslation */: {
6012
+ const sxi = 1 / sx, syi = 1 / sy;
6013
+ this.set5(this.a * sxi, this.b * sxi, this.c * syi, this.d * syi, 0);
6014
+ break;
6015
+ }
6016
+ case 2 /* NoRotationOrReflection */: {
6017
+ const sxi = 1 / sx, syi = 1 / sy;
6018
+ pa *= sxi;
6019
+ pc *= syi;
6020
+ const wa = this.a * sxi, wb = this.b * sxi, wc = this.c * syi, wd = this.d * syi;
6021
+ const s = 1 / (pa * pa + pc * pc), det = 1 / Math.abs(pad * sxi * syi);
6022
+ this.set5(
6023
+ (pa * wa + pc * wc) * s,
6024
+ (pa * wb + pc * wd) * s,
6025
+ (pa * wc - pc * wa) * det,
6026
+ (pa * wd - pc * wb) * det,
6027
+ MathUtils.atan2Deg(pc, pa)
6028
+ );
6029
+ break;
6030
+ }
6031
+ case 3 /* NoScale */:
6032
+ case 4 /* NoScaleOrReflection */: {
6033
+ const sxi = 1 / sx, syi = 1 / sy;
6034
+ const wa = this.a * sxi, wb = this.b * sxi, wc = this.c * syi, wd = this.d * syi;
6035
+ let tx = pd * this.a - pb * this.c, ty = pa * this.c - pc * this.a;
6036
+ if (pad < 0) {
6037
+ tx = -tx;
6038
+ ty = -ty;
6039
+ }
6040
+ let r = MathUtils.atan2Deg(ty, tx);
6041
+ this.rotation = r;
6042
+ r *= MathUtils.degRad;
6043
+ const cos = Math.cos(r), sin = Math.sin(r);
6044
+ let za = (pa * cos + pb * sin) * sxi;
6045
+ let zc = (pc * cos + pd * sin) * syi;
6046
+ const s = 1 / Math.sqrt(za * za + zc * zc);
6047
+ za *= s;
6048
+ zc *= s;
6049
+ const si = this.inherit === 3 /* NoScale */ && pad < 0 !== (sx < 0 !== sy < 0) ? -1 : 1;
6050
+ this.set4(za * wa + zc * wc, za * wb + zc * wd, (za * wc - zc * wa) * si, (za * wd - zc * wb) * si);
6051
+ }
6052
+ }
6053
+ }
6054
+ set4(ra, rb, rc, rd) {
6055
+ const x = ra * ra + rc * rc, y = rb * rb + rd * rd;
6056
+ if (x > MathUtils.epsilon2) {
6057
+ this.shearX = MathUtils.atan2Deg(rc, ra);
6058
+ this.scaleX = Math.sqrt(x);
6017
6059
  } else {
6018
- switch (this.inherit) {
6019
- case 2 /* NoRotationOrReflection */: {
6020
- const s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
6021
- pb = -pc * skeleton.scaleX * s / skeleton.scaleY;
6022
- pd = pa * skeleton.scaleY * s / skeleton.scaleX;
6023
- pid = 1 / (pa * pd - pb * pc);
6024
- ia = pd * pid;
6025
- ib = pb * pid;
6026
- break;
6027
- }
6028
- case 3 /* NoScale */:
6029
- case 4 /* NoScaleOrReflection */: {
6030
- let r = this.rotation * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r);
6031
- pa = (pa * cos + pb * sin) / skeleton.scaleX;
6032
- pc = (pc * cos + pd * sin) / skeleton.scaleY;
6033
- let s = Math.sqrt(pa * pa + pc * pc);
6034
- if (s > 1e-5) s = 1 / s;
6035
- pa *= s;
6036
- pc *= s;
6037
- s = Math.sqrt(pa * pa + pc * pc);
6038
- if (this.inherit === 3 /* NoScale */ && pid < 0 !== (skeleton.scaleX < 0 !== skeleton.scaleY < 0)) s = -s;
6039
- r = MathUtils.PI / 2 + Math.atan2(pc, pa);
6040
- pb = Math.cos(r) * s;
6041
- pd = Math.sin(r) * s;
6042
- pid = 1 / (pa * pd - pb * pc);
6043
- ia = pd * pid;
6044
- ib = pb * pid;
6045
- ic = pc * pid;
6046
- id = pa * pid;
6047
- }
6048
- }
6049
- ra = ia * this.a - ib * this.c;
6050
- rb = ia * this.b - ib * this.d;
6051
- rc = id * this.c - ic * this.a;
6052
- rd = id * this.d - ic * this.b;
6060
+ this.shearX = 0;
6061
+ this.scaleX = 0;
6053
6062
  }
6063
+ this.scaleY = Math.sqrt(y);
6064
+ if (y > MathUtils.epsilon2) {
6065
+ this.shearY = MathUtils.atan2Deg(rd, rb);
6066
+ if (ra * rd - rb * rc < 0) {
6067
+ this.scaleY = -this.scaleY;
6068
+ this.shearY += 90;
6069
+ } else
6070
+ this.shearY -= 90;
6071
+ if (this.shearY > 180)
6072
+ this.shearY -= 360;
6073
+ else if (this.shearY <= -180)
6074
+ this.shearY += 360;
6075
+ } else
6076
+ this.shearY = 0;
6077
+ }
6078
+ set5(ra, rb, rc, rd, ro) {
6054
6079
  this.shearX = 0;
6055
- this.scaleX = Math.sqrt(ra * ra + rc * rc);
6056
- if (this.scaleX > 1e-4) {
6057
- const det = ra * rd - rb * rc;
6058
- this.scaleY = det / this.scaleX;
6059
- this.shearY = -MathUtils.atan2Deg(ra * rb + rc * rd, det);
6060
- this.rotation = MathUtils.atan2Deg(rc, ra);
6080
+ const x = ra * ra + rc * rc, y = rb * rb + rd * rd;
6081
+ if (x > MathUtils.epsilon2) {
6082
+ const r = MathUtils.atan2Deg(rc, ra);
6083
+ this.rotation = r + ro;
6084
+ this.scaleX = Math.sqrt(x);
6085
+ this.scaleY = Math.sqrt(y);
6086
+ if (y > MathUtils.epsilon2) {
6087
+ this.shearY = MathUtils.atan2Deg(rd, rb);
6088
+ if (ra * rd - rb * rc < 0) {
6089
+ this.scaleY = -this.scaleY;
6090
+ this.shearY += 90 - r;
6091
+ } else
6092
+ this.shearY -= 90 + r;
6093
+ if (this.shearY > 180)
6094
+ this.shearY -= 360;
6095
+ else if (this.shearY <= -180)
6096
+ this.shearY += 360;
6097
+ } else
6098
+ this.shearY = 0;
6061
6099
  } else {
6062
6100
  this.scaleX = 0;
6063
- this.scaleY = Math.sqrt(rb * rb + rd * rd);
6101
+ this.scaleY = Math.sqrt(y);
6064
6102
  this.shearY = 0;
6065
- this.rotation = 90 - MathUtils.atan2Deg(rd, rb);
6103
+ this.rotation = y > MathUtils.epsilon2 ? MathUtils.atan2Deg(rd, rb) - 90 + ro : ro;
6066
6104
  }
6067
6105
  }
6068
6106
  /** If the world transform has been modified by constraints and the local transform no longer matches,
@@ -6307,6 +6345,12 @@ var ConstraintData = class extends PosedData {
6307
6345
  super(name, setup);
6308
6346
  }
6309
6347
  };
6348
+ var ScaleYMode = /* @__PURE__ */ ((ScaleYMode2) => {
6349
+ ScaleYMode2[ScaleYMode2["None"] = 0] = "None";
6350
+ ScaleYMode2[ScaleYMode2["Uniform"] = 1] = "Uniform";
6351
+ ScaleYMode2[ScaleYMode2["Volume"] = 2] = "Volume";
6352
+ return ScaleYMode2;
6353
+ })(ScaleYMode || {});
6310
6354
 
6311
6355
  // spine-core/src/Event.ts
6312
6356
  var Event = class {
@@ -6378,43 +6422,6 @@ var IkConstraintPose = class {
6378
6422
  }
6379
6423
  };
6380
6424
 
6381
- // spine-core/src/IkConstraintData.ts
6382
- var IkConstraintData = class extends ConstraintData {
6383
- /** The bones that are constrained by this IK constraint. */
6384
- bones = [];
6385
- _target = null;
6386
- /** The bone that is the IK target. */
6387
- set target(boneData) {
6388
- this._target = boneData;
6389
- }
6390
- get target() {
6391
- if (!this._target) throw new Error("target cannot be null.");
6392
- return this._target;
6393
- }
6394
- /** Determines how the {@link BonePose.scaleY} changes when {@link IkConstraintPose.compress} or
6395
- * {@link IkConstraintPose.stretch} set {@link BonePose.scaleX}. */
6396
- _scaleYMode = 0 /* None */;
6397
- set scaleYMode(scaleYMode) {
6398
- this._scaleYMode = scaleYMode;
6399
- }
6400
- get scaleYMode() {
6401
- if (this._scaleYMode == null) throw new Error("scaleYMode cannot be null.");
6402
- return this._scaleYMode;
6403
- }
6404
- constructor(name) {
6405
- super(name, new IkConstraintPose());
6406
- }
6407
- create(skeleton) {
6408
- return new IkConstraint(this, skeleton);
6409
- }
6410
- };
6411
- var ScaleYMode = /* @__PURE__ */ ((ScaleYMode2) => {
6412
- ScaleYMode2[ScaleYMode2["None"] = 0] = "None";
6413
- ScaleYMode2[ScaleYMode2["Uniform"] = 1] = "Uniform";
6414
- ScaleYMode2[ScaleYMode2["Volume"] = 2] = "Volume";
6415
- return ScaleYMode2;
6416
- })(ScaleYMode || {});
6417
-
6418
6425
  // spine-core/src/IkConstraint.ts
6419
6426
  var IkConstraint = class _IkConstraint extends Constraint {
6420
6427
  /** The 1 or 2 bones that will be modified by this IK constraint. */
@@ -6501,7 +6508,7 @@ var IkConstraint = class _IkConstraint extends Constraint {
6501
6508
  break;
6502
6509
  // biome-ignore lint/suspicious/noFallthroughSwitchClause: reference runtime
6503
6510
  case 2 /* NoRotationOrReflection */: {
6504
- const s = Math.abs(pa * pd - pb * pc) / Math.max(1e-4, pa * pa + pc * pc);
6511
+ const s = Math.abs(pa * pd - pb * pc) / Math.max(MathUtils.epsilon, pa * pa + pc * pc);
6505
6512
  const sa = pa / skeleton.scaleX;
6506
6513
  const sc = pc / skeleton.scaleY;
6507
6514
  pb = -sc * s * skeleton.scaleX;
@@ -6512,7 +6519,7 @@ var IkConstraint = class _IkConstraint extends Constraint {
6512
6519
  default: {
6513
6520
  const x = targetX - p.worldX, y = targetY - p.worldY;
6514
6521
  const d = pa * pd - pb * pc;
6515
- if (Math.abs(d) <= 1e-4) {
6522
+ if (Math.abs(d) <= MathUtils.epsilon) {
6516
6523
  tx = 0;
6517
6524
  ty = 0;
6518
6525
  } else {
@@ -6525,7 +6532,7 @@ var IkConstraint = class _IkConstraint extends Constraint {
6525
6532
  if (bone.scaleX < 0) rotationIK += 180;
6526
6533
  if (rotationIK > 180)
6527
6534
  rotationIK -= 360;
6528
- else if (rotationIK < -180)
6535
+ else if (rotationIK <= -180)
6529
6536
  rotationIK += 360;
6530
6537
  bone.rotation += rotationIK * mix;
6531
6538
  if (compress || stretch) {
@@ -6536,7 +6543,7 @@ var IkConstraint = class _IkConstraint extends Constraint {
6536
6543
  ty = targetY - bone.worldY;
6537
6544
  }
6538
6545
  const b = bone.bone.data.length * bone.scaleX;
6539
- if (b > 1e-4) {
6546
+ if (b > MathUtils.epsilon) {
6540
6547
  const dd = tx * tx + ty * ty;
6541
6548
  if (compress && dd < b * b || stretch && dd > b * b) {
6542
6549
  const s = (Math.sqrt(dd) / b - 1) * mix + 1;
@@ -6546,7 +6553,7 @@ var IkConstraint = class _IkConstraint extends Constraint {
6546
6553
  bone.scaleY *= s;
6547
6554
  break;
6548
6555
  case 2 /* Volume */:
6549
- bone.scaleY /= s;
6556
+ bone.scaleY /= s < 0.7 ? 0.25 + 0.642857 * s : s;
6550
6557
  }
6551
6558
  }
6552
6559
  }
@@ -6578,7 +6585,7 @@ var IkConstraint = class _IkConstraint extends Constraint {
6578
6585
  } else
6579
6586
  os2 = 0;
6580
6587
  let cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d;
6581
- const u = Math.abs(psx - psy) <= 1e-4;
6588
+ const u = Math.abs(psx - psy) <= MathUtils.epsilon;
6582
6589
  if (!u || stretch) {
6583
6590
  child.y = 0;
6584
6591
  cwx = a * child.x + parent.worldX;
@@ -6593,10 +6600,10 @@ var IkConstraint = class _IkConstraint extends Constraint {
6593
6600
  c = pp.c;
6594
6601
  d = pp.d;
6595
6602
  let id = a * d - b * c, x = cwx - pp.worldX, y = cwy - pp.worldY;
6596
- id = Math.abs(id) <= 1e-4 ? 0 : 1 / id;
6603
+ id = Math.abs(id) <= MathUtils.epsilon ? 0 : 1 / id;
6597
6604
  const dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py;
6598
6605
  let l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.bone.data.length * csx, a1, a2;
6599
- if (l1 < 1e-4) {
6606
+ if (l1 < MathUtils.epsilon) {
6600
6607
  _IkConstraint.apply(skeleton, parent, targetX, targetY, false, stretch, 0 /* None */, mix);
6601
6608
  child.rotation = 0;
6602
6609
  return;
@@ -6634,7 +6641,7 @@ var IkConstraint = class _IkConstraint extends Constraint {
6634
6641
  parent.scaleY *= a;
6635
6642
  break;
6636
6643
  case 2 /* Volume */:
6637
- parent.scaleY /= a;
6644
+ parent.scaleY /= a < 0.7 ? 0.25 + 0.642857 * a : a;
6638
6645
  }
6639
6646
  }
6640
6647
  } else
@@ -6696,18 +6703,49 @@ var IkConstraint = class _IkConstraint extends Constraint {
6696
6703
  a1 = (a1 - os) * MathUtils.radDeg + os1 - parent.rotation;
6697
6704
  if (a1 > 180)
6698
6705
  a1 -= 360;
6699
- else if (a1 < -180)
6706
+ else if (a1 <= -180)
6700
6707
  a1 += 360;
6701
6708
  parent.rotation += a1 * mix;
6702
6709
  a2 = ((a2 + os) * MathUtils.radDeg - child.shearX) * s2 + os2 - child.rotation;
6703
6710
  if (a2 > 180)
6704
6711
  a2 -= 360;
6705
- else if (a2 < -180)
6712
+ else if (a2 <= -180)
6706
6713
  a2 += 360;
6707
6714
  child.rotation += a2 * mix;
6708
6715
  }
6709
6716
  };
6710
6717
 
6718
+ // spine-core/src/IkConstraintData.ts
6719
+ var IkConstraintData = class extends ConstraintData {
6720
+ /** The bones that are constrained by this IK constraint. */
6721
+ bones = [];
6722
+ _target = null;
6723
+ /** The bone that is the IK target. */
6724
+ set target(boneData) {
6725
+ this._target = boneData;
6726
+ }
6727
+ get target() {
6728
+ if (!this._target) throw new Error("target cannot be null.");
6729
+ return this._target;
6730
+ }
6731
+ /** Determines how the {@link BonePose.scaleY} changes when {@link IkConstraintPose.compress} or
6732
+ * {@link IkConstraintPose.stretch} set {@link BonePose.scaleX}. */
6733
+ _scaleYMode = 0 /* None */;
6734
+ set scaleYMode(scaleYMode) {
6735
+ this._scaleYMode = scaleYMode;
6736
+ }
6737
+ get scaleYMode() {
6738
+ if (this._scaleYMode == null) throw new Error("scaleYMode cannot be null.");
6739
+ return this._scaleYMode;
6740
+ }
6741
+ constructor(name) {
6742
+ super(name, new IkConstraintPose());
6743
+ }
6744
+ create(skeleton) {
6745
+ return new IkConstraint(this, skeleton);
6746
+ }
6747
+ };
6748
+
6711
6749
  // spine-core/src/PathConstraintPose.ts
6712
6750
  var PathConstraintPose = class {
6713
6751
  /** The position along the path. */
@@ -6781,7 +6819,6 @@ var PathConstraint = class _PathConstraint extends Constraint {
6781
6819
  static NONE = -1;
6782
6820
  static BEFORE = -2;
6783
6821
  static AFTER = -3;
6784
- static epsilon = 1e-5;
6785
6822
  /** The path constraint's setup pose data. */
6786
6823
  data;
6787
6824
  /** The bones that will be modified by this path constraint. */
@@ -6837,7 +6874,7 @@ var PathConstraint = class _PathConstraint extends Constraint {
6837
6874
  for (let i = 0, n = spacesCount - 1; i < n; ) {
6838
6875
  const bone = bones[i];
6839
6876
  const setupLength = bone.bone.data.length;
6840
- if (setupLength < _PathConstraint.epsilon) {
6877
+ if (setupLength < MathUtils.epsilon) {
6841
6878
  if (scale) lengths[i] = 0;
6842
6879
  spaces[++i] = spacing;
6843
6880
  } else {
@@ -6860,7 +6897,7 @@ var PathConstraint = class _PathConstraint extends Constraint {
6860
6897
  for (let i = 0, n = spacesCount - 1; i < n; ) {
6861
6898
  const bone = bones[i];
6862
6899
  const setupLength = bone.bone.data.length;
6863
- if (setupLength < _PathConstraint.epsilon) {
6900
+ if (setupLength < MathUtils.epsilon) {
6864
6901
  if (scale) lengths[i] = 0;
6865
6902
  spaces[++i] = spacing;
6866
6903
  } else {
@@ -8001,9 +8038,20 @@ var PhysicsConstraint = class _PhysicsConstraint extends Constraint {
8001
8038
  }
8002
8039
  }
8003
8040
  if (scaleX) {
8004
- const s = 1 + (this.scaleOffset - this.scaleLag * z) * mix * this.data.scaleX;
8041
+ let s = 1 + (this.scaleOffset - this.scaleLag * z) * mix * this.data.scaleX;
8005
8042
  bone.a *= s;
8006
8043
  bone.c *= s;
8044
+ switch (this.data.scaleYMode) {
8045
+ case 1 /* Uniform */:
8046
+ bone.b *= s;
8047
+ bone.d *= s;
8048
+ break;
8049
+ case 2 /* Volume */:
8050
+ s = Math.abs(s);
8051
+ s = s >= 0.7 ? 1 / s : 4 - 3.67347 * s;
8052
+ bone.b *= s;
8053
+ bone.d *= s;
8054
+ }
8007
8055
  }
8008
8056
  if (physics !== 3 /* pose */) {
8009
8057
  this.tx = l * bone.a;
@@ -8062,6 +8110,16 @@ var PhysicsConstraintData = class extends ConstraintData {
8062
8110
  gravityGlobal = false;
8063
8111
  /** True when this constraint's mix is controlled by global slider timelines. */
8064
8112
  mixGlobal = false;
8113
+ /** Determines how the {@link BonePose.scaleY} changes when {@link PhysicsConstraintData.scaleX} sets
8114
+ * {@link BonePose.scaleX}. */
8115
+ _scaleYMode = 0 /* None */;
8116
+ get scaleYMode() {
8117
+ return this._scaleYMode;
8118
+ }
8119
+ set scaleYMode(scaleYMode) {
8120
+ if (scaleYMode == null) throw new Error("scaleYMode cannot be null.");
8121
+ this._scaleYMode = scaleYMode;
8122
+ }
8065
8123
  constructor(name) {
8066
8124
  super(name, new PhysicsConstraintPose());
8067
8125
  }
@@ -9114,7 +9172,17 @@ var SkeletonBinary = class {
9114
9172
  if ((flags & 2) !== 0) data.x = input.readFloat();
9115
9173
  if ((flags & 4) !== 0) data.y = input.readFloat();
9116
9174
  if ((flags & 8) !== 0) data.rotate = input.readFloat();
9117
- if ((flags & 16) !== 0) data.scaleX = input.readFloat();
9175
+ if ((flags & 16) !== 0) {
9176
+ let scaleX = input.readFloat();
9177
+ if (scaleX < -2) {
9178
+ data.scaleYMode = 2 /* Volume */;
9179
+ scaleX = -2 - scaleX;
9180
+ } else if (scaleX < 0) {
9181
+ data.scaleYMode = 1 /* Uniform */;
9182
+ scaleX = -1 - scaleX;
9183
+ }
9184
+ data.scaleX = scaleX;
9185
+ }
9118
9186
  if ((flags & 32) !== 0) data.shearX = input.readFloat();
9119
9187
  data.limit = ((flags & 64) !== 0 ? input.readFloat() : 5e3) * scale;
9120
9188
  data.step = 1 / input.readUnsignedByte();
@@ -11537,6 +11605,8 @@ var SkeletonJson = class {
11537
11605
  data.y = getValue(constraintMap, "y", 0);
11538
11606
  data.rotate = getValue(constraintMap, "rotate", 0);
11539
11607
  data.scaleX = getValue(constraintMap, "scaleX", 0);
11608
+ const scaleY = getValue(constraintMap, "scaleY", null);
11609
+ if (scaleY != null) data.scaleYMode = Utils.enumValue(ScaleYMode, scaleY);
11540
11610
  data.shearX = getValue(constraintMap, "shearX", 0);
11541
11611
  data.limit = getValue(constraintMap, "limit", 5e3) * scale;
11542
11612
  data.step = 1 / getValue(constraintMap, "fps", 60);
@@ -14671,10 +14741,12 @@ var SkeletonRenderer = class _SkeletonRenderer {
14671
14741
  twoColorTint = false;
14672
14742
  renderable = new Renderable([], 0, 0);
14673
14743
  clipper = new SkeletonClipping();
14674
- temp = new Vector2();
14675
- temp2 = new Vector2();
14676
- temp3 = new Color();
14677
- temp4 = new Color();
14744
+ /**
14745
+ * Batches additive slots together with normal slots by rendering additive slots with premultiplied alpha RGB and zero alpha,
14746
+ * while using normal PMA blending. This reduces draw calls for normal/additive/normal sequences with the same texture.
14747
+ * Disable this if rendering to a transparent target and the accumulated destination alpha from additive blending must be preserved.
14748
+ */
14749
+ pmaAdditiveBatching = true;
14678
14750
  constructor(context, twoColorTint = true) {
14679
14751
  this.twoColorTint = twoColorTint;
14680
14752
  if (twoColorTint)
@@ -14753,7 +14825,9 @@ var SkeletonRenderer = class _SkeletonRenderer {
14753
14825
  finalColor.r = skeletonColor.r * slotColor.r * attachmentColor.r * alpha;
14754
14826
  finalColor.g = skeletonColor.g * slotColor.g * attachmentColor.g * alpha;
14755
14827
  finalColor.b = skeletonColor.b * slotColor.b * attachmentColor.b * alpha;
14756
- finalColor.a = alpha;
14828
+ const slotBlendMode = slot.data.blendMode;
14829
+ const additiveBlend = this.pmaAdditiveBatching && slotBlendMode === 1 /* Additive */;
14830
+ finalColor.a = additiveBlend ? 0 : alpha;
14757
14831
  const darkColor = this.tempColor2;
14758
14832
  if (!pose.darkColor)
14759
14833
  darkColor.set(0, 0, 0, 1);
@@ -14763,9 +14837,9 @@ var SkeletonRenderer = class _SkeletonRenderer {
14763
14837
  darkColor.b = pose.darkColor.b * alpha;
14764
14838
  darkColor.a = 1;
14765
14839
  }
14766
- const slotBlendMode = slot.data.blendMode;
14767
- if (slotBlendMode !== blendMode) {
14768
- blendMode = slotBlendMode;
14840
+ const batchBlendMode = additiveBlend ? 0 /* Normal */ : slotBlendMode;
14841
+ if (batchBlendMode !== blendMode) {
14842
+ blendMode = batchBlendMode;
14769
14843
  batcher.setBlendMode(blendMode);
14770
14844
  }
14771
14845
  if (clipper.isClipping() && clipper.clipTriangles(renderable.vertices, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint, vertexSize)) {
@@ -14780,7 +14854,7 @@ var SkeletonRenderer = class _SkeletonRenderer {
14780
14854
  verts[v] = finalColor.r;
14781
14855
  verts[v + 1] = finalColor.g;
14782
14856
  verts[v + 2] = finalColor.b;
14783
- verts[v + 3] = alpha;
14857
+ verts[v + 3] = finalColor.a;
14784
14858
  verts[v + 4] = uvs[u];
14785
14859
  verts[v + 5] = uvs[u + 1];
14786
14860
  }
@@ -14789,7 +14863,7 @@ var SkeletonRenderer = class _SkeletonRenderer {
14789
14863
  verts[v] = finalColor.r;
14790
14864
  verts[v + 1] = finalColor.g;
14791
14865
  verts[v + 2] = finalColor.b;
14792
- verts[v + 3] = alpha;
14866
+ verts[v + 3] = finalColor.a;
14793
14867
  verts[v + 4] = uvs[u];
14794
14868
  verts[v + 5] = uvs[u + 1];
14795
14869
  verts[v + 6] = darkColor.r;