[cpp] Inherit timeline, latest ports from reference implementation, excluding loaders

This commit is contained in:
Mario Zechner 2024-03-28 12:09:20 +01:00
parent ce9bcd711d
commit 8210d25e2e
27 changed files with 439 additions and 197 deletions

View File

@ -250,6 +250,8 @@ namespace spine {
void setMixDuration(float inValue); void setMixDuration(float inValue);
void setMixDuration(float mixDuration, float delay);
MixBlend getMixBlend(); MixBlend getMixBlend();
void setMixBlend(MixBlend blend); void setMixBlend(MixBlend blend);
@ -277,6 +279,9 @@ namespace spine {
void setListener(AnimationStateListenerObject *listener); void setListener(AnimationStateListenerObject *listener);
/// Returns true if this track entry has been applied at least once.
///
/// See AnimationState::apply(Skeleton).
bool wasApplied(); bool wasApplied();
private: private:

View File

@ -33,6 +33,7 @@
#include <spine/Updatable.h> #include <spine/Updatable.h>
#include <spine/SpineObject.h> #include <spine/SpineObject.h>
#include <spine/Vector.h> #include <spine/Vector.h>
#include <spine/Inherit.h>
namespace spine { namespace spine {
class BoneData; class BoneData;
@ -95,6 +96,8 @@ namespace spine {
friend class TranslateYTimeline; friend class TranslateYTimeline;
friend class InheritTimeline;
RTTI_DECL RTTI_DECL
public: public:
@ -125,8 +128,12 @@ namespace spine {
void worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY); 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 localToWorld(float localX, float localY, float &outWorldX, float &outWorldY);
void parentToWorld(float worldX, float worldY, float &outX, float &outY);
float worldToLocalRotation(float worldRotation); float worldToLocalRotation(float worldRotation);
float localToWorldRotation(float localRotation); float localToWorldRotation(float localRotation);
@ -255,6 +262,10 @@ namespace spine {
void setActive(bool inValue); void setActive(bool inValue);
Inherit getInherit() { return _inherit; }
void setInherit(Inherit inValue) { _inherit = inValue; }
private: private:
static bool yDown; static bool yDown;
@ -268,6 +279,7 @@ namespace spine {
float _c, _d, _worldY; float _c, _d, _worldY;
bool _sorted; bool _sorted;
bool _active; bool _active;
Inherit _inherit;
}; };
} }

View File

@ -30,7 +30,7 @@
#ifndef Spine_BoneData_h #ifndef Spine_BoneData_h
#define Spine_BoneData_h #define Spine_BoneData_h
#include <spine/TransformMode.h> #include <spine/Inherit.h>
#include <spine/SpineObject.h> #include <spine/SpineObject.h>
#include <spine/SpineString.h> #include <spine/SpineString.h>
#include <spine/Color.h> #include <spine/Color.h>
@ -115,9 +115,9 @@ namespace spine {
void setShearY(float inValue); void setShearY(float inValue);
/// The transform mode for how parent world transforms affect this bone. /// The transform mode for how parent world transforms affect this bone.
TransformMode getTransformMode(); Inherit getInherit();
void setTransformMode(TransformMode inValue); void setInherit(Inherit inValue);
bool isSkinRequired(); bool isSkinRequired();
@ -139,7 +139,7 @@ namespace spine {
BoneData *_parent; BoneData *_parent;
float _length; float _length;
float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY;
TransformMode _transformMode; Inherit _inherit;
bool _skinRequired; bool _skinRequired;
Color _color; Color _color;
String _icon; String _icon;

View File

@ -31,12 +31,12 @@
#define Spine_TransformMode_h #define Spine_TransformMode_h
namespace spine { namespace spine {
enum TransformMode { enum Inherit {
TransformMode_Normal = 0, Inherit_Normal = 0,
TransformMode_OnlyTranslation, Inherit_OnlyTranslation,
TransformMode_NoRotationOrReflection, Inherit_NoRotationOrReflection,
TransformMode_NoScale, Inherit_NoScale,
TransformMode_NoScaleOrReflection Inherit_NoScaleOrReflection
}; };
} }

View File

@ -0,0 +1,68 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated July 28, 2023. Replaces all prior versions.
*
* Copyright (c) 2013-2023, 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_InheritTimeline_h
#define Spine_InheritTimeline_h
#include <spine/Timeline.h>
#include <spine/Animation.h>
#include <spine/Property.h>
#include <spine/Inherit.h>
namespace spine {
class SP_API InheritTimeline : public Timeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit InheritTimeline(size_t frameCount, int boneIndex);
virtual ~InheritTimeline();
void setFrame(int frame, float time, Inherit inherit);
virtual void
apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixBlend blend,
MixDirection direction);
int getBoneIndex() { return _boneIndex; }
void setBoneIndex(int inValue) { _boneIndex = inValue; }
private:
int _boneIndex;
};
}
#endif /* Spine_InheritTimeline_h */

View File

@ -76,6 +76,10 @@ namespace spine {
float getShearX() const; float getShearX() const;
void setLimit(float limit);
float getLimit() const;
void setStep(float step); void setStep(float step);
float getStep() const; float getStep() const;
@ -138,7 +142,7 @@ namespace spine {
private: private:
BoneData *_bone; BoneData *_bone;
float _x, _y, _rotate, _scaleX, _shearX; float _x, _y, _rotate, _scaleX, _shearX, _limit;
float _step, _inertia, _strength, _damping, _massInverse, _wind, _gravity, _mix; float _step, _inertia, _strength, _damping, _massInverse, _wind, _gravity, _mix;
bool _inertiaGlobal, _strengthGlobal, _dampingGlobal, _massGlobal, _windGlobal, _gravityGlobal, _mixGlobal; bool _inertiaGlobal, _strengthGlobal, _dampingGlobal, _massGlobal, _windGlobal, _gravityGlobal, _mixGlobal;
}; };

View File

@ -40,27 +40,28 @@ namespace spine {
Property_ScaleY = 1 << 4, Property_ScaleY = 1 << 4,
Property_ShearX = 1 << 5, Property_ShearX = 1 << 5,
Property_ShearY = 1 << 6, Property_ShearY = 1 << 6,
Property_Rgb = 1 << 7, Property_Inherit = 1 << 7,
Property_Alpha = 1 << 8, Property_Rgb = 1 << 8,
Property_Rgb2 = 1 << 9, Property_Alpha = 1 << 9,
Property_Attachment = 1 << 10, Property_Rgb2 = 1 << 10,
Property_Deform = 1 << 11, Property_Attachment = 1 << 11,
Property_Event = 1 << 12, Property_Deform = 1 << 12,
Property_DrawOrder = 1 << 13, Property_Event = 1 << 13,
Property_IkConstraint = 1 << 14, Property_DrawOrder = 1 << 14,
Property_TransformConstraint = 1 << 15, Property_IkConstraint = 1 << 15,
Property_PathConstraintPosition = 1 << 16, Property_TransformConstraint = 1 << 16,
Property_PathConstraintSpacing = 1 << 17, Property_PathConstraintPosition = 1 << 17,
Property_PathConstraintMix = 1 << 18, Property_PathConstraintSpacing = 1 << 18,
Property_PhysicsConstraintInertia = 1 << 19, Property_PathConstraintMix = 1 << 19,
Property_PhysicsConstraintStrength = 1 << 20, Property_PhysicsConstraintInertia = 1 << 20,
Property_PhysicsConstraintDamping = 1 << 21, Property_PhysicsConstraintStrength = 1 << 21,
Property_PhysicsConstraintMass = 1 << 22, Property_PhysicsConstraintDamping = 1 << 22,
Property_PhysicsConstraintWind = 1 << 23, Property_PhysicsConstraintMass = 1 << 23,
Property_PhysicsConstraintGravity = 1 << 24, Property_PhysicsConstraintWind = 1 << 24,
Property_PhysicsConstraintMix = 1 << 25, Property_PhysicsConstraintGravity = 1 << 25,
Property_PhysicsConstraintReset = 1 << 26, Property_PhysicsConstraintMix = 1 << 26,
Property_Sequence = 1 << 27 Property_PhysicsConstraintReset = 1 << 27,
Property_Sequence = 1 << 28
}; };
} }

