2011-11-01 03:59:16 +00:00
|
|
|
#include "objects.hpp"
|
2012-02-06 09:41:13 +00:00
|
|
|
|
2013-03-29 08:04:02 +00:00
|
|
|
#include <cmath>
|
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
#include <osg/Group>
|
|
|
|
#include <osg/Geode>
|
|
|
|
#include <osg/PositionAttitudeTransform>
|
2015-05-24 01:36:34 +00:00
|
|
|
#include <osg/UserDataContainer>
|
2012-02-06 09:41:13 +00:00
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
#include <osgParticle/ParticleSystem>
|
|
|
|
#include <osgParticle/ParticleProcessor>
|
2014-02-23 19:11:05 +00:00
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
#include <components/resource/scenemanager.hpp>
|
|
|
|
|
|
|
|
#include <components/sceneutil/visitor.hpp>
|
2012-07-03 11:55:53 +00:00
|
|
|
|
|
|
|
#include "../mwworld/ptr.hpp"
|
2012-07-30 19:28:14 +00:00
|
|
|
#include "../mwworld/class.hpp"
|
2012-07-03 11:55:53 +00:00
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
#include "animation.hpp"
|
2015-04-15 20:11:38 +00:00
|
|
|
#include "npcanimation.hpp"
|
2015-04-19 01:05:47 +00:00
|
|
|
#include "creatureanimation.hpp"
|
2015-05-23 03:42:37 +00:00
|
|
|
#include "vismask.hpp"
|
2015-04-12 13:34:50 +00:00
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
|
|
|
|
/// Removes all particle systems and related nodes in a subgraph.
|
|
|
|
class RemoveParticlesVisitor : public osg::NodeVisitor
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
RemoveParticlesVisitor()
|
|
|
|
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual void apply(osg::Node &node)
|
|
|
|
{
|
2015-06-17 13:13:17 +00:00
|
|
|
if (dynamic_cast<osgParticle::ParticleProcessor*>(&node))
|
2015-04-12 13:34:50 +00:00
|
|
|
mToRemove.push_back(&node);
|
|
|
|
|
|
|
|
traverse(node);
|
|
|
|
}
|
2011-11-01 03:59:16 +00:00
|
|
|
|
2015-06-17 13:13:17 +00:00
|
|
|
virtual void apply(osg::Geode& geode)
|
|
|
|
{
|
|
|
|
std::vector<osgParticle::ParticleSystem*> partsysVector;
|
|
|
|
for (unsigned int i=0; i<geode.getNumDrawables(); ++i)
|
|
|
|
{
|
|
|
|
osg::Drawable* drw = geode.getDrawable(i);
|
|
|
|
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(drw))
|
|
|
|
partsysVector.push_back(partsys);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (std::vector<osgParticle::ParticleSystem*>::iterator it = partsysVector.begin(); it != partsysVector.end(); ++it)
|
|
|
|
geode.removeDrawable(*it);
|
|
|
|
}
|
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
void remove()
|
|
|
|
{
|
|
|
|
for (std::vector<osg::ref_ptr<osg::Node> >::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
|
|
|
{
|
|
|
|
osg::Node* node = *it;
|
|
|
|
if (node->getNumParents())
|
|
|
|
node->getParent(0)->removeChild(node);
|
|
|
|
}
|
|
|
|
mToRemove.clear();
|
|
|
|
}
|
2011-11-03 23:40:37 +00:00
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
private:
|
|
|
|
std::vector<osg::ref_ptr<osg::Node> > mToRemove;
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
2011-11-01 03:59:16 +00:00
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
|
|
|
|
namespace MWRender
|
|
|
|
{
|
|
|
|
|
|
|
|
Objects::Objects(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> rootNode)
|
2015-05-23 20:44:00 +00:00
|
|
|
: mRootNode(rootNode)
|
|
|
|
, mResourceSystem(resourceSystem)
|
2012-02-06 09:41:13 +00:00
|
|
|
{
|
2015-04-12 13:34:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Objects::~Objects()
|
|
|
|
{
|
|
|
|
for(PtrAnimationMap::iterator iter = mObjects.begin();iter != mObjects.end();++iter)
|
|
|
|
delete iter->second;
|
|
|
|
mObjects.clear();
|
|
|
|
|
|
|
|
for (CellMap::iterator iter = mCellSceneNodes.begin(); iter != mCellSceneNodes.end(); ++iter)
|
|
|
|
iter->second->getParent(0)->removeChild(iter->second);
|
|
|
|
mCellSceneNodes.clear();
|
2011-11-17 22:10:27 +00:00
|
|
|
}
|
2012-02-06 09:41:13 +00:00
|
|
|
|
2013-08-07 10:51:57 +00:00
|
|
|
void Objects::insertBegin(const MWWorld::Ptr& ptr)
|
2012-02-06 09:41:13 +00:00
|
|
|
{
|
2015-04-12 13:34:50 +00:00
|
|
|
osg::ref_ptr<osg::Group> cellnode;
|
|
|
|
|
|
|
|
CellMap::iterator found = mCellSceneNodes.find(ptr.getCell());
|
|
|
|
if (found == mCellSceneNodes.end())
|
2011-11-05 01:57:39 +00:00
|
|
|
{
|
2015-04-12 13:34:50 +00:00
|
|
|
cellnode = new osg::Group;
|
|
|
|
mRootNode->addChild(cellnode);
|
2011-11-05 01:57:39 +00:00
|
|
|
mCellSceneNodes[ptr.getCell()] = cellnode;
|
2011-11-21 11:52:28 +00:00
|
|
|
}
|
|
|
|
else
|
2015-04-12 13:34:50 +00:00
|
|
|
cellnode = found->second;
|
2011-11-05 01:48:52 +00:00
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
osg::ref_ptr<osg::PositionAttitudeTransform> insert (new osg::PositionAttitudeTransform);
|
|
|
|
cellnode->addChild(insert);
|
2012-03-25 02:03:08 +00:00
|
|
|
|
2015-05-24 01:36:34 +00:00
|
|
|
insert->getOrCreateUserDataContainer()->addUserObject(new PtrHolder(ptr));
|
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
const float *f = ptr.getRefData().getPosition().pos;
|
2012-06-29 14:48:50 +00:00
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
insert->setPosition(osg::Vec3(f[0], f[1], f[2]));
|
2012-02-06 09:29:18 +00:00
|
|
|
|
2011-11-03 02:41:48 +00:00
|
|
|
ptr.getRefData().setBaseNode(insert);
|
2011-11-01 03:59:16 +00:00
|
|
|
}
|
2012-02-06 09:41:13 +00:00
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh, bool animated, bool allowLight)
|
2012-02-06 09:41:13 +00:00
|
|
|
{
|
2013-08-07 10:51:57 +00:00
|
|
|
insertBegin(ptr);
|
2013-02-28 21:56:29 +00:00
|
|
|
|
2015-05-28 13:44:58 +00:00
|
|
|
std::auto_ptr<ObjectAnimation> anim (new ObjectAnimation(ptr, mesh, mResourceSystem, animated, allowLight));
|
2015-04-12 13:34:50 +00:00
|
|
|
|
|
|
|
if (!allowLight)
|
|
|
|
{
|
|
|
|
RemoveParticlesVisitor visitor;
|
|
|
|
anim->getObjectRoot()->accept(visitor);
|
|
|
|
visitor.remove();
|
2011-11-05 01:57:39 +00:00
|
|
|
}
|
2013-02-23 03:06:05 +00:00
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
mObjects.insert(std::make_pair(ptr, anim.release()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Objects::insertCreature(const MWWorld::Ptr &ptr, const std::string &mesh, bool weaponsShields)
|
|
|
|
{
|
|
|
|
insertBegin(ptr);
|
2015-05-23 03:42:37 +00:00
|
|
|
ptr.getRefData().getBaseNode()->setNodeMask(Mask_Actor);
|
2015-04-12 13:34:50 +00:00
|
|
|
|
|
|
|
// CreatureAnimation
|
2015-04-19 01:05:47 +00:00
|
|
|
std::auto_ptr<Animation> anim;
|
|
|
|
|
|
|
|
if (weaponsShields)
|
|
|
|
anim.reset(new CreatureWeaponAnimation(ptr, mesh, mResourceSystem));
|
|
|
|
else
|
|
|
|
anim.reset(new CreatureAnimation(ptr, mesh, mResourceSystem));
|
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
mObjects.insert(std::make_pair(ptr, anim.release()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Objects::insertNPC(const MWWorld::Ptr &ptr)
|
|
|
|
{
|
2015-04-15 20:11:38 +00:00
|
|
|
insertBegin(ptr);
|
2015-05-23 03:42:37 +00:00
|
|
|
ptr.getRefData().getBaseNode()->setNodeMask(Mask_Actor);
|
2015-04-12 13:34:50 +00:00
|
|
|
|
2015-06-22 19:14:44 +00:00
|
|
|
std::auto_ptr<NpcAnimation> anim (new NpcAnimation(ptr, osg::ref_ptr<osg::Group>(ptr.getRefData().getBaseNode()), mResourceSystem));
|
2015-04-19 13:03:08 +00:00
|
|
|
|
2015-04-15 20:11:38 +00:00
|
|
|
mObjects.insert(std::make_pair(ptr, anim.release()));
|
2011-11-01 03:59:16 +00:00
|
|
|
}
|
2012-02-06 09:41:13 +00:00
|
|
|
|
2015-05-21 22:55:43 +00:00
|
|
|
bool Objects::removeObject (const MWWorld::Ptr& ptr)
|
2012-02-06 09:41:13 +00:00
|
|
|
{
|
2013-08-07 02:45:07 +00:00
|
|
|
if(!ptr.getRefData().getBaseNode())
|
|
|
|
return true;
|
2012-04-28 18:42:53 +00:00
|
|
|
|
2013-08-07 02:45:07 +00:00
|
|
|
PtrAnimationMap::iterator iter = mObjects.find(ptr);
|
|
|
|
if(iter != mObjects.end())
|
2012-02-06 09:41:13 +00:00
|
|
|
{
|
2013-08-07 02:45:07 +00:00
|
|
|
delete iter->second;
|
|
|
|
mObjects.erase(iter);
|
2012-02-06 09:41:13 +00:00
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
ptr.getRefData().getBaseNode()->getParent(0)->removeChild(ptr.getRefData().getBaseNode());
|
|
|
|
ptr.getRefData().setBaseNode(NULL);
|
2013-08-07 02:45:07 +00:00
|
|
|
return true;
|
2013-02-24 18:00:06 +00:00
|
|
|
}
|
2013-08-07 02:45:07 +00:00
|
|
|
return false;
|
2011-11-01 03:59:16 +00:00
|
|
|
}
|
2011-11-02 04:13:33 +00:00
|
|
|
|
2011-11-05 01:48:52 +00:00
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
void Objects::removeCell(const MWWorld::CellStore* store)
|
2012-02-06 09:41:13 +00:00
|
|
|
{
|
2013-08-07 02:45:07 +00:00
|
|
|
for(PtrAnimationMap::iterator iter = mObjects.begin();iter != mObjects.end();)
|
2011-11-05 01:48:52 +00:00
|
|
|
{
|
2013-08-07 02:45:07 +00:00
|
|
|
if(iter->first.getCell() == store)
|
|
|
|
{
|
|
|
|
delete iter->second;
|
|
|
|
mObjects.erase(iter++);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
++iter;
|
2011-11-05 01:48:52 +00:00
|
|
|
}
|
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
CellMap::iterator cell = mCellSceneNodes.find(store);
|
2013-08-07 02:45:07 +00:00
|
|
|
if(cell != mCellSceneNodes.end())
|
|
|
|
{
|
2015-04-12 13:34:50 +00:00
|
|
|
cell->second->getParent(0)->removeChild(cell->second);
|
2013-08-07 02:45:07 +00:00
|
|
|
mCellSceneNodes.erase(cell);
|
|
|
|
}
|
2012-03-10 14:28:18 +00:00
|
|
|
}
|
2012-04-02 17:37:24 +00:00
|
|
|
|
2015-05-14 15:34:55 +00:00
|
|
|
void Objects::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &cur)
|
2012-07-30 19:28:14 +00:00
|
|
|
{
|
2015-05-26 14:40:44 +00:00
|
|
|
osg::Node* objectNode = cur.getRefData().getBaseNode();
|
|
|
|
if (!objectNode)
|
|
|
|
return;
|
|
|
|
|
2013-02-24 10:59:21 +00:00
|
|
|
MWWorld::CellStore *newCell = cur.getCell();
|
2012-07-30 19:28:14 +00:00
|
|
|
|
2015-05-14 15:34:55 +00:00
|
|
|
osg::Group* cellnode;
|
2012-07-30 19:28:14 +00:00
|
|
|
if(mCellSceneNodes.find(newCell) == mCellSceneNodes.end()) {
|
2015-05-14 15:34:55 +00:00
|
|
|
cellnode = new osg::Group;
|
|
|
|
mRootNode->addChild(cellnode);
|
|
|
|
mCellSceneNodes[newCell] = cellnode;
|
2012-07-30 19:28:14 +00:00
|
|
|
} else {
|
2015-05-14 15:34:55 +00:00
|
|
|
cellnode = mCellSceneNodes[newCell];
|
2012-07-30 19:28:14 +00:00
|
|
|
}
|
2013-11-27 17:46:18 +00:00
|
|
|
|
2015-05-24 01:36:34 +00: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 15:34:55 +00:00
|
|
|
if (objectNode->getNumParents())
|
|
|
|
objectNode->getParent(0)->removeChild(objectNode);
|
|
|
|
cellnode->addChild(objectNode);
|
2013-11-27 17:46:18 +00:00
|
|
|
|
|
|
|
PtrAnimationMap::iterator iter = mObjects.find(old);
|
|
|
|
if(iter != mObjects.end())
|
|
|
|
{
|
2015-05-14 15:34:55 +00:00
|
|
|
Animation *anim = iter->second;
|
2013-11-27 17:46:18 +00:00
|
|
|
mObjects.erase(iter);
|
|
|
|
anim->updatePtr(cur);
|
|
|
|
mObjects[cur] = anim;
|
|
|
|
}
|
2012-07-30 19:28:14 +00:00
|
|
|
}
|
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
Animation* Objects::getAnimation(const MWWorld::Ptr &ptr)
|
2013-11-17 22:15:57 +00:00
|
|
|
{
|
|
|
|
PtrAnimationMap::const_iterator iter = mObjects.find(ptr);
|
|
|
|
if(iter != mObjects.end())
|
|
|
|
return iter->second;
|
2015-04-12 13:34:50 +00:00
|
|
|
|
2013-11-17 22:15:57 +00:00
|
|
|
return NULL;
|
2012-07-30 19:28:14 +00:00
|
|
|
}
|
|
|
|
|
2015-04-12 13:34:50 +00:00
|
|
|
}
|