Merge remote-tracking branch 'upstream/master'

Conflicts:
	spine-libgdx/.classpath
	spine-libgdx/test/com/esotericsoftware/spine/MixTest.java
	spine-libgdx/test/com/esotericsoftware/spine/SkeletonTest.java

*First Merge attempt.. may Gawd help us all.  -Disk1of5.
This commit is contained in:
Disk1of5 2013-03-15 11:58:48 -06:00
commit 3da5dcef69
39 changed files with 215 additions and 220 deletions

View File

@ -138,6 +138,7 @@ function Animation.RotateTimeline.new ()
local self = Animation.CurveTimeline.new() local self = Animation.CurveTimeline.new()
self.frames = {} self.frames = {}
self.boneIndex = -1
function self:getDuration () function self:getDuration ()
return self.frames[#self.frames - 1] return self.frames[#self.frames - 1]
@ -207,6 +208,7 @@ function Animation.TranslateTimeline.new ()
local self = Animation.CurveTimeline.new() local self = Animation.CurveTimeline.new()
self.frames = {} self.frames = {}
self.boneIndex = -1
function self:getDuration () function self:getDuration ()
return self.frames[#self.frames - 2] return self.frames[#self.frames - 2]
@ -297,6 +299,7 @@ function Animation.ColorTimeline.new ()
local self = Animation.CurveTimeline.new() local self = Animation.CurveTimeline.new()
self.frames = {} self.frames = {}
self.slotIndex = -1
function self:getDuration () function self:getDuration ()
return self.frames[#self.frames - 4] return self.frames[#self.frames - 4]
@ -360,6 +363,7 @@ function Animation.AttachmentTimeline.new ()
local self = Animation.CurveTimeline.new() local self = Animation.CurveTimeline.new()
self.frames = {} self.frames = {}
self.attachmentNames = {} self.attachmentNames = {}
self.slotName = nil
function self:getDuration () function self:getDuration ()
return self.frames[#self.frames] return self.frames[#self.frames]

View File

@ -143,11 +143,11 @@ function Skeleton.new (skeletonData, group)
if not attachmentName then error("attachmentName cannot be nil.", 2) end if not attachmentName then error("attachmentName cannot be nil.", 2) end
local slotIndex = self.data:findSlotIndex(slotName) local slotIndex = self.data:findSlotIndex(slotName)
if slotIndex == -1 then error("Slot not found: " .. slotName, 2) end if slotIndex == -1 then error("Slot not found: " .. slotName, 2) end
if self.skin then return self.skin:getAttachment(slotIndex, attachmentName) end
if self.data.defaultSkin then if self.data.defaultSkin then
local attachment = self.data.defaultSkin:getAttachment(slotIndex, attachmentName) local attachment = self.data.defaultSkin:getAttachment(slotIndex, attachmentName)
if attachment then return attachment end if attachment then return attachment end
end end
if self.skin then return self.skin:getAttachment(slotIndex, attachmentName) end
return nil return nil
end end

View File

@ -47,7 +47,7 @@ function Slot.new (slotData, skeleton, bone)
self:setAttachment(attachment) self:setAttachment(attachment)
end end
self:setColor(255, 255, 255, 255) self:setToBindPose()
return self return self
end end

View File

@ -31,7 +31,7 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/includes}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/includes}&quot;"/>
<listOptionValue builtIn="false" value="&quot;C:\Users\Nate\Desktop\SFML-2.0-rc\include&quot;"/> <listOptionValue builtIn="false" value="&quot;C:\Users\Nate\Desktop\SFML-2.0-rc\include&quot;"/>
</option> </option>
<option id="gnu.cpp.compiler.option.warnings.allwarn.2053349441" name="All warnings (-Wall)" superClass="gnu.cpp.compiler.option.warnings.allwarn" value="false" valueType="boolean"/> <option id="gnu.cpp.compiler.option.warnings.allwarn.2053349441" name="All warnings (-Wall)" superClass="gnu.cpp.compiler.option.warnings.allwarn" value="true" valueType="boolean"/>
<option id="gnu.cpp.compiler.option.preprocessor.def.1463772359" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def"/> <option id="gnu.cpp.compiler.option.preprocessor.def.1463772359" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def"/>
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1445618618" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1445618618" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool> </tool>

View File

@ -274,27 +274,5 @@
{ "time": 1.0666, "angle": 3.6 } { "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" }
]
}
} }
} }

View File

@ -8,9 +8,7 @@ namespace spine {
class AtlasPage: public BaseAtlasPage { class AtlasPage: public BaseAtlasPage {
public: public:
~AtlasPage(){ ~AtlasPage ();
delete texture;
}
sf::Texture *texture; sf::Texture *texture;
}; };
@ -34,7 +32,7 @@ public:
AtlasRegion* findRegion (const std::string &name); AtlasRegion* findRegion (const std::string &name);
private: private:
virtual BaseAtlasPage* newAtlasPage (std::string name); virtual BaseAtlasPage* newAtlasPage (const std::string &name);
virtual BaseAtlasRegion* newAtlasRegion (BaseAtlasPage* page); virtual BaseAtlasRegion* newAtlasRegion (BaseAtlasPage* page);
}; };

View File

@ -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; // BOZO - This is ugly. Support multiple textures? sf::Texture *texture; // This is a bit ugly and means all region attachments must use the same textures.
Skeleton (SkeletonData *skeletonData); Skeleton (SkeletonData *skeletonData);

View File

@ -10,6 +10,7 @@ class Atlas;
class SkeletonJson: public BaseSkeletonJson { class SkeletonJson: public BaseSkeletonJson {
public: public:
SkeletonJson (Atlas *atlas); SkeletonJson (Atlas *atlas);
/** The SkeletonJson owns the attachmentLoader */
SkeletonJson (BaseAttachmentLoader *attachmentLoader); SkeletonJson (BaseAttachmentLoader *attachmentLoader);
}; };

View File

