From 8d4df8347313a06d7cafeff9abcf33db6ef246fc Mon Sep 17 00:00:00 2001
From: Dominic Masters <dominic@domsplace.com>
Date: Sun, 12 Sep 2021 20:32:30 -0700
Subject: [PATCH] Added grid cell alignment

---
 include/dawn/game/poker/ui/pokerplayerui.h |   8 +-
 include/dawn/ui/grid.h                     |   2 +
 src/game/poker/ui/pokerplayerui.c          |  63 ++++++++++--
 src/game/poker/ui/pokerplayerui.h          |   4 +
 src/game/poker/ui/pokerui.c                |   6 +-
 src/ui/align.c                             |   7 +-
 src/ui/grid.c                              | 106 ++++++++++++++++-----
 src/ui/grid.h                              |  45 ++++++++-
 8 files changed, 199 insertions(+), 42 deletions(-)

diff --git a/include/dawn/game/poker/ui/pokerplayerui.h b/include/dawn/game/poker/ui/pokerplayerui.h
index 37e90d91..65af7c1f 100644
--- a/include/dawn/game/poker/ui/pokerplayerui.h
+++ b/include/dawn/game/poker/ui/pokerplayerui.h
@@ -12,6 +12,10 @@
 #include "../../../display/framebuffer.h"
 #include "../../../display/camera.h"
 
+
+#include "../../../ui/grid.h"
+#include "../../../ui/align.h"
+
 #define POKER_PLAYER_UI_IMAGE_SIZE 64
 #define POKER_PLAYER_UI_IMAGE_RESOLUTION POKER_PLAYER_UI_IMAGE_SIZE * 2
 #define POKER_PLAYER_UI_IMAGE_DIST 0.8f
@@ -20,7 +24,9 @@
 #define POKER_PLAYER_UI_CHIPS_ANIMATION_SPEED 0.5f
 
 typedef struct {
-  label_t label;
   framebuffer_t frame;
   primitive_t quad;
+  label_t label;
+
+  grid_t grid;
 } pokerplayerui_t;
