refactor: add GUI instance reference to UI nodes
This commit is contained in:
+61
-43
@@ -1,13 +1,15 @@
|
||||
#include "GUI.hpp"
|
||||
|
||||
#include "gui_util.hpp"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
#include "elements/UINode.hpp"
|
||||
#include "assets/Assets.hpp"
|
||||
#include "elements/Label.hpp"
|
||||
#include "elements/Menu.hpp"
|
||||
#include "elements/Panel.hpp"
|
||||
|
||||
#include "assets/Assets.hpp"
|
||||
#include "elements/UINode.hpp"
|
||||
#include "engine/Engine.hpp"
|
||||
#include "frontend/UiDocument.hpp"
|
||||
#include "frontend/locale.hpp"
|
||||
#include "graphics/core/Batch2D.hpp"
|
||||
@@ -15,31 +17,36 @@
|
||||
#include "graphics/core/Shader.hpp"
|
||||
#include "graphics/core/Font.hpp"
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
#include "graphics/core/Shader.hpp"
|
||||
#include "gui_util.hpp"
|
||||
#include "window/Camera.hpp"
|
||||
#include "window/Events.hpp"
|
||||
#include "window/Window.hpp"
|
||||
#include "window/input.hpp"
|
||||
#include "window/Camera.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
using namespace gui;
|
||||
|
||||
GUI::GUI()
|
||||
: batch2D(std::make_unique<Batch2D>(1024)),
|
||||
container(std::make_shared<Container>(glm::vec2(1000))) {
|
||||
GUI::GUI(Engine& engine)
|
||||
: engine(engine),
|
||||
input(engine.getInput()),
|
||||
batch2D(std::make_unique<Batch2D>(1024)),
|
||||
container(std::make_shared<Container>(*this, glm::vec2(1000))) {
|
||||
container->setId("root");
|
||||
uicamera = std::make_unique<Camera>(glm::vec3(), Window::height);
|
||||
uicamera->perspective = false;
|
||||
uicamera->flipped = true;
|
||||
|
||||
menu = std::make_shared<Menu>();
|
||||
menu = std::make_shared<Menu>(*this);
|
||||
menu->setId("menu");
|
||||
menu->setZIndex(10);
|
||||
container->add(menu);
|
||||
container->setScrollable(false);
|
||||
|
||||
tooltip = guiutil::create(
|
||||
*this,
|
||||
"<container color='#000000A0' interactive='false' z-index='999'>"
|
||||
"<label id='tooltip.label' pos='2' autoresize='true' multiline='true' text-wrap='false'></label>"
|
||||
"</container>"
|
||||
@@ -65,12 +72,15 @@ std::shared_ptr<Menu> GUI::getMenu() {
|
||||
}
|
||||
|
||||
void GUI::onAssetsLoad(Assets* assets) {
|
||||
assets->store(std::make_unique<UiDocument>(
|
||||
"core:root",
|
||||
uidocscript {},
|
||||
std::dynamic_pointer_cast<gui::UINode>(container),
|
||||
nullptr
|
||||
), "core:root");
|
||||
assets->store(
|
||||
std::make_unique<UiDocument>(
|
||||
"core:root",
|
||||
uidocscript {},
|
||||
std::dynamic_pointer_cast<gui::UINode>(container),
|
||||
nullptr
|
||||
),
|
||||
"core:root"
|
||||
);
|
||||
}
|
||||
|
||||
void GUI::resetTooltip() {
|
||||
@@ -79,11 +89,13 @@ void GUI::resetTooltip() {
|
||||
}
|
||||
|
||||
void GUI::updateTooltip(float delta) {
|
||||
if (hover == nullptr || !hover->isInside(Events::cursor)) {
|
||||
const auto& cursor = input.getCursor();
|
||||
if (hover == nullptr || !hover->isInside(cursor.pos)) {
|
||||
return resetTooltip();
|
||||
}
|
||||
if (tooltipTimer + delta >= hover->getTooltipDelay()) {
|
||||
auto label = std::dynamic_pointer_cast<gui::Label>(get("tooltip.label"));
|
||||
auto label =
|
||||
std::dynamic_pointer_cast<gui::Label>(get("tooltip.label"));
|
||||
const auto& text = hover->getTooltip();
|
||||
if (text.empty() && tooltip->isVisible()) {
|
||||
return resetTooltip();
|
||||
@@ -91,11 +103,11 @@ void GUI::updateTooltip(float delta) {
|
||||
if (label && !text.empty()) {
|
||||
tooltip->setVisible(true);
|
||||
label->setText(langs::get(text));
|
||||
auto size = label->getSize()+glm::vec2(4.0f);
|
||||
auto pos = Events::cursor+glm::vec2(10.0f);
|
||||
auto size = label->getSize() + glm::vec2(4.0f);
|
||||
auto pos = cursor.pos + glm::vec2(10.0f);
|
||||
auto rootSize = container->getSize();
|
||||
pos.x = glm::min(pos.x, rootSize.x-size.x);
|
||||
pos.y = glm::min(pos.y, rootSize.y-size.y);
|
||||
pos.x = glm::min(pos.x, rootSize.x - size.x);
|
||||
pos.y = glm::min(pos.y, rootSize.y - size.y);
|
||||
tooltip->setSize(size);
|
||||
tooltip->setPos(pos);
|
||||
}
|
||||
@@ -103,9 +115,9 @@ void GUI::updateTooltip(float delta) {
|
||||
tooltipTimer += delta;
|
||||
}
|
||||
|
||||
/// @brief Mouse related input and logic handling
|
||||
void GUI::actMouse(float delta) {
|
||||
float mouseDelta = glm::length(Events::delta);
|
||||
/// @brief Mouse related input and logic handling
|
||||
void GUI::actMouse(float delta, const CursorState& cursor) {
|
||||
float mouseDelta = glm::length(cursor.delta);
|
||||
doubleClicked = false;
|
||||
doubleClickTimer += delta + mouseDelta * 0.1f;
|
||||
|
||||
@@ -116,21 +128,21 @@ void GUI::actMouse(float delta) {
|
||||
if (hover) {
|
||||
hover->setHover(true);
|
||||
|
||||
int scroll = Events::getScroll();
|
||||
int scroll = input.getScroll();
|
||||
if (scroll) {
|
||||
hover->scrolled(scroll);
|
||||
}
|
||||
}
|
||||
this->hover = hover;
|
||||
|
||||
if (Events::jclicked(mousecode::BUTTON_1)) {
|
||||
if (input.jclicked(mousecode::BUTTON_1)) {
|
||||
if (pressed == nullptr && this->hover) {
|
||||
pressed = hover;
|
||||
if (doubleClickTimer < doubleClickDelay) {
|
||||
pressed->doubleClick(this, Events::cursor.x, Events::cursor.y);
|
||||
pressed->doubleClick(cursor.pos.x, cursor.pos.y);
|
||||
doubleClicked = true;
|
||||
} else {
|
||||
pressed->click(this, Events::cursor.x, Events::cursor.y);
|
||||
pressed->click(cursor.pos.x, cursor.pos.y);
|
||||
}
|
||||
doubleClickTimer = 0.0f;
|
||||
if (focus && focus != pressed) {
|
||||
@@ -138,7 +150,7 @@ void GUI::actMouse(float delta) {
|
||||
}
|
||||
if (focus != pressed) {
|
||||
focus = pressed;
|
||||
focus->onFocus(this);
|
||||
focus->onFocus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -146,22 +158,22 @@ void GUI::actMouse(float delta) {
|
||||
focus->defocus();
|
||||
focus = nullptr;
|
||||
}
|
||||
} else if (!Events::clicked(mousecode::BUTTON_1) && pressed) {
|
||||
pressed->mouseRelease(this, Events::cursor.x, Events::cursor.y);
|
||||
} else if (!input.clicked(mousecode::BUTTON_1) && pressed) {
|
||||
pressed->mouseRelease(cursor.pos.x, cursor.pos.y);
|
||||
pressed = nullptr;
|
||||
}
|
||||
|
||||
if (hover) {
|
||||
for (mousecode code : MOUSECODES_ALL) {
|
||||
if (Events::jclicked(code)) {
|
||||
hover->clicked(this, code);
|
||||
if (input.jclicked(code)) {
|
||||
hover->clicked(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::actFocused() {
|
||||
if (Events::jpressed(keycode::ESCAPE)) {
|
||||
if (input.jpressed(keycode::ESCAPE)) {
|
||||
focus->defocus();
|
||||
focus = nullptr;
|
||||
return;
|
||||
@@ -173,12 +185,13 @@ void GUI::actFocused() {
|
||||
focus->keyPressed(key);
|
||||
}
|
||||
|
||||
if (!Events::isCursorLocked()) {
|
||||
if (Events::clicked(mousecode::BUTTON_1) &&
|
||||
(Events::jclicked(mousecode::BUTTON_1) || Events::delta.x || Events::delta.y))
|
||||
{
|
||||
const auto& cursor = input.getCursor();
|
||||
if (!cursor.locked) {
|
||||
if (input.clicked(mousecode::BUTTON_1) &&
|
||||
(input.jclicked(mousecode::BUTTON_1) || cursor.delta.x ||
|
||||
cursor.delta.y)) {
|
||||
if (!doubleClicked) {
|
||||
focus->mouseMove(this, Events::cursor.x, Events::cursor.y);
|
||||
focus->mouseMove(cursor.pos.x, cursor.pos.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,15 +203,16 @@ void GUI::act(float delta, const Viewport& vp) {
|
||||
auto prevfocus = focus;
|
||||
|
||||
updateTooltip(delta);
|
||||
|
||||
const auto& cursor = input.getCursor();
|
||||
if (!Events::isCursorLocked()) {
|
||||
actMouse(delta);
|
||||
actMouse(delta, cursor);
|
||||
} else {
|
||||
if (hover) {
|
||||
hover->setHover(false);
|
||||
hover = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (focus) {
|
||||
actFocused();
|
||||
}
|
||||
@@ -316,7 +330,7 @@ void GUI::setFocus(std::shared_ptr<UINode> node) {
|
||||
}
|
||||
focus = std::move(node);
|
||||
if (focus) {
|
||||
focus->onFocus(this);
|
||||
focus->onFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,3 +353,7 @@ float GUI::getDoubleClickDelay() const {
|
||||
void GUI::toggleDebug() {
|
||||
debug = !debug;
|
||||
}
|
||||
|
||||
const Input& GUI::getInput() const {
|
||||
return engine.getInput();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,9 @@ class DrawContext;
|
||||
class Assets;
|
||||
class Camera;
|
||||
class Batch2D;
|
||||
class LineBatch;
|
||||
struct CursorState;
|
||||
class Engine;
|
||||
class Input;
|
||||
|
||||
/*
|
||||
Some info about padding and margin.
|
||||
@@ -56,6 +58,8 @@ namespace gui {
|
||||
|
||||
/// @brief The main UI controller
|
||||
class GUI {
|
||||
Engine& engine;
|
||||
Input& input;
|
||||
std::unique_ptr<Batch2D> batch2D;
|
||||
std::shared_ptr<Container> container;
|
||||
std::shared_ptr<UINode> hover;
|
||||
@@ -76,12 +80,12 @@ namespace gui {
|
||||
bool doubleClicked = false;
|
||||
bool debug = false;
|
||||
|
||||
void actMouse(float delta);
|
||||
void actMouse(float delta, const CursorState& cursor);
|
||||
void actFocused();
|
||||
void updateTooltip(float delta);
|
||||
void resetTooltip();
|
||||
public:
|
||||
GUI();
|
||||
GUI(Engine& engine);
|
||||
~GUI();
|
||||
|
||||
void setPageLoader(PageLoaderFunc pageLoader);
|
||||
@@ -152,5 +156,6 @@ namespace gui {
|
||||
float getDoubleClickDelay() const;
|
||||
|
||||
void toggleDebug();
|
||||
const Input& getInput() const;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -26,12 +26,13 @@ namespace gui {
|
||||
}
|
||||
protected:
|
||||
BasePanel(
|
||||
GUI& gui,
|
||||
glm::vec2 size,
|
||||
glm::vec4 padding = glm::vec4(0.0f),
|
||||
float interval = 2.0f,
|
||||
Orientation orientation = Orientation::vertical
|
||||
)
|
||||
: Container(std::move(size)),
|
||||
: Container(gui, std::move(size)),
|
||||
padding(std::move(padding)),
|
||||
interval(interval) {
|
||||
}
|
||||
|
||||
@@ -3,17 +3,23 @@
|
||||
#include <utility>
|
||||
|
||||
#include "Label.hpp"
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
#include "graphics/core/Batch2D.hpp"
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
|
||||
using namespace gui;
|
||||
|
||||
Button::Button(const std::shared_ptr<UINode>& content, glm::vec4 padding)
|
||||
: Panel(glm::vec2(), padding, 0) {
|
||||
Button::Button(
|
||||
GUI& gui, const std::shared_ptr<UINode>& content, glm::vec4 padding
|
||||
)
|
||||
: Panel(gui, glm::vec2(), padding, 0) {
|
||||
glm::vec4 margin = getMargin();
|
||||
setSize(content->getSize()+
|
||||
glm::vec2(padding[0]+padding[2]+margin[0]+margin[2],
|
||||
padding[1]+padding[3]+margin[1]+margin[3]));
|
||||
setSize(
|
||||
content->getSize() +
|
||||
glm::vec2(
|
||||
padding[0] + padding[2] + margin[0] + margin[2],
|
||||
padding[1] + padding[3] + margin[1] + margin[3]
|
||||
)
|
||||
);
|
||||
add(content);
|
||||
setScrollable(false);
|
||||
setHoverColor(glm::vec4(0.05f, 0.1f, 0.15f, 0.75f));
|
||||
@@ -22,15 +28,16 @@ Button::Button(const std::shared_ptr<UINode>& content, glm::vec4 padding)
|
||||
}
|
||||
|
||||
Button::Button(
|
||||
GUI& gui,
|
||||
const std::wstring& text,
|
||||
glm::vec4 padding,
|
||||
glm::vec4 padding,
|
||||
const onaction& action,
|
||||
glm::vec2 size
|
||||
) : Panel(size, padding, 0)
|
||||
{
|
||||
)
|
||||
: Panel(gui, size, padding, 0) {
|
||||
if (size.y < 0.0f) {
|
||||
size = glm::vec2(
|
||||
glm::max(padding.x + padding.z + text.length()*8, size.x),
|
||||
glm::max(padding.x + padding.z + text.length() * 8, size.x),
|
||||
glm::max(padding.y + padding.w + 16, size.y)
|
||||
);
|
||||
}
|
||||
@@ -41,9 +48,11 @@ Button::Button(
|
||||
}
|
||||
setScrollable(false);
|
||||
|
||||
label = std::make_shared<Label>(text);
|
||||
label = std::make_shared<Label>(gui, text);
|
||||
label->setAlign(Align::center);
|
||||
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
|
||||
label->setSize(
|
||||
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
|
||||
);
|
||||
label->setInteractive(false);
|
||||
add(label);
|
||||
setHoverColor(glm::vec4(0.05f, 0.1f, 0.15f, 0.75f));
|
||||
@@ -73,7 +82,9 @@ Button* Button::textSupplier(wstringsupplier supplier) {
|
||||
void Button::refresh() {
|
||||
Panel::refresh();
|
||||
if (label) {
|
||||
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
|
||||
label->setSize(
|
||||
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,13 +9,19 @@ namespace gui {
|
||||
protected:
|
||||
std::shared_ptr<Label> label;
|
||||
public:
|
||||
Button(const std::shared_ptr<UINode>& content,
|
||||
glm::vec4 padding=glm::vec4(2.0f));
|
||||
|
||||
Button(const std::wstring& text,
|
||||
glm::vec4 padding,
|
||||
const onaction& action,
|
||||
glm::vec2 size=glm::vec2(-1));
|
||||
Button(
|
||||
GUI& gui,
|
||||
const std::shared_ptr<UINode>& content,
|
||||
glm::vec4 padding = glm::vec4(2.0f)
|
||||
);
|
||||
|
||||
Button(
|
||||
GUI& gui,
|
||||
const std::wstring& text,
|
||||
glm::vec4 padding,
|
||||
const onaction& action,
|
||||
glm::vec2 size = glm::vec2(-1)
|
||||
);
|
||||
|
||||
virtual void drawBackground(
|
||||
const DrawContext& pctx, const Assets& assets
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
#include "graphics/core/Texture.hpp"
|
||||
|
||||
gui::Canvas::Canvas(ImageFormat inFormat, glm::uvec2 inSize) : UINode(inSize) {
|
||||
gui::Canvas::Canvas(GUI& gui, ImageFormat inFormat, glm::uvec2 inSize)
|
||||
: UINode(gui, inSize) {
|
||||
auto data = std::make_shared<ImageData>(inFormat, inSize.x, inSize.y);
|
||||
mTexture = Texture::from(data.get());
|
||||
mData = std::move(data);
|
||||
|
||||
@@ -9,7 +9,7 @@ class Texture;
|
||||
namespace gui {
|
||||
class Canvas final : public UINode {
|
||||
public:
|
||||
explicit Canvas(ImageFormat inFormat, glm::uvec2 inSize);
|
||||
explicit Canvas(GUI& gui, ImageFormat inFormat, glm::uvec2 inSize);
|
||||
|
||||
~Canvas() override = default;
|
||||
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
#include "graphics/core/Batch2D.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "graphics/core/Batch2D.hpp"
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
|
||||
using namespace gui;
|
||||
|
||||
CheckBox::CheckBox(bool checked) : UINode(glm::vec2(32.0f)), checked(checked) {
|
||||
CheckBox::CheckBox(GUI& gui, bool checked)
|
||||
: UINode(gui, glm::vec2(32.0f)), checked(checked) {
|
||||
setColor({0.0f, 0.0f, 0.0f, 0.5f});
|
||||
setHoverColor({0.05f, 0.1f, 0.2f, 0.75f});
|
||||
}
|
||||
@@ -24,7 +25,7 @@ void CheckBox::draw(const DrawContext& pctx, const Assets&) {
|
||||
batch->rect(pos.x, pos.y, size.x, size.y);
|
||||
}
|
||||
|
||||
void CheckBox::mouseRelease(GUI*, int, int) {
|
||||
void CheckBox::mouseRelease(int, int) {
|
||||
checked = !checked;
|
||||
if (consumer) {
|
||||
consumer(checked);
|
||||
@@ -44,15 +45,17 @@ CheckBox* CheckBox::setChecked(bool flag) {
|
||||
return this;
|
||||
}
|
||||
|
||||
FullCheckBox::FullCheckBox(const std::wstring& text, glm::vec2 size, bool checked)
|
||||
: Panel(size),
|
||||
checkbox(std::make_shared<CheckBox>(checked)),
|
||||
label(std::make_shared<Label>(text)) {
|
||||
FullCheckBox::FullCheckBox(
|
||||
GUI& gui, const std::wstring& text, glm::vec2 size, bool checked
|
||||
)
|
||||
: Panel(gui, size),
|
||||
checkbox(std::make_shared<CheckBox>(gui, checked)),
|
||||
label(std::make_shared<Label>(gui, text)) {
|
||||
setColor(glm::vec4(0.0f));
|
||||
setOrientation(Orientation::horizontal);
|
||||
|
||||
add(checkbox);
|
||||
|
||||
|
||||
label->setMargin(glm::vec4(5.f, 5.f, 0.f, 0.f));
|
||||
add(label);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "Panel.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "Panel.hpp"
|
||||
|
||||
namespace gui {
|
||||
class CheckBox : public UINode {
|
||||
@@ -13,11 +13,12 @@ namespace gui {
|
||||
boolconsumer consumer = nullptr;
|
||||
bool checked = false;
|
||||
public:
|
||||
CheckBox(bool checked=false);
|
||||
explicit CheckBox(GUI& gui, bool checked = false);
|
||||
|
||||
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
||||
virtual void draw(const DrawContext& pctx, const Assets& assets)
|
||||
override;
|
||||
|
||||
virtual void mouseRelease(GUI*, int x, int y) override;
|
||||
virtual void mouseRelease(int x, int y) override;
|
||||
|
||||
virtual void setSupplier(boolsupplier supplier);
|
||||
virtual void setConsumer(boolconsumer consumer);
|
||||
@@ -25,8 +26,7 @@ namespace gui {
|
||||
virtual CheckBox* setChecked(bool flag);
|
||||
|
||||
virtual bool isChecked() const {
|
||||
if (supplier)
|
||||
return supplier();
|
||||
if (supplier) return supplier();
|
||||
return checked;
|
||||
}
|
||||
};
|
||||
@@ -36,7 +36,12 @@ namespace gui {
|
||||
std::shared_ptr<CheckBox> checkbox;
|
||||
std::shared_ptr<Label> label;
|
||||
public:
|
||||
FullCheckBox(const std::wstring& text, glm::vec2 size, bool checked=false);
|
||||
explicit FullCheckBox(
|
||||
GUI& gui,
|
||||
const std::wstring& text,
|
||||
glm::vec2 size,
|
||||
bool checked = false
|
||||
);
|
||||
|
||||
virtual void setSupplier(boolsupplier supplier) {
|
||||
checkbox->setSupplier(std::move(supplier));
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
using namespace gui;
|
||||
|
||||
Container::Container(glm::vec2 size) : UINode(size) {
|
||||
Container::Container(GUI& gui, glm::vec2 size) : UINode(gui, size) {
|
||||
actualLength = size.y;
|
||||
setColor(glm::vec4());
|
||||
}
|
||||
@@ -41,8 +41,8 @@ std::shared_ptr<UINode> Container::getAt(const glm::vec2& pos) {
|
||||
return UINode::getAt(pos);
|
||||
}
|
||||
|
||||
void Container::mouseMove(GUI* gui, int x, int y) {
|
||||
UINode::mouseMove(gui, x, y);
|
||||
void Container::mouseMove(int x, int y) {
|
||||
UINode::mouseMove(x, y);
|
||||
if (!scrollable) {
|
||||
return;
|
||||
}
|
||||
@@ -65,8 +65,8 @@ void Container::mouseMove(GUI* gui, int x, int y) {
|
||||
prevScrollY = y;
|
||||
}
|
||||
|
||||
void Container::mouseRelease(GUI* gui, int x, int y) {
|
||||
UINode::mouseRelease(gui, x, y);
|
||||
void Container::mouseRelease(int x, int y) {
|
||||
UINode::mouseRelease(x, y);
|
||||
prevScrollY = -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <vector>
|
||||
|
||||
namespace gui {
|
||||
class Container : public UINode, public util::ObjectsKeeper {
|
||||
class Container : public UINode, public ::util::ObjectsKeeper {
|
||||
int prevScrollY = -1;
|
||||
protected:
|
||||
std::vector<std::shared_ptr<UINode>> nodes;
|
||||
@@ -22,7 +22,7 @@ namespace gui {
|
||||
return prevScrollY != -1;
|
||||
}
|
||||
public:
|
||||
Container(glm::vec2 size);
|
||||
Container(GUI& gui, glm::vec2 size);
|
||||
virtual ~Container();
|
||||
|
||||
virtual void act(float delta) override;
|
||||
@@ -44,8 +44,8 @@ namespace gui {
|
||||
virtual void refresh() override;
|
||||
void setScroll(int scroll);
|
||||
|
||||
virtual void mouseMove(GUI*, int x, int y) override;
|
||||
virtual void mouseRelease(GUI*, int x, int y) override;
|
||||
virtual void mouseMove(int x, int y) override;
|
||||
virtual void mouseRelease(int x, int y) override;
|
||||
|
||||
const std::vector<std::shared_ptr<UINode>>& getNodes() const;
|
||||
};
|
||||
|
||||
@@ -2,23 +2,24 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
#include "graphics/core/Batch2D.hpp"
|
||||
#include "graphics/core/Texture.hpp"
|
||||
#include "graphics/core/Atlas.hpp"
|
||||
#include "assets/Assets.hpp"
|
||||
#include "graphics/core/Atlas.hpp"
|
||||
#include "graphics/core/Batch2D.hpp"
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
#include "graphics/core/Texture.hpp"
|
||||
#include "maths/UVRegion.hpp"
|
||||
|
||||
using namespace gui;
|
||||
|
||||
Image::Image(std::string texture, glm::vec2 size) : UINode(size), texture(std::move(texture)) {
|
||||
Image::Image(GUI& gui, std::string texture, glm::vec2 size)
|
||||
: UINode(gui, size), texture(std::move(texture)) {
|
||||
setInteractive(false);
|
||||
}
|
||||
|
||||
void Image::draw(const DrawContext& pctx, const Assets& assets) {
|
||||
glm::vec2 pos = calcPos();
|
||||
auto batch = pctx.getBatch2D();
|
||||
|
||||
|
||||
Texture* texture = nullptr;
|
||||
auto separator = this->texture.find(':');
|
||||
if (separator == std::string::npos) {
|
||||
@@ -30,14 +31,16 @@ void Image::draw(const DrawContext& pctx, const Assets& assets) {
|
||||
} else {
|
||||
auto atlasName = this->texture.substr(0, separator);
|
||||
if (auto atlas = assets.get<Atlas>(atlasName)) {
|
||||
if (auto region = atlas->getIf(this->texture.substr(separator+1))) {
|
||||
if (auto region =
|
||||
atlas->getIf(this->texture.substr(separator + 1))) {
|
||||
texture = atlas->getTexture();
|
||||
batch->texture(atlas->getTexture());
|
||||
batch->setRegion(*region);
|
||||
if (autoresize) {
|
||||
setSize(glm::vec2(
|
||||
texture->getWidth()*region->getWidth(),
|
||||
texture->getHeight()*region->getHeight()));
|
||||
texture->getWidth() * region->getWidth(),
|
||||
texture->getHeight() * region->getHeight()
|
||||
));
|
||||
}
|
||||
} else {
|
||||
batch->texture(nullptr);
|
||||
@@ -45,8 +48,17 @@ void Image::draw(const DrawContext& pctx, const Assets& assets) {
|
||||
}
|
||||
}
|
||||
batch->rect(
|
||||
pos.x, pos.y, size.x, size.y,
|
||||
0, 0, 0, UVRegion(), false, true, calcColor()
|
||||
pos.x,
|
||||
pos.y,
|
||||
size.x,
|
||||
size.y,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
UVRegion(),
|
||||
false,
|
||||
true,
|
||||
calcColor()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace gui {
|
||||
std::string texture;
|
||||
bool autoresize = false;
|
||||
public:
|
||||
Image(std::string texture, glm::vec2 size=glm::vec2(32,32));
|
||||
Image(GUI& gui, std::string texture, glm::vec2 size=glm::vec2(32,32));
|
||||
|
||||
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
|
||||
using namespace gui;
|
||||
|
||||
InputBindBox::InputBindBox(Binding& binding, glm::vec4 padding)
|
||||
: Panel(glm::vec2(100,32), padding, 0),
|
||||
InputBindBox::InputBindBox(GUI& gui, Binding& binding, glm::vec4 padding)
|
||||
: Panel(gui, glm::vec2(100,32), padding, 0),
|
||||
binding(binding),
|
||||
label(std::make_shared<Label>(L"")) {
|
||||
label(std::make_shared<Label>(gui, L"")) {
|
||||
add(label);
|
||||
setScrollable(false);
|
||||
hoverColor = glm::vec4(0.05f, 0.1f, 0.2f, 0.75f);
|
||||
@@ -25,7 +25,7 @@ void InputBindBox::drawBackground(const DrawContext& pctx, const Assets&) {
|
||||
label->setText(util::str2wstr_utf8(binding.text()));
|
||||
}
|
||||
|
||||
void InputBindBox::clicked(GUI*, mousecode button) {
|
||||
void InputBindBox::clicked(mousecode button) {
|
||||
if (isFocused()) {
|
||||
binding.reset(button);
|
||||
defocus();
|
||||
|
||||
@@ -4,21 +4,25 @@
|
||||
|
||||
namespace gui {
|
||||
class Label;
|
||||
|
||||
|
||||
class InputBindBox : public Panel {
|
||||
protected:
|
||||
Binding& binding;
|
||||
glm::vec4 focusedColor {0.1f, 0.15f, 0.35f, 0.75f};
|
||||
std::shared_ptr<Label> label;
|
||||
public:
|
||||
InputBindBox(Binding& binding, glm::vec4 padding=glm::vec4(6.0f));
|
||||
|
||||
explicit InputBindBox(
|
||||
GUI& gui, Binding& binding, glm::vec4 padding = glm::vec4(6.0f)
|
||||
);
|
||||
|
||||
virtual void drawBackground(
|
||||
const DrawContext& pctx, const Assets& assets
|
||||
) override;
|
||||
|
||||
virtual void clicked(GUI*, mousecode button) override;
|
||||
virtual void clicked(mousecode button) override;
|
||||
virtual void keyPressed(keycode key) override;
|
||||
virtual bool isFocuskeeper() const override {return true;}
|
||||
virtual bool isFocuskeeper() const override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ SlotLayout::SlotLayout(
|
||||
shareFunc(std::move(shareFunc)),
|
||||
rightClick(std::move(rightClick)) {}
|
||||
|
||||
InventoryBuilder::InventoryBuilder() {
|
||||
view = std::make_shared<InventoryView>();
|
||||
InventoryBuilder::InventoryBuilder(GUI& gui) : gui(gui) {
|
||||
view = std::make_shared<InventoryView>(gui);
|
||||
}
|
||||
|
||||
void InventoryBuilder::addGrid(
|
||||
@@ -75,7 +75,8 @@ void InventoryBuilder::addGrid(
|
||||
view->setSize(vsize);
|
||||
|
||||
if (addpanel) {
|
||||
auto panel = std::make_shared<gui::Container>(glm::vec2(width, height));
|
||||
auto panel =
|
||||
std::make_shared<gui::Container>(gui, glm::vec2(width, height));
|
||||
view->setColor(glm::vec4(0.122f, 0.122f, 0.122f, 0.878f));
|
||||
view->add(panel, pos);
|
||||
}
|
||||
@@ -106,8 +107,8 @@ std::shared_ptr<InventoryView> InventoryBuilder::build() {
|
||||
}
|
||||
|
||||
SlotView::SlotView(
|
||||
SlotLayout layout
|
||||
) : UINode(glm::vec2(InventoryView::SLOT_SIZE)),
|
||||
GUI& gui, SlotLayout layout
|
||||
) : UINode(gui, glm::vec2(InventoryView::SLOT_SIZE)),
|
||||
layout(std::move(layout))
|
||||
{
|
||||
setColor(glm::vec4(0, 0, 0, 0.2f));
|
||||
@@ -347,11 +348,11 @@ void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) {
|
||||
}
|
||||
}
|
||||
|
||||
void SlotView::clicked(gui::GUI* gui, mousecode button) {
|
||||
void SlotView::clicked(mousecode button) {
|
||||
if (bound == nullptr)
|
||||
return;
|
||||
auto exchangeSlot =
|
||||
std::dynamic_pointer_cast<SlotView>(gui->get(EXCHANGE_SLOT_NAME));
|
||||
std::dynamic_pointer_cast<SlotView>(gui.get(EXCHANGE_SLOT_NAME));
|
||||
if (exchangeSlot == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -368,8 +369,8 @@ void SlotView::clicked(gui::GUI* gui, mousecode button) {
|
||||
}
|
||||
}
|
||||
|
||||
void SlotView::onFocus(gui::GUI* gui) {
|
||||
clicked(gui, mousecode::BUTTON_1);
|
||||
void SlotView::onFocus() {
|
||||
clicked(mousecode::BUTTON_1);
|
||||
}
|
||||
|
||||
const std::wstring& SlotView::getTooltip() const {
|
||||
@@ -398,7 +399,7 @@ ItemStack& SlotView::getStack() {
|
||||
return *bound;
|
||||
}
|
||||
|
||||
InventoryView::InventoryView() : Container(glm::vec2()) {
|
||||
InventoryView::InventoryView(GUI& gui) : Container(gui, glm::vec2()) {
|
||||
setColor(glm::vec4(0, 0, 0, 0.0f));
|
||||
}
|
||||
|
||||
@@ -419,7 +420,7 @@ std::shared_ptr<SlotView> InventoryView::addSlot(const SlotLayout& layout) {
|
||||
}
|
||||
setSize(vsize);
|
||||
|
||||
auto slot = std::make_shared<SlotView>(layout);
|
||||
auto slot = std::make_shared<SlotView>(gui, layout);
|
||||
if (!layout.background) {
|
||||
slot->setColor(glm::vec4());
|
||||
}
|
||||
|
||||
@@ -86,15 +86,15 @@ namespace gui {
|
||||
|
||||
void refreshTooltip(const ItemStack& stack, const ItemDef& item);
|
||||
public:
|
||||
SlotView(SlotLayout layout);
|
||||
SlotView(GUI& gui, SlotLayout layout);
|
||||
|
||||
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
||||
|
||||
void setHighlighted(bool flag);
|
||||
bool isHighlighted() const;
|
||||
|
||||
virtual void clicked(gui::GUI*, mousecode) override;
|
||||
virtual void onFocus(gui::GUI*) override;
|
||||
virtual void clicked(mousecode) override;
|
||||
virtual void onFocus() override;
|
||||
virtual const std::wstring& getTooltip() const override;
|
||||
|
||||
void bind(
|
||||
@@ -117,7 +117,7 @@ namespace gui {
|
||||
std::vector<SlotView*> slots;
|
||||
glm::vec2 origin {};
|
||||
public:
|
||||
InventoryView();
|
||||
InventoryView(GUI& gui);
|
||||
virtual ~InventoryView();
|
||||
|
||||
virtual void setPos(glm::vec2 pos) override;
|
||||
@@ -145,9 +145,10 @@ namespace gui {
|
||||
};
|
||||
|
||||
class InventoryBuilder {
|
||||
GUI& gui;
|
||||
std::shared_ptr<InventoryView> view;
|
||||
public:
|
||||
InventoryBuilder();
|
||||
InventoryBuilder(GUI& gui);
|
||||
|
||||
/// @brief Add slots grid to inventory view
|
||||
/// @param cols grid columns
|
||||
|
||||
@@ -83,8 +83,8 @@ void LabelCache::update(std::wstring_view text, bool multiline, bool wrap) {
|
||||
}
|
||||
}
|
||||
|
||||
Label::Label(const std::string& text, std::string fontName)
|
||||
: UINode(glm::vec2(text.length() * 8, 16)),
|
||||
Label::Label(GUI& gui, const std::string& text, std::string fontName)
|
||||
: UINode(gui, glm::vec2(text.length() * 8, 16)),
|
||||
text(util::str2wstr_utf8(text)),
|
||||
fontName(std::move(fontName))
|
||||
{
|
||||
@@ -93,8 +93,8 @@ Label::Label(const std::string& text, std::string fontName)
|
||||
}
|
||||
|
||||
|
||||
Label::Label(const std::wstring& text, std::string fontName)
|
||||
: UINode(glm::vec2(text.length() * 8, 16)),
|
||||
Label::Label(GUI& gui, const std::wstring& text, std::string fontName)
|
||||
: UINode(gui, glm::vec2(text.length() * 8, 16)),
|
||||
text(text),
|
||||
fontName(std::move(fontName))
|
||||
{
|
||||
|
||||
@@ -63,8 +63,8 @@ namespace gui {
|
||||
|
||||
std::unique_ptr<FontStylesScheme> styles;
|
||||
public:
|
||||
Label(const std::string& text, std::string fontName=FONT_DEFAULT);
|
||||
Label(const std::wstring& text, std::string fontName=FONT_DEFAULT);
|
||||
Label(GUI& gui, const std::string& text, std::string fontName="normal");
|
||||
Label(GUI& gui, const std::wstring& text, std::string fontName="normal");
|
||||
|
||||
virtual ~Label();
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
using namespace gui;
|
||||
|
||||
Menu::Menu() : Container(glm::vec2(1)){
|
||||
Menu::Menu(GUI& gui) : Container(gui, glm::vec2(1)){
|
||||
}
|
||||
|
||||
bool Menu::has(const std::string& name) {
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace gui {
|
||||
std::unordered_map<std::string, supplier<std::shared_ptr<UINode>>> pageSuppliers;
|
||||
PageLoaderFunc pagesLoader = nullptr;
|
||||
public:
|
||||
Menu();
|
||||
explicit Menu(GUI& gui);
|
||||
|
||||
/// @brief Check menu have page or page supplier
|
||||
/// @param name page name
|
||||
|
||||
@@ -4,14 +4,12 @@
|
||||
|
||||
using namespace gui;
|
||||
|
||||
Panel::Panel(glm::vec2 size, glm::vec4 padding, float interval)
|
||||
: BasePanel(size, padding, interval, Orientation::vertical)
|
||||
{
|
||||
Panel::Panel(GUI& gui, glm::vec2 size, glm::vec4 padding, float interval)
|
||||
: BasePanel(gui, size, padding, interval) {
|
||||
setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.75f));
|
||||
}
|
||||
|
||||
Panel::~Panel() {
|
||||
}
|
||||
Panel::~Panel() = default;
|
||||
|
||||
void Panel::setMaxLength(int value) {
|
||||
maxLength = value;
|
||||
@@ -46,7 +44,7 @@ void Panel::fullRefresh() {
|
||||
Container::fullRefresh();
|
||||
}
|
||||
|
||||
void Panel::add(const std::shared_ptr<UINode> &node) {
|
||||
void Panel::add(const std::shared_ptr<UINode>& node) {
|
||||
node->setResizing(true);
|
||||
Container::add(node);
|
||||
fullRefresh();
|
||||
@@ -68,10 +66,10 @@ void Panel::refresh() {
|
||||
for (auto& node : nodes) {
|
||||
const glm::vec4 margin = node->getMargin();
|
||||
y += margin.y;
|
||||
|
||||
|
||||
float ex = x + margin.x;
|
||||
node->setPos(glm::vec2(ex, y));
|
||||
|
||||
|
||||
float width = size.x - padding.x - padding.z - margin.x - margin.z;
|
||||
if (node->isResizing()) {
|
||||
node->setMaxSize({width, node->getMaxSize().y});
|
||||
@@ -80,7 +78,7 @@ void Panel::refresh() {
|
||||
node->refresh();
|
||||
glm::vec2 nodeSize = node->getSize();
|
||||
y += nodeSize.y + margin.w + interval;
|
||||
maxw = fmax(maxw, ex+nodeSize.x+margin.z+padding.z);
|
||||
maxw = fmax(maxw, ex + nodeSize.x + margin.z + padding.z);
|
||||
}
|
||||
actualLength = y + padding.w;
|
||||
} else {
|
||||
@@ -89,11 +87,13 @@ void Panel::refresh() {
|
||||
glm::vec2 nodesize = node->getSize();
|
||||
const glm::vec4 margin = node->getMargin();
|
||||
x += margin.x;
|
||||
node->setPos(glm::vec2(x, y+margin.y));
|
||||
node->setPos(glm::vec2(x, y + margin.y));
|
||||
x += nodesize.x + margin.z + interval;
|
||||
|
||||
|
||||
node->refresh();
|
||||
maxh = fmax(maxh, y+margin.y+node->getSize().y+margin.w+padding.w);
|
||||
maxh = fmax(
|
||||
maxh, y + margin.y + node->getSize().y + margin.w + padding.w
|
||||
);
|
||||
}
|
||||
actualLength = size.y;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "BasePanel.hpp"
|
||||
#include "commons.hpp"
|
||||
|
||||
namespace gui {
|
||||
class Panel : public BasePanel {
|
||||
public:
|
||||
Panel(
|
||||
glm::vec2 size,
|
||||
glm::vec4 padding=glm::vec4(0.0f),
|
||||
float interval=2.0f
|
||||
GUI& gui,
|
||||
glm::vec2 size,
|
||||
glm::vec4 padding = glm::vec4(2.0f),
|
||||
float interval = 2.0f
|
||||
);
|
||||
virtual ~Panel();
|
||||
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <memory>
|
||||
|
||||
#include "UINode.hpp"
|
||||
#include "typedefs.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class Assets;
|
||||
class DrawContext;
|
||||
|
||||
namespace gui {
|
||||
class Plotter : public gui::UINode {
|
||||
class Plotter : public UINode {
|
||||
std::unique_ptr<int[]> points;
|
||||
float multiplier;
|
||||
int index = 0;
|
||||
@@ -17,13 +18,18 @@ namespace gui {
|
||||
int dmheight;
|
||||
int labelsInterval;
|
||||
public:
|
||||
Plotter(uint width, uint height, float multiplier, int labelsInterval)
|
||||
: gui::UINode(glm::vec2(width, height)),
|
||||
multiplier(multiplier),
|
||||
dmwidth(width-50),
|
||||
dmheight(height),
|
||||
labelsInterval(labelsInterval)
|
||||
{
|
||||
Plotter(
|
||||
GUI& gui,
|
||||
uint width,
|
||||
uint height,
|
||||
float multiplier,
|
||||
int labelsInterval
|
||||
)
|
||||
: UINode(gui, glm::vec2(width, height)),
|
||||
multiplier(multiplier),
|
||||
dmwidth(width - 50),
|
||||
dmheight(height),
|
||||
labelsInterval(labelsInterval) {
|
||||
points = std::make_unique<int[]>(dmwidth);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
using namespace gui;
|
||||
|
||||
SplitBox::SplitBox(const glm::vec2& size, float splitPos, Orientation orientation)
|
||||
: BasePanel(size, glm::vec4(), 4.0f, orientation), splitPos(splitPos) {
|
||||
SplitBox::SplitBox(GUI& gui, const glm::vec2& size, float splitPos, Orientation orientation)
|
||||
: BasePanel(gui, size, glm::vec4(), 4.0f, orientation), splitPos(splitPos) {
|
||||
setCursor(
|
||||
orientation == Orientation::vertical ? CursorShape::NS_RESIZE
|
||||
: CursorShape::EW_RESIZE
|
||||
);
|
||||
}
|
||||
|
||||
void SplitBox::mouseMove(GUI*, int x, int y) {
|
||||
void SplitBox::mouseMove(int x, int y) {
|
||||
auto pos = calcPos();
|
||||
auto size = getSize();
|
||||
|
||||
@@ -59,7 +59,7 @@ void SplitBox::refresh() {
|
||||
}
|
||||
}
|
||||
|
||||
void SplitBox::doubleClick(GUI*, int x, int y) {
|
||||
void SplitBox::doubleClick(int x, int y) {
|
||||
if (nodes.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
namespace gui {
|
||||
class SplitBox : public BasePanel {
|
||||
public:
|
||||
SplitBox(const glm::vec2& size, float splitPos, Orientation orientation);
|
||||
SplitBox(GUI& gui, const glm::vec2& size, float splitPos, Orientation orientation);
|
||||
|
||||
virtual void mouseMove(GUI*, int x, int y) override;
|
||||
virtual void mouseMove(int x, int y) override;
|
||||
virtual void refresh() override;
|
||||
virtual void fullRefresh() override;
|
||||
virtual void doubleClick(GUI*, int x, int y) override;
|
||||
virtual void doubleClick(int x, int y) override;
|
||||
private:
|
||||
float splitPos;
|
||||
};
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include "../GUI.hpp"
|
||||
#include "../markdown.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "assets/Assets.hpp"
|
||||
#include "devtools/syntax_highlighting.hpp"
|
||||
#include "engine/Engine.hpp"
|
||||
#include "graphics/core/Batch2D.hpp"
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
#include "graphics/core/Font.hpp"
|
||||
@@ -186,8 +189,9 @@ namespace gui {
|
||||
};
|
||||
}
|
||||
|
||||
TextBox::TextBox(std::wstring placeholder, glm::vec4 padding)
|
||||
: Container(glm::vec2(200, 32)),
|
||||
TextBox::TextBox(GUI& gui, std::wstring placeholder, glm::vec4 padding)
|
||||
: Container(gui, glm::vec2(200, 32)),
|
||||
inputEvents(gui.getInput()),
|
||||
history(std::make_shared<ActionsHistory>()),
|
||||
historian(std::make_unique<TextBoxHistorian>(*this, *history)),
|
||||
padding(padding),
|
||||
@@ -197,19 +201,24 @@ TextBox::TextBox(std::wstring placeholder, glm::vec4 padding)
|
||||
setOnUpPressed(nullptr);
|
||||
setOnDownPressed(nullptr);
|
||||
setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.75f));
|
||||
label = std::make_shared<Label>(L"");
|
||||
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
|
||||
|
||||
label = std::make_shared<Label>(gui, L"");
|
||||
label->setSize(
|
||||
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
|
||||
);
|
||||
label->setPos(glm::vec2(
|
||||
padding.x + LINE_NUMBERS_PANE_WIDTH * showLineNumbers, padding.y
|
||||
));
|
||||
add(label);
|
||||
|
||||
lineNumbersLabel = std::make_shared<Label>(L"");
|
||||
lineNumbersLabel = std::make_shared<Label>(gui, L"");
|
||||
lineNumbersLabel->setMultiline(true);
|
||||
lineNumbersLabel->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
|
||||
lineNumbersLabel->setSize(
|
||||
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
|
||||
);
|
||||
lineNumbersLabel->setVerticalAlign(Align::top);
|
||||
add(lineNumbersLabel);
|
||||
|
||||
|
||||
setHoverColor(glm::vec4(0.05f, 0.1f, 0.2f, 0.75f));
|
||||
|
||||
textInitX = label->getPos().x;
|
||||
@@ -342,7 +351,7 @@ void TextBox::drawBackground(const DrawContext& pctx, const Assets&) {
|
||||
batch->texture(nullptr);
|
||||
|
||||
auto subctx = pctx.sub();
|
||||
subctx.setScissors(glm::vec4(pos.x, pos.y-0.5, size.x, size.y+1));
|
||||
subctx.setScissors(glm::vec4(pos.x, pos.y - 0.5, size.x, size.y + 1));
|
||||
|
||||
if (valid) {
|
||||
if (isFocused() && !multiline) {
|
||||
@@ -371,7 +380,8 @@ void TextBox::refreshLabel() {
|
||||
|
||||
const auto& displayText = input.empty() && !hint.empty() ? hint : getText();
|
||||
if (markup == "md") {
|
||||
auto [processedText, styles] = markdown::process(displayText, !focused || !editable);
|
||||
auto [processedText, styles] =
|
||||
markdown::process(displayText, !focused || !editable);
|
||||
label->setText(std::move(processedText));
|
||||
label->setStyles(std::move(styles));
|
||||
} else {
|
||||
@@ -380,13 +390,13 @@ void TextBox::refreshLabel() {
|
||||
label->setStyles(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (showLineNumbers) {
|
||||
if (lineNumbersLabel->getLinesNumber() != label->getLinesNumber()) {
|
||||
std::wstringstream ss;
|
||||
int n = 1;
|
||||
for (int i = 1; i <= label->getLinesNumber(); i++) {
|
||||
if (!label->isFakeLine(i-1)) {
|
||||
if (!label->isFakeLine(i - 1)) {
|
||||
ss << n;
|
||||
n++;
|
||||
}
|
||||
@@ -402,11 +412,12 @@ void TextBox::refreshLabel() {
|
||||
|
||||
if (autoresize && font) {
|
||||
auto size = getSize();
|
||||
int newy = glm::min(static_cast<int>(parent->getSize().y),
|
||||
static_cast<int>(
|
||||
label->getLinesNumber() *
|
||||
label->getLineInterval() *
|
||||
font->getLineHeight()) + 1
|
||||
int newy = glm::min(
|
||||
static_cast<int>(parent->getSize().y),
|
||||
static_cast<int>(
|
||||
label->getLinesNumber() * label->getLineInterval() *
|
||||
font->getLineHeight()
|
||||
) + 1
|
||||
);
|
||||
if (newy != static_cast<int>(size.y)) {
|
||||
size.y = newy;
|
||||
@@ -475,7 +486,7 @@ bool TextBox::eraseSelected() {
|
||||
input.substr(selectionStart, selectionEnd - selectionStart),
|
||||
true
|
||||
);
|
||||
erase(selectionStart, selectionEnd-selectionStart);
|
||||
erase(selectionStart, selectionEnd - selectionStart);
|
||||
resetSelection();
|
||||
onInput();
|
||||
return true;
|
||||
@@ -495,7 +506,7 @@ void TextBox::extendSelection(int index) {
|
||||
|
||||
size_t TextBox::getLineLength(uint line) const {
|
||||
size_t position = label->getTextLineOffset(line);
|
||||
size_t lineLength = label->getTextLineOffset(line+1)-position;
|
||||
size_t lineLength = label->getTextLineOffset(line + 1) - position;
|
||||
if (lineLength == 0) {
|
||||
lineLength = label->getText().length() - position + 1;
|
||||
}
|
||||
@@ -547,7 +558,7 @@ void TextBox::setMultiline(bool multiline) {
|
||||
bool TextBox::isMultiline() const {
|
||||
return multiline;
|
||||
}
|
||||
|
||||
|
||||
void TextBox::setTextWrapping(bool flag) {
|
||||
label->setTextWrapping(flag);
|
||||
}
|
||||
@@ -593,9 +604,9 @@ bool TextBox::isAutoResize() const {
|
||||
return autoresize;
|
||||
}
|
||||
|
||||
void TextBox::onFocus(GUI* gui) {
|
||||
Container::onFocus(gui);
|
||||
if (onEditStart){
|
||||
void TextBox::onFocus() {
|
||||
Container::onFocus();
|
||||
if (onEditStart) {
|
||||
setCaret(input.size());
|
||||
onEditStart();
|
||||
resetSelection();
|
||||
@@ -609,7 +620,9 @@ void TextBox::reposition() {
|
||||
|
||||
void TextBox::refresh() {
|
||||
Container::refresh();
|
||||
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
|
||||
label->setSize(
|
||||
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
|
||||
);
|
||||
label->setPos(glm::vec2(
|
||||
padding.x + LINE_NUMBERS_PANE_WIDTH * showLineNumbers + textInitX -
|
||||
static_cast<int>(textOffset),
|
||||
@@ -629,24 +642,27 @@ size_t TextBox::normalizeIndex(int index) {
|
||||
/// @param y screen Y position
|
||||
/// @return non-normalized character index
|
||||
int TextBox::calcIndexAt(int x, int y) const {
|
||||
if (font == nullptr)
|
||||
return 0;
|
||||
if (font == nullptr) return 0;
|
||||
const auto& labelText = label->getText();
|
||||
glm::vec2 lcoord = label->calcPos();
|
||||
uint line = label->getLineByYOffset(y-lcoord.y);
|
||||
line = std::min(line, label->getLinesNumber()-1);
|
||||
uint line = label->getLineByYOffset(y - lcoord.y);
|
||||
line = std::min(line, label->getLinesNumber() - 1);
|
||||
size_t lineLength = getLineLength(line);
|
||||
uint offset = 0;
|
||||
while (lcoord.x + font->calcWidth(labelText, offset) < x && offset < lineLength-1) {
|
||||
while (lcoord.x + font->calcWidth(labelText, offset) < x &&
|
||||
offset < lineLength - 1) {
|
||||
offset++;
|
||||
}
|
||||
return std::min(offset+label->getTextLineOffset(line), labelText.length());
|
||||
return std::min(
|
||||
offset + label->getTextLineOffset(line), labelText.length()
|
||||
);
|
||||
}
|
||||
|
||||
static 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";
|
||||
return L"abcdefghijklmnopqrstuvwxyz_"
|
||||
L"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
return L"0123456789";
|
||||
}
|
||||
@@ -660,7 +676,7 @@ void TextBox::tokenSelectAt(int index) {
|
||||
}
|
||||
int left = index;
|
||||
int right = index;
|
||||
|
||||
|
||||
std::wstring alphabet = get_alphabet(actualText.at(index));
|
||||
while (left >= 0) {
|
||||
if (alphabet.find(actualText.at(left)) == std::wstring::npos) {
|
||||
@@ -674,23 +690,23 @@ void TextBox::tokenSelectAt(int index) {
|
||||
}
|
||||
right++;
|
||||
}
|
||||
select(left+1, 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::doubleClick(int x, int y) {
|
||||
UINode::doubleClick(x, y);
|
||||
tokenSelectAt(normalizeIndex(calcIndexAt(x, y) - 1));
|
||||
}
|
||||
|
||||
void TextBox::click(GUI*, int x, int y) {
|
||||
void TextBox::click(int x, int y) {
|
||||
int index = normalizeIndex(calcIndexAt(x, y));
|
||||
selectionStart = index;
|
||||
selectionEnd = index;
|
||||
selectionOrigin = index;
|
||||
}
|
||||
|
||||
void TextBox::mouseMove(GUI* gui, int x, int y) {
|
||||
Container::mouseMove(gui, x, y);
|
||||
void TextBox::mouseMove(int x, int y) {
|
||||
Container::mouseMove(x, y);
|
||||
if (isScrolling()) {
|
||||
return;
|
||||
}
|
||||
@@ -701,7 +717,8 @@ void TextBox::mouseMove(GUI* gui, int x, int y) {
|
||||
}
|
||||
|
||||
void TextBox::resetMaxLocalCaret() {
|
||||
maxLocalCaret = caret - label->getTextLineOffset(label->getLineByTextIndex(caret));
|
||||
maxLocalCaret =
|
||||
caret - label->getTextLineOffset(label->getLineByTextIndex(caret));
|
||||
}
|
||||
|
||||
void TextBox::stepLeft(bool shiftPressed, bool breakSelection) {
|
||||
@@ -709,9 +726,9 @@ void TextBox::stepLeft(bool shiftPressed, bool breakSelection) {
|
||||
size_t caret = breakSelection ? selectionStart : this->caret;
|
||||
if (caret > 0) {
|
||||
if (caret > input.length()) {
|
||||
setCaret(input.length()-1);
|
||||
setCaret(input.length() - 1);
|
||||
} else {
|
||||
setCaret(caret-1);
|
||||
setCaret(caret - 1);
|
||||
}
|
||||
if (shiftPressed) {
|
||||
if (selectionStart == selectionEnd) {
|
||||
@@ -732,7 +749,7 @@ void TextBox::stepRight(bool shiftPressed, bool breakSelection) {
|
||||
uint previousCaret = this->caret;
|
||||
size_t caret = breakSelection ? selectionEnd : this->caret;
|
||||
if (caret < input.length()) {
|
||||
setCaret(caret+1);
|
||||
setCaret(caret + 1);
|
||||
caretLastMove = Window::time();
|
||||
if (shiftPressed) {
|
||||
if (selectionStart == selectionEnd) {
|
||||
@@ -753,9 +770,10 @@ void TextBox::stepDefaultDown(bool shiftPressed, bool breakSelection) {
|
||||
uint previousCaret = this->caret;
|
||||
uint caret = breakSelection ? selectionEnd : this->caret;
|
||||
uint caretLine = label->getLineByTextIndex(caret);
|
||||
if (caretLine < label->getLinesNumber()-1) {
|
||||
uint offset = std::min(size_t(maxLocalCaret), getLineLength(caretLine+1)-1);
|
||||
setCaret(label->getTextLineOffset(caretLine+1) + offset);
|
||||
if (caretLine < label->getLinesNumber() - 1) {
|
||||
uint offset =
|
||||
std::min(size_t(maxLocalCaret), getLineLength(caretLine + 1) - 1);
|
||||
setCaret(label->getTextLineOffset(caretLine + 1) + offset);
|
||||
} else {
|
||||
setCaret(input.length());
|
||||
}
|
||||
@@ -774,8 +792,9 @@ void TextBox::stepDefaultUp(bool shiftPressed, bool breakSelection) {
|
||||
uint caret = breakSelection ? selectionStart : this->caret;
|
||||
uint caretLine = label->getLineByTextIndex(caret);
|
||||
if (caretLine > 0) {
|
||||
uint offset = std::min(size_t(maxLocalCaret), getLineLength(caretLine-1)-1);
|
||||
setCaret(label->getTextLineOffset(caretLine-1) + offset);
|
||||
uint offset =
|
||||
std::min(size_t(maxLocalCaret), getLineLength(caretLine - 1) - 1);
|
||||
setCaret(label->getTextLineOffset(caretLine - 1) + offset);
|
||||
} else {
|
||||
setCaret(static_cast<size_t>(0));
|
||||
}
|
||||
@@ -805,7 +824,7 @@ void TextBox::onInput() {
|
||||
}
|
||||
|
||||
void TextBox::performEditingKeyboardEvents(keycode key) {
|
||||
bool shiftPressed = Events::pressed(keycode::LEFT_SHIFT);
|
||||
bool shiftPressed = gui.getInput().pressed(keycode::LEFT_SHIFT);
|
||||
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
|
||||
if (key == keycode::BACKSPACE) {
|
||||
if (!eraseSelected() && caret > 0 && input.length() > 0) {
|
||||
@@ -813,8 +832,8 @@ void TextBox::performEditingKeyboardEvents(keycode key) {
|
||||
caret = input.length();
|
||||
}
|
||||
historian->onErase(caret - 1, input.substr(caret - 1, 1));
|
||||
input = input.substr(0, caret-1) + input.substr(caret);
|
||||
setCaret(caret-1);
|
||||
input = input.substr(0, caret - 1) + input.substr(caret);
|
||||
setCaret(caret - 1);
|
||||
if (validate()) {
|
||||
onInput();
|
||||
}
|
||||
@@ -850,10 +869,11 @@ void TextBox::performEditingKeyboardEvents(keycode key) {
|
||||
}
|
||||
|
||||
void TextBox::keyPressed(keycode key) {
|
||||
const auto& inputEvents = gui.getInput();
|
||||
if (editable) {
|
||||
performEditingKeyboardEvents(key);
|
||||
}
|
||||
if (Events::pressed(keycode::LEFT_CONTROL) && key != keycode::LEFT_CONTROL) {
|
||||
if (inputEvents.pressed(keycode::LEFT_CONTROL) && key != keycode::LEFT_CONTROL) {
|
||||
if (controlCombinationsHandler) {
|
||||
if (controlCombinationsHandler(static_cast<int>(key))) {
|
||||
return;
|
||||
@@ -871,7 +891,7 @@ void TextBox::keyPressed(keycode key) {
|
||||
}
|
||||
// Paste text from clipboard
|
||||
if (key == keycode::V && editable) {
|
||||
const char* text = Window::getClipboardText();
|
||||
const char* text = inputEvents.getClipboardText();
|
||||
if (text) {
|
||||
historian->sync(); // flush buffer before combination
|
||||
// Combine deleting selected text and pasing a clipboard content
|
||||
@@ -924,14 +944,14 @@ std::shared_ptr<UINode> TextBox::getAt(const glm::vec2& pos) {
|
||||
return UINode::getAt(pos);
|
||||
}
|
||||
|
||||
void TextBox::setOnUpPressed(const runnable &callback) {
|
||||
void TextBox::setOnUpPressed(const runnable& callback) {
|
||||
if (callback == nullptr) {
|
||||
onUpPressed = [this]() {
|
||||
if (Events::pressed(keycode::LEFT_CONTROL)) {
|
||||
if (inputEvents.pressed(keycode::LEFT_CONTROL)) {
|
||||
scrolled(1);
|
||||
return;
|
||||
}
|
||||
bool shiftPressed = Events::pressed(keycode::LEFT_SHIFT);
|
||||
bool shiftPressed = inputEvents.pressed(keycode::LEFT_SHIFT);
|
||||
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
|
||||
stepDefaultUp(shiftPressed, breakSelection);
|
||||
};
|
||||
@@ -940,14 +960,14 @@ void TextBox::setOnUpPressed(const runnable &callback) {
|
||||
}
|
||||
}
|
||||
|
||||
void TextBox::setOnDownPressed(const runnable &callback) {
|
||||
void TextBox::setOnDownPressed(const runnable& callback) {
|
||||
if (callback == nullptr) {
|
||||
onDownPressed = [this]() {
|
||||
if (Events::pressed(keycode::LEFT_CONTROL)) {
|
||||
if (inputEvents.pressed(keycode::LEFT_CONTROL)) {
|
||||
scrolled(-1);
|
||||
return;
|
||||
}
|
||||
bool shiftPressed = Events::pressed(keycode::LEFT_SHIFT);
|
||||
bool shiftPressed = inputEvents.pressed(keycode::LEFT_SHIFT);
|
||||
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
|
||||
stepDefaultDown(shiftPressed, breakSelection);
|
||||
};
|
||||
@@ -984,7 +1004,6 @@ glm::vec4 TextBox::getFocusedColor() const {
|
||||
return focusedColor;
|
||||
}
|
||||
|
||||
|
||||
void TextBox::setTextColor(glm::vec4 color) {
|
||||
this->textColor = color;
|
||||
}
|
||||
@@ -1002,8 +1021,7 @@ glm::vec4 TextBox::getErrorColor() const {
|
||||
}
|
||||
|
||||
const std::wstring& TextBox::getText() const {
|
||||
if (input.empty())
|
||||
return placeholder;
|
||||
if (input.empty()) return placeholder;
|
||||
return input;
|
||||
}
|
||||
|
||||
@@ -1024,7 +1042,6 @@ void TextBox::setPlaceholder(const std::wstring& placeholder) {
|
||||
this->placeholder = placeholder;
|
||||
}
|
||||
|
||||
|
||||
const std::wstring& TextBox::getHint() const {
|
||||
return hint;
|
||||
}
|
||||
@@ -1035,7 +1052,7 @@ void TextBox::setHint(const std::wstring& text) {
|
||||
|
||||
std::wstring TextBox::getSelection() const {
|
||||
const auto& text = label->getText();
|
||||
return text.substr(selectionStart, selectionEnd-selectionStart);
|
||||
return text.substr(selectionStart, selectionEnd - selectionStart);
|
||||
}
|
||||
|
||||
size_t TextBox::getCaret() const {
|
||||
@@ -1057,24 +1074,25 @@ void TextBox::setCaret(size_t position) {
|
||||
|
||||
uint line = rawTextCache.getLineByTextIndex(caret);
|
||||
int offset = label->getLineYOffset(line) + getContentOffset().y;
|
||||
uint lineHeight = font->getLineHeight()*label->getLineInterval();
|
||||
uint lineHeight = font->getLineHeight() * label->getLineInterval();
|
||||
if (scrollStep == 0) {
|
||||
scrollStep = lineHeight;
|
||||
}
|
||||
if (offset < 0) {
|
||||
scrolled(-glm::floor(offset / static_cast<double>(scrollStep)+0.5f));
|
||||
scrolled(-glm::floor(offset / static_cast<double>(scrollStep) + 0.5f));
|
||||
} else if (offset >= getSize().y) {
|
||||
offset -= getSize().y;
|
||||
scrolled(-glm::ceil(offset / static_cast<double>(scrollStep)+0.5f));
|
||||
scrolled(-glm::ceil(offset / static_cast<double>(scrollStep) + 0.5f));
|
||||
}
|
||||
int lcaret = caret - rawTextCache.getTextLineOffset(line);
|
||||
int realoffset =
|
||||
font->calcWidth(labelText, lcaret) - static_cast<int>(textOffset) + 2;
|
||||
|
||||
if (realoffset-width > 0) {
|
||||
setTextOffset(textOffset + realoffset-width);
|
||||
if (realoffset - width > 0) {
|
||||
setTextOffset(textOffset + realoffset - width);
|
||||
} else if (realoffset < 0) {
|
||||
setTextOffset(std::max(textOffset + realoffset, static_cast<size_t>(0)));
|
||||
setTextOffset(std::max(textOffset + realoffset, static_cast<size_t>(0))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ class ActionsHistory;
|
||||
namespace gui {
|
||||
class TextBoxHistorian;
|
||||
class TextBox : public Container {
|
||||
const Input& inputEvents;
|
||||
LabelCache rawTextCache;
|
||||
std::shared_ptr<ActionsHistory> history;
|
||||
std::unique_ptr<TextBoxHistorian> historian;
|
||||
@@ -94,7 +95,8 @@ namespace gui {
|
||||
|
||||
void refreshSyntax();
|
||||
public:
|
||||
TextBox(
|
||||
explicit TextBox(
|
||||
GUI& gui,
|
||||
std::wstring placeholder,
|
||||
glm::vec4 padding=glm::vec4(4.0f)
|
||||
);
|
||||
@@ -227,11 +229,11 @@ namespace gui {
|
||||
virtual bool isShowLineNumbers() const;
|
||||
|
||||
virtual void reposition() override;
|
||||
virtual void onFocus(GUI*) override;
|
||||
virtual void onFocus() 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 void doubleClick(int x, int y) override;
|
||||
virtual void click(int, int) override;
|
||||
virtual void mouseMove(int x, int y) override;
|
||||
virtual bool isFocuskeeper() const override {return true;}
|
||||
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
||||
virtual void drawBackground(const DrawContext& pctx, const Assets& assets) override;
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
using namespace gui;
|
||||
|
||||
TrackBar::TrackBar(
|
||||
GUI& gui,
|
||||
double min,
|
||||
double max,
|
||||
double value,
|
||||
double step,
|
||||
int trackWidth
|
||||
) : UINode(glm::vec2(26)),
|
||||
) : UINode(gui, glm::vec2(26)),
|
||||
min(min),
|
||||
max(max),
|
||||
value(value),
|
||||
@@ -54,7 +55,7 @@ void TrackBar::setSubConsumer(doubleconsumer consumer) {
|
||||
this->subconsumer = std::move(consumer);
|
||||
}
|
||||
|
||||
void TrackBar::mouseMove(GUI*, int x, int) {
|
||||
void TrackBar::mouseMove(int x, int) {
|
||||
glm::vec2 pos = calcPos();
|
||||
value = x - trackWidth/2;
|
||||
value -= pos.x;
|
||||
@@ -62,7 +63,7 @@ void TrackBar::mouseMove(GUI*, int x, int) {
|
||||
value += min;
|
||||
value = (value > max) ? max : value;
|
||||
value = (value < min) ? min : value;
|
||||
value = (int64_t)round(value / step) * step;
|
||||
value = static_cast<int64_t>(std::round(value / step)) * step;
|
||||
|
||||
if (consumer && !changeOnRelease) {
|
||||
consumer(value);
|
||||
@@ -72,7 +73,7 @@ void TrackBar::mouseMove(GUI*, int x, int) {
|
||||
}
|
||||
}
|
||||
|
||||
void TrackBar::mouseRelease(GUI*, int, int) {
|
||||
void TrackBar::mouseRelease(int, int) {
|
||||
if (consumer && changeOnRelease) {
|
||||
consumer(value);
|
||||
}
|
||||
|
||||
@@ -16,19 +16,22 @@ namespace gui {
|
||||
int trackWidth;
|
||||
bool changeOnRelease = false;
|
||||
public:
|
||||
TrackBar(double min,
|
||||
double max,
|
||||
double value,
|
||||
double step=1.0,
|
||||
int trackWidth=12);
|
||||
TrackBar(
|
||||
GUI& gui,
|
||||
double min,
|
||||
double max,
|
||||
double value,
|
||||
double step = 1.0,
|
||||
int trackWidth = 12
|
||||
);
|
||||
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
||||
|
||||
virtual void setSupplier(doublesupplier);
|
||||
virtual void setConsumer(doubleconsumer);
|
||||
virtual void setSubConsumer(doubleconsumer);
|
||||
|
||||
virtual void mouseMove(GUI*, int x, int y) override;
|
||||
virtual void mouseRelease(GUI*, int x, int y) override;
|
||||
virtual void mouseMove(int x, int y) override;
|
||||
virtual void mouseRelease(int x, int y) override;
|
||||
|
||||
virtual double getValue() const;
|
||||
virtual double getMin() const;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
using gui::UINode;
|
||||
using gui::Align;
|
||||
|
||||
UINode::UINode(glm::vec2 size) : size(size) {
|
||||
UINode::UINode(GUI& gui, glm::vec2 size) : gui(gui), size(size) {
|
||||
}
|
||||
|
||||
UINode::~UINode() {
|
||||
@@ -74,18 +74,18 @@ UINode* UINode::listenDoubleClick(const onaction& action) {
|
||||
return this;
|
||||
}
|
||||
|
||||
void UINode::click(GUI*, int, int) {
|
||||
void UINode::click(int, int) {
|
||||
pressed = true;
|
||||
}
|
||||
|
||||
void UINode::doubleClick(GUI* gui, int x, int y) {
|
||||
void UINode::doubleClick(int x, int y) {
|
||||
pressed = true;
|
||||
if (isInside(glm::vec2(x, y))) {
|
||||
doubleClickCallbacks.notify(gui);
|
||||
}
|
||||
}
|
||||
|
||||
void UINode::mouseRelease(GUI* gui, int x, int y) {
|
||||
void UINode::mouseRelease(int x, int y) {
|
||||
pressed = false;
|
||||
if (isInside(glm::vec2(x, y))) {
|
||||
actions.notify(gui);
|
||||
|
||||
@@ -19,8 +19,8 @@ namespace gui {
|
||||
class GUI;
|
||||
class Container;
|
||||
|
||||
using onaction = std::function<void(GUI*)>;
|
||||
using onnumberchange = std::function<void(GUI*, double)>;
|
||||
using onaction = std::function<void(GUI&)>;
|
||||
using onnumberchange = std::function<void(GUI&, double)>;
|
||||
|
||||
class ActionsSet {
|
||||
std::unique_ptr<std::vector<onaction>> callbacks;
|
||||
@@ -32,7 +32,7 @@ namespace gui {
|
||||
callbacks->push_back(callback);
|
||||
}
|
||||
|
||||
void notify(GUI* gui) {
|
||||
void notify(GUI& gui) {
|
||||
if (callbacks) {
|
||||
for (auto& callback : *callbacks) {
|
||||
callback(gui);
|
||||
@@ -64,6 +64,9 @@ namespace gui {
|
||||
|
||||
/// @brief Base abstract class for all UI elements
|
||||
class UINode : public std::enable_shared_from_this<UINode> {
|
||||
protected:
|
||||
GUI& gui;
|
||||
private:
|
||||
/// @brief element identifier used for direct access in UiDocument
|
||||
std::string id = "";
|
||||
/// @brief element enabled state
|
||||
@@ -118,7 +121,7 @@ namespace gui {
|
||||
/// @brief cursor shape when mouse is over the element
|
||||
CursorShape cursor = CursorShape::ARROW;
|
||||
|
||||
UINode(glm::vec2 size);
|
||||
UINode(GUI& gui, glm::vec2 size);
|
||||
public:
|
||||
virtual ~UINode();
|
||||
|
||||
@@ -169,12 +172,12 @@ namespace gui {
|
||||
virtual UINode* listenAction(const onaction &action);
|
||||
virtual UINode* listenDoubleClick(const 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) {};
|
||||
virtual void mouseRelease(GUI*, int x, int y);
|
||||
virtual void onFocus() {focused = true;}
|
||||
virtual void doubleClick(int x, int y);
|
||||
virtual void click(int x, int y);
|
||||
virtual void clicked(mousecode button) {}
|
||||
virtual void mouseMove(int x, int y) {};
|
||||
virtual void mouseRelease(int x, int y);
|
||||
virtual void scrolled(int value);
|
||||
|
||||
bool isPressed() const;
|
||||
|
||||
@@ -1,37 +1,36 @@
|
||||
#include "gui_util.hpp"
|
||||
|
||||
#include "elements/Label.hpp"
|
||||
#include "elements/Menu.hpp"
|
||||
#include "elements/Button.hpp"
|
||||
#include "elements/TextBox.hpp"
|
||||
#include "gui_xml.hpp"
|
||||
|
||||
#include "logic/scripting/scripting.hpp"
|
||||
#include "frontend/locale.hpp"
|
||||
#include "util/stringutil.hpp"
|
||||
#include "delegates.hpp"
|
||||
|
||||
#include "window/Events.hpp"
|
||||
#include "engine/Engine.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "delegates.hpp"
|
||||
#include "elements/Button.hpp"
|
||||
#include "elements/Label.hpp"
|
||||
#include "elements/Menu.hpp"
|
||||
#include "elements/TextBox.hpp"
|
||||
#include "engine/Engine.hpp"
|
||||
#include "frontend/locale.hpp"
|
||||
#include "gui_xml.hpp"
|
||||
#include "logic/scripting/scripting.hpp"
|
||||
#include "util/stringutil.hpp"
|
||||
|
||||
using namespace gui;
|
||||
|
||||
std::shared_ptr<gui::UINode> guiutil::create(const std::string& source, scriptenv env) {
|
||||
std::shared_ptr<gui::UINode> guiutil::create(
|
||||
GUI& gui, const std::string& source, scriptenv env
|
||||
) {
|
||||
if (env == nullptr) {
|
||||
env = scripting::get_root_environment();
|
||||
}
|
||||
UiXmlReader reader(env);
|
||||
UiXmlReader reader(gui, env);
|
||||
return reader.readXML("[string]", source);
|
||||
}
|
||||
|
||||
void guiutil::alert(
|
||||
Engine& engine,
|
||||
const std::wstring& text,
|
||||
const runnable& on_hidden
|
||||
Engine& engine, const std::wstring& text, const runnable& on_hidden
|
||||
) {
|
||||
GUI& gui = engine.getGUI();
|
||||
auto panel = std::make_shared<Panel>(
|
||||
gui,
|
||||
glm::vec2(
|
||||
glm::min(
|
||||
static_cast<size_t>(650),
|
||||
@@ -44,7 +43,7 @@ void guiutil::alert(
|
||||
);
|
||||
panel->setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
||||
|
||||
auto menuPtr = engine.getGUI()->getMenu();
|
||||
auto menuPtr = gui.getMenu();
|
||||
auto& menu = *menuPtr;
|
||||
runnable on_hidden_final = [on_hidden, &menu]() {
|
||||
menu.removePage("<alert>");
|
||||
@@ -54,25 +53,26 @@ void guiutil::alert(
|
||||
menu.reset();
|
||||
}
|
||||
};
|
||||
|
||||
auto label = std::make_shared<Label>(text);
|
||||
|
||||
auto label = std::make_shared<Label>(gui, text);
|
||||
label->setMultiline(true);
|
||||
label->setSize(glm::vec2(1, 24));
|
||||
label->setAutoResize(true);
|
||||
panel->add(label);
|
||||
panel->add(std::make_shared<Button>(
|
||||
langs::get(L"Ok"), glm::vec4(10.f),
|
||||
[on_hidden_final](GUI*) {
|
||||
on_hidden_final();
|
||||
}
|
||||
gui,
|
||||
langs::get(L"Ok"),
|
||||
glm::vec4(10.f),
|
||||
[on_hidden_final](GUI&) { on_hidden_final(); }
|
||||
));
|
||||
panel->refresh();
|
||||
|
||||
panel->keepAlive(Events::addKeyCallback(keycode::ENTER, [on_hidden_final](){
|
||||
auto& input = engine.getInput();
|
||||
panel->keepAlive(input.addKeyCallback(keycode::ENTER, [on_hidden_final]() {
|
||||
on_hidden_final();
|
||||
return true;
|
||||
}));
|
||||
panel->keepAlive(Events::addKeyCallback(keycode::ESCAPE, [on_hidden_final](){
|
||||
panel->keepAlive(input.addKeyCallback(keycode::ESCAPE, [on_hidden_final]() {
|
||||
on_hidden_final();
|
||||
return true;
|
||||
}));
|
||||
@@ -91,17 +91,25 @@ void guiutil::confirm(
|
||||
if (yestext.empty()) yestext = langs::get(L"Yes");
|
||||
if (notext.empty()) notext = langs::get(L"No");
|
||||
|
||||
auto container = std::make_shared<Container>(glm::vec2(5000, 5000));
|
||||
auto& gui = engine.getGUI();
|
||||
auto& input = engine.getInput();
|
||||
|
||||
auto container = std::make_shared<Container>(gui, glm::vec2(5000, 5000));
|
||||
container->setColor(glm::vec4(0.05f, 0.05f, 0.05f, 0.7f));
|
||||
auto panel = std::make_shared<Panel>(glm::vec2(600, 200), glm::vec4(8.0f), 8.0f);
|
||||
|
||||
auto panel = std::make_shared<Panel>(
|
||||
gui, glm::vec2(600, 200), glm::vec4(8.0f), 8.0f
|
||||
);
|
||||
|
||||
panel->setGravity(Gravity::center_center);
|
||||
container->add(panel);
|
||||
|
||||
panel->setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
||||
panel->add(std::make_shared<Label>(text));
|
||||
auto subpanel = std::make_shared<Panel>(glm::vec2(600, 53));
|
||||
panel->add(std::make_shared<Label>(gui, text));
|
||||
auto subpanel = std::make_shared<Panel>(gui, glm::vec2(600, 53));
|
||||
subpanel->setColor(glm::vec4(0));
|
||||
|
||||
auto menu = engine.getGUI()->getMenu();
|
||||
auto menu = gui.getMenu();
|
||||
|
||||
runnable on_confirm_final = [on_confirm, menu]() {
|
||||
menu->removePage("<confirm>");
|
||||
@@ -121,20 +129,20 @@ void guiutil::confirm(
|
||||
}
|
||||
};
|
||||
|
||||
subpanel->add(std::make_shared<Button>(yestext, glm::vec4(8.f), [=](GUI*){
|
||||
subpanel->add(std::make_shared<Button>(gui, yestext, glm::vec4(8.f), [=](GUI&) {
|
||||
on_confirm_final();
|
||||
}));
|
||||
|
||||
subpanel->add(std::make_shared<Button>(notext, glm::vec4(8.f), [=](GUI*){
|
||||
subpanel->add(std::make_shared<Button>(gui, notext, glm::vec4(8.f), [=](GUI&) {
|
||||
on_deny_final();
|
||||
}));
|
||||
|
||||
panel->add(subpanel);
|
||||
panel->keepAlive(Events::addKeyCallback(keycode::ENTER, [=](){
|
||||
panel->keepAlive(input.addKeyCallback(keycode::ENTER, [=]() {
|
||||
on_confirm_final();
|
||||
return true;
|
||||
}));
|
||||
panel->keepAlive(Events::addKeyCallback(keycode::ESCAPE, [=](){
|
||||
panel->keepAlive(input.addKeyCallback(keycode::ESCAPE, [=]() {
|
||||
on_deny_final();
|
||||
return true;
|
||||
}));
|
||||
@@ -145,21 +153,25 @@ void guiutil::confirm(
|
||||
}
|
||||
|
||||
void guiutil::confirm_with_memo(
|
||||
const std::shared_ptr<gui::Menu>& menu,
|
||||
const std::wstring& text,
|
||||
const std::wstring& memo,
|
||||
const runnable& on_confirm,
|
||||
std::wstring yestext,
|
||||
std::wstring notext) {
|
||||
|
||||
Engine& engine,
|
||||
const std::wstring& text,
|
||||
const std::wstring& memo,
|
||||
const runnable& on_confirm,
|
||||
std::wstring yestext,
|
||||
std::wstring notext
|
||||
) {
|
||||
auto& gui = engine.getGUI();
|
||||
auto menu = gui.getMenu();
|
||||
if (yestext.empty()) yestext = langs::get(L"Yes");
|
||||
if (notext.empty()) notext = langs::get(L"No");
|
||||
|
||||
auto panel = std::make_shared<Panel>(glm::vec2(600, 500), glm::vec4(8.0f), 8.0f);
|
||||
auto panel = std::make_shared<Panel>(
|
||||
gui, glm::vec2(600, 500), glm::vec4(8.0f), 8.0f
|
||||
);
|
||||
panel->setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
||||
panel->add(std::make_shared<Label>(text));
|
||||
|
||||
auto textbox = std::make_shared<TextBox>(L"");
|
||||
panel->add(std::make_shared<Label>(gui, text));
|
||||
|
||||
auto textbox = std::make_shared<TextBox>(gui, L"");
|
||||
textbox->setMultiline(true);
|
||||
textbox->setTextWrapping(true);
|
||||
textbox->setSize(glm::vec2(600, 300));
|
||||
@@ -167,16 +179,15 @@ void guiutil::confirm_with_memo(
|
||||
textbox->setEditable(false);
|
||||
panel->add(textbox);
|
||||
|
||||
auto subpanel = std::make_shared<Panel>(glm::vec2(600, 53));
|
||||
auto subpanel = std::make_shared<Panel>(gui, glm::vec2(600, 53));
|
||||
subpanel->setColor(glm::vec4(0));
|
||||
|
||||
subpanel->add(std::make_shared<Button>(yestext, glm::vec4(8.f), [=](GUI*){
|
||||
if (on_confirm)
|
||||
on_confirm();
|
||||
subpanel->add(std::make_shared<Button>(gui, yestext, glm::vec4(8.f), [=](GUI&) {
|
||||
if (on_confirm) on_confirm();
|
||||
menu->back();
|
||||
}));
|
||||
|
||||
subpanel->add(std::make_shared<Button>(notext, glm::vec4(8.f), [=](GUI*){
|
||||
subpanel->add(std::make_shared<Button>(gui, notext, glm::vec4(8.f), [=](GUI&) {
|
||||
menu->back();
|
||||
}));
|
||||
|
||||
|
||||
@@ -1,38 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "typedefs.hpp"
|
||||
#include "delegates.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "delegates.hpp"
|
||||
#include "typedefs.hpp"
|
||||
|
||||
class Engine;
|
||||
|
||||
namespace guiutil {
|
||||
/// @brief Create element from XML
|
||||
/// @param source XML
|
||||
std::shared_ptr<gui::UINode> create(const std::string& source, scriptenv env=0);
|
||||
std::shared_ptr<gui::UINode> create(
|
||||
gui::GUI& gui, const std::string& source, scriptenv env = 0
|
||||
);
|
||||
|
||||
void alert(
|
||||
Engine& engine,
|
||||
const std::wstring& text,
|
||||
const runnable& on_hidden=nullptr
|
||||
const std::wstring& text,
|
||||
const runnable& on_hidden = nullptr
|
||||
);
|
||||
|
||||
void confirm(
|
||||
Engine& engine,
|
||||
const std::wstring& text,
|
||||
const runnable& on_confirm=nullptr,
|
||||
const runnable& on_deny=nullptr,
|
||||
std::wstring yestext=L"",
|
||||
std::wstring notext=L"");
|
||||
const std::wstring& text,
|
||||
const runnable& on_confirm = nullptr,
|
||||
const runnable& on_deny = nullptr,
|
||||
std::wstring yestext = L"",
|
||||
std::wstring notext = L""
|
||||
);
|
||||
|
||||
void confirm_with_memo(
|
||||
const std::shared_ptr<gui::Menu>& menu,
|
||||
const std::wstring& text,
|
||||
Engine& engine,
|
||||
const std::wstring& text,
|
||||
const std::wstring& memo,
|
||||
const runnable& on_confirm=nullptr,
|
||||
std::wstring yestext=L"",
|
||||
std::wstring notext=L"");
|
||||
const runnable& on_confirm = nullptr,
|
||||
std::wstring yestext = L"",
|
||||
std::wstring notext = L""
|
||||
);
|
||||
}
|
||||
|
||||
+105
-79
@@ -1,30 +1,31 @@
|
||||
#include "gui_xml.hpp"
|
||||
|
||||
#include "elements/Panel.hpp"
|
||||
#include "elements/Image.hpp"
|
||||
#include "elements/Menu.hpp"
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "elements/Button.hpp"
|
||||
#include "elements/Canvas.hpp"
|
||||
#include "elements/CheckBox.hpp"
|
||||
#include "elements/TextBox.hpp"
|
||||
#include "elements/SplitBox.hpp"
|
||||
#include "elements/TrackBar.hpp"
|
||||
#include "elements/Image.hpp"
|
||||
#include "elements/InputBindBox.hpp"
|
||||
#include "elements/InventoryView.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "elements/Menu.hpp"
|
||||
#include "elements/Panel.hpp"
|
||||
#include "elements/TextBox.hpp"
|
||||
#include "elements/TrackBar.hpp"
|
||||
#include "engine/Engine.hpp"
|
||||
|
||||
#include "frontend/menu.hpp"
|
||||
#include "frontend/locale.hpp"
|
||||
#include "frontend/menu.hpp"
|
||||
#include "items/Inventory.hpp"
|
||||
#include "logic/scripting/scripting.hpp"
|
||||
#include "maths/voxmaths.hpp"
|
||||
#include "util/stringutil.hpp"
|
||||
#include "window/Events.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
using namespace gui;
|
||||
|
||||
static Align align_from_string(const std::string& str, Align def) {
|
||||
@@ -56,7 +57,7 @@ static Gravity gravity_from_string(const std::string& str) {
|
||||
}
|
||||
|
||||
static runnable create_runnable(
|
||||
const UiXmlReader& reader,
|
||||
const UiXmlReader& reader,
|
||||
const xml::xmlelement& element,
|
||||
const std::string& name
|
||||
) {
|
||||
@@ -80,7 +81,7 @@ static onaction create_action(
|
||||
if (callback == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return [callback](GUI*) {callback();};
|
||||
return [callback](GUI&) { callback(); };
|
||||
}
|
||||
|
||||
/// @brief Read basic UINode properties
|
||||
@@ -152,9 +153,7 @@ static void read_uinode(
|
||||
node.setAlign(align_from_string(alignName, node.getAlign()));
|
||||
|
||||
if (element.has("gravity")) {
|
||||
node.setGravity(gravity_from_string(
|
||||
element.attr("gravity").getText()
|
||||
));
|
||||
node.setGravity(gravity_from_string(element.attr("gravity").getText()));
|
||||
}
|
||||
|
||||
if (element.has("tooltip")) {
|
||||
@@ -184,7 +183,9 @@ static void read_uinode(
|
||||
}
|
||||
}
|
||||
|
||||
static void read_container_impl(UiXmlReader& reader, const xml::xmlelement& element, Container& container) {
|
||||
static void read_container_impl(
|
||||
UiXmlReader& reader, const xml::xmlelement& element, Container& container
|
||||
) {
|
||||
read_uinode(reader, element, container);
|
||||
|
||||
if (element.has("scrollable")) {
|
||||
@@ -194,8 +195,7 @@ static void read_container_impl(UiXmlReader& reader, const xml::xmlelement& elem
|
||||
container.setScrollStep(element.attr("scroll-step").asInt());
|
||||
}
|
||||
for (auto& sub : element.getElements()) {
|
||||
if (sub->isText())
|
||||
continue;
|
||||
if (sub->isText()) continue;
|
||||
auto subnode = reader.readUINode(*sub);
|
||||
if (subnode) {
|
||||
container.add(subnode);
|
||||
@@ -203,7 +203,9 @@ static void read_container_impl(UiXmlReader& reader, const xml::xmlelement& elem
|
||||
}
|
||||
}
|
||||
|
||||
void UiXmlReader::readUINode(UiXmlReader& reader, const xml::xmlelement& element, Container& container) {
|
||||
void UiXmlReader::readUINode(
|
||||
UiXmlReader& reader, const xml::xmlelement& element, Container& container
|
||||
) {
|
||||
read_container_impl(reader, element, container);
|
||||
}
|
||||
|
||||
@@ -225,8 +227,7 @@ static void read_base_panel_impl(
|
||||
panel.setPadding(padding);
|
||||
glm::vec2 size = panel.getSize();
|
||||
panel.setSize(glm::vec2(
|
||||
size.x + padding.x + padding.z,
|
||||
size.y + padding.y + padding.w
|
||||
size.x + padding.x + padding.z, size.y + padding.y + padding.w
|
||||
));
|
||||
}
|
||||
if (element.has("orientation")) {
|
||||
@@ -254,10 +255,15 @@ static void read_panel_impl(
|
||||
if (element.has("min-length")) {
|
||||
panel.setMinLength(element.attr("min-length").asInt());
|
||||
}
|
||||
if (element.has("orientation")) {
|
||||
auto& oname = element.attr("orientation").getText();
|
||||
if (oname == "horizontal") {
|
||||
panel.setOrientation(Orientation::horizontal);
|
||||
}
|
||||
}
|
||||
if (subnodes) {
|
||||
for (auto& sub : element.getElements()) {
|
||||
if (sub->isText())
|
||||
continue;
|
||||
if (sub->isText()) continue;
|
||||
auto subnode = reader.readUINode(*sub);
|
||||
if (subnode) {
|
||||
panel.add(subnode);
|
||||
@@ -273,7 +279,7 @@ static std::wstring parse_inner_text(
|
||||
if (element.size() == 1) {
|
||||
std::string source = element.sub(0).attr("#").getText();
|
||||
util::trim(source);
|
||||
text = util::str2wstr_utf8(source);
|
||||
text = util::str2wstr_utf8(source);
|
||||
if (text[0] == '@') {
|
||||
if (context.empty()) {
|
||||
text = langs::get(text.substr(1));
|
||||
@@ -289,12 +295,12 @@ static std::shared_ptr<UINode> readLabel(
|
||||
const UiXmlReader& reader, const xml::xmlelement& element
|
||||
) {
|
||||
std::wstring text = parse_inner_text(element, reader.getContext());
|
||||
auto label = std::make_shared<Label>(text);
|
||||
auto label = std::make_shared<Label>(reader.getGUI(), text);
|
||||
read_uinode(reader, element, *label);
|
||||
if (element.has("valign")) {
|
||||
label->setVerticalAlign(
|
||||
align_from_string(element.attr("valign").getText(), label->getVerticalAlign())
|
||||
);
|
||||
label->setVerticalAlign(align_from_string(
|
||||
element.attr("valign").getText(), label->getVerticalAlign()
|
||||
));
|
||||
}
|
||||
if (element.has("supplier")) {
|
||||
label->textSupplier(scripting::create_wstring_supplier(
|
||||
@@ -324,7 +330,7 @@ static std::shared_ptr<UINode> readLabel(
|
||||
static std::shared_ptr<UINode> read_container(
|
||||
UiXmlReader& reader, const xml::xmlelement& element
|
||||
) {
|
||||
auto container = std::make_shared<Container>(glm::vec2());
|
||||
auto container = std::make_shared<Container>(reader.getGUI(), glm::vec2());
|
||||
read_container_impl(reader, element, *container);
|
||||
return container;
|
||||
}
|
||||
@@ -337,8 +343,9 @@ static std::shared_ptr<UINode> read_split_box(
|
||||
element.attr("orientation", "vertical").getText() == "horizontal"
|
||||
? Orientation::horizontal
|
||||
: Orientation::vertical;
|
||||
auto splitBox =
|
||||
std::make_shared<SplitBox>(glm::vec2(), splitPos, orientation);
|
||||
auto splitBox = std::make_shared<SplitBox>(
|
||||
reader.getGUI(), glm::vec2(), splitPos, orientation
|
||||
);
|
||||
read_base_panel_impl(reader, element, *splitBox);
|
||||
for (auto& sub : element.getElements()) {
|
||||
if (sub->isText())
|
||||
@@ -355,7 +362,9 @@ static std::shared_ptr<UINode> read_panel(
|
||||
UiXmlReader& reader, const xml::xmlelement& element
|
||||
) {
|
||||
float interval = element.attr("interval", "2").asFloat();
|
||||
auto panel = std::make_shared<Panel>(glm::vec2(), glm::vec4(), interval);
|
||||
auto panel = std::make_shared<Panel>(
|
||||
reader.getGUI(), glm::vec2(), glm::vec4(), interval
|
||||
);
|
||||
read_panel_impl(reader, element, *panel);
|
||||
return panel;
|
||||
}
|
||||
@@ -363,6 +372,7 @@ static std::shared_ptr<UINode> read_panel(
|
||||
static std::shared_ptr<UINode> read_button(
|
||||
UiXmlReader& reader, const xml::xmlelement& element
|
||||
) {
|
||||
auto& gui = reader.getGUI();
|
||||
glm::vec4 padding = element.attr("padding", "10").asVec4();
|
||||
|
||||
std::shared_ptr<Button> button;
|
||||
@@ -370,14 +380,14 @@ static std::shared_ptr<UINode> read_button(
|
||||
if (!elements.empty() && elements[0]->getTag() != "#") {
|
||||
auto inner = reader.readUINode(*elements.at(0));
|
||||
if (inner != nullptr) {
|
||||
button = std::make_shared<Button>(inner, padding);
|
||||
button = std::make_shared<Button>(gui, inner, padding);
|
||||
} else {
|
||||
button = std::make_shared<Button>(L"", padding, nullptr);
|
||||
button = std::make_shared<Button>(gui, L"", padding, nullptr);
|
||||
}
|
||||
read_panel_impl(reader, element, *button, false);
|
||||
} else {
|
||||
std::wstring text = parse_inner_text(element, reader.getContext());
|
||||
button = std::make_shared<Button>(text, padding, nullptr);
|
||||
button = std::make_shared<Button>(gui, text, padding, nullptr);
|
||||
read_panel_impl(reader, element, *button, true);
|
||||
}
|
||||
if (element.has("text-align")) {
|
||||
@@ -393,7 +403,9 @@ static std::shared_ptr<UINode> read_check_box(
|
||||
) {
|
||||
auto text = parse_inner_text(element, reader.getContext());
|
||||
bool checked = element.attr("checked", "false").asBool();
|
||||
auto checkbox = std::make_shared<FullCheckBox>(text, glm::vec2(32), checked);
|
||||
auto checkbox = std::make_shared<FullCheckBox>(
|
||||
reader.getGUI(), text, glm::vec2(32), checked
|
||||
);
|
||||
read_panel_impl(reader, element, *checkbox);
|
||||
|
||||
if (element.has("consumer")) {
|
||||
@@ -417,20 +429,22 @@ static std::shared_ptr<UINode> read_check_box(
|
||||
static std::shared_ptr<UINode> read_text_box(
|
||||
UiXmlReader& reader, const xml::xmlelement& element
|
||||
) {
|
||||
auto placeholder = util::str2wstr_utf8(element.attr("placeholder", "").getText());
|
||||
auto placeholder =
|
||||
util::str2wstr_utf8(element.attr("placeholder", "").getText());
|
||||
auto hint = util::str2wstr_utf8(element.attr("hint", "").getText());
|
||||
auto text = parse_inner_text(element, reader.getContext());
|
||||
auto textbox = std::make_shared<TextBox>(placeholder, glm::vec4(0.0f));
|
||||
auto textbox = std::make_shared<TextBox>(
|
||||
reader.getGUI(), placeholder, glm::vec4(0.0f)
|
||||
);
|
||||
textbox->setHint(hint);
|
||||
|
||||
|
||||
read_container_impl(reader, element, *textbox);
|
||||
if (element.has("padding")) {
|
||||
glm::vec4 padding = element.attr("padding").asVec4();
|
||||
textbox->setPadding(padding);
|
||||
glm::vec2 size = textbox->getSize();
|
||||
textbox->setSize(glm::vec2(
|
||||
size.x + padding.x + padding.z,
|
||||
size.y + padding.y + padding.w
|
||||
size.x + padding.x + padding.z, size.y + padding.y + padding.w
|
||||
));
|
||||
}
|
||||
textbox->setText(text);
|
||||
@@ -513,7 +527,7 @@ static std::shared_ptr<UINode> read_image(
|
||||
const UiXmlReader& reader, const xml::xmlelement& element
|
||||
) {
|
||||
std::string src = element.attr("src", "").getText();
|
||||
auto image = std::make_shared<Image>(src);
|
||||
auto image = std::make_shared<Image>(reader.getGUI(), src);
|
||||
read_uinode(reader, element, *image);
|
||||
return image;
|
||||
}
|
||||
@@ -521,11 +535,12 @@ static std::shared_ptr<UINode> read_image(
|
||||
static std::shared_ptr<UINode> read_canvas(
|
||||
const UiXmlReader& reader, const xml::xmlelement& element
|
||||
) {
|
||||
auto size = glm::uvec2{32, 32};
|
||||
auto size = glm::uvec2 {32, 32};
|
||||
if (element.has("size")) {
|
||||
size = element.attr("size").asVec2();
|
||||
}
|
||||
auto image = std::make_shared<Canvas>(ImageFormat::rgba8888, size);
|
||||
auto image =
|
||||
std::make_shared<Canvas>(reader.getGUI(), ImageFormat::rgba8888, size);
|
||||
read_uinode(reader, element, *image);
|
||||
return image;
|
||||
}
|
||||
@@ -540,19 +555,24 @@ static std::shared_ptr<UINode> read_track_bar(
|
||||
float def = element.attr("value", "0.0").asFloat();
|
||||
float step = element.attr("step", "1.0").asFloat();
|
||||
int trackWidth = element.attr("track-width", "12").asInt();
|
||||
auto bar = std::make_shared<TrackBar>(minv, maxv, def, step, trackWidth);
|
||||
auto bar = std::make_shared<TrackBar>(
|
||||
reader.getGUI(), minv, maxv, def, step, trackWidth
|
||||
);
|
||||
read_uinode(reader, element, *bar);
|
||||
if (element.has("consumer")) {
|
||||
bar->setConsumer(scripting::create_number_consumer(
|
||||
env, element.attr("consumer").getText(), file));
|
||||
env, element.attr("consumer").getText(), file
|
||||
));
|
||||
}
|
||||
if (element.has("sub-consumer")) {
|
||||
bar->setSubConsumer(scripting::create_number_consumer(
|
||||
env, element.attr("sub-consumer").getText(), file));
|
||||
env, element.attr("sub-consumer").getText(), file
|
||||
));
|
||||
}
|
||||
if (element.has("supplier")) {
|
||||
bar->setSupplier(scripting::create_number_supplier(
|
||||
env, element.attr("supplier").getText(), file));
|
||||
env, element.attr("supplier").getText(), file
|
||||
));
|
||||
}
|
||||
if (element.has("track-color")) {
|
||||
bar->setTrackColor(element.attr("track-color").asColor());
|
||||
@@ -567,14 +587,11 @@ static std::shared_ptr<UINode> read_input_bind_box(
|
||||
UiXmlReader& reader, const xml::xmlelement& element
|
||||
) {
|
||||
auto bindname = element.attr("binding").getText();
|
||||
auto found = Events::bindings.find(bindname);
|
||||
if (found == Events::bindings.end()) {
|
||||
throw std::runtime_error("binding does not exists "+util::quote(bindname));
|
||||
}
|
||||
auto& found = Events::requireBinding(bindname);
|
||||
glm::vec4 padding = element.attr("padding", "6").asVec4();
|
||||
auto bindbox = std::make_shared<InputBindBox>(found->second, padding);
|
||||
auto bindbox =
|
||||
std::make_shared<InputBindBox>(reader.getGUI(), found, padding);
|
||||
read_panel_impl(reader, element, *bindbox);
|
||||
|
||||
return bindbox;
|
||||
}
|
||||
|
||||
@@ -585,11 +602,12 @@ static slotcallback read_slot_func(
|
||||
const std::string& attr
|
||||
) {
|
||||
auto consumer = scripting::create_int_array_consumer(
|
||||
reader.getEnvironment(),
|
||||
element.attr(attr).getText()
|
||||
reader.getEnvironment(), element.attr(attr).getText()
|
||||
);
|
||||
return [=](uint slot, ItemStack&) {
|
||||
int args[] {int(view->getInventory()->getId()), int(slot)};
|
||||
int args[] {
|
||||
static_cast<int>(view->getInventory()->getId()),
|
||||
static_cast<int>(slot)};
|
||||
consumer(args, 2);
|
||||
};
|
||||
}
|
||||
@@ -601,7 +619,9 @@ static void readSlot(
|
||||
bool itemSource = element.attr("item-source", "false").asBool();
|
||||
bool taking = element.attr("taking", "true").asBool();
|
||||
bool placing = element.attr("placing", "true").asBool();
|
||||
SlotLayout layout(index, glm::vec2(), true, itemSource, nullptr, nullptr, nullptr);
|
||||
SlotLayout layout(
|
||||
index, glm::vec2(), true, itemSource, nullptr, nullptr, nullptr
|
||||
);
|
||||
if (element.has("pos")) {
|
||||
layout.position = element.attr("pos").asVec2();
|
||||
}
|
||||
@@ -612,7 +632,8 @@ static void readSlot(
|
||||
layout.shareFunc = read_slot_func(view, reader, element, "sharefunc");
|
||||
}
|
||||
if (element.has("onrightclick")) {
|
||||
layout.rightClick = read_slot_func(view, reader, element, "onrightclick");
|
||||
layout.rightClick =
|
||||
read_slot_func(view, reader, element, "onrightclick");
|
||||
}
|
||||
layout.taking = taking;
|
||||
layout.placing = placing;
|
||||
@@ -622,7 +643,9 @@ static void readSlot(
|
||||
}
|
||||
|
||||
static void readSlotsGrid(
|
||||
InventoryView* view, const UiXmlReader& reader, const xml::xmlelement& element
|
||||
InventoryView* view,
|
||||
const UiXmlReader& reader,
|
||||
const xml::xmlelement& element
|
||||
) {
|
||||
int startIndex = element.attr("start-index", "0").asInt();
|
||||
int rows = element.attr("rows", "0").asInt();
|
||||
@@ -647,7 +670,9 @@ static void readSlotsGrid(
|
||||
count = rows * cols;
|
||||
}
|
||||
bool itemSource = element.attr("item-source", "false").asBool();
|
||||
SlotLayout layout(-1, glm::vec2(), true, itemSource, nullptr, nullptr, nullptr);
|
||||
SlotLayout layout(
|
||||
-1, glm::vec2(), true, itemSource, nullptr, nullptr, nullptr
|
||||
);
|
||||
if (element.has("pos")) {
|
||||
layout.position = element.attr("pos").asVec2();
|
||||
}
|
||||
@@ -658,7 +683,8 @@ static void readSlotsGrid(
|
||||
layout.shareFunc = read_slot_func(view, reader, element, "sharefunc");
|
||||
}
|
||||
if (element.has("onrightclick")) {
|
||||
layout.rightClick = read_slot_func(view, reader, element, "onrightclick");
|
||||
layout.rightClick =
|
||||
read_slot_func(view, reader, element, "onrightclick");
|
||||
}
|
||||
layout.padding = padding;
|
||||
layout.taking = taking;
|
||||
@@ -674,7 +700,7 @@ static void readSlotsGrid(
|
||||
slotLayout.index = startIndex + idx;
|
||||
slotLayout.position += glm::vec2(
|
||||
padding + col * (slotSize + interval),
|
||||
padding + (rows-row-1) * (slotSize + interval)
|
||||
padding + (rows - row - 1) * (slotSize + interval)
|
||||
);
|
||||
auto slot = view->addSlot(slotLayout);
|
||||
view->add(slot, slotLayout.position);
|
||||
@@ -685,8 +711,8 @@ static void readSlotsGrid(
|
||||
static std::shared_ptr<UINode> read_inventory(
|
||||
UiXmlReader& reader, const xml::xmlelement& element
|
||||
) {
|
||||
auto view = std::make_shared<InventoryView>();
|
||||
view->setColor(glm::vec4(0.122f, 0.122f, 0.122f, 0.878f)); // todo: fixme
|
||||
auto view = std::make_shared<InventoryView>(reader.getGUI());
|
||||
view->setColor(glm::vec4(0.122f, 0.122f, 0.122f, 0.878f)); // TODO: fixme
|
||||
reader.addIgnore("slot");
|
||||
reader.addIgnore("slots-grid");
|
||||
reader.readUINode(reader, element, *view);
|
||||
@@ -704,16 +730,15 @@ static std::shared_ptr<UINode> read_inventory(
|
||||
static std::shared_ptr<UINode> read_page_box(
|
||||
UiXmlReader& reader, const xml::xmlelement& element
|
||||
) {
|
||||
auto menu = std::make_shared<Menu>();
|
||||
menu->setPageLoader(
|
||||
Engine::getInstance().getGUI()->getMenu()->getPageLoader()
|
||||
);
|
||||
auto& gui = reader.getGUI();
|
||||
auto menu = std::make_shared<Menu>(gui);
|
||||
menu->setPageLoader(gui.getMenu()->getPageLoader());
|
||||
read_container_impl(reader, element, *menu);
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
UiXmlReader::UiXmlReader(const scriptenv& env) : env(env) {
|
||||
UiXmlReader::UiXmlReader(gui::GUI& gui, const scriptenv& env) : gui(gui), env(env) {
|
||||
contextStack.emplace("");
|
||||
add("image", read_image);
|
||||
add("canvas", read_canvas);
|
||||
@@ -742,16 +767,15 @@ void UiXmlReader::addIgnore(const std::string& tag) {
|
||||
ignored.insert(tag);
|
||||
}
|
||||
|
||||
std::shared_ptr<UINode> UiXmlReader::readUINode(const xml::xmlelement& element) {
|
||||
std::shared_ptr<UINode> UiXmlReader::readUINode(const xml::xmlelement& element
|
||||
) {
|
||||
if (element.has("if")) {
|
||||
const auto& cond = element.attr("if").getText();
|
||||
if (cond.empty() || cond == "false" || cond == "nil")
|
||||
return nullptr;
|
||||
if (cond.empty() || cond == "false" || cond == "nil") return nullptr;
|
||||
}
|
||||
if (element.has("ifnot")) {
|
||||
const auto& cond = element.attr("ifnot").getText();
|
||||
if (!(cond.empty() || cond == "false" || cond == "nil"))
|
||||
return nullptr;
|
||||
if (!(cond.empty() || cond == "false" || cond == "nil")) return nullptr;
|
||||
}
|
||||
|
||||
const std::string& tag = element.getTag();
|
||||
@@ -760,7 +784,7 @@ std::shared_ptr<UINode> UiXmlReader::readUINode(const xml::xmlelement& element)
|
||||
if (ignored.find(tag) != ignored.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
throw std::runtime_error("unsupported element '"+tag+"'");
|
||||
throw std::runtime_error("unsupported element '" + tag + "'");
|
||||
}
|
||||
|
||||
bool hascontext = element.has("context");
|
||||
@@ -775,8 +799,7 @@ std::shared_ptr<UINode> UiXmlReader::readUINode(const xml::xmlelement& element)
|
||||
}
|
||||
|
||||
std::shared_ptr<UINode> UiXmlReader::readXML(
|
||||
const std::string& filename,
|
||||
const std::string& source
|
||||
const std::string& filename, const std::string& source
|
||||
) {
|
||||
this->filename = filename;
|
||||
auto document = xml::parse(filename, source);
|
||||
@@ -784,8 +807,7 @@ std::shared_ptr<UINode> UiXmlReader::readXML(
|
||||
}
|
||||
|
||||
std::shared_ptr<UINode> UiXmlReader::readXML(
|
||||
const std::string& filename,
|
||||
const xml::xmlelement& root
|
||||
const std::string& filename, const xml::xmlelement& root
|
||||
) {
|
||||
this->filename = filename;
|
||||
return readUINode(root);
|
||||
@@ -802,3 +824,7 @@ const std::string& UiXmlReader::getFilename() const {
|
||||
const scriptenv& UiXmlReader::getEnvironment() const {
|
||||
return env;
|
||||
}
|
||||
|
||||
gui::GUI& UiXmlReader::getGUI() const {
|
||||
return gui;
|
||||
}
|
||||
|
||||
@@ -15,13 +15,14 @@ namespace gui {
|
||||
std::shared_ptr<UINode>(UiXmlReader&, const xml::xmlelement&)>;
|
||||
|
||||
class UiXmlReader {
|
||||
gui::GUI& gui;
|
||||
std::unordered_map<std::string, uinode_reader> readers;
|
||||
std::unordered_set<std::string> ignored;
|
||||
std::stack<std::string> contextStack;
|
||||
std::string filename;
|
||||
const scriptenv& env;
|
||||
public:
|
||||
UiXmlReader(const scriptenv& env);
|
||||
UiXmlReader(gui::GUI& gui, const scriptenv& env);
|
||||
|
||||
void add(const std::string& tag, uinode_reader reader);
|
||||
bool hasReader(const std::string& tag) const;
|
||||
@@ -54,5 +55,6 @@ namespace gui {
|
||||
const std::string& getContext() const;
|
||||
const scriptenv& getEnvironment() const;
|
||||
const std::string& getFilename() const;
|
||||
gui::GUI& getGUI() const;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user