1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Restore / fix bone overrides

This commit is contained in:
Lars Mueller 2025-01-18 19:28:52 +01:00
parent a687a7a6e7
commit d10abba38c
5 changed files with 32 additions and 77 deletions

View file

@ -14,21 +14,6 @@ namespace scene
{ {
class IAnimatedMeshSceneNode; 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. //! Scene node capable of displaying an animated mesh.
class IAnimatedMeshSceneNode : public ISceneNode class IAnimatedMeshSceneNode : public ISceneNode
{ {
@ -108,11 +93,10 @@ public:
/** When true the animations are played looped */ /** When true the animations are played looped */
virtual bool getLoopMode() const = 0; virtual bool getLoopMode() const = 0;
//! Sets a callback interface which will be called if an animation playback has ended. //! Will be called right after the joints have been animated,
/** Set this to 0 to disable the callback again. //! but before the transforms have been propagated recursively to children.
Please note that this will only be called when in non looped virtual void setOnAnimateCallback(
mode, see IAnimatedMeshSceneNode::setLoopMode(). */ const std::function<void(f32 dtime)> &cb) = 0;
virtual void setAnimationEndCallback(IAnimationEndCallBack *callback = 0) = 0;
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. //! 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 /** In this way it is possible to change the materials a mesh

View file

@ -36,7 +36,7 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh *mesh,
TransitionTime(0), Transiting(0.f), TransitingBlend(0.f), TransitionTime(0), Transiting(0.f), TransitingBlend(0.f),
JointsUsed(false), JointsUsed(false),
Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false), Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false),
LoopCallBack(0), PassCount(0) PassCount(0)
{ {
setMesh(mesh); setMesh(mesh);
} }
@ -44,8 +44,6 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh *mesh,
//! destructor //! destructor
CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode() CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode()
{ {
if (LoopCallBack)
LoopCallBack->drop();
if (Mesh) if (Mesh)
Mesh->drop(); Mesh->drop();
} }
@ -87,8 +85,7 @@ void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs)
if (FramesPerSecond > 0.f) { // forwards... if (FramesPerSecond > 0.f) { // forwards...
if (CurrentFrameNr > EndFrame) if (CurrentFrameNr > EndFrame)
CurrentFrameNr = StartFrame + fmodf(CurrentFrameNr - StartFrame, EndFrame - StartFrame); CurrentFrameNr = StartFrame + fmodf(CurrentFrameNr - StartFrame, EndFrame - StartFrame);
} else // backwards... } else { // backwards...
{
if (CurrentFrameNr < StartFrame) if (CurrentFrameNr < StartFrame)
CurrentFrameNr = EndFrame - fmodf(EndFrame - CurrentFrameNr, EndFrame - StartFrame); CurrentFrameNr = EndFrame - fmodf(EndFrame - CurrentFrameNr, EndFrame - StartFrame);
} }
@ -97,18 +94,9 @@ void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs)
CurrentFrameNr += timeMs * FramesPerSecond; CurrentFrameNr += timeMs * FramesPerSecond;
if (FramesPerSecond > 0.f) { // forwards... if (FramesPerSecond > 0.f) { // forwards...
if (CurrentFrameNr > EndFrame) { CurrentFrameNr = std::min(CurrentFrameNr, EndFrame);
CurrentFrameNr = EndFrame; } else { // backwards...
if (LoopCallBack) CurrentFrameNr = std::max(CurrentFrameNr, StartFrame);
LoopCallBack->OnAnimationEnd(this);
}
} else // backwards...
{
if (CurrentFrameNr < StartFrame) {
CurrentFrameNr = StartFrame;
if (LoopCallBack)
LoopCallBack->OnAnimationEnd(this);
}
} }
} }
} }
@ -191,6 +179,8 @@ void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs)
// anything is rendered so that the transformations of children are up to date // anything is rendered so that the transformations of children are up to date
animateJoints(); animateJoints();
OnAnimateCallback(timeMs / 1000.0f);
IAnimatedMeshSceneNode::OnAnimate(timeMs); IAnimatedMeshSceneNode::OnAnimate(timeMs);
} }
@ -461,22 +451,6 @@ bool CAnimatedMeshSceneNode::getLoopMode() const
return Looping; 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. //! 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) void CAnimatedMeshSceneNode::setReadOnlyMaterials(bool readonly)
{ {
@ -681,9 +655,6 @@ ISceneNode *CAnimatedMeshSceneNode::clone(ISceneNode *newParent, ISceneManager *
newNode->TransitingBlend = TransitingBlend; newNode->TransitingBlend = TransitingBlend;
newNode->Looping = Looping; newNode->Looping = Looping;
newNode->ReadOnlyMaterials = ReadOnlyMaterials; newNode->ReadOnlyMaterials = ReadOnlyMaterials;
newNode->LoopCallBack = LoopCallBack;
if (newNode->LoopCallBack)
newNode->LoopCallBack->grab();
newNode->PassCount = PassCount; newNode->PassCount = PassCount;
newNode->JointChildSceneNodes = JointChildSceneNodes; newNode->JointChildSceneNodes = JointChildSceneNodes;
newNode->PretransitingSave = PretransitingSave; newNode->PretransitingSave = PretransitingSave;

View file

@ -54,9 +54,11 @@ public:
//! returns the current loop mode //! returns the current loop mode
bool getLoopMode() const override; bool getLoopMode() const override;
//! Sets a callback interface which will be called if an animation void setOnAnimateCallback(
//! playback has ended. Set this to 0 to disable the callback again. const std::function<void(f32 dtime)> &cb) override
void setAnimationEndCallback(IAnimationEndCallBack *callback = 0) override; {
OnAnimateCallback = cb;
}
//! sets the speed with which the animation is played //! 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 //! 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 ReadOnlyMaterials;
bool RenderFromIdentity; bool RenderFromIdentity;
IAnimationEndCallBack *LoopCallBack;
s32 PassCount; s32 PassCount;
std::function<void(f32)> OnAnimateCallback;
std::vector<IBoneSceneNode *> JointChildSceneNodes; std::vector<IBoneSceneNode *> JointChildSceneNodes;
core::array<core::matrix4> PretransitingSave; core::array<core::matrix4> PretransitingSave;

View file

@ -682,7 +682,6 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
m_animated_meshnode = m_smgr->addAnimatedMeshSceneNode(mesh, m_matrixnode); m_animated_meshnode = m_smgr->addAnimatedMeshSceneNode(mesh, m_matrixnode);
m_animated_meshnode->grab(); m_animated_meshnode->grab();
mesh->drop(); // The scene node took hold of it 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); m_animated_meshnode->setScale(m_prop.visual_size);
// set vertex colors to ensure alpha is set // 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) { m_animated_meshnode->forEachMaterial([this] (auto &mat) {
mat.BackfaceCulling = m_prop.backface_culling; 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 } else
errorstream<<"GenericCAO::addToScene(): Could not load mesh "<<m_prop.mesh<<std::endl; errorstream<<"GenericCAO::addToScene(): Could not load mesh "<<m_prop.mesh<<std::endl;
break; break;
@ -783,7 +797,6 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
updateMarker(); updateMarker();
updateNodePos(); updateNodePos();
updateAnimation(); updateAnimation();
updateBones(.0f);
updateAttachments(); updateAttachments();
setNodeLight(m_last_light); setNodeLight(m_last_light);
updateMeshCulling(); updateMeshCulling();
@ -1174,18 +1187,6 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
rot_translator.val_current = m_rotation; rot_translator.val_current = m_rotation;
updateNodePos(); updateNodePos();
} }
if (m_animated_meshnode) {
// Everything must be updated; the whole transform
// chain as well as the animated mesh node.
// Otherwise, bone attachments would be relative to
// a position that's one frame old.
if (m_matrixnode)
updatePositionRecursive(m_matrixnode);
m_animated_meshnode->updateAbsolutePosition();
m_animated_meshnode->animateJoints();
updateBones(dtime);
}
} }
static void setMeshBufferTextureCoords(scene::IMeshBuffer *buf, const v2f *uv, u32 count) static void setMeshBufferTextureCoords(scene::IMeshBuffer *buf, const v2f *uv, u32 count)
@ -1746,7 +1747,6 @@ void GenericCAO::processMessage(const std::string &data)
} else { } else {
m_bone_override[bone] = props; m_bone_override[bone] = props;
} }
// updateBones(); now called every step
} else if (cmd == AO_CMD_ATTACH_TO) { } else if (cmd == AO_CMD_ATTACH_TO) {
u16 parent_id = readS16(is); u16 parent_id = readS16(is);
std::string bone = deSerializeString16(is); std::string bone = deSerializeString16(is);

View file

@ -286,8 +286,6 @@ public:
void updateAnimationSpeed(); void updateAnimationSpeed();
void updateBones(f32 dtime);
void processMessage(const std::string &data) override; void processMessage(const std::string &data) override;
bool directReportPunch(v3f dir, const ItemStack *punchitem, bool directReportPunch(v3f dir, const ItemStack *punchitem,