#pragma once #include #include #include #include #include #include #include #include "Vector.hpp" #include "Block.hpp" #include "TextureAtlas.hpp" struct BlockModel { bool IsBlock = false; std::string BlockName; bool AmbientOcclusion = true; enum DisplayVariants { thirdperson_righthand, thirdperson_lefthand, firstperson_righthand, firstperson_lefthand, gui, head, ground, fixed, DisplayVariantsCount, }; struct DisplayData { Vector rotation; Vector translation; Vector scale; }; std::map Display; std::map Textures; struct ElementData { Vector from; Vector to; Vector rotationOrigin = Vector(8, 8, 8); enum Axis { x, y, z, } rotationAxis = Axis::x; int rotationAngle = 0; bool rotationRescale = false; bool shade = true; enum FaceDirection { down, up, north, south, west, east, none, }; struct FaceData { struct Uv { int x1, y1, x2, y2; } uv = { 0,0,0,0 }; std::string texture; FaceDirection cullface = FaceDirection::none; int rotation = 0; bool tintIndex = false; }; std::map faces; }; std::vector Elements; struct ParsedFace { ElementData::FaceDirection visibility; glm::mat4 transform; glm::vec4 texture; float layer; glm::vec3 color; }; std::vector parsedFaces; }; inline bool operator==(const BlockModel::ElementData::FaceData::Uv &lhs, const BlockModel::ElementData::FaceData::Uv &rhs) { return lhs.x1 == rhs.x1 && lhs.y1 == rhs.y1 && lhs.x2 == rhs.x2 && lhs.y2 == rhs.y2; } struct Asset { virtual ~Asset() {}; }; struct AssetTreeNode { std::vector> childs; std::vector data; std::string name; std::unique_ptr asset; AssetTreeNode *parent; }; struct AssetBlockModel : Asset { BlockModel blockModel; }; struct AssetTexture : Asset { std::vector textureData; unsigned int realWidth, realHeight; size_t id; }; class AssetManager { std::map assetIds; std::map blockIdToBlockName; std::unique_ptr assetTree; std::unique_ptr atlas; public: AssetManager(); ~AssetManager(); void LoadIds(); static AssetManager& Instance(); const BlockModel *GetBlockModelByBlockId(BlockId block); std::string GetAssetNameByBlockId(BlockId block); void ParseBlockModels(); void LoadAssets(); template T *GetAsset(const std::string &assetName) { AssetTreeNode *node; if (assetName[0] != '/') node = GetAssetByAssetName('/'+assetName); else node = GetAssetByAssetName(assetName); if (!node) return nullptr; return dynamic_cast(node->asset.get()); } void ParseAsset(AssetTreeNode &node); void ParseAssetBlockModel(AssetTreeNode &node); void RecursiveWalkAsset(const std::string &assetPath, std::function fnc); AssetTreeNode *GetAssetByAssetName(const std::string &assetName); void LoadTextures(); void ParseAssetTexture(AssetTreeNode &node); inline GLuint GetTextureAtlasId() { return atlas->GetRawTextureId(); } inline TextureCoord GetTexture(const std::string assetName) { AssetTexture *asset = GetAsset(assetName); if (!asset) return {}; return atlas->GetTexture(asset->id); } };