]> git.lizzy.rs Git - nothing.git/blobdiff - src/game/level/level_editor/point_layer.c
Merge pull request #902 from tsoding/893
[nothing.git] / src / game / level / level_editor / point_layer.c
index 076b5b9b000efaad30315f7486fb852dac843b80..d774f9d85ecf1d44a84c1c9a2b4b18f71c67a0ba 100644 (file)
@@ -1,4 +1,6 @@
-#include <SDL2/SDL.h>
+#include <stdio.h>
+
+#include <SDL.h>
 
 #include "dynarray.h"
 #include "game/camera.h"
@@ -11,6 +13,7 @@
 #include "ui/edit_field.h"
 #include "./point_layer.h"
 #include "math/extrema.h"
+#include "./color_picker.h"
 
 #define POINT_LAYER_ELEMENT_RADIUS 10.0f
 
@@ -28,9 +31,17 @@ struct PointLayer
     Dynarray/*<char[ID_MAX_SIZE]>*/ *ids;
     Edit_field *edit_field;
     int selected;
+    ColorPicker color_picker;
 };
 
-// TODO(#837): PointLayer does not allow to edit itself
+LayerPtr point_layer_as_layer(PointLayer *point_layer)
+{
+    LayerPtr layer = {
+        .type = LAYER_POINT,
+        .ptr = point_layer
+    };
+    return layer;
+}
 
 PointLayer *create_point_layer_from_line_stream(LineStream *line_stream)
 {
@@ -101,6 +112,8 @@ PointLayer *create_point_layer_from_line_stream(LineStream *line_stream)
 
     point_layer->selected = -1;
 
+    point_layer->color_picker.color = rgba(1.0f, 0.0f, 0.0f, 1.0f);
+
     return point_layer;
 }
 
