Move ui element rendering to window rendering
This commit is contained in:
		
							parent
							
								
									70a3032155
								
							
						
					
					
						commit
						4e585a4939
					
				| @ -4,70 +4,6 @@ | ||||
| #include "Dengine/Renderer.h" | ||||
| #include "Dengine/Debug.h" | ||||
| 
 | ||||
| i32 userInterface_window(UiState *const uiState, MemoryArena *const arena, | ||||
|                          AssetManager *const assetManager, | ||||
|                          Renderer *const renderer, Font *const font, | ||||
|                          const KeyInput input, WindowState *window) | ||||
| { | ||||
| 	if (math_pointInRect(window->rect, input.mouseP)) | ||||
| 	{ | ||||
| 		uiState->hotItem = window->id; | ||||
| 		if (uiState->activeItem == 0 && input.keys[keycode_mouseLeft].endedDown) | ||||
| 			uiState->activeItem = window->id; | ||||
| 	} | ||||
| 
 | ||||
| 	Rect rect = window->rect; | ||||
| 	RenderTex nullRenderTex = renderer_createNullRenderTex(assetManager); | ||||
| 	renderer_staticRect(renderer, rect.pos, rect.size, V2(0, 0), 0, | ||||
| 	                    nullRenderTex, V4(0.25f, 0.25f, 0.5f, 0.5f)); | ||||
| 
 | ||||
| 	v2 menuTitleP = v2_add(rect.pos, V2(0, rect.size.h - 10)); | ||||
| 	renderer_staticString(renderer, arena, font, window->title, menuTitleP, | ||||
| 	                      V2(0, 0), 0, V4(0, 0, 0, 1)); | ||||
| 
 | ||||
| 	// 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 (!input.keys[keycode_mouseLeft].endedDown) | ||||
| 		{ | ||||
| 			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); | ||||
| 			DEBUG_PUSH_VAR("Delta Pos %4.2f, %4.2f", deltaP, "v2"); | ||||
| 			window->rect.pos = v2_add(deltaP, window->rect.pos); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			window->prevFrameWindowHeld = TRUE; | ||||
| 		} | ||||
| 
 | ||||