@ -15,10 +15,10 @@ public:
float duration; float duration;
Animation (const std::vector<Timeline*> &timelines, float duration); Animation (const std::vector<Timeline*> &timelines, float duration);
~Animation(); ~Animation ();
void apply (BaseSkeleton *skeleton, float time, bool loop); void apply (BaseSkeleton *skeleton, float time, bool loop) const;
void mix (BaseSkeleton *skeleton, float time, bool loop, float alpha); void mix (BaseSkeleton *skeleton, float time, bool loop, float alpha) const;
}; };
// //
@ -28,11 +28,11 @@ public:
virtual ~Timeline () { virtual ~Timeline () {
} }
virtual float getDuration () = 0; virtual float getDuration () const = 0;
virtual int getKeyframeCount () = 0; virtual int getKeyframeCount () const = 0;
virtual void apply (BaseSkeleton *skeleton, float time, float alpha) = 0; virtual void apply (BaseSkeleton *skeleton, float time, float alpha) const = 0;
}; };
// //
@ -53,7 +53,7 @@ public:
* the difference between the keyframe's values. */ * the difference between the keyframe's values. */
void setCurve (int keyframeIndex, float cx1, float cy1, float cx2, float cy2); void setCurve (int keyframeIndex, float cx1, float cy1, float cx2, float cy2);
float getCurvePercent (int keyframeIndex, float percent); float getCurvePercent (int keyframeIndex, float percent) const;
}; };
// //
@ -67,9 +67,9 @@ public:
RotateTimeline (int keyframeCount); RotateTimeline (int keyframeCount);
virtual ~RotateTimeline (); virtual ~RotateTimeline ();
virtual float getDuration (); virtual float getDuration () const;
virtual int getKeyframeCount (); virtual int getKeyframeCount () const;
virtual void apply (BaseSkeleton *skeleton, float time, float alpha); virtual void apply (BaseSkeleton *skeleton, float time, float alpha) const;
void setKeyframe (int keyframeIndex, float time, float value); void setKeyframe (int keyframeIndex, float time, float value);
}; };
@ -85,9 +85,9 @@ public:
TranslateTimeline (int keyframeCount); TranslateTimeline (int keyframeCount);
virtual ~TranslateTimeline (); virtual ~TranslateTimeline ();
virtual float getDuration (); virtual float getDuration () const;
virtual int getKeyframeCount (); virtual int getKeyframeCount () const;
virtual void apply (BaseSkeleton *skeleton, float time, float alpha); virtual void apply (BaseSkeleton *skeleton, float time, float alpha) const;
void setKeyframe (int keyframeIndex, float time, float x, float y); void setKeyframe (int keyframeIndex, float time, float x, float y);
}; };
@ -98,7 +98,7 @@ class ScaleTimeline: public TranslateTimeline {
public: public:
ScaleTimeline (int keyframeCount); ScaleTimeline (int keyframeCount);
virtual void apply (BaseSkeleton *skeleton, float time, float alpha); virtual void apply (BaseSkeleton *skeleton, float time, float alpha) const;
}; };
// //
@ -112,9 +112,9 @@ public:
ColorTimeline (int keyframeCount); ColorTimeline (int keyframeCount);
virtual ~ColorTimeline (); virtual ~ColorTimeline ();
virtual float getDuration (); virtual float getDuration () const;
virtual int getKeyframeCount (); virtual int getKeyframeCount () const;
virtual void apply (BaseSkeleton *skeleton, float time, float alpha); virtual void apply (BaseSkeleton *skeleton, float time, float alpha) const;
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);
}; };
@ -131,12 +131,13 @@ public:
AttachmentTimeline (int keyframeCount); AttachmentTimeline (int keyframeCount);
virtual ~AttachmentTimeline (); virtual ~AttachmentTimeline ();
virtual float getDuration (); virtual float getDuration () const;
virtual int getKeyframeCount (); virtual int getKeyframeCount () const;
virtual void apply (BaseSkeleton *skeleton, float time, float alpha); virtual void apply (BaseSkeleton *skeleton, float time, float alpha) const;
/** @param attachmentName Pass an empty string to clear the image for a slot. */ /** The AttachmentTimeline owns the attachmentName.
void setKeyframe (int keyframeIndex, float time, const std::string &attachmentName); * @param attachmentName May be null to clear the image for a slot. */
void setKeyframe (int keyframeIndex, float time, std::string *attachmentName);
}; };
} /* namespace spine */ } /* namespace spine */

View File

@ -4,7 +4,6 @@
#include <istream> #include <istream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <map>
namespace spine { namespace spine {
@ -26,7 +25,7 @@ public:
virtual BaseAtlasRegion* findRegion (const std::string &name); virtual BaseAtlasRegion* findRegion (const std::string &name);
private: private:
virtual BaseAtlasPage* newAtlasPage (std::string name) = 0; virtual BaseAtlasPage* newAtlasPage (const std::string &name) = 0;
virtual BaseAtlasRegion* newAtlasRegion (BaseAtlasPage *page) = 0; virtual BaseAtlasRegion* newAtlasRegion (BaseAtlasPage *page) = 0;
}; };
@ -71,7 +70,7 @@ public:
int *splits; int *splits;
int *pads; int *pads;
BaseAtlasRegion() : splits(0), pads(0) {} BaseAtlasRegion ();
virtual ~BaseAtlasRegion (); virtual ~BaseAtlasRegion ();
}; };

View File

@ -1,10 +1,10 @@
#ifndef SPINE_BASEATTACHMENTLOADER_H_ #ifndef SPINE_BASEATTACHMENTLOADER_H_
#define SPINE_BASEATTACHMENTLOADER_H_ #define SPINE_BASEATTACHMENTLOADER_H_
#include <spine/Attachment.h>
namespace spine { namespace spine {
class Attachment;
enum AttachmentType { enum AttachmentType {
region, regionSequence region, regionSequence
}; };

View File

@ -23,6 +23,7 @@ public:
float time; float time;
bool flipX, flipY; bool flipX, flipY;
/** The BaseSkeleton owns the SkeletonData. */
BaseSkeleton (SkeletonData *data); BaseSkeleton (SkeletonData *data);
virtual ~BaseSkeleton (); virtual ~BaseSkeleton ();
@ -40,10 +41,11 @@ public:
int findSlotIndex (const std::string &slotName) const; int findSlotIndex (const std::string &slotName) const;
void setSkin (const std::string &skinName); void setSkin (const std::string &skinName);
void setSkin (Skin *newSkin); /** @param skin May be null. */
void setSkin (Skin *skin);
Attachment* getAttachment (const std::string &slotName, const std::string &attachmentName); Attachment* getAttachment (const std::string &slotName, const std::string &attachmentName) const;
Attachment* getAttachment (int slotIndex, const std::string &attachmentName); Attachment* getAttachment (int slotIndex, const std::string &attachmentName) const;
void setAttachment (const std::string &slotName, const std::string &attachmentName); void setAttachment (const std::string &slotName, const std::string &attachmentName);
}; };

View File

@ -13,8 +13,9 @@ class BaseSkeletonJson {
public: public:
BaseAttachmentLoader *attachmentLoader; BaseAttachmentLoader *attachmentLoader;
float scale; float scale;
bool flipY; bool yDown;
/** The BaseSkeletonJson owns the attachmentLoader. */
BaseSkeletonJson (BaseAttachmentLoader *attachmentLoader); BaseSkeletonJson (BaseAttachmentLoader *attachmentLoader);
virtual ~BaseSkeletonJson (); virtual ~BaseSkeletonJson ();

View File

@ -8,6 +8,7 @@ class BoneData;
class Bone { class Bone {
public: public:
BoneData *data; BoneData *data;
/** May be null. */
Bone *parent; Bone *parent;
float x, y; float x, y;
float rotation; float rotation;

View File

@ -13,7 +13,7 @@ public:
float x, y; float x, y;
float rotation; float rotation;
float scaleX, scaleY; float scaleX, scaleY;
float flipY; float yDown;
BoneData (const std::string &name) : BoneData (const std::string &name) :
name(name), name(name),
@ -24,7 +24,7 @@ public:
rotation(0), rotation(0),
scaleX(1), scaleX(1),
scaleY(1), scaleY(1),
flipY(false) { yDown(false) {
} }
}; };

View File

@ -12,9 +12,13 @@ class Skin;
class SkeletonData { class SkeletonData {
public: public:
/** The SkeletonData owns the bones. */
std::vector<BoneData*> bones; std::vector<BoneData*> bones;
/** The SkeletonData owns the slots. */
std::vector<SlotData*> slots; std::vector<SlotData*> slots;
/** The SkeletonData owns the skins. */
std::vector<Skin*> skins; std::vector<Skin*> skins;
/** May be null. */
Skin *defaultSkin; Skin *defaultSkin;
SkeletonData (); SkeletonData ();
@ -26,7 +30,7 @@ public:
SlotData* findSlot (const std::string &slotName) const; SlotData* findSlot (const std::string &slotName) const;
int findSlotIndex (const std::string &slotName) const; int findSlotIndex (const std::string &slotName) const;
Skin* findSkin (const std::string &skinName); Skin* findSkin (const std::string &skinName) const;
}; };
} /* namespace spine */ } /* namespace spine */

View File

