mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[cpp] More 4.0 porting, SkeletonBinary.
This commit is contained in:
parent
df6de224e3
commit
dbd708c866
@ -45,26 +45,38 @@ namespace spine {
|
|||||||
class Attachment;
|
class Attachment;
|
||||||
class VertexAttachment;
|
class VertexAttachment;
|
||||||
class Animation;
|
class Animation;
|
||||||
|
class Timeline;
|
||||||
class CurveTimeline;
|
class CurveTimeline;
|
||||||
|
class CurveTimeline1;
|
||||||
|
class CurveTimeline2;
|
||||||
|
|
||||||
class SP_API SkeletonBinary : public SpineObject {
|
class SP_API SkeletonBinary : public SpineObject {
|
||||||
public:
|
public:
|
||||||
static const int BONE_ROTATE;
|
static const int BONE_ROTATE = 0;
|
||||||
static const int BONE_TRANSLATE;
|
static const int BONE_TRANSLATE = 1;
|
||||||
static const int BONE_SCALE;
|
static const int BONE_TRANSLATEX = 2;
|
||||||
static const int BONE_SHEAR;
|
static const int BONE_TRANSLATEY = 3;
|
||||||
|
static const int BONE_SCALE = 4;
|
||||||
|
static const int BONE_SCALEX = 5;
|
||||||
|
static const int BONE_SCALEY = 6;
|
||||||
|
static const int BONE_SHEAR = 7;
|
||||||
|
static const int BONE_SHEARX = 8;
|
||||||
|
static const int BONE_SHEARY = 9;
|
||||||
|
|
||||||
static const int SLOT_ATTACHMENT;
|
static const int SLOT_ATTACHMENT = 0;
|
||||||
static const int SLOT_COLOR;
|
static const int SLOT_RGBA = 1;
|
||||||
static const int SLOT_TWO_COLOR;
|
static const int SLOT_RGB = 2;
|
||||||
|
static const int SLOT_RGBA2 = 3;
|
||||||
|
static const int SLOT_RGB2 = 4;
|
||||||
|
static const int SLOT_ALPHA = 5;
|
||||||
|
|
||||||
static const int PATH_POSITION;
|
static const int PATH_POSITION = 0;
|
||||||
static const int PATH_SPACING;
|
static const int PATH_SPACING = 1;
|
||||||
static const int PATH_MIX;
|
static const int PATH_MIX = 2;
|
||||||
|
|
||||||
static const int CURVE_LINEAR;
|
static const int CURVE_LINEAR = 0;
|
||||||
static const int CURVE_STEPPED;
|
static const int CURVE_STEPPED = 1;
|
||||||
static const int CURVE_BEZIER;
|
static const int CURVE_BEZIER = 2;
|
||||||
|
|
||||||
explicit SkeletonBinary(Atlas* atlasArray);
|
explicit SkeletonBinary(Atlas* atlasArray);
|
||||||
|
|
||||||
@ -124,7 +136,12 @@ namespace spine {
|
|||||||
|
|
||||||
Animation* readAnimation(const String& name, DataInput* input, SkeletonData *skeletonData);
|
Animation* readAnimation(const String& name, DataInput* input, SkeletonData *skeletonData);
|
||||||
|
|
||||||
void readCurve(DataInput* input, int frameIndex, CurveTimeline* timeline);
|
void setBezier(DataInput* input, CurveTimeline* timeline, int bezier, int frame, int value, float time1, float time2,
|
||||||
|
float value1, float value2, float scale);
|
||||||
|
|
||||||
|
Timeline *readTimeline (DataInput *input, CurveTimeline1 *timeline, float scale);
|
||||||
|
|
||||||
|
Timeline *readTimeline2 (DataInput *input, CurveTimeline2 *timeline, float scale);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,80 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Spine Runtimes License Agreement
|
|
||||||
* Last updated January 1, 2020. Replaces all prior versions.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013-2020, Esoteric Software LLC
|
|
||||||
*
|
|
||||||
* Integration of the Spine Runtimes into software or otherwise creating
|
|
||||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
|
||||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
|
||||||
* http://esotericsoftware.com/spine-editor-license
|
|
||||||
*
|
|
||||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
|
||||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
|
||||||
* "Products"), provided that each user of the Products must obtain their own
|
|
||||||
* Spine Editor license and redistribution of the Products in any form must
|
|
||||||
* include this license and copyright notice.
|
|
||||||
*
|
|
||||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
|
||||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef Spine_TwoColorTimeline_h
|
|
||||||
#define Spine_TwoColorTimeline_h
|
|
||||||
|
|
||||||
#include <spine/CurveTimeline.h>
|
|
||||||
|
|
||||||
namespace spine {
|
|
||||||
|
|
||||||
class SP_API TwoColorTimeline : public CurveTimeline {
|
|
||||||
friend class SkeletonBinary;
|
|
||||||
friend class SkeletonJson;
|
|
||||||
|
|
||||||
RTTI_DECL
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const int ENTRIES;
|
|
||||||
|
|
||||||
explicit TwoColorTimeline(int frameCount);
|
|
||||||
|
|
||||||
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 r, float g, float b, float a, float r2, float g2, float b2);
|
|
||||||
|
|
||||||
int getSlotIndex();
|
|
||||||
void setSlotIndex(int inValue);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const int PREV_TIME;
|
|
||||||
static const int PREV_R;
|
|
||||||
static const int PREV_G;
|
|
||||||
static const int PREV_B;
|
|
||||||
static const int PREV_A;
|
|
||||||
static const int PREV_R2;
|
|
||||||
static const int PREV_G2;
|
|
||||||
static const int PREV_B2;
|
|
||||||
static const int R;
|
|
||||||
static const int G;
|
|
||||||
static const int B;
|
|
||||||
static const int A;
|
|
||||||
static const int R2;
|
|
||||||
static const int G2;
|
|
||||||
static const int B2;
|
|
||||||
|
|
||||||
Vector<float> _frames; // time, r, g, b, a, r2, g2, b2, ...
|
|
||||||
int _slotIndex;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* Spine_TwoColorTimeline_h */
|
|
||||||
@ -59,7 +59,6 @@
|
|||||||
#include <spine/EventData.h>
|
#include <spine/EventData.h>
|
||||||
#include <spine/AttachmentTimeline.h>
|
#include <spine/AttachmentTimeline.h>
|
||||||
#include <spine/ColorTimeline.h>
|
#include <spine/ColorTimeline.h>
|
||||||
#include <spine/TwoColorTimeline.h>
|
|
||||||
#include <spine/RotateTimeline.h>
|
#include <spine/RotateTimeline.h>
|
||||||
#include <spine/TranslateTimeline.h>
|
#include <spine/TranslateTimeline.h>
|
||||||
#include <spine/ScaleTimeline.h>
|
#include <spine/ScaleTimeline.h>
|
||||||
@ -76,23 +75,6 @@
|
|||||||
|
|
||||||
using namespace spine;
|
using namespace spine;
|
||||||
|
|
||||||
const int SkeletonBinary::BONE_ROTATE = 0;
|
|
||||||
const int SkeletonBinary::BONE_TRANSLATE = 1;
|
|
||||||
const int SkeletonBinary::BONE_SCALE = 2;
|
|
||||||
const int SkeletonBinary::BONE_SHEAR = 3;
|
|
||||||
|
|
||||||
const int SkeletonBinary::SLOT_ATTACHMENT = 0;
|
|
||||||
const int SkeletonBinary::SLOT_COLOR = 1;
|
|
||||||
const int SkeletonBinary::SLOT_TWO_COLOR = 2;
|
|
||||||
|
|
||||||
const int SkeletonBinary::PATH_POSITION = 0;
|
|
||||||
const int SkeletonBinary::PATH_SPACING = 1;
|
|
||||||
const int SkeletonBinary::PATH_MIX = 2;
|
|
||||||
|
|
||||||
const int SkeletonBinary::CURVE_LINEAR = 0;
|
|
||||||
const int SkeletonBinary::CURVE_STEPPED = 1;
|
|
||||||
const int SkeletonBinary::CURVE_BEZIER = 2;
|
|
||||||
|
|
||||||
SkeletonBinary::SkeletonBinary(Atlas *atlasArray) : _attachmentLoader(
|
SkeletonBinary::SkeletonBinary(Atlas *atlasArray) : _attachmentLoader(
|
||||||
new(__FILE__, __LINE__) AtlasAttachmentLoader(atlasArray)), _error(), _scale(1), _ownsLoader(true) {
|
new(__FILE__, __LINE__) AtlasAttachmentLoader(atlasArray)), _error(), _scale(1), _ownsLoader(true) {
|
||||||
|
|
||||||
@ -123,17 +105,18 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|||||||
|
|
||||||
skeletonData = new(__FILE__, __LINE__) SkeletonData();
|
skeletonData = new(__FILE__, __LINE__) SkeletonData();
|
||||||
|
|
||||||
char *skeletonData_hash = readString(input);
|
char buffer[8] = { 0 };
|
||||||
skeletonData->_hash.own(skeletonData_hash);
|
int lowHash = readInt(input);
|
||||||
|
int hightHash = readInt(input);
|
||||||
|
String hashString;
|
||||||
|
sprintf(buffer, "%x", hightHash);
|
||||||
|
hashString.append(buffer);
|
||||||
|
sprintf(buffer, "%x", lowHash);
|
||||||
|
hashString.append(buffer);
|
||||||
|
skeletonData->_hash = hashString;
|
||||||
|
|
||||||
char *skeletonData_version = readString(input);
|
char *skeletonDataVersion = readString(input);
|
||||||
skeletonData->_version.own(skeletonData_version);
|
skeletonData->_version.own(skeletonDataVersion);
|
||||||
if ("3.8.75" == skeletonData->_version) {
|
|
||||||
delete input;
|
|
||||||
delete skeletonData;
|
|
||||||
setError("Unsupported skeleton data, please export with a newer version of Spine.", "");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
skeletonData->_x = readFloat(input);
|
skeletonData->_x = readFloat(input);
|
||||||
skeletonData->_y = readFloat(input);
|
skeletonData->_y = readFloat(input);
|
||||||
@ -239,10 +222,12 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|||||||
data->_offsetScaleX = readFloat(input);
|
data->_offsetScaleX = readFloat(input);
|
||||||
data->_offsetScaleY = readFloat(input);
|
data->_offsetScaleY = readFloat(input);
|
||||||
data->_offsetShearY = readFloat(input);
|
data->_offsetShearY = readFloat(input);
|
||||||
data->_rotateMix = readFloat(input);
|
data->_mixRotate = readFloat(input);
|
||||||
data->_translateMix = readFloat(input);
|
data->_mixX = readFloat(input);
|
||||||
data->_scaleMix = readFloat(input);
|
data->_mixY = readFloat(input);
|
||||||
data->_shearMix = readFloat(input);
|
data->_mixScaleX = readFloat(input);
|
||||||
|
data->_mixScaleY = readFloat(input);
|
||||||
|
data->_mixShearY = readFloat(input);
|
||||||
skeletonData->_transformConstraints[i] = data;
|
skeletonData->_transformConstraints[i] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,8 +253,9 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|||||||
data->_spacing = readFloat(input);
|
data->_spacing = readFloat(input);
|
||||||
if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed)
|
if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed)
|
||||||
data->_spacing *= _scale;
|
data->_spacing *= _scale;
|
||||||
data->_rotateMix = readFloat(input);
|
data->_mixRotate = readFloat(input);
|
||||||
data->_translateMix = readFloat(input);
|
data->_mixX = readFloat(input);
|
||||||
|
data->_mixY = readFloat(input);
|
||||||
skeletonData->_pathConstraints[i] = data;
|
skeletonData->_pathConstraints[i] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,69 +686,276 @@ void SkeletonBinary::readShortArray(DataInput *input, Vector<unsigned short> &ar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkeletonBinary::setBezier(DataInput* input, CurveTimeline* timeline, int bezier, int frame, int value, float time1, float time2,
|
||||||
|
float value1, float value2, float scale) {
|
||||||
|
float cx1 = readFloat(input);
|
||||||
|
float cy1 = readFloat(input);
|
||||||
|
float cx2 = readFloat(input);
|
||||||
|
float cy2 = readFloat(input);
|
||||||
|
timeline->setBezier(bezier, frame, value, time1, value1, cx1, cy1 * scale, cx2, cy2 * scale, time2, value2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Timeline *SkeletonBinary::readTimeline (DataInput *input, CurveTimeline1 *timeline, float scale) {
|
||||||
|
float time = readFloat(input);
|
||||||
|
float value = readFloat(input) * scale;
|
||||||
|
for (int frame = 0, bezier = 0, frameLast = timeline->getFrameCount() - 1;; frame++) {
|
||||||
|
timeline->setFrame(frame, time, value);
|
||||||
|
if (frame == frameLast) break;
|
||||||
|
float time2 = readFloat(input);
|
||||||
|
float value2 = readFloat(input) * scale;
|
||||||
|
switch (readSByte(input)) {
|
||||||
|
case CURVE_STEPPED:
|
||||||
|
timeline->setStepped(frame);
|
||||||
|
break;
|
||||||
|
case CURVE_BEZIER:
|
||||||
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, 1);
|
||||||
|
}
|
||||||
|
time = time2;
|
||||||
|
value = value2;
|
||||||
|
}
|
||||||
|
return timeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
Timeline *SkeletonBinary::readTimeline2 (DataInput *input, CurveTimeline2 *timeline, float scale) {
|
||||||
|
float time = readFloat(input);
|
||||||
|
float value1 = readFloat(input) * scale;
|
||||||
|
float value2 = readFloat(input) * scale;
|
||||||
|
for (int frame = 0, bezier = 0, frameLast = timeline->getFrameCount() - 1;; frame++) {
|
||||||
|
timeline->setFrame(frame, time, value1, value2);
|
||||||
|
if (frame == frameLast) break;
|
||||||
|
float time2 = readFloat(input);
|
||||||
|
float nvalue1 = readFloat(input) * scale;
|
||||||
|
float nvalue2 = readFloat(input) * scale;
|
||||||
|
switch (readSByte(input)) {
|
||||||
|
case CURVE_STEPPED:
|
||||||
|
timeline->setStepped(frame);
|
||||||
|
break;
|
||||||
|
case CURVE_BEZIER:
|
||||||
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale);
|
||||||
|
}
|
||||||
|
time = time2;
|
||||||
|
value1 = nvalue1;
|
||||||
|
value2 = nvalue2;
|
||||||
|
}
|
||||||
|
return timeline;
|
||||||
|
}
|
||||||
|
|
||||||
Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, SkeletonData *skeletonData) {
|
Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, SkeletonData *skeletonData) {
|
||||||
Vector<Timeline *> timelines;
|
Vector<Timeline *> timelines;
|
||||||
float scale = _scale;
|
float scale = _scale;
|
||||||
float duration = 0;
|
int numTimelines = readVarint(input, true);
|
||||||
|
|
||||||
// Slot timelines.
|
// Slot timelines.
|
||||||
for (int i = 0, n = readVarint(input, true); i < n; ++i) {
|
for (int i = 0, n = numTimelines; i < n; ++i) {
|
||||||
int slotIndex = readVarint(input, true);
|
int slotIndex = readVarint(input, true);
|
||||||
for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) {
|
for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) {
|
||||||
unsigned char timelineType = readByte(input);
|
unsigned char timelineType = readByte(input);
|
||||||
int frameCount = readVarint(input, true);
|
int frameCount = readVarint(input, true);
|
||||||
|
int frameLast = frameCount - 1;
|
||||||
switch (timelineType) {
|
switch (timelineType) {
|
||||||
case SLOT_ATTACHMENT: {
|
case SLOT_ATTACHMENT: {
|
||||||
AttachmentTimeline *timeline = new(__FILE__, __LINE__) AttachmentTimeline(frameCount);
|
AttachmentTimeline *timeline = new(__FILE__, __LINE__) AttachmentTimeline(frameCount, slotIndex);
|
||||||
timeline->_slotIndex = slotIndex;
|
for (int frame = 0; frame < frameCount; ++frame) {
|
||||||
for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
|
||||||
float time = readFloat(input);
|
float time = readFloat(input);
|
||||||
String attachmentName(readStringRef(input, skeletonData));
|
String attachmentName(readStringRef(input, skeletonData));
|
||||||
timeline->setFrame(frameIndex, time, attachmentName);
|
timeline->setFrame(frame, time, attachmentName);
|
||||||
}
|
}
|
||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
duration = MathUtil::max(duration, timeline->_frames[frameCount - 1]);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SLOT_COLOR: {
|
case SLOT_RGBA: {
|
||||||
ColorTimeline *timeline = new(__FILE__, __LINE__) ColorTimeline(frameCount);
|
int bezierCount = readVarint(input, true);
|
||||||
timeline->_slotIndex = slotIndex;
|
RGBATimeline *timeline = new(__FILE__, __LINE__) RGBATimeline(frameCount, bezierCount, slotIndex);
|
||||||
for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
|
||||||
float time = readFloat(input);
|
|
||||||
int color = readInt(input);
|
|
||||||
float r = ((color & 0xff000000) >> 24) / 255.0f;
|
|
||||||
float g = ((color & 0x00ff0000) >> 16) / 255.0f;
|
|
||||||
float b = ((color & 0x0000ff00) >> 8) / 255.0f;
|
|
||||||
float a = ((color & 0x000000ff)) / 255.0f;
|
|
||||||
timeline->setFrame(frameIndex, time, r, g, b, a);
|
|
||||||
if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
|
||||||
}
|
|
||||||
timelines.add(timeline);
|
|
||||||
duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * ColorTimeline::ENTRIES]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SLOT_TWO_COLOR: {
|
|
||||||
TwoColorTimeline *timeline = new(__FILE__, __LINE__) TwoColorTimeline(frameCount);
|
|
||||||
timeline->_slotIndex = slotIndex;
|
|
||||||
for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
|
||||||
float time = readFloat(input);
|
|
||||||
int color = readInt(input);
|
|
||||||
float r = ((color & 0xff000000) >> 24) / 255.0f;
|
|
||||||
float g = ((color & 0x00ff0000) >> 16) / 255.0f;
|
|
||||||
float b = ((color & 0x0000ff00) >> 8) / 255.0f;
|
|
||||||
float a = ((color & 0x000000ff)) / 255.0f;
|
|
||||||
int color2 = readInt(input); // 0x00rrggbb
|
|
||||||
float r2 = ((color2 & 0x00ff0000) >> 16) / 255.0f;
|
|
||||||
float g2 = ((color2 & 0x0000ff00) >> 8) / 255.0f;
|
|
||||||
float b2 = ((color2 & 0x000000ff)) / 255.0f;
|
|
||||||
|
|
||||||
timeline->setFrame(frameIndex, time, r, g, b, a, r2, g2, b2);
|
float time = readFloat(input);
|
||||||
if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
float r = readByte(input) / 255.0;
|
||||||
}
|
float g = readByte(input) / 255.0;
|
||||||
timelines.add(timeline);
|
float b = readByte(input) / 255.0;
|
||||||
duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * TwoColorTimeline::ENTRIES]);
|
float a = readByte(input) / 255.0;
|
||||||
break;
|
|
||||||
|
for (int frame = 0, bezier = 0;; frame++) {
|
||||||
|
timeline->setFrame(frame, time, r, g, b, a);
|
||||||
|
if (frame == frameLast) break;
|
||||||
|
|
||||||
|
float time2 = readFloat(input);
|
||||||
|
float r2 = readByte(input) / 255.0;
|
||||||
|
float g2 = readByte(input) / 255.0;
|
||||||
|
float b2 = readByte(input) / 255.0;
|
||||||
|
float a2 = readByte(input) / 255.0;
|
||||||
|
|
||||||
|
switch (readSByte(input)) {
|
||||||
|
case CURVE_STEPPED:
|
||||||
|
timeline->setStepped(frame);
|
||||||
|
break;
|
||||||
|
case CURVE_BEZIER:
|
||||||
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1);
|
||||||
|
}
|
||||||
|
time = time2;
|
||||||
|
r = r2;
|
||||||
|
g = g2;
|
||||||
|
b = b2;
|
||||||
|
a = a2;
|
||||||
|
}
|
||||||
|
timelines.add(timeline);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case SLOT_RGB: {
|
||||||
|
int bezierCount = readVarint(input, true);
|
||||||
|
RGBTimeline *timeline = new(__FILE__, __LINE__) RGBTimeline(frameCount, bezierCount, slotIndex);
|
||||||
|
|
||||||
|
float time = readFloat(input);
|
||||||
|
float r = readByte(input) / 255.0;
|
||||||
|
float g = readByte(input) / 255.0;
|
||||||
|
float b = readByte(input) / 255.0;
|
||||||
|
|
||||||
|
for (int frame = 0, bezier = 0;; frame++) {
|
||||||
|
timeline->setFrame(frame, time, r, g, b);
|
||||||
|
if (frame == frameLast) break;
|
||||||
|
|
||||||
|
float time2 = readFloat(input);
|
||||||
|
float r2 = readByte(input) / 255.0;
|
||||||
|
float g2 = readByte(input) / 255.0;
|
||||||
|
float b2 = readByte(input) / 255.0;
|
||||||
|
|
||||||
|
switch (readSByte(input)) {
|
||||||
|
case CURVE_STEPPED:
|
||||||
|
timeline->setStepped(frame);
|
||||||
|
break;
|
||||||
|
case CURVE_BEZIER:
|
||||||
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1);
|
||||||
|
}
|
||||||
|
time = time2;
|
||||||
|
r = r2;
|
||||||
|
g = g2;
|
||||||
|
b = b2;
|
||||||
|
}
|
||||||
|
timelines.add(timeline);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SLOT_RGBA2: {
|
||||||
|
int bezierCount = readVarint(input, true);
|
||||||
|
RGBA2Timeline *timeline = new(__FILE__, __LINE__) RGBA2Timeline(frameCount, bezierCount, slotIndex);
|
||||||
|
|
||||||
|
float time = readFloat(input);
|
||||||
|
float r = readByte(input) / 255.0;
|
||||||
|
float g = readByte(input) / 255.0;
|
||||||
|
float b = readByte(input) / 255.0;
|
||||||
|
float a = readByte(input) / 255.0;
|
||||||
|
float r2 = readByte(input) / 255.0;
|
||||||
|
float g2 = readByte(input) / 255.0;
|
||||||
|
float b2 = readByte(input) / 255.0;
|
||||||
|
|
||||||
|
for (int frame = 0, bezier = 0;; frame++) {
|
||||||
|
timeline->setFrame(frame, time, r, g, b, a, r2, g2, b2);
|
||||||
|
if (frame == frameLast) break;
|
||||||
|
float time2 = readFloat(input);
|
||||||
|
float nr = readByte(input) / 255.0;
|
||||||
|
float ng = readByte(input) / 255.0;
|
||||||
|
float nb = readByte(input) / 255.0;
|
||||||
|
float na = readByte(input) / 255.0;
|
||||||
|
float nr2 = readByte(input) / 255.0;
|
||||||
|
float ng2 = readByte(input) / 255.0;
|
||||||
|
float nb2 = readByte(input) / 255.0;
|
||||||
|
|
||||||
|
switch (readSByte(input)) {
|
||||||
|
case CURVE_STEPPED:
|
||||||
|
timeline->setStepped(frame);
|
||||||
|
break;
|
||||||
|
case CURVE_BEZIER:
|
||||||
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1);
|
||||||
|
}
|
||||||
|
time = time2;
|
||||||
|
r = nr;
|
||||||
|
g = ng;
|
||||||
|
b = nb;
|
||||||
|
a = na;
|
||||||
|
r2 = nr2;
|
||||||
|
g2 = ng2;
|
||||||
|
b2 = nb2;
|
||||||
|
}
|
||||||
|
timelines.add(timeline);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SLOT_RGB2: {
|
||||||
|
int bezierCount = readVarint(input, true);
|
||||||
|
RGB2Timeline *timeline = new(__FILE__, __LINE__) RGB2Timeline(frameCount, bezierCount, slotIndex);
|
||||||
|
|
||||||
|
float time = readFloat(input);
|
||||||
|
float r = readByte(input) / 255.0;
|
||||||
|
float g = readByte(input) / 255.0;
|
||||||
|
float b = readByte(input) / 255.0;
|
||||||
|
float r2 = readByte(input) / 255.0;
|
||||||
|
float g2 = readByte(input) / 255.0;
|
||||||
|
float b2 = readByte(input) / 255.0;
|
||||||
|
|
||||||
|
for (int frame = 0, bezier = 0;; frame++) {
|
||||||
|
timeline->setFrame(frame, time, r, g, b, r2, g2, b2);
|
||||||
|
if (frame == frameLast) break;
|
||||||
|
float time2 = readFloat(input);
|
||||||
|
float nr = readByte(input) / 255.0;
|
||||||
|
float ng = readByte(input) / 255.0;
|
||||||
|
float nb = readByte(input) / 255.0;
|
||||||
|
float nr2 = readByte(input) / 255.0;
|
||||||
|
float ng2 = readByte(input) / 255.0;
|
||||||
|
float nb2 = readByte(input) / 255.0;
|
||||||
|
|
||||||
|
switch (readSByte(input)) {
|
||||||
|
case CURVE_STEPPED:
|
||||||
|
timeline->setStepped(frame);
|
||||||
|
break;
|
||||||
|
case CURVE_BEZIER:
|
||||||
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1);
|
||||||
|
}
|
||||||
|
time = time2;
|
||||||
|
r = nr;
|
||||||
|
g = ng;
|
||||||
|
b = nb;
|
||||||
|
r2 = nr2;
|
||||||
|
g2 = ng2;
|
||||||
|
b2 = nb2;
|
||||||
|
}
|
||||||
|
timelines.add(timeline);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SLOT_ALPHA: {
|
||||||
|
int bezierCount = readVarint(input, true);
|
||||||
|
AlphaTimeline *timeline = new(__FILE__, __LINE__) AlphaTimeline(frameCount, bezierCount, slotIndex);
|
||||||
|
float time = readFloat(input);
|
||||||
|
float a = readByte(input) / 255.0;
|
||||||
|
for (int frame = 0, bezier = 0;; frame++) {
|
||||||
|
timeline->setFrame(frame, time, a);
|
||||||
|
if (frame == frameLast) break;
|
||||||
|
float time2 = readFloat(input);
|
||||||
|
float a2 = readByte(input) / 255;
|
||||||
|
switch (readSByte(input)) {
|
||||||
|
case CURVE_STEPPED:
|
||||||
|
timeline->setStepped(frame);
|
||||||
|
break;
|
||||||
|
case CURVE_BEZIER:
|
||||||
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1);
|
||||||
|
}
|
||||||
|
time = time2;
|
||||||
|
a = a2;
|
||||||
|
}
|
||||||
|
timelines.add(timeline);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
ContainerUtil::cleanUpVectorOfPointers(timelines);
|
ContainerUtil::cleanUpVectorOfPointers(timelines);
|
||||||
setError("Invalid timeline type for a slot: ", skeletonData->_slots[slotIndex]->_name.buffer());
|
setError("Invalid timeline type for a slot: ", skeletonData->_slots[slotIndex]->_name.buffer());
|
||||||
@ -778,144 +971,186 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|||||||
for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) {
|
for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) {
|
||||||
unsigned char timelineType = readByte(input);
|
unsigned char timelineType = readByte(input);
|
||||||
int frameCount = readVarint(input, true);
|
int frameCount = readVarint(input, true);
|
||||||
|
int bezierCount = readVarint(input, true);
|
||||||
|
Timeline *timeline = NULL;
|
||||||
switch (timelineType) {
|
switch (timelineType) {
|
||||||
case BONE_ROTATE: {
|
case BONE_ROTATE:
|
||||||
RotateTimeline *timeline = new(__FILE__, __LINE__) RotateTimeline(frameCount);
|
timeline = readTimeline(input, new(__FILE__, __LINE__) RotateTimeline(frameCount, bezierCount, boneIndex), 1);
|
||||||
timeline->_boneIndex = boneIndex;
|
break;
|
||||||
for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
case BONE_TRANSLATE:
|
||||||
float time = readFloat(input);
|
timeline = readTimeline2(input, new(__FILE__, __LINE__) TranslateTimeline(frameCount, bezierCount, boneIndex), scale);
|
||||||
float degrees = readFloat(input);
|
break;
|
||||||
timeline->setFrame(frameIndex, time, degrees);
|
case BONE_TRANSLATEX:
|
||||||
if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
timeline = readTimeline(input, new(__FILE__, __LINE__) TranslateXTimeline(frameCount, bezierCount, boneIndex), scale);
|
||||||
}
|
break;
|
||||||
timelines.add(timeline);
|
case BONE_TRANSLATEY:
|
||||||
duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * RotateTimeline::ENTRIES]);
|
timeline = readTimeline(input, new(__FILE__, __LINE__) TranslateYTimeline(frameCount, bezierCount, boneIndex), scale);
|
||||||
break;
|
break;
|
||||||
}
|
case BONE_SCALE:
|
||||||
case BONE_TRANSLATE:
|
timeline = readTimeline2(input, new(__FILE__, __LINE__) ScaleTimeline(frameCount, bezierCount, boneIndex), 1);
|
||||||
case BONE_SCALE:
|
break;
|
||||||
case BONE_SHEAR: {
|
case BONE_SCALEX:
|
||||||
TranslateTimeline *timeline;
|
timeline = readTimeline(input, new(__FILE__, __LINE__) ScaleXTimeline(frameCount, bezierCount, boneIndex), 1);
|
||||||
float timelineScale = 1;
|
break;
|
||||||
if (timelineType == BONE_SCALE) {
|
case BONE_SCALEY:
|
||||||
timeline = new(__FILE__, __LINE__) ScaleTimeline(frameCount);
|
timeline = readTimeline(input, new(__FILE__, __LINE__) ScaleYTimeline(frameCount, bezierCount, boneIndex), 1);
|
||||||
} else if (timelineType == BONE_SHEAR) {
|
break;
|
||||||
timeline = new(__FILE__, __LINE__) ShearTimeline(frameCount);
|
case BONE_SHEAR:
|
||||||
} else {
|
timeline = readTimeline2(input, new(__FILE__, __LINE__) ShearTimeline(frameCount, bezierCount, boneIndex), 1);
|
||||||
timeline = new(__FILE__, __LINE__) TranslateTimeline(frameCount);
|
break;
|
||||||
timelineScale = scale;
|
case BONE_SHEARX:
|
||||||
}
|
timeline = readTimeline(input, new(__FILE__, __LINE__) ShearXTimeline(frameCount, bezierCount, boneIndex), 1);
|
||||||
timeline->_boneIndex = boneIndex;
|
break;
|
||||||
for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
case BONE_SHEARY:
|
||||||
float time = readFloat(input);
|
timeline = readTimeline(input, new(__FILE__, __LINE__) ShearYTimeline(frameCount, bezierCount, boneIndex), 1);
|
||||||
float x = readFloat(input) * timelineScale;
|
break;
|
||||||
float y = readFloat(input) * timelineScale;
|
|
||||||
timeline->setFrame(frameIndex, time, x, y);
|
|
||||||
if (frameIndex < frameCount - 1) {
|
|
||||||
readCurve(input, frameIndex, timeline);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timelines.add(timeline);
|
|
||||||
duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * TranslateTimeline::ENTRIES]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
default: {
|
||||||
ContainerUtil::cleanUpVectorOfPointers(timelines);
|
ContainerUtil::cleanUpVectorOfPointers(timelines);
|
||||||
setError("Invalid timeline type for a bone: ", skeletonData->_bones[boneIndex]->_name.buffer());
|
setError("Invalid timeline type for a bone: ", skeletonData->_bones[boneIndex]->_name.buffer());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
timelines.add(timeline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IK timelines.
|
// IK timelines.
|
||||||
for (int i = 0, n = readVarint(input, true); i < n; ++i) {
|
for (int i = 0, n = readVarint(input, true); i < n; ++i) {
|
||||||
int index = readVarint(input, true);
|
int index = readVarint(input, true);
|
||||||
int frameCount = readVarint(input, true);
|
int frameCount = readVarint(input, true);
|
||||||
IkConstraintTimeline *timeline = new(__FILE__, __LINE__) IkConstraintTimeline(frameCount);
|
int frameLast = frameCount - 1;
|
||||||
timeline->_ikConstraintIndex = index;
|
int bezierCount = readVarint(input, true);
|
||||||
for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
IkConstraintTimeline *timeline = new (__FILE__, __LINE__) IkConstraintTimeline(frameCount, bezierCount, index);
|
||||||
float time = readFloat(input);
|
float time = readFloat(input);
|
||||||
float mix = readFloat(input);
|
float mix = readFloat(input);
|
||||||
float softness = readFloat(input) * _scale;
|
float softness = readFloat(input) * scale;
|
||||||
signed char bendDirection = readSByte(input);
|
for (int frame = 0, bezier = 0;; frame++) {
|
||||||
bool compress = readBoolean(input);
|
int bendDirection = readSByte(input);
|
||||||
bool stretch = readBoolean(input);
|
bool compress = readBoolean(input);
|
||||||
timeline->setFrame(frameIndex, time, mix, softness, bendDirection, compress, stretch);
|
bool stretch = readBoolean(input);
|
||||||
if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
timeline->setFrame(frame, time, mix, softness, bendDirection, compress, stretch);
|
||||||
}
|
if (frame == frameLast) break;
|
||||||
|
float time2 = readFloat(input);
|
||||||
|
float mix2 = readFloat(input);
|
||||||
|
float softness2 = readFloat(input) * scale;
|
||||||
|
switch (readSByte(input)) {
|
||||||
|
case CURVE_STEPPED:
|
||||||
|
timeline->setStepped(frame);
|
||||||
|
break;
|
||||||
|
case CURVE_BEZIER:
|
||||||
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale);
|
||||||
|
}
|
||||||
|
time = time2;
|
||||||
|
mix = mix2;
|
||||||
|
softness = softness2;
|
||||||
|
}
|
||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * IkConstraintTimeline::ENTRIES]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform constraint timelines.
|
// Transform constraint timelines.
|
||||||
for (int i = 0, n = readVarint(input, true); i < n; ++i) {
|
for (int i = 0, n = readVarint(input, true); i < n; ++i) {
|
||||||
int index = readVarint(input, true);
|
int index = readVarint(input, true);
|
||||||
int frameCount = readVarint(input, true);
|
int frameCount = readVarint(input, true);
|
||||||
TransformConstraintTimeline *timeline = new(__FILE__, __LINE__) TransformConstraintTimeline(frameCount);
|
int frameLast = frameCount - 1;
|
||||||
timeline->_transformConstraintIndex = index;
|
int bezierCount = readVarint(input, true);
|
||||||
for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
TransformConstraintTimeline *timeline = new TransformConstraintTimeline(frameCount, bezierCount, index);
|
||||||
float time = readFloat(input);
|
float time = readFloat(input);
|
||||||
float rotateMix = readFloat(input);
|
float mixRotate = readFloat(input);
|
||||||
float translateMix = readFloat(input);
|
float mixX = readFloat(input);
|
||||||
float scaleMix = readFloat(input);
|
float mixY = readFloat(input);
|
||||||
float shearMix = readFloat(input);
|
float mixScaleX = readFloat(input);
|
||||||
timeline->setFrame(frameIndex, time, rotateMix, translateMix, scaleMix, shearMix);
|
float mixScaleY = readFloat(input);
|
||||||
if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
float mixShearY = readFloat(input);
|
||||||
}
|
for (int frame = 0, bezier = 0;; frame++) {
|
||||||
|
timeline->setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY);
|
||||||
|
if (frame == frameLast) break;
|
||||||
|
float time2 = readFloat(input);
|
||||||
|
float mixRotate2 = readFloat(input);
|
||||||
|
float mixX2 = readFloat(input);
|
||||||
|
float mixY2 = readFloat(input);
|
||||||
|
float mixScaleX2 = readFloat(input);
|
||||||
|
float mixScaleY2 = readFloat(input);
|
||||||
|
float mixShearY2 = readFloat(input);
|
||||||
|
switch (readSByte(input)) {
|
||||||
|
case CURVE_STEPPED:
|
||||||
|
timeline->setStepped(frame);
|
||||||
|
break;
|
||||||
|
case CURVE_BEZIER:
|
||||||
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1);
|
||||||
|
}
|
||||||
|
time = time2;
|
||||||
|
mixRotate = mixRotate2;
|
||||||
|
mixX = mixX2;
|
||||||
|
mixY = mixY2;
|
||||||
|
mixScaleX = mixScaleX2;
|
||||||
|
mixScaleY = mixScaleY2;
|
||||||
|
mixShearY = mixShearY2;
|
||||||
|
}
|
||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * TransformConstraintTimeline::ENTRIES]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path constraint timelines.
|
// Path constraint timelines.
|
||||||
for (int i = 0, n = readVarint(input, true); i < n; ++i) {
|
for (int i = 0, n = readVarint(input, true); i < n; ++i) {
|
||||||
int index = readVarint(input, true);
|
int index = readVarint(input, true);
|
||||||
PathConstraintData *data = skeletonData->_pathConstraints[index];
|
PathConstraintData *data = skeletonData->_pathConstraints[index];
|
||||||
for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) {
|
for (int ii = 0, nn = readVarint(input, true); ii < nn; ii++) {
|
||||||
int timelineType = readSByte(input);
|
int type = readSByte(input);
|
||||||
int frameCount = readVarint(input, true);
|
int frameCount = readVarint(input, true);
|
||||||
switch (timelineType) {
|
int bezierCount = readVarint(input, true);
|
||||||
case PATH_POSITION:
|
switch (type) {
|
||||||
case PATH_SPACING: {
|
case PATH_POSITION: {
|
||||||
PathConstraintPositionTimeline *timeline;
|
timelines
|
||||||
float timelineScale = 1;
|
.add(readTimeline(input, new PathConstraintPositionTimeline(frameCount, bezierCount, index),
|
||||||
if (timelineType == PATH_SPACING) {
|
data->_positionMode == PositionMode_Fixed ? scale : 1));
|
||||||
timeline = new(__FILE__, __LINE__) PathConstraintSpacingTimeline(frameCount);
|
break;
|
||||||
|
}
|
||||||
|
case PATH_SPACING: {
|
||||||
|
timelines
|
||||||
|
.add(readTimeline(input,
|
||||||
|
new PathConstraintSpacingTimeline(frameCount,
|
||||||
|
bezierCount,
|
||||||
|
index),
|
||||||
|
data->_spacingMode == SpacingMode_Length ||
|
||||||
|
data->_spacingMode == SpacingMode_Fixed ? scale : 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PATH_MIX:
|
||||||
|
PathConstraintMixTimeline *timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index);
|
||||||
|
float time = readFloat(input);
|
||||||
|
float mixRotate = readFloat(input);
|
||||||
|
float mixX = readFloat(input);
|
||||||
|
float mixY = readFloat(input);
|
||||||
|
for (int frame = 0, bezier = 0, frameLast = timeline->getFrameCount() - 1;; frame++) {
|
||||||
|
timeline->setFrame(frame, time, mixRotate, mixX, mixY);
|
||||||
|
if (frame == frameLast) break;
|
||||||
|
float time2 = readFloat(input);
|
||||||
|
float mixRotate2 = readFloat(input);
|
||||||
|
float mixX2 = readFloat(input);
|
||||||
|
float mixY2 = readFloat(input);
|
||||||
|
switch (readSByte(input)) {
|
||||||
|
case CURVE_STEPPED:
|
||||||
|
timeline->setStepped(frame);
|
||||||
|
break;
|
||||||
|
case CURVE_BEZIER:
|
||||||
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1);
|
||||||
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1);
|
||||||
|
|
||||||
if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) timelineScale = scale;
|
}
|
||||||
} else {
|
time = time2;
|
||||||
timeline = new(__FILE__, __LINE__) PathConstraintPositionTimeline(frameCount);
|
mixRotate = mixRotate2;
|
||||||
|
mixX = mixX2;
|
||||||
if (data->_positionMode == PositionMode_Fixed) timelineScale = scale;
|
mixY = mixY2;
|
||||||
}
|
}
|
||||||
timeline->_pathConstraintIndex = index;
|
timelines.add(timeline);
|
||||||
for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
}
|
||||||
float time = readFloat(input);
|
}
|
||||||
float value = readFloat(input) * timelineScale;
|
|
||||||
timeline->setFrame(frameIndex, time, value);
|
|
||||||
if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
|
||||||
}
|
|
||||||
timelines.add(timeline);
|
|
||||||
duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * PathConstraintPositionTimeline::ENTRIES]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PATH_MIX: {
|
|
||||||
PathConstraintMixTimeline *timeline = new(__FILE__, __LINE__) PathConstraintMixTimeline(frameCount);
|
|
||||||
|
|
||||||
timeline->_pathConstraintIndex = index;
|
|
||||||
for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
|
||||||
float time = readFloat(input);
|
|
||||||
float rotateMix = readFloat(input);
|
|
||||||
float translateMix = readFloat(input);
|
|
||||||
timeline->setFrame(frameIndex, time, rotateMix, translateMix);
|
|
||||||
if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
|
||||||
}
|
|
||||||
timelines.add(timeline);
|
|
||||||
duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * PathConstraintMixTimeline::ENTRIES]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deform timelines.
|
// Deform timelines.
|
||||||
@ -937,22 +1172,21 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|||||||
|
|
||||||
bool weighted = attachment->_bones.size() > 0;
|
bool weighted = attachment->_bones.size() > 0;
|
||||||
Vector<float> &vertices = attachment->_vertices;
|
Vector<float> &vertices = attachment->_vertices;
|
||||||
size_t deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size();
|
int deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size();
|
||||||
|
|
||||||
size_t frameCount = (size_t)readVarint(input, true);
|
int frameCount = readVarint(input, true);
|
||||||
|
int frameLast = frameCount -1;
|
||||||
|
int bezierCount = readVarint(input, true);
|
||||||
|
DeformTimeline *timeline = new(__FILE__, __LINE__) DeformTimeline(frameCount, bezierCount, slotIndex, attachment);
|
||||||
|
|
||||||
DeformTimeline *timeline = new(__FILE__, __LINE__) DeformTimeline(frameCount);
|
float time = readFloat(input);
|
||||||
timeline->_slotIndex = slotIndex;
|
for (int frame = 0, bezier = 0;; ++frame) {
|
||||||
timeline->_attachment = attachment;
|
|
||||||
|
|
||||||
for (size_t frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
|
||||||
float time = readFloat(input);
|
|
||||||
Vector<float> deform;
|
Vector<float> deform;
|
||||||
size_t end = (size_t)readVarint(input, true);
|
size_t end = (size_t)readVarint(input, true);
|
||||||
if (end == 0) {
|
if (end == 0) {
|
||||||
if (weighted) {
|
if (weighted) {
|
||||||
deform.setSize(deformLength, 0);
|
deform.setSize(deformLength, 0);
|
||||||
for (size_t iiii = 0; iiii < deformLength; ++iiii)
|
for (int iiii = 0; iiii < deformLength; ++iiii)
|
||||||
deform[iiii] = 0;
|
deform[iiii] = 0;
|
||||||
} else {
|
} else {
|
||||||
deform.clearAndAddAll(vertices);
|
deform.clearAndAddAll(vertices);
|
||||||
@ -975,12 +1209,20 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
timeline->setFrame(frameIndex, time, deform);
|
timeline->setFrame(frame, time, deform);
|
||||||
if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
if (frame == frameLast) break;
|
||||||
|
float time2 = readFloat(input);
|
||||||
|
switch(readSByte(input)) {
|
||||||
|
case CURVE_STEPPED:
|
||||||
|
timeline->setStepped(frame);
|
||||||
|
break;
|
||||||
|
case CURVE_BEZIER:
|
||||||
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1);
|
||||||
|
}
|
||||||
|
time = time2;
|
||||||
}
|
}
|
||||||
|
|
||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
duration = MathUtil::max(duration, timeline->_frames[frameCount - 1]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1024,7 +1266,6 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|||||||
timeline->setFrame(i, time, drawOrder);
|
timeline->setFrame(i, time, drawOrder);
|
||||||
}
|
}
|
||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
duration = MathUtil::max(duration, timeline->_frames[drawOrderCount - 1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event timeline.
|
// Event timeline.
|
||||||
@ -1050,27 +1291,12 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|||||||
}
|
}
|
||||||
timeline->setFrame(i, event);
|
timeline->setFrame(i, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
duration = MathUtil::max(duration, timeline->_frames[eventCount - 1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float duration = 0;
|
||||||
|
for (int i = 0, n = timelines.size(); i < n; i++) {
|
||||||
|
duration = MathUtil::max(duration, (timelines[i])->getDuration());
|
||||||
|
}
|
||||||
return new(__FILE__, __LINE__) Animation(String(name), timelines, duration);
|
return new(__FILE__, __LINE__) Animation(String(name), timelines, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonBinary::readCurve(DataInput *input, int frameIndex, CurveTimeline *timeline) {
|
|
||||||
switch (readByte(input)) {
|
|
||||||
case CURVE_STEPPED: {
|
|
||||||
timeline->setStepped(frameIndex);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CURVE_BEZIER: {
|
|
||||||
float cx1 = readFloat(input);
|
|
||||||
float cy1 = readFloat(input);
|
|
||||||
float cx2 = readFloat(input);
|
|
||||||
float cy2 = readFloat(input);
|
|
||||||
timeline->setCurve(frameIndex, cx1, cy1, cx2, cy2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -58,7 +58,6 @@
|
|||||||
#include <spine/EventData.h>
|
#include <spine/EventData.h>
|
||||||
#include <spine/AttachmentTimeline.h>
|
#include <spine/AttachmentTimeline.h>
|
||||||
#include <spine/ColorTimeline.h>
|
#include <spine/ColorTimeline.h>
|
||||||
#include <spine/TwoColorTimeline.h>
|
|
||||||
#include <spine/RotateTimeline.h>
|
#include <spine/RotateTimeline.h>
|
||||||
#include <spine/TranslateTimeline.h>
|
#include <spine/TranslateTimeline.h>
|
||||||
#include <spine/ScaleTimeline.h>
|
#include <spine/ScaleTimeline.h>
|
||||||
|
|||||||
@ -1,182 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Spine Runtimes License Agreement
|
|
||||||
* Last updated January 1, 2020. Replaces all prior versions.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013-2020, Esoteric Software LLC
|
|
||||||
*
|
|
||||||
* Integration of the Spine Runtimes into software or otherwise creating
|
|
||||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
|
||||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
|
||||||
* http://esotericsoftware.com/spine-editor-license
|
|
||||||
*
|
|
||||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
|
||||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
|
||||||
* "Products"), provided that each user of the Products must obtain their own
|
|
||||||
* Spine Editor license and redistribution of the Products in any form must
|
|
||||||
* include this license and copyright notice.
|
|
||||||
*
|
|
||||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
|
||||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef SPINE_UE4
|
|
||||||
#include "SpinePluginPrivatePCH.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <spine/TwoColorTimeline.h>
|
|
||||||
|
|
||||||
#include <spine/Skeleton.h>
|
|
||||||
#include <spine/Event.h>
|
|
||||||
|
|
||||||
#include <spine/Animation.h>
|
|
||||||
#include <spine/Bone.h>
|
|
||||||
#include <spine/Property.h>
|
|
||||||
#include <spine/Slot.h>
|
|
||||||
#include <spine/SlotData.h>
|
|
||||||
|
|
||||||
using namespace spine;
|
|
||||||
|
|
||||||
RTTI_IMPL(TwoColorTimeline, CurveTimeline)
|
|
||||||
|
|
||||||
const int TwoColorTimeline::ENTRIES = 8;
|
|
||||||
const int TwoColorTimeline::PREV_TIME = -8;
|
|
||||||
const int TwoColorTimeline::PREV_R = -7;
|
|
||||||
const int TwoColorTimeline::PREV_G = -6;
|
|
||||||
const int TwoColorTimeline::PREV_B = -5;
|
|
||||||
const int TwoColorTimeline::PREV_A = -4;
|
|
||||||
const int TwoColorTimeline::PREV_R2 = -3;
|
|
||||||
const int TwoColorTimeline::PREV_G2 = -2;
|
|
||||||
const int TwoColorTimeline::PREV_B2 = -1;
|
|
||||||
const int TwoColorTimeline::R = 1;
|
|
||||||
const int TwoColorTimeline::G = 2;
|
|
||||||
const int TwoColorTimeline::B = 3;
|
|
||||||
const int TwoColorTimeline::A = 4;
|
|
||||||
const int TwoColorTimeline::R2 = 5;
|
|
||||||
const int TwoColorTimeline::G2 = 6;
|
|
||||||
const int TwoColorTimeline::B2 = 7;
|
|
||||||
|
|
||||||
TwoColorTimeline::TwoColorTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0) {
|
|
||||||
_frames.ensureCapacity(frameCount * ENTRIES);
|
|
||||||
_frames.setSize(frameCount * ENTRIES, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TwoColorTimeline::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);
|
|
||||||
|
|
||||||
Slot *slotP = skeleton._slots[_slotIndex];
|
|
||||||
Slot &slot = *slotP;
|
|
||||||
if (!slot._bone.isActive()) return;
|
|
||||||
|
|
||||||
if (time < _frames[0]) {
|
|
||||||
// Time is before first frame.
|
|
||||||
switch (blend) {
|
|
||||||
case MixBlend_Setup:
|
|
||||||
slot.getColor().set(slot.getData().getColor());
|
|
||||||
slot.getDarkColor().set(slot.getData().getDarkColor());
|
|
||||||
return;
|
|
||||||
case MixBlend_First: {
|
|
||||||
Color &color = slot.getColor();
|
|
||||||
color.r += (color.r - slot._data.getColor().r) * alpha;
|
|
||||||
color.g += (color.g - slot._data.getColor().g) * alpha;
|
|
||||||
color.b += (color.b - slot._data.getColor().b) * alpha;
|
|
||||||
color.a += (color.a - slot._data.getColor().a) * alpha;
|
|
||||||
|
|
||||||
Color &darkColor = slot.getDarkColor();
|
|
||||||
darkColor.r += (darkColor.r - slot._data.getDarkColor().r) * alpha;
|
|
||||||
darkColor.g += (darkColor.g - slot._data.getDarkColor().g) * alpha;
|
|
||||||
darkColor.b += (darkColor.b - slot._data.getDarkColor().b) * alpha;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float r, g, b, a, r2, g2, b2;
|
|
||||||
if (time >= _frames[_frames.size() - ENTRIES]) {
|
|
||||||
// Time is after last frame.
|
|
||||||
size_t i = _frames.size();
|
|
||||||
r = _frames[i + PREV_R];
|
|
||||||
g = _frames[i + PREV_G];
|
|
||||||
b = _frames[i + PREV_B];
|
|
||||||
a = _frames[i + PREV_A];
|
|
||||||
r2 = _frames[i + PREV_R2];
|
|
||||||
g2 = _frames[i + PREV_G2];
|
|
||||||
b2 = _frames[i + PREV_B2];
|
|
||||||
} else {
|
|
||||||
// Interpolate between the previous frame and the current frame.
|
|
||||||
size_t frame = (size_t)Animation::binarySearch(_frames, time, ENTRIES);
|
|
||||||
r = _frames[frame + PREV_R];
|
|
||||||
g = _frames[frame + PREV_G];
|
|
||||||
b = _frames[frame + PREV_B];
|
|
||||||
a = _frames[frame + PREV_A];
|
|
||||||
r2 = _frames[frame + PREV_R2];
|
|
||||||
g2 = _frames[frame + PREV_G2];
|
|
||||||
b2 = _frames[frame + PREV_B2];
|
|
||||||
float frameTime = _frames[frame];
|
|
||||||
float percent = getCurvePercent(frame / ENTRIES - 1,
|
|
||||||
1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime));
|
|
||||||
|
|
||||||
r += (_frames[frame + R] - r) * percent;
|
|
||||||
g += (_frames[frame + G] - g) * percent;
|
|
||||||
b += (_frames[frame + B] - b) * percent;
|
|
||||||
a += (_frames[frame + A] - a) * percent;
|
|
||||||
r2 += (_frames[frame + R2] - r2) * percent;
|
|
||||||
g2 += (_frames[frame + G2] - g2) * percent;
|
|
||||||
b2 += (_frames[frame + B2] - b2) * percent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (alpha == 1) {
|
|
||||||
Color &color = slot.getColor();
|
|
||||||
color.set(r, g, b, a);
|
|
||||||
|
|
||||||
Color &darkColor = slot.getDarkColor();
|
|
||||||
darkColor.set(r2, g2, b2, 1);
|
|
||||||
} else {
|
|
||||||
Color &light = slot._color;
|
|
||||||
Color &dark = slot._darkColor;
|
|
||||||
if (blend == MixBlend_Setup) {
|
|
||||||
light.set(slot._data._color);
|
|
||||||
dark.set(slot._data._darkColor);
|
|
||||||
}
|
|
||||||
light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha);
|
|
||||||
dark.add((r2 - dark.r) * alpha, (g2 - dark.g) * alpha, (b2 - dark.b) * alpha, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int TwoColorTimeline::getPropertyId() {
|
|
||||||
return ((int) TimelineType_TwoColor << 24) + _slotIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TwoColorTimeline::setFrame(int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) {
|
|
||||||
frameIndex *= ENTRIES;
|
|
||||||
_frames[frameIndex] = time;
|
|
||||||
_frames[frameIndex + R] = r;
|
|
||||||
_frames[frameIndex + G] = g;
|
|
||||||
_frames[frameIndex + B] = b;
|
|
||||||
_frames[frameIndex + A] = a;
|
|
||||||
_frames[frameIndex + R2] = r2;
|
|
||||||
_frames[frameIndex + G2] = g2;
|
|
||||||
_frames[frameIndex + B2] = b2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int TwoColorTimeline::getSlotIndex() {
|
|
||||||
return _slotIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TwoColorTimeline::setSlotIndex(int inValue) {
|
|
||||||
assert(inValue >= 0);
|
|
||||||
_slotIndex = inValue;
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user