Almost ready to implement file loading
This commit is contained in:
Stephen Gowen 2017-10-29 20:54:08 -04:00
parent c3e94bee82
commit 87a18e22b8
46 changed files with 1260 additions and 457 deletions

View File

@ -0,0 +1,82 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
#ifndef Spine_Animation_h
#define Spine_Animation_h
#include <spine/Vector.h>
#include <spine/MixPose.h>
#include <spine/MixDirection.h>
#include <string>
namespace Spine
{
class Timeline;
class Skeleton;
class Event;
class Animation
{
friend class RotateTimeline;
public:
Animation(std::string name, Vector<Timeline*>& timelines, float duration);
/// Applies all the animation's timelines to the specified skeleton.
/// See also Timeline::apply(Skeleton&, float, float, Vector, float, MixPose, MixDirection)
void apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction);
std::string getName();
Vector<Timeline*> getTimelines();
void setTimelines(Vector<Timeline*> inValue);
float getDuration();
void setDuration(float inValue);
private:
Vector<Timeline*> _timelines;
float _duration;
std::string _name;
/// @param target After the first and before the last entry.
static int binarySearch(Vector<float>& values, float target, int step);
/// @param target After the first and before the last entry.
static int binarySearch(Vector<float>& values, float target);
static int linearSearch(Vector<float>& values, float target, int step);
};
}
#endif /* Spine_Animation_h */

View File

@ -47,10 +47,14 @@ namespace Spine
/// constraint or application code modifies the world transform after it was computed from the local transform.
class Bone : public Updatable
{
RTTI_DECL;
friend class RotateTimeline;
friend class IkConstraint;
friend class TransformConstraint;
friend class VertexAttachment;
friend class PathConstraint;
friend class Skeleton;
public:
static void setYDown(bool inValue);

View File

@ -38,6 +38,8 @@ namespace Spine
/// The interface for all constraints.
class Constraint : public Updatable
{
RTTI_DECL;
public:
Constraint();

View File

@ -28,8 +28,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Attachment_h
#define Spine_Attachment_h
#ifndef Spine_ContainerUtil_h
#define Spine_ContainerUtil_h
#include <spine/Vector.h>
#include <spine/HashMap.h>
@ -50,7 +50,7 @@ namespace Spine
{
assert(name.length() > 0);
for (typename T* i = items.begin(); i != items.end(); ++i)
for (T** i = items.begin(); i != items.end(); ++i)
{
T* item = (*i);
if (item->getName() == name)
@ -68,12 +68,50 @@ namespace Spine
{
assert(name.length() > 0);
for (size_t i = 0, size_t len = items.size(); i < len; ++i)
for (size_t i = 0, len = items.size(); i < len; ++i)
{
T* item = items[i];
if (item->getName() == name)
{
return i;
return static_cast<int>(i);
}
}
return -1;
}
/// Finds an item by comparing each item's name.
/// It is more efficient to cache the results of this method than to call it multiple times.
/// @return May be NULL.
template<typename T>
static T* findWithDataName(Vector<T*>& items, std::string name)
{
assert(name.length() > 0);
for (T** i = items.begin(); i != items.end(); ++i)
{
T* item = (*i);
if (item->getData().getName() == name)
{
return item;
}
}
return NULL;
}
/// @return -1 if the item was not found.
template<typename T>
static int findIndexWithDataName(Vector<T*>& items, std::string name)
{
assert(name.length() > 0);
for (size_t i = 0, len = items.size(); i < len; ++i)
{
T* item = items[i];
if (item->getData().getName() == name)
{
return static_cast<int>(i);
}
}
@ -111,4 +149,4 @@ namespace Spine
};
}
#endif /* defined(__noctisgames__ContainerUtil__) */
#endif /* Spine_ContainerUtil_h */

View File

@ -41,6 +41,8 @@ namespace Spine
/// Base class for frames that use an interpolation bezier curve.
class CurveTimeline : public Timeline
{
RTTI_DECL;
public:
CurveTimeline(int frameCount);

View File

@ -38,11 +38,9 @@ namespace Spine
/// Stores the setup pose values for an Event.
class EventData
{
public:
int _intValue;
float _floatValue;
std::string _stringValue;
friend class Event;
public:
EventData(std::string name);
/// The name of the event, which is unique within the skeleton.
@ -58,8 +56,10 @@ namespace Spine
void setStringValue(std::string inValue);
private:
friend class Event;
const std::string _name;
int _intValue;
float _floatValue;
std::string _stringValue;
};
}

View File

@ -43,6 +43,10 @@ namespace Spine
class IkConstraint : public Constraint
{
friend class Skeleton;
RTTI_DECL;
public:
/// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified
/// in the world coordinate system.
@ -78,9 +82,9 @@ namespace Spine
private:
IkConstraintData& _data;
Vector<Bone*> _bones;
Bone* _target;
float _mix;
int _bendDirection;
Bone* _target;
};
}

View File

@ -41,6 +41,9 @@ namespace Spine
class IkConstraintData
{
friend class IkConstraint;
friend class Skeleton;
public:
IkConstraintData(std::string name);

View File

@ -73,11 +73,14 @@ namespace Spine
return false;
}
inline float clamp(float x, float lower, float upper)
{
return fminf(upper, fmaxf(x, lower));
}
class MathUtil
{
public:
static float SIN_TABLE[SIN_COUNT];
MathUtil();
/// Returns the sine in radians from a lookup table.
@ -95,12 +98,10 @@ namespace Spine
/// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323
/// degrees), largest error of 0.00488 radians (0.2796 degrees).
static float atan2(float y, float x);
};
inline float clamp(float x, float lower, float upper)
{
return fminf(upper, fmaxf(x, lower));
}
private:
static float SIN_TABLE[SIN_COUNT];
};
}
#endif /* Spine_MathUtil_h */

View File

