]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/select.cpp
Merge commit '0261afc6df181092b7d57751fec84e21d3ac593c' into garux-merge
[xonotic/netradiant.git] / radiant / select.cpp
index 1c97e9ee0138a13b6a266eb7e97959099ac5c08e..bca6f2ccddb7f249e7538212b8bb050f812ef99c 100644 (file)
@@ -41,6 +41,7 @@
 #include "gtkutil/widget.h"
 #include "brushmanip.h"
 #include "brush.h"
+#include "patch.h"
 #include "patchmanip.h"
 #include "patchdialog.h"
 #include "selection.h"
@@ -277,10 +278,11 @@ void Select_Delete( void ){
 class InvertSelectionWalker : public scene::Graph::Walker
 {
 SelectionSystem::EMode m_mode;
+SelectionSystem::EComponentMode m_compmode;
 mutable Selectable* m_selectable;
 public:
-InvertSelectionWalker( SelectionSystem::EMode mode )
-       : m_mode( mode ), m_selectable( 0 ){
+InvertSelectionWalker( SelectionSystem::EMode mode, SelectionSystem::EComponentMode compmode )
+       : m_mode( mode ), m_compmode( compmode ), m_selectable( 0 ){
 }
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
        if( !path.top().get().visible() ){
@@ -300,6 +302,18 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
                        m_selectable = path.top().get().visible() ? selectable : 0;
                        break;
                case SelectionSystem::eComponent:
+                       BrushInstance* brushinstance = Instance_getBrush( instance );
+                       if( brushinstance != 0 ){
+                               if( brushinstance->isSelected() )
+                                       brushinstance->invertComponentSelection( m_compmode );
+                       }
+                       else{
+                               PatchInstance* patchinstance = Instance_getPatch( instance );
+                               if( patchinstance != 0 && m_compmode == SelectionSystem::eVertex ){
+                                       if( patchinstance->isSelected() )
+                                               patchinstance->invertComponentSelection();
+                               }
+                       }
                        break;
                }
        }
@@ -314,13 +328,64 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
 };
 
 void Scene_Invert_Selection( scene::Graph& graph ){
-       graph.traverse( InvertSelectionWalker( GlobalSelectionSystem().Mode() ) );
+       graph.traverse( InvertSelectionWalker( GlobalSelectionSystem().Mode(), GlobalSelectionSystem().ComponentMode() ) );
 }
 
 void Select_Invert(){
        Scene_Invert_Selection( GlobalSceneGraph() );
 }
 
+//interesting printings
+class ExpandSelectionToEntitiesWalker_dbg : public scene::Graph::Walker
+{
+mutable std::size_t m_depth;
+NodeSmartReference worldspawn;
+public:
+ExpandSelectionToEntitiesWalker_dbg() : m_depth( 0 ), worldspawn( Map_FindOrInsertWorldspawn( g_map ) ){
+}
+bool pre( const scene::Path& path, scene::Instance& instance ) const {
+       ++m_depth;
+       globalOutputStream() << "pre depth_" << m_depth;
+       globalOutputStream() << " path.size()_" << path.size();
+       if ( path.top().get() == worldspawn )
+               globalOutputStream() << " worldspawn";
+       if( path.top().get().isRoot() )
+               globalOutputStream() << " path.top().get().isRoot()";
+       Entity* entity = Node_getEntity( path.top() );
+       if ( entity != 0 ){
+               globalOutputStream() << " entity!=0";
+               if( entity->isContainer() ){
+                       globalOutputStream() << " entity->isContainer()";
+               }
+               globalOutputStream() << " classname_" << entity->getKeyValue( "classname" );
+       }
+       globalOutputStream() << "\n";
+//     globalOutputStream() << "" <<  ;
+//     globalOutputStream() << "" <<  ;
+//     globalOutputStream() << "" <<  ;
+//     globalOutputStream() << "" <<  ;
+       return true;
+}
+void post( const scene::Path& path, scene::Instance& instance ) const {
+       globalOutputStream() << "post depth_" << m_depth;
+       globalOutputStream() << " path.size()_" << path.size();
+       if ( path.top().get() == worldspawn )
+               globalOutputStream() << " worldspawn";
+       if( path.top().get().isRoot() )
+               globalOutputStream() << " path.top().get().isRoot()";
+       Entity* entity = Node_getEntity( path.top() );
+       if ( entity != 0 ){
+               globalOutputStream() << " entity!=0";
+               if( entity->isContainer() ){
+                       globalOutputStream() << " entity->isContainer()";
+               }
+               globalOutputStream() << " classname_" << entity->getKeyValue( "classname" );
+       }
+       globalOutputStream() << "\n";
+       --m_depth;
+}
+};
+
 class ExpandSelectionToEntitiesWalker : public scene::Graph::Walker
 {
 mutable std::size_t m_depth;
@@ -332,17 +397,21 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
        ++m_depth;
 
        // ignore worldspawn
-       NodeSmartReference me( path.top().get() );
-       if ( me == worldspawn ) {
-               return false;
-       }
+//     NodeSmartReference me( path.top().get() );
+//     if ( me == worldspawn ) {
+//             return false;
+//     }
 
        if ( m_depth == 2 ) { // entity depth
                // traverse and select children if any one is selected
+               bool beselected = false;
                if ( instance.childSelected() ) {
-                       Instance_setSelected( instance, true );
+                       beselected = true;
+                       if( path.top().get() != worldspawn ){
+                               Instance_setSelected( instance, true );
+                       }
                }
-               return Node_getEntity( path.top() )->isContainer() && instance.isSelected();
+               return Node_getEntity( path.top() )->isContainer() && beselected;
        }
        else if ( m_depth == 3 ) { // primitive depth
                Instance_setSelected( instance, true );
@@ -524,20 +593,20 @@ inline Quaternion quaternion_for_axis90( axis_t axis, sign_t sign ){
 
 void Select_RotateAxis( int axis, float deg ){
        if ( fabs( deg ) == 90.f ) {
-               GlobalSelectionSystem().rotateSelected( quaternion_for_axis90( (axis_t)axis, ( deg > 0 ) ? eSignPositive : eSignNegative ) );
+               GlobalSelectionSystem().rotateSelected( quaternion_for_axis90( (axis_t)axis, ( deg > 0 ) ? eSignPositive : eSignNegative ), true );
        }
        else
        {
                switch ( axis )
                {
                case 0:
-                       GlobalSelectionSystem().rotateSelected( quaternion_for_matrix4_rotation( matrix4_rotation_for_x_degrees( deg ) ) );
+                       GlobalSelectionSystem().rotateSelected( quaternion_for_matrix4_rotation( matrix4_rotation_for_x_degrees( deg ) ), false );
                        break;
                case 1:
-                       GlobalSelectionSystem().rotateSelected( quaternion_for_matrix4_rotation( matrix4_rotation_for_y_degrees( deg ) ) );
+                       GlobalSelectionSystem().rotateSelected( quaternion_for_matrix4_rotation( matrix4_rotation_for_y_degrees( deg ) ), false );
                        break;
                case 2:
-                       GlobalSelectionSystem().rotateSelected( quaternion_for_matrix4_rotation( matrix4_rotation_for_z_degrees( deg ) ) );
+                       GlobalSelectionSystem().rotateSelected( quaternion_for_matrix4_rotation( matrix4_rotation_for_z_degrees( deg ) ), false );
                        break;
                }
        }
@@ -615,18 +684,32 @@ class EntityFindByPropertyValueWalker : public scene::Graph::Walker
 {
 const PropertyValues& m_propertyvalues;
 const char *m_prop;
+const NodeSmartReference worldspawn;
 public:
 EntityFindByPropertyValueWalker( const char *prop, const PropertyValues& propertyvalues )
-       : m_propertyvalues( propertyvalues ), m_prop( prop ){
+       : m_propertyvalues( propertyvalues ), m_prop( prop ), worldspawn( Map_FindOrInsertWorldspawn( g_map ) ){
 }
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
        if( !path.top().get().visible() ){
                return false;
        }
+       // ignore worldspawn
+       if ( path.top().get() == worldspawn ) {
+               return false;
+       }
+
        Entity* entity = Node_getEntity( path.top() );
-       if ( entity != 0
-                && propertyvalues_contain( m_propertyvalues, entity->getKeyValue( m_prop ) ) ) {
-               Instance_getSelectable( instance )->setSelected( true );
+       if ( entity != 0 ){
+               if( propertyvalues_contain( m_propertyvalues, entity->getKeyValue( m_prop ) ) ) {
+                       Instance_getSelectable( instance )->setSelected( true );
+                       return true;
+               }
+               return false;
+       }
+       else if( path.size() > 2 && !path.top().get().isRoot() ){
+               Selectable* selectable = Instance_getSelectable( instance );
+               if( selectable != 0 )
+                       selectable->setSelected( true );
        }
        return true;
 }
@@ -640,9 +723,37 @@ class EntityGetSelectedPropertyValuesWalker : public scene::Graph::Walker
 {
 PropertyValues& m_propertyvalues;
 const char *m_prop;
+const NodeSmartReference worldspawn;
 public:
 EntityGetSelectedPropertyValuesWalker( const char *prop, PropertyValues& propertyvalues )
-       : m_propertyvalues( propertyvalues ), m_prop( prop ){
+       : m_propertyvalues( propertyvalues ), m_prop( prop ), worldspawn( Map_FindOrInsertWorldspawn( g_map ) ){
+}
+bool pre( const scene::Path& path, scene::Instance& instance ) const {
+       Entity* entity = Node_getEntity( path.top() );
+       if ( entity != 0 ){
+               if( path.top().get() != worldspawn ){
+                       Selectable* selectable = Instance_getSelectable( instance );
+                       if ( ( selectable != 0 && selectable->isSelected() ) || instance.childSelected() ) {
+                               if ( !propertyvalues_contain( m_propertyvalues, entity->getKeyValue( m_prop ) ) ) {
+                                       m_propertyvalues.push_back( entity->getKeyValue( m_prop ) );
+                               }
+                       }
+               }
+               return false;
+       }
+       return true;
+}
+};
+/*
+class EntityGetSelectedPropertyValuesWalker : public scene::Graph::Walker
+{
+PropertyValues& m_propertyvalues;
+const char *m_prop;
+mutable bool m_selected_children;
+const NodeSmartReference worldspawn;
+public:
+EntityGetSelectedPropertyValuesWalker( const char *prop, PropertyValues& propertyvalues )
+       : m_propertyvalues( propertyvalues ), m_prop( prop ), m_selected_children( false ), worldspawn( Map_FindOrInsertWorldspawn( g_map ) ){
 }
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
        Selectable* selectable = Instance_getSelectable( instance );
@@ -653,12 +764,27 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
                        if ( !propertyvalues_contain( m_propertyvalues, entity->getKeyValue( m_prop ) ) ) {
                                m_propertyvalues.push_back( entity->getKeyValue( m_prop ) );
                        }
+                       return false;
+               }
+               else{
+                       m_selected_children = true;
                }
        }
        return true;
 }
+void post( const scene::Path& path, scene::Instance& instance ) const {
+       Entity* entity = Node_getEntity( path.top() );
+       if( entity != 0 && m_selected_children ){
+               m_selected_children = false;
+               if( path.top().get() == worldspawn )
+                       return;
+               if ( !propertyvalues_contain( m_propertyvalues, entity->getKeyValue( m_prop ) ) ) {
+                       m_propertyvalues.push_back( entity->getKeyValue( m_prop ) );
+               }
+       }
+}
 };
-
+*/
 void Scene_EntityGetPropertyValues( scene::Graph& graph, const char *prop, PropertyValues& propertyvalues ){
        graph.traverse( EntityGetSelectedPropertyValuesWalker( prop, propertyvalues ) );
 }
@@ -878,21 +1004,21 @@ void Selection_RotateAnticlockwise(){
 
 
 void Select_registerCommands(){
-       GlobalCommands_insert( "ShowHidden", FreeCaller<Select_ShowAllHidden>(), Accelerator( 'H', (GdkModifierType)GDK_SHIFT_MASK ) );
-       GlobalToggles_insert( "HideSelected", FreeCaller<HideSelected>(), ToggleItem::AddCallbackCaller( g_hidden_item ), Accelerator( 'H' ) );
+       GlobalCommands_insert( "ShowHidden", makeCallbackF( Select_ShowAllHidden ), Accelerator( 'H', (GdkModifierType)GDK_SHIFT_MASK ) );
+       GlobalToggles_insert( "HideSelected", makeCallbackF( HideSelected ), ToggleItem::AddCallbackCaller( g_hidden_item ), Accelerator( 'H' ) );
 
-       GlobalCommands_insert( "MirrorSelectionX", FreeCaller<Selection_Flipx>() );
-       GlobalCommands_insert( "RotateSelectionX", FreeCaller<Selection_Rotatex>() );
-       GlobalCommands_insert( "MirrorSelectionY", FreeCaller<Selection_Flipy>() );
-       GlobalCommands_insert( "RotateSelectionY", FreeCaller<Selection_Rotatey>() );
-       GlobalCommands_insert( "MirrorSelectionZ", FreeCaller<Selection_Flipz>() );
-       GlobalCommands_insert( "RotateSelectionZ", FreeCaller<Selection_Rotatez>() );
+       GlobalCommands_insert( "MirrorSelectionX", makeCallbackF( Selection_Flipx ) );
+       GlobalCommands_insert( "RotateSelectionX", makeCallbackF( Selection_Rotatex ) );
+       GlobalCommands_insert( "MirrorSelectionY", makeCallbackF( Selection_Flipy ) );
+       GlobalCommands_insert( "RotateSelectionY", makeCallbackF( Selection_Rotatey ) );
+       GlobalCommands_insert( "MirrorSelectionZ", makeCallbackF( Selection_Flipz ) );
+       GlobalCommands_insert( "RotateSelectionZ", makeCallbackF( Selection_Rotatez ) );
 
-       GlobalCommands_insert( "MirrorSelectionHorizontally", FreeCaller<Selection_FlipHorizontally>() );
-       GlobalCommands_insert( "MirrorSelectionVertically", FreeCaller<Selection_FlipVertically>() );
+       GlobalCommands_insert( "MirrorSelectionHorizontally", makeCallbackF( Selection_FlipHorizontally ) );
+       GlobalCommands_insert( "MirrorSelectionVertically", makeCallbackF( Selection_FlipVertically ) );
 
-       GlobalCommands_insert( "RotateSelectionClockwise", FreeCaller<Selection_RotateClockwise>() );
-       GlobalCommands_insert( "RotateSelectionAnticlockwise", FreeCaller<Selection_RotateAnticlockwise>() );
+       GlobalCommands_insert( "RotateSelectionClockwise", makeCallbackF( Selection_RotateClockwise ) );
+       GlobalCommands_insert( "RotateSelectionAnticlockwise", makeCallbackF( Selection_RotateAnticlockwise ) );
 }
 
 
@@ -993,7 +1119,7 @@ static gboolean rotatedlg_apply( ui::Widget widget, RotateDialog* rotateDialog )
        command << "rotateSelectedEulerXYZ -x " << eulerXYZ[0] << " -y " << eulerXYZ[1] << " -z " << eulerXYZ[2];
        UndoableCommand undo( command.c_str() );
 
-       GlobalSelectionSystem().rotateSelected( quaternion_for_euler_xyz_degrees( eulerXYZ ) );
+       GlobalSelectionSystem().rotateSelected( quaternion_for_euler_xyz_degrees( eulerXYZ ), false );
        return TRUE;
 }
 
@@ -1050,7 +1176,7 @@ void DoRotateDlg(){
                                }
                                {
                                        auto adj = ui::Adjustment( 0, -359, 359, 1, 10, 0 );
-                                       auto spin = ui::SpinButton( adj, 1, 0 );
+                                       auto spin = ui::SpinButton( adj, 1, 1 );
                                        spin.show();
                     table.attach(spin, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0});
                     spin.dimensions(64, -1);
@@ -1062,7 +1188,7 @@ void DoRotateDlg(){
                                }
                                {
                                        auto adj = ui::Adjustment( 0, -359, 359, 1, 10, 0 );
-                                       auto spin = ui::SpinButton( adj, 1, 0 );
+                                       auto spin = ui::SpinButton( adj, 1, 1 );
                                        spin.show();
                     table.attach(spin, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0});
                     spin.dimensions(64, -1);
@@ -1072,7 +1198,7 @@ void DoRotateDlg(){
                                }
                                {
                                        auto adj = ui::Adjustment( 0, -359, 359, 1, 10, 0 );
-                                       auto spin = ui::SpinButton( adj, 1, 0 );
+                                       auto spin = ui::SpinButton( adj, 1, 1 );
                                        spin.show();
                     table.attach(spin, {1, 2, 2, 3}, {GTK_EXPAND | GTK_FILL, 0});
                     spin.dimensions(64, -1);