46const std::vector<wxString>& stepExtensions()
48 static const std::vector<wxString> exts = {
49 wxS(
"step" ), wxS(
"stp" ), wxS(
"stpz" ),
50 wxS(
"step.gz" ), wxS(
"stp.gz" ),
51 wxS(
"iges" ), wxS(
"igs" )
60const std::vector<wxString>& dottedStepExtensions()
62 static const std::vector<wxString> dotted = []
64 std::vector<wxString>
result;
65 result.reserve( stepExtensions().size() );
67 for(
const wxString& ext : stepExtensions() )
68 result.push_back( wxS(
"." ) + ext );
77bool hasStepExtension(
const wxString& aPath )
79 const wxString lower = aPath.Lower();
81 for(
const wxString& dotted : dottedStepExtensions() )
83 if( lower.length() > dotted.length()
84 && lower.Right( dotted.length() ) == dotted )
97wxString normalizeStem(
const wxString& aName )
99 wxString stem = aName;
101 static const wxString stripList[] = {
102 wxS(
".step.gz" ), wxS(
".stp.gz" ),
103 wxS(
".wrl" ), wxS(
".wrz" ),
104 wxS(
".step" ), wxS(
".stp" ), wxS(
".stpz" ),
105 wxS(
".iges" ), wxS(
".igs" )
108 for(
const wxString& ext : stripList )
110 if( stem.length() > ext.length()
111 && stem.Right( ext.length() ).Lower() == ext )
113 stem = stem.Left( stem.length() - ext.length() );
120 stem.Replace( wxS(
"-" ), wxS(
"_" ) );
121 stem.Replace( wxS(
" " ), wxS(
"_" ) );
127wxString parentDirName(
const wxString& aPath )
129 wxFileName fn( aPath );
130 const wxArrayString& dirs = fn.GetDirs();
132 return dirs.empty() ? wxString() : dirs.Last();
139std::vector<wxString> gatherScanDirs(
const wxString& aProjectPath,
142 std::vector<wxString>
result;
143 std::unordered_set<wxString> seen;
145 auto addDir = [&](
const wxString& aDir )
150 wxFileName norm( aDir, wxEmptyString );
151 norm.Normalize( wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS );
152 const wxString key = norm.GetPath().Lower();
154 if( !seen.insert( key ).second )
157 if( wxDir::Exists( norm.GetPath() ) )
158 result.push_back( norm.GetPath() );
163 if(
const std::list<SEARCH_PATH>* paths = aResolver->
GetPaths() )
166 addDir( sp.m_Pathexp );
170 if( !aProjectPath.IsEmpty() )
172 wxFileName prj3D( aProjectPath, wxEmptyString );
173 prj3D.AppendDir( wxS(
"3dshapes" ) );
174 addDir( prj3D.GetPath() );
179 for(
const wxString& dir : common->m_Extra3DSearchDirs )
191 const wxString ext = aFilename.AfterLast(
'.' ).Lower();
193 return ext == wxS(
"wrl" ) || ext == wxS(
"wrz" );
201 for(
const wxString& dir : gatherScanDirs( aProjectPath, aResolver ) )
206 for(
const wxString& file : files )
208 if( !hasStepExtension( file ) )
211 const wxString stem = normalizeStem( wxFileName( file ).GetFullName() );
225 return wxEmptyString;
227 const wxString stem = normalizeStem( wxFileName( aMissingWrl ).GetFullName() );
230 return wxEmptyString;
234 if( it ==
m_byStem.end() || it->second.empty() )
235 return wxEmptyString;
237 const wxString wrlParent = parentDirName( aMissingWrl );
239 if( !wrlParent.IsEmpty() )
241 for(
const wxString& candidate : it->second )
243 if( parentDirName( candidate ).CmpNoCase( wrlParent ) == 0 )
248 return it->second.front();
void CollectFilesLoopSafe(const wxString &aRoot, wxArrayString &aFiles, const wxString &aFileSpec, int aFlags)
Recursively collect every file under aRoot, deduplicating subdirectories by their resolved path.
wxString result
Test unit parsing edge cases and error handling.