Improved 3D cache manager's ability to replace outdated cache models

This commit is contained in:
Cirilo Bernardo 2016-01-31 13:21:12 +11:00
parent b1d35965f5
commit 8dd744f635
9 changed files with 202 additions and 52 deletions

View File

@ -51,6 +51,15 @@
#define CACHE_CONFIG_NAME wxT( "cache.cfg" )
static bool checkTag( const char* aTag, void* aPluginMgrPtr )
{
if( NULL == aTag || NULL == aPluginMgrPtr )
return false;
S3D_PLUGIN_MANAGER *pp = (S3D_PLUGIN_MANAGER*) aPluginMgrPtr;
return pp->CheckTag( aTag );
}
static const wxString sha1ToWXString( const unsigned char* aSHA1Sum )
{
@ -136,8 +145,9 @@ public:
const wxString GetCacheBaseName( void );
unsigned char sha1sum[20];
SCENEGRAPH* sceneData;
S3DMODEL* renderData;
std::string pluginInfo; // PluginName:Version string
SCENEGRAPH* sceneData;
S3DMODEL* renderData;
};
@ -310,7 +320,7 @@ SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY**
if( wxFileName::FileExists( cachename ) && loadCacheData( ep ) )
return ep->sceneData;
ep->sceneData = m_Plugins->Load3DModel( aFileName );
ep->sceneData = m_Plugins->Load3DModel( aFileName, ep->pluginInfo );
if( NULL != ep->sceneData )
saveCacheData( ep );
@ -405,7 +415,7 @@ bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
if( NULL != aCacheItem->sceneData )
S3D::DestroyNode( (SGNODE*) aCacheItem->sceneData );
aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8() );
aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8(), m_Plugins, checkTag );
if( NULL == aCacheItem->sceneData )
return false;
@ -475,7 +485,8 @@ bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
}
}
return S3D::WriteCache( fname.ToUTF8(), true, (SGNODE*)aCacheItem->sceneData );
return S3D::WriteCache( fname.ToUTF8(), true, (SGNODE*)aCacheItem->sceneData,
aCacheItem->pluginInfo.c_str() );
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -27,6 +27,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <string>
#include <sstream>
#include <wx/string.h>
#include <wx/dir.h>
@ -398,7 +399,7 @@ std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const
}
SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName )
SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::string& aPluginInfo )
{
wxFileName raw( aFileName );
wxString ext = raw.GetExt();
@ -416,7 +417,10 @@ SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName )
SCENEGRAPH* sp = sL->second->Load( aFileName.ToUTF8() );
if( NULL != sp )
{
sL->second->GetPluginInfo( aPluginInfo );
return sp;
}
}
++sL;
@ -444,3 +448,45 @@ void S3D_PLUGIN_MANAGER::ClosePlugins( void )
return;
}
bool S3D_PLUGIN_MANAGER::CheckTag( const char* aTag )
{
if( NULL == aTag || aTag[0] == 0 || m_Plugins.empty() )
return false;
std::string tname = aTag;
std::string pname; // plugin name
size_t cpos = tname.find( ':' );
// if there is no colon or plugin name then the tag is bad
if( cpos == std::string::npos || cpos == 0 )
return false;
pname = tname.substr( 0, cpos );
std::string ptag; // tag from the plugin
std::list< KICAD_PLUGIN_LDR_3D* >::iterator pS = m_Plugins.begin();
std::list< KICAD_PLUGIN_LDR_3D* >::iterator pE = m_Plugins.end();
while( pS != pE )
{
ptag.clear();
(*pS)->GetPluginInfo( ptag );
// if the plugin name matches then the version
// must also match
if( !ptag.compare( 0, pname.size(), pname ) )
{
if( ptag.compare( tname ) )
return false;
return true;
}
++pS;
}
return true;
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -31,6 +31,7 @@
#include <map>
#include <list>
#include <string>
#include <wx/string.h>
class wxWindow;
@ -82,7 +83,7 @@ public:
*/
std::list< wxString > const* GetFileFilters( void ) const;
SCENEGRAPH* Load3DModel( const wxString& aFileName );
SCENEGRAPH* Load3DModel( const wxString& aFileName, std::string& aPluginInfo );
/**
* Function ClosePlugins
@ -91,6 +92,13 @@ public:
* reloaded as calls are made to load specific models.
*/
void ClosePlugins( void );
/**
* Function CheckTag
* checks the given tag and returns true if the plugin named in the tag
* is not loaded or the plugin is loaded and the version matches
*/
bool CheckTag( const char* aTag );
};
#endif // PLUGIN_MANAGER_3D_H

