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