Use better generic hashtable implement. for assets
This commit is contained in:
		
							parent
							
								
									c93e6ca37c
								
							
						
					
					
						commit
						8b0f2f93e3
					
				| @ -22,6 +22,61 @@ | ||||
| #include "Dengine/OpenGL.h" | ||||
| #include "Dengine/Platform.h" | ||||
| 
 | ||||
| /*
 | ||||
|  ********************************* | ||||
|  * Hash Table Operations | ||||
|  ********************************* | ||||
|  */ | ||||
| INTERNAL HashTableEntry *getFreeHashSlot(HashTable *const table, | ||||
|                                          MemoryArena *arena, | ||||
|                                          const char *const key) | ||||
| { | ||||
| 	u32 hashIndex = common_getHashIndex(key, table->size); | ||||
| 	HashTableEntry *result = &table->entries[hashIndex]; | ||||
| 	if (result->key) | ||||
| 	{ | ||||
| 		while (result->next) | ||||
| 		{ | ||||
| 			if (common_strcmp(result->key, key) == 0) | ||||
| 			{ | ||||
| 				// TODO(doyle): Error hash item already exists
 | ||||
| 				ASSERT(INVALID_CODE_PATH); | ||||
| 			} | ||||
| 			result = result->next; | ||||
| 		} | ||||
| 
 | ||||
| 		result->next = PLATFORM_MEM_ALLOC(arena, 1, HashTableEntry); | ||||
| 		result       = result->next; | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	/* Check if platform_mem_alloc failed(), otherwise always true if hash table
 | ||||
| 	 * entries initialised*/ | ||||
| 	if (result) | ||||
| 	{ | ||||
| 		// +1 Null terminator
 | ||||
| 		i32 keyLen  = common_strlen(key) + 1; | ||||
| 		result->key = PLATFORM_MEM_ALLOC(arena, keyLen, char); | ||||
| 		common_strncpy(result->key, key, keyLen); | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| INTERNAL HashTableEntry *getEntryFromHash(HashTable *const table, | ||||
|                                           const char *const key) | ||||
| { | ||||
| 	u32 hashIndex = common_getHashIndex(key, table->size); | ||||
| 	HashTableEntry *result = &table->entries[hashIndex]; | ||||
| 	if (result->key) | ||||
| 	{ | ||||
| 		while (result && common_strcmp(result->key, key) != 0) | ||||
| 			result = result->next; | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  ********************************* | ||||
|  * XML Operations | ||||
| @ -308,7 +363,8 @@ INTERNAL void parseXmlTreeToGame(AssetManager *assetManager, MemoryArena *arena, | ||||
| 			if (common_strcmp(node->attribute.name, "imagePath") == 0) | ||||
| 			{ | ||||
| 				char *imageName = atlasXmlNode->attribute.value; | ||||
| 				atlasEntry = asset_makeTexAtlas(assetManager, arena, imageName); | ||||
| 				atlasEntry = | ||||
| 				    asset_getFreeTexAtlasSlot(assetManager, arena, imageName); | ||||
| 
 | ||||
| 				char *dataDir       = "data/textures/WorldTraveller/"; | ||||
| 				char imagePath[512] = {0}; | ||||
| @ -574,29 +630,21 @@ INTERNAL AtlasSubTexture *getFreeAtlasSubTexSlot(TexAtlas *atlas, | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| INTERNAL Animation *getFreeAnimationSlot(Animation *table, u32 tableSize, | ||||
| INTERNAL Animation *getFreeAnimationSlot(AssetManager *assetManager, | ||||
|                                          MemoryArena *arena, char *key) | ||||
| { | ||||
| 	u32 hashIndex     = common_getHashIndex(key, tableSize); | ||||
| 	Animation *result = &table[hashIndex]; | ||||
| 	if (result->key) | ||||
| 	HashTableEntry *entry = getFreeHashSlot(&assetManager->anims, arena, key); | ||||
| 
 | ||||
| 	if (entry) | ||||
| 	{ | ||||
| 		while (result->next) | ||||
| 		{ | ||||
| 			if (common_strcmp(result->key, key) == 0) | ||||
| 			{ | ||||
| 				// TODO(doyle): Error correction whereby if a tex atlas already
 | ||||
| 				// exists
 | ||||
| 				ASSERT(INVALID_CODE_PATH); | ||||
| 			} | ||||
| 			result = result->next; | ||||
| 		} | ||||
| 
 | ||||
| 		result->next = PLATFORM_MEM_ALLOC(arena, 1, Animation); | ||||
| 		result = result->next; | ||||
| 		entry->data       = PLATFORM_MEM_ALLOC(arena, 1, Animation); | ||||
| 		Animation *result = CAST(Animation *) entry->data; | ||||
| 		return result; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| Rect asset_getSubTexRect(TexAtlas *atlas, char *key) | ||||
| @ -623,73 +671,71 @@ AudioVorbis *asset_getVorbis(AssetManager *assetManager, | ||||
| 
 | ||||
| Texture *asset_getTex(AssetManager *const assetManager, const char *const key) | ||||
| { | ||||
| 	u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->textures)); | ||||
| 	Texture *result = &assetManager->textures[hashIndex]; | ||||
| 	if (result->key) | ||||
| 	{ | ||||
| 		while (result && common_strcmp(result->key, key) != 0) | ||||
| 			result = result->next; | ||||
| 	} | ||||
| 	HashTableEntry *entry = getEntryFromHash(&assetManager->textures, key); | ||||
| 
 | ||||
| 	Texture *result = NULL; | ||||
| 	if (entry) result = CAST(Texture *)entry->data; | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| TexAtlas *asset_makeTexAtlas(AssetManager *const assetManager, | ||||
|                              MemoryArena *arena, const char *const key) | ||||
| Texture *asset_getFreeTexSlot(AssetManager *const assetManager, | ||||
|                               MemoryArena *const arena, const char *const key) | ||||
| { | ||||
| 	u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->texAtlas)); | ||||
| 	TexAtlas *result = &assetManager->texAtlas[hashIndex]; | ||||
| 	if (result->key) | ||||
| 
 | ||||
| 	HashTableEntry *const entry = | ||||
| 	    getFreeHashSlot(&assetManager->textures, arena, key); | ||||
| 
 | ||||
| 	if (entry) | ||||
| 	{ | ||||
| 		while (result->next) | ||||
| 		{ | ||||
| 			if (common_strcmp(result->key, key) == 0) | ||||
| 			{ | ||||
| 				// TODO(doyle): Error correction whereby if a tex atlas already
 | ||||
| 				// exists
 | ||||
| 				ASSERT(INVALID_CODE_PATH); | ||||
| 			} | ||||
| 			result = result->next; | ||||
| 		} | ||||
| 
 | ||||
| 		result->next = PLATFORM_MEM_ALLOC(arena, 1, TexAtlas); | ||||
| 		result = result->next; | ||||
| 		entry->data     = PLATFORM_MEM_ALLOC(arena, 1, Texture); | ||||
| 		Texture *result = CAST(Texture *) entry->data; | ||||
| 		return result; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	return result; | ||||
| TexAtlas *asset_getFreeTexAtlasSlot(AssetManager *const assetManager, | ||||
|                                     MemoryArena *arena, const char *const key) | ||||
| { | ||||
| 
 | ||||
| 	HashTableEntry *const entry = | ||||
| 	    getFreeHashSlot(&assetManager->texAtlas, arena, key); | ||||
| 
 | ||||
| 	if (entry) | ||||
| 	{ | ||||
| 		entry->data      = PLATFORM_MEM_ALLOC(arena, 1, TexAtlas); | ||||
| 		TexAtlas *result = CAST(TexAtlas *) entry->data; | ||||
| 		return result; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| TexAtlas *asset_getTexAtlas(AssetManager *const assetManager, | ||||
|                             const char *const key) | ||||
| { | ||||
| 	u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->texAtlas)); | ||||
| 	TexAtlas *result = &assetManager->texAtlas[hashIndex]; | ||||
| 	if (result->key) | ||||
| 	{ | ||||
| 		while (result && common_strcmp(result->key, key) != 0) | ||||
| 			result = result->next; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	HashTableEntry *entry = getEntryFromHash(&assetManager->texAtlas, key); | ||||
| 
 | ||||
| 	TexAtlas *result = NULL; | ||||
| 	if (entry) result = CAST(TexAtlas *)entry->data; | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| Animation *asset_getAnim(AssetManager *assetManager, char *key) | ||||
| Animation *asset_getAnim(AssetManager *const assetManager, | ||||
|                          const char *const key) | ||||
| { | ||||
| 	u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->anims)); | ||||
| 	Animation *result = &assetManager->anims[hashIndex]; | ||||
| 	if (result->key) | ||||
| 	{ | ||||
| 		while (result && common_strcmp(result->key, key) != 0) | ||||
| 			result = result->next; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	HashTableEntry *entry = getEntryFromHash(&assetManager->anims, key); | ||||
| 
 | ||||
| 	Animation *result = NULL; | ||||
| 	if (entry) result = CAST(Animation *)entry->data; | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| @ -726,33 +772,6 @@ const i32 asset_loadVorbis(AssetManager *assetManager, MemoryArena *arena, | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| // TODO(doyle): Revise passing in the assetmanager
 | ||||
| Texture *asset_getAndAllocFreeTexSlot(AssetManager *assetManager, | ||||
|                                       MemoryArena *arena, const char *const key) | ||||
| { | ||||
| 	i32 texListSize = ARRAY_COUNT(assetManager->textures); | ||||
| 	u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->textures)); | ||||
| 	Texture *result = &assetManager->textures[hashIndex]; | ||||
| 	if (result->key) | ||||
| 	{ | ||||
| 		while (result->next) | ||||
| 		{ | ||||
| 			if (common_strcmp(result->key, key) == 0) | ||||
| 			{ | ||||
| 				// TODO(doyle): Error correction whereby if a tex atlas already
 | ||||
| 				// exists
 | ||||
| 				ASSERT(INVALID_CODE_PATH); | ||||
| 			} | ||||
| 			result = result->next; | ||||
| 		} | ||||
| 
 | ||||
| 		result->next = PLATFORM_MEM_ALLOC(arena, 1, Texture); | ||||
| 		result       = result->next; | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| const i32 asset_loadTextureImage(AssetManager *assetManager, MemoryArena *arena, | ||||
|                                  const char *const path, const char *const key) | ||||
| { | ||||
| @ -777,7 +796,7 @@ const i32 asset_loadTextureImage(AssetManager *assetManager, MemoryArena *arena, | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	Texture *tex = asset_getAndAllocFreeTexSlot(assetManager, arena, key); | ||||
| 	Texture *tex = asset_getFreeTexSlot(assetManager, arena, key); | ||||
| 	*tex         = texture_gen(CAST(GLuint)(imgWidth), CAST(GLuint)(imgHeight), | ||||
| 	                   CAST(GLint)(bytesPerPixel), image); | ||||
| 
 | ||||
| @ -1015,7 +1034,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena, | ||||
| 	// align the baselines up so we don't need to do baseline adjusting at
 | ||||
| 	// render?
 | ||||
| 	char charToEncode = CAST(char)codepointRange.x; | ||||
| 	TexAtlas *fontAtlas = asset_makeTexAtlas(assetManager, arena, "font"); | ||||
| 	TexAtlas *fontAtlas = | ||||
| 	    asset_getFreeTexAtlasSlot(assetManager, arena, "font"); | ||||
| 	for (i32 row = 0; row < MAX_TEXTURE_SIZE; row++) | ||||
| 	{ | ||||
| 		u32 *destRow = fontBitmap + (row * MAX_TEXTURE_SIZE); | ||||
| @ -1095,9 +1115,9 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena, | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	Texture tex = texture_gen(MAX_TEXTURE_SIZE, MAX_TEXTURE_SIZE, 4, | ||||
| 	                          CAST(u8 *) fontBitmap); | ||||
| 	assetManager->textures[texlist_font] = tex; | ||||
| 	Texture *tex = asset_getFreeTexSlot(assetManager, arena, "font"); | ||||
| 	*tex         = texture_gen(MAX_TEXTURE_SIZE, MAX_TEXTURE_SIZE, 4, | ||||
| 	                   CAST(u8 *) fontBitmap); | ||||
| 
 | ||||
| #ifdef WT_RENDER_FONT_FILE | ||||
| 	/* save out a 4 channel image */ | ||||
| @ -1106,7 +1126,7 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena, | ||||
| #endif | ||||
| 	PLATFORM_MEM_FREE(arena, fontBitmap, bitmapSize); | ||||
| 
 | ||||
| 	fontAtlas->tex = &assetManager->textures[texlist_font]; | ||||
| 	fontAtlas->tex = tex; | ||||
| 	font->atlas   = fontAtlas; | ||||
| 
 | ||||
| 	// NOTE(doyle): Formula derived from STB Font
 | ||||
| @ -1130,17 +1150,16 @@ void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena, | ||||
|                         char *animName, TexAtlas *atlas, char **subTextureNames, | ||||
|                         i32 numSubTextures, f32 frameDuration) | ||||
| { | ||||
| 	Animation *anim = getFreeAnimationSlot( | ||||
| 	    assetManager->anims, ARRAY_COUNT(assetManager->anims), arena, animName); | ||||
| 	Animation *anim = getFreeAnimationSlot(assetManager, arena, animName); | ||||
| 
 | ||||
| 	/* Use same animation ptr for name from entry key */ | ||||
| 	HashTableEntry *entry = getEntryFromHash(&assetManager->anims, animName); | ||||
| 	anim->name            = entry->key; | ||||
| 
 | ||||
| 	anim->atlas         = atlas; | ||||
| 	anim->frameDuration = frameDuration; | ||||
| 	anim->numFrames     = numSubTextures; | ||||
| 
 | ||||
| 	// NOTE(doyle): +1 for the null terminator
 | ||||
| 	anim->name = PLATFORM_MEM_ALLOC(arena, common_strlen(animName) + 1, char); | ||||
| 	common_strncpy(anim->name, animName, common_strlen(animName)); | ||||
| 
 | ||||
| 	anim->frameList = PLATFORM_MEM_ALLOC(arena, numSubTextures, char*); | ||||
| 	for (i32 i = 0; i < numSubTextures; i++) | ||||
| 	{ | ||||
|  | ||||
| @ -116,12 +116,25 @@ INTERNAL void assetInit(GameState *state) | ||||
| 	AssetManager *assetManager = &state->assetManager; | ||||
| 	MemoryArena *arena = &state->arena; | ||||
| 
 | ||||
| 	/* Create empty 1x1 4bpp black texture */ | ||||
| 	u32 bitmap       = (0xFF << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF << 0); | ||||
| 	Texture *tex = asset_getAndAllocFreeTexSlot(assetManager, arena, "nullTex"); | ||||
| 	*tex         = texture_gen(1, 1, 4, CAST(u8 *)(&bitmap)); | ||||
| 	i32 texAtlasEntries         = 8; | ||||
| 	assetManager->texAtlas.size = texAtlasEntries; | ||||
| 	assetManager->texAtlas.entries = | ||||
| 	    PLATFORM_MEM_ALLOC(arena, texAtlasEntries, HashTableEntry); | ||||
| 
 | ||||
| 	//assetManager->texAtlas.type = hashtabletype_textureAtlas;
 | ||||
| 	i32 texEntries          = 32; | ||||
| 	assetManager->textures.size = texEntries; | ||||
| 	assetManager->textures.entries = | ||||
| 	    PLATFORM_MEM_ALLOC(arena, texEntries, HashTableEntry); | ||||
| 
 | ||||
| 	i32 animEntries          = 1024; | ||||
| 	assetManager->anims.size = animEntries; | ||||
| 	assetManager->anims.entries = | ||||
| 	    PLATFORM_MEM_ALLOC(arena, animEntries, HashTableEntry); | ||||
| 
 | ||||
| 	/* Create empty 1x1 4bpp black texture */ | ||||
| 	u32 bitmap   = (0xFF << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF << 0); | ||||
| 	Texture *tex = asset_getFreeTexSlot(assetManager, arena, "nullTex"); | ||||
| 	*tex         = texture_gen(1, 1, 4, CAST(u8 *)(&bitmap)); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 ********************************* | ||||
|  | ||||
| @ -9,15 +9,6 @@ | ||||
| typedef struct MemoryArena MemoryArena; | ||||
| typedef struct PlatformFileRead PlatformFileRead; | ||||
| 
 | ||||
| enum HashTableType | ||||
| { | ||||
| 	hashtabletype_unknown, | ||||
| 	hashtabletype_texture, | ||||
| 	hashtabletype_textureAtlas, | ||||
| 	hashtabletype_animation, | ||||
| 	hashtabletype_count, | ||||
| }; | ||||
| 
 | ||||
| typedef struct HashTableEntry | ||||
| { | ||||
| 	void *data; | ||||
| @ -30,15 +21,14 @@ typedef struct HashTable | ||||
| { | ||||
| 	HashTableEntry *entries; | ||||
| 	i32 size; | ||||
| 	enum HashTableType type; | ||||
| } HashTable; | ||||
| 
 | ||||
| typedef struct AssetManager | ||||
| { | ||||
| 	/* Hash Tables */ | ||||
| 	TexAtlas texAtlas[8]; | ||||
| 	Texture textures[32]; | ||||
| 	Animation anims[1024]; | ||||
| 	HashTable texAtlas; | ||||
| 	HashTable textures; | ||||
| 	HashTable anims; | ||||
| 
 | ||||
| 	/* Primitive Array */ | ||||
| 	Shader shaders[32]; | ||||
| @ -55,13 +45,12 @@ typedef struct AssetManager | ||||
|  */ | ||||
| Rect asset_getSubTexRect(TexAtlas *atlas, char *key); | ||||
| Texture *asset_getTex(AssetManager *const assetManager, const char *const key); | ||||
| TexAtlas *asset_makeTexAtlas(AssetManager *const assetManager, | ||||
|                              MemoryArena *arena, const char *const key); | ||||
| TexAtlas *asset_getFreeTexAtlasSlot(AssetManager *const assetManager, | ||||
|                                     MemoryArena *arena, const char *const key); | ||||
| TexAtlas *asset_getTexAtlas(AssetManager *const assetManager, | ||||
|                             const char *const key); | ||||
| Texture *asset_getAndAllocFreeTexSlot(AssetManager *assetManager, | ||||
|                                       MemoryArena *arena, | ||||
|                                       const char *const key); | ||||
| Texture *asset_getFreeTexSlot(AssetManager *const assetManager, | ||||
|                               MemoryArena *const arena, const char *const key); | ||||
| const i32 asset_loadTextureImage(AssetManager *assetManager, MemoryArena *arena, | ||||
|                                  const char *const path, | ||||
|                                  const char *const key); | ||||
| @ -74,7 +63,8 @@ const i32 asset_loadTextureImage(AssetManager *assetManager, MemoryArena *arena, | ||||
| void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena, | ||||
|                         char *animName, TexAtlas *atlas, char **subTextureNames, | ||||
|                         i32 numSubTextures, f32 frameDuration); | ||||
| Animation *asset_getAnim(AssetManager *assetManager, char *key); | ||||
| Animation *asset_getAnim(AssetManager *const assetManager, | ||||
|                          const char *const key); | ||||
| 
 | ||||
| /*
 | ||||
|  ********************************* | ||||
|  | ||||
| @ -111,8 +111,6 @@ typedef struct Animation | ||||
| 
 | ||||
| 	i32 numFrames; | ||||
| 	f32 frameDuration; | ||||
| 
 | ||||
| 	struct Animation *next; | ||||
| } Animation; | ||||
| 
 | ||||
| // TODO(doyle): We only use the offset and advance metric at the moment, remove?
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user