From 3b63ce8a48472cb5a7e3e8f81e7819ed80fa6fa9 Mon Sep 17 00:00:00 2001
From: Marek Roszko <mark.roszko@gmail.com>
Date: Sat, 8 Oct 2022 14:23:45 -0400
Subject: [PATCH] Don't use the 3d resolver config anymore

---
 common/filename_resolver.cpp                 |  82 --
 include/filename_resolver.h                  |   7 +-
 pcbnew/dialogs/dialog_export_step.cpp        |   5 -
 pcbnew/exporters/step/CMakeLists.txt         |   2 +-
 pcbnew/exporters/step/pcb/3d_resolver.cpp    | 797 -------------------
 pcbnew/exporters/step/pcb/3d_resolver.h      | 203 -----
 pcbnew/exporters/step/pcb/kicadfootprint.cpp |  18 +-
 pcbnew/exporters/step/pcb/kicadfootprint.h   |   4 +-
 pcbnew/exporters/step/pcb/kicadpcb.h         |   4 +-
 9 files changed, 11 insertions(+), 1111 deletions(-)
 delete mode 100644 pcbnew/exporters/step/pcb/3d_resolver.cpp
 delete mode 100644 pcbnew/exporters/step/pcb/3d_resolver.h

diff --git a/common/filename_resolver.cpp b/common/filename_resolver.cpp
index 530659d58e..1daeb1b1e4 100644
--- a/common/filename_resolver.cpp
+++ b/common/filename_resolver.cpp
@@ -499,88 +499,6 @@ bool FILENAME_RESOLVER::addPath( const SEARCH_PATH& aPath )
 }
 
 
