#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;
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,
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();
}
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;
} 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)
return layer;
}
-RectLayer *create_rect_layer(const char *id_name_prefix, Cursor *cursor)
+RectLayer create_rect_layer(const char *id_name_prefix, Cursor *cursor)
{
trace_assert(cursor);
- Lt *lt = create_lt();
+ RectLayer result = {0};
- 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);
- }
+ result.ids = create_dynarray(sizeof(char) * ENTITY_MAX_ID_SIZE);
+ result.rects = create_dynarray(sizeof(Rect));
+ result.colors = create_dynarray(sizeof(Color));
+ result.actions = create_dynarray(sizeof(Action));
+ result.id_edit_field.font_size = RECT_LAYER_ID_LABEL_SIZE;
+ result.id_edit_field.font_color = COLOR_BLACK;
+ result.color_picker = create_color_picker_from_rgba(rgba(1.0f, 0.0f, 0.0f, 1.0f));
+ result.selection = -1;
+ result.id_name_prefix = id_name_prefix;
+ result.cursor = cursor;
- 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;
- layer->cursor = cursor;
-
- return layer;
+ return result;
}
-RectLayer *create_rect_layer_from_line_stream(LineStream *line_stream,
- const char *id_name_prefix,
- Cursor *cursor)
+void rect_layer_reload(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);
- }
+ trace_assert(layer);
+ trace_assert(memory);
+ trace_assert(input);
- for (size_t i = 0; i < count; ++i) {
- line = line_stream_next(line_stream);
- if (line == NULL) {
- RETURN_LT(layer->lt, NULL);
- }
+ rect_layer_clean(layer);
- 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;
dynarray_push(&layer->actions, &action);
}
-
- return layer;
}
-void destroy_rect_layer(RectLayer *layer)
+void rect_layer_clean(RectLayer *rect_layer)
{
- trace_assert(layer);
-
- free(layer->ids.data);
- free(layer->rects.data);
- free(layer->colors.data);
- free(layer->actions.data);
-
- RETURN_LT0(layer->lt);
+ trace_assert(rect_layer);
+ dynarray_clear(&rect_layer->ids);
+ dynarray_clear(&rect_layer->rects);
+ dynarray_clear(&rect_layer->colors);
+ dynarray_clear(&rect_layer->actions);
}
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;
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);