KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The KiCad Developers, see AUTHORS.txt for contributors.
6 * Copyright (C) 2022 CERN
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#define GLM_FORCE_RADIANS
27
28#include <mutex>
29#include <utility>
30
31#include <wx/datetime.h>
32#include <wx/dir.h>
33#include <wx/log.h>
34#include <wx/stdpaths.h>
35
36#include "3d_cache.h"
37#include "3d_info.h"
38#include "3d_plugin_manager.h"
39#include "sg/scenegraph.h"
41
42#include <advanced_config.h>
43#include <common.h> // For ExpandEnvVarSubstitutions
44#include <filename_resolver.h>
45#include <mmh3_hash.h>
46#include <paths.h>
47#include <pgm_base.h>
48#include <project.h>
51#include <wx_filename.h>
52
53
54#define MASK_3D_CACHE "3D_CACHE"
55
56static std::mutex mutex3D_cache;
57
58
59static bool checkTag( const char* aTag, void* aPluginMgrPtr )
60{
61 if( nullptr == aTag || nullptr == aPluginMgrPtr )
62 return false;
63
64 S3D_PLUGIN_MANAGER *pp = (S3D_PLUGIN_MANAGER*) aPluginMgrPtr;
65
66 return pp->CheckTag( aTag );
67}
68
69
71{
72public:
75
76 void SetHash( const HASH_128& aHash );
77 const wxString GetCacheBaseName();
78
79 wxDateTime modTime; // file modification time
81 std::string pluginInfo; // PluginName:Version string
84
85private:
86 // prohibit assignment and default copy constructor
89
90 wxString m_CacheBaseName; // base name of cache file
91};
92
93
95{
96 sceneData = nullptr;
97 renderData = nullptr;
98 m_hash.Clear();
99}
100
101
103{
104 delete sceneData;
105
106 if( nullptr != renderData )
108}
109
110
112{
113 m_hash = aHash;
114}
115
116
118{
119 if( m_CacheBaseName.empty() )
121
122 return m_CacheBaseName;
123}
124
125
127{
129 m_project = nullptr;
131}
132
133
135{
136 FlushCache();
137
138 delete m_FNResolver;
139 delete m_Plugins;
140}
141
142
143SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePath,
144 S3D_CACHE_ENTRY** aCachePtr,
145 std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
146{
147 if( aCachePtr )
148 *aCachePtr = nullptr;
149
150 wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile, aBasePath, std::move( aEmbeddedFilesStack ) );
151
152 if( full3Dpath.empty() )
153 {
154 // the model cannot be found; we cannot proceed
155 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [3D model] could not find model '%s'\n" ),
156 __FILE__, __FUNCTION__, __LINE__, aModelFile );
157 return nullptr;
158 }
159
160 // check cache if file is already loaded
161 std::lock_guard<std::mutex> lock( mutex3D_cache );
162
163 std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
164 mi = m_CacheMap.find( full3Dpath );
165
166 if( mi != m_CacheMap.end() )
167 {
168 wxFileName fname( full3Dpath );
169
170 if( fname.FileExists() ) // Only check if file exists. If not, it will
171 { // use the same model in cache.
173 wxDateTime fmdate = fname.GetModificationTime();
174
175 if( fmdate != mi->second->modTime )
176 {
177 HASH_128 hashSum;
178 getHash( full3Dpath, hashSum );
179 mi->second->modTime = fmdate;
180
181 if( hashSum != mi->second->m_hash )
182 {
183 mi->second->SetHash( hashSum );
184 reload = true;
185 }
186 }
187
188 if( reload )
189 {
190 if( nullptr != mi->second->sceneData )
191 {
192 S3D::DestroyNode( mi->second->sceneData );
193 mi->second->sceneData = nullptr;
194 }
195
196 if( nullptr != mi->second->renderData )
197 S3D::Destroy3DModel( &mi->second->renderData );
198
199 mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath,
200 mi->second->pluginInfo );
201 }
202 }
203
204 if( nullptr != aCachePtr )
205 *aCachePtr = mi->second;
206
207 return mi->second->sceneData;
208 }
209
210 // a cache item does not exist; search the Filename->Cachename map
211 return checkCache( full3Dpath, aCachePtr );
212}
213
214
215SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile, const wxString& aBasePath,
216 std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
217{
218 return load( aModelFile, aBasePath, nullptr, std::move( aEmbeddedFilesStack ) );
219}
220
221
222SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr )
223{
224 if( aCachePtr )
225 *aCachePtr = nullptr;
226
227 HASH_128 hashSum;
229 m_CacheList.push_back( ep );
230 wxFileName fname( aFileName );
231 ep->modTime = fname.GetModificationTime();
232
233 if( !getHash( aFileName, hashSum ) || m_CacheDir.empty() )
234 {
235 // just in case we can't get a hash digest (for example, on access issues)
236 // or we do not have a configured cache file directory, we create an
237 // entry to prevent further attempts at loading the file
238
239 if( m_CacheMap.emplace( aFileName, ep ).second == false )
240 {
241 wxLogTrace( MASK_3D_CACHE,
242 wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
243 __FILE__, __FUNCTION__, __LINE__, aFileName );
244
245 m_CacheList.pop_back();
246 delete ep;
247 }
248 else
249 {
250 if( aCachePtr )
251 *aCachePtr = ep;
252 }
253
254 return nullptr;
255 }
256
257 if( m_CacheMap.emplace( aFileName, ep ).second == false )
258 {
259 wxLogTrace( MASK_3D_CACHE,
260 wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
261 __FILE__, __FUNCTION__, __LINE__, aFileName );
262
263 m_CacheList.pop_back();
264 delete ep;
265 return nullptr;
266 }
267
268 if( aCachePtr )
269 *aCachePtr = ep;
270
271 ep->SetHash( hashSum );
272
273 wxString bname = ep->GetCacheBaseName();
274 wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
275
276 if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && wxFileName::FileExists( cachename )
277 && loadCacheData( ep ) )
278 return ep->sceneData;
279
280 ep->sceneData = m_Plugins->Load3DModel( aFileName, ep->pluginInfo );
281
282 if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && nullptr != ep->sceneData )
283 saveCacheData( ep );
284
285 return ep->sceneData;
286}
287
288
289bool S3D_CACHE::getHash( const wxString& aFileName, HASH_128& aHash )
290{
291 if( aFileName.empty() )
292 {
293 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [BUG] empty filename" ),
294 __FILE__, __FUNCTION__, __LINE__ );
295
296 return false;
297 }
298
299#ifdef _WIN32
300 FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
301#else
302 FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
303#endif
304
305 if( nullptr == fp )
306 return false;
307
308 MMH3_HASH dblock( 0xA1B2C3D4 );
309 std::vector<char> block( 4096 );
310 size_t bsize = 0;
311
312 while( ( bsize = fread( block.data(), 1, 4096, fp ) ) > 0 )
313 dblock.add( block );
314
315 fclose( fp );
316 aHash = dblock.digest();
317 return true;
318}
319
320
322{
323 wxString bname = aCacheItem->GetCacheBaseName();
324
325 if( bname.empty() )
326 {
327 wxLogTrace( MASK_3D_CACHE,
328 wxT( " * [3D model] cannot load cached model; no file hash available" ) );
329
330 return false;
331 }
332
333 if( m_CacheDir.empty() )
334 {
335 wxLogTrace( MASK_3D_CACHE,
336 wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
337
338 return false;
339 }
340
341 wxString fname = m_CacheDir + bname + wxT( ".3dc" );
342
343 if( !wxFileName::FileExists( fname ) )
344 {
345 wxLogTrace( MASK_3D_CACHE, wxT( " * [3D model] cannot open file '%s'" ), fname.GetData() );
346 return false;
347 }
348
349 if( nullptr != aCacheItem->sceneData )
350 S3D::DestroyNode( (SGNODE*) aCacheItem->sceneData );
351
352 aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8(), m_Plugins, checkTag );
353
354 if( nullptr == aCacheItem->sceneData )
355 return false;
356
357 return true;
358}
359
360
362{
363 if( nullptr == aCacheItem )
364 {
365 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * NULL passed for aCacheItem" ),
366 __FILE__, __FUNCTION__, __LINE__ );
367
368 return false;
369 }
370
371 if( nullptr == aCacheItem->sceneData )
372 {
373 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * aCacheItem has no valid scene data" ),
374 __FILE__, __FUNCTION__, __LINE__ );
375
376 return false;
377 }
378
379 wxString bname = aCacheItem->GetCacheBaseName();
380
381 if( bname.empty() )
382 {
383 wxLogTrace( MASK_3D_CACHE,
384 wxT( " * [3D model] cannot load cached model; no file hash available" ) );
385
386 return false;
387 }
388
389 if( m_CacheDir.empty() )
390 {
391 wxLogTrace( MASK_3D_CACHE,
392 wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
393
394 return false;
395 }
396
397 wxString fname = m_CacheDir + bname + wxT( ".3dc" );
398
399 if( wxFileName::Exists( fname ) )
400 {
401 if( !wxFileName::FileExists( fname ) )
402 {
403 wxLogTrace( MASK_3D_CACHE,
404 wxT( " * [3D model] path exists but is not a regular file '%s'" ), fname );
405
406 return false;
407 }
408 }
409
410 return S3D::WriteCache( fname.ToUTF8(), true, (SGNODE*)aCacheItem->sceneData,
411 aCacheItem->pluginInfo.c_str() );
412}
413
414
415bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
416{
417 if( !m_ConfigDir.empty() )
418 return false;
419
420 wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), wxEmptyString );
421
422 cfgdir.Normalize( FN_NORMALIZE_FLAGS );
423
424 if( !cfgdir.DirExists() )
425 {
426 cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
427
428 if( !cfgdir.DirExists() )
429 {
430 wxLogTrace( MASK_3D_CACHE,
431 wxT( "%s:%s:%d\n * failed to create 3D configuration directory '%s'" ),
432 __FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
433
434 return false;
435 }
436 }
437
438 m_ConfigDir = cfgdir.GetPath();
439
440 // inform the file resolver of the config directory
442 {
443 wxLogTrace( MASK_3D_CACHE,
444 wxT( "%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
445 " * config directory: '%s'" ),
446 __FILE__, __FUNCTION__, __LINE__, m_ConfigDir );
447 }
448
449 // 3D cache data must go to a user's cache directory;
450 // unfortunately wxWidgets doesn't seem to provide
451 // functions to retrieve such a directory.
452 //
453 // 1. OSX: ~/Library/Caches/kicad/3d/
454 // 2. Linux: ${XDG_CACHE_HOME}/kicad/3d ~/.cache/kicad/3d/
455 // 3. MSWin: AppData\Local\kicad\3d
456 wxFileName cacheDir;
457 cacheDir.AssignDir( PATHS::GetUserCachePath() );
458 cacheDir.AppendDir( wxT( "3d" ) );
459
460 if( !cacheDir.DirExists() )
461 {
462 cacheDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
463
464 if( !cacheDir.DirExists() )
465 {
466 wxLogTrace( MASK_3D_CACHE,
467 wxT( "%s:%s:%d\n * failed to create 3D cache directory '%s'" ),
468 __FILE__, __FUNCTION__, __LINE__, cacheDir.GetPath() );
469
470 return false;
471 }
472 }
473
474 m_CacheDir = cacheDir.GetPathWithSep();
475 return true;
476}
477
478
480{
481 m_project = aProject;
482
483 bool hasChanged = false;
484
485 if( m_FNResolver->SetProject( aProject, &hasChanged ) && hasChanged )
486 {
487 m_CacheMap.clear();
488
489 std::list< S3D_CACHE_ENTRY* >::iterator sL = m_CacheList.begin();
490 std::list< S3D_CACHE_ENTRY* >::iterator eL = m_CacheList.end();
491
492 while( sL != eL )
493 {
494 delete *sL;
495 ++sL;
496 }
497
498 m_CacheList.clear();
499
500 return true;
501 }
502
503 return false;
504}
505
506
508{
510}
511
512
514{
515 return m_FNResolver;
516}
517
518
519std::list< wxString > const* S3D_CACHE::GetFileFilters() const
520{
521 return m_Plugins->GetFileFilters();
522}
523
524
525void S3D_CACHE::FlushCache( bool closePlugins )
526{
527 std::list< S3D_CACHE_ENTRY* >::iterator sCL = m_CacheList.begin();
528 std::list< S3D_CACHE_ENTRY* >::iterator eCL = m_CacheList.end();
529
530 while( sCL != eCL )
531 {
532 delete *sCL;
533 ++sCL;
534 }
535
536 m_CacheList.clear();
537 m_CacheMap.clear();
538
539 if( closePlugins )
540 ClosePlugins();
541}
542
543
545{
546 if( m_Plugins )
548}
549
550
551S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName, const wxString& aBasePath,
552 std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
553{
554 S3D_CACHE_ENTRY* cp = nullptr;
555 SCENEGRAPH* sp = load( aModelFileName, aBasePath, &cp, std::move( aEmbeddedFilesStack ) );
556
557 if( !sp )
558 return nullptr;
559
560 if( !cp )
561 {
562 wxLogTrace( MASK_3D_CACHE,
563 wxT( "%s:%s:%d\n * [BUG] model loaded with no associated S3D_CACHE_ENTRY" ),
564 __FILE__, __FUNCTION__, __LINE__ );
565
566 return nullptr;
567 }
568
569 if( cp->renderData )
570 return cp->renderData;
571
572 S3DMODEL* mp = S3D::GetModel( sp );
573 cp->renderData = mp;
574
575 return mp;
576}
577
578void S3D_CACHE::CleanCacheDir( int aNumDaysOld )
579{
580 wxDir dir;
581 wxString fileSpec = wxT( "*.3dc" );
582 wxArrayString fileList; // Holds list of ".3dc" files found in cache directory
583 size_t numFilesFound = 0;
584
585 wxFileName thisFile;
586 wxDateTime lastAccess, thresholdDate;
587 wxDateSpan durationInDays;
588
589 // Calc the threshold date above which we delete cache files
590 durationInDays.SetDays( aNumDaysOld );
591 thresholdDate = wxDateTime::Now() - durationInDays;
592
593 // If the cache directory can be found and opened, then we'll try and clean it up
594 if( dir.Open( m_CacheDir ) )
595 {
596 thisFile.SetPath( m_CacheDir ); // Set the base path to the cache folder
597
598 // Get a list of all the ".3dc" files in the cache directory
599 numFilesFound = dir.GetAllFiles( m_CacheDir, &fileList, fileSpec );
600
601 for( unsigned int i = 0; i < numFilesFound; i++ )
602 {
603 // Completes path to specific file so we can get its "last access" date
604 thisFile.SetFullName( fileList[i] );
605
606 // Only get "last access" time to compare against. Don't need the other 2 timestamps.
607 if( thisFile.GetTimes( &lastAccess, nullptr, nullptr ) )
608 {
609 if( lastAccess.IsEarlierThan( thresholdDate ) )
610 {
611 // This file is older than the threshold so delete it
612 wxRemoveFile( thisFile.GetFullPath() );
613 }
614 }
615 }
616 }
617}
#define MASK_3D_CACHE
Definition: 3d_cache.cpp:54
static std::mutex mutex3D_cache
Definition: 3d_cache.cpp:56
static bool checkTag(const char *aTag, void *aPluginMgrPtr)
Definition: 3d_cache.cpp:59
defines the basic data associated with a single 3D model.
manages 3D model plugins
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
Provide an extensible class to resolve 3D model paths.
wxString ResolvePath(const wxString &aFileName, const wxString &aWorkingPath, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack)
Determine the full path of the given file name.
bool Set3DConfigDir(const wxString &aConfigDir)
Set the user's configuration directory for 3D models.
void SetProgramBase(PGM_BASE *aBase)
Set a pointer to the application's PGM_BASE instance used to extract the local env vars.
bool SetProject(const PROJECT *aProject, bool *flgChanged=nullptr)
Set the current KiCad project directory as the first entry in the model path list.
A streaming C++ equivalent for MurmurHash3_x64_128.
Definition: mmh3_hash.h:60
FORCE_INLINE void add(const std::string &input)
Definition: mmh3_hash.h:95
FORCE_INLINE HASH_128 digest()
Definition: mmh3_hash.h:114
static wxString GetUserCachePath()
Gets the stock (install) 3d viewer plugins path.
Definition: paths.cpp:424
Container for data for KiCad programs.
Definition: pgm_base.h:103
Container for project specific data.
Definition: project.h:65
Definition: 3d_cache.cpp:71
S3D_CACHE_ENTRY & operator=(const S3D_CACHE_ENTRY &source)
HASH_128 m_hash
Definition: 3d_cache.cpp:80
S3DMODEL * renderData
Definition: 3d_cache.cpp:83
~S3D_CACHE_ENTRY()
Definition: 3d_cache.cpp:102
SCENEGRAPH * sceneData
Definition: 3d_cache.cpp:82
S3D_CACHE_ENTRY(const S3D_CACHE_ENTRY &source)
void SetHash(const HASH_128 &aHash)
Definition: 3d_cache.cpp:111
const wxString GetCacheBaseName()
Definition: 3d_cache.cpp:117
std::string pluginInfo
Definition: 3d_cache.cpp:81
wxString m_CacheBaseName
Definition: 3d_cache.cpp:90
wxDateTime modTime
Definition: 3d_cache.cpp:79
S3D_CACHE_ENTRY()
Definition: 3d_cache.cpp:94
void SetProgramBase(PGM_BASE *aBase)
Set the filename resolver's pointer to the application's PGM_BASE instance.
Definition: 3d_cache.cpp:507
wxString m_CacheDir
Definition: 3d_cache.h:192
bool loadCacheData(S3D_CACHE_ENTRY *aCacheItem)
Definition: 3d_cache.cpp:321
virtual ~S3D_CACHE()
Definition: 3d_cache.cpp:134
void FlushCache(bool closePlugins=true)
Free all data in the cache and by default closes all plugins.
Definition: 3d_cache.cpp:525
bool Set3DConfigDir(const wxString &aConfigDir)
Set the configuration directory to be used by the model manager for storing 3D model manager configur...
Definition: 3d_cache.cpp:415
S3DMODEL * GetModel(const wxString &aModelFileName, const wxString &aBasePath, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack)
Attempt to load the scene data for a model and to translate it into an S3D_MODEL structure for displa...
Definition: 3d_cache.cpp:551
SCENEGRAPH * checkCache(const wxString &aFileName, S3D_CACHE_ENTRY **aCachePtr=nullptr)
Find or create cache entry for file name.
Definition: 3d_cache.cpp:222
PROJECT * m_project
Definition: 3d_cache.h:191
S3D_PLUGIN_MANAGER * m_Plugins
Definition: 3d_cache.h:189
bool saveCacheData(S3D_CACHE_ENTRY *aCacheItem)
Definition: 3d_cache.cpp:361
SCENEGRAPH * load(const wxString &aModelFile, const wxString &aBasePath, S3D_CACHE_ENTRY **aCachePtr=nullptr, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack={})
Definition: 3d_cache.cpp:143
wxString m_ConfigDir
base configuration path for 3D items.
Definition: 3d_cache.h:193
std::list< wxString > const * GetFileFilters() const
Return the list of file filters retrieved from the plugins.
Definition: 3d_cache.cpp:519
FILENAME_RESOLVER * GetResolver() noexcept
Definition: 3d_cache.cpp:513
std::list< S3D_CACHE_ENTRY * > m_CacheList
Cache entries.
Definition: 3d_cache.h:182
bool SetProject(PROJECT *aProject)
Set the current project's working directory; this affects the model search path.
Definition: 3d_cache.cpp:479
void CleanCacheDir(int aNumDaysOld)
Delete up old cache files in cache directory.
Definition: 3d_cache.cpp:578
std::map< wxString, S3D_CACHE_ENTRY *, rsort_wxString > m_CacheMap
Mapping of file names to cache names and data.
Definition: 3d_cache.h:185
SCENEGRAPH * Load(const wxString &aModelFile, const wxString &aBasePath, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack)
Attempt to load the scene data for a model.
Definition: 3d_cache.cpp:215
void ClosePlugins()
Unload plugins to free memory.
Definition: 3d_cache.cpp:544
bool getHash(const wxString &aFileName, HASH_128 &aHash)
Calculate the SHA1 hash of the given file.
Definition: 3d_cache.cpp:289
FILENAME_RESOLVER * m_FNResolver
Definition: 3d_cache.h:187
void ClosePlugins(void)
Iterate through all discovered plugins and closes them to reclaim memory.
SCENEGRAPH * Load3DModel(const wxString &aFileName, std::string &aPluginInfo)
std::list< wxString > const * GetFileFilters(void) const noexcept
Return the list of file filters; this will contain at least the default "All Files (*....
bool CheckTag(const char *aTag)
Check the given tag and returns true if the plugin named in the tag is not loaded or the plugin is lo...
Define the basic data set required to represent a 3D model.
Definition: scenegraph.h:45
The base class of all Scene Graph nodes.
Definition: sg_node.h:75
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:353
The common library.
bool m_Skip3DModelMemoryCache
Skip reading/writing 3D model memory caches.
defines the API calls for the manipulation of SG* classes
SGLIB_API SGNODE * ReadCache(const char *aFileName, void *aPluginMgr, bool(*aTagCheck)(const char *, void *))
Read a binary cache file and creates an SGNODE tree.
Definition: ifsg_api.cpp:221
SGLIB_API bool WriteCache(const char *aFileName, bool overwrite, SGNODE *aNode, const char *aPluginInfo)
Write the SGNODE tree to a binary cache file.
Definition: ifsg_api.cpp:157
SGLIB_API void DestroyNode(SGNODE *aNode) noexcept
Delete the given SG* class node.
Definition: ifsg_api.cpp:149
SGLIB_API S3DMODEL * GetModel(SCENEGRAPH *aNode)
Create an S3DMODEL representation of aNode (raw data, no transforms).
Definition: ifsg_api.cpp:338
SGLIB_API void Destroy3DModel(S3DMODEL **aModel)
Free memory used by an S3DMODEL structure and sets the pointer to the structure to NULL.
Definition: ifsg_api.cpp:403
see class PGM_BASE
A storage class for 128-bit hash value.
Definition: hash_128.h:36
void Clear()
Definition: hash_128.h:37
std::string ToString() const
Definition: hash_128.h:47
Store the a model based on meshes and materials.
Definition: c3dmodel.h:95
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition: wx_filename.h:39