1 #include "system/stacktrace.h"
6 #include "system/str.h"
7 #include "system/line_stream.h"
8 #include "system/log.h"
10 #include "system/nth_alloc.h"
11 #include "game/level/level_editor/rect_layer.h"
12 #include "game/level/labels.h"
13 #include "game/level/goals.h"
16 RS_PLAYER_OUTSIDE = 0,
26 enum RegionState *states;
33 Regions *create_regions_from_rect_layer(const RectLayer *rect_layer,
37 trace_assert(rect_layer);
42 Regions *regions = PUSH_LT(
44 nth_calloc(1, sizeof(Regions)),
46 if (regions == NULL) {
51 regions->count = rect_layer_count(rect_layer);
53 regions->ids = PUSH_LT(
55 nth_calloc(regions->count * ENTITY_MAX_ID_SIZE, sizeof(char)),
57 if (regions->ids == NULL) {
61 rect_layer_ids(rect_layer),
62 regions->count * ENTITY_MAX_ID_SIZE * sizeof(char));
65 regions->rects = PUSH_LT(
67 nth_calloc(1, sizeof(Rect) * regions->count),
69 if (regions->rects == NULL) {
72 memcpy(regions->rects,
73 rect_layer_rects(rect_layer),
74 regions->count * sizeof(Rect));
77 regions->colors = PUSH_LT(
79 nth_calloc(1, sizeof(Color) * regions->count),
81 if (regions->colors == NULL) {
84 memcpy(regions->colors,
85 rect_layer_colors(rect_layer),
86 regions->count * sizeof(Color));
88 regions->states = PUSH_LT(
90 nth_calloc(1, sizeof(enum RegionState) * regions->count),
92 if (regions->states == NULL) {
96 regions->actions = PUSH_LT(
98 nth_calloc(1, sizeof(Action) * regions->count),
100 if (regions->actions == NULL) {
103 memcpy(regions->actions,
104 rect_layer_actions(rect_layer),
105 regions->count * sizeof(Action));
107 // TODO(#1108): impossible to change the region action from the Level Editor
110 regions->labels = labels;
111 regions->goals = goals;
116 void destroy_regions(Regions *regions)
118 trace_assert(regions);
119 RETURN_LT0(regions->lt);
122 void regions_player_enter(Regions *regions, Player *player)
124 trace_assert(regions);
125 trace_assert(player);
127 for (size_t i = 0; i < regions->count; ++i) {
128 if (regions->states[i] == RS_PLAYER_OUTSIDE &&
129 player_overlaps_rect(player, regions->rects[i])) {
130 regions->states[i] = RS_PLAYER_INSIDE;
132 switch (regions->actions[i].type) {
133 case ACTION_HIDE_LABEL: {
134 labels_hide(regions->labels, regions->actions[i].entity_id);
137 case ACTION_TOGGLE_GOAL: {
138 goals_hide(regions->goals, regions->actions[i].entity_id);
147 void regions_player_leave(Regions *regions, Player *player)
149 trace_assert(regions);
150 trace_assert(player);
152 for (size_t i = 0; i < regions->count; ++i) {
153 if (regions->states[i] == RS_PLAYER_INSIDE &&
154 !player_overlaps_rect(player, regions->rects[i])) {
155 regions->states[i] = RS_PLAYER_OUTSIDE;
157 switch (regions->actions[i].type) {
158 case ACTION_TOGGLE_GOAL: {
159 goals_show(regions->goals, regions->actions[i].entity_id);
168 int regions_render(Regions *regions, const Camera *camera)
170 trace_assert(regions);
171 trace_assert(camera);
173 for (size_t i = 0; i < regions->count; ++i) {
174 if (camera_render_debug_rect(
177 regions->colors[i]) < 0) {