]> git.lizzy.rs Git - nothing.git/blobdiff - src/game/level/level_editor/color_picker.c
(#1050) Replace system clipboard with internal one
[nothing.git] / src / game / level / level_editor / color_picker.c
index a1227c039dc7c05c60efa838e6a096a44a6dcfe7..6ed915c27cfb5740b177fada915af3699d9fe55d 100644 (file)
@@ -1,30 +1,58 @@
 #include <stdbool.h>
+#include <string.h>
 
 #include "game/level/boxes.h"
 #include "system/stacktrace.h"
+#include "system/line_stream.h"
+#include "system/log.h"
 #include "game/camera.h"
-#include "proto_rect.h"
 #include "color_picker.h"
 #include "color.h"
+#include "undo_history.h"
 
-#define COLOR_CELL_WIDTH 50.0f
-#define COLOR_CELL_HEIGHT 50.0f
+// TODO(#1021): ColorPicker doesn't have any padding between the sliders
+#define COLOR_SLIDER_HEIGHT 60.0f
+#define COLOR_PICKER_WIDTH 300.0f
+#define COLOR_PICKER_HEIGHT (COLOR_SLIDER_HEIGHT * COLOR_SLIDER_N)
+#define COLOR_PICKER_REFERENCE 1920.0f
+#define COLOR_PICKER_HW_RATIO (COLOR_PICKER_HEIGHT/ COLOR_PICKER_WIDTH)
+#define COLOR_PICKER_WR_RATIO (COLOR_PICKER_WIDTH / COLOR_PICKER_REFERENCE)
 
-// TODO(#788): Colors of ColorPicker are poor
-static Color colors[] = {
-    {1.0f, 0.0f, 0.0f, 1.0f},
-    {0.0f, 1.0f, 0.0f, 1.0f},
-    {0.0f, 0.0f, 1.0f, 1.0f}
+const char *slider_labels[COLOR_SLIDER_N] = {
+    "Hue",
+    "Saturation",
+    "Lightness"
 };
-static const size_t colors_count = sizeof(colors) / sizeof(Color);
 
-LayerPtr color_picker_as_layer(ColorPicker *color_picker)
+ColorPicker create_color_picker_from_rgba(Color color)
 {
-    LayerPtr layer = {
-        .ptr = color_picker,
-        .type = LAYER_COLOR_PICKER
+    Color color_hsla = rgba_to_hsla(color);
+    ColorPicker color_picker = {
+        .sliders = {
+            {0, color_hsla.r, 360.0f},
+            {0, color_hsla.g, 1.0f},
+            {0, color_hsla.b, 1.0f}
+        }
     };
-    return layer;
+    return color_picker;
+}
+
+int color_picker_read_from_line_stream(ColorPicker *color_picker,
+                                       LineStream *line_stream)
+{
+    char color[7];
+    const char *line = line_stream_next(line_stream);
+    if (line == NULL) {
+        return -1;
+    }
+
+    if (sscanf(line, "%6s", color) == EOF) {
+        log_fail("Could not read color\n");
+    }
+
+    *color_picker = create_color_picker_from_rgba(hexstr(color));
+
+    return 0;
 }
 
 int color_picker_render(const ColorPicker *color_picker,
@@ -33,13 +61,45 @@ int color_picker_render(const ColorPicker *color_picker,
     trace_assert(color_picker);
     trace_assert(camera);
 
-    for (size_t i = 0; i < colors_count; ++i) {
-        if (camera_fill_rect_screen(
+    const Rect viewport = camera_view_port_screen(camera);
+    const Rect boundary = rect(
+        0.0f, 0.0f,
+        viewport.w * COLOR_PICKER_WR_RATIO,
+        viewport.w * COLOR_PICKER_WR_RATIO * COLOR_PICKER_HW_RATIO);
+
+    const float color_slider_height =
+        boundary.h / (COLOR_SLIDER_N + 1.0f);
+
+    if (camera_fill_rect_screen(
+            camera,
+            rect(boundary.x, boundary.y,
+                 boundary.w, color_slider_height),
+            color_picker_rgba(color_picker)) < 0) {
+        return -1;
+    }
+
+    for (ColorPickerSlider index = 0; index < COLOR_SLIDER_N; ++index) {
+        const Rect slider_rect =
+            rect(boundary.x,
+                 boundary.y + color_slider_height * (float) (index + 1),
+                 boundary.w, color_slider_height);
+        const float font_scale = boundary.w / COLOR_PICKER_WIDTH;
+        const Point label_size = vec(2.5f * font_scale, 2.5f * font_scale);
+
+        if (slider_render(
+                &color_picker->sliders[index],
                 camera,
-                rect(COLOR_CELL_WIDTH * (float) i, 0,
-                     COLOR_CELL_WIDTH,
-                     COLOR_CELL_HEIGHT),
-                colors[i]) < 0) {
+                slider_rect) < 0) {
+            return -1;
+        }
+
+        if (camera_render_text_screen(
+                camera,
+                slider_labels[index],
+                label_size,
+                COLOR_BLACK,
+                vec(slider_rect.x + boundary.w,
+                    slider_rect.y + color_slider_height * 0.5f - label_size.y * (float) FONT_CHAR_HEIGHT * 0.5f)) < 0) {
             return -1;
         }
     }
@@ -47,33 +107,53 @@ int color_picker_render(const ColorPicker *color_picker,
     return 0;
 }
 
-int color_picker_mouse_button(ColorPicker *color_picker,
-                              const SDL_MouseButtonEvent *event,
-                              bool *selected)
+// TODO(#932): the `selected` event propagation control is cumbersome
+int color_picker_event(ColorPicker *color_picker,
+                       const SDL_Event *event,
+                       const Camera *camera,
+                       int *selected_out)
 {
     trace_assert(color_picker);
     trace_assert(event);
+    trace_assert(camera);
+
+    int selected = 0;
+
+    const Rect viewport = camera_view_port_screen(camera);
+    const Rect boundary = rect(
+        0.0f, 0.0f,
+        viewport.w * COLOR_PICKER_WR_RATIO,
+        viewport.w * COLOR_PICKER_WR_RATIO * COLOR_PICKER_HW_RATIO);
 
-    if (event->type == SDL_MOUSEBUTTONDOWN) {
-        switch (event->button) {
-        case SDL_BUTTON_LEFT: {
-            for (size_t i = 0; i < colors_count; ++i) {
-                const Vec mouse_position = vec((float) event->x, (float) event->y);
-                const Rect color_cell =
-                    rect(COLOR_CELL_WIDTH * (float) i, 0,
-                         COLOR_CELL_WIDTH,
-                         COLOR_CELL_HEIGHT);
-                if (rect_contains_point(color_cell, mouse_position)) {
-                    color_picker->color = colors[i];
-                    if (selected) {
-                        *selected = true;
-                    }
-                    return 0;
-                }
-            }
-        } break;
+    const float color_slider_height =
+        boundary.h / (COLOR_SLIDER_N + 1.0f);
+
+    for (ColorPickerSlider index = 0;
+         !selected && index < COLOR_SLIDER_N;
+         ++index) {
+        if (slider_event(
+                &color_picker->sliders[index],
+                event,
+                rect(boundary.x,
+                     boundary.y + color_slider_height * (float) (index + 1),
+                     boundary.w, color_slider_height),
+                &selected) < 0) {
+            return -1;
         }
     }
 
+    if (selected_out) {
+        *selected_out = selected;
+    }
+
     return 0;
 }
+
+Color color_picker_rgba(const ColorPicker *color_picker)
+{
+    return hsla(
+        color_picker->sliders[COLOR_SLIDER_HUE].value,
+        color_picker->sliders[COLOR_SLIDER_SAT].value,
+        color_picker->sliders[COLOR_SLIDER_LIT].value,
+        1.0f);
+}