25#include <wx/stdpaths.h>
26#include <wx/process.h>
28#include <wx/filedlg.h>
117 { wxID_CANCEL,
_(
"Close" ) } } );
123 SetTitle(
m_job->GetSettingsDialogTitle() );
146 size_t bad_count = 0;
152 if(
model.m_Scale.x != 1.0 ||
model.m_Scale.y != 1.0 ||
model.m_Scale.z != 1.0 )
154 bad_scales.Append( wxS(
"\n") );
155 bad_scales.Append(
model.m_Filename );
164 if( !bad_scales.empty() && !
Pgm().GetCommonSettings()->m_DoNotShowAgain.scaled_3d_models_warning )
166 wxString extendedMsg =
_(
"Non-unity scaled models:" ) + wxT(
"\n" ) + bad_scales;
169 "mechanical export." ),
170 _(
"Model Scale Warning" ), wxOK | wxICON_WARNING );
171 msgDlg.SetExtendedMessage( extendedMsg );
193 if( lastPath.IsEmpty() )
195 wxFileName brdFile(
m_editFrame->GetBoard()->GetFileName() );
196 brdFile.SetExt( wxT(
"step" ) );
197 lastPath = brdFile.GetFullPath();
202 wxString currentVariant =
m_editFrame->GetBoard()->GetCurrentVariant();
204 if( !currentVariant.IsEmpty() )
208 if( idx != wxNOT_FOUND )
221 if(
m_job->m_3dparams.m_UseDrillOrigin )
223 else if(
m_job->m_3dparams.m_UseGridOrigin )
225 else if(
m_job->m_3dparams.m_UseDefinedOrigin )
227 else if(
m_job->m_3dparams.m_UsePcbCenterOrigin )
251 if(
m_job->m_3dparams.m_BoardOutlinesChainingEpsilon > 0.05 )
253 else if(
m_job->m_3dparams.m_BoardOutlinesChainingEpsilon < 0.005 )
259 if(
m_job->m_3dparams.m_ComponentFilter.IsEmpty() )
267 if( !
m_job->m_variant.IsEmpty() )
271 if( idx != wxNOT_FOUND )
278 if( formats.second ==
m_job->m_3dparams.m_Format )
287 wxCommandEvent
dummy;
299 if( ( selection != 0 ) && ( selection != wxNOT_FOUND ) )
310 wxArrayString components;
316 components.push_back(
static_cast<FOOTPRINT*
>( item )->GetReference() );
319 return wxJoin( components,
',' );
325 return wxEmptyString;
332 wxFileName brdFile =
board->GetFileName();
356 wxString
filter =
_(
"STEP files" )
358 +
_(
"Binary glTF files" )
362 +
_(
"BREP (OCCT) files" )
368 +
_(
"Universal 3D files" )
378 wxFileDialog dlg(
this,
_(
"3D Model Output File" ), fn.GetPath(), fn.GetFullName(),
filter, wxFD_SAVE );
382 if( dlg.ShowModal() == wxID_CANCEL )
385 path = dlg.GetPath();
388 fn = wxFileName(
path );
408 if( choices.second == idx )
410 newExt = choices.first;
417 int sepIdx = std::max(
path.Find(
'/',
true ),
path.Find(
'\\',
true ) );
418 int dotIdx =
path.Find(
'.',
true );
420 if( dotIdx == -1 || dotIdx < sepIdx )
421 path <<
'.' << newExt;
423 path =
path.Mid( 0, dotIdx ) <<
'.' << newExt;
447 wxString& aInputPath, std::vector<wxString>& aTempFiles,
448 wxString& aErrorDetail )
450 aErrorDetail = wxEmptyString;
452 if( aBoardPath.IsEmpty() )
453 return _(
"Please save the board before exporting STEP." );
456 if( !aContentModified )
458 if( !wxFileExists( aBoardPath ) )
460 return _(
"Board file not found on disk.\n"
461 "Save the board before exporting STEP." );
464 aInputPath = aBoardPath;
465 return wxEmptyString;
468 wxFileName boardFn( aBoardPath );
470 if( !boardFn.DirExists() )
472 return _(
"The board directory no longer exists.\n"
473 "Save the board to a valid location before exporting STEP." );
478 wxString stemPrefix = boardFn.GetName() + wxS(
"-unsaved-export-" );
479 wxString reserved = wxFileName::CreateTempFileName( boardFn.GetPathWithSep() + stemPrefix );
481 if( reserved.IsEmpty() )
482 return _(
"Failed to reserve a temporary filename for STEP export." );
484 wxFileName stemFn( reserved );
490 aTempFiles.push_back( reserved );
491 wxRemoveFile( reserved );
496 pi->SaveBoard( tempBoardFn.GetFullPath(), *aBoard,
nullptr );
500 aErrorDetail = ioe.
What();
501 return _(
"Failed to save the current board state for export." );
504 aTempFiles.push_back( tempBoardFn.GetFullPath() );
506 wxFileName srcProjectFn = boardFn;
509 if( srcProjectFn.FileExists() )
511 if( !wxCopyFile( srcProjectFn.GetFullPath(), tempProjectFn.GetFullPath(),
true ) )
513 wxRemoveFile( tempBoardFn.GetFullPath() );
514 return _(
"Failed to stage the project file for STEP export." );
517 aTempFiles.push_back( tempProjectFn.GetFullPath() );
520 aInputPath = tempBoardFn.GetFullPath();
521 return wxEmptyString;
532 case 0: tolerance = 0.001;
break;
534 case 1: tolerance = 0.01;
break;
535 case 2: tolerance = 0.1;
break;
541 std::function<bool( wxString* )> textResolver =
542 [&]( wxString* token ) ->
bool
544 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
560 int chainingEpsilon =
pcbIUScale.mmToIU( tolerance );
568 "%.3f mm tolerance.\n"
569 "Run DRC for a full analysis." ),
574 wxFileName fn(
Prj().AbsolutePath(
path ) );
578 msg.Printf(
_(
"File '%s' already exists. Do you want overwrite this file?" ), fn.GetFullPath() );
580 if( wxMessageBox( msg,
_(
"STEP/GLTF Export" ), wxYES_NO | wxICON_QUESTION,
this ) == wxNO )
586 wxFileName appK2S( wxStandardPaths::Get().GetExecutablePath() );
589 if( appK2S.GetPath().Find(
"/Contents/Applications/pcbnew.app/Contents/MacOS" ) != wxNOT_FOUND )
591 appK2S.AppendDir( wxT(
".." ) );
592 appK2S.AppendDir( wxT(
".." ) );
593 appK2S.AppendDir( wxT(
".." ) );
594 appK2S.AppendDir( wxT(
".." ) );
595 appK2S.AppendDir( wxT(
"MacOS" ) );
600 appK2S.RemoveLastDir();
601 appK2S.AppendDir(
"kicad" );
605 appK2S.SetName( wxT(
"kicad-cli" ) );
608 wxString cmdK2S = wxT(
"\"" );
609 cmdK2S.Append( appK2S.GetFullPath() );
610 cmdK2S.Append( wxT(
"\"" ) );
612 cmdK2S.Append( wxT(
" pcb" ) );
613 cmdK2S.Append( wxT(
" export" ) );
615 cmdK2S.Append( wxT(
" " ) );
619 cmdK2S.Append( wxT(
" --no-unspecified" ) );
622 cmdK2S.Append( wxT(
" --no-dnp" ) );
625 cmdK2S.Append( wxT(
" --subst-models" ) );
628 cmdK2S.Append( wxT(
" --no-optimize-step" ) );
631 cmdK2S.Append( wxT(
" --no-board-body" ) );
634 cmdK2S.Append( wxT(
" --no-components" ) );
637 cmdK2S.Append( wxT(
" --include-tracks" ) );
640 cmdK2S.Append( wxT(
" --include-pads" ) );
643 cmdK2S.Append( wxT(
" --include-zones" ) );
646 cmdK2S.Append( wxT(
" --include-inner-copper" ) );
649 cmdK2S.Append( wxT(
" --include-silkscreen" ) );
652 cmdK2S.Append( wxT(
" --include-soldermask" ) );
655 cmdK2S.Append( wxT(
" --fuse-shapes" ) );
658 cmdK2S.Append( wxT(
" --cut-vias-in-body" ) );
661 cmdK2S.Append( wxT(
" --fill-all-vias" ) );
670 if( !selectedVariant.IsEmpty() )
672 cmdK2S.Append( wxString::Format( wxT(
" --variant %c%s%c" ),
673 dblquote, selectedVariant, dblquote ) );
678 cmdK2S.Append( wxString::Format( wxT(
" --net-filter %c%s%c" ),
684 cmdK2S.Append( wxString::Format( wxT(
" --component-filter %c%s%c" ),
690 cmdK2S.Append( wxT(
" --drill-origin" ) );
694 cmdK2S.Append( wxT(
" --grid-origin" ) );
702 cmdK2S.Append( wxString::Format( wxT(
" --user-origin=%c%.6fx%.6fmm%c" ),
703 quote, xOrg, yOrg, quote ) );
712 cmdK2S.Append( wxString::Format( wxT(
" --user-origin=%c%.6fx%.6fmm%c" ),
713 quote, xOrg, yOrg, quote ) );
717 wxFAIL_MSG( wxT(
"Unsupported origin option: how did we get here?" ) );
722 cmdK2S.Append( wxString::Format( wxT(
" --min-distance=%c%.3fmm%c" ),
723 quote, tolerance, quote ) );
727 cmdK2S.Append( wxString::Format( wxT(
" -f -o %c%s%c" ),
728 dblquote, fn.GetFullPath(), dblquote ) );
734 std::vector<wxString> tempFiles;
735 wxString errorDetail;
737 inputPath, tempFiles, errorDetail );
739 if( !error.IsEmpty() )
746 cmdK2S.Append( wxString::Format( wxT(
" %c%s%c" ), dblquote, inputPath, dblquote ) );
748 wxLogTrace(
traceKiCad2Step, wxT(
"export step command: %s" ), cmdK2S );
776 m_job->m_3dparams.m_BoardOutlinesChainingEpsilon = tolerance;
780 m_job->SetStepFormat( *formatChoice );
784 wxASSERT_MSG(
false, wxString::Format(
"Unknown format value %d",
m_choiceFormat->GetSelection() ) );
789 switch(
m_job->m_3dparams.m_Format )
802 m_job->m_3dparams.m_UseDrillOrigin =
false;
803 m_job->m_3dparams.m_UseGridOrigin =
false;
804 m_job->m_3dparams.m_UseDefinedOrigin =
false;
805 m_job->m_3dparams.m_UsePcbCenterOrigin =
false;
813 m_job->m_3dparams.m_UseDrillOrigin =
true;
817 m_job->m_3dparams.m_UseGridOrigin =
true;
821 m_job->m_3dparams.m_UseDefinedOrigin =
true;
828 m_job->m_3dparams.m_UsePcbCenterOrigin =
true;
constexpr EDA_IU_SCALE pcbIUScale
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
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
wxString getComponentFilter() const
Return the component filter implied by the component mode radio buttons.
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 OptOut(wxWindow *aWindow)
Opt out of control state saving.
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.
static bool RunningFromBuildDir()
True when KiCad runs from its build tree or KICAD_RUN_FROM_BUILD_DIR is set.
The main frame for Pcbnew.
@ KICAD_SEXP
S-expression Pcbnew file format.
static PCB_IO * FindPlugin(PCB_FILE_T aFileType)
Return a PCB_IO which the caller can use to import, export, save, or load design documents.
virtual COMMON_SETTINGS * GetCommonSettings() const
Represent a set of closed polygons.
wxString ResolveProjectPath(const wxString &aPath, const PROJECT *aProject, const std::function< bool(wxString *)> *aTextResolver)
Expand a user-entered file path as ExpandPathVariables() does, then anchor a relative result at the p...
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.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
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
bool scaled_3d_models_warning
wxLogTrace helper definitions.
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
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().