]> git.lizzy.rs Git - nothing.git/blobdiff - src/game/level/level_editor/rect_layer.c
(#1118) Try to fix warnings on MacOS build
[nothing.git] / src / game / level / level_editor / rect_layer.c
index 5cee6eeee175946c796a0c5bb0aec65041385c74..cdac135cbb8f48225ef0f14aaf1c4e0a22fee1c4 100644 (file)
 #include "ui/edit_field.h"
 #include "undo_history.h"
 #include "game/level/action.h"
+#include "action_picker.h"
 
 #define RECT_LAYER_SELECTION_THICCNESS 10.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;
@@ -42,15 +45,18 @@ struct RectLayer {
     Dynarray *colors;
     Dynarray *actions;
     ColorPicker color_picker;
+    ActionPicker action_picker;
     Vec2f create_begin;
     Vec2f create_end;
     int selection;
-    Vec2f move_anchor;
+    Vec2f move_anchor;          // The mouse offset from the left-top
+                                // corner of the rect during moving it
     Edit_field *id_edit_field;
     Color inter_color;
     Rect inter_rect;
     int id_name_counter;
     const char *id_name_prefix;
+    Grid *grid;
 };
 
 typedef enum {
@@ -272,16 +278,12 @@ static void rect_layer_swap_elements(RectLayer *layer, size_t a, size_t b,
 
 static Rect rect_layer_resize_anchor(const Camera *camera, Rect boundary_rect)
 {
-    const Rect overlay_rect =
-        rect_pad(
-            camera_rect(camera, boundary_rect),
-            RECT_LAYER_SELECTION_THICCNESS * 0.5f);
-
+    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.0f,
-        RECT_LAYER_SELECTION_THICCNESS * 2.0f);
+        RECT_LAYER_SELECTION_THICCNESS * 2.0,
+        RECT_LAYER_SELECTION_THICCNESS * 2.0);
 }
 
 static int rect_layer_delete_rect_at(RectLayer *layer,
@@ -543,17 +545,31 @@ static int rect_layer_event_move(RectLayer *layer,
 
     switch (event->type) {
     case SDL_MOUSEMOTION: {
-        Vec2f position = vec_sub(
+        const Uint8 *state = SDL_GetKeyboardState(NULL);
+        const Vec2f mouse_pos = vec_sub(
             camera_map_screen(
                 camera,
                 event->button.x,
                 event->button.y),
             layer->move_anchor);
 
-        trace_assert(layer->selection >= 0);
+        if (!(state[SDL_SCANCODE_LCTRL] || state[SDL_SCANCODE_RCTRL])) {
+            layer->inter_rect.x = mouse_pos.x;
+            layer->inter_rect.y = mouse_pos.y;
+        } else {
+            const Vec2f rect_pos = rect_position(rects[layer->selection]);
+
+            const float dx = fabsf(rect_pos.x - mouse_pos.x);
+            const float dy = fabsf(rect_pos.y - mouse_pos.y);
 
-        layer->inter_rect.x = position.x;
-        layer->inter_rect.y = position.y;
+            if (dx > dy) {
+                layer->inter_rect.x = mouse_pos.x;
+                layer->inter_rect.y = rect_pos.y;
+            } else {
+                layer->inter_rect.x = rect_pos.x;
+                layer->inter_rect.y = mouse_pos.y;
+            }
+        }
     } break;
 
     case SDL_MOUSEBUTTONUP: {
@@ -667,6 +683,20 @@ RectLayer *create_rect_layer(const char *id_name_prefix)
         RETURN_LT(lt, NULL);
     }
 
+    layer->grid =
+        PUSH_LT(
+            lt,
+            nth_calloc(
+                1,
+                sizeof(Grid) + sizeof(Widget*) * RECT_LAYER_GRID_ROWS * RECT_LAYER_GRID_COLUMNS),
+            free);
+    if (layer->grid == NULL) {
+        RETURN_LT(lt, NULL);
+    }
+    layer->grid->rows = RECT_LAYER_GRID_ROWS;
+    layer->grid->columns = RECT_LAYER_GRID_COLUMNS;
+    grid_put_widget(layer->grid, &layer->action_picker.widget, 0, RECT_LAYER_GRID_COLUMNS - 1);
+
     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;
@@ -720,7 +750,10 @@ RectLayer *create_rect_layer_from_line_stream(LineStream *line_stream, const cha
         dynarray_push(layer->ids, id);
         dynarray_push(layer->colors, &color);
 
-        Action action = {0};
+        Action action = {
+            .type = ACTION_NONE,
+            .entity_id = {0}
+        };
 
         if (sscanf(line, "%d%n", (int*)&action.type, &n) > 0) {
             line += n;
@@ -776,6 +809,7 @@ int rect_layer_render(const RectLayer *layer, const Camera *camera, int active)
             }
         }
 
+        // Main Rectangle
         if (camera_fill_rect(
                 camera,
                 rect,
@@ -784,62 +818,70 @@ int rect_layer_render(const RectLayer *layer, const Camera *camera, int active)
                     rgba(1.0f, 1.0f, 1.0f, active ? 1.0f : 0.5f))) < 0) {
             return -1;
         }
+    }
 
-        // Selection Overlay
-        if (active && (size_t) layer->selection == i) {
-            const Rect overlay_rect =
-                rect_pad(
-                    camera_rect(camera, rect),
-                    RECT_LAYER_SELECTION_THICCNESS * 0.5f);
-            const Color overlay_color = color_invert(color);
+    // Selection Overlay
+    if (active && layer->selection >= 0) {
+        Rect rect = rects[layer->selection];
+        Color color = colors[layer->selection];
 
-            // Main Rectangle
-            if (camera_fill_rect(
-                    camera,
-                    rect,
-                    color_scale(
-                        color,
-                        rgba(1.0f, 1.0f, 1.0f, active ? 1.0f : 0.5f))) < 0) {
-                return -1;
-            }
+        if (layer->state == RECT_LAYER_RESIZE || layer->state == RECT_LAYER_MOVE) {
+            rect = layer->inter_rect;
+        }
+
+        if (layer->state == RECT_LAYER_RECOLOR) {
+            color = layer->inter_color;
+        }
+
+        const Rect overlay_rect =
+            rect_pad(
+                camera_rect(camera, rect),
+                -RECT_LAYER_SELECTION_THICCNESS * 0.5f);
+        const Color overlay_color = color_invert(color);
+
+        // Selection
+        if (camera_draw_thicc_rect_screen(
+                camera,
+                overlay_rect,
+                overlay_color,
+                RECT_LAYER_SELECTION_THICCNESS) < 0) {
+            return -1;
+        }
+
+        const Vec2f rect_id_pos = vec_sub(
+            rect_position(rect),
+            vec_mult(
+                RECT_LAYER_ID_LABEL_SIZE,
+                vec(0.0f, FONT_CHAR_HEIGHT)));
 
-            if (camera_draw_thicc_rect_screen(
+        // Rectangle Id
+        if (layer->state == RECT_LAYER_ID_RENAME) {
+            // ID renaming Edit Field
+            if (edit_field_render_world(
+                    layer->id_edit_field,
                     camera,
-                    overlay_rect,
-                    overlay_color,
-                    RECT_LAYER_SELECTION_THICCNESS) < 0) {
+                    rect_id_pos) < 0) {
                 return -1;
             }
-
-            // Rectangle Id
-            if (layer->state == RECT_LAYER_ID_RENAME) {
-                // ID renaming Edit Field
-                if (edit_field_render_world(
-                        layer->id_edit_field,
-                        camera,
-                        rect_position(rect)) < 0) {
-                    return -1;
-                }
-            } else {
-                // Id text
-                if (camera_render_text(
-                        camera,
-                        ids + layer->selection * ENTITY_MAX_ID_SIZE,
-                        RECT_LAYER_ID_LABEL_SIZE,
-                        color_invert(color),
-                        rect_position(rect)) < 0) {
-                    return -1;
-                }
-            }
-
-            // Resize Anchor
-            if (camera_fill_rect_screen(
+        } else {
+            // Id text
+            if (camera_render_text(
                     camera,
-                    rect_layer_resize_anchor(camera, rect),
-                    overlay_color) < 0) {
+                    ids + layer->selection * ENTITY_MAX_ID_SIZE,
+                    RECT_LAYER_ID_LABEL_SIZE,
+                    color_invert(color),
+                    rect_id_pos) < 0) {
                 return -1;
             }
         }
+
+        // Resize Anchor
+        if (camera_fill_rect_screen(
+                camera,
+                rect_layer_resize_anchor(camera, rect),
+                overlay_color) < 0) {
+            return -1;
+        }
     }
 
     // Proto Rectangle
@@ -896,6 +938,18 @@ int rect_layer_event(RectLayer *layer,
     trace_assert(event);
     trace_assert(undo_history);
 
+    switch (event->type) {
+    case SDL_WINDOWEVENT: {
+        switch (event->window.event) {
+        case SDL_WINDOWEVENT_RESIZED: {
+            grid_relayout(layer->grid, rect(0.0f, 0.0f,
+                                            (float) event->window.data1,
+                                            (float) event->window.data2));
+        } break;
+        }
+    } break;
+    }
+
     switch (layer->state) {
     case RECT_LAYER_IDLE:
         return rect_layer_event_idle(layer, event, camera, undo_history);