Skip to content

Commit

Permalink
Add a basic Quake-style console
Browse files Browse the repository at this point in the history
Enabled only in Debug mode.

Runs Lua similar to the `lua` CLI.
Supports multiline input with Shift+Enter.

Missing features:
1. Scrollback.
2. Input history on up/down.

Open with backtick, close with Esc.
  • Loading branch information
glebm committed Oct 31, 2023
1 parent 115c071 commit fa7ad6b
Show file tree
Hide file tree
Showing 17 changed files with 462 additions and 88 deletions.
2 changes: 2 additions & 0 deletions CMake/Assets.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ set(devilutionx_assets
fonts/blue.trn
fonts/buttonface.trn
fonts/buttonpushed.trn
fonts/gamedialogwhite.trn
fonts/gamedialogred.trn
fonts/golduis.trn
fonts/goldui.trn
fonts/grayuis.trn
Expand Down
Binary file added Packaging/resources/assets/fonts/gamedialogred.trn
Binary file not shown.
Binary file added Packaging/resources/assets/fonts/gamedialogwhite.trn
Binary file not shown.
2 changes: 2 additions & 0 deletions Source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,12 @@ set(libdevilutionx_SRCS
levels/trigs.cpp

lua/lua.cpp
lua/repl.cpp
lua/modules/render.cpp
lua/modules/log.cpp

panels/charpanel.cpp
panels/console.cpp
panels/info_box.cpp
panels/mainpanel.cpp
panels/spell_book.cpp
Expand Down
45 changes: 23 additions & 22 deletions Source/DiabloUI/ui_flags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,29 @@ enum class UiFlags : uint32_t {
ColorUiGoldDark = 1 << 8,
ColorUiSilverDark = 1 << 9,
ColorDialogWhite = 1 << 10,
ColorYellow = 1 << 11,
ColorGold = 1 << 12,
ColorBlack = 1 << 13,
ColorWhite = 1 << 14,
ColorWhitegold = 1 << 15,
ColorRed = 1 << 16,
ColorBlue = 1 << 17,
ColorOrange = 1 << 18,
ColorButtonface = 1 << 19,
ColorButtonpushed = 1 << 20,

AlignCenter = 1 << 21,
AlignRight = 1 << 22,
VerticalCenter = 1 << 23,

KerningFitSpacing = 1 << 24,

ElementDisabled = 1 << 25,
ElementHidden = 1 << 26,

PentaCursor = 1 << 27,
Outlined = 1 << 28,
ColorDialogRed = 1 << 11,
ColorYellow = 1 << 12,
ColorGold = 1 << 13,
ColorBlack = 1 << 14,
ColorWhite = 1 << 15,
ColorWhitegold = 1 << 16,
ColorRed = 1 << 17,
ColorBlue = 1 << 18,
ColorOrange = 1 << 19,
ColorButtonface = 1 << 20,
ColorButtonpushed = 1 << 21,

AlignCenter = 1 << 22,
AlignRight = 1 << 23,
VerticalCenter = 1 << 24,

KerningFitSpacing = 1 << 25,

ElementDisabled = 1 << 26,
ElementHidden = 1 << 27,

PentaCursor = 1 << 28,
Outlined = 1 << 29,

/** @brief Ensures that the if current element is active that the next element is also visible. */
NeedsNextElement = 1 << 30,
Expand Down
10 changes: 0 additions & 10 deletions Source/debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,6 @@ std::string DebugCmdHelp(const std::string_view parameter)
return StrCat("Description: ", dbgCmdItem.description, "\nParameters: ", dbgCmdItem.requiredParameter);
}

std::string DebugCmdLua(std::string_view code)
{
tl::expected<std::string, std::string> result = RunLua(code);
if (!result.has_value()) {
return StrCat("> ", code, "\n") + std::move(result).error();
}
return StrCat("> ", code, "\n") + std::move(result).value();
}

std::string DebugCmdGiveGoldCheat(const std::string_view parameter)
{
Player &myPlayer = *MyPlayer;
Expand Down Expand Up @@ -1285,7 +1276,6 @@ std::vector<DebugCmdItem> DebugCmdList = {
{ "searchitem", "Searches the automap for {item}", "{item}", &DebugCmdSearchItem },
{ "searchobject", "Searches the automap for {object}", "{object}", &DebugCmdSearchObject },
{ "clearsearch", "Search in the auto map is cleared", "", &DebugCmdClearSearch },
{ "lua", "Run Lua code", "{code}", &DebugCmdLua },
};

} // namespace
Expand Down
13 changes: 13 additions & 0 deletions Source/diablo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#include "nthread.h"
#include "objects.h"
#include "options.h"
#include "panels/console.hpp"
#include "panels/info_box.hpp"
#include "panels/spell_book.hpp"
#include "panels/spell_list.hpp"
Expand Down Expand Up @@ -706,6 +707,12 @@ void GameEventHandler(const SDL_Event &event, uint16_t modState)
return;
}

#ifdef _DEBUG
if (ConsoleHandleEvent(event)) {
return;
}
#endif

if (IsTalkActive() && HandleTalkTextInputEvent(event)) {
return;
}
Expand Down Expand Up @@ -1864,6 +1871,12 @@ void InitKeymapActions()
ToggleChatLog();
});
#ifdef _DEBUG
sgOptions.Keymapper.AddAction(
"OpenConsole",
N_("Console"),
N_("Opens Lua console."),
'`',
OpenConsole);
sgOptions.Keymapper.AddAction(
"DebugToggle",
"Debug toggle",
Expand Down
5 changes: 5 additions & 0 deletions Source/engine/render/scrollrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "nthread.h"
#include "options.h"
#include "panels/charpanel.hpp"
#include "panels/console.hpp"
#include "plrmsg.h"
#include "qol/chatlog.h"
#include "qol/floatingnumbers.h"
Expand Down Expand Up @@ -1660,6 +1661,10 @@ void DrawAndBlit()

DrawMain(out, hgt, drawInfoBox, drawHealth, drawMana, drawBelt, drawControlButtons);

#ifdef _DEBUG
DrawConsole(out);
#endif

RedrawComplete();
for (PanelDrawComponent component : enum_values<PanelDrawComponent>()) {
if (IsRedrawComponent(component)) {
Expand Down
61 changes: 26 additions & 35 deletions Source/engine/render/text_render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@ constexpr std::array<int, 6> LineHeights = { 12, 26, 38, 42, 50, 22 };
constexpr int SmallFontTallLineHeight = 16;
std::array<int, 6> BaseLineOffset = { -3, -2, -3, -6, -7, 3 };

std::array<const char *, 15> ColorTranslations = {
std::array<const char *, 18> ColorTranslations = {
"fonts\\goldui.trn",
"fonts\\grayui.trn",
"fonts\\golduis.trn",
"fonts\\grayuis.trn",

nullptr,
nullptr, // ColorDialogWhite
nullptr, // ColorDialogRed
"fonts\\yellow.trn",

nullptr,
Expand All @@ -66,55 +67,43 @@ std::array<const char *, 15> ColorTranslations = {

"fonts\\buttonface.trn",
"fonts\\buttonpushed.trn",
"fonts\\gamedialogwhite.trn",
"fonts\\gamedialogred.trn",
};

std::array<std::optional<std::array<uint8_t, 256>>, 15> ColorTranslationsData;

GameFontTables GetSizeFromFlags(UiFlags flags)
{
if (HasAnyOf(flags, UiFlags::FontSize24))
return GameFont24;
else if (HasAnyOf(flags, UiFlags::FontSize30))
return GameFont30;
else if (HasAnyOf(flags, UiFlags::FontSize42))
return GameFont42;
else if (HasAnyOf(flags, UiFlags::FontSize46))
return GameFont46;
else if (HasAnyOf(flags, UiFlags::FontSizeDialog))
return FontSizeDialog;

return GameFont12;
}
std::array<std::optional<std::array<uint8_t, 256>>, 18> ColorTranslationsData;

text_color GetColorFromFlags(UiFlags flags)
{
if (HasAnyOf(flags, UiFlags::ColorWhite))
return ColorWhite;
else if (HasAnyOf(flags, UiFlags::ColorBlue))
if (HasAnyOf(flags, UiFlags::ColorBlue))
return ColorBlue;
else if (HasAnyOf(flags, UiFlags::ColorOrange))
if (HasAnyOf(flags, UiFlags::ColorOrange))
return ColorOrange;
else if (HasAnyOf(flags, UiFlags::ColorRed))
if (HasAnyOf(flags, UiFlags::ColorRed))
return ColorRed;
else if (HasAnyOf(flags, UiFlags::ColorBlack))
if (HasAnyOf(flags, UiFlags::ColorBlack))
return ColorBlack;
else if (HasAnyOf(flags, UiFlags::ColorGold))
if (HasAnyOf(flags, UiFlags::ColorGold))
return ColorGold;
else if (HasAnyOf(flags, UiFlags::ColorUiGold))
if (HasAnyOf(flags, UiFlags::ColorUiGold))
return ColorUiGold;
else if (HasAnyOf(flags, UiFlags::ColorUiSilver))
if (HasAnyOf(flags, UiFlags::ColorUiSilver))
return ColorUiSilver;
else if (HasAnyOf(flags, UiFlags::ColorUiGoldDark))
if (HasAnyOf(flags, UiFlags::ColorUiGoldDark))
return ColorUiGoldDark;
else if (HasAnyOf(flags, UiFlags::ColorUiSilverDark))
if (HasAnyOf(flags, UiFlags::ColorUiSilverDark))
return ColorUiSilverDark;
else if (HasAnyOf(flags, UiFlags::ColorDialogWhite))
return ColorDialogWhite;
else if (HasAnyOf(flags, UiFlags::ColorYellow))
if (HasAnyOf(flags, UiFlags::ColorDialogWhite))
return gbRunGame ? ColorInGameDialogWhite : ColorDialogWhite;
if (HasAnyOf(flags, UiFlags::ColorDialogRed))
return ColorInGameDialogRed;
if (HasAnyOf(flags, UiFlags::ColorYellow))
return ColorYellow;
else if (HasAnyOf(flags, UiFlags::ColorButtonface))
if (HasAnyOf(flags, UiFlags::ColorButtonface))
return ColorButtonface;
else if (HasAnyOf(flags, UiFlags::ColorButtonpushed))
if (HasAnyOf(flags, UiFlags::ColorButtonpushed))
return ColorButtonpushed;

return ColorWhitegold;
Expand Down Expand Up @@ -443,6 +432,8 @@ uint32_t DoDrawString(const Surface &out, std::string_view text, Rectangle rect,
const uint8_t frame = next & 0xFF;
const uint16_t width = (*currentFont.sprite)[frame].width();
if (next == U'\n' || characterPosition.x + width > rightMargin) {
if (next == '\n')
maybeDrawCursor();
const int nextLineY = characterPosition.y + opts.lineHeight;
if (nextLineY >= bottomMargin)
break;
Expand Down Expand Up @@ -683,7 +674,7 @@ std::string WordWrapString(std::string_view text, unsigned width, GameFontTables
*/
uint32_t DrawString(const Surface &out, std::string_view text, const Rectangle &rect, TextRenderOptions opts)
{
const GameFontTables size = GetSizeFromFlags(opts.flags);
const GameFontTables size = GetFontSizeFromUiFlags(opts.flags);
const text_color color = GetColorFromFlags(opts.flags);

int charactersInLine = 0;
Expand Down Expand Up @@ -734,7 +725,7 @@ uint32_t DrawString(const Surface &out, std::string_view text, const Rectangle &

void DrawStringWithColors(const Surface &out, std::string_view fmt, DrawStringFormatArg *args, std::size_t argsLen, const Rectangle &rect, TextRenderOptions opts)
{
const GameFontTables size = GetSizeFromFlags(opts.flags);
const GameFontTables size = GetFontSizeFromUiFlags(opts.flags);
const text_color color = GetColorFromFlags(opts.flags);

int charactersInLine = 0;
Expand Down
22 changes: 21 additions & 1 deletion Source/engine/render/text_render.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "engine/clx_sprite.hpp"
#include "engine/palette.h"
#include "engine/rectangle.hpp"
#include "utils/enum_traits.h"

namespace devilution {

Expand All @@ -38,7 +39,8 @@ enum text_color : uint8_t {
ColorUiGoldDark,
ColorUiSilverDark,

ColorDialogWhite,
ColorDialogWhite, // Dialog white in main menu
ColorDialogRed,
ColorYellow,

ColorGold,
Expand All @@ -52,8 +54,26 @@ enum text_color : uint8_t {

ColorButtonface,
ColorButtonpushed,

ColorInGameDialogWhite, // Dialog white in-game
ColorInGameDialogRed, // Dialog red in-game
};

constexpr GameFontTables GetFontSizeFromUiFlags(UiFlags flags)
{
if (HasAnyOf(flags, UiFlags::FontSize24))
return GameFont24;
if (HasAnyOf(flags, UiFlags::FontSize30))
return GameFont30;
if (HasAnyOf(flags, UiFlags::FontSize42))
return GameFont42;
if (HasAnyOf(flags, UiFlags::FontSize46))
return GameFont46;
if (HasAnyOf(flags, UiFlags::FontSizeDialog))
return FontSizeDialog;
return GameFont12;
}

/**
* @brief A format argument for `DrawStringWithColors`.
*/
Expand Down
15 changes: 2 additions & 13 deletions Source/lua/lua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <string_view>

#include <sol/sol.hpp>
#include <sol/utility/to_string.hpp>

#include "engine/assets.hpp"
#include "lua/modules/log.hpp"
Expand Down Expand Up @@ -137,19 +136,9 @@ void LuaEvent(std::string_view name)
CheckResult(fn());
}

tl::expected<std::string, std::string> RunLua(std::string_view code)
sol::state &LuaState()
{
sol::state &lua = *luaState;
const sol::protected_function_result result = lua.safe_script(code);
const bool valid = result.valid();
if (!valid) {
if (result.get_type() == sol::type::string) {
return tl::make_unexpected(result.get<std::string>());
}
return tl::make_unexpected("Unknown Lua error");
}

return sol::utility::to_string(sol::stack_object(result));
return *luaState;
}

} // namespace devilution
6 changes: 5 additions & 1 deletion Source/lua/lua.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@

#include <expected.hpp>

namespace sol {
class state;
} // namespace sol

namespace devilution {

void LuaInitialize();
void LuaShutdown();
void LuaEvent(std::string_view name);
tl::expected<std::string, std::string> RunLua(std::string_view code);
sol::state &LuaState();

} // namespace devilution
Loading

0 comments on commit fa7ad6b

Please sign in to comment.