|
@@ -59,7 +59,6 @@
|
|
|
#include <spine/EventData.h>
|
|
|
#include <spine/AttachmentTimeline.h>
|
|
|
#include <spine/ColorTimeline.h>
|
|
|
-#include <spine/TwoColorTimeline.h>
|
|
|
#include <spine/RotateTimeline.h>
|
|
|
#include <spine/TranslateTimeline.h>
|
|
|
#include <spine/ScaleTimeline.h>
|
|
@@ -76,23 +75,6 @@
|
|
|
|
|
|
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(
|
|
|
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();
|
|
|
|
|
|
- char *skeletonData_hash = readString(input);
|
|
|
- skeletonData->_hash.own(skeletonData_hash);
|
|
|
+ char buffer[8] = { 0 };
|
|
|
+ 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);
|
|
|
- skeletonData->_version.own(skeletonData_version);
|
|
|
- if ("3.8.75" == skeletonData->_version) {
|
|
|
- delete input;
|
|
|
- delete skeletonData;
|
|
|
- setError("Unsupported skeleton data, please export with a newer version of Spine.", "");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
+ char *skeletonDataVersion = readString(input);
|
|
|
+ skeletonData->_version.own(skeletonDataVersion);
|
|
|
|
|
|
skeletonData->_x = readFloat(input);
|
|
|
skeletonData->_y = readFloat(input);
|
|
@@ -239,10 +222,12 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|
|
data->_offsetScaleX = readFloat(input);
|
|
|
data->_offsetScaleY = readFloat(input);
|
|
|
data->_offsetShearY = readFloat(input);
|
|
|
- data->_rotateMix = readFloat(input);
|
|
|
- data->_translateMix = readFloat(input);
|
|
|
- data->_scaleMix = readFloat(input);
|
|
|
- data->_shearMix = readFloat(input);
|
|
|
+ data->_mixRotate = readFloat(input);
|
|
|
+ data->_mixX = readFloat(input);
|
|
|
+ data->_mixY = readFloat(input);
|
|
|
+ data->_mixScaleX = readFloat(input);
|
|
|
+ data->_mixScaleY = readFloat(input);
|
|
|
+ data->_mixShearY = readFloat(input);
|
|
|
skeletonData->_transformConstraints[i] = data;
|
|
|
}
|
|
|
|
|
@@ -268,8 +253,9 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
|
|
data->_spacing = readFloat(input);
|
|
|
if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed)
|
|
|
data->_spacing *= _scale;
|
|
|
- data->_rotateMix = readFloat(input);
|
|
|
- data->_translateMix = readFloat(input);
|
|
|
+ data->_mixRotate = readFloat(input);
|
|
|
+ data->_mixX = readFloat(input);
|
|
|
+ data->_mixY = readFloat(input);
|
|
|
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) {
|
|
|
Vector<Timeline *> timelines;
|
|
|
float scale = _scale;
|
|
|
- float duration = 0;
|
|
|
-
|
|
|
+ int numTimelines = readVarint(input, true);
|
|
|
// 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);
|
|
|
for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) {
|
|
|
unsigned char timelineType = readByte(input);
|
|
|
int frameCount = readVarint(input, true);
|
|
|
+ int frameLast = frameCount - 1;
|
|
|
switch (timelineType) {
|
|
|
case SLOT_ATTACHMENT: {
|
|
|
- AttachmentTimeline *timeline = new(__FILE__, __LINE__) AttachmentTimeline(frameCount);
|
|
|
- timeline->_slotIndex = slotIndex;
|
|
|
- for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
|
|
+ AttachmentTimeline *timeline = new(__FILE__, __LINE__) AttachmentTimeline(frameCount, slotIndex);
|
|
|
+ for (int frame = 0; frame < frameCount; ++frame) {
|
|
|
float time = readFloat(input);
|
|
|
String attachmentName(readStringRef(input, skeletonData));
|
|
|
- timeline->setFrame(frameIndex, time, attachmentName);
|
|
|
- }
|
|
|
- timelines.add(timeline);
|
|
|
- duration = MathUtil::max(duration, timeline->_frames[frameCount - 1]);
|
|
|
- break;
|
|
|
- }
|
|
|
- case SLOT_COLOR: {
|
|
|
- ColorTimeline *timeline = new(__FILE__, __LINE__) ColorTimeline(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;
|
|
|
- timeline->setFrame(frameIndex, time, r, g, b, a);
|
|
|
- if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
|
|
+ timeline->setFrame(frame, time, attachmentName);
|
|
|
}
|
|
|
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);
|
|
|
- if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
|
|
- }
|
|
|
- timelines.add(timeline);
|
|
|
- duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * TwoColorTimeline::ENTRIES]);
|
|
|
- break;
|
|
|
+ case SLOT_RGBA: {
|
|
|
+ int bezierCount = readVarint(input, true);
|
|
|
+ RGBATimeline *timeline = new(__FILE__, __LINE__) RGBATimeline(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;
|
|
|
+
|
|
|
+ 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: {
|
|
|
ContainerUtil::cleanUpVectorOfPointers(timelines);
|
|
|
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) {
|
|
|
unsigned char timelineType = readByte(input);
|
|
|
int frameCount = readVarint(input, true);
|
|
|
+ int bezierCount = readVarint(input, true);
|
|
|
+ Timeline *timeline = NULL;
|
|
|
switch (timelineType) {
|
|
|
- case BONE_ROTATE: {
|
|
|
- RotateTimeline *timeline = new(__FILE__, __LINE__) RotateTimeline(frameCount);
|
|
|
- timeline->_boneIndex = boneIndex;
|
|
|
- for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
|
|
- float time = readFloat(input);
|
|
|
- float degrees = readFloat(input);
|
|
|
- timeline->setFrame(frameIndex, time, degrees);
|
|
|
- if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
|
|
- }
|
|
|
- timelines.add(timeline);
|
|
|
- duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * RotateTimeline::ENTRIES]);
|
|
|
- break;
|
|
|
- }
|
|
|
- case BONE_TRANSLATE:
|
|
|
- case BONE_SCALE:
|
|
|
- case BONE_SHEAR: {
|
|
|
- TranslateTimeline *timeline;
|
|
|
- float timelineScale = 1;
|
|
|
- if (timelineType == BONE_SCALE) {
|
|
|
- timeline = new(__FILE__, __LINE__) ScaleTimeline(frameCount);
|
|
|
- } else if (timelineType == BONE_SHEAR) {
|
|
|
- timeline = new(__FILE__, __LINE__) ShearTimeline(frameCount);
|
|
|
- } else {
|
|
|
- timeline = new(__FILE__, __LINE__) TranslateTimeline(frameCount);
|
|
|
- timelineScale = scale;
|
|
|
- }
|
|
|
- timeline->_boneIndex = boneIndex;
|
|
|
- for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
|
|
- float time = readFloat(input);
|
|
|
- float x = readFloat(input) * timelineScale;
|
|
|
- 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;
|
|
|
- }
|
|
|
+ case BONE_ROTATE:
|
|
|
+ timeline = readTimeline(input, new(__FILE__, __LINE__) RotateTimeline(frameCount, bezierCount, boneIndex), 1);
|
|
|
+ break;
|
|
|
+ case BONE_TRANSLATE:
|
|
|
+ timeline = readTimeline2(input, new(__FILE__, __LINE__) TranslateTimeline(frameCount, bezierCount, boneIndex), scale);
|
|
|
+ break;
|
|
|
+ case BONE_TRANSLATEX:
|
|
|
+ timeline = readTimeline(input, new(__FILE__, __LINE__) TranslateXTimeline(frameCount, bezierCount, boneIndex), scale);
|
|
|
+ break;
|
|
|
+ case BONE_TRANSLATEY:
|
|
|
+ timeline = readTimeline(input, new(__FILE__, __LINE__) TranslateYTimeline(frameCount, bezierCount, boneIndex), scale);
|
|
|
+ break;
|
|
|
+ case BONE_SCALE:
|
|
|
+ timeline = readTimeline2(input, new(__FILE__, __LINE__) ScaleTimeline(frameCount, bezierCount, boneIndex), 1);
|
|
|
+ break;
|
|
|
+ case BONE_SCALEX:
|
|
|
+ timeline = readTimeline(input, new(__FILE__, __LINE__) ScaleXTimeline(frameCount, bezierCount, boneIndex), 1);
|
|
|
+ break;
|
|
|
+ case BONE_SCALEY:
|
|
|
+ timeline = readTimeline(input, new(__FILE__, __LINE__) ScaleYTimeline(frameCount, bezierCount, boneIndex), 1);
|
|
|
+ break;
|
|
|
+ case BONE_SHEAR:
|
|
|
+ timeline = readTimeline2(input, new(__FILE__, __LINE__) ShearTimeline(frameCount, bezierCount, boneIndex), 1);
|
|
|
+ break;
|
|
|
+ case BONE_SHEARX:
|
|
|
+ timeline = readTimeline(input, new(__FILE__, __LINE__) ShearXTimeline(frameCount, bezierCount, boneIndex), 1);
|
|
|
+ break;
|
|
|
+ case BONE_SHEARY:
|
|
|
+ timeline = readTimeline(input, new(__FILE__, __LINE__) ShearYTimeline(frameCount, bezierCount, boneIndex), 1);
|
|
|
+ break;
|
|
|
default: {
|
|
|
ContainerUtil::cleanUpVectorOfPointers(timelines);
|
|
|
setError("Invalid timeline type for a bone: ", skeletonData->_bones[boneIndex]->_name.buffer());
|
|
|
return NULL;
|
|
|
}
|
|
|
}
|
|
|
+ timelines.add(timeline);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// IK timelines.
|
|
|
for (int i = 0, n = readVarint(input, true); i < n; ++i) {
|
|
|
- int index = readVarint(input, true);
|
|
|
- int frameCount = readVarint(input, true);
|
|
|
- IkConstraintTimeline *timeline = new(__FILE__, __LINE__) IkConstraintTimeline(frameCount);
|
|
|
- timeline->_ikConstraintIndex = index;
|
|
|
- for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
|
|
- float time = readFloat(input);
|
|
|
- float mix = readFloat(input);
|
|
|
- float softness = readFloat(input) * _scale;
|
|
|
- signed char bendDirection = readSByte(input);
|
|
|
- bool compress = readBoolean(input);
|
|
|
- bool stretch = readBoolean(input);
|
|
|
- timeline->setFrame(frameIndex, time, mix, softness, bendDirection, compress, stretch);
|
|
|
- if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
|
|
- }
|
|
|
+ int index = readVarint(input, true);
|
|
|
+ int frameCount = readVarint(input, true);
|
|
|
+ int frameLast = frameCount - 1;
|
|
|
+ int bezierCount = readVarint(input, true);
|
|
|
+ IkConstraintTimeline *timeline = new (__FILE__, __LINE__) IkConstraintTimeline(frameCount, bezierCount, index);
|
|
|
+ float time = readFloat(input);
|
|
|
+ float mix = readFloat(input);
|
|
|
+ float softness = readFloat(input) * scale;
|
|
|
+ for (int frame = 0, bezier = 0;; frame++) {
|
|
|
+ int bendDirection = readSByte(input);
|
|
|
+ bool compress = readBoolean(input);
|
|
|
+ bool stretch = readBoolean(input);
|
|
|
+ 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);
|
|
|
- duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * IkConstraintTimeline::ENTRIES]);
|
|
|
}
|
|
|
|
|
|
// Transform constraint timelines.
|
|
|
for (int i = 0, n = readVarint(input, true); i < n; ++i) {
|
|
|
- int index = readVarint(input, true);
|
|
|
- int frameCount = readVarint(input, true);
|
|
|
- TransformConstraintTimeline *timeline = new(__FILE__, __LINE__) TransformConstraintTimeline(frameCount);
|
|
|
- timeline->_transformConstraintIndex = index;
|
|
|
- for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
|
|
- float time = readFloat(input);
|
|
|
- float rotateMix = readFloat(input);
|
|
|
- float translateMix = readFloat(input);
|
|
|
- float scaleMix = readFloat(input);
|
|
|
- float shearMix = readFloat(input);
|
|
|
- timeline->setFrame(frameIndex, time, rotateMix, translateMix, scaleMix, shearMix);
|
|
|
- if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
|
|
- }
|
|
|
+ int index = readVarint(input, true);
|
|
|
+ int frameCount = readVarint(input, true);
|
|
|
+ int frameLast = frameCount - 1;
|
|
|
+ int bezierCount = readVarint(input, true);
|
|
|
+ TransformConstraintTimeline *timeline = new TransformConstraintTimeline(frameCount, bezierCount, index);
|
|
|
+ float time = readFloat(input);
|
|
|
+ float mixRotate = readFloat(input);
|
|
|
+ float mixX = readFloat(input);
|
|
|
+ float mixY = readFloat(input);
|
|
|
+ float mixScaleX = readFloat(input);
|
|
|
+ float mixScaleY = readFloat(input);
|
|
|
+ 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);
|
|
|
- duration = MathUtil::max(duration, timeline->_frames[(frameCount - 1) * TransformConstraintTimeline::ENTRIES]);
|
|
|
}
|
|
|
|
|
|
// Path constraint timelines.
|
|
|
for (int i = 0, n = readVarint(input, true); i < n; ++i) {
|
|
|
- int index = readVarint(input, true);
|
|
|
- PathConstraintData *data = skeletonData->_pathConstraints[index];
|
|
|
- for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) {
|
|
|
- int timelineType = readSByte(input);
|
|
|
- int frameCount = readVarint(input, true);
|
|
|
- switch (timelineType) {
|
|
|
- case PATH_POSITION:
|
|
|
- case PATH_SPACING: {
|
|
|
- PathConstraintPositionTimeline *timeline;
|
|
|
- float timelineScale = 1;
|
|
|
- if (timelineType == PATH_SPACING) {
|
|
|
- timeline = new(__FILE__, __LINE__) PathConstraintSpacingTimeline(frameCount);
|
|
|
-
|
|
|
- if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) timelineScale = scale;
|
|
|
- } else {
|
|
|
- timeline = new(__FILE__, __LINE__) PathConstraintPositionTimeline(frameCount);
|
|
|
-
|
|
|
- if (data->_positionMode == PositionMode_Fixed) timelineScale = scale;
|
|
|
- }
|
|
|
- timeline->_pathConstraintIndex = index;
|
|
|
- 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;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ int index = readVarint(input, true);
|
|
|
+ PathConstraintData *data = skeletonData->_pathConstraints[index];
|
|
|
+ for (int ii = 0, nn = readVarint(input, true); ii < nn; ii++) {
|
|
|
+ int type = readSByte(input);
|
|
|
+ int frameCount = readVarint(input, true);
|
|
|
+ int bezierCount = readVarint(input, true);
|
|
|
+ switch (type) {
|
|
|
+ case PATH_POSITION: {
|
|
|
+ timelines
|
|
|
+ .add(readTimeline(input, new PathConstraintPositionTimeline(frameCount, bezierCount, index),
|
|
|
+ data->_positionMode == PositionMode_Fixed ? scale : 1));
|
|
|
+ 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);
|
|
|
+
|
|
|
+ }
|
|
|
+ time = time2;
|
|
|
+ mixRotate = mixRotate2;
|
|
|
+ mixX = mixX2;
|
|
|
+ mixY = mixY2;
|
|
|
+ }
|
|
|
+ timelines.add(timeline);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// Deform timelines.
|
|
@@ -937,22 +1172,21 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|
|
|
|
|
bool weighted = attachment->_bones.size() > 0;
|
|
|
Vector<float> &vertices = attachment->_vertices;
|
|
|
- size_t deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size();
|
|
|
-
|
|
|
- size_t frameCount = (size_t)readVarint(input, true);
|
|
|
+ int deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size();
|
|
|
|
|
|
- DeformTimeline *timeline = new(__FILE__, __LINE__) DeformTimeline(frameCount);
|
|
|
- timeline->_slotIndex = slotIndex;
|
|
|
- timeline->_attachment = attachment;
|
|
|
+ int frameCount = readVarint(input, true);
|
|
|
+ int frameLast = frameCount -1;
|
|
|
+ int bezierCount = readVarint(input, true);
|
|
|
+ DeformTimeline *timeline = new(__FILE__, __LINE__) DeformTimeline(frameCount, bezierCount, slotIndex, attachment);
|
|
|
|
|
|
- for (size_t frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
|
|
- float time = readFloat(input);
|
|
|
+ float time = readFloat(input);
|
|
|
+ for (int frame = 0, bezier = 0;; ++frame) {
|
|
|
Vector<float> deform;
|
|
|
size_t end = (size_t)readVarint(input, true);
|
|
|
if (end == 0) {
|
|
|
if (weighted) {
|
|
|
deform.setSize(deformLength, 0);
|
|
|
- for (size_t iiii = 0; iiii < deformLength; ++iiii)
|
|
|
+ for (int iiii = 0; iiii < deformLength; ++iiii)
|
|
|
deform[iiii] = 0;
|
|
|
} else {
|
|
|
deform.clearAndAddAll(vertices);
|
|
@@ -975,12 +1209,20 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- timeline->setFrame(frameIndex, time, deform);
|
|
|
- if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline);
|
|
|
+ timeline->setFrame(frame, time, deform);
|
|
|
+ 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);
|
|
|
- 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);
|
|
|
}
|
|
|
timelines.add(timeline);
|
|
|
- duration = MathUtil::max(duration, timeline->_frames[drawOrderCount - 1]);
|
|
|
}
|
|
|
|
|
|
// Event timeline.
|
|
@@ -1050,27 +1291,12 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
|
|
}
|
|
|
timeline->setFrame(i, event);
|
|
|
}
|
|
|
-
|
|
|
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);
|
|
|
}
|
|
|
-
|
|
|
-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;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|