5 #include "system/line_stream.h"
6 #include "system/stacktrace.h"
7 #include "system/nth_alloc.h"
9 #include "system/str.h"
10 #include "system/log.h"
11 #include "math/point.h"
12 #include "label_layer.h"
15 #include "game/camera.h"
16 #include "color_picker.h"
17 #include "ui/edit_field.h"
19 #define LABEL_LAYER_SELECTION_THICCNESS 5.0f
24 LABEL_LAYER_EDIT_TEXT,
30 LabelLayerState state;
36 ColorPicker color_picker;
38 Edit_field *edit_field;
41 LayerPtr label_layer_as_layer(LabelLayer *label_layer)
50 LabelLayer *create_label_layer(void)
54 LabelLayer *label_layer = PUSH_LT(
55 lt, nth_calloc(1, sizeof(LabelLayer)), free);
56 if (label_layer == NULL) {
61 label_layer->ids = PUSH_LT(
63 create_dynarray(sizeof(char) * LABEL_LAYER_ID_MAX_SIZE),
65 if (label_layer->ids == NULL) {
69 label_layer->positions = PUSH_LT(lt, create_dynarray(sizeof(Point)), destroy_dynarray);
70 if (label_layer->positions == NULL) {
74 label_layer->colors = PUSH_LT(lt, create_dynarray(sizeof(Color)), destroy_dynarray);
75 if (label_layer->colors == NULL) {
79 label_layer->texts = PUSH_LT(
81 create_dynarray(sizeof(char) * LABEL_LAYER_TEXT_MAX_SIZE),
83 if (label_layer->texts == NULL) {
87 label_layer->color_picker = create_color_picker_from_rgba(COLOR_RED);
88 label_layer->selected = -1;
90 label_layer->edit_field = PUSH_LT(
92 create_edit_field(LABELS_SIZE, COLOR_RED),
94 if (label_layer->edit_field == NULL) {
101 LabelLayer *create_label_layer_from_line_stream(LineStream *line_stream)
103 trace_assert(line_stream);
104 LabelLayer *label_layer = create_label_layer();
106 if (label_layer == NULL) {
107 RETURN_LT(label_layer->lt, NULL);
110 const char *line = line_stream_next(line_stream);
112 log_fail("Could not read amount of labels\n");
113 RETURN_LT(label_layer->lt, NULL);
117 if (sscanf(line, "%zu", &n) == EOF) {
118 log_fail("Could not parse amount of labels\n");
119 RETURN_LT(label_layer->lt, NULL);
122 for (size_t i = 0; i < n; ++i) {
124 char id[LABEL_LAYER_ID_MAX_SIZE];
127 line = line_stream_next(line_stream);
129 log_fail("Could not read label meta info\n");
130 RETURN_LT(label_layer->lt, NULL);
135 "%"STRINGIFY(LABEL_LAYER_ID_MAX_SIZE)"s%f%f%6s\n",
136 id, &position.x, &position.y, hex) == EOF) {
137 log_fail("Could not parse label meta info\n");
138 RETURN_LT(label_layer->lt, NULL);
141 Color color = hexstr(hex);
143 dynarray_push(label_layer->ids, id);
144 dynarray_push(label_layer->positions, &position);
145 dynarray_push(label_layer->colors, &color);
147 line = line_stream_next(line_stream);
149 log_fail("Could not read label text\n");
152 char label_text[LABEL_LAYER_TEXT_MAX_SIZE] = {0};
153 memcpy(label_text, line, LABEL_LAYER_TEXT_MAX_SIZE - 1);
154 trim_endline(label_text);
155 dynarray_push(label_layer->texts, &label_text);
161 void destroy_label_layer(LabelLayer *label_layer)
163 trace_assert(label_layer);
164 destroy_lt(label_layer->lt);
167 int label_layer_render(const LabelLayer *label_layer,
171 trace_assert(label_layer);
172 trace_assert(camera);
174 if (active && color_picker_render(&label_layer->color_picker, camera) < 0) {
178 size_t n = dynarray_count(label_layer->ids);
179 char *ids = dynarray_data(label_layer->ids);
180 Point *positions = dynarray_data(label_layer->positions);
181 Color *colors = dynarray_data(label_layer->colors);
182 char *texts = dynarray_data(label_layer->texts);
184 /* TODO(#891): LabelLayer doesn't show the final position of Label after the animation */
185 for (size_t i = 0; i < n; ++i) {
186 if (label_layer->state == LABEL_LAYER_EDIT_TEXT && label_layer->selected == (int) i) {
187 if (edit_field_render_world(
188 label_layer->edit_field,
194 if (camera_render_text(
196 texts + i * LABEL_LAYER_TEXT_MAX_SIZE,
200 rgba(1.0f, 1.0f, 1.0f, active ? 1.0f : 0.5f)),
206 if (label_layer->state == LABEL_LAYER_EDIT_ID && label_layer->selected == (int)i) {
207 if (edit_field_render_world(
208 label_layer->edit_field,
212 vec(0.0f, FONT_CHAR_HEIGHT))) < 0) {
216 if (camera_render_text(
218 ids + i * LABEL_LAYER_ID_MAX_SIZE,
221 color_invert(colors[i]),
222 rgba(1.0f, 1.0f, 1.0f, active ? 1.0f : 0.5f)),
223 vec_sub(positions[i], vec(0.0f, FONT_CHAR_HEIGHT))) < 0) {
229 if (label_layer->selected >= 0) {
236 sprite_font_boundary_box(
238 positions[label_layer->selected],
240 texts + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE),
241 sprite_font_boundary_box(
244 positions[label_layer->selected],
245 vec(0.0f, FONT_CHAR_HEIGHT)),
247 ids + label_layer->selected * LABEL_LAYER_ID_MAX_SIZE))),
248 LABEL_LAYER_SELECTION_THICCNESS * 0.5f);
251 if (camera_draw_thicc_rect_screen(
254 colors[label_layer->selected],
255 LABEL_LAYER_SELECTION_THICCNESS) < 0) {
264 int label_layer_element_at(LabelLayer *label_layer,
265 const Sprite_font *font,
268 trace_assert(label_layer);
270 const size_t n = dynarray_count(label_layer->texts);
271 char *ids = dynarray_data(label_layer->ids);
272 char *texts = dynarray_data(label_layer->texts);
273 Point *positions = dynarray_data(label_layer->positions);
275 for (size_t i = 0; i < n; ++i) {
276 Rect boundary = rect_boundary2(
277 sprite_font_boundary_box(
281 texts + i * LABEL_LAYER_TEXT_MAX_SIZE),
282 sprite_font_boundary_box(
286 vec(0.0f, FONT_CHAR_HEIGHT)),
288 ids + i * LABEL_LAYER_ID_MAX_SIZE));
290 if (rect_contains_point(boundary, position)) {
299 void label_layer_delete_nth_label(LabelLayer *label_layer,
302 trace_assert(label_layer);
303 dynarray_delete_at(label_layer->ids, i);
304 dynarray_delete_at(label_layer->positions, i);
305 dynarray_delete_at(label_layer->colors, i);
306 dynarray_delete_at(label_layer->texts, i);
310 int label_layer_add_label(LabelLayer *label_layer,
314 trace_assert(label_layer);
316 // TODO(#982): id generation code is duplicated in label_layer, point_layer and rect_layer
317 char id[LABEL_LAYER_ID_MAX_SIZE];
318 for (size_t i = 0; i < LABEL_LAYER_ID_MAX_SIZE - 1; ++i) {
319 id[i] = (char) ('a' + rand() % ('z' - 'a' + 1));
321 id[LABEL_LAYER_ID_MAX_SIZE - 1] = '\0';
323 size_t n = dynarray_count(label_layer->ids);
325 dynarray_push(label_layer->ids, id);
326 dynarray_push(label_layer->positions, &position);
327 dynarray_push(label_layer->colors, &color);
328 dynarray_push_empty(label_layer->texts);
334 int label_layer_idle_event(LabelLayer *label_layer,
335 const SDL_Event *event,
336 const Camera *camera)
338 trace_assert(label_layer);
340 trace_assert(camera);
342 Color *colors = dynarray_data(label_layer->colors);
343 Point *positions = dynarray_data(label_layer->positions);
344 char *ids = dynarray_data(label_layer->ids);
345 char *texts = dynarray_data(label_layer->texts);
347 switch (event->type) {
348 case SDL_MOUSEBUTTONDOWN: {
349 switch (event->button.button) {
350 case SDL_BUTTON_LEFT: {
351 const Point position = camera_map_screen(
356 const int element = label_layer_element_at(
362 label_layer->move_anchor = vec_sub(position, positions[element]);
363 label_layer->selected = element;
364 label_layer->state = LABEL_LAYER_MOVE;
366 label_layer->color_picker =
367 create_color_picker_from_rgba(colors[element]);
369 label_layer->selected = label_layer_add_label(
373 &label_layer->color_picker));
374 label_layer->state = LABEL_LAYER_EDIT_TEXT;
376 label_layer->edit_field,
377 texts + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE);
379 label_layer->edit_field,
381 colors[label_layer->selected]);
382 SDL_StartTextInput();
389 switch (event->key.keysym.sym) {
391 if (label_layer->selected >= 0) {
392 label_layer->state = LABEL_LAYER_EDIT_TEXT;
394 label_layer->edit_field,
395 texts + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE);
397 label_layer->edit_field,
399 colors[label_layer->selected]);
400 SDL_StartTextInput();
405 if (label_layer->selected >= 0) {
406 label_layer->state = LABEL_LAYER_EDIT_ID;
408 label_layer->edit_field,
409 ids + label_layer->selected * LABEL_LAYER_ID_MAX_SIZE);
411 label_layer->edit_field,
413 color_invert(colors[label_layer->selected]));
414 SDL_StartTextInput();
419 if (label_layer->selected >= 0) {
420 label_layer_delete_nth_label(
422 (size_t) label_layer->selected);
423 label_layer->selected = -1;
434 int label_layer_move_event(LabelLayer *label_layer,
435 const SDL_Event *event,
436 const Camera *camera)
438 trace_assert(label_layer);
440 trace_assert(camera);
441 trace_assert(label_layer->selected >= 0);
443 switch (event->type) {
444 case SDL_MOUSEMOTION: {
445 Point *positions = dynarray_data(label_layer->positions);
446 positions[label_layer->selected] =
452 label_layer->move_anchor);
455 case SDL_MOUSEBUTTONUP: {
456 switch (event->button.button) {
457 case SDL_BUTTON_LEFT: {
458 label_layer->state = LABEL_LAYER_IDLE;
468 int label_layer_edit_text_event(LabelLayer *label_layer,
469 const SDL_Event *event,
470 const Camera *camera)
472 trace_assert(label_layer);
474 trace_assert(camera);
475 trace_assert(label_layer->selected >= 0);
477 switch (event->type) {
479 switch (event->key.keysym.sym) {
482 (char*)dynarray_data(label_layer->texts) + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE;
483 memset(text, 0, LABEL_LAYER_TEXT_MAX_SIZE);
484 memcpy(text, edit_field_as_text(label_layer->edit_field), LABEL_LAYER_TEXT_MAX_SIZE - 1);
485 label_layer->state = LABEL_LAYER_IDLE;
491 label_layer->state = LABEL_LAYER_IDLE;
499 return edit_field_event(label_layer->edit_field, event);
503 int label_layer_edit_id_event(LabelLayer *label_layer,
504 const SDL_Event *event,
505 const Camera *camera)
507 trace_assert(label_layer);
509 trace_assert(camera);
510 trace_assert(label_layer->selected >= 0);
512 switch (event->type) {
514 switch (event->key.keysym.sym) {
517 (char*)dynarray_data(label_layer->ids) + label_layer->selected * LABEL_LAYER_ID_MAX_SIZE;
518 memset(id, 0, LABEL_LAYER_ID_MAX_SIZE);
519 memcpy(id, edit_field_as_text(label_layer->edit_field), LABEL_LAYER_ID_MAX_SIZE - 1);
520 label_layer->state = LABEL_LAYER_IDLE;
526 label_layer->state = LABEL_LAYER_IDLE;
534 return edit_field_event(label_layer->edit_field, event);
537 int label_layer_event(LabelLayer *label_layer,
538 const SDL_Event *event,
539 const Camera *camera)
541 trace_assert(label_layer);
543 trace_assert(camera);
547 if (color_picker_event(
548 &label_layer->color_picker,
555 if (label_layer->selected >= 0) {
556 Color *colors = dynarray_data(label_layer->colors);
557 colors[label_layer->selected] =
558 color_picker_rgba(&label_layer->color_picker);
563 switch (label_layer->state) {
564 case LABEL_LAYER_IDLE:
565 return label_layer_idle_event(label_layer, event, camera);
567 case LABEL_LAYER_MOVE:
568 return label_layer_move_event(label_layer, event, camera);
570 case LABEL_LAYER_EDIT_TEXT:
571 return label_layer_edit_text_event(label_layer, event, camera);
573 case LABEL_LAYER_EDIT_ID:
574 return label_layer_edit_id_event(label_layer, event, camera);
580 size_t label_layer_count(const LabelLayer *label_layer)
582 return dynarray_count(label_layer->ids);
585 char *label_layer_ids(const LabelLayer *label_layer)
587 return dynarray_data(label_layer->ids);
590 Point *label_layer_positions(const LabelLayer *label_layer)
592 return dynarray_data(label_layer->positions);
595 Color *label_layer_colors(const LabelLayer *label_layer)
597 return dynarray_data(label_layer->colors);
600 char *labels_layer_texts(const LabelLayer *label_layer)
602 return dynarray_data(label_layer->texts);
605 int label_layer_dump_stream(const LabelLayer *label_layer, FILE *filedump)
607 trace_assert(label_layer);
608 trace_assert(filedump);
610 size_t n = dynarray_count(label_layer->ids);
611 char *ids = dynarray_data(label_layer->ids);
612 Point *positions = dynarray_data(label_layer->positions);
613 Color *colors = dynarray_data(label_layer->colors);
614 char *texts = dynarray_data(label_layer->texts);
616 fprintf(filedump, "%zd\n", n);
617 for (size_t i = 0; i < n; ++i) {
618 fprintf(filedump, "%s %f %f ",
619 ids + LABEL_LAYER_ID_MAX_SIZE * i,
620 positions[i].x, positions[i].y);
621 color_hex_to_stream(colors[i], filedump);
622 fprintf(filedump, "\n%s\n", texts + i * LABEL_LAYER_TEXT_MAX_SIZE);