mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[cpp] 4.0 port, half done.
This commit is contained in:
parent
8c4d03c8be
commit
653c06a6b8
@ -286,7 +286,7 @@ xcopy "$(ProjectDir)..\Resources" "$(OutDir)\Resources" /D /E /I /F /Y
|
||||
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\String.h" />
|
||||
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TextureLoader.h" />
|
||||
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\Timeline.h" />
|
||||
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TimelineType.h" />
|
||||
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\Property.h" />
|
||||
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TransformConstraint.h" />
|
||||
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TransformConstraintData.h" />
|
||||
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TransformConstraintTimeline.h" />
|
||||
|
||||
@ -491,7 +491,7 @@
|
||||
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\Timeline.h">
|
||||
<Filter>spine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TimelineType.h">
|
||||
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\Property.h">
|
||||
<Filter>spine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\spine-cpp\spine-cpp\include\spine\TransformConstraint.h">
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
#include <spine/MixDirection.h>
|
||||
#include <spine/SpineObject.h>
|
||||
#include <spine/SpineString.h>
|
||||
#include <spine/Property.h>
|
||||
|
||||
namespace spine {
|
||||
class Timeline;
|
||||
@ -79,6 +80,10 @@ class SP_API Animation : public SpineObject {
|
||||
|
||||
friend class TranslateTimeline;
|
||||
|
||||
friend class TranslateXTimeline;
|
||||
|
||||
friend class TranslateYTimeline;
|
||||
|
||||
friend class TwoColorTimeline;
|
||||
|
||||
public:
|
||||
@ -95,27 +100,22 @@ public:
|
||||
|
||||
Vector<Timeline *> &getTimelines();
|
||||
|
||||
bool hasTimeline(int id);
|
||||
bool hasTimeline(Vector<PropertyId> ids);
|
||||
|
||||
float getDuration();
|
||||
|
||||
void setDuration(float inValue);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
Vector<Timeline *> _timelines;
|
||||
HashMap<int, bool> _timelineIds;
|
||||
HashMap<PropertyId, bool> _timelineIds;
|
||||
float _duration;
|
||||
String _name;
|
||||
|
||||
/// @param target After the first and before the last entry.
|
||||
static int binarySearch(Vector<float> &values, float target, int step);
|
||||
static int search(Vector<float> &values, float target);
|
||||
|
||||
/// @param target After the first and before the last entry.
|
||||
static int binarySearch(Vector<float> &values, float target);
|
||||
|
||||
static int linearSearch(Vector<float> &values, float target, int step);
|
||||
static int search(Vector<float> &values, float target, int step);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -65,10 +65,18 @@ class SP_API Bone : public Updatable {
|
||||
|
||||
friend class ScaleTimeline;
|
||||
|
||||
friend class ScaleXTimeline;
|
||||
|
||||
friend class ScaleYTimeline;
|
||||
|
||||
friend class ShearTimeline;
|
||||
|
||||
friend class TranslateTimeline;
|
||||
|
||||
friend class TranslateXTimeline;
|
||||
|
||||
friend class TranslateYTimeline;
|
||||
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
|
||||
@ -46,10 +46,18 @@ class SP_API BoneData : public SpineObject {
|
||||
|
||||
friend class ScaleTimeline;
|
||||
|
||||
friend class ScaleXTimeline;
|
||||
|
||||
friend class ScaleYTimeline;
|
||||
|
||||
friend class ShearTimeline;
|
||||
|
||||
friend class TranslateTimeline;
|
||||
|
||||
friend class TranslateXTimeline;
|
||||
|
||||
friend class TranslateYTimeline;
|
||||
|
||||
public:
|
||||
BoneData(int index, const String &name, BoneData *parent = NULL);
|
||||
|
||||
|
||||
@ -39,38 +39,59 @@ namespace spine {
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
explicit CurveTimeline(int frameCount);
|
||||
explicit CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount);
|
||||
|
||||
virtual ~CurveTimeline();
|
||||
|
||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction) = 0;
|
||||
void setLinear(size_t frame);
|
||||
|
||||
virtual int getPropertyId() = 0;
|
||||
void setStepped(size_t frame);
|
||||
|
||||
size_t getFrameCount();
|
||||
void setBezier (size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, float cy2, float time2, float value2);
|
||||
|
||||
void setLinear(size_t frameIndex);
|
||||
|
||||
void setStepped(size_t frameIndex);
|
||||
|
||||
/// Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
|
||||
/// cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of
|
||||
/// the difference between the keyframe's values.
|
||||
void setCurve(size_t frameIndex, float cx1, float cy1, float cx2, float cy2);
|
||||
|
||||
float getCurvePercent(size_t frameIndex, float percent);
|
||||
|
||||
float getCurveType(size_t frameIndex);
|
||||
float getBezierValue(float time, size_t frame, size_t valueOffset, size_t i);
|
||||
|
||||
protected:
|
||||
static const float LINEAR;
|
||||
static const float STEPPED;
|
||||
static const float BEZIER;
|
||||
static const int BEZIER_SIZE;
|
||||
static const int LINEAR = 0;
|
||||
static const int STEPPED = 1;
|
||||
static const int BEZIER = 2;
|
||||
static const int BEZIER_SIZE = 18;
|
||||
|
||||
private:
|
||||
Vector<float> _curves; // type, x, y, ...
|
||||
};
|
||||
|
||||
class SP_API CurveTimeline1 : public CurveTimeline {
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
explicit CurveTimeline1(size_t frameCount, size_t bezierCount);
|
||||
|
||||
virtual ~CurveTimeline1();
|
||||
|
||||
void setFrame(size_t frame, float time, float value);
|
||||
|
||||
float getCurveValue(float time);
|
||||
protected:
|
||||
static const int ENTRIES;
|
||||
static const int VALUE;
|
||||
};
|
||||
|
||||
class SP_API CurveTimeline2 : public CurveTimeline {
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
explicit CurveTimeline2(size_t frameCount, size_t bezierCount);
|
||||
|
||||
virtual ~CurveTimeline2();
|
||||
|
||||
void setFrame(size_t frame, float time, float value1, float value2);
|
||||
|
||||
float getCurveValue(float time);
|
||||
protected:
|
||||
static const int ENTRIES;
|
||||
static const int VALUE1;
|
||||
static const int VALUE2;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* Spine_CurveTimeline_h */
|
||||
|
||||
@ -65,11 +65,14 @@ namespace spine {
|
||||
float getSpacing();
|
||||
void setSpacing(float inValue);
|
||||
|
||||
float getRotateMix();
|
||||
void setRotateMix(float inValue);
|
||||
float getMixRotate();
|
||||
void setMixRotate(float inValue);
|
||||
|
||||
float getTranslateMix();
|
||||
void setTranslateMix(float inValue);
|
||||
float getMixX();
|
||||
void setMixX(float inValue);
|
||||
|
||||
float getMixY();
|
||||
void setMixY(float inValue);
|
||||
|
||||
Vector<Bone*>& getBones();
|
||||
|
||||
@ -91,7 +94,8 @@ namespace spine {
|
||||
PathConstraintData& _data;
|
||||
Vector<Bone*> _bones;
|
||||
Slot* _target;
|
||||
float _position, _spacing, _rotateMix, _translateMix;
|
||||
float _position, _spacing;
|
||||
float _mixRotate, _mixX, _mixY;
|
||||
|
||||
Vector<float> _spaces;
|
||||
Vector<float> _positions;
|
||||
@ -102,7 +106,7 @@ namespace spine {
|
||||
|
||||
bool _active;
|
||||
|
||||
Vector<float>& computeWorldPositions(PathAttachment& path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing);
|
||||
Vector<float>& computeWorldPositions(PathAttachment& path, int spacesCount, bool tangents);
|
||||
|
||||
static void addBeforePosition(float p, Vector<float>& temp, int i, Vector<float>& output, int o);
|
||||
|
||||
|
||||
@ -78,11 +78,14 @@ namespace spine {
|
||||
float getSpacing();
|
||||
void setSpacing(float inValue);
|
||||
|
||||
float getRotateMix();
|
||||
void setRotateMix(float inValue);
|
||||
float getMixRotate();
|
||||
void setMixRotate(float inValue);
|
||||
|
||||
float getTranslateMix();
|
||||
void setTranslateMix(float inValue);
|
||||
float getMixX();
|
||||
void setMixX(float inValue);
|
||||
|
||||
float getMixY();
|
||||
void setMixY(float inValue);
|
||||
|
||||
private:
|
||||
Vector<BoneData*> _bones;
|
||||
@ -91,7 +94,8 @@ namespace spine {
|
||||
SpacingMode _spacingMode;
|
||||
RotateMode _rotateMode;
|
||||
float _offsetRotation;
|
||||
float _position, _spacing, _rotateMix, _translateMix;
|
||||
float _position, _spacing;
|
||||
float _mixRotate, _mixX, _mixY;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -27,27 +27,32 @@
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef Spine_TimelineType_h
|
||||
#define Spine_TimelineType_h
|
||||
#ifndef Spine_Property_h
|
||||
#define Spine_Property_h
|
||||
|
||||
namespace spine {
|
||||
enum TimelineType {
|
||||
TimelineType_Rotate = 0,
|
||||
TimelineType_Translate,
|
||||
TimelineType_Scale,
|
||||
TimelineType_Shear,
|
||||
TimelineType_Attachment,
|
||||
TimelineType_Color,
|
||||
TimelineType_Deform,
|
||||
TimelineType_Event,
|
||||
TimelineType_DrawOrder,
|
||||
TimelineType_IkConstraint,
|
||||
TimelineType_TransformConstraint,
|
||||
TimelineType_PathConstraintPosition,
|
||||
TimelineType_PathConstraintSpacing,
|
||||
TimelineType_PathConstraintMix,
|
||||
TimelineType_TwoColor
|
||||
typedef long long PropertyId;
|
||||
enum Property {
|
||||
Property_Rotate = 1 << 0,
|
||||
Property_X = 1 << 1,
|
||||
Property_Y = 1 << 2,
|
||||
Property_ScaleX = 1 << 3,
|
||||
Property_ScaleY = 1 << 4,
|
||||
Property_ShearX = 1 << 5,
|
||||
Property_ShearY = 1 << 6,
|
||||
Property_Rgb = 1 << 7,
|
||||
Property_Alpha = 1 << 8,
|
||||
Property_Rgb2 = 1 << 9,
|
||||
Property_Attachment = 1 << 10,
|
||||
Property_Deform = 1 << 11,
|
||||
Property_Event = 1 << 12,
|
||||
Property_DrawOrder = 1 << 13,
|
||||
Property_IkConstraint = 1 << 14,
|
||||
Property_TransformConstraint = 1 << 15,
|
||||
Property_PathConstraintPosition = 1 << 16,
|
||||
Property_PathConstraintSpacing = 1 << 17,
|
||||
Property_OathConstraintMix = 1 << 18
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* Spine_TimelineType_h */
|
||||
#endif /* Spine_Property_h */
|
||||
@ -54,7 +54,7 @@ namespace spine {
|
||||
|
||||
void updateOffset();
|
||||
|
||||
void setUVs(float u, float v, float u2, float v2, bool rotate);
|
||||
void setUVs(float u, float v, float u2, float v2, float degrees);
|
||||
|
||||
/// Transforms the attachment's four vertices to world coordinates.
|
||||
/// @param bone The parent bone.
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
#include <spine/CurveTimeline.h>
|
||||
|
||||
namespace spine {
|
||||
class SP_API RotateTimeline : public CurveTimeline {
|
||||
class SP_API RotateTimeline : public CurveTimeline1 {
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonJson;
|
||||
friend class AnimationState;
|
||||
@ -41,29 +41,15 @@ namespace spine {
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
static const int ENTRIES = 2;
|
||||
|
||||
explicit RotateTimeline(int frameCount);
|
||||
explicit RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
|
||||
|
||||
virtual int getPropertyId();
|
||||
|
||||
/// Sets the time and value of the specified keyframe.
|
||||
void setFrame(int frameIndex, float time, float degrees);
|
||||
|
||||
int getBoneIndex();
|
||||
void setBoneIndex(int inValue);
|
||||
|
||||
Vector<float>& getFrames();
|
||||
int getBoneIndex() { return _boneIndex; }
|
||||
|
||||
void setBoneIndex(int inValue) { _boneIndex = inValue; }
|
||||
private:
|
||||
static const int PREV_TIME = -2;
|
||||
static const int PREV_ROTATION = -1;
|
||||
static const int ROTATION = 1;
|
||||
|
||||
int _boneIndex;
|
||||
Vector<float> _frames; // time, angle, ...
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -33,19 +33,65 @@
|
||||
#include <spine/TranslateTimeline.h>
|
||||
|
||||
namespace spine {
|
||||
class SP_API ScaleTimeline : public TranslateTimeline {
|
||||
class SP_API ScaleTimeline : public CurveTimeline2 {
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonJson;
|
||||
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
explicit ScaleTimeline(int frameCount);
|
||||
explicit ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
virtual ~ScaleTimeline();
|
||||
|
||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
|
||||
|
||||
virtual int getPropertyId();
|
||||
int getBoneIndex() { return _boneIndex; }
|
||||
|
||||
void setBoneIndex(int inValue) { _boneIndex = inValue; }
|
||||
private:
|
||||
int _boneIndex;
|
||||
};
|
||||
|
||||
class SP_API ScaleXTimeline : public CurveTimeline1 {
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonJson;
|
||||
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
explicit ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
virtual ~ScaleXTimeline();
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
class SP_API ScaleYTimeline : public CurveTimeline1 {
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonJson;
|
||||
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
explicit ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
virtual ~ScaleYTimeline();
|
||||
|
||||
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_ScaleTimeline_h */
|
||||
|
||||
@ -82,12 +82,22 @@ class SP_API Skeleton : public SpineObject {
|
||||
|
||||
friend class ScaleTimeline;
|
||||
|
||||
friend class ScaleXTimeline;
|
||||
|
||||
friend class ScaleYTimeline;
|
||||
|
||||
friend class ShearTimeline;
|
||||
|
||||
friend class TransformConstraintTimeline;
|
||||
|
||||
friend class RotateTimeline;
|
||||
|
||||
friend class TranslateTimeline;
|
||||
|
||||
friend class TranslateXTimeline;
|
||||
|
||||
friend class TranslateYTimeline;
|
||||
|
||||
friend class TwoColorTimeline;
|
||||
|
||||
public:
|
||||
@ -104,6 +114,8 @@ public:
|
||||
/// Updates the world transform for each bone and applies constraints.
|
||||
void updateWorldTransform();
|
||||
|
||||
void updateWorldTransform(Bone* parent);
|
||||
|
||||
/// Sets the bones, constraints, and slots to their setup pose values.
|
||||
void setToSetupPose();
|
||||
|
||||
@ -217,7 +229,6 @@ private:
|
||||
Vector<TransformConstraint *> _transformConstraints;
|
||||
Vector<PathConstraint *> _pathConstraints;
|
||||
Vector<Updatable *> _updateCache;
|
||||
Vector<Bone *> _updateCacheReset;
|
||||
Skin *_skin;
|
||||
Color _color;
|
||||
float _time;
|
||||
|
||||
@ -34,7 +34,8 @@ namespace spine {
|
||||
enum SpacingMode {
|
||||
SpacingMode_Length = 0,
|
||||
SpacingMode_Fixed,
|
||||
SpacingMode_Percent
|
||||
SpacingMode_Percent,
|
||||
SpacingMode_Proportional
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
#include <spine/MixBlend.h>
|
||||
#include <spine/MixDirection.h>
|
||||
#include <spine/SpineObject.h>
|
||||
#include <spine/Property.h>
|
||||
|
||||
namespace spine {
|
||||
class Skeleton;
|
||||
@ -45,7 +46,7 @@ class SP_API Timeline : public SpineObject {
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
Timeline();
|
||||
Timeline(size_t frameCount, size_t frameEntries);
|
||||
|
||||
virtual ~Timeline();
|
||||
|
||||
@ -63,7 +64,22 @@ public:
|
||||
apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha, MixBlend blend,
|
||||
MixDirection direction) = 0;
|
||||
|
||||
virtual int getPropertyId() = 0;
|
||||
size_t getFrameEntries();
|
||||
|
||||
size_t getFrameCount();
|
||||
|
||||
Vector<float> &getFrames();
|
||||
|
||||
float getDuration();
|
||||
|
||||
virtual Vector<PropertyId> &getPropertyIds();
|
||||
|
||||
protected:
|
||||
void setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount);
|
||||
|
||||
Vector<PropertyId> _propertyIds;
|
||||
Vector<float> _frames;
|
||||
size_t _frameEntries;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -48,8 +48,6 @@ namespace spine {
|
||||
public:
|
||||
TransformConstraint(TransformConstraintData& data, Skeleton& skeleton);
|
||||
|
||||
void apply();
|
||||
|
||||
virtual void update();
|
||||
|
||||
virtual int getOrder();
|
||||
@ -61,17 +59,23 @@ namespace spine {
|
||||
Bone* getTarget();
|
||||
void setTarget(Bone* inValue);
|
||||
|
||||
float getRotateMix();
|
||||
void setRotateMix(float inValue);
|
||||
float getMixRotate();
|
||||
void setMixRotate(float inValue);
|
||||
|
||||
float getTranslateMix();
|
||||
void setTranslateMix(float inValue);
|
||||
float getMixX();
|
||||
void setMixX(float inValue);
|
||||
|
||||
float getScaleMix();
|
||||
void setScaleMix(float inValue);
|
||||
float getMixY();
|
||||
void setMixY(float inValue);
|
||||
|
||||
float getShearMix();
|
||||
void setShearMix(float inValue);
|
||||
float getMixScaleX();
|
||||
void setMixScaleX(float inValue);
|
||||
|
||||
float getMixScaleY();
|
||||
void setMixScaleY(float inValue);
|
||||
|
||||
float getMixShearY();
|
||||
void setMixShearY(float inValue);
|
||||
|
||||
bool isActive();
|
||||
|
||||
@ -81,8 +85,8 @@ namespace spine {
|
||||
TransformConstraintData& _data;
|
||||
Vector<Bone*> _bones;
|
||||
Bone* _target;
|
||||
float _rotateMix, _translateMix, _scaleMix, _shearMix;
|
||||
bool _active;
|
||||
float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY;
|
||||
bool _active;
|
||||
|
||||
void applyAbsoluteWorld();
|
||||
|
||||
|
||||
@ -51,10 +51,12 @@ namespace spine {
|
||||
|
||||
Vector<BoneData*>& getBones();
|
||||
BoneData* getTarget();
|
||||
float getRotateMix();
|
||||
float getTranslateMix();
|
||||
float getScaleMix();
|
||||
float getShearMix();
|
||||
float getMixRotate();
|
||||
float getMixX();
|
||||
float getMixY();
|
||||
float getMixScaleX();
|
||||
float getMixScaleY();
|
||||
float getMixShearY();
|
||||
|
||||
float getOffsetRotation();
|
||||
float getOffsetX();
|
||||
@ -69,7 +71,7 @@ namespace spine {
|
||||
private:
|
||||
Vector<BoneData*> _bones;
|
||||
BoneData* _target;
|
||||
float _rotateMix, _translateMix, _scaleMix, _shearMix;
|
||||
float _mixRotate, _mixX, _mixY, _mixScaleX, _mixScaleY, _mixShearY;
|
||||
float _offsetRotation, _offsetX, _offsetY, _offsetScaleX, _offsetScaleY, _offsetShearY;
|
||||
bool _relative, _local;
|
||||
};
|
||||
|
||||
@ -33,40 +33,69 @@
|
||||
#include <spine/CurveTimeline.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
|
||||
namespace spine {
|
||||
|
||||
class SP_API TranslateTimeline : public CurveTimeline {
|
||||
class SP_API TranslateTimeline : public CurveTimeline2 {
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonJson;
|
||||
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
static const int ENTRIES;
|
||||
|
||||
explicit TranslateTimeline(int frameCount);
|
||||
explicit TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
virtual ~TranslateTimeline();
|
||||
|
||||
virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector<Event*>* pEvents, float alpha, MixBlend blend, MixDirection direction);
|
||||
|
||||
virtual int getPropertyId();
|
||||
int getBoneIndex() { return _boneIndex; }
|
||||
|
||||
/// Sets the time and value of the specified keyframe.
|
||||
void setFrame(int frameIndex, float time, float x, float y);
|
||||
|
||||
protected:
|
||||
static const int PREV_TIME;
|
||||
static const int PREV_X;
|
||||
static const int PREV_Y;
|
||||
static const int X;
|
||||
static const int Y;
|
||||
|
||||
Vector<float> _frames;
|
||||
int _boneIndex;
|
||||
void setBoneIndex(int inValue) { _boneIndex = inValue; }
|
||||
private:
|
||||
int _boneIndex;
|
||||
};
|
||||
|
||||
class SP_API TranslateXTimeline : public CurveTimeline1 {
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonJson;
|
||||
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
explicit TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
virtual ~TranslateXTimeline();
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
class SP_API TranslateYTimeline : public CurveTimeline1 {
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonJson;
|
||||
|
||||
RTTI_DECL
|
||||
|
||||
public:
|
||||
explicit TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
virtual ~TranslateYTimeline();
|
||||
|
||||
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_TranslateTimeline_h */
|
||||
|
||||
@ -95,7 +95,7 @@
|
||||
#include <spine/SpineString.h>
|
||||
#include <spine/TextureLoader.h>
|
||||
#include <spine/Timeline.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/TransformConstraint.h>
|
||||
#include <spine/TransformConstraintData.h>
|
||||
#include <spine/TransformConstraintTimeline.h>
|
||||
|
||||
@ -48,12 +48,18 @@ Animation::Animation(const String &name, Vector<Timeline *> &timelines, float du
|
||||
_duration(duration),
|
||||
_name(name) {
|
||||
assert(_name.length() > 0);
|
||||
for (int i = 0; i < (int)timelines.size(); i++)
|
||||
_timelineIds.put(timelines[i]->getPropertyId(), true);
|
||||
for (size_t i = 0; i < timelines.size(); i++) {
|
||||
Vector<PropertyId> propertyIds = timelines[i]->getPropertyIds();
|
||||
for (size_t ii = 0; ii < propertyIds.size(); ii++)
|
||||
_timelineIds.put(propertyIds[ii], true);
|
||||
}
|
||||
}
|
||||
|
||||
bool Animation::hasTimeline(int id) {
|
||||
return _timelineIds.containsKey(id);
|
||||
bool Animation::hasTimeline(Vector<PropertyId> ids) {
|
||||
for (size_t i = 0; i < ids.size(); i++) {
|
||||
if (_timelineIds.containsKey(ids[i])) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Animation::~Animation() {
|
||||
@ -91,52 +97,17 @@ void Animation::setDuration(float inValue) {
|
||||
_duration = inValue;
|
||||
}
|
||||
|
||||
int Animation::binarySearch(Vector<float> &values, float target, int step) {
|
||||
int low = 0;
|
||||
int size = (int)values.size();
|
||||
int high = size / step - 2;
|
||||
if (high == 0) {
|
||||
return step;
|
||||
}
|
||||
|
||||
int current = (int) (static_cast<uint32_t>(high) >> 1);
|
||||
while (true) {
|
||||
if (values[(current + 1) * step] <= target)
|
||||
low = current + 1;
|
||||
else
|
||||
high = current;
|
||||
|
||||
if (low == high) return (low + 1) * step;
|
||||
|
||||
current = (int) (static_cast<uint32_t>(low + high) >> 1);
|
||||
}
|
||||
int Animation::search(Vector<float> &frames, float target) {
|
||||
size_t n = (int)frames.size();
|
||||
for (size_t i = 1; i < n; i++) {
|
||||
if (frames[i] > target) return i - 1;
|
||||
}
|
||||
return n - 1;
|
||||
}
|
||||
|
||||
int Animation::binarySearch(Vector<float> &values, float target) {
|
||||
int low = 0;
|
||||
int size = (int)values.size();
|
||||
int high = size - 2;
|
||||
if (high == 0) return 1;
|
||||
|
||||
int current = (int) (static_cast<uint32_t>(high) >> 1);
|
||||
while (true) {
|
||||
if (values[(current + 1)] <= target)
|
||||
low = current + 1;
|
||||
else
|
||||
high = current;
|
||||
|
||||
if (low == high) return (low + 1);
|
||||
|
||||
current = (int) (static_cast<uint32_t>(low + high) >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
int Animation::linearSearch(Vector<float> &values, float target, int step) {
|
||||
for (int i = 0, last = (int)values.size() - step; i <= last; i += step) {
|
||||
if (values[i] > target) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
int Animation::search(Vector<float> &frames, float target, int step) {
|
||||
size_t n = frames.size();
|
||||
for (size_t i = step; i < n; i += step)
|
||||
if (frames[i] > target) return i - step;
|
||||
return n - step;
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
|
||||
@ -39,89 +39,111 @@ using namespace spine;
|
||||
|
||||
RTTI_IMPL(CurveTimeline, Timeline)
|
||||
|
||||
const float CurveTimeline::LINEAR = 0;
|
||||
const float CurveTimeline::STEPPED = 1;
|
||||
const float CurveTimeline::BEZIER = 2;
|
||||
const int CurveTimeline::BEZIER_SIZE = 10 * 2 - 1;
|
||||
|
||||
CurveTimeline::CurveTimeline(int frameCount) {
|
||||
assert(frameCount > 0);
|
||||
|
||||
_curves.setSize((frameCount - 1) * BEZIER_SIZE, 0);
|
||||
CurveTimeline::CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount): Timeline(frameCount, frameEntries) {
|
||||
_curves.setSize(frameCount + bezierCount * BEZIER_SIZE, 0);
|
||||
_curves[frameCount - 1] = STEPPED;
|
||||
}
|
||||
|
||||
CurveTimeline::~CurveTimeline() {
|
||||
}
|
||||
|
||||
size_t CurveTimeline::getFrameCount() {
|
||||
return _curves.size() / BEZIER_SIZE + 1;
|
||||
void CurveTimeline::setLinear(size_t frame) {
|
||||
_curves[frame] = LINEAR;
|
||||
}
|
||||
|
||||
void CurveTimeline::setLinear(size_t frameIndex) {
|
||||
_curves[frameIndex * BEZIER_SIZE] = LINEAR;
|
||||
void CurveTimeline::setStepped(size_t frame) {
|
||||
_curves[frame] = STEPPED;
|
||||
}
|
||||
|
||||
void CurveTimeline::setStepped(size_t frameIndex) {
|
||||
_curves[frameIndex * BEZIER_SIZE] = STEPPED;
|
||||
void CurveTimeline::setBezier (size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, float cy2, float time2, float value2) {
|
||||
size_t i = getFrameCount() + bezier * BEZIER_SIZE;
|
||||
if (value == 0) _curves[frame] = BEZIER + i;
|
||||
float tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03;
|
||||
float dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 0.006;
|
||||
float ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy;
|
||||
float dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667;
|
||||
float x = time1 + dx, y = value1 + dy;
|
||||
for (size_t n = i + BEZIER_SIZE; i < n; i += 2) {
|
||||
_curves[i] = x;
|
||||
_curves[i + 1] = y;
|
||||
dx += ddx;
|
||||
dy += ddy;
|
||||
ddx += dddx;
|
||||
ddy += dddy;
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
}
|
||||
|
||||
void CurveTimeline::setCurve(size_t frameIndex, float cx1, float cy1, float cx2, float cy2) {
|
||||
float tmpx = (-cx1 * 2 + cx2) * 0.03f, tmpy = (-cy1 * 2 + cy2) * 0.03f;
|
||||
float dddfx = ((cx1 - cx2) * 3 + 1) * 0.006f, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006f;
|
||||
float ddfx = tmpx * 2 + dddfx, ddfy = tmpy * 2 + dddfy;
|
||||
float dfx = cx1 * 0.3f + tmpx + dddfx * 0.16666667f, dfy = cy1 * 0.3f + tmpy + dddfy * 0.16666667f;
|
||||
|
||||
size_t i = frameIndex * BEZIER_SIZE;
|
||||
_curves[i++] = BEZIER;
|
||||
|
||||
float x = dfx, y = dfy;
|
||||
for (size_t n = i + BEZIER_SIZE - 1; i < n; i += 2) {
|
||||
_curves[i] = x;
|
||||
_curves[i + 1] = y;
|
||||
dfx += ddfx;
|
||||
dfy += ddfy;
|
||||
ddfx += dddfx;
|
||||
ddfy += dddfy;
|
||||
x += dfx;
|
||||
y += dfy;
|
||||
}
|
||||
float CurveTimeline::getBezierValue(float time, size_t frame, size_t valueOffset, size_t i) {
|
||||
if (_curves[i] > time) {
|
||||
float x = _frames[frame], y = _frames[frame + valueOffset];
|
||||
return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y);
|
||||
}
|
||||
size_t n = i + BEZIER_SIZE;
|
||||
for (i += 2; i < n; i += 2) {
|
||||
if (_curves[i] >= time) {
|
||||
float x = _curves[i - 2], y = _curves[i - 1];
|
||||
return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y);
|
||||
}
|
||||
}
|
||||
frame += getFrameEntries();
|
||||
float x = _curves[n - 2], y = _curves[n - 1];
|
||||
return y + (time - x) / (_frames[frame] - x) * (_frames[frame + valueOffset] - y);
|
||||
}
|
||||
|
||||
float CurveTimeline::getCurvePercent(size_t frameIndex, float percent) {
|
||||
percent = MathUtil::clamp(percent, 0, 1);
|
||||
size_t i = frameIndex * BEZIER_SIZE;
|
||||
float type = _curves[i];
|
||||
RTTI_IMPL(CurveTimeline1, CurveTimeline)
|
||||
const int CurveTimeline1::ENTRIES = 2;
|
||||
const int CurveTimeline1::VALUE = 1;
|
||||
|
||||
if (type == LINEAR) {
|
||||
return percent;
|
||||
}
|
||||
|
||||
if (type == STEPPED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
i++;
|
||||
float x = 0;
|
||||
for (size_t start = i, n = i + BEZIER_SIZE - 1; i < n; i += 2) {
|
||||
x = _curves[i];
|
||||
if (x >= percent) {
|
||||
float prevX, prevY;
|
||||
if (i == start) {
|
||||
prevX = 0;
|
||||
prevY = 0;
|
||||
} else {
|
||||
prevX = _curves[i - 2];
|
||||
prevY = _curves[i - 1];
|
||||
}
|
||||
return prevY + (_curves[i + 1] - prevY) * (percent - prevX) / (x - prevX);
|
||||
}
|
||||
}
|
||||
|
||||
float y = _curves[i - 1];
|
||||
|
||||
return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1.
|
||||
CurveTimeline1::CurveTimeline1(size_t frameCount, size_t bezierCount): CurveTimeline(frameCount, CurveTimeline1::ENTRIES, bezierCount) {
|
||||
}
|
||||
|
||||
float CurveTimeline::getCurveType(size_t frameIndex) {
|
||||
return _curves[frameIndex * BEZIER_SIZE];
|
||||
CurveTimeline1::~CurveTimeline1() {
|
||||
}
|
||||
|
||||
void CurveTimeline1::setFrame(size_t frame, float time, float value) {
|
||||
frame <<= 1;
|
||||
_frames[frame] = time;
|
||||
_frames[frame + CurveTimeline1::VALUE] = value;
|
||||
}
|
||||
|
||||
float CurveTimeline1::getCurveValue(float time) {
|
||||
int i = _frames.size() - 2;
|
||||
for (int ii = 2; ii <= i; ii += 2) {
|
||||
if (_frames[ii] > time) {
|
||||
i = ii - 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int curveType = (int)_curves[i >> 1];
|
||||
switch (curveType) {
|
||||
case CurveTimeline::LINEAR: {
|
||||
float before = _frames[i], value = _frames[i + CurveTimeline1::VALUE];
|
||||
return value + (time - before) / (_frames[i + CurveTimeline1::ENTRIES] - before) *
|
||||
(_frames[i + CurveTimeline1::ENTRIES + CurveTimeline1::VALUE] - value);
|
||||
}
|
||||
case CurveTimeline::STEPPED:
|
||||
return _frames[i + CurveTimeline1::VALUE];
|
||||
}
|
||||
return getBezierValue(time, i, CurveTimeline1::VALUE, curveType - CurveTimeline1::BEZIER);
|
||||
}
|
||||
|
||||
RTTI_IMPL(CurveTimeline2, CurveTimeline)
|
||||
const int CurveTimeline2::ENTRIES = 3;
|
||||
const int CurveTimeline2::VALUE1 = 1;
|
||||
const int CurveTimeline2::VALUE2 = 2;
|
||||
|
||||
CurveTimeline2::CurveTimeline2(size_t frameCount, size_t bezierCount): CurveTimeline(frameCount, CurveTimeline2::ENTRIES, bezierCount) {
|
||||
}
|
||||
|
||||
CurveTimeline2::~CurveTimeline2() {
|
||||
}
|
||||
|
||||
void CurveTimeline2::setFrame(size_t frame, float time, float value1, float value2) {
|
||||
frame *= CurveTimeline2::ENTRIES;
|
||||
_frames[frame] = time;
|
||||
_frames[frame + CurveTimeline2::VALUE1] = value1;
|
||||
_frames[frame + CurveTimeline2::VALUE2] = value2;
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
#include <spine/VertexAttachment.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
#include <spine/Event.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
#include <spine/Event.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/EventData.h>
|
||||
|
||||
@ -101,10 +101,6 @@ void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY
|
||||
Bone *pp = parent.getParent();
|
||||
float tx, ty, dx, dy, dd, l1, l2, a1, a2, r, td, sd, p;
|
||||
float id, x, y;
|
||||
if (alpha == 0) {
|
||||
child.updateWorldTransform();
|
||||
return;
|
||||
}
|
||||
if (!parent._appliedValid) parent.updateAppliedTransform();
|
||||
if (!child._appliedValid) child.updateAppliedTransform();
|
||||
px = parent._ax;
|
||||
@ -268,12 +264,8 @@ IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Updatab
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies the constraint to the constrained bones.
|
||||
void IkConstraint::apply() {
|
||||
update();
|
||||
}
|
||||
|
||||
void IkConstraint::update() {
|
||||
if (_mix == 0) return;
|
||||
switch (_bones.size()) {
|
||||
case 1: {
|
||||
Bone *bone0 = _bones[0];
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
#include <spine/Event.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/IkConstraint.h>
|
||||
|
||||
@ -57,8 +57,9 @@ PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : U
|
||||
data.getTarget()->getName())),
|
||||
_position(data.getPosition()),
|
||||
_spacing(data.getSpacing()),
|
||||
_rotateMix(data.getRotateMix()),
|
||||
_translateMix(data.getTranslateMix()),
|
||||
_mixRotate(data.getMixRotate()),
|
||||
_mixX(data.getMixX()),
|
||||
_mixY(data.getMixY()),
|
||||
_active(false)
|
||||
{
|
||||
_bones.ensureCapacity(_data.getBones().size());
|
||||
@ -70,77 +71,95 @@ PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : U
|
||||
_segments.setSize(10, 0);
|
||||
}
|
||||
|
||||
void PathConstraint::apply() {
|
||||
update();
|
||||
}
|
||||
|
||||
void PathConstraint::update() {
|
||||
Attachment *baseAttachment = _target->getAttachment();
|
||||
if (baseAttachment == NULL || !baseAttachment->getRTTI().instanceOf(PathAttachment::rtti)) {
|
||||
return;
|
||||
}
|
||||
|
||||
PathAttachment *attachment = static_cast<PathAttachment *>(baseAttachment);
|
||||
|
||||
float rotateMix = _rotateMix;
|
||||
float translateMix = _translateMix;
|
||||
bool translate = translateMix > 0;
|
||||
bool rotate = rotateMix > 0;
|
||||
if (!translate && !rotate) {
|
||||
return;
|
||||
}
|
||||
float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY;
|
||||
if (mixRotate == 0 && mixX == 0 && mixY == 0) return;
|
||||
|
||||
PathConstraintData &data = _data;
|
||||
bool percentSpacing = data._spacingMode == SpacingMode_Percent;
|
||||
RotateMode rotateMode = data._rotateMode;
|
||||
bool tangents = rotateMode == RotateMode_Tangent, scale = rotateMode == RotateMode_ChainScale;
|
||||
bool tangents = data._rotateMode == RotateMode_Tangent, scale = data._rotateMode == RotateMode_ChainScale;
|
||||
size_t boneCount = _bones.size();
|
||||
size_t spacesCount = tangents ? boneCount : boneCount + 1;
|
||||
_spaces.setSize(spacesCount, 0);
|
||||
if (scale) _lengths.setSize(boneCount, 0);
|
||||
float spacing = _spacing;
|
||||
if (scale || !percentSpacing) {
|
||||
if (scale) _lengths.setSize(boneCount, 0);
|
||||
bool lengthSpacing = data._spacingMode == SpacingMode_Length;
|
||||
|
||||
for (size_t i = 0, n = spacesCount - 1; i < n;) {
|
||||
Bone *boneP = _bones[i];
|
||||
Bone &bone = *boneP;
|
||||
float setupLength = bone._data.getLength();
|
||||
if (setupLength < PathConstraint::EPSILON) {
|
||||
if (scale) _lengths[i] = 0;
|
||||
_spaces[++i] = 0;
|
||||
} else if (percentSpacing) {
|
||||
if (scale) {
|
||||
float x = setupLength * bone._a, y = setupLength * bone._c;
|
||||
float length = MathUtil::sqrt(x * x + y * y);
|
||||
_lengths[i] = length;
|
||||
}
|
||||
_spaces[++i] = spacing;
|
||||
} else {
|
||||
float x = setupLength * bone._a;
|
||||
float y = setupLength * bone._c;
|
||||
float length = MathUtil::sqrt(x * x + y * y);
|
||||
if (scale) {
|
||||
_lengths[i] = length;
|
||||
}
|
||||
|
||||
_spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 1; i < spacesCount; ++i) {
|
||||
_spaces[i] = spacing;
|
||||
}
|
||||
switch(data._spacingMode) {
|
||||
case SpacingMode_Percent: {
|
||||
if (scale) {
|
||||
for (size_t i = 0, n = spacesCount - 1; i < n; i++) {
|
||||
Bone *boneP = _bones[i];
|
||||
Bone &bone = *boneP;
|
||||
float setupLength = bone._data.getLength();
|
||||
if (setupLength < PathConstraint::EPSILON) {
|
||||
_lengths[i] = 0;
|
||||
} else {
|
||||
float x = setupLength * bone._a, y = setupLength * bone._c;
|
||||
_lengths[i] = MathUtil::sqrt(x * x + y * y);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t i = 1; i < spacesCount; ++i) {
|
||||
_spaces[i] = spacing;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SpacingMode_Proportional: {
|
||||
float sum = 0;
|
||||
for (size_t i = 0; i < boneCount;) {
|
||||
Bone *boneP = _bones[i];
|
||||
Bone &bone = *boneP;
|
||||
float setupLength = bone._data.getLength();
|
||||
if (setupLength < PathConstraint::EPSILON) {
|
||||
if (scale) _lengths[i] = 0;
|
||||
_spaces[++i] = spacing;
|
||||
} else {
|
||||
float x = setupLength * bone._a, y = setupLength * bone._c;
|
||||
float length = MathUtil::sqrt(x * x + y * y);
|
||||
if (scale) _lengths[i] = length;
|
||||
_spaces[++i] = length;
|
||||
sum += length;
|
||||
}
|
||||
}
|
||||
if (sum > 0) {
|
||||
sum = spacesCount / sum * spacing;
|
||||
for (size_t i = 1; i < spacesCount; i++) {
|
||||
_spaces[i] *= sum;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
bool lengthSpacing = data._spacingMode == SpacingMode_Length;
|
||||
for (size_t i = 0, n = spacesCount - 1; i < n;) {
|
||||
Bone *boneP = _bones[i];
|
||||
Bone &bone = *boneP;
|
||||
float setupLength = bone._data.getLength();
|
||||
if (setupLength < PathConstraint::EPSILON) {
|
||||
if (scale) _lengths[i] = 0;
|
||||
_spaces[++i] = spacing;
|
||||
} else {
|
||||
float x = setupLength * bone._a, y = setupLength * bone._c;
|
||||
float length = MathUtil::sqrt(x * x + y * y);
|
||||
if (scale) _lengths[i] = length;
|
||||
_spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector<float>& positions = computeWorldPositions(*attachment, spacesCount, tangents,
|
||||
data.getPositionMode() == PositionMode_Percent, percentSpacing);
|
||||
Vector<float>& positions = computeWorldPositions(*attachment, spacesCount, tangents);
|
||||
float boneX = positions[0];
|
||||
float boneY = positions[1];
|
||||
float offsetRotation = data.getOffsetRotation();
|
||||
bool tip;
|
||||
if (offsetRotation == 0) {
|
||||
tip = rotateMode == RotateMode_Chain;
|
||||
tip = data._rotateMode == RotateMode_Chain;
|
||||
} else {
|
||||
tip = false;
|
||||
Bone &p = _target->getBone();
|
||||
@ -150,8 +169,8 @@ void PathConstraint::update() {
|
||||
for (size_t i = 0, p = 3; i < boneCount; i++, p += 3) {
|
||||
Bone *boneP = _bones[i];
|
||||
Bone &bone = *boneP;
|
||||
bone._worldX += (boneX - bone._worldX) * translateMix;
|
||||
bone._worldY += (boneY - bone._worldY) * translateMix;
|
||||
bone._worldX += (boneX - bone._worldX) * mixX;
|
||||
bone._worldY += (boneY - bone._worldY) * mixY;
|
||||
float x = positions[p];
|
||||
float y = positions[p + 1];
|
||||
float dx = x - boneX;
|
||||
@ -159,7 +178,7 @@ void PathConstraint::update() {
|
||||
if (scale) {
|
||||
float length = _lengths[i];
|
||||
if (length >= PathConstraint::EPSILON) {
|
||||
float s = (MathUtil::sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1;
|
||||
float s = (MathUtil::sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1;
|
||||
bone._a *= s;
|
||||
bone._c *= s;
|
||||
}
|
||||
@ -168,7 +187,7 @@ void PathConstraint::update() {
|
||||
boneX = x;
|
||||
boneY = y;
|
||||
|
||||
if (rotate) {
|
||||
if (mixRotate > 0) {
|
||||
float a = bone._a, b = bone._b, c = bone._c, d = bone._d, r, cos, sin;
|
||||
if (tangents)
|
||||
r = positions[p - 1];
|
||||
@ -183,8 +202,8 @@ void PathConstraint::update() {
|
||||
cos = MathUtil::cos(r);
|
||||
sin = MathUtil::sin(r);
|
||||
float length = bone._data.getLength();
|
||||
boneX += (length * (cos * a - sin * c) - dx) * rotateMix;
|
||||
boneY += (length * (sin * a + cos * c) - dy) * rotateMix;
|
||||
boneX += (length * (cos * a - sin * c) - dx) * mixRotate;
|
||||
boneY += (length * (sin * a + cos * c) - dy) * mixRotate;
|
||||
} else
|
||||
r += offsetRotation;
|
||||
|
||||
@ -193,7 +212,7 @@ void PathConstraint::update() {
|
||||
else if (r < -MathUtil::Pi)
|
||||
r += MathUtil::Pi_2;
|
||||
|
||||
r *= rotateMix;
|
||||
r *= mixRotate;
|
||||
cos = MathUtil::cos(r);
|
||||
sin = MathUtil::sin(r);
|
||||
bone._a = cos * a - sin * c;
|
||||
@ -226,20 +245,28 @@ void PathConstraint::setSpacing(float inValue) {
|
||||
_spacing = inValue;
|
||||
}
|
||||
|
||||
float PathConstraint::getRotateMix() {
|
||||
return _rotateMix;
|
||||
float PathConstraint::getMixRotate() {
|
||||
return _mixRotate;
|
||||
}
|
||||
|
||||
void PathConstraint::setRotateMix(float inValue) {
|
||||
_rotateMix = inValue;
|
||||
void PathConstraint::setMixRotate(float inValue) {
|
||||
_mixRotate = inValue;
|
||||
}
|
||||
|
||||
float PathConstraint::getTranslateMix() {
|
||||
return _translateMix;
|
||||
float PathConstraint::getMixX() {
|
||||
return _mixX;
|
||||
}
|
||||
|
||||
void PathConstraint::setTranslateMix(float inValue) {
|
||||
_translateMix = inValue;
|
||||
void PathConstraint::setMixX(float inValue) {
|
||||
_mixX = inValue;
|
||||
}
|
||||
|
||||
float PathConstraint::getMixY() {
|
||||
return _mixY;
|
||||
}
|
||||
|
||||
void PathConstraint::setMixY(float inValue) {
|
||||
_mixY = inValue;
|
||||
}
|
||||
|
||||
Vector<Bone *> &PathConstraint::getBones() {
|
||||
@ -259,7 +286,7 @@ PathConstraintData &PathConstraint::getData() {
|
||||
}
|
||||
|
||||
Vector<float>&
|
||||
PathConstraint::computeWorldPositions(PathAttachment &path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing) {
|
||||
PathConstraint::computeWorldPositions(PathAttachment &path, int spacesCount, bool tangents) {
|
||||
Slot &target = *_target;
|
||||
float position = _position;
|
||||
_positions.setSize(spacesCount * 3 + 2, 0);
|
||||
@ -275,16 +302,23 @@ PathConstraint::computeWorldPositions(PathAttachment &path, int spacesCount, boo
|
||||
Vector<float> &lengths = path.getLengths();
|
||||
curveCount -= closed ? 1 : 2;
|
||||
pathLength = lengths[curveCount];
|
||||
if (percentPosition) position *= pathLength;
|
||||
if (_data._positionMode == PositionMode_Percent) position *= pathLength;
|
||||
|
||||
if (percentSpacing) {
|
||||
for (int i = 1; i < spacesCount; ++i)
|
||||
_spaces[i] *= pathLength;
|
||||
}
|
||||
float multiplier = 0;
|
||||
switch (_data._spacingMode) {
|
||||
case SpacingMode_Percent:
|
||||
multiplier = pathLength;
|
||||
break;
|
||||
case SpacingMode_Proportional:
|
||||
multiplier = pathLength / spacesCount;
|
||||
break;
|
||||
default:
|
||||
multiplier = 1;
|
||||
}
|
||||
|
||||
world.setSize(8, 0);
|
||||
for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) {
|
||||
float space = _spaces[i];
|
||||
float space = _spaces[i] * multiplier;
|
||||
position += space;
|
||||
float p = position;
|
||||
|
||||
@ -393,19 +427,23 @@ PathConstraint::computeWorldPositions(PathAttachment &path, int spacesCount, boo
|
||||
y1 = y2;
|
||||
}
|
||||
|
||||
if (percentPosition)
|
||||
position *= pathLength;
|
||||
else
|
||||
position *= pathLength / path.getLengths()[curveCount - 1];
|
||||
if (_data._positionMode == PositionMode_Percent) position *= pathLength;
|
||||
|
||||
if (percentSpacing) {
|
||||
for (int i = 1; i < spacesCount; ++i)
|
||||
_spaces[i] *= pathLength;
|
||||
}
|
||||
float multiplier = 0;
|
||||
switch (_data._spacingMode) {
|
||||
case SpacingMode_Percent:
|
||||
multiplier = pathLength;
|
||||
break;
|
||||
case SpacingMode_Proportional:
|
||||
multiplier = pathLength / spacesCount;
|
||||
break;
|
||||
default:
|
||||
multiplier = 1;
|
||||
}
|
||||
|
||||
float curveLength = 0;
|
||||
for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) {
|
||||
float space = _spaces[i];
|
||||
float space = _spaces[i] * multiplier;
|
||||
position += space;
|
||||
float p = position;
|
||||
|
||||
|
||||
@ -41,90 +41,99 @@
|
||||
using namespace spine;
|
||||
|
||||
PathConstraintData::PathConstraintData(const String &name) :
|
||||
ConstraintData(name),
|
||||
_target(NULL),
|
||||
_positionMode(PositionMode_Fixed),
|
||||
_spacingMode(SpacingMode_Length),
|
||||
_rotateMode(RotateMode_Tangent),
|
||||
_offsetRotation(0),
|
||||
_position(0),
|
||||
_spacing(0),
|
||||
_rotateMix(0),
|
||||
_translateMix(0) {
|
||||
ConstraintData(name),
|
||||
_target(NULL),
|
||||
_positionMode(PositionMode_Fixed),
|
||||
_spacingMode(SpacingMode_Length),
|
||||
_rotateMode(RotateMode_Tangent),
|
||||
_offsetRotation(0),
|
||||
_position(0),
|
||||
_spacing(0),
|
||||
_mixRotate(0),
|
||||
_mixX(0),
|
||||
_mixY(0) {
|
||||
}
|
||||
|
||||
Vector<BoneData *> &PathConstraintData::getBones() {
|
||||
return _bones;
|
||||
return _bones;
|
||||
}
|
||||
|
||||
SlotData *PathConstraintData::getTarget() {
|
||||
return _target;
|
||||
return _target;
|
||||
}
|
||||
|
||||
void PathConstraintData::setTarget(SlotData *inValue) {
|
||||
_target = inValue;
|
||||
_target = inValue;
|
||||
}
|
||||
|
||||
PositionMode PathConstraintData::getPositionMode() {
|
||||
return _positionMode;
|
||||
return _positionMode;
|
||||
}
|
||||
|
||||
void PathConstraintData::setPositionMode(PositionMode inValue) {
|
||||
_positionMode = inValue;
|
||||
_positionMode = inValue;
|
||||
}
|
||||
|
||||
SpacingMode PathConstraintData::getSpacingMode() {
|
||||
return _spacingMode;
|
||||
return _spacingMode;
|
||||
}
|
||||
|
||||
void PathConstraintData::setSpacingMode(SpacingMode inValue) {
|
||||
_spacingMode = inValue;
|
||||
_spacingMode = inValue;
|
||||
}
|
||||
|
||||
RotateMode PathConstraintData::getRotateMode() {
|
||||
return _rotateMode;
|
||||
return _rotateMode;
|
||||
}
|
||||
|
||||
void PathConstraintData::setRotateMode(RotateMode inValue) {
|
||||
_rotateMode = inValue;
|
||||
_rotateMode = inValue;
|
||||
}
|
||||
|
||||
float PathConstraintData::getOffsetRotation() {
|
||||
return _offsetRotation;
|
||||
return _offsetRotation;
|
||||
}
|
||||
|
||||
void PathConstraintData::setOffsetRotation(float inValue) {
|
||||
_offsetRotation = inValue;
|
||||
_offsetRotation = inValue;
|
||||
}
|
||||
|
||||
float PathConstraintData::getPosition() {
|
||||
return _position;
|
||||
return _position;
|
||||
}
|
||||
|
||||
void PathConstraintData::setPosition(float inValue) {
|
||||
_position = inValue;
|
||||
_position = inValue;
|
||||
}
|
||||
|
||||
float PathConstraintData::getSpacing() {
|
||||
return _spacing;
|
||||
return _spacing;
|
||||
}
|
||||
|
||||
void PathConstraintData::setSpacing(float inValue) {
|
||||
_spacing = inValue;
|
||||
_spacing = inValue;
|
||||
}
|
||||
|
||||
float PathConstraintData::getRotateMix() {
|
||||
return _rotateMix;
|
||||
float PathConstraintData::getMixRotate() {
|
||||
return _mixRotate;
|
||||
}
|
||||
|
||||
void PathConstraintData::setRotateMix(float inValue) {
|
||||
_rotateMix = inValue;
|
||||
void PathConstraintData::setMixRotate(float inValue) {
|
||||
_mixRotate = inValue;
|
||||
}
|
||||
|
||||
float PathConstraintData::getTranslateMix() {
|
||||
return _translateMix;
|
||||
float PathConstraintData::getMixX() {
|
||||
return _mixX;
|
||||
}
|
||||
|
||||
void PathConstraintData::setTranslateMix(float inValue) {
|
||||
_translateMix = inValue;
|
||||
void PathConstraintData::setMixX(float inValue) {
|
||||
_mixX = inValue;
|
||||
}
|
||||
|
||||
float PathConstraintData::getMixY() {
|
||||
return _mixY;
|
||||
}
|
||||
|
||||
void PathConstraintData::setMixY(float inValue) {
|
||||
_mixY = inValue;
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
#include <spine/Event.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/PathConstraint.h>
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
#include <spine/Event.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/PathConstraint.h>
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
#include <spine/Event.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/PathConstraint.h>
|
||||
|
||||
@ -103,8 +103,8 @@ void RegionAttachment::updateOffset() {
|
||||
_vertexOffset[BRY] = localYCos + localX2Sin;
|
||||
}
|
||||
|
||||
void RegionAttachment::setUVs(float u, float v, float u2, float v2, bool rotate) {
|
||||
if (rotate) {
|
||||
void RegionAttachment::setUVs(float u, float v, float u2, float v2, float degrees) {
|
||||
if (degrees == 90) {
|
||||
_uvs[URX] = u;
|
||||
_uvs[URY] = v2;
|
||||
_uvs[BRX] = u;
|
||||
|
||||
@ -39,101 +39,48 @@
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(RotateTimeline, CurveTimeline)
|
||||
RTTI_IMPL(RotateTimeline, CurveTimeline1)
|
||||
|
||||
RotateTimeline::RotateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) {
|
||||
_frames.setSize(frameCount << 1, 0);
|
||||
RotateTimeline::RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, bezierCount), _boneIndex(boneIndex) {
|
||||
PropertyId ids[] = { ((PropertyId)Property_Rotate << 32) | boneIndex };
|
||||
setPropertyIds(ids, 1);
|
||||
}
|
||||
|
||||
void RotateTimeline::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(lastTime);
|
||||
SP_UNUSED(pEvents);
|
||||
SP_UNUSED(direction);
|
||||
|
||||
Bone *bone = skeleton.getBones()[_boneIndex];
|
||||
if (!bone->_active) return;
|
||||
Bone* bone = skeleton._bones[_boneIndex];
|
||||
if (!bone->_active) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup: {
|
||||
bone->_rotation = bone->_data._rotation;
|
||||
break;
|
||||
}
|
||||
case MixBlend_First: {
|
||||
float r = bone->_data._rotation - bone->_rotation;
|
||||
bone->_rotation += (r - (16384 - (int) (16384.499999999996 - r / 360)) * 360) * alpha;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// TODO?
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone->_rotation = bone->_data._rotation;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
bone->_rotation += (bone->_data._rotation - bone->_rotation) * alpha;
|
||||
default: {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (time >= _frames[_frames.size() - ENTRIES]) {
|
||||
float r = _frames[_frames.size() + PREV_ROTATION];
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone->_rotation = bone->_data._rotation + r * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
r += bone->_data._rotation - bone->_rotation;
|
||||
r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360;
|
||||
// Fall through.
|
||||
case MixBlend_Add:
|
||||
bone->_rotation += r * alpha;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Interpolate between the previous frame and the current frame.
|
||||
int frame = Animation::binarySearch(_frames, time, ENTRIES);
|
||||
float prevRotation = _frames[frame + PREV_ROTATION];
|
||||
float frameTime = _frames[frame];
|
||||
float percent = getCurvePercent((frame >> 1) - 1,
|
||||
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
|
||||
float r = _frames[frame + ROTATION] - prevRotation;
|
||||
r = prevRotation + (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * percent;
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone->_rotation = bone->_data._rotation + (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
r += bone->_data._rotation - bone->_rotation;
|
||||
// Fall through.
|
||||
case MixBlend_Add:
|
||||
bone->_rotation += (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
int RotateTimeline::getPropertyId() {
|
||||
return ((int) TimelineType_Rotate << 24) + _boneIndex;
|
||||
}
|
||||
|
||||
void RotateTimeline::setFrame(int frameIndex, float time, float degrees) {
|
||||
frameIndex <<= 1;
|
||||
_frames[frameIndex] = time;
|
||||
_frames[frameIndex + ROTATION] = degrees;
|
||||
}
|
||||
|
||||
int RotateTimeline::getBoneIndex() {
|
||||
return _boneIndex;
|
||||
}
|
||||
|
||||
void RotateTimeline::setBoneIndex(int inValue) {
|
||||
_boneIndex = inValue;
|
||||
}
|
||||
|
||||
Vector<float> &RotateTimeline::getFrames() {
|
||||
return _frames;
|
||||
}
|
||||
float r = getCurveValue(time);
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone->_rotation = bone->_data._rotation + r * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
r += bone->_data._rotation - bone->_rotation;
|
||||
case MixBlend_Add:
|
||||
bone->_rotation += r * alpha;
|
||||
}
|
||||
}
|
||||
@ -43,9 +43,12 @@
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(ScaleTimeline, TranslateTimeline)
|
||||
RTTI_IMPL(ScaleTimeline, CurveTimeline2)
|
||||
|
||||
ScaleTimeline::ScaleTimeline(int frameCount) : TranslateTimeline(frameCount) {
|
||||
ScaleTimeline::ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, bezierCount), _boneIndex(boneIndex) {
|
||||
PropertyId ids[] = { ((PropertyId)Property_ScaleX << 32) | boneIndex,
|
||||
((PropertyId)Property_ScaleY << 32) | boneIndex};
|
||||
setPropertyIds(ids, 2);
|
||||
}
|
||||
|
||||
void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
|
||||
@ -54,100 +57,244 @@ void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(pEvents);
|
||||
|
||||
Bone *boneP = skeleton._bones[_boneIndex];
|
||||
Bone &bone = *boneP;
|
||||
Bone *bone = skeleton._bones[_boneIndex];
|
||||
if (!bone->_active) return;
|
||||
|
||||
if (!bone._active) return;
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone->_scaleX = bone->_data._scaleX;
|
||||
bone->_scaleY = bone->_data._scaleY;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
bone->_scaleX += (bone->_data._scaleX - bone->_scaleX) * alpha;
|
||||
bone->_scaleY += (bone->_data._scaleY - bone->_scaleY) * alpha;
|
||||
default: {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone._scaleX = bone._data._scaleX;
|
||||
bone._scaleY = bone._data._scaleY;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
bone._scaleX += (bone._data._scaleX - bone._scaleX) * alpha;
|
||||
bone._scaleY += (bone._data._scaleY - bone._scaleY) * alpha;
|
||||
default: {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
float x, y;
|
||||
int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES);
|
||||
int curveType = (int)_curves[i / CurveTimeline2::ENTRIES];
|
||||
switch (curveType) {
|
||||
case CurveTimeline::LINEAR: {
|
||||
float before = _frames[i];
|
||||
x = _frames[i + CurveTimeline2::VALUE1];
|
||||
y = _frames[i + CurveTimeline2::VALUE2];
|
||||
float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before);
|
||||
x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t;
|
||||
y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t;
|
||||
break;
|
||||
}
|
||||
case CurveTimeline::STEPPED: {
|
||||
x = _frames[i + CurveTimeline2::VALUE1];
|
||||
y = _frames[i + CurveTimeline2::VALUE2];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
x = getBezierValue(time, i, CurveTimeline2::VALUE1, curveType - CurveTimeline2::BEZIER);
|
||||
y = getBezierValue(time, i, CurveTimeline2::VALUE2,
|
||||
curveType + CurveTimeline2::BEZIER_SIZE - CurveTimeline2::BEZIER);
|
||||
}
|
||||
}
|
||||
x *= bone->_data._scaleX;
|
||||
y *= bone->_data._scaleY;
|
||||
|
||||
float x, y;
|
||||
if (time >= _frames[_frames.size() - ENTRIES]) {
|
||||
// Time is after last frame.
|
||||
x = _frames[_frames.size() + PREV_X] * bone._data._scaleX;
|
||||
y = _frames[_frames.size() + PREV_Y] * bone._data._scaleY;
|
||||
} else {
|
||||
// Interpolate between the previous frame and the current frame.
|
||||
int frame = Animation::binarySearch(_frames, time, ENTRIES);
|
||||
x = _frames[frame + PREV_X];
|
||||
y = _frames[frame + PREV_Y];
|
||||
float frameTime = _frames[frame];
|
||||
float percent = getCurvePercent(frame / ENTRIES - 1,
|
||||
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
|
||||
|
||||
x = (x + (_frames[frame + X] - x) * percent) * bone._data._scaleX;
|
||||
y = (y + (_frames[frame + Y] - y) * percent) * bone._data._scaleY;
|
||||
}
|
||||
|
||||
if (alpha == 1) {
|
||||
if (blend == MixBlend_Add) {
|
||||
bone._scaleX += x - bone._data._scaleX;
|
||||
bone._scaleY += y - bone._data._scaleY;
|
||||
} else {
|
||||
bone._scaleX = x;
|
||||
bone._scaleY = y;
|
||||
}
|
||||
} else {
|
||||
// Mixing out uses sign of setup or current pose, else use sign of key.
|
||||
float bx, by;
|
||||
if (direction == MixDirection_Out) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bx = bone._data._scaleX;
|
||||
by = bone._data._scaleY;
|
||||
bone._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
|
||||
bone._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
bx = bone._scaleX;
|
||||
by = bone._scaleY;
|
||||
bone._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
|
||||
bone._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
bx = bone._scaleX;
|
||||
by = bone._scaleY;
|
||||
bone._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bone._data._scaleX) * alpha;
|
||||
bone._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - bone._data._scaleY) * alpha;
|
||||
}
|
||||
} else {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bx = MathUtil::abs(bone._data._scaleX) * MathUtil::sign(x);
|
||||
by = MathUtil::abs(bone._data._scaleY) * MathUtil::sign(y);
|
||||
bone._scaleX = bx + (x - bx) * alpha;
|
||||
bone._scaleY = by + (y - by) * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
bx = MathUtil::abs(bone._scaleX) * MathUtil::sign(x);
|
||||
by = MathUtil::abs(bone._scaleY) * MathUtil::sign(y);
|
||||
bone._scaleX = bx + (x - bx) * alpha;
|
||||
bone._scaleY = by + (y - by) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
bx = MathUtil::sign(x);
|
||||
by = MathUtil::sign(y);
|
||||
bone._scaleX = MathUtil::abs(bone._scaleX) * bx + (x - MathUtil::abs(bone._data._scaleX) * bx) * alpha;
|
||||
bone._scaleY = MathUtil::abs(bone._scaleY) * by + (y - MathUtil::abs(bone._data._scaleY) * by) * alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (alpha == 1) {
|
||||
if (blend == MixBlend_Add) {
|
||||
bone->_scaleX += x - bone->_data._scaleX;
|
||||
bone->_scaleY += y - bone->_data._scaleY;
|
||||
} else {
|
||||
bone->_scaleX = x;
|
||||
bone->_scaleY = y;
|
||||
}
|
||||
} else {
|
||||
float bx, by;
|
||||
if (direction == MixDirection_Out) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bx = bone->_data._scaleX;
|
||||
by = bone->_data._scaleY;
|
||||
bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
|
||||
bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
bx = bone->_scaleX;
|
||||
by = bone->_scaleY;
|
||||
bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
|
||||
bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
bx = bone->_scaleX;
|
||||
by = bone->_scaleY;
|
||||
bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bone->_data._scaleX) * alpha;
|
||||
bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - bone->_data._scaleY) * alpha;
|
||||
}
|
||||
} else {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bx = MathUtil::abs(bone->_data._scaleX) * MathUtil::sign(x);
|
||||
by = MathUtil::abs(bone->_data._scaleY) * MathUtil::sign(y);
|
||||
bone->_scaleX = bx + (x - bx) * alpha;
|
||||
bone->_scaleY = by + (y - by) * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
bx = MathUtil::abs(bone->_scaleX) * MathUtil::sign(x);
|
||||
by = MathUtil::abs(bone->_scaleY) * MathUtil::sign(y);
|
||||
bone->_scaleX = bx + (x - bx) * alpha;
|
||||
bone->_scaleY = by + (y - by) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
bx = MathUtil::sign(x);
|
||||
by = MathUtil::sign(y);
|
||||
bone->_scaleX = MathUtil::abs(bone->_scaleX) * bx + (x - MathUtil::abs(bone->_data._scaleX) * bx) * alpha;
|
||||
bone->_scaleY = MathUtil::abs(bone->_scaleY) * by + (y - MathUtil::abs(bone->_data._scaleY) * by) * alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ScaleTimeline::getPropertyId() {
|
||||
return ((int) TimelineType_Scale << 24) + _boneIndex;
|
||||
RTTI_IMPL(ScaleXTimeline, CurveTimeline1)
|
||||
|
||||
ScaleXTimeline::ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, bezierCount), _boneIndex(boneIndex) {
|
||||
PropertyId ids[] = { ((PropertyId)Property_ScaleX << 32) | boneIndex };
|
||||
setPropertyIds(ids, 1);
|
||||
}
|
||||
|
||||
void ScaleXTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
|
||||
MixBlend blend, MixDirection direction
|
||||
) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(pEvents);
|
||||
|
||||
Bone *bone = skeleton._bones[_boneIndex];
|
||||
if (!bone->_active) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone->_scaleX = bone->_data._scaleX;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
bone->_scaleX += (bone->_data._scaleX - bone->_scaleX) * alpha;
|
||||
default: {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float x = getCurveValue(time) * bone->_data._scaleX;
|
||||
if (alpha == 1) {
|
||||
if (blend == MixBlend_Add)
|
||||
bone->_scaleX += x - bone->_data._scaleX;
|
||||
else
|
||||
bone->_scaleX = x;
|
||||
} else {
|
||||
// Mixing out uses sign of setup or current pose, else use sign of key.
|
||||
float bx;
|
||||
if (direction == MixDirection_Out) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bx = bone->_data._scaleX;
|
||||
bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
bx = bone->_scaleX;
|
||||
bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
bx = bone->_scaleX;
|
||||
bone->_scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bone->_data._scaleX) * alpha;
|
||||
}
|
||||
} else {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bx = MathUtil::abs(bone->_data._scaleX) * MathUtil::sign(x);
|
||||
bone->_scaleX = bx + (x - bx) * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
bx = MathUtil::abs(bone->_scaleX) * MathUtil::sign(x);
|
||||
bone->_scaleX = bx + (x - bx) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
bx = MathUtil::sign(x);
|
||||
bone->_scaleX = MathUtil::abs(bone->_scaleX) * bx + (x - MathUtil::abs(bone->_data._scaleX) * bx) * alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RTTI_IMPL(ScaleYTimeline, CurveTimeline1)
|
||||
|
||||
ScaleYTimeline::ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, bezierCount), _boneIndex(boneIndex) {
|
||||
PropertyId ids[] = { ((PropertyId)Property_ScaleY << 32) | boneIndex };
|
||||
setPropertyIds(ids, 1);
|
||||
}
|
||||
|
||||
void ScaleYTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector<Event *> *pEvents, float alpha,
|
||||
MixBlend blend, MixDirection direction
|
||||
) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(pEvents);
|
||||
|
||||
Bone *bone = skeleton._bones[_boneIndex];
|
||||
if (!bone->_active) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone->_scaleY = bone->_data._scaleY;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
bone->_scaleY += (bone->_data._scaleY - bone->_scaleY) * alpha;
|
||||
default: {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float y = getCurveValue(time) * bone->_data._scaleY;
|
||||
if (alpha == 1) {
|
||||
if (blend == MixBlend_Add)
|
||||
bone->_scaleY += y - bone->_data._scaleY;
|
||||
else
|
||||
bone->_scaleY = y;
|
||||
} else {
|
||||
// Mixing out uses sign of setup or current pose, else use sign of key.
|
||||
float by = 0;
|
||||
if (direction == MixDirection_Out) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
by = bone->_data._scaleY;
|
||||
bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
by = bone->_scaleY;
|
||||
bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
by = bone->_scaleY;
|
||||
bone->_scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - bone->_data._scaleY) * alpha;
|
||||
}
|
||||
} else {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
by = MathUtil::abs(bone->_data._scaleY) * MathUtil::sign(y);
|
||||
bone->_scaleY = by + (y - by) * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
by = MathUtil::abs(bone->_scaleY) * MathUtil::sign(y);
|
||||
bone->_scaleY = by + (y - by) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
by = MathUtil::sign(y);
|
||||
bone->_scaleY = MathUtil::abs(bone->_scaleY) * by + (y - MathUtil::abs(bone->_data._scaleY) * by) * alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,7 +134,6 @@ Skeleton::~Skeleton() {
|
||||
|
||||
void Skeleton::updateCache() {
|
||||
_updateCache.clear();
|
||||
_updateCacheReset.clear();
|
||||
|
||||
for (size_t i = 0, n = _bones.size(); i < n; ++i) {
|
||||
Bone* bone = _bones[i];
|
||||
@ -213,24 +212,36 @@ void Skeleton::printUpdateCache() {
|
||||
}
|
||||
|
||||
void Skeleton::updateWorldTransform() {
|
||||
for (size_t i = 0, n = _updateCacheReset.size(); i < n; ++i) {
|
||||
Bone *boneP = _updateCacheReset[i];
|
||||
Bone &bone = *boneP;
|
||||
bone._ax = bone._x;
|
||||
bone._ay = bone._y;
|
||||
bone._arotation = bone._rotation;
|
||||
bone._ascaleX = bone._scaleX;
|
||||
bone._ascaleY = bone._scaleY;
|
||||
bone._ashearX = bone._shearX;
|
||||
bone._ashearY = bone._shearY;
|
||||
bone._appliedValid = true;
|
||||
}
|
||||
|
||||
for (size_t i = 0, n = _updateCache.size(); i < n; ++i) {
|
||||
_updateCache[i]->update();
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::updateWorldTransform(Bone* parent) {
|
||||
// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
|
||||
Bone& rootBone = *getRootBone();
|
||||
float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d;
|
||||
rootBone._worldX = pa * _x + pb * _y + parent->_worldX;
|
||||
rootBone._worldY = pc * _x + pd * _y + parent->_worldY;
|
||||
|
||||
float rotationY = rootBone._rotation + 90 + rootBone._shearY;
|
||||
float la = MathUtil::cosDeg(rootBone._rotation + rootBone._shearX) * rootBone._scaleX;
|
||||
float lb = MathUtil::cosDeg(rotationY) * rootBone._scaleY;
|
||||
float lc = MathUtil::sinDeg(rootBone._rotation + rootBone._shearX) * rootBone._scaleX;
|
||||
float ld = MathUtil::sinDeg(rotationY) * rootBone._scaleY;
|
||||
rootBone._a = (pa * la + pb * lc) * _scaleX;
|
||||
rootBone._b = (pa * lb + pb * ld) * _scaleX;
|
||||
rootBone._c = (pc * la + pd * lc) * _scaleY;
|
||||
rootBone._d = (pc * lb + pd * ld) * _scaleY;
|
||||
|
||||
// Update everything except root bone.
|
||||
Bone *rb = getRootBone();
|
||||
for (size_t i = 0, n = _updateCache.size(); i < n; i++) {
|
||||
Updatable *updatable = _updateCache[i];
|
||||
if (updatable != rb) updatable->update();
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::setToSetupPose() {
|
||||
setBonesToSetupPose();
|
||||
setSlotsToSetupPose();
|
||||
@ -257,10 +268,12 @@ void Skeleton::setBonesToSetupPose() {
|
||||
TransformConstraint &constraint = *constraintP;
|
||||
TransformConstraintData &constraintData = constraint._data;
|
||||
|
||||
constraint._rotateMix = constraintData._rotateMix;
|
||||
constraint._translateMix = constraintData._translateMix;
|
||||
constraint._scaleMix = constraintData._scaleMix;
|
||||
constraint._shearMix = constraintData._shearMix;
|
||||
constraint._mixRotate = constraintData._mixRotate;
|
||||
constraint._mixX = constraintData._mixX;
|
||||
constraint._mixY = constraintData._mixY;
|
||||
constraint._mixScaleX = constraintData._mixScaleX;
|
||||
constraint._mixScaleY = constraintData._mixScaleY;
|
||||
constraint._mixShearY = constraintData._mixShearY;
|
||||
}
|
||||
|
||||
for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) {
|
||||
@ -270,8 +283,9 @@ void Skeleton::setBonesToSetupPose() {
|
||||
|
||||
constraint._position = constraintData._position;
|
||||
constraint._spacing = constraintData._spacing;
|
||||
constraint._rotateMix = constraintData._rotateMix;
|
||||
constraint._translateMix = constraintData._translateMix;
|
||||
constraint._mixRotate = constraintData._mixRotate;
|
||||
constraint._mixX = constraintData._mixX;
|
||||
constraint._mixY = constraintData._mixY;
|
||||
}
|
||||
}
|
||||
|
||||
@ -563,15 +577,18 @@ void Skeleton::sortIkConstraint(IkConstraint *constraint) {
|
||||
Bone *parent = constrained[0];
|
||||
sortBone(parent);
|
||||
|
||||
if (constrained.size() > 1) {
|
||||
Bone *child = constrained[constrained.size() - 1];
|
||||
if (!_updateCache.contains(child)) _updateCacheReset.add(child);
|
||||
if (constrained.size() == 1) {
|
||||
_updateCache.add(constraint);
|
||||
sortReset(parent->_children);
|
||||
} else {
|
||||
Bone* child = constrained[constrained.size() - 1];
|
||||
sortBone(child);
|
||||
|
||||
_updateCache.add(constraint);
|
||||
|
||||
sortReset(parent->_children);
|
||||
child->_sorted = true;
|
||||
}
|
||||
|
||||
_updateCache.add(constraint);
|
||||
|
||||
sortReset(parent->getChildren());
|
||||
constrained[constrained.size() - 1]->_sorted = true;
|
||||
}
|
||||
|
||||
void Skeleton::sortPathConstraint(PathConstraint *constraint) {
|
||||
@ -617,7 +634,7 @@ void Skeleton::sortTransformConstraint(TransformConstraint *constraint) {
|
||||
for (size_t i = 0; i < boneCount; i++) {
|
||||
Bone *child = constrained[i];
|
||||
sortBone(child->getParent());
|
||||
if (!_updateCache.contains(child)) _updateCacheReset.add(child);
|
||||
sortBone(child);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < boneCount; ++i) {
|
||||
|
||||
@ -39,10 +39,39 @@
|
||||
namespace spine {
|
||||
RTTI_IMPL_NOPARENT(Timeline)
|
||||
|
||||
Timeline::Timeline() {
|
||||
Timeline::Timeline(size_t frameCount, size_t frameEntries): _propertyIds(), _frames(), _frameEntries(frameEntries) {
|
||||
_frames.setSize(frameCount * frameEntries, 0);
|
||||
}
|
||||
|
||||
Timeline::~Timeline() {
|
||||
}
|
||||
|
||||
Vector<PropertyId> &Timeline::getPropertyIds() {
|
||||
return _propertyIds;
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Timeline::getFrameCount() {
|
||||
return _frames.size() / _frameEntries;
|
||||
}
|
||||
|
||||
Vector<float> &Timeline::getFrames() {
|
||||
return _frames;
|
||||
}
|
||||
|
||||
size_t Timeline::getFrameEntries() {
|
||||
return _frameEntries;
|
||||
}
|
||||
|
||||
float Timeline::getDuration() {
|
||||
return _frames[_frames.size() - getFrameEntries()];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -45,18 +45,14 @@ RTTI_IMPL(TransformConstraint, Updatable)
|
||||
|
||||
TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : Updatable(),
|
||||
_data(data),
|
||||
_target(skeleton.findBone(
|
||||
data.getTarget()->getName())),
|
||||
_rotateMix(
|
||||
data.getRotateMix()),
|
||||
_translateMix(
|
||||
data.getTranslateMix()),
|
||||
_scaleMix(
|
||||
data.getScaleMix()),
|
||||
_shearMix(
|
||||
data.getShearMix()),
|
||||
_active(false)
|
||||
{
|
||||
_target(skeleton.findBone(data.getTarget()->getName())),
|
||||
_mixRotate(data.getMixRotate()),
|
||||
_mixX(data.getMixX()),
|
||||
_mixY(data.getMixY()),
|
||||
_mixScaleX(data.getMixScaleX()),
|
||||
_mixScaleY(data.getMixScaleY()),
|
||||
_mixShearY(data.getMixShearY()),
|
||||
_active(false) {
|
||||
_bones.ensureCapacity(_data.getBones().size());
|
||||
for (size_t i = 0; i < _data.getBones().size(); ++i) {
|
||||
BoneData *boneData = _data.getBones()[i];
|
||||
@ -64,11 +60,9 @@ TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton
|
||||
}
|
||||
}
|
||||
|
||||
void TransformConstraint::apply() {
|
||||
update();
|
||||
}
|
||||
|
||||
void TransformConstraint::update() {
|
||||
if (_mixRotate == 0 && _mixX == 0 && _mixY == 0 && _mixScaleX == 0 && _mixScaleX == 0 && _mixShearY == 0) return;
|
||||
|
||||
if (_data.isLocal()) {
|
||||
if (_data.isRelative())
|
||||
applyRelativeLocal();
|
||||
@ -102,40 +96,57 @@ void TransformConstraint::setTarget(Bone *inValue) {
|
||||
_target = inValue;
|
||||
}
|
||||
|
||||
float TransformConstraint::getRotateMix() {
|
||||
return _rotateMix;
|
||||
float TransformConstraint::getMixRotate() {
|
||||
return _mixRotate;
|
||||
}
|
||||
|
||||
void TransformConstraint::setRotateMix(float inValue) {
|
||||
_rotateMix = inValue;
|
||||
void TransformConstraint::setMixRotate(float inValue) {
|
||||
_mixRotate = inValue;
|
||||
}
|
||||
|
||||
float TransformConstraint::getTranslateMix() {
|
||||
return _translateMix;
|
||||
float TransformConstraint::getMixX() {
|
||||
return _mixX;
|
||||
}
|
||||
|
||||
void TransformConstraint::setTranslateMix(float inValue) {
|
||||
_translateMix = inValue;
|
||||
void TransformConstraint::setMixX(float inValue) {
|
||||
_mixX = inValue;
|
||||
}
|
||||
|
||||
float TransformConstraint::getScaleMix() {
|
||||
return _scaleMix;
|
||||
float TransformConstraint::getMixY() {
|
||||
return _mixY;
|
||||
}
|
||||
|
||||
void TransformConstraint::setScaleMix(float inValue) {
|
||||
_scaleMix = inValue;
|
||||
void TransformConstraint::setMixY(float inValue) {
|
||||
_mixY = inValue;
|
||||
}
|
||||
|
||||
float TransformConstraint::getShearMix() {
|
||||
return _shearMix;
|
||||
void TransformConstraint::setMixScaleX(float inValue) {
|
||||
_mixScaleX = inValue;
|
||||
}
|
||||
|
||||
void TransformConstraint::setShearMix(float inValue) {
|
||||
_shearMix = inValue;
|
||||
float TransformConstraint::getMixScaleX() {
|
||||
return _mixScaleX;
|
||||
}
|
||||
|
||||
float TransformConstraint::getMixScaleY() {
|
||||
return _mixScaleY;
|
||||
}
|
||||
|
||||
void TransformConstraint::setMixScaleY(float inValue) {
|
||||
_mixScaleY = inValue;
|
||||
}
|
||||
|
||||
float TransformConstraint::getMixShearY() {
|
||||
return _mixShearY;
|
||||
}
|
||||
|
||||
void TransformConstraint::setMixShearY(float inValue) {
|
||||
_mixShearY = inValue;
|
||||
}
|
||||
|
||||
void TransformConstraint::applyAbsoluteWorld() {
|
||||
float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix;
|
||||
float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY;
|
||||
bool translate = mixX != 0 || mixY != 0;
|
||||
Bone &target = *_target;
|
||||
float ta = target._a, tb = target._b, tc = target._c, td = target._d;
|
||||
float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad;
|
||||
@ -145,9 +156,7 @@ void TransformConstraint::applyAbsoluteWorld() {
|
||||
Bone *item = _bones[i];
|
||||
Bone &bone = *item;
|
||||
|
||||
bool modified = false;
|
||||
|
||||
if (rotateMix != 0) {
|
||||
if (mixRotate != 0) {
|
||||
float a = bone._a, b = bone._b, c = bone._c, d = bone._d;
|
||||
float r = MathUtil::atan2(tc, ta) - MathUtil::atan2(c, a) + offsetRotation;
|
||||
if (r > MathUtil::Pi)
|
||||
@ -155,38 +164,36 @@ void TransformConstraint::applyAbsoluteWorld() {
|
||||
else if (r < -MathUtil::Pi)
|
||||
r += MathUtil::Pi_2;
|
||||
|
||||
r *= rotateMix;
|
||||
r *= mixRotate;
|
||||
float cos = MathUtil::cos(r), sin = MathUtil::sin(r);
|
||||
bone._a = cos * a - sin * c;
|
||||
bone._b = cos * b - sin * d;
|
||||
bone._c = sin * a + cos * c;
|
||||
bone._d = sin * b + cos * d;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (translateMix != 0) {
|
||||
if (translate) {
|
||||
float tx, ty;
|
||||
target.localToWorld(_data._offsetX, _data._offsetY, tx, ty);
|
||||
bone._worldX += (tx - bone._worldX) * translateMix;
|
||||
bone._worldY += (ty - bone._worldY) * translateMix;
|
||||
modified = true;
|
||||
bone._worldX += (tx - bone._worldX) * mixX;
|
||||
bone._worldY += (ty - bone._worldY) * mixY;
|
||||
}
|
||||
|
||||
if (scaleMix > 0) {
|
||||
if (mixScaleX > 0) {
|
||||
float s = MathUtil::sqrt(bone._a * bone._a + bone._c * bone._c);
|
||||
|
||||
if (s > 0.00001f) s = (s + (MathUtil::sqrt(ta * ta + tc * tc) - s + _data._offsetScaleX) * scaleMix) / s;
|
||||
if (s != 0) s = (s + (MathUtil::sqrt(ta * ta + tc * tc) - s + _data._offsetScaleX) * mixScaleX) / s;
|
||||
bone._a *= s;
|
||||
bone._c *= s;
|
||||
s = MathUtil::sqrt(bone._b * bone._b + bone._d * bone._d);
|
||||
|
||||
if (s > 0.00001f) s = (s + (MathUtil::sqrt(tb * tb + td * td) - s + _data._offsetScaleY) * scaleMix) / s;
|
||||
bone._b *= s;
|
||||
bone._d *= s;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (shearMix > 0) {
|
||||
if (mixScaleY > 0) {
|
||||
float s = MathUtil::sqrt(bone._b * bone._b + bone._d * bone._d);
|
||||
if (s != 0) s = (s + (MathUtil::sqrt(tb * tb + td * td) - s + _data._offsetScaleY) * mixScaleY) / s;
|
||||
bone._b *= s;
|
||||
bone._d *= s;
|
||||
}
|
||||
|
||||
if (mixShearY > 0) {
|
||||
float b = bone._b, d = bone._d;
|
||||
float by = MathUtil::atan2(d, b);
|
||||
float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta) - (by - MathUtil::atan2(bone._c, bone._a));
|
||||
@ -195,19 +202,19 @@ void TransformConstraint::applyAbsoluteWorld() {
|
||||
else if (r < -MathUtil::Pi)
|
||||
r += MathUtil::Pi_2;
|
||||
|
||||
r = by + (r + offsetShearY) * shearMix;
|
||||
r = by + (r + offsetShearY) * mixShearY;
|
||||
float s = MathUtil::sqrt(b * b + d * d);
|
||||
bone._b = MathUtil::cos(r) * s;
|
||||
bone._d = MathUtil::sin(r) * s;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (modified) bone._appliedValid = false;
|
||||
bone._appliedValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
void TransformConstraint::applyRelativeWorld() {
|
||||
float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix;
|
||||
float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY;
|
||||
bool translate = mixX != 0 || mixY != 0;
|
||||
Bone &target = *_target;
|
||||
float ta = target._a, tb = target._b, tc = target._c, td = target._d;
|
||||
float degRadReflect = ta * td - tb * tc > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad;
|
||||
@ -216,9 +223,7 @@ void TransformConstraint::applyRelativeWorld() {
|
||||
Bone *item = _bones[i];
|
||||
Bone &bone = *item;
|
||||
|
||||
bool modified = false;
|
||||
|
||||
if (rotateMix != 0) {
|
||||
if (mixRotate != 0) {
|
||||
float a = bone._a, b = bone._b, c = bone._c, d = bone._d;
|
||||
float r = MathUtil::atan2(tc, ta) + offsetRotation;
|
||||
if (r > MathUtil::Pi)
|
||||
@ -226,34 +231,33 @@ void TransformConstraint::applyRelativeWorld() {
|
||||
else if (r < -MathUtil::Pi)
|
||||
r += MathUtil::Pi_2;
|
||||
|
||||
r *= rotateMix;
|
||||
r *= mixRotate;
|
||||
float cos = MathUtil::cos(r), sin = MathUtil::sin(r);
|
||||
bone._a = cos * a - sin * c;
|
||||
bone._b = cos * b - sin * d;
|
||||
bone._c = sin * a + cos * c;
|
||||
bone._d = sin * b + cos * d;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (translateMix != 0) {
|
||||
if (translate) {
|
||||
float tx, ty;
|
||||
target.localToWorld(_data._offsetX, _data._offsetY, tx, ty);
|
||||
bone._worldX += tx * translateMix;
|
||||
bone._worldY += ty * translateMix;
|
||||
modified = true;
|
||||
bone._worldX += tx * mixX;
|
||||
bone._worldY += ty * mixY;
|
||||
}
|
||||
|
||||
if (scaleMix > 0) {
|
||||
float s = (MathUtil::sqrt(ta * ta + tc * tc) - 1 + _data._offsetScaleX) * scaleMix + 1;
|
||||
bone._a *= s;
|
||||
bone._c *= s;
|
||||
s = (MathUtil::sqrt(tb * tb + td * td) - 1 + _data._offsetScaleY) * scaleMix + 1;
|
||||
bone._b *= s;
|
||||
bone._d *= s;
|
||||
modified = true;
|
||||
}
|
||||
if (mixScaleX != 0) {
|
||||
float s = (MathUtil::sqrt(ta * ta + tc * tc) - 1 + _data._offsetScaleX) * mixScaleX + 1;
|
||||
bone._a *= s;
|
||||
bone._c *= s;
|
||||
}
|
||||
if (mixScaleY != 0) {
|
||||
float s = (MathUtil::sqrt(tb * tb + td * td) - 1 + _data._offsetScaleY) * mixScaleY + 1;
|
||||
bone._b *= s;
|
||||
bone._d *= s;
|
||||
}
|
||||
|
||||
if (shearMix > 0) {
|
||||
if (mixShearY > 0) {
|
||||
float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta);
|
||||
if (r > MathUtil::Pi)
|
||||
r -= MathUtil::Pi_2;
|
||||
@ -261,19 +265,18 @@ void TransformConstraint::applyRelativeWorld() {
|
||||
r += MathUtil::Pi_2;
|
||||
|
||||
float b = bone._b, d = bone._d;
|
||||
r = MathUtil::atan2(d, b) + (r - MathUtil::Pi / 2 + offsetShearY) * shearMix;
|
||||
r = MathUtil::atan2(d, b) + (r - MathUtil::Pi / 2 + offsetShearY) * mixShearY;
|
||||
float s = MathUtil::sqrt(b * b + d * d);
|
||||
bone._b = MathUtil::cos(r) * s;
|
||||
bone._d = MathUtil::sin(r) * s;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (modified) bone._appliedValid = false;
|
||||
bone._appliedValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
void TransformConstraint::applyAbsoluteLocal() {
|
||||
float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix;
|
||||
float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY;
|
||||
Bone &target = *_target;
|
||||
if (!target._appliedValid) target.updateAppliedTransform();
|
||||
|
||||
@ -284,29 +287,27 @@ void TransformConstraint::applyAbsoluteLocal() {
|
||||
if (!bone._appliedValid) bone.updateAppliedTransform();
|
||||
|
||||
float rotation = bone._arotation;
|
||||
if (rotateMix != 0) {
|
||||
if (mixRotate != 0) {
|
||||
float r = target._arotation - rotation + _data._offsetRotation;
|
||||
r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360;
|
||||
rotation += r * rotateMix;
|
||||
rotation += r * mixRotate;
|
||||
}
|
||||
|
||||
float x = bone._ax, y = bone._ay;
|
||||
if (translateMix != 0) {
|
||||
x += (target._ax - x + _data._offsetX) * translateMix;
|
||||
y += (target._ay - y + _data._offsetY) * translateMix;
|
||||
}
|
||||
x += (target._ax - x + _data._offsetX) * mixX;
|
||||
y += (target._ay - y + _data._offsetY) * mixY;
|
||||
|
||||
float scaleX = bone._ascaleX, scaleY = bone._ascaleY;
|
||||
if (scaleMix != 0) {
|
||||
if (scaleX > 0.00001f) scaleX = (scaleX + (target._ascaleX - scaleX + _data._offsetScaleX) * scaleMix) / scaleX;
|
||||
if (scaleY > 0.00001f) scaleY = (scaleY + (target._ascaleY - scaleY + _data._offsetScaleY) * scaleMix) / scaleY;
|
||||
}
|
||||
if (mixScaleX != 0 && scaleX != 0)
|
||||
scaleX = (scaleX + (target._ascaleX - scaleX + _data._offsetScaleX) * mixScaleX) / scaleX;
|
||||
if (mixScaleY != 0 && scaleY != 0)
|
||||
scaleY = (scaleY + (target._ascaleY - scaleY + _data._offsetScaleY) * mixScaleY) / scaleY;
|
||||
|
||||
float shearY = bone._ashearY;
|
||||
if (shearMix != 0) {
|
||||
float shearY = bone._ashearY;
|
||||
if (mixShearY != 0) {
|
||||
float r = target._ashearY - shearY + _data._offsetShearY;
|
||||
r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360;
|
||||
bone._shearY += r * shearMix;
|
||||
bone._shearY += r * mixShearY;
|
||||
}
|
||||
|
||||
bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY);
|
||||
@ -314,7 +315,7 @@ void TransformConstraint::applyAbsoluteLocal() {
|
||||
}
|
||||
|
||||
void TransformConstraint::applyRelativeLocal() {
|
||||
float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix;
|
||||
float mixRotate = _mixRotate, mixX = _mixX, mixY = _mixY, mixScaleX = _mixScaleX, mixScaleY = _mixScaleY, mixShearY = _mixShearY;
|
||||
Bone &target = *_target;
|
||||
if (!target._appliedValid) target.updateAppliedTransform();
|
||||
|
||||
@ -324,25 +325,14 @@ void TransformConstraint::applyRelativeLocal() {
|
||||
|
||||
if (!bone._appliedValid) bone.updateAppliedTransform();
|
||||
|
||||
float rotation = bone._arotation;
|
||||
if (rotateMix != 0) rotation += (target._arotation + _data._offsetRotation) * rotateMix;
|
||||
float rotation = bone._arotation + (target._arotation + _data._offsetRotation) * mixRotate;
|
||||
float x = bone._ax + (target._ax + _data._offsetX) * mixX;
|
||||
float y = bone._ay + (target._ay + _data._offsetY) * mixY;
|
||||
float scaleX = (bone._ascaleX * ((target._ascaleX - 1 + _data._offsetScaleX) * mixScaleX) + 1);
|
||||
float scaleY = (bone._ascaleY * ((target._ascaleY - 1 + _data._offsetScaleY) * mixScaleY) + 1);
|
||||
float shearY = bone._ashearY + (target._ashearY + _data._offsetShearY) * mixShearY;
|
||||
|
||||
float x = bone._ax, y = bone._ay;
|
||||
if (translateMix != 0) {
|
||||
x += (target._ax + _data._offsetX) * translateMix;
|
||||
y += (target._ay + _data._offsetY) * translateMix;
|
||||
}
|
||||
|
||||
float scaleX = bone._ascaleX, scaleY = bone._ascaleY;
|
||||
if (scaleMix != 0) {
|
||||
if (scaleX > 0.00001f) scaleX *= ((target._ascaleX - 1 + _data._offsetScaleX) * scaleMix) + 1;
|
||||
if (scaleY > 0.00001f) scaleY *= ((target._ascaleY - 1 + _data._offsetScaleY) * scaleMix) + 1;
|
||||
}
|
||||
|
||||
float shearY = bone._ashearY;
|
||||
if (shearMix != 0) shearY += (target._ashearY + _data._offsetShearY) * shearMix;
|
||||
|
||||
bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY);
|
||||
bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -41,10 +41,12 @@ using namespace spine;
|
||||
TransformConstraintData::TransformConstraintData(const String &name) :
|
||||
ConstraintData(name),
|
||||
_target(NULL),
|
||||
_rotateMix(0),
|
||||
_translateMix(0),
|
||||
_scaleMix(0),
|
||||
_shearMix(0),
|
||||
_mixRotate(0),
|
||||
_mixX(0),
|
||||
_mixY(0),
|
||||
_mixScaleX(0),
|
||||
_mixScaleY(0),
|
||||
_mixShearY(0),
|
||||
_offsetRotation(0),
|
||||
_offsetX(0),
|
||||
_offsetY(0),
|
||||
@ -63,20 +65,28 @@ BoneData *TransformConstraintData::getTarget() {
|
||||
return _target;
|
||||
}
|
||||
|
||||
float TransformConstraintData::getRotateMix() {
|
||||
return _rotateMix;
|
||||
float TransformConstraintData::getMixRotate() {
|
||||
return _mixRotate;
|
||||
}
|
||||
|
||||
float TransformConstraintData::getTranslateMix() {
|
||||
return _translateMix;
|
||||
float TransformConstraintData::getMixX() {
|
||||
return _mixX;
|
||||
}
|
||||
|
||||
float TransformConstraintData::getScaleMix() {
|
||||
return _scaleMix;
|
||||
float TransformConstraintData::getMixY() {
|
||||
return _mixY;
|
||||
}
|
||||
|
||||
float TransformConstraintData::getShearMix() {
|
||||
return _shearMix;
|
||||
float TransformConstraintData::getMixScaleX() {
|
||||
return _mixScaleX;
|
||||
}
|
||||
|
||||
float TransformConstraintData::getMixScaleY() {
|
||||
return _mixScaleY;
|
||||
}
|
||||
|
||||
float TransformConstraintData::getMixShearY() {
|
||||
return _mixShearY;
|
||||
}
|
||||
|
||||
float TransformConstraintData::getOffsetRotation() {
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
#include <spine/Event.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/TransformConstraint.h>
|
||||
|
||||
@ -43,18 +43,12 @@
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(TranslateTimeline, CurveTimeline)
|
||||
RTTI_IMPL(TranslateTimeline, CurveTimeline2)
|
||||
|
||||
const int TranslateTimeline::ENTRIES = 3;
|
||||
const int TranslateTimeline::PREV_TIME = -3;
|
||||
const int TranslateTimeline::PREV_X = -2;
|
||||
const int TranslateTimeline::PREV_Y = -1;
|
||||
const int TranslateTimeline::X = 1;
|
||||
const int TranslateTimeline::Y = 2;
|
||||
|
||||
TranslateTimeline::TranslateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) {
|
||||
_frames.ensureCapacity(frameCount * ENTRIES);
|
||||
_frames.setSize(frameCount * ENTRIES, 0);
|
||||
TranslateTimeline::TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline2(frameCount, bezierCount), _boneIndex(boneIndex) {
|
||||
PropertyId ids[] = { ((PropertyId)Property_X << 32) | boneIndex,
|
||||
((PropertyId)Property_Y << 32) | boneIndex};
|
||||
setPropertyIds(ids, 2);
|
||||
}
|
||||
|
||||
TranslateTimeline::~TranslateTimeline() {
|
||||
@ -67,65 +61,152 @@ void TranslateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Ve
|
||||
SP_UNUSED(pEvents);
|
||||
SP_UNUSED(direction);
|
||||
|
||||
Bone *boneP = skeleton._bones[_boneIndex];
|
||||
Bone &bone = *boneP;
|
||||
if (!bone._active) return;
|
||||
Bone* bone = skeleton._bones[_boneIndex];
|
||||
if (!bone->_active) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone._x = bone._data._x;
|
||||
bone._y = bone._data._y;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
bone._x += (bone._data._x - bone._x) * alpha;
|
||||
bone._y += (bone._data._y - bone._y) * alpha;
|
||||
default: {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone->_x = bone->_data._x;
|
||||
bone->_y = bone->_data._y;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
bone->_x += (bone->_data._x - bone->_x) * alpha;
|
||||
bone->_y += (bone->_data._y - bone->_y) * alpha;
|
||||
default: {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float x, y;
|
||||
if (time >= _frames[_frames.size() - ENTRIES]) {
|
||||
// Time is after last frame.
|
||||
x = _frames[_frames.size() + PREV_X];
|
||||
y = _frames[_frames.size() + PREV_Y];
|
||||
} else {
|
||||
// Interpolate between the previous frame and the current frame.
|
||||
int frame = Animation::binarySearch(_frames, time, ENTRIES);
|
||||
x = _frames[frame + PREV_X];
|
||||
y = _frames[frame + PREV_Y];
|
||||
float frameTime = _frames[frame];
|
||||
float percent = getCurvePercent(frame / ENTRIES - 1,
|
||||
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
|
||||
float x = 0, y = 0;
|
||||
int i = Animation::search(_frames, time, CurveTimeline2::ENTRIES);
|
||||
int curveType = (int)_curves[i / CurveTimeline2::ENTRIES];
|
||||
switch (curveType) {
|
||||
case CurveTimeline::LINEAR: {
|
||||
float before = _frames[i];
|
||||
x = _frames[i + CurveTimeline2::VALUE1];
|
||||
y = _frames[i + CurveTimeline2::VALUE2];
|
||||
float t = (time - before) / (_frames[i + CurveTimeline2::ENTRIES] - before);
|
||||
x += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE1] - x) * t;
|
||||
y += (_frames[i + CurveTimeline2::ENTRIES + CurveTimeline2::VALUE2] - y) * t;
|
||||
break;
|
||||
}
|
||||
case CurveTimeline::STEPPED: {
|
||||
x = _frames[i + CurveTimeline2::VALUE1];
|
||||
y = _frames[i + CurveTimeline2::VALUE2];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
x = getBezierValue(time, i, CurveTimeline2::VALUE1, curveType - CurveTimeline::BEZIER);
|
||||
y = getBezierValue(time, i, CurveTimeline2::VALUE2,
|
||||
curveType + CurveTimeline::BEZIER_SIZE - CurveTimeline::BEZIER);
|
||||
}
|
||||
}
|
||||
|
||||
x += (_frames[frame + X] - x) * percent;
|
||||
y += (_frames[frame + Y] - y) * percent;
|
||||
}
|
||||
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone._x = bone._data._x + x * alpha;
|
||||
bone._y = bone._data._y + y * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
bone._x += (bone._data._x + x - bone._x) * alpha;
|
||||
bone._y += (bone._data._y + y - bone._y) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
bone._x += x * alpha;
|
||||
bone._y += y * alpha;
|
||||
}
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone->_x = bone->_data._x + x * alpha;
|
||||
bone->_y = bone->_data._y + y * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
bone->_x += (bone->_data._x + x - bone->_x) * alpha;
|
||||
bone->_y += (bone->_data._y + y - bone->_y) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
bone->_x += x * alpha;
|
||||
bone->_y += y * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
int TranslateTimeline::getPropertyId() {
|
||||
return ((int) TimelineType_Translate << 24) + _boneIndex;
|
||||
RTTI_IMPL(TranslateXTimeline, CurveTimeline1)
|
||||
|
||||
TranslateXTimeline::TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, bezierCount), _boneIndex(boneIndex) {
|
||||
PropertyId ids[] = { ((PropertyId)Property_X << 32) | boneIndex };
|
||||
setPropertyIds(ids, 1);
|
||||
}
|
||||
|
||||
void TranslateTimeline::setFrame(int frameIndex, float time, float x, float y) {
|
||||
frameIndex *= ENTRIES;
|
||||
_frames[frameIndex] = time;
|
||||
_frames[frameIndex + X] = x;
|
||||
_frames[frameIndex + Y] = y;
|
||||
TranslateXTimeline::~TranslateXTimeline() {
|
||||
}
|
||||
|
||||
void TranslateXTimeline::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);
|
||||
|
||||
Bone* bone = skeleton._bones[_boneIndex];
|
||||
if (!bone->_active) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone->_x = bone->_data._x;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
bone->_x += (bone->_data._x - bone->_x) * alpha;
|
||||
default: {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float x = getCurveValue(time);
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone->_x = bone->_data._x + x * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
bone->_x += (bone->_data._x + x - bone->_x) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
bone->_x += x * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
RTTI_IMPL(TranslateYTimeline, CurveTimeline1)
|
||||
|
||||
TranslateYTimeline::TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex) : CurveTimeline1(frameCount, bezierCount), _boneIndex(boneIndex) {
|
||||
PropertyId ids[] = { ((PropertyId)Property_Y << 32) | boneIndex };
|
||||
setPropertyIds(ids, 1);
|
||||
}
|
||||
|
||||
TranslateYTimeline::~TranslateYTimeline() {
|
||||
}
|
||||
|
||||
void TranslateYTimeline::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);
|
||||
|
||||
Bone* bone = skeleton._bones[_boneIndex];
|
||||
if (!bone->_active) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone->_y = bone->_data._y;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
bone->_y += (bone->_data._y - bone->_y) * alpha;
|
||||
default: {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float y = getCurveValue(time);
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bone->_y = bone->_data._y + y * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
bone->_y += (bone->_data._y + y - bone->_y) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
bone->_y += y * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
|
||||
@ -157,8 +157,7 @@ void VertexAttachment::setDeformAttachment(VertexAttachment* attachment) {
|
||||
|
||||
int VertexAttachment::getNextID() {
|
||||
static int nextID = 0;
|
||||
|
||||
return (nextID++ & 65535) << 11;
|
||||
return nextID++;
|
||||
}
|
||||
|
||||
void VertexAttachment::copyTo(VertexAttachment* other) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 2.8.9)
|
||||
#
|
||||
# First download and extract SFML 2.3.2 for the respective OS we are on
|
||||
# First download and extract SFML 2.4.1 for the respective OS we are on
|
||||
#
|
||||
set(DEPS_DIR "${CMAKE_CURRENT_LIST_DIR}/dependencies/")
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user