added tooltips

This commit is contained in:
MihailRis
2024-05-24 08:03:05 +03:00
parent 1c45236693
commit eb10904069
10 changed files with 146 additions and 11 deletions
+39 -1
View File
@@ -1,9 +1,14 @@
#include "GUI.hpp" #include "GUI.hpp"
#include "gui_util.hpp"
#include "elements/UINode.hpp" #include "elements/UINode.hpp"
#include "elements/Label.hpp"
#include "elements/Menu.hpp" #include "elements/Menu.hpp"
#include "../../assets/Assets.hpp" #include "../../assets/Assets.hpp"
#include "../../frontend/UiDocument.hpp" #include "../../frontend/UiDocument.hpp"
#include "../../frontend/locale.hpp"
#include "../../graphics/core/Batch2D.hpp" #include "../../graphics/core/Batch2D.hpp"
#include "../../graphics/core/Shader.hpp" #include "../../graphics/core/Shader.hpp"
#include "../../graphics/core/DrawContext.hpp" #include "../../graphics/core/DrawContext.hpp"
@@ -27,6 +32,15 @@ GUI::GUI() {
menu->setId("menu"); menu->setId("menu");
container->add(menu); container->add(menu);
container->setScrollable(false); container->setScrollable(false);
tooltip = guiutil::create(
"<container color='#000000A0' interactive='false' z-index='999'>"
"<label id='tooltip.label' pos='2' autoresize='true'></label>"
"</container>"
);
store("tooltip", tooltip);
store("tooltip.label", UINode::find(tooltip, "tooltip.label"));
container->add(tooltip);
} }
GUI::~GUI() { GUI::~GUI() {
@@ -45,10 +59,34 @@ void GUI::onAssetsLoad(Assets* assets) {
), "core:root"); ), "core:root");
} }
void GUI::updateTooltip(float delta) {
float mouseDelta = glm::length(Events::delta);
if ((hover && mouseDelta < 1.0f) ||
(hover && hover->isInside(Events::cursor) && tooltipTimer >= tooltipDelay)) {
if (tooltipTimer + delta >= tooltipDelay) {
auto label = std::dynamic_pointer_cast<gui::Label>(get("tooltip.label"));
const auto& text = hover->getTooltip();
if (label && !text.empty()) {
tooltip->setVisible(true);
tooltip->setPos(Events::cursor+glm::vec2(10.0f));
label->setText(langs::get(text));
tooltip->setSize(label->getSize()+glm::vec2(4.0f));
}
}
tooltipTimer += delta;
} else {
tooltipTimer = 0.0f;
tooltip->setVisible(false);
}
}
/// @brief Mouse related input and logic handling /// @brief Mouse related input and logic handling
void GUI::actMouse(float delta) { void GUI::actMouse(float delta) {
updateTooltip(delta);
float mouseDelta = glm::length(Events::delta);
doubleClicked = false; doubleClicked = false;
doubleClickTimer += delta + glm::length(Events::delta) * 0.1f; doubleClickTimer += delta + mouseDelta * 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) {
+7 -3
View File
@@ -54,21 +54,25 @@ namespace gui {
/// @brief The main UI controller /// @brief The main UI controller
class GUI { class GUI {
std::shared_ptr<Container> container; std::shared_ptr<Container> container;
std::shared_ptr<UINode> hover = nullptr; std::shared_ptr<UINode> hover;
std::shared_ptr<UINode> pressed = nullptr; std::shared_ptr<UINode> pressed;
std::shared_ptr<UINode> focus = nullptr; std::shared_ptr<UINode> focus;
std::shared_ptr<UINode> tooltip;
std::unordered_map<std::string, std::shared_ptr<UINode>> storage; std::unordered_map<std::string, std::shared_ptr<UINode>> storage;
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;
float tooltipTimer = 0.0f;
float tooltipDelay = 0.5f;
float doubleClickTimer = 0.0f; float doubleClickTimer = 0.0f;
float doubleClickDelay = 0.5f; float doubleClickDelay = 0.5f;
bool doubleClicked = false; bool doubleClicked = false;
void actMouse(float delta); void actMouse(float delta);
void actFocused(); void actFocused();
void updateTooltip(float delta);
public: public:
GUI(); GUI();
~GUI(); ~GUI();
+13 -1
View File
@@ -1,7 +1,9 @@
#include "InventoryView.hpp" #include "InventoryView.hpp"
#include "../../../assets/Assets.hpp" #include "../../../assets/Assets.hpp"
#include "../../../content/Content.hpp" #include "../../../content/Content.hpp"
#include "../../../frontend/LevelFrontend.hpp" #include "../../../frontend/LevelFrontend.hpp"
#include "../../../frontend/locale.hpp"
#include "../../../items/Inventories.hpp" #include "../../../items/Inventories.hpp"
#include "../../../items/Inventory.hpp" #include "../../../items/Inventory.hpp"
#include "../../../items/ItemDef.hpp" #include "../../../items/ItemDef.hpp"
@@ -22,7 +24,6 @@
#include "../../render/BlocksPreview.hpp" #include "../../render/BlocksPreview.hpp"
#include "../GUI.hpp" #include "../GUI.hpp"
#include <iostream>
#include <glm/glm.hpp> #include <glm/glm.hpp>
using namespace gui; using namespace gui;
@@ -270,6 +271,17 @@ void SlotView::onFocus(gui::GUI* gui) {
clicked(gui, mousecode::BUTTON_1); clicked(gui, mousecode::BUTTON_1);
} }
const std::wstring SlotView::getTooltip() const {
const auto str = UINode::getTooltip();
if (!str.empty() || bound->isEmpty()) {
return str;
}
auto def = content->getIndices()->getItemDef(bound->getItemId());
return util::capitalized(
langs::get(util::str2wstr_utf8(def->caption))
); // TODO: cache
}
void SlotView::bind( void SlotView::bind(
int64_t inventoryid, int64_t inventoryid,
ItemStack& stack, ItemStack& stack,
@@ -63,6 +63,7 @@ namespace gui {
virtual void clicked(gui::GUI*, mousecode) override; virtual void clicked(gui::GUI*, mousecode) override;
virtual void onFocus(gui::GUI*) override; virtual void onFocus(gui::GUI*) override;
virtual const std::wstring getTooltip() const override;
void bind( void bind(
int64_t inventoryid, int64_t inventoryid,
+27 -4
View File
@@ -64,12 +64,28 @@ Label::Label(std::wstring text, std::string fontName)
cache.update(this->text, multiline, textWrap); cache.update(this->text, multiline, textWrap);
} }
glm::vec2 Label::calcSize() {
auto font = cache.font;
uint lineHeight = font->getLineHeight();
if (cache.lines.size() > 1) {
lineHeight *= lineInterval;
}
return glm::vec2 (
cache.font->calcWidth(text),
lineHeight * cache.lines.size() + font->getYOffset()
);
}
void Label::setText(std::wstring text) { void Label::setText(std::wstring text) {
if (text == this->text && !cache.resetFlag) { if (text == this->text && !cache.resetFlag) {
return; return;
} }
this->text = text; this->text = text;
cache.update(this->text, multiline, textWrap); cache.update(this->text, multiline, textWrap);
if (cache.font) {
setSize(calcSize());
}
} }
const std::wstring& Label::getText() const { const std::wstring& Label::getText() const {
@@ -156,10 +172,10 @@ void Label::draw(const DrawContext* pctx, Assets* assets) {
lineHeight *= lineInterval; lineHeight *= lineInterval;
} }
glm::vec2 size = getSize(); glm::vec2 size = getSize();
glm::vec2 newsize ( glm::vec2 newsize = calcSize();
font->calcWidth(text), if (autoresize) {
lineHeight * cache.lines.size() + font->getYOffset() setSize(newsize);
); }
glm::vec2 pos = calcPos(); glm::vec2 pos = calcPos();
switch (align) { switch (align) {
@@ -194,6 +210,13 @@ void Label::textSupplier(wstringsupplier supplier) {
this->supplier = supplier; this->supplier = supplier;
} }
void Label::setAutoResize(bool flag) {
this->autoresize = flag;
}
bool Label::isAutoResize() const {
return autoresize;
}
void Label::setMultiline(bool multiline) { void Label::setMultiline(bool multiline) {
if (multiline != this->multiline) { if (multiline != this->multiline) {
+8
View File
@@ -24,6 +24,8 @@ namespace gui {
class Label : public UINode { class Label : public UINode {
LabelCache cache; LabelCache cache;
glm::vec2 calcSize();
protected: protected:
std::wstring text; std::wstring text;
std::string fontName; std::string fontName;
@@ -47,6 +49,9 @@ namespace gui {
/// @brief Text line height multiplied by line interval /// @brief Text line height multiplied by line interval
int totalLineHeight = 1; int totalLineHeight = 1;
/// @brief Auto resize label to fit text
bool autoresize = false;
public: public:
Label(std::string text, std::string fontName="normal"); Label(std::string text, std::string fontName="normal");
Label(std::wstring text, std::string fontName="normal"); Label(std::wstring text, std::string fontName="normal");
@@ -95,6 +100,9 @@ namespace gui {
virtual void textSupplier(wstringsupplier supplier); virtual void textSupplier(wstringsupplier supplier);
virtual void setAutoResize(bool flag);
virtual bool isAutoResize() const;
virtual void setMultiline(bool multiline); virtual void setMultiline(bool multiline);
virtual bool isMultiline() const; virtual bool isMultiline() const;
+25 -1
View File
@@ -129,6 +129,14 @@ bool UINode::isResizing() const {
return resizing; return resizing;
} }
void UINode::setTooltip(const std::wstring& text) {
this->tooltip = text;
}
const std::wstring UINode::getTooltip() const {
return tooltip;
}
glm::vec2 UINode::calcPos() const { glm::vec2 UINode::calcPos() const {
if (parent) { if (parent) {
return pos + parent->calcPos() + parent->contentOffset(); return pos + parent->calcPos() + parent->contentOffset();
@@ -316,7 +324,7 @@ void UINode::setGravity(Gravity gravity) {
} }
void UINode::getIndices( void UINode::getIndices(
std::shared_ptr<UINode> node, const std::shared_ptr<UINode> node,
std::unordered_map<std::string, std::shared_ptr<UINode>>& map std::unordered_map<std::string, std::shared_ptr<UINode>>& map
) { ) {
const std::string& id = node->getId(); const std::string& id = node->getId();
@@ -330,3 +338,19 @@ void UINode::getIndices(
} }
} }
} }
std::shared_ptr<UINode> UINode::find(
const std::shared_ptr<UINode> node,
const std::string& id
) {
if (node->getId() == id) {
return node;
}
if (auto container = std::dynamic_pointer_cast<Container>(node)) {
for (auto subnode : container->getNodes()) {
if (auto found = UINode::find(subnode, id)) {
return found;
}
}
}
return nullptr;
}
+11 -1
View File
@@ -109,6 +109,8 @@ namespace gui {
ActionsSet actions; ActionsSet actions;
/// @brief 'ondoubleclick' callbacks /// @brief 'ondoubleclick' callbacks
ActionsSet doubleClickCallbacks; ActionsSet doubleClickCallbacks;
/// @brief element tooltip text
std::wstring tooltip;
UINode(glm::vec2 size); UINode(glm::vec2 size);
public: public:
@@ -197,6 +199,9 @@ namespace gui {
virtual void setResizing(bool flag); virtual void setResizing(bool flag);
virtual bool isResizing() const; virtual bool isResizing() const;
virtual void setTooltip(const std::wstring& text);
virtual const std::wstring getTooltip() const;
virtual glm::vec4 calcColor() const; virtual glm::vec4 calcColor() const;
/// @brief Get inner content offset. Used for scroll /// @brief Get inner content offset. Used for scroll
@@ -237,9 +242,14 @@ namespace gui {
/// @brief collect all nodes having id /// @brief collect all nodes having id
static void getIndices( static void getIndices(
std::shared_ptr<UINode> node, const std::shared_ptr<UINode> node,
std::unordered_map<std::string, std::shared_ptr<UINode>>& map std::unordered_map<std::string, std::shared_ptr<UINode>>& map
); );
static std::shared_ptr<UINode> find(
const std::shared_ptr<UINode> node,
const std::string& id
);
}; };
} }
+7
View File
@@ -143,6 +143,10 @@ static void _readUINode(UiXmlReader& reader, xml::xmlelement element, UINode& no
)); ));
} }
if (element->has("tooltip")) {
node.setTooltip(util::str2wstr_utf8(element->attr("tooltip").getText()));
}
if (auto onclick = create_action(reader, element, "onclick")) { if (auto onclick = create_action(reader, element, "onclick")) {
node.listenAction(onclick); node.listenAction(onclick);
} }
@@ -245,6 +249,9 @@ static std::shared_ptr<UINode> readLabel(UiXmlReader& reader, xml::xmlelement el
reader.getFilename() reader.getFilename()
)); ));
} }
if (element->has("autoresize")) {
label->setAutoResize(element->attr("autoresize").asBool());
}
if (element->has("multiline")) { if (element->has("multiline")) {
label->setMultiline(element->attr("multiline").asBool()); label->setMultiline(element->attr("multiline").asBool());
if (!element->has("valign")) { if (!element->has("valign")) {
+8
View File
@@ -264,6 +264,9 @@ static int p_get_hover_color(UINode* node) {
static int p_get_pressed_color(UINode* node) { static int p_get_pressed_color(UINode* node) {
return lua::pushcolor_arr(state->getLua(), node->getPressedColor()); return lua::pushcolor_arr(state->getLua(), node->getPressedColor());
} }
static int p_get_tooltip(UINode* node) {
return state->pushstring(util::wstr2str_utf8(node->getTooltip()));
}
static int p_get_pos(UINode* node) { static int p_get_pos(UINode* node) {
return lua::pushvec2_arr(state->getLua(), node->getPos()); return lua::pushvec2_arr(state->getLua(), node->getPos());
} }
@@ -300,6 +303,7 @@ static int l_gui_getattr(lua_State* L) {
{"color", p_get_color}, {"color", p_get_color},
{"hoverColor", p_get_hover_color}, {"hoverColor", p_get_hover_color},
{"pressedColor", p_get_pressed_color}, {"pressedColor", p_get_pressed_color},
{"tooltip", p_get_tooltip},
{"pos", p_get_pos}, {"pos", p_get_pos},
{"wpos", p_get_wpos}, {"wpos", p_get_wpos},
{"size", p_get_size}, {"size", p_get_size},
@@ -345,6 +349,9 @@ static void p_set_hover_color(UINode* node, int idx) {
static void p_set_pressed_color(UINode* node, int idx) { static void p_set_pressed_color(UINode* node, int idx) {
node->setPressedColor(state->tocolor(idx)); node->setPressedColor(state->tocolor(idx));
} }
static void p_set_tooltip(UINode* node, int idx) {
node->setTooltip(util::str2wstr_utf8(state->tostring(idx)));
}
static void p_set_pos(UINode* node, int idx) { static void p_set_pos(UINode* node, int idx) {
node->setPos(state->tovec2(idx)); node->setPos(state->tovec2(idx));
} }
@@ -464,6 +471,7 @@ static int l_gui_setattr(lua_State* L) {
{"color", p_set_color}, {"color", p_set_color},
{"hoverColor", p_set_hover_color}, {"hoverColor", p_set_hover_color},
{"pressedColor", p_set_pressed_color}, {"pressedColor", p_set_pressed_color},
{"tooltip", p_set_tooltip},
{"pos", p_set_pos}, {"pos", p_set_pos},
{"wpos", p_set_wpos}, {"wpos", p_set_wpos},
{"size", p_set_size}, {"size", p_set_size},