mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 16:56:47 +00:00 
			
		
		
		
	Merge pull request #2498 from akortunov/master
[Regression] inject bones for NPC's with custom animation models
This commit is contained in:
		
						commit
						ca724d45a1
					
				
					 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