diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index b3fbf59a87..3c9fe898eb 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -360,6 +360,7 @@ bool EDIT_TOOL::Init() menu.AddItem( PCB_ACTIONS::routerRouteSelected, isRoutable ); menu.AddItem( PCB_ACTIONS::routerRouteSelectedFromEnd, isRoutable ); menu.AddItem( PCB_ACTIONS::unrouteSelected, isRoutable ); + menu.AddItem( PCB_ACTIONS::unrouteSegment, isRoutable ); menu.AddItem( PCB_ACTIONS::routerAutorouteSelected, isRoutable ); menu.AddItem( PCB_ACTIONS::moveIndividually, SELECTION_CONDITIONS::MoreThan( 1 ) && notMovingCondition ); diff --git a/pcbnew/tools/pcb_actions.cpp b/pcbnew/tools/pcb_actions.cpp index ef1a62742e..bdd361c9f5 100644 --- a/pcbnew/tools/pcb_actions.cpp +++ b/pcbnew/tools/pcb_actions.cpp @@ -2173,6 +2173,14 @@ TOOL_ACTION PCB_ACTIONS::unrouteSelected( TOOL_ACTION_ARGS() .Tooltip( _( "Unroutes selected items to the nearest pad." ) ) .Icon( BITMAPS::general_deletions ) ); +TOOL_ACTION PCB_ACTIONS::unrouteSegment( TOOL_ACTION_ARGS() + .Name( "pcbnew.InteractiveSelection.unrouteSegment" ) + .Scope( AS_GLOBAL ) + .DefaultHotkey( WXK_BACK ) + .FriendlyName( _( "Unroute Segment" ) ) + .Tooltip( _( "Unroutes segment to the nearest segment." ) ) + .Icon( BITMAPS::general_deletions ) ); + TOOL_ACTION PCB_ACTIONS::syncSelection( TOOL_ACTION_ARGS() .Name( "pcbnew.InteractiveSelection.SyncSelection" ) .Scope( AS_GLOBAL ) ); diff --git a/pcbnew/tools/pcb_actions.h b/pcbnew/tools/pcb_actions.h index e4736cdefd..83e060c78c 100644 --- a/pcbnew/tools/pcb_actions.h +++ b/pcbnew/tools/pcb_actions.h @@ -75,6 +75,9 @@ public: /// Removes all tracks from the selected items to the first pad static TOOL_ACTION unrouteSelected; + /// Removes track segment from the selected item to the next segment + static TOOL_ACTION unrouteSegment; + /// Select all connections belonging to a single net. static TOOL_ACTION selectNet; diff --git a/pcbnew/tools/pcb_selection_tool.cpp b/pcbnew/tools/pcb_selection_tool.cpp index 8e42fb38a6..b319344b0e 100644 --- a/pcbnew/tools/pcb_selection_tool.cpp +++ b/pcbnew/tools/pcb_selection_tool.cpp @@ -1411,6 +1411,46 @@ int PCB_SELECTION_TOOL::unrouteSelected( const TOOL_EVENT& aEvent ) } +int PCB_SELECTION_TOOL::unrouteSegment( const TOOL_EVENT& aEvent ) +{ + std::deque selectedItems = m_selection.GetItems(); + + // Get all footprints and pads + std::vector toUnroute; + + for( EDA_ITEM* item : selectedItems ) + { + if( item->Type() == PCB_TRACE_T || item->Type() == PCB_ARC_T || item->Type() == PCB_VIA_T ) + { + toUnroute.push_back( static_cast( item ) ); + } + } + + // Get the tracks connecting to our starting objects + ClearSelection(); + selectAllConnectedTracks( toUnroute, STOP_CONDITION::STOP_AT_SEGMENT ); + std::deque toSelectAfter; + // This will select the unroute items too, so filter them out + for( EDA_ITEM* item : m_selection.GetItemsSortedByTypeAndXY() ) + { + if( std::find( toUnroute.begin(), toUnroute.end(), item ) == toUnroute.end() ) + toSelectAfter.push_back( item ); + } + + ClearSelection( true ); + for( EDA_ITEM* item : toUnroute ) + select( item ); + m_toolMgr->RunAction( ACTIONS::doDelete ); + + // Now our after tracks so the user can continue backing up as desired + ClearSelection( true ); + for( EDA_ITEM* item : toSelectAfter ) + select( item ); + + return 0; +} + + int PCB_SELECTION_TOOL::expandConnection( const TOOL_EVENT& aEvent ) { // expandConnection will get called no matter whether the user selected a connected item or a @@ -1506,13 +1546,8 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks( auto connectivity = board()->GetConnectivity(); - std::map> trackMap; - std::map viaMap; - std::map padMap; - std::map> shapeMap; - std::set startPadSet; - std::vector cleanupItems; - std::vector> activePts; + std::set startPadSet; + std::vector cleanupItems; for( BOARD_CONNECTED_ITEM* startItem : aStartItems ) { @@ -1527,6 +1562,12 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks( for( BOARD_CONNECTED_ITEM* startItem : aStartItems ) { + std::map> trackMap; + std::map viaMap; + std::map padMap; + std::map> shapeMap; + std::vector> activePts; + if( startItem->HasFlag( SKIP_STRUCT ) ) // Skip already visited items continue; @@ -1696,7 +1737,8 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks( else activePts.push_back( { track->GetStart(), track->GetLayerSet() } ); - expand = true; + if( aStopCondition != STOP_AT_SEGMENT ) + expand = true; } } @@ -1721,7 +1763,8 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks( activePts.push_back( { newPoint, shape->GetLayerSet() } ); } - expand = true; + if( aStopCondition != STOP_AT_SEGMENT ) + expand = true; } } @@ -1738,7 +1781,9 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks( cleanupItems.push_back( via ); activePts.push_back( { via->GetPosition(), via->GetLayerSet() } ); - expand = true; + + if( aStopCondition != STOP_AT_SEGMENT ) + expand = true; } } @@ -4126,6 +4171,7 @@ void PCB_SELECTION_TOOL::setTransitions() Go( &PCB_SELECTION_TOOL::filterSelection, PCB_ACTIONS::filterSelection.MakeEvent() ); Go( &PCB_SELECTION_TOOL::expandConnection, PCB_ACTIONS::selectConnection.MakeEvent() ); Go( &PCB_SELECTION_TOOL::unrouteSelected, PCB_ACTIONS::unrouteSelected.MakeEvent() ); + Go( &PCB_SELECTION_TOOL::unrouteSegment, PCB_ACTIONS::unrouteSegment.MakeEvent() ); Go( &PCB_SELECTION_TOOL::selectNet, PCB_ACTIONS::selectNet.MakeEvent() ); Go( &PCB_SELECTION_TOOL::selectNet, PCB_ACTIONS::deselectNet.MakeEvent() ); Go( &PCB_SELECTION_TOOL::selectUnconnected, PCB_ACTIONS::selectUnconnected.MakeEvent() ); diff --git a/pcbnew/tools/pcb_selection_tool.h b/pcbnew/tools/pcb_selection_tool.h index 1cf23ab7eb..1a74484491 100644 --- a/pcbnew/tools/pcb_selection_tool.h +++ b/pcbnew/tools/pcb_selection_tool.h @@ -319,6 +319,11 @@ private: */ int unrouteSelected( const TOOL_EVENT& aEvent ); + /** + * Unroute the selected track connected item. + */ + int unrouteSegment( const TOOL_EVENT& aEvent ); + /** * Select all copper connections belonging to the same net(s) as the items in the selection. */ @@ -343,6 +348,8 @@ private: * on another layer as well, but a via with only one connection will be selected. */ STOP_AT_JUNCTION, + /** Stop when reaching a segment (next track/arc/via). */ + STOP_AT_SEGMENT, /** Stop when reaching a pad. */ STOP_AT_PAD, /** Select the entire net. */