KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_fp_properties_3d_model.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2015 Dick Hollenbeck, [email protected]
6 * Copyright (C) 2008 Wayne Stambaugh <[email protected]>
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
28
29#include <algorithm>
32#include <env_vars.h>
33#include <bitmaps.h>
36#include <widgets/wx_grid.h>
38#include <board.h>
39#include <footprint.h>
44#include "filename_resolver.h"
45#include <pgm_base.h>
46#include <kiplatform/ui.h>
51#include <project_pcb.h>
52
53#include <wx/defs.h>
54#include <wx/msgdlg.h>
55
62
63wxDEFINE_EVENT( wxCUSTOM_PANEL_SHOWN_EVENT, wxCommandEvent );
64
66 FOOTPRINT* aFootprint,
67 DIALOG_SHIM* aDialogParent,
68 PANEL_EMBEDDED_FILES* aFilesPanel,
69 wxWindow* aParent ) :
71 m_parentDialog( aDialogParent ),
72 m_frame( aFrame ),
73 m_footprint( aFootprint ),
74 m_filesPanel( aFilesPanel ),
75 m_inSelect( false )
76{
77 m_splitter1->SetSashPosition( FromDIP( m_splitter1->GetSashPosition() ) );
78 m_splitter1->SetMinimumPaneSize( FromDIP( m_splitter1->GetMinimumPaneSize() ) );
79
80 GRID_TRICKS* trick = new GRID_TRICKS( m_modelsGrid, [this]( wxCommandEvent& aEvent )
81 {
82 OnAdd3DRow( aEvent );
83 } );
85 m_modelsGrid->PushEventHandler( trick );
86 m_modelsGrid->SetupColumnAutosizer( COL_FILENAME );
87
88 // Get the last 3D directory
90
91 if( cfg && cfg->m_LastFootprint3dDir.IsEmpty() )
92 {
93 wxGetEnv( ENV_VAR::GetVersionedEnvVarName( wxS( "3DMODEL_DIR" ) ),
95 }
96
97 // Icon showing warning/error information
98 wxGridCellAttr* attr = new wxGridCellAttr;
99 attr->SetReadOnly();
100 m_modelsGrid->SetColAttr( COL_PROBLEM, attr );
101
102 // Filename
103 attr = new wxGridCellAttr;
104
105 if( cfg )
106 {
108 wxT( "*.*" ), true, m_frame->Prj().GetProjectPath(),
109 [this]( const wxString& aFile ) -> wxString
110 {
111 EMBEDDED_FILES::EMBEDDED_FILE* result = m_filesPanel->AddEmbeddedFile( aFile );
112
113 if( !result )
114 {
115 wxString msg = wxString::Format( _( "Error adding 3D model" ) );
116 wxMessageBox( msg, _( "Error" ), wxICON_ERROR | wxOK, this );
117 return wxString();
118 }
119
120 return result->GetLink();
121 } ) );
122 }
123
124 m_modelsGrid->SetColAttr( COL_FILENAME, attr );
125
126 // Show checkbox
127 attr = new wxGridCellAttr;
128 attr->SetRenderer( new wxGridCellBoolRenderer() );
129 attr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
130 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
131 m_modelsGrid->SetColAttr( COL_SHOWN, attr );
132 m_modelsGrid->SetWindowStyleFlag( m_modelsGrid->GetWindowStyle() & ~wxHSCROLL );
133
135
136 m_previewPane = new PANEL_PREVIEW_3D_MODEL( m_lowerPanel, m_frame, m_footprint, &m_shapes3D_list );
137
138 m_previewPane->SetEmbeddedFilesDelegate( m_filesPanel->GetLocalFiles() );
139
140 m_LowerSizer3D->Add( m_previewPane, 1, wxEXPAND, 5 );
141
142 // Configure button logos
143 m_button3DShapeAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
144 m_button3DShapeBrowse->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
145 m_button3DShapeRemove->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
146
147 m_modelsGrid->Bind( wxEVT_GRID_CELL_CHANGING, &PANEL_FP_PROPERTIES_3D_MODEL::on3DModelCellChanging, this );
148 Bind( wxEVT_SHOW, &PANEL_FP_PROPERTIES_3D_MODEL::onShowEvent, this );
149 m_parentDialog->Bind( wxEVT_ACTIVATE, &PANEL_FP_PROPERTIES_3D_MODEL::onDialogActivateEvent, this );
150}
151
152
154{
155 // Delete the GRID_TRICKS.
156 m_modelsGrid->PopEventHandler( true );
157
158 m_modelsGrid->Unbind( wxEVT_GRID_CELL_CHANGING, &PANEL_FP_PROPERTIES_3D_MODEL::on3DModelCellChanging, this );
159 // Unbind OnShowEvent to prevent unnecessary event handling.
160 Unbind( wxEVT_SHOW, &PANEL_FP_PROPERTIES_3D_MODEL::onShowEvent, this );
161
162 // free the memory used by all models, otherwise models which were
163 // browsed but not used would consume memory
165
166 delete m_previewPane;
167}
168
169
175
176
178{
179 return m_modelsGrid->CommitPendingChanges();
180}
181
182
184{
185 wxString default_path;
186 wxGetEnv( ENV_VAR::GetVersionedEnvVarName( wxS( "3DMODEL_DIR" ) ), &default_path );
187
188#ifdef __WINDOWS__
189 default_path.Replace( wxT( "/" ), wxT( "\\" ) );
190#endif
191
192 m_shapes3D_list.clear();
193 m_modelsGrid->ClearRows();
194
195 wxString origPath, alias, shortPath;
197
198 for( const FP_3DMODEL& model : m_footprint->Models() )
199 {
200 m_shapes3D_list.push_back( model );
201 origPath = model.m_Filename;
202
203 if( res && res->SplitAlias( origPath, alias, shortPath ) )
204 origPath = alias + wxT( ":" ) + shortPath;
205
206 m_modelsGrid->AppendRows( 1 );
207 int row = m_modelsGrid->GetNumberRows() - 1;
208 m_modelsGrid->SetCellValue( row, COL_FILENAME, origPath );
209 m_modelsGrid->SetCellValue( row, COL_SHOWN, model.m_Show ? wxT( "1" ) : wxT( "0" ) );
210
211 // Must be after the filename is set
213 }
214
215 select3DModel( 0 );
216
217 m_previewPane->UpdateDummyFootprint();
218 m_modelsGrid->SetGridWidthsDirty();
219
220 Layout();
221}
222
223
225{
226 m_inSelect = true;
227
228 aModelIdx = std::max( 0, aModelIdx );
229 aModelIdx = std::min( aModelIdx, m_modelsGrid->GetNumberRows() - 1 );
230
231 if( m_modelsGrid->GetNumberRows() )
232 {
233 m_modelsGrid->SelectRow( aModelIdx );
234 m_modelsGrid->SetGridCursor( aModelIdx, COL_FILENAME );
235 }
236
237 m_previewPane->SetSelectedModel( aModelIdx );
238
239 m_inSelect = false;
240}
241
242
244{
245 if( !m_inSelect )
246 select3DModel( aEvent.GetRow() );
247}
248
249
251{
252 if( !aFilename->empty() )
253 {
254 bool hasAlias = false;
256
257 aFilename->Replace( wxT( "\n" ), wxT( "" ) );
258 aFilename->Replace( wxT( "\r" ), wxT( "" ) );
259 aFilename->Replace( wxT( "\t" ), wxT( "" ) );
260
261 res->ValidateFileName( *aFilename, hasAlias );
262
263 // If the user has specified an alias in the name then prepend ':'
264 if( hasAlias )
265 aFilename->insert( 0, wxT( ":" ) );
266
267#ifdef __WINDOWS__
268 // In KiCad files, filenames and paths are stored using Unix notation
269 aFilename->Replace( wxT( "\\" ), wxT( "/" ) );
270#endif
271 }
272}
273
274
276{
277 if( aEvent.GetCol() == COL_FILENAME )
278 updateValidateStatus( aEvent.GetRow() );
279}
280
281
283{
284 if( aEvent.GetCol() == COL_FILENAME )
285 {
286 wxString filename = m_modelsGrid->GetCellValue( aEvent.GetRow(), COL_FILENAME );
287
288 if( !filename.empty() )
289 {
290 cleanupFilename( &filename );
291
292 // Update the grid with the modified filename
293 m_modelsGrid->SetCellValue( aEvent.GetRow(), COL_FILENAME, filename );
294 }
295
296 // Save the filename in the 3D shapes table
297 m_shapes3D_list[ aEvent.GetRow() ].m_Filename = filename;
298
299 // Update the validation status
300 updateValidateStatus( aEvent.GetRow() );
301 }
302 else if( aEvent.GetCol() == COL_SHOWN )
303 {
304 wxString showValue = m_modelsGrid->GetCellValue( aEvent.GetRow(), COL_SHOWN );
305
306 m_shapes3D_list[ aEvent.GetRow() ].m_Show = ( showValue == wxT( "1" ) );
307 }
308
309 m_previewPane->UpdateDummyFootprint();
310 onModify();
311}
312
313
315{
316 if( !m_modelsGrid->CommitPendingChanges() )
317 return;
318
319 if( !m_modelsGrid->GetNumberRows() || m_shapes3D_list.empty() )
320 return;
321
322 wxArrayInt selectedRows = m_modelsGrid->GetSelectedRows();
323 wxGridCellCoordsArray selectedCells = m_modelsGrid->GetSelectedCells();
324 wxGridCellCoordsArray blockTopLeft = m_modelsGrid->GetSelectionBlockTopLeft();
325 wxGridCellCoordsArray blockBottomRight = m_modelsGrid->GetSelectionBlockBottomRight();
326
327 for( unsigned ii = 0; ii < selectedCells.GetCount(); ++ii )
328 selectedRows.Add( selectedCells[ii].GetRow() );
329
330 if( !blockTopLeft.IsEmpty() && !blockBottomRight.IsEmpty() )
331 {
332 for( int row = blockTopLeft[0].GetRow(); row <= blockBottomRight[0].GetRow(); ++row )
333 selectedRows.Add( row );
334 }
335
336 if( selectedRows.empty() && m_modelsGrid->GetGridCursorRow() >= 0 )
337 selectedRows.Add( m_modelsGrid->GetGridCursorRow() );
338
339 if( selectedRows.empty() )
340 {
341 wxBell();
342 return;
343 }
344
345 std::sort( selectedRows.begin(), selectedRows.end() );
346
347 int nextSelection = selectedRows.front();
348 int lastRow = -1;
349
350 // Don't allow selection until we call select3DModel(), below. Otherwise wxWidgets
351 // has a tendency to get its knickers in a knot....
352 m_inSelect = true;
353
354 m_modelsGrid->ClearSelection();
355
356 for( int ii = selectedRows.size() - 1; ii >= 0; --ii )
357 {
358 int row = selectedRows[ii];
359
360 if( row == lastRow )
361 continue;
362
363 lastRow = row;
364
365 if( row < 0 || row >= (int) m_shapes3D_list.size() )
366 continue;
367
368 // Not all files are embedded but this will ignore the ones that are not
369 m_filesPanel->RemoveEmbeddedFile( m_shapes3D_list[row].m_Filename );
370 m_shapes3D_list.erase( m_shapes3D_list.begin() + row );
371 m_modelsGrid->DeleteRows( row );
372 }
373
374 if( m_modelsGrid->GetNumberRows() > 0 )
375 nextSelection = std::min( nextSelection, m_modelsGrid->GetNumberRows() - 1 );
376 else
377 nextSelection = 0;
378
379 select3DModel( nextSelection ); // will clamp index within bounds
380 m_previewPane->UpdateDummyFootprint();
381 m_inSelect = false;
382
383 onModify();
384}
385
386
388{
389 if( !m_modelsGrid->CommitPendingChanges() )
390 return;
391
392 int selected = m_modelsGrid->GetGridCursorRow();
393
394 PROJECT& prj = m_frame->Prj();
398
399 wxString initialpath = prj.GetRString( PROJECT::VIEWER_3D_PATH );
400 wxString sidx = prj.GetRString( PROJECT::VIEWER_3D_FILTER_INDEX );
401 int filter = 0;
402
403 // If the PROJECT::VIEWER_3D_PATH hasn't been set yet, use the 3DMODEL_DIR environment
404 // variable and fall back to the project path if necessary.
405 if( initialpath.IsEmpty() )
406 {
407 if( !wxGetEnv( ENV_VAR::GetVersionedEnvVarName( wxS( "3DMODEL_DIR" ) ), &initialpath )
408 || initialpath.IsEmpty() )
409 {
410 initialpath = prj.GetProjectPath();
411 }
412 }
413
414 if( !sidx.empty() )
415 {
416 long tmp;
417 sidx.ToLong( &tmp );
418
419 if( tmp > 0 && tmp <= INT_MAX )
420 filter = (int) tmp;
421 }
422
423 DIALOG_SELECT_3DMODEL dm( m_parentDialog, cache, &model, initialpath, filter );
424
425 // Use QuasiModal so that Configure3DPaths (and its help window) will work
426 int retval = dm.ShowQuasiModal();
427
428 if( retval != wxID_OK || model.m_Filename.empty() )
429 {
430 if( selected >= 0 )
431 {
432 select3DModel( selected );
433 updateValidateStatus( selected );
434 }
435
436 return;
437 }
438
439 if( dm.IsEmbedded3DModel() )
440 {
441 wxString libraryName = m_footprint->GetFPID().GetLibNickname();
442 wxString footprintBasePath = wxEmptyString;
443
444 std::optional<LIBRARY_TABLE_ROW*> fpRow =
445 PROJECT_PCB::FootprintLibAdapter( &m_frame->Prj() )->GetRow( libraryName );
446 if( fpRow )
447 footprintBasePath = LIBRARY_MANAGER::GetFullURI( *fpRow, true );
448
449 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
450 embeddedFilesStack.push_back( m_filesPanel->GetLocalFiles() );
451 embeddedFilesStack.push_back( m_frame->GetBoard()->GetEmbeddedFiles() );
452
453 wxString fullPath = res->ResolvePath( model.m_Filename, footprintBasePath, std::move( embeddedFilesStack ) );
454 wxFileName fname( fullPath );
455
456 EMBEDDED_FILES::EMBEDDED_FILE* result = m_filesPanel->AddEmbeddedFile( fname.GetFullPath() ); ;
457
458 if( !result )
459 {
460
461 wxString msg = wxString::Format( _( "Error adding 3D model" ) );
462 wxMessageBox( msg, _( "Error" ), wxICON_ERROR | wxOK, this );
463 return;
464 }
465
466 model.m_Filename = result->GetLink();
467 }
468
469 prj.SetRString( PROJECT::VIEWER_3D_PATH, initialpath );
470 sidx = wxString::Format( wxT( "%i" ), filter );
472
473 wxString alias;
474 wxString shortPath;
475 wxString filename = model.m_Filename;
476
477 if( res && res->SplitAlias( filename, alias, shortPath ) )
478 filename = alias + wxT( ":" ) + shortPath;
479
480#ifdef __WINDOWS__
481 // In KiCad files, filenames and paths are stored using Unix notation
482 model.m_Filename.Replace( wxT( "\\" ), wxT( "/" ) );
483#endif
484
485 model.m_Show = true;
486 m_shapes3D_list.push_back( model );
487
488 int idx = m_modelsGrid->GetNumberRows();
489 m_modelsGrid->AppendRows( 1 );
490 m_modelsGrid->SetCellValue( idx, COL_FILENAME, filename );
491 m_modelsGrid->SetCellValue( idx, COL_SHOWN, wxT( "1" ) );
492
493 select3DModel( idx );
495
496 m_previewPane->UpdateDummyFootprint();
497 onModify();
498}
499
500
502{
503 m_modelsGrid->OnAddRow(
504 [&]() -> std::pair<int, int>
505 {
507
508 model.m_Show = true;
509 m_shapes3D_list.push_back( model );
510
511 int row = m_modelsGrid->GetNumberRows();
512 m_modelsGrid->AppendRows( 1 );
513 m_modelsGrid->SetCellValue( row, COL_SHOWN, wxT( "1" ) );
514 m_modelsGrid->SetCellValue( row, COL_PROBLEM, "" );
515
516 select3DModel( row );
518 onModify();
519
520 return { row, COL_FILENAME };
521 } );
522}
523
524
526{
527 int icon = 0;
528 wxString errStr;
529 wxString filename = m_modelsGrid->GetCellValue( aRow, COL_FILENAME );
530
531 if( wxGridCellEditor* cellEditor = m_modelsGrid->GetCellEditor( aRow, COL_FILENAME ) )
532 {
533 if( cellEditor->IsCreated() && cellEditor->GetWindow()->IsShown() )
534 filename = cellEditor->GetValue();
535
536 cellEditor->DecRef();
537 }
538
539 switch( validateModelExists( filename ) )
540 {
542 icon = 0;
543 errStr = "";
544 break;
545
547 icon = wxICON_WARNING;
548 errStr = _( "No filename entered" );
549 break;
550
552 icon = wxICON_ERROR;
553 errStr = _( "Illegal filename" );
554 break;
555
557 icon = wxICON_ERROR;
558 errStr = _( "File not found" );
559 break;
560
562 icon = wxICON_ERROR;
563 errStr = _( "Unable to open file" );
564 break;
565
566 default:
567 icon = wxICON_ERROR;
568 errStr = _( "Unknown error" );
569 break;
570 }
571
572 m_modelsGrid->SetCellValue( aRow, COL_PROBLEM, errStr );
573 m_modelsGrid->SetCellRenderer( aRow, COL_PROBLEM, new GRID_CELL_STATUS_ICON_RENDERER( icon ) );
574}
575
576
578{
579 if( aFilename.empty() )
581
582 bool hasAlias = false;
584
585 if( !resolv )
587
588 if( !resolv->ValidateFileName( aFilename, hasAlias ) )
590
591 wxString libraryName = m_footprint->GetFPID().GetLibNickname();
592 wxString footprintBasePath = wxEmptyString;
593
594 std::optional<LIBRARY_TABLE_ROW*> fpRow =
595 PROJECT_PCB::FootprintLibAdapter( &m_frame->Prj() )->GetRow( libraryName );
596 if( fpRow )
597 footprintBasePath = LIBRARY_MANAGER::GetFullURI( *fpRow, true );
598
599 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
600 embeddedFilesStack.push_back( m_filesPanel->GetLocalFiles() );
601 embeddedFilesStack.push_back( m_frame->GetBoard()->GetEmbeddedFiles() );
602
603 wxString fullPath = resolv->ResolvePath( aFilename, footprintBasePath, std::move( embeddedFilesStack ) );
604
605 if( fullPath.IsEmpty() )
607
608 if( !wxFileName::IsFileReadable( fullPath ) )
610
612}
613
614
615void PANEL_FP_PROPERTIES_3D_MODEL::Cfg3DPath( wxCommandEvent& event )
616{
617 DIALOG_CONFIGURE_PATHS dlg( this );
618
619 if( dlg.ShowQuasiModal() == wxID_OK )
620 m_previewPane->UpdateDummyFootprint();
621}
622
623
624void PANEL_FP_PROPERTIES_3D_MODEL::OnUpdateUI( wxUpdateUIEvent& event )
625{
626 m_button3DShapeRemove->Enable( m_modelsGrid->GetNumberRows() > 0 );
627}
628
629
631{
632 if( DIALOG_SHIM* dlg = dynamic_cast<DIALOG_SHIM*>( wxGetTopLevelParent( this ) ) )
633 dlg->OnModify();
634}
635
636
638{
639 postCustomPanelShownEventWithPredicate( static_cast<int>( aEvent.IsShown() ) );
640 aEvent.Skip();
641}
642
643
645{
646 postCustomPanelShownEventWithPredicate( aEvent.GetActive() && m_previewPane->IsShownOnScreen() );
647 aEvent.Skip();
648}
649
650
652{
653 wxCommandEvent event( wxCUSTOM_PANEL_SHOWN_EVENT );
654 event.SetEventObject( m_previewPane );
655 event.SetInt( static_cast<int>( predicate ) );
656 m_previewPane->ProcessWindowEvent( event );
657}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition dialog_shim.h:68
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.
Definition grid_tricks.h:61
void SetTooltipEnable(int aCol, bool aEnable=true)
Enable the tooltip for a column.
Definition grid_tricks.h:75
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) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
PANEL_FP_PROPERTIES_3D_MODEL_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(778, 286), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
void on3DModelCellChanging(wxGridEvent &aEvent)
void OnUpdateUI(wxUpdateUIEvent &event) override
void Cfg3DPath(wxCommandEvent &event) override
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(PCB_BASE_EDIT_FRAME *aFrame, FOOTPRINT *aFootprint, DIALOG_SHIM *aDialogParent, PANEL_EMBEDDED_FILES *aFilesPanel, wxWindow *aParent)
void postCustomPanelShownEventWithPredicate(bool predicate)
MODEL_VALIDATE_ERRORS validateModelExists(const wxString &aFilename)
void OnAdd3DModel(wxCommandEvent &event) override
void OnAdd3DRow(wxCommandEvent &event) override
std::vector< FP_3DMODEL > m_shapes3D_list
void On3DModelSelected(wxGridEvent &) override
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.
Definition project.h:65
@ VIEWER_3D_FILTER_INDEX
Definition project.h:225
@ VIEWER_3D_PATH
Definition project.h:224
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:177
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...
Definition project.cpp:349
virtual const wxString & GetRString(RSTRING_T aStringId)
Return a "retained string", which is any session and project specific string identified in enum RSTRI...
Definition project.cpp:360
Cache for storing the 3D shapes.
Definition 3d_cache.h:55
void FlushCache(bool closePlugins=true)
Free all data in the cache and by default closes all plugins.
Definition 3d_cache.cpp:525
FILENAME_RESOLVER * GetResolver() noexcept
Definition 3d_cache.cpp:513
#define _(s)
Declaration of the eda_3d_viewer class.
Functions related to environment variables, including help functions.
KICOMMON_API wxString GetVersionedEnvVarName(const wxString &aBaseName)
Construct a versioned environment variable based on this KiCad major version.
Definition env_vars.cpp:77
wxDEFINE_EVENT(wxCUSTOM_PANEL_SHOWN_EVENT, wxCommandEvent)
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
T * GetAppSettings(const char *aFilename)
KIBIS_MODEL * model
VECTOR3I res
wxString result
Test unit parsing edge cases and error handling.