]> git.rm.cloudns.org Git - xonotic/netradiant.git/commitdiff
Allow deselecting primitives in a fully selected entity
authorMattia Basaglia <mattia.basaglia@gmail.com>
Thu, 23 Jul 2015 12:14:42 +0000 (14:14 +0200)
committerMattia Basaglia <mattia.basaglia@gmail.com>
Thu, 23 Jul 2015 12:14:42 +0000 (14:14 +0200)
libs/scenelib.h
radiant/brush.h
radiant/map.cpp
radiant/select.cpp
radiant/selection.cpp

index 29402065252cf7c8f2cb4d040d244e48d2e67427..57ccd0b27929b26391815282dd386603f7150ec7 100644 (file)
@@ -739,6 +739,10 @@ bool parentSelected() const {
        }
        return m_parentSelected;
 }
+Instance* parent() const
+{
+       return m_parent;
+}
 };
 }
 
index 46c820bdd4d84d88b7db384e37c73d783266d2e5..030db483fe275167bd09066fa61fa6c6640cf61b 100644 (file)
@@ -3197,6 +3197,12 @@ bool isSelected() const {
 }
 void setSelected( bool select ){
        m_selectable.setSelected( select );
+       if ( !select && parent() )
+       {
+               Selectable* sel_parent = Instance_getSelectable(*parent());
+               if ( sel_parent && sel_parent->isSelected() )
+                       sel_parent->setSelected(false);
+       }
 }
 
 void update_selected() const {
index 7493c088ded77e0d660e6a3f468187f6503f1059..36308f88c0a4f5e060af3e85d98eeaabd1f50a14 100644 (file)
@@ -1765,15 +1765,15 @@ void Scene_parentSelected(){
        if ( GlobalSelectionSystem().countSelected() > 1 ) {
                class ParentSelectedBrushesToEntityWalker : public SelectionSystem::Visitor
                {
-               const scene::Path& m_parent;
-public:
-               ParentSelectedBrushesToEntityWalker( const scene::Path& parent ) : m_parent( parent ){
-               }
-               void visit( scene::Instance& instance ) const {
-                       if ( &m_parent != &instance.path() ) {
-                               Path_parent( m_parent, instance.path() );
+                       const scene::Path& m_parent;
+               public:
+                       ParentSelectedBrushesToEntityWalker( const scene::Path& parent ) : m_parent( parent ){
+                       }
+                       void visit( scene::Instance& instance ) const {
+                               if ( &m_parent != &instance.path() ) {
+                                       Path_parent( m_parent, instance.path() );
+                               }
                        }
-               }
                };
 
                ParentSelectedBrushesToEntityWalker visitor( GlobalSelectionSystem().ultimateSelected().path() );
index 5d34645a8e4dccf267213cdaffe6b6687d386b8b..4a0c9b41b8d22d1d3b558c5bf3af834deda7d0a1 100644 (file)
@@ -60,36 +60,24 @@ select_workzone_t g_select_workzone;
  */
 class CollectSelectedBrushesBounds : public SelectionSystem::Visitor
 {
-AABB* m_bounds;     // array of AABBs
-Unsigned m_max;     // max AABB-elements in array
-Unsigned& m_count;  // count of valid AABBs stored in array
+       std::vector<AABB>& m_bounds;     // array of AABBs
 
 public:
-CollectSelectedBrushesBounds( AABB* bounds, Unsigned max, Unsigned& count )
-       : m_bounds( bounds ),
-       m_max( max ),
-       m_count( count ){
-       m_count = 0;
-}
-
-void visit( scene::Instance& instance ) const {
-       ASSERT_MESSAGE( m_count <= m_max, "Invalid m_count in CollectSelectedBrushesBounds" );
-
-       // stop if the array is already full
-       if ( m_count == m_max ) {
-               return;
+       CollectSelectedBrushesBounds( std::vector<AABB>& bounds )
+               : m_bounds( bounds )
+       {
+               m_bounds.clear();
        }
 
-       Selectable* selectable = Instance_getSelectable( instance );
-       if ( ( selectable != 0 )
-                && instance.isSelected() ) {
-               // brushes only
-               if ( Instance_getBrush( instance ) != 0 ) {
-                       m_bounds[m_count] = instance.worldAABB();
-                       ++m_count;
+       void visit( scene::Instance& instance ) const {
+               Selectable* selectable = Instance_getSelectable( instance );
+               if ( selectable && instance.isSelected() ) {
+                       // brushes only
+                       if ( Instance_getBrush( instance ) ) {
+                               m_bounds.push_back(instance.worldAABB());
+                       }
                }
        }
-}
 };
 
 /**
@@ -99,76 +87,66 @@ void visit( scene::Instance& instance ) const {
 template<class TSelectionPolicy>
 class SelectByBounds : public scene::Graph::Walker
 {
-AABB* m_aabbs;             // selection aabbs
-Unsigned m_count;          // number of aabbs in m_aabbs
-TSelectionPolicy policy;   // type that contains a custom intersection method aabb<->aabb
+       std::vector<AABB> m_aabbs; // selection aabbs
+       TSelectionPolicy policy;   // type that contains a custom intersection method aabb<->aabb
 
 public:
-SelectByBounds( AABB* aabbs, Unsigned count )
-       : m_aabbs( aabbs ),
-       m_count( count ){
-}
+       SelectByBounds( const std::vector<AABB>& aabbs )
+               : m_aabbs( aabbs )
+       {}
 
-bool pre( const scene::Path& path, scene::Instance& instance ) const {
-       Selectable* selectable = Instance_getSelectable( instance );
+       bool pre( const scene::Path& path, scene::Instance& instance ) const {
+               Selectable* selectable = Instance_getSelectable( instance );
 
-       // ignore worldspawn
-       Entity* entity = Node_getEntity( path.top() );
-       if ( entity ) {
-               if ( string_equal( entity->getKeyValue( "classname" ), "worldspawn" ) ) {
+               // ignore worldspawn
+               Entity* entity = Node_getEntity( path.top() );
+               if ( entity && 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 ( ( path.size() > 1 ) && ( !path.top().get().isRoot() ) && selectable )
                {
-                       if ( policy.Evaluate( m_aabbs[i], instance ) ) {
-                               selectable->setSelected( true );
+                       for ( const AABB& aabb : m_aabbs )
+                       {
+                               if ( policy.Evaluate( aabb, instance ) ) {
+                                       selectable->setSelected( true );
+                               }
                        }
                }
-       }
 
-       return true;
-}
+               return true;
+       }
 
-/**
-   Performs selection operation on the global scenegraph.
-   If delete_bounds_src is true, then the objects which were
-   used as source for the selection aabbs will be deleted.
- */
-static void DoSelection( bool delete_bounds_src = true ){
-       if ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) {
-               // we may not need all AABBs since not all selected objects have to be brushes
-               const Unsigned max = (Unsigned)GlobalSelectionSystem().countSelected();
-               AABB* aabbs = new AABB[max];
-
-               Unsigned count;
-               CollectSelectedBrushesBounds collector( aabbs, max, count );
-               GlobalSelectionSystem().foreachSelected( collector );
-
-               // nothing usable in selection
-               if ( !count ) {
-                       delete[] aabbs;
-                       return;
-               }
+       /**
+         Performs selection operation on the global scenegraph.
+         If delete_bounds_src is true, then the objects which were
+         used as source for the selection aabbs will be deleted.
+       */
+       static void DoSelection( bool delete_bounds_src = true ){
+               if ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) {
+                       // we may not need all AABBs since not all selected objects have to be brushes
+                       const Unsigned max = (Unsigned)GlobalSelectionSystem().countSelected();
+                       std::vector<AABB> aabbs(max);
+                       CollectSelectedBrushesBounds collector( aabbs );
+                       GlobalSelectionSystem().foreachSelected( collector );
+
+                       // nothing usable in selection
+                       if ( aabbs.empty() ) {
+                               return;
+                       }
 
-               // delete selected objects
-               if ( delete_bounds_src ) { // see deleteSelection
-                       UndoableCommand undo( "deleteSelected" );
-                       Select_Delete();
-               }
+                       // delete selected objects
+                       if ( delete_bounds_src ) { // see deleteSelection
+                               UndoableCommand undo( "deleteSelected" );
+                               Select_Delete();
+                       }
 
-               // select objects with bounds
-               GlobalSceneGraph().traverse( SelectByBounds<TSelectionPolicy>( aabbs, count ) );
+                       // select objects with bounds
+                       GlobalSceneGraph().traverse( SelectByBounds<TSelectionPolicy>( aabbs ) );
 
-               SceneChangeNotify();
-               delete[] aabbs;
+                       SceneChangeNotify();
+               }
        }
-}
 };
 
 /**
@@ -311,36 +289,38 @@ void Select_Invert(){
 
 class ExpandSelectionToEntitiesWalker : public scene::Graph::Walker
 {
-mutable std::size_t m_depth;
-NodeSmartReference worldspawn;
+       mutable std::size_t m_depth;
+       NodeSmartReference worldspawn;
 public:
-ExpandSelectionToEntitiesWalker() : m_depth( 0 ), worldspawn( Map_FindOrInsertWorldspawn( g_map ) ){
-}
-bool pre( const scene::Path& path, scene::Instance& instance ) const {
-       ++m_depth;
-
-       // ignore worldspawn
-       NodeSmartReference me( path.top().get() );
-       if ( me == worldspawn ) {
-               return false;
+       ExpandSelectionToEntitiesWalker()
+               : m_depth( 0 ),
+               worldspawn( Map_FindOrInsertWorldspawn( g_map ) ){
        }
+       bool pre( const scene::Path& path, scene::Instance& instance ) const {
+               ++m_depth;
 
-       if ( m_depth == 2 ) { // entity depth
-               // traverse and select children if any one is selected
-               if ( instance.childSelected() ) {
+               // ignore worldspawn
+               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
+                       if ( instance.childSelected() ) {
+                               Instance_setSelected( instance, true );
+                       }
+                       return Node_getEntity( path.top() )->isContainer() && instance.isSelected();
+               }
+               else if ( m_depth == 3 ) { // primitive depth
                        Instance_setSelected( instance, true );
+                       return false;
                }
-               return Node_getEntity( path.top() )->isContainer() && instance.isSelected();
+               return true;
        }
-       else if ( m_depth == 3 ) { // primitive depth
-               Instance_setSelected( instance, true );
-               return false;
+       void post( const scene::Path& path, scene::Instance& instance ) const {
+               --m_depth;
        }
-       return true;
-}
-void post( const scene::Path& path, scene::Instance& instance ) const {
-       --m_depth;
-}
 };
 
 void Scene_ExpandSelectionToEntities(){
index 2e481b409c0de96474f825615bea2d476c0dfe42..d39703a355a7f2fe8746aadd721b90d105d43b9d 100644 (file)
@@ -2804,11 +2804,12 @@ void SelectPoint( const View& view, const float device_point[2], const float dev
                        {
                                SelectableSortedSet::iterator best = selector.begin();
                                // toggle selection of the object with least depth
-                               if ( ( *best ).second->isSelected() ) {
-                                       ( *best ).second->setSelected( false );
+                               if ( best->second->isSelected() ) {
+                                       best->second->setSelected( false );
                                }
                                else{
-                                       ( *best ).second->setSelected( true );
+                                       best->second->setSelected( true );
+                                       /// \todo Might be cool to select the whole entity if all the children are selected
                                }
                        }
                        break;