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
This commit is contained in:
parent
7ca59bef0a
commit
dce6730b39
|
|
@ -47,6 +47,7 @@ enum
|
|||
EXCLUDE_BOTCLIP = 0x00040000,
|
||||
EXCLUDE_VISPORTALS = 0x00080000,
|
||||
EXCLUDE_DECALS = 0x00100000,
|
||||
EXCLUDE_FUNC_GROUPS = 0x00200000,
|
||||
};
|
||||
|
||||
class Filter
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -696,6 +696,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
|
|||
Instance_getSelectable( instance )->setSelected( true );
|
||||
}
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -110,26 +110,32 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
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 );
|
||||
// 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 ) &&
|
||||
( !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 ) ) ) {
|
||||
|
|
|
|||
|
|
@ -1392,6 +1392,9 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
|
|||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
BIN
setup/data/tools/bitmaps/f-funcgroups.png
Normal file
BIN
setup/data/tools/bitmaps/f-funcgroups.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 276 B |
Loading…
Reference in New Issue
Block a user