@ -0,0 +1,143 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
#ifndef Spine_MeshAttachment_h
#define Spine_MeshAttachment_h
#include <spine/VertexAttachment.h>
namespace Spine
{
/// Attachment that displays a texture region using a mesh.
class MeshAttachment : public VertexAttachment
{
RTTI_DECL;
public:
public int HullLength { get { return _hulllength; } set { _hulllength = value; } }
public float[] RegionUVs { get { return _regionUVs; } set { _regionUVs = value; } }
/// The UV pair for each vertex, normalized within the entire texture. <seealso cref="MeshAttachment.updateUVs"/>
public float[] UVs { get { return _uvs; } set { _uvs = value; } }
public int[] Triangles { get { return _triangles; } set { _triangles = value; } }
public float R { get { return r; } set { r = value; } }
public float G { get { return g; } set { g = value; } }
public float B { get { return b; } set { b = value; } }
public float A { get { return a; } set { a = value; } }
public string Path { get; set; }
public object RendererObject; //public Object RendererObject { get; set; }
public float RegionU { get; set; }
public float RegionV { get; set; }
public float RegionU2 { get; set; }
public float RegionV2 { get; set; }
public bool RegionRotate { get; set; }
public float RegionOffsetX { get { return _regionOffsetX; } set { _regionOffsetX = value; } }
public float RegionOffsetY { get { return _regionOffsetY; } set { _regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated.
public float RegionWidth { get { return _regionWidth; } set { _regionWidth = value; } }
public float RegionHeight { get { return _regionHeight; } set { _regionHeight = value; } } // Unrotated, stripped size.
public float RegionOriginalWidth { get { return _regionOriginalWidth; } set { _regionOriginalWidth = value; } }
public float RegionOriginalHeight { get { return _regionOriginalHeight; } set { _regionOriginalHeight = value; } } // Unrotated, unstripped size.
public bool InheritDeform { get { return _inheritDeform; } set { _inheritDeform = value; } }
public MeshAttachment ParentMesh {
get { return _parentMesh; }
set {
_parentMesh = value;
if (value != null) {
bones = value.bones;
vertices = value.vertices;
worldVerticesLength = value.worldVerticesLength;
_regionUVs = value._regionUVs;
_triangles = value._triangles;
HullLength = value.HullLength;
Edges = value.Edges;
Width = value.Width;
Height = value.Height;
}
}
}
// Nonessential.
public int[] Edges { get; set; }
public float Width { get; set; }
public float Height { get; set; }
public MeshAttachment (string name) : VertexAttachment(name)
{
// Empty
}
public void updateUVs()
{
float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV;
if (_uvs == null || _uvs.Length != _regionUVs.Length)
{
_uvs = new float[_regionUVs.Length];
}
float[] _uvs = _uvs;
if (_regionRotate)
{
for (int i = 0, n = _uvs.Length; i < n; i += 2)
{
_uvs[i] = u + _regionUVs[i + 1] * width;
_uvs[i + 1] = v + height - _regionUVs[i] * height;
}
}
else
{
for (int i = 0, n = _uvs.Length; i < n; i += 2)
{
_uvs[i] = u + _regionUVs[i] * width;
_uvs[i + 1] = v + _regionUVs[i + 1] * height;
}
}
}
virtual bool applyDeform(VertexAttachment* sourceAttachment)
{
return this == sourceAttachment || (_inheritDeform && _parentMesh == sourceAttachment);
}
private:
float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight;
MeshAttachment* _parentMesh;
float[] _uvs, _regionUVs;
int[] _triangles;
float r = 1, g = 1, b = 1, a = 1;
int _hulllength;
bool _inheritDeform;
bool _regionRotate;
}
}
#endif /* Spine_MeshAttachment_h */

View File

@ -37,23 +37,23 @@ namespace Spine
{
class PathAttachment : public VertexAttachment
{
RTTI_DECL;
public:
PathAttachment(std::string name) : VertexAttachment(name)
{
// Empty
}
PathAttachment(std::string name);
/// The length in the setup pose from the start of the path to the end of each curve.
float[] Lengths { return lengths; }
set { lengths = value; }
bool Closed { return closed; }
set { closed = value; }
bool ConstantSpeed { return constantSpeed; }
set { constantSpeed = value; }
Vector<float>& getLengths();
void setLengths(Vector<float> inValue);
bool isClosed();
void setClosed(bool inValue);
bool isConstantSpeed();
void setConstantSpeed(bool inValue);
private:
float[] lengths;
bool closed, constantSpeed;
Vector<float> _lengths;
bool _closed;
bool _constantSpeed;
};
}

View File

@ -45,6 +45,11 @@ namespace Spine
class PathConstraint : public Constraint
{
friend class Skeleton;
RTTI_DECL;
public:
PathConstraint(PathConstraintData& data, Skeleton& skeleton);
/// Applies the constraint to the constrained bones.

View File

@ -45,6 +45,9 @@ namespace Spine
class PathConstraintData
{
friend class PathConstraint;
friend class Skeleton;
public:
PathConstraintData(std::string name);

View File

@ -0,0 +1,192 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
#ifndef Spine_RegionAttachment_h
#define Spine_RegionAttachment_h
#include <spine/Attachment.h>
#include <spine/Vector.h>
#include <spine/MathUtil.h>
#include <assert.h>
namespace Spine
{
class Bone;
/// Attachment that displays a texture region.
class RegionAttachment : public Attachment
{
RTTI_DECL;
public:
const int BLX = 0;
const int BLY = 1;
const int ULX = 2;
const int ULY = 3;
const int URX = 4;
const int URY = 5;
const int BRX = 6;
const int BRY = 7;
float X { get { return x; } set { x = value; } }
float Y { get { return y; } set { y = value; } }
float Rotation { get { return _rotation; } set { _rotation = value; } }
float ScaleX { get { return scaleX; } set { scaleX = value; } }
float ScaleY { get { return scaleY; } set { scaleY = value; } }
float Width { get { return width; } set { width = value; } }
float Height { get { return height; } set { height = value; } }
float R { get { return r; } set { r = value; } }
float G { get { return g; } set { g = value; } }
float B { get { return b; } set { b = value; } }
float A { get { return a; } set { a = value; } }
std::string Path { get; set; }
object RendererObject; //object RendererObject { get; set; }
float RegionOffsetX { get { return _regionOffsetX; } set { _regionOffsetX = value; } }
float RegionOffsetY { get { return _regionOffsetY; } set { _regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated.
float RegionWidth { get { return _regionWidth; } set { _regionWidth = value; } }
float RegionHeight { get { return _regionHeight; } set { _regionHeight = value; } } // Unrotated, stripped size.
float RegionOriginalWidth { get { return _regionOriginalWidth; } set { _regionOriginalWidth = value; } }
float RegionOriginalHeight { get { return _regionOriginalHeight; } set { _regionOriginalHeight = value; } } // Unrotated, unstripped size.
float[] Offset { get { return _offset; } }
float[] UVs { get { return _uvs; } }
RegionAttachment (std::string name) : Attachment(name)
{
// Empty
}
void updateOffset()
{
float regionScaleX = _width / _regionOriginalWidth * _scaleX;
float regionScaleY = _height / _regionOriginalHeight * _scaleY;
float localX = -_width / 2 * _scaleX + _regionOffsetX * regionScaleX;
float localY = -_height / 2 * _scaleY + _regionOffsetY * regionScaleY;
float localX2 = localX + _regionWidth * regionScaleX;
float localY2 = localY + _regionHeight * regionScaleY;
float cos = MathUtil::cosDeg(_rotation);
float sin = MathUtil::sinDeg(_rotation);
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;
_offset[BLX] = localXCos - localYSin;
_offset[BLY] = localYCos + localXSin;
_offset[ULX] = localXCos - localY2Sin;
_offset[ULY] = localY2Cos + localXSin;
_offset[URX] = localX2Cos - localY2Sin;
_offset[URY] = localY2Cos + localX2Sin;
_offset[BRX] = localX2Cos - localYSin;
_offset[BRY] = localYCos + localX2Sin;
}
void setUVs(float u, float v, float u2, float v2, bool rotate)
{
if (rotate)
{
_uvs[URX] = u;
_uvs[URY] = v2;
_uvs[BRX] = u;
_uvs[BRY] = v;
_uvs[BLX] = u2;
_uvs[BLY] = v;
_uvs[ULX] = u2;
_uvs[ULY] = v2;
}
else
{
_uvs[ULX] = u;
_uvs[ULY] = v2;
_uvs[URX] = u;
_uvs[URY] = v;
_uvs[BRX] = u2;
_uvs[BRY] = v;
_uvs[BLX] = u2;
_uvs[BLY] = v2;
}
}
/// Transforms the attachment's four vertices to world coordinates.
/// @param bone The parent bone.
/// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8.
/// @param offset The worldVertices index to begin writing values.
/// @param stride The number of worldVertices entries between the value pairs written.
void computeWorldVertices(Bone& bone, Vector<float> worldVertices, int offset, int stride = 2)
{
assert(worldVertices.size() >= 8);
float[] vertexOffset = _offset;
float bwx = bone.worldX, bwy = bone.worldY;
float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
float offsetX, offsetY;
offsetX = vertexOffset[BRX]; // 0
offsetY = vertexOffset[BRY]; // 1
worldVertices[offset] = offsetX * a + offsetY * b + bwx; // bl
worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy;
offset += stride;
offsetX = vertexOffset[BLX]; // 2
offsetY = vertexOffset[BLY]; // 3
worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ul
worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy;
offset += stride;
offsetX = vertexOffset[ULX]; // 4
offsetY = vertexOffset[ULY]; // 5
worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ur
worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy;
offset += stride;
offsetX = vertexOffset[URX]; // 6
offsetY = vertexOffset[URY]; // 7
worldVertices[offset] = offsetX * a + offsetY * b + bwx; // br
worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy;
}
private:
float _x, _y, _rotation, _scaleX = 1, _scaleY = 1, _width, _height;
float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight;
float[] _offset = new float[8];
float[] _uvs = new float[8];
float r = 1, g = 1, b = 1, a = 1;
}
}
#endif /* Spine_RegionAttachment_h */

View File

@ -37,6 +37,8 @@ namespace Spine
{
class RotateTimeline : public CurveTimeline
{
RTTI_DECL;
public:
static const int ENTRIES = 2;

View File

@ -90,11 +90,11 @@ namespace Spine
/// If there was no old skin, each slot's setup mode attachment is attached from the new skin.
/// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling
/// See Skeleton::setSlotsToSetupPose()
/// Also, often AnimationState::Apply(Skeleton&) is called before the next time the
/// Also, often AnimationState::apply(Skeleton&) is called before the next time the
/// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin.
///
/// @param newSkin May be NULL.
void setSkin(Skin newSkin);
void setSkin(Skin* newSkin);
/// @return May be NULL.
Attachment* getAttachment(std::string slotName, std::string attachmentName);
@ -136,7 +136,6 @@ namespace Spine
Vector<TransformConstraint*>& getTransformConstraints();
Skin* getSkin();
void setSkin(Skin* inValue);
float getR();
void setR(float inValue);
float getG();
@ -167,7 +166,7 @@ namespace Spine
Vector<Updatable*> _updateCache;
Vector<Bone*> _updateCacheReset;
Skin* _skin;
float _r = 1, _g = 1, _b = 1, _a = 1;
float _r, _g, _b, _a;
float _time;
bool _flipX, _flipY;
float _x, _y;
@ -178,11 +177,11 @@ namespace Spine
void sortTransformConstraint(TransformConstraint* constraint);
void sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone* slotBone);
void sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone& slotBone);
void sortPathConstraintAttachment(Attachment* attachment, Bone* slotBone);
void sortPathConstraintAttachment(Attachment* attachment, Bone& slotBone);
void sortBone(Bone bone);
void sortBone(Bone* bone);
static void sortReset(Vector<Bone*>& bones);
};

View File

@ -49,6 +49,8 @@ namespace Spine
/// Stores the setup pose and all of the stateless data for a skeleton.
class SkeletonData
{
friend class Skeleton;
public:
SkeletonData();

View File

@ -35,8 +35,6 @@
#include <spine/HashMap.h>
#include <spine/Vector.h>
struct HashAttachmentKey;
namespace Spine
{
class Attachment;
@ -47,18 +45,37 @@ namespace Spine
/// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide.
class Skin
{
friend class Skeleton;
public:
class AttachmentKey
{
public:
const int _slotIndex;
const std::string _name;
public:
int _slotIndex;
std::string _name;
AttachmentKey(int slotIndex, std::string name);
AttachmentKey(int slotIndex = 0, std::string name = "");
bool operator==(const AttachmentKey &other) const;
};
struct HashAttachmentKey
{
std::size_t operator()(const Spine::Skin::AttachmentKey& val) const
{
std::size_t h1 = val._slotIndex;
std::size_t h2 = 7;
size_t strlen = val._name.length();
for (int i = 0; i < strlen; ++i)
{
h2 = h2 * 31 + val._name.at(i);
}
return h1 ^ (h2 << 1);
}
};
Skin(std::string name);
/// Adds an attachment to the skin for the specified slot index and name.
@ -90,21 +107,4 @@ namespace Spine
};
}
struct HashAttachmentKey
{
std::size_t operator()(const Spine::Skin::AttachmentKey& val) const
{
std::size_t h1 = static_cast<int(val._slotIndex);
std::size_t h2 = 7;
size_t strlen = val._name.length();
for (int i = 0; i < strlen; ++i)
{
h2 = h2 * 31 + val._name.at(i);
}
return h1 ^ (h2 << 1);
}
};
#endif /* Spine_Skin_h */

View File

@ -45,13 +45,14 @@ namespace Spine
class Slot
{
friend class VertexAttachment;
friend class Skeleton;
public:
Slot(SlotData& data, Bone& bone);
void setToSetupPose();
SlotData& getSlotData();
SlotData& getData();
Bone& getBone();
Skeleton& getSkeleton();
@ -84,7 +85,7 @@ namespace Spine
void setAttachmentVertices(Vector<float> inValue);
private:
SlotData& _slotData;
SlotData& _data;
Bone& _bone;
Skeleton& _skeleton;
float _r, _g, _b, _a;

View File

@ -42,7 +42,7 @@ namespace Spine
class SlotData
{
public:
SlotData(int index, std::string name, const BoneData& boneData);
SlotData(int index, std::string name, BoneData& boneData);
const int getIndex();

View File

@ -31,6 +31,7 @@
#ifndef Spine_Timeline_h
#define Spine_Timeline_h
#include <spine/RTTI.h>
#include <spine/Vector.h>
#include <spine/MixPose.h>
#include <spine/MixDirection.h>
@ -42,6 +43,8 @@ namespace Spine
class Timeline
{
RTTI_DECL;
public:
Timeline();

View File

@ -43,6 +43,10 @@ namespace Spine
class TransformConstraint : public Constraint
{
friend class Skeleton;
RTTI_DECL;
public:
TransformConstraint(TransformConstraintData& data, Skeleton& skeleton);

View File

@ -42,6 +42,7 @@ namespace Spine
class TransformConstraintData
{
friend class TransformConstraint;
friend class Skeleton;
public:
TransformConstraintData(std::string name);

View File

@ -31,10 +31,14 @@
#ifndef Spine_Updatable_h
#define Spine_Updatable_h
#include <spine/RTTI.h>
namespace Spine
{
class Updatable
{
RTTI_DECL;
public:
Updatable();

View File

@ -65,43 +65,56 @@ namespace Spine
deallocate(_buffer);
}
void push_back(const T& _value)
bool contains(const T& inValue)
{
if (_size == _capacity)
for (size_t i = 0; i < _size; ++i)
{
reserve();
if (_buffer[i] == inValue)
{
return true;
}
}
construct(_buffer + _size++, _value);
return false;
}
void insert(size_t _index, const T& _value)
void push_back(const T& inValue)
{
assert(_index < _size);
if (_size == _capacity)
{
reserve();
}
construct(_buffer + _size++, inValue);
}
void insert(size_t inIndex, const T& inValue)
{
assert(inIndex < _size);
if (_size == _capacity)
{
reserve();
}
for (size_t i = ++_size - 1; i > _index; --i)
for (size_t i = ++_size - 1; i > inIndex; --i)
{
construct(_buffer + i, _buffer[i - 1]);
destroy(_buffer + (i - 1));
}
construct(_buffer + _index, _value);
construct(_buffer + inIndex, inValue);
}
void erase(size_t _index)
void erase(size_t inIndex)
{
assert(_index < _size);
assert(inIndex < _size);
--_size;
if (_index != _size)
if (inIndex != _size)
{
for (size_t i = _index; i < _size; ++i)
for (size_t i = inIndex; i < _size; ++i)
{
_buffer[i] = std::move(_buffer[i + 1]);
}
@ -125,18 +138,21 @@ namespace Spine
return _size;
}
T& operator[](size_t _index)
T& operator[](size_t inIndex)
{
assert(_index < _size);
assert(inIndex < _size);
return _buffer[_index];
return _buffer[inIndex];
}
void reserve(long inCapacity = -1)
void reserve(size_t inCapacity = 0)
{
size_t newCapacity = inCapacity != -1 ? inCapacity : _capacity ? _capacity * 2 : 1;
_buffer = static_cast<T*>(realloc(_buffer, newCapacity * sizeof(T)));
_capacity = newCapacity;
size_t newCapacity = inCapacity > 0 ? inCapacity : _capacity > 0 ? _capacity * 2 : 1;
if (newCapacity > _capacity)
{
_buffer = static_cast<T*>(realloc(_buffer, newCapacity * sizeof(T)));
_capacity = newCapacity;
}
}
T* begin()

View File

@ -40,8 +40,10 @@ namespace Spine
class Slot;
/// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices.
class VertexAttachment : Attachment
class VertexAttachment : public Attachment
{
RTTI_DECL;
public:
VertexAttachment(std::string name);
@ -61,10 +63,10 @@ namespace Spine
/// Gets a unique ID for this attachment.
int getId();
Vector<int> getBones();
Vector<int>& getBones();
void setBones(Vector<int> inValue);
Vector<float> getVertices();
Vector<float>& getVertices();
void setVertices(Vector<float> inValue);
int getWorldVerticesLength();

View File

@ -0,0 +1,166 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
#include <spine/Animation.h>
#include <spine/Timeline.h>
#include <spine/Skeleton.h>
#include <spine/Event.h>
#include <assert.h>
#include <math.h> /* fmod */
namespace Spine
{
Animation::Animation(std::string name, Vector<Timeline*>& timelines, float duration) :
_name(name),
_timelines(timelines),
_duration(duration)
{
assert(_name.length() > 0);
}
void Animation::apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector<Event*>& events, float alpha, MixPose pose, MixDirection direction)
{
if (loop && _duration != 0)
{
time = fmod(time, _duration);
if (lastTime > 0)
{
lastTime = fmod(lastTime, _duration);
}
}
for (int i = 0, n = static_cast<int>(_timelines.size()); i < n; ++i)
{
_timelines[i]->apply(skeleton, lastTime, time, events, alpha, pose, direction);
}
}
std::string Animation::getName()
{
return _name;
}
Vector<Timeline*> Animation::getTimelines()
{
return _timelines;
}
void Animation::setTimelines(Vector<Timeline*> inValue)
{
_timelines = inValue;
}
float Animation::getDuration()
{
return _duration;
}
void Animation::setDuration(float inValue)
{
_duration = inValue;
}
int Animation::binarySearch(Vector<float>& values, float target, int step)
{
int low = 0;
int size = static_cast<int>(values.size());
int high = size / step - 2;
if (high == 0)
{
return step;
}
int current = (int)(static_cast<uint32_t>(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)(static_cast<uint32_t>(low + high) >> 1);
}
}
int Animation::binarySearch(Vector<float>& values, float target)
{
int low = 0;
int size = static_cast<int>(values.size());
int high = size - 2;
if (high == 0)
{
return 1;
}
int current = (int)(static_cast<uint32_t>(high) >> 1);
while (true)
{
if (values[(current + 1)] <= target)
{
low = current + 1;
}
else
{
high = current;
}
if (low == high)
{
return (low + 1);
}
current = (int)(static_cast<uint32_t>(low + high) >> 1);
}
}
int Animation::linearSearch(Vector<float>& values, float target, int step)
{
for (int i = 0, last = static_cast<int>(values.size()) - step; i <= last; i += step)
{
if (values[i] > target)
{
return i;
}
}
return -1;
}
}

View File

@ -621,4 +621,6 @@ namespace Spine
_arotation = 90 - MathUtil::atan2(rd, rb) * RadDeg;
}
}
RTTI_IMPL(Bone, Updatable);
}

View File

@ -41,5 +41,6 @@ namespace Spine
{
// Empty
}
RTTI_IMPL(Constraint, Updatable);
}

View File

@ -133,4 +133,6 @@ namespace Spine
{
return _curves[frameIndex * BEZIER_SIZE];
}
RTTI_IMPL(CurveTimeline, Timeline);
}

View File

@ -39,7 +39,7 @@ namespace Spine
_data(data),
_intValue(0),
_floatValue(0),
_stringValue(0)
_stringValue()
{
// Empty
}

View File

@ -357,4 +357,6 @@ namespace Spine
{
_mix = inValue;
}
RTTI_IMPL(IkConstraint, Constraint);
}

View File

@ -0,0 +1,36 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
#include <spine/MeshAttachment.h>
namespace Spine
{
RTTI_IMPL(MeshAttachment, VertexAttachment);
}

View File

@ -28,7 +28,44 @@
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include <spine/PathAttachment.h>
namespace Spine
{
// TODO
PathAttachment::PathAttachment(std::string name) : VertexAttachment(name)
{
// Empty
}
Vector<float>& PathAttachment::getLengths()
{
return _lengths;
}
void PathAttachment::setLengths(Vector<float> inValue)
{
_lengths = inValue;
}
bool PathAttachment::isClosed()
{
return _closed;
}
void PathAttachment::setClosed(bool inValue)
{
_closed = inValue;
}
bool PathAttachment::isConstantSpeed()
{
return _constantSpeed;
}
void PathAttachment::setConstantSpeed(bool inValue)
{
_constantSpeed = inValue;
}
RTTI_IMPL(PathAttachment, VertexAttachment);
}

View File

@ -94,42 +94,45 @@ namespace Spine
}
PathConstraintData data = _data;
SpacingMode spacingMode = data.spacingMode;
bool lengthSpacing = spacingMode == SpacingMode.Length;
RotateMode rotateMode = data.rotateMode;
SpacingMode spacingMode = data._spacingMode;
bool lengthSpacing = spacingMode == SpacingMode_Length;
RotateMode rotateMode = data._rotateMode;
bool tangents = rotateMode == RotateMode_Tangent, scale = rotateMode == RotateMode_ChainScale;
int boneCount = _bones.Count, spacesCount = tangents ? boneCount : boneCount + 1;
Bone[] bonesItems = _bones.Items;
Vector<float> spaces = _spaces.Resize(spacesCount), lengths = NULL;
size_t boneCount = _bones.size();
int spacesCount = static_cast<int>(tangents ? boneCount : boneCount + 1);
_spaces.reserve(spacesCount);
float spacing = _spacing;
if (scale || lengthSpacing)
{
if (scale)
{
lengths = _lengths.Resize(boneCount);
_lengths.reserve(boneCount);
}
for (int i = 0, n = spacesCount - 1; i < n;)
{
Bone bone = bonesItems[i];
float setupLength = bone.data.length;
if (setupLength < PathConstraint.EPSILON)
Bone* boneP = _bones[i];
Bone bone = *boneP;
float setupLength = bone._data.getLength();
if (setupLength < PathConstraint::EPSILON)
{
if (scale)
{
lengths.Items[i] = 0;
_lengths[i] = 0;
}
spaces.Items[++i] = 0;
_spaces[++i] = 0;
}
else
{
float x = setupLength * bone.a, y = setupLength * bone.c;
float length = (float)Math.Sqrt(x * x + y * y);
float x = setupLength * bone._a;
float y = setupLength * bone._c;
float length = (float)sqrt(x * x + y * y);
if (scale)
{
lengths.Items[i] = length;
_lengths[i] = length;
}
spaces.Items[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;
_spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;
}
}
}
@ -137,12 +140,14 @@ namespace Spine
{
for (int i = 1; i < spacesCount; ++i)
{
spaces.Items[i] = spacing;
_spaces[i] = spacing;
}
}
float[] positions = computeWorldPositions(attachment, spacesCount, tangents, data.positionMode == PositionMode_Percent, spacingMode == SpacingMode_Percent);
float boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation;
Vector<float> positions = computeWorldPositions(*attachment, spacesCount, tangents, data.getPositionMode() == PositionMode_Percent, spacingMode == SpacingMode_Percent);
float boneX = positions[0];
float boneY = positions[1];
float offsetRotation = data.getOffsetRotation();
bool tip;
if (offsetRotation == 0)
{
@ -151,24 +156,28 @@ namespace Spine
else
{
tip = false;
Bone p = target.bone;
offsetRotation *= p.a * p.d - p.b * p.c > 0 ? DegRad : -DegRad;
Bone p = _target->getBone();
offsetRotation *= p.getA() * p.getD() - p.getB() * p.getC() > 0 ? DegRad : -DegRad;
}
for (int i = 0, p = 3; i < boneCount; i++, p += 3)
{
Bone bone = bonesItems[i];
bone.worldX += (boneX - bone.worldX) * translateMix;
bone.worldY += (boneY - bone.worldY) * translateMix;
float x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY;
Bone* boneP = _bones[i];
Bone bone = *boneP;
bone._worldX += (boneX - bone._worldX) * translateMix;
bone._worldY += (boneY - bone._worldY) * translateMix;
float x = positions[p];
float y = positions[p + 1];
float dx = x - boneX;
float dy = y - boneY;
if (scale)
{
float length = lengths.Items[i];
if (length >= PathConstraint.EPSILON)
float length = _lengths[i];
if (length >= PathConstraint::EPSILON)
{
float s = ((float)Math.Sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1;
bone.a *= s;
bone.c *= s;
float s = ((float)sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1;
bone._a *= s;
bone._c *= s;
}
}
@ -177,12 +186,12 @@ namespace Spine
if (rotate)
{
float a = bone.a, b = bone.b, c = bone.c, d = bone.d, r, cos, sin;
float a = bone._a, b = bone._b, c = bone._c, d = bone._d, r, cos, sin;
if (tangents)
{
r = positions[p - 1];
}
else if (spaces.Items[i + 1] < PathConstraint.EPSILON)
else if (_spaces[i + 1] < PathConstraint::EPSILON)
{
r = positions[p + 2];
}
@ -197,7 +206,7 @@ namespace Spine
{
cos = MathUtil::cos(r);
sin = MathUtil::sin(r);
float length = bone.data.length;
float length = bone._data.getLength();
boneX += (length * (cos * a - sin * c) - dx) * rotateMix;
boneY += (length * (sin * a + cos * c) - dy) * rotateMix;
}
@ -218,12 +227,13 @@ namespace Spine
r *= rotateMix;
cos = MathUtil::cos(r);
sin = MathUtil::sin(r);
bone.a = cos * a - sin * c;
bone.b = cos * b - sin * d;
bone.c = sin * a + cos * c;
bone.d = sin * b + cos * d;
bone._a = cos * a - sin * c;
bone._b = cos * b - sin * d;
bone._c = sin * a + cos * c;
bone._d = sin * b + cos * d;
}
bone.appliedValid = false;
bone._appliedValid = false;
}
}
@ -296,14 +306,18 @@ namespace Spine
{
Slot target = *_target;
float position = _position;
float[] spacesItems = _spaces.Items, output = _positions.Resize(spacesCount * 3 + 2).Items, world;
bool closed = path.Closed;
int verticesLength = path.WorldVerticesLength, curveCount = verticesLength / 6, prevCurve = NONE;
// float[] spacesItems = _spaces.Items;
// float[] output = _positions.Resize(spacesCount * 3 + 2).Items;
_positions.reserve(spacesCount * 3 + 2);
bool closed = path.isClosed();
int verticesLength = path.getWorldVerticesLength();
int curveCount = verticesLength / 6;
int prevCurve = NONE;
float pathLength;
if (!path.ConstantSpeed)
if (!path.isConstantSpeed())
{
float[] lengths = path.Lengths;
Vector<float>& lengths = path.getLengths();
curveCount -= closed ? 1 : 2;
pathLength = lengths[curveCount];
if (percentPosition)
@ -315,20 +329,21 @@ namespace Spine
{
for (int i = 0; i < spacesCount; ++i)
{
spacesItems[i] *= pathLength;
_spaces[i] *= pathLength;
}
}
world = _world.Resize(8).Items;
_world.reserve(8);
for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3)
{
float space = spacesItems[i];
float space = _spaces[i];
position += space;
float p = position;
if (closed)
{
p %= pathLength;
p = fmod(p, pathLength);
if (p < 0)
{
p += pathLength;
@ -340,10 +355,10 @@ namespace Spine
if (prevCurve != BEFORE)
{
prevCurve = BEFORE;
path.ComputeWorldVertices(target, 2, 4, world, 0);
path.computeWorldVertices(target, 2, 4, _world, 0);
}
addBeforePosition(p, world, 0, output, o);
addBeforePosition(p, _world, 0, _positions, o);
continue;
}
@ -352,10 +367,10 @@ namespace Spine
if (prevCurve != AFTER)
{
prevCurve = AFTER;
path.ComputeWorldVertices(target, verticesLength - 6, 4, world, 0);
path.computeWorldVertices(target, verticesLength - 6, 4, _world, 0);
}
addAfterPosition(p - pathLength, world, 0, output, o);
addAfterPosition(p - pathLength, _world, 0, _positions, o);
continue;
}
@ -386,51 +401,51 @@ namespace Spine
prevCurve = curve;
if (closed && curve == curveCount)
{
path.ComputeWorldVertices(target, verticesLength - 4, 4, world, 0);
path.ComputeWorldVertices(target, 0, 4, world, 4);
path.computeWorldVertices(target, verticesLength - 4, 4, _world, 0);
path.computeWorldVertices(target, 0, 4, _world, 4);
}
else
{
path.ComputeWorldVertices(target, curve * 6 + 2, 8, world, 0);
path.computeWorldVertices(target, curve * 6 + 2, 8, _world, 0);
}
}
addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], output, o, tangents || (i > 0 && space < EPSILON));
addCurvePosition(p, _world[0], _world[1], _world[2], _world[3], _world[4], _world[5], _world[6], _world[7], _positions, o, tangents || (i > 0 && space < EPSILON));
}
return output;
return _world;
}
// World vertices.
if (closed)
{
verticesLength += 2;
world = _world.Resize(verticesLength).Items;
path.ComputeWorldVertices(target, 2, verticesLength - 4, world, 0);
path.ComputeWorldVertices(target, 0, 2, world, verticesLength - 4);
world[verticesLength - 2] = world[0];
world[verticesLength - 1] = world[1];
_world.reserve(verticesLength);
path.computeWorldVertices(target, 2, verticesLength - 4, _world, 0);
path.computeWorldVertices(target, 0, 2, _world, verticesLength - 4);
_world[verticesLength - 2] = _world[0];
_world[verticesLength - 1] = _world[1];
}
else
{
curveCount--;
verticesLength -= 4;
world = _world.Resize(verticesLength).Items;
path.ComputeWorldVertices(target, 2, verticesLength, world, 0);
_world.reserve(verticesLength);
path.computeWorldVertices(target, 2, verticesLength, _world, 0);
}
// Curve lengths.
float[] curves = _curves.Resize(curveCount).Items;
_curves.reserve(curveCount);
pathLength = 0;
float x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0;
float x1 = _world[0], y1 = _world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0;
float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy;
for (int i = 0, w = 2; i < curveCount; i++, w += 6)
{
cx1 = world[w];
cy1 = world[w + 1];
cx2 = world[w + 2];
cy2 = world[w + 3];
x2 = world[w + 4];
y2 = world[w + 5];
cx1 = _world[w];
cy1 = _world[w + 1];
cx2 = _world[w + 2];
cy2 = _world[w + 3];
x2 = _world[w + 4];
y2 = _world[w + 5];
tmpx = (x1 - cx1 * 2 + cx2) * 0.1875f;
tmpy = (y1 - cy1 * 2 + cy2) * 0.1875f;
dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375f;
@ -439,19 +454,19 @@ namespace Spine
ddfy = tmpy * 2 + dddfy;
dfx = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f;
dfy = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f;
pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
pathLength += (float)sqrt(dfx * dfx + dfy * dfy);
dfx += ddfx;
dfy += ddfy;
ddfx += dddfx;
ddfy += dddfy;
pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
pathLength += (float)sqrt(dfx * dfx + dfy * dfy);
dfx += ddfx;
dfy += ddfy;
pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
pathLength += (float)sqrt(dfx * dfx + dfy * dfy);
dfx += ddfx + dddfx;
dfy += ddfy + dddfy;
pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
curves[i] = pathLength;
pathLength += (float)sqrt(dfx * dfx + dfy * dfy);
_curves[i] = pathLength;
x1 = x2;
y1 = y2;
}
@ -465,21 +480,21 @@ namespace Spine
{
for (int i = 0; i < spacesCount; ++i)
{
spacesItems[i] *= pathLength;
_spaces[i] *= pathLength;
}
}
float[] segments = _segments;
float curveLength = 0;
for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3)
{
float space = spacesItems[i];
float space = _spaces[i];
position += space;
float p = position;
if (closed)
{
p %= pathLength;
p = fmod(p, pathLength);
if (p < 0)
{
p += pathLength;
@ -488,19 +503,19 @@ namespace Spine
}
else if (p < 0)
{
addBeforePosition(p, world, 0, output, o);
addBeforePosition(p, _world, 0, _positions, o);
continue;
}
else if (p > pathLength)
{
addAfterPosition(p - pathLength, world, verticesLength - 4, output, o);
addAfterPosition(p - pathLength, _world, verticesLength - 4, _positions, o);
continue;
}
// Determine curve containing position.
for (;; curve++)
{
float length = curves[curve];
float length = _curves[curve];
if (p > length)
{
continue;
@ -512,7 +527,7 @@ namespace Spine
}
else
{
float prev = curves[curve - 1];
float prev = _curves[curve - 1];
p = (p - prev) / (length - prev);
}
break;
@ -523,14 +538,14 @@ namespace Spine
{
prevCurve = curve;
int ii = curve * 6;
x1 = world[ii];
y1 = world[ii + 1];
cx1 = world[ii + 2];
cy1 = world[ii + 3];
cx2 = world[ii + 4];
cy2 = world[ii + 5];
x2 = world[ii + 6];
y2 = world[ii + 7];
x1 = _world[ii];
y1 = _world[ii + 1];
cx1 = _world[ii + 2];
cy1 = _world[ii + 3];
cx2 = _world[ii + 4];
cy2 = _world[ii + 5];
x2 = _world[ii + 6];
y2 = _world[ii + 7];
tmpx = (x1 - cx1 * 2 + cx2) * 0.03f;
tmpy = (y1 - cy1 * 2 + cy2) * 0.03f;
dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006f;
@ -539,25 +554,25 @@ namespace Spine
ddfy = tmpy * 2 + dddfy;
dfx = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f;
dfy = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f;
curveLength = (float)Math.Sqrt(dfx * dfx + dfy * dfy);
segments[0] = curveLength;
curveLength = (float)sqrt(dfx * dfx + dfy * dfy);
_segments[0] = curveLength;
for (ii = 1; ii < 8; ii++)
{
dfx += ddfx;
dfy += ddfy;
ddfx += dddfx;
ddfy += dddfy;
curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
segments[ii] = curveLength;
curveLength += (float)sqrt(dfx * dfx + dfy * dfy);
_segments[ii] = curveLength;
}
dfx += ddfx;
dfy += ddfy;
curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
segments[8] = curveLength;
curveLength += (float)sqrt(dfx * dfx + dfy * dfy);
_segments[8] = curveLength;
dfx += ddfx + dddfx;
dfy += ddfy + dddfy;
curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
segments[9] = curveLength;
curveLength += (float)sqrt(dfx * dfx + dfy * dfy);
_segments[9] = curveLength;
segment = 0;
}
@ -565,7 +580,7 @@ namespace Spine
p *= curveLength;
for (;; segment++)
{
float length = segments[segment];
float length = _segments[segment];
if (p > length)
{
continue;
@ -577,15 +592,15 @@ namespace Spine
}
else
{
float prev = segments[segment - 1];
float prev = _segments[segment - 1];
p = segment + (p - prev) / (length - prev);
}
break;
}
addCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, output, o, tangents || (i > 0 && space < EPSILON));
addCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, _positions, o, tangents || (i > 0 && space < EPSILON));
}
return output;
return _positions;
}
void PathConstraint::addBeforePosition(float p, Vector<float>& temp, int i, Vector<float>& output, int o)
@ -615,7 +630,7 @@ namespace Spine
void PathConstraint::addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, Vector<float>& output, int o, bool tangents)
{
if (p < EPSILON || float.IsNaN(p))
if (p < EPSILON || isnan(p))
{
p = EPSILON;
}
@ -627,7 +642,9 @@ namespace Spine
output[o + 1] = y;
if (tangents)
{
output[o + 2] = (float)Math.Atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt));
output[o + 2] = (float)atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt));
}
}
RTTI_IMPL(PathConstraint, Constraint);
}

