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