Add relative to footprint 3d model path resolution
Fixes https://gitlab.com/kicad/code/kicad/-/issues/2073
This commit is contained in:
parent
05f01ab6c6
commit
c50b4fb04f
|
@ -212,12 +212,13 @@ S3D_CACHE::~S3D_CACHE()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr )
|
SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePath,
|
||||||
|
S3D_CACHE_ENTRY** aCachePtr )
|
||||||
{
|
{
|
||||||
if( aCachePtr )
|
if( aCachePtr )
|
||||||
*aCachePtr = nullptr;
|
*aCachePtr = nullptr;
|
||||||
|
|
||||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile );
|
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile, aBasePath );
|
||||||
|
|
||||||
if( full3Dpath.empty() )
|
if( full3Dpath.empty() )
|
||||||
{
|
{
|
||||||
|
@ -282,9 +283,9 @@ SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCach
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile )
|
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile, const wxString& aBasePath )
|
||||||
{
|
{
|
||||||
return load( aModelFile );
|
return load( aModelFile, aBasePath );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -641,10 +642,10 @@ void S3D_CACHE::ClosePlugins()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName )
|
S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName, const wxString& aBasePath )
|
||||||
{
|
{
|
||||||
S3D_CACHE_ENTRY* cp = nullptr;
|
S3D_CACHE_ENTRY* cp = nullptr;
|
||||||
SCENEGRAPH* sp = load( aModelFileName, &cp );
|
SCENEGRAPH* sp = load( aModelFileName, aBasePath,&cp );
|
||||||
|
|
||||||
if( !sp )
|
if( !sp )
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -92,9 +92,10 @@ public:
|
||||||
|
|
||||||
*
|
*
|
||||||
* @param aModelFile is the partial or full path to the model to be loaded.
|
* @param aModelFile is the partial or full path to the model to be loaded.
|
||||||
|
* @param aBasePath is the path to search for any relative files
|
||||||
* @return true if the model was successfully loaded, otherwise false.
|
* @return true if the model was successfully loaded, otherwise false.
|
||||||
*/
|
*/
|
||||||
SCENEGRAPH* Load( const wxString& aModelFile );
|
SCENEGRAPH* Load( const wxString& aModelFile, const wxString& aBasePath );
|
||||||
|
|
||||||
FILENAME_RESOLVER* GetResolver() noexcept;
|
FILENAME_RESOLVER* GetResolver() noexcept;
|
||||||
|
|
||||||
|
@ -124,7 +125,7 @@ public:
|
||||||
* @param aModelFileName is the full path to the model to be loaded.
|
* @param aModelFileName is the full path to the model to be loaded.
|
||||||
* @return is a pointer to the render data or NULL if not available.
|
* @return is a pointer to the render data or NULL if not available.
|
||||||
*/
|
*/
|
||||||
S3DMODEL* GetModel( const wxString& aModelFileName );
|
S3DMODEL* GetModel( const wxString& aModelFileName, const wxString& aBasePath );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete up old cache files in cache directory.
|
* Delete up old cache files in cache directory.
|
||||||
|
@ -164,7 +165,7 @@ private:
|
||||||
bool saveCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
bool saveCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||||
|
|
||||||
// the real load function (can supply a cache entry pointer to member functions)
|
// the real load function (can supply a cache entry pointer to member functions)
|
||||||
SCENEGRAPH* load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr = nullptr );
|
SCENEGRAPH* load( const wxString& aModelFile, const wxString& aBasePath, S3D_CACHE_ENTRY** aCachePtr = nullptr );
|
||||||
|
|
||||||
/// cache entries
|
/// cache entries
|
||||||
std::list< S3D_CACHE_ENTRY* > m_CacheList;
|
std::list< S3D_CACHE_ENTRY* > m_CacheList;
|
||||||
|
|
|
@ -156,7 +156,7 @@ void EDA_3D_MODEL_VIEWER::Set3DModel( const wxString& aModelPathName)
|
||||||
|
|
||||||
if( m_cacheManager )
|
if( m_cacheManager )
|
||||||
{
|
{
|
||||||
const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName );
|
const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName, wxEmptyString );
|
||||||
|
|
||||||
if( model )
|
if( model )
|
||||||
Set3DModel( (const S3DMODEL &)*model );
|
Set3DModel( (const S3DMODEL &)*model );
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <trigo.h>
|
#include <trigo.h>
|
||||||
#include <project.h>
|
#include <project.h>
|
||||||
#include <profile.h> // To use GetRunningMicroSecs or another profiling utility
|
#include <profile.h> // To use GetRunningMicroSecs or another profiling utility
|
||||||
|
#include <fp_lib_table.h>
|
||||||
#include <eda_3d_canvas.h>
|
#include <eda_3d_canvas.h>
|
||||||
#include <eda_3d_viewer_frame.h>
|
#include <eda_3d_viewer_frame.h>
|
||||||
|
|
||||||
|
@ -922,6 +923,19 @@ void RENDER_3D_OPENGL::load3dModels( REPORTER* aStatusReporter )
|
||||||
// Go for all footprints
|
// Go for all footprints
|
||||||
for( const FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
|
for( const FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
|
||||||
{
|
{
|
||||||
|
wxString libraryName = footprint->GetFPID().GetLibNickname();
|
||||||
|
wxString footprintBasePath = wxEmptyString;
|
||||||
|
|
||||||
|
if( m_boardAdapter.GetBoard()->GetProject() )
|
||||||
|
{
|
||||||
|
const FP_LIB_TABLE_ROW* fpRow =
|
||||||
|
m_boardAdapter.GetBoard()->GetProject()->PcbFootprintLibs()->FindRow(
|
||||||
|
libraryName, false );
|
||||||
|
|
||||||
|
if( fpRow )
|
||||||
|
footprintBasePath = fpRow->GetFullURI( true );
|
||||||
|
}
|
||||||
|
|
||||||
for( const FP_3DMODEL& fp_model : footprint->Models() )
|
for( const FP_3DMODEL& fp_model : footprint->Models() )
|
||||||
{
|
{
|
||||||
if( fp_model.m_Show && !fp_model.m_Filename.empty() )
|
if( fp_model.m_Show && !fp_model.m_Filename.empty() )
|
||||||
|
@ -941,7 +955,7 @@ void RENDER_3D_OPENGL::load3dModels( REPORTER* aStatusReporter )
|
||||||
{
|
{
|
||||||
// It is not present, try get it from cache
|
// It is not present, try get it from cache
|
||||||
const S3DMODEL* modelPtr =
|
const S3DMODEL* modelPtr =
|
||||||
m_boardAdapter.Get3dCacheManager()->GetModel( fp_model.m_Filename );
|
m_boardAdapter.Get3dCacheManager()->GetModel( fp_model.m_Filename, footprintBasePath );
|
||||||
|
|
||||||
// only add it if the return is not NULL
|
// only add it if the return is not NULL
|
||||||
if( modelPtr )
|
if( modelPtr )
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
|
|
||||||
#include <board.h>
|
#include <board.h>
|
||||||
#include <footprint.h>
|
#include <footprint.h>
|
||||||
|
#include <fp_lib_table.h>
|
||||||
|
#include <eda_3d_viewer_frame.h>
|
||||||
|
|
||||||
#include <base_units.h>
|
#include <base_units.h>
|
||||||
#include <profile.h> // To use GetRunningMicroSecs or another profiling utility
|
#include <profile.h> // To use GetRunningMicroSecs or another profiling utility
|
||||||
|
@ -1251,13 +1253,27 @@ void RENDER_3D_RAYTRACE::load3DModels( CONTAINER_3D& aDstContainer, bool aSkipMa
|
||||||
auto sM = fp->Models().begin();
|
auto sM = fp->Models().begin();
|
||||||
auto eM = fp->Models().end();
|
auto eM = fp->Models().end();
|
||||||
|
|
||||||
|
wxString libraryName = fp->GetFPID().GetLibNickname();
|
||||||
|
|
||||||
|
wxString footprintBasePath = wxEmptyString;
|
||||||
|
if( m_boardAdapter.GetBoard()->GetProject() )
|
||||||
|
{
|
||||||
|
const FP_LIB_TABLE_ROW* fpRow =
|
||||||
|
m_boardAdapter.GetBoard()->GetProject()->PcbFootprintLibs()->FindRow(
|
||||||
|
libraryName, false );
|
||||||
|
|
||||||
|
if( fpRow )
|
||||||
|
footprintBasePath = fpRow->GetFullURI( true );
|
||||||
|
}
|
||||||
|
|
||||||
while( sM != eM )
|
while( sM != eM )
|
||||||
{
|
{
|
||||||
if( ( static_cast<float>( sM->m_Opacity ) > FLT_EPSILON )
|
if( ( static_cast<float>( sM->m_Opacity ) > FLT_EPSILON )
|
||||||
&& ( sM->m_Show && !sM->m_Filename.empty() ) )
|
&& ( sM->m_Show && !sM->m_Filename.empty() ) )
|
||||||
{
|
{
|
||||||
// get it from cache
|
// get it from cache
|
||||||
const S3DMODEL* modelPtr = cacheMgr->GetModel( sM->m_Filename );
|
const S3DMODEL* modelPtr =
|
||||||
|
cacheMgr->GetModel( sM->m_Filename, footprintBasePath );
|
||||||
|
|
||||||
// only add it if the return is not NULL.
|
// only add it if the return is not NULL.
|
||||||
if( modelPtr )
|
if( modelPtr )
|
||||||
|
|
|
@ -54,6 +54,7 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
|
||||||
m_userUnits = aFrame->GetUserUnits();
|
m_userUnits = aFrame->GetUserUnits();
|
||||||
|
|
||||||
m_dummyBoard = new BOARD();
|
m_dummyBoard = new BOARD();
|
||||||
|
m_dummyBoard->SetProject( &aFrame->Prj() );
|
||||||
|
|
||||||
// This board will only be used to hold a footprint for viewing
|
// This board will only be used to hold a footprint for viewing
|
||||||
m_dummyBoard->SetBoardUse( BOARD_USE::FPHOLDER );
|
m_dummyBoard->SetBoardUse( BOARD_USE::FPHOLDER );
|
||||||
|
|
|
@ -240,7 +240,7 @@ bool FILENAME_RESOLVER::UpdatePathList( const std::vector< SEARCH_PATH >& aPathL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
|
wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName, const wxString& aWorkingPath )
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock( mutex_resolver );
|
std::lock_guard<std::mutex> lock( mutex_resolver );
|
||||||
|
|
||||||
|
@ -324,6 +324,21 @@ wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check path relative to search path
|
||||||
|
if( !aWorkingPath.IsEmpty() && !tname.StartsWith( ":" ) )
|
||||||
|
{
|
||||||
|
wxString tmp = aWorkingPath;
|
||||||
|
tmp.Append( tmpFN.GetPathSeparator() );
|
||||||
|
tmp.Append( tname );
|
||||||
|
tmpFN.Assign( tmp );
|
||||||
|
|
||||||
|
if( tmpFN.MakeAbsolute() && tmpFN.FileExists() )
|
||||||
|
{
|
||||||
|
tname = tmpFN.GetFullPath();
|
||||||
|
return tname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check the partial path relative to ${KICAD6_3DMODEL_DIR} (legacy behavior)
|
// check the partial path relative to ${KICAD6_3DMODEL_DIR} (legacy behavior)
|
||||||
if( !tname.StartsWith( ":" ) )
|
if( !tname.StartsWith( ":" ) )
|
||||||
{
|
{
|
||||||
|
|
|
@ -101,8 +101,11 @@ public:
|
||||||
* In the future remote files may be supported, in which case it is best to require a full
|
* In the future remote files may be supported, in which case it is best to require a full
|
||||||
* URI in which case ResolvePath should check that the URI conforms to RFC-2396 and related
|
* URI in which case ResolvePath should check that the URI conforms to RFC-2396 and related
|
||||||
* documents and copies \a aFileName into aResolvedName if the URI is valid.
|
* documents and copies \a aFileName into aResolvedName if the URI is valid.
|
||||||
|
*
|
||||||
|
* @param aFileName The configured file path to resolve
|
||||||
|
* @param aWorkingPath The current working path for relative path resolutions
|
||||||
*/
|
*/
|
||||||
wxString ResolvePath( const wxString& aFileName );
|
wxString ResolvePath( const wxString& aFileName, const wxString& aWorkingPath );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce a relative path based on the existing search directories or returns the same path
|
* Produce a relative path based on the existing search directories or returns the same path
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <widgets/grid_text_button_helpers.h>
|
#include <widgets/grid_text_button_helpers.h>
|
||||||
#include <widgets/wx_grid.h>
|
#include <widgets/wx_grid.h>
|
||||||
#include <footprint.h>
|
#include <footprint.h>
|
||||||
|
#include <fp_lib_table.h>
|
||||||
#include <footprint_edit_frame.h>
|
#include <footprint_edit_frame.h>
|
||||||
#include <footprint_editor_settings.h>
|
#include <footprint_editor_settings.h>
|
||||||
#include <dialog_footprint_properties_fp_editor.h>
|
#include <dialog_footprint_properties_fp_editor.h>
|
||||||
|
@ -427,7 +428,15 @@ MODEL_VALIDATE_ERRORS PANEL_FP_PROPERTIES_3D_MODEL::validateModelExists( const w
|
||||||
if( !resolv->ValidateFileName( aFilename, hasAlias ) )
|
if( !resolv->ValidateFileName( aFilename, hasAlias ) )
|
||||||
return MODEL_VALIDATE_ERRORS::ILLEGAL_FILENAME;
|
return MODEL_VALIDATE_ERRORS::ILLEGAL_FILENAME;
|
||||||
|
|
||||||
wxString fullPath = resolv->ResolvePath( aFilename );
|
wxString libraryName = m_footprint->GetFPID().GetLibNickname();
|
||||||
|
const FP_LIB_TABLE_ROW* fpRow =
|
||||||
|
m_frame->Prj().PcbFootprintLibs()->FindRow( libraryName, false );
|
||||||
|
|
||||||
|
wxString footprintBasePath = wxEmptyString;
|
||||||
|
if( fpRow )
|
||||||
|
footprintBasePath = fpRow->GetFullURI( true );
|
||||||
|
|
||||||
|
wxString fullPath = resolv->ResolvePath( aFilename, footprintBasePath );
|
||||||
|
|
||||||
if( fullPath.IsEmpty() )
|
if( fullPath.IsEmpty() )
|
||||||
return MODEL_VALIDATE_ERRORS::RESOLVE_FAIL;
|
return MODEL_VALIDATE_ERRORS::RESOLVE_FAIL;
|
||||||
|
|
|
@ -411,7 +411,7 @@ static void idf_export_footprint( BOARD* aPcb, FOOTPRINT* aFootprint, IDF3_BOARD
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
idfFile.Assign( resolver->ResolvePath( sM->m_Filename ) );
|
idfFile.Assign( resolver->ResolvePath( sM->m_Filename, wxEmptyString ) );
|
||||||
idfExt = idfFile.GetExt();
|
idfExt = idfFile.GetExt();
|
||||||
|
|
||||||
if( idfExt.Cmp( wxT( "idf" ) ) && idfExt.Cmp( wxT( "IDF" ) ) )
|
if( idfExt.Cmp( wxT( "idf" ) ) && idfExt.Cmp( wxT( "IDF" ) ) )
|
||||||
|
|
|
@ -1013,7 +1013,7 @@ void EXPORTER_PCB_VRML::ExportVrmlFootprint( FOOTPRINT* aFootprint, std::ostream
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SGNODE* mod3d = (SGNODE*) m_Cache3Dmodels->Load( sM->m_Filename );
|
SGNODE* mod3d = (SGNODE*) m_Cache3Dmodels->Load( sM->m_Filename, wxEmptyString );
|
||||||
|
|
||||||
if( nullptr == mod3d )
|
if( nullptr == mod3d )
|
||||||
{
|
{
|
||||||
|
@ -1078,7 +1078,8 @@ void EXPORTER_PCB_VRML::ExportVrmlFootprint( FOOTPRINT* aFootprint, std::ostream
|
||||||
int old_precision = aOutputFile->precision();
|
int old_precision = aOutputFile->precision();
|
||||||
aOutputFile->precision( m_precision );
|
aOutputFile->precision( m_precision );
|
||||||
|
|
||||||
wxFileName srcFile = m_Cache3Dmodels->GetResolver()->ResolvePath( sM->m_Filename );
|
wxFileName srcFile =
|
||||||
|
m_Cache3Dmodels->GetResolver()->ResolvePath( sM->m_Filename, wxEmptyString );
|
||||||
wxFileName dstFile;
|
wxFileName dstFile;
|
||||||
dstFile.SetPath( m_Subdir3DFpModels );
|
dstFile.SetPath( m_Subdir3DFpModels );
|
||||||
dstFile.SetName( srcFile.GetName() );
|
dstFile.SetName( srcFile.GetName() );
|
||||||
|
|
Loading…
Reference in New Issue