update method

  1. @override
void update()
override

Implementation

@override
void update() {
  if (target!.getAttachment() is! PathAttachment) return;
  final PathAttachment attachment = target!.getAttachment() as PathAttachment;

  final double rotateMix = this.rotateMix, translateMix = this.translateMix;
  final bool translate = translateMix > 0, rotate = rotateMix > 0;
  if (!translate && !rotate) return;

  final PathConstraintData data = this.data;
  final SpacingMode? spacingMode = data.spacingMode;
  final bool lengthSpacing = spacingMode == SpacingMode.length;
  final RotateMode? rotateMode = data.rotateMode;
  final bool tangents = rotateMode == RotateMode.tangent,
      scale = rotateMode == RotateMode.chainScale;
  final int boneCount = this.bones.length,
      spacesCount = tangents ? boneCount : boneCount + 1;
  final List<Bone> bones = this.bones;
  final Float32List spaces = ArrayUtils.copyWithNewArraySize(
      this.spaces, spacesCount, double.infinity) as Float32List;
  late Float32List lengths;
  final double spacing = this.spacing;
  if (scale || lengthSpacing) {
    if (scale) {
      lengths = ArrayUtils.copyWithNewArraySize(
          this.lengths, boneCount, double.infinity) as Float32List;
    }
    final int n = spacesCount - 1;
    for (int i = 0; i < n;) {
      final Bone bone = bones[i];
      final double setupLength = bone.data.length;
      if (setupLength < PathConstraint.epsilon) {
        if (scale) lengths[i] = 0.0;
        spaces[++i] = 0.0;
      } else {
        final double x = setupLength * bone.a, y = setupLength * bone.c;
        final double length = math.sqrt(x * x + y * y);
        if (scale) lengths[i] = length;
        spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) *
            length /
            setupLength;
      }
    }
  } else {
    for (int i = 1; i < spacesCount; i++) {
      spaces[i] = spacing;
    }
  }

  final Float32List positions = computeWorldPositions(
      attachment,
      spacesCount,
      tangents,
      data.positionMode == PositionMode.percent,
      spacingMode == SpacingMode.percent);
  double boneX = positions[0],
      boneY = positions[1],
      offsetRotation = data.offsetRotation;
  bool tip = false;
  if (offsetRotation == 0) {
    tip = rotateMode == RotateMode.chain;
  } else {
    tip = false;
    final Bone p = target!.bone;
    offsetRotation = offsetRotation *
        (p.a * p.d - p.b * p.c > 0 ? MathUtils.degRad : -MathUtils.degRad);
  }
  for (int i = 0, p = 3; i < boneCount; i++, p += 3) {
    final Bone bone = bones[i];
    bone
      ..worldX += (boneX - bone.worldX) * translateMix
      ..worldY += (boneY - bone.worldY) * translateMix;
    final double x = positions[p],
        y = positions[p + 1],
        dx = x - boneX,
        dy = y - boneY;
    if (scale) {
      final double length = lengths[i];
      if (length != 0) {
        final double s =
            (math.sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1;
        bone
          ..a *= s
          ..c *= s;
      }
    }
    boneX = x;
    boneY = y;
    if (rotate) {
      final double a = bone.a, b = bone.b, c = bone.c, d = bone.d;
      double r = 0.0, cos = 0.0, sin = 0.0;
      if (tangents) {
        r = positions[p - 1];
      } else if (spaces[i + 1] == 0) {
        r = positions[p + 2];
      } else {
        r = math.atan2(dy, dx);
      }
      r -= math.atan2(c, a);
      if (tip) {
        cos = math.cos(r);
        sin = math.sin(r);
        final double length = bone.data.length;
        boneX += (length * (cos * a - sin * c) - dx) * rotateMix;
        boneY += (length * (sin * a + cos * c) - dy) * rotateMix;
      } else {
        r += offsetRotation;
      }
      if (r > math.pi) {
        r -= math.pi * 2;
      } else if (r < -math.pi) {
        r += math.pi * 2;
      }
      r *= rotateMix;
      cos = math.cos(r);
      sin = math.sin(r);
      bone
        ..a = cos * a - sin * c
        ..b = cos * b - sin * d
        ..c = sin * a + cos * c
        ..d = sin * b + cos * d;
    }
    bone.appliedValid = false;
  }
}