From 384e52c7d15f8f826c18b322528d6014c14575f9 Mon Sep 17 00:00:00 2001 From: superp00t Date: Wed, 16 Aug 2023 16:37:38 -0400 Subject: [PATCH] feat(console): limited console implementation --- src/console/CMakeLists.txt | 1 + src/console/CVar.cpp | 49 ++- src/console/CVar.hpp | 4 + src/console/Client.cpp | 5 +- src/console/Command.cpp | 225 +++++++++++- src/console/Command.hpp | 69 +++- src/console/Console.cpp | 25 ++ src/console/Console.hpp | 10 + src/console/Handlers.cpp | 157 ++++++++- src/console/Line.cpp | 245 +++++++++++++ src/console/Line.hpp | 44 +++ src/console/Screen.cpp | 329 +++++++++++++++++- src/console/Screen.hpp | 38 ++ .../command/console/AppendLogToFile.cpp | 6 + .../command/console/BackGroundColor.cpp | 6 + src/console/command/console/BufferSize.cpp | 6 + src/console/command/console/CharSpacing.cpp | 6 + src/console/command/console/ClearConsole.cpp | 6 + src/console/command/console/CloseConsole.cpp | 7 + .../command/console/CurrentSettings.cpp | 6 + .../command/console/DefaultSettings.cpp | 6 + src/console/command/console/Font.cpp | 6 + src/console/command/console/FontColor.cpp | 6 + src/console/command/console/FontSize.cpp | 6 + src/console/command/console/Help.cpp | 111 ++++++ .../command/console/HighLightColor.cpp | 6 + src/console/command/console/Proportional.cpp | 6 + src/console/command/console/RepeatHandler.cpp | 7 + src/console/command/console/Ver.cpp | 7 + src/console/command/default/Quit.cpp | 7 + src/console/command/default/SetMap.cpp | 5 + 31 files changed, 1370 insertions(+), 47 deletions(-) create mode 100644 src/console/Line.cpp create mode 100644 src/console/Line.hpp create mode 100644 src/console/command/console/AppendLogToFile.cpp create mode 100644 src/console/command/console/BackGroundColor.cpp create mode 100644 src/console/command/console/BufferSize.cpp create mode 100644 src/console/command/console/CharSpacing.cpp create mode 100644 src/console/command/console/ClearConsole.cpp create mode 100644 src/console/command/console/CloseConsole.cpp create mode 100644 src/console/command/console/CurrentSettings.cpp create mode 100644 src/console/command/console/DefaultSettings.cpp create mode 100644 src/console/command/console/Font.cpp create mode 100644 src/console/command/console/FontColor.cpp create mode 100644 src/console/command/console/FontSize.cpp create mode 100644 src/console/command/console/Help.cpp create mode 100644 src/console/command/console/HighLightColor.cpp create mode 100644 src/console/command/console/Proportional.cpp create mode 100644 src/console/command/console/RepeatHandler.cpp create mode 100644 src/console/command/console/Ver.cpp create mode 100644 src/console/command/default/Quit.cpp create mode 100644 src/console/command/default/SetMap.cpp diff --git a/src/console/CMakeLists.txt b/src/console/CMakeLists.txt index 5c38523..42c8794 100644 --- a/src/console/CMakeLists.txt +++ b/src/console/CMakeLists.txt @@ -1,5 +1,6 @@ file(GLOB PRIVATE_SOURCES "*.cpp" + "command/*/*.cpp" ) add_library(console STATIC diff --git a/src/console/CVar.cpp b/src/console/CVar.cpp index 424e5a2..cf30d5d 100644 --- a/src/console/CVar.cpp +++ b/src/console/CVar.cpp @@ -68,8 +68,7 @@ CVar* CVar::Register(const char* name, const char* help, uint32_t flags, const c var->m_flags |= 0x80; } - // TODO - // ConsoleCommandRegister(var->m_key.GetString(), &CvarCommandHandler, category, help); + ConsoleCommandRegister(name, CvarCommandHandler, CATEGORY(category), help); } return var; @@ -161,3 +160,49 @@ int32_t CVar::Update() { return 1; } + +int32_t CvarCommandHandler(const char* command, const char* arguments) { + auto cvar = CVar::Lookup(command); + STORM_ASSERT(cvar); + + while (*arguments == ' ') { + arguments++; + } + + if (arguments[0] != '\0') { + cvar->Set(arguments, true, true, false, false); + return 1; + } + + auto value = cvar->m_stringValue.GetString(); + + ConsoleWriteA("CVar \"%s\" is \"%s\"", DEFAULT_COLOR, command, value ? value : ""); + return 1; +} + +int32_t CvarListCommandHandler(const char* command, const char* arguments) { + char text[256]; + char text2[256]; + + for (auto i = CVar::s_registeredCVars.Head(); i != nullptr; i = CVar::s_registeredCVars.Next(i)) { + SStrPrintf(text, sizeof(text), " \"%s\" is \"%s\"", i->m_key.m_str, i->m_stringValue); + + if (i->m_defaultValue.GetString()) { + if (SStrCmp(i->m_stringValue.GetString(), i->m_defaultValue.GetString(), STORM_MAX_STR)) { + SStrPrintf(text2, sizeof(text2), " (default \"%s\")", i->m_defaultValue); + SStrPack(text, text2, sizeof(text)); + } + } + + if (i->m_resetValue.GetString()) { + if (SStrCmp(i->m_stringValue.GetString(), i->m_resetValue.GetString(), STORM_MAX_STR)) { + SStrPrintf(text2, sizeof(text2), " (reset \"%s\")", i->m_resetValue); + SStrPack(text, text2, sizeof(text)); + } + } + + ConsoleWrite(text, DEFAULT_COLOR); + } + + return 1; +} diff --git a/src/console/CVar.hpp b/src/console/CVar.hpp index f37b1e7..5cafccd 100644 --- a/src/console/CVar.hpp +++ b/src/console/CVar.hpp @@ -38,4 +38,8 @@ class CVar : public TSHashObject { int32_t Update(); }; +int32_t CvarCommandHandler(const char* command, const char* arguments); + +int32_t CvarListCommandHandler(const char* command, const char* arguments); + #endif diff --git a/src/console/Client.cpp b/src/console/Client.cpp index 24a5c84..b9709cf 100644 --- a/src/console/Client.cpp +++ b/src/console/Client.cpp @@ -1,7 +1,10 @@ #include "console/Client.hpp" +#include "console/Command.hpp" void ConsoleInitializeClientCommand() { - // TODO + ConsoleCommandInitialize(); + ConsoleInitializeCommonCommand(); + ConsoleInitializeDebugCommand(); } void ConsoleInitializeClientCVar(const char* a1) { diff --git a/src/console/Command.cpp b/src/console/Command.cpp index 0d31b38..26f45fe 100644 --- a/src/console/Command.cpp +++ b/src/console/Command.cpp @@ -1,5 +1,11 @@ #include "console/Command.hpp" +#include "console/Line.hpp" + #include +#include + +#include +#include int32_t ValidateFileName(const char* filename) { if (SStrStr(filename, "..") || SStrStr(filename, "\\")) { @@ -22,6 +28,47 @@ int32_t ValidateFileName(const char* filename) { TSHashTable g_consoleCommandHash; char g_commandHistory[HISTORY_DEPTH][CMD_BUFFER_SIZE]; uint32_t g_commandHistoryIndex; +char g_ExecBuffer[CONSOLE_EXEC_BUFFER_SIZE] = {0}; +EXECMODE g_ExecCreateMode = EM_NOTACTIVE; + +int32_t AddLineToExecFile(const char* currentLine) { + char stringToWrite[STORM_MAX_PATH]; + + if (g_ExecCreateMode != EM_PROMPTOVERWRITE) { + if (!SStrCmpI(currentLine, "end", STORM_MAX_STR)) { + if (g_ExecCreateMode != EM_APPEND) { + g_ExecCreateMode = EM_WRITEFILE; + } + + return 1; + } + + SStrPrintf(stringToWrite, sizeof(stringToWrite), "%s\n", currentLine); + + if (((sizeof(g_ExecBuffer)-1) - SStrLen(g_ExecBuffer)) != SStrLen(stringToWrite)){ + SStrPack(g_ExecBuffer, stringToWrite, sizeof(g_ExecBuffer)); + } + + return 0; + } + + if (currentLine[0] == 'n') { + ConsoleWrite("Canceled File Creation", ECHO_COLOR); + g_ExecCreateMode = EM_NOTACTIVE; + return 0; + } + + if (currentLine[0] != 'y') { + ConsoleWrite("You must type 'y' to confirm overwrite. Process aborted!", ERROR_COLOR); + g_ExecCreateMode = EM_NOTACTIVE; + return 0; + } + + // TODO + + return 1; +} + void ConsoleCommandDestroy() { g_consoleCommandHash.Clear(); @@ -32,6 +79,11 @@ char* ConsoleCommandHistory(uint32_t index) { return g_commandHistory[((g_commandHistoryIndex + (HISTORY_DEPTH - 1) - index) & (HISTORY_DEPTH - 1))]; } +void AddToHistory(const char* command) { + SStrCopy(g_commandHistory[g_commandHistoryIndex], command, CONSOLE_LINE_LENGTH); + g_commandHistoryIndex = (g_commandHistoryIndex + 1) & (HISTORY_DEPTH-1); +} + uint32_t ConsoleCommandHistoryDepth() { return HISTORY_DEPTH; } @@ -40,7 +92,7 @@ void ConsoleCommandInitialize() { ConsoleCommandRegister("help", ConsoleCommand_Help, CONSOLE, "Provides help information about a command."); } -int32_t ConsoleCommandRegister(const char* command, int32_t (*handler)(const char*, const char*), CATEGORY category, const char* helpText) { +int32_t ConsoleCommandRegister(const char* command, COMMANDHANDLER handler, CATEGORY category, const char* helpText) { STORM_ASSERT(command); STORM_ASSERT(handler); @@ -52,10 +104,9 @@ int32_t ConsoleCommandRegister(const char* command, int32_t (*handler)(const cha // Register the new command auto commandPtr = g_consoleCommandHash.New(command, 0, 0); - commandPtr->command = command; - commandPtr->handler = handler; - commandPtr->helpText = helpText; - commandPtr->category = category; + commandPtr->m_handler = handler; + commandPtr->m_helpText = helpText; + commandPtr->m_category = category; return 1; } @@ -69,18 +120,162 @@ void ConsoleCommandUnregister(const char* command) { } } -int32_t ConsoleCommand_Help(const char* command, const char* arguments) { - // TODO - return 0; +CONSOLECOMMAND* ParseCommand(const char* commandLine, const char** command, char* arguments, size_t argsize) { + STORM_ASSERT(commandLine); + + auto string = commandLine; + + static char cmd[32] = { 0 }; + + auto cmdptr = &cmd[0]; + + int32_t end = CONSOLE_MAX_CMD_LENGTH; + int32_t i = 0; + + while (i < end) { + int32_t chars; + + auto code = SUniSGetUTF8(reinterpret_cast(string), &chars); + + if (code == -1 || code == ' ' || chars > CONSOLE_MAX_CMD_LENGTH) { + break; + } + + if (chars) { + for (size_t c = 0; c < chars; c++) { + *cmdptr = *string; + cmdptr += chars; + string += chars; + } + } + + i += chars; + } + + *cmdptr = '\0'; + + if (command) { + *command = cmd; + } + + auto argptr = arguments; + + if (arguments) { + int32_t chars; + + auto code = SUniSGetUTF8(reinterpret_cast(string), &chars); + + // Discard space + while(code != -1 && code == ' ') { + string += chars; + code = SUniSGetUTF8(reinterpret_cast(string), &chars); + } + + SStrCopy(argptr, string, argsize); + + auto len = SStrLen(argptr); + + while (len > 0 && (argptr[len-1] == ' ')) { + len--; + argptr[len] = '\0'; + } + + } + + return g_consoleCommandHash.Ptr(cmd); } -int32_t ConsoleCommand_Quit(const char* command, const char* arguments) { - // TODO - // ConsolePostClose() - return 0; +void MakeCommandCurrent(CONSOLELINE* lineptr, char* command) { + auto len = lineptr->inputstart; + lineptr->inputpos = len; + lineptr->chars = len; + lineptr->buffer[len] = '\0'; + + len = SStrLen(command); + ReserveInputSpace(lineptr, len); + + SStrCopy(lineptr->buffer + lineptr->inputpos, command, STORM_MAX_STR); + + len = lineptr->inputpos + len; + lineptr->inputpos = len; + lineptr->chars = len; } -int32_t ConsoleCommand_Ver(const char* command, const char* arguments) { - // TODO - return 0; +void ConsoleCommandExecute(char* commandLine, int32_t addToHistory) { + auto em = g_ExecCreateMode; + + if (em == EM_RECORDING || em == EM_PROMPTOVERWRITE || em == EM_APPEND) { + AddLineToExecFile(commandLine); + return; + } + + auto history = ConsoleCommandHistory(0); + + if (addToHistory && (history == nullptr || SStrCmp(commandLine, history, STORM_MAX_STR))) { + AddToHistory(commandLine); + } + + const char* command = nullptr; + auto arguments = reinterpret_cast(SMemAlloc(CMD_BUFFER_SIZE, __FILE__, __LINE__, 0)); + + auto cmd = ParseCommand(commandLine, &command, arguments, CMD_BUFFER_SIZE); + + if (cmd) { + cmd->m_handler(command, arguments); + } else { + ConsoleWrite("Unknown command", DEFAULT_COLOR); + } + + if (arguments) { + SMemFree(arguments, __FILE__, __LINE__, 0); + } +} + +static ConsoleCommandList s_consoleSpecificCommands[] = { + { "fontcolor", ConsoleCommand_FontColor, "[ColorClassName] [Red 0-255] [Green 0-255] [Blue 0-255]" }, + { "bgcolor", ConsoleCommand_BackGroundColor, "[alpha 0-255] [Red 0-255] [Green 0-255] [Blue 0-255]" }, + { "highlightcolor", ConsoleCommand_HighLightColor, "[alpha 0-255] [Red 0-255] [Green 0-255] [Blue 0-255]" }, + { "fontsize", ConsoleCommand_FontSize, "[15-50] arbitrary font size" }, + { "font", ConsoleCommand_Font, "[fontname] make sure to use the .ttf file name" }, + { "consolelines", ConsoleCommand_BufferSize, "[number] number of lines to show in the console" }, + { "clear", ConsoleCommand_ClearConsole, "Clears the console buffer" }, + { "proportionaltext", ConsoleCommand_Proportional, "Toggles fixed-width text characters" }, + { "spacing", ConsoleCommand_CharSpacing, "[float] specifies inter-character spacing, in pixels" }, + { "settings", ConsoleCommand_CurrentSettings, "Shows current font and console settings" }, + { "default", ConsoleCommand_DefaultSettings, "Resets all the font and console settings" }, + { "closeconsole", ConsoleCommand_CloseConsole, "Closes the Console window" }, + { "repeat", ConsoleCommand_RepeatHandler, "Repeats a command" }, + { "AppendLogToFile", ConsoleCommand_AppendLogToFile, "[filename = ConsoleLogs/Log.txt] [numLines = all]" } +}; + +static ConsoleCommandList s_commonCommands[] = { + { "quit", ConsoleCommand_Quit, nullptr }, + { "ver", ConsoleCommand_Ver, nullptr }, + { "setmap", ConsoleCommand_SetMap, nullptr } +}; + +void RegisterConsoleCommandList(CATEGORY category, ConsoleCommandList list[], size_t count) { + size_t i = 0; + + while (i < count) { + auto& cmd = list[i]; + ConsoleCommandRegister(cmd.m_command, cmd.m_handler, category, cmd.m_helpText); + i++; + } +} + +void ConsoleInitializeScreenCommand() { + CONSOLE_REGISTER_LIST(CONSOLE, s_consoleSpecificCommands); +} + +void ConsoleCommandInitialize() { + ConsoleCommandRegister("help", ConsoleCommand_Help, CONSOLE, "Provides help information about a command."); +} + +void ConsoleInitializeCommonCommand() { + CONSOLE_REGISTER_LIST(DEFAULT, s_commonCommands); +} + +void ConsoleInitializeDebugCommand() { + // TODO } diff --git a/src/console/Command.hpp b/src/console/Command.hpp index 11f67a8..b97589e 100644 --- a/src/console/Command.hpp +++ b/src/console/Command.hpp @@ -4,11 +4,13 @@ #include #include -#define EXEC_BUFFER_SIZE 8192 -#define CMD_BUFFER_SIZE 1024 -#define MAX_CMD_LENGTH 64 -#define HISTORY_DEPTH 32 -#define NOHELP nullptr +#define CONSOLE_REGISTER_LIST(category, list) RegisterConsoleCommandList(category, list, std::size(list)) + +#define CONSOLE_EXEC_BUFFER_SIZE 8192 +#define CONSOLE_CMD_BUFFER_SIZE 1024 +#define CONSOLE_MAX_CMD_LENGTH 64 +#define CONSOLE_HISTORY_DEPTH 32 +#define CONSOLE_NOHELP nullptr enum CATEGORY { DEBUG, @@ -24,17 +26,26 @@ enum CATEGORY { LAST }; -struct CONSOLECOMMAND : TSHashObject { - const char* command; - int32_t (*handler)(const char*, const char*); - const char* helpText; - CATEGORY category; +typedef int32_t (*COMMANDHANDLER)(const char*, const char*); + +class CONSOLECOMMAND : public TSHashObject { + public: + COMMANDHANDLER m_handler; + const char* m_helpText; + CATEGORY m_category; +}; + +class ConsoleCommandList { + public: + const char* m_command; + COMMANDHANDLER m_handler; + const char* m_helpText; }; extern TSHashTable g_consoleCommandHash; -extern char g_commandHistory[HISTORY_DEPTH][CMD_BUFFER_SIZE]; +extern char g_commandHistory[CONSOLE_HISTORY_DEPTH][CONSOLE_CMD_BUFFER_SIZE]; extern uint32_t g_commandHistoryIndex; -extern char g_ExecBuffer[EXEC_BUFFER_SIZE]; +extern char g_ExecBuffer[CONSOLE_EXEC_BUFFER_SIZE]; void ConsoleCommandDestroy(); @@ -42,16 +53,44 @@ char* ConsoleCommandHistory(uint32_t index); uint32_t ConsoleCommandHistoryDepth(); +int32_t ConsoleCommandRegister(const char* command, COMMANDHANDLER handler, CATEGORY category, const char* helpText); + void ConsoleCommandInitialize(); -int32_t ConsoleCommandRegister(const char* command, int32_t (*handler)(const char*, const char*), CATEGORY category, const char* helpText); +void ConsoleInitializeCommonCommand(); + +void ConsoleInitializeDebugCommand(); + +void ConsoleInitializeScreenCommand(); + +void RegisterConsoleCommandList(CATEGORY category, ConsoleCommandList list[], size_t count); void ConsoleCommandUnregister(const char* command); -int32_t ConsoleCommand_Help(const char* command, const char* arguments); +void ConsoleCommandExecute(char* commandLine, int32_t addToHistory); + +void MakeCommandCurrent(CONSOLELINE* lineptr, char* command); + +// Commands int32_t ConsoleCommand_Quit(const char* command, const char* arguments); - int32_t ConsoleCommand_Ver(const char* command, const char* arguments); +int32_t ConsoleCommand_SetMap(const char* command, const char* arguments); + +int32_t ConsoleCommand_Help(const char* command, const char* arguments); +int32_t ConsoleCommand_FontColor(const char* command, const char* arguments); +int32_t ConsoleCommand_BackGroundColor(const char* command, const char* arguments); +int32_t ConsoleCommand_HighLightColor(const char* command, const char* arguments); +int32_t ConsoleCommand_FontSize(const char* command, const char* arguments); +int32_t ConsoleCommand_Font(const char* command, const char* arguments); +int32_t ConsoleCommand_BufferSize(const char* command, const char* arguments); +int32_t ConsoleCommand_ClearConsole(const char* command, const char* arguments); +int32_t ConsoleCommand_Proportional(const char* command, const char* arguments); +int32_t ConsoleCommand_CharSpacing(const char* command, const char* arguments); +int32_t ConsoleCommand_CurrentSettings(const char* command, const char* arguments); +int32_t ConsoleCommand_DefaultSettings(const char* command, const char* arguments); +int32_t ConsoleCommand_CloseConsole(const char* command, const char* arguments); +int32_t ConsoleCommand_RepeatHandler(const char* command, const char* arguments); +int32_t ConsoleCommand_AppendLogToFile(const char* command, const char* arguments); #endif diff --git a/src/console/Console.cpp b/src/console/Console.cpp index 9ceb7f8..8bb1a29 100644 --- a/src/console/Console.cpp +++ b/src/console/Console.cpp @@ -1,8 +1,13 @@ #include "console/Console.hpp" +#include "event/Context.hpp" +#include "event/Event.hpp" static int32_t s_active; static int32_t s_consoleAccessEnabled; static KEY s_consoleKey = KEY_TILDE; +static float s_consoleLines = 10.0f; +static float s_fontHeight = 0.02f; +static float s_consoleHeight = s_consoleLines * s_fontHeight; static CONSOLERESIZESTATE s_consoleResizeState = CS_NONE; int32_t ConsoleAccessGetEnabled() { @@ -17,6 +22,18 @@ int32_t ConsoleGetActive() { return s_active; } +float ConsoleGetFontHeight() { + return s_fontHeight; +} + +float ConsoleGetHeight() { + return s_consoleHeight; +} + +float ConsoleGetLines() { + return s_consoleLines; +} + KEY ConsoleGetHotKey() { return s_consoleKey; } @@ -36,3 +53,11 @@ void ConsoleSetHotKey(KEY hotkey) { void ConsoleSetResizeState(CONSOLERESIZESTATE state) { s_consoleResizeState = state; } + +void ConsoleSetHeight(float height) { + s_consoleHeight = height; +} + +void ConsolePostClose() { + EventPostCloseEx(EventGetCurrentContext()); +} diff --git a/src/console/Console.hpp b/src/console/Console.hpp index 82d967c..1421189 100644 --- a/src/console/Console.hpp +++ b/src/console/Console.hpp @@ -11,6 +11,12 @@ void ConsoleAccessSetEnabled(int32_t enable); int32_t ConsoleGetActive(); +float ConsoleGetFontHeight(); + +float ConsoleGetLines(); + +float ConsoleGetHeight(); + KEY ConsoleGetHotKey(); CONSOLERESIZESTATE ConsoleGetResizeState(); @@ -19,6 +25,10 @@ void ConsoleSetActive(int32_t active); void ConsoleSetHotKey(KEY hotkey); +void ConsoleSetHeight(float height); + void ConsoleSetResizeState(CONSOLERESIZESTATE state); +void ConsolePostClose(); + #endif // ifndef CONSOLE_CONSOLE_HPP diff --git a/src/console/Handlers.cpp b/src/console/Handlers.cpp index 38880bb..9ac0cb4 100644 --- a/src/console/Handlers.cpp +++ b/src/console/Handlers.cpp @@ -1,13 +1,34 @@ #include "console/Handlers.hpp" +#include "console/Line.hpp" #include "console/Console.hpp" +#include "console/Command.hpp" #include "console/Screen.hpp" #include "event/Event.hpp" #include +static int32_t s_historyIndex = 0; + namespace { int32_t OnChar(const EVENT_DATA_CHAR* data, void* param) { - // TODO + char character[2]; + + if (ConsoleAccessGetEnabled() && EventIsKeyDown(ConsoleGetHotKey())) { + return 0; + } + + if (ConsoleGetActive()) { + character[0] = char(data->ch); + character[1] = 0; + + PasteInInputLine(character); + ResetHighlight(); + return 0; + } + + // SUniSPutUTF8(data->ch, character); + + return 1; } @@ -27,7 +48,7 @@ int32_t OnKeyDown(const EVENT_DATA_KEY* data, void* param) { // Reset the highlight when toggled off if (!ConsoleGetActive()) { - // TODO ResetHighlight(); + ResetHighlight(); } return 0; @@ -37,6 +58,70 @@ int32_t OnKeyDown(const EVENT_DATA_KEY* data, void* param) { return 1; } + auto anyControl = (1 << KEY_LCONTROL) | (1 << KEY_RCONTROL); + + auto line = GetInputLine(); + + switch (data->key) { + case KEY_ESCAPE: + if (line->inputpos < line->inputstart || line->inputpos == line->inputstart) { + ConsoleSetActive(0); + } else { + line->inputpos = line->inputstart; + line->chars = line->inputstart; + line->buffer[line->inputstart] = '\0'; + SetInputString(line->buffer); + } + break; + case KEY_PAGEUP: + MoveLinePtr(1, data->metaKeyState); + break; + case KEY_PAGEDOWN: + MoveLinePtr(0, data->metaKeyState); + break; + case KEY_ENTER: + if (line->inputstart <= line->inputpos && line->inputpos != line->inputstart) { + line->inputpos = 0; + GenerateNodeString(line); + ConsoleCommandExecute(line->buffer + line->inputstart, 1); + s_historyIndex = -1; + } + break; + case KEY_HOME: + break; + case KEY_END: + break; + case KEY_C: + if (data->metaKeyState & anyControl) { + CutHighlightToClipboard(); + } + break; + case KEY_V: + if (data->metaKeyState & anyControl) { + PasteClipboardToHighlight(); + } + break; + case KEY_LEFT: + if (line->inputstart <= line->inputpos && line->inputpos != line->inputstart) { + line->inputpos--; + } + break; + case KEY_RIGHT: + if (line->inputpos < line->chars) { + line->inputpos++; + } + break; + + case KEY_BACKSPACE: + BackspaceLine(line); + break; + } + + if (data->key != KEY_TAB && data->key != KEY_LSHIFT && data->key != KEY_RSHIFT && data->key != KEY_LALT && data->key != KEY_RALT && !(data->metaKeyState & anyControl)) { + // s_completionMode = 0; + ResetHighlight(); + } + // TODO return 0; } @@ -52,17 +137,79 @@ int32_t OnKeyUp(const EVENT_DATA_KEY* data, void* param) { } int32_t OnMouseDown(const EVENT_DATA_MOUSE* data, void* param) { - // TODO + auto consoleHeight = ConsoleGetHeight(); + auto fontHeight = ConsoleGetFontHeight(); + + if (EventIsKeyDown(ConsoleGetHotKey()) || !ConsoleGetActive() || (1.0f - consoleHeight) > data->y) { + return 1; + } + + float clickPos = 1.0f - data->y; + + if (clickPos < (std::min(consoleHeight, 1.0f) - (fontHeight * 0.75f)) || clickPos > consoleHeight) { + ResetHighlight(); + + auto line = GetLineAtMousePosition(data->y); + + if (line) { + SetHighlightCopyText(line->buffer); + SetHighlightState(HS_HIGHLIGHTING); + + float v7 = 1.0f - (consoleHeight - (fontHeight * 0.75f) - (fontHeight) - ((consoleHeight - clickPos) / fontHeight - 1.0) * fontHeight); + + auto hRect = GetHighlightRect(); + + hRect.bottom = v7; + hRect.top = v7 - fontHeight; + + SetHighlightStart(v7); + SetHighlightEnd(v7); + + UpdateHighlight(); + + return 0; + } + + ResetHighlightCopyText(); + return 0; + } + + ResetHighlight(); + + ConsoleSetResizeState(CS_STRETCH); + return 1; } int32_t OnMouseMove(const EVENT_DATA_MOUSE* data, void* param) { - // TODO + if (EventIsKeyDown(ConsoleGetHotKey()) || !ConsoleGetActive()) { + return 1; + } + + if (ConsoleGetResizeState() == CS_STRETCH) { + auto newHeight = std::max(1.0f - data->y, ConsoleGetFontHeight()); + ConsoleSetHeight(newHeight); + } else if ((1.0f - ConsoleGetHeight()) > data->y) { + return 1; + } + + SetHighlightEnd(data->x); + + if (GetHighlightState() == HS_HIGHLIGHTING) { + UpdateHighlight(); + } + return 1; } int32_t OnMouseUp(const EVENT_DATA_MOUSE* data, void* param) { - // TODO + if (EventIsKeyDown(ConsoleGetHotKey()) || !ConsoleGetActive()) { + return 1; + } + + SetHighlightState(HS_ENDHIGHLIGHT); + ConsoleSetResizeState(CS_NONE); + return 1; } diff --git a/src/console/Line.cpp b/src/console/Line.cpp new file mode 100644 index 0000000..b1e6f25 --- /dev/null +++ b/src/console/Line.cpp @@ -0,0 +1,245 @@ + +#include "console/Line.hpp" +#include "console/Types.hpp" +#include "console/Console.hpp" +#include "console/Screen.hpp" +#include "gx/Device.hpp" + +#include +#include + +static SCritSect s_critsect; +// In this list: +// The head = the input line. +// The tail = the oldest line printed. +static STORM_LIST(CONSOLELINE) s_linelist; +// Pointer to the current line. Determines what region of the console history gets rendered. +static CONSOLELINE* s_currlineptr = nullptr; +static uint32_t s_NumLines = 0; + +void EnforceMaxLines() { + if (s_NumLines <= CONSOLE_LINES_MAX) { + return; + } + + // Pop oldest line off the list + auto lineptr = s_linelist.Tail(); + + if (lineptr == nullptr) { + lineptr = s_currlineptr; + } + + if (lineptr == nullptr) { + return; + } + + // Clean up oldest line. + s_linelist.UnlinkNode(lineptr); + s_linelist.DeleteNode(lineptr); + + s_NumLines--; +} + +CONSOLELINE* GetInputLine() { + auto head = s_linelist.Head(); + + // If the list is empty, or the list's head is an entered input-line, + // Create a fresh input line, with "> " prefixed before the caret. + if (!head || head->inputpos == 0) { + auto l = SMemAlloc(sizeof(CONSOLELINE), __FILE__, __LINE__, 0); + auto line = new(l) CONSOLELINE(); + line->buffer = reinterpret_cast(SMemAlloc(CONSOLE_LINE_PREALLOC, __FILE__, __LINE__, 0)); + line->charsalloc = CONSOLE_LINE_PREALLOC; + + s_linelist.LinkToHead(line); + + SStrCopy(line->buffer, "> ", line->charsalloc); + SetInputString(line->buffer); + auto chars = SStrLen(line->buffer); + s_NumLines++; + line->inputstart = chars; + line->inputpos = chars; + line->chars = chars; + line->colorType = INPUT_COLOR; + + s_currlineptr = line; + + EnforceMaxLines(); + + return line; + } + + return head; +} + +CONSOLELINE* GetLineAtMousePosition(float y) { + // Loop through linelist to find line at mouse position + int32_t linePos = static_cast((ConsoleGetHeight() - (1.0 - y)) / ConsoleGetFontHeight()); + + if (linePos == 1) { + return s_linelist.Head(); + } + + if (s_currlineptr != s_linelist.Head()) { + linePos--; + } + + CONSOLELINE* line = s_currlineptr; + + while (linePos > 1) { + linePos--; + + if (!line) { + line = s_linelist.Head(); + } + + if (line == nullptr) { + return nullptr; + } + + line = line->Next(); + } + + return line; +} + +void ReserveInputSpace(CONSOLELINE* line, size_t len) { + size_t newsize = line->chars + len; + if (newsize >= line->charsalloc) { + while (line->charsalloc <= newsize) { + line->charsalloc += CONSOLE_LINE_PREALLOC; + } + + auto buffer = reinterpret_cast(SMemAlloc(line->charsalloc, __FILE__, __LINE__, 0)); + SStrCopy(buffer, line->buffer, line->charsalloc); + SMemFree(line->buffer, __FILE__, __LINE__, 0x0); + line->buffer = buffer; + } +} + +void ConsoleWrite(const char* str, COLOR_T color) { + if (g_theGxDevicePtr == nullptr || str[0] == '\0') { + return; + } + + s_critsect.Enter(); + + auto l = reinterpret_cast(SMemAlloc(sizeof(CONSOLELINE), __FILE__, __LINE__, 0)); + auto lineptr = new(l) CONSOLELINE(); + + auto head = s_linelist.Head(); + + if (head == nullptr || head->inputpos == 0) { + // Attach console line to head + s_linelist.LinkToHead(lineptr); + } else { + // Attach console line between head and head-1 + s_linelist.LinkNode(lineptr, 1, head->Prev()); + } + + size_t len = SStrLen(str) + 1; + lineptr->chars = len; + lineptr->charsalloc = len; + lineptr->buffer = reinterpret_cast(SMemAlloc(len, __FILE__, __LINE__, 0)); + lineptr->colorType = color; + + SStrCopy(lineptr->buffer, str, STORM_MAX_STR); + + GenerateNodeString(lineptr); + + s_NumLines++; + + EnforceMaxLines(); + // + + s_critsect.Leave(); +} + +void ConsoleWriteA(const char* str, COLOR_T color, ...) { + char buffer[1024] = {0}; + + if (str != nullptr && str[0] != '\0') { + va_list list; + va_start(list, color); + vsnprintf(buffer, sizeof(buffer), str, list); + va_end(list); + + ConsoleWrite(buffer, color); + } +} + +void MoveLinePtr(int32_t direction, int32_t modifier) { + CONSOLELINE* lineptr = s_currlineptr; + + auto anyControl = (1 << KEY_LCONTROL) | (1 << KEY_RCONTROL); + + if (modifier & anyControl) { + for (int32_t i = 0; i < 10 && lineptr != nullptr; i++) { + CONSOLELINE* next; + + if (direction == 1) { + next = lineptr->m_link.Next(); + } else { + next = lineptr->m_link.Prev(); + } + + if (next != nullptr) { + lineptr = next; + } + } + } else { + // if (s_currlineptr == s_linelist.Head()) { + // s_currlineptr = s_currlineptr->Prev(); + // } + + if (direction == 1) { + lineptr = lineptr->m_link.Next(); + } else { + lineptr = lineptr->m_link.Prev(); + } + } + + if (lineptr) { + s_currlineptr = lineptr; + } +} + +void BackspaceLine(CONSOLELINE* line) { + if (line->inputstart <= line->inputpos && line->inputpos != line->inputstart) { + if (line->inputpos < line->chars) { + memmove(line->buffer + line->inputpos + -1, line->buffer + line->inputpos, (line->chars - line->inputpos) + 1); + } else { + line->buffer[line->inputpos - 1] = '\0'; + } + line->chars--; + line->inputpos--; + + SetInputString(line->buffer); + } +} + +CONSOLELINE* GetCurrentLine() { + return s_currlineptr; +} + +CONSOLELINE::~CONSOLELINE() { + if (this->buffer) { + SMemFree(this->buffer, __FILE__, __LINE__, 0); + } + + if (this->fontPointer) { + GxuFontDestroyString(this->fontPointer); + } +} + +void ConsoleClear() { + s_NumLines = 0; + + auto ptr = s_linelist.Head(); + + while (ptr) { + s_linelist.UnlinkNode(ptr); + s_linelist.DeleteNode(ptr); + ptr = s_linelist.Head(); + } +} diff --git a/src/console/Line.hpp b/src/console/Line.hpp new file mode 100644 index 0000000..625b1d9 --- /dev/null +++ b/src/console/Line.hpp @@ -0,0 +1,44 @@ +#ifndef CONSOLE_LINE_HPP +#define CONSOLE_LINE_HPP + +#include "console/Types.hpp" +#include "gx/Font.hpp" + +#include + +#define CONSOLE_LINES_MAX 256 +#define CONSOLE_LINE_LENGTH 1024 +#define CONSOLE_LINE_PREALLOC 16 + +class CONSOLELINE : public TSLinkedNode { + public: + char* buffer; + uint32_t chars; + uint32_t charsalloc; + uint32_t inputpos; + uint32_t inputstart; + COLOR_T colorType; + CGxString* fontPointer; + + ~CONSOLELINE(); +}; + +void ConsoleWrite(const char* str, COLOR_T color); +void ConsoleWriteA(const char* str, COLOR_T color, ...); + +void PasteInInputLine(char* characters); + +void MoveLinePtr(int32_t direction, int32_t modifier); + +void BackspaceLine(CONSOLELINE* line); + +void ReserveInputSpace(CONSOLELINE* line, size_t len); + +CONSOLELINE* GetInputLine(); +CONSOLELINE* GetCurrentLine(); + +CONSOLELINE* GetLineAtMousePosition(float y); + +void ConsoleClear(); + +#endif diff --git a/src/console/Screen.cpp b/src/console/Screen.cpp index 63b3821..cd2a0a2 100644 --- a/src/console/Screen.cpp +++ b/src/console/Screen.cpp @@ -1,6 +1,8 @@ #include "console/Screen.hpp" #include "console/Console.hpp" +#include "console/Command.hpp" #include "console/Handlers.hpp" +#include "console/Line.hpp" #include "console/Types.hpp" #include "gx/Buffer.hpp" #include "gx/Coordinate.hpp" @@ -10,23 +12,34 @@ #include "gx/Gx.hpp" #include "gx/RenderState.hpp" #include "gx/Screen.hpp" +#include #include #include #include static CGxStringBatch* s_batch; +static uint32_t s_baseTextFlags = 0x8; +static int32_t s_caret = 0; static float s_caretpixwidth; static float s_caretpixheight; -static float s_consoleLines = 10.0f; -static float s_fontHeight = 0.02f; -static float s_consoleHeight = s_consoleLines * s_fontHeight; +static float s_charSpacing = 0.0f; +static CGxString* s_inputString = nullptr; + static char s_fontName[STORM_MAX_PATH]; -static int32_t s_highlightState; static HLAYER s_layerBackground; static HLAYER s_layerText; static RECTF s_rect = { 0.0f, 1.0f, 1.0f, 1.0f }; static HTEXTFONT s_textFont; +static HIGHLIGHTSTATE s_highlightState = HS_NONE; +static RECTF s_hRect = { 0.0f, 0.0f, 0.0f, 0.0f }; +static float s_highlightHStart = 0.0f; +static float s_highlightHEnd = 0.0f; +static uint32_t s_highlightLeftCharIndex = 0; +static uint32_t s_highlightRightCharIndex = 0; +static int32_t s_highlightInput = 0; +static char s_copyText[HIGHLIGHT_COPY_SIZE] = { 0 }; + static CImVector s_colorArray[] = { { 0xFF, 0xFF, 0xFF, 0xFF }, // DEFAULT_COLOR { 0xFF, 0xFF, 0xFF, 0xFF }, // INPUT_COLOR @@ -70,7 +83,64 @@ void DrawBackground() { } void DrawHighLight() { - // TODO + uint16_t indices[] = { + 0, 1, 2, 3 + }; + + C3Vector position[] = { + { s_hRect.left, s_hRect.bottom, 0.0f }, + { s_hRect.right, s_hRect.bottom, 0.0f }, + { s_hRect.left, s_hRect.top, 0.0f }, + { s_hRect.right, s_hRect.top, 0.0f } + }; + + GxRsPush(); + + GxRsSet(GxRs_Lighting, 0); + GxRsSet(GxRs_BlendingMode, GxBlend_Alpha); + GxRsSet(GxRs_AlphaRef, CGxDevice::s_alphaRef[GxBlend_Alpha]); + + GxPrimLockVertexPtrs(4, position, sizeof(C3Vector), nullptr, 0, &s_colorArray[HIGHLIGHT_COLOR], 0, nullptr, 0, nullptr, 0, nullptr, 0); + GxDrawLockedElements(GxPrim_TriangleStrip, 4, indices); + GxPrimUnlockVertexPtrs(); + + GxRsPop(); +} + +void DrawCaret(C3Vector& caretpos) { + uint16_t indices[] = { + 0, 1, 2, 3 + }; + + float minX = caretpos.x; + float minY = caretpos.y; + + float maxX = caretpos.x + (s_caretpixwidth * 2); + float maxY = caretpos.y + ConsoleGetFontHeight(); + + C3Vector position[] = { + { minX, minY, 0.0f }, + { maxX, minY, 0.0f }, + { minX, maxY, 0.0f }, + { maxX, maxY, 0.0f } + }; + + GxRsPush(); + + GxRsSet(GxRs_Lighting, 0); + GxRsSet(GxRs_Fog, 0); + GxRsSet(GxRs_DepthTest, 0); + GxRsSet(GxRs_DepthWrite, 0); + GxRsSet(GxRs_Culling, 0); + GxRsSet(GxRs_PolygonOffset, 0.0f); + GxRsSet(GxRs_BlendingMode, GxBlend_Alpha); + GxRsSet(GxRs_AlphaRef, CGxDevice::s_alphaRef[GxBlend_Alpha]); + + GxPrimLockVertexPtrs(4, position, sizeof(C3Vector), nullptr, 0, &s_colorArray[INPUT_COLOR], 0, nullptr, 0, nullptr, 0, nullptr, 0); + GxDrawLockedElements(GxPrim_TriangleStrip, 4, indices); + GxPrimUnlockVertexPtrs(); + + GxRsPop(); } void PaintBackground(void* param, const RECTF* rect, const RECTF* visible, float elapsedSec) { @@ -83,12 +153,252 @@ void PaintBackground(void* param, const RECTF* rect, const RECTF* visible, float } } +void SetInputString(char* buffer) { + // s_highlightState = HS_NONE; + // s_hRect = { 0.0f, 0.0f, 0.0f, 0.0f }; + // s_highlightLeftCharIndex = 0; + // s_highlightRightCharIndex = 0; + // s_highlightInput = 0; + + if (s_inputString) { + GxuFontDestroyString(s_inputString); + } + + s_inputString = nullptr; + + auto fontHeight = ConsoleGetFontHeight(); + + if (buffer && buffer[0] != '\0') { + C3Vector pos = { 0.0f, 0.0f, 1.0f }; + + auto font = TextBlockGetFontPtr(s_textFont); + + GxuFontCreateString(font, buffer, fontHeight, pos, 1.0f, fontHeight, 0.0f, s_inputString, GxVJ_Middle, GxHJ_Left, s_baseTextFlags, s_colorArray[INPUT_COLOR], s_charSpacing, 1.0f); + } +} + +void PasteInInputLine(char* characters) { + auto len = SStrLen(characters); + + if (!len) { + return; + } + + auto line = GetInputLine(); + + ReserveInputSpace(line, len); + + if (line->inputpos < line->chars) { + if (len <= 1) { + memmove(&line->buffer[line->inputpos + 1], &line->buffer[line->inputpos], line->chars - (line->inputpos + 1)); + + line->buffer[line->inputpos] = *characters; + + line->inputpos++; + line->chars++; + } else { + auto input = reinterpret_cast(SMemAlloc(line->charsalloc, __FILE__, __LINE__, 0x0)); + SStrCopy(input, &line->buffer[line->inputpos], STORM_MAX_STR); + + auto buffer = reinterpret_cast(SMemAlloc(line->charsalloc, __FILE__, __LINE__, 0x0)); + SStrCopy(buffer, line->buffer, STORM_MAX_STR); + buffer[line->inputpos] = '\0'; + + SStrPack(buffer, characters, line->charsalloc); + + auto len = SStrLen(buffer); + + line->inputpos = len; + + SStrPack(buffer, input, line->charsalloc); + SStrCopy(line->buffer, buffer, STORM_MAX_STR); + + line->chars = SStrLen(line->buffer); + + if (input) { + SMemFree(input, __FILE__, __LINE__, 0); + } + + if (buffer) { + SMemFree(input, __FILE__, __LINE__, 0); + } + } + } else { + for (int32_t i = 0; i < len; i++) { + line->buffer[line->inputpos++] = characters[i]; + } + + line->buffer[line->inputpos] = '\0'; + line->chars = line->inputpos; + } + + SetInputString(line->buffer); +} + +void GenerateNodeString(CONSOLELINE* node) { + auto font = TextBlockGetFontPtr(s_textFont); + + if (font && node && node->buffer && node->buffer[0] != '\0') { + if (node->fontPointer) { + GxuFontDestroyString(node->fontPointer); + } + + C3Vector pos = { + 0.0f, 0.0f, 1.0f + }; + + auto fontHeight = ConsoleGetFontHeight(); + + GxuFontCreateString(font, node->buffer, fontHeight, pos, 1.0f, fontHeight, 0.0f, node->fontPointer, GxVJ_Middle, GxHJ_Left, s_baseTextFlags, s_colorArray[node->colorType], s_charSpacing, 1.0f); + BLIZZARD_ASSERT(node->fontPointer); + } +} + void PaintText(void* param, const RECTF* rect, const RECTF* visible, float elapsedSec) { - // TODO + if (s_rect.bottom >= 1.0f) { + return; + } + + static float carettime = 0.0f; + static C3Vector caretpos = { 0.0f, 0.0f, 0.0f }; + + // + carettime += elapsedSec; + if ((!s_caret && carettime > 0.2) || (carettime > 0.3)) { + s_caret = !s_caret; + carettime = 0; + } + + auto line = GetInputLine(); + + C3Vector pos = { + s_rect.left, + (ConsoleGetFontHeight() * 0.75f) + s_rect.bottom, + 1.0f + }; + + GxuFontClearBatch(s_batch); + + if (s_inputString) { + GxuFontSetStringPosition(s_inputString, pos); + GxuFontAddToBatch(s_batch, s_inputString); + } + + auto font = TextBlockGetFontPtr(s_textFont); + + if (line->inputpos) { + caretpos = pos; + + GxuFontGetTextExtent(font, line->buffer, line->inputpos, ConsoleGetFontHeight(), &caretpos.x, 0.0f, 1.0f, s_charSpacing, s_baseTextFlags); + + DrawCaret(caretpos); + } + + pos.y += ConsoleGetFontHeight(); + + for (auto lineptr = GetCurrentLine(); (lineptr && pos.y < 1.0); lineptr = lineptr->Next()) { + if (lineptr != line) { + if (lineptr->fontPointer == nullptr) { + GenerateNodeString(lineptr); + } + + GxuFontSetStringPosition(lineptr->fontPointer, pos); + GxuFontAddToBatch(s_batch, lineptr->fontPointer); + pos.y += ConsoleGetFontHeight(); + } + } + + GxuFontRenderBatch(s_batch); +} + +void UpdateHighlight() { + auto font = TextBlockGetFontPtr(s_textFont); + BLIZZARD_ASSERT(font); + + auto len = SStrLen(s_copyText); + + float left = std::min(s_highlightHStart, s_highlightHEnd); + float right = std::max(s_highlightHStart, s_highlightHEnd); + + auto chars = GxuFontGetMaxCharsWithinWidth(font, s_copyText, ConsoleGetFontHeight(), left, len, &s_hRect.left, 0.0f, 1.0f, s_charSpacing, s_baseTextFlags); + + s_highlightLeftCharIndex = chars; + + if (chars) { + s_highlightRightCharIndex = chars - 1; + } + + if (s_hRect.left < 0.015f) { + s_hRect.left = 0.0f; + } + + s_highlightRightCharIndex = GxuFontGetMaxCharsWithinWidth(font, s_copyText, ConsoleGetFontHeight(), right, len, &s_hRect.right, 0.0f, 1.0f, s_charSpacing, s_baseTextFlags); +} + +void ResetHighlight() { + s_highlightState = HS_NONE; + s_hRect = { 0.0f, 0.0f, 0.0f, 0.0f }; +} + +HIGHLIGHTSTATE GetHighlightState() { + return s_highlightState; +} + +void SetHighlightState(HIGHLIGHTSTATE hs) { + s_highlightState = hs; +} + +char* GetHighlightCopyText() { + return s_copyText; +} + +void SetHighlightCopyText(char* text) { + SStrCopy(s_copyText, text, HIGHLIGHT_COPY_SIZE); +} + +void ResetHighlightCopyText() { + s_copyText[0] = '\0'; +} + +RECTF& GetHighlightRect() { + return s_hRect; +} + +void SetHighlightStart(float start) { + s_highlightHStart = start; +} + +void SetHighlightEnd(float end) { + s_highlightHEnd = end; +} + +void CutHighlightToClipboard() { + char buffer[HIGHLIGHT_COPY_SIZE]; + + if (s_copyText[0] != '\0') { + uint32_t size = s_highlightRightCharIndex - s_highlightLeftCharIndex; + uint32_t capsize = HIGHLIGHT_COPY_SIZE-1; + size = std::min(size, capsize); + + SStrCopy(buffer, &s_copyText[s_highlightLeftCharIndex], size); + + buffer[size] = '\0'; + + // OsClipboardPutString(buffer); + } + + ResetHighlight(); +} + +void PasteClipboardToHighlight() { + // auto buffer = OsClipboardGetString(); + // PasteInInputLine(buffer); + // SMemFree(buffer, __FILE__, __LINE__, 0); + // ResetHighlight(); } void ConsoleScreenAnimate(float elapsedSec) { - auto finalPos = ConsoleGetActive() ? std::min(1.0f - s_consoleHeight, 1.0f) : 1.0f; + auto finalPos = ConsoleGetActive() ? std::min(1.0f - ConsoleGetHeight(), 1.0f) : 1.0f; finalPos = std::max(finalPos, 0.0f); if (s_rect.bottom == finalPos) { @@ -120,7 +430,7 @@ void ConsoleScreenInitialize(const char* title) { s_caretpixheight = height == 0.0f ? 1.0f : 1.0f / height; SStrCopy(s_fontName, "Fonts\\ARIALN.ttf", sizeof(s_fontName)); - s_textFont = TextBlockGenerateFont(s_fontName, 0, NDCToDDCHeight(s_fontHeight)); + s_textFont = TextBlockGenerateFont(s_fontName, 0, NDCToDDCHeight(ConsoleGetFontHeight())); ScrnLayerCreate(&s_rect, 6.0f, 0x1 | 0x2, nullptr, PaintBackground, &s_layerBackground); ScrnLayerCreate(&s_rect, 7.0f, 0x1 | 0x2, nullptr, PaintText, &s_layerText); @@ -128,10 +438,11 @@ void ConsoleScreenInitialize(const char* title) { RegisterHandlers(); // TODO register commands + ConsoleInitializeScreenCommand(); // TODO EventSetConfirmCloseCallback(EventCloseCallback, 0); - // TODO ConsoleCommandExecute("ver", 1); + ConsoleCommandExecute("ver", 1); s_batch = GxuFontCreateBatch(false, false); } diff --git a/src/console/Screen.hpp b/src/console/Screen.hpp index e065fb1..fce64dc 100644 --- a/src/console/Screen.hpp +++ b/src/console/Screen.hpp @@ -1,8 +1,46 @@ #ifndef CONSOLE_SCREEN_HPP #define CONSOLE_SCREEN_HPP +#define HIGHLIGHT_COPY_SIZE 128 + +#include "console/Line.hpp" +#include + +enum HIGHLIGHTSTATE { + HS_NONE = 0, + HS_HIGHLIGHTING = 1, + HS_ENDHIGHLIGHT = 2, + NUM_HIGHLIGHTSTATES +}; + void ConsoleScreenAnimate(float elapsedSec); void ConsoleScreenInitialize(const char* title); +void SetInputString(char* buffer); + +void ResetHighlight(); + +void UpdateHighlight(); + +HIGHLIGHTSTATE GetHighlightState(); + +void SetHighlightState(HIGHLIGHTSTATE hs); + +void SetHighlightCopyText(char* text); + +char* GetHighlightCopyText(); + +void ResetHighlightCopyText(); + +void SetHighlightStart(float start); +void SetHighlightEnd(float end); + +RECTF& GetHighlightRect(); + +void CutHighlightToClipboard(); +void PasteClipboardToHighlight(); + +void GenerateNodeString(CONSOLELINE* node); + #endif diff --git a/src/console/command/console/AppendLogToFile.cpp b/src/console/command/console/AppendLogToFile.cpp new file mode 100644 index 0000000..ef60729 --- /dev/null +++ b/src/console/command/console/AppendLogToFile.cpp @@ -0,0 +1,6 @@ +#include "console/Command.hpp" + +int32_t ConsoleCommand_AppendLogToFile(const char* command, const char* arguments) { + // TODO + return 1; +} diff --git a/src/console/command/console/BackGroundColor.cpp b/src/console/command/console/BackGroundColor.cpp new file mode 100644 index 0000000..41dbeb1 --- /dev/null +++ b/src/console/command/console/BackGroundColor.cpp @@ -0,0 +1,6 @@ +#include "console/Command.hpp" + +int32_t ConsoleCommand_BackGroundColor(const char* command, const char* arguments) { + // TODO + return 1; +} diff --git a/src/console/command/console/BufferSize.cpp b/src/console/command/console/BufferSize.cpp new file mode 100644 index 0000000..2602e03 --- /dev/null +++ b/src/console/command/console/BufferSize.cpp @@ -0,0 +1,6 @@ +#include "console/Command.hpp" + +int32_t ConsoleCommand_BufferSize(const char* command, const char* arguments) { + // TODO + return 1; +} diff --git a/src/console/command/console/CharSpacing.cpp b/src/console/command/console/CharSpacing.cpp new file mode 100644 index 0000000..05d6da9 --- /dev/null +++ b/src/console/command/console/CharSpacing.cpp @@ -0,0 +1,6 @@ +#include "console/Command.hpp" + +int32_t ConsoleCommand_CharSpacing(const char* command, const char* arguments) { + // TODO + return 1; +} diff --git a/src/console/command/console/ClearConsole.cpp b/src/console/command/console/ClearConsole.cpp new file mode 100644 index 0000000..c69d395 --- /dev/null +++ b/src/console/command/console/ClearConsole.cpp @@ -0,0 +1,6 @@ +#include "console/Command.hpp" + +int32_t ConsoleCommand_ClearConsole(const char* command, const char* arguments) { + ConsoleClear(); + return 1; +} diff --git a/src/console/command/console/CloseConsole.cpp b/src/console/command/console/CloseConsole.cpp new file mode 100644 index 0000000..6456635 --- /dev/null +++ b/src/console/command/console/CloseConsole.cpp @@ -0,0 +1,7 @@ +#include "console/Command.hpp" +#include "console/Console.hpp" + +int32_t ConsoleCommand_CloseConsole(const char* command, const char* arguments) { + ConsoleSetActive(false); + return 1; +} diff --git a/src/console/command/console/CurrentSettings.cpp b/src/console/command/console/CurrentSettings.cpp new file mode 100644 index 0000000..60ef851 --- /dev/null +++ b/src/console/command/console/CurrentSettings.cpp @@ -0,0 +1,6 @@ +#include "console/Command.hpp" + +int32_t ConsoleCommand_CurrentSettings(const char* command, const char* arguments) { + // TODO + return 1; +} diff --git a/src/console/command/console/DefaultSettings.cpp b/src/console/command/console/DefaultSettings.cpp new file mode 100644 index 0000000..d9bb63c --- /dev/null +++ b/src/console/command/console/DefaultSettings.cpp @@ -0,0 +1,6 @@ +#include "console/Command.hpp" + +int32_t ConsoleCommand_DefaultSettings(const char* command, const char* arguments) { + // TODO + return 1; +} diff --git a/src/console/command/console/Font.cpp b/src/console/command/console/Font.cpp new file mode 100644 index 0000000..cd0391f --- /dev/null +++ b/src/console/command/console/Font.cpp @@ -0,0 +1,6 @@ +#include "console/Command.hpp" + +int32_t ConsoleCommand_Font(const char* command, const char* arguments) { + // TODO + return 1; +} diff --git a/src/console/command/console/FontColor.cpp b/src/console/command/console/FontColor.cpp new file mode 100644 index 0000000..2c8777e --- /dev/null +++ b/src/console/command/console/FontColor.cpp @@ -0,0 +1,6 @@ +#include "console/Command.hpp" + +int32_t ConsoleCommand_FontColor(const char* command, const char* arguments) { + // TODO + return 1; +} diff --git a/src/console/command/console/FontSize.cpp b/src/console/command/console/FontSize.cpp new file mode 100644 index 0000000..596edfb --- /dev/null +++ b/src/console/command/console/FontSize.cpp @@ -0,0 +1,6 @@ +#include "console/Command.hpp" + +int32_t ConsoleCommand_FontSize(const char* command, const char* arguments) { + // TODO + return 1; +} diff --git a/src/console/command/console/Help.cpp b/src/console/command/console/Help.cpp new file mode 100644 index 0000000..cd8c05f --- /dev/null +++ b/src/console/command/console/Help.cpp @@ -0,0 +1,111 @@ +#include "console/Command.hpp" +#include "console/Line.hpp" + +struct CategoryTranslation { + CATEGORY categoryValue; + char categoryString[20]; +}; + +CategoryTranslation s_translation[] = { + { DEBUG, "debug" }, + { GRAPHICS, "graphics" }, + { CONSOLE, "console" }, + { COMBAT, "combat" }, + { GAME, "game" }, + { DEFAULT, "default" }, + { NET, "net" }, + { SOUND, "sound" }, + { GM, "gm" } +}; + +int32_t ConsoleCommand_Help(const char* command, const char* arguments) { + char buffer[128]; + bool showCategories = *arguments == '\0'; + + auto numTranslation = std::size(s_translation); + + if (showCategories) { + memset(buffer, 0, sizeof(buffer)); + + ConsoleWrite("Console help categories: ", DEFAULT_COLOR); + + uint32_t offset = 0; + + for (size_t i = 0; i < numTranslation; i++) { + auto& translation = s_translation[i]; + SStrPack(buffer, translation.categoryString, sizeof(buffer)); + + if (i + 1 != numTranslation) { + SStrPack(buffer, ", ", sizeof(buffer)); + } + } + + ConsoleWrite(buffer, WARNING_COLOR); + ConsoleWrite("For more information type 'help [command] or [category]'", WARNING_COLOR); + } else { + for (size_t i = 0; i < numTranslation; i++) { + auto& translation = s_translation[i]; + + if (SStrCmpI(translation.categoryString, arguments, STORM_MAX_STR) == 0) { + if (translation.categoryValue != NONE) { + memset(buffer, 0, sizeof(buffer)); + SStrPrintf(buffer, sizeof(buffer), "Commands registered for the category %s:", arguments); + + ConsoleWrite(buffer, WARNING_COLOR); + + buffer[0] = '\0'; + + uint32_t counter = 0; + + for (auto cmd = g_consoleCommandHash.Head(); cmd; cmd = g_consoleCommandHash.Next(cmd)) { + if (cmd->m_category == translation.categoryValue) { + SStrPack(buffer, cmd->m_key.m_str, sizeof(buffer)); + SStrPack(buffer, ", ", sizeof(buffer)); + + if (++counter == 8) { + ConsoleWrite(buffer, DEFAULT_COLOR); + buffer[0] = '\0'; + counter = 0; + } + } + } + + char* wr; + + if (buffer[0]) { + auto comma = reinterpret_cast(SStrChrR(buffer, ',')); + if (comma) { + *comma = 0x00; + } + + wr = buffer; + } else { + wr = "NONE"; + } + + ConsoleWrite(wr, DEFAULT_COLOR); + break; + } + } + } + + auto cmd = g_consoleCommandHash.Ptr(arguments); + + if (cmd == nullptr) { + return 1; + } + + SStrPrintf(buffer, 0xa5, "Help for command %s:", arguments); + ConsoleWrite(buffer, WARNING_COLOR); + + auto help = cmd->m_helpText; + if (help == nullptr) { + help = "No help yet"; + } + + SStrPrintf(buffer, 0xa5, " %s %s", arguments, help); + ConsoleWrite(buffer, DEFAULT_COLOR); + } + + return 1; +} diff --git a/src/console/command/console/HighLightColor.cpp b/src/console/command/console/HighLightColor.cpp new file mode 100644 index 0000000..1749c24 --- /dev/null +++ b/src/console/command/console/HighLightColor.cpp @@ -0,0 +1,6 @@ +#include "console/Command.hpp" + +int32_t ConsoleCommand_HighLightColor(const char* command, const char* arguments) { + // TODO + return 1; +} diff --git a/src/console/command/console/Proportional.cpp b/src/console/command/console/Proportional.cpp new file mode 100644 index 0000000..bb4d6cc --- /dev/null +++ b/src/console/command/console/Proportional.cpp @@ -0,0 +1,6 @@ +#include "console/Command.hpp" + +int32_t ConsoleCommand_Proportional(const char* command, const char* arguments) { + // TODO + return 1; +} diff --git a/src/console/command/console/RepeatHandler.cpp b/src/console/command/console/RepeatHandler.cpp new file mode 100644 index 0000000..5ea1125 --- /dev/null +++ b/src/console/command/console/RepeatHandler.cpp @@ -0,0 +1,7 @@ +#include "console/Command.hpp" +#include "console/Console.hpp" + +int32_t ConsoleCommand_RepeatHandler(const char* command, const char* arguments) { + // TODO + return 1; +} diff --git a/src/console/command/console/Ver.cpp b/src/console/command/console/Ver.cpp new file mode 100644 index 0000000..c165c8f --- /dev/null +++ b/src/console/command/console/Ver.cpp @@ -0,0 +1,7 @@ +#include "console/Command.hpp" +#include "console/Line.hpp" + +int32_t ConsoleCommand_Ver(const char* command, const char* arguments) { + ConsoleWrite("Whoa ", DEFAULT_COLOR); + return 1; +} diff --git a/src/console/command/default/Quit.cpp b/src/console/command/default/Quit.cpp new file mode 100644 index 0000000..ea1a9da --- /dev/null +++ b/src/console/command/default/Quit.cpp @@ -0,0 +1,7 @@ +#include "console/Command.hpp" +#include "console/Console.hpp" + +int32_t ConsoleCommand_Quit(const char* command, const char* arguments) { + ConsolePostClose(); + return 1; +} diff --git a/src/console/command/default/SetMap.cpp b/src/console/command/default/SetMap.cpp new file mode 100644 index 0000000..f4e8459 --- /dev/null +++ b/src/console/command/default/SetMap.cpp @@ -0,0 +1,5 @@ +#include "console/Command.hpp" + +int32_t ConsoleCommand_SetMap(const char* command, const char* arguments) { + return 1; +}