Introduce temp memory to free memory leaks
This commit is contained in:
		
							parent
							
								
									3729ddf164
								
							
						
					
					
						commit
						ad14d6d822
					
				| @ -980,11 +980,15 @@ typedef struct GlyphBitmap | ||||
| 	i32 codepoint; | ||||
| } GlyphBitmap; | ||||
| 
 | ||||
| const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena_ *arena, | ||||
|                            const char *filePath) | ||||
| const i32 asset_loadTTFont(AssetManager *assetManager, | ||||
|                            MemoryArena_ *persistentArena, | ||||
|                            MemoryArena_ *transientArena, const char *filePath) | ||||
| { | ||||
| 	TempMemory tempRegion = memory_begin_temporary_region(transientArena); | ||||
| 
 | ||||
| 	PlatformFileRead fontFileRead = {0}; | ||||
| 	i32 result = platform_readFileToBuffer(arena, filePath, &fontFileRead); | ||||
| 	i32 result = | ||||
| 	    platform_readFileToBuffer(transientArena, filePath, &fontFileRead); | ||||
| 	if (result) return result; | ||||
| 
 | ||||
| 	stbtt_fontinfo fontInfo = {0}; | ||||
| @ -1002,7 +1006,7 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena_ *arena, | ||||
| 	const i32 numGlyphs = CAST(i32)(codepointRange.y - codepointRange.x); | ||||
| 
 | ||||
| 	GlyphBitmap *glyphBitmaps = | ||||
| 	    memory_pushBytes(arena, numGlyphs * sizeof(GlyphBitmap)); | ||||
| 	    memory_pushBytes(transientArena, numGlyphs * sizeof(GlyphBitmap)); | ||||
| 	v2 largestGlyphDimension = V2(0, 0); | ||||
| 
 | ||||
| 	const f32 targetFontHeight = 15.0f; | ||||
| @ -1018,7 +1022,7 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena_ *arena, | ||||
| 	font->metrics = CAST(FontMetrics){ascent, descent, lineGap}; | ||||
| 
 | ||||
| 	font->charMetrics = | ||||
| 	    memory_pushBytes(arena, numGlyphs * sizeof(CharMetrics)); | ||||
| 	    memory_pushBytes(persistentArena, numGlyphs * sizeof(CharMetrics)); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 ************************************************************ | ||||
| @ -1038,7 +1042,7 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena_ *arena, | ||||
| 
 | ||||
| 		u8 *source       = monoBitmap; | ||||
| 		u32 *colorBitmap = | ||||
| 		    memory_pushBytes(arena, width * height * sizeof(u32)); | ||||
| 		    memory_pushBytes(transientArena, width * height * sizeof(u32)); | ||||
| 		u32 *dest        = colorBitmap; | ||||
| 
 | ||||
| 		// NOTE(doyle): STB generates 1 byte per pixel bitmaps, we use 4bpp, so
 | ||||
| @ -1114,7 +1118,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena_ *arena, | ||||
| #endif | ||||
| 
 | ||||
| 	i32 bitmapSize = SQUARED(TARGET_TEXTURE_SIZE) * TARGET_BYTES_PER_PIXEL; | ||||
| 	u32 *fontBitmap = memory_pushBytes(arena, bitmapSize * sizeof(u32)); | ||||
| 	u32 *fontBitmap = | ||||
| 	    memory_pushBytes(transientArena, bitmapSize * sizeof(u32)); | ||||
| 	const i32 pitch = MAX_TEXTURE_SIZE * TARGET_BYTES_PER_PIXEL; | ||||
| 
 | ||||
| 	// Check value to determine when a row of glyphs is completely printed
 | ||||
| @ -1131,8 +1136,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena_ *arena, | ||||
| 	char charToEncode = CAST(char)codepointRange.x; | ||||
| 
 | ||||
| 	i32 numSubTex = numGlyphs; | ||||
| 	TexAtlas *fontAtlas = | ||||
| 	    asset_getFreeTexAtlasSlot(assetManager, arena, "font", numSubTex); | ||||
| 	TexAtlas *fontAtlas = asset_getFreeTexAtlasSlot( | ||||
| 	    assetManager, persistentArena, "font", numSubTex); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 ********************************************************* | ||||
| @ -1159,7 +1164,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena_ *arena, | ||||
| 				// all ascii characters, charToEncode represents the character
 | ||||
| 				// 1:1
 | ||||
| 				const char key[2] = {charToEncode, 0}; | ||||
| 				SubTexture *subTex = getFreeAtlasSubTexSlot(fontAtlas, arena, key); | ||||
| 				SubTexture *subTex = | ||||
| 				    getFreeAtlasSubTexSlot(fontAtlas, persistentArena, key); | ||||
| 				subTex->rect = CAST(Rect){origin, font->maxSize}; | ||||
| 				charToEncode++; | ||||
| 			} | ||||
| @ -1213,7 +1219,7 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena_ *arena, | ||||
| 	 * Generate and store font bitmap to assets | ||||
| 	 ******************************************* | ||||
| 	 */ | ||||
| 	Texture *tex = asset_getFreeTexSlot(assetManager, arena, "font"); | ||||
| 	Texture *tex = asset_getFreeTexSlot(assetManager, persistentArena, "font"); | ||||
| 	*tex         = texture_gen(MAX_TEXTURE_SIZE, MAX_TEXTURE_SIZE, 4, | ||||
| 	                   CAST(u8 *) fontBitmap); | ||||
| 
 | ||||
