diff --git a/cocos/3d/CCAnimate3D.cpp b/cocos/3d/CCAnimate3D.cpp index 11f71d6a09..7327822d20 100644 --- a/cocos/3d/CCAnimate3D.cpp +++ b/cocos/3d/CCAnimate3D.cpp @@ -25,11 +25,15 @@ #include "3d/CCAnimate3D.h" #include "3d/CCSprite3D.h" #include "3d/CCSkeleton3D.h" -#include "3d/CCMeshSkin.h" #include "platform/CCFileUtils.h" NS_CC_BEGIN +std::unordered_map Animate3D::s_fadeInAnimates; +std::unordered_map Animate3D::s_fadeOutAnimates; +std::unordered_map Animate3D::s_runningAnimates; +float Animate3D::_transTime = 0.1f; + //create Animate3D using Animation. Animate3D* Animate3D::create(Animation3D* animation) { @@ -107,6 +111,40 @@ void Animate3D::startWithTarget(Node *target) { CCLOG("warning: no animation finde for the skeleton"); } + + auto runningAction = s_runningAnimates.find(sprite); + if (runningAction != s_runningAnimates.end()) + { + //make the running action fade out + auto action = (*runningAction).second; + if (action != this) + { + s_fadeOutAnimates[sprite] = action; + action->_state = Animate3D::Animate3DState::FadeOut; + action->_accTransTime = 0.0f; + action->_weight = 1.0f; + action->_lastTime = 0.f; + + s_fadeInAnimates[sprite] = this; + _accTransTime = 0.0f; + _state = Animate3D::Animate3DState::FadeIn; + _weight = 0.f; + _lastTime = 0.f; + } + } + else + { + s_runningAnimates[sprite] = this; + _state = Animate3D::Animate3DState::Running; + _weight = 1.0f; + } +} + +void Animate3D::stop() +{ + removeFromMap(); + + ActionInterval::stop(); } //! called every frame with it's delta time. DON'T override unless you know what you are doing. @@ -117,36 +155,69 @@ void Animate3D::step(float dt) void Animate3D::update(float t) { - if (_target && _weight > 0.f) + if (_target) { - float transDst[3], rotDst[4], scaleDst[3]; - float* trans = nullptr, *rot = nullptr, *scale = nullptr; - if (_playReverse) - t = 1 - t; + if (_state == Animate3D::Animate3DState::FadeIn && _lastTime > 0.f) + { + _accTransTime += (t - _lastTime) * getDuration(); + + _weight = _accTransTime / _transTime; + if (_weight >= 1.0f) + { + _accTransTime = _transTime; + _weight = 1.0f; + _state = Animate3D::Animate3DState::Running; + Sprite3D* sprite = static_cast(_target); + s_fadeInAnimates.erase(sprite); + s_runningAnimates[sprite] = this; + } + } + else if (_state == Animate3D::Animate3DState::FadeOut && _lastTime > 0.f) + { + _accTransTime += (t - _lastTime) * getDuration(); + + _weight = 1 - _accTransTime / _transTime; + if (_weight <= 0.0f) + { + _accTransTime = _transTime; + _weight = 0.0f; + + Sprite3D* sprite = static_cast(_target); + s_fadeOutAnimates.erase(sprite); + } + } + _lastTime = t; - t = _start + t * _last; - for (const auto& it : _boneCurves) { - auto bone = it.first; - auto curve = it.second; - if (curve->translateCurve) - { - curve->translateCurve->evaluate(t, transDst, EvaluateType::INT_LINEAR); - trans = &transDst[0]; + if (_weight > 0.0f) + { + float transDst[3], rotDst[4], scaleDst[3]; + float* trans = nullptr, *rot = nullptr, *scale = nullptr; + if (_playReverse) + t = 1 - t; + + t = _start + t * _last; + for (const auto& it : _boneCurves) { + auto bone = it.first; + auto curve = it.second; + if (curve->translateCurve) + { + curve->translateCurve->evaluate(t, transDst, EvaluateType::INT_LINEAR); + trans = &transDst[0]; + } + if (curve->rotCurve) + { + curve->rotCurve->evaluate(t, rotDst, EvaluateType::INT_QUAT_SLERP); + rot = &rotDst[0]; + } + if (curve->scaleCurve) + { + curve->scaleCurve->evaluate(t, scaleDst, EvaluateType::INT_LINEAR); + scale = &scaleDst[0]; + } + bone->setAnimationValue(trans, rot, scale, this, _weight); } - if (curve->rotCurve) - { - curve->rotCurve->evaluate(t, rotDst, EvaluateType::INT_QUAT_SLERP); - rot = &rotDst[0]; - } - if (curve->scaleCurve) - { - curve->scaleCurve->evaluate(t, scaleDst, EvaluateType::INT_LINEAR); - scale = &scaleDst[0]; - } - bone->setAnimationValue(trans, rot, scale, this, _weight); } } - } float Animate3D::getSpeed() const @@ -172,12 +243,32 @@ Animate3D::Animate3D() , _last(1.f) , _animation(nullptr) , _playReverse(false) +, _state(Animate3D::Animate3DState::Running) +, _accTransTime(0.0f) +, _lastTime(0.0f) { } Animate3D::~Animate3D() { + removeFromMap(); + CC_SAFE_RELEASE(_animation); } +void Animate3D::removeFromMap() +{ + //remove this action from map + if (_target) + { + Sprite3D* sprite = static_cast(_target); + if (_state == Animate3D::Animate3DState::FadeIn) + s_fadeInAnimates.erase(sprite); + else if (_state == Animate3D::Animate3DState::FadeOut) + s_fadeOutAnimates.erase(sprite); + else + s_runningAnimates.erase(sprite); + } +} + NS_CC_END diff --git a/cocos/3d/CCAnimate3D.h b/cocos/3d/CCAnimate3D.h index a1c79adefd..5591e96f4b 100644 --- a/cocos/3d/CCAnimate3D.h +++ b/cocos/3d/CCAnimate3D.h @@ -26,6 +26,7 @@ #define __CCANIMATE3D_H__ #include +#include #include "3d/CCAnimation3D.h" #include "3d/3dExport.h" @@ -36,6 +37,7 @@ NS_CC_BEGIN class Bone3D; +class Sprite3D; /** * Animate3D, Animates a Sprite3D given with an Animation3D */ @@ -57,6 +59,7 @@ public: // // Overrides // + virtual void stop() override; virtual void step(float dt) override; virtual void startWithTarget(Node *target) override; virtual Animate3D* reverse() const override; @@ -72,6 +75,9 @@ public: float getWeight() const { return _weight; } void setWeight(float weight); + /** animate transistion time */ + static float getTransitionTime() { return _transTime; } + /**get & set play reverse, these are deprecated, use set negative speed instead*/ CC_DEPRECATED_ATTRIBUTE bool getPlayBack() const { return _playReverse; } CC_DEPRECATED_ATTRIBUTE void setPlayBack(bool reverse) { _playReverse = reverse; } @@ -81,7 +87,16 @@ CC_CONSTRUCTOR_ACCESS: Animate3D(); virtual ~Animate3D(); + void removeFromMap(); + protected: + enum class Animate3DState + { + FadeIn, + FadeOut, + Running, + }; + Animate3DState _state; //animation state Animation3D* _animation; //animation data float _absSpeed; //playing speed @@ -89,7 +104,15 @@ protected: float _start; //start time 0 - 1, used to generate sub Animate3D float _last; //last time 0 - 1, used to generate sub Animate3D bool _playReverse; // is playing reverse - std::map _boneCurves; //weak ref + static float _transTime; //transition time from one animate3d to another + float _accTransTime; // acculate transition time + float _lastTime; // last t (0 - 1) + std::unordered_map _boneCurves; //weak ref + + //sprite animates + static std::unordered_map s_fadeInAnimates; + static std::unordered_map s_fadeOutAnimates; + static std::unordered_map s_runningAnimates; }; NS_CC_END diff --git a/cocos/3d/CCSkeleton3D.cpp b/cocos/3d/CCSkeleton3D.cpp index f3dc240a47..9aee6d79f6 100644 --- a/cocos/3d/CCSkeleton3D.cpp +++ b/cocos/3d/CCSkeleton3D.cpp @@ -231,6 +231,7 @@ void Bone3D::updateLocalMat() } quat = Quaternion(it.localRot.x * weight + quat.x, it.localRot.y * weight + quat.y, it.localRot.z * weight + quat.z, it.localRot.w * weight + quat.w); } + quat.normalize(); } } diff --git a/cocos/3d/cocos3d.h b/cocos/3d/cocos3d.h index fdbfef8fca..dbd2760feb 100755 --- a/cocos/3d/cocos3d.h +++ b/cocos/3d/cocos3d.h @@ -37,5 +37,6 @@ #include "3d/CCSprite3DMaterial.h" #include "3d/CCAttachNode.h" #include "3d/CCMeshVertexIndexData.h" +#include "3d/CCSkeleton3D.h" #endif diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index 0378994aee..6fdebe0823 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -808,7 +808,6 @@ Animate3DTest::Animate3DTest() , _swim(nullptr) , _sprite(nullptr) , _moveAction(nullptr) -, _transTime(0.1f) , _elapseTransTime(0.f) { addSprite3D(); @@ -842,28 +841,21 @@ void Animate3DTest::update(float dt) if (_state == State::HURT_TO_SWIMMING) { _elapseTransTime += dt; - float t = _elapseTransTime / _transTime; - if (t >= 1.f) + if (_elapseTransTime >= Animate3D::getTransitionTime()) { - t = 1.f; _sprite->stopAction(_hurt); _state = State::SWIMMING; } - _swim->setWeight(t); - _hurt->setWeight(1.f - t); } else if (_state == State::SWIMMING_TO_HURT) { _elapseTransTime += dt; - float t = _elapseTransTime / _transTime; - if (t >= 1.f) + if (_elapseTransTime >= Animate3D::getTransitionTime()) { - t = 1.f; + _sprite->stopAction(_swim); _state = State::HURT; } - _swim->setWeight(1.f - t); - _hurt->setWeight(t); } } @@ -880,8 +872,9 @@ void Animate3DTest::addSprite3D() if (animation) { auto animate = Animate3D::create(animation, 0.f, 1.933f); - sprite->runAction(RepeatForever::create(animate)); - _swim = animate; + _swim = RepeatForever::create(animate); + sprite->runAction(_swim); + _swim->retain(); _hurt = Animate3D::create(animation, 1.933f, 2.8f); _hurt->retain(); @@ -910,8 +903,10 @@ void Animate3DTest::reachEndCallBack() void Animate3DTest::renewCallBack() { - _sprite->stopActionByTag(101); + //rerun swim action + _sprite->runAction(_swim); _state = State::HURT_TO_SWIMMING; + _elapseTransTime = 0.0f; } void Animate3DTest::onTouchesEnded(const std::vector& touches, Event* event) @@ -928,12 +923,14 @@ void Animate3DTest::onTouchesEnded(const std::vector& touches, Event* ev //hurt the tortoise if (_state == State::SWIMMING) { + _elapseTransTime = 0.0f; + _state = State::SWIMMING_TO_HURT; + _sprite->stopAction(_hurt); _sprite->runAction(_hurt); - auto delay = DelayTime::create(_hurt->getDuration() - 0.1f); + auto delay = DelayTime::create(_hurt->getDuration() - Animate3D::getTransitionTime()); auto seq = Sequence::create(delay, CallFunc::create(CC_CALLBACK_0(Animate3DTest::renewCallBack, this)), nullptr); seq->setTag(101); _sprite->runAction(seq); - _state = State::SWIMMING_TO_HURT; } return; } diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h index b2ac350077..fcb5de6c0e 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h @@ -219,9 +219,9 @@ protected: cocos2d::Sprite3D* _sprite; - cocos2d::Animate3D* _swim; + cocos2d::Action* _swim; cocos2d::Animate3D* _hurt; - float _transTime; + float _elapseTransTime; State _state;