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

View File

@ -1,9 +1,14 @@
#include "GUI.hpp"
#include "gui_util.hpp"
#include "elements/UINode.hpp"
#include "elements/Label.hpp"
#include "elements/Menu.hpp"
#include "../../assets/Assets.hpp"
#include "../../frontend/UiDocument.hpp"
#include "../../frontend/locale.hpp"
#include "../../graphics/core/Batch2D.hpp"
#include "../../graphics/core/Shader.hpp"
#include "../../graphics/core/DrawContext.hpp"
@ -27,6 +32,15 @@ GUI::GUI() {
menu->setId("menu");
container->add(menu);
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() {
@ -45,10 +59,34 @@ void GUI::onAssetsLoad(Assets* assets) {
), "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
void GUI::actMouse(float delta) {
updateTooltip(delta);
float mouseDelta = glm::length(Events::delta);
doubleClicked = false;
doubleClickTimer += delta + glm::length(Events::delta) * 0.1f;
doubleClickTimer += delta + mouseDelta * 0.1f;
auto hover = container->getAt(Events::cursor, nullptr);
if (this->hover && this->hover != hover) {

View File

@ -54,21 +54,25 @@ namespace gui {
/// @brief The main UI controller
class GUI {
std::shared_ptr<Container> container;
std::shared_ptr<UINode> hover = nullptr;
std::shared_ptr<UINode> pressed = nullptr;
std::shared_ptr<UINode> focus = nullptr;
std::shared_ptr<UINode> hover;
std::shared_ptr<UINode> pressed;
std::shared_ptr<UINode> focus;
std::shared_ptr<UINode> tooltip;
std::unordered_map<std::string, std::shared_ptr<UINode>> storage;
std::unique_ptr<Camera> uicamera;
std::shared_ptr<Menu> menu;
std::queue<runnable> postRunnables;
float tooltipTimer = 0.0f;
float tooltipDelay = 0.5f;
float doubleClickTimer = 0.0f;
float doubleClickDelay = 0.5f;
bool doubleClicked = false;
void actMouse(float delta);
void actFocused();
void updateTooltip(float delta);
public:
GUI();
~GUI();

View File

@ -1,7 +1,9 @@
#include "InventoryView.hpp"
#include "../../../assets/Assets.hpp"
#include "../../../content/Content.hpp"
#include "../../../frontend/LevelFrontend.hpp"
#include "../../../frontend/locale.hpp"
#include "../../../items/Inventories.hpp"
#include "../../../items/Inventory.hpp"
#include "../../../items/ItemDef.hpp"
@ -22,7 +24,6 @@
#include "../../render/BlocksPreview.hpp"
#include "../GUI.hpp"
#include <iostream>
#include <glm/glm.hpp>
using namespace gui;
@ -270,6 +271,17 @@ void SlotView::onFocus(gui::GUI* gui) {
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(
int64_t inventoryid,
ItemStack& stack,

View File

@ -63,6 +63,7 @@ namespace gui {
virtual void clicked(gui::GUI*, mousecode) override;
virtual void onFocus(gui::GUI*) override;
virtual const std::wstring getTooltip() const override;
void bind(
int64_t inventoryid,

View File

@ -64,12 +64,28 @@ Label::Label(std::wstring text, std::string fontName)
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) {
if (text == this->text && !cache.resetFlag) {
return;
}
this->text = text;
cache.update(this->text, multiline, textWrap);
if (cache.font) {
setSize(calcSize());
}
}
const std::wstring& Label::getText() const {
@ -156,10 +172,10 @@ void Label::draw(const DrawContext* pctx, Assets* assets) {
lineHeight *= lineInterval;
}
glm::vec2 size = getSize();
glm::vec2 newsize (
font->calcWidth(text),
lineHeight * cache.lines.size() + font->getYOffset()
);
glm::vec2 newsize = calcSize();
if (autoresize) {
setSize(newsize);
}
glm::vec2 pos = calcPos();
switch (align) {
@ -194,6 +210,13 @@ void Label::textSupplier(wstringsupplier supplier) {
this->supplier = supplier;
}
void Label::setAutoResize(bool flag) {
this->autoresize = flag;
}
bool Label::isAutoResize() const {
return autoresize;
}
void Label::setMultiline(bool multiline) {
if (multiline != this->multiline) {

View File

@ -24,6 +24,8 @@ namespace gui {
class Label : public UINode {
LabelCache cache;
glm::vec2 calcSize();
protected:
std::wstring text;
std::string fontName;
@ -47,6 +49,9 @@ namespace gui {
/// @brief Text line height multiplied by line interval
int totalLineHeight = 1;
/// @brief Auto resize label to fit text
bool autoresize = false;
public:
Label(std::string 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 setAutoResize(bool flag);
virtual bool isAutoResize() const;
virtual void setMultiline(bool multiline);
virtual bool isMultiline() const;

View File

@ -129,6 +129,14 @@ bool UINode::isResizing() const {
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 {
if (parent) {
return pos + parent->calcPos() + parent->contentOffset();
@ -316,7 +324,7 @@ void UINode::setGravity(Gravity gravity) {
}
void UINode::getIndices(
std::shared_ptr<UINode> node,
const std::shared_ptr<UINode> node,
std::unordered_map<std::string, std::shared_ptr<UINode>>& map
) {
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;
}

View File

@ -109,6 +109,8 @@ namespace gui {
ActionsSet actions;
/// @brief 'ondoubleclick' callbacks
ActionsSet doubleClickCallbacks;
/// @brief element tooltip text
std::wstring tooltip;
UINode(glm::vec2 size);
public:
@ -197,6 +199,9 @@ namespace gui {
virtual void setResizing(bool flag);
virtual bool isResizing() const;
virtual void setTooltip(const std::wstring& text);
virtual const std::wstring getTooltip() const;
virtual glm::vec4 calcColor() const;
/// @brief Get inner content offset. Used for scroll
@ -237,9 +242,14 @@ namespace gui {
/// @brief collect all nodes having id
static void getIndices(
std::shared_ptr<UINode> node,
const std::shared_ptr<UINode> node,
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
);
};
}

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")) {
node.listenAction(onclick);
}
@ -245,6 +249,9 @@ static std::shared_ptr<UINode> readLabel(UiXmlReader& reader, xml::xmlelement el
reader.getFilename()
));
}
if (element->has("autoresize")) {
label->setAutoResize(element->attr("autoresize").asBool());
}
if (element->has("multiline")) {
label->setMultiline(element->attr("multiline").asBool());
if (!element->has("valign")) {

View File

@ -264,6 +264,9 @@ static int p_get_hover_color(UINode* node) {
static int p_get_pressed_color(UINode* node) {
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) {
return lua::pushvec2_arr(state->getLua(), node->getPos());
}
@ -300,6 +303,7 @@ static int l_gui_getattr(lua_State* L) {
{"color", p_get_color},
{"hoverColor", p_get_hover_color},
{"pressedColor", p_get_pressed_color},
{"tooltip", p_get_tooltip},
{"pos", p_get_pos},
{"wpos", p_get_wpos},
{"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) {
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) {
node->setPos(state->tovec2(idx));
}
@ -464,6 +471,7 @@ static int l_gui_setattr(lua_State* L) {
{"color", p_set_color},
{"hoverColor", p_set_hover_color},
{"pressedColor", p_set_pressed_color},
{"tooltip", p_set_tooltip},
{"pos", p_set_pos},
{"wpos", p_set_wpos},
{"size", p_set_size},