View File

@ -48,6 +48,10 @@
static char BadNode[] = " * [BUG] NULL pointer passed for aNode\n";
#endif
// version format of the cache file
#define SG_VERSION_TAG "VERSION:2"
static void formatMaterial( SMATERIAL& mat, SGAPPEARANCE const* app )
{
float v0, v1, v2;
@ -229,7 +233,8 @@ void S3D::DestroyNode( SGNODE* aNode )
}
bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode )
bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
const char* aPluginInfo )
{
if( NULL == aFileName || aFileName[0] == 0 )
return false;
@ -281,23 +286,34 @@ bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode )
return false;
}
output << "(" << SG_VERSION_TAG << ")";
if( NULL != aPluginInfo && aPluginInfo[0] != 0 )
output << "(" << aPluginInfo << ")";
else
output << "(INTERNAL:0.0.0.0)";
bool rval = aNode->WriteCache( output, NULL );
output.close();
#ifdef DEBUG
if( !rval )
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] problems encountered writing cache file '";
std::cerr << aFileName << "'\n";
#endif
// delete the defective file
wxRemoveFile( ofile );
}
#endif
return rval;
}
SGNODE* S3D::ReadCache( const char* aFileName )
SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
bool (*aTagCheck)( const char*, void* ) )
{
if( NULL == aFileName || aFileName[0] == 0 )
return NULL;
@ -336,6 +352,79 @@ SGNODE* S3D::ReadCache( const char* aFileName )
return NULL;
}
// from SG_VERSION_TAG 1, read the version tag; if it's not the expected tag
// then we fail to read the cache file
do
{
std::string name;
char schar;
file.get( schar );
if( '(' != schar )
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] corrupt data; missing left parenthesis at position ";
std::cerr << file.tellg() << "\n";
#endif
file.close();
return NULL;
}
file.get( schar );
while( ')' != schar && file.good() )
{
name.push_back( schar );
file.get( schar );
}
if( name.compare( SG_VERSION_TAG ) )
{
file.close();
return NULL;
}
} while( 0 );
// from SG_VERSION_TAG 2, read the PluginInfo string and check that it matches
// version tag; if it's not the expected tag then we fail to read the file
do
{
std::string name;
char schar;
file.get( schar );
if( '(' != schar )
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] corrupt data; missing left parenthesis at position ";
std::cerr << file.tellg() << "\n";
#endif
file.close();
return NULL;
}
file.get( schar );
while( ')' != schar && file.good() )
{
name.push_back( schar );
file.get( schar );
}
// check the plugin tag
if( NULL != aTagCheck && NULL != aPluginMgr && !aTagCheck( name.c_str(), aPluginMgr ) )
{
file.close();
return NULL;
}
} while( 0 );
bool rval = np->ReadCache( file, NULL );
file.close();

View File

