]> git.lizzy.rs Git - nothing.git/blobdiff - src/game/level/level_editor/rect_layer.c
(#164) Make layer translation units more unity build friendly
[nothing.git] / src / game / level / level_editor / rect_layer.c
index cdac135cbb8f48225ef0f14aaf1c4e0a22fee1c4..757db4d44f97622ff4434237e76e2cd365abe14c 100644 (file)
@@ -1,3 +1,4 @@
+#include <float.h>
 #include <errno.h>
 
 #include "game/camera.h"
 #include "undo_history.h"
 #include "game/level/action.h"
 #include "action_picker.h"
+#include "game.h"
 
-#define RECT_LAYER_SELECTION_THICCNESS 10.0f
+#define RECT_LAYER_SELECTION_THICCNESS 15.0f
 #define RECT_LAYER_ID_LABEL_SIZE vec(3.0f, 3.0f)
 #define CREATE_AREA_THRESHOLD 10.0
 #define RECT_LAYER_GRID_ROWS 3
 #define RECT_LAYER_GRID_COLUMNS 4
 
-static int clipboard = 0;
-static Rect clipboard_rect;
-static Color clipboard_color;
+static int rect_clipboard = 0;
+static Rect rect_clipboard_rect;
+static Color rect_clipboard_color;
+
+static Cursor_Style resize_styles[1 << RECT_SIDE_N] = {
+    0,                         // [0]
+    CURSOR_STYLE_RESIZE_VERT,  // [1]
+    CURSOR_STYLE_RESIZE_HORIS, // [2]
+    CURSOR_STYLE_RESIZE_DIAG1, // [3]
+    CURSOR_STYLE_RESIZE_VERT,  // [4]
+    0,                         // [5]
+    CURSOR_STYLE_RESIZE_DIAG2, // [6]
+    0,                         // [7]
+    CURSOR_STYLE_RESIZE_HORIS, // [8]
+    CURSOR_STYLE_RESIZE_DIAG2, // [9]
+    0,                         // [10]
+    0,                         // [11]
+    CURSOR_STYLE_RESIZE_DIAG1  // [12]
+};
 
 typedef enum {
     RECT_LAYER_IDLE = 0,
     RECT_LAYER_CREATE,
-    // TODO(#955): Rectangles in Level Editor have only one resize anchor to work with
     RECT_LAYER_RESIZE,
     RECT_LAYER_MOVE,
     RECT_LAYER_ID_RENAME,
@@ -40,6 +57,7 @@ typedef enum {
 struct RectLayer {
     Lt *lt;
     RectLayerState state;
+    int resize_mask;
     Dynarray *ids;
     Dynarray *rects;
     Dynarray *colors;
@@ -57,18 +75,21 @@ struct RectLayer {
     int id_name_counter;
     const char *id_name_prefix;
     Grid *grid;
+    Cursor *cursor;
+
+    int snapping_enabled;
 };
 
 typedef enum {
-    UNDO_ADD,
-    UNDO_DELETE,
-    UNDO_UPDATE,
-    UNDO_SWAP
-} UndoType;
+    RECT_UNDO_ADD,
+    RECT_UNDO_DELETE,
+    RECT_UNDO_UPDATE,
+    RECT_UNDO_SWAP
+} RectUndoType;
 
 // Delete, Update
 typedef struct {
-    UndoType type;
+    RectUndoType type;
     RectLayer *layer;
     size_t index;
     Rect rect;
@@ -79,47 +100,47 @@ typedef struct {
 
 // Add
 typedef struct {
-    UndoType type;
+    RectUndoType type;
     RectLayer *layer;
     size_t index;
 } UndoAddContext;
 
 // Swap
 typedef struct {
-    UndoType type;
+    RectUndoType type;
     RectLayer *layer;
     size_t index1;
     size_t index2;
 } UndoSwapContext;
 
 typedef union {
-    UndoType type;
+    RectUndoType type;
     UndoAddContext add;
     UndoElementContext element;
     UndoSwapContext swap;
-} UndoContext;
+} RectUndoContext;
 
 static
-UndoContext create_undo_add_context(RectLayer *layer, size_t index)
+RectUndoContext create_rect_undo_add_context(RectLayer *layer, size_t index)
 {
     trace_assert(layer);
     trace_assert(index < dynarray_count(layer->rects));
 
-    UndoContext undo_context;
-    undo_context.add.type = UNDO_ADD;
+    RectUndoContext undo_context;
+    undo_context.add.type = RECT_UNDO_ADD;
     undo_context.add.layer = layer;
     undo_context.add.index = index;
     return undo_context;
 }
 
 static
-UndoContext create_undo_element_context(RectLayer *layer)
+RectUndoContext create_rect_undo_element_context(RectLayer *layer)
 {
     trace_assert(layer);
     size_t index = (size_t) layer->selection;
     trace_assert(index < dynarray_count(layer->rects));
 
-    UndoContext undo_context;
+    RectUndoContext undo_context;
     undo_context.element.layer = layer;
     undo_context.element.index = index;
     dynarray_copy_to(layer->rects, &undo_context.element.rect, index);
@@ -130,26 +151,26 @@ UndoContext create_undo_element_context(RectLayer *layer)
 }
 
 static
-UndoContext create_undo_update_context(RectLayer *rect_layer)
+RectUndoContext create_rect_undo_update_context(RectLayer *rect_layer)
 {
-    UndoContext undo_context = create_undo_element_context(rect_layer);
-    undo_context.type = UNDO_UPDATE;
+    RectUndoContext undo_context = create_rect_undo_element_context(rect_layer);
+    undo_context.type = RECT_UNDO_UPDATE;
     return undo_context;
 }
 
 static
-UndoContext create_undo_delete_context(RectLayer *rect_layer)
+RectUndoContext create_rect_undo_delete_context(RectLayer *rect_layer)
 {
-    UndoContext undo_context = create_undo_element_context(rect_layer);
-    undo_context.type = UNDO_DELETE;
+    RectUndoContext undo_context = create_rect_undo_element_context(rect_layer);
+    undo_context.type = RECT_UNDO_DELETE;
     return undo_context;
 }
 
 static
-UndoContext create_undo_swap_context(RectLayer *rect_layer, size_t index1, size_t index2)
+RectUndoContext create_rect_undo_swap_context(RectLayer *rect_layer, size_t index1, size_t index2)
 {
-    UndoContext undo_context;
-    undo_context.swap.type = UNDO_SWAP;
+    RectUndoContext undo_context;
+    undo_context.swap.type = RECT_UNDO_SWAP;
     undo_context.swap.layer = rect_layer;
     undo_context.swap.index1 = index1;
     undo_context.swap.index2 = index2;
@@ -160,12 +181,12 @@ static
 void rect_layer_undo(void *context, size_t context_size)
 {
     trace_assert(context);
-    trace_assert(sizeof(UndoContext) == context_size);
+    trace_assert(sizeof(RectUndoContext) == context_size);
 
-    UndoContext *undo_context = context;
+    RectUndoContext *undo_context = context;
 
     switch (undo_context->type) {
-    case UNDO_ADD: {
+    case RECT_UNDO_ADD: {
         RectLayer *layer = undo_context->add.layer;
         dynarray_delete_at(layer->rects, undo_context->add.index);
         dynarray_delete_at(layer->colors, undo_context->add.index);
@@ -174,7 +195,7 @@ void rect_layer_undo(void *context, size_t context_size)
         layer->selection = -1;
     } break;
 
-    case UNDO_DELETE: {
+    case RECT_UNDO_DELETE: {
         RectLayer *layer = undo_context->element.layer;
         dynarray_insert_before(layer->rects, undo_context->element.index, &undo_context->element.rect);
         dynarray_insert_before(layer->colors, undo_context->element.index, &undo_context->element.color);
@@ -183,7 +204,7 @@ void rect_layer_undo(void *context, size_t context_size)
         layer->selection = -1;
     } break;
 
-    case UNDO_UPDATE: {
+    case RECT_UNDO_UPDATE: {
         RectLayer *layer = undo_context->element.layer;
         dynarray_replace_at(layer->rects, undo_context->element.index, &undo_context->element.rect);
         dynarray_replace_at(layer->colors, undo_context->element.index, &undo_context->element.color);
@@ -191,7 +212,7 @@ void rect_layer_undo(void *context, size_t context_size)
         dynarray_replace_at(layer->actions, undo_context->element.index, &undo_context->element.action);
     } break;
 
-    case UNDO_SWAP: {
+    case RECT_UNDO_SWAP: {
         RectLayer *layer = undo_context->element.layer;
         dynarray_swap(layer->rects, undo_context->swap.index1, undo_context->swap.index2);
         dynarray_swap(layer->colors, undo_context->swap.index1, undo_context->swap.index2);
@@ -201,9 +222,9 @@ void rect_layer_undo(void *context, size_t context_size)
     }
 }
 
-#define UNDO_PUSH(HISTORY, CONTEXT)                                     \
+#define RECT_UNDO_PUSH(HISTORY, CONTEXT)                                     \
     do {                                                                \
-        UndoContext context = (CONTEXT);                                \
+        RectUndoContext context = (CONTEXT);                                \
         undo_history_push(                                              \
             HISTORY,                                                    \
             rect_layer_undo,                                            \
@@ -236,9 +257,9 @@ static int rect_layer_add_rect(RectLayer *layer,
 
     dynarray_push_empty(layer->actions);
 
-    UNDO_PUSH(
+    RECT_UNDO_PUSH(
         undo_history,
-        create_undo_add_context(
+        create_rect_undo_add_context(
             layer,
             dynarray_count(layer->rects) - 1));
 
@@ -273,17 +294,7 @@ static void rect_layer_swap_elements(RectLayer *layer, size_t a, size_t b,
     dynarray_swap(layer->ids, a, b);
     dynarray_swap(layer->actions, a, b);
 
-    UNDO_PUSH(undo_history, create_undo_swap_context(layer, a, b));
-}
-
-static Rect rect_layer_resize_anchor(const Camera *camera, Rect boundary_rect)
-{
-    const Rect overlay_rect = camera_rect(camera, boundary_rect);
-    return rect(
-        overlay_rect.x + overlay_rect.w,
-        overlay_rect.y + overlay_rect.h,
-        RECT_LAYER_SELECTION_THICCNESS * 2.0,
-        RECT_LAYER_SELECTION_THICCNESS * 2.0);
+    RECT_UNDO_PUSH(undo_history, create_rect_undo_swap_context(layer, a, b));
 }
 
 static int rect_layer_delete_rect_at(RectLayer *layer,
@@ -292,7 +303,7 @@ static int rect_layer_delete_rect_at(RectLayer *layer,
 {
     trace_assert(layer);
 
-    UNDO_PUSH(undo_history, create_undo_delete_context(layer));
+    RECT_UNDO_PUSH(undo_history, create_rect_undo_delete_context(layer));
 
     dynarray_delete_at(layer->rects, i);
     dynarray_delete_at(layer->colors, i);
@@ -302,6 +313,17 @@ static int rect_layer_delete_rect_at(RectLayer *layer,
     return 0;
 }
 
+static int calc_resize_mask(Vec2f point, Rect rect)
+{
+    int mask = 0;
+    for (Rect_side side = 0; side < RECT_SIDE_N; ++side) {
+        if (rect_side_distance(rect, point, side) < RECT_LAYER_SELECTION_THICCNESS) {
+            mask = mask | (1 << side);
+        }
+    }
+    return mask;
+}
+
 static int rect_layer_event_idle(RectLayer *layer,
                                  const SDL_Event *event,
                                  const Camera *camera,
@@ -324,6 +346,8 @@ static int rect_layer_event_idle(RectLayer *layer,
         return 0;
     }
 
+    Rect *rects = dynarray_data(layer->rects);
+
     switch (event->type) {
     case SDL_MOUSEBUTTONDOWN: {
         switch (event->button.button) {
@@ -335,30 +359,26 @@ static int rect_layer_event_idle(RectLayer *layer,
             int rect_at_position =
                 rect_layer_rect_at(layer, position);
 
-            Rect *rects = dynarray_data(layer->rects);
+
             Color *colors = dynarray_data(layer->colors);
 
-            if (layer->selection >= 0 && rect_contains_point(
-                    rect_layer_resize_anchor(
-                        camera,
-                        rects[layer->selection]),
-                    vec(
-                        (float) event->button.x,
-                        (float) event->button.y))) {
+            if (layer->selection >= 0 &&
+                layer->selection == rect_at_position &&
+                (layer->resize_mask = calc_resize_mask(
+                    vec((float) event->button.x, (float)event->button.y),
+                    camera_rect(camera, rects[layer->selection])))) {
                 layer->state = RECT_LAYER_RESIZE;
                 dynarray_copy_to(layer->rects, &layer->inter_rect, (size_t) layer->selection);
             } else if (rect_at_position >= 0) {
                 layer->selection = rect_at_position;
                 layer->state = RECT_LAYER_MOVE;
-                layer->move_anchor =
-                    vec_sub(
-                        position,
-                        vec(
-                            rects[layer->selection].x,
-                            rects[layer->selection].y));
+                layer->move_anchor = vec_sub(
+                    position,
+                    vec(
+                        rects[layer->selection].x,
+                        rects[layer->selection].y));
                 layer->color_picker =
                     create_color_picker_from_rgba(colors[rect_at_position]);
-
                 dynarray_copy_to(layer->rects, &layer->inter_rect, (size_t) rect_at_position);
             } else {
                 layer->selection = rect_at_position;
@@ -373,6 +393,23 @@ static int rect_layer_event_idle(RectLayer *layer,
         }
     } break;
 
+    case SDL_MOUSEMOTION: {
+        int resize_mask = 0;
+        Vec2f position = camera_map_screen(
+            camera,
+            event->button.x,
+            event->button.y);
+        if (layer->selection >= 0 &&
+            layer->selection == rect_layer_rect_at(layer, position) &&
+            (resize_mask = calc_resize_mask(
+                vec((float) event->button.x, (float)event->button.y),
+                camera_rect(camera, rects[layer->selection])))) {
+            layer->cursor->style = resize_styles[resize_mask];
+        } else {
+            layer->cursor->style = CURSOR_STYLE_POINTER;
+        }
+    } break;
+
     case SDL_KEYDOWN: {
         switch (event->key.keysym.sym) {
         case SDLK_UP: {
@@ -408,6 +445,11 @@ static int rect_layer_event_idle(RectLayer *layer,
             }
         } break;
 
+        case SDLK_q: {
+            // TODO(#1171): there is no UI indication that we are in the snapping mode
+            layer->snapping_enabled = !layer->snapping_enabled;
+        } break;
+
         case SDLK_F2: {
             if (layer->selection >= 0) {
                 const char *ids = dynarray_data(layer->ids);
@@ -428,14 +470,14 @@ static int rect_layer_event_idle(RectLayer *layer,
 
         case SDLK_c: {
             if ((event->key.keysym.mod & KMOD_LCTRL) && layer->selection >= 0) {
-                clipboard = 1;
-                dynarray_copy_to(layer->rects, &clipboard_rect, (size_t)layer->selection);
-                dynarray_copy_to(layer->colors, &clipboard_color, (size_t)layer->selection);
+                rect_clipboard = 1;
+                dynarray_copy_to(layer->rects, &rect_clipboard_rect, (size_t)layer->selection);
+                dynarray_copy_to(layer->colors, &rect_clipboard_color, (size_t)layer->selection);
             }
         } break;
 
         case SDLK_v: {
-            if ((event->key.keysym.mod & KMOD_LCTRL) && clipboard) {
+            if ((event->key.keysym.mod & KMOD_LCTRL) && rect_clipboard) {
                 int x, y;
                 SDL_GetMouseState(&x, &y);
                 Vec2f position = camera_map_screen(camera, x, y);
@@ -443,8 +485,8 @@ static int rect_layer_event_idle(RectLayer *layer,
                 rect_layer_add_rect(
                     layer,
                     rect(position.x, position.y,
-                         clipboard_rect.w, clipboard_rect.h),
-                    clipboard_color,
+                         rect_clipboard_rect.w, rect_clipboard_rect.h),
+                    rect_clipboard_color,
                     undo_history);
             }
         } break;
@@ -498,6 +540,33 @@ static int rect_layer_event_create(RectLayer *layer,
     return 0;
 }
 
+static
+void snap_rect_resize_if_enabled(RectLayer *layer, Rect *a, float snapping_threshold)
+{
+    trace_assert(layer);
+    trace_assert(layer->selection >= 0);
+    trace_assert(a);
+
+    if (!layer->snapping_enabled) return;
+
+    Rect *rects = dynarray_data(layer->rects);
+    size_t rects_size = dynarray_count(layer->rects);
+
+    for (size_t i = 0; i < rects_size; ++i) {
+        if (i == (size_t) layer->selection) continue;
+
+        const Rect b = rects[i];
+
+        if (segment_overlap(vec(a->x, a->x + a->w), vec(b.x, b.x + b.w))) {
+            snap_var2seg(&a->y, b.y, 0, b.h, snapping_threshold);
+        }
+
+        if (segment_overlap(vec(a->y, a->y + a->h), vec(b.y, b.y + b.h))) {
+            snap_var2seg(&a->x, b.x, 0, b.w, snapping_threshold);
+        }
+    }
+}
+
 static int rect_layer_event_resize(RectLayer *layer,
                                    const SDL_Event *event,
                                    const Camera *camera,
@@ -508,22 +577,135 @@ static int rect_layer_event_resize(RectLayer *layer,
     trace_assert(camera);
     trace_assert(layer->selection >= 0);
 
+    Rect *rects = dynarray_data(layer->rects);
+
+    float scaled_snap_threshold = SNAPPING_THRESHOLD / camera->scale;
+
     switch (event->type) {
     case SDL_MOUSEMOTION: {
-        layer->inter_rect = rect_from_points(
-            vec(layer->inter_rect.x, layer->inter_rect.y),
-            vec_sum(
-                camera_map_screen(
-                    camera,
-                    event->button.x,
-                    event->button.y),
-                vec(RECT_LAYER_SELECTION_THICCNESS * -0.5f,
-                    RECT_LAYER_SELECTION_THICCNESS * -0.5f)));
+        Vec2f position = camera_map_screen(
+            camera,
+            event->button.x,
+            event->button.y);
+
+        switch (layer->resize_mask) {
+        case 1: {               // TOP
+            Rect a = rect(rects[layer->selection].x,
+                          position.y,
+                          rects[layer->selection].w,
+                          rects[layer->selection].h);
+
+            snap_rect_resize_if_enabled(layer, &a, scaled_snap_threshold);
+
+            layer->inter_rect = rect_from_points(
+                vec(a.x, a.y),
+                rect_position2(rects[layer->selection]));
+        } break;
+
+        case 2: {               // LEFT
+            Rect a = rect(position.x,
+                          rects[layer->selection].y,
+                          rects[layer->selection].w,
+                          rects[layer->selection].h);
+
+            snap_rect_resize_if_enabled(layer, &a, scaled_snap_threshold);
+
+            layer->inter_rect = rect_from_points(
+                vec(a.x, a.y),
+                rect_position2(rects[layer->selection]));
+        } break;
+
+        case 3: {               // TOP,LEFT
+            Rect a = rect(
+                position.x,
+                position.y,
+                rects[layer->selection].w,
+                rects[layer->selection].h);
+
+            snap_rect_resize_if_enabled(layer, &a, scaled_snap_threshold);
+
+            layer->inter_rect = rect_from_points(
+                vec(a.x, a.y),
+                rect_position2(rects[layer->selection]));
+        } break;
+
+        case 4: {               // BOTTOM
+            Rect a = rect(rects[layer->selection].x,
+                          position.y,
+                          rects[layer->selection].w,
+                          rects[layer->selection].h);
+
+            snap_rect_resize_if_enabled(layer, &a, scaled_snap_threshold);
+
+            layer->inter_rect = rect_from_points(
+                rect_position(rects[layer->selection]),
+                vec(rects[layer->selection].x + rects[layer->selection].w,
+                    a.y));
+        } break;
+
+        case 6: {               // BOTTOM,LEFT
+            Rect a = rect(
+                position.x,
+                position.y,
+                rects[layer->selection].w,
+                -rects[layer->selection].h);
+
+            snap_rect_resize_if_enabled(layer, &a, scaled_snap_threshold);
+
+            layer->inter_rect = rect_from_points(
+                vec(a.x, rects[layer->selection].y),
+                vec(rects[layer->selection].x + rects[layer->selection].w,
+                    a.y));
+        } break;
+
+        case 8: {               // RIGHT
+            Rect a = rect(position.x,
+                          rects[layer->selection].y,
+                          rects[layer->selection].w,
+                          rects[layer->selection].h);
+
+            snap_rect_resize_if_enabled(layer, &a, scaled_snap_threshold);
+
+            layer->inter_rect = rect_from_points(
+                rect_position(rects[layer->selection]),
+                vec(a.x, rects[layer->selection].y + rects[layer->selection].h));
+        } break;
+
+        case 9: {               // TOP,RIGHT
+            Rect a = rect(
+                position.x,
+                position.y,
+                -rects[layer->selection].w,
+                rects[layer->selection].h);
+
+            snap_rect_resize_if_enabled(layer, &a, scaled_snap_threshold);
+
+            layer->inter_rect = rect_from_points(
+                vec(rects[layer->selection].x, a.y),
+                vec(a.x,
+                    rects[layer->selection].y + rects[layer->selection].h));
+        } break;
+
+        case 12: {              // BOTTOM,RIGHT
+            Rect a = rect(
+                position.x,
+                position.y,
+                -rects[layer->selection].w,
+                -rects[layer->selection].h);
+
+            snap_rect_resize_if_enabled(layer, &a, scaled_snap_threshold);
+
+            layer->inter_rect = rect_from_points(
+                rect_position(rects[layer->selection]),
+                vec(a.x, a.y));
+        } break;
+        }
+
     } break;
 
     case SDL_MOUSEBUTTONUP: {
         layer->state = RECT_LAYER_IDLE;
-        UNDO_PUSH(undo_history, create_undo_update_context(layer));
+        RECT_UNDO_PUSH(undo_history, create_rect_undo_update_context(layer));
         dynarray_replace_at(layer->rects, (size_t) layer->selection, &layer->inter_rect);
     } break;
     }
@@ -531,6 +713,34 @@ static int rect_layer_event_resize(RectLayer *layer,
     return 0;
 }
 
+static
+void snap_rect_move_if_enabled(RectLayer *layer, Rect *a,
+                               float snapping_threshold)
+{
+    trace_assert(a);
+    trace_assert(layer);
+    trace_assert(layer->selection >= 0);
+
+    if (!layer->snapping_enabled) return;
+
+    Rect *rects = dynarray_data(layer->rects);
+    size_t rects_size = dynarray_count(layer->rects);
+
+    for (size_t i = 0; i < rects_size; ++i) {
+        if (i == (size_t) layer->selection) continue;
+
+        const Rect b = rects[i];
+
+        if (segment_overlap(vec(a->x, a->x + a->w), vec(b.x,  b.x  + b.w))) {
+            snap_seg2seg(&a->y, b.y, a->h, b.h, snapping_threshold);
+        }
+
+        if (segment_overlap(vec(a->y, a->y + a->h), vec(b.y,  b.y  + b.h))) {
+            snap_seg2seg(&a->x, b.x, a->w, b.w, snapping_threshold);
+        }
+    }
+}
+
 static int rect_layer_event_move(RectLayer *layer,
                                  const SDL_Event *event,
                                  const Camera *camera,
@@ -570,6 +780,9 @@ static int rect_layer_event_move(RectLayer *layer,
                 layer->inter_rect.y = mouse_pos.y;
             }
         }
+
+        snap_rect_move_if_enabled(layer, &layer->inter_rect,
+                                  SNAPPING_THRESHOLD / camera->scale);
     } break;
 
     case SDL_MOUSEBUTTONUP: {
@@ -580,7 +793,7 @@ static int rect_layer_event_move(RectLayer *layer,
                     rect_position(rects[layer->selection])));
 
         if (distance > 1e-6) {
-            UNDO_PUSH(undo_history, create_undo_update_context(layer));
+            RECT_UNDO_PUSH(undo_history, create_rect_undo_update_context(layer));
             dynarray_replace_at(layer->rects, (size_t) layer->selection, &layer->inter_rect);
         }
     } break;
@@ -602,7 +815,7 @@ static int rect_layer_event_id_rename(RectLayer *layer,
     case SDL_KEYDOWN: {
         switch (event->key.keysym.sym) {
         case SDLK_RETURN: {
-            UNDO_PUSH(undo_history, create_undo_update_context(layer));
+            RECT_UNDO_PUSH(undo_history, create_rect_undo_update_context(layer));
 
             char *id = dynarray_pointer_at(layer->ids, (size_t)layer->selection);
             memset(id, 0, ENTITY_MAX_ID_SIZE);
@@ -631,8 +844,10 @@ LayerPtr rect_layer_as_layer(RectLayer *rect_layer)
     return layer;
 }
 
-RectLayer *create_rect_layer(const char *id_name_prefix)
+RectLayer *create_rect_layer(const char *id_name_prefix, Cursor *cursor)
 {
+    trace_assert(cursor);
+
     Lt *lt = create_lt();
 
     RectLayer *layer = PUSH_LT(lt, nth_calloc(1, sizeof(RectLayer)), free);
@@ -700,15 +915,18 @@ RectLayer *create_rect_layer(const char *id_name_prefix)
     layer->color_picker = create_color_picker_from_rgba(rgba(1.0f, 0.0f, 0.0f, 1.0f));
     layer->selection = -1;
     layer->id_name_prefix = id_name_prefix;
+    layer->cursor = cursor;
 
     return layer;
 }
 
-RectLayer *create_rect_layer_from_line_stream(LineStream *line_stream, const char *id_name_prefix)
+RectLayer *create_rect_layer_from_line_stream(LineStream *line_stream,
+                                              const char *id_name_prefix,
+                                              Cursor *cursor)
 {
     trace_assert(line_stream);
 
-    RectLayer *layer = create_rect_layer(id_name_prefix);
+    RectLayer *layer = create_rect_layer(id_name_prefix, cursor);
     if (layer == NULL) {
         return NULL;
     }
@@ -874,14 +1092,6 @@ int rect_layer_render(const RectLayer *layer, const Camera *camera, int active)
                 return -1;
             }
         }
-
-        // Resize Anchor
-        if (camera_fill_rect_screen(
-                camera,
-                rect_layer_resize_anchor(camera, rect),
-                overlay_color) < 0) {
-            return -1;
-        }
     }
 
     // Proto Rectangle
@@ -920,7 +1130,7 @@ int rect_layer_event_recolor(RectLayer *layer,
         layer->inter_color = color_picker_rgba(&layer->color_picker);
 
         if (!color_picker_drag(&layer->color_picker)) {
-            UNDO_PUSH(undo_history, create_undo_update_context(layer));
+            RECT_UNDO_PUSH(undo_history, create_rect_undo_update_context(layer));
             dynarray_replace_at(layer->colors, (size_t) layer->selection, &layer->inter_color);
             layer->state = RECT_LAYER_IDLE;
         }
@@ -941,7 +1151,7 @@ int rect_layer_event(RectLayer *layer,
     switch (event->type) {
     case SDL_WINDOWEVENT: {
         switch (event->window.event) {
-        case SDL_WINDOWEVENT_RESIZED: {
+        case SDL_WINDOWEVENT_SIZE_CHANGED: {
             grid_relayout(layer->grid, rect(0.0f, 0.0f,
                                             (float) event->window.data1,
                                             (float) event->window.data2));
@@ -970,6 +1180,7 @@ int rect_layer_event(RectLayer *layer,
         return rect_layer_event_recolor(layer, event, camera, undo_history);
     }
 
+
     return 0;
 }