[Regression] inject bones for NPC's with custom animation models

pull/541/head
Andrei Kortunov 5 years ago
parent 0afb142b8e
commit 6156ab45de

@ -18,12 +18,14 @@
#include <components/resource/keyframemanager.hpp>
#include <components/misc/constants.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/nifosg/nifloader.hpp> // KeyframeHolder
#include <components/nifosg/controller.hpp>
#include <components/vfs/manager.hpp>
#include <components/sceneutil/actorutil.hpp>
#include <components/sceneutil/statesetupdater.hpp>
#include <components/sceneutil/visitor.hpp>
#include <components/sceneutil/lightmanager.hpp>
@ -1378,6 +1380,9 @@ namespace MWRender
void injectCustomBones(osg::ref_ptr<osg::Node>& node, const std::string& model, Resource::ResourceSystem* resourceSystem)
{
if (model.empty())
return;
const std::map<std::string, VFS::File*>& index = resourceSystem->getVFS()->getIndex();
std::string animationPath = model;
@ -1405,14 +1410,7 @@ namespace MWRender
}
}
enum InjectType
{
None,
Model,
ModelWithFallback
};
osg::ref_ptr<osg::Node> getModelInstance(Resource::ResourceSystem* resourceSystem, const std::string& model, bool baseonly, InjectType inject)
osg::ref_ptr<osg::Node> getModelInstance(Resource::ResourceSystem* resourceSystem, const std::string& model, bool baseonly, bool inject, const std::string& defaultSkeleton)
{
Resource::SceneManager* sceneMgr = resourceSystem->getSceneManager();
if (baseonly)
@ -1424,11 +1422,11 @@ namespace MWRender
{
osg::ref_ptr<osg::Node> created = sceneMgr->getInstance(model);
if (inject == InjectType::ModelWithFallback)
injectCustomBones(created, "meshes\\xbase_anim.nif", resourceSystem);
if (inject != InjectType::None)
if (inject)
{
injectCustomBones(created, defaultSkeleton, resourceSystem);
injectCustomBones(created, model, resourceSystem);
}
SceneUtil::CleanObjectRootVisitor removeDrawableVisitor;
created->accept(removeDrawableVisitor);
@ -1445,11 +1443,11 @@ namespace MWRender
{
osg::ref_ptr<osg::Node> created = sceneMgr->getInstance(model);
if (inject == InjectType::ModelWithFallback)
injectCustomBones(created, "meshes\\xbase_anim.nif", resourceSystem);
if (inject != InjectType::None)
if (inject)
{
injectCustomBones(created, defaultSkeleton, resourceSystem);
injectCustomBones(created, model, resourceSystem);
}
return created;
}
@ -1475,17 +1473,44 @@ namespace MWRender
mAccumCtrl = nullptr;
static const bool useAdditionalSources = Settings::Manager::getBool ("use additional anim sources", "Game");
InjectType inject = useAdditionalSources && mPtr.getClass().isActor() ? InjectType::Model : InjectType::None;
if (inject != InjectType::None && isCreature)
std::string defaultSkeleton;
bool inject = false;
if (useAdditionalSources && mPtr.getClass().isActor())
{
if (isCreature)
{
MWWorld::LiveCellRef<ESM::Creature> *ref = mPtr.get<ESM::Creature>();
if(ref->mBase->mFlags & ESM::Creature::Bipedal)
inject = InjectType::ModelWithFallback;
{
defaultSkeleton = "meshes\\xbase_anim.nif";
inject = true;
}
}
else
{
inject = true;
MWWorld::LiveCellRef<ESM::NPC> *ref = mPtr.get<ESM::NPC>();
if (!ref->mBase->mModel.empty())
{
// If NPC has a custom animation model attached, we should inject bones from default skeleton for given race and gender as well
// Since it is a quite rare case, there should not be a noticable performance loss
// Note: consider that player and werewolves have no custom animation files attached for now
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
const ESM::Race *race = store.get<ESM::Race>().find(ref->mBase->mRace);
bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0;
bool isFemale = !ref->mBase->isMale();
defaultSkeleton = SceneUtil::getActorSkeleton(false, isFemale, isBeast, false);
defaultSkeleton = Misc::ResourceHelpers::correctActorModelPath(defaultSkeleton, mResourceSystem->getVFS());
}
}
}
if (!forceskeleton)
{
osg::ref_ptr<osg::Node> created = getModelInstance(mResourceSystem, model, baseonly, inject);
osg::ref_ptr<osg::Node> created = getModelInstance(mResourceSystem, model, baseonly, inject, defaultSkeleton);
mInsert->addChild(created);
mObjectRoot = created->asGroup();
if (!mObjectRoot)
@ -1501,7 +1526,7 @@ namespace MWRender
}
else
{
osg::ref_ptr<osg::Node> created = getModelInstance(mResourceSystem, model, baseonly, inject);
osg::ref_ptr<osg::Node> created = getModelInstance(mResourceSystem, model, baseonly, inject, defaultSkeleton);
osg::ref_ptr<SceneUtil::Skeleton> skel = dynamic_cast<SceneUtil::Skeleton*>(created.get());
if (!skel)
{

Loading…
Cancel
Save