\ No newline at end of file
diff --git a/include/dawn/ui/grid.h b/include/dawn/ui/grid.h
index 09375356..55100c60 100644
--- a/include/dawn/ui/grid.h
+++ b/include/dawn/ui/grid.h
@@ -64,6 +64,8 @@ typedef struct {
   /** Internal size reference, used for caching resize events */
   float width;
   float height;
+  float x;
+  float y;
 
   /** Pointer to any custom user data */
   void *user;
diff --git a/src/game/poker/ui/pokerplayerui.c b/src/game/poker/ui/pokerplayerui.c
index 901ab64d..c8c33a8a 100644
--- a/src/game/poker/ui/pokerplayerui.c
+++ b/src/game/poker/ui/pokerplayerui.c
@@ -8,6 +8,8 @@
 #include "pokerplayerui.h"
 
 void pokerPlayerUiInit(pokerplayerui_t *ui) {
+  gridchild_t *child;
+
   labelInit(&ui->label);
   frameBufferInit(&ui->frame,
     POKER_PLAYER_UI_IMAGE_RESOLUTION, POKER_PLAYER_UI_IMAGE_RESOLUTION
@@ -16,6 +18,22 @@ void pokerPlayerUiInit(pokerplayerui_t *ui) {
     0, 0, 0, 1,
     POKER_PLAYER_UI_IMAGE_SIZE, POKER_PLAYER_UI_IMAGE_SIZE, 1, 0
   );
+
+  // Grid
+  gridInit(&ui->grid);
+  gridAddBreakpoint(&ui->grid, -1, 2, 2, 0, 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(
@@ -62,28 +80,50 @@ void pokerPlayerUiUpdate(
 
 void pokerPlayerUiRender(
   pokerplayerui_t *ui, pokergame_t *game, shader_t *shader, font_t *font,
+  engine_t *engine,
   int32_t playerIndex, float x, float y
 ) {
   pokerplayer_t *player;
   char buffer[32];
   float scale;
+  align_t align;
 
+  float gx, gy, gw, gh, sCol, sRow;
+  
   scale = fontGetScale(FONT_SIZE_DEFAULT);
   player = game->poker.players + playerIndex;
 
-  // Render Face
-  shaderUseTexture(shader, &ui->frame.texture);
-  shaderUsePosition(shader, x - POKER_PLAYER_UI_IMAGE_SIZE,y,0, 0,0,0);
-  primitiveDraw(&ui->quad, 0, -1);
+  // Resize the grid
+  align = alignmentGet(
+    ALIGN_POS_END | ALIGN_SIZE_ORIGINAL, ALIGN_POS_START | ALIGN_SIZE_ORIGINAL,
+    engine->render.width, engine->render.height,
+    300, POKER_PLAYER_UI_IMAGE_SIZE, -1, -1
+  );
+  gridSetSize(
+    &ui->grid, engine->render.width, engine->render.height,
+    align.width, align.height,
+    align.x, align.y
+  );
 
-  // Move everything left a bit.
-  x -= POKER_PLAYER_UI_IMAGE_SIZE + POKER_PLAYER_UI_PADDING;
-  y += (POKER_PLAYER_UI_IMAGE_SIZE - (FONT_LINE_HEIGHT * scale * 2)) / 2.0f;
+  // 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);
-  labelRender(&ui->label, shader, x - ui->label.info.width, y);
+  align = gridAlignChild(
+    &ui->grid, ui->grid.breakpointCurrent, ui->grid.children + 1, &sCol, &sRow, 
+    ALIGN_POS_END | ALIGN_SIZE_ORIGINAL, ALIGN_POS_START | 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) {
@@ -98,9 +138,12 @@ void pokerPlayerUiRender(
     sprintf(buffer, "Whatever");
   }
   labelSetText(&ui->label, font, buffer);
-  labelRender(&ui->label, shader,
-    x - ui->label.info.width, y + scale * FONT_LINE_HEIGHT
+  align = gridAlignChild(
+    &ui->grid, ui->grid.breakpointCurrent, ui->grid.children + 2, &sCol, &sRow, 
+    ALIGN_POS_END | ALIGN_SIZE_ORIGINAL, ALIGN_POS_START | 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/poker/ui/pokerplayerui.h b/src/game/poker/ui/pokerplayerui.h
index bc91d4b7..73ae67b2 100644
--- a/src/game/poker/ui/pokerplayerui.h
+++ b/src/game/poker/ui/pokerplayerui.h
@@ -16,6 +16,9 @@
 #include "../../../display/camera.h"
 #include "../../../vn/vncharacter.h"
 
+#include "../../../ui/grid.h"
+#include "../../../ui/align.h"
+
 void pokerPlayerUiInit(pokerplayerui_t *ui);
 
 void pokerPlayerUiUpdate(
@@ -25,6 +28,7 @@ void pokerPlayerUiUpdate(
 
 void pokerPlayerUiRender(
   pokerplayerui_t *ui, pokergame_t *game, shader_t *shader, font_t *font,
+  engine_t *engine,
   int32_t playerIndex, float x, float y
 );
 
diff --git a/src/game/poker/ui/pokerui.c b/src/game/poker/ui/pokerui.c
index ae79c108..f30a8937 100644
--- a/src/game/poker/ui/pokerui.c
+++ b/src/game/poker/ui/pokerui.c
@@ -40,9 +40,9 @@ void pokerUiRender(pokergame_t *pokerGame, engine_t *engine) {
     if(i == POKER_PLAYER_HUMAN_INDEX) continue;
     ui = pokerGame->ui.player + j;
 
-    pokerPlayerUiRender(ui, pokerGame,
-      &pokerGame->assets.shader, &pokerGame->assets.font, i,
-      engine->render.width, j * 75.0f
+    pokerPlayerUiRender(
+      ui, pokerGame, &pokerGame->assets.shader, &pokerGame->assets.font, engine, 
+      i, engine->render.width, j * 75.0f
     );
     j++;
   }
diff --git a/src/ui/align.c b/src/ui/align.c
index 4193f79a..6e16a980 100644
--- a/src/ui/align.c
+++ b/src/ui/align.c
@@ -33,7 +33,12 @@ align_t alignmentGet(
   float childWidth, float childHeight,
   float childX, float childY
 ) {
-  align_t out;
+  align_t out = {
+    .x = 0,
+    .y = 0,
+    .width = 0,
+    .height = 0
+  };
 
   if(alignX & ALIGN_SIZE_RATIO) {
     // Work out Y size and alignment first, then we base off that.
diff --git a/src/ui/grid.c b/src/ui/grid.c
index b66134be..2aa291c1 100644
--- a/src/ui/grid.c
+++ b/src/ui/grid.c
@@ -74,58 +74,114 @@ void gridSetSize(grid_t *grid,
   float x, float y
 ) {
   uint8_t i, breakpoint;
-  gridchild_t *child;
-  gridchildbreakpoint_t *childbp;
   gridbreakpoint_t *gridbp;
   float sizeCol, sizeRow, gx, gy, gw, gh;
 
   // Need to resize?
-  if(grid->width == width && grid->height == height) {
+  if(
+    grid->width == width && grid->height == height &&
+    grid->x == x && grid->y == y
+  ) {
     return;
   }
 
   // Update properties
   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;
 
-  // Determine the size of a single column/row
-  sizeCol = (width - (gridbp->gutterX * (gridbp->columns-1))) / gridbp->columns;
-  sizeRow = (height - (gridbp->gutterY * (gridbp->rows - 1))) / gridbp->rows;
-
   if(grid->onResize == NULL) return;
 
+  sizeCol = -1;
+  sizeRow = -1;
+
   // Resize children
   for(i = 0; i < grid->childCount; i++) {
     // Get the item and the definition.
-    child = grid->children + i;
-    
-    childbp = gridChildGetBreakpoint(child, breakpoint);
 
-    // Get the local X/Y
-    gx = (sizeCol * childbp->x) + (gridbp->gutterX * childbp->x);
-    gy = (sizeRow * childbp->y) + (gridbp->gutterY * childbp->y);
-
-    // Get the width/height
-    gw = (
-      (childbp->columns * sizeCol) + 
-      (mathMax(childbp->columns - 1, 0) * gridbp->gutterX)
-    );
-    gh = (
-      (childbp->rows * sizeRow) + 
-      (mathMax(childbp->rows - 1, 0) * gridbp->gutterY)
+    gridGetChildSize(
+      grid, breakpoint, grid->children + i,
+      &sizeCol, &sizeRow, &gx, &gy, &gw, &gh
     );
 
     // Fire the resize event.
     grid->onResize(
-      grid->user, i, childbp,
+      grid->user, i, gridChildGetBreakpoint(grid->children + i, breakpoint),
       screenWidth, screenHeight,
-      x + gx, y + gy,
-      gw, gh
+      gx, gy, gw, gh
     );
   }
+}
+
+void gridGetChildSize(
+  grid_t *grid, uint8_t breakpoint, gridchild_t *child,
+  float *sizeCol, float *sizeRow,
+  float *x, float *y, float *width, float *height
+) {
+  gridchildbreakpoint_t *childbp;
+  gridbreakpoint_t *gridbp;
+
+  gridbp = grid->breakpoints + breakpoint;
+  
+  if(*sizeCol < 0) {
+    *sizeCol = (
+      grid->width - (gridbp->gutterX * (gridbp->columns-1))
+    ) / gridbp->columns;
+  }
+
+  if(*sizeRow < 0) {
+    *sizeRow = (
+      grid->height - (gridbp->gutterY * (gridbp->rows - 1))
+    ) / gridbp->rows;
+  }
+
+  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)
+  );
+}
+
+
+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
+) {
+  float gridWidth, gridHeight, gridX, gridY;
+  align_t alignment;
+
+  // 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;
 }
\ No newline at end of file
diff --git a/src/ui/grid.h b/src/ui/grid.h
index b6f1603f..333a61af 100644
--- a/src/ui/grid.h
+++ b/src/ui/grid.h
@@ -7,6 +7,7 @@
 
 #pragma once
 #include <dawn/dawn.h>
+#include "align.h"
 
 /**
  * Initialize a grid system.
@@ -83,11 +84,51 @@ gridchildbreakpoint_t * gridChildGetBreakpoint(gridchild_t *child, uint8_t bp);
  * @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).
- * @param y Y position of this grid (to offset children by).
+ * @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,
+  float *x, float *y, float *width, float *height
+);
+
+/**
+ * Align a grid item child.
+ * 
+ * @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.
+ */
+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
 );
\ No newline at end of file