56#include <wx/filedlg.h>
102 wxGridCellAttr* attr =
new wxGridCellAttr;
107 attr =
new wxGridCellAttr;
112 wxT(
"*.*" ),
true,
m_frame->Prj().GetProjectPath(),
113 [
this](
const wxString& aFile ) -> wxString
115 EMBEDDED_FILES::EMBEDDED_FILE* result = m_filesPanel->AddEmbeddedFile( aFile );
119 wxString msg = wxString::Format( _(
"Error adding 3D model" ) );
120 wxMessageBox( msg, _(
"Error" ), wxICON_ERROR | wxOK, this );
131 attr =
new wxGridCellAttr;
132 attr->SetRenderer(
new wxGridCellBoolRenderer() );
134 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
135 m_modelsGrid->SetColAttr(
COL_SHOWN, attr );
136 m_modelsGrid->SetWindowStyleFlag( m_modelsGrid->GetWindowStyle() & ~wxHSCROLL );
142 m_previewPane->SetEmbeddedFilesDelegate( m_filesPanel->GetLocalFiles() );
144 m_LowerSizer3D->Add( m_previewPane, 1, wxEXPAND, 5 );
194 bool hasExtrusion =
m_footprint->HasExtrudedBody();
200 wxString::Format( wxT(
"%.4f" ), body ?
pcbIUScale.IUTomm( body->
m_height ) : 0.0 ) );
220 selection =
static_cast<int>( i );
244 GetSizer()->Fit(
this );
257 double compHeight = 0.0;
258 double standoff = 0.0;
262 if( compHeight <= 0.0 )
264 wxMessageBox(
_(
"Component height must be greater than zero." ),
_(
"Extruded 3D Body" ),
265 wxOK | wxICON_WARNING,
this );
272 if( standoff >= compHeight )
274 wxMessageBox(
_(
"Standoff height must be less than the overall height." ),
_(
"Extruded 3D Body" ),
275 wxOK | wxICON_WARNING,
this );
311 wxString default_path;
315 default_path.Replace( wxT(
"/" ), wxT(
"\\" ) );
321 wxString origPath, alias, shortPath;
327 origPath =
model.m_Filename;
329 if(
res &&
res->SplitAlias( origPath, alias, shortPath ) )
330 origPath = alias + wxT(
":" ) + shortPath;
354 aModelIdx = std::max( 0, aModelIdx );
355 aModelIdx = std::min( aModelIdx,
m_modelsGrid->GetNumberRows() - 1 );
378 if( !aFilename->empty() )
380 bool hasAlias =
false;
383 aFilename->Replace( wxT(
"\n" ), wxT(
"" ) );
384 aFilename->Replace( wxT(
"\r" ), wxT(
"" ) );
385 aFilename->Replace( wxT(
"\t" ), wxT(
"" ) );
387 res->ValidateFileName( *aFilename, hasAlias );
391 aFilename->insert( 0, wxT(
":" ) );
395 aFilename->Replace( wxT(
"\\" ), wxT(
"/" ) );
414 if( !filename.empty() )
432 m_shapes3D_list[ aEvent.GetRow() ].m_Show = ( showValue == wxT(
"1" ) );
448 wxArrayInt selectedRows =
m_modelsGrid->GetSelectedRows();
449 wxGridCellCoordsArray selectedCells =
m_modelsGrid->GetSelectedCells();
450 wxGridCellCoordsArray blockTopLeft =
m_modelsGrid->GetSelectionBlockTopLeft();
451 wxGridCellCoordsArray blockBottomRight =
m_modelsGrid->GetSelectionBlockBottomRight();
453 for(
unsigned ii = 0; ii < selectedCells.GetCount(); ++ii )
454 selectedRows.Add( selectedCells[ii].GetRow() );
456 if( !blockTopLeft.IsEmpty() && !blockBottomRight.IsEmpty() )
458 for(
int row = blockTopLeft[0].GetRow(); row <= blockBottomRight[0].GetRow(); ++row )
459 selectedRows.Add( row );
462 if( selectedRows.empty() &&
m_modelsGrid->GetGridCursorRow() >= 0 )
465 if( selectedRows.empty() )
471 std::sort( selectedRows.begin(), selectedRows.end() );
473 int nextSelection = selectedRows.front();
482 for(
int ii = selectedRows.size() - 1; ii >= 0; --ii )
484 int row = selectedRows[ii];
501 nextSelection = std::min( nextSelection,
m_modelsGrid->GetNumberRows() - 1 );
531 if( initialpath.IsEmpty() )
534 || initialpath.IsEmpty() )
545 if( tmp > 0 && tmp <= INT_MAX )
554 if( retval != wxID_OK ||
model.m_Filename.empty() )
567 wxString libraryName =
m_footprint->GetFPID().GetLibNickname();
568 wxString footprintBasePath = wxEmptyString;
570 std::optional<LIBRARY_TABLE_ROW*> fpRow =
575 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
576 embeddedFilesStack.push_back(
m_filesPanel->GetLocalFiles() );
577 embeddedFilesStack.push_back(
m_frame->GetBoard()->GetEmbeddedFiles() );
579 wxString fullPath =
res->ResolvePath(
model.m_Filename, footprintBasePath, std::move( embeddedFilesStack ) );
580 wxFileName fname( fullPath );
587 wxString msg = wxString::Format(
_(
"Error adding 3D model" ) );
588 wxMessageBox( msg,
_(
"Error" ), wxICON_ERROR | wxOK,
this );
596 sidx = wxString::Format( wxT(
"%i" ),
filter );
601 wxString filename =
model.m_Filename;
603 if(
res &&
res->SplitAlias( filename, alias, shortPath ) )
604 filename = alias + wxT(
":" ) + shortPath;
608 model.m_Filename.Replace( wxT(
"\\" ), wxT(
"/" ) );
630 [&]() -> std::pair<int, int>
659 if( cellEditor->IsCreated() && cellEditor->GetWindow()->IsShown() )
660 filename = cellEditor->GetValue();
662 cellEditor->DecRef();
673 icon = wxICON_WARNING;
674 errStr =
_(
"No filename entered" );
679 errStr =
_(
"Illegal filename" );
684 errStr =
_(
"File not found" );
689 errStr =
_(
"Unable to open file" );
694 errStr =
_(
"Unknown error" );
705 if( aFilename.empty() )
708 bool hasAlias =
false;
717 wxString libraryName =
m_footprint->GetFPID().GetLibNickname();
718 wxString footprintBasePath = wxEmptyString;
720 std::optional<LIBRARY_TABLE_ROW*> fpRow =
725 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
726 embeddedFilesStack.push_back(
m_filesPanel->GetLocalFiles() );
727 embeddedFilesStack.push_back(
m_frame->GetBoard()->GetEmbeddedFiles() );
729 wxString fullPath = resolv->
ResolvePath( aFilename, footprintBasePath, std::move( embeddedFilesStack ) );
731 if( fullPath.IsEmpty() )
734 if( !wxFileName::IsFileReadable( fullPath ) )
779 wxCommandEvent event( wxCUSTOM_PANEL_SHOWN_EVENT );
781 event.SetInt(
static_cast<int>( predicate ) );
845 double compHeight = 0.0;
846 double standoff = 0.0;
885 double standoff = 0.0;
891 wxMessageBox(
_(
"Component height must be greater than zero." ),
_(
"Export Extruded Body" ),
892 wxOK | wxICON_WARNING,
this );
904 wxMessageBox(
_(
"No extrusion outline could be generated for this footprint." ),
_(
"Export Extruded Body" ),
905 wxOK | wxICON_WARNING,
this );
909 wxString defaultName =
m_footprint->GetReference() + wxT(
"_extruded" );
911 wxFileDialog dlg(
this,
_(
"Export Extruded 3D Body" ), wxEmptyString, defaultName,
912 _(
"STEP files" ) + wxT(
" (*.step)|*.step|" ) +
_(
"GLB files" ) + wxT(
" (*.glb)|*.glb|" )
913 +
_(
"STL files" ) + wxT(
" (*.stl)|*.stl|" ) +
_(
"BREP files" )
914 + wxT(
" (*.brep)|*.brep" ),
915 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
917 if( dlg.ShowModal() == wxID_CANCEL )
920 wxString
path = dlg.GetPath();
921 int filterIdx = dlg.GetFilterIndex();
938 if( !
model.AddExtrudedBody( outline, bottom, standoff, height, origin, colorKey, material,
941 wxMessageBox(
_(
"Failed to create extruded body geometry." ),
_(
"Export Extruded Body" ), wxOK | wxICON_ERROR,
950 model.CreatePCB( boardOutline, origin,
false );
956 case 0: ok =
model.WriteSTEP(
path,
true,
false );
break;
957 case 1: ok =
model.WriteGLTF(
path );
break;
958 case 2: ok =
model.WriteSTL(
path );
break;
959 case 3: ok =
model.WriteBREP(
path );
break;
964 wxMessageBox(
_(
"Failed to write file." ),
_(
"Export Extruded Body" ), wxOK | wxICON_ERROR,
this );
bool GetExtrusionOutline(const FOOTPRINT *aFootprint, SHAPE_POLY_SET &aOutline, PCB_LAYER_ID aLayerOverride)
Get the extrusion outline polygon for a footprint in board coordinates.
constexpr EDA_IU_SCALE pcbIUScale
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
bool IsEmbedded3DModel() const
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
static KIGFX::COLOR4D GetDefaultColor(EXTRUSION_MATERIAL aMaterial)
static uint32_t PackColorKey(const KIGFX::COLOR4D &aColor)
EXTRUSION_MATERIAL m_material
Provide an extensible class to resolve 3D model paths.
bool ValidateFileName(const wxString &aFileName, bool &hasAlias) const
Return true if the given path is a valid aliased relative path.
wxString ResolvePath(const wxString &aFileName, const wxString &aWorkingPath, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack)
Determine the full path of the given file name.
void SetProgramBase(PGM_BASE *aBase)
Set a pointer to the application's PGM_BASE instance used to extract the local env vars.
Editor for wxGrid cells that adds a file/folder browser to the grid input field.
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
void SetTooltipEnable(int aCol, bool aEnable=true)
Enable the tooltip for a column.
A color representation with 4 components: red, green, blue, alpha.
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
std::optional< LIBRARY_TABLE_ROW * > GetRow(const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
Like LIBRARY_MANAGER::GetRow but filtered to the LIBRARY_TABLE_TYPE of this adapter.
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false)
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
A singleton reporter that reports to nowhere.
wxCheckBox * m_enableExtrusionCheckbox
wxCheckBox * m_showExtrusionCheckbox
wxSplitterWindow * m_splitter1
wxTextCtrl * m_componentHeightCtrl
wxChoice * m_extrusionLayerChoice
wxTextCtrl * m_standoffHeightCtrl
STD_BITMAP_BUTTON * m_button3DShapeRemove
wxChoice * m_extrusionMaterialChoice
wxButton * m_buttonExportExtruded
PANEL_FP_PROPERTIES_3D_MODEL_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(778, 420), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
COLOR_SWATCH * m_extrusionColorSwatch
void on3DModelCellChanging(wxGridEvent &aEvent)
void OnUpdateUI(wxUpdateUIEvent &event) override
void Cfg3DPath(wxCommandEvent &event) override
void OnEnableExtrusion(wxCommandEvent &event) override
bool m_userSetExtrusionColor
void updateExtrusionControls()
void OnRemove3DModel(wxCommandEvent &event) override
virtual void onShowEvent(wxShowEvent &aEvent)
void On3DModelCellChanged(wxGridEvent &aEvent) override
virtual void onDialogActivateEvent(wxActivateEvent &aEvent)
~PANEL_FP_PROPERTIES_3D_MODEL() override
PCB_BASE_EDIT_FRAME * m_frame
void ReloadModelsFromFootprint()
DIALOG_SHIM * m_parentDialog
std::vector< PCB_LAYER_ID > m_extrusionLayers
bool TransferDataToWindow() override
PANEL_PREVIEW_3D_MODEL * m_previewPane
void updateExtrusionPreview()
void cleanupFilename(wxString *aFilename)
PANEL_FP_PROPERTIES_3D_MODEL(PCB_BASE_EDIT_FRAME *aFrame, FOOTPRINT *aFootprint, DIALOG_SHIM *aDialogParent, PANEL_EMBEDDED_FILES *aFilesPanel, wxWindow *aParent)
void postCustomPanelShownEventWithPredicate(bool predicate)
void OnExportExtrudedModel(wxCommandEvent &event) override
void updateValidateStatus(int aRow)
bool TransferDataFromWindow() override
MODEL_VALIDATE_ERRORS validateModelExists(const wxString &aFilename)
void OnAdd3DModel(wxCommandEvent &event) override
void OnAdd3DRow(wxCommandEvent &event) override
void onExtrusionColorChanged(wxCommandEvent &event)
void onExtrusionControlChanged(wxCommandEvent &event)
PANEL_EMBEDDED_FILES * m_filesPanel
std::vector< FP_3DMODEL > m_shapes3D_list
void onExtrusionMaterialChanged(wxCommandEvent &event)
void On3DModelSelected(wxGridEvent &) override
void select3DModel(int aModelIdx)
wxString m_LastFootprint3dDir
Common, abstract interface for edit frames.
static S3D_CACHE * Get3DCacheManager(PROJECT *aProject, bool updateProjDir=false)
Return a pointer to an instance of the 3D cache manager.
static FILENAME_RESOLVER * Get3DFilenameResolver(PROJECT *aProject)
Accessor for 3D path resolver.
static FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(PROJECT *aProject)
Container for project specific data.
virtual const wxString GetProjectPath() const
Return the full path of the project.
virtual void SetRString(RSTRING_T aStringId, const wxString &aString)
Store a "retained string", which is any session and project specific string identified in enum RSTRIN...
virtual const wxString & GetRString(RSTRING_T aStringId)
Return a "retained string", which is any session and project specific string identified in enum RSTRI...
Cache for storing the 3D shapes.
void FlushCache(bool closePlugins=true)
Free all data in the cache and by default closes all plugins.
FILENAME_RESOLVER * GetResolver() noexcept
Represent a set of closed polygons.
int OutlineCount() const
Return the number of outlines in the set.
Declaration of the eda_3d_viewer class.
Functions related to environment variables, including help functions.
PCB_LAYER_ID
A quick note on layer IDs:
KICOMMON_API wxString GetVersionedEnvVarName(const wxString &aBaseName)
Construct a versioned environment variable based on this KiCad major version.
wxDEFINE_EVENT(wxCUSTOM_PANEL_SHOWN_EVENT, wxCommandEvent)
PGM_BASE & Pgm()
The global program "get" accessor.
T * GetAppSettings(const char *aFilename)
IbisParser parser & reporter
wxString result
Test unit parsing edge cases and error handling.
VECTOR2< double > VECTOR2D