5 #include "system/stacktrace.h"
7 #include "system/nth_alloc.h"
8 #include "system/str.h"
9 #include "math/point.h"
10 #include "game/sprite_font.h"
11 #include "system/log.h"
13 #include "./list_selector.h"
18 const Sprite_font *sprite_font;
28 ListSelector *create_list_selector(const Sprite_font *sprite_font,
38 ListSelector *list_selector = PUSH_LT(lt, nth_calloc(1, sizeof(ListSelector)), free);
39 if (list_selector == NULL) {
42 list_selector->lt = lt;
44 list_selector->sprite_font = sprite_font;
45 list_selector->items = items;
46 list_selector->count = count;
47 list_selector->cursor = 0;
48 list_selector->selected_item = -1;
49 list_selector->position = vec(0.0f, 0.0f);
50 list_selector->font_scale = font_scale;
51 list_selector->padding_bottom = padding_bottom;
56 void destroy_list_selector(ListSelector *list_selector)
58 trace_assert(list_selector);
59 RETURN_LT0(list_selector->lt);
62 int list_selector_render(const ListSelector *list_selector,
63 SDL_Renderer *renderer)
65 trace_assert(list_selector);
66 trace_assert(renderer);
68 for (size_t i = 0; i < list_selector->count; ++i) {
69 const Vec current_position = vec_sum(
70 list_selector->position,
71 vec(0.0f, (float) i * ((float) FONT_CHAR_HEIGHT * list_selector->font_scale.y + list_selector->padding_bottom)));
73 if (sprite_font_render_text(
74 list_selector->sprite_font,
77 list_selector->font_scale,
78 rgba(1.0f, 1.0f, 1.0f, 1.0f),
79 list_selector->items[i]) < 0) {
83 if (i == list_selector->cursor) {
84 SDL_Rect boundary_box = rect_for_sdl(
85 sprite_font_boundary_box(
86 list_selector->sprite_font,
88 list_selector->font_scale,
89 list_selector->items[i]));
90 if (SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255) < 0) {
94 if (SDL_RenderDrawRect(renderer, &boundary_box) < 0) {
103 Vec list_selector_size(const ListSelector *list_selector,
105 float padding_bottom)
107 trace_assert(list_selector);
109 Vec result = vec(0.0f, 0.0f);
111 for (size_t i = 0; i < list_selector->count; ++i) {
112 Rect boundary_box = sprite_font_boundary_box(
113 list_selector->sprite_font,
116 list_selector->items[i]);
118 result.x = fmaxf(result.x, boundary_box.w);
119 result.y += boundary_box.y + padding_bottom;
125 int list_selector_update(ListSelector *list_selector, float delta_time)
127 trace_assert(list_selector);
133 int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
135 trace_assert(list_selector);
138 switch (event->type) {
140 switch (event->key.keysym.sym) {
142 if (list_selector->cursor > 0) {
143 list_selector->cursor--;
147 if (list_selector->cursor < list_selector->count - 1) {
148 list_selector->cursor++;
152 list_selector->selected_item = (int) list_selector->cursor;
157 case SDL_MOUSEMOTION: {
158 const Vec mouse_pos = vec((float)event->motion.x, (float)event->motion.y);
159 Vec position = list_selector->position;
161 for (size_t i = 0; i < list_selector->count; ++i) {
162 Rect boundary_box = sprite_font_boundary_box(
163 list_selector->sprite_font,
165 list_selector->font_scale,
166 list_selector->items[i]);
168 if (rect_contains_point(boundary_box, mouse_pos)) {
169 list_selector->cursor = i;
172 position.y += boundary_box.h + list_selector->padding_bottom;
176 case SDL_MOUSEBUTTONDOWN: {
177 switch (event->button.button) {
178 case SDL_BUTTON_LEFT: {
179 list_selector->selected_item = (int) list_selector->cursor;
188 int list_selector_selected(const ListSelector *list_selector)
190 trace_assert(list_selector);
191 return list_selector->selected_item;
194 void list_selector_clean_selection(ListSelector *list_selector)
196 trace_assert(list_selector);
197 list_selector->selected_item = -1;
200 void list_selector_move(ListSelector *list_selector, Vec position)
202 list_selector->position = position;