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 <fstream>
28 #include <iostream>
29 #include <iterator>
30 #include <mutex>
31 #include <sstream>
32 #include <utility>
33 
34 #include <wx/datetime.h>
35 #include <wx/filename.h>
36 #include <wx/log.h>
37 #include <wx/stdpaths.h>
38 
39 #include <boost/version.hpp>
40 
41 #if BOOST_VERSION >= 106800
42 #include <boost/uuid/detail/sha1.hpp>
43 #else
44 #include <boost/uuid/sha1.hpp>
45 #endif
46 
47 #include <glm/glm.hpp>
48 #include <glm/ext.hpp>
49 
50 #include "3d_cache.h"
51 #include "3d_info.h"
52 #include "3d_plugin_manager.h"
53 #include "sg/scenegraph.h"
54 #include "plugins/3dapi/ifsg_api.h"
55 
56 #include <filename_resolver.h>
57 #include <pgm_base.h>
58 #include <project.h>
61 
62 
63 #define MASK_3D_CACHE "3D_CACHE"
64 
65 static std::mutex mutex3D_cache;
66 static std::mutex mutex3D_cacheManager;
67 
68 
69 static bool isSHA1Same( const unsigned char* shaA, const unsigned char* shaB ) noexcept
70 {
71  for( int i = 0; i < 20; ++i )
72  if( shaA[i] != shaB[i] )
73  return false;
74 
75  return true;
76 }
77 
78 
79 static bool checkTag( const char* aTag, void* aPluginMgrPtr )
80 {
81  if( NULL == aTag || NULL == aPluginMgrPtr )
82  return false;
83 
84  S3D_PLUGIN_MANAGER *pp = (S3D_PLUGIN_MANAGER*) aPluginMgrPtr;
85 
86  return pp->CheckTag( aTag );
87 }
88 
89 
90 static 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 {
126 private:
127  // prohibit assignment and default copy constructor
128  S3D_CACHE_ENTRY( const S3D_CACHE_ENTRY& source );
129  S3D_CACHE_ENTRY& operator=( const S3D_CACHE_ENTRY& source );
130 
131  wxString m_CacheBaseName; // base name of cache file (a SHA1 digest)
132 
133 public:
134  S3D_CACHE_ENTRY();
136 
137  void SetSHA1( const unsigned char* aSHA1Sum );
138  const wxString GetCacheBaseName();
139 
140  wxDateTime modTime; // file modification time
141  unsigned char sha1sum[20];
142  std::string pluginInfo; // PluginName:Version string
145 };
146 
147 
149 {
150  sceneData = NULL;
151  renderData = NULL;
152  memset( sha1sum, 0, 20 );
153 }
154 
155 
157 {
158  delete sceneData;
159 
160  if( NULL != renderData )
162 }
163 
164 
165 void S3D_CACHE_ENTRY::SetSHA1( const unsigned char* aSHA1Sum )
166 {
167  if( NULL == aSHA1Sum )
168  {
169  wxLogTrace( MASK_3D_CACHE, "%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  COMMON_SETTINGS* commonSettings = Pgm().GetCommonSettings();
199 
200  FlushCache();
201 
202  // We'll delete ".3dc" cache files older than this many days
203  int clearCacheInterval = commonSettings->m_System.clear_3d_cache_interval;
204 
205  // An interval of zero means the user doesn't want to ever clear the cache
206 
207  if( clearCacheInterval > 0 )
208  CleanCacheDir( clearCacheInterval );
209 
210  delete m_FNResolver;
211  delete m_Plugins;
212 }
213 
214 
215 SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr )
216 {
217  if( aCachePtr )
218  *aCachePtr = NULL;
219 
220  wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile );
221 
222  if( full3Dpath.empty() )
223  {
224  // the model cannot be found; we cannot proceed
225  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [3D model] could not find model '%s'\n",
226  __FILE__, __FUNCTION__, __LINE__, aModelFile );
227  return NULL;
228  }
229 
230  // check cache if file is already loaded
231  std::lock_guard<std::mutex> lock( mutex3D_cache );
232 
233  std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
234  mi = m_CacheMap.find( full3Dpath );
235 
236  if( mi != m_CacheMap.end() )
237  {
238  wxFileName fname( full3Dpath );
239 
240  if( fname.FileExists() ) // Only check if file exists. If not, it will
241  { // use the same model in cache.
242  bool reload = false;
243  wxDateTime fmdate = fname.GetModificationTime();
244 
245  if( fmdate != mi->second->modTime )
246  {
247  unsigned char hashSum[20];
248  getSHA1( full3Dpath, hashSum );
249  mi->second->modTime = fmdate;
250 
251  if( !isSHA1Same( hashSum, mi->second->sha1sum ) )
252  {
253  mi->second->SetSHA1( hashSum );
254  reload = true;
255  }
256  }
257 
258  if( reload )
259  {
260  if( NULL != mi->second->sceneData )
261  {
262  S3D::DestroyNode( mi->second->sceneData );
263  mi->second->sceneData = NULL;
264  }
265 
266  if( NULL != mi->second->renderData )
267  S3D::Destroy3DModel( &mi->second->renderData );
268 
269  mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath, mi->second->pluginInfo );
270  }
271  }
272 
273  if( NULL != 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 = NULL;
294 
295  unsigned char sha1sum[20];
296 
297  if( !getSHA1( aFileName, sha1sum ) || m_CacheDir.empty() )
298  {
299  // just in case we can't get a hash digest (for example, on access issues)
300  // or we do not have a configured cache file directory, we create an
301  // entry to prevent further attempts at loading the file
303  m_CacheList.push_back( ep );
304  wxFileName fname( aFileName );
305  ep->modTime = fname.GetModificationTime();
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 
323  return NULL;
324  }
325 
327  m_CacheList.push_back( ep );
328  wxFileName fname( aFileName );
329  ep->modTime = fname.GetModificationTime();
330 
331  if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
332  ( aFileName, ep ) ).second == false )
333  {
334  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'",
335  __FILE__, __FUNCTION__, __LINE__, aFileName );
336 
337  m_CacheList.pop_back();
338  delete ep;
339  return NULL;
340  }
341 
342  if( aCachePtr )
343  *aCachePtr = ep;
344 
345  ep->SetSHA1( sha1sum );
346 
347  wxString bname = ep->GetCacheBaseName();
348  wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
349 
350  if( wxFileName::FileExists( cachename ) && loadCacheData( ep ) )
351  return ep->sceneData;
352 
353  ep->sceneData = m_Plugins->Load3DModel( aFileName, ep->pluginInfo );
354 
355  if( NULL != ep->sceneData )
356  saveCacheData( ep );
357 
358  return ep->sceneData;
359 }
360 
361 
362 bool S3D_CACHE::getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum )
363 {
364  if( aFileName.empty() )
365  {
366  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] empty filename",
367  __FILE__, __FUNCTION__, __LINE__ );
368 
369  return false;
370  }
371 
372  if( NULL == aSHA1Sum )
373  {
374  wxLogTrace( MASK_3D_CACHE, "%s\n * [BUG] NULL pointer passed for aMD5Sum",
375  __FILE__, __FUNCTION__, __LINE__ );
376 
377  return false;
378  }
379 
380  #ifdef _WIN32
381  FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
382  #else
383  FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
384  #endif
385 
386  if( NULL == fp )
387  return false;
388 
389  boost::uuids::detail::sha1 dblock;
390  unsigned char block[4096];
391  size_t bsize = 0;
392 
393  while( ( bsize = fread( &block, 1, 4096, fp ) ) > 0 )
394  dblock.process_bytes( block, bsize );
395 
396  fclose( fp );
397  unsigned int digest[5];
398  dblock.get_digest( digest );
399 
400  // ensure MSB order
401  for( int i = 0; i < 5; ++i )
402  {
403  int idx = i << 2;
404  unsigned int tmp = digest[i];
405  aSHA1Sum[idx+3] = tmp & 0xff;
406  tmp >>= 8;
407  aSHA1Sum[idx+2] = tmp & 0xff;
408  tmp >>= 8;
409  aSHA1Sum[idx+1] = tmp & 0xff;
410  tmp >>= 8;
411  aSHA1Sum[idx] = tmp & 0xff;
412  }
413 
414  return true;
415 }
416 
417 
419 {
420  wxString bname = aCacheItem->GetCacheBaseName();
421 
422  if( bname.empty() )
423  {
424  wxLogTrace( MASK_3D_CACHE,
425  " * [3D model] cannot load cached model; no file hash available" );
426 
427  return false;
428  }
429 
430  if( m_CacheDir.empty() )
431  {
432  wxLogTrace( MASK_3D_CACHE,
433  " * [3D model] cannot load cached model; config directory unknown" );
434 
435  return false;
436  }
437 
438  wxString fname = m_CacheDir + bname + wxT( ".3dc" );
439 
440  if( !wxFileName::FileExists( fname ) )
441  {
442  wxString errmsg = "cannot open file";
443  wxLogTrace( MASK_3D_CACHE, " * [3D model] %s '%s'", errmsg.GetData(), fname.GetData() );
444  return false;
445  }
446 
447  if( NULL != aCacheItem->sceneData )
448  S3D::DestroyNode( (SGNODE*) aCacheItem->sceneData );
449 
450  aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8(), m_Plugins, checkTag );
451 
452  if( NULL == aCacheItem->sceneData )
453  return false;
454 
455  return true;
456 }
457 
458 
460 {
461  if( NULL == aCacheItem )
462  {
463  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * NULL passed for aCacheItem",
464  __FILE__, __FUNCTION__, __LINE__ );
465 
466  return false;
467  }
468 
469  if( NULL == aCacheItem->sceneData )
470  {
471  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * aCacheItem has no valid scene data",
472  __FILE__, __FUNCTION__, __LINE__ );
473 
474  return false;
475  }
476 
477  wxString bname = aCacheItem->GetCacheBaseName();
478 
479  if( bname.empty() )
480  {
481  wxLogTrace( MASK_3D_CACHE,
482  " * [3D model] cannot load cached model; no file hash available" );
483 
484  return false;
485  }
486 
487  if( m_CacheDir.empty() )
488  {
489  wxLogTrace( MASK_3D_CACHE,
490  " * [3D model] cannot load cached model; config directory unknown" );
491 
492  return false;
493  }
494 
495  wxString fname = m_CacheDir + bname + wxT( ".3dc" );
496 
497  if( wxFileName::Exists( fname ) )
498  {
499  if( !wxFileName::FileExists( fname ) )
500  {
501  wxLogTrace( MASK_3D_CACHE, " * [3D model] path exists but is not a regular file '%s'",
502  fname );
503 
504  return false;
505  }
506  }
507 
508  return S3D::WriteCache( fname.ToUTF8(), true, (SGNODE*)aCacheItem->sceneData,
509  aCacheItem->pluginInfo.c_str() );
510 }
511 
512 
513 bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
514 {
515  if( !m_ConfigDir.empty() )
516  return false;
517 
518  wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), "" );
519 
520  cfgdir.Normalize();
521 
522  if( !cfgdir.DirExists() )
523  {
524  cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
525 
526  if( !cfgdir.DirExists() )
527  {
528  wxLogTrace( MASK_3D_CACHE,
529  "%s:%s:%d\n * failed to create 3D configuration directory '%s'",
530  __FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
531 
532  return false;
533  }
534  }
535 
536  m_ConfigDir = cfgdir.GetPath();
537 
538  // inform the file resolver of the config directory
540  {
541  wxLogTrace( MASK_3D_CACHE,
542  "%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
543  " * config directory: '%s'",
544  __FILE__, __FUNCTION__, __LINE__, m_ConfigDir );
545  }
546 
547  // 3D cache data must go to a user's cache directory;
548  // unfortunately wxWidgets doesn't seem to provide
549  // functions to retrieve such a directory.
550  //
551  // 1. OSX: ~/Library/Caches/kicad/3d/
552  // 2. Linux: ${XDG_CACHE_HOME}/kicad/3d ~/.cache/kicad/3d/
553  // 3. MSWin: AppData\Local\kicad\3d
554  wxString cacheDir;
555 
556 #if defined(_WIN32)
557  wxStandardPaths::Get().UseAppInfo( wxStandardPaths::AppInfo_None );
558  cacheDir = wxStandardPaths::Get().GetUserLocalDataDir();
559  cacheDir.append( "\\kicad\\3d" );
560 #elif defined(__APPLE)
561  cacheDir = "${HOME}/Library/Caches/kicad/3d";
562 #else // assume Linux
563  cacheDir = ExpandEnvVarSubstitutions( "${XDG_CACHE_HOME}", nullptr );
564 
565  if( cacheDir.empty() || cacheDir == "${XDG_CACHE_HOME}" )
566  cacheDir = "${HOME}/.cache";
567 
568  cacheDir.append( "/kicad/3d" );
569 #endif
570 
571  cacheDir = ExpandEnvVarSubstitutions( cacheDir, m_project );
572  cfgdir.Assign( cacheDir, "" );
573 
574  if( !cfgdir.DirExists() )
575  {
576  cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
577 
578  if( !cfgdir.DirExists() )
579  {
580  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * failed to create 3D cache directory '%s'",
581  __FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
582 
583  return false;
584  }
585  }
586 
587  m_CacheDir = cfgdir.GetPathWithSep();
588  return true;
589 }
590 
591 
593 {
594  m_project = aProject;
595 
596  bool hasChanged = false;
597 
598  if( m_FNResolver->SetProject( aProject, &hasChanged ) && hasChanged )
599  {
600  m_CacheMap.clear();
601 
602  std::list< S3D_CACHE_ENTRY* >::iterator sL = m_CacheList.begin();
603  std::list< S3D_CACHE_ENTRY* >::iterator eL = m_CacheList.end();
604 
605  while( sL != eL )
606  {
607  delete *sL;
608  ++sL;
609  }
610 
611  m_CacheList.clear();
612 
613  return true;
614  }
615 
616  return false;
617 }
618 
619 
621 {
622  m_FNResolver->SetProgramBase( aBase );
623 }
624 
625 
627 {
628  return m_FNResolver;
629 }
630 
631 
632 std::list< wxString > const* S3D_CACHE::GetFileFilters() const
633 {
634  return m_Plugins->GetFileFilters();
635 }
636 
637 
638 void S3D_CACHE::FlushCache( bool closePlugins )
639 {
640  std::list< S3D_CACHE_ENTRY* >::iterator sCL = m_CacheList.begin();
641  std::list< S3D_CACHE_ENTRY* >::iterator eCL = m_CacheList.end();
642 
643  while( sCL != eCL )
644  {
645  delete *sCL;
646  ++sCL;
647  }
648 
649  m_CacheList.clear();
650  m_CacheMap.clear();
651 
652  if( closePlugins )
653  ClosePlugins();
654 }
655 
656 
658 {
659  if( m_Plugins )
661 }
662 
663 
664 S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName )
665 {
666  S3D_CACHE_ENTRY* cp = NULL;
667  SCENEGRAPH* sp = load( aModelFileName, &cp );
668 
669  if( !sp )
670  return NULL;
671 
672  if( !cp )
673  {
674  wxLogTrace( MASK_3D_CACHE,
675  "%s:%s:%d\n * [BUG] model loaded with no associated S3D_CACHE_ENTRY",
676  __FILE__, __FUNCTION__, __LINE__ );
677 
678  return NULL;
679  }
680 
681  if( cp->renderData )
682  return cp->renderData;
683 
684  S3DMODEL* mp = S3D::GetModel( sp );
685  cp->renderData = mp;
686 
687  return mp;
688 }
689 
690 void S3D_CACHE::CleanCacheDir( int aNumDaysOld )
691 {
692  wxDir dir;
693  wxString fileSpec = wxT( "*.3dc" );
694  wxArrayString fileList; // Holds list of ".3dc" files found in cache directory
695  size_t numFilesFound = 0;
696 
697  wxFileName thisFile;
698  wxDateTime lastAccess, thresholdDate;
699  wxDateSpan durationInDays;
700 
701  // Calc the threshold date above which we delete cache files
702  durationInDays.SetDays( aNumDaysOld );
703  thresholdDate = wxDateTime::Now() - durationInDays;
704 
705  // If the cache directory can be found and opened, then we'll try and clean it up
706  if( dir.Open( m_CacheDir ) )
707  {
708  thisFile.SetPath( m_CacheDir ); // Set the base path to the cache folder
709 
710  // Get a list of all the ".3dc" files in the cache directory
711  numFilesFound = dir.GetAllFiles( m_CacheDir, &fileList, fileSpec );
712 
713  for( unsigned int i = 0; i < numFilesFound; i++ )
714  {
715  // Completes path to specific file so we can get its "last access" date
716  thisFile.SetFullName( fileList[i] );
717 
718  // Only get "last access" time to compare against. Don't need the other 2 timestamps.
719  if( thisFile.GetTimes( &lastAccess, nullptr, nullptr ) )
720  {
721  if( lastAccess.IsEarlierThan( thresholdDate ) )
722  {
723  // This file is older than the threshold so delete it
724  wxRemoveFile( thisFile.GetFullPath() );
725  }
726  }
727  }
728  }
729 }
730 
731 S3D_CACHE* PROJECT::Get3DCacheManager( bool aUpdateProjDir )
732 {
733  std::lock_guard<std::mutex> lock( mutex3D_cacheManager );
734 
735  // Get the existing cache from the project
736  S3D_CACHE* cache = dynamic_cast<S3D_CACHE*>( GetElem( ELEM_3DCACHE ) );
737 
738  if( !cache )
739  {
740  // Create a cache if there is not one already
741  cache = new S3D_CACHE();
742 
743  wxFileName cfgpath;
744  cfgpath.AssignDir( SETTINGS_MANAGER::GetUserSettingsPath() );
745  cfgpath.AppendDir( wxT( "3d" ) );
746 
747  cache->SetProgramBase( &Pgm() );
748  cache->Set3DConfigDir( cfgpath.GetFullPath() );
749 
751  aUpdateProjDir = true;
752  }
753 
754  if( aUpdateProjDir )
755  cache->SetProject( this );
756 
757  return cache;
758 }
759 
760 
761 FILENAME_RESOLVER* PROJECT::Get3DFilenameResolver()
762 {
763  return Get3DCacheManager()->GetResolver();
764 }
static S3D_CACHE * cache
Definition: export_vrml.cpp:60
static const wxString sha1ToWXString(const unsigned char *aSHA1Sum)
Definition: 3d_cache.cpp:90
PROJECT holds project specific data.
Definition: project.h:63
wxString m_CacheBaseName
Definition: 3d_cache.cpp:131
std::string pluginInfo
Definition: 3d_cache.cpp:142
S3D_CACHE_ENTRY()
Definition: 3d_cache.cpp:148
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:321
PGM_BASE keeps program (whole process) data for KiCad programs.
Definition: pgm_base.h:137
std::list< wxString > const * GetFileFilters() const
Function GetFileFilters returns the list of file filters retrieved from the plugins; this will contai...
Definition: 3d_cache.cpp:632
#define MASK_3D_CACHE
Definition: 3d_cache.cpp:63
static std::mutex mutex3D_cache
Definition: 3d_cache.cpp:65
void SetProgramBase(PGM_BASE *aBase)
Function SetProgramBase sets the filename resolver's pointer to the application's PGM_BASE instance; ...
Definition: 3d_cache.cpp:620
provides an extensible class to resolve 3D model paths.
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:536
std::map< wxString, S3D_CACHE_ENTRY *, rsort_wxString > m_CacheMap
mapping of file names to cache names and data
Definition: 3d_cache.h:61
VTBL_ENTRY _ELEM * GetElem(ELEM_T aIndex)
Typically wrapped somewhere else in a more meaningful function wrapper.
Definition: project.cpp:246
bool loadCacheData(S3D_CACHE_ENTRY *aCacheItem)
Definition: 3d_cache.cpp:418
const wxString ExpandEnvVarSubstitutions(const wxString &aString, PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:255
SGNODE represents the base class of all Scene Graph nodes.
Definition: sg_node.h:76
S3D_CACHE.
Definition: 3d_cache.h:54
SCENEGRAPH * Load3DModel(const wxString &aFileName, std::string &aPluginInfo)
const wxString GetCacheBaseName()
Definition: 3d_cache.cpp:179
defines the basic data associated with a single 3D model.
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:102
defines the basic data set required to represent a 3D model; this model must remain compatible with V...
S3D_CACHE_ENTRY & operator=(const S3D_CACHE_ENTRY &source)
FILENAME_RESOLVER * m_FNResolver
Definition: 3d_cache.h:63
bool SetProject(PROJECT *aProject, bool *flgChanged=NULL)
Function SetProjectDir sets the current KiCad project directory as the first entry in the model path ...
S3DMODEL * GetModel(const wxString &aModelFileName)
Function GetModel attempts to load the scene data for a model and to translate it into an S3D_MODEL s...
Definition: 3d_cache.cpp:664
VTBL_ENTRY void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:258
bool saveCacheData(S3D_CACHE_ENTRY *aCacheItem)
Definition: 3d_cache.cpp:459
static std::mutex mutex3D_cacheManager
Definition: 3d_cache.cpp:66
void FlushCache(bool closePlugins=true)
Function FlushCache frees all data in the cache and by default closes all plugins.
Definition: 3d_cache.cpp:638
wxDateTime modTime
Definition: 3d_cache.cpp:140
SGLIB_API void DestroyNode(SGNODE *aNode) noexcept
Function DestroyNode deletes the given SG* class node.
Definition: ifsg_api.cpp:210
#define NULL
wxString m_CacheDir
Definition: 3d_cache.h:68
void SetSHA1(const unsigned char *aSHA1Sum)
Definition: 3d_cache.cpp:165
static bool checkTag(const char *aTag, void *aPluginMgrPtr)
Definition: 3d_cache.cpp:79
~S3D_CACHE_ENTRY()
Definition: 3d_cache.cpp:156
void ClosePlugins()
Function ClosePlugins unloads plugins to free memory.
Definition: 3d_cache.cpp:657
void CleanCacheDir(int aNumDaysOld)
Function Delete up old cache files in cache directory.
Definition: 3d_cache.cpp:690
bool getSHA1(const wxString &aFileName, unsigned char *aSHA1Sum)
Function getSHA1 calculates the SHA1 hash of the given file.
Definition: 3d_cache.cpp:362
SCENEGRAPH * checkCache(const wxString &aFileName, S3D_CACHE_ENTRY **aCachePtr=NULL)
base configuration path for 3D items
Definition: 3d_cache.cpp:290
virtual ~S3D_CACHE()
Definition: 3d_cache.cpp:196
SCENEGRAPH * sceneData
Definition: 3d_cache.cpp:143
defines the API calls for the manipulation of SG* classes
bool CheckTag(const char *aTag)
Function CheckTag checks the given tag and returns true if the plugin named in the tag is not loaded ...
SCENEGRAPH * load(const wxString &aModelFile, S3D_CACHE_ENTRY **aCachePtr=NULL)
Definition: 3d_cache.cpp:215
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
wxString ResolvePath(const wxString &aFileName)
Function ResolvePath determines the full path of the given file name.
S3DMODEL * renderData
Definition: 3d_cache.cpp:144
std::list< S3D_CACHE_ENTRY * > m_CacheList
cache entries
Definition: 3d_cache.h:58
std::list< wxString > const * GetFileFilters(void) const noexcept
Function GetFileFilters returns the list of file filters; this will contain at least the default "All...
see class PGM_BASE
manages 3D model plugins
bool Set3DConfigDir(const wxString &aConfigDir)
Function Set3DConfigDir Sets the configuration directory to be used by the model manager for storing ...
Definition: 3d_cache.cpp:513
FILENAME_RESOLVER * GetResolver() noexcept
Definition: 3d_cache.cpp:626
wxString m_ConfigDir
Definition: 3d_cache.h:69
PROJECT * m_project
Definition: 3d_cache.h:67
bool SetProject(PROJECT *aProject)
Function SetProjectDir sets the current project's working directory; this affects the model search pa...
Definition: 3d_cache.cpp:592
defines the display data cache manager for 3D models
void ClosePlugins(void)
Function ClosePlugins iterates through all discovered plugins and closes them to reclaim memory.
bool Set3DConfigDir(const wxString &aConfigDir)
Function Set3DConfigDir sets the user's configuration directory for 3D models.
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:232
unsigned char sha1sum[20]
Definition: 3d_cache.cpp:141
Store the a model based on meshes and materials.
Definition: c3dmodel.h:90
void SetProgramBase(PGM_BASE *aBase)
Function SetProgramBase sets a pointer to the application's PGM_BASE instance; the pointer is used to...
SCENEGRAPH * Load(const wxString &aModelFile)
Function Load attempts to load the scene data for a model; it will consult the internal cache list an...
Definition: 3d_cache.cpp:284
Definition: 3d_cache.cpp:124
SGLIB_API S3DMODEL * GetModel(SCENEGRAPH *aNode)
Function GetModel creates an S3DMODEL representation of aNode (raw data, no transforms)
Definition: ifsg_api.cpp:471
S3D_PLUGIN_MANAGER * m_Plugins
Definition: 3d_cache.h:65
static bool isSHA1Same(const unsigned char *shaA, const unsigned char *shaB) noexcept
Definition: 3d_cache.cpp:69