]> git.lizzy.rs Git - nothing.git/blobdiff - src/ui/console.c
TODO(#390)
[nothing.git] / src / ui / console.c
index 78ee724da9b0eb36b23fb7b580aa758c28f97e4c..8faa10482b815a93e3cd61601a3dcc0e37a0f639 100644 (file)
@@ -1,22 +1,37 @@
 #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
 {
@@ -24,8 +39,11 @@ 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 */
@@ -95,14 +113,39 @@ Console *create_console(Level *level,
         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;
 }
@@ -121,11 +164,26 @@ int console_handle_event(Console *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;
             }
 
@@ -134,22 +192,43 @@ int console_handle_event(Console *console,
                 &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);
 }
 
@@ -160,17 +239,26 @@ int console_render(const Console *console,
     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;
     }
 
@@ -183,11 +271,11 @@ int console_update(Console *console, float delta_time)
 
     /* 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;
         }
     }
 
@@ -197,5 +285,5 @@ int console_update(Console *console, float delta_time)
 void console_slide_down(Console *console)
 {
     assert(console);
-    console->y = -CONSOLE_HEIGHT;
+    console->a = 0.0f;
 }