diff --git a/3d-viewer/3d_cache/3d_cache.cpp b/3d-viewer/3d_cache/3d_cache.cpp index 365313c9f2..e2210a56c7 100644 --- a/3d-viewer/3d_cache/3d_cache.cpp +++ b/3d-viewer/3d_cache/3d_cache.cpp @@ -686,6 +686,13 @@ bool S3D_CACHE::SetProjectDir( const wxString& aProjDir ) } +void S3D_CACHE::SetProgramBase( PGM_BASE* aBase ) +{ + m_FNResolver->SetProgramBase( aBase ); + return; +} + + wxString S3D_CACHE::GetProjectDir( void ) { return m_FNResolver->GetProjectDir(); diff --git a/3d-viewer/3d_cache/3d_cache.h b/3d-viewer/3d_cache/3d_cache.h index 853d817916..d2bd760c5b 100644 --- a/3d-viewer/3d_cache/3d_cache.h +++ b/3d-viewer/3d_cache/3d_cache.h @@ -38,6 +38,7 @@ #include "plugins/3dapi/c3dmodel.h" +class PGM_BASE; class S3D_CACHE; class S3D_CACHE_ENTRY; class SCENEGRAPH; @@ -138,6 +139,14 @@ public: */ bool SetProjectDir( const wxString& aProjDir ); + /** + * Function SetProgramBase + * sets the filename resolver's pointer to the application's + * PGM_BASE instance; the pointer is used to extract the + * local env vars. + */ + void SetProgramBase( PGM_BASE* aBase ); + /** * Function GetProjectDir * returns the current project's working directory diff --git a/3d-viewer/3d_cache/3d_cache_wrapper.cpp b/3d-viewer/3d_cache/3d_cache_wrapper.cpp index 5beb9ca77c..f228412023 100644 --- a/3d-viewer/3d_cache/3d_cache_wrapper.cpp +++ b/3d-viewer/3d_cache/3d_cache_wrapper.cpp @@ -24,6 +24,7 @@ #include #include +#include #include "3d_cache_wrapper.h" static wxCriticalSection lock3D_wrapper; @@ -57,6 +58,7 @@ S3D_CACHE* PROJECT::Get3DCacheManager( bool updateProjDir ) wxFileName cfgpath; cfgpath.AssignDir( GetKicadConfigPath() ); cfgpath.AppendDir( wxT( "3d" ) ); + cache->SetProgramBase( &Pgm() ); cache->Set3DConfigDir( cfgpath.GetFullPath() ); SetElem( ELEM_3DCACHE, cw ); updateProjDir = true; diff --git a/3d-viewer/3d_cache/3d_filename_resolver.cpp b/3d-viewer/3d_cache/3d_filename_resolver.cpp index 2f5f583c8c..8c3098a8d1 100644 --- a/3d-viewer/3d_cache/3d_filename_resolver.cpp +++ b/3d-viewer/3d_cache/3d_filename_resolver.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "3d_filename_resolver.h" @@ -54,6 +55,7 @@ static bool getHollerith( const std::string& aString, size_t& aIndex, wxString& S3D_FILENAME_RESOLVER::S3D_FILENAME_RESOLVER() { m_errflags = 0; + m_pgm = NULL; } @@ -86,7 +88,7 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh if( false == projdir.DirExists() ) return false; - wxString path = projdir.GetPath(); + m_curProjDir = projdir.GetPath(); if( flgChanged ) *flgChanged = false; @@ -96,7 +98,7 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh S3D_ALIAS al; al.m_alias = _( "(DEFAULT)" ); al.m_pathvar = _( "${PROJDIR}" ); - al.m_pathexp = path; + al.m_pathexp = m_curProjDir; al.m_description = _( "Current project directory" ); m_Paths.push_back( al ); m_NameMap.clear(); @@ -107,9 +109,9 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh } else { - if( m_Paths.front().m_pathexp.Cmp( path ) ) + if( m_Paths.front().m_pathexp.Cmp( m_curProjDir ) ) { - m_Paths.front().m_pathexp = path; + m_Paths.front().m_pathexp = m_curProjDir; m_NameMap.clear(); if( flgChanged ) @@ -138,10 +140,22 @@ bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgCh wxString S3D_FILENAME_RESOLVER::GetProjectDir( void ) { - if( m_Paths.empty() ) - return wxEmptyString; + return m_curProjDir; +} - return m_Paths.front().m_pathexp; + +void S3D_FILENAME_RESOLVER::SetProgramBase( PGM_BASE* aBase ) +{ + m_pgm = aBase; + + if( NULL == m_pgm || m_Paths.empty() ) + return; + + // recreate the path list + m_Paths.clear(); + createPathList(); + + return; } @@ -157,15 +171,61 @@ bool S3D_FILENAME_RESOLVER::createPathList( void ) // the user may change this later with a call to SetProjectDir() S3D_ALIAS lpath; - lpath.m_alias = _( "(DEFAULT)" ); - lpath.m_pathvar = _( "${PROJDIR}" ); - lpath.m_description = _( "Current project directory" ); + lpath.m_alias = _( "${KIPRJMOD}" ); + lpath.m_pathvar = _( "${KIPRJMOD}" ); + lpath.m_pathexp = m_curProjDir; m_Paths.push_back( lpath ); + wxFileName fndummy; + wxUniChar psep = fndummy.GetPathSeparator(); - lpath.m_alias = wxT( "KISYS3DMOD" ); - lpath.m_pathvar = wxT( "${KISYS3DMOD}" ); - lpath.m_description = _( "Legacy 3D environment path" ); - addPath( lpath ); + // iterate over the list of internally defined ENV VARs + // and add existing paths to the resolver + if( m_pgm ) + { + ENV_VAR_MAP_CITER mS = m_pgm->GetLocalEnvVariables().begin(); + ENV_VAR_MAP_CITER mE = m_pgm->GetLocalEnvVariables().end(); + + while( mS != mE ) + { + // filter out URLs, template directories, and known system paths + if( mS->first == wxString( "KICAD_PTEMPLATES" ) + || mS->first == wxString( "KIGITHUB" ) + || mS->first == wxString( "KISYSMOD" ) ) + { + ++mS; + continue; + } + + if( wxString::npos != mS->second.GetValue().find( wxString( "://" ) ) ) + { + ++mS; + continue; + } + + fndummy.Assign( mS->second.GetValue(), "" ); + + if( !fndummy.DirExists() ) + { + ++mS; + continue; + } + + wxString tmp( "${" ); + tmp.Append( mS->first ); + tmp.Append( "}" ); + + lpath.m_alias = tmp; + lpath.m_pathvar = tmp; + lpath.m_pathexp = mS->second.GetValue(); + + if( !lpath.m_pathexp.empty() && psep == *lpath.m_pathexp.rbegin() ) + lpath.m_pathexp.erase( --lpath.m_pathexp.end() ); + + m_Paths.push_back( lpath ); + + ++mS; + } + } if( !m_ConfigDir.empty() ) readPathList(); @@ -191,7 +251,9 @@ bool S3D_FILENAME_RESOLVER::createPathList( void ) bool S3D_FILENAME_RESOLVER::UpdatePathList( std::vector< S3D_ALIAS >& aPathList ) { - while( m_Paths.size() > 2 ) + wxUniChar envMarker( '$' ); + + while( !m_Paths.empty() && envMarker != *m_Paths.back().m_alias.rbegin() ) m_Paths.pop_back(); size_t nI = aPathList.size(); @@ -258,6 +320,11 @@ wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName ) return tname; } + else if( resolveVirtualEnv( aFileName, tname ) ) + { + m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) ); + return tname; + } if( !( m_errflags & ERRFLG_ENVPATH ) ) { @@ -276,7 +343,8 @@ wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName ) // check the path relative to the current project directory; // note: this is not necessarily the same as the current working - // directory, which has already been checked + // directory, which has already been checked. This case accounts + // for partial paths which do not contain ${KIPRJMOD}. if( !sPL->m_pathexp.empty() ) { wxFileName fpath( wxFileName::DirName( sPL->m_pathexp ) ); @@ -295,28 +363,33 @@ wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName ) } } - ++sPL; // skip to item 2: KISYS3DMOD - - // check if the path is relative to KISYS3DMOD but lacking - // the "KISYS3DMOD:" alias tag - if( !sPL->m_pathexp.empty() ) + // ${ENV_VAR} paths have already been checked; skip all but + // ${KISYS3DMOD}, since legacy behavior was to check if paths + // were relative to ${KISYS3DMOD} + while( sPL != ePL && sPL->m_alias.StartsWith( "${" ) ) { - wxFileName fpath( wxFileName::DirName( sPL->m_pathexp ) ); - wxString fullPath = fpath.GetPathWithSep() + tname; - - if( wxFileName::FileExists( fullPath ) ) + if( sPL->m_alias == "${KISYS3DMOD}" ) { - wxFileName tmp( fullPath ); + wxFileName fpath( wxFileName::DirName( sPL->m_pathexp ) ); + wxString fullPath = fpath.GetPathWithSep() + tname; - if( tmp.Normalize() ) - tname = tmp.GetFullPath(); + if( wxFileName::FileExists( fullPath ) ) + { + wxFileName tmp( fullPath ); - m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) ); + if( tmp.Normalize() ) + tname = tmp.GetFullPath(); - return tname; + m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, tname ) ); + + return tname; + } } + + ++sPL; } + // at this point the filename must contain an alias or else it is invalid wxString alias; // the alias portion of the short filename wxString relpath; // the path relative to the alias @@ -324,8 +397,10 @@ wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName ) { if( !( m_errflags & ERRFLG_RELPATH ) ) { + // this can happen if the file was intended to be relative to + // ${KISYS3DMOD} but ${KISYS3DMOD} not set or incorrect. m_errflags |= ERRFLG_RELPATH; - wxString errmsg = _( "[3D File Resolver] No such path; ensure KISYS3DMOD is correctly defined" ); + wxString errmsg = _( "[3D File Resolver] No such path" ); errmsg.append( "\n" ); errmsg.append( tname ); wxLogTrace( MASK_3D_RESOLVER, "%s\n", errmsg.ToUTF8() ); @@ -378,7 +453,6 @@ bool S3D_FILENAME_RESOLVER::addPath( const S3D_ALIAS& aPath ) wxCriticalSectionLocker lock( lock3D_resolver ); S3D_ALIAS tpath = aPath; - tpath.m_duplicate = false; #ifdef _WIN32 while( tpath.m_pathvar.EndsWith( wxT( "\\" ) ) ) @@ -424,83 +498,6 @@ bool S3D_FILENAME_RESOLVER::addPath( const S3D_ALIAS& aPath ) while( sPL != ePL ) { - // aliases with the same m_pathvar are forbidden and the - // user must be forced to fix the problem in order to - // obtain good filename resolution - if( !sPL->m_pathvar.empty() && !tpath.m_pathvar.empty() - && !tpath.m_pathvar.Cmp( sPL->m_pathvar ) ) - { - wxString msg = _( "This alias: " ); - msg.append( tpath.m_alias ); - msg.append( wxT( "\n" ) ); - msg.append( _( "This path: " ) ); - msg.append( tpath.m_pathvar ); - msg.append( wxT( "\n" ) ); - msg.append( _( "Existing alias: " ) ); - msg.append( sPL->m_alias ); - msg.append( wxT( "\n" ) ); - msg.append( _( "Existing path: " ) ); - msg.append( sPL->m_pathvar ); - wxMessageBox( msg, _( "Bad alias (duplicate path)" ) ); - - return false; - } - - // aliases with the same m_pathexp are acceptable (one or both - // aliases being tested may be expanded variables) but when shortening - // names the preference is for (a) a fully specified path in m_pathvar - // then (b) the more senior alias in the list - if( !sPL->m_pathexp.empty() && !tpath.m_pathexp.empty() ) - { - if( !tpath.m_pathexp.Cmp( sPL->m_pathexp ) ) - { - wxString msg = _( "This alias: " ); - msg.append( tpath.m_alias ); - msg.append( wxT( "\n" ) ); - msg.append( _( "Existing alias: " ) ); - msg.append( sPL->m_alias ); - msg.append( wxT( "\n" ) ); - msg.append( _( "This path: " ) ); - msg.append( tpath.m_pathexp ); - msg.append( wxT( "\n" ) ); - msg.append( _( "Existing path: " ) ); - msg.append( sPL->m_pathexp ); - msg.append( wxT( "\n" ) ); - msg.append( _( "This full path: " ) ); - msg.append( tpath.m_pathexp ); - msg.append( wxT( "\n" ) ); - msg.append( _( "Existing full path: " ) ); - msg.append( sPL->m_pathexp ); - wxMessageBox( msg, _( "Bad alias (duplicate path)" ) ); - - if( tpath.m_pathvar.StartsWith( wxT( "${" ) ) ) - tpath.m_duplicate = true; - else if( sPL->m_pathvar.StartsWith( wxT( "${" ) ) ) - sPL->m_duplicate = true; - - } - - if( ( tpath.m_pathexp.find( sPL->m_pathexp ) != wxString::npos - || sPL->m_pathexp.find( tpath.m_pathexp ) != wxString::npos ) - && tpath.m_pathexp.Cmp( sPL->m_pathexp ) ) - { - wxString msg = _( "This alias: " ); - msg.append( tpath.m_alias ); - msg.append( wxT( "\n" ) ); - msg.append( _( "This path: " ) ); - msg.append( tpath.m_pathexp ); - msg.append( wxT( "\n" ) ); - msg.append( _( "Existing alias: " ) ); - msg.append( sPL->m_alias ); - msg.append( wxT( "\n" ) ); - msg.append( _( "Existing path: " ) ); - msg.append( sPL->m_pathexp ); - wxMessageBox( msg, _( "Bad alias (common path)" ) ); - - return false; - } - } - if( !tpath.m_alias.Cmp( sPL->m_alias ) ) { wxString msg = _( "Alias: " ); @@ -519,8 +516,6 @@ bool S3D_FILENAME_RESOLVER::addPath( const S3D_ALIAS& aPath ) ++sPL; } - // Note: at this point we may still have duplicated paths - m_Paths.push_back( tpath ); return true; } @@ -572,7 +567,6 @@ bool S3D_FILENAME_RESOLVER::readPathList( void ) int lineno = 0; S3D_ALIAS al; - al.m_duplicate = false; size_t idx; int vnum = 0; // version number @@ -647,11 +641,18 @@ bool S3D_FILENAME_RESOLVER::writePathList( void ) return false; } + // skip all ${ENV_VAR} alias names + std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin(); + std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end(); + + while( sPL != ePL && sPL->m_alias.StartsWith( "${" ) ) + ++sPL; + wxFileName cfgpath( m_ConfigDir, S3D_RESOLVER_CONFIG ); wxString cfgname = cfgpath.GetFullPath(); std::ofstream cfgFile; - if( m_Paths.empty() || 1 == m_Paths.size() ) + if( sPL == ePL ) { wxMessageDialog md( NULL, _( "3D search path list is empty;\ncontinue to write empty file?" ), @@ -692,23 +693,10 @@ bool S3D_FILENAME_RESOLVER::writePathList( void ) } cfgFile << "#V" << CFGFILE_VERSION << "\n"; - std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin(); - std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end(); - - // the first entry is the current project dir; we never add the implicit - // project dir to the path list in the configuration file - ++sPL; std::string tstr; while( sPL != ePL ) { - // never write the KISYS3DMOD entry - if( !sPL->m_alias.Cmp( wxT( "KISYS3DMOD") ) ) - { - ++sPL; - continue; - } - tstr = sPL->m_alias.ToUTF8(); cfgFile << "\"" << tstr.size() << ":" << tstr << "\","; tstr = sPL->m_pathvar.ToUTF8(); @@ -733,6 +721,50 @@ bool S3D_FILENAME_RESOLVER::writePathList( void ) } +bool S3D_FILENAME_RESOLVER::resolveVirtualEnv( const wxString& aFileName, wxString& aFullPath ) +{ + aFullPath.clear(); + + if( !aFileName.StartsWith( "${" ) ) + return false; + + size_t eDelim = aFileName.find( '}' ); + + if( eDelim == wxString::npos || eDelim + 2 >= aFileName.length() ) + return false; + + wxString tPath = aFileName.substr( 0, eDelim + 1 ); + + std::list< S3D_ALIAS >::const_iterator sPL = m_Paths.begin(); + std::list< S3D_ALIAS >::const_iterator ePL = m_Paths.end(); + + while( sPL != ePL ) + { + if( !sPL->m_alias.StartsWith( "${" ) ) + return false; + + if( sPL->m_alias == tPath ) + { + tPath.Append( aFileName.substr( eDelim + 2 ) ); + wxFileName tFile( tPath ); + tFile.Normalize(); + + if( tFile.FileExists() ) + { + aFullPath = tFile.GetFullPath(); + return true; + } + + return false; + } + + ++sPL; + } + + return false; +} + + wxString S3D_FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName ) { wxString fname = aFullPathName; @@ -745,32 +777,11 @@ wxString S3D_FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName ) std::list< S3D_ALIAS >::const_iterator eL = m_Paths.end(); size_t idx; - // test for files within the current project directory - // and KISYS3DMOD directory - for( int i = 0; i < 2 && sL != eL; ++i ) - { - if( !sL->m_pathexp.empty() ) - { - wxFileName fpath( sL->m_pathexp, wxT( "" ) ); - wxString fps = fpath.GetPathWithSep(); - - idx = fname.find( fps ); - - if( std::string::npos != idx && 0 == idx ) - { - fname = fname.substr( fps.size() ); - return fname; - } - } - - ++sL; - } - while( sL != eL ) { - // undefined paths and duplicates do not participate - // in the file name shortening procedure - if( sL->m_pathexp.empty() || sL->m_duplicate ) + // undefined paths do not participate in the + // file name shortening procedure + if( sL->m_pathexp.empty() ) { ++sL; continue; @@ -791,10 +802,21 @@ wxString S3D_FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName ) fname.Replace( wxT( "\\" ), wxT( "/" ) ); #endif - tname = ":"; - tname.append( sL->m_alias ); - tname.append( ":" ); - tname.append( fname ); + if( sL->m_alias.StartsWith( "${" ) ) + { + // old style ENV_VAR + tname = sL->m_alias; + tname.Append( "/" ); + tname.append( fname ); + } + else + { + // new style alias + tname = ":"; + tname.append( sL->m_alias ); + tname.append( ":" ); + tname.append( fname ); + } return tname; } diff --git a/3d-viewer/3d_cache/3d_filename_resolver.h b/3d-viewer/3d_cache/3d_filename_resolver.h index e1274b1985..331d5ecce5 100644 --- a/3d-viewer/3d_cache/3d_filename_resolver.h +++ b/3d-viewer/3d_cache/3d_filename_resolver.h @@ -39,9 +39,10 @@ #include #include "str_rsort.h" +class PGM_BASE; + struct S3D_ALIAS { - bool m_duplicate; wxString m_alias; // alias to the base path wxString m_pathvar; // base path as stored in the config file wxString m_pathexp; // expanded base path @@ -56,6 +57,8 @@ private: // mapping of (short) file names to resolved names std::map< wxString, wxString, S3D::rsort_wxString > m_NameMap; int m_errflags; + PGM_BASE* m_pgm; + wxString m_curProjDir; /** * Function createPathList @@ -95,6 +98,14 @@ private: */ bool writePathList( void ); + /** + * Function resolveVirtualEnv + * extracts the ${ENV_VAR} component of aFileName and puts a + * resolved path in aFullPath if the ${ENV_VAR} exists in the + * alias list and the referenced file exists. + */ + bool resolveVirtualEnv( const wxString& aFileName, wxString& aFullPath ); + public: S3D_FILENAME_RESOLVER(); @@ -120,6 +131,13 @@ public: bool SetProjectDir( const wxString& aProjDir, bool* flgChanged = NULL ); wxString GetProjectDir( void ); + /** + * Function SetProgramBase + * sets a pointer to the application's PGM_BASE instance; + * the pointer is used to extract the local env vars. + */ + void SetProgramBase( PGM_BASE* aBase ); + /** * Function UpdatePathList diff --git a/3d-viewer/3d_cache/dialogs/dlg_3d_pathconfig.cpp b/3d-viewer/3d_cache/dialogs/dlg_3d_pathconfig.cpp index 69472a2f10..3d474df020 100644 --- a/3d-viewer/3d_cache/dialogs/dlg_3d_pathconfig.cpp +++ b/3d-viewer/3d_cache/dialogs/dlg_3d_pathconfig.cpp @@ -42,33 +42,35 @@ DLG_3D_PATH_CONFIG::DLG_3D_PATH_CONFIG( wxWindow* aParent, S3D_FILENAME_RESOLVER m_aliasValidator.SetCharExcludes( wxT( "{}[]()%~<>\"='`;:.,&?/\\|$" ) ); const std::list< S3D_ALIAS >* rpaths = m_resolver->GetPaths(); + std::list< S3D_ALIAS >::const_iterator rI = rpaths->begin(); + std::list< S3D_ALIAS >::const_iterator rE = rpaths->end(); size_t listsize = rpaths->size(); + size_t listidx = 0; - if( listsize > 0 ) - m_curdir = rpaths->front().m_pathexp; + while( rI != rE && (*rI).m_alias.StartsWith( "${" ) ) + { + ++listidx; + ++rI; + } - if( listsize < 3 ) + if( listidx < listsize ) + m_curdir = (*rI).m_pathexp; + else return; - listsize = listsize - 2 - m_Aliases->GetNumberRows(); + listsize = listsize - listidx - m_Aliases->GetNumberRows(); // note: if the list allocation fails we have bigger problems // and there is no point in trying to notify the user here if( listsize > 0 && !m_Aliases->InsertRows( 0, listsize ) ) return; - std::list< S3D_ALIAS >::const_iterator sL = rpaths->begin(); - std::list< S3D_ALIAS >::const_iterator eL = rpaths->end(); int nitems = 0; - - // skip the current project dir and KISYS3DMOD - ++sL; - ++sL; wxGridCellTextEditor* pEdAlias; - while( sL != eL ) + while( rI != rE ) { - m_Aliases->SetCellValue( nitems, 0, sL->m_alias ); + m_Aliases->SetCellValue( nitems, 0, rI->m_alias ); if( 0 == nitems ) { @@ -83,12 +85,12 @@ DLG_3D_PATH_CONFIG::DLG_3D_PATH_CONFIG( wxWindow* aParent, S3D_FILENAME_RESOLVER m_Aliases->SetCellEditor( nitems, 0, pEdAlias ); } - m_Aliases->SetCellValue( nitems, 1, sL->m_pathvar ); - m_Aliases->SetCellValue( nitems++, 2, sL->m_description ); + m_Aliases->SetCellValue( nitems, 1, rI->m_pathvar ); + m_Aliases->SetCellValue( nitems++, 2, rI->m_description ); // TODO: implement a wxGridCellEditor which invokes a wxDirDialog - ++sL; + ++rI; } m_Aliases->AutoSize(); diff --git a/3d-viewer/3d_cache/dialogs/dlg_select_3dmodel.cpp b/3d-viewer/3d_cache/dialogs/dlg_select_3dmodel.cpp index 890df9cef4..4c75d81389 100644 --- a/3d-viewer/3d_cache/dialogs/dlg_select_3dmodel.cpp +++ b/3d-viewer/3d_cache/dialogs/dlg_select_3dmodel.cpp @@ -22,6 +22,7 @@ */ +#include #include "dlg_select_3dmodel.h" #include "project.h" #include "3d_cache/3d_info.h" @@ -240,12 +241,20 @@ void DLG_SELECT_3DMODEL::updateDirChoiceList( void ) std::list< S3D_ALIAS > const* md = m_resolver->GetPaths(); std::list< S3D_ALIAS >::const_iterator sL = md->begin(); std::list< S3D_ALIAS >::const_iterator eL = md->end(); - std::vector< wxString > cl; + std::set< wxString > cl; + wxString prjDir; + + // extract the current project dir + if( sL != eL ) + { + prjDir = sL->m_pathexp; + ++sL; + } while( sL != eL ) { - if( !sL->m_pathexp.empty() && !sL->m_duplicate ) - cl.push_back( sL->m_pathexp ); + if( !sL->m_pathexp.empty() && sL->m_pathexp.compare( prjDir ) ) + cl.insert( sL->m_pathexp ); ++sL; } @@ -253,7 +262,19 @@ void DLG_SELECT_3DMODEL::updateDirChoiceList( void ) if( !cl.empty() ) { dirChoices->Clear(); - dirChoices->Append( (int)cl.size(), &cl[0] ); + + if( !prjDir.empty() ) + dirChoices->Append( prjDir ); + + std::set< wxString >::const_iterator sI = cl.begin(); + std::set< wxString >::const_iterator eI = cl.end(); + + while( sI != eI ) + { + dirChoices->Append( *sI ); + ++sI; + } + dirChoices->Select( 0 ); } diff --git a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp index 42113b1b67..2c4b9e47e2 100644 --- a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp +++ b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp @@ -75,6 +75,7 @@ DIALOG_MODULE_BOARD_EDITOR::DIALOG_MODULE_BOARD_EDITOR( PCB_EDIT_FRAME* aParent m_OrientValueCtrl->SetValidator( m_OrientValidator ); m_OrientValidator.SetWindow( m_OrientValueCtrl ); + aParent->Prj().Get3DCacheManager()->GetResolver()->SetProgramBase( &Pgm() ); m_PreviewPane = new PANEL_PREV_3D( m_Panel3D, aParent->Prj().Get3DCacheManager() ); bLowerSizer3D->Add( m_PreviewPane, 1, wxEXPAND, 5 ); diff --git a/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp b/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp index dd39b01906..234c67d646 100644 --- a/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp +++ b/pcbnew/dialogs/dialog_edit_module_for_Modedit.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include "3d_cache/dialogs/panel_prev_model.h" #include "3d_cache/dialogs/3d_cache_dialogs.h" #include "3d_cache/3d_cache.h" @@ -70,6 +71,7 @@ DIALOG_MODULE_MODULE_EDITOR::DIALOG_MODULE_MODULE_EDITOR( FOOTPRINT_EDIT_FRAME* icon.CopyFromBitmap( KiBitmap( icon_modedit_xpm ) ); SetIcon( icon ); + aParent->Prj().Get3DCacheManager()->GetResolver()->SetProgramBase( &Pgm() ); m_PreviewPane = new PANEL_PREV_3D( m_Panel3D, aParent->Prj().Get3DCacheManager() ); bLowerSizer3D->Add( m_PreviewPane, 1, wxEXPAND, 5 );