]> git.lizzy.rs Git - nothing.git/blob - src/game/level_picker.c
(#1153) Remove TODO for #1157 (sorry!) and cleanup key handling.
[nothing.git] / src / game / level_picker.c
1 #include <stdio.h>
2
3 #include "./level_picker.h"
4 #include "game/level/background.h"
5 #include "game/sprite_font.h"
6 #include "system/lt.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"
15
16 #define TITLE_MARGIN_TOP 100.0f
17 #define TITLE_MARGIN_BOTTOM 100.0f
18
19 struct LevelPicker
20 {
21     Lt *lt;
22     Background background;
23     Vec2f camera_position;
24     LevelFolder *level_folder;
25     WigglyText wiggly_text;
26     ListSelector *list_selector;
27 };
28
29 LevelPicker *create_level_picker(const Sprite_font *sprite_font, const char *dirpath)
30 {
31     trace_assert(dirpath);
32
33     Lt *lt = create_lt();
34
35     LevelPicker *level_picker = PUSH_LT(
36         lt,
37         nth_calloc(1, sizeof(LevelPicker)),
38         free);
39     if (level_picker == NULL) {
40         RETURN_LT(lt, NULL);
41     }
42     level_picker->lt = lt;
43
44     level_picker->background = create_background(hexstr("073642"));
45
46     level_picker->camera_position = vec(0.0f, 0.0f);
47
48     level_picker->level_folder = PUSH_LT(
49         lt,
50         create_level_folder(dirpath),
51         destroy_level_folder);
52     if (level_picker->level_folder == NULL) {
53         RETURN_LT(lt, NULL);
54     }
55
56     level_picker->wiggly_text = (WigglyText) {
57         .text = "Select Level",
58         .scale = {10.0f, 10.0f},
59         .color = COLOR_WHITE,
60     };
61
62     level_picker->list_selector = PUSH_LT(
63         lt,
64         create_list_selector(
65             sprite_font,
66             level_folder_titles(level_picker->level_folder),
67             level_folder_count(level_picker->level_folder),
68             vec(5.0f, 5.0f),
69             50.0f),
70         destroy_list_selector);
71     if (level_picker->list_selector == NULL) {
72         RETURN_LT(lt, NULL);
73     }
74
75     return level_picker;
76 }
77
78 void destroy_level_picker(LevelPicker *level_picker)
79 {
80     trace_assert(level_picker);
81     RETURN_LT0(level_picker->lt);
82 }
83
84 int level_picker_render(const LevelPicker *level_picker,
85                         const Camera *camera)
86 {
87     trace_assert(level_picker);
88
89     const Rect viewport = camera_view_port_screen(camera);
90
91     if (background_render(&level_picker->background, camera) < 0) {
92         return -1;
93     }
94
95     const Vec2f title_size = wiggly_text_size(&level_picker->wiggly_text, camera);
96
97     if (wiggly_text_render(
98             &level_picker->wiggly_text,
99             camera,
100             vec(viewport.w * 0.5f - title_size.x * 0.5f, TITLE_MARGIN_TOP)) < 0) {
101         return -1;
102     }
103
104     if (list_selector_render(level_picker->list_selector, camera->renderer) < 0) {
105         return -1;
106     }
107
108     {
109         /* CSS */
110         const float padding = 20.0f;
111         const Vec2f size = vec(3.0f, 3.0f);
112         const Vec2f position = vec(0.0f, viewport.h - size.y * FONT_CHAR_HEIGHT);
113
114         /* HTML */
115         if (camera_render_text_screen(
116                 camera,
117                 "Press 'N' to create new level",
118                 size,
119                 COLOR_WHITE,
120                 vec(position.x + padding,
121                     position.y - padding)) < 0) {
122             return -1;
123         }
124     }
125
126     return 0;
127 }
128
129 int level_picker_update(LevelPicker *level_picker,
130                         float delta_time)
131 {
132     trace_assert(level_picker);
133
134     vec_add(&level_picker->camera_position,
135             vec(50.0f * delta_time, 0.0f));
136
137     if (wiggly_text_update(&level_picker->wiggly_text, delta_time) < 0) {
138         return -1;
139     }
140
141     return 0;
142 }
143
144 int level_picker_event(LevelPicker *level_picker,
145                        const SDL_Event *event,
146                        const Camera *camera)
147 {
148     trace_assert(level_picker);
149     trace_assert(event);
150
151     switch (event->type) {
152     case SDL_WINDOWEVENT: {
153         switch (event->window.event) {
154         case SDL_WINDOWEVENT_SHOWN:
155         case SDL_WINDOWEVENT_RESIZED: {
156             const Vec2f font_scale = vec(5.0f, 5.0f);
157             const float padding_bottom = 50.0f;
158
159             int width;
160             SDL_GetWindowSize(SDL_GetWindowFromID(event->window.windowID), &width, NULL);
161
162             const Vec2f title_size = wiggly_text_size(&level_picker->wiggly_text, camera);
163
164             const Vec2f selector_size = list_selector_size(
165                 level_picker->list_selector,
166                 font_scale,
167                 padding_bottom);
168
169             list_selector_move(
170                 level_picker->list_selector,
171                 vec((float)width * 0.5f - selector_size.x * 0.5f,
172                     TITLE_MARGIN_TOP + title_size.y + TITLE_MARGIN_BOTTOM));
173         } break;
174         }
175     } break;
176     }
177
178     return list_selector_event(level_picker->list_selector, event);
179 }
180
181 int level_picker_input(LevelPicker *level_picker,
182                        const Uint8 *const keyboard_state,
183                        SDL_Joystick *the_stick_of_joy)
184 {
185     trace_assert(level_picker);
186     trace_assert(keyboard_state);
187     (void) the_stick_of_joy;
188     return 0;
189 }
190
191 const char *level_picker_selected_level(const LevelPicker *level_picker)
192 {
193     trace_assert(level_picker);
194
195     const int selected_index = list_selector_selected(level_picker->list_selector);
196     if (selected_index < 0) {
197         return NULL;
198     }
199
200     const char **filenames = level_folder_filenames(level_picker->level_folder);
201
202     return filenames[selected_index];
203 }
204
205 void level_picker_clean_selection(LevelPicker *level_picker)
206 {
207     trace_assert(level_picker);
208     list_selector_clean_selection(level_picker->list_selector);
209 }
210
211 int level_picker_enter_camera_event(LevelPicker *level_picker,
212                                     Camera *camera)
213 {
214     camera_center_at(camera, level_picker->camera_position);
215     return 0;
216 }