View File

@ -0,0 +1,36 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
#include <spine/RegionAttachment.h>
namespace Spine
{
RTTI_IMPL(RegionAttachment, Attachment);
}

View File

@ -147,4 +147,6 @@ namespace Spine
{
_frames = inValue;
}
RTTI_IMPL(RotateTimeline, CurveTimeline);
}

View File

@ -45,6 +45,9 @@
#include <spine/IkConstraintData.h>
#include <spine/TransformConstraintData.h>
#include <spine/PathConstraintData.h>
#include <spine/RegionAttachment.h>
#include <spine/MeshAttachment.h>
#include <spine/PathAttachment.h>
#include <spine/ContainerUtil.h>
@ -135,81 +138,101 @@ namespace Spine
void Skeleton::updateCache()
{
Vector<Updatable> updateCache = _updateCache;
updateCache.Clear();
_updateCacheReset.Clear();
_updateCache.clear();
_updateCacheReset.clear();
Vector<Bone> bones = _bones;
for (int i = 0, n = bones.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_bones.size()); i < n; ++i)
{
bones.Items[i].sorted = false;
_bones[i]->_sorted = false;
}
Vector<IkConstraint> ikConstraints = _ikConstraints;
var transformConstraints = _transformConstraints;
var pathConstraints = _pathConstraints;
int ikCount = IkConstraints.Count, transformCount = transformConstraints.Count, pathCount = pathConstraints.Count;
int ikCount = static_cast<int>(_ikConstraints.size());
int transformCount = static_cast<int>(_transformConstraints.size());
int pathCount = static_cast<int>(_pathConstraints.size());
int constraintCount = ikCount + transformCount + pathCount;
//outer:
for (int i = 0; i < constraintCount; ++i)
{
bool gotoNextConstraintCount = false;
for (int ii = 0; ii < ikCount; ++ii)
{
IkConstraint constraint = ikConstraints.Items[ii];
if (constraint.data.order == i)
IkConstraint* constraint = _ikConstraints[ii];
if (constraint->getData().getOrder() == i)
{
sortIkConstraint(constraint);
goto continue_outer; //continue outer;
gotoNextConstraintCount = true;
break;
}
}
if (gotoNextConstraintCount)
{
break;
}
for (int ii = 0; ii < transformCount; ++ii)
{
TransformConstraint constraint = transformConstraints.Items[ii];
if (constraint.data.order == i)
TransformConstraint* constraint = _transformConstraints[ii];
if (constraint->getData().getOrder() == i)
{
sortTransformConstraint(constraint);
goto continue_outer; //continue outer;
gotoNextConstraintCount = true;
break;
}
}
if (gotoNextConstraintCount)
{
break;
}
for (int ii = 0; ii < pathCount; ++ii)
{
PathConstraint constraint = pathConstraints.Items[ii];
if (constraint.data.order == i)
PathConstraint* constraint = _pathConstraints[ii];
if (constraint->getData().getOrder() == i)
{
sortPathConstraint(constraint);
goto continue_outer; //continue outer;
gotoNextConstraintCount = true;
break;
}
}
continue_outer: {}
if (gotoNextConstraintCount)
{
break;
}
}
for (int i = 0, n = bones.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_bones.size()); i < n; ++i)
{
sortBone(bones.Items[i]);
sortBone(_bones[i]);
}
}
void Skeleton::updateWorldTransform()
{
var updateCacheReset = _updateCacheReset;
var updateCacheResetItems = updateCacheReset.Items;
for (int i = 0, n = updateCacheReset.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_updateCacheReset.size()); i < n; ++i)
{
Bone bone = updateCacheResetItems[i];
bone.ax = bone.x;
bone.ay = bone.y;
bone.arotation = bone.rotation;
bone.ascaleX = bone.scaleX;
bone.ascaleY = bone.scaleY;
bone.ashearX = bone.shearX;
bone.ashearY = bone.shearY;
bone.appliedValid = true;
Bone* boneP = _updateCacheReset[i];
Bone bone = *boneP;
bone._ax = bone._x;
bone._ay = bone._y;
bone._arotation = bone._rotation;
bone._ascaleX = bone._scaleX;
bone._ascaleY = bone._scaleY;
bone._ashearX = bone._shearX;
bone._ashearY = bone._shearY;
bone._appliedValid = true;
}
var updateItems = _updateCache.Items;
for (int i = 0, n = updateCache.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_updateCache.size()); i < n; ++i)
{
updateItems[i].update();
_updateCache[i]->update();
}
}
@ -221,213 +244,164 @@ namespace Spine
void Skeleton::setBonesToSetupPose()
{
var bonesItems = _bones.Items;
for (int i = 0, n = bones.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_bones.size()); i < n; ++i)
{
bonesItems[i].setToSetupPose();
_bones[i]->setToSetupPose();
}
var ikConstraintsItems = _ikConstraints.Items;
for (int i = 0, n = ikConstraints.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_ikConstraints.size()); i < n; ++i)
{
IkConstraint constraint = ikConstraintsItems[i];
constraint.bendDirection = constraint.data.bendDirection;
constraint.mix = constraint.data.mix;
IkConstraint* constraintP = _ikConstraints[i];
IkConstraint constraint = *constraintP;
constraint._bendDirection = constraint._data._bendDirection;
constraint._mix = constraint._data._mix;
}
var transformConstraintsItems = _transformConstraints.Items;
for (int i = 0, n = transformConstraints.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_transformConstraints.size()); i < n; ++i)
{
TransformConstraint constraint = transformConstraintsItems[i];
TransformConstraintData constraintData = constraint.data;
constraint.rotateMix = constraintData.rotateMix;
constraint.translateMix = constraintData.translateMix;
constraint.scaleMix = constraintData.scaleMix;
constraint.shearMix = constraintData.shearMix;
TransformConstraint* constraintP = _transformConstraints[i];
TransformConstraint constraint = *constraintP;
TransformConstraintData& constraintData = constraint._data;
constraint._rotateMix = constraintData._rotateMix;
constraint._translateMix = constraintData._translateMix;
constraint._scaleMix = constraintData._scaleMix;
constraint._shearMix = constraintData._shearMix;
}
var pathConstraintItems = _pathConstraints.Items;
for (int i = 0, n = pathConstraints.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_pathConstraints.size()); i < n; ++i)
{
PathConstraint constraint = pathConstraintItems[i];
PathConstraintData constraintData = constraint.data;
constraint.position = constraintData.position;
constraint.spacing = constraintData.spacing;
constraint.rotateMix = constraintData.rotateMix;
constraint.translateMix = constraintData.translateMix;
PathConstraint* constraintP = _pathConstraints[i];
PathConstraint constraint = *constraintP;
PathConstraintData& constraintData = constraint._data;
constraint._position = constraintData._position;
constraint._spacing = constraintData._spacing;
constraint._rotateMix = constraintData._rotateMix;
constraint._translateMix = constraintData._translateMix;
}
}
void Skeleton::setSlotsToSetupPose()
{
var slots = _slots;
var slotsItems = slots.Items;
drawOrder.Clear();
for (int i = 0, n = slots.Count; i < n; ++i)
_drawOrder.clear();
for (int i = 0, n = static_cast<int>(_slots.size()); i < n; ++i)
{
drawOrder.Add(slotsItems[i]);
_drawOrder.push_back(_slots[i]);
}
for (int i = 0, n = slots.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_slots.size()); i < n; ++i)
{
slotsItems[i].setToSetupPose();
_slots[i]->setToSetupPose();
}
}
Bone* Skeleton::findBone(std::string boneName)
{
assert(boneName.length() > 0);
var bones = _bones;
var bonesItems = bones.Items;
for (int i = 0, n = bones.Count; i < n; ++i)
{
Bone bone = bonesItems[i];
if (bone.data.name == boneName)
{
return bone;
}
}
return NULL;
return ContainerUtil::findWithDataName(_bones, boneName);
}
int Skeleton::findBoneIndex(std::string boneName)
{
assert(boneName.length() > 0);
var bones = _bones;
var bonesItems = bones.Items;
for (int i = 0, n = bones.Count; i < n; ++i)
{
if (bonesItems[i].data.name == boneName)
{
return i;
}
}
return -1;
return ContainerUtil::findIndexWithDataName(_bones, boneName);
}
Slot* Skeleton::findSlot(std::string slotName)
{
assert(slotName.length() > 0);
var slots = _slots;
var slotsItems = slots.Items;
for (int i = 0, n = slots.Count; i < n; ++i)
{
Slot slot = slotsItems[i];
if (slot.data.name == slotName)
{
return slot;
}
}
return NULL;
return ContainerUtil::findWithDataName(_slots, slotName);
}
int Skeleton::findSlotIndex(std::string slotName)
{
assert(slotName.length() > 0);
var slots = _slots;
var slotsItems = slots.Items;
for (int i = 0, n = slots.Count; i < n; ++i)
{
if (slotsItems[i].data.name.Equals(slotName))
{
return i;
}
}
return -1;
return ContainerUtil::findIndexWithDataName(_slots, slotName);
}
void Skeleton::setSkin(std::string skinName)
{
Skin foundSkin = data.FindSkin(skinName);
Skin* foundSkin = _data.findSkin(skinName);
assert(foundSkin != NULL);
setSkin(foundSkin);
}
void Skeleton::setSkin(Skin newSkin)
void Skeleton::setSkin(Skin* newSkin)
{
if (newSkin != NULL)
{
if (skin != NULL)
if (_skin != NULL)
{
newSkin.AttachAll(this, skin);
Skeleton& thisRef = *this;
newSkin->attachAll(thisRef, *_skin);
}
else
{
Vector<Slot> slots = _slots;
for (int i = 0, n = slots.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_slots.size()); i < n; ++i)
{
Slot slot = slots.Items[i];
std::string name = slot.data.attachmentName;
if (name != NULL)
Slot* slotP = _slots[i];
Slot slot = *slotP;
std::string name = slot._data.getAttachmentName();
if (name.length() > 0)
{
Attachment attachment = newSkin.getAttachment(i, name);
Attachment* attachment = newSkin->getAttachment(i, name);
if (attachment != NULL)
{
slot.Attachment = attachment;
slot.setAttachment(attachment);
}
}
}
}
}
skin = newSkin;
_skin = newSkin;
}
Attachment* Skeleton::getAttachment(std::string slotName, std::string attachmentName)
{
return getAttachment(data.findSlotIndex(slotName), attachmentName);
return getAttachment(_data.findSlotIndex(slotName), attachmentName);
}
Attachment* Skeleton::getAttachment(int slotIndex, std::string attachmentName)
{
assert(attachmentName.length() > 0);
if (skin != NULL)
if (_skin != NULL)
{
Attachment attachment = skin.getAttachment(slotIndex, attachmentName);
Attachment* attachment = _skin->getAttachment(slotIndex, attachmentName);
if (attachment != NULL)
{
return attachment;
}
}
return data.defaultSkin != NULL ? data.defaultSkin.getAttachment(slotIndex, attachmentName) : NULL;
return _data.getDefaultSkin() != NULL ? _data.getDefaultSkin()->getAttachment(slotIndex, attachmentName) : NULL;
}
void Skeleton::setAttachment(std::string slotName, std::string attachmentName)
{
assert(slotName.length() > 0);
Vector<Slot> slots = _slots;
for (int i = 0, n = slots.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_slots.size()); i < n; ++i)
{
Slot slot = slots.Items[i];
if (slot.data.name == slotName)
Slot* slot = _slots[i];
if (slot->_data.getName() == slotName)
{
Attachment attachment = NULL;
if (attachmentName != NULL)
Attachment* attachment = NULL;
if (attachmentName.length() > 0)
{
attachment = getAttachment(i, attachmentName);
assert(attachment != NULL);
}
slot.Attachment = attachment;
slot->setAttachment(attachment);
return;
}
}
printf("Slot not found: %s" + slotName.c_str());
printf("Slot not found: %s", slotName.c_str());
assert(false);
}
@ -436,11 +410,10 @@ namespace Spine
{
assert(constraintName.length() > 0);
Vector<IkConstraint> ikConstraints = _ikConstraints;
for (int i = 0, n = ikConstraints.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_ikConstraints.size()); i < n; ++i)
{
IkConstraint ikConstraint = ikConstraints.Items[i];
if (ikConstraint.data.name == constraintName)
IkConstraint* ikConstraint = _ikConstraints[i];
if (ikConstraint->_data.getName() == constraintName)
{
return ikConstraint;
}
@ -452,11 +425,10 @@ namespace Spine
{
assert(constraintName.length() > 0);
Vector<TransformConstraint> transformConstraints = _transformConstraints;
for (int i = 0, n = transformConstraints.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_transformConstraints.size()); i < n; ++i)
{
TransformConstraint transformConstraint = transformConstraints.Items[i];
if (transformConstraint.data.name == constraintName)
TransformConstraint* transformConstraint = _transformConstraints[i];
if (transformConstraint->_data.getName() == constraintName)
{
return transformConstraint;
}
@ -469,11 +441,10 @@ namespace Spine
{
assert(constraintName.length() > 0);
Vector<PathConstraint> pathConstraints = _pathConstraints;
for (int i = 0, n = pathConstraints.Count; i < n; ++i)
for (int i = 0, n = static_cast<int>(_pathConstraints.size()); i < n; ++i)
{
PathConstraint constraint = pathConstraints.Items[i];
if (constraint.data.name.Equals(constraintName))
PathConstraint* constraint = _pathConstraints[i];
if (constraint->_data.getName() == constraintName)
{
return constraint;
}
@ -494,40 +465,40 @@ namespace Spine
float maxX = std::numeric_limits<float>::min();
float maxY = std::numeric_limits<float>::min();
for (Slot* i = _drawOrder.begin(); i != _drawOrder.end(); ++i)
for (Slot** i = _drawOrder.begin(); i != _drawOrder.end(); ++i)
{
Slot* slot = i;
Slot* slot = (*i);
int verticesLength = 0;
Attachment* attachment = slot->getAttachment();
if (attachment != NULL && attachment->getRTTI().derivesFrom(RegionAttachment::rtti))
{
RegionAttachment* regionAttachment = static_cast<RegionAttachment*>(attachment);
verticesLength = 8;
if (vertexBuffer.size() < 8)
if (outVertexBuffer.size() < 8)
{
vertexBuffer.reserve(8);
outVertexBuffer.reserve(8);
}
regionAttachment->computeWorldVertices(slot->getBone(), vertexBuffer, 0);
regionAttachment->computeWorldVertices(slot->getBone(), outVertexBuffer, 0);
}
else if (attachment != NULL && attachment->getRTTI().derivesFrom(MeshAttachment::rtti))
{
MeshAttachment* mesh = static_cast<MeshAttachment*>(attachment);
verticesLength = mesh->getWorldVerticesLength();
if (vertexBuffer.size() < verticesLength)
if (outVertexBuffer.size() < verticesLength)
{
vertexBuffer.reserve(verticesLength);
outVertexBuffer.reserve(verticesLength);
}
mesh->computeWorldVertices(slot, 0, verticesLength, vertexBuffer, 0);
mesh->computeWorldVertices(slot, 0, verticesLength, outVertexBuffer, 0);
}
for (int ii = 0; ii < verticesLength; ii += 2)
{
float vx = vertexBuffer[ii];
float vy = vertexBuffer[ii + 1];
float vx = outVertexBuffer[ii];
float vy = outVertexBuffer[ii + 1];
minX = MIN(minX, vx);
minY = MIN(minY, vy);
@ -536,15 +507,15 @@ namespace Spine
}
}
x = minX;
y = minY;
width = maxX - minX;
height = maxY - minY;
outX = minX;
outY = minY;
outWidth = maxX - minX;
outHeight = maxY - minY;
}
Bone* Skeleton::getRootBone()
{
return _bones.size() == 0 ? NULL : &_bones[0];
return _bones.size() == 0 ? NULL : _bones[0];
}
const SkeletonData& Skeleton::getData()
@ -592,11 +563,6 @@ namespace Spine
return _skin;
}
void Skeleton::setSkin(Skin* inValue)
{
_skin = inValue;
}
float Skeleton::getR()
{
return _r;
@ -689,90 +655,90 @@ namespace Spine
void Skeleton::sortIkConstraint(IkConstraint* constraint)
{
Bone target = constraint.target;
Bone* target = constraint->getTarget();
sortBone(target);
var constrained = constraint.bones;
Bone parent = constrained.Items[0];
Vector<Bone*>& constrained = constraint->getBones();
Bone* parent = constrained[0];
sortBone(parent);
if (constrained.Count > 1)
if (constrained.size() > 1)
{
Bone child = constrained.Items[constrained.Count - 1];
if (!updateCache.Contains(child))
Bone* child = constrained[constrained.size() - 1];
if (!_updateCache.contains(child))
{
updateCacheReset.Add(child);
_updateCacheReset.push_back(child);
}
}
updateCache.Add(constraint);
_updateCache.push_back(constraint);
sortReset(parent.children);
constrained.Items[constrained.Count - 1].sorted = true;
sortReset(parent->getChildren());
constrained[constrained.size() - 1]->_sorted = true;
}
void Skeleton::sortPathConstraint(PathConstraint* constraint)
{
Slot slot = constraint.target;
int slotIndex = slot.data.index;
Bone slotBone = slot.bone;
Slot* slot = constraint->getTarget();
int slotIndex = slot->_data.getIndex();
Bone& slotBone = slot->_bone;
if (skin != NULL)
if (_skin != NULL)
{
sortPathConstraintAttachment(skin, slotIndex, slotBone);
sortPathConstraintAttachment(_skin, slotIndex, slotBone);
}
if (data.defaultSkin != NULL && data.defaultSkin != skin)
if (_data._defaultSkin != NULL && _data._defaultSkin != _skin)
{
sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
sortPathConstraintAttachment(_data._defaultSkin, slotIndex, slotBone);
}
for (int ii = 0, nn = data.skins.Count; ii < nn; ++ii)
for (int ii = 0, nn = static_cast<int>(_data._skins.size()); ii < nn; ++ii)
{
sortPathConstraintAttachment(data.skins.Items[ii], slotIndex, slotBone);
sortPathConstraintAttachment(_data._skins[ii], slotIndex, slotBone);
}
Attachment attachment = slot.attachment;
if (attachment is PathAttachment)
Attachment* attachment = slot->_attachment;
if (attachment != NULL && attachment->getRTTI().derivesFrom(PathAttachment::rtti))
{
sortPathConstraintAttachment(attachment, slotBone);
}
var constrained = constraint.bones;
int boneCount = constrained.Count;
Vector<Bone*>& constrained = constraint->getBones();
int boneCount = static_cast<int>(constrained.size());
for (int i = 0; i < boneCount; ++i)
{
sortBone(constrained.Items[i]);
sortBone(constrained[i]);
}
updateCache.Add(constraint);
_updateCache.push_back(constraint);
for (int i = 0; i < boneCount; ++i)
{
sortReset(constrained.Items[i].children);
sortReset(constrained[i]->getChildren());
}
for (int i = 0; i < boneCount; ++i)
{
constrained.Items[i].sorted = true;
constrained[i]->_sorted = true;
}
}
void Skeleton::sortTransformConstraint(TransformConstraint* constraint)
{
sortBone(constraint.target);
sortBone(constraint->getTarget());
var constrained = constraint.bones;
int boneCount = constrained.Count;
if (constraint.data.local)
Vector<Bone*>& constrained = constraint->getBones();
int boneCount = static_cast<int>(constrained.size());
if (constraint->_data.isLocal())
{
for (int i = 0; i < boneCount; ++i)
{
Bone child = constrained.Items[i];
sortBone(child.parent);
if (!updateCache.Contains(child))
Bone* child = constrained[i];
sortBone(child->getParent());
if (!_updateCache.contains(child))
{
updateCacheReset.Add(child);
_updateCacheReset.push_back(child);
}
}
}
@ -780,55 +746,61 @@ namespace Spine
{
for (int i = 0; i < boneCount; ++i)
{
sortBone(constrained.Items[i]);
sortBone(constrained[i]);
}
}
updateCache.Add(constraint);
_updateCache.push_back(constraint);
for (int i = 0; i < boneCount; ++i)
{
sortReset(constrained.Items[i].children);
sortReset(constrained[i]->getChildren());
}
for (int i = 0; i < boneCount; ++i)
{
constrained.Items[i].sorted = true;
constrained[i]->_sorted = true;
}
}
void Skeleton::sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone* slotBone)
void Skeleton::sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone& slotBone)
{
foreach (var entry in skin.Attachments)
HashMap<Skin::AttachmentKey, Attachment*, Skin::HashAttachmentKey>& attachments = skin->getAttachments();
for (typename HashMap<Skin::AttachmentKey, Attachment*, Skin::HashAttachmentKey>::Iterator i = attachments.begin(); i != attachments.end(); ++i)
{
if (entry.Key.slotIndex == slotIndex)
Skin::AttachmentKey key = i.first();
if (key._slotIndex == slotIndex)
{
sortPathConstraintAttachment(entry.Value, slotBone);
Attachment* value = i.second();
sortPathConstraintAttachment(value, slotBone);
}
}
}
void Skeleton::sortPathConstraintAttachment(Attachment* attachment, Bone* slotBone)
void Skeleton::sortPathConstraintAttachment(Attachment* attachment, Bone& slotBone)
{
if (!(attachment is PathAttachment))
if (attachment == NULL || attachment->getRTTI().derivesFrom(PathAttachment::rtti))
{
return;
}
int[] pathBones = ((PathAttachment)attachment).bones;
if (pathBones == NULL)
PathAttachment* pathAttachment = static_cast<PathAttachment*>(attachment);
Vector<int>& pathBonesRef = pathAttachment->getBones();
Vector<int> pathBones = pathBonesRef;
if (pathBones.size() == 0)
{
sortBone(slotBone);
sortBone(&slotBone);
}
else
{
var bones = _bones;
for (int i = 0, n = pathBones.Length; i < n;)
for (int i = 0, n = static_cast<int>(pathBones.size()); i < n;)
{
int nn = pathBones[i++];
nn += i;
while (i < nn)
{
sortBone(bones.Items[pathBones[i++]]);
sortBone(_bones[pathBones[i++]]);
}
}
}
@ -836,32 +808,35 @@ namespace Spine
void Skeleton::sortBone(Bone* bone)
{
if (bone.sorted)
assert(bone != NULL);
if (bone->_sorted)
{
return;
}
Bone parent = bone.parent;
Bone* parent = bone->_parent;
if (parent != NULL)
{
sortBone(parent);
}
bone.sorted = true;
updateCache.Add(bone);
bone->_sorted = true;
_updateCache.push_back(bone);
}
void Skeleton::sortReset(Vector<Bone*>& bones)
{
for (Bone* i = bones.begin(); i != bones.end(); ++i)
for (Bone** i = bones.begin(); i != bones.end(); ++i)
{
Bone* bone = i;
if (bone->isSorted())
Bone* bone = (*i);
if (bone->_sorted)
{
sortReset(bone->getChildren());
}
bone->setSorted(false);
bone->_sorted = false;
}
}
}

View File

@ -46,10 +46,14 @@
namespace Spine
{
SkeletonData::SkeletonData() :
_name(),
_defaultSkin(NULL),
_width(0),
_height(0),
_fps(0)
_version(),
_hash(),
_fps(0),
_imagesPath()
{
// Empty
}

View File

@ -60,7 +60,7 @@ namespace Spine
{
assert(attachment);
_attachments[AttachmentKey(slotIndex, name)] = attachment;
_attachments.insert(AttachmentKey(slotIndex, name), attachment);
}
Attachment* Skin::getAttachment(int slotIndex, std::string name)
@ -104,17 +104,19 @@ namespace Spine
return _name;
}
HashMap<Skin::AttachmentKey, Attachment*, HashAttachmentKey>& Skin::getAttachments()
HashMap<Skin::AttachmentKey, Attachment*, Skin::HashAttachmentKey>& Skin::getAttachments()
{
return _attachments;
}
void Skin::attachAll(Skeleton& skeleton, Skin& oldSkin)
{
Vector<Slot*>& slots = skeleton.getSlots();
for (HashMap<AttachmentKey, Attachment*, HashAttachmentKey>::Iterator i = oldSkin.getAttachments().begin(); i != oldSkin.getAttachments().end(); ++i)
{
int slotIndex = i.first()._slotIndex;
Slot* slot = skeleton.getSlots()[slotIndex];
Slot* slot = slots[slotIndex];
if (slot->getAttachment() == i.second())
{

View File

@ -38,9 +38,9 @@
namespace Spine
{
Slot::Slot(SlotData& data, Bone& bone) :
_slotData(data),
_data(data),
_bone(bone),
_skeleton(bone.getSkeletion()),
_skeleton(bone.getSkeleton()),
_r(1),
_g(1),
_b(1),
@ -57,16 +57,16 @@ namespace Spine
void Slot::setToSetupPose()
{
_r = _slotData.getR();
_g = _slotData.getG();
_b = _slotData.getB();
_a = _slotData.getA();
_r = _data.getR();
_g = _data.getG();
_b = _data.getB();
_a = _data.getA();
std::string attachmentName = _slotData.getAttachmentName();
std::string attachmentName = _data.getAttachmentName();
if (attachmentName.length() > 0)
{
_attachment = NULL;
setAttachment(_skeleton.getAttachment(_slotData.getIndex(), attachmentName));
setAttachment(_skeleton.getAttachment(_data.getIndex(), attachmentName));
}
else
{
@ -74,9 +74,9 @@ namespace Spine
}
}
SlotData& Slot::getSlotData()
SlotData& Slot::getData()
{
return _slotData;
return _data;
}
Bone& Slot::getBone()

View File

@ -34,7 +34,7 @@
namespace Spine
{
SlotData::SlotData(int index, std::string name, const BoneData& boneData) :
SlotData::SlotData(int index, std::string name, BoneData& boneData) :
_index(index),
_name(name),
_boneData(boneData),
@ -63,7 +63,7 @@ namespace Spine
return _name;
}
const BoneData& SlotData::getBoneData()
BoneData& SlotData::getBoneData()
{
return _boneData;
}

View File

@ -44,4 +44,6 @@ namespace Spine
{
// Empty
}
RTTI_IMPL_NOPARENT(Timeline);
}

View File

@ -427,22 +427,24 @@ namespace Spine
{
if (scaleX > 0.00001f)
{
scaleX *= ((target._ascaleX - 1 + data.offsetScaleX) * scaleMix) + 1;
scaleX *= ((target._ascaleX - 1 + _data._offsetScaleX) * scaleMix) + 1;
}
if (scaleY > 0.00001f)
{
scaleY *= ((target._ascaleY - 1 + data.offsetScaleY) * scaleMix) + 1;
scaleY *= ((target._ascaleY - 1 + _data._offsetScaleY) * scaleMix) + 1;
}
}
float shearY = bone._ashearY;
if (shearMix > 0)
{
shearY += (target._ashearY + data.offsetShearY) * shearMix;
shearY += (target._ashearY + _data._offsetShearY) * shearMix;
}
bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY);
}
}
RTTI_IMPL(TransformConstraint, Constraint);
}

View File

@ -41,4 +41,6 @@ namespace Spine
{
// Empty
}
RTTI_IMPL_NOPARENT(Updatable);
}

View File

@ -138,7 +138,7 @@ namespace Spine
return _id;
}
Vector<int> VertexAttachment::getBones()
Vector<int>& VertexAttachment::getBones()
{
return _bones;
}
@ -148,7 +148,7 @@ namespace Spine
_bones = inValue;
}
Vector<float> VertexAttachment::getVertices()
Vector<float>& VertexAttachment::getVertices()
{
return _vertices;
}
@ -174,4 +174,6 @@ namespace Spine
return (nextID++ & 65535) << 11;
}
RTTI_IMPL(VertexAttachment, Attachment);
}