1 #include "system/stacktrace.h"
4 #include "game/camera.h"
5 #include "game/level/labels.h"
6 #include "system/str.h"
7 #include "system/line_stream.h"
9 #include "system/nth_alloc.h"
10 #include "system/log.h"
11 #include "ebisp/interpreter.h"
12 #include "broadcast.h"
14 #define LABEL_MAX_ID_SIZE 36
18 LABEL_STATE_VIRGIN = 0,
33 enum LabelState *states;
36 Labels *create_labels_from_line_stream(LineStream *line_stream)
38 trace_assert(line_stream);
40 Lt *const lt = create_lt();
45 Labels * const labels = PUSH_LT(lt, nth_calloc(1, sizeof(Labels)), free);
52 line_stream_next(line_stream),
54 &labels->count) == EOF) {
55 log_fail("Could not read amount of labels\n");
59 labels->ids = PUSH_LT(lt, nth_calloc(1, sizeof(char*) * labels->count), free);
60 if (labels->ids == NULL) {
64 labels->positions = PUSH_LT(lt, nth_calloc(1, sizeof(Vec) * labels->count), free);
65 if (labels->positions == NULL) {
69 labels->colors = PUSH_LT(lt, nth_calloc(1, sizeof(Color) * labels->count), free);
70 if (labels->colors == NULL) {
74 labels->texts = PUSH_LT(lt, nth_calloc(1, sizeof(char*) * labels->count), free);
75 if (labels->texts == NULL) {
79 labels->alphas = PUSH_LT(lt, nth_calloc(1, sizeof(float) * labels->count), free);
80 if (labels->alphas == NULL) {
84 labels->delta_alphas = PUSH_LT(lt, nth_calloc(1, sizeof(float) * labels->count), free);
85 if (labels->delta_alphas == NULL) {
89 labels->states = PUSH_LT(lt, nth_calloc(1, sizeof(enum LabelState) * labels->count), free);
90 if (labels->states == NULL) {
95 for (size_t i = 0; i < labels->count; ++i) {
96 labels->alphas[i] = 0.0f;
97 labels->delta_alphas[i] = 0.0f;
98 labels->states[i] = LABEL_STATE_VIRGIN;
99 labels->texts[i] = NULL;
101 labels->ids[i] = PUSH_LT(lt, nth_calloc(1, sizeof(char) * LABEL_MAX_ID_SIZE), free);
102 if (labels->ids[i] == NULL) {
107 line_stream_next(line_stream),
108 "%" STRINGIFY(LABEL_MAX_ID_SIZE) "s%f%f%6s\n",
110 &labels->positions[i].x,
111 &labels->positions[i].y,
113 log_fail("Could not read position and color of %dth label\n", i);
117 labels->colors[i] = hexstr(color);
119 const char *label_text = line_stream_next(line_stream);
120 if (label_text == NULL) {
121 log_fail("Could not read text of %dth label\n", i);
125 labels->texts[i] = PUSH_LT(
127 string_duplicate(label_text, NULL),
129 if (labels->texts[i] == NULL) {
133 trim_endline(labels->texts[i]);
139 void destroy_labels(Labels *label)
142 RETURN_LT0(label->lt);
145 int labels_render(const Labels *label,
149 trace_assert(camera);
151 for (size_t i = 0; i < label->count; ++i) {
153 const float state = label->alphas[i] * (2 - label->alphas[i]);
155 if (camera_render_text(camera,
158 rgba(label->colors[i].r,
162 vec_sum(label->positions[i],
163 vec(0.0f, -8.0f * state))) < 0) {
171 void labels_update(Labels *label,
177 for (size_t i = 0; i < label->count; ++i) {
178 label->alphas[i] = label->alphas[i] + label->delta_alphas[i] * delta_time;
180 if (label->alphas[i] < 0.0f) {
181 label->alphas[i] = 0.0f;
182 label->delta_alphas[i] = 0.0f;
185 if (label->alphas[i] > 1.0f) {
186 label->alphas[i] = 1.0f;
187 label->delta_alphas[i] = 0.0f;
192 void labels_enter_camera_event(Labels *labels,
193 const Camera *camera)
195 trace_assert(labels);
196 trace_assert(camera);
198 for (size_t i = 0; i < labels->count; ++i) {
199 const int became_visible = camera_is_text_visible(
202 labels->positions[i],
205 if (labels->states[i] == LABEL_STATE_VIRGIN && became_visible) {
206 labels->states[i] = LABEL_STATE_APPEARED;
207 labels->alphas[i] = 0.0f;
208 labels->delta_alphas[i] = 1.0f;
213 static struct EvalResult
214 labels_action(Labels *labels,
220 trace_assert(labels);
224 const char *target = NULL;
225 struct Expr rest = void_expr();
226 struct EvalResult res = match_list(gc, "q*", path, &target, &rest);
231 if (strcmp(target, "hide") == 0) {
232 if (labels->states[index] != LABEL_STATE_HIDDEN) {
233 labels->states[index] = LABEL_STATE_HIDDEN;
234 labels->alphas[index] = 1.0f;
235 labels->delta_alphas[index] = -3.0f;
237 return eval_success(NIL(gc));
240 return unknown_target(gc, labels->ids[index], target);
244 labels_send(Labels *labels, Gc *gc, struct Scope *scope, struct Expr path)
246 trace_assert(labels);
250 const char *target = NULL;
251 struct Expr rest = void_expr();
252 struct EvalResult res = match_list(gc, "s*", path, &target, &rest);
257 for (size_t i = 0; i < labels->count; ++i) {
258 if (strcmp(target, labels->ids[i]) == 0) {
259 return labels_action(labels, i, gc, scope, rest);
263 return unknown_target(gc, "label", target);