@ -33,9 +33,6 @@
#include "3d_cache/sg/sg_helpers.h"
// version format of the cache file
#define SG_VERSION_TAG "VERSION:1"
SCENEGRAPH::SCENEGRAPH( SGNODE* aParent ) : SGNODE( aParent )
{
m_SGtype = S3D::SGTYPE_TRANSFORM;
@ -370,7 +367,6 @@ bool SCENEGRAPH::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
// ensure unique node names
ResetNodeIndex();
ReNameNodes();
aFile << "[" << SG_VERSION_TAG << "]";
}
if( aFile.fail() )
@ -467,36 +463,6 @@ bool SCENEGRAPH::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
if( NULL == parentNode )
{
// read the tag; if it's not the expected tag then we fail to read the cache file
do
{
char schar;
aFile.get( schar );
if( '[' != schar )
{
#ifdef DEBUG
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] corrupt data; missing left bracket at position ";
std::cerr << aFile.tellg() << "\n";
#endif
return false;
}
aFile.get( schar );
while( ']' != schar && aFile.good() )
{
name.push_back( schar );
aFile.get( schar );
}
if( name.compare( SG_VERSION_TAG ) )
return false;
} while( 0 );
// we need to read the tag and verify its type
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
{

View File

@ -69,7 +69,8 @@ namespace S3D
* @param aNode is any node within the node tree which is to be written
* @return true on success
*/
SGLIB_API bool WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode );
SGLIB_API bool WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
const char* aPluginInfo );
/**
* Function ReadCache
@ -80,7 +81,8 @@ namespace S3D
* if desired this node can be associated with an IFSG_TRANSFORM wrapper via
* the IFSG_TRANSFORM::Attach() function.
*/
SGLIB_API SGNODE* ReadCache( const char* aFileName );
SGLIB_API SGNODE* ReadCache( const char* aFileName, void* aPluginMgr,
bool (*aTagCheck)( const char*, void* ) );
/**
* Function WriteVRML

View File

@ -143,6 +143,11 @@ bool WRL1BASE::Read( WRLPROC& proc )
std::string glob;
WRL1NODES ntype;
// Note: according to the VRML1 specification, a file may contain
// only one grouping node at the top level. The following code
// supports non-conformant VRML1 files by processing all top level
// grouping nodes.
while( proc.ReadName( glob ) )
{
@ -728,6 +733,10 @@ SGNODE* WRL1BASE::TranslateToSG( SGNODE* aParent, WRL1STATUS* /*sp*/ )
if( m_Items.size() == 1 )
return (*m_Items.begin())->TranslateToSG( NULL, NULL );
// Note: according to the VRML1 specification, a file may contain
// only one grouping node at the top level. The following code
// supports non-conformant VRML1 files.
m_current.Init();
IFSG_TRANSFORM txNode( true );

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -241,6 +241,16 @@ bool KICAD_PLUGIN_LDR::open( const wxString& aFullFileName, const char* aPluginC
#endif
ok = true;
// set the plugin info string
m_pluginInfo = GetKicadPluginName();
std::ostringstream ostr;
unsigned char r0, r1, r2, r3;
GetVersion( &r0, &r1, &r2, &r3 );
ostr << ":" << (unsigned int)r0 << "." << (unsigned int)r1;
ostr << "." << (unsigned int)r2 << "." << (unsigned int)r3;
m_pluginInfo.append( ostr.str() );
return true;
}
@ -452,3 +462,9 @@ bool KICAD_PLUGIN_LDR::GetVersion( unsigned char* Major, unsigned char* Minor,
return true;
}
void KICAD_PLUGIN_LDR::GetPluginInfo( std::string& aPluginInfo )
{
aPluginInfo = m_pluginInfo;
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -63,7 +63,8 @@ private:
GET_PLUGIN_NAME m_getPluginName;
GET_VERSION m_getVersion;
wxString m_fileName; // name of last opened Plugin
wxString m_fileName; // name of last opened Plugin
std::string m_pluginInfo; // Name:Version tag for plugin
protected:
std::string m_error; // error message
@ -144,6 +145,8 @@ public:
// returns false if no plugin is loaded
bool GetVersion( unsigned char* Major, unsigned char* Minor,
unsigned char* Patch, unsigned char* Revision );
void GetPluginInfo( std::string& aPluginInfo );
};
#endif // PLUGINLDR_H