]> git.lizzy.rs Git - nothing.git/blobdiff - src/game/level_picker.c
Merge pull request #1197 from tsoding/cleanup
[nothing.git] / src / game / level_picker.c
index 89c7e6fee002e621d0a9218cf680dde02646d2a5..b53b67ab38e35f53a0066593fd10c3cae3e0903e 100644 (file)
 #include <stdio.h>
 
 #include "./level_picker.h"
-#include "system/stacktrace.h"
+#include "game/level/background.h"
+#include "game/sprite_font.h"
 #include "system/lt.h"
 #include "system/nth_alloc.h"
+#include "system/stacktrace.h"
 #include "system/str.h"
-#include "game/level/background.h"
+#include "ui/list_selector.h"
+#include "system/log.h"
+#include "game/level_folder.h"
+#include "ui/wiggly_text.h"
+#include "ui/slider.h"
 
-/* TODO(#606): LevelPicker doesn't allow to select any levels */
+#define TITLE_MARGIN_TOP 100.0f
+#define TITLE_MARGIN_BOTTOM 100.0f
 
 struct LevelPicker
 {
     Lt *lt;
-    const char *dirpath;
-    Background *background;
-    Vec camera_position;
+    Background background;
+    Vec2f camera_position;
+    LevelFolder level_folder;
+    WigglyText wiggly_text;
+    ListSelector list_selector;
 };
 
+static inline
+const char *list_item_text(void *element)
+{
+    trace_assert(element);
+    return ((LevelMetadata *)element)->title;
+}
+
 LevelPicker *create_level_picker(const char *dirpath)
 {
     trace_assert(dirpath);
 
     Lt *lt = create_lt();
-    if (lt == NULL) {
-        return NULL;
-    }
 
     LevelPicker *level_picker = PUSH_LT(
         lt,
-        nth_alloc(sizeof(LevelPicker)),
+        nth_calloc(1, sizeof(LevelPicker)),
         free);
     if (level_picker == NULL) {
         RETURN_LT(lt, NULL);
     }
     level_picker->lt = lt;
 
-    level_picker->dirpath = PUSH_LT(
-        lt,
-        string_duplicate(dirpath, NULL),
-        free);
-    if (level_picker->dirpath == NULL) {
-        RETURN_LT(lt, NULL);
-    }
-
-    level_picker->background = PUSH_LT(
-        lt,
-        create_background(hexstr("073642")),
-        destroy_background);
-    if (level_picker->background == NULL) {
-        RETURN_LT(lt, NULL);
-    }
+    level_picker->background = create_background(hexstr("073642"));
 
     level_picker->camera_position = vec(0.0f, 0.0f);
 
+    level_picker->level_folder = create_level_folder();
+    level_folder_read("./assets/levels", &level_picker->level_folder);
+
+    level_picker->wiggly_text = (WigglyText) {
+        .text = "Select Level",
+        .scale = {10.0f, 10.0f},
+        .color = COLOR_WHITE,
+    };
+
+    level_picker->list_selector.items = level_picker->level_folder.metadatas;
+    level_picker->list_selector.font_scale = vec(5.0f, 5.0f);
+    level_picker->list_selector.padding_bottom = 50.0f;
+    level_picker->list_selector.list_item_text = list_item_text;
+
     return level_picker;
 }
 
 void destroy_level_picker(LevelPicker *level_picker)
 {
     trace_assert(level_picker);
+    destroy_level_folder(level_picker->level_folder);
     RETURN_LT0(level_picker->lt);
 }
 
 int level_picker_render(const LevelPicker *level_picker,
-                        Camera *camera,
-                        SDL_Renderer *renderer)
+                        const Camera *camera)
 {
     trace_assert(level_picker);
-    trace_assert(renderer);
 
-    if (background_render(level_picker->background, camera) < 0) {
+    const Rect viewport = camera_view_port_screen(camera);
+
+    if (background_render(&level_picker->background, camera) < 0) {
         return -1;
     }
 
+    const Vec2f title_size = wiggly_text_size(&level_picker->wiggly_text);
+
+    wiggly_text_render(
+        &level_picker->wiggly_text,
+        camera,
+        vec(viewport.w * 0.5f - title_size.x * 0.5f, TITLE_MARGIN_TOP));
+
+    list_selector_render(camera, &level_picker->list_selector);
+
+    {
+        /* CSS */
+        const float padding = 20.0f;
+        const Vec2f size = vec(3.0f, 3.0f);
+        const Vec2f position = vec(0.0f, viewport.h - size.y * FONT_CHAR_HEIGHT);
+
+        /* HTML */
+        camera_render_text_screen(
+            camera,
+            "Press 'N' to create new level",
+            size,
+            COLOR_WHITE,
+            vec(position.x + padding,
+                position.y - padding));
+    }
+
     return 0;
 }
 
@@ -84,14 +123,46 @@ int level_picker_update(LevelPicker *level_picker,
     vec_add(&level_picker->camera_position,
             vec(50.0f * delta_time, 0.0f));
 
+    if (wiggly_text_update(&level_picker->wiggly_text, delta_time) < 0) {
+        return -1;
+    }
+
     return 0;
 }
 
-int level_picker_event(LevelPicker *level_picker, const SDL_Event *event)
+int level_picker_event(LevelPicker *level_picker,
+                       const SDL_Event *event)
 {
     trace_assert(level_picker);
     trace_assert(event);
-    return 0;
+
+    switch (event->type) {
+    case SDL_WINDOWEVENT: {
+        switch (event->window.event) {
+        case SDL_WINDOWEVENT_SHOWN:
+        case SDL_WINDOWEVENT_SIZE_CHANGED: {
+            const Vec2f font_scale = vec(5.0f, 5.0f);
+            const float padding_bottom = 50.0f;
+
+            int width;
+            SDL_GetRendererOutputSize(SDL_GetRenderer(SDL_GetWindowFromID(event->window.windowID)), &width, NULL);
+
+            const Vec2f title_size = wiggly_text_size(&level_picker->wiggly_text);
+
+            const Vec2f selector_size = list_selector_size(
+                &level_picker->list_selector,
+                font_scale,
+                padding_bottom);
+
+            level_picker->list_selector.position =
+                vec((float)width * 0.5f - selector_size.x * 0.5f,
+                    TITLE_MARGIN_TOP + title_size.y + TITLE_MARGIN_BOTTOM);
+        } break;
+        }
+    } break;
+    }
+
+    return list_selector_event(&level_picker->list_selector, event);
 }
 
 int level_picker_input(LevelPicker *level_picker,
@@ -107,12 +178,22 @@ int level_picker_input(LevelPicker *level_picker,
 const char *level_picker_selected_level(const LevelPicker *level_picker)
 {
     trace_assert(level_picker);
-    return level_picker->dirpath;
+
+    if (level_picker->list_selector.selected_item < 0) {
+        return NULL;
+    }
+
+    LevelMetadata *metadata = dynarray_pointer_at(
+        &level_picker->level_folder.metadatas,
+        (size_t)level_picker->list_selector.selected_item);
+
+    return metadata->filepath;
 }
 
 void level_picker_clean_selection(LevelPicker *level_picker)
 {
     trace_assert(level_picker);
+    level_picker->list_selector.selected_item = -1;
 }
 
 int level_picker_enter_camera_event(LevelPicker *level_picker,