From 31b07f8625b2af21e2febba950ea99612b1ba0c2 Mon Sep 17 00:00:00 2001 From: NathanSweet Date: Fri, 22 Feb 2013 23:37:36 +0100 Subject: [PATCH] Clean up --- spine-cpp/data/spineboy-walk.json | 22 ++++++ spine-cpp/includes/spine/Animation.h | 3 +- .../includes/spine/BaseRegionAttachment.h | 2 + spine-cpp/includes/spine/BaseSkeletonJson.h | 1 + spine-cpp/includes/spine/BoneData.h | 8 +- spine-cpp/src/main.cpp | 5 +- spine-cpp/src/spine-sfml/Skeleton.cpp | 1 - spine-cpp/src/spine-sfml/SkeletonJson.cpp | 2 + spine-cpp/src/spine/Animation.cpp | 32 ++++---- spine-cpp/src/spine/BaseRegionAttachment.cpp | 10 +++ spine-cpp/src/spine/BaseSkeletonJson.cpp | 74 +++++++++++++++++-- spine-cpp/src/spine/Bone.cpp | 12 ++- spine-cpp/src/spine/Slot.cpp | 6 +- .../esotericsoftware/spine/SkeletonJson.java | 14 ++-- .../src/com/esotericsoftware/spine/Slot.java | 3 +- 15 files changed, 156 insertions(+), 39 deletions(-) diff --git a/spine-cpp/data/spineboy-walk.json b/spine-cpp/data/spineboy-walk.json index b40e53a95..efb640cbb 100644 --- a/spine-cpp/data/spineboy-walk.json +++ b/spine-cpp/data/spineboy-walk.json @@ -274,5 +274,27 @@ { "time": 1.0666, "angle": 3.6 } ] } +}, +"slots": { + "torso": { + "attachment": [ + { "time": 0.4333, "name": null }, + { "time": 0.8, "name": "torso" } + ] + }, + "head": { + "color": [ + { "time": 0.1666, "color": "ffffffff" }, + { "time": 0.9333, "color": "ff0f00c1" } + ] + }, + "eyes": { + "attachment": [ + { "time": 0.2, "name": "eyes-closed" }, + { "time": 0.3, "name": "eyes" }, + { "time": 0.7, "name": "eyes-closed" }, + { "time": 0.8333, "name": "eyes" } + ] + } } } \ No newline at end of file diff --git a/spine-cpp/includes/spine/Animation.h b/spine-cpp/includes/spine/Animation.h index d9ed84ea8..45ae979dc 100644 --- a/spine-cpp/includes/spine/Animation.h +++ b/spine-cpp/includes/spine/Animation.h @@ -133,7 +133,8 @@ public: virtual int getKeyframeCount (); virtual void apply (BaseSkeleton *skeleton, float time, float alpha); - void setKeyframe (int keyframeIndex, float time, std::string *attachmentName); + /** @param attachmentName Pass an empty string to clear the image for a slot. */ + void setKeyframe (int keyframeIndex, float time, const std::string &attachmentName); }; } /* namespace spine */ diff --git a/spine-cpp/includes/spine/BaseRegionAttachment.h b/spine-cpp/includes/spine/BaseRegionAttachment.h index 86d38c426..60fc83e75 100644 --- a/spine-cpp/includes/spine/BaseRegionAttachment.h +++ b/spine-cpp/includes/spine/BaseRegionAttachment.h @@ -13,6 +13,8 @@ public: float x, y, scaleX, scaleY, rotation, width, height; float offset[8]; + BaseRegionAttachment (); + void updateOffset (); virtual void updateWorldVertices (Bone *bone) = 0; diff --git a/spine-cpp/includes/spine/BaseSkeletonJson.h b/spine-cpp/includes/spine/BaseSkeletonJson.h index 242ab8f62..69b659df0 100644 --- a/spine-cpp/includes/spine/BaseSkeletonJson.h +++ b/spine-cpp/includes/spine/BaseSkeletonJson.h @@ -13,6 +13,7 @@ class BaseSkeletonJson { public: BaseAttachmentLoader *attachmentLoader; float scale; + bool flipY; BaseSkeletonJson (BaseAttachmentLoader *attachmentLoader); virtual ~BaseSkeletonJson (); diff --git a/spine-cpp/includes/spine/BoneData.h b/spine-cpp/includes/spine/BoneData.h index df271cdf5..cb9af13cc 100644 --- a/spine-cpp/includes/spine/BoneData.h +++ b/spine-cpp/includes/spine/BoneData.h @@ -13,12 +13,18 @@ public: float x, y; float rotation; float scaleX, scaleY; + float flipY; BoneData (const std::string &name) : name(name), parent(0), + length(0), + x(0), + y(0), + rotation(0), scaleX(1), - scaleY(1) { + scaleY(1), + flipY(false) { } }; diff --git a/spine-cpp/src/main.cpp b/spine-cpp/src/main.cpp index 1f28c5081..3b1524940 100644 --- a/spine-cpp/src/main.cpp +++ b/spine-cpp/src/main.cpp @@ -21,6 +21,8 @@ int main () { Animation *animation = skeletonJson.readAnimation(animationFile, skeletonData); Skeleton *skeleton = new Skeleton(skeletonData); + skeleton->flipX = false; + skeleton->flipY = false; skeleton->setToBindPose(); skeleton->getRootBone()->x = 200; skeleton->getRootBone()->y = 420; @@ -42,9 +44,6 @@ int main () { deltaClock.restart(); animationTime += delta; - skeleton->setToBindPose(); - skeleton->getRootBone()->x = 200; - skeleton->getRootBone()->y = 420; animation->apply(skeleton, animationTime, true); skeleton->updateWorldTransform(); } diff --git a/spine-cpp/src/spine-sfml/Skeleton.cpp b/spine-cpp/src/spine-sfml/Skeleton.cpp index bc5c3fbac..69be90e27 100644 --- a/spine-cpp/src/spine-sfml/Skeleton.cpp +++ b/spine-cpp/src/spine-sfml/Skeleton.cpp @@ -17,7 +17,6 @@ Skeleton::Skeleton (SkeletonData *skeletonData) : BaseSkeleton(skeletonData), vertexArray(Quads, skeletonData->bones.size() * 4), texture(0) { - flipY = true; // BOZO - Flip in loader for animation? } void Skeleton::draw (RenderTarget& target, RenderStates states) const { diff --git a/spine-cpp/src/spine-sfml/SkeletonJson.cpp b/spine-cpp/src/spine-sfml/SkeletonJson.cpp index fe040c5b9..ffa201dd5 100644 --- a/spine-cpp/src/spine-sfml/SkeletonJson.cpp +++ b/spine-cpp/src/spine-sfml/SkeletonJson.cpp @@ -5,10 +5,12 @@ namespace spine { SkeletonJson::SkeletonJson (BaseAttachmentLoader *attachmentLoader) : BaseSkeletonJson(attachmentLoader) { + flipY = true; } SkeletonJson::SkeletonJson (Atlas *atlas) : BaseSkeletonJson(new AtlasAttachmentLoader(atlas)) { + flipY = true; } } /* namespace spine */ diff --git a/spine-cpp/src/spine/Animation.cpp b/spine-cpp/src/spine/Animation.cpp index bdcddcb42..3ebd42fc2 100644 --- a/spine-cpp/src/spine/Animation.cpp +++ b/spine-cpp/src/spine/Animation.cpp @@ -104,7 +104,7 @@ float CurveTimeline::getCurvePercent (int keyframeIndex, float percent) { // /** @param target After the first and before the last entry. */ -int binarySearch (float *values, int valuesLength, float target, int step) { +static int binarySearch (float *values, int valuesLength, float target, int step) { int low = 0; int high = valuesLength / step - 2; if (high == 0) return step; @@ -120,15 +120,15 @@ int binarySearch (float *values, int valuesLength, float target, int step) { return 0; } -int linearSearch (float *values, int valuesLength, float target, int step) { - for (int i = 0, last = valuesLength - step; i <= last; i += step) { - if (values[i] <= target) continue; - return i; - } - return -1; -} - -// +/* + static int linearSearch (float *values, int valuesLength, float target, int step) { + for (int i = 0, last = valuesLength - step; i <= last; i += step) { + if (values[i] <= target) continue; + return i; + } + return -1; + } + */ static const int ROTATE_LAST_FRAME_TIME = -2; static const int ROTATE_FRAME_VALUE = 1; @@ -138,6 +138,7 @@ RotateTimeline::RotateTimeline (int keyframeCount) : framesLength(keyframeCount * 2), frames(new float[framesLength]), boneIndex(0) { + memset(frames, 0, sizeof(float) * framesLength); } RotateTimeline::~RotateTimeline () { @@ -174,7 +175,7 @@ void RotateTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) { } // Interpolate between the last frame and the current frame. - int frameIndex = linearSearch(frames, framesLength, time, 2); + int frameIndex = binarySearch(frames, framesLength, time, 2); float lastFrameValue = frames[frameIndex - 1]; float frameTime = frames[frameIndex]; float percent = 1 - (time - frameTime) / (frames[frameIndex + ROTATE_LAST_FRAME_TIME] - frameTime); @@ -208,6 +209,7 @@ TranslateTimeline::TranslateTimeline (int keyframeCount) : framesLength(keyframeCount * 3), frames(new float[framesLength]), boneIndex(0) { + memset(frames, 0, sizeof(float) * framesLength); } TranslateTimeline::~TranslateTimeline () { @@ -260,7 +262,6 @@ void TranslateTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) ScaleTimeline::ScaleTimeline (int keyframeCount) : TranslateTimeline(keyframeCount) { - frames = new float[framesLength]; } void ScaleTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) { @@ -304,6 +305,7 @@ ColorTimeline::ColorTimeline (int keyframeCount) : framesLength(keyframeCount * 5), frames(new float[framesLength]), slotIndex(0) { + memset(frames, 0, sizeof(float) * framesLength); } ColorTimeline::~ColorTimeline () { @@ -379,6 +381,8 @@ AttachmentTimeline::AttachmentTimeline (int keyframeCount) : frames(new float[keyframeCount]), attachmentNames(new string*[keyframeCount]), slotIndex(0) { + memset(frames, 0, sizeof(float) * keyframeCount); + memset(attachmentNames, 0, sizeof(string*) * keyframeCount); } AttachmentTimeline::~AttachmentTimeline () { @@ -397,10 +401,10 @@ int AttachmentTimeline::getKeyframeCount () { return framesLength; } -void AttachmentTimeline::setKeyframe (int keyframeIndex, float time, string *attachmentName) { +void AttachmentTimeline::setKeyframe (int keyframeIndex, float time, const string &attachmentName) { frames[keyframeIndex] = time; if (attachmentNames[keyframeIndex]) delete attachmentNames[keyframeIndex]; - attachmentNames[keyframeIndex] = attachmentName ? new string(*attachmentName) : 0; + attachmentNames[keyframeIndex] = attachmentName.length() == 0 ? 0 : new string(attachmentName); } void AttachmentTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) { diff --git a/spine-cpp/src/spine/BaseRegionAttachment.cpp b/spine-cpp/src/spine/BaseRegionAttachment.cpp index ed83f6604..6da81d937 100644 --- a/spine-cpp/src/spine/BaseRegionAttachment.cpp +++ b/spine-cpp/src/spine/BaseRegionAttachment.cpp @@ -3,6 +3,16 @@ namespace spine { +BaseRegionAttachment::BaseRegionAttachment () : + x(0), + y(0), + scaleX(1), + scaleY(1), + rotation(0), + width(0), + height(0) { +} + void BaseRegionAttachment::updateOffset () { float localX2 = width / 2; float localY2 = height / 2; diff --git a/spine-cpp/src/spine/BaseSkeletonJson.cpp b/spine-cpp/src/spine/BaseSkeletonJson.cpp index ebf9fb0a8..43ab778c0 100644 --- a/spine-cpp/src/spine/BaseSkeletonJson.cpp +++ b/spine-cpp/src/spine/BaseSkeletonJson.cpp @@ -30,7 +30,8 @@ static float toColor (const string &value, int index) { BaseSkeletonJson::BaseSkeletonJson (BaseAttachmentLoader *attachmentLoader) : attachmentLoader(attachmentLoader), - scale(1) { + scale(1), + flipY(false) { } BaseSkeletonJson::~BaseSkeletonJson () { @@ -88,12 +89,13 @@ SkeletonData* BaseSkeletonJson::readSkeletonData (const char *begin, const char boneData->rotation = boneMap.get("rotation", 0).asDouble(); boneData->scaleX = boneMap.get("scaleX", 1).asDouble(); boneData->scaleY = boneMap.get("scaleY", 1).asDouble(); + boneData->flipY = flipY; skeletonData->bones.push_back(boneData); } - if (root.isMember("slots")) { - Json::Value slots = root["slots"]; + Json::Value slots = root["slots"]; + if (!slots.isNull()) { skeletonData->slots.reserve(slots.size()); for (int i = 0; i < slots.size(); ++i) { Json::Value slotMap = slots[i]; @@ -194,6 +196,15 @@ Animation* BaseSkeletonJson::readAnimation (const string &json, const SkeletonDa return readAnimation(begin, end, skeletonData); } +static void readCurve (CurveTimeline *timeline, int keyframeIndex, const Json::Value &valueMap) { + Json::Value curve = valueMap["curve"]; + if (curve.isNull()) return; + if (curve.isString() && curve.asString() == "stepped") + timeline->setStepped(keyframeIndex); + else if (curve.isArray()) + timeline->setCurve(keyframeIndex, curve[0u].asDouble(), curve[1u].asDouble(), curve[2u].asDouble(), curve[3u].asDouble()); +} + Animation* BaseSkeletonJson::readAnimation (const char *begin, const char *end, const SkeletonData *skeletonData) const { if (!begin) throw invalid_argument("begin cannot be null."); if (!end) throw invalid_argument("end cannot be null."); @@ -236,8 +247,7 @@ Animation* BaseSkeletonJson::readAnimation (const char *begin, const char *end, float time = valueMap["time"].asDouble(); timeline->setKeyframe(keyframeIndex, time, valueMap["angle"].asDouble()); - // BOZO - // readCurve(timeline, keyframeIndex, valueMap); + readCurve(timeline, keyframeIndex, valueMap); keyframeIndex++; } timelines.push_back(timeline); @@ -263,7 +273,7 @@ Animation* BaseSkeletonJson::readAnimation (const char *begin, const char *end, valueMap["time"].asDouble(), // valueMap.get("x", 0).asDouble() * timelineScale, // valueMap.get("y", 0).asDouble() * timelineScale); - // readCurve(timeline, keyframeIndex, valueMap); + readCurve(timeline, keyframeIndex, valueMap); keyframeIndex++; } timelines.push_back(timeline); @@ -275,6 +285,58 @@ Animation* BaseSkeletonJson::readAnimation (const char *begin, const char *end, } } + Json::Value slots = root["slots"]; + if (!slots.isNull()) { + vector slotNames = slots.getMemberNames(); + for (int i = 0; i < slotNames.size(); i++) { + string slotName = slotNames[i]; + int slotIndex = skeletonData->findSlotIndex(slotName); + if (slotIndex == -1) throw runtime_error("Slot not found: " + slotName); + + Json::Value timelineMap = slots[slotName]; + vector timelineNames = timelineMap.getMemberNames(); + for (int i = 0; i < timelineNames.size(); i++) { + string timelineName = timelineNames[i]; + Json::Value values = timelineMap[timelineName]; + + if (timelineName == TIMELINE_COLOR) { + ColorTimeline *timeline = new ColorTimeline(values.size()); + timeline->slotIndex = slotIndex; + + int keyframeIndex = 0; + for (int i = 0; i < values.size(); i++) { + Json::Value valueMap = values[i]; + + string s = valueMap["color"].asString(); + timeline->setKeyframe(keyframeIndex, valueMap["time"].asDouble(), // + toColor(s, 0), toColor(s, 1), toColor(s, 2), toColor(s, 3)); + readCurve(timeline, keyframeIndex, valueMap); + keyframeIndex++; + } + timelines.push_back(timeline); + if (timeline->getDuration() > duration) duration = timeline->getDuration(); + + } else if (timelineName == TIMELINE_ATTACHMENT) { + AttachmentTimeline *timeline = new AttachmentTimeline(values.size()); + timeline->slotIndex = slotIndex; + + int keyframeIndex = 0; + for (int i = 0; i < values.size(); i++) { + Json::Value valueMap = values[i]; + + Json::Value name = valueMap["name"]; + timeline->setKeyframe(keyframeIndex++, valueMap["time"].asDouble(), name.isNull() ? "" : name.asString()); + } + timelines.push_back(timeline); + if (timeline->getDuration() > duration) duration = timeline->getDuration(); + + } else { + throw runtime_error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"); + } + } + } + } + Animation *animation = new Animation(timelines, duration); return animation; } diff --git a/spine-cpp/src/spine/Bone.cpp b/spine-cpp/src/spine/Bone.cpp index 1fc6b1483..143b1701d 100644 --- a/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/src/spine/Bone.cpp @@ -8,10 +8,12 @@ namespace spine { Bone::Bone (BoneData *data) : data(data), parent(0), - scaleX(1), - scaleY(1) { + x(data->x), + y(data->y), + rotation(data->rotation), + scaleX(data->scaleX), + scaleY(data->scaleY) { if (!data) throw std::invalid_argument("data cannot be null."); - setToBindPose(); } void Bone::setToBindPose () { @@ -51,6 +53,10 @@ void Bone::updateWorldTransform (bool flipX, bool flipY) { m10 = -m10; m11 = -m11; } + if (data->flipY) { + m10 = -m10; + m11 = -m11; + } } } /* namespace spine */ diff --git a/spine-cpp/src/spine/Slot.cpp b/spine-cpp/src/spine/Slot.cpp index 6f7734645..7ceedbab2 100644 --- a/spine-cpp/src/spine/Slot.cpp +++ b/spine-cpp/src/spine/Slot.cpp @@ -1,6 +1,7 @@ #include #include #include +#include namespace spine { @@ -17,6 +18,7 @@ Slot::Slot (SlotData *data, BaseSkeleton *skeleton, Bone *bone) : if (!data) throw std::invalid_argument("data cannot be null."); if (!skeleton) throw std::invalid_argument("skeleton cannot be null."); if (!bone) throw std::invalid_argument("bone cannot be null."); + setToBindPose(); } void Slot::setAttachment (Attachment *attachment) { @@ -33,8 +35,8 @@ float Slot::getAttachmentTime () const { } void Slot::setToBindPose () { - for (int i = 0, n = skeleton->slots.size(); i < n; i++) { - if (this == skeleton->slots[i]) { + for (int i = 0, n = skeleton->data->slots.size(); i < n; i++) { + if (data == skeleton->data->slots[i]) { setToBindPose(i); return; } diff --git a/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java b/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java index 4c441f057..de9cd5cdb 100644 --- a/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java +++ b/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java @@ -226,12 +226,12 @@ public class SkeletonJson { for (Entry entry : slotsMap.entries()) { String slotName = entry.key; int slotIndex = skeletonData.findSlotIndex(slotName); - OrderedMap propertyMap = (OrderedMap)entry.value; + OrderedMap timelineMap = (OrderedMap)entry.value; - for (Entry propertyEntry : propertyMap.entries()) { - Array values = (Array)propertyEntry.value; - String timelineType = (String)propertyEntry.key; - if (timelineType.equals(TIMELINE_COLOR)) { + for (Entry timelineEntry : timelineMap.entries()) { + Array values = (Array)timelineEntry.value; + String timelineName = (String)timelineEntry.key; + if (timelineName.equals(TIMELINE_COLOR)) { ColorTimeline timeline = new ColorTimeline(values.size); timeline.setSlotIndex(slotIndex); @@ -246,7 +246,7 @@ public class SkeletonJson { timelines.add(timeline); duration = Math.max(duration, timeline.getDuration()); - } else if (timelineType.equals(TIMELINE_ATTACHMENT)) { + } else if (timelineName.equals(TIMELINE_ATTACHMENT)) { AttachmentTimeline timeline = new AttachmentTimeline(values.size); timeline.setSlotIndex(slotIndex); @@ -259,7 +259,7 @@ public class SkeletonJson { duration = Math.max(duration, timeline.getDuration()); } else - throw new RuntimeException("Invalid timeline type for a slot: " + timelineType + " (" + slotName + ")"); + throw new RuntimeException("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"); } } } diff --git a/spine-libgdx/src/com/esotericsoftware/spine/Slot.java b/spine-libgdx/src/com/esotericsoftware/spine/Slot.java index 4d8b3eb73..8338ab1ea 100644 --- a/spine-libgdx/src/com/esotericsoftware/spine/Slot.java +++ b/spine-libgdx/src/com/esotericsoftware/spine/Slot.java @@ -26,6 +26,7 @@ public class Slot { this.skeleton = skeleton; this.bone = bone; color = new Color(1, 1, 1, 1); + setToBindPose(); } /** Copy constructor. */ @@ -84,7 +85,7 @@ public class Slot { } public void setToBindPose () { - setToBindPose(skeleton.slots.indexOf(this, true)); + setToBindPose(skeleton.data.slots.indexOf(data, true)); } public String toString () {