mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 15:56:42 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			153 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "visitor.hpp"
 | 
						|
 | 
						|
#include <osg/Drawable>
 | 
						|
#include <osg/MatrixTransform>
 | 
						|
 | 
						|
#include <osgParticle/ParticleSystem>
 | 
						|
 | 
						|
#include <osgAnimation/Bone>
 | 
						|
 | 
						|
#include <components/debug/debuglog.hpp>
 | 
						|
#include <components/misc/strings/algorithm.hpp>
 | 
						|
 | 
						|
#include <cstring>
 | 
						|
#include <string_view>
 | 
						|
 | 
						|
namespace SceneUtil
 | 
						|
{
 | 
						|
    bool FindByNameVisitor::checkGroup(osg::Group& group)
 | 
						|
    {
 | 
						|
        if (Misc::StringUtils::ciEqual(group.getName(), mNameToFind))
 | 
						|
        {
 | 
						|
            mFoundNode = &group;
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    void FindByClassVisitor::apply(osg::Node& node)
 | 
						|
    {
 | 
						|
        if (Misc::StringUtils::ciEqual(node.className(), mNameToFind))
 | 
						|
            mFoundNodes.push_back(&node);
 | 
						|
 | 
						|
        traverse(node);
 | 
						|
    }
 | 
						|
 | 
						|
    void FindByNameVisitor::apply(osg::Group& group)
 | 
						|
    {
 | 
						|
        if (!mFoundNode && !checkGroup(group))
 | 
						|
            traverse(group);
 | 
						|
    }
 | 
						|
 | 
						|
    void FindByNameVisitor::apply(osg::MatrixTransform& node)
 | 
						|
    {
 | 
						|
        if (!mFoundNode && !checkGroup(node))
 | 
						|
            traverse(node);
 | 
						|
    }
 | 
						|
 | 
						|
    void FindByNameVisitor::apply(osg::Geometry&) {}
 | 
						|
 | 
						|
    void NodeMapVisitorBoneOnly::apply(osg::MatrixTransform& trans)
 | 
						|
    {
 | 
						|
        // Choose first found bone in file
 | 
						|
        if (dynamic_cast<osgAnimation::Bone*>(&trans) != nullptr)
 | 
						|
            mMap.emplace(trans.getName(), &trans);
 | 
						|
 | 
						|
        traverse(trans);
 | 
						|
    }
 | 
						|
 | 
						|
    void NodeMapVisitor::apply(osg::MatrixTransform& trans)
 | 
						|
    {
 | 
						|
        // Choose first found node in file
 | 
						|
        mMap.emplace(trans.getName(), &trans);
 | 
						|
        traverse(trans);
 | 
						|
    }
 | 
						|
 | 
						|
    void RemoveVisitor::remove()
 | 
						|
    {
 | 
						|
        for (RemoveVec::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
 | 
						|
        {
 | 
						|
            if (!it->second->removeChild(it->first))
 | 
						|
                Log(Debug::Error) << "error removing " << it->first->getName();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void CleanObjectRootVisitor::apply(osg::Drawable& drw)
 | 
						|
    {
 | 
						|
        applyDrawable(drw);
 | 
						|
    }
 | 
						|
 | 
						|
    void CleanObjectRootVisitor::apply(osg::Group& node)
 | 
						|
    {
 | 
						|
        applyNode(node);
 | 
						|
    }
 | 
						|
 | 
						|
    void CleanObjectRootVisitor::apply(osg::MatrixTransform& node)
 | 
						|
    {
 | 
						|
        applyNode(node);
 | 
						|
    }
 | 
						|
 | 
						|
    void CleanObjectRootVisitor::apply(osg::Node& node)
 | 
						|
    {
 | 
						|
        applyNode(node);
 | 
						|
    }
 | 
						|
 | 
						|
    void CleanObjectRootVisitor::applyNode(osg::Node& node)
 | 
						|
    {
 | 
						|
        if (node.getStateSet())
 | 
						|
            node.setStateSet(nullptr);
 | 
						|
 | 
						|
        if (node.getNodeMask() == 0x1 && node.getNumParents() == 1)
 | 
						|
            mToRemove.emplace_back(&node, node.getParent(0));
 | 
						|
        else
 | 
						|
            traverse(node);
 | 
						|
    }
 | 
						|
 | 
						|
    void CleanObjectRootVisitor::applyDrawable(osg::Node& node)
 | 
						|
    {
 | 
						|
        osg::NodePath::iterator parent = getNodePath().end() - 2;
 | 
						|
        // We know that the parent is a Group because only Groups can have children.
 | 
						|
        osg::Group* parentGroup = static_cast<osg::Group*>(*parent);
 | 
						|
 | 
						|
        // Try to prune nodes that would be empty after the removal
 | 
						|
        if (parent != getNodePath().begin())
 | 
						|
        {
 | 
						|
            // This could be extended to remove the parent's parent, and so on if they are empty as well.
 | 
						|
            // But for NIF files, there won't be a benefit since only TriShapes can be set to STATIC dataVariance.
 | 
						|
            osg::Group* parentParent = static_cast<osg::Group*>(*(parent - 1));
 | 
						|
            if (parentGroup->getNumChildren() == 1 && parentGroup->getDataVariance() == osg::Object::STATIC)
 | 
						|
            {
 | 
						|
                mToRemove.emplace_back(parentGroup, parentParent);
 | 
						|
                return;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        mToRemove.emplace_back(&node, parentGroup);
 | 
						|
    }
 | 
						|
 | 
						|
    void RemoveTriBipVisitor::apply(osg::Drawable& drw)
 | 
						|
    {
 | 
						|
        applyImpl(drw);
 | 
						|
    }
 | 
						|
 | 
						|
    void RemoveTriBipVisitor::apply(osg::Group& node)
 | 
						|
    {
 | 
						|
        traverse(node);
 | 
						|
    }
 | 
						|
 | 
						|
    void RemoveTriBipVisitor::apply(osg::MatrixTransform& node)
 | 
						|
    {
 | 
						|
        traverse(node);
 | 
						|
    }
 | 
						|
 | 
						|
    void RemoveTriBipVisitor::applyImpl(osg::Node& node)
 | 
						|
    {
 | 
						|
        if (Misc::StringUtils::ciStartsWith(node.getName(), "tri bip"))
 | 
						|
        {
 | 
						|
            osg::Group* parent = static_cast<osg::Group*>(*(getNodePath().end() - 2));
 | 
						|
            // Not safe to remove in apply(), since the visitor is still iterating the child list
 | 
						|
            mToRemove.emplace_back(&node, parent);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |