KiCad PCB EDA Suite
3d_cache.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) 2015-2016 Cirilo Bernardo <[email protected]>
5 * Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 * Copyright (C) 2022 CERN
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#define GLM_FORCE_RADIANS
27
28#include <mutex>
29#include <utility>
30
31#include <wx/datetime.h>
32#include <wx/dir.h>
33#include <wx/log.h>
34#include <wx/stdpaths.h>
35
36#include <boost/version.hpp>
37
38#if BOOST_VERSION >= 106800
39#include <boost/uuid/detail/sha1.hpp>
40#else
41#include <boost/uuid/sha1.hpp>
42#endif
43
44#include "3d_cache.h"
45#include "3d_info.h"
46#include "3d_plugin_manager.h"
47#include "sg/scenegraph.h"
49
50#include <advanced_config.h>
51#include <common.h> // For ExpandEnvVarSubstitutions
52#include <filename_resolver.h>
53#include <paths.h>
54#include <pgm_base.h>
55#include <project.h>
58#include <wx_filename.h>
59
60
61#define MASK_3D_CACHE "3D_CACHE"
62
63static std::mutex mutex3D_cache;
64static std::mutex mutex3D_cacheManager;
65
66
67static bool isSHA1Same( const unsigned char* shaA, const unsigned char* shaB ) noexcept
68{
69 for( int i = 0; i < 20; ++i )
70 {
71 if( shaA[i] != shaB[i] )
72 return false;
73 }
74
75 return true;
76}
77
78
79static bool checkTag( const char* aTag, void* aPluginMgrPtr )
80{
81 if( nullptr == aTag || nullptr == aPluginMgrPtr )
82 return false;
83
84 S3D_PLUGIN_MANAGER *pp = (S3D_PLUGIN_MANAGER*) aPluginMgrPtr;
85
86 return pp->CheckTag( aTag );
87}
88
89
90static const wxString sha1ToWXString( const unsigned char* aSHA1Sum )
91{
92 unsigned char uc;
93 unsigned char tmp;
94 char sha1[41];
95 int j = 0;
96
97 for( int i = 0; i < 20; ++i )
98 {
99 uc = aSHA1Sum[i];
100 tmp = uc / 16;
101
102 if( tmp > 9 )
103 tmp += 87;
104 else
105 tmp += 48;
106
107 sha1[j++] = tmp;
108 tmp = uc % 16;
109
110 if( tmp > 9 )
111 tmp += 87;
112 else
113 tmp += 48;
114
115 sha1[j++] = tmp;
116 }
117
118 sha1[j] = 0;
119
120 return wxString::FromUTF8Unchecked( sha1 );
121}
122
123
125{
126public:
129
130 void SetSHA1( const unsigned char* aSHA1Sum );
131 const wxString GetCacheBaseName();
132
133 wxDateTime modTime; // file modification time
134 unsigned char sha1sum[20];
135 std::string pluginInfo; // PluginName:Version string
138
139private:
140 // prohibit assignment and default copy constructor
143
144 wxString m_CacheBaseName; // base name of cache file (a SHA1 digest)
145};
146
147
149{
150 sceneData = nullptr;
151 renderData = nullptr;
152 memset( sha1sum, 0, 20 );
153}
154
155
157{
158 delete sceneData;
159
160 if( nullptr != renderData )
162}
163
164
165void S3D_CACHE_ENTRY::SetSHA1( const unsigned char* aSHA1Sum )
166{
167 if( nullptr == aSHA1Sum )
168 {
169 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [BUG] NULL passed for aSHA1Sum" ),
170 __FILE__, __FUNCTION__, __LINE__ );
171
172 return;
173 }
174
175 memcpy( sha1sum, aSHA1Sum, 20 );
176}
177
178
180{
181 if( m_CacheBaseName.empty() )
183
184 return m_CacheBaseName;
185}
186
187
189{
191 m_project = nullptr;
193}
194
195
197{
198 FlushCache();
199
200 delete m_FNResolver;
201 delete m_Plugins;
202}
203
204
205SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePath,
206 S3D_CACHE_ENTRY** aCachePtr )
207{
208 if( aCachePtr )
209 *aCachePtr = nullptr;
210
211 wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile, aBasePath );
212
213 if( full3Dpath.empty() )
214 {
215 // the model cannot be found; we cannot proceed
216 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [3D model] could not find model '%s'\n" ),
217 __FILE__, __FUNCTION__, __LINE__, aModelFile );
218 return nullptr;
219 }
220
221 // check cache if file is already loaded
222 std::lock_guard<std::mutex> lock( mutex3D_cache );
223
224 std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
225 mi = m_CacheMap.find( full3Dpath );
226
227 if( mi != m_CacheMap.end() )
228 {
229 wxFileName fname( full3Dpath );
230
231 if( fname.FileExists() ) // Only check if file exists. If not, it will
232 { // use the same model in cache.
234 wxDateTime fmdate = fname.GetModificationTime();
235
236 if( fmdate != mi->second->modTime )
237 {
238 unsigned char hashSum[20];
239 getSHA1( full3Dpath, hashSum );
240 mi->second->modTime = fmdate;
241
242 if( !isSHA1Same( hashSum, mi->second->sha1sum ) )
243 {
244 mi->second->SetSHA1( hashSum );
245 reload = true;
246 }
247 }
248
249 if( reload )
250 {
251 if( nullptr != mi->second->sceneData )
252 {
253 S3D::DestroyNode( mi->second->sceneData );
254 mi->second->sceneData = nullptr;
255 }
256
257 if( nullptr != mi->second->renderData )
258 S3D::Destroy3DModel( &mi->second->renderData );
259
260 mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath,
261 mi->second->pluginInfo );
262 }
263 }
264
265 if( nullptr != aCachePtr )
266 *aCachePtr = mi->second;
267
268 return mi->second->sceneData;
269 }
270
271 // a cache item does not exist; search the Filename->Cachename map
272 return checkCache( full3Dpath, aCachePtr );
273}
274
275
276SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile, const wxString& aBasePath )
277{
278 return load( aModelFile, aBasePath );
279}
280
281
282SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr )
283{
284 if( aCachePtr )
285 *aCachePtr = nullptr;
286
287 unsigned char sha1sum[20];
289 m_CacheList.push_back( ep );
290 wxFileName fname( aFileName );
291 ep->modTime = fname.GetModificationTime();
292
293 if( !getSHA1( aFileName, sha1sum ) || m_CacheDir.empty() )
294 {
295 // just in case we can't get a hash digest (for example, on access issues)
296 // or we do not have a configured cache file directory, we create an
297 // entry to prevent further attempts at loading the file
298
299 if( m_CacheMap.emplace( aFileName, ep ).second == false )
300 {
301 wxLogTrace( MASK_3D_CACHE,
302 wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
303 __FILE__, __FUNCTION__, __LINE__, aFileName );
304
305 m_CacheList.pop_back();
306 delete ep;
307 }
308 else
309 {
310 if( aCachePtr )
311 *aCachePtr = ep;
312 }
313
314 return nullptr;
315 }
316
317 if( m_CacheMap.emplace( aFileName, ep ).second == false )
318 {
319 wxLogTrace( MASK_3D_CACHE,
320 wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
321 __FILE__, __FUNCTION__, __LINE__, aFileName );
322
323 m_CacheList.pop_back();
324 delete ep;
325 return nullptr;
326 }
327
328 if( aCachePtr )
329 *aCachePtr = ep;
330
331 ep->SetSHA1( sha1sum );
332
333 wxString bname = ep->GetCacheBaseName();
334 wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
335
336 if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && wxFileName::FileExists( cachename )
337 && loadCacheData( ep ) )
338 return ep->sceneData;
339
340 ep->sceneData = m_Plugins->Load3DModel( aFileName, ep->pluginInfo );
341
342 if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && nullptr != ep->sceneData )
343 saveCacheData( ep );
344
345 return ep->sceneData;
346}
347
348
349bool S3D_CACHE::getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum )
350{
351 if( aFileName.empty() )
352 {
353 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [BUG] empty filename" ),
354 __FILE__, __FUNCTION__, __LINE__ );
355
356 return false;
357 }
358
359 if( nullptr == aSHA1Sum )
360 {
361 wxLogTrace( MASK_3D_CACHE, wxT( "%s\n * [BUG] NULL pointer passed for aMD5Sum" ),
362 __FILE__, __FUNCTION__, __LINE__ );
363
364 return false;
365 }
366
367#ifdef _WIN32
368 FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
369#else
370 FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
371#endif
372
373 if( nullptr == fp )
374 return false;
375
376 boost::uuids::detail::sha1 dblock;
377 unsigned char block[4096];
378 size_t bsize = 0;
379
380 while( ( bsize = fread( &block, 1, 4096, fp ) ) > 0 )
381 dblock.process_bytes( block, bsize );
382
383 fclose( fp );
384 unsigned int digest[5];
385 dblock.get_digest( digest );
386
387 // ensure MSB order
388 for( int i = 0; i < 5; ++i )
389 {
390 int idx = i << 2;
391 unsigned int tmp = digest[i];
392 aSHA1Sum[idx+3] = tmp & 0xff;
393 tmp >>= 8;
394 aSHA1Sum[idx+2] = tmp & 0xff;
395 tmp >>= 8;
396 aSHA1Sum[idx+1] = tmp & 0xff;
397 tmp >>= 8;
398 aSHA1Sum[idx] = tmp & 0xff;
399 }
400
401 return true;
402}
403
404
406{
407 wxString bname = aCacheItem->GetCacheBaseName();
408
409 if( bname.empty() )
410 {
411 wxLogTrace( MASK_3D_CACHE,
412 wxT( " * [3D model] cannot load cached model; no file hash available" ) );
413
414 return false;
415 }
416
417 if( m_CacheDir.empty() )
418 {
419 wxLogTrace( MASK_3D_CACHE,
420 wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
421
422 return false;
423 }
424
425 wxString fname = m_CacheDir + bname + wxT( ".3dc" );
426
427 if( !wxFileName::FileExists( fname ) )
428 {
429 wxLogTrace( MASK_3D_CACHE, wxT( " * [3D model] cannot open file '%s'" ), fname.GetData() );
430 return false;
431 }
432
433 if( nullptr != aCacheItem->sceneData )
434 S3D::DestroyNode( (SGNODE*) aCacheItem->sceneData );
435
436 aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8(), m_Plugins, checkTag );
437
438 if( nullptr == aCacheItem->sceneData )
439 return false;
440
441 return true;
442}
443
444
446{
447 if( nullptr == aCacheItem )
448 {
449 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * NULL passed for aCacheItem" ),
450 __FILE__, __FUNCTION__, __LINE__ );
451
452 return false;
453 }
454
455 if( nullptr == aCacheItem->sceneData )
456 {
457 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * aCacheItem has no valid scene data" ),
458 __FILE__, __FUNCTION__, __LINE__ );
459
460 return false;
461 }
462
463 wxString bname = aCacheItem->GetCacheBaseName();
464
465 if( bname.empty() )
466 {
467 wxLogTrace( MASK_3D_CACHE,
468 wxT( " * [3D model] cannot load cached model; no file hash available" ) );
469
470 return false;
471 }
472
473 if( m_CacheDir.empty() )
474 {
475 wxLogTrace( MASK_3D_CACHE,
476 wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
477
478 return false;
479 }
480
481 wxString fname = m_CacheDir + bname + wxT( ".3dc" );
482
483 if( wxFileName::Exists( fname ) )
484 {
485 if( !wxFileName::FileExists( fname ) )
486 {
487 wxLogTrace( MASK_3D_CACHE,
488 wxT( " * [3D model] path exists but is not a regular file '%s'" ), fname );
489
490 return false;
491 }
492 }
493
494 return S3D::WriteCache( fname.ToUTF8(), true, (SGNODE*)aCacheItem->sceneData,
495 aCacheItem->pluginInfo.c_str() );
496}
497
498
499bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
500{
501 if( !m_ConfigDir.empty() )
502 return false;
503
504 wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), wxEmptyString );
505
506 cfgdir.Normalize( FN_NORMALIZE_FLAGS );
507
508 if( !cfgdir.DirExists() )
509 {
510 cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
511
512 if( !cfgdir.DirExists() )
513 {
514 wxLogTrace( MASK_3D_CACHE,
515 wxT( "%s:%s:%d\n * failed to create 3D configuration directory '%s'" ),
516 __FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
517
518 return false;
519 }
520 }
521
522 m_ConfigDir = cfgdir.GetPath();
523
524 // inform the file resolver of the config directory
526 {
527 wxLogTrace( MASK_3D_CACHE,
528 wxT( "%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
529 " * config directory: '%s'" ),
530 __FILE__, __FUNCTION__, __LINE__, m_ConfigDir );
531 }
532
533 // 3D cache data must go to a user's cache directory;
534 // unfortunately wxWidgets doesn't seem to provide
535 // functions to retrieve such a directory.
536 //
537 // 1. OSX: ~/Library/Caches/kicad/3d/
538 // 2. Linux: ${XDG_CACHE_HOME}/kicad/3d ~/.cache/kicad/3d/
539 // 3. MSWin: AppData\Local\kicad\3d
540 wxFileName cacheDir;
541 cacheDir.AssignDir( PATHS::GetUserCachePath() );
542 cacheDir.AppendDir( wxT( "3d" ) );
543
544 if( !cacheDir.DirExists() )
545 {
546 cacheDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
547
548 if( !cacheDir.DirExists() )
549 {
550 wxLogTrace( MASK_3D_CACHE,
551 wxT( "%s:%s:%d\n * failed to create 3D cache directory '%s'" ),
552 __FILE__, __FUNCTION__, __LINE__, cacheDir.GetPath() );
553
554 return false;
555 }
556 }
557
558 m_CacheDir = cacheDir.GetPathWithSep();
559 return true;
560}
561
562
564{
565 m_project = aProject;
566
567 bool hasChanged = false;
568
569 if( m_FNResolver->SetProject( aProject, &hasChanged ) && hasChanged )
570 {
571 m_CacheMap.clear();
572
573 std::list< S3D_CACHE_ENTRY* >::iterator sL = m_CacheList.begin();
574 std::list< S3D_CACHE_ENTRY* >::iterator eL = m_CacheList.end();
575
576 while( sL != eL )
577 {
578 delete *sL;
579 ++sL;
580 }
581
582 m_CacheList.clear();
583
584 return true;
585 }
586
587 return false;
588}
589
590
592{
594}
595
596
598{
599 return m_FNResolver;
600}
601
602
603std::list< wxString > const* S3D_CACHE::GetFileFilters() const
604{
605 return m_Plugins->GetFileFilters();
606}
607
608
609void S3D_CACHE::FlushCache( bool closePlugins )
610{
611 std::list< S3D_CACHE_ENTRY* >::iterator sCL = m_CacheList.begin();
612 std::list< S3D_CACHE_ENTRY* >::iterator eCL = m_CacheList.end();
613
614 while( sCL != eCL )
615 {
616 delete *sCL;
617 ++sCL;
618 }
619
620 m_CacheList.clear();
621 m_CacheMap.clear();
622
623 if( closePlugins )
624 ClosePlugins();
625}
626
627
629{
630 if( m_Plugins )
632}
633
634
635S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName, const wxString& aBasePath )
636{
637 S3D_CACHE_ENTRY* cp = nullptr;
638 SCENEGRAPH* sp = load( aModelFileName, aBasePath,&cp );
639
640 if( !sp )
641 return nullptr;
642
643 if( !cp )
644 {
645 wxLogTrace( MASK_3D_CACHE,
646 wxT( "%s:%s:%d\n * [BUG] model loaded with no associated S3D_CACHE_ENTRY" ),
647 __FILE__, __FUNCTION__, __LINE__ );
648
649 return nullptr;
650 }
651
652 if( cp->renderData )
653 return cp->renderData;
654
655 S3DMODEL* mp = S3D::GetModel( sp );
656 cp->renderData = mp;
657
658 return mp;
659}
660
661void S3D_CACHE::CleanCacheDir( int aNumDaysOld )
662{
663 wxDir dir;
664 wxString fileSpec = wxT( "*.3dc" );
665 wxArrayString fileList; // Holds list of ".3dc" files found in cache directory
666 size_t numFilesFound = 0;
667
668 wxFileName thisFile;
669 wxDateTime lastAccess, thresholdDate;
670 wxDateSpan durationInDays;
671
672 // Calc the threshold date above which we delete cache files
673 durationInDays.SetDays( aNumDaysOld );
674 thresholdDate = wxDateTime::Now() - durationInDays;
675
676 // If the cache directory can be found and opened, then we'll try and clean it up
677 if( dir.Open( m_CacheDir ) )
678 {
679 thisFile.SetPath( m_CacheDir ); // Set the base path to the cache folder
680
681 // Get a list of all the ".3dc" files in the cache directory
682 numFilesFound = dir.GetAllFiles( m_CacheDir, &fileList, fileSpec );
683
684 for( unsigned int i = 0; i < numFilesFound; i++ )
685 {
686 // Completes path to specific file so we can get its "last access" date
687 thisFile.SetFullName( fileList[i] );
688
689 // Only get "last access" time to compare against. Don't need the other 2 timestamps.
690 if( thisFile.GetTimes( &lastAccess, nullptr, nullptr ) )
691 {
692 if( lastAccess.IsEarlierThan( thresholdDate ) )
693 {
694 // This file is older than the threshold so delete it
695 wxRemoveFile( thisFile.GetFullPath() );
696 }
697 }
698 }
699 }
700}
701
702
703void PROJECT::Cleanup3DCache()
704{
705 std::lock_guard<std::mutex> lock( mutex3D_cacheManager );
706
707 // Get the existing cache from the project
708 S3D_CACHE* cache = dynamic_cast<S3D_CACHE*>( GetElem( ELEM_3DCACHE ) );
709
710 if( cache )
711 {
712 // We'll delete ".3dc" cache files older than this many days
713 int clearCacheInterval = 0;
714
715 if( Pgm().GetCommonSettings() )
716 clearCacheInterval = Pgm().GetCommonSettings()->m_System.clear_3d_cache_interval;
717
718 // An interval of zero means the user doesn't want to ever clear the cache
719
720 if( clearCacheInterval > 0 )
721 cache->CleanCacheDir( clearCacheInterval );
722 }
723}
724
725
726S3D_CACHE* PROJECT::Get3DCacheManager( bool aUpdateProjDir )
727{
728 std::lock_guard<std::mutex> lock( mutex3D_cacheManager );
729
730 // Get the existing cache from the project
731 S3D_CACHE* cache = dynamic_cast<S3D_CACHE*>( GetElem( ELEM_3DCACHE ) );
732
733 if( !cache )
734 {
735 // Create a cache if there is not one already
736 cache = new S3D_CACHE();
737
738 wxFileName cfgpath;
739 cfgpath.AssignDir( SETTINGS_MANAGER::GetUserSettingsPath() );
740 cfgpath.AppendDir( wxT( "3d" ) );
741
742 cache->SetProgramBase( &Pgm() );
743 cache->Set3DConfigDir( cfgpath.GetFullPath() );
744
745 SetElem( ELEM_3DCACHE, cache );
746 aUpdateProjDir = true;
747 }
748
749 if( aUpdateProjDir )
750 cache->SetProject( this );
751
752 return cache;
753}
754
755
756FILENAME_RESOLVER* PROJECT::Get3DFilenameResolver()
757{
758 return Get3DCacheManager()->GetResolver();
759}
static bool isSHA1Same(const unsigned char *shaA, const unsigned char *shaB) noexcept
Definition: 3d_cache.cpp:67
static std::mutex mutex3D_cacheManager
Definition: 3d_cache.cpp:64
#define MASK_3D_CACHE
Definition: 3d_cache.cpp:61
static std::mutex mutex3D_cache
Definition: 3d_cache.cpp:63
static const wxString sha1ToWXString(const unsigned char *aSHA1Sum)
Definition: 3d_cache.cpp:90
static bool checkTag(const char *aTag, void *aPluginMgrPtr)
Definition: 3d_cache.cpp:79
defines the basic data associated with a single 3D model.
manages 3D model plugins
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
Provide an extensible class to resolve 3D model paths.
bool Set3DConfigDir(const wxString &aConfigDir)
Set the user's configuration directory for 3D models.
bool SetProject(PROJECT *aProject, bool *flgChanged=nullptr)
Set the current KiCad project directory as the first entry in the model path list.
void SetProgramBase(PGM_BASE *aBase)
Set a pointer to the application's PGM_BASE instance used to extract the local env vars.
wxString ResolvePath(const wxString &aFileName, const wxString &aWorkingPath)
Determines the full path of the given file name.
static wxString GetUserCachePath()
Gets the stock (install) 3d viewer plugins path.
Definition: paths.cpp:321
Container for data for KiCad programs.
Definition: pgm_base.h:95
Container for project specific data.
Definition: project.h:64
virtual _ELEM * GetElem(ELEM_T aIndex)
Get and set the elements for this project.
Definition: project.cpp:284
virtual void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:294
@ ELEM_3DCACHE
Definition: project.h:210
Definition: 3d_cache.cpp:125
void SetSHA1(const unsigned char *aSHA1Sum)
Definition: 3d_cache.cpp:165
S3D_CACHE_ENTRY & operator=(const S3D_CACHE_ENTRY &source)
S3DMODEL * renderData
Definition: 3d_cache.cpp:137
~S3D_CACHE_ENTRY()
Definition: 3d_cache.cpp:156
SCENEGRAPH * sceneData
Definition: 3d_cache.cpp:136
S3D_CACHE_ENTRY(const S3D_CACHE_ENTRY &source)
const wxString GetCacheBaseName()
Definition: 3d_cache.cpp:179
std::string pluginInfo
Definition: 3d_cache.cpp:135
wxString m_CacheBaseName
Definition: 3d_cache.cpp:144
wxDateTime modTime
Definition: 3d_cache.cpp:133
unsigned char sha1sum[20]
Definition: 3d_cache.cpp:134
S3D_CACHE_ENTRY()
Definition: 3d_cache.cpp:148
Cache for storing the 3D shapes.
Definition: 3d_cache.h:53
bool getSHA1(const wxString &aFileName, unsigned char *aSHA1Sum)
Calculate the SHA1 hash of the given file.
Definition: 3d_cache.cpp:349
void SetProgramBase(PGM_BASE *aBase)
Set the filename resolver's pointer to the application's PGM_BASE instance.
Definition: 3d_cache.cpp:591
SCENEGRAPH * load(const wxString &aModelFile, const wxString &aBasePath, S3D_CACHE_ENTRY **aCachePtr=nullptr)
Definition: 3d_cache.cpp:205
wxString m_CacheDir
Definition: 3d_cache.h:181
bool loadCacheData(S3D_CACHE_ENTRY *aCacheItem)
Definition: 3d_cache.cpp:405
virtual ~S3D_CACHE()
Definition: 3d_cache.cpp:196
void FlushCache(bool closePlugins=true)
Free all data in the cache and by default closes all plugins.
Definition: 3d_cache.cpp:609
bool Set3DConfigDir(const wxString &aConfigDir)
Sets the configuration directory to be used by the model manager for storing 3D model manager configu...
Definition: 3d_cache.cpp:499
S3DMODEL * GetModel(const wxString &aModelFileName, const wxString &aBasePath)
Attempt to load the scene data for a model and to translate it into an S3D_MODEL structure for displa...
Definition: 3d_cache.cpp:635
SCENEGRAPH * checkCache(const wxString &aFileName, S3D_CACHE_ENTRY **aCachePtr=nullptr)
Find or create cache entry for file name.
Definition: 3d_cache.cpp:282
PROJECT * m_project
Definition: 3d_cache.h:180
S3D_PLUGIN_MANAGER * m_Plugins
Definition: 3d_cache.h:178
bool saveCacheData(S3D_CACHE_ENTRY *aCacheItem)
Definition: 3d_cache.cpp:445
wxString m_ConfigDir
Definition: 3d_cache.h:182
std::list< wxString > const * GetFileFilters() const
Return the list of file filters retrieved from the plugins.
Definition: 3d_cache.cpp:603
FILENAME_RESOLVER * GetResolver() noexcept
Definition: 3d_cache.cpp:597
std::list< S3D_CACHE_ENTRY * > m_CacheList
cache entries
Definition: 3d_cache.h:171
bool SetProject(PROJECT *aProject)
Set the current project's working directory; this affects the model search path.
Definition: 3d_cache.cpp:563
void CleanCacheDir(int aNumDaysOld)
Delete up old cache files in cache directory.
Definition: 3d_cache.cpp:661
std::map< wxString, S3D_CACHE_ENTRY *, rsort_wxString > m_CacheMap
mapping of file names to cache names and data
Definition: 3d_cache.h:174
SCENEGRAPH * Load(const wxString &aModelFile, const wxString &aBasePath)
Attempt to load the scene data for a model.
Definition: 3d_cache.cpp:276
void ClosePlugins()
Unload plugins to free memory.
Definition: 3d_cache.cpp:628
FILENAME_RESOLVER * m_FNResolver
Definition: 3d_cache.h:176
void ClosePlugins(void)
Iterate through all discovered plugins and closes them to reclaim memory.
SCENEGRAPH * Load3DModel(const wxString &aFileName, std::string &aPluginInfo)
std::list< wxString > const * GetFileFilters(void) const noexcept
Return the list of file filters; this will contain at least the default "All Files (*....
bool CheckTag(const char *aTag)
Check the given tag and returns true if the plugin named in the tag is not loaded or the plugin is lo...
Define the basic data set required to represent a 3D model.
Definition: scenegraph.h:45
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
The base class of all Scene Graph nodes.
Definition: sg_node.h:75
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:299
The common library.
bool m_Skip3DModelMemoryCache
Skip reading/writing 3d model memory caches This ensures 3d models are always reloaded from disk even...
defines the API calls for the manipulation of SG* classes
SGLIB_API SGNODE * ReadCache(const char *aFileName, void *aPluginMgr, bool(*aTagCheck)(const char *, void *))
Function ReadCache reads a binary cache file and creates an SGNODE tree.
Definition: ifsg_api.cpp:221
SGLIB_API bool WriteCache(const char *aFileName, bool overwrite, SGNODE *aNode, const char *aPluginInfo)
Function WriteCache writes the SGNODE tree to a binary cache file.
Definition: ifsg_api.cpp:157
SGLIB_API void DestroyNode(SGNODE *aNode) noexcept
Function DestroyNode deletes the given SG* class node.
Definition: ifsg_api.cpp:149
SGLIB_API S3DMODEL * GetModel(SCENEGRAPH *aNode)
Function GetModel creates an S3DMODEL representation of aNode (raw data, no transforms)
Definition: ifsg_api.cpp:338
SGLIB_API void Destroy3DModel(S3DMODEL **aModel)
Function Destroy3DModel frees memory used by an S3DMODEL structure and sets the pointer to the struct...
Definition: ifsg_api.cpp:403
see class PGM_BASE
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
Store the a model based on meshes and materials.
Definition: c3dmodel.h:91
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition: wx_filename.h:38