diff options
Diffstat (limited to '')
-rw-r--r-- | src/AssetManager.cpp | 586 |
1 files changed, 310 insertions, 276 deletions
diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp index 7f4bf7d..6a4b3a3 100644 --- a/src/AssetManager.cpp +++ b/src/AssetManager.cpp @@ -14,17 +14,35 @@ namespace fs = std::experimental::filesystem::v1; const fs::path pathToAssets = "./assets/"; -//const fs::path pathToAssetsList = "./items.json"; -//const fs::path pathToTextureIndex = "./textures.json"; const std::string pathToAssetsList = "./items.json"; -const std::string pathToTextureIndex = "./textures.json"; -const fs::path pathToModels = "./assets/minecraft/models/"; +std::map<std::string, BlockId> assetIds; +std::map<BlockId, std::string> blockIdToBlockName; +std::unique_ptr<AssetTreeNode> assetTree; +std::unique_ptr<TextureAtlas> atlas; -AssetManager::AssetManager() { +void LoadIds(); +void LoadAssets(); +void LoadTextures(); + +void WalkDirEntry(const fs::directory_entry &dirEntry, AssetTreeNode *node); +void ParseAsset(AssetTreeNode &node); +void ParseAssetTexture(AssetTreeNode &node); +void ParseAssetBlockModel(AssetTreeNode &node); + +void ParseBlockModels(); + +void AssetManager::InitAssetManager() +{ + static bool Initialized = false; + if (Initialized) { + LOG(WARNING) << "Trying to init AssetManager twice"; + } + Initialized = true; + LoadAssets(); - auto parseAssetRecur = [this](AssetTreeNode &node) { + auto parseAssetRecur = [](AssetTreeNode &node) { ParseAsset(node); }; @@ -32,79 +50,248 @@ AssetManager::AssetManager() { LoadTextures(); - LoadIds(); - ParseBlockModels(); + LoadIds(); + ParseBlockModels(); } -void AssetManager::LoadIds() { - std::ifstream in(pathToAssetsList); - nlohmann::json index; - in >> index; - for (auto &it:index) { - unsigned short id = it["type"].get<int>(); - unsigned char state = it["meta"].get<int>(); - std::string blockName = it["text_type"].get<std::string>(); - assetIds[blockName] = BlockId{ id, state }; - } - LOG(INFO) << "Loaded " << assetIds.size() << " ids"; +void LoadIds() { + std::ifstream in(pathToAssetsList); + nlohmann::json index; + in >> index; + for (auto &it : index) { + unsigned short id = it["type"].get<int>(); + unsigned char state = it["meta"].get<int>(); + std::string blockName = it["text_type"].get<std::string>(); + assetIds[blockName] = BlockId{ id, state }; + } + LOG(INFO) << "Loaded " << assetIds.size() << " ids"; } -AssetManager::~AssetManager() { +void LoadAssets() { + assetTree = std::make_unique<AssetTreeNode>(); + assetTree->name = "/"; + WalkDirEntry(fs::directory_entry(pathToAssets), assetTree.get()); } -AssetManager &AssetManager::Instance() { - static AssetManager assetManager; - return assetManager; +void LoadTextures() { + std::vector<TextureData> textureData; + size_t id = 0; + AssetManager::RecursiveWalkAsset("/minecraft/textures/", [&](AssetTreeNode &node) { + TextureData data; + AssetTexture *textureAsset = dynamic_cast<AssetTexture*>(node.asset.get()); + if (!textureAsset) + return; + data.data = std::move(textureAsset->textureData); + data.width = textureAsset->realWidth; + data.height = textureAsset->realHeight; + textureData.push_back(data); + textureAsset->id = id++; + }); + atlas = std::make_unique<TextureAtlas>(textureData); } -const BlockModel *AssetManager::GetBlockModelByBlockId(BlockId block) { - block.state = 0; - if (blockIdToBlockName.find(block) == blockIdToBlockName.end()) { - std::string blockName = ""; - for (const auto& it : assetIds) { - if (BlockId{ it.second.id,0 } == block) { - blockName = it.first; - break; - } - } - if (blockName == "grass") - blockName = "grass_normal"; - if (blockName == "torch") - blockName = "normal_torch"; - if (blockName == "leaves") - blockName = "oak_leaves"; - if (blockName == "tallgrass") - blockName = "tall_grass"; - if (blockName == "log") - blockName = "oak_bark"; - if (blockName == "snow_layer") - blockName = "snow_height2"; +void WalkDirEntry(const fs::directory_entry &dirEntry, AssetTreeNode *node) { + for (auto &file : fs::directory_iterator(dirEntry)) { + node->childs.push_back(std::make_unique<AssetTreeNode>()); + AssetTreeNode *fileNode = node->childs.back().get(); + fileNode->parent = node; + fileNode->name = file.path().stem().string(); + if (fs::is_directory(file)) { + WalkDirEntry(file, fileNode); + } + else { + size_t fileSize = fs::file_size(file); + fileNode->data.resize(fileSize); + FILE *f = fopen(file.path().string().c_str(), "rb"); + fread(fileNode->data.data(), 1, fileSize, f); + fclose(f); + } + } +} - blockName = "block/" + blockName; +void ParseAsset(AssetTreeNode &node) { + if (node.data.empty() || node.asset) + return; - if (blockName == "") - return nullptr; + if (node.parent->name == "block" && node.parent->parent->name == "models") { + ParseAssetBlockModel(node); + return; + } - blockIdToBlockName[block] = blockName; - } + if (node.data[0] == 0x89 && node.data[1] == 'P' && node.data[2] == 'N' && node.data[3] == 'G') { + ParseAssetTexture(node); + return; + } +} - std::string blockName = blockIdToBlockName[block]; +void ParseAssetTexture(AssetTreeNode &node) { + SDL_RWops *rw = SDL_RWFromMem(node.data.data(), node.data.size()); + SDL_Surface *surface = IMG_LoadPNG_RW(rw); - AssetBlockModel *model = GetAsset<AssetBlockModel>("/minecraft/models/" + blockName); - return (model == nullptr) ? &GetAsset<AssetBlockModel>("/minecraft/models/block/diamond_block")->blockModel : &model->blockModel; + SDL_RWclose(rw); + if (!surface) { + return; + } + + if (surface->format->format != SDL_PIXELFORMAT_RGBA8888) { + SDL_Surface *temp = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGBA8888, 0); + std::swap(temp, surface); + if (!temp) { + std::swap(temp, surface); + } + SDL_FreeSurface(temp); + } + + SDL_LockSurface(surface); + + node.asset = std::make_unique<AssetTexture>(); + AssetTexture *asset = dynamic_cast<AssetTexture*>(node.asset.get()); + size_t dataLen = surface->h * surface->pitch; + asset->textureData.resize(dataLen); + std::memcpy(asset->textureData.data(), surface->pixels, dataLen); + asset->realWidth = surface->w; + asset->realHeight = surface->h; + + SDL_UnlockSurface(surface); + SDL_FreeSurface(surface); + + node.data.swap(std::vector<unsigned char>()); } -std::string AssetManager::GetAssetNameByBlockId(BlockId block) { - for (auto& it : assetIds) { - BlockId value = it.second; - value.state = 0; - if (value == block) - return it.first; - } - return "#NF"; +void ParseAssetBlockModel(AssetTreeNode &node) { + nlohmann::json modelData = nlohmann::json::parse(node.data); + BlockModel model; + + if (node.name == "button") { + int a = 15; + a++; + } + + if (modelData.find("parent") != modelData.end()) { + std::string parentName = modelData["parent"].get<std::string>(); + parentName = parentName.substr(parentName.find('/') + 1); + for (auto &it : node.parent->childs) { + if (it->name == parentName) { + ParseAsset(*it); + model = dynamic_cast<AssetBlockModel*>(it->asset.get())->blockModel; + unsigned char *b = reinterpret_cast<unsigned char*>(&model.IsBlock); + } + } + } + + model.BlockName = node.name; + + if (model.BlockName == "block") + model.IsBlock = true; + + if (model.BlockName == "thin_block" || model.BlockName == "leaves") + model.IsBlock = false; + + if (modelData.find("ambientocclusion") != modelData.end()) + model.AmbientOcclusion = modelData["ambientocclusion"].get<bool>(); + + //models.Display + + if (modelData.find("textures") != modelData.end()) { + for (nlohmann::json::iterator texture = modelData["textures"].begin(); texture != modelData["textures"].end(); ++texture) { + model.Textures[texture.key()] = texture.value().get<std::string>(); + } + } + + if (modelData.find("elements") != modelData.end()) { + model.Elements.clear(); + for (auto& it : modelData["elements"]) { + BlockModel::ElementData element; + + auto vec = it["from"]; + Vector from(vec[0].get<int>(), vec[1].get<int>(), vec[2].get<int>()); + vec = it["to"]; + Vector to(vec[0].get<int>(), vec[1].get<int>(), vec[2].get<int>()); + + element.from = from; + element.to = to; + + if (it.find("rotation") != it.end()) { + vec = it["rotation"]["origin"]; + Vector rotOrig(vec[0].get<int>(), vec[1].get<int>(), vec[2].get<int>()); + + element.rotationOrigin = rotOrig; + element.rotationAxis = (it["rotation"]["axis"].get<std::string>() == "x") ? BlockModel::ElementData::Axis::x : ((it["rotation"]["axis"].get<std::string>() == "y") ? BlockModel::ElementData::Axis::y : BlockModel::ElementData::Axis::z); + if (it["rotation"].find("angle") != it["rotation"].end()) + element.rotationAngle = it["rotation"]["angle"].get<int>(); + + if (it["rotation"].find("rescale") != it["rotation"].end()) + element.rotationRescale = it["rotation"]["rescale"].get<bool>(); + } + + if (it.find("shade") != it.end()) + element.shade = it["shade"].get<bool>(); + + for (nlohmann::json::iterator faceIt = it["faces"].begin(); faceIt != it["faces"].end(); ++faceIt) { + auto face = faceIt.value(); + BlockModel::ElementData::FaceData faceData; + + BlockModel::ElementData::FaceDirection faceDir; + if (faceIt.key() == "down") + faceDir = BlockModel::ElementData::FaceDirection::down; + else if (faceIt.key() == "up") + faceDir = BlockModel::ElementData::FaceDirection::up; + else if (faceIt.key() == "north") + faceDir = BlockModel::ElementData::FaceDirection::north; + else if (faceIt.key() == "south") + faceDir = BlockModel::ElementData::FaceDirection::south; + else if (faceIt.key() == "west") + faceDir = BlockModel::ElementData::FaceDirection::west; + else if (faceIt.key() == "east") + faceDir = BlockModel::ElementData::FaceDirection::east; + + if (face.find("uv") != face.end()) { + BlockModel::ElementData::FaceData::Uv uv; + uv.x1 = face["uv"][0]; + uv.y1 = face["uv"][1]; + uv.x2 = face["uv"][2]; + uv.y2 = face["uv"][3]; + faceData.uv = uv; + } + + BlockModel::ElementData::FaceDirection cullface = BlockModel::ElementData::FaceDirection::none; + if (face.find("cullface") != face.end()) { + if (face["cullface"] == "down") + cullface = BlockModel::ElementData::FaceDirection::down; + else if (face["cullface"] == "up") + cullface = BlockModel::ElementData::FaceDirection::up; + else if (face["cullface"] == "north") + cullface = BlockModel::ElementData::FaceDirection::north; + else if (face["cullface"] == "south") + cullface = BlockModel::ElementData::FaceDirection::south; + else if (face["cullface"] == "west") + cullface = BlockModel::ElementData::FaceDirection::west; + else if (face["cullface"] == "east") + cullface = BlockModel::ElementData::FaceDirection::east; + } + faceData.cullface = cullface; + + faceData.texture = face["texture"].get<std::string>(); + + if (face.find("rotation") != face.end()) + faceData.rotation = face["rotation"].get<int>(); + + if (face.find("tintindex") != face.end()) + faceData.tintIndex = true; + + element.faces[faceDir] = faceData; + } + + model.Elements.push_back(element); + } + } + + node.asset = std::make_unique<AssetBlockModel>(); + dynamic_cast<AssetBlockModel*>(node.asset.get())->blockModel = model; + node.data.swap(std::vector<unsigned char>()); } -void AssetManager::ParseBlockModels() { +void ParseBlockModels() { std::string textureName; auto parseBlockModel = [&](AssetTreeNode &node) { @@ -213,7 +400,7 @@ void AssetManager::ParseBlockModels() { TextureCoord texture; textureName = face.second.texture; if (model.Textures.empty()) { - texture = GetTexture("minecraft/texture/blocks/tnt_side"); + texture = AssetManager::GetTexture("minecraft/texture/blocks/tnt_side"); } else { while (textureName[0] == '#') { @@ -222,7 +409,7 @@ void AssetManager::ParseBlockModels() { textureName = textureIt != model.Textures.end() ? textureIt->second : "minecraft/texture/blocks/tnt_side"; } textureName.insert(0, "minecraft/textures/"); - texture = GetTexture(textureName); + texture = AssetManager::GetTexture(textureName); if (!(face.second.uv == BlockModel::ElementData::FaceData::Uv{ 0,16,0,16 }) && !(face.second.uv == BlockModel::ElementData::FaceData::Uv{ 0,0,0,0 }) && !(face.second.uv == BlockModel::ElementData::FaceData::Uv{ 0,0,16,16 })) { @@ -257,164 +444,65 @@ void AssetManager::ParseBlockModels() { } }; - RecursiveWalkAsset("/minecraft/models/", parseBlockModel); + AssetManager::RecursiveWalkAsset("/minecraft/models/", parseBlockModel); } -void WalkDirEntry(const fs::directory_entry &dirEntry, AssetTreeNode *node) { - for (auto &file : fs::directory_iterator(dirEntry)) { - node->childs.push_back(std::make_unique<AssetTreeNode>()); - AssetTreeNode *fileNode = node->childs.back().get(); - fileNode->parent = node; - fileNode->name = file.path().stem().string(); - if (fs::is_directory(file)) { - WalkDirEntry(file, fileNode); - } else { - size_t fileSize = fs::file_size(file); - fileNode->data.resize(fileSize); - FILE *f = fopen(file.path().string().c_str(), "rb"); - fread(fileNode->data.data(), 1, fileSize, f); - fclose(f); - } - } -} - -void AssetManager::LoadAssets() { - assetTree = std::make_unique<AssetTreeNode>(); - assetTree->name = "/"; - WalkDirEntry(fs::directory_entry(pathToAssets), assetTree.get()); -} - -void AssetManager::ParseAssetBlockModel(AssetTreeNode &node) { - nlohmann::json modelData = nlohmann::json::parse(node.data); - BlockModel model; - - if (node.name == "button") { - int a = 15; - a++; - } - - if (modelData.find("parent") != modelData.end()) { - std::string parentName = modelData["parent"].get<std::string>(); - parentName = parentName.substr(parentName.find('/') + 1); - for (auto &it : node.parent->childs) { - if (it->name == parentName) { - ParseAsset(*it); - model = dynamic_cast<AssetBlockModel*>(it->asset.get())->blockModel; - unsigned char *b = reinterpret_cast<unsigned char*>(&model.IsBlock); - } - } - } - - model.BlockName = node.name; - - if (model.BlockName == "block") - model.IsBlock = true; - - if (model.BlockName == "thin_block" || model.BlockName == "leaves") - model.IsBlock = false; - - if (modelData.find("ambientocclusion") != modelData.end()) - model.AmbientOcclusion = modelData["ambientocclusion"].get<bool>(); - - //models.Display - - if (modelData.find("textures") != modelData.end()) { - for (nlohmann::json::iterator texture = modelData["textures"].begin(); texture != modelData["textures"].end(); ++texture) { - model.Textures[texture.key()] = texture.value().get<std::string>(); - } - } - - if (modelData.find("elements") != modelData.end()) { - model.Elements.clear(); - for (auto& it : modelData["elements"]) { - BlockModel::ElementData element; - - auto vec = it["from"]; - Vector from(vec[0].get<int>(), vec[1].get<int>(), vec[2].get<int>()); - vec = it["to"]; - Vector to(vec[0].get<int>(), vec[1].get<int>(), vec[2].get<int>()); - - element.from = from; - element.to = to; - - if (it.find("rotation") != it.end()) { - vec = it["rotation"]["origin"]; - Vector rotOrig(vec[0].get<int>(), vec[1].get<int>(), vec[2].get<int>()); - - element.rotationOrigin = rotOrig; - element.rotationAxis = (it["rotation"]["axis"].get<std::string>() == "x") ? BlockModel::ElementData::Axis::x : ((it["rotation"]["axis"].get<std::string>() == "y") ? BlockModel::ElementData::Axis::y : BlockModel::ElementData::Axis::z); - if (it["rotation"].find("angle") != it["rotation"].end()) - element.rotationAngle = it["rotation"]["angle"].get<int>(); - - if (it["rotation"].find("rescale") != it["rotation"].end()) - element.rotationRescale = it["rotation"]["rescale"].get<bool>(); - } - - if (it.find("shade") != it.end()) - element.shade = it["shade"].get<bool>(); - - for (nlohmann::json::iterator faceIt = it["faces"].begin(); faceIt != it["faces"].end(); ++faceIt) { - auto face = faceIt.value(); - BlockModel::ElementData::FaceData faceData; - - BlockModel::ElementData::FaceDirection faceDir; - if (faceIt.key() == "down") - faceDir = BlockModel::ElementData::FaceDirection::down; - else if (faceIt.key() == "up") - faceDir = BlockModel::ElementData::FaceDirection::up; - else if (faceIt.key() == "north") - faceDir = BlockModel::ElementData::FaceDirection::north; - else if (faceIt.key() == "south") - faceDir = BlockModel::ElementData::FaceDirection::south; - else if (faceIt.key() == "west") - faceDir = BlockModel::ElementData::FaceDirection::west; - else if (faceIt.key() == "east") - faceDir = BlockModel::ElementData::FaceDirection::east; - - if (face.find("uv") != face.end()) { - BlockModel::ElementData::FaceData::Uv uv; - uv.x1 = face["uv"][0]; - uv.y1 = face["uv"][1]; - uv.x2 = face["uv"][2]; - uv.y2 = face["uv"][3]; - faceData.uv = uv; - } +const BlockModel *AssetManager::GetBlockModelByBlockId(BlockId block) { + block.state = 0; + if (blockIdToBlockName.find(block) == blockIdToBlockName.end()) { + std::string blockName = ""; + for (const auto& it : assetIds) { + if (BlockId{ it.second.id,0 } == block) { + blockName = it.first; + break; + } + } + if (blockName == "grass") + blockName = "grass_normal"; + if (blockName == "torch") + blockName = "normal_torch"; + if (blockName == "leaves") + blockName = "oak_leaves"; + if (blockName == "tallgrass") + blockName = "tall_grass"; + if (blockName == "log") + blockName = "oak_bark"; + if (blockName == "snow_layer") + blockName = "snow_height2"; - BlockModel::ElementData::FaceDirection cullface = BlockModel::ElementData::FaceDirection::none; - if (face.find("cullface") != face.end()) { - if (face["cullface"] == "down") - cullface = BlockModel::ElementData::FaceDirection::down; - else if (face["cullface"] == "up") - cullface = BlockModel::ElementData::FaceDirection::up; - else if (face["cullface"] == "north") - cullface = BlockModel::ElementData::FaceDirection::north; - else if (face["cullface"] == "south") - cullface = BlockModel::ElementData::FaceDirection::south; - else if (face["cullface"] == "west") - cullface = BlockModel::ElementData::FaceDirection::west; - else if (face["cullface"] == "east") - cullface = BlockModel::ElementData::FaceDirection::east; - } - faceData.cullface = cullface; + blockName = "block/" + blockName; - faceData.texture = face["texture"].get<std::string>(); + if (blockName == "") + return nullptr; - if (face.find("rotation") != face.end()) - faceData.rotation = face["rotation"].get<int>(); + blockIdToBlockName[block] = blockName; + } - if (face.find("tintindex") != face.end()) - faceData.tintIndex = true; + std::string blockName = blockIdToBlockName[block]; - element.faces[faceDir] = faceData; - } + AssetBlockModel *model = GetAsset<AssetBlockModel>("/minecraft/models/" + blockName); + return (model == nullptr) ? &GetAsset<AssetBlockModel>("/minecraft/models/block/diamond_block")->blockModel : &model->blockModel; +} - model.Elements.push_back(element); - } - } +std::string AssetManager::GetAssetNameByBlockId(BlockId block) { + for (auto& it : assetIds) { + BlockId value = it.second; + value.state = 0; + if (value == block) + return it.first; + } + return "#NF"; +} - node.asset = std::make_unique<AssetBlockModel>(); - dynamic_cast<AssetBlockModel*>(node.asset.get())->blockModel = model; - node.data.swap(std::vector<unsigned char>()); +Asset *AssetManager::GetAssetPtr(const std::string & assetName) { + AssetTreeNode *node; + if (assetName[0] != '/') + node = GetAssetByAssetName('/' + assetName); + else + node = GetAssetByAssetName(assetName); + if (!node) + return nullptr; + return node->asset.get(); } void AssetManager::RecursiveWalkAsset(const std::string & assetPath, std::function<void(AssetTreeNode&)> fnc) { @@ -430,7 +518,7 @@ void AssetManager::RecursiveWalkAsset(const std::string & assetPath, std::functi walkAssetRecur(*assetNode); } -AssetTreeNode * AssetManager::GetAssetByAssetName(const std::string & assetName) { +AssetTreeNode *AssetManager::GetAssetByAssetName(const std::string & assetName) { AssetTreeNode *node = assetTree.get(); unsigned int pos = 1; unsigned int prevPos = 1; @@ -450,68 +538,14 @@ AssetTreeNode * AssetManager::GetAssetByAssetName(const std::string & assetName) return node; } -void AssetManager::LoadTextures() { - std::vector<TextureData> textureData; - size_t id = 0; - RecursiveWalkAsset("/minecraft/textures/", [&](AssetTreeNode &node) { - TextureData data; - AssetTexture *textureAsset = dynamic_cast<AssetTexture*>(node.asset.get()); - if (!textureAsset) - return; - data.data = std::move(textureAsset->textureData); - data.width = textureAsset->realWidth; - data.height = textureAsset->realHeight; - textureData.push_back(data); - textureAsset->id = id++; - }); - atlas = std::make_unique<TextureAtlas>(textureData); +GLuint AssetManager::GetTextureAtlasId() +{ + return atlas->GetRawTextureId(); } -void AssetManager::ParseAssetTexture(AssetTreeNode &node) { - SDL_RWops *rw = SDL_RWFromMem(node.data.data(), node.data.size()); - SDL_Surface *surface = IMG_LoadPNG_RW(rw); - - SDL_RWclose(rw); - if (!surface) { - return; - } - - if (surface->format->format != SDL_PIXELFORMAT_RGBA8888) { - SDL_Surface *temp = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGBA8888, 0); - std::swap(temp, surface); - if (!temp) { - std::swap(temp, surface); - } - SDL_FreeSurface(temp); - } - - SDL_LockSurface(surface); - - node.asset = std::make_unique<AssetTexture>(); - AssetTexture *asset = dynamic_cast<AssetTexture*>(node.asset.get()); - size_t dataLen = surface->h * surface->pitch; - asset->textureData.resize(dataLen); - std::memcpy(asset->textureData.data(), surface->pixels, dataLen); - asset->realWidth = surface->w; - asset->realHeight = surface->h; - - SDL_UnlockSurface(surface); - SDL_FreeSurface(surface); - - node.data.swap(std::vector<unsigned char>()); +TextureCoord AssetManager::GetTexture(const std::string assetName) { + AssetTexture *asset = GetAsset<AssetTexture>(assetName); + if (!asset) + return {}; + return atlas->GetTexture(asset->id); } - -void AssetManager::ParseAsset(AssetTreeNode &node) { - if (node.data.empty() || node.asset) - return; - - if (node.parent->name == "block" && node.parent->parent->name == "models") { - ParseAssetBlockModel(node); - return; - } - - if (node.data[0] == 0x89 && node.data[1] == 'P' && node.data[2] == 'N' && node.data[3] == 'G') { - ParseAssetTexture(node); - return; - } -}
\ No newline at end of file |