diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp index e768777ef0..9d264f84a5 100644 --- a/pcbnew/board_commit.cpp +++ b/pcbnew/board_commit.cpp @@ -37,14 +37,16 @@ using namespace std::placeholders; -BOARD_COMMIT::BOARD_COMMIT( PCB_TOOL_BASE* aTool ) +BOARD_COMMIT::BOARD_COMMIT( PCB_TOOL_BASE* aTool ) : + m_resolveNetConflicts( false ) { m_toolMgr = aTool->GetManager(); m_isFootprintEditor = aTool->IsFootprintEditor(); } -BOARD_COMMIT::BOARD_COMMIT( EDA_DRAW_FRAME* aFrame ) +BOARD_COMMIT::BOARD_COMMIT( EDA_DRAW_FRAME* aFrame ) : + m_resolveNetConflicts( false ) { m_toolMgr = aFrame->GetToolManager(); m_isFootprintEditor = aFrame->IsType( FRAME_FOOTPRINT_EDITOR ); @@ -350,6 +352,9 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a { size_t num_changes = m_changes.size(); + if( m_resolveNetConflicts ) + connectivity->PropagateNets( this, PROPAGATE_MODE::RESOLVE_CONFLICTS ); + connectivity->RecalculateRatsnest( this ); connectivity->ClearDynamicRatsnest(); frame->GetCanvas()->RedrawRatsnest(); diff --git a/pcbnew/board_commit.h b/pcbnew/board_commit.h index 362950886a..3464fd96d8 100644 --- a/pcbnew/board_commit.h +++ b/pcbnew/board_commit.h @@ -51,12 +51,23 @@ public: COMMIT& Stage( const PICKED_ITEMS_LIST& aItems, UNDO_REDO aModFlag = UNDO_REDO::UNSPECIFIED ) override; + /** + * Sets a flag that will cause Push() to resolve net conflicts on track/via clusters instead + * of the default behavior which is to skip updating track/via clusters that have conflicts. + * This is used in the netlist updater to update any clusters that were changed due to pad nets + * changing, but should not be used for other changes as you typically don't want to change + * track/via nets due to temporary conflicts created by board editing operations. + * @param aResolve is true if this commit should resolve conflicting track/via net assignments + */ + void SetResolveNetConflicts( bool aResolve = true ) { m_resolveNetConflicts = aResolve; } + private: virtual EDA_ITEM* parentObject( EDA_ITEM* aItem ) const override; private: TOOL_MANAGER* m_toolMgr; bool m_isFootprintEditor; + bool m_resolveNetConflicts; }; #endif diff --git a/pcbnew/connectivity/connectivity_algo.cpp b/pcbnew/connectivity/connectivity_algo.cpp index e4fe163974..7bb325717a 100644 --- a/pcbnew/connectivity/connectivity_algo.cpp +++ b/pcbnew/connectivity/connectivity_algo.cpp @@ -477,11 +477,19 @@ void CN_CONNECTIVITY_ALGO::Build( const std::vector& aItems ) } -void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit ) +void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit, PROPAGATE_MODE aMode ) { + bool skipConflicts = ( aMode == PROPAGATE_MODE::SKIP_CONFLICTS ); + + wxLogTrace( "CN", "propagateConnections: propagate skip conflicts? %d", skipConflicts ); + for( const auto& cluster : m_connClusters ) { - if( cluster->IsOrphaned() ) + if( skipConflicts && cluster->IsConflicting() ) + { + wxLogTrace( "CN", "Conflicting nets in cluster %p; skipping update", cluster.get() ); + } + else if( cluster->IsOrphaned() ) { wxLogTrace( "CN", "Skipping orphaned cluster %p [net: %s]", cluster.get(), (const char*) cluster->OriginNetName().c_str() ); @@ -531,10 +539,10 @@ void CN_CONNECTIVITY_ALGO::propagateConnections( BOARD_COMMIT* aCommit ) } -void CN_CONNECTIVITY_ALGO::PropagateNets( BOARD_COMMIT* aCommit ) +void CN_CONNECTIVITY_ALGO::PropagateNets( BOARD_COMMIT* aCommit, PROPAGATE_MODE aMode ) { m_connClusters = SearchClusters( CSM_PROPAGATE ); - propagateConnections( aCommit ); + propagateConnections( aCommit, aMode ); } diff --git a/pcbnew/connectivity/connectivity_algo.h b/pcbnew/connectivity/connectivity_algo.h index 407a1f60b1..e66ef4a0e7 100644 --- a/pcbnew/connectivity/connectivity_algo.h +++ b/pcbnew/connectivity/connectivity_algo.h @@ -168,7 +168,8 @@ private: void searchConnections(); - void propagateConnections( BOARD_COMMIT* aCommit = nullptr ); + void propagateConnections( BOARD_COMMIT* aCommit = nullptr, + PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS ); template void add( Container& c, BItem brditem ) @@ -239,8 +240,10 @@ public: /** * Propagates nets from pads to other items in clusters * @param aCommit is used to store undo information for items modified by the call + * @param aMode controls how clusters with conflicting nets are resolved */ - void PropagateNets( BOARD_COMMIT* aCommit = nullptr ); + void PropagateNets( BOARD_COMMIT* aCommit = nullptr, + PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS ); void FindIsolatedCopperIslands( ZONE* aZone, PCB_LAYER_ID aLayer, std::vector& aIslands ); diff --git a/pcbnew/connectivity/connectivity_data.cpp b/pcbnew/connectivity/connectivity_data.cpp index b4f2fc620b..5d9286dc07 100644 --- a/pcbnew/connectivity/connectivity_data.cpp +++ b/pcbnew/connectivity/connectivity_data.cpp @@ -339,11 +339,12 @@ void CONNECTIVITY_DATA::HideDynamicRatsnest() } -void CONNECTIVITY_DATA::PropagateNets() +void CONNECTIVITY_DATA::PropagateNets( BOARD_COMMIT* aCommit, PROPAGATE_MODE aMode ) { - m_connAlgo->PropagateNets(); + m_connAlgo->PropagateNets( aCommit, aMode ); } + bool CONNECTIVITY_DATA::IsConnectedOnLayer( const BOARD_CONNECTED_ITEM *aItem, int aLayer, std::vector aTypes ) const { diff --git a/pcbnew/connectivity/connectivity_data.h b/pcbnew/connectivity/connectivity_data.h index a59f21486f..e291642668 100644 --- a/pcbnew/connectivity/connectivity_data.h +++ b/pcbnew/connectivity/connectivity_data.h @@ -82,6 +82,15 @@ struct RN_DYNAMIC_LINE VECTOR2I a, b; }; +/** + * Controls how nets are propagated through clusters + */ +enum class PROPAGATE_MODE +{ + SKIP_CONFLICTS, /// Clusters with conflicting drivers are not updated (default) + RESOLVE_CONFLICTS /// Clusters with conflicting drivers are updated to the most popular net +}; + // a wrapper class encompassing the connectivity computation algorithm and the class CONNECTIVITY_DATA { @@ -155,10 +164,12 @@ public: RN_NET* GetRatsnestForNet( int aNet ); /** - * Function PropagateNets() * Propagates the net codes from the source pads to the tracks/vias. + * @param aCommit is used to save the undo state of items modified by this call + * @param aMode controls how conflicts between pads are resolved */ - void PropagateNets(); + void PropagateNets( BOARD_COMMIT* aCommit = nullptr, + PROPAGATE_MODE aMode = PROPAGATE_MODE::SKIP_CONFLICTS ); bool CheckConnectivity( std::vector& aReport ); @@ -202,10 +213,10 @@ public: * @param aItem is the reference item to find other connected items. * @param aAnchor is the position to find connected items on. * @param aTypes allows one to filter by item types. - * @return + * @return */ const std::vector GetConnectedItemsAtAnchor( const BOARD_CONNECTED_ITEM* aItem, - const VECTOR2I& aAnchor, + const VECTOR2I& aAnchor, const KICAD_T aTypes[] ) const; void GetUnconnectedEdges( std::vector& aEdges ) const; diff --git a/pcbnew/netlist_reader/board_netlist_updater.cpp b/pcbnew/netlist_reader/board_netlist_updater.cpp index 31fe76b5c4..03388022e4 100644 --- a/pcbnew/netlist_reader/board_netlist_updater.cpp +++ b/pcbnew/netlist_reader/board_netlist_updater.cpp @@ -1095,6 +1095,7 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist ) } m_board->GetNetInfo().RemoveUnusedNets(); + m_commit.SetResolveNetConflicts(); m_commit.Push( _( "Update netlist" ) ); m_board->SynchronizeNetsAndNetClasses();