mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +08:00
wip
This commit is contained in:
parent
af243b4922
commit
072ada4c5c
@ -50,6 +50,10 @@ namespace Spine
|
||||
friend class RotateTimeline;
|
||||
|
||||
public:
|
||||
static void setYDown(bool inValue);
|
||||
|
||||
static bool isYDown();
|
||||
|
||||
/// @param parent May be null.
|
||||
Bone(BoneData& data, Skeleton& skeleton, Bone* parent);
|
||||
|
||||
@ -160,6 +164,8 @@ namespace Spine
|
||||
float getWorldScaleY();
|
||||
|
||||
private:
|
||||
static bool yDown;
|
||||
|
||||
BoneData& _data;
|
||||
Skeleton& _skeleton;
|
||||
Bone* _parent;
|
||||
|
||||
73
spine-cpp/spine-cpp/include/spine/ContainerUtil.h
Normal file
73
spine-cpp/spine-cpp/include/spine/ContainerUtil.h
Normal 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__) */
|
||||
@ -147,7 +147,7 @@ namespace Spine
|
||||
|
||||
size_t index = hash(key);
|
||||
|
||||
Entry* entry = new Entry;
|
||||
Entry* entry = new Entry();
|
||||
entry->_key = key;
|
||||
entry->_value = value;
|
||||
|
||||
@ -240,10 +240,12 @@ namespace Spine
|
||||
return Iterator(&_trailer);
|
||||
}
|
||||
|
||||
void erase(Iterator pos)
|
||||
Iterator erase(Iterator pos)
|
||||
{
|
||||
if (pos._entry != &_header && pos._entry != &_trailer)
|
||||
{
|
||||
Entry* next = pos._entry->next;
|
||||
|
||||
size_t index = hash(pos._entry->_key);
|
||||
|
||||
if (_hashTable[index].next == pos._entry && _hashTable[index].prev == pos._entry)
|
||||
@ -310,7 +312,11 @@ namespace Spine
|
||||
}
|
||||
|
||||
_hashSize--;
|
||||
|
||||
return Iterator(next);
|
||||
}
|
||||
|
||||
return Iterator(&_trailer);
|
||||
}
|
||||
|
||||
V operator[](const K& key)
|
||||
|
||||
@ -45,6 +45,8 @@
|
||||
#define DegFull 360
|
||||
#define RadToIndex SIN_COUNT / RadFull
|
||||
#define DegToIndex SIN_COUNT / DegFull
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
namespace Spine
|
||||
{
|
||||
|
||||
75
spine-cpp/spine-cpp/include/spine/RTTI.h
Normal file
75
spine-cpp/spine-cpp/include/spine/RTTI.h
Normal 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 */
|
||||
|
||||
@ -32,8 +32,10 @@
|
||||
#define Spine_Skeleton_h
|
||||
|
||||
#include <spine/SimpleArray.h>
|
||||
#include <spine/MathUtil.h>
|
||||
|
||||
#include <string>
|
||||
#include <limits> // std::numeric_limits
|
||||
|
||||
namespace Spine
|
||||
{
|
||||
@ -45,739 +47,142 @@ namespace Spine
|
||||
class PathConstraint;
|
||||
class TransformConstraint;
|
||||
class Skin;
|
||||
class Attachment;
|
||||
|
||||
class Skeleton
|
||||
{
|
||||
public:
|
||||
SkeletonData* getData();
|
||||
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
|
||||
}
|
||||
Skeleton(SkeletonData& data);
|
||||
|
||||
/// Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added
|
||||
/// or removed.
|
||||
void updateCache()
|
||||
{
|
||||
SimpleArray<IUpdatable> updateCache = this.updateCache;
|
||||
updateCache.Clear();
|
||||
this.updateCacheReset.Clear();
|
||||
void updateCache();
|
||||
|
||||
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.
|
||||
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();
|
||||
}
|
||||
}
|
||||
/// Updates the world transform for each bone and applies constraints.
|
||||
void updateWorldTransform();
|
||||
|
||||
/// Sets the bones, constraints, and slots to their setup pose values.
|
||||
void setToSetupPose()
|
||||
{
|
||||
setBonesToSetupPose();
|
||||
setSlotsToSetupPose();
|
||||
}
|
||||
void setToSetupPose();
|
||||
|
||||
/// Sets the bones and constraints to their setup pose values.
|
||||
void setBonesToSetupPose()
|
||||
{
|
||||
var bonesItems = this.bones.Items;
|
||||
for (int i = 0, n = bones.Count; i < n; i++)
|
||||
{
|
||||
bonesItems[i].setToSetupPose();
|
||||
}
|
||||
void setBonesToSetupPose();
|
||||
|
||||
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;
|
||||
}
|
||||
void setSlotsToSetupPose();
|
||||
|
||||
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;
|
||||
}
|
||||
/// @return May be NULL.
|
||||
Bone* findBone(std::string boneName);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
/// @return -1 if the bone was not found.
|
||||
int findBoneIndex(std::string boneName);
|
||||
|
||||
void setSlotsToSetupPose()
|
||||
{
|
||||
var slots = this.slots;
|
||||
var slotsItems = slots.Items;
|
||||
drawOrder.Clear();
|
||||
/// @return May be NULL.
|
||||
Slot* findSlot(std::string slotName);
|
||||
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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;
|
||||
}
|
||||
/// @return -1 if the bone was not found.
|
||||
int findSlotIndex(std::string slotName);
|
||||
|
||||
/// Sets a skin by name (see setSkin).
|
||||
void setSkin(std::string skinName)
|
||||
{
|
||||
Skin foundSkin = data.FindSkin(skinName);
|
||||
if (foundSkin == null)
|
||||
{
|
||||
throw new ArgumentException("Skin not found: " + skinName, "skinName");
|
||||
}
|
||||
|
||||
setSkin(foundSkin);
|
||||
}
|
||||
void setSkin(std::string skinName);
|
||||
|
||||
/// 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.
|
||||
/// If there was no old skin, each slot's setup mode attachment is attached from the new skin.</para>
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// @param newSkin May be NULL.
|
||||
void setSkin(Skin newSkin);
|
||||
|
||||
skin = newSkin;
|
||||
}
|
||||
/// @return May be NULL.
|
||||
Attachment* getAttachment(std::string slotName, std::string attachmentName);
|
||||
|
||||
/// May be null.
|
||||
Attachment getAttachment(std::string slotName, std::string attachmentName)
|
||||
{
|
||||
return getAttachment(data.findSlotIndex(slotName), attachmentName);
|
||||
}
|
||||
/// @return May be NULL.
|
||||
Attachment* getAttachment(int slotIndex, std::string attachmentName);
|
||||
|
||||
/// May be null.
|
||||
Attachment getAttachment(int slotIndex, std::string attachmentName)
|
||||
{
|
||||
if (attachmentName == null)
|
||||
{
|
||||
throw new ArgumentNullException("attachmentName", "attachmentName cannot be null.");
|
||||
}
|
||||
/// @param attachmentName May be empty.
|
||||
void setAttachment(std::string slotName, std::string attachmentName);
|
||||
|
||||
if (skin != null)
|
||||
{
|
||||
Attachment attachment = skin.getAttachment(slotIndex, attachmentName);
|
||||
if (attachment != null)
|
||||
{
|
||||
return attachment;
|
||||
}
|
||||
}
|
||||
/// @return May be NULL.
|
||||
IkConstraint* findIkConstraint(std::string constraintName);
|
||||
|
||||
return data.defaultSkin != null ? data.defaultSkin.getAttachment(slotIndex, attachmentName) : null;
|
||||
}
|
||||
/// @return May be NULL.
|
||||
TransformConstraint* findTransformConstraint(std::string constraintName);
|
||||
|
||||
/// @param attachmentName May be null.
|
||||
void setAttachment(std::string slotName, std::string attachmentName)
|
||||
{
|
||||
if (slotName == null)
|
||||
{
|
||||
throw new ArgumentNullException("slotName", "slotName cannot be null.");
|
||||
}
|
||||
/// @return May be NULL.
|
||||
PathConstraint* findPathConstraint(std::string constraintName);
|
||||
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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)
|
||||
{
|
||||
time += delta;
|
||||
}
|
||||
void update(float delta);
|
||||
|
||||
/// 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 y The vertical distance between the skeleton origin and the bottom side of the AABB.
|
||||
/// @param width The width 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.
|
||||
void getBounds(out float x, out float y, out float width, out float height, ref float[] vertexBuffer)
|
||||
{
|
||||
float[] temp = vertexBuffer;
|
||||
temp = temp ?? new float[8];
|
||||
var drawOrderItems = this.drawOrder.Items;
|
||||
float minX = int.MaxValue, minY = int.MaxValue, maxX = int.MinValue, maxY = int.MinValue;
|
||||
for (int i = 0, n = this.drawOrder.Count; i < n; i++)
|
||||
{
|
||||
Slot slot = drawOrderItems[i];
|
||||
int verticesLength = 0;
|
||||
float[] vertices = null;
|
||||
Attachment attachment = slot.attachment;
|
||||
var regionAttachment = attachment as RegionAttachment;
|
||||
if (regionAttachment != null)
|
||||
{
|
||||
verticesLength = 8;
|
||||
vertices = temp;
|
||||
if (vertices.Length < 8) vertices = temp = new float[8];
|
||||
regionAttachment.ComputeWorldVertices(slot.bone, temp, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var meshAttachment = attachment as MeshAttachment;
|
||||
if (meshAttachment != null)
|
||||
{
|
||||
MeshAttachment mesh = meshAttachment;
|
||||
verticesLength = mesh.WorldVerticesLength;
|
||||
vertices = temp;
|
||||
if (vertices.Length < verticesLength)
|
||||
{
|
||||
vertices = temp = new float[verticesLength];
|
||||
}
|
||||
/// @param vertexBuffer Reference to hold a SimpleArray of floats. This method will assign it with new floats as needed.
|
||||
void getBounds(float& outX, float& outY, float& outWidth, float& outHeight, SimpleArray<float>& vertexBuffer);
|
||||
|
||||
mesh.ComputeWorldVertices(slot, 0, verticesLength, temp, 0);
|
||||
}
|
||||
}
|
||||
Bone* getRootBone();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
const SkeletonData& getData();
|
||||
SimpleArray<Bone*>& getBones();
|
||||
SimpleArray<Updatable*>& getUpdateCacheList();
|
||||
SimpleArray<Slot*>& getSlots();
|
||||
SimpleArray<Slot*>& getDrawOrder();
|
||||
SimpleArray<IkConstraint*>& getIkConstraints();
|
||||
SimpleArray<PathConstraint*>& getPathConstraints();
|
||||
SimpleArray<TransformConstraint*>& getTransformConstraints();
|
||||
|
||||
x = minX;
|
||||
y = minY;
|
||||
width = maxX - minX;
|
||||
height = maxY - minY;
|
||||
vertexBuffer = temp;
|
||||
}
|
||||
Skin* getSkin();
|
||||
void setSkin(Skin* inValue);
|
||||
float getR();
|
||||
void setR(float inValue);
|
||||
float getG();
|
||||
void setG(float inValue);
|
||||
float getB();
|
||||
void setB(float inValue);
|
||||
float getA();
|
||||
void setA(float inValue);
|
||||
float getTime();
|
||||
void setTime(float inValue);
|
||||
float getX();
|
||||
void setX(float inValue);
|
||||
float getY();
|
||||
void setY(float inValue);
|
||||
bool getFlipX();
|
||||
void setFlipX(float inValue);
|
||||
bool getFlipY();
|
||||
void setFlipY(float inValue);
|
||||
|
||||
private:
|
||||
SkeletonData* _data;
|
||||
const SkeletonData& _data;
|
||||
SimpleArray<Bone*> _bones;
|
||||
SimpleArray<Slot*> _slots;
|
||||
SimpleArray<Slot*> _drawOrder;
|
||||
SimpleArray<IkConstraint*> _ikConstraints;
|
||||
SimpleArray<TransformConstraint*> _transformConstraints;
|
||||
SimpleArray<PathConstraint*> _pathConstraints;
|
||||
SimpleArray<IUpdatable*> _updateCache = new SimpleArray<IUpdatable>();
|
||||
SimpleArray<Bone*> _updateCacheReset = new SimpleArray<Bone>();
|
||||
Skin _skin;
|
||||
SimpleArray<Updatable*> _updateCache;
|
||||
SimpleArray<Bone*> _updateCacheReset;
|
||||
Skin* _skin;
|
||||
float _r = 1, _g = 1, _b = 1, _a = 1;
|
||||
float _time;
|
||||
bool _flipX, _flipY;
|
||||
float _x, _y;
|
||||
|
||||
void sortIkConstraint(IkConstraint constraint)
|
||||
{
|
||||
Bone target = constraint.target;
|
||||
sortBone(target);
|
||||
void sortIkConstraint(IkConstraint constraint);
|
||||
|
||||
var constrained = constraint.bones;
|
||||
Bone parent = constrained.Items[0];
|
||||
sortBone(parent);
|
||||
void sortPathConstraint(PathConstraint constraint);
|
||||
|
||||
if (constrained.Count > 1)
|
||||
{
|
||||
Bone child = constrained.Items[constrained.Count - 1];
|
||||
if (!updateCache.Contains(child))
|
||||
{
|
||||
updateCacheReset.Add(child);
|
||||
}
|
||||
}
|
||||
void sortTransformConstraint(TransformConstraint constraint);
|
||||
|
||||
updateCache.Add(constraint);
|
||||
void sortPathConstraintAttachment(Skin skin, int slotIndex, Bone slotBone);
|
||||
|
||||
sortReset(parent.children);
|
||||
constrained.Items[constrained.Count - 1].sorted = true;
|
||||
}
|
||||
void sortPathConstraintAttachment(Attachment attachment, Bone slotBone);
|
||||
|
||||
void sortPathConstraint(PathConstraint constraint)
|
||||
{
|
||||
Slot slot = constraint.target;
|
||||
int slotIndex = slot.data.index;
|
||||
Bone slotBone = slot.bone;
|
||||
if (skin != null)
|
||||
{
|
||||
sortPathConstraintAttachment(skin, slotIndex, slotBone);
|
||||
}
|
||||
void sortBone(Bone bone);
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
foreach (var entry in skin.Attachments)
|
||||
{
|
||||
if (entry.Key.slotIndex == slotIndex)
|
||||
{
|
||||
sortPathConstraintAttachment(entry.Value, 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
static void sortReset(SimpleArray<Bone*>& bones);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -38,6 +38,18 @@
|
||||
|
||||
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(),
|
||||
_data(data),
|
||||
_skeleton(skeleton),
|
||||
@ -106,6 +118,13 @@ namespace Spine
|
||||
lb = -lb;
|
||||
}
|
||||
|
||||
if (_skeleton.isFlipY() != Bone::isYDown())
|
||||
{
|
||||
y = -y;
|
||||
lc = -lc;
|
||||
ld = -ld;
|
||||
}
|
||||
|
||||
_a = la;
|
||||
_b = lb;
|
||||
_c = lc;
|
||||
@ -224,6 +243,12 @@ namespace Spine
|
||||
_a = -_a;
|
||||
_b = -_b;
|
||||
}
|
||||
|
||||
if (skeleton.isFlipY() != Bone::isYDown())
|
||||
{
|
||||
c = -c;
|
||||
d = -d;
|
||||
}
|
||||
}
|
||||
|
||||
void Bone::setToSetupPose()
|
||||
|
||||
@ -35,7 +35,7 @@ namespace Spine
|
||||
IkConstraintData::IkConstraintData(std::string name) :
|
||||
_name(name),
|
||||
_order(0),
|
||||
_target(nullptr),
|
||||
_target(NULL),
|
||||
_bendDirection(1),
|
||||
_mix(1)
|
||||
{
|
||||
|
||||
@ -40,7 +40,7 @@ namespace Spine
|
||||
PathConstraintData::PathConstraintData(std::string name) :
|
||||
_name(name),
|
||||
_order(0),
|
||||
_target(nullptr),
|
||||
_target(NULL),
|
||||
_positionMode(PositionMode_Fixed),
|
||||
_spacingMode(SpacingMode_Length),
|
||||
_rotateMode(RotateMode_Tangent),
|
||||
|
||||
71
spine-cpp/spine-cpp/src/spine/RTTI.cpp
Normal file
71
spine-cpp/spine-cpp/src/spine/RTTI.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -38,8 +38,786 @@
|
||||
#include <spine/PathConstraint.h>
|
||||
#include <spine/TransformConstraint.h>
|
||||
#include <spine/Skin.h>
|
||||
#include <spine/Attachment.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ namespace Spine
|
||||
{
|
||||
HashMap<AttachmentKey, Attachment*, HashAttachmentKey>::Iterator i = _attachments.find(AttachmentKey(slotIndex, name));
|
||||
|
||||
Attachment* ret = nullptr;
|
||||
Attachment* ret = NULL;
|
||||
|
||||
if (i != _attachments.end())
|
||||
{
|
||||
@ -118,7 +118,7 @@ namespace Spine
|
||||
|
||||
if (slot->getAttachment() == i.second())
|
||||
{
|
||||
Attachment* attachment = nullptr;
|
||||
Attachment* attachment = NULL;
|
||||
if ((attachment = getAttachment(slotIndex, i.first()._name)))
|
||||
{
|
||||
slot->setAttachment(attachment);
|
||||
|
||||
@ -49,7 +49,7 @@ namespace Spine
|
||||
_g2(0),
|
||||
_b2(0),
|
||||
_hasSecondColor(false),
|
||||
_attachment(nullptr),
|
||||
_attachment(NULL),
|
||||
_attachmentTime(0)
|
||||
{
|
||||
setToSetupPose();
|
||||
@ -65,12 +65,12 @@ namespace Spine
|
||||
std::string attachmentName = _slotData.getAttachmentName();
|
||||
if (attachmentName.length() > 0)
|
||||
{
|
||||
_attachment = nullptr;
|
||||
_attachment = NULL;
|
||||
setAttachment(_skeleton.getAttachment(_slotData.getIndex(), attachmentName));
|
||||
}
|
||||
else
|
||||
{
|
||||
setAttachment(nullptr);
|
||||
setAttachment(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ namespace Spine
|
||||
TransformConstraintData::TransformConstraintData(std::string name) :
|
||||
_name(name),
|
||||
_order(0),
|
||||
_target(nullptr),
|
||||
_target(NULL),
|
||||
_rotateMix(0),
|
||||
_translateMix(0),
|
||||
_scaleMix(0),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user