mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 00:26:39 +00:00 
			
		
		
		
	[Regression] inject bones for NPC's with custom animation models
This commit is contained in:
		
							parent
							
								
									0afb142b8e
								
							
						
					
					
						commit
						6156ab45de
					
				
					 1 changed files with 48 additions and 23 deletions
				
			
		| 
						 | 
				
			
			@ -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())
 | 
			
		||||
        {
 | 
			
		||||
            MWWorld::LiveCellRef<ESM::Creature> *ref = mPtr.get<ESM::Creature>();
 | 
			
		||||
            if(ref->mBase->mFlags & ESM::Creature::Bipedal)
 | 
			
		||||
                inject = InjectType::ModelWithFallback;
 | 
			
		||||
            if (isCreature)
 | 
			
		||||
            {
 | 
			
		||||
                MWWorld::LiveCellRef<ESM::Creature> *ref = mPtr.get<ESM::Creature>();
 | 
			
		||||
                if(ref->mBase->mFlags & ESM::Creature::Bipedal)
 | 
			
		||||
                {
 | 
			
		||||
                    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…
	
		Reference in a new issue