#include "system/nth_alloc.h"
#include "system/stacktrace.h"
#include "system/str.h"
-#include "ui/list_selector.h"
#include "system/log.h"
#include "game/level_folder.h"
#include "ui/wiggly_text.h"
Vec2f camera_position;
LevelFolder level_folder;
WigglyText wiggly_text;
- ListSelector list_selector;
+
+ Dynarray items;
+ size_t cursor;
+ int selected_item;
+ Vec2f position;
+ Vec2f font_scale;
+ float padding_bottom;
};
LevelPicker *create_level_picker(const char *dirpath)
.color = COLOR_WHITE,
};
- level_picker->list_selector.items = level_picker->level_folder.filepaths;
- level_picker->list_selector.font_scale = vec(5.0f, 5.0f);
- level_picker->list_selector.padding_bottom = 50.0f;
+ level_picker->items = level_picker->level_folder.filepaths;
+ level_picker->font_scale = vec(5.0f, 5.0f);
+ level_picker->padding_bottom = 50.0f;
return level_picker;
}
camera,
vec(viewport.w * 0.5f - title_size.x * 0.5f, TITLE_MARGIN_TOP));
- list_selector_render(camera, &level_picker->list_selector);
+ for (size_t i = 0; i < level_picker->items.count; ++i) {
+ const Vec2f current_position = vec_sum(
+ level_picker->position,
+ vec(0.0f, (float) i * ((float) FONT_CHAR_HEIGHT * level_picker->font_scale.y + level_picker->padding_bottom)));
+
+ const char *item_text = dynarray_pointer_at(&level_picker->items, i);
+
+ sprite_font_render_text(
+ &camera->font,
+ camera->renderer,
+ current_position,
+ level_picker->font_scale,
+ rgba(1.0f, 1.0f, 1.0f, 1.0f),
+ item_text);
+
+ if (i == level_picker->cursor) {
+ SDL_Rect boundary_box = rect_for_sdl(
+ sprite_font_boundary_box(
+ current_position,
+ level_picker->font_scale,
+ strlen(item_text)));
+ if (SDL_SetRenderDrawColor(camera->renderer, 255, 255, 255, 255) < 0) {
+ return -1;
+ }
+
+ if (SDL_RenderDrawRect(camera->renderer, &boundary_box) < 0) {
+ return -1;
+ }
+ }
+ }
{
/* CSS */
return 0;
}
+static
+Vec2f level_picker_list_size(const LevelPicker *level_picker,
+ Vec2f font_scale,
+ float padding_bottom)
+{
+ trace_assert(level_picker);
+
+ Vec2f result = vec(0.0f, 0.0f);
+
+ for (size_t i = 0; i < level_picker->items.count; ++i) {
+ const char *item_text = dynarray_pointer_at(
+ &level_picker->items,
+ i);
+
+ Rect boundary_box = sprite_font_boundary_box(
+ vec(0.0f, 0.0f),
+ font_scale,
+ strlen(item_text));
+
+ result.x = fmaxf(result.x, boundary_box.w);
+ result.y += boundary_box.y + padding_bottom;
+ }
+
+ return result;
+}
+
+
int level_picker_event(LevelPicker *level_picker,
const SDL_Event *event)
{
const Vec2f title_size = wiggly_text_size(&level_picker->wiggly_text);
- const Vec2f selector_size = list_selector_size(
- &level_picker->list_selector,
+ const Vec2f selector_size = level_picker_list_size(
+ level_picker,
font_scale,
padding_bottom);
- level_picker->list_selector.position =
+ level_picker->position =
vec((float)width * 0.5f - selector_size.x * 0.5f,
TITLE_MARGIN_TOP + title_size.y + TITLE_MARGIN_BOTTOM);
} break;
}
} break;
+
+ case SDL_KEYDOWN:
+ switch (event->key.keysym.sym) {
+ case SDLK_UP:
+ if (level_picker->cursor == 0) {
+ level_picker->cursor = level_picker->items.count - 1;
+ } else {
+ level_picker->cursor--;
+ }
+ break;
+ case SDLK_DOWN:
+ level_picker->cursor++;
+ if (level_picker->cursor == level_picker->items.count) {
+ level_picker->cursor = 0;
+ }
+ break;
+ case SDLK_RETURN:
+ if (level_picker->cursor < level_picker->items.count) {
+ level_picker->selected_item = (int) level_picker->cursor;
+ }
+ break;
+ }
+ break;
+
+ case SDL_MOUSEMOTION: {
+ const Vec2f mouse_pos = vec((float) event->motion.x, (float) event->motion.y);
+ Vec2f position = level_picker->position;
+
+ for (size_t i = 0; i < level_picker->items.count; ++i) {
+ const char *item_text = dynarray_pointer_at(
+ &level_picker->items,
+ i);
+
+ Rect boundary_box = sprite_font_boundary_box(
+ position,
+ level_picker->font_scale,
+ strlen(item_text));
+
+ if (rect_contains_point(boundary_box, mouse_pos)) {
+ level_picker->cursor = i;
+ }
+
+ position.y += boundary_box.h + level_picker->padding_bottom;
+ }
+ } break;
+
+ case SDL_MOUSEBUTTONDOWN: {
+ switch (event->button.button) {
+ case SDL_BUTTON_LEFT: {
+ // check if the click position was actually inside...
+ // note: make sure there's actually stuff in the list! tsoding likes
+ // to remove all levels and change title to "SMOL BREAK"...
+ if (level_picker->items.count == 0)
+ break;
+
+ // note: this assumes that all list items are the same height!
+ // this is probably a valid assumption as long as we use a sprite font.
+ float single_item_height =
+ FONT_CHAR_HEIGHT * level_picker->font_scale.y + level_picker->padding_bottom;
+
+ Vec2f position = level_picker->position;
+ vec_add(&position, vec(0.0f, (float) level_picker->cursor * single_item_height));
+
+ const char *item_text =
+ dynarray_pointer_at(
+ &level_picker->items,
+ level_picker->cursor);
+
+ Rect boundary_box = sprite_font_boundary_box(
+ position,
+ level_picker->font_scale,
+ strlen(item_text));
+
+ const Vec2f mouse_pos = vec((float) event->motion.x, (float) event->motion.y);
+ if (rect_contains_point(boundary_box, mouse_pos)) {
+ level_picker->selected_item = (int) level_picker->cursor;
+ }
+ } break;
+ }
+ } break;
}
- return list_selector_event(&level_picker->list_selector, event);
+ return 0;
}
int level_picker_input(LevelPicker *level_picker,
{
trace_assert(level_picker);
- if (level_picker->list_selector.selected_item < 0) {
+ if (level_picker->selected_item < 0) {
return NULL;
}
return dynarray_pointer_at(
- &level_picker->level_folder.filepaths,
- (size_t)level_picker->list_selector.selected_item);
+ &level_picker->items,
+ (size_t)level_picker->selected_item);
}
void level_picker_clean_selection(LevelPicker *level_picker)
{
trace_assert(level_picker);
- level_picker->list_selector.selected_item = -1;
+ level_picker->selected_item = -1;
}
int level_picker_enter_camera_event(LevelPicker *level_picker,
+++ /dev/null
-#include <stdlib.h>
-#include <string.h>
-
-#include <SDL.h>
-
-#include "system/stacktrace.h"
-#include "system/lt.h"
-#include "system/nth_alloc.h"
-#include "system/str.h"
-#include "math/vec.h"
-#include "game/sprite_font.h"
-#include "system/log.h"
-
-#include "./list_selector.h"
-
-
-int list_selector_render(const Camera *camera,
- const ListSelector *list_selector)
-{
- trace_assert(camera);
- trace_assert(list_selector);
-
- for (size_t i = 0; i < list_selector->items.count; ++i) {
- const Vec2f current_position = vec_sum(
- list_selector->position,
- vec(0.0f, (float) i * ((float) FONT_CHAR_HEIGHT * list_selector->font_scale.y + list_selector->padding_bottom)));
-
- const char *item_text = dynarray_pointer_at(&list_selector->items, i);
-
- sprite_font_render_text(
- &camera->font,
- camera->renderer,
- current_position,
- list_selector->font_scale,
- rgba(1.0f, 1.0f, 1.0f, 1.0f),
- item_text);
-
- if (i == list_selector->cursor) {
- SDL_Rect boundary_box = rect_for_sdl(
- sprite_font_boundary_box(
- current_position,
- list_selector->font_scale,
- strlen(item_text)));
- if (SDL_SetRenderDrawColor(camera->renderer, 255, 255, 255, 255) < 0) {
- return -1;
- }
-
- if (SDL_RenderDrawRect(camera->renderer, &boundary_box) < 0) {
- return -1;
- }
- }
- }
-
- return 0;
-}
-
-Vec2f list_selector_size(const ListSelector *list_selector,
- Vec2f font_scale,
- float padding_bottom)
-{
- trace_assert(list_selector);
-
- Vec2f result = vec(0.0f, 0.0f);
-
- for (size_t i = 0; i < list_selector->items.count; ++i) {
- const char *item_text = dynarray_pointer_at(
- &list_selector->items,
- i);
-
- Rect boundary_box = sprite_font_boundary_box(
- vec(0.0f, 0.0f),
- font_scale,
- strlen(item_text));
-
- result.x = fmaxf(result.x, boundary_box.w);
- result.y += boundary_box.y + padding_bottom;
- }
-
- return result;
-}
-
-int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
-{
- trace_assert(list_selector);
- trace_assert(event);
-
- switch (event->type) {
- case SDL_KEYDOWN:
- switch (event->key.keysym.sym) {
- case SDLK_UP:
- if (list_selector->cursor == 0) {
- list_selector->cursor = list_selector->items.count - 1;
- } else {
- list_selector->cursor--;
- }
- break;
- case SDLK_DOWN:
- list_selector->cursor++;
- if (list_selector->cursor == list_selector->items.count) {
- list_selector->cursor = 0;
- }
- break;
- case SDLK_RETURN:
- if (list_selector->cursor < list_selector->items.count) {
- list_selector->selected_item = (int) list_selector->cursor;
- }
- break;
- }
- break;
-
- case SDL_MOUSEMOTION: {
- const Vec2f mouse_pos = vec((float) event->motion.x, (float) event->motion.y);
- Vec2f position = list_selector->position;
-
- for (size_t i = 0; i < list_selector->items.count; ++i) {
- const char *item_text = dynarray_pointer_at(
- &list_selector->items,
- i);
-
- Rect boundary_box = sprite_font_boundary_box(
- position,
- list_selector->font_scale,
- strlen(item_text));
-
- if (rect_contains_point(boundary_box, mouse_pos)) {
- list_selector->cursor = i;
- }
-
- position.y += boundary_box.h + list_selector->padding_bottom;
- }
- } break;
-
- case SDL_MOUSEBUTTONDOWN: {
- switch (event->button.button) {
- case SDL_BUTTON_LEFT: {
- // check if the click position was actually inside...
- // note: make sure there's actually stuff in the list! tsoding likes
- // to remove all levels and change title to "SMOL BREAK"...
- if (list_selector->items.count == 0)
- break;
-
- // note: this assumes that all list items are the same height!
- // this is probably a valid assumption as long as we use a sprite font.
- float single_item_height =
- FONT_CHAR_HEIGHT * list_selector->font_scale.y + list_selector->padding_bottom;
-
- Vec2f position = list_selector->position;
- vec_add(&position, vec(0.0f, (float) list_selector->cursor * single_item_height));
-
- const char *item_text =
- dynarray_pointer_at(
- &list_selector->items,
- list_selector->cursor);
-
- Rect boundary_box = sprite_font_boundary_box(
- position,
- list_selector->font_scale,
- strlen(item_text));
-
- const Vec2f mouse_pos = vec((float) event->motion.x, (float) event->motion.y);
- if (rect_contains_point(boundary_box, mouse_pos)) {
- list_selector->selected_item = (int) list_selector->cursor;
- }
- } break;
- }
- } break;
- }
-
- return 0;
-}