mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +08:00
Committed spine-c into spine-unity.
Screw it, it's easier for Unity people.
This commit is contained in:
parent
803a8ab045
commit
4a4098ed45
415
spine-unity/Assets/Plugins/Spine/spine-csharp/Animation.cs
Normal file
415
spine-unity/Assets/Plugins/Spine/spine-csharp/Animation.cs
Normal file
@ -0,0 +1,415 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 Animation {
|
||||
public String Name { get; private set; }
|
||||
public List<Timeline> Timelines { get; set; }
|
||||
public float Duration { get; set; }
|
||||
|
||||
public Animation (String name, List<Timeline> timelines, float duration) {
|
||||
if (name == null) throw new ArgumentNullException("name cannot be null.");
|
||||
if (timelines == null) throw new ArgumentNullException("timelines cannot be null.");
|
||||
Name = name;
|
||||
Timelines = timelines;
|
||||
Duration = duration;
|
||||
}
|
||||
|
||||
/** Poses the skeleton at the specified time for this animation. */
|
||||
public void Apply (Skeleton skeleton, float time, bool loop) {
|
||||
if (skeleton == null) throw new ArgumentNullException("skeleton cannot be null.");
|
||||
|
||||
if (loop && Duration != 0) time %= Duration;
|
||||
|
||||
List<Timeline> timelines = Timelines;
|
||||
for (int i = 0, n = timelines.Count; i < n; i++)
|
||||
timelines[i].Apply(skeleton, time, 1);
|
||||
}
|
||||
|
||||
/** Poses the skeleton at the specified time for this animation mixed with the current pose.
|
||||
* @param alpha The amount of this animation that affects the current pose. */
|
||||
public void Mix (Skeleton skeleton, float time, bool loop, float alpha) {
|
||||
if (skeleton == null) throw new ArgumentNullException("skeleton cannot be null.");
|
||||
|
||||
if (loop && Duration != 0) time %= Duration;
|
||||
|
||||
List<Timeline> timelines = Timelines;
|
||||
for (int i = 0, n = timelines.Count; i < n; i++)
|
||||
timelines[i].Apply(skeleton, time, alpha);
|
||||
}
|
||||
|
||||
/** @param target After the first and before the last entry. */
|
||||
internal static int binarySearch (float[] values, float target, int step) {
|
||||
int low = 0;
|
||||
int high = values.Length / step - 2;
|
||||
if (high == 0) return step;
|
||||
int current = (int)((uint)high >> 1);
|
||||
while (true) {
|
||||
if (values[(current + 1) * step] <= target)
|
||||
low = current + 1;
|
||||
else
|
||||
high = current;
|
||||
if (low == high) return (low + 1) * step;
|
||||
current = (int)((uint)(low + high) >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
internal static int linearSearch (float[] values, float target, int step) {
|
||||
for (int i = 0, last = values.Length - step; i <= last; i += step)
|
||||
if (values[i] > target) return i;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public interface Timeline {
|
||||
/** Sets the value(s) for the specified time. */
|
||||
void Apply (Skeleton skeleton, float time, float alpha);
|
||||
}
|
||||
|
||||
/** Base class for frames that use an interpolation bezier curve. */
|
||||
abstract public class CurveTimeline : Timeline {
|
||||
static protected float LINEAR = 0;
|
||||
static protected float STEPPED = -1;
|
||||
static protected int BEZIER_SEGMENTS = 10;
|
||||
|
||||
private float[] curves; // dfx, dfy, ddfx, ddfy, dddfx, dddfy, ...
|
||||
public int FrameCount {
|
||||
get {
|
||||
return curves.Length / 6 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public CurveTimeline (int frameCount) {
|
||||
curves = new float[(frameCount - 1) * 6];
|
||||
}
|
||||
|
||||
abstract public void Apply (Skeleton skeleton, float time, float alpha);
|
||||
|
||||
public void SetLinear (int frameIndex) {
|
||||
curves[frameIndex * 6] = LINEAR;
|
||||
}
|
||||
|
||||
public void SetStepped (int frameIndex) {
|
||||
curves[frameIndex * 6] = STEPPED;
|
||||
}
|
||||
|
||||
/** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
|
||||
* cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of
|
||||
* the difference between the keyframe's values. */
|
||||
public void SetCurve (int frameIndex, float cx1, float cy1, float cx2, float cy2) {
|
||||
float subdiv_step = 1f / BEZIER_SEGMENTS;
|
||||
float subdiv_step2 = subdiv_step * subdiv_step;
|
||||
float subdiv_step3 = subdiv_step2 * subdiv_step;
|
||||
float pre1 = 3 * subdiv_step;
|
||||
float pre2 = 3 * subdiv_step2;
|
||||
float pre4 = 6 * subdiv_step2;
|
||||
float pre5 = 6 * subdiv_step3;
|
||||
float tmp1x = -cx1 * 2 + cx2;
|
||||
float tmp1y = -cy1 * 2 + cy2;
|
||||
float tmp2x = (cx1 - cx2) * 3 + 1;
|
||||
float tmp2y = (cy1 - cy2) * 3 + 1;
|
||||
int i = frameIndex * 6;
|
||||
float[] curves = this.curves;
|
||||
curves[i] = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3;
|
||||
curves[i + 1] = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3;
|
||||
curves[i + 2] = tmp1x * pre4 + tmp2x * pre5;
|
||||
curves[i + 3] = tmp1y * pre4 + tmp2y * pre5;
|
||||
curves[i + 4] = tmp2x * pre5;
|
||||
curves[i + 5] = tmp2y * pre5;
|
||||
}
|
||||
|
||||
public float GetCurvePercent (int frameIndex, float percent) {
|
||||
int curveIndex = frameIndex * 6;
|
||||
float[] curves = this.curves;
|
||||
float dfx = curves[curveIndex];
|
||||
if (dfx == LINEAR) return percent;
|
||||
if (dfx == STEPPED) return 0;
|
||||
float dfy = curves[curveIndex + 1];
|
||||
float ddfx = curves[curveIndex + 2];
|
||||
float ddfy = curves[curveIndex + 3];
|
||||
float dddfx = curves[curveIndex + 4];
|
||||
float dddfy = curves[curveIndex + 5];
|
||||
float x = dfx, y = dfy;
|
||||
int i = BEZIER_SEGMENTS - 2;
|
||||
while (true) {
|
||||
if (x >= percent) {
|
||||
float lastX = x - dfx;
|
||||
float lastY = y - dfy;
|
||||
return lastY + (y - lastY) * (percent - lastX) / (x - lastX);
|
||||
}
|
||||
if (i == 0) break;
|
||||
i--;
|
||||
dfx += ddfx;
|
||||
dfy += ddfy;
|
||||
ddfx += dddfx;
|
||||
ddfy += dddfy;
|
||||
x += dfx;
|
||||
y += dfy;
|
||||
}
|
||||
return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1.
|
||||
}
|
||||
}
|
||||
|
||||
public class RotateTimeline : CurveTimeline {
|
||||
static protected int LAST_FRAME_TIME = -2;
|
||||
static protected int FRAME_VALUE = 1;
|
||||
|
||||
public int BoneIndex { get; set; }
|
||||
public float[] Frames { get; private set; } // time, value, ...
|
||||
|
||||
public RotateTimeline (int frameCount)
|
||||
: base(frameCount) {
|
||||
Frames = new float[frameCount * 2];
|
||||
}
|
||||
|
||||
/** Sets the time and value of the specified keyframe. */
|
||||
public void SetFrame (int frameIndex, float time, float angle) {
|
||||
frameIndex *= 2;
|
||||
Frames[frameIndex] = time;
|
||||
Frames[frameIndex + 1] = angle;
|
||||
}
|
||||
|
||||
override public void Apply (Skeleton skeleton, float time, float alpha) {
|
||||
float[] frames = Frames;
|
||||
if (time < frames[0]) return; // Time is before first frame.
|
||||
|
||||
Bone bone = skeleton.Bones[BoneIndex];
|
||||
|
||||
float amount;
|
||||
|
||||
if (time >= frames[frames.Length - 2]) { // Time is after last frame.
|
||||
amount = bone.Data.Rotation + frames[frames.Length - 1] - bone.Rotation;
|
||||
while (amount > 180)
|
||||
amount -= 360;
|
||||
while (amount < -180)
|
||||
amount += 360;
|
||||
bone.Rotation += amount * alpha;
|
||||
return;
|
||||
}
|
||||
|
||||
// Interpolate between the last frame and the current frame.
|
||||
int frameIndex = Animation.binarySearch(frames, time, 2);
|
||||
float lastFrameValue = frames[frameIndex - 1];
|
||||
float frameTime = frames[frameIndex];
|
||||
float percent = 1 - (time - frameTime) / (frames[frameIndex + LAST_FRAME_TIME] - frameTime);
|
||||
percent = GetCurvePercent(frameIndex / 2 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
|
||||
|
||||
amount = frames[frameIndex + FRAME_VALUE] - lastFrameValue;
|
||||
while (amount > 180)
|
||||
amount -= 360;
|
||||
while (amount < -180)
|
||||
amount += 360;
|
||||
amount = bone.Data.Rotation + (lastFrameValue + amount * percent) - bone.Rotation;
|
||||
while (amount > 180)
|
||||
amount -= 360;
|
||||
while (amount < -180)
|
||||
amount += 360;
|
||||
bone.Rotation += amount * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
public class TranslateTimeline : CurveTimeline {
|
||||
static protected int LAST_FRAME_TIME = -3;
|
||||
static protected int FRAME_X = 1;
|
||||
static protected int FRAME_Y = 2;
|
||||
|
||||
public int BoneIndex { get; set; }
|
||||
public float[] Frames { get; private set; } // time, value, value, ...
|
||||
|
||||
public TranslateTimeline (int frameCount)
|
||||
: base(frameCount) {
|
||||
Frames = new float[frameCount * 3];
|
||||
}
|
||||
|
||||
/** Sets the time and value of the specified keyframe. */
|
||||
public void SetFrame (int frameIndex, float time, float x, float y) {
|
||||
frameIndex *= 3;
|
||||
Frames[frameIndex] = time;
|
||||
Frames[frameIndex + 1] = x;
|
||||
Frames[frameIndex + 2] = y;
|
||||
}
|
||||
|
||||
override public void Apply (Skeleton skeleton, float time, float alpha) {
|
||||
float[] frames = Frames;
|
||||
if (time < frames[0]) return; // Time is before first frame.
|
||||
|
||||
Bone bone = skeleton.Bones[BoneIndex];
|
||||
|
||||
if (time >= frames[frames.Length - 3]) { // Time is after last frame.
|
||||
bone.X += (bone.Data.X + frames[frames.Length - 2] - bone.X) * alpha;
|
||||
bone.Y += (bone.Data.Y + frames[frames.Length - 1] - bone.Y) * alpha;
|
||||
return;
|
||||
}
|
||||
|
||||
// Interpolate between the last frame and the current frame.
|
||||
int frameIndex = Animation.binarySearch(frames, time, 3);
|
||||
float lastFrameX = frames[frameIndex - 2];
|
||||
float lastFrameY = frames[frameIndex - 1];
|
||||
float frameTime = frames[frameIndex];
|
||||
float percent = 1 - (time - frameTime) / (frames[frameIndex + LAST_FRAME_TIME] - frameTime);
|
||||
percent = GetCurvePercent(frameIndex / 3 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
|
||||
|
||||
bone.X += (bone.Data.X + lastFrameX + (frames[frameIndex + FRAME_X] - lastFrameX) * percent - bone.X) * alpha;
|
||||
bone.Y += (bone.Data.Y + lastFrameY + (frames[frameIndex + FRAME_Y] - lastFrameY) * percent - bone.Y) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
public class ScaleTimeline : TranslateTimeline {
|
||||
public ScaleTimeline (int frameCount)
|
||||
: base(frameCount) {
|
||||
}
|
||||
|
||||
override public void Apply (Skeleton skeleton, float time, float alpha) {
|
||||
float[] frames = Frames;
|
||||
if (time < frames[0]) return; // Time is before first frame.
|
||||
|
||||
Bone bone = skeleton.Bones[BoneIndex];
|
||||
if (time >= frames[frames.Length - 3]) { // Time is after last frame.
|
||||
bone.ScaleX += (bone.Data.ScaleX - 1 + frames[frames.Length - 2] - bone.ScaleX) * alpha;
|
||||
bone.ScaleY += (bone.Data.ScaleY - 1 + frames[frames.Length - 1] - bone.ScaleY) * alpha;
|
||||
return;
|
||||
}
|
||||
|
||||
// Interpolate between the last frame and the current frame.
|
||||
int frameIndex = Animation.binarySearch(frames, time, 3);
|
||||
float lastFrameX = frames[frameIndex - 2];
|
||||
float lastFrameY = frames[frameIndex - 1];
|
||||
float frameTime = frames[frameIndex];
|
||||
float percent = 1 - (time - frameTime) / (frames[frameIndex + LAST_FRAME_TIME] - frameTime);
|
||||
percent = GetCurvePercent(frameIndex / 3 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
|
||||
|
||||
bone.ScaleX += (bone.Data.ScaleX - 1 + lastFrameX + (frames[frameIndex + FRAME_X] - lastFrameX) * percent - bone.ScaleX) * alpha;
|
||||
bone.ScaleY += (bone.Data.ScaleY - 1 + lastFrameY + (frames[frameIndex + FRAME_Y] - lastFrameY) * percent - bone.ScaleY) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
public class ColorTimeline : CurveTimeline {
|
||||
static protected int LAST_FRAME_TIME = -5;
|
||||
static protected int FRAME_R = 1;
|
||||
static protected int FRAME_G = 2;
|
||||
static protected int FRAME_B = 3;
|
||||
static protected int FRAME_A = 4;
|
||||
|
||||
public int SlotIndex { get; set; }
|
||||
public float[] Frames { get; private set; } // time, r, g, b, a, ...
|
||||
|
||||
public ColorTimeline (int frameCount)
|
||||
: base(frameCount) {
|
||||
Frames = new float[frameCount * 5];
|
||||
}
|
||||
|
||||
/** Sets the time and value of the specified keyframe. */
|
||||
public void setFrame (int frameIndex, float time, float r, float g, float b, float a) {
|
||||
frameIndex *= 5;
|
||||
Frames[frameIndex] = time;
|
||||
Frames[frameIndex + 1] = r;
|
||||
Frames[frameIndex + 2] = g;
|
||||
Frames[frameIndex + 3] = b;
|
||||
Frames[frameIndex + 4] = a;
|
||||
}
|
||||
|
||||
override public void Apply (Skeleton skeleton, float time, float alpha) {
|
||||
float[] frames = Frames;
|
||||
if (time < frames[0]) return; // Time is before first frame.
|
||||
|
||||
Slot slot = skeleton.Slots[SlotIndex];
|
||||
|
||||
if (time >= frames[frames.Length - 5]) { // Time is after last frame.
|
||||
int i = frames.Length - 1;
|
||||
slot.R = frames[i - 3];
|
||||
slot.G = frames[i - 2];
|
||||
slot.B = frames[i - 1];
|
||||
slot.A = frames[i];
|
||||
return;
|
||||
}
|
||||
|
||||
// Interpolate between the last frame and the current frame.
|
||||
int frameIndex = Animation.binarySearch(frames, time, 5);
|
||||
float lastFrameR = frames[frameIndex - 4];
|
||||
float lastFrameG = frames[frameIndex - 3];
|
||||
float lastFrameB = frames[frameIndex - 2];
|
||||
float lastFrameA = frames[frameIndex - 1];
|
||||
float frameTime = frames[frameIndex];
|
||||
float percent = 1 - (time - frameTime) / (frames[frameIndex + LAST_FRAME_TIME] - frameTime);
|
||||
percent = GetCurvePercent(frameIndex / 5 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
|
||||
|
||||
float r = lastFrameR + (frames[frameIndex + FRAME_R] - lastFrameR) * percent;
|
||||
float g = lastFrameG + (frames[frameIndex + FRAME_G] - lastFrameG) * percent;
|
||||
float b = lastFrameB + (frames[frameIndex + FRAME_B] - lastFrameB) * percent;
|
||||
float a = lastFrameA + (frames[frameIndex + FRAME_A] - lastFrameA) * percent;
|
||||
if (alpha < 1) {
|
||||
slot.R += (r - slot.R) * alpha;
|
||||
slot.G += (g - slot.G) * alpha;
|
||||
slot.B += (b - slot.B) * alpha;
|
||||
slot.A += (a - slot.A) * alpha;
|
||||
} else {
|
||||
slot.R = r;
|
||||
slot.G = g;
|
||||
slot.B = b;
|
||||
slot.A = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AttachmentTimeline : Timeline {
|
||||
public int SlotIndex { get; set; }
|
||||
public float[] Frames { get; private set; } // time, ...
|
||||
public String[] AttachmentNames { get; private set; }
|
||||
public int FrameCount {
|
||||
get {
|
||||
return Frames.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public AttachmentTimeline (int frameCount) {
|
||||
Frames = new float[frameCount];
|
||||
AttachmentNames = new String[frameCount];
|
||||
}
|
||||
|
||||
/** Sets the time and value of the specified keyframe. */
|
||||
public void setFrame (int frameIndex, float time, String attachmentName) {
|
||||
Frames[frameIndex] = time;
|
||||
AttachmentNames[frameIndex] = attachmentName;
|
||||
}
|
||||
|
||||
public void Apply (Skeleton skeleton, float time, float alpha) {
|
||||
float[] frames = Frames;
|
||||
if (time < frames[0]) return; // Time is before first frame.
|
||||
|
||||
int frameIndex;
|
||||
if (time >= frames[frames.Length - 1]) // Time is after last frame.
|
||||
frameIndex = frames.Length - 1;
|
||||
else
|
||||
frameIndex = Animation.binarySearch(frames, time, 1) - 1;
|
||||
|
||||
String attachmentName = AttachmentNames[frameIndex];
|
||||
skeleton.Slots[SlotIndex].Attachment =
|
||||
attachmentName == null ? null : skeleton.GetAttachment(SlotIndex, attachmentName);
|
||||
}
|
||||
}
|
||||
}
|
||||
101
spine-unity/Assets/Plugins/Spine/spine-csharp/AnimationState.cs
Normal file
101
spine-unity/Assets/Plugins/Spine/spine-csharp/AnimationState.cs
Normal file
@ -0,0 +1,101 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 AnimationState {
|
||||
public AnimationStateData Data { get; private set; }
|
||||
public Animation Animation { get; private set; }
|
||||
public float Time { get; set; }
|
||||
public bool Loop { get; set; }
|
||||
private Animation previous;
|
||||
float previousTime;
|
||||
bool previousLoop;
|
||||
float mixTime, mixDuration;
|
||||
|
||||
public AnimationState (AnimationStateData data) {
|
||||
if (data == null) throw new ArgumentNullException("data cannot be null.");
|
||||
Data = data;
|
||||
}
|
||||
|
||||
public void Update (float delta) {
|
||||
Time += delta;
|
||||
previousTime += delta;
|
||||
mixTime += delta;
|
||||
}
|
||||
|
||||
public void Apply (Skeleton skeleton) {
|
||||
if (Animation == null) return;
|
||||
if (previous != null) {
|
||||
previous.Apply(skeleton, previousTime, previousLoop);
|
||||
float alpha = mixTime / mixDuration;
|
||||
if (alpha >= 1) {
|
||||
alpha = 1;
|
||||
previous = null;
|
||||
}
|
||||
Animation.Mix(skeleton, Time, Loop, alpha);
|
||||
} else
|
||||
Animation.Apply(skeleton, Time, Loop);
|
||||
}
|
||||
|
||||
public void SetAnimation (String animationName, bool loop) {
|
||||
Animation animation = Data.SkeletonData.FindAnimation(animationName);
|
||||
if (animation == null) throw new ArgumentException("Animation not found: " + animationName);
|
||||
SetAnimation(animation, loop);
|
||||
}
|
||||
|
||||
public void SetAnimation (Animation animation, bool loop) {
|
||||
previous = null;
|
||||
if (animation != null && Animation != null) {
|
||||
mixDuration = Data.GetMix(Animation, animation);
|
||||
if (mixDuration > 0) {
|
||||
mixTime = 0;
|
||||
previous = Animation;
|
||||
previousTime = Time;
|
||||
previousLoop = Loop;
|
||||
}
|
||||
}
|
||||
Animation = animation;
|
||||
Loop = loop;
|
||||
Time = 0;
|
||||
}
|
||||
|
||||
public void ClearAnimation () {
|
||||
previous = null;
|
||||
Animation = null;
|
||||
}
|
||||
|
||||
/** Returns true if no animation is set or if the current time is greater than the animation duration, regardless of looping. */
|
||||
public bool isComplete () {
|
||||
return Animation == null || Time >= Animation.Duration;
|
||||
}
|
||||
|
||||
override public String ToString () {
|
||||
return (Animation != null && Animation.Name != null) ? Animation.Name : base.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 AnimationStateData {
|
||||
public SkeletonData SkeletonData { get; private set; }
|
||||
private Dictionary<KeyValuePair<Animation, Animation>, float> animationToMixTime = new Dictionary<KeyValuePair<Animation, Animation>, float>();
|
||||
|
||||
public AnimationStateData (SkeletonData skeletonData) {
|
||||
SkeletonData = skeletonData;
|
||||
}
|
||||
|
||||
public void SetMix (String fromName, String toName, float duration) {
|
||||
Animation from = SkeletonData.FindAnimation(fromName);
|
||||
if (from == null) throw new ArgumentException("Animation not found: " + fromName);
|
||||
Animation to = SkeletonData.FindAnimation(toName);
|
||||
if (to == null) throw new ArgumentException("Animation not found: " + toName);
|
||||
SetMix(from, to, duration);
|
||||
}
|
||||
|
||||
public void SetMix (Animation from, Animation to, float duration) {
|
||||
if (from == null) throw new ArgumentNullException("from cannot be null.");
|
||||
if (to == null) throw new ArgumentNullException("to cannot be null.");
|
||||
KeyValuePair<Animation, Animation> key = new KeyValuePair<Animation, Animation>(from, to);
|
||||
animationToMixTime.Remove(key);
|
||||
animationToMixTime.Add(key, duration);
|
||||
}
|
||||
|
||||
public float GetMix (Animation from, Animation to) {
|
||||
KeyValuePair<Animation, Animation> key = new KeyValuePair<Animation, Animation>(from, to);
|
||||
float duration;
|
||||
animationToMixTime.TryGetValue(key, out duration);
|
||||
return duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
229
spine-unity/Assets/Plugins/Spine/spine-csharp/Atlas.cs
Normal file
229
spine-unity/Assets/Plugins/Spine/spine-csharp/Atlas.cs
Normal file
@ -0,0 +1,229 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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;
|
||||
using System.IO;
|
||||
|
||||
namespace Spine {
|
||||
public class Atlas {
|
||||
List<AtlasPage> pages = new List<AtlasPage>();
|
||||
List<AtlasRegion> regions = new List<AtlasRegion>();
|
||||
TextureLoader textureLoader;
|
||||
|
||||
public Atlas (String path, TextureLoader textureLoader) {
|
||||
using (StreamReader reader = new StreamReader(path)) {
|
||||
try {
|
||||
Load(reader, Path.GetDirectoryName(path), textureLoader);
|
||||
} catch (Exception ex) {
|
||||
throw new Exception("Error reading atlas file: " + path, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Atlas (TextReader reader, String dir, TextureLoader textureLoader) {
|
||||
Load(reader, dir, textureLoader);
|
||||
}
|
||||
|
||||
private void Load (TextReader reader, String imagesDir, TextureLoader textureLoader) {
|
||||
if (textureLoader == null) throw new ArgumentNullException("textureLoader cannot be null.");
|
||||
this.textureLoader = textureLoader;
|
||||
|
||||
String[] tuple = new String[4];
|
||||
AtlasPage page = null;
|
||||
while (true) {
|
||||
String line = reader.ReadLine();
|
||||
if (line == null) break;
|
||||
if (line.Trim().Length == 0)
|
||||
page = null;
|
||||
else if (page == null) {
|
||||
page = new AtlasPage();
|
||||
page.name = line;
|
||||
|
||||
page.format = (Format)Enum.Parse(typeof(Format), readValue(reader), false);
|
||||
|
||||
readTuple(reader, tuple);
|
||||
page.minFilter = (TextureFilter)Enum.Parse(typeof(TextureFilter), tuple[0]);
|
||||
page.magFilter = (TextureFilter)Enum.Parse(typeof(TextureFilter), tuple[1]);
|
||||
|
||||
String direction = readValue(reader);
|
||||
page.uWrap = TextureWrap.ClampToEdge;
|
||||
page.vWrap = TextureWrap.ClampToEdge;
|
||||
if (direction == "x")
|
||||
page.uWrap = TextureWrap.Repeat;
|
||||
else if (direction == "y")
|
||||
page.vWrap = TextureWrap.Repeat;
|
||||
else if (direction == "xy")
|
||||
page.uWrap = page.vWrap = TextureWrap.Repeat;
|
||||
|
||||
textureLoader.Load(page, Path.Combine(imagesDir, line));
|
||||
|
||||
pages.Add(page);
|
||||
|
||||
} else {
|
||||
AtlasRegion region = new AtlasRegion();
|
||||
region.name = line;
|
||||
region.page = page;
|
||||
|
||||
region.rotate = Boolean.Parse(readValue(reader));
|
||||
|
||||
readTuple(reader, tuple);
|
||||
int x = int.Parse(tuple[0]);
|
||||
int y = int.Parse(tuple[1]);
|
||||
|
||||
readTuple(reader, tuple);
|
||||
int width = int.Parse(tuple[0]);
|
||||
int height = int.Parse(tuple[1]);
|
||||
|
||||
region.u = x / (float)page.width;
|
||||
region.v = y / (float)page.height;
|
||||
region.u2 = (x + width) / (float)page.width;
|
||||
region.v2 = (y + height) / (float)page.height;
|
||||
region.x = x;
|
||||
region.y = y;
|
||||
region.width = Math.Abs(width);
|
||||
region.height = Math.Abs(height);
|
||||
|
||||
if (readTuple(reader, tuple) == 4) { // split is optional
|
||||
region.splits = new int[] {int.Parse(tuple[0]), int.Parse(tuple[1]),
|
||||
int.Parse(tuple[2]), int.Parse(tuple[3])};
|
||||
|
||||
if (readTuple(reader, tuple) == 4) { // pad is optional, but only present with splits
|
||||
region.pads = new int[] {int.Parse(tuple[0]), int.Parse(tuple[1]),
|
||||
int.Parse(tuple[2]), int.Parse(tuple[3])};
|
||||
|
||||
readTuple(reader, tuple);
|
||||
}
|
||||
}
|
||||
|
||||
region.originalWidth = int.Parse(tuple[0]);
|
||||
region.originalHeight = int.Parse(tuple[1]);
|
||||
|
||||
readTuple(reader, tuple);
|
||||
region.offsetX = int.Parse(tuple[0]);
|
||||
region.offsetY = int.Parse(tuple[1]);
|
||||
|
||||
region.index = int.Parse(readValue(reader));
|
||||
|
||||
regions.Add(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static String readValue (TextReader reader) {
|
||||
String line = reader.ReadLine();
|
||||
int colon = line.IndexOf(':');
|
||||
if (colon == -1) throw new Exception("Invalid line: " + line);
|
||||
return line.Substring(colon + 1).Trim();
|
||||
}
|
||||
|
||||
/** Returns the number of tuple values read (2 or 4). */
|
||||
static int readTuple (TextReader reader, String[] tuple) {
|
||||
String line = reader.ReadLine();
|
||||
int colon = line.IndexOf(':');
|
||||
if (colon == -1) throw new Exception("Invalid line: " + line);
|
||||
int i = 0, lastMatch = colon + 1;
|
||||
for (; i < 3; i++) {
|
||||
int comma = line.IndexOf(',', lastMatch);
|
||||
if (comma == -1) {
|
||||
if (i == 0) throw new Exception("Invalid line: " + line);
|
||||
break;
|
||||
}
|
||||
tuple[i] = line.Substring(lastMatch, comma - lastMatch).Trim();
|
||||
lastMatch = comma + 1;
|
||||
}
|
||||
tuple[i] = line.Substring(lastMatch).Trim();
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
/** Returns the first region found with the specified name. This method uses string comparison to find the region, so the result
|
||||
* should be cached rather than calling this method multiple times.
|
||||
* @return The region, or null. */
|
||||
public AtlasRegion FindRegion (String name) {
|
||||
for (int i = 0, n = regions.Count; i < n; i++)
|
||||
if (regions[i].name == name) return regions[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Dispose () {
|
||||
for (int i = 0, n = pages.Count; i < n; i++)
|
||||
textureLoader.Unload(pages[i].texture);
|
||||
}
|
||||
}
|
||||
|
||||
public enum Format {
|
||||
Alpha,
|
||||
Intensity,
|
||||
LuminanceAlpha,
|
||||
RGB565,
|
||||
RGBA4444,
|
||||
RGB888,
|
||||
RGBA8888
|
||||
}
|
||||
|
||||
public enum TextureFilter {
|
||||
Nearest,
|
||||
Linear,
|
||||
MipMap,
|
||||
MipMapNearestNearest,
|
||||
MipMapLinearNearest,
|
||||
MipMapNearestLinear,
|
||||
MipMapLinearLinear
|
||||
}
|
||||
|
||||
public enum TextureWrap {
|
||||
MirroredRepeat,
|
||||
ClampToEdge,
|
||||
Repeat
|
||||
}
|
||||
|
||||
public class AtlasPage {
|
||||
public String name;
|
||||
public Format format;
|
||||
public TextureFilter minFilter;
|
||||
public TextureFilter magFilter;
|
||||
public TextureWrap uWrap;
|
||||
public TextureWrap vWrap;
|
||||
public Object texture;
|
||||
public int width, height;
|
||||
}
|
||||
|
||||
public class AtlasRegion {
|
||||
public AtlasPage page;
|
||||
public String name;
|
||||
public int x, y, width, height;
|
||||
public float u, v, u2, v2;
|
||||
public float offsetX, offsetY;
|
||||
public int originalWidth, originalHeight;
|
||||
public int index;
|
||||
public bool rotate;
|
||||
public int[] splits;
|
||||
public int[] pads;
|
||||
}
|
||||
|
||||
public interface TextureLoader {
|
||||
void Load (AtlasPage page, String path);
|
||||
void Unload (Object texture);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 AtlasAttachmentLoader : AttachmentLoader {
|
||||
private Atlas atlas;
|
||||
|
||||
public AtlasAttachmentLoader (Atlas atlas) {
|
||||
if (atlas == null) throw new ArgumentNullException("atlas cannot be null.");
|
||||
this.atlas = atlas;
|
||||
}
|
||||
|
||||
public Attachment NewAttachment (Skin skin, AttachmentType type, String name) {
|
||||
switch (type) {
|
||||
case AttachmentType.region:
|
||||
AtlasRegion region = atlas.FindRegion(name);
|
||||
if (region == null) throw new Exception("Region not found in atlas: " + name + " (" + type + ")");
|
||||
RegionAttachment attachment = new RegionAttachment(name);
|
||||
attachment.Region = region;
|
||||
return attachment;
|
||||
}
|
||||
throw new Exception("Unknown attachment type: " + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 {
|
||||
abstract public class Attachment {
|
||||
public String Name { get; private set; }
|
||||
|
||||
public Attachment (String name) {
|
||||
if (name == null) throw new ArgumentNullException("name cannot be null.");
|
||||
Name = name;
|
||||
}
|
||||
|
||||
override public String ToString () {
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 AttachmentLoader {
|
||||
/** @return May be null to not load any attachment. */
|
||||
Attachment NewAttachment (Skin skin, AttachmentType type, String name);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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.
|
||||
******************************************************************************/
|
||||
|
||||
namespace Spine {
|
||||
public enum AttachmentType {
|
||||
region, regionSequence
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,130 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 {
|
||||
/** Attachment that displays a texture region. */
|
||||
public class RegionAttachment : Attachment {
|
||||
public const int X1 = 0;
|
||||
public const int Y1 = 1;
|
||||
public const int X2 = 2;
|
||||
public const int Y2 = 3;
|
||||
public const int X3 = 4;
|
||||
public const int Y3 = 5;
|
||||
public const int X4 = 6;
|
||||
public const int Y4 = 7;
|
||||
|
||||
public float X { get; set; }
|
||||
public float Y { get; set; }
|
||||
public float ScaleX { get; set; }
|
||||
public float ScaleY { get; set; }
|
||||
public float Rotation { get; set; }
|
||||
public float Width { get; set; }
|
||||
public float Height { get; set; }
|
||||
|
||||
public float[] Offset { get; private set; }
|
||||
public float[] Vertices { get; private set; }
|
||||
public AtlasRegion Region { get; set; }
|
||||
|
||||
public RegionAttachment (string name)
|
||||
: base(name) {
|
||||
Offset = new float[8];
|
||||
Vertices = new float[8];
|
||||
ScaleX = 1;
|
||||
ScaleY = 1;
|
||||
}
|
||||
|
||||
public void UpdateOffset () {
|
||||
float width = Width;
|
||||
float height = Height;
|
||||
float localX2 = width / 2;
|
||||
float localY2 = height / 2;
|
||||
float localX = -localX2;
|
||||
float localY = -localY2;
|
||||
AtlasRegion region = Region;
|
||||
if (region != null) {
|
||||
if (region.rotate) {
|
||||
localX += region.offsetX / region.originalWidth * height;
|
||||
localY += region.offsetY / region.originalHeight * width;
|
||||
localX2 -= (region.originalWidth - region.offsetX - region.height) / region.originalWidth * width;
|
||||
localY2 -= (region.originalHeight - region.offsetY - region.width) / region.originalHeight * height;
|
||||
} else {
|
||||
localX += region.offsetX / region.originalWidth * width;
|
||||
localY += region.offsetY / region.originalHeight * height;
|
||||
localX2 -= (region.originalWidth - region.offsetX - region.width) / region.originalWidth * width;
|
||||
localY2 -= (region.originalHeight - region.offsetY - region.height) / region.originalHeight * height;
|
||||
}
|
||||
}
|
||||
float scaleX = ScaleX;
|
||||
float scaleY = ScaleY;
|
||||
localX *= scaleX;
|
||||
localY *= scaleY;
|
||||
localX2 *= scaleX;
|
||||
localY2 *= scaleY;
|
||||
float radians = Rotation * (float)Math.PI / 180;
|
||||
float cos = (float)Math.Cos(radians);
|
||||
float sin = (float)Math.Sin(radians);
|
||||
float x = X;
|
||||
float y = Y;
|
||||
float localXCos = localX * cos + x;
|
||||
float localXSin = localX * sin;
|
||||
float localYCos = localY * cos + y;
|
||||
float localYSin = localY * sin;
|
||||
float localX2Cos = localX2 * cos + x;
|
||||
float localX2Sin = localX2 * sin;
|
||||
float localY2Cos = localY2 * cos + y;
|
||||
float localY2Sin = localY2 * sin;
|
||||
float[] offset = Offset;
|
||||
offset[X1] = localXCos - localYSin;
|
||||
offset[Y1] = localYCos + localXSin;
|
||||
offset[X2] = localXCos - localY2Sin;
|
||||
offset[Y2] = localY2Cos + localXSin;
|
||||
offset[X3] = localX2Cos - localY2Sin;
|
||||
offset[Y3] = localY2Cos + localX2Sin;
|
||||
offset[X4] = localX2Cos - localYSin;
|
||||
offset[Y4] = localYCos + localX2Sin;
|
||||
}
|
||||
|
||||
public void UpdateVertices (Bone bone) {
|
||||
float x = bone.WorldX;
|
||||
float y = bone.WorldY;
|
||||
float m00 = bone.M00;
|
||||
float m01 = bone.M01;
|
||||
float m10 = bone.M10;
|
||||
float m11 = bone.M11;
|
||||
float[] vertices = Vertices;
|
||||
float[] offset = Offset;
|
||||
vertices[X1] = offset[X1] * m00 + offset[Y1] * m01 + x;
|
||||
vertices[Y1] = offset[X1] * m10 + offset[Y1] * m11 + y;
|
||||
vertices[X2] = offset[X2] * m00 + offset[Y2] * m01 + x;
|
||||
vertices[Y2] = offset[X2] * m10 + offset[Y2] * m11 + y;
|
||||
vertices[X3] = offset[X3] * m00 + offset[Y3] * m01 + x;
|
||||
vertices[Y3] = offset[X3] * m10 + offset[Y3] * m11 + y;
|
||||
vertices[X4] = offset[X4] * m00 + offset[Y4] * m01 + x;
|
||||
vertices[Y4] = offset[X4] * m10 + offset[Y4] * m11 + y;
|
||||
}
|
||||
}
|
||||
}
|
||||
108
spine-unity/Assets/Plugins/Spine/spine-csharp/Bone.cs
Normal file
108
spine-unity/Assets/Plugins/Spine/spine-csharp/Bone.cs
Normal file
@ -0,0 +1,108 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 Bone {
|
||||
static public bool yDown;
|
||||
|
||||
public BoneData Data { get; private set; }
|
||||
public Bone Parent { get; private set; }
|
||||
public float X { get; set; }
|
||||
public float Y { get; set; }
|
||||
public float Rotation { get; set; }
|
||||
public float ScaleX { get; set; }
|
||||
public float ScaleY { get; set; }
|
||||
|
||||
public float M00 { get; private set; }
|
||||
public float M01 { get; private set; }
|
||||
public float M10 { get; private set; }
|
||||
public float M11 { get; private set; }
|
||||
public float WorldX { get; private set; }
|
||||
public float WorldY { get; private set; }
|
||||
public float WorldRotation { get; private set; }
|
||||
public float WorldScaleX { get; private set; }
|
||||
public float WorldScaleY { get; private set; }
|
||||
|
||||
/** @param parent May be null. */
|
||||
public Bone (BoneData data, Bone parent) {
|
||||
if (data == null) throw new ArgumentNullException("data cannot be null.");
|
||||
Data = data;
|
||||
Parent = parent;
|
||||
SetToBindPose();
|
||||
}
|
||||
|
||||
/** Computes the world SRT using the parent bone and the local SRT. */
|
||||
public void UpdateWorldTransform (bool flipX, bool flipY) {
|
||||
Bone parent = Parent;
|
||||
if (parent != null) {
|
||||
WorldX = X * parent.M00 + Y * parent.M01 + parent.WorldX;
|
||||
WorldY = X * parent.M10 + Y * parent.M11 + parent.WorldY;
|
||||
WorldScaleX = parent.WorldScaleX * ScaleX;
|
||||
WorldScaleY = parent.WorldScaleY * ScaleY;
|
||||
WorldRotation = parent.WorldRotation + Rotation;
|
||||
} else {
|
||||
WorldX = X;
|
||||
WorldY = Y;
|
||||
WorldScaleX = ScaleX;
|
||||
WorldScaleY = ScaleY;
|
||||
WorldRotation = Rotation;
|
||||
}
|
||||
float radians = WorldRotation * (float)Math.PI / 180;
|
||||
float cos = (float)Math.Cos(radians);
|
||||
float sin = (float)Math.Sin(radians);
|
||||
M00 = cos * WorldScaleX;
|
||||
M10 = sin * WorldScaleX;
|
||||
M01 = -sin * WorldScaleY;
|
||||
M11 = cos * WorldScaleY;
|
||||
if (flipX) {
|
||||
M00 = -M00;
|
||||
M01 = -M01;
|
||||
}
|
||||
if (flipY) {
|
||||
M10 = -M10;
|
||||
M11 = -M11;
|
||||
}
|
||||
if (yDown) {
|
||||
M10 = -M10;
|
||||
M11 = -M11;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetToBindPose () {
|
||||
BoneData data = Data;
|
||||
X = data.X;
|
||||
Y = data.Y;
|
||||
Rotation = data.Rotation;
|
||||
ScaleX = data.ScaleX;
|
||||
ScaleY = data.ScaleY;
|
||||
}
|
||||
|
||||
override public String ToString () {
|
||||
return Data.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
53
spine-unity/Assets/Plugins/Spine/spine-csharp/BoneData.cs
Normal file
53
spine-unity/Assets/Plugins/Spine/spine-csharp/BoneData.cs
Normal file
@ -0,0 +1,53 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 BoneData {
|
||||
/** May be null. */
|
||||
public BoneData Parent { get; private set; }
|
||||
public String Name { get; private set; }
|
||||
public float Length { get; set; }
|
||||
public float X { get; set; }
|
||||
public float Y { get; set; }
|
||||
public float Rotation { get; set; }
|
||||
public float ScaleX { get; set; }
|
||||
public float ScaleY { get; set; }
|
||||
|
||||
/** @param parent May be null. */
|
||||
public BoneData (String name, BoneData parent) {
|
||||
if (name == null) throw new ArgumentNullException("name cannot be null.");
|
||||
Name = name;
|
||||
Parent = parent;
|
||||
ScaleX = 1;
|
||||
ScaleY = 1;
|
||||
}
|
||||
|
||||
override public String ToString () {
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
542
spine-unity/Assets/Plugins/Spine/spine-csharp/Json.cs
Normal file
542
spine-unity/Assets/Plugins/Spine/spine-csharp/Json.cs
Normal file
@ -0,0 +1,542 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Calvin Rien
|
||||
*
|
||||
* Based on the JSON parser by Patrick van Bergen
|
||||
* http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html
|
||||
*
|
||||
* Simplified it so that it doesn't throw exceptions
|
||||
* and can be used in Unity iPhone with maximum code stripping.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Spine
|
||||
{
|
||||
// Example usage:
|
||||
//
|
||||
// using UnityEngine;
|
||||
// using System.Collections;
|
||||
// using System.Collections.Generic;
|
||||
// using MiniJSON;
|
||||
//
|
||||
// public class MiniJSONTest : MonoBehaviour {
|
||||
// void Start () {
|
||||
// var jsonString = "{ \"array\": [1.44,2,3], " +
|
||||
// "\"object\": {\"key1\":\"value1\", \"key2\":256}, " +
|
||||
// "\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " +
|
||||
// "\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " +
|
||||
// "\"int\": 65536, " +
|
||||
// "\"float\": 3.1415926, " +
|
||||
// "\"bool\": true, " +
|
||||
// "\"null\": null }";
|
||||
//
|
||||
// var dict = Json.Deserialize(jsonString) as Dictionary<string,object>;
|
||||
//
|
||||
// Debug.Log("deserialized: " + dict.GetType());
|
||||
// Debug.Log("dict['array'][0]: " + ((List<object>) dict["array"])[0]);
|
||||
// Debug.Log("dict['string']: " + (string) dict["string"]);
|
||||
// Debug.Log("dict['float']: " + (float) dict["float"]);
|
||||
// Debug.Log("dict['int']: " + (long) dict["int"]); // ints come out as longs
|
||||
// Debug.Log("dict['unicode']: " + (string) dict["unicode"]);
|
||||
//
|
||||
// var str = Json.Serialize(dict);
|
||||
//
|
||||
// Debug.Log("serialized: " + str);
|
||||
// }
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// This class encodes and decodes JSON strings.
|
||||
/// Spec. details, see http://www.json.org/
|
||||
///
|
||||
/// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary.
|
||||
/// All numbers are parsed to floats.
|
||||
/// </summary>
|
||||
public static class Json {
|
||||
/// <summary>
|
||||
/// Parses the string json into a value
|
||||
/// </summary>
|
||||
/// <param name="json">A JSON string.</param>
|
||||
/// <returns>An List<object>, a Dictionary<string, object>, a float, an integer,a string, null, true, or false</returns>
|
||||
public static object Deserialize (TextReader json) {
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
return Parser.Parse(json);
|
||||
}
|
||||
|
||||
sealed class Parser : IDisposable {
|
||||
const string WHITE_SPACE = " \t\n\r";
|
||||
const string WORD_BREAK = " \t\n\r{}[],:\"";
|
||||
|
||||
enum TOKEN {
|
||||
NONE,
|
||||
CURLY_OPEN,
|
||||
CURLY_CLOSE,
|
||||
SQUARED_OPEN,
|
||||
SQUARED_CLOSE,
|
||||
COLON,
|
||||
COMMA,
|
||||
STRING,
|
||||
NUMBER,
|
||||
TRUE,
|
||||
FALSE,
|
||||
NULL
|
||||
};
|
||||
|
||||
TextReader json;
|
||||
|
||||
Parser(TextReader reader) {
|
||||
json = reader;
|
||||
}
|
||||
|
||||
public static object Parse (TextReader reader) {
|
||||
using (var instance = new Parser(reader)) {
|
||||
return instance.ParseValue();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
json.Dispose();
|
||||
json = null;
|
||||
}
|
||||
|
||||
Dictionary<string, object> ParseObject() {
|
||||
Dictionary<string, object> table = new Dictionary<string, object>();
|
||||
|
||||
// ditch opening brace
|
||||
json.Read();
|
||||
|
||||
// {
|
||||
while (true) {
|
||||
switch (NextToken) {
|
||||
case TOKEN.NONE:
|
||||
return null;
|
||||
case TOKEN.COMMA:
|
||||
continue;
|
||||
case TOKEN.CURLY_CLOSE:
|
||||
return table;
|
||||
default:
|
||||
// name
|
||||
string name = ParseString();
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// :
|
||||
if (NextToken != TOKEN.COLON) {
|
||||
return null;
|
||||
}
|
||||
// ditch the colon
|
||||
json.Read();
|
||||
|
||||
// value
|
||||
table[name] = ParseValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<object> ParseArray() {
|
||||
List<object> array = new List<object>();
|
||||
|
||||
// ditch opening bracket
|
||||
json.Read();
|
||||
|
||||
// [
|
||||
var parsing = true;
|
||||
while (parsing) {
|
||||
TOKEN nextToken = NextToken;
|
||||
|
||||
switch (nextToken) {
|
||||
case TOKEN.NONE:
|
||||
return null;
|
||||
case TOKEN.COMMA:
|
||||
continue;
|
||||
case TOKEN.SQUARED_CLOSE:
|
||||
parsing = false;
|
||||
break;
|
||||
default:
|
||||
object value = ParseByToken(nextToken);
|
||||
|
||||
array.Add(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
object ParseValue() {
|
||||
TOKEN nextToken = NextToken;
|
||||
return ParseByToken(nextToken);
|
||||
}
|
||||
|
||||
object ParseByToken(TOKEN token) {
|
||||
switch (token) {
|
||||
case TOKEN.STRING:
|
||||
return ParseString();
|
||||
case TOKEN.NUMBER:
|
||||
return ParseNumber();
|
||||
case TOKEN.CURLY_OPEN:
|
||||
return ParseObject();
|
||||
case TOKEN.SQUARED_OPEN:
|
||||
return ParseArray();
|
||||
case TOKEN.TRUE:
|
||||
return true;
|
||||
case TOKEN.FALSE:
|
||||
return false;
|
||||
case TOKEN.NULL:
|
||||
return null;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
string ParseString() {
|
||||
StringBuilder s = new StringBuilder();
|
||||
char c;
|
||||
|
||||
// ditch opening quote
|
||||
json.Read();
|
||||
|
||||
bool parsing = true;
|
||||
while (parsing) {
|
||||
|
||||
if (json.Peek() == -1) {
|
||||
parsing = false;
|
||||
break;
|
||||
}
|
||||
|
||||
c = NextChar;
|
||||
switch (c) {
|
||||
case '"':
|
||||
parsing = false;
|
||||
break;
|
||||
case '\\':
|
||||
if (json.Peek() == -1) {
|
||||
parsing = false;
|
||||
break;
|
||||
}
|
||||
|
||||
c = NextChar;
|
||||
switch (c) {
|
||||
case '"':
|
||||
case '\\':
|
||||
case '/':
|
||||
s.Append(c);
|
||||
break;
|
||||
case 'b':
|
||||
s.Append('\b');
|
||||
break;
|
||||
case 'f':
|
||||
s.Append('\f');
|
||||
break;
|
||||
case 'n':
|
||||
s.Append('\n');
|
||||
break;
|
||||
case 'r':
|
||||
s.Append('\r');
|
||||
break;
|
||||
case 't':
|
||||
s.Append('\t');
|
||||
break;
|
||||
case 'u':
|
||||
var hex = new StringBuilder();
|
||||
|
||||
for (int i=0; i< 4; i++) {
|
||||
hex.Append(NextChar);
|
||||
}
|
||||
|
||||
s.Append((char) Convert.ToInt32(hex.ToString(), 16));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
s.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return s.ToString();
|
||||
}
|
||||
|
||||
object ParseNumber() {
|
||||
string number = NextWord;
|
||||
float parsedFloat;
|
||||
float.TryParse(number, NumberStyles.Float, CultureInfo.InvariantCulture, out parsedFloat);
|
||||
return parsedFloat;
|
||||
}
|
||||
|
||||
void EatWhitespace() {
|
||||
while (WHITE_SPACE.IndexOf(PeekChar) != -1) {
|
||||
json.Read();
|
||||
|
||||
if (json.Peek() == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char PeekChar {
|
||||
get {
|
||||
return Convert.ToChar(json.Peek());
|
||||
}
|
||||
}
|
||||
|
||||
char NextChar {
|
||||
get {
|
||||
return Convert.ToChar(json.Read());
|
||||
}
|
||||
}
|
||||
|
||||
string NextWord {
|
||||
get {
|
||||
StringBuilder word = new StringBuilder();
|
||||
|
||||
while (WORD_BREAK.IndexOf(PeekChar) == -1) {
|
||||
word.Append(NextChar);
|
||||
|
||||
if (json.Peek() == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return word.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
TOKEN NextToken {
|
||||
get {
|
||||
EatWhitespace();
|
||||
|
||||
if (json.Peek() == -1) {
|
||||
return TOKEN.NONE;
|
||||
}
|
||||
|
||||
char c = PeekChar;
|
||||
switch (c) {
|
||||
case '{':
|
||||
return TOKEN.CURLY_OPEN;
|
||||
case '}':
|
||||
json.Read();
|
||||
return TOKEN.CURLY_CLOSE;
|
||||
case '[':
|
||||
return TOKEN.SQUARED_OPEN;
|
||||
case ']':
|
||||
json.Read();
|
||||
return TOKEN.SQUARED_CLOSE;
|
||||
case ',':
|
||||
json.Read();
|
||||
return TOKEN.COMMA;
|
||||
case '"':
|
||||
return TOKEN.STRING;
|
||||
case ':':
|
||||
return TOKEN.COLON;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '-':
|
||||
return TOKEN.NUMBER;
|
||||
}
|
||||
|
||||
string word = NextWord;
|
||||
|
||||
switch (word) {
|
||||
case "false":
|
||||
return TOKEN.FALSE;
|
||||
case "true":
|
||||
return TOKEN.TRUE;
|
||||
case "null":
|
||||
return TOKEN.NULL;
|
||||
}
|
||||
|
||||
return TOKEN.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string
|
||||
/// </summary>
|
||||
/// <param name="json">A Dictionary<string, object> / List<object></param>
|
||||
/// <returns>A JSON encoded string, or null if object 'json' is not serializable</returns>
|
||||
public static string Serialize(object obj) {
|
||||
return Serializer.Serialize(obj);
|
||||
}
|
||||
|
||||
sealed class Serializer {
|
||||
StringBuilder builder;
|
||||
|
||||
Serializer() {
|
||||
builder = new StringBuilder();
|
||||
}
|
||||
|
||||
public static string Serialize(object obj) {
|
||||
var instance = new Serializer();
|
||||
|
||||
instance.SerializeValue(obj);
|
||||
|
||||
return instance.builder.ToString();
|
||||
}
|
||||
|
||||
void SerializeValue(object value) {
|
||||
IList asList;
|
||||
IDictionary asDict;
|
||||
string asStr;
|
||||
|
||||
if (value == null) {
|
||||
builder.Append("null");
|
||||
}
|
||||
else if ((asStr = value as string) != null) {
|
||||
SerializeString(asStr);
|
||||
}
|
||||
else if (value is bool) {
|
||||
builder.Append(value.ToString().ToLower());
|
||||
}
|
||||
else if ((asList = value as IList) != null) {
|
||||
SerializeArray(asList);
|
||||
}
|
||||
else if ((asDict = value as IDictionary) != null) {
|
||||
SerializeObject(asDict);
|
||||
}
|
||||
else if (value is char) {
|
||||
SerializeString(value.ToString());
|
||||
}
|
||||
else {
|
||||
SerializeOther(value);
|
||||
}
|
||||
}
|
||||
|
||||
void SerializeObject(IDictionary obj) {
|
||||
bool first = true;
|
||||
|
||||
builder.Append('{');
|
||||
|
||||
foreach (object e in obj.Keys) {
|
||||
if (!first) {
|
||||
builder.Append(',');
|
||||
}
|
||||
|
||||
SerializeString(e.ToString());
|
||||
builder.Append(':');
|
||||
|
||||
SerializeValue(obj[e]);
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
builder.Append('}');
|
||||
}
|
||||
|
||||
void SerializeArray(IList anArray) {
|
||||
builder.Append('[');
|
||||
|
||||
bool first = true;
|
||||
|
||||
foreach (object obj in anArray) {
|
||||
if (!first) {
|
||||
builder.Append(',');
|
||||
}
|
||||
|
||||
SerializeValue(obj);
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
builder.Append(']');
|
||||
}
|
||||
|
||||
void SerializeString(string str) {
|
||||
builder.Append('\"');
|
||||
|
||||
char[] charArray = str.ToCharArray();
|
||||
foreach (var c in charArray) {
|
||||
switch (c) {
|
||||
case '"':
|
||||
builder.Append("\\\"");
|
||||
break;
|
||||
case '\\':
|
||||
builder.Append("\\\\");
|
||||
break;
|
||||
case '\b':
|
||||
builder.Append("\\b");
|
||||
break;
|
||||
case '\f':
|
||||
builder.Append("\\f");
|
||||
break;
|
||||
case '\n':
|
||||
builder.Append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
builder.Append("\\r");
|
||||
break;
|
||||
case '\t':
|
||||
builder.Append("\\t");
|
||||
break;
|
||||
default:
|
||||
int codepoint = Convert.ToInt32(c);
|
||||
if ((codepoint >= 32) && (codepoint <= 126)) {
|
||||
builder.Append(c);
|
||||
}
|
||||
else {
|
||||
builder.Append("\\u" + Convert.ToString(codepoint, 16).PadLeft(4, '0'));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
builder.Append('\"');
|
||||
}
|
||||
|
||||
void SerializeOther(object value) {
|
||||
if (value is float
|
||||
|| value is int
|
||||
|| value is uint
|
||||
|| value is long
|
||||
|| value is float
|
||||
|| value is sbyte
|
||||
|| value is byte
|
||||
|| value is short
|
||||
|| value is ushort
|
||||
|| value is ulong
|
||||
|| value is decimal) {
|
||||
builder.Append(value.ToString());
|
||||
}
|
||||
else {
|
||||
SerializeString(value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
196
spine-unity/Assets/Plugins/Spine/spine-csharp/Skeleton.cs
Normal file
196
spine-unity/Assets/Plugins/Spine/spine-csharp/Skeleton.cs
Normal file
@ -0,0 +1,196 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 Skeleton {
|
||||
public SkeletonData Data { get; private set; }
|
||||
public List<Bone> Bones { get; private set; }
|
||||
public List<Slot> Slots { get; private set; }
|
||||
public List<Slot> DrawOrder { get; private set; }
|
||||
public Skin Skin { get; set; }
|
||||
public float R { get; set; }
|
||||
public float G { get; set; }
|
||||
public float B { get; set; }
|
||||
public float A { get; set; }
|
||||
public float Time { get; set; }
|
||||
public bool FlipX { get; set; }
|
||||
public bool FlipY { get; set; }
|
||||
public Bone RootBone {
|
||||
get {
|
||||
return Bones.Count == 0 ? null : Bones[0];
|
||||
}
|
||||
}
|
||||
|
||||
public Skeleton (SkeletonData data) {
|
||||
if (data == null) throw new ArgumentNullException("data cannot be null.");
|
||||
Data = data;
|
||||
|
||||
Bones = new List<Bone>(Data.Bones.Count);
|
||||
foreach (BoneData boneData in Data.Bones) {
|
||||
Bone parent = boneData.Parent == null ? null : Bones[Data.Bones.IndexOf(boneData.Parent)];
|
||||
Bones.Add(new Bone(boneData, parent));
|
||||
}
|
||||
|
||||
Slots = new List<Slot>(Data.Slots.Count);
|
||||
DrawOrder = new List<Slot>(Data.Slots.Count);
|
||||
foreach (SlotData slotData in Data.Slots) {
|
||||
Bone bone = Bones[Data.Bones.IndexOf(slotData.BoneData)];
|
||||
Slot slot = new Slot(slotData, this, bone);
|
||||
Slots.Add(slot);
|
||||
DrawOrder.Add(slot);
|
||||
}
|
||||
|
||||
R = 1;
|
||||
G = 1;
|
||||
B = 1;
|
||||
A = 1;
|
||||
}
|
||||
|
||||
/** Updates the world transform for each bone. */
|
||||
public void UpdateWorldTransform () {
|
||||
bool flipX = FlipX;
|
||||
bool flipY = FlipY;
|
||||
List<Bone> bones = Bones;
|
||||
for (int i = 0, n = bones.Count; i < n; i++)
|
||||
bones[i].UpdateWorldTransform(flipX, flipY);
|
||||
}
|
||||
|
||||
/** Sets the bones and slots to their bind pose values. */
|
||||
public void SetToBindPose () {
|
||||
SetBonesToBindPose();
|
||||
SetSlotsToBindPose();
|
||||
}
|
||||
|
||||
public void SetBonesToBindPose () {
|
||||
List<Bone> bones = this.Bones;
|
||||
for (int i = 0, n = bones.Count; i < n; i++)
|
||||
bones[i].SetToBindPose();
|
||||
}
|
||||
|
||||
public void SetSlotsToBindPose () {
|
||||
List<Slot> slots = this.Slots;
|
||||
for (int i = 0, n = slots.Count; i < n; i++)
|
||||
slots[i].SetToBindPose(i);
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public Bone FindBone (String boneName) {
|
||||
if (boneName == null) throw new ArgumentNullException("boneName cannot be null.");
|
||||
List<Bone> bones = this.Bones;
|
||||
for (int i = 0, n = bones.Count; i < n; i++) {
|
||||
Bone bone = bones[i];
|
||||
if (bone.Data.Name == boneName) return bone;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return -1 if the bone was not found. */
|
||||
public int FindBoneIndex (String boneName) {
|
||||
if (boneName == null) throw new ArgumentNullException("boneName cannot be null.");
|
||||
List<Bone> bones = this.Bones;
|
||||
for (int i = 0, n = bones.Count; i < n; i++)
|
||||
if (bones[i].Data.Name == boneName) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public Slot FindSlot (String slotName) {
|
||||
if (slotName == null) throw new ArgumentNullException("slotName cannot be null.");
|
||||
List<Slot> slots = this.Slots;
|
||||
for (int i = 0, n = slots.Count; i < n; i++) {
|
||||
Slot slot = slots[i];
|
||||
if (slot.Data.Name == slotName) return slot;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return -1 if the bone was not found. */
|
||||
public int FindSlotIndex (String slotName) {
|
||||
if (slotName == null) throw new ArgumentNullException("slotName cannot be null.");
|
||||
List<Slot> slots = this.Slots;
|
||||
for (int i = 0, n = slots.Count; i < n; i++)
|
||||
if (slots[i].Data.Name.Equals(slotName)) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Sets a skin by name.
|
||||
* @see #setSkin(Skin) */
|
||||
public void SetSkin (String skinName) {
|
||||
Skin skin = Data.FindSkin(skinName);
|
||||
if (skin == null) throw new ArgumentException("Skin not found: " + skinName);
|
||||
SetSkin(skin);
|
||||
}
|
||||
|
||||
/** Sets the skin used to look up attachments not found in the {@link SkeletonData#getDefaultSkin() default skin}. Attachments
|
||||
* from the new skin are attached if the corresponding attachment from the old skin was attached.
|
||||
* @param newSkin May be null. */
|
||||
public void SetSkin (Skin newSkin) {
|
||||
if (Skin != null && newSkin != null) newSkin.AttachAll(this, Skin);
|
||||
Skin = newSkin;
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public Attachment GetAttachment (String slotName, String attachmentName) {
|
||||
return GetAttachment(Data.FindSlotIndex(slotName), attachmentName);
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public Attachment GetAttachment (int slotIndex, String attachmentName) {
|
||||
if (attachmentName == null) throw new ArgumentNullException("attachmentName cannot be null.");
|
||||
if (Skin != null) {
|
||||
Attachment attachment = Skin.GetAttachment(slotIndex, attachmentName);
|
||||
if (attachment != null) return attachment;
|
||||
}
|
||||
if (Data.DefaultSkin != null) return Data.DefaultSkin.GetAttachment(slotIndex, attachmentName);
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @param attachmentName May be null. */
|
||||
public void SetAttachment (String slotName, String attachmentName) {
|
||||
if (slotName == null) throw new ArgumentNullException("slotName cannot be null.");
|
||||
List<Slot> slots = Slots;
|
||||
for (int i = 0, n = slots.Count; i < n; i++) {
|
||||
Slot slot = slots[i];
|
||||
if (slot.Data.Name == slotName) {
|
||||
Attachment attachment = null;
|
||||
if (attachmentName != null) {
|
||||
attachment = GetAttachment(i, attachmentName);
|
||||
if (attachment == null) throw new ArgumentNullException("Attachment not found: " + attachmentName + ", for slot: " + slotName);
|
||||
}
|
||||
slot.Attachment = attachment;
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new Exception("Slot not found: " + slotName);
|
||||
}
|
||||
|
||||
public void Update (float delta) {
|
||||
Time += delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
135
spine-unity/Assets/Plugins/Spine/spine-csharp/SkeletonData.cs
Normal file
135
spine-unity/Assets/Plugins/Spine/spine-csharp/SkeletonData.cs
Normal file
@ -0,0 +1,135 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 SkeletonData {
|
||||
public String Name { get; set; }
|
||||
public List<BoneData> Bones { get; private set; } // Ordered parents first.
|
||||
public List<SlotData> Slots { get; private set; } // Bind pose draw order.
|
||||
public List<Skin> Skins { get; private set; }
|
||||
/** May be null. */
|
||||
public Skin DefaultSkin;
|
||||
public List<Animation> Animations { get; private set; }
|
||||
|
||||
public SkeletonData () {
|
||||
Bones = new List<BoneData>();
|
||||
Slots = new List<SlotData>();
|
||||
Skins = new List<Skin>();
|
||||
Animations = new List<Animation>();
|
||||
}
|
||||
|
||||
// --- Bones.
|
||||
|
||||
public void AddBone (BoneData bone) {
|
||||
if (bone == null) throw new ArgumentNullException("bone cannot be null.");
|
||||
Bones.Add(bone);
|
||||
}
|
||||
|
||||
|
||||
/** @return May be null. */
|
||||
public BoneData FindBone (String boneName) {
|
||||
if (boneName == null) throw new ArgumentNullException("boneName cannot be null.");
|
||||
for (int i = 0, n = Bones.Count; i < n; i++) {
|
||||
BoneData bone = Bones[i];
|
||||
if (bone.Name == boneName) return bone;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return -1 if the bone was not found. */
|
||||
public int FindBoneIndex (String boneName) {
|
||||
if (boneName == null) throw new ArgumentNullException("boneName cannot be null.");
|
||||
for (int i = 0, n = Bones.Count; i < n; i++)
|
||||
if (Bones[i].Name == boneName) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// --- Slots.
|
||||
|
||||
public void AddSlot (SlotData slot) {
|
||||
if (slot == null) throw new ArgumentNullException("slot cannot be null.");
|
||||
Slots.Add(slot);
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public SlotData FindSlot (String slotName) {
|
||||
if (slotName == null) throw new ArgumentNullException("slotName cannot be null.");
|
||||
for (int i = 0, n = Slots.Count; i < n; i++) {
|
||||
SlotData slot = Slots[i];
|
||||
if (slot.Name == slotName) return slot;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return -1 if the bone was not found. */
|
||||
public int FindSlotIndex (String slotName) {
|
||||
if (slotName == null) throw new ArgumentNullException("slotName cannot be null.");
|
||||
for (int i = 0, n = Slots.Count; i < n; i++)
|
||||
if (Slots[i].Name == slotName) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// --- Skins.
|
||||
|
||||
public void AddSkin (Skin skin) {
|
||||
if (skin == null) throw new ArgumentNullException("skin cannot be null.");
|
||||
Skins.Add(skin);
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public Skin FindSkin (String skinName) {
|
||||
if (skinName == null) throw new ArgumentNullException("skinName cannot be null.");
|
||||
foreach (Skin skin in Skins)
|
||||
if (skin.Name == skinName) return skin;
|
||||
return null;
|
||||
}
|
||||
|
||||
// --- Animations.
|
||||
|
||||
public void AddAnimation (Animation animation) {
|
||||
if (animation == null) throw new ArgumentNullException("animation cannot be null.");
|
||||
Animations.Add(animation);
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public Animation FindAnimation (String animationName) {
|
||||
if (animationName == null) throw new ArgumentNullException("animationName cannot be null.");
|
||||
for (int i = 0, n = Animations.Count; i < n; i++) {
|
||||
Animation animation = Animations[i];
|
||||
if (animation.Name == animationName) return animation;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
override public String ToString () {
|
||||
return Name != null ? Name : base.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
302
spine-unity/Assets/Plugins/Spine/spine-csharp/SkeletonJson.cs
Normal file
302
spine-unity/Assets/Plugins/Spine/spine-csharp/SkeletonJson.cs
Normal file
@ -0,0 +1,302 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine {
|
||||
public class SkeletonJson {
|
||||
static public String TIMELINE_SCALE = "scale";
|
||||
static public String TIMELINE_ROTATE = "rotate";
|
||||
static public String TIMELINE_TRANSLATE = "translate";
|
||||
static public String TIMELINE_ATTACHMENT = "attachment";
|
||||
static public String TIMELINE_COLOR = "color";
|
||||
|
||||
static public String ATTACHMENT_REGION = "region";
|
||||
static public String ATTACHMENT_REGION_SEQUENCE = "regionSequence";
|
||||
|
||||
private AttachmentLoader attachmentLoader;
|
||||
public float Scale { get; set; }
|
||||
|
||||
public SkeletonJson (Atlas atlas) {
|
||||
this.attachmentLoader = new AtlasAttachmentLoader(atlas);
|
||||
Scale = 1;
|
||||
}
|
||||
|
||||
public SkeletonJson (AttachmentLoader attachmentLoader) {
|
||||
if (attachmentLoader == null) throw new ArgumentNullException("attachmentLoader cannot be null.");
|
||||
this.attachmentLoader = attachmentLoader;
|
||||
Scale = 1;
|
||||
}
|
||||
|
||||
public SkeletonData ReadSkeletonData (String path) {
|
||||
using (StreamReader reader = new StreamReader(path)) {
|
||||
SkeletonData skeletonData = ReadSkeletonData(reader);
|
||||
skeletonData.Name = Path.GetFileNameWithoutExtension(path);
|
||||
return skeletonData;
|
||||
}
|
||||
}
|
||||
|
||||
public SkeletonData ReadSkeletonData (TextReader reader) {
|
||||
if (reader == null) throw new ArgumentNullException("reader cannot be null.");
|
||||
|
||||
SkeletonData skeletonData = new SkeletonData();
|
||||
|
||||
var root = Json.Deserialize(reader) as Dictionary<String, Object>;
|
||||
if (root == null) throw new Exception("Invalid JSON.");
|
||||
|
||||
// Bones.
|
||||
foreach (Dictionary<String, Object> boneMap in (List<Object>)root["bones"]) {
|
||||
BoneData parent = null;
|
||||
if (boneMap.ContainsKey("parent")) {
|
||||
parent = skeletonData.FindBone((String)boneMap["parent"]);
|
||||
if (parent == null)
|
||||
throw new Exception("Parent bone not found: " + boneMap["parent"]);
|
||||
}
|
||||
BoneData boneData = new BoneData((String)boneMap["name"], parent);
|
||||
boneData.Length = GetFloat(boneMap, "length", 0) * Scale;
|
||||
boneData.X = GetFloat(boneMap, "x", 0) * Scale;
|
||||
boneData.Y = GetFloat(boneMap, "y", 0) * Scale;
|
||||
boneData.Rotation = GetFloat(boneMap, "rotation", 0);
|
||||
boneData.ScaleX = GetFloat(boneMap, "scaleX", 1);
|
||||
boneData.ScaleY = GetFloat(boneMap, "scaleY", 1);
|
||||
skeletonData.AddBone(boneData);
|
||||
}
|
||||
|
||||
// Slots.
|
||||
if (root.ContainsKey("slots")) {
|
||||
var slots = (List<Object>)root["slots"];
|
||||
foreach (Dictionary<String, Object> slotMap in (List<Object>)slots) {
|
||||
String slotName = (String)slotMap["name"];
|
||||
String boneName = (String)slotMap["bone"];
|
||||
BoneData boneData = skeletonData.FindBone(boneName);
|
||||
if (boneData == null)
|
||||
throw new Exception("Slot bone not found: " + boneName);
|
||||
SlotData slotData = new SlotData(slotName, boneData);
|
||||
|
||||
if (slotMap.ContainsKey("color")) {
|
||||
String color = (String)slotMap["color"];
|
||||
slotData.R = ToColor(color, 0);
|
||||
slotData.G = ToColor(color, 1);
|
||||
slotData.B = ToColor(color, 2);
|
||||
slotData.A = ToColor(color, 3);
|
||||
}
|
||||
|
||||
if (slotMap.ContainsKey("attachment"))
|
||||
slotData.AttachmentName = (String)slotMap["attachment"];
|
||||
|
||||
skeletonData.AddSlot(slotData);
|
||||
}
|
||||
}
|
||||
|
||||
// Skins.
|
||||
if (root.ContainsKey("skins")) {
|
||||
var skinMap = (Dictionary<String, Object>)root["skins"];
|
||||
foreach (KeyValuePair<String, Object> entry in skinMap) {
|
||||
Skin skin = new Skin(entry.Key);
|
||||
foreach (KeyValuePair<String, Object> slotEntry in (Dictionary<String, Object>)entry.Value) {
|
||||
int slotIndex = skeletonData.FindSlotIndex(slotEntry.Key);
|
||||
foreach (KeyValuePair<String, Object> attachmentEntry in ((Dictionary<String, Object>)slotEntry.Value)) {
|
||||
Attachment attachment = ReadAttachment(skin, attachmentEntry.Key, (Dictionary<String, Object>)attachmentEntry.Value);
|
||||
skin.AddAttachment(slotIndex, attachmentEntry.Key, attachment);
|
||||
}
|
||||
}
|
||||
skeletonData.AddSkin(skin);
|
||||
if (skin.Name == "default")
|
||||
skeletonData.DefaultSkin = skin;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Animations.
|
||||
if (root.ContainsKey("animations")) {
|
||||
var animationMap = (Dictionary<String, Object>)root["animations"];
|
||||
foreach (KeyValuePair<String, Object> entry in animationMap)
|
||||
ReadAnimation(entry.Key, (Dictionary<String, Object>)entry.Value, skeletonData);
|
||||
}
|
||||
|
||||
skeletonData.Bones.TrimExcess();
|
||||
skeletonData.Slots.TrimExcess();
|
||||
skeletonData.Skins.TrimExcess();
|
||||
skeletonData.Animations.TrimExcess();
|
||||
return skeletonData;
|
||||
}
|
||||
|
||||
private Attachment ReadAttachment (Skin skin, String name, Dictionary<String, Object> map) {
|
||||
if (map.ContainsKey("name"))
|
||||
name = (String)map["name"];
|
||||
|
||||
AttachmentType type = AttachmentType.region;
|
||||
if (map.ContainsKey("type"))
|
||||
type = (AttachmentType)Enum.Parse(typeof(AttachmentType), (String)map["type"], false);
|
||||
Attachment attachment = attachmentLoader.NewAttachment(skin, type, name);
|
||||
|
||||
if (attachment is RegionAttachment) {
|
||||
RegionAttachment regionAttachment = (RegionAttachment)attachment;
|
||||
regionAttachment.X = GetFloat(map, "x", 0) * Scale;
|
||||
regionAttachment.Y = GetFloat(map, "y", 0) * Scale;
|
||||
regionAttachment.ScaleX = GetFloat(map, "scaleX", 1);
|
||||
regionAttachment.ScaleY = GetFloat(map, "scaleY", 1);
|
||||
regionAttachment.Rotation = GetFloat(map, "rotation", 0);
|
||||
regionAttachment.Width = GetFloat(map, "width", 32) * Scale;
|
||||
regionAttachment.Height = GetFloat(map, "height", 32) * Scale;
|
||||
regionAttachment.UpdateOffset();
|
||||
}
|
||||
|
||||
return attachment;
|
||||
}
|
||||
|
||||
private float GetFloat (Dictionary<String, Object> map, String name, float defaultValue) {
|
||||
if (!map.ContainsKey(name))
|
||||
return (float)defaultValue;
|
||||
return (float)map[name];
|
||||
}
|
||||
|
||||
public static float ToColor (String hexString, int colorIndex) {
|
||||
if (hexString.Length != 8)
|
||||
throw new ArgumentException("Color hexidecimal length must be 8, recieved: " + hexString);
|
||||
return Convert.ToInt32(hexString.Substring(colorIndex * 2, 2), 16) / (float)255;
|
||||
}
|
||||
|
||||
private void ReadAnimation (String name, Dictionary<String, Object> map, SkeletonData skeletonData) {
|
||||
var timelines = new List<Timeline>();
|
||||
float duration = 0;
|
||||
|
||||
if (map.ContainsKey("bones")) {
|
||||
var bonesMap = (Dictionary<String, Object>)map["bones"];
|
||||
foreach (KeyValuePair<String, Object> entry in bonesMap) {
|
||||
String boneName = entry.Key;
|
||||
int boneIndex = skeletonData.FindBoneIndex(boneName);
|
||||
if (boneIndex == -1)
|
||||
throw new Exception("Bone not found: " + boneName);
|
||||
|
||||
var timelineMap = (Dictionary<String, Object>)entry.Value;
|
||||
foreach (KeyValuePair<String, Object> timelineEntry in timelineMap) {
|
||||
var values = (List<Object>)timelineEntry.Value;
|
||||
String timelineName = (String)timelineEntry.Key;
|
||||
if (timelineName.Equals(TIMELINE_ROTATE)) {
|
||||
RotateTimeline timeline = new RotateTimeline(values.Count);
|
||||
timeline.BoneIndex = boneIndex;
|
||||
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<String, Object> valueMap in values) {
|
||||
float time = (float)valueMap["time"];
|
||||
timeline.SetFrame(frameIndex, time, (float)valueMap["angle"]);
|
||||
ReadCurve(timeline, frameIndex, valueMap);
|
||||
frameIndex++;
|
||||
}
|
||||
timelines.Add(timeline);
|
||||
duration = Math.Max(duration, timeline.Frames[timeline.FrameCount * 2 - 2]);
|
||||
|
||||
} else if (timelineName.Equals(TIMELINE_TRANSLATE) || timelineName.Equals(TIMELINE_SCALE)) {
|
||||
TranslateTimeline timeline;
|
||||
float timelineScale = 1;
|
||||
if (timelineName.Equals(TIMELINE_SCALE))
|
||||
timeline = new ScaleTimeline(values.Count);
|
||||
else {
|
||||
timeline = new TranslateTimeline(values.Count);
|
||||
timelineScale = Scale;
|
||||
}
|
||||
timeline.BoneIndex = boneIndex;
|
||||
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<String, Object> valueMap in values) {
|
||||
float time = (float)valueMap["time"];
|
||||
float x = valueMap.ContainsKey("x") ? (float)valueMap["x"] : 0;
|
||||
float y = valueMap.ContainsKey("y") ? (float)valueMap["y"] : 0;
|
||||
timeline.SetFrame(frameIndex, time, (float)x * timelineScale, (float)y * timelineScale);
|
||||
ReadCurve(timeline, frameIndex, valueMap);
|
||||
frameIndex++;
|
||||
}
|
||||
timelines.Add(timeline);
|
||||
duration = Math.Max(duration, timeline.Frames[timeline.FrameCount * 3 - 3]);
|
||||
|
||||
} else
|
||||
throw new Exception("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (map.ContainsKey("slots")) {
|
||||
var slotsMap = (Dictionary<String, Object>)map["slots"];
|
||||
foreach (KeyValuePair<String, Object> entry in slotsMap) {
|
||||
String slotName = entry.Key;
|
||||
int slotIndex = skeletonData.FindSlotIndex(slotName);
|
||||
var timelineMap = (Dictionary<String, Object>)entry.Value;
|
||||
|
||||
foreach (KeyValuePair<String, Object> timelineEntry in timelineMap) {
|
||||
var values = (List<Object>)timelineEntry.Value;
|
||||
String timelineName = (String)timelineEntry.Key;
|
||||
if (timelineName.Equals(TIMELINE_COLOR)) {
|
||||
ColorTimeline timeline = new ColorTimeline(values.Count);
|
||||
timeline.SlotIndex = slotIndex;
|
||||
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<String, Object> valueMap in values) {
|
||||
float time = (float)valueMap["time"];
|
||||
String c = (String)valueMap["color"];
|
||||
timeline.setFrame(frameIndex, time, ToColor(c, 0), ToColor(c, 1), ToColor(c, 2), ToColor(c, 3));
|
||||
ReadCurve(timeline, frameIndex, valueMap);
|
||||
frameIndex++;
|
||||
}
|
||||
timelines.Add(timeline);
|
||||
duration = Math.Max(duration, timeline.Frames[timeline.FrameCount * 5 - 5]);
|
||||
|
||||
} else if (timelineName.Equals(TIMELINE_ATTACHMENT)) {
|
||||
AttachmentTimeline timeline = new AttachmentTimeline(values.Count);
|
||||
timeline.SlotIndex = slotIndex;
|
||||
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<String, Object> valueMap in values) {
|
||||
float time = (float)valueMap["time"];
|
||||
timeline.setFrame(frameIndex++, time, (String)valueMap["name"]);
|
||||
}
|
||||
timelines.Add(timeline);
|
||||
duration = Math.Max(duration, timeline.Frames[timeline.FrameCount - 1]);
|
||||
|
||||
} else
|
||||
throw new Exception("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
timelines.TrimExcess();
|
||||
skeletonData.AddAnimation(new Animation(name, timelines, duration));
|
||||
}
|
||||
|
||||
private void ReadCurve (CurveTimeline timeline, int frameIndex, Dictionary<String, Object> valueMap) {
|
||||
if (!valueMap.ContainsKey("curve"))
|
||||
return;
|
||||
Object curveObject = valueMap["curve"];
|
||||
if (curveObject.Equals("stepped"))
|
||||
timeline.SetStepped(frameIndex);
|
||||
else if (curveObject is List<Object>) {
|
||||
List<Object> curve = (List<Object>)curveObject;
|
||||
timeline.SetCurve(frameIndex, (float)curve[0], (float)curve[1], (float)curve[2], (float)curve[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
80
spine-unity/Assets/Plugins/Spine/spine-csharp/Skin.cs
Normal file
80
spine-unity/Assets/Plugins/Spine/spine-csharp/Skin.cs
Normal file
@ -0,0 +1,80 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 {
|
||||
/** Stores attachments by slot index and attachment name. */
|
||||
public class Skin {
|
||||
public String Name { get; private set; }
|
||||
private Dictionary<KeyValuePair<int, String>, Attachment> attachments = new Dictionary<KeyValuePair<int, String>, Attachment>();
|
||||
|
||||
public Skin (String name) {
|
||||
if (name == null) throw new ArgumentNullException("name cannot be null.");
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public void AddAttachment (int slotIndex, String name, Attachment attachment) {
|
||||
if (attachment == null) throw new ArgumentNullException("attachment cannot be null.");
|
||||
attachments.Add(new KeyValuePair<int, String>(slotIndex, name), attachment);
|
||||
}
|
||||
|
||||
/** @return May be null. */
|
||||
public Attachment GetAttachment (int slotIndex, String name) {
|
||||
Attachment attachment;
|
||||
attachments.TryGetValue(new KeyValuePair<int, String>(slotIndex, name), out attachment);
|
||||
return attachment;
|
||||
}
|
||||
|
||||
public void FindNamesForSlot (int slotIndex, List<String> names) {
|
||||
if (names == null) throw new ArgumentNullException("names cannot be null.");
|
||||
foreach (KeyValuePair<int, String> key in attachments.Keys)
|
||||
if (key.Key == slotIndex) names.Add(key.Value);
|
||||
}
|
||||
|
||||
public void FindAttachmentsForSlot (int slotIndex, List<Attachment> attachments) {
|
||||
if (attachments == null) throw new ArgumentNullException("attachments cannot be null.");
|
||||
foreach (KeyValuePair<KeyValuePair<int, String>, Attachment> entry in this.attachments)
|
||||
if (entry.Key.Key == slotIndex) attachments.Add(entry.Value);
|
||||
}
|
||||
|
||||
override public String ToString () {
|
||||
return Name;
|
||||
}
|
||||
|
||||
/** Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. */
|
||||
internal void AttachAll (Skeleton skeleton, Skin oldSkin) {
|
||||
foreach (KeyValuePair<KeyValuePair<int, String>, Attachment> entry in oldSkin.attachments) {
|
||||
int slotIndex = entry.Key.Key;
|
||||
Slot slot = skeleton.Slots[slotIndex];
|
||||
if (slot.Attachment == entry.Value) {
|
||||
Attachment attachment = GetAttachment(slotIndex, entry.Key.Value);
|
||||
if (attachment != null) slot.Attachment = attachment;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
86
spine-unity/Assets/Plugins/Spine/spine-csharp/Slot.cs
Normal file
86
spine-unity/Assets/Plugins/Spine/spine-csharp/Slot.cs
Normal file
@ -0,0 +1,86 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 Slot {
|
||||
public SlotData Data { get; private set; }
|
||||
public Bone Bone { get; private set; }
|
||||
public Skeleton Skeleton { get; private set; }
|
||||
public float R { get; set; }
|
||||
public float G { get; set; }
|
||||
public float B { get; set; }
|
||||
public float A { get; set; }
|
||||
|
||||
/** May be null. */
|
||||
private Attachment attachment;
|
||||
public Attachment Attachment {
|
||||
get {
|
||||
return attachment;
|
||||
}
|
||||
set {
|
||||
attachment = value;
|
||||
attachmentTime = Skeleton.Time;
|
||||
}
|
||||
}
|
||||
|
||||
private float attachmentTime;
|
||||
public float AttachmentTime {
|
||||
get {
|
||||
return Skeleton.Time - attachmentTime;
|
||||
}
|
||||
set {
|
||||
attachmentTime = Skeleton.Time - value;
|
||||
}
|
||||
}
|
||||
|
||||
public Slot (SlotData data, Skeleton skeleton, Bone bone) {
|
||||
if (data == null) throw new ArgumentNullException("data cannot be null.");
|
||||
if (skeleton == null) throw new ArgumentNullException("skeleton cannot be null.");
|
||||
if (bone == null) throw new ArgumentNullException("bone cannot be null.");
|
||||
Data = data;
|
||||
Skeleton = skeleton;
|
||||
Bone = bone;
|
||||
SetToBindPose();
|
||||
}
|
||||
|
||||
internal void SetToBindPose (int slotIndex) {
|
||||
R = Data.R;
|
||||
G = Data.G;
|
||||
B = Data.B;
|
||||
A = Data.A;
|
||||
Attachment = Data.AttachmentName == null ? null : Skeleton.GetAttachment(slotIndex, Data.AttachmentName);
|
||||
}
|
||||
|
||||
public void SetToBindPose () {
|
||||
SetToBindPose(Skeleton.Data.Slots.IndexOf(Data));
|
||||
}
|
||||
|
||||
override public String ToString () {
|
||||
return Data.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
54
spine-unity/Assets/Plugins/Spine/spine-csharp/SlotData.cs
Normal file
54
spine-unity/Assets/Plugins/Spine/spine-csharp/SlotData.cs
Normal file
@ -0,0 +1,54 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 SlotData {
|
||||
public String Name { get; private set; }
|
||||
public BoneData BoneData { get; private set; }
|
||||
public float R { get; set; }
|
||||
public float G { get; set; }
|
||||
public float B { get; set; }
|
||||
public float A { get; set; }
|
||||
/** @param attachmentName May be null. */
|
||||
public String AttachmentName { get; set; }
|
||||
|
||||
public SlotData (String name, BoneData boneData) {
|
||||
if (name == null) throw new ArgumentNullException("name cannot be null.");
|
||||
if (boneData == null) throw new ArgumentNullException("boneData cannot be null.");
|
||||
Name = name;
|
||||
BoneData = boneData;
|
||||
R = 1;
|
||||
G = 1;
|
||||
B = 1;
|
||||
A = 1;
|
||||
}
|
||||
|
||||
override public String ToString () {
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user