diff --git a/pcbnew/router/length_tuner_tool.cpp b/pcbnew/router/length_tuner_tool.cpp index e3dd12f3df..b10082add3 100644 --- a/pcbnew/router/length_tuner_tool.cpp +++ b/pcbnew/router/length_tuner_tool.cpp @@ -109,10 +109,6 @@ LENGTH_TUNER_TOOL::~LENGTH_TUNER_TOOL() void LENGTH_TUNER_TOOL::Reset( RESET_REASON aReason ) { TOOL_BASE::Reset( aReason ); - - Go( &LENGTH_TUNER_TOOL::TuneSingleTrace, PCB_ACTIONS::routerActivateTuneSingleTrace.MakeEvent() ); - Go( &LENGTH_TUNER_TOOL::TuneDiffPair, PCB_ACTIONS::routerActivateTuneDiffPair.MakeEvent() ); - Go( &LENGTH_TUNER_TOOL::TuneDiffPairSkew, PCB_ACTIONS::routerActivateTuneDiffPairSkew.MakeEvent() ); } @@ -132,14 +128,14 @@ void LENGTH_TUNER_TOOL::performTuning() { if( m_startItem ) { - m_frame->SetActiveLayer( ToLAYER_ID ( m_startItem->Layers().Start() ) ); + frame()->SetActiveLayer( ToLAYER_ID ( m_startItem->Layers().Start() ) ); if( m_startItem->Net() >= 0 ) highlightNet( true, m_startItem->Net() ); } - m_ctls->ForceCursorPosition( false ); - m_ctls->SetAutoPan( true ); + controls()->ForceCursorPosition( false ); + controls()->SetAutoPan( true ); if( !m_router->StartRouting( m_startSnapPoint, m_startItem, 0 ) ) { @@ -155,7 +151,7 @@ void LENGTH_TUNER_TOOL::performTuning() VECTOR2I end( m_startSnapPoint ); - PNS_TUNE_STATUS_POPUP statusPopup( m_frame ); + PNS_TUNE_STATUS_POPUP statusPopup( frame() ); statusPopup.Popup(); m_router->Move( end, NULL ); @@ -210,27 +206,31 @@ void LENGTH_TUNER_TOOL::performTuning() int LENGTH_TUNER_TOOL::TuneSingleTrace( const TOOL_EVENT& aEvent ) { - m_frame->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Tune Trace Length" ) ); + frame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Tune Trace Length" ) ); return mainLoop( PNS::PNS_MODE_TUNE_SINGLE ); } int LENGTH_TUNER_TOOL::TuneDiffPair( const TOOL_EVENT& aEvent ) { - m_frame->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Tune Diff Pair Length" ) ); + frame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Tune Diff Pair Length" ) ); return mainLoop( PNS::PNS_MODE_TUNE_DIFF_PAIR ); } int LENGTH_TUNER_TOOL::TuneDiffPairSkew( const TOOL_EVENT& aEvent ) { - m_frame->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Tune Diff Pair Skew" ) ); + frame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Tune Diff Pair Skew" ) ); return mainLoop( PNS::PNS_MODE_TUNE_DIFF_PAIR_SKEW ); } void LENGTH_TUNER_TOOL::setTransitions() { + Go( &LENGTH_TUNER_TOOL::TuneSingleTrace, PCB_ACTIONS::routerActivateTuneSingleTrace.MakeEvent() ); + Go( &LENGTH_TUNER_TOOL::TuneDiffPair, PCB_ACTIONS::routerActivateTuneDiffPair.MakeEvent() ); + Go( &LENGTH_TUNER_TOOL::TuneDiffPairSkew, PCB_ACTIONS::routerActivateTuneDiffPairSkew.MakeEvent() ); + Go( &LENGTH_TUNER_TOOL::routerOptionsDialog, ACT_RouterOptions.MakeEvent() ); Go( &LENGTH_TUNER_TOOL::meanderSettingsDialog, ACT_Settings.MakeEvent() ); } @@ -245,9 +245,9 @@ int LENGTH_TUNER_TOOL::mainLoop( PNS::ROUTER_MODE aMode ) m_router->SetMode( aMode ); - m_ctls->SetSnapping( true ); - m_ctls->ShowCursor( true ); - m_frame->UndoRedoBlock( true ); + controls()->SetSnapping( true ); + controls()->ShowCursor( true ); + frame()->UndoRedoBlock( true ); std::unique_ptr ctxMenu( new TUNER_TOOL_MENU ); SetContextMenu( ctxMenu.get() ); @@ -270,8 +270,8 @@ int LENGTH_TUNER_TOOL::mainLoop( PNS::ROUTER_MODE aMode ) } } - m_frame->SetNoToolSelected(); - m_frame->UndoRedoBlock( false ); + frame()->SetNoToolSelected(); + frame()->UndoRedoBlock( false ); // Store routing settings till the next invocation m_savedSettings = m_router->Settings(); @@ -283,7 +283,7 @@ int LENGTH_TUNER_TOOL::mainLoop( PNS::ROUTER_MODE aMode ) int LENGTH_TUNER_TOOL::routerOptionsDialog( const TOOL_EVENT& aEvent ) { - DIALOG_PNS_SETTINGS settingsDlg( m_frame, m_router->Settings() ); + DIALOG_PNS_SETTINGS settingsDlg( frame(), m_router->Settings() ); if( settingsDlg.ShowModal() == wxID_OK ) { @@ -302,7 +302,7 @@ int LENGTH_TUNER_TOOL::meanderSettingsDialog( const TOOL_EVENT& aEvent ) return 0; PNS::MEANDER_SETTINGS settings = placer->MeanderSettings(); - DIALOG_PNS_LENGTH_TUNING_SETTINGS settingsDlg( m_frame, settings, m_router->Mode() ); + DIALOG_PNS_LENGTH_TUNING_SETTINGS settingsDlg( frame(), settings, m_router->Mode() ); if( settingsDlg.ShowModal() ) placer->UpdateSettings( settings ); diff --git a/pcbnew/router/pns_dragger.cpp b/pcbnew/router/pns_dragger.cpp index e12234e5c5..d8717e8733 100644 --- a/pcbnew/router/pns_dragger.cpp +++ b/pcbnew/router/pns_dragger.cpp @@ -30,7 +30,7 @@ DRAGGER::DRAGGER( ROUTER* aRouter ) : { m_world = NULL; m_lastNode = NULL; - m_mode = DRAG_SEGMENT; + m_mode = DM_SEGMENT; m_draggedVia = NULL; m_shove = NULL; m_draggedSegmentIndex = 0; @@ -62,14 +62,31 @@ bool DRAGGER::startDragSegment( const VECTOR2D& aP, SEGMENT* aSeg ) m_lastValidDraggedLine = m_draggedLine; m_lastValidDraggedLine.ClearSegmentLinks(); - if( ( aP - aSeg->Seg().A ).EuclideanNorm() <= w2 ) - m_mode = DRAG_CORNER; - else if( ( aP - aSeg->Seg().B ).EuclideanNorm() <= w2 ) + auto distA = ( aP - aSeg->Seg().A ).EuclideanNorm(); + auto distB = ( aP - aSeg->Seg().B ).EuclideanNorm(); + + + if( distA <= w2 ) + { + m_mode = DM_CORNER; + } + else if( distB <= w2 ) { m_draggedSegmentIndex++; - m_mode = DRAG_CORNER; - } else - m_mode = DRAG_SEGMENT; + m_mode = DM_CORNER; + } + else if ( m_freeAngleMode ) + { + if( distB < distA ) + { + m_draggedSegmentIndex++; + } + m_mode = DM_CORNER; + } + else + { + m_mode = DM_SEGMENT; + } return true; } @@ -79,7 +96,7 @@ bool DRAGGER::startDragVia( const VECTOR2D& aP, VIA* aVia ) { m_draggedVia = aVia; m_initialVia = aVia; - m_mode = DRAG_VIA; + m_mode = DM_VIA; VECTOR2I p0( aVia->Pos() ); JOINT* jt = m_world->FindJoint( p0, aVia->Layers().Start(), aVia->Net() ); @@ -112,6 +129,7 @@ bool DRAGGER::Start( const VECTOR2I& aP, ITEM* aStartItem ) m_lastNode = NULL; m_draggedItems.Clear(); m_currentMode = Settings().Mode(); + m_freeAngleMode = Settings().GetFreeAngleMode() || (m_mode & DM_FREE_ANGLE); aStartItem->Unmark( MK_LOCKED ); @@ -130,6 +148,10 @@ bool DRAGGER::Start( const VECTOR2I& aP, ITEM* aStartItem ) } } +void DRAGGER::SetMode( int aMode ) +{ + m_mode = aMode; +} bool DRAGGER::dragMarkObstacles( const VECTOR2I& aP ) { @@ -141,16 +163,16 @@ bool DRAGGER::dragMarkObstacles( const VECTOR2I& aP ) switch( m_mode ) { - case DRAG_SEGMENT: - case DRAG_CORNER: + case DM_SEGMENT: + case DM_CORNER: { int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0; LINE dragged( m_draggedLine ); - if( m_mode == DRAG_SEGMENT ) + if( m_mode == DM_SEGMENT ) dragged.DragSegment( aP, m_draggedSegmentIndex, thresh ); else - dragged.DragCorner( aP, m_draggedSegmentIndex, thresh ); + dragged.DragCorner( aP, m_draggedSegmentIndex, thresh, m_freeAngleMode ); m_lastNode = m_shove->CurrentNode()->Branch(); @@ -165,7 +187,7 @@ bool DRAGGER::dragMarkObstacles( const VECTOR2I& aP ) break; } - case DRAG_VIA: // fixme... + case DM_VIA: // fixme... { m_lastNode = m_shove->CurrentNode()->Branch(); dumbDragVia( m_initialVia, m_lastNode, aP ); @@ -205,7 +227,7 @@ void DRAGGER::dumbDragVia( VIA* aVia, NODE* aNode, const VECTOR2I& aP ) LINE origLine( *l ); LINE draggedLine( *l ); - draggedLine.DragCorner( aP, origLine.CLine().Find( aVia->Pos() ) ); + draggedLine.DragCorner( aP, origLine.CLine().Find( aVia->Pos() ), 0, m_freeAngleMode ); draggedLine.ClearSegmentLinks(); m_draggedItems.Add( draggedLine ); @@ -229,13 +251,13 @@ bool DRAGGER::dragShove( const VECTOR2I& aP ) switch( m_mode ) { - case DRAG_SEGMENT: - case DRAG_CORNER: + case DM_SEGMENT: + case DM_CORNER: { int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0; LINE dragged( m_draggedLine ); - if( m_mode == DRAG_SEGMENT ) + if( m_mode == DM_SEGMENT ) dragged.DragSegment( aP, m_draggedSegmentIndex, thresh ); else dragged.DragCorner( aP, m_draggedSegmentIndex, thresh ); @@ -264,7 +286,7 @@ bool DRAGGER::dragShove( const VECTOR2I& aP ) break; } - case DRAG_VIA: + case DM_VIA: { VIA* newVia; SHOVE::SHOVE_STATUS st = m_shove->ShoveDraggingVia( m_draggedVia, aP, &newVia ); @@ -305,6 +327,9 @@ bool DRAGGER::FixRoute() bool DRAGGER::Drag( const VECTOR2I& aP ) { + if( m_freeAngleMode ) + return dragMarkObstacles( aP ); + switch( m_currentMode ) { case RM_MarkObstacles: diff --git a/pcbnew/router/pns_dragger.h b/pcbnew/router/pns_dragger.h index 3aae5eddbc..90e00cb740 100644 --- a/pcbnew/router/pns_dragger.h +++ b/pcbnew/router/pns_dragger.h @@ -97,12 +97,10 @@ public: /// @copydoc ALGO_BASE::Logger() virtual LOGGER* Logger() override; + void SetMode( int aDragMode ); + private: - enum DragMode { - DRAG_CORNER = 0, - DRAG_SEGMENT, - DRAG_VIA - }; + bool dragMarkObstacles( const VECTOR2I& aP ); bool dragShove(const VECTOR2I& aP ); @@ -112,7 +110,7 @@ private: NODE* m_world; NODE* m_lastNode; - DragMode m_mode; + int m_mode; LINE m_draggedLine; VIA* m_draggedVia; LINE m_lastValidDraggedLine; @@ -123,6 +121,7 @@ private: ITEM_SET m_origViaConnections; VIA* m_initialVia; ITEM_SET m_draggedItems; + bool m_freeAngleMode; }; } diff --git a/pcbnew/router/pns_line.cpp b/pcbnew/router/pns_line.cpp index 24e457e02a..4d84889ad1 100644 --- a/pcbnew/router/pns_line.cpp +++ b/pcbnew/router/pns_line.cpp @@ -405,7 +405,7 @@ SHAPE_LINE_CHAIN dragCornerInternal( const SHAPE_LINE_CHAIN& aOrigin, const VECT } -void LINE::DragCorner( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ) +void LINE::dragCorner45( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ) { SHAPE_LINE_CHAIN path; @@ -429,6 +429,37 @@ void LINE::DragCorner( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ) } +void LINE::dragCornerFree( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ) +{ + m_line.Point( aIndex ) = aP; + m_line.Simplify(); +} + +void LINE::DragCorner( const VECTOR2I& aP, int aIndex, int aSnappingThreshold, bool aFreeAngle ) +{ + if( aFreeAngle ) + { + dragCornerFree ( aP, aIndex, aSnappingThreshold ); + } + else + { + dragCorner45 ( aP, aIndex, aSnappingThreshold ); + } +} + +void LINE::DragSegment( const VECTOR2I& aP, int aIndex, int aSnappingThreshold, bool aFreeAngle ) +{ + if( aFreeAngle ) + { + assert( false ); + } + else + { + dragSegment45 ( aP, aIndex, aSnappingThreshold ); + } +} + + VECTOR2I LINE::snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I& aP, int aIndex, int aThreshold ) const { @@ -517,7 +548,7 @@ VECTOR2I LINE::snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VEC } -void LINE::DragSegment( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ) +void LINE::dragSegment45( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ) { SHAPE_LINE_CHAIN path( m_line ); VECTOR2I target( aP ); diff --git a/pcbnew/router/pns_line.h b/pcbnew/router/pns_line.h index 076540ec57..c972833e03 100644 --- a/pcbnew/router/pns_line.h +++ b/pcbnew/router/pns_line.h @@ -256,8 +256,8 @@ public: virtual void Unmark( int aMarker = -1 ) override; virtual int Marker() const override; - void DragSegment( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 ); - void DragCorner( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 ); + void DragSegment( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0, bool aFreeAngle = false ); + void DragCorner( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0, bool aFreeAngle = false ); void SetRank( int aRank ) override; int Rank() const override; @@ -268,6 +268,12 @@ public: OPT_BOX2I ChangedArea( const LINE* aOther ) const; private: + + void dragSegment45( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ); + void dragCorner45( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ); + void dragSegmentFree( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ); + void dragCornerFree( const VECTOR2I& aP, int aIndex, int aSnappingThreshold ); + VECTOR2I snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, int aIndex, int aThreshold) const; diff --git a/pcbnew/router/pns_line_placer.cpp b/pcbnew/router/pns_line_placer.cpp index 5704e03ecf..f1cd748e17 100644 --- a/pcbnew/router/pns_line_placer.cpp +++ b/pcbnew/router/pns_line_placer.cpp @@ -800,18 +800,18 @@ NODE* LINE_PLACER::CurrentNode( bool aLoopsRemoved ) const } -void LINE_PLACER::splitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I& aP ) +bool LINE_PLACER::SplitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I& aP ) { if( !aSeg ) - return; + return false; if( !aSeg->OfKind( ITEM::SEGMENT_T ) ) - return; + return false; JOINT* jt = aNode->FindJoint( aP, aSeg ); if( jt && jt->LinkCount() >= 1 ) - return; + return false; SEGMENT* s_old = static_cast( aSeg ); @@ -826,6 +826,8 @@ void LINE_PLACER::splitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I aNode->Remove( s_old ); aNode->Add( std::move( s_new[0] ), true ); aNode->Add( std::move( s_new[1] ), true ); + + return true; } @@ -901,7 +903,7 @@ void LINE_PLACER::initPlacement() world->KillChildren(); NODE* rootNode = world->Branch(); - splitAdjacentSegments( rootNode, m_startItem, m_currentStart ); + SplitAdjacentSegments( rootNode, m_startItem, m_currentStart ); setWorld( rootNode ); @@ -950,7 +952,7 @@ bool LINE_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem ) if( eiDepth >= 0 && aEndItem && latestNode->Depth() > eiDepth && current.SegmentCount() ) { - splitAdjacentSegments( m_lastNode, aEndItem, current.CPoint( -1 ) ); + SplitAdjacentSegments( m_lastNode, aEndItem, current.CPoint( -1 ) ); if( Settings().RemoveLoops() ) removeLoops( m_lastNode, current ); diff --git a/pcbnew/router/pns_line_placer.h b/pcbnew/router/pns_line_placer.h index 1ab062cdb0..21a07c0b75 100644 --- a/pcbnew/router/pns_line_placer.h +++ b/pcbnew/router/pns_line_placer.h @@ -189,6 +189,14 @@ public: LOGGER* Logger() override; + /** + * Function SplitAdjacentSegments() + * + * Checks if point aP lies on segment aSeg. If so, splits the segment in two, + * forming a joint at aP and stores updated topology in node aNode. + */ + bool SplitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I& aP ); + private: /** @@ -234,14 +242,6 @@ private: */ void setInitialDirection( const DIRECTION_45& aDirection ); - /** - * Function splitAdjacentSegments() - * - * Checks if point aP lies on segment aSeg. If so, splits the segment in two, - * forming a joint at aP and stores updated topology in node aNode. - */ - void splitAdjacentSegments( NODE* aNode, ITEM* aSeg, const VECTOR2I& aP ); - /** * Function removeLoops() * diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index c4d2cb7e99..d7b6c544e8 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -124,12 +124,19 @@ const ITEM_SET ROUTER::QueryHoverItems( const VECTOR2I& aP ) } -bool ROUTER::StartDragging( const VECTOR2I& aP, ITEM* aStartItem ) +bool ROUTER::StartDragging( const VECTOR2I& aP, ITEM* aStartItem, int aDragMode ) { + + if( aDragMode & DM_FREE_ANGLE ) + m_forceMarkObstaclesMode = true; + else + m_forceMarkObstaclesMode = false; + if( !aStartItem || aStartItem->OfKind( ITEM::SOLID_T ) ) return false; m_dragger.reset( new DRAGGER( this ) ); + m_dragger->SetMode( aDragMode ); m_dragger->SetWorld( m_world.get() ); m_dragger->SetDebugDecorator ( m_iface->GetDebugDecorator () ); @@ -148,6 +155,8 @@ bool ROUTER::StartDragging( const VECTOR2I& aP, ITEM* aStartItem ) bool ROUTER::StartRouting( const VECTOR2I& aP, ITEM* aStartItem, int aLayer ) { + m_forceMarkObstaclesMode = false; + switch( m_mode ) { case PNS_MODE_ROUTE_SINGLE: @@ -262,7 +271,7 @@ void ROUTER::updateView( NODE* aNode, ITEM_SET& aCurrent ) if( !aNode ) return; - if( Settings().Mode() == RM_MarkObstacles ) + if( Settings().Mode() == RM_MarkObstacles || m_forceMarkObstaclesMode ) markViolations( aNode, aCurrent, removed ); aNode->GetUpdatedItems( removed, added ); @@ -486,4 +495,21 @@ void ROUTER::SetInterface( ROUTER_IFACE *aIface ) m_iface->SetRouter( this ); } +void ROUTER::BreakSegment( ITEM *aItem, const VECTOR2I& aP ) +{ + NODE *node = m_world->Branch(); + + LINE_PLACER placer( this ); + + if ( placer.SplitAdjacentSegments( node, aItem, aP ) ) + { + CommitRouting( node ); + } + else + { + delete node; + } + +} + } diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index 5454243b67..2368ce8378 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -69,6 +69,14 @@ enum ROUTER_MODE { PNS_MODE_TUNE_DIFF_PAIR_SKEW }; +enum DRAG_MODE +{ + DM_CORNER = 0x1, + DM_SEGMENT = 0x2, + DM_VIA = 0x4, + DM_FREE_ANGLE = 0x8, + DM_ANY = 0x7 +}; /** * Class ROUTER * @@ -126,6 +134,7 @@ public: bool StartRouting( const VECTOR2I& aP, ITEM* aItem, int aLayer ); void Move( const VECTOR2I& aP, ITEM* aItem ); bool FixRoute( const VECTOR2I& aP, ITEM* aItem ); + void BreakSegment( ITEM *aItem, const VECTOR2I& aP ); void StopRouting(); @@ -161,7 +170,7 @@ public: const ITEM_SET QueryHoverItems( const VECTOR2I& aP ); const VECTOR2I SnapToItem( ITEM* aItem, VECTOR2I aP, bool& aSplitsSegment ); - bool StartDragging( const VECTOR2I& aP, ITEM* aItem ); + bool StartDragging( const VECTOR2I& aP, ITEM* aItem, int aDragMode = DM_ANY ); void SetIterLimit( int aX ) { m_iterLimit = aX; } int GetIterLimit() const { return m_iterLimit; }; @@ -253,6 +262,7 @@ private: bool m_showInterSteps; int m_snapshotIter; bool m_violation; + bool m_forceMarkObstaclesMode = false; ROUTING_SETTINGS m_settings; SIZES_SETTINGS m_sizes; diff --git a/pcbnew/router/pns_routing_settings.cpp b/pcbnew/router/pns_routing_settings.cpp index 62147a2f57..9cba63334b 100644 --- a/pcbnew/router/pns_routing_settings.cpp +++ b/pcbnew/router/pns_routing_settings.cpp @@ -45,6 +45,8 @@ ROUTING_SETTINGS::ROUTING_SETTINGS() m_canViolateDRC = false; m_freeAngleMode = false; m_inlineDragEnabled = false; + m_snapToTracks = false; + m_snapToPads = false; } diff --git a/pcbnew/router/pns_routing_settings.h b/pcbnew/router/pns_routing_settings.h index 1aefa736d9..8615c05591 100644 --- a/pcbnew/router/pns_routing_settings.h +++ b/pcbnew/router/pns_routing_settings.h @@ -136,6 +136,12 @@ public: void SetInlineDragEnabled ( bool aEnable ) { m_inlineDragEnabled = aEnable; } bool InlineDragEnabled() const { return m_inlineDragEnabled; } + void SetSnapToTracks( bool aSnap ) { m_snapToTracks = aSnap; } + void SetSnapToPads( bool aSnap ) { m_snapToPads = aSnap; } + + bool GetSnapToTracks() const { return m_snapToTracks; } + bool GetSnapToPads() const { return m_snapToPads; } + private: bool m_shoveVias; bool m_startDiagonal; @@ -148,6 +154,8 @@ private: bool m_canViolateDRC; bool m_freeAngleMode; bool m_inlineDragEnabled; + bool m_snapToTracks; + bool m_snapToPads; PNS_MODE m_routingMode; PNS_OPTIMIZATION_EFFORT m_optimizerEffort; diff --git a/pcbnew/router/pns_tool_base.cpp b/pcbnew/router/pns_tool_base.cpp index 18cc53c776..7d33e72549 100644 --- a/pcbnew/router/pns_tool_base.cpp +++ b/pcbnew/router/pns_tool_base.cpp @@ -68,7 +68,7 @@ TOOL_ACTION TOOL_BASE::ACT_RouterOptions( "pcbnew.InteractiveRouter.RouterOption TOOL_BASE::TOOL_BASE( const std::string& aToolName ) : - TOOL_INTERACTIVE( aToolName ) + PCB_TOOL( aToolName ) { m_gridHelper = nullptr; m_iface = nullptr; @@ -78,10 +78,6 @@ TOOL_BASE::TOOL_BASE( const std::string& aToolName ) : m_startLayer = 0; m_endItem = nullptr; - - m_frame = nullptr; - m_ctls = nullptr; - m_board = nullptr; m_gridHelper = nullptr; } @@ -101,23 +97,19 @@ void TOOL_BASE::Reset( RESET_REASON aReason ) delete m_iface; delete m_router; - m_frame = getEditFrame(); - m_ctls = getViewControls(); - m_board = getModel(); - m_iface = new PNS_KICAD_IFACE; - m_iface->SetBoard( m_board ); + m_iface->SetBoard( board() ); m_iface->SetView( getView() ); - m_iface->SetHostFrame( m_frame ); + m_iface->SetHostFrame( frame() ); m_router = new ROUTER; - m_router->SetInterface(m_iface); + m_router->SetInterface( m_iface ); m_router->ClearWorld(); m_router->SyncWorld(); m_router->LoadSettings( m_savedSettings ); m_router->UpdateSizes( m_savedSizes ); - m_gridHelper = new GRID_HELPER( m_frame ); + m_gridHelper = new GRID_HELPER( frame() ); } @@ -206,11 +198,38 @@ void TOOL_BASE::highlightNet( bool aEnabled, int aNetcode ) getView()->UpdateAllLayersColor(); } +bool TOOL_BASE::checkSnap( ITEM *aItem ) +{ + bool doSnap = false; + + // Sync PNS engine settings with the general PCB editor options. I know the code below is awful, but... + auto& pnss = m_router->Settings(); + const auto& gens = frame()->Settings(); + + pnss.SetSnapToTracks( false ); + pnss.SetSnapToPads( false ); + + if( gens.m_magneticPads == CAPTURE_CURSOR_IN_TRACK_TOOL || gens.m_magneticPads == CAPTURE_ALWAYS ) + pnss.SetSnapToPads( true ); + + if( gens.m_magneticTracks == CAPTURE_CURSOR_IN_TRACK_TOOL || gens.m_magneticTracks == CAPTURE_ALWAYS ) + pnss.SetSnapToTracks( true ); + + if( aItem ) + { + if( ( aItem->OfKind( ITEM::VIA_T ) || aItem->OfKind( ITEM::SEGMENT_T ) ) && pnss.GetSnapToTracks() ) + doSnap = true; + else if( aItem->OfKind( ITEM::SOLID_T ) && pnss.GetSnapToPads() ) + doSnap = true; + } + + return doSnap; +} void TOOL_BASE::updateStartItem( TOOL_EVENT& aEvent ) { int tl = getView()->GetTopLayer(); - VECTOR2I cp = m_ctls->GetCursorPosition(); + VECTOR2I cp = controls()->GetCursorPosition(); VECTOR2I p; bool snapEnabled = true; @@ -231,20 +250,21 @@ void TOOL_BASE::updateStartItem( TOOL_EVENT& aEvent ) m_startItem = nullptr; m_startSnapPoint = snapToItem( snapEnabled, m_startItem, p ); - m_ctls->ForceCursorPosition( true, m_startSnapPoint ); + + controls()->ForceCursorPosition( true, checkSnap( m_startItem ) ? m_startSnapPoint : p ); } void TOOL_BASE::updateEndItem( const TOOL_EVENT& aEvent ) { - VECTOR2I p = m_ctls->GetMousePosition(); + VECTOR2I p = controls()->GetMousePosition(); int layer; bool snapEnabled = !aEvent.Modifier( MD_SHIFT ); if( m_router->GetCurrentNets().empty() || m_router->GetCurrentNets().front() < 0 ) { m_endSnapPoint = snapToItem( snapEnabled, nullptr, p ); - m_ctls->ForceCursorPosition( true, m_endSnapPoint ); + controls()->ForceCursorPosition( true, m_endSnapPoint ); m_endItem = nullptr; return; @@ -267,10 +287,16 @@ void TOOL_BASE::updateEndItem( const TOOL_EVENT& aEvent ) break; } - VECTOR2I cursorPos = snapToItem( snapEnabled, endItem, p ); - m_ctls->ForceCursorPosition( true, cursorPos ); - m_endItem = endItem; - m_endSnapPoint = cursorPos; + if( checkSnap( endItem ) ) + { + VECTOR2I cursorPos = snapToItem( snapEnabled, endItem, p ); + controls()->ForceCursorPosition( true, checkSnap( endItem ) ? cursorPos : p ); + m_endItem = endItem; + m_endSnapPoint = cursorPos; + } else { + m_endItem = nullptr; + m_endSnapPoint = p; + } if( m_endItem ) { diff --git a/pcbnew/router/pns_tool_base.h b/pcbnew/router/pns_tool_base.h index 8974aa42d0..327c7ac332 100644 --- a/pcbnew/router/pns_tool_base.h +++ b/pcbnew/router/pns_tool_base.h @@ -41,7 +41,7 @@ class PNS_TUNE_STATUS_POPUP; namespace PNS { -class APIEXPORT TOOL_BASE : public TOOL_INTERACTIVE +class APIEXPORT TOOL_BASE : public PCB_TOOL { public: static TOOL_ACTION ACT_RouterOptions; @@ -51,14 +51,10 @@ public: virtual void Reset( RESET_REASON aReason ) override; - const ROUTING_SETTINGS& PNSSettings() const - { - return m_savedSettings; - } - ROUTER* Router() const; protected: + bool checkSnap( ITEM* aItem ); const VECTOR2I snapToItem( bool aEnabled, ITEM* aItem, VECTOR2I aP); virtual ITEM* pickSingleItem( const VECTOR2I& aWhere, int aNet = -1, int aLayer = -1 ); virtual void highlightNet( bool aEnabled, int aNetcode = -1 ); @@ -77,9 +73,6 @@ protected: ITEM* m_endItem; VECTOR2I m_endSnapPoint; - PCB_EDIT_FRAME* m_frame; - KIGFX::VIEW_CONTROLS* m_ctls; - BOARD* m_board; GRID_HELPER* m_gridHelper; PNS_KICAD_IFACE* m_iface; ROUTER* m_router; diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index 25664ddafb..7dbef655ba 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -112,10 +112,28 @@ TOOL_ACTION PCB_ACTIONS::routerActivateTuneDiffPairSkew( "pcbnew.LengthTuner.Tun _( "Tune skew of a differential pair" ), "", NULL, AF_ACTIVATE ); TOOL_ACTION PCB_ACTIONS::routerInlineDrag( "pcbnew.InteractiveRouter.InlineDrag", - AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DRAG_TRACK_KEEP_SLOPE ), + AS_CONTEXT, 0, _( "Drag Track/Via" ), _( "Drags tracks and vias without breaking connections" ), drag_xpm ); +TOOL_ACTION PCB_ACTIONS::breakTrack( "pcbnew.InteractiveRouter.BreakTrack", + AS_GLOBAL, 0, + _( "Break Track" ), + _( "Splits the track segment into two segments connected at the cursor position." ), + break_line_xpm ); + +TOOL_ACTION PCB_ACTIONS::drag45Degree( "pcbnew.InteractiveRouter.Drag45Degree", + AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DRAG_TRACK_KEEP_SLOPE ), + _( "Drag (45 degree mode)" ), + _( "todo" ), + drag_segment_withslope_xpm ); + +TOOL_ACTION PCB_ACTIONS::dragFreeAngle( "pcbnew.InteractiveRouter.DragFreeAngle", + AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DRAG_ITEM ), + _( "Drag (free angle)" ), + _( "todo" ), + move_xpm ); + static const TOOL_ACTION ACT_NewTrack( "pcbnew.InteractiveRouter.NewTrack", AS_CONTEXT, TOOL_ACTION::LegacyHotKey( HK_ADD_NEW_TRACK ), _( "New Track" ), _( "Starts laying a new track." ), add_tracks_xpm ); @@ -180,7 +198,6 @@ static const TOOL_ACTION ACT_SetDpDimensions( "pcbnew.InteractiveRouter.SetDpDim _( "Sets the width and gap of the currently routed differential pair." ), ps_diff_pair_tune_length_xpm ); - ROUTER_TOOL::ROUTER_TOOL() : TOOL_BASE( "pcbnew.InteractiveRouter" ) { @@ -300,6 +317,11 @@ public: Add( ACT_NewTrack ); Add( ACT_EndTrack ); + Add( PCB_ACTIONS::breakTrack ); + + Add( PCB_ACTIONS::drag45Degree ); + Add( PCB_ACTIONS::dragFreeAngle ); + // Add( ACT_AutoEndRoute ); // fixme: not implemented yet. Sorry. Add( ACT_PlaceThroughVia ); Add( ACT_PlaceBlindVia ); @@ -349,12 +371,6 @@ ROUTER_TOOL::~ROUTER_TOOL() bool ROUTER_TOOL::Init() { - // Track & via dragging menu entry - auto selectionTool = m_toolMgr->GetTool(); - CONDITIONAL_MENU& menu = selectionTool->GetToolMenu().GetMenu(); - menu.AddItem( PCB_ACTIONS::routerInlineDrag, SELECTION_CONDITIONS::Count( 1 ) - && SELECTION_CONDITIONS::OnlyTypes( { PCB_TRACE_T, PCB_VIA_T, EOT } ) ); - m_savedSettings.Load( GetSettings() ); return true; } @@ -379,10 +395,10 @@ int ROUTER_TOOL::getDefaultWidth( int aNetCode ) void ROUTER_TOOL::getNetclassDimensions( int aNetCode, int& aWidth, int& aViaDiameter, int& aViaDrill ) { - BOARD_DESIGN_SETTINGS &bds = m_board->GetDesignSettings(); + BOARD_DESIGN_SETTINGS &bds = board()->GetDesignSettings(); NETCLASSPTR netClass; - NETINFO_ITEM* ni = m_board->FindNet( aNetCode ); + NETINFO_ITEM* ni = board()->FindNet( aNetCode ); if( ni ) { @@ -436,7 +452,7 @@ int ROUTER_TOOL::getStartLayer( const PNS::ITEM* aItem ) void ROUTER_TOOL::switchLayerOnViaPlacement() { - int al = m_frame->GetActiveLayer(); + int al = frame()->GetActiveLayer(); int cl = m_router->GetCurrentLayer(); if( cl != al ) @@ -450,7 +466,7 @@ void ROUTER_TOOL::switchLayerOnViaPlacement() newLayer = m_router->Sizes().GetLayerTop(); m_router->SwitchLayer( *newLayer ); - m_frame->SetActiveLayer( ToLAYER_ID( *newLayer ) ); + frame()->SetActiveLayer( ToLAYER_ID( *newLayer ) ); } @@ -486,12 +502,12 @@ int ROUTER_TOOL::onViaCommand( const TOOL_EVENT& aEvent ) VIATYPE_T viaType = getViaTypeFromFlags( actViaFlags ); const bool selectLayer = actViaFlags & VIA_ACTION_FLAGS::SELECT_LAYER; - BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); + BOARD_DESIGN_SETTINGS& bds = board()->GetDesignSettings(); const int layerCount = bds.GetCopperLayerCount(); int currentLayer = m_router->GetCurrentLayer(); - PCB_LAYER_ID pairTop = m_frame->GetScreen()->m_Route_Layer_TOP; - PCB_LAYER_ID pairBottom = m_frame->GetScreen()->m_Route_Layer_BOTTOM; + PCB_LAYER_ID pairTop = frame()->GetScreen()->m_Route_Layer_TOP; + PCB_LAYER_ID pairBottom = frame()->GetScreen()->m_Route_Layer_BOTTOM; PNS::SIZES_SETTINGS sizes = m_router->Sizes(); @@ -502,7 +518,7 @@ int ROUTER_TOOL::onViaCommand( const TOOL_EVENT& aEvent ) { wxPoint dlgPosition = wxGetMousePosition(); - targetLayer = m_frame->SelectLayer( static_cast( currentLayer ), + targetLayer = frame()->SelectLayer( static_cast( currentLayer ), LSET::AllNonCuMask(), dlgPosition ); } @@ -514,27 +530,27 @@ int ROUTER_TOOL::onViaCommand( const TOOL_EVENT& aEvent ) // Cannot place microvias or blind vias if not allowed (obvious) if( ( viaType == VIA_BLIND_BURIED ) && ( !bds.m_BlindBuriedViaAllowed ) ) { - DisplayError( m_frame, _( "Blind/buried vias have to be enabled in the design settings." ) ); + DisplayError( frame(), _( "Blind/buried vias have to be enabled in the design settings." ) ); return false; } if( ( viaType == VIA_MICROVIA ) && ( !bds.m_MicroViasAllowed ) ) { - DisplayError( m_frame, _( "Microvias have to be enabled in the design settings." ) ); + DisplayError( frame(), _( "Microvias have to be enabled in the design settings." ) ); return false; } // Can only place through vias on 2-layer boards if( ( viaType != VIA_THROUGH ) && ( layerCount <= 2 ) ) { - DisplayError( m_frame, _( "Only through vias are allowed on 2 layer boards." ) ); + DisplayError( frame(), _( "Only through vias are allowed on 2 layer boards." ) ); return false; } // Can only place microvias if we're on an outer layer, or directly adjacent to one if( ( viaType == VIA_MICROVIA ) && ( currentLayer > In1_Cu ) && ( currentLayer < layerCount - 2 ) ) { - DisplayError( m_frame, _( "Microvias can be placed only between the outer layers " \ + DisplayError( frame(), _( "Microvias can be placed only between the outer layers " \ "(F.Cu/B.Cu) and the ones directly adjacent to them." ) ); return false; } @@ -638,11 +654,11 @@ bool ROUTER_TOOL::prepareInteractive() if( !IsCopperLayer( routingLayer ) ) { - DisplayError( m_frame, _( "Tracks on Copper layers only" ) ); + DisplayError( frame(), _( "Tracks on Copper layers only" ) ); return false; } - m_frame->SetActiveLayer( ToLAYER_ID( routingLayer ) ); + frame()->SetActiveLayer( ToLAYER_ID( routingLayer ) ); // fixme: switch on invisible layer @@ -652,24 +668,24 @@ bool ROUTER_TOOL::prepareInteractive() { highlightNet( true, m_startItem->Net() ); // Update track width and via size shown in main toolbar comboboxes - m_frame->SetCurrentNetClass( m_startItem->Parent()->GetNetClass()->GetName() ); + frame()->SetCurrentNetClass( m_startItem->Parent()->GetNetClass()->GetName() ); } else - m_frame->SetCurrentNetClass( NETCLASS::Default ); + frame()->SetCurrentNetClass( NETCLASS::Default ); - m_ctls->ForceCursorPosition( false ); - m_ctls->SetAutoPan( true ); + controls()->ForceCursorPosition( false ); + controls()->SetAutoPan( true ); PNS::SIZES_SETTINGS sizes( m_router->Sizes() ); - sizes.Init( m_board, m_startItem ); - sizes.AddLayerPair( m_frame->GetScreen()->m_Route_Layer_TOP, - m_frame->GetScreen()->m_Route_Layer_BOTTOM ); + sizes.Init( board(), m_startItem ); + sizes.AddLayerPair( frame()->GetScreen()->m_Route_Layer_TOP, + frame()->GetScreen()->m_Route_Layer_BOTTOM ); m_router->UpdateSizes( sizes ); if( !m_router->StartRouting( m_startSnapPoint, m_startItem, routingLayer ) ) { - DisplayError( m_frame, m_router->FailureReason() ); + DisplayError( frame(), m_router->FailureReason() ); highlightNet( false ); return false; } @@ -677,7 +693,7 @@ bool ROUTER_TOOL::prepareInteractive() m_endItem = NULL; m_endSnapPoint = m_startSnapPoint; - m_frame->UndoRedoBlock( true ); + frame()->UndoRedoBlock( true ); return true; } @@ -687,9 +703,9 @@ bool ROUTER_TOOL::finishInteractive() { m_router->StopRouting(); - m_ctls->SetAutoPan( false ); - m_ctls->ForceCursorPosition( false ); - m_frame->UndoRedoBlock( false ); + controls()->SetAutoPan( false ); + controls()->ForceCursorPosition( false ); + frame()->UndoRedoBlock( false ); highlightNet( false ); return true; @@ -724,7 +740,7 @@ void ROUTER_TOOL::performRouting() switchLayerOnViaPlacement(); // Synchronize the indicated layer - m_frame->SetActiveLayer( ToLAYER_ID( m_router->GetCurrentLayer() ) ); + frame()->SetActiveLayer( ToLAYER_ID( m_router->GetCurrentLayer() ) ); updateEndItem( *evt ); m_router->Move( m_endSnapPoint, m_endItem ); m_startItem = NULL; @@ -737,7 +753,7 @@ void ROUTER_TOOL::performRouting() } else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) ) { - m_router->SwitchLayer( m_frame->GetActiveLayer() ); + m_router->SwitchLayer( frame()->GetActiveLayer() ); updateEndItem( *evt ); m_router->Move( m_endSnapPoint, m_endItem ); // refresh } @@ -763,7 +779,7 @@ int ROUTER_TOOL::DpDimensionsDialog( const TOOL_EVENT& aEvent ) Activate(); PNS::SIZES_SETTINGS sizes = m_router->Sizes(); - DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( m_frame, sizes ); + DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( frame(), sizes ); if( settingsDlg.ShowModal() ) { @@ -779,7 +795,7 @@ int ROUTER_TOOL::SettingsDialog( const TOOL_EVENT& aEvent ) { Activate(); - DIALOG_PNS_SETTINGS settingsDlg( m_frame, m_router->Settings() ); + DIALOG_PNS_SETTINGS settingsDlg( frame(), m_router->Settings() ); if( settingsDlg.ShowModal() ) m_savedSettings = m_router->Settings(); @@ -813,17 +829,24 @@ void ROUTER_TOOL::setTransitions() int ROUTER_TOOL::RouteSingleTrace( const TOOL_EVENT& aEvent ) { - m_frame->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Route Track" ) ); + frame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Route Track" ) ); return mainLoop( PNS::PNS_MODE_ROUTE_SINGLE ); } int ROUTER_TOOL::RouteDiffPair( const TOOL_EVENT& aEvent ) { - m_frame->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Router Differential Pair" ) ); + frame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Router Differential Pair" ) ); return mainLoop( PNS::PNS_MODE_ROUTE_DIFF_PAIR ); } +void ROUTER_TOOL::breakTrack() +{ + if ( m_startItem->OfKind( PNS::ITEM::SEGMENT_T ) ) + { + m_router->BreakSegment( m_startItem, m_startSnapPoint ); + } +} int ROUTER_TOOL::mainLoop( PNS::ROUTER_MODE aMode ) { @@ -837,7 +860,7 @@ int ROUTER_TOOL::mainLoop( PNS::ROUTER_MODE aMode ) m_router->SetMode( aMode ); - m_ctls->ShowCursor( true ); + controls()->ShowCursor( true ); m_startSnapPoint = getViewControls()->GetCursorPosition(); @@ -863,12 +886,25 @@ int ROUTER_TOOL::mainLoop( PNS::ROUTER_MODE aMode ) { updateStartItem( *evt ); } + else if( evt->IsAction( &PCB_ACTIONS::dragFreeAngle ) ) + { + performDragging( PNS::DM_ANY | PNS::DM_FREE_ANGLE ); + } + else if( evt->IsAction( &PCB_ACTIONS::drag45Degree ) ) + { + performDragging( PNS::DM_ANY ); + } + else if( evt->IsAction( &PCB_ACTIONS::breakTrack ) ) + { + updateStartItem( *evt ); + breakTrack( ); + } else if( evt->IsClick( BUT_LEFT ) || evt->IsAction( &ACT_NewTrack ) ) { updateStartItem( *evt ); if( evt->Modifier( MD_CTRL ) ) - performDragging(); + performDragging( PNS::DM_ANY ); else performRouting(); } @@ -897,17 +933,17 @@ int ROUTER_TOOL::mainLoop( PNS::ROUTER_MODE aMode ) } -void ROUTER_TOOL::performDragging() +void ROUTER_TOOL::performDragging( int aMode ) { VIEW_CONTROLS* ctls = getViewControls(); if( m_startItem && m_startItem->IsLocked() ) { - if( !IsOK( m_frame, _( "The item is locked. Do you want to continue?" ) ) ) + if( !IsOK( frame(), _( "The item is locked. Do you want to continue?" ) ) ) return; } - bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem ); + bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem, aMode ); if( !dragStarted ) return; @@ -917,7 +953,7 @@ void ROUTER_TOOL::performDragging() ctls->SetAutoPan( true ); - m_frame->UndoRedoBlock( true ); + frame()->UndoRedoBlock( true ); while( OPT_TOOL_EVENT evt = Wait() ) { @@ -945,7 +981,7 @@ void ROUTER_TOOL::performDragging() m_startItem = NULL; - m_frame->UndoRedoBlock( false ); + frame()->UndoRedoBlock( false ); ctls->SetAutoPan( false ); ctls->ForceCursorPosition( false ); highlightNet( false ); @@ -974,21 +1010,23 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent ) if( m_startItem && m_startItem->IsLocked() ) { - if( !IsOK( m_frame, _( "The item is locked. Do you want to continue?" ) ) ) + if( !IsOK( frame(), _( "The item is locked. Do you want to continue?" ) ) ) return false; } - VECTOR2I p0 = m_ctls->GetCursorPosition(); + VECTOR2I p0 = controls()->GetCursorPosition(); + + int dragMode = aEvent.Parameter (); - bool dragStarted = m_router->StartDragging( p0, m_startItem ); + bool dragStarted = m_router->StartDragging( p0, m_startItem, dragMode ); if( !dragStarted ) return 0; - m_ctls->ShowCursor( true ); - m_ctls->ForceCursorPosition( false ); - m_ctls->SetAutoPan( true ); - m_frame->UndoRedoBlock( true ); + controls()->ShowCursor( true ); + controls()->ForceCursorPosition( false ); + controls()->SetAutoPan( true ); + frame()->UndoRedoBlock( true ); while( OPT_TOOL_EVENT evt = Wait() ) { @@ -1012,9 +1050,9 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent ) if( m_router->RoutingInProgress() ) m_router->StopRouting(); - m_ctls->SetAutoPan( false ); - m_ctls->ShowCursor( false ); - m_frame->UndoRedoBlock( false ); + controls()->SetAutoPan( false ); + controls()->ShowCursor( false ); + frame()->UndoRedoBlock( false ); return 0; } @@ -1022,8 +1060,8 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent ) int ROUTER_TOOL::CustomTrackWidthDialog( const TOOL_EVENT& aEvent ) { - BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); - DIALOG_TRACK_VIA_SIZE sizeDlg( m_frame, bds ); + BOARD_DESIGN_SETTINGS& bds = board()->GetDesignSettings(); + DIALOG_TRACK_VIA_SIZE sizeDlg( frame(), bds ); if( sizeDlg.ShowModal() ) { @@ -1038,7 +1076,7 @@ int ROUTER_TOOL::CustomTrackWidthDialog( const TOOL_EVENT& aEvent ) int ROUTER_TOOL::onTrackViaSizeChanged( const TOOL_EVENT& aEvent ) { PNS::SIZES_SETTINGS sizes( m_router->Sizes() ); - sizes.ImportCurrent( m_board->GetDesignSettings() ); + sizes.ImportCurrent( board()->GetDesignSettings() ); m_router->UpdateSizes( sizes ); return 0; diff --git a/pcbnew/router/router_tool.h b/pcbnew/router/router_tool.h index 66a7c83a1f..f11f2c8bad 100644 --- a/pcbnew/router/router_tool.h +++ b/pcbnew/router/router_tool.h @@ -51,7 +51,8 @@ private: int getDefaultWidth( int aNetCode ); void performRouting(); - void performDragging(); + void performDragging( int aMode = PNS::DM_ANY ); + void breakTrack(); void getNetclassDimensions( int aNetCode, int& aWidth, int& aViaDiameter, int& aViaDrill ); void handleCommonEvents( const TOOL_EVENT& evt ); diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index 68f7933540..85535ee6f1 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -91,6 +91,10 @@ TOOL_ACTION PCB_ACTIONS::globalEditPads( "pcbnew.InteractiveEdit.globalPadEdit", _( "Changes pad properties globally." ), push_pad_settings_xpm ); TOOL_ACTION PCB_ACTIONS::editActivate( "pcbnew.InteractiveEdit", + AS_GLOBAL, 0, + _( "Edit Activate" ), _( "" ), move_xpm, AF_ACTIVATE ); + +TOOL_ACTION PCB_ACTIONS::move( "pcbnew.InteractiveEdit.move", AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_MOVE_ITEM ), _( "Move" ), _( "Moves the selected item(s)" ), move_xpm, AF_ACTIVATE ); @@ -157,7 +161,6 @@ TOOL_ACTION PCB_ACTIONS::measureTool( "pcbnew.InteractiveEdit.measureTool", _( "Measuring tool" ), _( "Interactively measure distance between points" ), nullptr, AF_ACTIVATE ); - static wxPoint getAnchorPoint( const SELECTION &selection, const MOVE_PARAMETERS ¶ms ) { wxPoint anchorPoint; @@ -270,13 +273,17 @@ bool EDIT_TOOL::Init() // Add context menu entries that are displayed when selection tool is active CONDITIONAL_MENU& menu = m_selectionTool->GetToolMenu().GetMenu(); - menu.AddItem( PCB_ACTIONS::editActivate, SELECTION_CONDITIONS::NotEmpty ); + + menu.AddItem( PCB_ACTIONS::move, SELECTION_CONDITIONS::NotEmpty ); + menu.AddItem( PCB_ACTIONS::drag45Degree, SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::Tracks ) ); + menu.AddItem( PCB_ACTIONS::dragFreeAngle, SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::Tracks ) ); menu.AddItem( PCB_ACTIONS::rotateCcw, SELECTION_CONDITIONS::NotEmpty ); menu.AddItem( PCB_ACTIONS::rotateCw, SELECTION_CONDITIONS::NotEmpty ); menu.AddItem( PCB_ACTIONS::flip, SELECTION_CONDITIONS::NotEmpty ); menu.AddItem( PCB_ACTIONS::remove, SELECTION_CONDITIONS::NotEmpty ); menu.AddItem( PCB_ACTIONS::properties, SELECTION_CONDITIONS::Count( 1 ) || SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::Tracks ) ); + menu.AddItem( PCB_ACTIONS::moveExact, SELECTION_CONDITIONS::NotEmpty ); menu.AddItem( PCB_ACTIONS::positionRelative, SELECTION_CONDITIONS::NotEmpty ); menu.AddItem( PCB_ACTIONS::duplicate, SELECTION_CONDITIONS::NotEmpty ); @@ -298,26 +305,39 @@ bool EDIT_TOOL::Init() } -bool EDIT_TOOL::invokeInlineRouter() +bool EDIT_TOOL::invokeInlineRouter( int aDragMode ) { TRACK* track = uniqueSelected(); VIA* via = uniqueSelected(); + + if( track || via ) { - ROUTER_TOOL* theRouter = static_cast( m_toolMgr->FindTool( "pcbnew.InteractiveRouter" ) ); + auto theRouter = static_cast( m_toolMgr->FindTool( "pcbnew.InteractiveRouter" ) ); assert( theRouter ); - if( !theRouter->PNSSettings().InlineDragEnabled() ) + if( !theRouter->Router()->Settings().InlineDragEnabled() ) return false; - m_toolMgr->RunAction( PCB_ACTIONS::routerInlineDrag, true ); + m_toolMgr->RunAction( PCB_ACTIONS::routerInlineDrag, true, aDragMode ); return true; } return false; } +int EDIT_TOOL::Drag( const TOOL_EVENT& aEvent ) +{ + int mode = PNS::DM_ANY; + + if( aEvent.IsAction( &PCB_ACTIONS::dragFreeAngle ) ) + mode |= PNS::DM_FREE_ANGLE; + + invokeInlineRouter( mode ); + + return 0; +} int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) { @@ -354,13 +374,16 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) // Main loop: keep receiving events do { - if( evt->IsAction( &PCB_ACTIONS::editActivate ) - || evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) + bool matchingAction = evt->IsAction( &PCB_ACTIONS::editActivate ) + || evt->IsAction( &PCB_ACTIONS::move ); + + if( matchingAction + || evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) { if( selection.Empty() ) break; - BOARD_ITEM* curr_item = static_cast( selection.Front() ); + auto curr_item = static_cast( selection.Front() ); if( m_dragging && evt->Category() == TC_MOUSE ) { @@ -376,7 +399,12 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) } else if( !m_dragging ) // Prepare to start dragging { - if( !invokeInlineRouter() ) + bool invokedRouter = false; + + if ( !evt->IsAction( &PCB_ACTIONS::move ) ) + invokedRouter = invokeInlineRouter( PNS::DM_ANY ); + + if( !invokedRouter ) { // deal with locked items (override lock or abort the operation) SELECTION_LOCK_FLAGS lockFlags = m_selectionTool->CheckLock(); @@ -509,6 +537,46 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) return 0; } +bool EDIT_TOOL::changeTrackWidthOnClick( const SELECTION& selection ) +{ + if ( selection.Size() == 1 && frame()->Settings().m_editActionChangesTrackWidth ) + { + auto item = static_cast( selection[0] ); + + m_commit->Modify( item ); + + if( auto via = dyn_cast( item ) ) + { + int new_width, new_drill; + + if( via->GetViaType() == VIA_MICROVIA ) + { + auto net = via->GetNet(); + + new_width = net->GetMicroViaSize(); + new_drill = net->GetMicroViaDrillSize(); + } + else + { + new_width = board()->GetDesignSettings().GetCurrentViaSize(); + new_drill = board()->GetDesignSettings().GetCurrentViaDrill(); + } + + via->SetDrill( new_drill ); + via->SetWidth( new_width ); + } + else if ( auto track = dyn_cast( item ) ) + { + int new_width = board()->GetDesignSettings().GetCurrentTrackWidth(); + track->SetWidth( new_width ); + } + + m_commit->Push( _("Edit track width/via size") ); + return true; + } + + return false; +} int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) { @@ -522,41 +590,7 @@ int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) // Tracks & vias are treated in a special way: if( ( SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::Tracks ) )( selection ) ) { - if ( selection.Size() == 1 && editFrame->Settings().m_editActionChangesTrackWidth ) - { - auto item = static_cast( selection[0] ); - - m_commit->Modify( item ); - - if( auto via = dyn_cast( item ) ) - { - int new_width, new_drill; - - if( via->GetViaType() == VIA_MICROVIA ) - { - auto net = via->GetNet(); - - new_width = net->GetMicroViaSize(); - new_drill = net->GetMicroViaDrillSize(); - } - else - { - new_width = board()->GetDesignSettings().GetCurrentViaSize(); - new_drill = board()->GetDesignSettings().GetCurrentViaDrill(); - } - - via->SetDrill( new_drill ); - via->SetWidth( new_width ); - } - else if ( auto track = dyn_cast( item ) ) - { - int new_width = board()->GetDesignSettings().GetCurrentTrackWidth(); - track->SetWidth( new_width ); - } - - m_commit->Push( _("Edit track width/via size") ); - } - else + if ( !changeTrackWidthOnClick( selection ) ) { DIALOG_TRACK_VIA_PROPERTIES dlg( editFrame, selection ); @@ -1151,6 +1185,9 @@ int EDIT_TOOL::MeasureTool( const TOOL_EVENT& aEvent ) void EDIT_TOOL::setTransitions() { Go( &EDIT_TOOL::Main, PCB_ACTIONS::editActivate.MakeEvent() ); + Go( &EDIT_TOOL::Main, PCB_ACTIONS::move.MakeEvent() ); + Go( &EDIT_TOOL::Drag, PCB_ACTIONS::drag45Degree.MakeEvent() ); + Go( &EDIT_TOOL::Drag, PCB_ACTIONS::dragFreeAngle.MakeEvent() ); Go( &EDIT_TOOL::Rotate, PCB_ACTIONS::rotateCw.MakeEvent() ); Go( &EDIT_TOOL::Rotate, PCB_ACTIONS::rotateCcw.MakeEvent() ); Go( &EDIT_TOOL::Flip, PCB_ACTIONS::flip.MakeEvent() ); @@ -1226,7 +1263,7 @@ int EDIT_TOOL::editFootprintInFpEditor( const TOOL_EVENT& aEvent ) template T* EDIT_TOOL::uniqueSelected() { - const auto selection = m_selectionTool->GetSelection(); + auto& selection = m_selectionTool->RequestSelection( SELECTION_DEFAULT ); if( selection.Size() != 1 ) return nullptr; diff --git a/pcbnew/tools/edit_tool.h b/pcbnew/tools/edit_tool.h index a9ac7c55ab..66ba412aad 100644 --- a/pcbnew/tools/edit_tool.h +++ b/pcbnew/tools/edit_tool.h @@ -29,6 +29,7 @@ #include #include + class BOARD_COMMIT; class BOARD_ITEM; class SELECTION_TOOL; @@ -60,6 +61,13 @@ public: */ int Main( const TOOL_EVENT& aEvent ); + /** + * Function Drag() + * + * todo + */ + int Drag( const TOOL_EVENT& aEvent ); + /** * Function Edit() * @@ -151,7 +159,10 @@ private: int editFootprintInFpEditor( const TOOL_EVENT& aEvent ); - bool invokeInlineRouter(); + bool invokeInlineRouter( int aDragMode ); + + bool changeTrackWidthOnClick( const SELECTION& selection ); + /** * Function hoverSelection() diff --git a/pcbnew/tools/pcb_actions.h b/pcbnew/tools/pcb_actions.h index 2bb17533f2..a391382685 100644 --- a/pcbnew/tools/pcb_actions.h +++ b/pcbnew/tools/pcb_actions.h @@ -86,6 +86,9 @@ public: /// Activation of the edit tool static TOOL_ACTION editActivate; + /// move an item + static TOOL_ACTION move; + /// Rotation of selected objects clockwise static TOOL_ACTION rotateCw; @@ -120,6 +123,11 @@ public: static TOOL_ACTION remove; static TOOL_ACTION removeAlt; + static TOOL_ACTION breakTrack; + static TOOL_ACTION drag45Degree; + static TOOL_ACTION dragFreeAngle; + + // Drawing Tool /// Activation of the drawing tool (line) static TOOL_ACTION drawLine; @@ -196,10 +204,7 @@ public: /// Activation of the Push and Shove router (inline dragging mode) static TOOL_ACTION routerInlineDrag; - - /// Break track action - static TOOL_ACTION breakTrack; - + // Point Editor /// Break outline (insert additional points to an edge) static TOOL_ACTION pointEditorAddCorner;