3 #include "game/camera.h"
4 #include "game/level/boxes.h"
5 #include "game/level/level_editor/proto_rect.h"
6 #include "game/level/level_editor/color_picker.h"
7 #include "game/level/level_editor/layer.h"
8 #include "game/level/level_editor/point_layer.h"
9 #include "game/level/level_editor/layer_picker.h"
10 #include "system/stacktrace.h"
11 #include "system/nth_alloc.h"
12 #include "system/lt.h"
14 #include "level_editor.h"
21 LayerPicker layer_picker;
22 ColorPicker color_picker;
25 RectLayer *boxes_rect_layer;
26 RectLayer *platforms_rect_layer;
27 RectLayer *back_platforms_rect_layer;
28 PointLayer *goals_rect_layer;
30 RectLayer *current_rect_layer;
31 PointLayer *current_point_rect_layer;
32 // TODO(#823): LevelEditor does not allow to switch the current layer
36 LevelEditor *create_level_editor(RectLayer *boxes_rect_layer,
37 RectLayer *platforms_rect_layer,
38 RectLayer *back_platforms_rect_layer,
39 PointLayer *goals_rect_layer)
41 trace_assert(boxes_rect_layer);
42 trace_assert(platforms_rect_layer);
43 trace_assert(back_platforms_rect_layer);
44 trace_assert(goals_rect_layer);
51 LevelEditor *level_editor = PUSH_LT(lt, nth_calloc(1, sizeof(LevelEditor)), free);
52 if (level_editor == NULL) {
55 level_editor->lt = lt;
57 level_editor->camera_position = vec(0.0f, 0.0f);
58 level_editor->camera_scale = 1.0f;
60 level_editor->boxes_rect_layer = PUSH_LT(lt, boxes_rect_layer, destroy_rect_layer);
61 level_editor->platforms_rect_layer = PUSH_LT(lt, platforms_rect_layer, destroy_rect_layer);
62 level_editor->back_platforms_rect_layer = PUSH_LT(lt, back_platforms_rect_layer, destroy_rect_layer);
63 level_editor->goals_rect_layer = PUSH_LT(lt, goals_rect_layer, destroy_point_rect_layer);
64 level_editor->current_rect_layer = boxes_rect_layer;
65 level_editor->current_point_rect_layer = goals_rect_layer;
67 level_editor->color_picker.color = rgba(1.0f, 0.0f, 0.0f, 1.0f);
68 level_editor->layer_picker = LAYER_PICKER_BOXES;
70 level_editor->proto_rect.color_current = &level_editor->color_picker.color;
71 level_editor->proto_rect.layer_current = &level_editor->current_rect_layer;
73 level_editor->drag = false;
78 void destroy_level_editor(LevelEditor *level_editor)
80 trace_assert(level_editor);
81 RETURN_LT0(level_editor->lt);
84 int level_editor_render(const LevelEditor *level_editor,
87 trace_assert(level_editor);
90 if (layer_render(level_editor->back_platforms_rect_layer, camera) < 0) {
94 if (layer_render(level_editor->boxes_rect_layer, camera) < 0) {
98 if (layer_render(level_editor->platforms_rect_layer, camera) < 0) {
102 if (proto_rect_render(&level_editor->proto_rect, camera) < 0) {
106 if (color_picker_render(&level_editor->color_picker, camera) < 0) {
110 if (layer_picker_render(&level_editor->layer_picker, camera) < 0) {
117 int level_editor_update(LevelEditor *level_editor,
120 trace_assert(level_editor);
122 if (proto_rect_update(&level_editor->proto_rect, delta_time) < 0) {
129 int level_editor_event(LevelEditor *level_editor,
130 const SDL_Event *event,
131 const Camera *camera)
133 trace_assert(level_editor);
135 trace_assert(camera);
137 switch (event->type) {
138 case SDL_MOUSEWHEEL: {
139 // TODO(#679): zooming in edit mode is not smooth enough
140 if (event->wheel.y > 0) {
141 level_editor->camera_scale += 0.1f;
142 } else if (event->wheel.y < 0) {
143 level_editor->camera_scale = fmaxf(0.1f, level_editor->camera_scale - 0.1f);
147 case SDL_MOUSEBUTTONUP:
148 case SDL_MOUSEBUTTONDOWN: {
149 bool selected = false;
150 if (color_picker_mouse_button(
151 &level_editor->color_picker,
157 if (layer_picker_mouse_button(
158 &level_editor->layer_picker,
165 switch (level_editor->layer_picker) {
166 case LAYER_PICKER_BOXES: {
167 level_editor->current_rect_layer = level_editor->boxes_rect_layer;
169 case LAYER_PICKER_PLATFORMS: {
170 level_editor->current_rect_layer = level_editor->platforms_rect_layer;
172 case LAYER_PICKER_BACK_PLATFORMS: {
173 level_editor->current_rect_layer = level_editor->back_platforms_rect_layer;
175 case LAYER_PICKER_GOALS: {
176 level_editor->current_point_rect_layer = level_editor->goals_rect_layer;
182 if (layer_picker_type(&level_editor->layer_picker) == LAYER_TYPE_RECT) {
183 if (!selected && proto_rect_mouse_button(
184 &level_editor->proto_rect,
190 point_layer_mouse_button(level_editor->current_point_rect_layer, &event->button);
193 if (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_MIDDLE) {
194 level_editor->drag = true;
197 if (event->type == SDL_MOUSEBUTTONUP && event->button.button == SDL_BUTTON_MIDDLE) {
198 level_editor->drag = false;
202 case SDL_MOUSEMOTION: {
203 if (level_editor->drag) {
204 const Vec next_position = camera_map_screen(camera, event->motion.x, event->motion.y);
205 const Vec prev_position = camera_map_screen(
207 event->motion.x + event->motion.xrel,
208 event->motion.y + event->motion.yrel);
210 vec_add(&level_editor->camera_position,
211 vec_sub(next_position, prev_position));
214 if (proto_rect_mouse_motion(&level_editor->proto_rect, &event->motion, camera) < 0) {
223 int level_editor_focus_camera(LevelEditor *level_editor,
226 camera_center_at(camera, level_editor->camera_position);
227 camera_scale(camera, level_editor->camera_scale);
231 const RectLayer *level_editor_boxes(const LevelEditor *level_editor)
233 return level_editor->boxes_rect_layer;
236 const RectLayer *level_editor_platforms(const LevelEditor *level_editor)
238 return level_editor->platforms_rect_layer;
241 const RectLayer *level_editor_back_platforms(const LevelEditor *level_editor)
243 return level_editor->back_platforms_rect_layer;