diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index 8c11e93f2c..7ab5f192c0 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -924,6 +925,36 @@ void MODULE::RunOnChildren( const std::function& aFunction ) } } + +void MODULE::GetAllDrawingLayers( int aLayers[], int& aCount, bool aIncludePads ) const +{ + std::unordered_set layers; + + for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) + { + layers.insert( static_cast( item->GetLayer() ) ); + } + + if( aIncludePads ) + { + for( D_PAD* pad = m_Pads; pad; pad = pad->Next() ) + { + int pad_layers[KIGFX::VIEW::VIEW_MAX_LAYERS], pad_layers_count; + pad->ViewGetLayers( pad_layers, pad_layers_count ); + + for( int i = 0; i < pad_layers_count; i++ ) + layers.insert( pad_layers[i] ); + } + } + + aCount = layers.size(); + int i = 0; + + for( auto layer : layers ) + aLayers[i++] = layer; +} + + void MODULE::ViewGetLayers( int aLayers[], int& aCount ) const { aCount = 2; diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 0af3253014..8b82b69271 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -610,6 +610,15 @@ public: */ void RunOnChildren( const std::function& aFunction ); + /** + * Returns a set of all layers that this module has drawings on + * similar to ViewGetLayers() + * + * @param aLayers is an array to store layer ids + * @param aCount is the number of layers stored in the array + * @param aIncludePads controls whether to also include pad layers + */ + void GetAllDrawingLayers( int aLayers[], int& aCount, bool aIncludePads = true ) const; virtual void ViewGetLayers( int aLayers[], int& aCount ) const override; diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index aae688207f..a02efdee7d 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -1599,13 +1599,37 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const if( viewArea > 0.0 && modArea > viewArea ) return false; - if( aItem->IsOnLayer( F_Cu ) && board()->IsElementVisible( LAYER_MOD_FR ) ) - return !m_editModules; + // Allow selection of footprints if at least one draw layer is on and + // the appropriate LAYER_MOD is on - if( aItem->IsOnLayer( B_Cu ) && board()->IsElementVisible( LAYER_MOD_BK ) ) - return !m_editModules; + bool layer_mod = ( ( aItem->IsOnLayer( F_Cu ) && board()->IsElementVisible( LAYER_MOD_FR ) ) || + ( aItem->IsOnLayer( B_Cu ) && board()->IsElementVisible( LAYER_MOD_BK ) ) ); - return false; + bool draw_layer_visible = false; + int draw_layers[KIGFX::VIEW::VIEW_MAX_LAYERS], draw_layers_count; + + static_cast( aItem )->GetAllDrawingLayers( draw_layers, + draw_layers_count, + true ); + + for( int i = 0; i < draw_layers_count; ++i ) + { + // NOTE: Pads return LAYER_PADS_PLATEDHOLES but the visibility + // control only directly switches LAYER_PADS_TH, so we overwrite it + // here so that the visibility check is accurate + if( draw_layers[i] == LAYER_PADS_PLATEDHOLES ) + draw_layers[i] = LAYER_PADS_TH; + + if( ( ( draw_layers[i] < PCB_LAYER_ID_COUNT ) && + board()->IsLayerVisible( static_cast( draw_layers[i] ) ) ) || + ( ( draw_layers[i] >= GAL_LAYER_ID_START ) && + board()->IsElementVisible( static_cast( draw_layers[i] ) ) ) ) + { + draw_layer_visible = true; + } + } + + return ( draw_layer_visible && layer_mod ); break; }