KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_export_step.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2016 Cirilo Bernardo
5 * Copyright (C) 2016-2024 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <wx/log.h>
26#include <wx/stdpaths.h>
27#include <wx/process.h>
28#include <wx/string.h>
29#include <wx/filedlg.h>
30
31#include <pgm_base.h>
32#include <board.h>
33#include <confirm.h>
34#include <kidialog.h>
38#include <footprint.h>
39#include <kiface_base.h>
40#include <locale_io.h>
41#include <math/vector3.h>
42#include <pcb_edit_frame.h>
43#include <pcbnew_settings.h>
44#include <project/project_file.h> // LAST_PATH_TYPE
45#include <reporter.h>
46#include <trace_helpers.h>
49#include <filename_resolver.h>
50
51
53{
54public:
56 {
57 STEP_ORIGIN_0, // absolute coordinates
58 STEP_ORIGIN_PLOT_AXIS, // origin is plot/drill axis origin
59 STEP_ORIGIN_GRID_AXIS, // origin is grid origin
60 STEP_ORIGIN_BOARD_CENTER, // origin is board center
61 STEP_ORIGIN_USER, // origin is entered by user
62 };
63
64 DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aParent, const wxString& aBoardPath );
66
67protected:
68 void onBrowseClicked( wxCommandEvent& aEvent ) override;
69 void onUpdateUnits( wxUpdateUIEvent& aEvent ) override;
70 void onUpdateXPos( wxUpdateUIEvent& aEvent ) override;
71 void onUpdateYPos( wxUpdateUIEvent& aEvent ) override;
72 void onExportButton( wxCommandEvent& aEvent ) override;
73
75 {
76 return m_STEP_OrgUnitChoice->GetSelection();
77 }
78
79 double GetXOrg() const
80 {
82 }
83
84 double GetYOrg()
85 {
87 }
88
90
92 {
93 return m_cbRemoveUnspecified->GetValue();
94 }
95
97 {
98 return m_cbRemoveDNP->GetValue();
99 }
100
102 {
103 return m_cbSubstModels->GetValue();
104 }
105
107 {
108 return m_cbOverwriteFile->GetValue();
109 }
110
111private:
113 STEP_ORIGIN_OPTION m_origin; // The last preference for STEP origin option
114 double m_userOriginX; // remember last User Origin X value
115 double m_userOriginY; // remember last User Origin Y value
116 int m_originUnits; // remember last units for User Origin
117 bool m_noUnspecified; // remember last preference for No Unspecified Component
118 bool m_noDNP; // remember last preference for No DNP Component
119 static bool m_optimizeStep; // remember last preference for Optimize STEP file (stored only for the session)
120 static bool m_exportBoardBody; // remember last preference to export board body (stored only for the session)
121 static bool m_exportComponents; // remember last preference to export components (stored only for the session)
122 static bool m_exportTracks; // remember last preference to export tracks (stored only for the session)
123 static bool m_exportZones; // remember last preference to export zones (stored only for the session)
124 static bool m_fuseShapes; // remember last preference to fuse shapes (stored only for the session)
125 static bool m_exportInnerCopper; // remember last preference to export inner layers (stored only for the session)
126 wxString m_netFilter; // filter copper nets
127 wxString m_boardPath; // path to the exported board file
128 static int m_toleranceLastChoice; // Store m_tolerance option during a session
129};
130
131
132int DIALOG_EXPORT_STEP::m_toleranceLastChoice = -1; // Use default
140
141DIALOG_EXPORT_STEP::DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aParent, const wxString& aBoardPath ) :
142 DIALOG_EXPORT_STEP_BASE( aParent )
143{
144 m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
145
146 m_parent = aParent;
147 m_boardPath = aBoardPath;
148
149 SetupStandardButtons( { { wxID_OK, _( "Export" ) },
150 { wxID_CANCEL, _( "Close" ) } } );
151
152 // Build default output file name
153 // (last saved filename in project or built from board filename)
155
156 if( path.IsEmpty() )
157 {
158 wxFileName brdFile( m_parent->GetBoard()->GetFileName() );
159 brdFile.SetExt( wxT( "step" ) );
160 path = brdFile.GetFullPath();
161 }
162
163 m_outputFileName->SetValue( path );
164
165 Layout();
166 bSizerSTEPFile->Fit( this );
167
168 SetFocus();
169
171
173
174 switch( m_origin )
175 {
176 default:
177 case STEP_ORIGIN_PLOT_AXIS: m_rbDrillAndPlotOrigin->SetValue( true ); break;
178 case STEP_ORIGIN_GRID_AXIS: m_rbGridOrigin->SetValue( true ); break;
179 case STEP_ORIGIN_USER: m_rbUserDefinedOrigin->SetValue( true ); break;
180 case STEP_ORIGIN_BOARD_CENTER: m_rbBoardCenterOrigin->SetValue( true ); break;
181 }
182
188
189 m_txtNetFilter->SetValue( m_netFilter );
190 m_cbOptimizeStep->SetValue( m_optimizeStep );
193 m_cbExportTracks->SetValue( m_exportTracks );
194 m_cbExportZones->SetValue( m_exportZones );
196 m_cbFuseShapes->SetValue( m_fuseShapes );
198 m_cbRemoveDNP->SetValue( m_noDNP );
201
202 m_STEP_OrgUnitChoice->SetSelection( m_originUnits );
203 wxString tmpStr;
204 tmpStr << m_userOriginX;
205 m_STEP_Xorg->SetValue( tmpStr );
206 tmpStr = wxEmptyString;
207 tmpStr << m_userOriginY;
208 m_STEP_Yorg->SetValue( tmpStr );
209
210 wxString bad_scales;
211 size_t bad_count = 0;
212
213 for( FOOTPRINT* fp : aParent->GetBoard()->Footprints() )
214 {
215 for( const FP_3DMODEL& model : fp->Models() )
216 {
217 if( model.m_Scale.x != 1.0 || model.m_Scale.y != 1.0 || model.m_Scale.z != 1.0 )
218 {
219 bad_scales.Append( wxS("\n") );
220 bad_scales.Append( model.m_Filename );
221 bad_count++;
222 }
223 }
224
225 if( bad_count >= 5 )
226 break;
227 }
228
229 if( !bad_scales.empty()
231 {
232 wxString extendedMsg = _( "Non-unity scaled models:" ) + wxT( "\n" ) + bad_scales;
233
234 KIDIALOG msgDlg( m_parent, _( "Scaled models detected. "
235 "Model scaling is not reliable for mechanical export." ),
236 _( "Model Scale Warning" ), wxOK | wxICON_WARNING );
237 msgDlg.SetExtendedMessage( extendedMsg );
238 msgDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
239
240 msgDlg.ShowModal();
241
242 if( msgDlg.DoNotShowAgain() )
244 }
245
246 if( m_toleranceLastChoice >= 0 )
248
249 // Now all widgets have the size fixed, call FinishDialogSettings
251}
252
253
255{
256 GetOriginOption(); // Update m_origin member.
257
258 PCBNEW_SETTINGS* cfg = nullptr;
259
260 try
261 {
263 }
264 catch( const std::runtime_error& e )
265 {
266 wxFAIL_MSG( e.what() );
267 }
268
269 if( cfg )
270 {
271 cfg->m_ExportStep.origin_mode = static_cast<int>( m_origin );
272 cfg->m_ExportStep.origin_units = m_STEP_OrgUnitChoice->GetSelection();
275
276 double val = 0.0;
277
278 m_STEP_Xorg->GetValue().ToDouble( &val );
279 cfg->m_ExportStep.origin_x = val;
280
281 m_STEP_Yorg->GetValue().ToDouble( &val );
282 cfg->m_ExportStep.origin_y = val;
283
285 cfg->m_ExportStep.no_dnp = m_cbRemoveDNP->GetValue();
286 }
287
288 m_netFilter = m_txtNetFilter->GetValue();
290 m_optimizeStep = m_cbOptimizeStep->GetValue();
291 m_exportBoardBody = m_cbExportBody->GetValue();
293 m_exportTracks = m_cbExportTracks->GetValue();
294 m_exportZones = m_cbExportZones->GetValue();
296 m_fuseShapes = m_cbFuseShapes->GetValue();
297}
298
299
301{
303
304 if( m_rbDrillAndPlotOrigin->GetValue() )
306 else if( m_rbGridOrigin->GetValue() )
308 else if( m_rbUserDefinedOrigin->GetValue() )
310 else if( m_rbBoardCenterOrigin->GetValue() )
312
313 return m_origin;
314}
315
316
317void PCB_EDIT_FRAME::OnExportSTEP( wxCommandEvent& event )
318{
319 wxFileName brdFile = GetBoard()->GetFileName();
320
321 if( GetScreen()->IsContentModified() || brdFile.GetFullPath().empty() )
322 {
323 if( !doAutoSave() )
324 {
325 DisplayErrorMessage( this, _( "STEP export failed! "
326 "Please save the PCB and try again" ) );
327 return;
328 }
329
330 // Use auto-saved board for export
331 brdFile.SetName( FILEEXT::AutoSaveFilePrefix + brdFile.GetName() );
332 }
333
334 DIALOG_EXPORT_STEP dlg( this, brdFile.GetFullPath() );
335 dlg.ShowModal();
336}
337
338
339void DIALOG_EXPORT_STEP::onUpdateUnits( wxUpdateUIEvent& aEvent )
340{
341 aEvent.Enable( m_rbUserDefinedOrigin->GetValue() );
342}
343
344
345void DIALOG_EXPORT_STEP::onUpdateXPos( wxUpdateUIEvent& aEvent )
346{
347 aEvent.Enable( m_rbUserDefinedOrigin->GetValue() );
348}
349
350
351void DIALOG_EXPORT_STEP::onUpdateYPos( wxUpdateUIEvent& aEvent )
352{
353 aEvent.Enable( m_rbUserDefinedOrigin->GetValue() );
354}
355
356
357void DIALOG_EXPORT_STEP::onBrowseClicked( wxCommandEvent& aEvent )
358{
359 wxString filter = _( "STEP files" )
361 + _( "Binary glTF files" )
363
364 // Build the absolute path of current output directory to preselect it in the file browser.
365 wxString path = ExpandEnvVarSubstitutions( m_outputFileName->GetValue(), &Prj() );
366 wxFileName fn( Prj().AbsolutePath( path ) );
367
368 wxFileDialog dlg( this, _( "STEP Output File" ), fn.GetPath(), fn.GetFullName(), filter,
369 wxFD_SAVE );
370
371 if( dlg.ShowModal() == wxID_CANCEL )
372 return;
373
374 m_outputFileName->SetValue( dlg.GetPath() );
375}
376
377
378void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
379{
380 wxString path = m_outputFileName->GetValue();
382
383 // Build the absolute path of current output directory to preselect it in the file browser.
384 std::function<bool( wxString* )> textResolver =
385 [&]( wxString* token ) -> bool
386 {
387 return m_parent->GetBoard()->ResolveTextVar( token, 0 );
388 };
389
390 path = ExpandTextVars( path, &textResolver );
392 path = Prj().AbsolutePath( path );
393
394 if( path.IsEmpty() )
395 {
396 DisplayErrorMessage( this, _( "No filename for output file" ) );
397 return;
398 }
399
400 m_netFilter = m_txtNetFilter->GetValue();
401
402 double tolerance; // default value in mm
404 m_optimizeStep = m_cbOptimizeStep->GetValue();
405 m_exportBoardBody = m_cbExportBody->GetValue();
407 m_exportTracks = m_cbExportTracks->GetValue();
408 m_exportZones = m_cbExportZones->GetValue();
410 m_fuseShapes = m_cbFuseShapes->GetValue();
411
412 switch( m_choiceTolerance->GetSelection() )
413 {
414 case 0: tolerance = 0.001; break;
415 default:
416 case 1: tolerance = 0.01; break;
417 case 2: tolerance = 0.1; break;
418 }
419
420 SHAPE_POLY_SET outline;
421 wxString msg;
422
423 // Check if the board outline is continuous
424 // max dist from one endPt to next startPt to build a closed shape:
425 int chainingEpsilon = pcbIUScale.mmToIU( tolerance );
426
427 // Arc to segment approx error (not critical here: we do not use the outline shape):
428 int maxError = pcbIUScale.mmToIU( 0.005 );
429 bool success = BuildBoardPolygonOutlines( m_parent->GetBoard(), outline, maxError,
430 chainingEpsilon, nullptr );
431 if( !success )
432 {
433 DisplayErrorMessage( this, wxString::Format(
434 _( "Board outline is missing or not closed using %.3f mm tolerance.\n"
435 "Run DRC for a full analysis." ), tolerance ) );
436 return;
437 }
438
439 wxFileName fn( Prj().AbsolutePath( path ) );
440
441 if( fn.FileExists() && !GetOverwriteFile() )
442 {
443 msg.Printf( _( "File '%s' already exists. Do you want overwrite this file?" ),
444 fn.GetFullPath() );
445
446 if( wxMessageBox( msg, _( "STEP/GLTF Export" ), wxYES_NO | wxICON_QUESTION, this ) == wxNO )
447 return;
448 }
449
450 wxFileName appK2S( wxStandardPaths::Get().GetExecutablePath() );
451#ifdef __WXMAC__
452 // On macOS, we have standalone applications inside the main bundle, so we handle that here:
453 if( appK2S.GetPath().Find( "/Contents/Applications/pcbnew.app/Contents/MacOS" ) != wxNOT_FOUND )
454 {
455 appK2S.AppendDir( wxT( ".." ) );
456 appK2S.AppendDir( wxT( ".." ) );
457 appK2S.AppendDir( wxT( ".." ) );
458 appK2S.AppendDir( wxT( ".." ) );
459 appK2S.AppendDir( wxT( "MacOS" ) );
460 }
461#else
462 if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
463 {
464 appK2S.RemoveLastDir();
465 appK2S.AppendDir( "kicad" );
466 }
467#endif
468
469 appK2S.SetName( wxT( "kicad-cli" ) );
470 appK2S.Normalize( FN_NORMALIZE_FLAGS );
471
472 wxString cmdK2S = wxT( "\"" );
473 cmdK2S.Append( appK2S.GetFullPath() );
474 cmdK2S.Append( wxT( "\"" ) );
475
476 cmdK2S.Append( wxT( " pcb" ) );
477 cmdK2S.Append( wxT( " export" ) );
478
479 if( fn.GetExt() == FILEEXT::GltfBinaryFileExtension )
480 cmdK2S.Append( wxT( " glb" ) );
481 else if( fn.GetExt() == FILEEXT::BrepFileExtension )
482 cmdK2S.Append( wxT( " brep" ) );
483 else if( fn.GetExt() == FILEEXT::XaoFileExtension )
484 cmdK2S.Append( wxT( " xao" ) );
485 else
486 cmdK2S.Append( wxT( " step" ) );
487
489 cmdK2S.Append( wxT( " --no-unspecified" ) );
490
491 if( GetNoDNPOption() )
492 cmdK2S.Append( wxT( " --no-dnp" ) );
493
494 if( GetSubstOption() )
495 cmdK2S.Append( wxT( " --subst-models" ) );
496
497 if( !m_optimizeStep )
498 cmdK2S.Append( wxT( " --no-optimize-step" ) );
499
500 if( !m_exportBoardBody )
501 cmdK2S.Append( wxT( " --no-board-body" ) );
502
503 if( !m_exportComponents )
504 cmdK2S.Append( wxT( " --no-components" ) );
505
506 if( m_exportTracks )
507 cmdK2S.Append( wxT( " --include-tracks" ) );
508
509 if( m_exportZones )
510 cmdK2S.Append( wxT( " --include-zones" ) );
511
513 cmdK2S.Append( wxT( " --include-inner-copper" ) );
514
515 if( m_fuseShapes )
516 cmdK2S.Append( wxT( " --fuse-shapes" ) );
517
518 // Note: for some reason, using \" to insert a quote in a format string, under MacOS
519 // wxString::Format does not work. So use a %c format in string
520 int quote = '\'';
521 int dblquote = '"';
522
523 if( !m_netFilter.empty() )
524 {
525 cmdK2S.Append( wxString::Format( wxT( " --net-filter %c%s%c" ), dblquote, m_netFilter,
526 dblquote ) );
527 }
528
529 switch( GetOriginOption() )
530 {
531 case STEP_ORIGIN_0:
532 wxFAIL_MSG( wxT( "Unsupported origin option: how did we get here?" ) );
533 break;
534
536 cmdK2S.Append( wxT( " --drill-origin" ) );
537 break;
538
540 cmdK2S.Append( wxT( " --grid-origin" ) );
541 break;
542
543 case STEP_ORIGIN_USER:
544 {
545 double xOrg = GetXOrg();
546 double yOrg = GetYOrg();
547
548 if( GetOrgUnitsChoice() == 1 )
549 {
550 // selected reference unit is in inches, and STEP units are mm
551 xOrg *= 25.4;
552 yOrg *= 25.4;
553 }
554
556 cmdK2S.Append( wxString::Format( wxT( " --user-origin=%c%.6fx%.6fmm%c" ),
557 quote, xOrg, yOrg, quote ) );
558 break;
559 }
560
562 {
563 BOX2I bbox = m_parent->GetBoard()->ComputeBoundingBox( true );
564 double xOrg = pcbIUScale.IUTomm( bbox.GetCenter().x );
565 double yOrg = pcbIUScale.IUTomm( bbox.GetCenter().y );
567
568 cmdK2S.Append( wxString::Format( wxT( " --user-origin=%c%.6fx%.6fmm%c" ),
569 quote, xOrg, yOrg, quote ) );
570 break;
571 }
572 }
573
574 {
576 cmdK2S.Append( wxString::Format( wxT( " --min-distance=%c%.3fmm%c" ),
577 quote, tolerance, quote ) );
578 }
579
580 // Output file path.
581 cmdK2S.Append( wxString::Format( wxT( " -f -o %c%s%c" ),
582 dblquote, fn.GetFullPath(), dblquote ) );
583
584
585 // Input file path.
586 cmdK2S.Append( wxString::Format( wxT( " %c%s%c" ), dblquote, m_boardPath, dblquote ) );
587
588 wxLogTrace( traceKiCad2Step, wxT( "export step command: %s" ), cmdK2S );
589
590 DIALOG_EXPORT_STEP_LOG* log = new DIALOG_EXPORT_STEP_LOG( this, cmdK2S );
591 log->ShowModal();
592 Close();
593}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Definition: bitmap.cpp:110
bool ResolveTextVar(wxString *token, int aDepth) const
Definition: board.cpp:424
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1555
const FOOTPRINTS & Footprints() const
Definition: board.h:323
const wxString & GetFileName() const
Definition: board.h:319
const Vec GetCenter() const
Definition: box2.h:220
DO_NOT_SHOW_AGAIN m_DoNotShowAgain
Class DIALOG_EXPORT_STEP_BASE.
wxRadioButton * m_rbDrillAndPlotOrigin
STD_BITMAP_BUTTON * m_browseButton
STEP_ORIGIN_OPTION GetOriginOption()
PCB_EDIT_FRAME * m_parent
void onUpdateXPos(wxUpdateUIEvent &aEvent) override
STEP_ORIGIN_OPTION m_origin
void onExportButton(wxCommandEvent &aEvent) override
DIALOG_EXPORT_STEP(PCB_EDIT_FRAME *aParent, const wxString &aBoardPath)
void onUpdateUnits(wxUpdateUIEvent &aEvent) override
void onUpdateYPos(wxUpdateUIEvent &aEvent) override
void onBrowseClicked(wxCommandEvent &aEvent) override
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:43
bool DoNotShowAgain() const
Definition: kidialog.cpp:59
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: kidialog.cpp:51
int ShowModal() override
Definition: kidialog.cpp:95
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:49
DIALOG_EXPORT_STEP m_ExportStep
PCBNEW_SETTINGS * GetPcbNewSettings() const
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
The main frame for Pcbnew.
void SetLastPath(LAST_PATH_TYPE aType, const wxString &aLastPath)
Set the path of the last file successfully read.
bool doAutoSave() override
Perform auto save when the board has been modified and not saved within the auto save interval.
void OnExportSTEP(wxCommandEvent &event)
Export the current BOARD to a STEP assembly.
wxString GetLastPath(LAST_PATH_TYPE aType)
Get the last path for a particular type.
bool IsContentModified() const override
Get if the current board has been modified but not saved.
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition: pgm_base.cpp:678
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
Definition: project.cpp:320
Represent a set of closed polygons.
void SetBitmap(const wxBitmapBundle &aBmp)
void SetValue(const wxString &aValue) override
Set a new value in evaluator buffer, and display it in the wxTextCtrl.
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:334
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject)
Definition: common.cpp:58
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:186
This file is part of the common library.
bool BuildBoardPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, int aErrorMax, int aChainingEpsilon, OUTLINE_ERROR_HANDLER *aErrorHandler, bool aAllowUseArcsInPolygons)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
#define _(s)
static const std::string BrepFileExtension
static const std::string StepFileAbrvExtension
static const std::string XaoFileExtension
static const std::string GltfBinaryFileExtension
static const std::string AutoSaveFilePrefix
static const std::string StepFileExtension
const wxChar *const traceKiCad2Step
Flag to enable KiCad2Step debug tracing.
This file is part of the common library.
KICOMMON_API double DoubleValueFromString(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Function DoubleValueFromString converts aTextValue to a double.
Definition: eda_units.cpp:572
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1059
see class PGM_BASE
@ LAST_PATH_STEP
Definition: project_file.h:50
std::vector< FAB_LAYER_COLOR > dummy
constexpr double IUTomm(int iu) const
Definition: base_units.h:86
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
wxLogTrace helper definitions.
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition: wx_filename.h:39