diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bd00ee2..af4c4e6b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ set(SETTING_GAME_POKER 1) set(SETTING_GAME_DAWN 2) set(SETTING_GAME_SANDBOX 3) -set(SETTING_GAME SETTING_GAME_POKER) +set(SETTING_GAME SETTING_GAME_SANDBOX) set(SETTING_GAME_NAME "DawnGame") ################################## Targets ##################################### diff --git a/include/dawn/game/sandbox/sandboxscene.h b/include/dawn/game/sandbox/sandboxscene.h index d648ee2b..d6f447aa 100644 --- a/include/dawn/game/sandbox/sandboxscene.h +++ b/include/dawn/game/sandbox/sandboxscene.h @@ -14,12 +14,6 @@ #include "../../display/renderlist.h" #include "../../display/texture.h" -#define GRID_BRUH_COUNT 1 - -typedef struct { - float x, y, width, height; -} gridbruh_t; - typedef struct { camera_t camera; @@ -27,6 +21,4 @@ typedef struct { texture_t texture; shader_t shader; font_t font; - - gridbruh_t items[GRID_BRUH_COUNT]; } sandboxscene_t; \ No newline at end of file diff --git a/include/dawn/ui/framedtextmenu.h b/include/dawn/ui/framedtextmenu.h index 60909a87..0fc579be 100644 --- a/include/dawn/ui/framedtextmenu.h +++ b/include/dawn/ui/framedtextmenu.h @@ -8,8 +8,10 @@ #include "frame.h" #include "textmenu.h" +/** The default gutter for the grid of a framed text menu */ +#define FRAMED_TEXT_MENU_GUTTER_DEFAULT 8.0f + 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/grid.h b/include/dawn/ui/grid.h index 55100c60..c2b5526d 100644 --- a/include/dawn/ui/grid.h +++ b/include/dawn/ui/grid.h @@ -8,68 +8,33 @@ #pragma once #include "../libs.h" -/** Maximum number of breakpoints a grid can support */ -#define GRID_BREAKPOINT_COUNT 4 +/** Maximum number of columns a grid can have */ +#define GRID_COLUMN_COUNT_MAX 16 +/** Maximum number of rows a grid can have */ +#define GRID_ROW_COUNT_MAX GRID_COLUMN_COUNT_MAX -/** Max number of children that a grid can support */ -#define GRID_CHILD_COUNT 32 - -/** Definition of a breakpoint */ -typedef struct { - float width; -} breakpointsize_t; - -/** Definition of a grid breakpoint */ -typedef struct { - uint8_t rows; - uint8_t columns; - float gutterX; - float gutterY; -} gridbreakpoint_t; - -/** Definition of a grid child's breakpoint */ -typedef struct { - uint8_t columns; - uint8_t rows; - uint8_t x; - uint8_t y; -} gridchildbreakpoint_t; - -/** Callback to receive when a grid child is to be resized */ -typedef void gridchildresizecallback_t( - void *user, uint8_t i, gridchildbreakpoint_t *breakpoint, - float screenWidth, float screenHeight, - float x, float y, - float width, float height -); - -/** Definition of a grid child */ -typedef struct { - gridchildbreakpoint_t breakpoints[GRID_BREAKPOINT_COUNT]; - uint8_t breakpointCount; -} gridchild_t; +/** Cell size for "auto", basically to fill the remaining space evenly */ +#define GRID_CEL_SIZE_AUTO -1 /** Definitio of a grid */ typedef struct { - /** Breakpoints */ - gridbreakpoint_t breakpoints[GRID_BREAKPOINT_COUNT]; - breakpointsize_t breakpointSizes[GRID_BREAKPOINT_COUNT]; - uint8_t breakpointCount; - uint8_t breakpointCurrent; + /** Count of columns/rows in the grid */ + uint8_t columns, rows; - /** Child items of the grid */ - gridchild_t children[GRID_CHILD_COUNT]; - uint8_t childCount; + /** Cell Definitions, used to control how the cells will size themselves */ + float columnDefinitions[GRID_COLUMN_COUNT_MAX]; + float rowDefinitions[GRID_COLUMN_COUNT_MAX]; + + /** Settings to control gutters (space between cells) and border (of grid) */ + float gutterX, gutterY; + float borderX, borderY; - /** Internal size reference, used for caching resize events */ - float width; - float height; - float x; - float y; + /** Calculated sizes and positions for each cell */ + float columnSizes[GRID_COLUMN_COUNT_MAX]; + float columnPositions[GRID_COLUMN_COUNT_MAX]; + float rowSizes[GRID_ROW_COUNT_MAX]; + float rowPositions[GRID_COLUMN_COUNT_MAX]; - /** Pointer to any custom user data */ - void *user; - - /** Callback to listen for when children are resized */ - gridchildresizecallback_t *onResize; + /** Cached size of the grid */ + float width, height; } grid_t; \ No newline at end of file diff --git a/include/dawn/ui/menu.h b/include/dawn/ui/menu.h index e3313796..27f4b548 100644 --- a/include/dawn/ui/menu.h +++ b/include/dawn/ui/menu.h @@ -7,17 +7,27 @@ #pragma once #include "../libs.h" -#include "grid.h" -/** Generic callback for menu events */ +/** The maximum number of items a menu can hold */ +#define MENU_ITEMS_MAX 32 + +/** Callback for when menu events are fired. */ typedef void menucallback_t(void *user, uint8_t i); -/** Structure for a menu */ typedef struct { - grid_t grid; + uint8_t x; + uint8_t y; + uint8_t width; + uint8_t height; +} menuitem_t; + +typedef struct { + menuitem_t items[MENU_ITEMS_MAX]; + uint8_t itemCount; uint8_t selected; uint8_t cursorX; uint8_t cursorY; + void *user; menucallback_t *onSelect; -} menu_t; +} menu_t; \ No newline at end of file diff --git a/include/dawn/ui/textmenu.h b/include/dawn/ui/textmenu.h index 32fb865e..011ba33f 100644 --- a/include/dawn/ui/textmenu.h +++ b/include/dawn/ui/textmenu.h @@ -11,23 +11,20 @@ #include "label.h" #include "rectangle.h" +/** Colour of the selection box for the text menu */ #define TEXTMENU_SELECTION_COLOR ((pixel_t){.r=0xFF,.g=0xFF,.b=0xFF,.a=0x64}) +/** Callback type for when an item is selected */ typedef void textmenucallback_t(void *user, uint8_t i, char *text); -typedef struct { - float x, y; - float width, height; -} textmenulabelinfo_t; - typedef struct { menu_t menu; - char *texts[GRID_CHILD_COUNT]; - + grid_t grid; font_t *font; - label_t labels[GRID_CHILD_COUNT]; rectangle_t rectangle; - textmenulabelinfo_t labelInfo[GRID_CHILD_COUNT]; + + char *texts[MENU_ITEMS_MAX]; + label_t labels[MENU_ITEMS_MAX]; textmenucallback_t *onSelect; void *user; diff --git a/src/game/poker/ui/pokerplayerui.c b/src/game/poker/ui/pokerplayerui.c index ab78e978..2a340cc5 100644 --- a/src/game/poker/ui/pokerplayerui.c +++ b/src/game/poker/ui/pokerplayerui.c @@ -8,8 +8,7 @@ #include "pokerplayerui.h" void pokerPlayerUiInit(pokerplayerui_t *ui) { - gridchild_t *child; - + gridInit(&ui->grid); labelInit(&ui->label); frameBufferInit(&ui->frame, POKER_PLAYER_UI_IMAGE_RESOLUTION, POKER_PLAYER_UI_IMAGE_RESOLUTION @@ -19,21 +18,6 @@ void pokerPlayerUiInit(pokerplayerui_t *ui) { POKER_PLAYER_UI_IMAGE_SIZE, POKER_PLAYER_UI_IMAGE_SIZE, 1, 0 ); - // Grid - gridInit(&ui->grid); - gridAddBreakpoint(&ui->grid, -1, 2, 2, POKER_PLAYER_UI_PADDING, 0); - - // Player UI Image - child = gridAddChild(&ui->grid); - gridChildAddBreakpoint(child, 1,0, 1,2); - - // Chips - child = gridAddChild(&ui->grid); - gridChildAddBreakpoint(child, 0,0, 1,1); - - // Title. - child = gridAddChild(&ui->grid); - gridChildAddBreakpoint(child, 0,1, 1,1); } void pokerPlayerUiUpdate( @@ -99,51 +83,51 @@ void pokerPlayerUiRender( engine->render.width, engine->render.height, POKER_PLAYER_UI_IMAGE_SIZE*2, POKER_PLAYER_UI_IMAGE_SIZE, -1, -1 ); - gridSetSize( - &ui->grid, engine->render.width, engine->render.height, - align.width, align.height, - align.x + x, align.y + y - ); + // gridSetSize( + // &ui->grid, engine->render.width, engine->render.height, + // align.width, align.height, + // align.x + x, align.y + y + // ); - // Render face - gridGetChildSize(&ui->grid, ui->grid.breakpointCurrent, ui->grid.children+0, - &sCol, &sRow, &gx, &gy, &gw, &gh - ); - shaderUseTexture(shader, &ui->frame.texture); - shaderUsePosition(shader, gx, gy, 0, 0,0,0); - primitiveDraw(&ui->quad, 0, -1); + // // Render face + // gridGetChildSize(&ui->grid, ui->grid.breakpointCurrent, ui->grid.children+0, + // &sCol, &sRow, &gx, &gy, &gw, &gh + // ); + // shaderUseTexture(shader, &ui->frame.texture); + // shaderUsePosition(shader, gx, gy, 0, 0,0,0); + // primitiveDraw(&ui->quad, 0, -1); - // Render chips - sprintf(buffer, "$%i", player->chips); - ui->label.maxWidth = -1; - labelSetText(&ui->label, font, buffer); - align = gridAlignChild( - &ui->grid, ui->grid.breakpointCurrent, ui->grid.children + 1, &sCol, &sRow, - ALIGN_POS_END | ALIGN_SIZE_ORIGINAL, ALIGN_POS_CENTER | ALIGN_SIZE_ORIGINAL, - ui->label.info.width, ui->label.info.height - ); - labelRender(&ui->label, shader, align.x, align.y); + // // Render chips + // sprintf(buffer, "$%i", player->chips); + // ui->label.maxWidth = -1; + // labelSetText(&ui->label, font, buffer); + // align = gridAlignChild( + // &ui->grid, ui->grid.breakpointCurrent, ui->grid.children + 1, &sCol, &sRow, + // ALIGN_POS_END | ALIGN_SIZE_ORIGINAL, ALIGN_POS_CENTER | ALIGN_SIZE_ORIGINAL, + // ui->label.info.width, ui->label.info.height + // ); + // labelRender(&ui->label, shader, align.x, align.y); - // Render state - if(player->state & POKER_PLAYER_STATE_OUT) { - sprintf(buffer, "Out"); - } else if(player->state & POKER_PLAYER_STATE_FOLDED) { - sprintf(buffer, "Folded"); - } else if(player->state & POKER_PLAYER_STATE_SHOWING) { - sprintf(buffer, "Showing"); - } else if(game->poker.bet.better == playerIndex) { - sprintf(buffer, "Thinking"); - } else { - sprintf(buffer, "Whatever"); - } - labelSetText(&ui->label, font, buffer); - align = gridAlignChild( - &ui->grid, ui->grid.breakpointCurrent, ui->grid.children + 2, &sCol, &sRow, - ALIGN_POS_END | ALIGN_SIZE_ORIGINAL, ALIGN_POS_CENTER | ALIGN_SIZE_ORIGINAL, - ui->label.info.width, ui->label.info.height - ); - labelRender(&ui->label, shader, align.x, align.y); + // // Render state + // if(player->state & POKER_PLAYER_STATE_OUT) { + // sprintf(buffer, "Out"); + // } else if(player->state & POKER_PLAYER_STATE_FOLDED) { + // sprintf(buffer, "Folded"); + // } else if(player->state & POKER_PLAYER_STATE_SHOWING) { + // sprintf(buffer, "Showing"); + // } else if(game->poker.bet.better == playerIndex) { + // sprintf(buffer, "Thinking"); + // } else { + // sprintf(buffer, "Whatever"); + // } + // labelSetText(&ui->label, font, buffer); + // align = gridAlignChild( + // &ui->grid, ui->grid.breakpointCurrent, ui->grid.children + 2, &sCol, &sRow, + // ALIGN_POS_END | ALIGN_SIZE_ORIGINAL, ALIGN_POS_CENTER | ALIGN_SIZE_ORIGINAL, + // ui->label.info.width, ui->label.info.height + // ); + // labelRender(&ui->label, shader, align.x, align.y); } void pokerPlayerUiDispose(pokerplayerui_t *ui) { diff --git a/src/game/sandbox/sandboxscene.c b/src/game/sandbox/sandboxscene.c index 845a3e51..8a545316 100644 --- a/src/game/sandbox/sandboxscene.c +++ b/src/game/sandbox/sandboxscene.c @@ -7,7 +7,7 @@ #include "sandboxscene.h" -framedtextmenu_t menu; +framedtextmenu_t ftm; bool sandboxSceneInit(sandboxscene_t *game) { assetFontLoad(&game->font, "fonts/opensans/OpenSans-Regular.ttf"); @@ -15,19 +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, 2, 3, 0, 0); - gridchild_t *child = textMenuListAdd(&menu.menu, "First"); - gridChildAddBreakpoint(child, 0,0, 1,1); - child = textMenuListAdd(&menu.menu, "Second"); - gridChildAddBreakpoint(child, 0,1, 1,1); - child = textMenuListAdd(&menu.menu, "Third"); - gridChildAddBreakpoint(child, 0,2, 1,1); - child = textMenuListAdd(&menu.menu, "Fourth"); - gridChildAddBreakpoint(child, 1,0, 1,1); + menuitem_t *item; + framedTextMenuInit(&ftm, &game->font, &game->texture); + ftm.menu.grid.rows = 3; + item = textMenuAdd(&ftm.menu, "Option 1"); + item->y = 0; + item = textMenuAdd(&ftm.menu, "Option 2"); + item->y = 1; + item = textMenuAdd(&ftm.menu, "Option 3"); + item->y = 2; return true; } @@ -46,12 +43,10 @@ void sandboxSceneUpdate(sandboxscene_t *game, engine_t *engine) { shaderUse(&game->shader); shaderUseCamera(&game->shader, &game->camera); - shaderUseTexture(&game->shader, &game->texture); - float x, y; - - framedTextMenuUpdate(&menu, engine); - framedTextMenuRender(&menu, &game->shader, 0, 0); + framedTextMenuResize(&ftm, 400, 400); + framedTextMenuUpdate(&ftm, engine); + framedTextMenuRender(&ftm, &game->shader, 0, 0); } void sandboxSceneDispose(sandboxscene_t *game) { diff --git a/src/game/sandbox/sandboxscene.h b/src/game/sandbox/sandboxscene.h index 8b538c8a..bc10d06e 100644 --- a/src/game/sandbox/sandboxscene.h +++ b/src/game/sandbox/sandboxscene.h @@ -22,6 +22,7 @@ #include "../../ui/grid.h" #include "../../ui/menu.h" #include "../../ui/textmenu.h" +#include "../../ui/image.h" #include "../../ui/framedtextmenu.h" /** diff --git a/src/ui/framedtextmenu.c b/src/ui/framedtextmenu.c index 4fa9c773..e21810be 100644 --- a/src/ui/framedtextmenu.c +++ b/src/ui/framedtextmenu.c @@ -11,51 +11,21 @@ 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; + menu->menu.grid.borderX = FRAME_BORDER_SIZE; + menu->menu.grid.borderY = FRAME_BORDER_SIZE; + menu->menu.grid.gutterX = FRAMED_TEXT_MENU_GUTTER_DEFAULT; + menu->menu.grid.gutterY = FRAMED_TEXT_MENU_GUTTER_DEFAULT; +} + +void framedTextMenuResize(framedtextmenu_t *menu, float width, float height) { + if(menu->menu.grid.width == width && menu->menu.grid.height == height) { + return; + } + gridResize(&menu->menu.grid, width, height); + frameSetSize(&menu->frame, width, height); } 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 - ); menuUpdate(&menu->menu.menu, engine); } @@ -63,9 +33,7 @@ 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 - ); + textMenuRender(&menu->menu, shader, x, y); } void framedTextMenuDispose(framedtextmenu_t *menu) { diff --git a/src/ui/framedtextmenu.h b/src/ui/framedtextmenu.h index 96a10c56..a11ed924 100644 --- a/src/ui/framedtextmenu.h +++ b/src/ui/framedtextmenu.h @@ -22,10 +22,19 @@ void framedTextMenuInit(framedtextmenu_t *menu, font_t *font, texture_t *text); /** - * Update a framed text menu ui element. + * Resize a framed text menu. + * + * @param menu Menu to resize. + * @param width Width of the menu. + * @param height Height of the menu. + */ +void framedTextMenuResize(framedtextmenu_t *menu, float width, float height); + +/** + * Update a framed text menu. * * @param menu Menu to update. - * @param engine Engine to use while updating. + * @param engine Engine to use when updating. */ void framedTextMenuUpdate(framedtextmenu_t *menu, engine_t *engine); diff --git a/src/ui/grid.c b/src/ui/grid.c index 2aa291c1..150721fb 100644 --- a/src/ui/grid.c +++ b/src/ui/grid.c @@ -8,180 +8,131 @@ #include "grid.h" void gridInit(grid_t *grid) { - grid->breakpointCount = 0x00; - grid->breakpointCurrent = 0x00; - grid->childCount = 0x00; - grid->width = 0; - grid->height = 0; - grid->onResize = NULL; -} - -uint8_t gridAddBreakpoint( - grid_t *grid, float width, - uint8_t columns, uint8_t rows, - float gutterX, float gutterY -) { - uint8_t i = grid->breakpointCount++; - - grid->breakpoints[i].rows = rows; - grid->breakpoints[i].columns = columns; - grid->breakpoints[i].gutterX = gutterX; - grid->breakpoints[i].gutterY = gutterY; - grid->breakpointSizes[i].width = width; - - return i; -} - -gridchild_t * gridAddChild(grid_t *grid) { - gridchild_t *child = grid->children + grid->childCount++; - child->breakpointCount = 0; - return child; -} - - -uint8_t gridChildAddBreakpoint(gridchild_t *child, - uint8_t x, uint8_t y, uint8_t columns, uint8_t rows -) { uint8_t i; - gridchildbreakpoint_t *bp; - i = child->breakpointCount++; - bp = child->breakpoints + i; - bp->x = x; - bp->y = y; - bp->rows = rows; - bp->columns = columns; - return i; + + grid->columns = 1; + grid->rows = 1; + grid->gutterX = 0; + grid->gutterY = 0; + grid->borderX = 0; + grid->borderY = 0; + grid->width = 1; + grid->height = 1; + + for(i = 0; i < GRID_COLUMN_COUNT_MAX; i++) { + grid->columnDefinitions[i] = GRID_CEL_SIZE_AUTO; + } + for(i = 0; i < GRID_ROW_COUNT_MAX; i++) { + grid->rowDefinitions[i] = GRID_CEL_SIZE_AUTO; + } } -gridchildbreakpoint_t * gridChildGetBreakpoint(gridchild_t *child, uint8_t bp) { - return child->breakpoints + ( - bp >= child->breakpointCount ? child->breakpointCount - 1 : bp +void gridRecalculate(grid_t *grid) { + uint8_t i, countFlexiColumns, countFlexiRows; + float flexiWidth, flexiHeight, s, p, totalFlexiWidth, totalFlexiHeight; + + // Pass 1, determine the "flexible width size" + countFlexiColumns = 0; + countFlexiRows = 0; + totalFlexiWidth = ( + grid->width - + (grid->gutterX * mathMax(grid->columns-1, 0)) - + (grid->borderX * 2.0f) + ); + totalFlexiHeight = ( + grid->height - + (grid->gutterY * mathMax(grid->rows-1, 0)) - + (grid->borderY * 2.0f) ); -} -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, - float x, float y -) { - uint8_t i, breakpoint; - gridbreakpoint_t *gridbp; - float sizeCol, sizeRow, gx, gy, gw, gh; - - // Need to resize? - if( - grid->width == width && grid->height == height && - grid->x == x && grid->y == y - ) { - return; + for(i = 0; i < grid->columns; i++) { + if(grid->columnDefinitions[i] == GRID_CEL_SIZE_AUTO) { + countFlexiColumns++; + } else { + totalFlexiWidth -= grid->columnDefinitions[i]; + } } - // Update properties + for(i = 0; i < grid->rows; i++) { + if(grid->rowDefinitions[i] == GRID_CEL_SIZE_AUTO) { + countFlexiRows++; + } else { + totalFlexiHeight -= grid->rowDefinitions[i]; + } + } + + // Determine the "flexi size for each flexi cell" + flexiWidth = totalFlexiWidth / countFlexiColumns; + flexiHeight = totalFlexiHeight / countFlexiRows; + + // Now set up the positions and sizes for each cell. + p = grid->borderX; + for(i = 0; i < grid->columns; i++) { + s = grid->columnDefinitions[i]; + if(s == GRID_CEL_SIZE_AUTO) s = flexiWidth; + + grid->columnPositions[i] = p; + grid->columnSizes[i] = s; + p += s + grid->gutterX; + } + + p = grid->borderY; + for(i = 0; i < grid->rows; i++) { + s = grid->rowDefinitions[i]; + if(s == GRID_CEL_SIZE_AUTO) s = flexiHeight; + + grid->rowPositions[i] = p; + grid->rowSizes[i] = s; + p += s + grid->gutterY; + } +} + +void gridResize(grid_t *grid, float width, float height) { + if(grid->width == width && grid->height == height) return; grid->width = width; grid->height = height; - grid->x = x; - grid->y = y; - - // Determine breakpoint - breakpoint = gridGetBreakpoint(grid, screenWidth); - gridbp = grid->breakpoints + breakpoint; - grid->breakpointCurrent = breakpoint; - - if(grid->onResize == NULL) return; - - sizeCol = -1; - sizeRow = -1; - - // Resize children - for(i = 0; i < grid->childCount; i++) { - // Get the item and the definition. - - gridGetChildSize( - grid, breakpoint, grid->children + i, - &sizeCol, &sizeRow, &gx, &gy, &gw, &gh - ); - - // Fire the resize event. - grid->onResize( - grid->user, i, gridChildGetBreakpoint(grid->children + i, breakpoint), - screenWidth, screenHeight, - gx, gy, gw, gh - ); - } + gridRecalculate(grid); } -void gridGetChildSize( - grid_t *grid, uint8_t breakpoint, gridchild_t *child, - float *sizeCol, float *sizeRow, +void gridGetChild( + grid_t *grid, uint8_t col, uint8_t row, uint8_t columns, uint8_t rows, float *x, float *y, float *width, float *height ) { - gridchildbreakpoint_t *childbp; - gridbreakpoint_t *gridbp; + uint8_t i; + float s; - gridbp = grid->breakpoints + breakpoint; - - if(*sizeCol < 0) { - *sizeCol = ( - grid->width - (gridbp->gutterX * (gridbp->columns-1)) - ) / gridbp->columns; + // Set positions + *x = grid->columnPositions[col]; + *y = grid->rowPositions[row]; + + // Calculate width. + s = 0; + for(i = col; i < col+columns; i++) { + s += grid->columnSizes[i]; } + *width = s; - if(*sizeRow < 0) { - *sizeRow = ( - grid->height - (gridbp->gutterY * (gridbp->rows - 1)) - ) / gridbp->rows; + // Calculate height + s = 0; + for(i = row; i < row+rows; i++) { + s += grid->rowSizes[i]; } - - childbp = gridChildGetBreakpoint(child, breakpoint); - - *x = (*sizeCol * childbp->x) + (gridbp->gutterX * childbp->x) + grid->x; - *y = (*sizeRow * childbp->y) + (gridbp->gutterY * childbp->y) + grid->y; - - *width = ( - (childbp->columns * *sizeCol) + - (mathMax(childbp->columns - 1, 0) * gridbp->gutterX) - ); - *height = ( - (childbp->rows * *sizeRow) + - (mathMax(childbp->rows - 1, 0) * gridbp->gutterY) - ); + *height = s; } - -align_t gridAlignChild( - grid_t *grid, uint8_t breakpoint, gridchild_t *child, - float *sizeCol, float *sizeRow, - uint8_t alignX, uint8_t alignY, - float width, float height +align_t gridGetAndAlignChild( + grid_t *grid, uint8_t col, uint8_t row, uint8_t columns, uint8_t rows, + uint8_t alignX, uint8_t alignY, float width, float height ) { - float gridWidth, gridHeight, gridX, gridY; - align_t alignment; + float gx, gy, gw, gh; - // Get the child size. - gridGetChildSize( - grid, breakpoint, child, sizeCol, sizeRow, - &gridX, &gridY, &gridWidth, &gridHeight - ); - - if(width == -1) width = gridWidth; - if(height == -1) height = gridHeight; - - // Align the child - alignment = alignmentGet( - alignX, alignY, gridWidth, gridHeight, width, height, -1, -1 - ); - - alignment.x += gridX; - alignment.y += gridY; - - return alignment; + // Get the size of the child first + gridGetChild(grid, col, row, columns, rows, &gx, &gy, &gw, &gh); + + // Now align + align_t align = alignmentGet(alignX, alignY, gw, gh, width, height, -1,-1); + align.x += gx; + align.y += gy; + return align; } \ No newline at end of file diff --git a/src/ui/grid.h b/src/ui/grid.h index 333a61af..eab27fdd 100644 --- a/src/ui/grid.h +++ b/src/ui/grid.h @@ -17,118 +17,54 @@ void gridInit(grid_t *grid); /** - * Adds a breakpoint to a grid system. + * Recalculate the cell size and positions. * - * @param grid Grid to add to. - * @param width Screen dimension width of the breakpoint. - * @param columns How many columns at this breakpoint. - * @param rows How many rows at this breakpoint. - * @param gutterX Gutter X at this breakpoint. - * @param gutterY Gutter Y at this breakpoint. - * @return Index of the breakpoint within the grid. + * @param grid Grid to recalculate for. */ -uint8_t gridAddBreakpoint( - grid_t *grid, float width, - uint8_t columns, uint8_t rows, - float gutterX, float gutterY -); +void gridRecalculate(grid_t *grid); /** - * Add a child to the grid. + * Resize (and recalculate) a grid. * - * @param grid Grid to add the child to. - * @return The grid child item that was added. + * @param grid Grid to resize. + * @param width Width to use. + * @param height Height to use. */ -gridchild_t * gridAddChild(grid_t *grid); - +void gridResize(grid_t *grid, float width, float height); /** - * Add a breakpoint to a grid child. - * - * @param child Child to add the breakpoint to. - * @param x Column X position. - * @param y Row Y position. - * @param columns Count of columns this child will span. - * @param rows Count of rows this child will span. - * @return The index to the breakpoint in question. - */ -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. + * Get the dimensions of a particular cell and span. * * @param grid Grid to get from. - * @param screenWidth Screen width to use. - * @return Grid index. + * @param col Starting column. + * @param row Starting row. + * @param columns Count of columns the cell spans. + * @param rows Count of rows the cell spans. + * @param x Pointer to output X float. + * @param y Pointer to output Y float + * @param width Pointer to output width float. + * @param height Pointer to output height float. */ -uint8_t gridGetBreakpoint(grid_t *grid, float screenWidth); - -/** - * Retreive the breakpoint to use for a child. Takes missing breakpoints into - * consideration. - * - * @param child Child to get the breakpoint from. - * @param bp Breakpoint index to use. - * @return The childs matching breakpoint - */ -gridchildbreakpoint_t * gridChildGetBreakpoint(gridchild_t *child, uint8_t bp); - -/** - * Set the size of a grid system. This will only update if it's found to be - * necessary. - * - * @param grid Grid system to resize. - * @param screenWidth Current screen width. - * @param screenHeight Current screen height. - * @param width Width of the grid itself, useful for nested grids. - * @param height Height of the grid itself, useful for nested grids. - * @param x X position of this grid (to offset children by). Only for events. - * @param y Y position of this grid (to offset children by). Only for events. - */ -void gridSetSize(grid_t *grid, - float screenWidth, float screenHeight, - float width, float height, - float x, float y -); - -/** - * Get the size of a grid child. - * - * @param grid Grid to get from. - * @param breakpoint Breakpoint index to get. - * @param child Grid child to get for. - * @param sizeCol Pointer to a float that will/already holds the column size. - * @param sizeRow Poitner to a float that will/aready holds the row size. - * @param x Pointer to the output X position. - * @param y Pointer to the output Y position. - * @param width Pointer to the output width. - * @param height Pointer to the output height. - */ -void gridGetChildSize( - grid_t *grid, uint8_t breakpoint, gridchild_t *child, - float *sizeCol, float *sizeRow, +void gridGetChild( + grid_t *grid, uint8_t col, uint8_t row, uint8_t columns, uint8_t rows, float *x, float *y, float *width, float *height ); /** - * Align a grid item child. + * Align a child within its set cell. * - * @param grid Grid to align within. - * @param breakpoint Breakpoint index. - * @param child Grid child. - * @param sizeCol Pointer to a float that will/already holds the column size. - * @param sizeRow Poitner to a float that will/aready holds the row size. - * @param alignX Alignment options for the X axis. - * @param alignY Alignment options for the Y axis. - * @param width Width of the child item to be aligned. - * @param height Height of the child item to be aligned. - * @return The alignment within the grid cell. + * @param grid Grid to use when aligning. + * @param col Starting column. + * @param row Starting row. + * @param columns Count of columns the cell spans. + * @param rows Count of rows the cell spans. + * @param alignX Alignment flags for the X axis. + * @param alignY Alignment flags for the Y axis. + * @param width Current width of the child. + * @param height Current height of the child. + * @return The alignment information to align the child within the cell. */ -align_t gridAlignChild( - grid_t *grid, uint8_t breakpoint, gridchild_t *child, - float *sizeCol, float *sizeRow, - uint8_t alignX, uint8_t alignY, - float width, float height +align_t gridGetAndAlignChild( + grid_t *grid, uint8_t col, uint8_t row, uint8_t columns, uint8_t rows, + uint8_t alignX, uint8_t alignY, float width, float height ); \ No newline at end of file diff --git a/src/ui/menu.c b/src/ui/menu.c index 44e97ec2..a8b46962 100644 --- a/src/ui/menu.c +++ b/src/ui/menu.c @@ -8,32 +8,27 @@ #include "menu.h" void menuInit(menu_t *menu) { - gridInit(&menu->grid); - menu->grid.user = menu; - + menu->itemCount = 0; + menu->selected = 0; menu->cursorX = 0; menu->cursorY = 0; - menu->selected = 0; menu->user = NULL; menu->onSelect = NULL; } void menuUpdate(menu_t *menu, engine_t *engine) { - uint8_t x, y, i, j, cx, cy; - gridchild_t *current; - gridchildbreakpoint_t *currentbp; - gridchild_t *item; - gridchildbreakpoint_t *itembp; + menuitem_t *current; + menuitem_t *item; + uint8_t x, y, i, j; + current = menu->items + menu->selected; - current = menu->grid.children + menu->selected; - currentbp = gridChildGetBreakpoint(current, menu->grid.breakpointCurrent); - if(inputIsPressed(&engine->input, INPUT_ACCEPT)) { - if(menu->onSelect != NULL) menu->onSelect(menu->user, menu->selected); + if(menu->onSelect != NULL) { + menu->onSelect(menu->user, menu->selected); + } return; } - // Handle press binds. if(inputIsPressed(&engine->input, INPUT_DOWN)) { @@ -53,35 +48,29 @@ void menuUpdate(menu_t *menu, engine_t *engine) { y = 0; } - // Update cursor positions if(x != 0 || y != 0) { if(x > 0) { - cx = (currentbp->x + currentbp->columns - 1) + x; + menu->cursorX = (current->x + current->width - 1) + x; } else if(x < 0) { - cx = currentbp->x + x; - } else { - cx = menu->cursorX; + menu->cursorX = current->x + x; } if(y > 0) { - cy = (currentbp->y + currentbp->rows - 1) + y; + menu->cursorY = (current->y + current->height - 1) + y; } else if(y < 0) { - cy = currentbp->y + y; - } else { - cy = menu->cursorY; + menu->cursorY = current->y + y; } // Get the item selected - j = GRID_CHILD_COUNT; - for(i = 0; i < menu->grid.childCount; i++) { + j = MENU_ITEMS_MAX; + for(i = 0; i < menu->itemCount; i++) { if(i == menu->selected) continue; - item = menu->grid.children + i; - itembp = gridChildGetBreakpoint(item, menu->grid.breakpointCurrent); + item = menu->items + i; if( - itembp->x > cx || (itembp->x + itembp->columns - 1) < cx || - itembp->y > cy || (itembp->y + itembp->rows - 1) < cy + item->x > menu->cursorX || (item->x+item->width-1) < menu->cursorX || + item->y > menu->cursorY || (item->y+item->height-1) < menu->cursorY ) continue; j = i; @@ -89,9 +78,19 @@ void menuUpdate(menu_t *menu, engine_t *engine) { } // Was a target found? - if(j == GRID_CHILD_COUNT) return; - menu->cursorX = cx; - menu->cursorY = cy; + if(j == MENU_ITEMS_MAX) return; menu->selected = j; } +} + +menuitem_t * menuAdd(menu_t *menu) { + menuitem_t *item = menu->items + menu->itemCount; + + item->x = 0; + item->y = 0; + item->width = 1; + item->height = 1; + + menu->itemCount++; + return item; } \ No newline at end of file diff --git a/src/ui/menu.h b/src/ui/menu.h index f0d87395..498463f4 100644 --- a/src/ui/menu.h +++ b/src/ui/menu.h @@ -7,20 +7,31 @@ #pragma once #include -#include "grid.h" #include "../input/input.h" +#include "../epoch/epoch.h" +#include "../util/array.h" /** - * Initialize a Menu UI component. + * Initialize a menu. * * @param menu Menu to initialize. + * @param columns Count of rows. + * @param rows Count of columns. */ void menuInit(menu_t *menu); /** - * Update a Menu UI Component + * Updates the menu to handle inputs. * - * @param menu Menu to update - * @param engine Engine to use during the update. + * @param menu Menu to update. + * @param engine Engine to update from. */ -void menuUpdate(menu_t *menu, engine_t *engine); \ No newline at end of file +void menuUpdate(menu_t *menu, engine_t *engine); + +/** + * Add an item to the menu + * + * @param menu Menu to add to. + * @return Item to add to. + */ +menuitem_t * menuAdd(menu_t *menu); \ No newline at end of file diff --git a/src/ui/textmenu.c b/src/ui/textmenu.c index 2cc8dba9..b31051dd 100644 --- a/src/ui/textmenu.c +++ b/src/ui/textmenu.c @@ -7,33 +7,17 @@ #include "textmenu.h" -void _textMenuOnSelect(menu_t *menu, uint8_t i) { - textmenu_t *textMenu = (textmenu_t *)menu->user; +void _textMenuOnSelect(void *user, uint8_t i) { + textmenu_t *textMenu = (textmenu_t *)user; if(textMenu->onSelect != NULL) { textMenu->onSelect(textMenu->user, i, textMenu->texts[i]); } } -void _textMenuOnResize( - void *user, uint8_t i, gridchildbreakpoint_t *breakpoint, - float screenWidth, float screenHeight, - float x, float y, - float width, float height -) { - textmenu_t *textMenu = (textmenu_t *)((menu_t *)user); - label_t *label = textMenu->labels + i; - textmenulabelinfo_t *info = textMenu->labelInfo + i; - info->x = x; - info->y = y; - info->width = width; - info->height = height; - label->maxWidth = width <= 0 ? -1 : width; - labelSetText(label, textMenu->font, textMenu->texts[i]); -} - void textMenuInit(textmenu_t *menu, font_t *font) { menuInit(&menu->menu); + gridInit(&menu->grid); rectangleInit(&menu->rectangle); rectangleSetColor(&menu->rectangle, TEXTMENU_SELECTION_COLOR); @@ -41,37 +25,49 @@ void textMenuInit(textmenu_t *menu, font_t *font) { menu->menu.onSelect = &_textMenuOnSelect; menu->font = font; menu->onSelect = NULL; - menu->menu.grid.onResize = &_textMenuOnResize; } -gridchild_t * textMenuListAdd(textmenu_t *menu, char *item) { - menu->texts[menu->menu.grid.childCount] = item; - labelInit(menu->labels + menu->menu.grid.childCount); - (menu->labels + menu->menu.grid.childCount)->font = menu->font; - return gridAddChild(&menu->menu.grid); +menuitem_t * textMenuAdd(textmenu_t *menu, char *item) { + menu->texts[menu->menu.itemCount] = item; + labelInit(menu->labels + menu->menu.itemCount); + labelSetText(menu->labels + menu->menu.itemCount, menu->font, item); + (menu->labels + menu->menu.itemCount)->font = menu->font; + return menuAdd(&menu->menu); } -void textMenuListRender(textmenu_t *menu, shader_t *shader, float x, float y) { +void textMenuRender(textmenu_t *menu, shader_t *shader, float x, float y) { uint8_t i; label_t *label; - textmenulabelinfo_t *info; - - info = menu->labelInfo + menu->menu.selected; - menu->rectangle.width = info->width; - menu->rectangle.height = info->height; - rectangleRender(&menu->rectangle, shader, x + info->x, y + info->y); + menuitem_t *item; + align_t align; + float gx, gy; - for(i = 0; i < menu->menu.grid.childCount; i++) { + // Render selection box. + item = menu->menu.items + menu->menu.selected; + gridGetChild( + &menu->grid, item->x, item->y, item->width, item->height, + &gx, &gy, &menu->rectangle.width, &menu->rectangle.height + ); + rectangleRender(&menu->rectangle, shader, x + gx, y + gy); + + // Render labels + for(i = 0; i < menu->menu.itemCount; i++) { + item = menu->menu.items + i; label = menu->labels + i; - info = menu->labelInfo + i; - labelRender(label, shader, x + info->x, y + info->y); + align = gridGetAndAlignChild( + &menu->grid, item->x, item->y, item->width, item->height, + ALIGN_POS_START | ALIGN_SIZE_ORIGINAL, + ALIGN_POS_START | ALIGN_SIZE_ORIGINAL, + label->info.width, label->info.height + ); + labelRender(label, shader, align.x + x, align.y + y); } } void textMenuDispse(textmenu_t *menu) { uint8_t i; rectangleDispose(&menu->rectangle); - for(i = 0; i < menu->menu.grid.childCount; i++) { + for(i = 0; i < menu->menu.itemCount; i++) { labelDispose(menu->labels + i); } } \ No newline at end of file diff --git a/src/ui/textmenu.h b/src/ui/textmenu.h index d28a340b..a0b55a03 100644 --- a/src/ui/textmenu.h +++ b/src/ui/textmenu.h @@ -13,15 +13,7 @@ #include "rectangle.h" /** Callback to be notified from the menu when the menu items are selected. */ -void _textMenuOnSelect(menu_t *menu, uint8_t i); - -/** Callback to lisen for resize events from the grid subsystem */ -void _textMenuOnResize( - void *user, uint8_t i, gridchildbreakpoint_t *breakpoint, - float screenWidth, float screenHeight, - float x, float y, - float width, float height -); +void _textMenuOnSelect(void *user, uint8_t i); /** * Initialize a text menu item. @@ -38,7 +30,7 @@ void textMenuInit(textmenu_t *menu, font_t *font); * @param item Text to add (must be a constant value). * @return The grid subsystem item. */ -gridchild_t * textMenuListAdd(textmenu_t *menu, char *item); +menuitem_t * textMenuAdd(textmenu_t *menu, char *item); /** * Render a text menu list. @@ -48,7 +40,7 @@ gridchild_t * textMenuListAdd(textmenu_t *menu, char *item); * @param x X position of the menu. * @param y Y position of the menu. */ -void textMenuListRender(textmenu_t *menu, shader_t *shader, float x, float y); +void textMenuRender(textmenu_t *menu, shader_t *shader, float x, float y); /** * Dispose/Cleanup a text menu.