@@ -111,7 +124,8 @@ void destroy_point_layer(PointLayer *point_layer)
 }
 
 int point_layer_render(const PointLayer *point_layer,
-                       Camera *camera)
+                       Camera *camera,
+                       float fa)
 {
     trace_assert(point_layer);
     trace_assert(camera);
@@ -119,7 +133,6 @@ int point_layer_render(const PointLayer *point_layer,
     const int n = (int) dynarray_count(point_layer->points);
     Point *points = dynarray_data(point_layer->points);
     Color *colors = dynarray_data(point_layer->colors);
-    char *ids = dynarray_data(point_layer->ids);
 
     for (int i = 0; i < n; ++i) {
         const Triangle t = triangle_mat3x3_product(
@@ -128,6 +141,10 @@ int point_layer_render(const PointLayer *point_layer,
                 trans_mat(points[i].x, points[i].y),
                 scale_mat(POINT_LAYER_ELEMENT_RADIUS)));
 
+        const Color color = color_scale(
+            colors[i],
+            rgba(1.0f, 1.0f, 1.0f, fa));
+
         if (i == point_layer->selected) {
             const Triangle t0 = triangle_mat3x3_product(
                 equilateral_triangle(),
@@ -135,43 +152,54 @@ int point_layer_render(const PointLayer *point_layer,
                     trans_mat(points[i].x, points[i].y),
                     scale_mat(15.0f)));
 
-            if (camera_fill_triangle(camera, t0, color_invert(colors[i])) < 0) {
+            if (camera_fill_triangle(camera, t0, color_invert(color)) < 0) {
                 return -1;
             }
         }
 
-        if (camera_fill_triangle(camera, t, colors[i]) < 0) {
+        if (camera_fill_triangle(camera, t, color) < 0) {
             return -1;
         }
 
-        if (camera_render_debug_text(camera, ids + ID_MAX_SIZE * i, points[i]) < 0) {
-            return -1;
-        }
+        /* TODO(#854): The ids of PointLayer are not displayed constantly */
     }
 
     if (point_layer->state == POINT_LAYER_ID_EDITING_STATE) {
+        /* TODO(#855): PointLayer edit field is not scaled on zoom */
         if (edit_field_render(
                 point_layer->edit_field,
                 camera,
-                vec(0.0f, 0.0f)) < 0) {
+                camera_point(camera, points[point_layer->selected])) < 0) {
             return -1;
         }
     }
 
+    if (color_picker_render(&point_layer->color_picker, camera) < 0) {
+        return -1;
+    }
+
+
     return 0;
 }
 
-// TODO(#841): PointLayer does not allow to remove elements
 
-int point_layer_mouse_button(PointLayer *point_layer,
-                             const SDL_MouseButtonEvent *event,
-                             const Camera *camera,
-                             Color color)
+static int point_layer_mouse_button(PointLayer *point_layer,
+                                    const SDL_MouseButtonEvent *event,
+                                    const Camera *camera)
 {
     trace_assert(point_layer);
     trace_assert(event);
 
-    if (point_layer->state == POINT_LAYER_NORMAL_STATE &&
+    bool selected = false;
+    if (color_picker_mouse_button(
+            &point_layer->color_picker,
+            event,
+            &selected) < 0) {
+        return -1;
+    }
+
+    if (!selected &&
+        point_layer->state == POINT_LAYER_NORMAL_STATE &&
         event->type == SDL_MOUSEBUTTONDOWN &&
         event->button == SDL_BUTTON_LEFT) {
         const int n = (int) dynarray_count(point_layer->points);
@@ -187,20 +215,20 @@ int point_layer_mouse_button(PointLayer *point_layer,
 
         char id[ID_MAX_SIZE];
 
-        // TODO(#842): PointLayer does not allow to specify an id of a point
         for (size_t i = 0; i < ID_MAX_SIZE - 1; ++i) {
             id[i] = (char) ('a' + rand() % ('z' - 'a' + 1));
         }
         id[ID_MAX_SIZE - 1] = '\0';
 
         dynarray_push(point_layer->points, &point);
-        dynarray_push(point_layer->colors, &color);
+        dynarray_push(point_layer->colors, &point_layer->color_picker.color);
         dynarray_push(point_layer->ids, id);
     }
 
     return 0;
 }
 
+static
 int point_layer_keyboard(PointLayer *point_layer,
                          const SDL_KeyboardEvent *key)
 {
@@ -227,6 +255,7 @@ int point_layer_keyboard(PointLayer *point_layer,
                     edit_field_replace(
                         point_layer->edit_field,
                         ids + ID_MAX_SIZE * point_layer->selected);
+                    SDL_StartTextInput();
                 }
             } break;
 
@@ -240,13 +269,23 @@ int point_layer_keyboard(PointLayer *point_layer,
             return -1;
         }
 
-        if (key->type == SDL_KEYDOWN && key->keysym.sym == SDLK_RETURN) {
-            char *ids = dynarray_data(point_layer->ids);
-            const char *text = edit_field_as_text(point_layer->edit_field);
-            size_t n = max_size_t(strlen(text), ID_MAX_SIZE - 1);
-            memcpy(ids + point_layer->selected * ID_MAX_SIZE, text, n);
-            *(ids + point_layer->selected * ID_MAX_SIZE + n) = '\0';
-            point_layer->state = POINT_LAYER_NORMAL_STATE;
+        if (key->type == SDL_KEYDOWN) {
+            switch(key->keysym.sym) {
+            case SDLK_RETURN: {
+                char *ids = dynarray_data(point_layer->ids);
+                const char *text = edit_field_as_text(point_layer->edit_field);
+                size_t n = max_size_t(strlen(text), ID_MAX_SIZE - 1);
+                memcpy(ids + point_layer->selected * ID_MAX_SIZE, text, n);
+                *(ids + point_layer->selected * ID_MAX_SIZE + n) = '\0';
+                point_layer->state = POINT_LAYER_NORMAL_STATE;
+                SDL_StopTextInput();
+            } break;
+
+            case SDLK_ESCAPE: {
+                point_layer->state = POINT_LAYER_NORMAL_STATE;
+                SDL_StopTextInput();
+            } break;
+            }
         }
     } break;
     }
@@ -255,6 +294,7 @@ int point_layer_keyboard(PointLayer *point_layer,
     return 0;
 }
 
+static
 int point_layer_text_input(PointLayer *point_layer,
                            const SDL_TextInputEvent *text_input)
 {
@@ -262,12 +302,44 @@ int point_layer_text_input(PointLayer *point_layer,
     trace_assert(text_input);
 
     if (point_layer->state == POINT_LAYER_ID_EDITING_STATE) {
+        /* TODO(#856): Special development keybindings interfere with id editing field */
         return edit_field_text_input(point_layer->edit_field, text_input);
     }
 
     return 0;
 }
 
+int point_layer_event(PointLayer *point_layer,
+                      const SDL_Event *event,
+                      const Camera *camera)
+{
+    trace_assert(point_layer);
+    trace_assert(event);
+    trace_assert(camera);
+
+    switch(event->type) {
+    case SDL_MOUSEBUTTONDOWN:
+    case SDL_MOUSEBUTTONUP:
+        return point_layer_mouse_button(
+            point_layer,
+            &event->button,
+            camera);
+
+    case SDL_KEYDOWN:
+    case SDL_KEYUP:
+        return point_layer_keyboard(
+            point_layer,
+            &event->key);
+
+    case SDL_TEXTINPUT:
+        return point_layer_text_input(
+            point_layer,
+            &event->text);
+    }
+
+    return 0;
+}
+
 size_t point_layer_count(const PointLayer *point_layer)
 {
     trace_assert(point_layer);
@@ -291,3 +363,26 @@ const char *point_layer_ids(const PointLayer *point_layer)
     trace_assert(point_layer);
     return dynarray_data(point_layer->ids);
 }
+
+int point_layer_dump_stream(const PointLayer *point_layer,
+                            FILE *filedump)
+{
+    trace_assert(point_layer);
+    trace_assert(filedump);
+
+    size_t n = dynarray_count(point_layer->ids);
+    char *ids = dynarray_data(point_layer->ids);
+    Point *points = dynarray_data(point_layer->points);
+    Color *colors = dynarray_data(point_layer->colors);
+
+    fprintf(filedump, "%ld\n", n);
+    for (size_t i = 0; i < n; ++i) {
+        fprintf(filedump, "%s %f %f ",
+                ids + ID_MAX_SIZE * i,
+                points[i].x, points[i].y);
+        color_hex_to_stream(colors[i], filedump);
+        fprintf(filedump, "\n");
+    }
+
+    return 0;
+}