#include "system/str.h"
#define RECT_LAYER_ID_MAX_SIZE 36
-#define RECT_LAYER_SELECTION_THICCNESS 10.0f
+#define RECT_LAYER_SELECTION_THICCNESS 5.0f
#define PROTO_AREA_THRESHOLD 10.0
+// TODO(#942): RectLayer does not allow to move rectangle arround
typedef enum {
RECT_LAYER_IDLE = 0,
- RECT_LAYER_PROTO
+ RECT_LAYER_PROTO,
+ RECT_LAYER_RESIZE
} RectLayerState;
/* TODO(#886): RectLayer does not allow to modify ids of Rects */
return -1;
}
-static int rect_layer_delete_rect_at(RectLayer *layer, Vec position)
+static int rect_layer_delete_rect_at(RectLayer *layer, size_t i)
{
trace_assert(layer);
- int i = rect_layer_rect_at(layer, position);
- if (i >= 0) {
- dynarray_delete_at(layer->rects, (size_t)i);
- dynarray_delete_at(layer->colors, (size_t)i);
- dynarray_delete_at(layer->ids, (size_t)i);
- }
+ dynarray_delete_at(layer->rects, i);
+ dynarray_delete_at(layer->colors, i);
+ dynarray_delete_at(layer->ids, i);
return 0;
}
+static Rect rect_layer_resize_anchor(const RectLayer *layer, size_t i)
+{
+ Rect *rects = dynarray_data(layer->rects);
+ return rect(rects[i].x + rects[i].w,
+ rects[i].y + rects[i].h,
+ RECT_LAYER_SELECTION_THICCNESS * 2.0f,
+ RECT_LAYER_SELECTION_THICCNESS * 2.0f);
+}
+
static int rect_layer_add_rect(RectLayer *layer, Rect rect, Color color)
{
trace_assert(layer);
- (void) rect_layer_delete_rect_at; // TODO:
- // rect_layer_delete_rect_at is
- // unused until #938 is
- // implemented
if (dynarray_push(layer->rects, &rect) < 0) {
return -1;
}
layer->color_picker = create_color_picker_from_rgba(rgba(1.0f, 0.0f, 0.0f, 1.0f));
- layer->selection = 0;
+ layer->selection = -1;
return layer;
}
for (size_t i = 0; i < n; ++i) {
if (layer->selection == (int) i) {
- if (active && camera_fill_rect(
- camera,
- // TODO: thiccness of RectLayer selection should be probably based on zoom
- rect_scale(rects[i], RECT_LAYER_SELECTION_THICCNESS),
- color_invert(colors[i])) < 0) {
- return -1;
+ if (active) {
+ const Color color = color_invert(colors[i]);
+
+ if (camera_fill_rect(
+ camera,
+ // TODO(#943): thiccness of RectLayer selection should be probably based on zoom
+ rect_scale(rects[i], RECT_LAYER_SELECTION_THICCNESS),
+ color) < 0) {
+ return -1;
+ }
+
+ if (camera_fill_rect(
+ camera,
+ rect_layer_resize_anchor(layer, i),
+ color) < 0) {
+ return -1;
+ }
}
}
return -1;
}
- if (!selected) {
- const Color color = color_picker_rgba(&layer->color_picker);
- if (layer->state == RECT_LAYER_PROTO) {
- // Active
- switch (event->type) {
- case SDL_MOUSEBUTTONUP: {
- switch (event->button.button) {
- case SDL_BUTTON_LEFT: {
- const Rect real_rect =
- rect_from_points(
- layer->proto_begin,
- layer->proto_end);
- const float area = real_rect.w * real_rect.h;
-
- if (area >= PROTO_AREA_THRESHOLD) {
- rect_layer_add_rect(layer, real_rect, color);
- } else {
- log_info("The area is too small %f. Such small box won't be created.\n", area);
- }
- layer->state = RECT_LAYER_IDLE;
- } break;
- }
- } break;
+ if (selected) {
+ return 0;
+ }
- case SDL_MOUSEMOTION: {
- layer->proto_end = camera_map_screen(
- camera,
- event->motion.x,
- event->motion.y);
+ const Color color = color_picker_rgba(&layer->color_picker);
+ if (layer->state == RECT_LAYER_PROTO) {
+ switch (event->type) {
+ case SDL_MOUSEBUTTONUP: {
+ switch (event->button.button) {
+ case SDL_BUTTON_LEFT: {
+ const Rect real_rect =
+ rect_from_points(
+ layer->proto_begin,
+ layer->proto_end);
+ const float area = real_rect.w * real_rect.h;
+
+ if (area >= PROTO_AREA_THRESHOLD) {
+ rect_layer_add_rect(layer, real_rect, color);
+ } else {
+ log_info("The area is too small %f. Such small box won't be created.\n", area);
+ }
+ layer->state = RECT_LAYER_IDLE;
} break;
}
- } else {
- // Inactive
- switch (event->type) {
- case SDL_MOUSEBUTTONDOWN: {
- switch (event->button.button) {
- case SDL_BUTTON_LEFT: {
- Point position = camera_map_screen(
+ } break;
+
+ case SDL_MOUSEMOTION: {
+ layer->proto_end = camera_map_screen(
+ camera,
+ event->motion.x,
+ event->motion.y);
+ } break;
+ }
+ } else if (layer->state == RECT_LAYER_RESIZE) {
+ switch (event->type) {
+ case SDL_MOUSEMOTION: {
+ Rect *rects = dynarray_data(layer->rects);
+ trace_assert(layer->selection >= 0);
+ rects[layer->selection] = rect_from_points(
+ vec(rects[layer->selection].x, rects[layer->selection].y),
+ vec_sum(
+ camera_map_screen(
camera,
event->button.x,
- event->button.y);
-
+ event->button.y),
+ vec(RECT_LAYER_SELECTION_THICCNESS * -0.5f,
+ RECT_LAYER_SELECTION_THICCNESS * -0.5f)));
+ } break;
+
+ case SDL_MOUSEBUTTONUP: {
+ layer->state = RECT_LAYER_IDLE;
+ } break;
+ }
+ } else {
+ switch (event->type) {
+ case SDL_MOUSEBUTTONDOWN: {
+ switch (event->button.button) {
+ case SDL_BUTTON_LEFT: {
+ Point position = camera_map_screen(
+ camera,
+ event->button.x,
+ event->button.y);
+
+ if (layer->selection >= 0 &&
+ rect_contains_point(
+ rect_layer_resize_anchor(
+ layer,
+ (size_t)layer->selection),
+ position)) {
+ layer->state = RECT_LAYER_RESIZE;
+ } else {
layer->selection = rect_layer_rect_at(layer, position);
if (layer->selection < 0) {
layer->proto_begin = position;
layer->proto_end = position;
}
- } break;
}
} break;
}
+ } break;
+
+ case SDL_KEYDOWN: {
+ switch (event->key.keysym.sym) {
+ case SDLK_DELETE: {
+ if (layer->selection >= 0) {
+ rect_layer_delete_rect_at(layer, (size_t) layer->selection);
+ layer->selection = -1;
+ }
+ } break;
+ }
+ } break;
}
}
+
return 0;
}