diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index 9cc0b5d48..1657b74a9 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -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; diff --git a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h new file mode 100644 index 000000000..33156e7ef --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -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 +#include + +namespace Spine +{ + class ContainerUtil + { + public: + template + static void cleanUpSimpleArrayOfPointers(SimpleArray& items) + { + for (size_t i = 0; i < items.size(); ) + { + T* item = items[i]; + delete item; + + items.erase(i); + } + } + + template + static void cleanUpHashMapOfPointers(HashMap& hashMap) + { + for (typename HashMap::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__) */ diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h index e159e4d4a..0eaff11df 100755 --- a/spine-cpp/spine-cpp/include/spine/HashMap.h +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -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) diff --git a/spine-cpp/spine-cpp/include/spine/MathUtil.h b/spine-cpp/spine-cpp/include/spine/MathUtil.h index 0eeb27f2c..a87a42d04 100644 --- a/spine-cpp/spine-cpp/include/spine/MathUtil.h +++ b/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -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 { diff --git a/spine-cpp/spine-cpp/include/spine/RTTI.h b/spine-cpp/spine-cpp/include/spine/RTTI.h new file mode 100644 index 000000000..79f413efa --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/RTTI.h @@ -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 + +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 */ + diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index 93ecaecc8..99022c939 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -32,8 +32,10 @@ #define Spine_Skeleton_h #include +#include #include +#include // 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 getBones(); - SimpleArray getUpdateCacheList(); - SimpleArray getSlots(); - SimpleArray getDrawOrder(); - SimpleArray getIkConstraints(); - SimpleArray getPathConstraints(); - SimpleArray 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(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(data.slots.Count); - drawOrder = new SimpleArray(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(data.ikConstraints.Count); - foreach (IkConstraintData ikConstraintData in data.ikConstraints) - ikConstraints.Add(new IkConstraint(ikConstraintData, this)); - - transformConstraints = new SimpleArray(data.transformConstraints.Count); - foreach (TransformConstraintData transformConstraintData in data.transformConstraints) - transformConstraints.Add(new TransformConstraint(transformConstraintData, this)); - - pathConstraints = new SimpleArray (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 updateCache = this.updateCache; - updateCache.Clear(); - this.updateCacheReset.Clear(); - - SimpleArray bones = this.bones; - for (int i = 0, n = bones.Count; i < n; i++) - { - bones.Items[i].sorted = false; - } - - SimpleArray 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]); - } - } + void updateCache(); - /// 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(); - } - - var ikConstraintsItems = this.ikConstraints.Items; - for (int i = 0, n = ikConstraints.Count; i < n; i++) - { - IkConstraint constraint = ikConstraintsItems[i]; - constraint.bendDirection = constraint.data.bendDirection; - constraint.mix = constraint.data.mix; - } - - var transformConstraintsItems = this.transformConstraints.Items; - for (int i = 0, n = transformConstraints.Count; i < n; i++) - { - TransformConstraint constraint = transformConstraintsItems[i]; - TransformConstraintData constraintData = constraint.data; - constraint.rotateMix = constraintData.rotateMix; - constraint.translateMix = constraintData.translateMix; - constraint.scaleMix = constraintData.scaleMix; - constraint.shearMix = constraintData.shearMix; - } - - var pathConstraintItems = this.pathConstraints.Items; - for (int i = 0, n = pathConstraints.Count; i < n; i++) - { - PathConstraint constraint = pathConstraintItems[i]; - PathConstraintData constraintData = constraint.data; - constraint.position = constraintData.position; - constraint.spacing = constraintData.spacing; - constraint.rotateMix = constraintData.rotateMix; - constraint.translateMix = constraintData.translateMix; - } - } + void setBonesToSetupPose(); - void setSlotsToSetupPose() - { - var slots = this.slots; - var slotsItems = slots.Items; - drawOrder.Clear(); - - for (int i = 0, n = slots.Count; i < n; i++) - { - drawOrder.Add(slotsItems[i]); - } - - for (int i = 0, n = slots.Count; i < n; i++) - { - slotsItems[i].setToSetupPose(); - } - } + void setSlotsToSetupPose(); - /// 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; - } + /// @return May be NULL. + Bone* findBone(std::string boneName); - /// -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; - } + /// @return -1 if the bone was not found. + int findBoneIndex(std::string boneName); - /// 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; - } + /// @return May be NULL. + Slot* findSlot(std::string slotName); - /// -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. /// - /// 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 - /// . - /// Also, often is called before the next time the - /// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. - /// - /// @param newSkin May be null. - void setSkin(Skin newSkin) - { - if (newSkin != null) - { - if (skin != null) - { - newSkin.AttachAll(this, skin); - } - else - { - SimpleArray 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; - } + /// @param newSkin May be NULL. + void setSkin(Skin newSkin); - /// May be null. - Attachment getAttachment(std::string slotName, std::string attachmentName) - { - return getAttachment(data.findSlotIndex(slotName), attachmentName); - } + /// @return May be NULL. + Attachment* getAttachment(std::string slotName, std::string attachmentName); - /// May be null. - Attachment getAttachment(int slotIndex, std::string attachmentName) - { - if (attachmentName == null) - { - throw new ArgumentNullException("attachmentName", "attachmentName cannot be null."); - } - - if (skin != null) - { - Attachment attachment = skin.getAttachment(slotIndex, attachmentName); - if (attachment != null) - { - return attachment; - } - } - - return data.defaultSkin != null ? data.defaultSkin.getAttachment(slotIndex, attachmentName) : null; - } + /// @return May be NULL. + Attachment* getAttachment(int slotIndex, std::string attachmentName); - /// @param attachmentName May be null. - void setAttachment(std::string slotName, std::string attachmentName) - { - if (slotName == null) - { - throw new ArgumentNullException("slotName", "slotName cannot be null."); - } - - SimpleArray 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); - } + /// @param attachmentName May be empty. + void setAttachment(std::string slotName, std::string attachmentName); - /// May be null. - IkConstraint findIkConstraint(std::string constraintName) - { - if (constraintName == null) - { - throw new ArgumentNullException("constraintName", "constraintName cannot be null."); - } - - SimpleArray 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; - } + /// @return May be NULL. + IkConstraint* findIkConstraint(std::string constraintName); - /// May be null. - TransformConstraint findTransformConstraint(std::string constraintName) - { - if (constraintName == null) - { - throw new ArgumentNullException("constraintName", "constraintName cannot be null."); - } - - SimpleArray 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; - } + /// @return May be NULL. + TransformConstraint* findTransformConstraint(std::string constraintName); - /// May be null. - PathConstraint findPathConstraint(std::string constraintName) - { - if (constraintName == null) - { - throw new ArgumentNullException("constraintName", "constraintName cannot be null."); - } - - SimpleArray 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; - } + /// @return May be NULL. + PathConstraint* findPathConstraint(std::string constraintName); - 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]; - } - - mesh.ComputeWorldVertices(slot, 0, verticesLength, temp, 0); - } - } - - if (vertices != null) - { - for (int ii = 0; ii < verticesLength; ii += 2) - { - float vx = vertices[ii], vy = vertices[ii + 1]; - minX = Math.Min(minX, vx); - minY = Math.Min(minY, vy); - maxX = Math.Max(maxX, vx); - maxY = Math.Max(maxY, vy); - } - } - } - - x = minX; - y = minY; - width = maxX - minX; - height = maxY - minY; - vertexBuffer = temp; - } + /// @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& vertexBuffer); + + Bone* getRootBone(); + + const SkeletonData& getData(); + SimpleArray& getBones(); + SimpleArray& getUpdateCacheList(); + SimpleArray& getSlots(); + SimpleArray& getDrawOrder(); + SimpleArray& getIkConstraints(); + SimpleArray& getPathConstraints(); + SimpleArray& getTransformConstraints(); + + 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 _bones; SimpleArray _slots; SimpleArray _drawOrder; SimpleArray _ikConstraints; SimpleArray _transformConstraints; SimpleArray _pathConstraints; - SimpleArray _updateCache = new SimpleArray(); - SimpleArray _updateCacheReset = new SimpleArray(); - Skin _skin; + SimpleArray _updateCache; + SimpleArray _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); - - 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 sortIkConstraint(IkConstraint constraint); - void sortPathConstraint(PathConstraint constraint) - { - Slot slot = constraint.target; - int slotIndex = slot.data.index; - Bone slotBone = slot.bone; - if (skin != null) - { - sortPathConstraintAttachment(skin, slotIndex, slotBone); - } - - if (data.defaultSkin != null && data.defaultSkin != skin) - { - sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone); - } - - for (int ii = 0, nn = data.skins.Count; ii < nn; ii++) - { - sortPathConstraintAttachment(data.skins.Items[ii], slotIndex, slotBone); - } - - Attachment attachment = slot.attachment; - if (attachment is PathAttachment) - { - sortPathConstraintAttachment(attachment, slotBone); - } - - var constrained = constraint.bones; - int boneCount = constrained.Count; - for (int i = 0; i < boneCount; i++) - { - sortBone(constrained.Items[i]); - } - - updateCache.Add(constraint); - - for (int i = 0; i < boneCount; i++) - { - sortReset(constrained.Items[i].children); - } - - for (int i = 0; i < boneCount; i++) - { - constrained.Items[i].sorted = true; - } - } + void sortPathConstraint(PathConstraint constraint); - void sortTransformConstraint(TransformConstraint constraint) - { - sortBone(constraint.target); - - var constrained = constraint.bones; - int boneCount = constrained.Count; - if (constraint.data.local) - { - for (int i = 0; i < boneCount; i++) - { - Bone child = constrained.Items[i]; - sortBone(child.parent); - if (!updateCache.Contains(child)) - { - updateCacheReset.Add(child); - } - } - } - else - { - for (int i = 0; i < boneCount; i++) - { - sortBone(constrained.Items[i]); - } - } - - updateCache.Add(constraint); - - for (int i = 0; i < boneCount; i++) - { - sortReset(constrained.Items[i].children); - } - for (int i = 0; i < boneCount; i++) - { - constrained.Items[i].sorted = true; - } - } + void sortTransformConstraint(TransformConstraint constraint); - 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(Skin skin, int slotIndex, Bone slotBone); - void sortPathConstraintAttachment(Attachment attachment, Bone slotBone) - { - if (!(attachment is PathAttachment)) return; - int[] pathBones = ((PathAttachment)attachment).bones; - if (pathBones == null) - { - sortBone(slotBone); - } - else - { - var bones = this.bones; - for (int i = 0, n = pathBones.Length; i < n;) - { - int nn = pathBones[i++]; - nn += i; - while (i < nn) - { - sortBone(bones.Items[pathBones[i++]]); - } - } - } - } + void sortPathConstraintAttachment(Attachment attachment, Bone slotBone); - void sortBone(Bone bone) - { - if (bone.sorted) - { - return; - } - - Bone parent = bone.parent; - if (parent != null) sortBone(parent); - bone.sorted = true; - updateCache.Add(bone); - } + void sortBone(Bone bone); - static void sortReset(SimpleArray& 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& bones); }; } diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index 21b275a6a..1e3882573 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -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() diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp index 36d16b307..70158d296 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -35,7 +35,7 @@ namespace Spine IkConstraintData::IkConstraintData(std::string name) : _name(name), _order(0), - _target(nullptr), + _target(NULL), _bendDirection(1), _mix(1) { diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp index a9e1d07ef..9a82bcbf5 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -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), diff --git a/spine-cpp/spine-cpp/src/spine/RTTI.cpp b/spine-cpp/spine-cpp/src/spine/RTTI.cpp new file mode 100644 index 000000000..3905c9d6b --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/RTTI.cpp @@ -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 + +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; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index f8e34294a..ad4b6976d 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -38,8 +38,786 @@ #include #include #include +#include namespace Spine { - // TODO + Skeleton::Skeleton(SkeletonData& data) : _data(data) + { + _bones.reserve(_data->getBones().size()); + bones = new SimpleArray(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(data.slots.Count); + drawOrder = new SimpleArray(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(data.ikConstraints.Count); + foreach (IkConstraintData ikConstraintData in data.ikConstraints) + ikConstraints.Add(new IkConstraint(ikConstraintData, this)); + + transformConstraints = new SimpleArray(data.transformConstraints.Count); + foreach (TransformConstraintData transformConstraintData in data.transformConstraints) + transformConstraints.Add(new TransformConstraint(transformConstraintData, this)); + + pathConstraints = new SimpleArray (data.pathConstraints.Count); + foreach (PathConstraintData pathConstraintData in data.pathConstraints) + pathConstraints.Add(new PathConstraint(pathConstraintData, this)); + + updateCache(); + updateWorldTransform(); + } + + void Skeleton::updateCache() + { + SimpleArray updateCache = _updateCache; + updateCache.Clear(); + _updateCacheReset.Clear(); + + SimpleArray bones = _bones; + for (int i = 0, n = bones.Count; i < n; ++i) + { + bones.Items[i].sorted = false; + } + + SimpleArray 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 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 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 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 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 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& vertexBuffer) + { + float minX = std::numeric_limits::max(); + float minY = std::numeric_limits::max(); + float maxX = std::numeric_limits::min(); + float maxY = std::numeric_limits::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(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(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& Skeleton::getBones() + { + return _bones; + } + + SimpleArray& Skeleton::getUpdateCacheList() + { + return _updateCache; + } + + SimpleArray& Skeleton::getSlots() + { + return _slots; + } + + SimpleArray& Skeleton::getDrawOrder() + { + return _drawOrder; + } + + SimpleArray& Skeleton::getIkConstraints() + { + return _ikConstraints; + } + + SimpleArray& Skeleton::getPathConstraints() + { + return _pathConstraints; + } + + SimpleArray& 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& bones) + { + for (Bone* i = bones.begin(); i != bones.end(); ++i) + { + Bone* bone = i; + if (bone->isSorted()) + { + sortReset(bone->getChildren()); + } + + bone->setSorted(false); + } + } } diff --git a/spine-cpp/spine-cpp/src/spine/Skin.cpp b/spine-cpp/spine-cpp/src/spine/Skin.cpp index d0a8c2663..949ac6504 100644 --- a/spine-cpp/spine-cpp/src/spine/Skin.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -67,7 +67,7 @@ namespace Spine { HashMap::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); diff --git a/spine-cpp/spine-cpp/src/spine/Slot.cpp b/spine-cpp/spine-cpp/src/spine/Slot.cpp index 6b587cd5d..c9ee69fb1 100644 --- a/spine-cpp/spine-cpp/src/spine/Slot.cpp +++ b/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -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); } } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp index b3d0006fd..d67e2e1b9 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -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),