ShitEngine 1.4.2
基于 C++20 与 SDL3 的轻量级 2D 游戏引擎
载入中...
搜索中...
未找到
ResourceManager.h
浏览该文件的文档.
1#pragma once
2
3#include <cstddef>
4#include <cstdint>
5#include <functional>
6#include <string>
7#include <string_view>
8#include <typeindex>
9#include <unordered_map>
10
12#include "ShitEngine/Core/Log.h"
14
15struct SDL_Texture;
16struct MIX_Audio;
17struct TTF_Font;
18struct MIX_Mixer;
19
20namespace Shit {
21
22 // 前向声明:完整定义在 ResourceManager 类之后(traits 工厂需访问其成员)
23 template <typename Res> struct ResourceTraits;
24 template <typename Res> class TypedResourceCache;
25
43 public:
46
51
52 // --- 静态API ---
54 inline static void Init() { GetInstance().init(); }
55 inline static void Destroy() { GetInstance().clear(); }
56
57 // --- 模板门面(Res 须已特化 ResourceTraits,见文件尾部内置三特化) ---
58
62 template <typename Res, typename... Args>
63 static Res* Load(Args&&... args) {
64 typename ResourceTraits<Res>::KeyType key{ std::forward<Args>(args)... };
65 return GetInstance().cacheFor<Res>().getOrLoad(key);
66 }
67
69 template <typename Res, typename... Args>
70 static Res* Find(Args&&... args) {
71 typename ResourceTraits<Res>::KeyType key{ std::forward<Args>(args)... };
72 return GetInstance().cacheFor<Res>().find(key);
73 }
74
76 template <typename Res, typename... Args>
77 static bool Unload(Args&&... args) {
78 typename ResourceTraits<Res>::KeyType key{ std::forward<Args>(args)... };
79 return GetInstance().cacheFor<Res>().unload(key);
80 }
81
83 template <typename Res>
84 static void Clear() { GetInstance().cacheFor<Res>().clear(); }
85
86 // 内部接口(供 AudioPlayer 注入混音器;Audio 的 traits 工厂经 audioMixer() 取用)
87 static void SetAudioMixer(MIX_Mixer* mixer);
88 MIX_Mixer* audioMixer() const { return m_mixer; }
89
90 // --- 资产根 ---
93 static void SetAssetRoot(const std::string& root);
94 static const std::string& GetAssetRoot();
96 static std::string ResolveAssetPath(const std::string& path);
97
99 static Resource* GetResourceByUuid(std::uint64_t uuid);
100
101 private:
102 void init();
103 void clear();
104
107 template <typename Res>
108 TypedResourceCache<Res>& cacheFor() {
109 const std::type_index id(typeid(Res));
110 auto it = m_caches.find(id);
111 if (it == m_caches.end())
112 it = registerCache(id, std::make_unique<TypedResourceCache<Res>>(*this));
113 return static_cast<TypedResourceCache<Res>&>(*it->second);
114 }
115
116 std::unordered_map<std::type_index, std::unique_ptr<TypedCacheBase>>::iterator
117 registerCache(std::type_index id, std::unique_ptr<TypedCacheBase> cache);
118
119 std::unordered_map<std::type_index, std::unique_ptr<TypedCacheBase>> m_caches;
120 MIX_Mixer* m_mixer = nullptr; // 非所有,AudioPlayer 注入/清空
121 std::string m_assetRoot; // 相对资产路径的解析根(空 = 仅进程 cwd)
122 bool m_ttfInitialized = false;
123 };
124
125 // ═══════════════════════════════════════════════════════════
126 // 资源类型 traits —— 扩展点
127 //
128 // 主模板故意不定义:漏特化的类型在 Load<T> 实例化处编译报错
129 //(incomplete type ResourceTraits<T>),防止忘注册。
130 // 内置三特化如下;新资源类型照此模式在自己的头文件/插件里特化即可。
131 // ═══════════════════════════════════════════════════════════
132
133 template <typename Res> struct ResourceTraits;
134
135 template <> struct ResourceTraits<Texture> {
136 using KeyType = std::string;
137 using HashType = std::hash<std::string>;
138 static constexpr std::string_view kTypeName = "纹理";
139 static std::unique_ptr<Texture> create(ResourceManager& owner, const KeyType& key) {
140 return std::make_unique<Texture>(owner.ResolveAssetPath(key));
141 }
142 };
143
144 template <> struct ResourceTraits<Font> {
147 static constexpr std::string_view kTypeName = "字体";
148 static std::unique_ptr<Font> create(ResourceManager& owner, const KeyType& key) {
149 return std::make_unique<Font>(owner.ResolveAssetPath(key.path), key.size);
150 }
151 };
152
153 template <> struct ResourceTraits<Audio> {
154 using KeyType = std::string;
155 using HashType = std::hash<std::string>;
156 static constexpr std::string_view kTypeName = "音频";
157 static std::unique_ptr<Audio> create(ResourceManager& owner, const KeyType& key) {
158 // mixer 注入到新建 Audio(缓存条目的 mixer 指针在 AudioPlayer 生命周期内有效)
159 auto audio = std::make_unique<Audio>(owner.ResolveAssetPath(key));
160 audio->setMixer(owner.audioMixer());
161 return audio;
162 }
163 };
164
171 template <typename Res>
172 class TypedResourceCache final : public TypedCacheBase {
173 public:
176
177 explicit TypedResourceCache(ResourceManager& owner) : m_owner(owner) {}
178
180 Res* getOrLoad(const KeyType& key) {
181 if (auto* hit = find(key)) return hit;
182 ST_CORE_DEBUG("{} {} 未命中缓存,正在加载 ...", ResourceTraits<Res>::kTypeName, logKey(key));
183 std::unique_ptr<Res> res = ResourceTraits<Res>::create(m_owner, key);
184 if (!res || !res->load())
185 return nullptr; // 失败不缓存:下次请求重试
186 Res* ptr = res.get();
187 m_cache.emplace(key, std::move(res));
188 return ptr;
189 }
190
191 Res* find(const KeyType& key) const {
192 if (auto it = m_cache.find(key); it != m_cache.end())
193 return it->second.get();
194 return nullptr;
195 }
196
197 bool unload(const KeyType& key) { return m_cache.erase(key) > 0; }
198
199 void clear() override { m_cache.clear(); }
200 size_t size() const override { return m_cache.size(); }
201 std::string_view typeName() const override { return ResourceTraits<Res>::kTypeName; }
202 void forEachResource(const std::function<void(Resource*)>& fn) const override {
203 for (const auto& [key, res] : m_cache) fn(res.get());
204 }
205
206 private:
207 // 日志键显示:字符串键原样;复合键带区分维度(字体字号),便于排查
208 static const std::string& logKey(const std::string& k) { return k; }
209 static std::string logKey(const FontKey& k) {
210 return k.path + " (" + std::to_string(k.size) + ")";
211 }
212
213 ResourceManager& m_owner;
214 std::unordered_map<KeyType, std::unique_ptr<Res>, HashType> m_cache;
215 };
216}
#define SHIT_API
定义 Core.h:14
#define ST_CORE_DEBUG(...)
定义 Log.h:68
音频:封装 MIX_Audio*(加载需 mixer 就绪,由管理器注入)
定义 Resource.h:110
字体:封装 TTF_Font*(按路径+字号复合键缓存)
定义 Resource.h:93
资源基类 —— 所有引擎资产(Texture / Font / Audio / 自定义类型)的统一封装
定义 Resource.h:36
资源管理器(引擎上下文持有)—— 模板化统一门面
定义 ResourceManager.h:42
static void SetAssetRoot(const std::string &root)
设置资产根目录(空串清除)。相对路径在资产根下存在时按根解析,否则原样 (进程 cwd 语义)。编辑器打开项目时指向项目根,使项目内相对路径可加载。
static bool Unload(Args &&... args)
卸载单个资源(返回是否确实缓存过)
定义 ResourceManager.h:77
static void Clear()
清空某类资源的全部缓存(如 Clear<Audio>())
定义 ResourceManager.h:84
static Res * Find(Args &&... args)
仅查询缓存(命中返回封装,未命中不加载返回 nullptr)
定义 ResourceManager.h:70
static void Init()
定义 ResourceManager.h:54
ResourceManager(ResourceManager &&)=delete
static std::string ResolveAssetPath(const std::string &path)
绝对路径原样返回;相对路径先试资产根(存在才用),否则原样返回
MIX_Mixer * audioMixer() const
定义 ResourceManager.h:88
static void Destroy()
释放所有资源缓存(必须在 SDL_Quit 之前调用)
定义 ResourceManager.h:55
static Resource * GetResourceByUuid(std::uint64_t uuid)
按会话级 uuid 查资源(遍历全部已注册缓存;未命中返回 nullptr)
static Res * Load(Args &&... args)
取或加载(懒加载)。键参数直接构造 ResourceTraits<Res>::KeyType: Load<Texture>("a.png") / Load<Font>("a....
定义 ResourceManager.h:63
static const std::string & GetAssetRoot()
static ResourceManager & GetInstance()
ResourceManager(const ResourceManager &)=delete
ResourceManager & operator=(ResourceManager &&)=delete
static void SetAudioMixer(MIX_Mixer *mixer)
ResourceManager & operator=(const ResourceManager &)=delete
纹理:封装 SDL_Texture*(渲染用;加载需渲染器已初始化)
定义 Resource.h:66
类型擦除缓存接口 —— ResourceManager 按资源类型注册缓存,经此统一遍历/清理
定义 Resource.h:137
类型化缓存 —— 统一「查缓存 → 工厂创建 → 加载 → 插入」模式
定义 ResourceManager.h:172
bool unload(const KeyType &key)
定义 ResourceManager.h:197
typename ResourceTraits< Res >::HashType HashType
定义 ResourceManager.h:175
TypedResourceCache(ResourceManager &owner)
定义 ResourceManager.h:177
typename ResourceTraits< Res >::KeyType KeyType
定义 ResourceManager.h:174
Res * getOrLoad(const KeyType &key)
查缓存命中直接返回;未命中用 traits 工厂创建并 load(),成功才入缓存
定义 ResourceManager.h:180
std::string_view typeName() const override
日志用类型名(来自 ResourceTraits<T>::kTypeName)
定义 ResourceManager.h:201
Res * find(const KeyType &key) const
定义 ResourceManager.h:191
void forEachResource(const std::function< void(Resource *)> &fn) const override
遍历缓存内全部资源封装(uuid 查询用;顺序不保证)
定义 ResourceManager.h:202
size_t size() const override
定义 ResourceManager.h:200
void clear() override
定义 ResourceManager.h:199
定义 AnimationClip.h:12
定义 Resource.h:86
字体缓存键:同字体不同字号各缓存一份
定义 Resource.h:81
std::string path
定义 Resource.h:82
float size
定义 Resource.h:83
static std::unique_ptr< Audio > create(ResourceManager &owner, const KeyType &key)
定义 ResourceManager.h:157
std::hash< std::string > HashType
定义 ResourceManager.h:155
std::string KeyType
定义 ResourceManager.h:154
static constexpr std::string_view kTypeName
定义 ResourceManager.h:156
static std::unique_ptr< Font > create(ResourceManager &owner, const KeyType &key)
定义 ResourceManager.h:148
static constexpr std::string_view kTypeName
定义 ResourceManager.h:147
FontKeyHash HashType
定义 ResourceManager.h:146
FontKey KeyType
定义 ResourceManager.h:145
std::hash< std::string > HashType
定义 ResourceManager.h:137
std::string KeyType
定义 ResourceManager.h:136
static std::unique_ptr< Texture > create(ResourceManager &owner, const KeyType &key)
定义 ResourceManager.h:139
static constexpr std::string_view kTypeName
定义 ResourceManager.h:138
定义 ResourceManager.h:23