InventoryView inventory property

This commit is contained in:
MihailRis 2024-04-29 15:18:45 +03:00
parent 1401eca712
commit beaeba43af
10 changed files with 382 additions and 369 deletions

View File

@ -4,8 +4,6 @@
#include "../typedefs.h"
#include <memory>
#include <string>
#include <unordered_map>
class Content;
class Assets;

View File

@ -1,140 +0,0 @@
#ifndef FRONTEND_INVENTORY_VIEW_H_
#define FRONTEND_INVENTORY_VIEW_H_
#include "../graphics/ui/elements/UINode.hpp"
#include "../graphics/ui/elements/Container.hpp"
#include "../typedefs.h"
#include "../constants.h"
#include <vector>
#include <functional>
#include <glm/glm.hpp>
class Assets;
class GfxContext;
class Content;
class ItemStack;
class ContentIndices;
class LevelFrontend;
class Inventory;
namespace gui {
class UiXmlReader;
}
using slotcallback = std::function<void(uint, ItemStack&)>;
struct SlotLayout {
int index;
glm::vec2 position;
bool background;
bool itemSource;
slotcallback updateFunc;
slotcallback shareFunc;
slotcallback rightClick;
int padding = 0;
SlotLayout(
int index,
glm::vec2 position,
bool background,
bool itemSource,
slotcallback updateFunc,
slotcallback shareFunc,
slotcallback rightClick
);
};
class SlotView : public gui::UINode {
const Content* content;
SlotLayout layout;
bool highlighted = false;
int64_t inventoryid = 0;
ItemStack* bound = nullptr;
public:
SlotView(SlotLayout layout);
virtual void draw(const GfxContext* pctx, Assets* assets) override;
void setHighlighted(bool flag);
bool isHighlighted() const;
virtual void clicked(gui::GUI*, mousecode) override;
virtual void onFocus(gui::GUI*) override;
void bind(
int64_t inventoryid,
ItemStack& stack,
const Content* content
);
ItemStack& getStack();
const SlotLayout& getLayout() const;
static inline std::string EXCHANGE_SLOT_NAME = "exchange-slot";
};
class InventoryView : public gui::Container {
const Content* content;
std::shared_ptr<Inventory> inventory;
std::vector<SlotView*> slots;
glm::vec2 origin {};
public:
InventoryView();
virtual ~InventoryView();
virtual void setPos(glm::vec2 pos) override;
void setOrigin(glm::vec2 origin);
glm::vec2 getOrigin() const;
void setSelected(int index);
void bind(
std::shared_ptr<Inventory> inventory,
const Content* content
);
void unbind();
std::shared_ptr<SlotView> addSlot(SlotLayout layout);
std::shared_ptr<Inventory> getInventory() const;
size_t getSlotsCount() const;
static void createReaders(gui::UiXmlReader& reader);
static const int SLOT_INTERVAL = 4;
static const int SLOT_SIZE = ITEM_ICON_SIZE;
};
class InventoryBuilder {
std::shared_ptr<InventoryView> view;
public:
InventoryBuilder();
/// @brief Add slots grid to inventory view
/// @param cols grid columns
/// @param count total number of grid slots
/// @param pos position of the first slot of the grid
/// @param padding additional space around the grid
/// @param addpanel automatically create panel behind the grid
/// with size including padding
/// @param slotLayout slot settings (index and position are ignored)
void addGrid(
int cols, int count,
glm::vec2 pos,
int padding,
bool addpanel,
SlotLayout slotLayout
);
void add(SlotLayout slotLayout);
std::shared_ptr<InventoryView> build();
};
#endif // FRONTEND_INVENTORY_VIEW_H_

View File

