Add text field draft implementation
This commit is contained in:
		
							parent
							
								
									4127542d1d
								
							
						
					
					
						commit
						22973ef51d
					
				| @ -90,6 +90,7 @@ INTERNAL inline RenderQuad | ||||
| createDefaultTexQuad(Renderer *renderer, RenderTex renderTex) | ||||
| { | ||||
| 	RenderQuad result = {0}; | ||||
| 	// TODO(doyle): We need to switch this so its xy bottom left, zw top right!!
 | ||||
| 	v4 defaultQuad    = V4(0.0f, renderer->size.h, renderer->size.w, 0.0f); | ||||
| 	result            = createTexQuad(renderer, defaultQuad, renderTex); | ||||
| 	return result; | ||||
|  | ||||
| @ -341,6 +341,8 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize) | ||||
| 	DEBUG_LOG("World populated"); | ||||
| #endif | ||||
| 
 | ||||
| 	state->uiState.keyEntered = keycode_null; | ||||
| 
 | ||||
| 	srand(CAST(u32)(time(NULL))); | ||||
| } | ||||
| 
 | ||||
| @ -375,24 +377,24 @@ INTERNAL void parseInput(GameState *state, const f32 dt) | ||||
| 		// if a button ended down
 | ||||
| 		LOCAL_PERSIST b32 spaceBarWasDown = FALSE; | ||||
| 
 | ||||
| 		if (state->input.right) | ||||
| 		if (state->input.keys[keycode_right]) | ||||
| 		{ | ||||
| 			ddPos.x         = 1.0f; | ||||
| 			hero->direction = direction_east; | ||||
| 		} | ||||
| 
 | ||||
| 		if (state->input.left) | ||||
| 		if (state->input.keys[keycode_left]) | ||||
| 		{ | ||||
| 			ddPos.x         = -1.0f; | ||||
| 			hero->direction = direction_west; | ||||
| 		} | ||||
| 
 | ||||
| 		if (state->input.up) | ||||
| 		if (state->input.keys[keycode_up]) | ||||
| 		{ | ||||
| 			ddPos.y = 1.0f; | ||||
| 		} | ||||
| 
 | ||||
| 		if (state->input.down) | ||||
| 		if (state->input.keys[keycode_down]) | ||||
| 		{ | ||||
| 			ddPos.y = -1.0f; | ||||
| 		} | ||||
| @ -406,10 +408,18 @@ INTERNAL void parseInput(GameState *state, const f32 dt) | ||||
| 			ddPos = v2_scale(ddPos, 0.70710678118f); | ||||
| 		} | ||||
| 
 | ||||
| 		if (state->input.keys[keycode_enter]) | ||||
| 		{ | ||||
| 			state->uiState.keyEntered = keycode_enter; | ||||
| 		} | ||||
| 
 | ||||
| 		LOCAL_PERSIST b32 toggleFlag = TRUE; | ||||
| 		// TODO(doyle): Revisit key input with state checking for last ended down
 | ||||
| 		if (state->input.space && spaceBarWasDown == FALSE) | ||||
| 		if (state->input.keys[keycode_space] && spaceBarWasDown == FALSE) | ||||
| 		{ | ||||
| 			state->uiState.keyEntered = keycode_space; | ||||
| 
 | ||||
| #if 0 | ||||
| 			Renderer *renderer = &state->renderer; | ||||
| 			f32 yPos = CAST(f32)(rand() % CAST(i32)renderer->size.h); | ||||
| 			f32 xModifier =  5.0f - CAST(f32)(rand() % 3); | ||||
| @ -417,9 +427,10 @@ INTERNAL void parseInput(GameState *state, const f32 dt) | ||||
| 			v2 pos = V2(renderer->size.w - (renderer->size.w / xModifier), yPos); | ||||
| 			entity_addGenericMob(&state->arena, &state->assetManager, world, | ||||
| 			                     pos); | ||||
| #endif | ||||
| 			spaceBarWasDown = TRUE; | ||||
| 		} | ||||
| 		else if (!state->input.space) | ||||
| 		else if (!state->input.keys[keycode_space]) | ||||
| 		{ | ||||
| 			spaceBarWasDown = FALSE; | ||||
| 		} | ||||
| @ -444,8 +455,16 @@ INTERNAL void parseInput(GameState *state, const f32 dt) | ||||
| 	} | ||||
| 
 | ||||
