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>
40#include <fp_lib_table.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 Bind( wxEVT_SHOW, &PANEL_FP_PROPERTIES_3D_MODEL::onShowEvent, this );
148 m_parentDialog->Bind( wxEVT_ACTIVATE, &PANEL_FP_PROPERTIES_3D_MODEL::onDialogActivateEvent, this );
149}
150
151
153{
154 // Delete the GRID_TRICKS.
155 m_modelsGrid->PopEventHandler( true );
156
157 // Unbind OnShowEvent to prevent unnecessary event handling.
158 Unbind( wxEVT_SHOW, &PANEL_FP_PROPERTIES_3D_MODEL::onShowEvent, this );
159
160 // free the memory used by all models, otherwise models which were
161 // browsed but not used would consume memory
163
164 delete m_previewPane;
165}
166
167
173
174
176{
177 return m_modelsGrid->CommitPendingChanges();
178}
179
180
182{
183 wxString default_path;
184 wxGetEnv( ENV_VAR::GetVersionedEnvVarName( wxS( "3DMODEL_DIR" ) ), &default_path );
185
186#ifdef __WINDOWS__
187 default_path.Replace( wxT( "/" ), wxT( "\\" ) );
188#endif
189
190 m_shapes3D_list.clear();
191 m_modelsGrid->ClearRows();
192
193 wxString origPath, alias, shortPath;
195
196 for( const FP_3DMODEL& model : m_footprint->Models() )
197 {
198 m_shapes3D_list.push_back( model );
199 origPath = model.m_Filename;
200
201 if( res && res->SplitAlias( origPath, alias, shortPath ) )
202 origPath = alias + wxT( ":" ) + shortPath;
203
204 m_modelsGrid->AppendRows( 1 );
205 int row = m_modelsGrid->GetNumberRows() - 1;
206 m_modelsGrid->SetCellValue( row, COL_FILENAME, origPath );
207 m_modelsGrid->SetCellValue( row, COL_SHOWN, model.m_Show ? wxT( "1" ) : wxT( "0" ) );
208
209 // Must be after the filename is set
211 }
212
213 select3DModel( 0 );
214
215 m_previewPane->UpdateDummyFootprint();
216 m_modelsGrid->SetGridWidthsDirty();
217
218 Layout();
219}
220
221
223{
224 m_inSelect = true;
225
226 aModelIdx = std::max( 0, aModelIdx );
227 aModelIdx = std::min( aModelIdx, m_modelsGrid->GetNumberRows() - 1 );
228
229 if( m_modelsGrid->GetNumberRows() )
230 {
231 m_modelsGrid->SelectRow( aModelIdx );
232 m_modelsGrid->SetGridCursor( aModelIdx, COL_FILENAME );
233 }
234
235 m_previewPane->SetSelectedModel( aModelIdx );
236
237 m_inSelect = false;
238}
239
240
242{
243 if( !m_inSelect )
244 select3DModel( aEvent.GetRow() );
245}
246
247
249{
250 if( aEvent.GetCol() == COL_FILENAME )
251 {
252 bool hasAlias = false;
254 wxString filename = m_modelsGrid->GetCellValue( aEvent.GetRow(), COL_FILENAME );
255
256 // Perform cleanup and validation on the filename if it isn't empty
257 if( !filename.empty() )
258 {
259 filename.Replace( wxT( "\n" ), wxT( "" ) );
260 filename.Replace( wxT( "\r" ), wxT( "" ) );
261 filename.Replace( wxT( "\t" ), wxT( "" ) );
262
263 res->ValidateFileName( filename, hasAlias );
264
265 // If the user has specified an alias in the name then prepend ':'
266 if( hasAlias )
267 filename.insert( 0, wxT( ":" ) );
268
269#ifdef __WINDOWS__
270 // In KiCad files, filenames and paths are stored using Unix notation
271 filename.Replace( wxT( "\\" ), wxT( "/" ) );
272#endif
273
274 // Update the grid with the modified filename
275 m_modelsGrid->SetCellValue( aEvent.GetRow(), COL_FILENAME, filename );
276 }
277
278 // Save the filename in the 3D shapes table
279 m_shapes3D_list[ aEvent.GetRow() ].m_Filename = filename;
280
281 // Update the validation status
282 updateValidateStatus( aEvent.GetRow() );
283 }
284 else if( aEvent.GetCol() == COL_SHOWN )
285 {
286 wxString showValue = m_modelsGrid->GetCellValue( aEvent.GetRow(), COL_SHOWN );
287
288 m_shapes3D_list[ aEvent.GetRow() ].m_Show = ( showValue == wxT( "1" ) );
289 }
290
291 m_previewPane->UpdateDummyFootprint();
292 onModify();
293}
294
295
297{
298 if( !m_modelsGrid->CommitPendingChanges() )
299 return;
300
301 if( !m_modelsGrid->GetNumberRows() || m_shapes3D_list.empty() )
302 return;
303
304 wxArrayInt selectedRows = m_modelsGrid->GetSelectedRows();
305 wxGridCellCoordsArray selectedCells = m_modelsGrid->GetSelectedCells();
306 wxGridCellCoordsArray blockTopLeft = m_modelsGrid->GetSelectionBlockTopLeft();
307 wxGridCellCoordsArray blockBottomRight = m_modelsGrid->GetSelectionBlockBottomRight();
308
309 for( unsigned ii = 0; ii < selectedCells.GetCount(); ++ii )
310 selectedRows.Add( selectedCells[ii].GetRow() );
311
312 if( !blockTopLeft.IsEmpty() && !blockBottomRight.IsEmpty() )
313 {
314 for( int row = blockTopLeft[0].GetRow(); row <= blockBottomRight[0].GetRow(); ++row )
315 selectedRows.Add( row );
316 }
317
318 if( selectedRows.empty() && m_modelsGrid->GetGridCursorRow() >= 0 )
319 selectedRows.Add( m_modelsGrid->GetGridCursorRow() );
320
321 if( selectedRows.empty() )
322 {
323 wxBell();
324 return;
325 }
326
327 std::sort( selectedRows.begin(), selectedRows.end() );
328
329 int nextSelection = selectedRows.front();
330 int lastRow = -1;
331
332 // Don't allow selection until we call select3DModel(), below. Otherwise wxWidgets
333 // has a tendency to get its knickers in a knot....
334 m_inSelect = true;
335
336 m_modelsGrid->ClearSelection();
337
338 for( int ii = selectedRows.size() - 1; ii >= 0; --ii )
339 {
340 int row = selectedRows[ii];
341
342 if( row == lastRow )
343 continue;
344
345 lastRow = row;
346
347 if( row < 0 || row >= (int) m_shapes3D_list.size() )
348 continue;
349
350 // Not all files are embedded but this will ignore the ones that are not
351 m_filesPanel->RemoveEmbeddedFile( m_shapes3D_list[row].m_Filename );
352 m_shapes3D_list.erase( m_shapes3D_list.begin() + row );
353 m_modelsGrid->DeleteRows( row );
354 }
355
356 if( m_modelsGrid->GetNumberRows() > 0 )
357 nextSelection = std::min( nextSelection, m_modelsGrid->GetNumberRows() - 1 );
358 else
359 nextSelection = 0;
360
361 select3DModel( nextSelection ); // will clamp index within bounds
362 m_previewPane->UpdateDummyFootprint();
363 m_inSelect = false;
364
365 onModify();
366}
367
368
370{
371 if( !m_modelsGrid->CommitPendingChanges() )
372 return;
373
374 int selected = m_modelsGrid->GetGridCursorRow();
375
376 PROJECT& prj = m_frame->Prj();
377 FP_3DMODEL model;
380
381 wxString initialpath = prj.GetRString( PROJECT::VIEWER_3D_PATH );
382 wxString sidx = prj.GetRString( PROJECT::VIEWER_3D_FILTER_INDEX );
383 int filter = 0;
384
385 // If the PROJECT::VIEWER_3D_PATH hasn't been set yet, use the 3DMODEL_DIR environment
386 // variable and fall back to the project path if necessary.
387 if( initialpath.IsEmpty() )
388 {
389 if( !wxGetEnv( ENV_VAR::GetVersionedEnvVarName( wxS( "3DMODEL_DIR" ) ), &initialpath )
390 || initialpath.IsEmpty() )
391 {
392 initialpath = prj.GetProjectPath();
393 }
394 }
395
396 if( !sidx.empty() )
397 {
398 long tmp;
399 sidx.ToLong( &tmp );
400
401 if( tmp > 0 && tmp <= INT_MAX )
402 filter = (int) tmp;
403 }
404
405 DIALOG_SELECT_3DMODEL dm( m_parentDialog, cache, &model, initialpath, filter );
406
407 // Use QuasiModal so that Configure3DPaths (and its help window) will work
408 int retval = dm.ShowQuasiModal();
409
410 if( retval != wxID_OK || model.m_Filename.empty() )
411 {
412 if( selected >= 0 )
413 {
414 select3DModel( selected );
415 updateValidateStatus( selected );
416 }
417
418 return;
419 }
420
421 if( dm.IsEmbedded3DModel() )
422 {
423 wxString libraryName = m_footprint->GetFPID().GetLibNickname();
424 const FP_LIB_TABLE_ROW* fpRow = nullptr;
425
426 wxString footprintBasePath = wxEmptyString;
427
428 try
429 {
430 fpRow = PROJECT_PCB::PcbFootprintLibs( &m_frame->Prj() )->FindRow( libraryName, false );
431
432 if( fpRow )
433 footprintBasePath = fpRow->GetFullURI( true );
434 }
435 catch( ... )
436 {
437 // if libraryName is not found in table, do nothing
438 }
439
440 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
441 embeddedFilesStack.push_back( m_filesPanel->GetLocalFiles() );
442 embeddedFilesStack.push_back( m_frame->GetBoard()->GetEmbeddedFiles() );
443
444 wxString fullPath = res->ResolvePath( model.m_Filename, footprintBasePath, std::move( embeddedFilesStack ) );
445 wxFileName fname( fullPath );
446
447 EMBEDDED_FILES::EMBEDDED_FILE* result = m_filesPanel->AddEmbeddedFile( fname.GetFullPath() ); ;
448
449 if( !result )
450 {
451
452 wxString msg = wxString::Format( _( "Error adding 3D model" ) );
453 wxMessageBox( msg, _( "Error" ), wxICON_ERROR | wxOK, this );
454 return;
455 }
456
457 model.m_Filename = result->GetLink();
458 }
459
460 prj.SetRString( PROJECT::VIEWER_3D_PATH, initialpath );
461 sidx = wxString::Format( wxT( "%i" ), filter );
463
464 wxString alias;
465 wxString shortPath;
466 wxString filename = model.m_Filename;
467
468 if( res && res->SplitAlias( filename, alias, shortPath ) )
469 filename = alias + wxT( ":" ) + shortPath;
470
471#ifdef __WINDOWS__
472 // In KiCad files, filenames and paths are stored using Unix notation
473 model.m_Filename.Replace( wxT( "\\" ), wxT( "/" ) );
474#endif
475
476 model.m_Show = true;
477 m_shapes3D_list.push_back( model );
478
479 int idx = m_modelsGrid->GetNumberRows();
480 m_modelsGrid->AppendRows( 1 );
481 m_modelsGrid->SetCellValue( idx, COL_FILENAME, filename );
482 m_modelsGrid->SetCellValue( idx, COL_SHOWN, wxT( "1" ) );
483
484 select3DModel( idx );
486
487 m_previewPane->UpdateDummyFootprint();
488 onModify();
489}
490
491
493{
494 m_modelsGrid->OnAddRow(
495 [&]() -> std::pair<int, int>
496 {
497 FP_3DMODEL model;
498
499 model.m_Show = true;
500 m_shapes3D_list.push_back( model );
501
502 int row = m_modelsGrid->GetNumberRows();
503 m_modelsGrid->AppendRows( 1 );
504 m_modelsGrid->SetCellValue( row, COL_SHOWN, wxT( "1" ) );
505 m_modelsGrid->SetCellValue( row, COL_PROBLEM, "" );
506
507 select3DModel( row );
509 onModify();
510
511 return { row, COL_FILENAME };
512 } );
513}
514
515
517{
518 int icon = 0;
519 wxString errStr;
520
521 switch( validateModelExists( m_modelsGrid->GetCellValue( aRow, COL_FILENAME) ) )
522 {
524 icon = 0;
525 errStr = "";
526 break;
527
529 icon = wxICON_WARNING;
530 errStr = _( "No filename entered" );
531 break;
532
534 icon = wxICON_ERROR;
535 errStr = _( "Illegal filename" );
536 break;
537
539 icon = wxICON_ERROR;
540 errStr = _( "File not found" );
541 break;
542
544 icon = wxICON_ERROR;
545 errStr = _( "Unable to open file" );
546 break;
547
548 default:
549 icon = wxICON_ERROR;
550 errStr = _( "Unknown error" );
551 break;
552 }
553
554 m_modelsGrid->SetCellValue( aRow, COL_PROBLEM, errStr );
555 m_modelsGrid->SetCellRenderer( aRow, COL_PROBLEM, new GRID_CELL_STATUS_ICON_RENDERER( icon ) );
556}
557
558
560{
561 if( aFilename.empty() )
563
564 bool hasAlias = false;
566
567 if( !resolv )
569
570 if( !resolv->ValidateFileName( aFilename, hasAlias ) )
572
573 wxString libraryName = m_footprint->GetFPID().GetLibNickname();
574 const FP_LIB_TABLE_ROW* fpRow = nullptr;
575
576 try
577 {
578 fpRow = PROJECT_PCB::PcbFootprintLibs( &m_frame->Prj() )->FindRow( libraryName, false );
579 }
580 catch( ... )
581 {
582 // if libraryName is not found in table, do nothing
583 }
584
585 wxString footprintBasePath = wxEmptyString;
586
587 if( fpRow )
588 footprintBasePath = fpRow->GetFullURI( true );
589
590 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
591 embeddedFilesStack.push_back( m_filesPanel->GetLocalFiles() );
592 embeddedFilesStack.push_back( m_frame->GetBoard()->GetEmbeddedFiles() );
593
594 wxString fullPath = resolv->ResolvePath( aFilename, footprintBasePath, std::move( embeddedFilesStack ) );
595
596 if( fullPath.IsEmpty() )
598
599 if( !wxFileName::IsFileReadable( fullPath ) )
601
603}
604
605
606void PANEL_FP_PROPERTIES_3D_MODEL::Cfg3DPath( wxCommandEvent& event )
607{
608 DIALOG_CONFIGURE_PATHS dlg( this );
609
610 if( dlg.ShowQuasiModal() == wxID_OK )
611 m_previewPane->UpdateDummyFootprint();
612}
613
614
615void PANEL_FP_PROPERTIES_3D_MODEL::OnUpdateUI( wxUpdateUIEvent& event )
616{
617 m_button3DShapeRemove->Enable( m_modelsGrid->GetNumberRows() > 0 );
618}
619
620
622{
623 if( DIALOG_SHIM* dlg = dynamic_cast<DIALOG_SHIM*>( wxGetTopLevelParent( this ) ) )
624 dlg->OnModify();
625}
626
627
629{
630 postCustomPanelShownEventWithPredicate( static_cast<int>( aEvent.IsShown() ) );
631 aEvent.Skip();
632}
633
634
636{
637 postCustomPanelShownEventWithPredicate( aEvent.GetActive() && m_previewPane->IsShownOnScreen() );
638 aEvent.Skip();
639}
640
641
643{
644 wxCommandEvent event( wxCUSTOM_PANEL_SHOWN_EVENT );
645 event.SetEventObject( m_previewPane );
646 event.SetInt( static_cast<int>( predicate ) );
647 m_previewPane->ProcessWindowEvent( event );
648}
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.
wxString m_Filename
The 3D shape filename in 3D library.
Definition footprint.h:121
bool m_Show
Include model in rendering.
Definition footprint.h:122
Hold a record identifying a library accessed by the appropriate footprint library #PLUGIN object in t...
const FP_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an FP_LIB_TABLE_ROW if aNickName is found in this table or in any chained fall back table frag...
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
const wxString GetFullURI(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 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 FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
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.
Container for project specific data.
Definition project.h:65
@ VIEWER_3D_FILTER_INDEX
Definition project.h:226
@ VIEWER_3D_PATH
Definition project.h:225
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:162
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:334
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:345
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.
Definition pgm_base.cpp:913
see class PGM_BASE
T * GetAppSettings(const char *aFilename)
VECTOR3I res
wxString result
Test unit parsing edge cases and error handling.