Commit abe5c08e authored by jean-pierre charras's avatar jean-pierre charras

3D-viewer: code cleaning. Added option in menu: show a 3D grid.

All: press ctrl+shift key when moving the mouse allows the graphic cursor to be moved outside the grid.
(useful to place graphic objects, texts in any position, regardless the current grid)
parent 7c3f47ec
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include <class_pcb_text.h> #include <class_pcb_text.h>
#include <3d_viewer.h> #include <3d_viewer.h>
#include <info3d_visu.h>
#include <trackball.h> #include <trackball.h>
...@@ -176,47 +177,45 @@ GLuint EDA_3D_CANVAS::DisplayCubeforTest() ...@@ -176,47 +177,45 @@ GLuint EDA_3D_CANVAS::DisplayCubeforTest()
} }
Info_3D_Visu::Info_3D_Visu() INFO3D_VISU::INFO3D_VISU()
{ {
int ii; int ii;
m_Beginx = m_Beginy = 0.0; /* position of mouse */ m_Beginx = m_Beginy = 0.0; // position of mouse
m_Zoom = 1.0; /* field of view in degrees */ m_Zoom = 1.0;
m_3D_Grid = 10.0; // Grid value in mm
trackball( m_Quat, 0.0, 0.0, 0.0, 0.0 ); trackball( m_Quat, 0.0, 0.0, 0.0, 0.0 );
for( ii = 0; ii < 4; ii++ ) for( ii = 0; ii < 4; ii++ )
m_Rot[ii] = 0.0; m_Rot[ii] = 0.0;
m_Layers = 1; m_CopperLayersCount = 2;
m_BoardSettings = NULL; m_BoardSettings = NULL;
// default all special item layers Visible // default all special item layers Visible
for (ii=0; ii< FL_LAST; ii++) for( ii = 0; ii < FL_LAST; ii++)
m_DrawFlags[ii]=true; m_DrawFlags[ii] = true;
m_DrawFlags[FL_GRID] = false;
} }
Info_3D_Visu::~Info_3D_Visu() INFO3D_VISU::~INFO3D_VISU()
{ {
} }
WinEDA_VertexCtrl::WinEDA_VertexCtrl( wxWindow* parent, const wxString& title, VERTEX_VALUE_CTRL::VERTEX_VALUE_CTRL( wxWindow* parent, const wxString& title,
wxBoxSizer* BoxSizer, wxBoxSizer* BoxSizer )
EDA_UNITS_T units, int internal_unit )
{ {
wxString text; wxString text;
wxStaticText* msgtitle; wxStaticText* msgtitle;
m_Units = units;
m_Internal_Unit = internal_unit;
if( title.IsEmpty() ) if( title.IsEmpty() )
text = _( "Vertex " ); text = _( "Vertex " );
else else
text = title; text = title;
text += ReturnUnitSymbol( units );
msgtitle = new wxStaticText( parent, -1, text, wxDefaultPosition, wxSize( -1, -1 ), 0 ); msgtitle = new wxStaticText( parent, -1, text, wxDefaultPosition, wxSize( -1, -1 ), 0 );
BoxSizer->Add( msgtitle, wxGROW | wxLEFT | wxRIGHT | wxTOP | wxBOTTOM ); BoxSizer->Add( msgtitle, wxGROW | wxLEFT | wxRIGHT | wxTOP | wxBOTTOM );
...@@ -267,12 +266,12 @@ WinEDA_VertexCtrl::WinEDA_VertexCtrl( wxWindow* parent, const wxString& title, ...@@ -267,12 +266,12 @@ WinEDA_VertexCtrl::WinEDA_VertexCtrl( wxWindow* parent, const wxString& title,
} }
WinEDA_VertexCtrl::~WinEDA_VertexCtrl() VERTEX_VALUE_CTRL::~VERTEX_VALUE_CTRL()
{ {
} }
S3D_Vertex WinEDA_VertexCtrl::GetValue() S3D_Vertex VERTEX_VALUE_CTRL::GetValue()
{ {
S3D_Vertex value; S3D_Vertex value;
double dtmp; double dtmp;
...@@ -287,7 +286,7 @@ S3D_Vertex WinEDA_VertexCtrl::GetValue() ...@@ -287,7 +286,7 @@ S3D_Vertex WinEDA_VertexCtrl::GetValue()
} }
void WinEDA_VertexCtrl::SetValue( S3D_Vertex vertex ) void VERTEX_VALUE_CTRL::SetValue( S3D_Vertex vertex )
{ {
wxString text; wxString text;
...@@ -305,7 +304,7 @@ void WinEDA_VertexCtrl::SetValue( S3D_Vertex vertex ) ...@@ -305,7 +304,7 @@ void WinEDA_VertexCtrl::SetValue( S3D_Vertex vertex )
} }
void WinEDA_VertexCtrl::Enable( bool onoff ) void VERTEX_VALUE_CTRL::Enable( bool onoff )
{ {
m_XValueCtrl->Enable( onoff ); m_XValueCtrl->Enable( onoff );
m_YValueCtrl->Enable( onoff ); m_YValueCtrl->Enable( onoff );
......
...@@ -17,7 +17,9 @@ ...@@ -17,7 +17,9 @@
#include <gestfich.h> #include <gestfich.h>
#include <3d_viewer.h> #include <3d_viewer.h>
#include <info3d_visu.h>
#include <trackball.h> #include <trackball.h>
#include <3d_viewer_id.h>
// ----------------- // -----------------
......
...@@ -6,13 +6,6 @@ ...@@ -6,13 +6,6 @@
#include <3d_viewer.h> #include <3d_viewer.h>
S3D_Vertex::S3D_Vertex()
{
x = y = z = 0.0;
}
S3D_MATERIAL::S3D_MATERIAL( S3D_MASTER* father, const wxString& name ) : S3D_MATERIAL::S3D_MATERIAL( S3D_MASTER* father, const wxString& name ) :
EDA_ITEM( father, NOT_USED ) EDA_ITEM( father, NOT_USED )
{ {
......
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -47,21 +45,18 @@ ...@@ -47,21 +45,18 @@
#include <colors_selection.h> #include <colors_selection.h>
#include <3d_viewer.h> #include <3d_viewer.h>
#include <info3d_visu.h>
#include <trackball.h> #include <trackball.h>
#if !wxUSE_GLCANVAS
#error Please set wxUSE_GLCANVAS to 1 in setup.h.
#endif
extern void CheckGLError(); extern void CheckGLError();
static void Draw3D_FilledCircle( double posx, double posy, double rayon, static void Draw3D_FilledCircle( double posx, double posy, double radius,
double hole_rayon, double zpos ); double hole_radius, double zpos );
static void Draw3D_FilledSegment( double startx, double starty, static void Draw3D_FilledSegment( double startx, double starty,
double endx, double endy, double endx, double endy,
double width, double zpos ); double width, double zpos );
static void Draw3D_FilledCylinder( double posx, double posy, double rayon, static void Draw3D_ZaxisCylinder( const S3D_Vertex& aPos, double aRadius, double aHeight );
double height, double zpos );
static void Draw3D_FilledSegmentWithHole( double startx, double starty, static void Draw3D_FilledSegmentWithHole( double startx, double starty,
double endx, double endy, double endx, double endy,
double width, double holex, double width, double holex,
...@@ -93,11 +88,7 @@ void EDA_3D_CANVAS::Redraw( bool finish ) ...@@ -93,11 +88,7 @@ void EDA_3D_CANVAS::Redraw( bool finish )
if( !IsShown() ) if( !IsShown() )
return; return;
#if wxCHECK_VERSION( 2, 7, 0 )
SetCurrent( *m_glRC ); SetCurrent( *m_glRC );
#else
SetCurrent();
#endif
// Set the OpenGL viewport according to the client size of this canvas. // Set the OpenGL viewport according to the client size of this canvas.
// This is done here rather than in a wxSizeEvent handler because our // This is done here rather than in a wxSizeEvent handler because our
...@@ -136,7 +127,7 @@ void EDA_3D_CANVAS::Redraw( bool finish ) ...@@ -136,7 +127,7 @@ void EDA_3D_CANVAS::Redraw( bool finish )
} }
glFlush(); glFlush();
if( finish ); if( finish )
glFinish(); glFinish();
SwapBuffers(); SwapBuffers();
...@@ -163,39 +154,94 @@ GLuint EDA_3D_CANVAS::CreateDrawGL_List() ...@@ -163,39 +154,94 @@ GLuint EDA_3D_CANVAS::CreateDrawGL_List()
g_Parm_3D_Visu.m_BoardPos = bbbox.Centre(); g_Parm_3D_Visu.m_BoardPos = bbbox.Centre();
g_Parm_3D_Visu.m_BoardPos.y = -g_Parm_3D_Visu.m_BoardPos.y; g_Parm_3D_Visu.m_BoardPos.y = -g_Parm_3D_Visu.m_BoardPos.y;
g_Parm_3D_Visu.m_Layers = pcb->GetCopperLayerCount(); g_Parm_3D_Visu.m_CopperLayersCount = pcb->GetCopperLayerCount();
// Ensure the board has 2 sides for 3D views, because it is hard to find // Ensure the board has 2 sides for 3D views, because it is hard to find
// a *really* single side board in the true life... // a *really* single side board in the true life...
if( g_Parm_3D_Visu.m_Layers < 2 ) if( g_Parm_3D_Visu.m_CopperLayersCount < 2 )
g_Parm_3D_Visu.m_Layers = 2; g_Parm_3D_Visu.m_CopperLayersCount = 2;
g_Parm_3D_Visu.m_BoardScale = 2.0 / std::max( g_Parm_3D_Visu.m_BoardSize.x, g_Parm_3D_Visu.m_BoardScale = 2.0 / std::max( g_Parm_3D_Visu.m_BoardSize.x,
g_Parm_3D_Visu.m_BoardSize.y ); g_Parm_3D_Visu.m_BoardSize.y );
g_Parm_3D_Visu.m_Epoxy_Width = pcb->GetDesignSettings().GetBoardThickness() g_Parm_3D_Visu.m_EpoxyThickness = pcb->GetDesignSettings().GetBoardThickness()
* g_Parm_3D_Visu.m_BoardScale; * g_Parm_3D_Visu.m_BoardScale;
// Arbitrary choose a thickness for non copper layers:
g_Parm_3D_Visu.m_NonCopperLayerThickness = g_Parm_3D_Visu.m_EpoxyThickness / 20;
// calculate z position for each layer // Init Z position of each layer
for( ii = 0; ii < 32; ii++ ) // calculate z position for each copper layer
for( ii = 0; ii < g_Parm_3D_Visu.m_CopperLayersCount; ii++ )
{ {
if( ii < g_Parm_3D_Visu.m_Layers ) g_Parm_3D_Visu.m_LayerZcoord[ii] = g_Parm_3D_Visu.m_EpoxyThickness
g_Parm_3D_Visu.m_LayerZcoord[ii] = g_Parm_3D_Visu.m_Epoxy_Width * ii / (g_Parm_3D_Visu.m_CopperLayersCount - 1);
* ii / (g_Parm_3D_Visu.m_Layers - 1); }
else double zpos_copper_back = g_Parm_3D_Visu.m_LayerZcoord[0];
g_Parm_3D_Visu.m_LayerZcoord[ii] = g_Parm_3D_Visu.m_Epoxy_Width; double zpos_copper_front = g_Parm_3D_Visu.m_EpoxyThickness;
// Fill remaining unused copper layers and front layer zpos
// with g_Parm_3D_Visu.m_EpoxyThickness
for( ; ii <= LAST_COPPER_LAYER; ii++ )
{
g_Parm_3D_Visu.m_LayerZcoord[ii] = g_Parm_3D_Visu.m_EpoxyThickness;
}
// calculate z position for each non copper layer
for( int layer_id = FIRST_NO_COPPER_LAYER; layer_id < NB_LAYERS; layer_id++ )
{
double zpos;
switch( layer_id )
{
case ADHESIVE_N_BACK:
zpos = zpos_copper_back -
4 * g_Parm_3D_Visu.m_NonCopperLayerThickness;
break;
case ADHESIVE_N_FRONT:
zpos = zpos_copper_front +
4 * g_Parm_3D_Visu.m_NonCopperLayerThickness;
break;
case SOLDERPASTE_N_BACK:
zpos = zpos_copper_back -
3 * g_Parm_3D_Visu.m_NonCopperLayerThickness;
break;
case SOLDERPASTE_N_FRONT:
zpos = zpos_copper_front +
3 * g_Parm_3D_Visu.m_NonCopperLayerThickness;
break;
case SOLDERMASK_N_BACK:
zpos = zpos_copper_back -
1 * g_Parm_3D_Visu.m_NonCopperLayerThickness;
break;
case SOLDERMASK_N_FRONT:
zpos = zpos_copper_front +
1 * g_Parm_3D_Visu.m_NonCopperLayerThickness;
break;
case SILKSCREEN_N_BACK:
zpos = zpos_copper_back -
2 * g_Parm_3D_Visu.m_NonCopperLayerThickness;
break;
case SILKSCREEN_N_FRONT:
zpos = zpos_copper_front +
2 * g_Parm_3D_Visu.m_NonCopperLayerThickness;
break;
default:
zpos = zpos_copper_front +
(layer_id - FIRST_NO_COPPER_LAYER + 5) *
g_Parm_3D_Visu.m_NonCopperLayerThickness;
break;
} }
GLfloat zpos_cu = 10 * g_Parm_3D_Visu.m_BoardScale; g_Parm_3D_Visu.m_LayerZcoord[layer_id] = zpos;
GLfloat zpos_cmp = g_Parm_3D_Visu.m_Epoxy_Width + zpos_cu; }
g_Parm_3D_Visu.m_LayerZcoord[ADHESIVE_N_BACK] = -zpos_cu * 2;
g_Parm_3D_Visu.m_LayerZcoord[ADHESIVE_N_FRONT] = zpos_cmp + zpos_cu;
g_Parm_3D_Visu.m_LayerZcoord[SILKSCREEN_N_BACK] = -zpos_cu;
g_Parm_3D_Visu.m_LayerZcoord[SILKSCREEN_N_FRONT] = zpos_cmp;
g_Parm_3D_Visu.m_LayerZcoord[DRAW_N] = zpos_cmp + zpos_cu;
g_Parm_3D_Visu.m_LayerZcoord[COMMENT_N] = zpos_cmp + zpos_cu;
g_Parm_3D_Visu.m_LayerZcoord[ECO1_N] = zpos_cmp + zpos_cu;
g_Parm_3D_Visu.m_LayerZcoord[ECO2_N] = zpos_cmp + zpos_cu;
glNewList( m_gllist, GL_COMPILE_AND_EXECUTE ); glNewList( m_gllist, GL_COMPILE_AND_EXECUTE );
...@@ -362,9 +408,11 @@ GLuint EDA_3D_CANVAS::CreateDrawGL_List() ...@@ -362,9 +408,11 @@ GLuint EDA_3D_CANVAS::CreateDrawGL_List()
MODULE* Module = pcb->m_Modules; MODULE* Module = pcb->m_Modules;
for( ; Module != NULL; Module = Module->Next() ) for( ; Module != NULL; Module = Module->Next() )
{
Module->Draw3D( this ); Module->Draw3D( this );
}
// Draw grid
if( g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_GRID] )
DrawGrid( g_Parm_3D_Visu.m_3D_Grid );
glEndList(); glEndList();
...@@ -375,12 +423,140 @@ GLuint EDA_3D_CANVAS::CreateDrawGL_List() ...@@ -375,12 +423,140 @@ GLuint EDA_3D_CANVAS::CreateDrawGL_List()
} }
// draw mm grid..
void EDA_3D_CANVAS::DrawGrid( double aGriSizeMM )
{
double zpos = -g_Parm_3D_Visu.m_NonCopperLayerThickness/2;
int gridcolor = DARKGRAY; // Color of grid lines
int gridcolor_marker = LIGHTGRAY; // Color of grid lines every 5 lines
double scale = g_Parm_3D_Visu.m_BoardScale;
glNormal3f( 0.0, 0.0, 1.0 );
wxSize brd_size = g_Parm_3D_Visu.m_BoardSize;
wxPoint brd_center_pos = g_Parm_3D_Visu.m_BoardPos;
NEGATE( brd_center_pos.y );
int xsize = std::max( brd_size.x, Millimeter2iu( 100 ) );
int ysize = std::max( brd_size.y, Millimeter2iu( 100 ) );
// Grid limits, in 3D units
double xmin = (brd_center_pos.x - xsize/2) * scale;
double xmax = (brd_center_pos.x + xsize/2) * scale;
double ymin = (brd_center_pos.y - ysize/2) * scale;
double ymax = (brd_center_pos.y + ysize/2) * scale;
double zmin = Millimeter2iu( -50 ) * scale;
double zmax = Millimeter2iu( 100 ) * scale;
// Draw horizontal grid centered on 3D origin (center of the board)
for( int ii = 0; ; ii++ )
{
if( (ii % 5) )
SetGLColor( gridcolor );
else
SetGLColor( gridcolor_marker );
int delta = KiROUND( ii * aGriSizeMM * IU_PER_MM );
if( delta <= xsize/2 ) // Draw grid lines parallel to X axis
{
glBegin(GL_LINES);
glVertex3f( (brd_center_pos.x + delta) * scale, -ymin, zpos );
glVertex3f( (brd_center_pos.x + delta) * scale, -ymax, zpos );
glEnd();
if( ii != 0 )
{
glBegin(GL_LINES);
glVertex3f( (brd_center_pos.x - delta) * scale, -ymin, zpos );
glVertex3f( (brd_center_pos.x - delta) * scale, -ymax, zpos );
glEnd();
}
}
if( delta <= ysize/2 ) // Draw grid lines parallel to Y axis
{
glBegin(GL_LINES);
glVertex3f( xmin, -(brd_center_pos.y + delta) * scale, zpos );
glVertex3f( xmax, -(brd_center_pos.y + delta) * scale, zpos );
glEnd();
if( ii != 0 )
{
glBegin(GL_LINES);
glVertex3f( xmin, -(brd_center_pos.y - delta) * scale, zpos );
glVertex3f( xmax, -(brd_center_pos.y - delta) * scale, zpos );
glEnd();
}
}
if( ( delta > ysize/2 ) && ( delta > xsize/2 ) )
break;
}
// Draw vertical grid n Z axis
glNormal3f( 0.0, -1.0, 0.0 );
// Draw vertical grid lines (parallel to Z axis)
for( int ii = 0; ; ii++ )
{
if( (ii % 5) )
SetGLColor( gridcolor );
else
SetGLColor( gridcolor_marker );
double delta = ii * aGriSizeMM * IU_PER_MM;
glBegin(GL_LINES);
glVertex3f( (brd_center_pos.x + delta) * scale, -brd_center_pos.y * scale, zmin );
glVertex3f( (brd_center_pos.x + delta) * scale, -brd_center_pos.y * scale, zmax );
glEnd();
if( ii != 0 )
{
glBegin(GL_LINES);
glVertex3f( (brd_center_pos.x - delta) * scale, -brd_center_pos.y * scale, zmin );
glVertex3f( (brd_center_pos.x - delta) * scale, -brd_center_pos.y * scale, zmax );
glEnd();
}
if( delta > xsize/2 )
break;
}
// Draw horizontal grid lines on Z axis
for( int ii = 0; ; ii++ )
{
if( (ii % 5) )
SetGLColor( gridcolor );
else
SetGLColor( gridcolor_marker );
double delta = ii * aGriSizeMM * IU_PER_MM * scale;
if( delta <= zmax )
{ // Draw grid lines on Z axis (positive Z axis coordinates)
glBegin(GL_LINES);
glVertex3f(xmin, -brd_center_pos.y * scale, delta);
glVertex3f(xmax, -brd_center_pos.y * scale, delta);
glEnd();
}
if( delta <= -zmin && ( ii != 0 ) )
{ // Draw grid lines on Z axis (negative Z axis coordinates)
glBegin(GL_LINES);
glVertex3f(xmin, -brd_center_pos.y * scale, -delta);
glVertex3f(xmax, -brd_center_pos.y * scale, -delta);
glEnd();
}
if( ( delta > zmax ) && ( delta > -zmin ) )
break;
}
}
void EDA_3D_CANVAS::Draw3D_Track( TRACK* track ) void EDA_3D_CANVAS::Draw3D_Track( TRACK* track )
{ {
double zpos;
int layer = track->GetLayer(); int layer = track->GetLayer();
double ox, oy, fx, fy;
double w;
if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false ) if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
return; return;
...@@ -388,18 +564,18 @@ void EDA_3D_CANVAS::Draw3D_Track( TRACK* track ) ...@@ -388,18 +564,18 @@ void EDA_3D_CANVAS::Draw3D_Track( TRACK* track )
int color = g_ColorsSettings.GetLayerColor( layer ); int color = g_ColorsSettings.GetLayerColor( layer );
if( layer == LAST_COPPER_LAYER ) if( layer == LAST_COPPER_LAYER )
layer = g_Parm_3D_Visu.m_Layers - 1; layer = g_Parm_3D_Visu.m_CopperLayersCount - 1;
zpos = g_Parm_3D_Visu.m_LayerZcoord[layer]; double zpos = g_Parm_3D_Visu.m_LayerZcoord[layer];
SetGLColor( color ); SetGLColor( color );
glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 ); glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 );
w = track->m_Width * g_Parm_3D_Visu.m_BoardScale; double w = track->m_Width * g_Parm_3D_Visu.m_BoardScale;
ox = track->m_Start.x * g_Parm_3D_Visu.m_BoardScale; double ox = track->m_Start.x * g_Parm_3D_Visu.m_BoardScale;
oy = track->m_Start.y * g_Parm_3D_Visu.m_BoardScale; double oy = track->m_Start.y * g_Parm_3D_Visu.m_BoardScale;
fx = track->m_End.x * g_Parm_3D_Visu.m_BoardScale; double fx = track->m_End.x * g_Parm_3D_Visu.m_BoardScale;
fy = track->m_End.y * g_Parm_3D_Visu.m_BoardScale; double fy = track->m_End.y * g_Parm_3D_Visu.m_BoardScale;
Draw3D_FilledSegment( ox, -oy, fx, -fy, w, zpos ); Draw3D_FilledSegment( ox, -oy, fx, -fy, w, zpos );
} }
...@@ -415,7 +591,7 @@ void EDA_3D_CANVAS::Draw3D_SolidPolygonsInZones( ZONE_CONTAINER* aZone ) ...@@ -415,7 +591,7 @@ void EDA_3D_CANVAS::Draw3D_SolidPolygonsInZones( ZONE_CONTAINER* aZone )
int color = g_ColorsSettings.GetLayerColor( layer ); int color = g_ColorsSettings.GetLayerColor( layer );
if( layer == LAST_COPPER_LAYER ) if( layer == LAST_COPPER_LAYER )
layer = g_Parm_3D_Visu.m_Layers - 1; layer = g_Parm_3D_Visu.m_CopperLayersCount - 1;
zpos = g_Parm_3D_Visu.m_LayerZcoord[layer]; zpos = g_Parm_3D_Visu.m_LayerZcoord[layer];
g_Parm_3D_Visu.m_ActZpos = zpos; g_Parm_3D_Visu.m_ActZpos = zpos;
...@@ -433,7 +609,7 @@ void EDA_3D_CANVAS::Draw3D_SolidPolygonsInZones( ZONE_CONTAINER* aZone ) ...@@ -433,7 +609,7 @@ void EDA_3D_CANVAS::Draw3D_SolidPolygonsInZones( ZONE_CONTAINER* aZone )
GLdouble v_data[3]; GLdouble v_data[3];
v_data[2] = zpos; v_data[2] = zpos;
//gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); //gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
// Draw solid areas contained in this zone // Draw solid areas contained in this zone
int StartContour = 1; int StartContour = 1;
...@@ -480,11 +656,11 @@ void EDA_3D_CANVAS::Draw3D_Via( SEGVIA* via ) ...@@ -480,11 +656,11 @@ void EDA_3D_CANVAS::Draw3D_Via( SEGVIA* via )
via->ReturnLayerPair( &top_layer, &bottom_layer ); via->ReturnLayerPair( &top_layer, &bottom_layer );
// Drawing filled circles: // Drawing filled circles:
for( layer = bottom_layer; layer < g_Parm_3D_Visu.m_Layers; layer++ ) for( layer = bottom_layer; layer < g_Parm_3D_Visu.m_CopperLayersCount; layer++ )
{ {
zpos = g_Parm_3D_Visu.m_LayerZcoord[layer]; zpos = g_Parm_3D_Visu.m_LayerZcoord[layer];
if( layer < g_Parm_3D_Visu.m_Layers - 1 ) if( layer < g_Parm_3D_Visu.m_CopperLayersCount - 1 )
{ {
if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false ) if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false )
continue; continue;
...@@ -519,7 +695,8 @@ void EDA_3D_CANVAS::Draw3D_Via( SEGVIA* via ) ...@@ -519,7 +695,8 @@ void EDA_3D_CANVAS::Draw3D_Via( SEGVIA* via )
color = g_ColorsSettings.GetItemColor( VIAS_VISIBLE + via->m_Shape ); color = g_ColorsSettings.GetItemColor( VIAS_VISIBLE + via->m_Shape );
SetGLColor( color ); SetGLColor( color );
height = g_Parm_3D_Visu.m_LayerZcoord[top_layer] - g_Parm_3D_Visu.m_LayerZcoord[bottom_layer]; height = g_Parm_3D_Visu.m_LayerZcoord[top_layer] - g_Parm_3D_Visu.m_LayerZcoord[bottom_layer];
Draw3D_FilledCylinder( x, -y, hole, height, g_Parm_3D_Visu.m_LayerZcoord[bottom_layer] ); S3D_Vertex position( x, -y, g_Parm_3D_Visu.m_LayerZcoord[bottom_layer] );
Draw3D_ZaxisCylinder( position, hole, height );
} }
...@@ -547,7 +724,7 @@ void EDA_3D_CANVAS::Draw3D_DrawSegment( DRAWSEGMENT* segment ) ...@@ -547,7 +724,7 @@ void EDA_3D_CANVAS::Draw3D_DrawSegment( DRAWSEGMENT* segment )
if( layer == EDGE_N ) if( layer == EDGE_N )
{ {
for( layer = 0; layer < g_Parm_3D_Visu.m_Layers; layer++ ) for( layer = 0; layer < g_Parm_3D_Visu.m_CopperLayersCount; layer++ )
{ {
glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 ); glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 );
zpos = g_Parm_3D_Visu.m_LayerZcoord[layer]; zpos = g_Parm_3D_Visu.m_LayerZcoord[layer];
...@@ -761,7 +938,7 @@ void EDGE_MODULE::Draw3D( EDA_3D_CANVAS* glcanvas ) ...@@ -761,7 +938,7 @@ void EDGE_MODULE::Draw3D( EDA_3D_CANVAS* glcanvas )
if( m_Layer == EDGE_N ) if( m_Layer == EDGE_N )
{ {
for( int layer = 0; layer < g_Parm_3D_Visu.m_Layers; layer++ ) for( int layer = 0; layer < g_Parm_3D_Visu.m_CopperLayersCount; layer++ )
{ {
glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 ); glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 );
zpos = g_Parm_3D_Visu.m_LayerZcoord[layer]; zpos = g_Parm_3D_Visu.m_LayerZcoord[layer];
...@@ -899,12 +1076,14 @@ void D_PAD::Draw3D( EDA_3D_CANVAS* glcanvas ) ...@@ -899,12 +1076,14 @@ void D_PAD::Draw3D( EDA_3D_CANVAS* glcanvas )
if( holeX && holeY ) if( holeX && holeY )
{ {
SetGLColor( DARKGRAY ); SetGLColor( DARKGRAY );
Draw3D_FilledCylinder( drillx, -drilly, hole, S3D_Vertex position( drillx, -drilly, g_Parm_3D_Visu.m_LayerZcoord[LAYER_N_BACK] );
g_Parm_3D_Visu.m_LayerZcoord[LAYER_N_FRONT], 0.0 ); double height = g_Parm_3D_Visu.m_LayerZcoord[LAYER_N_FRONT] -
g_Parm_3D_Visu.m_LayerZcoord[LAYER_N_BACK];
Draw3D_ZaxisCylinder( position, hole, height );
} }
glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis
nlmax = g_Parm_3D_Visu.m_Layers - 1; nlmax = g_Parm_3D_Visu.m_CopperLayersCount - 1;
Oncu = (m_layerMask & LAYER_BACK) ? true : false; Oncu = (m_layerMask & LAYER_BACK) ? true : false;
Oncmp = (m_layerMask & LAYER_FRONT) ? true : false; Oncmp = (m_layerMask & LAYER_FRONT) ? true : false;
Both = Oncu && Oncmp; Both = Oncu && Oncmp;
...@@ -1104,54 +1283,50 @@ void SetGLColor( int color ) ...@@ -1104,54 +1283,50 @@ void SetGLColor( int color )
static void Draw3D_FilledCircle( double posx, double posy, static void Draw3D_FilledCircle( double posx, double posy,
double rayon, double hole, double zpos ) double radius, double hole, double zpos )
{ {
int ii, slice = 16; const int slice = 16;
double x, y; const int rot_angle = 3600/16;
glBegin( GL_QUAD_STRIP ); glBegin( GL_QUAD_STRIP );
for( ii = 0; ii <= slice; ii++ ) for( int ii = 0; ii <= slice; ii++ )
{ {
x = hole; double x = hole;
y = 0.0; double y = 0.0;
RotatePoint( &x, &y, ii * 225 ); RotatePoint( &x, &y, ii * rot_angle );
glVertex3f( x + posx, y + posy, zpos ); glVertex3f( x + posx, y + posy, zpos );
x = rayon; x = radius;
y = 0.0; y = 0.0;
RotatePoint( &x, &y, ii * 225 ); RotatePoint( &x, &y, ii * rot_angle );
glVertex3f( x + posx, y + posy, zpos ); glVertex3f( x + posx, y + posy, zpos );
} }
glEnd(); glEnd();
} }
static void Draw3D_ZaxisCylinder( const S3D_Vertex& aPos, double aRadius, double aHeight )
static void Draw3D_FilledCylinder( double posx, double posy, double rayon,
double height, double zpos )
{ {
int ii; const int slice = 12;
double x, y;
#define NB_SEGM 12
std::vector< S3D_Vertex > coords; std::vector< S3D_Vertex > coords;
coords.resize( 4 ); coords.resize( 4 );
double tmp = DataScale3D; double tmp = DataScale3D;
DataScale3D = 1.0; // Coordinate is already in range for Set_Object_Data(); DataScale3D = 1.0; // Coordinate is already in range for Set_Object_Data();
coords[0].x = coords[1].x = posx + rayon;
coords[0].y = coords[1].y = posy;
coords[0].z = coords[3].z = zpos;
coords[1].z = coords[2].z = zpos + height;
for( ii = 0; ii <= NB_SEGM; ii++ ) coords[0].x = coords[1].x = aPos.x + aRadius;
coords[0].y = coords[1].y = aPos.y;
coords[0].z = coords[3].z = aPos.z;
coords[1].z = coords[2].z = aPos.z + aHeight;
for( int ii = 0; ii <= slice; ii++ )
{ {
x = rayon; double x = aRadius;
y = 0.0; double y = 0.0;
RotatePoint( &x, &y, ii * (3600 / NB_SEGM) ); RotatePoint( &x, &y, ii * (3600 / slice) );
coords[2].x = coords[3].x = posx + x; coords[2].x = coords[3].x = aPos.x + x;
coords[2].y = coords[3].y = posy + y; coords[2].y = coords[3].y = aPos.y + y;
Set_Object_Data( coords ); Set_Object_Data( coords );
coords[0].x = coords[2].x; coords[0].x = coords[2].x;
coords[0].y = coords[2].y; coords[0].y = coords[2].y;
...@@ -1183,11 +1358,12 @@ static void Draw3D_FilledSegment( double startx, double starty, double endx, ...@@ -1183,11 +1358,12 @@ static void Draw3D_FilledSegment( double startx, double starty, double endx,
glBegin( GL_POLYGON ); glBegin( GL_POLYGON );
// Trace the flare to right (1st half polygon at the end of the segment) // Trace the flare to right (1st half polygon at the end of the segment)
for( ii = 0; ii <= 8; ii++ ) const int slice = 16;
for( ii = 0; ii <= slice/2; ii++ )
{ {
x = 0.0; x = 0.0;
y = -width; y = -width;
RotatePoint( &x, &y, -ii * 225 ); RotatePoint( &x, &y, -ii * 3600/slice );
x += dx; x += dx;
RotatePoint( &x, &y, -angle ); RotatePoint( &x, &y, -angle );
glVertex3f( startx + x, starty + y, zpos ); glVertex3f( startx + x, starty + y, zpos );
...@@ -1200,9 +1376,9 @@ static void Draw3D_FilledSegment( double startx, double starty, double endx, ...@@ -1200,9 +1376,9 @@ static void Draw3D_FilledSegment( double startx, double starty, double endx,
} }
// Rounding the left (2nd half polygon is the origin of the segment) // Rounding the left (2nd half polygon is the origin of the segment)
for( ii = 0; ii <= 8; ii++ ) for( ii = 0; ii <= slice/2; ii++ )
{ {
int jj = ii * 225; int jj = ii * 3600/slice;
x = 0.0; x = 0.0;
y = width; y = width;
RotatePoint( &x, &y, -angle - jj ); RotatePoint( &x, &y, -angle - jj );
...@@ -1228,7 +1404,7 @@ static void Draw3D_FilledSegmentWithHole( double startx, double starty, ...@@ -1228,7 +1404,7 @@ static void Draw3D_FilledSegmentWithHole( double startx, double starty,
// Calculate the coordinates of the segment assumed horizontal // Calculate the coordinates of the segment assumed horizontal
// Then turn the strips of the desired angle // Then turn the strips of the desired angle
// All calculations are done with startx, starty as the origin of the route // All calculations are done with startx, starty as local origin
endx -= startx; endx -= startx;
endy -= starty; endy -= starty;
holex -= startx; holex -= startx;
...@@ -1294,14 +1470,12 @@ static void Draw3D_FilledSegmentWithHole( double startx, double starty, ...@@ -1294,14 +1470,12 @@ static void Draw3D_FilledSegmentWithHole( double startx, double starty,
static void Draw3D_ArcSegment( double startx, double starty, double centrex, static void Draw3D_ArcSegment( double startx, double starty, double centrex,
double centrey, double arc_angle, double width, double zpos ) double centrey, double arc_angle, double width, double zpos )
{ {
int ii; const int slice = 36; // Number of segments to approximate a circle by segments
int slice = 36; // Number of segments to approximate a circle by segments
double hole, rayon;
double arcStart_Angle; double arcStart_Angle;
arcStart_Angle = (atan2( startx - centrex, starty - centrey ) * 1800 / M_PI ); arcStart_Angle = (atan2( startx - centrex, starty - centrey ) * 1800 / M_PI );
rayon = hypot( startx - centrex, starty - centrey ) + ( width / 2); double radius = hypot( startx - centrex, starty - centrey ) + ( width / 2);
hole = rayon - width; double hole = radius - width;
// Calculate the number of segments to approximate this arc // Calculate the number of segments to approximate this arc
int imax = (int) ( (double) arc_angle * slice / 3600.0 ); int imax = (int) ( (double) arc_angle * slice / 3600.0 );
...@@ -1318,7 +1492,7 @@ static void Draw3D_ArcSegment( double startx, double starty, double centrex, ...@@ -1318,7 +1492,7 @@ static void Draw3D_ArcSegment( double startx, double starty, double centrex,
glBegin( GL_QUAD_STRIP ); glBegin( GL_QUAD_STRIP );
for( ii = 0; ii <= imax; ii++ ) for( int ii = 0; ii <= imax; ii++ )
{ {
double angle = (double) ii * delta_angle; double angle = (double) ii * delta_angle;
angle += arcStart_Angle + 900; angle += arcStart_Angle + 900;
...@@ -1326,7 +1500,7 @@ static void Draw3D_ArcSegment( double startx, double starty, double centrex, ...@@ -1326,7 +1500,7 @@ static void Draw3D_ArcSegment( double startx, double starty, double centrex,
double dy = 0.0; double dy = 0.0;
RotatePoint( &dx, &dy, (int) angle ); RotatePoint( &dx, &dy, (int) angle );
glVertex3f( dx + startx, dy + starty, zpos ); glVertex3f( dx + startx, dy + starty, zpos );
dx = rayon; dx = radius;
dy = 0.0; dy = 0.0;
RotatePoint( &dx, &dy, (int) angle ); RotatePoint( &dx, &dy, (int) angle );
glVertex3f( dx + startx, dy + starty, zpos ); glVertex3f( dx + startx, dy + starty, zpos );
...@@ -1339,20 +1513,20 @@ static void Draw3D_ArcSegment( double startx, double starty, double centrex, ...@@ -1339,20 +1513,20 @@ static void Draw3D_ArcSegment( double startx, double starty, double centrex,
static void Draw3D_CircleSegment( double startx, double starty, double endx, static void Draw3D_CircleSegment( double startx, double starty, double endx,
double endy, double width, double zpos ) double endy, double width, double zpos )
{ {
int ii, slice = 36; const int slice = 36;
double x, y, hole, rayon; double x, y, hole, radius;
rayon = hypot( startx - endx, starty - endy ) + ( width / 2); radius = hypot( startx - endx, starty - endy ) + ( width / 2);
hole = rayon - width; hole = radius - width;
glBegin( GL_QUAD_STRIP ); glBegin( GL_QUAD_STRIP );
for( ii = 0; ii <= slice; ii++ ) for( int ii = 0; ii <= slice; ii++ )
{ {
x = hole; y = 0.0; x = hole; y = 0.0;
RotatePoint( &x, &y, ii * 3600 / slice ); RotatePoint( &x, &y, ii * 3600 / slice );
glVertex3f( x + startx, y + starty, zpos ); glVertex3f( x + startx, y + starty, zpos );
x = rayon; y = 0.0; x = radius; y = 0.0;
RotatePoint( &x, &y, ii * 3600 / slice ); RotatePoint( &x, &y, ii * 3600 / slice );
glVertex3f( x + startx, y + starty, zpos ); glVertex3f( x + startx, y + starty, zpos );
} }
...@@ -1374,7 +1548,7 @@ void EDA_3D_CANVAS::Draw3D_Polygon( std::vector<wxPoint>& aCornersList, double a ...@@ -1374,7 +1548,7 @@ void EDA_3D_CANVAS::Draw3D_Polygon( std::vector<wxPoint>& aCornersList, double a
GLdouble v_data[3]; GLdouble v_data[3];
v_data[2] = aZpos; v_data[2] = aZpos;
//gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); //gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
// Draw solid polygon // Draw solid polygon
gluTessBeginPolygon( tess, NULL ); gluTessBeginPolygon( tess, NULL );
......
///////////////////////////////////////////////////////////////////////////// /**
// Name: 3d_frame.cpp * @file 3d_frame.cpp
///////////////////////////////////////////////////////////////////////////// */
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <fctsys.h> #include <fctsys.h>
#include <appl_wxstruct.h> #include <appl_wxstruct.h>
#if !wxUSE_GLCANVAS
#error Please set wxUSE_GLCANVAS to 1 in setup.h.
#endif
#include <3d_viewer.h> #include <3d_viewer.h>
#include <info3d_visu.h>
#include <trackball.h> #include <trackball.h>
#include <wx/colordlg.h> #include <wx/colordlg.h>
#include <wxstruct.h> #include <wxstruct.h>
#include <3d_viewer_id.h>
Info_3D_Visu g_Parm_3D_Visu; INFO3D_VISU g_Parm_3D_Visu;
double DataScale3D; // 3D conversion units. double DataScale3D; // 3D conversion units.
BEGIN_EVENT_TABLE( EDA_3D_FRAME, wxFrame ) BEGIN_EVENT_TABLE( EDA_3D_FRAME, wxFrame )
EVT_ACTIVATE( EDA_3D_FRAME::OnActivate ) EVT_ACTIVATE( EDA_3D_FRAME::OnActivate )
EVT_TOOL_RANGE( ID_ZOOM_IN, ID_ZOOM_PAGE, EDA_3D_FRAME::Process_Zoom ) EVT_TOOL_RANGE( ID_ZOOM_IN, ID_ZOOM_PAGE, EDA_3D_FRAME::Process_Zoom )
EVT_TOOL_RANGE( ID_START_COMMAND_3D, ID_END_COMMAND_3D, EVT_TOOL_RANGE( ID_START_COMMAND_3D, ID_END_COMMAND_3D,
EDA_3D_FRAME::Process_Special_Functions ) EDA_3D_FRAME::Process_Special_Functions )
EVT_MENU( wxID_EXIT, EDA_3D_FRAME::Exit3DFrame ) EVT_MENU( wxID_EXIT, EDA_3D_FRAME::Exit3DFrame )
EVT_MENU( ID_MENU_SCREENCOPY_PNG, EDA_3D_FRAME::Process_Special_Functions ) EVT_MENU( ID_MENU_SCREENCOPY_PNG, EDA_3D_FRAME::Process_Special_Functions )
EVT_MENU( ID_MENU_SCREENCOPY_JPEG, EDA_3D_FRAME::Process_Special_Functions ) EVT_MENU( ID_MENU_SCREENCOPY_JPEG, EDA_3D_FRAME::Process_Special_Functions )
EVT_MENU_RANGE( ID_MENU3D_GRID, ID_MENU3D_GRID_END,
EDA_3D_FRAME::On3DGridSelection )
EVT_CLOSE( EDA_3D_FRAME::OnCloseWindow ) EVT_CLOSE( EDA_3D_FRAME::OnCloseWindow )
END_EVENT_TABLE() END_EVENT_TABLE()
...@@ -38,7 +65,6 @@ EDA_3D_FRAME::EDA_3D_FRAME( PCB_BASE_FRAME* parent, const wxString& title, long ...@@ -38,7 +65,6 @@ EDA_3D_FRAME::EDA_3D_FRAME( PCB_BASE_FRAME* parent, const wxString& title, long
m_Canvas = NULL; m_Canvas = NULL;
m_HToolBar = NULL; m_HToolBar = NULL;
m_VToolBar = NULL; m_VToolBar = NULL;
m_InternalUnits = 10000; // Internal units = 1/10000 inch
m_reloadRequest = false; m_reloadRequest = false;
// Give it an icon // Give it an icon
...@@ -322,7 +348,7 @@ void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event ) ...@@ -322,7 +348,7 @@ void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event )
return; return;
default: default:
wxMessageBox( wxT( "EDA_3D_FRAME::Process_Special_Functions() error: unknown command" ) ); wxLogMessage( wxT( "EDA_3D_FRAME::Process_Special_Functions() error: unknown command" ) );
return; return;
} }
...@@ -330,6 +356,52 @@ void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event ) ...@@ -330,6 +356,52 @@ void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event )
m_Canvas->DisplayStatus(); m_Canvas->DisplayStatus();
} }
void EDA_3D_FRAME::On3DGridSelection( wxCommandEvent& event )
{
int id = event.GetId();
for( int ii = ID_MENU3D_GRID; ii < ID_MENU3D_GRID_END; ii++ )
{
if( event.GetId() == ii )
continue;
GetMenuBar()->Check( ii, false );
}
switch( id )
{
case ID_MENU3D_GRID_NOGRID:
g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_GRID] = false;
break;
case ID_MENU3D_GRID_10_MM:
g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_GRID] = true;
g_Parm_3D_Visu.m_3D_Grid = 10.0;
break;
case ID_MENU3D_GRID_5_MM:
g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_GRID] = true;
g_Parm_3D_Visu.m_3D_Grid = 5.0;
break;
case ID_MENU3D_GRID_2P5_MM:
g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_GRID] = true;
g_Parm_3D_Visu.m_3D_Grid = 2.5;
break;
case ID_MENU3D_GRID_1_MM:
g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_GRID] = true;
g_Parm_3D_Visu.m_3D_Grid = 1.0;
break;
default:
wxLogMessage( wxT( "EDA_3D_FRAME::On3DGridSelection() error: unknown command" ) );
return;
}
NewDisplay();
}
void EDA_3D_FRAME::NewDisplay() void EDA_3D_FRAME::NewDisplay()
{ {
......
...@@ -47,19 +47,31 @@ class S3D_Color /* 3D color (R, G, G) 3 floats range 0 to 1.0*/ ...@@ -47,19 +47,31 @@ class S3D_Color /* 3D color (R, G, G) 3 floats range 0 to 1.0*/
{ {
public: public:
double m_Red, m_Green, m_Blue; double m_Red, m_Green, m_Blue;
public: S3D_Color() public: S3D_Color()
{ {
m_Red = m_Green = m_Blue = 0; m_Red = m_Green = m_Blue = 0;
} }
}; };
class S3D_Vertex /* 3D coordinate (3 float numbers: x,y,z coordinates)*/ /* S3D_Vertex manage a 3D coordinate (3 float numbers: x,y,z coordinates)*/
class S3D_Vertex
{ {
public: public:
double x, y, z; double x, y, z;
public: public:
S3D_Vertex(); S3D_Vertex()
{
x = y = z = 0.0;
}
S3D_Vertex( double px, double py, double pz)
{
x = px;
y = py;
z = pz;
}
}; };
class S3D_MATERIAL : public EDA_ITEM /* openGL "material" data*/ class S3D_MATERIAL : public EDA_ITEM /* openGL "material" data*/
...@@ -166,26 +178,20 @@ public: ...@@ -166,26 +178,20 @@ public:
/** /**
* Class WinEDA_VertexCtrl * Class VERTEX_VALUE_CTRL
* displays a vertex for editing. A vertex is a triplet of values in INCHES, MM, * displays a vertex for editing. A vertex is a triplet of values
* or without units. * Values can be scale, rotation, offset...
*
* Internal_units are the internal units by inch which is 1000 for Eeschema and
* 10000 for Pcbnew
*/ */
class WinEDA_VertexCtrl class VERTEX_VALUE_CTRL
{ {
private: private:
int m_Units;
int m_Internal_Unit;
wxTextCtrl* m_XValueCtrl, * m_YValueCtrl, * m_ZValueCtrl; wxTextCtrl* m_XValueCtrl, * m_YValueCtrl, * m_ZValueCtrl;
wxStaticText* m_Text; wxStaticText* m_Text;
public: public:
WinEDA_VertexCtrl( wxWindow* parent, const wxString& title, VERTEX_VALUE_CTRL( wxWindow* parent, const wxString& title, wxBoxSizer* BoxSizer );
wxBoxSizer* BoxSizer, EDA_UNITS_T units, int internal_unit );
~WinEDA_VertexCtrl(); ~VERTEX_VALUE_CTRL();
/** /**
* Function GetValue * Function GetValue
......
...@@ -30,7 +30,9 @@ ...@@ -30,7 +30,9 @@
#include <fctsys.h> #include <fctsys.h>
#include <3d_viewer.h> #include <3d_viewer.h>
#include <info3d_visu.h>
#include <menus_helpers.h> #include <menus_helpers.h>
#include <3d_viewer_id.h>
void EDA_3D_FRAME::ReCreateHToolbar() void EDA_3D_FRAME::ReCreateHToolbar()
...@@ -175,6 +177,18 @@ void EDA_3D_FRAME::ReCreateMenuBar() ...@@ -175,6 +177,18 @@ void EDA_3D_FRAME::ReCreateMenuBar()
_( "Show Zone &Filling" ), KiBitmap( add_zone_xpm ), wxITEM_CHECK ); _( "Show Zone &Filling" ), KiBitmap( add_zone_xpm ), wxITEM_CHECK );
item->Check(g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ZONE]); item->Check(g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ZONE]);
// Creates grid menu
wxMenu * gridlistMenu = new wxMenu;
item = AddMenuItem( prefsMenu, gridlistMenu, ID_MENU3D_GRID,
_( "3D Grid" ), KiBitmap( grid_xpm ) );
gridlistMenu->Append( ID_MENU3D_GRID_NOGRID, _( "No 3D Grid" ), wxEmptyString, true );
gridlistMenu->Check( ID_MENU3D_GRID_NOGRID, true );
gridlistMenu->Append( ID_MENU3D_GRID_10_MM, _( "3D Grid 10 mm" ), wxEmptyString, true );
gridlistMenu->Append( ID_MENU3D_GRID_5_MM, _( "3D Grid 5 mm" ), wxEmptyString, true );
gridlistMenu->Append( ID_MENU3D_GRID_2P5_MM, _( "3D Grid 2.5 mm" ), wxEmptyString, true );
gridlistMenu->Append( ID_MENU3D_GRID_1_MM, _( "3D Grid 1 mm" ), wxEmptyString, true );
item = AddMenuItem( prefsMenu, ID_MENU3D_COMMENTS_ONOFF, item = AddMenuItem( prefsMenu, ID_MENU3D_COMMENTS_ONOFF,
_( "Show &Comments Layer" ), KiBitmap( edit_sheet_xpm ), wxITEM_CHECK ); _( "Show &Comments Layer" ), KiBitmap( edit_sheet_xpm ), wxITEM_CHECK );
item->Check(g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_COMMENTS]); item->Check(g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_COMMENTS]);
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#define __3D_VIEWER_H__ #define __3D_VIEWER_H__
#include <wxBasePcbFrame.h> // m_auimanager member. #include <wxBasePcbFrame.h> // m_auimanager member.
#include <layers_id_colors_and_visibility.h> // Layers id definitions
#if !wxUSE_GLCANVAS #if !wxUSE_GLCANVAS
#error Please set wxUSE_GLCANVAS to 1 in setup.h. #error Please set wxUSE_GLCANVAS to 1 in setup.h.
...@@ -50,7 +50,6 @@ ...@@ -50,7 +50,6 @@
#endif #endif
#include <3d_struct.h> #include <3d_struct.h>
#include <id.h>
class BOARD_DESIGN_SETTINGS; class BOARD_DESIGN_SETTINGS;
...@@ -62,109 +61,15 @@ class ZONE_CONTAINER; ...@@ -62,109 +61,15 @@ class ZONE_CONTAINER;
#define KICAD_DEFAULT_3D_DRAWFRAME_STYLE wxDEFAULT_FRAME_STYLE | wxWANTS_CHARS #define KICAD_DEFAULT_3D_DRAWFRAME_STYLE wxDEFAULT_FRAME_STYLE | wxWANTS_CHARS
#define LIB3D_PATH wxT( "packages3d" ) #define LIB3D_PATH wxT( "packages3d" )
/**
* Command IDs for the 3D viewer.
*
* Please add IDs that are unique to the 3D viewer here and not in the global
* id.h file. This will prevent the entire project from being rebuilt when
* adding new commands to the 3D viewer.
*/
enum id_3dview_frm
{
ID_START_COMMAND_3D = ID_END_LIST,
ID_ROTATE3D_X_NEG,
ID_ROTATE3D_X_POS,
ID_ROTATE3D_Y_NEG,
ID_ROTATE3D_Y_POS,
ID_ROTATE3D_Z_NEG,
ID_ROTATE3D_Z_POS,
ID_RELOAD3D_BOARD,
ID_TOOL_SCREENCOPY_TOCLIBBOARD,
ID_MOVE3D_LEFT,
ID_MOVE3D_RIGHT,
ID_MOVE3D_UP,
ID_MOVE3D_DOWN,
ID_ORTHO,
ID_MENU3D_BGCOLOR_SELECTION,
ID_MENU3D_AXIS_ONOFF,
ID_MENU3D_MODULE_ONOFF,
ID_MENU3D_UNUSED,
ID_MENU3D_ZONE_ONOFF,
ID_MENU3D_DRAWINGS_ONOFF,
ID_MENU3D_COMMENTS_ONOFF,
ID_MENU3D_ECO1_ONOFF,
ID_MENU3D_ECO2_ONOFF,
ID_END_COMMAND_3D,
ID_MENU_SCREENCOPY_PNG,
ID_MENU_SCREENCOPY_JPEG,
ID_MENU_SCREENCOPY_TOCLIBBOARD,
ID_POPUP_3D_VIEW_START,
ID_POPUP_ZOOMIN,
ID_POPUP_ZOOMOUT,
ID_POPUP_VIEW_XPOS,
ID_POPUP_VIEW_XNEG,
ID_POPUP_VIEW_YPOS,
ID_POPUP_VIEW_YNEG,
ID_POPUP_VIEW_ZPOS,
ID_POPUP_VIEW_ZNEG,
ID_POPUP_MOVE3D_LEFT,
ID_POPUP_MOVE3D_RIGHT,
ID_POPUP_MOVE3D_UP,
ID_POPUP_MOVE3D_DOWN,
ID_POPUP_3D_VIEW_END
};
class EDA_3D_CANVAS; class EDA_3D_CANVAS;
class EDA_3D_FRAME; class EDA_3D_FRAME;
class Info_3D_Visu;
class S3D_Vertex; class S3D_Vertex;
class SEGVIA; class SEGVIA;
#define m_ROTX m_Rot[0]
#define m_ROTY m_Rot[1]
#define m_ROTZ m_Rot[2]
/* information needed to display 3D board */
class Info_3D_Visu
{
public:
enum {
FL_AXIS=0, FL_MODULE, FL_ZONE,
FL_COMMENTS, FL_DRAWINGS, FL_ECO1, FL_ECO2,
FL_LAST
};
double m_Beginx, m_Beginy; /* position of mouse */
double m_Quat[4]; /* orientation of object */
double m_Rot[4]; /* man rotation of object */
double m_Zoom; /* field of view in degrees */
S3D_Color m_BgColor;
bool m_DrawFlags[FL_LAST]; /* show these special items */
wxPoint m_BoardPos;
wxSize m_BoardSize;
int m_Layers;
const BOARD_DESIGN_SETTINGS* m_BoardSettings; // Link to current board design settings
double m_Epoxy_Width; // Epoxy thickness (normalized)
double m_BoardScale; /* Normalization scale for coordinates:
* when scaled between -1.0 and +1.0 */
double m_LayerZcoord[32];
double m_ActZpos;
public: Info_3D_Visu();
~Info_3D_Visu();
};
class EDA_3D_CANVAS : public wxGLCanvas class EDA_3D_CANVAS : public wxGLCanvas
{ {
...@@ -218,6 +123,9 @@ public: ...@@ -218,6 +123,9 @@ public:
m_draw3dOffset.x = aPosX; m_draw3dOffset.x = aPosX;
m_draw3dOffset.y = aPosY; m_draw3dOffset.y = aPosY;
} }
void DrawGrid( double aGriSizeMM );
void Draw3D_Track( TRACK* track ); void Draw3D_Track( TRACK* track );
/** /**
...@@ -275,7 +183,6 @@ private: ...@@ -275,7 +183,6 @@ private:
EDA_3D_CANVAS* m_Canvas; EDA_3D_CANVAS* m_Canvas;
wxAuiToolBar* m_HToolBar; wxAuiToolBar* m_HToolBar;
wxAuiToolBar* m_VToolBar; wxAuiToolBar* m_VToolBar;
int m_InternalUnits;
wxPoint m_FramePos; wxPoint m_FramePos;
wxSize m_FrameSize; wxSize m_FrameSize;
wxAuiManager m_auimgr; wxAuiManager m_auimgr;
...@@ -290,14 +197,6 @@ public: ...@@ -290,14 +197,6 @@ public:
}; };
PCB_BASE_FRAME* Parent() { return (PCB_BASE_FRAME*)GetParent(); } PCB_BASE_FRAME* Parent() { return (PCB_BASE_FRAME*)GetParent(); }
void Exit3DFrame( wxCommandEvent& event );
void OnCloseWindow( wxCloseEvent& Event );
void ReCreateMenuBar();
void ReCreateHToolbar();
void ReCreateVToolbar();
void SetToolbars();
void GetSettings();
void SaveSettings();
/** /**
* Function ReloadRequest * Function ReloadRequest
...@@ -310,16 +209,33 @@ public: ...@@ -310,16 +209,33 @@ public:
m_reloadRequest = true; m_reloadRequest = true;
} }
/**
* Function NewDisplay
* Rebuild the display list.
* must be called when 3D opengl data is modified
*/
void NewDisplay();
private:
void Exit3DFrame( wxCommandEvent& event );
void OnCloseWindow( wxCloseEvent& Event );
void ReCreateMenuBar();
void ReCreateHToolbar();
void ReCreateVToolbar();
void SetToolbars();
void GetSettings();
void SaveSettings();
void OnLeftClick( wxDC* DC, const wxPoint& MousePos ); void OnLeftClick( wxDC* DC, const wxPoint& MousePos );
void OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu ); void OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu );
void OnKeyEvent( wxKeyEvent& event ); void OnKeyEvent( wxKeyEvent& event );
double BestZoom(); double BestZoom();
void RedrawActiveWindow( wxDC* DC, bool EraseBg ); void RedrawActiveWindow( wxDC* DC, bool EraseBg );
void Process_Special_Functions( wxCommandEvent& event ); void Process_Special_Functions( wxCommandEvent& event );
void On3DGridSelection( wxCommandEvent& event );
void Process_Zoom( wxCommandEvent& event ); void Process_Zoom( wxCommandEvent& event );
void OnActivate( wxActivateEvent& event ); void OnActivate( wxActivateEvent& event );
void NewDisplay();
void Set3DBgColor(); void Set3DBgColor();
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
...@@ -328,7 +244,4 @@ public: ...@@ -328,7 +244,4 @@ public:
void SetGLColor( int color ); void SetGLColor( int color );
void Set_Object_Data( std::vector< S3D_Vertex >& aVertices ); void Set_Object_Data( std::vector< S3D_Vertex >& aVertices );
extern Info_3D_Visu g_Parm_3D_Visu;
extern double DataScale3D; // 3D scale units.
#endif /* __3D_VIEWER_H__ */ #endif /* __3D_VIEWER_H__ */
/**
* @file 3d_viewer_id.h
*/
/**
* Command IDs for the 3D viewer.
*
* Please add IDs that are unique to the 3D viewer here and not in the global
* id.h file. This will prevent the entire project from being rebuilt when
* adding new commands to the 3D viewer.
*/
#include <id.h> // Generic Id.
enum id_3dview_frm
{
ID_START_COMMAND_3D = ID_END_LIST,
ID_ROTATE3D_X_NEG,
ID_ROTATE3D_X_POS,
ID_ROTATE3D_Y_NEG,
ID_ROTATE3D_Y_POS,
ID_ROTATE3D_Z_NEG,
ID_ROTATE3D_Z_POS,
ID_RELOAD3D_BOARD,
ID_TOOL_SCREENCOPY_TOCLIBBOARD,
ID_MOVE3D_LEFT,
ID_MOVE3D_RIGHT,
ID_MOVE3D_UP,
ID_MOVE3D_DOWN,
ID_ORTHO,
ID_MENU3D_BGCOLOR_SELECTION,
ID_MENU3D_AXIS_ONOFF,
ID_MENU3D_MODULE_ONOFF,
ID_MENU3D_ZONE_ONOFF,
ID_MENU3D_DRAWINGS_ONOFF,
ID_MENU3D_COMMENTS_ONOFF,
ID_MENU3D_ECO1_ONOFF,
ID_MENU3D_ECO2_ONOFF,
ID_END_COMMAND_3D,
ID_MENU3D_GRID,
ID_MENU3D_GRID_NOGRID,
ID_MENU3D_GRID_10_MM,
ID_MENU3D_GRID_5_MM,
ID_MENU3D_GRID_2P5_MM,
ID_MENU3D_GRID_1_MM,
ID_MENU3D_GRID_END,
ID_MENU_SCREENCOPY_PNG,
ID_MENU_SCREENCOPY_JPEG,
ID_MENU_SCREENCOPY_TOCLIBBOARD,
ID_POPUP_3D_VIEW_START,
ID_POPUP_ZOOMIN,
ID_POPUP_ZOOMOUT,
ID_POPUP_VIEW_XPOS,
ID_POPUP_VIEW_XNEG,
ID_POPUP_VIEW_YPOS,
ID_POPUP_VIEW_YNEG,
ID_POPUP_VIEW_ZPOS,
ID_POPUP_VIEW_ZNEG,
ID_POPUP_MOVE3D_LEFT,
ID_POPUP_MOVE3D_RIGHT,
ID_POPUP_MOVE3D_UP,
ID_POPUP_MOVE3D_DOWN,
ID_POPUP_3D_VIEW_END
};
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file 3d_viewer.h
*/
#ifndef __INFO3D_VISU_H__
#define __INFO3D_VISU_H__
#include <wxBasePcbFrame.h> // m_auimanager member.
#include <layers_id_colors_and_visibility.h> // Layers id definitions
#if !wxUSE_GLCANVAS
#error Please set wxUSE_GLCANVAS to 1 in setup.h.
#endif
#include <wx/glcanvas.h>
#ifdef __WXMAC__
# ifdef __DARWIN__
# include <OpenGL/glu.h>
# else
# include <glu.h>
# endif
#else
# include <GL/glu.h>
#endif
#include <3d_struct.h>
#define m_ROTX m_Rot[0]
#define m_ROTY m_Rot[1]
#define m_ROTZ m_Rot[2]
/* information needed to display 3D board */
class INFO3D_VISU
{
public:
enum DISPLAY3D_FLG
{
FL_AXIS=0, FL_MODULE, FL_ZONE,
FL_COMMENTS, FL_DRAWINGS, FL_ECO1, FL_ECO2,
FL_GRID,
FL_LAST
};
double m_Beginx, m_Beginy; // position of mouse
double m_Quat[4]; // orientation of object
double m_Rot[4]; // man rotation of object
double m_Zoom; // field of view in degrees
double m_3D_Grid; // 3D grid valmue, in mm
S3D_Color m_BgColor;
bool m_DrawFlags[FL_LAST]; // show these special items
wxPoint m_BoardPos;
wxSize m_BoardSize;
int m_CopperLayersCount; // Number of copper layers actually used by the board
const BOARD_DESIGN_SETTINGS* m_BoardSettings; // Link to current board design settings
double m_EpoxyThickness; // Epoxy thickness (normalized)
double m_NonCopperLayerThickness; // Non copper layers thickness
double m_BoardScale; /* Normalization scale for coordinates:
* when scaled between -1.0 and +1.0 */
double m_LayerZcoord[LAYER_COUNT]; // Z position of each layer (normalized)
double m_ActZpos;
public: INFO3D_VISU();
~INFO3D_VISU();
};
extern INFO3D_VISU g_Parm_3D_Visu;
extern double DataScale3D; // 3D scale units.
#endif /* __INFO3D_VISU_H__ */
...@@ -8,83 +8,83 @@ ...@@ -8,83 +8,83 @@
static const unsigned char png[] = { static const unsigned char png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c,
0xce, 0x00, 0x00, 0x04, 0xae, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xad, 0x96, 0x6d, 0x48, 0x5b, 0xce, 0x00, 0x00, 0x04, 0xaa, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xad, 0x96, 0x6d, 0x4c, 0x5b,
0x67, 0x14, 0x80, 0xfd, 0x98, 0x06, 0x53, 0xb5, 0x3a, 0xa4, 0x6e, 0xb2, 0xfe, 0x09, 0xac, 0x1b, 0x65, 0x14, 0x80, 0x0b, 0xc8, 0x9a, 0x31, 0x60, 0x60, 0x16, 0x51, 0xa2, 0x7f, 0x9a, 0xf8, 0x91,
0x53, 0x61, 0x7f, 0xfc, 0x53, 0x98, 0x13, 0xe9, 0x3f, 0x75, 0x03, 0x15, 0xb6, 0xc1, 0x9c, 0x53, 0x00, 0xc9, 0xfe, 0x10, 0x93, 0x25, 0xa2, 0x21, 0xfb, 0x07, 0x68, 0x02, 0x24, 0x6a, 0x22, 0x41,
0x18, 0xdd, 0x90, 0x89, 0x15, 0x65, 0x9b, 0xe0, 0x8f, 0x52, 0x37, 0xe9, 0x1a, 0x5c, 0x0b, 0xda, 0xf6, 0xc7, 0x18, 0x22, 0x41, 0x02, 0x31, 0xa2, 0x15, 0x17, 0x70, 0x38, 0x87, 0x13, 0x13, 0x08,
0xd2, 0xb4, 0xb8, 0xda, 0x98, 0xb5, 0xd1, 0xaa, 0xf1, 0x03, 0xfc, 0xda, 0xd0, 0xa9, 0x71, 0xcc, 0xe3, 0x82, 0x40, 0x57, 0x50, 0xda, 0x0e, 0x56, 0x3e, 0x12, 0xbe, 0x34, 0x45, 0xa0, 0x4c, 0x11,
0xd9, 0x8d, 0x8a, 0xd1, 0xc5, 0x4e, 0x6d, 0x68, 0xab, 0x8d, 0x31, 0xc6, 0x8f, 0x98, 0x44, 0x73, 0x5d, 0x5c, 0x5c, 0x08, 0x5b, 0x10, 0xc9, 0xc6, 0x58, 0xbf, 0x3f, 0x69, 0x0b, 0xbd, 0xed, 0xf1,
0x93, 0xb3, 0x73, 0x8e, 0xde, 0x78, 0xa3, 0x4d, 0xe8, 0x60, 0x81, 0x87, 0xe4, 0x26, 0xef, 0x3d, 0x3d, 0x07, 0x6e, 0xb9, 0x17, 0xd6, 0x66, 0x26, 0xde, 0xe4, 0x49, 0xef, 0x6d, 0xdf, 0x7b, 0x9e,
0xcf, 0x7b, 0xde, 0x73, 0xde, 0xf7, 0x26, 0x24, 0x24, 0x24, 0xe4, 0x65, 0xe4, 0xed, 0xff, 0x11, 0xf7, 0x9c, 0xf3, 0xde, 0xf7, 0x56, 0x26, 0x93, 0xc9, 0x9e, 0x64, 0x9c, 0xfe, 0x1f, 0x91, 0x03,
0x19, 0x00, 0x84, 0x1c, 0x86, 0x5e, 0xa7, 0x2d, 0x16, 0x8b, 0xd3, 0x6a, 0x5d, 0xf3, 0xac, 0xad, 0x80, 0xec, 0x30, 0x78, 0x9c, 0xb1, 0x58, 0x2c, 0x7e, 0x9b, 0xcd, 0x1e, 0xb2, 0xdb, 0x19, 0x0e,
0x21, 0x36, 0x9b, 0xc7, 0xb6, 0xbe, 0xee, 0x59, 0x27, 0x36, 0x36, 0x3c, 0x1b, 0x22, 0x9b, 0x9b, 0x47, 0xc8, 0xe1, 0x74, 0x86, 0x9c, 0x88, 0xcb, 0x15, 0x72, 0x09, 0xb8, 0xdd, 0x21, 0x37, 0xe2,
0x9e, 0x4d, 0x62, 0x6b, 0xcb, 0xb3, 0x15, 0x80, 0x89, 0x89, 0x09, 0x13, 0xc6, 0x7b, 0x25, 0xa0, 0xf1, 0x84, 0x3c, 0x51, 0x58, 0x5a, 0x5a, 0xda, 0x60, 0xf1, 0x9e, 0x8e, 0x2a, 0x72, 0x38, 0x1c,
0xc8, 0x66, 0xb3, 0x09, 0x2b, 0x16, 0x0b, 0x58, 0x56, 0x57, 0x61, 0xd5, 0x6a, 0x05, 0xeb, 0xda, 0xbc, 0xd9, 0x62, 0x01, 0x8b, 0xd5, 0x0a, 0x56, 0x9b, 0x0d, 0x6c, 0x76, 0x3b, 0x30, 0x21, 0x30,
0x1a, 0xa0, 0x10, 0x50, 0x08, 0xeb, 0xc4, 0xc6, 0x06, 0xa0, 0x08, 0x36, 0x89, 0xad, 0x2d, 0xd8, 0x21, 0x38, 0x11, 0x97, 0x0b, 0x98, 0x08, 0xdc, 0x88, 0xc7, 0x03, 0x1e, 0x01, 0xaf, 0x57, 0xc2,
0x12, 0xb1, 0xdb, 0xfd, 0x98, 0x9d, 0x9d, 0x35, 0x07, 0x15, 0x61, 0x30, 0x81, 0x24, 0x8d, 0x8d, 0xca, 0xca, 0x8a, 0x29, 0xa6, 0x88, 0x05, 0xe3, 0x51, 0xd2, 0xd3, 0xd3, 0x03, 0x06, 0x83, 0x01,
0x8d, 0x30, 0x34, 0x34, 0x04, 0xbf, 0x8e, 0x8c, 0xc0, 0x08, 0x31, 0x3a, 0x0a, 0xa3, 0x81, 0x18, 0x7e, 0x9e, 0x9b, 0x83, 0x39, 0x64, 0x7e, 0x1e, 0xe6, 0xa3, 0xb1, 0xb0, 0x00, 0x0b, 0x88, 0xd1,
0x1b, 0x83, 0x31, 0x42, 0xaf, 0xdf, 0x03, 0x3f, 0xe3, 0xbd, 0xee, 0xde, 0xde, 0x5e, 0x63, 0x5f, 0xb8, 0x07, 0x3b, 0x67, 0xf7, 0x06, 0x27, 0x26, 0x26, 0x56, 0x27, 0x27, 0x27, 0xff, 0x2a, 0x29,
0x5f, 0xdf, 0x74, 0x5e, 0x5e, 0x5e, 0xdd, 0x11, 0x11, 0x2e, 0x8d, 0x40, 0x59, 0x68, 0xb5, 0x5a, 0x29, 0xb9, 0x7c, 0x44, 0xc4, 0x4a, 0xc3, 0x63, 0x16, 0x1a, 0x8d, 0x86, 0xb2, 0x32, 0x99, 0xcd,
0xce, 0xca, 0xbc, 0xb2, 0xe2, 0x9f, 0x9d, 0x34, 0x43, 0xca, 0x4e, 0x9a, 0xe1, 0x7e, 0x96, 0x87, 0xd2, 0xec, 0xc4, 0x19, 0x62, 0x76, 0xe2, 0x0c, 0xf7, 0xb3, 0x3c, 0x4c, 0x53, 0x53, 0x93, 0xf6,
0xa9, 0xa9, 0xa9, 0x69, 0x39, 0x2a, 0xda, 0xdc, 0x14, 0x28, 0x50, 0x4b, 0x4b, 0x0b, 0x58, 0x31, 0xa8, 0xc8, 0xed, 0xe6, 0x31, 0x90, 0x56, 0xab, 0x05, 0x1b, 0x0b, 0xfe, 0x60, 0x6b, 0x8b, 0xa4,
0xf8, 0xd2, 0xf2, 0x32, 0x4b, 0x75, 0x3a, 0x1d, 0xe8, 0x3a, 0x3b, 0xa1, 0x93, 0xe8, 0xea, 0x82, 0x7a, 0xbd, 0x1e, 0xf4, 0x23, 0x23, 0x30, 0x82, 0x8c, 0x8e, 0xc2, 0xe8, 0x3e, 0x63, 0x63, 0x63,
0xae, 0x7d, 0xba, 0xbb, 0xbb, 0xa1, 0xbb, 0xa7, 0x07, 0x7a, 0x82, 0x50, 0x56, 0x56, 0xf6, 0x67, 0x30, 0x36, 0x3e, 0x0e, 0xe3, 0x31, 0xa8, 0xae, 0xae, 0xfe, 0xa3, 0xac, 0xac, 0xec, 0x03, 0x44,
0x41, 0x41, 0xc1, 0x97, 0x84, 0x4c, 0x26, 0x7b, 0x83, 0x45, 0x38, 0x2b, 0x81, 0x66, 0xda, 0xd2, 0x2e, 0x97, 0xbf, 0x48, 0x22, 0x36, 0x2b, 0x1e, 0x67, 0xaa, 0xd5, 0xe9, 0x68, 0xe6, 0xf7, 0x37,
0xda, 0xca, 0x33, 0x7f, 0xf2, 0xf4, 0x29, 0x2f, 0x87, 0x65, 0x35, 0x48, 0xbd, 0xf6, 0x67, 0x4e, 0x37, 0xa9, 0x1c, 0x16, 0x6b, 0x8c, 0x7e, 0xed, 0xcf, 0x1c, 0x7b, 0xe3, 0x8d, 0x41, 0x60, 0x67,
0xb5, 0xb1, 0x07, 0xc1, 0xb5, 0xb3, 0x03, 0x49, 0x49, 0x49, 0xef, 0xb1, 0x08, 0x0b, 0x2b, 0xd0, 0x07, 0x32, 0x33, 0x33, 0x5f, 0x27, 0x11, 0x6b, 0x2c, 0x8f, 0x37, 0xeb, 0x98, 0xe8, 0xa1, 0xc9,
0xcd, 0xad, 0x28, 0x7a, 0x66, 0x36, 0xc3, 0xc2, 0xe2, 0x22, 0xd7, 0xc1, 0xbc, 0x12, 0xa0, 0x41, 0x04, 0x7f, 0xaf, 0xaf, 0x53, 0x1f, 0x4c, 0xe6, 0x28, 0x0b, 0x44, 0x5c, 0x3e, 0x41, 0x18, 0x45,
0xa4, 0xcb, 0x27, 0x0a, 0x03, 0x48, 0x9d, 0x2e, 0xd7, 0x81, 0x08, 0xbf, 0x10, 0x68, 0xb0, 0x5a, 0xea, 0x0f, 0x04, 0x0e, 0x44, 0xec, 0x0b, 0x1e, 0x07, 0xab, 0xd5, 0x6a, 0x48, 0x4c, 0x4c, 0xc4,
0xad, 0x86, 0x88, 0x88, 0x08, 0x5a, 0x50, 0x08, 0x0b, 0x0b, 0x83, 0xb9, 0x87, 0x0f, 0x79, 0x29, 0x82, 0x42, 0x7c, 0x7c, 0x3c, 0xdc, 0xb9, 0x7b, 0x97, 0x4a, 0x29, 0x08, 0xba, 0x3f, 0x93, 0x43,
0x45, 0xc1, 0x8c, 0x4c, 0x06, 0x06, 0xfc, 0x2d, 0x18, 0x73, 0xa7, 0x4e, 0xc1, 0x36, 0x4e, 0xc0, 0x67, 0xbd, 0x2c, 0x26, 0x83, 0x5f, 0xbf, 0xc0, 0x04, 0x6e, 0xf0, 0xf9, 0x7c, 0xc4, 0x8e, 0x38,
0xe1, 0x70, 0x30, 0x3b, 0xd2, 0x8c, 0xec, 0xdb, 0xdb, 0x02, 0xd9, 0x2b, 0x2b, 0x2b, 0x59, 0x22, 0x23, 0xef, 0xf6, 0x36, 0x8f, 0xf6, 0xba, 0xba, 0x3a, 0x92, 0x08, 0x74, 0x72, 0x9c, 0x24, 0x8b,
0x72, 0x5d, 0xa5, 0xf2, 0xcb, 0xe2, 0x45, 0x44, 0x84, 0xb9, 0xae, 0x0e, 0x5c, 0x98, 0x09, 0xb1, 0xc7, 0x11, 0x21, 0x37, 0xe7, 0x2e, 0x43, 0x80, 0x65, 0x82, 0xec, 0x06, 0x83, 0x07, 0xa2, 0x6d,
0xeb, 0x76, 0x1f, 0x88, 0xb6, 0x51, 0x84, 0x40, 0x66, 0x66, 0xa6, 0x9f, 0x28, 0x3f, 0x3f, 0x9f, 0x26, 0x62, 0x40, 0x7e, 0x7e, 0xbe, 0x44, 0x54, 0x5a, 0x5a, 0x4a, 0x7d, 0xc1, 0x32, 0x61, 0xc6,
0xeb, 0x42, 0xcb, 0x44, 0x19, 0x8b, 0xa2, 0xa6, 0x6b, 0x6a, 0x50, 0x37, 0xb5, 0x41, 0xf3, 0xed, 0x82, 0xa8, 0xb7, 0x4b, 0x0d, 0x6a, 0xd5, 0x10, 0xf4, 0x5f, 0x1d, 0x8e, 0x30, 0xa0, 0xbe, 0x0e,
0x76, 0x1f, 0x1a, 0x75, 0x07, 0xf4, 0x9c, 0xfb, 0x86, 0x7f, 0x9f, 0x8e, 0x3d, 0x0e, 0x4e, 0x2c, 0xaa, 0x8e, 0x8f, 0xe9, 0xf7, 0xee, 0x86, 0x93, 0xe0, 0x71, 0x99, 0x60, 0x77, 0x77, 0x17, 0x78,
0xc1, 0xee, 0xee, 0x2e, 0x08, 0x82, 0x20, 0x11, 0x39, 0x1c, 0x2c, 0x8a, 0x8b, 0x8b, 0x63, 0x41, 0x9e, 0x17, 0x89, 0x7c, 0x3e, 0x12, 0xa5, 0xa5, 0xa5, 0x91, 0x20, 0x2f, 0x2f, 0x8f, 0x3e, 0xd3,
0x7a, 0x7a, 0x3a, 0xbf, 0xc7, 0xc7, 0xc7, 0x73, 0x46, 0x24, 0xa1, 0x8c, 0x45, 0xd1, 0x3d, 0x75, 0xd3, 0xd3, 0x29, 0x23, 0x94, 0x60, 0xc6, 0x82, 0x48, 0xfb, 0xc3, 0x10, 0xcd, 0x16, 0xcb, 0x82,
0x1b, 0xcf, 0x96, 0x96, 0x85, 0x82, 0x89, 0xb8, 0x71, 0xf6, 0x0b, 0x19, 0x19, 0x3c, 0xc6, 0xf4, 0xc1, 0x04, 0x82, 0x6c, 0xf6, 0x23, 0xdc, 0x6b, 0x34, 0xc6, 0x30, 0xf4, 0x3e, 0x5d, 0x4b, 0x44,
0xf9, 0x17, 0x7c, 0xed, 0x27, 0xc2, 0xb5, 0x14, 0xc6, 0xc7, 0xc7, 0x7d, 0x99, 0xe0, 0xa6, 0x83, 0xac, 0x96, 0xfc, 0xe2, 0xe2, 0x62, 0x24, 0x13, 0xf6, 0xd0, 0x41, 0x42, 0x42, 0x02, 0x9d, 0x4f,
0xf0, 0xf0, 0x70, 0xfe, 0x3c, 0x30, 0x38, 0xc8, 0x12, 0x9a, 0x88, 0x28, 0x6a, 0x6b, 0x6e, 0xf7, 0xcf, 0xcc, 0x90, 0x04, 0x27, 0x22, 0x88, 0x74, 0x83, 0xc3, 0x92, 0xe0, 0x62, 0x4c, 0xf7, 0x7e,
0x0b, 0x2e, 0xc5, 0x7e, 0xff, 0x3e, 0x18, 0xb0, 0xbe, 0x06, 0xbc, 0xdf, 0x61, 0x30, 0x1c, 0x15, 0x07, 0xee, 0x93, 0x78, 0x46, 0x02, 0x58, 0x1f, 0xde, 0x3e, 0x2a, 0x52, 0x2a, 0x95, 0x14, 0x98,
0x55, 0x57, 0x57, 0x73, 0x60, 0xfc, 0x12, 0x56, 0xb1, 0xd3, 0x52, 0x53, 0x53, 0xf9, 0xba, 0xa2, 0x7d, 0x09, 0x56, 0xb6, 0xd2, 0x72, 0x72, 0x72, 0xe8, 0xba, 0xb6, 0xb6, 0x96, 0x24, 0x3e, 0xbf,
0xa2, 0x82, 0x25, 0x0e, 0xa7, 0xd3, 0x27, 0x6a, 0xd7, 0x74, 0xf8, 0x05, 0xa7, 0x60, 0x52, 0x1e, 0x3f, 0x22, 0xba, 0xa6, 0xb9, 0x2e, 0x09, 0x8e, 0xc1, 0xc4, 0x18, 0xae, 0x9d, 0xa3, 0x71, 0xd5,
0x17, 0x17, 0xf3, 0x38, 0xd5, 0x5b, 0xd1, 0x10, 0xfb, 0xc3, 0x9b, 0x20, 0xbb, 0xa4, 0xd8, 0xdd, 0x9f, 0x27, 0x43, 0xea, 0x37, 0x2f, 0x81, 0xfc, 0x92, 0x62, 0x77, 0x4f, 0xe4, 0xf7, 0xf3, 0xb9,
0x13, 0x39, 0x9d, 0x42, 0x5a, 0x5a, 0x1a, 0x07, 0x2e, 0x2c, 0x2c, 0xe4, 0x4e, 0x2b, 0x2a, 0x2a, 0xb9, 0xb9, 0x14, 0xb8, 0xbc, 0xbc, 0x9c, 0x56, 0x5a, 0x45, 0x45, 0x05, 0x5d, 0x67, 0x67, 0x67,
0xe2, 0xeb, 0x94, 0x94, 0x14, 0x96, 0xd0, 0x52, 0x1d, 0x16, 0x49, 0x83, 0x7b, 0x3c, 0x1e, 0x1f, 0x93, 0x04, 0x4b, 0x75, 0x58, 0x24, 0x0e, 0x1e, 0x0a, 0x85, 0x22, 0x78, 0x5d, 0x0f, 0xe0, 0xca,
0x3b, 0x4b, 0x4b, 0xf0, 0x40, 0xbe, 0x37, 0x36, 0xe3, 0xb3, 0x57, 0x41, 0xa6, 0x54, 0xf0, 0xd1, 0xfe, 0xd8, 0xd3, 0xcd, 0xcf, 0x80, 0xbc, 0x45, 0x41, 0x5b, 0xc3, 0x99, 0x8d, 0x8d, 0x0d, 0x3e,
0x70, 0xda, 0x64, 0x32, 0x09, 0xa1, 0xa1, 0xa1, 0x1c, 0x58, 0xa3, 0xd1, 0xf0, 0x91, 0xd3, 0xd0, 0x2e, 0x2e, 0x8e, 0x02, 0x0f, 0x0c, 0x0c, 0xd0, 0x96, 0xd3, 0xde, 0xde, 0x1e, 0x29, 0xe5, 0xda,
0xd0, 0xe0, 0x5b, 0xca, 0xf9, 0xf9, 0x79, 0xae, 0x87, 0x54, 0xf4, 0x3c, 0x81, 0xd7, 0xeb, 0x65, 0xda, 0x1a, 0xf5, 0x43, 0x2c, 0x7a, 0x94, 0x20, 0x1c, 0x0e, 0x13, 0x01, 0xbf, 0x13, 0xae, 0x9c,
0x04, 0x6c, 0xa0, 0xbf, 0xe2, 0x63, 0x78, 0x6c, 0xd6, 0x27, 0x89, 0x07, 0x22, 0x95, 0x4a, 0xe5, 0x4f, 0xa1, 0xb1, 0x2f, 0x5f, 0xc8, 0x38, 0x10, 0x71, 0x1c, 0x17, 0x12, 0x82, 0x4e, 0x4d, 0x4d,
0x11, 0x83, 0xf6, 0xf7, 0xf7, 0xf3, 0xa1, 0x4a, 0x07, 0xac, 0x28, 0xaf, 0xaf, 0xaf, 0xe7, 0x7a, 0xd1, 0xa6, 0x8a, 0x1b, 0xac, 0x20, 0x6f, 0x6b, 0x6b, 0xa3, 0x7e, 0x08, 0xa2, 0x21, 0xad, 0x5e,
0x88, 0xa2, 0x8e, 0x9f, 0x74, 0x7e, 0x12, 0x51, 0x40, 0xd0, 0xeb, 0x19, 0x6e, 0x13, 0x1a, 0xa7, 0x22, 0x11, 0x04, 0x08, 0x1e, 0xbf, 0x4c, 0xd4, 0xd1, 0xb8, 0x8f, 0x1a, 0x8e, 0xc3, 0x89, 0x96,
0x51, 0x44, 0xc1, 0x31, 0xe5, 0xeb, 0x20, 0xfb, 0x5e, 0xe1, 0x66, 0x51, 0x6e, 0x6e, 0xae, 0x57, 0xe7, 0x41, 0xfe, 0x95, 0x22, 0x48, 0xa2, 0xe2, 0xe2, 0xe2, 0xb0, 0x78, 0x59, 0x1f, 0xa6, 0xa0,
0xda, 0xd6, 0x87, 0xc9, 0xca, 0xca, 0x3a, 0x22, 0x3a, 0x2c, 0xa1, 0x17, 0x5d, 0x3b, 0x8c, 0x46, 0xa0, 0xe0, 0x88, 0xe8, 0xb0, 0x04, 0x0f, 0xbc, 0xb6, 0x9b, 0x57, 0xa1, 0x4b, 0x79, 0x8c, 0x16,
0x98, 0x89, 0x8c, 0xe4, 0x86, 0xe8, 0xb9, 0x78, 0x05, 0x7e, 0x1b, 0xff, 0x9d, 0xba, 0xf7, 0x2c, 0xc4, 0xa0, 0xea, 0x5b, 0xb8, 0xb1, 0xf8, 0x2b, 0xae, 0xde, 0xf7, 0x50, 0xf4, 0x4a, 0x6a, 0x6a,
0x89, 0xde, 0x89, 0x8d, 0x8d, 0x85, 0x60, 0x22, 0xb9, 0x5c, 0xee, 0xd7, 0xde, 0xba, 0x3b, 0x9d, 0x2a, 0xc4, 0x12, 0x25, 0x25, 0x25, 0x49, 0x96, 0xf7, 0xb0, 0x6e, 0x24, 0x22, 0xc1, 0x03, 0x3f,
0x3e, 0x09, 0xbd, 0xe8, 0x9d, 0x3b, 0x0e, 0xc7, 0xfc, 0x83, 0x93, 0xa2, 0x31, 0x53, 0x39, 0xef, 0xb1, 0x67, 0x38, 0x66, 0xac, 0xa7, 0x60, 0x6f, 0x32, 0x9d, 0x6f, 0x80, 0x4e, 0x33, 0x0a, 0x0e,
0x43, 0xab, 0xb6, 0x0b, 0x6c, 0xb8, 0x07, 0xc5, 0xae, 0x2b, 0x11, 0x03, 0xe6, 0xe4, 0xe4, 0x80, 0xf6, 0x0c, 0x0a, 0xab, 0xae, 0x52, 0x08, 0x58, 0x54, 0x54, 0x04, 0x2d, 0x2d, 0x2d, 0xd0, 0xdc,
0x52, 0xa9, 0x84, 0xda, 0xda, 0x5a, 0x28, 0x2f, 0x2f, 0xa7, 0x13, 0xd8, 0x27, 0xa3, 0x13, 0x59, 0xdc, 0x0c, 0x35, 0x35, 0x35, 0xb8, 0x03, 0x47, 0x64, 0xb8, 0x23, 0x8b, 0x45, 0xe2, 0x72, 0xa1,
0x2a, 0x92, 0x2e, 0x17, 0x49, 0xa8, 0xae, 0x0b, 0x77, 0xef, 0xee, 0x6d, 0xd8, 0xa8, 0x28, 0xa8, 0x04, 0xfb, 0x7a, 0xf3, 0xc6, 0x20, 0xfd, 0xde, 0xa5, 0x3c, 0x0e, 0x5f, 0x36, 0x9e, 0x87, 0xe9,
0xfb, 0xea, 0x3c, 0x0c, 0x0c, 0xfc, 0x0c, 0xcd, 0x5a, 0xed, 0x63, 0xbc, 0xff, 0x35, 0x12, 0xa9, 0xe9, 0x1f, 0xa1, 0x5f, 0xa3, 0xb9, 0xc7, 0xee, 0x7f, 0x16, 0x45, 0x1c, 0x06, 0x62, 0xfd, 0xe0,
0x28, 0x10, 0xd6, 0x43, 0x28, 0x2d, 0x2d, 0xfd, 0x83, 0x8a, 0x4e, 0xa7, 0xc1, 0xe4, 0xe4, 0x24, 0xab, 0xaa, 0xaa, 0x7e, 0xc3, 0xa6, 0xe3, 0x6e, 0xb0, 0xbc, 0xbc, 0x4c, 0xef, 0x9a, 0xe4, 0xe4,
0x3f, 0x6b, 0xa2, 0xa3, 0xa3, 0x59, 0x54, 0x52, 0x52, 0xe2, 0x13, 0x4d, 0xc5, 0xc5, 0x83, 0x31, 0x64, 0x12, 0x55, 0x56, 0x56, 0x46, 0x44, 0x5d, 0x0d, 0xe9, 0x70, 0x95, 0x35, 0x59, 0x40, 0xf5,
0x31, 0xd1, 0xc7, 0xdf, 0x27, 0x4e, 0xc0, 0x4c, 0x42, 0x02, 0x4c, 0xef, 0xff, 0x3e, 0x53, 0x7a, 0xc5, 0x53, 0xd0, 0xdb, 0x78, 0x0a, 0xb8, 0x4f, 0xf7, 0x7e, 0x9f, 0xd2, 0x7c, 0x08, 0x86, 0x9f,
0x0e, 0x86, 0x7e, 0xd1, 0xc3, 0xcd, 0x5b, 0xb7, 0xcc, 0x31, 0x31, 0x31, 0x09, 0xe2, 0xf3, 0xc8, 0x8c, 0xd0, 0xdd, 0xd7, 0x67, 0x4a, 0x49, 0x49, 0x39, 0x25, 0xbc, 0x8f, 0x6e, 0xef, 0xcf, 0x7a,
0xb0, 0x3f, 0xeb, 0xb1, 0xaa, 0xaa, 0xaa, 0x6b, 0x52, 0x11, 0xb5, 0x74, 0x76, 0x76, 0x36, 0x8b, 0xa1, 0xbe, 0xbe, 0xbe, 0x43, 0x2c, 0xc2, 0x25, 0x5d, 0x58, 0x58, 0x48, 0x22, 0x85, 0x42, 0xf1,
0x14, 0x0a, 0xc5, 0x0b, 0x9d, 0x75, 0xc6, 0x93, 0x27, 0xe1, 0xf6, 0xf5, 0x66, 0xf8, 0xee, 0xe2, 0x58, 0x7b, 0x5d, 0xff, 0xc5, 0xe7, 0xa0, 0xef, 0xbb, 0x7e, 0xb8, 0x70, 0xf1, 0xd2, 0xfd, 0x8c,
0xa5, 0x27, 0x89, 0x89, 0x89, 0xc7, 0xa4, 0x0f, 0xbe, 0xe3, 0x48, 0x1c, 0x22, 0xc7, 0xa6, 0xb8, 0x8c, 0x8c, 0x13, 0xe2, 0x17, 0xdf, 0x49, 0x46, 0x1a, 0x23, 0x89, 0x2d, 0x8a, 0x46, 0xa3, 0xd1,
0xa0, 0xd7, 0xeb, 0xe7, 0x87, 0x87, 0x87, 0x1f, 0xe1, 0x49, 0xe1, 0x26, 0x29, 0x65, 0x85, 0x7f, 0xb8, 0x36, 0x3b, 0x3b, 0xfb, 0x0f, 0xdb, 0x29, 0x82, 0x28, 0xc5, 0xac, 0xd8, 0x9f, 0x17, 0x7a,
0x5e, 0x78, 0x13, 0xbb, 0xf0, 0x39, 0x65, 0x7f, 0x64, 0x02, 0x6d, 0xfd, 0x8f, 0x70, 0xef, 0x6a, 0x88, 0x3d, 0xce, 0x4d, 0xb0, 0x5b, 0x36, 0x40, 0xdd, 0xdb, 0x0b, 0xdf, 0xab, 0x54, 0x84, 0xaa,
0x13, 0x73, 0xe7, 0xca, 0x4d, 0xb8, 0xf1, 0xed, 0x65, 0xa8, 0xfb, 0xfa, 0x02, 0x5c, 0x3d, 0xaf, 0xbb, 0x1b, 0xda, 0x5b, 0x5b, 0x59, 0xa9, 0x1a, 0xa1, 0x95, 0x95, 0x9d, 0xeb, 0xe0, 0xe0, 0xed,
0x84, 0xc6, 0xcb, 0x2a, 0xf8, 0xe8, 0xe3, 0xe2, 0xb9, 0xe4, 0xe4, 0xe4, 0x48, 0xbf, 0x27, 0x6c, 0x77, 0xce, 0xdd, 0xc9, 0xca, 0xca, 0x3a, 0x26, 0x79, 0xc3, 0x46, 0xf9, 0x23, 0x91, 0xc4, 0x84,
0x80, 0x3f, 0x12, 0x72, 0x14, 0x2e, 0x8a, 0x67, 0x99, 0x74, 0x73, 0x4a, 0x3b, 0x8d, 0x3e, 0xd3, 0xeb, 0xc2, 0x5e, 0x26, 0x7e, 0x38, 0xc5, 0x2b, 0x0d, 0xcf, 0x71, 0xd7, 0x60, 0xcf, 0x21, 0xeb,
0xa9, 0x81, 0xfb, 0x10, 0xeb, 0x31, 0x00, 0x0f, 0xa6, 0xa6, 0xbc, 0x79, 0x1f, 0x7c, 0x78, 0x03, 0xc7, 0x34, 0xfc, 0x79, 0xeb, 0x56, 0xb8, 0xe4, 0xcd, 0xb7, 0xba, 0xd8, 0xfd, 0x71, 0x47, 0x62,
0xef, 0x0f, 0x3d, 0x12, 0x33, 0x90, 0x68, 0x70, 0x70, 0xd0, 0x88, 0x12, 0x2f, 0x4a, 0x18, 0x94, 0x46, 0x13, 0xcd, 0xcc, 0xcc, 0xac, 0x32, 0x49, 0x98, 0x49, 0x08, 0x26, 0x21, 0x58, 0x70, 0x09,
0x30, 0x18, 0xdc, 0x0f, 0x97, 0x6b, 0xc7, 0xbb, 0x6c, 0x5e, 0xf1, 0xb6, 0xea, 0xba, 0xec, 0xef, 0x81, 0xc0, 0x4e, 0x78, 0xcb, 0x64, 0x0e, 0xeb, 0xf4, 0xa3, 0xde, 0x57, 0xcf, 0x9e, 0x7d, 0xf7,
0x9e, 0x39, 0xf3, 0xe9, 0xf3, 0xe2, 0x05, 0x13, 0xbd, 0x44, 0xfb, 0xeb, 0x3f, 0xa2, 0x08, 0x24, 0x51, 0xf1, 0x62, 0x89, 0x9e, 0xc0, 0xe7, 0xeb, 0x3f, 0xa2, 0x88, 0x26, 0x41, 0xfe, 0x05, 0xd8,
0x21, 0xfe, 0x05, 0x91, 0xa7, 0xfc, 0x24, 0x73, 0x8d, 0x40, 0x41, 0x00, 0x00, 0x00, 0x00, 0x49, 0x59, 0x10, 0x8c, 0xd8, 0x02, 0xbb, 0x25, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae,
0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0x42, 0x60, 0x82,
}; };
const BITMAP_OPAQUE add_hierarchical_label_xpm[1] = {{ png, sizeof( png ), "add_hierarchical_label_xpm" }}; const BITMAP_OPAQUE add_hierarchical_label_xpm[1] = {{ png, sizeof( png ), "add_hierarchical_label_xpm" }};
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
width="26" width="26"
version="1.1" version="1.1"
id="svg2" id="svg2"
inkscape:version="0.48.2 r9819" inkscape:version="0.48.1 "
sodipodi:docname="add_hierarchical_label.svg"> sodipodi:docname="add_hierarchical_label.svg">
<metadata <metadata
id="metadata22"> id="metadata22">
...@@ -801,14 +801,14 @@ ...@@ -801,14 +801,14 @@
inkscape:pageopacity="0" inkscape:pageopacity="0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:window-width="1280" inkscape:window-width="1280"
inkscape:window-height="941" inkscape:window-height="968"
id="namedview18" id="namedview18"
showgrid="true" showgrid="true"
inkscape:zoom="27.812867" inkscape:zoom="30.205858"
inkscape:cx="13.075538" inkscape:cx="14.001662"
inkscape:cy="10.42187" inkscape:cy="12.978439"
inkscape:window-x="0" inkscape:window-x="-4"
inkscape:window-y="30" inkscape:window-y="-4"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:current-layer="svg2" inkscape:current-layer="svg2"
inkscape:snap-grids="false" inkscape:snap-grids="false"
...@@ -929,7 +929,7 @@ ...@@ -929,7 +929,7 @@
id="path42" id="path42"
d="m 12.030832,21.080758 7.978779,0 3.419474,-6.034091 -3.419474,-6.0340911 -7.978779,0 0,12.0681821 z" d="m 12.030832,21.080758 7.978779,0 3.419474,-6.034091 -3.419474,-6.0340911 -7.978779,0 0,12.0681821 z"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:none;stroke:#d50000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> style="fill:none;stroke:#997a00;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path <path
sodipodi:nodetypes="ccccccccccc" sodipodi:nodetypes="ccccccccccc"
id="path40" id="path40"
......
...@@ -57,7 +57,7 @@ SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, const KIC ...@@ -57,7 +57,7 @@ SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, const KIC
SCH_COMPONENT* LibItem = NULL; SCH_COMPONENT* LibItem = NULL;
wxPoint gridPosition = GetScreen()->GetNearestGridPosition( aPosition ); wxPoint gridPosition = GetScreen()->GetNearestGridPosition( aPosition );
// Check the on grid position first. There is more likely to be multple items on // Check the on grid position first. There is more likely to be multiple items on
// grid than off grid. // grid than off grid.
item = LocateItem( gridPosition, aFilterList, aHotKeyCommandId ); item = LocateItem( gridPosition, aFilterList, aHotKeyCommandId );
...@@ -197,7 +197,16 @@ void SCH_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH ...@@ -197,7 +197,16 @@ void SCH_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH
wxPoint oldpos; wxPoint oldpos;
wxPoint pos = aPosition; wxPoint pos = aPosition;
// when moving mouse, use the "magnetic" grid, unless the shift+ctrl keys is pressed
// for next cursor position
// ( shift or ctrl key down are PAN command with mouse wheel)
bool snapToGrid = true;
if( !aHotKey && wxGetKeyState( WXK_SHIFT ) && wxGetKeyState( WXK_CONTROL ) )
snapToGrid = false;
if( snapToGrid )
pos = screen->GetNearestGridPosition( pos ); pos = screen->GetNearestGridPosition( pos );
oldpos = screen->GetCrossHairPosition(); oldpos = screen->GetCrossHairPosition();
gridSize = screen->GetGridSize(); gridSize = screen->GetGridSize();
...@@ -235,14 +244,14 @@ void SCH_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH ...@@ -235,14 +244,14 @@ void SCH_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH
} }
// Update cursor position. // Update cursor position.
screen->SetCrossHairPosition( pos ); screen->SetCrossHairPosition( pos, snapToGrid );
if( oldpos != screen->GetCrossHairPosition() ) if( oldpos != screen->GetCrossHairPosition() )
{ {
pos = screen->GetCrossHairPosition(); pos = screen->GetCrossHairPosition();
screen->SetCrossHairPosition( oldpos ); screen->SetCrossHairPosition( oldpos, false);
m_canvas->CrossHairOff( aDC ); m_canvas->CrossHairOff( aDC );
screen->SetCrossHairPosition( pos ); screen->SetCrossHairPosition( pos, snapToGrid );
m_canvas->CrossHairOn( aDC ); m_canvas->CrossHairOn( aDC );
if( m_canvas->IsMouseCaptured() ) if( m_canvas->IsMouseCaptured() )
...@@ -282,7 +291,16 @@ void LIB_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH ...@@ -282,7 +291,16 @@ void LIB_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH
wxPoint oldpos; wxPoint oldpos;
wxPoint pos = aPosition; wxPoint pos = aPosition;
// when moving mouse, use the "magnetic" grid, unless the shift+ctrl keys is pressed
// for next cursor position
// ( shift or ctrl key down are PAN command with mouse wheel)
bool snapToGrid = true;
if( !aHotKey && wxGetKeyState( WXK_SHIFT ) && wxGetKeyState( WXK_CONTROL ) )
snapToGrid = false;
if( snapToGrid )
pos = screen->GetNearestGridPosition( pos ); pos = screen->GetNearestGridPosition( pos );
oldpos = screen->GetCrossHairPosition(); oldpos = screen->GetCrossHairPosition();
gridSize = screen->GetGridSize(); gridSize = screen->GetGridSize();
...@@ -320,14 +338,14 @@ void LIB_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH ...@@ -320,14 +338,14 @@ void LIB_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH
} }
// Update the cursor position. // Update the cursor position.
screen->SetCrossHairPosition( pos ); screen->SetCrossHairPosition( pos, snapToGrid );
if( oldpos != screen->GetCrossHairPosition() ) if( oldpos != screen->GetCrossHairPosition() )
{ {
pos = screen->GetCrossHairPosition(); pos = screen->GetCrossHairPosition();
screen->SetCrossHairPosition( oldpos ); screen->SetCrossHairPosition( oldpos, false );
m_canvas->CrossHairOff( aDC ); m_canvas->CrossHairOff( aDC );
screen->SetCrossHairPosition( pos ); screen->SetCrossHairPosition( pos, snapToGrid );
m_canvas->CrossHairOn( aDC ); m_canvas->CrossHairOn( aDC );
if( m_canvas->IsMouseCaptured() ) if( m_canvas->IsMouseCaptured() )
......
...@@ -67,4 +67,11 @@ inline int Mils2iu( int mils ) ...@@ -67,4 +67,11 @@ inline int Mils2iu( int mils )
} }
#endif #endif
/// Convert mm to internal units (iu).
inline int Millimeter2iu( double mm )
{
return (int) ( mm < 0 ? mm * IU_PER_MM - 0.5 : mm * IU_PER_MM + 0.5);
}
#endif // CONVERT_TO_BIU_H_ #endif // CONVERT_TO_BIU_H_
...@@ -262,7 +262,17 @@ void PCB_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH ...@@ -262,7 +262,17 @@ void PCB_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH
{ {
wxRealPoint gridSize; wxRealPoint gridSize;
wxPoint oldpos; wxPoint oldpos;
wxPoint pos = GetScreen()->GetNearestGridPosition( aPosition ); wxPoint pos = aPosition;
// when moving mouse, use the "magnetic" grid, unless the shift+ctrl keys is pressed
// for next cursor position
// ( shift or ctrl key down are PAN command with mouse wheel)
bool snapToGrid = true;
if( !aHotKey && wxGetKeyState( WXK_SHIFT ) && wxGetKeyState( WXK_CONTROL ) )
snapToGrid = false;
if( snapToGrid )
pos = GetScreen()->GetNearestGridPosition( pos );
oldpos = GetScreen()->GetCrossHairPosition(); oldpos = GetScreen()->GetCrossHairPosition();
...@@ -299,34 +309,25 @@ void PCB_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH ...@@ -299,34 +309,25 @@ void PCB_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH
} }
// Put cursor in new position, according to the zoom keys (if any). // Put cursor in new position, according to the zoom keys (if any).
GetScreen()->SetCrossHairPosition( pos ); GetScreen()->SetCrossHairPosition( pos, snapToGrid );
/* Put cursor on grid or a pad centre if requested. If the tool DELETE is active the /* Put cursor on grid or a pad centre if requested. If the tool DELETE is active the
* cursor is left off grid this is better to reach items to delete off grid, * cursor is left off grid this is better to reach items to delete off grid,
*/ */
bool keep_on_grid = true;
if( GetToolId() == ID_PCB_DELETE_ITEM_BUTT ) if( GetToolId() == ID_PCB_DELETE_ITEM_BUTT )
keep_on_grid = false; snapToGrid = false;
/* Cursor is left off grid if no block in progress and no moving object */ // Cursor is left off grid if no block in progress
if( GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK ) if( GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK )
keep_on_grid = true; snapToGrid = true;
EDA_ITEM* DrawStruct = GetScreen()->GetCurItem();
if( DrawStruct && DrawStruct->GetFlags() ) wxPoint curs_pos = pos;
keep_on_grid = true;
if( keep_on_grid )
{
wxPoint on_grid = GetScreen()->GetNearestGridPosition( pos );
wxSize grid; wxSize grid;
grid.x = (int) GetScreen()->GetGridSize().x; grid.x = KiROUND( GetScreen()->GetGridSize().x );
grid.y = (int) GetScreen()->GetGridSize().y; grid.y = KiROUND( GetScreen()->GetGridSize().y );
if( Magnetize( m_Pcb, this, GetToolId(), grid, on_grid, &pos ) ) if( Magnetize( m_Pcb, this, GetToolId(), grid, curs_pos, &pos ) )
{ {
GetScreen()->SetCrossHairPosition( pos, false ); GetScreen()->SetCrossHairPosition( pos, false );
} }
...@@ -339,11 +340,11 @@ void PCB_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH ...@@ -339,11 +340,11 @@ void PCB_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aH
|| !LocateIntrusion( m_Pcb->m_Track, g_CurrentTrackSegment, || !LocateIntrusion( m_Pcb->m_Track, g_CurrentTrackSegment,
GetScreen()->m_Active_Layer, GetScreen()->RefPos( true ) ) ) GetScreen()->m_Active_Layer, GetScreen()->RefPos( true ) ) )
{ {
GetScreen()->SetCrossHairPosition( on_grid ); GetScreen()->SetCrossHairPosition( curs_pos, snapToGrid );
}
} }
} }
if( oldpos != GetScreen()->GetCrossHairPosition() ) if( oldpos != GetScreen()->GetCrossHairPosition() )
{ {
pos = GetScreen()->GetCrossHairPosition(); pos = GetScreen()->GetCrossHairPosition();
......
...@@ -312,18 +312,16 @@ void DIALOG_MODULE_BOARD_EDITOR::InitModeditProperties() ...@@ -312,18 +312,16 @@ void DIALOG_MODULE_BOARD_EDITOR::InitModeditProperties()
// Initialize 3D parameters // Initialize 3D parameters
wxBoxSizer* BoxSizer = new wxBoxSizer( wxVERTICAL ); wxBoxSizer* BoxSizer = new wxBoxSizer( wxVERTICAL );
m_3D_Scale = new WinEDA_VertexCtrl( m_Panel3D, _( "Shape Scale:" ), m_3D_Scale = new VERTEX_VALUE_CTRL( m_Panel3D, _( "Shape Scale:" ), BoxSizer );
BoxSizer, UNSCALED_UNITS, 1 );
m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 ); m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 );
BoxSizer = new wxBoxSizer( wxVERTICAL ); BoxSizer = new wxBoxSizer( wxVERTICAL );
m_3D_Offset = new WinEDA_VertexCtrl( m_Panel3D, _( "Shape Offset:" ), m_3D_Offset = new VERTEX_VALUE_CTRL( m_Panel3D, _( "Shape Offset (inch):" ), BoxSizer );
BoxSizer, UNSCALED_UNITS, 1 );
m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 ); m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 );
BoxSizer = new wxBoxSizer( wxVERTICAL ); BoxSizer = new wxBoxSizer( wxVERTICAL );
m_3D_Rotation = new WinEDA_VertexCtrl( m_Panel3D, _( "Shape Rotation:" ), m_3D_Rotation = new VERTEX_VALUE_CTRL( m_Panel3D,
BoxSizer, UNSCALED_UNITS, 1 ); _( "Shape Rotation (degrees):" ), BoxSizer );
m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 ); m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 );
// if m_3D_ShapeNameListBox is not empty, preselect first 3D shape // if m_3D_ShapeNameListBox is not empty, preselect first 3D shape
......
...@@ -20,9 +20,9 @@ private: ...@@ -20,9 +20,9 @@ private:
TEXTE_MODULE* m_ValueCopy; TEXTE_MODULE* m_ValueCopy;
std::vector <S3D_MASTER*> m_Shapes3D_list; std::vector <S3D_MASTER*> m_Shapes3D_list;
int m_LastSelected3DShapeIndex; int m_LastSelected3DShapeIndex;
WinEDA_VertexCtrl * m_3D_Scale; VERTEX_VALUE_CTRL * m_3D_Scale;
WinEDA_VertexCtrl * m_3D_Offset; VERTEX_VALUE_CTRL * m_3D_Offset;
WinEDA_VertexCtrl * m_3D_Rotation; VERTEX_VALUE_CTRL * m_3D_Rotation;
public: public:
......
...@@ -131,15 +131,15 @@ void DIALOG_MODULE_MODULE_EDITOR::InitModeditProperties() ...@@ -131,15 +131,15 @@ void DIALOG_MODULE_MODULE_EDITOR::InitModeditProperties()
// Initialize 3D parameters // Initialize 3D parameters
wxBoxSizer* BoxSizer = new wxBoxSizer( wxVERTICAL ); wxBoxSizer* BoxSizer = new wxBoxSizer( wxVERTICAL );
m_3D_Scale = new WinEDA_VertexCtrl( m_Panel3D, _( "Shape Scale:" ), BoxSizer, UNSCALED_UNITS, 1 ); m_3D_Scale = new VERTEX_VALUE_CTRL( m_Panel3D, _( "Shape Scale:" ), BoxSizer );
m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 ); m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 );
BoxSizer = new wxBoxSizer( wxVERTICAL ); BoxSizer = new wxBoxSizer( wxVERTICAL );
m_3D_Offset = new WinEDA_VertexCtrl( m_Panel3D, _( "Shape Offset:" ), BoxSizer, UNSCALED_UNITS, 1 ); m_3D_Offset = new VERTEX_VALUE_CTRL( m_Panel3D, _( "Shape Offset (inch):" ), BoxSizer );
m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 ); m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 );
BoxSizer = new wxBoxSizer( wxVERTICAL ); BoxSizer = new wxBoxSizer( wxVERTICAL );
m_3D_Rotation = new WinEDA_VertexCtrl( m_Panel3D, _( "Shape Rotation:" ), BoxSizer, UNSCALED_UNITS, 1 ); m_3D_Rotation = new VERTEX_VALUE_CTRL( m_Panel3D, _( "Shape Rotation (degrees):" ), BoxSizer );
m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 ); m_Sizer3DValues->Add( BoxSizer, 0, wxGROW | wxALL, 5 );
// Initialize dialog relative to masks clearances // Initialize dialog relative to masks clearances
......
...@@ -23,9 +23,9 @@ private: ...@@ -23,9 +23,9 @@ private:
TEXTE_MODULE* m_ValueCopy; TEXTE_MODULE* m_ValueCopy;
std::vector <S3D_MASTER*> m_Shapes3D_list; std::vector <S3D_MASTER*> m_Shapes3D_list;
int m_LastSelected3DShapeIndex; int m_LastSelected3DShapeIndex;
WinEDA_VertexCtrl * m_3D_Scale; VERTEX_VALUE_CTRL * m_3D_Scale;
WinEDA_VertexCtrl * m_3D_Offset; VERTEX_VALUE_CTRL * m_3D_Offset;
WinEDA_VertexCtrl * m_3D_Rotation; VERTEX_VALUE_CTRL * m_3D_Rotation;
public: public:
......
...@@ -343,7 +343,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() ...@@ -343,7 +343,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
// 3D Display // 3D Display
AddMenuItem( viewMenu, ID_MENU_PCB_SHOW_3D_FRAME, AddMenuItem( viewMenu, ID_MENU_PCB_SHOW_3D_FRAME,
_( "3&D Display" ),_( "Show board in 3D viewer" ), _( "&3D Display" ),_( "Show board in 3D viewer" ),
KiBitmap( three_d_xpm ) ); KiBitmap( three_d_xpm ) );
// List Nets // List Nets
...@@ -372,7 +372,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() ...@@ -372,7 +372,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
// Keepout areas // Keepout areas
AddMenuItem( placeMenu, ID_PCB_KEEPOUT_AREA_BUTT, AddMenuItem( placeMenu, ID_PCB_KEEPOUT_AREA_BUTT,
_( "&Zone" ), _( "Add keepout areas" ), KiBitmap( add_keepout_area_xpm ) ); _( "&Keepout Area" ), _( "Add keepout areas" ), KiBitmap( add_keepout_area_xpm ) );
// Text // Text
AddMenuItem( placeMenu, ID_PCB_ADD_TEXT_BUTT, AddMenuItem( placeMenu, ID_PCB_ADD_TEXT_BUTT,
......
...@@ -429,7 +429,16 @@ void FOOTPRINT_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, ...@@ -429,7 +429,16 @@ void FOOTPRINT_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition,
wxPoint oldpos; wxPoint oldpos;
wxPoint pos = aPosition; wxPoint pos = aPosition;
pos = GetScreen()->GetNearestGridPosition( aPosition ); // when moving mouse, use the "magnetic" grid, unless the shift+ctrl keys is pressed
// for next cursor position
// ( shift or ctrl key down are PAN command with mouse wheel)
bool snapToGrid = true;
if( !aHotKey && wxGetKeyState( WXK_SHIFT ) && wxGetKeyState( WXK_CONTROL ) )
snapToGrid = false;
if( snapToGrid )
pos = GetScreen()->GetNearestGridPosition( pos );
oldpos = GetScreen()->GetCrossHairPosition(); oldpos = GetScreen()->GetCrossHairPosition();
gridSize = GetScreen()->GetGridSize(); gridSize = GetScreen()->GetGridSize();
...@@ -463,14 +472,14 @@ void FOOTPRINT_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, ...@@ -463,14 +472,14 @@ void FOOTPRINT_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition,
break; break;
} }
GetScreen()->SetCrossHairPosition( pos ); GetScreen()->SetCrossHairPosition( pos, snapToGrid );
if( oldpos != GetScreen()->GetCrossHairPosition() ) if( oldpos != GetScreen()->GetCrossHairPosition() )
{ {
pos = GetScreen()->GetCrossHairPosition(); pos = GetScreen()->GetCrossHairPosition();
GetScreen()->SetCrossHairPosition( oldpos ); GetScreen()->SetCrossHairPosition( oldpos, false );
m_canvas->CrossHairOff( aDC ); m_canvas->CrossHairOff( aDC );
GetScreen()->SetCrossHairPosition( pos ); GetScreen()->SetCrossHairPosition( pos, snapToGrid );
m_canvas->CrossHairOn( aDC ); m_canvas->CrossHairOn( aDC );
if( m_canvas->IsMouseCaptured() ) if( m_canvas->IsMouseCaptured() )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment