From dce6730b39a2e6484015e483c46edbe93054f6a0 Mon Sep 17 00:00:00 2001 From: Garux Date: Tue, 1 Aug 2017 14:27:03 +0300 Subject: [PATCH] Radiant: misc... * fix: select inside and touching: ignored ANY filters and hiding, and region * fix: M3 tex paint/grab ignored _hidden_ models * fix: M3 tex paint/grab ignored group ent (world, triggers, et cetera), model filters * fix: shift+a by tex: ignored group ent (world, triggers, et cetera) filters * fix: tex find/replace: ignored any filters, regioning & hiding * fix: shift+a by classname: ignored filters, hiding, region * fix: floor walker ignored group ent filters * fix: csg subtract ignored group ent filters * fix: invert selection: ignored group ent filters * fix: tex find/replace: 'select by shader' mode for patches (was replacing with notex instead) * fix: select inside and touching: were selecting group ents, as single unit (=sensitive to parent node and its bbox) * fix: csg merge two group ents = empty group ent * fix: csg subtract group ent completely = empty group ent * fix: hollow group ent: could produce empty group ent * func_groups are filtered by world filter only, not entities one * new func_group filter, filterBar button; Rightclick = create func_group --- include/ifilter.h | 1 + libs/scenelib.h | 9 +++- plugins/entity/entity.cpp | 15 +++++- radiant/brushmanip.cpp | 3 ++ radiant/camwindow.cpp | 3 ++ radiant/csg.cpp | 63 ++++++++++++++++++++-- radiant/filterbar.cpp | 15 +++++- radiant/filters.cpp | 2 + radiant/mainframe.cpp | 1 + radiant/patch.h | 9 ++++ radiant/patchmanip.cpp | 20 ++++++- radiant/select.cpp | 43 +++++++++------ radiant/surfacedialog.cpp | 3 ++ setup/data/tools/bitmaps/f-funcgroups.png | Bin 0 -> 276 bytes 14 files changed, 162 insertions(+), 25 deletions(-) create mode 100644 setup/data/tools/bitmaps/f-funcgroups.png diff --git a/include/ifilter.h b/include/ifilter.h index 7efbb8a9..f75a217a 100644 --- a/include/ifilter.h +++ b/include/ifilter.h @@ -47,6 +47,7 @@ enum EXCLUDE_BOTCLIP = 0x00040000, EXCLUDE_VISPORTALS = 0x00080000, EXCLUDE_DECALS = 0x00100000, + EXCLUDE_FUNC_GROUPS = 0x00200000, }; class Filter diff --git a/libs/scenelib.h b/libs/scenelib.h index 29402065..08566259 100644 --- a/libs/scenelib.h +++ b/libs/scenelib.h @@ -762,7 +762,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; } }; diff --git a/plugins/entity/entity.cpp b/plugins/entity/entity.cpp index db0e16b4..c862459e 100644 --- a/plugins/entity/entity.cpp +++ b/plugins/entity/entity.cpp @@ -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 ); diff --git a/radiant/brushmanip.cpp b/radiant/brushmanip.cpp index 36ed6a9b..11db0ba9 100644 --- a/radiant/brushmanip.cpp +++ b/radiant/brushmanip.cpp @@ -696,6 +696,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const { Instance_getSelectable( instance )->setSelected( true ); } } + else{ + return false; + } return true; } }; diff --git a/radiant/camwindow.cpp b/radiant/camwindow.cpp index 46281295..134ab7d2 100644 --- a/radiant/camwindow.cpp +++ b/radiant/camwindow.cpp @@ -1249,6 +1249,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const { m_bestDown = floorHeight; } } + else if( !path.top().get().visible() ){ + return false; + } return true; } }; diff --git a/radiant/csg.cpp b/radiant/csg.cpp index 1b0d6004..1b824b6a 100644 --- a/radiant/csg.cpp +++ b/radiant/csg.cpp @@ -379,7 +379,7 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const { return true; } }; - +/* class BrushDeleteSelected : public scene::Graph::Walker { public: @@ -397,7 +397,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 ); + } + } +} +}; /* ============= @@ -568,12 +608,16 @@ 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 { if ( path.top().get().visible() ) { @@ -626,9 +670,20 @@ void post( const scene::Path& path, scene::Instance& instance ) const { } } 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 ); + } + } } }; @@ -868,7 +923,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 ); diff --git a/radiant/filterbar.cpp b/radiant/filterbar.cpp index 918f3d80..6317fa47 100644 --- a/radiant/filterbar.cpp +++ b/radiant/filterbar.cpp @@ -11,7 +11,7 @@ #include "gtkutil/accelerator.h" #include "generic/callback.h" - +#include "entity.h" int ToggleActions = 0; @@ -147,6 +147,16 @@ gboolean Trigger_button_press( GtkWidget *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( GtkWidget *widget, GdkEventButton *event, gpointer data ){ if ( event->button == 3 && event->type == GDK_BUTTON_PRESS ) { GlobalCommands_find( "MakeDetail" ).m_callback(); @@ -181,6 +191,8 @@ GtkToolbar* create_filter_toolbar(){ button = toolbar_append_toggle_button( filter_toolbar, "Details (CTRL + D)\nRightClick: MakeDetail", "f-details.png", "FilterDetails" ); g_signal_connect( G_OBJECT( button ), "button_press_event", G_CALLBACK( Detail_button_press ), 0 ); + 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" ); gtk_toolbar_append_space( GTK_TOOLBAR( filter_toolbar ) ); @@ -216,6 +228,7 @@ GtkToolbar* create_filter_toolbar(){ //toolbar_append_toggle_button( filter_toolbar, "Decals (SHIFT + D)", "f-decals.png", "FilterDecals" ); gtk_toolbar_append_space( GTK_TOOLBAR( filter_toolbar ) ); toolbar_append_button( filter_toolbar, "InvertFilters", "f-invert.png", "InvertFilters" ); + toolbar_append_button( filter_toolbar, "ResetFilters", "f-reset.png", "ResetFilters" ); return filter_toolbar; } diff --git a/radiant/filters.cpp b/radiant/filters.cpp index 3ff4ddd0..b232b791 100644 --- a/radiant/filters.cpp +++ b/radiant/filters.cpp @@ -205,6 +205,7 @@ void Filters_constructMenu( GtkMenu* 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(); } diff --git a/radiant/mainframe.cpp b/radiant/mainframe.cpp index 4c9fc6b3..4c8ddd7c 100644 --- a/radiant/mainframe.cpp +++ b/radiant/mainframe.cpp @@ -2778,6 +2778,7 @@ void MainFrame::Create(){ GtkWidget* vbox = gtk_vbox_new( FALSE, 0 ); gtk_container_add( GTK_CONTAINER( window ), vbox ); gtk_widget_show( vbox ); + gtk_container_set_focus_chain( GTK_CONTAINER( vbox ), NULL ); global_accel_connect_window( window ); diff --git a/radiant/patch.h b/radiant/patch.h index 7cca4286..b1a897be 100644 --- a/radiant/patch.h +++ b/radiant/patch.h @@ -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; } }; diff --git a/radiant/patchmanip.cpp b/radiant/patchmanip.cpp index 4a7e72ab..b941e2ae 100644 --- a/radiant/patchmanip.cpp +++ b/radiant/patchmanip.cpp @@ -453,12 +453,28 @@ void operator()( Patch& patch ) const { } }; +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( PatchFindReplaceShader( find, 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( PatchFindReplaceShader( find, 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 ) ); + } } diff --git a/radiant/select.cpp b/radiant/select.cpp index 175af349..c42b4003 100644 --- a/radiant/select.cpp +++ b/radiant/select.cpp @@ -110,27 +110,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; } @@ -275,6 +281,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 ) @@ -608,6 +618,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 ) ) ) { diff --git a/radiant/surfacedialog.cpp b/radiant/surfacedialog.cpp index d0ff4c1c..cc6c116b 100644 --- a/radiant/surfacedialog.cpp +++ b/radiant/surfacedialog.cpp @@ -1392,6 +1392,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 index 0000000000000000000000000000000000000000..aef96139e26836591a4641c3e29a44f26bc40268 GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6;>1s;*b z3=DjSK$uZf!>a)(C{^MbQ4*Y=R#Ki=l*$m0n3-3i=jR%tP-d)Ws%L0m@TF)WP}Kxa z7sn6_|Fe@1@*Ys&aQ%2=_U@9#zGoSH7v`>5;Ii?^skIV^UFGV2vU!*%ST!o8_(eBP zm(gxua(wT$qPt65L0Kj>*VWqJl*{3$Q(S813dT6eE3tPI7;5e|rS44 z-x4{^w)Lp=4#wzpTU1;+?q1XOj`B;17Y_ZSAiKt