diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ee8bd8d92..be789859ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Bug #3855: AI sometimes spams defensive spells Bug #3905: Great House Dagoth issues Bug #4203: Resurrecting an actor should close the loot GUI + Bug #4389: NPC's lips do not move if his head model has the NiBSAnimationNode root node Bug #4602: Robert's Bodies: crash inside createInstance() Bug #4700: Editor: Incorrect command implementation Bug #4744: Invisible particles must still be processed diff --git a/apps/openmw/mwrender/actoranimation.cpp b/apps/openmw/mwrender/actoranimation.cpp index 1679c07bf4..25a9904e26 100644 --- a/apps/openmw/mwrender/actoranimation.cpp +++ b/apps/openmw/mwrender/actoranimation.cpp @@ -332,7 +332,7 @@ void ActorAnimation::resetControllers(osg::Node* node) std::shared_ptr src; src.reset(new NullAnimationTime); - SceneUtil::AssignControllerSourcesVisitor removeVisitor(src); + SceneUtil::ForceControllerSourcesVisitor removeVisitor(src); node->accept(removeVisitor); } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 0d6c21c308..7031b5a02b 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -837,14 +837,18 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g } } } + SceneUtil::ForceControllerSourcesVisitor assignVisitor(src); + node->accept(assignVisitor); } - else if (type == ESM::PRT_Weapon) - src = mWeaponAnimationTime; else - src.reset(new NullAnimationTime); - - SceneUtil::AssignControllerSourcesVisitor assignVisitor(src); - node->accept(assignVisitor); + { + if (type == ESM::PRT_Weapon) + src = mWeaponAnimationTime; + else + src.reset(new NullAnimationTime); + SceneUtil::AssignControllerSourcesVisitor assignVisitor(src); + node->accept(assignVisitor); + } } return true; diff --git a/components/sceneutil/controller.cpp b/components/sceneutil/controller.cpp index dfc72918aa..2c7507d0a3 100644 --- a/components/sceneutil/controller.cpp +++ b/components/sceneutil/controller.cpp @@ -121,6 +121,21 @@ namespace SceneUtil ctrl.setSource(mToAssign); } + ForceControllerSourcesVisitor::ForceControllerSourcesVisitor() + : AssignControllerSourcesVisitor() + { + } + + ForceControllerSourcesVisitor::ForceControllerSourcesVisitor(std::shared_ptr toAssign) + : AssignControllerSourcesVisitor(toAssign) + { + } + + void ForceControllerSourcesVisitor::visit(osg::Node&, Controller &ctrl) + { + ctrl.setSource(mToAssign); + } + FindMaxControllerLengthVisitor::FindMaxControllerLengthVisitor() : SceneUtil::ControllerVisitor() , mMaxLength(0) diff --git a/components/sceneutil/controller.hpp b/components/sceneutil/controller.hpp index 2656d654e1..6ef800f05b 100644 --- a/components/sceneutil/controller.hpp +++ b/components/sceneutil/controller.hpp @@ -85,10 +85,20 @@ namespace SceneUtil /// By default assigns the ControllerSource passed to the constructor of this class if no ControllerSource is assigned to that controller yet. void visit(osg::Node& node, Controller& ctrl) override; - private: + protected: std::shared_ptr mToAssign; }; + class ForceControllerSourcesVisitor : public AssignControllerSourcesVisitor + { + public: + ForceControllerSourcesVisitor(); + ForceControllerSourcesVisitor(std::shared_ptr toAssign); + + /// Assign the wanted ControllerSource even if one is already assigned to the controller. + void visit(osg::Node& node, Controller& ctrl) override; + }; + /// Finds the maximum of all controller functions in the given scene graph class FindMaxControllerLengthVisitor : public ControllerVisitor {