]> git.xonotic.org Git - xonotic/netradiant.git/commitdiff
Merge commit 'b25e4389ba4d089fc94cc3860774c8510b843042' into master-merge
authorThomas Debesse <dev@illwieckz.net>
Tue, 21 Jun 2022 01:57:24 +0000 (03:57 +0200)
committerThomas Debesse <dev@illwieckz.net>
Tue, 21 Jun 2022 01:57:24 +0000 (03:57 +0200)
14 files changed:
include/ifilter.h
libs/scenelib.h
plugins/entity/entity.cpp
radiant/brushmanip.cpp
radiant/camwindow.cpp
radiant/csg.cpp
radiant/filterbar.cpp
radiant/filters.cpp
radiant/mainframe.cpp
radiant/patch.h
radiant/patchmanip.cpp
radiant/select.cpp
radiant/surfacedialog.cpp
setup/data/tools/bitmaps/f-funcgroups.png [new file with mode: 0644]

index 7efbb8a9c878eee60bf753db0753ed1ef9d2de87..f75a217a4de23a13ce1fccbdb03608fd53442c03 100644 (file)
@@ -47,6 +47,7 @@ enum
        EXCLUDE_BOTCLIP          = 0x00040000,
        EXCLUDE_VISPORTALS       = 0x00080000,
        EXCLUDE_DECALS           = 0x00100000,
+       EXCLUDE_FUNC_GROUPS       = 0x00200000,
 };
 
 class Filter
index e1c05d464d8ba5ee096c55f6f08c2a122db47e9e..c18f5bdbac20c160ae716b6904ad6272a6959a4f 100644 (file)
@@ -763,7 +763,14 @@ public:
 InstanceWalker( const Functor& functor ) : m_functor( functor ){
 }
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
-       m_functor( instance );
+       //m_functor( instance );
+       //return true;
+       if ( path.top().get().visible() ) {
+               m_functor( instance );
+       }
+       else{
+               return false;
+       }
        return true;
 }
 };
index 181f9412082ed9c74434b7dbf4701957454e7765..a251bde5c442be67c0438e89cf3ff56ef945932d 100644 (file)
@@ -307,7 +307,7 @@ bool filter( const Entity& entity ) const {
 }
 };
 
-filter_entity_classname g_filter_entity_world( "worldspawn" );
+//filter_entity_classname g_filter_entity_world( "worldspawn" );
 filter_entity_classname g_filter_entity_func_group( "func_group" );
 filter_entity_classname g_filter_entity_light( "light" );
 filter_entity_classname g_filter_entity_misc_model( "misc_model" );
@@ -327,9 +327,20 @@ bool filter( const Entity& entity ) const {
 filter_entity_doom3model g_filter_entity_doom3model;
 
 
+class filter_entity_world : public EntityFilter
+{
+public:
+bool filter( const Entity& entity ) const {
+       return string_equal( entity.getKeyValue( "classname" ), "worldspawn" )
+                  || string_equal( entity.getKeyValue( "classname" ), "func_group" );
+}
+};
+
+filter_entity_world g_filter_entity_world;
+
 void Entity_InitFilters(){
        add_entity_filter( g_filter_entity_world, EXCLUDE_WORLD );
-       add_entity_filter( g_filter_entity_func_group, EXCLUDE_WORLD );
+       add_entity_filter( g_filter_entity_func_group, EXCLUDE_FUNC_GROUPS );
        add_entity_filter( g_filter_entity_world, EXCLUDE_ENT, true );
        add_entity_filter( g_filter_entity_trigger, EXCLUDE_TRIGGERS );
        add_entity_filter( g_filter_entity_misc_model, EXCLUDE_MODELS );
index ceb9b321b3a9eff7611021b40954212559be674c..f4c122dd37d24cb8b4ad89229cc5f97a7179ed02 100644 (file)
@@ -626,6 +626,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
                        Instance_getSelectable( instance )->setSelected( true );
                }
        }
+       else{
+               return false;
+       }
        return true;
 }
 };
