]> git.lizzy.rs Git - nothing.git/blobdiff - src/game/level/level_editor/rect_layer.c
Add TODO(#943)
[nothing.git] / src / game / level / level_editor / rect_layer.c
index 8780613689adc912c001a79b21fc2e42550ff26b..69c410a45f4647780d606da5b762a35eef804a62 100644 (file)
 #include "system/str.h"
 
 #define RECT_LAYER_ID_MAX_SIZE 36
-#define RECT_LAYER_SELECTION_THICCNESS 10.0f
+#define RECT_LAYER_SELECTION_THICCNESS 5.0f
 #define PROTO_AREA_THRESHOLD 10.0
 
+// TODO(#942): RectLayer does not allow to move rectangle arround
 typedef enum {
     RECT_LAYER_IDLE = 0,
-    RECT_LAYER_PROTO
+    RECT_LAYER_PROTO,
+    RECT_LAYER_RESIZE
 } RectLayerState;
 
 /* TODO(#886): RectLayer does not allow to modify ids of Rects */
@@ -49,27 +51,29 @@ static int rect_layer_rect_at(RectLayer *layer, Vec position)
     return -1;
 }
 
-static int rect_layer_delete_rect_at(RectLayer *layer, Vec position)
+static int rect_layer_delete_rect_at(RectLayer *layer, size_t i)
 {
     trace_assert(layer);
 
-    int i = rect_layer_rect_at(layer, position);
-    if (i >= 0) {
-        dynarray_delete_at(layer->rects, (size_t)i);
-        dynarray_delete_at(layer->colors, (size_t)i);
-        dynarray_delete_at(layer->ids, (size_t)i);
-    }
+    dynarray_delete_at(layer->rects, i);
+    dynarray_delete_at(layer->colors, i);
+    dynarray_delete_at(layer->ids, i);
 
     return 0;
 }
 
+static Rect rect_layer_resize_anchor(const RectLayer *layer, size_t i)
+{
+    Rect *rects = dynarray_data(layer->rects);
+    return rect(rects[i].x + rects[i].w,
+                rects[i].y + rects[i].h,
+                RECT_LAYER_SELECTION_THICCNESS * 2.0f,
+                RECT_LAYER_SELECTION_THICCNESS * 2.0f);
+}
+
 static int rect_layer_add_rect(RectLayer *layer, Rect rect, Color color)
 {
     trace_assert(layer);
-    (void) rect_layer_delete_rect_at; // TODO:
-                                      // rect_layer_delete_rect_at is
-                                      // unused until #938 is
-                                      // implemented
 
     if (dynarray_push(layer->rects, &rect) < 0) {
         return -1;
@@ -137,7 +141,7 @@ RectLayer *create_rect_layer(void)
     }
 
     layer->color_picker = create_color_picker_from_rgba(rgba(1.0f, 0.0f, 0.0f, 1.0f));
-    layer->selection = 0;
+    layer->selection = -1;
 
     return layer;
 }
