]> git.lizzy.rs Git - nothing.git/blob - src/game/level/level_editor/layer_picker.c
Introduce Phantom Platforms
[nothing.git] / src / game / level / level_editor / layer_picker.c
1 #include <stdbool.h>
2 #include <string.h>
3
4 #include <SDL.h>
5
6 #include "system/stacktrace.h"
7 #include "layer_picker.h"
8 #include "color.h"
9 #include "game/camera.h"
10 #include "math/rect.h"
11 #include "math/extrema.h"
12 #include "game/sprite_font.h"
13
14 #define LAYER_TITLE_PADDING 15.0f
15 #define LAYER_TITLE_SIZE 3.0f
16 #define LAYER_SELECTED_OFFSET 15.0f
17
18 static const Color LAYER_CELL_BACKGROUND_COLORS[LAYER_PICKER_N] = {
19     {1.0f, 0.0f, 0.0f, 1.0f}, // LAYER_PICKER_BACKGROUND
20     {0.0f, 1.0f, 0.0f, 1.0f}, // LAYER_PICKER_PLAYER
21     {0.6f, 0.6f, 1.0f, 1.0f}, // LAYER_PICKER_BACK_PLATFORMS
22     {0.0f, 0.0f, 1.0f, 1.0f}, // LAYER_PICKER_PLATFORMS
23     {1.0f, 1.0f, 1.0f, 1.0f}, // LAYER_PICKER_GOALS
24     {1.0f, 0.2f, 0.6f, 1.0f}, // LAYER_PICKER_LAVA
25     {0.2f, 1.0f, 0.6f, 1.0f}, // LAYER_PICKER_BOXES
26     {0.2f, 0.6f, 1.0f, 1.0f}, // LAYER_PICKER_LABELS
27     {0.2f, 1.0f, 0.6f, 1.0f}, // LAYER_PICKER_REGIONS
28     {0.2f, 1.0f, 0.6f, 1.0f}, // LAYER_PICKER_PP
29 };
30
31 static const char *LAYER_CELL_TITLES[LAYER_PICKER_N] = {
32     "Background",              // LAYER_PICKER_BACKGROUND
33     "Player",                  // LAYER_PICKER_PLAYER
34     "Back Platforms",          // LAYER_PICKER_BACK_PLATFORMS
35     "Platforms",               // LAYER_PICKER_PLATFORMS
36     "Goals",                   // LAYER_PICKER_GOALS
37     "Lava",                    // LAYER_PICKER_LAVA
38     "Boxes",                   // LAYER_PICKER_BOXES
39     "Labels",                  // LAYER_PICKER_LABELS
40     "Regions",                 // LAYER_PICKER_REGIONS
41     "Phantom Platforms",       // LAYER_PICKER_PP
42 };
43
44 inline static float layer_picker_max_width(void)
45 {
46     size_t max = 0;
47
48     for (size_t i = 0; i < LAYER_PICKER_N; ++i) {
49         max = max_size_t(max, strlen(LAYER_CELL_TITLES[i]));
50     }
51
52     return (float) max * FONT_CHAR_WIDTH * LAYER_TITLE_SIZE + LAYER_TITLE_PADDING * 2.0f;
53 }
54
55 #define LAYER_CELL_WIDTH layer_picker_max_width()
56 #define LAYER_CELL_HEIGHT (LAYER_TITLE_SIZE * FONT_CHAR_HEIGHT + LAYER_TITLE_PADDING * 2.0f)
57 #define LAYER_CELL_REFERENCE 1980.0f
58 #define LAYER_CELL_WR_RATIO (LAYER_CELL_WIDTH / LAYER_CELL_REFERENCE)
59 #define LAYER_CELL_HW_RATIO (LAYER_CELL_HEIGHT / LAYER_CELL_WIDTH)
60 #define LAYER_TITLE_SW_RATIO (LAYER_TITLE_SIZE / LAYER_CELL_WIDTH)
61 #define LAYER_TITLE_PW_RATIO (LAYER_TITLE_PADDING / LAYER_CELL_WIDTH)
62 #define LAYER_CELL_OW_RATIO (LAYER_SELECTED_OFFSET / LAYER_CELL_WIDTH)
63
64 int layer_picker_render(const LayerPicker *layer_picker,
65                         const Camera *camera)
66 {
67     trace_assert(layer_picker);
68     trace_assert(camera);
69
70     const Rect viewport = camera_view_port_screen(camera);
71
72     for (size_t i = 0; i < LAYER_PICKER_N; ++i) {
73         const Vec2f size = {
74             .x = viewport.w * LAYER_CELL_WR_RATIO,
75             .y = viewport.w * LAYER_CELL_WR_RATIO * LAYER_CELL_HW_RATIO
76         };
77
78         Vec2f position = {
79             .x = 0.0f,
80             .y = viewport.h * 0.5f - size.y * LAYER_PICKER_N * 0.5f
81         };
82
83         Color color = LAYER_CELL_BACKGROUND_COLORS[i];
84
85         if (*layer_picker == i) {
86             position.x += size.x * LAYER_CELL_OW_RATIO;
87         } else {
88             color.a *= 0.70f;
89         }
90
91         if (camera_fill_rect_screen(
92                 camera,
93                 rect(
94                     position.x,
95                     size.y * (float) i + position.y,
96                     size.x, size.y),
97                 color) < 0) {
98             return -1;
99         }
100
101         camera_render_text_screen(
102             camera,
103             LAYER_CELL_TITLES[i],
104             vec(size.x * LAYER_TITLE_SW_RATIO,
105                 size.x * LAYER_TITLE_SW_RATIO),
106             color_invert(color),
107             vec(position.x + size.x * LAYER_TITLE_PW_RATIO,
108                 size.y * (float) i + position.y + size.x * LAYER_TITLE_PW_RATIO));
109     }
110
111     return 0;
112 }
113
114 int layer_picker_event(LayerPicker *layer_picker,
115                        const SDL_Event *event,
116                        const Camera *camera,
117                        bool *selected)
118 {
119     trace_assert(layer_picker);
120     trace_assert(event);
121     trace_assert(camera);
122
123     const Rect viewport = camera_view_port_screen(camera);
124
125     const Vec2f size = {
126         .x = viewport.w * LAYER_CELL_WR_RATIO,
127         .y = viewport.w * LAYER_CELL_WR_RATIO * LAYER_CELL_HW_RATIO
128     };
129
130     const Vec2f position = {
131         .x = 0.0f,
132         .y = viewport.h * 0.5f - size.y * LAYER_PICKER_N * 0.5f
133     };
134
135     switch (event->type) {
136     case SDL_MOUSEBUTTONDOWN: {
137         for (LayerPicker i = 0; i < LAYER_PICKER_N; ++i) {
138             const Rect cell = rect(
139                 position.x,
140                 size.y * (float) i + position.y,
141                 size.x, size.y);
142             if (rect_contains_point(cell, vec((float) event->button.x, (float) event->button.y))) {
143                 *layer_picker = i;
144                 *selected = true;
145                 return 0;
146             }
147         }
148     } break;
149     }
150
151     return 0;
152 }