Start merging hash table access into assets
Basic implementation with many pre-existing features disabled untill all parts of the system that interact with the assets transitions over.
This commit is contained in:
		
							parent
							
								
									b43754986f
								
							
						
					
					
						commit
						7ca42f781a
					
				| @ -21,6 +21,76 @@ | ||||
| #include "Dengine/OpenGL.h" | ||||
| #include "Dengine/Platform.h" | ||||
| 
 | ||||
| INTERNAL AtlasSubTexture *getAtlasSubTexture(TexAtlas *atlas, char *key) | ||||
| { | ||||
| 	u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(atlas->subTex)); | ||||
| 	AtlasSubTexture *result = &atlas->subTex[hashIndex]; | ||||
| 	if (result->key) | ||||
| 	{ | ||||
| 		while (result && common_strcmp(result->key, key) != 0) | ||||
| 			result = result->next; | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| INTERNAL AtlasSubTexture *makeAtlasSubTexture(TexAtlas *atlas, | ||||
|                                               MemoryArena *arena, char *key) | ||||
| { | ||||
| 	u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(atlas->subTex)); | ||||
| 	AtlasSubTexture *result = &atlas->subTex[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, AtlasSubTexture); | ||||
| 		result = result->next; | ||||
| 	} | ||||
| 	 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| INTERNAL Animation *getFreeAnimSlot(Animation *table, u32 tableSize, | ||||
|                                     MemoryArena *arena, char *key) | ||||
| { | ||||
| 	u32 hashIndex     = common_getHashIndex(key, tableSize); | ||||
| 	Animation *result = &table[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, Animation); | ||||
| 		result = result->next; | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| Rect asset_getAtlasSubTexRect(TexAtlas *atlas, char *key) | ||||
| { | ||||
| 	AtlasSubTexture *subTex = getAtlasSubTexture(atlas, key); | ||||
| 	Rect result = subTex->rect; | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| // TODO(doyle): Switch to hash based lookup
 | ||||
| // TODO(doyle): Use pointers, so we can forward declare all assets?
 | ||||
| AudioVorbis *asset_getVorbis(AssetManager *assetManager, | ||||
| @ -49,27 +119,64 @@ Texture *asset_getTexture(AssetManager *const assetManager, | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| TexAtlas *asset_getTextureAtlas(AssetManager *assetManager, const enum TexList type) | ||||
| TexAtlas *asset_makeTexAtlas(AssetManager *const assetManager, | ||||
|                              MemoryArena *arena, const char *const key) | ||||
| { | ||||
| 	if (type < texlist_count) | ||||
| 		return &assetManager->texAtlas[type]; | ||||
| 	u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->texAtlas)); | ||||
| 	TexAtlas *result = &assetManager->texAtlas[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; | ||||
| 		} | ||||
| 
 | ||||
| #ifdef DENGINE_DEBUG | ||||
| 	ASSERT(INVALID_CODE_PATH); | ||||
| #endif | ||||
| 	return NULL; | ||||
| 		result->next = PLATFORM_MEM_ALLOC(arena, 1, TexAtlas); | ||||
| 		result = result->next; | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| Animation *asset_getAnim(AssetManager *assetManager, const enum AnimList type) | ||||
| TexAtlas *asset_getTexAtlas(AssetManager *const assetManager, | ||||
|                             const char *const key) | ||||
| { | ||||
| 	if (type < animlist_count) | ||||
| 		return &assetManager->anims[type]; | ||||
| 	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; | ||||
| 	} | ||||
| 
 | ||||
| #ifdef DENGINE_DEBUG | ||||
| 	ASSERT(INVALID_CODE_PATH); | ||||
| #endif | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| 	return NULL; | ||||
| Animation *asset_getAnim(AssetManager *assetManager, char *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; | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| const i32 asset_loadVorbis(AssetManager *assetManager, MemoryArena *arena, | ||||
| @ -364,7 +471,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena, | ||||
| 	// TODO(doyle): We copy over the bitmap direct to the font sheet, should we
 | ||||
| 	// align the baselines up so we don't need to do baseline adjusting at
 | ||||
| 	// render?
 | ||||
| 	i32 atlasIndex = 0; | ||||
| 	char charToEncode = CAST(char)codepointRange.x; | ||||
| 	TexAtlas *fontAtlas = asset_makeTexAtlas(assetManager, arena, "font"); | ||||
| 	for (i32 row = 0; row < MAX_TEXTURE_SIZE; row++) | ||||
| 	{ | ||||
| 		u32 *destRow = fontBitmap + (row * MAX_TEXTURE_SIZE); | ||||
| @ -378,23 +486,26 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena, | ||||
| 			/* Store the location of glyph into atlas */ | ||||
| 			if (verticalPixelsBlitted == 0) | ||||
| 			{ | ||||
| 				TexAtlas *fontAtlas = &assetManager->texAtlas[texlist_font]; | ||||
| #ifdef DENGINE_DEBUG | ||||
| 				ASSERT(activeGlyph.codepoint < ARRAY_COUNT(fontAtlas->texRect)); | ||||
| 				ASSERT(activeGlyph.codepoint < ARRAY_COUNT(fontAtlas->subTex)); | ||||
| #endif | ||||
| 
 | ||||
| 				v2 origin = | ||||
| 				    V2(CAST(f32)(glyphIndex * font->maxSize.w), CAST(f32) row); | ||||
| #if 1 | ||||
| 				fontAtlas->texRect[atlasIndex++] = | ||||
| 				    math_getRect(origin, V2(CAST(f32) font->maxSize.w, | ||||
| 				                            CAST(f32) font->maxSize.h)); | ||||
| #else | ||||
| 				v2i fontSize = | ||||
| 				    font->charMetrics[activeGlyph.codepoint - 32].trueSize; | ||||
| 				fontAtlas->texRect[atlasIndex++] = math_getRect( | ||||
| 				    origin, V2(CAST(f32) fontSize.x, CAST(f32) fontSize.y)); | ||||
| #endif | ||||
| 
 | ||||
| 				// NOTE(doyle): Since charToEncode starts from 0 and we record
 | ||||
| 				// all ascii characters, charToEncode represents the character
 | ||||
| 				// 1:1
 | ||||
| 				char charTmp[2] = {0}; | ||||
| 				charTmp[0] = charToEncode; | ||||
| 				AtlasSubTexture *subTex = | ||||
| 				    makeAtlasSubTexture(fontAtlas, arena, charTmp); | ||||
| 
 | ||||
| 				subTex->key = PLATFORM_MEM_ALLOC(arena, 1, char); | ||||
| 				subTex->key[0] = charToEncode; | ||||
| 
 | ||||
| 				subTex->rect = CAST(Rect){origin, font->maxSize}; | ||||
| 				charToEncode++; | ||||
| 			} | ||||
| 
 | ||||
| 			/* Copy over exactly one row of pixels */ | ||||
| @ -452,8 +563,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena, | ||||
| #endif | ||||
| 	PLATFORM_MEM_FREE(arena, fontBitmap, bitmapSize); | ||||
| 
 | ||||
| 	font->tex = &assetManager->textures[texlist_font]; | ||||
| 	font->atlas = &assetManager->texAtlas[texlist_font]; | ||||
| 	fontAtlas->tex = &assetManager->textures[texlist_font]; | ||||
| 	font->atlas   = fontAtlas; | ||||
| 
 | ||||
| 	// NOTE(doyle): Formula derived from STB Font
 | ||||
| 	font->verticalSpacing = | ||||
| @ -472,26 +583,28 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena, | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena, | ||||
|                         i32 texId, i32 animId, i32 *frameIndex, i32 numFrames, | ||||
|                         f32 frameDuration) | ||||
|                         char *animName, TexAtlas *atlas, char **subTextureNames, | ||||
|                         i32 numSubTextures, f32 frameDuration) | ||||
| { | ||||
| #ifdef DENGINE_DEBUG | ||||
| 	ASSERT(assetManager && frameIndex) | ||||
| 	ASSERT(!assetManager->anims[animId].frameIndex); | ||||
| #endif | ||||
| 	Animation *anim = getFreeAnimSlot( | ||||
| 	    assetManager->anims, ARRAY_COUNT(assetManager->anims), arena, animName); | ||||
| 
 | ||||
| 	Animation anim = {0}; | ||||
| 	anim.atlas     = asset_getTextureAtlas(assetManager, texId); | ||||
| 	anim->atlas         = atlas; | ||||
| 	anim->frameDuration = frameDuration; | ||||
| 	anim->numFrames     = numSubTextures; | ||||
| 
 | ||||
| 	anim.frameIndex = PLATFORM_MEM_ALLOC(arena, numFrames, i32); | ||||
| 	for (i32 i = 0; i < numFrames; i++) anim.frameIndex[i] = frameIndex[i]; | ||||
| 	// 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.numFrames     = numFrames; | ||||
| 	anim.frameDuration = frameDuration; | ||||
| 	anim->frameList = PLATFORM_MEM_ALLOC(arena, numSubTextures, char*); | ||||
| 	for (i32 i = 0; i < numSubTextures; i++) | ||||
| 	{ | ||||
| 		AtlasSubTexture *subTex = getAtlasSubTexture(atlas, subTextureNames[i]); | ||||
| 		anim->frameList[i]       = subTex->key; | ||||
| 	} | ||||
| 
 | ||||
| 	assetManager->anims[animId] = anim; | ||||
| } | ||||
| 
 | ||||
| v2 asset_stringDimInPixels(const Font *const font, const char *const string) | ||||
|  | ||||
							
								
								
									
										79
									
								
								src/Entity.c
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								src/Entity.c
									
									
									
									
									
								
							| @ -3,20 +3,28 @@ | ||||
| #include "Dengine/Platform.h" | ||||
| #include "Dengine/WorldTraveller.h" | ||||
| 
 | ||||
| void entity_setActiveAnim(Entity *entity, enum AnimList animId) | ||||
| void entity_setActiveAnim(Entity *entity, char *animName) | ||||
| { | ||||
| #ifdef DENGINE_DEBUG | ||||
| 	ASSERT(animId < animlist_count); | ||||
| 	ASSERT(entity->anim[animId].anim); | ||||
| #endif | ||||
| 
 | ||||
| 	/* Reset current anim data */ | ||||
| 	EntityAnim_ *currAnim  = &entity->anim[entity->currAnimId]; | ||||
| 	currAnim->currDuration = currAnim->anim->frameDuration; | ||||
| 	currAnim->currFrame    = 0; | ||||
| 	EntityAnim *currEntityAnim = &entity->animList[entity->currAnimId]; | ||||
| 	currEntityAnim->currDuration = currEntityAnim->anim->frameDuration; | ||||
| 	currEntityAnim->currFrame    = 0; | ||||
| 
 | ||||
| 	/* Set entity active animation */ | ||||
| 	entity->currAnimId = animId; | ||||
| 	for (i32 i = 0; i < ARRAY_COUNT(entity->animList); i++) | ||||
| 	{ | ||||
| 		Animation *anim = entity->animList[i].anim; | ||||
| 		if (anim) | ||||
| 		{ | ||||
| 			if (common_strcmp(anim->key, animName) == 0) | ||||
| 			{ | ||||
| 				entity->currAnimId = i; | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	DEBUG_LOG("Entity does not have access to desired anim"); | ||||
| } | ||||
| 
 | ||||
| void entity_updateAnim(Entity *entity, f32 dt) | ||||
| @ -24,20 +32,15 @@ void entity_updateAnim(Entity *entity, f32 dt) | ||||
| 	if (!entity->tex) | ||||
| 		return; | ||||
| 
 | ||||
| 	// TODO(doyle): Recheck why we have this twice
 | ||||
| 	EntityAnim_ *entityAnim = &entity->anim[entity->currAnimId]; | ||||
| 	Animation anim          = *entityAnim->anim; | ||||
| 	i32 frameIndex          = anim.frameIndex[entityAnim->currFrame]; | ||||
| 	v4 texRect              = anim.atlas->texRect[frameIndex]; | ||||
| 	EntityAnim *currEntityAnim = &entity->animList[entity->currAnimId]; | ||||
| 	Animation *anim = currEntityAnim->anim; | ||||
| 
 | ||||
| 	entityAnim->currDuration -= dt; | ||||
| 	if (entityAnim->currDuration <= 0.0f) | ||||
| 	currEntityAnim->currDuration -= dt; | ||||
| 	if (currEntityAnim->currDuration <= 0.0f) | ||||
| 	{ | ||||
| 		entityAnim->currFrame++; | ||||
| 		entityAnim->currFrame = entityAnim->currFrame % anim.numFrames; | ||||
| 		frameIndex = entityAnim->anim->frameIndex[entityAnim->currFrame]; | ||||
| 		texRect    = anim.atlas->texRect[frameIndex]; | ||||
| 		entityAnim->currDuration = anim.frameDuration; | ||||
| 		currEntityAnim->currFrame++; | ||||
| 		currEntityAnim->currFrame    = currEntityAnim->currFrame % anim->numFrames; | ||||
| 		currEntityAnim->currDuration = anim->frameDuration; | ||||
| 	} | ||||
| 
 | ||||
| 	// NOTE(doyle): If humanoid entity, let animation dictate render size which
 | ||||
| @ -47,18 +50,31 @@ void entity_updateAnim(Entity *entity, f32 dt) | ||||
| 	case entitytype_hero: | ||||
| 	case entitytype_mob: | ||||
| 	case entitytype_npc: | ||||
| 		entity->renderSize = math_getRectSize(texRect); | ||||
| 		char *frameName = anim->frameList[currEntityAnim->currFrame]; | ||||
| 		Rect texRect = | ||||
| 		    asset_getAtlasSubTexRect(anim->atlas, frameName); | ||||
| 		entity->renderSize = texRect.size; | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void entity_addAnim(AssetManager *assetManager, Entity *entity, i32 animId) | ||||
| void entity_addAnim(AssetManager *assetManager, Entity *entity, char *animName) | ||||
| { | ||||
| 	Animation *anim                   = asset_getAnim(assetManager, animId); | ||||
| 	entity->anim[animId].anim         = anim; | ||||
| 	entity->anim[animId].currFrame    = 0; | ||||
| 	entity->anim[animId].currDuration = anim->frameDuration; | ||||
| 	i32 freeAnimIndex = 0; | ||||
| 	for (i32 i = 0; i < ARRAY_COUNT(entity->animList); i++) | ||||
| 	{ | ||||
| 		EntityAnim *entityAnim = &entity->animList[i]; | ||||
| 		if (!entityAnim->anim) | ||||
| 		{ | ||||
| 			entityAnim->anim         = asset_getAnim(assetManager, animName); | ||||
| 			entityAnim->currFrame    = 0; | ||||
| 			entityAnim->currDuration = entityAnim->anim->frameDuration; | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	DEBUG_LOG("No more free entity animation slots"); | ||||
| } | ||||
| 
 | ||||
| void entity_addGenericMob(MemoryArena *arena, AssetManager *assetManager, | ||||
| @ -81,12 +97,7 @@ void entity_addGenericMob(MemoryArena *arena, AssetManager *assetManager, | ||||
| 	mob->audioRenderer->sourceIndex = AUDIO_SOURCE_UNASSIGNED; | ||||
| 
 | ||||
| 	/* Populate mob animation references */ | ||||
| 	entity_addAnim(assetManager, mob, animlist_hero_idle); | ||||
| 	entity_addAnim(assetManager, mob, animlist_hero_walk); | ||||
| 	entity_addAnim(assetManager, mob, animlist_hero_wave); | ||||
| 	entity_addAnim(assetManager, mob, animlist_hero_battlePose); | ||||
| 	entity_addAnim(assetManager, mob, animlist_hero_tackle); | ||||
| 	mob->currAnimId    = animlist_hero_idle; | ||||
| 	entity_addAnim(assetManager, mob, "Claude idle"); | ||||
| } | ||||
| 
 | ||||
| Entity *entity_add(MemoryArena *arena, World *world, v2 pos, v2 size, | ||||
|  | ||||
| @ -175,16 +175,13 @@ void renderer_string(Renderer *const renderer, MemoryArena *arena, Rect camera, | ||||
|                      v2 pivotPoint, f32 rotate, v4 color) | ||||
| { | ||||
| 	i32 strLen = common_strlen(string); | ||||
| 	// TODO(doyle): Scale, not too important .. but rudimentary infrastructure
 | ||||
| 	// laid out here
 | ||||
| 	f32 scale = 1.0f; | ||||
| 
 | ||||
| 	// TODO(doyle): Slightly incorrect string length in pixels calculation,
 | ||||
| 	// because we use the advance metric of each character for length not
 | ||||
| 	// maximum character size in rendering
 | ||||
| 	v2 rightAlignedP = | ||||
| 	    v2_add(pos, V2(scale *(CAST(f32) font->maxSize.w * CAST(f32) strLen), | ||||
| 	                   scale * CAST(f32) font->maxSize.h)); | ||||
| 	    v2_add(pos, V2((CAST(f32) font->maxSize.w * CAST(f32) strLen), | ||||
| 	                   CAST(f32) font->maxSize.h)); | ||||
| 	v2 leftAlignedP  = pos; | ||||
| 	if (math_pointInRect(camera, leftAlignedP) || | ||||
| 	    math_pointInRect(camera, rightAlignedP)) | ||||
| @ -197,27 +194,32 @@ void renderer_string(Renderer *const renderer, MemoryArena *arena, Rect camera, | ||||
| 		pos = posInCameraSpace; | ||||
| 
 | ||||
| 		// TODO(doyle): Find why font is 1px off, might be arial font semantics
 | ||||
| 		Texture *tex = font->atlas->tex; | ||||
| 		f32 baseline = pos.y - font->verticalSpacing + 1; | ||||
| 		for (i32 i = 0; i < strLen; i++) | ||||
| 		{ | ||||
| 			// NOTE(doyle): Atlas packs fonts tightly, so offset the codepoint
 | ||||
| 			// to its actual atlas index, i.e. we skip the first 31 glyphs
 | ||||
| 			i32 codepoint     = string[i]; | ||||
| 			i32 relativeIndex = CAST(i32)(codepoint - font->codepointRange.x); | ||||
| 			CharMetrics charMetric = font->charMetrics[relativeIndex]; | ||||
| 			pos.y                  = baseline - (scale * charMetric.offset.y); | ||||
| 			pos.y                  = baseline - (charMetric.offset.y); | ||||
| 
 | ||||
| 			const v4 charRectOnScreen = | ||||
| 			    math_getRect(pos, V2(scale * CAST(f32) font->maxSize.w, | ||||
| 			                         scale * CAST(f32) font->maxSize.h)); | ||||
| 			    math_getRect(pos, V2(CAST(f32) font->maxSize.w, | ||||
| 			                         CAST(f32) font->maxSize.h)); | ||||
| 
 | ||||
| 			pos.x += scale * charMetric.advance; | ||||
| 			pos.x += charMetric.advance; | ||||
| 
 | ||||
| 			/* Get texture out */ | ||||
| 			v4 charTexRect = font->atlas->texRect[relativeIndex]; | ||||
| 			flipTexCoord(&charTexRect, FALSE, TRUE); | ||||
| 			RenderTex renderTex = {font->tex, charTexRect}; | ||||
| 			Rect charTexRect = | ||||
| 			    asset_getAtlasSubTexRect(font->atlas, &CAST(char)codepoint); | ||||
| 
 | ||||
| 			v4 deprecatedTexRect = {0}; | ||||
| 			deprecatedTexRect.vec2[0] = charTexRect.pos; | ||||
| 			deprecatedTexRect.vec2[1] = v2_add(charTexRect.pos, charTexRect.size); | ||||
| 
 | ||||
| 			flipTexCoord(&deprecatedTexRect, FALSE, TRUE); | ||||
| 
 | ||||
| 			RenderTex renderTex = {tex, deprecatedTexRect}; | ||||
| 			RenderQuad charQuad = | ||||
| 			    createTexQuad(renderer, charRectOnScreen, renderTex); | ||||
| 			stringQuads[quadIndex++] = charQuad; | ||||
| @ -228,7 +230,7 @@ void renderer_string(Renderer *const renderer, MemoryArena *arena, Rect camera, | ||||
| 		// we're rendering a window sized buffer
 | ||||
| 		updateBufferObject(renderer, stringQuads, quadIndex); | ||||
| 		renderObject(renderer, V2(0.0f, 0.0f), renderer->size, pivotPoint, | ||||
| 		             rotate, color, font->tex); | ||||
| 		             rotate, color, tex); | ||||
| 		PLATFORM_MEM_FREE(arena, stringQuads, strLen * sizeof(RenderQuad)); | ||||
| 	} | ||||
| } | ||||
| @ -246,12 +248,17 @@ void renderer_entity(Renderer *renderer, Rect camera, Entity *entity, | ||||
| 	if (math_pointInRect(camera, leftAlignedP) || | ||||
| 	    math_pointInRect(camera, rightAlignedP)) | ||||
| 	{ | ||||
| 		EntityAnim_ *entityAnim = &entity->anim[entity->currAnimId]; | ||||
| 		Animation *anim         = entityAnim->anim; | ||||
| 		i32 frameIndex          = anim->frameIndex[entityAnim->currFrame]; | ||||
| 		v4 animTexRect          = anim->atlas->texRect[frameIndex]; | ||||
| 		EntityAnim *entityAnim = &entity->animList[entity->currAnimId]; | ||||
| 		Animation *anim        = entityAnim->anim; | ||||
| 		char *frameName        = anim->frameList[entityAnim->currFrame]; | ||||
| 		Rect animRect = asset_getAtlasSubTexRect(anim->atlas, frameName); | ||||
| 
 | ||||
| 		if (entity->direction == direction_east) | ||||
| 		// TODO(doyle): Switch to rect
 | ||||
| 		v4 animTexRect = {0}; | ||||
| 		animTexRect.vec2[0] = animRect.pos; | ||||
| 		animTexRect.vec2[1] = v2_add(animRect.pos, animRect.size); | ||||
| 
 | ||||
| 		    if (entity->direction == direction_east) | ||||
| 		{ | ||||
| 			flipTexCoord(&animTexRect, TRUE, FALSE); | ||||
| 		} | ||||
|  | ||||
| @ -420,9 +420,6 @@ INTERNAL void assetInit(GameState *state) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| // TODO(doyle): Use a proper random seed
 | ||||
| #define RANDOM_SEED 0xDEADBEEF | ||||
| 
 | ||||
| #if 1 | ||||
| 	DEBUG_RECURSIVE_PRINT_XML_TREE(&root); | ||||
| #endif | ||||
| @ -433,31 +430,11 @@ INTERNAL void assetInit(GameState *state) | ||||
| 		if(common_strcmp(node->name, "TextureAtlas") == 0) | ||||
| 		{ | ||||
| 			XmlNode *atlasXmlNode     = node; | ||||
| 			TexAtlasEntry *atlasEntry = NULL; | ||||
| 			TexAtlas *atlasEntry = NULL; | ||||
| 			if (common_strcmp(node->attribute.name, "imagePath") == 0) | ||||
| 			{ | ||||
| 				char *imageName = atlasXmlNode->attribute.value; | ||||
| 				u32 atlasHashIndex = common_murmurHash2( | ||||
| 				    imageName, common_strlen(imageName), RANDOM_SEED); | ||||
| 				atlasHashIndex = | ||||
| 				    atlasHashIndex % ARRAY_COUNT(assetManager->texAtlas_); | ||||
| 
 | ||||
| 				atlasEntry = &assetManager->texAtlas_[atlasHashIndex]; | ||||
| 				if (atlasEntry->name) | ||||
| 				{ | ||||
| #ifdef DENGINE_DEBUG | ||||
| 
 | ||||
| 					// NOTE(doyle): Two atlas textures have the same access name
 | ||||
| 					ASSERT(common_strcmp(atlasEntry->name, imageName) != 0); | ||||
| #endif | ||||
| 
 | ||||
| 					while (atlasEntry->next) | ||||
| 						atlasEntry = atlasEntry->next; | ||||
| 
 | ||||
| 					atlasEntry->next = | ||||
| 					    PLATFORM_MEM_ALLOC(arena, 1, TexAtlasEntry); | ||||
| 					atlasEntry       = atlasEntry->next; | ||||
| 				} | ||||
| 				atlasEntry = asset_makeTexAtlas(assetManager, arena, imageName); | ||||
| 
 | ||||
| 				char *dataDir = "data/textures/WorldTraveller/"; | ||||
| 				char imagePath[512] = {0}; | ||||
| @ -466,9 +443,9 @@ INTERNAL void assetInit(GameState *state) | ||||
| 
 | ||||
| 				asset_loadTextureImage(assetManager, imagePath, texlist_claude); | ||||
| 
 | ||||
| 				atlasEntry->name = | ||||
| 				    PLATFORM_MEM_ALLOC(arena, common_strlen(imageName), char); | ||||
| 				common_strncpy(atlasEntry->name, imageName, | ||||
| 				atlasEntry->key = | ||||
| 				    PLATFORM_MEM_ALLOC(arena, common_strlen(imageName)+1, char); | ||||
| 				common_strncpy(atlasEntry->key, imageName, | ||||
| 				               common_strlen(imageName)); | ||||
| 
 | ||||
| 				atlasEntry->tex = | ||||
| @ -495,39 +472,43 @@ INTERNAL void assetInit(GameState *state) | ||||
| 							    0) | ||||
| 							{ | ||||
| 								char *value   = subTextureAttrib->value; | ||||
| 								newSubTexEntry.name = value; | ||||
| 								newSubTexEntry.key = value; | ||||
| 							} | ||||
| 							else if (common_strcmp(subTextureAttrib->name, | ||||
| 							                       "x") == 0) | ||||
| 							{ | ||||
| 								char *value  = subTextureAttrib->value; | ||||
| 								i32 valueLen = common_strlen(value); | ||||
| 								newSubTexEntry.rect.pos.x = | ||||
| 								    CAST(f32) common_atoi(value, valueLen); | ||||
| 								i32 intValue = common_atoi(value, valueLen); | ||||
| 
 | ||||
| 								newSubTexEntry.rect.pos.x = CAST(f32) intValue; | ||||
| 							} | ||||
| 							else if (common_strcmp(subTextureAttrib->name, | ||||
| 							                       "y") == 0) | ||||
| 							{ | ||||
| 								char *value  = subTextureAttrib->value; | ||||
| 								i32 valueLen = common_strlen(value); | ||||
| 								newSubTexEntry.rect.pos.y = | ||||
| 								    CAST(f32) common_atoi(value, valueLen); | ||||
| 
 | ||||
| 								i32 intValue = common_atoi(value, valueLen); | ||||
| 								newSubTexEntry.rect.pos.y = CAST(f32) intValue; | ||||
| 							} | ||||
| 							else if (common_strcmp(subTextureAttrib->name, | ||||
| 							                       "width") == 0) | ||||
| 							{ | ||||
| 								char *value  = subTextureAttrib->value; | ||||
| 								i32 valueLen = common_strlen(value); | ||||
| 								newSubTexEntry.rect.size.w = | ||||
| 								    CAST(f32) common_atoi(value, valueLen); | ||||
| 								i32 intValue = common_atoi(value, valueLen); | ||||
| 
 | ||||
| 								newSubTexEntry.rect.size.w = CAST(f32) intValue; | ||||
| 							} | ||||
| 							else if (common_strcmp(subTextureAttrib->name, | ||||
| 							                       "height") == 0) | ||||
| 							{ | ||||
| 								char *value  = subTextureAttrib->value; | ||||
| 								i32 valueLen = common_strlen(value); | ||||
| 								newSubTexEntry.rect.size.h = | ||||
| 								    CAST(f32) common_atoi(value, valueLen); | ||||
| 								i32 intValue = common_atoi(value, valueLen); | ||||
| 
 | ||||
| 								newSubTexEntry.rect.size.h = CAST(f32) intValue; | ||||
| 							} | ||||
| 							else | ||||
| 							{ | ||||
| @ -536,32 +517,37 @@ INTERNAL void assetInit(GameState *state) | ||||
| 								    "Unsupported xml attribute in SubTexture"); | ||||
| #endif | ||||
| 							} | ||||
| 
 | ||||
| 							subTextureAttrib = subTextureAttrib->next; | ||||
| 						} | ||||
| 
 | ||||
| 						// TODO(doyle): XML specifies 0,0 top left, we
 | ||||
| 						// prefer 0,0 bottom right, so offset by size since 0,0
 | ||||
| 						// is top left and size creates a bounding box below it
 | ||||
| 						newSubTexEntry.rect.pos.y = | ||||
| 						    1024 - newSubTexEntry.rect.pos.y; | ||||
| 						newSubTexEntry.rect.pos.y -= newSubTexEntry.rect.size.h; | ||||
| 
 | ||||
| #ifdef DENGINE_DEBUG | ||||
| 						ASSERT(newSubTexEntry.name) | ||||
| 						ASSERT(newSubTexEntry.key) | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| 						u32 subTexHashIndex = common_murmurHash2( | ||||
| 						    newSubTexEntry.name, common_strlen(newSubTexEntry.name), | ||||
| 						    RANDOM_SEED); | ||||
| 						    newSubTexEntry.key, | ||||
| 						    common_strlen(newSubTexEntry.key), 0xDEADBEEF); | ||||
| 						subTexHashIndex = | ||||
| 						    subTexHashIndex % ARRAY_COUNT(atlasEntry->subTex); | ||||
| 
 | ||||
| 						// NOTE(doyle): Hash collision
 | ||||
| 						AtlasSubTexture *subTexEntry = | ||||
| 						    &atlasEntry->subTex[subTexHashIndex]; | ||||
| 						if (subTexEntry->name) | ||||
| 						if (subTexEntry->key) | ||||
| 						{ | ||||
| #ifdef DENGINE_DEBUG | ||||
| 
 | ||||
| 							// NOTE(doyle): Two textures have the same access
 | ||||
| 							// name
 | ||||
| 							ASSERT(common_strcmp(subTexEntry->name, | ||||
| 							                     newSubTexEntry.name) != 0); | ||||
| 							ASSERT(common_strcmp(subTexEntry->key, | ||||
| 							                     newSubTexEntry.key) != 0); | ||||
| #endif | ||||
| 							while (subTexEntry->next) | ||||
| 								subTexEntry = subTexEntry->next; | ||||
| @ -572,8 +558,12 @@ INTERNAL void assetInit(GameState *state) | ||||
| 						} | ||||
| 
 | ||||
| 						*subTexEntry = newSubTexEntry; | ||||
| 						common_strncpy(subTexEntry->name, newSubTexEntry.name, | ||||
| 						               common_strlen(newSubTexEntry.name)); | ||||
| 						i32 keyLen   = common_strlen(newSubTexEntry.key); | ||||
| 
 | ||||
| 						subTexEntry->key = | ||||
| 						    PLATFORM_MEM_ALLOC(arena, keyLen+1, char); | ||||
| 						common_strncpy(subTexEntry->key, newSubTexEntry.key, | ||||
| 						               keyLen); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| @ -601,34 +591,6 @@ INTERNAL void assetInit(GameState *state) | ||||
| 		node = node->next; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Load textures */ | ||||
| 	asset_loadTextureImage(assetManager, | ||||
| 	                       "data/textures/WorldTraveller/TerraSprite1024.png", | ||||
| 	                       texlist_hero); | ||||
| 	TexAtlas *heroAtlas = asset_getTextureAtlas(assetManager, texlist_hero); | ||||
| 	heroAtlas->texRect[herorects_idle]       = V4(746, 920, 804, 1018); | ||||
| 	heroAtlas->texRect[herorects_walkA]      = V4(641, 920, 699, 1018); | ||||
| 	heroAtlas->texRect[herorects_walkB]      = V4(849, 920, 904, 1018); | ||||
| 	heroAtlas->texRect[herorects_head]       = V4(108, 975, 159, 1024); | ||||
| 	heroAtlas->texRect[herorects_waveA]      = V4(944, 816, 1010, 918); | ||||
| 	heroAtlas->texRect[herorects_waveB]      = V4(944, 710, 1010, 812); | ||||
| 	heroAtlas->texRect[herorects_battlePose] = V4(8, 814, 71, 910); | ||||
| 	heroAtlas->texRect[herorects_castA]      = V4(428, 814, 493, 910); | ||||
| 	heroAtlas->texRect[herorects_castB]      = V4(525, 816, 590, 919); | ||||
| 	heroAtlas->texRect[herorects_castC]      = V4(640, 816, 698, 916); | ||||
| 
 | ||||
| 	asset_loadTextureImage(assetManager, | ||||
| 	                       "data/textures/WorldTraveller/Terrain.png", | ||||
| 	                       texlist_terrain); | ||||
| 	TexAtlas *terrainAtlas = | ||||
| 	    asset_getTextureAtlas(assetManager, texlist_terrain); | ||||
| 	f32 atlasTileSize = 128.0f; | ||||
| 	const i32 texSize = 1024; | ||||
| 	v2 texOrigin = V2(0, 768); | ||||
| 	terrainAtlas->texRect[terrainrects_ground] = | ||||
| 	    V4(texOrigin.x, texOrigin.y, texOrigin.x + atlasTileSize, | ||||
| 	       texOrigin.y + atlasTileSize); | ||||
| 
 | ||||
| 	/* Load shaders */ | ||||
| 	asset_loadShaderFiles(assetManager, arena, "data/shaders/sprite.vert.glsl", | ||||
| 	                      "data/shaders/sprite.frag.glsl", | ||||
| @ -643,6 +605,7 @@ INTERNAL void assetInit(GameState *state) | ||||
| 	DEBUG_LOG("Assets loaded"); | ||||
| #endif | ||||
| 
 | ||||
| #if 0 | ||||
| 	/* Load animations */ | ||||
| 	f32 duration = 1.0f; | ||||
| 	i32 numRects = 1; | ||||
| @ -660,7 +623,20 @@ INTERNAL void assetInit(GameState *state) | ||||
| 	i32 idleAnimAtlasIndexes[1] = {herorects_idle}; | ||||
| 	asset_addAnimation(assetManager, arena, texlist_hero, animlist_hero_idle, | ||||
| 	                   idleAnimAtlasIndexes, numRects, duration); | ||||
| #else | ||||
| 	f32 duration = 1.0f; | ||||
| 	i32 numRects = 1; | ||||
| 	TexAtlas *claudeAtlas = | ||||
| 	    asset_getTexAtlas(assetManager, "ClaudeSpriteSheet.png"); | ||||
| 
 | ||||
| 	duration      = 1.0f; | ||||
| 	numRects      = 1; | ||||
| 	char *subTextureNames = {"ClaudeSprite_001"}; | ||||
| 	asset_addAnimation(assetManager, arena, "Claude_idle", claudeAtlas, | ||||
| 	                   &subTextureNames, 1, 1.0f); | ||||
| #endif | ||||
| 
 | ||||
| #if 0 | ||||
| 	// Walk animation
 | ||||
| 	duration          = 0.10f; | ||||
| 	numRects          = 3; | ||||
| @ -690,6 +666,8 @@ INTERNAL void assetInit(GameState *state) | ||||
| 	                                 herorects_castC}; | ||||
| 	asset_addAnimation(assetManager, arena, texlist_hero, animlist_hero_tackle, | ||||
| 	                   tackleAnimAtlasIndexes, numRects, duration); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef DENGINE_DEBUG | ||||
| 	DEBUG_LOG("Animations created"); | ||||
| #endif | ||||
| @ -739,6 +717,7 @@ INTERNAL void entityInit(GameState *state, v2 windowSize) | ||||
| 		                                    CAST(f32) state->tileSize)); | ||||
| 		world->uniqueIdAccumulator = 0; | ||||
| 
 | ||||
| #if 0 | ||||
| 		TexAtlas *const atlas = | ||||
| 		    asset_getTextureAtlas(assetManager, world->texType); | ||||
| 
 | ||||
| @ -765,6 +744,7 @@ INTERNAL void entityInit(GameState *state, v2 windowSize) | ||||
| 				tile->currAnimId = animlist_terrain; | ||||
| 			} | ||||
| 		} | ||||
| #endif | ||||
| 	} | ||||
| 
 | ||||
| 	World *const world = &state->world[state->currWorldIndex]; | ||||
| @ -790,7 +770,7 @@ INTERNAL void entityInit(GameState *state, v2 windowSize) | ||||
| 	pos             = V2(size.x, CAST(f32) state->tileSize); | ||||
| 	type            = entitytype_hero; | ||||
| 	dir             = direction_east; | ||||
| 	tex             = asset_getTexture(assetManager, texlist_hero); | ||||
| 	tex             = asset_getTexture(assetManager, texlist_claude); | ||||
| 	collides        = TRUE; | ||||
| 	Entity *hero = | ||||
| 	    entity_add(arena, world, pos, size, type, dir, tex, collides); | ||||
| @ -801,13 +781,10 @@ INTERNAL void entityInit(GameState *state, v2 windowSize) | ||||
| 	world->cameraFollowingId = hero->id; | ||||
| 
 | ||||
| 	/* Populate hero animation references */ | ||||
| 	entity_addAnim(assetManager, hero, animlist_hero_idle); | ||||
| 	entity_addAnim(assetManager, hero, animlist_hero_walk); | ||||
| 	entity_addAnim(assetManager, hero, animlist_hero_wave); | ||||
| 	entity_addAnim(assetManager, hero, animlist_hero_battlePose); | ||||
| 	entity_addAnim(assetManager, hero, animlist_hero_tackle); | ||||
| 	hero->currAnimId = animlist_hero_idle; | ||||
| 	entity_addAnim(assetManager, hero, "Claude_idle"); | ||||
| 	entity_setActiveAnim(hero, "Claude_idle"); | ||||
| 
 | ||||
| #if 0 | ||||
| 	/* Create a NPC */ | ||||
| 	pos         = V2(hero->pos.x * 3, CAST(f32) state->tileSize); | ||||
| 	size        = hero->hitboxSize; | ||||
| @ -825,6 +802,7 @@ INTERNAL void entityInit(GameState *state, v2 windowSize) | ||||
| 	pos = V2(renderer->size.w - (renderer->size.w / 3.0f), | ||||
| 	         CAST(f32) state->tileSize); | ||||
| 	entity_addGenericMob(arena, assetManager, world, pos); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef DENGINE_DEBUG | ||||
| 	DEBUG_LOG("World populated"); | ||||
| @ -1152,7 +1130,7 @@ INTERNAL inline void updateWorldBattleEntities(World *world, Entity *entity, | ||||
| INTERNAL inline void resetEntityState(World *world, Entity *entity) | ||||
| { | ||||
| 	updateWorldBattleEntities(world, entity, ENTITY_NOT_IN_BATTLE); | ||||
| 	entity_setActiveAnim(entity, animlist_hero_idle); | ||||
| 	entity_setActiveAnim(entity, "Claude_idle"); | ||||
| 	entity->stats->busyDuration     = 0; | ||||
| 	entity->stats->actionTimer      = entity->stats->actionRate; | ||||
| 	entity->stats->queuedAttack     = entityattack_invalid; | ||||
| @ -1196,7 +1174,7 @@ INTERNAL void entityStateSwitch(EventQueue *eventQueue, World *world, | ||||
| 		// or not (i.e. has moved out of frame last frame).
 | ||||
| 		case entitystate_dead: | ||||
| 			registerEvent(eventQueue, eventtype_entity_died, CAST(void *)entity); | ||||
| 			entity_setActiveAnim(entity, animlist_hero_idle); | ||||
| 			entity_setActiveAnim(entity, "Claude_idle"); | ||||
| 			entity->stats->busyDuration     = 0; | ||||
| 			entity->stats->actionTimer      = entity->stats->actionRate; | ||||
| 			entity->stats->queuedAttack     = entityattack_invalid; | ||||
| @ -1236,7 +1214,7 @@ INTERNAL void entityStateSwitch(EventQueue *eventQueue, World *world, | ||||
| 		switch (newState) | ||||
| 		{ | ||||
| 		case entitystate_battle: | ||||
| 			entity_setActiveAnim(entity, animlist_hero_battlePose); | ||||
| 			entity_setActiveAnim(entity, "Claude_idle"); | ||||
| 			entity->stats->actionTimer  = entity->stats->actionRate; | ||||
| 			entity->stats->busyDuration = 0; | ||||
| 			break; | ||||
| @ -1288,6 +1266,7 @@ typedef struct AttackSpec | ||||
| INTERNAL void beginAttack(EventQueue *eventQueue, World *world, | ||||
|                           Entity *attacker) | ||||
| { | ||||
| #if 0 | ||||
| #ifdef DENGINE_DEBUG | ||||
| 	ASSERT(attacker->stats->entityIdToAttack != ENTITY_NULL_ID); | ||||
| 	ASSERT(attacker->state == entitystate_battle); | ||||
| @ -1313,6 +1292,7 @@ INTERNAL void beginAttack(EventQueue *eventQueue, World *world, | ||||
| #endif | ||||
| 		break; | ||||
| 	} | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // TODO(doyle): MemArena here is temporary until we incorporate AttackSpec to
 | ||||
| @ -1320,6 +1300,7 @@ INTERNAL void beginAttack(EventQueue *eventQueue, World *world, | ||||
| INTERNAL void endAttack(MemoryArena *arena, EventQueue *eventQueue, | ||||
|                         World *world, Entity *attacker) | ||||
| { | ||||
| #if 0 | ||||
| #ifdef DENGINE_DEBUG | ||||
| 	ASSERT(attacker->stats->entityIdToAttack != ENTITY_NULL_ID); | ||||
| #endif | ||||
| @ -1398,6 +1379,7 @@ INTERNAL void endAttack(MemoryArena *arena, EventQueue *eventQueue, | ||||
| 			entityStateSwitch(eventQueue, world, attacker, entitystate_idle); | ||||
| 		} | ||||
| 	} | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| INTERNAL void sortWorldEntityList(World *world) | ||||
| @ -1735,12 +1717,12 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt) | ||||
| 				hero->dPos = V2(0.0f, 0.0f); | ||||
| 				if (hero->currAnimId == animlist_hero_walk) | ||||
| 				{ | ||||
| 					entity_setActiveAnim(hero, animlist_hero_idle); | ||||
| 					entity_setActiveAnim(hero, "Claude_idle"); | ||||
| 				} | ||||
| 			} | ||||
| 			else if (hero->currAnimId == animlist_hero_idle) | ||||
| 			{ | ||||
| 				entity_setActiveAnim(hero, animlist_hero_walk); | ||||
| 				entity_setActiveAnim(hero, "Claude_idle"); | ||||
| 			} | ||||
| 
 | ||||
| 			f32 heroSpeed = 6.2f * METERS_TO_PIXEL; | ||||
| @ -1978,7 +1960,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt) | ||||
| 		{ | ||||
| 			hero->state                       = entitystate_idle; | ||||
| 			world->entityIdInBattle[hero->id] = FALSE; | ||||
| 			entity_setActiveAnim(hero, animlist_hero_idle); | ||||
| 			entity_setActiveAnim(hero, "Claude_idle"); | ||||
| 		} | ||||
| 		hero->stats->entityIdToAttack = -1; | ||||
| 		hero->stats->actionTimer      = hero->stats->actionRate; | ||||
| @ -2058,6 +2040,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt) | ||||
| 	state->uiState.keyChar    = keycode_null; | ||||
| 
 | ||||
| 	/* Draw hero avatar */ | ||||
| #if 0 | ||||
| 	TexAtlas *heroAtlas  = asset_getTextureAtlas(assetManager, texlist_hero); | ||||
| 	v4 heroAvatarTexRect = heroAtlas->texRect[herorects_head]; | ||||
| 	v2 heroAvatarSize    = math_getRectSize(heroAvatarTexRect); | ||||
| @ -2079,6 +2062,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt) | ||||
| 
 | ||||
| 	renderer_staticString(&state->renderer, &state->arena, font, heroAvatarStr, | ||||
| 	                      strPos, V2(0, 0), 0, V4(0, 0, 1, 1)); | ||||
| #endif | ||||
| 
 | ||||
| 	for (i32 i = 0; i < world->maxEntities; i++) | ||||
| 	{ | ||||
|  | ||||
| @ -11,25 +11,33 @@ typedef struct MemoryArena MemoryArena; | ||||
| typedef struct AssetManager | ||||
| { | ||||
| 	Texture textures[32]; | ||||
| 	TexAtlas texAtlas[32]; | ||||
| 	Shader shaders[32]; | ||||
| 	Animation anims[32]; | ||||
| 	Animation anims[1024]; | ||||
| 	AudioVorbis audio[32]; | ||||
| 	Font font; | ||||
| 
 | ||||
| 	TexAtlasEntry texAtlas_[8]; | ||||
| 	TexAtlas texAtlas[8]; | ||||
| } AssetManager; | ||||
| 
 | ||||
| #define MAX_TEXTURE_SIZE 1024 | ||||
| 
 | ||||
| Rect asset_getAtlasSubTexRect(TexAtlas *atlas, char *key); | ||||
| 
 | ||||
| AudioVorbis *asset_getVorbis(AssetManager *assetManager, | ||||
|                              const enum AudioList type); | ||||
| 
 | ||||
| Texture *asset_getTexture(AssetManager *const assetManager, | ||||
|                           const enum TexList type); | ||||
| 
 | ||||
| TexAtlas *asset_makeTexAtlas(AssetManager *const assetManager, | ||||
|                              MemoryArena *arena, const char *const key); | ||||
| 
 | ||||
| Shader *asset_getShader(AssetManager *assetManager, const enum ShaderList type); | ||||
| TexAtlas *asset_getTextureAtlas(AssetManager *assetManager, | ||||
|                                 const enum TexList type); | ||||
| Animation *asset_getAnim(AssetManager *assetManager, i32 type); | ||||
| 
 | ||||
| TexAtlas *asset_getTexAtlas(AssetManager *const assetManager, | ||||
|                             const char *const key); | ||||
| 
 | ||||
| Animation *asset_getAnim(AssetManager *assetManager, char *key); | ||||
| 
 | ||||
| const i32 asset_loadVorbis(AssetManager *assetManager, MemoryArena *arena, | ||||
|                            const char *const path, const enum AudioList type); | ||||
| @ -46,8 +54,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena, | ||||
|                            const char *filePath); | ||||
| 
 | ||||
| void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena, | ||||
|                         i32 texId, i32 animId, i32 *atlasIndexes, i32 numFrames, | ||||
|                         f32 frameDuration); | ||||
|                         char *animName, TexAtlas *atlas, char **subTextureNames, | ||||
|                         i32 numSubTextures, f32 frameDuration); | ||||
| 
 | ||||
| v2 asset_stringDimInPixels(const Font *const font, const char *const string); | ||||
| 
 | ||||
|  | ||||
| @ -83,36 +83,37 @@ typedef struct AudioVorbis | ||||
| 
 | ||||
| typedef struct AtlasSubTexture | ||||
| { | ||||
| 	char *name; | ||||
| 	// NOTE(doyle): Key used to arrive to hash entry
 | ||||
| 	char *key; | ||||
| 	Rect rect; | ||||
| 	 | ||||
| 	// NOTE(doyle): For hashing collisions
 | ||||
| 	struct AtlasSubTexture *next; | ||||
| } AtlasSubTexture; | ||||
| 
 | ||||
| typedef struct TexAtlasEntry | ||||
| { | ||||
| 	char *name; | ||||
| 	Texture *tex; | ||||
| 	AtlasSubTexture subTex[1024]; | ||||
| 
 | ||||
| 	// NOTE(doyle): For hashing collisions
 | ||||
| 	struct TexAtlasEntry *next; | ||||
| } TexAtlasEntry; | ||||
| 
 | ||||
| typedef struct TexAtlas | ||||
| { | ||||
| 	// TODO(doyle): String hash based lookup
 | ||||
| 	v4 texRect[128]; | ||||
| 	char *key; | ||||
| 	Texture *tex; | ||||
| 	AtlasSubTexture subTex[512]; | ||||
| 
 | ||||
| 	struct TexAtlas *next; | ||||
| } TexAtlas; | ||||
| 
 | ||||
| typedef struct Animation | ||||
| { | ||||
| 	union { | ||||
| 		char *name; | ||||
| 		char *key; | ||||
| 	}; | ||||
| 
 | ||||
| 	TexAtlas *atlas; | ||||
| 	i32 *frameIndex; | ||||
| 	char **frameList; | ||||
| 
 | ||||
| 	i32 numFrames; | ||||
| 	f32 frameDuration; | ||||
| 
 | ||||
| 	struct Animation *next; | ||||
| } Animation; | ||||
| 
 | ||||
| // TODO(doyle): We only use the offset and advance metric at the moment, remove?
 | ||||
| @ -136,8 +137,6 @@ typedef struct CharMetrics | ||||
| typedef struct Font | ||||
| { | ||||
| 	TexAtlas *atlas; | ||||
| 	Texture *tex; | ||||
| 
 | ||||
| 	FontMetrics metrics; | ||||
| 
 | ||||
| 	// NOTE(doyle): Array of character's by ASCII value starting from
 | ||||
|  | ||||
| @ -54,4 +54,14 @@ i32 common_atoi(const char *string, const i32 len); | ||||
| //    machines.
 | ||||
| u32 common_murmurHash2(const void *key, i32 len, u32 seed); | ||||
| 
 | ||||
| // TODO(doyle): Use a proper random seed
 | ||||
| #define RANDOM_SEED 0xDEADBEEF | ||||
| inline u32 common_getHashIndex(const char *const key, u32 tableSize) | ||||
| { | ||||
| 	u32 result = common_murmurHash2(key, common_strlen(key), RANDOM_SEED); | ||||
| 	result     = result % tableSize; | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -63,12 +63,12 @@ typedef struct EntityStats | ||||
| 	enum EntityAttack queuedAttack; | ||||
| } EntityStats; | ||||
| 
 | ||||
| typedef struct EntityAnim_ | ||||
| typedef struct EntityAnim | ||||
| { | ||||
| 	Animation *anim; | ||||
| 	i32 currFrame; | ||||
| 	f32 currDuration; | ||||
| } EntityAnim_; | ||||
| } EntityAnim; | ||||
| 
 | ||||
| typedef struct Entity | ||||
| { | ||||
| @ -86,22 +86,17 @@ typedef struct Entity | ||||
| 	Texture *tex; | ||||
| 	b32 collides; | ||||
| 
 | ||||
| 	// TODO(doyle): String based access
 | ||||
| 	// TODO(doyle): Separate animation refs from curr animation state, entity
 | ||||
| 	// only ever has one active current animation. ATM every entity animation
 | ||||
| 	// has a currframe and duration .. either that or we stop resetting
 | ||||
| 	// animation on entity context switch
 | ||||
| 	EntityAnim_ anim[16]; | ||||
| 	enum AnimList currAnimId; | ||||
| 	EntityAnim animList[16]; | ||||
| 	i32 currAnimId; | ||||
| 
 | ||||
| 	EntityStats *stats; | ||||
| 	AudioRenderer *audioRenderer; | ||||
| 	i32 numAudioRenderers; | ||||
| } Entity; | ||||
| 
 | ||||
| void entity_setActiveAnim(Entity *entity, enum AnimList animId); | ||||
| void entity_setActiveAnim(Entity *entity, char *animName); | ||||
| void entity_updateAnim(Entity *entity, f32 dt); | ||||
| void entity_addAnim(AssetManager *assetManager, Entity *entity, i32 animId); | ||||
| void entity_addAnim(AssetManager *assetManager, Entity *entity, char *animName); | ||||
| void entity_addGenericMob(MemoryArena *arena, AssetManager *assetManager, | ||||
|                           World *world, v2 pos); | ||||
| Entity *entity_add(MemoryArena *arena, World *world, v2 pos, v2 size, | ||||
|  | ||||
| @ -25,6 +25,8 @@ typedef struct Renderer | ||||
| typedef struct RenderTex | ||||
| { | ||||
| 	Texture *tex; | ||||
| 
 | ||||
| 	// TODO(doyle): Switch to rect
 | ||||
| 	v4 texRect; | ||||
| } RenderTex; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user