Merge branch 'main' into devtools

This commit is contained in:
MihailRis
2024-05-16 06:44:27 +03:00
8 changed files with 132 additions and 16 deletions
+25 -6
View File
@@ -45,8 +45,11 @@ void GUI::onAssetsLoad(Assets* assets) {
), "core:root"); ), "core:root");
} }
// @brief Mouse related input and logic handling /// @brief Mouse related input and logic handling
void GUI::actMouse() { void GUI::actMouse(float delta) {
doubleClicked = false;
doubleClickTimer += delta + glm::length(Events::delta) * 0.1f;
auto hover = container->getAt(Events::cursor, nullptr); auto hover = container->getAt(Events::cursor, nullptr);
if (this->hover && this->hover != hover) { if (this->hover && this->hover != hover) {
this->hover->setHover(false); this->hover->setHover(false);
@@ -62,7 +65,13 @@ void GUI::actMouse() {
if (Events::jclicked(mousecode::BUTTON_1)) { if (Events::jclicked(mousecode::BUTTON_1)) {
if (pressed == nullptr && this->hover) { if (pressed == nullptr && this->hover) {
pressed = 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) { if (focus && focus != pressed) {
focus->defocus(); focus->defocus();
} }
@@ -107,7 +116,9 @@ void GUI::actFocused() {
if (Events::clicked(mousecode::BUTTON_1) && if (Events::clicked(mousecode::BUTTON_1) &&
(Events::jclicked(mousecode::BUTTON_1) || Events::delta.x || Events::delta.y)) (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; auto prevfocus = focus;
if (!Events::_cursor_locked) { if (!Events::_cursor_locked) {
actMouse(); actMouse(delta);
} }
if (focus) { if (focus) {
@@ -144,7 +155,7 @@ void GUI::draw(const DrawContext* pctx, Assets* assets) {
Shader* uishader = assets->getShader("ui"); Shader* uishader = assets->getShader("ui");
uishader->use(); uishader->use();
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView()); uishader->uniformMatrix("u_projview", uicamera->getProjView());
pctx->getBatch2D()->begin(); pctx->getBatch2D()->begin();
container->draw(pctx, assets); container->draw(pctx, assets);
@@ -199,3 +210,11 @@ std::shared_ptr<Container> GUI::getContainer() const {
void GUI::postRunnable(runnable callback) { void GUI::postRunnable(runnable callback) {
postRunnables.push(callback); postRunnables.push(callback);
} }
void GUI::setDoubleClickDelay(float delay) {
doubleClickDelay = delay;
}
float GUI::getDoubleClickDelay() const {
return doubleClickDelay;
}
+9 -1
View File
@@ -62,7 +62,12 @@ namespace gui {
std::unique_ptr<Camera> uicamera; std::unique_ptr<Camera> uicamera;
std::shared_ptr<Menu> menu; std::shared_ptr<Menu> menu;
std::queue<runnable> postRunnables; std::queue<runnable> postRunnables;
void actMouse();
float doubleClickTimer = 0.0f;
float doubleClickDelay = 0.5f;
bool doubleClicked = false;
void actMouse(float delta);
void actFocused(); void actFocused();
public: public:
GUI(); GUI();
@@ -121,6 +126,9 @@ namespace gui {
void onAssetsLoad(Assets* assets); void onAssetsLoad(Assets* assets);
void postRunnable(runnable callback); void postRunnable(runnable callback);
void setDoubleClickDelay(float delay);
float getDoubleClickDelay() const;
}; };
} }
+35
View File
@@ -320,6 +320,41 @@ int TextBox::calcIndexAt(int x, int y) const {
return std::min(offset+label->getTextLineOffset(line), input.length()); 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<size_t>(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) { void TextBox::click(GUI*, int x, int y) {
int index = normalizeIndex(calcIndexAt(x, y)); int index = normalizeIndex(calcIndexAt(x, y));
selectionStart = index; selectionStart = index;
+2
View File
@@ -52,6 +52,7 @@ namespace gui {
bool eraseSelected(); bool eraseSelected();
void resetSelection(); void resetSelection();
void extendSelection(int index); void extendSelection(int index);
void tokenSelectAt(int index);
size_t getLineLength(uint line) const; size_t getLineLength(uint line) const;
/// @brief Get total length of the selection /// @brief Get total length of the selection
@@ -151,6 +152,7 @@ namespace gui {
virtual void onFocus(GUI*) override; virtual void onFocus(GUI*) override;
virtual void refresh() override; virtual void refresh() override;
virtual void doubleClick(GUI*, int x, int y) override;
virtual void click(GUI*, int, int) override; virtual void click(GUI*, int, int) override;
virtual void mouseMove(GUI*, int x, int y) override; virtual void mouseMove(GUI*, int x, int y) override;
virtual bool isFocuskeeper() const override {return true;} virtual bool isFocuskeeper() const override {return true;}
+14
View File
@@ -64,10 +64,24 @@ UINode* UINode::listenAction(onaction action) {
return this; return this;
} }
UINode* UINode::listenDoubleClick(onaction action) {
doubleClickCallbacks.push_back(action);
return this;
}
void UINode::click(GUI*, int, int) { void UINode::click(GUI*, int, int) {
pressed = true; 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) { void UINode::mouseRelease(GUI* gui, int x, int y) {
pressed = false; pressed = false;
if (isInside(glm::vec2(x, y))) { if (isInside(glm::vec2(x, y))) {
+4
View File
@@ -88,6 +88,8 @@ namespace gui {
vec2supplier sizefunc = nullptr; vec2supplier sizefunc = nullptr;
/// @brief 'onclick' callbacks /// @brief 'onclick' callbacks
std::vector<onaction> actions; std::vector<onaction> actions;
/// @brief 'ondoubleclick' callbacks
std::vector<onaction> doubleClickCallbacks;
UINode(glm::vec2 size); UINode(glm::vec2 size);
public: public:
@@ -138,8 +140,10 @@ namespace gui {
int getZIndex() const; int getZIndex() const;
virtual UINode* listenAction(onaction action); virtual UINode* listenAction(onaction action);
virtual UINode* listenDoubleClick(onaction action);
virtual void onFocus(GUI*) {focused = true;} virtual void onFocus(GUI*) {focused = true;}
virtual void doubleClick(GUI*, int x, int y);
virtual void click(GUI*, int x, int y); virtual void click(GUI*, int x, int y);
virtual void clicked(GUI*, mousecode button) {} virtual void clicked(GUI*, mousecode button) {}
virtual void mouseMove(GUI*, int x, int y) {}; virtual void mouseMove(GUI*, int x, int y) {};
+13 -3
View File
@@ -123,15 +123,25 @@ static void _readUINode(UiXmlReader& reader, xml::xmlelement element, UINode& no
std::string text = element->attr("onclick").getText(); std::string text = element->attr("onclick").getText();
if (!text.empty()) { if (!text.empty()) {
auto callback = scripting::create_runnable( auto callback = scripting::create_runnable(
reader.getEnvironment(), reader.getEnvironment(), text, reader.getFilename()
text,
reader.getFilename()
); );
node.listenAction([callback](GUI*) { node.listenAction([callback](GUI*) {
callback(); 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) { static void _readContainer(UiXmlReader& reader, xml::xmlelement element, Container& container) {
+30 -6
View File
@@ -43,6 +43,28 @@ static int l_file_write(lua_State* L) {
return 1; 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) { static int l_file_exists(lua_State* L) {
fs::path path = resolve_path(L, lua_tostring(L, 1)); fs::path path = resolve_path(L, lua_tostring(L, 1));
lua_pushboolean(L, fs::exists(path)); lua_pushboolean(L, fs::exists(path));
@@ -172,18 +194,20 @@ static int l_file_list(lua_State* L) {
} }
const luaL_Reg filelib [] = { const luaL_Reg filelib [] = {
{"resolve", lua_wrap_errors<l_file_resolve>},
{"find", lua_wrap_errors<l_file_find>},
{"read", lua_wrap_errors<l_file_read>},
{"write", lua_wrap_errors<l_file_write>},
{"exists", lua_wrap_errors<l_file_exists>}, {"exists", lua_wrap_errors<l_file_exists>},
{"isfile", lua_wrap_errors<l_file_isfile>}, {"find", lua_wrap_errors<l_file_find>},
{"isdir", lua_wrap_errors<l_file_isdir>}, {"isdir", lua_wrap_errors<l_file_isdir>},
{"isfile", lua_wrap_errors<l_file_isfile>},
{"length", lua_wrap_errors<l_file_length>}, {"length", lua_wrap_errors<l_file_length>},
{"list", lua_wrap_errors<l_file_list>},
{"mkdir", lua_wrap_errors<l_file_mkdir>}, {"mkdir", lua_wrap_errors<l_file_mkdir>},
{"mkdirs", lua_wrap_errors<l_file_mkdirs>}, {"mkdirs", lua_wrap_errors<l_file_mkdirs>},
{"read_bytes", lua_wrap_errors<l_file_read_bytes>}, {"read_bytes", lua_wrap_errors<l_file_read_bytes>},
{"read", lua_wrap_errors<l_file_read>},
{"remove", lua_wrap_errors<l_file_remove>},
{"remove_tree", lua_wrap_errors<l_file_remove_tree>},
{"resolve", lua_wrap_errors<l_file_resolve>},
{"write_bytes", lua_wrap_errors<l_file_write_bytes>}, {"write_bytes", lua_wrap_errors<l_file_write_bytes>},
{"list", lua_wrap_errors<l_file_list>}, {"write", lua_wrap_errors<l_file_write>},
{NULL, NULL} {NULL, NULL}
}; };