Support both X and Y mirroring in FPEditor.

Fixes https://gitlab.com/kicad/code/kicad/issues/12409
This commit is contained in:
Jeff Young 2022-09-21 00:16:00 +01:00
parent 0150655ed3
commit 513fc872bb
9 changed files with 82 additions and 23 deletions

View File

@ -1118,7 +1118,8 @@ void FOOTPRINT_EDIT_FRAME::setupUIConditions()
mgr->SetConditions( PCB_ACTIONS::rotateCw, ENABLE( cond.HasItems() ) );
mgr->SetConditions( PCB_ACTIONS::rotateCcw, ENABLE( cond.HasItems() ) );
mgr->SetConditions( PCB_ACTIONS::mirror, ENABLE( cond.HasItems() ) );
mgr->SetConditions( PCB_ACTIONS::mirrorH, ENABLE( cond.HasItems() ) );
mgr->SetConditions( PCB_ACTIONS::mirrorV, ENABLE( cond.HasItems() ) );
mgr->SetConditions( PCB_ACTIONS::group, ENABLE( SELECTION_CONDITIONS::MoreThan( 1 ) ) );
mgr->SetConditions( PCB_ACTIONS::ungroup, ENABLE( haveAtLeastOneGroupCond ) );

View File

@ -330,9 +330,7 @@ void FP_SHAPE::Mirror( const VECTOR2I& aCentre, bool aMirrorAroundXAxis )
break;
case SHAPE_T::POLY:
// polygon corners coordinates are always relative to the
// footprint position, orientation 0
m_poly.Mirror( !aMirrorAroundXAxis, aMirrorAroundXAxis );
m_poly.Mirror( !aMirrorAroundXAxis, aMirrorAroundXAxis, aCentre );
break;
default:

View File