@@ -207,12 +211,23 @@ int rect_layer_render(const RectLayer *layer, Camera *camera, int active)
 
     for (size_t i = 0; i < n; ++i) {
         if (layer->selection == (int) i) {
-            if (active && camera_fill_rect(
-                    camera,
-                    // TODO: thiccness of RectLayer selection should be probably based on zoom
-                    rect_scale(rects[i], RECT_LAYER_SELECTION_THICCNESS),
-                    color_invert(colors[i])) < 0) {
-                return -1;
+            if (active) {
+                const Color color = color_invert(colors[i]);
+
+                if (camera_fill_rect(
+                        camera,
+                        // TODO(#943): thiccness of RectLayer selection should be probably based on zoom
+                        rect_scale(rects[i], RECT_LAYER_SELECTION_THICCNESS),
+                        color) < 0) {
+                    return -1;
+                }
+
+                if (camera_fill_rect(
+                        camera,
+                        rect_layer_resize_anchor(layer, i),
+                        color) < 0) {
+                    return -1;
+                }
             }
         }
 
@@ -251,48 +266,77 @@ int rect_layer_event(RectLayer *layer, const SDL_Event *event, const Camera *cam
         return -1;
     }
 
-    if (!selected) {
-        const Color color = color_picker_rgba(&layer->color_picker);
-        if (layer->state == RECT_LAYER_PROTO) {
-            // Active
-            switch (event->type) {
-            case SDL_MOUSEBUTTONUP: {
-                switch (event->button.button) {
-                case SDL_BUTTON_LEFT: {
-                    const Rect real_rect =
-                        rect_from_points(
-                            layer->proto_begin,
-                            layer->proto_end);
-                    const float area = real_rect.w * real_rect.h;
-
-                    if (area >= PROTO_AREA_THRESHOLD) {
-                        rect_layer_add_rect(layer, real_rect, color);
-                    } else {
-                        log_info("The area is too small %f. Such small box won't be created.\n", area);
-                    }
-                    layer->state = RECT_LAYER_IDLE;
-                } break;
-                }
-            } break;
+    if (selected) {
+        return 0;
+    }
 
-            case SDL_MOUSEMOTION: {
-                layer->proto_end = camera_map_screen(
-                    camera,
-                    event->motion.x,
-                    event->motion.y);
+    const Color color = color_picker_rgba(&layer->color_picker);
+    if (layer->state == RECT_LAYER_PROTO) {
+        switch (event->type) {
+        case SDL_MOUSEBUTTONUP: {
+            switch (event->button.button) {
+            case SDL_BUTTON_LEFT: {
+                const Rect real_rect =
+                    rect_from_points(
+                        layer->proto_begin,
+                        layer->proto_end);
+                const float area = real_rect.w * real_rect.h;
+
+                if (area >= PROTO_AREA_THRESHOLD) {
+                    rect_layer_add_rect(layer, real_rect, color);
+                } else {
+                    log_info("The area is too small %f. Such small box won't be created.\n", area);
+                }
+                layer->state = RECT_LAYER_IDLE;
             } break;
             }
-        } else {
-            // Inactive
-            switch (event->type) {
-            case SDL_MOUSEBUTTONDOWN: {
-                switch (event->button.button) {
-                case SDL_BUTTON_LEFT: {
-                    Point position = camera_map_screen(
+        } break;
+
+        case SDL_MOUSEMOTION: {
+            layer->proto_end = camera_map_screen(
+                camera,
+                event->motion.x,
+                event->motion.y);
+        } break;
+        }
+    } else if (layer->state == RECT_LAYER_RESIZE) {
+        switch (event->type) {
+        case SDL_MOUSEMOTION: {
+            Rect *rects = dynarray_data(layer->rects);
+            trace_assert(layer->selection >= 0);
+            rects[layer->selection] = rect_from_points(
+                vec(rects[layer->selection].x, rects[layer->selection].y),
+                vec_sum(
+                    camera_map_screen(
                         camera,
                         event->button.x,
-                        event->button.y);
-
+                        event->button.y),
+                    vec(RECT_LAYER_SELECTION_THICCNESS * -0.5f,
+                        RECT_LAYER_SELECTION_THICCNESS * -0.5f)));
+        } break;
+
+        case SDL_MOUSEBUTTONUP: {
+            layer->state = RECT_LAYER_IDLE;
+        } break;
+        }
+    } else {
+        switch (event->type) {
+        case SDL_MOUSEBUTTONDOWN: {
+            switch (event->button.button) {
+            case SDL_BUTTON_LEFT: {
+                Point position = camera_map_screen(
+                    camera,
+                    event->button.x,
+                    event->button.y);
+
+                if (layer->selection >= 0 &&
+                    rect_contains_point(
+                        rect_layer_resize_anchor(
+                            layer,
+                            (size_t)layer->selection),
+                        position)) {
+                    layer->state = RECT_LAYER_RESIZE;
+                } else {
                     layer->selection = rect_layer_rect_at(layer, position);
 
                     if (layer->selection < 0) {
@@ -300,13 +344,25 @@ int rect_layer_event(RectLayer *layer, const SDL_Event *event, const Camera *cam
                         layer->proto_begin = position;
                         layer->proto_end = position;
                     }
-                } break;
                 }
             } break;
             }
+        } break;
+
+        case SDL_KEYDOWN: {
+            switch (event->key.keysym.sym) {
+            case SDLK_DELETE: {
+                if (layer->selection >= 0) {
+                    rect_layer_delete_rect_at(layer, (size_t) layer->selection);
+                    layer->selection = -1;
+                }
+            } break;
+            }
+        } break;
         }
     }
 
+
     return 0;
 }