diff --git a/pcbnew/collectors.cpp b/pcbnew/collectors.cpp index d7434b0332..ec39472bd6 100644 --- a/pcbnew/collectors.cpp +++ b/pcbnew/collectors.cpp @@ -271,10 +271,10 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* aTestItem, void* aTestData if( footprint ) { - if( m_Guide->IgnoreFootprintsOnBack() && ( footprint->GetLayer() == B_Cu ) ) + if( m_Guide->IgnoreFootprintsOnBack() && footprint->GetSide() == B_Cu ) return INSPECT_RESULT::CONTINUE; - if( m_Guide->IgnoreFootprintsOnFront() && ( footprint->GetLayer() == F_Cu ) ) + if( m_Guide->IgnoreFootprintsOnFront() && footprint->GetSide() == F_Cu ) return INSPECT_RESULT::CONTINUE; } diff --git a/pcbnew/dialogs/dialog_board_statistics.cpp b/pcbnew/dialogs/dialog_board_statistics.cpp index 7af477cfaf..a9e9f2d4d9 100644 --- a/pcbnew/dialogs/dialog_board_statistics.cpp +++ b/pcbnew/dialogs/dialog_board_statistics.cpp @@ -217,10 +217,13 @@ void DIALOG_BOARD_STATISTICS::getDataFromPCB() { if( ( footprint->GetAttributes() & line.attribute_mask ) == line.attribute_value ) { - if( footprint->IsFlipped() ) - line.backSideQty++; - else - line.frontSideQty++; + switch( footprint->GetSide() ) + { + case F_Cu: line.frontSideQty++; break; + case B_Cu: line.backSideQty++; break; + default: /* unsided: user-layers only, etc. */ break; + } + break; } } diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp index 02a74ee7f2..cdb280d1a9 100644 --- a/pcbnew/footprint.cpp +++ b/pcbnew/footprint.cpp @@ -989,6 +989,7 @@ const BOX2I FOOTPRINT::GetBoundingBox( bool aIncludeText, bool aIncludeInvisible std::vector texts; const BOARD* board = GetBoard(); bool isFPEdit = board && board->IsFootprintHolder(); + PCB_LAYER_ID footprintSide = GetSide(); if( board ) { @@ -1029,8 +1030,9 @@ const BOX2I FOOTPRINT::GetBoundingBox( bool aIncludeText, bool aIncludeInvisible continue; } - // If we're not including text then drop annotations as well - if( !aIncludeText ) + // If we're not including text then drop annotations as well -- unless, of course, it's + // an unsided footprint -- in which case it's likely to be nothing *but* annotations. + if( !aIncludeText && footprintSide != UNDEFINED_LAYER ) { if( BaseType( item->Type() ) == PCB_DIMENSION_T ) continue; @@ -1287,7 +1289,13 @@ void FOOTPRINT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vectorIsFootprintHolder() ) + return UNDEFINED_LAYER; + } + + // Test pads first; they're the most likely to return a quick answer. + for( PAD* pad : m_pads ) + { + if( ( LSET::SideSpecificMask() & pad->GetLayerSet() ).any() ) + return GetLayer(); + } + + for( BOARD_ITEM* item : m_drawings ) + { + if( LSET::SideSpecificMask().test( item->GetLayer() ) ) + return GetLayer(); + } + + for( ZONE* zone : m_zones ) + { + if( ( LSET::SideSpecificMask() & zone->GetLayerSet() ).any() ) + return GetLayer(); + } + + return UNDEFINED_LAYER; +} + + bool FOOTPRINT::IsOnLayer( PCB_LAYER_ID aLayer ) const { // If we have any pads, fall back on normal checking diff --git a/pcbnew/footprint.h b/pcbnew/footprint.h index e114b8a103..6bbaeb8547 100644 --- a/pcbnew/footprint.h +++ b/pcbnew/footprint.h @@ -350,6 +350,12 @@ public: */ bool IsFlipped() const { return GetLayer() == B_Cu; } + /** + * Use instead of IsFlipped() when you also need to account for unsided footprints (those + * purely on user-layers, etc.). + */ + PCB_LAYER_ID GetSide() const; + /** * @copydoc BOARD_ITEM::IsOnLayer */ diff --git a/pcbnew/tools/pcb_selection_tool.cpp b/pcbnew/tools/pcb_selection_tool.cpp index bfb8d479ca..d3ba808fa0 100644 --- a/pcbnew/tools/pcb_selection_tool.cpp +++ b/pcbnew/tools/pcb_selection_tool.cpp @@ -2605,16 +2605,20 @@ bool PCB_SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibili if( aItem->Type() == PCB_FOOTPRINT_T ) { + const FOOTPRINT* footprint = static_cast( aItem ); + // In footprint editor, we do not want to select the footprint itself. if( m_isFootprintEditor ) return false; // Allow selection of footprints if some part of the footprint is visible. - const FOOTPRINT* footprint = static_cast( aItem ); - LSET boardSide = footprint->IsFlipped() ? LSET::BackMask() : LSET::FrontMask(); + if( footprint->GetSide() != UNDEFINED_LAYER && !m_skip_heuristics ) + { + LSET boardSide = footprint->IsFlipped() ? LSET::BackMask() : LSET::FrontMask(); - if( !( visibleLayers() & boardSide ).any() && !m_skip_heuristics ) - return false; + if( !( visibleLayers() & boardSide ).any() ) + return false; + } // If the footprint has no items except the reference and value fields, include the // footprint in the selections.