| 		window->prevMouseP = input.mouseP; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!input.keys[keycode_mouseLeft].endedDown && | ||||
| 	    uiState->hotItem == window->id && | ||||
| 	    uiState->activeItem == window->id) | ||||
| 	{ | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| i32 userInterface_button(UiState *const uiState, | ||||
|                          MemoryArena *const arena, | ||||
|                          AssetManager *const assetManager, | ||||
| @ -194,13 +130,13 @@ i32 userInterface_button(UiState *const uiState, | ||||
| 	    uiState->hotItem == id && | ||||
| 	    uiState->activeItem == id) | ||||
| 	{ | ||||
| 		return 1; | ||||
| 		return id; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| i32 userInterface_scrollBar(UiState *const uiState, | ||||
| i32 userInterface_scrollbar(UiState *const uiState, | ||||
|                             AssetManager *const assetManager, | ||||
|                             Renderer *const renderer, const KeyInput input, | ||||
|                             const i32 id, const Rect scrollBarRect, | ||||
| @ -277,13 +213,13 @@ i32 userInterface_scrollBar(UiState *const uiState, | ||||
| 			if (*value < maxValue) | ||||
| 			{ | ||||
| 				(*value)++; | ||||
| 				return 1; | ||||
| 				return id; | ||||
| 			} | ||||
| 		case keycode_down: | ||||
| 			if (*value > 0) | ||||
| 			{ | ||||
| 				(*value)--; | ||||
| 				return 1; | ||||
| 				return id; | ||||
| 			} | ||||
| 		default: | ||||
| 			break; | ||||
| @ -309,7 +245,7 @@ i32 userInterface_scrollBar(UiState *const uiState, | ||||
| 		if (newValue != *value) | ||||
| 		{ | ||||
| 			*value = newValue; | ||||
| 			return 1; | ||||
| 			return id; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| @ -319,17 +255,13 @@ i32 userInterface_scrollBar(UiState *const uiState, | ||||
| 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, | ||||
|                             KeyInput input, const i32 id, const Rect rect, | ||||
|                             char *const string) | ||||
| { | ||||
| 	i32 strLen = common_strlen(string); | ||||
| 	b32 changed = FALSE; | ||||
| 
 | ||||
| 	Rect textRect = {0}; | ||||
| 	textRect.pos = pos; | ||||
| 	textRect.size = V2(30 * font->maxSize.w, font->maxSize.h); | ||||
| 
 | ||||
| 	if (math_pointInRect(textRect, input.mouseP)) | ||||
| 	if (math_pointInRect(rect, input.mouseP)) | ||||
| 	{ | ||||
| 		uiState->hotItem = id; | ||||
| 		if (uiState->activeItem == uiState->statWindow.id || | ||||
| @ -352,28 +284,27 @@ i32 userInterface_textField(UiState *const uiState, MemoryArena *const arena, | ||||
| 	if (uiState->kbdItem == id) | ||||
| 	{ | ||||
| 		// Draw outline
 | ||||
| 		renderer_staticRect(renderer, v2_add(V2(-2, -2), textRect.pos), | ||||
| 		                    v2_add(V2(4, 4), textRect.size), V2(0, 0), 0, | ||||
| 		renderer_staticRect(renderer, v2_add(V2(-2, -2), rect.pos), | ||||
| 		                    v2_add(V2(4, 4), rect.size), V2(0, 0), 0, | ||||
| 		                    renderTex, V4(1.0f, 0, 0, 1)); | ||||
| 	} | ||||
| 
 | ||||
| 	// Render text field
 | ||||
| 	renderer_staticRect(renderer, textRect.pos, textRect.size, V2(0, 0), 0, | ||||
| 	renderer_staticRect(renderer, rect.pos, rect.size, V2(0, 0), 0, | ||||
| 	                    renderTex, V4(0.75f, 0.5f, 0.5f, 1)); | ||||
| 
 | ||||
| 	if (uiState->activeItem == id || uiState->hotItem == id) | ||||
| 	{ | ||||
| 		renderer_staticRect(renderer, textRect.pos, textRect.size, V2(0, 0), 0, | ||||
| 		renderer_staticRect(renderer, rect.pos, rect.size, V2(0, 0), 0, | ||||
| 		                    renderTex, V4(0.75f, 0.75f, 0.0f, 1)); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		renderer_staticRect(renderer, textRect.pos, textRect.size, V2(0, 0), 0, | ||||
| 		renderer_staticRect(renderer, rect.pos, rect.size, V2(0, 0), 0, | ||||
| 		                    renderTex, V4(0.5f, 0.5f, 0.5f, 1)); | ||||
| 	} | ||||
| 
 | ||||
| 	v2 strPos = textRect.pos; | ||||
| 
 | ||||
| 	v2 strPos = rect.pos; | ||||
| 	renderer_staticString(renderer, arena, font, string, strPos, V2(0, 0), 0, | ||||
| 	                      V4(0, 0, 0, 1)); | ||||
| 
 | ||||
| @ -417,6 +348,138 @@ i32 userInterface_textField(UiState *const uiState, MemoryArena *const arena, | ||||
| 	} | ||||
| 
 | ||||
| 	uiState->lastWidget = id; | ||||
| 	return changed; | ||||
| 
 | ||||
| 	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 KeyInput input, WindowState *window) | ||||
| { | ||||
| 	if (math_pointInRect(window->rect, input.mouseP)) | ||||
| 	{ | ||||
| 		uiState->hotItem = window->id; | ||||
| 		if (uiState->activeItem == 0 && input.keys[keycode_mouseLeft].endedDown) | ||||
| 			uiState->activeItem = window->id; | ||||
| 	} | ||||
| 
 | ||||
| 	Rect rect = window->rect; | ||||
| 	RenderTex nullRenderTex = renderer_createNullRenderTex(assetManager); | ||||
| 	renderer_staticRect(renderer, rect.pos, rect.size, V2(0, 0), 0, | ||||
| 	                    nullRenderTex, V4(0.25f, 0.25f, 0.5f, 0.5f)); | ||||
| 
 | ||||
| 	v2 menuTitleP = v2_add(rect.pos, V2(0, rect.size.h - 10)); | ||||
| 	renderer_staticString(renderer, arena, font, window->title, menuTitleP, | ||||
| 	                      V2(0, 0), 0, V4(0, 0, 0, 1)); | ||||
| 
 | ||||
| 	// 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 0 | ||||
| 	for (i32 i = 0; i < window->numChildItems; i++) | ||||
| 	{ | ||||
| 		if (uiState->activeItem == window->childUiId[i]) | ||||
| 		{ | ||||
| 			window->windowHeld          = FALSE; | ||||
| 			window->prevFrameWindowHeld = FALSE; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	if (window->windowHeld) | ||||
| 	{ | ||||
| 		if (!input.keys[keycode_mouseLeft].endedDown) | ||||
| 		{ | ||||
| 			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.pos = v2_add(deltaP, childUi->rect.pos); | ||||
| 			} | ||||
| 
 | ||||
| 			DEBUG_PUSH_VAR("Delta Pos %4.2f, %4.2f", deltaP, "v2"); | ||||
| 			window->rect.pos = v2_add(deltaP, window->rect.pos); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			window->prevFrameWindowHeld = TRUE; | ||||
| 		} | ||||
| 
 | ||||
| 		window->prevMouseP = input.mouseP; | ||||
| 	} | ||||
| 
 | ||||
| 	/* 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: | ||||
| 			// TODO(doyle): window steals scrollbar focus
 | ||||
| 			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; | ||||
| 
 | ||||
| 	if (!input.keys[keycode_mouseLeft].endedDown && | ||||
| 	    uiState->hotItem == window->id && | ||||
| 	    uiState->activeItem == window->id) | ||||
| 	{ | ||||
| 		return window->id; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -323,6 +323,56 @@ INTERNAL void entityInit(GameState *state, v2 windowSize) | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| INTERNAL v2 getPosRelativeToRect(Rect rect, v2 offset, | ||||
|                                  enum RectBaseline baseline) | ||||
| { | ||||
| #ifdef DENGINE_DEBUG | ||||
| 	ASSERT(baseline < rectbaseline_count); | ||||
| #endif | ||||
| 	v2 result = {0}; | ||||
| 
 | ||||
| 	v2 posToOffsetFrom = rect.pos; | ||||
| 	switch (baseline) | ||||
| 	{ | ||||
| 		case rectbaseline_top: | ||||
| 			posToOffsetFrom.y += (rect.size.h); | ||||
| 			posToOffsetFrom.x += (rect.size.w * 0.5f); | ||||
| 		    break; | ||||
| 		case rectbaseline_topLeft: | ||||
| 			posToOffsetFrom.y += (rect.size.h); | ||||
| 			break; | ||||
| 		case rectbaseline_topRight: | ||||
| 			posToOffsetFrom.y += (rect.size.h); | ||||
| 			posToOffsetFrom.x += (rect.size.w); | ||||
| 			break; | ||||
| 		case rectbaseline_bottom: | ||||
| 			posToOffsetFrom.x += (rect.size.w * 0.5f); | ||||
| 			break; | ||||
| 		case rectbaseline_bottomRight: | ||||
| 			posToOffsetFrom.x += (rect.size.w); | ||||
| 			break; | ||||
| 		case rectbaseline_left: | ||||
| 			posToOffsetFrom.y += (rect.size.h * 0.5f); | ||||
| 			break; | ||||
| 		case rectbaseline_right: | ||||
| 			posToOffsetFrom.x += (rect.size.w); | ||||
| 			posToOffsetFrom.y += (rect.size.h * 0.5f); | ||||
| 			break; | ||||
| 
 | ||||
| 		case rectbaseline_bottomLeft: | ||||
| 		    break; | ||||
| 		default: | ||||
| #ifdef DENGINE_DEBUG | ||||
| 		    DEBUG_LOG( | ||||
| 		        "getPosRelativeToRect() warning: baseline enum not recognised"); | ||||
| #endif | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	result = v2_add(posToOffsetFrom, offset); | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| // TODO(doyle): Remove and implement own random generator!
 | ||||
| #include <time.h> | ||||
| #include <stdlib.h> | ||||
| @ -339,6 +389,8 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize) | ||||
| 	state->state              = state_active; | ||||
| 	state->currWorldIndex     = 0; | ||||
| 	state->tileSize           = 64; | ||||
| 
 | ||||
| 	state->uiState.uniqueId   = 1; | ||||
| 	state->uiState.keyEntered = keycode_null; | ||||
| 	state->uiState.keyMod     = keycode_null; | ||||
| 	state->uiState.keyChar    = keycode_null; | ||||
| @ -351,18 +403,63 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize) | ||||
| 	state->uiState.statWindow.prevFrameWindowHeld = FALSE; | ||||
| 	state->uiState.statWindow.windowHeld          = FALSE; | ||||
| 
 | ||||
| 	common_strncpy(state->uiState.debugWindow.title, "Debug Menu", | ||||
| 	WindowState *debugWindow = &state->uiState.debugWindow; | ||||
| 	common_strncpy(debugWindow->title, "Debug Menu", | ||||
| 	               common_strlen("Debug Menu")); | ||||
| 	state->uiState.debugWindow.id                  = 98; | ||||
| 	state->uiState.debugWindow.rect.pos            = V2(800, 400); | ||||
| 	state->uiState.debugWindow.rect.size           = V2(750, 400); | ||||
| 	state->uiState.debugWindow.prevFrameWindowHeld = FALSE; | ||||
| 	state->uiState.debugWindow.windowHeld          = FALSE; | ||||
| 	debugWindow->id                  = 98; | ||||
| 	debugWindow->numChildUiItems     = 0; | ||||
| 	debugWindow->rect.pos            = V2(800, 400); | ||||
| 	debugWindow->rect.size           = V2(750, 400); | ||||
| 	debugWindow->prevFrameWindowHeld = FALSE; | ||||
| 	debugWindow->windowHeld          = FALSE; | ||||
| 
 | ||||
| 	UiItem *audioBtn = | ||||
| 	    (debugWindow->childUiItems) + debugWindow->numChildUiItems++; | ||||
| 	common_strncpy(audioBtn->label, "Toggle Music", | ||||
| 	               common_strlen("Toggle Music")); | ||||
| 	audioBtn->id        = userInterface_generateId(&state->uiState); | ||||
| 	audioBtn->rect.size = V2(100, 50); | ||||
| 	audioBtn->rect.pos = getPosRelativeToRect(debugWindow->rect, V2(10, -65.0f), | ||||
| 	                                          rectbaseline_topLeft); | ||||
| 	audioBtn->type = uitype_button; | ||||
| 
 | ||||
| 	UiItem *debugBtn = | ||||
| 	    (debugWindow->childUiItems) + debugWindow->numChildUiItems++; | ||||
| 	common_strncpy(debugBtn->label, "Toggle Debug", | ||||
| 	               common_strlen("Toggle Debug")); | ||||
| 	debugBtn->id        = userInterface_generateId(&state->uiState); | ||||
| 	debugBtn->rect.size = V2(100, 50); | ||||
| 	debugBtn->rect.pos  = getPosRelativeToRect(audioBtn->rect, V2(25, 0), | ||||
| 	                                          rectbaseline_bottomRight); | ||||
| 	debugBtn->type = uitype_button; | ||||
| 
 | ||||
| 	UiItem *scrollbar = | ||||
| 	    (debugWindow->childUiItems) + debugWindow->numChildUiItems++; | ||||
| 	scrollbar->id     = userInterface_generateId(&state->uiState); | ||||
| 
 | ||||
| 	scrollbar->rect.size = V2(16, debugWindow->rect.size.h); | ||||
| 	scrollbar->rect.pos = | ||||
| 	    getPosRelativeToRect(debugWindow->rect, V2(-scrollbar->rect.size.w, 0), | ||||
| 	                         rectbaseline_bottomRight); | ||||
| 	scrollbar->value    = 0; | ||||
| 	scrollbar->maxValue = 160; | ||||
| 	scrollbar->type = uitype_scrollbar; | ||||
| 
 | ||||
| 	UiItem *textField = | ||||
| 	    (debugWindow->childUiItems) + debugWindow->numChildUiItems++; | ||||
| 	textField->id = userInterface_generateId(&state->uiState); | ||||
| 	textField->rect.size = V2(200, 20); | ||||
| 	textField->rect.pos  = getPosRelativeToRect( | ||||
| 	    audioBtn->rect, V2(0, -textField->rect.size.h - 10), | ||||
| 	    rectbaseline_bottomLeft); | ||||
| 
 | ||||
| 	common_strncpy(textField->string, "Hello world", | ||||
| 	               common_strlen("Hello world")); | ||||
| 	textField->type = uitype_textField; | ||||
| 
 | ||||
| 	state->config.playWorldAudio   = FALSE; | ||||
| 	state->config.showDebugDisplay = TRUE; | ||||
| 
 | ||||
| 
 | ||||
| 	assetInit(state); | ||||
| 	rendererInit(state, windowSize); | ||||
| 	entityInit(state, windowSize); | ||||
| @ -1039,70 +1136,6 @@ typedef struct BattleState | ||||
| 
 | ||||
| GLOBAL_VAR BattleState battleState = {0}; | ||||
| 
 | ||||
| enum RectBaseline | ||||
| { | ||||
| 	rectbaseline_top, | ||||
| 	rectbaseline_topLeft, | ||||
| 	rectbaseline_topRight, | ||||
| 	rectbaseline_bottom, | ||||
| 	rectbaseline_bottomRight, | ||||
| 	rectbaseline_bottomLeft, | ||||
| 	rectbaseline_left, | ||||
| 	rectbaseline_right, | ||||
| 	rectbaseline_center, | ||||
| 	rectbaseline_count, | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| INTERNAL v2 getPosRelativeToRect(Rect rect, v2 offset, | ||||
|                                  enum RectBaseline baseline) | ||||
| { | ||||
| #ifdef DENGINE_DEBUG | ||||
| 	ASSERT(baseline < rectbaseline_count); | ||||
| #endif | ||||
| 	v2 result = {0}; | ||||
| 
 | ||||
| 	v2 posToOffsetFrom = rect.pos; | ||||
| 	switch (baseline) | ||||
| 	{ | ||||
| 		case rectbaseline_top: | ||||
| 			posToOffsetFrom.y += (rect.size.h); | ||||
| 			posToOffsetFrom.x += (rect.size.w * 0.5f); | ||||
| 		    break; | ||||
| 		case rectbaseline_topLeft: | ||||
| 			posToOffsetFrom.y += (rect.size.h); | ||||
| 			break; | ||||
| 		case rectbaseline_topRight: | ||||
| 			posToOffsetFrom.y += (rect.size.h); | ||||
| 			posToOffsetFrom.x += (rect.size.w); | ||||
| 			break; | ||||
| 		case rectbaseline_bottom: | ||||
| 			posToOffsetFrom.x += (rect.size.w * 0.5f); | ||||
| 			break; | ||||
| 		case rectbaseline_bottomRight: | ||||
| 			posToOffsetFrom.x += (rect.size.w); | ||||
| 			break; | ||||
| 		case rectbaseline_left: | ||||
| 			posToOffsetFrom.y += (rect.size.h * 0.5f); | ||||
| 			break; | ||||
| 		case rectbaseline_right: | ||||
| 			posToOffsetFrom.x += (rect.size.w); | ||||
| 			posToOffsetFrom.y += (rect.size.h * 0.5f); | ||||
| 			break; | ||||
| 
 | ||||
| 		case rectbaseline_bottomLeft: | ||||
| 		    break; | ||||
| 		default: | ||||
| #ifdef DENGINE_DEBUG | ||||
| 		    DEBUG_LOG( | ||||
| 		        "getPosRelativeToRect() warning: baseline enum not recognised"); | ||||
| #endif | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	result = v2_add(posToOffsetFrom, offset); | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt) | ||||
| { | ||||
| @ -1412,53 +1445,22 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt) | ||||
| 
 | ||||
| 	/* Draw debug window */ | ||||
| 	WindowState *debugWindow = &state->uiState.debugWindow; | ||||
| 	userInterface_window(&state->uiState, &state->arena, assetManager, renderer, | ||||
| 	                     font, state->input, debugWindow); | ||||
| 	i32 activeId = | ||||
| 	    userInterface_window(&state->uiState, &state->arena, assetManager, | ||||
| 	                         renderer, font, state->input, debugWindow); | ||||
| 
 | ||||
| 	// TODO(doyle): Bug in font rendering once button reaches 700-800+ pixels
 | ||||
| 	Rect toggleAudioButtonRect = {0}; | ||||
| 	toggleAudioButtonRect.size = V2(100, 50); | ||||
| 	toggleAudioButtonRect.pos  = getPosRelativeToRect( | ||||
| 	    debugWindow->rect, V2(10, -65.0f), rectbaseline_topLeft); | ||||
| 
 | ||||
| 	b32 toggleAudioClicked = userInterface_button( | ||||
| 	    &state->uiState, &state->arena, assetManager, renderer, font, | ||||
| 	    state->input, 1, toggleAudioButtonRect, "Toggle Music"); | ||||
| 
 | ||||
| 	if (toggleAudioClicked) | ||||
| 	// TODO(doyle): Name lookup to user interface id
 | ||||
| 	if (activeId == 1) | ||||
| 	{ | ||||
| 		state->config.playWorldAudio = | ||||
| 		    (state->config.playWorldAudio == TRUE) ? FALSE : TRUE; | ||||
| 	} | ||||
| 
 | ||||
| 	Rect toggleDebugButtonRect = {0}; | ||||
| 	toggleDebugButtonRect.size = V2(100, 50); | ||||
| 	toggleDebugButtonRect.pos  = getPosRelativeToRect( | ||||
| 	    toggleAudioButtonRect, V2(25, 0), rectbaseline_bottomRight); | ||||
| 	b32 toggleDebugClicked = userInterface_button( | ||||
| 	    &state->uiState, &state->arena, assetManager, renderer, font, | ||||
| 	    state->input, 2, toggleDebugButtonRect, "Toggle Debug Display"); | ||||
| 
 | ||||
| 	if (toggleDebugClicked) | ||||
| 	else if (activeId == 2) | ||||
| 	{ | ||||
| 		state->config.showDebugDisplay = | ||||
| 		    (state->config.showDebugDisplay == TRUE) ? FALSE : TRUE; | ||||
| 	} | ||||
| 
 | ||||
| 	LOCAL_PERSIST i32 scrollValue = 30; | ||||
| 	Rect scrollRectA              = {V2(0, 0), V2(16, 255)}; | ||||
| 	scrollRectA.pos = getPosRelativeToRect(debugWindow->rect, V2(-20, -260), | ||||
| 	                                       rectbaseline_topRight); | ||||
| 	userInterface_scrollBar(&state->uiState, assetManager, renderer, | ||||
| 	                        state->input, 3, scrollRectA, &scrollValue, 160); | ||||
| 
 | ||||
| 	LOCAL_PERSIST char fieldString[80] = "Hello world"; | ||||
| 	v2 textFieldP = getPosRelativeToRect(toggleAudioButtonRect, V2(0, -20), | ||||
| 	                                     rectbaseline_bottomLeft); | ||||
| 	userInterface_textField(&state->uiState, &state->arena, assetManager, | ||||
| 	                        renderer, font, state->input, 4, textFieldP, | ||||
| 	                        fieldString); | ||||
| 
 | ||||
| 	// RESET IMGUI
 | ||||
| 	if (!state->input.keys[keycode_mouseLeft].endedDown) | ||||
| 		state->uiState.activeItem = 0; | ||||
|  | ||||
| @ -15,7 +15,7 @@ enum UiType | ||||
| { | ||||
| 	uitype_button, | ||||
| 	uitype_scrollbar, | ||||
| 	uitype_textfield, | ||||
| 	uitype_textField, | ||||
| 	uitype_string, | ||||
| 	uitype_count, | ||||
| }; | ||||
| @ -23,14 +23,24 @@ enum UiType | ||||
| typedef struct UiItem | ||||
| { | ||||
| 	i32 id; | ||||
| 	Rect rect; | ||||
| 	char label[64]; | ||||
| 	enum UiType type; | ||||
| 
 | ||||
| 	Rect rect; | ||||
| 
 | ||||
| 	// TODO(doyle): ECS this? Not all elements need
 | ||||
| 	i32 value; | ||||
| 	i32 maxValue; | ||||
| 	char string[80]; | ||||
| } UiItem; | ||||
| 
 | ||||
| typedef struct WindowState | ||||
| { | ||||
| 	i32 id; | ||||
| 	char title[64]; | ||||
| 	i32 id; | ||||
| 
 | ||||
| 	UiItem childUiItems[16]; | ||||
| 	i32 numChildUiItems; | ||||
| 
 | ||||
| 	Rect rect; | ||||
| 	// TODO(doyle): Store this in the input data not window?
 | ||||
| @ -42,6 +52,8 @@ typedef struct WindowState | ||||
| 
 | ||||
| typedef struct UiState | ||||
| { | ||||
| 	i32 uniqueId; | ||||
| 
 | ||||
| 	UiItem uiList[128]; | ||||
| 	i32 numItems; | ||||
| 
 | ||||
| @ -58,10 +70,11 @@ typedef struct UiState | ||||
| 	WindowState debugWindow; | ||||
| } UiState; | ||||
| 
 | ||||
| i32 userInterface_window(UiState *const uiState, MemoryArena *const arena, | ||||
|                          AssetManager *const assetManager, | ||||
|                          Renderer *const renderer, Font *const font, | ||||
|                          const KeyInput input, WindowState *window); | ||||
| inline i32 userInterface_generateId(UiState *const uiState) | ||||
| { | ||||
| 	i32 result = uiState->uniqueId++; | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| i32 userInterface_button(UiState *const uiState, | ||||
|                          MemoryArena *const arena, | ||||
| @ -76,12 +89,17 @@ 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, | ||||
|                             KeyInput input, const i32 id, const Rect rect, | ||||
|                             char *const string); | ||||
| 
 | ||||
| i32 userInterface_scrollBar(UiState *const uiState, | ||||
| i32 userInterface_scrollbar(UiState *const uiState, | ||||
|                             AssetManager *const assetManager, | ||||
|                             Renderer *const renderer, const KeyInput 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 KeyInput input, WindowState *window); | ||||
| #endif | ||||
|  | ||||
| @ -16,6 +16,21 @@ | ||||
| /* Forward declaration */ | ||||
| typedef struct Entity Entity; | ||||
| 
 | ||||
| enum RectBaseline | ||||
| { | ||||
| 	rectbaseline_top, | ||||
| 	rectbaseline_topLeft, | ||||
| 	rectbaseline_topRight, | ||||
| 	rectbaseline_bottom, | ||||
| 	rectbaseline_bottomRight, | ||||
| 	rectbaseline_bottomLeft, | ||||
| 	rectbaseline_left, | ||||
| 	rectbaseline_right, | ||||
| 	rectbaseline_center, | ||||
| 	rectbaseline_count, | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| typedef struct Config | ||||
| { | ||||
| 	b32 playWorldAudio; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user