]> git.lizzy.rs Git - nothing.git/blob - src/game/level/level_editor/color_picker.c
(#1118) Try to fix warnings on MacOS build
[nothing.git] / src / game / level / level_editor / color_picker.c
1 #include <stdbool.h>
2 #include <string.h>
3
4 #include "game/level/boxes.h"
5 #include "system/stacktrace.h"
6 #include "system/line_stream.h"
7 #include "system/log.h"
8 #include "game/camera.h"
9 #include "color_picker.h"
10 #include "color.h"
11 #include "undo_history.h"
12
13 #define COLOR_SLIDER_HEIGHT 60.0f
14 #define COLOR_PICKER_WIDTH 300.0f
15 #define COLOR_PICKER_HEIGHT (COLOR_SLIDER_HEIGHT * COLOR_SLIDER_N)
16 #define COLOR_PICKER_REFERENCE 1920.0f
17 #define COLOR_PICKER_HW_RATIO (COLOR_PICKER_HEIGHT/ COLOR_PICKER_WIDTH)
18 #define COLOR_PICKER_WR_RATIO (COLOR_PICKER_WIDTH / COLOR_PICKER_REFERENCE)
19
20 const char *slider_labels[COLOR_SLIDER_N] = {
21     "Hue",
22     "Saturation",
23     "Lightness"
24 };
25
26 ColorPicker create_color_picker_from_rgba(Color color)
27 {
28     Color color_hsla = rgba_to_hsla(color);
29     ColorPicker color_picker = {
30         .sliders = {
31             {0, color_hsla.r, 360.0f},
32             {0, color_hsla.g, 1.0f},
33             {0, color_hsla.b, 1.0f}
34         }
35     };
36     return color_picker;
37 }
38
39 int color_picker_read_from_line_stream(ColorPicker *color_picker,
40                                        LineStream *line_stream)
41 {
42     char color[7];
43     const char *line = line_stream_next(line_stream);
44     if (line == NULL) {
45         return -1;
46     }
47
48     if (sscanf(line, "%6s", color) == EOF) {
49         log_fail("Could not read color\n");
50     }
51
52     *color_picker = create_color_picker_from_rgba(hexstr(color));
53
54     return 0;
55 }
56
57 int color_picker_render(const ColorPicker *color_picker,
58                         const Camera *camera)
59 {
60     trace_assert(color_picker);
61     trace_assert(camera);
62
63     const Rect viewport = camera_view_port_screen(camera);
64     const Rect boundary = rect(
65         0.0f, 0.0f,
66         viewport.w * COLOR_PICKER_WR_RATIO,
67         viewport.w * COLOR_PICKER_WR_RATIO * COLOR_PICKER_HW_RATIO);
68
69     const float color_slider_height =
70         boundary.h / (COLOR_SLIDER_N + 1.0f);
71
72     if (camera_fill_rect_screen(
73             camera,
74             rect(boundary.x, boundary.y,
75                  boundary.w, color_slider_height),
76             color_picker_rgba(color_picker)) < 0) {
77         return -1;
78     }
79
80     for (ColorPickerSlider index = 0; index < COLOR_SLIDER_N; ++index) {
81         const Rect slider_rect =
82             rect(boundary.x,
83                  boundary.y + color_slider_height * (float) (index + 1),
84                  boundary.w, color_slider_height);
85         const float font_scale = boundary.w / COLOR_PICKER_WIDTH;
86         const Vec2f label_size = vec(2.5f * font_scale, 2.5f * font_scale);
87
88         if (slider_render(
89                 &color_picker->sliders[index],
90                 camera,
91                 slider_rect) < 0) {
92             return -1;
93         }
94
95         if (camera_render_text_screen(
96                 camera,
97                 slider_labels[index],
98                 label_size,
99                 COLOR_BLACK,
100                 vec(slider_rect.x + boundary.w,
101                     slider_rect.y + color_slider_height * 0.5f - label_size.y * (float) FONT_CHAR_HEIGHT * 0.5f)) < 0) {
102             return -1;
103         }
104     }
105
106     return 0;
107 }
108
109 // TODO(#932): the `selected` event propagation control is cumbersome
110 int color_picker_event(ColorPicker *color_picker,
111                        const SDL_Event *event,
112                        const Camera *camera,
113                        int *selected_out)
114 {
115     trace_assert(color_picker);
116     trace_assert(event);
117     trace_assert(camera);
118
119     int selected = 0;
120
121     const Rect viewport = camera_view_port_screen(camera);
122     const Rect boundary = rect(
123         0.0f, 0.0f,
124         viewport.w * COLOR_PICKER_WR_RATIO,
125         viewport.w * COLOR_PICKER_WR_RATIO * COLOR_PICKER_HW_RATIO);
126
127     const float color_slider_height =
128         boundary.h / (COLOR_SLIDER_N + 1.0f);
129
130     for (ColorPickerSlider index = 0;
131          !selected && index < COLOR_SLIDER_N;
132          ++index) {
133         if (slider_event(
134                 &color_picker->sliders[index],
135                 event,
136                 rect(boundary.x,
137                      boundary.y + color_slider_height * (float) (index + 1),
138                      boundary.w, color_slider_height),
139                 &selected) < 0) {
140             return -1;
141         }
142     }
143
144     if (selected_out) {
145         *selected_out = selected;
146     }
147
148     return 0;
149 }
150
151 Color color_picker_rgba(const ColorPicker *color_picker)
152 {
153     return hsla(
154         color_picker->sliders[COLOR_SLIDER_HUE].value,
155         color_picker->sliders[COLOR_SLIDER_SAT].value,
156         color_picker->sliders[COLOR_SLIDER_LIT].value,
157         1.0f);
158 }