From 5c1c24cdabf3daa4517ef4b9b976d28731672a24 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Thu, 24 Jun 2021 14:13:30 -0400 Subject: [PATCH] Pcbnew: fix footprint selection bug. Do not remove footprint objects from list of selected objects when there are no drawable objects other than the reference and value text. Increase the minimum size rectangle for footprints from 0.025mm to 1mm when the footprint has no drawing objects so that it is easier to select the footprint in this case. Add debugging code to show the footprint bounding box and polygon outline so that it's possible to tell the difference between selection areas. Fixes https://gitlab.com/kicad/code/kicad/-/issues/8379 --- pcbnew/class_module.cpp | 21 +++++++++++-------- pcbnew/pcb_painter.cpp | 37 ++++++++++++++++++++++++++++++++- pcbnew/tools/selection_tool.cpp | 10 +++++++-- 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index 4c34aef098..27c19deb8e 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -4,7 +4,7 @@ * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2015 Wayne Stambaugh - * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -460,7 +460,9 @@ EDA_RECT MODULE::GetFootprintRect() const area.SetOrigin( m_Pos ); area.SetEnd( m_Pos ); - area.Inflate( Millimeter2iu( 0.25 ) ); // Give a min size to the area + + // Give a minimum size to the area in case footprint has no drawing or pad objects. + area.Inflate( Millimeter2iu( 0.5 ) ); for( const BOARD_ITEM* item = m_Drawings.GetFirst(); item; item = item->Next() ) { @@ -479,13 +481,6 @@ const EDA_RECT MODULE::GetBoundingBox() const { EDA_RECT area = GetFootprintRect(); - // Add in items not collected by GetFootprintRect(): - for( const BOARD_ITEM* item = m_Drawings.GetFirst(); item; item = item->Next() ) - { - if( item->Type() != PCB_MODULE_EDGE_T ) - area.Merge( item->GetBoundingBox() ); - } - area.Merge( m_Value->GetBoundingBox() ); area.Merge( m_Reference->GetBoundingBox() ); @@ -529,6 +524,7 @@ SHAPE_POLY_SET MODULE::GetBoundingPoly() const poly.Append( p ); BOARD* board = GetBoard(); + if( board ) { int biggest_clearance = board->GetDesignSettings().GetBiggestClearanceValue(); @@ -650,13 +646,20 @@ bool MODULE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) co arect.Inflate( aAccuracy ); if( aContained ) + { return arect.Contains( m_BoundaryBox ); + } else { // If the rect does not intersect the bounding box, skip any tests if( !aRect.Intersects( GetBoundingBox() ) ) return false; + // If there are no drawing objects, there was still an intersection with the reference + // and/or value text. + if( m_Pads.GetCount() == 0 && m_Drawings.GetCount() == 0 ) + return true; + // Determine if any elements in the MODULE intersect the rect for( D_PAD* pad = m_Pads; pad; pad = pad->Next() ) { diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 50b4871cb4..b8a0b291c6 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -2,6 +2,8 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2013-2019 CERN + * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors. + * * @author Tomasz Wlostowski * @author Maciej Suminski * @@ -383,7 +385,40 @@ bool PCB_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer ) return false; } - return true; + // Draw bounding boxes after drawing objects so they can be seen. +#if 0 + // Show bounding boxes of painted objects for debugging. + EDA_RECT box = item->GetBoundingBox(); + m_gal->SetIsFill( false ); + m_gal->SetIsStroke( true ); + + if( item->Type() == PCB_MODULE_T ) + m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) : + COLOR4D( MAGENTA ) ); + else + m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) : + COLOR4D( 0.2, 0.2, 0.2, 1 ) ); + + m_gal->SetLineWidth( 1.5 / m_gal->GetWorldScale() ); + m_gal->DrawRectangle( box.GetOrigin(), box.GetEnd() ); + + if( item->Type() == PCB_MODULE_T ) + { + m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) : + COLOR4D( CYAN ) ); + + const MODULE* fp = static_cast( item ); + + if( fp ) + { + SHAPE_POLY_SET convex = fp->GetBoundingPoly(); + + m_gal->DrawPolyline( convex.COutline( 0 ) ); + } + } +#endif + +return true; } diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index 4282dd158f..c79a34fcd1 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -2,9 +2,10 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2013-2017 CERN + * Copyright (C) 2018-2021 KiCad Developers, see AUTHORS.txt for contributors. + * * @author Tomasz Wlostowski * @author Maciej Suminski - * Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -1701,9 +1702,14 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem, bool checkVisibilityOn return false; // Allow selection of footprints if some part of the footprint is visible. - MODULE* module = const_cast( static_cast( aItem ) ); + // If the footprint has no drawable items other than the reference and value test, + // then it can be selected. + if( ( module->GraphicalItemsList().GetCount() == 0 ) && + ( module->PadsList().GetCount() == 0 ) ) + return true; + for( auto item : module->GraphicalItems() ) { if( selectable( item, true ) )