[cpp] More physics porting, fix sanitizer issues

This commit is contained in:
Mario Zechner 2024-01-03 09:47:39 +01:00
parent 1547e09eab
commit a190bc8899
17 changed files with 220 additions and 162 deletions

View File

@ -43,96 +43,101 @@ namespace spine {
class SP_API PhysicsConstraint : public Updatable { class SP_API PhysicsConstraint : public Updatable {
friend class Skeleton;
RTTI_DECL RTTI_DECL
public: public:
explicit PhysicsConstraint(PhysicsConstraintData& data, Skeleton& skeleton); PhysicsConstraint(PhysicsConstraintData& data, Skeleton& skeleton);
PhysicsConstraintData &getData();
void setBone(Bone* bone); void setBone(Bone* bone);
Bone* getBone() const; Bone* getBone();
void setInertia(float value); void setInertia(float value);
float getInertia() const; float getInertia();
void setStrength(float value); void setStrength(float value);
float getStrength() const; float getStrength();
void setDamping(float value); void setDamping(float value);
float getDamping() const; float getDamping();
void setMassInverse(float value); void setMassInverse(float value);
float getMassInverse() const; float getMassInverse();
void setWind(float value); void setWind(float value);
float getWind() const; float getWind();
void setGravity(float value); void setGravity(float value);
float getGravity() const; float getGravity();
void setMix(float value); void setMix(float value);
float getMix() const; float getMix();
void setReset(bool value); void setReset(bool value);
bool getReset() const; bool getReset();
void setUx(float value); void setUx(float value);
float getUx() const; float getUx();
void setUy(float value); void setUy(float value);
float getUy() const; float getUy();
void setCx(float value); void setCx(float value);
float getCx() const; float getCx();
void setCy(float value); void setCy(float value);
float getCy() const; float getCy();
void setTx(float value); void setTx(float value);
float getTx() const; float getTx();
void setTy(float value); void setTy(float value);
float getTy() const; float getTy();
void setXOffset(float value); void setXOffset(float value);
float getXOffset() const; float getXOffset();
void setXVelocity(float value); void setXVelocity(float value);
float getXVelocity() const; float getXVelocity();
void setYOffset(float value); void setYOffset(float value);
float getYOffset() const; float getYOffset();
void setYVelocity(float value); void setYVelocity(float value);
float getYVelocity() const; float getYVelocity();
void setRotateOffset(float value); void setRotateOffset(float value);
float getRotateOffset() const; float getRotateOffset();
void setRotateVelocity(float value); void setRotateVelocity(float value);
float getRotateVelocity() const; float getRotateVelocity();
void setScaleOffset(float value); void setScaleOffset(float value);
float getScaleOffset() const; float getScaleOffset();
void setScaleVelocity(float value); void setScaleVelocity(float value);
float getScaleVelocity() const; float getScaleVelocity();
void setActive(bool value); void setActive(bool value);
bool isActive() const; bool isActive();
void setRemaining(float value); void setRemaining(float value);
float getRemaining() const; float getRemaining();
void setLastTime(float value); void setLastTime(float value);
float getLastTime() const; float getLastTime();
void reset(); void reset();
void setToSetupPose(); void setToSetupPose();
void update(Physics physics) override; virtual void update(Physics physics);
private: private:
const PhysicsConstraintData& _data; PhysicsConstraintData& _data;
Bone* _bone; Bone* _bone;
float _inertia; float _inertia;

View File

@ -35,6 +35,7 @@
#include <spine/SpineObject.h> #include <spine/SpineObject.h>
#include <spine/SpineString.h> #include <spine/SpineString.h>
#include <spine/Color.h> #include <spine/Color.h>
#include <spine/Physics.h>
namespace spine { namespace spine {
class SkeletonData; class SkeletonData;
@ -125,10 +126,13 @@ namespace spine {
void printUpdateCache(); void printUpdateCache();
/// Updates the world transform for each bone and applies constraints. /// Updates the world transform for each bone and applies all constraints.
void updateWorldTransform(); ///
/// See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
/// Runtimes Guide.
void updateWorldTransform(Physics physics);
void updateWorldTransform(Bone *parent); void updateWorldTransform(Physics physics, Bone *parent);
/// Sets the bones, constraints, and slots to their setup pose values. /// Sets the bones, constraints, and slots to their setup pose values.
void setToSetupPose(); void setToSetupPose();
@ -174,6 +178,9 @@ namespace spine {
/// @return May be NULL. /// @return May be NULL.
PathConstraint *findPathConstraint(const String &constraintName); PathConstraint *findPathConstraint(const String &constraintName);
/// @return May be NULL.
PhysicsConstraint *findPhysicsConstraint(const String &constraintName);
/// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. /// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
/// @param outX The horizontal distance between the skeleton origin and the left side of the AABB. /// @param outX The horizontal distance between the skeleton origin and the left side of the AABB.
/// @param outY The vertical distance between the skeleton origin and the bottom side of the AABB. /// @param outY The vertical distance between the skeleton origin and the bottom side of the AABB.
@ -200,6 +207,8 @@ namespace spine {
Vector<TransformConstraint *> &getTransformConstraints(); Vector<TransformConstraint *> &getTransformConstraints();
Vector<PhysicsConstraint *> &getPhysicsConstraints();
Skin *getSkin(); Skin *getSkin();
Color &getColor(); Color &getColor();
@ -224,7 +233,7 @@ namespace spine {
float getTime(); float getTime();
float setTime(float time); void setTime(float time);
void update(float delta); void update(float delta);
@ -236,6 +245,7 @@ namespace spine {
Vector<IkConstraint *> _ikConstraints; Vector<IkConstraint *> _ikConstraints;
Vector<TransformConstraint *> _transformConstraints; Vector<TransformConstraint *> _transformConstraints;
Vector<PathConstraint *> _pathConstraints; Vector<PathConstraint *> _pathConstraints;
Vector<PhysicsConstraint *> _physicsConstraints;
Vector<Updatable *> _updateCache; Vector<Updatable *> _updateCache;
Skin *_skin; Skin *_skin;
Color _color; Color _color;

View File

@ -50,6 +50,8 @@ namespace spine {
class PathConstraintData; class PathConstraintData;
class PhysicsConstraintData;
/// Stores the setup pose and all of the stateless data for a skeleton. /// Stores the setup pose and all of the stateless data for a skeleton.
class SP_API SkeletonData : public SpineObject { class SP_API SkeletonData : public SpineObject {
friend class SkeletonBinary; friend class SkeletonBinary;
@ -89,6 +91,9 @@ namespace spine {
/// @return May be NULL. /// @return May be NULL.
PathConstraintData *findPathConstraint(const String &constraintName); PathConstraintData *findPathConstraint(const String &constraintName);
/// @return May be NULL.
PhysicsConstraintData *findPhysicsConstraint(const String &constraintName);
const String &getName(); const String &getName();
void setName(const String &inValue); void setName(const String &inValue);
@ -118,6 +123,8 @@ namespace spine {
Vector<PathConstraintData *> &getPathConstraints(); Vector<PathConstraintData *> &getPathConstraints();
Vector<PhysicsConstraintData *> &getPhysicsConstraints();
float getX(); float getX();
void setX(float inValue); void setX(float inValue);
@ -167,6 +174,7 @@ namespace spine {
Vector<IkConstraintData *> _ikConstraints; Vector<IkConstraintData *> _ikConstraints;
Vector<TransformConstraintData *> _transformConstraints; Vector<TransformConstraintData *> _transformConstraints;
Vector<PathConstraintData *> _pathConstraints; Vector<PathConstraintData *> _pathConstraints;
Vector<PhysicsConstraintData *> _physicsConstraints;
float _x, _y, _width, _height; float _x, _y, _width, _height;
String _version; String _version;
String _hash; String _hash;

View File

@ -27,11 +27,11 @@
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#ifndef SPINE_VERTEXEFFECT_H_ #ifndef SPINE_VERSION_H_
#define SPINE_VERTEXEFFECT_H_ #define SPINE_VERSION_H_
#define SPINE_MAJOR_VERSION 4 #define SPINE_MAJOR_VERSION 4
#define SPINE_MINOR_VERSION 1 #define SPINE_MINOR_VERSION 2
#define SPINE_VERSION_STRING "4.1" #define SPINE_VERSION_STRING "4.2"
#endif #endif

View File

@ -72,6 +72,8 @@
#include <spine/PathConstraintMixTimeline.h> #include <spine/PathConstraintMixTimeline.h>
#include <spine/PathConstraintPositionTimeline.h> #include <spine/PathConstraintPositionTimeline.h>
#include <spine/PathConstraintSpacingTimeline.h> #include <spine/PathConstraintSpacingTimeline.h>
#include <spine/PhysicsConstraintData.h>
#include <spine/PhysicsConstraint.h>
#include <spine/PointAttachment.h> #include <spine/PointAttachment.h>
#include <spine/Pool.h> #include <spine/Pool.h>
#include <spine/PositionMode.h> #include <spine/PositionMode.h>

View File

@ -75,7 +75,7 @@ Bone::Bone(BoneData &data, Skeleton &skeleton, Bone *parent) : Updatable(),
setToSetupPose(); setToSetupPose();
} }
void Bone::update(Physics physics) { void Bone::update(Physics) {
updateWorldTransform(_ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY); updateWorldTransform(_ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY);
} }
@ -96,7 +96,7 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX,
_ashearY = shearY; _ashearY = shearY;
if (!parent) { /* Root bone. */ if (!parent) { /* Root bone. */
auto skeleton = this->_skeleton; Skeleton &skeleton = this->_skeleton;
float sx = skeleton.getScaleX(); float sx = skeleton.getScaleX();
float sy = skeleton.getScaleY(); float sy = skeleton.getScaleY();
float rx = (rotation + shearX) * MathUtil::Deg_Rad; float rx = (rotation + shearX) * MathUtil::Deg_Rad;
@ -522,7 +522,7 @@ void Bone::updateAppliedTransform() {
break; break;
} }
case TransformMode_NoScale: case TransformMode_NoScale:
case TransformMode_NoScaleOrReflection: case TransformMode_NoScaleOrReflection: {
float cos = MathUtil::cosDeg(_rotation), sin = MathUtil::sinDeg(_rotation); float cos = MathUtil::cosDeg(_rotation), sin = MathUtil::sinDeg(_rotation);
pa = (pa * cos + pb * sin) / _skeleton.getScaleX(); pa = (pa * cos + pb * sin) / _skeleton.getScaleX();
pc = (pc * cos + pd * sin) / _skeleton.getScaleY(); pc = (pc * cos + pd * sin) / _skeleton.getScaleY();
@ -531,7 +531,9 @@ void Bone::updateAppliedTransform() {
pa *= s; pa *= s;
pc *= s; pc *= s;
s = MathUtil::sqrt(pa * pa + pc * pc); s = MathUtil::sqrt(pa * pa + pc * pc);
if (_data.getTransformMode() == TransformMode_NoScale && pid < 0 != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0)) s = -s; if (_data.getTransformMode() == TransformMode_NoScale &&
pid < 0 != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0))
s = -s;
float r = MathUtil::Pi / 2 + MathUtil::atan2(pc, pa); float r = MathUtil::Pi / 2 + MathUtil::atan2(pc, pa);
pb = MathUtil::cos(r) * s; pb = MathUtil::cos(r) * s;
pd = MathUtil::sin(r) * s; pd = MathUtil::sin(r) * s;
@ -541,6 +543,10 @@ void Bone::updateAppliedTransform() {
ic = pc * pid; ic = pc * pid;
id = pa * pid; id = pa * pid;
break; break;
}
case TransformMode_Normal:
case TransformMode_OnlyTranslation:
break;
} }
ra = ia * _a - ib * _c; ra = ia * _a - ib * _c;
rb = ia * _b - ib * _d; rb = ia * _b - ib * _d;

View File

@ -283,7 +283,7 @@ IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Updatab
} }
} }
void IkConstraint::update(Physics physics) { void IkConstraint::update(Physics) {
if (_mix == 0) return; if (_mix == 0) return;
switch (_bones.size()) { switch (_bones.size()) {
case 1: { case 1: {
@ -369,7 +369,7 @@ void IkConstraint::setSoftness(float inValue) {
} }
void IkConstraint::setToSetupPose() { void IkConstraint::setToSetupPose() {
auto data = this->_data; IkConstraintData &data = this->_data;
this->_mix = data._mix; this->_mix = data._mix;
this->_softness = data._softness; this->_softness = data._softness;
this->_bendDirection = data._bendDirection; this->_bendDirection = data._bendDirection;

View File

@ -372,7 +372,6 @@ const char *Json::parseNumber(Json *item, const char *num) {
if (*ptr == 'e' || *ptr == 'E') { if (*ptr == 'e' || *ptr == 'E') {
double exponent = 0; double exponent = 0;
int expNegative = 0; int expNegative = 0;
int n = 0;
++ptr; ++ptr;
if (*ptr == '-') { if (*ptr == '-') {
@ -385,7 +384,6 @@ const char *Json::parseNumber(Json *item, const char *num) {
while (*ptr >= '0' && *ptr <= '9') { while (*ptr >= '0' && *ptr <= '9') {
exponent = (exponent * 10.0) + (*ptr - '0'); exponent = (exponent * 10.0) + (*ptr - '0');
++ptr; ++ptr;
++n;
} }
if (expNegative) { if (expNegative) {

View File

@ -66,7 +66,7 @@ PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : U
_segments.setSize(10, 0); _segments.setSize(10, 0);
} }
void PathConstraint::update(Physics physics) { void PathConstraint::update(Physics) {
Attachment *baseAttachment = _target->getAttachment(); Attachment *baseAttachment = _target->getAttachment();
if (baseAttachment == NULL || !baseAttachment->getRTTI().instanceOf(PathAttachment::rtti)) { if (baseAttachment == NULL || !baseAttachment->getRTTI().instanceOf(PathAttachment::rtti)) {
return; return;
@ -580,7 +580,7 @@ void PathConstraint::setActive(bool inValue) {
} }
void PathConstraint::setToSetupPose() { void PathConstraint::setToSetupPose() {
auto data = this->_data; PathConstraintData &data = this->_data;
this->_position = data._position; this->_position = data._position;
this->_spacing = data._spacing; this->_spacing = data._spacing;
this->_mixRotate = data._mixRotate; this->_mixRotate = data._mixRotate;

View File

@ -40,9 +40,7 @@ RTTI_IMPL(PhysicsConstraint, Updatable)
PhysicsConstraint::PhysicsConstraint(PhysicsConstraintData& data, Skeleton& skeleton) PhysicsConstraint::PhysicsConstraint(PhysicsConstraintData& data, Skeleton& skeleton)
: _data(data), _skeleton(skeleton) { : _data(data), _skeleton(skeleton) {
// Assuming 'bones' is a vector or similar container in 'Skeleton' _bone = skeleton.getBones()[data.getBone()->getIndex()];
// and 'index' is an accessible member of 'BoneData' in 'PhysicsConstraintData'
_bone = skeleton.getBones()[data.getBone()->getIndex()]; // Adjust based on actual data structure
_inertia = data.getInertia(); _inertia = data.getInertia();
_strength = data.getStrength(); _strength = data.getStrength();
@ -72,11 +70,15 @@ PhysicsConstraint::PhysicsConstraint(PhysicsConstraintData& data, Skeleton& skel
_lastTime = 0; _lastTime = 0;
} }
PhysicsConstraintData &PhysicsConstraint::getData() {
return _data;
}
void PhysicsConstraint::setBone(Bone* bone) { void PhysicsConstraint::setBone(Bone* bone) {
_bone = bone; _bone = bone;
} }
Bone* PhysicsConstraint::getBone() const { Bone* PhysicsConstraint::getBone(){
return _bone; return _bone;
} }
@ -84,7 +86,7 @@ void PhysicsConstraint::setInertia(float value) {
_inertia = value; _inertia = value;
} }
float PhysicsConstraint::getInertia() const { float PhysicsConstraint::getInertia(){
return _inertia; return _inertia;
} }
@ -92,7 +94,7 @@ void PhysicsConstraint::setStrength(float value) {
_strength = value; _strength = value;
} }
float PhysicsConstraint::getStrength() const { float PhysicsConstraint::getStrength(){
return _strength; return _strength;
} }
@ -100,7 +102,7 @@ void PhysicsConstraint::setDamping(float value) {
_damping = value; _damping = value;
} }
float PhysicsConstraint::getDamping() const { float PhysicsConstraint::getDamping(){
return _damping; return _damping;
} }
@ -108,7 +110,7 @@ void PhysicsConstraint::setMassInverse(float value) {
_massInverse = value; _massInverse = value;
} }
float PhysicsConstraint::getMassInverse() const { float PhysicsConstraint::getMassInverse(){
return _massInverse; return _massInverse;
} }
@ -116,7 +118,7 @@ void PhysicsConstraint::setWind(float value) {
_wind = value; _wind = value;
} }
float PhysicsConstraint::getWind() const { float PhysicsConstraint::getWind(){
return _wind; return _wind;
} }
@ -124,7 +126,7 @@ void PhysicsConstraint::setGravity(float value) {
_gravity = value; _gravity = value;
} }
float PhysicsConstraint::getGravity() const { float PhysicsConstraint::getGravity(){
return _gravity; return _gravity;
} }
@ -132,7 +134,7 @@ void PhysicsConstraint::setMix(float value) {
_mix = value; _mix = value;
} }
float PhysicsConstraint::getMix() const { float PhysicsConstraint::getMix(){
return _mix; return _mix;
} }
@ -140,7 +142,7 @@ void PhysicsConstraint::setReset(bool value) {
_reset = value; _reset = value;
} }
bool PhysicsConstraint::getReset() const { bool PhysicsConstraint::getReset(){
return _reset; return _reset;
} }
@ -148,7 +150,7 @@ void PhysicsConstraint::setUx(float value) {
_ux = value; _ux = value;
} }
float PhysicsConstraint::getUx() const { float PhysicsConstraint::getUx(){
return _ux; return _ux;
} }
@ -156,7 +158,7 @@ void PhysicsConstraint::setUy(float value) {
_uy = value; _uy = value;
} }
float PhysicsConstraint::getUy() const { float PhysicsConstraint::getUy(){
return _uy; return _uy;
} }
@ -164,7 +166,7 @@ void PhysicsConstraint::setCx(float value) {
_cx = value; _cx = value;
} }
float PhysicsConstraint::getCx() const { float PhysicsConstraint::getCx(){
return _cx; return _cx;
} }
@ -172,7 +174,7 @@ void PhysicsConstraint::setCy(float value) {
_cy = value; _cy = value;
} }
float PhysicsConstraint::getCy() const { float PhysicsConstraint::getCy(){
return _cy; return _cy;
} }
@ -180,7 +182,7 @@ void PhysicsConstraint::setTx(float value) {
_tx = value; _tx = value;
} }
float PhysicsConstraint::getTx() const { float PhysicsConstraint::getTx(){
return _tx; return _tx;
} }
@ -188,7 +190,7 @@ void PhysicsConstraint::setTy(float value) {
_ty = value; _ty = value;
} }
float PhysicsConstraint::getTy() const { float PhysicsConstraint::getTy(){
return _ty; return _ty;
} }
@ -196,7 +198,7 @@ void PhysicsConstraint::setXOffset(float value) {
_xOffset = value; _xOffset = value;
} }
float PhysicsConstraint::getXOffset() const { float PhysicsConstraint::getXOffset(){
return _xOffset; return _xOffset;
} }
@ -204,7 +206,7 @@ void PhysicsConstraint::setXVelocity(float value) {
_xVelocity = value; _xVelocity = value;
} }
float PhysicsConstraint::getXVelocity() const { float PhysicsConstraint::getXVelocity(){
return _xVelocity; return _xVelocity;
} }
@ -212,7 +214,7 @@ void PhysicsConstraint::setYOffset(float value) {
_yOffset = value; _yOffset = value;
} }
float PhysicsConstraint::getYOffset() const { float PhysicsConstraint::getYOffset(){
return _yOffset; return _yOffset;
} }
@ -220,7 +222,7 @@ void PhysicsConstraint::setYVelocity(float value) {
_yVelocity = value; _yVelocity = value;
} }
float PhysicsConstraint::getYVelocity() const { float PhysicsConstraint::getYVelocity(){
return _yVelocity; return _yVelocity;
} }
@ -228,7 +230,7 @@ void PhysicsConstraint::setRotateOffset(float value) {
_rotateOffset = value; _rotateOffset = value;
} }
float PhysicsConstraint::getRotateOffset() const { float PhysicsConstraint::getRotateOffset(){
return _rotateOffset; return _rotateOffset;
} }
@ -236,7 +238,7 @@ void PhysicsConstraint::setRotateVelocity(float value) {
_rotateVelocity = value; _rotateVelocity = value;
} }
float PhysicsConstraint::getRotateVelocity() const { float PhysicsConstraint::getRotateVelocity(){
return _rotateVelocity; return _rotateVelocity;
} }
@ -244,7 +246,7 @@ void PhysicsConstraint::setScaleOffset(float value) {
_scaleOffset = value; _scaleOffset = value;
} }
float PhysicsConstraint::getScaleOffset() const { float PhysicsConstraint::getScaleOffset(){
return _scaleOffset; return _scaleOffset;
} }
@ -252,7 +254,7 @@ void PhysicsConstraint::setScaleVelocity(float value) {
_scaleVelocity = value; _scaleVelocity = value;
} }
float PhysicsConstraint::getScaleVelocity() const { float PhysicsConstraint::getScaleVelocity(){
return _scaleVelocity; return _scaleVelocity;
} }
@ -260,7 +262,7 @@ void PhysicsConstraint::setActive(bool value) {
_active = value; _active = value;
} }
bool PhysicsConstraint::isActive() const { bool PhysicsConstraint::isActive(){
return _active; return _active;
} }
@ -268,7 +270,7 @@ void PhysicsConstraint::setRemaining(float value) {
_remaining = value; _remaining = value;
} }
float PhysicsConstraint::getRemaining() const { float PhysicsConstraint::getRemaining(){
return _remaining; return _remaining;
} }
@ -276,13 +278,13 @@ void PhysicsConstraint::setLastTime(float value) {
_lastTime = value; _lastTime = value;
} }
float PhysicsConstraint::getLastTime() const { float PhysicsConstraint::getLastTime(){
return _lastTime; return _lastTime;
} }
void PhysicsConstraint::reset() { void PhysicsConstraint::reset() {
_remaining = 0; _remaining = 0;
_lastTime = _skeleton.getTime(); // Assuming Skeleton has a method getTime() _lastTime = _skeleton.getTime();
_reset = true; _reset = true;
_xOffset = 0; _xOffset = 0;
_xVelocity = 0; _xVelocity = 0;
@ -313,7 +315,7 @@ void PhysicsConstraint::update(Physics physics) {
bool scaleX = _data._scaleX > 0; bool scaleX = _data._scaleX > 0;
Bone* bone = _bone; Bone* bone = _bone;
float l = bone->_data.getLength(); // Direct access to Bone's length float l = bone->_data.getLength();
switch (physics) { switch (physics) {
case Physics::none: case Physics::none:

View File

@ -33,6 +33,7 @@
#include <spine/Bone.h> #include <spine/Bone.h>
#include <spine/IkConstraint.h> #include <spine/IkConstraint.h>
#include <spine/PathConstraint.h> #include <spine/PathConstraint.h>
#include <spine/PhysicsConstraint.h>
#include <spine/SkeletonData.h> #include <spine/SkeletonData.h>
#include <spine/Skin.h> #include <spine/Skin.h>
#include <spine/Slot.h> #include <spine/Slot.h>
@ -43,6 +44,7 @@
#include <spine/MeshAttachment.h> #include <spine/MeshAttachment.h>
#include <spine/PathAttachment.h> #include <spine/PathAttachment.h>
#include <spine/PathConstraintData.h> #include <spine/PathConstraintData.h>
#include <spine/PhysicsConstraintData.h>
#include <spine/RegionAttachment.h> #include <spine/RegionAttachment.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>
#include <spine/TransformConstraintData.h> #include <spine/TransformConstraintData.h>
@ -116,6 +118,15 @@ Skeleton::Skeleton(SkeletonData *skeletonData) : _data(skeletonData),
_pathConstraints.add(constraint); _pathConstraints.add(constraint);
} }
_physicsConstraints.ensureCapacity(_data->getPhysicsConstraints().size());
for (size_t i = 0; i < _data->getPhysicsConstraints().size(); ++i) {
PhysicsConstraintData *data = _data->getPhysicsConstraints()[i];
PhysicsConstraint *constraint = new (__FILE__, __LINE__) PhysicsConstraint(*data, *this);
_physicsConstraints.add(constraint);
}
updateCache(); updateCache();
} }
@ -151,8 +162,9 @@ void Skeleton::updateCache() {
size_t ikCount = _ikConstraints.size(); size_t ikCount = _ikConstraints.size();
size_t transformCount = _transformConstraints.size(); size_t transformCount = _transformConstraints.size();
size_t pathCount = _pathConstraints.size(); size_t pathCount = _pathConstraints.size();
size_t physicsCount = _physicsConstraints.size();
size_t constraintCount = ikCount + transformCount + pathCount; size_t constraintCount = ikCount + transformCount + pathCount + physicsCount;
size_t i = 0; size_t i = 0;
continue_outer: continue_outer:
@ -183,6 +195,15 @@ continue_outer:
goto continue_outer; goto continue_outer;
} }
} }
for (size_t ii = 0; ii < pathCount; ++ii) {
PhysicsConstraint *constraint = _physicsConstraints[ii];
if (constraint->getData().getOrder() == i) {
sortPhysicsConstraint(constraint);
i++;
goto continue_outer;
}
}
} }
size_t n = _bones.size(); size_t n = _bones.size();
@ -206,7 +227,7 @@ void Skeleton::printUpdateCache() {
} }
} }
void Skeleton::updateWorldTransform() { void Skeleton::updateWorldTransform(Physics physics) {
for (size_t i = 0, n = _bones.size(); i < n; i++) { for (size_t i = 0, n = _bones.size(); i < n; i++) {
Bone *bone = _bones[i]; Bone *bone = _bones[i];
bone->_ax = bone->_x; bone->_ax = bone->_x;
@ -219,32 +240,34 @@ void Skeleton::updateWorldTransform() {
} }
for (size_t i = 0, n = _updateCache.size(); i < n; ++i) { for (size_t i = 0, n = _updateCache.size(); i < n; ++i) {
_updateCache[i]->update(); Updatable *updatable = _updateCache[i];
updatable->update(physics);
} }
} }
void Skeleton::updateWorldTransform(Bone *parent) { void Skeleton::updateWorldTransform(Physics physics, Bone *parent) {
// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection. // Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
Bone &rootBone = *getRootBone(); Bone *rootBone = getRootBone();
float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d; float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d;
rootBone._worldX = pa * _x + pb * _y + parent->_worldX; rootBone->_worldX = pa * _x + pb * _y + parent->_worldX;
rootBone._worldY = pc * _x + pd * _y + parent->_worldY; rootBone->_worldY = pc * _x + pd * _y + parent->_worldY;
float rotationY = rootBone._rotation + 90 + rootBone._shearY; float rx = (rootBone->_rotation + rootBone->_shearX) * MathUtil::Deg_Rad;
float la = MathUtil::cosDeg(rootBone._rotation + rootBone._shearX) * rootBone._scaleX; float ry = (rootBone->_rotation + 90 + rootBone->_shearY) * MathUtil::Deg_Rad;
float lb = MathUtil::cosDeg(rotationY) * rootBone._scaleY; float la = MathUtil::cos(rx) * rootBone->_scaleX;
float lc = MathUtil::sinDeg(rootBone._rotation + rootBone._shearX) * rootBone._scaleX; float lb = MathUtil::cos(ry) * rootBone->_scaleY;
float ld = MathUtil::sinDeg(rotationY) * rootBone._scaleY; float lc = MathUtil::sin(rx) * rootBone->_scaleX;
rootBone._a = (pa * la + pb * lc) * _scaleX; float ld = MathUtil::sin(ry) * rootBone->_scaleY;
rootBone._b = (pa * lb + pb * ld) * _scaleX; rootBone->_a = (pa * la + pb * lc) * _scaleX;
rootBone._c = (pc * la + pd * lc) * _scaleY; rootBone->_b = (pa * lb + pb * ld) * _scaleX;
rootBone._d = (pc * lb + pd * ld) * _scaleY; rootBone->_c = (pc * la + pd * lc) * _scaleY;
rootBone->_d = (pc * lb + pd * ld) * _scaleY;
// Update everything except root bone. // Update everything except root bone.
Bone *rb = getRootBone(); Bone *rb = getRootBone();
for (size_t i = 0, n = _updateCache.size(); i < n; i++) { for (size_t i = 0, n = _updateCache.size(); i < n; i++) {
Updatable *updatable = _updateCache[i]; Updatable *updatable = _updateCache[i];
if (updatable != rb) updatable->update(); if (updatable != rb) updatable->update(physics);
} }
} }
@ -259,40 +282,20 @@ void Skeleton::setBonesToSetupPose() {
} }
for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) { for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) {
IkConstraint *constraintP = _ikConstraints[i]; _ikConstraints[i]->setToSetupPose();
IkConstraint &constraint = *constraintP;
constraint._bendDirection = constraint._data._bendDirection;
constraint._compress = constraint._data._compress;
constraint._stretch = constraint._data._stretch;
constraint._mix = constraint._data._mix;
constraint._softness = constraint._data._softness;
} }
for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) { for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) {
TransformConstraint *constraintP = _transformConstraints[i]; _transformConstraints[i]->setToSetupPose();
TransformConstraint &constraint = *constraintP;
TransformConstraintData &constraintData = constraint._data;
constraint._mixRotate = constraintData._mixRotate;
constraint._mixX = constraintData._mixX;
constraint._mixY = constraintData._mixY;
constraint._mixScaleX = constraintData._mixScaleX;
constraint._mixScaleY = constraintData._mixScaleY;
constraint._mixShearY = constraintData._mixShearY;
} }
for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) { for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) {
PathConstraint *constraintP = _pathConstraints[i]; _pathConstraints[i]->setToSetupPose();
PathConstraint &constraint = *constraintP;
PathConstraintData &constraintData = constraint._data;
constraint._position = constraintData._position;
constraint._spacing = constraintData._spacing;
constraint._mixRotate = constraintData._mixRotate;
constraint._mixX = constraintData._mixX;
constraint._mixY = constraintData._mixY;
} }
for (size_t i = 0, n = _physicsConstraints.size(); i < n; ++i) {
_physicsConstraints[i]->setToSetupPose();
}
} }
void Skeleton::setSlotsToSetupPose() { void Skeleton::setSlotsToSetupPose() {
@ -640,6 +643,18 @@ void Skeleton::sortTransformConstraint(TransformConstraint *constraint) {
constrained[i]->_sorted = true; constrained[i]->_sorted = true;
} }
void Skeleton::sortPhysicsConstraint(PhysicsConstraint *constraint) {
Bone *bone = constraint->getBone();
constraint->_active = bone->_active && (!constraint->_data.isSkinRequired() ||
(_skin && _skin->_constraints.contains(&constraint->_data)));
if (!constraint->_active) return;
sortBone(bone);
_updateCache.add(constraint);
sortReset(bone->getChildren());
bone->_sorted = true;
}
void Skeleton::sortPathConstraintAttachment(Skin *skin, size_t slotIndex, Bone &slotBone) { void Skeleton::sortPathConstraintAttachment(Skin *skin, size_t slotIndex, Bone &slotBone) {
Skin::AttachmentMap::Entries attachments = skin->getAttachments(); Skin::AttachmentMap::Entries attachments = skin->getAttachments();
@ -689,10 +704,11 @@ float Skeleton::getTime() {
return _time; return _time;
} }
float Skeleton::setTime(float time) { void Skeleton::setTime(float time) {
_time = time; _time = time;
} }
void Skeleton::update(float delta) { void Skeleton::update(float delta) {
_time += delta; _time += delta;
} }

View File

@ -34,6 +34,7 @@
#include <spine/EventData.h> #include <spine/EventData.h>
#include <spine/IkConstraintData.h> #include <spine/IkConstraintData.h>
#include <spine/PathConstraintData.h> #include <spine/PathConstraintData.h>
#include <spine/PhysicsConstraintData.h>
#include <spine/Skin.h> #include <spine/Skin.h>
#include <spine/SlotData.h> #include <spine/SlotData.h>
#include <spine/TransformConstraintData.h> #include <spine/TransformConstraintData.h>
@ -66,6 +67,7 @@ SkeletonData::~SkeletonData() {
ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); ContainerUtil::cleanUpVectorOfPointers(_ikConstraints);
ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); ContainerUtil::cleanUpVectorOfPointers(_transformConstraints);
ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); ContainerUtil::cleanUpVectorOfPointers(_pathConstraints);
ContainerUtil::cleanUpVectorOfPointers(_physicsConstraints);
for (size_t i = 0; i < _strings.size(); i++) { for (size_t i = 0; i < _strings.size(); i++) {
SpineExtension::free(_strings[i], __FILE__, __LINE__); SpineExtension::free(_strings[i], __FILE__, __LINE__);
} }
@ -103,6 +105,10 @@ PathConstraintData *SkeletonData::findPathConstraint(const String &constraintNam
return ContainerUtil::findWithName(_pathConstraints, constraintName); return ContainerUtil::findWithName(_pathConstraints, constraintName);
} }
PhysicsConstraintData *SkeletonData::findPhysicsConstraint(const String &constraintName) {
return ContainerUtil::findWithName(_physicsConstraints, constraintName);
}
const String &SkeletonData::getName() { const String &SkeletonData::getName() {
return _name; return _name;
} }
@ -151,6 +157,10 @@ Vector<PathConstraintData *> &SkeletonData::getPathConstraints() {
return _pathConstraints; return _pathConstraints;
} }
Vector<PhysicsConstraintData *> &SkeletonData::getPhysicsConstraints() {
return _physicsConstraints;
}
float SkeletonData::getX() { float SkeletonData::getX() {
return _x; return _x;
} }

