added tooltips
This commit is contained in:
parent
1c45236693
commit
eb10904069
@ -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) {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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")) {
|
||||
|
||||
@ -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},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user