Initial jobset creation and running within the CLI and GUI.
Incomplete, just pushing this before feature freeze, much fixing left
This commit is contained in:
@@ -49,6 +49,7 @@
|
||||
#include <filename_resolver.h>
|
||||
#include <core/map_helpers.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <jobs/job_export_pcb_3d.h>
|
||||
|
||||
|
||||
// Maps m_choiceFormat selection to extension (and kicad-cli command)
|
||||
@@ -81,16 +82,33 @@ bool DIALOG_EXPORT_STEP::m_fuseShapes = false;
|
||||
DIALOG_EXPORT_STEP::COMPONENT_MODE DIALOG_EXPORT_STEP::m_componentMode = COMPONENT_MODE::EXPORT_ALL;
|
||||
wxString DIALOG_EXPORT_STEP::m_componentFilter;
|
||||
|
||||
|
||||
DIALOG_EXPORT_STEP::DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aEditFrame, const wxString& aBoardPath ) :
|
||||
DIALOG_EXPORT_STEP_BASE( aEditFrame )
|
||||
DIALOG_EXPORT_STEP( aEditFrame, aEditFrame, aBoardPath )
|
||||
{
|
||||
m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
|
||||
}
|
||||
|
||||
m_editFrame = aEditFrame;
|
||||
m_boardPath = aBoardPath;
|
||||
|
||||
SetupStandardButtons( { { wxID_OK, _( "Export" ) },
|
||||
{ wxID_CANCEL, _( "Close" ) } } );
|
||||
DIALOG_EXPORT_STEP::DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aEditFrame, wxWindow* aParent,
|
||||
const wxString& aBoardPath,
|
||||
JOB_EXPORT_PCB_3D* aJob ) :
|
||||
DIALOG_EXPORT_STEP_BASE( aEditFrame ),
|
||||
m_editFrame( aEditFrame ),
|
||||
m_job( aJob ),
|
||||
m_boardPath( aBoardPath )
|
||||
{
|
||||
if( m_job == nullptr )
|
||||
{
|
||||
m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
|
||||
SetupStandardButtons( { { wxID_OK, _( "Export" ) },
|
||||
{ wxID_CANCEL, _( "Close" ) } } );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_browseButton->Hide();
|
||||
SetupStandardButtons( { { wxID_OK, _( "Save" ) },
|
||||
{ wxID_CANCEL, _( "Close" ) } } );
|
||||
}
|
||||
|
||||
// Build default output file name
|
||||
// (last saved filename in project or built from board filename)
|
||||
@@ -110,62 +128,65 @@ DIALOG_EXPORT_STEP::DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aEditFrame, const wxStri
|
||||
|
||||
SetFocus();
|
||||
|
||||
PCBNEW_SETTINGS* cfg = m_editFrame->GetPcbNewSettings();
|
||||
|
||||
m_origin = static_cast<STEP_ORIGIN_OPTION>( cfg->m_ExportStep.origin_mode );
|
||||
|
||||
switch( m_origin )
|
||||
if( !m_job )
|
||||
{
|
||||
default:
|
||||
case STEP_ORIGIN_PLOT_AXIS: m_rbDrillAndPlotOrigin->SetValue( true ); break;
|
||||
case STEP_ORIGIN_GRID_AXIS: m_rbGridOrigin->SetValue( true ); break;
|
||||
case STEP_ORIGIN_USER: m_rbUserDefinedOrigin->SetValue( true ); break;
|
||||
case STEP_ORIGIN_BOARD_CENTER: m_rbBoardCenterOrigin->SetValue( true ); break;
|
||||
PCBNEW_SETTINGS* cfg = m_editFrame->GetPcbNewSettings();
|
||||
|
||||
m_origin = static_cast<STEP_ORIGIN_OPTION>( cfg->m_ExportStep.origin_mode );
|
||||
|
||||
switch( m_origin )
|
||||
{
|
||||
default:
|
||||
case STEP_ORIGIN_PLOT_AXIS: m_rbDrillAndPlotOrigin->SetValue( true ); break;
|
||||
case STEP_ORIGIN_GRID_AXIS: m_rbGridOrigin->SetValue( true ); break;
|
||||
case STEP_ORIGIN_USER: m_rbUserDefinedOrigin->SetValue( true ); break;
|
||||
case STEP_ORIGIN_BOARD_CENTER: m_rbBoardCenterOrigin->SetValue( true ); break;
|
||||
}
|
||||
|
||||
m_originUnits = cfg->m_ExportStep.origin_units;
|
||||
m_userOriginX = cfg->m_ExportStep.origin_x;
|
||||
m_userOriginY = cfg->m_ExportStep.origin_y;
|
||||
m_noUnspecified = cfg->m_ExportStep.no_unspecified;
|
||||
m_noDNP = cfg->m_ExportStep.no_dnp;
|
||||
|
||||
m_txtNetFilter->SetValue( m_netFilter );
|
||||
m_cbOptimizeStep->SetValue( m_optimizeStep );
|
||||
m_cbExportBody->SetValue( m_exportBoardBody );
|
||||
m_cbExportComponents->SetValue( m_exportComponents );
|
||||
m_cbExportTracks->SetValue( m_exportTracks );
|
||||
m_cbExportPads->SetValue( m_exportPads );
|
||||
m_cbExportZones->SetValue( m_exportZones );
|
||||
m_cbExportInnerCopper->SetValue( m_exportInnerCopper );
|
||||
m_cbExportSilkscreen->SetValue( m_exportSilkscreen );
|
||||
m_cbExportSoldermask->SetValue( m_exportSoldermask );
|
||||
m_cbFuseShapes->SetValue( m_fuseShapes );
|
||||
m_cbRemoveUnspecified->SetValue( m_noUnspecified );
|
||||
m_cbRemoveDNP->SetValue( m_noDNP );
|
||||
m_cbSubstModels->SetValue( cfg->m_ExportStep.replace_models );
|
||||
m_cbOverwriteFile->SetValue( cfg->m_ExportStep.overwrite_file );
|
||||
|
||||
m_txtComponentFilter->SetValue( m_componentFilter );
|
||||
|
||||
switch( m_componentMode )
|
||||
{
|
||||
case COMPONENT_MODE::EXPORT_ALL: m_rbAllComponents->SetValue( true ); break;
|
||||
case COMPONENT_MODE::EXPORT_SELECTED: m_rbOnlySelected->SetValue( true ); break;
|
||||
case COMPONENT_MODE::CUSTOM_FILTER: m_rbFilteredComponents->SetValue( true ); break;
|
||||
}
|
||||
|
||||
// Sync the enabled states
|
||||
wxCommandEvent dummy;
|
||||
DIALOG_EXPORT_STEP::onCbExportComponents( dummy );
|
||||
|
||||
m_STEP_OrgUnitChoice->SetSelection( m_originUnits );
|
||||
wxString tmpStr;
|
||||
tmpStr << m_userOriginX;
|
||||
m_STEP_Xorg->SetValue( tmpStr );
|
||||
tmpStr = wxEmptyString;
|
||||
tmpStr << m_userOriginY;
|
||||
m_STEP_Yorg->SetValue( tmpStr );
|
||||
}
|
||||
|
||||
m_originUnits = cfg->m_ExportStep.origin_units;
|
||||
m_userOriginX = cfg->m_ExportStep.origin_x;
|
||||
m_userOriginY = cfg->m_ExportStep.origin_y;
|
||||
m_noUnspecified = cfg->m_ExportStep.no_unspecified;
|
||||
m_noDNP = cfg->m_ExportStep.no_dnp;
|
||||
|
||||
m_txtNetFilter->SetValue( m_netFilter );
|
||||
m_cbOptimizeStep->SetValue( m_optimizeStep );
|
||||
m_cbExportBody->SetValue( m_exportBoardBody );
|
||||
m_cbExportComponents->SetValue( m_exportComponents );
|
||||
m_cbExportTracks->SetValue( m_exportTracks );
|
||||
m_cbExportPads->SetValue( m_exportPads );
|
||||
m_cbExportZones->SetValue( m_exportZones );
|
||||
m_cbExportInnerCopper->SetValue( m_exportInnerCopper );
|
||||
m_cbExportSilkscreen->SetValue( m_exportSilkscreen );
|
||||
m_cbExportSoldermask->SetValue( m_exportSoldermask );
|
||||
m_cbFuseShapes->SetValue( m_fuseShapes );
|
||||
m_cbRemoveUnspecified->SetValue( m_noUnspecified );
|
||||
m_cbRemoveDNP->SetValue( m_noDNP );
|
||||
m_cbSubstModels->SetValue( cfg->m_ExportStep.replace_models );
|
||||
m_cbOverwriteFile->SetValue( cfg->m_ExportStep.overwrite_file );
|
||||
|
||||
m_txtComponentFilter->SetValue( m_componentFilter );
|
||||
|
||||
switch( m_componentMode )
|
||||
{
|
||||
case COMPONENT_MODE::EXPORT_ALL: m_rbAllComponents->SetValue( true ); break;
|
||||
case COMPONENT_MODE::EXPORT_SELECTED: m_rbOnlySelected->SetValue( true ); break;
|
||||
case COMPONENT_MODE::CUSTOM_FILTER: m_rbFilteredComponents->SetValue( true ); break;
|
||||
}
|
||||
|
||||
// Sync the enabled states
|
||||
wxCommandEvent dummy;
|
||||
DIALOG_EXPORT_STEP::onCbExportComponents( dummy );
|
||||
|
||||
m_STEP_OrgUnitChoice->SetSelection( m_originUnits );
|
||||
wxString tmpStr;
|
||||
tmpStr << m_userOriginX;
|
||||
m_STEP_Xorg->SetValue( tmpStr );
|
||||
tmpStr = wxEmptyString;
|
||||
tmpStr << m_userOriginY;
|
||||
m_STEP_Yorg->SetValue( tmpStr );
|
||||
|
||||
wxString bad_scales;
|
||||
size_t bad_count = 0;
|
||||
|
||||
@@ -424,261 +445,324 @@ void DIALOG_EXPORT_STEP::OnComponentModeChange( wxCommandEvent& event )
|
||||
|
||||
void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
|
||||
{
|
||||
wxString path = m_outputFileName->GetValue();
|
||||
m_editFrame->SetLastPath( LAST_PATH_STEP, path );
|
||||
|
||||
// Build the absolute path of current output directory to preselect it in the file browser.
|
||||
std::function<bool( wxString* )> textResolver =
|
||||
[&]( wxString* token ) -> bool
|
||||
{
|
||||
return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
|
||||
};
|
||||
|
||||
path = ExpandTextVars( path, &textResolver );
|
||||
path = ExpandEnvVarSubstitutions( path, &Prj() );
|
||||
path = Prj().AbsolutePath( path );
|
||||
|
||||
if( path.IsEmpty() )
|
||||
if( !m_job )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "No filename for output file" ) );
|
||||
return;
|
||||
}
|
||||
wxString path = m_outputFileName->GetValue();
|
||||
m_editFrame->SetLastPath( LAST_PATH_STEP, path );
|
||||
|
||||
m_netFilter = m_txtNetFilter->GetValue();
|
||||
m_componentFilter = m_txtComponentFilter->GetValue();
|
||||
// Build the absolute path of current output directory to preselect it in the file browser.
|
||||
std::function<bool( wxString* )> textResolver =
|
||||
[&]( wxString* token ) -> bool
|
||||
{
|
||||
return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
|
||||
};
|
||||
|
||||
if( m_rbAllComponents->GetValue() )
|
||||
m_componentMode = COMPONENT_MODE::EXPORT_ALL;
|
||||
else if( m_rbOnlySelected->GetValue() )
|
||||
m_componentMode = COMPONENT_MODE::EXPORT_SELECTED;
|
||||
else
|
||||
m_componentMode = COMPONENT_MODE::CUSTOM_FILTER;
|
||||
path = ExpandTextVars( path, &textResolver );
|
||||
path = ExpandEnvVarSubstitutions( path, &Prj() );
|
||||
path = Prj().AbsolutePath( path );
|
||||
|
||||
double tolerance; // default value in mm
|
||||
m_toleranceLastChoice = m_choiceTolerance->GetSelection();
|
||||
m_formatLastChoice = m_choiceFormat->GetSelection();
|
||||
m_optimizeStep = m_cbOptimizeStep->GetValue();
|
||||
m_exportBoardBody = m_cbExportBody->GetValue();
|
||||
m_exportComponents = m_cbExportComponents->GetValue();
|
||||
m_exportTracks = m_cbExportTracks->GetValue();
|
||||
m_exportPads = m_cbExportPads->GetValue();
|
||||
m_exportZones = m_cbExportZones->GetValue();
|
||||
m_exportInnerCopper = m_cbExportInnerCopper->GetValue();
|
||||
m_exportSilkscreen = m_cbExportSilkscreen->GetValue();
|
||||
m_exportSoldermask = m_cbExportSoldermask->GetValue();
|
||||
m_fuseShapes = m_cbFuseShapes->GetValue();
|
||||
|
||||
switch( m_choiceTolerance->GetSelection() )
|
||||
{
|
||||
case 0: tolerance = 0.001; break;
|
||||
default:
|
||||
case 1: tolerance = 0.01; break;
|
||||
case 2: tolerance = 0.1; break;
|
||||
}
|
||||
|
||||
SHAPE_POLY_SET outline;
|
||||
wxString msg;
|
||||
|
||||
// Check if the board outline is continuous
|
||||
// max dist from one endPt to next startPt to build a closed shape:
|
||||
int chainingEpsilon = pcbIUScale.mmToIU( tolerance );
|
||||
|
||||
// Arc to segment approx error (not critical here: we do not use the outline shape):
|
||||
int maxError = pcbIUScale.mmToIU( 0.005 );
|
||||
bool success = BuildBoardPolygonOutlines( m_editFrame->GetBoard(), outline, maxError,
|
||||
chainingEpsilon, nullptr );
|
||||
if( !success )
|
||||
{
|
||||
DisplayErrorMessage( this, wxString::Format(
|
||||
_( "Board outline is missing or not closed using %.3f mm tolerance.\n"
|
||||
"Run DRC for a full analysis." ), tolerance ) );
|
||||
return;
|
||||
}
|
||||
|
||||
wxFileName fn( Prj().AbsolutePath( path ) );
|
||||
|
||||
if( fn.FileExists() && !GetOverwriteFile() )
|
||||
{
|
||||
msg.Printf( _( "File '%s' already exists. Do you want overwrite this file?" ),
|
||||
fn.GetFullPath() );
|
||||
|
||||
if( wxMessageBox( msg, _( "STEP/GLTF Export" ), wxYES_NO | wxICON_QUESTION, this ) == wxNO )
|
||||
return;
|
||||
}
|
||||
|
||||
wxFileName appK2S( wxStandardPaths::Get().GetExecutablePath() );
|
||||
#ifdef __WXMAC__
|
||||
// On macOS, we have standalone applications inside the main bundle, so we handle that here:
|
||||
if( appK2S.GetPath().Find( "/Contents/Applications/pcbnew.app/Contents/MacOS" ) != wxNOT_FOUND )
|
||||
{
|
||||
appK2S.AppendDir( wxT( ".." ) );
|
||||
appK2S.AppendDir( wxT( ".." ) );
|
||||
appK2S.AppendDir( wxT( ".." ) );
|
||||
appK2S.AppendDir( wxT( ".." ) );
|
||||
appK2S.AppendDir( wxT( "MacOS" ) );
|
||||
}
|
||||
#else
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
{
|
||||
appK2S.RemoveLastDir();
|
||||
appK2S.AppendDir( "kicad" );
|
||||
}
|
||||
#endif
|
||||
|
||||
appK2S.SetName( wxT( "kicad-cli" ) );
|
||||
appK2S.Normalize( FN_NORMALIZE_FLAGS );
|
||||
|
||||
wxString cmdK2S = wxT( "\"" );
|
||||
cmdK2S.Append( appK2S.GetFullPath() );
|
||||
cmdK2S.Append( wxT( "\"" ) );
|
||||
|
||||
cmdK2S.Append( wxT( " pcb" ) );
|
||||
cmdK2S.Append( wxT( " export" ) );
|
||||
|
||||
cmdK2S.Append( wxT( " " ) );
|
||||
cmdK2S.Append( c_formatCommand[m_choiceFormat->GetSelection()] );
|
||||
|
||||
if( GetNoUnspecifiedOption() )
|
||||
cmdK2S.Append( wxT( " --no-unspecified" ) );
|
||||
|
||||
if( GetNoDNPOption() )
|
||||
cmdK2S.Append( wxT( " --no-dnp" ) );
|
||||
|
||||
if( GetSubstOption() )
|
||||
cmdK2S.Append( wxT( " --subst-models" ) );
|
||||
|
||||
if( !m_optimizeStep )
|
||||
cmdK2S.Append( wxT( " --no-optimize-step" ) );
|
||||
|
||||
if( !m_exportBoardBody )
|
||||
cmdK2S.Append( wxT( " --no-board-body" ) );
|
||||
|
||||
if( !m_exportComponents )
|
||||
cmdK2S.Append( wxT( " --no-components" ) );
|
||||
|
||||
if( m_exportTracks )
|
||||
cmdK2S.Append( wxT( " --include-tracks" ) );
|
||||
|
||||
if( m_exportPads )
|
||||
cmdK2S.Append( wxT( " --include-pads" ) );
|
||||
|
||||
if( m_exportZones )
|
||||
cmdK2S.Append( wxT( " --include-zones" ) );
|
||||
|
||||
if( m_exportInnerCopper )
|
||||
cmdK2S.Append( wxT( " --include-inner-copper" ) );
|
||||
|
||||
if( m_exportSilkscreen )
|
||||
cmdK2S.Append( wxT( " --include-silkscreen" ) );
|
||||
|
||||
if( m_exportSoldermask )
|
||||
cmdK2S.Append( wxT( " --include-soldermask" ) );
|
||||
|
||||
if( m_fuseShapes )
|
||||
cmdK2S.Append( wxT( " --fuse-shapes" ) );
|
||||
|
||||
// Note: for some reason, using \" to insert a quote in a format string, under MacOS
|
||||
// wxString::Format does not work. So use a %c format in string
|
||||
int quote = '\'';
|
||||
int dblquote = '"';
|
||||
|
||||
if( !m_netFilter.empty() )
|
||||
{
|
||||
cmdK2S.Append( wxString::Format( wxT( " --net-filter %c%s%c" ), dblquote, m_netFilter,
|
||||
dblquote ) );
|
||||
}
|
||||
|
||||
switch( m_componentMode )
|
||||
{
|
||||
case COMPONENT_MODE::EXPORT_SELECTED:
|
||||
{
|
||||
wxArrayString components;
|
||||
SELECTION& selection = m_editFrame->GetCurrentSelection();
|
||||
|
||||
std::for_each( selection.begin(), selection.end(),
|
||||
[&components]( EDA_ITEM* item )
|
||||
{
|
||||
if( item->Type() == PCB_FOOTPRINT_T )
|
||||
components.push_back( static_cast<FOOTPRINT*>( item )->GetReference() );
|
||||
} );
|
||||
|
||||
cmdK2S.Append( wxString::Format( wxT( " --component-filter %c%s%c" ), dblquote,
|
||||
wxJoin( components, ',' ), dblquote ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case COMPONENT_MODE::CUSTOM_FILTER:
|
||||
cmdK2S.Append( wxString::Format( wxT( " --component-filter %c%s%c" ), dblquote,
|
||||
m_componentFilter, dblquote ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch( GetOriginOption() )
|
||||
{
|
||||
case STEP_ORIGIN_0:
|
||||
wxFAIL_MSG( wxT( "Unsupported origin option: how did we get here?" ) );
|
||||
break;
|
||||
|
||||
case STEP_ORIGIN_PLOT_AXIS:
|
||||
cmdK2S.Append( wxT( " --drill-origin" ) );
|
||||
break;
|
||||
|
||||
case STEP_ORIGIN_GRID_AXIS:
|
||||
cmdK2S.Append( wxT( " --grid-origin" ) );
|
||||
break;
|
||||
|
||||
case STEP_ORIGIN_USER:
|
||||
{
|
||||
double xOrg = GetXOrg();
|
||||
double yOrg = GetYOrg();
|
||||
|
||||
if( GetOrgUnitsChoice() == 1 )
|
||||
if( path.IsEmpty() )
|
||||
{
|
||||
// selected reference unit is in inches, and STEP units are mm
|
||||
xOrg *= 25.4;
|
||||
yOrg *= 25.4;
|
||||
DisplayErrorMessage( this, _( "No filename for output file" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
LOCALE_IO dummy;
|
||||
cmdK2S.Append( wxString::Format( wxT( " --user-origin=%c%.6fx%.6fmm%c" ),
|
||||
quote, xOrg, yOrg, quote ) );
|
||||
break;
|
||||
}
|
||||
m_netFilter = m_txtNetFilter->GetValue();
|
||||
m_componentFilter = m_txtComponentFilter->GetValue();
|
||||
|
||||
case STEP_ORIGIN_BOARD_CENTER:
|
||||
if( m_rbAllComponents->GetValue() )
|
||||
m_componentMode = COMPONENT_MODE::EXPORT_ALL;
|
||||
else if( m_rbOnlySelected->GetValue() )
|
||||
m_componentMode = COMPONENT_MODE::EXPORT_SELECTED;
|
||||
else
|
||||
m_componentMode = COMPONENT_MODE::CUSTOM_FILTER;
|
||||
|
||||
double tolerance; // default value in mm
|
||||
m_toleranceLastChoice = m_choiceTolerance->GetSelection();
|
||||
m_formatLastChoice = m_choiceFormat->GetSelection();
|
||||
m_optimizeStep = m_cbOptimizeStep->GetValue();
|
||||
m_exportBoardBody = m_cbExportBody->GetValue();
|
||||
m_exportComponents = m_cbExportComponents->GetValue();
|
||||
m_exportTracks = m_cbExportTracks->GetValue();
|
||||
m_exportPads = m_cbExportPads->GetValue();
|
||||
m_exportZones = m_cbExportZones->GetValue();
|
||||
m_exportInnerCopper = m_cbExportInnerCopper->GetValue();
|
||||
m_exportSilkscreen = m_cbExportSilkscreen->GetValue();
|
||||
m_exportSoldermask = m_cbExportSoldermask->GetValue();
|
||||
m_fuseShapes = m_cbFuseShapes->GetValue();
|
||||
|
||||
switch( m_choiceTolerance->GetSelection() )
|
||||
{
|
||||
case 0: tolerance = 0.001; break;
|
||||
default:
|
||||
case 1: tolerance = 0.01; break;
|
||||
case 2: tolerance = 0.1; break;
|
||||
}
|
||||
|
||||
SHAPE_POLY_SET outline;
|
||||
wxString msg;
|
||||
|
||||
// Check if the board outline is continuous
|
||||
// max dist from one endPt to next startPt to build a closed shape:
|
||||
int chainingEpsilon = pcbIUScale.mmToIU( tolerance );
|
||||
|
||||
// Arc to segment approx error (not critical here: we do not use the outline shape):
|
||||
int maxError = pcbIUScale.mmToIU( 0.005 );
|
||||
bool success = BuildBoardPolygonOutlines( m_editFrame->GetBoard(), outline, maxError,
|
||||
chainingEpsilon, nullptr );
|
||||
if( !success )
|
||||
{
|
||||
DisplayErrorMessage( this, wxString::Format(
|
||||
_( "Board outline is missing or not closed using %.3f mm tolerance.\n"
|
||||
"Run DRC for a full analysis." ), tolerance ) );
|
||||
return;
|
||||
}
|
||||
|
||||
wxFileName fn( Prj().AbsolutePath( path ) );
|
||||
|
||||
if( fn.FileExists() && !GetOverwriteFile() )
|
||||
{
|
||||
msg.Printf( _( "File '%s' already exists. Do you want overwrite this file?" ),
|
||||
fn.GetFullPath() );
|
||||
|
||||
if( wxMessageBox( msg, _( "STEP/GLTF Export" ), wxYES_NO | wxICON_QUESTION, this ) == wxNO )
|
||||
return;
|
||||
}
|
||||
|
||||
wxFileName appK2S( wxStandardPaths::Get().GetExecutablePath() );
|
||||
#ifdef __WXMAC__
|
||||
// On macOS, we have standalone applications inside the main bundle, so we handle that here:
|
||||
if( appK2S.GetPath().Find( "/Contents/Applications/pcbnew.app/Contents/MacOS" ) != wxNOT_FOUND )
|
||||
{
|
||||
appK2S.AppendDir( wxT( ".." ) );
|
||||
appK2S.AppendDir( wxT( ".." ) );
|
||||
appK2S.AppendDir( wxT( ".." ) );
|
||||
appK2S.AppendDir( wxT( ".." ) );
|
||||
appK2S.AppendDir( wxT( "MacOS" ) );
|
||||
}
|
||||
#else
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
{
|
||||
appK2S.RemoveLastDir();
|
||||
appK2S.AppendDir( "kicad" );
|
||||
}
|
||||
#endif
|
||||
|
||||
appK2S.SetName( wxT( "kicad-cli" ) );
|
||||
appK2S.Normalize( FN_NORMALIZE_FLAGS );
|
||||
|
||||
wxString cmdK2S = wxT( "\"" );
|
||||
cmdK2S.Append( appK2S.GetFullPath() );
|
||||
cmdK2S.Append( wxT( "\"" ) );
|
||||
|
||||
cmdK2S.Append( wxT( " pcb" ) );
|
||||
cmdK2S.Append( wxT( " export" ) );
|
||||
|
||||
cmdK2S.Append( wxT( " " ) );
|
||||
cmdK2S.Append( c_formatCommand[m_choiceFormat->GetSelection()] );
|
||||
|
||||
if( GetNoUnspecifiedOption() )
|
||||
cmdK2S.Append( wxT( " --no-unspecified" ) );
|
||||
|
||||
if( GetNoDNPOption() )
|
||||
cmdK2S.Append( wxT( " --no-dnp" ) );
|
||||
|
||||
if( GetSubstOption() )
|
||||
cmdK2S.Append( wxT( " --subst-models" ) );
|
||||
|
||||
if( !m_optimizeStep )
|
||||
cmdK2S.Append( wxT( " --no-optimize-step" ) );
|
||||
|
||||
if( !m_exportBoardBody )
|
||||
cmdK2S.Append( wxT( " --no-board-body" ) );
|
||||
|
||||
if( !m_exportComponents )
|
||||
cmdK2S.Append( wxT( " --no-components" ) );
|
||||
|
||||
if( m_exportTracks )
|
||||
cmdK2S.Append( wxT( " --include-tracks" ) );
|
||||
|
||||
if( m_exportPads )
|
||||
cmdK2S.Append( wxT( " --include-pads" ) );
|
||||
|
||||
if( m_exportZones )
|
||||
cmdK2S.Append( wxT( " --include-zones" ) );
|
||||
|
||||
if( m_exportInnerCopper )
|
||||
cmdK2S.Append( wxT( " --include-inner-copper" ) );
|
||||
|
||||
if( m_exportSilkscreen )
|
||||
cmdK2S.Append( wxT( " --include-silkscreen" ) );
|
||||
|
||||
if( m_exportSoldermask )
|
||||
cmdK2S.Append( wxT( " --include-soldermask" ) );
|
||||
|
||||
if( m_fuseShapes )
|
||||
cmdK2S.Append( wxT( " --fuse-shapes" ) );
|
||||
|
||||
// Note: for some reason, using \" to insert a quote in a format string, under MacOS
|
||||
// wxString::Format does not work. So use a %c format in string
|
||||
int quote = '\'';
|
||||
int dblquote = '"';
|
||||
|
||||
if( !m_netFilter.empty() )
|
||||
{
|
||||
cmdK2S.Append( wxString::Format( wxT( " --net-filter %c%s%c" ), dblquote, m_netFilter,
|
||||
dblquote ) );
|
||||
}
|
||||
|
||||
switch( m_componentMode )
|
||||
{
|
||||
case COMPONENT_MODE::EXPORT_SELECTED:
|
||||
{
|
||||
wxArrayString components;
|
||||
SELECTION& selection = m_editFrame->GetCurrentSelection();
|
||||
|
||||
std::for_each( selection.begin(), selection.end(),
|
||||
[&components]( EDA_ITEM* item )
|
||||
{
|
||||
if( item->Type() == PCB_FOOTPRINT_T )
|
||||
components.push_back( static_cast<FOOTPRINT*>( item )->GetReference() );
|
||||
} );
|
||||
|
||||
cmdK2S.Append( wxString::Format( wxT( " --component-filter %c%s%c" ), dblquote,
|
||||
wxJoin( components, ',' ), dblquote ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case COMPONENT_MODE::CUSTOM_FILTER:
|
||||
cmdK2S.Append( wxString::Format( wxT( " --component-filter %c%s%c" ), dblquote,
|
||||
m_componentFilter, dblquote ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch( GetOriginOption() )
|
||||
{
|
||||
case STEP_ORIGIN_0:
|
||||
wxFAIL_MSG( wxT( "Unsupported origin option: how did we get here?" ) );
|
||||
break;
|
||||
|
||||
case STEP_ORIGIN_PLOT_AXIS:
|
||||
cmdK2S.Append( wxT( " --drill-origin" ) );
|
||||
break;
|
||||
|
||||
case STEP_ORIGIN_GRID_AXIS:
|
||||
cmdK2S.Append( wxT( " --grid-origin" ) );
|
||||
break;
|
||||
|
||||
case STEP_ORIGIN_USER:
|
||||
{
|
||||
double xOrg = GetXOrg();
|
||||
double yOrg = GetYOrg();
|
||||
|
||||
if( GetOrgUnitsChoice() == 1 )
|
||||
{
|
||||
// selected reference unit is in inches, and STEP units are mm
|
||||
xOrg *= 25.4;
|
||||
yOrg *= 25.4;
|
||||
}
|
||||
|
||||
LOCALE_IO dummy;
|
||||
cmdK2S.Append( wxString::Format( wxT( " --user-origin=%c%.6fx%.6fmm%c" ),
|
||||
quote, xOrg, yOrg, quote ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case STEP_ORIGIN_BOARD_CENTER:
|
||||
{
|
||||
BOX2I bbox = m_editFrame->GetBoard()->ComputeBoundingBox( true );
|
||||
double xOrg = pcbIUScale.IUTomm( bbox.GetCenter().x );
|
||||
double yOrg = pcbIUScale.IUTomm( bbox.GetCenter().y );
|
||||
LOCALE_IO dummy;
|
||||
|
||||
cmdK2S.Append( wxString::Format( wxT( " --user-origin=%c%.6fx%.6fmm%c" ),
|
||||
quote, xOrg, yOrg, quote ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
LOCALE_IO dummy;
|
||||
cmdK2S.Append( wxString::Format( wxT( " --min-distance=%c%.3fmm%c" ),
|
||||
quote, tolerance, quote ) );
|
||||
}
|
||||
|
||||
// Output file path.
|
||||
cmdK2S.Append( wxString::Format( wxT( " -f -o %c%s%c" ),
|
||||
dblquote, fn.GetFullPath(), dblquote ) );
|
||||
|
||||
|
||||
// Input file path.
|
||||
cmdK2S.Append( wxString::Format( wxT( " %c%s%c" ), dblquote, m_boardPath, dblquote ) );
|
||||
|
||||
wxLogTrace( traceKiCad2Step, wxT( "export step command: %s" ), cmdK2S );
|
||||
|
||||
DIALOG_EXPORT_STEP_LOG* log = new DIALOG_EXPORT_STEP_LOG( this, cmdK2S );
|
||||
log->ShowModal();
|
||||
}
|
||||
else
|
||||
{
|
||||
BOX2I bbox = m_editFrame->GetBoard()->ComputeBoundingBox( true );
|
||||
double xOrg = pcbIUScale.IUTomm( bbox.GetCenter().x );
|
||||
double yOrg = pcbIUScale.IUTomm( bbox.GetCenter().y );
|
||||
LOCALE_IO dummy;
|
||||
m_job->SetOutputPath( m_outputFileName->GetValue() );
|
||||
m_job->m_3dparams.m_NetFilter = m_txtNetFilter->GetValue();
|
||||
m_job->m_3dparams.m_ComponentFilter = m_txtComponentFilter->GetValue();
|
||||
m_job->m_3dparams.m_ExportBoardBody = m_cbExportBody->GetValue();
|
||||
m_job->m_3dparams.m_ExportComponents = m_cbExportComponents->GetValue();
|
||||
m_job->m_3dparams.m_ExportTracksVias = m_cbExportTracks->GetValue();
|
||||
m_job->m_3dparams.m_ExportPads = m_cbExportPads->GetValue();
|
||||
m_job->m_3dparams.m_ExportZones = m_cbExportZones->GetValue();
|
||||
m_job->m_3dparams.m_ExportInnerCopper = m_cbExportInnerCopper->GetValue();
|
||||
m_job->m_3dparams.m_ExportSilkscreen = m_cbExportSilkscreen->GetValue();
|
||||
m_job->m_3dparams.m_ExportSoldermask = m_cbExportSoldermask->GetValue();
|
||||
m_job->m_3dparams.m_FuseShapes = m_cbFuseShapes->GetValue();
|
||||
m_job->m_3dparams.m_OptimizeStep = m_cbOptimizeStep->GetValue();
|
||||
m_job->m_3dparams.m_Format = static_cast<EXPORTER_STEP_PARAMS::FORMAT>( m_choiceFormat->GetSelection() );
|
||||
m_job->m_3dparams.m_Overwrite = m_cbOverwriteFile->GetValue();
|
||||
m_job->m_3dparams.m_IncludeUnspecified = !m_cbRemoveUnspecified->GetValue();
|
||||
m_job->m_3dparams.m_IncludeDNP = !m_cbRemoveDNP->GetValue();
|
||||
m_job->m_3dparams.m_SubstModels = m_cbSubstModels->GetValue();
|
||||
|
||||
switch( GetOriginOption() )
|
||||
{
|
||||
case STEP_ORIGIN_0:
|
||||
break;
|
||||
case STEP_ORIGIN_PLOT_AXIS:
|
||||
m_job->m_3dparams.m_UseDrillOrigin = true;
|
||||
break;
|
||||
case STEP_ORIGIN_GRID_AXIS:
|
||||
m_job->m_3dparams.m_UseGridOrigin = true;
|
||||
break;
|
||||
case STEP_ORIGIN_USER:
|
||||
{
|
||||
double xOrg = GetXOrg();
|
||||
double yOrg = GetYOrg();
|
||||
|
||||
if( GetOrgUnitsChoice() == 1 )
|
||||
{
|
||||
// selected reference unit is in inches, and STEP units are mm
|
||||
xOrg *= 25.4;
|
||||
yOrg *= 25.4;
|
||||
}
|
||||
|
||||
m_job->m_3dparams.m_Origin = VECTOR2D( xOrg, yOrg );
|
||||
break;
|
||||
}
|
||||
|
||||
case STEP_ORIGIN_BOARD_CENTER:
|
||||
{
|
||||
BOX2I bbox = m_editFrame->GetBoard()->ComputeBoundingBox( true );
|
||||
double xOrg = pcbIUScale.IUTomm( bbox.GetCenter().x );
|
||||
double yOrg = pcbIUScale.IUTomm( bbox.GetCenter().y );
|
||||
LOCALE_IO dummy;
|
||||
|
||||
m_job->m_3dparams.m_Origin = VECTOR2D( xOrg, yOrg );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cmdK2S.Append( wxString::Format( wxT( " --user-origin=%c%.6fx%.6fmm%c" ),
|
||||
quote, xOrg, yOrg, quote ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
LOCALE_IO dummy;
|
||||
cmdK2S.Append( wxString::Format( wxT( " --min-distance=%c%.3fmm%c" ),
|
||||
quote, tolerance, quote ) );
|
||||
}
|
||||
|
||||
// Output file path.
|
||||
cmdK2S.Append( wxString::Format( wxT( " -f -o %c%s%c" ),
|
||||
dblquote, fn.GetFullPath(), dblquote ) );
|
||||
|
||||
|
||||
// Input file path.
|
||||
cmdK2S.Append( wxString::Format( wxT( " %c%s%c" ), dblquote, m_boardPath, dblquote ) );
|
||||
|
||||
wxLogTrace( traceKiCad2Step, wxT( "export step command: %s" ), cmdK2S );
|
||||
|
||||
DIALOG_EXPORT_STEP_LOG* log = new DIALOG_EXPORT_STEP_LOG( this, cmdK2S );
|
||||
log->ShowModal();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user