@ -2,9 +2,9 @@
#include "../files/files.h"
#include "../graphics/ui/elements/UINode.hpp"
#include "../graphics/ui/elements/InventoryView.hpp"
#include "../graphics/ui/gui_xml.hpp"
#include "../logic/scripting/scripting.h"
#include "InventoryView.h"
UiDocument::UiDocument(
std::string id,
@ -60,7 +60,6 @@ std::unique_ptr<UiDocument> UiDocument::read(scriptenv penv, std::string name, f
: scripting::create_doc_environment(penv, name);
gui::UiXmlReader reader(env);
InventoryView::createReaders(reader);
auto view = reader.readXML(
file.u8string(), xmldoc->getRoot()
);

View File

@ -14,6 +14,7 @@
#include "../graphics/core/Shader.hpp"
#include "../graphics/core/Texture.hpp"
#include "../graphics/render/WorldRenderer.hpp"
#include "../graphics/ui/elements/InventoryView.hpp"
#include "../graphics/ui/elements/Menu.hpp"
#include "../graphics/ui/elements/Panel.hpp"
#include "../graphics/ui/elements/Plotter.hpp"
@ -39,7 +40,6 @@
#include "../world/Level.h"
#include "../world/World.h"
#include "ContentGfxCache.h"
#include "InventoryView.h"
#include "LevelFrontend.h"
#include "UiDocument.h"
@ -48,9 +48,10 @@
#include <stdexcept>
#include <string>
using namespace gui;
// implemented in debug_panel.cpp
extern std::shared_ptr<gui::UINode> create_debug_panel(
extern std::shared_ptr<UINode> create_debug_panel(
Engine* engine,
Level* level,
Player* player
@ -59,7 +60,7 @@ extern std::shared_ptr<gui::UINode> create_debug_panel(
HudElement::HudElement(
hud_element_mode mode,
UiDocument* document,
std::shared_ptr<gui::UINode> node,
std::shared_ptr<UINode> node,
bool debug
) : mode(mode), document(document), node(node), debug(debug) {
}
@ -89,7 +90,7 @@ UiDocument* HudElement::getDocument() const {
return document;
}
std::shared_ptr<gui::UINode> HudElement::getNode() const {
std::shared_ptr<UINode> HudElement::getNode() const {
return node;
}
@ -144,7 +145,7 @@ Hud::Hud(Engine* engine, LevelFrontend* frontend, Player* player)
player(player)
{
contentAccess = createContentAccess();
contentAccessPanel = std::make_shared<gui::Panel>(
contentAccessPanel = std::make_shared<Panel>(
contentAccess->getSize(), glm::vec4(0.0f), 0.0f
);
contentAccessPanel->setColor(glm::vec4());
@ -168,8 +169,8 @@ Hud::Hud(Engine* engine, LevelFrontend* frontend, Player* player)
gui->add(debugPanel);
gui->add(contentAccessPanel);
auto dplotter = std::make_shared<gui::Plotter>(350, 250, 2000, 16);
dplotter->setGravity(gui::Gravity::bottom_right);
auto dplotter = std::make_shared<Plotter>(350, 250, 2000, 16);
dplotter->setGravity(Gravity::bottom_right);
add(HudElement(hud_element_mode::permanent, nullptr, dplotter, true));
}
@ -411,7 +412,7 @@ void Hud::onRemove(HudElement& element) {
gui->remove(element.getNode());
}
void Hud::remove(std::shared_ptr<gui::UINode> node) {
void Hud::remove(std::shared_ptr<UINode> node) {
for (auto& element : elements) {
if (element.getNode() == node) {
element.setRemoved();

View File

@ -13,9 +13,7 @@ class Block;
class Assets;
class Player;
class Engine;
class SlotView;
class Inventory;
class InventoryView;
class LevelFrontend;
class UiDocument;
class GfxContext;
@ -26,6 +24,8 @@ namespace gui {
class UINode;
class Panel;
class Container;
class InventoryView;
class SlotView;
}
enum class hud_element_mode {
@ -78,24 +78,24 @@ class Hud {
/// @brief Content access panel scroll container
std::shared_ptr<gui::Container> contentAccessPanel;
/// @brief Content access panel itself
std::shared_ptr<InventoryView> contentAccess;
std::shared_ptr<gui::InventoryView> contentAccess;
/// @brief Player inventory hotbar
std::shared_ptr<InventoryView> hotbarView;
std::shared_ptr<gui::InventoryView> hotbarView;
/// @brief Debug info and control panel (F3 key)
std::shared_ptr<gui::UINode> debugPanel;
/// @brief Overlay used in pause mode
std::shared_ptr<gui::UINode> darkOverlay;
/// @brief Inventories interaction agent (grabbed item)
std::shared_ptr<SlotView> exchangeSlot;
std::shared_ptr<gui::SlotView> exchangeSlot;
/// @brief Exchange slot inventory (1 slot only)
std::shared_ptr<Inventory> exchangeSlotInv = nullptr;
/// @brief List of all controlled hud elements
std::vector<HudElement> elements;
/// @brief Player inventory view
std::shared_ptr<InventoryView> inventoryView = nullptr;
std::shared_ptr<gui::InventoryView> inventoryView = nullptr;
/// @brief Block inventory view
std::shared_ptr<InventoryView> blockUI = nullptr;
std::shared_ptr<gui::InventoryView> blockUI = nullptr;
/// @brief Position of the block open
glm::ivec3 blockPos {};
/// @brief Id of the block open (used to detect block destruction or replacement)
@ -104,8 +104,8 @@ class Hud {
/// @brief UI element will be dynamicly positioned near to inventory or in screen center
std::shared_ptr<gui::UINode> secondUI = nullptr;
std::shared_ptr<InventoryView> createContentAccess();
std::shared_ptr<InventoryView> createHotbar();
std::shared_ptr<gui::InventoryView> createContentAccess();
std::shared_ptr<gui::InventoryView> createHotbar();
void processInput(bool visible);
void updateElementsPosition(const Viewport& viewport);

View File

@ -1,30 +1,31 @@
#include "InventoryView.h"
#include "InventoryView.hpp"
#include "../../../assets/Assets.h"
#include "../../../content/Content.h"
#include "../../../frontend/LevelFrontend.h"
#include "../../../items/Inventories.h"
#include "../../../items/Inventory.h"
#include "../../../items/ItemDef.h"
#include "../../../items/ItemStack.h"
#include "../../../logic/scripting/scripting.h"
#include "../../../maths/voxmaths.h"
#include "../../../objects/Player.h"
#include "../../../util/stringutil.h"
#include "../../../voxels/Block.h"
#include "../../../window/Events.h"
#include "../../../window/input.h"
#include "../../../world/Level.h"
#include "../../core/Atlas.hpp"
#include "../../core/Batch2D.hpp"
#include "../../core/Font.hpp"
#include "../../core/GfxContext.hpp"
#include "../../core/Shader.hpp"
#include "../../render/BlocksPreview.hpp"
#include "../GUI.hpp"
#include <iostream>
#include <glm/glm.hpp>
#include "../assets/Assets.h"
#include "../content/Content.h"
#include "../graphics/core/Atlas.hpp"
#include "../graphics/core/Batch2D.hpp"
#include "../graphics/core/Font.hpp"
#include "../graphics/core/GfxContext.hpp"
#include "../graphics/core/Shader.hpp"
#include "../graphics/ui/GUI.hpp"
#include "../graphics/render/BlocksPreview.hpp"
#include "../items/Inventories.h"
#include "../items/Inventory.h"
#include "../items/ItemDef.h"
#include "../items/ItemStack.h"
#include "../logic/scripting/scripting.h"
#include "../maths/voxmaths.h"
#include "../objects/Player.h"
#include "../util/stringutil.h"
#include "../voxels/Block.h"
#include "../window/Events.h"
#include "../window/input.h"
#include "../world/Level.h"
#include "LevelFrontend.h"
using namespace gui;
SlotLayout::SlotLayout(
int index,
@ -361,112 +362,3 @@ void InventoryView::setOrigin(glm::vec2 origin) {
glm::vec2 InventoryView::getOrigin() const {
return origin;
}
#include "../coders/xml.h"
#include "../graphics/ui/gui_xml.hpp"
static slotcallback readSlotFunc(InventoryView* view, gui::UiXmlReader& reader, xml::xmlelement& element, const std::string& attr) {
auto consumer = scripting::create_int_array_consumer(
reader.getEnvironment(),
element->attr(attr).getText()
);
return [=](uint slot, ItemStack& stack) {
int args[] {int(view->getInventory()->getId()), int(slot)};
consumer(args, 2);
};
}
static void readSlot(InventoryView* view, gui::UiXmlReader& reader, xml::xmlelement element) {
int index = element->attr("index", "0").asInt();
bool itemSource = element->attr("item-source", "false").asBool();
SlotLayout layout(index, glm::vec2(), true, itemSource, nullptr, nullptr, nullptr);
if (element->has("pos")) {
layout.position = element->attr("pos").asVec2();
}
if (element->has("updatefunc")) {
layout.updateFunc = readSlotFunc(view, reader, element, "updatefunc");
}
if (element->has("sharefunc")) {
layout.shareFunc = readSlotFunc(view, reader, element, "sharefunc");
}
if (element->has("onrightclick")) {
layout.rightClick = readSlotFunc(view, reader, element, "onrightclick");
}
auto slot = view->addSlot(layout);
reader.readUINode(reader, element, *slot);
view->add(slot);
}
static void readSlotsGrid(InventoryView* view, gui::UiXmlReader& reader, xml::xmlelement element) {
int startIndex = element->attr("start-index", "0").asInt();
int rows = element->attr("rows", "0").asInt();
int cols = element->attr("cols", "0").asInt();
int count = element->attr("count", "0").asInt();
const int slotSize = InventoryView::SLOT_SIZE;
int interval = element->attr("interval", "-1").asInt();
if (interval < 0) {
interval = InventoryView::SLOT_INTERVAL;
}
int padding = element->attr("padding", "-1").asInt();
if (padding < 0) {
padding = interval;
}
if (rows == 0) {
rows = ceildiv(count, cols);
} else if (cols == 0) {
cols = ceildiv(count, rows);
} else if (count == 0) {
count = rows * cols;
}
bool itemSource = element->attr("item-source", "false").asBool();
SlotLayout layout(-1, glm::vec2(), true, itemSource, nullptr, nullptr, nullptr);
if (element->has("pos")) {
layout.position = element->attr("pos").asVec2();
}
if (element->has("updatefunc")) {
layout.updateFunc = readSlotFunc(view, reader, element, "updatefunc");
}
if (element->has("sharefunc")) {
layout.shareFunc = readSlotFunc(view, reader, element, "sharefunc");
}
if (element->has("onrightclick")) {
layout.rightClick = readSlotFunc(view, reader, element, "onrightclick");
}
layout.padding = padding;
int idx = 0;
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++, idx++) {
if (idx >= count) {
return;
}
SlotLayout slotLayout = layout;
slotLayout.index = startIndex + idx;
slotLayout.position += glm::vec2(
padding + col * (slotSize + interval),
padding + (rows-row-1) * (slotSize + interval)
);
auto slot = view->addSlot(slotLayout);
view->add(slot, slotLayout.position);
}
}
}
void InventoryView::createReaders(gui::UiXmlReader& reader) {
reader.add("inventory", [=](gui::UiXmlReader& reader, xml::xmlelement element) {
auto view = std::make_shared<InventoryView>();
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);
for (auto& sub : element->getElements()) {
if (sub->getTag() == "slot") {
readSlot(view.get(), reader, sub);
} else if (sub->getTag() == "slots-grid") {
readSlotsGrid(view.get(), reader, sub);
}
}
return view;
});
}

View File

@ -0,0 +1,140 @@
#ifndef FRONTEND_INVENTORY_VIEW_H_
#define FRONTEND_INVENTORY_VIEW_H_
#include "UINode.hpp"
#include "Container.hpp"
#include "../../../typedefs.h"
#include "../../../constants.h"
#include <vector>
#include <functional>
#include <glm/glm.hpp>
class Assets;
class GfxContext;
class Content;
class ItemStack;
class ContentIndices;
class LevelFrontend;
class Inventory;
namespace gui {
class UiXmlReader;
}
namespace gui {
using slotcallback = std::function<void(uint, ItemStack&)>;
struct SlotLayout {
int index;
glm::vec2 position;
bool background;
bool itemSource;
slotcallback updateFunc;
slotcallback shareFunc;
slotcallback rightClick;
int padding = 0;
SlotLayout(
int index,
glm::vec2 position,
bool background,
bool itemSource,
slotcallback updateFunc,
slotcallback shareFunc,
slotcallback rightClick
);
};
class SlotView : public gui::UINode {
const Content* content;
SlotLayout layout;
bool highlighted = false;
int64_t inventoryid = 0;
ItemStack* bound = nullptr;
public:
SlotView(SlotLayout layout);
virtual void draw(const GfxContext* pctx, Assets* assets) override;
void setHighlighted(bool flag);
bool isHighlighted() const;
virtual void clicked(gui::GUI*, mousecode) override;
virtual void onFocus(gui::GUI*) override;
void bind(
int64_t inventoryid,
ItemStack& stack,
const Content* content
);
ItemStack& getStack();
const SlotLayout& getLayout() const;
static inline std::string EXCHANGE_SLOT_NAME = "exchange-slot";
};
class InventoryView : public gui::Container {
const Content* content;
std::shared_ptr<Inventory> inventory;
std::vector<SlotView*> slots;
glm::vec2 origin {};
public:
InventoryView();
virtual ~InventoryView();
virtual void setPos(glm::vec2 pos) override;
void setOrigin(glm::vec2 origin);
glm::vec2 getOrigin() const;
void setSelected(int index);
void bind(
std::shared_ptr<Inventory> inventory,
const Content* content
);
void unbind();
std::shared_ptr<SlotView> addSlot(SlotLayout layout);
std::shared_ptr<Inventory> getInventory() const;
size_t getSlotsCount() const;
static const int SLOT_INTERVAL = 4;
static const int SLOT_SIZE = ITEM_ICON_SIZE;
};
class InventoryBuilder {
std::shared_ptr<InventoryView> view;
public:
InventoryBuilder();
/// @brief Add slots grid to inventory view
/// @param cols grid columns
/// @param count total number of grid slots
/// @param pos position of the first slot of the grid
/// @param padding additional space around the grid
/// @param addpanel automatically create panel behind the grid
/// with size including padding
/// @param slotLayout slot settings (index and position are ignored)
void addGrid(
int cols, int count,
glm::vec2 pos,
int padding,
bool addpanel,
SlotLayout slotLayout
);
void add(SlotLayout slotLayout);
std::shared_ptr<InventoryView> build();
};
}
#endif // FRONTEND_INVENTORY_VIEW_H_

View File

@ -1,8 +1,5 @@
#include "gui_xml.hpp"
#include <charconv>
#include <stdexcept>
#include "elements/Panel.hpp"
#include "elements/Image.hpp"
#include "elements/Button.hpp"
@ -10,12 +7,17 @@
#include "elements/TextBox.hpp"
#include "elements/TrackBar.hpp"
#include "elements/InputBindBox.hpp"
#include "elements/InventoryView.hpp"
#include "../../frontend/locale/langs.h"
#include "../../items/Inventory.h"
#include "../../logic/scripting/scripting.h"
#include "../../maths/voxmaths.h"
#include "../../util/stringutil.h"
#include "../../window/Events.h"
#include <stdexcept>
using namespace gui;
static Align align_from_string(const std::string& str, Align def) {
@ -84,12 +86,11 @@ static void _readUINode(UiXmlReader& reader, xml::xmlelement element, UINode& no
node.setVisible(element->attr("visible").asBool());
}
if (element->has("position-func")) {
auto supplier = scripting::create_vec2_supplier(
node.setPositionFunc(scripting::create_vec2_supplier(
reader.getEnvironment(),
element->attr("position-func").getText(),
reader.getFilename()+".lua"
);
node.setPositionFunc(supplier);
));
}
if (element->has("hover-color")) {
node.setHoverColor(element->attr("hover-color").asColor());
@ -208,12 +209,11 @@ static std::shared_ptr<UINode> readLabel(UiXmlReader& reader, xml::xmlelement el
);
}
if (element->has("supplier")) {
auto supplier = scripting::create_wstring_supplier(
label->textSupplier(scripting::create_wstring_supplier(
reader.getEnvironment(),
element->attr("supplier").getText(),
reader.getFilename()
);
label->textSupplier(supplier);
));
}
if (element->has("multiline")) {
label->setMultiline(element->attr("multiline").asBool());
@ -268,21 +268,19 @@ static std::shared_ptr<UINode> readCheckBox(UiXmlReader& reader, xml::xmlelement
_readPanel(reader, element, *checkbox);
if (element->has("consumer")) {
auto consumer = scripting::create_bool_consumer(
checkbox->setConsumer(scripting::create_bool_consumer(
reader.getEnvironment(),
element->attr("consumer").getText(),
reader.getFilename()
);
checkbox->setConsumer(consumer);
));
}
if (element->has("supplier")) {
auto supplier = scripting::create_bool_supplier(
checkbox->setSupplier(scripting::create_bool_supplier(
reader.getEnvironment(),
element->attr("supplier").getText(),
reader.getFilename()
);
checkbox->setSupplier(supplier);
));
}
return checkbox;
}
@ -306,21 +304,19 @@ static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, xml::xmlelement
}
if (element->has("consumer")) {
auto consumer = scripting::create_wstring_consumer(
textbox->setTextConsumer(scripting::create_wstring_consumer(
reader.getEnvironment(),
element->attr("consumer").getText(),
reader.getFilename()
);
textbox->setTextConsumer(consumer);
));
}
if (element->has("supplier")) {
auto supplier = scripting::create_wstring_supplier(
textbox->setTextSupplier(scripting::create_wstring_supplier(
reader.getEnvironment(),
element->attr("supplier").getText(),
reader.getFilename()
);
textbox->setTextSupplier(supplier);
));
}
if (element->has("focused-color")) {
textbox->setFocusedColor(element->attr("focused-color").asColor());
@ -329,12 +325,11 @@ static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, xml::xmlelement
textbox->setErrorColor(element->attr("error-color").asColor());
}
if (element->has("validator")) {
auto validator = scripting::create_wstring_validator(
textbox->setTextValidator(scripting::create_wstring_validator(
reader.getEnvironment(),
element->attr("validator").getText(),
reader.getFilename()
);
textbox->setTextValidator(validator);
));
}
return textbox;
}
@ -351,24 +346,22 @@ static std::shared_ptr<UINode> readTrackBar(UiXmlReader& reader, xml::xmlelement
float max = element->attr("max", "1.0").asFloat();
float def = element->attr("value", "0.0").asFloat();
float step = element->attr("step", "1.0").asFloat();
int trackWidth = element->attr("track-width", "12.0").asInt();
int trackWidth = element->attr("track-width", "12").asInt();
auto bar = std::make_shared<TrackBar>(min, max, def, step, trackWidth);
_readUINode(reader, element, *bar);
if (element->has("consumer")) {
auto consumer = scripting::create_number_consumer(
bar->setConsumer(scripting::create_number_consumer(
reader.getEnvironment(),
element->attr("consumer").getText(),
reader.getFilename()
);
bar->setConsumer(consumer);
));
}
if (element->has("supplier")) {
auto supplier = scripting::create_number_supplier(
bar->setSupplier(scripting::create_number_supplier(
reader.getEnvironment(),
element->attr("supplier").getText(),
reader.getFilename()
);
bar->setSupplier(supplier);
));
}
if (element->has("track-color")) {
bar->setTrackColor(element->attr("track-color").asColor());
@ -389,6 +382,110 @@ static std::shared_ptr<UINode> readInputBindBox(UiXmlReader& reader, xml::xmlele
return bindbox;
}
static slotcallback readSlotFunc(InventoryView* view, UiXmlReader& reader, xml::xmlelement& element, const std::string& attr) {
auto consumer = scripting::create_int_array_consumer(
reader.getEnvironment(),
element->attr(attr).getText()
);
return [=](uint slot, ItemStack& stack) {
int args[] {int(view->getInventory()->getId()), int(slot)};
consumer(args, 2);
};
}
static void readSlot(InventoryView* view, UiXmlReader& reader, xml::xmlelement element) {
int index = element->attr("index", "0").asInt();
bool itemSource = element->attr("item-source", "false").asBool();
SlotLayout layout(index, glm::vec2(), true, itemSource, nullptr, nullptr, nullptr);
if (element->has("pos")) {
layout.position = element->attr("pos").asVec2();
}
if (element->has("updatefunc")) {
layout.updateFunc = readSlotFunc(view, reader, element, "updatefunc");
}
if (element->has("sharefunc")) {
layout.shareFunc = readSlotFunc(view, reader, element, "sharefunc");
}
if (element->has("onrightclick")) {
layout.rightClick = readSlotFunc(view, reader, element, "onrightclick");
}
auto slot = view->addSlot(layout);
reader.readUINode(reader, element, *slot);
view->add(slot);
}
static void readSlotsGrid(InventoryView* view, UiXmlReader& reader, xml::xmlelement element) {
int startIndex = element->attr("start-index", "0").asInt();
int rows = element->attr("rows", "0").asInt();
int cols = element->attr("cols", "0").asInt();
int count = element->attr("count", "0").asInt();
const int slotSize = InventoryView::SLOT_SIZE;
int interval = element->attr("interval", "-1").asInt();
if (interval < 0) {
interval = InventoryView::SLOT_INTERVAL;
}
int padding = element->attr("padding", "-1").asInt();
if (padding < 0) {
padding = interval;
}
if (rows == 0) {
rows = ceildiv(count, cols);
} else if (cols == 0) {
cols = ceildiv(count, rows);
} else if (count == 0) {
count = rows * cols;
}
bool itemSource = element->attr("item-source", "false").asBool();
SlotLayout layout(-1, glm::vec2(), true, itemSource, nullptr, nullptr, nullptr);
if (element->has("pos")) {
layout.position = element->attr("pos").asVec2();
}
if (element->has("updatefunc")) {
layout.updateFunc = readSlotFunc(view, reader, element, "updatefunc");
}
if (element->has("sharefunc")) {
layout.shareFunc = readSlotFunc(view, reader, element, "sharefunc");
}
if (element->has("onrightclick")) {
layout.rightClick = readSlotFunc(view, reader, element, "onrightclick");
}
layout.padding = padding;
int idx = 0;
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++, idx++) {
if (idx >= count) {
return;
}
SlotLayout slotLayout = layout;
slotLayout.index = startIndex + idx;
slotLayout.position += glm::vec2(
padding + col * (slotSize + interval),
padding + (rows-row-1) * (slotSize + interval)
);
auto slot = view->addSlot(slotLayout);
view->add(slot, slotLayout.position);
}
}
}
static std::shared_ptr<UINode> readInventory(UiXmlReader& reader, xml::xmlelement element) {
auto view = std::make_shared<InventoryView>();
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);
for (auto& sub : element->getElements()) {
if (sub->getTag() == "slot") {
readSlot(view.get(), reader, sub);
} else if (sub->getTag() == "slots-grid") {
readSlotsGrid(view.get(), reader, sub);
}
}
return view;
}
UiXmlReader::UiXmlReader(const scriptenv& env) : env(env) {
contextStack.push("");
add("image", readImage);
@ -400,6 +497,7 @@ UiXmlReader::UiXmlReader(const scriptenv& env) : env(env) {
add("trackbar", readTrackBar);
add("container", readContainer);
add("bindbox", readInputBindBox);
add("inventory", readInventory);
}
void UiXmlReader::add(const std::string& tag, uinode_reader reader) {

View File

@ -8,6 +8,7 @@
#include "../../../engine.h"
#include "../../../assets/Assets.h"
#include "../../../items/Inventories.h"
#include "../../../graphics/ui/gui_util.hpp"
#include "../../../graphics/ui/elements/UINode.hpp"
#include "../../../graphics/ui/elements/Button.hpp"
@ -16,13 +17,17 @@
#include "../../../graphics/ui/elements/TrackBar.hpp"
#include "../../../graphics/ui/elements/Panel.hpp"
#include "../../../graphics/ui/elements/Menu.hpp"
#include "../../../graphics/ui/elements/InventoryView.hpp"
#include "../../../frontend/UiDocument.h"
#include "../../../frontend/locale/langs.h"
#include "../../../util/stringutil.h"
#include "../../../world/Level.h"
using namespace gui;
struct DocumentNode {
UiDocument* document;
gui::UINode* node;
UINode* node;
};
static DocumentNode getDocumentNode(lua_State* L, const std::string& name, const std::string& nodeName) {
@ -37,7 +42,7 @@ static DocumentNode getDocumentNode(lua_State* L, const std::string& name, const
return {doc, node.get()};
}
static bool getattr(lua_State* L, gui::TrackBar* bar, const std::string& attr) {
static bool getattr(lua_State* L, TrackBar* bar, const std::string& attr) {
if (bar == nullptr)
return false;
if (attr == "value") {
@ -59,7 +64,7 @@ static bool getattr(lua_State* L, gui::TrackBar* bar, const std::string& attr) {
return false;
}
static bool setattr(lua_State* L, gui::TrackBar* bar, const std::string& attr) {
static bool setattr(lua_State* L, TrackBar* bar, const std::string& attr) {
if (bar == nullptr)
return false;
if (attr == "value") {
@ -84,7 +89,7 @@ static bool setattr(lua_State* L, gui::TrackBar* bar, const std::string& attr) {
return false;
}
static bool getattr(lua_State* L, gui::Button* button, const std::string& attr) {
static bool getattr(lua_State* L, Button* button, const std::string& attr) {
if (button == nullptr)
return false;
if (attr == "text") {
@ -96,7 +101,7 @@ static bool getattr(lua_State* L, gui::Button* button, const std::string& attr)
return false;
}
static bool getattr(lua_State* L, gui::Label* label, const std::string& attr) {
static bool getattr(lua_State* L, Label* label, const std::string& attr) {
if (label == nullptr)
return false;
if (attr == "text") {
@ -106,7 +111,7 @@ static bool getattr(lua_State* L, gui::Label* label, const std::string& attr) {
return false;
}
static bool getattr(lua_State* L, gui::FullCheckBox* box, const std::string& attr) {
static bool getattr(lua_State* L, FullCheckBox* box, const std::string& attr) {
if (box == nullptr)
return false;
if (attr == "checked") {
@ -116,7 +121,7 @@ static bool getattr(lua_State* L, gui::FullCheckBox* box, const std::string& att
return false;
}
static bool getattr(lua_State* L, gui::TextBox* box, const std::string& attr) {
static bool getattr(lua_State* L, TextBox* box, const std::string& attr) {
if (box == nullptr)
return false;
if (attr == "text") {
@ -144,19 +149,19 @@ static DocumentNode getDocumentNode(lua_State* L) {
static int menu_back(lua_State* L) {
auto node = getDocumentNode(L);
auto menu = dynamic_cast<gui::Menu*>(node.node);
auto menu = dynamic_cast<Menu*>(node.node);
menu->back();
return 0;
}
static int menu_reset(lua_State* L) {
auto node = getDocumentNode(L);
auto menu = dynamic_cast<gui::Menu*>(node.node);
auto menu = dynamic_cast<Menu*>(node.node);
menu->reset();
return 0;
}
static bool getattr(lua_State* L, gui::Menu* menu, const std::string& attr) {
static bool getattr(lua_State* L, Menu* menu, const std::string& attr) {
if (menu == nullptr)
return false;
if (attr == "page") {
@ -172,7 +177,7 @@ static bool getattr(lua_State* L, gui::Menu* menu, const std::string& attr) {
return false;
}
static bool setattr(lua_State* L, gui::FullCheckBox* box, const std::string& attr) {
static bool setattr(lua_State* L, FullCheckBox* box, const std::string& attr) {
if (box == nullptr)
return false;
if (attr == "checked") {
@ -182,7 +187,7 @@ static bool setattr(lua_State* L, gui::FullCheckBox* box, const std::string& att
return false;
}
static bool setattr(lua_State* L, gui::Button* button, const std::string& attr) {
static bool setattr(lua_State* L, Button* button, const std::string& attr) {
if (button == nullptr)
return false;
if (attr == "text") {
@ -194,7 +199,7 @@ static bool setattr(lua_State* L, gui::Button* button, const std::string& attr)
return false;
}
static bool setattr(lua_State* L, gui::TextBox* box, const std::string& attr) {
static bool setattr(lua_State* L, TextBox* box, const std::string& attr) {
if (box == nullptr)
return false;
if (attr == "text") {
@ -207,7 +212,7 @@ static bool setattr(lua_State* L, gui::TextBox* box, const std::string& attr) {
return false;
}
static bool setattr(lua_State* L, gui::Label* label, const std::string& attr) {
static bool setattr(lua_State* L, Label* label, const std::string& attr) {
if (label == nullptr)
return false;
if (attr == "text") {
@ -217,7 +222,7 @@ static bool setattr(lua_State* L, gui::Label* label, const std::string& attr) {
return false;
}
static bool setattr(lua_State* L, gui::Menu* menu, const std::string& attr) {
static bool setattr(lua_State* L, Menu* menu, const std::string& attr) {
if (menu == nullptr)
return false;
if (attr == "page") {
@ -228,21 +233,29 @@ static bool setattr(lua_State* L, gui::Menu* menu, const std::string& attr) {
return false;
}
static bool setattr(lua_State* L, InventoryView* inventory, const std::string& attr) {
if (attr == "inventory") {
auto inv = scripting::level->inventories->get(lua_tointeger(L, 1));
inventory->bind(inv, scripting::content);
}
return false;
}
static int container_add(lua_State* L) {
auto docnode = getDocumentNode(L);
auto node = dynamic_cast<gui::Container*>(docnode.node);
auto node = dynamic_cast<Container*>(docnode.node);
auto xmlsrc = lua_tostring(L, 2);
try {
auto subnode = guiutil::create(xmlsrc, docnode.document->getEnvironment());
node->add(subnode);
gui::UINode::getIndices(subnode, docnode.document->getMapWriteable());
UINode::getIndices(subnode, docnode.document->getMapWriteable());
} catch (const std::exception& err) {
luaL_error(L, err.what());
}
return 0;
}
static bool getattr(lua_State* L, gui::Container* container, const std::string& attr) {
static bool getattr(lua_State* L, Container* container, const std::string& attr) {
if (container == nullptr)
return false;
@ -253,6 +266,15 @@ static bool getattr(lua_State* L, gui::Container* container, const std::string&
return false;
}
static bool getattr(lua_State* L, InventoryView* inventory, const std::string& attr) {
if (attr == "inventory") {
auto inv = inventory->getInventory();
lua_pushinteger(L, inv ? inv->getId() : 0);
return true;
}
return false;
}
static int l_gui_getattr(lua_State* L) {
auto docname = lua_tostring(L, 1);
auto element = lua_tostring(L, 2);
@ -276,19 +298,21 @@ static int l_gui_getattr(lua_State* L) {
return 1;
}
if (getattr(L, dynamic_cast<gui::Container*>(node), attr))
if (getattr(L, dynamic_cast<Container*>(node), attr))
return 1;
if (getattr(L, dynamic_cast<gui::Button*>(node), attr))
if (getattr(L, dynamic_cast<Button*>(node), attr))
return 1;
if (getattr(L, dynamic_cast<gui::Label*>(node), attr))
if (getattr(L, dynamic_cast<Label*>(node), attr))
return 1;
if (getattr(L, dynamic_cast<gui::TextBox*>(node), attr))
if (getattr(L, dynamic_cast<TextBox*>(node), attr))
return 1;
if (getattr(L, dynamic_cast<gui::TrackBar*>(node), attr))
if (getattr(L, dynamic_cast<TrackBar*>(node), attr))
return 1;
if (getattr(L, dynamic_cast<gui::FullCheckBox*>(node), attr))
if (getattr(L, dynamic_cast<FullCheckBox*>(node), attr))
return 1;
if (getattr(L, dynamic_cast<gui::Menu*>(node), attr))
if (getattr(L, dynamic_cast<Menu*>(node), attr))
return 1;
if (getattr(L, dynamic_cast<InventoryView*>(node), attr))
return 1;
return 0;
@ -319,17 +343,19 @@ static int l_gui_setattr(lua_State* L) {
} else if (attr == "visible") {
node->setVisible(lua_toboolean(L, 4));
} else {
if (setattr(L, dynamic_cast<gui::Button*>(node), attr))
if (setattr(L, dynamic_cast<Button*>(node), attr))
return 0;
if (setattr(L, dynamic_cast<gui::Label*>(node), attr))
if (setattr(L, dynamic_cast<Label*>(node), attr))
return 0;
if (setattr(L, dynamic_cast<gui::TextBox*>(node), attr))
if (setattr(L, dynamic_cast<TextBox*>(node), attr))
return 0;
if (setattr(L, dynamic_cast<gui::TrackBar*>(node), attr))
if (setattr(L, dynamic_cast<TrackBar*>(node), attr))
return 0;
if (setattr(L, dynamic_cast<gui::FullCheckBox*>(node), attr))
if (setattr(L, dynamic_cast<FullCheckBox*>(node), attr))
return 0;
if (setattr(L, dynamic_cast<gui::Menu*>(node), attr))
if (setattr(L, dynamic_cast<Menu*>(node), attr))
return 0;
if (setattr(L, dynamic_cast<InventoryView*>(node), attr))
return 0;
}
return 0;

View File

@ -1,24 +1,23 @@
#include "lua_commons.h"
#include "api_lua.h"
#include "LuaState.h"
#include "../../../assets/Assets.h"
#include "../../../content/Content.h"
#include "../../../engine.h"
#include "../../../frontend/hud.h"
#include "../../../frontend/UiDocument.h"
#include "../../../graphics/ui/elements/InventoryView.hpp"
#include "../../../items/Inventories.h"
#include "../../../logic/BlocksController.h"
#include "../../../voxels/Block.h"
#include "../../../voxels/Chunks.h"
#include "../../../voxels/voxel.h"
#include "../../../world/Level.h"
#include "../scripting.h"
#include <iostream>
#include <glm/glm.hpp>
#include "../scripting.h"
#include "../../../assets/Assets.h"
#include "../../../frontend/hud.h"
#include "../../../world/Level.h"
#include "../../../voxels/Chunks.h"
#include "../../../voxels/voxel.h"
#include "../../../voxels/Block.h"
#include "../../../content/Content.h"
#include "../../../logic/BlocksController.h"
#include "../../../items/Inventories.h"
#include "../../../engine.h"
#include "../../../frontend/UiDocument.h"
#include "../../../frontend/InventoryView.h"
namespace scripting {
extern Hud* hud;
}