mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
Updated spine-csharp to Spine v3.
This commit is contained in:
parent
4b7fc36328
commit
08b74f5b18
@ -53,35 +53,91 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="src\Animation.cs" />
|
||||
<Compile Include="src\AnimationStateData.cs" />
|
||||
<Compile Include="src\Atlas.cs" />
|
||||
<Compile Include="src\Attachments\AttachmentLoader.cs" />
|
||||
<Compile Include="src\Animation.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\AnimationState.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\AnimationStateData.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\Atlas.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\Attachments\AtlasAttachmentLoader.cs" />
|
||||
<Compile Include="src\Attachments\Attachment.cs" />
|
||||
<Compile Include="src\Attachments\AttachmentLoader.cs" />
|
||||
<Compile Include="src\Attachments\AttachmentType.cs" />
|
||||
<Compile Include="src\Attachments\BoundingBoxAttachment.cs" />
|
||||
<Compile Include="src\Attachments\MeshAttachment.cs" />
|
||||
<Compile Include="src\Attachments\RegionAttachment.cs" />
|
||||
<Compile Include="src\Attachments\SkinnedMeshAttachment.cs" />
|
||||
<Compile Include="src\BlendMode.cs" />
|
||||
<Compile Include="src\Bone.cs" />
|
||||
<Compile Include="src\BoneData.cs" />
|
||||
<Compile Include="src\AnimationState.cs" />
|
||||
<Compile Include="src\Event.cs" />
|
||||
<Compile Include="src\EventData.cs" />
|
||||
<Compile Include="src\ExposedList.cs" />
|
||||
<Compile Include="src\IkConstraint.cs" />
|
||||
<Compile Include="src\IkConstraintData.cs" />
|
||||
<Compile Include="src\Json.cs" />
|
||||
<Compile Include="src\Skeleton.cs" />
|
||||
<Compile Include="src\SkeletonData.cs" />
|
||||
<Compile Include="src\SkeletonJson.cs" />
|
||||
<Compile Include="src\SkeletonBinary.cs" />
|
||||
<Compile Include="src\Skin.cs" />
|
||||
<Compile Include="src\Slot.cs" />
|
||||
<Compile Include="src\SlotData.cs" />
|
||||
<Compile Include="src\Attachments\WeightedMeshAttachment.cs" />
|
||||
<Compile Include="src\BlendMode.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\Bone.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\BoneData.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\Event.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\EventData.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\ExposedList.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\IkConstraint.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\IkConstraintData.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\IUpdatable.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\Json.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\MathUtils.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\Skeleton.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\SkeletonBinary.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\SkeletonBounds.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\SkeletonData.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\SkeletonJson.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\Skin.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\Slot.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\SlotData.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\TransformConstraint.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="src\TransformConstraintData.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!--
|
||||
To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
@ -91,4 +147,4 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
</Project>
|
||||
@ -674,52 +674,4 @@ namespace Spine {
|
||||
ikConstraint.bendDirection = (int)frames[frameIndex + PREV_FRAME_BEND_DIRECTION];
|
||||
}
|
||||
}
|
||||
|
||||
public class FlipXTimeline : Timeline {
|
||||
internal int boneIndex;
|
||||
internal float[] frames;
|
||||
|
||||
public int BoneIndex { get { return boneIndex; } set { boneIndex = value; } }
|
||||
public float[] Frames { get { return frames; } set { frames = value; } } // time, flip, ...
|
||||
public int FrameCount { get { return frames.Length >> 1; } }
|
||||
|
||||
public FlipXTimeline (int frameCount) {
|
||||
frames = new float[frameCount << 1];
|
||||
}
|
||||
|
||||
/// <summary>Sets the time and value of the specified keyframe.</summary>
|
||||
public void SetFrame (int frameIndex, float time, bool flip) {
|
||||
frameIndex *= 2;
|
||||
frames[frameIndex] = time;
|
||||
frames[frameIndex + 1] = flip ? 1 : 0;
|
||||
}
|
||||
|
||||
public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList<Event> firedEvents, float alpha) {
|
||||
float[] frames = this.frames;
|
||||
if (time < frames[0]) {
|
||||
if (lastTime > time) Apply(skeleton, lastTime, int.MaxValue, null, 0);
|
||||
return;
|
||||
} else if (lastTime > time) //
|
||||
lastTime = -1;
|
||||
|
||||
int frameIndex = (time >= frames[frames.Length - 2] ? frames.Length : Animation.binarySearch(frames, time, 2)) - 2;
|
||||
if (frames[frameIndex] < lastTime) return;
|
||||
|
||||
SetFlip(skeleton.bones.Items[boneIndex], frames[frameIndex + 1] != 0);
|
||||
}
|
||||
|
||||
virtual protected void SetFlip (Bone bone, bool flip) {
|
||||
bone.flipX = flip;
|
||||
}
|
||||
}
|
||||
|
||||
public class FlipYTimeline : FlipXTimeline {
|
||||
public FlipYTimeline (int frameCount)
|
||||
: base(frameCount) {
|
||||
}
|
||||
|
||||
override protected void SetFlip (Bone bone, bool flip) {
|
||||
bone.flipY = flip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,10 +74,10 @@ namespace Spine {
|
||||
return attachment;
|
||||
}
|
||||
|
||||
public SkinnedMeshAttachment NewSkinnedMeshAttachment (Skin skin, String name, String path) {
|
||||
public WeightedMeshAttachment NewWeightedMeshAttachment (Skin skin, String name, String path) {
|
||||
AtlasRegion region = FindRegion(path);
|
||||
if (region == null) throw new Exception("Region not found in atlas: " + path + " (skinned mesh attachment: " + name + ")");
|
||||
SkinnedMeshAttachment attachment = new SkinnedMeshAttachment(name);
|
||||
if (region == null) throw new Exception("Region not found in atlas: " + path + " (weighted mesh attachment: " + name + ")");
|
||||
WeightedMeshAttachment attachment = new WeightedMeshAttachment(name);
|
||||
attachment.RendererObject = region;
|
||||
attachment.RegionU = region.u;
|
||||
attachment.RegionV = region.v;
|
||||
|
||||
@ -40,7 +40,7 @@ namespace Spine {
|
||||
MeshAttachment NewMeshAttachment (Skin skin, String name, String path);
|
||||
|
||||
/// <return>May be null to not load any attachment.</return>
|
||||
SkinnedMeshAttachment NewSkinnedMeshAttachment (Skin skin, String name, String path);
|
||||
WeightedMeshAttachment NewWeightedMeshAttachment (Skin skin, String name, String path);
|
||||
|
||||
/// <return>May be null to not load any attachment.</return>
|
||||
BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, String name);
|
||||
|
||||
@ -31,6 +31,6 @@
|
||||
|
||||
namespace Spine {
|
||||
public enum AttachmentType {
|
||||
region, boundingbox, mesh, skinnedmesh
|
||||
region, boundingbox, mesh, weightedmesh
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,10 +45,10 @@ namespace Spine {
|
||||
/// <param name="worldVertices">Must have at least the same length as this attachment's vertices.</param>
|
||||
public void ComputeWorldVertices (Bone bone, float[] worldVertices) {
|
||||
float x = bone.skeleton.x + bone.worldX, y = bone.skeleton.y + bone.worldY;
|
||||
float m00 = bone.m00;
|
||||
float m01 = bone.m01;
|
||||
float m10 = bone.m10;
|
||||
float m11 = bone.m11;
|
||||
float m00 = bone.a;
|
||||
float m01 = bone.b;
|
||||
float m10 = bone.c;
|
||||
float m11 = bone.d;
|
||||
float[] vertices = this.vertices;
|
||||
for (int i = 0, n = vertices.Length; i < n; i += 2) {
|
||||
float px = vertices[i];
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
using System;
|
||||
|
||||
namespace Spine {
|
||||
/// <summary>Attachment that displays a texture region.</summary>
|
||||
/// <summary>Attachment that displays a texture region using a mesh.</summary>
|
||||
public class MeshAttachment : Attachment {
|
||||
internal float[] vertices, uvs, regionUVs;
|
||||
internal int[] triangles;
|
||||
@ -94,7 +94,7 @@ namespace Spine {
|
||||
public void ComputeWorldVertices (Slot slot, float[] worldVertices) {
|
||||
Bone bone = slot.bone;
|
||||
float x = bone.skeleton.x + bone.worldX, y = bone.skeleton.y + bone.worldY;
|
||||
float m00 = bone.m00, m01 = bone.m01, m10 = bone.m10, m11 = bone.m11;
|
||||
float m00 = bone.a, m01 = bone.b, m10 = bone.c, m11 = bone.d;
|
||||
float[] vertices = this.vertices;
|
||||
int verticesCount = vertices.Length;
|
||||
if (slot.attachmentVerticesCount == verticesCount) vertices = slot.AttachmentVertices;
|
||||
|
||||
@ -137,7 +137,7 @@ namespace Spine {
|
||||
|
||||
public void ComputeWorldVertices (Bone bone, float[] worldVertices) {
|
||||
float x = bone.skeleton.x + bone.worldX, y = bone.skeleton.y + bone.worldY;
|
||||
float m00 = bone.m00, m01 = bone.m01, m10 = bone.m10, m11 = bone.m11;
|
||||
float m00 = bone.a, m01 = bone.b, m10 = bone.c, m11 = bone.d;
|
||||
float[] offset = this.offset;
|
||||
worldVertices[X1] = offset[X1] * m00 + offset[Y1] * m01 + x;
|
||||
worldVertices[Y1] = offset[X1] * m10 + offset[Y1] * m11 + y;
|
||||
|
||||
@ -33,8 +33,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine {
|
||||
/// <summary>Attachment that displays a texture region.</summary>
|
||||
public class SkinnedMeshAttachment : Attachment {
|
||||
/// <summary>Attachment that displays a texture region using a mesh which can be deformed by bones.</summary>
|
||||
public class WeightedMeshAttachment : Attachment {
|
||||
internal int[] bones;
|
||||
internal float[] weights, uvs, regionUVs;
|
||||
internal int[] triangles;
|
||||
@ -72,7 +72,7 @@ namespace Spine {
|
||||
public float Width { get; set; }
|
||||
public float Height { get; set; }
|
||||
|
||||
public SkinnedMeshAttachment (string name)
|
||||
public WeightedMeshAttachment (string name)
|
||||
: base(name) {
|
||||
}
|
||||
|
||||
@ -107,8 +107,8 @@ namespace Spine {
|
||||
for (; v < nn; v++, b += 3) {
|
||||
Bone bone = skeletonBones.Items[bones[v]];
|
||||
float vx = weights[b], vy = weights[b + 1], weight = weights[b + 2];
|
||||
wx += (vx * bone.m00 + vy * bone.m01 + bone.worldX) * weight;
|
||||
wy += (vx * bone.m10 + vy * bone.m11 + bone.worldY) * weight;
|
||||
wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
|
||||
wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
|
||||
}
|
||||
worldVertices[w] = wx + x;
|
||||
worldVertices[w + 1] = wy + y;
|
||||
@ -121,8 +121,8 @@ namespace Spine {
|
||||
for (; v < nn; v++, b += 3, f += 2) {
|
||||
Bone bone = skeletonBones.Items[bones[v]];
|
||||
float vx = weights[b] + ffd[f], vy = weights[b + 1] + ffd[f + 1], weight = weights[b + 2];
|
||||
wx += (vx * bone.m00 + vy * bone.m01 + bone.worldX) * weight;
|
||||
wy += (vx * bone.m10 + vy * bone.m11 + bone.worldY) * weight;
|
||||
wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
|
||||
wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
|
||||
}
|
||||
worldVertices[w] = wx + x;
|
||||
worldVertices[w + 1] = wy + y;
|
||||
@ -33,18 +33,19 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine {
|
||||
public class Bone {
|
||||
public class Bone : IUpdatable {
|
||||
static public bool yDown;
|
||||
|
||||
internal BoneData data;
|
||||
internal Skeleton skeleton;
|
||||
internal Bone parent;
|
||||
internal ExposedList<Bone> children = new ExposedList<Bone>();
|
||||
internal float x, y, rotation, rotationIK, scaleX, scaleY;
|
||||
internal bool flipX, flipY;
|
||||
internal float m00, m01, m10, m11;
|
||||
internal float worldX, worldY, worldRotation, worldScaleX, worldScaleY;
|
||||
internal bool worldFlipX, worldFlipY;
|
||||
internal float x, y, rotation, scaleX, scaleY;
|
||||
internal float appliedRotation, appliedScaleX, appliedScaleY;
|
||||
|
||||
internal float a, b, worldX;
|
||||
internal float c, d, worldY;
|
||||
internal float worldSignX, worldSignY;
|
||||
|
||||
public BoneData Data { get { return data; } }
|
||||
public Skeleton Skeleton { get { return skeleton; } }
|
||||
@ -52,26 +53,28 @@ namespace Spine {
|
||||
public ExposedList<Bone> Children { get { return children; } }
|
||||
public float X { get { return x; } set { x = value; } }
|
||||
public float Y { get { return y; } set { y = value; } }
|
||||
/// <summary>The forward kinetics rotation.</summary>
|
||||
public float Rotation { get { return rotation; } set { rotation = value; } }
|
||||
/// <summary>The inverse kinetics rotation, as calculated by any IK constraints.</summary>
|
||||
public float RotationIK { get { return rotationIK; } set { rotationIK = value; } }
|
||||
/// <summary>The rotation, as calculated by any constraints.</summary>
|
||||
public float AppliedRotation { get { return appliedRotation; } set { appliedRotation = value; } }
|
||||
/// <summary>The scale X, as calculated by any constraints.</summary>
|
||||
public float AppliedScaleX { get { return appliedScaleX; } set { appliedScaleX = value; } }
|
||||
/// <summary>The scale Y, as calculated by any constraints.</summary>
|
||||
public float AppliedScaleY { get { return appliedScaleY; } set { appliedScaleY = value; } }
|
||||
public float ScaleX { get { return scaleX; } set { scaleX = value; } }
|
||||
public float ScaleY { get { return scaleY; } set { scaleY = value; } }
|
||||
public bool FlipX { get { return flipX; } set { flipX = value; } }
|
||||
public bool FlipY { get { return flipY; } set { flipY = value; } }
|
||||
|
||||
public float M00 { get { return m00; } }
|
||||
public float M01 { get { return m01; } }
|
||||
public float M10 { get { return m10; } }
|
||||
public float M11 { get { return m11; } }
|
||||
public float A { get { return a; } }
|
||||
public float B { get { return b; } }
|
||||
public float C { get { return c; } }
|
||||
public float D { get { return d; } }
|
||||
public float WorldX { get { return worldX; } }
|
||||
public float WorldY { get { return worldY; } }
|
||||
public float WorldRotation { get { return worldRotation; } }
|
||||
public float WorldScaleX { get { return worldScaleX; } }
|
||||
public float WorldScaleY { get { return worldScaleY; } }
|
||||
public bool WorldFlipX { get { return worldFlipX; } set { worldFlipX = value; } }
|
||||
public bool WorldFlipY { get { return worldFlipY; } set { worldFlipY = value; } }
|
||||
public float WorldSignX { get { return worldSignX; } }
|
||||
public float WorldSignY { get { return worldSignY; } }
|
||||
public float WorldRotationX { get { return MathUtils.Atan2(c, a) * MathUtils.radDeg; } }
|
||||
public float WorldRotationY { get { return MathUtils.Atan2(d, b) * MathUtils.radDeg; } }
|
||||
public float WorldScaleX { get { return (float)Math.Sqrt(a * a + b * b) * worldSignX; } }
|
||||
public float WorldScaleY { get { return (float)Math.Sqrt(c * c + d * d) * worldSignY; } }
|
||||
|
||||
/// <param name="parent">May be null.</param>
|
||||
public Bone (BoneData data, Skeleton skeleton, Bone parent) {
|
||||
@ -83,80 +86,155 @@ namespace Spine {
|
||||
SetToSetupPose();
|
||||
}
|
||||
|
||||
/// <summary>Computes the world SRT using the parent bone and the local SRT.</summary>
|
||||
/// <summary>Computes the world SRT using the parent bone and this bone's local SRT.</summary>
|
||||
public void UpdateWorldTransform () {
|
||||
Bone parent = this.parent;
|
||||
float x = this.x, y = this.y;
|
||||
if (parent != null) {
|
||||
worldX = x * parent.m00 + y * parent.m01 + parent.worldX;
|
||||
worldY = x * parent.m10 + y * parent.m11 + parent.worldY;
|
||||
if (data.inheritScale) {
|
||||
worldScaleX = parent.worldScaleX * scaleX;
|
||||
worldScaleY = parent.worldScaleY * scaleY;
|
||||
} else {
|
||||
worldScaleX = scaleX;
|
||||
worldScaleY = scaleY;
|
||||
}
|
||||
worldRotation = data.inheritRotation ? parent.worldRotation + rotationIK : rotationIK;
|
||||
worldFlipX = parent.worldFlipX != flipX;
|
||||
worldFlipY = parent.worldFlipY != flipY;
|
||||
} else {
|
||||
Skeleton skeleton = this.skeleton;
|
||||
bool skeletonFlipX = skeleton.flipX, skeletonFlipY = skeleton.flipY;
|
||||
worldX = skeletonFlipX ? -x : x;
|
||||
worldY = skeletonFlipY != yDown ? -y : y;
|
||||
worldScaleX = scaleX;
|
||||
worldScaleY = scaleY;
|
||||
worldRotation = rotationIK;
|
||||
worldFlipX = skeletonFlipX != flipX;
|
||||
worldFlipY = skeletonFlipY != flipY;
|
||||
}
|
||||
float radians = worldRotation * (float)Math.PI / 180;
|
||||
float cos = (float)Math.Cos(radians);
|
||||
float sin = (float)Math.Sin(radians);
|
||||
if (worldFlipX) {
|
||||
m00 = -cos * worldScaleX;
|
||||
m01 = sin * worldScaleY;
|
||||
} else {
|
||||
m00 = cos * worldScaleX;
|
||||
m01 = -sin * worldScaleY;
|
||||
}
|
||||
if (worldFlipY != yDown) {
|
||||
m10 = -sin * worldScaleX;
|
||||
m11 = -cos * worldScaleY;
|
||||
} else {
|
||||
m10 = sin * worldScaleX;
|
||||
m11 = cos * worldScaleY;
|
||||
}
|
||||
UpdateWorldTransform(x, y, rotation, scaleX, scaleY);
|
||||
}
|
||||
|
||||
/// <summary>Computes the world SRT using the parent bone and the specified local SRT.</summary>
|
||||
public void UpdateWorldTransform (float x, float y, float rotation, float scaleX, float scaleY) {
|
||||
appliedRotation = rotation;
|
||||
appliedScaleX = scaleX;
|
||||
appliedScaleY = scaleY;
|
||||
|
||||
float cos = MathUtils.CosDeg(rotation), sin = MathUtils.SinDeg(rotation);
|
||||
float la = cos * scaleX, lb = -sin * scaleY, lc = sin * scaleX, ld = cos * scaleY;
|
||||
Bone parent = this.parent;
|
||||
if (parent == null) { // Root bone.
|
||||
Skeleton skeleton = this.skeleton;
|
||||
if (skeleton.flipX) {
|
||||
la = -la;
|
||||
lc = -lc;
|
||||
scaleX = -scaleX;
|
||||
x = -x;
|
||||
}
|
||||
if (skeleton.flipY != yDown) {
|
||||
lb = -lb;
|
||||
ld = -ld;
|
||||
scaleY = -scaleY;
|
||||
y = -y;
|
||||
}
|
||||
a = la;
|
||||
b = lb;
|
||||
c = lc;
|
||||
d = ld;
|
||||
worldX = x;
|
||||
worldY = y;
|
||||
worldSignX = Math.Sign(scaleX);
|
||||
worldSignY = Math.Sign(scaleY);
|
||||
return;
|
||||
}
|
||||
|
||||
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
|
||||
worldX = pa * x + pb * y + parent.worldX;
|
||||
worldY = pc * x + pd * y + parent.worldY;
|
||||
worldSignX = parent.worldSignX * Math.Sign(scaleX);
|
||||
worldSignY = parent.worldSignY * Math.Sign(scaleY);
|
||||
|
||||
if (data.inheritRotation && data.inheritScale) {
|
||||
a = pa * la + pb * lc;
|
||||
b = pa * lb + pb * ld;
|
||||
c = pc * la + pd * lc;
|
||||
d = pc * lb + pd * ld;
|
||||
} else if (data.inheritRotation) { // No scale inheritance.
|
||||
Bone p = parent;
|
||||
pa = 1;
|
||||
pb = 0;
|
||||
pc = 0;
|
||||
pd = 1;
|
||||
while (p != null) {
|
||||
cos = MathUtils.CosDeg(p.appliedRotation);
|
||||
sin = MathUtils.SinDeg(p.appliedRotation);
|
||||
float a = pa * cos + pb * sin;
|
||||
float b = pa * -sin + pb * cos;
|
||||
float c = pc * cos + pd * sin;
|
||||
float d = pc * -sin + pd * cos;
|
||||
pa = a;
|
||||
pb = b;
|
||||
pc = c;
|
||||
pd = d;
|
||||
p = p.parent;
|
||||
}
|
||||
if (yDown) {
|
||||
pb = -pb;
|
||||
pd = -pd;
|
||||
}
|
||||
this.a = pa * la + pb * lc;
|
||||
this.b = pa * lb + pb * ld;
|
||||
this.c = pc * la + pd * lc;
|
||||
this.d = pc * lb + pd * ld;
|
||||
} else if (data.inheritScale) { // No rotation inheritance.
|
||||
Bone p = parent;
|
||||
pa = 1;
|
||||
pb = 0;
|
||||
pc = 0;
|
||||
pd = 1;
|
||||
while (p != null) {
|
||||
float r = p.rotation;
|
||||
cos = MathUtils.CosDeg(r);
|
||||
sin = MathUtils.SinDeg(r);
|
||||
float psx = p.appliedScaleX, psy = p.appliedScaleY;
|
||||
float za = cos * psx, zb = -sin * psy, zc = sin * psx, zd = cos * psy;
|
||||
float temp = pa * za + pb * zc;
|
||||
pb = pa * zb + pb * zd;
|
||||
pa = temp;
|
||||
temp = pc * za + pd * zc;
|
||||
pd = pc * zb + pd * zd;
|
||||
pc = temp;
|
||||
|
||||
if (psx < 0) r = -r;
|
||||
cos = MathUtils.CosDeg(-r);
|
||||
sin = MathUtils.SinDeg(-r);
|
||||
temp = pa * cos + pb * sin;
|
||||
pb = pa * -sin + pb * cos;
|
||||
pa = temp;
|
||||
temp = pc * cos + pd * sin;
|
||||
pd = pc * -sin + pd * cos;
|
||||
pc = temp;
|
||||
|
||||
p = p.parent;
|
||||
}
|
||||
if (yDown) {
|
||||
pb = -pb;
|
||||
pd = -pd;
|
||||
}
|
||||
a = pa * la + pb * lc;
|
||||
b = pa * lb + pb * ld;
|
||||
c = pc * la + pd * lc;
|
||||
d = pc * lb + pd * ld;
|
||||
} else {
|
||||
a = la;
|
||||
b = lb;
|
||||
c = lc;
|
||||
d = ld;
|
||||
}
|
||||
}
|
||||
|
||||
public void Update () {
|
||||
UpdateWorldTransform(x, y, rotation, scaleX, scaleY);
|
||||
}
|
||||
|
||||
public void SetToSetupPose () {
|
||||
BoneData data = this.data;
|
||||
x = data.x;
|
||||
y = data.y;
|
||||
rotation = data.rotation;
|
||||
rotationIK = rotation;
|
||||
scaleX = data.scaleX;
|
||||
scaleY = data.scaleY;
|
||||
flipX = data.flipX;
|
||||
flipY = data.flipY;
|
||||
BoneData data = this.data;
|
||||
x = data.x;
|
||||
y = data.y;
|
||||
rotation = data.rotation;
|
||||
scaleX = data.scaleX;
|
||||
scaleY = data.scaleY;
|
||||
}
|
||||
|
||||
public void worldToLocal (float worldX, float worldY, out float localX, out float localY) {
|
||||
float dx = worldX - this.worldX, dy = worldY - this.worldY;
|
||||
float m00 = this.m00, m10 = this.m10, m01 = this.m01, m11 = this.m11;
|
||||
if (worldFlipX != (worldFlipY != yDown)) {
|
||||
m00 = -m00;
|
||||
m11 = -m11;
|
||||
}
|
||||
float invDet = 1 / (m00 * m11 - m01 * m10);
|
||||
localX = (dx * m00 * invDet - dy * m01 * invDet);
|
||||
localY = (dy * m11 * invDet - dx * m10 * invDet);
|
||||
public void WorldToLocal (float worldX, float worldY, out float localX, out float localY) {
|
||||
float x = worldX - this.worldX, y = worldY - this.worldY;
|
||||
float a = this.a, b = this.b, c = this.c, d = this.d;
|
||||
float invDet = 1 / (a * d - b * c);
|
||||
localX = (x * a * invDet - y * b * invDet);
|
||||
localY = (y * d * invDet - x * c * invDet);
|
||||
}
|
||||
|
||||
public void localToWorld (float localX, float localY, out float worldX, out float worldY) {
|
||||
worldX = localX * m00 + localY * m01 + this.worldX;
|
||||
worldY = localX * m10 + localY * m11 + this.worldY;
|
||||
public void LocalToWorld (float localX, float localY, out float worldX, out float worldY) {
|
||||
float x = localX, y = localY;
|
||||
worldX = x * a + y * b + this.worldX;
|
||||
worldY = x * c + y * d + this.worldY;
|
||||
}
|
||||
|
||||
override public String ToString () {
|
||||
|
||||
@ -36,7 +36,6 @@ namespace Spine {
|
||||
internal BoneData parent;
|
||||
internal String name;
|
||||
internal float length, x, y, rotation, scaleX = 1, scaleY = 1;
|
||||
internal bool flipX, flipY;
|
||||
internal bool inheritScale = true, inheritRotation = true;
|
||||
|
||||
/// <summary>May be null.</summary>
|
||||
@ -48,8 +47,6 @@ namespace Spine {
|
||||
public float Rotation { get { return rotation; } set { rotation = value; } }
|
||||
public float ScaleX { get { return scaleX; } set { scaleX = value; } }
|
||||
public float ScaleY { get { return scaleY; } set { scaleY = value; } }
|
||||
public bool FlipX { get { return flipX; } set { flipX = value; } }
|
||||
public bool FlipY { get { return flipY; } set { flipY = value; } }
|
||||
public bool InheritScale { get { return inheritScale; } set { inheritScale = value; } }
|
||||
public bool InheritRotation { get { return inheritRotation; } set { inheritRotation = value; } }
|
||||
|
||||
|
||||
@ -37,8 +37,9 @@ namespace Spine {
|
||||
public int Int { get; set; }
|
||||
public float Float { get; set; }
|
||||
public String String { get; set; }
|
||||
public float Time { get; private set; }
|
||||
|
||||
public Event (EventData data) {
|
||||
public Event (float time, EventData data) {
|
||||
Data = data;
|
||||
}
|
||||
|
||||
|
||||
38
spine-csharp/src/IUpdatable.cs
Normal file
38
spine-csharp/src/IUpdatable.cs
Normal file
@ -0,0 +1,38 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes Software License
|
||||
* Version 2.3
|
||||
*
|
||||
* Copyright (c) 2013-2015, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* You are granted a perpetual, non-exclusive, non-sublicensable and
|
||||
* non-transferable license to use, install, execute and perform the Spine
|
||||
* Runtimes Software (the "Software") and derivative works solely for personal
|
||||
* or internal use. Without the written permission of Esoteric Software (see
|
||||
* Section 2 of the Spine Software License Agreement), you may not (a) modify,
|
||||
* translate, adapt or otherwise create derivative works, improvements of the
|
||||
* Software or develop new applications using the Software or (b) remove,
|
||||
* delete, alter or obscure any trademarks or any copyright, trademark, patent
|
||||
* or other intellectual property or proprietary rights notices on or in the
|
||||
* Software, including any copy thereof. Redistributions in binary or source
|
||||
* form must include this license and terms.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Spine {
|
||||
public interface IUpdatable {
|
||||
void Update ();
|
||||
}
|
||||
}
|
||||
@ -33,9 +33,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine {
|
||||
public class IkConstraint {
|
||||
private const float radDeg = 180 / (float)Math.PI;
|
||||
|
||||
public class IkConstraint : IUpdatable {
|
||||
internal IkConstraintData data;
|
||||
internal ExposedList<Bone> bones = new ExposedList<Bone>();
|
||||
internal Bone target;
|
||||
@ -61,15 +59,19 @@ namespace Spine {
|
||||
target = skeleton.FindBone(data.target.name);
|
||||
}
|
||||
|
||||
public void apply () {
|
||||
public void Update () {
|
||||
Apply();
|
||||
}
|
||||
|
||||
public void Apply () {
|
||||
Bone target = this.target;
|
||||
ExposedList<Bone> bones = this.bones;
|
||||
switch (bones.Count) {
|
||||
case 1:
|
||||
apply(bones.Items[0], target.worldX, target.worldY, mix);
|
||||
Apply(bones.Items[0], target.worldX, target.worldY, mix);
|
||||
break;
|
||||
case 2:
|
||||
apply(bones.Items[0], bones.Items[1], target.worldX, target.worldY, bendDirection, mix);
|
||||
Apply(bones.Items[0], bones.Items[1], target.worldX, target.worldY, bendDirection, mix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -80,72 +82,137 @@ namespace Spine {
|
||||
|
||||
/// <summary>Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified
|
||||
/// in the world coordinate system.</summary>
|
||||
static public void apply (Bone bone, float targetX, float targetY, float alpha) {
|
||||
float parentRotation = (!bone.data.inheritRotation || bone.parent == null) ? 0 : bone.parent.worldRotation;
|
||||
static public void Apply (Bone bone, float targetX, float targetY, float alpha) {
|
||||
float parentRotation = bone.parent == null ? 0 : bone.parent.WorldRotationX;
|
||||
float rotation = bone.rotation;
|
||||
float rotationIK = (float)Math.Atan2(targetY - bone.worldY, targetX - bone.worldX) * radDeg;
|
||||
if (bone.worldFlipX != (bone.worldFlipY != Bone.yDown)) rotationIK = -rotationIK;
|
||||
rotationIK -= parentRotation;
|
||||
bone.rotationIK = rotation + (rotationIK - rotation) * alpha;
|
||||
float rotationIK = MathUtils.Atan2(targetY - bone.worldY, targetX - bone.worldX) * MathUtils.radDeg - parentRotation;
|
||||
if (bone.worldSignX != bone.worldSignY) rotationIK = 360 - rotationIK;
|
||||
if (rotationIK > 180) rotationIK -= 360;
|
||||
else if (rotationIK < -180) rotationIK += 360;
|
||||
bone.UpdateWorldTransform(bone.x, bone.y, rotation + (rotationIK - rotation) * alpha, bone.scaleX, bone.scaleY);
|
||||
}
|
||||
|
||||
/// <summary>Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as
|
||||
/// possible. The target is specified in the world coordinate system.</summary>
|
||||
/// <param name="child">Any descendant bone of the parent.</param>
|
||||
static public void apply (Bone parent, Bone child, float targetX, float targetY, int bendDirection, float alpha) {
|
||||
float childRotation = child.rotation, parentRotation = parent.rotation;
|
||||
if (alpha == 0) {
|
||||
child.rotationIK = childRotation;
|
||||
parent.rotationIK = parentRotation;
|
||||
return;
|
||||
}
|
||||
float positionX, positionY;
|
||||
Bone parentParent = parent.parent;
|
||||
if (parentParent != null) {
|
||||
parentParent.worldToLocal(targetX, targetY, out positionX, out positionY);
|
||||
targetX = (positionX - parent.x) * parentParent.worldScaleX;
|
||||
targetY = (positionY - parent.y) * parentParent.worldScaleY;
|
||||
/// <param name="child">A direct descendant of the parent bone.</param>
|
||||
static public void Apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) {
|
||||
if (alpha == 0) return;
|
||||
float px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY, csx = child.scaleX, cy = child.y;
|
||||
int offset1, offset2, sign2;
|
||||
if (psx < 0) {
|
||||
psx = -psx;
|
||||
offset1 = 180;
|
||||
sign2 = -1;
|
||||
} else {
|
||||
targetX -= parent.x;
|
||||
targetY -= parent.y;
|
||||
offset1 = 0;
|
||||
sign2 = 1;
|
||||
}
|
||||
if (child.parent == parent) {
|
||||
positionX = child.x;
|
||||
positionY = child.y;
|
||||
if (psy < 0) {
|
||||
psy = -psy;
|
||||
sign2 = -sign2;
|
||||
}
|
||||
if (csx < 0) {
|
||||
csx = -csx;
|
||||
offset2 = 180;
|
||||
} else
|
||||
offset2 = 0;
|
||||
Bone pp = parent.parent;
|
||||
float tx, ty, dx, dy;
|
||||
if (pp == null) {
|
||||
tx = targetX - px;
|
||||
ty = targetY - py;
|
||||
dx = child.worldX - px;
|
||||
dy = child.worldY - py;
|
||||
} else {
|
||||
child.parent.localToWorld(child.x, child.y, out positionX, out positionY);
|
||||
parent.worldToLocal(positionX, positionY, out positionX, out positionY);
|
||||
float a = pp.a, b = pp.b, c = pp.c, d = pp.d, invDet = 1 / (a * d - b * c);
|
||||
float wx = pp.worldX, wy = pp.worldY, x = targetX - wx, y = targetY - wy;
|
||||
tx = (x * d - y * b) * invDet - px;
|
||||
ty = (y * a - x * c) * invDet - py;
|
||||
x = child.worldX - wx;
|
||||
y = child.worldY - wy;
|
||||
dx = (x * d - y * b) * invDet - px;
|
||||
dy = (y * a - x * c) * invDet - py;
|
||||
}
|
||||
float childX = positionX * parent.worldScaleX, childY = positionY * parent.worldScaleY;
|
||||
float offset = (float)Math.Atan2(childY, childX);
|
||||
float len1 = (float)Math.Sqrt(childX * childX + childY * childY), len2 = child.data.length * child.worldScaleX;
|
||||
// Based on code by Ryan Juckett with permission: Copyright (c) 2008-2009 Ryan Juckett, http://www.ryanjuckett.com/
|
||||
float cosDenom = 2 * len1 * len2;
|
||||
if (cosDenom < 0.0001f) {
|
||||
child.rotationIK = childRotation + ((float)Math.Atan2(targetY, targetX) * radDeg - parentRotation - childRotation)
|
||||
* alpha;
|
||||
return;
|
||||
float l1 = (float)Math.Sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2;
|
||||
if (Math.Abs(psx - psy) <= 0.0001f) {
|
||||
l2 *= psx;
|
||||
float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2);
|
||||
if (cos < -1)
|
||||
cos = -1;
|
||||
else if (cos > 1) cos = 1;
|
||||
a2 = (float)Math.Acos(cos) * bendDir;
|
||||
float a = l1 + l2 * cos, o = l2 * MathUtils.Sin(a2);
|
||||
a1 = MathUtils.Atan2(ty * a - tx * o, tx * a + ty * o);
|
||||
} else {
|
||||
cy = 0;
|
||||
float a = psx * l2, b = psy * l2, ta = MathUtils.Atan2(ty, tx);
|
||||
float aa = a * a, bb = b * b, ll = l1 * l1, dd = tx * tx + ty * ty;
|
||||
float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa;
|
||||
float d = c1 * c1 - 4 * c2 * c0;
|
||||
if (d >= 0) {
|
||||
float q = (float)Math.Sqrt(d);
|
||||
if (c1 < 0) q = -q;
|
||||
q = -(c1 + q) / 2;
|
||||
float r0 = q / c2, r1 = c0 / q;
|
||||
float r = Math.Abs(r0) < Math.Abs(r1) ? r0 : r1;
|
||||
if (r * r <= dd) {
|
||||
float y1 = (float)Math.Sqrt(dd - r * r) * bendDir;
|
||||
a1 = ta - MathUtils.Atan2(y1, r);
|
||||
a2 = MathUtils.Atan2(y1 / psy, (r - l1) / psx);
|
||||
goto outer;
|
||||
}
|
||||
}
|
||||
float minAngle = 0, minDist = float.MaxValue, minX = 0, minY = 0;
|
||||
float maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0;
|
||||
float x = l1 + a, dist = x * x;
|
||||
if (dist > maxDist) {
|
||||
maxAngle = 0;
|
||||
maxDist = dist;
|
||||
maxX = x;
|
||||
}
|
||||
x = l1 - a;
|
||||
dist = x * x;
|
||||
if (dist < minDist) {
|
||||
minAngle = MathUtils.PI;
|
||||
minDist = dist;
|
||||
minX = x;
|
||||
}
|
||||
float angle = (float)Math.Acos(-a * l1 / (aa - bb));
|
||||
x = a * MathUtils.Cos(angle) + l1;
|
||||
float y = b * MathUtils.Sin(angle);
|
||||
dist = x * x + y * y;
|
||||
if (dist < minDist) {
|
||||
minAngle = angle;
|
||||
minDist = dist;
|
||||
minX = x;
|
||||
minY = y;
|
||||
}
|
||||
if (dist > maxDist) {
|
||||
maxAngle = angle;
|
||||
maxDist = dist;
|
||||
maxX = x;
|
||||
maxY = y;
|
||||
}
|
||||
if (dd <= (minDist + maxDist) / 2) {
|
||||
a1 = ta - MathUtils.Atan2(minY * bendDir, minX);
|
||||
a2 = minAngle * bendDir;
|
||||
} else {
|
||||
a1 = ta - MathUtils.Atan2(maxY * bendDir, maxX);
|
||||
a2 = maxAngle * bendDir;
|
||||
}
|
||||
}
|
||||
float cos = (targetX * targetX + targetY * targetY - len1 * len1 - len2 * len2) / cosDenom;
|
||||
if (cos < -1)
|
||||
cos = -1;
|
||||
else if (cos > 1)
|
||||
cos = 1;
|
||||
float childAngle = (float)Math.Acos(cos) * bendDirection;
|
||||
float adjacent = len1 + len2 * cos, opposite = len2 * (float)Math.Sin(childAngle);
|
||||
float parentAngle = (float)Math.Atan2(targetY * adjacent - targetX * opposite, targetX * adjacent + targetY * opposite);
|
||||
float rotation = (parentAngle - offset) * radDeg - parentRotation;
|
||||
if (rotation > 180)
|
||||
rotation -= 360;
|
||||
else if (rotation < -180) //
|
||||
rotation += 360;
|
||||
parent.rotationIK = parentRotation + rotation * alpha;
|
||||
rotation = (childAngle + offset) * radDeg - childRotation;
|
||||
if (rotation > 180)
|
||||
rotation -= 360;
|
||||
else if (rotation < -180) //
|
||||
rotation += 360;
|
||||
child.rotationIK = childRotation + (rotation + parent.worldRotation - child.parent.worldRotation) * alpha;
|
||||
outer:
|
||||
float offset = MathUtils.Atan2(cy, child.x) * sign2;
|
||||
a1 = (a1 - offset) * MathUtils.radDeg + offset1;
|
||||
a2 = (a2 + offset) * MathUtils.radDeg * sign2 + offset2;
|
||||
if (a1 > 180) a1 -= 360;
|
||||
else if (a1 < -180) a1 += 360;
|
||||
if (a2 > 180) a2 -= 360;
|
||||
else if (a2 < -180) a2 += 360;
|
||||
float rotation = parent.rotation;
|
||||
parent.UpdateWorldTransform(parent.x, parent.y, rotation + (a1 - rotation) * alpha, parent.scaleX, parent.scaleY);
|
||||
rotation = child.rotation;
|
||||
child.UpdateWorldTransform(child.x, cy, rotation + (a2 - rotation) * alpha, child.scaleX, child.scaleY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
94
spine-csharp/src/MathUtils.cs
Normal file
94
spine-csharp/src/MathUtils.cs
Normal file
@ -0,0 +1,94 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes Software License
|
||||
* Version 2.3
|
||||
*
|
||||
* Copyright (c) 2013-2015, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* You are granted a perpetual, non-exclusive, non-sublicensable and
|
||||
* non-transferable license to use, install, execute and perform the Spine
|
||||
* Runtimes Software (the "Software") and derivative works solely for personal
|
||||
* or internal use. Without the written permission of Esoteric Software (see
|
||||
* Section 2 of the Spine Software License Agreement), you may not (a) modify,
|
||||
* translate, adapt or otherwise create derivative works, improvements of the
|
||||
* Software or develop new applications using the Software or (b) remove,
|
||||
* delete, alter or obscure any trademarks or any copyright, trademark, patent
|
||||
* or other intellectual property or proprietary rights notices on or in the
|
||||
* Software, including any copy thereof. Redistributions in binary or source
|
||||
* form must include this license and terms.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Spine {
|
||||
public class MathUtils {
|
||||
static public float PI = 3.1415927f;
|
||||
static public float radDeg = 180f / PI;
|
||||
static public float degRad = PI / 180;
|
||||
|
||||
static private int SIN_BITS = 14; // 16KB. Adjust for accuracy.
|
||||
static private int SIN_MASK = ~(-1 << SIN_BITS);
|
||||
static private int SIN_COUNT = SIN_MASK + 1;
|
||||
static private float radFull = PI * 2;
|
||||
static private float degFull = 360;
|
||||
static private float radToIndex = SIN_COUNT / radFull;
|
||||
static private float degToIndex = SIN_COUNT / degFull;
|
||||
static float[] sin = new float[SIN_COUNT];
|
||||
|
||||
static MathUtils () {
|
||||
for (int i = 0; i < SIN_COUNT; i++)
|
||||
sin[i] = (float)Math.Sin((i + 0.5f) / SIN_COUNT * radFull);
|
||||
for (int i = 0; i < 360; i += 90)
|
||||
sin[(int)(i * degToIndex) & SIN_MASK] = (float)Math.Sin(i * degRad);
|
||||
}
|
||||
|
||||
/** Returns the sine in radians from a lookup table. */
|
||||
static public float Sin (float radians) {
|
||||
return sin[(int)(radians * radToIndex) & SIN_MASK];
|
||||
}
|
||||
|
||||
/** Returns the cosine in radians from a lookup table. */
|
||||
static public float Cos (float radians) {
|
||||
return sin[(int)((radians + PI / 2) * radToIndex) & SIN_MASK];
|
||||
}
|
||||
|
||||
/** Returns the sine in radians from a lookup table. */
|
||||
static public float SinDeg (float degrees) {
|
||||
return sin[(int)(degrees * degToIndex) & SIN_MASK];
|
||||
}
|
||||
|
||||
/** Returns the cosine in radians from a lookup table. */
|
||||
static public float CosDeg (float degrees) {
|
||||
return sin[(int)((degrees + 90) * degToIndex) & SIN_MASK];
|
||||
}
|
||||
|
||||
/// <summary>Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323
|
||||
/// degrees), largest error of 0.00488 radians (0.2796 degrees).</summary>
|
||||
static public float Atan2 (float y, float x) {
|
||||
if (x == 0f) {
|
||||
if (y > 0f) return PI / 2;
|
||||
if (y == 0f) return 0f;
|
||||
return -PI / 2;
|
||||
}
|
||||
float atan, z = y / x;
|
||||
if (Math.Abs(z) < 1f) {
|
||||
atan = z / (1f + 0.28f * z * z);
|
||||
if (x < 0f) return atan + (y < 0f ? -PI : PI);
|
||||
return atan;
|
||||
}
|
||||
atan = PI / 2 - z / (z * z + 0.28f);
|
||||
return y < 0f ? atan - PI : atan;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -39,7 +39,8 @@ namespace Spine {
|
||||
internal ExposedList<Slot> slots;
|
||||
internal ExposedList<Slot> drawOrder;
|
||||
internal ExposedList<IkConstraint> ikConstraints;
|
||||
private ExposedList<ExposedList<Bone>> boneCache = new ExposedList<ExposedList<Bone>>();
|
||||
internal ExposedList<TransformConstraint> transformConstraints;
|
||||
private ExposedList<IUpdatable> updateCache = new ExposedList<IUpdatable>();
|
||||
internal Skin skin;
|
||||
internal float r = 1, g = 1, b = 1, a = 1;
|
||||
internal float time;
|
||||
@ -89,81 +90,62 @@ namespace Spine {
|
||||
drawOrder.Add(slot);
|
||||
}
|
||||
|
||||
ikConstraints = new ExposedList<IkConstraint>(data.ikConstraints.Count);
|
||||
foreach (IkConstraintData ikConstraintData in data.ikConstraints)
|
||||
ikConstraints.Add(new IkConstraint(ikConstraintData, this));
|
||||
ikConstraints = new ExposedList<IkConstraint>(data.ikConstraints.Count);
|
||||
foreach (IkConstraintData ikConstraintData in data.ikConstraints)
|
||||
ikConstraints.Add(new IkConstraint(ikConstraintData, this));
|
||||
|
||||
transformConstraints = new ExposedList<TransformConstraint>(data.transformConstraints.Count);
|
||||
foreach (TransformConstraintData transformConstraintData in data.transformConstraints)
|
||||
transformConstraints.Add(new TransformConstraint(transformConstraintData, this));
|
||||
|
||||
UpdateCache();
|
||||
UpdateWorldTransform();
|
||||
}
|
||||
|
||||
/// <summary>Caches information about bones and IK constraints. Must be called if bones or IK constraints are added or
|
||||
/// removed.</summary>
|
||||
/// <summary>Caches information about bones and constraints. Must be called if bones or constraints are added
|
||||
/// or removed.</summary>
|
||||
public void UpdateCache () {
|
||||
ExposedList<ExposedList<Bone>> boneCache = this.boneCache;
|
||||
ExposedList<Bone> bones = this.bones;
|
||||
ExposedList<IUpdatable> updateCache = this.updateCache;
|
||||
ExposedList<IkConstraint> ikConstraints = this.ikConstraints;
|
||||
ExposedList<TransformConstraint> transformConstraints = this.transformConstraints;
|
||||
int ikConstraintsCount = ikConstraints.Count;
|
||||
|
||||
int arrayCount = ikConstraintsCount + 1;
|
||||
if (boneCache.Count > arrayCount) boneCache.RemoveRange(arrayCount, boneCache.Count - arrayCount);
|
||||
for (int i = 0, n = boneCache.Count; i < n; i++)
|
||||
boneCache.Items[i].Clear();
|
||||
while (boneCache.Count < arrayCount)
|
||||
boneCache.Add(new ExposedList<Bone>());
|
||||
|
||||
ExposedList<Bone> nonIkBones = boneCache.Items[0];
|
||||
|
||||
int transformConstraintsCount = transformConstraints.Count;
|
||||
updateCache.Clear();
|
||||
for (int i = 0, n = bones.Count; i < n; i++) {
|
||||
Bone bone = bones.Items[i];
|
||||
Bone current = bone;
|
||||
do {
|
||||
for (int ii = 0; ii < ikConstraintsCount; ii++) {
|
||||
IkConstraint ikConstraint = ikConstraints.Items[ii];
|
||||
Bone parent = ikConstraint.bones.Items[0];
|
||||
Bone child = ikConstraint.bones.Items[ikConstraint.bones.Count - 1];
|
||||
while (true) {
|
||||
if (current == child) {
|
||||
boneCache.Items[ii].Add(bone);
|
||||
boneCache.Items[ii + 1].Add(bone);
|
||||
goto outer;
|
||||
}
|
||||
if (child == parent) break;
|
||||
child = child.parent;
|
||||
}
|
||||
updateCache.Add(bone);
|
||||
for (int ii = 0; ii < transformConstraintsCount; ii++) {
|
||||
TransformConstraint transformConstraint = transformConstraints.Items[ii];
|
||||
if (bone == transformConstraint.bone) {
|
||||
updateCache.Add(transformConstraint);
|
||||
break;
|
||||
}
|
||||
current = current.parent;
|
||||
} while (current != null);
|
||||
nonIkBones.Add(bone);
|
||||
outer: { }
|
||||
}
|
||||
for (int ii = 0; ii < ikConstraintsCount; ii++) {
|
||||
IkConstraint ikConstraint = ikConstraints.Items[ii];
|
||||
if (bone == ikConstraint.bones.Items[ikConstraint.bones.Count - 1]) {
|
||||
updateCache.Add(ikConstraint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Updates the world transform for each bone and applies IK constraints.</summary>
|
||||
public void UpdateWorldTransform () {
|
||||
ExposedList<Bone> bones = this.bones;
|
||||
for (int ii = 0, nn = bones.Count; ii < nn; ii++) {
|
||||
Bone bone = bones.Items[ii];
|
||||
bone.rotationIK = bone.rotation;
|
||||
}
|
||||
ExposedList<ExposedList<Bone>> boneCache = this.boneCache;
|
||||
ExposedList<IkConstraint> ikConstraints = this.ikConstraints;
|
||||
int i = 0, last = boneCache.Count - 1;
|
||||
while (true) {
|
||||
ExposedList<Bone> updateBones = boneCache.Items[i];
|
||||
for (int ii = 0, nn = updateBones.Count; ii < nn; ii++)
|
||||
updateBones.Items[ii].UpdateWorldTransform();
|
||||
if (i == last) break;
|
||||
ikConstraints.Items[i].apply();
|
||||
i++;
|
||||
}
|
||||
ExposedList<IUpdatable> updateCache = this.updateCache;
|
||||
for (int i = 0, n = updateCache.Count; i < n; i++)
|
||||
updateCache.Items[i].Update();
|
||||
}
|
||||
|
||||
/// <summary>Sets the bones and slots to their setup pose values.</summary>
|
||||
/// <summary>Sets the bones, constraints, and slots to their setup pose values.</summary>
|
||||
public void SetToSetupPose () {
|
||||
SetBonesToSetupPose();
|
||||
SetSlotsToSetupPose();
|
||||
}
|
||||
|
||||
/// <summary>Sets the bones and constraints to their setup pose values.</summary>
|
||||
public void SetBonesToSetupPose () {
|
||||
ExposedList<Bone> bones = this.bones;
|
||||
for (int i = 0, n = bones.Count; i < n; i++)
|
||||
@ -171,9 +153,17 @@ namespace Spine {
|
||||
|
||||
ExposedList<IkConstraint> ikConstraints = this.ikConstraints;
|
||||
for (int i = 0, n = ikConstraints.Count; i < n; i++) {
|
||||
IkConstraint ikConstraint = ikConstraints.Items[i];
|
||||
ikConstraint.bendDirection = ikConstraint.data.bendDirection;
|
||||
ikConstraint.mix = ikConstraint.data.mix;
|
||||
IkConstraint constraint = ikConstraints.Items[i];
|
||||
constraint.bendDirection = constraint.data.bendDirection;
|
||||
constraint.mix = constraint.data.mix;
|
||||
}
|
||||
|
||||
ExposedList<TransformConstraint> transformConstraints = this.transformConstraints;
|
||||
for (int i = 0, n = transformConstraints.Count; i < n; i++) {
|
||||
TransformConstraint constraint = transformConstraints.Items[i];
|
||||
constraint.translateMix = constraint.data.translateMix;
|
||||
constraint.x = constraint.data.x;
|
||||
constraint.y = constraint.data.y;
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,12 +283,23 @@ namespace Spine {
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public IkConstraint FindIkConstraint (String ikConstraintName) {
|
||||
if (ikConstraintName == null) throw new ArgumentNullException("ikConstraintName cannot be null.");
|
||||
public IkConstraint FindIkConstraint (String constraintName) {
|
||||
if (constraintName == null) throw new ArgumentNullException("constraintName cannot be null.");
|
||||
ExposedList<IkConstraint> ikConstraints = this.ikConstraints;
|
||||
for (int i = 0, n = ikConstraints.Count; i < n; i++) {
|
||||
IkConstraint ikConstraint = ikConstraints.Items[i];
|
||||
if (ikConstraint.data.name == ikConstraintName) return ikConstraint;
|
||||
if (ikConstraint.data.name == constraintName) return ikConstraint;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public TransformConstraint FindTransformConstraint (String constraintName) {
|
||||
if (constraintName == null) throw new ArgumentNullException("constraintName cannot be null.");
|
||||
ExposedList<TransformConstraint> transformConstraints = this.transformConstraints;
|
||||
for (int i = 0, n = transformConstraints.Count; i < n; i++) {
|
||||
TransformConstraint transformConstraint = transformConstraints.Items[i];
|
||||
if (transformConstraint.data.name == constraintName) return transformConstraint;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -45,8 +45,6 @@ namespace Spine {
|
||||
public const int TIMELINE_TRANSLATE = 2;
|
||||
public const int TIMELINE_ATTACHMENT = 3;
|
||||
public const int TIMELINE_COLOR = 4;
|
||||
public const int TIMELINE_FLIPX = 5;
|
||||
public const int TIMELINE_FLIPY = 6;
|
||||
|
||||
public const int CURVE_LINEAR = 0;
|
||||
public const int CURVE_STEPPED = 1;
|
||||
@ -130,8 +128,6 @@ namespace Spine {
|
||||
boneData.scaleY = ReadFloat(input);
|
||||
boneData.rotation = ReadFloat(input);
|
||||
boneData.length = ReadFloat(input) * scale;
|
||||
boneData.flipX = ReadBoolean(input);
|
||||
boneData.flipY = ReadBoolean(input);
|
||||
boneData.inheritScale = ReadBoolean(input);
|
||||
boneData.inheritRotation = ReadBoolean(input);
|
||||
if (nonessential) ReadInt(input); // Skip bone color.
|
||||
@ -149,6 +145,17 @@ namespace Spine {
|
||||
skeletonData.ikConstraints.Add(ikConstraintData);
|
||||
}
|
||||
|
||||
// Transform constraints.
|
||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
||||
TransformConstraintData transformConstraintData = new TransformConstraintData(ReadString(input));
|
||||
transformConstraintData.bone = skeletonData.bones.Items[ReadInt(input, true)];
|
||||
transformConstraintData.target = skeletonData.bones.Items[ReadInt(input, true)];
|
||||
transformConstraintData.translateMix = ReadFloat(input);
|
||||
transformConstraintData.x = ReadFloat(input);
|
||||
transformConstraintData.y = ReadFloat(input);
|
||||
skeletonData.transformConstraints.Add(transformConstraintData);
|
||||
}
|
||||
|
||||
// Slots.
|
||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
||||
String slotName = ReadString(input);
|
||||
@ -269,10 +276,10 @@ namespace Spine {
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
case AttachmentType.skinnedmesh: {
|
||||
case AttachmentType.weightedmesh: {
|
||||
String path = ReadString(input);
|
||||
if (path == null) path = name;
|
||||
SkinnedMeshAttachment mesh = attachmentLoader.NewSkinnedMeshAttachment(skin, name, path);
|
||||
WeightedMeshAttachment mesh = attachmentLoader.NewWeightedMeshAttachment(skin, name, path);
|
||||
if (mesh == null) return null;
|
||||
mesh.Path = path;
|
||||
float[] uvs = ReadFloatArray(input, 1);
|
||||
@ -422,17 +429,6 @@ namespace Spine {
|
||||
duration = Math.Max(duration, timeline.frames[frameCount * 3 - 3]);
|
||||
break;
|
||||
}
|
||||
case TIMELINE_FLIPX:
|
||||
case TIMELINE_FLIPY: {
|
||||
FlipXTimeline timeline = timelineType == TIMELINE_FLIPX ? new FlipXTimeline(frameCount) : new FlipYTimeline(
|
||||
frameCount);
|
||||
timeline.boneIndex = boneIndex;
|
||||
for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
|
||||
timeline.SetFrame(frameIndex, ReadFloat(input), ReadBoolean(input));
|
||||
timelines.Add(timeline);
|
||||
duration = Math.Max(duration, timeline.frames[frameCount * 2 - 2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -470,7 +466,7 @@ namespace Spine {
|
||||
if (attachment is MeshAttachment)
|
||||
vertexCount = ((MeshAttachment)attachment).vertices.Length;
|
||||
else
|
||||
vertexCount = ((SkinnedMeshAttachment)attachment).weights.Length / 3 * 2;
|
||||
vertexCount = ((WeightedMeshAttachment)attachment).weights.Length / 3 * 2;
|
||||
|
||||
int end = ReadInt(input, true);
|
||||
if (end == 0) {
|
||||
@ -544,7 +540,7 @@ namespace Spine {
|
||||
for (int i = 0; i < eventCount; i++) {
|
||||
float time = ReadFloat(input);
|
||||
EventData eventData = skeletonData.events.Items[ReadInt(input, true)];
|
||||
Event e = new Event(eventData);
|
||||
Event e = new Event(time, eventData);
|
||||
e.Int = ReadInt(input, false);
|
||||
e.Float = ReadFloat(input);
|
||||
e.String = ReadBoolean(input) ? ReadString(input) : eventData.String;
|
||||
|
||||
@ -42,6 +42,7 @@ namespace Spine {
|
||||
internal ExposedList<EventData> events = new ExposedList<EventData>();
|
||||
internal ExposedList<Animation> animations = new ExposedList<Animation>();
|
||||
internal ExposedList<IkConstraintData> ikConstraints = new ExposedList<IkConstraintData>();
|
||||
internal ExposedList<TransformConstraintData> transformConstraints = new ExposedList<TransformConstraintData>();
|
||||
internal float width, height;
|
||||
internal String version, hash, imagesPath;
|
||||
|
||||
@ -140,12 +141,25 @@ namespace Spine {
|
||||
// --- IK constraints.
|
||||
|
||||
/// <returns>May be null.</returns>
|
||||
public IkConstraintData FindIkConstraint (String ikConstraintName) {
|
||||
if (ikConstraintName == null) throw new ArgumentNullException("ikConstraintName cannot be null.");
|
||||
public IkConstraintData FindIkConstraint (String constraintName) {
|
||||
if (constraintName == null) throw new ArgumentNullException("constraintName cannot be null.");
|
||||
ExposedList<IkConstraintData> ikConstraints = this.ikConstraints;
|
||||
for (int i = 0, n = ikConstraints.Count; i < n; i++) {
|
||||
IkConstraintData ikConstraint = ikConstraints.Items[i];
|
||||
if (ikConstraint.name == ikConstraintName) return ikConstraint;
|
||||
if (ikConstraint.name == constraintName) return ikConstraint;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// --- Transform constraints.
|
||||
|
||||
/// <returns>May be null.</returns>
|
||||
public TransformConstraintData FindTransformConstraint (String constraintName) {
|
||||
if (constraintName == null) throw new ArgumentNullException("constraintName cannot be null.");
|
||||
ExposedList<TransformConstraintData> transformConstraints = this.transformConstraints;
|
||||
for (int i = 0, n = transformConstraints.Count; i < n; i++) {
|
||||
TransformConstraintData transformConstraint = transformConstraints.Items[i];
|
||||
if (transformConstraint.name == constraintName) return transformConstraint;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -118,8 +118,6 @@ namespace Spine {
|
||||
boneData.rotation = GetFloat(boneMap, "rotation", 0);
|
||||
boneData.scaleX = GetFloat(boneMap, "scaleX", 1);
|
||||
boneData.scaleY = GetFloat(boneMap, "scaleY", 1);
|
||||
boneData.flipX = GetBoolean(boneMap, "flipX", false);
|
||||
boneData.flipY = GetBoolean(boneMap, "flipY", false);
|
||||
boneData.inheritScale = GetBoolean(boneMap, "inheritScale", true);
|
||||
boneData.inheritRotation = GetBoolean(boneMap, "inheritRotation", true);
|
||||
skeletonData.bones.Add(boneData);
|
||||
@ -147,6 +145,27 @@ namespace Spine {
|
||||
}
|
||||
}
|
||||
|
||||
// Transform constraints.
|
||||
if (root.ContainsKey("transform")) {
|
||||
foreach (Dictionary<String, Object> transformMap in (List<Object>)root["ik"]) {
|
||||
TransformConstraintData transformConstraintData = new TransformConstraintData((String)transformMap["name"]);
|
||||
|
||||
String boneName = (String)transformMap["bone"];
|
||||
transformConstraintData.target = skeletonData.FindBone(boneName);
|
||||
if (transformConstraintData.target == null) throw new Exception("Bone not found: " + boneName);
|
||||
|
||||
String targetName = (String)transformMap["target"];
|
||||
transformConstraintData.target = skeletonData.FindBone(targetName);
|
||||
if (transformConstraintData.target == null) throw new Exception("Target bone not found: " + targetName);
|
||||
|
||||
transformConstraintData.translateMix = GetFloat(transformMap, "mix", 1);
|
||||
transformConstraintData.x = GetFloat(transformMap, "x", 0);
|
||||
transformConstraintData.y = GetFloat(transformMap, "y", 0);
|
||||
|
||||
skeletonData.transformConstraints.Add(transformConstraintData);
|
||||
}
|
||||
}
|
||||
|
||||
// Slots.
|
||||
if (root.ContainsKey("slots")) {
|
||||
foreach (Dictionary<String, Object> slotMap in (List<Object>)root["slots"]) {
|
||||
@ -226,8 +245,11 @@ namespace Spine {
|
||||
name = (String)map["name"];
|
||||
|
||||
var type = AttachmentType.region;
|
||||
if (map.ContainsKey("type"))
|
||||
type = (AttachmentType)Enum.Parse(typeof(AttachmentType), (String)map["type"], false);
|
||||
if (map.ContainsKey("type")) {
|
||||
var typeName = (String)map["type"];
|
||||
if (typeName == "skinnedmesh") typeName = "weightedmesh";
|
||||
type = (AttachmentType)Enum.Parse(typeof(AttachmentType), typeName , false);
|
||||
}
|
||||
|
||||
String path = name;
|
||||
if (map.ContainsKey("path"))
|
||||
@ -281,8 +303,8 @@ namespace Spine {
|
||||
|
||||
return mesh;
|
||||
}
|
||||
case AttachmentType.skinnedmesh: {
|
||||
SkinnedMeshAttachment mesh = attachmentLoader.NewSkinnedMeshAttachment(skin, name, path);
|
||||
case AttachmentType.weightedmesh: {
|
||||
WeightedMeshAttachment mesh = attachmentLoader.NewWeightedMeshAttachment(skin, name, path);
|
||||
if (mesh == null) return null;
|
||||
|
||||
mesh.Path = path;
|
||||
@ -478,21 +500,6 @@ namespace Spine {
|
||||
timelines.Add(timeline);
|
||||
duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 3 - 3]);
|
||||
|
||||
} else if (timelineName == "flipX" || timelineName == "flipY") {
|
||||
bool x = timelineName == "flipX";
|
||||
var timeline = x ? new FlipXTimeline(values.Count) : new FlipYTimeline(values.Count);
|
||||
timeline.boneIndex = boneIndex;
|
||||
|
||||
String field = x ? "x" : "y";
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<String, Object> valueMap in values) {
|
||||
float time = (float)valueMap["time"];
|
||||
timeline.SetFrame(frameIndex, time, valueMap.ContainsKey(field) ? (bool)valueMap[field] : false);
|
||||
frameIndex++;
|
||||
}
|
||||
timelines.Add(timeline);
|
||||
duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 2 - 2]);
|
||||
|
||||
} else
|
||||
throw new Exception("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
|
||||
}
|
||||
@ -536,7 +543,7 @@ namespace Spine {
|
||||
if (attachment is MeshAttachment)
|
||||
vertexCount = ((MeshAttachment)attachment).vertices.Length;
|
||||
else
|
||||
vertexCount = ((SkinnedMeshAttachment)attachment).Weights.Length / 3 * 2;
|
||||
vertexCount = ((WeightedMeshAttachment)attachment).Weights.Length / 3 * 2;
|
||||
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<String, Object> valueMap in values) {
|
||||
@ -619,11 +626,12 @@ namespace Spine {
|
||||
foreach (Dictionary<String, Object> eventMap in eventsMap) {
|
||||
EventData eventData = skeletonData.FindEvent((String)eventMap["name"]);
|
||||
if (eventData == null) throw new Exception("Event not found: " + eventMap["name"]);
|
||||
var e = new Event(eventData);
|
||||
float time = (float)eventMap["time"];
|
||||
var e = new Event(time, eventData);
|
||||
e.Int = GetInt(eventMap, "int", eventData.Int);
|
||||
e.Float = GetFloat(eventMap, "float", eventData.Float);
|
||||
e.String = GetString(eventMap, "string", eventData.String);
|
||||
timeline.SetFrame(frameIndex++, (float)eventMap["time"], e);
|
||||
timeline.SetFrame(frameIndex++, time, e);
|
||||
}
|
||||
timelines.Add(timeline);
|
||||
duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]);
|
||||
|
||||
82
spine-csharp/src/TransformConstraint.cs
Normal file
82
spine-csharp/src/TransformConstraint.cs
Normal file
@ -0,0 +1,82 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes Software License
|
||||
* Version 2.3
|
||||
*
|
||||
* Copyright (c) 2013-2015, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* You are granted a perpetual, non-exclusive, non-sublicensable and
|
||||
* non-transferable license to use, install, execute and perform the Spine
|
||||
* Runtimes Software (the "Software") and derivative works solely for personal
|
||||
* or internal use. Without the written permission of Esoteric Software (see
|
||||
* Section 2 of the Spine Software License Agreement), you may not (a) modify,
|
||||
* translate, adapt or otherwise create derivative works, improvements of the
|
||||
* Software or develop new applications using the Software or (b) remove,
|
||||
* delete, alter or obscure any trademarks or any copyright, trademark, patent
|
||||
* or other intellectual property or proprietary rights notices on or in the
|
||||
* Software, including any copy thereof. Redistributions in binary or source
|
||||
* form must include this license and terms.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine {
|
||||
public class TransformConstraint : IUpdatable {
|
||||
internal TransformConstraintData data;
|
||||
internal Bone bone, target;
|
||||
internal float translateMix;
|
||||
internal float x, y;
|
||||
|
||||
public TransformConstraintData Data { get { return data; } }
|
||||
public Bone Bone { get { return bone; } set { bone = value; } }
|
||||
public Bone Target { get { return target; } set { target = value; } }
|
||||
public float TranslateMix { get { return translateMix; } set { translateMix = value; } }
|
||||
public float X { get { return x; } set { x = value; } }
|
||||
public float Y { get { return y; } set { y = value; } }
|
||||
|
||||
public TransformConstraint (TransformConstraintData data, Skeleton skeleton) {
|
||||
if (data == null) throw new ArgumentNullException("data cannot be null.");
|
||||
if (skeleton == null) throw new ArgumentNullException("skeleton cannot be null.");
|
||||
this.data = data;
|
||||
translateMix = data.translateMix;
|
||||
x = data.x;
|
||||
y = data.y;
|
||||
|
||||
if (skeleton != null) {
|
||||
bone = skeleton.FindBone(data.bone.name);
|
||||
target = skeleton.FindBone(data.target.name);
|
||||
}
|
||||
}
|
||||
|
||||
public void Update () {
|
||||
Apply();
|
||||
}
|
||||
|
||||
public void Apply () {
|
||||
float translateMix = this.translateMix;
|
||||
if (translateMix > 0) {
|
||||
Bone bone = this.bone;
|
||||
float tx, ty;
|
||||
target.LocalToWorld(x, y, out tx, out ty);
|
||||
bone.worldX += (tx - bone.worldX) * translateMix;
|
||||
bone.worldY += (ty - bone.worldY) * translateMix;
|
||||
}
|
||||
}
|
||||
|
||||
override public String ToString () {
|
||||
return data.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
58
spine-csharp/src/TransformConstraintData.cs
Normal file
58
spine-csharp/src/TransformConstraintData.cs
Normal file
@ -0,0 +1,58 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes Software License
|
||||
* Version 2.3
|
||||
*
|
||||
* Copyright (c) 2013-2015, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* You are granted a perpetual, non-exclusive, non-sublicensable and
|
||||
* non-transferable license to use, install, execute and perform the Spine
|
||||
* Runtimes Software (the "Software") and derivative works solely for personal
|
||||
* or internal use. Without the written permission of Esoteric Software (see
|
||||
* Section 2 of the Spine Software License Agreement), you may not (a) modify,
|
||||
* translate, adapt or otherwise create derivative works, improvements of the
|
||||
* Software or develop new applications using the Software or (b) remove,
|
||||
* delete, alter or obscure any trademarks or any copyright, trademark, patent
|
||||
* or other intellectual property or proprietary rights notices on or in the
|
||||
* Software, including any copy thereof. Redistributions in binary or source
|
||||
* form must include this license and terms.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine {
|
||||
public class TransformConstraintData {
|
||||
internal String name;
|
||||
internal BoneData bone, target;
|
||||
internal float translateMix;
|
||||
internal float x, y;
|
||||
|
||||
public String Name { get { return name; } }
|
||||
public BoneData Bone { get { return bone; } set { bone = value; } }
|
||||
public BoneData Target { get { return target; } set { target = value; } }
|
||||
public float TranslateMix { get { return translateMix; } set { translateMix = value; } }
|
||||
public float X { get { return x; } set { x = value; } }
|
||||
public float Y { get { return y; } set { y = value; } }
|
||||
|
||||
public TransformConstraintData (String name) {
|
||||
if (name == null) throw new ArgumentNullException("name cannot be null.");
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
override public String ToString () {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -125,9 +125,9 @@
|
||||
<Content Include="GameThumbnail.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\spine-csharp\spine-csharp_xna.csproj">
|
||||
<Project>{DF7AAFE1-401E-4278-8F9A-3DD2B8CC3D0A}</Project>
|
||||
<Name>spine-csharp_xna</Name>
|
||||
<ProjectReference Include="..\..\spine-csharp\spine-csharp.csproj">
|
||||
<Project>{94144e22-2431-4a8f-ac04-dec22f7edd8f}</Project>
|
||||
<Name>spine-csharp</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\spine-xna.csproj">
|
||||
<Project>{7F8F2327-C016-49C8-BB4D-F3F77971961E}</Project>
|
||||
|
||||
@ -138,13 +138,13 @@
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\spine-csharp\spine-csharp_xna.csproj">
|
||||
<Project>{DF7AAFE1-401E-4278-8F9A-3DD2B8CC3D0A}</Project>
|
||||
<Name>spine-csharp_xna</Name>
|
||||
</ProjectReference>
|
||||
<Compile Include="src\SkeletonMeshRenderer.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="src\SkeletonMeshRenderer.cs" />
|
||||
<ProjectReference Include="..\spine-csharp\spine-csharp.csproj">
|
||||
<Project>{94144e22-2431-4a8f-ac04-dec22f7edd8f}</Project>
|
||||
<Name>spine-csharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.targets" />
|
||||
|
||||
@ -1,30 +1,55 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual C# Express 2010
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Express 2012 for Windows Desktop
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spine-xna", "spine-xna.csproj", "{7F8F2327-C016-49C8-BB4D-F3F77971961E}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F} = {94144E22-2431-4A8F-AC04-DEC22F7EDD8F}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spine-xna-example", "example\spine-xna-example.csproj", "{29CC4385-294A-4885-A3E8-FD4825E0CFDD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spine-csharp_xna", "..\spine-csharp\spine-csharp_xna.csproj", "{DF7AAFE1-401E-4278-8F9A-3DD2B8CC3D0A}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spine-csharp", "..\spine-csharp\spine-csharp.csproj", "{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|Mixed Platforms = Debug|Mixed Platforms
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|Mixed Platforms = Release|Mixed Platforms
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7F8F2327-C016-49C8-BB4D-F3F77971961E}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{7F8F2327-C016-49C8-BB4D-F3F77971961E}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
|
||||
{7F8F2327-C016-49C8-BB4D-F3F77971961E}.Debug|Mixed Platforms.Build.0 = Debug|x86
|
||||
{7F8F2327-C016-49C8-BB4D-F3F77971961E}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{7F8F2327-C016-49C8-BB4D-F3F77971961E}.Debug|x86.Build.0 = Debug|x86
|
||||
{7F8F2327-C016-49C8-BB4D-F3F77971961E}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{7F8F2327-C016-49C8-BB4D-F3F77971961E}.Release|Mixed Platforms.ActiveCfg = Release|x86
|
||||
{7F8F2327-C016-49C8-BB4D-F3F77971961E}.Release|Mixed Platforms.Build.0 = Release|x86
|
||||
{7F8F2327-C016-49C8-BB4D-F3F77971961E}.Release|x86.ActiveCfg = Release|x86
|
||||
{7F8F2327-C016-49C8-BB4D-F3F77971961E}.Release|x86.Build.0 = Release|x86
|
||||
{29CC4385-294A-4885-A3E8-FD4825E0CFDD}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{29CC4385-294A-4885-A3E8-FD4825E0CFDD}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
|
||||
{29CC4385-294A-4885-A3E8-FD4825E0CFDD}.Debug|Mixed Platforms.Build.0 = Debug|x86
|
||||
{29CC4385-294A-4885-A3E8-FD4825E0CFDD}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{29CC4385-294A-4885-A3E8-FD4825E0CFDD}.Debug|x86.Build.0 = Debug|x86
|
||||
{29CC4385-294A-4885-A3E8-FD4825E0CFDD}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{29CC4385-294A-4885-A3E8-FD4825E0CFDD}.Release|Mixed Platforms.ActiveCfg = Release|x86
|
||||
{29CC4385-294A-4885-A3E8-FD4825E0CFDD}.Release|Mixed Platforms.Build.0 = Release|x86
|
||||
{29CC4385-294A-4885-A3E8-FD4825E0CFDD}.Release|x86.ActiveCfg = Release|x86
|
||||
{29CC4385-294A-4885-A3E8-FD4825E0CFDD}.Release|x86.Build.0 = Release|x86
|
||||
{DF7AAFE1-401E-4278-8F9A-3DD2B8CC3D0A}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{DF7AAFE1-401E-4278-8F9A-3DD2B8CC3D0A}.Debug|x86.Build.0 = Debug|x86
|
||||
{DF7AAFE1-401E-4278-8F9A-3DD2B8CC3D0A}.Release|x86.ActiveCfg = Release|x86
|
||||
{DF7AAFE1-401E-4278-8F9A-3DD2B8CC3D0A}.Release|x86.Build.0 = Release|x86
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@ -189,8 +189,8 @@ namespace Spine {
|
||||
itemVertices[ii].TextureCoordinate.X = uvs[v];
|
||||
itemVertices[ii].TextureCoordinate.Y = uvs[v + 1];
|
||||
}
|
||||
} else if (attachment is SkinnedMeshAttachment) {
|
||||
SkinnedMeshAttachment mesh = (SkinnedMeshAttachment)attachment;
|
||||
} else if (attachment is WeightedMeshAttachment) {
|
||||
WeightedMeshAttachment mesh = (WeightedMeshAttachment)attachment;
|
||||
int vertexCount = mesh.UVs.Length;
|
||||
if (vertices.Length < vertexCount) vertices = new float[vertexCount];
|
||||
mesh.ComputeWorldVertices(slot, vertices);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user