index 6ccf3ec642383733e6424451e4774f3eb388ab2f..dd01aeec71d180c21298bd7ee9bf2e6891bafcf6 100644 (file)
@@ -1248,6 +1248,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
                        m_bestDown = floorHeight;
                }
        }
+       else if( !path.top().get().visible() ){
+               return false;
+       }
        return true;
 }
 };
index c034095df43d925e16d69461fb9be8f4bb3bf1e6..59ea7e9c1b902cb40d64c368099f1287c13ad070 100644 (file)
@@ -381,7 +381,7 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
        return true;
 }
 };
-
+/*
 class BrushDeleteSelected : public scene::Graph::Walker
 {
 public:
@@ -399,7 +399,47 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
        }
 }
 };
+*/
+#include "ientity.h"
 
+class BrushDeleteSelected : public scene::Graph::Walker
+{
+scene::Node* m_keepNode;
+mutable bool m_eraseParent;
+public:
+BrushDeleteSelected( scene::Node* keepNode ): m_keepNode( keepNode ), m_eraseParent( false ){
+}
+BrushDeleteSelected(): m_keepNode( NULL ), m_eraseParent( false ){
+}
+bool pre( const scene::Path& path, scene::Instance& instance ) const {
+       return true;
+}
+void post( const scene::Path& path, scene::Instance& instance ) const {
+       //globalOutputStream() << path.size() << "\n";
+       if ( path.top().get().visible() ) {
+               Brush* brush = Node_getBrush( path.top() );
+               if ( brush != 0
+                        && Instance_getSelectable( instance )->isSelected()
+                        && path.size() > 1 ) {
+                       Path_deleteTop( path );
+                       if( Node_getTraversable( path.parent() )->empty() ){
+                               m_eraseParent = true;
+                               //globalOutputStream() << "Empty node?!.\n";
+                       }
+               }
+       }
+       if( m_eraseParent && !Node_isPrimitive( path.top() ) && path.size() > 1 ){
+               //globalOutputStream() << "about to Delete empty node!.\n";
+               m_eraseParent = false;
+               Entity* entity = Node_getEntity( path.top() );
+               if ( entity != 0 && path.top().get_pointer() != Map_FindWorldspawn( g_map )
+                       && Node_getTraversable( path.top() )->empty() && path.top().get_pointer() != m_keepNode ) {
+                       //globalOutputStream() << "now Deleting empty node!.\n";
+                       Path_deleteTop( path );
+               }
+       }
+}
+};
 
 /*
    =============
@@ -553,13 +593,17 @@ class SubtractBrushesFromUnselected : public scene::Graph::Walker
 const brush_vector_t& m_brushlist;
 std::size_t& m_before;
 std::size_t& m_after;
+mutable bool m_eraseParent;
 public:
 SubtractBrushesFromUnselected( const brush_vector_t& brushlist, std::size_t& before, std::size_t& after )
-       : m_brushlist( brushlist ), m_before( before ), m_after( after ){
+       : m_brushlist( brushlist ), m_before( before ), m_after( after ), m_eraseParent( false ){
 }
 
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
-       return true;
+       if ( path.top().get().visible() ) {
+               return true;
+       }
+       return false;
 }
 
 void post( const scene::Path& path, scene::Instance& instance ) const {
@@ -609,9 +653,20 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
                                        delete b;
                                }
                                Path_deleteTop( path );
+                               if( Node_getTraversable( path.parent() )->empty() ){
+                                       m_eraseParent = true;
+                               }
                        }
                }
        }
+       if( m_eraseParent && !Node_isPrimitive( path.top() ) && path.size() > 1 ){
+               m_eraseParent = false;
+               Entity* entity = Node_getEntity( path.top() );
+               if ( entity != 0 && path.top().get_pointer() != Map_FindWorldspawn( g_map )
+                       && Node_getTraversable( path.top() )->empty() ) {
+                       Path_deleteTop( path );
+               }
+       }
 }
 };
 
@@ -858,7 +913,7 @@ void CSG_Merge( void ){
                ASSERT_MESSAGE( !brush->empty(), "brush left with no faces after merge" );
 
                // free the original brushes
-               GlobalSceneGraph().traverse( BrushDeleteSelected() );
+               GlobalSceneGraph().traverse( BrushDeleteSelected( merged_path.parent().get_pointer() ) );
 
                merged_path.pop();
                Node_getTraversable( merged_path.top() )->insert( node );
index 424280ce2f9da105cbe6b710b0e2832819e13d9d..af2c829d31c070ecc91423044c95b13a48391a13 100644 (file)
@@ -13,7 +13,7 @@
 #include "gtkutil/accelerator.h"
 #include "generic/callback.h"
 
-
+#include "entity.h"
 int ToggleActions = 0;
 int ButtonNum = 0;
 
@@ -152,6 +152,16 @@ gboolean Trigger_button_press( ui::Widget widget, GdkEventButton *event, gpointe
        return FALSE;
 }
 
+gboolean Func_Groups_button_press( GtkWidget *widget, GdkEventButton *event, gpointer data ){
+       if ( event->button == 3 && event->type == GDK_BUTTON_PRESS ) {
+               UndoableCommand undo( "create func_group" );
+               Entity_createFromSelection( "func_group", g_vector3_identity );
+               ToggleActions = 0;
+               return TRUE;
+       }
+       return FALSE;
+}
+
 
 gboolean Detail_button_press( ui::Widget widget, GdkEventButton *event, gpointer data ){
        if ( event->button == 3 && event->type == GDK_BUTTON_PRESS ) {
@@ -200,7 +210,13 @@ ui::Toolbar create_filter_toolbar(){
                                g_signal_connect( G_OBJECT( button ), "button_press_event", G_CALLBACK( Detail_button_press ), 0 );
                        }
 
-                       toolbar_append_toggle_button( filter_toolbar, "Patches (CTRL + P)", "patch_wireframe.png", "FilterPatches" );
+                       {
+                               auto button = toolbar_append_toggle_button( filter_toolbar, "Func_Groups\nRightClick: create func_group", "f-funcgroups.png", "FilterFuncGroups" );
+                               g_signal_connect( G_OBJECT( button ), "button_press_event", G_CALLBACK( Func_Groups_button_press ), 0 );
+
+                               toolbar_append_toggle_button( filter_toolbar, "Patches (CTRL + P)", "patch_wireframe.png", "FilterPatches" );
+                       }
+
                        space();
 
                        {
@@ -208,7 +224,6 @@ ui::Toolbar create_filter_toolbar(){
                                g_signal_connect( G_OBJECT( button ), "button_press_event", G_CALLBACK( Areaportals_button_press ), 0 );
                        }
 
-
                        toolbar_append_toggle_button( filter_toolbar, "Translucent (ALT + 4)", "f-translucent.png", "FilterTranslucent" );
 
                        {
@@ -232,7 +247,9 @@ ui::Toolbar create_filter_toolbar(){
                        }
 
                        //toolbar_append_toggle_button( filter_toolbar, "Paths (ALT + 8)", "texture_lock.png", "FilterPaths" );
+
                        space();
+
                        toolbar_append_toggle_button( filter_toolbar, "Entities (ALT + 2)", "f-entities.png", "FilterEntities" );
                        toolbar_append_toggle_button( filter_toolbar, "Lights (ALT + 0)", "f-lights.png", "FilterLights" );
                        toolbar_append_toggle_button( filter_toolbar, "Models (SHIFT + M)", "f-models.png", "FilterModels" );
@@ -245,6 +262,7 @@ ui::Toolbar create_filter_toolbar(){
                        //toolbar_append_toggle_button( filter_toolbar, "Decals (SHIFT + D)", "f-decals.png", "FilterDecals" );
                        space();
                        toolbar_append_button( filter_toolbar, "InvertFilters", "f-invert.png", "InvertFilters" );
+
                        toolbar_append_button( filter_toolbar, "ResetFilters", "f-reset.png", "ResetFilters" );
                        return filter_toolbar;
 }
index 3957af62e41b74fd9df16a629fb07b006d0ce800..3a9516056679556478d3fe9809e2db4f2ab4d96a 100644 (file)
@@ -205,6 +205,7 @@ void Filters_constructMenu( ui::Menu menu_in_menu ){
                create_check_menu_item_with_mnemonic( menu_in_menu, "Botclips", "FilterBotClips" );
                create_check_menu_item_with_mnemonic( menu_in_menu, "Decals", "FilterDecals" );
        }
+       create_check_menu_item_with_mnemonic( menu_in_menu, "FuncGroups", "FilterFuncGroups" );
        // filter manipulation
        menu_separator( menu_in_menu );
        create_menu_item_with_mnemonic( menu_in_menu, "Invert filters", "InvertFilters" );
@@ -252,6 +253,7 @@ void ConstructFilters(){
                add_filter_command( EXCLUDE_BOTCLIP, "FilterBotClips", Accelerator( 'M', (GdkModifierType)GDK_MOD1_MASK ) );
                add_filter_command( EXCLUDE_DECALS, "FilterDecals", Accelerator( 'D', (GdkModifierType)GDK_SHIFT_MASK ) );
        }
+       add_filter_command( EXCLUDE_FUNC_GROUPS, "FilterFuncGroups", accelerator_null() );
 
        PerformFiltering();
 }
index 1d08469350f414bbbad805e23faf195d93c6939c..41e9461e5046007f29658be29691819f54c46c9b 100644 (file)
@@ -3017,6 +3017,7 @@ void MainFrame::Create(){
        auto vbox = ui::VBox( FALSE, 0 );
        window.add(vbox);
        vbox.show();
+       gtk_container_set_focus_chain( GTK_CONTAINER( vbox ), NULL );
 
        global_accel_connect_window( window );
 
index 89deeac95ceadb55a04e9d2d5e311bb86d88dd66..c9812e614b88820fdc78f8c3a5953156d9f80a3b 100644 (file)
@@ -1810,6 +1810,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
                        m_functor( *patch );
                }
        }
+       else{
+               return false;
+       }
        return true;
 }
 };
@@ -1834,6 +1837,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
                        m_functor( *patch );
                }
        }
+       else{
+               return false;
+       }
        return true;
 }
 };
@@ -1857,6 +1863,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
                        m_functor( *patch );
                }
        }
+       else{
+               return false;
+       }
        return true;
 }
 };
index e0ab819c6325be6b40f8b48b4af581bb7382a01e..7a764976f4395ff34850c725bb19305707923533 100644 (file)
@@ -378,6 +378,20 @@ void Scene_PatchGetShader_Selected( scene::Graph& graph, CopiedString& name ){
        }
 }
 
+class PatchSelectByShader
+{
+const char* m_name;
+public:
+inline PatchSelectByShader( const char* name )
+       : m_name( name ){
+}
+void operator()( PatchInstance& patch ) const {
+       if ( shader_equal( patch.getPatch().GetShader(), m_name ) ) {
+               patch.setSelected( true );
+       }
+}
+};
+
 void Scene_PatchSelectByShader( scene::Graph& graph, const char* name ){
        Scene_forEachVisiblePatchInstance([&](PatchInstance &patch) {
                if (shader_equal(patch.getPatch().GetShader(), name)) {
@@ -387,20 +401,42 @@ void Scene_PatchSelectByShader( scene::Graph& graph, const char* name ){
 }
 
 
+class PatchFindReplaceShader
+{
+const char* m_find;
+const char* m_replace;
+public:
+PatchFindReplaceShader( const char* find, const char* replace ) : m_find( find ), m_replace( replace ){
+}
+void operator()( Patch& patch ) const {
+       if ( shader_equal( patch.GetShader(), m_find ) ) {
+               patch.SetShader( m_replace );
+       }
+}
+};
+
+namespace{
+bool DoingSearch( const char *repl ){
+       return ( repl == NULL || ( strcmp( "textures/", repl ) == 0 ) );
+}
+}
 void Scene_PatchFindReplaceShader( scene::Graph& graph, const char* find, const char* replace ){
-       Scene_forEachVisiblePatch([&](Patch &patch) {
-               if (shader_equal(patch.GetShader(), find)) {
-                       patch.SetShader(replace);
-               }
-       });
+       if( DoingSearch( replace ) ){
+               Scene_forEachVisiblePatchInstance( PatchSelectByShader( find ) );
+       }
+       else{
+               Scene_forEachVisiblePatch( PatchFindReplaceShader( find, replace ) );
+       }
 }
 
 void Scene_PatchFindReplaceShader_Selected( scene::Graph& graph, const char* find, const char* replace ){
-       Scene_forEachVisibleSelectedPatch([&](Patch &patch) {
-               if (shader_equal(patch.GetShader(), find)) {
-                       patch.SetShader(replace);
-               }
-       });
+       if( DoingSearch( replace ) ){
+               //do nothing, because alternative is replacing to notex
+               //perhaps deselect ones with not matching shaders here?
+       }
+       else{
+               Scene_forEachVisibleSelectedPatch( PatchFindReplaceShader( find, replace ) );
+       }
 }
 
 
index 8447897a4ab7b3a99aaa110a7ffd4153e55c2c44..f92706b5bdb9ecc5156ce8f09bc0e7a63e772806 100644 (file)
@@ -112,27 +112,33 @@ SelectByBounds( AABB* aabbs, Unsigned count )
 }
 
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
-       Selectable* selectable = Instance_getSelectable( instance );
+       if( path.top().get().visible() ){
+               Selectable* selectable = Instance_getSelectable( instance );
 
-       // ignore worldspawn
-       Entity* entity = Node_getEntity( path.top() );
-       if ( entity ) {
-               if ( string_equal( entity->getKeyValue( "classname" ), "worldspawn" ) ) {
-                       return true;
+               // ignore worldspawn
+               Entity* entity = Node_getEntity( path.top() );
+               if ( entity ) {
+                       if ( string_equal( entity->getKeyValue( "classname" ), "worldspawn" ) ) {
+                               return true;
+                       }
                }
-       }
 
-       if ( ( path.size() > 1 ) &&
-                ( !path.top().get().isRoot() ) &&
-                ( selectable != 0 )
-                ) {
-               for ( Unsigned i = 0; i < m_count; ++i )
-               {
-                       if ( policy.Evaluate( m_aabbs[i], instance ) ) {
-                               selectable->setSelected( true );
+               if ( ( path.size() > 1 ) &&
+                       ( !path.top().get().isRoot() ) &&
+                       ( selectable != 0 ) &&
+                       ( !node_is_group( path.top() ) )
+                       ) {
+                       for ( Unsigned i = 0; i < m_count; ++i )
+                       {
+                               if ( policy.Evaluate( m_aabbs[i], instance ) ) {
+                                       selectable->setSelected( true );
+                               }
                        }
                }
        }
+       else{
+               return false;
+       }
 
        return true;
 }
@@ -277,6 +283,10 @@ InvertSelectionWalker( SelectionSystem::EMode mode )
        : m_mode( mode ), m_selectable( 0 ){
 }
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
+       if( !path.top().get().visible() ){
+               m_selectable = 0;
+               return false;
+       }
        Selectable* selectable = Instance_getSelectable( instance );
        if ( selectable ) {
                switch ( m_mode )
@@ -610,6 +620,9 @@ EntityFindByPropertyValueWalker( const char *prop, const PropertyValues& propert
        : m_propertyvalues( propertyvalues ), m_prop( prop ){
 }
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
+       if( !path.top().get().visible() ){
+               return false;
+       }
        Entity* entity = Node_getEntity( path.top() );
        if ( entity != 0
                 && propertyvalues_contain( m_propertyvalues, entity->getKeyValue( m_prop ) ) ) {
index 8cab31e469b84bae4a2cc470d55d074f194d7008..51d497ad78e5def5cbfaeebdc50889faf021436c 100644 (file)
@@ -1306,6 +1306,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
                        }
                }
        }
+       else{
+               return false;
+       }
        return true;
 }
 };
diff --git a/setup/data/tools/bitmaps/f-funcgroups.png b/setup/data/tools/bitmaps/f-funcgroups.png
new file mode 100644 (file)
index 0000000..aef9613
Binary files /dev/null and b/setup/data/tools/bitmaps/f-funcgroups.png differ