]> git.lizzy.rs Git - nothing.git/blob - src/game/level/level_editor/label_layer.c
Merge pull request #902 from tsoding/893
[nothing.git] / src / game / level / level_editor / label_layer.c
1 #include <stdio.h>
2
3 #include <SDL.h>
4
5 #include "system/line_stream.h"
6 #include "system/stacktrace.h"
7 #include "system/nth_alloc.h"
8 #include "system/lt.h"
9 #include "system/str.h"
10 #include "system/log.h"
11 #include "math/point.h"
12 #include "label_layer.h"
13 #include "dynarray.h"
14 #include "color.h"
15 #include "game/camera.h"
16
17 #define LABEL_LAYER_ID_MAX_SIZE 36
18
19 struct LabelLayer {
20     Lt *lt;
21     Dynarray *ids;
22     Dynarray *positions;
23     Dynarray *colors;
24     Dynarray *texts;
25 };
26
27 LayerPtr label_layer_as_layer(LabelLayer *label_layer)
28 {
29     LayerPtr layer = {
30         .ptr = label_layer,
31         .type = LAYER_LABEL
32     };
33     return layer;
34 }
35
36 LabelLayer *create_label_layer(void)
37 {
38     Lt *lt = create_lt();
39
40     LabelLayer *label_layer = PUSH_LT(
41         lt, nth_calloc(1, sizeof(LabelLayer)), free);
42     if (label_layer == NULL) {
43         RETURN_LT(lt, NULL);
44     }
45     label_layer->lt = lt;
46
47     label_layer->ids = PUSH_LT(
48         lt,
49         create_dynarray(sizeof(char) * LABEL_LAYER_ID_MAX_SIZE),
50         destroy_dynarray);
51     if (label_layer->ids == NULL) {
52         RETURN_LT(lt, NULL);
53     }
54
55     label_layer->positions = PUSH_LT(lt, create_dynarray(sizeof(Point)), destroy_dynarray);
56     if (label_layer->positions == NULL) {
57         RETURN_LT(lt, NULL);
58     }
59
60     label_layer->colors = PUSH_LT(lt, create_dynarray(sizeof(Color)), destroy_dynarray);
61     if (label_layer->colors == NULL) {
62         RETURN_LT(lt, NULL);
63     }
64
65     label_layer->texts = PUSH_LT(lt, create_dynarray(sizeof(char*)), destroy_dynarray);
66     if (label_layer->texts == NULL) {
67         RETURN_LT(lt, NULL);
68     }
69
70     return label_layer;
71 }
72
73 LabelLayer *create_label_layer_from_line_stream(LineStream *line_stream)
74 {
75     trace_assert(line_stream);
76     LabelLayer *label_layer = create_label_layer();
77
78     if (label_layer == NULL) {
79         RETURN_LT(label_layer->lt, NULL);
80     }
81
82     const char *line = line_stream_next(line_stream);
83     if (line == NULL) {
84         log_fail("Could not read amount of labels\n");
85         RETURN_LT(label_layer->lt, NULL);
86     }
87
88     size_t n = 0;
89     if (sscanf(line, "%lu", &n) == EOF) {
90         log_fail("Could not parse amount of labels\n");
91         RETURN_LT(label_layer->lt, NULL);
92     }
93
94     for (size_t i = 0; i < n; ++i) {
95         char hex[7];
96         char id[LABEL_LAYER_ID_MAX_SIZE];
97         Point position;
98
99         line = line_stream_next(line_stream);
100         if (line == NULL) {
101             log_fail("Could not read label meta info\n");
102             RETURN_LT(label_layer->lt, NULL);
103         }
104
105         if (sscanf(
106                 line,
107                 "%"STRINGIFY(LABEL_LAYER_ID_MAX_SIZE)"s%f%f%6s\n",
108                 id, &position.x, &position.y, hex) == EOF) {
109             log_fail("Could not parse label meta info\n");
110             RETURN_LT(label_layer->lt, NULL);
111         }
112
113         Color color = hexstr(hex);
114
115         dynarray_push(label_layer->ids, id);
116         dynarray_push(label_layer->positions, &position);
117         dynarray_push(label_layer->colors, &color);
118
119         line = line_stream_next(line_stream);
120         if (line == NULL) {
121             log_fail("Could not read label text\n");
122         }
123
124         char *label_text = PUSH_LT(label_layer->lt, string_duplicate(line, NULL), free);
125         trim_endline(label_text);
126         dynarray_push(label_layer->texts, &label_text);
127     }
128
129     return label_layer;
130 }
131
132 void destroy_label_layer(LabelLayer *label_layer)
133 {
134     trace_assert(label_layer);
135     destroy_lt(label_layer->lt);
136 }
137
138 int label_layer_render(const LabelLayer *label_layer,
139                        Camera *camera,
140                        float fa)
141 {
142     trace_assert(label_layer);
143     trace_assert(camera);
144
145     size_t n = dynarray_count(label_layer->ids);
146     Point *positions = dynarray_data(label_layer->positions);
147     Color *colors = dynarray_data(label_layer->colors);
148     char **texts = dynarray_data(label_layer->texts);
149
150     /* TODO(#891): LabelLayer doesn't show the final position of Label after the animation */
151     for (size_t i = 0; i < n; ++i) {
152         if (camera_render_text(
153                 camera,
154                 texts[i],
155                 vec(2.0f, 2.0f),
156                 color_scale(
157                     colors[i],
158                     rgba(1.0f, 1.0f, 1.0f, fa)),
159                 positions[i]) < 0) {
160             return -1;
161         }
162     }
163
164     return 0;
165 }
166
167 int label_layer_event(LabelLayer *label_layer,
168                       const SDL_Event *event,
169                       const Camera *camera)
170 {
171     trace_assert(label_layer);
172     trace_assert(event);
173     trace_assert(camera);
174     /* TODO(#892): LabelLayer doesn't allow to modify and add labels */
175     return 0;
176 }
177
178 size_t label_layer_count(const LabelLayer *label_layer)
179 {
180     return dynarray_count(label_layer->ids);
181 }
182
183 char *label_layer_ids(const LabelLayer *label_layer)
184 {
185     return dynarray_data(label_layer->ids);
186 }
187
188 Point *label_layer_positions(const LabelLayer *label_layer)
189 {
190     return dynarray_data(label_layer->positions);
191 }
192
193 Color *label_layer_colors(const LabelLayer *label_layer)
194 {
195     return dynarray_data(label_layer->colors);
196 }
197
198 char **labels_layer_texts(const LabelLayer *label_layer)
199 {
200     return dynarray_data(label_layer->texts);
201 }
202
203 int label_layer_dump_stream(const LabelLayer *label_layer, FILE *filedump)
204 {
205     trace_assert(label_layer);
206     trace_assert(filedump);
207
208     size_t n = dynarray_count(label_layer->ids);
209     char *ids = dynarray_data(label_layer->ids);
210     Point *positions = dynarray_data(label_layer->positions);
211     Color *colors = dynarray_data(label_layer->colors);
212     char **texts = dynarray_data(label_layer->texts);
213
214     fprintf(filedump, "%ld\n", n);
215     for (size_t i = 0; i < n; ++i) {
216         fprintf(filedump, "%s %f %f ",
217                 ids + LABEL_LAYER_ID_MAX_SIZE * i,
218                 positions[i].x, positions[i].y);
219         color_hex_to_stream(colors[i], filedump);
220         fprintf(filedump, "\n%s\n", texts[i]);
221     }
222
223     return 0;
224 }