From 524575a595efb225cdf74b3cca241e10b86b5050 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Thu, 24 Apr 2025 11:33:02 +0100 Subject: [PATCH] Allow embedded files to come from components as well as parent containers, part II. Fixes https://gitlab.com/kicad/code/kicad/-/issues/20210 --- 3d-viewer/3d_cache/3d_cache.cpp | 13 ++++----- 3d-viewer/3d_cache/3d_cache.h | 12 +++++---- 3d-viewer/3d_canvas/eda_3d_canvas.cpp | 4 +-- .../3d_model_viewer/eda_3d_model_viewer.cpp | 2 +- .../3d_rendering/opengl/create_scene.cpp | 15 ++++++----- .../3d_rendering/raytracing/create_scene.cpp | 8 ++++-- 3d-viewer/dialogs/panel_preview_3d_model.cpp | 2 ++ common/dialogs/dialog_page_settings.cpp | 2 +- common/filename_resolver.cpp | 13 ++++++--- eeschema/dialogs/dialog_sim_model.cpp | 21 +++++++++------ eeschema/dialogs/dialog_sim_model.h | 18 ++++++------- eeschema/eeschema_config.cpp | 4 +-- eeschema/eeschema_jobs_handler.cpp | 2 +- eeschema/erc/erc.cpp | 2 +- .../netlist_exporter_spice.cpp | 5 +++- eeschema/sch_edit_frame.cpp | 11 +++++--- eeschema/sch_field.cpp | 11 ++++++-- eeschema/sch_symbol.cpp | 15 ++++++++++- eeschema/sch_symbol.h | 6 +++++ eeschema/sim/sim_lib_mgr.cpp | 10 ++++--- eeschema/sim/sim_lib_mgr.h | 6 ++--- eeschema/sim/sim_model.cpp | 18 ++++++++----- eeschema/sim/sim_model_ibis.cpp | 12 ++++++--- eeschema/sim/simulator_frame_ui.cpp | 11 ++++++-- eeschema/tools/sch_editor_control.cpp | 13 ++++++--- include/filename_resolver.h | 5 ++-- pcbnew/board.cpp | 27 ++++++++++++------- pcbnew/board.h | 7 ++++- .../dialogs/dialog_footprint_properties.cpp | 6 ++++- .../dialogs/panel_fp_properties_3d_model.cpp | 13 ++++++--- pcbnew/exporters/export_idf.cpp | 6 ++++- pcbnew/exporters/exporter_vrml.cpp | 14 +++++++--- pcbnew/exporters/step/exporter_step.cpp | 5 +++- pcbnew/pcbnew_config.cpp | 2 +- pcbnew/pcbnew_jobs_handler.cpp | 2 +- .../scripting/pcbnew_scripting_helpers.cpp | 4 +-- 36 files changed, 225 insertions(+), 102 deletions(-) diff --git a/3d-viewer/3d_cache/3d_cache.cpp b/3d-viewer/3d_cache/3d_cache.cpp index c3d8fd7c99..a59c10a4a6 100644 --- a/3d-viewer/3d_cache/3d_cache.cpp +++ b/3d-viewer/3d_cache/3d_cache.cpp @@ -141,12 +141,13 @@ S3D_CACHE::~S3D_CACHE() SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePath, - S3D_CACHE_ENTRY** aCachePtr, const EMBEDDED_FILES* aEmbeddedFiles ) + S3D_CACHE_ENTRY** aCachePtr, + std::vector aEmbeddedFilesStack ) { if( aCachePtr ) *aCachePtr = nullptr; - wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile, aBasePath, aEmbeddedFiles ); + wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile, aBasePath, aEmbeddedFilesStack ); 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, - const EMBEDDED_FILES* aEmbeddedFiles ) + std::vector 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, - const EMBEDDED_FILES* aEmbeddedFiles ) + std::vector aEmbeddedFilesStack ) { S3D_CACHE_ENTRY* cp = nullptr; - SCENEGRAPH* sp = load( aModelFileName, aBasePath, &cp, aEmbeddedFiles ); + SCENEGRAPH* sp = load( aModelFileName, aBasePath, &cp, aEmbeddedFilesStack ); if( !sp ) return nullptr; diff --git a/3d-viewer/3d_cache/3d_cache.h b/3d-viewer/3d_cache/3d_cache.h index 8d40187f9d..318eae4b3e 100644 --- a/3d-viewer/3d_cache/3d_cache.h +++ b/3d-viewer/3d_cache/3d_cache.h @@ -95,11 +95,12 @@ public: * * @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 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. */ SCENEGRAPH* Load( const wxString& aModelFile, const wxString& aBasePath, - const EMBEDDED_FILES* aEmbeddedFiles ); + std::vector aEmbeddedFilesStack ); FILENAME_RESOLVER* GetResolver() noexcept; @@ -128,11 +129,12 @@ public: * * @param aModelFileName is the full path to the model to be loaded. * @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. */ S3DMODEL* GetModel( const wxString& aModelFileName, const wxString& aBasePath, - const EMBEDDED_FILES* aEmbeddedFiles ); + std::vector aEmbeddedFilesStack ); /** * 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) SCENEGRAPH* load( const wxString& aModelFile, const wxString& aBasePath, S3D_CACHE_ENTRY** aCachePtr = nullptr, - const EMBEDDED_FILES* aEmbeddedFiles = nullptr ); + std::vector aEmbeddedFilesStack = {} ); /// Cache entries. std::list< S3D_CACHE_ENTRY* > m_CacheList; diff --git a/3d-viewer/3d_canvas/eda_3d_canvas.cpp b/3d-viewer/3d_canvas/eda_3d_canvas.cpp index ad18a048f2..9520f76c63 100644 --- a/3d-viewer/3d_canvas/eda_3d_canvas.cpp +++ b/3d-viewer/3d_canvas/eda_3d_canvas.cpp @@ -451,7 +451,7 @@ void EDA_3D_CANVAS::DoRePaint() 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 ) { 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; } - // 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 ) { const bool was_camera_changed = m_camera.ParametersChanged(); diff --git a/3d-viewer/3d_model_viewer/eda_3d_model_viewer.cpp b/3d-viewer/3d_model_viewer/eda_3d_model_viewer.cpp index b4eb37352f..aa6aafe738 100644 --- a/3d-viewer/3d_model_viewer/eda_3d_model_viewer.cpp +++ b/3d-viewer/3d_model_viewer/eda_3d_model_viewer.cpp @@ -157,7 +157,7 @@ void EDA_3D_MODEL_VIEWER::Set3DModel( const wxString& aModelPathName) if( m_cacheManager ) { - const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName, wxEmptyString, nullptr ); + const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName, wxEmptyString, {} ); if( model ) Set3DModel( (const S3DMODEL &)*model ); diff --git a/3d-viewer/3d_rendering/opengl/create_scene.cpp b/3d-viewer/3d_rendering/opengl/create_scene.cpp index 03faa9666f..e8adeb472d 100644 --- a/3d-viewer/3d_rendering/opengl/create_scene.cpp +++ b/3d-viewer/3d_rendering/opengl/create_scene.cpp @@ -926,8 +926,8 @@ void RENDER_3D_OPENGL::load3dModels( REPORTER* aStatusReporter ) // Go for all footprints for( const FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() ) { - wxString libraryName = footprint->GetFPID().GetLibNickname(); - wxString footprintBasePath = wxEmptyString; + wxString libraryName = footprint->GetFPID().GetLibNickname(); + wxString footprintBasePath = wxEmptyString; if( m_boardAdapter.GetBoard()->GetProject() ) { @@ -965,10 +965,13 @@ void RENDER_3D_OPENGL::load3dModels( REPORTER* aStatusReporter ) if( !m_3dModelMap.contains( fp_model.m_Filename ) ) { // It is not present, try get it from cache - const S3DMODEL* modelPtr = - m_boardAdapter.Get3dCacheManager()->GetModel( fp_model.m_Filename, - footprintBasePath, - footprint ); + std::vector embeddedFilesStack; + embeddedFilesStack.push_back( footprint->GetEmbeddedFiles() ); + embeddedFilesStack.push_back( m_boardAdapter.GetBoard()->GetEmbeddedFiles() ); + + const S3DMODEL* modelPtr = m_boardAdapter.Get3dCacheManager()->GetModel( fp_model.m_Filename, + footprintBasePath, + embeddedFilesStack ); // only add it if the return is not NULL if( modelPtr ) diff --git a/3d-viewer/3d_rendering/raytracing/create_scene.cpp b/3d-viewer/3d_rendering/raytracing/create_scene.cpp index a5c60ceb28..04bc83c677 100644 --- a/3d-viewer/3d_rendering/raytracing/create_scene.cpp +++ b/3d-viewer/3d_rendering/raytracing/create_scene.cpp @@ -1291,8 +1291,12 @@ void RENDER_3D_RAYTRACE_BASE::load3DModels( CONTAINER_3D& aDstContainer, continue; // get it from cache - const S3DMODEL* modelPtr = - cacheMgr->GetModel( model.m_Filename, footprintBasePath, fp ); + std::vector embeddedFilesStack; + 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. if( modelPtr ) diff --git a/3d-viewer/dialogs/panel_preview_3d_model.cpp b/3d-viewer/dialogs/panel_preview_3d_model.cpp index e68fe232d1..56ad6b41ed 100644 --- a/3d-viewer/dialogs/panel_preview_3d_model.cpp +++ b/3d-viewer/dialogs/panel_preview_3d_model.cpp @@ -27,6 +27,7 @@ #include "panel_preview_3d_model.h" #include #include <3d_canvas/eda_3d_canvas.h> +#include <3d_rendering/opengl/render_3d_opengl.h> #include #include #include @@ -64,6 +65,7 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM m_dummyBoard = new BOARD(); m_dummyBoard->SetProject( &aFrame->Prj(), true ); + m_dummyBoard->SetEmbeddedFilesDelegate( aFrame->GetBoard() ); // This board will only be used to hold a footprint for viewing m_dummyBoard->SetBoardUse( BOARD_USE::FPHOLDER ); diff --git a/common/dialogs/dialog_page_settings.cpp b/common/dialogs/dialog_page_settings.cpp index 0b99103d27..5260e659b1 100644 --- a/common/dialogs/dialog_page_settings.cpp +++ b/common/dialogs/dialog_page_settings.cpp @@ -477,7 +477,7 @@ bool DIALOG_PAGES_SETTINGS::SavePageSettings() if( fileName != BASE_SCREEN::m_DrawingSheetFileName ) { wxString fullFileName = m_filenameResolver->ResolvePath( fileName, m_projectPath, - m_embeddedFiles ); + { m_embeddedFiles } ); BASE_SCREEN::m_DrawingSheetFileName = fileName; diff --git a/common/filename_resolver.cpp b/common/filename_resolver.cpp index 0fdc1b376c..6a7fe24fbf 100644 --- a/common/filename_resolver.cpp +++ b/common/filename_resolver.cpp @@ -244,7 +244,7 @@ bool FILENAME_RESOLVER::UpdatePathList( const std::vector< SEARCH_PATH >& aPathL wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName, const wxString& aWorkingPath, - const EMBEDDED_FILES* aFiles ) + std::vector aEmbeddedFilesStack ) { std::lock_guard 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. if( tname.StartsWith( FILEEXT::KiCadUriPrefix + "://" ) ) { - if( !aFiles ) + if( aEmbeddedFilesStack.empty() ) { wxLogTrace( wxT( "KICAD_EMBED" ), wxT( "No EMBEDDED_FILES object provided for kicad_embed URI" ) ); return wxEmptyString; } - wxString path = tname.Mid( 14 ); - wxFileName temp_file = aFiles->GetTemporaryFileName( path ); + wxString path = tname.Mid( wxString( FILEEXT::KiCadUriPrefix + "://" ).length() ); + + 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() ) { diff --git a/eeschema/dialogs/dialog_sim_model.cpp b/eeschema/dialogs/dialog_sim_model.cpp index 2a992b98c9..dadd8c5f75 100644 --- a/eeschema/dialogs/dialog_sim_model.cpp +++ b/eeschema/dialogs/dialog_sim_model.cpp @@ -69,8 +69,8 @@ DIALOG_SIM_MODEL::DIALOG_SIM_MODEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame m_frame( aFrame ), m_symbol( aSymbol ), m_fields( aFields ), - m_libraryModelsMgr( &Prj(), nullptr ), - m_builtinModelsMgr( &Prj(), nullptr ), + m_libraryModelsMgr( &Prj() ), + m_builtinModelsMgr( &Prj() ), m_prevModel( nullptr ), m_curModelType( SIM_MODEL::TYPE::NONE ), m_scintillaTricksCode( nullptr ), @@ -83,12 +83,15 @@ DIALOG_SIM_MODEL::DIALOG_SIM_MODEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame m_infoBar->AddCloseButton(); if constexpr (std::is_same_v) - m_files = aSymbol.Schematic(); - else - m_files = &aSymbol; + { + SCH_SYMBOL* symbol = static_cast( &aSymbol ); + m_filesStack.push_back( symbol->Schematic()->GetEmbeddedFiles() ); + } - m_libraryModelsMgr.SetFiles( m_files ); - m_builtinModelsMgr.SetFiles( m_files ); + m_filesStack.push_back( aSymbol.GetEmbeddedFiles() ); + + m_libraryModelsMgr.SetFilesStack( m_filesStack ); + m_builtinModelsMgr.SetFilesStack( m_filesStack ); for( SCH_PIN* pin : aSymbol.GetPins() ) { @@ -1256,11 +1259,13 @@ void DIALOG_SIM_MODEL::onBrowseButtonClick( wxCommandEvent& aEvent ) 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(); } else if( fn.MakeRelativeTo( Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith( wxS( ".." ) ) ) + { path = fn.GetFullPath(); + } WX_STRING_REPORTER reporter; diff --git a/eeschema/dialogs/dialog_sim_model.h b/eeschema/dialogs/dialog_sim_model.h index 40601fb05c..bb421147df 100644 --- a/eeschema/dialogs/dialog_sim_model.h +++ b/eeschema/dialogs/dialog_sim_model.h @@ -125,17 +125,17 @@ private: bool isIbisLoaded() { return dynamic_cast( library() ); } private: - EDA_BASE_FRAME* m_frame; - T& m_symbol; - std::vector& m_fields; + EDA_BASE_FRAME* m_frame; + T& m_symbol; + std::vector& m_fields; - EMBEDDED_FILES* m_files; - SIM_LIB_MGR m_libraryModelsMgr; - SIM_LIB_MGR m_builtinModelsMgr; - wxString m_prevLibrary; - const SIM_MODEL* m_prevModel; + std::vector m_filesStack; + SIM_LIB_MGR m_libraryModelsMgr; + SIM_LIB_MGR m_builtinModelsMgr; + wxString m_prevLibrary; + const SIM_MODEL* m_prevModel; - std::map m_modelListBoxEntryToLibraryIdx; + std::map m_modelListBoxEntryToLibraryIdx; std::vector m_sortedPartPins; ///< Pins of the current part. std::map m_curModelTypeOfDeviceType; diff --git a/eeschema/eeschema_config.cpp b/eeschema/eeschema_config.cpp index 43b339af23..6cc0fe90c2 100644 --- a/eeschema/eeschema_config.cpp +++ b/eeschema/eeschema_config.cpp @@ -93,7 +93,7 @@ void SCH_EDIT_FRAME::LoadDrawingSheet() wxString filename = resolver.ResolvePath( settings.m_SchDrawingSheetFileName, Prj().GetProjectPath(), - Schematic().GetEmbeddedFiles() ); + { Schematic().GetEmbeddedFiles() } ); wxString 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, Prj().GetProjectPath(), - Schematic().GetEmbeddedFiles() ) ); + { Schematic().GetEmbeddedFiles() } ) ); bool success = true; diff --git a/eeschema/eeschema_jobs_handler.cpp b/eeschema/eeschema_jobs_handler.cpp index 8224ff7101..43320a09a1 100644 --- a/eeschema/eeschema_jobs_handler.cpp +++ b/eeschema/eeschema_jobs_handler.cpp @@ -224,7 +224,7 @@ void EESCHEMA_JOBS_HANDLER::InitRenderSettings( SCH_RENDER_SETTINGS* aRenderSett resolve.SetProgramBase( &Pgm() ); wxString absolutePath = resolve.ResolvePath( path, wxGetCwd(), - aSch->GetEmbeddedFiles() ); + { aSch->GetEmbeddedFiles() } ); if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( absolutePath, &msg ) ) { diff --git a/eeschema/erc/erc.cpp b/eeschema/erc/erc.cpp index 786b26f943..29b11c7f27 100644 --- a/eeschema/erc/erc.cpp +++ b/eeschema/erc/erc.cpp @@ -1740,7 +1740,7 @@ int ERC_TESTER::TestSimModelIssues() { WX_STRING_REPORTER reporter; 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 ) { diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.cpp b/eeschema/netlist_exporters/netlist_exporter_spice.cpp index 3cb4c4e96a..276970799d 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_spice.cpp @@ -63,8 +63,11 @@ std::string NAME_GENERATOR::Generate( const std::string& aProposedName ) NETLIST_EXPORTER_SPICE::NETLIST_EXPORTER_SPICE( SCHEMATIC* aSchematic ) : NETLIST_EXPORTER_BASE( aSchematic ), - m_libMgr( &aSchematic->Prj(), aSchematic ) + m_libMgr( &aSchematic->Prj() ) { + std::vector embeddedFilesStack; + embeddedFilesStack.push_back( aSchematic->GetEmbeddedFiles() ); + m_libMgr.SetFilesStack( embeddedFilesStack ); } diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp index 585322a6be..b390cfd3a7 100644 --- a/eeschema/sch_edit_frame.cpp +++ b/eeschema/sch_edit_frame.cpp @@ -1516,7 +1516,7 @@ void SCH_EDIT_FRAME::OnExit( wxCommandEvent& event ) void SCH_EDIT_FRAME::RefreshOperatingPointDisplay() { SCHEMATIC_SETTINGS& settings = m_schematic->Settings(); - SIM_LIB_MGR simLibMgr( &Prj(), &Schematic() ); + SIM_LIB_MGR simLibMgr( &Prj() ); NULL_REPORTER devnull; // Patch for bug early in V7.99 dev @@ -1608,8 +1608,13 @@ void SCH_EDIT_FRAME::RefreshOperatingPointDisplay() } else { - SIM_MODEL& model = simLibMgr.CreateModel( &GetCurrentSheet(), *symbol, - devnull ).model; + std::vector embeddedFilesStack; + 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; spiceItem.refName = ref; diff --git a/eeschema/sch_field.cpp b/eeschema/sch_field.cpp index e8899e5760..5007bcae61 100644 --- a/eeschema/sch_field.cpp +++ b/eeschema/sch_field.cpp @@ -749,8 +749,15 @@ void SCH_FIELD::OnScintillaCharAdded( SCINTILLA_TRICKS* aScintillaTricks, { NULL_REPORTER devnull; SCH_SHEET_PATH& sheet = schematic->CurrentSheet(); - SIM_LIB_MGR mgr( &schematic->Prj(), schematic ); - SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, devnull ).model; + SIM_LIB_MGR mgr( &schematic->Prj() ); + + std::vector embeddedFilesStack; + embeddedFilesStack.push_back( schematic->GetEmbeddedFiles() ); + embeddedFilesStack.push_back( symbol->GetEmbeddedFiles() ); + + mgr.SetFilesStack( embeddedFilesStack ); + + SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, devnull ).model; for( wxString pin : model.GetPinNames() ) { diff --git a/eeschema/sch_symbol.cpp b/eeschema/sch_symbol.cpp index 8157fc930b..8432d3195a 100644 --- a/eeschema/sch_symbol.cpp +++ b/eeschema/sch_symbol.cpp @@ -1311,7 +1311,14 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i if( range.IsEmpty() ) range = wxS( "~A" ); - SIM_LIB_MGR simLibMgr( &schematic->Prj(), schematic ); + SIM_LIB_MGR simLibMgr( &schematic->Prj() ); + + std::vector embeddedFilesStack; + embeddedFilesStack.push_back( schematic->GetEmbeddedFiles() ); + embeddedFilesStack.push_back( GetLibSymbolRef()->GetEmbeddedFiles() ); + + simLibMgr.SetFilesStack( embeddedFilesStack ); + NULL_REPORTER devnull; SIM_MODEL& model = simLibMgr.CreateModel( aPath, const_cast( *this ), 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 ) { int dx = m_pos.x; diff --git a/eeschema/sch_symbol.h b/eeschema/sch_symbol.h index cffbc557bc..0b905515ec 100644 --- a/eeschema/sch_symbol.h +++ b/eeschema/sch_symbol.h @@ -684,6 +684,12 @@ public: /// Set the selected unit of this symbol for all sheets. 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 { if( aMoveVector == VECTOR2I( 0, 0 ) ) diff --git a/eeschema/sim/sim_lib_mgr.cpp b/eeschema/sim/sim_lib_mgr.cpp index 321f9d4677..ae3f7b6be0 100644 --- a/eeschema/sim/sim_lib_mgr.cpp +++ b/eeschema/sim/sim_lib_mgr.cpp @@ -41,8 +41,7 @@ using namespace std::placeholders; -SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT* aPrj, EMBEDDED_FILES* aFiles ) : - m_files( aFiles ), +SIM_LIB_MGR::SIM_LIB_MGR( const PROJECT* aPrj ) : m_project( aPrj ), m_forceFullParse( false ) { @@ -62,7 +61,12 @@ wxString SIM_LIB_MGR::ResolveLibraryPath( const wxString& aLibraryPath, REPORTER resolver.SetProject( m_project ); - wxString expandedPath = resolver.ResolvePath( aLibraryPath, wxEmptyString, m_files ); + std::vector embeddedFilesStack; + + for( const EMBEDDED_FILES* embeddedFiles : m_embeddedFilesStack ) + embeddedFilesStack.push_back( embeddedFiles ); + + wxString expandedPath = resolver.ResolvePath( aLibraryPath, wxEmptyString, embeddedFilesStack ); wxFileName fn( expandedPath ); diff --git a/eeschema/sim/sim_lib_mgr.h b/eeschema/sim/sim_lib_mgr.h index 81885e5783..1b5549e857 100644 --- a/eeschema/sim/sim_lib_mgr.h +++ b/eeschema/sim/sim_lib_mgr.h @@ -39,14 +39,14 @@ class SCH_SYMBOL; class SIM_LIB_MGR { public: - SIM_LIB_MGR( const PROJECT* aPrj, EMBEDDED_FILES* aFiles ); + SIM_LIB_MGR( const PROJECT* aPrj ); virtual ~SIM_LIB_MGR() = default; void SetForceFullParse() { m_forceFullParse = true; } void Clear(); - void SetFiles( EMBEDDED_FILES* aFiles ) { m_files = aFiles; } + void SetFilesStack( std::vector aFilesStack ) { m_embeddedFilesStack = aFilesStack; } void SetLibrary( const wxString& aLibraryPath, REPORTER& aReporter ); @@ -83,7 +83,7 @@ public: REPORTER& aReporter ); private: - EMBEDDED_FILES* m_files; + std::vector m_embeddedFilesStack; const PROJECT* m_project; bool m_forceFullParse; std::map> m_libraries; diff --git a/eeschema/sim/sim_model.cpp b/eeschema/sim/sim_model.cpp index 8691fdfd83..c8b8cace90 100644 --- a/eeschema/sim/sim_model.cpp +++ b/eeschema/sim/sim_model.cpp @@ -1668,14 +1668,20 @@ void SIM_MODEL::MigrateSimModel( T& aSymbol, const PROJECT* aProject ) if( !lib.IsEmpty() ) { - WX_STRING_REPORTER reporter; - SIM_LIB_MGR libMgr( aProject, nullptr ); - std::vector emptyFields; + WX_STRING_REPORTER reporter; + SIM_LIB_MGR libMgr( aProject ); + std::vector emptyFields; + std::vector embeddedFilesStack; if constexpr (std::is_same_v) - libMgr.SetFiles( aSymbol.Schematic() ); - else - libMgr.SetFiles( &aSymbol ); + { + SCH_SYMBOL* symbol = static_cast( &aSymbol ); + embeddedFilesStack.push_back( symbol->Schematic()->GetEmbeddedFiles() ); + } + + embeddedFilesStack.push_back( aSymbol.GetEmbeddedFiles() ); + + libMgr.SetFilesStack( embeddedFilesStack ); // Pull out any following parameters from model name model = model.BeforeFirst( ' ', &modelLineParams ); diff --git a/eeschema/sim/sim_model_ibis.cpp b/eeschema/sim/sim_model_ibis.cpp index 5f732df3d6..76a6d281a9 100644 --- a/eeschema/sim/sim_model_ibis.cpp +++ b/eeschema/sim/sim_model_ibis.cpp @@ -53,8 +53,7 @@ std::vector SPICE_GENERATOR_IBIS::CurrentNames( const SPICE_ITEM& a std::string SPICE_GENERATOR_IBIS::IbisDevice( const SPICE_ITEM& aItem, SCHEMATIC* aSchematic, - const wxString& aCacheDir, - REPORTER& aReporter ) const + const wxString& aCacheDir, REPORTER& aReporter ) const { std::string ibisLibFilename = GetFieldValue( &aItem.fields, SIM_LIBRARY::LIBRARY_FIELD ); std::string ibisCompName = GetFieldValue( &aItem.fields, SIM_LIBRARY::NAME_FIELD ); @@ -63,8 +62,13 @@ std::string SPICE_GENERATOR_IBIS::IbisDevice( const SPICE_ITEM& aItem, SCHEMATIC bool diffMode = GetFieldValue( &aItem.fields, SIM_LIBRARY_IBIS::DIFF_FIELD ) == "1"; WX_STRING_REPORTER reporter; - SIM_LIB_MGR mgr( &aSchematic->Prj(), aSchematic ); - wxString path = mgr.ResolveLibraryPath( ibisLibFilename, reporter ); + SIM_LIB_MGR mgr( &aSchematic->Prj() ); + + std::vector embeddedFilesStack; + embeddedFilesStack.push_back( aSchematic->GetEmbeddedFiles() ); + mgr.SetFilesStack( embeddedFilesStack ); + + wxString path = mgr.ResolveLibraryPath( ibisLibFilename, reporter ); if( reporter.HasMessage() ) THROW_IO_ERROR( reporter.GetMessages() ); diff --git a/eeschema/sim/simulator_frame_ui.cpp b/eeschema/sim/simulator_frame_ui.cpp index a1d50551c3..b3eb8bad92 100644 --- a/eeschema/sim/simulator_frame_ui.cpp +++ b/eeschema/sim/simulator_frame_ui.cpp @@ -1664,8 +1664,15 @@ void SIMULATOR_FRAME_UI::UpdateTunerValue( const SCH_SHEET_PATH& aSheetPath, con } NULL_REPORTER devnull; - SIM_LIB_MGR mgr( &m_schematicFrame->Prj(), &m_schematicFrame->Schematic() ); - SIM_MODEL& model = mgr.CreateModel( &aSheetPath, *symbol, devnull ).model; + SIM_LIB_MGR mgr( &m_schematicFrame->Prj() ); + + std::vector 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; const SIM_MODEL::PARAM* tunerParam = model.GetTunerParam(); diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index 54bf870bcf..eb993d0816 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -580,17 +580,22 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent ) SCH_SYMBOL* symbol = static_cast( item->GetParent() ); WX_STRING_REPORTER reporter; - SIM_LIB_MGR mgr( &m_frame->Prj(), &m_frame->Schematic() ); + SIM_LIB_MGR mgr( &m_frame->Prj() ); - SIM_MODEL& model = mgr.CreateModel( &sheet, *symbol, reporter ).model; + std::vector 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; if( reporter.HasMessage() ) THROW_IO_ERROR( reporter.GetMessages() ); SPICE_ITEM spiceItem; spiceItem.refName = symbol->GetRef( &sheet ).ToStdString(); - std::vector currentNames = - model.SpiceGenerator().CurrentNames( spiceItem ); + std::vector currentNames = model.SpiceGenerator().CurrentNames( spiceItem ); if( currentNames.size() == 0 ) { diff --git a/include/filename_resolver.h b/include/filename_resolver.h index 21b5afd22c..4761a5d395 100644 --- a/include/filename_resolver.h +++ b/include/filename_resolver.h @@ -100,10 +100,11 @@ public: * * @param aFileName The configured file path to resolve. * @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, - const EMBEDDED_FILES* aFiles ); + std::vector aEmbeddedFilesStack ); /** * Produce a relative path based on the existing search directories or returns the same path diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index 3e5fe6f7a4..5459157052 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -74,11 +74,20 @@ VECTOR2I BOARD_ITEM::ZeroOffset( 0, 0 ); BOARD::BOARD() : - BOARD_ITEM_CONTAINER( (BOARD_ITEM*) nullptr, PCB_T ), m_LegacyDesignSettingsLoaded( false ), - m_LegacyCopperEdgeClearanceLoaded( false ), m_LegacyNetclassesLoaded( false ), 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_componentClassManager( std::make_unique( this ) ), + BOARD_ITEM_CONTAINER( (BOARD_ITEM*) nullptr, PCB_T ), + m_LegacyDesignSettingsLoaded( false ), + m_LegacyCopperEdgeClearanceLoaded( false ), + m_LegacyNetclassesLoaded( false ), + 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( this ) ), m_lengthDelayCalc( std::make_unique( this ) ) { // 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() { - if( IsFootprintHolder() ) - return static_cast( GetFirstFootprint() ); + if( m_embeddedFilesDelegate ) + return static_cast( m_embeddedFilesDelegate ); return static_cast( this ); } @@ -2582,8 +2591,8 @@ EMBEDDED_FILES* BOARD::GetEmbeddedFiles() const EMBEDDED_FILES* BOARD::GetEmbeddedFiles() const { - if( IsFootprintHolder() ) - return static_cast( GetFirstFootprint() ); + if( m_embeddedFilesDelegate ) + return static_cast( m_embeddedFilesDelegate ); return static_cast( this ); } diff --git a/pcbnew/board.h b/pcbnew/board.h index b9b5a82b56..2a1138191c 100644 --- a/pcbnew/board.h +++ b/pcbnew/board.h @@ -1275,6 +1275,8 @@ public: EMBEDDED_FILES* GetEmbeddedFiles() override; const EMBEDDED_FILES* GetEmbeddedFiles() const; + void SetEmbeddedFilesDelegate( EMBEDDED_FILES* aDelegate ) { m_embeddedFilesDelegate = aDelegate; } + /** * Get the list of all outline fonts used in the board */ @@ -1413,8 +1415,11 @@ private: bool m_embedFonts; - std::unique_ptr 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 m_componentClassManager; std::unique_ptr m_lengthDelayCalc; }; diff --git a/pcbnew/dialogs/dialog_footprint_properties.cpp b/pcbnew/dialogs/dialog_footprint_properties.cpp index 8f83774055..340f8607c4 100644 --- a/pcbnew/dialogs/dialog_footprint_properties.cpp +++ b/pcbnew/dialogs/dialog_footprint_properties.cpp @@ -84,7 +84,11 @@ DIALOG_FOOTPRINT_PROPERTIES::DIALOG_FOOTPRINT_PROPERTIES( PCB_EDIT_FRAME* aParen m_posX.SetCoordType( ORIGIN_TRANSFORMS::ABS_X_COORD ); m_posY.SetCoordType( ORIGIN_TRANSFORMS::ABS_Y_COORD ); - m_fields = new PCB_FIELDS_GRID_TABLE( m_frame, this, { m_embeddedFiles->GetLocalFiles() } ); + std::vector 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_delayedFocusGrid = nullptr; diff --git a/pcbnew/dialogs/panel_fp_properties_3d_model.cpp b/pcbnew/dialogs/panel_fp_properties_3d_model.cpp index 24b660507c..a8991da118 100644 --- a/pcbnew/dialogs/panel_fp_properties_3d_model.cpp +++ b/pcbnew/dialogs/panel_fp_properties_3d_model.cpp @@ -34,9 +34,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -379,8 +379,11 @@ void PANEL_FP_PROPERTIES_3D_MODEL::OnAdd3DModel( wxCommandEvent& ) // if libraryName is not found in table, do nothing } + std::vector 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 ); 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 ) footprintBasePath = fpRow->GetFullURI( true ); - wxString fullPath = resolv->ResolvePath( aFilename, footprintBasePath, m_footprint ); + std::vector embeddedFilesStack; + embeddedFilesStack.push_back( m_filesPanel->GetLocalFiles() ); + embeddedFilesStack.push_back( m_frame->GetBoard()->GetEmbeddedFiles() ); + + wxString fullPath = resolv->ResolvePath( aFilename, footprintBasePath, embeddedFilesStack ); if( fullPath.IsEmpty() ) return MODEL_VALIDATE_ERRORS::RESOLVE_FAIL; diff --git a/pcbnew/exporters/export_idf.cpp b/pcbnew/exporters/export_idf.cpp index 253e178f9b..5ad51218b7 100644 --- a/pcbnew/exporters/export_idf.cpp +++ b/pcbnew/exporters/export_idf.cpp @@ -437,7 +437,11 @@ static void idf_export_footprint( BOARD* aPcb, FOOTPRINT* aFootprint, IDF3_BOARD continue; } - idfFile.Assign( resolver->ResolvePath( sM->m_Filename, footprintBasePath, aFootprint ) ); + std::vector embeddedFilesStack; + embeddedFilesStack.push_back( aFootprint->GetEmbeddedFiles() ); + embeddedFilesStack.push_back( aPcb->GetEmbeddedFiles() ); + + idfFile.Assign( resolver->ResolvePath( sM->m_Filename, footprintBasePath, embeddedFilesStack ) ); idfExt = idfFile.GetExt(); if( idfExt.Cmp( wxT( "idf" ) ) && idfExt.Cmp( wxT( "IDF" ) ) ) diff --git a/pcbnew/exporters/exporter_vrml.cpp b/pcbnew/exporters/exporter_vrml.cpp index c5e9441a0a..cbe64793d8 100644 --- a/pcbnew/exporters/exporter_vrml.cpp +++ b/pcbnew/exporters/exporter_vrml.cpp @@ -1044,7 +1044,11 @@ void EXPORTER_PCB_VRML::ExportVrmlFootprint( FOOTPRINT* aFootprint, std::ostream continue; } - SGNODE* mod3d = (SGNODE*) m_Cache3Dmodels->Load( sM->m_Filename, footprintBasePath, aFootprint ); + std::vector 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 ) { @@ -1109,8 +1113,12 @@ void EXPORTER_PCB_VRML::ExportVrmlFootprint( FOOTPRINT* aFootprint, std::ostream int old_precision = aOutputFile->precision(); aOutputFile->precision( m_precision ); - wxFileName srcFile = - m_Cache3Dmodels->GetResolver()->ResolvePath( sM->m_Filename, footprintBasePath, aFootprint ); + std::vector embeddedFilesStack; + embeddedFilesStack.push_back( aFootprint->GetEmbeddedFiles() ); + embeddedFilesStack.push_back( m_board->GetEmbeddedFiles() ); + + wxFileName srcFile = m_Cache3Dmodels->GetResolver()->ResolvePath( sM->m_Filename, footprintBasePath, + embeddedFilesStack ); wxFileName dstFile; dstFile.SetPath( m_Subdir3DFpModels ); dstFile.SetName( srcFile.GetName() ); diff --git a/pcbnew/exporters/step/exporter_step.cpp b/pcbnew/exporters/step/exporter_step.cpp index 919fdb6fa8..03b242dd3d 100644 --- a/pcbnew/exporters/step/exporter_step.cpp +++ b/pcbnew/exporters/step/exporter_step.cpp @@ -360,8 +360,11 @@ bool EXPORTER_STEP::buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOri continue; std::vector searchedPaths; - wxString mname = m_resolver->ResolvePath( fp_model.m_Filename, footprintBasePath, aFootprint ); + std::vector 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 ) ) { diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp index 1583754f88..78b74c8a20 100644 --- a/pcbnew/pcbnew_config.cpp +++ b/pcbnew/pcbnew_config.cpp @@ -53,7 +53,7 @@ void PCB_EDIT_FRAME::LoadDrawingSheet() wxString filename = resolver.ResolvePath( project.m_BoardDrawingSheetFile, Prj().GetProjectPath(), - GetBoard()->GetEmbeddedFiles() ); + { GetBoard()->GetEmbeddedFiles() } ); wxString msg; diff --git a/pcbnew/pcbnew_jobs_handler.cpp b/pcbnew/pcbnew_jobs_handler.cpp index 2e73df4cfe..74d53e3d48 100644 --- a/pcbnew/pcbnew_jobs_handler.cpp +++ b/pcbnew/pcbnew_jobs_handler.cpp @@ -2431,7 +2431,7 @@ void PCBNEW_JOBS_HANDLER::loadOverrideDrawingSheet( BOARD* aBrd, const wxString& wxString filename = resolver.ResolvePath( BASE_SCREEN::m_DrawingSheetFileName, aBrd->GetProject()->GetProjectPath(), - aBrd->GetEmbeddedFiles() ); + { aBrd->GetEmbeddedFiles() } ); wxString msg; if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( filename, &msg ) ) diff --git a/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp b/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp index 9f31fba06d..9e3065e46e 100644 --- a/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp +++ b/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp @@ -210,8 +210,8 @@ BOARD* LoadBoard( const wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, boo resolver.SetProgramBase( PgmOrNull() ); wxString filename = resolver.ResolvePath( BASE_SCREEN::m_DrawingSheetFileName, - project->GetProjectPath(), - brd->GetEmbeddedFiles() ); + project->GetProjectPath(), + { brd->GetEmbeddedFiles() } ); wxString msg;