29#include <wx/stdpaths.h>
30#include <wx/process.h>
32#include <wx/filedlg.h>
119 { wxID_CANCEL,
_(
"Close" ) } } );
123 SetTitle(
m_job->GetSettingsDialogTitle() );
142 size_t bad_count = 0;
148 if(
model.m_Scale.x != 1.0 ||
model.m_Scale.y != 1.0 ||
model.m_Scale.z != 1.0 )
150 bad_scales.Append( wxS(
"\n") );
151 bad_scales.Append(
model.m_Filename );
160 if( !bad_scales.empty() && !
Pgm().GetCommonSettings()->m_DoNotShowAgain.scaled_3d_models_warning )
162 wxString extendedMsg =
_(
"Non-unity scaled models:" ) + wxT(
"\n" ) + bad_scales;
165 "mechanical export." ),
166 _(
"Model Scale Warning" ), wxOK | wxICON_WARNING );
167 msgDlg.SetExtendedMessage( extendedMsg );
189 wxFileName brdFile(
m_editFrame->GetBoard()->GetFileName() );
190 brdFile.SetExt( wxT(
"step" ) );
194 wxString currentVariant =
m_editFrame->GetBoard()->GetCurrentVariant();
196 if( !currentVariant.IsEmpty() )
200 if( idx != wxNOT_FOUND )
213 if(
m_job->m_3dparams.m_UseDrillOrigin )
215 else if(
m_job->m_3dparams.m_UseGridOrigin )
217 else if(
m_job->m_3dparams.m_UseDefinedOrigin )
219 else if(
m_job->m_3dparams.m_UsePcbCenterOrigin )
243 if(
m_job->m_3dparams.m_BoardOutlinesChainingEpsilon > 0.05 )
245 else if(
m_job->m_3dparams.m_BoardOutlinesChainingEpsilon < 0.005 )
253 if( !
m_job->m_variant.IsEmpty() )
257 if( idx != wxNOT_FOUND )
264 if( formats.second ==
m_job->m_3dparams.m_Format )
273 wxCommandEvent
dummy;
285 if( ( selection != 0 ) && ( selection != wxNOT_FOUND ) )
295 wxFileName brdFile =
board->GetFileName();
319 wxString
filter =
_(
"STEP files" )
321 +
_(
"Binary glTF files" )
325 +
_(
"BREP (OCCT) files" )
331 +
_(
"Universal 3D files" )
339 wxFileName fn(
Prj().AbsolutePath(
path ) );
341 wxFileDialog dlg(
this,
_(
"3D Model Output File" ), fn.GetPath(), fn.GetFullName(),
filter, wxFD_SAVE );
345 if( dlg.ShowModal() == wxID_CANCEL )
348 path = dlg.GetPath();
351 fn = wxFileName(
path );
371 if( choices.second == idx )
373 newExt = choices.first;
380 int sepIdx = std::max(
path.Find(
'/',
true ),
path.Find(
'\\',
true ) );
381 int dotIdx =
path.Find(
'.',
true );
383 if( dotIdx == -1 || dotIdx < sepIdx )
384 path <<
'.' << newExt;
386 path =
path.Mid( 0, dotIdx ) <<
'.' << newExt;
410 wxString& aInputPath, std::vector<wxString>& aTempFiles,
411 wxString& aErrorDetail )
413 aErrorDetail = wxEmptyString;
415 if( aBoardPath.IsEmpty() )
416 return _(
"Please save the board before exporting STEP." );
419 if( !aContentModified )
421 if( !wxFileExists( aBoardPath ) )
423 return _(
"Board file not found on disk.\n"
424 "Save the board before exporting STEP." );
427 aInputPath = aBoardPath;
428 return wxEmptyString;
431 wxFileName boardFn( aBoardPath );
433 if( !boardFn.DirExists() )
435 return _(
"The board directory no longer exists.\n"
436 "Save the board to a valid location before exporting STEP." );
441 wxString stemPrefix = boardFn.GetName() + wxS(
"-unsaved-export-" );
442 wxString reserved = wxFileName::CreateTempFileName( boardFn.GetPathWithSep() + stemPrefix );
444 if( reserved.IsEmpty() )
445 return _(
"Failed to reserve a temporary filename for STEP export." );
447 wxFileName stemFn( reserved );
453 aTempFiles.push_back( reserved );
454 wxRemoveFile( reserved );
459 pi->SaveBoard( tempBoardFn.GetFullPath(), aBoard,
nullptr );
463 aErrorDetail = ioe.
What();
464 return _(
"Failed to save the current board state for export." );
467 aTempFiles.push_back( tempBoardFn.GetFullPath() );
469 wxFileName srcProjectFn = boardFn;
472 if( srcProjectFn.FileExists() )
474 if( !wxCopyFile( srcProjectFn.GetFullPath(), tempProjectFn.GetFullPath(),
true ) )
476 wxRemoveFile( tempBoardFn.GetFullPath() );
477 return _(
"Failed to stage the project file for STEP export." );
480 aTempFiles.push_back( tempProjectFn.GetFullPath() );
483 aInputPath = tempBoardFn.GetFullPath();
484 return wxEmptyString;
495 case 0: tolerance = 0.001;
break;
497 case 1: tolerance = 0.01;
break;
498 case 2: tolerance = 0.1;
break;
504 std::function<bool( wxString* )> textResolver =
505 [&]( wxString* token ) ->
bool
507 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
525 int chainingEpsilon =
pcbIUScale.mmToIU( tolerance );
533 "%.3f mm tolerance.\n"
534 "Run DRC for a full analysis." ),
539 wxFileName fn(
Prj().AbsolutePath(
path ) );
543 msg.Printf(
_(
"File '%s' already exists. Do you want overwrite this file?" ), fn.GetFullPath() );
545 if( wxMessageBox( msg,
_(
"STEP/GLTF Export" ), wxYES_NO | wxICON_QUESTION,
this ) == wxNO )
549 wxFileName appK2S( wxStandardPaths::Get().GetExecutablePath() );
552 if( appK2S.GetPath().Find(
"/Contents/Applications/pcbnew.app/Contents/MacOS" ) != wxNOT_FOUND )
554 appK2S.AppendDir( wxT(
".." ) );
555 appK2S.AppendDir( wxT(
".." ) );
556 appK2S.AppendDir( wxT(
".." ) );
557 appK2S.AppendDir( wxT(
".." ) );
558 appK2S.AppendDir( wxT(
"MacOS" ) );
561 if( wxGetEnv( wxT(
"KICAD_RUN_FROM_BUILD_DIR" ),
nullptr ) )
563 appK2S.RemoveLastDir();
564 appK2S.AppendDir(
"kicad" );
568 appK2S.SetName( wxT(
"kicad-cli" ) );
571 wxString cmdK2S = wxT(
"\"" );
572 cmdK2S.Append( appK2S.GetFullPath() );
573 cmdK2S.Append( wxT(
"\"" ) );
575 cmdK2S.Append( wxT(
" pcb" ) );
576 cmdK2S.Append( wxT(
" export" ) );
578 cmdK2S.Append( wxT(
" " ) );
582 cmdK2S.Append( wxT(
" --no-unspecified" ) );
585 cmdK2S.Append( wxT(
" --no-dnp" ) );
588 cmdK2S.Append( wxT(
" --subst-models" ) );
591 cmdK2S.Append( wxT(
" --no-optimize-step" ) );
594 cmdK2S.Append( wxT(
" --no-board-body" ) );
597 cmdK2S.Append( wxT(
" --no-components" ) );
600 cmdK2S.Append( wxT(
" --include-tracks" ) );
603 cmdK2S.Append( wxT(
" --include-pads" ) );
606 cmdK2S.Append( wxT(
" --include-zones" ) );
609 cmdK2S.Append( wxT(
" --include-inner-copper" ) );
612 cmdK2S.Append( wxT(
" --include-silkscreen" ) );
615 cmdK2S.Append( wxT(
" --include-soldermask" ) );
618 cmdK2S.Append( wxT(
" --fuse-shapes" ) );
621 cmdK2S.Append( wxT(
" --cut-vias-in-body" ) );
624 cmdK2S.Append( wxT(
" --fill-all-vias" ) );
633 if( !selectedVariant.IsEmpty() )
635 cmdK2S.Append( wxString::Format( wxT(
" --variant %c%s%c" ),
636 dblquote, selectedVariant, dblquote ) );
641 cmdK2S.Append( wxString::Format( wxT(
" --net-filter %c%s%c" ),
647 wxArrayString components;
650 std::for_each( selection.
begin(), selection.
end(),
653 if( item->Type() == PCB_FOOTPRINT_T )
654 components.push_back( static_cast<FOOTPRINT*>( item )->GetReference() );
657 cmdK2S.Append( wxString::Format( wxT(
" --component-filter %c%s%c" ),
658 dblquote, wxJoin( components,
',' ), dblquote ) );
662 cmdK2S.Append( wxString::Format( wxT(
" --component-filter %c%s%c" ),
668 cmdK2S.Append( wxT(
" --drill-origin" ) );
672 cmdK2S.Append( wxT(
" --grid-origin" ) );
680 cmdK2S.Append( wxString::Format( wxT(
" --user-origin=%c%.6fx%.6fmm%c" ),
681 quote, xOrg, yOrg, quote ) );
690 cmdK2S.Append( wxString::Format( wxT(
" --user-origin=%c%.6fx%.6fmm%c" ),
691 quote, xOrg, yOrg, quote ) );
695 wxFAIL_MSG( wxT(
"Unsupported origin option: how did we get here?" ) );
700 cmdK2S.Append( wxString::Format( wxT(
" --min-distance=%c%.3fmm%c" ),
701 quote, tolerance, quote ) );
705 cmdK2S.Append( wxString::Format( wxT(
" -f -o %c%s%c" ),
706 dblquote, fn.GetFullPath(), dblquote ) );
712 std::vector<wxString> tempFiles;
713 wxString errorDetail;
715 inputPath, tempFiles, errorDetail );
717 if( !error.IsEmpty() )
724 cmdK2S.Append( wxString::Format( wxT(
" %c%s%c" ), dblquote, inputPath, dblquote ) );
726 wxLogTrace(
traceKiCad2Step, wxT(
"export step command: %s" ), cmdK2S );
754 m_job->m_3dparams.m_BoardOutlinesChainingEpsilon = tolerance;
758 m_job->SetStepFormat( *formatChoice );
762 wxASSERT_MSG(
false, wxString::Format(
"Unknown format value %d",
m_choiceFormat->GetSelection() ) );
767 switch(
m_job->m_3dparams.m_Format )
780 m_job->m_3dparams.m_UseDrillOrigin =
false;
781 m_job->m_3dparams.m_UseGridOrigin =
false;
782 m_job->m_3dparams.m_UseDefinedOrigin =
false;
783 m_job->m_3dparams.m_UsePcbCenterOrigin =
false;
787 m_job->m_3dparams.m_UseDrillOrigin =
true;
791 m_job->m_3dparams.m_UseGridOrigin =
true;
798 m_job->m_3dparams.m_UseDefinedOrigin =
true;
808 m_job->m_3dparams.m_UsePcbCenterOrigin =
true;
constexpr EDA_IU_SCALE pcbIUScale
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
int ExportSTEP(const TOOL_EVENT &aEvent)
Information pertinent to a Pcbnew printed circuit board.
constexpr const Vec GetCenter() const
DO_NOT_SHOW_AGAIN m_DoNotShowAgain
wxCheckBox * m_cbExportTracks
wxChoice * m_choiceVariant
wxCheckBox * m_cbSubstModels
wxRadioButton * m_rbOnlySelected
wxRadioButton * m_rbGridOrigin
TEXT_CTRL_EVAL * m_originXCtrl
wxStaticText * m_originXUnits
wxStaticText * m_originYUnits
wxCheckBox * m_cbExportBody
wxCheckBox * m_cbRemoveUnspecified
wxCheckBox * m_cbOverwriteFile
wxStaticText * m_originXLabel
wxCheckBox * m_cbRemoveDNP
wxBoxSizer * bSizerSTEPFile
wxCheckBox * m_cbExportComponents
wxCheckBox * m_cbOptimizeStep
wxCheckBox * m_cbFuseShapes
wxRadioButton * m_rbBoardCenterOrigin
wxTextCtrl * m_outputFileName
wxCheckBox * m_cbExportInnerCopper
wxChoice * m_choiceTolerance
wxStaticText * m_originYLabel
wxTextCtrl * m_txtNetFilter
wxCheckBox * m_cbExportSoldermask
wxCheckBox * m_cbExportPads
wxChoice * m_choiceFormat
wxCheckBox * m_cbExportZones
DIALOG_EXPORT_STEP_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Export 3D Model"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
wxRadioButton * m_rbAllComponents
wxRadioButton * m_rbUserDefinedOrigin
wxCheckBox * m_cbExportSilkscreen
wxRadioButton * m_rbFilteredComponents
TEXT_CTRL_EVAL * m_originYCtrl
wxCheckBox * m_cbCutViasInBody
wxRadioButton * m_rbDrillAndPlotOrigin
wxTextCtrl * m_txtComponentFilter
STD_BITMAP_BUTTON * m_browseButton
wxCheckBox * m_cbFillAllVias
void SetTempFilesToCleanup(std::vector< wxString > aPaths)
Register files that should be removed once the subprocess is known to have terminated (or been repare...
void onFormatChoice(wxCommandEvent &event) override
void OnFmtChoiceOptionChanged()
void onCbExportComponents(wxCommandEvent &event) override
PCB_EDIT_FRAME * m_editFrame
void OnComponentModeChange(wxCommandEvent &event) override
DIALOG_EXPORT_STEP(PCB_EDIT_FRAME *aEditFrame, const wxString &aBoardPath)
wxString getSelectedVariant() const
void onUpdateXPos(wxUpdateUIEvent &aEvent) override
JOB_EXPORT_PCB_3D * m_job
static wxString StageBoardForExport(const wxString &aBoardPath, bool aContentModified, BOARD *aBoard, wxString &aInputPath, std::vector< wxString > &aTempFiles, wxString &aErrorDetail)
Resolve the board file to hand to the external 3D/STEP exporter.
bool TransferDataToWindow() override
void onExportButton(wxCommandEvent &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...
A base class for most all the KiCad significant classes used in schematics and boards.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
bool DoNotShowAgain() const
Checks the 'do not show again' setting for the dialog.
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
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.
The main frame for Pcbnew.
@ KICAD_SEXP
S-expression Pcbnew file format.
static PCB_IO * FindPlugin(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
virtual COMMON_SETTINGS * GetCommonSettings() const
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.
Represent a set of closed polygons.
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
bool BuildBoardPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, int aErrorMax, int aChainingEpsilon, bool aInferOutlineIfNecessary, 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...
static const std::map< wxString, int > c_formatExtToChoice
static const std::vector< wxString > c_formatCommand
static const std::map< int, EXPORTER_STEP_PARAMS::FORMAT > c_formatJobCommand
static const std::string BrepFileExtension
static const std::string StepFileAbrvExtension
static const std::string XaoFileExtension
static const std::string GltfBinaryFileExtension
static const std::string ProjectFileExtension
static const std::string U3DFileExtension
static const std::string PdfFileExtension
static const std::string StlFileExtension
static const std::string PlyFileExtension
static const std::string StepFileExtension
static const std::string StepZFileAbrvExtension
static const std::string KiCadPcbFileExtension
const wxChar *const traceKiCad2Step
Flag to enable KiCad2Step debug tracing.
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
std::optional< V > get_opt(const std::map< wxString, V > &aMap, const wxString &aKey)
PGM_BASE & Pgm()
The global program "get" accessor.
std::vector< FAB_LAYER_COLOR > dummy
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
bool scaled_3d_models_warning
wxLogTrace helper definitions.
VECTOR2< double > VECTOR2D
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().