mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 22:56:44 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			232 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			232 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "objects.hpp"
 | |
| 
 | |
| #include <osg/Group>
 | |
| #include <osg/UserDataContainer>
 | |
| 
 | |
| #include <components/sceneutil/positionattitudetransform.hpp>
 | |
| #include <components/sceneutil/unrefqueue.hpp>
 | |
| 
 | |
| #include "../mwworld/ptr.hpp"
 | |
| #include "../mwworld/class.hpp"
 | |
| 
 | |
| #include "animation.hpp"
 | |
| #include "npcanimation.hpp"
 | |
| #include "creatureanimation.hpp"
 | |
| #include "vismask.hpp"
 | |
| 
 | |
| 
 | |
| namespace MWRender
 | |
| {
 | |
| 
 | |
| Objects::Objects(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> rootNode, SceneUtil::UnrefQueue* unrefQueue)
 | |
|     : mRootNode(rootNode)
 | |
|     , mResourceSystem(resourceSystem)
 | |
|     , mUnrefQueue(unrefQueue)
 | |
| {
 | |
| }
 | |
| 
 | |
| Objects::~Objects()
 | |
| {
 | |
|     mObjects.clear();
 | |
| 
 | |
|     for (CellMap::iterator iter = mCellSceneNodes.begin(); iter != mCellSceneNodes.end(); ++iter)
 | |
|         iter->second->getParent(0)->removeChild(iter->second);
 | |
|     mCellSceneNodes.clear();
 | |
| }
 | |
| 
 | |
| void Objects::insertBegin(const MWWorld::Ptr& ptr)
 | |
| {
 | |
|     assert(mObjects.find(ptr) == mObjects.end());
 | |
| 
 | |
|     osg::ref_ptr<osg::Group> cellnode;
 | |
| 
 | |
|     CellMap::iterator found = mCellSceneNodes.find(ptr.getCell());
 | |
|     if (found == mCellSceneNodes.end())
 | |
|     {
 | |
|         cellnode = new osg::Group;
 | |
|         cellnode->setName("Cell Root");
 | |
|         mRootNode->addChild(cellnode);
 | |
|         mCellSceneNodes[ptr.getCell()] = cellnode;
 | |
|     }
 | |
|     else
 | |
|         cellnode = found->second;
 | |
| 
 | |
|     osg::ref_ptr<SceneUtil::PositionAttitudeTransform> insert (new SceneUtil::PositionAttitudeTransform);
 | |
|     cellnode->addChild(insert);
 | |
| 
 | |
|     insert->getOrCreateUserDataContainer()->addUserObject(new PtrHolder(ptr));
 | |
| 
 | |
|     const float *f = ptr.getRefData().getPosition().pos;
 | |
| 
 | |
|     insert->setPosition(osg::Vec3(f[0], f[1], f[2]));
 | |
| 
 | |
|     const float scale = ptr.getCellRef().getScale();
 | |
|     osg::Vec3f scaleVec(scale, scale, scale);
 | |
|     ptr.getClass().adjustScale(ptr, scaleVec, true);
 | |
|     insert->setScale(scaleVec);
 | |
| 
 | |
|     ptr.getRefData().setBaseNode(insert);
 | |
| }
 | |
| 
 | |
| void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh, bool animated, bool allowLight)
 | |
| {
 | |
|     insertBegin(ptr);
 | |
|     ptr.getRefData().getBaseNode()->setNodeMask(Mask_Object);
 | |
| 
 | |
|     osg::ref_ptr<ObjectAnimation> anim (new ObjectAnimation(ptr, mesh, mResourceSystem, animated, allowLight));
 | |
| 
 | |
|     mObjects.insert(std::make_pair(ptr, anim));
 | |
| }
 | |
| 
 | |
| void Objects::insertCreature(const MWWorld::Ptr &ptr, const std::string &mesh, bool weaponsShields)
 | |
| {
 | |
|     insertBegin(ptr);
 | |
|     ptr.getRefData().getBaseNode()->setNodeMask(Mask_Actor);
 | |
| 
 | |
|     // CreatureAnimation
 | |
|     osg::ref_ptr<Animation> anim;
 | |
| 
 | |
|     if (weaponsShields)
 | |
|         anim = new CreatureWeaponAnimation(ptr, mesh, mResourceSystem);
 | |
|     else
 | |
|         anim = new CreatureAnimation(ptr, mesh, mResourceSystem);
 | |
| 
 | |
|     if (mObjects.insert(std::make_pair(ptr, anim)).second)
 | |
|         ptr.getClass().getContainerStore(ptr).setContListener(static_cast<ActorAnimation*>(anim.get()));
 | |
| }
 | |
| 
 | |
| void Objects::insertNPC(const MWWorld::Ptr &ptr)
 | |
| {
 | |
|     insertBegin(ptr);
 | |
|     ptr.getRefData().getBaseNode()->setNodeMask(Mask_Actor);
 | |
| 
 | |
|     osg::ref_ptr<NpcAnimation> anim (new NpcAnimation(ptr, osg::ref_ptr<osg::Group>(ptr.getRefData().getBaseNode()), mResourceSystem));
 | |
| 
 | |
|     if (mObjects.insert(std::make_pair(ptr, anim)).second)
 | |
|     {
 | |
|         ptr.getClass().getInventoryStore(ptr).setInvListener(anim.get(), ptr);
 | |
|         ptr.getClass().getInventoryStore(ptr).setContListener(anim.get());
 | |
|     }
 | |
| }
 | |