View File

@ -30,7 +30,7 @@
#ifndef Spine_SkeletonBinary_h #ifndef Spine_SkeletonBinary_h
#define Spine_SkeletonBinary_h #define Spine_SkeletonBinary_h
#include <spine/TransformMode.h> #include <spine/Inherit.h>
#include <spine/Vector.h> #include <spine/Vector.h>
#include <spine/SpineObject.h> #include <spine/SpineObject.h>
#include <spine/SpineString.h> #include <spine/SpineString.h>

View File

@ -141,6 +141,10 @@ namespace spine {
void setHeight(float inValue); void setHeight(float inValue);
float getReferenceScale();
void setReferenceScale(float inValue);
/// The Spine version used to export this data, or NULL. /// The Spine version used to export this data, or NULL.
const String &getVersion(); const String &getVersion();
@ -176,6 +180,7 @@ namespace spine {
Vector<PathConstraintData *> _pathConstraints; Vector<PathConstraintData *> _pathConstraints;
Vector<PhysicsConstraintData *> _physicsConstraints; Vector<PhysicsConstraintData *> _physicsConstraints;
float _x, _y, _width, _height; float _x, _y, _width, _height;
float _referenceScale;
String _version; String _version;
String _hash; String _hash;
Vector<char *> _strings; Vector<char *> _strings;

View File

@ -32,6 +32,7 @@
#include <spine/Vector.h> #include <spine/Vector.h>
#include <spine/SpineString.h> #include <spine/SpineString.h>
#include <spine/Color.h>
namespace spine { namespace spine {
class Attachment; class Attachment;
@ -153,11 +154,14 @@ namespace spine {
Vector<ConstraintData *> &getConstraints(); Vector<ConstraintData *> &getConstraints();
Color &getColor() { return _color; }
private: private:
const String _name; const String _name;
AttachmentMap _attachments; AttachmentMap _attachments;
Vector<BoneData *> _bones; Vector<BoneData *> _bones;
Vector<ConstraintData *> _constraints; Vector<ConstraintData *> _constraints;
Color _color;
/// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached.
void attachAll(Skeleton &skeleton, Skin &oldSkin); void attachAll(Skeleton &skeleton, Skin &oldSkin);

View File

@ -109,6 +109,10 @@ namespace spine {
void setVisible(bool inValue); void setVisible(bool inValue);
String &getPath() { return _path; }
void setPath(const String &inValue) { _path = inValue; }
private: private:
const int _index; const int _index;
String _name; String _name;
@ -120,6 +124,7 @@ namespace spine {
String _attachmentName; String _attachmentName;
BlendMode _blendMode; BlendMode _blendMode;
bool _visible; bool _visible;
String _path;
}; };
} }

View File

@ -60,6 +60,7 @@
#include <spine/IkConstraint.h> #include <spine/IkConstraint.h>
#include <spine/IkConstraintData.h> #include <spine/IkConstraintData.h>
#include <spine/IkConstraintTimeline.h> #include <spine/IkConstraintTimeline.h>
#include <spine/InheritTimeline.h>
#include <spine/Json.h> #include <spine/Json.h>
#include <spine/LinkedMesh.h> #include <spine/LinkedMesh.h>
#include <spine/MathUtil.h> #include <spine/MathUtil.h>
@ -101,7 +102,7 @@
#include <spine/TransformConstraint.h> #include <spine/TransformConstraint.h>
#include <spine/TransformConstraintData.h> #include <spine/TransformConstraintData.h>
#include <spine/TransformConstraintTimeline.h> #include <spine/TransformConstraintTimeline.h>
#include <spine/TransformMode.h> #include <spine/Inherit.h>
#include <spine/TranslateTimeline.h> #include <spine/TranslateTimeline.h>
#include <spine/Triangulator.h> #include <spine/Triangulator.h>
#include <spine/Updatable.h> #include <spine/Updatable.h>

View File

@ -162,6 +162,12 @@ float TrackEntry::getMixDuration() { return _mixDuration; }
void TrackEntry::setMixDuration(float inValue) { _mixDuration = inValue; } void TrackEntry::setMixDuration(float inValue) { _mixDuration = inValue; }
void TrackEntry::setMixDuration(float mixDuration, float delay) {
_mixDuration = mixDuration;
if (_previous && delay <= 0) delay += _previous->getTrackComplete() - mixDuration;
this->_delay = delay;
}
TrackEntry *TrackEntry::getMixingFrom() { return _mixingFrom; } TrackEntry *TrackEntry::getMixingFrom() { return _mixingFrom; }
TrackEntry *TrackEntry::getMixingTo() { return _mixingTo; } TrackEntry *TrackEntry::getMixingTo() { return _mixingTo; }
@ -484,7 +490,7 @@ bool AnimationState::apply(Skeleton &skeleton) {
timelineBlend, timelinesRotation, ii << 1, firstFrame); timelineBlend, timelinesRotation, ii << 1, firstFrame);
else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti))
applyAttachmentTimeline(static_cast<AttachmentTimeline *>(timeline), skeleton, applyTime, applyAttachmentTimeline(static_cast<AttachmentTimeline *>(timeline), skeleton, applyTime,
timelineBlend, true); blend, attachments);
else else
timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend, timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend,
MixDirection_In); MixDirection_In);
@ -928,10 +934,16 @@ void AnimationState::queueEvents(TrackEntry *entry, float animationTime) {
// Queue complete if completed a loop iteration or the animation. // Queue complete if completed a loop iteration or the animation.
bool complete = false; bool complete = false;
if (entry->_loop) if (entry->_loop) {
complete = duration == 0 || (trackLastWrapped > MathUtil::fmod(entry->_trackTime, duration)); if (duration == 0)
else complete = true;
else {
int cycles = (int) (entry->_trackTime / duration);
complete = cycles > 0 && cycles > (int) (entry->_trackLast / duration);
}
} else {
complete = animationTime >= animationEnd && entry->_animationLast < animationEnd; complete = animationTime >= animationEnd && entry->_animationLast < animationEnd;
}
if (complete) _queue->complete(entry); if (complete) _queue->complete(entry);
// Queue events after complete. // Queue events after complete.
@ -985,8 +997,8 @@ TrackEntry *AnimationState::newTrackEntry(size_t trackIndex, Animation *animatio
entry._shortestRotation = false; entry._shortestRotation = false;
entry._eventThreshold = 0; entry._eventThreshold = 0;
entry._mixAttachmentThreshold = 0;
entry._alphaAttachmentThreshold = 0; entry._alphaAttachmentThreshold = 0;
entry._mixAttachmentThreshold = 0;
entry._mixDrawOrderThreshold = 0; entry._mixDrawOrderThreshold = 0;
entry._animationStart = 0; entry._animationStart = 0;

View File

@ -71,7 +71,8 @@ Bone::Bone(BoneData &data, Skeleton &skeleton, Bone *parent) : Updatable(),
_d(1), _d(1),
_worldY(0), _worldY(0),
_sorted(false), _sorted(false),
_active(false) { _active(false),
_inherit(Inherit_Normal){
setToSetupPose(); setToSetupPose();
} }
@ -118,8 +119,8 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX,
_worldX = pa * x + pb * y + parent->_worldX; _worldX = pa * x + pb * y + parent->_worldX;
_worldY = pc * x + pd * y + parent->_worldY; _worldY = pc * x + pd * y + parent->_worldY;
switch (_data.getTransformMode()) { switch (_inherit) {
case TransformMode_Normal: { case Inherit_Normal: {
float rx = (rotation + shearX) * MathUtil::Deg_Rad; float rx = (rotation + shearX) * MathUtil::Deg_Rad;
float ry = (rotation + 90 + shearY) * MathUtil::Deg_Rad; float ry = (rotation + 90 + shearY) * MathUtil::Deg_Rad;
float la = MathUtil::cos(rx) * scaleX; float la = MathUtil::cos(rx) * scaleX;
@ -132,7 +133,7 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX,
_d = pc * lb + pd * ld; _d = pc * lb + pd * ld;
return; return;
} }
case TransformMode_OnlyTranslation: { case Inherit_OnlyTranslation: {
float rx = (rotation + shearX) * MathUtil::Deg_Rad; float rx = (rotation + shearX) * MathUtil::Deg_Rad;
float ry = (rotation + 90 + shearY) * MathUtil::Deg_Rad; float ry = (rotation + 90 + shearY) * MathUtil::Deg_Rad;
_a = MathUtil::cos(rx) * scaleX; _a = MathUtil::cos(rx) * scaleX;
@ -141,7 +142,7 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX,
_d = MathUtil::sin(ry) * scaleY; _d = MathUtil::sin(ry) * scaleY;
break; break;
} }
case TransformMode_NoRotationOrReflection: { case Inherit_NoRotationOrReflection: {
float s = pa * pa + pc * pc; float s = pa * pa + pc * pc;
float prx; float prx;
if (s > 0.0001f) { if (s > 0.0001f) {
@ -150,11 +151,11 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX,
pc /= _skeleton.getScaleY(); pc /= _skeleton.getScaleY();
pb = pc * s; pb = pc * s;
pd = pa * s; pd = pa * s;
prx = MathUtil::atan2(pc, pa) * MathUtil::Rad_Deg; prx = MathUtil::atan2Deg(pc, pa);
} else { } else {
pa = 0; pa = 0;
pc = 0; pc = 0;
prx = 90 - MathUtil::atan2(pd, pb) * MathUtil::Rad_Deg; prx = 90 - MathUtil::atan2Deg(pd, pb);
} }
float rx = (rotation + shearX - prx) * MathUtil::Deg_Rad; float rx = (rotation + shearX - prx) * MathUtil::Deg_Rad;
float ry = (rotation + shearY - prx + 90) * MathUtil::Deg_Rad; float ry = (rotation + shearY - prx + 90) * MathUtil::Deg_Rad;
@ -168,8 +169,8 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX,
_d = pc * lb + pd * ld; _d = pc * lb + pd * ld;
break; break;
} }
case TransformMode_NoScale: case Inherit_NoScale:
case TransformMode_NoScaleOrReflection: { case Inherit_NoScaleOrReflection: {
rotation *= MathUtil::Deg_Rad; rotation *= MathUtil::Deg_Rad;
float cosine = MathUtil::cos(rotation); float cosine = MathUtil::cos(rotation);
float sine = MathUtil::sin(rotation); float sine = MathUtil::sin(rotation);
@ -180,7 +181,7 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX,
za *= s; za *= s;
zc *= s; zc *= s;
s = MathUtil::sqrt(za * za + zc * zc); s = MathUtil::sqrt(za * za + zc * zc);
if (_data.getTransformMode() == TransformMode_NoScale && if (_inherit == Inherit_NoScale &&
(pa * pd - pb * pc < 0) != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0)) (pa * pd - pb * pc < 0) != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0))
s = -s; s = -s;
rotation = MathUtil::Pi / 2 + MathUtil::atan2(zc, za); rotation = MathUtil::Pi / 2 + MathUtil::atan2(zc, za);
@ -213,6 +214,7 @@ void Bone::setToSetupPose() {
_scaleY = data.getScaleY(); _scaleY = data.getScaleY();
_shearX = data.getShearX(); _shearX = data.getShearX();
_shearY = data.getShearY(); _shearY = data.getShearY();
_inherit = data.getInherit();
} }
void Bone::worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY) { void Bone::worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY) {
@ -229,25 +231,39 @@ void Bone::worldToLocal(float worldX, float worldY, float &outLocalX, float &out
outLocalY = (y * a * invDet - x * c * 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) { void Bone::localToWorld(float localX, float localY, float &outWorldX, float &outWorldY) {
outWorldX = localX * _a + localY * _b + _worldX; outWorldX = localX * _a + localY * _b + _worldX;
outWorldY = localX * _c + localY * _d + _worldY; outWorldY = localX * _c + localY * _d + _worldY;
} }
float Bone::worldToLocalRotation(float worldRotation) { void Bone::parentToWorld(float worldX, float worldY, float &outX, float &outY) {
float sin = MathUtil::sinDeg(worldRotation); if (!_parent) {
float cos = MathUtil::cosDeg(worldRotation); outX = worldX;
outY = worldY;
} else {
_parent->localToWorld(worldX, worldY, outX, outY);
}
}
return MathUtil::atan2(_a * sin - _c * cos, _d * cos - _b * sin) * MathUtil::Rad_Deg + this->_rotation - float Bone::worldToLocalRotation(float worldRotation) {
this->_shearX; 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) { float Bone::localToWorldRotation(float localRotation) {
localRotation -= this->_rotation - this->_shearX; localRotation = (localRotation - _rotation - _shearX) * MathUtil::Deg_Rad;
float sin = MathUtil::sinDeg(localRotation); float sine = MathUtil::sin(localRotation), cosine = MathUtil::cos(localRotation);
float cos = MathUtil::cosDeg(localRotation); return MathUtil::atan2Deg(cosine * _c + sine * _d, cosine * _a + sine * _b);
return MathUtil::atan2(cos * _c + sin * _d, cos * _a + sin * _b) * MathUtil::Rad_Deg;
} }
void Bone::rotateWorld(float degrees) { void Bone::rotateWorld(float degrees) {
@ -469,11 +485,11 @@ void Bone::setWorldY(float inValue) {
} }
float Bone::getWorldRotationX() { float Bone::getWorldRotationX() {
return MathUtil::atan2(_c, _a) * MathUtil::Rad_Deg; return MathUtil::atan2Deg(_c, _a);
} }
float Bone::getWorldRotationY() { float Bone::getWorldRotationY() {
return MathUtil::atan2(_d, _b) * MathUtil::Rad_Deg; return MathUtil::atan2Deg(_d, _b);
} }
float Bone::getWorldScaleX() { float Bone::getWorldScaleX() {
@ -489,11 +505,11 @@ void Bone::updateAppliedTransform() {
if (!parent) { if (!parent) {
_ax = _worldX - _skeleton.getX(); _ax = _worldX - _skeleton.getX();
_ay = _worldY - _skeleton.getY(); _ay = _worldY - _skeleton.getY();
_arotation = MathUtil::atan2(_c, _a) * MathUtil::Rad_Deg; _arotation = MathUtil::atan2Deg(_c, _a);
_ascaleX = MathUtil::sqrt(_a * _a + _c * _c); _ascaleX = MathUtil::sqrt(_a * _a + _c * _c);
_ascaleY = MathUtil::sqrt(_b * _b + _d * _d); _ascaleY = MathUtil::sqrt(_b * _b + _d * _d);
_ashearX = 0; _ashearX = 0;
_ashearY = MathUtil::atan2(_a * _b + _c * _d, _a * _d - _b * _c) * MathUtil::Rad_Deg; _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 pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d;
float pid = 1 / (pa * pd - pb * pc); float pid = 1 / (pa * pd - pb * pc);
@ -503,14 +519,14 @@ void Bone::updateAppliedTransform() {
_ay = (dy * id - dx * ic); _ay = (dy * id - dx * ic);
float ra, rb, rc, rd; float ra, rb, rc, rd;
if (_data.getTransformMode() == TransformMode_OnlyTranslation) { if (_inherit == Inherit_OnlyTranslation) {
ra = _a; ra = _a;
rb = _b; rb = _b;
rc = _c; rc = _c;
rd = _d; rd = _d;
} else { } else {
switch (_data.getTransformMode()) { switch (_inherit) {
case TransformMode_NoRotationOrReflection: { case Inherit_NoRotationOrReflection: {
float s = MathUtil::abs(pa * pd - pb * pc) / (pa * pa + pc * pc); float s = MathUtil::abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
float sa = pa / _skeleton.getScaleX(); float sa = pa / _skeleton.getScaleX();
float sc = pc / _skeleton.getScaleY(); float sc = pc / _skeleton.getScaleY();
@ -521,9 +537,10 @@ void Bone::updateAppliedTransform() {
ib = pb * pid; ib = pb * pid;
break; break;
} }
case TransformMode_NoScale: case Inherit_NoScale:
case TransformMode_NoScaleOrReflection: { case Inherit_NoScaleOrReflection: {
float cos = MathUtil::cosDeg(_rotation), sin = MathUtil::sinDeg(_rotation); float r = _rotation * MathUtil::Deg_Rad;
float cos = MathUtil::cos(r), sin = MathUtil::sin(r);
pa = (pa * cos + pb * sin) / _skeleton.getScaleX(); pa = (pa * cos + pb * sin) / _skeleton.getScaleX();
pc = (pc * cos + pd * sin) / _skeleton.getScaleY(); pc = (pc * cos + pd * sin) / _skeleton.getScaleY();
float s = MathUtil::sqrt(pa * pa + pc * pc); float s = MathUtil::sqrt(pa * pa + pc * pc);
@ -531,10 +548,10 @@ void Bone::updateAppliedTransform() {
pa *= s; pa *= s;
pc *= s; pc *= s;
s = MathUtil::sqrt(pa * pa + pc * pc); s = MathUtil::sqrt(pa * pa + pc * pc);
if (_data.getTransformMode() == TransformMode_NoScale && if (_inherit == Inherit_NoScale &&
pid < 0 != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0)) pid < 0 != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0))
s = -s; s = -s;
float r = MathUtil::Pi / 2 + MathUtil::atan2(pc, pa); r = MathUtil::Pi / 2 + MathUtil::atan2(pc, pa);
pb = MathUtil::cos(r) * s; pb = MathUtil::cos(r) * s;
pd = MathUtil::sin(r) * s; pd = MathUtil::sin(r) * s;
pid = 1 / (pa * pd - pb * pc); pid = 1 / (pa * pd - pb * pc);
@ -544,8 +561,8 @@ void Bone::updateAppliedTransform() {
id = pa * pid; id = pa * pid;
break; break;
} }
case TransformMode_Normal: case Inherit_Normal:
case TransformMode_OnlyTranslation: case Inherit_OnlyTranslation:
break; break;
} }
ra = ia * _a - ib * _c; ra = ia * _a - ib * _c;
@ -559,13 +576,13 @@ void Bone::updateAppliedTransform() {
if (_ascaleX > 0.0001f) { if (_ascaleX > 0.0001f) {
float det = ra * rd - rb * rc; float det = ra * rd - rb * rc;
_ascaleY = det / _ascaleX; _ascaleY = det / _ascaleX;
_ashearY = -MathUtil::atan2(ra * rb + rc * rd, det) * MathUtil::Rad_Deg; _ashearY = -MathUtil::atan2Deg(ra * rb + rc * rd, det);
_arotation = MathUtil::atan2(rc, ra) * MathUtil::Rad_Deg; _arotation = MathUtil::atan2Deg(rc, ra);
} else { } else {
_ascaleX = 0; _ascaleX = 0;
_ascaleY = MathUtil::sqrt(rb * rb + rd * rd); _ascaleY = MathUtil::sqrt(rb * rb + rd * rd);
_ashearY = 0; _ashearY = 0;
_arotation = 90 - MathUtil::atan2(rd, rb) * MathUtil::Rad_Deg; _arotation = 90 - MathUtil::atan2Deg(rd, rb);
} }
} }

View File

@ -44,7 +44,7 @@ BoneData::BoneData(int index, const String &name, BoneData *parent) : _index(ind
_scaleY(1), _scaleY(1),
_shearX(0), _shearX(0),
_shearY(0), _shearY(0),
_transformMode(TransformMode_Normal), _inherit(Inherit_Normal),
_skinRequired(false), _skinRequired(false),
_color(), _color(),
_icon(), _icon(),
@ -129,12 +129,12 @@ void BoneData::setShearY(float inValue) {
_shearY = inValue; _shearY = inValue;
} }
TransformMode BoneData::getTransformMode() { Inherit BoneData::getInherit() {
return _transformMode; return _inherit;
} }
void BoneData::setTransformMode(TransformMode inValue) { void BoneData::setInherit(Inherit inValue) {
_transformMode = inValue; _inherit = inValue;
} }
bool BoneData::isSkinRequired() { bool BoneData::isSkinRequired() {

View File

@ -45,18 +45,18 @@ void IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress
float rotationIK = -bone._ashearX - bone._arotation; float rotationIK = -bone._ashearX - bone._arotation;
float tx = 0, ty = 0; float tx = 0, ty = 0;
switch (bone._data.getTransformMode()) { switch (bone._data.getInherit()) {
case TransformMode_OnlyTranslation: case Inherit_OnlyTranslation:
tx = (targetX - bone._worldX) * MathUtil::sign(bone.getSkeleton().getScaleX()); tx = (targetX - bone._worldX) * MathUtil::sign(bone.getSkeleton().getScaleX());
ty = (targetY - bone._worldY) * MathUtil::sign(bone.getSkeleton().getScaleY()); ty = (targetY - bone._worldY) * MathUtil::sign(bone.getSkeleton().getScaleY());
break; break;
case TransformMode_NoRotationOrReflection: { case Inherit_NoRotationOrReflection: {
float s = MathUtil::abs(pa * pd - pb * pc) / MathUtil::max(0.0001f, pa * pa + pc * pc); float s = MathUtil::abs(pa * pd - pb * pc) / MathUtil::max(0.0001f, pa * pa + pc * pc);
float sa = pa / bone._skeleton.getScaleX(); float sa = pa / bone._skeleton.getScaleX();
float sc = pc / bone._skeleton.getScaleY(); float sc = pc / bone._skeleton.getScaleY();
pb = -sc * s * bone._skeleton.getScaleX(); pb = -sc * s * bone._skeleton.getScaleX();
pd = sa * s * bone._skeleton.getScaleY(); pd = sa * s * bone._skeleton.getScaleY();
rotationIK += MathUtil::atan2(sc, sa) * MathUtil::Rad_Deg; rotationIK += MathUtil::atan2Deg(sc, sa);
} }
default: default:
float x = targetX - p->_worldX, y = targetY - p->_worldY; float x = targetX - p->_worldX, y = targetY - p->_worldY;
@ -69,7 +69,7 @@ void IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress
ty = (y * pa - x * pc) / d - bone._ay; ty = (y * pa - x * pc) / d - bone._ay;
} }
} }
rotationIK += MathUtil::atan2(ty, tx) * MathUtil::Rad_Deg; rotationIK += MathUtil::atan2Deg(ty, tx);
if (bone._ascaleX < 0) rotationIK += 180; if (bone._ascaleX < 0) rotationIK += 180;
if (rotationIK > 180) rotationIK -= 360; if (rotationIK > 180) rotationIK -= 360;
else if (rotationIK < -180) else if (rotationIK < -180)
@ -77,9 +77,9 @@ void IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress
float sx = bone._ascaleX; float sx = bone._ascaleX;
float sy = bone._ascaleY; float sy = bone._ascaleY;
if (compress || stretch) { if (compress || stretch) {
switch (bone._data.getTransformMode()) { switch (bone._data.getInherit()) {
case TransformMode_NoScale: case Inherit_NoScale:
case TransformMode_NoScaleOrReflection: case Inherit_NoScaleOrReflection:
tx = targetX - bone._worldX; tx = targetX - bone._worldX;
ty = targetY - bone._worldY; ty = targetY - bone._worldY;
default:; default:;

View File

@ -0,0 +1,80 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated July 28, 2023. Replaces all prior versions.
*
* Copyright (c) 2013-2023, 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/InheritTimeline.h>
#include <spine/Event.h>
#include <spine/Skeleton.h>
#include <spine/Bone.h>
#include <spine/BoneData.h>
#include <spine/Slot.h>
#include <spine/SlotData.h>
using namespace spine;
RTTI_IMPL(InheritTimeline, Timeline)
#define ENTRIES 2
#define INHERIT 1
InheritTimeline::InheritTimeline(size_t frameCount, int boneIndex) : Timeline(frameCount, ENTRIES),
_boneIndex(boneIndex) {
PropertyId ids[] = {((PropertyId) Property_Inherit << 32) | boneIndex };
setPropertyIds(ids, 1);
}
InheritTimeline::~InheritTimeline() {
}
void InheritTimeline::setFrame(int frame, float time, Inherit inherit) {
frame *= ENTRIES;
_frames[frame] = time;
_frames[frame + INHERIT] = inherit;
}
void InheritTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
MixBlend blend, MixDirection direction) {
SP_UNUSED(lastTime);
SP_UNUSED(pEvents);
SP_UNUSED(direction);
SP_UNUSED(alpha);
Bone *bone = skeleton.getBones()[_boneIndex];
if (!bone->isActive()) return;
if (time < _frames[0]) {
if (blend == MixBlend_Setup || blend == MixBlend_First) bone->_inherit = bone->_data.getInherit();
return;
}
int idx = Animation::search(_frames, time, ENTRIES) + INHERIT;
bone->_inherit = (Inherit)_frames[idx];
}

View File

@ -32,6 +32,7 @@
#include <spine/Bone.h> #include <spine/Bone.h>
#include <spine/Skeleton.h> #include <spine/Skeleton.h>
#include <spine/SkeletonData.h>
#include <spine/BoneData.h> #include <spine/BoneData.h>
using namespace spine; using namespace spine;
@ -41,7 +42,6 @@ RTTI_IMPL(PhysicsConstraint, Updatable)
PhysicsConstraint::PhysicsConstraint(PhysicsConstraintData &data, Skeleton &skeleton) PhysicsConstraint::PhysicsConstraint(PhysicsConstraintData &data, Skeleton &skeleton)
: _data(data), _skeleton(skeleton) { : _data(data), _skeleton(skeleton) {
_bone = skeleton.getBones()[data.getBone()->getIndex()]; _bone = skeleton.getBones()[data.getBone()->getIndex()];
_inertia = data.getInertia(); _inertia = data.getInertia();
_strength = data.getStrength(); _strength = data.getStrength();
_damping = data.getDamping(); _damping = data.getDamping();
@ -324,7 +324,8 @@ void PhysicsConstraint::update(Physics physics) {
reset(); reset();
// Fall through. // Fall through.
case Physics::Physics_Update: { case Physics::Physics_Update: {
_remaining += MathUtil::max(_skeleton.getTime() - _lastTime, 0.0f); float delta = MathUtil::max(_skeleton.getTime() - _lastTime, 0.0f);
_remaining += delta;
_lastTime = _skeleton.getTime(); _lastTime = _skeleton.getTime();
float bx = bone->_worldX, by = bone->_worldY; float bx = bone->_worldX, by = bone->_worldY;
@ -333,44 +334,54 @@ void PhysicsConstraint::update(Physics physics) {
_ux = bx; _ux = bx;
_uy = by; _uy = by;
} else { } else {
float remaining = _remaining, i = _inertia, step = _data._step; float a = _remaining, i = _inertia, q = _data._limit * delta, t = _data._step, f = _skeleton.getData()->getReferenceScale(), d = -1;
if (x || y) { if (x || y) {
if (x) { if (x) {
_xOffset += (_ux - bx) * i; float u = (_ux - bx) * i;
_xOffset += u > q ? q : u < -q ? -q : u;
_ux = bx; _ux = bx;
} }
if (y) { if (y) {
_yOffset += (_uy - by) * i; float u = (_uy - by) * i;
_yOffset += u > q ? q : u < -q ? -q : u;
_uy = by; _uy = by;
} }
if (remaining >= step) { if (a >= t) {
float m = _massInverse * step, e = _strength, w = _wind * 100, g = _gravity * -100; d = MathUtil::pow(_damping, 60 * t);
float d = MathUtil::pow(_damping, 60 * step); float m = _massInverse * t, e = _strength, w = _wind * f, g = _gravity * f;
do { do {
if (x) { if (x) {
_xVelocity += (w - _xOffset * e) * m; _xVelocity += (w - _xOffset * e) * m;
_xOffset += _xVelocity * step; _xOffset += _xVelocity * t;
_xVelocity *= d; _xVelocity *= d;
} }
if (y) { if (y) {
_yVelocity += (g - _yOffset * e) * m; _yVelocity -= (g + _yOffset * e) * m;
_yOffset += _yVelocity * step; _yOffset += _yVelocity * t;
_yVelocity *= d; _yVelocity *= d;
} }
remaining -= step; a -= t;
} while (remaining >= step); } while (a >= t);
} }
if (x) bone->_worldX += _xOffset * mix * _data._x; if (x) bone->_worldX += _xOffset * mix * _data._x;
if (y) bone->_worldY += _yOffset * mix * _data._y; if (y) bone->_worldY += _yOffset * mix * _data._y;
} }
if (rotateOrShearX || scaleX) { if (rotateOrShearX || scaleX) {
float ca = MathUtil::atan2(bone->_c, bone->_a), c = 0, s = 0, mr = 0; float ca = MathUtil::atan2(bone->_c, bone->_a), c, s, mr = 0;
float dx = _cx - bone->_worldX, dy = _cy - bone->_worldY;
if (dx > q)
dx = q;
else if (dx < -q) //
dx = -q;
if (dy > q)
dy = q;
else if (dy < -q) //
dy = -q;
if (rotateOrShearX) { if (rotateOrShearX) {
mr = (_data._rotate + _data._shearX) * mix; mr = (_data._rotate + _data._shearX) * mix;
float dx = _cx - bone->_worldX, dy = _cy - bone->_worldY;
float r = MathUtil::atan2(dy + _ty, dx + _tx) - ca - _rotateOffset * mr; float r = MathUtil::atan2(dy + _ty, dx + _tx) - ca - _rotateOffset * mr;
_rotateOffset += (r - MathUtil::ceil(r * MathUtil::InvPi_2 - 0.5) * MathUtil::Pi_2) * i; _rotateOffset += (r - MathUtil::ceil(r * MathUtil::InvPi_2 - 0.5f) * MathUtil::Pi_2) * i;
r = _rotateOffset * mr + ca; r = _rotateOffset * mr + ca;
c = MathUtil::cos(r); c = MathUtil::cos(r);
s = MathUtil::sin(r); s = MathUtil::sin(r);
@ -382,34 +393,33 @@ void PhysicsConstraint::update(Physics physics) {
c = MathUtil::cos(ca); c = MathUtil::cos(ca);
s = MathUtil::sin(ca); s = MathUtil::sin(ca);
float r = l * bone->getWorldScaleX(); float r = l * bone->getWorldScaleX();
if (r > 0) _scaleOffset += ((this->_cx - bone->_worldX) * c + (this->_cy - bone->_worldY) * s) * i / r; if (r > 0) _scaleOffset += (dx * c + dy * s) * i / r;
} }
a = _remaining;
remaining = _remaining; if (a >= t) {
if (remaining >= step) { if (d == -1) d = MathUtil::pow(_damping, 60 * t);
float m = _massInverse * step, e = _strength; float m = _massInverse * t, e = _strength, w = _wind, g = _gravity, h = l / f;
float d = MathUtil::pow(_damping, 60 * step);
while (true) { while (true) {
remaining -= step; a -= t;
if (scaleX) { if (scaleX) {
_scaleVelocity += (_wind * c - _gravity * s - _scaleOffset * e) * m; _scaleVelocity += (w * c - g * s - _scaleOffset * e) * m;
_scaleOffset += _scaleVelocity * step; _scaleOffset += _scaleVelocity * t;
_scaleVelocity *= d; _scaleVelocity *= d;
} }
if (rotateOrShearX) { if (rotateOrShearX) {
_rotateVelocity += (-0.01f * l * (_wind * s + _gravity * c) - _rotateOffset * e) * m; _rotateVelocity -= ((w * s + g * c) * h + _rotateOffset * e) * m;
_rotateOffset += _rotateVelocity * step; _rotateOffset += _rotateVelocity * t;
_rotateVelocity *= d; _rotateVelocity *= d;
if (remaining < step) break; if (a < t) break;
float r = _rotateOffset * mr + ca; float r = _rotateOffset * mr + ca;
c = MathUtil::cos(r); c = MathUtil::cos(r);
s = MathUtil::sin(r); s = MathUtil::sin(r);
} else if (remaining < step)// } else if (a < t) //
break; break;
} }
} }
} }
_remaining = remaining; _remaining = a;
} }
_cx = bone->_worldX; _cx = bone->_worldX;
@ -467,9 +477,6 @@ void PhysicsConstraint::update(Physics physics) {
void PhysicsConstraint::rotate(float x, float y, float degrees) { void PhysicsConstraint::rotate(float x, float y, float degrees) {
float r = degrees * MathUtil::Deg_Rad, cos = MathUtil::cos(r), sin = MathUtil::sin(r); float r = degrees * MathUtil::Deg_Rad, cos = MathUtil::cos(r), sin = MathUtil::sin(r);
r = _tx * cos - _ty * sin;
_ty = _tx * sin + _ty * cos;
_tx = r;
float dx = _cx - x, dy = _cy - y; float dx = _cx - x, dy = _cy - y;
translate(dx * cos - dy * sin - dx, dx * sin + dy * cos - dy); translate(dx * cos - dy * sin - dx, dx * sin + dy * cos - dy);
} }

View File

@ -39,7 +39,7 @@ RTTI_IMPL(PhysicsConstraintData, ConstraintData)
PhysicsConstraintData::PhysicsConstraintData(const String &name) : ConstraintData(name), PhysicsConstraintData::PhysicsConstraintData(const String &name) : ConstraintData(name),
_bone(nullptr), _bone(nullptr),
_x(0), _y(0), _rotate(0), _scaleX(0), _shearX(0), _x(0), _y(0), _rotate(0), _scaleX(0), _shearX(0), _limit(0),
_step(0), _inertia(0), _strength(0), _damping(0), _massInverse(0), _wind(0), _gravity(0), _mix(0), _step(0), _inertia(0), _strength(0), _damping(0), _massInverse(0), _wind(0), _gravity(0), _mix(0),
_inertiaGlobal(false), _strengthGlobal(false), _dampingGlobal(false), _massGlobal(false), _inertiaGlobal(false), _strengthGlobal(false), _dampingGlobal(false), _massGlobal(false),
_windGlobal(false), _gravityGlobal(false), _mixGlobal(false) { _windGlobal(false), _gravityGlobal(false), _mixGlobal(false) {
@ -94,6 +94,14 @@ float PhysicsConstraintData::getShearX() const {
return _shearX; return _shearX;
} }
void PhysicsConstraintData::setLimit(float limit) {
_limit = limit;
}
float PhysicsConstraintData::getLimit() const {
return _limit;
}
void PhysicsConstraintData::setStep(float step) { void PhysicsConstraintData::setStep(float step) {
_step = step; _step = step;
} }

View File

@ -93,7 +93,7 @@ void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vec
int index = modeAndIndex >> 4, count = (int) sequence->getRegions().size(); int index = modeAndIndex >> 4, count = (int) sequence->getRegions().size();
int mode = modeAndIndex & 0xf; int mode = modeAndIndex & 0xf;
if (mode != SequenceMode::hold) { if (mode != SequenceMode::hold) {
index += (int) (((time - before) / delay + 0.00001)); index += (int) (((time - before) / delay + 0.0001));
switch (mode) { switch (mode) {
case SequenceMode::once: case SequenceMode::once:
index = MathUtil::min(count - 1, index); index = MathUtil::min(count - 1, index);

View File

@ -158,5 +158,5 @@ void ShearYTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto
SP_UNUSED(direction); SP_UNUSED(direction);
Bone *bone = skeleton._bones[_boneIndex]; Bone *bone = skeleton._bones[_boneIndex];
if (bone->_active) bone->_shearY = getRelativeValue(time, alpha, blend, bone->_shearX, bone->_data._shearY); if (bone->_active) bone->_shearY = getRelativeValue(time, alpha, blend, bone->_shearY, bone->_data._shearY);
} }

View File

@ -163,7 +163,6 @@ void Skeleton::updateCache() {
size_t transformCount = _transformConstraints.size(); size_t transformCount = _transformConstraints.size();
size_t pathCount = _pathConstraints.size(); size_t pathCount = _pathConstraints.size();
size_t physicsCount = _physicsConstraints.size(); size_t physicsCount = _physicsConstraints.size();
size_t constraintCount = ikCount + transformCount + pathCount + physicsCount; size_t constraintCount = ikCount + transformCount + pathCount + physicsCount;
size_t i = 0; size_t i = 0;
@ -510,6 +509,10 @@ Vector<TransformConstraint *> &Skeleton::getTransformConstraints() {
return _transformConstraints; return _transformConstraints;
} }
Vector<PhysicsConstraint *> &Skeleton::getPhysicsConstraints() {
return _physicsConstraints;
}
Skin *Skeleton::getSkin() { Skin *Skeleton::getSkin() {
return _skin; return _skin;
} }

View File

@ -157,7 +157,7 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
data->_shearX = readFloat(input); data->_shearX = readFloat(input);
data->_shearY = readFloat(input); data->_shearY = readFloat(input);
data->_length = readFloat(input) * _scale; data->_length = readFloat(input) * _scale;
data->_transformMode = static_cast<TransformMode>(readVarint(input, true)); data->_inherit = static_cast<Inherit>(readVarint(input, true));
data->_skinRequired = readBoolean(input); data->_skinRequired = readBoolean(input);
if (nonessential) { if (nonessential) {
readColor(input, data->getColor()); readColor(input, data->getColor());

View File

@ -49,6 +49,7 @@ SkeletonData::SkeletonData() : _name(),
_y(0), _y(0),
_width(0), _width(0),
_height(0), _height(0),
_referenceScale(100),
_version(), _version(),
_hash(), _hash(),
_fps(0), _fps(0),
@ -193,6 +194,14 @@ void SkeletonData::setHeight(float inValue) {
_height = inValue; _height = inValue;
} }
float SkeletonData::getReferenceScale() {
return _referenceScale;
}
void SkeletonData::setReferenceScale(float inValue) {
_referenceScale = inValue;
}
const String &SkeletonData::getVersion() { const String &SkeletonData::getVersion() {
return _version; return _version;
} }

View File

@ -194,17 +194,17 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
data->_scaleY = Json::getFloat(boneMap, "scaleY", 1); data->_scaleY = Json::getFloat(boneMap, "scaleY", 1);
data->_shearX = Json::getFloat(boneMap, "shearX", 0); data->_shearX = Json::getFloat(boneMap, "shearX", 0);
data->_shearY = Json::getFloat(boneMap, "shearY", 0); data->_shearY = Json::getFloat(boneMap, "shearY", 0);
transformMode = Json::getString(boneMap, "transform", "normal"); transformMode = Json::getString(boneMap, "inherit", "normal");
data->_transformMode = TransformMode_Normal; data->_inherit = Inherit_Normal;
if (strcmp(transformMode, "normal") == 0) data->_transformMode = TransformMode_Normal; if (strcmp(transformMode, "normal") == 0) data->_inherit = Inherit_Normal;
else if (strcmp(transformMode, "onlyTranslation") == 0) else if (strcmp(transformMode, "onlyTranslation") == 0)
data->_transformMode = TransformMode_OnlyTranslation; data->_inherit = Inherit_OnlyTranslation;
else if (strcmp(transformMode, "noRotationOrReflection") == 0) else if (strcmp(transformMode, "noRotationOrReflection") == 0)
data->_transformMode = TransformMode_NoRotationOrReflection; data->_inherit = Inherit_NoRotationOrReflection;
else if (strcmp(transformMode, "noScale") == 0) else if (strcmp(transformMode, "noScale") == 0)
data->_transformMode = TransformMode_NoScale; data->_inherit = Inherit_NoScale;
else if (strcmp(transformMode, "noScaleOrReflection") == 0) else if (strcmp(transformMode, "noScaleOrReflection") == 0)
data->_transformMode = TransformMode_NoScaleOrReflection; data->_inherit = Inherit_NoScaleOrReflection;
data->_skinRequired = Json::getBoolean(boneMap, "skin", false); data->_skinRequired = Json::getBoolean(boneMap, "skin", false);
const char *color = Json::getString(boneMap, "color", NULL); const char *color = Json::getString(boneMap, "color", NULL);

View File

@ -88,7 +88,7 @@ Skin::AttachmentMap::Entries Skin::AttachmentMap::getEntries() {
return Skin::AttachmentMap::Entries(_buckets); return Skin::AttachmentMap::Entries(_buckets);
} }
Skin::Skin(const String &name) : _name(name), _attachments() { Skin::Skin(const String &name) : _name(name), _attachments(), _color(0.99607843f, 0.61960787f, 0.30980393f, 1) {
assert(_name.length() > 0); assert(_name.length() > 0);
} }

View File

@ -54,7 +54,8 @@ SkeletonDrawable::~SkeletonDrawable() {
void SkeletonDrawable::update(float delta) { void SkeletonDrawable::update(float delta) {
animationState->update(delta); animationState->update(delta);
animationState->apply(*skeleton); animationState->apply(*skeleton);
skeleton->updateWorldTransform(); skeleton->update(delta);
skeleton->updateWorldTransform(Physics_Update);
} }
void SkeletonDrawable::draw(SDL_Renderer *renderer) { void SkeletonDrawable::draw(SDL_Renderer *renderer) {