mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-21 01:36:02 +08:00
cpp, loading, applying and animating with SFML is working.
This commit is contained in:
parent
268933242f
commit
6710c1e9c9
@ -140,12 +140,12 @@ function SkeletonJson.new (attachmentResolver)
|
|||||||
if not root then error("Invalid JSON: " .. jsonText, 2) end
|
if not root then error("Invalid JSON: " .. jsonText, 2) end
|
||||||
|
|
||||||
local bonesMap = root["bones"]
|
local bonesMap = root["bones"]
|
||||||
for boneName,propertyMap in pairs(bonesMap) do
|
for boneName,timelineMap in pairs(bonesMap) do
|
||||||
local boneIndex = skeletonData:findBoneIndex(boneName)
|
local boneIndex = skeletonData:findBoneIndex(boneName)
|
||||||
if boneIndex == -1 then error("Bone not found: " .. boneName) end
|
if boneIndex == -1 then error("Bone not found: " .. boneName) end
|
||||||
|
|
||||||
for timelineType,values in pairs(propertyMap) do
|
for timelineName,values in pairs(timelineMap) do
|
||||||
if timelineType == TIMELINE_ROTATE then
|
if timelineName == TIMELINE_ROTATE then
|
||||||
local timeline = Animation.RotateTimeline.new()
|
local timeline = Animation.RotateTimeline.new()
|
||||||
timeline.boneIndex = boneIndex
|
timeline.boneIndex = boneIndex
|
||||||
|
|
||||||
@ -159,10 +159,10 @@ function SkeletonJson.new (attachmentResolver)
|
|||||||
table.insert(timelines, timeline)
|
table.insert(timelines, timeline)
|
||||||
duration = math.max(duration, timeline:getDuration())
|
duration = math.max(duration, timeline:getDuration())
|
||||||
|
|
||||||
elseif timelineType == TIMELINE_TRANSLATE or timelineType == TIMELINE_SCALE then
|
elseif timelineName == TIMELINE_TRANSLATE or timelineName == TIMELINE_SCALE then
|
||||||
local timeline
|
local timeline
|
||||||
local timelineScale = 1
|
local timelineScale = 1
|
||||||
if timelineType == TIMELINE_SCALE then
|
if timelineName == TIMELINE_SCALE then
|
||||||
timeline = Animation.ScaleTimeline.new()
|
timeline = Animation.ScaleTimeline.new()
|
||||||
else
|
else
|
||||||
timeline = Animation.TranslateTimeline.new()
|
timeline = Animation.TranslateTimeline.new()
|
||||||
@ -183,18 +183,18 @@ function SkeletonJson.new (attachmentResolver)
|
|||||||
duration = math.max(duration, timeline:getDuration())
|
duration = math.max(duration, timeline:getDuration())
|
||||||
|
|
||||||
else
|
else
|
||||||
error("Invalid timeline type for a bone: " .. timelineType .. " (" .. boneName .. ")")
|
error("Invalid timeline type for a bone: " .. timelineName .. " (" .. boneName .. ")")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local slotsMap = root["slots"]
|
local slotsMap = root["slots"]
|
||||||
if slotsMap then
|
if slotsMap then
|
||||||
for slotName,propertyMap in pairs(slotsMap) do
|
for slotName,timelineMap in pairs(slotsMap) do
|
||||||
local slotIndex = skeletonData:findSlotIndex(slotName)
|
local slotIndex = skeletonData:findSlotIndex(slotName)
|
||||||
|
|
||||||
for timelineType,values in pairs(propertyMap) do
|
for timelineName,values in pairs(timelineMap) do
|
||||||
if timelineType == TIMELINE_COLOR then
|
if timelineName == TIMELINE_COLOR then
|
||||||
local timeline = Animation.ColorTimeline.new()
|
local timeline = Animation.ColorTimeline.new()
|
||||||
timeline.slotIndex = slotIndex
|
timeline.slotIndex = slotIndex
|
||||||
|
|
||||||
@ -215,7 +215,7 @@ function SkeletonJson.new (attachmentResolver)
|
|||||||
table.insert(timelines, timeline)
|
table.insert(timelines, timeline)
|
||||||
duration = math.max(duration, timeline:getDuration())
|
duration = math.max(duration, timeline:getDuration())
|
||||||
|
|
||||||
elseif timelineType == TIMELINE_ATTACHMENT then
|
elseif timelineName == TIMELINE_ATTACHMENT then
|
||||||
local timeline = Animation.AttachmentTimeline.new()
|
local timeline = Animation.AttachmentTimeline.new()
|
||||||
timeline.slotName = slotName
|
timeline.slotName = slotName
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ function SkeletonJson.new (attachmentResolver)
|
|||||||
duration = math.max(duration, timeline:getDuration())
|
duration = math.max(duration, timeline:getDuration())
|
||||||
|
|
||||||
else
|
else
|
||||||
error("Invalid frame type for a slot: " .. timelineType .. " (" .. slotName .. ")")
|
error("Invalid frame type for a slot: " .. timelineName .. " (" .. slotName .. ")")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -19,7 +19,7 @@ org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
|
|||||||
org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()}
|
org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()}
|
||||||
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
|
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
|
||||||
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
|
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=-Warning
|
||||||
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true}
|
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true}
|
||||||
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
|
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
|
||||||
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
@ -65,3 +65,4 @@ org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
|
|||||||
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")}
|
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")}
|
||||||
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
|
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
|
||||||
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
useParentScope=false
|
||||||
|
|||||||
@ -9,7 +9,7 @@ namespace spine {
|
|||||||
class Skeleton: public BaseSkeleton, public sf::Drawable {
|
class Skeleton: public BaseSkeleton, public sf::Drawable {
|
||||||
public:
|
public:
|
||||||
sf::VertexArray vertexArray;
|
sf::VertexArray vertexArray;
|
||||||
sf::Texture *texture;
|
sf::Texture *texture; // BOZO - This is ugly. Support multiple textures?
|
||||||
|
|
||||||
Skeleton (SkeletonData *skeletonData);
|
Skeleton (SkeletonData *skeletonData);
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,8 @@ public:
|
|||||||
float duration;
|
float duration;
|
||||||
|
|
||||||
Animation (const std::vector<Timeline*> &timelines, float duration);
|
Animation (const std::vector<Timeline*> &timelines, float duration);
|
||||||
|
|
||||||
|
void apply (BaseSkeleton *skeleton, float time, bool loop);
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -63,9 +65,9 @@ public:
|
|||||||
RotateTimeline (int keyframeCount);
|
RotateTimeline (int keyframeCount);
|
||||||
virtual ~RotateTimeline ();
|
virtual ~RotateTimeline ();
|
||||||
|
|
||||||
virtual float getDuration () = 0;
|
virtual float getDuration ();
|
||||||
virtual int getKeyframeCount () = 0;
|
virtual int getKeyframeCount ();
|
||||||
virtual void apply (BaseSkeleton *skeleton, float time, float alpha) = 0;
|
virtual void apply (BaseSkeleton *skeleton, float time, float alpha);
|
||||||
|
|
||||||
void setKeyframe (int keyframeIndex, float time, float value);
|
void setKeyframe (int keyframeIndex, float time, float value);
|
||||||
};
|
};
|
||||||
@ -81,9 +83,9 @@ public:
|
|||||||
TranslateTimeline (int keyframeCount);
|
TranslateTimeline (int keyframeCount);
|
||||||
virtual ~TranslateTimeline ();
|
virtual ~TranslateTimeline ();
|
||||||
|
|
||||||
virtual float getDuration () = 0;
|
virtual float getDuration ();
|
||||||
virtual int getKeyframeCount () = 0;
|
virtual int getKeyframeCount ();
|
||||||
virtual void apply (BaseSkeleton *skeleton, float time, float alpha) = 0;
|
virtual void apply (BaseSkeleton *skeleton, float time, float alpha);
|
||||||
|
|
||||||
void setKeyframe (int keyframeIndex, float time, float x, float y);
|
void setKeyframe (int keyframeIndex, float time, float x, float y);
|
||||||
};
|
};
|
||||||
@ -94,9 +96,7 @@ class ScaleTimeline: public TranslateTimeline {
|
|||||||
public:
|
public:
|
||||||
ScaleTimeline (int keyframeCount);
|
ScaleTimeline (int keyframeCount);
|
||||||
|
|
||||||
virtual float getDuration () = 0;
|
virtual void apply (BaseSkeleton *skeleton, float time, float alpha);
|
||||||
virtual int getKeyframeCount () = 0;
|
|
||||||
virtual void apply (BaseSkeleton *skeleton, float time, float alpha) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -110,9 +110,9 @@ public:
|
|||||||
ColorTimeline (int keyframeCount);
|
ColorTimeline (int keyframeCount);
|
||||||
virtual ~ColorTimeline ();
|
virtual ~ColorTimeline ();
|
||||||
|
|
||||||
virtual float getDuration () = 0;
|
virtual float getDuration ();
|
||||||
virtual int getKeyframeCount () = 0;
|
virtual int getKeyframeCount ();
|
||||||
virtual void apply (BaseSkeleton *skeleton, float time, float alpha) = 0;
|
virtual void apply (BaseSkeleton *skeleton, float time, float alpha);
|
||||||
|
|
||||||
void setKeyframe (int keyframeIndex, float time, float r, float g, float b, float a);
|
void setKeyframe (int keyframeIndex, float time, float r, float g, float b, float a);
|
||||||
};
|
};
|
||||||
@ -129,9 +129,9 @@ public:
|
|||||||
AttachmentTimeline (int keyframeCount);
|
AttachmentTimeline (int keyframeCount);
|
||||||
virtual ~AttachmentTimeline ();
|
virtual ~AttachmentTimeline ();
|
||||||
|
|
||||||
virtual float getDuration () = 0;
|
virtual float getDuration ();
|
||||||
virtual int getKeyframeCount () = 0;
|
virtual int getKeyframeCount ();
|
||||||
virtual void apply (BaseSkeleton *skeleton, float time, float alpha) = 0;
|
virtual void apply (BaseSkeleton *skeleton, float time, float alpha);
|
||||||
|
|
||||||
void setKeyframe (int keyframeIndex, float time, std::string *attachmentName);
|
void setKeyframe (int keyframeIndex, float time, std::string *attachmentName);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,7 +11,6 @@ class Slot;
|
|||||||
class Attachment {
|
class Attachment {
|
||||||
public:
|
public:
|
||||||
std::string name;
|
std::string name;
|
||||||
float x, y, scaleX, scaleY, rotation, width, height;
|
|
||||||
|
|
||||||
virtual ~Attachment () {
|
virtual ~Attachment () {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ class Slot;
|
|||||||
|
|
||||||
class BaseRegionAttachment: public Attachment {
|
class BaseRegionAttachment: public Attachment {
|
||||||
public:
|
public:
|
||||||
|
float x, y, scaleX, scaleY, rotation, width, height;
|
||||||
float offset[8];
|
float offset[8];
|
||||||
|
|
||||||
void updateOffset ();
|
void updateOffset ();
|
||||||
|
|||||||
@ -5,8 +5,9 @@
|
|||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
|
|
||||||
class SkeletonData;
|
|
||||||
class BaseAttachmentLoader;
|
class BaseAttachmentLoader;
|
||||||
|
class SkeletonData;
|
||||||
|
class Animation;
|
||||||
|
|
||||||
class BaseSkeletonJson {
|
class BaseSkeletonJson {
|
||||||
public:
|
public:
|
||||||
@ -20,6 +21,11 @@ public:
|
|||||||
SkeletonData* readSkeletonData (std::istream &file) const;
|
SkeletonData* readSkeletonData (std::istream &file) const;
|
||||||
SkeletonData* readSkeletonData (const std::string &json) const;
|
SkeletonData* readSkeletonData (const std::string &json) const;
|
||||||
SkeletonData* readSkeletonData (const char *begin, const char *end) const;
|
SkeletonData* readSkeletonData (const char *begin, const char *end) const;
|
||||||
|
|
||||||
|
Animation* readAnimation (std::ifstream &file, const SkeletonData *skeletonData) const;
|
||||||
|
Animation* readAnimation (std::istream &file, const SkeletonData *skeletonData) const;
|
||||||
|
Animation* readAnimation (const std::string &json, const SkeletonData *skeletonData) const;
|
||||||
|
Animation* readAnimation (const char *begin, const char *end, const SkeletonData *skeletonData) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace spine */
|
} /* namespace spine */
|
||||||
|
|||||||
@ -7,13 +7,19 @@ using namespace std;
|
|||||||
using namespace spine;
|
using namespace spine;
|
||||||
|
|
||||||
int main () {
|
int main () {
|
||||||
ifstream file("../data/spineboy-skeleton.json");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ifstream file2("../data/spineboy.atlas");
|
ifstream atlasFile("../data/spineboy.atlas");
|
||||||
Atlas *atlas = new Atlas(file2);
|
Atlas *atlas = new Atlas(atlasFile);
|
||||||
|
|
||||||
SkeletonJson skeletonJson(atlas);
|
SkeletonJson skeletonJson(atlas);
|
||||||
SkeletonData *skeletonData = skeletonJson.readSkeletonData(file);
|
|
||||||
|
ifstream skeletonFile("../data/spineboy-skeleton.json");
|
||||||
|
SkeletonData *skeletonData = skeletonJson.readSkeletonData(skeletonFile);
|
||||||
|
|
||||||
|
ifstream animationFile("../data/spineboy-walk.json");
|
||||||
|
Animation *animation = skeletonJson.readAnimation(animationFile, skeletonData);
|
||||||
|
|
||||||
Skeleton *skeleton = new Skeleton(skeletonData);
|
Skeleton *skeleton = new Skeleton(skeletonData);
|
||||||
skeleton->setToBindPose();
|
skeleton->setToBindPose();
|
||||||
skeleton->getRootBone()->x = 200;
|
skeleton->getRootBone()->x = 200;
|
||||||
@ -23,12 +29,24 @@ int main () {
|
|||||||
sf::RenderWindow window(sf::VideoMode(640, 480), "Spine SFML");
|
sf::RenderWindow window(sf::VideoMode(640, 480), "Spine SFML");
|
||||||
window.setFramerateLimit(60);
|
window.setFramerateLimit(60);
|
||||||
sf::Event event;
|
sf::Event event;
|
||||||
|
sf::Clock deltaClock;
|
||||||
|
float animationTime = 0;
|
||||||
while (window.isOpen()) {
|
while (window.isOpen()) {
|
||||||
while (window.pollEvent(event))
|
while (window.pollEvent(event))
|
||||||
if (event.type == sf::Event::Closed) window.close();
|
if (event.type == sf::Event::Closed) window.close();
|
||||||
window.clear();
|
window.clear();
|
||||||
window.draw(*skeleton);
|
window.draw(*skeleton);
|
||||||
window.display();
|
window.display();
|
||||||
|
|
||||||
|
float delta = deltaClock.getElapsedTime().asSeconds();
|
||||||
|
deltaClock.restart();
|
||||||
|
animationTime += delta;
|
||||||
|
|
||||||
|
skeleton->setToBindPose();
|
||||||
|
skeleton->getRootBone()->x = 200;
|
||||||
|
skeleton->getRootBone()->y = 420;
|
||||||
|
animation->apply(skeleton, animationTime, true);
|
||||||
|
skeleton->updateWorldTransform();
|
||||||
}
|
}
|
||||||
} catch (exception &ex) {
|
} catch (exception &ex) {
|
||||||
cout << ex.what() << endl << flush;
|
cout << ex.what() << endl << flush;
|
||||||
|
|||||||
@ -9,8 +9,7 @@
|
|||||||
namespace spine {
|
namespace spine {
|
||||||
|
|
||||||
RegionAttachment::RegionAttachment (AtlasRegion *region) {
|
RegionAttachment::RegionAttachment (AtlasRegion *region) {
|
||||||
texture = region->page->texture;
|
texture = region->page->texture; // BOZO - Resolve attachment as late as possible?
|
||||||
sf::Vector2u size = texture->getSize();
|
|
||||||
int u = region->x;
|
int u = region->x;
|
||||||
int u2 = u + region->width;
|
int u2 = u + region->width;
|
||||||
int v = region->y;
|
int v = region->y;
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <math.h>
|
||||||
#include <spine/Animation.h>
|
#include <spine/Animation.h>
|
||||||
#include <spine/Bone.h>
|
#include <spine/Bone.h>
|
||||||
#include <spine/Slot.h>
|
#include <spine/Slot.h>
|
||||||
@ -14,6 +18,15 @@ Animation::Animation (const vector<Timeline*> &timelines, float duration) :
|
|||||||
duration(duration) {
|
duration(duration) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Animation::apply (BaseSkeleton *skeleton, float time, bool loop) {
|
||||||
|
if (!skeleton) throw std::invalid_argument("skeleton cannot be null.");
|
||||||
|
|
||||||
|
if (loop && duration) time = fmodf(time, duration);
|
||||||
|
|
||||||
|
for (int i = 0, n = timelines.size(); i < n; i++)
|
||||||
|
timelines[i]->apply(skeleton, time, 1);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
static const float LINEAR = 0;
|
static const float LINEAR = 0;
|
||||||
@ -22,6 +35,7 @@ static const int BEZIER_SEGMENTS = 10;
|
|||||||
|
|
||||||
CurveTimeline::CurveTimeline (int keyframeCount) :
|
CurveTimeline::CurveTimeline (int keyframeCount) :
|
||||||
curves(new float[(keyframeCount - 1) * 6]) {
|
curves(new float[(keyframeCount - 1) * 6]) {
|
||||||
|
memset(curves, 0, sizeof(float) * (keyframeCount - 1) * 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurveTimeline::~CurveTimeline () {
|
CurveTimeline::~CurveTimeline () {
|
||||||
@ -122,7 +136,8 @@ static const int ROTATE_FRAME_VALUE = 1;
|
|||||||
RotateTimeline::RotateTimeline (int keyframeCount) :
|
RotateTimeline::RotateTimeline (int keyframeCount) :
|
||||||
CurveTimeline(keyframeCount),
|
CurveTimeline(keyframeCount),
|
||||||
framesLength(keyframeCount * 2),
|
framesLength(keyframeCount * 2),
|
||||||
frames(new float[framesLength]) {
|
frames(new float[framesLength]),
|
||||||
|
boneIndex(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
RotateTimeline::~RotateTimeline () {
|
RotateTimeline::~RotateTimeline () {
|
||||||
@ -159,7 +174,7 @@ void RotateTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Interpolate between the last frame and the current frame.
|
// Interpolate between the last frame and the current frame.
|
||||||
int frameIndex = binarySearch(frames, framesLength, time, 2);
|
int frameIndex = linearSearch(frames, framesLength, time, 2);
|
||||||
float lastFrameValue = frames[frameIndex - 1];
|
float lastFrameValue = frames[frameIndex - 1];
|
||||||
float frameTime = frames[frameIndex];
|
float frameTime = frames[frameIndex];
|
||||||
float percent = 1 - (time - frameTime) / (frames[frameIndex + ROTATE_LAST_FRAME_TIME] - frameTime);
|
float percent = 1 - (time - frameTime) / (frames[frameIndex + ROTATE_LAST_FRAME_TIME] - frameTime);
|
||||||
@ -191,7 +206,8 @@ static const int TRANSLATE_FRAME_Y = 2;
|
|||||||
TranslateTimeline::TranslateTimeline (int keyframeCount) :
|
TranslateTimeline::TranslateTimeline (int keyframeCount) :
|
||||||
CurveTimeline(keyframeCount),
|
CurveTimeline(keyframeCount),
|
||||||
framesLength(keyframeCount * 3),
|
framesLength(keyframeCount * 3),
|
||||||
frames(new float[framesLength]) {
|
frames(new float[framesLength]),
|
||||||
|
boneIndex(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TranslateTimeline::~TranslateTimeline () {
|
TranslateTimeline::~TranslateTimeline () {
|
||||||
@ -286,7 +302,8 @@ static const int COLOR_FRAME_A = 4;
|
|||||||
ColorTimeline::ColorTimeline (int keyframeCount) :
|
ColorTimeline::ColorTimeline (int keyframeCount) :
|
||||||
CurveTimeline(keyframeCount),
|
CurveTimeline(keyframeCount),
|
||||||
framesLength(keyframeCount * 5),
|
framesLength(keyframeCount * 5),
|
||||||
frames(new float[framesLength]) {
|
frames(new float[framesLength]),
|
||||||
|
slotIndex(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorTimeline::~ColorTimeline () {
|
ColorTimeline::~ColorTimeline () {
|
||||||
@ -360,7 +377,8 @@ void ColorTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) {
|
|||||||
AttachmentTimeline::AttachmentTimeline (int keyframeCount) :
|
AttachmentTimeline::AttachmentTimeline (int keyframeCount) :
|
||||||
framesLength(keyframeCount),
|
framesLength(keyframeCount),
|
||||||
frames(new float[keyframeCount]),
|
frames(new float[keyframeCount]),
|
||||||
attachmentNames(new string*[keyframeCount]) {
|
attachmentNames(new string*[keyframeCount]),
|
||||||
|
slotIndex(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
AttachmentTimeline::~AttachmentTimeline () {
|
AttachmentTimeline::~AttachmentTimeline () {
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::runtime_error;
|
using std::runtime_error;
|
||||||
|
using std::invalid_argument;
|
||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
|
|
||||||
@ -75,11 +76,15 @@ BaseAtlas::~BaseAtlas () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BaseAtlas::load (std::ifstream &file) {
|
void BaseAtlas::load (std::ifstream &file) {
|
||||||
|
if (!file) throw invalid_argument("file cannot be null.");
|
||||||
if (!file.is_open()) throw runtime_error("Atlas file is not open.");
|
if (!file.is_open()) throw runtime_error("Atlas file is not open.");
|
||||||
|
|
||||||
load((std::istream&)file);
|
load((std::istream&)file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseAtlas::load (std::istream &input) {
|
void BaseAtlas::load (std::istream &input) {
|
||||||
|
if (!input) throw invalid_argument("input cannot be null.");
|
||||||
|
|
||||||
string text;
|
string text;
|
||||||
std::getline(input, text, (char)EOF);
|
std::getline(input, text, (char)EOF);
|
||||||
const char *begin = text.c_str();
|
const char *begin = text.c_str();
|
||||||
@ -94,6 +99,9 @@ void BaseAtlas::load (const string &text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BaseAtlas::load (const char *current, const char *end) {
|
void BaseAtlas::load (const char *current, const char *end) {
|
||||||
|
if (!current) throw invalid_argument("current cannot be null.");
|
||||||
|
if (!end) throw invalid_argument("end cannot be null.");
|
||||||
|
|
||||||
string value;
|
string value;
|
||||||
string tuple[4];
|
string tuple[4];
|
||||||
BaseAtlasPage *page;
|
BaseAtlasPage *page;
|
||||||
|
|||||||
@ -4,17 +4,30 @@
|
|||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
#include <spine/BaseSkeletonJson.h>
|
#include <spine/BaseSkeletonJson.h>
|
||||||
#include <spine/BaseAttachmentLoader.h>
|
#include <spine/BaseAttachmentLoader.h>
|
||||||
|
#include <spine/BaseRegionAttachment.h>
|
||||||
#include <spine/SkeletonData.h>
|
#include <spine/SkeletonData.h>
|
||||||
#include <spine/BoneData.h>
|
#include <spine/BoneData.h>
|
||||||
#include <spine/SlotData.h>
|
#include <spine/SlotData.h>
|
||||||
#include <spine/Skin.h>
|
#include <spine/Skin.h>
|
||||||
|
#include <spine/Animation.h>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::runtime_error;
|
using std::runtime_error;
|
||||||
|
using std::invalid_argument;
|
||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
|
|
||||||
|
static float toColor (const string &value, int index) {
|
||||||
|
if (value.size() != 8) throw runtime_error("Error parsing color, length must be 8: " + value);
|
||||||
|
char *p;
|
||||||
|
int color = strtoul(value.substr(index * 2, 2).c_str(), &p, 16);
|
||||||
|
if (*p != 0) throw runtime_error("Error parsing color: " + value + ", invalid hex value: " + value.substr(index * 2, 2));
|
||||||
|
return color / (float)255;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
BaseSkeletonJson::BaseSkeletonJson (BaseAttachmentLoader *attachmentLoader) :
|
BaseSkeletonJson::BaseSkeletonJson (BaseAttachmentLoader *attachmentLoader) :
|
||||||
attachmentLoader(attachmentLoader),
|
attachmentLoader(attachmentLoader),
|
||||||
scale(1) {
|
scale(1) {
|
||||||
@ -23,20 +36,16 @@ BaseSkeletonJson::BaseSkeletonJson (BaseAttachmentLoader *attachmentLoader) :
|
|||||||
BaseSkeletonJson::~BaseSkeletonJson () {
|
BaseSkeletonJson::~BaseSkeletonJson () {
|
||||||
}
|
}
|
||||||
|
|
||||||
float toColor (const string &value, int index) {
|
|
||||||
if (value.size() != 8) throw runtime_error("Error parsing color, length must be 8: " + value);
|
|
||||||
char *p;
|
|
||||||
int color = strtoul(value.substr(index * 2, 2).c_str(), &p, 16);
|
|
||||||
if (*p != 0) throw runtime_error("Error parsing color: " + value + ", invalid hex value: " + value.substr(index * 2, 2));
|
|
||||||
return color / (float)255;
|
|
||||||
}
|
|
||||||
|
|
||||||
SkeletonData* BaseSkeletonJson::readSkeletonData (std::ifstream &file) const {
|
SkeletonData* BaseSkeletonJson::readSkeletonData (std::ifstream &file) const {
|
||||||
|
if (!file) throw invalid_argument("file cannot be null.");
|
||||||
if (!file.is_open()) throw runtime_error("Skeleton file is not open.");
|
if (!file.is_open()) throw runtime_error("Skeleton file is not open.");
|
||||||
|
|
||||||
return readSkeletonData((std::istream&)file);
|
return readSkeletonData((std::istream&)file);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkeletonData* BaseSkeletonJson::readSkeletonData (std::istream &input) const {
|
SkeletonData* BaseSkeletonJson::readSkeletonData (std::istream &input) const {
|
||||||
|
if (!input) throw invalid_argument("input cannot be null.");
|
||||||
|
|
||||||
string json;
|
string json;
|
||||||
std::getline(input, json, (char)EOF);
|
std::getline(input, json, (char)EOF);
|
||||||
return readSkeletonData(json);
|
return readSkeletonData(json);
|
||||||
@ -49,6 +58,9 @@ SkeletonData* BaseSkeletonJson::readSkeletonData (const string &json) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SkeletonData* BaseSkeletonJson::readSkeletonData (const char *begin, const char *end) const {
|
SkeletonData* BaseSkeletonJson::readSkeletonData (const char *begin, const char *end) const {
|
||||||
|
if (!begin) throw invalid_argument("begin cannot be null.");
|
||||||
|
if (!end) throw invalid_argument("end cannot be null.");
|
||||||
|
|
||||||
static string const ATTACHMENT_REGION = "region";
|
static string const ATTACHMENT_REGION = "region";
|
||||||
static string const ATTACHMENT_REGION_SEQUENCE = "regionSequence";
|
static string const ATTACHMENT_REGION_SEQUENCE = "regionSequence";
|
||||||
|
|
||||||
@ -140,13 +152,17 @@ SkeletonData* BaseSkeletonJson::readSkeletonData (const char *begin, const char
|
|||||||
|
|
||||||
Attachment* attachment = attachmentLoader->newAttachment(type,
|
Attachment* attachment = attachmentLoader->newAttachment(type,
|
||||||
attachmentMap.get("name", attachmentName).asString());
|
attachmentMap.get("name", attachmentName).asString());
|
||||||
attachment->x = attachmentMap.get("x", 0).asDouble() * scale;
|
|
||||||
attachment->y = attachmentMap.get("y", 0).asDouble() * scale;
|
if (type == region || type == regionSequence) {
|
||||||
attachment->scaleX = attachmentMap.get("scaleX", 1).asDouble();
|
BaseRegionAttachment *regionAttachment = reinterpret_cast<BaseRegionAttachment*>(attachment);
|
||||||
attachment->scaleY = attachmentMap.get("scaleY", 1).asDouble();
|
regionAttachment->x = attachmentMap.get("x", 0).asDouble() * scale;
|
||||||
attachment->rotation = attachmentMap.get("rotation", 0).asDouble();
|
regionAttachment->y = attachmentMap.get("y", 0).asDouble() * scale;
|
||||||
attachment->width = attachmentMap.get("width", 32).asDouble() * scale;
|
regionAttachment->scaleX = attachmentMap.get("scaleX", 1).asDouble();
|
||||||
attachment->height = attachmentMap.get("height", 32).asDouble() * scale;
|
regionAttachment->scaleY = attachmentMap.get("scaleY", 1).asDouble();
|
||||||
|
regionAttachment->rotation = attachmentMap.get("rotation", 0).asDouble();
|
||||||
|
regionAttachment->width = attachmentMap.get("width", 32).asDouble() * scale;
|
||||||
|
regionAttachment->height = attachmentMap.get("height", 32).asDouble() * scale;
|
||||||
|
}
|
||||||
|
|
||||||
skin->addAttachment(slotIndex, attachmentName, attachment);
|
skin->addAttachment(slotIndex, attachmentName, attachment);
|
||||||
}
|
}
|
||||||
@ -157,4 +173,110 @@ SkeletonData* BaseSkeletonJson::readSkeletonData (const char *begin, const char
|
|||||||
return skeletonData;
|
return skeletonData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Animation* BaseSkeletonJson::readAnimation (std::ifstream &file, const SkeletonData *skeletonData) const {
|
||||||
|
if (!file) throw invalid_argument("file cannot be null.");
|
||||||
|
if (!file.is_open()) throw runtime_error("Animation file is not open.");
|
||||||
|
|
||||||
|
return readAnimation((std::istream&)file, skeletonData);
|
||||||
|
}
|
||||||
|
|
||||||
|
Animation* BaseSkeletonJson::readAnimation (std::istream &input, const SkeletonData *skeletonData) const {
|
||||||
|
if (!input) throw invalid_argument("input cannot be null.");
|
||||||
|
|
||||||
|
string json;
|
||||||
|
std::getline(input, json, (char)EOF);
|
||||||
|
return readAnimation(json, skeletonData);
|
||||||
|
}
|
||||||
|
|
||||||
|
Animation* BaseSkeletonJson::readAnimation (const string &json, const SkeletonData *skeletonData) const {
|
||||||
|
const char *begin = json.c_str();
|
||||||
|
const char *end = begin + json.length();
|
||||||
|
return readAnimation(begin, end, skeletonData);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.");
|
||||||
|
if (!skeletonData) throw invalid_argument("skeletonData cannot be null.");
|
||||||
|
|
||||||
|
static string const TIMELINE_SCALE = "scale";
|
||||||
|
static string const TIMELINE_ROTATE = "rotate";
|
||||||
|
static string const TIMELINE_TRANSLATE = "translate";
|
||||||
|
static string const TIMELINE_ATTACHMENT = "attachment";
|
||||||
|
static string const TIMELINE_COLOR = "color";
|
||||||
|
|
||||||
|
vector<Timeline*> timelines;
|
||||||
|
float duration = 0;
|
||||||
|
|
||||||
|
Json::Value root;
|
||||||
|
Json::Reader reader;
|
||||||
|
if (!reader.parse(begin, end, root))
|
||||||
|
throw runtime_error("Error parsing animation JSON.\n" + reader.getFormatedErrorMessages());
|
||||||
|
|
||||||
|
Json::Value bones = root["bones"];
|
||||||
|
vector<string> boneNames = bones.getMemberNames();
|
||||||
|
for (int i = 0; i < boneNames.size(); i++) {
|
||||||
|
string boneName = boneNames[i];
|
||||||
|
int boneIndex = skeletonData->findBoneIndex(boneName);
|
||||||
|
if (boneIndex == -1) throw runtime_error("Bone not found: " + boneName);
|
||||||
|
|
||||||
|
Json::Value timelineMap = bones[boneName];
|
||||||
|
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_ROTATE) {
|
||||||
|
RotateTimeline *timeline = new RotateTimeline(values.size());
|
||||||
|
timeline->boneIndex = boneIndex;
|
||||||
|
|
||||||
|
int keyframeIndex = 0;
|
||||||
|
for (int i = 0; i < values.size(); i++) {
|
||||||
|
Json::Value valueMap = values[i];
|
||||||
|
|
||||||
|
float time = valueMap["time"].asDouble();
|
||||||
|
timeline->setKeyframe(keyframeIndex, time, valueMap["angle"].asDouble());
|
||||||
|
// BOZO
|
||||||
|
// readCurve(timeline, keyframeIndex, valueMap);
|
||||||
|
keyframeIndex++;
|
||||||
|
}
|
||||||
|
timelines.push_back(timeline);
|
||||||
|
if (timeline->getDuration() > duration) duration = timeline->getDuration();
|
||||||
|
|
||||||
|
} else if (timelineName == TIMELINE_TRANSLATE || timelineName == TIMELINE_SCALE) {
|
||||||
|
TranslateTimeline *timeline;
|
||||||
|
float timelineScale = 1;
|
||||||
|
if (timelineName == TIMELINE_SCALE)
|
||||||
|
timeline = new ScaleTimeline(values.size());
|
||||||
|
else {
|
||||||
|
timeline = new TranslateTimeline(values.size());
|
||||||
|
timelineScale = scale;
|
||||||
|
}
|
||||||
|
timeline->boneIndex = boneIndex;
|
||||||
|
|
||||||
|
int keyframeIndex = 0;
|
||||||
|
for (int i = 0; i < values.size(); i++) {
|
||||||
|
Json::Value valueMap = values[i];
|
||||||
|
|
||||||
|
float time = valueMap["time"].asDouble();
|
||||||
|
timeline->setKeyframe(keyframeIndex, //
|
||||||
|
valueMap["time"].asDouble(), //
|
||||||
|
valueMap.get("x", 0).asDouble() * timelineScale, //
|
||||||
|
valueMap.get("y", 0).asDouble() * timelineScale);
|
||||||
|
// readCurve(timeline, keyframeIndex, valueMap);
|
||||||
|
keyframeIndex++;
|
||||||
|
}
|
||||||
|
timelines.push_back(timeline);
|
||||||
|
if (timeline->getDuration() > duration) duration = timeline->getDuration();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw runtime_error("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Animation *animation = new Animation(timelines, duration);
|
||||||
|
return animation;
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace spine */
|
} /* namespace spine */
|
||||||
|
|||||||
@ -12,7 +12,8 @@ Slot::Slot (SlotData *data, BaseSkeleton *skeleton, Bone *bone) :
|
|||||||
g(1),
|
g(1),
|
||||||
b(1),
|
b(1),
|
||||||
a(1),
|
a(1),
|
||||||
attachment(0) {
|
attachment(0),
|
||||||
|
attachmentTime(0) {
|
||||||
if (!data) throw std::invalid_argument("data cannot be null.");
|
if (!data) throw std::invalid_argument("data cannot be null.");
|
||||||
if (!skeleton) throw std::invalid_argument("skeleton cannot be null.");
|
if (!skeleton) throw std::invalid_argument("skeleton cannot be null.");
|
||||||
if (!bone) throw std::invalid_argument("bone cannot be null.");
|
if (!bone) throw std::invalid_argument("bone cannot be null.");
|
||||||
|
|||||||
@ -35,9 +35,9 @@ public class Animation {
|
|||||||
|
|
||||||
if (loop && duration != 0) time %= duration;
|
if (loop && duration != 0) time %= duration;
|
||||||
|
|
||||||
Array<Timeline> timeline = this.timelines;
|
Array<Timeline> timelines = this.timelines;
|
||||||
for (int i = 0, n = timeline.size; i < n; i++)
|
for (int i = 0, n = timelines.size; i < n; i++)
|
||||||
timeline.get(i).apply(skeleton, time, 1);
|
timelines.get(i).apply(skeleton, time, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Poses the skeleton at the specified time for this animation mixed with the current pose.
|
/** Poses the skeleton at the specified time for this animation mixed with the current pose.
|
||||||
@ -47,9 +47,9 @@ public class Animation {
|
|||||||
|
|
||||||
if (loop && duration != 0) time %= duration;
|
if (loop && duration != 0) time %= duration;
|
||||||
|
|
||||||
Array<Timeline> timeline = this.timelines;
|
Array<Timeline> timelines = this.timelines;
|
||||||
for (int i = 0, n = timeline.size; i < n; i++)
|
for (int i = 0, n = timelines.size; i < n; i++)
|
||||||
timeline.get(i).apply(skeleton, time, alpha);
|
timelines.get(i).apply(skeleton, time, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param target After the first and before the last entry. */
|
/** @param target After the first and before the last entry. */
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
|||||||
abstract public class Attachment {
|
abstract public class Attachment {
|
||||||
final String name;
|
final String name;
|
||||||
boolean resolved;
|
boolean resolved;
|
||||||
private float x, y, scaleX, scaleY, rotation, width, height;
|
|
||||||
|
|
||||||
public Attachment (String name) {
|
public Attachment (String name) {
|
||||||
if (name == null) throw new IllegalArgumentException("name cannot be null.");
|
if (name == null) throw new IllegalArgumentException("name cannot be null.");
|
||||||
@ -17,62 +16,6 @@ abstract public class Attachment {
|
|||||||
|
|
||||||
abstract public void draw (SpriteBatch batch, Slot slot);
|
abstract public void draw (SpriteBatch batch, Slot slot);
|
||||||
|
|
||||||
public float getX () {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setX (float x) {
|
|
||||||
this.x = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getY () {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setY (float y) {
|
|
||||||
this.y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getScaleX () {
|
|
||||||
return scaleX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setScaleX (float scaleX) {
|
|
||||||
this.scaleX = scaleX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getScaleY () {
|
|
||||||
return scaleY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setScaleY (float scaleY) {
|
|
||||||
this.scaleY = scaleY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getRotation () {
|
|
||||||
return rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRotation (float rotation) {
|
|
||||||
this.rotation = rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getWidth () {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWidth (float width) {
|
|
||||||
this.width = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getHeight () {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHeight (float height) {
|
|
||||||
this.height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isResolved () {
|
public boolean isResolved () {
|
||||||
return resolved;
|
return resolved;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -149,13 +149,17 @@ public class SkeletonBinary {
|
|||||||
throw new SerializationException("Unknown attachment type: " + type + " (" + name + ")");
|
throw new SerializationException("Unknown attachment type: " + type + " (" + name + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
attachment.setX(input.readFloat() * scale);
|
if (attachment instanceof RegionAttachment) {
|
||||||
attachment.setY(input.readFloat() * scale);
|
RegionAttachment regionAttachment = (RegionAttachment)attachment;
|
||||||
attachment.setScaleX(input.readFloat());
|
regionAttachment.setX(input.readFloat() * scale);
|
||||||
attachment.setScaleY(input.readFloat());
|
regionAttachment.setY(input.readFloat() * scale);
|
||||||
attachment.setRotation(input.readFloat());
|
regionAttachment.setScaleX(input.readFloat());
|
||||||
attachment.setWidth(input.readFloat() * scale);
|
regionAttachment.setScaleY(input.readFloat());
|
||||||
attachment.setHeight(input.readFloat() * scale);
|
regionAttachment.setRotation(input.readFloat());
|
||||||
|
regionAttachment.setWidth(input.readFloat() * scale);
|
||||||
|
regionAttachment.setHeight(input.readFloat() * scale);
|
||||||
|
}
|
||||||
|
|
||||||
return attachment;
|
return attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -140,13 +140,17 @@ public class SkeletonJson {
|
|||||||
} else
|
} else
|
||||||
throw new SerializationException("Unknown attachment type: " + type + " (" + name + ")");
|
throw new SerializationException("Unknown attachment type: " + type + " (" + name + ")");
|
||||||
|
|
||||||
attachment.setX(getFloat(map, "x", 0) * scale);
|
if (attachment instanceof RegionAttachment) {
|
||||||
attachment.setY(getFloat(map, "y", 0) * scale);
|
RegionAttachment regionAttachment = (RegionAttachment)attachment;
|
||||||
attachment.setScaleX(getFloat(map, "scaleX", 1));
|
regionAttachment.setX(getFloat(map, "x", 0) * scale);
|
||||||
attachment.setScaleY(getFloat(map, "scaleY", 1));
|
regionAttachment.setY(getFloat(map, "y", 0) * scale);
|
||||||
attachment.setRotation(getFloat(map, "rotation", 0));
|
regionAttachment.setScaleX(getFloat(map, "scaleX", 1));
|
||||||
attachment.setWidth(getFloat(map, "width", 32) * scale);
|
regionAttachment.setScaleY(getFloat(map, "scaleY", 1));
|
||||||
attachment.setHeight(getFloat(map, "height", 32) * scale);
|
regionAttachment.setRotation(getFloat(map, "rotation", 0));
|
||||||
|
regionAttachment.setWidth(getFloat(map, "width", 32) * scale);
|
||||||
|
regionAttachment.setHeight(getFloat(map, "height", 32) * scale);
|
||||||
|
}
|
||||||
|
|
||||||
return attachment;
|
return attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,12 +174,12 @@ public class SkeletonJson {
|
|||||||
String boneName = entry.key;
|
String boneName = entry.key;
|
||||||
int boneIndex = skeletonData.findBoneIndex(boneName);
|
int boneIndex = skeletonData.findBoneIndex(boneName);
|
||||||
if (boneIndex == -1) throw new SerializationException("Bone not found: " + boneName);
|
if (boneIndex == -1) throw new SerializationException("Bone not found: " + boneName);
|
||||||
OrderedMap<?, ?> propertyMap = (OrderedMap)entry.value;
|
|
||||||
|
|
||||||
for (Entry propertyEntry : propertyMap.entries()) {
|
OrderedMap<?, ?> timelineMap = (OrderedMap)entry.value;
|
||||||
Array<OrderedMap> values = (Array)propertyEntry.value;
|
for (Entry timelineEntry : timelineMap.entries()) {
|
||||||
String timelineType = (String)propertyEntry.key;
|
Array<OrderedMap> values = (Array)timelineEntry.value;
|
||||||
if (timelineType.equals(TIMELINE_ROTATE)) {
|
String timelineName = (String)timelineEntry.key;
|
||||||
|
if (timelineName.equals(TIMELINE_ROTATE)) {
|
||||||
RotateTimeline timeline = new RotateTimeline(values.size);
|
RotateTimeline timeline = new RotateTimeline(values.size);
|
||||||
timeline.setBoneIndex(boneIndex);
|
timeline.setBoneIndex(boneIndex);
|
||||||
|
|
||||||
@ -189,10 +193,10 @@ public class SkeletonJson {
|
|||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
duration = Math.max(duration, timeline.getDuration());
|
duration = Math.max(duration, timeline.getDuration());
|
||||||
|
|
||||||
} else if (timelineType.equals(TIMELINE_TRANSLATE) || timelineType.equals(TIMELINE_SCALE)) {
|
} else if (timelineName.equals(TIMELINE_TRANSLATE) || timelineName.equals(TIMELINE_SCALE)) {
|
||||||
TranslateTimeline timeline;
|
TranslateTimeline timeline;
|
||||||
float timelineScale = 1;
|
float timelineScale = 1;
|
||||||
if (timelineType.equals(TIMELINE_SCALE))
|
if (timelineName.equals(TIMELINE_SCALE))
|
||||||
timeline = new ScaleTimeline(values.size);
|
timeline = new ScaleTimeline(values.size);
|
||||||
else {
|
else {
|
||||||
timeline = new TranslateTimeline(values.size);
|
timeline = new TranslateTimeline(values.size);
|
||||||
@ -213,7 +217,7 @@ public class SkeletonJson {
|
|||||||
duration = Math.max(duration, timeline.getDuration());
|
duration = Math.max(duration, timeline.getDuration());
|
||||||
|
|
||||||
} else
|
} else
|
||||||
throw new RuntimeException("Invalid timeline type for a bone: " + timelineType + " (" + boneName + ")");
|
throw new RuntimeException("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import com.badlogic.gdx.utils.NumberUtils;
|
|||||||
/** Attachment that displays a texture region. */
|
/** Attachment that displays a texture region. */
|
||||||
public class RegionAttachment extends Attachment {
|
public class RegionAttachment extends Attachment {
|
||||||
private TextureRegion region;
|
private TextureRegion region;
|
||||||
|
private float x, y, scaleX, scaleY, rotation, width, height;
|
||||||
private final float[] vertices = new float[20];
|
private final float[] vertices = new float[20];
|
||||||
private final float[] offset = new float[8];
|
private final float[] offset = new float[8];
|
||||||
|
|
||||||
@ -150,4 +151,60 @@ public class RegionAttachment extends Attachment {
|
|||||||
public float[] getWorldVertices () {
|
public float[] getWorldVertices () {
|
||||||
return vertices;
|
return vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getX () {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX (float x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getY () {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY (float y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getScaleX () {
|
||||||
|
return scaleX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScaleX (float scaleX) {
|
||||||
|
this.scaleX = scaleX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getScaleY () {
|
||||||
|
return scaleY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScaleY (float scaleY) {
|
||||||
|
this.scaleY = scaleY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getRotation () {
|
||||||
|
return rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRotation (float rotation) {
|
||||||
|
this.rotation = rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getWidth () {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWidth (float width) {
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getHeight () {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeight (float height) {
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user