Extra2D/include/assets/assets_module.h

400 lines
11 KiB
C
Raw Normal View History

#pragma once
#include <event/events.h>
#include <module/module.h>
#include <module/module_registry.h>
#include <assets/handle.h>
#include <assets/asset_storage.h>
#include <assets/asset_loader.h>
#include <renderer/texture.h>
#include <renderer/shader.h>
#include <renderer/material.h>
#include <renderer/mesh.h>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
namespace extra2d {
/**
* @brief ECS
*
* Bevy/Amethyst
* - AssetStorage:
* - load<T>():
* - Handle<T>:
*/
class AssetsModule : public Module {
E2D_REGISTER_MODULE(AssetsModule, "Assets", 2)
public:
AssetsModule();
~AssetsModule() override;
bool init() override;
void shutdown() override;
/**
* @brief OpenGL
*/
void onGLContextReady();
//===========================================================================
// 核心加载接口(模板方法,主流设计)
//===========================================================================
/**
* @brief
*
*
* @code
* Handle<Texture> tex = assets->load<Texture>("player.png");
* Handle<Shader> shader = assets->load<Shader>("sprite.vert", "sprite.frag");
* @endcode
*
* @tparam T
* @param path
* @return
*/
template<typename T, typename... Args>
Handle<T> load(const std::string& path, Args&&... args);
/**
* @brief
* @tparam T
* @param key
* @param data
* @param size
* @return
*/
template<typename T>
Handle<T> loadFromMemory(const std::string& key, const uint8_t* data, size_t size);
/**
* @brief nullptr
*
*
* @code
* Texture* tex = assets->get(handle);
* if (tex) {
* tex->bind();
* }
* @endcode
*/
template<typename T>
T* get(Handle<T> handle);
/**
* @brief
*/
template<typename T>
Ptr<T> getPtr(Handle<T> handle);
/**
* @brief
*/
template<typename T>
bool isValid(Handle<T> handle) const;
/**
* @brief
*/
template<typename T>
void remove(Handle<T> handle);
//===========================================================================
// 批量加载(目录/包)
//===========================================================================
/**
* @brief
* @tparam T
* @param directory
* @param pattern "*.png"
* @param recursive
* @return
*/
template<typename T>
std::vector<Handle<T>> loadDir(const std::string& directory,
const std::string& pattern = "*",
bool recursive = true);
//===========================================================================
// 异步加载
//===========================================================================
/**
* @brief
* @tparam T
* @param path
* @param callback
*/
template<typename T>
void loadAsync(const std::string& path,
std::function<void(Handle<T>)> callback);
//===========================================================================
// 注册加载器(扩展点)
//===========================================================================
/**
* @brief
* @tparam T
* @param loader
*/
template<typename T>
void registerLoader(std::unique_ptr<AssetLoader<T>> loader);
//===========================================================================
// 默认资源
//===========================================================================
/**
* @brief
* @return
*/
bool createDefaultResources();
/**
* @brief
*/
void destroyDefaultResources();
Handle<Texture> getDefaultTexture();
Handle<Shader> getDefaultShader();
Handle<Material> getDefaultMaterial();
Handle<Mesh> getDefaultQuad();
Texture* getDefaultTexturePtr();
Shader* getDefaultShaderPtr();
Material* getDefaultMaterialPtr();
Mesh* getDefaultQuadPtr();
//===========================================================================
// 热重载
//===========================================================================
/**
* @brief /
* @param enable
*/
void enableHotReload(bool enable);
/**
* @brief
*/
void checkForChanges();
//===========================================================================
// 统计
//===========================================================================
struct Stats {
size_t textureCount = 0;
size_t shaderCount = 0;
size_t materialCount = 0;
size_t meshCount = 0;
};
Stats getStats() const;
private:
// 资源存储
AssetStorage<Texture> textures_;
AssetStorage<Shader> shaders_;
AssetStorage<Material> materials_;
AssetStorage<Mesh> meshes_;
// 加载器
std::unique_ptr<AssetLoader<Texture>> textureLoader_;
std::unique_ptr<AssetLoader<Shader>> shaderLoader_;
// 路径缓存(避免重复加载)
std::unordered_map<std::string, Handle<Texture>> texturePathCache_;
std::unordered_map<std::string, Handle<Shader>> shaderPathCache_;
// 默认资源
Handle<Texture> defaultTexture_;
Handle<Shader> defaultShader_;
Handle<Material> defaultMaterial_;
Handle<Mesh> defaultQuad_;
// 热重载
bool hotReloadEnabled_ = false;
// 线程安全
mutable std::mutex mutex_;
// 事件监听器
std::unique_ptr<events::OnShow::Listener> onShowListener_;
// 标记默认资源是否已创建
bool defaultResourcesCreated_ = false;
};
// 全局访问
AssetsModule* getAssets();
//===========================================================================
// 模板实现
//===========================================================================
template<typename T, typename... Args>
Handle<T> AssetsModule::load(const std::string& path, Args&&... args) {
static_assert(sizeof...(Args) == 0 || sizeof...(Args) == 1,
"load() accepts 0 or 1 additional arguments");
return Handle<T>::invalid();
}
template<>
Handle<Texture> AssetsModule::load<Texture>(const std::string& path);
template<>
Handle<Shader> AssetsModule::load<Shader>(const std::string& path);
template<>
Handle<Shader> AssetsModule::load<Shader>(const std::string& vertPath, const std::string& fragPath);
template<typename T>
Handle<T> AssetsModule::loadFromMemory(const std::string& key, const uint8_t* data, size_t size) {
return Handle<T>::invalid();
}
template<>
Handle<Texture> AssetsModule::loadFromMemory<Texture>(const std::string& key, const uint8_t* data, size_t size);
template<typename T>
T* AssetsModule::get(Handle<T> handle) {
return nullptr;
}
template<>
inline Texture* AssetsModule::get<Texture>(Handle<Texture> handle) {
return textures_.get(handle);
}
template<>
inline Shader* AssetsModule::get<Shader>(Handle<Shader> handle) {
return shaders_.get(handle);
}
template<>
inline Material* AssetsModule::get<Material>(Handle<Material> handle) {
return materials_.get(handle);
}
template<>
inline Mesh* AssetsModule::get<Mesh>(Handle<Mesh> handle) {
return meshes_.get(handle);
}
template<typename T>
Ptr<T> AssetsModule::getPtr(Handle<T> handle) {
return Ptr<T>();
}
template<>
inline Ptr<Texture> AssetsModule::getPtr<Texture>(Handle<Texture> handle) {
return textures_.getPtr(handle);
}
template<>
inline Ptr<Shader> AssetsModule::getPtr<Shader>(Handle<Shader> handle) {
return shaders_.getPtr(handle);
}
template<>
inline Ptr<Material> AssetsModule::getPtr<Material>(Handle<Material> handle) {
return materials_.getPtr(handle);
}
template<>
inline Ptr<Mesh> AssetsModule::getPtr<Mesh>(Handle<Mesh> handle) {
return meshes_.getPtr(handle);
}
template<typename T>
bool AssetsModule::isValid(Handle<T> handle) const {
return false;
}
template<>
inline bool AssetsModule::isValid<Texture>(Handle<Texture> handle) const {
return textures_.isValid(handle);
}
template<>
inline bool AssetsModule::isValid<Shader>(Handle<Shader> handle) const {
return shaders_.isValid(handle);
}
template<>
inline bool AssetsModule::isValid<Material>(Handle<Material> handle) const {
return materials_.isValid(handle);
}
template<>
inline bool AssetsModule::isValid<Mesh>(Handle<Mesh> handle) const {
return meshes_.isValid(handle);
}
template<typename T>
void AssetsModule::remove(Handle<T> handle) {
}
template<>
inline void AssetsModule::remove<Texture>(Handle<Texture> handle) {
textures_.remove(handle);
}
template<>
inline void AssetsModule::remove<Shader>(Handle<Shader> handle) {
shaders_.remove(handle);
}
template<>
inline void AssetsModule::remove<Material>(Handle<Material> handle) {
materials_.remove(handle);
}
template<>
inline void AssetsModule::remove<Mesh>(Handle<Mesh> handle) {
meshes_.remove(handle);
}
template<typename T>
std::vector<Handle<T>> AssetsModule::loadDir(const std::string& directory,
const std::string& pattern,
bool recursive) {
return {};
}
template<>
std::vector<Handle<Texture>> AssetsModule::loadDir<Texture>(const std::string& directory,
const std::string& pattern,
bool recursive);
template<typename T>
void AssetsModule::loadAsync(const std::string& path,
std::function<void(Handle<T>)> callback) {
}
template<>
void AssetsModule::loadAsync<Texture>(const std::string& path,
std::function<void(Handle<Texture>)> callback);
template<typename T>
void AssetsModule::registerLoader(std::unique_ptr<AssetLoader<T>> loader) {
}
template<>
void AssetsModule::registerLoader<Texture>(std::unique_ptr<AssetLoader<Texture>> loader);
template<>
void AssetsModule::registerLoader<Shader>(std::unique_ptr<AssetLoader<Shader>> loader);
} // namespace extra2d