mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
Posed hierarchy changes
This commit is contained in:
parent
922e94485c
commit
f2e6b9095f
@ -123,6 +123,8 @@ namespace spine {
|
||||
static int search(Vector<float> &values, float target);
|
||||
|
||||
static int search(Vector<float> &values, float target, int step);
|
||||
|
||||
Vector<int> &getBones();
|
||||
private:
|
||||
Vector<Timeline *> _timelines;
|
||||
HashMap<PropertyId, bool> _timelineIds;
|
||||
|
||||
@ -42,7 +42,7 @@ namespace spine {
|
||||
/// A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a
|
||||
/// local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a
|
||||
/// constraint or application code modifies the world transform after it was computed from the local transform.
|
||||
class SP_API Bone : public PosedActive<BoneData, BoneLocal, BonePose> {
|
||||
class SP_API Bone : public PosedActiveGeneric<BoneData, BoneLocal, BonePose> {
|
||||
friend class AnimationState;
|
||||
friend class RotateTimeline;
|
||||
friend class IkConstraint;
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include <spine/PosedActive.h>
|
||||
#include <spine/Update.h>
|
||||
#include <spine/RTTI.h>
|
||||
#include <spine/ConstraintData.h>
|
||||
|
||||
namespace spine {
|
||||
class Skeleton;
|
||||
@ -42,14 +43,16 @@ namespace spine {
|
||||
public:
|
||||
Constraint();
|
||||
virtual ~Constraint();
|
||||
|
||||
ConstraintData &getData();
|
||||
};
|
||||
|
||||
template<class T, class D, class P>
|
||||
class SP_API ConstraintGeneric : public PosedActive<D, P, P>, public Constraint {
|
||||
class SP_API ConstraintGeneric : public PosedActiveGeneric<D, P, P>, public Constraint {
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
ConstraintGeneric(D& data) : PosedActive<D, P, P>(data), Constraint() {
|
||||
ConstraintGeneric(D& data) : PosedActiveGeneric<D, P, P>(data), Constraint() {
|
||||
}
|
||||
|
||||
virtual ~ConstraintGeneric() {
|
||||
|
||||
@ -55,20 +55,14 @@ namespace spine {
|
||||
friend class SkeletonJson;
|
||||
|
||||
public:
|
||||
ConstraintDataGeneric(const String &name);
|
||||
virtual ~ConstraintDataGeneric();
|
||||
ConstraintDataGeneric(const String &name) : PosedData<P>(name), ConstraintData(name) {
|
||||
}
|
||||
virtual ~ConstraintDataGeneric() {
|
||||
}
|
||||
|
||||
/// Creates a constraint instance.
|
||||
virtual T* create(Skeleton& skeleton) = 0;
|
||||
};
|
||||
|
||||
template<class T, class P>
|
||||
ConstraintDataGeneric<T, P>::ConstraintDataGeneric(const String &name) : PosedData<P>(name), ConstraintData(name) {
|
||||
}
|
||||
|
||||
template<class T, class P>
|
||||
ConstraintDataGeneric<T, P>::~ConstraintDataGeneric() {
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Spine_ConstraintData_h */
|
||||
|
||||
@ -38,6 +38,12 @@ namespace spine {
|
||||
public:
|
||||
Posed() {}
|
||||
virtual ~Posed() {}
|
||||
|
||||
virtual void resetApplied() = 0;
|
||||
|
||||
virtual void pose() = 0;
|
||||
|
||||
virtual void constrained() = 0;
|
||||
};
|
||||
|
||||
template<class D, class P, class A>
|
||||
@ -72,16 +78,10 @@ namespace spine {
|
||||
friend class InheritTimeline;
|
||||
|
||||
public:
|
||||
Posed(D& data) : _data(data), _pose(), _constrained() {
|
||||
static_assert(std::is_base_of<P, A>::value, "A must extend P");
|
||||
// Match Java behavior: applied initially points to pose
|
||||
// Note: Both _pose and _constrained are stored as type A to match Java's
|
||||
// "new BonePose(), new BonePose()" pattern. For most classes P==A, but
|
||||
// Bone uses P=BoneLocal, A=BonePose where BonePose extends BoneLocal.
|
||||
_applied = &_pose;
|
||||
PosedGeneric(D &data) : _data(data), _pose(), _constrained(), _applied(&_pose) {
|
||||
}
|
||||
|
||||
virtual ~Posed() {
|
||||
virtual ~PosedGeneric() {
|
||||
}
|
||||
|
||||
void setupPose() {
|
||||
@ -103,12 +103,24 @@ namespace spine {
|
||||
return *_applied;
|
||||
}
|
||||
|
||||
virtual void resetApplied() {
|
||||
_constrained.set(_pose);
|
||||
}
|
||||
|
||||
virtual void pose() {
|
||||
_applied = &_pose;
|
||||
}
|
||||
|
||||
virtual void constrained() {
|
||||
_applied = &_constrained;
|
||||
}
|
||||
|
||||
protected:
|
||||
D &_data;
|
||||
A _pose; ///< Stored as A type (concrete pose type) to match Java behavior
|
||||
A _constrained;///< Stored as A type (concrete pose type) to match Java behavior
|
||||
A *_applied; ///< Points to either _pose or _constrained, reassignable like Java
|
||||
};
|
||||
}
|
||||
}// namespace spine
|
||||
|
||||
#endif /* Spine_Posed_h */
|
||||
@ -35,33 +35,22 @@
|
||||
|
||||
namespace spine {
|
||||
|
||||
class SP_API PosedActive {
|
||||
public:
|
||||
PosedActive() {}
|
||||
virtual ~PosedActive() {}
|
||||
|
||||
/// Returns false when this constraint won't be updated by
|
||||
/// Skeleton::updateWorldTransform() because a skin is required and the
|
||||
/// active skin does not contain this item.
|
||||
/// @see Skin::getBones()
|
||||
/// @see Skin::getConstraints()
|
||||
/// @see PosedData::getSkinRequired()
|
||||
/// @see Skeleton::updateCache()
|
||||
bool isActive();
|
||||
|
||||
protected:
|
||||
bool _active;
|
||||
};
|
||||
|
||||
template<class D, class P, class A>
|
||||
class SP_API PosedActiveGeneric : public PosedGeneric<D, P, A> {
|
||||
friend class SlotCurveTimeline;
|
||||
|
||||
public:
|
||||
PosedActive(D &data): PosedGeneric<D, P, A>(data), _active(false) {
|
||||
PosedActiveGeneric(D &data): PosedGeneric<D, P, A>(data), _active(false) {
|
||||
this->setupPose();
|
||||
}
|
||||
virtual ~PosedActive() {}
|
||||
virtual ~PosedActiveGeneric() {}
|
||||
|
||||
bool isActive() {
|
||||
return _active;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool _active;
|
||||
};
|
||||
}// namespace spine
|
||||
|
||||
|
||||
@ -298,21 +298,20 @@ namespace spine {
|
||||
void update(float delta);
|
||||
|
||||
protected:
|
||||
Vector<Update *> _updateCache;
|
||||
|
||||
private:
|
||||
SkeletonData &_data;
|
||||
Vector<Bone *> _bones;
|
||||
Vector<Slot *> _slots;
|
||||
Vector<Slot *> _drawOrder;
|
||||
Vector<Constraint *> _constraints;
|
||||
Vector<PhysicsConstraint *> _physics;
|
||||
Vector<Update *> _updateCache;
|
||||
Vector<Posed *> _resetCache;
|
||||
Skin *_skin;
|
||||
Color _color;
|
||||
float _scaleX, _scaleY;
|
||||
float _x, _y;
|
||||
float _time;
|
||||
float _scaleX, _scaleY;
|
||||
float _windX, _windY, _gravityX, _gravityY;
|
||||
float _time;
|
||||
int _update;
|
||||
};
|
||||
}// namespace spine
|
||||
|
||||
@ -118,8 +118,7 @@ void Animation::setTimelines(Vector<Timeline *> &timelines) {
|
||||
_timelineIds.put(propertyIds[ii], true);
|
||||
}
|
||||
|
||||
BoneTimeline *boneTimeline = timeline->getRTTI().instanceOf(BoneTimeline1::rtti) ?
|
||||
static_cast<BoneTimeline1 *>(timeline) : NULL;
|
||||
BoneTimeline *boneTimeline = timeline->getRTTI().instanceOf(BoneTimeline1::rtti) ? static_cast<BoneTimeline1 *>(timeline) : NULL;
|
||||
if (boneTimeline) {
|
||||
int boneIndex = boneTimeline->getBoneIndex();
|
||||
if (!boneSet.containsKey(boneIndex)) {
|
||||
|
||||
@ -36,7 +36,7 @@ using namespace spine;
|
||||
|
||||
RTTI_IMPL_NOPARENT(Bone)
|
||||
|
||||
Bone::Bone(BoneData& data, Bone* parent) : PosedActive(data),
|
||||
Bone::Bone(BoneData &data, Bone *parent) : PosedActiveGeneric(data),
|
||||
_parent(parent),
|
||||
_children(),
|
||||
_sorted(false) {
|
||||
|
||||
@ -42,8 +42,7 @@ RTTI_IMPL_NOPARENT(BoneTimeline)
|
||||
|
||||
RTTI_IMPL(BoneTimeline1, CurveTimeline1)
|
||||
|
||||
BoneTimeline1::BoneTimeline1(size_t frameCount, size_t bezierCount, int boneIndex, Property property) :
|
||||
BoneTimeline(boneIndex),
|
||||
BoneTimeline1::BoneTimeline1(size_t frameCount, size_t bezierCount, int boneIndex, Property property) : BoneTimeline(boneIndex),
|
||||
CurveTimeline1(frameCount, bezierCount) {
|
||||
PropertyId ids[] = {((PropertyId) property << 32) | boneIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
@ -62,8 +61,7 @@ void BoneTimeline1::apply(Skeleton &skeleton, float lastTime, float time, Vector
|
||||
|
||||
RTTI_IMPL(BoneTimeline2, CurveTimeline2)
|
||||
|
||||
BoneTimeline2::BoneTimeline2(size_t frameCount, size_t bezierCount, int boneIndex, Property property1, Property property2) :
|
||||
BoneTimeline(boneIndex),
|
||||
BoneTimeline2::BoneTimeline2(size_t frameCount, size_t bezierCount, int boneIndex, Property property1, Property property2) : BoneTimeline(boneIndex),
|
||||
CurveTimeline2(frameCount, bezierCount) {
|
||||
PropertyId ids[] = {((PropertyId) property1 << 32) | boneIndex, ((PropertyId) property2 << 32) | boneIndex};
|
||||
setPropertyIds(ids, 2);
|
||||
|
||||
@ -249,8 +249,7 @@ void IkConstraint::apply(Skeleton& skeleton, BonePose& parent, BonePose& child,
|
||||
child._rotation += a2 * mix;
|
||||
}
|
||||
|
||||
IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) :
|
||||
ConstraintGeneric<IkConstraint, IkConstraintData, IkConstraintPose>(data),
|
||||
IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : ConstraintGeneric<IkConstraint, IkConstraintData, IkConstraintPose>(data),
|
||||
_target(skeleton.findBone(data.getTarget()->getName())) {
|
||||
|
||||
_bones.ensureCapacity(data.getBones().size());
|
||||
@ -299,8 +298,8 @@ void IkConstraint::sort(Skeleton& skeleton) {
|
||||
skeleton._updateCache.add(this);
|
||||
parent->_sorted = false;
|
||||
skeleton.sortReset(parent->_children);
|
||||
skeleton.constrained(parent);
|
||||
if (_bones.size() > 1) skeleton.constrained(_bones[1]->_bone);
|
||||
skeleton.constrained(*parent);
|
||||
if (_bones.size() > 1) skeleton.constrained(*_bones[1]->_bone);
|
||||
}
|
||||
|
||||
bool IkConstraint::isSourceActive() {
|
||||
|
||||
@ -51,8 +51,7 @@ const int PathConstraint::NONE = -1;
|
||||
const int PathConstraint::BEFORE = -2;
|
||||
const int PathConstraint::AFTER = -3;
|
||||
|
||||
PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) :
|
||||
ConstraintGeneric<PathConstraint, PathConstraintData, PathConstraintPose>(data),
|
||||
PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : ConstraintGeneric<PathConstraint, PathConstraintData, PathConstraintPose>(data),
|
||||
_slot(skeleton._slots.buffer()[data._slot->_index]) {
|
||||
|
||||
_bones.ensureCapacity(data.getBones().size());
|
||||
|
||||
@ -41,8 +41,7 @@ using namespace spine;
|
||||
|
||||
RTTI_IMPL(PhysicsConstraint, Constraint)
|
||||
|
||||
PhysicsConstraint::PhysicsConstraint(PhysicsConstraintData &data, Skeleton &skeleton) :
|
||||
ConstraintGeneric<PhysicsConstraint, PhysicsConstraintData, PhysicsConstraintPose>(data),
|
||||
PhysicsConstraint::PhysicsConstraint(PhysicsConstraintData &data, Skeleton &skeleton) : ConstraintGeneric<PhysicsConstraint, PhysicsConstraintData, PhysicsConstraintPose>(data),
|
||||
_reset(true), _ux(0), _uy(0), _cx(0), _cy(0), _tx(0), _ty(0),
|
||||
_xOffset(0), _xLag(0), _xVelocity(0), _yOffset(0), _yLag(0), _yVelocity(0),
|
||||
_rotateOffset(0), _rotateLag(0), _rotateVelocity(0), _scaleOffset(0), _scaleLag(0), _scaleVelocity(0),
|
||||
@ -60,9 +59,9 @@ PhysicsConstraint* PhysicsConstraint::copy(Skeleton& skeleton) {
|
||||
void PhysicsConstraint::sort(Skeleton &skeleton) {
|
||||
Bone *bone = _bone->_bone;
|
||||
skeleton.sortBone(bone);
|
||||
skeleton.updateCache.add(this);
|
||||
skeleton._updateCache.add(this);
|
||||
skeleton.sortReset(bone->_children);
|
||||
skeleton.constrained(bone);
|
||||
skeleton.constrained(*bone);
|
||||
}
|
||||
|
||||
bool PhysicsConstraint::isSourceActive() {
|
||||
@ -127,12 +126,14 @@ void PhysicsConstraint::update(Skeleton& skeleton, Physics physics) {
|
||||
if (x || y) {
|
||||
if (x) {
|
||||
float u = (_ux - bx) * i;
|
||||
_xOffset += u > qx ? qx : u < -qx ? -qx : u;
|
||||
_xOffset += u > qx ? qx : u < -qx ? -qx
|
||||
: u;
|
||||
_ux = bx;
|
||||
}
|
||||
if (y) {
|
||||
float u = (_uy - by) * i;
|
||||
_yOffset += u > qy ? qy : u < -qy ? -qy : u;
|
||||
_yOffset += u > qy ? qy : u < -qy ? -qy
|
||||
: u;
|
||||
_uy = by;
|
||||
}
|
||||
if (a >= t) {
|
||||
|
||||
@ -35,8 +35,7 @@ using namespace spine;
|
||||
|
||||
RTTI_IMPL(RotateTimeline, BoneTimeline1)
|
||||
|
||||
RotateTimeline::RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) :
|
||||
BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Rotate) {
|
||||
RotateTimeline::RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Rotate) {
|
||||
}
|
||||
|
||||
void RotateTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend,
|
||||
|
||||
@ -42,8 +42,7 @@ using namespace spine;
|
||||
|
||||
RTTI_IMPL(ScaleTimeline, BoneTimeline2)
|
||||
|
||||
ScaleTimeline::ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex) :
|
||||
BoneTimeline2(frameCount, bezierCount, boneIndex, Property_ScaleX, Property_ScaleY) {
|
||||
ScaleTimeline::ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : BoneTimeline2(frameCount, bezierCount, boneIndex, Property_ScaleX, Property_ScaleY) {
|
||||
}
|
||||
|
||||
void ScaleTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend,
|
||||
@ -144,8 +143,7 @@ void ScaleTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float a
|
||||
|
||||
RTTI_IMPL(ScaleXTimeline, BoneTimeline1)
|
||||
|
||||
ScaleXTimeline::ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) :
|
||||
BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleX) {
|
||||
ScaleXTimeline::ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleX) {
|
||||
}
|
||||
|
||||
void ScaleXTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend,
|
||||
@ -155,8 +153,7 @@ void ScaleXTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float
|
||||
|
||||
RTTI_IMPL(ScaleYTimeline, BoneTimeline1)
|
||||
|
||||
ScaleYTimeline::ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) :
|
||||
BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleY) {
|
||||
ScaleYTimeline::ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleY) {
|
||||
}
|
||||
|
||||
void ScaleYTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend,
|
||||
|
||||
@ -42,8 +42,7 @@ using namespace spine;
|
||||
|
||||
RTTI_IMPL(ShearTimeline, BoneTimeline2)
|
||||
|
||||
ShearTimeline::ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex) :
|
||||
BoneTimeline2(frameCount, bezierCount, boneIndex, Property_ShearX, Property_ShearY) {
|
||||
ShearTimeline::ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : BoneTimeline2(frameCount, bezierCount, boneIndex, Property_ShearX, Property_ShearY) {
|
||||
}
|
||||
|
||||
void ShearTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend,
|
||||
@ -106,8 +105,7 @@ void ShearTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float a
|
||||
|
||||
RTTI_IMPL(ShearXTimeline, BoneTimeline1)
|
||||
|
||||
ShearXTimeline::ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) :
|
||||
BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearX) {
|
||||
ShearXTimeline::ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearX) {
|
||||
}
|
||||
|
||||
void ShearXTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend,
|
||||
@ -117,8 +115,7 @@ void ShearXTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float
|
||||
|
||||
RTTI_IMPL(ShearYTimeline, BoneTimeline1)
|
||||
|
||||
ShearYTimeline::ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) :
|
||||
BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearY) {
|
||||
ShearYTimeline::ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearY) {
|
||||
}
|
||||
|
||||
void ShearYTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend,
|
||||
|
||||
569
spine-cpp/spine-cpp/src/spine/SkeletonNew.cpp
Normal file
569
spine-cpp/spine-cpp/src/spine/SkeletonNew.cpp
Normal file
@ -0,0 +1,569 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated April 5, 2025. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2025, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/SkeletonData.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/ConstraintData.h>
|
||||
#include <spine/PhysicsConstraintData.h>
|
||||
#include <spine/IkConstraintData.h>
|
||||
#include <spine/PathConstraintData.h>
|
||||
#include <spine/TransformConstraintData.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/IkConstraint.h>
|
||||
#include <spine/PathConstraint.h>
|
||||
#include <spine/PhysicsConstraint.h>
|
||||
#include <spine/TransformConstraint.h>
|
||||
#include <spine/Skin.h>
|
||||
#include <spine/Attachment.h>
|
||||
#include <spine/RegionAttachment.h>
|
||||
#include <spine/MeshAttachment.h>
|
||||
#include <spine/ClippingAttachment.h>
|
||||
#include <spine/SkeletonClipping.h>
|
||||
#include <spine/MathUtil.h>
|
||||
#include <spine/BonePose.h>
|
||||
#include <spine/SlotPose.h>
|
||||
#include <spine/Posed.h>
|
||||
#include <spine/Update.h>
|
||||
#include <float.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
static const unsigned short quadTriangles[] = {0, 1, 2, 2, 3, 0};
|
||||
|
||||
Skeleton::Skeleton(SkeletonData &skeletonData) : _data(skeletonData), _skin(NULL), _color(1, 1, 1, 1),
|
||||
_scaleX(1), _scaleY(1), _x(0), _y(0), _time(0), _windX(1), _windY(0), _gravityX(0), _gravityY(1), _update(0) {
|
||||
|
||||
// Create bones
|
||||
_bones.ensureCapacity(_data.getBones().size());
|
||||
Vector<BoneData *> &boneDataArray = _data.getBones();
|
||||
for (size_t i = 0; i < boneDataArray.size(); ++i) {
|
||||
BoneData *boneData = boneDataArray[i];
|
||||
Bone *bone;
|
||||
if (boneData->getParent() == NULL) {
|
||||
bone = new (__FILE__, __LINE__) Bone(*boneData, NULL);
|
||||
} else {
|
||||
Bone *parent = _bones[boneData->getParent()->getIndex()];
|
||||
bone = new (__FILE__, __LINE__) Bone(*boneData, parent);
|
||||
parent->getChildren().add(bone);
|
||||
}
|
||||
_bones.add(bone);
|
||||
}
|
||||
|
||||
// Create slots
|
||||
_slots.ensureCapacity(_data.getSlots().size());
|
||||
_drawOrder.ensureCapacity(_data.getSlots().size());
|
||||
Vector<SlotData *> &slotDataArray = _data.getSlots();
|
||||
for (size_t i = 0; i < slotDataArray.size(); ++i) {
|
||||
SlotData *slotData = slotDataArray[i];
|
||||
Slot *slot = new (__FILE__, __LINE__) Slot(*slotData, *this);
|
||||
_slots.add(slot);
|
||||
_drawOrder.add(slot);
|
||||
}
|
||||
|
||||
// Create constraints and physics
|
||||
_physics.ensureCapacity(8);
|
||||
_constraints.ensureCapacity(_data.getConstraints().size());
|
||||
Vector<ConstraintData *> &constraintDataArray = _data.getConstraints();
|
||||
for (size_t i = 0; i < constraintDataArray.size(); ++i) {
|
||||
ConstraintData *constraintData = constraintDataArray[i];
|
||||
Constraint *constraint = constraintData->create(*this);
|
||||
PhysicsConstraint *physicsConstraint = dynamic_cast<PhysicsConstraint *>(constraint);
|
||||
if (physicsConstraint != NULL) {
|
||||
_physics.add(physicsConstraint);
|
||||
}
|
||||
_constraints.add(constraint);
|
||||
}
|
||||
_physics.shrink();
|
||||
|
||||
updateCache();
|
||||
}
|
||||
|
||||
Skeleton::~Skeleton() {
|
||||
for (size_t i = 0; i < _bones.size(); ++i) {
|
||||
delete _bones[i];
|
||||
}
|
||||
for (size_t i = 0; i < _slots.size(); ++i) {
|
||||
delete _slots[i];
|
||||
}
|
||||
for (size_t i = 0; i < _constraints.size(); ++i) {
|
||||
delete _constraints[i];
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::updateCache() {
|
||||
_updateCache.clear();
|
||||
|
||||
// Reset slot applied poses to current pose
|
||||
for (size_t i = 0; i < _slots.size(); ++i) {
|
||||
Slot *slot = _slots[i];
|
||||
slot->getAppliedPose().set(slot->getPose());
|
||||
}
|
||||
|
||||
// Mark bones based on skin requirements
|
||||
size_t boneCount = _bones.size();
|
||||
for (size_t i = 0; i < boneCount; ++i) {
|
||||
Bone *bone = _bones[i];
|
||||
bone->_sorted = bone->getData().getSkinRequired();
|
||||
bone->_active = !bone->_sorted;
|
||||
bone->getAppliedPose().set(bone->getPose());
|
||||
}
|
||||
|
||||
// Activate bones required by skin
|
||||
if (_skin != NULL) {
|
||||
Vector<BoneData *> &skinBones = _skin->getBones();
|
||||
for (size_t i = 0; i < skinBones.size(); ++i) {
|
||||
Bone *bone = _bones[skinBones[i]->getIndex()];
|
||||
do {
|
||||
bone->_sorted = false;
|
||||
bone->_active = true;
|
||||
bone = bone->getParent();
|
||||
} while (bone != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// Set constraint applied poses and mark active constraints
|
||||
for (size_t i = 0; i < _constraints.size(); ++i) {
|
||||
Constraint *constraint = _constraints[i];
|
||||
constraint->getAppliedPose().set(constraint->getPose());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < _constraints.size(); ++i) {
|
||||
Constraint *constraint = _constraints[i];
|
||||
constraint->_active = constraint->isSourceActive() &&
|
||||
(!constraint->getData().getSkinRequired() || (_skin != NULL && _skin->getConstraints().contains(&constraint->getData(), true)));
|
||||
if (constraint->_active) {
|
||||
constraint->sort(*this);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort all bones
|
||||
for (size_t i = 0; i < boneCount; ++i) {
|
||||
sortBone(_bones[i]);
|
||||
}
|
||||
|
||||
// Replace bone references in update cache with their applied poses
|
||||
for (size_t i = 0; i < _updateCache.size(); ++i) {
|
||||
Update *updateItem = _updateCache[i];
|
||||
Bone *bone = dynamic_cast<Bone *>(updateItem);
|
||||
if (bone != NULL) {
|
||||
_updateCache[i] = &bone->getAppliedPose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::constrained(Posed &object) {
|
||||
if (&object.getPose() == &object.getAppliedPose()) {
|
||||
object.setAppliedPose(object.getConstrainedPose());
|
||||
// Add to reset cache - this would need a resetCache member like Java
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::sortBone(Bone *bone) {
|
||||
if (bone->_sorted || !bone->_active) return;
|
||||
Bone *parent = bone->getParent();
|
||||
if (parent != NULL) sortBone(parent);
|
||||
bone->_sorted = true;
|
||||
_updateCache.add(bone);
|
||||
}
|
||||
|
||||
void Skeleton::sortReset(Vector<Bone *> &bones) {
|
||||
for (size_t i = 0; i < bones.size(); ++i) {
|
||||
Bone *bone = bones[i];
|
||||
if (bone->_active) {
|
||||
if (bone->_sorted) sortReset(bone->getChildren());
|
||||
bone->_sorted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::updateWorldTransform(Physics physics) {
|
||||
_update++;
|
||||
|
||||
// Reset all applied poses to their base poses
|
||||
// This would require a resetCache implementation like Java has
|
||||
|
||||
// Update all items in update cache
|
||||
for (size_t i = 0; i < _updateCache.size(); ++i) {
|
||||
Update *updateItem = _updateCache[i];
|
||||
updateItem->update(*this, physics);
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::updateWorldTransform(Physics physics, BonePose *parent) {
|
||||
if (parent == NULL) return;
|
||||
|
||||
_update++;
|
||||
|
||||
// Reset all applied poses to their base poses
|
||||
// This would require a resetCache implementation like Java has
|
||||
|
||||
// Apply the parent bone transform to the root bone
|
||||
BonePose &rootBone = getRootBone()->getAppliedPose();
|
||||
float pa = parent->getA(), pb = parent->getB(), pc = parent->getC(), pd = parent->getD();
|
||||
rootBone.setWorldX(pa * _x + pb * _y + parent->getWorldX());
|
||||
rootBone.setWorldY(pc * _x + pd * _y + parent->getWorldY());
|
||||
|
||||
float rx = (rootBone.getRotation() + rootBone.getShearX()) * MathUtil::Deg_Rad;
|
||||
float ry = (rootBone.getRotation() + 90 + rootBone.getShearY()) * MathUtil::Deg_Rad;
|
||||
float la = MathUtil::cos(rx) * rootBone.getScaleX();
|
||||
float lb = MathUtil::cos(ry) * rootBone.getScaleY();
|
||||
float lc = MathUtil::sin(rx) * rootBone.getScaleX();
|
||||
float ld = MathUtil::sin(ry) * rootBone.getScaleY();
|
||||
rootBone.setA((pa * la + pb * lc) * _scaleX);
|
||||
rootBone.setB((pa * lb + pb * ld) * _scaleX);
|
||||
rootBone.setC((pc * la + pd * lc) * _scaleY);
|
||||
rootBone.setD((pc * lb + pd * ld) * _scaleY);
|
||||
|
||||
// Update everything except root bone
|
||||
for (size_t i = 0; i < _updateCache.size(); ++i) {
|
||||
Update *updateItem = _updateCache[i];
|
||||
if (updateItem != &rootBone) {
|
||||
updateItem->update(*this, physics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::setupPose() {
|
||||
setupPoseBones();
|
||||
setupPoseSlots();
|
||||
}
|
||||
|
||||
void Skeleton::setupPoseBones() {
|
||||
for (size_t i = 0; i < _bones.size(); ++i) {
|
||||
_bones[i]->setupPose();
|
||||
}
|
||||
for (size_t i = 0; i < _constraints.size(); ++i) {
|
||||
_constraints[i]->setupPose();
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::setupPoseSlots() {
|
||||
// Copy slots to draw order in setup pose order
|
||||
for (size_t i = 0; i < _slots.size(); ++i) {
|
||||
_drawOrder[i] = _slots[i];
|
||||
}
|
||||
for (size_t i = 0; i < _slots.size(); ++i) {
|
||||
_slots[i]->setupPose();
|
||||
}
|
||||
}
|
||||
|
||||
SkeletonData *Skeleton::getData() {
|
||||
return &_data;
|
||||
}
|
||||
|
||||
Vector<Bone *> &Skeleton::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
|
||||
Vector<Update *> &Skeleton::getUpdateCache() {
|
||||
return _updateCache;
|
||||
}
|
||||
|
||||
Bone *Skeleton::getRootBone() {
|
||||
return _bones.size() == 0 ? NULL : _bones[0];
|
||||
}
|
||||
|
||||
Bone *Skeleton::findBone(const String &boneName) {
|
||||
if (boneName.isEmpty()) return NULL;
|
||||
for (size_t i = 0; i < _bones.size(); ++i) {
|
||||
if (_bones[i]->getData().getName() == boneName) {
|
||||
return _bones[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Vector<Slot *> &Skeleton::getSlots() {
|
||||
return _slots;
|
||||
}
|
||||
|
||||
Slot *Skeleton::findSlot(const String &slotName) {
|
||||
if (slotName.isEmpty()) return NULL;
|
||||
for (size_t i = 0; i < _slots.size(); ++i) {
|
||||
if (_slots[i]->getData().getName() == slotName) {
|
||||
return _slots[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Vector<Slot *> &Skeleton::getDrawOrder() {
|
||||
return _drawOrder;
|
||||
}
|
||||
|
||||
Skin *Skeleton::getSkin() {
|
||||
return _skin;
|
||||
}
|
||||
|
||||
void Skeleton::setSkin(const String &skinName) {
|
||||
Skin *skin = _data.findSkin(skinName);
|
||||
if (skin == NULL && !skinName.isEmpty()) {
|
||||
// Handle error - skin not found
|
||||
return;
|
||||
}
|
||||
setSkin(skin);
|
||||
}
|
||||
|
||||
void Skeleton::setSkin(Skin *newSkin) {
|
||||
if (newSkin == _skin) return;
|
||||
if (newSkin != NULL) {
|
||||
if (_skin != NULL) {
|
||||
newSkin->attachAll(*this, *_skin);
|
||||
} else {
|
||||
for (size_t i = 0; i < _slots.size(); ++i) {
|
||||
Slot *slot = _slots[i];
|
||||
const String &name = slot->getData().getAttachmentName();
|
||||
if (!name.isEmpty()) {
|
||||
Attachment *attachment = newSkin->getAttachment((int) i, name);
|
||||
if (attachment != NULL) {
|
||||
slot->getPose().setAttachment(attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_skin = newSkin;
|
||||
updateCache();
|
||||
}
|
||||
|
||||
Attachment *Skeleton::getAttachment(const String &slotName, const String &attachmentName) {
|
||||
SlotData *slotData = _data.findSlot(slotName);
|
||||
if (slotData == NULL) return NULL;
|
||||
return getAttachment(slotData->getIndex(), attachmentName);
|
||||
}
|
||||
|
||||
Attachment *Skeleton::getAttachment(int slotIndex, const String &attachmentName) {
|
||||
if (attachmentName.isEmpty()) return NULL;
|
||||
if (_skin != NULL) {
|
||||
Attachment *attachment = _skin->getAttachment(slotIndex, attachmentName);
|
||||
if (attachment != NULL) return attachment;
|
||||
}
|
||||
if (_data.getDefaultSkin() != NULL) {
|
||||
return _data.getDefaultSkin()->getAttachment(slotIndex, attachmentName);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Skeleton::setAttachment(const String &slotName, const String &attachmentName) {
|
||||
if (slotName.isEmpty()) return;
|
||||
Slot *slot = findSlot(slotName);
|
||||
if (slot == NULL) return;
|
||||
Attachment *attachment = NULL;
|
||||
if (!attachmentName.isEmpty()) {
|
||||
attachment = getAttachment(slot->getData().getIndex(), attachmentName);
|
||||
if (attachment == NULL) {
|
||||
// Handle error - attachment not found
|
||||
return;
|
||||
}
|
||||
}
|
||||
slot->getPose().setAttachment(attachment);
|
||||
}
|
||||
|
||||
Vector<Constraint *> &Skeleton::getConstraints() {
|
||||
return _constraints;
|
||||
}
|
||||
|
||||
Vector<PhysicsConstraint *> &Skeleton::getPhysicsConstraints() {
|
||||
return _physics;
|
||||
}
|
||||
|
||||
void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector<float> &outVertexBuffer) {
|
||||
getBounds(outX, outY, outWidth, outHeight, outVertexBuffer, NULL);
|
||||
}
|
||||
|
||||
void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector<float> &outVertexBuffer, SkeletonClipping *clipper) {
|
||||
float minX = FLT_MAX, minY = FLT_MAX, maxX = -FLT_MAX, maxY = -FLT_MAX;
|
||||
|
||||
for (size_t i = 0; i < _drawOrder.size(); ++i) {
|
||||
Slot *slot = _drawOrder[i];
|
||||
if (!slot->getBone().isActive()) continue;
|
||||
|
||||
size_t verticesLength = 0;
|
||||
float *vertices = NULL;
|
||||
const unsigned short *triangles = NULL;
|
||||
Attachment *attachment = slot->getPose().getAttachment();
|
||||
|
||||
if (attachment != NULL) {
|
||||
RegionAttachment *region = dynamic_cast<RegionAttachment *>(attachment);
|
||||
if (region != NULL) {
|
||||
verticesLength = 8;
|
||||
outVertexBuffer.setSize(8);
|
||||
vertices = outVertexBuffer.buffer();
|
||||
region->computeWorldVertices(*slot, vertices, 0, 2);
|
||||
triangles = quadTriangles;
|
||||
} else {
|
||||
MeshAttachment *mesh = dynamic_cast<MeshAttachment *>(attachment);
|
||||
if (mesh != NULL) {
|
||||
verticesLength = mesh->getWorldVerticesLength();
|
||||
outVertexBuffer.setSize(verticesLength);
|
||||
vertices = outVertexBuffer.buffer();
|
||||
mesh->computeWorldVertices(*this, *slot, 0, verticesLength, vertices, 0, 2);
|
||||
triangles = mesh->getTriangles().buffer();
|
||||
} else {
|
||||
ClippingAttachment *clip = dynamic_cast<ClippingAttachment *>(attachment);
|
||||
if (clip != NULL && clipper != NULL) {
|
||||
clipper->clipEnd(*slot);
|
||||
clipper->clipStart(*this, *slot, *clip);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vertices != NULL) {
|
||||
if (clipper != NULL && clipper->isClipping() && clipper->clipTriangles(vertices, triangles, 6)) {
|
||||
vertices = clipper->getClippedVertices().buffer();
|
||||
verticesLength = clipper->getClippedVertices().size();
|
||||
}
|
||||
for (size_t ii = 0; ii < verticesLength; ii += 2) {
|
||||
float x = vertices[ii], y = vertices[ii + 1];
|
||||
minX = MathUtil::min(minX, x);
|
||||
minY = MathUtil::min(minY, y);
|
||||
maxX = MathUtil::max(maxX, x);
|
||||
maxY = MathUtil::max(maxY, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clipper != NULL) clipper->clipEnd(*slot);
|
||||
}
|
||||
if (clipper != NULL) clipper->clipEnd();
|
||||
|
||||
outX = minX;
|
||||
outY = minY;
|
||||
outWidth = maxX - minX;
|
||||
outHeight = maxY - minY;
|
||||
}
|
||||
|
||||
Color &Skeleton::getColor() {
|
||||
return _color;
|
||||
}
|
||||
|
||||
void Skeleton::setColor(Color &color) {
|
||||
_color = color;
|
||||
}
|
||||
|
||||
float Skeleton::getScaleX() {
|
||||
return _scaleX;
|
||||
}
|
||||
|
||||
void Skeleton::setScaleX(float inValue) {
|
||||
_scaleX = inValue;
|
||||
}
|
||||
|
||||
float Skeleton::getScaleY() {
|
||||
return _scaleY;
|
||||
}
|
||||
|
||||
void Skeleton::setScaleY(float inValue) {
|
||||
_scaleY = inValue;
|
||||
}
|
||||
|
||||
void Skeleton::setScale(float scaleX, float scaleY) {
|
||||
_scaleX = scaleX;
|
||||
_scaleY = scaleY;
|
||||
}
|
||||
|
||||
float Skeleton::getX() {
|
||||
return _x;
|
||||
}
|
||||
|
||||
void Skeleton::setX(float inValue) {
|
||||
_x = inValue;
|
||||
}
|
||||
|
||||
float Skeleton::getY() {
|
||||
return _y;
|
||||
}
|
||||
|
||||
void Skeleton::setY(float inValue) {
|
||||
_y = inValue;
|
||||
}
|
||||
|
||||
void Skeleton::setPosition(float x, float y) {
|
||||
_x = x;
|
||||
_y = y;
|
||||
}
|
||||
|
||||
float Skeleton::getWindX() {
|
||||
return _windX;
|
||||
}
|
||||
|
||||
void Skeleton::setWindX(float windX) {
|
||||
_windX = windX;
|
||||
}
|
||||
|
||||
float Skeleton::getWindY() {
|
||||
return _windY;
|
||||
}
|
||||
|
||||
void Skeleton::setWindY(float windY) {
|
||||
_windY = windY;
|
||||
}
|
||||
|
||||
float Skeleton::getGravityX() {
|
||||
return _gravityX;
|
||||
}
|
||||
|
||||
void Skeleton::setGravityX(float gravityX) {
|
||||
_gravityX = gravityX;
|
||||
}
|
||||
|
||||
float Skeleton::getGravityY() {
|
||||
return _gravityY;
|
||||
}
|
||||
|
||||
void Skeleton::setGravityY(float gravityY) {
|
||||
_gravityY = gravityY;
|
||||
}
|
||||
|
||||
void Skeleton::physicsTranslate(float x, float y) {
|
||||
for (size_t i = 0; i < _physics.size(); ++i) {
|
||||
_physics[i]->translate(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::physicsRotate(float x, float y, float degrees) {
|
||||
for (size_t i = 0; i < _physics.size(); ++i) {
|
||||
_physics[i]->rotate(x, y, degrees);
|
||||
}
|
||||
}
|
||||
|
||||
float Skeleton::getTime() {
|
||||
return _time;
|
||||
}
|
||||
|
||||
void Skeleton::setTime(float time) {
|
||||
_time = time;
|
||||
}
|
||||
|
||||
void Skeleton::update(float delta) {
|
||||
_time += delta;
|
||||
}
|
||||
@ -57,50 +57,11 @@ Slider* Slider::copy(Skeleton& skeleton) {
|
||||
}
|
||||
|
||||
void Slider::update(Skeleton &skeleton, Physics physics) {
|
||||
SliderPose& p = *_applied;
|
||||
if (p.getMix() == 0) return;
|
||||
|
||||
Animation* animation = _data.getAnimation();
|
||||
if (_bone != NULL) {
|
||||
if (!_bone->isActive()) return;
|
||||
if (_data.getLocal()) _bone->getAppliedPose().validateLocalTransform(skeleton);
|
||||
p.setTime((_data.getProperty()->value(_bone->getAppliedPose(), _data.getLocal(), _offsets) - _data.getProperty()->offset) * _data.getScale());
|
||||
if (_data.getLoop()) {
|
||||
// TODO: Implement when Animation is ported
|
||||
p.setTime(animation->getDuration() + MathUtil::fmod(p.getTime(), animation->getDuration()));
|
||||
} else {
|
||||
p.setTime(MathUtil::max(0.0f, p.getTime()));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement when Animation is ported
|
||||
// Vector<Bone*>& bones = skeleton.getBones();
|
||||
// Vector<size_t>& indices = animation->getBones();
|
||||
// for (size_t i = 0, n = indices.size(); i < n; i++) {
|
||||
// bones[indices[i]]->getAppliedPose().modifyLocal(skeleton);
|
||||
// }
|
||||
|
||||
// TODO: Implement when Animation is ported
|
||||
// animation->apply(skeleton, p.getTime(), p.getTime(), _data.getLoop(), NULL, p.getMix(),
|
||||
// _data.getAdditive() ? MixBlend_Add : MixBlend_Replace, MixDirection_In);
|
||||
}
|
||||
|
||||
void Slider::sort(Skeleton &skeleton) {
|
||||
// TODO: Implement when Animation is ported
|
||||
// if (_bone != NULL && !_data.getLocal()) skeleton.sortBone(_bone);
|
||||
skeleton.getUpdateCacheList().add(this);
|
||||
|
||||
// TODO: Implement when Animation is ported
|
||||
// Vector<Bone*>& bones = skeleton.getBones();
|
||||
// Vector<size_t>& indices = _data.getAnimation()->getBones();
|
||||
// for (size_t i = 0, n = indices.size(); i < n; i++) {
|
||||
// Bone* bone = bones[indices[i]];
|
||||
// bone->setSorted(false);
|
||||
// skeleton.sortReset(bone->getChildren());
|
||||
// skeleton.constrained(bone);
|
||||
// }
|
||||
|
||||
// TODO: Implement when Animation is ported - timeline processing
|
||||
}
|
||||
|
||||
Bone *Slider::getBone() {
|
||||
|
||||
@ -37,8 +37,7 @@
|
||||
|
||||
using namespace spine;
|
||||
|
||||
Slot::Slot(SlotData &data, Skeleton &skeleton) :
|
||||
Posed<SlotData, SlotPose, SlotPose>(data),
|
||||
Slot::Slot(SlotData &data, Skeleton &skeleton) : Posed<SlotData, SlotPose, SlotPose>(data),
|
||||
_skeleton(skeleton),
|
||||
_bone(*skeleton.getBones()[data.getBoneData().getIndex()]),
|
||||
_attachmentState(0) {
|
||||
|
||||
@ -35,8 +35,7 @@
|
||||
|
||||
using namespace spine;
|
||||
|
||||
SlotData::SlotData(int index, const String& name, BoneData& boneData) :
|
||||
PosedData<SlotPose>(name),
|
||||
SlotData::SlotData(int index, const String &name, BoneData &boneData) : PosedData<SlotPose>(name),
|
||||
_index(index),
|
||||
_boneData(boneData),
|
||||
_attachmentName(),
|
||||
|
||||
@ -41,8 +41,7 @@ using namespace spine;
|
||||
|
||||
RTTI_IMPL(TransformConstraint, Constraint)
|
||||
|
||||
TransformConstraint::TransformConstraint(TransformConstraintData& data, Skeleton& skeleton) :
|
||||
ConstraintGeneric<TransformConstraint, TransformConstraintData, TransformConstraintPose>(data) {
|
||||
TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : ConstraintGeneric<TransformConstraint, TransformConstraintData, TransformConstraintPose>(data) {
|
||||
|
||||
_bones.ensureCapacity(data.getBones().size());
|
||||
for (size_t i = 0; i < data.getBones().size(); i++) {
|
||||
@ -74,7 +73,7 @@ void TransformConstraint::update(Skeleton& skeleton, Physics physics) {
|
||||
Vector<FromProperty *> &properties = data.getProperties();
|
||||
FromProperty **fromItems = properties.buffer();
|
||||
size_t fn = properties.size();
|
||||
int update = 1; // TODO: Add skeleton.update field
|
||||
int update = skeleton._update;
|
||||
BonePose **bones = _bones.buffer();
|
||||
for (size_t i = 0, n = _bones.size(); i < n; i++) {
|
||||
BonePose *bone = bones[i];
|
||||
@ -106,22 +105,22 @@ void TransformConstraint::update(Skeleton& skeleton, Physics physics) {
|
||||
}
|
||||
|
||||
void TransformConstraint::sort(Skeleton &skeleton) {
|
||||
// if (!_data.getLocalSource()) skeleton.sortBone(_source); // TODO: sortBone is private, need friend access
|
||||
if (!_data.getLocalSource()) skeleton.sortBone(_source);
|
||||
BonePose **bones = _bones.buffer();
|
||||
size_t boneCount = _bones.size();
|
||||
bool worldTarget = !_data.getLocalTarget();
|
||||
// if (worldTarget) {
|
||||
// for (size_t i = 0; i < boneCount; i++)
|
||||
// skeleton.sortBone(bones[i]->_bone); // TODO: sortBone is private, need friend access
|
||||
// }
|
||||
// skeleton._updateCache.add(this); // TODO: _updateCache is private, need friend access
|
||||
// for (size_t i = 0; i < boneCount; i++) {
|
||||
// Bone* bone = bones[i]->_bone;
|
||||
// skeleton.sortReset(bone->getChildren()); // TODO: sortReset is private, need friend access
|
||||
// // skeleton.constrained(bone); // TODO: Add constrained() method to Skeleton class
|
||||
// }
|
||||
// for (size_t i = 0; i < boneCount; i++)
|
||||
// bones[i]->_bone->_sorted = worldTarget; // TODO: _sorted is private, need friend access
|
||||
if (worldTarget) {
|
||||
for (size_t i = 0; i < boneCount; i++)
|
||||
skeleton.sortBone(bones[i]->_bone);
|
||||
}
|
||||
skeleton._updateCache.add(this);
|
||||
for (size_t i = 0; i < boneCount; i++) {
|
||||
Bone* bone = bones[i]->_bone;
|
||||
skeleton.sortReset(bone->getChildren());
|
||||
skeleton.constrained(*bone);
|
||||
}
|
||||
for (size_t i = 0; i < boneCount; i++)
|
||||
bones[i]->_bone->_sorted = worldTarget;
|
||||
}
|
||||
|
||||
bool TransformConstraint::isSourceActive() {
|
||||
|
||||
@ -169,8 +169,7 @@ ToProperty::~ToProperty() {
|
||||
|
||||
float FromRotate::value(BonePose &source, bool local, float *offsets) {
|
||||
if (local) return source.getRotation() + offsets[TransformConstraintData::ROTATION];
|
||||
float value = MathUtil::atan2(source._c, source._a) * MathUtil::Rad_Deg
|
||||
+ (source._a * source._d - source._b * source._c > 0 ? offsets[TransformConstraintData::ROTATION] : -offsets[TransformConstraintData::ROTATION]);
|
||||
float value = MathUtil::atan2(source._c, source._a) * MathUtil::Rad_Deg + (source._a * source._d - source._b * source._c > 0 ? offsets[TransformConstraintData::ROTATION] : -offsets[TransformConstraintData::ROTATION]);
|
||||
if (value < 0) value += 360;
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -31,8 +31,7 @@
|
||||
|
||||
using namespace spine;
|
||||
|
||||
TransformConstraintPose::TransformConstraintPose() :
|
||||
_mixRotate(0), _mixX(0), _mixY(0), _mixScaleX(0), _mixScaleY(0), _mixShearY(0) {
|
||||
TransformConstraintPose::TransformConstraintPose() : _mixRotate(0), _mixX(0), _mixY(0), _mixScaleX(0), _mixScaleY(0), _mixShearY(0) {
|
||||
}
|
||||
|
||||
TransformConstraintPose::~TransformConstraintPose() {
|
||||
|
||||
@ -42,8 +42,7 @@ using namespace spine;
|
||||
|
||||
RTTI_IMPL(TranslateTimeline, BoneTimeline2)
|
||||
|
||||
TranslateTimeline::TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) :
|
||||
BoneTimeline2(frameCount, bezierCount, boneIndex, Property_X, Property_Y) {
|
||||
TranslateTimeline::TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : BoneTimeline2(frameCount, bezierCount, boneIndex, Property_X, Property_Y) {
|
||||
}
|
||||
|
||||
void TranslateTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend,
|
||||
@ -106,8 +105,7 @@ void TranslateTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, flo
|
||||
|
||||
RTTI_IMPL(TranslateXTimeline, BoneTimeline1)
|
||||
|
||||
TranslateXTimeline::TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) :
|
||||
BoneTimeline1(frameCount, bezierCount, boneIndex, Property_X) {
|
||||
TranslateXTimeline::TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_X) {
|
||||
}
|
||||
|
||||
void TranslateXTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend,
|
||||
@ -117,8 +115,7 @@ void TranslateXTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, fl
|
||||
|
||||
RTTI_IMPL(TranslateYTimeline, BoneTimeline1)
|
||||
|
||||
TranslateYTimeline::TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) :
|
||||
BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Y) {
|
||||
TranslateYTimeline::TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Y) {
|
||||
}
|
||||
|
||||
void TranslateYTimeline::apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user