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_layer;
26 RectLayer *platforms_layer;
27 RectLayer *back_platforms_layer;
28 PointLayer *goals_layer;
30 RectLayer *current_rect_layer;
31 PointLayer *current_point_layer;
32 // TODO(#823): LevelEditor does not allow to switch the current layer
36 LevelEditor *create_level_editor(RectLayer *boxes_layer,
37 RectLayer *platforms_layer,
38 RectLayer *back_platforms_layer,
39 PointLayer *goals_layer)
41 trace_assert(boxes_layer);
42 trace_assert(platforms_layer);
43 trace_assert(back_platforms_layer);
44 trace_assert(goals_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_layer = PUSH_LT(lt, boxes_layer, destroy_rect_layer);
61 level_editor->platforms_layer = PUSH_LT(lt, platforms_layer, destroy_rect_layer);
62 level_editor->back_platforms_layer = PUSH_LT(lt, back_platforms_layer, destroy_rect_layer);
63 level_editor->goals_layer = PUSH_LT(lt, goals_layer, destroy_point_layer);
64 level_editor->current_rect_layer = boxes_layer;
65 level_editor->current_point_layer = goals_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 (rect_layer_render(level_editor->back_platforms_layer, camera) < 0) {
94 if (rect_layer_render(level_editor->boxes_layer, camera) < 0) {
98 if (rect_layer_render(level_editor->platforms_layer, camera) < 0) {
102 if (point_layer_render(level_editor->goals_layer, camera) < 0) {
106 if (proto_rect_render(&level_editor->proto_rect, camera) < 0) {
110 if (color_picker_render(&level_editor->color_picker, camera) < 0) {
114 if (layer_picker_render(&level_editor->layer_picker, camera) < 0) {
121 int level_editor_update(LevelEditor *level_editor,
124 trace_assert(level_editor);
126 if (proto_rect_update(&level_editor->proto_rect, delta_time) < 0) {
133 int level_editor_event(LevelEditor *level_editor,
134 const SDL_Event *event,
135 const Camera *camera)
137 trace_assert(level_editor);
139 trace_assert(camera);
141 switch (event->type) {
144 if (layer_picker_type(&level_editor->layer_picker) == LAYER_TYPE_RECT) {
147 if (point_layer_keyboard(
148 level_editor->current_point_layer,
155 case SDL_MOUSEWHEEL: {
156 // TODO(#679): zooming in edit mode is not smooth enough
157 if (event->wheel.y > 0) {
158 level_editor->camera_scale += 0.1f;
159 } else if (event->wheel.y < 0) {
160 level_editor->camera_scale = fmaxf(0.1f, level_editor->camera_scale - 0.1f);
164 case SDL_MOUSEBUTTONUP:
165 case SDL_MOUSEBUTTONDOWN: {
166 bool selected = false;
167 if (color_picker_mouse_button(
168 &level_editor->color_picker,
174 if (layer_picker_mouse_button(
175 &level_editor->layer_picker,
182 switch (level_editor->layer_picker) {
183 case LAYER_PICKER_BOXES: {
184 level_editor->current_rect_layer = level_editor->boxes_layer;
186 case LAYER_PICKER_PLATFORMS: {
187 level_editor->current_rect_layer = level_editor->platforms_layer;
189 case LAYER_PICKER_BACK_PLATFORMS: {
190 level_editor->current_rect_layer = level_editor->back_platforms_layer;
192 case LAYER_PICKER_GOALS: {
193 level_editor->current_point_layer = level_editor->goals_layer;
199 if (layer_picker_type(&level_editor->layer_picker) == LAYER_TYPE_RECT) {
200 if (!selected && proto_rect_mouse_button(
201 &level_editor->proto_rect,
207 if (!selected && point_layer_mouse_button(
208 level_editor->current_point_layer,
211 level_editor->color_picker.color) < 0) {
216 if (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_MIDDLE) {
217 level_editor->drag = true;
220 if (event->type == SDL_MOUSEBUTTONUP && event->button.button == SDL_BUTTON_MIDDLE) {
221 level_editor->drag = false;
225 case SDL_MOUSEMOTION: {
226 if (level_editor->drag) {
227 const Vec next_position = camera_map_screen(camera, event->motion.x, event->motion.y);
228 const Vec prev_position = camera_map_screen(
230 event->motion.x + event->motion.xrel,
231 event->motion.y + event->motion.yrel);
233 vec_add(&level_editor->camera_position,
234 vec_sub(next_position, prev_position));
237 if (proto_rect_mouse_motion(&level_editor->proto_rect, &event->motion, camera) < 0) {
246 int level_editor_focus_camera(LevelEditor *level_editor,
249 camera_center_at(camera, level_editor->camera_position);
250 camera_scale(camera, level_editor->camera_scale);
254 const RectLayer *level_editor_boxes(const LevelEditor *level_editor)
256 return level_editor->boxes_layer;
259 const RectLayer *level_editor_platforms(const LevelEditor *level_editor)
261 return level_editor->platforms_layer;
264 const RectLayer *level_editor_back_platforms(const LevelEditor *level_editor)
266 return level_editor->back_platforms_layer;
269 const PointLayer *level_editor_goals_layer(const LevelEditor *level_editor)
271 return level_editor->goals_layer;