diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua new file mode 100644 index 00000000..35927573 --- /dev/null +++ b/res/scripts/stdlib.lua @@ -0,0 +1,51 @@ +-- kit of standard functions + +-- Check if given table is an array +function is_array(x) + if #t > 0 then + return true + end + for k, v in pairs(x) do + return false + end + return true +end + +local __cached_scripts = {} +local __cached_results = {} + +-- Get entry-point and filename from `entry-point:filename` path +function parse_path(path) + local index = string.find(path, ':') + if index == nil then + error("invalid path syntax (':' missing)") + end + return string.sub(path, 1, index-1), string.sub(path, index+1, -1) +end + +-- Load script with caching +-- +-- path - script path `contentpack:filename`. +-- Example `base:scripts/tests.lua` +-- +-- nocache - ignore cached script, load anyway +function load_script(path, nocache) + local packname, filename = parse_path(path) + local packpath = pack.get_folder(packname) + local fullpath = packpath..filename + + -- __cached_scripts used in condition because cached result may be nil + if not nocache and __cached_scripts[fullpath] ~= nil then + return __cached_results[fullpath] + end + local script = loadfile(fullpath) + if script == nil then + error("script '"..filename.."' not found in '"..packname.."'") + end + local result = script() + if not nocache then + __cached_scripts[fullpath] = script + __cached_results[fullpath] = result + end + return result +end diff --git a/src/constants.h b/src/constants.h index dd5e56e0..f9cc1d4b 100644 --- a/src/constants.h +++ b/src/constants.h @@ -17,6 +17,8 @@ const int CHUNK_D = 16; const uint VOXEL_USER_BITS = 8; constexpr uint VOXEL_USER_BITS_OFFSET = sizeof(blockstate_t)*8-VOXEL_USER_BITS; +const int ITEM_ICON_SIZE = 48; + /* Chunk volume (count of voxels per Chunk) */ constexpr int CHUNK_VOL = (CHUNK_W * CHUNK_H * CHUNK_D); diff --git a/src/files/WorldFiles.cpp b/src/files/WorldFiles.cpp index 6fd51b84..f9db0c02 100644 --- a/src/files/WorldFiles.cpp +++ b/src/files/WorldFiles.cpp @@ -17,6 +17,7 @@ #include "../coders/json.h" #include "../constants.h" #include "../items/ItemDef.h" +#include "../items/Inventory.h" #include "../data/dynamic.h" @@ -488,12 +489,13 @@ void WorldFiles::writeWorldInfo(const World* world) { versionobj.put("major", ENGINE_VERSION_MAJOR); versionobj.put("minor", ENGINE_VERSION_MINOR); - root.put("name", world->name); - root.put("seed", world->seed); + root.put("name", world->getName()); + root.put("seed", world->getSeed()); auto& timeobj = root.putMap("time"); timeobj.put("day-time", world->daytime); timeobj.put("day-time-speed", world->daytimeSpeed); + timeobj.put("total-time", world->totalTime); files::write_json(getWorldFile(), &root); } @@ -506,8 +508,9 @@ bool WorldFiles::readWorldInfo(World* world) { } auto root = files::read_json(file); - root->str("name", world->name); - root->num("seed", world->seed); + + world->setName(root->getStr("name", world->getName())); + world->setSeed(root->getInt("seed", world->getSeed())); auto verobj = root->map("version"); if (verobj) { @@ -521,12 +524,13 @@ bool WorldFiles::readWorldInfo(World* world) { if (timeobj) { timeobj->num("day-time", world->daytime); timeobj->num("day-time-speed", world->daytimeSpeed); + timeobj->num("total-time", world->totalTime); } return true; } -void WorldFiles::writePlayer(Player* player){ +void WorldFiles::writePlayer(Player* player) { glm::vec3 position = player->hitbox->position; dynamic::Map root; auto& posarr = root.putList("position"); @@ -540,6 +544,8 @@ void WorldFiles::writePlayer(Player* player){ root.put("flight", player->flight); root.put("noclip", player->noclip); + root.put("chosen-slot", player->getChosenSlot()); + root.put("inventory", player->getInventory()->write().release()); files::write_json(getPlayerFile(), &root); } @@ -565,5 +571,11 @@ bool WorldFiles::readPlayer(Player* player) { root->flag("flight", player->flight); root->flag("noclip", player->noclip); + player->setChosenSlot(root->getInt("chosen-slot", player->getChosenSlot())); + + auto invmap = root->map("inventory"); + if (invmap) { + player->getInventory()->read(invmap); + } return true; } diff --git a/src/files/files.cpp b/src/files/files.cpp index 8f459dcc..55ca345f 100644 --- a/src/files/files.cpp +++ b/src/files/files.cpp @@ -6,6 +6,7 @@ #include #include #include "../coders/json.h" +#include "../coders/gzip.h" #include "../util/stringutil.h" #include "../data/dynamic.h" @@ -32,21 +33,21 @@ void files::rafile::read(char* buffer, std::streamsize size) { file.read(buffer, size); } -bool files::write_bytes(fs::path filename, const char* data, size_t size) { +bool files::write_bytes(fs::path filename, const ubyte* data, size_t size) { std::ofstream output(filename, std::ios::binary); if (!output.is_open()) return false; - output.write(data, size); + output.write((const char*)data, size); output.close(); return true; } -uint files::append_bytes(fs::path filename, const char* data, size_t size) { +uint files::append_bytes(fs::path filename, const ubyte* data, size_t size) { std::ofstream output(filename, std::ios::binary | std::ios::app); if (!output.is_open()) return 0; uint position = output.tellp(); - output.write(data, size); + output.write((const char*)data, size); output.close(); return position; } @@ -60,7 +61,7 @@ bool files::read(fs::path filename, char* data, size_t size) { return true; } -char* files::read_bytes(fs::path filename, size_t& length) { +ubyte* files::read_bytes(fs::path filename, size_t& length) { std::ifstream input(filename, std::ios::binary); if (!input.is_open()) return nullptr; @@ -71,17 +72,17 @@ char* files::read_bytes(fs::path filename, size_t& length) { std::unique_ptr data(new char[length]); input.read(data.get(), length); input.close(); - return data.release(); + return (ubyte*)data.release(); } std::string files::read_string(fs::path filename) { size_t size; - std::unique_ptr chars (read_bytes(filename, size)); - if (chars == nullptr) { + std::unique_ptr bytes (read_bytes(filename, size)); + if (bytes == nullptr) { throw std::runtime_error("could not to load file '"+ filename.string()+"'"); } - return std::string(chars.get(), size); + return std::string((const char*)bytes.get(), size); } bool files::write_string(fs::path filename, const std::string content) { @@ -94,27 +95,21 @@ bool files::write_string(fs::path filename, const std::string content) { } bool files::write_json(fs::path filename, const dynamic::Map* obj, bool nice) { - // -- binary json tests - //return write_binary_json(fs::path(filename.u8string()+".bin"), obj); return files::write_string(filename, json::stringify(obj, nice, " ")); } -bool files::write_binary_json(fs::path filename, const dynamic::Map* obj) { - std::vector bytes = json::to_binary(obj); - return files::write_bytes(filename, (const char*)bytes.data(), bytes.size()); +bool files::write_binary_json(fs::path filename, const dynamic::Map* obj, bool compression) { + auto bytes = json::to_binary(obj); + if (compression) { + bytes = gzip::compress(bytes.data(), bytes.size()); + } + return files::write_bytes(filename, bytes.data(), bytes.size()); } std::unique_ptr files::read_json(fs::path filename) { - // binary json tests - // fs::path binfile = fs::path(filename.u8string()+".bin"); - // if (fs::is_regular_file(binfile)){ - // return read_binary_json(binfile); - // } - std::string text = files::read_string(filename); try { auto obj = json::parse(filename.string(), text); - //write_binary_json(binfile, obj); return obj; } catch (const parsing_error& error) { std::cerr << error.errorLog() << std::endl; @@ -124,8 +119,10 @@ std::unique_ptr files::read_json(fs::path filename) { std::unique_ptr files::read_binary_json(fs::path file) { size_t size; - std::unique_ptr bytes (files::read_bytes(file, size)); - return std::unique_ptr(json::from_binary((const ubyte*)bytes.get(), size)); + std::unique_ptr bytes (files::read_bytes(file, size)); + return std::unique_ptr( + json::from_binary(bytes.get(), size) + ); } std::vector files::read_list(fs::path filename) { diff --git a/src/files/files.h b/src/files/files.h index 4e136fa6..f7515712 100644 --- a/src/files/files.h +++ b/src/files/files.h @@ -27,15 +27,33 @@ namespace files { size_t length() const; }; + /* Write bytes array to the file without any extra data */ + extern bool write_bytes(fs::path, const ubyte* data, size_t size); - extern bool write_bytes(fs::path, const char* data, size_t size); - extern uint append_bytes(fs::path, const char* data, size_t size); + /* Append bytes array to the file without any extra data */ + extern uint append_bytes(fs::path, const ubyte* data, size_t size); + + /* Write string to the file */ extern bool write_string(fs::path filename, const std::string content); - extern bool write_json(fs::path filename, const dynamic::Map* obj, bool nice=true); - extern bool write_binary_json(fs::path filename, const dynamic::Map* obj); + + /* Write dynamic data to the JSON file + @param nice if true, + human readable format will be used, otherwise minimal */ + extern bool write_json( + fs::path filename, + const dynamic::Map* obj, + bool nice=true); + + /* Write dynamic data to the binary JSON file + (see src/coders/binary_json_spec.md) + @param compressed use gzip compression */ + extern bool write_binary_json( + fs::path filename, + const dynamic::Map* obj, + bool compressed=false); extern bool read(fs::path, char* data, size_t size); - extern char* read_bytes(fs::path, size_t& length); + extern ubyte* read_bytes(fs::path, size_t& length); extern std::string read_string(fs::path filename); extern std::unique_ptr read_json(fs::path file); extern std::unique_ptr read_binary_json(fs::path file); diff --git a/src/frontend/BlocksPreview.cpp b/src/frontend/BlocksPreview.cpp index 846afc4a..b400527e 100644 --- a/src/frontend/BlocksPreview.cpp +++ b/src/frontend/BlocksPreview.cpp @@ -8,47 +8,23 @@ #include "../graphics/Texture.h" #include "../graphics/Atlas.h" #include "../graphics/Batch3D.h" +#include "../graphics/Framebuffer.h" +#include "../graphics/GfxContext.h" +#include "../window/Window.h" #include "../window/Camera.h" #include "../voxels/Block.h" +#include "../content/Content.h" +#include "../constants.h" #include "ContentGfxCache.h" -BlocksPreview::BlocksPreview(Assets* assets, const ContentGfxCache* cache) - : shader(assets->getShader("ui3d")), - atlas(assets->getAtlas("blocks")), - cache(cache) { - batch = std::make_unique(1024); -} - -BlocksPreview::~BlocksPreview() { -} - -void BlocksPreview::begin(const Viewport* viewport) { - this->viewport = viewport; - shader->use(); - shader->uniformMatrix("u_projview", - glm::ortho(0.0f, float(viewport->getWidth()), - 0.0f, float(viewport->getHeight()), - -100.0f, 100.0f) * - glm::lookAt(glm::vec3(2, 2, 2), glm::vec3(0.0f), glm::vec3(0, 1, 0))); - atlas->getTexture()->bind(); -} - -/* Draw one block preview at given screen position */ -void BlocksPreview::draw(const Block* def, int x, int y, int size, glm::vec4 tint) { - uint width = viewport->getWidth(); - uint height = viewport->getHeight(); - - y = height - y - 1 - 35 /* magic garbage */; - x += 2; - - if (def->model == BlockModel::aabb) { - x += (1.0f - def->hitbox.size()).x * size * 0.5f; - y += (1.0f - def->hitbox.size()).y * size * 0.25f; - } - - glm::vec3 offset (x/float(width) * 2, y/float(height) * 2, 0.0f); - shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset)); - +ImageData* BlocksPreview::draw( + const ContentGfxCache* cache, + Framebuffer* fbo, + Batch3D* batch, + const Block* def, + int size +){ + Window::clear(); blockid_t id = def->rt.id; const UVRegion texfaces[6]{cache->getRegion(id, 0), cache->getRegion(id, 1), cache->getRegion(id, 2), cache->getRegion(id, 3), @@ -59,11 +35,12 @@ void BlocksPreview::draw(const Block* def, int x, int y, int size, glm::vec4 tin // something went wrong... break; case BlockModel::block: - batch->blockCube(glm::vec3(size * 0.63f), texfaces, tint, !def->rt.emissive); + batch->blockCube(glm::vec3(size * 0.63f), texfaces, + glm::vec4(1.0f), !def->rt.emissive); break; case BlockModel::aabb: batch->blockCube(def->hitbox.size() * glm::vec3(size * 0.63f), - texfaces, tint, !def->rt.emissive); + texfaces, glm::vec4(1.0f), !def->rt.emissive); break; case BlockModel::custom: case BlockModel::xsprite: { @@ -73,10 +50,64 @@ void BlocksPreview::draw(const Block* def, int x, int y, int size, glm::vec4 tin right, size*0.5f, size*0.6f, texfaces[0], - tint); + glm::vec4(1.0f)); break; } } - batch->flush(); + return fbo->texture->readData(); +} + +std::unique_ptr BlocksPreview::build( + const ContentGfxCache* cache, + Assets* assets, + const Content* content +) { + auto indices = content->getIndices(); + size_t count = indices->countBlockDefs(); + size_t iconSize = ITEM_ICON_SIZE; + + Shader* shader = assets->getShader("ui3d"); + Atlas* atlas = assets->getAtlas("blocks"); + + Viewport viewport(iconSize, iconSize); + GfxContext pctx(nullptr, viewport, nullptr); + GfxContext ctx = pctx.sub(); + ctx.cullFace(true); + ctx.depthTest(true); + + Framebuffer fbo(iconSize, iconSize, true); + Batch3D batch(1024); + batch.begin(); + + shader->use(); + shader->uniformMatrix("u_projview", + + glm::ortho(0.0f, float(iconSize), 0.0f, float(iconSize), + -100.0f, 100.0f) * + glm::lookAt(glm::vec3(2, 2, 2), + glm::vec3(0.0f), + glm::vec3(0, 1, 0))); + + AtlasBuilder builder; + Window::viewport(0, 0, iconSize, iconSize); + Window::setBgColor(glm::vec4(0.0f)); + + fbo.bind(); + for (size_t i = 0; i < count; i++) { + auto def = indices->getBlockDef(i); + + glm::vec3 offset(0.1f, 0.5f, 0.1f); + if (def->model == BlockModel::aabb) { + offset.y += (1.0f - def->hitbox.size()).y * 0.5f; + } + atlas->getTexture()->bind(); + shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset)); + + builder.add(def->name, draw(cache, &fbo, &batch, def, iconSize)); + } + fbo.unbind(); + + Window::viewport(0, 0, Window::width, Window::height); + return std::unique_ptr(builder.build(2)); } diff --git a/src/frontend/BlocksPreview.h b/src/frontend/BlocksPreview.h index 0a1a03f3..5c4ab4c1 100644 --- a/src/frontend/BlocksPreview.h +++ b/src/frontend/BlocksPreview.h @@ -6,25 +6,27 @@ #include class Assets; -class Viewport; -class Shader; +class ImageData; class Atlas; +class Framebuffer; class Batch3D; class Block; +class Content; class ContentGfxCache; class BlocksPreview { - Shader* shader; - Atlas* atlas; - std::unique_ptr batch; - const ContentGfxCache* const cache; - const Viewport* viewport; public: - BlocksPreview(Assets* assets, const ContentGfxCache* cache); - ~BlocksPreview(); + static ImageData* draw( + const ContentGfxCache* cache, + Framebuffer* framebuffer, + Batch3D* batch, + const Block* block, + int size); - void begin(const Viewport* viewport); - void draw(const Block* block, int x, int y, int size, glm::vec4 tint); + static std::unique_ptr build( + const ContentGfxCache* cache, + Assets* assets, + const Content* content); }; #endif // FRONTEND_BLOCKS_PREVIEW_H_ diff --git a/src/frontend/InventoryView.cpp b/src/frontend/InventoryView.cpp index 723af338..a09d64c1 100644 --- a/src/frontend/InventoryView.cpp +++ b/src/frontend/InventoryView.cpp @@ -28,6 +28,10 @@ void InventoryLayout::add(SlotLayout slot) { slots.push_back(slot); } +void InventoryLayout::add(InventoryPanel panel) { + panels.push_back(panel); +} + void InventoryLayout::setSize(glm::vec2 size) { this->size = size; } @@ -48,6 +52,10 @@ std::vector& InventoryLayout::getSlots() { return slots; } +std::vector& InventoryLayout::getPanels() { + return panels; +} + SlotLayout::SlotLayout( glm::vec2 position, bool background, @@ -72,14 +80,17 @@ InventoryBuilder::InventoryBuilder() {} void InventoryBuilder::addGrid( - int cols, int rows, + int cols, int count, glm::vec2 coord, - int padding, + int padding, + bool addpanel, SlotLayout slotLayout) { const int slotSize = InventoryView::SLOT_SIZE; const int interval = InventoryView::SLOT_INTERVAL; + int rows = ceildiv(count, cols); + uint width = cols * (slotSize + interval) - interval + padding*2; uint height = rows * (slotSize + interval) - interval + padding*2; @@ -94,6 +105,8 @@ void InventoryBuilder::addGrid( for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { + if (row * cols + col >= count) + break; glm::vec2 position ( col * (slotSize + interval) + padding, row * (slotSize + interval) + padding @@ -103,6 +116,32 @@ void InventoryBuilder::addGrid( layout->add(builtSlot); } } + + if (addpanel) { + add(InventoryPanel( + coord, + glm::vec2(width, height), + glm::vec4(0, 0, 0, 0.5f))); + } +} + +void InventoryBuilder::add(SlotLayout slotLayout) { + uint width = InventoryView::SLOT_SIZE; + uint height = InventoryView::SLOT_SIZE; + + auto coord = slotLayout.position; + auto lsize = layout->getSize(); + if (coord.x + width > lsize.x) { + lsize.x = coord.x + width; + } + if (coord.y + height > lsize.y) { + lsize.y = coord.y + height; + } + layout->add(slotLayout); +} + +void InventoryBuilder::add(InventoryPanel panel) { + layout->add(panel); } std::unique_ptr InventoryBuilder::build() { @@ -149,31 +188,23 @@ void SlotView::draw(Batch2D* batch, Assets* assets) { batch->color = glm::vec4(1.0f); - Shader* uiShader = assets->getShader("ui"); - Viewport viewport(Window::width, Window::height); - GfxContext ctx(nullptr, viewport, batch); - - auto preview = frontend->getBlocksPreview(); + auto previews = frontend->getBlocksAtlas(); auto indices = content->getIndices(); - ItemDef* item = indices->getItemDef(stack.getItemId()); + ItemDef* item = indices->getItemDef(stack.getItemId()); switch (item->iconType) { case item_icon_type::none: break; - case item_icon_type::block: - batch->render(); - { - GfxContext subctx = ctx.sub(); - subctx.depthTest(true); - subctx.cullFace(true); + case item_icon_type::block: { + Block* cblock = content->requireBlock(item->icon); + batch->texture(previews->getTexture()); - Block* cblock = content->requireBlock(item->icon); - preview->begin(&subctx.getViewport()); - preview->draw(cblock, coord.x, coord.y, slotSize, tint); - } - uiShader->use(); - batch->begin(); + UVRegion region = previews->get(cblock->name); + batch->rect( + coord.x, coord.y, slotSize, slotSize, + 0, 0, 0, region, false, true, tint); break; + } case item_icon_type::sprite: { size_t index = item->icon.find(':'); std::string name = item->icon.substr(index+1); @@ -279,14 +310,17 @@ InventoryView::InventoryView( frontend(frontend), interaction(interaction) { size(this->layout->getSize()); - color(glm::vec4(0, 0, 0, 0.5f)); + color(glm::vec4(0, 0, 0, 0.0f)); } InventoryView::~InventoryView() {} void InventoryView::build() { - int index = 0; + size_t index = 0; for (auto& slot : layout->getSlots()) { + if (index >= inventory->size()) + break; + ItemStack& item = inventory->getSlot(index); auto view = std::make_shared( @@ -320,15 +354,15 @@ InventoryLayout* InventoryView::getLayout() const { return layout.get(); } -// performance disaster x2 -void InventoryView::draw(Batch2D* batch, Assets* assets) { - Container::draw(batch, assets); - Window::clearDepth(); -} - void InventoryView::drawBackground(Batch2D* batch, Assets* assets) { glm::vec2 coord = calcCoord(); + batch->texture(nullptr); - batch->color = color_; - batch->rect(coord.x-1, coord.y-1, size_.x+2, size_.y+2); + + for (auto& panel : layout->getPanels()) { + glm::vec2 size = panel.size; + glm::vec2 pos = coord + panel.position; + batch->color = panel.color; + batch->rect(pos.x-1, pos.y-1, size.x+2, size.y+2); + } } diff --git a/src/frontend/InventoryView.h b/src/frontend/InventoryView.h index 1115428e..cb31da01 100644 --- a/src/frontend/InventoryView.h +++ b/src/frontend/InventoryView.h @@ -53,10 +53,12 @@ class InventoryLayout { glm::vec2 size; glm::vec2 origin; std::vector slots; + std::vector panels; public: InventoryLayout(glm::vec2 size); void add(SlotLayout slot); + void add(InventoryPanel panel); void setSize(glm::vec2 size); void setOrigin(glm::vec2 origin); @@ -64,6 +66,7 @@ public: glm::vec2 getOrigin() const; std::vector& getSlots(); + std::vector& getPanels(); }; class InventoryBuilder { @@ -72,10 +75,15 @@ public: InventoryBuilder(); void addGrid( - int cols, int rows, + int cols, int count, glm::vec2 coord, - int padding, + int padding, + bool addpanel, SlotLayout slotLayout); + + void add(SlotLayout slotLayout); + void add(InventoryPanel panel); + std::unique_ptr build(); }; @@ -126,7 +134,6 @@ public: void build(); - virtual void draw(Batch2D* batch, Assets* assets) override; virtual void drawBackground(Batch2D* batch, Assets* assets) override; void setInventory(std::shared_ptr inventory); @@ -138,7 +145,7 @@ public: void setSelected(int index); static const int SLOT_INTERVAL = 4; - static const int SLOT_SIZE = 48; + static const int SLOT_SIZE = ITEM_ICON_SIZE; }; class InventoryInteraction { diff --git a/src/frontend/LevelFrontend.cpp b/src/frontend/LevelFrontend.cpp index 4b1c6542..9561dfb2 100644 --- a/src/frontend/LevelFrontend.cpp +++ b/src/frontend/LevelFrontend.cpp @@ -2,6 +2,7 @@ #include "../world/Level.h" #include "../assets/Assets.h" +#include "../graphics/Atlas.h" #include "BlocksPreview.h" #include "ContentGfxCache.h" @@ -9,8 +10,7 @@ LevelFrontend::LevelFrontend(Level* level, Assets* assets) : level(level), assets(assets), contentCache(std::make_unique(level->content, assets)), - blocksPreview(std::make_unique(assets, contentCache.get())) { - + blocksAtlas(BlocksPreview::build(contentCache.get(), assets, level->content)) { } LevelFrontend::~LevelFrontend() { @@ -24,10 +24,10 @@ Assets* LevelFrontend::getAssets() const { return assets; } -BlocksPreview* LevelFrontend::getBlocksPreview() const { - return blocksPreview.get(); -} - ContentGfxCache* LevelFrontend::getContentGfxCache() const { return contentCache.get(); } + +Atlas* LevelFrontend::getBlocksAtlas() const { + return blocksAtlas.get(); +} diff --git a/src/frontend/LevelFrontend.h b/src/frontend/LevelFrontend.h index 095f5535..98a8a111 100644 --- a/src/frontend/LevelFrontend.h +++ b/src/frontend/LevelFrontend.h @@ -3,6 +3,7 @@ #include +class Atlas; class Level; class Assets; class BlocksPreview; @@ -12,15 +13,15 @@ class LevelFrontend { Level* level; Assets* assets; std::unique_ptr contentCache; - std::unique_ptr blocksPreview; + std::unique_ptr blocksAtlas; public: LevelFrontend(Level* level, Assets* assets); ~LevelFrontend(); Level* getLevel() const; Assets* getAssets() const; - BlocksPreview* getBlocksPreview() const; ContentGfxCache* getContentGfxCache() const; + Atlas* getBlocksAtlas() const; }; diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 8a4c3a0c..66a5ea6b 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -52,106 +52,106 @@ using glm::vec4; using namespace gui; inline std::shared_ptr