mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 07:14:55 +08:00
[cpp] 4.3 porting WIP
This commit is contained in:
parent
2e369a8130
commit
e3fb50da5b
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
62
spine-cpp/spine-cpp/include/spine/Constraint.h
Normal file
62
spine-cpp/spine-cpp/include/spine/Constraint.h
Normal 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 */
|
||||
@ -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();
|
||||
|
||||
@ -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 */
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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()];
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user