2011-10-31 23:59:16 -04:00
|
|
|
#include "objects.hpp"
|
2012-02-06 10:41:13 +01:00
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
#include <osg/Group>
|
2015-05-24 03:36:34 +02:00
|
|
|
#include <osg/UserDataContainer>
|
2012-02-06 10:41:13 +01:00
|
|
|
|
2015-11-20 21:57:04 +01:00
|
|
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
2022-07-24 20:55:03 +02:00
|
|
|
#include <components/sceneutil/unrefqueue.hpp>
|
2012-07-03 13:55:53 +02:00
|
|
|
|
|
|
|
#include "../mwworld/ptr.hpp"
|
2012-07-30 23:28:14 +04:00
|
|
|
#include "../mwworld/class.hpp"
|
2012-07-03 13:55:53 +02:00
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
#include "animation.hpp"
|
2015-04-15 22:11:38 +02:00
|
|
|
#include "npcanimation.hpp"
|
2015-04-19 03:05:47 +02:00
|
|
|
#include "creatureanimation.hpp"
|
2020-04-20 18:47:14 +02:00
|
|
|
#include "vismask.hpp"
|
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
|
|
|
|
namespace MWRender
|
|
|
|
{
|
|
|
|
|
2022-07-24 20:55:03 +02:00
|
|
|
Objects::Objects(Resource::ResourceSystem* resourceSystem, const osg::ref_ptr<osg::Group>& rootNode,
|
|
|
|
SceneUtil::UnrefQueue& unrefQueue)
|
2015-05-23 22:44:00 +02:00
|
|
|
: mRootNode(rootNode)
|
|
|
|
, mResourceSystem(resourceSystem)
|
2022-07-24 20:55:03 +02:00
|
|
|
, mUnrefQueue(unrefQueue)
|
2012-02-06 10:41:13 +01:00
|
|
|
{
|
2015-04-12 15:34:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Objects::~Objects()
|
|
|
|
{
|
|
|
|
mObjects.clear();
|
|
|
|
|
|
|
|
for (CellMap::iterator iter = mCellSceneNodes.begin(); iter != mCellSceneNodes.end(); ++iter)
|
|
|
|
iter->second->getParent(0)->removeChild(iter->second);
|
|
|
|
mCellSceneNodes.clear();
|
2011-11-17 17:10:27 -05:00
|
|
|
}
|
2012-02-06 10:41:13 +01:00
|
|
|
|
2013-08-07 03:51:57 -07:00
|
|
|
void Objects::insertBegin(const MWWorld::Ptr& ptr)
|
2012-02-06 10:41:13 +01:00
|
|
|
{
|
2022-05-20 23:07:50 +02:00
|
|
|
assert(mObjects.find(ptr.mRef) == mObjects.end());
|
2017-06-28 22:40:13 +02:00
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
osg::ref_ptr<osg::Group> cellnode;
|
|
|
|
|
|
|
|
CellMap::iterator found = mCellSceneNodes.find(ptr.getCell());
|
|
|
|
if (found == mCellSceneNodes.end())
|
2011-11-04 21:57:39 -04:00
|
|
|
{
|
2015-04-12 15:34:50 +02:00
|
|
|
cellnode = new osg::Group;
|
2017-02-02 21:46:25 +01:00
|
|
|
cellnode->setName("Cell Root");
|
2015-04-12 15:34:50 +02:00
|
|
|
mRootNode->addChild(cellnode);
|
2011-11-04 21:57:39 -04:00
|
|
|
mCellSceneNodes[ptr.getCell()] = cellnode;
|
2011-11-21 12:52:28 +01:00
|
|
|
}
|
|
|
|
else
|
2015-04-12 15:34:50 +02:00
|
|
|
cellnode = found->second;
|
2011-11-04 21:48:52 -04:00
|
|
|
|
2015-11-20 21:57:04 +01:00
|
|
|
osg::ref_ptr<SceneUtil::PositionAttitudeTransform> insert (new SceneUtil::PositionAttitudeTransform);
|
2015-04-12 15:34:50 +02:00
|
|
|
cellnode->addChild(insert);
|
2012-03-24 22:03:08 -04:00
|
|
|
|
2015-05-24 03:36:34 +02:00
|
|
|
insert->getOrCreateUserDataContainer()->addUserObject(new PtrHolder(ptr));
|
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
const float *f = ptr.getRefData().getPosition().pos;
|
2012-06-29 16:48:50 +02:00
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
insert->setPosition(osg::Vec3(f[0], f[1], f[2]));
|
2012-02-06 10:29:18 +01:00
|
|
|
|
2015-11-19 15:57:12 +01:00
|
|
|
const float scale = ptr.getCellRef().getScale();
|
|
|
|
osg::Vec3f scaleVec(scale, scale, scale);
|
|
|
|
ptr.getClass().adjustScale(ptr, scaleVec, true);
|
|
|
|
insert->setScale(scaleVec);
|
|
|
|
|
2011-11-02 22:41:48 -04:00
|
|
|
ptr.getRefData().setBaseNode(insert);
|
2011-10-31 23:59:16 -04:00
|
|
|
}
|
2012-02-06 10:41:13 +01:00
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh, bool animated, bool allowLight)
|
2012-02-06 10:41:13 +01:00
|
|
|
{
|
2013-08-07 03:51:57 -07:00
|
|
|
insertBegin(ptr);
|
2020-04-20 18:47:14 +02:00
|
|
|
ptr.getRefData().getBaseNode()->setNodeMask(Mask_Object);
|
2013-02-28 22:56:29 +01:00
|
|
|
|
2017-02-22 15:22:40 +01:00
|
|
|
osg::ref_ptr<ObjectAnimation> anim (new ObjectAnimation(ptr, mesh, mResourceSystem, animated, allowLight));
|
2015-04-12 15:34:50 +02:00
|
|
|
|
2022-05-20 23:07:50 +02:00
|
|
|
mObjects.emplace(ptr.mRef, std::move(anim));
|
2015-04-12 15:34:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Objects::insertCreature(const MWWorld::Ptr &ptr, const std::string &mesh, bool weaponsShields)
|
|
|
|
{
|
|
|
|
insertBegin(ptr);
|
2020-04-20 18:47:14 +02:00
|
|
|
ptr.getRefData().getBaseNode()->setNodeMask(Mask_Actor);
|
2015-04-12 15:34:50 +02:00
|
|
|
|
|
|
|
// CreatureAnimation
|
2017-02-22 15:22:40 +01:00
|
|
|
osg::ref_ptr<Animation> anim;
|
2015-04-19 03:05:47 +02:00
|
|
|
|
|
|
|
if (weaponsShields)
|
2017-02-22 15:22:40 +01:00
|
|
|
anim = new CreatureWeaponAnimation(ptr, mesh, mResourceSystem);
|
2015-04-19 03:05:47 +02:00
|
|
|
else
|
2017-02-22 15:22:40 +01:00
|
|
|
anim = new CreatureAnimation(ptr, mesh, mResourceSystem);
|
2015-04-19 03:05:47 +02:00
|
|
|
|
2022-05-20 23:07:50 +02:00
|
|
|
if (mObjects.emplace(ptr.mRef, anim).second)
|
2017-06-28 22:40:13 +02:00
|
|
|
ptr.getClass().getContainerStore(ptr).setContListener(static_cast<ActorAnimation*>(anim.get()));
|
2015-04-12 15:34:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Objects::insertNPC(const MWWorld::Ptr &ptr)
|
|
|
|
{
|
2015-04-15 22:11:38 +02:00
|
|
|
insertBegin(ptr);
|
2020-04-20 18:47:14 +02:00
|
|
|
ptr.getRefData().getBaseNode()->setNodeMask(Mask_Actor);
|
2015-04-12 15:34:50 +02:00
|
|
|
|
2017-02-22 15:22:40 +01:00
|
|
|
osg::ref_ptr<NpcAnimation> anim (new NpcAnimation(ptr, osg::ref_ptr<osg::Group>(ptr.getRefData().getBaseNode()), mResourceSystem));
|
2015-04-19 15:03:08 +02:00
|
|
|
|
2022-05-20 23:07:50 +02:00
|
|
|
if (mObjects.emplace(ptr.mRef, anim).second)
|
2017-06-28 22:40:13 +02:00
|
|
|
{
|
|
|
|
ptr.getClass().getInventoryStore(ptr).setInvListener(anim.get(), ptr);
|
|
|
|
ptr.getClass().getInventoryStore(ptr).setContListener(anim.get());
|
|
|
|
}
|
2011-10-31 23:59:16 -04:00
|
|
|
}
|
2012-02-06 10:41:13 +01:00
|
|
|
|
2015-05-22 00:55:43 +02:00
|
|
|
bool Objects::removeObject (const MWWorld::Ptr& ptr)
|
2012-02-06 10:41:13 +01:00
|
|
|
{
|
2013-08-06 19:45:07 -07:00
|
|
|
if(!ptr.getRefData().getBaseNode())
|
|
|
|
return true;
|
2012-04-28 20:42:53 +02:00
|
|
|
|
2022-05-20 23:07:50 +02:00
|
|
|
const auto iter = mObjects.find(ptr.mRef);
|
2013-08-06 19:45:07 -07:00
|
|
|
if(iter != mObjects.end())
|
2012-02-06 10:41:13 +01:00
|
|
|
{
|
2022-07-23 18:30:28 +02:00
|
|
|
iter->second->removeFromScene();
|
2022-07-24 20:55:03 +02:00
|
|
|
mUnrefQueue.push(std::move(iter->second));
|
2013-08-06 19:45:07 -07:00
|
|
|
mObjects.erase(iter);
|
2012-02-06 10:41:13 +01:00
|
|
|
|
2018-06-05 18:09:10 +03:00
|
|
|
if (ptr.getClass().isActor())
|
2017-02-22 14:54:40 +01:00
|
|
|
{
|
2018-06-05 18:09:10 +03:00
|
|
|
if (ptr.getClass().hasInventoryStore(ptr))
|
2018-10-09 10:21:12 +04:00
|
|
|
ptr.getClass().getInventoryStore(ptr).setInvListener(nullptr, ptr);
|
2018-06-05 18:09:10 +03:00
|
|
|
|
2018-10-09 10:21:12 +04:00
|
|
|
ptr.getClass().getContainerStore(ptr).setContListener(nullptr);
|
2017-02-22 14:54:40 +01:00
|
|
|
}
|
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
ptr.getRefData().getBaseNode()->getParent(0)->removeChild(ptr.getRefData().getBaseNode());
|
2016-02-09 15:30:53 +01:00
|
|
|
|
2018-10-09 10:21:12 +04:00
|
|
|
ptr.getRefData().setBaseNode(nullptr);
|
2013-08-06 19:45:07 -07:00
|
|
|
return true;
|
2013-02-24 19:00:06 +01:00
|
|
|
}
|
2013-08-06 19:45:07 -07:00
|
|
|
return false;
|
2011-10-31 23:59:16 -04:00
|
|
|
}
|
2011-11-02 00:13:33 -04:00
|
|
|
|
2011-11-04 21:48:52 -04:00
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
void Objects::removeCell(const MWWorld::CellStore* store)
|
2012-02-06 10:41:13 +01:00
|
|
|
{
|
2013-08-06 19:45:07 -07:00
|
|
|
for(PtrAnimationMap::iterator iter = mObjects.begin();iter != mObjects.end();)
|
2011-11-04 21:48:52 -04:00
|
|
|
{
|
2017-02-22 14:54:40 +01:00
|
|
|
MWWorld::Ptr ptr = iter->second->getPtr();
|
|
|
|
if(ptr.getCell() == store)
|
2013-08-06 19:45:07 -07:00
|
|
|
{
|
2021-11-15 16:31:38 +01:00
|
|
|
if (ptr.getClass().isActor() && ptr.getRefData().getCustomData())
|
2017-02-22 14:54:40 +01:00
|
|
|
{
|
2021-11-15 16:31:38 +01:00
|
|
|
if (ptr.getClass().hasInventoryStore(ptr))
|
|
|
|
ptr.getClass().getInventoryStore(ptr).setInvListener(nullptr, ptr);
|
|
|
|
ptr.getClass().getContainerStore(ptr).setContListener(nullptr);
|
2017-02-22 14:54:40 +01:00
|
|
|
}
|
|
|
|
|
2022-07-23 18:30:28 +02:00
|
|
|
iter->second->removeFromScene();
|
2022-07-24 20:55:03 +02:00
|
|
|
mUnrefQueue.push(std::move(iter->second));
|
2022-07-23 18:30:28 +02:00
|
|
|
iter = mObjects.erase(iter);
|
2013-08-06 19:45:07 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
++iter;
|
2011-11-04 21:48:52 -04:00
|
|
|
}
|
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
CellMap::iterator cell = mCellSceneNodes.find(store);
|
2013-08-06 19:45:07 -07:00
|
|
|
if(cell != mCellSceneNodes.end())
|
|
|
|
{
|
2015-04-12 15:34:50 +02:00
|
|
|
cell->second->getParent(0)->removeChild(cell->second);
|
2013-08-06 19:45:07 -07:00
|
|
|
mCellSceneNodes.erase(cell);
|
|
|
|
}
|
2012-03-10 15:28:18 +01:00
|
|
|
}
|
2012-04-02 19:37:24 +02:00
|
|
|
|
2015-05-14 17:34:55 +02:00
|
|
|
void Objects::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &cur)
|
2012-07-30 23:28:14 +04:00
|
|
|
{
|
2022-03-26 15:16:22 +00:00
|
|
|
osg::ref_ptr<osg::Node> objectNode = cur.getRefData().getBaseNode();
|
2015-05-26 16:40:44 +02:00
|
|
|
if (!objectNode)
|
|
|
|
return;
|
|
|
|
|
2013-02-24 14:59:21 +04:00
|
|
|
MWWorld::CellStore *newCell = cur.getCell();
|
2012-07-30 23:28:14 +04:00
|
|
|
|
2015-05-14 17:34:55 +02:00
|
|
|
osg::Group* cellnode;
|
2012-07-30 23:28:14 +04:00
|
|
|
if(mCellSceneNodes.find(newCell) == mCellSceneNodes.end()) {
|
2015-05-14 17:34:55 +02:00
|
|
|
cellnode = new osg::Group;
|
|
|
|
mRootNode->addChild(cellnode);
|
|
|
|
mCellSceneNodes[newCell] = cellnode;
|
2012-07-30 23:28:14 +04:00
|
|
|
} else {
|
2015-05-14 17:34:55 +02:00
|
|
|
cellnode = mCellSceneNodes[newCell];
|
2012-07-30 23:28:14 +04:00
|
|
|
}
|
2013-11-27 18:46:18 +01:00
|
|
|
|
2015-05-24 03:36:34 +02:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2015-05-14 17:34:55 +02:00
|
|
|
if (objectNode->getNumParents())
|
|
|
|
objectNode->getParent(0)->removeChild(objectNode);
|
|
|
|
cellnode->addChild(objectNode);
|
2013-11-27 18:46:18 +01:00
|
|
|
|
2022-05-20 23:07:50 +02:00
|
|
|
PtrAnimationMap::iterator iter = mObjects.find(old.mRef);
|
2013-11-27 18:46:18 +01:00
|
|
|
if(iter != mObjects.end())
|
2022-05-20 23:07:50 +02:00
|
|
|
iter->second->updatePtr(cur);
|
2012-07-30 23:28:14 +04:00
|
|
|
}
|
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
Animation* Objects::getAnimation(const MWWorld::Ptr &ptr)
|
2013-11-17 23:15:57 +01:00
|
|
|
{
|
2022-05-20 23:07:50 +02:00
|
|
|
PtrAnimationMap::const_iterator iter = mObjects.find(ptr.mRef);
|
2013-11-17 23:15:57 +01:00
|
|
|
if(iter != mObjects.end())
|
|
|
|
return iter->second;
|
2015-04-12 15:34:50 +02:00
|
|
|
|
2018-10-09 10:21:12 +04:00
|
|
|
return nullptr;
|
2012-07-30 23:28:14 +04:00
|
|
|
}
|
|
|
|
|
2015-12-18 17:21:51 +01:00
|
|
|
const Animation* Objects::getAnimation(const MWWorld::ConstPtr &ptr) const
|
|
|
|
{
|
2022-05-20 23:07:50 +02:00
|
|
|
PtrAnimationMap::const_iterator iter = mObjects.find(ptr.mRef);
|
2015-12-18 17:21:51 +01:00
|
|
|
if(iter != mObjects.end())
|
|
|
|
return iter->second;
|
|
|
|
|
2018-10-09 10:21:12 +04:00
|
|
|
return nullptr;
|
2015-12-18 17:21:51 +01:00
|
|
|
}
|
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
}
|