Files
UnrealEngine/Engine/Source/ThirdParty/MaterialX/MaterialX-1.38.10/source/MaterialXFormat/Util.cpp
2025-05-18 13:04:45 +08:00

241 lines
7.7 KiB
C++

//
// Copyright Contributors to the MaterialX Project
// SPDX-License-Identifier: Apache-2.0
//
#include <MaterialXFormat/Util.h>
#include <fstream>
#include <iostream>
#include <sstream>
MATERIALX_NAMESPACE_BEGIN
string readFile(const FilePath& filePath)
{
std::ifstream file(filePath.asString(), std::ios::in);
if (file)
{
std::stringstream stream;
stream << file.rdbuf();
file.close();
if (stream)
{
return stream.str();
}
}
return EMPTY_STRING;
}
void getSubdirectories(const FilePathVec& rootDirectories, const FileSearchPath& searchPath, FilePathVec& subDirectories)
{
for (const FilePath& root : rootDirectories)
{
FilePath rootPath = searchPath.find(root);
if (rootPath.exists())
{
FilePathVec childDirectories = rootPath.getSubDirectories();
subDirectories.insert(std::end(subDirectories), std::begin(childDirectories), std::end(childDirectories));
}
}
}
void loadDocuments(const FilePath& rootPath, const FileSearchPath& searchPath, const StringSet& skipFiles,
const StringSet& includeFiles, vector<DocumentPtr>& documents, StringVec& documentsPaths,
const XmlReadOptions* readOptions, StringVec* errors)
{
for (const FilePath& dir : rootPath.getSubDirectories())
{
for (const FilePath& file : dir.getFilesInDirectory(MTLX_EXTENSION))
{
if (!skipFiles.count(file) &&
(includeFiles.empty() || includeFiles.count(file)))
{
DocumentPtr doc = createDocument();
const FilePath filePath = dir / file;
try
{
FileSearchPath readSearchPath(searchPath);
readSearchPath.append(dir);
readFromXmlFile(doc, filePath, readSearchPath, readOptions);
documents.push_back(doc);
documentsPaths.push_back(filePath.asString());
}
catch (Exception& e)
{
if (errors)
{
errors->push_back("Failed to load: " + filePath.asString() + ". Error: " + e.what());
}
}
}
}
}
}
void loadLibrary(const FilePath& file, DocumentPtr doc, const FileSearchPath& searchPath, const XmlReadOptions* readOptions)
{
DocumentPtr libDoc = createDocument();
readFromXmlFile(libDoc, file, searchPath, readOptions);
doc->importLibrary(libDoc);
}
StringSet loadLibraries(const FilePathVec& libraryFolders,
const FileSearchPath& searchPath,
DocumentPtr doc,
const StringSet& excludeFiles,
const XmlReadOptions* readOptions)
{
// Append environment path to the specified search path.
FileSearchPath librarySearchPath = searchPath;
librarySearchPath.append(getEnvironmentPath());
StringSet loadedLibraries;
if (libraryFolders.empty())
{
// No libraries specified so scan in all search paths
for (const FilePath& libraryPath : librarySearchPath)
{
for (const FilePath& path : libraryPath.getSubDirectories())
{
for (const FilePath& filename : path.getFilesInDirectory(MTLX_EXTENSION))
{
if (!excludeFiles.count(filename))
{
const FilePath& file = path / filename;
if (loadedLibraries.count(file) == 0)
{
loadLibrary(file, doc, searchPath, readOptions);
loadedLibraries.insert(file.asString());
}
}
}
}
}
}
else
{
// Look for specific library folders in the search paths
for (const FilePath& libraryName : libraryFolders)
{
FilePath libraryPath = librarySearchPath.find(libraryName);
for (const FilePath& path : libraryPath.getSubDirectories())
{
for (const FilePath& filename : path.getFilesInDirectory(MTLX_EXTENSION))
{
if (!excludeFiles.count(filename))
{
const FilePath& file = path / filename;
if (loadedLibraries.count(file) == 0)
{
loadLibrary(file, doc, searchPath, readOptions);
loadedLibraries.insert(file.asString());
}
}
}
}
}
}
return loadedLibraries;
}
void flattenFilenames(DocumentPtr doc, const FileSearchPath& searchPath, StringResolverPtr customResolver)
{
for (ElementPtr elem : doc->traverseTree())
{
ValueElementPtr valueElem = elem->asA<ValueElement>();
if (!valueElem || valueElem->getType() != FILENAME_TYPE_STRING)
{
continue;
}
FilePath unresolvedValue(valueElem->getValueString());
if (unresolvedValue.isEmpty())
{
continue;
}
StringResolverPtr elementResolver = elem->createStringResolver();
// If the path is already absolute then don't allow an additional prefix
// as this would make the path invalid.
if (unresolvedValue.isAbsolute())
{
elementResolver->setFilePrefix(EMPTY_STRING);
}
string resolvedString = valueElem->getResolvedValueString(elementResolver);
// Convert relative to absolute pathing if the file is not already found
if (!searchPath.isEmpty())
{
FilePath resolvedValue(resolvedString);
if (!resolvedValue.isAbsolute())
{
for (size_t i = 0; i < searchPath.size(); i++)
{
FilePath testPath = searchPath[i] / resolvedValue;
testPath = testPath.getNormalized();
if (testPath.exists())
{
resolvedString = testPath.asString();
break;
}
}
}
}
// Apply any custom filename resolver
if (customResolver && customResolver->isResolvedType(FILENAME_TYPE_STRING))
{
resolvedString = customResolver->resolve(resolvedString, FILENAME_TYPE_STRING);
}
valueElem->setValueString(resolvedString);
}
// Remove any file prefix attributes
for (ElementPtr elem : doc->traverseTree())
{
if (elem->hasFilePrefix())
{
elem->removeAttribute(Element::FILE_PREFIX_ATTRIBUTE);
}
}
}
FileSearchPath getSourceSearchPath(ConstDocumentPtr doc)
{
StringSet pathSet;
for (ConstElementPtr elem : doc->traverseTree())
{
if (elem->hasSourceUri())
{
FilePath sourceFilename = FilePath(elem->getSourceUri());
pathSet.insert(sourceFilename.getParentPath());
}
}
FileSearchPath searchPath;
for (FilePath path : pathSet)
{
searchPath.append(path);
}
return searchPath;
}
FileSearchPath getDefaultDataSearchPath()
{
const FilePath REQUIRED_LIBRARY_FOLDER("libraries/targets");
FilePath currentPath = FilePath::getModulePath();
while (!currentPath.isEmpty())
{
if ((currentPath / REQUIRED_LIBRARY_FOLDER).exists())
{
return FileSearchPath(currentPath);
}
currentPath = currentPath.getParentPath();
}
return FileSearchPath();
}
MATERIALX_NAMESPACE_END