@ -3,11 +3,11 @@
#include <string> #include <string>
#include <map> #include <map>
#include <spine/Attachment.h>
namespace spine { namespace spine {
class BaseSkeleton; class BaseSkeleton;
class Attachment;
class Skin { class Skin {
friend class BaseSkeleton; friend class BaseSkeleton;
@ -31,8 +31,9 @@ public:
std::string name; std::string name;
Skin (const std::string &name); Skin (const std::string &name);
~Skin(); ~Skin ();
/** The Skin owns the attachment. */
void addAttachment (int slotIndex, const std::string &name, Attachment *attachment); void addAttachment (int slotIndex, const std::string &name, Attachment *attachment);
Attachment* getAttachment (int slotIndex, const std::string &name); Attachment* getAttachment (int slotIndex, const std::string &name);

View File

@ -25,6 +25,7 @@ public:
Slot (SlotData *data, BaseSkeleton *skeleton, Bone *bone); Slot (SlotData *data, BaseSkeleton *skeleton, Bone *bone);
/** @param attachment May be null. */
void setAttachment (Attachment *attachment); void setAttachment (Attachment *attachment);
void setAttachmentTime (float time); void setAttachmentTime (float time);

View File

@ -2,7 +2,6 @@
#define SPINE_SLOTDATA_H_ #define SPINE_SLOTDATA_H_
#include <string> #include <string>
#include <stdexcept>
namespace spine { namespace spine {
@ -15,23 +14,8 @@ public:
float r, g, b, a; float r, g, b, a;
std::string *attachmentName; std::string *attachmentName;
SlotData (const std::string &name, BoneData *boneData) : SlotData (const std::string &name, BoneData *boneData);
name(name), ~SlotData ();
boneData(boneData),
r(1),
g(1),
b(1),
a(1),
attachmentName(0) {
if (!boneData) throw std::invalid_argument("boneData cannot be null.");
}
~SlotData () {
if (attachmentName) {
delete attachmentName;
attachmentName = 0;
}
}
}; };
} /* namespace spine */ } /* namespace spine */

View File

@ -3,6 +3,12 @@
namespace spine { namespace spine {
AtlasPage::~AtlasPage () {
delete texture;
}
//
Atlas::Atlas (std::ifstream &file) { Atlas::Atlas (std::ifstream &file) {
load(file); load(file);
} }
@ -19,7 +25,7 @@ Atlas::Atlas (const char *begin, const char *end) {
load(begin, end); load(begin, end);
} }
BaseAtlasPage* Atlas::newAtlasPage (std::string name) { BaseAtlasPage* Atlas::newAtlasPage (const std::string &name) {
AtlasPage *page = new AtlasPage(); AtlasPage *page = new AtlasPage();
page->texture = new sf::Texture(); page->texture = new sf::Texture();
page->texture->loadFromFile(name); page->texture->loadFromFile(name);

View File

@ -9,7 +9,7 @@
namespace spine { namespace spine {
RegionAttachment::RegionAttachment (AtlasRegion *region) { RegionAttachment::RegionAttachment (AtlasRegion *region) {
texture = region->page->texture; // BOZO - Resolve attachment as late as possible? texture = region->page->texture;
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;
@ -59,9 +59,9 @@ void RegionAttachment::draw (Slot *slot) {
vertices[3].color.b = b; vertices[3].color.b = b;
vertices[3].color.a = a; vertices[3].color.a = a;
updateOffset(); // BOZO - Move to resolve()?
updateWorldVertices(slot->bone); updateWorldVertices(slot->bone);
// SMFL doesn't handle batching for us, so we'll just force a single texture per skeleton.
skeleton->texture = texture; skeleton->texture = texture;
skeleton->vertexArray.append(vertices[0]); skeleton->vertexArray.append(vertices[0]);
skeleton->vertexArray.append(vertices[1]); skeleton->vertexArray.append(vertices[1]);

View File

@ -5,12 +5,12 @@ namespace spine {
SkeletonJson::SkeletonJson (BaseAttachmentLoader *attachmentLoader) : SkeletonJson::SkeletonJson (BaseAttachmentLoader *attachmentLoader) :
BaseSkeletonJson(attachmentLoader) { BaseSkeletonJson(attachmentLoader) {
flipY = true; yDown = true;
} }
SkeletonJson::SkeletonJson (Atlas *atlas) : SkeletonJson::SkeletonJson (Atlas *atlas) :
BaseSkeletonJson(new AtlasAttachmentLoader(atlas)) { BaseSkeletonJson(new AtlasAttachmentLoader(atlas)) {
flipY = true; yDown = true;
} }
} /* namespace spine */ } /* namespace spine */

View File

@ -18,26 +18,19 @@ Animation::Animation (const vector<Timeline*> &timelines, float duration) :
duration(duration) { duration(duration) {
} }
Animation::~Animation() Animation::~Animation () {
{ for (int i = 0, n = timelines.size(); i < n; i++)
for (std::vector<Timeline*>::iterator iter = timelines.begin(); iter != timelines.end(); ++iter) delete timelines[i];
{
delete *iter;
}
} }
void Animation::apply (BaseSkeleton *skeleton, float time, bool loop) { void Animation::apply (BaseSkeleton *skeleton, float time, bool loop) const {
if (!skeleton) throw std::invalid_argument("skeleton cannot be null.");
if (loop && duration) time = fmodf(time, duration); if (loop && duration) time = fmodf(time, duration);
for (int i = 0, n = timelines.size(); i < n; i++) for (int i = 0, n = timelines.size(); i < n; i++)
timelines[i]->apply(skeleton, time, 1); timelines[i]->apply(skeleton, time, 1);
} }
void Animation::mix (BaseSkeleton *skeleton, float time, bool loop, float alpha) { void Animation::mix (BaseSkeleton *skeleton, float time, bool loop, float alpha) const {
if (!skeleton) throw std::invalid_argument("skeleton cannot be null.");
if (loop && duration) time = fmodf(time, duration); if (loop && duration) time = fmodf(time, duration);
for (int i = 0, n = timelines.size(); i < n; i++) for (int i = 0, n = timelines.size(); i < n; i++)
@ -88,7 +81,7 @@ void CurveTimeline::setCurve (int keyframeIndex, float cx1, float cy1, float cx2
curves[i + 5] = tmp2y * pre5; curves[i + 5] = tmp2y * pre5;
} }
float CurveTimeline::getCurvePercent (int keyframeIndex, float percent) { float CurveTimeline::getCurvePercent (int keyframeIndex, float percent) const {
int curveIndex = keyframeIndex * 6; int curveIndex = keyframeIndex * 6;
float dfx = curves[curveIndex]; float dfx = curves[curveIndex];
if (dfx == LINEAR) return percent; if (dfx == LINEAR) return percent;
@ -162,11 +155,11 @@ RotateTimeline::~RotateTimeline () {
delete[] frames; delete[] frames;
} }
float RotateTimeline::getDuration () { float RotateTimeline::getDuration () const {
return frames[framesLength - 2]; return frames[framesLength - 2];
} }
int RotateTimeline::getKeyframeCount () { int RotateTimeline::getKeyframeCount () const {
return framesLength / 2; return framesLength / 2;
} }
@ -176,7 +169,7 @@ void RotateTimeline::setKeyframe (int keyframeIndex, float time, float value) {
frames[keyframeIndex + 1] = value; frames[keyframeIndex + 1] = value;
} }
void RotateTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) { void RotateTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) const {
if (time < frames[0]) return; // Time is before first frame. if (time < frames[0]) return; // Time is before first frame.
Bone *bone = skeleton->bones[boneIndex]; Bone *bone = skeleton->bones[boneIndex];
@ -233,11 +226,11 @@ TranslateTimeline::~TranslateTimeline () {
delete[] frames; delete[] frames;
} }
float TranslateTimeline::getDuration () { float TranslateTimeline::getDuration () const {
return frames[framesLength - 3]; return frames[framesLength - 3];
} }
int TranslateTimeline::getKeyframeCount () { int TranslateTimeline::getKeyframeCount () const {
return framesLength / 3; return framesLength / 3;
} }
@ -248,7 +241,7 @@ void TranslateTimeline::setKeyframe (int keyframeIndex, float time, float x, flo
frames[keyframeIndex + 2] = y; frames[keyframeIndex + 2] = y;
} }
void TranslateTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) { void TranslateTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) const {
if (time < frames[0]) return; // Time is before first frame. if (time < frames[0]) return; // Time is before first frame.
Bone *bone = skeleton->bones[boneIndex]; Bone *bone = skeleton->bones[boneIndex];
@ -281,7 +274,7 @@ ScaleTimeline::ScaleTimeline (int keyframeCount) :
TranslateTimeline(keyframeCount) { TranslateTimeline(keyframeCount) {
} }
void ScaleTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) { void ScaleTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) const {
if (time < frames[0]) return; // Time is before first frame. if (time < frames[0]) return; // Time is before first frame.
Bone *bone = skeleton->bones[boneIndex]; Bone *bone = skeleton->bones[boneIndex];
@ -329,11 +322,11 @@ ColorTimeline::~ColorTimeline () {
delete[] frames; delete[] frames;
} }
float ColorTimeline::getDuration () { float ColorTimeline::getDuration () const {
return frames[framesLength - 5]; return frames[framesLength - 5];
} }
int ColorTimeline::getKeyframeCount () { int ColorTimeline::getKeyframeCount () const {
return framesLength / 5; return framesLength / 5;
} }
@ -346,7 +339,7 @@ void ColorTimeline::setKeyframe (int keyframeIndex, float time, float r, float g
frames[keyframeIndex + 4] = a; frames[keyframeIndex + 4] = a;
} }
void ColorTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) { void ColorTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) const {
if (time < frames[0]) return; // Time is before first frame. if (time < frames[0]) return; // Time is before first frame.
Slot *slot = skeleton->slots[slotIndex]; Slot *slot = skeleton->slots[slotIndex];
@ -410,21 +403,21 @@ AttachmentTimeline::~AttachmentTimeline () {
delete[] attachmentNames; delete[] attachmentNames;
} }
float AttachmentTimeline::getDuration () { float AttachmentTimeline::getDuration () const {
return frames[framesLength - 1]; return frames[framesLength - 1];
} }
int AttachmentTimeline::getKeyframeCount () { int AttachmentTimeline::getKeyframeCount () const {
return framesLength; return framesLength;
} }
void AttachmentTimeline::setKeyframe (int keyframeIndex, float time, const string &attachmentName) { void AttachmentTimeline::setKeyframe (int keyframeIndex, float time, string *attachmentName) {
frames[keyframeIndex] = time; frames[keyframeIndex] = time;
if (attachmentNames[keyframeIndex]) delete attachmentNames[keyframeIndex]; if (attachmentNames[keyframeIndex]) delete attachmentNames[keyframeIndex];
attachmentNames[keyframeIndex] = attachmentName.length() == 0 ? 0 : new string(attachmentName); attachmentNames[keyframeIndex] = attachmentName;
} }
void AttachmentTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) { void AttachmentTimeline::apply (BaseSkeleton *skeleton, float time, float alpha) const {
if (time < frames[0]) return; // Time is before first frame. if (time < frames[0]) return; // Time is before first frame.
int frameIndex; int frameIndex;

View File

@ -105,7 +105,7 @@ void BaseAtlas::load (const char *current, const char *end) {
string value; string value;
string tuple[4]; string tuple[4];
BaseAtlasPage *page = NULL; BaseAtlasPage *page = 0;
while (current != end) { while (current != end) {
readLine(current, end, value); readLine(current, end, value);
trim(value); trim(value);
@ -185,6 +185,11 @@ BaseAtlasRegion* BaseAtlas::findRegion (const std::string &name) {
// //
BaseAtlasRegion::BaseAtlasRegion () :
splits(0),
pads(0) {
}
BaseAtlasRegion::~BaseAtlasRegion () { BaseAtlasRegion::~BaseAtlasRegion () {
if (splits) delete splits; if (splits) delete splits;
if (pads) delete pads; if (pads) delete pads;

View File

@ -1,8 +1,8 @@
#include <math.h> #include <math.h>
#include <spine/BaseRegionAttachment.h> #include <spine/BaseRegionAttachment.h>
#ifndef M_PI // fix for windows removing precious information #ifndef M_PI
#define M_PI 3.14159265358979323846 #define M_PI 3.1415926535897932385
#endif #endif
namespace spine { namespace spine {

View File

@ -1,3 +1,4 @@
#include <stdexcept>
#include <iostream> #include <iostream>
#include <spine/BaseSkeleton.h> #include <spine/BaseSkeleton.h>
#include <spine/SkeletonData.h> #include <spine/SkeletonData.h>
@ -92,25 +93,25 @@ Bone* BaseSkeleton::getRootBone () const {
} }
Bone* BaseSkeleton::findBone (const string &boneName) const { Bone* BaseSkeleton::findBone (const string &boneName) const {
for (unsigned int i = 0; i < bones.size(); i++) for (int i = 0, n = bones.size(); i < n; i++)
if (data->bones[i]->name == boneName) return bones[i]; if (data->bones[i]->name == boneName) return bones[i];
return 0; return 0;
} }
int BaseSkeleton::findBoneIndex (const string &boneName) const { int BaseSkeleton::findBoneIndex (const string &boneName) const {
for (unsigned int i = 0; i < bones.size(); i++) for (int i = 0, n = bones.size(); i < n; i++)
if (data->bones[i]->name == boneName) return i; if (data->bones[i]->name == boneName) return i;
return -1; return -1;
} }
Slot* BaseSkeleton::findSlot (const string &slotName) const { Slot* BaseSkeleton::findSlot (const string &slotName) const {
for (unsigned int i = 0; i < slots.size(); i++) for (int i = 0, n = slots.size(); i < n; i++)
if (data->slots[i]->name == slotName) return slots[i]; if (data->slots[i]->name == slotName) return slots[i];
return 0; return 0;
} }
int BaseSkeleton::findSlotIndex (const string &slotName) const { int BaseSkeleton::findSlotIndex (const string &slotName) const {
for (unsigned int i = 0; i < slots.size(); i++) for (int i = 0, n = slots.size(); i < n; i++)
if (data->slots[i]->name == slotName) return i; if (data->slots[i]->name == slotName) return i;
return -1; return -1;
} }
@ -126,16 +127,16 @@ void BaseSkeleton::setSkin (Skin *newSkin) {
skin = newSkin; skin = newSkin;
} }
Attachment* BaseSkeleton::getAttachment (const string &slotName, const string &attachmentName) { Attachment* BaseSkeleton::getAttachment (const string &slotName, const string &attachmentName) const {
return getAttachment(data->findSlotIndex(slotName), attachmentName); return getAttachment(data->findSlotIndex(slotName), attachmentName);
} }
Attachment* BaseSkeleton::getAttachment (int slotIndex, const string &attachmentName) { Attachment* BaseSkeleton::getAttachment (int slotIndex, const string &attachmentName) const {
if (skin) return skin->getAttachment(slotIndex, attachmentName);
if (data->defaultSkin) { if (data->defaultSkin) {
Attachment *attachment = data->defaultSkin->getAttachment(slotIndex, attachmentName); Attachment *attachment = data->defaultSkin->getAttachment(slotIndex, attachmentName);
if (attachment) return attachment; if (attachment) return attachment;
} }
if (skin) return skin->getAttachment(slotIndex, attachmentName);
return 0; return 0;
} }

View File

@ -32,12 +32,12 @@ static float toColor (const string &value, int index) {
BaseSkeletonJson::BaseSkeletonJson (BaseAttachmentLoader *attachmentLoader) : BaseSkeletonJson::BaseSkeletonJson (BaseAttachmentLoader *attachmentLoader) :
attachmentLoader(attachmentLoader), attachmentLoader(attachmentLoader),
scale(1), scale(1),
flipY(false) { yDown(false) {
if (!attachmentLoader) throw invalid_argument("attachmentLoader cannot be null.");
} }
BaseSkeletonJson::~BaseSkeletonJson () { BaseSkeletonJson::~BaseSkeletonJson () {
if (attachmentLoader) delete attachmentLoader;
delete attachmentLoader;
} }
SkeletonData* BaseSkeletonJson::readSkeletonData (std::ifstream &file) const { SkeletonData* BaseSkeletonJson::readSkeletonData (std::ifstream &file) const {
@ -76,7 +76,7 @@ SkeletonData* BaseSkeletonJson::readSkeletonData (const char *begin, const char
Json::Value bones = root["bones"]; Json::Value bones = root["bones"];
skeletonData->bones.reserve(bones.size()); skeletonData->bones.reserve(bones.size());
for (unsigned int i = 0; i < bones.size(); ++i) { for (int i = 0, n = bones.size(); i < n; ++i) {
Json::Value boneMap = bones[i]; Json::Value boneMap = bones[i];
string boneName = boneMap["name"].asString(); string boneName = boneMap["name"].asString();
@ -92,7 +92,7 @@ SkeletonData* BaseSkeletonJson::readSkeletonData (const char *begin, const char
boneData->rotation = (float)(boneMap.get("rotation", 0).asDouble()); boneData->rotation = (float)(boneMap.get("rotation", 0).asDouble());
boneData->scaleX = (float)(boneMap.get("scaleX", 1).asDouble()); boneData->scaleX = (float)(boneMap.get("scaleX", 1).asDouble());
boneData->scaleY = (float)(boneMap.get("scaleY", 1).asDouble()); boneData->scaleY = (float)(boneMap.get("scaleY", 1).asDouble());
boneData->flipY = flipY; boneData->yDown = yDown;
skeletonData->bones.push_back(boneData); skeletonData->bones.push_back(boneData);
} }
@ -100,7 +100,7 @@ SkeletonData* BaseSkeletonJson::readSkeletonData (const char *begin, const char
Json::Value slots = root["slots"]; Json::Value slots = root["slots"];
if (!slots.isNull()) { if (!slots.isNull()) {
skeletonData->slots.reserve(slots.size()); skeletonData->slots.reserve(slots.size());
for (unsigned int i = 0; i < slots.size(); ++i) { for (int i = 0, n = slots.size(); i < n; ++i) {
Json::Value slotMap = slots[i]; Json::Value slotMap = slots[i];
string slotName = slotMap["name"].asString(); string slotName = slotMap["name"].asString();
@ -128,7 +128,7 @@ SkeletonData* BaseSkeletonJson::readSkeletonData (const char *begin, const char
Json::Value skinsMap = root["skins"]; Json::Value skinsMap = root["skins"];
vector<string> skinNames = skinsMap.getMemberNames(); vector<string> skinNames = skinsMap.getMemberNames();
skeletonData->skins.reserve(skinNames.size()); skeletonData->skins.reserve(skinNames.size());
for (unsigned int i = 0; i < skinNames.size(); i++) { for (int i = 0, n = skinNames.size(); i < n; i++) {
string skinName = skinNames[i]; string skinName = skinNames[i];
Skin *skin = new Skin(skinName); Skin *skin = new Skin(skinName);
skeletonData->skins.push_back(skin); skeletonData->skins.push_back(skin);
@ -136,13 +136,13 @@ SkeletonData* BaseSkeletonJson::readSkeletonData (const char *begin, const char
Json::Value slotMap = skinsMap[skinName]; Json::Value slotMap = skinsMap[skinName];
vector<string> slotNames = slotMap.getMemberNames(); vector<string> slotNames = slotMap.getMemberNames();
for (unsigned int i = 0; i < slotNames.size(); i++) { for (int i = 0, n = slotNames.size(); i < n; i++) {
string slotName = slotNames[i]; string slotName = slotNames[i];
int slotIndex = skeletonData->findSlotIndex(slotName); int slotIndex = skeletonData->findSlotIndex(slotName);
Json::Value attachmentsMap = slotMap[slotName]; Json::Value attachmentsMap = slotMap[slotName];
vector<string> attachmentNames = attachmentsMap.getMemberNames(); vector<string> attachmentNames = attachmentsMap.getMemberNames();
for (unsigned int i = 0; i < attachmentNames.size(); i++) { for (int i = 0, n = attachmentNames.size(); i < n; i++) {
string attachmentName = attachmentNames[i]; string attachmentName = attachmentNames[i];
Json::Value attachmentMap = attachmentsMap[attachmentName]; Json::Value attachmentMap = attachmentsMap[attachmentName];
@ -167,6 +167,7 @@ SkeletonData* BaseSkeletonJson::readSkeletonData (const char *begin, const char
regionAttachment->rotation = (float)(attachmentMap.get("rotation", 0).asDouble()); regionAttachment->rotation = (float)(attachmentMap.get("rotation", 0).asDouble());
regionAttachment->width = (float)(attachmentMap.get("width", 32).asDouble() * scale); regionAttachment->width = (float)(attachmentMap.get("width", 32).asDouble() * scale);
regionAttachment->height = (float)(attachmentMap.get("height", 32).asDouble() * scale); regionAttachment->height = (float)(attachmentMap.get("height", 32).asDouble() * scale);
regionAttachment->updateOffset();
} }
skin->addAttachment(slotIndex, attachmentName, attachment); skin->addAttachment(slotIndex, attachmentName, attachment);
@ -205,7 +206,8 @@ static void readCurve (CurveTimeline *timeline, int keyframeIndex, const Json::V
if (curve.isString() && curve.asString() == "stepped") if (curve.isString() && curve.asString() == "stepped")
timeline->setStepped(keyframeIndex); timeline->setStepped(keyframeIndex);
else if (curve.isArray()) else if (curve.isArray())
timeline->setCurve(keyframeIndex, (float)curve[0u].asDouble(), (float)curve[1u].asDouble(), (float)curve[2u].asDouble(), (float)curve[3u].asDouble()); timeline->setCurve(keyframeIndex, (float)curve[0u].asDouble(), (float)curve[1u].asDouble(), (float)curve[2u].asDouble(),
(float)curve[3u].asDouble());
} }
Animation* BaseSkeletonJson::readAnimation (const char *begin, const char *end, const SkeletonData *skeletonData) const { Animation* BaseSkeletonJson::readAnimation (const char *begin, const char *end, const SkeletonData *skeletonData) const {
@ -229,14 +231,14 @@ Animation* BaseSkeletonJson::readAnimation (const char *begin, const char *end,
Json::Value bones = root["bones"]; Json::Value bones = root["bones"];
vector<string> boneNames = bones.getMemberNames(); vector<string> boneNames = bones.getMemberNames();
for (unsigned int i = 0; i < boneNames.size(); i++) { for (int i = 0, n = boneNames.size(); i < n; i++) {
string boneName = boneNames[i]; string boneName = boneNames[i];
int boneIndex = skeletonData->findBoneIndex(boneName); int boneIndex = skeletonData->findBoneIndex(boneName);
if (boneIndex == -1) throw runtime_error("Bone not found: " + boneName); if (boneIndex == -1) throw runtime_error("Bone not found: " + boneName);
Json::Value timelineMap = bones[boneName]; Json::Value timelineMap = bones[boneName];
vector<string> timelineNames = timelineMap.getMemberNames(); vector<string> timelineNames = timelineMap.getMemberNames();
for (unsigned int i = 0; i < timelineNames.size(); i++) { for (int i = 0, n = timelineNames.size(); i < n; i++) {
string timelineName = timelineNames[i]; string timelineName = timelineNames[i];
Json::Value values = timelineMap[timelineName]; Json::Value values = timelineMap[timelineName];
@ -245,7 +247,7 @@ Animation* BaseSkeletonJson::readAnimation (const char *begin, const char *end,
timeline->boneIndex = boneIndex; timeline->boneIndex = boneIndex;
int keyframeIndex = 0; int keyframeIndex = 0;
for (unsigned int i = 0; i < values.size(); i++) { for (int i = 0, n = values.size(); i < n; i++) {
Json::Value valueMap = values[i]; Json::Value valueMap = values[i];
float time = (float)valueMap["time"].asDouble(); float time = (float)valueMap["time"].asDouble();
@ -268,10 +270,9 @@ Animation* BaseSkeletonJson::readAnimation (const char *begin, const char *end,
timeline->boneIndex = boneIndex; timeline->boneIndex = boneIndex;
int keyframeIndex = 0; int keyframeIndex = 0;
for (unsigned int i = 0; i < values.size(); i++) { for (int i = 0, n = values.size(); i < n; i++) {
Json::Value valueMap = values[i]; Json::Value valueMap = values[i];
float time = (float)valueMap["time"].asDouble();
timeline->setKeyframe(keyframeIndex, // timeline->setKeyframe(keyframeIndex, //
(float)valueMap["time"].asDouble(), // (float)valueMap["time"].asDouble(), //
(float)valueMap.get("x", 0).asDouble() * timelineScale, // (float)valueMap.get("x", 0).asDouble() * timelineScale, //
@ -291,14 +292,14 @@ Animation* BaseSkeletonJson::readAnimation (const char *begin, const char *end,
Json::Value slots = root["slots"]; Json::Value slots = root["slots"];
if (!slots.isNull()) { if (!slots.isNull()) {
vector<string> slotNames = slots.getMemberNames(); vector<string> slotNames = slots.getMemberNames();
for (unsigned int i = 0; i < slotNames.size(); i++) { for (int i = 0, n = slotNames.size(); i < n; i++) {
string slotName = slotNames[i]; string slotName = slotNames[i];
int slotIndex = skeletonData->findSlotIndex(slotName); int slotIndex = skeletonData->findSlotIndex(slotName);
if (slotIndex == -1) throw runtime_error("Slot not found: " + slotName); if (slotIndex == -1) throw runtime_error("Slot not found: " + slotName);
Json::Value timelineMap = slots[slotName]; Json::Value timelineMap = slots[slotName];
vector<string> timelineNames = timelineMap.getMemberNames(); vector<string> timelineNames = timelineMap.getMemberNames();
for (unsigned int i = 0; i < timelineNames.size(); i++) { for (int i = 0, n = timelineNames.size(); i < n; i++) {
string timelineName = timelineNames[i]; string timelineName = timelineNames[i];
Json::Value values = timelineMap[timelineName]; Json::Value values = timelineMap[timelineName];
@ -307,7 +308,7 @@ Animation* BaseSkeletonJson::readAnimation (const char *begin, const char *end,
timeline->slotIndex = slotIndex; timeline->slotIndex = slotIndex;
int keyframeIndex = 0; int keyframeIndex = 0;
for (unsigned int i = 0; i < values.size(); i++) { for (int i = 0, n = values.size(); i < n; i++) {
Json::Value valueMap = values[i]; Json::Value valueMap = values[i];
string s = valueMap["color"].asString(); string s = valueMap["color"].asString();
@ -324,11 +325,12 @@ Animation* BaseSkeletonJson::readAnimation (const char *begin, const char *end,
timeline->slotIndex = slotIndex; timeline->slotIndex = slotIndex;
int keyframeIndex = 0; int keyframeIndex = 0;
for (unsigned int i = 0; i < values.size(); i++) { for (int i = 0, n = values.size(); i < n; i++) {
Json::Value valueMap = values[i]; Json::Value valueMap = values[i];
Json::Value name = valueMap["name"]; Json::Value nameValue = valueMap["name"];
timeline->setKeyframe(keyframeIndex++, (float)valueMap["time"].asDouble(), name.isNull() ? "" : name.asString()); timeline->setKeyframe(keyframeIndex++, (float)valueMap["time"].asDouble(),
nameValue.isNull() ? 0 : new string(nameValue.asString()));
} }
timelines.push_back(timeline); timelines.push_back(timeline);
if (timeline->getDuration() > duration) duration = timeline->getDuration(); if (timeline->getDuration() > duration) duration = timeline->getDuration();

View File

@ -58,7 +58,7 @@ void Bone::updateWorldTransform (bool flipX, bool flipY) {
m10 = -m10; m10 = -m10;
m11 = -m11; m11 = -m11;
} }
if (data->flipY) { if (data->yDown) {
m10 = -m10; m10 = -m10;
m11 = -m11; m11 = -m11;
} }

View File

@ -21,31 +21,31 @@ SkeletonData::~SkeletonData () {
} }
BoneData* SkeletonData::findBone (const string &boneName) const { BoneData* SkeletonData::findBone (const string &boneName) const {
for (unsigned int i = 0; i < bones.size(); i++) for (int i = 0, n = bones.size(); i < n; i++)
if (bones[i]->name == boneName) return bones[i]; if (bones[i]->name == boneName) return bones[i];
return 0; return 0;
} }
int SkeletonData::findBoneIndex (const string &boneName) const { int SkeletonData::findBoneIndex (const string &boneName) const {
for (unsigned int i = 0; i < bones.size(); i++) for (int i = 0, n = bones.size(); i < n; i++)
if (bones[i]->name == boneName) return i; if (bones[i]->name == boneName) return i;
return -1; return -1;
} }
SlotData* SkeletonData::findSlot (const string &slotName) const { SlotData* SkeletonData::findSlot (const string &slotName) const {
for (unsigned int i = 0; i < slots.size(); i++) for (int i = 0, n = slots.size(); i < n; i++)
if (slots[i]->name == slotName) return slots[i]; if (slots[i]->name == slotName) return slots[i];
return 0; return 0;
} }
int SkeletonData::findSlotIndex (const string &slotName) const { int SkeletonData::findSlotIndex (const string &slotName) const {
for (unsigned int i = 0; i < slots.size(); i++) for (int i = 0, n = slots.size(); i < n; i++)
if (slots[i]->name == slotName) return i; if (slots[i]->name == slotName) return i;
return -1; return -1;
} }
Skin* SkeletonData::findSkin (const string &skinName) { Skin* SkeletonData::findSkin (const string &skinName) const {
for (unsigned int i = 0; i < skins.size(); i++) for (int i = 0, n = skins.size(); i < n; i++)
if (skins[i]->name == skinName) return skins[i]; if (skins[i]->name == skinName) return skins[i];
return 0; return 0;
} }

View File

@ -1,3 +1,5 @@
#include <stdexcept>
#include <spine/Attachment.h>
#include <spine/Skin.h> #include <spine/Skin.h>
#include <spine/BaseSkeleton.h> #include <spine/BaseSkeleton.h>
#include <spine/Slot.h> #include <spine/Slot.h>
@ -8,14 +10,13 @@ Skin::Skin (const std::string &name) :
name(name) { name(name) {
} }
Skin::~Skin() Skin::~Skin () {
{ for (std::map<Key, Attachment*>::iterator iter = attachments.begin(); iter != attachments.end(); iter++)
for (std::map<Key, Attachment*>::iterator iter = attachments.begin(); iter != attachments.end(); ++iter) { delete iter->second;
delete iter->second;
}
} }
void Skin::addAttachment (int slotIndex, const std::string &name, Attachment *attachment) { void Skin::addAttachment (int slotIndex, const std::string &name, Attachment *attachment) {
if (!attachment) throw std::invalid_argument("attachment cannot be null.");
Key key = {slotIndex, name}; Key key = {slotIndex, name};
attachments[key] = attachment; attachments[key] = attachment;
} }
@ -26,7 +27,6 @@ Attachment* Skin::getAttachment (int slotIndex, const std::string &name) {
return 0; return 0;
} }
/** Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. */
void Skin::attachAll (BaseSkeleton *skeleton, Skin *oldSkin) { void Skin::attachAll (BaseSkeleton *skeleton, Skin *oldSkin) {
for (std::map<Key, Attachment*>::iterator iter = attachments.begin(); iter != attachments.end(); iter++) { for (std::map<Key, Attachment*>::iterator iter = attachments.begin(); iter != attachments.end(); iter++) {
const Key key = iter->first; const Key key = iter->first;

View File

@ -1,3 +1,4 @@
#include <stdexcept>
#include <spine/Slot.h> #include <spine/Slot.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>
#include <spine/BaseSkeleton.h> #include <spine/BaseSkeleton.h>
@ -6,6 +7,7 @@
namespace spine { namespace spine {
Slot::Slot (SlotData *data, BaseSkeleton *skeleton, Bone *bone) : Slot::Slot (SlotData *data, BaseSkeleton *skeleton, Bone *bone) :
attachmentTime(0),
data(data), data(data),
skeleton(skeleton), skeleton(skeleton),
bone(bone), bone(bone),
@ -13,8 +15,7 @@ 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.");

View File

@ -0,0 +1,25 @@
#include <stdexcept>
#include <spine/SlotData.h>
namespace spine {
SlotData::SlotData (const std::string &name, BoneData *boneData) :
name(name),
boneData(boneData),
r(1),
g(1),
b(1),
a(1),
attachmentName(0) {
if (!boneData) throw std::invalid_argument("boneData cannot be null.");
}
SlotData::~SlotData () {
if (attachmentName) {
delete attachmentName;
attachmentName = 0;
}
}
}
/* namespace spine */

View File

@ -1,9 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/> <classpathentry kind="src" path="test"/>
<classpathentry combineaccessrules="false" exported="true" kind="src" path="/gdx-backend-jglfw"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> <classpathentry combineaccessrules="false" exported="true" kind="src" path="/gdx-backend-lwjgl"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
<classpathentry exported="true" kind="lib" path="libs/gdx.jar" sourcepath="libs/gdx-sources.jar"/>
</classpath> </classpath>

View File

@ -22,7 +22,6 @@
<disable_hints /> <disable_hints />
</component> </component>
<component name="DebuggerManager"> <component name="DebuggerManager">
<ui_properties default_suspend_policy="SuspendAll" default_condition_enabled="true" />
<breakpoint_any default_suspend_policy="SuspendAll" default_condition_enabled="true"> <breakpoint_any default_suspend_policy="SuspendAll" default_condition_enabled="true">
<breakpoint> <breakpoint>
<option name="NOTIFY_CAUGHT" value="true" /> <option name="NOTIFY_CAUGHT" value="true" />
@ -57,6 +56,7 @@
<option name="LOG_MESSAGE" value="" /> <option name="LOG_MESSAGE" value="" />
</breakpoint> </breakpoint>
</breakpoint_any> </breakpoint_any>
<ui_properties default_suspend_policy="SuspendAll" default_condition_enabled="true" />
<breakpoint_rules /> <breakpoint_rules />
<ui_properties /> <ui_properties />
</component> </component>
@ -78,7 +78,7 @@
<file leaf-file-name="SkeletonTest.java" pinned="false" current="true" current-in-tab="true"> <file leaf-file-name="SkeletonTest.java" pinned="false" current="true" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/test/com/esotericsoftware/spine/SkeletonTest.java"> <entry file="file://$PROJECT_DIR$/test/com/esotericsoftware/spine/SkeletonTest.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state line="23" column="116" selection-start="940" selection-end="940" vertical-scroll-proportion="0.59380376"> <state line="23" column="116" selection-start="940" selection-end="940" vertical-scroll-proportion="0.017441861">
<folding> <folding>
<element signature="imports" expanded="true" /> <element signature="imports" expanded="true" />
</folding> </folding>
@ -99,9 +99,7 @@
<entry file="file://$PROJECT_DIR$/test/com/esotericsoftware/spine/MixTest.java"> <entry file="file://$PROJECT_DIR$/test/com/esotericsoftware/spine/MixTest.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state line="115" column="8" selection-start="3622" selection-end="3697" vertical-scroll-proportion="0.0"> <state line="115" column="8" selection-start="3622" selection-end="3697" vertical-scroll-proportion="0.0">
<folding> <folding />
<element signature="imports" expanded="true" />
</folding>
</state> </state>
</provider> </provider>
</entry> </entry>
@ -154,7 +152,7 @@
<file leaf-file-name="spine-libgdx.iws" pinned="false" current="false" current-in-tab="false"> <file leaf-file-name="spine-libgdx.iws" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/spine-libgdx.iws"> <entry file="file://$PROJECT_DIR$/spine-libgdx.iws">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state line="10" column="0" selection-start="781" selection-end="781" vertical-scroll-proportion="0.0"> <state line="9" column="0" selection-start="648" selection-end="648" vertical-scroll-proportion="0.0">
<folding /> <folding />
</state> </state>
</provider> </provider>
@ -178,9 +176,10 @@
</option> </option>
</component> </component>
<component name="ProjectFrameBounds"> <component name="ProjectFrameBounds">
<option name="y" value="24" /> <option name="x" value="1919" />
<option name="width" value="1920" /> <option name="y" value="-4" />
<option name="height" value="1056" /> <option name="width" value="1682" />
<option name="height" value="1055" />
</component> </component>
<component name="ProjectInspectionProfilesVisibleTreeState"> <component name="ProjectInspectionProfilesVisibleTreeState">
<entry key="Project Default"> <entry key="Project Default">
@ -254,6 +253,7 @@
</navigator> </navigator>
<panes> <panes>
<pane id="Scope" /> <pane id="Scope" />
<pane id="PackagesPane" />
<pane id="ProjectPane"> <pane id="ProjectPane">
<subPane> <subPane>
<PATH> <PATH>
@ -320,7 +320,6 @@
</PATH> </PATH>
</subPane> </subPane>
</pane> </pane>
<pane id="PackagesPane" />
</panes> </panes>
</component> </component>
<component name="PropertiesComponent"> <component name="PropertiesComponent">
@ -339,9 +338,9 @@
<property name="restartRequiresConfirmation" value="true" /> <property name="restartRequiresConfirmation" value="true" />
<property name="MemberChooser.showClasses" value="true" /> <property name="MemberChooser.showClasses" value="true" />
<property name="GoToClass.includeLibraries" value="false" /> <property name="GoToClass.includeLibraries" value="false" />
<property name="options.splitter.details.proportions" value="0.2" />
<property name="options.searchVisible" value="true" />
<property name="dynamic.classpath" value="false" /> <property name="dynamic.classpath" value="false" />
<property name="options.searchVisible" value="true" />
<property name="options.splitter.details.proportions" value="0.2" />
</component> </component>
<component name="RecentsManager"> <component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS"> <key name="CopyFile.RECENT_KEYS">
@ -364,6 +363,19 @@
<option name="PORT" value="5005" /> <option name="PORT" value="5005" />
<method /> <method />
</configuration> </configuration>
<configuration default="true" type="Applet" factoryName="Applet">
<module name="" />
<option name="MAIN_CLASS_NAME" />
<option name="HTML_FILE_NAME" />
<option name="HTML_USED" value="false" />
<option name="WIDTH" value="400" />
<option name="HEIGHT" value="300" />
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
<option name="VM_PARAMETERS" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<method />
</configuration>
<configuration default="true" type="TestNG" factoryName="TestNG"> <configuration default="true" type="TestNG" factoryName="TestNG">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" /> <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="" /> <module name="" />
@ -392,19 +404,6 @@
<listeners /> <listeners />
<method /> <method />
</configuration> </configuration>
<configuration default="true" type="Applet" factoryName="Applet">
<module name="" />
<option name="MAIN_CLASS_NAME" />
<option name="HTML_FILE_NAME" />
<option name="HTML_USED" value="false" />
<option name="WIDTH" value="400" />
<option name="HEIGHT" value="300" />
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
<option name="VM_PARAMETERS" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<method />
</configuration>
<configuration default="true" type="Application" factoryName="Application"> <configuration default="true" type="Application" factoryName="Application">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" /> <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="MAIN_CLASS_NAME" value="com.esotericsoftware.spine.MixTest" /> <option name="MAIN_CLASS_NAME" value="com.esotericsoftware.spine.MixTest" />
@ -530,8 +529,8 @@
<servers /> <servers />
</component> </component>
<component name="ToolWindowManager"> <component name="ToolWindowManager">
<frame x="0" y="24" width="1920" height="1056" extended-state="6" /> <frame x="1919" y="-4" width="1682" height="1055" extended-state="6" />
<editor active="true" /> <editor active="false" />
<layout> <layout>
<window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" /> <window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="JetGradle" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" /> <window_info id="JetGradle" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
@ -544,19 +543,19 @@
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" /> <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
<window_info id="IDEtalk" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32977587" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" /> <window_info id="IDEtalk" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32977587" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" /> <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32977587" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" /> <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="true" content_ui="tabs" /> <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="true" content_ui="tabs" />
<window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" /> <window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" /> <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Application Servers" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" /> <window_info id="Application Servers" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="JSON Formatter" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" /> <window_info id="JSON Formatter" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.2497332" sideWeight="0.67022413" order="0" side_tool="false" content_ui="combo" /> <window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.249694" sideWeight="0.67022413" order="0" side_tool="false" content_ui="combo" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.32977587" sideWeight="0.9989328" order="2" side_tool="false" content_ui="tabs" /> <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32977587" sideWeight="0.9989328" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" /> <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" /> <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" /> <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" /> <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32977587" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" /> <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
</layout> </layout>
</component> </component>
@ -671,7 +670,7 @@
</entry> </entry>
<entry file="file://$PROJECT_DIR$/spine-libgdx.iws"> <entry file="file://$PROJECT_DIR$/spine-libgdx.iws">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state line="10" column="0" selection-start="781" selection-end="781" vertical-scroll-proportion="0.0"> <state line="9" column="0" selection-start="648" selection-end="648" vertical-scroll-proportion="0.0">
<folding /> <folding />
</state> </state>
</provider> </provider>
@ -685,9 +684,7 @@
</entry> </entry>
<entry file="file://$PROJECT_DIR$/src/com/esotericsoftware/spine/AttachmentType.java"> <entry file="file://$PROJECT_DIR$/src/com/esotericsoftware/spine/AttachmentType.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state line="3" column="12" selection-start="50" selection-end="50" vertical-scroll-proportion="0.0"> <state line="3" column="12" selection-start="50" selection-end="50" vertical-scroll-proportion="0.0" />
<folding />
</state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/src/com/esotericsoftware/spine/BoneData.java"> <entry file="file://$PROJECT_DIR$/src/com/esotericsoftware/spine/BoneData.java">
@ -721,15 +718,13 @@
<entry file="file://$PROJECT_DIR$/test/com/esotericsoftware/spine/MixTest.java"> <entry file="file://$PROJECT_DIR$/test/com/esotericsoftware/spine/MixTest.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state line="115" column="8" selection-start="3622" selection-end="3697" vertical-scroll-proportion="0.0"> <state line="115" column="8" selection-start="3622" selection-end="3697" vertical-scroll-proportion="0.0">
<folding> <folding />
<element signature="imports" expanded="true" />
</folding>
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/test/com/esotericsoftware/spine/SkeletonTest.java"> <entry file="file://$PROJECT_DIR$/test/com/esotericsoftware/spine/SkeletonTest.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state line="23" column="116" selection-start="940" selection-end="940" vertical-scroll-proportion="0.59380376"> <state line="23" column="116" selection-start="940" selection-end="940" vertical-scroll-proportion="0.017441861">
<folding> <folding>
<element signature="imports" expanded="true" /> <element signature="imports" expanded="true" />
</folding> </folding>

View File

@ -2,5 +2,6 @@
package com.esotericsoftware.spine; package com.esotericsoftware.spine;
public interface AttachmentLoader { public interface AttachmentLoader {
/** @return May be null to not load any attachment. */
public Attachment newAttachment (AttachmentType type, String name); public Attachment newAttachment (AttachmentType type, String name);
} }

View File

@ -216,11 +216,11 @@ public class Skeleton {
/** @return May be null. */ /** @return May be null. */
public Attachment getAttachment (int slotIndex, String attachmentName) { public Attachment getAttachment (int slotIndex, String attachmentName) {
if (attachmentName == null) throw new IllegalArgumentException("attachmentName cannot be null."); if (attachmentName == null) throw new IllegalArgumentException("attachmentName cannot be null.");
if (skin != null) return skin.getAttachment(slotIndex, attachmentName);
if (data.defaultSkin != null) { if (data.defaultSkin != null) {
Attachment attachment = data.defaultSkin.getAttachment(slotIndex, attachmentName); Attachment attachment = data.defaultSkin.getAttachment(slotIndex, attachmentName);
if (attachment != null) return attachment; if (attachment != null) return attachment;
} }
if (skin != null) return skin.getAttachment(slotIndex, attachmentName);
return null; return null;
} }

View File

@ -103,7 +103,7 @@ public class SkeletonJson {
int slotIndex = skeletonData.findSlotIndex(slotEntry.key); int slotIndex = skeletonData.findSlotIndex(slotEntry.key);
for (Entry<String, OrderedMap> attachmentEntry : ((OrderedMap<String, OrderedMap>)slotEntry.value).entries()) { for (Entry<String, OrderedMap> attachmentEntry : ((OrderedMap<String, OrderedMap>)slotEntry.value).entries()) {
Attachment attachment = readAttachment(attachmentEntry.key, attachmentEntry.value); Attachment attachment = readAttachment(attachmentEntry.key, attachmentEntry.value);
skin.addAttachment(slotIndex, attachmentEntry.key, attachment); if (attachment != null) skin.addAttachment(slotIndex, attachmentEntry.key, attachment);
} }
} }
skeletonData.addSkin(skin); skeletonData.addSkin(skin);

View File

@ -113,10 +113,6 @@ public class MixTest extends ApplicationAdapter {
} }
public static void main (String[] args) throws Exception { public static void main (String[] args) throws Exception {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); new LwjglApplication(new MixTest());
config.title = "Mix Test";
config.width = 640;
config.height = 480;
new LwjglApplication(new MixTest(), config);
} }
} }

View File

@ -114,10 +114,6 @@ public class SkeletonTest extends ApplicationAdapter {
} }
public static void main (String[] args) throws Exception { public static void main (String[] args) throws Exception {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); new LwjglApplication(new SkeletonTest());
config.title = "Skeleton Test";
config.width = 640;
config.height = 480;
new LwjglApplication(new SkeletonTest(), config);
} }
} }