mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 22:34:53 +08:00
wip
This commit is contained in:
parent
af243b4922
commit
072ada4c5c
@ -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;
|
||||||
|
|||||||
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);
|
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)
|
||||||
|
|||||||
@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
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
|
#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;
|
/// Updates the world transform for each bone and applies constraints.
|
||||||
for (int i = 0, n = bones.Count; i < n; i++)
|
void updateWorldTransform();
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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;
|
void setSlotsToSetupPose();
|
||||||
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;
|
/// @return May be NULL.
|
||||||
for (int i = 0, n = transformConstraints.Count; i < n; i++)
|
Bone* findBone(std::string boneName);
|
||||||
{
|
|
||||||
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;
|
/// @return -1 if the bone was not found.
|
||||||
for (int i = 0, n = pathConstraints.Count; i < n; i++)
|
int findBoneIndex(std::string boneName);
|
||||||
{
|
|
||||||
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()
|
/// @return May be NULL.
|
||||||
{
|
Slot* findSlot(std::string slotName);
|
||||||
var slots = this.slots;
|
|
||||||
var slotsItems = slots.Items;
|
|
||||||
drawOrder.Clear();
|
|
||||||
|
|
||||||
for (int i = 0, n = slots.Count; i < n; i++)
|
/// @return -1 if the bone was not found.
|
||||||
{
|
int findSlotIndex(std::string slotName);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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;
|
/// @return May be NULL.
|
||||||
}
|
Attachment* getAttachment(std::string slotName, std::string attachmentName);
|
||||||
|
|
||||||
/// May be null.
|
/// @return May be NULL.
|
||||||
Attachment getAttachment(std::string slotName, std::string attachmentName)
|
Attachment* getAttachment(int slotIndex, std::string attachmentName);
|
||||||
{
|
|
||||||
return getAttachment(data.findSlotIndex(slotName), attachmentName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// May be null.
|
/// @param attachmentName May be empty.
|
||||||
Attachment getAttachment(int slotIndex, std::string attachmentName)
|
void setAttachment(std::string slotName, std::string attachmentName);
|
||||||
{
|
|
||||||
if (attachmentName == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("attachmentName", "attachmentName cannot be null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skin != null)
|
/// @return May be NULL.
|
||||||
{
|
IkConstraint* findIkConstraint(std::string constraintName);
|
||||||
Attachment attachment = skin.getAttachment(slotIndex, attachmentName);
|
|
||||||
if (attachment != null)
|
|
||||||
{
|
|
||||||
return attachment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.defaultSkin != null ? data.defaultSkin.getAttachment(slotIndex, attachmentName) : null;
|
/// @return May be NULL.
|
||||||
}
|
TransformConstraint* findTransformConstraint(std::string constraintName);
|
||||||
|
|
||||||
/// @param attachmentName May be null.
|
/// @return May be NULL.
|
||||||
void setAttachment(std::string slotName, std::string attachmentName)
|
PathConstraint* findPathConstraint(std::string constraintName);
|
||||||
{
|
|
||||||
if (slotName == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("slotName", "slotName cannot be null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleArray<Slot> slots = this.slots;
|
void update(float delta);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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;
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh.ComputeWorldVertices(slot, 0, verticesLength, temp, 0);
|
Bone* getRootBone();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vertices != null)
|
const SkeletonData& getData();
|
||||||
{
|
SimpleArray<Bone*>& getBones();
|
||||||
for (int ii = 0; ii < verticesLength; ii += 2)
|
SimpleArray<Updatable*>& getUpdateCacheList();
|
||||||
{
|
SimpleArray<Slot*>& getSlots();
|
||||||
float vx = vertices[ii], vy = vertices[ii + 1];
|
SimpleArray<Slot*>& getDrawOrder();
|
||||||
minX = Math.Min(minX, vx);
|
SimpleArray<IkConstraint*>& getIkConstraints();
|
||||||
minY = Math.Min(minY, vy);
|
SimpleArray<PathConstraint*>& getPathConstraints();
|
||||||
maxX = Math.Max(maxX, vx);
|
SimpleArray<TransformConstraint*>& getTransformConstraints();
|
||||||
maxY = Math.Max(maxY, vy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
x = minX;
|
Skin* getSkin();
|
||||||
y = minY;
|
void setSkin(Skin* inValue);
|
||||||
width = maxX - minX;
|
float getR();
|
||||||
height = maxY - minY;
|
void setR(float inValue);
|
||||||
vertexBuffer = temp;
|
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:
|
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;
|
void sortPathConstraint(PathConstraint constraint);
|
||||||
Bone parent = constrained.Items[0];
|
|
||||||
sortBone(parent);
|
|
||||||
|
|
||||||
if (constrained.Count > 1)
|
void sortTransformConstraint(TransformConstraint constraint);
|
||||||
{
|
|
||||||
Bone child = constrained.Items[constrained.Count - 1];
|
|
||||||
if (!updateCache.Contains(child))
|
|
||||||
{
|
|
||||||
updateCacheReset.Add(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateCache.Add(constraint);
|
void sortPathConstraintAttachment(Skin skin, int slotIndex, Bone slotBone);
|
||||||
|
|
||||||
sortReset(parent.children);
|
void sortPathConstraintAttachment(Attachment attachment, Bone slotBone);
|
||||||
constrained.Items[constrained.Count - 1].sorted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sortPathConstraint(PathConstraint constraint)
|
void sortBone(Bone bone);
|
||||||
{
|
|
||||||
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)
|
static void sortReset(SimpleArray<Bone*>& bones);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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),
|
||||||
|
|||||||
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/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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user