4 #include "system/stacktrace.h"
7 #include "game/level.h"
8 #include "sdl/renderer.h"
9 #include "system/log.h"
10 #include "system/lt.h"
11 #include "system/nth_alloc.h"
12 #include "ui/console.h"
13 #include "ui/console_log.h"
14 #include "ui/edit_field.h"
15 #include "ui/history.h"
16 #include "math/extrema.h"
18 #define FONT_WIDTH_SCALE 3.0f
19 #define FONT_HEIGHT_SCALE 3.0f
21 #define CONSOLE_LOG_CAPACITY 10
22 #define HISTORY_CAPACITY 20
23 #define PROMPT_HEIGHT (FONT_HEIGHT_SCALE * FONT_CHAR_HEIGHT)
24 #define CONSOLE_LOG_HEIGHT (FONT_HEIGHT_SCALE * FONT_CHAR_HEIGHT * CONSOLE_LOG_CAPACITY)
26 #define CONSOLE_HEIGHT (CONSOLE_LOG_HEIGHT + PROMPT_HEIGHT)
28 #define SLIDE_DOWN_TIME 0.4f
30 #define CONSOLE_ALPHA (0.80f)
31 #define CONSOLE_BACKGROUND (rgba(0.20f, 0.20f, 0.20f, CONSOLE_ALPHA))
32 #define CONSOLE_FOREGROUND (rgba(0.80f, 0.80f, 0.80f, CONSOLE_ALPHA))
33 #define CONSOLE_ERROR (rgba(0.80f, 0.50f, 0.50f, CONSOLE_ALPHA))
38 Edit_field edit_field;
39 Console_Log *console_log;
45 /* TODO(#356): Console does not support autocompletion */
47 Console *create_console(Game *game)
51 Console *console = PUSH_LT(lt, nth_calloc(1, sizeof(Console)), free);
52 if (console == NULL) {
57 console->edit_field.font_size = vec(FONT_WIDTH_SCALE, FONT_HEIGHT_SCALE);
58 console->edit_field.font_color = CONSOLE_FOREGROUND;
60 console->console_log = PUSH_LT(
63 vec(FONT_WIDTH_SCALE, FONT_HEIGHT_SCALE),
64 CONSOLE_LOG_CAPACITY),
69 console->history = PUSH_LT(
71 create_history(HISTORY_CAPACITY),
73 if (console->history == NULL) {
82 void destroy_console(Console *console)
84 trace_assert(console);
85 RETURN_LT0(console->lt);
88 static int console_eval_input(Console *console)
90 const char *input_text = edit_field_as_text(&console->edit_field);
92 String input = string_nt(input_text);
93 String command = chop_word(&input);
95 if (string_equal(command, STRING_LIT(""))) {
96 edit_field_clean(&console->edit_field);
100 if (history_push(console->history, input_text) < 0) {
104 if (console_log_push_line(console->console_log, input_text, NULL, CONSOLE_FOREGROUND) < 0) {
108 if (string_equal(command, STRING_LIT("load"))) {
109 String level = chop_word(&input);
110 console_log_push_line(console->console_log, "Loading level:", NULL, CONSOLE_FOREGROUND);
111 console_log_push_line(console->console_log, level.data, level.data + level.count, CONSOLE_FOREGROUND);
112 char level_name[256];
113 memset(level_name, 0, 256);
114 memcpy(level_name, level.data, min_size_t(level.count, 255));
116 if (game_load_level(console->game, level_name) < 0) {
117 console_log_push_line(console->console_log, "Could not load level", NULL, CONSOLE_ERROR);
119 } else if (string_equal(command, STRING_LIT("menu"))) {
120 console_log_push_line(console->console_log, "Loading menu", NULL, CONSOLE_FOREGROUND);
121 game_switch_state(console->game, GAME_STATE_LEVEL_PICKER);
123 console_log_push_line(console->console_log, "Unknown command", NULL, CONSOLE_ERROR);
126 edit_field_clean(&console->edit_field);
131 int console_handle_event(Console *console,
132 const SDL_Event *event)
134 switch(event->type) {
136 switch(event->key.keysym.sym) {
138 return console_eval_input(console);
142 &console->edit_field,
143 history_current(console->history));
144 history_prev(console->history);
148 if (event->key.keysym.mod & KMOD_CTRL) {
150 &console->edit_field,
151 history_current(console->history));
152 history_prev(console->history);
158 if (event->key.keysym.mod & KMOD_CTRL) {
159 console_log_clear(console->console_log);
166 &console->edit_field,
167 history_current(console->history));
168 history_next(console->history);
172 if (event->key.keysym.mod & KMOD_CTRL) {
174 &console->edit_field, history_current(console->history));
175 history_next(console->history);
183 return edit_field_event(&console->edit_field, event);
186 int console_render(const Console *console,
187 const Camera *camera)
189 /* TODO(#364): console doesn't have any padding around the edit fields */
191 SDL_RenderGetViewport(camera->renderer, &view_port);
193 const float e = console->a * (2 - console->a);
194 const float y = -(1.0f - e) * CONSOLE_HEIGHT;
196 if (camera_fill_rect_screen(
201 CONSOLE_BACKGROUND) < 0) {
205 console_log_render(console->console_log,
209 if (edit_field_render_screen(&console->edit_field,
211 vec(0.0f, y + CONSOLE_LOG_HEIGHT)) < 0) {
218 int console_update(Console *console, float delta_time)
220 trace_assert(console);
222 if (console->a < 1.0f) {
223 console->a += 1.0f / SLIDE_DOWN_TIME * delta_time;
225 if (console->a > 1.0f) {
233 void console_slide_down(Console *console)
235 trace_assert(console);