From 9c59c4ee12534aa968bac99519d82dd0fc01f274 Mon Sep 17 00:00:00 2001 From: Mike Williams Date: Mon, 14 Feb 2022 22:52:34 +0000 Subject: [PATCH] Schematic: orthogonal drag bends should depend on move direction Prevents overlapping lines when possible. Fixes: https://gitlab.com/kicad/code/kicad/-/issues/10844 --- eeschema/tools/sch_move_tool.cpp | 31 ++++++++++++++++++++++++++++--- include/tool/selection.h | 12 +++++++++--- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/eeschema/tools/sch_move_tool.cpp b/eeschema/tools/sch_move_tool.cpp index afae2b3049..7c0427c7ec 100644 --- a/eeschema/tools/sch_move_tool.cpp +++ b/eeschema/tools/sch_move_tool.cpp @@ -373,6 +373,30 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent ) VECTOR2I delta( m_cursor - prevPos ); m_anchorPos = m_cursor; + // We need to check if the movement will change the net offset direction on the + // X an Y axes. This is because we remerge added bend lines in realtime, and we + // also account for the direction of the move when adding bend lines. So, if the + // move direction changes, we need to split it into a move that gets us back to + // zero, then the rest of the move. + std::vector splitMoves; + + if( std::signbit( m_moveOffset.x ) != std::signbit( ( m_moveOffset + delta ).x ) ) + { + splitMoves.emplace_back( VECTOR2I( -1 * m_moveOffset.x, 0 ) ); + splitMoves.emplace_back( VECTOR2I( delta.x + m_moveOffset.x, 0 ) ); + } + else + splitMoves.emplace_back( VECTOR2I( delta.x, 0 ) ); + + if( std::signbit( m_moveOffset.y ) != std::signbit( ( m_moveOffset + delta ).y ) ) + { + splitMoves.emplace_back( VECTOR2I( 0, -1 * m_moveOffset.y ) ); + splitMoves.emplace_back( VECTOR2I( 0, delta.y + m_moveOffset.y ) ); + } + else + splitMoves.emplace_back( VECTOR2I( 0, delta.y ) ); + + m_moveOffset += delta; prevPos = m_cursor; @@ -381,13 +405,14 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent ) int yBendCount = 1; // Split the move into X and Y moves so we can correctly drag orthogonal lines - for( VECTOR2I splitDelta : { VECTOR2I( delta.x, 0 ), VECTOR2I( 0, delta.y ) } ) + for( VECTOR2I splitDelta : splitMoves ) { // Skip non-moves if( splitDelta == VECTOR2I( 0, 0 ) ) continue; - for( EDA_ITEM* item : selection.GetItemsSortedByTypeAndXY() ) + for( EDA_ITEM* item : + selection.GetItemsSortedByTypeAndXY( ( delta.x >= 0 ), ( delta.y >= 0 ) ) ) { // Don't double move pins, fields, etc. if( item->GetParent() && item->GetParent()->IsSelected() ) @@ -596,7 +621,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent ) int yLength = abs( unselectedEnd.y - selectedEnd.y ); int xMove = ( xLength - ( xBendCount * grid.GetGrid().x ) ) * sign( selectedEnd.x - unselectedEnd.x ); - int yMove = ( yLength - ( yBendCount * grid.GetGrid().y ) ) + int yMove = ( yLength - ( yBendCount * grid.GetGrid().y ) ) * sign( selectedEnd.y - unselectedEnd.y ); // Create a new wire ending at the unselected end, we'll diff --git a/include/tool/selection.h b/include/tool/selection.h index f380cbeb75..ac8236fcd4 100644 --- a/include/tool/selection.h +++ b/include/tool/selection.h @@ -117,7 +117,8 @@ public: * * @return Vector of sorted items */ - const std::vector GetItemsSortedByTypeAndXY() const + const std::vector GetItemsSortedByTypeAndXY( bool leftBeforeRight = true, + bool topBeforeBottom = true ) const { std::vector sorted_items = std::vector( m_items.begin(), m_items.end() ); @@ -131,10 +132,15 @@ public: if( a->GetPosition().y == b->GetPosition().y ) return a->m_Uuid < b->m_Uuid; - return a->GetPosition().y < b->GetPosition().y; + if( topBeforeBottom ) + return a->GetPosition().y < b->GetPosition().y; + else + return a->GetPosition().y > b->GetPosition().y; } - else + else if( leftBeforeRight ) return a->GetPosition().x < b->GetPosition().x; + else + return a->GetPosition().x > b->GetPosition().x; } else return a->Type() < b->Type();