6 #include "game/camera.h"
7 #include "system/line_stream.h"
8 #include "system/log.h"
10 #include "system/nth_alloc.h"
11 #include "system/stacktrace.h"
12 #include "system/str.h"
13 #include "ui/edit_field.h"
14 #include "./point_layer.h"
15 #include "math/extrema.h"
16 #include "./color_picker.h"
18 #define POINT_LAYER_ELEMENT_RADIUS 10.0f
28 PointLayerState state;
29 Dynarray/*<Point>*/ *points;
30 Dynarray/*<Color>*/ *colors;
31 Dynarray/*<char[ID_MAX_SIZE]>*/ *ids;
32 Edit_field *edit_field;
34 ColorPicker color_picker;
37 LayerPtr point_layer_as_layer(PointLayer *point_layer)
46 PointLayer *create_point_layer(void)
50 PointLayer *point_layer = PUSH_LT(lt, nth_calloc(1, sizeof(PointLayer)), free);
51 if (point_layer == NULL) {
56 point_layer->state = POINT_LAYER_IDLE;
58 point_layer->points = PUSH_LT(lt, create_dynarray(sizeof(Point)), destroy_dynarray);
59 if (point_layer->points == NULL) {
63 point_layer->colors = PUSH_LT(lt, create_dynarray(sizeof(Color)), destroy_dynarray);
64 if (point_layer->colors == NULL) {
68 point_layer->ids = PUSH_LT(lt, create_dynarray(sizeof(char) * ID_MAX_SIZE), destroy_dynarray);
69 if (point_layer->ids == NULL) {
73 point_layer->edit_field = PUSH_LT(
77 rgba(0.0f, 0.0f, 0.0f, 1.0f)),
79 if (point_layer->edit_field == NULL) {
86 PointLayer *create_point_layer_from_line_stream(LineStream *line_stream)
88 trace_assert(line_stream);
90 PointLayer *point_layer = create_point_layer();
94 line_stream_next(line_stream),
97 log_fail("Could not read amount of points");
98 RETURN_LT(point_layer->lt, NULL);
102 char id[ID_MAX_SIZE];
104 for (size_t i = 0; i < count; ++i) {
106 line_stream_next(line_stream),
107 "%"STRINGIFY(ID_MAX_SIZE)"s%f%f%6s",
108 id, &x, &y, color_name) < 0) {
109 log_fail("Could not read %dth goal\n", i);
110 RETURN_LT(point_layer->lt, NULL);
112 const Color color = hexstr(color_name);
113 const Point point = vec(x, y);
115 dynarray_push(point_layer->colors, &color);
116 dynarray_push(point_layer->points, &point);
117 dynarray_push(point_layer->ids, id);
120 point_layer->selected = -1;
122 point_layer->color_picker = create_color_picker_from_rgba(rgba(1.0f, 0.0f, 0.0f, 1.0f));
127 void destroy_point_layer(PointLayer *point_layer)
129 trace_assert(point_layer);
130 RETURN_LT0(point_layer->lt);
133 int point_layer_render(const PointLayer *point_layer,
137 trace_assert(point_layer);
138 trace_assert(camera);
140 const int n = (int) dynarray_count(point_layer->points);
141 Point *points = dynarray_data(point_layer->points);
142 Color *colors = dynarray_data(point_layer->colors);
144 for (int i = 0; i < n; ++i) {
145 const Triangle t = triangle_mat3x3_product(
146 equilateral_triangle(),
148 trans_mat(points[i].x, points[i].y),
149 scale_mat(POINT_LAYER_ELEMENT_RADIUS)));
151 const Color color = color_scale(
153 rgba(1.0f, 1.0f, 1.0f, active ? 1.0f : 0.5f));
155 if (i == point_layer->selected) {
156 const Triangle t0 = triangle_mat3x3_product(
157 equilateral_triangle(),
159 trans_mat(points[i].x, points[i].y),
162 if (camera_fill_triangle(camera, t0, color_invert(color)) < 0) {
167 if (camera_fill_triangle(camera, t, color) < 0) {
171 /* TODO(#854): The ids of PointLayer are not displayed constantly */
174 if (point_layer->state == POINT_LAYER_EDIT_ID) {
175 /* TODO(#855): PointLayer edit field is not scaled on zoom */
176 if (edit_field_render_screen(
177 point_layer->edit_field,
179 camera_point(camera, points[point_layer->selected])) < 0) {
184 if (active && color_picker_render(&point_layer->color_picker, camera) < 0) {
193 int point_layer_idle_event(PointLayer *point_layer,
194 const SDL_Event *event,
195 const Camera *camera)
197 trace_assert(point_layer);
199 trace_assert(camera);
202 if (color_picker_event(
203 &point_layer->color_picker,
213 switch (event->type) {
214 case SDL_MOUSEBUTTONDOWN: {
215 switch (event->button.button) {
216 case SDL_BUTTON_LEFT: {
217 const int n = (int) dynarray_count(point_layer->points);
218 const Point *points = dynarray_data(point_layer->points);
219 const Point point = camera_map_screen(camera, event->button.x, event->button.y);
220 const Color color = color_picker_rgba(&point_layer->color_picker);
222 for (int i = 0; i < n; ++i) {
223 if (vec_length(vec_sub(points[i], point)) < POINT_LAYER_ELEMENT_RADIUS) {
224 point_layer->selected = i;
229 char id[ID_MAX_SIZE];
231 for (size_t i = 0; i < ID_MAX_SIZE - 1; ++i) {
232 id[i] = (char) ('a' + rand() % ('z' - 'a' + 1));
234 id[ID_MAX_SIZE - 1] = '\0';
236 dynarray_push(point_layer->points, &point);
237 dynarray_push(point_layer->colors, &color);
238 dynarray_push(point_layer->ids, id);
244 switch (event->key.keysym.sym) {
246 if (0 <= point_layer->selected && point_layer->selected < (int) dynarray_count(point_layer->points)) {
247 dynarray_delete_at(point_layer->points, (size_t) point_layer->selected);
248 dynarray_delete_at(point_layer->colors, (size_t) point_layer->selected);
249 dynarray_delete_at(point_layer->ids, (size_t) point_layer->selected);
251 point_layer->selected = -1;
255 if (point_layer->selected >= 0) {
256 char *ids = dynarray_data(point_layer->ids);
257 point_layer->state = POINT_LAYER_EDIT_ID;
259 point_layer->edit_field,
260 ids + ID_MAX_SIZE * point_layer->selected);
261 SDL_StartTextInput();
272 int point_layer_edit_id_event(PointLayer *point_layer,
273 const SDL_Event *event,
274 const Camera *camera)
276 trace_assert(point_layer);
278 trace_assert(camera);
280 switch (event->type) {
282 switch(event->key.keysym.sym) {
284 char *ids = dynarray_data(point_layer->ids);
285 const char *text = edit_field_as_text(point_layer->edit_field);
286 size_t n = max_size_t(strlen(text), ID_MAX_SIZE - 1);
287 memcpy(ids + point_layer->selected * ID_MAX_SIZE, text, n);
288 *(ids + point_layer->selected * ID_MAX_SIZE + n) = '\0';
289 point_layer->state = POINT_LAYER_IDLE;
295 point_layer->state = POINT_LAYER_IDLE;
303 return edit_field_event(point_layer->edit_field, event);
306 int point_layer_event(PointLayer *point_layer,
307 const SDL_Event *event,
308 const Camera *camera)
310 trace_assert(point_layer);
312 trace_assert(camera);
314 switch (point_layer->state) {
315 case POINT_LAYER_IDLE:
316 return point_layer_idle_event(point_layer, event, camera);
318 case POINT_LAYER_EDIT_ID:
319 return point_layer_edit_id_event(point_layer, event, camera);
325 size_t point_layer_count(const PointLayer *point_layer)
327 trace_assert(point_layer);
328 return dynarray_count(point_layer->points);
331 const Point *point_layer_points(const PointLayer *point_layer)
333 trace_assert(point_layer);
334 return dynarray_data(point_layer->points);
337 const Color *point_layer_colors(const PointLayer *point_layer)
339 trace_assert(point_layer);
340 return dynarray_data(point_layer->colors);
343 const char *point_layer_ids(const PointLayer *point_layer)
345 trace_assert(point_layer);
346 return dynarray_data(point_layer->ids);
349 int point_layer_dump_stream(const PointLayer *point_layer,
352 trace_assert(point_layer);
353 trace_assert(filedump);
355 size_t n = dynarray_count(point_layer->ids);
356 char *ids = dynarray_data(point_layer->ids);
357 Point *points = dynarray_data(point_layer->points);
358 Color *colors = dynarray_data(point_layer->colors);
360 fprintf(filedump, "%zd\n", n);
361 for (size_t i = 0; i < n; ++i) {
362 fprintf(filedump, "%s %f %f ",
363 ids + ID_MAX_SIZE * i,
364 points[i].x, points[i].y);
365 color_hex_to_stream(colors[i], filedump);
366 fprintf(filedump, "\n");