forked from 0ad/0ad
TerrainTextureManager file loading rewrite. Fixes #3358.
Add directory callback to vfs::ForEachFile. Each terrain directory should now have a terrains.xml file, as using the previous terrains.xml file is unlikely to be what was intended. This was SVN commit r17341.
This commit is contained in:
parent
af202ae963
commit
6f09803e8c
@ -82,11 +82,6 @@ CTerrainTextureEntry* CTerrainTextureManager::FindTexture(const CStr& tag_) cons
|
||||
return 0;
|
||||
}
|
||||
|
||||
CTerrainPropertiesPtr CTerrainTextureManager::GetPropertiesFromFile(const CTerrainPropertiesPtr& props, const VfsPath& pathname)
|
||||
{
|
||||
return CTerrainProperties::FromXML(props, pathname);
|
||||
}
|
||||
|
||||
CTerrainTextureEntry* CTerrainTextureManager::AddTexture(const CTerrainPropertiesPtr& props, const VfsPath& path)
|
||||
{
|
||||
CTerrainTextureEntry* entry = new CTerrainTextureEntry(props, path);
|
||||
@ -103,64 +98,37 @@ void CTerrainTextureManager::DeleteTexture(CTerrainTextureEntry* entry)
|
||||
delete entry;
|
||||
}
|
||||
|
||||
// FIXME This could be effectivized by surveying the xml files in the directory
|
||||
// instead of trial-and-error checking for existence of the xml file through
|
||||
// the VFS.
|
||||
// jw: indeed this is inefficient and RecurseDirectory should be implemented
|
||||
// via VFSUtil::EnumFiles, but it works fine and "only" takes 25ms for
|
||||
// typical maps. therefore, we'll leave it for now.
|
||||
void CTerrainTextureManager::LoadTextures(const CTerrainPropertiesPtr& props, const VfsPath& path)
|
||||
struct AddTextureCallbackData
|
||||
{
|
||||
VfsPaths pathnames;
|
||||
if(vfs::GetPathnames(g_VFS, path, 0, pathnames) < 0)
|
||||
return;
|
||||
CTerrainTextureManager* self;
|
||||
CTerrainPropertiesPtr props;
|
||||
};
|
||||
|
||||
for(size_t i = 0; i < pathnames.size(); i++)
|
||||
{
|
||||
if (pathnames[i].Extension() != L".xml")
|
||||
continue;
|
||||
|
||||
if (pathnames[i].Basename() == L"terrains")
|
||||
continue;
|
||||
|
||||
AddTexture(props, pathnames[i]);
|
||||
}
|
||||
static Status AddTextureDirCallback(const VfsPath& pathname, const uintptr_t cbData)
|
||||
{
|
||||
AddTextureCallbackData& data = *(AddTextureCallbackData*)cbData;
|
||||
VfsPath path = pathname / L"terrains.xml";
|
||||
if (!VfsFileExists(path))
|
||||
LOGMESSAGE("'%s' does not exist. Using previous properties.", path.string8());
|
||||
else
|
||||
data.props = CTerrainProperties::FromXML(data.props, path);
|
||||
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
void CTerrainTextureManager::RecurseDirectory(const CTerrainPropertiesPtr& parentProps, const VfsPath& path)
|
||||
static Status AddTextureCallback(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData)
|
||||
{
|
||||
//LOGMESSAGE("CTextureManager::RecurseDirectory(%s)", path.string8());
|
||||
AddTextureCallbackData& data = *(AddTextureCallbackData*)cbData;
|
||||
if (pathname.Basename() != L"terrains")
|
||||
data.self->AddTexture(data.props, pathname);
|
||||
|
||||
CTerrainPropertiesPtr props;
|
||||
|
||||
// Load terrains.xml first, if it exists
|
||||
VfsPath pathname = path / "terrains.xml";
|
||||
if (VfsFileExists(pathname))
|
||||
props = GetPropertiesFromFile(parentProps, pathname);
|
||||
|
||||
// No terrains.xml, or read failures -> use parent props (i.e.
|
||||
if (!props)
|
||||
{
|
||||
LOGMESSAGE("CTerrainTextureManager::RecurseDirectory(%s): no terrains.xml (or errors while loading) - using parent properties", path.string8());
|
||||
props = parentProps;
|
||||
}
|
||||
|
||||
// Recurse once for each subdirectory
|
||||
DirectoryNames subdirectoryNames;
|
||||
(void)g_VFS->GetDirectoryEntries(path, 0, &subdirectoryNames);
|
||||
for (size_t i=0;i<subdirectoryNames.size();i++)
|
||||
{
|
||||
VfsPath subdirectoryPath = path / subdirectoryNames[i] / "";
|
||||
RecurseDirectory(props, subdirectoryPath);
|
||||
}
|
||||
|
||||
LoadTextures(props, path);
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
int CTerrainTextureManager::LoadTerrainTextures()
|
||||
{
|
||||
CTerrainPropertiesPtr rootProps(new CTerrainProperties(CTerrainPropertiesPtr()));
|
||||
RecurseDirectory(rootProps, L"art/terrains/");
|
||||
AddTextureCallbackData data = {this, CTerrainPropertiesPtr(new CTerrainProperties(CTerrainPropertiesPtr()))};
|
||||
vfs::ForEachFile(g_VFS, L"art/terrains/", AddTextureCallback, (uintptr_t)&data, L"*.xml", vfs::DIR_RECURSIVE, AddTextureDirCallback, (uintptr_t)&data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -103,15 +103,6 @@ private:
|
||||
|
||||
size_t m_LastGroupIndex;
|
||||
|
||||
// Find+load all textures in directory; check if
|
||||
// there's an override XML with the same basename (if there is, load it)
|
||||
void LoadTextures(const CTerrainPropertiesPtr& props, const VfsPath& path);
|
||||
|
||||
// Load all terrains below path, using props as the parent property sheet.
|
||||
void RecurseDirectory(const CTerrainPropertiesPtr& props, const VfsPath& path);
|
||||
|
||||
CTerrainPropertiesPtr GetPropertiesFromFile(const CTerrainPropertiesPtr& props, const VfsPath& pathname);
|
||||
|
||||
public:
|
||||
// constructor, destructor
|
||||
CTerrainTextureManager();
|
||||
|
@ -56,7 +56,7 @@ Status GetPathnames(const PIVFS& fs, const VfsPath& path, const wchar_t* filter,
|
||||
}
|
||||
|
||||
|
||||
Status ForEachFile(const PIVFS& fs, const VfsPath& startPath, FileCallback cb, uintptr_t cbData, const wchar_t* pattern, size_t flags)
|
||||
Status ForEachFile(const PIVFS& fs, const VfsPath& startPath, FileCallback cb, uintptr_t cbData, const wchar_t* pattern, size_t flags, DirCallback dircb, uintptr_t dircbData)
|
||||
{
|
||||
// (declare here to avoid reallocations)
|
||||
CFileInfos files;
|
||||
@ -72,6 +72,9 @@ Status ForEachFile(const PIVFS& fs, const VfsPath& startPath, FileCallback cb, u
|
||||
|
||||
RETURN_STATUS_IF_ERR(fs->GetDirectoryEntries(path, &files, &subdirectoryNames));
|
||||
|
||||
if(dircb)
|
||||
RETURN_STATUS_IF_ERR(dircb(path, dircbData));
|
||||
|
||||
for(size_t i = 0; i < files.size(); i++)
|
||||
{
|
||||
const CFileInfo fileInfo = files[i];
|
||||
|
@ -48,13 +48,25 @@ extern Status GetPathnames(const PIVFS& fs, const VfsPath& path, const wchar_t*
|
||||
**/
|
||||
typedef Status (*FileCallback)(const VfsPath& pathname, const CFileInfo& fileInfo, const uintptr_t cbData);
|
||||
|
||||
/**
|
||||
* called for directories in a directory.
|
||||
*
|
||||
* @param pathname full pathname
|
||||
* @param cbData user-specified context
|
||||
* @return INFO::OK on success; any other value will immediately
|
||||
* be returned to the caller (no more calls will be forthcoming).
|
||||
*
|
||||
* CAVEAT: pathname only valid until the function returns!
|
||||
**/
|
||||
typedef Status (*DirCallback)(const VfsPath& pathname, const uintptr_t cbData);
|
||||
|
||||
enum DirFlags
|
||||
{
|
||||
DIR_RECURSIVE = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* call back for each file in a directory tree
|
||||
* call back for each file in a directory tree, and optionally each directory.
|
||||
*
|
||||
* @param fs
|
||||
* @param path
|
||||
@ -63,9 +75,11 @@ enum DirFlags
|
||||
* @param pattern that file names must match. '*' and '&' wildcards
|
||||
* are allowed. 0 matches everything.
|
||||
* @param flags @ref DirFlags
|
||||
* @param dircb @ref DirCallback
|
||||
* @param dircbData
|
||||
* @return Status
|
||||
**/
|
||||
extern Status ForEachFile(const PIVFS& fs, const VfsPath& path, FileCallback cb, uintptr_t cbData, const wchar_t* pattern = 0, size_t flags = 0);
|
||||
extern Status ForEachFile(const PIVFS& fs, const VfsPath& path, FileCallback cb, uintptr_t cbData, const wchar_t* pattern = 0, size_t flags = 0, DirCallback dircb = NULL, uintptr_t dircbData = 0);
|
||||
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user