This commit is contained in:
Stephen Gowen 2017-10-17 18:05:43 -04:00
parent af243b4922
commit 072ada4c5c
14 changed files with 1132 additions and 691 deletions

View File

@ -50,6 +50,10 @@ namespace Spine
friend class RotateTimeline; friend class RotateTimeline;
public: public:
static void setYDown(bool inValue);
static bool isYDown();
/// @param parent May be null. /// @param parent May be null.
Bone(BoneData& data, Skeleton& skeleton, Bone* parent); Bone(BoneData& data, Skeleton& skeleton, Bone* parent);
@ -160,6 +164,8 @@ namespace Spine
float getWorldScaleY(); float getWorldScaleY();
private: private:
static bool yDown;
BoneData& _data; BoneData& _data;
Skeleton& _skeleton; Skeleton& _skeleton;
Bone* _parent; Bone* _parent;

View File

@ -0,0 +1,73 @@
/******************************************************************************
* 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_Attachment_h
#define Spine_Attachment_h
#include <spine/SimpleArray.h>
#include <spine/HashMap.h>
namespace Spine
{
class ContainerUtil
{
public:
template<typename T>
static void cleanUpSimpleArrayOfPointers(SimpleArray<T*>& items)
{
for (size_t i = 0; i < items.size(); )
{
T* item = items[i];
delete item;
items.erase(i);
}
}
template<typename K, typename T, typename H>
static void cleanUpHashMapOfPointers(HashMap<K, T*, H>& hashMap)
{
for (typename HashMap<K, T*, H>::Iterator i = hashMap.begin(); i != hashMap.end(); )
{
delete i.second();
i = hashMap.erase(i);
}
}
private:
// ctor, copy ctor, and assignment should be private in a Singleton
ContainerUtil();
ContainerUtil(const ContainerUtil&);
ContainerUtil& operator=(const ContainerUtil&);
};
}
#endif /* defined(__noctisgames__ContainerUtil__) */

View File

@ -147,7 +147,7 @@ namespace Spine
size_t index = hash(key); size_t index = hash(key);
Entry* entry = new Entry; Entry* entry = new Entry();
entry->_key = key; entry->_key = key;
entry->_value = value; entry->_value = value;
@ -240,10 +240,12 @@ namespace Spine
return Iterator(&_trailer); return Iterator(&_trailer);
} }
void erase(Iterator pos) Iterator erase(Iterator pos)
{ {
if (pos._entry != &_header && pos._entry != &_trailer) if (pos._entry != &_header && pos._entry != &_trailer)
{ {
Entry* next = pos._entry->next;
size_t index = hash(pos._entry->_key); size_t index = hash(pos._entry->_key);
if (_hashTable[index].next == pos._entry && _hashTable[index].prev == pos._entry) if (_hashTable[index].next == pos._entry && _hashTable[index].prev == pos._entry)
@ -310,7 +312,11 @@ namespace Spine
} }
_hashSize--; _hashSize--;
return Iterator(next);
} }
return Iterator(&_trailer);
} }
V operator[](const K& key) V operator[](const K& key)

View File

