]> git.lizzy.rs Git - nothing.git/blob - src/game/level/level_editor/player_layer.c
Implement chop_player_layer
[nothing.git] / src / game / level / level_editor / player_layer.c
1 #include <stdio.h>
2
3 #include <SDL.h>
4
5 #include "game/camera.h"
6 #include "system/stacktrace.h"
7 #include "player_layer.h"
8 #include "system/nth_alloc.h"
9 #include "system/log.h"
10 #include "undo_history.h"
11 #include "system/memory.h"
12
13 typedef struct {
14     PlayerLayer *layer;
15     Vec2f position;
16     Color color;
17 } PlayerUndoContext;
18
19 static
20 PlayerUndoContext player_layer_create_undo_context(PlayerLayer *player_layer)
21 {
22     PlayerUndoContext context = {
23         .layer = player_layer,
24         .position = player_layer->position,
25         .color = player_layer->prev_color
26     };
27
28     return context;
29 }
30
31 static
32 void player_layer_undo(void *context, size_t context_size)
33 {
34     trace_assert(context);
35     trace_assert(sizeof(PlayerUndoContext) == context_size);
36
37     PlayerUndoContext *undo_context = context;
38     PlayerLayer *player_layer = undo_context->layer;
39
40     player_layer->position = undo_context->position;
41     player_layer->color_picker = create_color_picker_from_rgba(undo_context->color);
42     player_layer->prev_color = undo_context->color;
43 }
44
45 PlayerLayer create_player_layer(Vec2f position, Color color)
46 {
47     return (PlayerLayer) {
48         .position = position,
49         .color_picker = create_color_picker_from_rgba(color),
50         .prev_color = color
51     };
52 }
53
54 PlayerLayer create_player_layer_from_line_stream(LineStream *line_stream)
55 {
56     trace_assert(line_stream);
57
58     const char *line = line_stream_next(line_stream);
59     trace_assert(line);
60
61     char colorstr[7] = "000000";
62     Vec2f position = vec(0.0f, 0.0f);
63
64     const int bound =
65         sscanf(line, "%f%f%6s", &position.x, &position.y, colorstr);
66
67 #define BOUND_EXPECTED 3
68     if (bound != BOUND_EXPECTED) {
69         log_fail("Could not read Player Layer properly. Parsed tokens: %d. Expected: %d\n",
70                  bound, BOUND_EXPECTED);
71     }
72 #undef BOUND_EXPECTED
73
74     return create_player_layer(position, hexstr(colorstr));
75 }
76
77 PlayerLayer chop_player_layer(Memory *memory, String *input)
78 {
79     trace_assert(memory);
80     trace_assert(input);
81
82     String line = chop_by_delim(input, '\n');
83     float x = strtof(string_to_cstr(memory, chop_word(&line)), NULL);
84     float y = strtof(string_to_cstr(memory, chop_word(&line)), NULL);
85     Color color = hexs(chop_word(&line));
86
87     return create_player_layer(vec(x, y), color);
88 }
89
90 LayerPtr player_layer_as_layer(PlayerLayer *player_layer)
91 {
92     LayerPtr layer = {
93         .type = LAYER_PLAYER,
94         .ptr = player_layer
95     };
96     return layer;
97 }
98
99 int player_layer_render(const PlayerLayer *player_layer,
100                         const Camera *camera,
101                         int active)
102 {
103     trace_assert(player_layer);
104     trace_assert(camera);
105
106     if (camera_fill_rect(
107             camera,
108             rect_from_vecs(
109                 player_layer->position,
110                 vec(25.0f, 25.0f)),
111             color_scale(
112                 color_picker_rgba(&player_layer->color_picker),
113                 rgba(1.0f, 1.0f, 1.0f, active ? 1.0f : 0.5f))) < 0) {
114         return -1;
115     }
116
117     if (active && color_picker_render(
118             &player_layer->color_picker,
119             camera)) {
120         return -1;
121     }
122
123     return 0;
124 }
125
126 int player_layer_event(PlayerLayer *player_layer,
127                        const SDL_Event *event,
128                        const Camera *camera,
129                        UndoHistory *undo_history)
130 {
131     trace_assert(player_layer);
132     trace_assert(event);
133     trace_assert(camera);
134     trace_assert(undo_history);
135
136     int selected = 0;
137     if (color_picker_event(
138             &player_layer->color_picker,
139             event,
140             camera,
141             &selected) < 0) {
142         return -1;
143     }
144
145     if (selected && !color_picker_drag(&player_layer->color_picker)) {
146         PlayerUndoContext context =
147             player_layer_create_undo_context(player_layer);
148         undo_history_push(
149             undo_history,
150             player_layer_undo,
151             &context,
152             sizeof(context));
153         player_layer->prev_color = color_picker_rgba(&player_layer->color_picker);
154     }
155
156     if (!selected &&
157         event->type == SDL_MOUSEBUTTONDOWN &&
158         event->button.button == SDL_BUTTON_LEFT) {
159
160         PlayerUndoContext context =
161             player_layer_create_undo_context(player_layer);
162
163         undo_history_push(
164             undo_history,
165             player_layer_undo,
166             &context, sizeof(context));
167
168         player_layer->position =
169             camera_map_screen(camera,
170                               event->button.x,
171                               event->button.y);
172     }
173
174     return 0;
175 }
176
177 int player_layer_dump_stream(const PlayerLayer *player_layer,
178                              FILE *filedump)
179 {
180     trace_assert(player_layer);
181     trace_assert(filedump);
182
183     fprintf(filedump, "%f %f ", player_layer->position.x, player_layer->position.y);
184     color_hex_to_stream(color_picker_rgba(&player_layer->color_picker), filedump);
185     fprintf(filedump, "\n");
186
187     return 0;
188 }