From 372bf08e79fc9fe47bc3e5fd5e2711ea0266139e Mon Sep 17 00:00:00 2001 From: Garux Date: Mon, 10 Feb 2025 22:51:45 +0500 Subject: [PATCH] * add bobToolz.explodeEntity: create group entity from each primitive of existing group entity closes #212 --- contrib/bobtoolz/bobToolz-GTK.cpp | 4 ++ contrib/bobtoolz/funchandlers-GTK.cpp | 64 +++++++++++++++++++++++++++ contrib/bobtoolz/funchandlers.h | 1 + docs/changelog-custom.txt | 1 + 4 files changed, 70 insertions(+) diff --git a/contrib/bobtoolz/bobToolz-GTK.cpp b/contrib/bobtoolz/bobToolz-GTK.cpp index 4f8d257e..fb0f032f 100644 --- a/contrib/bobtoolz/bobToolz-GTK.cpp +++ b/contrib/bobtoolz/bobToolz-GTK.cpp @@ -66,6 +66,7 @@ constexpr char PLUGIN_COMMANDS[] = "About...," "Polygon Builder," "Caulk Selection," "-," + "Explode Entity," "Tree Planter," "Drop Entity," "Plot Splines," @@ -163,6 +164,9 @@ extern "C" void QERPlug_Dispatch( const char *p, vec3_t vMin, vec3_t vMax, bool else if ( string_equal_nocase( p, "path plotter..." ) ) { DoPathPlotter(); } + else if ( string_equal_nocase( p, "explode entity" ) ) { + DoExplodeEntity(); + } else if ( string_equal_nocase( p, "about..." ) ) { DoMessageBox( PLUGIN_ABOUT, "About" ); } diff --git a/contrib/bobtoolz/funchandlers-GTK.cpp b/contrib/bobtoolz/funchandlers-GTK.cpp index 2125c9d8..d10e884d 100644 --- a/contrib/bobtoolz/funchandlers-GTK.cpp +++ b/contrib/bobtoolz/funchandlers-GTK.cpp @@ -865,5 +865,69 @@ void DoFlipTerrain() { Path_deleteTop( brushes[i]->path() ); delete newBrushes[i]; } +} + +class ExplodeWalker : public scene::Traversable::Walker +{ + scene::Node* m_entitynode; + scene::Cloneable* m_entitycloneable; + scene::Traversable* m_traversableroot; +public: + ExplodeWalker( scene::Node* entitynode, scene::Cloneable* entitycloneable, scene::Traversable* traversableroot ) + : m_entitynode( entitynode ), m_entitycloneable( entitycloneable ), m_traversableroot( traversableroot ){ + } + bool pre( scene::Node& node ) const { + return false; + } + void post( scene::Node& node ) const { + NodeSmartReference clone( m_entitycloneable->clone() ); // duplicate entity + m_traversableroot->insert( clone ); + + NodeSmartReference brush( node ); // move primitive + Node_getTraversable( *m_entitynode )->erase( node ); + Node_getTraversable( clone )->insert( node ); + } +}; + +void DoExplodeEntity(){ + scene::Node* entitynode = nullptr; + scene::Node* rootnode = nullptr; + { + if( GlobalSelectionSystem().countSelected() == 0 ){ + globalErrorStream() << "nothing selected\n"; + return; + } + scene::Path path = GlobalSelectionSystem().ultimateSelected().path(); + Entity* entity = Node_getEntity( path.top() ); + if ( entity == nullptr && path.size() >= 3 ) { // path.size() = 3 as in root.entity.brush, guarantees getting `rootnode` later + path.pop(); + entity = Node_getEntity( path.top() ); + } + if( entity == nullptr ){ + globalErrorStream() << "no entity selected\n"; + return; + } + if( !entity->isContainer() ){ + globalErrorStream() << "!entity->isContainer()\n"; + return; + } + if( string_equal_nocase( entity->getClassName(), "worldspawn" ) ){ + globalErrorStream() << "can't explode worldspawn\n"; + return; + } + entitynode = path.top().get_pointer(); + rootnode = path.parent().get_pointer(); + } + + if( scene::Traversable* traversable = Node_getTraversable( *entitynode ) ){ + if( scene::Traversable* traversableroot = Node_getTraversable( *rootnode ) ){ + if( scene::Cloneable* entitycloneable = NodeTypeCast::cast( *entitynode ) ){ + UndoableCommand undo( "bobToolz.explodeEntity" ); + ExplodeWalker walker( entitynode, entitycloneable, traversableroot ); + traversable->traverse( walker ); + traversableroot->erase( *entitynode ); // remove original entity + } + } + } } diff --git a/contrib/bobtoolz/funchandlers.h b/contrib/bobtoolz/funchandlers.h index c53668ee..3b59e220 100644 --- a/contrib/bobtoolz/funchandlers.h +++ b/contrib/bobtoolz/funchandlers.h @@ -72,3 +72,4 @@ void DoTreePlanter(); void DoDropEnts(); void DoMakeChain(); void DoFlipTerrain(); +void DoExplodeEntity(); diff --git a/docs/changelog-custom.txt b/docs/changelog-custom.txt index ec963b1a..ced6cc9e 100644 --- a/docs/changelog-custom.txt +++ b/docs/changelog-custom.txt @@ -1110,6 +1110,7 @@ misc... * light radiuses: don't render biggest radius, make them less occluding in 3D * fix surface inspector updates on patch texturing changes, on UV Tool edits * add prefs->Build->Region Box Shader (shader to use on the box generated around region) + * add bobToolz.explodeEntity: create group entity from each primitive of existing group entity