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/Renderer.h" | ||||||
| #include "Dengine/Debug.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, | i32 userInterface_button(UiState *const uiState, | ||||||
|                          MemoryArena *const arena, |                          MemoryArena *const arena, | ||||||
|                          AssetManager *const assetManager, |                          AssetManager *const assetManager, | ||||||
| @ -194,13 +130,13 @@ i32 userInterface_button(UiState *const uiState, | |||||||
| 	    uiState->hotItem == id && | 	    uiState->hotItem == id && | ||||||
| 	    uiState->activeItem == id) | 	    uiState->activeItem == id) | ||||||
| 	{ | 	{ | ||||||
| 		return 1; | 		return id; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| i32 userInterface_scrollBar(UiState *const uiState, | i32 userInterface_scrollbar(UiState *const uiState, | ||||||
|                             AssetManager *const assetManager, |                             AssetManager *const assetManager, | ||||||
|                             Renderer *const renderer, const KeyInput input, |                             Renderer *const renderer, const KeyInput input, | ||||||
|                             const i32 id, const Rect scrollBarRect, |                             const i32 id, const Rect scrollBarRect, | ||||||
| @ -277,13 +213,13 @@ i32 userInterface_scrollBar(UiState *const uiState, | |||||||
| 			if (*value < maxValue) | 			if (*value < maxValue) | ||||||
| 			{ | 			{ | ||||||
| 				(*value)++; | 				(*value)++; | ||||||
| 				return 1; | 				return id; | ||||||
| 			} | 			} | ||||||
| 		case keycode_down: | 		case keycode_down: | ||||||
| 			if (*value > 0) | 			if (*value > 0) | ||||||
| 			{ | 			{ | ||||||
| 				(*value)--; | 				(*value)--; | ||||||
| 				return 1; | 				return id; | ||||||
| 			} | 			} | ||||||
| 		default: | 		default: | ||||||
| 			break; | 			break; | ||||||
| @ -309,7 +245,7 @@ i32 userInterface_scrollBar(UiState *const uiState, | |||||||
| 		if (newValue != *value) | 		if (newValue != *value) | ||||||
| 		{ | 		{ | ||||||
| 			*value = newValue; | 			*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, | i32 userInterface_textField(UiState *const uiState, MemoryArena *const arena, | ||||||
|                             AssetManager *const assetManager, |                             AssetManager *const assetManager, | ||||||
|                             Renderer *const renderer, Font *const font, |                             Renderer *const renderer, Font *const font, | ||||||
|                             KeyInput input, const i32 id, v2 pos, |                             KeyInput input, const i32 id, const Rect rect, | ||||||
|                             char *const string) |                             char *const string) | ||||||
| { | { | ||||||
| 	i32 strLen = common_strlen(string); | 	i32 strLen = common_strlen(string); | ||||||
| 	b32 changed = FALSE; | 	b32 changed = FALSE; | ||||||
| 
 | 
 | ||||||
| 	Rect textRect = {0}; | 	if (math_pointInRect(rect, input.mouseP)) | ||||||
| 	textRect.pos = pos; |  | ||||||
| 	textRect.size = V2(30 * font->maxSize.w, font->maxSize.h); |  | ||||||
| 
 |  | ||||||
| 	if (math_pointInRect(textRect, input.mouseP)) |  | ||||||
| 	{ | 	{ | ||||||
| 		uiState->hotItem = id; | 		uiState->hotItem = id; | ||||||
| 		if (uiState->activeItem == uiState->statWindow.id || | 		if (uiState->activeItem == uiState->statWindow.id || | ||||||
| @ -352,28 +284,27 @@ i32 userInterface_textField(UiState *const uiState, MemoryArena *const arena, | |||||||
| 	if (uiState->kbdItem == id) | 	if (uiState->kbdItem == id) | ||||||
| 	{ | 	{ | ||||||
| 		// Draw outline
 | 		// Draw outline
 | ||||||
| 		renderer_staticRect(renderer, v2_add(V2(-2, -2), textRect.pos), | 		renderer_staticRect(renderer, v2_add(V2(-2, -2), rect.pos), | ||||||
| 		                    v2_add(V2(4, 4), textRect.size), V2(0, 0), 0, | 		                    v2_add(V2(4, 4), rect.size), V2(0, 0), 0, | ||||||
| 		                    renderTex, V4(1.0f, 0, 0, 1)); | 		                    renderTex, V4(1.0f, 0, 0, 1)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Render text field
 | 	// 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)); | 	                    renderTex, V4(0.75f, 0.5f, 0.5f, 1)); | ||||||
| 
 | 
 | ||||||
| 	if (uiState->activeItem == id || uiState->hotItem == id) | 	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)); | 		                    renderTex, V4(0.75f, 0.75f, 0.0f, 1)); | ||||||
| 	} | 	} | ||||||
| 	else | 	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)); | 		                    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, | 	renderer_staticString(renderer, arena, font, string, strPos, V2(0, 0), 0, | ||||||
| 	                      V4(0, 0, 0, 1)); | 	                      V4(0, 0, 0, 1)); | ||||||
| 
 | 
 | ||||||
| @ -417,6 +348,138 @@ i32 userInterface_textField(UiState *const uiState, MemoryArena *const arena, | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	uiState->lastWidget = id; | 	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 | #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!
 | // TODO(doyle): Remove and implement own random generator!
 | ||||||
| #include <time.h> | #include <time.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| @ -339,6 +389,8 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize) | |||||||
| 	state->state              = state_active; | 	state->state              = state_active; | ||||||
| 	state->currWorldIndex     = 0; | 	state->currWorldIndex     = 0; | ||||||
| 	state->tileSize           = 64; | 	state->tileSize           = 64; | ||||||
|  | 
 | ||||||
|  | 	state->uiState.uniqueId   = 1; | ||||||
| 	state->uiState.keyEntered = keycode_null; | 	state->uiState.keyEntered = keycode_null; | ||||||
| 	state->uiState.keyMod     = keycode_null; | 	state->uiState.keyMod     = keycode_null; | ||||||
| 	state->uiState.keyChar    = 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.prevFrameWindowHeld = FALSE; | ||||||
| 	state->uiState.statWindow.windowHeld          = 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")); | 	               common_strlen("Debug Menu")); | ||||||
| 	state->uiState.debugWindow.id                  = 98; | 	debugWindow->id                  = 98; | ||||||
| 	state->uiState.debugWindow.rect.pos            = V2(800, 400); | 	debugWindow->numChildUiItems     = 0; | ||||||
| 	state->uiState.debugWindow.rect.size           = V2(750, 400); | 	debugWindow->rect.pos            = V2(800, 400); | ||||||
| 	state->uiState.debugWindow.prevFrameWindowHeld = FALSE; | 	debugWindow->rect.size           = V2(750, 400); | ||||||
| 	state->uiState.debugWindow.windowHeld          = FALSE; | 	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.playWorldAudio   = FALSE; | ||||||
| 	state->config.showDebugDisplay = TRUE; | 	state->config.showDebugDisplay = TRUE; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	assetInit(state); | 	assetInit(state); | ||||||
| 	rendererInit(state, windowSize); | 	rendererInit(state, windowSize); | ||||||
| 	entityInit(state, windowSize); | 	entityInit(state, windowSize); | ||||||
| @ -1039,70 +1136,6 @@ typedef struct BattleState | |||||||
| 
 | 
 | ||||||
| GLOBAL_VAR BattleState battleState = {0}; | 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) | void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt) | ||||||
| { | { | ||||||
| @ -1412,53 +1445,22 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt) | |||||||
| 
 | 
 | ||||||
| 	/* Draw debug window */ | 	/* Draw debug window */ | ||||||
| 	WindowState *debugWindow = &state->uiState.debugWindow; | 	WindowState *debugWindow = &state->uiState.debugWindow; | ||||||
| 	userInterface_window(&state->uiState, &state->arena, assetManager, renderer, | 	i32 activeId = | ||||||
| 	                     font, state->input, debugWindow); | 	    userInterface_window(&state->uiState, &state->arena, assetManager, | ||||||
|  | 	                         renderer, font, state->input, debugWindow); | ||||||
| 
 | 
 | ||||||
| 	// TODO(doyle): Bug in font rendering once button reaches 700-800+ pixels
 | 	// TODO(doyle): Name lookup to user interface id
 | ||||||
| 	Rect toggleAudioButtonRect = {0}; | 	if (activeId == 1) | ||||||
| 	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) |  | ||||||
| 	{ | 	{ | ||||||
| 		state->config.playWorldAudio = | 		state->config.playWorldAudio = | ||||||
| 		    (state->config.playWorldAudio == TRUE) ? FALSE : TRUE; | 		    (state->config.playWorldAudio == TRUE) ? FALSE : TRUE; | ||||||
| 	} | 	} | ||||||
| 
 | 	else if (activeId == 2) | ||||||
| 	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) |  | ||||||
| 	{ | 	{ | ||||||
| 		state->config.showDebugDisplay = | 		state->config.showDebugDisplay = | ||||||
| 		    (state->config.showDebugDisplay == TRUE) ? FALSE : TRUE; | 		    (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
 | 	// RESET IMGUI
 | ||||||
| 	if (!state->input.keys[keycode_mouseLeft].endedDown) | 	if (!state->input.keys[keycode_mouseLeft].endedDown) | ||||||
| 		state->uiState.activeItem = 0; | 		state->uiState.activeItem = 0; | ||||||
|  | |||||||
| @ -15,7 +15,7 @@ enum UiType | |||||||
| { | { | ||||||
| 	uitype_button, | 	uitype_button, | ||||||
| 	uitype_scrollbar, | 	uitype_scrollbar, | ||||||
| 	uitype_textfield, | 	uitype_textField, | ||||||
| 	uitype_string, | 	uitype_string, | ||||||
| 	uitype_count, | 	uitype_count, | ||||||
| }; | }; | ||||||
| @ -23,14 +23,24 @@ enum UiType | |||||||
| typedef struct UiItem | typedef struct UiItem | ||||||
| { | { | ||||||
| 	i32 id; | 	i32 id; | ||||||
| 	Rect rect; | 	char label[64]; | ||||||
| 	enum UiType type; | 	enum UiType type; | ||||||
|  | 
 | ||||||
|  | 	Rect rect; | ||||||
|  | 
 | ||||||
|  | 	// TODO(doyle): ECS this? Not all elements need
 | ||||||
|  | 	i32 value; | ||||||
|  | 	i32 maxValue; | ||||||
|  | 	char string[80]; | ||||||
| } UiItem; | } UiItem; | ||||||
| 
 | 
 | ||||||
| typedef struct WindowState | typedef struct WindowState | ||||||
| { | { | ||||||
| 	i32 id; |  | ||||||
| 	char title[64]; | 	char title[64]; | ||||||
|  | 	i32 id; | ||||||
|  | 
 | ||||||
|  | 	UiItem childUiItems[16]; | ||||||
|  | 	i32 numChildUiItems; | ||||||
| 
 | 
 | ||||||
| 	Rect rect; | 	Rect rect; | ||||||
| 	// TODO(doyle): Store this in the input data not window?
 | 	// TODO(doyle): Store this in the input data not window?
 | ||||||
| @ -42,6 +52,8 @@ typedef struct WindowState | |||||||
| 
 | 
 | ||||||
| typedef struct UiState | typedef struct UiState | ||||||
| { | { | ||||||
|  | 	i32 uniqueId; | ||||||
|  | 
 | ||||||
| 	UiItem uiList[128]; | 	UiItem uiList[128]; | ||||||
| 	i32 numItems; | 	i32 numItems; | ||||||
| 
 | 
 | ||||||
| @ -58,10 +70,11 @@ typedef struct UiState | |||||||
| 	WindowState debugWindow; | 	WindowState debugWindow; | ||||||
| } UiState; | } UiState; | ||||||
| 
 | 
 | ||||||
| i32 userInterface_window(UiState *const uiState, MemoryArena *const arena, | inline i32 userInterface_generateId(UiState *const uiState) | ||||||
|                          AssetManager *const assetManager, | { | ||||||
|                          Renderer *const renderer, Font *const font, | 	i32 result = uiState->uniqueId++; | ||||||
|                          const KeyInput input, WindowState *window); | 	return result; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| i32 userInterface_button(UiState *const uiState, | i32 userInterface_button(UiState *const uiState, | ||||||
|                          MemoryArena *const arena, |                          MemoryArena *const arena, | ||||||
| @ -76,12 +89,17 @@ i32 userInterface_textField(UiState *const uiState, | |||||||
|                             MemoryArena *const arena, |                             MemoryArena *const arena, | ||||||
|                             AssetManager *const assetManager, |                             AssetManager *const assetManager, | ||||||
|                             Renderer *const renderer, Font *const font, |                             Renderer *const renderer, Font *const font, | ||||||
|                             KeyInput input, const i32 id, v2 pos, |                             KeyInput input, const i32 id, const Rect rect, | ||||||
|                             char *const string); |                             char *const string); | ||||||
| 
 | 
 | ||||||
| i32 userInterface_scrollBar(UiState *const uiState, | i32 userInterface_scrollbar(UiState *const uiState, | ||||||
|                             AssetManager *const assetManager, |                             AssetManager *const assetManager, | ||||||
|                             Renderer *const renderer, const KeyInput input, |                             Renderer *const renderer, const KeyInput input, | ||||||
|                             const i32 id, const Rect scrollBarRect, |                             const i32 id, const Rect scrollBarRect, | ||||||
|                             i32 *const value, const i32 maxValue); |                             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 | #endif | ||||||
|  | |||||||
| @ -16,6 +16,21 @@ | |||||||
| /* Forward declaration */ | /* Forward declaration */ | ||||||
| typedef struct Entity Entity; | 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 | typedef struct Config | ||||||
| { | { | ||||||
| 	b32 playWorldAudio; | 	b32 playWorldAudio; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user