Improve handling of dragging around locked segments

Locked segments now are not modified if they weren't the start item.
If a locked segment is the start item, it is automatically unlocked.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/9145
This commit is contained in:
Jon Evans 2021-09-21 22:38:53 -04:00
parent b605111542
commit cf53b053a1
2 changed files with 47 additions and 9 deletions

View File

@ -1068,19 +1068,23 @@ int NODE::FindLinesBetweenJoints( const JOINT& aA, const JOINT& aB, std::vector<
void NODE::FixupVirtualVias()
{
SEGMENT* locked_seg = nullptr;
std::vector<VVIA*> vvias;
for( auto& joint : m_joints )
for( auto& jointPair : m_joints )
{
if( joint.second.Layers().IsMultilayer() )
JOINT joint = jointPair.second;
if( joint.Layers().IsMultilayer() )
continue;
int n_seg = 0, n_solid = 0, n_vias = 0;
int prev_w = -1;
int max_w = -1;
int prev_w = -1;
int max_w = -1;
bool is_width_change = false;
bool is_locked = false;
for( const auto& lnk : joint.second.LinkList() )
for( const auto& lnk : joint.LinkList() )
{
if( lnk.item->OfKind( ITEM::VIA_T ) )
{
@ -1101,15 +1105,28 @@ void NODE::FixupVirtualVias()
max_w = std::max( w, max_w );
prev_w = w;
is_locked = t->IsLocked();
locked_seg = t;
}
}
if( ( is_width_change || n_seg >= 3 ) && n_solid == 0 && n_vias == 0 )
if( ( is_width_change || n_seg >= 3 || is_locked ) && n_solid == 0 && n_vias == 0 )
{
// fixme: the hull margin here is an ugly temporary workaround. The real fix
// is to use octagons for via force propagation.
vvias.push_back( new VVIA( joint.second.Pos(), joint.second.Layers().Start(),
max_w + 2 * PNS_HULL_MARGIN, joint.second.Net() ) );
vvias.push_back( new VVIA( joint.Pos(), joint.Layers().Start(),
max_w + 2 * PNS_HULL_MARGIN, joint.Net() ) );
}
if( is_locked )
{
const VECTOR2I& secondPos = ( locked_seg->Seg().A == joint.Pos() ) ?
locked_seg->Seg().B :
locked_seg->Seg().A;
vvias.push_back( new VVIA( secondPos, joint.Layers().Start(),
max_w + 2 * PNS_HULL_MARGIN, joint.Net() ) );
}
}

View File

@ -1564,7 +1564,7 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
if( selection.Size() != 1 )
return 0;
const BOARD_ITEM* item = static_cast<const BOARD_ITEM*>( selection.Front() );
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.Front() );
if( item->Type() != PCB_TRACE_T
&& item->Type() != PCB_VIA_T
@ -1573,6 +1573,19 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
return 0;
}
// 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
// this case the lock can't be reliably re-applied, because there is no guarantee that the end
// state of the drag results in the same number of segments so it's not clear which segment to
// apply the lock state to.
bool wasLocked = false;
if( item->IsLocked() )
{
wasLocked = true;
item->SetLocked( false );
}
Activate();
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
@ -1643,7 +1656,12 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
bool dragStarted = m_router->StartDragging( p, itemsToDrag, dragMode );
if( !dragStarted )
{
if( wasLocked )
item->SetLocked( true );
return 0;
}
m_gridHelper->SetAuxAxes( true, p );
controls()->ShowCursor( true );
@ -1677,6 +1695,9 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
if( evt->IsCancelInteractive() )
{
if( wasLocked )
item->SetLocked( true );
break;
}
else if( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )