45const std::vector<wxString>& stepExtensions()
47 static const std::vector<wxString> exts = {
48 wxS(
"step" ), wxS(
"stp" ), wxS(
"stpz" ),
49 wxS(
"step.gz" ), wxS(
"stp.gz" ),
50 wxS(
"iges" ), wxS(
"igs" )
59const std::vector<wxString>& dottedStepExtensions()
61 static const std::vector<wxString> dotted = []
63 std::vector<wxString>
result;
64 result.reserve( stepExtensions().size() );
66 for(
const wxString& ext : stepExtensions() )
67 result.push_back( wxS(
"." ) + ext );
76bool hasStepExtension(
const wxString& aPath )
78 const wxString lower = aPath.Lower();
80 for(
const wxString& dotted : dottedStepExtensions() )
82 if( lower.length() > dotted.length()
83 && lower.Right( dotted.length() ) == dotted )
96wxString normalizeStem(
const wxString& aName )
98 wxString stem = aName;
100 static const wxString stripList[] = {
101 wxS(
".step.gz" ), wxS(
".stp.gz" ),
102 wxS(
".wrl" ), wxS(
".wrz" ),
103 wxS(
".step" ), wxS(
".stp" ), wxS(
".stpz" ),
104 wxS(
".iges" ), wxS(
".igs" )
107 for(
const wxString& ext : stripList )
109 if( stem.length() > ext.length()
110 && stem.Right( ext.length() ).Lower() == ext )
112 stem = stem.Left( stem.length() - ext.length() );
119 stem.Replace( wxS(
"-" ), wxS(
"_" ) );
120 stem.Replace( wxS(
" " ), wxS(
"_" ) );
126wxString parentDirName(
const wxString& aPath )
128 wxFileName fn( aPath );
129 const wxArrayString& dirs = fn.GetDirs();
131 return dirs.empty() ? wxString() : dirs.Last();
138std::vector<wxString> gatherScanDirs(
const wxString& aProjectPath,
141 std::vector<wxString>
result;
142 std::unordered_set<wxString> seen;
144 auto addDir = [&](
const wxString& aDir )
149 wxFileName norm( aDir, wxEmptyString );
150 norm.Normalize( wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS );
151 const wxString key = norm.GetPath().Lower();
153 if( !seen.insert( key ).second )
156 if( wxDir::Exists( norm.GetPath() ) )
157 result.push_back( norm.GetPath() );
162 if(
const std::list<SEARCH_PATH>* paths = aResolver->
GetPaths() )
165 addDir( sp.m_Pathexp );
169 if( !aProjectPath.IsEmpty() )
171 wxFileName prj3D( aProjectPath, wxEmptyString );
172 prj3D.AppendDir( wxS(
"3dshapes" ) );
173 addDir( prj3D.GetPath() );
178 for(
const wxString& dir : common->m_Extra3DSearchDirs )
190 const wxString ext = aFilename.AfterLast(
'.' ).Lower();
192 return ext == wxS(
"wrl" ) || ext == wxS(
"wrz" );
200 for(
const wxString& dir : gatherScanDirs( aProjectPath, aResolver ) )
203 wxDir::GetAllFiles( dir, &files, wxEmptyString, wxDIR_FILES | wxDIR_DIRS );
205 for(
const wxString& file : files )
207 if( !hasStepExtension( file ) )
210 const wxString stem = normalizeStem( wxFileName( file ).GetFullName() );
224 return wxEmptyString;
226 const wxString stem = normalizeStem( wxFileName( aMissingWrl ).GetFullName() );
229 return wxEmptyString;
233 if( it ==
m_byStem.end() || it->second.empty() )
234 return wxEmptyString;
236 const wxString wrlParent = parentDirName( aMissingWrl );
238 if( !wrlParent.IsEmpty() )
240 for(
const wxString& candidate : it->second )
242 if( parentDirName( candidate ).CmpNoCase( wrlParent ) == 0 )
247 return it->second.front();
wxString result
Test unit parsing edge cases and error handling.