| @ -1238,14 +1244,9 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena_ *arena, | ||||
| 		i32 glyphBitmapSizeInBytes = CAST(i32) glyphBitmaps[i].dimensions.w * | ||||
| 		                             CAST(i32) glyphBitmaps[i].dimensions.h * | ||||
| 		                             sizeof(u32); | ||||
| 		// TODO(doyle): Mem free
 | ||||
| 		// PLATFORM_MEM_FREE(arena, glyphBitmaps[i].pixels, glyphBitmapSizeInBytes);
 | ||||
| 	} | ||||
| 
 | ||||
| 	// TODO(doyle): Mem free
 | ||||
| 	// PLATFORM_MEM_FREE(arena, glyphBitmaps, numGlyphs * sizeof(GlyphBitmap));
 | ||||
| 	platform_closeFileRead(arena, &fontFileRead); | ||||
| 
 | ||||
| 	memory_end_temporary_region(tempRegion); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -27,8 +27,9 @@ void initAssetManager(GameState *state) | ||||
| 		Texture *tex = asset_getFreeTexSlot(assetManager, arena, "nullTex"); | ||||
| 		*tex         = texture_gen(1, 1, 4, CAST(u8 *)(&bitmap)); | ||||
| 
 | ||||
| 		i32 result = asset_loadTTFont(assetManager, arena, | ||||
| 		                              "C:/Windows/Fonts/Arialbd.ttf"); | ||||
| 		i32 result = | ||||
| 		    asset_loadTTFont(assetManager, arena, &state->transientArena, | ||||
| 		                     "C:/Windows/Fonts/Arialbd.ttf"); | ||||
| 	} | ||||
| 
 | ||||
