5 #include "ebisp/interpreter.h"
6 #include "game/camera.h"
7 #include "game/level/labels.h"
8 #include "system/line_stream.h"
9 #include "system/log.h"
10 #include "system/lt.h"
11 #include "system/nth_alloc.h"
12 #include "system/stacktrace.h"
13 #include "system/str.h"
15 #define LABEL_MAX_ID_SIZE 36
19 LABEL_STATE_VIRGIN = 0,
34 enum LabelState *states;
37 Labels *create_labels_from_line_stream(LineStream *line_stream)
39 trace_assert(line_stream);
43 Labels * const labels = PUSH_LT(lt, nth_calloc(1, sizeof(Labels)), free);
50 line_stream_next(line_stream),
52 &labels->count) == EOF) {
53 log_fail("Could not read amount of labels\n");
57 labels->ids = PUSH_LT(lt, nth_calloc(1, sizeof(char*) * labels->count), free);
58 if (labels->ids == NULL) {
62 labels->positions = PUSH_LT(lt, nth_calloc(1, sizeof(Vec) * labels->count), free);
63 if (labels->positions == NULL) {
67 labels->colors = PUSH_LT(lt, nth_calloc(1, sizeof(Color) * labels->count), free);
68 if (labels->colors == NULL) {
72 labels->texts = PUSH_LT(lt, nth_calloc(1, sizeof(char*) * labels->count), free);
73 if (labels->texts == NULL) {
77 labels->alphas = PUSH_LT(lt, nth_calloc(1, sizeof(float) * labels->count), free);
78 if (labels->alphas == NULL) {
82 labels->delta_alphas = PUSH_LT(lt, nth_calloc(1, sizeof(float) * labels->count), free);
83 if (labels->delta_alphas == NULL) {
87 labels->states = PUSH_LT(lt, nth_calloc(1, sizeof(enum LabelState) * labels->count), free);
88 if (labels->states == NULL) {
93 for (size_t i = 0; i < labels->count; ++i) {
94 labels->alphas[i] = 0.0f;
95 labels->delta_alphas[i] = 0.0f;
96 labels->states[i] = LABEL_STATE_VIRGIN;
97 labels->texts[i] = NULL;
99 labels->ids[i] = PUSH_LT(lt, nth_calloc(1, sizeof(char) * LABEL_MAX_ID_SIZE), free);
100 if (labels->ids[i] == NULL) {
105 line_stream_next(line_stream),
106 "%" STRINGIFY(LABEL_MAX_ID_SIZE) "s%f%f%6s\n",
108 &labels->positions[i].x,
109 &labels->positions[i].y,
111 log_fail("Could not read position and color of %dth label\n", i);
115 labels->colors[i] = hexstr(color);
117 const char *label_text = line_stream_next(line_stream);
118 if (label_text == NULL) {
119 log_fail("Could not read text of %dth label\n", i);
123 labels->texts[i] = PUSH_LT(
125 string_duplicate(label_text, NULL),
127 if (labels->texts[i] == NULL) {
131 trim_endline(labels->texts[i]);
137 void destroy_labels(Labels *label)
140 RETURN_LT0(label->lt);
143 int labels_render(const Labels *label,
147 trace_assert(camera);
149 for (size_t i = 0; i < label->count; ++i) {
151 const float state = label->alphas[i] * (2 - label->alphas[i]);
153 if (camera_render_text(camera,
156 rgba(label->colors[i].r,
160 vec_sum(label->positions[i],
161 vec(0.0f, -8.0f * state))) < 0) {
169 void labels_update(Labels *label,
175 for (size_t i = 0; i < label->count; ++i) {
176 label->alphas[i] = label->alphas[i] + label->delta_alphas[i] * delta_time;
178 if (label->alphas[i] < 0.0f) {
179 label->alphas[i] = 0.0f;
180 label->delta_alphas[i] = 0.0f;
183 if (label->alphas[i] > 1.0f) {
184 label->alphas[i] = 1.0f;
185 label->delta_alphas[i] = 0.0f;
190 void labels_enter_camera_event(Labels *labels,
191 const Camera *camera)
193 trace_assert(labels);
194 trace_assert(camera);
196 for (size_t i = 0; i < labels->count; ++i) {
197 const int became_visible = camera_is_text_visible(
200 labels->positions[i],
203 if (labels->states[i] == LABEL_STATE_VIRGIN && became_visible) {
204 labels->states[i] = LABEL_STATE_APPEARED;
205 labels->alphas[i] = 0.0f;
206 labels->delta_alphas[i] = 1.0f;
211 static struct EvalResult
212 labels_action(Labels *labels,
218 trace_assert(labels);
222 const char *target = NULL;
223 struct Expr rest = void_expr();
224 struct EvalResult res = match_list(gc, "q*", path, &target, &rest);
229 if (strcmp(target, "hide") == 0) {
230 if (labels->states[index] != LABEL_STATE_HIDDEN) {
231 labels->states[index] = LABEL_STATE_HIDDEN;
232 labels->alphas[index] = 1.0f;
233 labels->delta_alphas[index] = -3.0f;
235 return eval_success(NIL(gc));
238 return unknown_target(gc, labels->ids[index], target);
242 labels_send(Labels *labels, Gc *gc, struct Scope *scope, struct Expr path)
244 trace_assert(labels);
248 const char *target = NULL;
249 struct Expr rest = void_expr();
250 struct EvalResult res = match_list(gc, "s*", path, &target, &rest);
255 for (size_t i = 0; i < labels->count; ++i) {
256 if (strcmp(target, labels->ids[i]) == 0) {
257 return labels_action(labels, i, gc, scope, rest);
261 return unknown_target(gc, "label", target);