| 	f32 heroSpeed = 6.2f * METERS_TO_PIXEL; | ||||
| 	if (state->input.leftShift) | ||||
| 	if (state->input.keys[keycode_leftShift]) | ||||
| 	{ | ||||
| 		// TODO: Context sensitive command separation
 | ||||
| 		state->uiState.keyMod = keycode_leftShift; | ||||
| 		heroSpeed = CAST(f32)(22.0f * 10.0f * METERS_TO_PIXEL); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		state->uiState.keyMod = keycode_null; | ||||
| 	} | ||||
| 
 | ||||
| 	ddPos = v2_scale(ddPos, heroSpeed); | ||||
| 	// TODO(doyle): Counteracting force on player's acceleration is arbitrary
 | ||||
| @ -878,9 +897,8 @@ INTERNAL i32 button(UiState *uiState, AssetManager *assetManager, | ||||
| { | ||||
| 	if (math_pointInRect(rect, input.mouseP)) | ||||
| 	{ | ||||
| 		DEBUG_PUSH_STRING("POINT IN RECT"); | ||||
| 		uiState->hotItem = id; | ||||
| 		if (uiState->activeItem == 0 && input.mouseLeft) | ||||
| 		if (uiState->activeItem == 0 && input.keys[keycode_mouseLeft]) | ||||
| 			uiState->activeItem = id; | ||||
| 	} | ||||
| 
 | ||||
| @ -925,22 +943,27 @@ INTERNAL i32 button(UiState *uiState, AssetManager *assetManager, | ||||
| 	// After renderering before click check, see if we need to process keys
 | ||||
| 	if (uiState->kbdItem == id) | ||||
| 	{ | ||||
| 		if (input.space) | ||||
| 		switch (uiState->keyEntered) | ||||
| 		{ | ||||
| 		case keycode_space: | ||||
| 			// Set focus to nothing and let next widget get focus
 | ||||
| 			uiState->kbdItem = 0; | ||||
| 			if (input.leftShift) | ||||
| 			if (uiState->keyMod == keycode_leftShift) | ||||
| 				uiState->kbdItem = uiState->lastWidget; | ||||
| 
 | ||||
| 			// Clear key state so next widget doesn't auto grab
 | ||||
| 			input.space     = FALSE; | ||||
| 			input.leftShift = FALSE; | ||||
| 			uiState->keyEntered = keycode_null; | ||||
| 			break; | ||||
| 		case keycode_enter: | ||||
| 			return 1; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	uiState->lastWidget = id; | ||||
| 
 | ||||
| 	if (!input.mouseLeft && | ||||
| 	if (!input.keys[keycode_mouseLeft] && | ||||
| 	    uiState->hotItem == id && | ||||
| 	    uiState->activeItem == id) | ||||
| 	{ | ||||
| @ -961,12 +984,25 @@ INTERNAL i32 scrollBar(UiState *uiState, AssetManager *assetManager, | ||||
| 	if (math_pointInRect(scrollBarRect, input.mouseP)) | ||||
| 	{ | ||||
| 		uiState->hotItem = id; | ||||
| 		if (uiState->activeItem == 0 && input.mouseLeft) | ||||
| 		if (uiState->activeItem == 0 && input.keys[keycode_mouseLeft]) | ||||
| 			uiState->activeItem = id; | ||||
| 	} | ||||
| 
 | ||||
| 	RenderTex renderTex = renderer_createNullRenderTex(assetManager); | ||||
| 
 | ||||
| 	/* If no widget has keyboard focus, take it */ | ||||
| 	if (uiState->kbdItem == 0) | ||||
| 		uiState->kbdItem = id; | ||||
| 
 | ||||
| 	/* If we have keyboard focus, show it */ | ||||
| 	if (uiState->kbdItem == id) | ||||
| 	{ | ||||
| 		// Draw outline
 | ||||
| 		renderer_staticRect(renderer, v2_add(V2(-6, -6), scrollBarRect.pos), | ||||
| 		                    v2_add(V2(20, 20), scrollBarRect.size), V2(0, 0), 0, | ||||
| 		                    renderTex, V4(1.0f, 0, 0, 1)); | ||||
| 	} | ||||
| 
 | ||||
| 	// Render scroll bar background
 | ||||
| 	renderer_staticRect(renderer, scrollBarRect.pos, scrollBarRect.size, | ||||
| 	                    V2(0, 0), 0, renderTex, V4(0.75f, 0.5f, 0.5f, 1)); | ||||
| @ -988,6 +1024,38 @@ INTERNAL i32 scrollBar(UiState *uiState, AssetManager *assetManager, | ||||
| 	renderer_staticRect(renderer, sliderPos, sliderSize, V2(0, 0), 0, renderTex, | ||||
| 	                    sliderColor); | ||||
| 
 | ||||
| 	if (uiState->kbdItem == id) | ||||
| 	{ | ||||
| 		switch (uiState->keyEntered) | ||||
| 		{ | ||||
| 		case keycode_space: | ||||
| 			uiState->kbdItem = 0; | ||||
| 			if (uiState->keyMod == keycode_leftShift) | ||||
| 				uiState->kbdItem = uiState->lastWidget; | ||||
| 
 | ||||
| 			// Clear key state so next widget doesn't auto grab
 | ||||
| 			uiState->keyEntered = keycode_null; | ||||
| 			break; | ||||
| 		case keycode_up: | ||||
| 			// TODO(doyle): Fix input for this to work, i.e. proper rate limited input poll
 | ||||
| 			if (*value < maxValue) | ||||
| 			{ | ||||
| 				(*value)++; | ||||
| 				return 1; | ||||
| 			} | ||||
| 		case keycode_down: | ||||
| 			if (*value > 0) | ||||
| 			{ | ||||
| 				(*value)--; | ||||
| 				return 1; | ||||
| 			} | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	uiState->lastWidget = id; | ||||
| 
 | ||||
| 	if (uiState->activeItem == id) | ||||
| 	{ | ||||
| 		f32 mouseYRelToRect = input.mouseP.y - scrollBarRect.pos.y; | ||||
| @ -1012,6 +1080,103 @@ INTERNAL i32 scrollBar(UiState *uiState, AssetManager *assetManager, | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| INTERNAL i32 textField(UiState *const uiState, MemoryArena *arena, | ||||
|                        AssetManager *const assetManager, | ||||
|                        Renderer *const renderer, Font *const font, | ||||
|                        KeyInput input, const i32 id, v2 pos, | ||||
|                        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)) | ||||
| 	{ | ||||
| 		uiState->hotItem = id; | ||||
| 		if (uiState->activeItem == 0 && input.keys[keycode_mouseLeft]) | ||||
| 		{ | ||||
| 			uiState->activeItem = id; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* If no widget has keyboard focus, take it */ | ||||
| 	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(-4, -4), textRect.pos), | ||||
| 		                    v2_add(V2(16, 16), textRect.size), V2(0, 0), 0, | ||||
| 		                    renderTex, V4(1.0f, 0, 0, 1)); | ||||
| 	} | ||||
| 
 | ||||
| 	// Render
 | ||||
| 	renderer_staticRect(renderer, textRect.pos, textRect.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, | ||||
| 		                    renderTex, V4(0.75f, 0.75f, 0.0f, 1)); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		renderer_staticRect(renderer, textRect.pos, textRect.size, V2(0, 0), 0, | ||||
| 		                    renderTex, V4(0.5f, 0.5f, 0.5f, 1)); | ||||
| 	} | ||||
| 
 | ||||
| 	renderer_staticString(renderer, arena, font, string, textRect.pos, V2(0, 0), | ||||
| 	                      0, V4(0, 0, 0, 1)); | ||||
| 
 | ||||
| 	if (uiState->kbdItem == id) | ||||
| 	{ | ||||
| 		switch (uiState->keyEntered) | ||||
| 		{ | ||||
| 		case keycode_space: | ||||
| 			uiState->kbdItem = 0; | ||||
| 			if (uiState->keyMod == keycode_leftShift) | ||||
| 				uiState->kbdItem = uiState->lastWidget; | ||||
| 
 | ||||
| 			uiState->keyEntered = keycode_null; | ||||
| 			break; | ||||
| 
 | ||||
| 		case keycode_backspace: | ||||
| 			if (strLen > 0) | ||||
| 			{ | ||||
| 				strLen--; | ||||
| 				string[strLen] = 0; | ||||
| 				changed        = TRUE; | ||||
| 			} | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		if (uiState->keyChar >= keycode_space && | ||||
| 		    uiState->keyChar <= keycode_Z && strLen < 30) | ||||
| 		{ | ||||
| 			string[strLen++] = uiState->keyChar; | ||||
| 			string[strLen] = 0; | ||||
| 			changed = TRUE; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (!input.keys[keycode_mouseLeft] && | ||||
| 	    uiState->hotItem == id && | ||||
| 	    uiState->activeItem == id) | ||||
| 	{ | ||||
| 		uiState->kbdItem = id; | ||||
| 	} | ||||
| 
 | ||||
| 	uiState->lastWidget = id; | ||||
| 	return changed; | ||||
| } | ||||
| 
 | ||||
| void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt) | ||||
| { | ||||
| 	if (dt >= 1.0f) dt = 1.0f; | ||||
| @ -1276,12 +1441,22 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt) | ||||
| 
 | ||||
| 	LOCAL_PERSIST i32 scrollValue = 30; | ||||
| 	Rect scrollRectA = {V2(900, 500), V2(16, 255)}; | ||||
| 	scrollBar(&state->uiState, assetManager, renderer, state->input, 3, | ||||
| 	scrollBar(&state->uiState, assetManager, renderer, state->input, 4, | ||||
| 	          scrollRectA, &scrollValue, 160); | ||||
| 
 | ||||
| 	LOCAL_PERSIST char fieldString[80] = "Hello world"; | ||||
| 	textField(&state->uiState, &state->arena, assetManager, renderer, font, | ||||
| 	          state->input, 5, V2(1000, 500), fieldString); | ||||
| 
 | ||||
| 	// RESET IMGUI
 | ||||
| 	if (!state->input.mouseLeft)             state->uiState.activeItem = 0; | ||||
| 	else if (state->uiState.activeItem == 0) state->uiState.activeItem = -1; | ||||
| 	if (!state->input.keys[keycode_mouseLeft]) | ||||
| 		state->uiState.activeItem = 0; | ||||
| 	else if (state->uiState.activeItem == 0) | ||||
| 		state->uiState.activeItem = -1; | ||||
| 
 | ||||
| 	if (state->uiState.keyEntered == keycode_space) state->uiState.kbdItem = 0; | ||||
| 	state->uiState.keyEntered = keycode_null; | ||||
| 	state->uiState.keyChar    = keycode_null; | ||||
| 
 | ||||
| 	/* Draw hero avatar */ | ||||
| 	TexAtlas *heroAtlas  = asset_getTextureAtlas(assetManager, texlist_hero); | ||||
|  | ||||
| @ -24,24 +24,33 @@ INTERNAL void keyCallback(GLFWwindow *window, int key, int scancode, int action, | ||||
| 	switch (key) | ||||
| 	{ | ||||
| 	case GLFW_KEY_UP: | ||||
| 		processKey(&game->input.up, key, action); | ||||
| 		processKey(&game->input.keys[keycode_up], key, action); | ||||
| 		break; | ||||
| 	case GLFW_KEY_DOWN: | ||||
| 		processKey(&game->input.down, key, action); | ||||
| 		processKey(&game->input.keys[keycode_down], key, action); | ||||
| 		break; | ||||
| 	case GLFW_KEY_LEFT: | ||||
| 		processKey(&game->input.left, key, action); | ||||
| 		processKey(&game->input.keys[keycode_left], key, action); | ||||
| 		break; | ||||
| 	case GLFW_KEY_RIGHT: | ||||
| 		processKey(&game->input.right, key, action); | ||||
| 		break; | ||||
| 	case GLFW_KEY_SPACE: | ||||
| 		processKey(&game->input.space, key, action); | ||||
| 		processKey(&game->input.keys[keycode_right], key, action); | ||||
| 		break; | ||||
| 	case GLFW_KEY_LEFT_SHIFT: | ||||
| 		processKey(&game->input.leftShift, key, action); | ||||
| 		processKey(&game->input.keys[keycode_leftShift], key, action); | ||||
| 		break; | ||||
| 	case GLFW_KEY_ENTER: | ||||
| 		processKey(&game->input.keys[keycode_enter], key, action); | ||||
| 		break; | ||||
| 	case GLFW_KEY_BACKSPACE: | ||||
| 		processKey(&game->input.keys[keycode_backspace], key, action); | ||||
| 		break; | ||||
| 	default: | ||||
| 		if (key >= ' ' && key <= '~') | ||||
| 		{ | ||||
| 			processKey(&game->input.keys[key - ' '], key, action); | ||||
| 			// TODO(doyle): Temporary
 | ||||
| 			game->uiState.keyChar = key - ' '; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| @ -64,7 +73,7 @@ INTERNAL void mouseButtonCallback(GLFWwindow *window, int button, int action, | ||||
| 	switch(button) | ||||
| 	{ | ||||
| 	case GLFW_MOUSE_BUTTON_LEFT: | ||||
| 		processKey(&game->input.mouseLeft, button, action); | ||||
| 		processKey(&game->input.keys[keycode_mouseLeft], button, action); | ||||
| 		break; | ||||
| 	default: | ||||
| 		break; | ||||
|  | ||||
| @ -7,35 +7,123 @@ | ||||
| /* Forward Declaration */ | ||||
| typedef struct MemoryArena MemoryArena; | ||||
| 
 | ||||
| enum KeyCodes | ||||
| // TODO(doyle): Revise key code system -- should we store the extraneous keys or
 | ||||
| // have a mapping function to map it back to ascii?
 | ||||
| enum KeyCode | ||||
| { | ||||
| 	keycode_space = 0, | ||||
| 	keycode_exclamation, | ||||
| 	keycode_dbl_quotes, | ||||
| 	keycode_hash, | ||||
| 	keycode_dollar, | ||||
| 	keycode_percent, | ||||
| 	keycode_ampersand, | ||||
| 	keycode_single_quote, | ||||
| 	keycode_left_parenthesis, | ||||
| 	keycode_right_parenthesis, | ||||
| 	keycode_star, | ||||
| 	keycode_plus, | ||||
| 	keycode_comma, | ||||
| 	keycode_minus, | ||||
| 	keycode_hyphen, | ||||
| 	keycode_dot, | ||||
| 	keycode_forward_slash, | ||||
| 	keycode_0, | ||||
| 	keycode_1, | ||||
| 	keycode_2, | ||||
| 	keycode_3, | ||||
| 	keycode_4, | ||||
| 	keycode_5, | ||||
| 	keycode_6, | ||||
| 	keycode_7, | ||||
| 	keycode_8, | ||||
| 	keycode_9, | ||||
| 	keycode_colon, | ||||
| 	keycode_semi_colon, | ||||
| 	keycode_left_angle_bracket, | ||||
| 	keycode_equal, | ||||
| 	keycode_right_angle_bracket, | ||||
| 	keycode_question_mark, | ||||
| 	keycode_at, | ||||
| 	keycode_A, | ||||
| 	keycode_B, | ||||
| 	keycode_C, | ||||
| 	keycode_D, | ||||
| 	keycode_E, | ||||
| 	keycode_F, | ||||
| 	keycode_G, | ||||
| 	keycode_H, | ||||
| 	keycode_I, | ||||
| 	keycode_J, | ||||
| 	keycode_K, | ||||
| 	keycode_L, | ||||
| 	keycode_M, | ||||
| 	keycode_N, | ||||
| 	keycode_O, | ||||
| 	keycode_P, | ||||
| 	keycode_Q, | ||||
| 	keycode_R, | ||||
| 	keycode_S, | ||||
| 	keycode_T, | ||||
| 	keycode_U, | ||||
| 	keycode_V, | ||||
| 	keycode_W, | ||||
| 	keycode_X, | ||||
| 	keycode_Y, | ||||
| 	keycode_Z, | ||||
| 	keycode_left_square_bracket, | ||||
| 	keycode_back_slash, | ||||
| 	keycode_right_square_bracket, | ||||
| 	keycode_up_hat, | ||||
| 	keycode_underscore, | ||||
| 	keycode_alt_tilda, | ||||
| 	keycode_a, | ||||
| 	keycode_b, | ||||
| 	keycode_c, | ||||
| 	keycode_d, | ||||
| 	keycode_e, | ||||
| 	keycode_f, | ||||
| 	keycode_g, | ||||
| 	keycode_h, | ||||
| 	keycode_i, | ||||
| 	keycode_j, | ||||
| 	keycode_k, | ||||
| 	keycode_l, | ||||
| 	keycode_m, | ||||
| 	keycode_n, | ||||
| 	keycode_o, | ||||
| 	keycode_p, | ||||
| 	keycode_q, | ||||
| 	keycode_r, | ||||
| 	keycode_s, | ||||
| 	keycode_t, | ||||
| 	keycode_u, | ||||
| 	keycode_v, | ||||
| 	keycode_w, | ||||
| 	keycode_x, | ||||
| 	keycode_y, | ||||
| 	keycode_z, | ||||
| 	keycode_left_squiggly_bracket, | ||||
| 	keycode_pipe, | ||||
| 	keycode_right_squiggly_bracket, | ||||
| 	keycode_tilda, | ||||
| 	keycode_up, | ||||
| 	keycode_down, | ||||
| 	keycode_left, | ||||
| 	keycode_right, | ||||
| 	keycode_space, | ||||
| 	keycode_leftShift, | ||||
| 	keycode_mouseLeft, | ||||
| 	keycode_enter, | ||||
| 	keycode_count, | ||||
| 	keycode_backspace, | ||||
| 	keycode_tab, | ||||
| 	keycode_null, | ||||
| }; | ||||
| 
 | ||||
| typedef struct KeyInput | ||||
| { | ||||
| 	v2 mouseP; | ||||
| 	union | ||||
| 	{ | ||||
| 		b32 keys[keycode_count - 1]; | ||||
| 		struct | ||||
| 		{ | ||||
| 			b32 up; | ||||
| 			b32 down; | ||||
| 			b32 left; | ||||
| 			b32 right; | ||||
| 			b32 space; | ||||
| 			b32 leftShift; | ||||
| 			b32 mouseLeft; | ||||
| 		}; | ||||
| 	}; | ||||
| 	b32 keys[keycode_count - 1]; | ||||
| } KeyInput; | ||||
| 
 | ||||
| typedef struct PlatformFileRead | ||||
|  | ||||
| @ -19,8 +19,9 @@ typedef struct UiState | ||||
| 	i32 activeItem; | ||||
| 
 | ||||
| 	i32 kbdItem; | ||||
| 	i32 keyEntered; | ||||
| 	i32 keyMod; | ||||
| 	enum KeyCode keyEntered; | ||||
| 	enum KeyCode keyMod; | ||||
| 	enum KeyCode keyChar; | ||||
| 
 | ||||
| 	i32 lastWidget; | ||||
| } UiState; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user