@ -1050,7 +1050,8 @@ void PCB_PAINTER::draw( const PAD* aPad, int aLayer )
if( primitive->IsAnnotationProxy() )
{
position = aPad->GetPosition() + primitive->GetCenter();
padsize = primitive->GetBotRight() - primitive->GetTopLeft();
padsize.x = abs( primitive->GetBotRight().x - primitive->GetTopLeft().x );
padsize.y = abs( primitive->GetBotRight().y - primitive->GetTopLeft().y );
// We normally draw a bit outside the pad, but this will be somewhat
// unexpected when the user has drawn a box.
@ -1080,7 +1081,7 @@ void PCB_PAINTER::draw( const PAD* aPad, int aLayer )
m_gal->Translate( position );
// Keep the size ratio for the font, but make it smaller
if( padsize.x < padsize.y )
if( padsize.x < ( padsize.y * 0.95 ) )
{
m_gal->Rotate( -ANGLE_90.AsRadians() );
size = padsize.x;

View File

@ -76,7 +76,8 @@ void FOOTPRINT_EDIT_FRAME::ReCreateHToolbar()
m_mainToolBar->AddScaledSeparator( this );
m_mainToolBar->Add( PCB_ACTIONS::rotateCcw );
m_mainToolBar->Add( PCB_ACTIONS::rotateCw );
m_mainToolBar->Add( PCB_ACTIONS::mirror );
m_mainToolBar->Add( PCB_ACTIONS::mirrorH );
m_mainToolBar->Add( PCB_ACTIONS::mirrorV );
m_mainToolBar->Add( PCB_ACTIONS::group );
m_mainToolBar->Add( PCB_ACTIONS::ungroup );

View File

@ -197,7 +197,8 @@ bool EDIT_TOOL::Init()
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::mirror, inFootprintEditor && SELECTION_CONDITIONS::NotEmpty );
menu.AddItem( PCB_ACTIONS::mirrorH, inFootprintEditor && SELECTION_CONDITIONS::NotEmpty );
menu.AddItem( PCB_ACTIONS::mirrorV, inFootprintEditor && SELECTION_CONDITIONS::NotEmpty );
menu.AddItem( PCB_ACTIONS::swap, SELECTION_CONDITIONS::MoreThan( 1 ) );
menu.AddItem( PCB_ACTIONS::properties, propertiesCondition );
@ -934,11 +935,10 @@ int EDIT_TOOL::FilletTracks( const TOOL_EVENT& aEvent )
continue;
SHAPE_ARC sArc( t1Seg, t2Seg, filletRadiusIU );
wxPoint t1newPoint, t2newPoint;
VECTOR2I t1newPoint, t2newPoint;
auto setIfPointOnSeg =
[]( wxPoint& aPointToSet, SEG aSegment, VECTOR2I aVecToTest )
[]( VECTOR2I& aPointToSet, SEG aSegment, VECTOR2I aVecToTest )
{
VECTOR2I segToVec = aSegment.NearestPoint( aVecToTest ) - aVecToTest;
@ -1206,6 +1206,21 @@ static VECTOR2I mirrorPointX( const VECTOR2I& aPoint, const VECTOR2I& aMirrorPoi
}
/**
* Mirror a point about the vertical axis passing through another point.
*/
static VECTOR2I mirrorPointY( const VECTOR2I& aPoint, const VECTOR2I& aMirrorPoint )
{
VECTOR2I mirrored = aPoint;
mirrored.y -= aMirrorPoint.y;
mirrored.y = -mirrored.y;
mirrored.y += aMirrorPoint.y;
return mirrored;
}
/**
* Mirror a pad in the vertical axis passing through a point (mirror left to right).
*/
@ -1231,6 +1246,31 @@ static void mirrorPadX( PAD& aPad, const VECTOR2I& aMirrorPoint )
}
/**
* Mirror a pad in the vertical axis passing through a point (mirror left to right).
*/
static void mirrorPadY( PAD& aPad, const VECTOR2I& aMirrorPoint )
{
if( aPad.GetShape() == PAD_SHAPE::CUSTOM )
aPad.FlipPrimitives( false ); // mirror primitives top to bottom
VECTOR2I tmpPt = mirrorPointY( aPad.GetPosition(), aMirrorPoint );
aPad.SetPosition( tmpPt );
aPad.SetY0( aPad.GetPosition().y );
tmpPt = aPad.GetOffset();
tmpPt.y = -tmpPt.y;
aPad.SetOffset( tmpPt );
auto tmpz = aPad.GetDelta();
tmpz.y = -tmpz.y;
aPad.SetDelta( tmpz );
aPad.SetOrientation( -aPad.GetOrientation() );
}
int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
{
if( isRouterActive() )
@ -1252,18 +1292,23 @@ int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
return 0;
updateModificationPoint( selection );
auto refPoint = selection.GetReferencePoint();
wxPoint mirrorPoint( refPoint.x, refPoint.y );
VECTOR2I mirrorPoint = selection.GetReferencePoint();
// When editing footprints, all items have the same parent
if( IsFootprintEditor() )
m_commit->Modify( selection.Front() );
// Set the mirroring options. We are mirroring here Left to Right.
// Set the mirroring options.
// Unfortunately, the mirror function do not have the same parameter for all items
// So we need these 2 parameters to avoid mistakes
const bool mirrorLeftRight = true;
const bool mirrorAroundXaxis = false;
bool mirrorLeftRight = true;
bool mirrorAroundXaxis = false;
if( aEvent.IsAction( &PCB_ACTIONS::mirrorV ) )
{
mirrorLeftRight = false;
mirrorAroundXaxis = true;
}
for( EDA_ITEM* item : selection )
{
@ -1318,7 +1363,11 @@ int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
case PCB_PAD_T:
{
PAD* pad = static_cast<PAD*>( item );
mirrorPadX( *pad, mirrorPoint );
if( mirrorLeftRight )
mirrorPadX( *pad, mirrorPoint );
else
mirrorPadY( *pad, mirrorPoint );
break;
}
@ -2192,7 +2241,8 @@ void EDIT_TOOL::setTransitions()
Go( &EDIT_TOOL::Duplicate, ACTIONS::duplicate.MakeEvent() );
Go( &EDIT_TOOL::Duplicate, PCB_ACTIONS::duplicateIncrement.MakeEvent() );
Go( &EDIT_TOOL::CreateArray, PCB_ACTIONS::createArray.MakeEvent() );
Go( &EDIT_TOOL::Mirror, PCB_ACTIONS::mirror.MakeEvent() );
Go( &EDIT_TOOL::Mirror, PCB_ACTIONS::mirrorH.MakeEvent() );
Go( &EDIT_TOOL::Mirror, PCB_ACTIONS::mirrorV.MakeEvent() );
Go( &EDIT_TOOL::Swap, PCB_ACTIONS::swap.MakeEvent() );
Go( &EDIT_TOOL::ChangeTrackWidth, PCB_ACTIONS::changeTrackWidth.MakeEvent() );
Go( &EDIT_TOOL::FilletTracks, PCB_ACTIONS::filletTracks.MakeEvent() );

View File

@ -846,7 +846,8 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference )
else if( evt->IsAction( &PCB_ACTIONS::rotateCw )
|| evt->IsAction( &PCB_ACTIONS::rotateCcw )
|| evt->IsAction( &PCB_ACTIONS::flip )
|| evt->IsAction( &PCB_ACTIONS::mirror ) )
|| evt->IsAction( &PCB_ACTIONS::mirrorH )
|| evt->IsAction( &PCB_ACTIONS::mirrorV ) )
{
updateBBox = true;
eatFirstMouseUp = false;

View File

@ -122,7 +122,8 @@ bool PAD_TOOL::Init()
ctxMenu.AddItem( PCB_ACTIONS::rotateCcw, SELECTION_CONDITIONS::ShowAlways );
ctxMenu.AddItem( PCB_ACTIONS::rotateCw, SELECTION_CONDITIONS::ShowAlways );
ctxMenu.AddItem( PCB_ACTIONS::flip, SELECTION_CONDITIONS::ShowAlways );
ctxMenu.AddItem( PCB_ACTIONS::mirror, SELECTION_CONDITIONS::ShowAlways );
ctxMenu.AddItem( PCB_ACTIONS::mirrorH, SELECTION_CONDITIONS::ShowAlways );
ctxMenu.AddItem( PCB_ACTIONS::mirrorV, SELECTION_CONDITIONS::ShowAlways );
ctxMenu.AddItem( PCB_ACTIONS::properties, SELECTION_CONDITIONS::ShowAlways );
// Finally, add the standard zoom/grid items

View File

@ -320,11 +320,16 @@ TOOL_ACTION PCB_ACTIONS::flip( "pcbnew.InteractiveEdit.flip",
_( "Change Side / Flip" ), _( "Flips selected item(s) to opposite side of board" ),
BITMAPS::swap_layer );
TOOL_ACTION PCB_ACTIONS::mirror( "pcbnew.InteractiveEdit.mirror",
TOOL_ACTION PCB_ACTIONS::mirrorH( "pcbnew.InteractiveEdit.mirrorHoriontally",
AS_GLOBAL, 0, "",
_( "Mirror" ), _( "Mirrors selected item" ),
_( "Mirror Horizontally" ), _( "Mirrors selected item across the Y axis" ),
BITMAPS::mirror_h );
TOOL_ACTION PCB_ACTIONS::mirrorV( "pcbnew.InteractiveEdit.mirrorVertically",
AS_GLOBAL, 0, "",
_( "Mirror Vertically" ), _( "Mirrors selected item across the X axis" ),
BITMAPS::mirror_v );
TOOL_ACTION PCB_ACTIONS::swap( "pcbnew.InteractiveEdit.swap",
AS_GLOBAL,
'S', "",

View File

@ -117,7 +117,8 @@ public:
static TOOL_ACTION flip;
/// Mirroring of selected items
static TOOL_ACTION mirror;
static TOOL_ACTION mirrorH;
static TOOL_ACTION mirrorV;
/// Swapping of selected items
static TOOL_ACTION swap;