diff --git a/src/frontend/ContentGfxCache.h b/src/frontend/ContentGfxCache.h index 7c644709..a34d0c92 100644 --- a/src/frontend/ContentGfxCache.h +++ b/src/frontend/ContentGfxCache.h @@ -4,8 +4,6 @@ #include "../typedefs.h" #include -#include -#include class Content; class Assets; diff --git a/src/frontend/InventoryView.h b/src/frontend/InventoryView.h deleted file mode 100644 index 93632367..00000000 --- a/src/frontend/InventoryView.h +++ /dev/null @@ -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 -#include -#include - -class Assets; -class GfxContext; -class Content; -class ItemStack; -class ContentIndices; -class LevelFrontend; -class Inventory; - -namespace gui { - class UiXmlReader; -} - -using slotcallback = std::function; - -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; - - std::vector 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, - const Content* content - ); - - void unbind(); - - std::shared_ptr addSlot(SlotLayout layout); - - std::shared_ptr 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 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 build(); -}; - -#endif // FRONTEND_INVENTORY_VIEW_H_ diff --git a/src/frontend/UiDocument.cpp b/src/frontend/UiDocument.cpp index a535961d..000d2fa8 100644 --- a/src/frontend/UiDocument.cpp +++ b/src/frontend/UiDocument.cpp @@ -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::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() ); diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 86994dbb..90544f03 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -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 #include +using namespace gui; // implemented in debug_panel.cpp -extern std::shared_ptr create_debug_panel( +extern std::shared_ptr create_debug_panel( Engine* engine, Level* level, Player* player @@ -59,7 +60,7 @@ extern std::shared_ptr create_debug_panel( HudElement::HudElement( hud_element_mode mode, UiDocument* document, - std::shared_ptr node, + std::shared_ptr node, bool debug ) : mode(mode), document(document), node(node), debug(debug) { } @@ -89,7 +90,7 @@ UiDocument* HudElement::getDocument() const { return document; } -std::shared_ptr HudElement::getNode() const { +std::shared_ptr 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( + contentAccessPanel = std::make_shared( 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(350, 250, 2000, 16); - dplotter->setGravity(gui::Gravity::bottom_right); + auto dplotter = std::make_shared(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 node) { +void Hud::remove(std::shared_ptr node) { for (auto& element : elements) { if (element.getNode() == node) { element.setRemoved(); diff --git a/src/frontend/hud.h b/src/frontend/hud.h index c7ead508..5dd64314 100644 --- a/src/frontend/hud.h +++ b/src/frontend/hud.h @@ -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 contentAccessPanel; /// @brief Content access panel itself - std::shared_ptr contentAccess; + std::shared_ptr contentAccess; /// @brief Player inventory hotbar - std::shared_ptr hotbarView; + std::shared_ptr hotbarView; /// @brief Debug info and control panel (F3 key) std::shared_ptr debugPanel; /// @brief Overlay used in pause mode std::shared_ptr darkOverlay; /// @brief Inventories interaction agent (grabbed item) - std::shared_ptr exchangeSlot; + std::shared_ptr exchangeSlot; /// @brief Exchange slot inventory (1 slot only) std::shared_ptr exchangeSlotInv = nullptr; /// @brief List of all controlled hud elements std::vector elements; /// @brief Player inventory view - std::shared_ptr inventoryView = nullptr; + std::shared_ptr inventoryView = nullptr; /// @brief Block inventory view - std::shared_ptr blockUI = nullptr; + std::shared_ptr 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 secondUI = nullptr; - std::shared_ptr createContentAccess(); - std::shared_ptr createHotbar(); + std::shared_ptr createContentAccess(); + std::shared_ptr createHotbar(); void processInput(bool visible); void updateElementsPosition(const Viewport& viewport); diff --git a/src/frontend/InventoryView.cpp b/src/graphics/ui/elements/InventoryView.cpp similarity index 65% rename from src/frontend/InventoryView.cpp rename to src/graphics/ui/elements/InventoryView.cpp index a4a8264d..2e1ad608 100644 --- a/src/frontend/InventoryView.cpp +++ b/src/graphics/ui/elements/InventoryView.cpp @@ -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 #include -#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(); - 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; - }); -} diff --git a/src/graphics/ui/elements/InventoryView.hpp b/src/graphics/ui/elements/InventoryView.hpp new file mode 100644 index 00000000..d38e7242 --- /dev/null +++ b/src/graphics/ui/elements/InventoryView.hpp @@ -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 +#include +#include + +class Assets; +class GfxContext; +class Content; +class ItemStack; +class ContentIndices; +class LevelFrontend; +class Inventory; + +namespace gui { + class UiXmlReader; +} + +namespace gui { + using slotcallback = std::function; + + 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; + + std::vector 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, + const Content* content + ); + + void unbind(); + + std::shared_ptr addSlot(SlotLayout layout); + + std::shared_ptr 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 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 build(); + }; +} + +#endif // FRONTEND_INVENTORY_VIEW_H_ diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index 6117be37..70c43682 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -1,8 +1,5 @@ #include "gui_xml.hpp" -#include -#include - #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 + 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 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 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 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 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 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(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 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 readInventory(UiXmlReader& reader, xml::xmlelement element) { + auto view = std::make_shared(); + 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) { diff --git a/src/logic/scripting/lua/libgui.cpp b/src/logic/scripting/lua/libgui.cpp index b1399443..955a8ae4 100644 --- a/src/logic/scripting/lua/libgui.cpp +++ b/src/logic/scripting/lua/libgui.cpp @@ -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(node.node); + auto menu = dynamic_cast(node.node); menu->back(); return 0; } static int menu_reset(lua_State* L) { auto node = getDocumentNode(L); - auto menu = dynamic_cast(node.node); + auto menu = dynamic_cast(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(docnode.node); + auto node = dynamic_cast(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(node), attr)) + if (getattr(L, dynamic_cast(node), attr)) return 1; - if (getattr(L, dynamic_cast(node), attr)) + if (getattr(L, dynamic_cast(node), attr)) return 1; - if (getattr(L, dynamic_cast(node), attr)) + if (getattr(L, dynamic_cast(node), attr)) return 1; - if (getattr(L, dynamic_cast(node), attr)) + if (getattr(L, dynamic_cast(node), attr)) return 1; - if (getattr(L, dynamic_cast(node), attr)) + if (getattr(L, dynamic_cast(node), attr)) return 1; - if (getattr(L, dynamic_cast(node), attr)) + if (getattr(L, dynamic_cast(node), attr)) return 1; - if (getattr(L, dynamic_cast(node), attr)) + if (getattr(L, dynamic_cast(node), attr)) + return 1; + if (getattr(L, dynamic_cast(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(node), attr)) + if (setattr(L, dynamic_cast(node), attr)) return 0; - if (setattr(L, dynamic_cast(node), attr)) + if (setattr(L, dynamic_cast(node), attr)) return 0; - if (setattr(L, dynamic_cast(node), attr)) + if (setattr(L, dynamic_cast(node), attr)) return 0; - if (setattr(L, dynamic_cast(node), attr)) + if (setattr(L, dynamic_cast(node), attr)) return 0; - if (setattr(L, dynamic_cast(node), attr)) + if (setattr(L, dynamic_cast(node), attr)) return 0; - if (setattr(L, dynamic_cast(node), attr)) + if (setattr(L, dynamic_cast(node), attr)) + return 0; + if (setattr(L, dynamic_cast(node), attr)) return 0; } return 0; diff --git a/src/logic/scripting/lua/libhud.cpp b/src/logic/scripting/lua/libhud.cpp index 555c6e69..9efb0a14 100644 --- a/src/logic/scripting/lua/libhud.cpp +++ b/src/logic/scripting/lua/libhud.cpp @@ -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 #include -#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; }