| 
 | |
| bool Objects::removeObject (const MWWorld::Ptr& ptr)
 | |
| {
 | |
|     if(!ptr.getRefData().getBaseNode())
 | |
|         return true;
 | |
| 
 | |
|     PtrAnimationMap::iterator iter = mObjects.find(ptr);
 | |
|     if(iter != mObjects.end())
 | |
|     {
 | |
|         if (mUnrefQueue.get())
 | |
|             mUnrefQueue->push(iter->second);
 | |
| 
 | |
|         mObjects.erase(iter);
 | |
| 
 | |
|         if (ptr.getClass().isActor())
 | |
|         {
 | |
|             if (ptr.getClass().hasInventoryStore(ptr))
 | |
|                 ptr.getClass().getInventoryStore(ptr).setInvListener(nullptr, ptr);
 | |
| 
 | |
|             ptr.getClass().getContainerStore(ptr).setContListener(nullptr);
 | |
|         }
 | |
| 
 | |
|         ptr.getRefData().getBaseNode()->getParent(0)->removeChild(ptr.getRefData().getBaseNode());
 | |
| 
 | |
|         ptr.getRefData().setBaseNode(nullptr);
 | |
|         return true;
 | |
|     }
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| 
 | |
| void Objects::removeCell(const MWWorld::CellStore* store)
 | |
| {
 | |
|     for(PtrAnimationMap::iterator iter = mObjects.begin();iter != mObjects.end();)
 | |
|     {
 | |
|         MWWorld::Ptr ptr = iter->second->getPtr();
 | |
|         if(ptr.getCell() == store)
 | |
|         {
 | |
|             if (mUnrefQueue.get())
 | |
|                 mUnrefQueue->push(iter->second);
 | |
| 
 | |
|             if (ptr.getClass().isNpc() && ptr.getRefData().getCustomData())
 | |
|             {
 | |
|                 MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore(ptr);
 | |
|                 invStore.setInvListener(nullptr, ptr);
 | |
|                 invStore.setContListener(nullptr);
 | |
|             }
 | |
| 
 | |
|             mObjects.erase(iter++);
 | |
|         }
 | |
|         else
 | |
|             ++iter;
 | |
|     }
 | |
| 
 | |
|     CellMap::iterator cell = mCellSceneNodes.find(store);
 | |
|     if(cell != mCellSceneNodes.end())
 | |
|     {
 | |
|         cell->second->getParent(0)->removeChild(cell->second);
 | |
|         if (mUnrefQueue.get())
 | |
|             mUnrefQueue->push(cell->second);
 | |
|         mCellSceneNodes.erase(cell);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void Objects::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &cur)
 | |
| {
 | |
|     osg::Node* objectNode = cur.getRefData().getBaseNode();
 | |
|     if (!objectNode)
 | |
|         return;
 | |
| 
 | |
|     MWWorld::CellStore *newCell = cur.getCell();
 | |
| 
 | |
|     osg::Group* cellnode;
 | |
|     if(mCellSceneNodes.find(newCell) == mCellSceneNodes.end()) {
 | |
|         cellnode = new osg::Group;
 | |
|         mRootNode->addChild(cellnode);
 | |
|         mCellSceneNodes[newCell] = cellnode;
 | |
|     } else {
 | |
|         cellnode = mCellSceneNodes[newCell];
 | |
|     }
 | |
| 
 | |
|     osg::UserDataContainer* userDataContainer = objectNode->getUserDataContainer();
 | |
|     if (userDataContainer)
 | |
|         for (unsigned int i=0; i<userDataContainer->getNumUserObjects(); ++i)
 | |
|         {
 | |
|             if (dynamic_cast<PtrHolder*>(userDataContainer->getUserObject(i)))
 | |
|                 userDataContainer->setUserObject(i, new PtrHolder(cur));
 | |
|         }
 | |
| 
 | |
|     if (objectNode->getNumParents())
 | |
|         objectNode->getParent(0)->removeChild(objectNode);
 | |
|     cellnode->addChild(objectNode);
 | |
| 
 | |
|     PtrAnimationMap::iterator iter = mObjects.find(old);
 | |
|     if(iter != mObjects.end())
 | |
|     {
 | |
|         osg::ref_ptr<Animation> anim = iter->second;
 | |
|         mObjects.erase(iter);
 | |
|         anim->updatePtr(cur);
 | |
|         mObjects[cur] = anim;
 | |
|     }
 | |
| }
 | |
| 
 | |
| Animation* Objects::getAnimation(const MWWorld::Ptr &ptr)
 | |
| {
 | |
|     PtrAnimationMap::const_iterator iter = mObjects.find(ptr);
 | |
|     if(iter != mObjects.end())
 | |
|         return iter->second;
 | |
| 
 | |
|     return nullptr;
 | |
| }
 | |
| 
 | |
| const Animation* Objects::getAnimation(const MWWorld::ConstPtr &ptr) const
 | |
| {
 | |
|     PtrAnimationMap::const_iterator iter = mObjects.find(ptr);
 | |
|     if(iter != mObjects.end())
 | |
|         return iter->second;
 | |
| 
 | |
|     return nullptr;
 | |
| }
 | |
| 
 | |
| }
 |