@ -45,6 +45,8 @@
#define DegFull 360 #define DegFull 360
#define RadToIndex SIN_COUNT / RadFull #define RadToIndex SIN_COUNT / RadFull
#define DegToIndex SIN_COUNT / DegFull #define DegToIndex SIN_COUNT / DegFull
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
namespace Spine namespace Spine
{ {

View File

@ -0,0 +1,75 @@
/******************************************************************************
* 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_RTTI_h
#define Spine_RTTI_h
#include <string>
namespace Spine
{
class RTTI
{
public:
RTTI(const std::string& className);
RTTI(const std::string& className, const RTTI& baseRTTI);
const std::string& getClassName() const;
bool isExactly(const RTTI& rtti) const;
bool derivesFrom(const RTTI& rtti) const;
private:
// Prevent copying
RTTI(const RTTI& obj);
RTTI& operator=(const RTTI& obj);
const std::string m_className;
const RTTI *m_pBaseRTTI;
};
}
#define RTTI_DECL \
public: \
static const Spine::RTTI rtti; \
virtual const Spine::RTTI& getRTTI();
#define RTTI_IMPL_NOPARENT(name) \
const Spine::RTTI name::rtti(#name); \
const Spine::RTTI& name::getRTTI() { return rtti; }
#define RTTI_IMPL(name,parent) \
const Spine::RTTI name::rtti(#name, parent::rtti); \
const Spine::RTTI& name::getRTTI() { return rtti; }
#endif /* Spine_RTTI_h */

View File

@ -32,8 +32,10 @@
#define Spine_Skeleton_h #define Spine_Skeleton_h
#include <spine/SimpleArray.h> #include <spine/SimpleArray.h>
#include <spine/MathUtil.h>
#include <string> #include <string>
#include <limits> // std::numeric_limits
namespace Spine namespace Spine
{ {
@ -45,739 +47,142 @@ namespace Spine
class PathConstraint; class PathConstraint;
class TransformConstraint; class TransformConstraint;
class Skin; class Skin;
class Attachment;
class Skeleton class Skeleton
{ {
public: public:
SkeletonData* getData(); Skeleton(SkeletonData& data);
SimpleArray<Bone*> getBones();
SimpleArray<Updatable*> getUpdateCacheList();
SimpleArray<Slot*> getSlots();
SimpleArray<Slot*> getDrawOrder();
SimpleArray<IkConstraint*> getIkConstraints();
SimpleArray<PathConstraint*> getPathConstraints();
SimpleArray<TransformConstraint*> getTransformConstraints();
Skin* getSkin { get { return skin; } set { skin = value; } }
float getR { get { return r; } set { r = value; } }
float getG { get { return g; } set { g = value; } }
float getB { get { return b; } set { b = value; } }
float getA { get { return a; } set { a = value; } }
float getTime { get { return time; } set { time = value; } }
float getX { get { return x; } set { x = value; } }
float getY { get { return y; } set { y = value; } }
bool getFlipX { get { return flipX; } set { flipX = value; } }
bool getFlipY { get { return flipY; } set { flipY = value; } }
Bone* getRootBone()
{
return _bones.size() == 0 ? nullptr : _bones.at(0);
//get { return bones.Count == 0 ? null : bones.Items[0]; }
}
Skeleton(const SkeletonData& data)
{
if (data == null)
{
throw new ArgumentNullException("data", "data cannot be null.");
}
this.data = data;
bones = new SimpleArray<Bone>(data.bones.Count);
foreach (BoneData boneData in data.bones)
{
Bone bone;
if (boneData.parent == null)
{
bone = new Bone(boneData, this, null);
}
else
{
Bone parent = bones.Items[boneData.parent.index];
bone = new Bone(boneData, this, parent);
parent.children.Add(bone);
}
bones.Add(bone);
}
slots = new SimpleArray<Slot>(data.slots.Count);
drawOrder = new SimpleArray<Slot>(data.slots.Count);
foreach (SlotData slotData in data.slots)
{
Bone bone = bones.Items[slotData.boneData.index];
Slot slot = new Slot(slotData, bone);
slots.Add(slot);
drawOrder.Add(slot);
}
ikConstraints = new SimpleArray<IkConstraint>(data.ikConstraints.Count);
foreach (IkConstraintData ikConstraintData in data.ikConstraints)
ikConstraints.Add(new IkConstraint(ikConstraintData, this));
transformConstraints = new SimpleArray<TransformConstraint>(data.transformConstraints.Count);
foreach (TransformConstraintData transformConstraintData in data.transformConstraints)
transformConstraints.Add(new TransformConstraint(transformConstraintData, this));
pathConstraints = new SimpleArray<PathConstraint> (data.pathConstraints.Count);
foreach (PathConstraintData pathConstraintData in data.pathConstraints)
pathConstraints.Add(new PathConstraint(pathConstraintData, this));
updateCache();
updateWorldTransform();
}
~Skeleton()
{
// TODO
}
/// Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added /// Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added
/// or removed. /// or removed.
void updateCache() void updateCache();
{
SimpleArray<IUpdatable> updateCache = this.updateCache;
updateCache.Clear();
this.updateCacheReset.Clear();
SimpleArray<Bone> bones = this.bones;
for (int i = 0, n = bones.Count; i < n; i++)
{
bones.Items[i].sorted = false;
}
SimpleArray<IkConstraint> ikConstraints = this.ikConstraints;
var transformConstraints = this.transformConstraints;
var pathConstraints = this.pathConstraints;
int ikCount = IkConstraints.Count, transformCount = transformConstraints.Count, pathCount = pathConstraints.Count;
int constraintCount = ikCount + transformCount + pathCount;
//outer:
for (int i = 0; i < constraintCount; i++)
{
for (int ii = 0; ii < ikCount; ii++)
{
IkConstraint constraint = ikConstraints.Items[ii];
if (constraint.data.order == i)
{
sortIkConstraint(constraint);
goto continue_outer; //continue outer;
}
}
for (int ii = 0; ii < transformCount; ii++)
{
TransformConstraint constraint = transformConstraints.Items[ii];
if (constraint.data.order == i)
{
sortTransformConstraint(constraint);
goto continue_outer; //continue outer;
}
}
for (int ii = 0; ii < pathCount; ii++)
{
PathConstraint constraint = pathConstraints.Items[ii];
if (constraint.data.order == i)
{
sortPathConstraint(constraint);
goto continue_outer; //continue outer;
}
}
continue_outer: {}
}
for (int i = 0, n = bones.Count; i < n; i++)
{
sortBone(bones.Items[i]);
}
}
/// updates the world transform for each bone and applies constraints. /// Updates the world transform for each bone and applies constraints.
void updateWorldTransform() void updateWorldTransform();
{
var updateCacheReset = this.updateCacheReset;
var updateCacheResetItems = updateCacheReset.Items;
for (int i = 0, n = updateCacheReset.Count; 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;
}
var updateItems = this.updateCache.Items;
for (int i = 0, n = updateCache.Count; i < n; i++)
{
updateItems[i].update();
}
}
/// Sets the bones, constraints, and slots to their setup pose values. /// Sets the bones, constraints, and slots to their setup pose values.
void setToSetupPose() void setToSetupPose();
{
setBonesToSetupPose();
setSlotsToSetupPose();
}
/// Sets the bones and constraints to their setup pose values. /// Sets the bones and constraints to their setup pose values.
void setBonesToSetupPose() void setBonesToSetupPose();
{
var bonesItems = this.bones.Items;
for (int i = 0, n = bones.Count; i < n; i++)
{
bonesItems[i].setToSetupPose();
}
var ikConstraintsItems = this.ikConstraints.Items;
for (int i = 0, n = ikConstraints.Count; i < n; i++)
{
IkConstraint constraint = ikConstraintsItems[i];
constraint.bendDirection = constraint.data.bendDirection;
constraint.mix = constraint.data.mix;
}
var transformConstraintsItems = this.transformConstraints.Items;
for (int i = 0, n = transformConstraints.Count; 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;
}
var pathConstraintItems = this.pathConstraints.Items;
for (int i = 0, n = pathConstraints.Count; 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;
}
}
void setSlotsToSetupPose() void setSlotsToSetupPose();
{
var slots = this.slots;
var slotsItems = slots.Items;
drawOrder.Clear();
for (int i = 0, n = slots.Count; i < n; i++)
{
drawOrder.Add(slotsItems[i]);
}
for (int i = 0, n = slots.Count; i < n; i++)
{
slotsItems[i].setToSetupPose();
}
}
/// May be null. /// @return May be NULL.
Bone findBone(std::string boneName) Bone* findBone(std::string boneName);
{
if (boneName == null)
{
throw new ArgumentNullException("boneName", "boneName cannot be null.");
}
var bones = this.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;
}
/// -1 if the bone was not found. /// @return -1 if the bone was not found.
int findBoneIndex(std::string boneName) int findBoneIndex(std::string boneName);
{
if (boneName == null) throw new ArgumentNullException("boneName", "boneName cannot be null.");
var bones = this.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;
}
/// May be null. /// @return May be NULL.
Slot findSlot(std::string slotName) Slot* findSlot(std::string slotName);
{
if (slotName == null)
{
throw new ArgumentNullException("slotName", "slotName cannot be null.");
}
var slots = this.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;
}
/// -1 if the bone was not found. /// @return -1 if the bone was not found.
int findSlotIndex(std::string slotName) int findSlotIndex(std::string slotName);
{
if (slotName == null)
{
throw new ArgumentNullException("slotName", "slotName cannot be null.");
}
var slots = this.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;
}
/// Sets a skin by name (see setSkin). /// Sets a skin by name (see setSkin).
void setSkin(std::string skinName) void setSkin(std::string skinName);
{
Skin foundSkin = data.FindSkin(skinName);
if (foundSkin == null)
{
throw new ArgumentException("Skin not found: " + skinName, "skinName");
}
setSkin(foundSkin);
}
/// Attachments from the new skin are attached if the corresponding attachment from the old skin was attached.
/// 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
/// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin.
/// ///
/// <para>Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. /// @param newSkin May be NULL.
/// If there was no old skin, each slot's setup mode attachment is attached from the new skin.</para> void setSkin(Skin newSkin);
/// <para>After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling
/// <see cref="Skeleton.setSlotsToSetupPose()"/>.
/// Also, often <see cref="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.</para>
///
/// @param newSkin May be null.
void setSkin(Skin newSkin)
{
if (newSkin != null)
{
if (skin != null)
{
newSkin.AttachAll(this, skin);
}
else
{
SimpleArray<Slot> slots = this.slots;
for (int i = 0, n = slots.Count; i < n; i++)
{
Slot slot = slots.Items[i];
std::string name = slot.data.attachmentName;
if (name != null)
{
Attachment attachment = newSkin.getAttachment(i, name);
if (attachment != null)
{
slot.Attachment = attachment;
}
}
}
}
}
skin = newSkin;
}
/// May be null. /// @return May be NULL.
Attachment getAttachment(std::string slotName, std::string attachmentName) Attachment* getAttachment(std::string slotName, std::string attachmentName);
{
return getAttachment(data.findSlotIndex(slotName), attachmentName);
}
/// May be null. /// @return May be NULL.
Attachment getAttachment(int slotIndex, std::string attachmentName) Attachment* getAttachment(int slotIndex, std::string attachmentName);
{
if (attachmentName == null)
{
throw new ArgumentNullException("attachmentName", "attachmentName cannot be null.");
}
if (skin != null)
{
Attachment attachment = skin.getAttachment(slotIndex, attachmentName);
if (attachment != null)
{
return attachment;
}
}
return data.defaultSkin != null ? data.defaultSkin.getAttachment(slotIndex, attachmentName) : null;
}
/// @param attachmentName May be null. /// @param attachmentName May be empty.
void setAttachment(std::string slotName, std::string attachmentName) void setAttachment(std::string slotName, std::string attachmentName);
{
if (slotName == null)
{
throw new ArgumentNullException("slotName", "slotName cannot be null.");
}
SimpleArray<Slot> slots = this.slots;
for (int i = 0, n = slots.Count; i < n; i++)
{
Slot slot = slots.Items[i];
if (slot.data.name == slotName)
{
Attachment attachment = null;
if (attachmentName != null)
{
attachment = getAttachment(i, attachmentName);
if (attachment == null)
{
throw new Exception("Attachment not found: " + attachmentName + ", for slot: " + slotName);
}
}
slot.Attachment = attachment;
return;
}
}
throw new Exception("Slot not found: " + slotName);
}
/// May be null. /// @return May be NULL.
IkConstraint findIkConstraint(std::string constraintName) IkConstraint* findIkConstraint(std::string constraintName);
{
if (constraintName == null)
{
throw new ArgumentNullException("constraintName", "constraintName cannot be null.");
}
SimpleArray<IkConstraint> ikConstraints = this.ikConstraints;
for (int i = 0, n = ikConstraints.Count; i < n; i++)
{
IkConstraint ikConstraint = ikConstraints.Items[i];
if (ikConstraint.data.name == constraintName) return ikConstraint;
}
return null;
}
/// May be null. /// @return May be NULL.
TransformConstraint findTransformConstraint(std::string constraintName) TransformConstraint* findTransformConstraint(std::string constraintName);
{
if (constraintName == null)
{
throw new ArgumentNullException("constraintName", "constraintName cannot be null.");
}
SimpleArray<TransformConstraint> transformConstraints = this.transformConstraints;
for (int i = 0, n = transformConstraints.Count; i < n; i++)
{
TransformConstraint transformConstraint = transformConstraints.Items[i];
if (transformConstraint.data.name == constraintName) return transformConstraint;
}
return null;
}
/// May be null. /// @return May be NULL.
PathConstraint findPathConstraint(std::string constraintName) PathConstraint* findPathConstraint(std::string constraintName);
{
if (constraintName == null)
{
throw new ArgumentNullException("constraintName", "constraintName cannot be null.");
}
SimpleArray<PathConstraint> pathConstraints = this.pathConstraints;
for (int i = 0, n = pathConstraints.Count; i < n; i++)
{
PathConstraint constraint = pathConstraints.Items[i];
if (constraint.data.name.Equals(constraintName)) return constraint;
}
return null;
}
void update(float delta) void update(float delta);
{
time += delta;
}
/// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. /// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
/// @param x The horizontal distance between the skeleton origin and the left side of the AABB. /// @param x The horizontal distance between the skeleton origin and the left side of the AABB.
/// @param y The vertical distance between the skeleton origin and the bottom side of the AABB. /// @param y The vertical distance between the skeleton origin and the bottom side of the AABB.
/// @param width The width of the AABB /// @param width The width of the AABB
/// @param height The height of the AABB. /// @param height The height of the AABB.
/// @param vertexBuffer Reference to hold a float[]. May be a null reference. This method will assign it a new float[] with the appropriate size as needed. /// @param vertexBuffer Reference to hold a SimpleArray of floats. This method will assign it with new floats as needed.
void getBounds(out float x, out float y, out float width, out float height, ref float[] vertexBuffer) void getBounds(float& outX, float& outY, float& outWidth, float& outHeight, SimpleArray<float>& vertexBuffer);
{
float[] temp = vertexBuffer; Bone* getRootBone();
temp = temp ?? new float[8];
var drawOrderItems = this.drawOrder.Items; const SkeletonData& getData();
float minX = int.MaxValue, minY = int.MaxValue, maxX = int.MinValue, maxY = int.MinValue; SimpleArray<Bone*>& getBones();
for (int i = 0, n = this.drawOrder.Count; i < n; i++) SimpleArray<Updatable*>& getUpdateCacheList();
{ SimpleArray<Slot*>& getSlots();
Slot slot = drawOrderItems[i]; SimpleArray<Slot*>& getDrawOrder();
int verticesLength = 0; SimpleArray<IkConstraint*>& getIkConstraints();
float[] vertices = null; SimpleArray<PathConstraint*>& getPathConstraints();
Attachment attachment = slot.attachment; SimpleArray<TransformConstraint*>& getTransformConstraints();
var regionAttachment = attachment as RegionAttachment;
if (regionAttachment != null) Skin* getSkin();
{ void setSkin(Skin* inValue);
verticesLength = 8; float getR();
vertices = temp; void setR(float inValue);
if (vertices.Length < 8) vertices = temp = new float[8]; float getG();
regionAttachment.ComputeWorldVertices(slot.bone, temp, 0); void setG(float inValue);
} float getB();
else void setB(float inValue);
{ float getA();
var meshAttachment = attachment as MeshAttachment; void setA(float inValue);
if (meshAttachment != null) float getTime();
{ void setTime(float inValue);
MeshAttachment mesh = meshAttachment; float getX();
verticesLength = mesh.WorldVerticesLength; void setX(float inValue);
vertices = temp; float getY();
if (vertices.Length < verticesLength) void setY(float inValue);
{ bool getFlipX();
vertices = temp = new float[verticesLength]; void setFlipX(float inValue);
} bool getFlipY();
void setFlipY(float inValue);
mesh.ComputeWorldVertices(slot, 0, verticesLength, temp, 0);
}
}
if (vertices != null)
{
for (int ii = 0; ii < verticesLength; ii += 2)
{
float vx = vertices[ii], vy = vertices[ii + 1];
minX = Math.Min(minX, vx);
minY = Math.Min(minY, vy);
maxX = Math.Max(maxX, vx);
maxY = Math.Max(maxY, vy);
}
}
}
x = minX;
y = minY;
width = maxX - minX;
height = maxY - minY;
vertexBuffer = temp;
}
private: private:
SkeletonData* _data; const SkeletonData& _data;
SimpleArray<Bone*> _bones; SimpleArray<Bone*> _bones;
SimpleArray<Slot*> _slots; SimpleArray<Slot*> _slots;
SimpleArray<Slot*> _drawOrder; SimpleArray<Slot*> _drawOrder;
SimpleArray<IkConstraint*> _ikConstraints; SimpleArray<IkConstraint*> _ikConstraints;
SimpleArray<TransformConstraint*> _transformConstraints; SimpleArray<TransformConstraint*> _transformConstraints;
SimpleArray<PathConstraint*> _pathConstraints; SimpleArray<PathConstraint*> _pathConstraints;
SimpleArray<IUpdatable*> _updateCache = new SimpleArray<IUpdatable>(); SimpleArray<Updatable*> _updateCache;
SimpleArray<Bone*> _updateCacheReset = new SimpleArray<Bone>(); SimpleArray<Bone*> _updateCacheReset;
Skin _skin; Skin* _skin;
float _r = 1, _g = 1, _b = 1, _a = 1; float _r = 1, _g = 1, _b = 1, _a = 1;
float _time; float _time;
bool _flipX, _flipY; bool _flipX, _flipY;
float _x, _y; float _x, _y;
void sortIkConstraint(IkConstraint constraint) void sortIkConstraint(IkConstraint constraint);
{
Bone target = constraint.target;
sortBone(target);
var constrained = constraint.bones;
Bone parent = constrained.Items[0];
sortBone(parent);
if (constrained.Count > 1)
{
Bone child = constrained.Items[constrained.Count - 1];
if (!updateCache.Contains(child))
{
updateCacheReset.Add(child);
}
}
updateCache.Add(constraint);
sortReset(parent.children);
constrained.Items[constrained.Count - 1].sorted = true;
}
void sortPathConstraint(PathConstraint constraint) void sortPathConstraint(PathConstraint constraint);
{
Slot slot = constraint.target;
int slotIndex = slot.data.index;
Bone slotBone = slot.bone;
if (skin != null)
{
sortPathConstraintAttachment(skin, slotIndex, slotBone);
}
if (data.defaultSkin != null && data.defaultSkin != skin)
{
sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
}
for (int ii = 0, nn = data.skins.Count; ii < nn; ii++)
{
sortPathConstraintAttachment(data.skins.Items[ii], slotIndex, slotBone);
}
Attachment attachment = slot.attachment;
if (attachment is PathAttachment)
{
sortPathConstraintAttachment(attachment, slotBone);
}
var constrained = constraint.bones;
int boneCount = constrained.Count;
for (int i = 0; i < boneCount; i++)
{
sortBone(constrained.Items[i]);
}
updateCache.Add(constraint);
for (int i = 0; i < boneCount; i++)
{
sortReset(constrained.Items[i].children);
}
for (int i = 0; i < boneCount; i++)
{
constrained.Items[i].sorted = true;
}
}
void sortTransformConstraint(TransformConstraint constraint) void sortTransformConstraint(TransformConstraint constraint);
{
sortBone(constraint.target);
var constrained = constraint.bones;
int boneCount = constrained.Count;
if (constraint.data.local)
{
for (int i = 0; i < boneCount; i++)
{
Bone child = constrained.Items[i];
sortBone(child.parent);
if (!updateCache.Contains(child))
{
updateCacheReset.Add(child);
}
}
}
else
{
for (int i = 0; i < boneCount; i++)
{
sortBone(constrained.Items[i]);
}
}
updateCache.Add(constraint);
for (int i = 0; i < boneCount; i++)
{
sortReset(constrained.Items[i].children);
}
for (int i = 0; i < boneCount; i++)
{
constrained.Items[i].sorted = true;
}
}
void sortPathConstraintAttachment(Skin skin, int slotIndex, Bone slotBone) void sortPathConstraintAttachment(Skin skin, int slotIndex, Bone slotBone);
{
foreach (var entry in skin.Attachments)
{
if (entry.Key.slotIndex == slotIndex)
{
sortPathConstraintAttachment(entry.Value, slotBone);
}
}
}
void sortPathConstraintAttachment(Attachment attachment, Bone slotBone) void sortPathConstraintAttachment(Attachment attachment, Bone slotBone);
{
if (!(attachment is PathAttachment)) return;
int[] pathBones = ((PathAttachment)attachment).bones;
if (pathBones == null)
{
sortBone(slotBone);
}
else
{
var bones = this.bones;
for (int i = 0, n = pathBones.Length; i < n;)
{
int nn = pathBones[i++];
nn += i;
while (i < nn)
{
sortBone(bones.Items[pathBones[i++]]);
}
}
}
}
void sortBone(Bone bone) void sortBone(Bone bone);
{
if (bone.sorted)
{
return;
}
Bone parent = bone.parent;
if (parent != null) sortBone(parent);
bone.sorted = true;
updateCache.Add(bone);
}
static void sortReset(SimpleArray<Bone*>& bones) static void sortReset(SimpleArray<Bone*>& bones);
{
var bonesItems = bones.Items;
for (int i = 0, n = bones.Count; i < n; i++)
{
Bone bone = bonesItems[i];
if (bone.sorted)
{
sortReset(bone.children);
}
bone.sorted = false;
}
}
}; };
} }

View File

@ -38,6 +38,18 @@
namespace Spine namespace Spine
{ {
bool Bone::yDown = false;
void Bone::setYDown(bool inValue)
{
yDown = inValue;
}
bool Bone::isYDown()
{
return yDown;
}
Bone::Bone(BoneData& data, Skeleton& skeleton, Bone* parent) : Updatable(), Bone::Bone(BoneData& data, Skeleton& skeleton, Bone* parent) : Updatable(),
_data(data), _data(data),
_skeleton(skeleton), _skeleton(skeleton),
@ -106,6 +118,13 @@ namespace Spine
lb = -lb; lb = -lb;
} }
if (_skeleton.isFlipY() != Bone::isYDown())
{
y = -y;
lc = -lc;
ld = -ld;
}
_a = la; _a = la;
_b = lb; _b = lb;
_c = lc; _c = lc;
@ -224,6 +243,12 @@ namespace Spine
_a = -_a; _a = -_a;
_b = -_b; _b = -_b;
} }
if (skeleton.isFlipY() != Bone::isYDown())
{
c = -c;
d = -d;
}
} }
void Bone::setToSetupPose() void Bone::setToSetupPose()

