]> git.lizzy.rs Git - nothing.git/blobdiff - src/game/level/level_editor/rect_layer.c
Try to remove malloc from LevelEditor
[nothing.git] / src / game / level / level_editor / rect_layer.c
index 076335a91b9de8b83a38d249eac2036b457a1038..f18b9bb31a89e13601295acf44d4ed97318761c2 100644 (file)
@@ -2,7 +2,6 @@
 #include <errno.h>
 
 #include "game/camera.h"
-#include "system/lt.h"
 #include "system/stacktrace.h"
 #include "system/nth_alloc.h"
 #include "system/log.h"
 #include "color.h"
 #include "rect_layer.h"
 #include "dynarray.h"
-#include "system/line_stream.h"
-#include "color_picker.h"
 #include "system/str.h"
-#include "ui/edit_field.h"
 #include "undo_history.h"
 #include "game/level/action.h"
-#include "action_picker.h"
 #include "game.h"
+#include "math/extrema.h"
 
 #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 rect_clipboard = 0;
 static Rect rect_clipboard_rect;
@@ -45,41 +39,6 @@ static Cursor_Style resize_styles[1 << RECT_SIDE_N] = {
     CURSOR_STYLE_RESIZE_DIAG1  // [12]
 };
 
-typedef enum {
-    RECT_LAYER_IDLE = 0,
-    RECT_LAYER_CREATE,
-    RECT_LAYER_RESIZE,
-    RECT_LAYER_MOVE,
-    RECT_LAYER_ID_RENAME,
-    RECT_LAYER_RECOLOR
-} RectLayerState;
-
-struct RectLayer {
-    Lt *lt;
-    RectLayerState state;
-    int resize_mask;
-    Dynarray ids;
-    Dynarray rects;
-    Dynarray colors;
-    Dynarray actions;
-    ColorPicker color_picker;
-    ActionPicker action_picker;
-    Vec2f create_begin;
-    Vec2f create_end;
-    int selection;
-    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;
-    Cursor *cursor;
-
-    int snapping_enabled;
-};
-
 typedef enum {
     RECT_UNDO_ADD,
     RECT_UNDO_DELETE,
@@ -264,7 +223,7 @@ static int rect_layer_rect_at(RectLayer *layer, Vec2f position)
     trace_assert(layer);
 
     int n = (int) layer->rects.count;
-    Rect *rects = dynarray_data(&layer->rects);
+    Rect *rects = (Rect*)layer->rects.data;
 
     for (int i = n - 1; i >= 0; --i) {
         if (rect_contains_point(rects[i], position)) {
@@ -339,7 +298,7 @@ static int rect_layer_event_idle(RectLayer *layer,
         return 0;
     }
 
-    Rect *rects = dynarray_data(&layer->rects);
+    Rect *rects = (Rect*)layer->rects.data;
 
     switch (event->type) {
     case SDL_MOUSEBUTTONDOWN: {
@@ -353,7 +312,7 @@ static int rect_layer_event_idle(RectLayer *layer,
                 rect_layer_rect_at(layer, position);
 
 
-            Color *colors = dynarray_data(&layer->colors);
+            Color *colors = (Color*)layer->colors.data;
 
             if (layer->selection >= 0 &&
                 layer->selection == rect_at_position &&
@@ -445,17 +404,17 @@ static int rect_layer_event_idle(RectLayer *layer,
 
         case SDLK_F2: {
             if (layer->selection >= 0) {
-                const char *ids = dynarray_data(&layer->ids);
-                Color *colors = dynarray_data(&layer->colors);
+                const char *ids = (char*)layer->ids.data;
+                Color *colors = (Color*)layer->colors.data;
 
                 edit_field_restyle(
-                    layer->id_edit_field,
+                    &layer->id_edit_field,
                     RECT_LAYER_ID_LABEL_SIZE,
                     color_invert(colors[layer->selection]));
 
                 layer->state = RECT_LAYER_ID_RENAME;
                 edit_field_replace(
-                    layer->id_edit_field,
+                    &layer->id_edit_field,
                     ids + layer->selection * ENTITY_MAX_ID_SIZE);
                 SDL_StartTextInput();
             }
@@ -542,8 +501,8 @@ void snap_rect_resize_if_enabled(RectLayer *layer, Rect *a, float snapping_thres
 
     if (!layer->snapping_enabled) return;
 
-    Rect *rects = dynarray_data(&layer->rects);
-    size_t rects_size = dynarray_count(&layer->rects);
+    Rect *rects = (Rect*)layer->rects.data;
+    size_t rects_size = layer->rects.count;
 
     for (size_t i = 0; i < rects_size; ++i) {
         if (i == (size_t) layer->selection) continue;
@@ -570,7 +529,7 @@ static int rect_layer_event_resize(RectLayer *layer,
     trace_assert(camera);
     trace_assert(layer->selection >= 0);
 
-    Rect *rects = dynarray_data(&layer->rects);
+    Rect *rects = (Rect*)layer->rects.data;
 
     float scaled_snap_threshold = SNAPPING_THRESHOLD / camera->scale;
 
@@ -716,8 +675,8 @@ void snap_rect_move_if_enabled(RectLayer *layer, Rect *a,
 
     if (!layer->snapping_enabled) return;
 
-    Rect *rects = dynarray_data(&layer->rects);
-    size_t rects_size = dynarray_count(&layer->rects);
+    Rect *rects = (Rect*)layer->rects.data;
+    size_t rects_size = layer->rects.count;
 
     for (size_t i = 0; i < rects_size; ++i) {
         if (i == (size_t) layer->selection) continue;
@@ -744,7 +703,7 @@ static int rect_layer_event_move(RectLayer *layer,
     trace_assert(camera);
     trace_assert(layer->selection >= 0);
 
-    Rect *rects = dynarray_data(&layer->rects);
+    Rect *rects = (Rect*)layer->rects.data;
 
     switch (event->type) {
     case SDL_MOUSEMOTION: {
@@ -812,7 +771,7 @@ static int rect_layer_event_id_rename(RectLayer *layer,
 
             char *id = dynarray_pointer_at(&layer->ids, (size_t)layer->selection);
             memset(id, 0, ENTITY_MAX_ID_SIZE);
-            memcpy(id, edit_field_as_text(layer->id_edit_field), ENTITY_MAX_ID_SIZE - 1);
+            memcpy(id, edit_field_as_text(&layer->id_edit_field), ENTITY_MAX_ID_SIZE - 1);
             layer->state = RECT_LAYER_IDLE;
             SDL_StopTextInput();
         } break;
@@ -825,7 +784,7 @@ static int rect_layer_event_id_rename(RectLayer *layer,
     } break;
     }
 
-    return edit_field_event(layer->id_edit_field, event);
+    return edit_field_event(&layer->id_edit_field, event);
 }
 
 LayerPtr rect_layer_as_layer(RectLayer *rect_layer)
@@ -837,119 +796,78 @@ LayerPtr rect_layer_as_layer(RectLayer *rect_layer)
     return layer;
 }
 
-RectLayer *create_rect_layer(const char *id_name_prefix, Cursor *cursor)
+RectLayer *create_rect_layer_from_memory(Memory *memory,
+                                         const char *id_name_prefix,
+                                         Cursor *cursor)
 {
+    trace_assert(memory);
+    trace_assert(id_name_prefix);
     trace_assert(cursor);
 
-    Lt *lt = create_lt();
-
-    RectLayer *layer = PUSH_LT(lt, nth_calloc(1, sizeof(RectLayer)), free);
-    if (layer == NULL) {
-        RETURN_LT(lt, NULL);
-    }
-    layer->lt = lt;
-
-    layer->ids = create_dynarray(sizeof(char) * ENTITY_MAX_ID_SIZE);
-    layer->rects = create_dynarray(sizeof(Rect));
-    layer->colors = create_dynarray(sizeof(Color));
-    layer->actions = create_dynarray(sizeof(Action));
-
-    layer->id_edit_field = PUSH_LT(
-        lt,
-        create_edit_field(
-            RECT_LAYER_ID_LABEL_SIZE,
-            COLOR_BLACK),
-        destroy_edit_field);
-    if (layer->id_edit_field == NULL) {
-        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);
+    RectLayer *rect_layer = memory_alloc(memory, sizeof(RectLayer));
 
-    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;
+    rect_layer->ids = create_dynarray_from_memory(memory, sizeof(char) * ENTITY_MAX_ID_SIZE);
+    rect_layer->rects = create_dynarray_from_memory(memory, sizeof(Rect));
+    rect_layer->colors = create_dynarray_from_memory(memory, sizeof(Color));
+    rect_layer->actions = create_dynarray_from_memory(memory, sizeof(Action));
+    rect_layer->id_edit_field.font_size = RECT_LAYER_ID_LABEL_SIZE;
+    rect_layer->id_edit_field.font_color = COLOR_BLACK;
+    rect_layer->color_picker = create_color_picker_from_rgba(rgba(1.0f, 0.0f, 0.0f, 1.0f));
+    rect_layer->selection = -1;
+    rect_layer->id_name_prefix = id_name_prefix;
+    rect_layer->cursor = cursor;
 
-    return layer;
+    return rect_layer;
 }
 
-RectLayer *create_rect_layer_from_line_stream(LineStream *line_stream,
-                                              const char *id_name_prefix,
-                                              Cursor *cursor)
+void rect_layer_load(RectLayer *layer, Memory *memory, String *input)
 {
-    trace_assert(line_stream);
-
-    RectLayer *layer = create_rect_layer(id_name_prefix, cursor);
-    if (layer == NULL) {
-        return NULL;
-    }
-
-    const char *line = line_stream_next(line_stream);
-    if (line == NULL) {
-        RETURN_LT(layer->lt, NULL);
-    }
-
-    size_t count = 0;
-    if (sscanf(line, "%zu", &count) < 0) {
-        RETURN_LT(layer->lt, NULL);
-    }
-
-    for (size_t i = 0; i < count; ++i) {
-        line = line_stream_next(line_stream);
-        if (line == NULL) {
-            RETURN_LT(layer->lt, NULL);
-        }
+    trace_assert(layer);
+    trace_assert(memory);
+    trace_assert(input);
 
-        char hex[7];
+    int n = atoi(string_to_cstr(memory, trim(chop_by_delim(input, '\n'))));
+    char id[ENTITY_MAX_ID_SIZE];
+    for (int i = 0; i < n; ++i) {
         Rect rect;
-        char id[ENTITY_MAX_ID_SIZE];
-
-        int n = 0;
-        if (sscanf(line,
-                   "%"STRINGIFY(ENTITY_MAX_ID_SIZE)"s%f%f%f%f%6s%n",
-                   id,
-                   &rect.x, &rect.y,
-                   &rect.w, &rect.h,
-                   hex, &n) <= 0) {
-            log_fail("%s\n", strerror(errno));
-            RETURN_LT(layer->lt, NULL);
-        }
-        line += n;
+        String line = trim(chop_by_delim(input, '\n'));
+        String string_id = trim(chop_word(&line));
+        rect.x = strtof(string_to_cstr(memory, trim(chop_word(&line))), NULL);
+        rect.y = strtof(string_to_cstr(memory, trim(chop_word(&line))), NULL);
+        rect.w = strtof(string_to_cstr(memory, trim(chop_word(&line))), NULL);
+        rect.h = strtof(string_to_cstr(memory, trim(chop_word(&line))), NULL);
+        Color color = hexs(trim(chop_word(&line)));
+
+        memset(id, 0, ENTITY_MAX_ID_SIZE);
+        memcpy(
+            id,
+            string_id.data,
+            min_size_t(ENTITY_MAX_ID_SIZE - 1, string_id.count));
 
-        Color color = hexstr(hex);
         dynarray_push(&layer->rects, &rect);
-        dynarray_push(&layer->ids, id);
         dynarray_push(&layer->colors, &color);
+        dynarray_push(&layer->ids, id);
 
         Action action = {
             .type = ACTION_NONE,
             .entity_id = {0}
         };
 
-        if (sscanf(line, "%d%n", (int*)&action.type, &n) > 0) {
-            line += n;
+        String action_string = trim(chop_word(&line));
+        if (action_string.count > 0) {
+            action.type = (ActionType)atol(string_to_cstr(memory, action_string));
             switch (action.type) {
             case ACTION_NONE: break;
-
             case ACTION_TOGGLE_GOAL:
             case ACTION_HIDE_LABEL: {
-                if (sscanf(line, "%"STRINGIFY(ENTITY_MAX_ID_SIZE)"s", action.entity_id) <= 0) {
-                    log_fail("%s\n", strerror(errno));
-                    RETURN_LT(layer->lt, NULL);
-                }
+                String label_id = trim(chop_word(&line));
+                trace_assert(label_id.count > 0);
+                memset(action.entity_id, 0, ENTITY_MAX_ID_SIZE);
+                memcpy(action.entity_id,
+                       label_id.data,
+                       min_size_t(
+                           ENTITY_MAX_ID_SIZE - 1,
+                           label_id.count));
             } break;
 
             case ACTION_N: break;
@@ -958,20 +876,6 @@ RectLayer *create_rect_layer_from_line_stream(LineStream *line_stream,
 
         dynarray_push(&layer->actions, &action);
     }
-
-    return layer;
-}
-
-void destroy_rect_layer(RectLayer *layer)
-{
-    trace_assert(layer);
-
-    free(layer->ids.data);
-    free(layer->rects.data);
-    free(layer->colors.data);
-    free(layer->actions.data);
-
-    RETURN_LT0(layer->lt);
 }
 
 int rect_layer_render(const RectLayer *layer, const Camera *camera, int active)
@@ -1048,7 +952,7 @@ int rect_layer_render(const RectLayer *layer, const Camera *camera, int active)
         if (layer->state == RECT_LAYER_ID_RENAME) {
             // ID renaming Edit Field
             if (edit_field_render_world(
-                    layer->id_edit_field,
+                    &layer->id_edit_field,
                     camera,
                     rect_id_pos) < 0) {
                 return -1;
@@ -1120,18 +1024,6 @@ 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_SIZE_CHANGED: {
-            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);