pcbnew: Implement consistent graphical snapping
This creates a standard snapping framework in the GRID_HELPER class that allows snapping to items on the same layer as the object being created/moved as well as consistent toggling of this using the Shift key modifier. Fixes: lp:806260 * https://bugs.launchpad.net/kicad/+bug/806260 Fixes: lp:1604616 * https://bugs.launchpad.net/kicad/+bug/1604616
This commit is contained in:
parent
f714d2fa64
commit
03e642a8db
|
@ -975,6 +975,7 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
|
||||||
assert( aShape == S_SEGMENT || aShape == S_CIRCLE );
|
assert( aShape == S_SEGMENT || aShape == S_CIRCLE );
|
||||||
|
|
||||||
DRAWSEGMENT line45;
|
DRAWSEGMENT line45;
|
||||||
|
GRID_HELPER grid( m_frame );
|
||||||
|
|
||||||
m_frame->SetActiveLayer( getDrawingLayer() );
|
m_frame->SetActiveLayer( getDrawingLayer() );
|
||||||
|
|
||||||
|
@ -998,9 +999,11 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
|
||||||
// Init the new item attributes
|
// Init the new item attributes
|
||||||
aGraphic->SetShape( (STROKE_T) aShape );
|
aGraphic->SetShape( (STROKE_T) aShape );
|
||||||
aGraphic->SetWidth( m_lineWidth );
|
aGraphic->SetWidth( m_lineWidth );
|
||||||
aGraphic->SetStart( wxPoint( aStartingPoint->x, aStartingPoint->y ) );
|
|
||||||
aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
|
|
||||||
aGraphic->SetLayer( getDrawingLayer() );
|
aGraphic->SetLayer( getDrawingLayer() );
|
||||||
|
aGraphic->SetStart( wxPoint( aStartingPoint->x, aStartingPoint->y ) );
|
||||||
|
|
||||||
|
cursorPos = grid.BestSnapAnchor( cursorPos, aGraphic );
|
||||||
|
aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||||
|
|
||||||
if( aShape == S_SEGMENT )
|
if( aShape == S_SEGMENT )
|
||||||
line45 = *aGraphic; // used only for direction 45 mode with lines
|
line45 = *aGraphic; // used only for direction 45 mode with lines
|
||||||
|
@ -1018,7 +1021,9 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
|
||||||
// Main loop: keep receiving events
|
// Main loop: keep receiving events
|
||||||
while( OPT_TOOL_EVENT evt = Wait() )
|
while( OPT_TOOL_EVENT evt = Wait() )
|
||||||
{
|
{
|
||||||
cursorPos = m_controls->GetCursorPosition();
|
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
|
||||||
|
|
||||||
|
cursorPos = grid.BestSnapAnchor( evt->Position(), aGraphic );
|
||||||
|
|
||||||
// 45 degree angle constraint enabled with an option and toggled with Ctrl
|
// 45 degree angle constraint enabled with an option and toggled with Ctrl
|
||||||
const bool limit45 = ( frame()->Settings().m_use45DegreeGraphicSegments != !!( evt->Modifier( MD_CTRL ) ) );
|
const bool limit45 = ( frame()->Settings().m_use45DegreeGraphicSegments != !!( evt->Modifier( MD_CTRL ) ) );
|
||||||
|
@ -1030,7 +1035,7 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
|
||||||
if( direction45 )
|
if( direction45 )
|
||||||
{
|
{
|
||||||
preview.Add( &line45 );
|
preview.Add( &line45 );
|
||||||
make45DegLine( aGraphic, &line45 );
|
make45DegLine( aGraphic, &line45, cursorPos );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1121,7 +1126,7 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
|
||||||
{
|
{
|
||||||
// 45 degree lines
|
// 45 degree lines
|
||||||
if( direction45 && aShape == S_SEGMENT )
|
if( direction45 && aShape == S_SEGMENT )
|
||||||
make45DegLine( aGraphic, &line45 );
|
make45DegLine( aGraphic, &line45, cursorPos );
|
||||||
else
|
else
|
||||||
aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
|
aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||||
|
|
||||||
|
@ -1198,6 +1203,7 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic )
|
||||||
SELECTION preview;
|
SELECTION preview;
|
||||||
m_view->Add( &preview );
|
m_view->Add( &preview );
|
||||||
m_view->Add( &arcAsst );
|
m_view->Add( &arcAsst );
|
||||||
|
GRID_HELPER grid( m_frame );
|
||||||
|
|
||||||
m_controls->ShowCursor( true );
|
m_controls->ShowCursor( true );
|
||||||
m_controls->SetSnapping( true );
|
m_controls->SetSnapping( true );
|
||||||
|
@ -1209,7 +1215,11 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic )
|
||||||
// Main loop: keep receiving events
|
// Main loop: keep receiving events
|
||||||
while( OPT_TOOL_EVENT evt = Wait() )
|
while( OPT_TOOL_EVENT evt = Wait() )
|
||||||
{
|
{
|
||||||
const VECTOR2I cursorPos = m_controls->GetCursorPosition();
|
PCB_LAYER_ID layer = getDrawingLayer();
|
||||||
|
aGraphic->SetLayer( layer );
|
||||||
|
|
||||||
|
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
|
||||||
|
const VECTOR2I cursorPos = grid.BestSnapAnchor( evt->Position(), aGraphic );
|
||||||
|
|
||||||
if( evt->IsClick( BUT_LEFT ) )
|
if( evt->IsClick( BUT_LEFT ) )
|
||||||
{
|
{
|
||||||
|
@ -1218,13 +1228,10 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic )
|
||||||
m_controls->SetAutoPan( true );
|
m_controls->SetAutoPan( true );
|
||||||
m_controls->CaptureCursor( true );
|
m_controls->CaptureCursor( true );
|
||||||
|
|
||||||
PCB_LAYER_ID layer = getDrawingLayer();
|
|
||||||
|
|
||||||
// Init the new item attributes
|
// Init the new item attributes
|
||||||
// (non-geometric, those are handled by the manager)
|
// (non-geometric, those are handled by the manager)
|
||||||
aGraphic->SetShape( S_ARC );
|
aGraphic->SetShape( S_ARC );
|
||||||
aGraphic->SetWidth( m_lineWidth );
|
aGraphic->SetWidth( m_lineWidth );
|
||||||
aGraphic->SetLayer( layer );
|
|
||||||
|
|
||||||
preview.Add( aGraphic );
|
preview.Add( aGraphic );
|
||||||
firstPoint = true;
|
firstPoint = true;
|
||||||
|
@ -1342,13 +1349,16 @@ void DRAWING_TOOL::runPolygonEventLoop( POLYGON_GEOM_MANAGER& polyGeomMgr )
|
||||||
auto& controls = *getViewControls();
|
auto& controls = *getViewControls();
|
||||||
bool started = false;
|
bool started = false;
|
||||||
|
|
||||||
|
GRID_HELPER grid( m_frame );
|
||||||
STATUS_TEXT_POPUP status( m_frame );
|
STATUS_TEXT_POPUP status( m_frame );
|
||||||
status.SetTextColor( wxColour( 255, 0, 0 ) );
|
status.SetTextColor( wxColour( 255, 0, 0 ) );
|
||||||
status.SetText( _( "Self-intersecting polygons are not allowed" ) );
|
status.SetText( _( "Self-intersecting polygons are not allowed" ) );
|
||||||
|
|
||||||
while( OPT_TOOL_EVENT evt = Wait() )
|
while( OPT_TOOL_EVENT evt = Wait() )
|
||||||
{
|
{
|
||||||
VECTOR2I cursorPos = controls.GetCursorPosition();
|
LSET layers( m_frame->GetActiveLayer() );
|
||||||
|
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
|
||||||
|
VECTOR2I cursorPos = grid.BestSnapAnchor( evt->Position(), layers );
|
||||||
|
|
||||||
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
|
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) )
|
||||||
{
|
{
|
||||||
|
@ -1489,12 +1499,12 @@ int DRAWING_TOOL::drawZone( bool aKeepout, ZONE_MODE aMode )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) const
|
void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper,
|
||||||
|
VECTOR2I& aPos ) const
|
||||||
{
|
{
|
||||||
VECTOR2I cursorPos = m_controls->GetCursorPosition();
|
|
||||||
VECTOR2I origin( aSegment->GetStart() );
|
VECTOR2I origin( aSegment->GetStart() );
|
||||||
DIRECTION_45 direction( origin - cursorPos );
|
DIRECTION_45 direction( origin - aPos );
|
||||||
SHAPE_LINE_CHAIN newChain = direction.BuildInitialTrace( origin, cursorPos );
|
SHAPE_LINE_CHAIN newChain = direction.BuildInitialTrace( origin, aPos );
|
||||||
|
|
||||||
if( newChain.PointCount() > 2 )
|
if( newChain.PointCount() > 2 )
|
||||||
{
|
{
|
||||||
|
@ -1504,9 +1514,9 @@ void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
aSegment->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
|
aSegment->SetEnd( wxPoint( aPos.x, aPos.y ) );
|
||||||
aHelper->SetStart( wxPoint( cursorPos.x, cursorPos.y ) );
|
aHelper->SetStart( wxPoint( aPos.x, aPos.y ) );
|
||||||
aHelper->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
|
aHelper->SetEnd( wxPoint( aPos.x, aPos.y ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1593,13 +1603,7 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
||||||
|
|
||||||
// bool do_snap = ( m_frame->Settings().m_magneticTracks == CAPTURE_CURSOR_IN_TRACK_TOOL
|
// bool do_snap = ( m_frame->Settings().m_magneticTracks == CAPTURE_CURSOR_IN_TRACK_TOOL
|
||||||
// || m_frame->Settings().m_magneticTracks == CAPTURE_ALWAYS );
|
// || m_frame->Settings().m_magneticTracks == CAPTURE_ALWAYS );
|
||||||
bool do_snap = true;
|
m_gridHelper.SetSnap( !( m_modifiers & MD_SHIFT ) );
|
||||||
|
|
||||||
if( m_modifiers & MD_SHIFT )
|
|
||||||
do_snap = !do_snap;
|
|
||||||
|
|
||||||
if( do_snap )
|
|
||||||
{
|
|
||||||
auto via = static_cast<VIA*>( aItem );
|
auto via = static_cast<VIA*>( aItem );
|
||||||
wxPoint pos = via->GetPosition();
|
wxPoint pos = via->GetPosition();
|
||||||
TRACK* track = findTrack( via );
|
TRACK* track = findTrack( via );
|
||||||
|
@ -1612,7 +1616,6 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
||||||
aItem->SetPosition( wxPoint( snap.x, snap.y ) );
|
aItem->SetPosition( wxPoint( snap.x, snap.y ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void PlaceItem( BOARD_ITEM* aItem, BOARD_COMMIT& aCommit ) override
|
void PlaceItem( BOARD_ITEM* aItem, BOARD_COMMIT& aCommit ) override
|
||||||
{
|
{
|
||||||
|
|
|
@ -251,8 +251,9 @@ private:
|
||||||
* the end of the aSegment is modified according to the current cursor position.
|
* the end of the aSegment is modified according to the current cursor position.
|
||||||
* @param aSegment is the segment that is currently drawn.
|
* @param aSegment is the segment that is currently drawn.
|
||||||
* @param aHelper is a helper line that shows the next possible segment.
|
* @param aHelper is a helper line that shows the next possible segment.
|
||||||
|
* @param aPos is the position of the cursor for this event
|
||||||
*/
|
*/
|
||||||
void make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) const;
|
void make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper, VECTOR2I& aPos ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function constrainDimension()
|
* Function constrainDimension()
|
||||||
|
|
|
@ -372,6 +372,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
|
||||||
// Main loop: keep receiving events
|
// Main loop: keep receiving events
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
|
||||||
|
|
||||||
if( evt->IsAction( &PCB_ACTIONS::editActivate ) ||
|
if( evt->IsAction( &PCB_ACTIONS::editActivate ) ||
|
||||||
evt->IsAction( &PCB_ACTIONS::move ) ||
|
evt->IsAction( &PCB_ACTIONS::move ) ||
|
||||||
evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
|
evt->IsMotion() || evt->IsDrag( BUT_LEFT ) )
|
||||||
|
|
|
@ -46,6 +46,8 @@ GRID_HELPER::GRID_HELPER( PCB_BASE_FRAME* aFrame ) :
|
||||||
m_frame( aFrame )
|
m_frame( aFrame )
|
||||||
{
|
{
|
||||||
m_diagonalAuxAxesEnable = true;
|
m_diagonalAuxAxesEnable = true;
|
||||||
|
m_enableSnap = true;
|
||||||
|
m_snapSize = 100;
|
||||||
KIGFX::VIEW* view = m_frame->GetGalCanvas()->GetView();
|
KIGFX::VIEW* view = m_frame->GetGalCanvas()->GetView();
|
||||||
|
|
||||||
m_viewAxis.SetSize( 20000 );
|
m_viewAxis.SetSize( 20000 );
|
||||||
|
@ -141,6 +143,9 @@ VECTOR2I GRID_HELPER::AlignToSegment( const VECTOR2I& aPoint, const SEG& aSeg )
|
||||||
{
|
{
|
||||||
OPT_VECTOR2I pts[6];
|
OPT_VECTOR2I pts[6];
|
||||||
|
|
||||||
|
if( !m_enableSnap )
|
||||||
|
return aPoint;
|
||||||
|
|
||||||
const VECTOR2D gridOffset( GetOrigin() );
|
const VECTOR2D gridOffset( GetOrigin() );
|
||||||
const VECTOR2D gridSize( GetGrid() );
|
const VECTOR2D gridSize( GetGrid() );
|
||||||
|
|
||||||
|
@ -238,9 +243,22 @@ std::set<BOARD_ITEM*> GRID_HELPER::queryVisible( const BOX2I& aArea ) const
|
||||||
|
|
||||||
|
|
||||||
VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, BOARD_ITEM* aDraggedItem )
|
VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, BOARD_ITEM* aDraggedItem )
|
||||||
|
{
|
||||||
|
LSET layers;
|
||||||
|
|
||||||
|
if( aDraggedItem )
|
||||||
|
layers = aDraggedItem->GetLayer();
|
||||||
|
else
|
||||||
|
layers = LSET::AllLayersMask();
|
||||||
|
|
||||||
|
return BestSnapAnchor( aOrigin, layers );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, LSET& aLayers )
|
||||||
{
|
{
|
||||||
double worldScale = m_frame->GetGalCanvas()->GetGAL()->GetWorldScale();
|
double worldScale = m_frame->GetGalCanvas()->GetGAL()->GetWorldScale();
|
||||||
int snapRange = (int) ( 100.0 / worldScale );
|
int snapRange = (int) ( m_snapSize / worldScale );
|
||||||
|
|
||||||
BOX2I bb( VECTOR2I( aOrigin.x - snapRange / 2, aOrigin.y - snapRange / 2 ), VECTOR2I( snapRange, snapRange ) );
|
BOX2I bb( VECTOR2I( aOrigin.x - snapRange / 2, aOrigin.y - snapRange / 2 ), VECTOR2I( snapRange, snapRange ) );
|
||||||
|
|
||||||
|
@ -251,19 +269,12 @@ VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, BOARD_ITEM* aDrag
|
||||||
computeAnchors( item, aOrigin );
|
computeAnchors( item, aOrigin );
|
||||||
}
|
}
|
||||||
|
|
||||||
LSET layers;
|
ANCHOR* nearest = nearestAnchor( aOrigin, CORNER | SNAPPABLE, aLayers );
|
||||||
|
|
||||||
if( aDraggedItem )
|
|
||||||
layers = aDraggedItem->GetLayer();
|
|
||||||
else
|
|
||||||
layers = LSET::AllLayersMask();
|
|
||||||
|
|
||||||
ANCHOR* nearest = nearestAnchor( aOrigin, CORNER | SNAPPABLE, layers );
|
|
||||||
|
|
||||||
VECTOR2I nearestGrid = Align( aOrigin );
|
VECTOR2I nearestGrid = Align( aOrigin );
|
||||||
double gridDist = ( nearestGrid - aOrigin ).EuclideanNorm();
|
double gridDist = ( nearestGrid - aOrigin ).EuclideanNorm();
|
||||||
|
|
||||||
if( nearest )
|
if( nearest && m_enableSnap )
|
||||||
{
|
{
|
||||||
double snapDist = nearest->Distance( aOrigin );
|
double snapDist = nearest->Distance( aOrigin );
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,12 @@ public:
|
||||||
|
|
||||||
VECTOR2I BestDragOrigin( const VECTOR2I& aMousePos, BOARD_ITEM* aItem );
|
VECTOR2I BestDragOrigin( const VECTOR2I& aMousePos, BOARD_ITEM* aItem );
|
||||||
VECTOR2I BestSnapAnchor( const VECTOR2I& aOrigin, BOARD_ITEM* aDraggedItem );
|
VECTOR2I BestSnapAnchor( const VECTOR2I& aOrigin, BOARD_ITEM* aDraggedItem );
|
||||||
|
VECTOR2I BestSnapAnchor( const VECTOR2I& aOrigin, LSET& aLayers );
|
||||||
|
|
||||||
|
void SetSnap( bool aSnap )
|
||||||
|
{
|
||||||
|
m_enableSnap = aSnap;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum ANCHOR_FLAGS {
|
enum ANCHOR_FLAGS {
|
||||||
|
@ -79,8 +85,6 @@ private:
|
||||||
{
|
{
|
||||||
return ( aP - pos ).EuclideanNorm();
|
return ( aP - pos ).EuclideanNorm();
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool CanSnapItem( const BOARD_ITEM* aItem ) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<ANCHOR> m_anchors;
|
std::vector<ANCHOR> m_anchors;
|
||||||
|
@ -103,8 +107,13 @@ private:
|
||||||
|
|
||||||
PCB_BASE_FRAME* m_frame;
|
PCB_BASE_FRAME* m_frame;
|
||||||
OPT<VECTOR2I> m_auxAxis;
|
OPT<VECTOR2I> m_auxAxis;
|
||||||
bool m_diagonalAuxAxesEnable;
|
|
||||||
KIGFX::ORIGIN_VIEWITEM m_viewSnapPoint, m_viewAxis;
|
bool m_diagonalAuxAxesEnable; ///< If true, use the aux axis for snapping as well
|
||||||
|
bool m_enableSnap; ///< If true, allow snapping to other items on the layers
|
||||||
|
int m_snapSize; ///< Sets the radius in screen units for snapping to items
|
||||||
|
|
||||||
|
KIGFX::ORIGIN_VIEWITEM m_viewSnapPoint;
|
||||||
|
KIGFX::ORIGIN_VIEWITEM m_viewAxis;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -329,6 +329,8 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
|
||||||
if( revert )
|
if( revert )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
|
||||||
|
|
||||||
if( !m_editPoints ||
|
if( !m_editPoints ||
|
||||||
evt->Matches( m_selectionTool->ClearedEvent ) ||
|
evt->Matches( m_selectionTool->ClearedEvent ) ||
|
||||||
evt->Matches( m_selectionTool->UnselectedEvent ) ||
|
evt->Matches( m_selectionTool->UnselectedEvent ) ||
|
||||||
|
@ -346,7 +348,6 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
|
||||||
{
|
{
|
||||||
commit.StageItems( selection, CHT_MODIFY );
|
commit.StageItems( selection, CHT_MODIFY );
|
||||||
|
|
||||||
controls->ForceCursorPosition( false );
|
|
||||||
m_original = *m_editedPoint; // Save the original position
|
m_original = *m_editedPoint; // Save the original position
|
||||||
controls->SetAutoPan( true );
|
controls->SetAutoPan( true );
|
||||||
modified = true;
|
modified = true;
|
||||||
|
@ -358,14 +359,14 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
|
||||||
if( enableAltConstraint != (bool) m_altConstraint ) // alternative constraint
|
if( enableAltConstraint != (bool) m_altConstraint ) // alternative constraint
|
||||||
setAltConstraint( enableAltConstraint );
|
setAltConstraint( enableAltConstraint );
|
||||||
|
|
||||||
m_editedPoint->SetPosition( controls->GetCursorPosition() );
|
|
||||||
|
|
||||||
if( m_altConstraint )
|
if( m_altConstraint )
|
||||||
m_altConstraint->Apply();
|
m_altConstraint->Apply();
|
||||||
else
|
else
|
||||||
m_editedPoint->ApplyConstraint();
|
m_editedPoint->ApplyConstraint();
|
||||||
|
|
||||||
m_editedPoint->SetPosition( grid.Align( m_editedPoint->GetPosition() ) );
|
|
||||||
|
m_editedPoint->SetPosition( grid.BestSnapAnchor( evt->Position(),
|
||||||
|
static_cast<BOARD_ITEM*>( item ) ) );
|
||||||
updateItem();
|
updateItem();
|
||||||
updatePoints();
|
updatePoints();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue