#include "system/lt.h"
#include "system/str.h"
#include "system/log.h"
-#include "math/point.h"
+#include "math/vec.h"
#include "label_layer.h"
#include "dynarray.h"
#include "color.h"
#include "game/camera.h"
#include "color_picker.h"
#include "ui/edit_field.h"
+#include "math/extrema.h"
#define LABEL_LAYER_SELECTION_THICCNESS 5.0f
+
typedef enum {
LABEL_LAYER_IDLE = 0,
LABEL_LAYER_MOVE,
LABEL_LAYER_EDIT_TEXT,
- LABEL_LAYER_EDIT_ID
+ LABEL_LAYER_EDIT_ID,
+ LABEL_LAYER_RECOLOR
} LabelLayerState;
-// TODO(#963): LabelLayer cannot add the labels
-// TODO(#964): LabelLayer cannot modify the labels' id
+static int clipboard;
+static char clipboard_text[LABEL_LAYER_TEXT_MAX_SIZE];
+static Color clipboard_color;
+
struct LabelLayer {
Lt *lt;
LabelLayerState state;
Dynarray *positions;
Dynarray *colors;
Dynarray *texts;
- int selected;
+ int selection;
ColorPicker color_picker;
- Point move_anchor;
+ Vec2f move_anchor;
Edit_field *edit_field;
+ Vec2f inter_position;
+ Color inter_color;
+ int id_name_counter;
+ const char *id_name_prefix;
};
+typedef enum {
+ UNDO_ADD,
+ UNDO_DELETE,
+ UNDO_UPDATE,
+ UNDO_SWAP
+} UndoType;
+
+typedef struct {
+ UndoType type;
+ LabelLayer *layer;
+ char id[LABEL_LAYER_ID_MAX_SIZE];
+ Vec2f position;
+ Color color;
+ char text[LABEL_LAYER_TEXT_MAX_SIZE];
+ size_t index;
+ size_t index2;
+} UndoContext;
+
+static
+UndoContext create_undo_swap_context(LabelLayer *label_layer,
+ size_t index, size_t index2)
+{
+ trace_assert(label_layer);
+ trace_assert(index < dynarray_count(label_layer->positions));
+ trace_assert(index2 < dynarray_count(label_layer->positions));
+
+ UndoContext undo_context;
+ undo_context.type = UNDO_SWAP;
+ undo_context.layer = label_layer;
+ undo_context.index = index;
+ undo_context.index2 = index2;
+ return undo_context;
+}
+
+static
+UndoContext create_undo_context(LabelLayer *label_layer, UndoType type)
+{
+ trace_assert(label_layer);
+ trace_assert(type != UNDO_SWAP);
+
+ UndoContext undo_context;
+
+ size_t index = type == UNDO_ADD
+ ? dynarray_count(label_layer->positions) - 1
+ : (size_t)label_layer->selection;
+
+ undo_context.type = type;
+ undo_context.layer = label_layer;
+ dynarray_copy_to(label_layer->ids, &undo_context.id, index);
+ dynarray_copy_to(label_layer->positions, &undo_context.position, index);
+ dynarray_copy_to(label_layer->colors, &undo_context.color, index);
+ dynarray_copy_to(label_layer->texts, &undo_context.text, index);
+ undo_context.index = index;
+
+ return undo_context;
+}
+
+static
+void label_layer_undo(void *context, size_t context_size)
+{
+ trace_assert(context);
+ trace_assert(sizeof(UndoContext) == context_size);
+
+ UndoContext *undo_context = context;
+ LabelLayer *label_layer = undo_context->layer;
+
+ switch (undo_context->type) {
+ case UNDO_ADD: {
+ dynarray_delete_at(label_layer->ids, undo_context->index);
+ dynarray_delete_at(label_layer->positions, undo_context->index);
+ dynarray_delete_at(label_layer->colors, undo_context->index);
+ dynarray_delete_at(label_layer->texts, undo_context->index);
+ } break;
+
+ case UNDO_DELETE: {
+ dynarray_insert_before(label_layer->ids, undo_context->index, &undo_context->id);
+ dynarray_insert_before(label_layer->positions, undo_context->index, &undo_context->position);
+ dynarray_insert_before(label_layer->colors, undo_context->index, &undo_context->color);
+ dynarray_insert_before(label_layer->texts, undo_context->index, &undo_context->text);
+ } break;
+
+ case UNDO_UPDATE: {
+ dynarray_replace_at(label_layer->ids, undo_context->index, &undo_context->id);
+ dynarray_replace_at(label_layer->positions, undo_context->index, &undo_context->position);
+ dynarray_replace_at(label_layer->colors, undo_context->index, &undo_context->color);
+ dynarray_replace_at(label_layer->texts, undo_context->index, &undo_context->text);
+ } break;
+
+ case UNDO_SWAP: {
+ dynarray_swap(label_layer->ids, undo_context->index, undo_context->index2);
+ dynarray_swap(label_layer->positions, undo_context->index, undo_context->index2);
+ dynarray_swap(label_layer->colors, undo_context->index, undo_context->index2);
+ dynarray_swap(label_layer->texts, undo_context->index, undo_context->index2);
+ } break;
+ }
+}
+
+#define UNDO_PUSH(HISTORY, CONTEXT) \
+ do { \
+ UndoContext context = (CONTEXT); \
+ undo_history_push( \
+ HISTORY, \
+ label_layer_undo, \
+ &context, \
+ sizeof(context)); \
+ } while(0)
+
+
LayerPtr label_layer_as_layer(LabelLayer *label_layer)
{
LayerPtr layer = {
return layer;
}
-LabelLayer *create_label_layer(void)
+LabelLayer *create_label_layer(const char *id_name_prefix)
{
Lt *lt = create_lt();
RETURN_LT(lt, NULL);
}
- label_layer->positions = PUSH_LT(lt, create_dynarray(sizeof(Point)), destroy_dynarray);
+ label_layer->positions = PUSH_LT(lt, create_dynarray(sizeof(Vec2f)), destroy_dynarray);
if (label_layer->positions == NULL) {
RETURN_LT(lt, NULL);
}
}
label_layer->color_picker = create_color_picker_from_rgba(COLOR_RED);
- label_layer->selected = -1;
+ label_layer->selection = -1;
label_layer->edit_field = PUSH_LT(
lt,
RETURN_LT(lt, NULL);
}
+ label_layer->id_name_prefix = id_name_prefix;
+
return label_layer;
}
-LabelLayer *create_label_layer_from_line_stream(LineStream *line_stream)
+LabelLayer *create_label_layer_from_line_stream(LineStream *line_stream, const char *id_name_prefix)
{
trace_assert(line_stream);
- LabelLayer *label_layer = create_label_layer();
+ LabelLayer *label_layer = create_label_layer(id_name_prefix);
if (label_layer == NULL) {
RETURN_LT(label_layer->lt, NULL);
for (size_t i = 0; i < n; ++i) {
char hex[7];
char id[LABEL_LAYER_ID_MAX_SIZE];
- Point position;
+ Vec2f position;
line = line_stream_next(line_stream);
if (line == NULL) {
}
int label_layer_render(const LabelLayer *label_layer,
- Camera *camera,
+ const Camera *camera,
int active)
{
trace_assert(label_layer);
size_t n = dynarray_count(label_layer->ids);
char *ids = dynarray_data(label_layer->ids);
- Point *positions = dynarray_data(label_layer->positions);
+ Vec2f *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) {
+ const Color color = label_layer->state == LABEL_LAYER_RECOLOR && label_layer->selection == (int) i
+ ? label_layer->inter_color
+ : colors[i];
+
+ const Vec2f position =
+ label_layer->state == LABEL_LAYER_MOVE && label_layer->selection == (int) i
+ ? label_layer->inter_position
+ : positions[i];
+
+ // Label Text
+ if (label_layer->state == LABEL_LAYER_EDIT_TEXT && label_layer->selection == (int) i) {
if (edit_field_render_world(
label_layer->edit_field,
camera,
- positions[i]) < 0) {
+ position) < 0) {
return -1;
}
} else {
texts + i * LABEL_LAYER_TEXT_MAX_SIZE,
LABELS_SIZE,
color_scale(
- colors[i],
+ color,
rgba(1.0f, 1.0f, 1.0f, active ? 1.0f : 0.5f)),
- positions[i]) < 0) {
+ position) < 0) {
return -1;
}
}
- if (label_layer->state == LABEL_LAYER_EDIT_ID) {
+ // Label ID
+ if (label_layer->state == LABEL_LAYER_EDIT_ID && label_layer->selection == (int)i) {
if (edit_field_render_world(
label_layer->edit_field,
camera,
vec_sub(
- positions[i],
+ position,
vec(0.0f, FONT_CHAR_HEIGHT))) < 0) {
return -1;
}
ids + i * LABEL_LAYER_ID_MAX_SIZE,
vec(1.0f, 1.0f),
color_scale(
- color_invert(colors[i]),
+ color_invert(color),
rgba(1.0f, 1.0f, 1.0f, active ? 1.0f : 0.5f)),
- vec_sub(positions[i], vec(0.0f, FONT_CHAR_HEIGHT))) < 0) {
+ vec_sub(position, vec(0.0f, FONT_CHAR_HEIGHT))) < 0) {
return -1;
}
}
- }
-
- if (label_layer->selected >= 0) {
- Rect selection =
- rect_scale(
- camera_rect(
+ // Label Selection
+ if (active && label_layer->selection == (int) i) {
+ Rect selection =
+ rect_scale(
+ camera_rect(
+ camera,
+ rect_boundary2(
+ sprite_font_boundary_box(
+ camera_font(camera),
+ position,
+ LABELS_SIZE,
+ texts + label_layer->selection * LABEL_LAYER_TEXT_MAX_SIZE),
+ sprite_font_boundary_box(
+ camera_font(camera),
+ vec_sub(
+ position,
+ vec(0.0f, FONT_CHAR_HEIGHT)),
+ vec(1.0f, 1.0f),
+ ids + label_layer->selection * LABEL_LAYER_ID_MAX_SIZE))),
+ LABEL_LAYER_SELECTION_THICCNESS * 0.5f);
+
+
+ if (camera_draw_thicc_rect_screen(
camera,
- sprite_font_boundary_box(
- camera_font(camera),
- positions[label_layer->selected],
- LABELS_SIZE,
- texts + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE)),
- LABEL_LAYER_SELECTION_THICCNESS * 0.5f);
-
-
- if (camera_draw_thicc_rect_screen(
- camera,
- selection,
- colors[label_layer->selected],
- LABEL_LAYER_SELECTION_THICCNESS) < 0) {
- return -1;
+ selection,
+ color,
+ LABEL_LAYER_SELECTION_THICCNESS) < 0) {
+ return -1;
+ }
}
}
+
return 0;
}
static
int label_layer_element_at(LabelLayer *label_layer,
const Sprite_font *font,
- Point position)
+ Vec2f position)
{
trace_assert(label_layer);
- const size_t n = dynarray_count(label_layer->texts);
+ const int n = (int) 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);
+ Vec2f *positions = dynarray_data(label_layer->positions);
+
+ for (int i = n - 1; i >= 0; --i) {
+ 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 i;
}
}
return -1;
}
+static
+void label_layer_delete_selected_label(LabelLayer *label_layer,
+ UndoHistory *undo_history)
+{
+ trace_assert(label_layer);
+ trace_assert(label_layer->selection >= 0);
+
+ UNDO_PUSH(undo_history, create_undo_context(label_layer, UNDO_DELETE));
+
+ dynarray_delete_at(label_layer->ids, (size_t)label_layer->selection);
+ dynarray_delete_at(label_layer->positions, (size_t)label_layer->selection);
+ dynarray_delete_at(label_layer->colors, (size_t)label_layer->selection);
+ dynarray_delete_at(label_layer->texts, (size_t)label_layer->selection);
+
+ label_layer->selection = -1;
+}
+
+static
+int label_layer_add_label(LabelLayer *label_layer,
+ Vec2f position,
+ Color color,
+ const char *text,
+ UndoHistory *undo_history)
+{
+ 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];
+ snprintf(id, LABEL_LAYER_ID_MAX_SIZE, "%s_%d",
+ label_layer->id_name_prefix,
+ label_layer->id_name_counter++);
+
+ 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);
+ memcpy(
+ dynarray_pointer_at(label_layer->texts, n),
+ text,
+ min_size_t(LABEL_LAYER_ID_MAX_SIZE - 1, strlen(text)));
+
+ UNDO_PUSH(undo_history, create_undo_context(label_layer, UNDO_ADD));
+
+ return (int) n;
+}
+
+static
+void label_layer_swap_elements(LabelLayer *label_layer,
+ size_t a, size_t b,
+ UndoHistory *undo_history)
+{
+ trace_assert(label_layer);
+ trace_assert(undo_history);
+ trace_assert(a < dynarray_count(label_layer->positions));
+ trace_assert(b < dynarray_count(label_layer->positions));
+
+ dynarray_swap(label_layer->ids, a, b);
+ dynarray_swap(label_layer->positions, a, b);
+ dynarray_swap(label_layer->colors, a, b);
+ dynarray_swap(label_layer->texts, a, b);
+
+ UNDO_PUSH(undo_history, create_undo_swap_context(label_layer, a, b));
+}
+
static
int label_layer_idle_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);
+
+ int changed = 0;
+ if (color_picker_event(
+ &label_layer->color_picker,
+ event,
+ camera,
+ &changed) < 0) {
+ return -1;
+ }
+
+ if (changed) {
+ if (label_layer->selection >= 0) {
+ label_layer->state = LABEL_LAYER_RECOLOR;
+ label_layer->inter_color = color_picker_rgba(&label_layer->color_picker);
+ }
+ return 0;
+ }
+
Color *colors = dynarray_data(label_layer->colors);
- Point *positions = dynarray_data(label_layer->positions);
+ Vec2f *positions = dynarray_data(label_layer->positions);
char *ids = dynarray_data(label_layer->ids);
char *texts = dynarray_data(label_layer->texts);
case SDL_MOUSEBUTTONDOWN: {
switch (event->button.button) {
case SDL_BUTTON_LEFT: {
- const Point position = camera_map_screen(
+ const Vec2f position = camera_map_screen(
camera,
event->button.x,
event->button.y);
if (element >= 0) {
label_layer->move_anchor = vec_sub(position, positions[element]);
- label_layer->selected = element;
+ label_layer->selection = element;
label_layer->state = LABEL_LAYER_MOVE;
+ label_layer->inter_position = positions[element];
label_layer->color_picker =
create_color_picker_from_rgba(colors[element]);
+ } else {
+ label_layer->selection = label_layer_add_label(
+ label_layer,
+ position,
+ color_picker_rgba(
+ &label_layer->color_picker),
+ "",
+ undo_history);
+ label_layer->state = LABEL_LAYER_EDIT_TEXT;
+ edit_field_replace(
+ label_layer->edit_field,
+ texts + label_layer->selection * LABEL_LAYER_TEXT_MAX_SIZE);
+ edit_field_restyle(
+ label_layer->edit_field,
+ LABELS_SIZE,
+ colors[label_layer->selection]);
+ SDL_StartTextInput();
}
} break;
}
case SDL_KEYDOWN: {
switch (event->key.keysym.sym) {
+ case SDLK_UP: {
+ if ((event->key.keysym.mod & KMOD_SHIFT)
+ && (label_layer->selection >= 0)
+ && ((size_t)(label_layer->selection + 1) < dynarray_count(label_layer->positions))) {
+ label_layer_swap_elements(
+ label_layer,
+ (size_t) label_layer->selection,
+ (size_t) label_layer->selection + 1,
+ undo_history);
+ label_layer->selection++;
+ }
+ } break;
+
+ case SDLK_DOWN: {
+ if ((event->key.keysym.mod & KMOD_SHIFT)
+ && (label_layer->selection > 0)
+ && ((size_t) label_layer->selection < dynarray_count(label_layer->positions))) {
+ label_layer_swap_elements(
+ label_layer,
+ (size_t) label_layer->selection,
+ (size_t) label_layer->selection - 1,
+ undo_history);
+ label_layer->selection--;
+ }
+ } break;
+
case SDLK_F2: {
- if (label_layer->selected >= 0) {
+ if (label_layer->selection >= 0) {
label_layer->state = LABEL_LAYER_EDIT_TEXT;
edit_field_replace(
label_layer->edit_field,
- texts + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE);
+ texts + label_layer->selection * LABEL_LAYER_TEXT_MAX_SIZE);
edit_field_restyle(
label_layer->edit_field,
LABELS_SIZE,
- colors[label_layer->selected]);
+ colors[label_layer->selection]);
SDL_StartTextInput();
}
} break;
case SDLK_F3: {
- if (label_layer->selected >= 0) {
+ if (label_layer->selection >= 0) {
label_layer->state = LABEL_LAYER_EDIT_ID;
edit_field_replace(
label_layer->edit_field,
- ids + label_layer->selected * LABEL_LAYER_ID_MAX_SIZE);
+ ids + label_layer->selection * LABEL_LAYER_ID_MAX_SIZE);
edit_field_restyle(
label_layer->edit_field,
vec(1.0f, 1.0f),
- color_invert(colors[label_layer->selected]));
+ color_invert(colors[label_layer->selection]));
SDL_StartTextInput();
}
} break;
+
+ case SDLK_DELETE: {
+ if (label_layer->selection >= 0) {
+ label_layer_delete_selected_label(
+ label_layer,
+ undo_history);
+ label_layer->selection = -1;
+ }
+ } break;
+
+ case SDLK_c: {
+ if ((event->key.keysym.mod & KMOD_LCTRL) && label_layer->selection >= 0) {
+ clipboard = 1;
+ dynarray_copy_to(label_layer->texts, clipboard_text, (size_t)label_layer->selection);
+ dynarray_copy_to(label_layer->colors, &clipboard_color, (size_t)label_layer->selection);
+ }
+ } break;
+
+ case SDLK_v: {
+ if ((event->key.keysym.mod & KMOD_LCTRL) && clipboard) {
+ int x, y;
+ SDL_GetMouseState(&x, &y);
+ Vec2f position = camera_map_screen(camera, x, y);
+
+ label_layer_add_label(
+ label_layer,
+ position,
+ clipboard_color,
+ clipboard_text,
+ undo_history);
+ }
+ } break;
}
} break;
}
static
int label_layer_move_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(label_layer->selected >= 0);
+ trace_assert(label_layer->selection >= 0);
+
+ Vec2f *positions = dynarray_data(label_layer->positions);
switch (event->type) {
case SDL_MOUSEMOTION: {
- Point *positions = dynarray_data(label_layer->positions);
- positions[label_layer->selected] =
- vec_sub(
- camera_map_screen(
- camera,
- event->motion.x,
- event->motion.y),
- label_layer->move_anchor);
+ label_layer->inter_position = vec_sub(
+ camera_map_screen(
+ camera,
+ event->motion.x,
+ event->motion.y),
+ label_layer->move_anchor);
} break;
case SDL_MOUSEBUTTONUP: {
switch (event->button.button) {
case SDL_BUTTON_LEFT: {
+ const float distance = vec_length(
+ vec_sub(label_layer->inter_position,
+ positions[label_layer->selection]));
+
+ if (distance > 1e-6) {
+ UNDO_PUSH(undo_history, create_undo_context(label_layer, UNDO_UPDATE));
+
+ dynarray_replace_at(
+ label_layer->positions,
+ (size_t)label_layer->selection,
+ &label_layer->inter_position);
+ }
+
label_layer->state = LABEL_LAYER_IDLE;
} break;
}
static
int label_layer_edit_text_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(label_layer->selected >= 0);
+ trace_assert(label_layer->selection >= 0);
switch (event->type) {
case SDL_KEYDOWN: {
- if (event->key.keysym.sym == SDLK_RETURN) {
+ switch (event->key.keysym.sym) {
+ case SDLK_RETURN: {
+ UNDO_PUSH(undo_history, create_undo_context(label_layer, UNDO_UPDATE));
+
char *text =
- (char*)dynarray_data(label_layer->texts) + label_layer->selected * LABEL_LAYER_TEXT_MAX_SIZE;
+ (char*)dynarray_data(label_layer->texts) + label_layer->selection * 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;
}
static
int label_layer_edit_id_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(label_layer->selected >= 0);
-
+ trace_assert(undo_history);
+ trace_assert(label_layer->selection >= 0);
switch (event->type) {
case SDL_KEYDOWN: {
- if (event->key.keysym.sym == SDLK_RETURN) {
+ switch (event->key.keysym.sym) {
+ case SDLK_RETURN: {
+ UNDO_PUSH(undo_history, create_undo_context(label_layer, UNDO_UPDATE));
+
char *id =
- (char*)dynarray_data(label_layer->ids) + label_layer->selected * LABEL_LAYER_ID_MAX_SIZE;
+ (char*)dynarray_data(label_layer->ids) + label_layer->selection * 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;
}
-
return edit_field_event(label_layer->edit_field, event);
}
-int label_layer_event(LabelLayer *label_layer,
- const SDL_Event *event,
- const Camera *camera)
+static
+int label_layer_recolor_event(LabelLayer *label_layer,
+ const SDL_Event *event,
+ const Camera *camera,
+ UndoHistory *undo_history)
{
trace_assert(label_layer);
trace_assert(event);
trace_assert(camera);
+ trace_assert(undo_history);
+ trace_assert(label_layer->selection >= 0);
int changed = 0;
if (color_picker_event(
&label_layer->color_picker,
event,
+ camera,
&changed) < 0) {
return -1;
}
- if (changed && label_layer->selected >= 0) {
- Color *colors = dynarray_data(label_layer->colors);
- colors[label_layer->selected] =
+ if (changed) {
+ label_layer->inter_color =
color_picker_rgba(&label_layer->color_picker);
+
+ if (!color_picker_drag(&label_layer->color_picker)) {
+ UNDO_PUSH(undo_history, create_undo_context(label_layer, UNDO_UPDATE));
+
+ dynarray_replace_at(
+ label_layer->colors,
+ (size_t) label_layer->selection,
+ &label_layer->inter_color);
+ label_layer->state = LABEL_LAYER_IDLE;
+ }
}
+ return 0;
+}
+
+int label_layer_event(LabelLayer *label_layer,
+ const SDL_Event *event,
+ const Camera *camera,
+ UndoHistory *undo_history)
+{
+ trace_assert(label_layer);
+ trace_assert(event);
+ trace_assert(camera);
+ trace_assert(undo_history);
+
switch (label_layer->state) {
case LABEL_LAYER_IDLE:
- return label_layer_idle_event(label_layer, event, camera);
+ return label_layer_idle_event(label_layer, event, camera, undo_history);
case LABEL_LAYER_MOVE:
- return label_layer_move_event(label_layer, event, camera);
+ return label_layer_move_event(label_layer, event, camera, undo_history);
case LABEL_LAYER_EDIT_TEXT:
- return label_layer_edit_text_event(label_layer, event, camera);
+ return label_layer_edit_text_event(label_layer, event, camera, undo_history);
case LABEL_LAYER_EDIT_ID:
- return label_layer_edit_id_event(label_layer, event, camera);
+ return label_layer_edit_id_event(label_layer, event, camera, undo_history);
+
+ case LABEL_LAYER_RECOLOR:
+ return label_layer_recolor_event(label_layer, event, camera, undo_history);
}
return 0;
return dynarray_data(label_layer->ids);
}
-Point *label_layer_positions(const LabelLayer *label_layer)
+Vec2f *label_layer_positions(const LabelLayer *label_layer)
{
return dynarray_data(label_layer->positions);
}
size_t n = dynarray_count(label_layer->ids);
char *ids = dynarray_data(label_layer->ids);
- Point *positions = dynarray_data(label_layer->positions);
+ Vec2f *positions = dynarray_data(label_layer->positions);
Color *colors = dynarray_data(label_layer->colors);
char *texts = dynarray_data(label_layer->texts);