private void SortPathConstraintAttachment(Attachment attachment, Bone slotBone) { PathAttachment pathAttachment = attachment as PathAttachment; if (pathAttachment == null) { return; } int[] array = pathAttachment.bones; if (array == null) { this.SortBone(slotBone); } else { ExposedList <Bone> exposedList = this.bones; int i = 0; int num = array.Length; while (i < num) { this.SortBone(exposedList.Items[array[i]]); i++; } } }
public override Attachment Copy() { PathAttachment copy = new PathAttachment(this.Name); CopyTo(copy); copy.lengths = new float[lengths.Length]; Array.Copy(lengths, 0, copy.lengths, 0, lengths.Length); copy.closed = closed; copy.constantSpeed = constantSpeed; return(copy); }
public void Update() { PathAttachment path = this.target.Attachment as PathAttachment; if (path != null) { float rotateMix = this.rotateMix; float translateMix = this.translateMix; bool flag = translateMix > 0f; bool flag2 = rotateMix > 0f; if (flag || flag2) { bool flag6; PathConstraintData data = this.data; SpacingMode spacingMode = data.spacingMode; bool flag3 = spacingMode == SpacingMode.Length; RotateMode rotateMode = data.rotateMode; bool tangents = rotateMode == RotateMode.Tangent; bool flag5 = rotateMode == RotateMode.ChainScale; int count = this.bones.Count; int newSize = !tangents ? (count + 1) : count; Bone[] items = this.bones.Items; ExposedList <float> list = this.spaces.Resize(newSize); ExposedList <float> list2 = null; float spacing = this.spacing; if (flag5 || flag3) { if (flag5) { list2 = this.lengths.Resize(count); } int num6 = 0; int num7 = newSize - 1; while (num6 < num7) { Bone bone = items[num6]; float length = bone.data.length; if (length < 1E-05f) { if (flag5) { list2.Items[num6] = 0f; } list.Items[++num6] = 0f; } else { float num9 = length * bone.a; float num10 = length * bone.c; float num11 = (float)Math.Sqrt((double)((num9 * num9) + (num10 * num10))); if (flag5) { list2.Items[num6] = num11; } list.Items[++num6] = ((!flag3 ? spacing : (length + spacing)) * num11) / length; } } } else { for (int j = 1; j < newSize; j++) { list.Items[j] = spacing; } } float[] numArray = this.ComputeWorldPositions(path, newSize, tangents, data.positionMode == PositionMode.Percent, spacingMode == SpacingMode.Percent); float num13 = numArray[0]; float num14 = numArray[1]; float offsetRotation = data.offsetRotation; if (offsetRotation == 0f) { flag6 = rotateMode == RotateMode.Chain; } else { flag6 = false; Bone bone = this.target.bone; offsetRotation *= (((bone.a * bone.d) - (bone.b * bone.c)) <= 0f) ? -0.01745329f : 0.01745329f; } int index = 0; for (int i = 3; index < count; i += 3) { Bone bone3 = items[index]; bone3.worldX += (num13 - bone3.worldX) * translateMix; bone3.worldY += (num14 - bone3.worldY) * translateMix; float num18 = numArray[i]; float num19 = numArray[i + 1]; float x = num18 - num13; float y = num19 - num14; if (flag5) { float num22 = list2.Items[index]; if (num22 >= 1E-05f) { float num23 = (((((float)Math.Sqrt((double)((x * x) + (y * y)))) / num22) - 1f) * rotateMix) + 1f; bone3.a *= num23; bone3.c *= num23; } } num13 = num18; num14 = num19; if (flag2) { float num28; float num29; float num30; float a = bone3.a; float b = bone3.b; float c = bone3.c; float d = bone3.d; if (tangents) { num28 = numArray[i - 1]; } else if (list.Items[index + 1] < 1E-05f) { num28 = numArray[i + 2]; } else { num28 = MathUtils.Atan2(y, x); } num28 -= MathUtils.Atan2(c, a); if (flag6) { num29 = MathUtils.Cos(num28); num30 = MathUtils.Sin(num28); float length = bone3.data.length; num13 += ((length * ((num29 * a) - (num30 * c))) - x) * rotateMix; num14 += ((length * ((num30 * a) + (num29 * c))) - y) * rotateMix; } else { num28 += offsetRotation; } if (num28 > 3.141593f) { num28 -= 6.283185f; } else if (num28 < -3.141593f) { num28 += 6.283185f; } num28 *= rotateMix; num29 = MathUtils.Cos(num28); num30 = MathUtils.Sin(num28); bone3.a = (num29 * a) - (num30 * c); bone3.b = (num29 * b) - (num30 * d); bone3.c = (num30 * a) + (num29 * c); bone3.d = (num30 * b) + (num29 * d); } bone3.appliedValid = false; index++; } } } }
private float[] ComputeWorldPositions(PathAttachment path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing) { float[] numArray3; float num5; float num22; float num23; float num24; float num25; float num26; float num27; float num28; float num29; Slot target = this.target; float position = this.position; float[] items = this.spaces.Items; float[] output = this.positions.Resize((spacesCount * 3) + 2).Items; bool closed = path.Closed; int worldVerticesLength = path.WorldVerticesLength; int index = worldVerticesLength / 6; int num4 = -1; if (!path.ConstantSpeed) { float[] lengths = path.Lengths; index -= !closed ? 2 : 1; num5 = lengths[index]; if (percentPosition) { position *= num5; } if (percentSpacing) { for (int j = 0; j < spacesCount; j++) { items[j] *= num5; } } numArray3 = this.world.Resize(8).Items; int num7 = 0; int num8 = 0; int num9 = 0; while (num7 < spacesCount) { float num12; float num10 = items[num7]; position += num10; float p = position; if (closed) { p = p % num5; if (p < 0f) { p += num5; } num9 = 0; } else { if (p < 0f) { if (num4 != -2) { num4 = -2; path.ComputeWorldVertices(target, 2, 4, numArray3, 0, 2); } AddBeforePosition(p, numArray3, 0, output, num8); goto Label_0263; } if (p > num5) { if (num4 != -3) { num4 = -3; path.ComputeWorldVertices(target, worldVerticesLength - 6, 4, numArray3, 0, 2); } AddAfterPosition(p - num5, numArray3, 0, output, num8); goto Label_0263; } } Label_017D: num12 = lengths[num9]; if (p <= num12) { if (num9 == 0) { p /= num12; } else { float num13 = lengths[num9 - 1]; p = (p - num13) / (num12 - num13); } } else { num9++; goto Label_017D; } if (num9 != num4) { num4 = num9; if (closed && (num9 == index)) { path.ComputeWorldVertices(target, worldVerticesLength - 4, 4, numArray3, 0, 2); path.ComputeWorldVertices(target, 0, 4, numArray3, 4, 2); } else { path.ComputeWorldVertices(target, (num9 * 6) + 2, 8, numArray3, 0, 2); } } AddCurvePosition(p, numArray3[0], numArray3[1], numArray3[2], numArray3[3], numArray3[4], numArray3[5], numArray3[6], numArray3[7], output, num8, tangents || ((num7 > 0) && (num10 < 1E-05f))); Label_0263: num7++; num8 += 3; } return(output); } if (closed) { worldVerticesLength += 2; numArray3 = this.world.Resize(worldVerticesLength).Items; path.ComputeWorldVertices(target, 2, worldVerticesLength - 4, numArray3, 0, 2); path.ComputeWorldVertices(target, 0, 2, numArray3, worldVerticesLength - 4, 2); numArray3[worldVerticesLength - 2] = numArray3[0]; numArray3[worldVerticesLength - 1] = numArray3[1]; } else { index--; worldVerticesLength -= 4; numArray3 = this.world.Resize(worldVerticesLength).Items; path.ComputeWorldVertices(target, 2, worldVerticesLength, numArray3, 0, 2); } float[] numArray5 = this.curves.Resize(index).Items; num5 = 0f; float num14 = numArray3[0]; float num15 = numArray3[1]; float num16 = 0f; float num17 = 0f; float num18 = 0f; float num19 = 0f; float num20 = 0f; float num21 = 0f; int num30 = 0; for (int i = 2; num30 < index; i += 6) { num16 = numArray3[i]; num17 = numArray3[i + 1]; num18 = numArray3[i + 2]; num19 = numArray3[i + 3]; num20 = numArray3[i + 4]; num21 = numArray3[i + 5]; num22 = ((num14 - (num16 * 2f)) + num18) * 0.1875f; num23 = ((num15 - (num17 * 2f)) + num19) * 0.1875f; num24 = ((((num16 - num18) * 3f) - num14) + num20) * 0.09375f; num25 = ((((num17 - num19) * 3f) - num15) + num21) * 0.09375f; num26 = (num22 * 2f) + num24; num27 = (num23 * 2f) + num25; num28 = (((num16 - num14) * 0.75f) + num22) + (num24 * 0.1666667f); num29 = (((num17 - num15) * 0.75f) + num23) + (num25 * 0.1666667f); num5 += (float)Math.Sqrt((double)((num28 * num28) + (num29 * num29))); num28 += num26; num29 += num27; num26 += num24; num27 += num25; num5 += (float)Math.Sqrt((double)((num28 * num28) + (num29 * num29))); num28 += num26; num29 += num27; num5 += (float)Math.Sqrt((double)((num28 * num28) + (num29 * num29))); num28 += num26 + num24; num29 += num27 + num25; num5 += (float)Math.Sqrt((double)((num28 * num28) + (num29 * num29))); numArray5[num30] = num5; num14 = num20; num15 = num21; num30++; } if (percentPosition) { position *= num5; } if (percentSpacing) { for (int j = 0; j < spacesCount; j++) { items[j] *= num5; } } float[] segments = this.segments; float num33 = 0f; int num34 = 0; int o = 0; int num36 = 0; int num37 = 0; while (num34 < spacesCount) { float num40; float num38 = items[num34]; position += num38; float p = position; if (closed) { p = p % num5; if (p < 0f) { p += num5; } num36 = 0; } else { if (p < 0f) { AddBeforePosition(p, numArray3, 0, output, o); goto Label_0883; } if (p > num5) { AddAfterPosition(p - num5, numArray3, worldVerticesLength - 4, output, o); goto Label_0883; } } Label_05CD: num40 = numArray5[num36]; if (p <= num40) { if (num36 == 0) { p /= num40; } else { float num41 = numArray5[num36 - 1]; p = (p - num41) / (num40 - num41); } } else { num36++; goto Label_05CD; } if (num36 != num4) { num4 = num36; int num42 = num36 * 6; num14 = numArray3[num42]; num15 = numArray3[num42 + 1]; num16 = numArray3[num42 + 2]; num17 = numArray3[num42 + 3]; num18 = numArray3[num42 + 4]; num19 = numArray3[num42 + 5]; num20 = numArray3[num42 + 6]; num21 = numArray3[num42 + 7]; num22 = ((num14 - (num16 * 2f)) + num18) * 0.03f; num23 = ((num15 - (num17 * 2f)) + num19) * 0.03f; num24 = ((((num16 - num18) * 3f) - num14) + num20) * 0.006f; num25 = ((((num17 - num19) * 3f) - num15) + num21) * 0.006f; num26 = (num22 * 2f) + num24; num27 = (num23 * 2f) + num25; num28 = (((num16 - num14) * 0.3f) + num22) + (num24 * 0.1666667f); num29 = (((num17 - num15) * 0.3f) + num23) + (num25 * 0.1666667f); num33 = (float)Math.Sqrt((double)((num28 * num28) + (num29 * num29))); segments[0] = num33; for (num42 = 1; num42 < 8; num42++) { num28 += num26; num29 += num27; num26 += num24; num27 += num25; num33 += (float)Math.Sqrt((double)((num28 * num28) + (num29 * num29))); segments[num42] = num33; } num28 += num26; num29 += num27; num33 += (float)Math.Sqrt((double)((num28 * num28) + (num29 * num29))); segments[8] = num33; num28 += num26 + num24; num29 += num27 + num25; num33 += (float)Math.Sqrt((double)((num28 * num28) + (num29 * num29))); segments[9] = num33; num37 = 0; } p *= num33; while (true) { float num43 = segments[num37]; if (p <= num43) { if (num37 == 0) { p /= num43; } else { float num44 = segments[num37 - 1]; p = num37 + ((p - num44) / (num43 - num44)); } break; } num37++; } AddCurvePosition(p * 0.1f, num14, num15, num16, num17, num18, num19, num20, num21, output, o, tangents || ((num34 > 0) && (num38 < 1E-05f))); Label_0883: num34++; o += 3; } return(output); }
public void UpdateCache() { ExposedList <IUpdatable> exposedList = this.updateCache; exposedList.Clear(true); ExposedList <Bone> exposedList2 = this.bones; int i = 0; int count = exposedList2.Count; while (i < count) { exposedList2.Items[i].sorted = false; i++; } ExposedList <IkConstraint> exposedList3 = this.ikConstraintsSorted; exposedList3.Clear(true); exposedList3.AddRange(this.ikConstraints); int count2 = exposedList3.Count; int j = 0; int num = count2; while (j < num) { IkConstraint ikConstraint = exposedList3.Items[j]; Bone parent = ikConstraint.bones.Items[0].parent; int num2 = 0; while (parent != null) { parent = parent.parent; num2++; } ikConstraint.level = num2; j++; } for (int k = 1; k < count2; k++) { IkConstraint ikConstraint2 = exposedList3.Items[k]; int level = ikConstraint2.level; int l; for (l = k - 1; l >= 0; l--) { IkConstraint ikConstraint3 = exposedList3.Items[l]; if (ikConstraint3.level < level) { break; } exposedList3.Items[l + 1] = ikConstraint3; } exposedList3.Items[l + 1] = ikConstraint2; } int m = 0; int count3 = exposedList3.Count; while (m < count3) { IkConstraint ikConstraint4 = exposedList3.Items[m]; Bone target = ikConstraint4.target; this.SortBone(target); ExposedList <Bone> exposedList4 = ikConstraint4.bones; Bone bone = exposedList4.Items[0]; this.SortBone(bone); exposedList.Add(ikConstraint4); this.SortReset(bone.children); exposedList4.Items[exposedList4.Count - 1].sorted = true; m++; } ExposedList <PathConstraint> exposedList5 = this.pathConstraints; int n = 0; int count4 = exposedList5.Count; while (n < count4) { PathConstraint pathConstraint = exposedList5.Items[n]; Slot target2 = pathConstraint.target; int index = target2.data.index; Bone bone2 = target2.bone; if (this.skin != null) { this.SortPathConstraintAttachment(this.skin, index, bone2); } if (this.data.defaultSkin != null && this.data.defaultSkin != this.skin) { this.SortPathConstraintAttachment(this.data.defaultSkin, index, bone2); } int num3 = 0; int count5 = this.data.skins.Count; while (num3 < count5) { this.SortPathConstraintAttachment(this.data.skins.Items[num3], index, bone2); num3++; } PathAttachment pathAttachment = target2.Attachment as PathAttachment; if (pathAttachment != null) { this.SortPathConstraintAttachment(pathAttachment, bone2); } ExposedList <Bone> exposedList6 = pathConstraint.bones; int count6 = exposedList6.Count; for (int num4 = 0; num4 < count6; num4++) { this.SortBone(exposedList6.Items[num4]); } exposedList.Add(pathConstraint); for (int num5 = 0; num5 < count6; num5++) { this.SortReset(exposedList6.Items[num5].children); } for (int num6 = 0; num6 < count6; num6++) { exposedList6.Items[num6].sorted = true; } n++; } ExposedList <TransformConstraint> exposedList7 = this.transformConstraints; int num7 = 0; int count7 = exposedList7.Count; while (num7 < count7) { TransformConstraint transformConstraint = exposedList7.Items[num7]; this.SortBone(transformConstraint.target); ExposedList <Bone> exposedList8 = transformConstraint.bones; int count8 = exposedList8.Count; for (int num8 = 0; num8 < count8; num8++) { this.SortBone(exposedList8.Items[num8]); } exposedList.Add(transformConstraint); for (int num9 = 0; num9 < count8; num9++) { this.SortReset(exposedList8.Items[num9].children); } for (int num10 = 0; num10 < count8; num10++) { exposedList8.Items[num10].sorted = true; } num7++; } int num11 = 0; int count9 = exposedList2.Count; while (num11 < count9) { this.SortBone(exposedList2.Items[num11]); num11++; } }
public static void DrawPath (Slot s, PathAttachment p, Transform t, bool includeName) { int worldVerticesLength = p.WorldVerticesLength; if (pathVertexBuffer == null || pathVertexBuffer.Length < worldVerticesLength) pathVertexBuffer = new float[worldVerticesLength]; float[] pv = pathVertexBuffer; p.ComputeWorldVertices(s, pv); var ocolor = Handles.color; Handles.color = SpineHandles.PathColor; Matrix4x4 m = t.localToWorldMatrix; const int step = 6; int n = worldVerticesLength - step; Vector3 p0, p1, p2, p3; for (int i = 2; i < n; i += step) { p0 = m.MultiplyPoint(new Vector3(pv[i], pv[i+1])); p1 = m.MultiplyPoint(new Vector3(pv[i+2], pv[i+3])); p2 = m.MultiplyPoint(new Vector3(pv[i+4], pv[i+5])); p3 = m.MultiplyPoint(new Vector3(pv[i+6], pv[i+7])); DrawCubicBezier(p0, p1, p2, p3); } n += step; if (p.Closed) { p0 = m.MultiplyPoint(new Vector3(pv[n - 4], pv[n - 3])); p1 = m.MultiplyPoint(new Vector3(pv[n - 2], pv[n - 1])); p2 = m.MultiplyPoint(new Vector3(pv[0], pv[1])); p3 = m.MultiplyPoint(new Vector3(pv[2], pv[3])); DrawCubicBezier(p0, p1, p2, p3); } const float endCapSize = 0.05f; Vector3 firstPoint = m.MultiplyPoint(new Vector3(pv[2], pv[3])); Handles.DotCap(0, firstPoint, Quaternion.identity, endCapSize * HandleUtility.GetHandleSize(firstPoint)); // if (!p.Closed) Handles.DotCap(0, m.MultiplyPoint(new Vector3(pv[n - 4], pv[n - 3])), q, endCapSize); if (includeName) Handles.Label(firstPoint + new Vector3(0,0.1f), p.Name, PathNameStyle); Handles.color = ocolor; }
float[] ComputeWorldPositions(PathAttachment path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing) { Slot target = this.target; float position = this.position; float[] spacesItems = this.spaces.Items, output = this.positions.Resize(spacesCount * 3 + 2).Items, world; bool closed = path.Closed; int verticesLength = path.WorldVerticesLength, curveCount = verticesLength / 6, prevCurve = NONE; float pathLength = 0; if (!path.ConstantSpeed) { float[] lengths = path.Lengths; curveCount -= closed ? 1 : 2; pathLength = lengths[curveCount]; if (percentPosition) { position *= pathLength; } if (percentSpacing) { for (int i = 1; i < spacesCount; i++) { spacesItems[i] *= pathLength; } } world = this.world.Resize(8).Items; for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { float space = spacesItems[i]; position += space; float p = position; if (closed) { p %= pathLength; if (p < 0) { p += pathLength; } curve = 0; } else if (p < 0) { if (prevCurve != BEFORE) { prevCurve = BEFORE; path.ComputeWorldVertices(target, 2, 4, world, 0, 2); } AddBeforePosition(p, world, 0, output, o); continue; } else if (p > pathLength) { if (prevCurve != AFTER) { prevCurve = AFTER; path.ComputeWorldVertices(target, verticesLength - 6, 4, world, 0, 2); } AddAfterPosition(p - pathLength, world, 0, output, o); continue; } // Determine curve containing position. for (;; curve++) { float length = lengths[curve]; if (p > length) { continue; } if (curve == 0) { p /= length; } else { float prev = lengths[curve - 1]; p = (p - prev) / (length - prev); } break; } if (curve != prevCurve) { prevCurve = curve; if (closed && curve == curveCount) { path.ComputeWorldVertices(target, verticesLength - 4, 4, world, 0, 2); path.ComputeWorldVertices(target, 0, 4, world, 4, 2); } else { path.ComputeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2); } } AddCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], output, o, tangents || (i > 0 && space < PathConstraint.Epsilon)); } return(output); } // World vertices. if (closed) { verticesLength += 2; world = this.world.Resize(verticesLength).Items; path.ComputeWorldVertices(target, 2, verticesLength - 4, world, 0, 2); path.ComputeWorldVertices(target, 0, 2, world, verticesLength - 4, 2); world[verticesLength - 2] = world[0]; world[verticesLength - 1] = world[1]; } else { curveCount--; verticesLength -= 4; world = this.world.Resize(verticesLength).Items; path.ComputeWorldVertices(target, 2, verticesLength, world, 0, 2); } // Curve lengths. float[] curves = this.curves.Resize(curveCount).Items; pathLength = 0; float x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy; for (int i = 0, w = 2; i < curveCount; i++, w += 6) { cx1 = world[w]; cy1 = world[w + 1]; cx2 = world[w + 2]; cy2 = world[w + 3]; x2 = world[w + 4]; y2 = world[w + 5]; tmpx = (x1 - cx1 * 2 + cx2) * 0.1875f; tmpy = (y1 - cy1 * 2 + cy2) * 0.1875f; dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375f; dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375f; ddfx = tmpx * 2 + dddfx; ddfy = tmpy * 2 + dddfy; dfx = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f; dfy = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f; pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); dfx += ddfx; dfy += ddfy; ddfx += dddfx; ddfy += dddfy; pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); dfx += ddfx; dfy += ddfy; pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); dfx += ddfx + dddfx; dfy += ddfy + dddfy; pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); curves[i] = pathLength; x1 = x2; y1 = y2; } if (percentPosition) { position *= pathLength; } else { position *= pathLength / path.lengths[curveCount - 1]; } if (percentSpacing) { for (int i = 1; i < spacesCount; i++) { spacesItems[i] *= pathLength; } } float[] segments = this.segments; float curveLength = 0; for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { float space = spacesItems[i]; position += space; float p = position; if (closed) { p %= pathLength; if (p < 0) { p += pathLength; } curve = 0; } else if (p < 0) { AddBeforePosition(p, world, 0, output, o); continue; } else if (p > pathLength) { AddAfterPosition(p - pathLength, world, verticesLength - 4, output, o); continue; } // Determine curve containing position. for (;; curve++) { float length = curves[curve]; if (p > length) { continue; } if (curve == 0) { p /= length; } else { float prev = curves[curve - 1]; p = (p - prev) / (length - prev); } break; } // Curve segment lengths. if (curve != prevCurve) { prevCurve = curve; int ii = curve * 6; x1 = world[ii]; y1 = world[ii + 1]; cx1 = world[ii + 2]; cy1 = world[ii + 3]; cx2 = world[ii + 4]; cy2 = world[ii + 5]; x2 = world[ii + 6]; y2 = world[ii + 7]; tmpx = (x1 - cx1 * 2 + cx2) * 0.03f; tmpy = (y1 - cy1 * 2 + cy2) * 0.03f; dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006f; dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006f; ddfx = tmpx * 2 + dddfx; ddfy = tmpy * 2 + dddfy; dfx = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f; dfy = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f; curveLength = (float)Math.Sqrt(dfx * dfx + dfy * dfy); segments[0] = curveLength; for (ii = 1; ii < 8; ii++) { dfx += ddfx; dfy += ddfy; ddfx += dddfx; ddfy += dddfy; curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); segments[ii] = curveLength; } dfx += ddfx; dfy += ddfy; curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); segments[8] = curveLength; dfx += ddfx + dddfx; dfy += ddfy + dddfy; curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); segments[9] = curveLength; segment = 0; } // Weight by segment length. p *= curveLength; for (;; segment++) { float length = segments[segment]; if (p > length) { continue; } if (segment == 0) { p /= length; } else { float prev = segments[segment - 1]; p = segment + (p - prev) / (length - prev); } break; } AddCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, output, o, tangents || (i > 0 && space < PathConstraint.Epsilon)); } return(output); }
private Attachment ReadAttachment(Dictionary <String, Object> map, Skin skin, int slotIndex, String name) { var scale = this.Scale; name = GetString(map, "name", name); var typeName = GetString(map, "type", "region"); if (typeName == "skinnedmesh") { typeName = "weightedmesh"; } if (typeName == "weightedmesh") { typeName = "mesh"; } if (typeName == "weightedlinkedmesh") { typeName = "linkedmesh"; } var type = (AttachmentType)Enum.Parse(typeof(AttachmentType), typeName, true); String path = GetString(map, "path", name); switch (type) { case AttachmentType.Region: RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path); if (region == null) { return(null); } region.Path = path; region.x = GetFloat(map, "x", 0) * scale; region.y = GetFloat(map, "y", 0) * scale; region.scaleX = GetFloat(map, "scaleX", 1); region.scaleY = GetFloat(map, "scaleY", 1); region.rotation = GetFloat(map, "rotation", 0); region.width = GetFloat(map, "width", 32) * scale; region.height = GetFloat(map, "height", 32) * scale; region.UpdateOffset(); if (map.ContainsKey("color")) { var color = (String)map["color"]; region.r = ToColor(color, 0); region.g = ToColor(color, 1); region.b = ToColor(color, 2); region.a = ToColor(color, 3); } region.UpdateOffset(); return(region); case AttachmentType.Boundingbox: BoundingBoxAttachment box = attachmentLoader.NewBoundingBoxAttachment(skin, name); if (box == null) { return(null); } ReadVertices(map, box, GetInt(map, "vertexCount", 0) << 1); return(box); case AttachmentType.Mesh: case AttachmentType.Linkedmesh: { MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path); if (mesh == null) { return(null); } mesh.Path = path; if (map.ContainsKey("color")) { var color = (String)map["color"]; mesh.r = ToColor(color, 0); mesh.g = ToColor(color, 1); mesh.b = ToColor(color, 2); mesh.a = ToColor(color, 3); } mesh.Width = GetFloat(map, "width", 0) * scale; mesh.Height = GetFloat(map, "height", 0) * scale; String parent = GetString(map, "parent", null); if (parent != null) { mesh.InheritDeform = GetBoolean(map, "deform", true); linkedMeshes.Add(new LinkedMesh(mesh, GetString(map, "skin", null), slotIndex, parent)); return(mesh); } float[] uvs = GetFloatArray(map, "uvs", 1); ReadVertices(map, mesh, uvs.Length); mesh.triangles = GetIntArray(map, "triangles"); mesh.regionUVs = uvs; mesh.UpdateUVs(); if (map.ContainsKey("hull")) { mesh.HullLength = GetInt(map, "hull", 0) * 2; } if (map.ContainsKey("edges")) { mesh.Edges = GetIntArray(map, "edges"); } return(mesh); } case AttachmentType.Path: { PathAttachment pathAttachment = attachmentLoader.NewPathAttachment(skin, name); if (pathAttachment == null) { return(null); } pathAttachment.closed = GetBoolean(map, "closed", false); pathAttachment.constantSpeed = GetBoolean(map, "constantSpeed", true); int vertexCount = GetInt(map, "vertexCount", 0); ReadVertices(map, pathAttachment, vertexCount << 1); // potential BOZO see Java impl pathAttachment.lengths = GetFloatArray(map, "lengths", scale); return(pathAttachment); } } return(null); }
private Attachment ReadAttachment(Stream input, SkeletonData skeletonData, Skin skin, int slotIndex, string attachmentName, bool nonessential) { float scale = Scale; string text = ReadString(input); if (text == null) { text = attachmentName; } switch (input.ReadByte()) { case 0: { string text2 = ReadString(input); float rotation = ReadFloat(input); float num3 = ReadFloat(input); float num4 = ReadFloat(input); float scaleX = ReadFloat(input); float scaleY = ReadFloat(input); float num5 = ReadFloat(input); float num6 = ReadFloat(input); int num7 = ReadInt(input); if (text2 == null) { text2 = text; } RegionAttachment regionAttachment = attachmentLoader.NewRegionAttachment(skin, text, text2); if (regionAttachment == null) { return(null); } regionAttachment.Path = text2; regionAttachment.x = num3 * scale; regionAttachment.y = num4 * scale; regionAttachment.scaleX = scaleX; regionAttachment.scaleY = scaleY; regionAttachment.rotation = rotation; regionAttachment.width = num5 * scale; regionAttachment.height = num6 * scale; regionAttachment.r = (float)((num7 & 4278190080u) >> 24) / 255f; regionAttachment.g = (float)((num7 & 0xFF0000) >> 16) / 255f; regionAttachment.b = (float)((num7 & 0xFF00) >> 8) / 255f; regionAttachment.a = (float)(num7 & 0xFF) / 255f; regionAttachment.UpdateOffset(); return(regionAttachment); } case 1: { int num20 = ReadVarint(input, optimizePositive: true); Vertices vertices4 = ReadVertices(input, num20); if (nonessential) { ReadInt(input); } BoundingBoxAttachment boundingBoxAttachment = attachmentLoader.NewBoundingBoxAttachment(skin, text); if (boundingBoxAttachment == null) { return(null); } boundingBoxAttachment.worldVerticesLength = num20 << 1; boundingBoxAttachment.vertices = vertices4.vertices; boundingBoxAttachment.bones = vertices4.bones; return(boundingBoxAttachment); } case 2: { string text3 = ReadString(input); int num8 = ReadInt(input); int num9 = ReadVarint(input, optimizePositive: true); float[] regionUVs = ReadFloatArray(input, num9 << 1, 1f); int[] triangles = ReadShortArray(input); Vertices vertices2 = ReadVertices(input, num9); int num10 = ReadVarint(input, optimizePositive: true); int[] edges = null; float num11 = 0f; float num12 = 0f; if (nonessential) { edges = ReadShortArray(input); num11 = ReadFloat(input); num12 = ReadFloat(input); } if (text3 == null) { text3 = text; } MeshAttachment meshAttachment = attachmentLoader.NewMeshAttachment(skin, text, text3); if (meshAttachment == null) { return(null); } meshAttachment.Path = text3; meshAttachment.r = (float)((num8 & 4278190080u) >> 24) / 255f; meshAttachment.g = (float)((num8 & 0xFF0000) >> 16) / 255f; meshAttachment.b = (float)((num8 & 0xFF00) >> 8) / 255f; meshAttachment.a = (float)(num8 & 0xFF) / 255f; meshAttachment.bones = vertices2.bones; meshAttachment.vertices = vertices2.vertices; meshAttachment.WorldVerticesLength = num9 << 1; meshAttachment.triangles = triangles; meshAttachment.regionUVs = regionUVs; meshAttachment.UpdateUVs(); meshAttachment.HullLength = num10 << 1; if (nonessential) { meshAttachment.Edges = edges; meshAttachment.Width = num11 * scale; meshAttachment.Height = num12 * scale; } return(meshAttachment); } case 3: { string text4 = ReadString(input); int num13 = ReadInt(input); string skin2 = ReadString(input); string parent = ReadString(input); bool inheritDeform = ReadBoolean(input); float num14 = 0f; float num15 = 0f; if (nonessential) { num14 = ReadFloat(input); num15 = ReadFloat(input); } if (text4 == null) { text4 = text; } MeshAttachment meshAttachment2 = attachmentLoader.NewMeshAttachment(skin, text, text4); if (meshAttachment2 == null) { return(null); } meshAttachment2.Path = text4; meshAttachment2.r = (float)((num13 & 4278190080u) >> 24) / 255f; meshAttachment2.g = (float)((num13 & 0xFF0000) >> 16) / 255f; meshAttachment2.b = (float)((num13 & 0xFF00) >> 8) / 255f; meshAttachment2.a = (float)(num13 & 0xFF) / 255f; meshAttachment2.inheritDeform = inheritDeform; if (nonessential) { meshAttachment2.Width = num14 * scale; meshAttachment2.Height = num15 * scale; } linkedMeshes.Add(new SkeletonJson.LinkedMesh(meshAttachment2, skin2, slotIndex, parent)); return(meshAttachment2); } case 4: { bool closed = ReadBoolean(input); bool constantSpeed = ReadBoolean(input); int num16 = ReadVarint(input, optimizePositive: true); Vertices vertices3 = ReadVertices(input, num16); float[] array = new float[num16 / 3]; int i = 0; for (int num17 = array.Length; i < num17; i++) { array[i] = ReadFloat(input) * scale; } if (nonessential) { ReadInt(input); } PathAttachment pathAttachment = attachmentLoader.NewPathAttachment(skin, text); if (pathAttachment == null) { return(null); } pathAttachment.closed = closed; pathAttachment.constantSpeed = constantSpeed; pathAttachment.worldVerticesLength = num16 << 1; pathAttachment.vertices = vertices3.vertices; pathAttachment.bones = vertices3.bones; pathAttachment.lengths = array; return(pathAttachment); } case 5: { float rotation2 = ReadFloat(input); float num18 = ReadFloat(input); float num19 = ReadFloat(input); if (nonessential) { ReadInt(input); } PointAttachment pointAttachment = attachmentLoader.NewPointAttachment(skin, text); if (pointAttachment == null) { return(null); } pointAttachment.x = num18 * scale; pointAttachment.y = num19 * scale; pointAttachment.rotation = rotation2; return(pointAttachment); } case 6: { int num = ReadVarint(input, optimizePositive: true); int num2 = ReadVarint(input, optimizePositive: true); Vertices vertices = ReadVertices(input, num2); if (nonessential) { ReadInt(input); } ClippingAttachment clippingAttachment = attachmentLoader.NewClippingAttachment(skin, text); if (clippingAttachment == null) { return(null); } clippingAttachment.EndSlot = skeletonData.slots.Items[num]; clippingAttachment.worldVerticesLength = num2 << 1; clippingAttachment.vertices = vertices.vertices; clippingAttachment.bones = vertices.bones; return(clippingAttachment); } default: return(null); } }
private float[] ComputeWorldPositions(PathAttachment path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing) { Slot slot = this.target; float num = this.position; float[] items = this.spaces.Items; float[] items2 = this.positions.Resize(spacesCount * 3 + 2).Items; bool closed = path.Closed; int num2 = path.WorldVerticesLength; int num3 = num2 / 6; int num4 = -1; float num5; float[] items3; if (!path.ConstantSpeed) { float[] array = path.Lengths; num3 -= ((!closed) ? 2 : 1); num5 = array[num3]; if (percentPosition) { num *= num5; } if (percentSpacing) { for (int i = 0; i < spacesCount; i++) { items[i] *= num5; } } items3 = this.world.Resize(8).Items; int j = 0; int num6 = 0; int num7 = 0; while (j < spacesCount) { float num8 = items[j]; num += num8; float num9 = num; if (closed) { num9 %= num5; if (num9 < 0f) { num9 += num5; } num7 = 0; goto IL_178; } if (num9 < 0f) { if (num4 != -2) { num4 = -2; path.ComputeWorldVertices(slot, 2, 4, items3, 0); } this.AddBeforePosition(num9, items3, 0, items2, num6); } else { if (num9 <= num5) { goto IL_178; } if (num4 != -3) { num4 = -3; path.ComputeWorldVertices(slot, num2 - 6, 4, items3, 0); } this.AddAfterPosition(num9 - num5, items3, 0, items2, num6); } IL_261: j++; num6 += 3; continue; IL_178: float num10; for (;;) { num10 = array[num7]; if (num9 <= num10) { break; } num7++; } if (num7 == 0) { num9 /= num10; } else { float num11 = array[num7 - 1]; num9 = (num9 - num11) / (num10 - num11); } if (num7 != num4) { num4 = num7; if (closed && num7 == num3) { path.ComputeWorldVertices(slot, num2 - 4, 4, items3, 0); path.ComputeWorldVertices(slot, 0, 4, items3, 4); } else { path.ComputeWorldVertices(slot, num7 * 6 + 2, 8, items3, 0); } } this.AddCurvePosition(num9, items3[0], items3[1], items3[2], items3[3], items3[4], items3[5], items3[6], items3[7], items2, num6, tangents || (j > 0 && num8 == 0f)); goto IL_261; } return(items2); } if (closed) { num2 += 2; items3 = this.world.Resize(num2).Items; path.ComputeWorldVertices(slot, 2, num2 - 4, items3, 0); path.ComputeWorldVertices(slot, 0, 2, items3, num2 - 4); items3[num2 - 2] = items3[0]; items3[num2 - 1] = items3[1]; } else { num3--; num2 -= 4; items3 = this.world.Resize(num2).Items; path.ComputeWorldVertices(slot, 2, num2, items3, 0); } float[] items4 = this.curves.Resize(num3).Items; num5 = 0f; float num12 = items3[0]; float num13 = items3[1]; float num14 = 0f; float num15 = 0f; float num16 = 0f; float num17 = 0f; float num18 = 0f; float num19 = 0f; int k = 0; int num20 = 2; while (k < num3) { num14 = items3[num20]; num15 = items3[num20 + 1]; num16 = items3[num20 + 2]; num17 = items3[num20 + 3]; num18 = items3[num20 + 4]; num19 = items3[num20 + 5]; float num21 = (num12 - num14 * 2f + num16) * 0.1875f; float num22 = (num13 - num15 * 2f + num17) * 0.1875f; float num23 = ((num14 - num16) * 3f - num12 + num18) * 0.09375f; float num24 = ((num15 - num17) * 3f - num13 + num19) * 0.09375f; float num25 = num21 * 2f + num23; float num26 = num22 * 2f + num24; float num27 = (num14 - num12) * 0.75f + num21 + num23 * 0.166666672f; float num28 = (num15 - num13) * 0.75f + num22 + num24 * 0.166666672f; num5 += (float)Math.Sqrt((double)(num27 * num27 + num28 * num28)); num27 += num25; num28 += num26; num25 += num23; num26 += num24; num5 += (float)Math.Sqrt((double)(num27 * num27 + num28 * num28)); num27 += num25; num28 += num26; num5 += (float)Math.Sqrt((double)(num27 * num27 + num28 * num28)); num27 += num25 + num23; num28 += num26 + num24; num5 += (float)Math.Sqrt((double)(num27 * num27 + num28 * num28)); items4[k] = num5; num12 = num18; num13 = num19; k++; num20 += 6; } if (percentPosition) { num *= num5; } if (percentSpacing) { for (int l = 0; l < spacesCount; l++) { items[l] *= num5; } } float[] array2 = this.segments; float num29 = 0f; int m = 0; int num30 = 0; int num31 = 0; int num32 = 0; while (m < spacesCount) { float num33 = items[m]; num += num33; float num34 = num; if (closed) { num34 %= num5; if (num34 < 0f) { num34 += num5; } num31 = 0; goto IL_5C5; } if (num34 < 0f) { this.AddBeforePosition(num34, items3, 0, items2, num30); } else { if (num34 <= num5) { goto IL_5C5; } this.AddAfterPosition(num34 - num5, items3, num2 - 4, items2, num30); } IL_881: m++; num30 += 3; continue; IL_5C5: float num35; for (;;) { num35 = items4[num31]; if (num34 <= num35) { break; } num31++; } if (num31 == 0) { num34 /= num35; } else { float num36 = items4[num31 - 1]; num34 = (num34 - num36) / (num35 - num36); } if (num31 != num4) { num4 = num31; int n = num31 * 6; num12 = items3[n]; num13 = items3[n + 1]; num14 = items3[n + 2]; num15 = items3[n + 3]; num16 = items3[n + 4]; num17 = items3[n + 5]; num18 = items3[n + 6]; num19 = items3[n + 7]; float num21 = (num12 - num14 * 2f + num16) * 0.03f; float num22 = (num13 - num15 * 2f + num17) * 0.03f; float num23 = ((num14 - num16) * 3f - num12 + num18) * 0.006f; float num24 = ((num15 - num17) * 3f - num13 + num19) * 0.006f; float num25 = num21 * 2f + num23; float num26 = num22 * 2f + num24; float num27 = (num14 - num12) * 0.3f + num21 + num23 * 0.166666672f; float num28 = (num15 - num13) * 0.3f + num22 + num24 * 0.166666672f; num29 = (float)Math.Sqrt((double)(num27 * num27 + num28 * num28)); array2[0] = num29; for (n = 1; n < 8; n++) { num27 += num25; num28 += num26; num25 += num23; num26 += num24; num29 += (float)Math.Sqrt((double)(num27 * num27 + num28 * num28)); array2[n] = num29; } num27 += num25; num28 += num26; num29 += (float)Math.Sqrt((double)(num27 * num27 + num28 * num28)); array2[8] = num29; num27 += num25 + num23; num28 += num26 + num24; num29 += (float)Math.Sqrt((double)(num27 * num27 + num28 * num28)); array2[9] = num29; num32 = 0; } num34 *= num29; float num37; for (;;) { num37 = array2[num32]; if (num34 <= num37) { break; } num32++; } if (num32 == 0) { num34 /= num37; } else { float num38 = array2[num32 - 1]; num34 = (float)num32 + (num34 - num38) / (num37 - num38); } this.AddCurvePosition(num34 * 0.1f, num12, num13, num14, num15, num16, num17, num18, num19, items2, num30, tangents || (m > 0 && num33 == 0f)); goto IL_881; } return(items2); }
public void Update() { PathAttachment pathAttachment = this.target.Attachment as PathAttachment; if (pathAttachment == null) { return; } float num = this.rotateMix; float num2 = this.translateMix; bool flag = num2 > 0f; bool flag2 = num > 0f; if (!flag && !flag2) { return; } PathConstraintData pathConstraintData = this.data; SpacingMode spacingMode = pathConstraintData.spacingMode; bool flag3 = spacingMode == SpacingMode.Length; RotateMode rotateMode = pathConstraintData.rotateMode; bool flag4 = rotateMode == RotateMode.Tangent; bool flag5 = rotateMode == RotateMode.ChainScale; int count = this.bones.Count; int num3 = (!flag4) ? (count + 1) : count; Bone[] items = this.bones.Items; ExposedList <float> exposedList = this.spaces.Resize(num3); ExposedList <float> exposedList2 = null; float num4 = this.spacing; if (flag5 || flag3) { if (flag5) { exposedList2 = this.lengths.Resize(count); } int i = 0; int num5 = num3 - 1; while (i < num5) { Bone bone = items[i]; float num6 = bone.data.length; float num7 = num6 * bone.a; float num8 = num6 * bone.c; num6 = (float)Math.Sqrt((double)(num7 * num7 + num8 * num8)); if (flag5) { exposedList2.Items[i] = num6; } exposedList.Items[++i] = ((!flag3) ? num4 : Math.Max(0f, num6 + num4)); } } else { for (int j = 1; j < num3; j++) { exposedList.Items[j] = num4; } } float[] array = this.ComputeWorldPositions(pathAttachment, num3, flag4, pathConstraintData.positionMode == PositionMode.Percent, spacingMode == SpacingMode.Percent); Skeleton skeleton = this.target.Skeleton; float x = skeleton.x; float y = skeleton.y; float num9 = array[0]; float num10 = array[1]; float offsetRotation = pathConstraintData.offsetRotation; bool flag6 = rotateMode == RotateMode.Chain && offsetRotation == 0f; int k = 0; int num11 = 3; while (k < count) { Bone bone2 = items[k]; bone2.worldX += (num9 - x - bone2.worldX) * num2; bone2.worldY += (num10 - y - bone2.worldY) * num2; float num12 = array[num11]; float num13 = array[num11 + 1]; float num14 = num12 - num9; float num15 = num13 - num10; if (flag5) { float num16 = exposedList2.Items[k]; if (num16 != 0f) { float num17 = ((float)Math.Sqrt((double)(num14 * num14 + num15 * num15)) / num16 - 1f) * num + 1f; bone2.a *= num17; bone2.c *= num17; } } num9 = num12; num10 = num13; if (flag2) { float a = bone2.a; float b = bone2.b; float c = bone2.c; float d = bone2.d; float num18; if (flag4) { num18 = array[num11 - 1]; } else if (exposedList.Items[k + 1] == 0f) { num18 = array[num11 + 2]; } else { num18 = MathUtils.Atan2(num15, num14); } num18 -= MathUtils.Atan2(c, a) - offsetRotation * 0.0174532924f; float num19; float num20; if (flag6) { num19 = MathUtils.Cos(num18); num20 = MathUtils.Sin(num18); float length = bone2.data.length; num9 += (length * (num19 * a - num20 * c) - num14) * num; num10 += (length * (num20 * a + num19 * c) - num15) * num; } if (num18 > 3.14159274f) { num18 -= 6.28318548f; } else if (num18 < -3.14159274f) { num18 += 6.28318548f; } num18 *= num; num19 = MathUtils.Cos(num18); num20 = MathUtils.Sin(num18); bone2.a = num19 * a - num20 * c; bone2.b = num19 * b - num20 * d; bone2.c = num20 * a + num19 * c; bone2.d = num20 * b + num19 * d; } k++; num11 += 3; } }
/// <returns>May be null to not load any attachment</returns> public PathAttachment NewPathAttachment(Skin skin, string name) { var attachment = new PathAttachment(name); return(attachment); }
public void Update() { PathAttachment attachment = target.Attachment as PathAttachment; if (attachment == null) { return; } float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY; if (mixRotate == 0 && mixX == 0 && mixY == 0) { return; } PathConstraintData data = this.data; bool tangents = data.rotateMode == RotateMode.Tangent, scale = data.rotateMode == RotateMode.ChainScale; int boneCount = this.bones.Count, spacesCount = tangents ? boneCount : boneCount + 1; Bone[] bonesItems = this.bones.Items; float[] spaces = this.spaces.Resize(spacesCount).Items, lengths = scale ? this.lengths.Resize(boneCount).Items : null; float spacing = this.spacing; switch (data.spacingMode) { case SpacingMode.Percent: if (scale) { for (int i = 0, n = spacesCount - 1; i < n; i++) { Bone bone = bonesItems[i]; float setupLength = bone.data.length; if (setupLength < PathConstraint.Epsilon) { lengths[i] = 0; } else { float x = setupLength * bone.a, y = setupLength * bone.c; lengths[i] = (float)Math.Sqrt(x * x + y * y); } } } ArraysFill(spaces, 1, spacesCount, spacing); break; case SpacingMode.Proportional: { float sum = 0; for (int i = 0, n = spacesCount - 1; i < n;) { Bone bone = bonesItems[i]; float setupLength = bone.data.length; if (setupLength < PathConstraint.Epsilon) { if (scale) { lengths[i] = 0; } spaces[++i] = spacing; } else { float x = setupLength * bone.a, y = setupLength * bone.c; float length = (float)Math.Sqrt(x * x + y * y); if (scale) { lengths[i] = length; } spaces[++i] = length; sum += length; } } if (sum > 0) { sum = spacesCount / sum * spacing; for (int i = 1; i < spacesCount; i++) { spaces[i] *= sum; } } break; } default: { bool lengthSpacing = data.spacingMode == SpacingMode.Length; for (int i = 0, n = spacesCount - 1; i < n;) { Bone bone = bonesItems[i]; float setupLength = bone.data.length; if (setupLength < PathConstraint.Epsilon) { if (scale) { lengths[i] = 0; } spaces[++i] = spacing; } else { float x = setupLength * bone.a, y = setupLength * bone.c; float length = (float)Math.Sqrt(x * x + y * y); if (scale) { lengths[i] = length; } spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; } } break; } } float[] positions = ComputeWorldPositions(attachment, spacesCount, tangents); float boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; bool tip; if (offsetRotation == 0) { tip = data.rotateMode == RotateMode.Chain; } else { tip = false; Bone p = target.bone; 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) { Bone bone = bonesItems[i]; bone.worldX += (boneX - bone.worldX) * mixX; bone.worldY += (boneY - bone.worldY) * mixY; float x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; if (scale) { float length = lengths[i]; if (length >= PathConstraint.Epsilon) { float s = ((float)Math.Sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1; bone.a *= s; bone.c *= s; } } boneX = x; boneY = y; if (mixRotate > 0) { float a = bone.a, b = bone.b, c = bone.c, d = bone.d, r, cos, sin; if (tangents) { r = positions[p - 1]; } else if (spaces[i + 1] < PathConstraint.Epsilon) { r = positions[p + 2]; } else { r = MathUtils.Atan2(dy, dx); } r -= MathUtils.Atan2(c, a); if (tip) { cos = MathUtils.Cos(r); sin = MathUtils.Sin(r); float length = bone.data.length; boneX += (length * (cos * a - sin * c) - dx) * mixRotate; boneY += (length * (sin * a + cos * c) - dy) * mixRotate; } else { r += offsetRotation; } if (r > MathUtils.PI) { r -= MathUtils.PI2; } else if (r < -MathUtils.PI) // { r += MathUtils.PI2; } r *= mixRotate; cos = MathUtils.Cos(r); sin = MathUtils.Sin(r); bone.a = cos * a - sin * c; bone.b = cos * b - sin * d; bone.c = sin * a + cos * c; bone.d = sin * b + cos * d; } bone.UpdateAppliedTransform(); } }
private float[] ComputeWorldPositions(PathAttachment path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing) { Slot slot = target; float num = position; float[] items = spaces.Items; float[] items2 = positions.Resize(spacesCount * 3 + 2).Items; bool closed = path.Closed; int worldVerticesLength = path.WorldVerticesLength; int num2 = worldVerticesLength / 6; int num3 = -1; float[] items3; float num4; if (!path.ConstantSpeed) { float[] array = path.Lengths; num2 -= (closed ? 1 : 2); num4 = array[num2]; if (percentPosition) { num *= num4; } if (percentSpacing) { for (int i = 0; i < spacesCount; i++) { items[i] *= num4; } } items3 = world.Resize(8).Items; int j = 0; int k = 0; int num5 = 0; for (; j < spacesCount; j++, k += 3) { float num6 = items[j]; num += num6; float num7 = num; if (closed) { num7 %= num4; if (num7 < 0f) { num7 += num4; } num5 = 0; } else { if (num7 < 0f) { if (num3 != -2) { num3 = -2; path.ComputeWorldVertices(slot, 2, 4, items3, 0); } AddBeforePosition(num7, items3, 0, items2, k); continue; } if (num7 > num4) { if (num3 != -3) { num3 = -3; path.ComputeWorldVertices(slot, worldVerticesLength - 6, 4, items3, 0); } AddAfterPosition(num7 - num4, items3, 0, items2, k); continue; } } float num8; while (true) { num8 = array[num5]; if (!(num7 > num8)) { break; } num5++; } if (num5 == 0) { num7 /= num8; } else { float num9 = array[num5 - 1]; num7 = (num7 - num9) / (num8 - num9); } if (num5 != num3) { num3 = num5; if (closed && num5 == num2) { path.ComputeWorldVertices(slot, worldVerticesLength - 4, 4, items3, 0); path.ComputeWorldVertices(slot, 0, 4, items3, 4); } else { path.ComputeWorldVertices(slot, num5 * 6 + 2, 8, items3, 0); } } AddCurvePosition(num7, items3[0], items3[1], items3[2], items3[3], items3[4], items3[5], items3[6], items3[7], items2, k, tangents || (j > 0 && num6 == 0f)); } return(items2); } if (closed) { worldVerticesLength += 2; items3 = world.Resize(worldVerticesLength).Items; path.ComputeWorldVertices(slot, 2, worldVerticesLength - 4, items3, 0); path.ComputeWorldVertices(slot, 0, 2, items3, worldVerticesLength - 4); items3[worldVerticesLength - 2] = items3[0]; items3[worldVerticesLength - 1] = items3[1]; } else { num2--; worldVerticesLength -= 4; items3 = world.Resize(worldVerticesLength).Items; path.ComputeWorldVertices(slot, 2, worldVerticesLength, items3, 0); } float[] items4 = curves.Resize(num2).Items; num4 = 0f; float num10 = items3[0]; float num11 = items3[1]; float num12 = 0f; float num13 = 0f; float num14 = 0f; float num15 = 0f; float num16 = 0f; float num17 = 0f; int num18 = 0; int num19 = 2; while (num18 < num2) { num12 = items3[num19]; num13 = items3[num19 + 1]; num14 = items3[num19 + 2]; num15 = items3[num19 + 3]; num16 = items3[num19 + 4]; num17 = items3[num19 + 5]; float num20 = (num10 - num12 * 2f + num14) * 0.1875f; float num21 = (num11 - num13 * 2f + num15) * 0.1875f; float num22 = ((num12 - num14) * 3f - num10 + num16) * (3f / 32f); float num23 = ((num13 - num15) * 3f - num11 + num17) * (3f / 32f); float num24 = num20 * 2f + num22; float num25 = num21 * 2f + num23; float num26 = (num12 - num10) * 0.75f + num20 + num22 * (355f / (678f * (float)Math.PI)); float num27 = (num13 - num11) * 0.75f + num21 + num23 * (355f / (678f * (float)Math.PI)); num4 += (float)Math.Sqrt(num26 * num26 + num27 * num27); num26 += num24; num27 += num25; num24 += num22; num25 += num23; num4 += (float)Math.Sqrt(num26 * num26 + num27 * num27); num26 += num24; num27 += num25; num4 += (float)Math.Sqrt(num26 * num26 + num27 * num27); num26 += num24 + num22; num27 += num25 + num23; num4 = (items4[num18] = num4 + (float)Math.Sqrt(num26 * num26 + num27 * num27)); num10 = num16; num11 = num17; num18++; num19 += 6; } if (percentPosition) { num *= num4; } if (percentSpacing) { for (int l = 0; l < spacesCount; l++) { items[l] *= num4; } } float[] array2 = segments; float num28 = 0f; int m = 0; int n = 0; int num29 = 0; int num30 = 0; for (; m < spacesCount; m++, n += 3) { float num31 = items[m]; num += num31; float num32 = num; if (closed) { num32 %= num4; if (num32 < 0f) { num32 += num4; } num29 = 0; } else { if (num32 < 0f) { AddBeforePosition(num32, items3, 0, items2, n); continue; } if (num32 > num4) { AddAfterPosition(num32 - num4, items3, worldVerticesLength - 4, items2, n); continue; } } float num33; while (true) { num33 = items4[num29]; if (!(num32 > num33)) { break; } num29++; } if (num29 == 0) { num32 /= num33; } else { float num34 = items4[num29 - 1]; num32 = (num32 - num34) / (num33 - num34); } if (num29 != num3) { num3 = num29; int num35 = num29 * 6; num10 = items3[num35]; num11 = items3[num35 + 1]; num12 = items3[num35 + 2]; num13 = items3[num35 + 3]; num14 = items3[num35 + 4]; num15 = items3[num35 + 5]; num16 = items3[num35 + 6]; num17 = items3[num35 + 7]; float num20 = (num10 - num12 * 2f + num14) * 0.03f; float num21 = (num11 - num13 * 2f + num15) * 0.03f; float num22 = ((num12 - num14) * 3f - num10 + num16) * 0.006f; float num23 = ((num13 - num15) * 3f - num11 + num17) * 0.006f; float num24 = num20 * 2f + num22; float num25 = num21 * 2f + num23; float num26 = (num12 - num10) * 0.3f + num20 + num22 * (355f / (678f * (float)Math.PI)); float num27 = (num13 - num11) * 0.3f + num21 + num23 * (355f / (678f * (float)Math.PI)); num28 = (array2[0] = (float)Math.Sqrt(num26 * num26 + num27 * num27)); for (num35 = 1; num35 < 8; num35++) { num26 += num24; num27 += num25; num24 += num22; num25 += num23; num28 = (array2[num35] = num28 + (float)Math.Sqrt(num26 * num26 + num27 * num27)); } num26 += num24; num27 += num25; num28 = (array2[8] = num28 + (float)Math.Sqrt(num26 * num26 + num27 * num27)); num26 += num24 + num22; num27 += num25 + num23; num28 = (array2[9] = num28 + (float)Math.Sqrt(num26 * num26 + num27 * num27)); num30 = 0; } num32 *= num28; float num36; while (true) { num36 = array2[num30]; if (!(num32 > num36)) { break; } num30++; } if (num30 == 0) { num32 /= num36; } else { float num37 = array2[num30 - 1]; num32 = (float)num30 + (num32 - num37) / (num36 - num37); } AddCurvePosition(num32 * 0.1f, num10, num11, num12, num13, num14, num15, num16, num17, items2, n, tangents || (m > 0 && num31 == 0f)); } return(items2); }
public void Update() { PathAttachment pathAttachment = target.Attachment as PathAttachment; if (pathAttachment == null) { return; } float num = rotateMix; float num2 = translateMix; bool flag = num2 > 0f; bool flag2 = num > 0f; if (!flag && !flag2) { return; } PathConstraintData pathConstraintData = data; SpacingMode spacingMode = pathConstraintData.spacingMode; bool flag3 = spacingMode == SpacingMode.Length; RotateMode rotateMode = pathConstraintData.rotateMode; bool flag4 = rotateMode == RotateMode.Tangent; bool flag5 = rotateMode == RotateMode.ChainScale; int count = bones.Count; int num3 = (!flag4) ? (count + 1) : count; Bone[] items = bones.Items; ExposedList <float> exposedList = spaces.Resize(num3); ExposedList <float> exposedList2 = null; float num4 = spacing; if (flag5 || flag3) { if (flag5) { exposedList2 = lengths.Resize(count); } int num5 = 0; int num6 = num3 - 1; while (num5 < num6) { Bone bone = items[num5]; float num7 = bone.data.length; if (num7 == 0f) { num7 = 1E-09f; } float num8 = num7 * bone.a; float num9 = num7 * bone.c; float num10 = (float)Math.Sqrt(num8 * num8 + num9 * num9); if (flag5) { exposedList2.Items[num5] = num7; } exposedList.Items[++num5] = ((!flag3) ? num4 : Math.Max(0f, num7 + num4)) * num10 / num7; } } else { for (int i = 1; i < num3; i++) { exposedList.Items[i] = num4; } } float[] array = ComputeWorldPositions(pathAttachment, num3, flag4, pathConstraintData.positionMode == PositionMode.Percent, spacingMode == SpacingMode.Percent); float num11 = array[0]; float num12 = array[1]; float num13 = pathConstraintData.offsetRotation; bool flag6; if (num13 == 0f) { flag6 = (rotateMode == RotateMode.Chain); } else { flag6 = false; Bone bone2 = target.bone; num13 *= ((!(bone2.a * bone2.d - bone2.b * bone2.c > 0f)) ? (-(float)Math.PI / 180f) : ((float)Math.PI / 180f)); } int num14 = 0; int num15 = 3; while (num14 < count) { Bone bone3 = items[num14]; bone3.worldX += (num11 - bone3.worldX) * num2; bone3.worldY += (num12 - bone3.worldY) * num2; float num16 = array[num15]; float num17 = array[num15 + 1]; float num18 = num16 - num11; float num19 = num17 - num12; if (flag5) { float num20 = exposedList2.Items[num14]; if (num20 != 0f) { float num21 = ((float)Math.Sqrt(num18 * num18 + num19 * num19) / num20 - 1f) * num + 1f; bone3.a *= num21; bone3.c *= num21; } } num11 = num16; num12 = num17; if (flag2) { float a = bone3.a; float b = bone3.b; float c = bone3.c; float d = bone3.d; float num22 = flag4 ? array[num15 - 1] : ((exposedList.Items[num14 + 1] != 0f) ? MathUtils.Atan2(num19, num18) : array[num15 + 2]); num22 -= MathUtils.Atan2(c, a); float num23; float num24; if (flag6) { num23 = MathUtils.Cos(num22); num24 = MathUtils.Sin(num22); float length = bone3.data.length; num11 += (length * (num23 * a - num24 * c) - num18) * num; num12 += (length * (num24 * a + num23 * c) - num19) * num; } else { num22 += num13; } if (num22 > (float)Math.PI) { num22 -= (float)Math.PI * 2f; } else if (num22 < -(float)Math.PI) { num22 += (float)Math.PI * 2f; } num22 *= num; num23 = MathUtils.Cos(num22); num24 = MathUtils.Sin(num22); bone3.a = num23 * a - num24 * c; bone3.b = num23 * b - num24 * d; bone3.c = num24 * a + num23 * c; bone3.d = num24 * b + num23 * d; } bone3.appliedValid = false; num14++; num15 += 3; } }
/// <summary>Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added /// or removed.</summary> public void UpdateCache() { ExposedList <IUpdatable> updateCache = this.updateCache; updateCache.Clear(); ExposedList <Bone> bones = this.bones; for (int i = 0, n = bones.Count; i < n; i++) { bones.Items[i].sorted = false; } ExposedList <IkConstraint> ikConstraints = this.ikConstraintsSorted; ikConstraints.Clear(); ikConstraints.AddRange(this.ikConstraints); int ikCount = ikConstraints.Count; for (int i = 0, level, n = ikCount; i < n; i++) { IkConstraint ik = ikConstraints.Items[i]; Bone bone = ik.bones.Items[0].parent; for (level = 0; bone != null; level++) { bone = bone.parent; } ik.level = level; } for (int i = 1, ii; i < ikCount; i++) { IkConstraint ik = ikConstraints.Items[i]; int level = ik.level; for (ii = i - 1; ii >= 0; ii--) { IkConstraint other = ikConstraints.Items[ii]; if (other.level < level) { break; } ikConstraints.Items[ii + 1] = other; } ikConstraints.Items[ii + 1] = ik; } for (int i = 0, n = ikConstraints.Count; i < n; i++) { IkConstraint constraint = ikConstraints.Items[i]; Bone target = constraint.target; SortBone(target); ExposedList <Bone> constrained = constraint.bones; Bone parent = constrained.Items[0]; SortBone(parent); updateCache.Add(constraint); SortReset(parent.children); constrained.Items[constrained.Count - 1].sorted = true; } ExposedList <PathConstraint> pathConstraints = this.pathConstraints; for (int i = 0, n = pathConstraints.Count; i < n; i++) { PathConstraint constraint = pathConstraints.Items[i]; Slot slot = constraint.target; int slotIndex = slot.data.index; Bone slotBone = slot.bone; if (skin != null) { SortPathConstraintAttachment(skin, slotIndex, slotBone); } if (data.defaultSkin != null && data.defaultSkin != skin) { SortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone); } for (int ii = 0, nn = data.skins.Count; ii < nn; ii++) { SortPathConstraintAttachment(data.skins.Items[ii], slotIndex, slotBone); } PathAttachment attachment = slot.Attachment as PathAttachment; if (attachment != null) { SortPathConstraintAttachment(attachment, slotBone); } ExposedList <Bone> constrained = constraint.bones; int boneCount = constrained.Count; for (int ii = 0; ii < boneCount; ii++) { SortBone(constrained.Items[ii]); } updateCache.Add(constraint); for (int ii = 0; ii < boneCount; ii++) { SortReset(constrained.Items[ii].children); } for (int ii = 0; ii < boneCount; ii++) { constrained.Items[ii].sorted = true; } } ExposedList <TransformConstraint> transformConstraints = this.transformConstraints; for (int i = 0, n = transformConstraints.Count; i < n; i++) { TransformConstraint constraint = transformConstraints.Items[i]; SortBone(constraint.target); ExposedList <Bone> constrained = constraint.bones; int boneCount = constrained.Count; for (int ii = 0; ii < boneCount; ii++) { SortBone(constrained.Items[ii]); } updateCache.Add(constraint); for (int ii = 0; ii < boneCount; ii++) { SortReset(constrained.Items[ii].children); } for (int ii = 0; ii < boneCount; ii++) { constrained.Items[ii].sorted = true; } } for (int i = 0, n = bones.Count; i < n; i++) { SortBone(bones.Items[i]); } }
private Attachment ReadAttachment(NewStream input, Skin skin, int slotIndex, String attachmentName, bool nonessential) { float scale = Scale; String name = ReadString(input); if (name == null) { name = attachmentName; } AttachmentType type = (AttachmentType)input.ReadByte(); switch (type) { case AttachmentType.Region: { String path = ReadString(input); float rotation = ReadFloat(input); float x = ReadFloat(input); float y = ReadFloat(input); float scaleX = ReadFloat(input); float scaleY = ReadFloat(input); float width = ReadFloat(input); float height = ReadFloat(input); int color = ReadInt(input); if (path == null) { path = name; } RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path); if (region == null) { return(null); } region.Path = path; region.x = x * scale; region.y = y * scale; region.scaleX = scaleX; region.scaleY = scaleY; region.rotation = rotation; region.width = width * scale; region.height = height * scale; region.r = ((color & 0xff000000) >> 24) / 255f; region.g = ((color & 0x00ff0000) >> 16) / 255f; region.b = ((color & 0x0000ff00) >> 8) / 255f; region.a = ((color & 0x000000ff)) / 255f; region.UpdateOffset(); return(region); } case AttachmentType.Boundingbox: { int vertexCount = ReadVarint(input, true); Vertices vertices = ReadVertices(input, vertexCount); if (nonessential) { ReadInt(input); //int color = nonessential ? ReadInt(input) : 0; // Avoid unused local warning. } BoundingBoxAttachment box = attachmentLoader.NewBoundingBoxAttachment(skin, name); if (box == null) { return(null); } box.worldVerticesLength = vertexCount << 1; box.vertices = vertices.vertices; box.bones = vertices.bones; return(box); } case AttachmentType.Mesh: { String path = ReadString(input); int color = ReadInt(input); int vertexCount = ReadVarint(input, true); float[] uvs = ReadFloatArray(input, vertexCount << 1, 1); int[] triangles = ReadShortArray(input); Vertices vertices = ReadVertices(input, vertexCount); int hullLength = ReadVarint(input, true); int[] edges = null; float width = 0, height = 0; if (nonessential) { edges = ReadShortArray(input); width = ReadFloat(input); height = ReadFloat(input); } if (path == null) { path = name; } MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path); if (mesh == null) { return(null); } mesh.Path = path; mesh.r = ((color & 0xff000000) >> 24) / 255f; mesh.g = ((color & 0x00ff0000) >> 16) / 255f; mesh.b = ((color & 0x0000ff00) >> 8) / 255f; mesh.a = ((color & 0x000000ff)) / 255f; mesh.bones = vertices.bones; mesh.vertices = vertices.vertices; mesh.WorldVerticesLength = vertexCount << 1; mesh.triangles = triangles; mesh.regionUVs = uvs; mesh.UpdateUVs(); mesh.HullLength = hullLength << 1; if (nonessential) { mesh.Edges = edges; mesh.Width = width * scale; mesh.Height = height * scale; } return(mesh); } case AttachmentType.Linkedmesh: { String path = ReadString(input); int color = ReadInt(input); String skinName = ReadString(input); String parent = ReadString(input); bool inheritDeform = ReadBoolean(input); float width = 0, height = 0; if (nonessential) { width = ReadFloat(input); height = ReadFloat(input); } if (path == null) { path = name; } MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path); if (mesh == null) { return(null); } mesh.Path = path; mesh.r = ((color & 0xff000000) >> 24) / 255f; mesh.g = ((color & 0x00ff0000) >> 16) / 255f; mesh.b = ((color & 0x0000ff00) >> 8) / 255f; mesh.a = ((color & 0x000000ff)) / 255f; mesh.inheritDeform = inheritDeform; if (nonessential) { mesh.Width = width * scale; mesh.Height = height * scale; } linkedMeshes.Add(new SkeletonJson.LinkedMesh(mesh, skinName, slotIndex, parent)); return(mesh); } case AttachmentType.Path: { bool closed = ReadBoolean(input); bool constantSpeed = ReadBoolean(input); int vertexCount = ReadVarint(input, true); Vertices vertices = ReadVertices(input, vertexCount); float[] lengths = new float[vertexCount / 3]; for (int i = 0, n = lengths.Length; i < n; i++) { lengths[i] = ReadFloat(input) * scale; } if (nonessential) { ReadInt(input); //int color = nonessential ? ReadInt(input) : 0; // Avoid unused local warning. } PathAttachment path = attachmentLoader.NewPathAttachment(skin, name); if (path == null) { return(null); } path.closed = closed; path.constantSpeed = constantSpeed; path.worldVerticesLength = vertexCount << 1; path.vertices = vertices.vertices; path.bones = vertices.bones; path.lengths = lengths; return(path); } } return(null); }
public void Update() { PathAttachment attachment = target.Attachment as PathAttachment; if (attachment == null) { return; } float rotateMix = this.rotateMix, translateMix = this.translateMix; bool translate = translateMix > 0, rotate = rotateMix > 0; if (!translate && !rotate) { return; } PathConstraintData data = this.data; SpacingMode spacingMode = data.spacingMode; bool lengthSpacing = spacingMode == SpacingMode.Length; RotateMode rotateMode = data.rotateMode; bool tangents = rotateMode == RotateMode.Tangent, scale = rotateMode == RotateMode.ChainScale; int boneCount = this.bones.Count, spacesCount = tangents ? boneCount : boneCount + 1; Bone[] bones = this.bones.Items; ExposedList <float> spaces = this.spaces.Resize(spacesCount), lengths = null; float spacing = this.spacing; if (scale || lengthSpacing) { if (scale) { lengths = this.lengths.Resize(boneCount); } for (int i = 0, n = spacesCount - 1; i < n;) { Bone bone = bones[i]; float length = bone.data.length, x = length * bone.a, y = length * bone.c; length = (float)Math.Sqrt(x * x + y * y); if (scale) { lengths.Items[i] = length; } spaces.Items[++i] = lengthSpacing ? Math.Max(0, length + spacing) : spacing; } } else { for (int i = 1; i < spacesCount; i++) { spaces.Items[i] = spacing; } } float[] positions = ComputeWorldPositions(attachment, spacesCount, tangents, data.positionMode == PositionMode.Percent, spacingMode == SpacingMode.Percent); Skeleton skeleton = target.Skeleton; float skeletonX = skeleton.x, skeletonY = skeleton.y; float boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; bool tip = rotateMode == RotateMode.Chain && offsetRotation == 0; for (int i = 0, p = 3; i < boneCount; i++, p += 3) { Bone bone = (Bone)bones[i]; bone.worldX += (boneX - skeletonX - bone.worldX) * translateMix; bone.worldY += (boneY - skeletonY - bone.worldY) * translateMix; float x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; if (scale) { float length = lengths.Items[i]; if (length != 0) { float s = ((float)Math.Sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1; bone.a *= s; bone.c *= s; } } boneX = x; boneY = y; if (rotate) { float a = bone.a, b = bone.b, c = bone.c, d = bone.d, r, cos, sin; if (tangents) { r = positions[p - 1]; } else if (spaces.Items[i + 1] == 0) { r = positions[p + 2]; } else { r = MathUtils.Atan2(dy, dx); } r -= MathUtils.Atan2(c, a) - offsetRotation * MathUtils.degRad; if (tip) { cos = MathUtils.Cos(r); sin = MathUtils.Sin(r); float length = bone.data.length; boneX += (length * (cos * a - sin * c) - dx) * rotateMix; boneY += (length * (sin * a + cos * c) - dy) * rotateMix; } if (r > MathUtils.PI) { r -= MathUtils.PI2; } else if (r < -MathUtils.PI) // { r += MathUtils.PI2; } r *= rotateMix; cos = MathUtils.Cos(r); sin = MathUtils.Sin(r); bone.a = cos * a - sin * c; bone.b = cos * b - sin * d; bone.c = sin * a + cos * c; bone.d = sin * b + cos * d; } } }
public void Update() { PathAttachment attachment = target.Attachment as PathAttachment; if (attachment == null) { return; } float rotateMix = this.rotateMix, translateMix = this.translateMix; bool translate = translateMix > 0, rotate = rotateMix > 0; if (!translate && !rotate) { return; } PathConstraintData data = this.data; bool percentSpacing = data.spacingMode == SpacingMode.Percent; RotateMode rotateMode = data.rotateMode; bool tangents = rotateMode == RotateMode.Tangent, scale = rotateMode == RotateMode.ChainScale; int boneCount = this.bones.Count, spacesCount = tangents ? boneCount : boneCount + 1; Bone[] bonesItems = this.bones.Items; ExposedList <float> spaces = this.spaces.Resize(spacesCount), lengths = null; float spacing = this.spacing; if (scale || !percentSpacing) { if (scale) { lengths = this.lengths.Resize(boneCount); } bool lengthSpacing = data.spacingMode == SpacingMode.Length; for (int i = 0, n = spacesCount - 1; i < n;) { Bone bone = bonesItems[i]; float setupLength = bone.data.length; if (setupLength < PathConstraint.Epsilon) { if (scale) { lengths.Items[i] = 0; } spaces.Items[++i] = 0; } else if (percentSpacing) { if (scale) { float x = setupLength * bone.a, y = setupLength * bone.c; float length = (float)Math.Sqrt(x * x + y * y); lengths.Items[i] = length; } spaces.Items[++i] = spacing; } else { float x = setupLength * bone.a, y = setupLength * bone.c; float length = (float)Math.Sqrt(x * x + y * y); if (scale) { lengths.Items[i] = length; } spaces.Items[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; } } } else { for (int i = 1; i < spacesCount; i++) { spaces.Items[i] = spacing; } } float[] positions = ComputeWorldPositions(attachment, spacesCount, tangents, data.positionMode == PositionMode.Percent, percentSpacing); float boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; bool tip; if (offsetRotation == 0) { tip = rotateMode == RotateMode.Chain; } else { tip = false; Bone p = target.bone; 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) { Bone bone = bonesItems[i]; bone.worldX += (boneX - bone.worldX) * translateMix; bone.worldY += (boneY - bone.worldY) * translateMix; float x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; if (scale) { float length = lengths.Items[i]; if (length >= PathConstraint.Epsilon) { float s = ((float)Math.Sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1; bone.a *= s; bone.c *= s; } } boneX = x; boneY = y; if (rotate) { float a = bone.a, b = bone.b, c = bone.c, d = bone.d, r, cos, sin; if (tangents) { r = positions[p - 1]; } else if (spaces.Items[i + 1] < PathConstraint.Epsilon) { r = positions[p + 2]; } else { r = MathUtils.Atan2(dy, dx); } r -= MathUtils.Atan2(c, a); if (tip) { cos = MathUtils.Cos(r); sin = MathUtils.Sin(r); float 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 > MathUtils.PI) { r -= MathUtils.PI2; } else if (r < -MathUtils.PI) // { r += MathUtils.PI2; } r *= rotateMix; cos = MathUtils.Cos(r); sin = MathUtils.Sin(r); bone.a = cos * a - sin * c; bone.b = cos * b - sin * d; bone.c = sin * a + cos * c; bone.d = sin * b + cos * d; } bone.appliedValid = false; } }
private Attachment ReadAttachment(Stream input, Skin skin, int slotIndex, string attachmentName, bool nonessential) { float scale = this.Scale; string text = this.ReadString(input); if (text == null) { text = attachmentName; } switch (input.ReadByte()) { case 0: { string text2 = this.ReadString(input); float rotation = this.ReadFloat(input); float num = this.ReadFloat(input); float num2 = this.ReadFloat(input); float scaleX = this.ReadFloat(input); float scaleY = this.ReadFloat(input); float num3 = this.ReadFloat(input); float num4 = this.ReadFloat(input); int num5 = SkeletonBinary.ReadInt(input); if (text2 == null) { text2 = text; } RegionAttachment regionAttachment = this.attachmentLoader.NewRegionAttachment(skin, text, text2); if (regionAttachment == null) { return(null); } regionAttachment.Path = text2; regionAttachment.x = num * scale; regionAttachment.y = num2 * scale; regionAttachment.scaleX = scaleX; regionAttachment.scaleY = scaleY; regionAttachment.rotation = rotation; regionAttachment.width = num3 * scale; regionAttachment.height = num4 * scale; regionAttachment.r = (float)((num5 & 4278190080u) >> 24) / 255f; regionAttachment.g = (float)((num5 & 16711680) >> 16) / 255f; regionAttachment.b = (float)((num5 & 65280) >> 8) / 255f; regionAttachment.a = (float)(num5 & 255) / 255f; regionAttachment.UpdateOffset(); return(regionAttachment); } case 1: { int num6 = SkeletonBinary.ReadVarint(input, true); Vertices vertices = this.ReadVertices(input, num6); if (nonessential) { SkeletonBinary.ReadInt(input); } BoundingBoxAttachment boundingBoxAttachment = this.attachmentLoader.NewBoundingBoxAttachment(skin, text); if (boundingBoxAttachment == null) { return(null); } boundingBoxAttachment.worldVerticesLength = num6 << 1; boundingBoxAttachment.vertices = vertices.vertices; boundingBoxAttachment.bones = vertices.bones; return(boundingBoxAttachment); } case 2: { string text3 = this.ReadString(input); int num7 = SkeletonBinary.ReadInt(input); int num8 = SkeletonBinary.ReadVarint(input, true); float[] regionUVs = this.ReadFloatArray(input, num8 << 1, 1f); int[] triangles = this.ReadShortArray(input); Vertices vertices2 = this.ReadVertices(input, num8); int num9 = SkeletonBinary.ReadVarint(input, true); int[] edges = null; float num10 = 0f; float num11 = 0f; if (nonessential) { edges = this.ReadShortArray(input); num10 = this.ReadFloat(input); num11 = this.ReadFloat(input); } if (text3 == null) { text3 = text; } MeshAttachment meshAttachment = this.attachmentLoader.NewMeshAttachment(skin, text, text3); if (meshAttachment == null) { return(null); } meshAttachment.Path = text3; meshAttachment.r = (float)((num7 & 4278190080u) >> 24) / 255f; meshAttachment.g = (float)((num7 & 16711680) >> 16) / 255f; meshAttachment.b = (float)((num7 & 65280) >> 8) / 255f; meshAttachment.a = (float)(num7 & 255) / 255f; meshAttachment.bones = vertices2.bones; meshAttachment.vertices = vertices2.vertices; meshAttachment.WorldVerticesLength = num8 << 1; meshAttachment.triangles = triangles; meshAttachment.regionUVs = regionUVs; meshAttachment.UpdateUVs(); meshAttachment.HullLength = num9 << 1; if (nonessential) { meshAttachment.Edges = edges; meshAttachment.Width = num10 * scale; meshAttachment.Height = num11 * scale; } return(meshAttachment); } case 3: { string text4 = this.ReadString(input); int num12 = SkeletonBinary.ReadInt(input); string skin2 = this.ReadString(input); string parent = this.ReadString(input); bool inheritDeform = SkeletonBinary.ReadBoolean(input); float num13 = 0f; float num14 = 0f; if (nonessential) { num13 = this.ReadFloat(input); num14 = this.ReadFloat(input); } if (text4 == null) { text4 = text; } MeshAttachment meshAttachment2 = this.attachmentLoader.NewMeshAttachment(skin, text, text4); if (meshAttachment2 == null) { return(null); } meshAttachment2.Path = text4; meshAttachment2.r = (float)((num12 & 4278190080u) >> 24) / 255f; meshAttachment2.g = (float)((num12 & 16711680) >> 16) / 255f; meshAttachment2.b = (float)((num12 & 65280) >> 8) / 255f; meshAttachment2.a = (float)(num12 & 255) / 255f; meshAttachment2.inheritDeform = inheritDeform; if (nonessential) { meshAttachment2.Width = num13 * scale; meshAttachment2.Height = num14 * scale; } this.linkedMeshes.Add(new SkeletonJson.LinkedMesh(meshAttachment2, skin2, slotIndex, parent)); return(meshAttachment2); } case 4: { bool closed = SkeletonBinary.ReadBoolean(input); bool constantSpeed = SkeletonBinary.ReadBoolean(input); int num15 = SkeletonBinary.ReadVarint(input, true); Vertices vertices3 = this.ReadVertices(input, num15); float[] array = new float[num15 / 3]; int i = 0; int num16 = array.Length; while (i < num16) { array[i] = this.ReadFloat(input) * scale; i++; } if (nonessential) { SkeletonBinary.ReadInt(input); } PathAttachment pathAttachment = this.attachmentLoader.NewPathAttachment(skin, text); if (pathAttachment == null) { return(null); } pathAttachment.closed = closed; pathAttachment.constantSpeed = constantSpeed; pathAttachment.worldVerticesLength = num15 << 1; pathAttachment.vertices = vertices3.vertices; pathAttachment.bones = vertices3.bones; pathAttachment.lengths = array; return(pathAttachment); } default: return(null); } }
float[] ComputeWorldPositions (PathAttachment path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing) { Slot target = this.target; float position = this.position; float[] spaces = this.spaces.Items, output = this.positions.Resize(spacesCount * 3 + 2).Items, world; bool closed = path.Closed; int verticesLength = path.WorldVerticesLength, curveCount = verticesLength / 6, prevCurve = NONE; float pathLength; if (!path.ConstantSpeed) { float[] lengths = path.Lengths; curveCount -= closed ? 1 : 2; pathLength = lengths[curveCount]; if (percentPosition) position *= pathLength; if (percentSpacing) { for (int i = 0; i < spacesCount; i++) spaces[i] *= pathLength; } world = this.world.Resize(8).Items; for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { float space = spaces[i]; position += space; float p = position; if (closed) { p %= pathLength; if (p < 0) p += pathLength; curve = 0; } else if (p < 0) { if (prevCurve != BEFORE) { prevCurve = BEFORE; path.ComputeWorldVertices(target, 2, 4, world, 0); } AddBeforePosition(p, world, 0, output, o); continue; } else if (p > pathLength) { if (prevCurve != AFTER) { prevCurve = AFTER; path.ComputeWorldVertices(target, verticesLength - 6, 4, world, 0); } AddAfterPosition(p - pathLength, world, 0, output, o); continue; } // Determine curve containing position. for (;; curve++) { float length = lengths[curve]; if (p > length) continue; if (curve == 0) p /= length; else { float prev = lengths[curve - 1]; p = (p - prev) / (length - prev); } break; } if (curve != prevCurve) { prevCurve = curve; if (closed && curve == curveCount) { path.ComputeWorldVertices(target, verticesLength - 4, 4, world, 0); path.ComputeWorldVertices(target, 0, 4, world, 4); } else path.ComputeWorldVertices(target, curve * 6 + 2, 8, world, 0); } AddCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], output, o, tangents || (i > 0 && space == 0)); } return output; } // World vertices. if (closed) { verticesLength += 2; world = this.world.Resize(verticesLength).Items; path.ComputeWorldVertices(target, 2, verticesLength - 4, world, 0); path.ComputeWorldVertices(target, 0, 2, world, verticesLength - 4); world[verticesLength - 2] = world[0]; world[verticesLength - 1] = world[1]; } else { curveCount--; verticesLength -= 4; world = this.world.Resize(verticesLength).Items; path.ComputeWorldVertices(target, 2, verticesLength, world, 0); } // Curve lengths. float[] curves = this.curves.Resize(curveCount).Items; pathLength = 0; float x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy; for (int i = 0, w = 2; i < curveCount; i++, w += 6) { cx1 = world[w]; cy1 = world[w + 1]; cx2 = world[w + 2]; cy2 = world[w + 3]; x2 = world[w + 4]; y2 = world[w + 5]; tmpx = (x1 - cx1 * 2 + cx2) * 0.1875f; tmpy = (y1 - cy1 * 2 + cy2) * 0.1875f; dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375f; dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375f; ddfx = tmpx * 2 + dddfx; ddfy = tmpy * 2 + dddfy; dfx = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f; dfy = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f; pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); dfx += ddfx; dfy += ddfy; ddfx += dddfx; ddfy += dddfy; pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); dfx += ddfx; dfy += ddfy; pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); dfx += ddfx + dddfx; dfy += ddfy + dddfy; pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); curves[i] = pathLength; x1 = x2; y1 = y2; } if (percentPosition) position *= pathLength; if (percentSpacing) { for (int i = 0; i < spacesCount; i++) spaces[i] *= pathLength; } float[] segments = this.segments; float curveLength = 0; for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { float space = spaces[i]; position += space; float p = position; if (closed) { p %= pathLength; if (p < 0) p += pathLength; curve = 0; } else if (p < 0) { AddBeforePosition(p, world, 0, output, o); continue; } else if (p > pathLength) { AddAfterPosition(p - pathLength, world, verticesLength - 4, output, o); continue; } // Determine curve containing position. for (;; curve++) { float length = curves[curve]; if (p > length) continue; if (curve == 0) p /= length; else { float prev = curves[curve - 1]; p = (p - prev) / (length - prev); } break; } // Curve segment lengths. if (curve != prevCurve) { prevCurve = curve; int ii = curve * 6; x1 = world[ii]; y1 = world[ii + 1]; cx1 = world[ii + 2]; cy1 = world[ii + 3]; cx2 = world[ii + 4]; cy2 = world[ii + 5]; x2 = world[ii + 6]; y2 = world[ii + 7]; tmpx = (x1 - cx1 * 2 + cx2) * 0.03f; tmpy = (y1 - cy1 * 2 + cy2) * 0.03f; dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006f; dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006f; ddfx = tmpx * 2 + dddfx; ddfy = tmpy * 2 + dddfy; dfx = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f; dfy = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f; curveLength = (float)Math.Sqrt(dfx * dfx + dfy * dfy); segments[0] = curveLength; for (ii = 1; ii < 8; ii++) { dfx += ddfx; dfy += ddfy; ddfx += dddfx; ddfy += dddfy; curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); segments[ii] = curveLength; } dfx += ddfx; dfy += ddfy; curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); segments[8] = curveLength; dfx += ddfx + dddfx; dfy += ddfy + dddfy; curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); segments[9] = curveLength; segment = 0; } // Weight by segment length. p *= curveLength; for (;; segment++) { float length = segments[segment]; if (p > length) continue; if (segment == 0) p /= length; else { float prev = segments[segment - 1]; p = segment + (p - prev) / (length - prev); } break; } AddCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, output, o, tangents || (i > 0 && space == 0)); } return output; }
private Attachment ReadAttachment(Dictionary <string, object> map, Skin skin, int slotIndex, string name, SkeletonData skeletonData) { float scale = Scale; name = GetString(map, "name", name); string text = GetString(map, "type", "region"); if (text == "skinnedmesh") { text = "weightedmesh"; } if (text == "weightedmesh") { text = "mesh"; } if (text == "weightedlinkedmesh") { text = "linkedmesh"; } AttachmentType attachmentType = (AttachmentType)Enum.Parse(typeof(AttachmentType), text, ignoreCase: true); string @string = GetString(map, "path", name); switch (attachmentType) { case AttachmentType.Region: { RegionAttachment regionAttachment = attachmentLoader.NewRegionAttachment(skin, name, @string); if (regionAttachment == null) { return(null); } regionAttachment.Path = @string; regionAttachment.x = GetFloat(map, "x", 0f) * scale; regionAttachment.y = GetFloat(map, "y", 0f) * scale; regionAttachment.scaleX = GetFloat(map, "scaleX", 1f); regionAttachment.scaleY = GetFloat(map, "scaleY", 1f); regionAttachment.rotation = GetFloat(map, "rotation", 0f); regionAttachment.width = GetFloat(map, "width", 32f) * scale; regionAttachment.height = GetFloat(map, "height", 32f) * scale; regionAttachment.UpdateOffset(); if (map.ContainsKey("color")) { string hexString2 = (string)map["color"]; regionAttachment.r = ToColor(hexString2, 0); regionAttachment.g = ToColor(hexString2, 1); regionAttachment.b = ToColor(hexString2, 2); regionAttachment.a = ToColor(hexString2, 3); } regionAttachment.UpdateOffset(); return(regionAttachment); } case AttachmentType.Boundingbox: { BoundingBoxAttachment boundingBoxAttachment = attachmentLoader.NewBoundingBoxAttachment(skin, name); if (boundingBoxAttachment == null) { return(null); } ReadVertices(map, boundingBoxAttachment, GetInt(map, "vertexCount", 0) << 1); return(boundingBoxAttachment); } case AttachmentType.Mesh: case AttachmentType.Linkedmesh: { MeshAttachment meshAttachment = attachmentLoader.NewMeshAttachment(skin, name, @string); if (meshAttachment == null) { return(null); } meshAttachment.Path = @string; if (map.ContainsKey("color")) { string hexString = (string)map["color"]; meshAttachment.r = ToColor(hexString, 0); meshAttachment.g = ToColor(hexString, 1); meshAttachment.b = ToColor(hexString, 2); meshAttachment.a = ToColor(hexString, 3); } meshAttachment.Width = GetFloat(map, "width", 0f) * scale; meshAttachment.Height = GetFloat(map, "height", 0f) * scale; string string3 = GetString(map, "parent", null); if (string3 != null) { meshAttachment.InheritDeform = GetBoolean(map, "deform", defaultValue: true); linkedMeshes.Add(new LinkedMesh(meshAttachment, GetString(map, "skin", null), slotIndex, string3)); return(meshAttachment); } float[] floatArray = GetFloatArray(map, "uvs", 1f); ReadVertices(map, meshAttachment, floatArray.Length); meshAttachment.triangles = GetIntArray(map, "triangles"); meshAttachment.regionUVs = floatArray; meshAttachment.UpdateUVs(); if (map.ContainsKey("hull")) { meshAttachment.HullLength = GetInt(map, "hull", 0) * 2; } if (map.ContainsKey("edges")) { meshAttachment.Edges = GetIntArray(map, "edges"); } return(meshAttachment); } case AttachmentType.Path: { PathAttachment pathAttachment = attachmentLoader.NewPathAttachment(skin, name); if (pathAttachment == null) { return(null); } pathAttachment.closed = GetBoolean(map, "closed", defaultValue: false); pathAttachment.constantSpeed = GetBoolean(map, "constantSpeed", defaultValue: true); int @int = GetInt(map, "vertexCount", 0); ReadVertices(map, pathAttachment, @int << 1); pathAttachment.lengths = GetFloatArray(map, "lengths", scale); return(pathAttachment); } case AttachmentType.Point: { PointAttachment pointAttachment = attachmentLoader.NewPointAttachment(skin, name); if (pointAttachment == null) { return(null); } pointAttachment.x = GetFloat(map, "x", 0f) * scale; pointAttachment.y = GetFloat(map, "y", 0f) * scale; pointAttachment.rotation = GetFloat(map, "rotation", 0f); return(pointAttachment); } case AttachmentType.Clipping: { ClippingAttachment clippingAttachment = attachmentLoader.NewClippingAttachment(skin, name); if (clippingAttachment == null) { return(null); } string string2 = GetString(map, "end", null); if (string2 != null) { SlotData slotData = skeletonData.FindSlot(string2); if (slotData == null) { throw new Exception("Clipping end slot not found: " + string2); } clippingAttachment.EndSlot = slotData; } ReadVertices(map, clippingAttachment, GetInt(map, "vertexCount", 0) << 1); return(clippingAttachment); } default: return(null); } }