diff --git a/include/dawn/dawn.h b/include/dawn/dawn.h index 7353e915..93c6400e 100644 --- a/include/dawn/dawn.h +++ b/include/dawn/dawn.h @@ -70,15 +70,16 @@ // User Interface Objects +#include "ui/align.h" +#include "ui/frame.h" +#include "ui/framedtextmenu.h" #include "ui/grid.h" +#include "ui/image.h" #include "ui/label.h" #include "ui/menuv2.h" #include "ui/rectangle.h" #include "ui/textmenu.h" -#include "ui/align.h" -#include "ui/frame.h" -#include "ui/image.h" #include "ui/menu.h" #include "ui/menulist.h" diff --git a/include/dawn/ui/framedtextmenu.h b/include/dawn/ui/framedtextmenu.h new file mode 100644 index 00000000..60909a87 --- /dev/null +++ b/include/dawn/ui/framedtextmenu.h @@ -0,0 +1,15 @@ +// Copyright (c) 2021 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "../libs.h" +#include "frame.h" +#include "textmenu.h" + +typedef struct { + frame_t frame; + textmenu_t menu; + float width, height; +} framedtextmenu_t; \ No newline at end of file diff --git a/include/dawn/ui/menuv2.h b/include/dawn/ui/menuv2.h index 7b74775b..50183cd1 100644 --- a/include/dawn/ui/menuv2.h +++ b/include/dawn/ui/menuv2.h @@ -7,6 +7,7 @@ #pragma once #include "../libs.h" +#include "grid.h" /** Generic callback for menu events */ typedef void menuv2callback_t(void *user, uint8_t i); diff --git a/src/display/font.c b/src/display/font.c index 2485189c..b0781a22 100644 --- a/src/display/font.c +++ b/src/display/font.c @@ -82,7 +82,7 @@ void fontTextClamp(font_t *font, fonttextinfo_t *info, char *text, scale = fontGetScale(fontSize); // Adjust the max width to match the scale, and allow "no max width". - maxWidth = maxWidth == -1 ? 999999 : maxWidth * (1 / scale); + maxWidth = maxWidth == -1 ? 9999999 : maxWidth * (1 / scale); /** Which index in the original text var is the current word from */ int32_t wordStart = 0; @@ -145,7 +145,8 @@ void fontTextClamp(font_t *font, fonttextinfo_t *info, char *text, ); // Now measure the width of the line (take the right side of that quad) - if(x > maxWidth) { + // if(x > maxWidth) { + if(quad->x1 > maxWidth) { // We've exceeded the edge, go back to the start of the word and newline. x = quad->x1 - wordX; for(j = wordStart; j <= info->realLength; j++) { @@ -189,6 +190,8 @@ void fontTextClamp(font_t *font, fonttextinfo_t *info, char *text, info->width = mathMax(info->width, quad->x1); info->height = mathMax(info->height, quad->y1); } + + printf("Break"); } int32_t fontGetLineCharCount(fonttextinfo_t *info,int32_t start,int32_t count) { diff --git a/src/game/sandbox/sandboxscene.c b/src/game/sandbox/sandboxscene.c index ce54c07a..4d8ee7ea 100644 --- a/src/game/sandbox/sandboxscene.c +++ b/src/game/sandbox/sandboxscene.c @@ -7,7 +7,7 @@ #include "sandboxscene.h" -textmenu_t menu; +framedtextmenu_t menu; bool sandboxSceneInit(sandboxscene_t *game) { assetFontLoad(&game->font, "fonts/opensans/OpenSans-Regular.ttf"); @@ -15,16 +15,16 @@ bool sandboxSceneInit(sandboxscene_t *game) { assetShaderLoad(&game->shader, "shaders/textured.vert", "shaders/textured.frag" ); + + framedTextMenuInit(&menu, &game->font, &game->texture); + + gridAddBreakpoint(&menu.menu.menu.grid, -1, 3, 1, 0, 0); - textMenuInit(&menu, &game->font); - gridAddBreakpoint(&menu.menu.grid, -1, 3, 1, 0, 0); - gridchild_t *child = textMenuListAdd(&menu, "First"); + gridchild_t *child = textMenuListAdd(&menu.menu, "First"); gridChildAddBreakpoint(child, 0,0, 1,1); - - child = textMenuListAdd(&menu, "Second"); + child = textMenuListAdd(&menu.menu, "Second"); gridChildAddBreakpoint(child, 0,1, 1,1); - - child = textMenuListAdd(&menu, "Third"); + child = textMenuListAdd(&menu.menu, "Third"); gridChildAddBreakpoint(child, 0,2, 1,1); return true; @@ -46,13 +46,10 @@ void sandboxSceneUpdate(sandboxscene_t *game, engine_t *engine) { shaderUseCamera(&game->shader, &game->camera); shaderUseTexture(&game->shader, &game->texture); - gridSetSize(&menu.menu.grid, - engine->render.width, engine->render.height, - 100.0f, FONT_LINE_HEIGHT * fontGetScale(16.0f) * 3, - 0, 0 - ); - menu2Update(&menu.menu, engine); - textMenuListRender(&menu, &game->shader, 0, 0); + float x, y; + + framedTextMenuUpdate(&menu, engine); + framedTextMenuRender(&menu, &game->shader, 0, 0); } void sandboxSceneDispose(sandboxscene_t *game) { diff --git a/src/game/sandbox/sandboxscene.h b/src/game/sandbox/sandboxscene.h index df5c871c..788f251a 100644 --- a/src/game/sandbox/sandboxscene.h +++ b/src/game/sandbox/sandboxscene.h @@ -20,6 +20,7 @@ #include "../../ui/grid.h" #include "../../ui/menuv2.h" #include "../../ui/textmenu.h" +#include "../../ui/framedtextmenu.h" /** * Initialize the sandbox scene test game. diff --git a/src/ui/framedtextmenu.c b/src/ui/framedtextmenu.c new file mode 100644 index 00000000..e340a7a2 --- /dev/null +++ b/src/ui/framedtextmenu.c @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2021 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "framedtextmenu.h" + +void framedTextMenuInit(framedtextmenu_t *menu, font_t *font, texture_t *text) { + frameInit(&menu->frame); + textMenuInit(&menu->menu, font); + menu->frame.texture = text; + + menu->width = -1; + menu->height = -1; +} + +void framedTextMenuUpdate(framedtextmenu_t *menu, engine_t *engine) { + float iw, ih; + uint8_t bp; + gridbreakpoint_t *breakpoint; + + bp = gridGetBreakpoint(&menu->menu.menu.grid, engine->render.width); + breakpoint = menu->menu.menu.grid.breakpoints + bp; + + if(menu->width < 0) { + if(menu->menu.menu.grid.childCount > 0) { + iw = 0; + for(uint8_t i = 0; i < menu->menu.menu.grid.childCount; i++) { + iw = mathMax(menu->menu.labels[i].info.width, iw); + } + iw *= breakpoint->columns; + if(iw == 0) iw = engine->render.width - FRAME_BORDER_SIZE_FULL; + } else { + iw = engine->render.width - FRAME_BORDER_SIZE_FULL; + } + } else { + iw = menu->width - FRAME_BORDER_SIZE_FULL; + } + + if(menu->height < 0) { + if(menu->menu.menu.grid.childCount > 0) { + ih = breakpoint->rows * ( + fontGetScale(menu->menu.labels->fontSize) * FONT_LINE_HEIGHT + ); + } else { + ih = 0; + } + } else { + ih = menu->height - FRAME_BORDER_SIZE_FULL; + } + + frameSetInnerSize(&menu->frame, iw, ih); + gridSetSize(&menu->menu.menu.grid, + engine->render.width, engine->render.height, + iw, ih, + 0, 0 + ); + menu2Update(&menu->menu.menu, engine); +} + +void framedTextMenuRender( + framedtextmenu_t *menu, shader_t *shader, float x, float y +) { + frameRender(&menu->frame, shader, x, y); + textMenuListRender(&menu->menu, shader, + x + FRAME_BORDER_SIZE, y + FRAME_BORDER_SIZE + ); +} + +void framedTextMenuDispose(framedtextmenu_t *menu) { + textMenuDispse(&menu->menu); + frameDispose(&menu->frame); +} \ No newline at end of file diff --git a/src/ui/framedtextmenu.h b/src/ui/framedtextmenu.h new file mode 100644 index 00000000..d986a004 --- /dev/null +++ b/src/ui/framedtextmenu.h @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2021 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include +#include "frame.h" +#include "textmenu.h" +#include "grid.h" + +/** + * Initialize a framed text ui element. + * + * @param menu Menu to initialize. + * @param font Font to use for the text. + * @param text Texture for the frame. + */ +void framedTextMenuInit(framedtextmenu_t *menu, font_t *font, texture_t *text); + +/** + * Update a framed text menu ui element. + * + * @param menu Menu to update. + * @param engine Engine to use while updating. + */ +void framedTextMenuUpdate(framedtextmenu_t *menu, engine_t *engine); + +/** + * Render a framed text menu. + * + * @param menu Menu to render. + * @param shader Shader to use. + * @param x X Position. + * @param y Y Position. + */ +void framedTextMenuRender( + framedtextmenu_t *menu, shader_t *shader, float x, float y +); + +/** + * Dispose a previously created framed text menu. + * + * @param menu Menu to dispose. + */ +void framedTextMenuDispose(framedtextmenu_t *menu); \ No newline at end of file diff --git a/src/ui/grid.c b/src/ui/grid.c index dc53a17a..19c19465 100644 --- a/src/ui/grid.c +++ b/src/ui/grid.c @@ -59,6 +59,15 @@ gridchildbreakpoint_t * gridChildGetBreakpoint(gridchild_t *child, uint8_t bp) { ); } +uint8_t gridGetBreakpoint(grid_t *grid, float screenWidth) { + uint8_t i; + for(i = 0; i < grid->breakpointCount; i++) { + if(grid->breakpointSizes[i].width < screenWidth) continue; + return i; + } + return grid->breakpointCount - 1; +} + void gridSetSize(grid_t *grid, float screenWidth, float screenHeight, float width, float height, @@ -80,12 +89,7 @@ void gridSetSize(grid_t *grid, grid->height = height; // Determine breakpoint - breakpoint = 0xFF; - for(i = 0; i < grid->breakpointCount; i++) { - if(grid->breakpointSizes[i].width < screenWidth) continue; - breakpoint = i; - } - if(breakpoint == 0xFF) breakpoint = grid->breakpointCount - 1; + breakpoint = gridGetBreakpoint(grid, screenWidth); gridbp = grid->breakpoints + breakpoint; grid->breakpointCurrent = breakpoint; diff --git a/src/ui/grid.h b/src/ui/grid.h index d66e7aa1..eda7a21d 100644 --- a/src/ui/grid.h +++ b/src/ui/grid.h @@ -55,6 +55,15 @@ uint8_t gridChildAddBreakpoint(gridchild_t *child, uint8_t x, uint8_t y, uint8_t columns, uint8_t rows ); +/** + * Get the breakpoint (index) from a grid and screen width. + * + * @param grid Grid to get from. + * @param screenWidth Screen width to use. + * @return Grid index. + */ +uint8_t gridGetBreakpoint(grid_t *grid, float screenWidth); + /** * Retreive the breakpoint to use for a child. Takes missing breakpoints into * consideration. diff --git a/src/ui/textmenu.c b/src/ui/textmenu.c index f0f9bf68..0414a8a5 100644 --- a/src/ui/textmenu.c +++ b/src/ui/textmenu.c @@ -28,7 +28,7 @@ void _textMenuOnResize( info->y = y; info->width = width; info->height = height; - label->maxWidth = width; + label->maxWidth = width <= 0 ? -1 : width; labelSetText(label, textMenu->font, textMenu->texts[i]); } @@ -59,7 +59,7 @@ void textMenuListRender(textmenu_t *menu, shader_t *shader, float x, float y) { info = menu->labelInfo + menu->menu.selected; menu->rectangle.width = info->width; menu->rectangle.height = info->height; - rectangleRender(&menu->rectangle, shader, info->x, info->y); + rectangleRender(&menu->rectangle, shader, x + info->x, y + info->y); for(i = 0; i < menu->menu.grid.childCount; i++) { label = menu->labels + i;