Merge pull request #671 from MihailRis/debugging-client

Debugging client
This commit is contained in:
MihailRis
2025-11-20 22:55:16 +03:00
committed by GitHub
35 changed files with 430 additions and 73 deletions
+1
View File
@@ -197,6 +197,7 @@ bool DebuggingServer::performCommand(
connectionEstablished = true;
logger.info() << "client connection established";
connection->sendResponse("success");
return true;
}
if (!connectionEstablished) {
return false;
+1
View File
@@ -70,6 +70,7 @@ void Engine::onContentLoad() {
for (auto& pack : content->getAllContentPacks()) {
auto configFolder = pack.folder / "config";
auto bindsFile = configFolder / "bindings.toml";
logger.info() << "loading bindings: " << bindsFile.string();
if (io::is_regular_file(bindsFile)) {
input->getBindings().read(
toml::parse(
+8
View File
@@ -72,6 +72,14 @@ EnginePaths::EnginePaths(CoreParameters& params)
io::create_subdevice("config", "user", "config");
}
std::filesystem::path EnginePaths::getResourcesFolder() const {
return resourcesFolder;
}
std::filesystem::path EnginePaths::getUserFilesFolder() const {
return userFilesFolder;
}
io::path EnginePaths::getNewScreenshotFile(const std::string& ext) const {
auto folder = SCREENSHOTS_FOLDER;
if (!io::is_directory(folder)) {
+3
View File
@@ -48,6 +48,9 @@ public:
EnginePaths(CoreParameters& params);
std::filesystem::path getResourcesFolder() const;
std::filesystem::path getUserFilesFolder() const;
io::path getWorldFolderByName(const std::string& name);
io::path getWorldsFolder() const;
+5 -4
View File
@@ -33,11 +33,12 @@ WindowControl::Result WindowControl::initialize() {
auto& settings = engine.getSettings();
std::string title = project.title;
if (title.empty()) {
title = "VoxelCore v" +
std::to_string(ENGINE_VERSION_MAJOR) + "." +
std::to_string(ENGINE_VERSION_MINOR);
if (!title.empty()) {
title += " - ";
}
title += "VoxelCore v" +
std::to_string(ENGINE_VERSION_MAJOR) + "." +
std::to_string(ENGINE_VERSION_MINOR);
if (ENGINE_DEBUG_BUILD) {
title += " [debug]";
}
+2 -2
View File
@@ -93,10 +93,9 @@ void Container::act(float delta) {
}
}
}
GUI& gui = this->gui;
intervalEvents.erase(std::remove_if(
intervalEvents.begin(), intervalEvents.end(),
[&gui](const IntervalEvent& event) {
[](const IntervalEvent& event) {
return event.repeat == 0;
}
), intervalEvents.end());
@@ -177,6 +176,7 @@ void Container::add(const std::shared_ptr<UINode>& node) {
parent->setMustRefresh();
parent = parent->getParent();
}
gui.getWindow().setShouldRefresh();
}
void Container::add(const std::shared_ptr<UINode>& node, glm::vec2 pos) {
+3 -1
View File
@@ -37,7 +37,9 @@ namespace gui {
virtual void scrolled(int value) override;
virtual void setScrollable(bool flag);
void listenInterval(float interval, OnTimeOut callback, int repeat=-1);
virtual glm::vec2 getContentOffset() override {return glm::vec2(0.0f, scroll);};
virtual glm::vec2 getContentOffset() const override {
return glm::vec2(0.0f, scroll);
};
virtual void setSize(const glm::vec2& size) override;
virtual int getScrollStep() const;
virtual void setScrollStep(int step);
+4 -5
View File
@@ -36,12 +36,11 @@ void InlineFrame::setDocument(const std::shared_ptr<UiDocument>& document) {
}
void InlineFrame::act(float delta) {
Container::act(delta);
if (document || src.empty()) {
return;
if (document == nullptr && !src.empty()) {
const auto& assets = *gui.getEngine().getAssets();
setDocument(assets.getShared<UiDocument>(src));
}
const auto& assets = *gui.getEngine().getAssets();
setDocument(assets.getShared<UiDocument>(src));
Container::act(delta);
}
void InlineFrame::setSize(const glm::vec2& size) {
+52 -37
View File
@@ -231,7 +231,7 @@ TextBox::~TextBox() = default;
void TextBox::draw(const DrawContext& pctx, const Assets& assets) {
Container::draw(pctx, assets);
if (!isFocused()) {
if (!isFocused() && !keepLineSelection) {
return;
}
const auto& labelText = getText();
@@ -252,7 +252,7 @@ void TextBox::draw(const DrawContext& pctx, const Assets& assets) {
float time = gui.getWindow().time();
if (editable && static_cast<int>((time - caretLastMove) * 2) % 2 == 0) {
if (isFocused() && editable && static_cast<int>((time - caretLastMove) * 2) % 2 == 0) {
uint line = label->getLineByTextIndex(caret);
uint lcaret = caret - label->getTextLineOffset(line);
int width = rawTextCache.metrics.calcWidth(input, 0, lcaret);
@@ -308,42 +308,44 @@ void TextBox::draw(const DrawContext& pctx, const Assets& assets) {
}
}
if (isFocused() && multiline) {
auto selectionCtx = subctx.sub(batch);
selectionCtx.setBlendMode(BlendMode::addition);
batch->setColor(glm::vec4(1, 1, 1, 0.1f));
uint line = label->getLineByTextIndex(caret);
while (label->isFakeLine(line)) {
line--;
}
do {
int lineY = label->getLineYOffset(line);
batch->setColor(glm::vec4(1, 1, 1, 0.05f));
if (showLineNumbers) {
batch->rect(
lcoord.x - 8,
lcoord.y + lineY,
label->getSize().x,
lineHeight
);
batch->setColor(glm::vec4(1, 1, 1, 0.10f));
batch->rect(
lcoord.x - LINE_NUMBERS_PANE_WIDTH,
lcoord.y + lineY,
LINE_NUMBERS_PANE_WIDTH - 8,
lineHeight
);
} else {
batch->rect(
lcoord.x, lcoord.y + lineY, label->getSize().x, lineHeight
);
}
line++;
} while (line < label->getLinesNumber() && label->isFakeLine(line));
if (!multiline) {
return;
}
auto selectionCtx = subctx.sub(batch);
selectionCtx.setBlendMode(BlendMode::addition);
batch->setColor(glm::vec4(1, 1, 1, 0.1f));
uint line = label->getLineByTextIndex(caret);
while (label->isFakeLine(line)) {
line--;
}
do {
int lineY = label->getLineYOffset(line);
batch->setColor(glm::vec4(1, 1, 1, 0.05f));
if (showLineNumbers) {
batch->rect(
lcoord.x - 8,
lcoord.y + lineY,
label->getSize().x,
lineHeight
);
batch->setColor(glm::vec4(1, 1, 1, 0.10f));
batch->rect(
lcoord.x - LINE_NUMBERS_PANE_WIDTH,
lcoord.y + lineY,
LINE_NUMBERS_PANE_WIDTH - 8,
lineHeight
);
} else {
batch->rect(
lcoord.x, lcoord.y + lineY, label->getSize().x, lineHeight
);
}
line++;
} while (line < label->getLinesNumber() && label->isFakeLine(line));
}
void TextBox::drawBackground(const DrawContext& pctx, const Assets& assets) {
@@ -605,6 +607,14 @@ size_t TextBox::getSelectionEnd() const {
return selectionEnd;
}
void TextBox::setKeepLineSelection(bool flag) {
keepLineSelection = flag;
}
bool TextBox::isKeepLineSelection() const {
return keepLineSelection;
}
void TextBox::setOnEditStart(runnable oneditstart) {
onEditStart = oneditstart;
}
@@ -671,6 +681,11 @@ int TextBox::calcIndexAt(int x, int y) const {
);
}
int TextBox::getLineYOffset(int line) const {
if (rawTextCache.fontId == 0) return 0;
return label->getLineYOffset(line);
}
static inline std::wstring get_alphabet(wchar_t c) {
std::wstring alphabet {c};
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') {
+7 -1
View File
@@ -62,6 +62,7 @@ namespace gui {
bool editable = true;
bool autoresize = false;
bool showLineNumbers = false;
bool keepLineSelection = false;
std::string markup;
std::string syntax;
@@ -74,7 +75,6 @@ namespace gui {
size_t normalizeIndex(int index);
int calcIndexAt(int x, int y) const;
void setTextOffset(uint x);
bool eraseSelected();
void resetSelection();
@@ -186,6 +186,9 @@ namespace gui {
/// @return line position in text
virtual size_t getLinePos(uint line) const;
int calcIndexAt(int x, int y) const;
int getLineYOffset(int line) const;
/// @brief Check text with validator set with setTextValidator
/// @return true if text is valid
virtual bool validate();
@@ -220,6 +223,9 @@ namespace gui {
size_t getSelectionStart() const;
size_t getSelectionEnd() const;
void setKeepLineSelection(bool flag);
bool isKeepLineSelection() const;
/// @brief Set runnable called on textbox focus
virtual void setOnEditStart(runnable oneditstart);
+10
View File
@@ -68,6 +68,10 @@ void UINode::listenClick(OnAction action) {
actions.listen(UIAction::CLICK, std::move(action));
}
void UINode::listenRightClick(OnAction action) {
actions.listen(UIAction::RIGHT_CLICK, std::move(action));
}
void UINode::listenDoubleClick(OnAction action) {
actions.listen(UIAction::DOUBLE_CLICK, std::move(action));
}
@@ -84,6 +88,12 @@ void UINode::click(int, int) {
pressed = true;
}
void UINode::clicked(Mousecode button) {
if (button == Mousecode::BUTTON_2) {
actions.notify(UIAction::RIGHT_CLICK, gui);
}
}
void UINode::doubleClick(int x, int y) {
pressed = true;
if (isInside(glm::vec2(x, y))) {
+4 -3
View File
@@ -75,7 +75,7 @@ namespace gui {
};
enum class UIAction {
CLICK, DOUBLE_CLICK, FOCUS, DEFOCUS
CLICK, DOUBLE_CLICK, FOCUS, DEFOCUS, RIGHT_CLICK
};
using ActionsSet = TaggedCallbacksSet<UIAction, GUI&>;
@@ -214,6 +214,7 @@ namespace gui {
int getZIndex() const;
virtual void listenClick(OnAction action);
virtual void listenRightClick(OnAction action);
virtual void listenDoubleClick(OnAction action);
virtual void listenFocus(OnAction action);
virtual void listenDefocus(OnAction action);
@@ -221,7 +222,7 @@ namespace gui {
virtual void onFocus();
virtual void doubleClick(int x, int y);
virtual void click(int x, int y);
virtual void clicked(Mousecode button) {}
virtual void clicked(Mousecode button);
virtual void mouseMove(int x, int y) {};
virtual void mouseRelease(int x, int y);
virtual void scrolled(int value);
@@ -266,7 +267,7 @@ namespace gui {
virtual glm::vec4 calcColor() const;
/// @brief Get inner content offset. Used for scroll
virtual glm::vec2 getContentOffset() {return glm::vec2(0.0f);};
virtual glm::vec2 getContentOffset() const {return glm::vec2(0.0f);};
/// @brief Calculate screen position of the element
virtual glm::vec2 calcPos() const;
virtual void setPos(const glm::vec2& pos);
+9
View File
@@ -181,6 +181,10 @@ static void read_uinode(
node.listenClick(onclick);
}
if (auto onclick = create_action(reader, element, "onrightclick")) {
node.listenRightClick(onclick);
}
if (auto onfocus = create_action(reader, element, "onfocus")) {
node.listenFocus(onfocus);
}
@@ -569,6 +573,11 @@ static std::shared_ptr<UINode> read_text_box(
if (element.has("line-numbers")) {
textbox->setShowLineNumbers(element.attr("line-numbers").asBool());
}
if (element.has("keep-line-selection")) {
textbox->setKeepLineSelection(
element.attr("keep-line-selection").asBool()
);
}
if (element.has("markup")) {
textbox->setMarkup(element.attr("markup").getText());
}
+33 -3
View File
@@ -2,12 +2,40 @@
#include "io/io.hpp"
#include "io/devices/MemoryDevice.hpp"
#include "engine/Engine.hpp"
#include "content/ContentControl.hpp"
#include "logic/scripting/scripting.hpp"
#include "content/ContentControl.hpp"
#include "engine/Engine.hpp"
#include "engine/EnginePaths.hpp"
#include "network/Network.hpp"
#include "util/platform.hpp"
#include "window/Window.hpp"
using namespace scripting;
static int l_start_debug_instance(lua::State* L) {
int port = lua::tointeger(L, 1);
if (port == 0) {
port = engine->getNetwork().findFreePort();
if (port == -1) {
throw std::runtime_error("could not find free port");
}
}
const auto& paths = engine->getPaths();
std::vector<std::string> args {
"--res", paths.getResourcesFolder().u8string(),
"--dir", paths.getUserFilesFolder().u8string(),
"--dbg-server", "tcp:" + std::to_string(port),
};
platform::new_engine_instance(std::move(args));
return lua::pushinteger(L, port);
}
static int l_focus(lua::State* L) {
engine->getWindow().focus();
return 0;
}
static int l_create_memory_device(lua::State* L) {
std::string name = lua::require_string(L, 1);
if (io::get_device(name)) {
@@ -54,10 +82,12 @@ static int l_reset_content_sources(lua::State* L) {
}
const luaL_Reg applib[] = {
{"start_debug_instance", lua::wrap<l_start_debug_instance>},
{"focus", lua::wrap<l_focus>},
{"create_memory_device", lua::wrap<l_create_memory_device>},
{"get_content_sources", lua::wrap<l_get_content_sources>},
{"set_content_sources", lua::wrap<l_set_content_sources>},
{"reset_content_sources", lua::wrap<l_reset_content_sources>},
// see libcore.cpp an stdlib.lua
// for other functions see libcore.cpp and stdlib.lua
{nullptr, nullptr}
};
+8
View File
@@ -25,6 +25,7 @@
#include "graphics/ui/gui_util.hpp"
#include "graphics/ui/GUI.hpp"
#include "graphics/ui/elements/Menu.hpp"
#include "window/Window.hpp"
using namespace scripting;
@@ -299,6 +300,12 @@ static int l_capture_output(lua::State* L) {
return 1;
}
static int l_set_title(lua::State* L) {
auto title = lua::require_string(L, 1);
engine->getWindow().setTitle(title);
return 0;
}
const luaL_Reg corelib[] = {
{"blank", lua::wrap<l_blank>},
{"get_version", lua::wrap<l_get_version>},
@@ -320,5 +327,6 @@ const luaL_Reg corelib[] = {
{"open_url", lua::wrap<l_open_url>},
{"quit", lua::wrap<l_quit>},
{"capture_output", lua::wrap<l_capture_output>},
{"set_title", lua::wrap<l_set_title>},
{nullptr, nullptr}
};
+27 -1
View File
@@ -173,7 +173,25 @@ static int l_get_line_at(lua::State* L) {
auto node = get_document_node(L, 1);
auto position = lua::tointeger(L, 2);
if (auto box = dynamic_cast<TextBox*>(node.node.get())) {
return lua::pushinteger(L, box->getLineAt(position));
return lua::pushinteger(L, box->getLineAt(position) + 1);
}
return 0;
}
static int l_get_index_by_pos(lua::State* L) {
auto node = get_document_node(L, 1);
auto position = lua::tovec2(L, 2);
if (auto box = dynamic_cast<TextBox*>(node.node.get())) {
return lua::pushinteger(L, box->calcIndexAt(position.x, position.y));
}
return 0;
}
static int l_get_line_y(lua::State* L) {
auto node = get_document_node(L, 1);
auto line = lua::tointeger(L, 2);
if (auto box = dynamic_cast<TextBox*>(node.node.get())) {
return lua::pushinteger(L, box->getLineYOffset(line - 1));
}
return 0;
}
@@ -509,6 +527,12 @@ static int p_get_focused(UINode* node, lua::State* L) {
static int p_get_line_at(UINode*, lua::State* L) {
return lua::pushcfunction(L, l_get_line_at);
}
static int p_get_index_by_pos(UINode*, lua::State* L) {
return lua::pushcfunction(L, l_get_index_by_pos);
}
static int p_get_line_y(UINode*, lua::State* L) {
return lua::pushcfunction(L, l_get_line_y);
}
static int p_get_line_pos(UINode*, lua::State* L) {
return lua::pushcfunction(L, l_get_line_pos);
}
@@ -619,6 +643,8 @@ static int l_gui_getattr(lua::State* L) {
{"edited", p_get_edited},
{"lineNumbers", p_get_line_numbers},
{"lineAt", p_get_line_at},
{"indexByPos", p_get_index_by_pos},
{"lineY", p_get_line_y},
{"linePos", p_get_line_pos},
{"syntax", p_get_syntax},
{"markup", p_get_markup},
+5 -2
View File
@@ -50,8 +50,11 @@ static int l_add_callback(lua::State* L) {
handler = input.addKeyCallback(key, actual_callback);
}
}
auto callback = [&gui, actual_callback]() -> bool {
if (!gui.isFocusCaught()) {
bool isTopLevel = lua::toboolean(L, 4);
auto callback = [&gui, actual_callback, isTopLevel]() -> bool {
if (isTopLevel || !gui.isFocusCaught()) {
return actual_callback();
}
return false;
+5 -1
View File
@@ -410,7 +410,11 @@ static int l_get_total_download(lua::State* L, network::Network& network) {
}
static int l_find_free_port(lua::State* L, network::Network& network) {
return lua::pushinteger(L, network.findFreePort());
int port = network.findFreePort();
if (port == -1) {
return 0;
}
return lua::pushinteger(L, port);
}
static int l_set_nodelay(lua::State* L, network::Network& network) {
+5 -4
View File
@@ -309,14 +309,15 @@ static int l_debug_sendvalue(lua::State* L) {
lua::pushnil(L);
while (lua::next(L, 1)) {
auto key = lua::tolstring(L, -2);
lua::pushvalue(L, -2);
int type = lua::type(L, -1);
auto key = lua::tolstring(L, -1);
int type = lua::type(L, -2);
table[std::string(key)] = dv::object({
{"type", std::string(lua::type_name(L, type))},
{"short", get_short_value(L, -1, type)},
{"short", get_short_value(L, -2, type)},
});
lua::pop(L);
lua::pop(L, 2);
}
lua::pop(L);
value = std::move(table);
+3
View File
@@ -36,6 +36,9 @@ public:
virtual void setMode(WindowMode mode) = 0;
virtual WindowMode getMode() const = 0;
virtual void focus() = 0;
virtual void setTitle(const std::string& title) = 0;
virtual void setIcon(const ImageData* image) = 0;
virtual void pushScissor(glm::vec4 area) = 0;
+9 -1
View File
@@ -188,7 +188,7 @@ public:
codepoints.clear();
pressedKeys.clear();
if (waitForRefresh) {
glfwWaitEvents();
glfwWaitEventsTimeout(0.5);
} else {
glfwPollEvents();
}
@@ -468,6 +468,14 @@ public:
return mode;
}
void focus() override {
glfwFocusWindow(window);
}
void setTitle(const std::string& title) override {
glfwSetWindowTitle(window, title.c_str());
}
void setIcon(const ImageData* image) override {
if (image == nullptr) {
glfwSetWindowIcon(window, 0, nullptr);