26#define GLM_FORCE_RADIANS 
   31#include <wx/datetime.h> 
   34#include <wx/stdpaths.h> 
   54#define MASK_3D_CACHE "3D_CACHE" 
   59static bool checkTag( 
const char* aTag, 
void* aPluginMgrPtr )
 
   61    if( 
nullptr == aTag || 
nullptr == aPluginMgrPtr )
 
 
  145                             std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
 
  148        *aCachePtr = 
nullptr;
 
  150    wxString full3Dpath = 
m_FNResolver->ResolvePath( aModelFile, aBasePath, std::move( aEmbeddedFilesStack ) );
 
  152    if( full3Dpath.empty() )
 
  155        wxLogTrace( 
MASK_3D_CACHE, wxT( 
"%s:%s:%d\n * [3D model] could not find model '%s'\n" ),
 
  156                    __FILE__, __FUNCTION__, __LINE__, aModelFile );
 
  163    std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
 
  168        wxFileName fname( full3Dpath );
 
  170        if( fname.FileExists() )    
 
  173            wxDateTime fmdate = fname.GetModificationTime();
 
  175            if( fmdate != mi->second->modTime )
 
  178                getHash( full3Dpath, hashSum );
 
  179                mi->second->modTime = fmdate;
 
  181                if( hashSum != mi->second->m_hash )
 
  183                    mi->second->SetHash( hashSum );
 
  190                if( 
nullptr != mi->second->sceneData )
 
  193                    mi->second->sceneData = 
nullptr;
 
  196                if( 
nullptr != mi->second->renderData )
 
  199                mi->second->sceneData = 
m_Plugins->Load3DModel( full3Dpath,
 
  200                                                                mi->second->pluginInfo );
 
  204        if( 
nullptr != aCachePtr )
 
  205            *aCachePtr = mi->second;
 
  207        return mi->second->sceneData;
 
 
  216                             std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
 
  218    return load( aModelFile, aBasePath, 
nullptr, std::move( aEmbeddedFilesStack ) );
 
 
  225        *aCachePtr = 
nullptr;
 
  230    wxFileName fname( aFileName );
 
  231    ep->
modTime = fname.GetModificationTime();
 
  239        if( 
m_CacheMap.emplace( aFileName, ep ).second == 
false )
 
  242                        wxT( 
"%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
 
  243                        __FILE__, __FUNCTION__, __LINE__, aFileName );
 
  257    if( 
m_CacheMap.emplace( aFileName, ep ).second == 
false )
 
  260                    wxT( 
"%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
 
  261                    __FILE__, __FUNCTION__, __LINE__, aFileName );
 
  274    wxString cachename = 
m_CacheDir + bname + wxT( 
".3dc" );
 
 
  291    if( aFileName.empty() )
 
  293        wxLogTrace( 
MASK_3D_CACHE, wxT( 
"%s:%s:%d\n * [BUG] empty filename" ),
 
  294                    __FILE__, __FUNCTION__, __LINE__ );
 
  300    FILE* fp = _wfopen( aFileName.wc_str(), 
L"rb" );
 
  302    FILE* fp = fopen( aFileName.ToUTF8(), 
"rb" );
 
  309    std::vector<char> block( 4096 );
 
  312    while( ( bsize = fread( block.data(), 1, 4096, fp ) ) > 0 )
 
 
  328                    wxT( 
" * [3D model] cannot load cached model; no file hash available" ) );
 
  336                    wxT( 
" * [3D model] cannot load cached model; config directory unknown" ) );
 
  341    wxString fname = 
m_CacheDir + bname + wxT( 
".3dc" );
 
  343    if( !wxFileName::FileExists( fname ) )
 
  345        wxLogTrace( 
MASK_3D_CACHE, wxT( 
" * [3D model] cannot open file '%s'" ), fname.GetData() );
 
 
  363    if( 
nullptr == aCacheItem )
 
  365        wxLogTrace( 
MASK_3D_CACHE, wxT( 
"%s:%s:%d\n * NULL passed for aCacheItem" ),
 
  366                    __FILE__, __FUNCTION__, __LINE__ );
 
  373        wxLogTrace( 
MASK_3D_CACHE, wxT( 
"%s:%s:%d\n * aCacheItem has no valid scene data" ),
 
  374                    __FILE__, __FUNCTION__, __LINE__ );
 
  384                    wxT( 
" * [3D model] cannot load cached model; no file hash available" ) );
 
  392                    wxT( 
" * [3D model] cannot load cached model; config directory unknown" ) );
 
  397    wxString fname = 
m_CacheDir + bname + wxT( 
".3dc" );
 
  399    if( wxFileName::Exists( fname ) )
 
  401        if( !wxFileName::FileExists( fname ) )
 
  404                        wxT( 
" * [3D model] path exists but is not a regular file '%s'" ), fname );
 
 
  424    if( !cfgdir.DirExists() )
 
  426        cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
 
  428        if( !cfgdir.DirExists() )
 
  431                        wxT( 
"%s:%s:%d\n * failed to create 3D configuration directory '%s'" ),
 
  432                        __FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
 
  444                    wxT( 
"%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n" 
  445                         " * config directory: '%s'" ),
 
  458    cacheDir.AppendDir( wxT( 
"3d" ) );
 
  460    if( !cacheDir.DirExists() )
 
  462        cacheDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
 
  464        if( !cacheDir.DirExists() )
 
  467                        wxT( 
"%s:%s:%d\n * failed to create 3D cache directory '%s'" ),
 
  468                        __FILE__, __FUNCTION__, __LINE__, cacheDir.GetPath() );
 
 
  483    bool hasChanged = 
