Skip to content

Commit

Permalink
console: remember prompt history
Browse files Browse the repository at this point in the history
  • Loading branch information
rr- committed Oct 7, 2024
1 parent 53101ab commit 8bab311
Show file tree
Hide file tree
Showing 15 changed files with 198 additions and 12 deletions.
1 change: 1 addition & 0 deletions docs/tr1/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- added `/nextlevel` alias to `/endlevel` console command
- added `/quit` alias to `/exit` console command
- added an option to toggle the in-game UI, such as healthbars and ammo text (#1656)
- added the ability to cycle through console prompt history (#1571)
- changed the easter egg console command to pack more punch
- changed `/set` console command to do fuzzy matching (LostArtefacts/libtrx#38)
- fixed console caret position off by a couple of pixels (regression from 3.0)
Expand Down
1 change: 1 addition & 0 deletions docs/tr2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
- added `/sfx` command
- added `/nextlevel` alias to `/endlevel` console command
- added `/quit` alias to `/exit` console command
- added the ability to cycle through console prompt history (#1571)
- changed `/set` console command to do fuzzy matching (LostArtefacts/libtrx#38)
- fixed crash in the `/set` console command (regression from 0.3)
- fixed using console in cutscenes immediately exiting the game (regression from 0.3)
Expand Down
1 change: 1 addition & 0 deletions src/libtrx/config/file.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "config/file.h"

#include "filesystem.h"
#include "game/console/history.h"
#include "log.h"
#include "memory.h"

Expand Down
4 changes: 4 additions & 0 deletions src/libtrx/game/console/common.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "game/console/common.h"

#include "./internal.h"
#include "game/console/extern.h"
#include "game/game_string.h"
#include "game/ui/widgets/console.h"
Expand All @@ -18,6 +19,7 @@ static UI_WIDGET *m_Console;
void Console_Init(void)
{
m_Console = UI_Console_Create();
Console_History_Init();
}

void Console_Shutdown(void)
Expand All @@ -27,6 +29,8 @@ void Console_Shutdown(void)
m_Console = NULL;
}

Console_History_Shutdown();

m_IsOpened = false;
}

Expand Down
91 changes: 91 additions & 0 deletions src/libtrx/game/console/history.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include "game/console/history.h"

#include "config/file.h"
#include "memory.h"
#include "utils.h"
#include "vector.h"

#define MAX_HISTORY_ENTRIES 30

VECTOR *m_History = NULL;
static const char *m_Path = "cfg/" PROJECT_NAME "_console_history.json5";

void M_LoadFromJSON(JSON_OBJECT *const root_obj)
{
JSON_ARRAY *const arr = JSON_ObjectGetArray(root_obj, "entries");
if (arr == NULL) {
return;
}

Console_History_Clear();
for (size_t i = 0; i < arr->length; i++) {
const char *const line = JSON_ArrayGetString(arr, i, NULL);
if (line != NULL) {
Console_History_Append(line);
}
}
}

void M_DumpToJSON(JSON_OBJECT *const root_obj)
{
JSON_ARRAY *const arr = JSON_ArrayNew();

bool has_elements = false;
for (int32_t i = 0; i < Console_History_GetLength(); i++) {
JSON_ArrayAppendString(arr, Console_History_Get(i));
has_elements = true;
}

if (has_elements) {
JSON_ObjectAppendArray(root_obj, "entries", arr);
} else {
JSON_ArrayFree(arr);
}
}

void Console_History_Init(void)
{
m_History = Vector_Create(sizeof(char *));
ConfigFile_Read(m_Path, &M_LoadFromJSON);
}

void Console_History_Shutdown(void)
{
if (m_History != NULL) {
ConfigFile_Write(m_Path, &M_DumpToJSON);
for (int32_t i = m_History->count - 1; i >= 0; i--) {
char *const prompt = *(char **)Vector_Get(m_History, i);
Memory_Free(prompt);
}
Vector_Free(m_History);
m_History = NULL;
}
}

int32_t Console_History_GetLength(void)
{
return m_History->count;
}

void Console_History_Clear(void)
{
Vector_Clear(m_History);
}

void Console_History_Append(const char *const prompt)
{
if (m_History->count == MAX_HISTORY_ENTRIES) {
Vector_RemoveAt(m_History, 0);
}
char *prompt_copy = Memory_DupStr(prompt);
Vector_Add(m_History, &prompt_copy);
}

const char *Console_History_Get(const int32_t idx)
{
if (idx < 0 || idx >= m_History->count) {
return NULL;
}
const char *const prompt = *(char **)Vector_Get(m_History, idx);
return prompt;
}
4 changes: 4 additions & 0 deletions src/libtrx/game/console/internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#pragma once

void Console_History_Init(void);
void Console_History_Shutdown(void);
76 changes: 64 additions & 12 deletions src/libtrx/game/ui/widgets/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "game/clock.h"
#include "game/console/common.h"
#include "game/console/history.h"
#include "game/text.h"
#include "game/ui/common.h"
#include "game/ui/events.h"
Expand All @@ -16,8 +17,9 @@
#include <string.h>

#define WINDOW_MARGIN 5
#define LOG_MARGIN 10
#define MAX_LOG_LINES 20
#define MAX_LISTENERS 4
#define LOG_MARGIN 10
#define LOG_SCALE 0.8
#define DELAY_PER_CHAR 0.2

Expand All @@ -28,17 +30,17 @@ typedef struct {
UI_WIDGET *spacer;
char *log_lines;
int32_t logs_on_screen;
int32_t history_idx;

int32_t listener1;
int32_t listener2;
int32_t listener3;

int32_t listeners[MAX_LISTENERS];
struct {
double expire_at;
UI_WIDGET *label;
} logs[MAX_LOG_LINES];
} UI_CONSOLE;

static void M_MoveHistoryUp(UI_CONSOLE *self);
static void M_MoveHistoryDown(UI_CONSOLE *self);
static void M_HandlePromptCancel(const EVENT *event, void *data);
static void M_HandlePromptConfirm(const EVENT *event, void *data);
static void M_HandleCanvasResize(const EVENT *event, void *data);
Expand All @@ -51,16 +53,44 @@ static void M_Control(UI_CONSOLE *self);
static void M_Draw(UI_CONSOLE *self);
static void M_Free(UI_CONSOLE *self);

static void M_MoveHistoryUp(UI_CONSOLE *const self)
{
self->history_idx--;
CLAMP(self->history_idx, 0, Console_History_GetLength());
const char *const new_prompt = Console_History_Get(self->history_idx);
if (new_prompt == NULL) {
UI_Prompt_ChangeText(self->prompt, "");
} else {
UI_Prompt_ChangeText(self->prompt, new_prompt);
}
}

static void M_MoveHistoryDown(UI_CONSOLE *const self)
{
self->history_idx++;
CLAMP(self->history_idx, 0, Console_History_GetLength());
const char *const new_prompt = Console_History_Get(self->history_idx);
if (new_prompt == NULL) {
UI_Prompt_ChangeText(self->prompt, "");
} else {
UI_Prompt_ChangeText(self->prompt, new_prompt);
}
}

static void M_HandlePromptCancel(const EVENT *const event, void *const data)
{
Console_Close();
}

static void M_HandlePromptConfirm(const EVENT *const event, void *const data)
{
UI_CONSOLE *const self = (UI_CONSOLE *)data;
const char *text = event->data;
Console_History_Append(text);
Console_Eval(text);
Console_Close();

self->history_idx = Console_History_GetLength();
}

static void M_HandleCanvasResize(const EVENT *event, void *data)
Expand All @@ -69,6 +99,24 @@ static void M_HandleCanvasResize(const EVENT *event, void *data)
UI_Stack_SetSize(self->container, M_GetWidth(self), M_GetHeight(self));
}

static void M_HandleKeyDown(const EVENT *const event, void *const user_data)
{
if (!Console_IsOpened()) {
return;
}

UI_CONSOLE *const self = user_data;
const UI_INPUT key = (UI_INPUT)(uintptr_t)event->data;

// clang-format off
switch (key) {
case UI_KEY_UP: M_MoveHistoryUp(self); break;
case UI_KEY_DOWN: M_MoveHistoryDown(self); break;
default: break;
}
// clang-format on
}

static void M_UpdateLogCount(UI_CONSOLE *const self)
{
self->logs_on_screen = 0;
Expand Down Expand Up @@ -114,9 +162,9 @@ static void M_Free(UI_CONSOLE *const self)
self->spacer->free(self->spacer);
self->prompt->free(self->prompt);
self->container->free(self->container);
UI_Events_Unsubscribe(self->listener1);
UI_Events_Unsubscribe(self->listener2);
UI_Events_Unsubscribe(self->listener3);
for (int32_t i = 0; i < MAX_LISTENERS; i++) {
UI_Events_Unsubscribe(self->listeners[i]);
}
Memory_Free(self);
}

Expand Down Expand Up @@ -151,12 +199,15 @@ UI_WIDGET *UI_Console_Create(void)

M_SetPosition(self, WINDOW_MARGIN, WINDOW_MARGIN);

self->listener1 = UI_Events_Subscribe(
"confirm", self->prompt, M_HandlePromptConfirm, NULL);
self->listener2 =
int32_t i = 0;
self->listeners[i++] = UI_Events_Subscribe(
"confirm", self->prompt, M_HandlePromptConfirm, self);
self->listeners[i++] =
UI_Events_Subscribe("cancel", self->prompt, M_HandlePromptCancel, NULL);
self->listener3 =
self->listeners[i++] =
UI_Events_Subscribe("canvas_resize", NULL, M_HandleCanvasResize, self);
self->listeners[i++] =
UI_Events_Subscribe("key_down", NULL, M_HandleKeyDown, self);

return (UI_WIDGET *)self;
}
Expand All @@ -165,6 +216,7 @@ void UI_Console_HandleOpen(UI_WIDGET *const widget)
{
UI_CONSOLE *const self = (UI_CONSOLE *)widget;
UI_Prompt_SetFocus(self->prompt, true);
self->history_idx = Console_History_GetLength();
}

void UI_Console_HandleClose(UI_WIDGET *const widget)
Expand Down
10 changes: 10 additions & 0 deletions src/libtrx/game/ui/widgets/prompt.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ static void M_HandleKeyDown(const EVENT *const event, void *const user_data)
case UI_KEY_BACK: M_DeleteCharBack(self); break;
case UI_KEY_RETURN: M_Confirm(self); break;
case UI_KEY_ESCAPE: M_Cancel(self); break;
default: break;
}
// clang-format on
}
Expand Down Expand Up @@ -305,3 +306,12 @@ void UI_Prompt_Clear(UI_WIDGET *const widget)
UI_PROMPT *const self = (UI_PROMPT *)widget;
M_Clear(self);
}