View File

@ -35,7 +35,7 @@ namespace Spine
IkConstraintData::IkConstraintData(std::string name) : IkConstraintData::IkConstraintData(std::string name) :
_name(name), _name(name),
_order(0), _order(0),
_target(nullptr), _target(NULL),
_bendDirection(1), _bendDirection(1),
_mix(1) _mix(1)
{ {

View File

@ -40,7 +40,7 @@ namespace Spine
PathConstraintData::PathConstraintData(std::string name) : PathConstraintData::PathConstraintData(std::string name) :
_name(name), _name(name),
_order(0), _order(0),
_target(nullptr), _target(NULL),
_positionMode(PositionMode_Fixed), _positionMode(PositionMode_Fixed),
_spacingMode(SpacingMode_Length), _spacingMode(SpacingMode_Length),
_rotateMode(RotateMode_Tangent), _rotateMode(RotateMode_Tangent),

View File

@ -0,0 +1,71 @@
/******************************************************************************
* 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/RTTI.h>
namespace Spine
{
RTTI::RTTI(const std::string& className) : m_className(className), m_pBaseRTTI(nullptr)
{
// Empty
}
RTTI::RTTI(const std::string& className, const RTTI& baseRTTI) : m_className(className), m_pBaseRTTI(&baseRTTI)
{
// Empty
}
const std::string& RTTI::getClassName() const
{
return m_className;
}
bool RTTI::isExactly(const RTTI& rtti) const
{
return (this == &rtti);
}
bool RTTI::derivesFrom(const RTTI& rtti) const
{
const RTTI * pCompare = this;
while (pCompare)
{
if (pCompare == &rtti)
{
return true;
}
pCompare = pCompare->m_pBaseRTTI;
}
return false;
}
}

View File

@ -38,8 +38,786 @@
#include <spine/PathConstraint.h> #include <spine/PathConstraint.h>
#include <spine/TransformConstraint.h> #include <spine/TransformConstraint.h>
#include <spine/Skin.h> #include <spine/Skin.h>
#include <spine/Attachment.h>
namespace Spine namespace Spine
{ {
// TODO Skeleton::Skeleton(SkeletonData& data) : _data(data)
{
_bones.reserve(_data->getBones().size());
bones = new SimpleArray<Bone>(data.bones.Count);
foreach (BoneData boneData in data.bones)
{
Bone bone;
if (boneData.parent == NULL)
{
bone = new Bone(boneData, this, NULL);
}
else
{
Bone parent = bones.Items[boneData.parent.index];
bone = new Bone(boneData, this, parent);
parent.children.Add(bone);
}
bones.Add(bone);
}
slots = new SimpleArray<Slot>(data.slots.Count);
drawOrder = new SimpleArray<Slot>(data.slots.Count);
foreach (SlotData slotData in data.slots)
{
Bone bone = bones.Items[slotData.boneData.index];
Slot slot = new Slot(slotData, bone);
slots.Add(slot);
drawOrder.Add(slot);
}
ikConstraints = new SimpleArray<IkConstraint>(data.ikConstraints.Count);
foreach (IkConstraintData ikConstraintData in data.ikConstraints)
ikConstraints.Add(new IkConstraint(ikConstraintData, this));
transformConstraints = new SimpleArray<TransformConstraint>(data.transformConstraints.Count);
foreach (TransformConstraintData transformConstraintData in data.transformConstraints)
transformConstraints.Add(new TransformConstraint(transformConstraintData, this));
pathConstraints = new SimpleArray<PathConstraint> (data.pathConstraints.Count);
foreach (PathConstraintData pathConstraintData in data.pathConstraints)
pathConstraints.Add(new PathConstraint(pathConstraintData, this));
updateCache();
updateWorldTransform();
}
void Skeleton::updateCache()
{
SimpleArray<IUpdatable> updateCache = _updateCache;
updateCache.Clear();
_updateCacheReset.Clear();
SimpleArray<Bone> bones = _bones;
for (int i = 0, n = bones.Count; i < n; ++i)
{
bones.Items[i].sorted = false;
}
SimpleArray<IkConstraint> ikConstraints = _ikConstraints;
var transformConstraints = _transformConstraints;
var pathConstraints = _pathConstraints;
int ikCount = IkConstraints.Count, transformCount = transformConstraints.Count, pathCount = pathConstraints.Count;
int constraintCount = ikCount + transformCount + pathCount;
//outer:
for (int i = 0; i < constraintCount; ++i)
{
for (int ii = 0; ii < ikCount; ++ii)
{
IkConstraint constraint = ikConstraints.Items[ii];
if (constraint.data.order == i)
{
sortIkConstraint(constraint);
goto continue_outer; //continue outer;
}
}
for (int ii = 0; ii < transformCount; ++ii)
{
TransformConstraint constraint = transformConstraints.Items[ii];
if (constraint.data.order == i)
{
sortTransformConstraint(constraint);
goto continue_outer; //continue outer;
}
}
for (int ii = 0; ii < pathCount; ++ii)
{
PathConstraint constraint = pathConstraints.Items[ii];
if (constraint.data.order == i)
{
sortPathConstraint(constraint);
goto continue_outer; //continue outer;
}
}
continue_outer: {}
}
for (int i = 0, n = bones.Count; i < n; ++i)
{
sortBone(bones.Items[i]);
}
}
void Skeleton::updateWorldTransform()
{
var updateCacheReset = _updateCacheReset;
var updateCacheResetItems = updateCacheReset.Items;
for (int i = 0, n = updateCacheReset.Count; 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;
}
var updateItems = _updateCache.Items;
for (int i = 0, n = updateCache.Count; i < n; ++i)
{
updateItems[i].update();
}
}
void Skeleton::setToSetupPose()
{
setBonesToSetupPose();
setSlotsToSetupPose();
}
void Skeleton::setBonesToSetupPose()
{
var bonesItems = _bones.Items;
for (int i = 0, n = bones.Count; i < n; ++i)
{
bonesItems[i].setToSetupPose();
}
var ikConstraintsItems = _ikConstraints.Items;
for (int i = 0, n = ikConstraints.Count; i < n; ++i)
{
IkConstraint constraint = ikConstraintsItems[i];
constraint.bendDirection = constraint.data.bendDirection;
constraint.mix = constraint.data.mix;
}
var transformConstraintsItems = _transformConstraints.Items;
for (int i = 0, n = transformConstraints.Count; 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;
}
var pathConstraintItems = _pathConstraints.Items;
for (int i = 0, n = pathConstraints.Count; 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;
}
}
void Skeleton::setSlotsToSetupPose()
{
var slots = _slots;
var slotsItems = slots.Items;
drawOrder.Clear();
for (int i = 0, n = slots.Count; i < n; ++i)
{
drawOrder.Add(slotsItems[i]);
}
for (int i = 0, n = slots.Count; i < n; ++i)
{
slotsItems[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;
}
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;
}
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;
}
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;
}
void Skeleton::setSkin(std::string skinName)
{
Skin foundSkin = data.FindSkin(skinName);
assert(foundSkin != NULL);
setSkin(foundSkin);
}
void Skeleton::setSkin(Skin newSkin)
{
if (newSkin != NULL)
{
if (skin != NULL)
{
newSkin.AttachAll(this, skin);
}
else
{
SimpleArray<Slot> slots = _slots;
for (int i = 0, n = slots.Count; i < n; ++i)
{
Slot slot = slots.Items[i];
std::string name = slot.data.attachmentName;
if (name != NULL)
{
Attachment attachment = newSkin.getAttachment(i, name);
if (attachment != NULL)
{
slot.Attachment = attachment;
}
}
}
}
}
skin = newSkin;
}
Attachment* Skeleton::getAttachment(std::string slotName, std::string attachmentName)
{
return getAttachment(data.findSlotIndex(slotName), attachmentName);
}
Attachment* Skeleton::getAttachment(int slotIndex, std::string attachmentName)
{
assert(attachmentName.length() > 0);
if (skin != NULL)
{
Attachment attachment = skin.getAttachment(slotIndex, attachmentName);
if (attachment != NULL)
{
return attachment;
}
}
return data.defaultSkin != NULL ? data.defaultSkin.getAttachment(slotIndex, attachmentName) : NULL;
}
void Skeleton::setAttachment(std::string slotName, std::string attachmentName)
{
assert(slotName.length() > 0);
SimpleArray<Slot> slots = _slots;
for (int i = 0, n = slots.Count; i < n; ++i)
{
Slot slot = slots.Items[i];
if (slot.data.name == slotName)
{
Attachment attachment = NULL;
if (attachmentName != NULL)
{
attachment = getAttachment(i, attachmentName);
assert(attachment != NULL);
}
slot.Attachment = attachment;
return;
}
}
printf("Slot not found: %s" + slotName.c_str());
assert(false);
}
IkConstraint* Skeleton::findIkConstraint(std::string constraintName)
{
assert(constraintName.length() > 0);
SimpleArray<IkConstraint> ikConstraints = _ikConstraints;
for (int i = 0, n = ikConstraints.Count; i < n; ++i)
{
IkConstraint ikConstraint = ikConstraints.Items[i];
if (ikConstraint.data.name == constraintName)
{
return ikConstraint;
}
}
return NULL;
}
TransformConstraint* Skeleton::findTransformConstraint(std::string constraintName)
{
assert(constraintName.length() > 0);
SimpleArray<TransformConstraint> transformConstraints = _transformConstraints;
for (int i = 0, n = transformConstraints.Count; i < n; ++i)
{
TransformConstraint transformConstraint = transformConstraints.Items[i];
if (transformConstraint.data.name == constraintName)
{
return transformConstraint;
}
}
return NULL;
}
PathConstraint* Skeleton::findPathConstraint(std::string constraintName)
{
assert(constraintName.length() > 0);
SimpleArray<PathConstraint> pathConstraints = _pathConstraints;
for (int i = 0, n = pathConstraints.Count; i < n; ++i)
{
PathConstraint constraint = pathConstraints.Items[i];
if (constraint.data.name.Equals(constraintName))
{
return constraint;
}
}
return NULL;
}
void Skeleton::update(float delta)
{
_time += delta;
}
void Skeleton::getBounds(float& outX, float& outY, float& outWidth, float& outHeight, SimpleArray<float>& vertexBuffer)
{
float minX = std::numeric_limits<float>::max();
float minY = std::numeric_limits<float>::max();
float maxX = std::numeric_limits<float>::min();
float maxY = std::numeric_limits<float>::min();
for (Slot* i = _drawOrder.begin(); i != _drawOrder.end(); ++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)
{
vertexBuffer.reserve(8);
}
regionAttachment->computeWorldVertices(slot->getBone(), vertexBuffer, 0);
}
else if (attachment != NULL && attachment->getRTTI().derivesFrom(MeshAttachment::rtti))
{
MeshAttachment* mesh = static_cast<MeshAttachment*>(attachment);
verticesLength = mesh->getWorldVerticesLength();
if (vertexBuffer.size() < verticesLength)
{
vertexBuffer.reserve(verticesLength);
}
mesh->computeWorldVertices(slot, 0, verticesLength, vertexBuffer, 0);
}
for (int ii = 0; ii < verticesLength; ii += 2)
{
float vx = vertexBuffer[ii];
float vy = vertexBuffer[ii + 1];
minX = MIN(minX, vx);
minY = MIN(minY, vy);
maxX = MAX(maxX, vx);
maxY = MAX(maxY, vy);
}
}
x = minX;
y = minY;
width = maxX - minX;
height = maxY - minY;
}
Bone* Skeleton::getRootBone()
{
return _bones.size() == 0 ? NULL : &_bones[0];
}
const SkeletonData& Skeleton::getData()
{
return _data;
}
SimpleArray<Bone*>& Skeleton::getBones()
{
return _bones;
}
SimpleArray<Updatable*>& Skeleton::getUpdateCacheList()
{
return _updateCache;
}
SimpleArray<Slot*>& Skeleton::getSlots()
{
return _slots;
}
SimpleArray<Slot*>& Skeleton::getDrawOrder()
{
return _drawOrder;
}
SimpleArray<IkConstraint*>& Skeleton::getIkConstraints()
{
return _ikConstraints;
}
SimpleArray<PathConstraint*>& Skeleton::getPathConstraints()
{
return _pathConstraints;
}
SimpleArray<TransformConstraint*>& Skeleton::getTransformConstraints()
{
return _transformConstraints;
}
Skin* Skeleton::getSkin()
{
return _skin;
}
void Skeleton::setSkin(Skin* inValue)
{
_skin = inValue;
}
float Skeleton::getR()
{
return _r;
}
void Skeleton::setR(float inValue)
{
_r = inValue;
}
float Skeleton::getG()
{
return _g;
}
void Skeleton::setG(float inValue)
{
_g = inValue;
}
float Skeleton::getB()
{
return _b;
}
void Skeleton::setB(float inValue)
{
_b = inValue;
}
float Skeleton::getA()
{
return _a;
}
void Skeleton::setA(float inValue)
{
_a = inValue;
}
float Skeleton::getTime()
{
return _time;
}
void Skeleton::setTime(float inValue)
{
_time = inValue;
}
float Skeleton::getX()
{
return _x;
}
void Skeleton::setX(float inValue)
{
_x = inValue;
}
float Skeleton::getY()
{
return _y;
}
void Skeleton::setY(float inValue)
{
_y = inValue;
}
bool Skeleton::getFlipX()
{
return _flipX;
}
void Skeleton::setFlipX(float inValue)
{
_flipX = inValue;
}
bool Skeleton::getFlipY()
{
return _flipY;
}
void Skeleton::setFlipY(float inValue)
{
_flipY = inValue;
}
void Skeleton::sortIkConstraint(IkConstraint constraint)
{
Bone target = constraint.target;
sortBone(target);
var constrained = constraint.bones;
Bone parent = constrained.Items[0];
sortBone(parent);
if (constrained.Count > 1)
{
Bone child = constrained.Items[constrained.Count - 1];
if (!updateCache.Contains(child))
{
updateCacheReset.Add(child);
}
}
updateCache.Add(constraint);
sortReset(parent.children);
constrained.Items[constrained.Count - 1].sorted = true;
}
void Skeleton::sortPathConstraint(PathConstraint constraint)
{
Slot slot = constraint.target;
int slotIndex = slot.data.index;
Bone slotBone = slot.bone;
if (skin != NULL)
{
sortPathConstraintAttachment(skin, slotIndex, slotBone);
}
if (data.defaultSkin != NULL && data.defaultSkin != skin)
{
sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
}
for (int ii = 0, nn = data.skins.Count; ii < nn; ++ii)
{
sortPathConstraintAttachment(data.skins.Items[ii], slotIndex, slotBone);
}
Attachment attachment = slot.attachment;
if (attachment is PathAttachment)
{
sortPathConstraintAttachment(attachment, slotBone);
}
var constrained = constraint.bones;
int boneCount = constrained.Count;
for (int i = 0; i < boneCount; ++i)
{
sortBone(constrained.Items[i]);
}
updateCache.Add(constraint);
for (int i = 0; i < boneCount; ++i)
{
sortReset(constrained.Items[i].children);
}
for (int i = 0; i < boneCount; ++i)
{
constrained.Items[i].sorted = true;
}
}
void Skeleton::sortTransformConstraint(TransformConstraint constraint)
{
sortBone(constraint.target);
var constrained = constraint.bones;
int boneCount = constrained.Count;
if (constraint.data.local)
{
for (int i = 0; i < boneCount; ++i)
{
Bone child = constrained.Items[i];
sortBone(child.parent);
if (!updateCache.Contains(child))
{
updateCacheReset.Add(child);
}
}
}
else
{
for (int i = 0; i < boneCount; ++i)
{
sortBone(constrained.Items[i]);
}
}
updateCache.Add(constraint);
for (int i = 0; i < boneCount; ++i)
{
sortReset(constrained.Items[i].children);
}
for (int i = 0; i < boneCount; ++i)
{
constrained.Items[i].sorted = true;
}
}
void Skeleton::sortPathConstraintAttachment(Skin skin, int slotIndex, Bone slotBone)
{
foreach (var entry in skin.Attachments)
{
if (entry.Key.slotIndex == slotIndex)
{
sortPathConstraintAttachment(entry.Value, slotBone);
}
}
}
void Skeleton::sortPathConstraintAttachment(Attachment attachment, Bone slotBone)
{
if (!(attachment is PathAttachment))
{
return;
}
int[] pathBones = ((PathAttachment)attachment).bones;
if (pathBones == NULL)
{
sortBone(slotBone);
}
else
{
var bones = _bones;
for (int i = 0, n = pathBones.Length; i < n;)
{
int nn = pathBones[i++];
nn += i;
while (i < nn)
{
sortBone(bones.Items[pathBones[i++]]);
}
}
}
}
void Skeleton::sortBone(Bone bone)
{
if (bone.sorted)
{
return;
}
Bone parent = bone.parent;
if (parent != NULL)
{
sortBone(parent);
}
bone.sorted = true;
updateCache.Add(bone);
}
void Skeleton::sortReset(SimpleArray<Bone*>& bones)
{
for (Bone* i = bones.begin(); i != bones.end(); ++i)
{
Bone* bone = i;
if (bone->isSorted())
{
sortReset(bone->getChildren());
}
bone->setSorted(false);
}
}
} }

View File

@ -67,7 +67,7 @@ namespace Spine
{ {
HashMap<AttachmentKey, Attachment*, HashAttachmentKey>::Iterator i = _attachments.find(AttachmentKey(slotIndex, name)); HashMap<AttachmentKey, Attachment*, HashAttachmentKey>::Iterator i = _attachments.find(AttachmentKey(slotIndex, name));
Attachment* ret = nullptr; Attachment* ret = NULL;
if (i != _attachments.end()) if (i != _attachments.end())
{ {
@ -118,7 +118,7 @@ namespace Spine
if (slot->getAttachment() == i.second()) if (slot->getAttachment() == i.second())
{ {
Attachment* attachment = nullptr; Attachment* attachment = NULL;
if ((attachment = getAttachment(slotIndex, i.first()._name))) if ((attachment = getAttachment(slotIndex, i.first()._name)))
{ {
slot->setAttachment(attachment); slot->setAttachment(attachment);

View File

@ -49,7 +49,7 @@ namespace Spine
_g2(0), _g2(0),
_b2(0), _b2(0),
_hasSecondColor(false), _hasSecondColor(false),
_attachment(nullptr), _attachment(NULL),
_attachmentTime(0) _attachmentTime(0)
{ {
setToSetupPose(); setToSetupPose();
@ -65,12 +65,12 @@ namespace Spine
std::string attachmentName = _slotData.getAttachmentName(); std::string attachmentName = _slotData.getAttachmentName();
if (attachmentName.length() > 0) if (attachmentName.length() > 0)
{ {
_attachment = nullptr; _attachment = NULL;
setAttachment(_skeleton.getAttachment(_slotData.getIndex(), attachmentName)); setAttachment(_skeleton.getAttachment(_slotData.getIndex(), attachmentName));
} }
else else
{ {
setAttachment(nullptr); setAttachment(NULL);
} }
} }

View File

@ -39,7 +39,7 @@ namespace Spine
TransformConstraintData::TransformConstraintData(std::string name) : TransformConstraintData::TransformConstraintData(std::string name) :
_name(name), _name(name),
_order(0), _order(0),
_target(nullptr), _target(NULL),
_rotateMix(0), _rotateMix(0),
_translateMix(0), _translateMix(0),
_scaleMix(0), _scaleMix(0),