]> git.lizzy.rs Git - nothing.git/blob - src/game/level/labels.c
(#553) Remove labels->enabled
[nothing.git] / src / game / level / labels.c
1 #include <assert.h>
2 #include <stdbool.h>
3
4 #include "game/camera.h"
5 #include "game/level/labels.h"
6 #include "str.h"
7 #include "system/line_stream.h"
8 #include "system/lt.h"
9 #include "system/nth_alloc.h"
10 #include "system/log.h"
11
12 #define LABEL_MAX_ID_SIZE 36
13
14 enum LabelState
15 {
16     LABEL_STATE_VIRGIN = 0,
17     LABEL_STATE_APPEARED,
18     LABEL_STATE_HIDDEN
19 };
20
21 struct Labels
22 {
23     Lt *lt;
24     size_t count;
25     char **ids;
26     Vec *positions;
27     Color *colors;
28     char **texts;
29     float *alphas;
30     float *delta_alphas;
31     enum LabelState *states;
32     int *visible;
33 };
34
35 Labels *create_labels_from_line_stream(LineStream *line_stream)
36 {
37     assert(line_stream);
38
39     Lt *const lt = create_lt();
40     if (lt == NULL) {
41         return NULL;
42     }
43
44     Labels * const labels = PUSH_LT(lt, nth_alloc(sizeof(Labels)), free);
45     if (labels == NULL) {
46         RETURN_LT(lt, NULL);
47     }
48     labels->lt = lt;
49
50     if (sscanf(
51             line_stream_next(line_stream),
52             "%lu",
53             &labels->count) == EOF) {
54         log_fail("Could not read amount of labels\n");
55         RETURN_LT(lt, NULL);
56     }
57
58     labels->ids = PUSH_LT(lt, nth_alloc(sizeof(char*) * labels->count), free);
59     if (labels->ids == NULL) {
60         RETURN_LT(lt, NULL);
61     }
62
63     labels->positions = PUSH_LT(lt, nth_alloc(sizeof(Vec) * labels->count), free);
64     if (labels->positions == NULL) {
65         RETURN_LT(lt, NULL);
66     }
67
68     labels->colors = PUSH_LT(lt, nth_alloc(sizeof(Color) * labels->count), free);
69     if (labels->colors == NULL) {
70         RETURN_LT(lt, NULL);
71     }
72
73     labels->texts = PUSH_LT(lt, nth_alloc(sizeof(char*) * labels->count), free);
74     if (labels->texts == NULL) {
75         RETURN_LT(lt, NULL);
76     }
77
78     labels->alphas = PUSH_LT(lt, nth_alloc(sizeof(float) * labels->count), free);
79     if (labels->alphas == NULL) {
80         RETURN_LT(lt, NULL);
81     }
82
83     labels->delta_alphas = PUSH_LT(lt, nth_alloc(sizeof(float) * labels->count), free);
84     if (labels->delta_alphas == NULL) {
85         RETURN_LT(lt, NULL);
86     }
87
88     labels->states = PUSH_LT(lt, nth_alloc(sizeof(enum LabelState) * labels->count), free);
89     if (labels->states == NULL) {
90         RETURN_LT(lt, NULL);
91     }
92
93     labels->visible = PUSH_LT(lt, nth_alloc(sizeof(int) * labels->count), free);
94     if (labels->visible == NULL) {
95         RETURN_LT(lt, NULL);
96     }
97
98     char color[7];
99     for (size_t i = 0; i < labels->count; ++i) {
100         labels->alphas[i] = 0.0f;
101         labels->delta_alphas[i] = 0.0f;
102         labels->states[i] = LABEL_STATE_VIRGIN;
103         labels->visible[i] = 0;
104         labels->texts[i] = NULL;
105
106         labels->ids[i] = PUSH_LT(lt, nth_alloc(sizeof(char) * LABEL_MAX_ID_SIZE), free);
107         if (labels->ids[i] == NULL) {
108             RETURN_LT(lt, NULL);
109         }
110
111         if (sscanf(
112                 line_stream_next(line_stream),
113                 "%" STRINGIFY(LABEL_MAX_ID_SIZE) "s%f%f%6s\n",
114                 labels->ids[i],
115                 &labels->positions[i].x,
116                 &labels->positions[i].y,
117                 color) == EOF) {
118             log_fail("Could not read position and color of %dth label\n", i);
119             RETURN_LT(lt, NULL);
120         }
121
122         labels->colors[i] = hexstr(color);
123
124         const char *label_text = line_stream_next(line_stream);
125         if (label_text == NULL) {
126             log_fail("Could not read text of %dth label\n", i);
127             RETURN_LT(lt, NULL);
128         }
129
130         labels->texts[i] = PUSH_LT(
131             lt,
132             string_duplicate(label_text, NULL),
133             free);
134         if (labels->texts[i] == NULL) {
135             RETURN_LT(lt, NULL);
136         }
137
138         trim_endline(labels->texts[i]);
139     }
140
141     return labels;
142 }
143
144 void destroy_labels(Labels *label)
145 {
146     assert(label);
147     RETURN_LT0(label->lt);
148 }
149
150 int labels_render(const Labels *label,
151                  Camera *camera)
152 {
153     assert(label);
154     assert(camera);
155
156     for (size_t i = 0; i < label->count; ++i) {
157         if (label->visible[i]) {
158             /* Easing */
159             const float state = label->alphas[i] * (2 - label->alphas[i]);
160
161             if (camera_render_text(camera,
162                                    label->texts[i],
163                                    vec(2.0f, 2.0f),
164                                    rgba(label->colors[i].r,
165                                         label->colors[i].g,
166                                         label->colors[i].b,
167                                         state),
168                                    vec_sum(label->positions[i],
169                                            vec(0.0f, -8.0f * state))) < 0) {
170                 return -1;
171             }
172         }
173     }
174
175     return 0;
176 }
177
178 void labels_update(Labels *label,
179                    float delta_time)
180 {
181     assert(label);
182     (void) delta_time;
183
184     for (size_t i = 0; i < label->count; ++i) {
185         label->alphas[i] = label->alphas[i] + label->delta_alphas[i] * delta_time;
186
187         if (label->alphas[i] < 0.0f) {
188             label->alphas[i] = 0.0f;
189             label->delta_alphas[i] = 0.0f;
190         }
191
192         if (label->alphas[i] > 1.0f) {
193             label->alphas[i] = 1.0f;
194             label->delta_alphas[i] = 0.0f;
195         }
196     }
197 }
198
199 void labels_enter_camera_event(Labels *labels,
200                                const Camera *camera)
201 {
202     assert(labels);
203     assert(camera);
204
205     for (size_t i = 0; i < labels->count; ++i) {
206         const int became_visible = camera_is_text_visible(
207             camera,
208             vec(2.0f, 2.0f),
209             labels->positions[i],
210             labels->texts[i]);
211
212         if (labels->states[i] == LABEL_STATE_VIRGIN && !labels->visible[i] && became_visible) {
213             labels->states[i] = LABEL_STATE_APPEARED;
214             labels->alphas[i] = 0.0f;
215             labels->delta_alphas[i] = 1.0f;
216         }
217
218         /* TODO: can we replace labels->visible with labels->states? */
219         labels->visible[i] = became_visible;
220     }
221 }
222
223 void labels_hide(Labels *labels,
224                  const char *label_id)
225 {
226     assert(labels);
227     assert(label_id);
228
229     for (size_t i = 0; i < labels->count; ++i) {
230         if (strcmp(labels->ids[i], label_id) == 0 && labels->states[i] != LABEL_STATE_HIDDEN) {
231             labels->states[i] = LABEL_STATE_HIDDEN;
232             labels->alphas[i] = 1.0f;
233             labels->delta_alphas[i] = -1.0f;
234             return;
235         }
236     }
237 }