Add string length in pixel func, add button label
This commit is contained in:
		
							parent
							
								
									c33b37b0ea
								
							
						
					
					
						commit
						90068d2c64
					
				| @ -455,6 +455,10 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena, | ||||
| 	font->tex = &assetManager->textures[texlist_font]; | ||||
| 	font->atlas = &assetManager->texAtlas[texlist_font]; | ||||
| 
 | ||||
| 	// NOTE(doyle): Formula derived from STB Font
 | ||||
| 	font->verticalSpacing = | ||||
| 	    font->metrics.ascent - font->metrics.descent + font->metrics.lineGap; | ||||
| 
 | ||||
| 	for (i32 i = 0; i < numGlyphs; i++) | ||||
| 	{ | ||||
| 		i32 glyphBitmapSizeInBytes = CAST(i32) glyphBitmaps[i].dimensions.w * | ||||
| @ -489,3 +493,25 @@ void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena, | ||||
| 
 | ||||
| 	assetManager->anims[animId] = anim; | ||||
| } | ||||
| 
 | ||||
| v2 asset_stringDimInPixels(const Font *const font, const char *const string) | ||||
| { | ||||
| 	v2 stringDim = V2(0, 0); | ||||
| 	for (i32 i = 0; i < common_strlen(string); i++) | ||||
| 	{ | ||||
| 		i32 codepoint = string[i]; | ||||
| 
 | ||||
| #ifdef DENGINE_DEBUG | ||||
| 		ASSERT(codepoint >= font->codepointRange.x && | ||||
| 		       codepoint <= font->codepointRange.y) | ||||
| #endif | ||||
| 
 | ||||
| 		i32 relativeIndex = CAST(i32)(codepoint - font->codepointRange.x); | ||||
| 
 | ||||
| 		v2 charDim  = font->charMetrics[relativeIndex].trueSize; | ||||
| 		stringDim.x += charDim.x; | ||||
| 		stringDim.y = (charDim.y > stringDim.y) ? charDim.y : stringDim.y; | ||||
| 	} | ||||
| 
 | ||||
| 	return stringDim; | ||||
| } | ||||
|  | ||||
| @ -81,7 +81,7 @@ void debug_init(MemoryArena *arena, v2 windowSize, Font font) | ||||
| { | ||||
| 	GLOBAL_debug.font                 = font; | ||||
| 	GLOBAL_debug.callCount = PLATFORM_MEM_ALLOC(arena, debugcallcount_num, i32); | ||||
| 	GLOBAL_debug.stringLineGap = 1.1f * asset_getVFontSpacing(font.metrics); | ||||
| 	GLOBAL_debug.stringLineGap = CAST(f32)font.verticalSpacing; | ||||
| 
 | ||||
| 	/* Init debug string stack */ | ||||
| 	GLOBAL_debug.numDebugStrings   = 0; | ||||
| @ -357,7 +357,7 @@ void debug_drawUi(GameState *state, f32 dt) | ||||
| 			renderer_string(&state->renderer, &state->arena, camera, font, | ||||
| 			                debugString, strPos, V2(0, 0), 0, color); | ||||
| 
 | ||||
| 			f32 stringLineGap = 1.1f * asset_getVFontSpacing(font->metrics); | ||||
| 			f32 stringLineGap = 1.1f * font->verticalSpacing; | ||||
| 			strPos.y -= GLOBAL_debug.stringLineGap; | ||||
| 
 | ||||
| 			char entityPosStr[128]; | ||||
|  | ||||
| @ -211,7 +211,9 @@ void renderer_string(Renderer *const renderer, MemoryArena *arena, Rect camera, | ||||
| 		v2 posInCameraSpace = v2_sub(pos, camera.pos); | ||||
| 
 | ||||
| 		pos          = posInCameraSpace; | ||||
| 		f32 baseline = pos.y; | ||||
| 
 | ||||
| 		// TODO(doyle): Find why font is 1px off, might be arial font semantics
 | ||||
| 		f32 baseline = pos.y - font->verticalSpacing + 1; | ||||
| 		for (i32 i = 0; i < strLen; i++) | ||||
| 		{ | ||||
| 			// NOTE(doyle): Atlas packs fonts tightly, so offset the codepoint
 | ||||
|  | ||||
| @ -1,11 +1,16 @@ | ||||
| #include "Dengine/UserInterface.h" | ||||
| #include "Dengine/AssetManager.h" | ||||
| #include "Dengine/Assets.h" | ||||
| #include "Dengine/Renderer.h" | ||||
| #include "Dengine/Debug.h" | ||||
| 
 | ||||
| i32 userInterface_button(UiState *const uiState, | ||||
|                          MemoryArena *const arena, | ||||
|                          AssetManager *const assetManager, | ||||
|                          Renderer *const renderer, const KeyInput input, | ||||
|                          const i32 id, const Rect rect) | ||||
|                          Renderer *const renderer, | ||||
|                          Font *const font, | ||||
|                          const KeyInput input, | ||||
|                          const i32 id, const Rect rect, const char *const label) | ||||
| { | ||||
| 	if (math_pointInRect(rect, input.mouseP)) | ||||
| 	{ | ||||
| @ -33,25 +38,60 @@ i32 userInterface_button(UiState *const uiState, | ||||
| 	renderer_staticRect(renderer, v2_add(V2(8, 8), rect.pos), rect.size, | ||||
| 	                    V2(0, 0), 0, renderTex, V4(0, 0, 0, 1)); | ||||
| 
 | ||||
| 	v2 buttonOffset = V2(0, 0); | ||||
| 	if (uiState->hotItem == id) | ||||
| 	{ | ||||
| 		if (uiState->activeItem == id) | ||||
| 		{ | ||||
| 			renderer_staticRect(renderer, v2_add(V2(2, 2), rect.pos), rect.size, | ||||
| 			                    V2(0, 0), 0, renderTex, V4(1, 1, 1, 1)); | ||||
| 			buttonOffset = V2(2, 2); | ||||
| 			renderer_staticRect(renderer, v2_add(buttonOffset, rect.pos), | ||||
| 			                    rect.size, V2(0, 0), 0, renderTex, | ||||
| 			                    V4(1, 1, 1, 1)); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			renderer_staticRect(renderer, v2_add(V2(0, 0), rect.pos), rect.size, | ||||
| 			                    V2(0, 0), 0, renderTex, V4(1, 1, 1, 1)); | ||||
| 			renderer_staticRect(renderer, v2_add(buttonOffset, rect.pos), | ||||
| 			                    rect.size, V2(0, 0), 0, renderTex, | ||||
| 			                    V4(1, 1, 1, 1)); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		renderer_staticRect(renderer, v2_add(V2(0, 0), rect.pos), rect.size, | ||||
| 		renderer_staticRect(renderer, v2_add(buttonOffset, rect.pos), rect.size, | ||||
| 		                    V2(0, 0), 0, renderTex, V4(0.5f, 0.5f, 0.5f, 1)); | ||||
| 	} | ||||
| 
 | ||||
| 	if (label) | ||||
| 	{ | ||||
| 		v2 labelDim = asset_stringDimInPixels(font, label); | ||||
| 		DEBUG_PUSH_VAR("label dim: %4.2f, %4.2f", labelDim, "v2"); | ||||
| 		v2 labelPos = rect.pos; | ||||
| 		if (labelDim.w < rect.size.w) | ||||
| 		{ | ||||
| 			// Initially position the label to half the width of the button
 | ||||
| 			labelPos.x += (rect.size.w * 0.5f); | ||||
| 
 | ||||
| 			// Move the label pos back half the length of the string (i.e.
 | ||||
| 			// center it)
 | ||||
| 			labelPos.x -= (CAST(f32)labelDim.w * 0.5f); | ||||
| 		} | ||||
| 
 | ||||
| 		if (labelDim.h < rect.size.h) | ||||
| 		{ | ||||
| 			labelPos.y += (rect.size.h * 0.5f); | ||||
| 			labelPos.y -= (CAST(f32)labelDim.h * 0.5f); | ||||
| 		} | ||||
| 
 | ||||
| 		labelPos = v2_add(labelPos, buttonOffset); | ||||
| 		renderer_staticString(renderer, arena, font, label, labelPos, V2(0, 0), | ||||
| 		                      0, V4(0, 0, 0, 1)); | ||||
| 
 | ||||
| 		v2 rulerPos = rect.pos; | ||||
| 		rulerPos.y -= 10; | ||||
| 		renderer_staticRect(renderer, rulerPos, V2(10, 10), V2(0, 0), 0, | ||||
| 		                    renderTex, V4(0.5f, 0.1f, 0.7f, 1)); | ||||
| 	} | ||||
| 
 | ||||
| 	// After renderering before click check, see if we need to process keys
 | ||||
| 	if (uiState->kbdItem == id) | ||||
| 	{ | ||||
| @ -194,7 +234,7 @@ i32 userInterface_scrollBar(UiState *const uiState, | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| i32 userInterface_textField(UiState *const uiState, MemoryArena *arena, | ||||
| i32 userInterface_textField(UiState *const uiState, MemoryArena *const arena, | ||||
|                             AssetManager *const assetManager, | ||||
|                             Renderer *const renderer, Font *const font, | ||||
|                             KeyInput input, const i32 id, v2 pos, | ||||
| @ -244,8 +284,7 @@ i32 userInterface_textField(UiState *const uiState, MemoryArena *arena, | ||||
| 		                    renderTex, V4(0.5f, 0.5f, 0.5f, 1)); | ||||
| 	} | ||||
| 
 | ||||
| 	// TODO(doyle): Figure out why we need to offset text ..
 | ||||
| 	v2 strPos = v2_add(textRect.pos, V2(0, -font->maxSize.h)); | ||||
| 	v2 strPos = textRect.pos; | ||||
| 
 | ||||
| 	renderer_staticString(renderer, arena, font, string, strPos, V2(0, 0), 0, | ||||
| 	                      V4(0, 0, 0, 1)); | ||||
|  | ||||
| @ -1305,16 +1305,16 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt) | ||||
| 
 | ||||
| 	/* Draw ui */ | ||||
| 	Rect buttonRectA = {V2(300, 500), V2(100, 50)}; | ||||
| 	userInterface_button(&state->uiState, assetManager, renderer, state->input, | ||||
| 	                     1, buttonRectA); | ||||
| 	userInterface_button(&state->uiState, &state->arena, assetManager, renderer, | ||||
| 	                     font, state->input, 1, buttonRectA, "HELLO WORLD"); | ||||
| 
 | ||||
| 	Rect buttonRectB = {V2(500, 500), V2(100, 50)}; | ||||
| 	userInterface_button(&state->uiState, assetManager, renderer, state->input, | ||||
| 	                     2, buttonRectB); | ||||
| 	userInterface_button(&state->uiState, &state->arena, assetManager, renderer, | ||||
| 	                     font, state->input, 2, buttonRectB, "button2"); | ||||
| 
 | ||||
| 	Rect buttonRectC = {V2(700, 500), V2(100, 50)}; | ||||
| 	userInterface_button(&state->uiState, assetManager, renderer, state->input, | ||||
| 	                     3, buttonRectC); | ||||
| 	userInterface_button(&state->uiState, &state->arena, assetManager, renderer, | ||||
| 	                     font, state->input, 3, buttonRectC, "button3"); | ||||
| 
 | ||||
| 	LOCAL_PERSIST i32 scrollValue = 30; | ||||
| 	Rect scrollRectA              = {V2(900, 500), V2(16, 255)}; | ||||
| @ -1356,6 +1356,9 @@ 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)); | ||||
| 
 | ||||
| 	renderer_staticString(&state->renderer, &state->arena, font, heroAvatarStr, | ||||
| 	                      strPos, V2(0, 0), 0, V4(0, 0, 1, 1)); | ||||
| 
 | ||||
| 	for (i32 i = 0; i < world->maxEntities; i++) | ||||
| 	{ | ||||
| 		Entity *entity = &world->entities[i]; | ||||
|  | ||||
| @ -43,14 +43,10 @@ const i32 asset_loadShaderFiles(AssetManager *assetManager, MemoryArena *arena, | ||||
| const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena, | ||||
|                            const char *filePath); | ||||
| 
 | ||||
| inline i32 asset_getVFontSpacing(FontMetrics metrics) | ||||
| { | ||||
| 	i32 result = metrics.ascent - metrics.descent + metrics.lineGap; | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena, | ||||
|                         i32 texId, i32 animId, i32 *atlasIndexes, i32 numFrames, | ||||
|                         f32 frameDuration); | ||||
| 
 | ||||
| v2 asset_stringDimInPixels(const Font *const font, const char *const string); | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -118,8 +118,13 @@ typedef struct Font | ||||
| 	Texture *tex; | ||||
| 
 | ||||
| 	FontMetrics metrics; | ||||
| 
 | ||||
| 	// NOTE(doyle): Array of character's by ASCII value starting from
 | ||||
| 	// codepointRange and their metrics
 | ||||
| 	CharMetrics *charMetrics; | ||||
| 
 | ||||
| 	i32 verticalSpacing; | ||||
| 
 | ||||
| 	v2 codepointRange; | ||||
| 	v2 maxSize; | ||||
| 
 | ||||
|  | ||||
| @ -43,11 +43,16 @@ typedef struct UiState | ||||
| } UiState; | ||||
| 
 | ||||
| i32 userInterface_button(UiState *const uiState, | ||||
|                          MemoryArena *const arena, | ||||
|                          AssetManager *const assetManager, | ||||
|                          Renderer *const renderer, const KeyInput input, | ||||
|                          const i32 id, const Rect rect); | ||||
|                          Renderer *const renderer, | ||||
|                          Font *const font, | ||||
|                          const KeyInput input, | ||||
|                          const i32 id, const Rect rect, | ||||
|                          const char *const label); | ||||
| 
 | ||||
| i32 userInterface_textField(UiState *const uiState, MemoryArena *arena, | ||||
| i32 userInterface_textField(UiState *const uiState, | ||||
|                             MemoryArena *const arena, | ||||
|                             AssetManager *const assetManager, | ||||
|                             Renderer *const renderer, Font *const font, | ||||
|                             KeyInput input, const i32 id, v2 pos, | ||||
|  | ||||
| @ -16,6 +16,11 @@ | ||||
| /* Forward declaration */ | ||||
| typedef struct Entity Entity; | ||||
| 
 | ||||
| typedef struct Config | ||||
| { | ||||
| 	b32 playWorldAudio; | ||||
| } Config; | ||||
| 
 | ||||
| typedef struct World | ||||
| { | ||||
| 	Entity *entities; | ||||
| @ -49,6 +54,7 @@ typedef struct GameState | ||||
| 
 | ||||
| 	AssetManager assetManager; | ||||
| 	AudioManager audioManager; | ||||
| 	Config config; | ||||
| 	MemoryArena arena; | ||||
| 	UiState uiState; | ||||
| } GameState; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user