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,
41 ListSelector *list_selector = PUSH_LT(lt, nth_calloc(1, sizeof(ListSelector)), free);
42 if (list_selector == NULL) {
45 list_selector->lt = lt;
47 list_selector->sprite_font = sprite_font;
48 list_selector->items = items;
49 list_selector->count = count;
50 list_selector->cursor = 0;
51 list_selector->selected_item = -1;
52 list_selector->position = vec(0.0f, 0.0f);
53 list_selector->font_scale = font_scale;
54 list_selector->padding_bottom = padding_bottom;
59 void destroy_list_selector(ListSelector *list_selector)
61 trace_assert(list_selector);
62 RETURN_LT0(list_selector->lt);
65 int list_selector_render(const ListSelector *list_selector,
66 SDL_Renderer *renderer)
68 trace_assert(list_selector);
69 trace_assert(renderer);
71 for (size_t i = 0; i < list_selector->count; ++i) {
72 const Vec current_position = vec_sum(
73 list_selector->position,
74 vec(0.0f, (float) i * ((float) FONT_CHAR_HEIGHT * list_selector->font_scale.y + list_selector->padding_bottom)));
76 if (sprite_font_render_text(
77 list_selector->sprite_font,
80 list_selector->font_scale,
81 rgba(1.0f, 1.0f, 1.0f, 1.0f),
82 list_selector->items[i]) < 0) {
86 if (i == list_selector->cursor) {
87 SDL_Rect boundary_box = rect_for_sdl(
88 sprite_font_boundary_box(
89 list_selector->sprite_font,
91 list_selector->font_scale,
92 list_selector->items[i]));
93 if (SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255) < 0) {
97 if (SDL_RenderDrawRect(renderer, &boundary_box) < 0) {
106 Vec list_selector_size(const ListSelector *list_selector,
108 float padding_bottom)
110 trace_assert(list_selector);
112 Vec result = vec(0.0f, 0.0f);
114 for (size_t i = 0; i < list_selector->count; ++i) {
115 Rect boundary_box = sprite_font_boundary_box(
116 list_selector->sprite_font,
119 list_selector->items[i]);
121 result.x = fmaxf(result.x, boundary_box.w);
122 result.y += boundary_box.y + padding_bottom;
128 int list_selector_update(ListSelector *list_selector, float delta_time)
130 trace_assert(list_selector);
136 int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
138 trace_assert(list_selector);
141 switch (event->type) {
143 switch (event->key.keysym.sym) {
145 if (list_selector->cursor > 0) {
146 list_selector->cursor--;
150 if (list_selector->cursor < list_selector->count - 1) {
151 list_selector->cursor++;
155 list_selector->selected_item = (int) list_selector->cursor;
160 case SDL_MOUSEMOTION: {
161 const Vec mouse_pos = vec((float)event->motion.x, (float)event->motion.y);
162 Vec position = list_selector->position;
164 for (size_t i = 0; i < list_selector->count; ++i) {
165 Rect boundary_box = sprite_font_boundary_box(
166 list_selector->sprite_font,
168 list_selector->font_scale,
169 list_selector->items[i]);
171 if (rect_contains_point(boundary_box, mouse_pos)) {
172 list_selector->cursor = i;
175 position.y += boundary_box.h + list_selector->padding_bottom;
179 case SDL_MOUSEBUTTONDOWN: {
180 switch (event->button.button) {
181 case SDL_BUTTON_LEFT: {
182 list_selector->selected_item = (int) list_selector->cursor;
191 int list_selector_selected(const ListSelector *list_selector)
193 trace_assert(list_selector);
194 return list_selector->selected_item;
197 void list_selector_clean_selection(ListSelector *list_selector)
199 trace_assert(list_selector);
200 list_selector->selected_item = -1;
203 void list_selector_move(ListSelector *list_selector, Vec position)
205 list_selector->position = position;