PNS: Allow dragging more than one footprint

Fixes https://gitlab.com/kicad/code/kicad/-/issues/11312
This commit is contained in:
Jon Evans 2023-09-18 22:36:57 -04:00
parent 5dc62368b0
commit 5a9c028e85
1 changed files with 107 additions and 79 deletions

View File

@ -2107,8 +2107,6 @@ bool ROUTER_TOOL::CanInlineDrag( int aDragMode )
NeighboringSegmentFilter ); NeighboringSegmentFilter );
const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection(); const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
if( selection.Size() == 1 )
{
const BOARD_ITEM* item = static_cast<const BOARD_ITEM*>( selection.Front() ); const BOARD_ITEM* item = static_cast<const BOARD_ITEM*>( selection.Front() );
// Note: EDIT_TOOL::Drag temporarily handles items of type PCB_ARC_T on its own using // Note: EDIT_TOOL::Drag temporarily handles items of type PCB_ARC_T on its own using
@ -2121,7 +2119,6 @@ bool ROUTER_TOOL::CanInlineDrag( int aDragMode )
else else
return true; return true;
} }
}
return false; return false;
} }
@ -2137,7 +2134,7 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
NeighboringSegmentFilter ); NeighboringSegmentFilter );
} }
if( selection.Size() != 1 ) if( selection.Empty() )
return 0; return 0;
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() ); BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
@ -2149,6 +2146,25 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
return 0; return 0;
} }
std::set<FOOTPRINT*> footprints;
// We can drag multiple footprints, but not a grab-bag of items
if( selection.Size() > 1 )
{
if( item->Type() != PCB_FOOTPRINT_T )
return 0;
footprints.insert( static_cast<FOOTPRINT*>( item ) );
for( int idx = 1; idx < selection.Size(); ++idx )
{
if( static_cast<BOARD_ITEM*>( selection.GetItem( idx ) )->Type() != PCB_FOOTPRINT_T )
return 0;
footprints.insert( static_cast<FOOTPRINT*>( selection.GetItem( idx ) ) );
}
}
// If we overrode locks, we want to clear the flag from the source item before SyncWorld is // If we overrode locks, we want to clear the flag from the source item before SyncWorld is
// called so that virtual vias are not generated for the (now unlocked) track segment. Note in // called so that virtual vias are not generated for the (now unlocked) track segment. Note in
// this case the lock can't be reliably re-applied, because there is no guarantee that the end // this case the lock can't be reliably re-applied, because there is no guarantee that the end
@ -2171,7 +2187,6 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
PNS::ITEM* startItem = nullptr; PNS::ITEM* startItem = nullptr;
PNS::ITEM_SET itemsToDrag; PNS::ITEM_SET itemsToDrag;
FOOTPRINT* footprint = nullptr;
bool showCourtyardConflicts = frame()->GetPcbNewSettings()->m_ShowCourtyardCollisions; bool showCourtyardConflicts = frame()->GetPcbNewSettings()->m_ShowCourtyardCollisions;
@ -2183,10 +2198,13 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
std::unique_ptr<CONNECTIVITY_DATA> dynamicData = nullptr; std::unique_ptr<CONNECTIVITY_DATA> dynamicData = nullptr;
VECTOR2I lastOffset; VECTOR2I lastOffset;
if( item->Type() == PCB_FOOTPRINT_T ) if( !footprints.empty() )
{ {
footprint = static_cast<FOOTPRINT*>( item ); if( showCourtyardConflicts )
courtyardClearanceDRC.Init( board() );
for( FOOTPRINT* footprint : footprints )
{
for( PAD* pad : footprint->Pads() ) for( PAD* pad : footprint->Pads() )
{ {
PNS::ITEM* solid = m_router->GetWorld()->FindItemByParent( pad ); PNS::ITEM* solid = m_router->GetWorld()->FindItemByParent( pad );
@ -2210,8 +2228,6 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
} }
if( showCourtyardConflicts ) if( showCourtyardConflicts )
{
courtyardClearanceDRC.Init( board() );
courtyardClearanceDRC.m_FpInMove.push_back( footprint ); courtyardClearanceDRC.m_FpInMove.push_back( footprint );
} }
@ -2241,8 +2257,10 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
if( m_startItem->Net() ) if( m_startItem->Net() )
highlightNets( true, { m_startItem->Net() } ); highlightNets( true, { m_startItem->Net() } );
} }
else if( footprint ) else if( !footprints.empty() )
{ {
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
// The mouse is going to be moved on grid before dragging begins. // The mouse is going to be moved on grid before dragging begins.
VECTOR2I tweakedMousePos; VECTOR2I tweakedMousePos;
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
@ -2319,13 +2337,15 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
updateEndItem( *evt ); updateEndItem( *evt );
m_router->Move( m_endSnapPoint, m_endItem ); m_router->Move( m_endSnapPoint, m_endItem );
if( footprint ) if( !footprints.empty() )
{ {
VECTOR2I offset = m_endSnapPoint - p; VECTOR2I offset = m_endSnapPoint - p;
BOARD_ITEM* previewItem; BOARD_ITEM* previewItem;
view()->ClearPreview(); view()->ClearPreview();
for( FOOTPRINT* footprint : footprints )
{
for( BOARD_ITEM* drawing : footprint->GraphicalItems() ) for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
{ {
previewItem = static_cast<BOARD_ITEM*>( drawing->Clone() ); previewItem = static_cast<BOARD_ITEM*>( drawing->Clone() );
@ -2364,10 +2384,15 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
view()->Hide( &footprint->Value() ); view()->Hide( &footprint->Value() );
if( showCourtyardConflicts ) if( showCourtyardConflicts )
{
footprint->Move( offset ); footprint->Move( offset );
}
if( showCourtyardConflicts )
{
courtyardClearanceDRC.Run(); courtyardClearanceDRC.Run();
courtyardClearanceDRC.UpdateConflicts( getView(), false ); courtyardClearanceDRC.UpdateConflicts( getView(), false );
for( FOOTPRINT* footprint : footprints )
footprint->Move( -offset ); footprint->Move( -offset );
} }
@ -2422,7 +2447,9 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
handleCommonEvents( *evt ); handleCommonEvents( *evt );
} }
if( footprint ) if( !footprints.empty() )
{
for( FOOTPRINT* footprint : footprints )
{ {
for( BOARD_ITEM* drawing : footprint->GraphicalItems() ) for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
view()->Hide( drawing, false ); view()->Hide( drawing, false );
@ -2432,6 +2459,7 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
for( PAD* pad : footprint->Pads() ) for( PAD* pad : footprint->Pads() )
view()->Hide( pad, false ); view()->Hide( pad, false );
}
view()->ClearPreview(); view()->ClearPreview();
view()->ShowPreview( false ); view()->ShowPreview( false );