[cpp] 4.0 port, half done.

This commit is contained in:
badlogic 2021-03-02 16:54:14 +01:00
parent 8c4d03c8be
commit 653c06a6b8
45 changed files with 1178 additions and 781 deletions

View File

@ -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" />

View File

@ -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">

View File

@ -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);
};
}

View File

@ -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:

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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;
};
}

View File

@ -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 */

View File

@ -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.

View File

@ -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, ...
};
}

View File

@ -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 */

View File

@ -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;

View File

@ -34,7 +34,8 @@ namespace spine {
enum SpacingMode {
SpacingMode_Length = 0,
SpacingMode_Fixed,
SpacingMode_Percent
SpacingMode_Percent,
SpacingMode_Proportional
};
}

View File

@ -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;
};
}

View File

@ -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();

View File

@ -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;
};

View File

@ -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 */

View File

@ -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>

View File

@ -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;
}

View File

@ -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>

View File

@ -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>

View File

@ -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;
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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];

View File

@ -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>

View File

@ -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;

View File

@ -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;
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;
}
}
}
}

View File

@ -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) {

View File

@ -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()];
}
}

View File

@ -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);
}
}

View File

@ -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() {

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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) {

View File

@ -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")