From c661c30f68a65ca4eb5305053ee93d9854d04583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= Date: Fri, 2 Dec 2016 18:59:48 +0100 Subject: [PATCH] pcbnew: added flip view mode --- common/gal/graphics_abstraction_layer.cpp | 16 ++++++++-------- common/gal/opengl/opengl_gal.cpp | 15 +++++++++------ common/gal/opengl/shader.vert | 4 ++-- include/gal/graphics_abstraction_layer.h | 18 +++++++----------- include/wxPcbStruct.h | 1 + pcbnew/menubar_pcbframe.cpp | 5 +++++ pcbnew/pcbframe.cpp | 9 +++++++++ pcbnew/pcbnew_id.h | 1 + 8 files changed, 42 insertions(+), 27 deletions(-) diff --git a/common/gal/graphics_abstraction_layer.cpp b/common/gal/graphics_abstraction_layer.cpp index b5847fc707..b6206c790e 100644 --- a/common/gal/graphics_abstraction_layer.cpp +++ b/common/gal/graphics_abstraction_layer.cpp @@ -110,8 +110,9 @@ void GAL::ComputeWorldScreenMatrix() scale.SetScale( VECTOR2D( worldScale, worldScale ) ); MATRIX3x3D flip; + flip.SetIdentity(); - flip.SetScale( VECTOR2D( flipX, flipY ) ); + flip.SetScale( VECTOR2D( globalFlipX ? -1.0 : 1.0, globalFlipY ? -1.0 : 1.0 ) ); MATRIX3x3D lookat; lookat.SetIdentity(); @@ -150,9 +151,8 @@ void GAL::DrawGrid() int gridEndX = KiROUND( worldEndPoint.x / gridSize.x ); int gridStartY = KiROUND( worldStartPoint.y / gridSize.y ); int gridEndY = KiROUND( worldEndPoint.y / gridSize.y ); - - assert( gridEndX >= gridStartX ); - assert( gridEndY >= gridStartY ); + int dirX = gridEndX >= gridStartX ? 1 : -1; + int dirY = gridEndY >= gridStartY ? 1 : -1; // Correct the index, else some lines are not correctly painted gridStartX -= std::abs( gridOrigin.x / gridSize.x ) + 1; @@ -172,7 +172,7 @@ void GAL::DrawGrid() // Now draw the grid, every coarse grid line gets the double width // Vertical lines - for( int j = gridStartY; j < gridEndY; j += 1 ) + for( int j = gridStartY; j != gridEndY; j += dirY ) { if( j % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold ) SetLineWidth( doubleMarker ); @@ -188,7 +188,7 @@ void GAL::DrawGrid() } // Horizontal lines - for( int i = gridStartX; i < gridEndX; i += 1 ) + for( int i = gridStartX; i != gridEndX; i += dirX ) { if( i % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold ) SetLineWidth( doubleMarker ); @@ -210,14 +210,14 @@ void GAL::DrawGrid() SetIsStroke( false ); SetFillColor( gridColor ); - for( int j = gridStartY; j < gridEndY; j += 1 ) + for( int j = gridStartY; j != gridEndY; j += dirY ) { if( j % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold ) tickY = true; else tickY = false; - for( int i = gridStartX; i < gridEndX; i += 1 ) + for( int i = gridStartX; i != gridEndX; i += dirX ) { if( i % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold ) tickX = true; diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index c94bc4f94b..2fba9a2c2c 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -766,7 +766,11 @@ void OPENGL_GAL::BitmapText( const wxString& aText, const VECTOR2D& aPosition, currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); currentManager->Translate( aPosition.x, aPosition.y, layerDepth ); currentManager->Rotate( aRotationAngle, 0.0f, 0.0f, -1.0f ); - currentManager->Scale( SCALE, SCALE, 0 ); + + double sx = SCALE * (globalFlipX ? -1.0 : 1.0); + double sy = SCALE * (globalFlipY ? -1.0 : 1.0); + + currentManager->Scale( sx, sy, 0 ); currentManager->Translate( 0, -commonOffset, 0 ); switch( GetHorizontalJustify() ) @@ -874,9 +878,8 @@ void OPENGL_GAL::DrawGrid() int gridEndX = KiROUND( worldEndPoint.x / gridSize.x ); int gridStartY = KiROUND( worldStartPoint.y / gridSize.y ); int gridEndY = KiROUND( worldEndPoint.y / gridSize.y ); - - assert( gridEndX >= gridStartX ); - assert( gridEndY >= gridStartY ); + int dirX = gridStartX >= gridEndX ? -1 : 1; + int dirY = gridStartY >= gridEndY ? -1 : 1; // Correct the index, else some lines are not correctly painted gridStartX -= std::abs( gridOrigin.x / gridSize.x ) + 1; @@ -900,7 +903,7 @@ void OPENGL_GAL::DrawGrid() } // Vertical lines - for( int j = gridStartY; j < gridEndY; j += 1 ) + for( int j = gridStartY; j != gridEndY; j += dirY ) { if( j % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold ) glLineWidth( 2.0 ); @@ -924,7 +927,7 @@ void OPENGL_GAL::DrawGrid() } // Horizontal lines - for( int i = gridStartX; i < gridEndX; i += 1 ) + for( int i = gridStartX; i != gridEndX; i += dirX ) { if( i % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold ) glLineWidth( 2.0 ); diff --git a/common/gal/opengl/shader.vert b/common/gal/opengl/shader.vert index a937ff1d28..db8558de5f 100644 --- a/common/gal/opengl/shader.vert +++ b/common/gal/opengl/shader.vert @@ -47,7 +47,7 @@ void main() if( shaderParams[0] == SHADER_LINE ) { float lineWidth = shaderParams[3]; - float worldScale = gl_ModelViewMatrix[0][0]; + float worldScale = abs ( gl_ModelViewMatrix[0][0] ); // Make lines appear to be at least 1 pixel wide if( worldScale * lineWidth < MIN_WIDTH ) @@ -79,7 +79,7 @@ void main() // Make the line appear to be at least 1 pixel wide float lineWidth = shaderParams[3]; - float worldScale = gl_ModelViewMatrix[0][0]; + float worldScale = abs( gl_ModelViewMatrix[0][0] ); if( worldScale * lineWidth < MIN_WIDTH ) shaderParams[3] = shaderParams[3] / ( worldScale * lineWidth ); diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index 20f8130ba6..5b2044d224 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -49,6 +49,7 @@ enum GRID_STYLE GRID_STYLE_DOTS ///< Use dots for the grid }; + /** * @brief Class GAL is the abstract interface for drawing on a 2D-surface. * @@ -690,17 +691,11 @@ public: */ inline void SetFlip( bool xAxis, bool yAxis ) { - if( xAxis ) - flipX = -1.0; // flipped - else - flipX = 1.0; // regular - - if( yAxis ) - flipY = -1.0; // flipped - else - flipY = 1.0; // regular + globalFlipX = xAxis; + globalFlipY = yAxis; } + // --------------------------- // Buffer manipulation methods // --------------------------- @@ -978,8 +973,9 @@ protected: MATRIX3x3D worldScreenMatrix; ///< World transformation MATRIX3x3D screenWorldMatrix; ///< Screen transformation double worldScale; ///< The scale factor world->screen - double flipX; ///< Flag for X axis flipping - double flipY; ///< Flag for Y axis flipping + + bool globalFlipX; + bool globalFlipY; double lineWidth; ///< The line width diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index 55f8da62a7..296861474e 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -637,6 +637,7 @@ public: bool OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu ) override; void OnSelectOptionToolbar( wxCommandEvent& event ); + void OnFlipPcbView( wxCommandEvent& event ); void ToolOnRightClick( wxCommandEvent& event ) override; /* Block operations: */ diff --git a/pcbnew/menubar_pcbframe.cpp b/pcbnew/menubar_pcbframe.cpp index b787dd7e60..06acb07868 100644 --- a/pcbnew/menubar_pcbframe.cpp +++ b/pcbnew/menubar_pcbframe.cpp @@ -389,6 +389,11 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() text, _( "Switch the canvas implementation to Cairo" ), KiBitmap( tools_xpm ) ); + viewMenu->AppendSeparator(); + AddMenuItem( viewMenu, ID_MENU_PCB_FLIP_VIEW, _("&Flip View"), _( "Flips (mirrors) the board view." ), + KiBitmap( three_d_xpm ), wxITEM_CHECK ); + + //----- Place Menu ---------------------------------------------------------- wxMenu* placeMenu = new wxMenu; diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 18f69a9ae6..7a863a813e 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -115,6 +115,7 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) // Menu Files: EVT_MENU( ID_MAIN_MENUBAR, PCB_EDIT_FRAME::Process_Special_Functions ) + EVT_MENU( ID_MENU_PCB_FLIP_VIEW, PCB_EDIT_FRAME::OnFlipPcbView ) EVT_MENU( ID_APPEND_FILE, PCB_EDIT_FRAME::Files_io ) EVT_MENU( ID_SAVE_BOARD_AS, PCB_EDIT_FRAME::Files_io ) @@ -1131,3 +1132,11 @@ void PCB_EDIT_FRAME::OnUpdatePCBFromSch( wxCommandEvent& event ) Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_PCB_UPDATE_REQUEST, "", this ); } } + +void PCB_EDIT_FRAME::OnFlipPcbView(wxCommandEvent& evt) +{ + auto view = GetGalCanvas()->GetView(); + view->SetMirror( evt.IsChecked(), false ); + view->RecacheAllItems(); + GetGalCanvas()->ForceRefresh(); +} diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h index e5a6e90cbb..801a4e021c 100644 --- a/pcbnew/pcbnew_id.h +++ b/pcbnew/pcbnew_id.h @@ -52,6 +52,7 @@ enum pcbnew_ids ID_PCB_MASK_CLEARANCE, ID_PCB_LAYERS_SETUP, + ID_MENU_PCB_FLIP_VIEW, ID_POPUP_PCB_START_RANGE, ID_POPUP_PCB_MOVE_MODULE_REQUEST,