1 #include "game/camera.h"
3 #include "system/stacktrace.h"
4 #include "system/nth_alloc.h"
5 #include "system/log.h"
8 #include "rect_layer.h"
10 #include "system/line_stream.h"
11 #include "color_picker.h"
12 #include "system/str.h"
14 #define RECT_LAYER_ID_MAX_SIZE 36
15 #define PROTO_AREA_THRESHOLD 10.0
22 /* TODO(#886): RectLayer does not allow to modify ids of Rects */
29 ColorPicker color_picker;
33 LayerPtr rect_layer_as_layer(RectLayer *rect_layer)
42 RectLayer *create_rect_layer(void)
46 RectLayer *layer = PUSH_LT(lt, nth_calloc(1, sizeof(RectLayer)), free);
54 create_dynarray(sizeof(char) * RECT_LAYER_ID_MAX_SIZE),
56 if (layer->ids == NULL) {
60 layer->rects = PUSH_LT(
62 create_dynarray(sizeof(Rect)),
64 if (layer->rects == NULL) {
68 layer->colors = PUSH_LT(
70 create_dynarray(sizeof(Color)),
72 if (layer->colors == NULL) {
76 layer->color_picker = create_color_picker_from_rgba(rgba(1.0f, 0.0f, 0.0f, 1.0f));
81 RectLayer *create_rect_layer_from_line_stream(LineStream *line_stream)
83 trace_assert(line_stream);
85 RectLayer *layer = create_rect_layer();
90 const char *line = line_stream_next(line_stream);
92 RETURN_LT(layer->lt, NULL);
96 if (sscanf(line, "%zu", &count) < 0) {
97 RETURN_LT(layer->lt, NULL);
100 for (size_t i = 0; i < count; ++i) {
101 line = line_stream_next(line_stream);
103 RETURN_LT(layer->lt, NULL);
108 char id[RECT_LAYER_ID_MAX_SIZE];
111 "%"STRINGIFY(RECT_LAYER_ID_MAX_SIZE)"s%f%f%f%f%6s\n",
116 RETURN_LT(layer->lt, NULL);
119 Color color = hexstr(hex);
121 dynarray_push(layer->rects, &rect);
122 dynarray_push(layer->ids, id);
123 dynarray_push(layer->colors, &color);
129 void destroy_rect_layer(RectLayer *layer)
132 RETURN_LT0(layer->lt);
135 int rect_layer_render(const RectLayer *layer, Camera *camera, int active)
138 trace_assert(camera);
140 const size_t n = dynarray_count(layer->rects);
141 Rect *rects = dynarray_data(layer->rects);
142 Color *colors = dynarray_data(layer->colors);
144 for (size_t i = 0; i < n; ++i) {
145 if (camera_fill_rect(
150 rgba(1.0f, 1.0f, 1.0f, active ? 1.0f : 0.5f))) < 0) {
155 const Color color = color_picker_rgba(&layer->color_picker);
156 if (layer->state == RECT_LAYER_PROTO) {
157 if (camera_fill_rect(camera, rect_from_points(layer->begin, layer->end), color) < 0) {
162 if (active && color_picker_render(&layer->color_picker, camera) < 0) {
169 int rect_layer_event(RectLayer *layer, const SDL_Event *event, const Camera *camera)
175 if (color_picker_event(&layer->color_picker, event, &selected) < 0) {
180 const Color color = color_picker_rgba(&layer->color_picker);
181 if (layer->state == RECT_LAYER_PROTO) {
183 switch (event->type) {
184 case SDL_MOUSEBUTTONUP: {
185 switch (event->button.button) {
186 case SDL_BUTTON_LEFT: {
187 const Rect real_rect =
191 const float area = real_rect.w * real_rect.h;
193 if (area >= PROTO_AREA_THRESHOLD) {
194 rect_layer_add_rect(layer, real_rect, color);
196 log_info("The area is too small %f. Such small box won't be created.\n", area);
198 layer->state = RECT_LAYER_IDLE;
203 case SDL_MOUSEMOTION: {
204 layer->end = camera_map_screen(
212 switch (event->type) {
213 case SDL_MOUSEBUTTONDOWN: {
214 switch (event->button.button) {
215 case SDL_BUTTON_LEFT: {
216 layer->state = RECT_LAYER_PROTO;
217 layer->begin = camera_map_screen(
221 layer->end = layer->begin;
232 int rect_layer_add_rect(RectLayer *layer, Rect rect, Color color)
236 if (dynarray_push(layer->rects, &rect) < 0) {
240 if (dynarray_push(layer->colors, &color) < 0) {
244 char id[RECT_LAYER_ID_MAX_SIZE];
245 for (size_t i = 0; i < RECT_LAYER_ID_MAX_SIZE - 1; ++i) {
246 id[i] = (char) ('a' + rand() % ('z' - 'a' + 1));
248 id[RECT_LAYER_ID_MAX_SIZE - 1] = '\0';
250 if (dynarray_push(layer->ids, id)) {
257 int rect_layer_delete_rect_at(RectLayer *layer, Vec position)
261 const size_t n = dynarray_count(layer->rects);
262 Rect *rects = dynarray_data(layer->rects);
264 for (size_t i = 0; i < n; ++i) {
265 if (rect_contains_point(rects[i], position)) {
266 dynarray_delete_at(layer->rects, i);
267 dynarray_delete_at(layer->colors, i);
275 size_t rect_layer_count(const RectLayer *layer)
277 return dynarray_count(layer->rects);
280 const Rect *rect_layer_rects(const RectLayer *layer)
282 return dynarray_data(layer->rects);
285 const Color *rect_layer_colors(const RectLayer *layer)
287 return dynarray_data(layer->colors);
290 const char *rect_layer_ids(const RectLayer *layer)
292 return dynarray_data(layer->ids);
295 int rect_layer_dump_stream(const RectLayer *layer, FILE *filedump)
298 trace_assert(filedump);
300 size_t n = dynarray_count(layer->ids);
301 char *ids = dynarray_data(layer->ids);
302 Rect *rects = dynarray_data(layer->rects);
303 Color *colors = dynarray_data(layer->colors);
305 fprintf(filedump, "%zd\n", n);
306 for (size_t i = 0; i < n; ++i) {
307 fprintf(filedump, "%s %f %f %f %f ",
308 ids + RECT_LAYER_ID_MAX_SIZE * i,
309 rects[i].x, rects[i].y, rects[i].w, rects[i].h);
310 color_hex_to_stream(colors[i], filedump);
311 fprintf(filedump, "\n");