diff --git a/irr/include/IAnimatedMeshSceneNode.h b/irr/include/IAnimatedMeshSceneNode.h index 2400c354f..6a9a2774f 100644 --- a/irr/include/IAnimatedMeshSceneNode.h +++ b/irr/include/IAnimatedMeshSceneNode.h @@ -14,21 +14,6 @@ namespace scene { class IAnimatedMeshSceneNode; -//! Callback interface for catching events of ended animations. -/** Implement this interface and use -IAnimatedMeshSceneNode::setAnimationEndCallback to be able to -be notified if an animation playback has ended. -**/ -class IAnimationEndCallBack : public virtual IReferenceCounted -{ -public: - //! Will be called when the animation playback has ended. - /** See IAnimatedMeshSceneNode::setAnimationEndCallback for - more information. - \param node: Node of which the animation has ended. */ - virtual void OnAnimationEnd(IAnimatedMeshSceneNode *node) = 0; -}; - //! Scene node capable of displaying an animated mesh. class IAnimatedMeshSceneNode : public ISceneNode { @@ -108,11 +93,10 @@ public: /** When true the animations are played looped */ virtual bool getLoopMode() const = 0; - //! Sets a callback interface which will be called if an animation playback has ended. - /** Set this to 0 to disable the callback again. - Please note that this will only be called when in non looped - mode, see IAnimatedMeshSceneNode::setLoopMode(). */ - virtual void setAnimationEndCallback(IAnimationEndCallBack *callback = 0) = 0; + //! Will be called right after the joints have been animated, + //! but before the transforms have been propagated recursively to children. + virtual void setOnAnimateCallback( + const std::function &cb) = 0; //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. /** In this way it is possible to change the materials a mesh diff --git a/irr/src/CAnimatedMeshSceneNode.cpp b/irr/src/CAnimatedMeshSceneNode.cpp index d36932689..c8eb0eabd 100644 --- a/irr/src/CAnimatedMeshSceneNode.cpp +++ b/irr/src/CAnimatedMeshSceneNode.cpp @@ -36,7 +36,7 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh *mesh, TransitionTime(0), Transiting(0.f), TransitingBlend(0.f), JointsUsed(false), Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false), - LoopCallBack(0), PassCount(0) + PassCount(0) { setMesh(mesh); } @@ -44,8 +44,6 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh *mesh, //! destructor CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode() { - if (LoopCallBack) - LoopCallBack->drop(); if (Mesh) Mesh->drop(); } @@ -87,8 +85,7 @@ void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs) if (FramesPerSecond > 0.f) { // forwards... if (CurrentFrameNr > EndFrame) CurrentFrameNr = StartFrame + fmodf(CurrentFrameNr - StartFrame, EndFrame - StartFrame); - } else // backwards... - { + } else { // backwards... if (CurrentFrameNr < StartFrame) CurrentFrameNr = EndFrame - fmodf(EndFrame - CurrentFrameNr, EndFrame - StartFrame); } @@ -97,18 +94,9 @@ void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs) CurrentFrameNr += timeMs * FramesPerSecond; if (FramesPerSecond > 0.f) { // forwards... - if (CurrentFrameNr > EndFrame) { - CurrentFrameNr = EndFrame; - if (LoopCallBack) - LoopCallBack->OnAnimationEnd(this); - } - } else // backwards... - { - if (CurrentFrameNr < StartFrame) { - CurrentFrameNr = StartFrame; - if (LoopCallBack) - LoopCallBack->OnAnimationEnd(this); - } + CurrentFrameNr = std::min(CurrentFrameNr, EndFrame); + } else { // backwards... + CurrentFrameNr = std::max(CurrentFrameNr, StartFrame); } } } @@ -191,6 +179,8 @@ void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs) // anything is rendered so that the transformations of children are up to date animateJoints(); + OnAnimateCallback(timeMs / 1000.0f); + IAnimatedMeshSceneNode::OnAnimate(timeMs); } @@ -461,22 +451,6 @@ bool CAnimatedMeshSceneNode::getLoopMode() const return Looping; } -//! Sets a callback interface which will be called if an animation -//! playback has ended. Set this to 0 to disable the callback again. -void CAnimatedMeshSceneNode::setAnimationEndCallback(IAnimationEndCallBack *callback) -{ - if (callback == LoopCallBack) - return; - - if (LoopCallBack) - LoopCallBack->drop(); - - LoopCallBack = callback; - - if (LoopCallBack) - LoopCallBack->grab(); -} - //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. void CAnimatedMeshSceneNode::setReadOnlyMaterials(bool readonly) { @@ -681,9 +655,6 @@ ISceneNode *CAnimatedMeshSceneNode::clone(ISceneNode *newParent, ISceneManager * newNode->TransitingBlend = TransitingBlend; newNode->Looping = Looping; newNode->ReadOnlyMaterials = ReadOnlyMaterials; - newNode->LoopCallBack = LoopCallBack; - if (newNode->LoopCallBack) - newNode->LoopCallBack->grab(); newNode->PassCount = PassCount; newNode->JointChildSceneNodes = JointChildSceneNodes; newNode->PretransitingSave = PretransitingSave; diff --git a/irr/src/CAnimatedMeshSceneNode.h b/irr/src/CAnimatedMeshSceneNode.h index b8e5fd245..6acc5e241 100644 --- a/irr/src/CAnimatedMeshSceneNode.h +++ b/irr/src/CAnimatedMeshSceneNode.h @@ -54,9 +54,11 @@ public: //! returns the current loop mode bool getLoopMode() const override; - //! Sets a callback interface which will be called if an animation - //! playback has ended. Set this to 0 to disable the callback again. - void setAnimationEndCallback(IAnimationEndCallBack *callback = 0) override; + void setOnAnimateCallback( + const std::function &cb) override + { + OnAnimateCallback = cb; + } //! sets the speed with which the animation is played //! NOTE: setMesh will also change this value and set it to the default speed of the mesh @@ -161,8 +163,8 @@ private: bool ReadOnlyMaterials; bool RenderFromIdentity; - IAnimationEndCallBack *LoopCallBack; s32 PassCount; + std::function OnAnimateCallback; std::vector JointChildSceneNodes; core::array PretransitingSave; diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 16aac49a7..13648aa87 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -682,7 +682,6 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr) m_animated_meshnode = m_smgr->addAnimatedMeshSceneNode(mesh, m_matrixnode); m_animated_meshnode->grab(); mesh->drop(); // The scene node took hold of it - m_animated_meshnode->animateJoints(); // Needed for some animations m_animated_meshnode->setScale(m_prop.visual_size); // set vertex colors to ensure alpha is set @@ -693,6 +692,21 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr) m_animated_meshnode->forEachMaterial([this] (auto &mat) { mat.BackfaceCulling = m_prop.backface_culling; }); + + m_animated_meshnode->setOnAnimateCallback([&](f32 dtime) { + for (auto &it : m_bone_override) { + auto* bone = m_animated_meshnode->getJointNode(it.first.c_str()); + if (!bone) + continue; + + BoneOverride &props = it.second; + props.dtime_passed += dtime; + + bone->setPosition(props.getPosition(bone->getPosition())); + bone->setRotation(props.getRotationEulerDeg(bone->getRotation())); + bone->setScale(props.getScale(bone->getScale())); + } + }); } else errorstream<<"GenericCAO::addToScene(): Could not load mesh "<updateAbsolutePosition(); - m_animated_meshnode->animateJoints(); - updateBones(dtime); - } } static void setMeshBufferTextureCoords(scene::IMeshBuffer *buf, const v2f *uv, u32 count) @@ -1746,7 +1747,6 @@ void GenericCAO::processMessage(const std::string &data) } else { m_bone_override[bone] = props; } - // updateBones(); now called every step } else if (cmd == AO_CMD_ATTACH_TO) { u16 parent_id = readS16(is); std::string bone = deSerializeString16(is); diff --git a/src/client/content_cao.h b/src/client/content_cao.h index 9762684f6..2e765ab6e 100644 --- a/src/client/content_cao.h +++ b/src/client/content_cao.h @@ -286,8 +286,6 @@ public: void updateAnimationSpeed(); - void updateBones(f32 dtime); - void processMessage(const std::string &data) override; bool directReportPunch(v3f dir, const ItemStack *punchitem,