3 #include "./level_picker.h"
4 #include "game/level/background.h"
5 #include "game/sprite_font.h"
7 #include "system/nth_alloc.h"
8 #include "system/stacktrace.h"
9 #include "system/str.h"
10 #include "ui/list_selector.h"
11 #include "system/log.h"
12 #include "game/level_folder.h"
13 #include "ui/wiggly_text.h"
14 #include "ui/slider.h"
16 #define TITLE_MARGIN_TOP 100.0f
17 #define TITLE_MARGIN_BOTTOM 100.0f
22 Background background;
23 Vec2f camera_position;
24 LevelFolder level_folder;
25 WigglyText wiggly_text;
26 ListSelector list_selector;
30 const char *list_item_text(void *element)
32 trace_assert(element);
33 return ((LevelMetadata *)element)->title;
36 LevelPicker *create_level_picker(const char *dirpath)
38 trace_assert(dirpath);
42 LevelPicker *level_picker = PUSH_LT(
44 nth_calloc(1, sizeof(LevelPicker)),
46 if (level_picker == NULL) {
49 level_picker->lt = lt;
51 level_picker->background = create_background(hexstr("073642"));
53 level_picker->camera_position = vec(0.0f, 0.0f);
55 level_picker->level_folder = create_level_folder();
56 level_folder_read("./assets/levels", &level_picker->level_folder);
58 level_picker->wiggly_text = (WigglyText) {
59 .text = "Select Level",
60 .scale = {10.0f, 10.0f},
64 level_picker->list_selector.items = level_picker->level_folder.metadatas;
65 level_picker->list_selector.font_scale = vec(5.0f, 5.0f);
66 level_picker->list_selector.padding_bottom = 50.0f;
67 level_picker->list_selector.list_item_text = list_item_text;
72 void destroy_level_picker(LevelPicker *level_picker)
74 trace_assert(level_picker);
75 destroy_level_folder(level_picker->level_folder);
76 RETURN_LT0(level_picker->lt);
79 int level_picker_render(const LevelPicker *level_picker,
82 trace_assert(level_picker);
84 const Rect viewport = camera_view_port_screen(camera);
86 if (background_render(&level_picker->background, camera) < 0) {
90 const Vec2f title_size = wiggly_text_size(&level_picker->wiggly_text);
93 &level_picker->wiggly_text,
95 vec(viewport.w * 0.5f - title_size.x * 0.5f, TITLE_MARGIN_TOP));
97 list_selector_render(camera, &level_picker->list_selector);
101 const float padding = 20.0f;
102 const Vec2f size = vec(3.0f, 3.0f);
103 const Vec2f position = vec(0.0f, viewport.h - size.y * FONT_CHAR_HEIGHT);
106 camera_render_text_screen(
108 "Press 'N' to create new level",
111 vec(position.x + padding,
112 position.y - padding));
118 int level_picker_update(LevelPicker *level_picker,
121 trace_assert(level_picker);
123 vec_add(&level_picker->camera_position,
124 vec(50.0f * delta_time, 0.0f));
126 if (wiggly_text_update(&level_picker->wiggly_text, delta_time) < 0) {
133 int level_picker_event(LevelPicker *level_picker,
134 const SDL_Event *event)
136 trace_assert(level_picker);
139 switch (event->type) {
140 case SDL_WINDOWEVENT: {
141 switch (event->window.event) {
142 case SDL_WINDOWEVENT_SHOWN:
143 case SDL_WINDOWEVENT_SIZE_CHANGED: {
144 const Vec2f font_scale = vec(5.0f, 5.0f);
145 const float padding_bottom = 50.0f;
148 SDL_GetRendererOutputSize(SDL_GetRenderer(SDL_GetWindowFromID(event->window.windowID)), &width, NULL);
150 const Vec2f title_size = wiggly_text_size(&level_picker->wiggly_text);
152 const Vec2f selector_size = list_selector_size(
153 &level_picker->list_selector,
157 level_picker->list_selector.position =
158 vec((float)width * 0.5f - selector_size.x * 0.5f,
159 TITLE_MARGIN_TOP + title_size.y + TITLE_MARGIN_BOTTOM);
165 return list_selector_event(&level_picker->list_selector, event);
168 int level_picker_input(LevelPicker *level_picker,
169 const Uint8 *const keyboard_state,
170 SDL_Joystick *the_stick_of_joy)
172 trace_assert(level_picker);
173 trace_assert(keyboard_state);
174 (void) the_stick_of_joy;
178 const char *level_picker_selected_level(const LevelPicker *level_picker)
180 trace_assert(level_picker);
182 if (level_picker->list_selector.selected_item < 0) {
186 LevelMetadata *metadata = dynarray_pointer_at(
187 &level_picker->level_folder.metadatas,
188 (size_t)level_picker->list_selector.selected_item);
190 return metadata->filepath;
193 void level_picker_clean_selection(LevelPicker *level_picker)
195 trace_assert(level_picker);
196 level_picker->list_selector.selected_item = -1;
199 int level_picker_enter_camera_event(LevelPicker *level_picker,
202 camera_center_at(camera, level_picker->camera_position);