]> git.lizzy.rs Git - nothing.git/blob - src/game/level/level_editor.c
(#802) TODO
[nothing.git] / src / game / level / level_editor.c
1 #include <stdbool.h>
2
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"
11
12 #include "level_editor.h"
13
14 // TODO(#802): Level Editor should modify boxes_layer instead of boxes
15 struct LevelEditor
16 {
17     Lt *lt;
18     Vec camera_position;
19     float camera_scale;
20     ProtoRect proto_rect;
21     ColorPicker color_picker;
22     // TODO: boxes_layer is not connected with the level->boxes
23     Layer *boxes_layer;
24     bool drag;
25 };
26
27 LevelEditor *create_level_editor(void)
28 {
29     Lt *lt = create_lt();
30     if (lt == NULL) {
31         return NULL;
32     }
33
34     LevelEditor *level_editor = PUSH_LT(lt, nth_calloc(1, sizeof(LevelEditor)), free);
35     if (level_editor == NULL) {
36         RETURN_LT(lt, NULL);
37     }
38     level_editor->lt = lt;
39
40     level_editor->camera_position = vec(0.0f, 0.0f);
41     level_editor->camera_scale = 1.0f;
42     level_editor->proto_rect.color = rgba(1.0f, 0.0f, 0.0f, 1.0f);
43     level_editor->color_picker.position = vec(0.0f, 0.0f);
44     level_editor->color_picker.proto_rect = &level_editor->proto_rect;
45     level_editor->boxes_layer = PUSH_LT(lt, create_layer(), destroy_layer);
46
47     if (level_editor->boxes_layer == NULL) {
48         RETURN_LT(lt, NULL);
49     }
50
51     level_editor->drag = false;
52
53     return level_editor;
54 }
55
56 void destroy_level_editor(LevelEditor *level_editor)
57 {
58     trace_assert(level_editor);
59     RETURN_LT0(level_editor->lt);
60 }
61
62 int level_editor_render(const LevelEditor *level_editor,
63                         Camera *camera)
64 {
65     trace_assert(level_editor);
66     trace_assert(camera);
67
68     if (layer_render(level_editor->boxes_layer, camera) < 0) {
69         return -1;
70     }
71
72     if (proto_rect_render(&level_editor->proto_rect, camera) < 0) {
73         return -1;
74     }
75
76     if (color_picker_render(&level_editor->color_picker, camera) < 0) {
77         return -1;
78     }
79
80     return 0;
81 }
82
83 int level_editor_update(LevelEditor *level_editor,
84                         float delta_time)
85 {
86     trace_assert(level_editor);
87
88     if (proto_rect_update(&level_editor->proto_rect, delta_time) < 0) {
89         return -1;
90     }
91
92     return 0;
93 }
94
95 int level_editor_event(LevelEditor *level_editor,
96                        const SDL_Event *event,
97                        const Camera *camera)
98 {
99     trace_assert(level_editor);
100     trace_assert(event);
101
102     (void) camera;
103
104     switch (event->type) {
105     case SDL_MOUSEWHEEL: {
106         // TODO(#679): zooming in edit mode is not smooth enough
107         if (event->wheel.y > 0) {
108             level_editor->camera_scale += 0.1f;
109         } else if (event->wheel.y < 0) {
110             level_editor->camera_scale = fmaxf(0.1f, level_editor->camera_scale - 0.1f);
111         }
112     } break;
113
114     case SDL_MOUSEBUTTONUP:
115     case SDL_MOUSEBUTTONDOWN: {
116         if (event->type == SDL_MOUSEBUTTONUP) {
117             const Vec position = camera_map_screen(camera, event->button.x, event->button.y);
118             if (layer_delete_rect_at(level_editor->boxes_layer, position) < 0) {
119                 return -1;
120             }
121         }
122
123         bool selected = false;
124         if (color_picker_mouse_button(
125                 &level_editor->color_picker,
126                 &event->button,
127                 &selected) < 0) {
128             return -1;
129         }
130
131         if (!selected && proto_rect_mouse_button(
132                 &level_editor->proto_rect,
133                 &event->button,
134                 level_editor->boxes_layer,
135                 camera) < 0) {
136             return -1;
137         }
138
139         if (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_MIDDLE) {
140             level_editor->drag = true;
141         }
142
143         if (event->type == SDL_MOUSEBUTTONUP && event->button.button == SDL_BUTTON_MIDDLE) {
144             level_editor->drag = false;
145         }
146     } break;
147
148     case SDL_MOUSEMOTION: {
149         if (level_editor->drag) {
150             const Vec next_position = camera_map_screen(camera, event->motion.x, event->motion.y);
151             const Vec prev_position = camera_map_screen(
152                 camera,
153                 event->motion.x + event->motion.xrel,
154                 event->motion.y + event->motion.yrel);
155
156             vec_add(&level_editor->camera_position,
157                     vec_sub(next_position, prev_position));
158         }
159
160         if (proto_rect_mouse_motion(&level_editor->proto_rect, &event->motion, camera) < 0) {
161             return -1;
162         }
163     } break;
164     }
165
166     return 0;
167 }
168
169 int level_editor_focus_camera(LevelEditor *level_editor,
170                               Camera *camera)
171 {
172     camera_center_at(camera, level_editor->camera_position);
173     camera_scale(camera, level_editor->camera_scale);
174     return 0;
175 }