#define LABEL_LAYER_SELECTION_THICCNESS 5.0f
+// TODO(#999): LabelLayer does not support UndoHistory
+
typedef enum {
LABEL_LAYER_IDLE = 0,
LABEL_LAYER_MOVE,
- LABEL_LAYER_EDIT_TEXT
+ LABEL_LAYER_EDIT_TEXT,
+ LABEL_LAYER_EDIT_ID
} LabelLayerState;
-// TODO(#963): LabelLayer cannot add the labels
-// TODO(#964): LabelLayer cannot modify the labels' id
struct LabelLayer {
Lt *lt;
LabelLayerState state;
}
size_t n = dynarray_count(label_layer->ids);
+ char *ids = dynarray_data(label_layer->ids);
Point *positions = dynarray_data(label_layer->positions);
Color *colors = dynarray_data(label_layer->colors);
char *texts = dynarray_data(label_layer->texts);
/* TODO(#891): LabelLayer doesn't show the final position of Label after the animation */
for (size_t i = 0; i < n; ++i) {
- if (label_layer->state == LABEL_LAYER_EDIT_TEXT) {
+ if (label_layer->state == LABEL_LAYER_EDIT_TEXT && label_layer->selected == (int) i) {
if (edit_field_render_world(
label_layer->edit_field,
camera,
return -1;
}
}
+
+ if (label_layer->state == LABEL_LAYER_EDIT_ID && label_layer->selected == (int)i) {
+ if (edit_field_render_world(
+ label_layer->edit_field,
+ camera,
+ vec_sub(
+ positions[i],
+ vec(0.0f, FONT_CHAR_HEIGHT))) < 0) {
+ return -1;
+ }
+ } else {
+ if (camera_render_text(
+ camera,
+ ids + i * LABEL_LAYER_ID_MAX_SIZE,
+ vec(1.0f, 1.0f),
+ color_scale(
+ color_invert(colors[i]),
+ rgba(1.0f, 1.0f, 1.0f, active ? 1.0f : 0.5f)),
+ vec_sub(positions[i], vec(0.0f, FONT_CHAR_HEIGHT))) < 0) {
+ return -1;
+ }
+ }
}
if (label_layer->selected >= 0) {
rect_scale(
camera_rect(
camera,
- sprite_font_boundary_box(
- camera_font(camera),
- positions[label_layer->selected],
- LABELS_SIZE,
- texts + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE)),
+ rect_boundary2(
+ sprite_font_boundary_box(
+ camera_font(camera),
+ positions[label_layer->selected],
+ LABELS_SIZE,
+ texts + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE),
+ sprite_font_boundary_box(
+ camera_font(camera),
+ vec_sub(
+ positions[label_layer->selected],
+ vec(0.0f, FONT_CHAR_HEIGHT)),
+ vec(1.0f, 1.0f),
+ ids + label_layer->selected * LABEL_LAYER_ID_MAX_SIZE))),
LABEL_LAYER_SELECTION_THICCNESS * 0.5f);
trace_assert(label_layer);
const size_t n = dynarray_count(label_layer->texts);
+ char *ids = dynarray_data(label_layer->ids);
char *texts = dynarray_data(label_layer->texts);
Point *positions = dynarray_data(label_layer->positions);
for (size_t i = 0; i < n; ++i) {
- Rect boundary = sprite_font_boundary_box(
- font,
- positions[i],
- LABELS_SIZE,
- texts + i * LABEL_LAYER_TEXT_MAX_SIZE);
+ Rect boundary = rect_boundary2(
+ sprite_font_boundary_box(
+ font,
+ positions[i],
+ LABELS_SIZE,
+ texts + i * LABEL_LAYER_TEXT_MAX_SIZE),
+ sprite_font_boundary_box(
+ font,
+ vec_sub(
+ positions[i],
+ vec(0.0f, FONT_CHAR_HEIGHT)),
+ vec(1.0f, 1.0f),
+ ids + i * LABEL_LAYER_ID_MAX_SIZE));
if (rect_contains_point(boundary, position)) {
return (int) i;
return -1;
}
+static
+void label_layer_delete_nth_label(LabelLayer *label_layer,
+ size_t i)
+{
+ trace_assert(label_layer);
+ dynarray_delete_at(label_layer->ids, i);
+ dynarray_delete_at(label_layer->positions, i);
+ dynarray_delete_at(label_layer->colors, i);
+ dynarray_delete_at(label_layer->texts, i);
+}
+
+static
+int label_layer_add_label(LabelLayer *label_layer,
+ Point position,
+ Color color)
+{
+ trace_assert(label_layer);
+
+ // TODO(#982): id generation code is duplicated in label_layer, point_layer and rect_layer
+ char id[LABEL_LAYER_ID_MAX_SIZE];
+ for (size_t i = 0; i < LABEL_LAYER_ID_MAX_SIZE - 1; ++i) {
+ id[i] = (char) ('a' + rand() % ('z' - 'a' + 1));
+ }
+ id[LABEL_LAYER_ID_MAX_SIZE - 1] = '\0';
+
+ size_t n = dynarray_count(label_layer->ids);
+
+ dynarray_push(label_layer->ids, id);
+ dynarray_push(label_layer->positions, &position);
+ dynarray_push(label_layer->colors, &color);
+ dynarray_push_empty(label_layer->texts);
+
+ return (int) n;
+}
+
static
int label_layer_idle_event(LabelLayer *label_layer,
const SDL_Event *event,
trace_assert(event);
trace_assert(camera);
+ Color *colors = dynarray_data(label_layer->colors);
+ Point *positions = dynarray_data(label_layer->positions);
+ char *ids = dynarray_data(label_layer->ids);
+ char *texts = dynarray_data(label_layer->texts);
+
switch (event->type) {
case SDL_MOUSEBUTTONDOWN: {
switch (event->button.button) {
position);
if (element >= 0) {
- Point *positions = dynarray_data(label_layer->positions);
- Color *colors = dynarray_data(label_layer->colors);
-
label_layer->move_anchor = vec_sub(position, positions[element]);
label_layer->selected = element;
label_layer->state = LABEL_LAYER_MOVE;
label_layer->color_picker =
create_color_picker_from_rgba(colors[element]);
+ } else {
+ label_layer->selected = label_layer_add_label(
+ label_layer,
+ position,
+ color_picker_rgba(
+ &label_layer->color_picker));
+ label_layer->state = LABEL_LAYER_EDIT_TEXT;
+ edit_field_replace(
+ label_layer->edit_field,
+ texts + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE);
+ edit_field_restyle(
+ label_layer->edit_field,
+ LABELS_SIZE,
+ colors[label_layer->selected]);
+ SDL_StartTextInput();
}
} break;
}
switch (event->key.keysym.sym) {
case SDLK_F2: {
if (label_layer->selected >= 0) {
- char *texts = dynarray_data(label_layer->texts);
label_layer->state = LABEL_LAYER_EDIT_TEXT;
edit_field_replace(
label_layer->edit_field,
texts + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE);
+ edit_field_restyle(
+ label_layer->edit_field,
+ LABELS_SIZE,
+ colors[label_layer->selected]);
+ SDL_StartTextInput();
+ }
+ } break;
+
+ case SDLK_F3: {
+ if (label_layer->selected >= 0) {
+ label_layer->state = LABEL_LAYER_EDIT_ID;
+ edit_field_replace(
+ label_layer->edit_field,
+ ids + label_layer->selected * LABEL_LAYER_ID_MAX_SIZE);
+ edit_field_restyle(
+ label_layer->edit_field,
+ vec(1.0f, 1.0f),
+ color_invert(colors[label_layer->selected]));
SDL_StartTextInput();
}
} break;
+
+ case SDLK_DELETE: {
+ if (label_layer->selected >= 0) {
+ label_layer_delete_nth_label(
+ label_layer,
+ (size_t) label_layer->selected);
+ label_layer->selected = -1;
+ }
+ } break;
}
} break;
}
switch (event->type) {
case SDL_KEYDOWN: {
- if (event->key.keysym.sym == SDLK_RETURN) {
+ switch (event->key.keysym.sym) {
+ case SDLK_RETURN: {
char *text =
(char*)dynarray_data(label_layer->texts) + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE;
memset(text, 0, LABEL_LAYER_TEXT_MAX_SIZE);
memcpy(text, edit_field_as_text(label_layer->edit_field), LABEL_LAYER_TEXT_MAX_SIZE - 1);
label_layer->state = LABEL_LAYER_IDLE;
+ SDL_StopTextInput();
+ return 0;
+ } break;
+
+ case SDLK_ESCAPE: {
+ label_layer->state = LABEL_LAYER_IDLE;
+ SDL_StopTextInput();
+ return 0;
+ } break;
+ }
+ } break;
+ }
+
+ return edit_field_event(label_layer->edit_field, event);
+}
+
+static
+int label_layer_edit_id_event(LabelLayer *label_layer,
+ const SDL_Event *event,
+ const Camera *camera)
+{
+ trace_assert(label_layer);
+ trace_assert(event);
+ trace_assert(camera);
+ trace_assert(label_layer->selected >= 0);
+
+ switch (event->type) {
+ case SDL_KEYDOWN: {
+ switch (event->key.keysym.sym) {
+ case SDLK_RETURN: {
+ char *id =
+ (char*)dynarray_data(label_layer->ids) + label_layer->selected * LABEL_LAYER_ID_MAX_SIZE;
+ memset(id, 0, LABEL_LAYER_ID_MAX_SIZE);
+ memcpy(id, edit_field_as_text(label_layer->edit_field), LABEL_LAYER_ID_MAX_SIZE - 1);
+ label_layer->state = LABEL_LAYER_IDLE;
+ SDL_StopTextInput();
return 0;
+ } break;
+
+ case SDLK_ESCAPE: {
+ label_layer->state = LABEL_LAYER_IDLE;
+ SDL_StopTextInput();
+ return 0;
+ } break;
}
} break;
}
int label_layer_event(LabelLayer *label_layer,
const SDL_Event *event,
- const Camera *camera)
+ const Camera *camera,
+ UndoHistory *undo_history)
{
trace_assert(label_layer);
trace_assert(event);
trace_assert(camera);
+ trace_assert(undo_history);
int changed = 0;
return -1;
}
- if (changed && label_layer->selected >= 0) {
- Color *colors = dynarray_data(label_layer->colors);
- colors[label_layer->selected] =
- color_picker_rgba(&label_layer->color_picker);
+ if (changed) {
+ if (label_layer->selected >= 0) {
+ Color *colors = dynarray_data(label_layer->colors);
+ colors[label_layer->selected] =
+ color_picker_rgba(&label_layer->color_picker);
+ }
+ return 0;
}
switch (label_layer->state) {
case LABEL_LAYER_EDIT_TEXT:
return label_layer_edit_text_event(label_layer, event, camera);
+
+ case LABEL_LAYER_EDIT_ID:
+ return label_layer_edit_id_event(label_layer, event, camera);
}
return 0;