-bool FILENAME_RESOLVER::WritePathList( const wxString& aDir, const wxString& aFilename,
-                                       bool aResolvePaths )
-{
-    if( aDir.empty() )
-    {
-        std::ostringstream ostr;
-        ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
-        wxString errmsg = _( "3D configuration directory is unknown" );
-        ostr << " * " << errmsg.ToUTF8();
-        wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() );
-        wxMessageBox( errmsg, _( "Write 3D search path list" ) );
-
-        return false;
-    }
-
-    std::list<SEARCH_PATH>::const_iterator sPL = m_paths.begin();
-
-    if( !aResolvePaths )
-    {
-        // skip all ${ENV_VAR} alias names
-
-        while( sPL != m_paths.end()
-                && ( sPL->m_Alias.StartsWith( "${" ) || sPL->m_Alias.StartsWith( "$(" ) ) )
-        {
-            ++sPL;
-        }
-    }
-
-    wxFileName cfgpath( aDir, aFilename );
-    wxString cfgname = cfgpath.GetFullPath();
-    std::ofstream cfgFile;
-
-    cfgFile.open( cfgname.ToUTF8(), std::ios_base::trunc );
-
-    if( !cfgFile.is_open() )
-    {
-        std::ostringstream ostr;
-        ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
-        wxString errmsg = _( "Could not open configuration file" );
-        ostr << " * " << errmsg.ToUTF8() << " '" << cfgname.ToUTF8() << "'";
-        wxLogTrace( MASK_3D_RESOLVER, "%s\n", ostr.str().c_str() );
-        wxMessageBox( errmsg, _( "Write 3D search path list" ) );
-
-        return false;
-    }
-
-    cfgFile << "#V" << CFGFILE_VERSION << "\n";
-    std::string tstr;
-
-    while( sPL != m_paths.end() )
-    {
-        tstr = sPL->m_Alias.ToUTF8();
-        cfgFile << "\"" << tstr.size() << ":" << tstr << "\",";
-
-        if( aResolvePaths )
-            tstr = ExpandEnvVarSubstitutions( sPL->m_Pathvar, m_project ).ToUTF8();
-        else
-            tstr = sPL->m_Pathvar.ToUTF8();
-
-        cfgFile << "\"" << tstr.size() << ":" << tstr << "\",";
-
-        tstr = sPL->m_Description.ToUTF8();
-        cfgFile << "\"" << tstr.size() << ":" << tstr << "\"\n";
-
-        ++sPL;
-    }
-
-    bool bad = cfgFile.bad();
-    cfgFile.close();
-
-    if( bad )
-    {
-        wxMessageBox( _( "Problems writing configuration file" ),
-                      _( "Write 3D search path list" ) );
-
-        return false;
-    }
-
-    return true;
-}
-
-
 void FILENAME_RESOLVER::checkEnvVarPath( const wxString& aPath )
 {
     bool useParen = false;
diff --git a/include/filename_resolver.h b/include/filename_resolver.h
index 7d8febdcfc..4570f60215 100644
--- a/include/filename_resolver.h
+++ b/include/filename_resolver.h
@@ -34,6 +34,7 @@
 #include <vector>
 #include <wx/string.h>
 
+class PROJECT;
 class PGM_BASE;
 
 struct SEARCH_PATH
@@ -89,12 +90,6 @@ public:
      */
     bool UpdatePathList( const std::vector<SEARCH_PATH>& aPathList );
 
-    /**
-     * Write the current path list to a config file.
-     * @param aResolvePaths indicates whether env vars should also be written out or not
-     */
-    bool WritePathList( const wxString& aDir, const wxString& aFilename, bool aResolvePaths );
-
     /**
      * Determines the full path of the given file name.
      *
diff --git a/pcbnew/dialogs/dialog_export_step.cpp b/pcbnew/dialogs/dialog_export_step.cpp
index 48e421326d..56e79ba3e6 100644
--- a/pcbnew/dialogs/dialog_export_step.cpp
+++ b/pcbnew/dialogs/dialog_export_step.cpp
@@ -363,11 +363,6 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
             return;
     }
 
-    FILENAME_RESOLVER* fnResolver = m_parent->Prj().Get3DFilenameResolver();
-
-    fnResolver->WritePathList( wxStandardPaths::Get().GetTempDir(), wxT( "ExportPaths.cfg" ),
-                               true );
-
     DIALOG_EXPORT_STEP::STEP_ORG_OPT orgOpt = GetOriginOption();
     double xOrg = 0.0;
     double yOrg = 0.0;
diff --git a/pcbnew/exporters/step/CMakeLists.txt b/pcbnew/exporters/step/CMakeLists.txt
index 1f4f4b9e5b..8d01797291 100644
--- a/pcbnew/exporters/step/CMakeLists.txt
+++ b/pcbnew/exporters/step/CMakeLists.txt
@@ -5,7 +5,7 @@ include_directories( SYSTEM
 
 set( KS2_LIB_FILES
     kicad2step.cpp
-    pcb/3d_resolver.cpp
+    
     pcb/base.cpp
     pcb/kicadmodel.cpp
     pcb/kicadfootprint.cpp
diff --git a/pcbnew/exporters/step/pcb/3d_resolver.cpp b/pcbnew/exporters/step/pcb/3d_resolver.cpp
deleted file mode 100644
index 20d21d9200..0000000000
--- a/pcbnew/exporters/step/pcb/3d_resolver.cpp
+++ /dev/null
@@ -1,797 +0,0 @@
-/*
- * This program source code file is part kicad2mcad
- *
- * Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
- * Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, you may find one here:
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- * or you may search the http://www.gnu.org website for the version 2 license,
- * or you may write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-#include <cstdlib>
-#include <cstring>
-#include <fstream>
-#include <iostream>
-#include <mutex>
-#include <sstream>
-
-#include <wx/fileconf.h>
-#include <wx/log.h>
-#include <wx/thread.h>
-#include <wx/msgdlg.h>
-#include <wx/stdpaths.h>
-
-#include <wx_filename.h>
-
-#include "3d_resolver.h"
-
-// configuration file version
-#define CFGFILE_VERSION 1
-#define S3D_RESOLVER_CONFIG "ExportPaths.cfg"
-
-// flag bits used to track different one-off messages to users
-#define ERRFLG_ALIAS    (1)
-#define ERRFLG_RELPATH  (2)
-#define ERRFLG_ENVPATH  (4)
-
-
-/**
- * Flag to enable plugin loader trace output.
- *
- * @ingroup trace_env_vars
- */
-const wxChar* const trace3dResolver = wxT( "KICAD_3D_RESOLVER" );
-
-
-static std::mutex mutex3D_resolver;
-
-
-static bool getHollerith( const std::string& aString, size_t& aIndex, wxString& aResult );
-
-
-S3D_RESOLVER::S3D_RESOLVER()
-{
-    m_errflags = 0;
-}
-
-
-bool S3D_RESOLVER::Set3DConfigDir( const wxString& aConfigDir )
-{
-    createPathList();
-
-    return true;
-}
-
-
-bool S3D_RESOLVER::createPathList( void )
-{
-    if( !m_Paths.empty() )
-        return true;
-
-    readPathList();
-
-    if( m_Paths.empty() )
-        return false;
-
-#ifdef DEBUG
-    wxLogTrace( trace3dResolver, wxT( " * [3D model] search paths:\n" ) );
-
-    for( const SEARCH_PATH& searchPath : m_Paths )
-        wxLogTrace( trace3dResolver, wxT( "   + '%s'\n" ), searchPath.m_Pathexp );
-#endif
-
-    return true;
-}
-
-
-wxString S3D_RESOLVER::ResolvePath( const wxString& aFileName,
-                                    std::vector<wxString>& aSearchedPaths )
-{
-    std::lock_guard<std::mutex> lock( mutex3D_resolver );
-
-    if( aFileName.empty() )
-        return wxEmptyString;
-
-    if( m_Paths.empty() )
-        createPathList();
-
-    // look up the filename in the internal filename map
-    std::map<wxString, wxString, S3D::rsort_wxString>::iterator mi;
-    mi = m_NameMap.find( aFileName );
-
-    if( mi != m_NameMap.end() )
-        return mi->second;
-
-    // first attempt to use the name as specified:
-    wxString tname = aFileName;
-
-#ifdef _WIN32
-    // translate from KiCad's internal UNIX-like path to MSWin paths
-    tname.Replace( wxT( "/" ), wxT( "\\" ) );
-#endif
-
-    // Note: variable expansion must preferably be performed via a threadsafe wrapper for the
-    // getenv() system call. If we allow the wxFileName::Normalize() routine to perform expansion
-    // then we will have a race condition since wxWidgets does not assure a threadsafe wrapper
-    // for getenv().
-    if( tname.StartsWith( wxT( "${" ) ) || tname.StartsWith( wxT( "$(" ) ) )
-        tname = expandVars( tname );
-
-    wxFileName tmpFN( tname );
-
-    // in the case of absolute filenames we don't store a map item
-    if( !aFileName.StartsWith( wxT( "${" ) ) && !aFileName.StartsWith( wxT( "$(" ) )
-            && tmpFN.IsAbsolute() )
-    {
-        if( tmpFN.FileExists() )
-        {
-            tmpFN.Normalize( FN_NORMALIZE_FLAGS );
-            return tmpFN.GetFullPath();
-        }
-        else
-        {
-            aSearchedPaths.push_back( tmpFN.GetFullPath() );
-        }
-    }
-
-    // this case covers full paths, leading expanded vars, and paths relative to the current
-    // working directory (which is not necessarily the current project directory)
-    tmpFN.Normalize( FN_NORMALIZE_FLAGS );
-
-    if( tmpFN.FileExists() )
-    {
-        tname = tmpFN.GetFullPath();
-        m_NameMap[ aFileName ] = tname;
-
-        // special case: if a path begins with ${ENV_VAR} but is not in the resolver's path list
-        // then add it
-        if( aFileName.StartsWith( wxT( "${" ) ) || aFileName.StartsWith( wxT( "$(" ) ) )
-            checkEnvVarPath( aFileName );
-
-        return tname;
-    }
-    else if( tmpFN.GetFullPath() != aFileName )
-    {
-        aSearchedPaths.push_back( tmpFN.GetFullPath() );
-    }
-
-    // if a path begins with ${ENV_VAR}/$(ENV_VAR) and is not resolved then the file either does
-    // not exist or the ENV_VAR is not defined
-    if( aFileName.StartsWith( wxT( "${" ) ) || aFileName.StartsWith( wxT( "$(" ) ) )
-    {
-        m_errflags |= ERRFLG_ENVPATH;
-        return aFileName;
-    }
-
-    // at this point aFileName is:
-    // a. an aliased shortened name or
-    // b. cannot be determined
-
-    // check the path relative to the current project directory;
-    // NB: this is not necessarily the same as the current working directory, which has already
-    // been checked. This case accounts for partial paths which do not contain ${KIPRJMOD}.
-    // This check is performed before checking the path relative to ${KICAD6_3DMODEL_DIR} so that
-    // users can potentially override a model within ${KICAD6_3DMODEL_DIR}.
-    if( !m_Paths.empty() && !m_Paths.begin()->m_Pathexp.empty() && !tname.StartsWith( wxT( ":" ) ) )
-    {
-        tmpFN.Assign( m_Paths.begin()->m_Pathexp, wxT( "" ) );
-        wxString fullPath = tmpFN.GetPathWithSep() + tname;
-
-        if( fullPath.StartsWith( wxT( "${" ) ) || fullPath.StartsWith( wxT( "$(" ) ) )
-            fullPath = expandVars( fullPath );
-
-        tmpFN.Assign( fullPath );
-        tmpFN.Normalize( FN_NORMALIZE_FLAGS );
-
-        if( tmpFN.FileExists() )
-        {
-            tname = tmpFN.GetFullPath();
-            m_NameMap[ aFileName ] = tname;
-            return tname;
-        }
-        else if( tmpFN.GetFullPath() != aFileName )
-        {
-            aSearchedPaths.push_back( tmpFN.GetFullPath() );
-        }
-    }
-
-    // check the partial path relative to ${KICAD6_3DMODEL_DIR} (legacy behavior)
-    if( !tname.Contains( wxT( ":" ) ) )
-    {
-        wxFileName fpath;
-        wxString fullPath( wxT( "${KICAD6_3DMODEL_DIR}" ) );
-        fullPath.Append( fpath.GetPathSeparator() );
-        fullPath.Append( tname );
-        fullPath = expandVars( fullPath );
-        fpath.Assign( fullPath );
-        fpath.Normalize( FN_NORMALIZE_FLAGS );
-
-        if( fpath.FileExists() )
-        {
-            tname = fpath.GetFullPath();
-            m_NameMap[ aFileName ] = tname;
-            return tname;
-        }
-        else
-        {
-            aSearchedPaths.push_back( fpath.GetFullPath() );
-        }
-    }
-
-    // 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
-
-    if( !SplitAlias( tname, alias, relpath ) )
-    {
-        // this can happen if the file was intended to be relative to ${KICAD6_3DMODEL_DIR}
-        // but ${KICAD6_3DMODEL_DIR} is not set or is incorrect.
-        m_errflags |= ERRFLG_RELPATH;
-        return aFileName;
-    }
-
-    for( const SEARCH_PATH& path : m_Paths )
-    {
-        // ${ENV_VAR} paths have already been checked; skip them
-        if( path.m_Alias.StartsWith( wxT( "${" ) ) || path.m_Alias.StartsWith( wxT( "$(" ) ) )
-            continue;
-
-        if( path.m_Alias == alias && !path.m_Pathexp.empty() )
-        {
-            wxFileName fpath( wxFileName::DirName( path.m_Pathexp ) );
-            wxString fullPath = fpath.GetPathWithSep() + relpath;
-
-            if( fullPath.StartsWith( wxT( "${" ) ) || fullPath.StartsWith( wxT( "$(" ) ) )
-                fullPath = expandVars( fullPath );
-
-            wxFileName tmp( fullPath );
-            tmp.Normalize( FN_NORMALIZE_FLAGS );
-
-            if( tmp.FileExists() )
-            {
-                tname = tmp.GetFullPath();
-                m_NameMap[ aFileName ] = tname;
-                return tname;
-            }
-            else
-            {
-                aSearchedPaths.push_back( tmp.GetFullPath() );
-            }
-        }
-    }
-
-    m_errflags |= ERRFLG_ALIAS;
-    return aFileName;
-}
-
-
-bool S3D_RESOLVER::addPath( const SEARCH_PATH& aPath )
-{
-    if( aPath.m_Alias.empty() || aPath.m_Pathvar.empty() )
-        return false;
-
-    std::lock_guard<std::mutex> lock( mutex3D_resolver );
-
-    SEARCH_PATH tpath = aPath;
-
-#ifdef _WIN32
-    while( tpath.m_Pathvar.EndsWith( wxT( "\\" ) ) )
-        tpath.m_Pathvar.erase( tpath.m_Pathvar.length() - 1 );
-#else
-    while( tpath.m_Pathvar.EndsWith( wxT( "/" ) ) && tpath.m_Pathvar.length() > 1 )
-        tpath.m_Pathvar.erase( tpath.m_Pathvar.length() - 1 );
-#endif
-
-    wxFileName path( tpath.m_Pathvar, wxT( "" ) );
-    path.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
-
-    if( !path.DirExists() )
-    {
-        // Show a message only in debug mode
-#ifdef DEBUG
-        if( aPath.m_Pathvar == wxT( "${KICAD6_3DMODEL_DIR}" )
-                || aPath.m_Pathvar == wxT( "${KIPRJMOD}" )
-                || aPath.m_Pathvar == wxT( "${KISYS3DMOD}" ) )
-        {
-            // suppress the message if the missing pathvar is a system variable
-        }
-        else
-        {
-            wxString msg = _( "The given path does not exist" );
-            msg.append( wxT( "\n" ) );
-            msg.append( tpath.m_Pathvar );
-            wxLogMessage( wxT( "%s\n" ), msg.ToUTF8() );
-        }
-#endif
-
-        tpath.m_Pathexp.clear();
-    }
-    else
-    {
-        tpath.m_Pathexp = path.GetFullPath();
-
-#ifdef _WIN32
-        while( tpath.m_Pathexp.EndsWith( wxT( "\\" ) ) )
-            tpath.m_Pathexp.erase( tpath.m_Pathexp.length() - 1 );
-#else
-        while( tpath.m_Pathexp.EndsWith( wxT( "/" ) ) && tpath.m_Pathexp.length() > 1 )
-            tpath.m_Pathexp.erase( tpath.m_Pathexp.length() - 1 );
-#endif
-    }
-
-    std::list< SEARCH_PATH >::iterator sPL = m_Paths.begin();
-    std::list< SEARCH_PATH >::iterator ePL = m_Paths.end();
-
-    while( sPL != ePL )
-    {
-        if( tpath.m_Alias == sPL->m_Alias )
-        {
-            wxString msg = _( "Alias:" ) + wxS( " " );
-            msg.append( tpath.m_Alias );
-            msg.append( wxS( "\n" ) );
-            msg.append( _( "This path:" ) + wxS( " " ) );
-            msg.append( tpath.m_Pathvar );
-            msg.append( wxS( "\n" ) );
-            msg.append( _( "Existing path:" ) + wxS( " " ) );
-            msg.append( sPL->m_Pathvar );
-            wxMessageBox( msg, _( "Bad alias (duplicate name)" ) );
-
-            return false;
-        }
-
-        ++sPL;
-    }
-
-    m_Paths.push_back( tpath );
-    return true;
-}
-
-
-bool S3D_RESOLVER::readPathList( void )
-{
-    wxFileName cfgpath( wxStandardPaths::Get().GetTempDir(), S3D_RESOLVER_CONFIG );
-    cfgpath.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
-    wxString cfgname = cfgpath.GetFullPath();
-
-    size_t nitems = m_Paths.size();
-
-    std::ifstream cfgFile;
-    std::string   cfgLine;
-
-    if( !wxFileName::Exists( cfgname ) )
-    {
-        wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n * no 3D configuration file '%s'" ),
-                    __FILE__, __FUNCTION__, __LINE__, cfgname );
-
-        return false;
-    }
-
-    cfgFile.open( cfgname.ToUTF8() );
-
-    if( !cfgFile.is_open() )
-    {
-        wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n * Could not open configuration file '%s'" ),
-                    __FILE__, __FUNCTION__, __LINE__, cfgname );
-
-        return false;
-    }
-
-    int lineno = 0;
-    SEARCH_PATH al;
-    size_t idx;
-    int vnum = 0;           // version number
-
-    while( cfgFile.good() )
-    {
-        cfgLine.clear();
-        std::getline( cfgFile, cfgLine );
-        ++lineno;
-
-        if( cfgLine.empty() )
-        {
-            if( cfgFile.eof() )
-                break;
-
-            continue;
-        }
-
-        if( 1 == lineno && cfgLine.compare( 0, 2, "#V" ) == 0 )
-        {
-            // extract the version number and parse accordingly
-            if( cfgLine.size() > 2 )
-            {
-                std::istringstream istr;
-                istr.str( cfgLine.substr( 2 ) );
-                istr >> vnum;
-            }
-
-            continue;
-        }
-
-        idx = 0;
-
-        if( !getHollerith( cfgLine, idx, al.m_Alias ) )
-            continue;
-
-        if( !getHollerith( cfgLine, idx, al.m_Pathvar ) )
-            continue;
-
-        if( !getHollerith( cfgLine, idx, al.m_Description ) )
-            continue;
-
-        addPath( al );
-    }
-
-    cfgFile.close();
-
-    if( m_Paths.size() != nitems )
-        return true;
-
-    return false;
-}
-
-
-void S3D_RESOLVER::checkEnvVarPath( const wxString& aPath )
-{
-    bool useParen = false;
-
-    if( aPath.StartsWith( wxT( "$(" ) ) )
-        useParen = true;
-    else if( !aPath.StartsWith( wxT( "${" ) ) )
-        return;
-
-    size_t pEnd;
-
-    if( useParen )
-        pEnd = aPath.find( wxT( ")" ) );
-    else
-        pEnd = aPath.find( wxT( "}" ) );
-
-    if( pEnd == wxString::npos )
-        return;
-
-    wxString envar = aPath.substr( 0, pEnd + 1 );
-
-    // check if the alias exists; if not then add it to the end of the
-    // env var section of the path list
-    std::list< SEARCH_PATH >::iterator sPL = m_Paths.begin();
-    std::list< SEARCH_PATH >::iterator ePL = m_Paths.end();
-
-    while( sPL != ePL )
-    {
-        if( sPL->m_Alias == envar )
-            return;
-
-        if( !sPL->m_Alias.StartsWith( wxT( "${" ) ) )
-            break;
-
-        ++sPL;
-    }
-
-    SEARCH_PATH lpath;
-    lpath.m_Alias = envar;
-    lpath.m_Pathvar = lpath.m_Alias;
-    wxFileName tmpFN( lpath.m_Alias, wxT( "" ) );
-    wxUniChar psep = tmpFN.GetPathSeparator();
-    tmpFN.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
-
-    if( !tmpFN.DirExists() )
-        return;
-
-    lpath.m_Pathexp = tmpFN.GetFullPath();
-
-    if( !lpath.m_Pathexp.empty() && psep == *lpath.m_Pathexp.rbegin() )
-        lpath.m_Pathexp.erase( --lpath.m_Pathexp.end() );
-
-    if( lpath.m_Pathexp.empty() )
-        return;
-
-    m_Paths.insert( sPL, lpath );
-    return;
-}
-
-
-wxString S3D_RESOLVER::expandVars( const wxString& aPath )
-{
-    if( aPath.empty() )
-        return wxEmptyString;
-
-    wxString result;
-
-    for( const std::pair<const wxString, wxString>& i : m_EnvVars )
-    {
-        if( !aPath.compare( 2, i.first.length(), i.first ) )
-        {
-            result = i.second;
-            result.append( aPath.substr( 3 + i.first.length() ) );
-
-            if( result.StartsWith( wxT( "${" ) ) || result.StartsWith( wxT( "$(" ) ) )
-                result = expandVars( result );
-
-            return result;
-        }
-    }
-
-    result = wxExpandEnvVars( aPath );
-
-    if( result == aPath )
-        return wxEmptyString;
-
-    if( result.StartsWith( wxT( "${" ) ) || result.StartsWith( wxT( "$(" ) ) )
-        result = expandVars( result );
-
-    return result;
-}
-
-
-wxString S3D_RESOLVER::ShortenPath( const wxString& aFullPathName )
-{
-    wxString fname = aFullPathName;
-
-    if( m_Paths.empty() )
-        createPathList();
-
-    std::lock_guard<std::mutex> lock( mutex3D_resolver );
-
-    std::list< SEARCH_PATH >::const_iterator sL = m_Paths.begin();
-    std::list< SEARCH_PATH >::const_iterator eL = m_Paths.end();
-    size_t idx;
-
-    while( sL != eL )
-    {
-        // undefined paths do not participate in the file name shortening procedure.
-        if( sL->m_Pathexp.empty() )
-        {
-            ++sL;
-            continue;
-        }
-
-        wxFileName fpath( sL->m_Pathexp, wxT( "" ) );
-        wxString fps = fpath.GetPathWithSep();
-        wxString tname;
-
-        idx = fname.find( fps );
-
-        if( std::string::npos != idx && 0 == idx )
-        {
-            fname = fname.substr( fps.size() );
-
-#ifdef _WIN32
-            // ensure only the '/' separator is used in the internal name
-            fname.Replace( wxT( "\\" ), wxT( "/" ) );
-#endif
-
-            if( sL->m_Alias.StartsWith( wxT( "${" ) ) || sL->m_Alias.StartsWith( wxT( "$(" ) ) )
-            {
-                // old style ENV_VAR
-                tname = sL->m_Alias;
-                tname.Append( wxT( "/" ) );
-                tname.append( fname );
-            }
-            else
-            {
-                // new style alias
-                tname = wxT( ":" );
-                tname.append( sL->m_Alias );
-                tname.append( wxT( ":" ) );
-                tname.append( fname );
-            }
-
-            return tname;
-        }
-
-        ++sL;
-    }
-
-#ifdef _WIN32
-    // it is strange to convert an MSWin full path to use the
-    // UNIX separator but this is done for consistency and can
-    // be helpful even when transferring project files from
-    // MSWin to *NIX.
-    fname.Replace( wxT( "\\" ), wxT( "/" ) );
-#endif
-
-    return fname;
-}
-
-
-const std::list< SEARCH_PATH >* S3D_RESOLVER::GetPaths( void )
-{
-    return &m_Paths;
-}
-
-
-bool S3D_RESOLVER::SplitAlias( const wxString& aFileName, wxString& anAlias, wxString& aRelPath )
-{
-    anAlias.clear();
-    aRelPath.clear();
-
-    size_t searchStart = 0;
-
-    if( aFileName.StartsWith( wxT( ":" ) ) )
-        searchStart = 1;
-
-    size_t tagpos = aFileName.find( wxT( ":" ), searchStart );
-
-    if( tagpos == wxString::npos || tagpos == searchStart )
-        return false;
-
-    if( tagpos + 1 >= aFileName.length() )
-        return false;
-
-    anAlias = aFileName.substr( searchStart, tagpos - searchStart );
-    aRelPath = aFileName.substr( tagpos + 1 );
-
-    return true;
-}
-
-
-static bool getHollerith( const std::string& aString, size_t& aIndex, wxString& aResult )
-{
-    aResult.clear();
-
-    if( aIndex >= aString.size() )
-    {
-        wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n * Bad Hollerith string in line '%s'" ),
-                    __FILE__, __FUNCTION__, __LINE__, aString );
-
-        return false;
-    }
-
-    size_t i2 = aString.find( '"', aIndex );
-
-    if( std::string::npos == i2 )
-    {
-        wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n * missing opening quote mark in line '%s'" ),
-                    __FILE__, __FUNCTION__, __LINE__, aString );
-
-        return false;
-    }
-
-    ++i2;
-
-    if( i2 >= aString.size() )
-    {
-        wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n * unexpected end of line in line '%s'" ),
-                    __FILE__, __FUNCTION__, __LINE__, aString );
-
-        return false;
-    }
-
-    std::string tnum;
-
-    while( aString[i2] >= '0' && aString[i2] <= '9' )
-        tnum.append( 1, aString[i2++] );
-
-    if( tnum.empty() || aString[i2++] != ':' )
-    {
-        wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n * Bad Hollerith string in line '%s'" ),
-                    __FILE__, __FUNCTION__, __LINE__, aString );
-
-        return false;
-    }
-
-    std::istringstream istr;
-    istr.str( tnum );
-    size_t nchars;
-    istr >> nchars;
-
-    if( ( i2 + nchars ) >= aString.size() )
-    {
-        wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n * unexpected end of line in line '%s'" ),
-                    __FILE__, __FUNCTION__, __LINE__, aString );
-
-        return false;
-    }
-
-    if( nchars > 0 )
-    {
-        aResult = wxString::FromUTF8( aString.substr( i2, nchars ).c_str() );
-        i2 += nchars;
-    }
-
-    if( i2 >= aString.size() || aString[i2] != '"' )
-    {
-        wxLogTrace( trace3dResolver, wxT( "%s:%s:%d\n * missing closing quote mark in line '%s'" ),
-                    __FILE__, __FUNCTION__, __LINE__, aString );
-
-        return false;
-    }
-
-    aIndex = i2 + 1;
-    return true;
-}
-
-
-bool S3D_RESOLVER::ValidateFileName( const wxString& aFileName, bool& hasAlias )
-{
-    // Rules:
-    // 1. The generic form of an aliased 3D relative path is:
-    //    ALIAS:relative/path
-    // 2. ALIAS is a UTF string excluding "{}[]()%~<>\"='`;:.,&?/\\|$"
-    // 3. The relative path must be a valid relative path for the platform
-    hasAlias = false;
-
-    if( aFileName.empty() )
-        return false;
-
-    wxString filename = aFileName;
-    wxString lpath;
-    size_t aliasStart = aFileName.StartsWith( ':' ) ? 1 : 0;
-    size_t aliasEnd = aFileName.find( ':' );
-
-    // ensure that the file separators suit the current platform
-#ifdef __WINDOWS__
-    filename.Replace( wxT( "/" ), wxT( "\\" ) );
-
-    // if we see the :\ pattern then it must be a drive designator
-    if( aliasEnd != wxString::npos )
-    {
-        size_t pos1 = aFileName.find( wxT( ":\\" ) );
-
-        if( pos1 != wxString::npos && ( pos1 != aliasEnd || pos1 != 1 ) )
-            return false;
-
-        // if we have a drive designator then we have no alias
-        if( pos1 != wxString::npos )
-            aliasEnd = wxString::npos;
-    }
-#else
-    filename.Replace( wxT( "\\" ), wxT( "/" ) );
-#endif
-
-    // names may not end with ':'
-    if( aliasEnd == aFileName.length() - 1 )
-        return false;
-
-    if( aliasEnd != wxString::npos )
-    {
-        // ensure the alias component is not empty
-        if( aliasEnd == aliasStart )
-            return false;
-
-        lpath = filename.substr( aliasStart, aliasEnd );
-
-        // check the alias for restricted characters
-        if( wxString::npos != lpath.find_first_of( "{}[]()%~<>\"='`;:.,&?/\\|$" ) )
-            return false;
-
-        hasAlias = true;
-        lpath = aFileName.substr( aliasEnd + 1 );
-    }
-    else
-    {
-        lpath = aFileName;
-
-        // in the case of ${ENV_VAR}|$(ENV_VAR)/path, strip the
-        // environment string before testing
-        aliasEnd = wxString::npos;
-
-        if( aFileName.StartsWith( wxT( "${" ) ) )
-            aliasEnd = aFileName.find( '}' );
-        else if( aFileName.StartsWith( wxT( "$(" ) ) )
-            aliasEnd = aFileName.find( ')' );
-
-        if( aliasEnd != wxString::npos )
-            lpath = aFileName.substr( aliasEnd + 1 );
-    }
-
-    if( wxString::npos != lpath.find_first_of( wxFileName::GetForbiddenChars() ) )
-        return false;
-
-    return true;
-}
diff --git a/pcbnew/exporters/step/pcb/3d_resolver.h b/pcbnew/exporters/step/pcb/3d_resolver.h
deleted file mode 100644
index fd3c010032..0000000000
--- a/pcbnew/exporters/step/pcb/3d_resolver.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
- * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, you may find one here:
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- * or you may search the http://www.gnu.org website for the version 2 license,
- * or you may write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-/**
- * @file 3d_resolver.h
- * provides an extensible class to resolve 3D model paths.
- * Derived from 3d_filename_resolver.h,cpp and modified for
- * use in stand-alone utilities.
- */
-
-#ifndef RESOLVER_3D_H
-#define RESOLVER_3D_H
-
-#include <list>
-#include <map>
-#include <vector>
-#include <wx/string.h>
-
-namespace S3D
-{
-struct rsort_wxString
-{
-    bool operator() (const wxString& strA, const wxString& strB ) const
-    {
-        // sort a wxString using the reverse character order; for 3d model
-        // filenames this will typically be a much faster operation than
-        // a normal alphabetic sort
-        wxString::const_reverse_iterator sA = strA.rbegin();
-        wxString::const_reverse_iterator eA = strA.rend();
-
-        wxString::const_reverse_iterator sB = strB.rbegin();
-        wxString::const_reverse_iterator eB = strB.rend();
-
-        if( strA.empty() )
-        {
-            if( strB.empty() )
-                return false;
-
-            // note: this rule implies that a null string is first in the sort order
-            return true;
-        }
-
-        if( strB.empty() )
-            return false;
-
-        while( sA != eA && sB != eB )
-        {
-            if( (*sA) == (*sB) )
-            {
-                ++sA;
-                ++sB;
-                continue;
-            }
-
-            if( (*sA) < (*sB) )
-                return true;
-            else
-                return false;
-        }
-
-        if( sB == eB )
-            return false;
-
-        return true;
-    }
-};
-
-};  // end NAMESPACE
-
-
-class KICADPCB;
-
-struct SEARCH_PATH
-{
-    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
-    wxString m_Description;     // description of the aliased path
-};
-
-
-class S3D_RESOLVER
-{
-public:
-    S3D_RESOLVER();
-
-    /**
-     * Set the user's configuration directory for 3D models.
-     *
-     * @param aConfigDir
-     * @return true if the call succeeds (directory exists).
-     */
-    bool Set3DConfigDir( const wxString& aConfigDir );
-
-    /**
-     * Determine the full path of the given file name.
-     *
-     * In the future remote files may be supported, in which case it is best to require a full
-     * URI in which case #ResolvePath should check that the URI conforms to RFC-2396 and related
-     * documents and copies \a aFileName into the resolved name if the URI is valid.
-     *
-     * If the file is not found, \a aSearchedPaths will contain the paths that were searched.
-     */
-    wxString ResolvePath( const wxString& aFileName, std::vector<wxString>& aSearchedPaths );
-
-    /**
-     * Produce a relative path based on the existing search directories or returns the same path
-     * if the path is not a superset of an existing search path.
-     *
-     * @param aFullPathName is an absolute path to shorten.
-     * @return the shortened path or aFullPathName.
-     */
-    wxString ShortenPath( const wxString& aFullPathName );
-
-    /**
-     * Return a pointer to the internal path list.
-     *
-     * The list can be used to set up the list of search paths available to a 3D file browser.
-     *
-     * @return the search path list.
-     */
-    const std::list< SEARCH_PATH >* GetPaths( void );
-
-    /**
-     * Return true if the given name contains an alias and populates the string with the alias
-     * and the relative path.
-     */
-    bool SplitAlias( const wxString& aFileName, wxString& anAlias, wxString& aRelPath );
-
-    /**
-     * If the path contains an alias then \a hasAlias is set true.
-     *
-     * @return true if the given path is a valid aliased relative path.
-     */
-    bool ValidateFileName( const wxString& aFileName, bool& hasAlias );
-
-private:
-    /**
-     * Build the path list using available information such as KICAD6_3DMODEL_DIR and the
-     * 3d_path_list configuration file.
-     *
-     * Invalid paths are silently discarded and removed from the configuration file.
-     *
-     * @return true if at least one valid path was found
-     */
-    bool createPathList( void );
-
-    /**
-     * Check that \a aPath is valid and adds it to the search list.
-     *
-     * @param aPath is the alias set to be checked and added.
-     * @return true if \a aPath is valid.
-     */
-    bool addPath( const SEARCH_PATH& aPath );
-
-    /**
-     * Read a list of path names from a configuration file.
-     *
-     * @return true if a file was found and contained at least one valid path.
-     */
-    bool readPathList( void );
-
-    /**
-     * Check the ${ENV_VAR} component of a path and adds it to the resolver's path list if it
-     * is not yet in the list.
-     */
-    void checkEnvVarPath( const wxString& aPath );
-
-    wxString expandVars( const wxString& aPath );
-
-    std::list< SEARCH_PATH > m_Paths; ///< List of base search paths.
-
-    ///< Mapping of (short) file names to resolved names.
-    std::map< wxString, wxString, S3D::rsort_wxString > m_NameMap;
-    int m_errflags;
-    wxString m_curProjDir;
-
-    ///< Environment variables.
-    std::map< wxString, wxString > m_EnvVars;
-};
-
-#endif  // RESOLVER_3D_H
diff --git a/pcbnew/exporters/step/pcb/kicadfootprint.cpp b/pcbnew/exporters/step/pcb/kicadfootprint.cpp
index 222b4b00a0..ac596daf4a 100644
--- a/pcbnew/exporters/step/pcb/kicadfootprint.cpp
+++ b/pcbnew/exporters/step/pcb/kicadfootprint.cpp
@@ -24,7 +24,7 @@
 
 #include "kicadfootprint.h"
 
