From 5ffdcdb1e65bed2fafb0a508a8953021901a9d85 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 22 Dec 2023 17:26:49 +0100 Subject: [PATCH] [cpp] Initial pass at physics, incomplete --- .../spine-cpp/include/spine/AnimationState.h | 18 +- spine-cpp/spine-cpp/include/spine/Bone.h | 4 +- spine-cpp/spine-cpp/include/spine/BoneData.h | 10 + .../spine-cpp/include/spine/IkConstraint.h | 4 +- spine-cpp/spine-cpp/include/spine/MathUtil.h | 5 + .../spine-cpp/include/spine/PathConstraint.h | 4 +- spine-cpp/spine-cpp/include/spine/Physics.h | 49 ++ .../include/spine/PhysicsConstraint.h | 170 +++++++ .../include/spine/PhysicsConstraintData.h | 147 ++++++ spine-cpp/spine-cpp/include/spine/Skeleton.h | 11 + spine-cpp/spine-cpp/include/spine/SlotData.h | 5 + .../include/spine/TransformConstraint.h | 4 +- spine-cpp/spine-cpp/include/spine/Updatable.h | 3 +- .../spine-cpp/src/spine/AnimationState.cpp | 58 ++- spine-cpp/spine-cpp/src/spine/Bone.cpp | 206 ++++---- spine-cpp/spine-cpp/src/spine/BoneData.cpp | 21 +- .../spine-cpp/src/spine/IkConstraint.cpp | 27 +- spine-cpp/spine-cpp/src/spine/MathUtil.cpp | 9 + .../spine-cpp/src/spine/PathConstraint.cpp | 23 +- .../spine-cpp/src/spine/PhysicsConstraint.cpp | 464 ++++++++++++++++++ .../src/spine/PhysicsConstraintData.cpp | 216 ++++++++ .../spine-cpp/src/spine/PointAttachment.cpp | 10 +- spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 15 +- spine-cpp/spine-cpp/src/spine/SlotData.cpp | 11 +- .../src/spine/TransformConstraint.cpp | 16 +- 25 files changed, 1345 insertions(+), 165 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/Physics.h create mode 100644 spine-cpp/spine-cpp/include/spine/PhysicsConstraint.h create mode 100644 spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h create mode 100644 spine-cpp/spine-cpp/src/spine/PhysicsConstraint.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h index 52cc69f6e..269868142 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationState.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -209,16 +209,22 @@ namespace spine { /// When the mix percentage (mix time / mix duration) is less than the attachment threshold, attachment timelines for the /// animation being mixed out will be applied. Defaults to 0, so attachment timelines are not applied for an animation being /// mixed out. - float getAttachmentThreshold(); + float getMixAttachmentThreshold(); - void setAttachmentThreshold(float inValue); + void setMixAttachmentThreshold(float inValue); + + /// When getAlpha() is greater than alphaAttachmentThreshold, attachment timelines are applied. + /// Defaults to 0, so attachment timelines are always applied. */ + float getAlphaAttachmentThreshold(); + + void setAlphaAttachmentThreshold(float inValue); /// When the mix percentage (mix time / mix duration) is less than the draw order threshold, draw order timelines for the /// animation being mixed out will be applied. Defaults to 0, so draw order timelines are not applied for an animation being /// mixed out. - float getDrawOrderThreshold(); + float getMixDrawOrderThreshold(); - void setDrawOrderThreshold(float inValue); + void setMixDrawOrderThreshold(float inValue); /// The animation queued to start after this animation, or NULL. TrackEntry *getNext(); @@ -271,6 +277,8 @@ namespace spine { void setListener(AnimationStateListenerObject *listener); + bool wasApplied(); + private: Animation *_animation; TrackEntry *_previous; @@ -280,7 +288,7 @@ namespace spine { int _trackIndex; bool _loop, _holdPrevious, _reverse, _shortestRotation; - float _eventThreshold, _attachmentThreshold, _drawOrderThreshold; + float _eventThreshold, _mixAttachmentThreshold, _alphaAttachmentThreshold, _mixDrawOrderThreshold; float _animationStart, _animationEnd, _animationLast, _nextAnimationLast; float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale; float _alpha, _mixTime, _mixDuration, _interruptAlpha, _totalAlpha; diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index e1384aa94..108bba150 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -57,6 +57,8 @@ namespace spine { friend class PathConstraint; + friend class PhysicsConstraint; + friend class Skeleton; friend class RegionAttachment; @@ -104,7 +106,7 @@ namespace spine { Bone(BoneData &data, Skeleton &skeleton, Bone *parent = NULL); /// Same as updateWorldTransform. This method exists for Bone to implement Spine::Updatable. - virtual void update(); + virtual void update(Physics physics); /// Computes the world transform using the parent bone and this bone's local transform. void updateWorldTransform(); diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index 51c04a6d3..eb608bf7c 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -125,6 +125,14 @@ namespace spine { Color &getColor(); + const String &getIcon(); + + void setIcon(const String &icon); + + bool isVisible(); + + void setVisible(bool inValue); + private: const int _index; const String _name; @@ -134,6 +142,8 @@ namespace spine { TransformMode _transformMode; bool _skinRequired; Color _color; + String _icon; + bool _visible; }; } diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h index 02d7629bf..a43043f24 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -64,7 +64,7 @@ namespace spine { IkConstraint(IkConstraintData &data, Skeleton &skeleton); - virtual void update(); + virtual void update(Physics physics); virtual int getOrder(); @@ -100,6 +100,8 @@ namespace spine { void setActive(bool inValue); + void setToSetupPose(); + private: IkConstraintData &_data; Vector _bones; diff --git a/spine-cpp/spine-cpp/include/spine/MathUtil.h b/spine-cpp/spine-cpp/include/spine/MathUtil.h index 38691e737..6ce5361f9 100644 --- a/spine-cpp/spine-cpp/include/spine/MathUtil.h +++ b/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -46,6 +46,7 @@ namespace spine { public: static const float Pi; static const float Pi_2; + static const float InvPi_2; static const float Deg_Rad; static const float Rad_Deg; @@ -77,6 +78,8 @@ namespace spine { /// degrees), largest error of 0.00488 radians (0.2796 degrees). static float atan2(float y, float x); + static float atan2Deg(float x, float y); + static float acos(float v); static float sqrt(float v); @@ -92,6 +95,8 @@ namespace spine { static float randomTriangular(float min, float max, float mode); static float pow(float a, float b); + + static float ceil(float v); }; struct SP_API Interpolation { diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/spine-cpp/spine-cpp/include/spine/PathConstraint.h index 870c1ef94..769b0216d 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -59,7 +59,7 @@ namespace spine { public: PathConstraint(PathConstraintData &data, Skeleton &skeleton); - virtual void update(); + virtual void update(Physics physics); virtual int getOrder(); @@ -95,6 +95,8 @@ namespace spine { void setActive(bool inValue); + void setToSetupPose(); + private: static const float EPSILON; static const int NONE; diff --git a/spine-cpp/spine-cpp/include/spine/Physics.h b/spine-cpp/spine-cpp/include/spine/Physics.h new file mode 100644 index 000000000..493535535 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Physics.h @@ -0,0 +1,49 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ +#ifndef Spine_Physics_h +#define Spine_Physics_h + +/** Determines how physics and other non-deterministic updates are applied. */ +namespace spine { + enum Physics { + /** Physics are not updated or applied. */ + none, + + /** Physics are reset to the current pose. */ + reset, + + /** Physics are updated and the pose from physics is applied. */ + update, + + /** Physics are not updated but the pose from physics is applied. */ + pose + }; +} + +#endif \ No newline at end of file diff --git a/spine-cpp/spine-cpp/include/spine/PhysicsConstraint.h b/spine-cpp/spine-cpp/include/spine/PhysicsConstraint.h new file mode 100644 index 000000000..66c9e2cc6 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PhysicsConstraint.h @@ -0,0 +1,170 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PhysicsConstraint_h +#define Spine_PhysicsConstraint_h + +#include + +#include + +namespace spine { + class PhysicsConstraintData; + + class Skeleton; + + class Bone; + + class SP_API PhysicsConstraint : public Updatable { + + RTTI_DECL + public: + explicit PhysicsConstraint(PhysicsConstraintData& data, Skeleton& skeleton); + + void setBone(Bone* bone); + Bone* getBone() const; + + void setInertia(float value); + float getInertia() const; + + void setStrength(float value); + float getStrength() const; + + void setDamping(float value); + float getDamping() const; + + void setMassInverse(float value); + float getMassInverse() const; + + void setWind(float value); + float getWind() const; + + void setGravity(float value); + float getGravity() const; + + void setMix(float value); + float getMix() const; + + void setReset(bool value); + bool getReset() const; + + void setUx(float value); + float getUx() const; + + void setUy(float value); + float getUy() const; + + void setCx(float value); + float getCx() const; + + void setCy(float value); + float getCy() const; + + void setTx(float value); + float getTx() const; + + void setTy(float value); + float getTy() const; + + void setXOffset(float value); + float getXOffset() const; + + void setXVelocity(float value); + float getXVelocity() const; + + void setYOffset(float value); + float getYOffset() const; + + void setYVelocity(float value); + float getYVelocity() const; + + void setRotateOffset(float value); + float getRotateOffset() const; + + void setRotateVelocity(float value); + float getRotateVelocity() const; + + void setScaleOffset(float value); + float getScaleOffset() const; + + void setScaleVelocity(float value); + float getScaleVelocity() const; + + void setActive(bool value); + bool isActive() const; + + void setRemaining(float value); + float getRemaining() const; + + void setLastTime(float value); + float getLastTime() const; + + void reset(); + + void setToSetupPose(); + + void update(Physics physics) override; + + private: + const PhysicsConstraintData& _data; + Bone* _bone; + + float _inertia; + float _strength; + float _damping; + float _massInverse; + float _wind; + float _gravity; + float _mix; + + bool _reset; + float _ux; + float _uy; + float _cx; + float _cy; + float _tx; + float _ty; + float _xOffset; + float _xVelocity; + float _yOffset; + float _yVelocity; + float _rotateOffset; + float _rotateVelocity; + float _scaleOffset; + float _scaleVelocity; + + bool _active; + + Skeleton& _skeleton; + float _remaining; + float _lastTime; + }; +} + +#endif /* Spine_PhysicsConstraint_h */ diff --git a/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h b/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h new file mode 100644 index 000000000..81a95f673 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PhysicsConstraintData.h @@ -0,0 +1,147 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PhysicsConstraintData_h +#define Spine_PhysicsConstraintData_h + +#include +#include +#include +#include + +namespace spine { + class BoneData; + + class SP_API PhysicsConstraintData : public ConstraintData { + friend class SkeletonBinary; + + friend class SkeletonJson; + + friend class Skeleton; + + friend class PhysicsConstraint; + + public: + RTTI_DECL + + explicit PhysicsConstraintData(const String &name); + + void setBone(BoneData* bone); + + BoneData* getBone() const; + + void setX(float x); + + float getX() const; + + void setY(float y); + + float getY() const; + + void setRotate(float rotate); + + float getRotate() const; + + void setScaleX(float scaleX); + + float getScaleX() const; + + void setShearX(float shearX); + + float getShearX() const; + + void setStep(float step); + + float getStep() const; + + void setInertia(float inertia); + + float getInertia() const; + + void setStrength(float strength); + + float getStrength() const; + + void setDamping(float damping); + + float getDamping() const; + + void setMassInverse(float massInverse); + + float getMassInverse() const; + + void setWind(float wind); + + float getWind() const; + + void setGravity(float gravity); + + float getGravity() const; + + void setMix(float mix); + + float getMix() const; + + void setInertiaGlobal(bool inertiaGlobal); + + bool isInertiaGlobal() const; + + void setStrengthGlobal(bool strengthGlobal); + + bool isStrengthGlobal() const; + + void setDampingGlobal(bool dampingGlobal); + + bool isDampingGlobal() const; + + void setMassGlobal(bool massGlobal); + + bool isMassGlobal() const; + + void setWindGlobal(bool windGlobal); + + bool isWindGlobal() const; + + void setGravityGlobal(bool gravityGlobal); + + bool isGravityGlobal() const; + + void setMixGlobal(bool mixGlobal); + + bool isMixGlobal() const; + + private: + BoneData *_bone; + float _x, _y, _rotate, _scaleX, _shearX; + float _step, _inertia, _strength, _damping, _massInverse, _wind, _gravity, _mix; + bool _inertiaGlobal, _strengthGlobal, _dampingGlobal, _massGlobal, _windGlobal, _gravityGlobal, _mixGlobal; + }; +} + +#endif /* Spine_PhysicsConstraintData_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index 5dc0c27d9..402b47d55 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -49,6 +49,8 @@ namespace spine { class PathConstraint; + class PhysicsConstraint; + class TransformConstraint; class Skin; @@ -220,6 +222,12 @@ namespace spine { void setScaleY(float inValue); + float getTime(); + + float setTime(float time); + + void update(float delta); + private: SkeletonData *_data; Vector _bones; @@ -233,11 +241,14 @@ namespace spine { Color _color; float _scaleX, _scaleY; float _x, _y; + float _time; void sortIkConstraint(IkConstraint *constraint); void sortPathConstraint(PathConstraint *constraint); + void sortPhysicsConstraint(PhysicsConstraint *constraint); + void sortTransformConstraint(TransformConstraint *constraint); void sortPathConstraintAttachment(Skin *skin, size_t slotIndex, Bone &slotBone); diff --git a/spine-cpp/spine-cpp/include/spine/SlotData.h b/spine-cpp/spine-cpp/include/spine/SlotData.h index 3733aea29..045198b05 100644 --- a/spine-cpp/spine-cpp/include/spine/SlotData.h +++ b/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -105,6 +105,10 @@ namespace spine { void setBlendMode(BlendMode inValue); + bool isVisible(); + + void setVisible(bool inValue); + private: const int _index; String _name; @@ -115,6 +119,7 @@ namespace spine { bool _hasDarkColor; String _attachmentName; BlendMode _blendMode; + bool _visible; }; } diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h index 93dc472e9..a610c4b7a 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -51,7 +51,7 @@ namespace spine { public: TransformConstraint(TransformConstraintData &data, Skeleton &skeleton); - virtual void update(); + virtual void update(Physics physics); virtual int getOrder(); @@ -91,6 +91,8 @@ namespace spine { void setActive(bool inValue); + void setToSetupPose(); + private: TransformConstraintData &_data; Vector _bones; diff --git a/spine-cpp/spine-cpp/include/spine/Updatable.h b/spine-cpp/spine-cpp/include/spine/Updatable.h index 481cac5df..86e8c8577 100644 --- a/spine-cpp/spine-cpp/include/spine/Updatable.h +++ b/spine-cpp/spine-cpp/include/spine/Updatable.h @@ -32,6 +32,7 @@ #include #include +#include namespace spine { class SP_API Updatable : public SpineObject { @@ -42,7 +43,7 @@ namespace spine { virtual ~Updatable(); - virtual void update() = 0; + virtual void update(Physics physics) = 0; virtual bool isActive() = 0; diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index 2cbaa73da..e3791defd 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -56,7 +56,7 @@ void dummyOnAnimationEventFunc(AnimationState *state, spine::EventType type, Tra TrackEntry::TrackEntry() : _animation(NULL), _previous(NULL), _next(NULL), _mixingFrom(NULL), _mixingTo(0), _trackIndex(0), _loop(false), _holdPrevious(false), _reverse(false), _shortestRotation(false), - _eventThreshold(0), _attachmentThreshold(0), _drawOrderThreshold(0), _animationStart(0), + _eventThreshold(0), _mixAttachmentThreshold(0), _alphaAttachmentThreshold(0), _mixDrawOrderThreshold(0), _animationStart(0), _animationEnd(0), _animationLast(0), _nextAnimationLast(0), _delay(0), _trackTime(0), _trackLast(0), _nextTrackLast(0), _trackEnd(0), _timeScale(1.0f), _alpha(0), _mixTime(0), _mixDuration(0), _interruptAlpha(0), _totalAlpha(0), _mixBlend(MixBlend_Replace), @@ -136,13 +136,17 @@ float TrackEntry::getEventThreshold() { return _eventThreshold; } void TrackEntry::setEventThreshold(float inValue) { _eventThreshold = inValue; } -float TrackEntry::getAttachmentThreshold() { return _attachmentThreshold; } +float TrackEntry::getMixAttachmentThreshold() { return _mixAttachmentThreshold; } -void TrackEntry::setAttachmentThreshold(float inValue) { _attachmentThreshold = inValue; } +void TrackEntry::setMixAttachmentThreshold(float inValue) { _mixAttachmentThreshold = inValue; } -float TrackEntry::getDrawOrderThreshold() { return _drawOrderThreshold; } +float TrackEntry::getAlphaAttachmentThreshold() { return _alphaAttachmentThreshold; } -void TrackEntry::setDrawOrderThreshold(float inValue) { _drawOrderThreshold = inValue; } +void TrackEntry::setAlphaAttachmentThreshold(float inValue) { _alphaAttachmentThreshold = inValue; } + +float TrackEntry::getMixDrawOrderThreshold() { return _mixDrawOrderThreshold; } + +void TrackEntry::setMixDrawOrderThreshold(float inValue) { _mixDrawOrderThreshold = inValue; } TrackEntry *TrackEntry::getNext() { return _next; } @@ -206,6 +210,10 @@ float TrackEntry::getTrackComplete() { return _trackTime;// Next update. } +bool TrackEntry::wasApplied() { + return _nextTrackLast != -1; +} + EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry *trackEntry, Event *event) : _type(eventType), _entry(trackEntry), _event(event) { @@ -428,14 +436,16 @@ bool AnimationState::apply(Skeleton &skeleton) { MixBlend blend = i == 0 ? MixBlend_First : current._mixBlend; // apply mixing from entries first. - float mix = current._alpha; + float alpha = current._alpha; if (current._mixingFrom != NULL) { - mix *= applyMixingFrom(currentP, skeleton, blend); + alpha *= applyMixingFrom(currentP, skeleton, blend); } else if (current._trackTime >= current._trackEnd && current._next == NULL) { - mix = 0;// Set to setup pose the last time the entry will be applied. + alpha = 0;// Set to setup pose the last time the entry will be applied. } + bool attachments = alpha >= current._alphaAttachmentThreshold; - // apply current entry. + + // apply current entry. float animationLast = current._animationLast, animationTime = current.getAnimationTime(); float applyTime = animationTime; Vector *applyEvents = &_events; @@ -445,14 +455,15 @@ bool AnimationState::apply(Skeleton &skeleton) { } size_t timelineCount = current._animation->_timelines.size(); Vector &timelines = current._animation->_timelines; - if ((i == 0 && mix == 1) || blend == MixBlend_Add) { - for (size_t ii = 0; ii < timelineCount; ++ii) { + if ((i == 0 && alpha == 1) || blend == MixBlend_Add) { + if (i == 0) attachments = true; + for (size_t ii = 0; ii < timelineCount; ++ii) { Timeline *timeline = timelines[ii]; if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, blend, - true); + attachments); else - timeline->apply(skeleton, animationLast, applyTime, applyEvents, mix, blend, MixDirection_In); + timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, MixDirection_In); } } else { Vector &timelineMode = current._timelineMode; @@ -469,14 +480,14 @@ bool AnimationState::apply(Skeleton &skeleton) { MixBlend timelineBlend = timelineMode[ii] == Subsequent ? blend : MixBlend_Setup; if (!shortestRotation && timeline->getRTTI().isExactly(RotateTimeline::rtti)) - applyRotateTimeline(static_cast(timeline), skeleton, applyTime, mix, - timelineBlend, timelinesRotation, ii << 1, firstFrame); + applyRotateTimeline(static_cast(timeline), skeleton, applyTime, alpha, + timelineBlend, timelinesRotation, ii << 1, firstFrame); else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, timelineBlend, true); else - timeline->apply(skeleton, animationLast, applyTime, applyEvents, mix, timelineBlend, - MixDirection_In); + timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend, + MixDirection_In); } } @@ -733,8 +744,8 @@ void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleto // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. float total, diff = r2 - r1; - diff -= (16384 - (int) (16384.499999999996 - diff / 360)) * 360; - if (diff == 0) { + diff -= MathUtil::ceil(diff / 360 - 0.5) * 360; + if (diff == 0) { total = timelinesRotation[i]; } else { float lastTotal, lastDiff; @@ -812,7 +823,7 @@ float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBle if (blend != MixBlend_First) blend = from->_mixBlend; } - bool attachments = mix < from->_attachmentThreshold, drawOrder = mix < from->_drawOrderThreshold; + bool attachments = mix < from->_mixAttachmentThreshold, drawOrder = mix < from->_mixDrawOrderThreshold; Vector &timelines = from->_animation->_timelines; size_t timelineCount = timelines.size(); float alphaHold = from->_alpha * to->_interruptAlpha, alphaMix = alphaHold * (1 - mix); @@ -874,7 +885,7 @@ float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton, MixBle timelinesRotation, i << 1, firstFrame); } else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) { applyAttachmentTimeline(static_cast(timeline), skeleton, applyTime, timelineBlend, - attachments); + attachments && alpha >= from->_alphaAttachmentThreshold); } else { if (drawOrder && timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) && timelineBlend == MixBlend_Setup) @@ -974,8 +985,9 @@ TrackEntry *AnimationState::newTrackEntry(size_t trackIndex, Animation *animatio entry._shortestRotation = false; entry._eventThreshold = 0; - entry._attachmentThreshold = 0; - entry._drawOrderThreshold = 0; + entry._mixAttachmentThreshold = 0; + entry._alphaAttachmentThreshold = 0; + entry._mixDrawOrderThreshold = 0; entry._animationStart = 0; entry._animationEnd = animation->getDuration(); diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index cfbe466b8..a5f3b9891 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -75,7 +75,7 @@ Bone::Bone(BoneData &data, Skeleton &skeleton, Bone *parent) : Updatable(), setToSetupPose(); } -void Bone::update() { +void Bone::update(Physics physics) { updateWorldTransform(_ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY); } @@ -84,7 +84,6 @@ void Bone::updateWorldTransform() { } void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { - float cosine, sine; float pa, pb, pc, pd; Bone *parent = _parent; @@ -97,13 +96,15 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, _ashearY = shearY; if (!parent) { /* Root bone. */ - float rotationY = rotation + 90 + shearY; - float sx = _skeleton.getScaleX(); - float sy = _skeleton.getScaleY(); - _a = MathUtil::cosDeg(rotation + shearX) * scaleX * sx; - _b = MathUtil::cosDeg(rotationY) * scaleY * sx; - _c = MathUtil::sinDeg(rotation + shearX) * scaleX * sy; - _d = MathUtil::sinDeg(rotationY) * scaleY * sy; + auto skeleton = this->_skeleton; + float sx = skeleton.getScaleX(); + float sy = skeleton.getScaleY(); + float rx = (rotation + shearX) * MathUtil::Deg_Rad; + float ry = (rotation + 90 + shearY) * MathUtil::Deg_Rad; + _a = MathUtil::cos(rx) * scaleX * sx; + _b = MathUtil::cos(ry) * scaleY * sx; + _c = MathUtil::sin(rx) * scaleX * sy; + _d = MathUtil::sin(ry) * scaleY * sy; _worldX = x * sx + _skeleton.getX(); _worldY = y * sy + _skeleton.getY(); return; @@ -119,11 +120,12 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, switch (_data.getTransformMode()) { case TransformMode_Normal: { - float rotationY = rotation + 90 + shearY; - float la = MathUtil::cosDeg(rotation + shearX) * scaleX; - float lb = MathUtil::cosDeg(rotationY) * scaleY; - float lc = MathUtil::sinDeg(rotation + shearX) * scaleX; - float ld = MathUtil::sinDeg(rotationY) * scaleY; + float rx = (rotation + shearX) * MathUtil::Deg_Rad; + float ry = (rotation + 90 + shearY) * MathUtil::Deg_Rad; + float la = MathUtil::cos(rx) * scaleX; + float lb = MathUtil::cos(ry) * scaleY; + float lc = MathUtil::sin(rx) * scaleX; + float ld = MathUtil::sin(ry) * scaleY; _a = pa * la + pb * lc; _b = pa * lb + pb * ld; _c = pc * la + pd * lc; @@ -131,16 +133,17 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, return; } case TransformMode_OnlyTranslation: { - float rotationY = rotation + 90 + shearY; - _a = MathUtil::cosDeg(rotation + shearX) * scaleX; - _b = MathUtil::cosDeg(rotationY) * scaleY; - _c = MathUtil::sinDeg(rotation + shearX) * scaleX; - _d = MathUtil::sinDeg(rotationY) * scaleY; + float rx = (rotation + shearX) * MathUtil::Deg_Rad; + float ry = (rotation + 90 + shearY) * MathUtil::Deg_Rad; + _a = MathUtil::cos(rx) * scaleX; + _b = MathUtil::cos(ry) * scaleY; + _c = MathUtil::sin(rx) * scaleX; + _d = MathUtil::sin(ry) * scaleY; break; } case TransformMode_NoRotationOrReflection: { float s = pa * pa + pc * pc; - float prx, rx, ry, la, lb, lc, ld; + float prx; if (s > 0.0001f) { s = MathUtil::abs(pa * pd - pb * pc) / s; pa /= _skeleton.getScaleX(); @@ -153,12 +156,12 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, pc = 0; prx = 90 - MathUtil::atan2(pd, pb) * MathUtil::Rad_Deg; } - rx = rotation + shearX - prx; - ry = rotation + shearY - prx + 90; - la = MathUtil::cosDeg(rx) * scaleX; - lb = MathUtil::cosDeg(ry) * scaleY; - lc = MathUtil::sinDeg(rx) * scaleX; - ld = MathUtil::sinDeg(ry) * scaleY; + float rx = (rotation + shearX - prx) * MathUtil::Deg_Rad; + float ry = (rotation + shearY - prx + 90) * MathUtil::Deg_Rad; + float la = MathUtil::cos(rx) * scaleX; + float lb = MathUtil::cos(ry) * scaleY; + float lc = MathUtil::sin(rx) * scaleX; + float ld = MathUtil::sin(ry) * scaleY; _a = pa * la - pb * lc; _b = pa * lb - pb * ld; _c = pc * la + pd * lc; @@ -167,13 +170,12 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, } case TransformMode_NoScale: case TransformMode_NoScaleOrReflection: { - float za, zc, s; - float r, zb, zd, la, lb, lc, ld; - cosine = MathUtil::cosDeg(rotation); - sine = MathUtil::sinDeg(rotation); - za = (pa * cosine + pb * sine) / _skeleton.getScaleX(); - zc = (pc * cosine + pd * sine) / _skeleton.getScaleY(); - s = MathUtil::sqrt(za * za + zc * zc); + rotation *= MathUtil::Deg_Rad; + float cosine = MathUtil::cos(rotation); + float sine = MathUtil::sin(rotation); + float za = (pa * cosine + pb * sine) / _skeleton.getScaleX(); + float zc = (pc * cosine + pd * sine) / _skeleton.getScaleY(); + float s = MathUtil::sqrt(za * za + zc * zc); if (s > 0.00001f) s = 1 / s; za *= s; zc *= s; @@ -181,13 +183,15 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, if (_data.getTransformMode() == TransformMode_NoScale && (pa * pd - pb * pc < 0) != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0)) s = -s; - r = MathUtil::Pi / 2 + MathUtil::atan2(zc, za); - zb = MathUtil::cos(r) * s; - zd = MathUtil::sin(r) * s; - la = MathUtil::cosDeg(shearX) * scaleX; - lb = MathUtil::cosDeg(90 + shearY) * scaleY; - lc = MathUtil::sinDeg(shearX) * scaleX; - ld = MathUtil::sinDeg(90 + shearY) * scaleY; + rotation = MathUtil::Pi / 2 + MathUtil::atan2(zc, za); + float zb = MathUtil::cos(rotation) * s; + float zd = MathUtil::sin(rotation) * s; + shearX *= MathUtil::Deg_Rad; + shearY = (90 + shearY) * MathUtil::Deg_Rad; + float la = MathUtil::cos(shearX) * scaleX; + float lb = MathUtil::cos(shearY) * scaleY; + float lc = MathUtil::sin(shearX) * scaleX; + float ld = MathUtil::sin(shearY) * scaleY; _a = za * la + zb * lc; _b = za * lb + zb * ld; _c = zc * la + zd * lc; @@ -247,18 +251,13 @@ float Bone::localToWorldRotation(float localRotation) { } void Bone::rotateWorld(float degrees) { - float a = _a; - float b = _b; - float c = _c; - float d = _d; - - float cos = MathUtil::cosDeg(degrees); - float sin = MathUtil::sinDeg(degrees); - - _a = cos * a - sin * c; - _b = cos * b - sin * d; - _c = sin * a + cos * c; - _d = sin * b + cos * d; + degrees *= MathUtil::Deg_Rad; + float sine = MathUtil::sin(degrees), cosine = MathUtil::cos(degrees); + float ra = _a, rb = _b; + _a = cosine * ra - sine * _c; + _b = cosine * rb - sine * _d; + _c = sine * ra + cosine * _c; + _d = sine * rb + cosine * _d; } float Bone::getWorldToLocalRotationX() { @@ -498,67 +497,64 @@ void Bone::updateAppliedTransform() { } float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d; float pid = 1 / (pa * pd - pb * pc); - float ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid; - float dx = _worldX - parent->_worldX, dy = _worldY - parent->_worldY; + float ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid; + float dx = _worldX - parent->_worldX, dy = _worldY - parent->_worldY; _ax = (dx * ia - dy * ib); _ay = (dy * id - dx * ic); - float ra, rb, rc, rd; - if (_data.getTransformMode() == TransformMode_OnlyTranslation) { - ra = _a; - rb = _b; - rc = _c; - rd = _d; - } else { - switch (_data.getTransformMode()) { - case TransformMode_NoRotationOrReflection: { - float s = MathUtil::abs(pa * pd - pb * pc) / (pa * pa + pc * pc); - float sa = pa / _skeleton.getScaleX(); - float sc = pc / _skeleton.getScaleY(); - pb = -sc * s * _skeleton.getScaleX(); - pd = sa * s * _skeleton.getScaleY(); - pid = 1 / (pa * pd - pb * pc); - ia = pd * pid; - ib = pb * pid; - break; - } - case TransformMode_NoScale: - case TransformMode_NoScaleOrReflection: { - float cos = MathUtil::cosDeg(_rotation), sin = MathUtil::sinDeg(_rotation); - pa = (pa * cos + pb * sin) / _skeleton.getScaleX(); - pc = (pc * cos + pd * sin) / _skeleton.getScaleY(); - float s = MathUtil::sqrt(pa * pa + pc * pc); - if (s > 0.00001f) s = 1 / s; - pa *= s; - pc *= s; - s = MathUtil::sqrt(pa * pa + pc * pc); - if (_data.getTransformMode() == TransformMode_NoScale && pid < 0 != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0)) s = -s; - float r = MathUtil::Pi / 2 + MathUtil::atan2(pc, pa); - pb = MathUtil::cos(r) * s; - pd = MathUtil::sin(r) * s; - pid = 1 / (pa * pd - pb * pc); - ia = pd * pid; - ib = pb * pid; - ic = pc * pid; - id = pa * pid; - break; - } - default: - break; - } - ra = ia * _a - ib * _c; - rb = ia * _b - ib * _d; - rc = id * _c - ic * _a; - rd = id * _d - ic * _b; - } + float ra, rb, rc, rd; + if (_data.getTransformMode() == TransformMode_OnlyTranslation) { + ra = _a; + rb = _b; + rc = _c; + rd = _d; + } else { + switch (_data.getTransformMode()) { + case TransformMode_NoRotationOrReflection: { + float s = MathUtil::abs(pa * pd - pb * pc) / (pa * pa + pc * pc); + float sa = pa / _skeleton.getScaleX(); + float sc = pc / _skeleton.getScaleY(); + pb = -sc * s * _skeleton.getScaleX(); + pd = sa * s * _skeleton.getScaleY(); + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + break; + } + case TransformMode_NoScale: + case TransformMode_NoScaleOrReflection: + float cos = MathUtil::cosDeg(_rotation), sin = MathUtil::sinDeg(_rotation); + pa = (pa * cos + pb * sin) / _skeleton.getScaleX(); + pc = (pc * cos + pd * sin) / _skeleton.getScaleY(); + float s = MathUtil::sqrt(pa * pa + pc * pc); + if (s > 0.00001) s = 1 / s; + pa *= s; + pc *= s; + s = MathUtil::sqrt(pa * pa + pc * pc); + if (_data.getTransformMode() == TransformMode_NoScale && pid < 0 != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0)) s = -s; + float r = MathUtil::Pi / 2 + MathUtil::atan2(pc, pa); + pb = MathUtil::cos(r) * s; + pd = MathUtil::sin(r) * s; + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + ic = pc * pid; + id = pa * pid; + break; + } + ra = ia * _a - ib * _c; + rb = ia * _b - ib * _d; + rc = id * _c - ic * _a; + rd = id * _d - ic * _b; + } - _ashearX = 0; + _ashearX = 0; _ascaleX = MathUtil::sqrt(ra * ra + rc * rc); if (_ascaleX > 0.0001f) { float det = ra * rd - rb * rc; _ascaleY = det / _ascaleX; - _ashearY = -MathUtil::atan2(ra * rb + rc * rd, det) * MathUtil::Rad_Deg; - _arotation = MathUtil::atan2(rc, ra) * MathUtil::Rad_Deg; + _ashearY = -MathUtil::atan2(ra * rb + rc * rd, det) * MathUtil::Rad_Deg; + _arotation = MathUtil::atan2(rc, ra) * MathUtil::Rad_Deg; } else { _ascaleX = 0; _ascaleY = MathUtil::sqrt(rb * rb + rd * rd); diff --git a/spine-cpp/spine-cpp/src/spine/BoneData.cpp b/spine-cpp/spine-cpp/src/spine/BoneData.cpp index 87aca70cc..28f634e7e 100644 --- a/spine-cpp/spine-cpp/src/spine/BoneData.cpp +++ b/spine-cpp/spine-cpp/src/spine/BoneData.cpp @@ -46,7 +46,9 @@ BoneData::BoneData(int index, const String &name, BoneData *parent) : _index(ind _shearY(0), _transformMode(TransformMode_Normal), _skinRequired(false), - _color() { + _color(), + _icon(), + _visible(true){ assert(index >= 0); assert(_name.length() > 0); } @@ -146,3 +148,20 @@ void BoneData::setSkinRequired(bool inValue) { Color &BoneData::getColor() { return _color; } + +const String &BoneData::getIcon() { + return _icon; +} + +void BoneData::setIcon(const String &icon) { + this->_icon = icon; +} + +bool BoneData::isVisible() { + return _visible; +} + +void BoneData::setVisible(bool inValue) { + this->_visible = inValue; +} + diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index bf667d6b7..1921388f6 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -84,12 +84,16 @@ void IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress ty = targetY - bone._worldY; default:; } - float b = bone._data.getLength() * sx, dd = MathUtil::sqrt(tx * tx + ty * ty); - if (((compress && dd < b) || (stretch && dd > b)) && (b > 0.0001f)) { - float s = (dd / b - 1) * alpha + 1; - sx *= s; - if (uniform) sy *= s; - } + + float b = bone._data.getLength() * sx; + if (b > 0.0001) { + float dd = tx * tx + ty * ty; + if ((compress && dd < b * b) || (stretch && dd > b * b)) { + float s = (MathUtil::sqrt(dd) / b - 1) * alpha + 1; + sx *= s; + if (uniform) sy *= s; + } + } } bone.updateWorldTransform(bone._ax, bone._ay, bone._arotation + rotationIK * alpha, sx, sy, bone._ashearX, bone._ashearY); @@ -279,7 +283,7 @@ IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Updatab } } -void IkConstraint::update() { +void IkConstraint::update(Physics physics) { if (_mix == 0) return; switch (_bones.size()) { case 1: { @@ -363,3 +367,12 @@ float IkConstraint::getSoftness() { void IkConstraint::setSoftness(float inValue) { _softness = inValue; } + +void IkConstraint::setToSetupPose() { + auto data = this->_data; + this->_mix = data._mix; + this->_softness = data._softness; + this->_bendDirection = data._bendDirection; + this->_compress = data._compress; + this->_stretch = data._stretch; +} diff --git a/spine-cpp/spine-cpp/src/spine/MathUtil.cpp b/spine-cpp/spine-cpp/src/spine/MathUtil.cpp index d3df88a14..e9fdb4ce0 100644 --- a/spine-cpp/spine-cpp/src/spine/MathUtil.cpp +++ b/spine-cpp/spine-cpp/src/spine/MathUtil.cpp @@ -40,6 +40,7 @@ using namespace spine; const float MathUtil::Pi = 3.1415926535897932385f; const float MathUtil::Pi_2 = 3.1415926535897932385f * 2; +const float MathUtil::InvPi_2 = 1 / MathUtil::Pi_2; const float MathUtil::Deg_Rad = (3.1415926535897932385f / 180.0f); const float MathUtil::Rad_Deg = (180.0f / 3.1415926535897932385f); @@ -66,6 +67,10 @@ float MathUtil::atan2(float y, float x) { return (float) ::atan2(y, x); } +float MathUtil::atan2Deg(float x, float y) { + return MathUtil::atan2(x, y) * MathUtil::Deg_Rad; +} + /// Returns the cosine in radians from a lookup table. float MathUtil::cos(float radians) { return (float) ::cos(radians); @@ -122,3 +127,7 @@ float MathUtil::randomTriangular(float min, float max, float mode) { float MathUtil::pow(float a, float b) { return (float) ::pow(a, b); } + +float MathUtil::ceil(float v) { + return ::ceil(v); +} diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp index df399fd05..b06e80423 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -66,7 +66,7 @@ PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : U _segments.setSize(10, 0); } -void PathConstraint::update() { +void PathConstraint::update(Physics physics) { Attachment *baseAttachment = _target->getAttachment(); if (baseAttachment == NULL || !baseAttachment->getRTTI().instanceOf(PathAttachment::rtti)) { return; @@ -91,13 +91,11 @@ void PathConstraint::update() { Bone *boneP = _bones[i]; Bone &bone = *boneP; float setupLength = bone._data.getLength(); - if (setupLength < PathConstraint::EPSILON) { - _lengths[i] = 0; - } else { - float x = setupLength * bone._a, y = setupLength * bone._c; - _lengths[i] = MathUtil::sqrt(x * x + y * y); - } - } + float x = setupLength * bone._a; + float y = setupLength * bone._c; + _lengths[i] = MathUtil::sqrt(x * x + y * y); + + } } for (size_t i = 1; i < spacesCount; ++i) { _spaces[i] = spacing; @@ -580,3 +578,12 @@ bool PathConstraint::isActive() { void PathConstraint::setActive(bool inValue) { _active = inValue; } + +void PathConstraint::setToSetupPose() { + auto data = this->_data; + this->_position = data._position; + this->_spacing = data._spacing; + this->_mixRotate = data._mixRotate; + this->_mixX = data._mixX; + this->_mixY = data._mixY; +} diff --git a/spine-cpp/spine-cpp/src/spine/PhysicsConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PhysicsConstraint.cpp new file mode 100644 index 000000000..c664e8b7d --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/PhysicsConstraint.cpp @@ -0,0 +1,464 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +#include +#include +#include + +using namespace spine; + +RTTI_IMPL(PhysicsConstraint, Updatable) + +PhysicsConstraint::PhysicsConstraint(PhysicsConstraintData& data, Skeleton& skeleton) + : _data(data), _skeleton(skeleton) { + // Assuming 'bones' is a vector or similar container in 'Skeleton' + // 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(); + _strength = data.getStrength(); + _damping = data.getDamping(); + _massInverse = data.getMassInverse(); + _wind = data.getWind(); + _gravity = data.getGravity(); + _mix = data.getMix(); + + _reset = true; + _ux = 0; + _uy = 0; + _cx = 0; + _cy = 0; + _tx = 0; + _ty = 0; + _xOffset = 0; + _xVelocity = 0; + _yOffset = 0; + _yVelocity = 0; + _rotateOffset = 0; + _rotateVelocity = 0; + _scaleOffset = 0; + _scaleVelocity = 0; + _active = false; + _remaining = 0; + _lastTime = 0; +} + +void PhysicsConstraint::setBone(Bone* bone) { + _bone = bone; +} + +Bone* PhysicsConstraint::getBone() const { + return _bone; +} + +void PhysicsConstraint::setInertia(float value) { + _inertia = value; +} + +float PhysicsConstraint::getInertia() const { + return _inertia; +} + +void PhysicsConstraint::setStrength(float value) { + _strength = value; +} + +float PhysicsConstraint::getStrength() const { + return _strength; +} + +void PhysicsConstraint::setDamping(float value) { + _damping = value; +} + +float PhysicsConstraint::getDamping() const { + return _damping; +} + +void PhysicsConstraint::setMassInverse(float value) { + _massInverse = value; +} + +float PhysicsConstraint::getMassInverse() const { + return _massInverse; +} + +void PhysicsConstraint::setWind(float value) { + _wind = value; +} + +float PhysicsConstraint::getWind() const { + return _wind; +} + +void PhysicsConstraint::setGravity(float value) { + _gravity = value; +} + +float PhysicsConstraint::getGravity() const { + return _gravity; +} + +void PhysicsConstraint::setMix(float value) { + _mix = value; +} + +float PhysicsConstraint::getMix() const { + return _mix; +} + +void PhysicsConstraint::setReset(bool value) { + _reset = value; +} + +bool PhysicsConstraint::getReset() const { + return _reset; +} + +void PhysicsConstraint::setUx(float value) { + _ux = value; +} + +float PhysicsConstraint::getUx() const { + return _ux; +} + +void PhysicsConstraint::setUy(float value) { + _uy = value; +} + +float PhysicsConstraint::getUy() const { + return _uy; +} + +void PhysicsConstraint::setCx(float value) { + _cx = value; +} + +float PhysicsConstraint::getCx() const { + return _cx; +} + +void PhysicsConstraint::setCy(float value) { + _cy = value; +} + +float PhysicsConstraint::getCy() const { + return _cy; +} + +void PhysicsConstraint::setTx(float value) { + _tx = value; +} + +float PhysicsConstraint::getTx() const { + return _tx; +} + +void PhysicsConstraint::setTy(float value) { + _ty = value; +} + +float PhysicsConstraint::getTy() const { + return _ty; +} + +void PhysicsConstraint::setXOffset(float value) { + _xOffset = value; +} + +float PhysicsConstraint::getXOffset() const { + return _xOffset; +} + +void PhysicsConstraint::setXVelocity(float value) { + _xVelocity = value; +} + +float PhysicsConstraint::getXVelocity() const { + return _xVelocity; +} + +void PhysicsConstraint::setYOffset(float value) { + _yOffset = value; +} + +float PhysicsConstraint::getYOffset() const { + return _yOffset; +} + +void PhysicsConstraint::setYVelocity(float value) { + _yVelocity = value; +} + +float PhysicsConstraint::getYVelocity() const { + return _yVelocity; +} + +void PhysicsConstraint::setRotateOffset(float value) { + _rotateOffset = value; +} + +float PhysicsConstraint::getRotateOffset() const { + return _rotateOffset; +} + +void PhysicsConstraint::setRotateVelocity(float value) { + _rotateVelocity = value; +} + +float PhysicsConstraint::getRotateVelocity() const { + return _rotateVelocity; +} + +void PhysicsConstraint::setScaleOffset(float value) { + _scaleOffset = value; +} + +float PhysicsConstraint::getScaleOffset() const { + return _scaleOffset; +} + +void PhysicsConstraint::setScaleVelocity(float value) { + _scaleVelocity = value; +} + +float PhysicsConstraint::getScaleVelocity() const { + return _scaleVelocity; +} + +void PhysicsConstraint::setActive(bool value) { + _active = value; +} + +bool PhysicsConstraint::isActive() const { + return _active; +} + +void PhysicsConstraint::setRemaining(float value) { + _remaining = value; +} + +float PhysicsConstraint::getRemaining() const { + return _remaining; +} + +void PhysicsConstraint::setLastTime(float value) { + _lastTime = value; +} + +float PhysicsConstraint::getLastTime() const { + return _lastTime; +} + +void PhysicsConstraint::reset() { + _remaining = 0; + _lastTime = _skeleton.getTime(); // Assuming Skeleton has a method getTime() + _reset = true; + _xOffset = 0; + _xVelocity = 0; + _yOffset = 0; + _yVelocity = 0; + _rotateOffset = 0; + _rotateVelocity = 0; + _scaleOffset = 0; + _scaleVelocity = 0; +} + +void PhysicsConstraint::setToSetupPose() { + _inertia = _data.getInertia(); + _strength = _data.getStrength(); + _damping = _data.getDamping(); + _massInverse = _data.getMassInverse(); + _wind = _data.getWind(); + _gravity = _data.getGravity(); + _mix = _data.getMix(); +} +void PhysicsConstraint::update(Physics physics) { + float mix = _mix; + if (mix == 0) return; + + bool x = _data._x > 0; + bool y = _data._y > 0; + bool rotateOrShearX = _data._rotate > 0 || _data._shearX > 0; + bool scaleX = _data._scaleX > 0; + + Bone* bone = _bone; + float l = bone->_data.getLength(); // Direct access to Bone's length + + switch (physics) { + case Physics::none: + return; + case Physics::reset: + reset(); + // Fall through. + case Physics::update: { + _remaining += MathUtil::max(_skeleton.getTime() - _lastTime, 0.0f); + _lastTime = _skeleton.getTime(); + + float bx = bone->_worldX, by = bone->_worldY; + if (_reset) { + _reset = false; + _ux = bx; + _uy = by; + } else { + float remaining = _remaining, i = _inertia, step = _data._step; + if (x || y) { + if (x) { + _xOffset += (_ux - bx) * i; + _ux = bx; + } + if (y) { + _yOffset += (_uy - by) * i; + _uy = by; + } + if (remaining >= step) { + float m = _massInverse * step, e = _strength, w = _wind * 100, g = _gravity * -100; + float d = MathUtil::pow(_damping, 60 * step); + do { + if (x) { + _xVelocity += (w - _xOffset * e) * m; + _xOffset += _xVelocity * step; + _xVelocity *= d; + } + if (y) { + _yVelocity += (g - _yOffset * e) * m; + _yOffset += _yVelocity * step; + _yVelocity *= d; + } + remaining -= step; + } while (remaining >= step); + } + if (x) bone->_worldX += _xOffset * mix * _data._x; + if (y) bone->_worldY += _yOffset * mix * _data._y; + } + + if (rotateOrShearX || scaleX) { + float ca = MathUtil::atan2(bone->_c, bone->_a), c = 0, s = 0, mr = 0; + if (rotateOrShearX) { + mr = (_data._rotate + _data._shearX) * mix; + float dx = _cx - bone->_worldX, dy = _cy - bone->_worldY; + float r = MathUtil::atan2(dy + _ty, dx + _tx) - ca - _rotateOffset * mr; + _rotateOffset += (r - MathUtil::ceil(r * MathUtil::InvPi_2 - 0.5) * MathUtil::Pi_2) * i; + r = _rotateOffset * mr + ca; + c = MathUtil::cos(r); + s = MathUtil::sin(r); + if (scaleX) { + r = l * bone->getWorldScaleX(); + if (r > 0) _scaleOffset += (dx * c + dy * s) * i / r; + } + } else { + c = MathUtil::cos(ca); + s = MathUtil::sin(ca); + float r = l * bone->getWorldScaleX(); + if (r > 0) _scaleOffset += ((this->_cx - bone->_worldX) * c + (this->_cy - bone->_worldY) * s) * i / r; + } + + remaining = _remaining; + if (remaining >= step) { + float m = _massInverse * step, e = _strength; + float d = MathUtil::pow(_damping, 60 * step); + while(true) { + remaining -= step; + if (scaleX) { + _scaleVelocity += (_wind * c - _gravity * s - _scaleOffset * e) * m; + _scaleOffset += _scaleVelocity * step; + _scaleVelocity *= d; + } + if (rotateOrShearX) { + _rotateVelocity += (-0.01f * l * (_wind * s + _gravity * c) - _rotateOffset * e) * m; + _rotateOffset += _rotateVelocity * step; + _rotateVelocity *= d; + if (remaining < step) break; + float r = _rotateOffset * mr + ca; + c = MathUtil::cos(r); + s = MathUtil::sin(r); + } else if (remaining < step) // + break; + } + } + } + _remaining = remaining; + } + + _cx = bone->_worldX; + _cy = bone->_worldY; + break; + } + case Physics::pose: { + if (x) bone->_worldX += _xOffset * mix * _data._x; + if (y) bone->_worldY += _yOffset * mix * _data._y; + break; + } + } + + if (rotateOrShearX) { + float o = _rotateOffset * mix, s = 0, c = 0, a = 0; + if (_data._shearX > 0) { + float r = 0; + if (_data._rotate > 0) { + r = o * _data._rotate; + s = MathUtil::sin(r); + c = MathUtil::cos(r); + a = bone->_b; + bone->_b = c * a - s * bone->_d; + bone->_d = s * a + c * bone->_d; + } + r += o * _data._shearX; + s = MathUtil::sin(r); + c = MathUtil::cos(r); + a = bone->_a; + bone->_a = c * a - s * bone->_c; + bone->_c = s * a + c * bone->_c; + } else { + o *= _data._rotate; + s = MathUtil::sin(o); + c = MathUtil::cos(o); + a = bone->_a; + bone->_a = c * a - s * bone->_c; + bone->_c = s * a + c * bone->_c; + a = bone->_b; + bone->_b = c * a - s * bone->_d; + bone->_d = s * a + c * bone->_d; + } + } + if (scaleX) { + float s = 1 + _scaleOffset * mix * _data._scaleX; + bone->_a *= s; + bone->_c *= s; + } + if (physics != Physics::pose) { + _tx = l * bone->_a; + _ty = l * bone->_c; + } + bone->updateAppliedTransform(); +} \ No newline at end of file diff --git a/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp new file mode 100644 index 000000000..b52e172c9 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/PhysicsConstraintData.cpp @@ -0,0 +1,216 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +#include + +#include + +using namespace spine; + +RTTI_IMPL(PhysicsConstraintData, ConstraintData) + +PhysicsConstraintData::PhysicsConstraintData(const String &name) : ConstraintData(name), + _bone(nullptr), + _x(0), _y(0), _rotate(0), _scaleX(0), _shearX(0), + _step(0), _inertia(0), _strength(0), _damping(0), _massInverse(0), _wind(0), _gravity(0), _mix(0), + _inertiaGlobal(false), _strengthGlobal(false), _dampingGlobal(false), _massGlobal(false), + _windGlobal(false), _gravityGlobal(false), _mixGlobal(false) +{ +} + + +void PhysicsConstraintData::setBone(BoneData* bone) { + _bone = bone; +} + +BoneData* PhysicsConstraintData::getBone() const { + return _bone; +} + +void PhysicsConstraintData::setX(float x) { + _x = x; +} + +float PhysicsConstraintData::getX() const { + return _x; +} + +void PhysicsConstraintData::setY(float y) { + _y = y; +} + +float PhysicsConstraintData::getY() const { + return _y; +} + +void PhysicsConstraintData::setRotate(float rotate) { + _rotate = rotate; +} + +float PhysicsConstraintData::getRotate() const { + return _rotate; +} + +void PhysicsConstraintData::setScaleX(float scaleX) { + _scaleX = scaleX; +} + +float PhysicsConstraintData::getScaleX() const { + return _scaleX; +} + +void PhysicsConstraintData::setShearX(float shearX) { + _shearX = shearX; +} + +float PhysicsConstraintData::getShearX() const { + return _shearX; +} + +void PhysicsConstraintData::setStep(float step) { + _step = step; +} + +float PhysicsConstraintData::getStep() const { + return _step; +} + +void PhysicsConstraintData::setInertia(float inertia) { + _inertia = inertia; +} + +float PhysicsConstraintData::getInertia() const { + return _inertia; +} + +void PhysicsConstraintData::setStrength(float strength) { + _strength = strength; +} + +float PhysicsConstraintData::getStrength() const { + return _strength; +} + +void PhysicsConstraintData::setDamping(float damping) { + _damping = damping; +} + +float PhysicsConstraintData::getDamping() const { + return _damping; +} + +void PhysicsConstraintData::setMassInverse(float massInverse) { + _massInverse = massInverse; +} + +float PhysicsConstraintData::getMassInverse() const { + return _massInverse; +} + +void PhysicsConstraintData::setWind(float wind) { + _wind = wind; +} + +float PhysicsConstraintData::getWind() const { + return _wind; +} + +void PhysicsConstraintData::setGravity(float gravity) { + _gravity = gravity; +} + +float PhysicsConstraintData::getGravity() const { + return _gravity; +} + +void PhysicsConstraintData::setMix(float mix) { + _mix = mix; +} + +float PhysicsConstraintData::getMix() const { + return _mix; +} + +void PhysicsConstraintData::setInertiaGlobal(bool inertiaGlobal) { + _inertiaGlobal = inertiaGlobal; +} + +bool PhysicsConstraintData::isInertiaGlobal() const { + return _inertiaGlobal; +} + +void PhysicsConstraintData::setStrengthGlobal(bool strengthGlobal) { + _strengthGlobal = strengthGlobal; +} + +bool PhysicsConstraintData::isStrengthGlobal() const { + return _strengthGlobal; +} + +void PhysicsConstraintData::setDampingGlobal(bool dampingGlobal) { + _dampingGlobal = dampingGlobal; +} + +bool PhysicsConstraintData::isDampingGlobal() const { + return _dampingGlobal; +} + +void PhysicsConstraintData::setMassGlobal(bool massGlobal) { + _massGlobal = massGlobal; +} + +bool PhysicsConstraintData::isMassGlobal() const { + return _massGlobal; +} + +void PhysicsConstraintData::setWindGlobal(bool windGlobal) { + _windGlobal = windGlobal; +} + +bool PhysicsConstraintData::isWindGlobal() const { + return _windGlobal; +} + +void PhysicsConstraintData::setGravityGlobal(bool gravityGlobal) { + _gravityGlobal = gravityGlobal; +} + +bool PhysicsConstraintData::isGravityGlobal() const { + return _gravityGlobal; +} + +void PhysicsConstraintData::setMixGlobal(bool mixGlobal) { + _mixGlobal = mixGlobal; +} + +bool PhysicsConstraintData::isMixGlobal() const { + return _mixGlobal; +} diff --git a/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp index 64ea89b3a..097d71d58 100644 --- a/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp @@ -45,12 +45,10 @@ void PointAttachment::computeWorldPosition(Bone &bone, float &ox, float &oy) { } float PointAttachment::computeWorldRotation(Bone &bone) { - float cos = MathUtil::cosDeg(_rotation); - float sin = MathUtil::sinDeg(_rotation); - float ix = cos * bone._a + sin * bone._b; - float iy = cos * bone._c + sin * bone._d; - - return MathUtil::atan2(iy, ix) * MathUtil::Rad_Deg; + float r = _rotation * MathUtil::Deg_Rad, cosine = MathUtil::cos(r), sine = MathUtil::sin(r); + float x = cosine * bone._a + sine * bone._b; + float y = cosine * bone._c + sine * bone._d; + return MathUtil::atan2Deg(y, x); } float PointAttachment::getX() { diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index 6b05f9efb..f6aa51169 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -59,7 +59,8 @@ Skeleton::Skeleton(SkeletonData *skeletonData) : _data(skeletonData), _scaleX(1), _scaleY(1), _x(0), - _y(0) { + _y(0), + _time(0){ _bones.ensureCapacity(_data->getBones().size()); for (size_t i = 0; i < _data->getBones().size(); ++i) { BoneData *data = _data->getBones()[i]; @@ -683,3 +684,15 @@ void Skeleton::sortReset(Vector &bones) { bone->_sorted = false; } } + +float Skeleton::getTime() { + return _time; +} + +float Skeleton::setTime(float time) { + _time = time; +} + +void Skeleton::update(float delta) { + _time += delta; +} \ No newline at end of file diff --git a/spine-cpp/spine-cpp/src/spine/SlotData.cpp b/spine-cpp/spine-cpp/src/spine/SlotData.cpp index 5def32512..76cf97897 100644 --- a/spine-cpp/spine-cpp/src/spine/SlotData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SlotData.cpp @@ -40,7 +40,8 @@ SlotData::SlotData(int index, const String &name, BoneData &boneData) : _index(i _darkColor(0, 0, 0, 0), _hasDarkColor(false), _attachmentName(), - _blendMode(BlendMode_Normal) { + _blendMode(BlendMode_Normal), + _visible(true) { assert(_index >= 0); assert(_name.length() > 0); } @@ -88,3 +89,11 @@ BlendMode SlotData::getBlendMode() { void SlotData::setBlendMode(BlendMode inValue) { _blendMode = inValue; } + +bool SlotData::isVisible() { + return _visible; +} + +void SlotData::setVisible(bool inValue) { + this->_visible = inValue; +} diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp index 3d3ffc304..fd3ca9cd2 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -61,7 +61,7 @@ TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton } } -void TransformConstraint::update() { +void TransformConstraint::update(Physics physics) { if (_mixRotate == 0 && _mixX == 0 && _mixY == 0 && _mixScaleX == 0 && _mixScaleY == 0 && _mixShearY == 0) return; if (_data.isLocal()) { @@ -287,7 +287,7 @@ void TransformConstraint::applyAbsoluteLocal() { float rotation = bone._arotation; if (mixRotate != 0) { float r = target._arotation - rotation + _data._offsetRotation; - r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360; + r -= MathUtil::ceil(r / 360 - 0.5) * 360; rotation += r * mixRotate; } @@ -304,7 +304,7 @@ void TransformConstraint::applyAbsoluteLocal() { float shearY = bone._ashearY; if (mixShearY != 0) { float r = target._ashearY - shearY + _data._offsetShearY; - r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360; + r -= MathUtil::ceil(r / 360 - 0.5) * 360; bone._shearY += r * mixShearY; } @@ -338,3 +338,13 @@ bool TransformConstraint::isActive() { void TransformConstraint::setActive(bool inValue) { _active = inValue; } + +void TransformConstraint::setToSetupPose() { + auto data = this->_data; + this->_mixRotate = data._mixRotate; + this->_mixX = data._mixX; + this->_mixY = data._mixY; + this->_mixScaleX = data._mixScaleX; + this->_mixScaleY = data._mixScaleY; + this->_mixShearY = data._mixShearY; +}