Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
4.6 kB · 130 lines
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131#include "clone.hpp"
#include <osg/StateSet>
#include <osgAnimation/MorphGeometry>#include <osgAnimation/RigGeometry>
#include <osgParticle/Emitter>#include <osgParticle/ParticleProcessor>#include <osgParticle/ParticleSystemUpdater>
#include <components/sceneutil/controller.hpp>#include <components/sceneutil/morphgeometry.hpp>#include <components/sceneutil/riggeometry.hpp>#include <components/sceneutil/riggeometryosgaextension.hpp>
namespace SceneUtil{
CopyOp::CopyOp() { setCopyFlags(osg::CopyOp::DEEP_COPY_NODES // Controller might need different inputs per scene instance | osg::CopyOp::DEEP_COPY_CALLBACKS | osg::CopyOp::DEEP_COPY_USERDATA); }
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 = new osgParticle::ParticleSystemUpdater(*updater, osg::CopyOp::SHALLOW_COPY); mUpdaterToOldPs[cloned] = updater->getParticleSystem(0); return cloned; }
osg::Node* cloned = osg::CopyOp::operator()(node); if (cloned) mClonedNodes[node] = cloned;
return cloned; }
osg::Callback* CopyOp::operator()(const osg::Callback* callback) const { osg::Callback* cloned = osg::CopyOp::operator()(callback); for (osg::Callback* cb = cloned; cb != nullptr; cb = cb->getNestedCallback()) { if (auto* ctrl = dynamic_cast<Controller*>(cb)) mControllersToRemap.push_back(ctrl); } return cloned; }
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 SceneUtil::RigGeometry*>(drawable) || dynamic_cast<const SceneUtil::MorphGeometry*>(drawable) || dynamic_cast<const osgAnimation::RigGeometry*>(drawable) || dynamic_cast<const osgAnimation::MorphGeometry*>(drawable) || dynamic_cast<const SceneUtil::RigGeometryHolder*>(drawable)) { return static_cast<osg::Drawable*>(drawable->clone(*this)); }
return osg::CopyOp::operator()(drawable); }
osgParticle::ParticleProcessor* CopyOp::operator()(const osgParticle::ParticleProcessor* processor) const { osgParticle::ParticleProcessor* cloned = static_cast<osgParticle::ParticleProcessor*>(processor->clone(osg::CopyOp::DEEP_COPY_CALLBACKS)); for (const auto& oldPsNewPsPair : mOldPsToNewPs) { if (processor->getParticleSystem() == oldPsNewPsPair.first) { cloned->setParticleSystem(oldPsNewPsPair.second); return cloned; } }
mProcessorToOldPs[cloned] = processor->getParticleSystem(); return cloned; }
osgParticle::ParticleSystem* CopyOp::operator()(const osgParticle::ParticleSystem* partsys) const { osgParticle::ParticleSystem* cloned = static_cast<osgParticle::ParticleSystem*>(partsys->clone(*this));
for (const auto& processorPsPair : mProcessorToOldPs) { if (processorPsPair.second == partsys) { processorPsPair.first->setParticleSystem(cloned); } } for (const auto& updaterPsPair : mUpdaterToOldPs) { if (updaterPsPair.second == partsys) { osgParticle::ParticleSystemUpdater* updater = updaterPsPair.first; updater->removeParticleSystem(updater->getParticleSystem(0)); updater->addParticleSystem(cloned); } } // In rare situations a particle processor may be placed after the particle system in the scene graph. mOldPsToNewPs[partsys] = cloned;
return cloned; }
osg::Node* CopyOp::getClonedNode(const osg::Node* original) const { auto it = mClonedNodes.find(original); return it != mClonedNodes.end() ? it->second : nullptr; }
void CopyOp::remapControllerTargets() const { for (Controller* ctrl : mControllersToRemap) ctrl->remapTargets(*this); }
}