60#include <wx/filedlg.h>
106 wxGridCellAttr* attr =
new wxGridCellAttr;
111 attr =
new wxGridCellAttr;
116 wxT(
"*.*" ),
true,
m_frame->Prj().GetProjectPath(),
117 [
this](
const wxString& aFile ) -> wxString
119 EMBEDDED_FILES::EMBEDDED_FILE* result = m_filesPanel->AddEmbeddedFile( aFile );
123 wxString msg = wxString::Format( _(
"Error adding 3D model" ) );
124 wxMessageBox( msg, _(
"Error" ), wxICON_ERROR | wxOK, this );
135 attr =
new wxGridCellAttr;
136 attr->SetRenderer(
new wxGridCellBoolRenderer() );
138 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
139 m_modelsGrid->SetColAttr(
COL_SHOWN, attr );
140 m_modelsGrid->SetWindowStyleFlag( m_modelsGrid->GetWindowStyle() & ~wxHSCROLL );
146 m_previewPane->SetEmbeddedFilesDelegate( m_filesPanel->GetLocalFiles() );
148 m_LowerSizer3D->Add( m_previewPane, 1, wxEXPAND, 5 );
198 bool hasExtrusion =
m_footprint->HasExtrudedBody();
204 wxString::Format( wxT(
"%.4f" ), body ?
pcbIUScale.IUTomm( body->
m_height ) : 0.0 ) );
224 selection =
static_cast<int>( i );
256 double compHeight = 0.0;
257 double standoff = 0.0;
261 if( compHeight <= 0.0 )
263 wxMessageBox(
_(
"Component height must be greater than zero." ),
_(
"Extruded 3D Body" ),
264 wxOK | wxICON_WARNING,
this );
271 if( standoff >= compHeight )
273 wxMessageBox(
_(
"Standoff height must be less than the overall height." ),
_(
"Extruded 3D Body" ),
274 wxOK | wxICON_WARNING,
this );
310 wxString default_path;
314 default_path.Replace( wxT(
"/" ), wxT(
"\\" ) );
320 wxString origPath, alias, shortPath;
326 origPath =
model.m_Filename;
328 if(
res &&
res->SplitAlias( origPath, alias, shortPath ) )
329 origPath = alias + wxT(
":" ) + shortPath;
353 aModelIdx = std::max( 0, aModelIdx );
354 aModelIdx = std::min( aModelIdx,
m_modelsGrid->GetNumberRows() - 1 );
377 if( !aFilename->empty() )
379 bool hasAlias =
false;
382 aFilename->Replace( wxT(
"\n" ), wxT(
"" ) );
383 aFilename->Replace( wxT(
"\r" ), wxT(
"" ) );
384 aFilename->Replace( wxT(
"\t" ), wxT(
"" ) );
386 res->ValidateFileName( *aFilename, hasAlias );
390 aFilename->insert( 0, wxT(
":" ) );
394 aFilename->Replace( wxT(
"\\" ), wxT(
"/" ) );
413 if( !filename.empty() )
431 m_shapes3D_list[ aEvent.GetRow() ].m_Show = ( showValue == wxT(
"1" ) );
447 wxArrayInt selectedRows =
m_modelsGrid->GetSelectedRows();
448 wxGridCellCoordsArray selectedCells =
m_modelsGrid->GetSelectedCells();
449 wxGridCellCoordsArray blockTopLeft =
m_modelsGrid->GetSelectionBlockTopLeft();
450 wxGridCellCoordsArray blockBottomRight =
m_modelsGrid->GetSelectionBlockBottomRight();
452 for(
unsigned ii = 0; ii < selectedCells.GetCount(); ++ii )
453 selectedRows.Add( selectedCells[ii].GetRow() );
455 if( !blockTopLeft.IsEmpty() && !blockBottomRight.IsEmpty() )
457 for(
int row = blockTopLeft[0].GetRow(); row <= blockBottomRight[0].GetRow(); ++row )
458 selectedRows.Add( row );
461 if( selectedRows.empty() &&
m_modelsGrid->GetGridCursorRow() >= 0 )
464 if( selectedRows.empty() )
470 std::sort( selectedRows.begin(), selectedRows.end() );
472 int nextSelection = selectedRows.front();
481 for(
int ii = selectedRows.size() - 1; ii >= 0; --ii )
483 int row = selectedRows[ii];
500 nextSelection = std::min( nextSelection,
m_modelsGrid->GetNumberRows() - 1 );
530 if( initialpath.IsEmpty() )
533 || initialpath.IsEmpty() )
544 if( tmp > 0 && tmp <= INT_MAX )
553 if( retval != wxID_OK ||
model.m_Filename.empty() )
566 wxString libraryName =
m_footprint->GetFPID().GetLibNickname();
567 wxString footprintBasePath = wxEmptyString;
569 std::optional<LIBRARY_TABLE_ROW*> fpRow =
574 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
575 embeddedFilesStack.push_back(
m_filesPanel->GetLocalFiles() );
576 embeddedFilesStack.push_back(
m_frame->GetBoard()->GetEmbeddedFiles() );
578 wxString fullPath =
res->ResolvePath(
model.m_Filename, footprintBasePath, std::move( embeddedFilesStack ) );
579 wxFileName fname( fullPath );
586 wxString msg = wxString::Format(
_(
"Error adding 3D model" ) );
587 wxMessageBox( msg,
_(
"Error" ), wxICON_ERROR | wxOK,
this );
595 sidx = wxString::Format( wxT(
"%i" ),
filter );
600 wxString filename =
model.m_Filename;
602 if(
res &&
res->SplitAlias( filename, alias, shortPath ) )
603 filename = alias + wxT(
":" ) + shortPath;
607 model.m_Filename.Replace( wxT(
"\\" ), wxT(
"/" ) );
629 [&]() -> std::pair<int, int>
658 if( cellEditor->IsCreated() && cellEditor->GetWindow()->IsShown() )
659 filename = cellEditor->GetValue();
661 cellEditor->DecRef();
672 icon = wxICON_WARNING;
673 errStr =
_(
"No filename entered" );
678 errStr =
_(
"Illegal filename" );
683 errStr =
_(
"File not found" );
688 errStr =
_(
"Unable to open file" );
693 errStr =
_(
"Unknown error" );
704 if( aFilename.empty() )
707 bool hasAlias =
false;
716 wxString libraryName =
m_footprint->GetFPID().GetLibNickname();
717 wxString footprintBasePath = wxEmptyString;
719 std::optional<LIBRARY_TABLE_ROW*> fpRow =
724 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
725 embeddedFilesStack.push_back(
m_filesPanel->GetLocalFiles() );
726 embeddedFilesStack.push_back(
m_frame->GetBoard()->GetEmbeddedFiles() );
728 wxString fullPath = resolv->
ResolvePath( aFilename, footprintBasePath, std::move( embeddedFilesStack ) );
730 if( fullPath.IsEmpty() )
733 if( !wxFileName::IsFileReadable( fullPath ) )
778 wxCommandEvent event( wxCUSTOM_PANEL_SHOWN_EVENT );
780 event.SetInt(
static_cast<int>( predicate ) );
844 double compHeight = 0.0;
845 double standoff = 0.0;
884 double standoff = 0.0;
890 wxMessageBox(
_(
"Component height must be greater than zero." ),
_(
"Export Extruded Body" ),
891 wxOK | wxICON_WARNING,
this );
903 wxMessageBox(
_(
"No extrusion outline could be generated for this footprint." ),
_(
"Export Extruded Body" ),
904 wxOK | wxICON_WARNING,
this );
908 wxString defaultName =
m_footprint->GetReference() + wxT(
"_extruded" );
910 wxFileDialog dlg(
this,
_(
"Export Extruded 3D Body" ), wxEmptyString, defaultName,
911 _(
"STEP files" ) + wxT(
" (*.step)|*.step|" ) +
_(
"GLB files" ) + wxT(
" (*.glb)|*.glb|" )
912 +
_(
"STL files" ) + wxT(
" (*.stl)|*.stl|" ) +
_(
"BREP files" )
913 + wxT(
" (*.brep)|*.brep" ),
914 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
916 if( dlg.ShowModal() == wxID_CANCEL )
919 wxString
path = dlg.GetPath();
920 int filterIdx = dlg.GetFilterIndex();
937 if( !
model.AddExtrudedBody( outline, bottom, standoff, height, origin, colorKey, material,
940 wxMessageBox(
_(
"Failed to create extruded body geometry." ),
_(
"Export Extruded Body" ), wxOK | wxICON_ERROR,
949 model.CreatePCB( boardOutline, origin,
false );
955 case 0: ok =
model.WriteSTEP(
path,
true,
false );
break;
956 case 1: ok =
model.WriteGLTF(
path );
break;
957 case 2: ok =
model.WriteSTL(
path );
break;
958 case 3: ok =
model.WriteBREP(
path );
break;
963 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)
wxString result
Test unit parsing edge cases and error handling.
VECTOR2< double > VECTOR2D