| 	{ // Init shaders assets
 | ||||
| @ -997,20 +998,23 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | ||||
| 		Renderer *renderer           = &state->renderer; | ||||
| 		InputBuffer *inputBuffer     = &state->input; | ||||
| 
 | ||||
| 		renderer_rect(renderer, world->camera, V2(0, 0), renderer->size, | ||||
| 		              V2(0, 0), 0, NULL, V4(0, 0, 0, 0.5f), | ||||
| 		              renderflag_no_texture); | ||||
| 
 | ||||
| 		v2 titleP = V2(20, renderer->size.h - 100); | ||||
| 		renderer_staticString(renderer, transientArena, &assetManager->font, | ||||
| 		                      "Asteroids", titleP, V2(0, 0), 0, V4(1, 0, 0, 1), | ||||
| 		                      0); | ||||
| 
 | ||||
| 		userInterface_beginState(uiState); | ||||
| 
 | ||||
| 		WindowState window = {0}; | ||||
| 		window.id          = userInterface_generateId(uiState); | ||||
| 		Rect buttonRect = {V2(20, 20), V2(40, 40)}; | ||||
| 
 | ||||
| 		Rect windowRect = {0}; | ||||
| 		windowRect.min  = V2(200, 200); | ||||
| 		windowRect.max  = V2(500, 500); | ||||
| 
 | ||||
| 		window.rect = windowRect; | ||||
| 
 | ||||
| #if 0 | ||||
| 		userInterface_window(uiState, transientArena, assetManager, renderer, | ||||
| 		                     &assetManager->font, *inputBuffer, &window); | ||||
| #if 1 | ||||
| 		userInterface_button(uiState, transientArena, assetManager, renderer, | ||||
| 		                     &assetManager->font, *inputBuffer, 0, buttonRect, | ||||
| 		                     "test button"); | ||||
| #endif | ||||
| 
 | ||||
| 		userInterface_endState(uiState, inputBuffer); | ||||
|  | ||||
| @ -272,7 +272,7 @@ const i32 audio_playVorbis(MemoryArena_ *arena, AudioManager *audioManager, | ||||
|                            AudioRenderer *audioRenderer, AudioVorbis *vorbis, | ||||
|                            i32 numPlays) | ||||
| { | ||||
| 	if(vorbis) return -1; | ||||
| 	if (vorbis == NULL) return -1; | ||||
| 
 | ||||
| 	i32 result = initRendererForPlayback(arena, audioManager, audioRenderer, | ||||
| 	                                     vorbis, numPlays); | ||||
| @ -304,7 +304,7 @@ const i32 audio_streamPlayVorbis(MemoryArena_ *arena, AudioManager *audioManager | ||||
| 	// TODO(doyle): Streaming leaks memory, we don't free the "copy audio"
 | ||||
| 	ASSERT(INVALID_CODE_PATH); | ||||
| 
 | ||||
| 	if(vorbis) return -1; | ||||
| 	if (vorbis == NULL) return -1; | ||||
| 
 | ||||
| 	i32 result = initRendererForPlayback(arena, audioManager, audioRenderer, | ||||
| 	                                     vorbis, numPlays); | ||||
|  | ||||
| @ -2,7 +2,30 @@ | ||||
| 
 | ||||
| void memory_arenaInit(MemoryArena_ *arena, void *base, size_t size) | ||||
| { | ||||
| 	arena->size = size; | ||||
| 	arena->used = 0; | ||||
| 	arena->base = CAST(u8 *)base; | ||||
| 	arena->size            = size; | ||||
| 	arena->used            = 0; | ||||
| 	arena->base            = CAST(u8 *) base; | ||||
| 	arena->tempMemoryCount = 0; | ||||
| } | ||||
| 
 | ||||
| TempMemory memory_begin_temporary_region(MemoryArena_ *arena) | ||||
| { | ||||
| 	TempMemory result = {0}; | ||||
| 	result.arena      = arena; | ||||
| 	result.used       = arena->used; | ||||
| 
 | ||||
| 	arena->tempMemoryCount++; | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| void memory_end_temporary_region(TempMemory tempMemory) | ||||
| { | ||||
| 	MemoryArena_ *arena = tempMemory.arena; | ||||
| 	ASSERT(arena->used > tempMemory.used) | ||||
| 
 | ||||
| 	arena->used        = tempMemory.used; | ||||
| 	ASSERT(arena->tempMemoryCount > 0) | ||||
| 
 | ||||
| 	arena->tempMemoryCount--; | ||||
| } | ||||
|  | ||||
| @ -28,6 +28,7 @@ void *platform_memoryAlloc(MemoryArena_ *arena, size_t numBytes) | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| // TODO(doyle): If we use arena temporary memory this is not necessary
 | ||||
| void platform_closeFileRead(MemoryArena_ *arena, PlatformFileRead *file) | ||||
| { | ||||
| 	// TODO(doyle): Mem free
 | ||||
| @ -178,4 +179,3 @@ b32 platform_queryKey(KeyState *key, enum ReadKeyType readType, | ||||
| 
 | ||||
| 	return FALSE; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -424,7 +424,11 @@ void renderer_rect(Renderer *const renderer, Rect camera, v2 pos, v2 size, | ||||
| 	v2 posInCameraSpace = v2_sub(pos, camera.min); | ||||
| 
 | ||||
| 	RenderTex emptyRenderTex = {0}; | ||||
| 	if (!renderTex) renderTex = &emptyRenderTex; | ||||
| 	if (!renderTex) | ||||
| 	{ | ||||
| 		renderTex = &emptyRenderTex; | ||||
| 		ASSERT(common_isSet(flags, renderflag_no_texture)); | ||||
| 	} | ||||
| 
 | ||||
| 	RenderQuad quad = createRenderQuad(renderer, posInCameraSpace, size, | ||||
| 	                                   pivotPoint, rotate, *renderTex); | ||||
| @ -496,7 +500,11 @@ void renderer_polygon(Renderer *const renderer, Rect camera, | ||||
| 
 | ||||
| 	// TODO(doyle): Do something with render texture
 | ||||
| 	RenderTex emptyRenderTex  = {0}; | ||||
| 	if (!renderTex) renderTex = &emptyRenderTex; | ||||
| 	if (!renderTex) | ||||
| 	{ | ||||
| 		renderTex = &emptyRenderTex; | ||||
| 		ASSERT(common_isSet(flags, renderflag_no_texture)); | ||||
| 	} | ||||
| 
 | ||||
| 	v2 triangulationBaseP                = polygonPoints[0]; | ||||
| 	RenderVertex triangulationBaseVertex = {0}; | ||||
|  | ||||
| @ -37,15 +37,7 @@ i32 userInterface_button(UiState *const uiState, MemoryArena_ *const arena, | ||||
| 	if (math_pointInRect(rect, input.mouseP)) | ||||
| 	{ | ||||
| 		uiState->hotItem = id; | ||||
| 
 | ||||
| 		// NOTE(doyle): UI windows are drawn first, they steal focus on mouse
 | ||||
| 		// click since window logic is paired with the window rendering. If
 | ||||
| 		// a UI element resides over our mouse, we allow the element to override
 | ||||
| 		// the windows focus
 | ||||
| 		// TODO(doyle): Make a window list to iterate over window ids
 | ||||
| 		if (uiState->activeItem == uiState->statWindow.id || | ||||
| 		    uiState->activeItem == uiState->debugWindow.id || | ||||
| 			uiState->activeItem == 0) | ||||
| 		if (uiState->activeItem == 0) | ||||
| 		{ | ||||
| 			if (common_isSet(input.keys[keycode_mouseLeft].flags, | ||||
| 			                 keystateflag_ended_down)) | ||||
| @ -56,8 +48,6 @@ i32 userInterface_button(UiState *const uiState, MemoryArena_ *const arena, | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	RenderTex renderTex = renderer_createNullRenderTex(assetManager); | ||||
| 
 | ||||
| #if 0 | ||||
| 	// Draw shadow
 | ||||
| 	renderer_staticRect(renderer, v2_add(V2(1, 1), rect.min), rect.size, | ||||
| @ -65,23 +55,23 @@ i32 userInterface_button(UiState *const uiState, MemoryArena_ *const arena, | ||||
| #endif | ||||
| 
 | ||||
| 	v2 buttonOffset = V2(0, 0); | ||||
| 	v4 buttonColor = {0}; | ||||
| 	v4 buttonColor = V4(1, 1, 1, 1); | ||||
| 	if (uiState->hotItem == id) | ||||
| 	{ | ||||
| 		if (uiState->activeItem == id) | ||||
| 		{ | ||||
| 			buttonOffset = V2(1, 1); | ||||
| 			buttonColor = V4(1, 1, 1, 1); | ||||
| 			buttonColor = V4(1.0f, 0, 0, 1); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			// TODO(doyle): Optional add effect on button hover
 | ||||
| 			buttonColor = V4(1, 1, 1, 1); | ||||
| 			buttonColor = V4(1.0f, 0, 0, 1); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		buttonColor = V4(0.5f, 0.5f, 0.5f, 1); | ||||
| 		buttonColor = V4(1.0f, 0, 0, 1); | ||||
| 	} | ||||
| 
 | ||||
| 	/* If no widget has keyboard focus, take it */ | ||||
| @ -94,12 +84,12 @@ i32 userInterface_button(UiState *const uiState, MemoryArena_ *const arena, | ||||
| 		// Draw outline
 | ||||
| 		renderer_staticRect(renderer, | ||||
| 		                    v2_add(V2(-2, -2), v2_add(buttonOffset, rect.min)), | ||||
| 		                    v2_add(V2(4, 4), rect.max), V2(0, 0), 0, &renderTex, | ||||
| 		                    buttonColor, 0); | ||||
| 		                    v2_add(V2(4, 4), rect.max), V2(0, 0), 0, NULL, | ||||
| 		                    buttonColor, renderflag_no_texture); | ||||
| 	} | ||||
| 
 | ||||
| 	renderer_staticRect(renderer, v2_add(buttonOffset, rect.min), rect.max, | ||||
| 	                    V2(0, 0), 0, &renderTex, buttonColor, 0); | ||||
| 	                    V2(0, 0), 0, NULL, buttonColor, renderflag_no_texture); | ||||
| 
 | ||||
| 	if (label) | ||||
| 	{ | ||||
| @ -172,9 +162,7 @@ i32 userInterface_scrollbar(UiState *const uiState, | ||||
| 	if (math_pointInRect(scrollBarRect, input.mouseP)) | ||||
| 	{ | ||||
| 		uiState->hotItem = id; | ||||
| 		if (uiState->activeItem == uiState->statWindow.id || | ||||
| 		    uiState->activeItem == uiState->debugWindow.id || | ||||
| 			uiState->activeItem == 0) | ||||
| 		if (uiState->activeItem == 0) | ||||
| 		{ | ||||
| 			if (common_isSet(input.keys[keycode_mouseLeft].flags, | ||||
| 			                 keystateflag_ended_down)) | ||||
| @ -288,9 +276,7 @@ i32 userInterface_textField(UiState *const uiState, MemoryArena_ *const arena, | ||||
| 	if (math_pointInRect(rect, input.mouseP)) | ||||
| 	{ | ||||
| 		uiState->hotItem = id; | ||||
| 		if (uiState->activeItem == uiState->statWindow.id || | ||||
| 		    uiState->activeItem == uiState->debugWindow.id || | ||||
| 			uiState->activeItem == 0) | ||||
| 		if (uiState->activeItem == 0) | ||||
| 		{ | ||||
| 			if (common_isSet(input.keys[keycode_mouseLeft].flags, | ||||
| 			                 keystateflag_ended_down)) | ||||
| @ -304,29 +290,28 @@ i32 userInterface_textField(UiState *const uiState, MemoryArena_ *const arena, | ||||
| 	if (uiState->kbdItem == 0) | ||||
| 		uiState->kbdItem = id; | ||||
| 
 | ||||
| 	RenderTex renderTex = renderer_createNullRenderTex(assetManager); | ||||
| 	/* If we have keyboard focus, show it */ | ||||
| 	if (uiState->kbdItem == id) | ||||
| 	{ | ||||
| 		// Draw outline
 | ||||
| 		renderer_staticRect(renderer, v2_add(V2(-2, -2), rect.min), | ||||
| 		                    v2_add(V2(4, 4), rect.max), V2(0, 0), 0, | ||||
| 		                    &renderTex, V4(1.0f, 0, 0, 1), 0); | ||||
| 		                    NULL, V4(1.0f, 0, 0, 1), 0); | ||||
| 	} | ||||
| 
 | ||||
| 	// Render text field
 | ||||
| 	renderer_staticRect(renderer, rect.min, rect.max, V2(0, 0), 0, | ||||
| 	                    &renderTex, V4(0.75f, 0.5f, 0.5f, 1), 0); | ||||
| 	renderer_staticRect(renderer, rect.min, rect.max, V2(0, 0), 0, NULL, | ||||
| 	                    V4(0.75f, 0.5f, 0.5f, 1), 0); | ||||
| 
 | ||||
| 	if (uiState->activeItem == id || uiState->hotItem == id) | ||||
| 	{ | ||||
| 		renderer_staticRect(renderer, rect.min, rect.max, V2(0, 0), 0, | ||||
| 		                    &renderTex, V4(0.75f, 0.75f, 0.0f, 1), 0); | ||||
| 		                    NULL, V4(0.75f, 0.75f, 0.0f, 1), 0); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		renderer_staticRect(renderer, rect.min, rect.max, V2(0, 0), 0, | ||||
| 		                    &renderTex, V4(0.5f, 0.5f, 0.5f, 1), 0); | ||||
| 		                    NULL, V4(0.5f, 0.5f, 0.5f, 1), 0); | ||||
| 	} | ||||
| 
 | ||||
| 	v2 strPos = rect.min; | ||||
| @ -377,124 +362,3 @@ i32 userInterface_textField(UiState *const uiState, MemoryArena_ *const arena, | ||||
| 	if (changed) return id; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| i32 userInterface_window(UiState *const uiState, MemoryArena_ *const arena, | ||||
|                          AssetManager *const assetManager, | ||||
|                          Renderer *const renderer, Font *const font, | ||||
|                          const InputBuffer input, WindowState *window) | ||||
| { | ||||
| 	if (math_pointInRect(window->rect, input.mouseP)) | ||||
| 	{ | ||||
| 		uiState->hotItem = window->id; | ||||
| 		if (uiState->activeItem == 0 && | ||||
| 		    common_isSet(input.keys[keycode_mouseLeft].flags, | ||||
| 		                 keystateflag_ended_down)) | ||||
| 			uiState->activeItem = window->id; | ||||
| 	} | ||||
| 
 | ||||
| 	Rect rect = window->rect; | ||||
| 	RenderTex nullRenderTex = renderer_createNullRenderTex(assetManager); | ||||
| 	renderer_staticRect(renderer, rect.min, rect.max, V2(0, 0), 0, | ||||
| 	                    &nullRenderTex, V4(0.25f, 0.25f, 0.5f, 0.5f), 0); | ||||
| 
 | ||||
| 	v2 menuTitleP = v2_add(rect.min, V2(0, rect.max.h - 10)); | ||||
| 	renderer_staticString(renderer, arena, font, window->title, menuTitleP, | ||||
| 	                      V2(0, 0), 0, V4(0, 0, 0, 1), 0); | ||||
| 
 | ||||
| 	/* Draw window elements */ | ||||
| 	i32 firstActiveChildId = -1; | ||||
| 	for (i32 i = 0; i < window->numChildUiItems; i++) | ||||
| 	{ | ||||
| 		UiItem *childUi = &window->childUiItems[i]; | ||||
| 
 | ||||
| 		// TODO(doyle): Redundant? If we can only have 1 active child at a time
 | ||||
| 		// What about overlapping elements?
 | ||||
| 		i32 getChildActiveState = -1; | ||||
| 		switch(childUi->type) | ||||
| 		{ | ||||
| 		case uitype_button: | ||||
| 			// TODO(doyle): Bug in font rendering once button reaches 700-800+
 | ||||
| 			// pixels
 | ||||
| 			getChildActiveState = userInterface_button( | ||||
| 			    uiState, arena, assetManager, renderer, font, input, | ||||
| 			    childUi->id, childUi->rect, childUi->label); | ||||
| 			break; | ||||
| 
 | ||||
| 		case uitype_scrollbar: | ||||
| 			getChildActiveState = userInterface_scrollbar( | ||||
| 			    uiState, assetManager, renderer, input, childUi->id, | ||||
| 			    childUi->rect, &childUi->value, childUi->maxValue); | ||||
| 			break; | ||||
| 
 | ||||
| 		case uitype_textField: | ||||
| 			getChildActiveState = userInterface_textField( | ||||
| 			    uiState, arena, assetManager, renderer, font, input, | ||||
| 			    childUi->id, childUi->rect, childUi->string); | ||||
| 			break; | ||||
| 
 | ||||
| 		default: | ||||
| 			DEBUG_LOG( | ||||
| 			    "userInterface_window() warning: Enum uitype unrecognised"); | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		// NOTE(doyle): Capture only the first active id, but keep loop going to
 | ||||
| 		// render the rest of the window ui
 | ||||
| 		if (firstActiveChildId == -1 && getChildActiveState > 0) | ||||
| 			firstActiveChildId = getChildActiveState; | ||||
| 	} | ||||
| 
 | ||||
| 	if (firstActiveChildId != -1) | ||||
| 		return firstActiveChildId; | ||||
| 
 | ||||
| 	// NOTE(doyle): activeItem captures mouse click within the UI bounds, but if
 | ||||
| 	// the user drags the mouse outside the bounds quicker than the game updates
 | ||||
| 	// then we use a second flag which only "unclicks" when the mouse is let go
 | ||||
| 	if (uiState->activeItem == window->id) window->windowHeld = TRUE; | ||||
| 
 | ||||
| 	if (window->windowHeld) | ||||
| 	{ | ||||
| 		if (!common_isSet(input.keys[keycode_mouseLeft].flags, | ||||
| 		                  keystateflag_ended_down)) | ||||
| 		{ | ||||
| 			window->windowHeld          = FALSE; | ||||
| 			window->prevFrameWindowHeld = FALSE; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (window->windowHeld) | ||||
| 	{ | ||||
| 		// NOTE(doyle): If this is the first window click we don't process
 | ||||
| 		// movement and store the current position to delta from next cycle
 | ||||
| 		if (window->prevFrameWindowHeld) | ||||
| 		{ | ||||
| 			// NOTE(doyle): Window clicked and held
 | ||||
| 			v2 deltaP = v2_sub(input.mouseP, window->prevMouseP); | ||||
| 
 | ||||
| 			for (i32 i = 0; i < window->numChildUiItems; i++) | ||||
| 			{ | ||||
| 				UiItem *childUi = &window->childUiItems[i]; | ||||
| 				childUi->rect.min = v2_add(deltaP, childUi->rect.min); | ||||
| 			} | ||||
| 
 | ||||
| 			DEBUG_PUSH_VAR("Delta Pos %4.2f, %4.2f", deltaP, "v2"); | ||||
| 			window->rect.min = v2_add(deltaP, window->rect.min); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			window->prevFrameWindowHeld = TRUE; | ||||
| 		} | ||||
| 
 | ||||
| 		window->prevMouseP = input.mouseP; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!common_isSet(input.keys[keycode_mouseLeft].flags, | ||||
| 	                  keystateflag_ended_down) && | ||||
| 	    uiState->hotItem == window->id && uiState->activeItem == window->id) | ||||
| 	{ | ||||
| 		return window->id; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -165,7 +165,7 @@ i32 main(void) | ||||
| 	 */ | ||||
| 	Memory memory = {0}; | ||||
| 	MemoryIndex persistentSize = MEGABYTES(32); | ||||
| 	MemoryIndex transientSize  = MEGABYTES(32); | ||||
| 	MemoryIndex transientSize  = MEGABYTES(64); | ||||
| 
 | ||||
| 	memory.persistentSize = persistentSize; | ||||
| 	memory.persistent     = PLATFORM_MEM_ALLOC_(NULL, persistentSize, u8); | ||||
|  | ||||
| @ -78,8 +78,9 @@ const i32 asset_loadShaderFiles(AssetManager *assetManager, MemoryArena_ *arena, | ||||
|                                 const char *const fragmentPath, | ||||
|                                 const enum ShaderList type); | ||||
| 
 | ||||
| const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena_ *arena, | ||||
|                            const char *filePath); | ||||
| const i32 asset_loadTTFont(AssetManager *assetManager, | ||||
|                            MemoryArena_ *persistentArena, | ||||
|                            MemoryArena_ *transientArena, const char *filePath); | ||||
| const v2 asset_stringDimInPixels(const Font *const font, | ||||
|                                  const char *const string); | ||||
| 
 | ||||
|  | ||||
| @ -8,6 +8,8 @@ typedef struct MemoryArena | ||||
| 	MemoryIndex size; | ||||
| 	MemoryIndex used; | ||||
| 	u8 *base; | ||||
| 
 | ||||
| 	i32 tempMemoryCount; | ||||
| } MemoryArena_; | ||||
| 
 | ||||
| typedef struct Memory | ||||
| @ -21,6 +23,15 @@ typedef struct Memory | ||||
| 	b32 init; | ||||
| } Memory; | ||||
| 
 | ||||
| typedef struct TempMemory | ||||
| { | ||||
| 	MemoryArena_ *arena; | ||||
| 	MemoryIndex used; | ||||
| } TempMemory; | ||||
| 
 | ||||
| TempMemory memory_begin_temporary_region(MemoryArena_ *arena); | ||||
| void memory_end_temporary_region(TempMemory tempMemory); | ||||
| 
 | ||||
| #define MEMORY_PUSH_STRUCT(arena, type) (type *)memory_pushBytes(arena, sizeof(type)) | ||||
| #define MEMORY_PUSH_ARRAY(arena, count, type) (type *)memory_pushBytes(arena, (count)*sizeof(type)) | ||||
| inline void *memory_pushBytes(MemoryArena_ *arena, MemoryIndex size) | ||||
|  | ||||
| @ -35,22 +35,6 @@ typedef struct UiItem | ||||
| 	char string[80]; | ||||
| } UiItem; | ||||
| 
 | ||||
| typedef struct WindowState | ||||
| { | ||||
| 	char title[64]; | ||||
| 	i32 id; | ||||
| 
 | ||||
| 	UiItem childUiItems[16]; | ||||
| 	i32 numChildUiItems; | ||||
| 
 | ||||
| 	Rect rect; | ||||
| 	// TODO(doyle): Store this in the input data not window?
 | ||||
| 	v2 prevMouseP; | ||||
| 
 | ||||
| 	b32 prevFrameWindowHeld; | ||||
| 	b32 windowHeld; | ||||
| } WindowState; | ||||
| 
 | ||||
| typedef struct UiState | ||||
| { | ||||
| 	i32 uniqueId; | ||||
| @ -66,9 +50,6 @@ typedef struct UiState | ||||
| 	enum KeyCode keyEntered; | ||||
| 	enum KeyCode keyMod; | ||||
| 	enum KeyCode keyChar; | ||||
| 
 | ||||
| 	WindowState statWindow; | ||||
| 	WindowState debugWindow; | ||||
| } UiState; | ||||
| 
 | ||||
| inline i32 userInterface_generateId(UiState *const uiState) | ||||
| @ -97,9 +78,4 @@ i32 userInterface_scrollbar(UiState *const uiState, | ||||
|                             Renderer *const renderer, const InputBuffer input, | ||||
|                             const i32 id, const Rect scrollBarRect, | ||||
|                             i32 *const value, const i32 maxValue); | ||||
| 
 | ||||
| i32 userInterface_window(UiState *const uiState, MemoryArena_ *const arena, | ||||
|                          AssetManager *const assetManager, | ||||
|                          Renderer *const renderer, Font *const font, | ||||
|                          const InputBuffer input, WindowState *window); | ||||
| #endif | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user