From a57fba4fa4bc303c63ec41f0ff8fc06fb7db710f Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 30 Jan 2024 22:47:51 +0300 Subject: [PATCH 001/115] inventory slots fix --- src/frontend/InventoryView.cpp | 4 ++++ src/frontend/InventoryView.h | 1 + 2 files changed, 5 insertions(+) diff --git a/src/frontend/InventoryView.cpp b/src/frontend/InventoryView.cpp index a09d64c1..c7488958 100644 --- a/src/frontend/InventoryView.cpp +++ b/src/frontend/InventoryView.cpp @@ -296,6 +296,10 @@ void SlotView::clicked(gui::GUI* gui, int button) { } } +void SlotView::focus(gui::GUI* gui) { + clicked(gui, 0); +} + InventoryView::InventoryView( const Content* content, LevelFrontend* frontend, diff --git a/src/frontend/InventoryView.h b/src/frontend/InventoryView.h index 6191d8c8..3f85d187 100644 --- a/src/frontend/InventoryView.h +++ b/src/frontend/InventoryView.h @@ -108,6 +108,7 @@ public: bool isHighlighted() const; virtual void clicked(gui::GUI*, int) override; + virtual void focus(gui::GUI*) override; }; class InventoryView : public gui::Container { From 49fdcdfb273ccb95c18499a056959c1a2d0d9796 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 31 Jan 2024 00:14:43 +0300 Subject: [PATCH 002/115] inventory regions, minor refactor --- res/content/base/package.json | 2 +- src/coders/binary_json.cpp | 6 ++- src/coders/binary_json.h | 2 +- src/coders/byte_utils.cpp | 12 ++--- src/constants.h | 4 +- src/content/ContentLoader.cpp | 1 + src/files/WorldFiles.cpp | 88 ++++++++++++++++++---------------- src/files/WorldFiles.h | 12 +++-- src/files/files.cpp | 5 +- src/frontend/hud.cpp | 2 +- src/frontend/menu.cpp | 14 ++++-- src/items/Inventory.cpp | 5 +- src/items/Inventory.h | 8 +++- src/lighting/LightSolver.cpp | 14 +++--- src/lighting/Lighting.cpp | 18 +++---- src/lighting/Lightmap.cpp | 22 ++------- src/lighting/Lightmap.h | 19 ++++---- src/logic/BlocksController.cpp | 2 + src/logic/BlocksController.h | 1 + src/objects/Player.cpp | 2 +- src/voxels/Block.h | 1 + src/voxels/Chunk.cpp | 52 +++++++++++--------- src/voxels/Chunk.h | 30 ++++++++++-- src/voxels/Chunks.cpp | 4 +- src/voxels/ChunksStorage.cpp | 6 +-- src/world/Level.cpp | 4 +- src/world/Level.h | 1 + src/world/World.cpp | 68 +++++++++++++++++++++----- src/world/World.h | 14 +++++- 29 files changed, 259 insertions(+), 160 deletions(-) diff --git a/res/content/base/package.json b/res/content/base/package.json index bd8c1c2a..249dd4ee 100644 --- a/res/content/base/package.json +++ b/res/content/base/package.json @@ -1,6 +1,6 @@ { "id": "base", "title": "Base", - "version": "0.18", + "version": "0.19", "description": "basic content package" } diff --git a/src/coders/binary_json.cpp b/src/coders/binary_json.cpp index c296dc16..04d91dfa 100644 --- a/src/coders/binary_json.cpp +++ b/src/coders/binary_json.cpp @@ -56,7 +56,11 @@ static void to_binary(ByteBuilder& builder, const Value* value) { static List* array_from_binary(ByteReader& reader); static Map* object_from_binary(ByteReader& reader); -std::vector json::to_binary(const Map* obj) { +std::vector json::to_binary(const Map* obj, bool compress) { + if (compress) { + auto bytes = to_binary(obj, false); + return gzip::compress(bytes.data(), bytes.size()); + } ByteBuilder builder; // type byte builder.put(BJSON_TYPE_DOCUMENT); diff --git a/src/coders/binary_json.h b/src/coders/binary_json.h index 018f6573..913e71ec 100644 --- a/src/coders/binary_json.h +++ b/src/coders/binary_json.h @@ -21,7 +21,7 @@ namespace json { const int BJSON_TYPE_NULL = 0xC; const int BJSON_TYPE_CDOCUMENT = 0x1F; - extern std::vector to_binary(const dynamic::Map* obj); + extern std::vector to_binary(const dynamic::Map* obj, bool compress=false); extern std::unique_ptr from_binary(const ubyte* src, size_t size); } diff --git a/src/coders/byte_utils.cpp b/src/coders/byte_utils.cpp index eaead0dc..5b9876a7 100644 --- a/src/coders/byte_utils.cpp +++ b/src/coders/byte_utils.cpp @@ -121,21 +121,21 @@ void ByteReader::checkMagic(const char* data, size_t size) { ubyte ByteReader::get() { if (pos == size) { - throw std::underflow_error("buffer underflow"); + throw std::runtime_error("buffer underflow"); } return data[pos++]; } ubyte ByteReader::peek() { if (pos == size) { - throw std::underflow_error("buffer underflow"); + throw std::runtime_error("buffer underflow"); } return data[pos]; } int16_t ByteReader::getInt16() { if (pos+2 > size) { - throw std::underflow_error("unexpected end"); + throw std::runtime_error("buffer underflow"); } pos += 2; return (static_cast(data[pos - 1]) << 8) | @@ -144,7 +144,7 @@ int16_t ByteReader::getInt16() { int32_t ByteReader::getInt32() { if (pos+4 > size) { - throw std::underflow_error("unexpected end"); + throw std::runtime_error("buffer underflow"); } pos += 4; return (static_cast(data[pos - 1]) << 24) | @@ -155,7 +155,7 @@ int32_t ByteReader::getInt32() { int64_t ByteReader::getInt64() { if (pos+8 > size) { - throw std::underflow_error("unexpected end"); + throw std::runtime_error("buffer underflow"); } pos += 8; return (static_cast(data[pos - 1]) << 56) | @@ -191,7 +191,7 @@ const char* ByteReader::getCString() { std::string ByteReader::getString() { uint32_t length = (uint32_t)getInt32(); if (pos+length > size) { - throw std::underflow_error("unexpected end"); + throw std::runtime_error("buffer underflow"); } pos += length; return std::string(reinterpret_cast(data+pos-length), length); diff --git a/src/constants.h b/src/constants.h index c67a5f7c..05cc1a21 100644 --- a/src/constants.h +++ b/src/constants.h @@ -5,7 +5,7 @@ #include "typedefs.h" const int ENGINE_VERSION_MAJOR = 0; -const int ENGINE_VERSION_MINOR = 18; +const int ENGINE_VERSION_MINOR = 19; const int BLOCK_AIR = 0; const int ITEM_EMPTY = 0; @@ -28,7 +28,7 @@ const itemid_t ITEM_VOID = std::numeric_limits::max(); const blockid_t MAX_BLOCKS = BLOCK_VOID; -inline uint vox_index(int x, int y, int z, int w=CHUNK_W, int d=CHUNK_D) { +constexpr uint vox_index(uint x, uint y, uint z, uint w=CHUNK_W, uint d=CHUNK_D) { return (y * d + z) * w + x; } diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 75af2fcd..6cec4a36 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -173,6 +173,7 @@ void ContentLoader::loadBlock(Block* def, std::string name, fs::path file) { root->num("draw-group", def->drawGroup); root->str("picking-item", def->pickingItem); root->str("script-name", def->scriptName); + root->num("inventory-size", def->inventorySize); } void ContentLoader::loadCustomBlockModel(Block* def, dynamic::Map* primitives) { diff --git a/src/files/WorldFiles.cpp b/src/files/WorldFiles.cpp index 6616d54d..6b011909 100644 --- a/src/files/WorldFiles.cpp +++ b/src/files/WorldFiles.cpp @@ -13,6 +13,7 @@ #include "../world/World.h" #include "../lighting/Lightmap.h" +#include "../coders/byte_utils.h" #include "../util/data_io.h" #include "../coders/json.h" #include "../constants.h" @@ -189,7 +190,7 @@ void WorldFiles::put(Chunk* chunk){ int localX = chunk->x - (regionX * REGION_SIZE); int localZ = chunk->z - (regionZ * REGION_SIZE); - /* Writing Voxels */ { + /* Writing voxels */ { size_t compressedSize; std::unique_ptr chunk_data (chunk->encode()); ubyte* data = compress(chunk_data.get(), CHUNK_DATA_LEN, compressedSize); @@ -198,15 +199,39 @@ void WorldFiles::put(Chunk* chunk){ region->setUnsaved(true); region->put(localX, localZ, data, compressedSize); } + /* Writing lights cache */ if (doWriteLights && chunk->isLighted()) { size_t compressedSize; - std::unique_ptr light_data (chunk->lightmap->encode()); + std::unique_ptr light_data (chunk->lightmap.encode()); ubyte* data = compress(light_data.get(), LIGHTMAP_DATA_LEN, compressedSize); WorldRegion* region = getOrCreateRegion(lights, regionX, regionZ); region->setUnsaved(true); region->put(localX, localZ, data, compressedSize); } + /* Writing block inventories */ + if (!chunk->inventories.empty()){ + auto& inventories = chunk->inventories; + ByteBuilder builder; + builder.putInt32(inventories.size()); + for (auto& entry : inventories) { + builder.putInt32(entry.first); + auto map = entry.second->serialize(); + auto bytes = json::to_binary(map.get(), true); + builder.putInt32(bytes.size()); + builder.put(bytes.data(), bytes.size()); + } + WorldRegion* region = getOrCreateRegion(storages, regionX, regionZ); + region->setUnsaved(true); + + auto datavec = builder.data(); + uint datasize = builder.size(); + auto data = std::make_unique(builder.size()); + for (uint i = 0; i < builder.size(); i++) { + data[i] = datavec[i]; + } + region->put(localX, localZ, data.release(), datasize); + } } fs::path WorldFiles::getRegionsFolder() const { @@ -217,6 +242,10 @@ fs::path WorldFiles::getLightsFolder() const { return directory/fs::path("lights"); } +fs::path WorldFiles::getInventoriesFolder() const { + return directory/fs::path("inventories"); +} + fs::path WorldFiles::getRegionFilename(int x, int z) const { return fs::path(std::to_string(x) + "_" + std::to_string(z) + ".bin"); } @@ -436,20 +465,24 @@ void WorldFiles::writeRegions(regionsmap& regions, const fs::path& folder, int l void WorldFiles::write(const World* world, const Content* content) { fs::path regionsFolder = getRegionsFolder(); fs::path lightsFolder = getLightsFolder(); + fs::path inventoriesFolder = getInventoriesFolder(); fs::create_directories(regionsFolder); + fs::create_directories(inventoriesFolder); fs::create_directories(lightsFolder); if (world) { writeWorldInfo(world); writePacks(world); } - if (generatorTestMode) + if (generatorTestMode) { return; + } writeIndices(content->getIndices()); writeRegions(regions, regionsFolder, REGION_LAYER_VOXELS); writeRegions(lights, lightsFolder, REGION_LAYER_LIGHTS); + writeRegions(storages, inventoriesFolder, REGION_LAYER_STORAGES); } void WorldFiles::writePacks(const World* world) { @@ -488,21 +521,7 @@ void WorldFiles::writeIndices(const ContentIndices* indices) { } void WorldFiles::writeWorldInfo(const World* world) { - dynamic::Map root; - - auto& versionobj = root.putMap("version"); - versionobj.put("major", ENGINE_VERSION_MAJOR); - versionobj.put("minor", ENGINE_VERSION_MINOR); - - 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); + files::write_json(getWorldFile(), world->serialize().get()); } bool WorldFiles::readWorldInfo(World* world) { @@ -513,25 +532,7 @@ bool WorldFiles::readWorldInfo(World* world) { } auto root = files::read_json(file); - - world->setName(root->getStr("name", world->getName())); - world->setSeed(root->getInt("seed", world->getSeed())); - - auto verobj = root->map("version"); - if (verobj) { - int major=0, minor=-1; - verobj->num("major", major); - verobj->num("minor", minor); - std::cout << "world version: " << major << "." << minor << std::endl; - } - - auto timeobj = root->map("time"); - if (timeobj) { - timeobj->num("day-time", world->daytime); - timeobj->num("day-time-speed", world->daytimeSpeed); - timeobj->num("total-time", world->totalTime); - } - + world->deserialize(root.get()); return true; } @@ -550,8 +551,15 @@ bool WorldFiles::readPlayer(Player* player) { return true; } -void WorldFiles::addPack(const std::string& id) { - auto packs = files::read_list(getPacksFile()); +void WorldFiles::addPack(const World* world, const std::string& id) { + fs::path file = getPacksFile(); + if (!fs::is_regular_file(file)) { + if (!fs::is_directory(directory)) { + fs::create_directories(directory); + } + writePacks(world); + } + auto packs = files::read_list(file); packs.push_back(id); std::stringstream ss; @@ -559,5 +567,5 @@ void WorldFiles::addPack(const std::string& id) { for (const auto& pack : packs) { ss << pack << "\n"; } - files::write_string(getPacksFile(), ss.str()); + files::write_string(file, ss.str()); } diff --git a/src/files/WorldFiles.h b/src/files/WorldFiles.h index 291604dc..a6f9d534 100644 --- a/src/files/WorldFiles.h +++ b/src/files/WorldFiles.h @@ -16,8 +16,11 @@ #include "../settings.h" const uint REGION_HEADER_SIZE = 10; + const uint REGION_LAYER_VOXELS = 0; const uint REGION_LAYER_LIGHTS = 1; +const uint REGION_LAYER_STORAGES = 2; + const uint REGION_SIZE_BIT = 5; const uint REGION_SIZE = (1 << (REGION_SIZE_BIT)); const uint REGION_CHUNKS_COUNT = ((REGION_SIZE) * (REGION_SIZE)); @@ -74,8 +77,7 @@ class WorldFiles { std::unordered_map> openRegFiles; void writeWorldInfo(const World* world); - fs::path getLightsFolder() const; - fs::path getRegionFilename(int x, int y) const; + fs::path getRegionFilename(int x, int y) const; fs::path getWorldFile() const; fs::path getIndicesFile() const; fs::path getPacksFile() const; @@ -110,12 +112,16 @@ class WorldFiles { int x, int z, int layer); regfile* getRegFile(glm::ivec3 coord, const fs::path& folder); + + fs::path getLightsFolder() const; + fs::path getInventoriesFolder() const; public: static bool parseRegionFilename(const std::string& name, int& x, int& y); fs::path getRegionsFolder() const; fs::path getPlayerFile() const; regionsmap regions; + regionsmap storages; regionsmap lights; fs::path directory; std::unique_ptr compressionBuffer; @@ -147,7 +153,7 @@ public: void writePacks(const World* world); void writeIndices(const ContentIndices* indices); /* Append pack to packs.list without duplicate check */ - void addPack(const std::string& id); + void addPack(const World* world, const std::string& id); static const char* WORLD_FILE; }; diff --git a/src/files/files.cpp b/src/files/files.cpp index 55ca345f..59fa44b1 100644 --- a/src/files/files.cpp +++ b/src/files/files.cpp @@ -99,10 +99,7 @@ bool files::write_json(fs::path filename, const dynamic::Map* obj, bool nice) { } 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()); - } + auto bytes = json::to_binary(obj, compression); return files::write_bytes(filename, bytes.data(), bytes.size()); } diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 7a05abdd..14f7e169 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -172,7 +172,7 @@ std::shared_ptr HudRenderer::createContentAccess() { auto inventory = player->getInventory(); int itemsCount = indices->countItemDefs(); - auto accessInventory = std::make_shared(itemsCount); + auto accessInventory = std::make_shared(0, itemsCount); for (int id = 1; id < itemsCount; id++) { accessInventory->getSlot(id-1).set(ItemStack(id, 1)); } diff --git a/src/frontend/menu.cpp b/src/frontend/menu.cpp index 4d3d50a6..0d224745 100644 --- a/src/frontend/menu.cpp +++ b/src/frontend/menu.cpp @@ -252,7 +252,12 @@ typedef std::function packconsumer; const int PACKS_PANEL_WIDTH = 550; -std::shared_ptr create_packs_panel(const std::vector& packs, Engine* engine, bool backbutton, packconsumer callback) { +std::shared_ptr create_packs_panel( + const std::vector& packs, + Engine* engine, + bool backbutton, + packconsumer callback) +{ auto assets = engine->getAssets(); auto panel = std::make_shared(vec2(PACKS_PANEL_WIDTH, 200), vec4(5.0f)); panel->color(vec4(1.0f, 1.0f, 1.0f, 0.07f)); @@ -298,8 +303,9 @@ std::shared_ptr create_packs_panel(const std::vector& packs, packpanel->color(vec4(0.06f, 0.12f, 0.18f, 0.7f)); panel->add(packpanel); } - if (backbutton) + if (backbutton) { panel->add(guiutil::backButton(engine->getGUI()->getMenu())); + } return panel; } @@ -338,11 +344,11 @@ void create_content_panel(Engine* engine, PagesControl* menu) { return; } if (!world->hasPack(dependency)) { - world->wfile->addPack(dependency); + world->wfile->addPack(world, dependency); } } - world->wfile->addPack(pack.id); + world->wfile->addPack(world, pack.id); std::string wname = world->getName(); engine->setScreen(nullptr); diff --git a/src/items/Inventory.cpp b/src/items/Inventory.cpp index 1fbf2aa7..e414d152 100644 --- a/src/items/Inventory.cpp +++ b/src/items/Inventory.cpp @@ -2,7 +2,7 @@ #include "../content/ContentLUT.h" -Inventory::Inventory(size_t size) : slots(size) { +Inventory::Inventory(uint id, size_t size) : id(id), slots(size) { } ItemStack& Inventory::getSlot(size_t index) { @@ -45,6 +45,7 @@ void Inventory::move( } void Inventory::deserialize(dynamic::Map* src) { + id = src->getNum("id", 1); auto slotsarr = src->list("slots"); size_t slotscount = std::min(slotsarr->size(), slots.size()); for (size_t i = 0; i < slotscount; i++) { @@ -58,6 +59,8 @@ void Inventory::deserialize(dynamic::Map* src) { std::unique_ptr Inventory::serialize() const { auto map = std::make_unique(); + map->put("id", id); + auto& slotsarr = map->putList("slots"); for (size_t i = 0; i < slots.size(); i++) { auto& item = slots[i]; diff --git a/src/items/Inventory.h b/src/items/Inventory.h index 4ac0d130..e24fd3df 100644 --- a/src/items/Inventory.h +++ b/src/items/Inventory.h @@ -13,11 +13,11 @@ class ContentLUT; class ContentIndices; -// TODO: items indices fix class Inventory : Serializable { + uint id; std::vector slots; public: - Inventory(size_t size); + Inventory(uint id, size_t size); ItemStack& getSlot(size_t index); size_t findEmptySlot(size_t begin=0, size_t end=-1) const; @@ -40,6 +40,10 @@ public: static void convert(dynamic::Map* data, const ContentLUT* lut); + inline uint getId() const { + return id; + } + static const size_t npos; }; diff --git a/src/lighting/LightSolver.cpp b/src/lighting/LightSolver.cpp index 74637e64..d103b65b 100644 --- a/src/lighting/LightSolver.cpp +++ b/src/lighting/LightSolver.cpp @@ -22,7 +22,7 @@ void LightSolver::add(int x, int y, int z, int emission) { Chunk* chunk = chunks->getChunkByVoxel(x, y, z); chunk->setModified(true); - chunk->lightmap->set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, emission); + chunk->lightmap.set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, emission); } void LightSolver::add(int x, int y, int z) { @@ -35,12 +35,12 @@ void LightSolver::remove(int x, int y, int z) { if (chunk == nullptr) return; - ubyte light = chunk->lightmap->get(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel); + ubyte light = chunk->lightmap.get(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel); if (light == 0){ return; } remqueue.push(lightentry {x, y, z, light}); - chunk->lightmap->set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, 0); + chunk->lightmap.set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, 0); } void LightSolver::solve(){ @@ -67,10 +67,10 @@ void LightSolver::solve(){ int lz = z - chunk->z * CHUNK_D; chunk->setModified(true); - ubyte light = chunk->lightmap->get(lx,y,lz, channel); + ubyte light = chunk->lightmap.get(lx,y,lz, channel); if (light != 0 && light == entry.light-1){ remqueue.push(lightentry {x, y, z, light}); - chunk->lightmap->set(lx, y, lz, channel, 0); + chunk->lightmap.set(lx, y, lz, channel, 0); } else if (light >= entry.light){ addqueue.push(lightentry {x, y, z, light}); @@ -94,11 +94,11 @@ void LightSolver::solve(){ int lz = z - chunk->z * CHUNK_D; chunk->setModified(true); - ubyte light = chunk->lightmap->get(lx, y, lz, channel); + ubyte light = chunk->lightmap.get(lx, y, lz, channel); voxel& v = chunk->voxels[vox_index(lx, y, lz)]; const Block* block = blockDefs[v.id]; if (block->lightPassing && light+2 <= entry.light){ - chunk->lightmap->set( + chunk->lightmap.set( x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, entry.light-1); diff --git a/src/lighting/Lighting.cpp b/src/lighting/Lighting.cpp index 74924c72..6433db4f 100644 --- a/src/lighting/Lighting.cpp +++ b/src/lighting/Lighting.cpp @@ -29,9 +29,9 @@ void Lighting::clear(){ auto chunk = chunks->chunks[index]; if (chunk == nullptr) continue; - Lightmap* lightmap = chunk->lightmap; + Lightmap& lightmap = chunk->lightmap; for (int i = 0; i < CHUNK_VOL; i++){ - lightmap->map[i] = 0; + lightmap.map[i] = 0; } } } @@ -51,13 +51,13 @@ void Lighting::prebuildSkyLight(Chunk* chunk, const ContentIndices* indices){ highestPoint = y; break; } - chunk->lightmap->setS(x,y,z, 15); + chunk->lightmap.setS(x,y,z, 15); } } } if (highestPoint < CHUNK_H-1) highestPoint++; - chunk->lightmap->highestPoint = highestPoint; + chunk->lightmap.highestPoint = highestPoint; } void Lighting::buildSkyLight(int cx, int cz){ @@ -66,13 +66,13 @@ void Lighting::buildSkyLight(int cx, int cz){ Chunk* chunk = chunks->getChunk(cx, cz); for (int z = 0; z < CHUNK_D; z++){ for (int x = 0; x < CHUNK_W; x++){ - for (int y = chunk->lightmap->highestPoint; y >= 0; y--){ + for (int y = chunk->lightmap.highestPoint; y >= 0; y--){ int gx = x + cx * CHUNK_W; int gz = z + cz * CHUNK_D; while (y > 0 && !blockDefs[chunk->voxels[vox_index(x, y, z)].id]->lightPassing) { y--; } - if (chunk->lightmap->getS(x, y, z) != 15) { + if (chunk->lightmap.getS(x, y, z) != 15) { solverS->add(gx,y+1,gz); for (; y >= 0; y--){ solverS->add(gx+1,y,gz); @@ -99,7 +99,7 @@ void Lighting::onChunkLoaded(int cx, int cz, bool expand){ for (uint y = 0; y < CHUNK_H; y++){ for (uint z = 0; z < CHUNK_D; z++){ for (uint x = 0; x < CHUNK_W; x++){ - voxel& vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]; + const voxel& vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]; const Block* block = blockDefs[vox.id]; int gx = x + cx * CHUNK_W; int gz = z + cz * CHUNK_D; @@ -118,7 +118,7 @@ void Lighting::onChunkLoaded(int cx, int cz, bool expand){ for (int z = 0; z < CHUNK_D; z++) { int gx = x + cx * CHUNK_W; int gz = z + cz * CHUNK_D; - int rgbs = chunk->lightmap->get(x, y, z); + int rgbs = chunk->lightmap.get(x, y, z); if (rgbs){ solverR->add(gx,y,gz, Lightmap::extract(rgbs, 0)); solverG->add(gx,y,gz, Lightmap::extract(rgbs, 1)); @@ -133,7 +133,7 @@ void Lighting::onChunkLoaded(int cx, int cz, bool expand){ for (int x = 0; x < CHUNK_W; x++) { int gx = x + cx * CHUNK_W; int gz = z + cz * CHUNK_D; - int rgbs = chunk->lightmap->get(x, y, z); + int rgbs = chunk->lightmap.get(x, y, z); if (rgbs){ solverR->add(gx,y,gz, Lightmap::extract(rgbs, 0)); solverG->add(gx,y,gz, Lightmap::extract(rgbs, 1)); diff --git a/src/lighting/Lightmap.cpp b/src/lighting/Lightmap.cpp index f8698964..c513535b 100644 --- a/src/lighting/Lightmap.cpp +++ b/src/lighting/Lightmap.cpp @@ -3,26 +3,14 @@ #include "../util/data_io.h" -Lightmap::Lightmap(){ - map = new light_t[CHUNK_VOL]; - for (uint i = 0; i < CHUNK_VOL; i++){ - map[i] = 0x0000; - } -} - -Lightmap::~Lightmap(){ - delete[] map; -} - void Lightmap::set(const Lightmap* lightmap) { - for (unsigned int i = 0; i < CHUNK_VOL; i++){ - map[i] = lightmap->map[i]; - } + set(lightmap->map); } -void Lightmap::set(light_t* map) { - delete[] this->map; - this->map = map; +void Lightmap::set(const light_t* map) { + for (size_t i = 0; i < CHUNK_VOL; i++) { + this->map[i] = map[i]; + } } static_assert(sizeof(light_t) == 2, "replace dataio calls to new light_t"); diff --git a/src/lighting/Lightmap.h b/src/lighting/Lightmap.h index 14fb9d7f..16a273dd 100644 --- a/src/lighting/Lightmap.h +++ b/src/lighting/Lightmap.h @@ -3,43 +3,40 @@ #include "../constants.h" #include "../typedefs.h" -#include "../voxels/Chunk.h" const int LIGHTMAP_DATA_LEN = CHUNK_VOL/2; // Lichtkarte class Lightmap { public: - light_t* map; + light_t map[CHUNK_VOL] {}; int highestPoint = 0; - Lightmap(); - ~Lightmap(); void set(const Lightmap* lightmap); - void set(light_t* map); + void set(const light_t* map); - inline unsigned short get(int x, int y, int z){ + inline unsigned short get(int x, int y, int z) const { return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x]); } - inline unsigned char get(int x, int y, int z, int channel){ + inline unsigned char get(int x, int y, int z, int channel) const { return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> (channel << 2)) & 0xF; } - inline unsigned char getR(int x, int y, int z){ + inline unsigned char getR(int x, int y, int z) const { return map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] & 0xF; } - inline unsigned char getG(int x, int y, int z){ + inline unsigned char getG(int x, int y, int z) const { return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 4) & 0xF; } - inline unsigned char getB(int x, int y, int z){ + inline unsigned char getB(int x, int y, int z) const { return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 8) & 0xF; } - inline unsigned char getS(int x, int y, int z){ + inline unsigned char getS(int x, int y, int z) const { return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 12) & 0xF; } diff --git a/src/logic/BlocksController.cpp b/src/logic/BlocksController.cpp index 46a548d4..1fc968c4 100644 --- a/src/logic/BlocksController.cpp +++ b/src/logic/BlocksController.cpp @@ -5,10 +5,12 @@ #include "../voxels/Chunk.h" #include "../voxels/Chunks.h" #include "../world/Level.h" +#include "../world/World.h" #include "../content/Content.h" #include "../lighting/Lighting.h" #include "../util/timeutil.h" #include "../maths/fastmaths.h" +#include "../items/Inventory.h" #include "scripting/scripting.h" diff --git a/src/logic/BlocksController.h b/src/logic/BlocksController.h index 83bc8b02..d8e45dfe 100644 --- a/src/logic/BlocksController.h +++ b/src/logic/BlocksController.h @@ -46,6 +46,7 @@ public: void update(float delta); void randomTick(int tickid, int parts); void onBlocksTick(int tickid, int parts); + uint createBlockInventory(int x, int y, int z); }; #endif // LOGIC_BLOCKS_CONTROLLER_H_ diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index 3a5299fa..32ad381f 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -21,7 +21,7 @@ const float JUMP_FORCE = 8.0f; Player::Player(glm::vec3 position, float speed) : speed(speed), chosenSlot(0), - inventory(new Inventory(40)), + inventory(new Inventory(0, 40)), camera(new Camera(position, glm::radians(90.0f))), spCamera(new Camera(position, glm::radians(90.0f))), tpCamera(new Camera(position, glm::radians(90.0f))), diff --git a/src/voxels/Block.h b/src/voxels/Block.h index 5157713d..77da51a4 100644 --- a/src/voxels/Block.h +++ b/src/voxels/Block.h @@ -97,6 +97,7 @@ public: BlockRotProfile rotations; std::string pickingItem = name+BLOCK_ITEM_SUFFIX; std::string scriptName = name.substr(name.find(':')+1); + uint inventorySize = 0; struct { blockid_t id; diff --git a/src/voxels/Chunk.cpp b/src/voxels/Chunk.cpp index aba45f03..3193ee30 100644 --- a/src/voxels/Chunk.cpp +++ b/src/voxels/Chunk.cpp @@ -1,30 +1,23 @@ #include "Chunk.h" -#include - #include "voxel.h" + +#include "../items/Inventory.h" #include "../content/ContentLUT.h" #include "../lighting/Lightmap.h" Chunk::Chunk(int xpos, int zpos) : x(xpos), z(zpos){ bottom = 0; top = CHUNK_H; - voxels = new voxel[CHUNK_VOL]; - for (size_t i = 0; i < CHUNK_VOL; i++) { + for (uint i = 0; i < CHUNK_VOL; i++) { voxels[i].id = 2; voxels[i].states = 0; } - lightmap = new Lightmap(); -} - -Chunk::~Chunk(){ - delete lightmap; - delete[] voxels; } bool Chunk::isEmpty(){ int id = -1; - for (size_t i = 0; i < CHUNK_VOL; i++){ + for (uint i = 0; i < CHUNK_VOL; i++){ if (voxels[i].id != id){ if (id != -1) return false; @@ -36,13 +29,12 @@ bool Chunk::isEmpty(){ } void Chunk::updateHeights() { - for (size_t i = 0; i < CHUNK_VOL; i++) { + for (uint i = 0; i < CHUNK_VOL; i++) { if (voxels[i].id != 0) { bottom = i / (CHUNK_D * CHUNK_W); break; } } - for (int i = CHUNK_VOL - 1; i >= 0; i--) { if (voxels[i].id != 0) { top = i / (CHUNK_D * CHUNK_W) + 1; @@ -51,11 +43,28 @@ void Chunk::updateHeights() { } } -Chunk* Chunk::clone() const { - Chunk* other = new Chunk(x,z); - for (size_t i = 0; i < CHUNK_VOL; i++) +void Chunk::addBlockInventory(std::shared_ptr inventory, + uint x, uint y, uint z) { + inventories[vox_index(x, y, z)] = inventory; + setUnsaved(true); +} + +std::shared_ptr Chunk::getBlockInventory(uint x, uint y, uint z) const { + if (x >= CHUNK_W || y >= CHUNK_H || z >= CHUNK_D) + return nullptr; + const auto& found = inventories.find(vox_index(x, y, z)); + if (found == inventories.end()) { + return nullptr; + } + return found->second; +} + +std::unique_ptr Chunk::clone() const { + auto other = std::make_unique(x,z); + for (uint i = 0; i < CHUNK_VOL; i++) { other->voxels[i] = voxels[i]; - other->lightmap->set(lightmap); + } + other->lightmap.set(&lightmap); return other; } @@ -75,7 +84,7 @@ Chunk* Chunk::clone() const { */ ubyte* Chunk::encode() const { ubyte* buffer = new ubyte[CHUNK_DATA_LEN]; - for (size_t i = 0; i < CHUNK_VOL; i++) { + for (uint i = 0; i < CHUNK_VOL; i++) { buffer[i] = voxels[i].id >> 8; buffer[CHUNK_VOL+i] = voxels[i].id & 0xFF; buffer[CHUNK_VOL*2 + i] = voxels[i].states >> 8; @@ -84,11 +93,8 @@ ubyte* Chunk::encode() const { return buffer; } -/** - * @return true if all is fine - **/ bool Chunk::decode(ubyte* data) { - for (size_t i = 0; i < CHUNK_VOL; i++) { + for (uint i = 0; i < CHUNK_VOL; i++) { voxel& vox = voxels[i]; ubyte bid1 = data[i]; @@ -104,7 +110,7 @@ bool Chunk::decode(ubyte* data) { } void Chunk::convert(ubyte* data, const ContentLUT* lut) { - for (size_t i = 0; i < CHUNK_VOL; i++) { + for (uint i = 0; i < CHUNK_VOL; i++) { // see encode method to understand what the hell is going on here blockid_t id = ((blockid_t(data[i]) << 8) | blockid_t(data[CHUNK_VOL+i])); diff --git a/src/voxels/Chunk.h b/src/voxels/Chunk.h index 5103dc54..72a4a02f 100644 --- a/src/voxels/Chunk.h +++ b/src/voxels/Chunk.h @@ -1,8 +1,13 @@ #ifndef VOXELS_CHUNK_H_ #define VOXELS_CHUNK_H_ +#include #include +#include + #include "../constants.h" +#include "voxel.h" +#include "../lighting/Lightmap.h" struct ChunkFlag { static const int MODIFIED = 0x1; @@ -14,26 +19,29 @@ struct ChunkFlag { }; #define CHUNK_DATA_LEN (CHUNK_VOL*4) -struct voxel; class Lightmap; class ContentLUT; +class Inventory; class Chunk { public: int x, z; int bottom, top; - voxel* voxels; - Lightmap* lightmap; + voxel voxels[CHUNK_VOL]; + Lightmap lightmap; int flags = 0; + /* Block inventories map where key is index of block in voxels array */ + std::unordered_map> inventories; + Chunk(int x, int z); - ~Chunk(); bool isEmpty(); void updateHeights(); - Chunk* clone() const; + // unused + std::unique_ptr clone() const; // flags getters/setters below inline void setFlags(int mask, bool value){ @@ -43,6 +51,14 @@ public: flags &= ~(mask); } + /* Creates new block inventory given size + @return inventory id or 0 if block does not exists */ + void addBlockInventory(std::shared_ptr inventory, + uint x, uint y, uint z); + + /* @return inventory bound to the given block or nullptr */ + std::shared_ptr getBlockInventory(uint x, uint y, uint z) const; + inline bool isUnsaved() const {return flags & ChunkFlag::UNSAVED;} inline bool isModified() const {return flags & ChunkFlag::MODIFIED;} @@ -68,6 +84,10 @@ public: inline void setReady(bool newState) {setFlags(ChunkFlag::READY, newState);} ubyte* encode() const; + + /** + * @return true if all is fine + **/ bool decode(ubyte* data); static void convert(ubyte* data, const ContentLUT* lut); diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index 8f83dafa..488a76c0 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -107,7 +107,7 @@ ubyte Chunks::getLight(int x, int y, int z, int channel){ int lx = x - cx * CHUNK_W; int ly = y - cy * CHUNK_H; int lz = z - cz * CHUNK_D; - return chunk->lightmap->get(lx,ly,lz, channel); + return chunk->lightmap.get(lx,ly,lz, channel); } light_t Chunks::getLight(int x, int y, int z){ @@ -124,7 +124,7 @@ light_t Chunks::getLight(int x, int y, int z){ int lx = x - cx * CHUNK_W; int ly = y - cy * CHUNK_H; int lz = z - cz * CHUNK_D; - return chunk->lightmap->get(lx,ly,lz); + return chunk->lightmap.get(lx,ly,lz); } Chunk* Chunks::getChunkByVoxel(int x, int y, int z){ diff --git a/src/voxels/ChunksStorage.cpp b/src/voxels/ChunksStorage.cpp index 38f4808a..caf51d74 100644 --- a/src/voxels/ChunksStorage.cpp +++ b/src/voxels/ChunksStorage.cpp @@ -61,9 +61,9 @@ std::shared_ptr ChunksStorage::create(int x, int z) { verifyLoadedChunk(level->content->getIndices(), chunk.get()); } - light_t* lights = wfile->getLights(chunk->x, chunk->z); + std::unique_ptr lights (wfile->getLights(chunk->x, chunk->z)); if (lights) { - chunk->lightmap->set(lights); + chunk->lightmap.set(lights.get()); chunk->setLoadedLights(true); } return chunk; @@ -114,7 +114,7 @@ void ChunksStorage::getVoxels(VoxelsVolume* volume, bool backlight) const { } else { auto& chunk = found->second; const voxel* cvoxels = chunk->voxels; - const light_t* clights = chunk->lightmap->getLights(); + const light_t* clights = chunk->lightmap.getLights(); for (int ly = y; ly < y + h; ly++) { for (int lz = max(z, cz * CHUNK_D); lz < min(z + d, (cz + 1) * CHUNK_D); diff --git a/src/world/Level.cpp b/src/world/Level.cpp index f49d4ad6..4bd23183 100644 --- a/src/world/Level.cpp +++ b/src/world/Level.cpp @@ -9,6 +9,7 @@ #include "../physics/Hitbox.h" #include "../physics/PhysicsSolver.h" #include "../objects/Player.h" +#include "../items/Inventory.h" Level::Level(World* world, const Content* content, Player* player, EngineSettings& settings) : world(world), @@ -16,7 +17,8 @@ Level::Level(World* world, const Content* content, Player* player, EngineSetting player(player), chunksStorage(new ChunksStorage(this)), events(new LevelEvents()) , - settings(settings) { + settings(settings) +{ physics = new PhysicsSolver(glm::vec3(0, -22.6f, 0)); uint matrixSize = (settings.chunks.loadDistance+ diff --git a/src/world/Level.h b/src/world/Level.h index 0e2df5cc..2f42a78b 100644 --- a/src/world/Level.h +++ b/src/world/Level.h @@ -10,6 +10,7 @@ class Content; class World; class Player; class Chunks; +class Inventory; class LevelEvents; class Lighting; class PhysicsSolver; diff --git a/src/world/World.cpp b/src/world/World.cpp index 29997e61..d3e934c5 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -1,6 +1,7 @@ #include "World.h" #include +#include #include #include "Level.h" @@ -71,20 +72,11 @@ Level* World::create(std::string name, EngineSettings& settings, const Content* content, const std::vector& packs) { - World* world = new World(name, directory, seed, settings, content, packs); - Player* player = new Player(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED); + auto world = new World(name, directory, seed, settings, content, packs); + auto player = new Player(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED); return new Level(world, content, player, settings); } -ContentLUT* World::checkIndices(const fs::path& directory, - const Content* content) { - fs::path indicesFile = directory/fs::path("indices.json"); - if (fs::is_regular_file(indicesFile)) { - return ContentLUT::create(indicesFile, content); - } - return nullptr; -} - Level* World::load(fs::path directory, EngineSettings& settings, const Content* content, @@ -98,14 +90,23 @@ Level* World::load(fs::path directory, throw world_load_error("could not to find world.json"); } - Player* player = new Player(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED); - Level* level = new Level(world.get(), content, player, settings); + auto player = new Player(glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED); + auto level = new Level(world.get(), content, player, settings); wfile->readPlayer(player); world.release(); return level; } +ContentLUT* World::checkIndices(const fs::path& directory, + const Content* content) { + fs::path indicesFile = directory/fs::path("indices.json"); + if (fs::is_regular_file(indicesFile)) { + return ContentLUT::create(indicesFile, content); + } + return nullptr; +} + void World::setName(const std::string& name) { this->name = name; } @@ -133,3 +134,44 @@ uint64_t World::getSeed() const { const std::vector& World::getPacks() const { return packs; } + +void World::deserialize(dynamic::Map* root) { + name = root->getStr("name", name); + seed = root->getInt("seed", seed); + + auto verobj = root->map("version"); + if (verobj) { + int major=0, minor=-1; + verobj->num("major", major); + verobj->num("minor", minor); + std::cout << "world version: " << major << "." << minor << std::endl; + } + + auto timeobj = root->map("time"); + if (timeobj) { + timeobj->num("day-time", daytime); + timeobj->num("day-time-speed", daytimeSpeed); + timeobj->num("total-time", totalTime); + } + + nextInventoryId = root->getNum("next-inventory-id", 2); +} + +std::unique_ptr World::serialize() const { + auto root = std::make_unique(); + + auto& versionobj = root->putMap("version"); + versionobj.put("major", ENGINE_VERSION_MAJOR); + versionobj.put("minor", ENGINE_VERSION_MINOR); + + root->put("name", name); + root->put("seed", seed); + + auto& timeobj = root->putMap("time"); + timeobj.put("day-time", daytime); + timeobj.put("day-time-speed", daytimeSpeed); + timeobj.put("total-time", totalTime); + + root->put("next-inventory-id", nextInventoryId); + return root; +} diff --git a/src/world/World.h b/src/world/World.h index 527e1ce4..3e4716fe 100644 --- a/src/world/World.h +++ b/src/world/World.h @@ -8,7 +8,8 @@ #include "../typedefs.h" #include "../settings.h" #include "../util/timeutil.h" - +#include "../data/dynamic.h" +#include "../interfaces/Serializable.h" #include "../content/ContentPack.h" class Content; @@ -25,12 +26,14 @@ public: world_load_error(std::string message); }; -class World { +class World : Serializable { std::string name; uint64_t seed; EngineSettings& settings; const Content* const content; std::vector packs; + + uint nextInventoryId = 1; public: WorldFiles* wfile; @@ -74,6 +77,13 @@ public: std::string getName() const; uint64_t getSeed() const; const std::vector& getPacks() const; + + std::unique_ptr serialize() const override; + void deserialize(dynamic::Map *src) override; + + uint getNextInventoryId() { + return nextInventoryId++; + } }; #endif /* WORLD_WORLD_H_ */ From 8c722b146edac69c942b0e36d945ed4afc18d9ba Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 31 Jan 2024 04:26:35 +0300 Subject: [PATCH 003/115] frontend/gui refactor --- src/engine.cpp | 7 +- src/frontend/InventoryView.cpp | 18 +-- src/frontend/InventoryView.h | 5 +- src/frontend/gui/GUI.cpp | 24 ++-- src/frontend/gui/GUI.h | 4 +- src/frontend/gui/UINode.cpp | 80 ++++++------- src/frontend/gui/UINode.h | 56 +++++---- src/frontend/gui/controls.cpp | 211 ++++++++++++++++----------------- src/frontend/gui/controls.h | 40 +++---- src/frontend/gui/gui_util.cpp | 6 +- src/frontend/gui/panels.cpp | 98 ++++++++------- src/frontend/gui/panels.h | 7 +- src/frontend/hud.cpp | 43 ++++--- src/frontend/hud.h | 4 +- src/frontend/menu.cpp | 48 ++++---- src/graphics/GfxContext.cpp | 10 ++ src/graphics/GfxContext.h | 2 + 17 files changed, 331 insertions(+), 332 deletions(-) diff --git a/src/engine.cpp b/src/engine.cpp index ac6958c6..0b6e979b 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -17,6 +17,7 @@ #include "window/Camera.h" #include "window/input.h" #include "graphics/Batch2D.h" +#include "graphics/GfxContext.h" #include "graphics/Shader.h" #include "graphics/ImageData.h" #include "frontend/gui/GUI.h" @@ -113,7 +114,11 @@ void Engine::mainloop() { if (!Window::isIconified()) { screen->draw(delta); - gui->draw(&batch, assets.get()); + + Viewport viewport(Window::width, Window::height); + GfxContext ctx(nullptr, viewport, &batch); + gui->draw(&ctx, assets.get()); + Window::swapInterval(settings.display.swapInterval); } else { Window::swapInterval(1); diff --git a/src/frontend/InventoryView.cpp b/src/frontend/InventoryView.cpp index c7488958..acae9e55 100644 --- a/src/frontend/InventoryView.cpp +++ b/src/frontend/InventoryView.cpp @@ -160,22 +160,23 @@ SlotView::SlotView( content(content), stack(stack), layout(layout) { - color(glm::vec4(0, 0, 0, 0.2f)); + setColor(glm::vec4(0, 0, 0, 0.2f)); } // performance disaster -void SlotView::draw(Batch2D* batch, Assets* assets) { +void SlotView::draw(const GfxContext* pctx, Assets* assets) { glm::vec2 coord = calcCoord(); int slotSize = InventoryView::SLOT_SIZE; glm::vec4 tint(1.0f); - glm::vec4 color = color_; - if (hover_ || highlighted) { + glm::vec4 color = getColor(); + if (hover || highlighted) { tint *= 1.333f; color = glm::vec4(1, 1, 1, 0.2f); } + auto batch = pctx->getBatch2D(); batch->color = color; if (color.a > 0.0) { batch->texture(nullptr); @@ -313,8 +314,8 @@ InventoryView::InventoryView( layout(std::move(layout)), frontend(frontend), interaction(interaction) { - size(this->layout->getSize()); - color(glm::vec4(0, 0, 0, 0.0f)); + setSize(this->layout->getSize()); + setColor(glm::vec4(0, 0, 0, 0.0f)); } InventoryView::~InventoryView() {} @@ -331,7 +332,7 @@ void InventoryView::build() { item, frontend, interaction, content, slot ); if (!slot.background) { - view->color(glm::vec4()); + view->setColor(glm::vec4()); } slots.push_back(view.get()); add(view, slot.position); @@ -358,8 +359,9 @@ InventoryLayout* InventoryView::getLayout() const { return layout.get(); } -void InventoryView::drawBackground(Batch2D* batch, Assets* assets) { +void InventoryView::drawBackground(const GfxContext* pctx, Assets* assets) { glm::vec2 coord = calcCoord(); + auto batch = pctx->getBatch2D(); batch->texture(nullptr); diff --git a/src/frontend/InventoryView.h b/src/frontend/InventoryView.h index 3f85d187..7c6b26db 100644 --- a/src/frontend/InventoryView.h +++ b/src/frontend/InventoryView.h @@ -11,7 +11,6 @@ #include "../items/ItemStack.h" #include "../typedefs.h" -class Batch2D; class Assets; class GfxContext; class Content; @@ -102,7 +101,7 @@ public: const Content* content, SlotLayout layout); - virtual void draw(Batch2D* batch, Assets* assets) override; + virtual void draw(const GfxContext* pctx, Assets* assets) override; void setHighlighted(bool flag); bool isHighlighted() const; @@ -135,7 +134,7 @@ public: void build(); - virtual void drawBackground(Batch2D* batch, Assets* assets) override; + virtual void drawBackground(const GfxContext* pctx, Assets* assets) override; void setInventory(std::shared_ptr inventory); diff --git a/src/frontend/gui/GUI.cpp b/src/frontend/gui/GUI.cpp index 5dd189c9..114693d3 100644 --- a/src/frontend/gui/GUI.cpp +++ b/src/frontend/gui/GUI.cpp @@ -8,6 +8,7 @@ #include "../../assets/Assets.h" #include "../../graphics/Batch2D.h" #include "../../graphics/Shader.h" +#include "../../graphics/GfxContext.h" #include "../../window/Events.h" #include "../../window/input.h" #include "../../window/Camera.h" @@ -42,10 +43,10 @@ PagesControl* GUI::getMenu() { void GUI::actMouse(float delta) { auto hover = container->getAt(Events::cursor, nullptr); if (this->hover && this->hover != hover) { - this->hover->hover(false); + this->hover->setHover(false); } if (hover) { - hover->hover(true); + hover->setHover(true); if (Events::scroll) { hover->scrolled(Events::scroll); } @@ -84,7 +85,7 @@ void GUI::actMouse(float delta) { } void GUI::act(float delta) { - container->size(vec2(Window::width, Window::height)); + container->setSize(vec2(Window::width, Window::height)); container->act(delta); auto prevfocus = focus; @@ -111,21 +112,24 @@ void GUI::act(float delta) { } } } - if (focus && !focus->isfocused()) { + if (focus && !focus->isFocused()) { focus = nullptr; } } -void GUI::draw(Batch2D* batch, Assets* assets) { - menu->setCoord((Window::size() - menu->size()) / 2.0f); - uicamera->setFov(Window::height); +void GUI::draw(const GfxContext* pctx, Assets* assets) { + auto& viewport = pctx->getViewport(); + glm::vec2 wsize = viewport.size(); + + menu->setCoord((wsize - menu->getSize()) / 2.0f); + uicamera->setFov(wsize.y); Shader* uishader = assets->getShader("ui"); uishader->use(); uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView()); - batch->begin(); - container->draw(batch, assets); + pctx->getBatch2D()->begin(); + container->draw(pctx, assets); } shared_ptr GUI::getFocused() const { @@ -133,7 +137,7 @@ shared_ptr GUI::getFocused() const { } bool GUI::isFocusCaught() const { - return focus && focus->isfocuskeeper(); + return focus && focus->isFocuskeeper(); } void GUI::addBack(std::shared_ptr panel) { diff --git a/src/frontend/gui/GUI.h b/src/frontend/gui/GUI.h index 3e159f4a..6b8876f9 100644 --- a/src/frontend/gui/GUI.h +++ b/src/frontend/gui/GUI.h @@ -8,7 +8,7 @@ #include #include -class Batch2D; +class GfxContext; class Assets; class Camera; @@ -71,7 +71,7 @@ namespace gui { bool isFocusCaught() const; void act(float delta); - void draw(Batch2D* batch, Assets* assets); + void draw(const GfxContext* pctx, Assets* assets); void addBack(std::shared_ptr panel); void add(std::shared_ptr panel); void remove(std::shared_ptr panel); diff --git a/src/frontend/gui/UINode.cpp b/src/frontend/gui/UINode.cpp index 239da047..d87e1c9e 100644 --- a/src/frontend/gui/UINode.cpp +++ b/src/frontend/gui/UINode.cpp @@ -2,42 +2,40 @@ #include "../../graphics/Batch2D.h" -using std::shared_ptr; - using gui::UINode; using gui::Align; using glm::vec2; using glm::vec4; -UINode::UINode(vec2 coord, vec2 size) : coord(coord), size_(size) { +UINode::UINode(vec2 coord, vec2 size) : coord(coord), size(size) { } UINode::~UINode() { } -bool UINode::visible() const { - return isvisible; +bool UINode::isVisible() const { + return visible; } -void UINode::visible(bool flag) { - isvisible = flag; +void UINode::setVisible(bool flag) { + visible = flag; } -Align UINode::align() const { - return align_; +Align UINode::getAlign() const { + return align; } -void UINode::align(Align align) { - align_ = align; +void UINode::setAlign(Align align) { + this->align = align; } -void UINode::hover(bool flag) { - hover_ = flag; +void UINode::setHover(bool flag) { + hover = flag; } -bool UINode::hover() const { - return hover_; +bool UINode::isHover() const { + return hover; } void UINode::setParent(UINode* node) { @@ -49,33 +47,33 @@ UINode* UINode::getParent() const { } void UINode::click(GUI*, int x, int y) { - pressed_ = true; + pressed = true; } void UINode::mouseRelease(GUI*, int x, int y) { - pressed_ = false; + pressed = false; } -bool UINode::ispressed() const { - return pressed_; +bool UINode::isPressed() const { + return pressed; } void UINode::defocus() { - focused_ = false; + focused = false; } -bool UINode::isfocused() const { - return focused_; +bool UINode::isFocused() const { + return focused; } bool UINode::isInside(glm::vec2 pos) { vec2 coord = calcCoord(); - vec2 size = this->size(); + vec2 size = getSize(); return (pos.x >= coord.x && pos.y >= coord.y && pos.x < coord.x + size.x && pos.y < coord.y + size.y); } -shared_ptr UINode::getAt(vec2 pos, shared_ptr self) { +std::shared_ptr UINode::getAt(vec2 pos, std::shared_ptr self) { if (!interactive) { return nullptr; } @@ -83,7 +81,7 @@ shared_ptr UINode::getAt(vec2 pos, shared_ptr self) { } bool UINode::isInteractive() const { - return interactive && visible(); + return interactive && isVisible(); } void UINode::setInteractive(bool flag) { @@ -107,36 +105,28 @@ void UINode::setCoord(vec2 coord) { this->coord = coord; } -vec2 UINode::size() const { - return size_; +vec2 UINode::getSize() const { + return size; } -void UINode::size(vec2 size) { - if (sizelock) - return; - this->size_ = size; +void UINode::setSize(vec2 size) { + this->size = size; } -void UINode::_size(vec2 size) { - if (sizelock) - return; - this->size_ = size; +void UINode::setColor(vec4 color) { + this->color = color; } -void UINode::color(vec4 color) { - this->color_ = color; +vec4 UINode::getColor() const { + return color; } -vec4 UINode::color() const { - return color_; +void UINode::setMargin(vec4 margin) { + this->margin = margin; } -void UINode::margin(vec4 margin) { - this->margin_ = margin; -} - -vec4 UINode::margin() const { - return margin_; +vec4 UINode::getMargin() const { + return margin; } void UINode::lock() { diff --git a/src/frontend/gui/UINode.h b/src/frontend/gui/UINode.h index 6f909ba5..56859cd7 100644 --- a/src/frontend/gui/UINode.h +++ b/src/frontend/gui/UINode.h @@ -6,7 +6,7 @@ #include #include -class Batch2D; +class GfxContext; class Assets; namespace gui { @@ -22,52 +22,51 @@ namespace gui { class UINode { protected: glm::vec2 coord; - glm::vec2 size_; - glm::vec4 color_ {1.0f}; - glm::vec4 margin_ {1.0f}; - bool isvisible = true; - bool sizelock = false; - bool hover_ = false; - bool pressed_ = false; - bool focused_ = false; + glm::vec2 size; + glm::vec4 color {1.0f}; + glm::vec4 margin {1.0f}; + bool visible = true; + bool hover = false; + bool pressed = false; + bool focused = false; bool interactive = true; - Align align_ = Align::left; + Align align = Align::left; UINode* parent = nullptr; UINode(glm::vec2 coord, glm::vec2 size); public: virtual ~UINode(); virtual void act(float delta) {}; - virtual void draw(Batch2D* batch, Assets* assets) = 0; + virtual void draw(const GfxContext* pctx, Assets* assets) = 0; - virtual void visible(bool flag); - bool visible() const; + virtual void setVisible(bool flag); + bool isVisible() const; - virtual void align(Align align); - Align align() const; + virtual void setAlign(Align align); + Align getAlign() const; - virtual void hover(bool flag); - bool hover() const; + virtual void setHover(bool flag); + bool isHover() const; virtual void setParent(UINode* node); UINode* getParent() const; - virtual void color(glm::vec4 newColor); - glm::vec4 color() const; + virtual void setColor(glm::vec4 newColor); + glm::vec4 getColor() const; - virtual void margin(glm::vec4 margin); - glm::vec4 margin() const; + virtual void setMargin(glm::vec4 margin); + glm::vec4 getMargin() const; - virtual void focus(GUI*) {focused_ = true;} + virtual void focus(GUI*) {focused = true;} virtual void click(GUI*, int x, int y); virtual void clicked(GUI*, int button) {} virtual void mouseMove(GUI*, int x, int y) {}; virtual void mouseRelease(GUI*, int x, int y); virtual void scrolled(int value); - bool ispressed() const; + bool isPressed() const; void defocus(); - bool isfocused() const; - virtual bool isfocuskeeper() const {return false;} + bool isFocused() const; + virtual bool isFocuskeeper() const {return false;} virtual void typed(unsigned int codepoint) {}; virtual void keyPressed(int key) {}; @@ -79,11 +78,10 @@ namespace gui { virtual void setInteractive(bool flag); virtual glm::vec2 contentOffset() {return glm::vec2(0.0f);}; - glm::vec2 calcCoord() const; + virtual glm::vec2 calcCoord() const; virtual void setCoord(glm::vec2 coord); - virtual glm::vec2 size() const; - virtual void size(glm::vec2 size); - void _size(glm::vec2 size); + virtual glm::vec2 getSize() const; + virtual void setSize(glm::vec2 size); virtual void refresh() {}; virtual void lock(); }; diff --git a/src/frontend/gui/controls.cpp b/src/frontend/gui/controls.cpp index 54188b43..b5fc5b65 100644 --- a/src/frontend/gui/controls.cpp +++ b/src/frontend/gui/controls.cpp @@ -6,58 +6,53 @@ #include "../../assets/Assets.h" #include "../../graphics/Batch2D.h" #include "../../graphics/Font.h" +#include "../../graphics/GfxContext.h" #include "../../util/stringutil.h" #include "GUI.h" -using std::string; -using std::wstring; -using std::shared_ptr; using glm::vec2; using glm::vec3; using glm::vec4; -const uint KEY_ESCAPE = 256; -const uint KEY_ENTER = 257; -const uint KEY_BACKSPACE = 259; - using namespace gui; -Label::Label(string text, string fontName) +Label::Label(std::string text, std::string fontName) : UINode(vec2(), vec2(text.length() * 8, 15)), - text_(util::str2wstr_utf8(text)), + text(util::str2wstr_utf8(text)), fontName_(fontName) { } -Label::Label(wstring text, string fontName) +Label::Label(std::wstring text, std::string fontName) : UINode(vec2(), vec2(text.length() * 8, 15)), - text_(text), + text(text), fontName_(fontName) { } -Label& Label::text(wstring text) { - this->text_ = text; - return *this; +void Label::setText(std::wstring text) { + this->text = text; } -wstring Label::text() const { - return text_; +std::wstring Label::getText() const { + return text; } -void Label::draw(Batch2D* batch, Assets* assets) { +void Label::draw(const GfxContext* pctx, Assets* assets) { if (supplier) { - text(supplier()); + setText(supplier()); } - batch->color = color_; + + auto batch = pctx->getBatch2D(); + batch->color = getColor(); Font* font = assets->getFont(fontName_); - vec2 size = UINode::size(); - vec2 newsize = vec2(font->calcWidth(text_), font->lineHeight()); + vec2 size = getSize(); + vec2 newsize = vec2(font->calcWidth(text), font->lineHeight()); if (newsize.x > size.x) { - this->size(newsize); + setSize(newsize); size = newsize; } vec2 coord = calcCoord(); - font->draw(batch, text_, coord.x, coord.y); + font->draw(batch, text, coord.x, coord.y); } Label* Label::textSupplier(wstringsupplier supplier) { @@ -65,58 +60,61 @@ Label* Label::textSupplier(wstringsupplier supplier) { return this; } -void Label::size(vec2 sizenew) { - UINode::size(vec2(UINode::size().x, sizenew.y)); +void Label::setSize(vec2 sizenew) { + UINode::setSize(vec2(UINode::getSize().x, sizenew.y)); } // ================================= Image ==================================== -Image::Image(string texture, vec2 size) : UINode(vec2(), size), texture(texture) { +Image::Image(std::string texture, vec2 size) : UINode(vec2(), size), texture(texture) { setInteractive(false); } -void Image::draw(Batch2D* batch, Assets* assets) { +void Image::draw(const GfxContext* pctx, Assets* assets) { vec2 coord = calcCoord(); + vec4 color = getColor(); + auto batch = pctx->getBatch2D(); batch->texture(assets->getTexture(texture)); - batch->color = color_; - batch->rect(coord.x, coord.y, size_.x, size_.y, 0, 0, 0, UVRegion(), false, true, color_); + batch->color = color; + batch->rect(coord.x, coord.y, size.x, size.y, + 0, 0, 0, UVRegion(), false, true, color); } // ================================= Button =================================== -Button::Button(shared_ptr content, glm::vec4 padding) - : Panel(content->size()+vec2(padding[0]+padding[2]+content->margin()[0]+content->margin()[2], - padding[1]+padding[3]+content->margin()[1]+content->margin()[3]), padding, 0) { +Button::Button(std::shared_ptr content, glm::vec4 padding) + : Panel(vec2(), padding, 0) { + vec4 margin = getMargin(); + setSize(content->getSize()+vec2(padding[0]+padding[2]+margin[0]+margin[2], + padding[1]+padding[3]+margin[1]+margin[3])); add(content); scrollable(false); } -Button::Button(wstring text, glm::vec4 padding, glm::vec4 margin) - : Panel(vec2(32,32), padding, 0) { - this->margin(margin); - Label* label = new Label(text); - label->align(Align::center); - this->label = shared_ptr(label); - add(this->label); +Button::Button(std::wstring text, glm::vec4 padding, glm::vec4 margin) + : Panel(vec2(32,32), padding, 0) +{ + setMargin(margin); scrollable(false); + + label = std::make_shared