Allow embedded files to come from components

as well as parent containers, part II.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20210
This commit is contained in:
Jeff Young 2025-04-24 11:33:02 +01:00
parent c2be7fa3e6
commit 524575a595
36 changed files with 225 additions and 102 deletions

View File

@ -141,12 +141,13 @@ S3D_CACHE::~S3D_CACHE()
SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePath, SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePath,
S3D_CACHE_ENTRY** aCachePtr, const EMBEDDED_FILES* aEmbeddedFiles ) S3D_CACHE_ENTRY** aCachePtr,
std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
{ {
if( aCachePtr ) if( aCachePtr )
*aCachePtr = nullptr; *aCachePtr = nullptr;
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile, aBasePath, aEmbeddedFiles ); wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile, aBasePath, aEmbeddedFilesStack );
if( full3Dpath.empty() ) if( full3Dpath.empty() )
{ {
@ -212,9 +213,9 @@ SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePa
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile, const wxString& aBasePath, SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile, const wxString& aBasePath,
const EMBEDDED_FILES* aEmbeddedFiles ) std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
{ {
return load( aModelFile, aBasePath, nullptr, aEmbeddedFiles ); return load( aModelFile, aBasePath, nullptr, aEmbeddedFilesStack );
} }
@ -548,10 +549,10 @@ void S3D_CACHE::ClosePlugins()
S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName, const wxString& aBasePath, S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName, const wxString& aBasePath,
const EMBEDDED_FILES* aEmbeddedFiles ) std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
{ {
S3D_CACHE_ENTRY* cp = nullptr; S3D_CACHE_ENTRY* cp = nullptr;
SCENEGRAPH* sp = load( aModelFileName, aBasePath, &cp, aEmbeddedFiles ); SCENEGRAPH* sp = load( aModelFileName, aBasePath, &cp, aEmbeddedFilesStack );
if( !sp ) if( !sp )
return nullptr; return nullptr;

View File

@ -95,11 +95,12 @@ 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 * @param aBasePath is the path to search for any relative files
* @param aEmbeddedFiles is a pointer to the embedded files list. * @param aEmbeddedFilesStack is a list of pointers to the embedded files list. They will
* be searched from the front of the list.
* @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, const wxString& aBasePath, SCENEGRAPH* Load( const wxString& aModelFile, const wxString& aBasePath,
const EMBEDDED_FILES* aEmbeddedFiles ); std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack );
FILENAME_RESOLVER* GetResolver() noexcept; FILENAME_RESOLVER* GetResolver() noexcept;
@ -128,11 +129,12 @@ 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.
* @param aBasePath is the path to search for any relative files. * @param aBasePath is the path to search for any relative files.
* @param aEmbeddedFiles is a pointer to the embedded files list. * @param aEmbeddedFilesStack is a stack of pointers to the embedded files lists. They will
* be searched from the bottom of the stack.
* @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, const wxString& aBasePath, S3DMODEL* GetModel( const wxString& aModelFileName, const wxString& aBasePath,
const EMBEDDED_FILES* aEmbeddedFiles ); std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack );
/** /**
* Delete up old cache files in cache directory. * Delete up old cache files in cache directory.
@ -174,7 +176,7 @@ private:
// 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, const wxString& aBasePath, SCENEGRAPH* load( const wxString& aModelFile, const wxString& aBasePath,
S3D_CACHE_ENTRY** aCachePtr = nullptr, S3D_CACHE_ENTRY** aCachePtr = nullptr,
const EMBEDDED_FILES* aEmbeddedFiles = nullptr ); std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack = {} );
/// Cache entries. /// Cache entries.
std::list< S3D_CACHE_ENTRY* > m_CacheList; std::list< S3D_CACHE_ENTRY* > m_CacheList;

View File

@ -451,7 +451,7 @@ void EDA_3D_CANVAS::DoRePaint()
return; return;
} }
// Don't attend to ray trace if OpenGL doesn't support it. // Don't attempt to ray trace if OpenGL doesn't support it.
if( !m_opengl_supports_raytracing ) if( !m_opengl_supports_raytracing )
{ {
m_3d_render = m_3d_render_opengl; m_3d_render = m_3d_render_opengl;
@ -459,7 +459,7 @@ void EDA_3D_CANVAS::DoRePaint()
m_boardAdapter.m_Cfg->m_Render.engine = RENDER_ENGINE::OPENGL; m_boardAdapter.m_Cfg->m_Render.engine = RENDER_ENGINE::OPENGL;
} }
// Check if a raytacing was requested and need to switch to raytracing mode // Check if a raytracing was requested and need to switch to raytracing mode
if( m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL ) if( m_boardAdapter.m_Cfg->m_Render.engine == RENDER_ENGINE::OPENGL )
{ {
const bool was_camera_changed = m_camera.ParametersChanged(); const bool was_camera_changed = m_camera.ParametersChanged();

View File

@ -157,7 +157,7 @@ void EDA_3D_MODEL_VIEWER::Set3DModel( const wxString& aModelPathName)
if( m_cacheManager ) if( m_cacheManager )
{ {
const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName, wxEmptyString, nullptr ); const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName, wxEmptyString, {} );
if( model ) if( model )
Set3DModel( (const S3DMODEL &)*model ); Set3DModel( (const S3DMODEL &)*model );

View File

@ -965,10 +965,13 @@ void RENDER_3D_OPENGL::load3dModels( REPORTER* aStatusReporter )
if( !m_3dModelMap.contains( fp_model.m_Filename ) ) if( !m_3dModelMap.contains( fp_model.m_Filename ) )
{ {
// It is not present, try get it from cache // It is not present, try get it from cache
const S3DMODEL* modelPtr = std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
m_boardAdapter.Get3dCacheManager()->GetModel( fp_model.m_Filename, embeddedFilesStack.push_back( footprint->GetEmbeddedFiles() );
embeddedFilesStack.push_back( m_boardAdapter.GetBoard()->GetEmbeddedFiles() );
const S3DMODEL* modelPtr = m_boardAdapter.Get3dCacheManager()->GetModel( fp_model.m_Filename,
footprintBasePath, footprintBasePath,
footprint ); embeddedFilesStack );
// only add it if the return is not NULL // only add it if the return is not NULL
if( modelPtr ) if( modelPtr )

View File

@ -1291,8 +1291,12 @@ void RENDER_3D_RAYTRACE_BASE::load3DModels( CONTAINER_3D& aDstContainer,
continue; continue;
// get it from cache // get it from cache
const S3DMODEL* modelPtr = std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
cacheMgr->GetModel( model.m_Filename, footprintBasePath, fp ); embeddedFilesStack.push_back( fp->GetEmbeddedFiles() );
embeddedFilesStack.push_back( m_boardAdapter.GetBoard()->GetEmbeddedFiles() );
const S3DMODEL* modelPtr = cacheMgr->GetModel( model.m_Filename, footprintBasePath,
embeddedFilesStack );
// only add it if the return is not NULL. // only add it if the return is not NULL.
if( modelPtr ) if( modelPtr )

View File

@ -27,6 +27,7 @@
#include "panel_preview_3d_model.h" #include "panel_preview_3d_model.h"
#include <dialogs/dialog_unit_entry.h> #include <dialogs/dialog_unit_entry.h>
#include <3d_canvas/eda_3d_canvas.h> #include <3d_canvas/eda_3d_canvas.h>
#include <3d_rendering/opengl/render_3d_opengl.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <tool/tool_dispatcher.h> #include <tool/tool_dispatcher.h>
#include <tools/eda_3d_actions.h> #include <tools/eda_3d_actions.h>
@ -64,6 +65,7 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
m_dummyBoard = new BOARD(); m_dummyBoard = new BOARD();
m_dummyBoard->SetProject( &aFrame->Prj(), true ); m_dummyBoard->SetProject( &aFrame->Prj(), true );
m_dummyBoard->SetEmbeddedFilesDelegate( aFrame->GetBoard() );
// 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 );

View File

@ -477,7 +477,7 @@ bool DIALOG_PAGES_SETTINGS::SavePageSettings()
if( fileName != BASE_SCREEN::m_DrawingSheetFileName ) if( fileName != BASE_SCREEN::m_DrawingSheetFileName )
{ {
wxString fullFileName = m_filenameResolver->ResolvePath( fileName, m_projectPath, wxString fullFileName = m_filenameResolver->ResolvePath( fileName, m_projectPath,
m_embeddedFiles ); { m_embeddedFiles } );
BASE_SCREEN::m_DrawingSheetFileName = fileName; BASE_SCREEN::m_DrawingSheetFileName = fileName;

View File

@ -244,7 +244,7 @@ bool FILENAME_RESOLVER::UpdatePathList( const std::vector< SEARCH_PATH >& aPathL
wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName, const wxString& aWorkingPath, wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName, const wxString& aWorkingPath,
const EMBEDDED_FILES* aFiles ) std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
{ {
std::lock_guard<std::mutex> lock( mutex_resolver ); std::lock_guard<std::mutex> lock( mutex_resolver );
@ -266,15 +266,20 @@ wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName, const wxStri
// Check to see if the file is a URI for an embedded file. // Check to see if the file is a URI for an embedded file.
if( tname.StartsWith( FILEEXT::KiCadUriPrefix + "://" ) ) if( tname.StartsWith( FILEEXT::KiCadUriPrefix + "://" ) )
{ {
if( !aFiles ) if( aEmbeddedFilesStack.empty() )
{ {
wxLogTrace( wxT( "KICAD_EMBED" ), wxLogTrace( wxT( "KICAD_EMBED" ),
wxT( "No EMBEDDED_FILES object provided for kicad_embed URI" ) ); wxT( "No EMBEDDED_FILES object provided for kicad_embed URI" ) );
return wxEmptyString; return wxEmptyString;
} }
wxString path = tname.Mid( 14 ); wxString path = tname.Mid( wxString( FILEEXT::KiCadUriPrefix + "://" ).length() );
wxFileName temp_file = aFiles->GetTemporaryFileName( path );
wxFileName temp_file = aEmbeddedFilesStack[0]->GetTemporaryFileName( path );
int ii = 1;
while( !temp_file.IsOk() && ii < (int) aEmbeddedFilesStack.size() )
temp_file = aEmbeddedFilesStack[ii++]->GetTemporaryFileName( path );
if( !temp_file.IsOk() ) if( !temp_file.IsOk() )
{ {

View File

@ -69,8 +69,8 @@ DIALOG_SIM_MODEL<T>::DIALOG_SIM_MODEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame
m_frame( aFrame ), m_frame( aFrame ),
m_symbol( aSymbol ), m_symbol( aSymbol ),
m_fields( aFields ), m_fields( aFields ),
m_libraryModelsMgr( &Prj(), nullptr ), m_libraryModelsMgr( &Prj() ),
m_builtinModelsMgr( &Prj(), nullptr ), m_builtinModelsMgr( &Prj() ),
m_prevModel( nullptr ), m_prevModel( nullptr ),
m_curModelType( SIM_MODEL::TYPE::NONE ), m_curModelType( SIM_MODEL::TYPE::NONE ),
m_scintillaTricksCode( nullptr ), m_scintillaTricksCode( nullptr ),
@ -83,12 +83,15 @@ DIALOG_SIM_MODEL<T>::DIALOG_SIM_MODEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame
m_infoBar->AddCloseButton(); m_infoBar->AddCloseButton();
if constexpr (std::is_same_v<T, SCH_SYMBOL>) if constexpr (std::is_same_v<T, SCH_SYMBOL>)
m_files = aSymbol.Schematic(); {
else SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( &aSymbol );
m_files = &aSymbol; m_filesStack.push_back( symbol->Schematic()->GetEmbeddedFiles() );
}
m_libraryModelsMgr.SetFiles( m_files ); m_filesStack.push_back( aSymbol.GetEmbeddedFiles() );
m_builtinModelsMgr.SetFiles( m_files );
m_libraryModelsMgr.SetFilesStack( m_filesStack );
m_builtinModelsMgr.SetFilesStack( m_filesStack );
for( SCH_PIN* pin : aSymbol.GetPins() ) for( SCH_PIN* pin : aSymbol.GetPins() )
{ {
@ -1256,11 +1259,13 @@ void DIALOG_SIM_MODEL<T>::onBrowseButtonClick( wxCommandEvent& aEvent )
if( customize.GetEmbed() ) if( customize.GetEmbed() )
{ {
EMBEDDED_FILES::EMBEDDED_FILE* result = m_files->AddFile( fn, false ); EMBEDDED_FILES::EMBEDDED_FILE* result = m_filesStack[0]->AddFile( fn, false );
path = result->GetLink(); path = result->GetLink();
} }
else if( fn.MakeRelativeTo( Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith( wxS( ".." ) ) ) else if( fn.MakeRelativeTo( Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith( wxS( ".." ) ) )
{
path = fn.GetFullPath(); path = fn.GetFullPath();
}
WX_STRING_REPORTER reporter; WX_STRING_REPORTER reporter;

View File

@ -129,7 +129,7 @@ private:
T& m_symbol; T& m_symbol;
std::vector<SCH_FIELD>& m_fields; std::vector<SCH_FIELD>& m_fields;
EMBEDDED_FILES* m_files; std::vector<EMBEDDED_FILES*> m_filesStack;
SIM_LIB_MGR m_libraryModelsMgr; SIM_LIB_MGR m_libraryModelsMgr;
SIM_LIB_MGR m_builtinModelsMgr; SIM_LIB_MGR m_builtinModelsMgr;
wxString m_prevLibrary; wxString m_prevLibrary;

View File

@ -93,7 +93,7 @@ void SCH_EDIT_FRAME::LoadDrawingSheet()
wxString filename = resolver.ResolvePath( settings.m_SchDrawingSheetFileName, wxString filename = resolver.ResolvePath( settings.m_SchDrawingSheetFileName,
Prj().GetProjectPath(), Prj().GetProjectPath(),
Schematic().GetEmbeddedFiles() ); { Schematic().GetEmbeddedFiles() } );
wxString msg; wxString msg;
if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( filename, &msg ) ) if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( filename, &msg ) )
@ -220,7 +220,7 @@ void SCH_EDIT_FRAME::saveProjectSettings()
wxFileName layoutfn( resolve.ResolvePath( BASE_SCREEN::m_DrawingSheetFileName, wxFileName layoutfn( resolve.ResolvePath( BASE_SCREEN::m_DrawingSheetFileName,
Prj().GetProjectPath(), Prj().GetProjectPath(),
Schematic().GetEmbeddedFiles() ) ); { Schematic().GetEmbeddedFiles() } ) );
bool success = true; bool success = true;

View File

@ -224,7 +224,7 @@ void EESCHEMA_JOBS_HANDLER::InitRenderSettings( SCH_RENDER_SETTINGS* aRenderSett
resolve.SetProgramBase( &Pgm() ); resolve.SetProgramBase( &Pgm() );
wxString absolutePath = resolve.ResolvePath( path, wxGetCwd(), wxString absolutePath = resolve.ResolvePath( path, wxGetCwd(),
aSch->GetEmbeddedFiles() ); { aSch->GetEmbeddedFiles() } );
if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( absolutePath, &msg ) ) if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( absolutePath, &msg ) )
{ {

View File

@ -1740,7 +1740,7 @@ int ERC_TESTER::TestSimModelIssues()
{ {
WX_STRING_REPORTER reporter; WX_STRING_REPORTER reporter;
int err_count = 0; int err_count = 0;
SIM_LIB_MGR libMgr( &m_schematic->Prj(), m_schematic ); SIM_LIB_MGR libMgr( &m_schematic->Prj() );
for( SCH_SHEET_PATH& sheet : m_sheetList ) for( SCH_SHEET_PATH& sheet : m_sheetList )
{ {

View File

@ -63,8 +63,11 @@ std::string NAME_GENERATOR::Generate( const std::string& aProposedName )
NETLIST_EXPORTER_SPICE::NETLIST_EXPORTER_SPICE( SCHEMATIC* aSchematic ) : NETLIST_EXPORTER_SPICE::NETLIST_EXPORTER_SPICE( SCHEMATIC* aSchematic ) :
NETLIST_EXPORTER_BASE( aSchematic ), NETLIST_EXPORTER_BASE( aSchematic ),
m_libMgr( &aSchematic->Prj(), aSchematic ) m_libMgr( &aSchematic->Prj() )
{ {
std::vector<EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( aSchematic->GetEmbeddedFiles() );
m_libMgr.SetFilesStack( embeddedFilesStack );
} }

View File

@ -1516,7 +1516,7 @@ void SCH_EDIT_FRAME::OnExit( wxCommandEvent& event )
void SCH_EDIT_FRAME::RefreshOperatingPointDisplay() void SCH_EDIT_FRAME::RefreshOperatingPointDisplay()
{ {
SCHEMATIC_SETTINGS& settings = m_schematic->Settings(); SCHEMATIC_SETTINGS& settings = m_schematic->Settings();
SIM_LIB_MGR simLibMgr( &Prj(), &Schematic() ); SIM_LIB_MGR simLibMgr( &Prj() );
NULL_REPORTER devnull; NULL_REPORTER devnull;
// Patch for bug early in V7.99 dev // Patch for bug early in V7.99 dev
@ -1608,8 +1608,13 @@ void SCH_EDIT_FRAME::RefreshOperatingPointDisplay()
} }
else else
{ {
SIM_MODEL& model = simLibMgr.CreateModel( &GetCurrentSheet(), *symbol, std::vector<EMBEDDED_FILES*> embeddedFilesStack;
devnull ).model; embeddedFilesStack.push_back( m_schematic->GetEmbeddedFiles() );
embeddedFilesStack.push_back( symbol->GetEmbeddedFiles() );
simLibMgr.SetFilesStack( embeddedFilesStack );
SIM_MODEL& model = simLibMgr.CreateModel( &GetCurrentSheet(), *symbol, devnull ).model;
SPICE_ITEM spiceItem; SPICE_ITEM spiceItem;
spiceItem.refName = ref; spiceItem.refName = ref;

View File

@ -749,7 +749,14 @@ void SCH_FIELD::OnScintillaCharAdded( SCINTILLA_TRICKS* aScintillaTricks,
{ {
NULL_REPORTER devnull; NULL_REPORTER devnull;
SCH_SHEET_PATH& sheet = schematic->CurrentSheet(); SCH_SHEET_PATH& sheet = schematic->CurrentSheet();
SIM_LIB_MGR mgr( &schematic->Prj(), schematic ); SIM_LIB_MGR mgr( &schematic->Prj() );
std::vector<EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( schematic->GetEmbeddedFiles() );
embeddedFilesStack.push_back( symbol->GetEmbeddedFiles() );
mgr.SetFilesStack( embeddedFilesStack );
SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, devnull ).model; SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, devnull ).model;
for( wxString pin : model.GetPinNames() ) for( wxString pin : model.GetPinNames() )

View File

@ -1311,7 +1311,14 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i
if( range.IsEmpty() ) if( range.IsEmpty() )
range = wxS( "~A" ); range = wxS( "~A" );
SIM_LIB_MGR simLibMgr( &schematic->Prj(), schematic ); SIM_LIB_MGR simLibMgr( &schematic->Prj() );
std::vector<EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( schematic->GetEmbeddedFiles() );
embeddedFilesStack.push_back( GetLibSymbolRef()->GetEmbeddedFiles() );
simLibMgr.SetFilesStack( embeddedFilesStack );
NULL_REPORTER devnull; NULL_REPORTER devnull;
SIM_MODEL& model = simLibMgr.CreateModel( aPath, const_cast<SCH_SYMBOL&>( *this ), SIM_MODEL& model = simLibMgr.CreateModel( aPath, const_cast<SCH_SYMBOL&>( *this ),
devnull ).model; devnull ).model;
@ -2027,6 +2034,12 @@ BITMAPS SCH_SYMBOL::GetMenuImage() const
} }
EMBEDDED_FILES* SCH_SYMBOL::GetEmbeddedFiles()
{
return GetLibSymbolRef()->GetEmbeddedFiles();
}
void SCH_SYMBOL::MirrorHorizontally( int aCenter ) void SCH_SYMBOL::MirrorHorizontally( int aCenter )
{ {
int dx = m_pos.x; int dx = m_pos.x;

View File

@ -684,6 +684,12 @@ public:
/// Set the selected unit of this symbol for all sheets. /// Set the selected unit of this symbol for all sheets.
void SetUnitSelection( int aUnitSelection ); void SetUnitSelection( int aUnitSelection );
/**
* SCH_SYMBOLs don't currently support embedded files, but their LIB_SYMBOL counterparts
* do.
*/
EMBEDDED_FILES* GetEmbeddedFiles() override;
void Move( const VECTOR2I& aMoveVector ) override void Move( const VECTOR2I& aMoveVector ) override
{ {
if( aMoveVector == VECTOR2I( 0, 0 ) ) if( aMoveVector == VECTOR2I( 0, 0 ) )

View File

@ -41,8 +41,7 @@
using namespace std::placeholders; using namespace std::placeholders;
SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT* aPrj, EMBEDDED_FILES* aFiles ) : SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT* aPrj ) :
m_files( aFiles ),
m_project( aPrj ), m_project( aPrj ),
m_forceFullParse( false ) m_forceFullParse( false )
{ {
@ -62,7 +61,12 @@ wxString SIM_LIB_MGR::ResolveLibraryPath( const wxString& aLibraryPath, REPORTER
resolver.SetProject( m_project ); resolver.SetProject( m_project );
wxString expandedPath = resolver.ResolvePath( aLibraryPath, wxEmptyString, m_files ); std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
for( const EMBEDDED_FILES* embeddedFiles : m_embeddedFilesStack )
embeddedFilesStack.push_back( embeddedFiles );
wxString expandedPath = resolver.ResolvePath( aLibraryPath, wxEmptyString, embeddedFilesStack );
wxFileName fn( expandedPath ); wxFileName fn( expandedPath );

View File

@ -39,14 +39,14 @@ class SCH_SYMBOL;
class SIM_LIB_MGR class SIM_LIB_MGR
{ {
public: public:
SIM_LIB_MGR( const PROJECT* aPrj, EMBEDDED_FILES* aFiles ); SIM_LIB_MGR( const PROJECT* aPrj );
virtual ~SIM_LIB_MGR() = default; virtual ~SIM_LIB_MGR() = default;
void SetForceFullParse() { m_forceFullParse = true; } void SetForceFullParse() { m_forceFullParse = true; }
void Clear(); void Clear();
void SetFiles( EMBEDDED_FILES* aFiles ) { m_files = aFiles; } void SetFilesStack( std::vector<EMBEDDED_FILES*> aFilesStack ) { m_embeddedFilesStack = aFilesStack; }
void SetLibrary( const wxString& aLibraryPath, REPORTER& aReporter ); void SetLibrary( const wxString& aLibraryPath, REPORTER& aReporter );
@ -83,7 +83,7 @@ public:
REPORTER& aReporter ); REPORTER& aReporter );
private: private:
EMBEDDED_FILES* m_files; std::vector<EMBEDDED_FILES*> m_embeddedFilesStack;
const PROJECT* m_project; const PROJECT* m_project;
bool m_forceFullParse; bool m_forceFullParse;
std::map<wxString, std::unique_ptr<SIM_LIBRARY>> m_libraries; std::map<wxString, std::unique_ptr<SIM_LIBRARY>> m_libraries;

View File

@ -1669,13 +1669,19 @@ void SIM_MODEL::MigrateSimModel( T& aSymbol, const PROJECT* aProject )
if( !lib.IsEmpty() ) if( !lib.IsEmpty() )
{ {
WX_STRING_REPORTER reporter; WX_STRING_REPORTER reporter;
SIM_LIB_MGR libMgr( aProject, nullptr ); SIM_LIB_MGR libMgr( aProject );
std::vector<SCH_FIELD> emptyFields; std::vector<SCH_FIELD> emptyFields;
std::vector<EMBEDDED_FILES*> embeddedFilesStack;
if constexpr (std::is_same_v<T, SCH_SYMBOL>) if constexpr (std::is_same_v<T, SCH_SYMBOL>)
libMgr.SetFiles( aSymbol.Schematic() ); {
else SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( &aSymbol );
libMgr.SetFiles( &aSymbol ); embeddedFilesStack.push_back( symbol->Schematic()->GetEmbeddedFiles() );
}
embeddedFilesStack.push_back( aSymbol.GetEmbeddedFiles() );
libMgr.SetFilesStack( embeddedFilesStack );
// Pull out any following parameters from model name // Pull out any following parameters from model name
model = model.BeforeFirst( ' ', &modelLineParams ); model = model.BeforeFirst( ' ', &modelLineParams );

View File

@ -53,8 +53,7 @@ std::vector<std::string> SPICE_GENERATOR_IBIS::CurrentNames( const SPICE_ITEM& a
std::string SPICE_GENERATOR_IBIS::IbisDevice( const SPICE_ITEM& aItem, SCHEMATIC* aSchematic, std::string SPICE_GENERATOR_IBIS::IbisDevice( const SPICE_ITEM& aItem, SCHEMATIC* aSchematic,
const wxString& aCacheDir, const wxString& aCacheDir, REPORTER& aReporter ) const
REPORTER& aReporter ) const
{ {
std::string ibisLibFilename = GetFieldValue( &aItem.fields, SIM_LIBRARY::LIBRARY_FIELD ); std::string ibisLibFilename = GetFieldValue( &aItem.fields, SIM_LIBRARY::LIBRARY_FIELD );
std::string ibisCompName = GetFieldValue( &aItem.fields, SIM_LIBRARY::NAME_FIELD ); std::string ibisCompName = GetFieldValue( &aItem.fields, SIM_LIBRARY::NAME_FIELD );
@ -63,7 +62,12 @@ std::string SPICE_GENERATOR_IBIS::IbisDevice( const SPICE_ITEM& aItem, SCHEMATIC
bool diffMode = GetFieldValue( &aItem.fields, SIM_LIBRARY_IBIS::DIFF_FIELD ) == "1"; bool diffMode = GetFieldValue( &aItem.fields, SIM_LIBRARY_IBIS::DIFF_FIELD ) == "1";
WX_STRING_REPORTER reporter; WX_STRING_REPORTER reporter;
SIM_LIB_MGR mgr( &aSchematic->Prj(), aSchematic ); SIM_LIB_MGR mgr( &aSchematic->Prj() );
std::vector<EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( aSchematic->GetEmbeddedFiles() );
mgr.SetFilesStack( embeddedFilesStack );
wxString path = mgr.ResolveLibraryPath( ibisLibFilename, reporter ); wxString path = mgr.ResolveLibraryPath( ibisLibFilename, reporter );
if( reporter.HasMessage() ) if( reporter.HasMessage() )

View File

@ -1664,7 +1664,14 @@ void SIMULATOR_FRAME_UI::UpdateTunerValue( const SCH_SHEET_PATH& aSheetPath, con
} }
NULL_REPORTER devnull; NULL_REPORTER devnull;
SIM_LIB_MGR mgr( &m_schematicFrame->Prj(), &m_schematicFrame->Schematic() ); SIM_LIB_MGR mgr( &m_schematicFrame->Prj() );
std::vector<EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( m_schematicFrame->Schematic().GetEmbeddedFiles() );
embeddedFilesStack.push_back( symbol->GetEmbeddedFiles() );
mgr.SetFilesStack( embeddedFilesStack );
SIM_MODEL& model = mgr.CreateModel( &aSheetPath, *symbol, devnull ).model; SIM_MODEL& model = mgr.CreateModel( &aSheetPath, *symbol, devnull ).model;
const SIM_MODEL::PARAM* tunerParam = model.GetTunerParam(); const SIM_MODEL::PARAM* tunerParam = model.GetTunerParam();

View File

@ -580,7 +580,13 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item->GetParent() ); SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item->GetParent() );
WX_STRING_REPORTER reporter; WX_STRING_REPORTER reporter;
SIM_LIB_MGR mgr( &m_frame->Prj(), &m_frame->Schematic() ); SIM_LIB_MGR mgr( &m_frame->Prj() );
std::vector<EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( m_frame->Schematic().GetEmbeddedFiles() );
embeddedFilesStack.push_back( symbol->GetEmbeddedFiles() );
mgr.SetFilesStack( embeddedFilesStack );
SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, reporter ).model; SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, reporter ).model;
@ -589,8 +595,7 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
SPICE_ITEM spiceItem; SPICE_ITEM spiceItem;
spiceItem.refName = symbol->GetRef( &sheet ).ToStdString(); spiceItem.refName = symbol->GetRef( &sheet ).ToStdString();
std::vector<std::string> currentNames = std::vector<std::string> currentNames = model.SpiceGenerator().CurrentNames( spiceItem );
model.SpiceGenerator().CurrentNames( spiceItem );
if( currentNames.size() == 0 ) if( currentNames.size() == 0 )
{ {

View File

@ -100,10 +100,11 @@ public:
* *
* @param aFileName The configured file path to resolve. * @param aFileName The configured file path to resolve.
* @param aWorkingPath The current working path for relative path resolutions. * @param aWorkingPath The current working path for relative path resolutions.
* @param aFiles The embedded files object to use for embedded file resolution. * @param aEmbeddedFilesStack is a list of pointers to the embedded files list. They will
* be searched from the front of the list.
*/ */
wxString ResolvePath( const wxString& aFileName, const wxString& aWorkingPath, wxString ResolvePath( const wxString& aFileName, const wxString& aWorkingPath,
const EMBEDDED_FILES* aFiles ); std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack );
/** /**
* 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

View File

@ -74,11 +74,20 @@ VECTOR2I BOARD_ITEM::ZeroOffset( 0, 0 );
BOARD::BOARD() : BOARD::BOARD() :
BOARD_ITEM_CONTAINER( (BOARD_ITEM*) nullptr, PCB_T ), m_LegacyDesignSettingsLoaded( false ), BOARD_ITEM_CONTAINER( (BOARD_ITEM*) nullptr, PCB_T ),
m_LegacyCopperEdgeClearanceLoaded( false ), m_LegacyNetclassesLoaded( false ), m_boardUse( BOARD_USE::NORMAL ), m_LegacyDesignSettingsLoaded( false ),
m_timeStamp( 1 ), m_paper( PAGE_INFO::A4 ), m_project( nullptr ), m_userUnits( EDA_UNITS::MM ), m_LegacyCopperEdgeClearanceLoaded( false ),
m_designSettings( new BOARD_DESIGN_SETTINGS( nullptr, "board.design_settings" ) ), m_NetInfo( this ), m_LegacyNetclassesLoaded( false ),
m_embedFonts( false ), m_componentClassManager( std::make_unique<COMPONENT_CLASS_MANAGER>( this ) ), m_boardUse( BOARD_USE::NORMAL ),
m_timeStamp( 1 ),
m_paper( PAGE_INFO::A4 ),
m_project( nullptr ),
m_userUnits( EDA_UNITS::MM ),
m_designSettings( new BOARD_DESIGN_SETTINGS( nullptr, "board.design_settings" ) ),
m_NetInfo( this ),
m_embedFonts( false ),
m_embeddedFilesDelegate( nullptr ),
m_componentClassManager( std::make_unique<COMPONENT_CLASS_MANAGER>( this ) ),
m_lengthDelayCalc( std::make_unique<LENGTH_DELAY_CALCULATION>( this ) ) m_lengthDelayCalc( std::make_unique<LENGTH_DELAY_CALCULATION>( this ) )
{ {
// A too small value do not allow connecting 2 shapes (i.e. segments) not exactly connected // A too small value do not allow connecting 2 shapes (i.e. segments) not exactly connected
@ -2573,8 +2582,8 @@ bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines,
EMBEDDED_FILES* BOARD::GetEmbeddedFiles() EMBEDDED_FILES* BOARD::GetEmbeddedFiles()
{ {
if( IsFootprintHolder() ) if( m_embeddedFilesDelegate )
return static_cast<EMBEDDED_FILES*>( GetFirstFootprint() ); return static_cast<EMBEDDED_FILES*>( m_embeddedFilesDelegate );
return static_cast<EMBEDDED_FILES*>( this ); return static_cast<EMBEDDED_FILES*>( this );
} }
@ -2582,8 +2591,8 @@ EMBEDDED_FILES* BOARD::GetEmbeddedFiles()
const EMBEDDED_FILES* BOARD::GetEmbeddedFiles() const const EMBEDDED_FILES* BOARD::GetEmbeddedFiles() const
{ {
if( IsFootprintHolder() ) if( m_embeddedFilesDelegate )
return static_cast<const EMBEDDED_FILES*>( GetFirstFootprint() ); return static_cast<const EMBEDDED_FILES*>( m_embeddedFilesDelegate );
return static_cast<const EMBEDDED_FILES*>( this ); return static_cast<const EMBEDDED_FILES*>( this );
} }

View File

@ -1275,6 +1275,8 @@ public:
EMBEDDED_FILES* GetEmbeddedFiles() override; EMBEDDED_FILES* GetEmbeddedFiles() override;
const EMBEDDED_FILES* GetEmbeddedFiles() const; const EMBEDDED_FILES* GetEmbeddedFiles() const;
void SetEmbeddedFilesDelegate( EMBEDDED_FILES* aDelegate ) { m_embeddedFilesDelegate = aDelegate; }
/** /**
* Get the list of all outline fonts used in the board * Get the list of all outline fonts used in the board
*/ */
@ -1413,8 +1415,11 @@ private:
bool m_embedFonts; bool m_embedFonts;
std::unique_ptr<COMPONENT_CLASS_MANAGER> m_componentClassManager; // Used for dummy boards, such as a footprint holder, where we don't want to make a copy
// of all the parent's embedded data.
EMBEDDED_FILES* m_embeddedFilesDelegate;
std::unique_ptr<COMPONENT_CLASS_MANAGER> m_componentClassManager;
std::unique_ptr<LENGTH_DELAY_CALCULATION> m_lengthDelayCalc; std::unique_ptr<LENGTH_DELAY_CALCULATION> m_lengthDelayCalc;
}; };

View File

@ -84,7 +84,11 @@ DIALOG_FOOTPRINT_PROPERTIES::DIALOG_FOOTPRINT_PROPERTIES( PCB_EDIT_FRAME* aParen
m_posX.SetCoordType( ORIGIN_TRANSFORMS::ABS_X_COORD ); m_posX.SetCoordType( ORIGIN_TRANSFORMS::ABS_X_COORD );
m_posY.SetCoordType( ORIGIN_TRANSFORMS::ABS_Y_COORD ); m_posY.SetCoordType( ORIGIN_TRANSFORMS::ABS_Y_COORD );
m_fields = new PCB_FIELDS_GRID_TABLE( m_frame, this, { m_embeddedFiles->GetLocalFiles() } ); std::vector<EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( m_embeddedFiles->GetLocalFiles() );
embeddedFilesStack.push_back( m_frame->GetBoard()->GetEmbeddedFiles() );
m_fields = new PCB_FIELDS_GRID_TABLE( m_frame, this, embeddedFilesStack );
m_delayedErrorMessage = wxEmptyString; m_delayedErrorMessage = wxEmptyString;
m_delayedFocusGrid = nullptr; m_delayedFocusGrid = nullptr;

View File

@ -34,9 +34,9 @@
#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 <widgets/std_bitmap_button.h> #include <widgets/std_bitmap_button.h>
#include <board.h>
#include <footprint.h> #include <footprint.h>
#include <fp_lib_table.h> #include <fp_lib_table.h>
#include <footprint.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>
@ -379,8 +379,11 @@ void PANEL_FP_PROPERTIES_3D_MODEL::OnAdd3DModel( wxCommandEvent& )
// if libraryName is not found in table, do nothing // if libraryName is not found in table, do nothing
} }
std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( m_filesPanel->GetLocalFiles() );
embeddedFilesStack.push_back( m_frame->GetBoard()->GetEmbeddedFiles() );
wxString fullPath = res->ResolvePath( model.m_Filename, footprintBasePath, nullptr ); wxString fullPath = res->ResolvePath( model.m_Filename, footprintBasePath, embeddedFilesStack );
wxFileName fname( fullPath ); wxFileName fname( fullPath );
EMBEDDED_FILES::EMBEDDED_FILE* result = m_filesPanel->AddEmbeddedFile( fname.GetFullPath() ); ; EMBEDDED_FILES::EMBEDDED_FILE* result = m_filesPanel->AddEmbeddedFile( fname.GetFullPath() ); ;
@ -532,7 +535,11 @@ MODEL_VALIDATE_ERRORS PANEL_FP_PROPERTIES_3D_MODEL::validateModelExists( const w
if( fpRow ) if( fpRow )
footprintBasePath = fpRow->GetFullURI( true ); footprintBasePath = fpRow->GetFullURI( true );
wxString fullPath = resolv->ResolvePath( aFilename, footprintBasePath, m_footprint ); std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( m_filesPanel->GetLocalFiles() );
embeddedFilesStack.push_back( m_frame->GetBoard()->GetEmbeddedFiles() );
wxString fullPath = resolv->ResolvePath( aFilename, footprintBasePath, embeddedFilesStack );
if( fullPath.IsEmpty() ) if( fullPath.IsEmpty() )
return MODEL_VALIDATE_ERRORS::RESOLVE_FAIL; return MODEL_VALIDATE_ERRORS::RESOLVE_FAIL;

View File

@ -437,7 +437,11 @@ static void idf_export_footprint( BOARD* aPcb, FOOTPRINT* aFootprint, IDF3_BOARD
continue; continue;
} }
idfFile.Assign( resolver->ResolvePath( sM->m_Filename, footprintBasePath, aFootprint ) ); std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( aFootprint->GetEmbeddedFiles() );
embeddedFilesStack.push_back( aPcb->GetEmbeddedFiles() );
idfFile.Assign( resolver->ResolvePath( sM->m_Filename, footprintBasePath, embeddedFilesStack ) );
idfExt = idfFile.GetExt(); idfExt = idfFile.GetExt();
if( idfExt.Cmp( wxT( "idf" ) ) && idfExt.Cmp( wxT( "IDF" ) ) ) if( idfExt.Cmp( wxT( "idf" ) ) && idfExt.Cmp( wxT( "IDF" ) ) )

View File

@ -1044,7 +1044,11 @@ void EXPORTER_PCB_VRML::ExportVrmlFootprint( FOOTPRINT* aFootprint, std::ostream
continue; continue;
} }
SGNODE* mod3d = (SGNODE*) m_Cache3Dmodels->Load( sM->m_Filename, footprintBasePath, aFootprint ); std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( aFootprint->GetEmbeddedFiles() );
embeddedFilesStack.push_back( m_board->GetEmbeddedFiles() );
SGNODE* mod3d = (SGNODE*) m_Cache3Dmodels->Load( sM->m_Filename, footprintBasePath, embeddedFilesStack );
if( nullptr == mod3d ) if( nullptr == mod3d )
{ {
@ -1109,8 +1113,12 @@ 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 = std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
m_Cache3Dmodels->GetResolver()->ResolvePath( sM->m_Filename, footprintBasePath, aFootprint ); embeddedFilesStack.push_back( aFootprint->GetEmbeddedFiles() );
embeddedFilesStack.push_back( m_board->GetEmbeddedFiles() );
wxFileName srcFile = m_Cache3Dmodels->GetResolver()->ResolvePath( sM->m_Filename, footprintBasePath,
embeddedFilesStack );
wxFileName dstFile; wxFileName dstFile;
dstFile.SetPath( m_Subdir3DFpModels ); dstFile.SetPath( m_Subdir3DFpModels );
dstFile.SetName( srcFile.GetName() ); dstFile.SetName( srcFile.GetName() );

View File

@ -360,8 +360,11 @@ bool EXPORTER_STEP::buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOri
continue; continue;
std::vector<wxString> searchedPaths; std::vector<wxString> searchedPaths;
wxString mname = m_resolver->ResolvePath( fp_model.m_Filename, footprintBasePath, aFootprint ); std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
embeddedFilesStack.push_back( aFootprint->GetEmbeddedFiles() );
embeddedFilesStack.push_back( m_board->GetEmbeddedFiles() );
wxString mname = m_resolver->ResolvePath( fp_model.m_Filename, footprintBasePath, embeddedFilesStack );
if( mname.empty() || !wxFileName::FileExists( mname ) ) if( mname.empty() || !wxFileName::FileExists( mname ) )
{ {

View File

@ -53,7 +53,7 @@ void PCB_EDIT_FRAME::LoadDrawingSheet()
wxString filename = resolver.ResolvePath( project.m_BoardDrawingSheetFile, wxString filename = resolver.ResolvePath( project.m_BoardDrawingSheetFile,
Prj().GetProjectPath(), Prj().GetProjectPath(),
GetBoard()->GetEmbeddedFiles() ); { GetBoard()->GetEmbeddedFiles() } );
wxString msg; wxString msg;

View File

@ -2431,7 +2431,7 @@ void PCBNEW_JOBS_HANDLER::loadOverrideDrawingSheet( BOARD* aBrd, const wxString&
wxString filename = resolver.ResolvePath( BASE_SCREEN::m_DrawingSheetFileName, wxString filename = resolver.ResolvePath( BASE_SCREEN::m_DrawingSheetFileName,
aBrd->GetProject()->GetProjectPath(), aBrd->GetProject()->GetProjectPath(),
aBrd->GetEmbeddedFiles() ); { aBrd->GetEmbeddedFiles() } );
wxString msg; wxString msg;
if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( filename, &msg ) ) if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( filename, &msg ) )

View File

@ -211,7 +211,7 @@ BOARD* LoadBoard( const wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, boo
wxString filename = resolver.ResolvePath( BASE_SCREEN::m_DrawingSheetFileName, wxString filename = resolver.ResolvePath( BASE_SCREEN::m_DrawingSheetFileName,
project->GetProjectPath(), project->GetProjectPath(),
brd->GetEmbeddedFiles() ); { brd->GetEmbeddedFiles() } );
wxString msg; wxString msg;