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 "system/stacktrace.h"
9 #include "system/nth_alloc.h"
10 #include "system/lt.h"
12 #include "level_editor.h"
20 ColorPicker color_picker;
21 // TODO(#805): boxes_layer is not connected with the level->boxes
23 Layer *platforms_layer;
24 Layer *back_platforms_layer;
25 // TODO: LevelEditor does not allow to switch the current layer
30 LevelEditor *create_level_editor(Layer *boxes_layer,
31 Layer *platforms_layer,
32 Layer *back_platforms_layer)
34 trace_assert(boxes_layer);
35 trace_assert(platforms_layer);
36 trace_assert(back_platforms_layer);
43 LevelEditor *level_editor = PUSH_LT(lt, nth_calloc(1, sizeof(LevelEditor)), free);
44 if (level_editor == NULL) {
47 level_editor->lt = lt;
49 level_editor->camera_position = vec(0.0f, 0.0f);
50 level_editor->camera_scale = 1.0f;
51 level_editor->proto_rect.color = rgba(1.0f, 0.0f, 0.0f, 1.0f);
52 level_editor->color_picker.position = vec(0.0f, 0.0f);
53 level_editor->color_picker.proto_rect = &level_editor->proto_rect;
54 level_editor->boxes_layer = PUSH_LT(lt, boxes_layer, destroy_layer);
55 level_editor->platforms_layer = PUSH_LT(lt, platforms_layer, destroy_layer);
56 level_editor->back_platforms_layer = PUSH_LT(lt, back_platforms_layer, destroy_layer);
57 level_editor->drag = false;
58 level_editor->current_layer = level_editor->platforms_layer;
63 void destroy_level_editor(LevelEditor *level_editor)
65 trace_assert(level_editor);
66 RETURN_LT0(level_editor->lt);
69 int level_editor_render(const LevelEditor *level_editor,
72 trace_assert(level_editor);
75 if (layer_render(level_editor->back_platforms_layer, camera) < 0) {
79 if (layer_render(level_editor->boxes_layer, camera) < 0) {
83 if (layer_render(level_editor->platforms_layer, camera) < 0) {
87 if (proto_rect_render(&level_editor->proto_rect, camera) < 0) {
91 if (color_picker_render(&level_editor->color_picker, camera) < 0) {
98 int level_editor_update(LevelEditor *level_editor,
101 trace_assert(level_editor);
103 if (proto_rect_update(&level_editor->proto_rect, delta_time) < 0) {
110 int level_editor_event(LevelEditor *level_editor,
111 const SDL_Event *event,
112 const Camera *camera)
114 trace_assert(level_editor);
119 switch (event->type) {
120 case SDL_MOUSEWHEEL: {
121 // TODO(#679): zooming in edit mode is not smooth enough
122 if (event->wheel.y > 0) {
123 level_editor->camera_scale += 0.1f;
124 } else if (event->wheel.y < 0) {
125 level_editor->camera_scale = fmaxf(0.1f, level_editor->camera_scale - 0.1f);
129 case SDL_MOUSEBUTTONUP:
130 case SDL_MOUSEBUTTONDOWN: {
131 if (event->type == SDL_MOUSEBUTTONUP) {
132 const Vec position = camera_map_screen(camera, event->button.x, event->button.y);
133 if (layer_delete_rect_at(level_editor->current_layer, position) < 0) {
138 bool selected = false;
139 if (color_picker_mouse_button(
140 &level_editor->color_picker,
146 if (!selected && proto_rect_mouse_button(
147 &level_editor->proto_rect,
149 level_editor->current_layer,
154 if (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_MIDDLE) {
155 level_editor->drag = true;
158 if (event->type == SDL_MOUSEBUTTONUP && event->button.button == SDL_BUTTON_MIDDLE) {
159 level_editor->drag = false;
163 case SDL_MOUSEMOTION: {
164 if (level_editor->drag) {
165 const Vec next_position = camera_map_screen(camera, event->motion.x, event->motion.y);
166 const Vec prev_position = camera_map_screen(
168 event->motion.x + event->motion.xrel,
169 event->motion.y + event->motion.yrel);
171 vec_add(&level_editor->camera_position,
172 vec_sub(next_position, prev_position));
175 if (proto_rect_mouse_motion(&level_editor->proto_rect, &event->motion, camera) < 0) {
184 int level_editor_focus_camera(LevelEditor *level_editor,
187 camera_center_at(camera, level_editor->camera_position);
188 camera_scale(camera, level_editor->camera_scale);
192 const Layer *level_editor_boxes(const LevelEditor *level_editor)
194 return level_editor->boxes_layer;
197 const Layer *level_editor_platforms(const LevelEditor *level_editor)
199 return level_editor->platforms_layer;