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
21 POINT_LAYER_NORMAL_STATE = 0,
22 POINT_LAYER_ID_EDITING_STATE
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_from_line_stream(LineStream *line_stream)
48 trace_assert(line_stream);
52 PointLayer *point_layer = PUSH_LT(lt, nth_calloc(1, sizeof(PointLayer)), free);
53 if (point_layer == NULL) {
58 point_layer->state = POINT_LAYER_NORMAL_STATE;
60 point_layer->points = PUSH_LT(lt, create_dynarray(sizeof(Point)), destroy_dynarray);
61 if (point_layer->points == NULL) {
65 point_layer->colors = PUSH_LT(lt, create_dynarray(sizeof(Color)), destroy_dynarray);
66 if (point_layer->colors == NULL) {
70 point_layer->ids = PUSH_LT(lt, create_dynarray(sizeof(char) * ID_MAX_SIZE), destroy_dynarray);
71 if (point_layer->ids == NULL) {
77 line_stream_next(line_stream),
80 log_fail("Could not read amount of points");
87 for (size_t i = 0; i < count; ++i) {
89 line_stream_next(line_stream),
90 "%"STRINGIFY(ID_MAX_SIZE)"s%f%f%6s",
91 id, &x, &y, color_name) < 0) {
92 log_fail("Could not read %dth goal\n", i);
95 const Color color = hexstr(color_name);
96 const Point point = vec(x, y);
98 dynarray_push(point_layer->colors, &color);
99 dynarray_push(point_layer->points, &point);
100 dynarray_push(point_layer->ids, id);
103 point_layer->edit_field = PUSH_LT(
107 rgba(0.0f, 0.0f, 0.0f, 1.0f)),
109 if (point_layer->edit_field == NULL) {
110 RETURN_LT(point_layer->lt, NULL);
113 point_layer->selected = -1;
115 point_layer->color_picker.color = rgba(1.0f, 0.0f, 0.0f, 1.0f);
120 void destroy_point_layer(PointLayer *point_layer)
122 trace_assert(point_layer);
123 RETURN_LT0(point_layer->lt);
126 int point_layer_render(const PointLayer *point_layer,
130 trace_assert(point_layer);
131 trace_assert(camera);
133 const int n = (int) dynarray_count(point_layer->points);
134 Point *points = dynarray_data(point_layer->points);
135 Color *colors = dynarray_data(point_layer->colors);
137 for (int i = 0; i < n; ++i) {
138 const Triangle t = triangle_mat3x3_product(
139 equilateral_triangle(),
141 trans_mat(points[i].x, points[i].y),
142 scale_mat(POINT_LAYER_ELEMENT_RADIUS)));
144 const Color color = color_scale(
146 rgba(1.0f, 1.0f, 1.0f, fa));
148 if (i == point_layer->selected) {
149 const Triangle t0 = triangle_mat3x3_product(
150 equilateral_triangle(),
152 trans_mat(points[i].x, points[i].y),
155 if (camera_fill_triangle(camera, t0, color_invert(color)) < 0) {
160 if (camera_fill_triangle(camera, t, color) < 0) {
164 /* TODO(#854): The ids of PointLayer are not displayed constantly */
167 if (point_layer->state == POINT_LAYER_ID_EDITING_STATE) {
168 /* TODO(#855): PointLayer edit field is not scaled on zoom */
169 if (edit_field_render(
170 point_layer->edit_field,
172 camera_point(camera, points[point_layer->selected])) < 0) {
177 if (color_picker_render(&point_layer->color_picker, camera) < 0) {
186 static int point_layer_mouse_button(PointLayer *point_layer,
187 const SDL_MouseButtonEvent *event,
188 const Camera *camera)
190 trace_assert(point_layer);
193 bool selected = false;
194 if (color_picker_mouse_button(
195 &point_layer->color_picker,
202 point_layer->state == POINT_LAYER_NORMAL_STATE &&
203 event->type == SDL_MOUSEBUTTONDOWN &&
204 event->button == SDL_BUTTON_LEFT) {
205 const int n = (int) dynarray_count(point_layer->points);
206 const Point *points = dynarray_data(point_layer->points);
207 const Point point = camera_map_screen(camera, event->x, event->y);
209 for (int i = 0; i < n; ++i) {
210 if (vec_length(vec_sub(points[i], point)) < POINT_LAYER_ELEMENT_RADIUS) {
211 point_layer->selected = i;
216 char id[ID_MAX_SIZE];
218 for (size_t i = 0; i < ID_MAX_SIZE - 1; ++i) {
219 id[i] = (char) ('a' + rand() % ('z' - 'a' + 1));
221 id[ID_MAX_SIZE - 1] = '\0';
223 dynarray_push(point_layer->points, &point);
224 dynarray_push(point_layer->colors, &point_layer->color_picker.color);
225 dynarray_push(point_layer->ids, id);
232 int point_layer_keyboard(PointLayer *point_layer,
233 const SDL_KeyboardEvent *key)
235 trace_assert(point_layer);
238 switch(point_layer->state) {
239 case POINT_LAYER_NORMAL_STATE: {
240 if (key->type == SDL_KEYDOWN) {
241 switch (key->keysym.sym) {
243 if (0 <= point_layer->selected && point_layer->selected < (int) dynarray_count(point_layer->points)) {
244 dynarray_delete_at(point_layer->points, (size_t) point_layer->selected);
245 dynarray_delete_at(point_layer->colors, (size_t) point_layer->selected);
246 dynarray_delete_at(point_layer->ids, (size_t) point_layer->selected);
248 point_layer->selected = -1;
252 if (point_layer->selected >= 0) {
253 char *ids = dynarray_data(point_layer->ids);
254 point_layer->state = POINT_LAYER_ID_EDITING_STATE;
256 point_layer->edit_field,
257 ids + ID_MAX_SIZE * point_layer->selected);
258 SDL_StartTextInput();
267 case POINT_LAYER_ID_EDITING_STATE: {
268 if (edit_field_keyboard(point_layer->edit_field, key) < 0) {
272 if (key->type == SDL_KEYDOWN) {
273 switch(key->keysym.sym) {
275 char *ids = dynarray_data(point_layer->ids);
276 const char *text = edit_field_as_text(point_layer->edit_field);
277 size_t n = max_size_t(strlen(text), ID_MAX_SIZE - 1);
278 memcpy(ids + point_layer->selected * ID_MAX_SIZE, text, n);
279 *(ids + point_layer->selected * ID_MAX_SIZE + n) = '\0';
280 point_layer->state = POINT_LAYER_NORMAL_STATE;
285 point_layer->state = POINT_LAYER_NORMAL_STATE;
298 int point_layer_text_input(PointLayer *point_layer,
299 const SDL_TextInputEvent *text_input)
301 trace_assert(point_layer);
302 trace_assert(text_input);
304 if (point_layer->state == POINT_LAYER_ID_EDITING_STATE) {
305 /* TODO(#856): Special development keybindings interfere with id editing field */
306 return edit_field_text_input(point_layer->edit_field, text_input);
312 int point_layer_event(PointLayer *point_layer,
313 const SDL_Event *event,
314 const Camera *camera)
316 trace_assert(point_layer);
318 trace_assert(camera);
320 switch(event->type) {
321 case SDL_MOUSEBUTTONDOWN:
322 case SDL_MOUSEBUTTONUP:
323 return point_layer_mouse_button(
330 return point_layer_keyboard(
335 return point_layer_text_input(
343 size_t point_layer_count(const PointLayer *point_layer)
345 trace_assert(point_layer);
346 return dynarray_count(point_layer->points);
349 const Point *point_layer_points(const PointLayer *point_layer)
351 trace_assert(point_layer);
352 return dynarray_data(point_layer->points);
355 const Color *point_layer_colors(const PointLayer *point_layer)
357 trace_assert(point_layer);
358 return dynarray_data(point_layer->colors);
361 const char *point_layer_ids(const PointLayer *point_layer)
363 trace_assert(point_layer);
364 return dynarray_data(point_layer->ids);