[cpp] 4.3 porting WIP

This commit is contained in:
Mario Zechner 2025-06-11 14:39:38 +02:00
parent 2e369a8130
commit e3fb50da5b
9 changed files with 191 additions and 840 deletions

View File

@ -30,256 +30,62 @@
#ifndef Spine_Bone_h
#define Spine_Bone_h
#include <spine/Update.h>
#include <spine/SpineObject.h>
#include <spine/PosedActive.h>
#include <spine/BoneData.h>
#include <spine/BoneLocal.h>
#include <spine/BonePose.h>
#include <spine/Vector.h>
#include <spine/Inherit.h>
namespace spine {
class BoneData;
class Skeleton;
/// Stores a bone's current pose.
///
/// 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 Update {
/// The current pose for a bone, before constraints are applied.
///
/// 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> {
friend class AnimationState;
friend class RotateTimeline;
friend class IkConstraint;
friend class TransformConstraint;
friend class VertexAttachment;
friend class PathConstraint;
friend class PhysicsConstraint;
friend class PhysicsConstraint;
friend class Skeleton;
friend class RegionAttachment;
friend class PointAttachment;
friend class AttachmentTimeline;
friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class ScaleTimeline;
friend class ScaleXTimeline;
friend class ScaleYTimeline;
friend class ShearTimeline;
friend class ShearXTimeline;
friend class ShearYTimeline;
friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
friend class InheritTimeline;
friend class InheritTimeline;
RTTI_DECL
RTTI_DECL
public:
static void setYDown(bool inValue);
static bool isYDown();
/// @param parent May be NULL.
Bone(BoneData &data, Skeleton &skeleton, Bone *parent = NULL);
Bone(BoneData& data, Bone* parent);
/// Same as updateWorldTransform. This method exists for Bone to implement Spine::Updatable.
virtual void update(Physics physics);
/// The parent bone, or null if this is the root bone.
Bone* getParent();
/// Computes the world transform using the parent bone and this bone's local transform.
void updateWorldTransform();
/// Computes the world transform using the parent bone and the specified local transform.
void
updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY);
/// Computes the individual applied transform values from the world transform. This can be useful to perform processing using
/// the applied transform after the world transform has been modified directly (eg, by a constraint)..
///
/// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation.
void updateAppliedTransform();
void setToSetupPose();
void worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY);
void worldToParent(float worldX, float worldY, float &outParentX, float &outParentY);
void localToWorld(float localX, float localY, float &outWorldX, float &outWorldY);
void parentToWorld(float worldX, float worldY, float &outX, float &outY);
float worldToLocalRotation(float worldRotation);
float localToWorldRotation(float localRotation);
/// Rotates the world transform the specified amount and sets isAppliedValid to false.
/// @param degrees Degrees.
void rotateWorld(float degrees);
float getWorldToLocalRotationX();
float getWorldToLocalRotationY();
BoneData &getData();
Skeleton &getSkeleton();
Bone *getParent();
Vector<Bone *> &getChildren();
/// The local X translation.
float getX();
void setX(float inValue);
/// The local Y translation.
float getY();
void setY(float inValue);
/// The local rotation.
float getRotation();
void setRotation(float inValue);
/// The local scaleX.
float getScaleX();
void setScaleX(float inValue);
/// The local scaleY.
float getScaleY();
void setScaleY(float inValue);
/// The local shearX.
float getShearX();
void setShearX(float inValue);
/// The local shearY.
float getShearY();
void setShearY(float inValue);
/// The rotation, as calculated by any constraints.
float getAppliedRotation();
void setAppliedRotation(float inValue);
/// The applied local x translation.
float getAX();
void setAX(float inValue);
/// The applied local y translation.
float getAY();
void setAY(float inValue);
/// The applied local scaleX.
float getAScaleX();
void setAScaleX(float inValue);
/// The applied local scaleY.
float getAScaleY();
void setAScaleY(float inValue);
/// The applied local shearX.
float getAShearX();
void setAShearX(float inValue);
/// The applied local shearY.
float getAShearY();
void setAShearY(float inValue);
float getA();
void setA(float inValue);
float getB();
void setB(float inValue);
float getC();
void setC(float inValue);
float getD();
void setD(float inValue);
float getWorldX();
void setWorldX(float inValue);
float getWorldY();
void setWorldY(float inValue);
float getWorldRotationX();
float getWorldRotationY();
/// Returns the magnitide (always positive) of the world scale X.
float getWorldScaleX();
/// Returns the magnitide (always positive) of the world scale Y.
float getWorldScaleY();
bool isActive();
void setActive(bool inValue);
Inherit getInherit() { return _inherit; }
void setInherit(Inherit inValue) { _inherit = inValue; }
/// The immediate children of this bone.
Vector<Bone*>& getChildren();
private:
static bool yDown;
BoneData &_data;
Skeleton &_skeleton;
Bone *_parent;
Vector<Bone *> _children;
float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY;
float _ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY;
float _a, _b, _worldX;
float _c, _d, _worldY;
Bone* const _parent;
Vector<Bone*> _children;
bool _sorted;
bool _active;
Inherit _inherit;
};
}

