mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-19 08:16:41 +08:00
[cpp] Ported skin bones/constraints changes. See #1346.
This commit is contained in:
parent
625f9b076a
commit
29322c5c51
@ -223,6 +223,10 @@ public:
|
||||
bool isAppliedValid();
|
||||
void setAppliedValid(bool valid);
|
||||
|
||||
bool isActive();
|
||||
|
||||
void setActive(bool inValue);
|
||||
|
||||
private:
|
||||
static bool yDown;
|
||||
|
||||
@ -236,6 +240,7 @@ private:
|
||||
float _a, _b, _worldX;
|
||||
float _c, _d, _worldY;
|
||||
bool _sorted;
|
||||
bool _active;
|
||||
|
||||
/// Computes the individual applied transform values from the world transform. This can be useful to perform processing using
|
||||
/// the applied transform after the world transform has been modified directly (eg, by a constraint)..
|
||||
|
||||
@ -106,6 +106,9 @@ public:
|
||||
|
||||
void setTransformMode(TransformMode inValue);
|
||||
|
||||
bool isSkinRequired();
|
||||
void setSkinRequired(bool inValue);
|
||||
|
||||
private:
|
||||
const int _index;
|
||||
const String _name;
|
||||
@ -113,6 +116,7 @@ private:
|
||||
float _length;
|
||||
float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY;
|
||||
TransformMode _transformMode;
|
||||
bool _skinRequired;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -31,21 +31,32 @@
|
||||
#define Spine_Constraint_h
|
||||
|
||||
#include <spine/Updatable.h>
|
||||
#include <spine/SpineString.h>
|
||||
|
||||
namespace spine {
|
||||
/// The interface for all constraints.
|
||||
class SP_API Constraint : public Updatable {
|
||||
RTTI_DECL
|
||||
class SP_API ConstraintData : public SpineObject {
|
||||
|
||||
public:
|
||||
Constraint();
|
||||
ConstraintData(const String& name);
|
||||
|
||||
virtual ~Constraint();
|
||||
virtual ~ConstraintData();
|
||||
|
||||
virtual void update() = 0;
|
||||
/// The IK constraint's name, which is unique within the skeleton.
|
||||
const String& getName();
|
||||
|
||||
/// The ordinal for the order a skeleton's constraints will be applied.
|
||||
virtual int getOrder() = 0;
|
||||
size_t getOrder();
|
||||
void setOrder(size_t inValue);
|
||||
|
||||
/// Whether the constraint is only active for a specific skin.
|
||||
bool isSkinRequired();
|
||||
void setSkinRequired(bool inValue);
|
||||
|
||||
private:
|
||||
const String _name;
|
||||
size_t _order;
|
||||
bool _skinRequired;
|
||||
};
|
||||
}
|
||||
|
||||
@ -55,6 +55,7 @@ public:
|
||||
|
||||
void reportLeaks() {
|
||||
for (std::map<void*, Allocation>::iterator it = _allocated.begin(); it != _allocated.end(); it++) {
|
||||
void* addr = it->second.address;
|
||||
printf("\"%s:%i (%zu bytes at %p)\n", it->second.fileName, it->second.line, it->second.size, it->second.address);
|
||||
}
|
||||
printf("allocations: %zu, reallocations: %zu, frees: %zu\n", _allocations, _reallocations, _frees);
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef Spine_IkConstraint_h
|
||||
#define Spine_IkConstraint_h
|
||||
|
||||
#include <spine/Constraint.h>
|
||||
#include <spine/ConstraintData.h>
|
||||
|
||||
#include <spine/Vector.h>
|
||||
|
||||
@ -41,7 +41,7 @@ class Skeleton;
|
||||
|
||||
class Bone;
|
||||
|
||||
class SP_API IkConstraint : public Constraint {
|
||||
class SP_API IkConstraint : public Updatable {
|
||||
friend class Skeleton;
|
||||
|
||||
friend class IkConstraintTimeline;
|
||||
@ -91,6 +91,10 @@ public:
|
||||
|
||||
void setMix(float inValue);
|
||||
|
||||
bool isActive();
|
||||
|
||||
void setActive(bool inValue);
|
||||
|
||||
private:
|
||||
IkConstraintData &_data;
|
||||
Vector<Bone *> _bones;
|
||||
@ -99,6 +103,7 @@ private:
|
||||
bool _stretch;
|
||||
float _mix;
|
||||
Bone *_target;
|
||||
bool _active;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -33,11 +33,12 @@
|
||||
#include <spine/Vector.h>
|
||||
#include <spine/SpineObject.h>
|
||||
#include <spine/SpineString.h>
|
||||
#include <spine/ConstraintData.h>
|
||||
|
||||
namespace spine {
|
||||
class BoneData;
|
||||
|
||||
class SP_API IkConstraintData : public SpineObject {
|
||||
class SP_API IkConstraintData : public ConstraintData {
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonJson;
|
||||
friend class IkConstraint;
|
||||
@ -47,12 +48,6 @@ namespace spine {
|
||||
public:
|
||||
explicit IkConstraintData(const String& name);
|
||||
|
||||
/// The IK constraint's name, which is unique within the skeleton.
|
||||
const String& getName();
|
||||
|
||||
size_t getOrder();
|
||||
void setOrder(size_t inValue);
|
||||
|
||||
/// The bones that are constrained by this IK Constraint.
|
||||
Vector<BoneData*>& getBones();
|
||||
|
||||
@ -77,8 +72,6 @@ namespace spine {
|
||||
void setMix(float inValue);
|
||||
|
||||
private:
|
||||
const String _name;
|
||||
size_t _order;
|
||||
Vector<BoneData*> _bones;
|
||||
BoneData* _target;
|
||||
int _bendDirection;
|
||||
|
||||
@ -60,6 +60,8 @@ public:
|
||||
|
||||
static int getInt(Json *object, const char *name, int defaultValue);
|
||||
|
||||
static bool getBoolean(Json *object, const char *name, bool defaultValue);
|
||||
|
||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when Json_create() returns 0. 0 when Json_create() succeeds. */
|
||||
static const char *getError();
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef Spine_PathConstraint_h
|
||||
#define Spine_PathConstraint_h
|
||||
|
||||
#include <spine/Constraint.h>
|
||||
#include <spine/ConstraintData.h>
|
||||
|
||||
#include <spine/Vector.h>
|
||||
|
||||
@ -41,7 +41,7 @@ namespace spine {
|
||||
class Bone;
|
||||
class Slot;
|
||||
|
||||
class SP_API PathConstraint : public Constraint {
|
||||
class SP_API PathConstraint : public Updatable {
|
||||
friend class Skeleton;
|
||||
friend class PathConstraintMixTimeline;
|
||||
friend class PathConstraintPositionTimeline;
|
||||
@ -77,6 +77,10 @@ namespace spine {
|
||||
void setTarget(Slot* inValue);
|
||||
|
||||
PathConstraintData& getData();
|
||||
|
||||
bool isActive();
|
||||
|
||||
void setActive(bool inValue);
|
||||
|
||||
private:
|
||||
static const float EPSILON;
|
||||
@ -95,6 +99,8 @@ namespace spine {
|
||||
Vector<float> _curves;
|
||||
Vector<float> _lengths;
|
||||
Vector<float> _segments;
|
||||
|
||||
bool _active;
|
||||
|
||||
Vector<float>& computeWorldPositions(PathAttachment& path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing);
|
||||
|
||||
|
||||
@ -36,12 +36,13 @@
|
||||
#include <spine/Vector.h>
|
||||
#include <spine/SpineObject.h>
|
||||
#include <spine/SpineString.h>
|
||||
#include <spine/ConstraintData.h>
|
||||
|
||||
namespace spine {
|
||||
class BoneData;
|
||||
class SlotData;
|
||||
|
||||
class SP_API PathConstraintData : public SpineObject {
|
||||
class SP_API PathConstraintData : public ConstraintData {
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonJson;
|
||||
|
||||
@ -53,11 +54,6 @@ namespace spine {
|
||||
|
||||
public:
|
||||
explicit PathConstraintData(const String& name);
|
||||
|
||||
const String& getName();
|
||||
|
||||
int getOrder();
|
||||
void setOrder(int inValue);
|
||||
|
||||
Vector<BoneData*>& getBones();
|
||||
|
||||
@ -89,8 +85,6 @@ namespace spine {
|
||||
void setTranslateMix(float inValue);
|
||||
|
||||
private:
|
||||
const String _name;
|
||||
int _order;
|
||||
Vector<BoneData*> _bones;
|
||||
SlotData* _target;
|
||||
PositionMode _positionMode;
|
||||
|
||||
@ -95,6 +95,8 @@ namespace spine {
|
||||
void setError(const char* value1, const char* value2);
|
||||
|
||||
char* readString(DataInput* input);
|
||||
|
||||
char* readStringRef(DataInput* input, SkeletonData* skeletonData);
|
||||
|
||||
float readFloat(DataInput* input);
|
||||
|
||||
@ -110,7 +112,7 @@ namespace spine {
|
||||
|
||||
int readVarint(DataInput* input, bool optimizePositive);
|
||||
|
||||
Skin* readSkin(DataInput* input, const String& skinName, SkeletonData* skeletonData, bool nonessential);
|
||||
Skin* readSkin(DataInput* input, bool defaultSkin, SkeletonData* skeletonData, bool nonessential);
|
||||
|
||||
Attachment* readAttachment(DataInput* input, Skin* skin, int slotIndex, const String& attachmentName, SkeletonData* skeletonData, bool nonessential);
|
||||
|
||||
|
||||
@ -172,6 +172,7 @@ private:
|
||||
float _x, _y, _width, _height;
|
||||
String _version;
|
||||
String _hash;
|
||||
Vector<char*> _strings;
|
||||
|
||||
// Nonessential.
|
||||
float _fps;
|
||||
|
||||
@ -37,6 +37,8 @@ namespace spine {
|
||||
class Attachment;
|
||||
|
||||
class Skeleton;
|
||||
class BoneData;
|
||||
class ConstraintData;
|
||||
|
||||
/// Stores attachments by slot index and attachment name.
|
||||
/// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and
|
||||
@ -142,9 +144,14 @@ public:
|
||||
|
||||
AttachmentMap::Entries getAttachments();
|
||||
|
||||
Vector<BoneData*>& getBones();
|
||||
|
||||
Vector<ConstraintData*>& getConstraints();
|
||||
private:
|
||||
const String _name;
|
||||
AttachmentMap _attachments;
|
||||
Vector<BoneData*> _bones;
|
||||
Vector<ConstraintData*> _constraints;
|
||||
|
||||
/// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached.
|
||||
void attachAll(Skeleton &skeleton, Skin &oldSkin);
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef Spine_TransformConstraint_h
|
||||
#define Spine_TransformConstraint_h
|
||||
|
||||
#include <spine/Constraint.h>
|
||||
#include <spine/ConstraintData.h>
|
||||
|
||||
#include <spine/Vector.h>
|
||||
|
||||
@ -39,7 +39,7 @@ namespace spine {
|
||||
class Skeleton;
|
||||
class Bone;
|
||||
|
||||
class SP_API TransformConstraint : public Constraint {
|
||||
class SP_API TransformConstraint : public Updatable {
|
||||
friend class Skeleton;
|
||||
friend class TransformConstraintTimeline;
|
||||
|
||||
@ -72,12 +72,17 @@ namespace spine {
|
||||
|
||||
float getShearMix();
|
||||
void setShearMix(float inValue);
|
||||
|
||||
bool isActive();
|
||||
|
||||
void setActive(bool inValue);
|
||||
|
||||
private:
|
||||
TransformConstraintData& _data;
|
||||
Vector<Bone*> _bones;
|
||||
Bone* _target;
|
||||
float _rotateMix, _translateMix, _scaleMix, _shearMix;
|
||||
bool _active;
|
||||
|
||||
void applyAbsoluteWorld();
|
||||
|
||||
|
||||
@ -33,11 +33,12 @@
|
||||
#include <spine/Vector.h>
|
||||
#include <spine/SpineObject.h>
|
||||
#include <spine/SpineString.h>
|
||||
#include <spine/ConstraintData.h>
|
||||
|
||||
namespace spine {
|
||||
class BoneData;
|
||||
|
||||
class SP_API TransformConstraintData : public SpineObject {
|
||||
class SP_API TransformConstraintData : public ConstraintData {
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonJson;
|
||||
|
||||
@ -48,8 +49,6 @@ namespace spine {
|
||||
public:
|
||||
explicit TransformConstraintData(const String& name);
|
||||
|
||||
const String& getName();
|
||||
int getOrder();
|
||||
Vector<BoneData*>& getBones();
|
||||
BoneData* getTarget();
|
||||
float getRotateMix();
|
||||
@ -68,8 +67,6 @@ namespace spine {
|
||||
bool isLocal();
|
||||
|
||||
private:
|
||||
const String _name;
|
||||
int _order;
|
||||
Vector<BoneData*> _bones;
|
||||
BoneData* _target;
|
||||
float _rotateMix, _translateMix, _scaleMix, _shearMix;
|
||||
|
||||
@ -43,6 +43,10 @@ public:
|
||||
virtual ~Updatable();
|
||||
|
||||
virtual void update() = 0;
|
||||
|
||||
virtual bool isActive() = 0;
|
||||
|
||||
virtual void setActive(bool inValue) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
#include <spine/ClippingAttachment.h>
|
||||
#include <spine/Color.h>
|
||||
#include <spine/ColorTimeline.h>
|
||||
#include <spine/Constraint.h>
|
||||
#include <spine/ConstraintData.h>
|
||||
#include <spine/ContainerUtil.h>
|
||||
#include <spine/CurveTimeline.h>
|
||||
#include <spine/Debug.h>
|
||||
|
||||
@ -668,6 +668,7 @@ void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleto
|
||||
}
|
||||
|
||||
Bone *bone = skeleton._bones[rotateTimeline->_boneIndex];
|
||||
if (!bone->isActive()) return;
|
||||
Vector<float>& frames = rotateTimeline->_frames;
|
||||
float r1, r2;
|
||||
if (time < frames[0]) {
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
#include <spine/Event.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
@ -67,6 +68,8 @@ void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, V
|
||||
String *attachmentName;
|
||||
Slot *slotP = skeleton._slots[_slotIndex];
|
||||
Slot &slot = *slotP;
|
||||
if (!slot._bone.isActive()) return;
|
||||
|
||||
if (direction == MixDirection_Out && blend == MixBlend_Setup) {
|
||||
attachmentName = &slot._data._attachmentName;
|
||||
slot.setAttachment(attachmentName->length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName));
|
||||
|
||||
@ -75,7 +75,8 @@ Bone::Bone(BoneData &data, Skeleton &skeleton, Bone *parent) : Updatable(),
|
||||
_c(0),
|
||||
_d(1),
|
||||
_worldY(0),
|
||||
_sorted(false) {
|
||||
_sorted(false),
|
||||
_active(false) {
|
||||
setToSetupPose();
|
||||
}
|
||||
|
||||
@ -538,3 +539,11 @@ void Bone::updateAppliedTransform() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Bone::isActive() {
|
||||
return _active;
|
||||
}
|
||||
|
||||
void Bone::setActive(bool inValue) {
|
||||
_active = inValue;
|
||||
}
|
||||
|
||||
@ -49,7 +49,8 @@ BoneData::BoneData(int index, const String &name, BoneData *parent) :
|
||||
_scaleY(1),
|
||||
_shearX(0),
|
||||
_shearY(0),
|
||||
_transformMode(TransformMode_Normal) {
|
||||
_transformMode(TransformMode_Normal),
|
||||
_skinRequired(false) {
|
||||
assert(index >= 0);
|
||||
assert(_name.length() > 0);
|
||||
}
|
||||
@ -137,3 +138,11 @@ TransformMode BoneData::getTransformMode() {
|
||||
void BoneData::setTransformMode(TransformMode inValue) {
|
||||
_transformMode = inValue;
|
||||
}
|
||||
|
||||
bool BoneData::isSkinRequired() {
|
||||
return _skinRequired;
|
||||
}
|
||||
|
||||
void BoneData::setSkinRequired(bool inValue) {
|
||||
_skinRequired = inValue;
|
||||
}
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
#include <spine/Event.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
@ -68,6 +69,7 @@ void ColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
|
||||
|
||||
Slot *slotP = skeleton._slots[_slotIndex];
|
||||
Slot &slot = *slotP;
|
||||
if (!slot._bone.isActive()) return;
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
|
||||
@ -31,14 +31,32 @@
|
||||
#include "SpinePluginPrivatePCH.h"
|
||||
#endif
|
||||
|
||||
#include <spine/Constraint.h>
|
||||
#include <spine/ConstraintData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(Constraint, Updatable)
|
||||
|
||||
Constraint::Constraint() {
|
||||
ConstraintData::ConstraintData(const String& name): _name(name), _order(0), _skinRequired(false) {
|
||||
}
|
||||
|
||||
Constraint::~Constraint() {
|
||||
ConstraintData::~ConstraintData() {
|
||||
}
|
||||
|
||||
const String& ConstraintData::getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
size_t ConstraintData::getOrder() {
|
||||
return _order;
|
||||
}
|
||||
|
||||
void ConstraintData::setOrder(size_t inValue) {
|
||||
_order = inValue;
|
||||
}
|
||||
|
||||
bool ConstraintData::isSkinRequired() {
|
||||
return _skinRequired;
|
||||
}
|
||||
|
||||
void ConstraintData::setSkinRequired(bool inValue) {
|
||||
_skinRequired = inValue;
|
||||
}
|
||||
@ -41,6 +41,7 @@
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
using namespace spine;
|
||||
@ -67,6 +68,7 @@ void DeformTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto
|
||||
|
||||
Slot *slotP = skeleton._slots[_slotIndex];
|
||||
Slot &slot = *slotP;
|
||||
if (!slot._bone.isActive()) return;
|
||||
|
||||
Attachment *slotAttachment = slot.getAttachment();
|
||||
if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) {
|
||||
|
||||
@ -41,7 +41,7 @@
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(IkConstraint, Constraint)
|
||||
RTTI_IMPL(IkConstraint, Updatable)
|
||||
|
||||
void IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha) {
|
||||
Bone *p = bone.getParent();
|
||||
@ -207,14 +207,15 @@ void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY
|
||||
}
|
||||
}
|
||||
|
||||
IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Constraint(),
|
||||
IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Updatable(),
|
||||
_data(data),
|
||||
_bendDirection(data.getBendDirection()),
|
||||
_compress(data.getCompress()),
|
||||
_stretch(data.getStretch()),
|
||||
_mix(data.getMix()),
|
||||
_target(skeleton.findBone(
|
||||
data.getTarget()->getName())) {
|
||||
data.getTarget()->getName())),
|
||||
_active(false) {
|
||||
_bones.ensureCapacity(_data.getBones().size());
|
||||
for (size_t i = 0; i < _data.getBones().size(); i++) {
|
||||
BoneData *boneData = _data.getBones()[i];
|
||||
@ -294,3 +295,12 @@ bool IkConstraint::getCompress() {
|
||||
void IkConstraint::setCompress(bool inValue) {
|
||||
_compress = inValue;
|
||||
}
|
||||
|
||||
bool IkConstraint::isActive() {
|
||||
return _active;
|
||||
}
|
||||
|
||||
void IkConstraint::setActive(bool inValue) {
|
||||
_active = inValue;
|
||||
}
|
||||
|
||||
|
||||
@ -38,8 +38,7 @@
|
||||
using namespace spine;
|
||||
|
||||
IkConstraintData::IkConstraintData(const String &name) :
|
||||
_name(name),
|
||||
_order(0),
|
||||
ConstraintData(name),
|
||||
_target(NULL),
|
||||
_bendDirection(1),
|
||||
_compress(false),
|
||||
@ -48,18 +47,6 @@ IkConstraintData::IkConstraintData(const String &name) :
|
||||
_mix(1) {
|
||||
}
|
||||
|
||||
const String &IkConstraintData::getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
size_t IkConstraintData::getOrder() {
|
||||
return _order;
|
||||
}
|
||||
|
||||
void IkConstraintData::setOrder(size_t inValue) {
|
||||
_order = inValue;
|
||||
}
|
||||
|
||||
Vector<BoneData *> &IkConstraintData::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
|
||||
@ -69,6 +69,8 @@ void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time,
|
||||
|
||||
IkConstraint *constraintP = skeleton._ikConstraints[_ikConstraintIndex];
|
||||
IkConstraint &constraint = *constraintP;
|
||||
if (!constraint.isActive()) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
|
||||
@ -90,6 +90,18 @@ int Json::getInt(Json *value, const char *name, int defaultValue) {
|
||||
return value ? value->_valueInt : defaultValue;
|
||||
}
|
||||
|
||||
bool Json::getBoolean(spine::Json *value, const char *name, bool defaultValue) {
|
||||
value = getItem(value, name);
|
||||
if (value) {
|
||||
if (value->_valueString) return strcmp(value->_valueString, "true") == 0;
|
||||
if (value->_type == JSON_NULL) return false;
|
||||
if (value->_type == JSON_NUMBER) return value->_valueFloat != 0;
|
||||
return defaultValue;
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
const char *Json::getError() {
|
||||
return _error;
|
||||
}
|
||||
|
||||
@ -44,21 +44,22 @@
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(PathConstraint, Constraint)
|
||||
RTTI_IMPL(PathConstraint, Updatable)
|
||||
|
||||
const float PathConstraint::EPSILON = 0.00001f;
|
||||
const int PathConstraint::NONE = -1;
|
||||
const int PathConstraint::BEFORE = -2;
|
||||
const int PathConstraint::AFTER = -3;
|
||||
|
||||
PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : Constraint(),
|
||||
PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : Updatable(),
|
||||
_data(data),
|
||||
_target(skeleton.findSlot(
|
||||
data.getTarget()->getName())),
|
||||
_position(data.getPosition()),
|
||||
_spacing(data.getSpacing()),
|
||||
_rotateMix(data.getRotateMix()),
|
||||
_translateMix(data.getTranslateMix()) {
|
||||
_translateMix(data.getTranslateMix()),
|
||||
_active(false) {
|
||||
_bones.ensureCapacity(_data.getBones().size());
|
||||
for (size_t i = 0; i < _data.getBones().size(); i++) {
|
||||
BoneData *boneData = _data.getBones()[i];
|
||||
@ -568,3 +569,11 @@ void PathConstraint::addCurvePosition(float p, float x1, float y1, float cx1, fl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PathConstraint::isActive() {
|
||||
return _active;
|
||||
}
|
||||
|
||||
void PathConstraint::setActive(bool inValue) {
|
||||
_active = inValue;
|
||||
}
|
||||
|
||||
@ -41,8 +41,7 @@
|
||||
using namespace spine;
|
||||
|
||||
PathConstraintData::PathConstraintData(const String &name) :
|
||||
_name(name),
|
||||
_order(0),
|
||||
ConstraintData(name),
|
||||
_target(NULL),
|
||||
_positionMode(PositionMode_Fixed),
|
||||
_spacingMode(SpacingMode_Length),
|
||||
@ -52,19 +51,6 @@ PathConstraintData::PathConstraintData(const String &name) :
|
||||
_spacing(0),
|
||||
_rotateMix(0),
|
||||
_translateMix(0) {
|
||||
assert(_name.length() > 0);
|
||||
}
|
||||
|
||||
const String &PathConstraintData::getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
int PathConstraintData::getOrder() {
|
||||
return _order;
|
||||
}
|
||||
|
||||
void PathConstraintData::setOrder(int inValue) {
|
||||
_order = inValue;
|
||||
}
|
||||
|
||||
Vector<BoneData *> &PathConstraintData::getBones() {
|
||||
|
||||
@ -68,6 +68,8 @@ PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time,
|
||||
|
||||
PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex];
|
||||
PathConstraint &constraint = *constraintP;
|
||||
if (!constraint.isActive()) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
|
||||
@ -68,6 +68,8 @@ void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, f
|
||||
|
||||
PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex];
|
||||
PathConstraint &constraint = *constraintP;
|
||||
if (!constraint.isActive()) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
|
||||
@ -59,6 +59,8 @@ void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, fl
|
||||
|
||||
PathConstraint *constraintP = skeleton._pathConstraints[_pathConstraintIndex];
|
||||
PathConstraint &constraint = *constraintP;
|
||||
if (!constraint.isActive()) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
|
||||
@ -303,4 +303,4 @@ Attachment* RegionAttachment::copy() {
|
||||
copy->_vertexOffset.clearAndAddAll(_vertexOffset);
|
||||
copy->_color.set(_color);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +56,7 @@ void RotateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vecto
|
||||
SP_UNUSED(direction);
|
||||
|
||||
Bone *bone = skeleton.getBones()[_boneIndex];
|
||||
if (!bone->_active) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
|
||||
@ -55,6 +55,8 @@ void ScaleTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
|
||||
Bone *boneP = skeleton._bones[_boneIndex];
|
||||
Bone &bone = *boneP;
|
||||
|
||||
if (!bone._active) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
|
||||
@ -56,6 +56,7 @@ void ShearTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vector
|
||||
|
||||
Bone *boneP = skeleton._bones[_boneIndex];
|
||||
Bone &bone = *boneP;
|
||||
if (!bone._active) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
|
||||
@ -135,7 +135,21 @@ void Skeleton::updateCache() {
|
||||
_updateCacheReset.clear();
|
||||
|
||||
for (size_t i = 0, n = _bones.size(); i < n; ++i) {
|
||||
_bones[i]->_sorted = false;
|
||||
Bone* bone = _bones[i];
|
||||
bone->_sorted = bone->_data.isSkinRequired();
|
||||
bone->_active = !bone->_sorted;
|
||||
}
|
||||
|
||||
if (_skin) {
|
||||
Vector<BoneData*>& skinBones = _skin->getBones();
|
||||
for (size_t i = 0, n = skinBones.size(); i < n; i++) {
|
||||
Bone* bone = _bones[skinBones[i]->getIndex()];
|
||||
do {
|
||||
bone->_sorted = false;
|
||||
bone->_active = true;
|
||||
bone = bone->_parent;
|
||||
} while (bone);
|
||||
}
|
||||
}
|
||||
|
||||
size_t ikCount = _ikConstraints.size();
|
||||
@ -158,7 +172,7 @@ void Skeleton::updateCache() {
|
||||
|
||||
for (size_t ii = 0; ii < transformCount; ++ii) {
|
||||
TransformConstraint *constraint = _transformConstraints[ii];
|
||||
if (constraint->getData().getOrder() == (int)i) {
|
||||
if (constraint->getData().getOrder() == i) {
|
||||
sortTransformConstraint(constraint);
|
||||
i++;
|
||||
goto continue_outer;
|
||||
@ -167,7 +181,7 @@ void Skeleton::updateCache() {
|
||||
|
||||
for (size_t ii = 0; ii < pathCount; ++ii) {
|
||||
PathConstraint *constraint = _pathConstraints[ii];
|
||||
if (constraint->getData().getOrder() == (int)i) {
|
||||
if (constraint->getData().getOrder() == i) {
|
||||
sortPathConstraint(constraint);
|
||||
i++;
|
||||
goto continue_outer;
|
||||
@ -407,6 +421,7 @@ void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHe
|
||||
|
||||
for (size_t i = 0; i < _drawOrder.size(); ++i) {
|
||||
Slot *slot = _drawOrder[i];
|
||||
if (!slot->_bone._active) continue;
|
||||
size_t verticesLength = 0;
|
||||
Attachment *attachment = slot->getAttachment();
|
||||
|
||||
@ -536,6 +551,9 @@ void Skeleton::setScaleY(float inValue) {
|
||||
}
|
||||
|
||||
void Skeleton::sortIkConstraint(IkConstraint *constraint) {
|
||||
constraint->_active = constraint->_target->_active && (!constraint->_data.isSkinRequired() || (_skin && _skin->_constraints.contains(&constraint->_data)));
|
||||
if (!constraint->_active) return;
|
||||
|
||||
Bone *target = constraint->getTarget();
|
||||
sortBone(target);
|
||||
|
||||
@ -555,6 +573,9 @@ void Skeleton::sortIkConstraint(IkConstraint *constraint) {
|
||||
}
|
||||
|
||||
void Skeleton::sortPathConstraint(PathConstraint *constraint) {
|
||||
constraint->_active = constraint->_target->_bone._active && (!constraint->_data.isSkinRequired() || (_skin && _skin->_constraints.contains(&constraint->_data)));
|
||||
if (!constraint->_active) return;
|
||||
|
||||
Slot *slot = constraint->getTarget();
|
||||
int slotIndex = slot->getData().getIndex();
|
||||
Bone &slotBone = slot->getBone();
|
||||
@ -583,6 +604,9 @@ void Skeleton::sortPathConstraint(PathConstraint *constraint) {
|
||||
}
|
||||
|
||||
void Skeleton::sortTransformConstraint(TransformConstraint *constraint) {
|
||||
constraint->_active = constraint->_target->_active && (!constraint->_data.isSkinRequired() || (_skin && _skin->_constraints.contains(&constraint->_data)));
|
||||
if (!constraint->_active) return;
|
||||
|
||||
sortBone(constraint->getTarget());
|
||||
|
||||
Vector<Bone *> &constrained = constraint->getBones();
|
||||
@ -646,6 +670,7 @@ void Skeleton::sortBone(Bone *bone) {
|
||||
void Skeleton::sortReset(Vector<Bone *> &bones) {
|
||||
for (size_t i = 0, n = bones.size(); i < n; ++i) {
|
||||
Bone *bone = bones[i];
|
||||
if (!bone->_active) continue;
|
||||
if (bone->_sorted) sortReset(bone->getChildren());
|
||||
bone->_sorted = false;
|
||||
}
|
||||
|
||||
@ -144,6 +144,10 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
||||
skeletonData->_audioPath.own(readString(input));
|
||||
}
|
||||
|
||||
int numStrings = readVarint(input, true);
|
||||
for (int i = 0; i < numStrings; i++)
|
||||
skeletonData->_strings.add(readString(input));
|
||||
|
||||
/* Bones. */
|
||||
int numBones = readVarint(input, true);
|
||||
skeletonData->_bones.setSize(numBones, 0);
|
||||
@ -160,6 +164,7 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
||||
data->_shearY = readFloat(input);
|
||||
data->_length = readFloat(input) * _scale;
|
||||
data->_transformMode = static_cast<TransformMode>(readVarint(input, true));
|
||||
data->_skinRequired = readBoolean(input);
|
||||
if (nonessential) {
|
||||
/* Skip bone color. */
|
||||
readInt(input);
|
||||
@ -184,7 +189,7 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
||||
slotData->getDarkColor().set(r / 255.0f, g / 255.0f, b / 255.0f, 1);
|
||||
slotData->setHasDarkColor(true);
|
||||
}
|
||||
slotData->_attachmentName.own(readString(input));
|
||||
slotData->_attachmentName = readStringRef(input, skeletonData);
|
||||
slotData->_blendMode = static_cast<BlendMode>(readVarint(input, true));
|
||||
skeletonData->_slots[i] = slotData;
|
||||
}
|
||||
@ -195,7 +200,8 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
||||
for (int i = 0; i < ikConstraintsCount; ++i) {
|
||||
const char *name = readString(input);
|
||||
IkConstraintData *data = new(__FILE__, __LINE__) IkConstraintData(String(name, true));
|
||||
data->_order = readVarint(input, true);
|
||||
data->setOrder(readVarint(input, true));
|
||||
data->setSkinRequired(readBoolean(input));
|
||||
int bonesCount = readVarint(input, true);
|
||||
data->_bones.setSize(bonesCount, 0);
|
||||
for (int ii = 0; ii < bonesCount; ++ii) {
|
||||
@ -216,7 +222,8 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
||||
for (int i = 0; i < transformConstraintsCount; ++i) {
|
||||
const char *name = readString(input);
|
||||
TransformConstraintData *data = new(__FILE__, __LINE__) TransformConstraintData(String(name, true));
|
||||
data->_order = readVarint(input, true);
|
||||
data->setOrder(readVarint(input, true));
|
||||
data->setSkinRequired(readBoolean(input));
|
||||
int bonesCount = readVarint(input, true);
|
||||
data->_bones.setSize(bonesCount, 0);
|
||||
for (int ii = 0; ii < bonesCount; ++ii) {
|
||||
@ -244,7 +251,8 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
||||
for (int i = 0; i < pathConstraintsCount; ++i) {
|
||||
const char *name = readString(input);
|
||||
PathConstraintData *data = new(__FILE__, __LINE__) PathConstraintData(String(name, true));
|
||||
data->_order = readVarint(input, true);
|
||||
data->setOrder(readVarint(input, true));
|
||||
data->setSkinRequired(readBoolean(input));
|
||||
int bonesCount = readVarint(input, true);
|
||||
data->_bones.setSize(bonesCount, 0);
|
||||
for (int ii = 0; ii < bonesCount; ++ii) {
|
||||
@ -266,20 +274,15 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
||||
}
|
||||
|
||||
/* Default skin. */
|
||||
skeletonData->_defaultSkin = readSkin(input, "default", skeletonData, nonessential);
|
||||
int skinsCount = readVarint(input, true);
|
||||
if (skeletonData->_defaultSkin) {
|
||||
++skinsCount;
|
||||
}
|
||||
skeletonData->_skins.setSize(skinsCount, 0);
|
||||
if (skeletonData->_defaultSkin) {
|
||||
skeletonData->_skins[0] = skeletonData->_defaultSkin;
|
||||
Skin* defaultSkin = readSkin(input, true, skeletonData, nonessential);
|
||||
if (defaultSkin) {
|
||||
skeletonData->_defaultSkin = defaultSkin;
|
||||
skeletonData->_skins.add(defaultSkin);
|
||||
}
|
||||
|
||||
/* Skins. */
|
||||
for (size_t i = skeletonData->_defaultSkin ? 1 : 0; i < skeletonData->_skins.size(); ++i) {
|
||||
String skinName(readString(input), true);
|
||||
skeletonData->_skins[i] = readSkin(input, skinName, skeletonData, nonessential);
|
||||
for (size_t i = 0, n = (size_t)readVarint(input, true); i < n; ++i) {
|
||||
skeletonData->_skins.add(readSkin(input, false, skeletonData, nonessential));
|
||||
}
|
||||
|
||||
/* Linked meshes. */
|
||||
@ -312,8 +315,8 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
|
||||
int eventsCount = readVarint(input, true);
|
||||
skeletonData->_events.setSize(eventsCount, 0);
|
||||
for (int i = 0; i < eventsCount; ++i) {
|
||||
const char *name = readString(input);
|
||||
EventData *eventData = new(__FILE__, __LINE__) EventData(String(name, true));
|
||||
const char *name = readStringRef(input, skeletonData);
|
||||
EventData *eventData = new(__FILE__, __LINE__) EventData(String(name));
|
||||
eventData->_intValue = readVarint(input, false);
|
||||
eventData->_floatValue = readFloat(input);
|
||||
eventData->_stringValue.own(readString(input));
|
||||
@ -381,6 +384,11 @@ char *SkeletonBinary::readString(DataInput *input) {
|
||||
return string;
|
||||
}
|
||||
|
||||
char* SkeletonBinary::readStringRef(DataInput* input, SkeletonData* skeletonData) {
|
||||
int index = readVarint(input, true);
|
||||
return index == 0 ? nullptr : skeletonData->_strings[index - 1];
|
||||
}
|
||||
|
||||
float SkeletonBinary::readFloat(DataInput *input) {
|
||||
union {
|
||||
int intValue;
|
||||
@ -447,14 +455,27 @@ int SkeletonBinary::readVarint(DataInput *input, bool optimizePositive) {
|
||||
}
|
||||
|
||||
Skin *
|
||||
SkeletonBinary::readSkin(DataInput *input, const String &skinName, SkeletonData *skeletonData, bool nonessential) {
|
||||
int slotCount = readVarint(input, true);
|
||||
if (slotCount == 0) return NULL;
|
||||
Skin *skin = new(__FILE__, __LINE__) Skin(skinName);
|
||||
for (int i = 0; i < slotCount; ++i) {
|
||||
SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential) {
|
||||
Skin *skin = new(__FILE__, __LINE__) Skin(defaultSkin ? "default" : readStringRef(input, skeletonData));
|
||||
|
||||
if (!defaultSkin) {
|
||||
for (int i = 0, n = readVarint(input, true); i < n; i++)
|
||||
skin->getBones().add(skeletonData->_bones[readVarint(input, true)]);
|
||||
|
||||
for (int i = 0, n = readVarint(input, true); i < n; i++)
|
||||
skin->getConstraints().add(skeletonData->_ikConstraints[readVarint(input, true)]);
|
||||
|
||||
for (int i = 0, n = readVarint(input, true); i < n; i++)
|
||||
skin->getConstraints().add(skeletonData->_transformConstraints[readVarint(input, true)]);
|
||||
|
||||
for (int i = 0, n = readVarint(input, true); i < n; i++)
|
||||
skin->getConstraints().add(skeletonData->_pathConstraints[readVarint(input, true)]);
|
||||
}
|
||||
|
||||
for (int i = 0, n = readVarint(input, true); i < n; ++i) {
|
||||
int slotIndex = readVarint(input, true);
|
||||
for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) {
|
||||
String name(readString(input), true);
|
||||
String name(readStringRef(input, skeletonData));
|
||||
Attachment *attachment = readAttachment(input, skin, slotIndex, name, skeletonData, nonessential);
|
||||
if (attachment) skin->setAttachment(slotIndex, String(name), attachment);
|
||||
}
|
||||
@ -464,13 +485,13 @@ SkeletonBinary::readSkin(DataInput *input, const String &skinName, SkeletonData
|
||||
|
||||
Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName,
|
||||
SkeletonData *skeletonData, bool nonessential) {
|
||||
String name(readString(input), true);
|
||||
String name(readStringRef(input, skeletonData));
|
||||
if (name.isEmpty()) name = attachmentName;
|
||||
|
||||
AttachmentType type = static_cast<AttachmentType>(readByte(input));
|
||||
switch (type) {
|
||||
case AttachmentType_Region: {
|
||||
String path(readString(input), true);
|
||||
String path(readStringRef(input, skeletonData));
|
||||
if (path.isEmpty()) path = name;
|
||||
RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path));
|
||||
region->_path = path;
|
||||
@ -500,7 +521,7 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
||||
case AttachmentType_Mesh: {
|
||||
int vertexCount;
|
||||
MeshAttachment *mesh;
|
||||
String path(readString(input), true);
|
||||
String path(readStringRef(input, skeletonData));
|
||||
if (path.isEmpty()) path = name;
|
||||
|
||||
mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path));
|
||||
@ -524,14 +545,14 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
|
||||
return mesh;
|
||||
}
|
||||
case AttachmentType_Linkedmesh: {
|
||||
String path(readString(input), true);
|
||||
String path(readStringRef(input, skeletonData));
|
||||
if (path.isEmpty()) path = name;
|
||||
|
||||
MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path));
|
||||
mesh->_path = path;
|
||||
readColor(input, mesh->getColor());
|
||||
String skinName(readString(input), true);
|
||||
String parent(readString(input), true);
|
||||
String skinName(readStringRef(input, skeletonData));
|
||||
String parent(readStringRef(input, skeletonData));
|
||||
bool inheritDeform = readBoolean(input);
|
||||
if (nonessential) {
|
||||
mesh->_width = readFloat(input) * _scale;
|
||||
@ -661,7 +682,7 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
||||
timeline->_slotIndex = slotIndex;
|
||||
for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
|
||||
float time = readFloat(input);
|
||||
String attachmentName = String(readString(input), true);
|
||||
String attachmentName(readStringRef(input, skeletonData));
|
||||
timeline->setFrame(frameIndex, time, attachmentName);
|
||||
}
|
||||
timelines.add(timeline);
|
||||
@ -888,8 +909,8 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
|
||||
for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) {
|
||||
int slotIndex = readVarint(input, true);
|
||||
for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) {
|
||||
const char *attachmentName = readString(input);
|
||||
Attachment *baseAttachment = skin->getAttachment(slotIndex, String(attachmentName, true));
|
||||
const char *attachmentName = readStringRef(input, skeletonData);
|
||||
Attachment *baseAttachment = skin->getAttachment(slotIndex, String(attachmentName));
|
||||
|
||||
if (!baseAttachment) {
|
||||
ContainerUtil::cleanUpVectorOfPointers(timelines);
|
||||
|
||||
@ -71,6 +71,9 @@ SkeletonData::~SkeletonData() {
|
||||
ContainerUtil::cleanUpVectorOfPointers(_ikConstraints);
|
||||
ContainerUtil::cleanUpVectorOfPointers(_transformConstraints);
|
||||
ContainerUtil::cleanUpVectorOfPointers(_pathConstraints);
|
||||
for (size_t i = 0; i < _strings.size(); i++) {
|
||||
SpineExtension::free(_strings[i], __FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
BoneData *SkeletonData::findBone(const String &boneName) {
|
||||
|
||||
@ -189,6 +189,7 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
if (strcmp(transformMode, "noScaleOrReflection") == 0) {
|
||||
data->_transformMode = TransformMode_NoScaleOrReflection;
|
||||
}
|
||||
data->_skinRequired = Json::getBoolean(boneMap, "skin", false);
|
||||
|
||||
skeletonData->_bones[i] = data;
|
||||
bonesCount++;
|
||||
@ -267,7 +268,8 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
IkConstraintData *data = new(__FILE__, __LINE__) IkConstraintData(
|
||||
Json::getString(constraintMap, "name", 0));
|
||||
|
||||
data->_order = Json::getInt(constraintMap, "order", 0);
|
||||
data->setOrder(Json::getInt(constraintMap, "order", 0));
|
||||
data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false));
|
||||
|
||||
boneMap = Json::getItem(constraintMap, "bones");
|
||||
data->_bones.ensureCapacity(boneMap->_size);
|
||||
@ -311,7 +313,8 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
TransformConstraintData *data = new(__FILE__, __LINE__) TransformConstraintData(
|
||||
Json::getString(constraintMap, "name", 0));
|
||||
|
||||
data->_order = Json::getInt(constraintMap, "order", 0);
|
||||
data->setOrder(Json::getInt(constraintMap, "order", 0));
|
||||
data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false));
|
||||
|
||||
boneMap = Json::getItem(constraintMap, "bones");
|
||||
data->_bones.ensureCapacity(boneMap->_size);
|
||||
@ -364,7 +367,8 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
PathConstraintData *data = new(__FILE__, __LINE__) PathConstraintData(
|
||||
Json::getString(constraintMap, "name", 0));
|
||||
|
||||
data->_order = Json::getInt(constraintMap, "order", 0);
|
||||
data->setOrder(Json::getInt(constraintMap, "order", 0));
|
||||
data->setSkinRequired(Json::getBoolean(constraintMap, "skin", false));
|
||||
|
||||
boneMap = Json::getItem(constraintMap, "bones");
|
||||
data->_bones.ensureCapacity(boneMap->_size);
|
||||
@ -438,15 +442,67 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
Json *attachmentsMap;
|
||||
Json *curves;
|
||||
|
||||
Skin *skin = new(__FILE__, __LINE__) Skin(skinMap->_name);
|
||||
Skin *skin = new(__FILE__, __LINE__) Skin(Json::getString(skinMap, "name", ""));
|
||||
|
||||
Json *item = Json::getItem(skinMap, "bones");
|
||||
if (item) {
|
||||
for (item = item->_child; item; item = item->_next) {
|
||||
BoneData* data = skeletonData->findBone(item->_valueString);
|
||||
if (!data) {
|
||||
delete skeletonData;
|
||||
setError(root, String("Skin bone not found: "), item->_valueString);
|
||||
return NULL;
|
||||
}
|
||||
skin->getBones().add(data);
|
||||
}
|
||||
}
|
||||
|
||||
item = Json::getItem(skinMap, "ik");
|
||||
if (item) {
|
||||
for (item = item->_child; item; item = item->_next) {
|
||||
IkConstraintData* data = skeletonData->findIkConstraint(item->_valueString);
|
||||
if (!data) {
|
||||
delete skeletonData;
|
||||
setError(root, String("Skin IK constraint not found: "), item->_valueString);
|
||||
return NULL;
|
||||
}
|
||||
skin->getConstraints().add(data);
|
||||
}
|
||||
}
|
||||
|
||||
item = Json::getItem(skinMap, "transform");
|
||||
if (item) {
|
||||
for (item = item->_child; item; item = item->_next) {
|
||||
TransformConstraintData* data = skeletonData->findTransformConstraint(item->_valueString);
|
||||
if (!data) {
|
||||
delete skeletonData;
|
||||
setError(root, String("Skin transform constraint not found: "), item->_valueString);
|
||||
return NULL;
|
||||
}
|
||||
skin->getConstraints().add(data);
|
||||
}
|
||||
}
|
||||
|
||||
item = Json::getItem(skinMap, "path");
|
||||
if (item) {
|
||||
for (item = item->_child; item; item = item->_next) {
|
||||
PathConstraintData* data = skeletonData->findPathConstraint(item->_valueString);
|
||||
if (!data) {
|
||||
delete skeletonData;
|
||||
setError(root, String("Skin path constraint not found: "), item->_valueString);
|
||||
return NULL;
|
||||
}
|
||||
skin->getConstraints().add(data);
|
||||
}
|
||||
}
|
||||
|
||||
skeletonData->_skins[skinsIndex++] = skin;
|
||||
if (strcmp(skinMap->_name, "default") == 0) {
|
||||
if (strcmp(Json::getString(skinMap, "name", ""), "default") == 0) {
|
||||
skeletonData->_defaultSkin = skin;
|
||||
}
|
||||
|
||||
for (attachmentsMap = skinMap->_child; attachmentsMap; attachmentsMap = attachmentsMap->_next) {
|
||||
int slotIndex = skeletonData->findSlotIndex(attachmentsMap->_name);
|
||||
for (attachmentsMap = Json::getItem(skinMap, "attachments")->_child; attachmentsMap; attachmentsMap = attachmentsMap->_next) {
|
||||
SlotData* slot = skeletonData->findSlot(attachmentsMap->_name);
|
||||
Json *attachmentMap;
|
||||
|
||||
for (attachmentMap = attachmentsMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) {
|
||||
@ -574,7 +630,7 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
String(Json::getString(
|
||||
attachmentMap,
|
||||
"skin", 0)),
|
||||
slotIndex,
|
||||
slot->getIndex(),
|
||||
String(entry->_valueString), inheritDeform);
|
||||
_linkedMeshes.add(linkedMesh);
|
||||
}
|
||||
@ -640,7 +696,7 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
}
|
||||
}
|
||||
|
||||
skin->setAttachment(slotIndex, skinAttachmentName, attachment);
|
||||
skin->setAttachment(slot->getIndex(), skinAttachmentName, attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -746,13 +802,12 @@ void SkeletonJson::readCurve(Json *frame, CurveTimeline *timeline, size_t frameI
|
||||
}
|
||||
if (curve->_type == Json::JSON_STRING && strcmp(curve->_valueString, "stepped") == 0) {
|
||||
timeline->setStepped(frameIndex);
|
||||
} else if (curve->_type == Json::JSON_ARRAY) {
|
||||
Json *child0 = curve->_child;
|
||||
Json *child1 = child0->_next;
|
||||
Json *child2 = child1->_next;
|
||||
Json *child3 = child2->_next;
|
||||
timeline->setCurve(frameIndex, child0->_valueFloat, child1->_valueFloat, child2->_valueFloat,
|
||||
child3->_valueFloat);
|
||||
} else {
|
||||
float c1 = Json::getFloat(frame, "curve", 0);
|
||||
float c2 = Json::getFloat(frame, "c2", 0);
|
||||
float c3 = Json::getFloat(frame, "c3", 1);
|
||||
float c4 = Json::getFloat(frame, "c4", 1);
|
||||
timeline->setCurve(frameIndex, c1, c2, c3, c4);
|
||||
}
|
||||
}
|
||||
|
||||
@ -905,9 +960,11 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
|
||||
int isShear = strcmp(timelineMap->_name, "shear") == 0;
|
||||
if (isScale || isTranslate || isShear) {
|
||||
float timelineScale = isTranslate ? _scale : 1;
|
||||
float defaultValue = 0;
|
||||
TranslateTimeline *timeline = 0;
|
||||
if (isScale) {
|
||||
timeline = new(__FILE__, __LINE__) ScaleTimeline(timelineMap->_size);
|
||||
defaultValue = 1;
|
||||
} else if (isTranslate) {
|
||||
timeline = new(__FILE__, __LINE__) TranslateTimeline(timelineMap->_size);
|
||||
} else if (isShear) {
|
||||
@ -917,8 +974,8 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
|
||||
|
||||
for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) {
|
||||
timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0),
|
||||
Json::getFloat(valueMap, "x", 0) * timelineScale,
|
||||
Json::getFloat(valueMap, "y", 0) * timelineScale);
|
||||
Json::getFloat(valueMap, "x", defaultValue) * timelineScale,
|
||||
Json::getFloat(valueMap, "y", defaultValue) * timelineScale);
|
||||
readCurve(valueMap, timeline, frameIndex);
|
||||
}
|
||||
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/ConstraintData.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@ -157,6 +158,12 @@ void Skin::attachAll(Skeleton &skeleton, Skin &oldSkin) {
|
||||
}
|
||||
|
||||
void Skin::addSkin(Skin* other) {
|
||||
for (int i = 0; i < other->getBones().size(); i++)
|
||||
if (!_bones.contains(other->getBones()[i])) _bones.add(other->getBones()[i]);
|
||||
|
||||
for (int i = 0; i < other->getConstraints().size(); i++)
|
||||
if (!_constraints.contains(other->getConstraints()[i])) _constraints.add(other->getConstraints()[i]);
|
||||
|
||||
AttachmentMap::Entries entries = other->getAttachments();
|
||||
while(entries.hasNext()) {
|
||||
AttachmentMap::Entry& entry = entries.next();
|
||||
@ -165,6 +172,12 @@ void Skin::addSkin(Skin* other) {
|
||||
}
|
||||
|
||||
void Skin::copySkin(Skin* other) {
|
||||
for (int i = 0; i < other->getBones().size(); i++)
|
||||
if (!_bones.contains(other->getBones()[i])) _bones.add(other->getBones()[i]);
|
||||
|
||||
for (int i = 0; i < other->getConstraints().size(); i++)
|
||||
if (!_constraints.contains(other->getConstraints()[i])) _constraints.add(other->getConstraints()[i]);
|
||||
|
||||
AttachmentMap::Entries entries = other->getAttachments();
|
||||
while(entries.hasNext()) {
|
||||
AttachmentMap::Entry& entry = entries.next();
|
||||
@ -175,3 +188,11 @@ void Skin::copySkin(Skin* other) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector<ConstraintData*>& Skin::getConstraints() {
|
||||
return _constraints;
|
||||
}
|
||||
|
||||
Vector<BoneData*>& Skin::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
|
||||
@ -41,9 +41,9 @@
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(TransformConstraint, Constraint)
|
||||
RTTI_IMPL(TransformConstraint, Updatable)
|
||||
|
||||
TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : Constraint(),
|
||||
TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : Updatable(),
|
||||
_data(data),
|
||||
_target(skeleton.findBone(
|
||||
data.getTarget()->getName())),
|
||||
@ -54,7 +54,8 @@ TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton
|
||||
_scaleMix(
|
||||
data.getScaleMix()),
|
||||
_shearMix(
|
||||
data.getShearMix()) {
|
||||
data.getShearMix()),
|
||||
_active(false) {
|
||||
_bones.ensureCapacity(_data.getBones().size());
|
||||
for (size_t i = 0; i < _data.getBones().size(); ++i) {
|
||||
BoneData *boneData = _data.getBones()[i];
|
||||
@ -380,3 +381,12 @@ void TransformConstraint::applyRelativeLocal() {
|
||||
bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY);
|
||||
}
|
||||
}
|
||||
|
||||
bool TransformConstraint::isActive() {
|
||||
return _active;
|
||||
}
|
||||
|
||||
void TransformConstraint::setActive(bool inValue) {
|
||||
_active = inValue;
|
||||
}
|
||||
|
||||
|
||||
@ -39,8 +39,7 @@
|
||||
|
||||
using namespace spine;
|
||||
TransformConstraintData::TransformConstraintData(const String &name) :
|
||||
_name(name),
|
||||
_order(0),
|
||||
ConstraintData(name),
|
||||
_target(NULL),
|
||||
_rotateMix(0),
|
||||
_translateMix(0),
|
||||
@ -54,15 +53,6 @@ TransformConstraintData::TransformConstraintData(const String &name) :
|
||||
_offsetShearY(0),
|
||||
_relative(false),
|
||||
_local(false) {
|
||||
assert(_name.length() > 0);
|
||||
}
|
||||
|
||||
const String &TransformConstraintData::getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
int TransformConstraintData::getOrder() {
|
||||
return _order;
|
||||
}
|
||||
|
||||
Vector<BoneData *> &TransformConstraintData::getBones() {
|
||||
|
||||
@ -71,6 +71,7 @@ void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, floa
|
||||
|
||||
TransformConstraint *constraintP = skeleton._transformConstraints[_transformConstraintIndex];
|
||||
TransformConstraint &constraint = *constraintP;
|
||||
if (!constraint.isActive()) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
|
||||
@ -68,6 +68,7 @@ void TranslateTimeline::apply(Skeleton &skeleton, float lastTime, float time, Ve
|
||||
|
||||
Bone *boneP = skeleton._bones[_boneIndex];
|
||||
Bone &bone = *boneP;
|
||||
if (!bone._active) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
#include <spine/Event.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/TimelineType.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
@ -75,6 +76,7 @@ void TwoColorTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vec
|
||||
|
||||
Slot *slotP = skeleton._slots[_slotIndex];
|
||||
Slot &slot = *slotP;
|
||||
if (!slot._bone.isActive()) return;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
// Time is before first frame.
|
||||
|
||||
@ -128,7 +128,7 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
|
||||
if (!attachment) continue;
|
||||
|
||||
// Early out if slot is invisible
|
||||
if (slot->color.a == 0) {
|
||||
if (slot->color.a == 0 || !slot->bone->active) {
|
||||
spSkeletonClipping_clipEnd(clipper, slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -473,7 +473,7 @@ int main () {
|
||||
SpineExtension::setInstance(&dbgExtension);
|
||||
|
||||
testcase(goblins, "data/goblins-pro.json", "data/goblins-pro.skel", "data/goblins-pma.atlas", 1.4f);
|
||||
/*testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl-pma.atlas", 0.5f);
|
||||
testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl-pma.atlas", 0.5f);
|
||||
testcase(spineboy, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f);
|
||||
testcase(stretchymanStrechyIk, "data/stretchyman-stretchy-ik-pro.json", "data/stretchyman-stretchy-ik-pro.skel", "data/stretchyman-pma.atlas", 0.6f);
|
||||
testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor-pma.atlas", 0.5f);
|
||||
@ -481,7 +481,7 @@ int main () {
|
||||
testcase(vine, "data/vine-pro.json", "data/vine-pro.skel", "data/vine-pma.atlas", 0.5f);
|
||||
testcase(tank, "data/tank-pro.json", "data/tank-pro.skel", "data/tank-pma.atlas", 0.2f);
|
||||
testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor-pma.atlas", 0.5f);
|
||||
testcase(stretchyman, "data/stretchyman-pro.json", "data/stretchyman-pro.skel", "data/stretchyman-pma.atlas", 0.6f);*/
|
||||
testcase(stretchyman, "data/stretchyman-pro.json", "data/stretchyman-pro.skel", "data/stretchyman-pma.atlas", 0.6f);
|
||||
|
||||
dbgExtension.reportLeaks();
|
||||
return 0;
|
||||
|
||||
@ -102,8 +102,8 @@ void SkeletonDrawable::draw(RenderTarget &target, RenderStates states) const {
|
||||
Attachment *attachment = slot.getAttachment();
|
||||
if (!attachment) continue;
|
||||
|
||||
// Early out if the slot color is 0
|
||||
if (slot.getColor().a == 0) {
|
||||
// Early out if the slot color is 0 or the bone is not active
|
||||
if (slot.getColor().a == 0 || !slot.getBone().isActive()) {
|
||||
clipper.clipEnd(slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user