From a3bd6b9c4f775b9cee9ab29901ff82cb20157584 Mon Sep 17 00:00:00 2001 From: danij Date: Sat, 7 Jan 2012 01:25:31 +0000 Subject: [PATCH] Added search path flag SPF_NO_DECEND ResourceNamespace search paths are now defined including a set of flags which govern how the path will be interpreted. SPF_NO_DECEND means that only resources in the base of the search target will be included when populating the namespace. Otherwise, all resources below the base of the search target will be included. --- .../portable/include/resourcenamespace.h | 26 +++++- .../engine/portable/include/sys_reslocator.h | 10 ++- doomsday/engine/portable/src/dd_main.c | 2 +- doomsday/engine/portable/src/def_read.c | 11 ++- .../engine/portable/src/resourcenamespace.c | 72 ++++++++++++--- doomsday/engine/portable/src/sys_reslocator.c | 90 ++++++++++--------- 6 files changed, 145 insertions(+), 66 deletions(-) diff --git a/doomsday/engine/portable/include/resourcenamespace.h b/doomsday/engine/portable/include/resourcenamespace.h index b167e81e5d..f512bff0f8 100644 --- a/doomsday/engine/portable/include/resourcenamespace.h +++ b/doomsday/engine/portable/include/resourcenamespace.h @@ -38,6 +38,13 @@ typedef enum { #define VALID_RESOURCENAMESPACE_SEARCHPATHGROUP(g) ((g) >= SPG_OVERRIDE && (g) < SEARCHPATHGROUP_COUNT) +/** + * @defgroup searchPathFlags Search Path Flags + * @{ + */ +#define SPF_NO_DECEND 0x1 /// Do not decend into branches when populating paths. +/**@}*/ + /** * Resource Namespace. * @@ -47,10 +54,15 @@ typedef enum { #define RESOURCENAMESPACE_HASHSIZE 512 typedef unsigned short resourcenamespace_namehash_key_t; +typedef struct { + int flags; /// @see searchPathFlags + Uri* uri; +} resourcenamespace_searchpath_t; + typedef struct { /// Sets of search paths known by this namespace. /// Each set is in order of greatest-importance, right to left. - Uri** _searchPaths[SEARCHPATHGROUP_COUNT]; + resourcenamespace_searchpath_t* _searchPaths[SEARCHPATHGROUP_COUNT]; uint _searchPathsCount[SEARCHPATHGROUP_COUNT]; /// Name hash table. @@ -73,12 +85,13 @@ void ResourceNamespace_Clear(resourcenamespace_t* rnamespace); /** * Add a new path to this namespace. * + * @param flags @see searchPathFlags * @param path New unresolved path to add. * @param group Group to add this path to. @see resourcenamespace_searchpathgroup_t * @return @c true if the path is correctly formed and present in the namespace. */ -boolean ResourceNamespace_AddSearchPath(resourcenamespace_t* rn, const Uri* path, - resourcenamespace_searchpathgroup_t group); +boolean ResourceNamespace_AddSearchPath(resourcenamespace_t* rn, int flags, + const Uri* path, resourcenamespace_searchpathgroup_t group); /** * Clear search paths in this namespace. @@ -87,7 +100,7 @@ boolean ResourceNamespace_AddSearchPath(resourcenamespace_t* rn, const Uri* path void ResourceNamespace_ClearSearchPaths(resourcenamespace_t* rn, resourcenamespace_searchpathgroup_t group); /** - * Compose the list of search paths into a @a delimited string. + * Compose the list of search paths into a delimited string. * * @param delimiter Discreet paths will be delimited by this character. * @return Resultant string which should be released with Str_Delete(). @@ -95,6 +108,11 @@ void ResourceNamespace_ClearSearchPaths(resourcenamespace_t* rn, resourcenamespa ddstring_t* ResourceNamespace_ComposeSearchPathList2(resourcenamespace_t* rn, char delimiter); ddstring_t* ResourceNamespace_ComposeSearchPathList(resourcenamespace_t* rn); /*delimiter= ';'*/ +int ResourceNamespace_IterateSearchPaths2(resourcenamespace_t* rn, + int (*callback) (const Uri* uri, int flags, void* paramaters), void* paramaters); +int ResourceNamespace_IterateSearchPaths(resourcenamespace_t* rn, + int (*callback) (const Uri* uri, int flags, void* paramaters)); /*paramaters=NULL*/ + /** * Add a new named resource into the namespace. Multiple names for a given * resource may coexist however duplicates are automatically pruned. diff --git a/doomsday/engine/portable/include/sys_reslocator.h b/doomsday/engine/portable/include/sys_reslocator.h index b1111b681f..847d2ef143 100644 --- a/doomsday/engine/portable/include/sys_reslocator.h +++ b/doomsday/engine/portable/include/sys_reslocator.h @@ -139,8 +139,14 @@ resourcenamespace_t* F_CreateResourceNamespace(const char* name, FileDirectory* directory, ddstring_t* (*composeHashNameFunc) (const ddstring_t* path), resourcenamespace_namehash_key_t (*hashNameFunc) (const ddstring_t* name), byte flags); -boolean F_AddSearchPathToResourceNamespace(resourcenamespaceid_t rni, const Uri* uri, - resourcenamespace_searchpathgroup_t group); +/** + * @param rni Unique identifier of the namespace to add to. + * @param flags @see searchPathFlags + * @param searchPath Uri representing the search path to be added. + * @param group Group to add the new search path to. + */ +boolean F_AddSearchPathToResourceNamespace(resourcenamespaceid_t rni, int flags, + const Uri* searchPath, resourcenamespace_searchpathgroup_t group); const ddstring_t* F_ResourceNamespaceName(resourcenamespaceid_t rni); diff --git a/doomsday/engine/portable/src/dd_main.c b/doomsday/engine/portable/src/dd_main.c index b8170caac1..a675116371 100644 --- a/doomsday/engine/portable/src/dd_main.c +++ b/doomsday/engine/portable/src/dd_main.c @@ -1503,7 +1503,7 @@ int DD_Main(void) dir = Dir_ConstructFromPathDir(filePath); searchPath = Uri_NewWithPath2(Dir_Path(dir), RC_PACKAGE); - F_AddSearchPathToResourceNamespace(rnId, searchPath, SPG_DEFAULT); + F_AddSearchPathToResourceNamespace(rnId, 0, searchPath, SPG_DEFAULT); Uri_Delete(searchPath); Dir_Delete(dir); diff --git a/doomsday/engine/portable/src/def_read.c b/doomsday/engine/portable/src/def_read.c index 9741c6939f..c3b07d1ede 100644 --- a/doomsday/engine/portable/src/def_read.c +++ b/doomsday/engine/portable/src/def_read.c @@ -815,12 +815,15 @@ static int DED_ReadData(ded_t* ded, const char* buffer, const char* _sourceFile) if(ISTOKEN("ModelPath")) { + Uri* newSearchPath; + READSTR(label); CHECKSC; - { Uri* newUri = Uri_NewWithPath2(label, RC_NULL); - F_AddSearchPathToResourceNamespace(F_DefaultResourceNamespaceForClass(RC_MODEL), newUri, SPG_EXTRA); - Uri_Delete(newUri); - } + + newSearchPath = Uri_NewWithPath2(label, RC_NULL); + F_AddSearchPathToResourceNamespace(F_DefaultResourceNamespaceForClass(RC_MODEL), + 0, newSearchPath, SPG_EXTRA); + Uri_Delete(newSearchPath); } if(ISTOKEN("Header")) diff --git a/doomsday/engine/portable/src/resourcenamespace.c b/doomsday/engine/portable/src/resourcenamespace.c index 1ca2fb310d..e9e45e5b8d 100644 --- a/doomsday/engine/portable/src/resourcenamespace.c +++ b/doomsday/engine/portable/src/resourcenamespace.c @@ -119,7 +119,7 @@ static void appendSearchPathsInGroup(resourcenamespace_t* rn, for(i = 0; i < rn->_searchPathsCount[group]; ++i) { - ddstring_t* path = Uri_ComposePath(rn->_searchPaths[group][i]); + ddstring_t* path = Uri_ComposePath(rn->_searchPaths[group][i].uri); Str_Appendf(pathList, "%s%c", Str_Text(path), delimiter); Str_Delete(path); } @@ -190,35 +190,48 @@ void ResourceNamespace_Clear(resourcenamespace_t* rn) clearNameHash(rn); } -boolean ResourceNamespace_AddSearchPath(resourcenamespace_t* rn, const Uri* newUri, - resourcenamespace_searchpathgroup_t group) +boolean ResourceNamespace_AddSearchPath(resourcenamespace_t* rn, int flags, + const Uri* searchPath, resourcenamespace_searchpathgroup_t group) { uint i, j; - assert(rn && newUri && VALID_RESOURCENAMESPACE_SEARCHPATHGROUP(group)); + assert(rn); - if(Str_IsEmpty(Uri_Path(newUri)) || !Str_CompareIgnoreCase(Uri_Path(newUri), "/")) - return false; // Not suitable. + // Is this suitable? + if(!searchPath || Str_IsEmpty(Uri_Path(searchPath)) || !Str_CompareIgnoreCase(Uri_Path(searchPath), "/")) + return false; + + if(!VALID_RESOURCENAMESPACE_SEARCHPATHGROUP(group)) + { +#if _DEBUG + Con_Message("ResourceNamespace::AddSearchPath: Invalid SearchPathGroup %i, ignoring.\n", (int)group); +#endif + return false; + } // Have we seen this path already (we don't want duplicates)? for(i = 0; i < SEARCHPATHGROUP_COUNT; ++i) for(j = 0; j < rn->_searchPathsCount[i]; ++j) { - if(Uri_Equality(rn->_searchPaths[i][j], newUri)) + if(Uri_Equality(rn->_searchPaths[i][j].uri, searchPath)) + { + rn->_searchPaths[i][j].flags = flags; return true; + } } - rn->_searchPaths[group] = (Uri**) realloc(rn->_searchPaths[group], - sizeof **rn->_searchPaths * ++rn->_searchPathsCount[group]); + rn->_searchPaths[group] = realloc(rn->_searchPaths[group], + sizeof(**rn->_searchPaths) * ++rn->_searchPathsCount[group]); if(!rn->_searchPaths[group]) - Con_Error("ResourceNamespace::AddExtraSearchPath: Failed on reallocation of %lu bytes for " + Con_Error("ResourceNamespace::AddSearchPath: Failed on reallocation of %lu bytes for " "searchPath list.", (unsigned long) sizeof **rn->_searchPaths * (rn->_searchPathsCount[group]-1)); // Prepend to the path list - newer paths have priority. if(rn->_searchPathsCount[group] > 1) memmove(rn->_searchPaths[group] + 1, rn->_searchPaths[group], sizeof(*rn->_searchPaths[group]) * (rn->_searchPathsCount[group]-1)); - rn->_searchPaths[group][0] = Uri_NewCopy(newUri); + rn->_searchPaths[group][0].uri = Uri_NewCopy(searchPath); + rn->_searchPaths[group][0].flags = flags; return true; } @@ -226,13 +239,21 @@ boolean ResourceNamespace_AddSearchPath(resourcenamespace_t* rn, const Uri* newU void ResourceNamespace_ClearSearchPaths(resourcenamespace_t* rn, resourcenamespace_searchpathgroup_t group) { uint i; - assert(rn && VALID_RESOURCENAMESPACE_SEARCHPATHGROUP(group)); + assert(rn); + + if(!VALID_RESOURCENAMESPACE_SEARCHPATHGROUP(group)) + { +#if _DEBUG + Con_Message("ResourceNamespace::ClearSearchPaths: Invalid SearchPathGroup %i, ignoring.\n", (int)group); +#endif + return; + } if(!rn->_searchPaths[group]) return; for(i = 0; i < rn->_searchPathsCount[group]; ++i) { - Uri_Delete(rn->_searchPaths[group][i]); + Uri_Delete(rn->_searchPaths[group][i].uri); } free(rn->_searchPaths[group]); rn->_searchPaths[group] = 0; @@ -249,6 +270,31 @@ ddstring_t* ResourceNamespace_ComposeSearchPathList(resourcenamespace_t* rn) return ResourceNamespace_ComposeSearchPathList2(rn, ';'); } +int ResourceNamespace_IterateSearchPaths2(resourcenamespace_t* rn, + int (*callback) (const Uri* uri, int flags, void* paramaters), void* paramaters) +{ + int result = 0; + assert(rn); + if(callback) + { + uint i, j; + for(i = 0; i < SEARCHPATHGROUP_COUNT; ++i) + for(j = 0; j < rn->_searchPathsCount[i]; ++j) + { + resourcenamespace_searchpath_t* path = &rn->_searchPaths[i][j]; + result = callback(path->uri, path->flags, paramaters); + if(result) return result; + } + } + return result; +} + +int ResourceNamespace_IterateSearchPaths(resourcenamespace_t* rn, + int (*callback) (const Uri* uri, int flags, void* paramaters)) +{ + return ResourceNamespace_IterateSearchPaths2(rn, callback, NULL); +} + int ResourceNamespace_Iterate2(resourcenamespace_t* rn, const ddstring_t* name, int (*callback) (PathDirectoryNode* node, void* paramaters), void* paramaters) { diff --git a/doomsday/engine/portable/src/sys_reslocator.c b/doomsday/engine/portable/src/sys_reslocator.c index cf26e56d07..5fba683ffc 100644 --- a/doomsday/engine/portable/src/sys_reslocator.c +++ b/doomsday/engine/portable/src/sys_reslocator.c @@ -204,7 +204,8 @@ static void resetAllNamespaces(void) } } -static void addResourceToNamespace(resourcenamespaceinfo_t* rnInfo, PathDirectoryNode* node) +static void addResourceToNamespace(resourcenamespaceinfo_t* rnInfo, + PathDirectoryNode* node) { ddstring_t* name; assert(rnInfo && node); @@ -697,7 +698,7 @@ static void createPackagesResourceNamespace(void) uint i; for(i = 0; i < searchPathsCount; ++i) { - ResourceNamespace_AddSearchPath(rnamespace, searchPaths[i], SPG_DEFAULT); + ResourceNamespace_AddSearchPath(rnamespace, 0, searchPaths[i], SPG_DEFAULT); } } @@ -714,29 +715,40 @@ void F_CreateNamespacesForFileResourcePaths(void) const char* name; const char* optOverridePath; const char* optFallbackPath; - byte flags; - const char* defaultPaths[NAMESPACEDEF_MAX_SEARCHPATHS]; + byte flags; /// @see resourceNamespaceFlags + int searchPathFlags; /// @see searchPathFlags + const char* searchPaths[NAMESPACEDEF_MAX_SEARCHPATHS]; } defs[] = { - { DEFINITIONS_RESOURCE_NAMESPACE_NAME, NULL, NULL, 0, - { "$(Game.DefsPath)/$(Game.IdentityKey)/", "$(Game.DefsPath)/", "$(App.DefsPath)/" } }, - { GRAPHICS_RESOURCE_NAMESPACE_NAME, "-gfxdir2", "-gfxdir", 0, - { "$(App.DataPath)/graphics/" } }, - { MODELS_RESOURCE_NAMESPACE_NAME, "-modeldir2", "-modeldir", RNF_USE_VMAP, - { "$(Game.DataPath)/models/$(Game.IdentityKey)/", "$(Game.DataPath)/models/" } }, - { SOUNDS_RESOURCE_NAMESPACE_NAME, "-sfxdir2", "-sfxdir", RNF_USE_VMAP, - { "$(Game.DataPath)/sfx/$(Game.IdentityKey)/", "$(Game.DataPath)/sfx/" } }, - { MUSIC_RESOURCE_NAMESPACE_NAME, "-musdir2", "-musdir", RNF_USE_VMAP, - { "$(Game.DataPath)/music/$(Game.IdentityKey)/", "$(Game.DataPath)/music/" } }, - { TEXTURES_RESOURCE_NAMESPACE_NAME, "-texdir2", "-texdir", RNF_USE_VMAP, - { "$(Game.DataPath)/textures/$(Game.IdentityKey)/", "$(Game.DataPath)/textures/" } }, - { FLATS_RESOURCE_NAMESPACE_NAME, "-flatdir2", "-flatdir", RNF_USE_VMAP, - { "$(Game.DataPath)/flats/$(Game.IdentityKey)/", "$(Game.DataPath)/flats/" } }, - { PATCHES_RESOURCE_NAMESPACE_NAME, "-patdir2", "-patdir", RNF_USE_VMAP, - { "$(Game.DataPath)/patches/$(Game.IdentityKey)/", "$(Game.DataPath)/patches/" } }, - { LIGHTMAPS_RESOURCE_NAMESPACE_NAME, "-lmdir2", "-lmdir", RNF_USE_VMAP, - { "$(Game.DataPath)/lightmaps/$(Game.IdentityKey)/", "$(Game.DataPath)/lightmaps/" } }, - { FONTS_RESOURCE_NAMESPACE_NAME, "-fontdir2", "-fontdir", RNF_USE_VMAP, - { "$(Game.DataPath)/fonts/$(Game.IdentityKey)/", "$(Game.DataPath)/fonts/", "$(App.DataPath)/fonts/" } }, + { DEFINITIONS_RESOURCE_NAMESPACE_NAME, NULL, NULL, 0, 0, + { "$(Game.DefsPath)/$(Game.IdentityKey)/", "$(Game.DefsPath)/", "$(App.DefsPath)/" } + }, + { GRAPHICS_RESOURCE_NAMESPACE_NAME, "-gfxdir2", "-gfxdir", 0, 0, + { "$(App.DataPath)/graphics/" } + }, + { MODELS_RESOURCE_NAMESPACE_NAME, "-modeldir2", "-modeldir", RNF_USE_VMAP, 0, + { "$(Game.DataPath)/models/$(Game.IdentityKey)/", "$(Game.DataPath)/models/" } + }, + { SOUNDS_RESOURCE_NAMESPACE_NAME, "-sfxdir2", "-sfxdir", RNF_USE_VMAP, SPF_NO_DECEND, + { "$(Game.DataPath)/sfx/$(Game.IdentityKey)/", "$(Game.DataPath)/sfx/" } + }, + { MUSIC_RESOURCE_NAMESPACE_NAME, "-musdir2", "-musdir", RNF_USE_VMAP, SPF_NO_DECEND, + { "$(Game.DataPath)/music/$(Game.IdentityKey)/", "$(Game.DataPath)/music/" } + }, + { TEXTURES_RESOURCE_NAMESPACE_NAME, "-texdir2", "-texdir", RNF_USE_VMAP, SPF_NO_DECEND, + { "$(Game.DataPath)/textures/$(Game.IdentityKey)/", "$(Game.DataPath)/textures/" } + }, + { FLATS_RESOURCE_NAMESPACE_NAME, "-flatdir2", "-flatdir", RNF_USE_VMAP, SPF_NO_DECEND, + { "$(Game.DataPath)/flats/$(Game.IdentityKey)/", "$(Game.DataPath)/flats/" } + }, + { PATCHES_RESOURCE_NAMESPACE_NAME, "-patdir2", "-patdir", RNF_USE_VMAP, SPF_NO_DECEND, + { "$(Game.DataPath)/patches/$(Game.IdentityKey)/", "$(Game.DataPath)/patches/" } + }, + { LIGHTMAPS_RESOURCE_NAMESPACE_NAME, "-lmdir2", "-lmdir", RNF_USE_VMAP, 0, + { "$(Game.DataPath)/lightmaps/" } + }, + { FONTS_RESOURCE_NAMESPACE_NAME, "-fontdir2", "-fontdir", RNF_USE_VMAP, SPF_NO_DECEND, + { "$(Game.DataPath)/fonts/$(Game.IdentityKey)/", "$(Game.DataPath)/fonts/", "$(App.DataPath)/fonts/" } + }, { NULL } }; Uri* uri = Uri_New(); @@ -748,20 +760,20 @@ void F_CreateNamespacesForFileResourcePaths(void) { size_t i; for(i = 0; defs[i].name; ++i) { - uint j, defaultPathCount; + uint j, searchPathCount; struct namespacedef_s* def = &defs[i]; FileDirectory* directory = FileDirectory_New(); resourcenamespace_t* rnamespace = F_CreateResourceNamespace(def->name, directory, F_ComposeHashNameForFilePath, F_HashKeyForFilePathHashName, def->flags); - defaultPathCount = 0; - while(def->defaultPaths[defaultPathCount] && ++defaultPathCount < NAMESPACEDEF_MAX_SEARCHPATHS) + searchPathCount = 0; + while(def->searchPaths[searchPathCount] && ++searchPathCount < NAMESPACEDEF_MAX_SEARCHPATHS) {} - for(j = 0; j < defaultPathCount; ++j) + for(j = 0; j < searchPathCount; ++j) { - Uri_SetUri3(uri, def->defaultPaths[j], RC_NULL); - ResourceNamespace_AddSearchPath(rnamespace, uri, SPG_DEFAULT); + Uri_SetUri3(uri, def->searchPaths[j], RC_NULL); + ResourceNamespace_AddSearchPath(rnamespace, def->searchPathFlags, uri, SPG_DEFAULT); } if(def->optOverridePath && ArgCheckWith(def->optOverridePath, 1)) @@ -773,10 +785,10 @@ void F_CreateNamespacesForFileResourcePaths(void) Str_Init(&path2); Str_Appendf(&path2, "%s/$(Game.IdentityKey)", path); Uri_SetUri3(uri, Str_Text(&path2), RC_NULL); - ResourceNamespace_AddSearchPath(rnamespace, uri, SPG_OVERRIDE); + ResourceNamespace_AddSearchPath(rnamespace, def->searchPathFlags, uri, SPG_OVERRIDE); Uri_SetUri3(uri, path, RC_NULL); - ResourceNamespace_AddSearchPath(rnamespace, uri, SPG_OVERRIDE); + ResourceNamespace_AddSearchPath(rnamespace, def->searchPathFlags, uri, SPG_OVERRIDE); Str_Free(&path2); } @@ -784,7 +796,7 @@ void F_CreateNamespacesForFileResourcePaths(void) if(def->optFallbackPath && ArgCheckWith(def->optFallbackPath, 1)) { Uri_SetUri3(uri, ArgNext(), RC_NULL); - ResourceNamespace_AddSearchPath(rnamespace, uri, SPG_FALLBACK); + ResourceNamespace_AddSearchPath(rnamespace, def->searchPathFlags, uri, SPG_FALLBACK); } }} @@ -892,13 +904,13 @@ resourcenamespace_t* F_CreateResourceNamespace(const char* name, FileDirectory* return rn; } -boolean F_AddSearchPathToResourceNamespace(resourcenamespaceid_t rni, const Uri* uri, - resourcenamespace_searchpathgroup_t group) +boolean F_AddSearchPathToResourceNamespace(resourcenamespaceid_t rni, int flags, + const Uri* searchPath, resourcenamespace_searchpathgroup_t group) { resourcenamespaceinfo_t* info; errorIfNotInited("F_AddSearchPathToResourceNamespace"); info = getNamespaceInfoForId(rni); - if(ResourceNamespace_AddSearchPath(info->rnamespace, uri, group)) + if(ResourceNamespace_AddSearchPath(info->rnamespace, flags, searchPath, group)) { info->flags |= RNF_IS_DIRTY; return true; @@ -906,12 +918,6 @@ boolean F_AddSearchPathToResourceNamespace(resourcenamespaceid_t rni, const Uri* return false; } -void F_AddResourceToNamespace(resourcenamespaceid_t rni, PathDirectoryNode* node) -{ - errorIfNotInited("F_AddResourceToNamespace"); - addResourceToNamespace(getNamespaceInfoForId(rni), node); -} - const ddstring_t* F_ResourceNamespaceName(resourcenamespaceid_t rni) { return &(getNamespaceInfoForId(rni))->name;