View File

@ -0,0 +1,62 @@
/******************************************************************************
* 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.
*****************************************************************************/
#ifndef Spine_Constraint_h
#define Spine_Constraint_h
#include <spine/PosedActive.h>
#include <spine/Update.h>
#include <spine/RTTI.h>
namespace spine {
class Skeleton;
template<class T, class D, class P>
class SP_API Constraint : public PosedActive<D, P, P>, public Update {
RTTI_DECL
public:
Constraint(D& data, P& pose, P& constrained) : PosedActive<D, P, P>(data, pose, constrained) {
}
virtual ~Constraint() {
}
virtual void sort(Skeleton& skeleton) = 0;
virtual bool isSourceActive() {
return true;
}
// Inherited from Update
virtual void update(Skeleton& skeleton, Physics physics) = 0;
};
}
#endif /* Spine_Constraint_h */

View File

@ -41,6 +41,9 @@ namespace spine {
/// Base class for all constraint data.
template<class T, class P>
class SP_API ConstraintData : public PosedData<P> {
friend class SkeletonBinary;
friend class SkeletonJson;
public:
ConstraintData(const String &name, P* setup);
virtual ~ConstraintData();

View File

@ -31,58 +31,76 @@
#define Spine_Posed_h
#include <spine/SpineObject.h>
#include <type_traits>
namespace spine {
template<class D, class P, class A>
class SP_API Posed : public SpineObject {
public:
Posed(D& data, P& pose, A& constrained);
virtual ~Posed();
friend class AnimationState;
friend class RotateTimeline;
friend class IkConstraint;
friend class TransformConstraint;
friend class VertexAttachment;
friend class PathConstraint;
friend class PhysicsConstraint;
friend class Skeleton;
friend class RegionAttachment;
friend class PointAttachment;
friend class AttachmentTimeline;
friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class ScaleTimeline;
friend class ScaleXTimeline;
friend class ScaleYTimeline;
friend class ShearTimeline;
friend class ShearXTimeline;
friend class ShearYTimeline;
friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
friend class InheritTimeline;
void setupPose();
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;
}
virtual ~Posed() {
}
void setupPose() {
_pose.set(*_data.getSetupPose());
}
/// The constraint's setup pose data.
D& getData();
D& getData() {
return _data;
}
P& getPose();
P& getPose() {
// Upcast A to P (safe due to static_assert that A extends P)
// For most classes P==A so this is a no-op, but for Bone it casts BonePose->BoneLocal
return _pose;
}
A& getAppliedPose();
A& getAppliedPose() {
return *_applied;
}
protected:
D& _data;
P& _pose;
A& _constrained;
A* _applied;
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
};
template<class D, class P, class A>
Posed<D, P, A>::Posed(D& data, P& pose, A& constrained) : _data(data), _pose(pose), _constrained(constrained) {
_applied = &pose;
}
template<class D, class P, class A>
Posed<D, P, A>::~Posed() {
}
template<class D, class P, class A>
void Posed<D, P, A>::setupPose() {
_pose.set(_data.setup);
}
template<class D, class P, class A>
D& Posed<D, P, A>::getData() {
return _data;
}
template<class D, class P, class A>
P& Posed<D, P, A>::getPose() {
return _pose;
}
template<class D, class P, class A>
A& Posed<D, P, A>::getAppliedPose() {
return *_applied;
}
}
#endif /* Spine_Posed_h */

View File

@ -40,7 +40,7 @@ namespace spine {
bool _active;
public:
PosedActive(D& data, P& pose, A& constrained);
PosedActive(D& data);
virtual ~PosedActive();
/// Returns false when this constraint won't be updated by
@ -54,7 +54,7 @@ namespace spine {
};
template<class D, class P, class A>
PosedActive<D, P, A>::PosedActive(D& data, P& pose, A& constrained) : Posed<D, P, A>(data, pose, constrained), _active(false) {
PosedActive<D, P, A>::PosedActive(D& data) : Posed<D, P, A>(data), _active(false) {
this->setupPose();
}

View File

@ -40,6 +40,9 @@ namespace spine {
/// The base class for all constrained datas.
template<class P>
class SP_API PosedData : public SpineObject {
friend class SkeletonBinary;
friend class SkeletonJson;
private:
spine::String _name;
P* _setup;

View File

@ -60,9 +60,10 @@ namespace spine {
/// time, an animation can be mixed in or out. alpha can also be useful to apply animations on top of each other (layered).
/// @param blend Controls how mixing is applied when alpha is than 1.
/// @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions such as DrawOrderTimeline and AttachmentTimeline.
/// @param appliedPose True to modify the applied pose.
virtual void
apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixBlend blend,
MixDirection direction) = 0;
MixDirection direction, bool appliedPose) = 0;
size_t getFrameEntries();

View File

@ -28,568 +28,26 @@
*****************************************************************************/
#include <spine/Bone.h>
#include <spine/BoneData.h>
#include <spine/Skeleton.h>
#include <spine/BoneLocal.h>
#include <spine/BonePose.h>
using namespace spine;
RTTI_IMPL(Bone, Updatable)
RTTI_IMPL_NOPARENT(Bone)
bool Bone::yDown = false;
void Bone::setYDown(bool inValue) {
yDown = inValue;
Bone::Bone(BoneData& data, Bone* parent) : PosedActive(data),
_parent(parent),
_children(),
_sorted(false) {
_constrained._bone = this;
_applied->_bone = this;
}
bool Bone::isYDown() {
return yDown;
}
Bone::Bone(BoneData &data, Skeleton &skeleton, Bone *parent) : Updatable(),
_data(data),
_skeleton(skeleton),
_parent(parent),
_x(0),
_y(0),
_rotation(0),
_scaleX(0),
_scaleY(0),
_shearX(0),
_shearY(0),
_ax(0),
_ay(0),
_arotation(0),
_ascaleX(0),
_ascaleY(0),
_ashearX(0),
_ashearY(0),
_a(1),
_b(0),
_worldX(0),
_c(0),
_d(1),
_worldY(0),
_sorted(false),
_active(false),
_inherit(Inherit_Normal) {
setToSetupPose();
}
void Bone::update(Physics) {
updateWorldTransform(_ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY);
}
void Bone::updateWorldTransform() {
updateWorldTransform(_x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY);
}
void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) {
float pa, pb, pc, pd;
Bone *parent = _parent;
_ax = x;
_ay = y;
_arotation = rotation;
_ascaleX = scaleX;
_ascaleY = scaleY;
_ashearX = shearX;
_ashearY = shearY;
if (!parent) { /* Root bone. */
Skeleton &skeleton = this->_skeleton;
float sx = skeleton.getScaleX();
float sy = skeleton.getScaleY();
float rx = (rotation + shearX) * MathUtil::Deg_Rad;
float ry = (rotation + 90 + shearY) * MathUtil::Deg_Rad;
_a = MathUtil::cos(rx) * scaleX * sx;
_b = MathUtil::cos(ry) * scaleY * sx;
_c = MathUtil::sin(rx) * scaleX * sy;
_d = MathUtil::sin(ry) * scaleY * sy;
_worldX = x * sx + _skeleton.getX();
_worldY = y * sy + _skeleton.getY();
return;
}
pa = parent->_a;
pb = parent->_b;
pc = parent->_c;
pd = parent->_d;
_worldX = pa * x + pb * y + parent->_worldX;
_worldY = pc * x + pd * y + parent->_worldY;
switch (_inherit) {
case Inherit_Normal: {
float rx = (rotation + shearX) * MathUtil::Deg_Rad;
float ry = (rotation + 90 + shearY) * MathUtil::Deg_Rad;
float la = MathUtil::cos(rx) * scaleX;
float lb = MathUtil::cos(ry) * scaleY;
float lc = MathUtil::sin(rx) * scaleX;
float ld = MathUtil::sin(ry) * scaleY;
_a = pa * la + pb * lc;
_b = pa * lb + pb * ld;
_c = pc * la + pd * lc;
_d = pc * lb + pd * ld;
return;
}
case Inherit_OnlyTranslation: {
float rx = (rotation + shearX) * MathUtil::Deg_Rad;
float ry = (rotation + 90 + shearY) * MathUtil::Deg_Rad;
_a = MathUtil::cos(rx) * scaleX;
_b = MathUtil::cos(ry) * scaleY;
_c = MathUtil::sin(rx) * scaleX;
_d = MathUtil::sin(ry) * scaleY;
break;
}
case Inherit_NoRotationOrReflection: {
float s = pa * pa + pc * pc;
float prx;
if (s > 0.0001f) {
s = MathUtil::abs(pa * pd - pb * pc) / s;
pa /= _skeleton.getScaleX();
pc /= _skeleton.getScaleY();
pb = pc * s;
pd = pa * s;
prx = MathUtil::atan2Deg(pc, pa);
} else {
pa = 0;
pc = 0;
prx = 90 - MathUtil::atan2Deg(pd, pb);
}
float rx = (rotation + shearX - prx) * MathUtil::Deg_Rad;
float ry = (rotation + shearY - prx + 90) * MathUtil::Deg_Rad;
float la = MathUtil::cos(rx) * scaleX;
float lb = MathUtil::cos(ry) * scaleY;
float lc = MathUtil::sin(rx) * scaleX;
float ld = MathUtil::sin(ry) * scaleY;
_a = pa * la - pb * lc;
_b = pa * lb - pb * ld;
_c = pc * la + pd * lc;
_d = pc * lb + pd * ld;
break;
}
case Inherit_NoScale:
case Inherit_NoScaleOrReflection: {
rotation *= MathUtil::Deg_Rad;
float cosine = MathUtil::cos(rotation);
float sine = MathUtil::sin(rotation);
float za = (pa * cosine + pb * sine) / _skeleton.getScaleX();
float zc = (pc * cosine + pd * sine) / _skeleton.getScaleY();
float s = MathUtil::sqrt(za * za + zc * zc);
if (s > 0.00001f) s = 1 / s;
za *= s;
zc *= s;
s = MathUtil::sqrt(za * za + zc * zc);
if (_inherit == Inherit_NoScale &&
(pa * pd - pb * pc < 0) != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0))
s = -s;
rotation = MathUtil::Pi / 2 + MathUtil::atan2(zc, za);
float zb = MathUtil::cos(rotation) * s;
float zd = MathUtil::sin(rotation) * s;
shearX *= MathUtil::Deg_Rad;
shearY = (90 + shearY) * MathUtil::Deg_Rad;
float la = MathUtil::cos(shearX) * scaleX;
float lb = MathUtil::cos(shearY) * scaleY;
float lc = MathUtil::sin(shearX) * scaleX;
float ld = MathUtil::sin(shearY) * scaleY;
_a = za * la + zb * lc;
_b = za * lb + zb * ld;
_c = zc * la + zd * lc;
_d = zc * lb + zd * ld;
}
}
_a *= _skeleton.getScaleX();
_b *= _skeleton.getScaleX();
_c *= _skeleton.getScaleY();
_d *= _skeleton.getScaleY();
}
void Bone::setToSetupPose() {
BoneData &data = _data;
_x = data.getX();
_y = data.getY();
_rotation = data.getRotation();
_scaleX = data.getScaleX();
_scaleY = data.getScaleY();
_shearX = data.getShearX();
_shearY = data.getShearY();
_inherit = data.getInherit();
}
void Bone::worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY) {
float a = _a;
float b = _b;
float c = _c;
float d = _d;
float invDet = 1 / (a * d - b * c);
float x = worldX - _worldX;
float y = worldY - _worldY;
outLocalX = (x * d * invDet - y * b * invDet);
outLocalY = (y * a * invDet - x * c * invDet);
}
void Bone::worldToParent(float worldX, float worldY, float &outParentX, float &outParentY) {
if (!_parent) {
outParentX = worldX;
outParentY = worldY;
} else {
_parent->worldToLocal(worldX, worldY, outParentX, outParentY);
}
}
void Bone::localToWorld(float localX, float localY, float &outWorldX, float &outWorldY) {
outWorldX = localX * _a + localY * _b + _worldX;
outWorldY = localX * _c + localY * _d + _worldY;
}
void Bone::parentToWorld(float worldX, float worldY, float &outX, float &outY) {
if (!_parent) {
outX = worldX;
outY = worldY;
} else {
_parent->localToWorld(worldX, worldY, outX, outY);
}
}
float Bone::worldToLocalRotation(float worldRotation) {
worldRotation *= MathUtil::Deg_Rad;
float sine = MathUtil::sin(worldRotation), cosine = MathUtil::cos(worldRotation);
return MathUtil::atan2Deg(_a * sine - _c * cosine, _d * cosine - _b * sine) + _rotation - _shearX;
}
float Bone::localToWorldRotation(float localRotation) {
localRotation = (localRotation - _rotation - _shearX) * MathUtil::Deg_Rad;
float sine = MathUtil::sin(localRotation), cosine = MathUtil::cos(localRotation);
return MathUtil::atan2Deg(cosine * _c + sine * _d, cosine * _a + sine * _b);
}
void Bone::rotateWorld(float degrees) {
degrees *= MathUtil::Deg_Rad;
float sine = MathUtil::sin(degrees), cosine = MathUtil::cos(degrees);
float ra = _a, rb = _b;
_a = cosine * ra - sine * _c;
_b = cosine * rb - sine * _d;
_c = sine * ra + cosine * _c;
_d = sine * rb + cosine * _d;
}
float Bone::getWorldToLocalRotationX() {
Bone *parent = _parent;
if (!parent) {
return _arotation;
}
float pa = parent->_a;
float pb = parent->_b;
float pc = parent->_c;
float pd = parent->_d;
float a = _a;
float c = _c;
return MathUtil::atan2(pa * c - pc * a, pd * a - pb * c) * MathUtil::Rad_Deg;
}
float Bone::getWorldToLocalRotationY() {
Bone *parent = _parent;
if (!parent) {
return _arotation;
}
float pa = parent->_a;
float pb = parent->_b;
float pc = parent->_c;
float pd = parent->_d;
float b = _b;
float d = _d;
return MathUtil::atan2(pa * d - pc * b, pd * b - pb * d) * MathUtil::Rad_Deg;
}
BoneData &Bone::getData() {
return _data;
}
Skeleton &Bone::getSkeleton() {
return _skeleton;
}
Bone *Bone::getParent() {
Bone* Bone::getParent() {
return _parent;
}
Vector<Bone *> &Bone::getChildren() {
Vector<Bone*>& Bone::getChildren() {
return _children;
}
float Bone::getX() {
return _x;
}
void Bone::setX(float inValue) {
_x = inValue;
}
float Bone::getY() {
return _y;
}
void Bone::setY(float inValue) {
_y = inValue;
}
float Bone::getRotation() {
return _rotation;
}
void Bone::setRotation(float inValue) {
_rotation = inValue;
}
float Bone::getScaleX() {
return _scaleX;
}
void Bone::setScaleX(float inValue) {
_scaleX = inValue;
}
float Bone::getScaleY() {
return _scaleY;
}
void Bone::setScaleY(float inValue) {
_scaleY = inValue;
}
float Bone::getShearX() {
return _shearX;
}
void Bone::setShearX(float inValue) {
_shearX = inValue;
}
float Bone::getShearY() {
return _shearY;
}
void Bone::setShearY(float inValue) {
_shearY = inValue;
}
float Bone::getAppliedRotation() {
return _arotation;
}
void Bone::setAppliedRotation(float inValue) {
_arotation = inValue;
}
float Bone::getAX() {
return _ax;
}
void Bone::setAX(float inValue) {
_ax = inValue;
}
float Bone::getAY() {
return _ay;
}
void Bone::setAY(float inValue) {
_ay = inValue;
}
float Bone::getAScaleX() {
return _ascaleX;
}
void Bone::setAScaleX(float inValue) {
_ascaleX = inValue;
}
float Bone::getAScaleY() {
return _ascaleY;
}
void Bone::setAScaleY(float inValue) {
_ascaleY = inValue;
}
float Bone::getAShearX() {
return _ashearX;
}
void Bone::setAShearX(float inValue) {
_ashearX = inValue;
}
float Bone::getAShearY() {
return _ashearY;
}
void Bone::setAShearY(float inValue) {
_ashearY = inValue;
}
float Bone::getA() {
return _a;
}
void Bone::setA(float inValue) {
_a = inValue;
}
float Bone::getB() {
return _b;
}
void Bone::setB(float inValue) {
_b = inValue;
}
float Bone::getC() {
return _c;
}
void Bone::setC(float inValue) {
_c = inValue;
}
float Bone::getD() {
return _d;
}
void Bone::setD(float inValue) {
_d = inValue;
}
float Bone::getWorldX() {
return _worldX;
}
void Bone::setWorldX(float inValue) {
_worldX = inValue;
}
float Bone::getWorldY() {
return _worldY;
}
void Bone::setWorldY(float inValue) {
_worldY = inValue;
}
float Bone::getWorldRotationX() {
return MathUtil::atan2Deg(_c, _a);
}
float Bone::getWorldRotationY() {
return MathUtil::atan2Deg(_d, _b);
}
float Bone::getWorldScaleX() {
return MathUtil::sqrt(_a * _a + _c * _c);
}
float Bone::getWorldScaleY() {
return MathUtil::sqrt(_b * _b + _d * _d);
}
void Bone::updateAppliedTransform() {
Bone *parent = _parent;
if (!parent) {
_ax = _worldX - _skeleton.getX();
_ay = _worldY - _skeleton.getY();
_arotation = MathUtil::atan2Deg(_c, _a);
_ascaleX = MathUtil::sqrt(_a * _a + _c * _c);
_ascaleY = MathUtil::sqrt(_b * _b + _d * _d);
_ashearX = 0;
_ashearY = MathUtil::atan2Deg(_a * _b + _c * _d, _a * _d - _b * _c);
}
float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d;
float pid = 1 / (pa * pd - pb * pc);
float ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid;
float dx = _worldX - parent->_worldX, dy = _worldY - parent->_worldY;
_ax = (dx * ia - dy * ib);
_ay = (dy * id - dx * ic);
float ra, rb, rc, rd;
if (_inherit == Inherit_OnlyTranslation) {
ra = _a;
rb = _b;
rc = _c;
rd = _d;
} else {
switch (_inherit) {
case Inherit_NoRotationOrReflection: {
float s = MathUtil::abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
float sa = pa / _skeleton.getScaleX();
float sc = pc / _skeleton.getScaleY();
pb = -sc * s * _skeleton.getScaleX();
pd = sa * s * _skeleton.getScaleY();
pid = 1 / (pa * pd - pb * pc);
ia = pd * pid;
ib = pb * pid;
break;
}
case Inherit_NoScale:
case Inherit_NoScaleOrReflection: {
float r = _rotation * MathUtil::Deg_Rad;
float cos = MathUtil::cos(r), sin = MathUtil::sin(r);
pa = (pa * cos + pb * sin) / _skeleton.getScaleX();
pc = (pc * cos + pd * sin) / _skeleton.getScaleY();
float s = MathUtil::sqrt(pa * pa + pc * pc);
if (s > 0.00001) s = 1 / s;
pa *= s;
pc *= s;
s = MathUtil::sqrt(pa * pa + pc * pc);
if (_inherit == Inherit_NoScale &&
pid < 0 != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0))
s = -s;
r = MathUtil::Pi / 2 + MathUtil::atan2(pc, pa);
pb = MathUtil::cos(r) * s;
pd = MathUtil::sin(r) * s;
pid = 1 / (pa * pd - pb * pc);
ia = pd * pid;
ib = pb * pid;
ic = pc * pid;
id = pa * pid;
break;
}
case Inherit_Normal:
case Inherit_OnlyTranslation:
break;
}
ra = ia * _a - ib * _c;
rb = ia * _b - ib * _d;
rc = id * _c - ic * _a;
rd = id * _d - ic * _b;
}
_ashearX = 0;
_ascaleX = MathUtil::sqrt(ra * ra + rc * rc);
if (_ascaleX > 0.0001f) {
float det = ra * rd - rb * rc;
_ascaleY = det / _ascaleX;
_ashearY = -MathUtil::atan2Deg(ra * rb + rc * rd, det);
_arotation = MathUtil::atan2Deg(rc, ra);
} else {
_ascaleX = 0;
_ascaleY = MathUtil::sqrt(rb * rb + rd * rd);
_ashearY = 0;
_arotation = 90 - MathUtil::atan2Deg(rd, rb);
}
}
bool Bone::isActive() {
return _active;
}
void Bone::setActive(bool inValue) {
_active = inValue;
}
}

View File

@ -32,42 +32,42 @@
#include <spine/Event.h>
#include <spine/Skeleton.h>
namespace spine {
RTTI_IMPL_NOPARENT(Timeline)
using namespace spine;
Timeline::Timeline(size_t frameCount, size_t frameEntries)
: _propertyIds(), _frames(), _frameEntries(frameEntries) {
_frames.setSize(frameCount * frameEntries, 0);
}
RTTI_IMPL_NOPARENT(Timeline)
Timeline::~Timeline() {
}
Timeline::Timeline(size_t frameCount, size_t frameEntries)
: _propertyIds(), _frames(), _frameEntries(frameEntries) {
_frames.setSize(frameCount * frameEntries, 0);
}
Vector<PropertyId> &Timeline::getPropertyIds() {
return _propertyIds;
}
Timeline::~Timeline() {
}
void Timeline::setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount) {
_propertyIds.clear();
_propertyIds.ensureCapacity(propertyIdsCount);
for (size_t i = 0; i < propertyIdsCount; i++) {
_propertyIds.add(propertyIds[i]);
}
}
Vector<PropertyId> &Timeline::getPropertyIds() {
return _propertyIds;
}
size_t Timeline::getFrameCount() {
return _frames.size() / _frameEntries;
void Timeline::setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount) {
_propertyIds.clear();
_propertyIds.ensureCapacity(propertyIdsCount);
for (size_t i = 0; i < propertyIdsCount; i++) {
_propertyIds.add(propertyIds[i]);
}
}
Vector<float> &Timeline::getFrames() {
return _frames;
}
size_t Timeline::getFrameCount() {
return _frames.size() / _frameEntries;
}
size_t Timeline::getFrameEntries() {
return _frameEntries;
}
Vector<float> &Timeline::getFrames() {
return _frames;
}
float Timeline::getDuration() {
return _frames[_frames.size() - getFrameEntries()];
}
}// namespace spine
size_t Timeline::getFrameEntries() {
return _frameEntries;
}
float Timeline::getDuration() {
return _frames[_frames.size() - getFrameEntries()];
}