Add resolution changer in options menu
This commit is contained in:
		
							parent
							
								
									eb4b0e1714
								
							
						
					
					
						commit
						10891ab56e
					
				
							
								
								
									
										230
									
								
								src/Asteroid.c
									
									
									
									
									
								
							
							
						
						
									
										230
									
								
								src/Asteroid.c
									
									
									
									
									
								
							| @ -91,7 +91,7 @@ INTERNAL v2 *createAsteroidVertexList(MemoryArena_ *arena, i32 iterations, | |||||||
| 		ASSERT(result[i].x >= 0 && result[i].y >= 0); | 		ASSERT(result[i].x >= 0 && result[i].y >= 0); | ||||||
| 
 | 
 | ||||||
| #if 1 | #if 1 | ||||||
| 		f32 displacementDist   = 0.50f * asteroidRadius; | 		f32 displacementDist = 0.50f * asteroidRadius; | ||||||
| 		i32 vertexDisplacement = | 		i32 vertexDisplacement = | ||||||
| 		    randValue % (i32)displacementDist + (i32)(displacementDist * 0.25f); | 		    randValue % (i32)displacementDist + (i32)(displacementDist * 0.25f); | ||||||
| 
 | 
 | ||||||
| @ -240,16 +240,15 @@ INTERNAL u32 moveEntity(GameWorldState *world, MemoryArena_ *transientArena, | |||||||
| 			ASSERT(checkEntity->vertexPoints); | 			ASSERT(checkEntity->vertexPoints); | ||||||
| 
 | 
 | ||||||
| 			/* Create entity edge lists */ | 			/* Create entity edge lists */ | ||||||
| 			v2 *entityVertexListOffsetToP = entity_generateUpdatedVertexList( | 			v2 *entityVertexListOffsetToP = | ||||||
| 			    transientArena, entity); | 			    entity_generateUpdatedVertexList(transientArena, entity); | ||||||
| 
 | 
 | ||||||
| 			v2 *checkEntityVertexListOffsetToP = | 			v2 *checkEntityVertexListOffsetToP = | ||||||
| 			    entity_generateUpdatedVertexList(transientArena, | 			    entity_generateUpdatedVertexList(transientArena, checkEntity); | ||||||
| 			                                     checkEntity); |  | ||||||
| 
 | 
 | ||||||
| 			v2 *entityEdgeList = createNormalEdgeList(transientArena, | 			v2 *entityEdgeList = | ||||||
| 			                                          entityVertexListOffsetToP, | 			    createNormalEdgeList(transientArena, entityVertexListOffsetToP, | ||||||
| 			                                          entity->numVertexPoints); | 			                         entity->numVertexPoints); | ||||||
| 
 | 
 | ||||||
| 			v2 *checkEntityEdgeList = createNormalEdgeList( | 			v2 *checkEntityEdgeList = createNormalEdgeList( | ||||||
| 			    transientArena, checkEntityVertexListOffsetToP, | 			    transientArena, checkEntityVertexListOffsetToP, | ||||||
| @ -296,7 +295,8 @@ enum AsteroidSize | |||||||
| 	asteroidsize_count, | 	asteroidsize_count, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct | ||||||
|  | { | ||||||
| 	v2 pos; | 	v2 pos; | ||||||
| 	v2 dP; | 	v2 dP; | ||||||
| } AsteroidSpec; | } AsteroidSpec; | ||||||
| @ -377,12 +377,12 @@ INTERNAL void addAsteroidWithSpec(GameWorldState *world, | |||||||
| 		{ | 		{ | ||||||
| 			ASSERT(INVALID_CODE_PATH); | 			ASSERT(INVALID_CODE_PATH); | ||||||
| 		} | 		} | ||||||
| 		asteroid->pos       = newP; | 		asteroid->pos = newP; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		asteroid->pos       = spec->pos; | 		asteroid->pos = spec->pos; | ||||||
| 		asteroid->dP        = spec->dP; | 		asteroid->dP  = spec->dP; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	asteroid->size            = size; | 	asteroid->size            = size; | ||||||
| @ -406,7 +406,7 @@ INTERNAL void addAsteroidWithSpec(GameWorldState *world, | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	asteroid->vertexPoints = vertexCache[cacheIndex]; | 	asteroid->vertexPoints = vertexCache[cacheIndex]; | ||||||
| 	asteroid->color = V4(1.0f, 1.0f, 1.0f, 1.0f); | 	asteroid->color        = V4(1.0f, 1.0f, 1.0f, 1.0f); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| INTERNAL void addAsteroid(GameWorldState *world, enum AsteroidSize asteroidSize) | INTERNAL void addAsteroid(GameWorldState *world, enum AsteroidSize asteroidSize) | ||||||
| @ -456,7 +456,7 @@ INTERNAL AudioRenderer *getFreeAudioRenderer(GameWorldState *world, | |||||||
|                                              AudioVorbis *vorbis, |                                              AudioVorbis *vorbis, | ||||||
|                                              i32 maxSimultaneousPlayers) |                                              i32 maxSimultaneousPlayers) | ||||||
| { | { | ||||||
| 	i32 freeIndex = -1; | 	i32 freeIndex             = -1; | ||||||
| 	i32 sameAudioPlayingCount = 0; | 	i32 sameAudioPlayingCount = 0; | ||||||
| 
 | 
 | ||||||
| 	AudioRenderer *result = NULL; | 	AudioRenderer *result = NULL; | ||||||
| @ -512,13 +512,13 @@ INTERNAL void addPlayer(GameWorldState *world) | |||||||
| INTERNAL void deleteEntity(GameWorldState *world, i32 entityIndex) | INTERNAL void deleteEntity(GameWorldState *world, i32 entityIndex) | ||||||
| { | { | ||||||
| 	ASSERT(entityIndex > 0); | 	ASSERT(entityIndex > 0); | ||||||
| 	ASSERT(entityIndex < ARRAY_COUNT(world->entityList)); | 	ASSERT(entityIndex < world->entityListSize); | ||||||
| 
 | 
 | ||||||
| 	/* Last entity replaces the entity to delete */ | 	/* Last entity replaces the entity to delete */ | ||||||
| 	world->entityList[entityIndex] = world->entityList[world->entityIndex - 1]; | 	world->entityList[entityIndex] = world->entityList[world->entityIndex - 1]; | ||||||
| 
 | 
 | ||||||
| 	/* Make sure the replaced entity from end of list is cleared out */ | 	/* Make sure the replaced entity from end of list is cleared out */ | ||||||
| 	Entity emptyEntity = {0}; | 	Entity emptyEntity                      = {0}; | ||||||
| 	world->entityList[--world->entityIndex] = emptyEntity; | 	world->entityList[--world->entityIndex] = emptyEntity; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -581,6 +581,10 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 		world->camera.max = state->renderer.size; | 		world->camera.max = state->renderer.size; | ||||||
| 		world->size       = state->renderer.size; | 		world->size       = state->renderer.size; | ||||||
| 
 | 
 | ||||||
|  | 		world->entityListSize = 1024; | ||||||
|  | 		world->entityList     = MEMORY_PUSH_ARRAY(&world->entityArena, | ||||||
|  | 		                                      world->entityListSize, Entity); | ||||||
|  | 
 | ||||||
| 		{ // Init null entity
 | 		{ // Init null entity
 | ||||||
| 			Entity *nullEntity = &world->entityList[world->entityIndex++]; | 			Entity *nullEntity = &world->entityList[world->entityIndex++]; | ||||||
| 			nullEntity->id     = world->entityIdCounter++; | 			nullEntity->id     = world->entityIdCounter++; | ||||||
| @ -613,7 +617,7 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 
 | 
 | ||||||
| 		world->numStarP = 100; | 		world->numStarP = 100; | ||||||
| 		world->starPList = | 		world->starPList = | ||||||
| 		    MEMORY_PUSH_ARRAY(&state->persistentArena, world->numStarP, v2); | 		    MEMORY_PUSH_ARRAY(&world->entityArena, world->numStarP, v2); | ||||||
| 
 | 
 | ||||||
| 		for (i32 i = 0; i < world->numStarP; i++) | 		for (i32 i = 0; i < world->numStarP; i++) | ||||||
| 		{ | 		{ | ||||||
| @ -630,7 +634,7 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 		addAsteroid(world, (rand() % asteroidsize_count)); | 		addAsteroid(world, (rand() % asteroidsize_count)); | ||||||
| 
 | 
 | ||||||
| 	Radians starRotation = DEGREES_TO_RADIANS(45.0f); | 	Radians starRotation = DEGREES_TO_RADIANS(45.0f); | ||||||
| 	v2 starSize = V2(2, 2); | 	v2 starSize          = V2(2, 2); | ||||||
| 	for (i32 i = 0; i < world->numStarP; i++) | 	for (i32 i = 0; i < world->numStarP; i++) | ||||||
| 	{ | 	{ | ||||||
| 		renderer_rect(&state->renderer, world->camera, world->starPList[i], | 		renderer_rect(&state->renderer, world->camera, world->starPList[i], | ||||||
| @ -640,7 +644,7 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (platform_queryKey(&state->input.keys[keycode_left_square_bracket], | 	if (platform_queryKey(&state->input.keys[keycode_left_square_bracket], | ||||||
| 	                 readkeytype_repeat, 0.2f)) | 	                      readkeytype_repeat, 0.2f)) | ||||||
| 	{ | 	{ | ||||||
| 		addAsteroid(world, (rand() % asteroidsize_count)); | 		addAsteroid(world, (rand() % asteroidsize_count)); | ||||||
| 	} | 	} | ||||||
| @ -673,17 +677,17 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 			{ | 			{ | ||||||
| 				addBullet(world, entity); | 				addBullet(world, entity); | ||||||
| 
 | 
 | ||||||
| 					AudioVorbis *fire = | 				AudioVorbis *fire = | ||||||
| 					    asset_vorbisGet(&state->assetManager, "fire"); | 				    asset_vorbisGet(&state->assetManager, "fire"); | ||||||
| 				    AudioRenderer *audioRenderer = | 				AudioRenderer *audioRenderer = | ||||||
| 				        getFreeAudioRenderer(world, fire, 2); | 				    getFreeAudioRenderer(world, fire, 2); | ||||||
| 				    if (audioRenderer) | 				if (audioRenderer) | ||||||
| 				    { | 				{ | ||||||
| 					    // TODO(doyle): Atm transient arena is not used, this is
 | 					// TODO(doyle): Atm transient arena is not used, this is
 | ||||||
| 					    // just to fill out the arguments
 | 					// just to fill out the arguments
 | ||||||
| 					    audio_vorbisPlay(&state->transientArena, | 					audio_vorbisPlay(&state->transientArena, | ||||||
| 					                     &state->audioManager, audioRenderer, | 					                 &state->audioManager, audioRenderer, fire, | ||||||
| 					                     fire, 1); | 					                 1); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| @ -768,11 +772,15 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 			// direction by extrapolating from it's current dp
 | 			// direction by extrapolating from it's current dp
 | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				if (entity->dP.x >= 0) localDp.x = 1.0f; | 				if (entity->dP.x >= 0) | ||||||
| 				else localDp.x = -1.0f; | 					localDp.x = 1.0f; | ||||||
|  | 				else | ||||||
|  | 					localDp.x = -1.0f; | ||||||
| 
 | 
 | ||||||
| 				if (entity->dP.y >= 0) localDp.y = 1.0f; | 				if (entity->dP.y >= 0) | ||||||
| 				else localDp.y = -1.0f; | 					localDp.y = 1.0f; | ||||||
|  | 				else | ||||||
|  | 					localDp.y = -1.0f; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			/*
 | 			/*
 | ||||||
| @ -814,10 +822,9 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 
 | 
 | ||||||
| 			f32 divisor = | 			f32 divisor = | ||||||
| 			    MAX(entity->particleInitDp.x, entity->particleInitDp.y); | 			    MAX(entity->particleInitDp.x, entity->particleInitDp.y); | ||||||
| 			f32 maxDp   = MAX(entity->dP.x, entity->dP.y); | 			f32 maxDp = MAX(entity->dP.x, entity->dP.y); | ||||||
| 
 | 
 | ||||||
| 			entity->color.a = maxDp / divisor; | 			entity->color.a = maxDp / divisor; | ||||||
| 
 |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		/* Loop entity around world */ | 		/* Loop entity around world */ | ||||||
| @ -876,10 +883,10 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 					spec.dP           = v2_scale(colliderA->dP, -4.0f); | 					spec.dP           = v2_scale(colliderA->dP, -4.0f); | ||||||
| 					addAsteroidWithSpec(world, asteroidsize_medium, &spec); | 					addAsteroidWithSpec(world, asteroidsize_medium, &spec); | ||||||
| 
 | 
 | ||||||
| 					spec.dP        = v2_perpendicular(spec.dP); | 					spec.dP = v2_perpendicular(spec.dP); | ||||||
| 					addAsteroidWithSpec(world, asteroidsize_small, &spec); | 					addAsteroidWithSpec(world, asteroidsize_small, &spec); | ||||||
| 
 | 
 | ||||||
| 					spec.dP        = v2_perpendicular(colliderA->dP); | 					spec.dP = v2_perpendicular(colliderA->dP); | ||||||
| 					addAsteroidWithSpec(world, asteroidsize_small, &spec); | 					addAsteroidWithSpec(world, asteroidsize_small, &spec); | ||||||
| 
 | 
 | ||||||
| 					numParticles = 16; | 					numParticles = 16; | ||||||
| @ -892,8 +899,8 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 						    &world->entityList[world->entityIndex++]; | 						    &world->entityList[world->entityIndex++]; | ||||||
| 						particle->id = world->entityIdCounter++; | 						particle->id = world->entityIdCounter++; | ||||||
| 
 | 
 | ||||||
| 						particle->pos        = colliderA->pos; | 						particle->pos  = colliderA->pos; | ||||||
| 						particle->size       = V2(4.0f, 4.0f); | 						particle->size = V2(4.0f, 4.0f); | ||||||
| 
 | 
 | ||||||
| 						i32 randValue = rand(); | 						i32 randValue = rand(); | ||||||
| 						Radians rotation = | 						Radians rotation = | ||||||
| @ -977,11 +984,9 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 
 | 
 | ||||||
| 		RenderFlags flags = renderflag_wireframe | renderflag_no_texture; | 		RenderFlags flags = renderflag_wireframe | renderflag_no_texture; | ||||||
| 		renderer_entity(&state->renderer, &state->transientArena, world->camera, | 		renderer_entity(&state->renderer, &state->transientArena, world->camera, | ||||||
| 		                entity, V2(0, 0), 0, | 		                entity, V2(0, 0), 0, collideColor, flags); | ||||||
| 		                collideColor, flags); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	for (i32 i = 0; i < world->numAudioRenderers; i++) | 	for (i32 i = 0; i < world->numAudioRenderers; i++) | ||||||
| 	{ | 	{ | ||||||
| 		AudioRenderer *audioRenderer = &world->audioRenderer[i]; | 		AudioRenderer *audioRenderer = &world->audioRenderer[i]; | ||||||
| @ -1000,6 +1005,45 @@ INTERNAL void startMenuUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 	StartMenuState *menuState = | 	StartMenuState *menuState = | ||||||
| 	    GET_STATE_DATA(state, &state->persistentArena, StartMenuState); | 	    GET_STATE_DATA(state, &state->persistentArena, StartMenuState); | ||||||
| 
 | 
 | ||||||
|  | 	if (!menuState->init) | ||||||
|  | 	{ | ||||||
|  | 		MemoryArena_ *persistentArena   = &state->persistentArena; | ||||||
|  | 		OptimalArrayV2 *resolutionArray = inputBuffer->resolutionList; | ||||||
|  | 		v2 currRes                      = renderer->size; | ||||||
|  | 		i32 resIndex                    = -1; | ||||||
|  | 
 | ||||||
|  | 		menuState->resStrings = memory_pushBytes( | ||||||
|  | 		    persistentArena, resolutionArray->index * sizeof(String *)); | ||||||
|  | 
 | ||||||
|  | 		for (i32 i = 0; i < resolutionArray->index; i++) | ||||||
|  | 		{ | ||||||
|  | 			v2 res = resolutionArray->ptr[i]; | ||||||
|  | 			if (v2_equals(res, currRes)) resIndex = i; | ||||||
|  | 
 | ||||||
|  | 			char widthString[8]  = {0}; | ||||||
|  | 			char heightString[8] = {0}; | ||||||
|  | 			common_itoa((i32)res.w, widthString, ARRAY_COUNT(widthString)); | ||||||
|  | 			common_itoa((i32)res.h, heightString, ARRAY_COUNT(heightString)); | ||||||
|  | 
 | ||||||
|  | 			String *resString = common_stringMake(transientArena, widthString); | ||||||
|  | 			resString = common_stringAppend(transientArena, resString, "x", 1); | ||||||
|  | 			resString = | ||||||
|  | 			    common_stringAppend(transientArena, resString, heightString, | ||||||
|  | 			                        ARRAY_COUNT(heightString)); | ||||||
|  | 
 | ||||||
|  | 			menuState->resStrings[i] = MEMORY_PUSH_ARRAY( | ||||||
|  | 			    persistentArena, common_stringLen(resString), char); | ||||||
|  | 			common_strncpy(menuState->resStrings[i], resString, | ||||||
|  | 			               common_stringLen(resString)); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (resIndex == -1) ASSERT(INVALID_CODE_PATH); | ||||||
|  | 
 | ||||||
|  | 		menuState->init                  = TRUE; | ||||||
|  | 		menuState->numResStrings         = resolutionArray->index; | ||||||
|  | 		menuState->resStringDisplayIndex = resIndex; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	Font *arial15 = asset_fontGetOrCreateOnDemand( | 	Font *arial15 = asset_fontGetOrCreateOnDemand( | ||||||
| 	    assetManager, &state->persistentArena, transientArena, "Arial", 15); | 	    assetManager, &state->persistentArena, transientArena, "Arial", 15); | ||||||
| 	Font *arial25 = asset_fontGetOrCreateOnDemand( | 	Font *arial25 = asset_fontGetOrCreateOnDemand( | ||||||
| @ -1008,7 +1052,6 @@ INTERNAL void startMenuUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 	v2 screenCenter = v2_scale(renderer->size, 0.5f); | 	v2 screenCenter = v2_scale(renderer->size, 0.5f); | ||||||
| 
 | 
 | ||||||
| 	ui_beginState(uiState); | 	ui_beginState(uiState); | ||||||
| 
 |  | ||||||
| 	if (menuState->optionsShow) | 	if (menuState->optionsShow) | ||||||
| 	{ | 	{ | ||||||
| 		if (platform_queryKey(&inputBuffer->keys[keycode_o], | 		if (platform_queryKey(&inputBuffer->keys[keycode_o], | ||||||
| @ -1020,39 +1063,78 @@ INTERNAL void startMenuUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			f32 textYOffset = arial25->size * 1.5f;; |  | ||||||
| 			const char *const title = "Options"; |  | ||||||
| 			v2 p               = v2_add(screenCenter, V2(0, textYOffset)); |  | ||||||
| 			renderer_stringFixedCentered(renderer, transientArena, arial25, |  | ||||||
| 			                             title, p, V2(0, 0), 0, V4(1, 0, 1, 1), |  | ||||||
| 			                             0); |  | ||||||
| 
 |  | ||||||
| 			const char *const resolutionLabel = "Resolution"; |  | ||||||
| 			p = v2_add(screenCenter, V2(0, 0)); |  | ||||||
| 
 |  | ||||||
| 			renderer_stringFixedCentered(renderer, transientArena, arial25, |  | ||||||
| 			                             resolutionLabel, p, V2(0, 0), 0, |  | ||||||
| 			                             V4(1, 0, 1, 1), 0); |  | ||||||
| 
 |  | ||||||
| 			const char *const resSizeLabel = "< 800x600 >"; |  | ||||||
| 			p = v2_add(screenCenter, V2(0, -textYOffset)); |  | ||||||
| 
 |  | ||||||
| 			renderer_stringFixedCentered(renderer, transientArena, arial25, |  | ||||||
| 			                             resSizeLabel, p, V2(0, 0), 0, |  | ||||||
| 			                             V4(1, 0, 1, 1), 0); |  | ||||||
| 
 |  | ||||||
| 			if (platform_queryKey(&inputBuffer->keys[keycode_enter], | 			if (platform_queryKey(&inputBuffer->keys[keycode_enter], | ||||||
| 			                      readkeytype_one_shot, KEY_DELAY_NONE)) | 			                      readkeytype_one_shot, KEY_DELAY_NONE)) | ||||||
| 			{ | 			{ | ||||||
| 				menuState->newResolutionRequest = TRUE; | 				OptimalArrayV2 *resolutionArray = inputBuffer->resolutionList; | ||||||
| 				menuState->newResolution        = V2(800, 600); |  | ||||||
| 
 | 
 | ||||||
| 				renderer->size        = menuState->newResolution; | 				menuState->newResolutionRequest = TRUE; | ||||||
|  | 				v2 newSize = | ||||||
|  | 				    resolutionArray->ptr[menuState->resStringDisplayIndex]; | ||||||
| 
 | 
 | ||||||
| 				GameWorldState *world = GET_STATE_DATA( | 				GameWorldState *world = GET_STATE_DATA( | ||||||
| 				    state, &state->persistentArena, GameWorldState); | 				    state, &state->persistentArena, GameWorldState); | ||||||
| 				world->size       = menuState->newResolution; | 
 | ||||||
| 				world->camera.max = menuState->newResolution; | 				renderer_updateSize(renderer, &state->assetManager, newSize); | ||||||
|  | 
 | ||||||
|  | 				// TODO(doyle): reset world arena instead of zeroing out struct
 | ||||||
|  | 				common_memset((u8 *)world, 0, sizeof(GameWorldState)); | ||||||
|  | 				debug_init(newSize, *arial15); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				if (platform_queryKey(&inputBuffer->keys[keycode_left], | ||||||
|  | 				                      readkeytype_one_shot, KEY_DELAY_NONE)) | ||||||
|  | 				{ | ||||||
|  | 					menuState->resStringDisplayIndex--; | ||||||
|  | 				} | ||||||
|  | 				else if (platform_queryKey(&inputBuffer->keys[keycode_right], | ||||||
|  | 				                           readkeytype_one_shot, | ||||||
|  | 				                           KEY_DELAY_NONE)) | ||||||
|  | 				{ | ||||||
|  | 					menuState->resStringDisplayIndex++; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (menuState->resStringDisplayIndex < 0) | ||||||
|  | 				{ | ||||||
|  | 					menuState->resStringDisplayIndex = 0; | ||||||
|  | 				} | ||||||
|  | 				else if (menuState->resStringDisplayIndex >= | ||||||
|  | 				         menuState->numResStrings) | ||||||
|  | 				{ | ||||||
|  | 					menuState->resStringDisplayIndex = | ||||||
|  | 					    menuState->numResStrings - 1; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			f32 textYOffset = arial25->size * 1.5f; | ||||||
|  | 			{ // Options Title String Display
 | ||||||
|  | 				const char *const title = "Options"; | ||||||
|  | 
 | ||||||
|  | 				v2 p = v2_add(screenCenter, V2(0, textYOffset)); | ||||||
|  | 				renderer_stringFixedCentered(renderer, transientArena, arial25, | ||||||
|  | 				                             title, p, V2(0, 0), 0, | ||||||
|  | 				                             V4(1, 0, 1, 1), 0); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			{ // Resolution String Display
 | ||||||
|  | 
 | ||||||
|  | 				/* Draw label */ | ||||||
|  | 				const char *const resolutionLabel = "Resolution"; | ||||||
|  | 
 | ||||||
|  | 				v2 p = v2_add(screenCenter, V2(0, 0)); | ||||||
|  | 				renderer_stringFixedCentered(renderer, transientArena, arial25, | ||||||
|  | 				                             resolutionLabel, p, V2(0, 0), 0, | ||||||
|  | 				                             V4(1, 0, 1, 1), 0); | ||||||
|  | 
 | ||||||
|  | 				/* Draw label value */ | ||||||
|  | 				char *resStringToDisplay = | ||||||
|  | 				    menuState->resStrings[menuState->resStringDisplayIndex]; | ||||||
|  | 
 | ||||||
|  | 				p = v2_add(screenCenter, V2(0, -textYOffset)); | ||||||
|  | 				renderer_stringFixedCentered(renderer, transientArena, arial25, | ||||||
|  | 				                             resStringToDisplay, p, V2(0, 0), 0, | ||||||
|  | 				                             V4(1, 0, 1, 1), 0); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @ -1084,10 +1166,10 @@ INTERNAL void startMenuUpdate(GameState *state, Memory *memory, f32 dt) | |||||||
| 
 | 
 | ||||||
| 		{ // Draw show options prompt
 | 		{ // Draw show options prompt
 | ||||||
| 			const char *const optionPrompt = "Press [o] for options "; | 			const char *const optionPrompt = "Press [o] for options "; | ||||||
| 			v2 p       = v2_add(screenCenter, V2(0, -120)); | 			v2 p                           = v2_add(screenCenter, V2(0, -120)); | ||||||
| 			renderer_stringFixedCentered(renderer, transientArena, arial25, | 			renderer_stringFixedCentered(renderer, transientArena, arial25, | ||||||
| 			                     optionPrompt, p, V2(0, 0), 0, V4(1, 1, 0, 1), | 			                             optionPrompt, p, V2(0, 0), 0, | ||||||
| 			                     0); | 			                             V4(1, 1, 0, 1), 0); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (platform_queryKey(&inputBuffer->keys[keycode_enter], | 		if (platform_queryKey(&inputBuffer->keys[keycode_enter], | ||||||
| @ -1139,7 +1221,7 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | |||||||
| 		              &state->persistentArena, windowSize); | 		              &state->persistentArena, windowSize); | ||||||
| 
 | 
 | ||||||
| 		Font *arial15 = asset_fontGet(&state->assetManager, "Arial", 15); | 		Font *arial15 = asset_fontGet(&state->assetManager, "Arial", 15); | ||||||
| 		debug_init(&state->persistentArena, windowSize, *arial15); | 		debug_init(windowSize, *arial15); | ||||||
| 
 | 
 | ||||||
| 		state->currState = appstate_StartMenuState; | 		state->currState = appstate_StartMenuState; | ||||||
| 		state->init      = TRUE; | 		state->init      = TRUE; | ||||||
|  | |||||||
							
								
								
									
										203
									
								
								src/Common.c
									
									
									
									
									
								
							
							
						
						
									
										203
									
								
								src/Common.c
									
									
									
									
									
								
							| @ -1,10 +1,173 @@ | |||||||
|  | #include <stdlib.h> | ||||||
|  | 
 | ||||||
| #include "Dengine/Common.h" | #include "Dengine/Common.h" | ||||||
| #include "Dengine/Math.h" | #include "Dengine/MemoryArena.h" | ||||||
|  | 
 | ||||||
|  | void common_optimalArrayV2Create(OptimalArrayV2 *array) | ||||||
|  | { | ||||||
|  | 	array->ptr  = array->fastStorage; | ||||||
|  | 	array->size = ARRAY_COUNT(array->fastStorage); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | i32 common_optimalArrayV2Push(OptimalArrayV2 *array, v2 data) | ||||||
|  | { | ||||||
|  | 	if (array->index + 1 > array->size) | ||||||
|  | 	{ | ||||||
|  | 		array->size += ARRAY_COUNT(array->fastStorage); | ||||||
|  | 		i32 newSizeInBytes = array->size * sizeof(v2); | ||||||
|  | 
 | ||||||
|  | 		/* If first time expanding, we need to manually malloc and copy */ | ||||||
|  | 		if (array->ptr == array->fastStorage) | ||||||
|  | 		{ | ||||||
|  | 			array->ptr = malloc(newSizeInBytes); | ||||||
|  | 			for (i32 i = 0; i < ARRAY_COUNT(array->fastStorage); i++) | ||||||
|  | 			{ | ||||||
|  | 				array->ptr[i] = array->fastStorage[i]; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			array->ptr = realloc(array->ptr, newSizeInBytes); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (!array->ptr) return optimalarrayerror_out_of_memory; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	array->ptr[array->index++] = data; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void common_optimalArrayV2Destroy(OptimalArrayV2 *array) | ||||||
|  | { | ||||||
|  | 	if (array->ptr != array->fastStorage) | ||||||
|  | 	{ | ||||||
|  | 		free(array->ptr); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * +-------------------------------------+ | ||||||
|  |  * | Header | C-String | Null Terminator | | ||||||
|  |  * +-------------------------------------+ | ||||||
|  |  *          | | ||||||
|  |  *          +--> Functions return the c-string for compatibility with other | ||||||
|  |  *               string libraries | ||||||
|  |  * | ||||||
|  |  * Headers are retrieved using pointer arithmetric from the C string. These | ||||||
|  |  * strings are typechecked by their own typedef char String. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | typedef struct StringHeader | ||||||
|  | { | ||||||
|  | 	i32 len; | ||||||
|  | 
 | ||||||
|  | 	// NOTE(doyle): A string is stored as one contiguous chunk of memory. We
 | ||||||
|  | 	// don't use a pointer for storing the string as this'd require an extra
 | ||||||
|  | 	// 4 bytes to store the pointer, which we don't need if everything is
 | ||||||
|  | 	// contiguous. The string follows on from the len, and we return the address
 | ||||||
|  | 	// of the string to simulate a pointer.
 | ||||||
|  | 	String string; | ||||||
|  | } StringHeader; | ||||||
|  | 
 | ||||||
|  | // TODO(doyle): string capacity- append if already enough space
 | ||||||
|  | INTERNAL StringHeader *stringGetHeader(String *const string) | ||||||
|  | { | ||||||
|  | 	StringHeader *result = NULL; | ||||||
|  | 
 | ||||||
|  | 	// NOTE(doyle): C-String must be located at end of struct type for offset to
 | ||||||
|  | 	// be correct! We cannot just subtract the string-header since we start at
 | ||||||
|  | 	// the string ptr position
 | ||||||
|  | 	if (string) | ||||||
|  | 	{ | ||||||
|  | 		i32 byteOffsetToHeader = sizeof(StringHeader) - sizeof(String *); | ||||||
|  | 		result = CAST(StringHeader *)((CAST(u8 *) string) - byteOffsetToHeader); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | i32 common_stringLen(String *const string) | ||||||
|  | { | ||||||
|  | 	if (!string) return -1; | ||||||
|  | 
 | ||||||
|  | 	StringHeader *header = stringGetHeader(string); | ||||||
|  | 	i32 result           = header->len; | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | String *const common_stringAppend(MemoryArena_ *const arena, String *oldString, | ||||||
|  |                                   char *appendString, i32 appendLen) | ||||||
|  | 
 | ||||||
|  | { | ||||||
|  | 	if (!oldString || !appendString || !arena) return oldString; | ||||||
|  | 
 | ||||||
|  | 	/* Calculate size of new string */ | ||||||
|  | 	StringHeader *oldHeader = stringGetHeader(oldString); | ||||||
|  | 	i32 newLen              = oldHeader->len + appendLen; | ||||||
|  | 	String *newString       = common_stringMakeLen(arena, newLen); | ||||||
|  | 
 | ||||||
|  | 	/* Append strings together */ | ||||||
|  | 	String *insertPtr = newString; | ||||||
|  | 	common_strncpy(insertPtr, oldString, oldHeader->len); | ||||||
|  | 	insertPtr += oldHeader->len; | ||||||
|  | 	common_strncpy(insertPtr, appendString, appendLen); | ||||||
|  | 
 | ||||||
|  | 	/* Free old string */ | ||||||
|  | 	common_stringFree(arena, oldString); | ||||||
|  | 
 | ||||||
|  | 	return newString; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void common_stringFree(MemoryArena_ *arena, String *string) | ||||||
|  | { | ||||||
|  | 	if (!string || !arena) return; | ||||||
|  | 
 | ||||||
|  | 	StringHeader *header = stringGetHeader(string); | ||||||
|  | 	i32 bytesToFree      = sizeof(StringHeader) + header->len; | ||||||
|  | 
 | ||||||
|  | 	common_memset((u8 *)header, 0, bytesToFree); | ||||||
|  | 
 | ||||||
|  | 	// TODO(doyle): Mem free
 | ||||||
|  | 	// PLATFORM_MEM_FREE(arena, header, bytesToFree);
 | ||||||
|  | 
 | ||||||
|  | 	string = NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | String *const common_stringMake(MemoryArena_ *const arena, char *string) | ||||||
|  | { | ||||||
|  | 	if (!arena) return NULL; | ||||||
|  | 
 | ||||||
|  | 	i32 len        = common_strlen(string); | ||||||
|  | 	String *result = common_stringMakeLen(arena, len); | ||||||
|  | 	common_strncpy(result, string, len); | ||||||
|  | 
 | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | String *const common_stringMakeLen(MemoryArena_ *const arena, i32 len) | ||||||
|  | { | ||||||
|  | 	if (!arena) return NULL; | ||||||
|  | 
 | ||||||
|  | 	// NOTE(doyle): Allocate the string header size plus the len. But _note_
 | ||||||
|  | 	// that StringHeader contains a single String character. This has
 | ||||||
|  | 	// a side-effect of already preallocating a byte for the null-terminating
 | ||||||
|  | 	// character. Whilst the len of a string counts up to the last character
 | ||||||
|  | 	// _not_ including null-terminator.
 | ||||||
|  | 	i32 bytesToAllocate = sizeof(StringHeader) + len; | ||||||
|  | 	void *chunk         = memory_pushBytes(arena, bytesToAllocate * sizeof(u8)); | ||||||
|  | 	if (!chunk) return NULL; | ||||||
|  | 
 | ||||||
|  | 	StringHeader *header = CAST(StringHeader *) chunk; | ||||||
|  | 	header->len          = len; | ||||||
|  | 	return &header->string; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| i32 common_strlen(const char *const string) | i32 common_strlen(const char *const string) | ||||||
| { | { | ||||||
| 	i32 result = 0; | 	i32 result = 0; | ||||||
| 	while (string[result]) result++; | 	while (string[result]) | ||||||
|  | 		result++; | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -12,8 +175,7 @@ i32 common_strcmp(const char *a, const char *b) | |||||||
| { | { | ||||||
| 	while (*a == *b) | 	while (*a == *b) | ||||||
| 	{ | 	{ | ||||||
| 		if (!*a) | 		if (!*a) return 0; | ||||||
| 			return 0; |  | ||||||
| 		a++; | 		a++; | ||||||
| 		b++; | 		b++; | ||||||
| 	} | 	} | ||||||
| @ -27,13 +189,13 @@ void common_strncat(char *dest, const char *src, i32 numChars) | |||||||
| 	while (*stringPtr) | 	while (*stringPtr) | ||||||
| 		stringPtr++; | 		stringPtr++; | ||||||
| 
 | 
 | ||||||
| 	for (i32 i = 0; i < numChars; i++) | 	for (i32 i         = 0; i < numChars; i++) | ||||||
| 		*(stringPtr++) = src[i]; | 		*(stringPtr++) = src[i]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| char *common_strncpy(char *dest, const char *src, i32 numChars) | char *common_strncpy(char *dest, const char *src, i32 numChars) | ||||||
| { | { | ||||||
| 	for (i32 i = 0; i < numChars; i++) | 	for (i32 i  = 0; i < numChars; i++) | ||||||
| 		dest[i] = src[i]; | 		dest[i] = src[i]; | ||||||
| 
 | 
 | ||||||
| 	return dest; | 	return dest; | ||||||
| @ -54,9 +216,9 @@ INTERNAL void reverseString(char *const buf, const i32 bufSize) | |||||||
| 
 | 
 | ||||||
| 	for (i32 i = 0; i < mid; i++) | 	for (i32 i = 0; i < mid; i++) | ||||||
| 	{ | 	{ | ||||||
| 		char tmp         = buf[i]; | 		char tmp               = buf[i]; | ||||||
| 		buf[i]           = buf[(bufSize-1) - i]; | 		buf[i]                 = buf[(bufSize - 1) - i]; | ||||||
| 		buf[(bufSize-1) - i] = tmp; | 		buf[(bufSize - 1) - i] = tmp; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -65,9 +227,9 @@ void common_itoa(i32 value, char *buf, i32 bufSize) | |||||||
| 	if (!buf || bufSize == 0) return; | 	if (!buf || bufSize == 0) return; | ||||||
| 
 | 
 | ||||||
| 	// NOTE(doyle): Max 32bit integer (+-)2147483647
 | 	// NOTE(doyle): Max 32bit integer (+-)2147483647
 | ||||||
| 	i32 charIndex   = 0; | 	i32 charIndex = 0; | ||||||
| 
 | 
 | ||||||
| 	b32 negative = FALSE; | 	b32 negative            = FALSE; | ||||||
| 	if (value < 0) negative = TRUE; | 	if (value < 0) negative = TRUE; | ||||||
| 
 | 
 | ||||||
| 	if (negative) buf[charIndex++] = '-'; | 	if (negative) buf[charIndex++] = '-'; | ||||||
| @ -75,7 +237,7 @@ void common_itoa(i32 value, char *buf, i32 bufSize) | |||||||
| 	i32 val = ABS(value); | 	i32 val = ABS(value); | ||||||
| 	while (val != 0 && charIndex < bufSize) | 	while (val != 0 && charIndex < bufSize) | ||||||
| 	{ | 	{ | ||||||
| 		i32 rem = val % 10; | 		i32 rem          = val % 10; | ||||||
| 		buf[charIndex++] = rem + '0'; | 		buf[charIndex++] = rem + '0'; | ||||||
| 		val /= 10; | 		val /= 10; | ||||||
| 	} | 	} | ||||||
| @ -137,9 +299,9 @@ u32 common_murmurHash2(const void *key, i32 len, u32 seed) | |||||||
| 
 | 
 | ||||||
| 	// Mix 4 bytes at a time into the hash
 | 	// Mix 4 bytes at a time into the hash
 | ||||||
| 
 | 
 | ||||||
| 	const unsigned char * data = (const unsigned char *)key; | 	const unsigned char *data = (const unsigned char *)key; | ||||||
| 
 | 
 | ||||||
| 	while(len >= 4) | 	while (len >= 4) | ||||||
| 	{ | 	{ | ||||||
| 		u32 k = *(u32 *)data; | 		u32 k = *(u32 *)data; | ||||||
| 
 | 
 | ||||||
| @ -156,12 +318,15 @@ u32 common_murmurHash2(const void *key, i32 len, u32 seed) | |||||||
| 
 | 
 | ||||||
| 	// Handle the last few bytes of the input array
 | 	// Handle the last few bytes of the input array
 | ||||||
| 
 | 
 | ||||||
| 	switch(len) | 	switch (len) | ||||||
| 	{ | 	{ | ||||||
| 	case 3: h ^= data[2] << 16; | 	case 3: | ||||||
| 	case 2: h ^= data[1] << 8; | 		h ^= data[2] << 16; | ||||||
| 	case 1: h ^= data[0]; | 	case 2: | ||||||
| 	        h *= m; | 		h ^= data[1] << 8; | ||||||
|  | 	case 1: | ||||||
|  | 		h ^= data[0]; | ||||||
|  | 		h *= m; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	// Do a few final mixes of the hash to ensure the last few
 | 	// Do a few final mixes of the hash to ensure the last few
 | ||||||
|  | |||||||
							
								
								
									
										22
									
								
								src/Debug.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								src/Debug.c
									
									
									
									
									
								
							| @ -9,7 +9,7 @@ typedef struct DebugState | |||||||
| { | { | ||||||
| 	b32 init; | 	b32 init; | ||||||
| 	Font font; | 	Font font; | ||||||
| 	i32 *callCount; | 	i32 callCount[debugcount_num]; | ||||||
| 	f32 stringLineGap; | 	f32 stringLineGap; | ||||||
| 
 | 
 | ||||||
| 	/* Debug strings rendered in top left corner */ | 	/* Debug strings rendered in top left corner */ | ||||||
| @ -28,11 +28,12 @@ typedef struct DebugState | |||||||
| 
 | 
 | ||||||
| GLOBAL_VAR DebugState GLOBAL_debug; | GLOBAL_VAR DebugState GLOBAL_debug; | ||||||
| 
 | 
 | ||||||
| void debug_init(MemoryArena_ *arena, v2 windowSize, Font font) | void debug_init(v2 windowSize, Font font) | ||||||
| { | { | ||||||
| 	GLOBAL_debug.font = font; | 	GLOBAL_debug.font          = font; | ||||||
| 	GLOBAL_debug.callCount = | 
 | ||||||
| 	    memory_pushBytes(arena, debugcount_num * sizeof(i32)); | 	for (i32 i = 0; i < debugcount_num; i++) GLOBAL_debug.callCount[i] = 0; | ||||||
|  | 
 | ||||||
| 	GLOBAL_debug.stringLineGap = CAST(f32) font.verticalSpacing; | 	GLOBAL_debug.stringLineGap = CAST(f32) font.verticalSpacing; | ||||||
| 
 | 
 | ||||||
| 	/* Init debug string stack */ | 	/* Init debug string stack */ | ||||||
| @ -40,18 +41,17 @@ void debug_init(MemoryArena_ *arena, v2 windowSize, Font font) | |||||||
| 	GLOBAL_debug.stringUpdateTimer = 0.0f; | 	GLOBAL_debug.stringUpdateTimer = 0.0f; | ||||||
| 	GLOBAL_debug.stringUpdateRate  = 0.15f; | 	GLOBAL_debug.stringUpdateRate  = 0.15f; | ||||||
| 
 | 
 | ||||||
| 	GLOBAL_debug.initialStringP = | 	GLOBAL_debug.initialStringP = V2(0.0f, (windowSize.h - 1.8f * GLOBAL_debug.stringLineGap)); | ||||||
| 	    V2(0.0f, (windowSize.h - 1.8f * GLOBAL_debug.stringLineGap)); | 	GLOBAL_debug.currStringP    = GLOBAL_debug.initialStringP; | ||||||
| 	GLOBAL_debug.currStringP = GLOBAL_debug.initialStringP; |  | ||||||
| 
 | 
 | ||||||
| 	/* Init gui console */ | 	/* Init gui console */ | ||||||
| 	i32 maxConsoleStrLen = ARRAY_COUNT(GLOBAL_debug.console[0]); | 	i32 maxConsoleStrLen      = ARRAY_COUNT(GLOBAL_debug.console[0]); | ||||||
| 	GLOBAL_debug.consoleIndex = 0; | 	GLOBAL_debug.consoleIndex = 0; | ||||||
| 
 | 
 | ||||||
| 	// TODO(doyle): Font max size not entirely correct? using 1 * font.maxSize.w
 | 	// TODO(doyle): Font max size not entirely correct? using 1 * font.maxSize.w
 | ||||||
| 	// reveals around 4 characters ..
 | 	// reveals around 4 characters ..
 | ||||||
| 	f32 consoleXPos = font.maxSize.w * 20; | 	f32 consoleXPos              = font.maxSize.w * 20; | ||||||
| 	f32 consoleYPos = windowSize.h - 1.8f * GLOBAL_debug.stringLineGap; | 	f32 consoleYPos              = windowSize.h - 1.8f * GLOBAL_debug.stringLineGap; | ||||||
| 	GLOBAL_debug.initialConsoleP = V2(consoleXPos, consoleYPos); | 	GLOBAL_debug.initialConsoleP = V2(consoleXPos, consoleYPos); | ||||||
| 
 | 
 | ||||||
| 	GLOBAL_debug.init = TRUE; | 	GLOBAL_debug.init = TRUE; | ||||||
|  | |||||||
| @ -32,8 +32,7 @@ void shaderUniformSetVec4f(u32 shaderId, const GLchar *name, | |||||||
| 
 | 
 | ||||||
| void shaderUse(u32 shaderId) { glUseProgram(shaderId); } | void shaderUse(u32 shaderId) { glUseProgram(shaderId); } | ||||||
| 
 | 
 | ||||||
| void renderer_init(Renderer *renderer, AssetManager *assetManager, | void renderer_updateSize(Renderer *renderer, AssetManager *assetManager, v2 windowSize) | ||||||
|                    MemoryArena_ *persistentArena, v2 windowSize) |  | ||||||
| { | { | ||||||
| 	renderer->size = windowSize; | 	renderer->size = windowSize; | ||||||
| 	// NOTE(doyle): Value to map a screen coordinate to NDC coordinate
 | 	// NOTE(doyle): Value to map a screen coordinate to NDC coordinate
 | ||||||
| @ -43,6 +42,7 @@ void renderer_init(Renderer *renderer, AssetManager *assetManager, | |||||||
| 
 | 
 | ||||||
| 	const mat4 projection = | 	const mat4 projection = | ||||||
| 	    mat4_ortho(0.0f, renderer->size.w, 0.0f, renderer->size.h, 0.0f, 1.0f); | 	    mat4_ortho(0.0f, renderer->size.w, 0.0f, renderer->size.h, 0.0f, 1.0f); | ||||||
|  | 
 | ||||||
| 	for (i32 i = 0; i < shaderlist_count; i++) | 	for (i32 i = 0; i < shaderlist_count; i++) | ||||||
| 	{ | 	{ | ||||||
| 		renderer->shaderList[i] = asset_shaderGet(assetManager, i); | 		renderer->shaderList[i] = asset_shaderGet(assetManager, i); | ||||||
| @ -54,6 +54,12 @@ void renderer_init(Renderer *renderer, AssetManager *assetManager, | |||||||
| 
 | 
 | ||||||
| 	renderer->activeShaderId = renderer->shaderList[shaderlist_default]; | 	renderer->activeShaderId = renderer->shaderList[shaderlist_default]; | ||||||
| 	GL_CHECK_ERROR(); | 	GL_CHECK_ERROR(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void renderer_init(Renderer *renderer, AssetManager *assetManager, | ||||||
|  |                    MemoryArena_ *persistentArena, v2 windowSize) | ||||||
|  | { | ||||||
|  | 	renderer_updateSize(renderer, assetManager, windowSize); | ||||||
| 
 | 
 | ||||||
| 	/* Create buffers */ | 	/* Create buffers */ | ||||||
| 	glGenVertexArrays(ARRAY_COUNT(renderer->vao), renderer->vao); | 	glGenVertexArrays(ARRAY_COUNT(renderer->vao), renderer->vao); | ||||||
|  | |||||||
							
								
								
									
										117
									
								
								src/String.c
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								src/String.c
									
									
									
									
									
								
							| @ -1,120 +1,3 @@ | |||||||
| #include "Dengine/String.h" | #include "Dengine/String.h" | ||||||
| #include "Dengine/MemoryArena.h" | #include "Dengine/MemoryArena.h" | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * +-------------------------------------+ |  | ||||||
|  * | Header | C-String | Null Terminator | |  | ||||||
|  * +-------------------------------------+ |  | ||||||
|  *          | |  | ||||||
|  *          +--> Functions return the c-string for compatibility with other |  | ||||||
|  *               string libraries |  | ||||||
|  * |  | ||||||
|  * Headers are retrieved using pointer arithmetric from the C string. These |  | ||||||
|  * strings are typechecked by their own typedef char String. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| typedef struct StringHeader |  | ||||||
| { |  | ||||||
| 	i32 len; |  | ||||||
| 
 |  | ||||||
| 	// NOTE(doyle): A string is stored as one contiguous chunk of memory. We
 |  | ||||||
| 	// don't use a pointer for storing the string as this'd require an extra
 |  | ||||||
| 	// 4 bytes to store the pointer, which we don't need if everything is
 |  | ||||||
| 	// contiguous. The string follows on from the len, and we return the address
 |  | ||||||
| 	// of the string to simulate a pointer.
 |  | ||||||
| 	String string; |  | ||||||
| } StringHeader; |  | ||||||
| 
 |  | ||||||
| // TODO(doyle): string capacity- append if already enough space
 |  | ||||||
| INTERNAL StringHeader *string_getHeader(String *const string) |  | ||||||
| { |  | ||||||
| 	StringHeader *result = NULL; |  | ||||||
| 
 |  | ||||||
| 	// NOTE(doyle): C-String must be located at end of struct type for offset to
 |  | ||||||
| 	// be correct! We cannot just subtract the string-header since we start at
 |  | ||||||
| 	// the string ptr position
 |  | ||||||
| 	if (string) |  | ||||||
| 	{ |  | ||||||
| 		i32 byteOffsetToHeader = sizeof(StringHeader) - sizeof(String *); |  | ||||||
| 		result = CAST(StringHeader *)((CAST(u8 *) string) - byteOffsetToHeader); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| i32 string_len(String *const string) |  | ||||||
| { |  | ||||||
| 	if (!string) return -1; |  | ||||||
| 
 |  | ||||||
| 	StringHeader *header = string_getHeader(string); |  | ||||||
| 	i32 result           = header->len; |  | ||||||
| 	return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| String *const string_append(MemoryArena_ *const arena, String *oldString, |  | ||||||
|                             char *appendString, i32 appendLen) |  | ||||||
| 
 |  | ||||||
| { |  | ||||||
| 	if (!oldString || !appendString || !arena) return oldString; |  | ||||||
| 
 |  | ||||||
| 	/* Calculate size of new string */ |  | ||||||
| 	StringHeader *oldHeader = string_getHeader(oldString); |  | ||||||
| 	i32 newLen              = oldHeader->len + appendLen; |  | ||||||
| 	String *newString       = string_makeLen(arena, newLen); |  | ||||||
| 
 |  | ||||||
| 	/* Append strings together */ |  | ||||||
| 	String *insertPtr = newString; |  | ||||||
| 	common_strncpy(insertPtr, oldString, oldHeader->len); |  | ||||||
| 	insertPtr += oldHeader->len; |  | ||||||
| 	common_strncpy(insertPtr, appendString, appendLen); |  | ||||||
| 
 |  | ||||||
| 	/* Free old string */ |  | ||||||
| 	string_free(arena, oldString); |  | ||||||
| 
 |  | ||||||
| 	return newString; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void string_free(MemoryArena_ *arena, String *string) |  | ||||||
| { |  | ||||||
| 	if (!string || !arena) return; |  | ||||||
| 
 |  | ||||||
| 	StringHeader *header = string_getHeader(string); |  | ||||||
| 	i32 bytesToFree = sizeof(StringHeader) + header->len; |  | ||||||
| 
 |  | ||||||
| 	common_memset((u8 *)header, 0, bytesToFree); |  | ||||||
| 
 |  | ||||||
| 	// TODO(doyle): Mem free
 |  | ||||||
| 	// PLATFORM_MEM_FREE(arena, header, bytesToFree);
 |  | ||||||
| 
 |  | ||||||
| 	string = NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| String *const string_make(MemoryArena_ *const arena, char *string) |  | ||||||
| { |  | ||||||
| 	if (!arena) return NULL; |  | ||||||
| 
 |  | ||||||
| 	i32 len        = common_strlen(string); |  | ||||||
| 	String *result = string_makeLen(arena, len); |  | ||||||
| 	common_strncpy(result, string, len); |  | ||||||
| 
 |  | ||||||
| 	return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| String *const string_makeLen(MemoryArena_ *const arena, i32 len) |  | ||||||
| { |  | ||||||
| 	if (!arena) return NULL; |  | ||||||
| 
 |  | ||||||
| 	// NOTE(doyle): Allocate the string header size plus the len. But _note_
 |  | ||||||
| 	// that StringHeader contains a single String character. This has
 |  | ||||||
| 	// a side-effect of already preallocating a byte for the null-terminating
 |  | ||||||
| 	// character. Whilst the len of a string counts up to the last character
 |  | ||||||
| 	// _not_ including null-terminator.
 |  | ||||||
| 	i32 bytesToAllocate = sizeof(StringHeader) + len; |  | ||||||
| 	void *chunk         = memory_pushBytes(arena, bytesToAllocate * sizeof(u8)); |  | ||||||
| 	if (!chunk) return NULL; |  | ||||||
| 
 |  | ||||||
| 	StringHeader *header   = CAST(StringHeader *) chunk; |  | ||||||
| 	header->len            = len; |  | ||||||
| 	return &header->string; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
|  | |||||||
| @ -83,7 +83,7 @@ INTERNAL void mouseButtonCallback(GLFWwindow *window, int button, int action, | |||||||
| { | { | ||||||
| 	GameState *game = CAST(GameState *)(glfwGetWindowUserPointer(window)); | 	GameState *game = CAST(GameState *)(glfwGetWindowUserPointer(window)); | ||||||
| 
 | 
 | ||||||
| 	switch(button) | 	switch (button) | ||||||
| 	{ | 	{ | ||||||
| 	case GLFW_MOUSE_BUTTON_LEFT: | 	case GLFW_MOUSE_BUTTON_LEFT: | ||||||
| 		processKey(&game->input.keys[keycode_mouseLeft], action); | 		processKey(&game->input.keys[keycode_mouseLeft], action); | ||||||
| @ -115,8 +115,73 @@ i32 main(void) | |||||||
| 	glfwInit(); | 	glfwInit(); | ||||||
| 	setGlfwWindowHints(); | 	setGlfwWindowHints(); | ||||||
| 
 | 
 | ||||||
| 	i32 windowWidth = 1600; | 	OptimalArrayV2 vidList = {0}; | ||||||
| 	i32 windowHeight = 900; | 	common_optimalArrayV2Create(&vidList); | ||||||
|  | 
 | ||||||
|  | 	i32 windowWidth  = 0; | ||||||
|  | 	i32 windowHeight = 0; | ||||||
|  | 	{ // Query Computer Video Resolutions
 | ||||||
|  | 
 | ||||||
|  | 		i32 numMonitors; | ||||||
|  | 		GLFWmonitor **monitors      = glfwGetMonitors(&numMonitors); | ||||||
|  | 		GLFWmonitor *primaryMonitor = monitors[0]; | ||||||
|  | 
 | ||||||
|  | 		i32 numModes; | ||||||
|  | 		const GLFWvidmode *modes = glfwGetVideoModes(primaryMonitor, &numModes); | ||||||
|  | 
 | ||||||
|  | 		i32 targetRefreshHz   = 60; | ||||||
|  | 		f32 targetWindowRatio = 16.0f / 9.0f; | ||||||
|  | 
 | ||||||
|  | 		i32 targetPixelDensity   = 1280 * 720; | ||||||
|  | 		i32 minPixelDensityDelta = 100000000; | ||||||
|  | 
 | ||||||
|  | 		printf("== Supported video modes ==\n"); | ||||||
|  | 		for (i32 i = 0; i < numModes; i++) | ||||||
|  | 		{ | ||||||
|  | 			GLFWvidmode mode = modes[i]; | ||||||
|  | 			printf("width: %d, height: %d, rgb: %d, %d, %d, refresh: %d\n", | ||||||
|  | 			       mode.width, mode.height, mode.redBits, mode.greenBits, | ||||||
|  | 			       mode.blueBits, mode.refreshRate); | ||||||
|  | 
 | ||||||
|  | 			if (mode.refreshRate == targetRefreshHz) | ||||||
|  | 			{ | ||||||
|  | 				i32 result = common_optimalArrayV2Push( | ||||||
|  | 				    &vidList, V2i(mode.width, mode.height)); | ||||||
|  | 
 | ||||||
|  | 				if (result) | ||||||
|  | 				{ | ||||||
|  | 					printf( | ||||||
|  | 					    "common_optimalArrayV2Push(): Failed error code %d\n", | ||||||
|  | 					    result); | ||||||
|  | 					ASSERT(INVALID_CODE_PATH); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				f32 sizeRatio = (f32)mode.width / (f32)mode.height; | ||||||
|  | 				f32 delta     = targetWindowRatio - sizeRatio; | ||||||
|  | 				if (delta < 0.1f) | ||||||
|  | 				{ | ||||||
|  | 					i32 pixelDensity = mode.width * mode.height; | ||||||
|  | 					i32 densityDelta = ABS((pixelDensity - targetPixelDensity)); | ||||||
|  | 
 | ||||||
|  | 					if (densityDelta < minPixelDensityDelta) | ||||||
|  | 					{ | ||||||
|  | 						minPixelDensityDelta = densityDelta; | ||||||
|  | 						windowWidth          = mode.width; | ||||||
|  | 						windowHeight         = mode.height; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		printf("==  ==\n"); | ||||||
|  | 		ASSERT(vidList.index > 0); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (windowWidth == 0 || windowHeight == 0) | ||||||
|  | 	{ | ||||||
|  | 		// NOTE(doyle): In this case just fallback to some value we hope is safe
 | ||||||
|  | 		windowWidth  = 800; | ||||||
|  | 		windowHeight = 600; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	GLFWwindow *window = | 	GLFWwindow *window = | ||||||
| 	    glfwCreateWindow(windowWidth, windowHeight, "Dengine", NULL, NULL); | 	    glfwCreateWindow(windowWidth, windowHeight, "Dengine", NULL, NULL); | ||||||
| @ -168,7 +233,7 @@ i32 main(void) | |||||||
| 	 * INITIALISE GAME | 	 * INITIALISE GAME | ||||||
| 	 ******************* | 	 ******************* | ||||||
| 	 */ | 	 */ | ||||||
| 	Memory memory = {0}; | 	Memory memory              = {0}; | ||||||
| 	MemoryIndex persistentSize = MEGABYTES(32); | 	MemoryIndex persistentSize = MEGABYTES(32); | ||||||
| 	MemoryIndex transientSize  = MEGABYTES(64); | 	MemoryIndex transientSize  = MEGABYTES(64); | ||||||
| 
 | 
 | ||||||
| @ -181,12 +246,12 @@ i32 main(void) | |||||||
| 	MemoryArena_ gameArena = {0}; | 	MemoryArena_ gameArena = {0}; | ||||||
| 	memory_arenaInit(&gameArena, memory.persistent, memory.persistentSize); | 	memory_arenaInit(&gameArena, memory.persistent, memory.persistentSize); | ||||||
| 
 | 
 | ||||||
| 	GameState *gameState = MEMORY_PUSH_STRUCT(&gameArena, GameState); | 	GameState *gameState       = MEMORY_PUSH_STRUCT(&gameArena, GameState); | ||||||
| 	gameState->persistentArena = gameArena; | 	gameState->persistentArena = gameArena; | ||||||
| 
 | 
 | ||||||
| 	glfwSetWindowUserPointer(window, CAST(void *)(gameState)); | 	glfwSetWindowUserPointer(window, CAST(void *)(gameState)); | ||||||
| 
 | 
 | ||||||
| 	{ | 	{ // Load game icon
 | ||||||
| 		i32 width, height; | 		i32 width, height; | ||||||
| 		char *iconPath = "data/textures/Asteroids/icon.png"; | 		char *iconPath = "data/textures/Asteroids/icon.png"; | ||||||
| 		u8 *pixels = asset_imageLoad(&width, &height, NULL, iconPath, FALSE); | 		u8 *pixels = asset_imageLoad(&width, &height, NULL, iconPath, FALSE); | ||||||
| @ -198,6 +263,7 @@ i32 main(void) | |||||||
| 			asset_imageFree(pixels); | 			asset_imageFree(pixels); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	gameState->input.resolutionList = &vidList; | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 ******************* | 	 ******************* | ||||||
| @ -209,7 +275,6 @@ i32 main(void) | |||||||
| 
 | 
 | ||||||
| #if 0 | #if 0 | ||||||
| 	// TODO(doyle): Get actual monitor refresh rate
 | 	// TODO(doyle): Get actual monitor refresh rate
 | ||||||
| 	i32 monitorRefreshHz      = 60; |  | ||||||
| 	f32 targetSecondsPerFrame = 1.0f / CAST(f32)(monitorRefreshHz); | 	f32 targetSecondsPerFrame = 1.0f / CAST(f32)(monitorRefreshHz); | ||||||
| #else | #else | ||||||
| 	// TODO(doyle): http://gafferongames.com/game-physics/fix-your-timestep/
 | 	// TODO(doyle): http://gafferongames.com/game-physics/fix-your-timestep/
 | ||||||
| @ -234,7 +299,7 @@ i32 main(void) | |||||||
| 		/* Swap the buffers */ | 		/* Swap the buffers */ | ||||||
| 		glfwSwapBuffers(window); | 		glfwSwapBuffers(window); | ||||||
| 
 | 
 | ||||||
| 		f32 endTime    = CAST(f32)glfwGetTime(); | 		f32 endTime    = CAST(f32) glfwGetTime(); | ||||||
| 		secondsElapsed = endTime - startTime; | 		secondsElapsed = endTime - startTime; | ||||||
| 
 | 
 | ||||||
| #if 0 | #if 0 | ||||||
| @ -277,8 +342,11 @@ i32 main(void) | |||||||
| 		{ | 		{ | ||||||
| 			if (menuState->newResolutionRequest) | 			if (menuState->newResolutionRequest) | ||||||
| 			{ | 			{ | ||||||
| 				windowSize = menuState->newResolution; | 				i32 index  = menuState->resStringDisplayIndex; | ||||||
|  | 				windowSize = gameState->input.resolutionList->ptr[index]; | ||||||
|  | 
 | ||||||
| 				glfwSetWindowSize(window, (i32)windowSize.w, (i32)windowSize.h); | 				glfwSetWindowSize(window, (i32)windowSize.w, (i32)windowSize.h); | ||||||
|  | 				glViewport(0, 0, (i32)windowSize.w, (i32)windowSize.h); | ||||||
| 
 | 
 | ||||||
| 				menuState->newResolutionRequest = FALSE; | 				menuState->newResolutionRequest = FALSE; | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -24,7 +24,8 @@ typedef struct GameWorldState | |||||||
| 	MemoryArena_ entityArena; | 	MemoryArena_ entityArena; | ||||||
| 
 | 
 | ||||||
| 	v2 *entityVertexListCache[entitytype_count]; | 	v2 *entityVertexListCache[entitytype_count]; | ||||||
| 	Entity entityList[1024]; | 	Entity *entityList; | ||||||
|  | 	i32 entityListSize; | ||||||
| 	i32 entityIndex; | 	i32 entityIndex; | ||||||
| 	u32 entityIdCounter; | 	u32 entityIdCounter; | ||||||
| 
 | 
 | ||||||
| @ -54,19 +55,23 @@ typedef struct GameWorldState | |||||||
| 
 | 
 | ||||||
| typedef struct StartMenuState | typedef struct StartMenuState | ||||||
| { | { | ||||||
|  | 	b32 init; | ||||||
|  | 
 | ||||||
| 	f32 startPromptBlinkTimer; | 	f32 startPromptBlinkTimer; | ||||||
| 	b32 startPromptShow; | 	b32 startPromptShow; | ||||||
| 
 | 
 | ||||||
| 	b32 optionsShow; | 	char **resStrings; | ||||||
|  | 	i32 numResStrings; | ||||||
|  | 	i32 resStringDisplayIndex; | ||||||
| 
 | 
 | ||||||
| 	b32 newResolutionRequest; | 	b32 newResolutionRequest; | ||||||
| 	v2 newResolution; | 
 | ||||||
|  | 	b32 optionsShow; | ||||||
| } StartMenuState; | } StartMenuState; | ||||||
| 
 | 
 | ||||||
| typedef struct GameState | typedef struct GameState | ||||||
| { | { | ||||||
| 	b32 init; | 	b32 init; | ||||||
| 
 |  | ||||||
| 	enum AppState currState; | 	enum AppState currState; | ||||||
| 	void *appStateData[appstate_count]; | 	void *appStateData[appstate_count]; | ||||||
| 
 | 
 | ||||||
| @ -81,8 +86,7 @@ typedef struct GameState | |||||||
| 	UiState uiState; | 	UiState uiState; | ||||||
| } GameState; | } GameState; | ||||||
| 
 | 
 | ||||||
| #define ASTEROID_GET_STATE_DATA(state, type)                                   \ | #define ASTEROID_GET_STATE_DATA(state, type) (type *)asteroid_getStateData_(state, appstate_##type) | ||||||
| 	(type *)asteroid_getStateData_(state, appstate_##type) |  | ||||||
| void *asteroid_getStateData_(GameState *state, enum AppState appState); | void *asteroid_getStateData_(GameState *state, enum AppState appState); | ||||||
| 
 | 
 | ||||||
| void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | ||||||
|  | |||||||
| @ -15,6 +15,9 @@ typedef float f32; | |||||||
| typedef double f64; | typedef double f64; | ||||||
| 
 | 
 | ||||||
| typedef size_t MemoryIndex; | typedef size_t MemoryIndex; | ||||||
|  | typedef char String; | ||||||
|  | 
 | ||||||
|  | typedef struct MemoryArena MemoryArena_; | ||||||
| 
 | 
 | ||||||
| #define TRUE 1 | #define TRUE 1 | ||||||
| #define FALSE 0 | #define FALSE 0 | ||||||
| @ -34,6 +37,44 @@ typedef size_t MemoryIndex; | |||||||
| 
 | 
 | ||||||
| #define DENGINE_DEBUG | #define DENGINE_DEBUG | ||||||
| 
 | 
 | ||||||
|  | #include "Dengine/Math.h" | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |    NOTE(doyle): Small sized optimised dynamic array that grows as required. The | ||||||
|  |    array uses the stack first, only if it runs out of space does it rely on | ||||||
|  |    memory allocated from the machine. | ||||||
|  | 
 | ||||||
|  |    The array->ptr is initially set to fast storage. Once we are out of space | ||||||
|  |    we allocate space on the heap for the ptr and copy over the elements in | ||||||
|  |    fast storage. | ||||||
|  | 
 | ||||||
|  |    The default behaviour expands the array storage by the size of fastStorage. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | enum OptimalArrayError | ||||||
|  | { | ||||||
|  | 	optimalarrayerror_out_of_memory = 1, | ||||||
|  | 	optimalarrayerror_count, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef struct OptimalArrayV2 | ||||||
|  | { | ||||||
|  | 	v2 fastStorage[16]; | ||||||
|  | 	v2 *ptr; | ||||||
|  | 	i32 index; | ||||||
|  | 	i32 size; | ||||||
|  | } OptimalArrayV2; | ||||||
|  | void common_optimalArrayV2Create(OptimalArrayV2 *array); | ||||||
|  | i32 common_optimalArrayV2Push(OptimalArrayV2 *array, v2 data); | ||||||
|  | void common_optimalArrayV2Destroy(OptimalArrayV2 *array); | ||||||
|  | 
 | ||||||
|  | i32 common_stringLen(String *const string); | ||||||
|  | String *const common_stringAppend(MemoryArena_ *const arena, String *oldString, | ||||||
|  |                                   String *appendString, i32 appendLen); | ||||||
|  | void common_stringFree(MemoryArena_ *arena, String *string); | ||||||
|  | String *const common_stringMake(MemoryArena_ *const arena, char *string); | ||||||
|  | String *const common_stringMakeLen(MemoryArena_ *const arena, i32 len); | ||||||
|  | 
 | ||||||
| i32 common_strlen(const char *const string); | i32 common_strlen(const char *const string); | ||||||
| i32 common_strcmp(const char *a, const char *b); | i32 common_strcmp(const char *a, const char *b); | ||||||
| void common_strncat(char *dest, const char *src, i32 numChars); | void common_strncat(char *dest, const char *src, i32 numChars); | ||||||
|  | |||||||
| @ -20,7 +20,7 @@ enum DebugCount | |||||||
| 	debugcount_num, | 	debugcount_num, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void debug_init(MemoryArena_ *arena, v2 windowSize, Font font); | void debug_init(v2 windowSize, Font font); | ||||||
| 
 | 
 | ||||||
| #define DEBUG_RECURSIVE_PRINT_XML_TREE(sig) debug_recursivePrintXmlTree(sig, 1) | #define DEBUG_RECURSIVE_PRINT_XML_TREE(sig) debug_recursivePrintXmlTree(sig, 1) | ||||||
| void debug_recursivePrintXmlTree(XmlNode *root, i32 levelsDeep); | void debug_recursivePrintXmlTree(XmlNode *root, i32 levelsDeep); | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| #define DENGINE_MATH_H | #define DENGINE_MATH_H | ||||||
| 
 | 
 | ||||||
| #include <math.h> | #include <math.h> | ||||||
|  | 
 | ||||||
| #include "Dengine/Common.h" | #include "Dengine/Common.h" | ||||||
| 
 | 
 | ||||||
| #define MATH_PI 3.14159265359f | #define MATH_PI 3.14159265359f | ||||||
|  | |||||||
| @ -143,6 +143,8 @@ typedef struct KeyState | |||||||
| 
 | 
 | ||||||
| typedef struct InputBuffer | typedef struct InputBuffer | ||||||
| { | { | ||||||
|  | 	OptimalArrayV2 *resolutionList; | ||||||
|  | 
 | ||||||
| 	v2 mouseP; | 	v2 mouseP; | ||||||
| 	KeyState keys[keycode_count]; | 	KeyState keys[keycode_count]; | ||||||
| } InputBuffer; | } InputBuffer; | ||||||
|  | |||||||
| @ -84,6 +84,7 @@ typedef struct Renderer | |||||||
| 	i32 groupCapacity; | 	i32 groupCapacity; | ||||||
| } Renderer; | } Renderer; | ||||||
| 
 | 
 | ||||||
|  | void renderer_updateSize(Renderer *renderer, AssetManager *assetManager, v2 windowSize); | ||||||
| void renderer_init(Renderer *renderer, AssetManager *assetManager, | void renderer_init(Renderer *renderer, AssetManager *assetManager, | ||||||
|                    MemoryArena_ *persistentArena, v2 windowSize); |                    MemoryArena_ *persistentArena, v2 windowSize); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,16 +1,5 @@ | |||||||
| #ifndef DENGINE_STRING_H | #ifndef DENGINE_STRING_H | ||||||
| #define DENGINE_STRING_H | #define DENGINE_STRING_H | ||||||
| 
 | 
 | ||||||
| #include "Dengine/Common.h" |  | ||||||
| 
 |  | ||||||
| typedef struct MemoryArena MemoryArena_; |  | ||||||
| typedef char String; |  | ||||||
| 
 |  | ||||||
| i32 string_len(String *const string); |  | ||||||
| String *const string_append(MemoryArena_ *const arena, String *oldString, |  | ||||||
|                             String *appendString, i32 appendLen); |  | ||||||
| void string_free(MemoryArena_ *arena, String *string); |  | ||||||
| String *const string_make(MemoryArena_ *const arena, char *string); |  | ||||||
| String *const string_makeLen(MemoryArena_ *const arena, i32 len); |  | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user