From 7e553efdecb273b30f57b03ec060461f56022f5c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 16 Feb 2024 13:57:03 +0300 Subject: [PATCH] lua: hud library --- res/layouts/inventory.xml.lua | 4 -- src/frontend/InventoryView.cpp | 5 ++ src/frontend/InventoryView.h | 2 + src/frontend/hud.cpp | 70 ++++++++++++++++------ src/frontend/hud.h | 10 +++- src/frontend/screens.cpp | 4 +- src/frontend/screens.h | 4 +- src/items/Inventories.cpp | 4 ++ src/items/Inventories.h | 3 + src/logic/scripting/api/libhud.cpp | 20 +++++++ src/logic/scripting/api/libhud.h | 15 +++++ src/logic/scripting/scripting.h | 2 - src/logic/scripting/scripting_frontend.cpp | 16 +++++ src/logic/scripting/scripting_frontend.h | 12 ++++ 14 files changed, 140 insertions(+), 31 deletions(-) create mode 100644 src/logic/scripting/api/libhud.cpp create mode 100644 src/logic/scripting/api/libhud.h create mode 100644 src/logic/scripting/scripting_frontend.cpp create mode 100644 src/logic/scripting/scripting_frontend.h diff --git a/res/layouts/inventory.xml.lua b/res/layouts/inventory.xml.lua index f38a00e7..c5cd5791 100644 --- a/res/layouts/inventory.xml.lua +++ b/res/layouts/inventory.xml.lua @@ -9,7 +9,3 @@ end function inventory_share_func(invid, slotid) inventory.set(invid, slotid, 0, 0) end - -function inventory_reposition() - return 10, gui.get_viewport()[2] - document.root.size[2] - 100 -end diff --git a/src/frontend/InventoryView.cpp b/src/frontend/InventoryView.cpp index 90304790..05cd88fd 100644 --- a/src/frontend/InventoryView.cpp +++ b/src/frontend/InventoryView.cpp @@ -310,6 +310,11 @@ std::shared_ptr InventoryView::getInventory() const { return inventory; } + +size_t InventoryView::getSlotsCount() const { + return slots.size(); +} + void InventoryView::bind( std::shared_ptr inventory, LevelFrontend* frontend, diff --git a/src/frontend/InventoryView.h b/src/frontend/InventoryView.h index 7a8238ae..0a4cc0ba 100644 --- a/src/frontend/InventoryView.h +++ b/src/frontend/InventoryView.h @@ -117,6 +117,8 @@ public: std::shared_ptr getInventory() const; + size_t getSlotsCount() const; + static void createReaders(gui::UiXmlReader& reader); static const int SLOT_INTERVAL = 4; diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index f9b93a95..2a29f355 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -48,6 +48,7 @@ #include "../core_defs.h" #include "../items/ItemDef.h" #include "../items/Inventory.h" +#include "../items/Inventories.h" #include "../logic/scripting/scripting.h" using namespace gui; @@ -94,7 +95,7 @@ std::shared_ptr HudElement::getNode() const { return node; } -std::shared_ptr HudRenderer::createDebugPanel(Engine* engine) { +std::shared_ptr Hud::createDebugPanel(Engine* engine) { auto level = frontend->getLevel(); auto panel = std::make_shared(glm::vec2(250, 200), glm::vec4(5.0f), 2.0f); @@ -204,7 +205,7 @@ std::shared_ptr HudRenderer::createDebugPanel(Engine* engine) { return panel; } -std::shared_ptr HudRenderer::createContentAccess() { +std::shared_ptr Hud::createContentAccess() { auto level = frontend->getLevel(); auto content = level->content; auto indices = content->getIndices(); @@ -234,7 +235,7 @@ std::shared_ptr HudRenderer::createContentAccess() { return view; } -std::shared_ptr HudRenderer::createHotbar() { +std::shared_ptr Hud::createHotbar() { auto level = frontend->getLevel(); auto player = level->player; auto inventory = player->getInventory(); @@ -250,7 +251,7 @@ std::shared_ptr HudRenderer::createHotbar() { return view; } -HudRenderer::HudRenderer(Engine* engine, LevelFrontend* frontend) +Hud::Hud(Engine* engine, LevelFrontend* frontend) : assets(engine->getAssets()), gui(engine->getGUI()), frontend(frontend) @@ -300,7 +301,7 @@ HudRenderer::HudRenderer(Engine* engine, LevelFrontend* frontend) gui->add(grabbedItemView); } -HudRenderer::~HudRenderer() { +Hud::~Hud() { // removing all controlled ui gui->remove(grabbedItemView); for (auto& element : elements) { @@ -312,13 +313,13 @@ HudRenderer::~HudRenderer() { gui->remove(debugPanel); } -void HudRenderer::drawDebug(int fps){ +void Hud::drawDebug(int fps){ this->fps = fps; fpsMin = min(fps, fpsMin); fpsMax = max(fps, fpsMax); } -void HudRenderer::update(bool visible) { +void Hud::update(bool visible) { auto level = frontend->getLevel(); auto player = level->player; auto menu = gui->getMenu(); @@ -391,7 +392,7 @@ void HudRenderer::update(bool visible) { /** * Show inventory on the screen and turn on inventory mode blocking movement */ -void HudRenderer::openInventory() { +void Hud::openInventory() { auto level = frontend->getLevel(); auto player = level->player; auto inventory = player->getInventory(); @@ -404,17 +405,48 @@ void HudRenderer::openInventory() { add(HudElement(hud_element_mode::inventory_bound, inventoryDocument, inventoryView, false)); } +/** + * Show player inventory + block UI + * @param block world position of the open block + * @param doc block UI document (root element must be an InventoryView) + * @param blockinv block inventory. + * In case of nullptr a new virtual inventory will be created + */ +void Hud::openInventory(glm::ivec3 block, UiDocument* doc, std::shared_ptr blockinv) { + auto level = frontend->getLevel(); + blockUI = std::dynamic_pointer_cast(doc->getRoot()); + if (blockUI == nullptr) { + throw std::runtime_error("block UI root element must be 'inventory'"); + } + openInventory(); + if (blockinv == nullptr) { + blockinv = level->inventories->createVirtual(blockUI->getSlotsCount()); + } + blockUI->bind(blockinv, frontend, interaction.get()); + add(HudElement(hud_element_mode::inventory_bound, doc, blockUI, false)); +} + /** * Hide inventory and turn off inventory mode */ -void HudRenderer::closeInventory() { +void Hud::closeInventory() { + auto level = frontend->getLevel(); + inventoryOpen = false; ItemStack& grabbed = interaction->getGrabbedItem(); grabbed.clear(); inventoryView = nullptr; + if (blockUI) { + auto blockinv = blockUI->getInventory(); + // todo: do it automatically + if (blockinv->isVirtual()) { + level->inventories->remove(blockinv->getId()); + } + blockUI = nullptr; + } } -void HudRenderer::add(HudElement element) { +void Hud::add(HudElement element) { gui->add(element.getNode()); auto invview = std::dynamic_pointer_cast(element.getNode()); auto document = element.getDocument(); @@ -429,7 +461,7 @@ void HudRenderer::add(HudElement element) { elements.push_back(element); } -void HudRenderer::remove(HudElement& element) { +void Hud::remove(HudElement& element) { auto document = element.getDocument(); if (document) { Inventory* inventory = nullptr; @@ -442,7 +474,7 @@ void HudRenderer::remove(HudElement& element) { gui->remove(element.getNode()); } -void HudRenderer::draw(const GfxContext& ctx){ +void Hud::draw(const GfxContext& ctx){ auto level = frontend->getLevel(); auto player = level->player; @@ -499,24 +531,24 @@ void HudRenderer::draw(const GfxContext& ctx){ contentAccessPanel->setCoord(glm::vec2(width-caWidth, 0)); glm::vec2 invSize = inventoryView->getSize(); - //inventoryView->setCoord(glm::vec2( - // glm::min(width/2-invSize.x/2, width-caWidth-10-invSize.x), - // height/2-invSize.y/2 - //)); + inventoryView->setCoord(glm::vec2( + glm::min(width/2-invSize.x/2, width-caWidth-10-invSize.x), + height/2-invSize.y/2 + )); } grabbedItemView->setCoord(glm::vec2(Events::cursor)); batch->render(); } -bool HudRenderer::isInventoryOpen() const { +bool Hud::isInventoryOpen() const { return inventoryOpen; } -bool HudRenderer::isPause() const { +bool Hud::isPause() const { return pause; } -void HudRenderer::setPause(bool pause) { +void Hud::setPause(bool pause) { if (this->pause == pause) { return; } diff --git a/src/frontend/hud.h b/src/frontend/hud.h index a5ba1c41..d15ccb4f 100644 --- a/src/frontend/hud.h +++ b/src/frontend/hud.h @@ -16,6 +16,7 @@ class Player; class Level; class Engine; class SlotView; +class Inventory; class InventoryView; class LevelFrontend; class UiDocument; @@ -59,7 +60,7 @@ public: } }; -class HudRenderer { +class Hud { Assets* assets; std::unique_ptr uicamera; @@ -83,13 +84,15 @@ class HudRenderer { std::vector elements; std::shared_ptr inventoryView = nullptr; + std::shared_ptr blockUI = nullptr; + glm::ivec3 currentblock {}; std::shared_ptr createDebugPanel(Engine* engine); std::shared_ptr createContentAccess(); std::shared_ptr createHotbar(); public: - HudRenderer(Engine* engine, LevelFrontend* frontend); - ~HudRenderer(); + Hud(Engine* engine, LevelFrontend* frontend); + ~Hud(); void update(bool hudVisible); void draw(const GfxContext& context); @@ -100,6 +103,7 @@ public: void setPause(bool pause); void openInventory(); + void openInventory(glm::ivec3 block, UiDocument* doc, std::shared_ptr blockInv); void closeInventory(); void add(HudElement element); diff --git a/src/frontend/screens.cpp b/src/frontend/screens.cpp index 475d3d86..26fff2c7 100644 --- a/src/frontend/screens.cpp +++ b/src/frontend/screens.cpp @@ -21,6 +21,7 @@ #include "../objects/Player.h" #include "../logic/ChunksController.h" #include "../logic/LevelController.h" +#include "../logic/scripting/scripting_frontend.h" #include "../voxels/Chunks.h" #include "../voxels/Chunk.h" #include "../engine.h" @@ -87,7 +88,7 @@ LevelScreen::LevelScreen(Engine* engine, Level* level) : Screen(engine), level(level), frontend(std::make_unique(level, engine->getAssets())), - hud(std::make_unique(engine, frontend.get())), + hud(std::make_unique(engine, frontend.get())), worldRenderer(std::make_unique(engine, frontend.get())), controller(std::make_unique(engine->getSettings(), level)) { @@ -96,6 +97,7 @@ LevelScreen::LevelScreen(Engine* engine, Level* level) animator.reset(new TextureAnimator()); animator->addAnimations(engine->getAssets()->getAnimations()); + scripting::on_frontend_init(hud.get()); } LevelScreen::~LevelScreen() { diff --git a/src/frontend/screens.h b/src/frontend/screens.h index 631b0669..464b7489 100644 --- a/src/frontend/screens.h +++ b/src/frontend/screens.h @@ -7,7 +7,7 @@ class Assets; class Level; class WorldRenderer; -class HudRenderer; +class Hud; class Engine; class Camera; class Batch2D; @@ -40,7 +40,7 @@ public: class LevelScreen : public Screen { std::unique_ptr level; std::unique_ptr frontend; - std::unique_ptr hud; + std::unique_ptr hud; std::unique_ptr worldRenderer; std::unique_ptr controller; std::unique_ptr animator; diff --git a/src/items/Inventories.cpp b/src/items/Inventories.cpp index c072ff27..3bf3e706 100644 --- a/src/items/Inventories.cpp +++ b/src/items/Inventories.cpp @@ -33,6 +33,10 @@ void Inventories::store(std::shared_ptr inv) { map[inv->getId()] = inv; } +void Inventories::remove(int64_t id) { + map.erase(id); +} + std::shared_ptr Inventories::get(int64_t id) { auto found = map.find(id); if (found == map.end()) diff --git a/src/items/Inventories.h b/src/items/Inventories.h index 9ad30343..40e3f2ee 100644 --- a/src/items/Inventories.h +++ b/src/items/Inventories.h @@ -30,6 +30,9 @@ public: /* Store inventory */ void store(std::shared_ptr inv); + /* Remove inventory from map */ + void remove(int64_t id); + /* Get inventory by id (works with both real and virtual)*/ std::shared_ptr get(int64_t id); diff --git a/src/logic/scripting/api/libhud.cpp b/src/logic/scripting/api/libhud.cpp new file mode 100644 index 00000000..27513de7 --- /dev/null +++ b/src/logic/scripting/api/libhud.cpp @@ -0,0 +1,20 @@ +#include "libhud.h" + +#include + +#include "../scripting.h" +#include "../../../frontend/hud.h" + +namespace scripting { + extern Hud* hud; +} + +int l_hud_open_inventory(lua_State* L) { + scripting::hud->openInventory(); + return 0; +} + +int l_hud_close_inventory(lua_State* L) { + scripting::hud->closeInventory(); + return 0; +} \ No newline at end of file diff --git a/src/logic/scripting/api/libhud.h b/src/logic/scripting/api/libhud.h new file mode 100644 index 00000000..2ceddfc5 --- /dev/null +++ b/src/logic/scripting/api/libhud.h @@ -0,0 +1,15 @@ +#ifndef LOGIC_SCRIPTING_API_LIBHUD_H_ +#define LOGIC_SCRIPTING_API_LIBHUD_H_ + +#include + +extern int l_hud_open_inventory(lua_State* L); +extern int l_hud_close_inventory(lua_State* L); + +static const luaL_Reg hudlib [] = { + {"open_inventory", l_hud_open_inventory}, + {"close_inventory", l_hud_close_inventory}, + {NULL, NULL} +}; + +#endif // LOGIC_SCRIPTING_API_LIBHUD_H_ diff --git a/src/logic/scripting/scripting.h b/src/logic/scripting/scripting.h index 4d30c35f..39c85a75 100644 --- a/src/logic/scripting/scripting.h +++ b/src/logic/scripting/scripting.h @@ -7,8 +7,6 @@ namespace fs = std::filesystem; -class LuaState; - class Engine; class Content; struct ContentPack; diff --git a/src/logic/scripting/scripting_frontend.cpp b/src/logic/scripting/scripting_frontend.cpp new file mode 100644 index 00000000..66da8136 --- /dev/null +++ b/src/logic/scripting/scripting_frontend.cpp @@ -0,0 +1,16 @@ +#include "scripting_frontend.h" +#include "scripting.h" + +#include "api/libhud.h" +#include "LuaState.h" + +namespace scripting { + extern lua::LuaState* state; +} + +Hud* scripting::hud = nullptr; + +void scripting::on_frontend_init(Hud* hud) { + scripting::hud = hud; + scripting::state->openlib("hud", hudlib, 0); +} diff --git a/src/logic/scripting/scripting_frontend.h b/src/logic/scripting/scripting_frontend.h new file mode 100644 index 00000000..d6e8a2ac --- /dev/null +++ b/src/logic/scripting/scripting_frontend.h @@ -0,0 +1,12 @@ +#ifndef LOGIC_SCRIPTING_SCRIPTING_FRONTEND_H_ +#define LOGIC_SCRIPTING_SCRIPTING_FRONTEND_H_ + +class Hud; + +namespace scripting { + extern Hud* hud; + + void on_frontend_init(Hud* hud); +} + +#endif // LOGIC_SCRIPTING_SCRIPTING_FRONTEND_H_