-#include "3d_resolver.h"
+#include <filename_resolver.h>
 #include "kicadcurve.h"
 #include "kicadmodel.h"
 #include "kicadpad.h"
@@ -358,7 +358,7 @@ bool KICADFOOTPRINT::parsePad( SEXPR::SEXPR* data )
 }
 
 
-bool KICADFOOTPRINT::ComposePCB( class PCBMODEL* aPCB, S3D_RESOLVER* resolver,
+bool KICADFOOTPRINT::ComposePCB( class PCBMODEL* aPCB, FILENAME_RESOLVER* resolver,
                                  DOUBLET aOrigin, bool aComposeVirtual, bool aSubstituteModels )
 {
     // translate pads and curves to final position and append to PCB.
@@ -439,22 +439,14 @@ bool KICADFOOTPRINT::ComposePCB( class PCBMODEL* aPCB, S3D_RESOLVER* resolver,
             continue;
 
         std::vector<wxString> searchedPaths;
-        mname = resolver->ResolvePath( mname, searchedPaths );
+        mname = resolver->ResolvePath( mname, wxEmptyString );
 
         if( !wxFileName::FileExists( mname ) )
         {
-            wxString paths;
-
-            for( const wxString& path : searchedPaths )
-                paths += "    " + path + "\n";
-
             ReportMessage( wxString::Format( wxT( "Could not add 3D model to %s.\n"
-                                                  "File not found: %s\n"
-                                                  "Searched paths:\n"
-                                                  "%s" ),
+                                                  "File not found: %s\n" ),
                                              m_refdes,
-                                             mname,
-                                             paths) );
+                                             mname) );
             continue;
         }
 
