diff --git a/editor/includes/converters/assimpconverter.h b/editor/includes/converters/assimpconverter.h index bca9eba66..052199adf 100644 --- a/editor/includes/converters/assimpconverter.h +++ b/editor/includes/converters/assimpconverter.h @@ -116,9 +116,9 @@ class AssimpConverter : public AssetConverter { Actor *createActor(const AssetConverterSettings *settings, const TString &guid) const override; - Actor *importObject(const aiScene *scene, const aiNode *element, Actor *parent, AssimpImportSettings *fbxSettings); + Actor *importObject(const aiScene *scene, const aiNode *element, AssimpImportSettings *fbxSettings, Actor *parent); - static Mesh *importMesh(const aiScene *scene, const aiNode *element, Actor *actor, AssimpImportSettings *fbxSettings); + static Mesh *importMesh(const aiScene *scene, const aiNode *element, AssimpImportSettings *fbxSettings, Actor *actor, int32_t lod); static void importAnimation(const aiScene *scene, AssimpImportSettings *fbxSettings); diff --git a/editor/includes/editor/assetconverter.h b/editor/includes/editor/assetconverter.h index 3af97431e..b90149511 100644 --- a/editor/includes/editor/assetconverter.h +++ b/editor/includes/editor/assetconverter.h @@ -118,6 +118,8 @@ class EDITOR_EXPORT AssetConverterSettings : public Object { std::list> &changedUuids(); void clearChangedUuids(); + TString fixUuid(const TString &uuid, const TString &type, int lod, bool solve = true); + protected: virtual TString propertyAllias(const TString &name) const; @@ -125,8 +127,6 @@ class EDITOR_EXPORT AssetConverterSettings : public Object { void setVersion(uint32_t version); - TString fixUuid(const TString &uuid, const TString &type, int lod, bool solve = true); - static QImage renderDocumentIcon(const TString &path, const TString &color = TString("#0277bd")); protected: diff --git a/editor/includes/editor/assetmanager.h b/editor/includes/editor/assetmanager.h index 35860f54f..d8d9fb522 100644 --- a/editor/includes/editor/assetmanager.h +++ b/editor/includes/editor/assetmanager.h @@ -107,8 +107,6 @@ protected slots: BaseAssetProvider *m_assetProvider; - ResourceSystem::Dictionary &m_indices; - QTimer *m_timer; bool m_force; diff --git a/editor/src/converters/assimpconverter.cpp b/editor/src/converters/assimpconverter.cpp index d26568465..facf66520 100644 --- a/editor/src/converters/assimpconverter.cpp +++ b/editor/src/converters/assimpconverter.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "components/actor.h" #include "components/armature.h" @@ -258,7 +259,7 @@ AssetConverter::ReturnCode AssimpConverter::convertFile(AssetConverterSettings * } /// \todo We need to reuse actors if possible - Actor *root = importObject(scene, scene->mRootNode, nullptr, fbxSettings); + Actor *root = importObject(scene, scene->mRootNode, fbxSettings, nullptr); prefab->setActor(root); @@ -291,15 +292,33 @@ AssetConverter::ReturnCode AssimpConverter::convertFile(AssetConverterSettings * } Actor *importObjectHelper(const aiScene *scene, const aiNode *element, const aiMatrix4x4 &p, Actor *parent, AssimpImportSettings *fbxSettings) { - std::string name = element->mName.C_Str(); + TString name = element->mName.C_Str(); - if(name.find("$") != std::string::npos) { + if(name.contains("$")) { for(uint32_t c = 0; c < element->mNumChildren; c++) { importObjectHelper(scene, element->mChildren[c], p * element->mTransformation, parent, fbxSettings); } } else { - Actor *actor = Engine::objectCreate(name, parent); - Transform *transform = static_cast(actor->addComponent("Transform")); + uint32_t lod = 0; + StringList pair = name.split("_lod"); + if(pair.size() == 2) { + name = pair.front(); + lod = pair.back().toInt(); + } + + Actor *actor = nullptr; + Transform *transform = nullptr; + + auto it = fbxSettings->m_actors.find(name); + if(it != fbxSettings->m_actors.end()) { + actor = it->second; + transform = actor->transform(); + } else { + actor = Engine::objectCreate(name, parent); + transform = static_cast(actor->addComponent("Transform")); + + fbxSettings->m_actors[name] = actor; + } if(fbxSettings->m_rootActor == nullptr) { fbxSettings->m_rootActor = actor; @@ -314,8 +333,6 @@ Actor *importObjectHelper(const aiScene *scene, const aiNode *element, const aiM } } - fbxSettings->m_actors[actor->name()] = actor; - aiMatrix4x4 t = p * element->mTransformation; aiVector3D scale, euler, position; @@ -330,19 +347,16 @@ Actor *importObjectHelper(const aiScene *scene, const aiNode *element, const aiM transform->setRotation(Vector3(euler.x, euler.y, euler.z) * RAD2DEG); transform->setScale(Vector3(scale.x, scale.y, scale.z)); - Mesh *result = AssimpConverter::importMesh(scene, element, actor, fbxSettings); - if(result) { + Mesh *result = AssimpConverter::importMesh(scene, element, fbxSettings, actor, lod); + if(result && lod == 0) { + MeshRender *render = nullptr; if(!result->weights().empty()) { - SkinnedMeshRender *render = static_cast(actor->addComponent("SkinnedMeshRender")); - - render->setMesh(result); - fbxSettings->m_renders.push_back(render); + render = static_cast(actor->addComponent("SkinnedMeshRender")); } else { - MeshRender *render = static_cast(actor->addComponent("MeshRender")); - - render->setMesh(result); - fbxSettings->m_renders.push_back(render); + render = static_cast(actor->addComponent("MeshRender")); } + render->setMesh(result); + fbxSettings->m_renders.push_back(render); } for(uint32_t c = 0; c < element->mNumChildren; c++) { @@ -355,27 +369,21 @@ Actor *importObjectHelper(const aiScene *scene, const aiNode *element, const aiM return nullptr; } -Actor *AssimpConverter::importObject(const aiScene *scene, const aiNode *element, Actor *parent, AssimpImportSettings *fbxSettings) { +Actor *AssimpConverter::importObject(const aiScene *scene, const aiNode *element, AssimpImportSettings *fbxSettings, Actor *parent) { aiMatrix4x4 m; return importObjectHelper(scene, element, m, parent, fbxSettings); } -Mesh *AssimpConverter::importMesh(const aiScene *scene, const aiNode *element, Actor *actor, AssimpImportSettings *fbxSettings) { +Mesh *AssimpConverter::importMesh(const aiScene *scene, const aiNode *element, AssimpImportSettings *fbxSettings, Actor *actor, int32_t lod) { if(element->mNumMeshes) { uint32_t hash = 16; for(uint32_t index = 0; index < element->mNumMeshes; index++) { Mathf::hashCombine(hash, element->mMeshes[index]); } - Mesh *mesh = nullptr; - auto it = fbxSettings->m_meshes.find(hash); if(it != fbxSettings->m_meshes.end()) { - mesh = it->second; - } - - if(mesh) { - return mesh; + return it->second; } size_t total_v = 0; @@ -385,7 +393,11 @@ Mesh *AssimpConverter::importMesh(const aiScene *scene, const aiNode *element, A size_t count_i = 0; ResourceSystem::ResourceInfo info = fbxSettings->subItem(actor->name(), MetaType::name()); + if(lod > 0) { + info.uuid = fbxSettings->fixUuid(info.uuid, info.type, lod, false); + } + Mesh *mesh = nullptr; for(uint32_t index = 0; index < element->mNumMeshes; index++) { const aiMesh *item = scene->mMeshes[element->mMeshes[index]]; @@ -621,7 +633,11 @@ Mesh *AssimpConverter::importMesh(const aiScene *scene, const aiNode *element, A AssetConverter::ReturnCode result = fbxSettings->saveBinary(Engine::toVariant(mesh), dst.absoluteDir() + "/" + info.uuid); if(result == AssetConverter::Success) { info.id = mesh->uuid(); - fbxSettings->setSubItem(actor->name(), info); + TString name(actor->name()); + if(lod > 0) { + name += TString("_lod%1").arg(TString::number(lod)); + } + fbxSettings->setSubItem(name, info, lod); } fbxSettings->m_meshes[hash] = mesh; diff --git a/editor/src/editor/assetconverter.cpp b/editor/src/editor/assetconverter.cpp index 37dbdaa69..b37d1c65d 100644 --- a/editor/src/editor/assetconverter.cpp +++ b/editor/src/editor/assetconverter.cpp @@ -230,9 +230,11 @@ TString AssetConverterSettings::fixUuid(const TString &uuid, const TString &type if(!result.isNull()) { int index = Engine::resourceSystem()->indexOf(type) + 1; ByteArray array = result.toByteArray(); - array[0] = index; - array[1] = (array[1] & 0x0F) | ((lod & 0x0F) << 4); - result.fromByteArray(array); + if(array[0] != index) { + array[0] = index; + array[1] = (array[1] & 0x0F) | ((lod & 0x0F) << 4); + result.fromByteArray(array); + } } TString str(result.toString()); @@ -373,6 +375,8 @@ ResourceSystem::ResourceInfo AssetConverterSettings::subItem(const TString &key, ResourceSystem::ResourceInfo info; info.type = type; info.uuid = fixUuid(Uuid::createUuid().toString(), info.type, 0, false); + info.md5 = m_info.md5; + info.bundle = m_info.bundle; return info; } return ResourceSystem::ResourceInfo(); @@ -383,7 +387,7 @@ ResourceSystem::ResourceInfo AssetConverterSettings::subItem(const TString &key, void AssetConverterSettings::setSubItem(const TString &name, const ResourceSystem::ResourceInfo &info, int lod) { if(!name.isEmpty() && !info.uuid.isEmpty()) { ResourceSystem::ResourceInfo fixedInfo(info); - fixedInfo.uuid = fixUuid(fixedInfo.uuid, fixedInfo.type, 0); + fixedInfo.uuid = fixUuid(fixedInfo.uuid, fixedInfo.type, lod); m_subItems[name] = {fixedInfo, QImage(), false}; } diff --git a/editor/src/editor/assetmanager.cpp b/editor/src/editor/assetmanager.cpp index 02323cb74..24428f62e 100644 --- a/editor/src/editor/assetmanager.cpp +++ b/editor/src/editor/assetmanager.cpp @@ -45,7 +45,6 @@ namespace { AssetManager::AssetManager() : m_assetProvider(new BaseAssetProvider), - m_indices(Engine::resourceSystem()->indices()), m_timer(new QTimer(this)), m_force(false) { @@ -410,13 +409,14 @@ TString AssetManager::uuidToPath(const TString &uuid) const { } TString AssetManager::pathToUuid(const TString &path) const { - auto it = m_indices.find(path); - if(it != m_indices.end()) { - return it->second.uuid; + ResourceSystem::Aliases &aliases = Engine::resourceSystem()->aliases(); + auto it = aliases.find(path); + if(it != aliases.end()) { + return it->second; } - it = m_indices.find(pathToLocal(path)); - if(it != m_indices.end()) { - return it->second.uuid; + it = aliases.find(pathToLocal(path)); + if(it != aliases.end()) { + return it->second; } return TString(); @@ -452,9 +452,9 @@ void AssetManager::dumpBundle() { VariantMap root; VariantMap paths; - for(auto &it : m_indices) { + for(auto &it : Engine::resourceSystem()->indices()) { VariantList item; - item.push_back(it.first); + item.push_back(pathToLocal(uuidToPath(it.first))); item.push_back(it.second.type); item.push_back(it.second.md5); item.push_back(static_cast(it.second.id)); @@ -522,10 +522,11 @@ void AssetManager::onPerform() { } } - auto tmp = m_indices; + ResourceSystem::Dictionary &indices = Engine::resourceSystem()->indices(); + auto tmp = indices; for(auto &index : tmp) { if(index.second.uuid.isEmpty() || (!File::exists(ProjectSettings::instance()->importPath() + "/" + index.second.uuid))) { - m_indices.erase(m_indices.find(index.first)); + indices.erase(index.second.uuid); } } @@ -615,7 +616,11 @@ void AssetManager::registerAsset(const TString &source, const ResourceSystem::Re if(File::exists(ProjectSettings::instance()->importPath() + "/" + info.uuid)) { TString path = pathToLocal(source); - m_indices[path] = info; + ResourceSystem::Dictionary &indices = Engine::resourceSystem()->indices(); + indices[info.uuid] = info; + ResourceSystem::Aliases &aliases = Engine::resourceSystem()->aliases(); + aliases[path] = info.uuid; + m_paths[info.uuid] = source; m_labels.insert(info.type); @@ -623,18 +628,16 @@ void AssetManager::registerAsset(const TString &source, const ResourceSystem::Re } TString AssetManager::unregisterAsset(const TString &source) { - TString path = pathToLocal(source); - auto it = m_indices.find(path); - if(it != m_indices.end()) { - auto pathIt = m_paths.find(it->second.uuid); - if(pathIt != m_paths.end() && !pathIt->second.isEmpty()) { - TString uuid(it->second.uuid); + TString uuid(pathToUuid(source)); + if(!uuid.isEmpty()) { + ResourceSystem::Dictionary &indices = Engine::resourceSystem()->indices(); + indices.erase(uuid); + ResourceSystem::Aliases &aliases = Engine::resourceSystem()->aliases(); + aliases.erase(pathToLocal(source)); + m_paths.erase(uuid); - m_indices.erase(it); - m_paths.erase(pathIt); - - return uuid; - } + return uuid; } + return TString(); } diff --git a/editor/src/viewport/viewport.cpp b/editor/src/viewport/viewport.cpp index a3f044433..903c6e0ad 100644 --- a/editor/src/viewport/viewport.cpp +++ b/editor/src/viewport/viewport.cpp @@ -200,6 +200,8 @@ void Viewport::onDraw() { } Engine::instance().processEvents(); + Engine::resourceSystem()->setActiveWorld(m_world); + Engine::resourceSystem()->processEvents(); Engine::renderSystem()->setActiveWorld(m_world); Engine::renderSystem()->processEvents(); } diff --git a/engine/includes/components/meshrender.h b/engine/includes/components/meshrender.h index 620db33de..e14fb79ec 100644 --- a/engine/includes/components/meshrender.h +++ b/engine/includes/components/meshrender.h @@ -5,6 +5,8 @@ #include +#include + class Material; class MaterialInstance; @@ -39,12 +41,17 @@ class ENGINE_EXPORT MeshRender : public Renderable { void composeComponent() override; - Mesh *ensureMeshInstance(); + bool ensureMeshInstance(); + + void updateBlendShapes(); protected: std::vector m_blendShapeWeights; + std::array, 3> m_lods; + + TString m_meshRef; - Mesh *m_mesh; + Mesh *m_baseMesh; Mesh *m_meshInstance; }; diff --git a/engine/includes/components/renderable.h b/engine/includes/components/renderable.h index 87eccd9aa..8629be2e7 100644 --- a/engine/includes/components/renderable.h +++ b/engine/includes/components/renderable.h @@ -5,9 +5,6 @@ #include -class CommandBuffer; -class PipelineContext; - class Mesh; class Material; class MaterialInstance; @@ -58,6 +55,8 @@ class ENGINE_EXPORT Renderable : public NativeBehaviour { virtual AABBox localBound(); + virtual void setLod(uint32_t lod); + virtual void setMaterialsList(const std::list &materials); void applyBlendShapeWeights(Mesh &mesh, Mesh &instance, const std::vector &weights); diff --git a/engine/includes/systems/resourcesystem.h b/engine/includes/systems/resourcesystem.h index ee43e11dd..9fa68bb4e 100644 --- a/engine/includes/systems/resourcesystem.h +++ b/engine/includes/systems/resourcesystem.h @@ -17,8 +17,8 @@ class ENGINE_EXPORT ResourceSystem : public System { uint32_t id = 0; }; - typedef std::unordered_map Dictionary; + typedef std::unordered_map Aliases; typedef void (*BundleUpdatedCallback)(const TString &path, bool unload, void *object); @@ -29,9 +29,9 @@ class ENGINE_EXPORT ResourceSystem : public System { bool loadBundle(const TString &path); bool unloadBundle(const TString &path); - Resource *loadResource(const TString &path); + Resource *loadResource(const TString &path, uint32_t lod = 0); - Resource *loadResourceAsync(const TString &path); + Resource *loadResourceAsync(const TString &path, uint32_t lod = 0); void unloadResource(Resource *resource, bool force = false); @@ -48,6 +48,7 @@ class ENGINE_EXPORT ResourceSystem : public System { void setResource(Resource *object, const TString &uuid); Dictionary &indices(); + Aliases &aliases(); void deleteFromCahe(Resource *resource); @@ -75,6 +76,7 @@ class ENGINE_EXPORT ResourceSystem : public System { std::list> m_observers; ResourceSystem::Dictionary m_indexMap; + ResourceSystem::Aliases m_aliases; std::unordered_map m_resourceCache; std::unordered_map m_referenceCache; diff --git a/engine/src/components/meshrender.cpp b/engine/src/components/meshrender.cpp index 792c55a59..284780705 100644 --- a/engine/src/components/meshrender.cpp +++ b/engine/src/components/meshrender.cpp @@ -2,6 +2,8 @@ #include "resources/material.h" +#include "systems/resourcesystem.h" + #include "pipelinecontext.h" #include "gizmos.h" @@ -14,13 +16,21 @@ */ MeshRender::MeshRender() : - m_mesh(nullptr), + m_baseMesh(nullptr), m_meshInstance(nullptr) { + for(auto &it : m_lods) { + it.first = nullptr; + it.second = false; + } } MeshRender::~MeshRender() { - if(m_mesh) { - m_mesh->decRef(); + for(auto &it : m_lods) { + if(it.first) { + it.first->decRef(); + it.first = nullptr; + } + it.second = false; } if(m_meshInstance) { @@ -35,14 +45,33 @@ Mesh *MeshRender::meshToDraw() { if(m_meshInstance) { return m_meshInstance; } - return m_mesh; + + Mesh *lastMesh = m_baseMesh; + for(int32_t i = 2; i >= static_cast(m_lod); --i) { + if(m_lods[i].first) { + Resource::State state = m_lods[i].first->state(); + if(state >= Resource::ToBeUpdated && state <= Resource::Ready) { + lastMesh = m_lods[i].first; + } + } else if(i == m_lod && !m_lods[i].second) { + ResourceSystem *system = Engine::resourceSystem(); + m_lods[i].first = dynamic_cast(system->loadResourceAsync(m_meshRef, i)); + m_lods[i].second = true; + if(m_lods[i].first) { + m_lods[i].first->incRef(); + lastMesh = m_lods[i].first; + } + } + } + + return lastMesh; } /*! \internal */ AABBox MeshRender::localBound() { - if(m_mesh) { - return m_mesh->bound(); + if(m_baseMesh) { + return m_baseMesh->bound(); } return Renderable::localBound(); } @@ -50,15 +79,19 @@ AABBox MeshRender::localBound() { Returns a Mesh assigned to this component. */ Mesh *MeshRender::mesh() const { - return m_mesh; + return m_baseMesh; } /*! Assigns a new \a mesh to draw. */ void MeshRender::setMesh(Mesh *mesh) { - if(m_mesh != mesh) { - if(m_mesh) { - m_mesh->decRef(); + if(m_baseMesh != mesh) { + for(auto &it : m_lods) { + if(it.first) { + it.first->decRef(); + it.first = nullptr; + } + it.second = false; } if(m_meshInstance) { @@ -66,19 +99,24 @@ void MeshRender::setMesh(Mesh *mesh) { m_meshInstance = nullptr; } - m_mesh = mesh; - m_blendShapeWeights.clear(); - if(m_mesh) { - m_mesh->incRef(); + m_baseMesh = mesh; + if(m_baseMesh) { + m_baseMesh->incRef(); + + m_meshRef = Engine::reference(m_baseMesh); + + updateBlendShapes(); if(m_materials.empty()) { std::list materials; - for(int i = 0; i < m_mesh->subMeshCount(); i++) { - materials.push_back(m_mesh->defaultMaterial(i)); + for(int i = 0; i < m_baseMesh->subMeshCount(); i++) { + materials.push_back(m_baseMesh->defaultMaterial(i)); } setMaterialsList(materials); } + } else { + m_meshRef.clear(); } } } @@ -100,11 +138,7 @@ void MeshRender::setBlendShapeWeight(size_t index, float weight) { } m_blendShapeWeights[index] = weight; - if(m_mesh && m_mesh->blendShapeCount() > index) { - if(ensureMeshInstance()) { - applyBlendShapeWeights(*m_mesh, *m_meshInstance, m_blendShapeWeights); - } - } + updateBlendShapes(); } /*! Returns a list of assigned materials. @@ -149,23 +183,33 @@ void MeshRender::composeComponent() { /*! \internal */ -Mesh *MeshRender::ensureMeshInstance() { - if(m_mesh == nullptr) { - return nullptr; +bool MeshRender::ensureMeshInstance() { + if(m_lods[m_lod].first == nullptr) { + return false; } if(m_meshInstance == nullptr) { m_meshInstance = Engine::objectCreate(); - m_meshInstance->setIndices(m_mesh->indices()); - m_meshInstance->setVertices(m_mesh->vertices()); - m_meshInstance->setNormals(m_mesh->normals()); - m_meshInstance->setTangents(m_mesh->tangents()); - m_meshInstance->setUv0(m_mesh->uv0()); - m_meshInstance->setUv1(m_mesh->uv1()); - m_meshInstance->setColors(m_mesh->colors()); - m_meshInstance->setBones(m_mesh->bones()); - m_meshInstance->setWeights(m_mesh->weights()); + m_meshInstance->setIndices(m_lods[m_lod].first->indices()); + m_meshInstance->setVertices(m_lods[m_lod].first->vertices()); + m_meshInstance->setNormals(m_lods[m_lod].first->normals()); + m_meshInstance->setTangents(m_lods[m_lod].first->tangents()); + m_meshInstance->setUv0(m_lods[m_lod].first->uv0()); + m_meshInstance->setUv1(m_lods[m_lod].first->uv1()); + m_meshInstance->setColors(m_lods[m_lod].first->colors()); + m_meshInstance->setBones(m_lods[m_lod].first->bones()); + m_meshInstance->setWeights(m_lods[m_lod].first->weights()); } - return m_meshInstance; + return true; +} +/*! + \internal +*/ +void MeshRender::updateBlendShapes() { + if(m_lod < 3 && m_lods[m_lod].first && m_lods[m_lod].first->blendShapeCount() > 0) { + if(ensureMeshInstance()) { + applyBlendShapeWeights(*(m_lods[m_lod].first), *m_meshInstance, m_blendShapeWeights); + } + } } diff --git a/engine/src/components/renderable.cpp b/engine/src/components/renderable.cpp index 52349abcc..7e831258d 100644 --- a/engine/src/components/renderable.cpp +++ b/engine/src/components/renderable.cpp @@ -65,7 +65,7 @@ bool Renderable::isCulled(const Frustum &frustum, const Matrix4 &viewProjection) Vector2 l1(v1.x / v1.w, v1.y / v1.w); float size = (l1 - l0).length(); - m_lod = PipelineContext::lod(size); + setLod(PipelineContext::lod(size)); return !(m_lod < 3); } @@ -146,6 +146,12 @@ void Renderable::setMaterialsList(const std::list &materials) { AABBox Renderable::localBound() { return AABBox(); } +/*! + Sets current \a lod level. +*/ +void Renderable::setLod(uint32_t lod) { + m_lod = lod; +} /*! Filters \a out an \a in renderable components by it's material \a layer. */ diff --git a/engine/src/pipelinecontext.cpp b/engine/src/pipelinecontext.cpp index e743e5d2a..2911ba1ca 100644 --- a/engine/src/pipelinecontext.cpp +++ b/engine/src/pipelinecontext.cpp @@ -344,7 +344,7 @@ Texture *PipelineContext::whiteTexture() { int32_t PipelineContext::lod(float size) { if(size < 0.01f) { return 3; - } else if(size < 0.3f) { + } else if(size < 0.1f) { return 2; } else if(size < 0.6f) { return 1; diff --git a/engine/src/systems/resourcesystem.cpp b/engine/src/systems/resourcesystem.cpp index b63229634..dd81a8659 100644 --- a/engine/src/systems/resourcesystem.cpp +++ b/engine/src/systems/resourcesystem.cpp @@ -101,7 +101,7 @@ bool ResourceSystem::loadBundle(const TString &path) { for(auto &it : root[gContent].toMap()) { VariantList item = it.second.toList(); auto i = item.begin(); - TString path = i->toString(); + TString filePath = i->toString(); i++; TString type = i->toString(); i++; @@ -113,7 +113,8 @@ bool ResourceSystem::loadBundle(const TString &path) { id = static_cast(i->toInt()); } - m_indexMap[path] = {path, type, it.first, md5, id}; + m_indexMap[it.first] = {path, type, it.first, md5, id}; + m_aliases[filePath] = it.first; } for(auto &it : root[gSettings].toMap()) { @@ -139,7 +140,8 @@ bool ResourceSystem::unloadBundle(const TString &path) { auto indexCopy = m_indexMap; for(auto &it : indexCopy) { if(it.second.bundle == path) { - m_indexMap.erase(it.first); + m_indexMap.erase(it.second.uuid); + m_aliases.erase(it.second.uuid); } } @@ -157,15 +159,14 @@ void ResourceSystem::factoryAdd(const TString &name, const TString &url, const M } } -Resource *ResourceSystem::loadResource(const TString &path) { +Resource *ResourceSystem::loadResource(const TString &path, uint32_t lod) { PROFILE_FUNCTION(); if(!path.isEmpty()) { - TString uuid = path; - - Resource *object = resource(uuid); - if(object) { - return object; + TString uuid(path); + Resource *resource = ResourceSystem::resource(uuid); + if(resource) { + return resource; } File fp(uuid); @@ -178,7 +179,7 @@ Resource *ResourceSystem::loadResource(const TString &path) { var = Json::load(TString(data)); } if(var.isValid()) { - Resource *resource = static_cast(Engine::toObject(var, nullptr, uuid)); + resource = static_cast(Engine::toObject(var, nullptr, uuid)); if(resource) { resource->switchState(Resource::ToBeUpdated); } @@ -192,36 +193,38 @@ Resource *ResourceSystem::loadResource(const TString &path) { return nullptr; } -Resource *ResourceSystem::loadResourceAsync(const TString &path) { +Resource *ResourceSystem::loadResourceAsync(const TString &path, uint32_t lod) { if(!path.isEmpty()) { + TString uuid(path); + if(uuid.front() != '{') { + uuid = reference(path); + } + + if(lod > 0 && lod < 16) { + static const char *select = "0123456789abcdef"; + uuid[3] = select[lod]; + } + ResourceInfo info; - auto indexIt = m_indexMap.find(path); + auto indexIt = m_indexMap.find(uuid); if(indexIt != m_indexMap.end()) { info = indexIt->second; - } else { - for(auto &it : m_indexMap) { - if(it.second.uuid == path) { - info = it.second; - break; - } - } - } - - auto resourceIt = m_resourceCache.find(info.uuid); - if(resourceIt != m_resourceCache.end() && resourceIt->second) { - return resourceIt->second; } - Resource *resource = nullptr; - if(!m_clean || File::isFile(info.uuid)) { - if(!info.type.isEmpty()) { - resource = static_cast(Engine::objectCreate(info.type, info.uuid, nullptr, info.id)); - resource->setState(Resource::Loading); + if(!info.uuid.isEmpty()) { + Resource *resource = ResourceSystem::resource(info.uuid); + if(resource == nullptr) { + if(!m_clean || File::isFile(info.uuid)) { + if(!info.type.isEmpty()) { + resource = static_cast(Engine::objectCreate(info.type, info.uuid, nullptr, info.id)); + resource->setState(Resource::Loading); + } + } } - } - return resource; + return resource; + } } return nullptr; } @@ -261,16 +264,21 @@ void ResourceSystem::releaseAll() { bool ResourceSystem::isResourceExist(const TString &path) const { PROFILE_FUNCTION(); - auto it = m_indexMap.find(path); + TString uuid(path); + if(uuid.front() != '{') { + uuid = reference(path); + } + + auto it = m_indexMap.find(uuid); return (it != m_indexMap.end()); } TString ResourceSystem::reference(const TString &path) const { PROFILE_FUNCTION(); - auto it = m_indexMap.find(path); - if(it != m_indexMap.end()) { - return it->second.uuid; + auto it = m_aliases.find(path); + if(it != m_aliases.end()) { + return it->second; } return path; } @@ -288,6 +296,10 @@ ResourceSystem::Dictionary &ResourceSystem::indices() { return m_indexMap; } +ResourceSystem::Aliases &ResourceSystem::aliases() { + return m_aliases; +} + void ResourceSystem::deleteFromCahe(Resource *resource) { PROFILE_FUNCTION(); auto ref = m_referenceCache.find(resource); @@ -338,7 +350,9 @@ void ResourceSystem::unsubscribe(void *object) { } Resource *ResourceSystem::resource(TString &path) const { - path = reference(path); + if(path.front() != '{') { + path = reference(path); + } auto it = m_resourceCache.find(path); if(it != m_resourceCache.end() && it->second) {