From bd570c297efc407c63758288b8ab89453be86aff Mon Sep 17 00:00:00 2001 From: ostanton Date: Sat, 5 Apr 2025 15:20:09 +0100 Subject: Side panel and button things --- src/all.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 126 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/all.c b/src/all.c index 37a57c9..1dbe9a1 100644 --- a/src/all.c +++ b/src/all.c @@ -8,26 +8,48 @@ #define xmemcpy __builtin_memcpy #endif - typedef struct { unsigned char r, g, b, a; } Color; +typedef enum { + BUTTON_STATE_IDLE, + BUTTON_STATE_HOVERED, + BUTTON_STATE_PRESSED +} ButtonState; + +typedef struct { + int idle_colour; + int hover_colour; + int pressed_colour; +} ButtonStyle; + +typedef struct { + int x, y, w, h; + ButtonState state; +} Button; + typedef struct { int x, y, w, h; Color fill; Color border; } DrawElement; +typedef struct { + DrawElement bg; +} SidePanel; + typedef struct { int len; DrawElement els[512]; + SidePanel panel; } DrawList; #define MEM_SIZE (1<<16) #define GRIDWIDTH 16 #define GRIDHEIGHT 16 #define TICK_LENGTH 1000 +#define GRID_OFFSET_X 256 typedef struct { char *start; @@ -88,18 +110,35 @@ static const Color colors[N_COLORS] = { {255, 255, 0, 255} }; +static const ButtonStyle button_style = { + .idle_colour = BLACK, + .hover_colour = RED, + .pressed_colour = YELLOW +}; + +enum { + BUTTON_RETRY, + BUTTON_BACK, + N_BUTTONS, +}; + +static Button buttons[N_BUTTONS] = { + {.x = 64, .y = 64, .w = 128, .h = 32, .state = BUTTON_STATE_IDLE}, + {.x = 64, .y = 114, .w = 128, .h = 32, .state = BUTTON_STATE_IDLE}, +}; + static DrawList *render(State *state, UI *ui, Arena *a) { (void) ui; DrawList *drawList = new(a, 1, DrawList); - int cellWidth = ui->width / GRIDWIDTH; + int cellWidth = (ui->width - GRID_OFFSET_X) / GRIDWIDTH; int cellHeight = ui->height / GRIDHEIGHT; for (int x = 0; x < GRIDWIDTH; x++) { for (int y = 0; y < GRIDHEIGHT; y++) { drawList->els[drawList->len++] = (DrawElement) { - .x = cellWidth * x, + .x = cellWidth * x + GRID_OFFSET_X, .y = cellHeight * y, .w = cellWidth, .h = cellHeight, @@ -109,14 +148,45 @@ static DrawList *render(State *state, UI *ui, Arena *a) { } } + drawList->panel = (SidePanel) { + .bg = (DrawElement) { + .x = 0, + .y = 0, + .w = GRID_OFFSET_X, + .h = ui->height, + .fill = colors[YELLOW], + .border = {0, 0, 0, 255} + } + }; + return drawList; } +static void update_buttons(const int mx, const int my, const int mstate) { + for (int i = 0; i < N_BUTTONS; i++) { + if ( + mx > buttons[i].x && mx < buttons[i].x + buttons[i].w && + my > buttons[i].y && my < buttons[i].y + buttons[i].h + ) { + if (mstate == 1) { + buttons[i].state = BUTTON_STATE_PRESSED; + } + else + buttons[i].state = BUTTON_STATE_HOVERED; + } + else { + buttons[i].state = BUTTON_STATE_IDLE; + } + } +} + static void update(Game *game, uint64_t now, Arena a) { + const int offset_width = game->ui.width - GRID_OFFSET_X; + switch (game->input) { int x, y; case INPUT_CLICK: - x = game->mousex * GRIDWIDTH / game->ui.width; + x = game->mousex * GRIDWIDTH / offset_width; y = game->mousey * GRIDHEIGHT / game->ui.height; game->state.grid[x + y * GRIDWIDTH] = (game->state.grid[x + y * GRIDWIDTH] + 1) % (sizeof(colors) / sizeof(colors[0])); break; @@ -161,6 +231,45 @@ static void update(Game *game, uint64_t now, Arena a) { #include +void render_button(SDL_Renderer* r, const Button* b) { + Color colour = colors[BLACK]; + switch (b->state) { + case BUTTON_STATE_IDLE: + colour = colors[button_style.idle_colour]; + break; + case BUTTON_STATE_HOVERED: + colour = colors[button_style.hover_colour]; + break; + case BUTTON_STATE_PRESSED: + colour = colors[button_style.pressed_colour]; + break; + } + SDL_SetRenderDrawColor(r, colour.r, colour.g, colour.b, colour.a); + SDL_FRect rect = { + .x = (float) b->x, + .y = (float) b->y, + .w = (float) b->w, + .h = (float) b->h + }; + SDL_RenderFillRect(r, &rect); +} + +void render_side_panel(SDL_Renderer* r, SidePanel* panel) { + Color* bg_colour = &panel->bg.fill; + SDL_FRect rect = { + .x = (float) panel->bg.x, + .y = (float) panel->bg.y, + .w = (float) panel->bg.w, + .h = (float) panel->bg.h, + }; + SDL_SetRenderDrawColor(r, bg_colour->r, bg_colour->g, bg_colour->b, bg_colour->a); + SDL_RenderFillRect(r, &rect); + + for (int i = 0; i < N_BUTTONS; i++) { + render_button(r, &buttons[i]); + } +} + int main(int argc, char **argv) { (void) argc; (void) argv; @@ -191,7 +300,8 @@ int main(int argc, char **argv) { SDL_SetNumberProperty(renderProps, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER, 1); SDL_Renderer *r = SDL_CreateRendererWithProperties(renderProps); SDL_DestroyProperties(renderProps); - + + int mousex = 0, mousey = 0, mousestate = 0; for (;;) { uint64_t now = SDL_GetTicks(); game->input = INPUT_NONE; @@ -202,8 +312,16 @@ int main(int argc, char **argv) { return 0; case SDL_EVENT_MOUSE_BUTTON_DOWN: game->input = INPUT_CLICK; - game->mousex = (int) e.button.x; + game->mousex = (int) e.button.x - GRID_OFFSET_X; game->mousey = (int) e.button.y; + mousestate = SDL_BUTTON_MASK(e.motion.state); + break; + case SDL_EVENT_MOUSE_BUTTON_UP: + mousestate = 0; + break; + case SDL_EVENT_MOUSE_MOTION: + mousex = (int) e.motion.x; + mousey = (int) e.motion.y; break; case SDL_EVENT_KEY_DOWN: switch (e.key.key) { @@ -216,6 +334,7 @@ int main(int argc, char **argv) { SDL_GetWindowSize(w, &game->ui.width, &game->ui.height); break; } + update_buttons(mousex, mousey, mousestate); } Arena scratch = a; @@ -248,6 +367,7 @@ int main(int argc, char **argv) { ); SDL_RenderRect(r, &rect); } + render_side_panel(r, &drawList->panel); update(game, now, a); -- cgit v1.2.3 From 9a5b7dc761291d4b3f8d44d7485521ec6b054815 Mon Sep 17 00:00:00 2001 From: ostanton Date: Sat, 5 Apr 2025 18:20:59 +0100 Subject: Made UI platform-agnostic --- src/all.c | 162 ++++++++++++++++++++++---------------------------------------- 1 file changed, 58 insertions(+), 104 deletions(-) (limited to 'src') diff --git a/src/all.c b/src/all.c index 1dbe9a1..8e5170c 100644 --- a/src/all.c +++ b/src/all.c @@ -18,17 +18,6 @@ typedef enum { BUTTON_STATE_PRESSED } ButtonState; -typedef struct { - int idle_colour; - int hover_colour; - int pressed_colour; -} ButtonStyle; - -typedef struct { - int x, y, w, h; - ButtonState state; -} Button; - typedef struct { int x, y, w, h; Color fill; @@ -42,7 +31,6 @@ typedef struct { typedef struct { int len; DrawElement els[512]; - SidePanel panel; } DrawList; #define MEM_SIZE (1<<16) @@ -75,10 +63,17 @@ typedef struct { int width, height; } UI; +enum { + BUTTON_RETRY, + BUTTON_BACK, + N_BUTTONS, +}; + typedef struct { uint64_t lastTick; char playing; int grid[GRIDWIDTH * GRIDHEIGHT]; + ButtonState buttonStates[N_BUTTONS]; } State; // Mirror these in src/index.html.in @@ -110,21 +105,13 @@ static const Color colors[N_COLORS] = { {255, 255, 0, 255} }; -static const ButtonStyle button_style = { - .idle_colour = BLACK, - .hover_colour = RED, - .pressed_colour = YELLOW -}; - -enum { - BUTTON_RETRY, - BUTTON_BACK, - N_BUTTONS, -}; +typedef struct { + int x, y, w, h; +} Button; -static Button buttons[N_BUTTONS] = { - {.x = 64, .y = 64, .w = 128, .h = 32, .state = BUTTON_STATE_IDLE}, - {.x = 64, .y = 114, .w = 128, .h = 32, .state = BUTTON_STATE_IDLE}, +static const Button buttons[N_BUTTONS] = { + [BUTTON_RETRY] = {.x = 16, .y = 16, .w = 128, .h = 32}, + [BUTTON_BACK] = {.x = 16, .y = 48, .w = 128, .h = 32}, }; static DrawList *render(State *state, UI *ui, Arena *a) { @@ -148,36 +135,39 @@ static DrawList *render(State *state, UI *ui, Arena *a) { } } - drawList->panel = (SidePanel) { - .bg = (DrawElement) { - .x = 0, - .y = 0, - .w = GRID_OFFSET_X, - .h = ui->height, - .fill = colors[YELLOW], - .border = {0, 0, 0, 255} - } + drawList->els[drawList->len++] = (DrawElement) { + .x = 0, + .y = 0, + .w = GRID_OFFSET_X, + .h = ui->height, + .fill = colors[YELLOW], + .border = {0, 0, 0, 255} }; - - return drawList; -} - -static void update_buttons(const int mx, const int my, const int mstate) { + for (int i = 0; i < N_BUTTONS; i++) { - if ( - mx > buttons[i].x && mx < buttons[i].x + buttons[i].w && - my > buttons[i].y && my < buttons[i].y + buttons[i].h - ) { - if (mstate == 1) { - buttons[i].state = BUTTON_STATE_PRESSED; - } - else - buttons[i].state = BUTTON_STATE_HOVERED; - } - else { - buttons[i].state = BUTTON_STATE_IDLE; + int colour = BLACK; + switch (state->buttonStates[i]) { + case BUTTON_STATE_IDLE: + colour = BLACK; + break; + case BUTTON_STATE_HOVERED: + colour = YELLOW; + break; + case BUTTON_STATE_PRESSED: + colour = RED; + break; } + drawList->els[drawList->len++] = (DrawElement) { + .x = buttons[i].x, + .y = buttons[i].y, + .w = buttons[i].w, + .h = buttons[i].h, + .fill = colors[colour], + .border = {0, 0, 0, 255} + }; } + + return drawList; } static void update(Game *game, uint64_t now, Arena a) { @@ -186,9 +176,18 @@ static void update(Game *game, uint64_t now, Arena a) { switch (game->input) { int x, y; case INPUT_CLICK: - x = game->mousex * GRIDWIDTH / offset_width; + x = (game->mousex - GRID_OFFSET_X) * GRIDWIDTH / offset_width; y = game->mousey * GRIDHEIGHT / game->ui.height; game->state.grid[x + y * GRIDWIDTH] = (game->state.grid[x + y * GRIDWIDTH] + 1) % (sizeof(colors) / sizeof(colors[0])); + for (int i = 0; i < N_BUTTONS; i++) { + if ( + game->mousex > buttons[i].x && game->mousex < buttons[i].x + buttons[i].w && + game->mousey > buttons[i].y && game->mousey < buttons[i].y + buttons[i].h + ) { + // TODO - CLICK THINGS + //game->state.buttonStates[i] = BUTTON_STATE_PRESSED; + } + } break; case INPUT_PAUSE_PLAY: game->state.playing = !game->state.playing; @@ -231,45 +230,6 @@ static void update(Game *game, uint64_t now, Arena a) { #include -void render_button(SDL_Renderer* r, const Button* b) { - Color colour = colors[BLACK]; - switch (b->state) { - case BUTTON_STATE_IDLE: - colour = colors[button_style.idle_colour]; - break; - case BUTTON_STATE_HOVERED: - colour = colors[button_style.hover_colour]; - break; - case BUTTON_STATE_PRESSED: - colour = colors[button_style.pressed_colour]; - break; - } - SDL_SetRenderDrawColor(r, colour.r, colour.g, colour.b, colour.a); - SDL_FRect rect = { - .x = (float) b->x, - .y = (float) b->y, - .w = (float) b->w, - .h = (float) b->h - }; - SDL_RenderFillRect(r, &rect); -} - -void render_side_panel(SDL_Renderer* r, SidePanel* panel) { - Color* bg_colour = &panel->bg.fill; - SDL_FRect rect = { - .x = (float) panel->bg.x, - .y = (float) panel->bg.y, - .w = (float) panel->bg.w, - .h = (float) panel->bg.h, - }; - SDL_SetRenderDrawColor(r, bg_colour->r, bg_colour->g, bg_colour->b, bg_colour->a); - SDL_RenderFillRect(r, &rect); - - for (int i = 0; i < N_BUTTONS; i++) { - render_button(r, &buttons[i]); - } -} - int main(int argc, char **argv) { (void) argc; (void) argv; @@ -287,6 +247,9 @@ int main(int argc, char **argv) { .width = 640, .height = 480, }; + for (int i = 0; i < N_BUTTONS; i++) { + game->state.buttonStates[i] = BUTTON_STATE_IDLE; + } SDL_Init(SDL_INIT_VIDEO); SDL_Window *w = SDL_CreateWindow( @@ -301,7 +264,6 @@ int main(int argc, char **argv) { SDL_Renderer *r = SDL_CreateRendererWithProperties(renderProps); SDL_DestroyProperties(renderProps); - int mousex = 0, mousey = 0, mousestate = 0; for (;;) { uint64_t now = SDL_GetTicks(); game->input = INPUT_NONE; @@ -312,16 +274,8 @@ int main(int argc, char **argv) { return 0; case SDL_EVENT_MOUSE_BUTTON_DOWN: game->input = INPUT_CLICK; - game->mousex = (int) e.button.x - GRID_OFFSET_X; + game->mousex = (int) e.button.x; game->mousey = (int) e.button.y; - mousestate = SDL_BUTTON_MASK(e.motion.state); - break; - case SDL_EVENT_MOUSE_BUTTON_UP: - mousestate = 0; - break; - case SDL_EVENT_MOUSE_MOTION: - mousex = (int) e.motion.x; - mousey = (int) e.motion.y; break; case SDL_EVENT_KEY_DOWN: switch (e.key.key) { @@ -334,9 +288,10 @@ int main(int argc, char **argv) { SDL_GetWindowSize(w, &game->ui.width, &game->ui.height); break; } - update_buttons(mousex, mousey, mousestate); } + SDL_Log("Button 1 state: %d", game->state.buttonStates[0]); + Arena scratch = a; DrawList *drawList = render(&game->state, &game->ui, &scratch); SDL_SetRenderDrawColor(r, 0, 0, 0, 255); @@ -367,7 +322,6 @@ int main(int argc, char **argv) { ); SDL_RenderRect(r, &rect); } - render_side_panel(r, &drawList->panel); update(game, now, a); -- cgit v1.2.3