forked from teamnwah/openmw-tes3coop
Add SceneManager and clone utility
parent
60f288195f
commit
99e1720980
@ -0,0 +1,24 @@
|
||||
#include "resourcesystem.hpp"
|
||||
|
||||
#include "scenemanager.hpp"
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
|
||||
ResourceSystem::ResourceSystem(const VFS::Manager *vfs)
|
||||
: mVFS(vfs)
|
||||
{
|
||||
mSceneManager.reset(new SceneManager(vfs));
|
||||
}
|
||||
|
||||
SceneManager* ResourceSystem::getSceneManager()
|
||||
{
|
||||
return mSceneManager.get();
|
||||
}
|
||||
|
||||
const VFS::Manager* ResourceSystem::getVFS() const
|
||||
{
|
||||
return mVFS;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
#ifndef OPENMW_COMPONENTS_RESOURCE_RESOURCESYSTEM_H
|
||||
#define OPENMW_COMPONENTS_RESOURCE_RESOURCESYSTEM_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
class Manager;
|
||||
}
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
|
||||
class SceneManager;
|
||||
|
||||
/// @brief Wrapper class that constructs and provides access to the various resource subsystems.
|
||||
class ResourceSystem
|
||||
{
|
||||
public:
|
||||
ResourceSystem(const VFS::Manager* vfs);
|
||||
|
||||
SceneManager* getSceneManager();
|
||||
|
||||
const VFS::Manager* getVFS() const;
|
||||
|
||||
private:
|
||||
std::auto_ptr<SceneManager> mSceneManager;
|
||||
|
||||
const VFS::Manager* mVFS;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,49 @@
|
||||
#include "scenemanager.hpp"
|
||||
|
||||
#include <osg/Node>
|
||||
|
||||
#include <components/nifosg/nifloader.hpp>
|
||||
#include <components/nif/niffile.hpp>
|
||||
|
||||
#include <components/sceneutil/clone.hpp>
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
|
||||
SceneManager::SceneManager(const VFS::Manager *vfs)
|
||||
: mVFS(vfs)
|
||||
{
|
||||
}
|
||||
|
||||
osg::ref_ptr<const osg::Node> SceneManager::getTemplate(const std::string &name)
|
||||
{
|
||||
std::string normalized = name;
|
||||
mVFS->normalizeFilename(normalized);
|
||||
|
||||
Index::iterator it = mIndex.find(normalized);
|
||||
if (it == mIndex.end())
|
||||
{
|
||||
Files::IStreamPtr file = mVFS->get(normalized);
|
||||
|
||||
// TODO: add support for non-NIF formats
|
||||
|
||||
NifOsg::Loader loader;
|
||||
loader.resourceManager = mVFS;
|
||||
osg::ref_ptr<const osg::Node> loaded = loader.load(Nif::NIFFilePtr(new Nif::NIFFile(file, normalized)));
|
||||
|
||||
// TODO: provide way for the user to get textKeys (attach to the node?)
|
||||
|
||||
mIndex[normalized] = loaded;
|
||||
return loaded;
|
||||
}
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> SceneManager::getInstance(const std::string &name)
|
||||
{
|
||||
osg::ref_ptr<const osg::Node> scene = getTemplate(name);
|
||||
return osg::clone(scene.get(), SceneUtil::CopyOp());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
#ifndef OPENMW_COMPONENTS_RESOURCE_SCENEMANAGER_H
|
||||
#define OPENMW_COMPONENTS_RESOURCE_SCENEMANAGER_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Node>
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
class Manager;
|
||||
}
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
|
||||
/// @brief Handles loading and caching of scenes, e.g. NIF files
|
||||
class SceneManager
|
||||
{
|
||||
public:
|
||||
SceneManager(const VFS::Manager* vfs);
|
||||
|
||||
/// Get a read-only copy of this scene "template"
|
||||
osg::ref_ptr<const osg::Node> getTemplate(const std::string& name);
|
||||
|
||||
/// Create an instance of the given scene template
|
||||
osg::ref_ptr<osg::Node> getInstance(const std::string& name);
|
||||
|
||||
private:
|
||||
const VFS::Manager* mVFS;
|
||||
|
||||
// observer_ptr?
|
||||
typedef std::map<std::string, osg::ref_ptr<const osg::Node> > Index;
|
||||
Index mIndex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,85 @@
|
||||
#include "clone.hpp"
|
||||
|
||||
#include <osg/StateSet>
|
||||
|
||||
#include <osgParticle/ParticleProcessor>
|
||||
#include <osgParticle/ParticleSystemUpdater>
|
||||
#include <osgParticle/Emitter>
|
||||
#include <osgParticle/Program>
|
||||
#include <osgAnimation/RigGeometry>
|
||||
#include <osgAnimation/MorphGeometry>
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
|
||||
CopyOp::CopyOp()
|
||||
{
|
||||
setCopyFlags(osg::CopyOp::DEEP_COPY_NODES
|
||||
// Controller might need different inputs per scene instance
|
||||
| osg::CopyOp::DEEP_COPY_CALLBACKS);
|
||||
}
|
||||
|
||||
osg::StateSet* CopyOp::operator ()(const osg::StateSet* stateset) const
|
||||
{
|
||||
if (!stateset)
|
||||
return NULL;
|
||||
if (stateset->getDataVariance() == osg::StateSet::DYNAMIC)
|
||||
return osg::clone(stateset, osg::CopyOp::DEEP_COPY_STATESETS);
|
||||
return const_cast<osg::StateSet*>(stateset);
|
||||
}
|
||||
|
||||
osg::Node* CopyOp::operator ()(const osg::Node* node) const
|
||||
{
|
||||
if (const osgParticle::ParticleProcessor* processor = dynamic_cast<const osgParticle::ParticleProcessor*>(node))
|
||||
return operator()(processor);
|
||||
if (const osgParticle::ParticleSystemUpdater* updater = dynamic_cast<const osgParticle::ParticleSystemUpdater*>(node))
|
||||
{
|
||||
osgParticle::ParticleSystemUpdater* cloned = osg::clone(updater, osg::CopyOp::DEEP_COPY_NODES);
|
||||
mMap2[cloned] = updater->getParticleSystem(0);
|
||||
return cloned;
|
||||
}
|
||||
return osg::CopyOp::operator()(node);
|
||||
}
|
||||
|
||||
osg::Drawable* CopyOp::operator ()(const osg::Drawable* drawable) const
|
||||
{
|
||||
if (const osgParticle::ParticleSystem* partsys = dynamic_cast<const osgParticle::ParticleSystem*>(drawable))
|
||||
return operator()(partsys);
|
||||
if (dynamic_cast<const osgAnimation::RigGeometry*>(drawable)
|
||||
|| dynamic_cast<const osgAnimation::MorphGeometry*>(drawable))
|
||||
return osg::clone(drawable, osg::CopyOp::DEEP_COPY_DRAWABLES);
|
||||
|
||||
return osg::CopyOp::operator()(drawable);
|
||||
}
|
||||
|
||||
osgParticle::ParticleProcessor* CopyOp::operator() (const osgParticle::ParticleProcessor* processor) const
|
||||
{
|
||||
osgParticle::ParticleProcessor* cloned = osg::clone(processor, osg::CopyOp::DEEP_COPY_NODES);
|
||||
mMap[cloned] = processor->getParticleSystem();
|
||||
return cloned;
|
||||
}
|
||||
|
||||
osgParticle::ParticleSystem* CopyOp::operator ()(const osgParticle::ParticleSystem* partsys) const
|
||||
{
|
||||
osgParticle::ParticleSystem* cloned = osg::clone(partsys, osg::CopyOp::DEEP_COPY_DRAWABLES);
|
||||
|
||||
for (std::map<osgParticle::ParticleProcessor*, const osgParticle::ParticleSystem*>::const_iterator it = mMap.begin(); it != mMap.end(); ++it)
|
||||
{
|
||||
if (it->second == partsys)
|
||||
{
|
||||
it->first->setParticleSystem(cloned);
|
||||
}
|
||||
}
|
||||
for (std::map<osgParticle::ParticleSystemUpdater*, const osgParticle::ParticleSystem*>::const_iterator it = mMap2.begin(); it != mMap2.end(); ++it)
|
||||
{
|
||||
if (it->second == partsys)
|
||||
{
|
||||
osgParticle::ParticleSystemUpdater* updater = it->first;
|
||||
updater->removeParticleSystem(updater->getParticleSystem(0));
|
||||
updater->addParticleSystem(cloned);
|
||||
}
|
||||
}
|
||||
return cloned;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
#ifndef OPENMW_COMPONENTS_SCENEUTIL_CLONE_H
|
||||
#define OPENMW_COMPONENTS_SCENEUTIL_CLONE_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <osg/CopyOp>
|
||||
|
||||
namespace osgParticle
|
||||
{
|
||||
class ParticleProcessor;
|
||||
class ParticleSystem;
|
||||
class ParticleSystemUpdater;
|
||||
}
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
|
||||
/// @par Defines the cloning behaviour we need:
|
||||
/// * Assigns updated ParticleSystem pointers on cloned emitters and programs.
|
||||
/// * Creates deep copy of StateSets if they have a DYNAMIC data variance.
|
||||
/// * Deep copies RigGeometry and MorphGeometry so they can animate without affecting clones.
|
||||
/// @warning Do not use an object of this class for more than one copy operation.
|
||||
class CopyOp : public osg::CopyOp
|
||||
{
|
||||
public:
|
||||
CopyOp();
|
||||
|
||||
virtual osgParticle::ParticleSystem* operator() (const osgParticle::ParticleSystem* partsys) const;
|
||||
virtual osgParticle::ParticleProcessor* operator() (const osgParticle::ParticleProcessor* processor) const;
|
||||
|
||||
virtual osg::Node* operator() (const osg::Node* node) const;
|
||||
virtual osg::Drawable* operator() (const osg::Drawable* drawable) const;
|
||||
|
||||
virtual osg::StateSet* operator() (const osg::StateSet* stateset) const;
|
||||
|
||||
private:
|
||||
// maps new ParticleProcessor to their old ParticleSystem pointer
|
||||
// a little messy, but I think this should be the most efficient way
|
||||
mutable std::map<osgParticle::ParticleProcessor*, const osgParticle::ParticleSystem*> mMap;
|
||||
mutable std::map<osgParticle::ParticleSystemUpdater*, const osgParticle::ParticleSystem*> mMap2;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue