]> git.lizzy.rs Git - nothing.git/blob - src/game/level/labels.c
Delete LineStream from the existance
[nothing.git] / src / game / level / labels.c
1 #include <stdio.h>
2 #include <stdbool.h>
3
4 #include "config.h"
5 #include "game/camera.h"
6 #include "game/level/labels.h"
7 #include "game/level/level_editor/label_layer.h"
8 #include "system/log.h"
9 #include "system/lt.h"
10 #include "system/nth_alloc.h"
11 #include "system/stacktrace.h"
12 #include "system/str.h"
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     Vec2f *positions;
27     Color *colors;
28     char **texts;
29
30     /* Animation state */
31     float *alphas;
32     float *delta_alphas;
33     enum LabelState *states;
34 };
35
36 Labels *create_labels_from_label_layer(const LabelLayer *label_layer)
37 {
38     trace_assert(label_layer);
39
40     Lt *lt = create_lt();
41
42     Labels *labels = PUSH_LT(lt, nth_calloc(1, sizeof(Labels)), free);
43     if (labels == NULL) {
44         RETURN_LT(lt, NULL);
45     }
46     labels->lt = lt;
47
48     labels->count = label_layer_count(label_layer);
49
50     labels->ids = PUSH_LT(lt, nth_calloc(labels->count, sizeof(char) * ENTITY_MAX_ID_SIZE), free);
51     if (labels->ids == NULL) {
52         RETURN_LT(lt, NULL);
53     }
54     memcpy(labels->ids,
55            label_layer_ids(label_layer),
56            labels->count * sizeof(char) * ENTITY_MAX_ID_SIZE);
57
58     labels->positions = PUSH_LT(lt, nth_calloc(1, sizeof(Vec2f) * labels->count), free);
59     if (labels->positions == NULL) {
60         RETURN_LT(lt, NULL);
61     }
62     memcpy(labels->positions,
63            label_layer_positions(label_layer),
64            labels->count * sizeof(Vec2f));
65
66     labels->colors = PUSH_LT(lt, nth_calloc(1, sizeof(Color) * labels->count), free);
67     if (labels->colors == NULL) {
68         RETURN_LT(lt, NULL);
69     }
70     memcpy(labels->colors,
71            label_layer_colors(label_layer),
72            labels->count * sizeof(Color));
73
74     labels->texts = PUSH_LT(lt, nth_calloc(1, sizeof(char*) * labels->count), free);
75     if (labels->texts == NULL) {
76         RETURN_LT(lt, NULL);
77     }
78
79     char *texts = labels_layer_texts(label_layer);
80     for (size_t i = 0; i < labels->count; ++i) {
81         labels->texts[i] = PUSH_LT(
82             labels->lt,
83             string_duplicate(texts + i * LABEL_LAYER_TEXT_MAX_SIZE, NULL),
84             free);
85     }
86
87     labels->alphas = PUSH_LT(lt, nth_calloc(1, sizeof(float) * labels->count), free);
88     if (labels->alphas == NULL) {
89         RETURN_LT(lt, NULL);
90     }
91
92     labels->delta_alphas = PUSH_LT(lt, nth_calloc(1, sizeof(float) * labels->count), free);
93     if (labels->delta_alphas == NULL) {
94         RETURN_LT(lt, NULL);
95     }
96
97     labels->states = PUSH_LT(lt, nth_calloc(1, sizeof(enum LabelState) * labels->count), free);
98     if (labels->states == NULL) {
99         RETURN_LT(lt, NULL);
100     }
101
102     return labels;
103 }
104
105 void destroy_labels(Labels *label)
106 {
107     trace_assert(label);
108     RETURN_LT0(label->lt);
109 }
110
111 int labels_render(const Labels *label,
112                   const Camera *camera)
113 {
114     trace_assert(label);
115     trace_assert(camera);
116
117     for (size_t i = 0; i < label->count; ++i) {
118         /* Easing */
119         const float state = label->alphas[i] * (2 - label->alphas[i]);
120
121         if (camera_render_text(camera,
122                                label->texts[i],
123                                LABELS_SIZE,
124                                rgba(label->colors[i].r,
125                                     label->colors[i].g,
126                                     label->colors[i].b,
127                                     state),
128                                vec_sum(label->positions[i],
129                                        vec(0.0f, -8.0f * state))) < 0) {
130             return -1;
131         }
132     }
133
134     return 0;
135 }
136
137 void labels_update(Labels *label,
138                    float delta_time)
139 {
140     trace_assert(label);
141     (void) delta_time;
142
143     for (size_t i = 0; i < label->count; ++i) {
144         label->alphas[i] = label->alphas[i] + label->delta_alphas[i] * delta_time;
145
146         if (label->alphas[i] < 0.0f) {
147             label->alphas[i] = 0.0f;
148             label->delta_alphas[i] = 0.0f;
149         }
150
151         if (label->alphas[i] > 1.0f) {
152             label->alphas[i] = 1.0f;
153             label->delta_alphas[i] = 0.0f;
154         }
155     }
156 }
157
158 void labels_enter_camera_event(Labels *labels,
159                                const Camera *camera)
160 {
161     trace_assert(labels);
162     trace_assert(camera);
163
164     for (size_t i = 0; i < labels->count; ++i) {
165         const int became_visible = camera_is_text_visible(
166             camera,
167             vec(2.0f, 2.0f),
168             labels->positions[i],
169             labels->texts[i]);
170
171         if (labels->states[i] == LABEL_STATE_VIRGIN && became_visible) {
172             labels->states[i] = LABEL_STATE_APPEARED;
173             labels->alphas[i] = 0.0f;
174             labels->delta_alphas[i] = 1.0f;
175         }
176     }
177 }
178
179 void labels_hide(Labels *labels, char id[ENTITY_MAX_ID_SIZE])
180 {
181     trace_assert(labels);
182     trace_assert(id);
183
184     for (size_t i = 0; i < labels->count; ++i) {
185         if (strncmp(id, labels->ids + i * ENTITY_MAX_ID_SIZE, ENTITY_MAX_ID_SIZE) == 0) {
186             if (labels->states[i] != LABEL_STATE_HIDDEN) {
187                 labels->states[i] = LABEL_STATE_HIDDEN;
188                 labels->alphas[i] = 1.0f;
189                 labels->delta_alphas[i] = -3.0f;
190             }
191             return;
192         }
193     }
194 }