#include <assert.h>
-#include "console.h"
-#include "ui/edit_field.h"
#include "game/level.h"
#include "game/level/player/rigid_rect.h"
#include "script/gc.h"
#include "script/interpreter.h"
#include "script/parser.h"
#include "script/scope.h"
+#include "sdl/renderer.h"
#include "system/error.h"
#include "system/lt.h"
-#include "sdl/renderer.h"
+#include "ui/console.h"
+#include "ui/edit_field.h"
+#include "ui/history.h"
+#include "ui/log.h"
#define FONT_WIDTH_SCALE 3.0f
#define FONT_HEIGHT_SCALE 3.0f
-#define SLIDE_DOWN_TIME 0.1f
-#define SLIDE_DOWN_SPEED (FONT_CHAR_HEIGHT * FONT_HEIGHT_SCALE / SLIDE_DOWN_TIME)
-#define CONSOLE_HEIGHT (FONT_HEIGHT_SCALE * FONT_CHAR_HEIGHT)
+
+#define LOG_CAPACITY 10
+#define HISTORY_CAPACITY 20
+#define PROMPT_HEIGHT (FONT_HEIGHT_SCALE * FONT_CHAR_HEIGHT)
+#define LOG_HEIGHT (FONT_HEIGHT_SCALE * FONT_CHAR_HEIGHT * LOG_CAPACITY)
+
+#define CONSOLE_HEIGHT (LOG_HEIGHT + PROMPT_HEIGHT)
+
+#define SLIDE_DOWN_TIME 0.4f
+
+#define CONSOLE_ALPHA (0.80f)
+#define CONSOLE_BACKGROUND (color(0.20f, 0.20f, 0.20f, CONSOLE_ALPHA))
+#define CONSOLE_FOREGROUND (color(0.80f, 0.80f, 0.80f, CONSOLE_ALPHA))
+#define CONSOLE_ERROR (color(0.80f, 0.50f, 0.50f, CONSOLE_ALPHA))
+
+#define CONSOLE_EVAL_RESULT_SIZE 256
struct Console
{
Gc *gc;
struct Scope scope;
Edit_field *edit_field;
+ Log *log;
Level *level;
- float y;
+ History *history;
+ float a;
+ char *eval_result;
};
/* TODO(#354): Console does not allow to travel the history by pressing up and down */
create_edit_field(
font,
vec(FONT_WIDTH_SCALE, FONT_HEIGHT_SCALE),
- color(0.80f, 0.80f, 0.80f, 1.0f)),
+ CONSOLE_FOREGROUND),
destroy_edit_field);
if (console->edit_field == NULL) {
RETURN_LT(lt, NULL);
}
+ console->log = PUSH_LT(
+ lt,
+ create_log(
+ font,
+ vec(FONT_WIDTH_SCALE, FONT_HEIGHT_SCALE),
+ LOG_CAPACITY),
+ destroy_log);
+
console->level = level;
- console->y = -CONSOLE_HEIGHT;
+ console->a = 0;
+
+ console->eval_result = PUSH_LT(
+ lt,
+ malloc(sizeof(char) * CONSOLE_EVAL_RESULT_SIZE),
+ free);
+ if (console->eval_result == NULL) {
+ RETURN_LT(lt, NULL);
+ }
+ memset(console->eval_result, 0, sizeof(char) * CONSOLE_EVAL_RESULT_SIZE);
+
+ console->history = PUSH_LT(
+ lt,
+ create_history(HISTORY_CAPACITY),
+ destroy_history);
+ if (console->history == NULL) {
+ RETURN_LT(lt, NULL);
+ }
return console;
}
switch(event->key.keysym.sym) {
case SDLK_RETURN: {
const char *source_code = edit_field_as_text(console->edit_field);
+
+ /* TODO(#387): console pushes empty strings to the history */
+ if (history_push(console->history, source_code) < 0) {
+ return -1;
+ }
+
+ if (log_push_line(console->log, source_code, CONSOLE_FOREGROUND) < 0) {
+ return -1;
+ }
+
struct ParseResult parse_result = read_expr_from_string(console->gc,
source_code);
+
if (parse_result.is_error) {
- /* TODO(#359): Console doesn't report any parsing errors visually */
- print_parse_error(stderr, source_code, parse_result);
+ if (log_push_line(console->log, parse_result.error_message, CONSOLE_ERROR)) {
+ return -1;
+ }
+
+ edit_field_clean(console->edit_field);
+
return 0;
}
&console->scope,
parse_result.expr);
- if (eval_result.is_error) {
- /* TODO(#360): Console doesn't report any eval errors visually */
- printf("Error:\t");
- print_expr_as_sexpr(eval_result.expr);
- printf("\n");
+ if (expr_as_sexpr(
+ eval_result.expr,
+ console->eval_result,
+ CONSOLE_EVAL_RESULT_SIZE) < 0) {
+ return -1;
}
- gc_collect(console->gc, console->scope.expr);
+ if (log_push_line(console->log,
+ console->eval_result,
+ eval_result.is_error ?
+ CONSOLE_ERROR :
+ CONSOLE_FOREGROUND)) {
+ return -1;
+ }
+ gc_collect(console->gc, console->scope.expr);
edit_field_clean(console->edit_field);
+ } return 0;
+
+ case SDLK_UP: {
+ edit_field_replace(
+ console->edit_field,
+ history_current(console->history));
+ history_prev(console->history);
+ } return 0;
+ case SDLK_DOWN: {
+ edit_field_replace(
+ console->edit_field,
+ history_current(console->history));
+ history_next(console->history);
} return 0;
}
break;
}
+ /* TODO(#390): shift is not detected by edit_field anymore */
return edit_field_handle_event(console->edit_field, event);
}
SDL_Rect view_port;
SDL_RenderGetViewport(renderer, &view_port);
+ const float e = console->a * (2 - console->a);
+ const float y = -(1.0f - e) * CONSOLE_HEIGHT;
+
if (fill_rect(renderer,
- rect(0.0f, console->y,
+ rect(0.0f, y,
(float) view_port.w,
CONSOLE_HEIGHT),
- color(0.20f, 0.20f, 0.20f, 1.0f)) < 0) {
+ CONSOLE_BACKGROUND) < 0) {
+ return -1;
+ }
+
+ if (log_render(console->log,
+ renderer,
+ vec(0.0f, y)) < 0) {
return -1;
}
if (edit_field_render(console->edit_field,
renderer,
- vec(0.0f, console->y)) < 0) {
+ vec(0.0f, y + LOG_HEIGHT)) < 0) {
return -1;
}
/* TODO(#366): console slide down animation doesn't have any easing */
- if (console->y < 0.0f) {
- console->y += SLIDE_DOWN_SPEED * delta_time;
+ if (console->a < 1.0f) {
+ console->a += 1.0f / SLIDE_DOWN_TIME * delta_time;
- if (console->y > 0.0f) {
- console->y = 0.0f;
+ if (console->a > 1.0f) {
+ console->a = 1.0f;
}
}
void console_slide_down(Console *console)
{
assert(console);
- console->y = -CONSOLE_HEIGHT;
+ console->a = 0.0f;
}