mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-20 01:06:00 +08:00
Clean up
This commit is contained in:
parent
6710c1e9c9
commit
31b07f8625
@ -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" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 */
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -13,6 +13,7 @@ class BaseSkeletonJson {
|
||||
public:
|
||||
BaseAttachmentLoader *attachmentLoader;
|
||||
float scale;
|
||||
bool flipY;
|
||||
|
||||
BaseSkeletonJson (BaseAttachmentLoader *attachmentLoader);
|
||||
virtual ~BaseSkeletonJson ();
|
||||
|
||||
@ -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) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<string> 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<string> 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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/BaseSkeleton.h>
|
||||
#include <spine/SkeletonData.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -226,12 +226,12 @@ public class SkeletonJson {
|
||||
for (Entry<String, ?> 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<OrderedMap> values = (Array)propertyEntry.value;
|
||||
String timelineType = (String)propertyEntry.key;
|
||||
if (timelineType.equals(TIMELINE_COLOR)) {
|
||||
for (Entry timelineEntry : timelineMap.entries()) {
|
||||
Array<OrderedMap> 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 + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 () {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user