diff --git a/pcbnew/exporters/step/pcb/kicadfootprint.h b/pcbnew/exporters/step/pcb/kicadfootprint.h
index e0810f9c20..c6618e68c1 100644
--- a/pcbnew/exporters/step/pcb/kicadfootprint.h
+++ b/pcbnew/exporters/step/pcb/kicadfootprint.h
@@ -40,7 +40,7 @@ class KICADPAD;
 class KICADCURVE;
 class KICADMODEL;
 class PCBMODEL;
-class S3D_RESOLVER;
+class FILENAME_RESOLVER;
 
 class KICADFOOTPRINT
 {
@@ -50,7 +50,7 @@ public:
 
     bool Read( SEXPR::SEXPR* aEntry );
 
-    bool ComposePCB( class PCBMODEL* aPCB, S3D_RESOLVER* resolver,
+    bool ComposePCB( class PCBMODEL* aPCB, FILENAME_RESOLVER* resolver,
                      DOUBLET aOrigin, bool aComposeVirtual = true, bool aSubstituteModels = true );
 
 private:
diff --git a/pcbnew/exporters/step/pcb/kicadpcb.h b/pcbnew/exporters/step/pcb/kicadpcb.h
index 08669b6dba..8f40237b97 100644
--- a/pcbnew/exporters/step/pcb/kicadpcb.h
+++ b/pcbnew/exporters/step/pcb/kicadpcb.h
@@ -34,7 +34,7 @@
 #include <wx/colour.h>
 #include <string>
 #include <vector>
-#include "3d_resolver.h"
+#include <filename_resolver.h>
 #include "base.h"
 
 #ifdef SUPPORTS_IGES
@@ -102,7 +102,7 @@ private:
     bool parsePolygon( SEXPR::SEXPR* data );
 
 private:
-    S3D_RESOLVER                 m_resolver;
+    FILENAME_RESOLVER            m_resolver;
     wxString                     m_filename;
     PCBMODEL*                    m_pcb_model;
     DOUBLET                      m_origin;