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 <cirilo.bernardo@gmail.com>
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, "%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, "%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, "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'",
311  __FILE__, __FUNCTION__, __LINE__, aFileName );
312 
313  m_CacheList.pop_back();
314  delete ep;
315  }
316  else
317  {
318  if( aCachePtr )
319  *aCachePtr = ep;
320  }
321 
322  return nullptr;
323  }
324 
325  if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
326  ( aFileName, ep ) ).second == false )
327  {
328  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'",
329  __FILE__, __FUNCTION__, __LINE__, aFileName );
330 
331  m_CacheList.pop_back();
332  delete ep;
333  return nullptr;
334  }
335 
336  if( aCachePtr )
337  *aCachePtr = ep;
338 
339  ep->SetSHA1( sha1sum );
340 
341  wxString bname = ep->GetCacheBaseName();
342  wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
343 
344  if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && wxFileName::FileExists( cachename )
345  && loadCacheData( ep ) )
346  return ep->sceneData;
347 
348  ep->sceneData = m_Plugins->Load3DModel( aFileName, ep->pluginInfo );
349 
350  if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && nullptr != ep->sceneData )
351  saveCacheData( ep );
352 
353  return ep->sceneData;
354 }
355 
356 
357 bool S3D_CACHE::getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum )
358 {
359  if( aFileName.empty() )
360  {
361  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] empty filename",
362  __FILE__, __FUNCTION__, __LINE__ );
363 
364  return false;
365  }
366 
367  if( nullptr == aSHA1Sum )
368  {
369  wxLogTrace( MASK_3D_CACHE, "%s\n * [BUG] NULL pointer passed for aMD5Sum",
370  __FILE__, __FUNCTION__, __LINE__ );
371 
372  return false;
373  }
374 
375 #ifdef _WIN32
376  FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
377 #else
378  FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
379 #endif
380 
381  if( nullptr == fp )
382  return false;
383 
384  boost::uuids::detail::sha1 dblock;
385  unsigned char block[4096];
386  size_t bsize = 0;
387 
388  while( ( bsize = fread( &block, 1, 4096, fp ) ) > 0 )
389  dblock.process_bytes( block, bsize );
390 
391  fclose( fp );
392  unsigned int digest[5];
393  dblock.get_digest( digest );
394 
395  // ensure MSB order
396  for( int i = 0; i < 5; ++i )
397  {
398  int idx = i << 2;
399  unsigned int tmp = digest[i];
400  aSHA1Sum[idx+3] = tmp & 0xff;
401  tmp >>= 8;
402  aSHA1Sum[idx+2] = tmp & 0xff;
403  tmp >>= 8;
404  aSHA1Sum[idx+1] = tmp & 0xff;
405  tmp >>= 8;
406  aSHA1Sum[idx] = tmp & 0xff;
407  }
408 
409  return true;
410 }
411 
412 
414 {
415  wxString bname = aCacheItem->GetCacheBaseName();
416 
417  if( bname.empty() )
418  {
419  wxLogTrace( MASK_3D_CACHE,
420  " * [3D model] cannot load cached model; no file hash available" );
421 
422  return false;
423  }
424 
425  if( m_CacheDir.empty() )
426  {
427  wxLogTrace( MASK_3D_CACHE,
428  " * [3D model] cannot load cached model; config directory unknown" );
429 
430  return false;
431  }
432 
433  wxString fname = m_CacheDir + bname + wxT( ".3dc" );
434 
435  if( !wxFileName::FileExists( fname ) )
436  {
437  wxString errmsg = "cannot open file";
438  wxLogTrace( MASK_3D_CACHE, " * [3D model] %s '%s'", errmsg.GetData(), fname.GetData() );
439  return false;
440  }
441 
442  if( nullptr != aCacheItem->sceneData )
443  S3D::DestroyNode( (SGNODE*) aCacheItem->sceneData );
444 
445  aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8(), m_Plugins, checkTag );
446 
447  if( nullptr == aCacheItem->sceneData )
448  return false;
449 
450  return true;
451 }
452 
453 
455 {
456  if( nullptr == aCacheItem )
457  {
458  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * NULL passed for aCacheItem",
459  __FILE__, __FUNCTION__, __LINE__ );
460 
461  return false;
462  }
463 
464  if( nullptr == aCacheItem->sceneData )
465  {
466  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * aCacheItem has no valid scene data",
467  __FILE__, __FUNCTION__, __LINE__ );
468 
469  return false;
470  }
471 
472  wxString bname = aCacheItem->GetCacheBaseName();
473 
474  if( bname.empty() )
475  {
476  wxLogTrace( MASK_3D_CACHE,
477  " * [3D model] cannot load cached model; no file hash available" );
478 
479  return false;
480  }
481 
482  if( m_CacheDir.empty() )
483  {
484  wxLogTrace( MASK_3D_CACHE,
485  " * [3D model] cannot load cached model; config directory unknown" );
486 
487  return false;
488  }
489 
490  wxString fname = m_CacheDir + bname + wxT( ".3dc" );
491 
492  if( wxFileName::Exists( fname ) )
493  {
494  if( !wxFileName::FileExists( fname ) )
495  {
496  wxLogTrace( MASK_3D_CACHE, " * [3D model] path exists but is not a regular file '%s'",
497  fname );
498 
499  return false;
500  }
501  }
502 
503  return S3D::WriteCache( fname.ToUTF8(), true, (SGNODE*)aCacheItem->sceneData,
504  aCacheItem->pluginInfo.c_str() );
505 }
506 
507 
508 bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
509 {
510  if( !m_ConfigDir.empty() )
511  return false;
512 
513  wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), "" );
514 
515  cfgdir.Normalize();
516 
517  if( !cfgdir.DirExists() )
518  {
519  cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
520 
521  if( !cfgdir.DirExists() )
522  {
523  wxLogTrace( MASK_3D_CACHE,
524  "%s:%s:%d\n * failed to create 3D configuration directory '%s'",
525  __FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
526 
527  return false;
528  }
529  }
530 
531  m_ConfigDir = cfgdir.GetPath();
532 
533  // inform the file resolver of the config directory
535  {
536  wxLogTrace( MASK_3D_CACHE,
537  "%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
538  " * config directory: '%s'",
539  __FILE__, __FUNCTION__, __LINE__, m_ConfigDir );
540  }
541 
542  // 3D cache data must go to a user's cache directory;
543  // unfortunately wxWidgets doesn't seem to provide
544  // functions to retrieve such a directory.
545  //
546  // 1. OSX: ~/Library/Caches/kicad/3d/
547  // 2. Linux: ${XDG_CACHE_HOME}/kicad/3d ~/.cache/kicad/3d/
548  // 3. MSWin: AppData\Local\kicad\3d
549  wxFileName cacheDir;
550  cacheDir.AssignDir( PATHS::GetUserCachePath() );
551  cacheDir.AppendDir( "3d" );
552 
553  if( !cacheDir.DirExists() )
554  {
555  cacheDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
556 
557  if( !cacheDir.DirExists() )
558  {
559  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * failed to create 3D cache directory '%s'",
560  __FILE__, __FUNCTION__, __LINE__, cacheDir.GetPath() );
561 
562  return false;
563  }
564  }
565 
566  m_CacheDir = cacheDir.GetPathWithSep();
567  return true;
568 }
569 
570 
572 {
573  m_project = aProject;
574 
575  bool hasChanged = false;
576 
577  if( m_FNResolver->SetProject( aProject, &hasChanged ) && hasChanged )
578  {
579  m_CacheMap.clear();
580 
581  std::list< S3D_CACHE_ENTRY* >::iterator sL = m_CacheList.begin();
582  std::list< S3D_CACHE_ENTRY* >::iterator eL = m_CacheList.end();
583 
584  while( sL != eL )
585  {
586  delete *sL;
587  ++sL;
588  }
589 
590  m_CacheList.clear();
591 
592  return true;
593  }
594 
595  return false;
596 }
597 
598 
600 {
601  m_FNResolver->SetProgramBase( aBase );
602 }
603 
604 
606 {
607  return m_FNResolver;
608 }
609 
610 
611 std::list< wxString > const* S3D_CACHE::GetFileFilters() const
612 {
613  return m_Plugins->GetFileFilters();
614 }
615 
616 
617 void S3D_CACHE::FlushCache( bool closePlugins )
618 {
619  std::list< S3D_CACHE_ENTRY* >::iterator sCL = m_CacheList.begin();
620  std::list< S3D_CACHE_ENTRY* >::iterator eCL = m_CacheList.end();
621 
622  while( sCL != eCL )
623  {
624  delete *sCL;
625  ++sCL;
626  }
627 
628  m_CacheList.clear();
629  m_CacheMap.clear();
630 
631  if( closePlugins )
632  ClosePlugins();
633 }
634 
635 
637 {
638  if( m_Plugins )
640 }
641 
642 
643 S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName )
644 {
645  S3D_CACHE_ENTRY* cp = nullptr;
646  SCENEGRAPH* sp = load( aModelFileName, &cp );
647 
648  if( !sp )
649  return nullptr;
650 
651  if( !cp )
652  {
653  wxLogTrace( MASK_3D_CACHE,
654  "%s:%s:%d\n * [BUG] model loaded with no associated S3D_CACHE_ENTRY",
655  __FILE__, __FUNCTION__, __LINE__ );
656 
657  return nullptr;
658  }
659 
660  if( cp->renderData )
661  return cp->renderData;
662 
663  S3DMODEL* mp = S3D::GetModel( sp );
664  cp->renderData = mp;
665 
666  return mp;
667 }
668 
669 void S3D_CACHE::CleanCacheDir( int aNumDaysOld )
670 {
671  wxDir dir;
672  wxString fileSpec = wxT( "*.3dc" );
673  wxArrayString fileList; // Holds list of ".3dc" files found in cache directory
674  size_t numFilesFound = 0;
675 
676  wxFileName thisFile;
677  wxDateTime lastAccess, thresholdDate;
678  wxDateSpan durationInDays;
679 
680  // Calc the threshold date above which we delete cache files
681  durationInDays.SetDays( aNumDaysOld );
682  thresholdDate = wxDateTime::Now() - durationInDays;
683 
684  // If the cache directory can be found and opened, then we'll try and clean it up
685  if( dir.Open( m_CacheDir ) )
686  {
687  thisFile.SetPath( m_CacheDir ); // Set the base path to the cache folder
688 
689  // Get a list of all the ".3dc" files in the cache directory
690  numFilesFound = dir.GetAllFiles( m_CacheDir, &fileList, fileSpec );
691 
692  for( unsigned int i = 0; i < numFilesFound; i++ )
693  {
694  // Completes path to specific file so we can get its "last access" date
695  thisFile.SetFullName( fileList[i] );
696 
697  // Only get "last access" time to compare against. Don't need the other 2 timestamps.
698  if( thisFile.GetTimes( &lastAccess, nullptr, nullptr ) )
699  {
700  if( lastAccess.IsEarlierThan( thresholdDate ) )
701  {
702  // This file is older than the threshold so delete it
703  wxRemoveFile( thisFile.GetFullPath() );
704  }
705  }
706  }
707  }
708 }
709 
710 
711 S3D_CACHE* PROJECT::Get3DCacheManager( bool aUpdateProjDir )
712 {
713  std::lock_guard<std::mutex> lock( mutex3D_cacheManager );
714 
715  // Get the existing cache from the project
716  S3D_CACHE* cache = dynamic_cast<S3D_CACHE*>( GetElem( ELEM_3DCACHE ) );
717 
718  if( !cache )
719  {
720  // Create a cache if there is not one already
721  cache = new S3D_CACHE();
722 
723  wxFileName cfgpath;
724  cfgpath.AssignDir( SETTINGS_MANAGER::GetUserSettingsPath() );
725  cfgpath.AppendDir( wxT( "3d" ) );
726 
727  cache->SetProgramBase( &Pgm() );
728  cache->Set3DConfigDir( cfgpath.GetFullPath() );
729 
730  SetElem( ELEM_3DCACHE, cache );
731  aUpdateProjDir = true;
732  }
733 
734  if( aUpdateProjDir )
735  cache->SetProject( this );
736 
737  return cache;
738 }
739 
740 
741 FILENAME_RESOLVER* PROJECT::Get3DFilenameResolver()
742 {
743  return Get3DCacheManager()->GetResolver();
744 }
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:219
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:611
#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:599
static wxString GetUserCachePath()
Gets the stock (install) 3d viewer plugins path.
Definition: paths.cpp:263
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:401
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:413
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:643
virtual void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:258
bool saveCacheData(S3D_CACHE_ENTRY *aCacheItem)
Definition: 3d_cache.cpp:454
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:617
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:148
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:636
void CleanCacheDir(int aNumDaysOld)
Delete up old cache files in cache directory.
Definition: 3d_cache.cpp:669
bool getSHA1(const wxString &aFileName, unsigned char *aSHA1Sum)
Calculate the SHA1 hash of the given file.
Definition: 3d_cache.cpp:357
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:508
FILENAME_RESOLVER * GetResolver() noexcept
Definition: 3d_cache.cpp:605
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:571
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:156
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:336
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