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
27 // TODO(#963): LabelLayer cannot add the labels
28 // TODO(#964): LabelLayer cannot modify the labels' id
31 LabelLayerState state;
37 ColorPicker color_picker;
39 Edit_field *edit_field;
42 LayerPtr label_layer_as_layer(LabelLayer *label_layer)
51 LabelLayer *create_label_layer(void)
55 LabelLayer *label_layer = PUSH_LT(
56 lt, nth_calloc(1, sizeof(LabelLayer)), free);
57 if (label_layer == NULL) {
62 label_layer->ids = PUSH_LT(
64 create_dynarray(sizeof(char) * LABEL_LAYER_ID_MAX_SIZE),
66 if (label_layer->ids == NULL) {
70 label_layer->positions = PUSH_LT(lt, create_dynarray(sizeof(Point)), destroy_dynarray);
71 if (label_layer->positions == NULL) {
75 label_layer->colors = PUSH_LT(lt, create_dynarray(sizeof(Color)), destroy_dynarray);
76 if (label_layer->colors == NULL) {
80 label_layer->texts = PUSH_LT(
82 create_dynarray(sizeof(char) * LABEL_LAYER_TEXT_MAX_SIZE),
84 if (label_layer->texts == NULL) {
88 label_layer->color_picker = create_color_picker_from_rgba(COLOR_RED);
89 label_layer->selected = -1;
91 label_layer->edit_field = PUSH_LT(
93 create_edit_field(LABELS_SIZE, COLOR_RED),
95 if (label_layer->edit_field == NULL) {
102 LabelLayer *create_label_layer_from_line_stream(LineStream *line_stream)
104 trace_assert(line_stream);
105 LabelLayer *label_layer = create_label_layer();
107 if (label_layer == NULL) {
108 RETURN_LT(label_layer->lt, NULL);
111 const char *line = line_stream_next(line_stream);
113 log_fail("Could not read amount of labels\n");
114 RETURN_LT(label_layer->lt, NULL);
118 if (sscanf(line, "%zu", &n) == EOF) {
119 log_fail("Could not parse amount of labels\n");
120 RETURN_LT(label_layer->lt, NULL);
123 for (size_t i = 0; i < n; ++i) {
125 char id[LABEL_LAYER_ID_MAX_SIZE];
128 line = line_stream_next(line_stream);
130 log_fail("Could not read label meta info\n");
131 RETURN_LT(label_layer->lt, NULL);
136 "%"STRINGIFY(LABEL_LAYER_ID_MAX_SIZE)"s%f%f%6s\n",
137 id, &position.x, &position.y, hex) == EOF) {
138 log_fail("Could not parse label meta info\n");
139 RETURN_LT(label_layer->lt, NULL);
142 Color color = hexstr(hex);
144 dynarray_push(label_layer->ids, id);
145 dynarray_push(label_layer->positions, &position);
146 dynarray_push(label_layer->colors, &color);
148 line = line_stream_next(line_stream);
150 log_fail("Could not read label text\n");
153 char label_text[LABEL_LAYER_TEXT_MAX_SIZE] = {0};
154 memcpy(label_text, line, LABEL_LAYER_TEXT_MAX_SIZE - 1);
155 trim_endline(label_text);
156 dynarray_push(label_layer->texts, &label_text);
162 void destroy_label_layer(LabelLayer *label_layer)
164 trace_assert(label_layer);
165 destroy_lt(label_layer->lt);
168 int label_layer_render(const LabelLayer *label_layer,
172 trace_assert(label_layer);
173 trace_assert(camera);
175 if (active && color_picker_render(&label_layer->color_picker, camera) < 0) {
179 size_t n = dynarray_count(label_layer->ids);
180 char *ids = dynarray_data(label_layer->ids);
181 Point *positions = dynarray_data(label_layer->positions);
182 Color *colors = dynarray_data(label_layer->colors);
183 char *texts = dynarray_data(label_layer->texts);
185 /* TODO(#891): LabelLayer doesn't show the final position of Label after the animation */
186 for (size_t i = 0; i < n; ++i) {
187 if (label_layer->state == LABEL_LAYER_EDIT_TEXT) {
188 if (edit_field_render_world(
189 label_layer->edit_field,
195 if (camera_render_text(
197 texts + i * LABEL_LAYER_TEXT_MAX_SIZE,
201 rgba(1.0f, 1.0f, 1.0f, active ? 1.0f : 0.5f)),
207 if (camera_render_text(
209 ids + i * LABEL_LAYER_ID_MAX_SIZE,
212 color_invert(colors[i]),
213 rgba(1.0f, 1.0f, 1.0f, active ? 1.0f : 0.5f)),
214 vec_sub(positions[i], vec(0.0f, FONT_CHAR_HEIGHT))) < 0) {
219 if (label_layer->selected >= 0) {
225 sprite_font_boundary_box(
227 positions[label_layer->selected],
229 texts + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE)),
230 LABEL_LAYER_SELECTION_THICCNESS * 0.5f);
233 if (camera_draw_thicc_rect_screen(
236 colors[label_layer->selected],
237 LABEL_LAYER_SELECTION_THICCNESS) < 0) {
246 int label_layer_element_at(LabelLayer *label_layer,
247 const Sprite_font *font,
250 trace_assert(label_layer);
252 const size_t n = dynarray_count(label_layer->texts);
253 char *texts = dynarray_data(label_layer->texts);
254 Point *positions = dynarray_data(label_layer->positions);
256 for (size_t i = 0; i < n; ++i) {
257 Rect boundary = sprite_font_boundary_box(
261 texts + i * LABEL_LAYER_TEXT_MAX_SIZE);
263 if (rect_contains_point(boundary, position)) {
272 int label_layer_idle_event(LabelLayer *label_layer,
273 const SDL_Event *event,
274 const Camera *camera)
276 trace_assert(label_layer);
278 trace_assert(camera);
280 switch (event->type) {
281 case SDL_MOUSEBUTTONDOWN: {
282 switch (event->button.button) {
283 case SDL_BUTTON_LEFT: {
284 const Point position = camera_map_screen(
289 const int element = label_layer_element_at(
295 Point *positions = dynarray_data(label_layer->positions);
296 Color *colors = dynarray_data(label_layer->colors);
298 label_layer->move_anchor = vec_sub(position, positions[element]);
299 label_layer->selected = element;
300 label_layer->state = LABEL_LAYER_MOVE;
302 label_layer->color_picker =
303 create_color_picker_from_rgba(colors[element]);
310 switch (event->key.keysym.sym) {
312 if (label_layer->selected >= 0) {
313 char *texts = dynarray_data(label_layer->texts);
314 label_layer->state = LABEL_LAYER_EDIT_TEXT;
316 label_layer->edit_field,
317 texts + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE);
318 SDL_StartTextInput();
329 int label_layer_move_event(LabelLayer *label_layer,
330 const SDL_Event *event,
331 const Camera *camera)
333 trace_assert(label_layer);
335 trace_assert(camera);
336 trace_assert(label_layer->selected >= 0);
338 switch (event->type) {
339 case SDL_MOUSEMOTION: {
340 Point *positions = dynarray_data(label_layer->positions);
341 positions[label_layer->selected] =
347 label_layer->move_anchor);
350 case SDL_MOUSEBUTTONUP: {
351 switch (event->button.button) {
352 case SDL_BUTTON_LEFT: {
353 label_layer->state = LABEL_LAYER_IDLE;
363 int label_layer_edit_text_event(LabelLayer *label_layer,
364 const SDL_Event *event,
365 const Camera *camera)
367 trace_assert(label_layer);
369 trace_assert(camera);
370 trace_assert(label_layer->selected >= 0);
372 switch (event->type) {
374 if (event->key.keysym.sym == SDLK_RETURN) {
376 (char*)dynarray_data(label_layer->texts) + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE;
377 memset(text, 0, LABEL_LAYER_TEXT_MAX_SIZE);
378 memcpy(text, edit_field_as_text(label_layer->edit_field), LABEL_LAYER_TEXT_MAX_SIZE - 1);
379 label_layer->state = LABEL_LAYER_IDLE;
385 return edit_field_event(label_layer->edit_field, event);
388 int label_layer_event(LabelLayer *label_layer,
389 const SDL_Event *event,
390 const Camera *camera)
392 trace_assert(label_layer);
394 trace_assert(camera);
398 if (color_picker_event(
399 &label_layer->color_picker,
405 if (changed && label_layer->selected >= 0) {
406 Color *colors = dynarray_data(label_layer->colors);
407 colors[label_layer->selected] =
408 color_picker_rgba(&label_layer->color_picker);
411 switch (label_layer->state) {
412 case LABEL_LAYER_IDLE:
413 return label_layer_idle_event(label_layer, event, camera);
415 case LABEL_LAYER_MOVE:
416 return label_layer_move_event(label_layer, event, camera);
418 case LABEL_LAYER_EDIT_TEXT:
419 return label_layer_edit_text_event(label_layer, event, camera);
425 size_t label_layer_count(const LabelLayer *label_layer)
427 return dynarray_count(label_layer->ids);
430 char *label_layer_ids(const LabelLayer *label_layer)
432 return dynarray_data(label_layer->ids);
435 Point *label_layer_positions(const LabelLayer *label_layer)
437 return dynarray_data(label_layer->positions);
440 Color *label_layer_colors(const LabelLayer *label_layer)
442 return dynarray_data(label_layer->colors);
445 char *labels_layer_texts(const LabelLayer *label_layer)
447 return dynarray_data(label_layer->texts);
450 int label_layer_dump_stream(const LabelLayer *label_layer, FILE *filedump)
452 trace_assert(label_layer);
453 trace_assert(filedump);
455 size_t n = dynarray_count(label_layer->ids);
456 char *ids = dynarray_data(label_layer->ids);
457 Point *positions = dynarray_data(label_layer->positions);
458 Color *colors = dynarray_data(label_layer->colors);
459 char *texts = dynarray_data(label_layer->texts);
461 fprintf(filedump, "%zd\n", n);
462 for (size_t i = 0; i < n; ++i) {
463 fprintf(filedump, "%s %f %f ",
464 ids + LABEL_LAYER_ID_MAX_SIZE * i,
465 positions[i].x, positions[i].y);
466 color_hex_to_stream(colors[i], filedump);
467 fprintf(filedump, "\n%s\n", texts + i * LABEL_LAYER_TEXT_MAX_SIZE);