false;
 
  485    if( 
m_FNResolver->SetProject( aProject, &hasChanged ) && hasChanged )
 
  489        std::list< S3D_CACHE_ENTRY* >::iterator sL = 
m_CacheList.begin();
 
  490        std::list< S3D_CACHE_ENTRY* >::iterator eL = 
m_CacheList.end();
 
 
  527    std::list< S3D_CACHE_ENTRY* >::iterator sCL = 
m_CacheList.begin();
 
  528    std::list< S3D_CACHE_ENTRY* >::iterator eCL = 
m_CacheList.end();
 
 
  552                               std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
 
  555    SCENEGRAPH*      sp = 
load( aModelFileName, aBasePath, &cp, std::move( aEmbeddedFilesStack ) );
 
  563                    wxT( 
"%s:%s:%d\n  * [BUG] model loaded with no associated S3D_CACHE_ENTRY" ),
 
  564                    __FILE__, __FUNCTION__, __LINE__ );
 
 
  581    wxString      fileSpec = wxT( 
"*.3dc" );
 
  582    wxArrayString fileList; 
 
  583    size_t        numFilesFound = 0;
 
  586    wxDateTime lastAccess, thresholdDate;
 
  587    wxDateSpan durationInDays;
 
  590    durationInDays.SetDays( aNumDaysOld );
 
  591    thresholdDate = wxDateTime::Now() - durationInDays;
 
  599        numFilesFound = dir.GetAllFiles( 
m_CacheDir, &fileList, fileSpec );
 
  601        for( 
unsigned int i = 0; i < numFilesFound; i++ )
 
  604            thisFile.SetFullName( fileList[i] );
 
  607            if( thisFile.GetTimes( &lastAccess, 
nullptr, 
nullptr ) )
 
  609                if( lastAccess.IsEarlierThan( thresholdDate ) )
 
  612                    wxRemoveFile( thisFile.GetFullPath() );
 
 
static std::mutex mutex3D_cache
 
static bool checkTag(const char *aTag, void *aPluginMgrPtr)
 
defines the basic data associated with a single 3D model.
 
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.
 
A streaming C++ equivalent for MurmurHash3_x64_128.
 
FORCE_INLINE void add(const std::string &input)
 
FORCE_INLINE HASH_128 digest()
 
static wxString GetUserCachePath()
Gets the stock (install) 3d viewer plugins path.
 
Container for data for KiCad programs.
 
Container for project specific data.
 
S3D_CACHE_ENTRY & operator=(const S3D_CACHE_ENTRY &source)
 
S3D_CACHE_ENTRY(const S3D_CACHE_ENTRY &source)
 
void SetHash(const HASH_128 &aHash)
 
const wxString GetCacheBaseName()
 
void SetProgramBase(PGM_BASE *aBase)
Set the filename resolver's pointer to the application's PGM_BASE instance.
 
bool loadCacheData(S3D_CACHE_ENTRY *aCacheItem)
 
void FlushCache(bool closePlugins=true)
Free all data in the cache and by default closes all plugins.
 
bool Set3DConfigDir(const wxString &aConfigDir)
Set the configuration directory to be used by the model manager for storing 3D model manager configur...
 
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...
 
SCENEGRAPH * checkCache(const wxString &aFileName, S3D_CACHE_ENTRY **aCachePtr=nullptr)
Find or create cache entry for file name.
 
S3D_PLUGIN_MANAGER * m_Plugins
 
bool saveCacheData(S3D_CACHE_ENTRY *aCacheItem)
 
SCENEGRAPH * load(const wxString &aModelFile, const wxString &aBasePath, S3D_CACHE_ENTRY **aCachePtr=nullptr, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack={})
 
wxString m_ConfigDir
base configuration path for 3D items.
 
std::list< wxString > const * GetFileFilters() const
Return the list of file filters retrieved from the plugins.
 
FILENAME_RESOLVER * GetResolver() noexcept
 
std::list< S3D_CACHE_ENTRY * > m_CacheList
Cache entries.
 
bool SetProject(PROJECT *aProject)
Set the current project's working directory; this affects the model search path.
 
void CleanCacheDir(int aNumDaysOld)
Delete up old cache files in cache directory.
 
std::map< wxString, S3D_CACHE_ENTRY *, rsort_wxString > m_CacheMap
Mapping of file names to cache names and data.
 
SCENEGRAPH * Load(const wxString &aModelFile, const wxString &aBasePath, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack)
Attempt to load the scene data for a model.
 
void ClosePlugins()
Unload plugins to free memory.
 
bool getHash(const wxString &aFileName, HASH_128 &aHash)
Calculate the SHA1 hash of the given file.
 
FILENAME_RESOLVER * m_FNResolver
 
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.
 
The base class of all Scene Graph nodes.
 
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
 
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.
 
SGLIB_API bool WriteCache(const char *aFileName, bool overwrite, SGNODE *aNode, const char *aPluginInfo)
Write the SGNODE tree to a binary cache file.
 
SGLIB_API void DestroyNode(SGNODE *aNode) noexcept
Delete the given SG* class node.
 
SGLIB_API S3DMODEL * GetModel(SCENEGRAPH *aNode)
Create an S3DMODEL representation of aNode (raw data, no transforms).
 
SGLIB_API void Destroy3DModel(S3DMODEL **aModel)
Free memory used by an S3DMODEL structure and sets the pointer to the structure to NULL.
 
A storage class for 128-bit hash value.
 
Store the a model based on meshes and materials.
 
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().