From b6f2456a826a6616095ed7e3b49db0ddc3c62574 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 15 May 2024 18:01:35 +0300 Subject: [PATCH 1/2] added file.remove, file.remove_tree --- src/logic/scripting/lua/libfile.cpp | 36 ++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/logic/scripting/lua/libfile.cpp b/src/logic/scripting/lua/libfile.cpp index 7db2d5ab..b14a15b4 100644 --- a/src/logic/scripting/lua/libfile.cpp +++ b/src/logic/scripting/lua/libfile.cpp @@ -43,6 +43,28 @@ static int l_file_write(lua_State* L) { return 1; } +static int l_file_remove(lua_State* L) { + std::string rawpath = lua_tostring(L, 1); + fs::path path = resolve_path(L, rawpath); + auto entryPoint = rawpath.substr(0, rawpath.find(':')); + if (entryPoint != "world") { + throw std::runtime_error("access denied"); + } + lua_pushboolean(L, fs::remove(path)); + return 1; +} + +static int l_file_remove_tree(lua_State* L) { + std::string rawpath = lua_tostring(L, 1); + fs::path path = resolve_path(L, rawpath); + auto entryPoint = rawpath.substr(0, rawpath.find(':')); + if (entryPoint != "world") { + throw std::runtime_error("access denied"); + } + lua_pushinteger(L, fs::remove_all(path)); + return 1; +} + static int l_file_exists(lua_State* L) { fs::path path = resolve_path(L, lua_tostring(L, 1)); lua_pushboolean(L, fs::exists(path)); @@ -172,18 +194,20 @@ static int l_file_list(lua_State* L) { } const luaL_Reg filelib [] = { - {"resolve", lua_wrap_errors}, - {"find", lua_wrap_errors}, - {"read", lua_wrap_errors}, - {"write", lua_wrap_errors}, {"exists", lua_wrap_errors}, - {"isfile", lua_wrap_errors}, + {"find", lua_wrap_errors}, {"isdir", lua_wrap_errors}, + {"isfile", lua_wrap_errors}, {"length", lua_wrap_errors}, + {"list", lua_wrap_errors}, {"mkdir", lua_wrap_errors}, {"mkdirs", lua_wrap_errors}, {"read_bytes", lua_wrap_errors}, + {"read", lua_wrap_errors}, + {"remove", lua_wrap_errors}, + {"remove_tree", lua_wrap_errors}, + {"resolve", lua_wrap_errors}, {"write_bytes", lua_wrap_errors}, - {"list", lua_wrap_errors}, + {"write", lua_wrap_errors}, {NULL, NULL} }; From a678eddb777c773098d614bc1a78d75a29bed5cd Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 16 May 2024 06:43:53 +0300 Subject: [PATCH 2/2] double click support --- src/graphics/ui/GUI.cpp | 31 +++++++++++++++++++----- src/graphics/ui/GUI.hpp | 10 +++++++- src/graphics/ui/elements/TextBox.cpp | 35 ++++++++++++++++++++++++++++ src/graphics/ui/elements/TextBox.hpp | 2 ++ src/graphics/ui/elements/UINode.cpp | 14 +++++++++++ src/graphics/ui/elements/UINode.hpp | 4 ++++ src/graphics/ui/gui_xml.cpp | 16 ++++++++++--- 7 files changed, 102 insertions(+), 10 deletions(-) diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp index 3b8d8a1b..cdff6fc5 100644 --- a/src/graphics/ui/GUI.cpp +++ b/src/graphics/ui/GUI.cpp @@ -45,8 +45,11 @@ void GUI::onAssetsLoad(Assets* assets) { ), "core:root"); } -// @brief Mouse related input and logic handling -void GUI::actMouse() { +/// @brief Mouse related input and logic handling +void GUI::actMouse(float delta) { + doubleClicked = false; + doubleClickTimer += delta + glm::length(Events::delta) * 0.1f; + auto hover = container->getAt(Events::cursor, nullptr); if (this->hover && this->hover != hover) { this->hover->setHover(false); @@ -62,7 +65,13 @@ void GUI::actMouse() { if (Events::jclicked(mousecode::BUTTON_1)) { if (pressed == nullptr && this->hover) { pressed = hover; - pressed->click(this, Events::cursor.x, Events::cursor.y); + if (doubleClickTimer < doubleClickDelay) { + pressed->doubleClick(this, Events::cursor.x, Events::cursor.y); + doubleClicked = true; + } else { + pressed->click(this, Events::cursor.x, Events::cursor.y); + } + doubleClickTimer = 0.0f; if (focus && focus != pressed) { focus->defocus(); } @@ -107,7 +116,9 @@ void GUI::actFocused() { if (Events::clicked(mousecode::BUTTON_1) && (Events::jclicked(mousecode::BUTTON_1) || Events::delta.x || Events::delta.y)) { - focus->mouseMove(this, Events::cursor.x, Events::cursor.y); + if (!doubleClicked) { + focus->mouseMove(this, Events::cursor.x, Events::cursor.y); + } } } } @@ -124,7 +135,7 @@ void GUI::act(float delta, const Viewport& vp) { auto prevfocus = focus; if (!Events::_cursor_locked) { - actMouse(); + actMouse(delta); } if (focus) { @@ -144,7 +155,7 @@ void GUI::draw(const DrawContext* pctx, Assets* assets) { Shader* uishader = assets->getShader("ui"); uishader->use(); - uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView()); + uishader->uniformMatrix("u_projview", uicamera->getProjView()); pctx->getBatch2D()->begin(); container->draw(pctx, assets); @@ -199,3 +210,11 @@ std::shared_ptr GUI::getContainer() const { void GUI::postRunnable(runnable callback) { postRunnables.push(callback); } + +void GUI::setDoubleClickDelay(float delay) { + doubleClickDelay = delay; +} + +float GUI::getDoubleClickDelay() const { + return doubleClickDelay; +} diff --git a/src/graphics/ui/GUI.hpp b/src/graphics/ui/GUI.hpp index 20c14efb..e88a3ea1 100644 --- a/src/graphics/ui/GUI.hpp +++ b/src/graphics/ui/GUI.hpp @@ -62,7 +62,12 @@ namespace gui { std::unique_ptr uicamera; std::shared_ptr menu; std::queue postRunnables; - void actMouse(); + + float doubleClickTimer = 0.0f; + float doubleClickDelay = 0.5f; + bool doubleClicked = false; + + void actMouse(float delta); void actFocused(); public: GUI(); @@ -121,6 +126,9 @@ namespace gui { void onAssetsLoad(Assets* assets); void postRunnable(runnable callback); + + void setDoubleClickDelay(float delay); + float getDoubleClickDelay() const; }; } diff --git a/src/graphics/ui/elements/TextBox.cpp b/src/graphics/ui/elements/TextBox.cpp index 7d6690de..1cd21faf 100644 --- a/src/graphics/ui/elements/TextBox.cpp +++ b/src/graphics/ui/elements/TextBox.cpp @@ -294,6 +294,41 @@ int TextBox::calcIndexAt(int x, int y) const { return std::min(offset+label->getTextLineOffset(line), input.length()); } +inline std::wstring get_alphabet(wchar_t c) { + std::wstring alphabet {c}; + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') { + return L"abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + } else if (c >= '0' && c <= '9') { + return L"0123456789"; + } + return alphabet; +} + +void TextBox::tokenSelectAt(int index) { + int left = index; + int right = index; + + std::wstring alphabet = get_alphabet(input.at(index)); + while (left >= 0) { + if (alphabet.find(input.at(left)) == std::wstring::npos) { + break; + } + left--; + } + while (static_cast(right) < input.length()) { + if (alphabet.find(input.at(right)) == std::wstring::npos) { + break; + } + right++; + } + select(left+1, right); +} + +void TextBox::doubleClick(GUI* gui, int x, int y) { + UINode::doubleClick(gui, x, y); + tokenSelectAt(normalizeIndex(calcIndexAt(x, y)-1)); +} + void TextBox::click(GUI*, int x, int y) { int index = normalizeIndex(calcIndexAt(x, y)); selectionStart = index; diff --git a/src/graphics/ui/elements/TextBox.hpp b/src/graphics/ui/elements/TextBox.hpp index bf06c9db..55701b63 100644 --- a/src/graphics/ui/elements/TextBox.hpp +++ b/src/graphics/ui/elements/TextBox.hpp @@ -47,6 +47,7 @@ namespace gui { bool eraseSelected(); void resetSelection(); void extendSelection(int index); + void tokenSelectAt(int index); size_t getLineLength(uint line) const; /// @brief Get total length of the selection @@ -141,6 +142,7 @@ namespace gui { virtual void onFocus(GUI*) override; virtual void refresh() override; + virtual void doubleClick(GUI*, int x, int y) override; virtual void click(GUI*, int, int) override; virtual void mouseMove(GUI*, int x, int y) override; virtual bool isFocuskeeper() const override {return true;} diff --git a/src/graphics/ui/elements/UINode.cpp b/src/graphics/ui/elements/UINode.cpp index 5669abf1..eda24fff 100644 --- a/src/graphics/ui/elements/UINode.cpp +++ b/src/graphics/ui/elements/UINode.cpp @@ -64,10 +64,24 @@ UINode* UINode::listenAction(onaction action) { return this; } +UINode* UINode::listenDoubleClick(onaction action) { + doubleClickCallbacks.push_back(action); + return this; +} + void UINode::click(GUI*, int, int) { pressed = true; } +void UINode::doubleClick(GUI* gui, int x, int y) { + pressed = true; + if (isInside(glm::vec2(x, y))) { + for (auto callback : doubleClickCallbacks) { + callback(gui); + } + } +} + void UINode::mouseRelease(GUI* gui, int x, int y) { pressed = false; if (isInside(glm::vec2(x, y))) { diff --git a/src/graphics/ui/elements/UINode.hpp b/src/graphics/ui/elements/UINode.hpp index 99bd39b0..3f7ba24e 100644 --- a/src/graphics/ui/elements/UINode.hpp +++ b/src/graphics/ui/elements/UINode.hpp @@ -88,6 +88,8 @@ namespace gui { vec2supplier sizefunc = nullptr; /// @brief 'onclick' callbacks std::vector actions; + /// @brief 'ondoubleclick' callbacks + std::vector doubleClickCallbacks; UINode(glm::vec2 size); public: @@ -138,8 +140,10 @@ namespace gui { int getZIndex() const; virtual UINode* listenAction(onaction action); + virtual UINode* listenDoubleClick(onaction action); virtual void onFocus(GUI*) {focused = true;} + virtual void doubleClick(GUI*, int x, int y); virtual void click(GUI*, int x, int y); virtual void clicked(GUI*, mousecode button) {} virtual void mouseMove(GUI*, int x, int y) {}; diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index 8f7acac2..9ac22ec7 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -123,15 +123,25 @@ static void _readUINode(UiXmlReader& reader, xml::xmlelement element, UINode& no std::string text = element->attr("onclick").getText(); if (!text.empty()) { auto callback = scripting::create_runnable( - reader.getEnvironment(), - text, - reader.getFilename() + reader.getEnvironment(), text, reader.getFilename() ); node.listenAction([callback](GUI*) { callback(); }); } } + + if (element->has("ondoubleclick")) { + std::string text = element->attr("ondoubleclick").getText(); + if (!text.empty()) { + auto callback = scripting::create_runnable( + reader.getEnvironment(), text, reader.getFilename() + ); + node.listenDoubleClick([callback](GUI*) { + callback(); + }); + } + } } static void _readContainer(UiXmlReader& reader, xml::xmlelement element, Container& container) {