View File

@ -61,7 +61,7 @@ TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton
} }
} }
void TransformConstraint::update(Physics physics) { void TransformConstraint::update(Physics) {
if (_mixRotate == 0 && _mixX == 0 && _mixY == 0 && _mixScaleX == 0 && _mixScaleY == 0 && _mixShearY == 0) return; if (_mixRotate == 0 && _mixX == 0 && _mixY == 0 && _mixScaleX == 0 && _mixScaleY == 0 && _mixShearY == 0) return;
if (_data.isLocal()) { if (_data.isLocal()) {
@ -340,7 +340,7 @@ void TransformConstraint::setActive(bool inValue) {
} }
void TransformConstraint::setToSetupPose() { void TransformConstraint::setToSetupPose() {
auto data = this->_data; TransformConstraintData &data = this->_data;
this->_mixRotate = data._mixRotate; this->_mixRotate = data._mixRotate;
this->_mixX = data._mixX; this->_mixX = data._mixX;
this->_mixY = data._mixY; this->_mixY = data._mixY;

View File

@ -39,7 +39,7 @@ using namespace spine;
template<typename T, typename... Args> template<typename T, typename... Args>
unique_ptr<T> make_unique_test(Args &&...args) { unique_ptr<T> make_unique_test(Args &&...args) {
return unique_ptr<T>(new T(forward<Args>(args)...)); return unique_ptr<T>(new T(std::forward<Args>(args)...));
} }
void callback(AnimationState *state, EventType type, TrackEntry *entry, Event *event) { void callback(AnimationState *state, EventType type, TrackEntry *entry, Event *event) {
@ -124,7 +124,7 @@ void spineboy(SkeletonData *skeletonData, Atlas *atlas) {
skeleton->setToSetupPose(); skeleton->setToSetupPose();
skeleton->setPosition(320, 590); skeleton->setPosition(320, 590);
skeleton->updateWorldTransform(); skeleton->updateWorldTransform(Physics::update);
Slot *headSlot = skeleton->findSlot("head"); Slot *headSlot = skeleton->findSlot("head");
@ -227,7 +227,7 @@ void ikDemo(SkeletonData *skeletonData, Atlas *atlas) {
// Calculate final world transform with the // Calculate final world transform with the
// crosshair bone set to the mouse cursor // crosshair bone set to the mouse cursor
// position. // position.
drawable.skeleton->updateWorldTransform(); drawable.skeleton->updateWorldTransform(Physics::update);
window.clear(); window.clear();
window.draw(drawable); window.draw(drawable);
@ -246,7 +246,7 @@ void goblins(SkeletonData *skeletonData, Atlas *atlas) {
skeleton->setSkin("goblingirl"); skeleton->setSkin("goblingirl");
skeleton->setSlotsToSetupPose(); skeleton->setSlotsToSetupPose();
skeleton->setPosition(320, 590); skeleton->setPosition(320, 590);
skeleton->updateWorldTransform(); skeleton->updateWorldTransform(Physics::update);
drawable.state->setAnimation(0, "walk", true); drawable.state->setAnimation(0, "walk", true);
@ -281,7 +281,7 @@ void raptor(SkeletonData *skeletonData, Atlas *atlas) {
Skeleton *skeleton = drawable.skeleton; Skeleton *skeleton = drawable.skeleton;
skeleton->setPosition(320, 590); skeleton->setPosition(320, 590);
skeleton->updateWorldTransform(); skeleton->updateWorldTransform(Physics::update);
drawable.state->setAnimation(0, "walk", true); drawable.state->setAnimation(0, "walk", true);
drawable.state->addAnimation(1, "gun-grab", false, 2); drawable.state->addAnimation(1, "gun-grab", false, 2);
@ -314,7 +314,7 @@ void tank(SkeletonData *skeletonData, Atlas *atlas) {
Skeleton *skeleton = drawable.skeleton; Skeleton *skeleton = drawable.skeleton;
skeleton->setPosition(500, 590); skeleton->setPosition(500, 590);
skeleton->updateWorldTransform(); skeleton->updateWorldTransform(Physics::update);
drawable.state->setAnimation(0, "drive", true); drawable.state->setAnimation(0, "drive", true);
@ -345,7 +345,7 @@ void vine(SkeletonData *skeletonData, Atlas *atlas) {
Skeleton *skeleton = drawable.skeleton; Skeleton *skeleton = drawable.skeleton;
skeleton->setPosition(320, 590); skeleton->setPosition(320, 590);
skeleton->updateWorldTransform(); skeleton->updateWorldTransform(Physics::update);
drawable.state->setAnimation(0, "grow", true); drawable.state->setAnimation(0, "grow", true);
@ -378,7 +378,7 @@ void stretchyman(SkeletonData *skeletonData, Atlas *atlas) {
Skeleton *skeleton = drawable.skeleton; Skeleton *skeleton = drawable.skeleton;
skeleton->setPosition(100, 590); skeleton->setPosition(100, 590);
skeleton->updateWorldTransform(); skeleton->updateWorldTransform(Physics::update);
drawable.state->setAnimation(0, "sneak", true); drawable.state->setAnimation(0, "sneak", true);
@ -411,7 +411,7 @@ void stretchymanStrechyIk(SkeletonData *skeletonData, Atlas *atlas) {
Skeleton *skeleton = drawable->skeleton; Skeleton *skeleton = drawable->skeleton;
skeleton->setPosition(100, 590); skeleton->setPosition(100, 590);
skeleton->updateWorldTransform(); skeleton->updateWorldTransform(Physics::update);
drawable->state->setAnimation(0, "sneak", true); drawable->state->setAnimation(0, "sneak", true);
@ -445,7 +445,7 @@ void coin(SkeletonData *skeletonData, Atlas *atlas) {
Skeleton *skeleton = drawable.skeleton; Skeleton *skeleton = drawable.skeleton;
skeleton->setPosition(320, 320); skeleton->setPosition(320, 320);
skeleton->updateWorldTransform(); skeleton->updateWorldTransform(Physics::update);
drawable.state->setAnimation(0, "animation", true); drawable.state->setAnimation(0, "animation", true);
@ -479,7 +479,7 @@ void dragon(SkeletonData *skeletonData, Atlas *atlas) {
Skeleton *skeleton = drawable.skeleton; Skeleton *skeleton = drawable.skeleton;
skeleton->setPosition(320, 320); skeleton->setPosition(320, 320);
skeleton->updateWorldTransform(); skeleton->updateWorldTransform(Physics::update);
drawable.state->setAnimation(0, "flying", true); drawable.state->setAnimation(0, "flying", true);
@ -513,7 +513,7 @@ void owl(SkeletonData *skeletonData, Atlas *atlas) {
Skeleton *skeleton = drawable.skeleton; Skeleton *skeleton = drawable.skeleton;
skeleton->setPosition(320, 400); skeleton->setPosition(320, 400);
skeleton->updateWorldTransform(); skeleton->updateWorldTransform(Physics::update);
drawable.state->setAnimation(0, "idle", true); drawable.state->setAnimation(0, "idle", true);
drawable.state->setAnimation(1, "blink", true); drawable.state->setAnimation(1, "blink", true);
@ -588,7 +588,7 @@ void mixAndMatch(SkeletonData *skeletonData, Atlas *atlas) {
skeleton->setSlotsToSetupPose(); skeleton->setSlotsToSetupPose();
skeleton->setPosition(320, 590); skeleton->setPosition(320, 590);
skeleton->updateWorldTransform(); skeleton->updateWorldTransform(Physics::update);
drawable.state->setAnimation(0, "dance", true); drawable.state->setAnimation(0, "dance", true);
@ -626,7 +626,7 @@ void test(SkeletonData *skeletonData, Atlas *atlas) {
for (int i = 0; i < 1; i++) { for (int i = 0; i < 1; i++) {
animationState.update(d); animationState.update(d);
animationState.apply(skeleton); animationState.apply(skeleton);
skeleton.updateWorldTransform(); skeleton.updateWorldTransform(Physics::update);
d += 0.1f; d += 0.1f;
} }
} }

View File

@ -35,47 +35,47 @@ using namespace spine;
class NullTextureLoader : public TextureLoader { class NullTextureLoader : public TextureLoader {
public: public:
virtual void load(AtlasPage &page, const String &path) {} virtual void load(AtlasPage &, const String &) {}
virtual void unload(void *texture) {} virtual void unload(void *) {}
}; };
class NullAttachmentLoader : public AttachmentLoader { class NullAttachmentLoader : public AttachmentLoader {
virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) { virtual RegionAttachment *newRegionAttachment(Skin &, const String &name, const String &, Sequence *) {
return new (__FILE__, __LINE__) RegionAttachment(name); return new (__FILE__, __LINE__) RegionAttachment(name);
} }
virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) { virtual MeshAttachment *newMeshAttachment(Skin &, const String &name, const String &, Sequence *) {
return new (__FILE__, __LINE__) MeshAttachment(name); return new (__FILE__, __LINE__) MeshAttachment(name);
} }
virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &skin, const String &name) { virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &, const String &name) {
return new (__FILE__, __LINE__) BoundingBoxAttachment(name); return new (__FILE__, __LINE__) BoundingBoxAttachment(name);
} }
virtual PathAttachment *newPathAttachment(Skin &skin, const String &name) { virtual PathAttachment *newPathAttachment(Skin &, const String &name) {
return new (__FILE__, __LINE__) PathAttachment(name); return new (__FILE__, __LINE__) PathAttachment(name);
} }
virtual PointAttachment *newPointAttachment(Skin &skin, const String &name) { virtual PointAttachment *newPointAttachment(Skin &, const String &name) {
return new (__FILE__, __LINE__) PointAttachment(name); return new (__FILE__, __LINE__) PointAttachment(name);
} }
virtual ClippingAttachment *newClippingAttachment(Skin &skin, const String &name) { virtual ClippingAttachment *newClippingAttachment(Skin &, const String &name) {
return new (__FILE__, __LINE__) ClippingAttachment(name); return new (__FILE__, __LINE__) ClippingAttachment(name);
} }
virtual void configureAttachment(Attachment *attachment) { virtual void configureAttachment(Attachment *) {
} }
}; };
int main(void) { int main(void) {
String atlasFile("/Users/badlogic/Desktop/basemodel-male/basemodel-male.atlas"); String atlasFile("data/sack-pma.atlas");
String skeletonFile("/Users/badlogic/Desktop/basemodel-male/basemodel-male.skel"); String skeletonFile("data/sack-pro.json");
String animation = ""; String animation = "walk";
String skin = "BasicBody"; String skin = "";
float scale = 0.1f; float scale = 0.6f;
SFMLTextureLoader textureLoader; SFMLTextureLoader textureLoader;
NullAttachmentLoader nullLoader; NullAttachmentLoader nullLoader;
Atlas *atlas = atlasFile.length() == 0 ? nullptr : new Atlas(atlasFile, &textureLoader); Atlas *atlas = atlasFile.length() == 0 ? nullptr : new Atlas(atlasFile, &textureLoader);
@ -104,12 +104,13 @@ int main(void) {
AnimationStateData stateData(skeletonData); AnimationStateData stateData(skeletonData);
SkeletonDrawable drawable(skeletonData, &stateData); SkeletonDrawable drawable(skeletonData, &stateData);
drawable.skeleton->updateWorldTransform(); drawable.skeleton->getRootBone()->update(Physics::update);
drawable.skeleton->setPosition(320, 590); drawable.skeleton->updateWorldTransform(Physics::update);
drawable.skeleton->setPosition(320, 960);
if (animation.length() > 0) drawable.state->setAnimation(0, animation, true); if (animation.length() > 0) drawable.state->setAnimation(0, animation, true);
if (skin.length() > 0) drawable.skeleton->setSkin(skin); if (skin.length() > 0) drawable.skeleton->setSkin(skin);
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - testbed"); sf::RenderWindow window(sf::VideoMode(1024, 1024), "Spine SFML - testbed");
window.setFramerateLimit(60); window.setFramerateLimit(60);
sf::Event event; sf::Event event;
sf::Clock deltaClock; sf::Clock deltaClock;

View File

@ -49,7 +49,7 @@ namespace spine {
SkeletonDrawable::SkeletonDrawable(SkeletonData *skeletonData, AnimationStateData *stateData) : timeScale(1), SkeletonDrawable::SkeletonDrawable(SkeletonData *skeletonData, AnimationStateData *stateData) : timeScale(1),
vertexArray(new VertexArray(Triangles, skeletonData->getBones().size() * 4)), vertexArray(new VertexArray(Triangles, skeletonData->getBones().size() * 4)),
worldVertices(), clipper() { worldVertices(), clipper(), usePremultipliedAlpha(false) {
Bone::setYDown(true); Bone::setYDown(true);
worldVertices.ensureCapacity(SPINE_MESH_VERTEX_COUNT_MAX); worldVertices.ensureCapacity(SPINE_MESH_VERTEX_COUNT_MAX);
skeleton = new (__FILE__, __LINE__) Skeleton(skeletonData); skeleton = new (__FILE__, __LINE__) Skeleton(skeletonData);
@ -76,10 +76,10 @@ namespace spine {
delete skeleton; delete skeleton;
} }
void SkeletonDrawable::update(float deltaTime) { void SkeletonDrawable::update(float deltaTime, Physics physics) {
state->update(deltaTime * timeScale); state->update(deltaTime * timeScale);
state->apply(*skeleton); state->apply(*skeleton);
skeleton->updateWorldTransform(); skeleton->updateWorldTransform(physics);
} }
void SkeletonDrawable::draw(RenderTarget &target, RenderStates states) const { void SkeletonDrawable::draw(RenderTarget &target, RenderStates states) const {

View File

@ -52,7 +52,7 @@ namespace spine {
~SkeletonDrawable(); ~SkeletonDrawable();
void update(float deltaTime); void update(float deltaTime, Physics physics = Physics::update);
virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const; virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const;