void UI_Prompt_ChangeText(UI_WIDGET *widget, const char *new_text)
{
UI_PROMPT *const self = (UI_PROMPT *)widget;
Memory_FreePointer(&self->current_text);
self->current_text = Memory_DupStr(new_text);
self->caret_pos = strlen(new_text);
M_UpdateCaretLabel(self);
}
8 changes: 8 additions & 0 deletions src/libtrx/include/libtrx/game/console/history.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

#include <stdint.h>

int32_t Console_History_GetLength(void);
void Console_History_Clear(void);
void Console_History_Append(const char *prompt);
const char *Console_History_Get(int32_t idx);
2 changes: 2 additions & 0 deletions src/libtrx/include/libtrx/game/ui/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "./events.h"

typedef enum {
UI_KEY_UP,
UI_KEY_DOWN,
UI_KEY_LEFT,
UI_KEY_RIGHT,
UI_KEY_HOME,
Expand Down
1 change: 1 addition & 0 deletions src/libtrx/include/libtrx/game/ui/widgets/prompt.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ void UI_Prompt_SetSize(UI_WIDGET *widget, int32_t width, int32_t height);

void UI_Prompt_SetFocus(UI_WIDGET *widget, bool is_focused);
void UI_Prompt_Clear(UI_WIDGET *widget);
void UI_Prompt_ChangeText(UI_WIDGET *widget, const char *new_text);

extern const char *UI_Prompt_GetPromptChar(void);
extern int32_t UI_Prompt_GetCaretFlashRate(void);
6 changes: 6 additions & 0 deletions src/libtrx/include/libtrx/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,9 @@

#define MKTAG(a, b, c, d) \
((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24))

#if TR_VERSION == 1
#define PROJECT_NAME "TR1X"
#elif TR_VERSION == 2
#define PROJECT_NAME "TR2X"
#endif
1 change: 1 addition & 0 deletions src/libtrx/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ sources = [
'game/console/cmd/sfx.c',
'game/console/cmd/teleport.c',
'game/console/common.c',
'game/console/history.c',
'game/game_string.c',
'game/items.c',
'game/objects/names.c',
Expand Down
2 changes: 2 additions & 0 deletions src/tr1/game/ui/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ UI_INPUT UI_TranslateInput(uint32_t system_keycode)
{
// clang-format off
switch (system_keycode) {
case SDLK_UP: return UI_KEY_UP;
case SDLK_DOWN: return UI_KEY_DOWN;
case SDLK_LEFT: return UI_KEY_LEFT;
case SDLK_RIGHT: return UI_KEY_RIGHT;
case SDLK_HOME: return UI_KEY_HOME;
Expand Down
2 changes: 2 additions & 0 deletions src/tr2/game/ui/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ UI_INPUT UI_TranslateInput(uint32_t system_keycode)
{
// clang-format off
switch (system_keycode) {
case VK_UP: return UI_KEY_UP;
case VK_DOWN: return UI_KEY_DOWN;
case VK_LEFT: return UI_KEY_LEFT;
case VK_RIGHT: return UI_KEY_RIGHT;
case VK_HOME: return UI_KEY_HOME;
Expand Down

0 comments on commit 8bab311

Please sign in to comment.