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 <common.h>
57 #include <filename_resolver.h>
58 #include <pgm_base.h>
59 #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  FlushCache();
199 
200  delete m_FNResolver;
201  delete m_Plugins;
202 }
203 
204 
205 SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr )
206 {
207  if( aCachePtr )
208  *aCachePtr = NULL;
209 
210  wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile );
211 
212  if( full3Dpath.empty() )
213  {
214  // the model cannot be found; we cannot proceed
215  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [3D model] could not find model '%s'\n",
216  __FILE__, __FUNCTION__, __LINE__, aModelFile );
217  return NULL;
218  }
219 
220  // check cache if file is already loaded
221  std::lock_guard<std::mutex> lock( mutex3D_cache );
222 
223  std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
224  mi = m_CacheMap.find( full3Dpath );
225 
226  if( mi != m_CacheMap.end() )
227  {
228  wxFileName fname( full3Dpath );
229 
230  if( fname.FileExists() ) // Only check if file exists. If not, it will
231  { // use the same model in cache.
232  bool reload = false;
233  wxDateTime fmdate = fname.GetModificationTime();
234 
235  if( fmdate != mi->second->modTime )
236  {
237  unsigned char hashSum[20];
238  getSHA1( full3Dpath, hashSum );
239  mi->second->modTime = fmdate;
240 
241  if( !isSHA1Same( hashSum, mi->second->sha1sum ) )
242  {
243  mi->second->SetSHA1( hashSum );
244  reload = true;
245  }
246  }
247 
248  if( reload )
249  {
250  if( NULL != mi->second->sceneData )
251  {
252  S3D::DestroyNode( mi->second->sceneData );
253  mi->second->sceneData = NULL;
254  }
255 
256  if( NULL != mi->second->renderData )
257  S3D::Destroy3DModel( &mi->second->renderData );
258 
259  mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath, mi->second->pluginInfo );
260  }
261  }
262 
263  if( NULL != aCachePtr )
264  *aCachePtr = mi->second;
265 
266  return mi->second->sceneData;
267  }
268 
269  // a cache item does not exist; search the Filename->Cachename map
270  return checkCache( full3Dpath, aCachePtr );
271 }
272 
273 
274 SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile )
275 {
276  return load( aModelFile );
277 }
278 
279 
280 SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr )
281 {
282  if( aCachePtr )
283  *aCachePtr = NULL;
284 
285  unsigned char sha1sum[20];
286 
287  if( !getSHA1( aFileName, sha1sum ) || m_CacheDir.empty() )
288  {
289  // just in case we can't get a hash digest (for example, on access issues)
290  // or we do not have a configured cache file directory, we create an
291  // entry to prevent further attempts at loading the file
293  m_CacheList.push_back( ep );
294  wxFileName fname( aFileName );
295  ep->modTime = fname.GetModificationTime();
296 
297  if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
298  ( aFileName, ep ) ).second == false )
299  {
300  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'",
301  __FILE__, __FUNCTION__, __LINE__, aFileName );
302 
303  m_CacheList.pop_back();
304  delete ep;
305  }
306  else
307  {
308  if( aCachePtr )
309  *aCachePtr = ep;
310 
311  }
312 
313  return NULL;
314  }
315 
317  m_CacheList.push_back( ep );
318  wxFileName fname( aFileName );
319  ep->modTime = fname.GetModificationTime();
320 
321  if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
322  ( aFileName, ep ) ).second == false )
323  {
324  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'",
325  __FILE__, __FUNCTION__, __LINE__, aFileName );
326 
327  m_CacheList.pop_back();
328  delete ep;
329  return NULL;
330  }
331 
332  if( aCachePtr )
333  *aCachePtr = ep;
334 
335  ep->SetSHA1( sha1sum );
336 
337  wxString bname = ep->GetCacheBaseName();
338  wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
339 
340  if( wxFileName::FileExists( cachename ) && loadCacheData( ep ) )
341  return ep->sceneData;
342 
343  ep->sceneData = m_Plugins->Load3DModel( aFileName, ep->pluginInfo );
344 
345  if( NULL != ep->sceneData )
346  saveCacheData( ep );
347 
348  return ep->sceneData;
349 }
350 
351 
352 bool S3D_CACHE::getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum )
353 {
354  if( aFileName.empty() )
355  {
356  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] empty filename",
357  __FILE__, __FUNCTION__, __LINE__ );
358 
359  return false;
360  }
361 
362  if( NULL == aSHA1Sum )
363  {
364  wxLogTrace( MASK_3D_CACHE, "%s\n * [BUG] NULL pointer passed for aMD5Sum",
365  __FILE__, __FUNCTION__, __LINE__ );
366 
367  return false;
368  }
369 
370  #ifdef _WIN32
371  FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
372  #else
373  FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
374  #endif
375 
376  if( NULL == fp )
377  return false;
378 
379  boost::uuids::detail::sha1 dblock;
380  unsigned char block[4096];
381  size_t bsize = 0;
382 
383  while( ( bsize = fread( &block, 1, 4096, fp ) ) > 0 )
384  dblock.process_bytes( block, bsize );
385 
386  fclose( fp );
387  unsigned int digest[5];
388  dblock.get_digest( digest );
389 
390  // ensure MSB order
391  for( int i = 0; i < 5; ++i )
392  {
393  int idx = i << 2;
394  unsigned int tmp = digest[i];
395  aSHA1Sum[idx+3] = tmp & 0xff;
396  tmp >>= 8;
397  aSHA1Sum[idx+2] = tmp & 0xff;
398  tmp >>= 8;
399  aSHA1Sum[idx+1] = tmp & 0xff;
400  tmp >>= 8;
401  aSHA1Sum[idx] = tmp & 0xff;
402  }
403 
404  return true;
405 }
406 
407 
409 {
410  wxString bname = aCacheItem->GetCacheBaseName();
411 
412  if( bname.empty() )
413  {
414  wxLogTrace( MASK_3D_CACHE,
415  " * [3D model] cannot load cached model; no file hash available" );
416 
417  return false;
418  }
419 
420  if( m_CacheDir.empty() )
421  {
422  wxLogTrace( MASK_3D_CACHE,
423  " * [3D model] cannot load cached model; config directory unknown" );
424 
425  return false;
426  }
427 
428  wxString fname = m_CacheDir + bname + wxT( ".3dc" );
429 
430  if( !wxFileName::FileExists( fname ) )
431  {
432  wxString errmsg = "cannot open file";
433  wxLogTrace( MASK_3D_CACHE, " * [3D model] %s '%s'", errmsg.GetData(), fname.GetData() );
434  return false;
435  }
436 
437  if( NULL != aCacheItem->sceneData )
438  S3D::DestroyNode( (SGNODE*) aCacheItem->sceneData );
439 
440  aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8(), m_Plugins, checkTag );
441 
442  if( NULL == aCacheItem->sceneData )
443  return false;
444 
445  return true;
446 }
447 
448 
450 {
451  if( NULL == aCacheItem )
452  {
453  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * NULL passed for aCacheItem",
454  __FILE__, __FUNCTION__, __LINE__ );
455 
456  return false;
457  }
458 
459  if( NULL == aCacheItem->sceneData )
460  {
461  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * aCacheItem has no valid scene data",
462  __FILE__, __FUNCTION__, __LINE__ );
463 
464  return false;
465  }
466 
467  wxString bname = aCacheItem->GetCacheBaseName();
468 
469  if( bname.empty() )
470  {
471  wxLogTrace( MASK_3D_CACHE,
472  " * [3D model] cannot load cached model; no file hash available" );
473 
474  return false;
475  }
476 
477  if( m_CacheDir.empty() )
478  {
479  wxLogTrace( MASK_3D_CACHE,
480  " * [3D model] cannot load cached model; config directory unknown" );
481 
482  return false;
483  }
484 
485  wxString fname = m_CacheDir + bname + wxT( ".3dc" );
486 
487  if( wxFileName::Exists( fname ) )
488  {
489  if( !wxFileName::FileExists( fname ) )
490  {
491  wxLogTrace( MASK_3D_CACHE, " * [3D model] path exists but is not a regular file '%s'",
492  fname );
493 
494  return false;
495  }
496  }
497 
498  return S3D::WriteCache( fname.ToUTF8(), true, (SGNODE*)aCacheItem->sceneData,
499  aCacheItem->pluginInfo.c_str() );
500 }
501 
502 
503 bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
504 {
505  if( !m_ConfigDir.empty() )
506  return false;
507 
508  wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), "" );
509 
510  cfgdir.Normalize();
511 
512  if( !cfgdir.DirExists() )
513  {
514  cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
515 
516  if( !cfgdir.DirExists() )
517  {
518  wxLogTrace( MASK_3D_CACHE,
519  "%s:%s:%d\n * failed to create 3D configuration directory '%s'",
520  __FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
521 
522  return false;
523  }
524  }
525 
526  m_ConfigDir = cfgdir.GetPath();
527 
528  // inform the file resolver of the config directory
530  {
531  wxLogTrace( MASK_3D_CACHE,
532  "%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
533  " * config directory: '%s'",
534  __FILE__, __FUNCTION__, __LINE__, m_ConfigDir );
535  }
536 
537  // 3D cache data must go to a user's cache directory;
538  // unfortunately wxWidgets doesn't seem to provide
539  // functions to retrieve such a directory.
540  //
541  // 1. OSX: ~/Library/Caches/kicad/3d/
542  // 2. Linux: ${XDG_CACHE_HOME}/kicad/3d ~/.cache/kicad/3d/
543  // 3. MSWin: AppData\Local\kicad\3d
544  wxString cacheDir;
545 
546 #if defined(_WIN32)
547  wxStandardPaths::Get().UseAppInfo( wxStandardPaths::AppInfo_None );
548  cacheDir = wxStandardPaths::Get().GetUserLocalDataDir();
549  cacheDir.append( "\\kicad\\3d" );
550 #elif defined(__APPLE)
551  cacheDir = "${HOME}/Library/Caches/kicad/3d";
552 #else // assume Linux
553  cacheDir = ExpandEnvVarSubstitutions( "${XDG_CACHE_HOME}", nullptr );
554 
555  if( cacheDir.empty() || cacheDir == "${XDG_CACHE_HOME}" )
556  cacheDir = "${HOME}/.cache";
557 
558  cacheDir.append( "/kicad/3d" );
559 #endif
560 
561  cacheDir = ExpandEnvVarSubstitutions( cacheDir, m_project );
562  cfgdir.Assign( cacheDir, "" );
563 
564  if( !cfgdir.DirExists() )
565  {
566  cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
567 
568  if( !cfgdir.DirExists() )
569  {
570  wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * failed to create 3D cache directory '%s'",
571  __FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
572 
573  return false;
574  }
575  }
576 
577  m_CacheDir = cfgdir.GetPathWithSep();
578  return true;
579 }
580 
581 
583 {
584  m_project = aProject;
585 
586  bool hasChanged = false;
587 
588  if( m_FNResolver->SetProject( aProject, &hasChanged ) && hasChanged )
589  {
590  m_CacheMap.clear();
591 
592  std::list< S3D_CACHE_ENTRY* >::iterator sL = m_CacheList.begin();
593  std::list< S3D_CACHE_ENTRY* >::iterator eL = m_CacheList.end();
594 
595  while( sL != eL )
596  {
597  delete *sL;
598  ++sL;
599  }
600 
601  m_CacheList.clear();
602 
603  return true;
604  }
605 
606  return false;
607 }
608 
609 
611 {
612  m_FNResolver->SetProgramBase( aBase );
613 }
614 
615 
617 {
618  return m_FNResolver;
619 }
620 
621 
622 std::list< wxString > const* S3D_CACHE::GetFileFilters() const
623 {
624  return m_Plugins->GetFileFilters();
625 }
626 
627 
628 void S3D_CACHE::FlushCache( bool closePlugins )
629 {
630  std::list< S3D_CACHE_ENTRY* >::iterator sCL = m_CacheList.begin();
631  std::list< S3D_CACHE_ENTRY* >::iterator eCL = m_CacheList.end();
632 
633  while( sCL != eCL )
634  {
635  delete *sCL;
636  ++sCL;
637  }
638 
639  m_CacheList.clear();
640  m_CacheMap.clear();
641 
642  if( closePlugins )
643  ClosePlugins();
644 }
645 
646 
648 {
649  if( m_Plugins )
651 }
652 
653 
654 S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName )
655 {
656  S3D_CACHE_ENTRY* cp = NULL;
657  SCENEGRAPH* sp = load( aModelFileName, &cp );
658 
659  if( !sp )
660  return NULL;
661 
662  if( !cp )
663  {
664  wxLogTrace( MASK_3D_CACHE,
665  "%s:%s:%d\n * [BUG] model loaded with no associated S3D_CACHE_ENTRY",
666  __FILE__, __FUNCTION__, __LINE__ );
667 
668  return NULL;
669  }
670 
671  if( cp->renderData )
672  return cp->renderData;
673 
674  S3DMODEL* mp = S3D::GetModel( sp );
675  cp->renderData = mp;
676 
677  return mp;
678 }
679 
680 
681 S3D_CACHE* PROJECT::Get3DCacheManager( bool aUpdateProjDir )
682 {
683  std::lock_guard<std::mutex> lock( mutex3D_cacheManager );
684 
685  // Get the existing cache from the project
686  S3D_CACHE* cache = dynamic_cast<S3D_CACHE*>( GetElem( ELEM_3DCACHE ) );
687 
688  if( !cache )
689  {
690  // Create a cache if there is not one already
691  cache = new S3D_CACHE();
692 
693  wxFileName cfgpath;
694  cfgpath.AssignDir( SETTINGS_MANAGER::GetUserSettingsPath() );
695  cfgpath.AppendDir( wxT( "3d" ) );
696 
697  cache->SetProgramBase( &Pgm() );
698  cache->Set3DConfigDir( cfgpath.GetFullPath() );
699 
701  aUpdateProjDir = true;
702  }
703 
704  if( aUpdateProjDir )
705  cache->SetProject( this );
706 
707  return cache;
708 }
709 
710 
711 FILENAME_RESOLVER* PROJECT::Get3DFilenameResolver()
712 {
713  return Get3DCacheManager()->GetResolver();
714 }
static S3D_CACHE * cache
Definition: export_vrml.cpp:65
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:104
static const wxString sha1ToWXString(const unsigned char *aSHA1Sum)
Definition: 3d_cache.cpp:90
PROJECT holds project specific data.
Definition: project.h:61
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:622
#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:610
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:241
bool loadCacheData(S3D_CACHE_ENTRY *aCacheItem)
Definition: 3d_cache.cpp:408
const wxString ExpandEnvVarSubstitutions(const wxString &aString, PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:574
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.
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:654
VTBL_ENTRY void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:253
bool saveCacheData(S3D_CACHE_ENTRY *aCacheItem)
Definition: 3d_cache.cpp:449
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:628
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:647
bool getSHA1(const wxString &aFileName, unsigned char *aSHA1Sum)
Function getSHA1 calculates the SHA1 hash of the given file.
Definition: 3d_cache.cpp:352
SCENEGRAPH * checkCache(const wxString &aFileName, S3D_CACHE_ENTRY **aCachePtr=NULL)
base configuration path for 3D items
Definition: 3d_cache.cpp:280
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:205
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:503
FILENAME_RESOLVER * GetResolver() noexcept
Definition: 3d_cache.cpp:616
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:582
defines the display data cache manager for 3D models
The common library.
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:274
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