docs: sync asset import and material docs
This commit is contained in:
226
docs/api/XCEngine/Core/Asset/ArtifactFormats/ArtifactFormats.md
Normal file
226
docs/api/XCEngine/Core/Asset/ArtifactFormats/ArtifactFormats.md
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
# ArtifactFormats
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `header-overview`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ArtifactFormats.h`
|
||||||
|
|
||||||
|
**描述**: 定义 `Texture`、`Material`、`Mesh` 与 `Shader` artifact 的二进制头结构和 schema 常量,供 `AssetDatabase` 写出、各 loader 回读共享。
|
||||||
|
|
||||||
|
## 角色概述
|
||||||
|
|
||||||
|
`ArtifactFormats.h` 是项目资产导入链路的磁盘格式契约层。
|
||||||
|
|
||||||
|
它回答的是:
|
||||||
|
|
||||||
|
- `AssetDatabase` 把 source asset 导入到 `Library/Artifacts/...` 时,头结构和 magic 是什么
|
||||||
|
- `TextureLoader`、`MaterialLoader`、`MeshLoader`、`ShaderLoader` 回读时,二进制布局该怎样解释
|
||||||
|
|
||||||
|
它不负责:
|
||||||
|
|
||||||
|
- 扫描 `Assets`
|
||||||
|
- 生成 GUID
|
||||||
|
- 维护 source / artifact 数据库
|
||||||
|
- 直接触发运行时异步加载
|
||||||
|
|
||||||
|
## 当前 schema 常量
|
||||||
|
|
||||||
|
- `kTextureArtifactSchemaVersion = 1`
|
||||||
|
- `kMaterialArtifactSchemaVersion = 2`
|
||||||
|
- `kMeshArtifactSchemaVersion = 2`
|
||||||
|
- `kShaderArtifactSchemaVersion = 1`
|
||||||
|
|
||||||
|
## Texture artifact: `.xctex`
|
||||||
|
|
||||||
|
- 头结构: `TextureArtifactHeader`
|
||||||
|
- magic: `XCTEX01`
|
||||||
|
|
||||||
|
`TextureArtifactHeader` 当前记录:
|
||||||
|
|
||||||
|
- `textureType`
|
||||||
|
- `textureFormat`
|
||||||
|
- `width`
|
||||||
|
- `height`
|
||||||
|
- `depth`
|
||||||
|
- `mipLevels`
|
||||||
|
- `arraySize`
|
||||||
|
- `pixelDataSize`
|
||||||
|
|
||||||
|
写入顺序当前是:
|
||||||
|
|
||||||
|
1. `TextureArtifactHeader`
|
||||||
|
2. 原始像素 payload
|
||||||
|
|
||||||
|
## Material artifact: `.xcmat`
|
||||||
|
|
||||||
|
- 文件头: `MaterialArtifactFileHeader`
|
||||||
|
- 主头结构: `MaterialArtifactHeader`
|
||||||
|
- 属性结构: `MaterialPropertyArtifact`
|
||||||
|
- schema: `2`
|
||||||
|
- magic: `XCMAT02`
|
||||||
|
|
||||||
|
### 当前正文布局
|
||||||
|
|
||||||
|
`.xcmat` 当前不是“一个大 struct 一次性写完”,而是“文件头 + 变长字符串段 + 固定头 + 变长数组”的布局:
|
||||||
|
|
||||||
|
1. `MaterialArtifactFileHeader`
|
||||||
|
2. 材质名字符串
|
||||||
|
3. source 材质路径字符串
|
||||||
|
4. shader 路径字符串
|
||||||
|
5. shader pass 字符串
|
||||||
|
6. `MaterialArtifactHeader`
|
||||||
|
7. `tagCount` 对 tag 名/值字符串
|
||||||
|
8. `propertyCount` 个属性名字符串 + `MaterialPropertyArtifact`
|
||||||
|
9. `textureBindingCount` 组 texture binding 三元组:
|
||||||
|
- binding name
|
||||||
|
- 编码后的 `AssetRef` 字符串
|
||||||
|
- 可选 texture path 字符串
|
||||||
|
|
||||||
|
### `MaterialArtifactHeader`
|
||||||
|
|
||||||
|
当前记录:
|
||||||
|
|
||||||
|
- `renderQueue`
|
||||||
|
- `renderState`
|
||||||
|
- `tagCount`
|
||||||
|
- `propertyCount`
|
||||||
|
- `textureBindingCount`
|
||||||
|
|
||||||
|
### `MaterialPropertyArtifact`
|
||||||
|
|
||||||
|
只记录:
|
||||||
|
|
||||||
|
- `propertyType`
|
||||||
|
- `MaterialProperty::Value`
|
||||||
|
|
||||||
|
当前 writer 只把非 texture 属性写进 property 段;texture / cubemap 绑定统一走 texture binding 段。
|
||||||
|
|
||||||
|
### texture binding v2 语义
|
||||||
|
|
||||||
|
texture binding 当前不再只保存 path。
|
||||||
|
|
||||||
|
写入侧 `AssetDatabase::WriteMaterialArtifactFile(...)` 会尽量为每个 binding 同时保存:
|
||||||
|
|
||||||
|
- 编码 `AssetRef`
|
||||||
|
格式是 `guid,localID,resourceTypeInt`
|
||||||
|
- 可选 path
|
||||||
|
|
||||||
|
`AssetRef` 的求值优先级当前是:
|
||||||
|
|
||||||
|
1. binding 自己显式持有的 `AssetRef`
|
||||||
|
2. 已加载纹理句柄映射出的 `AssetRef`
|
||||||
|
3. 纹理 path 反查得到的 `AssetRef`
|
||||||
|
|
||||||
|
path 的求值优先级当前是:
|
||||||
|
|
||||||
|
1. 已加载纹理映射出的 artifact / source path
|
||||||
|
2. binding 自己保存的 `texturePath`
|
||||||
|
|
||||||
|
回读侧 `MaterialLoader` 当前会:
|
||||||
|
|
||||||
|
- 先解码 `AssetRef`
|
||||||
|
- 再解析 path
|
||||||
|
- 有效 `AssetRef` 优先走 `Material::SetTextureAssetRef(...)`
|
||||||
|
- 否则退到 `Material::SetTexturePath(...)`
|
||||||
|
|
||||||
|
这意味着 `.xcmat` v2 可以只靠 `AssetRef` 恢复稳定引用,path 只作为可选辅助信息存在。
|
||||||
|
|
||||||
|
## Mesh artifact: `.xcmesh`
|
||||||
|
|
||||||
|
- 头结构: `MeshArtifactHeader`
|
||||||
|
- schema: `2`
|
||||||
|
- magic: `XCMESH2`
|
||||||
|
|
||||||
|
`MeshArtifactHeader` 当前记录:
|
||||||
|
|
||||||
|
- `vertexCount`
|
||||||
|
- `vertexStride`
|
||||||
|
- `vertexAttributes`
|
||||||
|
- `indexCount`
|
||||||
|
- `use32BitIndex`
|
||||||
|
- `sectionCount`
|
||||||
|
- `materialCount`
|
||||||
|
- `boundsMin`
|
||||||
|
- `boundsMax`
|
||||||
|
- `vertexDataSize`
|
||||||
|
- `indexDataSize`
|
||||||
|
|
||||||
|
`.xcmesh` 当前写入顺序是:
|
||||||
|
|
||||||
|
1. `MeshArtifactHeader`
|
||||||
|
2. `sectionCount` 个 `MeshSection`
|
||||||
|
3. 顶点数据 blob
|
||||||
|
4. 索引数据 blob
|
||||||
|
5. `materialCount` 个材质 artifact 路径字符串
|
||||||
|
|
||||||
|
## Shader artifact
|
||||||
|
|
||||||
|
- 文件头: `ShaderArtifactFileHeader`
|
||||||
|
- 主头结构: `ShaderArtifactHeader`
|
||||||
|
- pass 头结构: `ShaderPassArtifactHeader`
|
||||||
|
- 属性结构: `ShaderPropertyArtifact`
|
||||||
|
- 资源结构: `ShaderResourceArtifact`
|
||||||
|
- variant 头结构: `ShaderVariantArtifactHeader`
|
||||||
|
- magic: `XCSHD01`
|
||||||
|
|
||||||
|
当前 `ArtifactFormats.h` 已经把 shader artifact 的头结构一起纳入契约。
|
||||||
|
|
||||||
|
## 导入与消费链路
|
||||||
|
|
||||||
|
### 写入侧
|
||||||
|
|
||||||
|
- `AssetDatabase::ImportTextureAsset()` 产出 `main.xctex`
|
||||||
|
- `AssetDatabase::ImportMaterialAsset()` 产出 `main.xcmat`
|
||||||
|
- `AssetDatabase::ImportModelAsset()` 产出 `main.xcmesh`
|
||||||
|
- `AssetDatabase::ImportShaderAsset()` 产出 shader artifact
|
||||||
|
|
||||||
|
模型导入还会在同一个 artifact 目录里附带生成:
|
||||||
|
|
||||||
|
- `texture_<n>.xctex`
|
||||||
|
- `material_<n>.xcmat`
|
||||||
|
|
||||||
|
### 读取侧
|
||||||
|
|
||||||
|
- `TextureLoader` 回读 `.xctex`
|
||||||
|
- `MaterialLoader` 回读 `.xcmat`
|
||||||
|
- `MeshLoader` 回读 `.xcmesh`
|
||||||
|
|
||||||
|
`ResourceManager::LoadResource()` 在项目模式下会先经 `AssetImportService::EnsureArtifact()` 准备 `ImportedAsset`,再把 `runtimeLoadPath` 交给具体 loader。
|
||||||
|
|
||||||
|
## 兼容性与边界
|
||||||
|
|
||||||
|
### 当前版本语义
|
||||||
|
|
||||||
|
- loader 目前显式检查的仍主要是 magic
|
||||||
|
- `schemaVersion` 已经写进文件头,但当前代码没有基于它做多版本分支读取
|
||||||
|
|
||||||
|
因此当前兼容策略更接近“magic + 整套代码同步升级”,而不是长期维护多代 reader。
|
||||||
|
|
||||||
|
### 二进制稳定性边界
|
||||||
|
|
||||||
|
当前 artifact 文件仍直接写入/读回这些 C++ 原生布局:
|
||||||
|
|
||||||
|
- `TextureArtifactHeader`
|
||||||
|
- `MaterialArtifactFileHeader`
|
||||||
|
- `MaterialArtifactHeader`
|
||||||
|
- `MaterialPropertyArtifact`
|
||||||
|
- `MeshArtifactHeader`
|
||||||
|
- `ShaderArtifactFileHeader`
|
||||||
|
- `ShaderArtifactHeader`
|
||||||
|
- `ShaderPassArtifactHeader`
|
||||||
|
- `ShaderPropertyArtifact`
|
||||||
|
- `ShaderResourceArtifact`
|
||||||
|
- `ShaderVariantArtifactHeader`
|
||||||
|
|
||||||
|
这意味着它本质上仍是引擎内部缓存格式,不是长期稳定的外部交换格式。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [当前模块](../Asset.md)
|
||||||
|
- [AssetDatabase](../AssetDatabase/AssetDatabase.md)
|
||||||
|
- [AssetRef](../AssetRef/AssetRef.md)
|
||||||
|
- [ResourceManager](../ResourceManager/ResourceManager.md)
|
||||||
|
- [Material](../../../Resources/Material/Material/Material.md)
|
||||||
|
- [MaterialLoader](../../../Resources/Material/MaterialLoader/MaterialLoader.md)
|
||||||
|
- [API 总索引](../../../../main.md)
|
||||||
@@ -4,41 +4,68 @@
|
|||||||
|
|
||||||
**类型**: `submodule`
|
**类型**: `submodule`
|
||||||
|
|
||||||
**描述**: 定义运行时资源系统的标识、句柄、缓存、加载和依赖管理基础设施。
|
**描述**: 定义项目资产数据库、artifact 缓存、运行时资源加载、句柄、缓存与项目资产查询快照这一整套资源基础设施。
|
||||||
|
|
||||||
## 概览
|
## 概述
|
||||||
|
|
||||||
`Core/Asset` 是当前引擎运行时资源系统的基础层。它并不直接实现材质、着色器、网格或音频资源本身,而是提供一套更底层的通用约定:
|
当前 `Core/Asset` 已经不只是“运行时按路径加载资源”的薄层接口,而是可以分成三层来看:
|
||||||
|
|
||||||
- 用 [ResourceTypes](ResourceTypes/ResourceTypes.md) 定义资源类型和 GUID 规则
|
1. [AssetDatabase](AssetDatabase/AssetDatabase.md)
|
||||||
- 用 [IResource](IResource/IResource.md) 约束资源对象的最小公共接口
|
负责扫描项目 `Assets`、维护 `.meta`、保存 source/artifact 索引,并在需要时把源资产导入成 `Library/Artifacts/...` 下的 artifact。
|
||||||
- 用 [ImportSettings](ImportSettings/ImportSettings.md) 传递资源导入配置
|
2. [AssetImportService](AssetImportService/AssetImportService.md) + [ProjectAssetIndex](ProjectAssetIndex/ProjectAssetIndex.md)
|
||||||
- 用 [ResourceManager](ResourceManager/ResourceManager.md) 做同步加载、加载器注册和引用计数入口
|
负责把 `AssetDatabase` 包装成线程安全服务,并导出供热路径查询使用的 path/GUID snapshot。
|
||||||
- 用 [ResourceHandle](ResourceHandle/ResourceHandle.md) 在上层代码里传递带类型的资源引用
|
3. [ResourceManager](ResourceManager/ResourceManager.md)
|
||||||
- 用 [ResourceCache](ResourceCache/ResourceCache.md)、[AsyncLoader](AsyncLoader/AsyncLoader.md)、[ResourceDependencyGraph](ResourceDependencyGraph/ResourceDependencyGraph.md) 为缓存、异步加载和依赖卸载预留基础结构
|
负责运行时加载、缓存、句柄与 loader 分发;当设置了项目根目录后,它会先经 `AssetImportService` 准备 artifact,再通过 `ProjectAssetIndex` 做 `AssetRef` / 路径查询。
|
||||||
|
|
||||||
从设计意图上看,这一层更接近商业引擎里“运行时资源服务”的雏形,而不是 Unity `AssetDatabase` 那类编辑器资产数据库。它强调的是运行时可加载、可引用、可扩展,而不是导入流水线和编辑器管理界面。
|
这意味着当前资源系统的真实链路是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Assets/... source files
|
||||||
|
-> AssetDatabase
|
||||||
|
-> AssetImportService
|
||||||
|
-> ProjectAssetIndex snapshot
|
||||||
|
-> ResourceManager
|
||||||
|
-> concrete loader / runtime resource
|
||||||
|
```
|
||||||
|
|
||||||
|
其中,[AssetGUID](AssetGUID/AssetGUID.md)、[AssetRef](AssetRef/AssetRef.md) 和 [ArtifactFormats](ArtifactFormats/ArtifactFormats.md) 分别补上了“资产身份”“资产引用”和“artifact 磁盘格式”这三块基础协议。
|
||||||
|
|
||||||
|
## 当前实现关系
|
||||||
|
|
||||||
|
- `editor/src/Application.cpp` 初始化编辑器时会调用 `ResourceManager::SetResourceRoot(projectRoot)`,从而绑定项目根、初始化 `ResourceFileSystem`,并刷新 `ProjectAssetIndex` 快照。
|
||||||
|
- `ResourceManager::LoadResource()` 在加载项目资产时,会先调用 `AssetImportService::EnsureArtifact()`;只有 artifact 就绪后,才把 `ImportedAsset::runtimeLoadPath` 交给具体 loader。
|
||||||
|
- `ProjectAssetIndex::TryGetAssetRef()` 当前会优先查本地 snapshot,cache miss 时再回退到 `AssetImportService`;必要时会先 `Refresh()` 数据库再整体重建 snapshot。
|
||||||
|
- `ProjectAssetIndex::TryResolveAssetPath()` 当前同样优先查 snapshot,但 miss 时只回退到 `AssetImportService::TryGetPrimaryAssetPath()`,不会主动刷新整份 snapshot。
|
||||||
|
- `engine/src/Resources/Material/MaterialLoader.cpp` 现在已经把材质纹理路径解析、`.xcmat` 中的 texture `AssetRef` 回读,以及首次访问时的懒加载纳入真实行为范围,因此 `AssetDatabase` 的材质依赖快照不再只是预留设计。
|
||||||
|
- `.xcmat` 当前已经是 material artifact v2:texture binding 会同时写出编码后的 `AssetRef` 和可选路径字符串,后续由 `MaterialLoader` 与 `Material` 协作懒解析成真正贴图句柄。
|
||||||
|
|
||||||
## 设计要点
|
## 设计要点
|
||||||
|
|
||||||
- 资源身份和资源对象分离。`ResourceGUID` 负责标识,`IResource` 负责对象实例,`ResourceHandle<T>` 负责类型化访问。
|
- 把“项目资产身份与导入缓存”和“运行时资源实例加载”拆成两层,避免 `ResourceManager` 直接承载 GUID、`.meta` 和 artifact 细节。
|
||||||
- 资源类型分派依赖 `GetResourceType<T>()` 模板特化,而不是 RTTI 或字符串注册。
|
- 再引入 `AssetImportService + ProjectAssetIndex` 作为服务层和只读快照层,把线程同步、项目根切换和高频查询从 `AssetDatabase` 与 `ResourceManager` 本体里拆出来。
|
||||||
- `ResourceManager` 当前是主入口,但它和 `ResourceCache`、`AsyncLoader`、`ResourceDependencyGraph` 的集成还没有完全做完。
|
- `AssetDatabase` 通过 `guid + importer + source/meta/dependency snapshot` 生成 `artifactKey`,让重导入条件可复现。
|
||||||
- 当前自动注册的内建 loader 只有 `MaterialLoader` 和 `ShaderLoader`。
|
- `ResourceManager` 仍保留 `builtin://` 这类虚拟路径直载能力;只有能解析到项目 `Assets` 的路径才会进入项目资产链路。
|
||||||
- 这套接口已经有明显的“未来做流式加载和资源依赖卸载”的方向,但当前很多能力仍处于占位或半成品状态。
|
- `ResourceHandle`、`ResourceCache` 和 `AsyncLoader` 继续围绕运行时 `IResource` 实例运转,而不是直接把 source asset 当作运行时对象。
|
||||||
|
|
||||||
## 当前实现现状
|
## 当前实现边界
|
||||||
|
|
||||||
- 同步加载路径是当前最可靠的使用方式。
|
- `AssetDatabase` 当前只有 `TextureImporter`、`MaterialImporter` 和 `ModelImporter` 会产出 artifact;`FolderImporter` 和 `DefaultImporter` 只保留 source 记录。
|
||||||
- `Load<T>()` 直接把传入路径交给 loader,当前不会自动调用 `ResolvePath()`,所以 `SetResourceRoot()` 只是一个路径拼接辅助,不是统一的实际加载入口。
|
- `.meta` 文件当前只保存 `guid`、`folderAsset`、`importer` 和 `importerVersion`,还没有持久化 importer 专属设置。
|
||||||
- `LoadAsync()` 已经有 API 形状,但当前队列不会被后台线程消费,成功回调路径也没有闭环,不能把它当成成熟的异步流式系统。
|
- `ProjectAssetIndex` 当前只缓存主资产路径,生成的 `AssetRef` 仍默认使用 `kMainAssetLocalID`。
|
||||||
- `ResourceManager`、`ResourceCache` 和句柄引用计数之间还没有完全打通,文档里会明确标出这些差异,而不把它们包装成“完整资源生命周期管理”。
|
- `ResourceManager` 会在同步加载路径里触发 artifact 生成,但当前没有后台导入队列或文件监听闭环。
|
||||||
|
- `LoadAsync()` / `AsyncLoader` 当前已经具备真实的工作线程与完成队列闭环,但回调仍依赖 `Update()` 手动轮询分发,取消与配置所有权语义也还比较原始。
|
||||||
|
|
||||||
## 头文件
|
## 头文件
|
||||||
|
|
||||||
|
- [ArtifactFormats](ArtifactFormats/ArtifactFormats.md) - `ArtifactFormats.h`
|
||||||
|
- [AssetDatabase](AssetDatabase/AssetDatabase.md) - `AssetDatabase.h`
|
||||||
|
- [AssetGUID](AssetGUID/AssetGUID.md) - `AssetGUID.h`
|
||||||
|
- [AssetImportService](AssetImportService/AssetImportService.md) - `AssetImportService.h`
|
||||||
|
- [AssetRef](AssetRef/AssetRef.md) - `AssetRef.h`
|
||||||
- [AsyncLoader](AsyncLoader/AsyncLoader.md) - `AsyncLoader.h`
|
- [AsyncLoader](AsyncLoader/AsyncLoader.md) - `AsyncLoader.h`
|
||||||
- [ImportSettings](ImportSettings/ImportSettings.md) - `ImportSettings.h`
|
- [ImportSettings](ImportSettings/ImportSettings.md) - `ImportSettings.h`
|
||||||
- [IResource](IResource/IResource.md) - `IResource.h`
|
- [IResource](IResource/IResource.md) - `IResource.h`
|
||||||
|
- [ProjectAssetIndex](ProjectAssetIndex/ProjectAssetIndex.md) - `ProjectAssetIndex.h`
|
||||||
- [ResourceCache](ResourceCache/ResourceCache.md) - `ResourceCache.h`
|
- [ResourceCache](ResourceCache/ResourceCache.md) - `ResourceCache.h`
|
||||||
- [ResourceDependencyGraph](ResourceDependencyGraph/ResourceDependencyGraph.md) - `ResourceDependencyGraph.h`
|
- [ResourceDependencyGraph](ResourceDependencyGraph/ResourceDependencyGraph.md) - `ResourceDependencyGraph.h`
|
||||||
- [ResourceHandle](ResourceHandle/ResourceHandle.md) - `ResourceHandle.h`
|
- [ResourceHandle](ResourceHandle/ResourceHandle.md) - `ResourceHandle.h`
|
||||||
@@ -47,10 +74,11 @@
|
|||||||
|
|
||||||
## 推荐阅读顺序
|
## 推荐阅读顺序
|
||||||
|
|
||||||
1. 先读 [ResourceTypes](ResourceTypes/ResourceTypes.md),理解 `ResourceType` 和 `ResourceGUID`。
|
1. 先读 [AssetGUID](AssetGUID/AssetGUID.md) 与 [AssetRef](AssetRef/AssetRef.md),理解项目资产的身份与引用契约。
|
||||||
2. 再读 [IResource](IResource/IResource.md) 与 [ImportSettings](ImportSettings/ImportSettings.md),理解资源对象和导入配置契约。
|
2. 再读 [AssetDatabase](AssetDatabase/AssetDatabase.md) 与 [ArtifactFormats](ArtifactFormats/ArtifactFormats.md),理解 source asset 如何导入为 `Library/Artifacts` 下的 artifact。
|
||||||
3. 然后读 [ResourceManager](ResourceManager/ResourceManager.md) 与 [ResourceHandle](ResourceHandle/ResourceHandle.md),这是当前实际最常用的运行时入口。
|
3. 然后读 [AssetImportService](AssetImportService/AssetImportService.md) 与 [ProjectAssetIndex](ProjectAssetIndex/ProjectAssetIndex.md),理解数据库如何被包装成线程安全服务和热路径查询缓存。
|
||||||
4. 最后再读 [ResourceCache](ResourceCache/ResourceCache.md)、[AsyncLoader](AsyncLoader/AsyncLoader.md)、[ResourceDependencyGraph](ResourceDependencyGraph/ResourceDependencyGraph.md),它们更偏向扩展机制和当前限制说明。
|
4. 接着读 [ResourceManager](ResourceManager/ResourceManager.md) 与 [ResourceHandle](ResourceHandle/ResourceHandle.md),理解运行时如何消费这些 artifact 和 snapshot。
|
||||||
|
5. 最后再看 [ResourceCache](ResourceCache/ResourceCache.md)、[AsyncLoader](AsyncLoader/AsyncLoader.md) 和 [ResourceDependencyGraph](ResourceDependencyGraph/ResourceDependencyGraph.md),理解缓存、异步与依赖管理的现状。
|
||||||
|
|
||||||
## 相关指南
|
## 相关指南
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# AssetDatabase::ArtifactDependencyRecord
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `struct`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
**描述**: 记录单个依赖文件的规范化路径与内容快照,用于判断 artifact 是否需要因依赖变化而重导入。
|
||||||
|
|
||||||
|
## 字段
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `path` | `Containers::String` | 依赖文件路径。优先记录为项目相对路径,否则保留规范化后的路径字符串。 |
|
||||||
|
| `hash` | `Containers::String` | 依赖文件内容哈希。 |
|
||||||
|
| `fileSize` | `Core::uint64` | 依赖文件大小快照。 |
|
||||||
|
| `writeTime` | `Core::uint64` | 依赖文件写时间快照。 |
|
||||||
|
|
||||||
|
## 当前实现语义
|
||||||
|
|
||||||
|
- 材质导入会把纹理绑定路径收集成依赖记录;这些路径来自 `MaterialLoader` 解析后的真实绑定路径。
|
||||||
|
- 模型导入会收集 `obj -> mtl -> texture` 这条声明依赖链路,也会补充导入后 mesh 上暴露出的纹理路径。
|
||||||
|
- `AreDependenciesCurrent()` 会同时比较文件是否存在、大小、写时间和哈希;任意一个变化都会触发重导入。
|
||||||
|
- 如果某个依赖在记录时就不存在,则它会以空哈希和零大小/写时间写入;之后该文件一旦出现,也会被视为依赖变化并触发重导入。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [ArtifactRecord](ArtifactRecord.md)
|
||||||
40
docs/api/XCEngine/Core/Asset/AssetDatabase/ArtifactRecord.md
Normal file
40
docs/api/XCEngine/Core/Asset/AssetDatabase/ArtifactRecord.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# AssetDatabase::ArtifactRecord
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `struct`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
**描述**: 保存某个 GUID 当前 artifact 结果的索引记录,是 `Library/ArtifactDB/artifacts.db` 的核心行结构。
|
||||||
|
|
||||||
|
## 字段
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `artifactKey` | `Containers::String` | 基于 GUID、导入器、source/meta/dependency 快照计算出的唯一 key。 |
|
||||||
|
| `assetGuid` | `AssetGUID` | 对应的 source asset GUID。 |
|
||||||
|
| `importerName` | `Containers::String` | 生成该 artifact 时使用的 importer 名称。 |
|
||||||
|
| `importerVersion` | `Core::uint32` | 生成该 artifact 时使用的 importer 版本。 |
|
||||||
|
| `resourceType` | `ResourceType` | 该 artifact 的主资源类型。 |
|
||||||
|
| `artifactDirectory` | `Containers::String` | artifact 目录的项目相对路径,通常位于 `Library/Artifacts/...`。 |
|
||||||
|
| `mainArtifactPath` | `Containers::String` | 主 artifact 文件的项目相对路径。 |
|
||||||
|
| `sourceHash` | `Containers::String` | 导入时的 source 内容哈希。 |
|
||||||
|
| `metaHash` | `Containers::String` | 导入时的 `.meta` 哈希。 |
|
||||||
|
| `sourceFileSize` | `Core::uint64` | 导入时的 source 文件大小。 |
|
||||||
|
| `sourceWriteTime` | `Core::uint64` | 导入时的 source 写时间。 |
|
||||||
|
| `mainLocalID` | `LocalID` | 当前主资产 local ID,默认是 `kMainAssetLocalID`。 |
|
||||||
|
| `dependencies` | `std::vector<ArtifactDependencyRecord>` | 导入时捕获的依赖快照。 |
|
||||||
|
|
||||||
|
## 当前实现语义
|
||||||
|
|
||||||
|
- `artifactDirectory` / `mainArtifactPath` 在数据库里保存的是相对项目根的 `Library/...` 路径;`EnsureArtifact()` 返回给调用方时才会展开成绝对路径。
|
||||||
|
- `ShouldReimport()` 会拿这里的 importer 版本、source/meta 快照和依赖快照与当前文件系统状态比较,决定是否需要重导入。
|
||||||
|
- 主 artifact 文件缺失时,即使其他快照字段都没变,也会触发重建。
|
||||||
|
- 当前主 `localID` 还没有扩展成完整子资产系统,因此大多数调用都保持主资产值。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [ArtifactDependencyRecord](ArtifactDependencyRecord.md)
|
||||||
|
- [ResolvedAsset](ResolvedAsset.md)
|
||||||
231
docs/api/XCEngine/Core/Asset/AssetDatabase/AssetDatabase.md
Normal file
231
docs/api/XCEngine/Core/Asset/AssetDatabase/AssetDatabase.md
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
# AssetDatabase
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `class`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
**描述**: 管理项目 `Assets` 目录里的 source asset、`.meta` sidecar、source/artifact 快照以及 artifact 导入结果的项目资产数据库。
|
||||||
|
|
||||||
|
## 概览
|
||||||
|
|
||||||
|
`AssetDatabase` 处理的是“项目资产”和“artifact 索引”,而不是已经加载进内存的运行时资源实例。
|
||||||
|
|
||||||
|
它当前的真实职责是:
|
||||||
|
|
||||||
|
1. 扫描项目根目录下的 `Assets`
|
||||||
|
2. 为每个 source asset 或文件夹确保存在 `.meta` sidecar,并维持稳定 GUID
|
||||||
|
3. 保存 source 侧快照和 artifact 侧快照
|
||||||
|
4. 在需要时把 source asset 导入到 `Library/Artifacts/<shard>/<artifactKey>/...`
|
||||||
|
5. 为 [AssetImportService](../AssetImportService/AssetImportService.md) 和 [ProjectAssetIndex](../ProjectAssetIndex/ProjectAssetIndex.md) 提供 GUID / 路径查询与 lookup snapshot
|
||||||
|
|
||||||
|
当前它并不直接暴露给 `ResourceManager` 调用点,而是经 `AssetImportService` 包装后再进入运行时路径。
|
||||||
|
|
||||||
|
## 生命周期
|
||||||
|
|
||||||
|
- [Initialize](Initialize.md)
|
||||||
|
设置项目根、`Assets` 根和 `Library` 根,确保目录结构存在,然后加载 source/artifact 数据库并扫描当前资产树。
|
||||||
|
- [Refresh](Refresh.md)
|
||||||
|
重新扫描 `Assets` 并更新 source 记录,不会批量重导 artifact。
|
||||||
|
- [Shutdown](Shutdown.md)
|
||||||
|
把 source/artifact 两份数据库写回磁盘,然后清空内存状态。
|
||||||
|
|
||||||
|
当前 `AssetDatabase` 自身没有内部锁。线程同步由外层 [AssetImportService](../AssetImportService/AssetImportService.md) 的 `recursive_mutex` 提供。
|
||||||
|
|
||||||
|
## 持久化布局
|
||||||
|
|
||||||
|
### Source 侧
|
||||||
|
|
||||||
|
- 每个 source asset 或文件夹都对应一个 `.meta` sidecar
|
||||||
|
- `.meta` 当前记录:
|
||||||
|
- `guid`
|
||||||
|
- `folderAsset`
|
||||||
|
- `importer`
|
||||||
|
- `importerVersion`
|
||||||
|
- `Library/SourceAssetDB/assets.db` 保存 `SourceAssetRecord` 快照
|
||||||
|
|
||||||
|
`assets.db` 当前是制表符分隔的文本快照,而不是二进制数据库。
|
||||||
|
|
||||||
|
### Artifact 侧
|
||||||
|
|
||||||
|
- `Library/ArtifactDB/artifacts.db` 保存 `ArtifactRecord` 快照
|
||||||
|
- artifact 目录按 `artifactKey` 前两位分片:
|
||||||
|
- `Library/Artifacts/<2-char-shard>/<artifactKey>/...`
|
||||||
|
- 主 artifact 文件当前约定为:
|
||||||
|
- 纹理: `main.xctex`
|
||||||
|
- 材质: `main.xcmat`
|
||||||
|
- 模型: `main.xcmesh`
|
||||||
|
- Shader: `main.xcshader`
|
||||||
|
|
||||||
|
模型 artifact 还会在同一目录下产出内嵌材质和纹理 artifact,例如 `material_0.xcmat`、`texture_0.xctex`。
|
||||||
|
|
||||||
|
`artifacts.db` 当前同样是文本快照,依赖记录以附加字段顺序存储。
|
||||||
|
|
||||||
|
## 查询与快照链路
|
||||||
|
|
||||||
|
### 路径解析
|
||||||
|
|
||||||
|
- [ResolvePath](ResolvePath.md) 只把项目内 `Assets/...` 或可相对当前项目根还原为 `Assets/...` 的绝对路径视为正式项目资产路径
|
||||||
|
- 带 `://` 的虚拟路径会直接失败,不进入项目资产数据库
|
||||||
|
- 其他普通相对路径虽然可以被展开为绝对路径,但 `relativePath` 会保持为空,因此不会被认作正式项目资产
|
||||||
|
|
||||||
|
### GUID 与 `AssetRef`
|
||||||
|
|
||||||
|
- [TryGetAssetGuid](TryGetAssetGuid.md)
|
||||||
|
通过规范化、大小写无关的 `Assets/...` 路径 key 查 GUID
|
||||||
|
- [TryGetAssetRef](TryGetAssetRef.md)
|
||||||
|
只是把 GUID 包装成主资产 `AssetRef`,并原样写入调用方给定的 `ResourceType`
|
||||||
|
- [TryGetPrimaryAssetPath](TryGetPrimaryAssetPath.md)
|
||||||
|
做 GUID 到主 source 路径的反查
|
||||||
|
|
||||||
|
### Lookup snapshot
|
||||||
|
|
||||||
|
[BuildLookupSnapshot](BuildLookupSnapshot.md) 会从当前 source 快照导出两张查找表:
|
||||||
|
|
||||||
|
- `pathKey -> AssetGUID`
|
||||||
|
- `AssetGUID -> relativePath`
|
||||||
|
|
||||||
|
它不做扫描,也不触发导入。当前真实链路是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
AssetDatabase::BuildLookupSnapshot
|
||||||
|
-> AssetImportService::BuildLookupSnapshot
|
||||||
|
-> ProjectAssetIndex::RefreshFrom
|
||||||
|
-> ResourceManager hot-path queries
|
||||||
|
```
|
||||||
|
|
||||||
|
## 导入与重导链路
|
||||||
|
|
||||||
|
### 当前导入器映射
|
||||||
|
|
||||||
|
| importer | 扩展名/来源 | 主资源类型 | 当前 artifact |
|
||||||
|
|------|------|------|------|
|
||||||
|
| `TextureImporter` | `.png` `.jpg` `.jpeg` `.bmp` `.tga` `.gif` `.hdr` | `Texture` | `main.xctex` |
|
||||||
|
| `MaterialImporter` | `.mat` `.material` `.json` | `Material` | `main.xcmat` |
|
||||||
|
| `ModelImporter` | `.obj` `.fbx` `.gltf` `.glb` `.dae` `.stl` | `Mesh` | `main.xcmesh` + 内嵌材质/纹理 artifact |
|
||||||
|
| `ShaderImporter` | `.shader` `.hlsl` `.glsl` `.vert` `.frag` `.geom` `.comp` | `Shader` | `main.xcshader` |
|
||||||
|
| `FolderImporter` | 文件夹 | `Unknown` | 无 artifact |
|
||||||
|
| `DefaultImporter` | 其他扩展名 | `Unknown` | 无 artifact |
|
||||||
|
|
||||||
|
`SourceAssetRecord::importerVersion` 当前统一取头文件里的 `kCurrentImporterVersion`。按 `engine/include/XCEngine/Core/Asset/AssetDatabase.h` 的当前定义,这个值是 `5`。
|
||||||
|
|
||||||
|
### 重导入判定
|
||||||
|
|
||||||
|
`ShouldReimport()` 当前会在以下任一条件满足时要求重导入:
|
||||||
|
|
||||||
|
- 没有现存 `ArtifactRecord`
|
||||||
|
- `artifactKey` 或 `mainArtifactPath` 为空
|
||||||
|
- 主 artifact 文件已经不存在
|
||||||
|
- importer 版本变化
|
||||||
|
- source 内容哈希变化
|
||||||
|
- `.meta` 哈希变化
|
||||||
|
- source 文件大小或写时间变化
|
||||||
|
- 任一依赖文件快照不再匹配
|
||||||
|
|
||||||
|
因此当前 artifact key 并不是唯一判定条件;真正的重导入 gate 是一组 source / meta / dependency snapshot。
|
||||||
|
|
||||||
|
### `EnsureArtifact()`
|
||||||
|
|
||||||
|
[EnsureArtifact](EnsureArtifact.md) 是当前最关键的入口。它会:
|
||||||
|
|
||||||
|
1. 解析请求路径并确认它落在项目 `Assets` 下
|
||||||
|
2. 检查 source 文件是否存在
|
||||||
|
3. 调用 `EnsureMetaForPath()`,确保 source 记录、GUID、`.meta` 和 importerVersion 有效
|
||||||
|
4. 根据 importer 推导主资源类型,并检查是否与 `requestedType` 一致
|
||||||
|
5. 查找已有 `ArtifactRecord`
|
||||||
|
6. 若 `ShouldReimport()` 要求重建,则同步调用对应 importer:
|
||||||
|
- 纹理 -> `ImportTextureAsset()`
|
||||||
|
- 材质 -> `ImportMaterialAsset()`
|
||||||
|
- 模型 -> `ImportModelAsset()`
|
||||||
|
- Shader -> `ImportShaderAsset()`
|
||||||
|
7. 成功后更新 `m_artifactsByGuid`,并把 `lastKnownArtifactKey` 回写到两份 source 记录索引
|
||||||
|
8. 调用 `SaveArtifactDB()` 和 `SaveSourceAssetDB()` 持久化结果
|
||||||
|
9. 把 source 绝对路径、相对路径、GUID、artifact 绝对目录和主 artifact 绝对路径写入 `ResolvedAsset`
|
||||||
|
|
||||||
|
### 材质 artifact 写入
|
||||||
|
|
||||||
|
`ImportMaterialAsset()` 当前不是简单把 source 文件原样拷进 `Library`。
|
||||||
|
|
||||||
|
它的真实路径是:
|
||||||
|
|
||||||
|
1. 用 `MaterialLoader` 先把 source 材质解析成运行时 `Material`
|
||||||
|
2. 通过 `CollectMaterialDependencies()` 收集 shader 和 texture binding 依赖快照
|
||||||
|
3. 基于 source/meta/dependencies 生成新的 `artifactKey`
|
||||||
|
4. 调用 `WriteMaterialArtifactFile(...)` 写出 `main.xcmat`
|
||||||
|
|
||||||
|
当前写出的 `.xcmat` 已经是 v2:
|
||||||
|
|
||||||
|
- magic `XCMAT02`
|
||||||
|
- schema version `2`
|
||||||
|
- texture binding 段同时保存编码 `AssetRef` 与可选 path
|
||||||
|
|
||||||
|
这让 artifact 可以同时保留:
|
||||||
|
|
||||||
|
- 稳定的项目资产身份
|
||||||
|
- 当前可用的定位 path
|
||||||
|
|
||||||
|
### 依赖快照
|
||||||
|
|
||||||
|
`ArtifactDependencyRecord` 当前已经进入真实行为范围,不再只是预留结构。
|
||||||
|
|
||||||
|
- 材质导入会通过 `CollectMaterialDependencies()` 收集:
|
||||||
|
- shader path
|
||||||
|
- 每个 texture binding 的 path
|
||||||
|
- 模型导入会通过 `CollectModelDependencies()` 收集:
|
||||||
|
- `obj -> mtl` 声明依赖
|
||||||
|
- `mtl -> texture` 声明依赖
|
||||||
|
- 导入后 mesh 暴露出的纹理路径
|
||||||
|
- Shader 导入会通过 `CollectShaderDependencies()` 收集 shader manifest 和 `ShaderLoader::CollectSourceDependencies()` 解析出的源码依赖
|
||||||
|
- `AreDependenciesCurrent()` 会同时比较文件是否存在、大小、写时间和内容哈希
|
||||||
|
|
||||||
|
这意味着贴图、`.mtl`、shader manifest、shader 源文件或其他已记录依赖变化时,当前都会触发新的 artifact 重建。
|
||||||
|
|
||||||
|
## 公开数据结构
|
||||||
|
|
||||||
|
- [ArtifactDependencyRecord](ArtifactDependencyRecord.md) - 单个依赖文件的快照记录
|
||||||
|
- [SourceAssetRecord](SourceAssetRecord.md) - source 资产记录
|
||||||
|
- [ArtifactRecord](ArtifactRecord.md) - artifact 数据库记录
|
||||||
|
- [ResolvedAsset](ResolvedAsset.md) - `EnsureArtifact()` 返回给调用方的解析结果
|
||||||
|
|
||||||
|
## 公开方法
|
||||||
|
|
||||||
|
| 方法 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| [Initialize](Initialize.md) | 初始化项目根与数据库状态。 |
|
||||||
|
| [Shutdown](Shutdown.md) | 写回数据库并清理内存状态。 |
|
||||||
|
| [Refresh](Refresh.md) | 重新扫描 `Assets`。 |
|
||||||
|
| [ResolvePath](ResolvePath.md) | 解析请求路径到绝对/相对项目路径。 |
|
||||||
|
| [TryGetAssetGuid](TryGetAssetGuid.md) | 通过路径查 GUID。 |
|
||||||
|
| [TryGetAssetRef](TryGetAssetRef.md) | 通过路径组装主资产 `AssetRef`。 |
|
||||||
|
| [EnsureArtifact](EnsureArtifact.md) | 确保 source asset 对应的 artifact 可用。 |
|
||||||
|
| [TryGetPrimaryAssetPath](TryGetPrimaryAssetPath.md) | 通过 GUID 反查主 source 路径。 |
|
||||||
|
| [BuildLookupSnapshot](BuildLookupSnapshot.md) | 导出 path/GUID lookup snapshot。 |
|
||||||
|
| [GetProjectRoot](GetProjectRoot.md) | 获取项目根目录。 |
|
||||||
|
| [GetAssetsRoot](GetAssetsRoot.md) | 获取 `Assets` 根目录。 |
|
||||||
|
| [GetLibraryRoot](GetLibraryRoot.md) | 获取 `Library` 根目录。 |
|
||||||
|
|
||||||
|
## 真实使用位置
|
||||||
|
|
||||||
|
- [AssetImportService](../AssetImportService/AssetImportService.md) 当前持有 `AssetDatabase`,并负责所有外部访问的加锁与项目根切换
|
||||||
|
- [ProjectAssetIndex](../ProjectAssetIndex/ProjectAssetIndex.md) 通过 `BuildLookupSnapshot()` 构建热路径 snapshot
|
||||||
|
- `ResourceManager::LoadResource()` 通过 `AssetImportService::EnsureArtifact()` 准备 artifact,再交给具体 loader
|
||||||
|
- `tests/core/Asset/test_resource_manager.cpp` 覆盖了新建项目资产后 `TryGetAssetRef()` cache miss 刷新 snapshot、随后 `TryResolveAssetPath()` 成功的真实链路
|
||||||
|
- `tests/Resources/Texture/test_texture_loader.cpp`、`tests/Resources/Material/test_material_loader.cpp`、`tests/Resources/Mesh/test_mesh_loader.cpp` 覆盖了 artifact 生成、复用和依赖变化触发重导的主路径
|
||||||
|
|
||||||
|
## 当前实现边界
|
||||||
|
|
||||||
|
- 当前只处理项目 `Assets` 下的资产,`builtin://` 等虚拟路径不会进入这里
|
||||||
|
- `.meta` 只存导入器名称和版本,不存 importer 细节设置
|
||||||
|
- `FolderImporter` / `DefaultImporter` 不会产出 artifact
|
||||||
|
- 当前没有文件监听器,也没有后台导入任务;artifact 通常在首次加载或显式调用时同步生成
|
||||||
|
- `TryGetAssetRef()` 只保证“路径有 GUID”,不保证请求的 `ResourceType` 与实际 importer 一致;真正的类型匹配要到 `EnsureArtifact()` 阶段才检查
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [当前模块](../Asset.md)
|
||||||
|
- [AssetImportService](../AssetImportService/AssetImportService.md)
|
||||||
|
- [ProjectAssetIndex](../ProjectAssetIndex/ProjectAssetIndex.md)
|
||||||
|
- [ResourceManager](../ResourceManager/ResourceManager.md)
|
||||||
|
- [ImportSettings](../ImportSettings/ImportSettings.md)
|
||||||
|
- [API 总索引](../../../../main.md)
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# AssetDatabase::BuildLookupSnapshot
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void BuildLookupSnapshot(
|
||||||
|
std::unordered_map<std::string, AssetGUID>& outPathToGuid,
|
||||||
|
std::unordered_map<AssetGUID, Containers::String>& outGuidToPath) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
从当前 source 资产记录导出一份 path/GUID 双向查询快照,供外层热路径缓存使用。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 先清空两张输出 map。
|
||||||
|
- 以当前 `m_sourcesByPathKey` 的容量为基准预留空间。
|
||||||
|
- 遍历 `m_sourcesByPathKey`,把有效 GUID 和非空相对路径写入 `outPathToGuid`。
|
||||||
|
- 遍历 `m_sourcesByGuid`,把有效 GUID 和非空相对路径写入 `outGuidToPath`。
|
||||||
|
|
||||||
|
## 关键语义
|
||||||
|
|
||||||
|
- `outPathToGuid` 的 key 不是原始路径,而是已经规范化并转小写的 `pathKey`。
|
||||||
|
- `outGuidToPath` 保存的是规范化后的 `Assets/...` 相对路径,而不是绝对路径。
|
||||||
|
- 该方法本身不做扫描、不触发导入,也不刷新数据库;它只导出当前内存中的 source 快照。
|
||||||
|
|
||||||
|
当前真实消费链路是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
AssetDatabase::BuildLookupSnapshot
|
||||||
|
-> AssetImportService::BuildLookupSnapshot
|
||||||
|
-> ProjectAssetIndex::RefreshFrom
|
||||||
|
```
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [AssetImportService](../AssetImportService/BuildLookupSnapshot.md)
|
||||||
|
- [ProjectAssetIndex](../ProjectAssetIndex/RefreshFrom.md)
|
||||||
|
- [TryGetPrimaryAssetPath](TryGetPrimaryAssetPath.md)
|
||||||
60
docs/api/XCEngine/Core/Asset/AssetDatabase/EnsureArtifact.md
Normal file
60
docs/api/XCEngine/Core/Asset/AssetDatabase/EnsureArtifact.md
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# AssetDatabase::EnsureArtifact
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool EnsureArtifact(
|
||||||
|
const Containers::String& requestPath,
|
||||||
|
ResourceType requestedType,
|
||||||
|
ResolvedAsset& outAsset);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
确保指定 project asset 的主 artifact 已经存在且与当前 source / `.meta` / dependency snapshot 一致,并把可直接加载的 artifact 路径回传给调用方。
|
||||||
|
|
||||||
|
## 当前实现流程
|
||||||
|
|
||||||
|
1. 把 `outAsset` 重置为默认值
|
||||||
|
2. 调用 [ResolvePath](ResolvePath.md) 解析请求路径;若无法得到 `Assets/...` 相对路径则失败
|
||||||
|
3. 检查 source 文件是否存在
|
||||||
|
4. 调用内部 `EnsureMetaForPath()`,确保 source 记录、GUID、`.meta` 和 `importerVersion` 有效
|
||||||
|
5. 根据 importer 推导主资源类型,并检查是否与 `requestedType` 一致
|
||||||
|
6. 查找已有 `ArtifactRecord`
|
||||||
|
7. 若 `ShouldReimport()` 判定需要重建,则同步调用对应 importer:
|
||||||
|
- 纹理 -> `ImportTextureAsset()`
|
||||||
|
- 材质 -> `ImportMaterialAsset()`
|
||||||
|
- 模型 -> `ImportModelAsset()`
|
||||||
|
- Shader -> `ImportShaderAsset()`
|
||||||
|
8. 成功重建后,更新 `m_artifactsByGuid`,并把 `lastKnownArtifactKey` 回写到两份 source 记录索引
|
||||||
|
9. 调用 `SaveArtifactDB()` 和 `SaveSourceAssetDB()` 持久化结果
|
||||||
|
10. 把 source 绝对路径、相对路径、GUID、artifact 绝对目录和主 artifact 绝对路径写入 `outAsset`
|
||||||
|
|
||||||
|
## 返回值
|
||||||
|
|
||||||
|
- `true`
|
||||||
|
表示 source 存在、类型匹配,且主 artifact 已可直接使用
|
||||||
|
- `false`
|
||||||
|
表示路径不合法、source 不存在、类型不匹配、导入失败,或当前 importer 不支持产出 artifact
|
||||||
|
|
||||||
|
## 关键语义
|
||||||
|
|
||||||
|
- 当前成功路径里会把 `exists` 和 `artifactReady` 一起置为 `true`
|
||||||
|
- `artifactKey` 由 GUID、importer、版本、source/meta 哈希、文件大小、写时间和依赖快照共同决定
|
||||||
|
- `ShouldReimport()` 不只比较 `artifactKey`;它还会检查主 artifact 文件是否仍然存在,以及依赖快照是否仍匹配
|
||||||
|
- 材质、模型和 Shader 导入的依赖快照都已经进入真实行为范围,因此贴图、`.mtl`、shader manifest 或 shader 源文件变化时都会触发新的 artifact
|
||||||
|
- 返回给调用方的 `artifactDirectory` 与 `artifactMainPath` 都是绝对路径,适合直接交给 loader 或文件系统操作
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [ResolvedAsset](ResolvedAsset.md)
|
||||||
|
- [ArtifactRecord](ArtifactRecord.md)
|
||||||
|
- [ArtifactDependencyRecord](ArtifactDependencyRecord.md)
|
||||||
|
- [ResolvePath](ResolvePath.md)
|
||||||
27
docs/api/XCEngine/Core/Asset/AssetDatabase/GetAssetsRoot.md
Normal file
27
docs/api/XCEngine/Core/Asset/AssetDatabase/GetAssetsRoot.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# AssetDatabase::GetAssetsRoot
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const Containers::String& GetAssetsRoot() const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
返回当前项目 `Assets` 根目录的绝对路径字符串。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 直接返回内部缓存的 `m_assetsRoot`。
|
||||||
|
- 它由 [Initialize](Initialize.md) 通过 `projectRoot / "Assets"` 推导得到。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [GetProjectRoot](GetProjectRoot.md)
|
||||||
27
docs/api/XCEngine/Core/Asset/AssetDatabase/GetLibraryRoot.md
Normal file
27
docs/api/XCEngine/Core/Asset/AssetDatabase/GetLibraryRoot.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# AssetDatabase::GetLibraryRoot
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const Containers::String& GetLibraryRoot() const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
返回当前项目 `Library` 根目录的绝对路径字符串。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 直接返回内部缓存的 `m_libraryRoot`。
|
||||||
|
- 它由 [Initialize](Initialize.md) 通过 `projectRoot / "Library"` 推导得到。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [GetProjectRoot](GetProjectRoot.md)
|
||||||
28
docs/api/XCEngine/Core/Asset/AssetDatabase/GetProjectRoot.md
Normal file
28
docs/api/XCEngine/Core/Asset/AssetDatabase/GetProjectRoot.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# AssetDatabase::GetProjectRoot
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const Containers::String& GetProjectRoot() const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
返回当前初始化后的项目根目录。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 直接返回内部缓存的 `m_projectRoot`。
|
||||||
|
- 该值在 [Initialize](Initialize.md) 中设置,在 [Shutdown](Shutdown.md) 中清空。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [GetAssetsRoot](GetAssetsRoot.md)
|
||||||
|
- [GetLibraryRoot](GetLibraryRoot.md)
|
||||||
36
docs/api/XCEngine/Core/Asset/AssetDatabase/Initialize.md
Normal file
36
docs/api/XCEngine/Core/Asset/AssetDatabase/Initialize.md
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# AssetDatabase::Initialize
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void Initialize(const Containers::String& projectRoot);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
设置项目根目录并初始化 `Assets` / `Library` 相关数据库状态。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
1. 规范化 `projectRoot`。
|
||||||
|
2. 推导 `Assets`、`Library`、`Library/SourceAssetDB/assets.db`、`Library/ArtifactDB/artifacts.db` 路径。
|
||||||
|
3. 确保 `Assets`、`Library/SourceAssetDB`、`Library/ArtifactDB`、`Library/Artifacts` 目录存在。
|
||||||
|
4. 从磁盘加载 source 与 artifact 数据库。
|
||||||
|
5. 立即扫描一次 `Assets`,补齐 `.meta` 并更新 source 记录。
|
||||||
|
|
||||||
|
## 关键语义
|
||||||
|
|
||||||
|
- 初始化阶段不会预先为所有 source asset 生成 artifact;artifact 仍然是按需生成。
|
||||||
|
- 当前没有增量监听器,因此这一步是“加载旧快照 + 重新扫目录”的模型。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [Refresh](Refresh.md)
|
||||||
|
- [Shutdown](Shutdown.md)
|
||||||
34
docs/api/XCEngine/Core/Asset/AssetDatabase/Refresh.md
Normal file
34
docs/api/XCEngine/Core/Asset/AssetDatabase/Refresh.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# AssetDatabase::Refresh
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void Refresh();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
重新扫描项目 `Assets` 目录,更新 source 资产索引与 `.meta`。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 当前实现只是调用 `ScanAssets()`。
|
||||||
|
- 会补齐缺失 `.meta`、更新 source 文件快照、移除已经不存在的 source 记录。
|
||||||
|
- 若发现 source 记录被删除,会同步从 artifact 索引中移除对应记录。
|
||||||
|
|
||||||
|
## 当前限制
|
||||||
|
|
||||||
|
- 不会主动为所有资产重建 artifact。
|
||||||
|
- 也不会自动通知编辑器 UI 或运行时缓存刷新;这些动作仍需外层系统自己串起来。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [Initialize](Initialize.md)
|
||||||
|
- [BuildLookupSnapshot](BuildLookupSnapshot.md)
|
||||||
38
docs/api/XCEngine/Core/Asset/AssetDatabase/ResolvePath.md
Normal file
38
docs/api/XCEngine/Core/Asset/AssetDatabase/ResolvePath.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# AssetDatabase::ResolvePath
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool ResolvePath(
|
||||||
|
const Containers::String& requestPath,
|
||||||
|
Containers::String& outAbsolutePath,
|
||||||
|
Containers::String& outRelativePath) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
把调用方给出的请求路径解析成绝对路径,并在可能时补出项目相对路径。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 空路径返回 `false`。
|
||||||
|
- 带 `://` 的虚拟路径返回 `false`。
|
||||||
|
- 若传入绝对路径,会直接规范化成 `outAbsolutePath`,并在它位于项目 `Assets` 下时补出 `outRelativePath`。
|
||||||
|
- 若传入 `Assets/...` 形式的相对路径,会补出绝对路径和相同的相对路径。
|
||||||
|
- 若传入其他项目相对路径,只会给出绝对路径,`outRelativePath` 保持为空。
|
||||||
|
|
||||||
|
## 关键语义
|
||||||
|
|
||||||
|
- `EnsureArtifact()` 需要 `outRelativePath` 非空,因此真正可导入的仍然只有项目 `Assets` 下的资产。
|
||||||
|
- 这个方法不检查目标文件是否存在,只做路径规范化和归类。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [EnsureArtifact](EnsureArtifact.md)
|
||||||
34
docs/api/XCEngine/Core/Asset/AssetDatabase/ResolvedAsset.md
Normal file
34
docs/api/XCEngine/Core/Asset/AssetDatabase/ResolvedAsset.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# AssetDatabase::ResolvedAsset
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `struct`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
**描述**: `EnsureArtifact()` 返回给调用方的解析结果,汇总 source 路径、GUID 和可直接加载的 artifact 主文件信息。
|
||||||
|
|
||||||
|
## 字段
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `exists` | `bool` | 当前 source asset 与 artifact 均成功解析时为 `true`。 |
|
||||||
|
| `artifactReady` | `bool` | 当前 artifact 已可用时为 `true`。 |
|
||||||
|
| `absolutePath` | `Containers::String` | source asset 的绝对路径。 |
|
||||||
|
| `relativePath` | `Containers::String` | source asset 的项目相对路径,通常是 `Assets/...`。 |
|
||||||
|
| `assetGuid` | `AssetGUID` | source asset GUID。 |
|
||||||
|
| `resourceType` | `ResourceType` | artifact 的主资源类型。 |
|
||||||
|
| `artifactMainPath` | `Containers::String` | 主 artifact 文件的绝对路径。 |
|
||||||
|
| `artifactDirectory` | `Containers::String` | artifact 目录的绝对路径。 |
|
||||||
|
| `mainLocalID` | `LocalID` | 主资产 local ID。 |
|
||||||
|
|
||||||
|
## 当前实现语义
|
||||||
|
|
||||||
|
- 当前实现里,`exists` 和 `artifactReady` 只会在完全成功时一起置为 `true`。
|
||||||
|
- 失败时整个结构会保持默认值,因此它还不能表达“source 已存在但 artifact 尚未生成”的中间态。
|
||||||
|
- `artifactMainPath` 与 `artifactDirectory` 都已经被展开为绝对路径,适合直接交给 loader 或文件系统调用。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [EnsureArtifact](EnsureArtifact.md)
|
||||||
32
docs/api/XCEngine/Core/Asset/AssetDatabase/Shutdown.md
Normal file
32
docs/api/XCEngine/Core/Asset/AssetDatabase/Shutdown.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# AssetDatabase::Shutdown
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void Shutdown();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
把数据库状态写回磁盘,并清空当前 `AssetDatabase` 的路径与索引缓存。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 先调用 `SaveSourceAssetDB()` 与 `SaveArtifactDB()`。
|
||||||
|
- 然后清空项目根、`Assets` 根、`Library` 根、数据库路径以及三张内存索引表。
|
||||||
|
|
||||||
|
## 关键语义
|
||||||
|
|
||||||
|
- 当前析构函数没有自动调用这一逻辑,因此显式生命周期管理仍然重要。
|
||||||
|
- 关闭不会删除 `Library` 下的 artifact 文件,只是保存索引并释放内存状态。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [Initialize](Initialize.md)
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# AssetDatabase::SourceAssetRecord
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `struct`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
**描述**: 保存 source asset 在扫描后的核心索引信息,包括 GUID、`.meta`、导入器、source 快照和最近一次成功构建的 artifact key。
|
||||||
|
|
||||||
|
## 字段
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `guid` | `AssetGUID` | 该 source asset 的稳定 GUID。 |
|
||||||
|
| `relativePath` | `Containers::String` | 相对项目根的路径,通常是 `Assets/...`。 |
|
||||||
|
| `metaPath` | `Containers::String` | sidecar `.meta` 的相对路径。 |
|
||||||
|
| `isFolder` | `bool` | 是否为文件夹资产。 |
|
||||||
|
| `importerName` | `Containers::String` | 当前推断或从 `.meta` 读出的 importer 名称。 |
|
||||||
|
| `importerVersion` | `Core::uint32` | 当前 importer 版本;扫描阶段会强制对齐到 `kCurrentImporterVersion`。 |
|
||||||
|
| `metaHash` | `Containers::String` | `.meta` 文件内容哈希。 |
|
||||||
|
| `sourceHash` | `Containers::String` | 源文件内容哈希;文件夹资产为空。 |
|
||||||
|
| `sourceFileSize` | `Core::uint64` | 源文件大小;文件夹资产为 `0`。 |
|
||||||
|
| `sourceWriteTime` | `Core::uint64` | 源文件写时间;文件夹资产为 `0`。 |
|
||||||
|
| `lastKnownArtifactKey` | `Containers::String` | 最近一次成功导入后记录的 artifact key。 |
|
||||||
|
|
||||||
|
## 当前实现语义
|
||||||
|
|
||||||
|
- `EnsureMetaForPath()` 会在扫描时维护这里的大部分字段。
|
||||||
|
- 若 `.meta` 缺失、无效、GUID 冲突,或 importerVersion 过旧,当前实现会重写 `.meta`。
|
||||||
|
- 若文件大小和写时间未变化,扫描阶段会复用旧的 `sourceHash`,避免重复计算文件哈希。
|
||||||
|
- `lastKnownArtifactKey` 会在 `EnsureArtifact()` 成功重建后回写,但真正的重导入判定仍依赖 `ArtifactRecord` 与当前文件系统快照,而不是只看这个字段。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [ArtifactRecord](ArtifactRecord.md)
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# AssetDatabase::TryGetAssetGuid
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool TryGetAssetGuid(const Containers::String& requestPath, AssetGUID& outGuid) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
通过 source 路径查询对应的 `AssetGUID`。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 先调用 [ResolvePath](ResolvePath.md)。
|
||||||
|
- 只有能解析到项目相对路径的 `Assets/...` 请求才会继续查表。
|
||||||
|
- 内部使用规范化、转小写后的路径 key 查 `m_sourcesByPathKey`。
|
||||||
|
- 找到后把记录中的 GUID 写到 `outGuid`,并要求 GUID 本身有效。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [TryGetAssetRef](TryGetAssetRef.md)
|
||||||
|
- [TryGetPrimaryAssetPath](TryGetPrimaryAssetPath.md)
|
||||||
43
docs/api/XCEngine/Core/Asset/AssetDatabase/TryGetAssetRef.md
Normal file
43
docs/api/XCEngine/Core/Asset/AssetDatabase/TryGetAssetRef.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# AssetDatabase::TryGetAssetRef
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool TryGetAssetRef(
|
||||||
|
const Containers::String& requestPath,
|
||||||
|
ResourceType resourceType,
|
||||||
|
AssetRef& outRef) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
把 source 路径包装成当前主资产的 `AssetRef`。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 内部先通过 [TryGetAssetGuid](TryGetAssetGuid.md) 查 GUID。
|
||||||
|
- 成功后把:
|
||||||
|
- `assetGuid`
|
||||||
|
- `localID = kMainAssetLocalID`
|
||||||
|
- `resourceType = 调用方传入值`
|
||||||
|
写入 `outRef`。
|
||||||
|
|
||||||
|
## 关键语义
|
||||||
|
|
||||||
|
- 这个方法不检查传入的 `resourceType` 是否与 source asset 的 importer 类型一致。
|
||||||
|
- 这个方法也不会触发 `EnsureArtifact()`;只要路径能稳定映射到 GUID,它就可以成功。
|
||||||
|
- 真正的类型匹配要到 [EnsureArtifact](EnsureArtifact.md) 或后续 `ResourceManager::LoadResource()` 阶段才会校验。
|
||||||
|
|
||||||
|
因此它更适合被理解成“主资产身份查询”,而不是“可加载资源可用性检查”。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [TryGetAssetGuid](TryGetAssetGuid.md)
|
||||||
|
- [ResolvedAsset](ResolvedAsset.md)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# AssetDatabase::TryGetPrimaryAssetPath
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetDatabase.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool TryGetPrimaryAssetPath(const AssetGUID& guid, Containers::String& outRelativePath) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
通过 GUID 反查主 source asset 的项目相对路径。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 直接查 `m_sourcesByGuid`。
|
||||||
|
- 命中后返回记录里的 `relativePath`,通常是 `Assets/...`。
|
||||||
|
- 不会返回 artifact 路径,也不会检查 artifact 当前是否可用。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetDatabase](AssetDatabase.md)
|
||||||
|
- [TryGetAssetGuid](TryGetAssetGuid.md)
|
||||||
|
- [BuildLookupSnapshot](BuildLookupSnapshot.md)
|
||||||
160
docs/api/XCEngine/Core/Asset/AssetGUID/AssetGUID.md
Normal file
160
docs/api/XCEngine/Core/Asset/AssetGUID/AssetGUID.md
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
# AssetGUID
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `header-overview`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetGUID.h`
|
||||||
|
|
||||||
|
**描述**: 定义项目资产的 128 位标识、`LocalID` 约定,以及字符串/字节到 `AssetGUID` 的辅助生成函数。
|
||||||
|
|
||||||
|
## 角色概述
|
||||||
|
|
||||||
|
`AssetGUID` 是当前项目资产层的稳定身份基石。
|
||||||
|
|
||||||
|
在这套资源系统里,运行时实例的缓存键和项目资产的身份不是一回事:
|
||||||
|
|
||||||
|
- 运行时 `IResource` 仍有自己那套 `ResourceGUID`
|
||||||
|
- 项目里的 source asset、`.meta`、artifact 数据库、`AssetRef` 则统一围绕 `AssetGUID`
|
||||||
|
|
||||||
|
这让系统可以把“项目资产身份”与“某次加载出来的运行时对象”分层处理。
|
||||||
|
|
||||||
|
## 当前公开内容
|
||||||
|
|
||||||
|
### `AssetGUID`
|
||||||
|
|
||||||
|
`AssetGUID` 本体由两个 `uint64` 组成:
|
||||||
|
|
||||||
|
- `high`
|
||||||
|
- `low`
|
||||||
|
|
||||||
|
它提供:
|
||||||
|
|
||||||
|
- `IsValid()`
|
||||||
|
- `operator==`
|
||||||
|
- `operator!=`
|
||||||
|
- `Generate()`
|
||||||
|
- `TryParse()`
|
||||||
|
- `ParseOrDefault()`
|
||||||
|
- `ToString()`
|
||||||
|
|
||||||
|
### `LocalID`
|
||||||
|
|
||||||
|
头文件还同时定义了:
|
||||||
|
|
||||||
|
- `using LocalID = Core::uint64`
|
||||||
|
- `kInvalidLocalID = 0`
|
||||||
|
- `kMainAssetLocalID = 1`
|
||||||
|
|
||||||
|
这套约定是给 `AssetRef` 用的,用来在同一个 `AssetGUID` 下进一步区分主资产和潜在子资产。
|
||||||
|
|
||||||
|
### 辅助函数与哈希
|
||||||
|
|
||||||
|
- `HashBytesToAssetGUID(const void*, size_t)`
|
||||||
|
- `HashStringToAssetGUID(const Containers::String&)`
|
||||||
|
- `std::hash<AssetGUID>`
|
||||||
|
|
||||||
|
其中 `std::hash<AssetGUID>` 主要服务 `unordered_map` / `unordered_set` 这类容器。
|
||||||
|
|
||||||
|
## 生成与解析语义
|
||||||
|
|
||||||
|
### 随机生成
|
||||||
|
|
||||||
|
`AssetGUID::Generate()` 当前使用 `std::mt19937_64` 连续生成 `high` 和 `low`,并循环跳过全零 GUID。
|
||||||
|
|
||||||
|
这说明它的定位是:
|
||||||
|
|
||||||
|
- 可以生成新的随机资产身份
|
||||||
|
- 但它不是 RFC 风格 UUID,也没有版本位语义
|
||||||
|
|
||||||
|
真正能让 GUID 跨重启稳定的,不是 `Generate()` 本身,而是它被写进 `.meta` 并持久化下来。
|
||||||
|
|
||||||
|
### 字符串格式
|
||||||
|
|
||||||
|
`ToString()` 当前固定输出:
|
||||||
|
|
||||||
|
- 32 个十六进制字符
|
||||||
|
- 先 `high` 后 `low`
|
||||||
|
- 小写
|
||||||
|
- 不带连字符、花括号或前缀
|
||||||
|
|
||||||
|
例如形状是:
|
||||||
|
|
||||||
|
`0123456789abcdeffedcba9876543210`
|
||||||
|
|
||||||
|
### 解析规则
|
||||||
|
|
||||||
|
`TryParse()` 当前要求非常严格:
|
||||||
|
|
||||||
|
- 长度必须正好是 `32`
|
||||||
|
- 每一位都必须是十六进制字符
|
||||||
|
- 不接受 `-` 分隔格式
|
||||||
|
- 不接受大括号包裹格式
|
||||||
|
|
||||||
|
但它同时接受大小写十六进制字符;真正写回时,`ToString()` 会统一成小写。
|
||||||
|
|
||||||
|
`ParseOrDefault()` 则是在解析失败时直接返回全零无效 GUID。
|
||||||
|
|
||||||
|
## 确定性哈希语义
|
||||||
|
|
||||||
|
除了随机生成,这个头文件还提供“从内容派生 GUID”的辅助函数。
|
||||||
|
|
||||||
|
### `HashBytesToAssetGUID()`
|
||||||
|
|
||||||
|
- 对字节序列做两次不同 seed 的 FNV-1a 64 位哈希
|
||||||
|
- 结果分别填进 `high` 和 `low`
|
||||||
|
- `data == nullptr` 或 `size == 0` 时返回无效全零 GUID
|
||||||
|
|
||||||
|
### `HashStringToAssetGUID()`
|
||||||
|
|
||||||
|
- 直接对 `text.CStr()` 与 `text.Length()` 做哈希
|
||||||
|
- 不额外附带终止符
|
||||||
|
|
||||||
|
这类哈希 GUID 当前主要用于“稳定签名”而不是“随机身份”:
|
||||||
|
|
||||||
|
- `AssetDatabase` 用它计算 `.meta` 内容哈希
|
||||||
|
- 也用它参与 artifact key / 内容签名相关逻辑
|
||||||
|
|
||||||
|
需要把它理解成轻量、可复现的标识生成器,而不是抗碰撞的密码学摘要。
|
||||||
|
|
||||||
|
## 在当前资产链路中的作用
|
||||||
|
|
||||||
|
### 项目资产身份
|
||||||
|
|
||||||
|
`AssetDatabase` 会把 `AssetGUID` 持久化到每个 `.meta` sidecar,并用它连接:
|
||||||
|
|
||||||
|
- source asset 记录
|
||||||
|
- artifact 记录
|
||||||
|
- path/GUID 查询表
|
||||||
|
|
||||||
|
这让文件重命名、相对路径变化和 artifact 重建可以围绕同一资产身份继续工作。
|
||||||
|
|
||||||
|
### 资产反查与引用
|
||||||
|
|
||||||
|
- `AssetDatabase::TryGetPrimaryAssetPath()` 做 GUID 到主 source 路径的反查
|
||||||
|
- `AssetDatabase::TryGetAssetRef()` 和 `ResourceManager::TryGetAssetRef()` 用它组装 `AssetRef`
|
||||||
|
- `ResourceManager::TryResolveAssetPath()` 也最终依赖 `AssetGUID` 找回 `Assets/...` 路径
|
||||||
|
|
||||||
|
### `LocalID` 现状
|
||||||
|
|
||||||
|
虽然已经定义了 `LocalID`,但当前主链路几乎都只使用:
|
||||||
|
|
||||||
|
- `kMainAssetLocalID`
|
||||||
|
|
||||||
|
也就是说,现在的系统主要还是“一个 GUID 对应一个主资产”的模型,子资产寻址接口已经预留,但还没有真正展开。
|
||||||
|
|
||||||
|
## 当前实现边界
|
||||||
|
|
||||||
|
- `TryParse()` 只接受 32 位纯十六进制文本,格式容忍度很低。
|
||||||
|
- 全零 GUID 是统一的无效哨兵值;空输入哈希也会落到这个值。
|
||||||
|
- `HashBytesToAssetGUID()` / `HashStringToAssetGUID()` 不是密码学安全哈希,理论上存在碰撞可能。
|
||||||
|
- `Generate()` 生成的是随机值,不持久化就不会天然稳定。
|
||||||
|
- `LocalID` 概念已经存在,但当前没有公开的子资产 ID 分配规则。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [当前模块](../Asset.md)
|
||||||
|
- [AssetDatabase](../AssetDatabase/AssetDatabase.md)
|
||||||
|
- [AssetRef](../AssetRef/AssetRef.md)
|
||||||
|
- [ResourceManager](../ResourceManager/ResourceManager.md)
|
||||||
|
- [API 总索引](../../../../main.md)
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
# AssetImportService
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `class`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
**描述**: 以线程安全服务层的形式封装 `AssetDatabase`,向 `ResourceManager` 和 `ProjectAssetIndex` 暴露项目资产导入、`AssetRef` 查询、`Library` 根目录查询以及 lookup snapshot 导出能力。
|
||||||
|
|
||||||
|
## 概览
|
||||||
|
|
||||||
|
`AssetImportService` 是当前 `Core/Asset` 分层里的“受控数据库入口”:
|
||||||
|
|
||||||
|
- [AssetDatabase](../AssetDatabase/AssetDatabase.md) 负责真实的扫描、`.meta`、artifact 与导入逻辑
|
||||||
|
- `AssetImportService` 用一把 `std::recursive_mutex` 串行化这些数据库入口,并把结果整理成更适合运行时消费的服务 API
|
||||||
|
- [ProjectAssetIndex](../ProjectAssetIndex/ProjectAssetIndex.md) 再基于它导出的 [LookupSnapshot](LookupSnapshot.md) 构建热路径查询缓存
|
||||||
|
|
||||||
|
## 公开类型
|
||||||
|
|
||||||
|
### `LookupSnapshot`
|
||||||
|
|
||||||
|
[LookupSnapshot](LookupSnapshot.md) 是一个值对象,里面保存两张表:
|
||||||
|
|
||||||
|
- `path key -> AssetGUID`
|
||||||
|
- `AssetGUID -> relative path`
|
||||||
|
|
||||||
|
它的用途不是长期持有数据库状态,而是给 `ProjectAssetIndex::RefreshFrom()` 做一次性整体拉取。
|
||||||
|
|
||||||
|
### `ImportedAsset`
|
||||||
|
|
||||||
|
[ImportedAsset](ImportedAsset.md) 是 [EnsureArtifact](EnsureArtifact.md) 的输出对象。它把 `AssetDatabase::ResolvedAsset` 转成更适合运行时装配的结果:
|
||||||
|
|
||||||
|
- 保留 source 绝对路径、`Assets/...` 相对路径和 `AssetGUID`
|
||||||
|
- 保留 `artifactDirectory` 与 `mainLocalID`
|
||||||
|
- 暴露 `runtimeLoadPath`,供 `ResourceManager::LoadResource()` 决定真正交给 loader 的路径
|
||||||
|
|
||||||
|
按 `ConvertResolvedAsset()` 的字段转换规则,`runtimeLoadPath` 会在 `artifactReady=true` 时取主 artifact 绝对路径,否则退回 source 绝对路径;但按当前 `AssetDatabase::EnsureArtifact()` 的实现,`AssetImportService::EnsureArtifact()` 只有在主 artifact 已经可用时才会成功返回,因此当前成功路径里的 `runtimeLoadPath` 实际上总是指向 `Library/Artifacts/.../main.*`。
|
||||||
|
|
||||||
|
## 生命周期
|
||||||
|
|
||||||
|
### `Initialize()`
|
||||||
|
|
||||||
|
当前实现是空函数。它更像一个生命周期锚点,给未来后台导入队列或统计能力预留挂接位置。
|
||||||
|
|
||||||
|
### `Shutdown()`
|
||||||
|
|
||||||
|
`Shutdown()` 会在锁内执行:
|
||||||
|
|
||||||
|
- `m_assetDatabase.Shutdown()`
|
||||||
|
- 清空 `m_projectRoot`
|
||||||
|
|
||||||
|
这会彻底断开当前项目的资产数据库状态,而不只是清理临时缓存。
|
||||||
|
|
||||||
|
### `SetProjectRoot()` / `GetProjectRoot()` / `GetLibraryRoot()`
|
||||||
|
|
||||||
|
- `SetProjectRoot()` 是最关键的状态切换入口
|
||||||
|
- 如果新旧项目根相同,直接返回
|
||||||
|
- 如果旧项目根非空,先关闭旧的 `AssetDatabase`
|
||||||
|
- 写入新的 `m_projectRoot` 后,若新项目根非空则重新初始化 `AssetDatabase`
|
||||||
|
- [GetLibraryRoot](GetLibraryRoot.md) 返回当前项目 `Library` 根目录的绝对路径,供测试和更高层缓存重建入口使用
|
||||||
|
|
||||||
|
因此它当前是单项目绑定服务,不支持同时托管多个项目根。
|
||||||
|
|
||||||
|
## 当前公开能力
|
||||||
|
|
||||||
|
### `Refresh()`
|
||||||
|
|
||||||
|
在项目根有效时转发到 `AssetDatabase::Refresh()`,用于重新扫描 source 资产并刷新数据库状态。
|
||||||
|
|
||||||
|
### `RebuildLibraryCache()`
|
||||||
|
|
||||||
|
[RebuildLibraryCache](RebuildLibraryCache.md) 是更重的入口:
|
||||||
|
|
||||||
|
1. 记录当前 `projectRoot` 和 `libraryRoot`
|
||||||
|
2. `m_assetDatabase.Shutdown()`
|
||||||
|
3. 删除整个 `Library` 目录
|
||||||
|
4. 用原项目根重新 `Initialize()`
|
||||||
|
|
||||||
|
测试 `AssetImportService_Test.RebuildLibraryCacheKeepsStableAssetRefs` 说明它会清空缓存产物,但不会破坏现有 `.meta` 驱动的 `AssetGUID` 稳定性。
|
||||||
|
|
||||||
|
### `EnsureArtifact()`
|
||||||
|
|
||||||
|
[EnsureArtifact](EnsureArtifact.md) 会在项目根有效时转发到底层数据库,并把结果转换成 [ImportedAsset](ImportedAsset.md)。
|
||||||
|
|
||||||
|
当前成功路径里:
|
||||||
|
|
||||||
|
- `artifactReady` 为 `true`
|
||||||
|
- `runtimeLoadPath` 指向主 artifact 的绝对路径
|
||||||
|
- `absolutePath` / `relativePath` / `assetGuid` 仍保留 source 资产身份
|
||||||
|
|
||||||
|
`ResourceManager::LoadResource()` 用它决定真正交给 loader 的加载路径。
|
||||||
|
|
||||||
|
### `TryGetAssetRef()` / `TryGetPrimaryAssetPath()`
|
||||||
|
|
||||||
|
- `TryGetAssetRef()` 按请求路径解析主资产 `AssetRef`
|
||||||
|
- `TryGetPrimaryAssetPath()` 通过 `AssetGUID` 反查主相对路径
|
||||||
|
|
||||||
|
它们都只负责数据库查询本身;高频缓存和 cache miss 刷新策略由 `ProjectAssetIndex` 负责。
|
||||||
|
|
||||||
|
### `BuildLookupSnapshot()`
|
||||||
|
|
||||||
|
[BuildLookupSnapshot](BuildLookupSnapshot.md) 会先清空传入的 [LookupSnapshot](LookupSnapshot.md),再导出当前双向查询表。这是 `ProjectAssetIndex` 刷新本地 snapshot 的唯一上游入口。
|
||||||
|
|
||||||
|
## 与 `ResourceManager` 的关系
|
||||||
|
|
||||||
|
`ResourceManager` 不再直接把 `AssetDatabase` 当成自己的内部实现细节,而是通过 `AssetImportService` 访问项目资产层:
|
||||||
|
|
||||||
|
- `SetResourceRoot()` 用它切换项目根
|
||||||
|
- `LoadResource()` 用它确保 artifact 就绪
|
||||||
|
- [RefreshProjectAssets](../ResourceManager/RefreshProjectAssets.md) 用它刷新数据库,再同步重建 `ProjectAssetIndex`
|
||||||
|
- [RebuildProjectAssetCache](../ResourceManager/RebuildProjectAssetCache.md) 用它重建整个 `Library` 缓存
|
||||||
|
|
||||||
|
这让“数据库导入能力”和“运行时资源加载器”之间多了一层清晰职责边界。
|
||||||
|
|
||||||
|
## 当前实现边界
|
||||||
|
|
||||||
|
- `Initialize()` 仍是空实现,没有后台导入线程或事件订阅
|
||||||
|
- 没有项目根时,所有数据库相关入口都会直接失败或返回空结果
|
||||||
|
- 线程模型当前很直接: 一把 `recursive_mutex` 串行化所有服务入口
|
||||||
|
- `LookupSnapshot` 是整份重建,不是增量同步
|
||||||
|
|
||||||
|
## 相关方法
|
||||||
|
|
||||||
|
- [Initialize](Initialize.md)
|
||||||
|
- [Shutdown](Shutdown.md)
|
||||||
|
- [SetProjectRoot](SetProjectRoot.md)
|
||||||
|
- [GetProjectRoot](GetProjectRoot.md)
|
||||||
|
- [GetLibraryRoot](GetLibraryRoot.md)
|
||||||
|
- [Refresh](Refresh.md)
|
||||||
|
- [RebuildLibraryCache](RebuildLibraryCache.md)
|
||||||
|
- [EnsureArtifact](EnsureArtifact.md)
|
||||||
|
- [TryGetAssetRef](TryGetAssetRef.md)
|
||||||
|
- [TryGetPrimaryAssetPath](TryGetPrimaryAssetPath.md)
|
||||||
|
- [BuildLookupSnapshot](BuildLookupSnapshot.md)
|
||||||
|
- [LookupSnapshot](LookupSnapshot.md)
|
||||||
|
- [ImportedAsset](ImportedAsset.md)
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [当前模块](../Asset.md)
|
||||||
|
- [AssetDatabase](../AssetDatabase/AssetDatabase.md)
|
||||||
|
- [ProjectAssetIndex](../ProjectAssetIndex/ProjectAssetIndex.md)
|
||||||
|
- [ResourceManager](../ResourceManager/ResourceManager.md)
|
||||||
|
- [API 总索引](../../../../main.md)
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# AssetImportService::BuildLookupSnapshot
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void BuildLookupSnapshot(LookupSnapshot& outSnapshot) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
导出当前项目资产的 `path <-> AssetGUID` 查询快照。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 在 `std::recursive_mutex` 保护下执行。
|
||||||
|
- 先调用 `outSnapshot.Clear()` 清空已有内容。
|
||||||
|
- 如果当前没有项目根,直接返回空快照。
|
||||||
|
- 否则转发到 `AssetDatabase::BuildLookupSnapshot()`,填充:
|
||||||
|
- `outSnapshot.assetGuidByPathKey`
|
||||||
|
- `outSnapshot.assetPathByGuid`
|
||||||
|
|
||||||
|
## 当前语义
|
||||||
|
|
||||||
|
- 这是一次性值拷贝,不是把 `AssetDatabase` 的内部 map 直接暴露给外部。
|
||||||
|
- `ProjectAssetIndex::RefreshFrom()` 会在锁外构建完整 snapshot,再整体替换本地索引。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetImportService](AssetImportService.md)
|
||||||
|
- [LookupSnapshot](LookupSnapshot.md)
|
||||||
|
- [ProjectAssetIndex::RefreshFrom](../ProjectAssetIndex/RefreshFrom.md)
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# AssetImportService::EnsureArtifact
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool EnsureArtifact(
|
||||||
|
const Containers::String& requestPath,
|
||||||
|
ResourceType requestedType,
|
||||||
|
ImportedAsset& outAsset);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
确保指定项目资产请求已经具备可供运行时加载的主 artifact,并把数据库层结果转换成服务层返回对象。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 在 `std::recursive_mutex` 保护下执行
|
||||||
|
- 如果当前没有项目根,直接返回 `false`
|
||||||
|
- 否则先调用 `AssetDatabase::EnsureArtifact()`,再把得到的 `ResolvedAsset` 转成 [ImportedAsset](ImportedAsset.md)
|
||||||
|
- 字段转换时,`ConvertResolvedAsset()` 会把 `runtimeLoadPath` 设为:
|
||||||
|
- `artifactMainPath`,当 `artifactReady=true`
|
||||||
|
- `absolutePath`,当 `artifactReady=false`
|
||||||
|
|
||||||
|
但按当前实现,`AssetDatabase::EnsureArtifact()` 只有在主 artifact 已可直接使用时才会返回成功,因此这条服务 API 的当前成功路径里,`runtimeLoadPath` 实际总是主 artifact 的绝对路径。
|
||||||
|
|
||||||
|
## 当前语义
|
||||||
|
|
||||||
|
- 这一层不再把 `AssetDatabase::ResolvedAsset` 直接暴露给上游
|
||||||
|
- `ResourceManager::LoadResource()` 用它决定后续应该让 loader 读取 source 文件还是读取 `Library/Artifacts/.../main.*`
|
||||||
|
- 以当前代码路径来看,只要本方法返回 `true`,调用方就可以把 `runtimeLoadPath` 当作可直接交给 loader 的最终路径
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetImportService](AssetImportService.md)
|
||||||
|
- [ImportedAsset](ImportedAsset.md)
|
||||||
|
- [AssetDatabase::EnsureArtifact](../AssetDatabase/EnsureArtifact.md)
|
||||||
|
- [ResourceManager](../ResourceManager/ResourceManager.md)
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# AssetImportService::GetLibraryRoot
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Containers::String GetLibraryRoot() const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
返回当前项目 `Library` 目录的根路径。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 在 `std::recursive_mutex` 保护下执行。
|
||||||
|
- 直接返回 `m_assetDatabase.GetLibraryRoot()` 的按值副本。
|
||||||
|
- 如果当前还没有设置项目根,通常返回空字符串。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetImportService](AssetImportService.md)
|
||||||
|
- [SetProjectRoot](SetProjectRoot.md)
|
||||||
|
- [RebuildLibraryCache](RebuildLibraryCache.md)
|
||||||
|
- [ResourceManager::GetProjectLibraryRoot](../ResourceManager/GetProjectLibraryRoot.md)
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# AssetImportService::GetProjectRoot
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Containers::String GetProjectRoot() const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
返回当前项目根路径副本。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 在 `std::recursive_mutex` 保护下执行。
|
||||||
|
- 返回的是 `Containers::String` 副本,不暴露内部引用。
|
||||||
|
- 当前未绑定项目根时返回空字符串。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetImportService](AssetImportService.md)
|
||||||
|
- [SetProjectRoot](SetProjectRoot.md)
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# AssetImportService::ImportedAsset
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `struct`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
## 概览
|
||||||
|
|
||||||
|
`ImportedAsset` 是 `AssetImportService::EnsureArtifact()` 向上层返回的轻量结果对象。它把 `AssetDatabase::ResolvedAsset` 转成更适合运行时消费的形态。
|
||||||
|
|
||||||
|
## 当前字段
|
||||||
|
|
||||||
|
- `exists`
|
||||||
|
- source 资产是否存在
|
||||||
|
- `artifactReady`
|
||||||
|
- 对应主 artifact 是否已经就绪
|
||||||
|
- `absolutePath`
|
||||||
|
- source 资产绝对路径
|
||||||
|
- `relativePath`
|
||||||
|
- 项目内相对路径,通常是 `Assets/...`
|
||||||
|
- `assetGuid`
|
||||||
|
- source 资产的稳定身份
|
||||||
|
- `resourceType`
|
||||||
|
- 当前导入得到的主资源类型
|
||||||
|
- `runtimeLoadPath`
|
||||||
|
- 运行时实际应交给 loader 的路径
|
||||||
|
- `ConvertResolvedAsset()` 会在 `artifactReady=true` 时写入主 artifact 绝对路径
|
||||||
|
- 否则回退到 `absolutePath`
|
||||||
|
- `artifactDirectory`
|
||||||
|
- 当前 artifact 目录的绝对路径
|
||||||
|
- `mainLocalID`
|
||||||
|
- 当前主资产的 local ID,默认值是 `kMainAssetLocalID`
|
||||||
|
|
||||||
|
## 当前实现语义
|
||||||
|
|
||||||
|
- 它不是持久化格式,也不是数据库记录本身;只是服务层返回给运行时装配链路的结果快照
|
||||||
|
- `ResourceManager::LoadResource()` 主要依赖它决定:
|
||||||
|
- 是否把请求路径切换成 artifact 主文件路径
|
||||||
|
- 是否把 `assetGuid -> relativePath` 关系回填给 `ProjectAssetIndex`
|
||||||
|
- 虽然结构体字段允许表达“source 已知但 artifact 尚未就绪”的形态,但按当前 `AssetImportService::EnsureArtifact()` 的公开成功路径,调用方实际拿到的结果总是 `artifactReady=true`
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetImportService](AssetImportService.md)
|
||||||
|
- [EnsureArtifact](EnsureArtifact.md)
|
||||||
|
- [AssetDatabase::ResolvedAsset](../AssetDatabase/ResolvedAsset.md)
|
||||||
|
- [ResourceManager](../ResourceManager/ResourceManager.md)
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# AssetImportService::Initialize
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void Initialize();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
初始化 `AssetImportService`。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 当前实现为空。
|
||||||
|
- 不会创建 `AssetDatabase`,也不会设置项目根。
|
||||||
|
- 真正的数据库切换入口是 [SetProjectRoot](SetProjectRoot.md)。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetImportService](AssetImportService.md)
|
||||||
|
- [SetProjectRoot](SetProjectRoot.md)
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# AssetImportService::LookupSnapshot
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `struct`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
`LookupSnapshot` 是 `AssetImportService` 导出的只读查询快照,供 [ProjectAssetIndex](../ProjectAssetIndex/ProjectAssetIndex.md) 一次性拉取当前 `path <-> AssetGUID` 映射。
|
||||||
|
|
||||||
|
## 当前字段
|
||||||
|
|
||||||
|
- `assetGuidByPathKey`
|
||||||
|
- 规范化路径键到 `AssetGUID` 的映射。
|
||||||
|
- `assetPathByGuid`
|
||||||
|
- `AssetGUID` 到主相对路径的映射。
|
||||||
|
|
||||||
|
## 当前公开能力
|
||||||
|
|
||||||
|
### `Clear()`
|
||||||
|
|
||||||
|
- 清空两张 lookup 表。
|
||||||
|
- [BuildLookupSnapshot](BuildLookupSnapshot.md) 会先调用它,再决定是否从 `AssetDatabase` 填充新快照。
|
||||||
|
|
||||||
|
## 设计位置
|
||||||
|
|
||||||
|
- 这个结构体不是长期持有的数据库对象,而是一次性导出的值对象。
|
||||||
|
- `ProjectAssetIndex::RefreshFrom()` 会在锁外构建完整快照,再在锁内整体替换本地索引,避免读线程看到半更新状态。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetImportService](AssetImportService.md)
|
||||||
|
- [BuildLookupSnapshot](BuildLookupSnapshot.md)
|
||||||
|
- [ProjectAssetIndex::RefreshFrom](../ProjectAssetIndex/RefreshFrom.md)
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# AssetImportService::RebuildLibraryCache
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool RebuildLibraryCache();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
删除当前项目的 `Library` 目录,并重新初始化 `AssetDatabase`。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 在 `std::recursive_mutex` 保护下执行
|
||||||
|
- 如果当前没有项目根,直接返回 `false`
|
||||||
|
- 否则会:
|
||||||
|
1. 记录当前 `projectRoot` 和 `libraryRoot`
|
||||||
|
2. `m_assetDatabase.Shutdown()`
|
||||||
|
3. 调用 `std::filesystem::remove_all(libraryRoot, ec)`
|
||||||
|
4. 用原来的 `projectRoot` 重新 `Initialize()`
|
||||||
|
- 返回值表示 `remove_all` 是否没有报告错误,而不是“实际删除了多少文件”
|
||||||
|
|
||||||
|
## 当前语义
|
||||||
|
|
||||||
|
- 这是导入缓存层的重建入口,比普通的 [Refresh](Refresh.md) 更重
|
||||||
|
- 它不会改动 `.meta` 里的 `AssetGUID`,因此已生成 `AssetRef` 的稳定性仍由 source 资产身份保证
|
||||||
|
- `tests/core/Asset/test_resource_manager.cpp` 中的 `AssetImportService_Test.RebuildLibraryCacheKeepsStableAssetRefs` 专门覆盖了这条语义
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetImportService](AssetImportService.md)
|
||||||
|
- [GetLibraryRoot](GetLibraryRoot.md)
|
||||||
|
- [Refresh](Refresh.md)
|
||||||
|
- [ResourceManager::RebuildProjectAssetCache](../ResourceManager/RebuildProjectAssetCache.md)
|
||||||
28
docs/api/XCEngine/Core/Asset/AssetImportService/Refresh.md
Normal file
28
docs/api/XCEngine/Core/Asset/AssetImportService/Refresh.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# AssetImportService::Refresh
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void Refresh();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
刷新当前项目根对应的资产数据库。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 在 `std::recursive_mutex` 保护下执行。
|
||||||
|
- 只有 `m_projectRoot` 非空时才会调用 `AssetDatabase::Refresh()`。
|
||||||
|
- 空项目根下调用会被安全忽略。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetImportService](AssetImportService.md)
|
||||||
|
- [BuildLookupSnapshot](BuildLookupSnapshot.md)
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# AssetImportService::SetProjectRoot
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void SetProjectRoot(const Containers::String& projectRoot);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
切换当前绑定的项目根目录。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 在 `std::recursive_mutex` 保护下执行。
|
||||||
|
- 若新旧 `projectRoot` 相同,直接返回。
|
||||||
|
- 若旧项目根非空,会先关闭内部 `AssetDatabase`。
|
||||||
|
- 更新 `m_projectRoot` 后,只有新项目根非空时才会调用 `AssetDatabase::Initialize()`。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetImportService](AssetImportService.md)
|
||||||
|
- [GetProjectRoot](GetProjectRoot.md)
|
||||||
|
- [Shutdown](Shutdown.md)
|
||||||
28
docs/api/XCEngine/Core/Asset/AssetImportService/Shutdown.md
Normal file
28
docs/api/XCEngine/Core/Asset/AssetImportService/Shutdown.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# AssetImportService::Shutdown
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void Shutdown();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
关闭内部资产数据库并清空当前项目根。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 在 `std::recursive_mutex` 保护下执行。
|
||||||
|
- 调用内部 `AssetDatabase::Shutdown()`。
|
||||||
|
- 调用后会把 `m_projectRoot` 清空。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetImportService](AssetImportService.md)
|
||||||
|
- [SetProjectRoot](SetProjectRoot.md)
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# AssetImportService::TryGetAssetRef
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool TryGetAssetRef(
|
||||||
|
const Containers::String& requestPath,
|
||||||
|
ResourceType resourceType,
|
||||||
|
AssetRef& outRef) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
按请求路径解析主资产 `AssetRef`。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 在 `std::recursive_mutex` 保护下执行。
|
||||||
|
- 若当前没有项目根,直接返回 `false`。
|
||||||
|
- 否则转发到 `AssetDatabase::TryGetAssetRef()`。
|
||||||
|
- 读优化和 cache miss 刷新逻辑不在这里,而在 [ProjectAssetIndex](../ProjectAssetIndex/ProjectAssetIndex.md)。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetImportService](AssetImportService.md)
|
||||||
|
- [ProjectAssetIndex::TryGetAssetRef](../ProjectAssetIndex/TryGetAssetRef.md)
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# AssetImportService::TryGetPrimaryAssetPath
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetImportService.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool TryGetPrimaryAssetPath(
|
||||||
|
const AssetGUID& guid,
|
||||||
|
Containers::String& outRelativePath) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
按 `AssetGUID` 反查主资产相对路径。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 在 `std::recursive_mutex` 保护下执行。
|
||||||
|
- 若当前没有项目根,直接返回 `false`。
|
||||||
|
- 否则转发到 `AssetDatabase::TryGetPrimaryAssetPath()`。
|
||||||
|
- 返回路径通常是相对项目根的 `Assets/...` 形式。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [AssetImportService](AssetImportService.md)
|
||||||
|
- [ProjectAssetIndex::TryResolveAssetPath](../ProjectAssetIndex/TryResolveAssetPath.md)
|
||||||
129
docs/api/XCEngine/Core/Asset/AssetRef/AssetRef.md
Normal file
129
docs/api/XCEngine/Core/Asset/AssetRef/AssetRef.md
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
# AssetRef
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `header-overview`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/AssetRef.h`
|
||||||
|
|
||||||
|
**描述**: 定义项目资产引用的最小身份元组,用 `AssetGUID + LocalID + ResourceType` 表达一个可序列化的资产目标。
|
||||||
|
|
||||||
|
## 角色概述
|
||||||
|
|
||||||
|
`AssetRef` 解决的问题不是“如何加载一个路径”,而是“如何在路径变化后仍然能找到同一个项目资产”。
|
||||||
|
|
||||||
|
当前资源链路里,路径只适合做即时查找,但不适合做长期引用标识;`AssetRef` 则是那层更稳定的序列化外壳。它通常经历这样的流程:
|
||||||
|
|
||||||
|
1. 上层拿 `Assets/...` 路径向 `ResourceManager` 或 `AssetDatabase` 请求一个 `AssetRef`
|
||||||
|
2. 组件、场景或其他序列化数据保存这个引用
|
||||||
|
3. 反序列化时再把 `AssetRef` 解析回主 source 路径
|
||||||
|
4. 最终仍通过正常资源加载链路去拿运行时资源实例
|
||||||
|
|
||||||
|
## 当前结构
|
||||||
|
|
||||||
|
`AssetRef` 由三部分组成:
|
||||||
|
|
||||||
|
- `assetGuid`
|
||||||
|
- `localID`
|
||||||
|
- `resourceType`
|
||||||
|
|
||||||
|
它的有效性规则也很直接:
|
||||||
|
|
||||||
|
- `assetGuid` 必须有效
|
||||||
|
- `localID` 不能是 `kInvalidLocalID`
|
||||||
|
- `resourceType` 不能是 `ResourceType::Unknown`
|
||||||
|
|
||||||
|
只要这三者任一缺失,`IsValid()` 就会返回 `false`。
|
||||||
|
|
||||||
|
## 当前公开能力
|
||||||
|
|
||||||
|
### 基础方法
|
||||||
|
|
||||||
|
- `IsValid()` 检查引用是否完整
|
||||||
|
- `Reset()` 把三元组清零回默认无效状态
|
||||||
|
- `ToString()` 返回人类可读的调试字符串
|
||||||
|
|
||||||
|
`ToString()` 的格式当前是:
|
||||||
|
|
||||||
|
`<guid>:<localID>:<ResourceTypeName>`
|
||||||
|
|
||||||
|
例如:
|
||||||
|
|
||||||
|
`0123456789abcdeffedcba9876543210:1:Mesh`
|
||||||
|
|
||||||
|
这更适合日志和调试,不是当前组件序列化真正落盘的格式。
|
||||||
|
|
||||||
|
### `MakeMainAssetRef<T>()`
|
||||||
|
|
||||||
|
模板辅助函数 `MakeMainAssetRef<T>()` 会:
|
||||||
|
|
||||||
|
- 写入调用方给定的 `assetGuid`
|
||||||
|
- 把 `localID` 设为 `kMainAssetLocalID`
|
||||||
|
- 通过 `GetResourceType<T>()` 推导 `resourceType`
|
||||||
|
|
||||||
|
它表达的是“给我这个 GUID 对应的主资产引用”,而不是任意子资产引用。
|
||||||
|
|
||||||
|
## 在当前系统里的真实语义
|
||||||
|
|
||||||
|
### 主资产引用而非 artifact 路径
|
||||||
|
|
||||||
|
当前 `AssetRef` 指向的是项目资产身份,不是 `Library/Artifacts/...` 里的某个缓存文件。
|
||||||
|
|
||||||
|
`ResourceManager::TryResolveAssetPath()` 会把它还原成主 source 路径,例如:
|
||||||
|
|
||||||
|
- `Assets/runtime.material`
|
||||||
|
|
||||||
|
随后 `Load<T>(const AssetRef&)` 再复用普通 `Load<T>(path)` 流程,必要时由 `AssetDatabase::EnsureArtifact()` 重新找到或重建 artifact。
|
||||||
|
|
||||||
|
### `localID` 现状
|
||||||
|
|
||||||
|
虽然结构里有 `localID`,但当前主链路基本都固定写:
|
||||||
|
|
||||||
|
- `kMainAssetLocalID`
|
||||||
|
|
||||||
|
`AssetDatabase::TryGetAssetRef()` 和 `ResourceManager::TryGetAssetRef()` 当前都会直接生成主资产引用,而不是给模型子材质、子纹理或其他子对象分配独立 local ID。
|
||||||
|
|
||||||
|
### `resourceType` 现状
|
||||||
|
|
||||||
|
`resourceType` 是引用元组的一部分,但当前生成它时,`AssetDatabase::TryGetAssetRef()` 只是接受调用方传入的类型并原样写入,不会回头校验这个类型是否真的和 importer 匹配。
|
||||||
|
|
||||||
|
真正的类型匹配仍然主要发生在后续加载与导入链路里。
|
||||||
|
|
||||||
|
## 序列化现实
|
||||||
|
|
||||||
|
### 调试字符串和落盘格式不是一回事
|
||||||
|
|
||||||
|
头文件提供的 `ToString()` 使用冒号和资源类型名,适合人读。
|
||||||
|
|
||||||
|
但组件实际落盘时,`MeshFilterComponent` 和 `MeshRendererComponent` 当前采用的是另一套更紧凑的编码:
|
||||||
|
|
||||||
|
- 单个引用: `guid,localID,resourceTypeInt`
|
||||||
|
- 多个材质引用: 用 `|` 连接多个单个引用
|
||||||
|
|
||||||
|
所以如果你在排查场景或组件序列化问题,不能把 `ToString()` 输出误当成真实持久化格式。
|
||||||
|
|
||||||
|
### 反序列化路径
|
||||||
|
|
||||||
|
当前组件反序列化时会:
|
||||||
|
|
||||||
|
1. 先把 `guid,localID,resourceTypeInt` 文本解码回 `AssetRef`
|
||||||
|
2. 再调用 `ResourceManager::TryResolveAssetPath()` 反查回 `Assets/...`
|
||||||
|
3. 根据是否启用 deferred scene load,立即或延后去加载资源
|
||||||
|
|
||||||
|
这就是 `AssetRef` 真正承担“路径可迁移引用”的地方。
|
||||||
|
|
||||||
|
## 当前实现边界
|
||||||
|
|
||||||
|
- 当前主要服务项目 `Assets` 资产,不适合表示 `builtin://` 这类虚拟路径。
|
||||||
|
- `localID` 子资产寻址能力还没有真正展开,实际几乎都等于 `kMainAssetLocalID`。
|
||||||
|
- `resourceType` 当前更多是调用约束和调试信息,不是强校验凭证。
|
||||||
|
- `MakeMainAssetRef<T>()` 依赖 `GetResourceType<T>()` 的显式特化;不是任意类型都能安全使用。
|
||||||
|
- `AssetRef` 解析到的是主 source 路径,不是 artifact 缓存文件路径。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [当前模块](../Asset.md)
|
||||||
|
- [AssetGUID](../AssetGUID/AssetGUID.md)
|
||||||
|
- [AssetDatabase](../AssetDatabase/AssetDatabase.md)
|
||||||
|
- [ResourceManager](../ResourceManager/ResourceManager.md)
|
||||||
|
- [API 总索引](../../../../main.md)
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
# ProjectAssetIndex
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `class`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ProjectAssetIndex.h`
|
||||||
|
|
||||||
|
**描述**: 维护项目资产 `path/GUID` 的本地热路径索引缓存,为 `ResourceManager` 提供快速 `AssetRef` 查询与 `AssetGUID -> path` 反查。
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
`ProjectAssetIndex` 是当前项目资产链路里的“轻量 snapshot 缓存层”:
|
||||||
|
|
||||||
|
- [AssetDatabase](../AssetDatabase/AssetDatabase.md) 负责真实数据和导入逻辑。
|
||||||
|
- [AssetImportService](../AssetImportService/AssetImportService.md) 负责线程安全数据库访问。
|
||||||
|
- `ProjectAssetIndex` 负责把这些能力转成高频查询友好的本地缓存。
|
||||||
|
|
||||||
|
它的职责不是拥有数据库真相,而是:
|
||||||
|
|
||||||
|
- 保存一份适合频繁读取的 `path/GUID` snapshot
|
||||||
|
- 优先走本地共享锁查询
|
||||||
|
- miss 时回退到 `AssetImportService`
|
||||||
|
- 在成功查询后把结果记回本地缓存
|
||||||
|
|
||||||
|
## 当前存储模型
|
||||||
|
|
||||||
|
内部当前维护两张表:
|
||||||
|
|
||||||
|
- `m_assetGuidByPathKey`
|
||||||
|
- `m_assetPathByGuid`
|
||||||
|
|
||||||
|
其中 path key 会先规范成相对项目路径,再统一转成小写字符串,因此当前查找对路径大小写不敏感。
|
||||||
|
|
||||||
|
`m_projectRoot` 记录当前绑定的项目根,并由 `ResetProjectRoot()` 或 `RefreshFrom()` 统一更新。
|
||||||
|
|
||||||
|
## 路径规范化语义
|
||||||
|
|
||||||
|
`ProjectAssetIndex` 当前只接受正式项目资产路径:
|
||||||
|
|
||||||
|
- `Assets/...`
|
||||||
|
- 或者能够相对当前项目根还原成 `Assets/...` 的绝对路径
|
||||||
|
|
||||||
|
以下路径不会进入索引系统:
|
||||||
|
|
||||||
|
- 带 `://` 的虚拟路径,例如 `builtin://...`
|
||||||
|
- 不落在项目 `Assets` 目录下的绝对路径
|
||||||
|
- 其他普通相对路径
|
||||||
|
|
||||||
|
因此它缓存的是“项目资产索引”,不是所有资源路径索引。
|
||||||
|
|
||||||
|
## 当前公开能力
|
||||||
|
|
||||||
|
### `ResetProjectRoot()`
|
||||||
|
|
||||||
|
设置新的项目根,并清空两张 lookup 表。`ResourceManager::SetResourceRoot("")` 会走这条路径,确保旧项目 snapshot 不会泄漏到新上下文。
|
||||||
|
|
||||||
|
### `RefreshFrom()`
|
||||||
|
|
||||||
|
从 `AssetImportService` 拉取一整份新的 [LookupSnapshot](../AssetImportService/LookupSnapshot.md)。
|
||||||
|
|
||||||
|
当前流程是:
|
||||||
|
|
||||||
|
1. 在锁外读取当前项目根
|
||||||
|
2. 如果项目根有效,则调用 `BuildLookupSnapshot(snapshot)`
|
||||||
|
3. 在独占锁下一次性替换 `m_projectRoot`、`m_assetGuidByPathKey` 和 `m_assetPathByGuid`
|
||||||
|
|
||||||
|
这让读线程只会看到旧 snapshot 或新 snapshot,不会看到半更新状态。
|
||||||
|
|
||||||
|
### `TryGetAssetRef()`
|
||||||
|
|
||||||
|
这是最核心的查询入口,当前策略是:
|
||||||
|
|
||||||
|
1. 先用共享锁查本地 `path -> guid`
|
||||||
|
2. 命中后直接组装主资产 `AssetRef`
|
||||||
|
3. miss 时回退到 `AssetImportService::TryGetAssetRef()`
|
||||||
|
4. 如果第一次回退仍失败,且路径像项目资产路径,则触发一次:
|
||||||
|
- `importService.Refresh()`
|
||||||
|
- `RefreshFrom(importService)`
|
||||||
|
- 再重试
|
||||||
|
5. 成功后再通过 `TryGetPrimaryAssetPath()` 调用 `RememberResolvedPath()` 回填缓存
|
||||||
|
|
||||||
|
因此它不是纯只读缓存,而是“可自我修复的查询索引”。
|
||||||
|
|
||||||
|
### `TryResolveAssetPath()`
|
||||||
|
|
||||||
|
反查逻辑和上面类似,但方向相反:
|
||||||
|
|
||||||
|
1. 先查本地 `guid -> path`
|
||||||
|
2. miss 时回退到 `AssetImportService::TryGetPrimaryAssetPath()`
|
||||||
|
3. 成功后记回缓存
|
||||||
|
|
||||||
|
它支撑的是 `ResourceManager::Load<T>(const AssetRef&)` 这条链路。
|
||||||
|
|
||||||
|
### `RememberResolvedPath()`
|
||||||
|
|
||||||
|
把已知的 `AssetGUID -> relativePath` 写回两张表。当前只接受:
|
||||||
|
|
||||||
|
- 有效的 `AssetGUID`
|
||||||
|
- 非空相对路径
|
||||||
|
|
||||||
|
`ResourceManager::LoadResource()` 在 `EnsureArtifact()` 成功后,会通过它把最新 GUID/path 关系记回索引。
|
||||||
|
|
||||||
|
## 与 `ResourceManager` 的关系
|
||||||
|
|
||||||
|
`ResourceManager` 当前把项目资产职责拆成三层:
|
||||||
|
|
||||||
|
- [AssetImportService](../AssetImportService/AssetImportService.md):导入与数据库服务
|
||||||
|
- `ProjectAssetIndex`:本地 snapshot 缓存
|
||||||
|
- `ResourceManager` 自己:运行时加载、缓存、句柄与日志
|
||||||
|
|
||||||
|
因此:
|
||||||
|
|
||||||
|
- `SetResourceRoot()` 会在设置项目根后立刻刷新这份 snapshot
|
||||||
|
- [RefreshProjectAssets](../ResourceManager/RefreshProjectAssets.md) 会刷新导入服务,再整体刷新索引
|
||||||
|
- `TryGetAssetRef()` / `TryResolveAssetPath()` 对 `ResourceManager` 来说只是转发到这里
|
||||||
|
|
||||||
|
## 当前实现边界
|
||||||
|
|
||||||
|
- 当前只缓存主资产路径,`localID` 基本固定为 `kMainAssetLocalID`
|
||||||
|
- 本地索引不持久化,完全依赖 `AssetImportService` 提供的新 snapshot 重建
|
||||||
|
- miss 时的恢复策略是“整份 snapshot 刷新”,不是细粒度增量同步
|
||||||
|
- 只对项目 `Assets` 路径生效,不覆盖 `builtin://` 这类虚拟资源
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [当前模块](../Asset.md)
|
||||||
|
- [AssetImportService](../AssetImportService/AssetImportService.md)
|
||||||
|
- [AssetDatabase](../AssetDatabase/AssetDatabase.md)
|
||||||
|
- [AssetRef](../AssetRef/AssetRef.md)
|
||||||
|
- [ResourceManager](../ResourceManager/ResourceManager.md)
|
||||||
|
- [API 总索引](../../../../main.md)
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# ProjectAssetIndex::RefreshFrom
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ProjectAssetIndex.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void RefreshFrom(const AssetImportService& importService);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
从 `AssetImportService` 重建 path/GUID 快照。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 先在锁外向 `importService` 请求项目根和双向 lookup snapshot。
|
||||||
|
- 然后在独占锁下整体替换 `m_projectRoot`、`m_assetGuidByPathKey` 和 `m_assetPathByGuid`。
|
||||||
|
- 这让读线程只会看到旧快照或新快照,不会看到半更新状态。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ProjectAssetIndex](ProjectAssetIndex.md)
|
||||||
|
- [AssetImportService::BuildLookupSnapshot](../AssetImportService/BuildLookupSnapshot.md)
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# ProjectAssetIndex::RememberResolvedPath
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ProjectAssetIndex.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void RememberResolvedPath(
|
||||||
|
const AssetGUID& assetGuid,
|
||||||
|
const Containers::String& relativePath);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
把一次成功解析的 GUID/path 结果写回索引缓存。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 当 `assetGuid` 无效或 `relativePath` 为空时直接返回。
|
||||||
|
- 否则在独占锁下同时更新:
|
||||||
|
- 小写路径键到 `AssetGUID` 的映射
|
||||||
|
- `AssetGUID` 到原始相对路径的映射
|
||||||
|
- 这是一次局部缓存写回,不会重建整份 snapshot。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ProjectAssetIndex](ProjectAssetIndex.md)
|
||||||
|
- [TryGetAssetRef](TryGetAssetRef.md)
|
||||||
|
- [TryResolveAssetPath](TryResolveAssetPath.md)
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# ProjectAssetIndex::ResetProjectRoot
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ProjectAssetIndex.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void ResetProjectRoot(
|
||||||
|
const Containers::String& projectRoot = Containers::String());
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
切换项目根并清空当前索引缓存。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 在 `std::shared_mutex` 的独占锁下执行。
|
||||||
|
- 会更新 `m_projectRoot`。
|
||||||
|
- 同时清空 `m_assetGuidByPathKey` 与 `m_assetPathByGuid`。
|
||||||
|
- 不会主动向 `AssetImportService` 拉取新快照。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ProjectAssetIndex](ProjectAssetIndex.md)
|
||||||
|
- [RefreshFrom](RefreshFrom.md)
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# ProjectAssetIndex::TryGetAssetRef
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ProjectAssetIndex.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool TryGetAssetRef(
|
||||||
|
AssetImportService& importService,
|
||||||
|
const Containers::String& path,
|
||||||
|
ResourceType resourceType,
|
||||||
|
AssetRef& outRef) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
优先通过本地索引、必要时回退到导入服务,把路径解析成主资产 `AssetRef`。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 先把输入路径规范化到 `Assets/...` 语义,并生成小写 lookup key。
|
||||||
|
- 若本地 `pathKey -> AssetGUID` 命中:
|
||||||
|
- 直接写出 `assetGuid`
|
||||||
|
- 把 `localID` 设为 `kMainAssetLocalID`
|
||||||
|
- 把调用方传入的 `resourceType` 写入结果
|
||||||
|
- 若本地 miss:
|
||||||
|
- 先调用 `importService.TryGetAssetRef()`
|
||||||
|
- 若仍失败且路径看起来属于当前项目 `Assets`,则触发一次 `importService.Refresh()` + [RefreshFrom](RefreshFrom.md) 后重试
|
||||||
|
- 最终成功时,会尝试反查主路径并通过 [RememberResolvedPath](RememberResolvedPath.md) 写回缓存。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ProjectAssetIndex](ProjectAssetIndex.md)
|
||||||
|
- [RefreshFrom](RefreshFrom.md)
|
||||||
|
- [RememberResolvedPath](RememberResolvedPath.md)
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# ProjectAssetIndex::TryResolveAssetPath
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ProjectAssetIndex.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool TryResolveAssetPath(
|
||||||
|
const AssetImportService& importService,
|
||||||
|
const AssetRef& assetRef,
|
||||||
|
Containers::String& outPath) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
优先通过本地索引、必要时回退到导入服务,把 `AssetRef` 反查成主资产路径。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 对无效 `AssetRef` 直接返回 `false`。
|
||||||
|
- 若本地 `AssetGUID -> path` 缓存命中,直接返回缓存路径。
|
||||||
|
- 若本地 miss,则调用 `importService.TryGetPrimaryAssetPath()`。
|
||||||
|
- fallback 成功后,会通过 [RememberResolvedPath](RememberResolvedPath.md) 写回缓存。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ProjectAssetIndex](ProjectAssetIndex.md)
|
||||||
|
- [RememberResolvedPath](RememberResolvedPath.md)
|
||||||
|
- [AssetImportService::TryGetPrimaryAssetPath](../AssetImportService/TryGetPrimaryAssetPath.md)
|
||||||
@@ -1,31 +1,30 @@
|
|||||||
# ResourceManager::AddRef
|
# ResourceManager::AddRef
|
||||||
|
|
||||||
添加元素或建立关联。
|
增加指定资源 GUID 的句柄引用计数。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void AddRef(ResourceGUID guid);
|
void AddRef(ResourceGUID guid);
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:**
|
按当前实现:
|
||||||
- `guid` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
1. 在 `m_refCounts` 中把该 GUID 的计数加一;若之前不存在,则插入为 `1`
|
||||||
|
2. 如果当前 `m_resourceCache` 里还没有该 GUID,对应路径会尝试调用内部 `ReloadResource(guid)`
|
||||||
|
|
||||||
**示例:**
|
## 当前语义
|
||||||
|
|
||||||
```cpp
|
- 这是 [ResourceHandle](../ResourceHandle/ResourceHandle.md) 构造、拷贝和赋值链路里的底层计数接口。
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
- 计数增加本身不等于资源一定已在缓存中。
|
||||||
|
|
||||||
void Example() {
|
## 当前实现边界
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::AddRef(...)。
|
- 当前 `ReloadResource(guid)` 仍基本是 stub,且依赖 `m_guidToPath` 里已有路径记录。
|
||||||
(void)object;
|
- 因此 `AddRef()` 现在并不保证“计数一加就能把缺失资源重新加载回来”。
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [Release](Release.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [GetRefCount](GetRefCount.md)
|
||||||
|
- [ResourceHandle](../ResourceHandle/ResourceHandle.md)
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# ResourceManager::BeginDeferredSceneLoad
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void BeginDeferredSceneLoad();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
进入 deferred scene load 状态,使内部深度计数加一。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 当前只是对 `m_deferredSceneLoadDepth` 做原子自增。
|
||||||
|
- 没有额外锁,也没有附带回调或事件。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
- [EndDeferredSceneLoad](EndDeferredSceneLoad.md)
|
||||||
|
- [ScopedDeferredSceneLoad](ScopedDeferredSceneLoad.md)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# ResourceManager::EndDeferredSceneLoad
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void EndDeferredSceneLoad();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
退出一层 deferred scene load 状态。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 先读取当前原子深度。
|
||||||
|
- 如果深度已经是 `0`,直接返回,避免下溢。
|
||||||
|
- 否则执行一次原子自减。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
- [BeginDeferredSceneLoad](BeginDeferredSceneLoad.md)
|
||||||
|
- [ScopedDeferredSceneLoad](ScopedDeferredSceneLoad.md)
|
||||||
@@ -1,44 +1,31 @@
|
|||||||
# ResourceManager::Exists
|
# ResourceManager::Exists
|
||||||
|
|
||||||
公开方法,详见头文件声明。
|
判断某个资源当前是否已经存在于运行时缓存。
|
||||||
|
|
||||||
该方法在 `XCEngine/Core/Asset/ResourceManager.h` 中提供了 2 个重载,当前页面统一汇总这些公开声明。
|
|
||||||
|
|
||||||
## 重载 1: 声明
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
bool Exists(const Containers::String& path) const;
|
bool Exists(const Containers::String& path) const;
|
||||||
```
|
|
||||||
|
|
||||||
**参数:**
|
|
||||||
- `path` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `bool` - 返回值语义详见头文件声明。
|
|
||||||
|
|
||||||
## 重载 2: 声明
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
bool Exists(ResourceGUID guid) const;
|
bool Exists(ResourceGUID guid) const;
|
||||||
```
|
```
|
||||||
|
|
||||||
**参数:**
|
## 当前行为
|
||||||
- `guid` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `bool` - 返回值语义详见头文件声明。
|
### `Exists(path)`
|
||||||
|
|
||||||
**示例:**
|
- 先把路径转成 `ResourceGUID::Generate(path)`
|
||||||
|
- 再转发到 `Exists(guid)`
|
||||||
|
|
||||||
```cpp
|
### `Exists(guid)`
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
- 直接查询 `m_resourceCache.Contains(guid)`
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::Exists(...)。
|
## 当前语义
|
||||||
(void)object;
|
|
||||||
}
|
- 这不是磁盘存在性检查。
|
||||||
```
|
- 也不是项目资产数据库存在性检查。
|
||||||
|
- 它只回答“这个资源当前是否已经在运行时缓存里”。
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [Find](Find.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [Load](Load.md)
|
||||||
|
- [Unload](Unload.md)
|
||||||
|
|||||||
@@ -1,44 +1,37 @@
|
|||||||
# ResourceManager::Find
|
# ResourceManager::Find
|
||||||
|
|
||||||
查找并返回匹配对象。
|
在当前运行时缓存中查找资源对象。
|
||||||
|
|
||||||
该方法在 `XCEngine/Core/Asset/ResourceManager.h` 中提供了 2 个重载,当前页面统一汇总这些公开声明。
|
|
||||||
|
|
||||||
## 重载 1: 声明
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
IResource* Find(const Containers::String& path);
|
IResource* Find(const Containers::String& path);
|
||||||
```
|
|
||||||
|
|
||||||
**参数:**
|
|
||||||
- `path` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `IResource*` - 返回值语义详见头文件声明。
|
|
||||||
|
|
||||||
## 重载 2: 声明
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
IResource* Find(ResourceGUID guid);
|
IResource* Find(ResourceGUID guid);
|
||||||
```
|
```
|
||||||
|
|
||||||
**参数:**
|
## 当前行为
|
||||||
- `guid` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `IResource*` - 返回值语义详见头文件声明。
|
### `Find(path)`
|
||||||
|
|
||||||
**示例:**
|
- 先用 `ResourceGUID::Generate(path)` 生成 GUID
|
||||||
|
- 再转发到 `Find(guid)`
|
||||||
|
|
||||||
```cpp
|
### `Find(guid)`
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
- 调用内部 `FindInCache(guid)`
|
||||||
XCEngine::Resources::ResourceManager object;
|
- 只查询当前 `m_resourceCache`
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::Find(...)。
|
|
||||||
(void)object;
|
## 当前语义
|
||||||
}
|
|
||||||
```
|
- 这不是“若没找到就去加载”的接口。
|
||||||
|
- 它也不会回退到 `AssetDatabase`、磁盘文件系统或 loader。
|
||||||
|
- 只有资源已经在运行时缓存里,才会返回非空指针。
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
- 路径版查找依赖传入路径生成的 GUID 与加载时使用的原始请求路径一致。
|
||||||
|
- 对项目资产来说,通常应传 `Assets/...` 这类原始 source 路径,而不是 artifact 路径。
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [Exists](Exists.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [Load](Load.md)
|
||||||
|
- [Unload](Unload.md)
|
||||||
|
|||||||
@@ -1,30 +1,22 @@
|
|||||||
# ResourceManager::FlushCache
|
# ResourceManager::FlushCache
|
||||||
|
|
||||||
公开方法,详见头文件声明。
|
把底层 `ResourceCache` 执行一次显式刷新。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void FlushCache();
|
void FlushCache();
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:** 无。
|
- 直接调用 `m_cache.Flush()`
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
## 当前语义
|
||||||
|
|
||||||
**示例:**
|
- 它操作的是 `ResourceCache`,不是直接清空 `m_resourceCache`。
|
||||||
|
- 当前实现下,这并不等同于“卸载所有资源”。
|
||||||
```cpp
|
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::FlushCache(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [UnloadAll](UnloadAll.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [UnloadUnused](UnloadUnused.md)
|
||||||
|
- [ResourceCache](../ResourceCache/ResourceCache.md)
|
||||||
|
|||||||
@@ -1,29 +1,28 @@
|
|||||||
# ResourceManager::Get
|
# ResourceManager::Get
|
||||||
|
|
||||||
获取相关状态或对象。
|
获取 `ResourceManager` 的进程级单例。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
static ResourceManager& Get();
|
static ResourceManager& Get();
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:** 无。
|
当前实现使用函数内静态对象:
|
||||||
|
|
||||||
**返回:** `ResourceManager&` - 返回值语义详见头文件声明。
|
|
||||||
|
|
||||||
**示例:**
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
static ResourceManager instance;
|
||||||
|
return instance;
|
||||||
void Example() {
|
|
||||||
auto& instance = XCEngine::Resources::ResourceManager::Get();
|
|
||||||
(void)instance;
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
这意味着:
|
||||||
|
|
||||||
|
- 整个进程当前只有一个 `ResourceManager`
|
||||||
|
- 调用方拿到的是同一个共享实例
|
||||||
|
- 返回值不表达所有权,调用方不应自行销毁
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [ResourceManager](ResourceManager.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [Initialize](Initialize.md)
|
||||||
|
- [Shutdown](Shutdown.md)
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# ResourceManager::GetAsyncPendingCount
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Core::uint32 GetAsyncPendingCount() const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
返回异步加载器当前记录的待处理请求数量。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 当 `m_asyncLoader` 为空时返回 `0`。
|
||||||
|
- 否则直接返回 `m_asyncLoader->GetPendingCount()`。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
- [LoadAsync](LoadAsync.md)
|
||||||
|
- [IsAsyncLoading](IsAsyncLoading.md)
|
||||||
@@ -1,31 +1,23 @@
|
|||||||
# ResourceManager::GetLoader
|
# ResourceManager::GetLoader
|
||||||
|
|
||||||
获取相关状态或对象。
|
查询某个资源类型当前注册的 loader。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
IResourceLoader* GetLoader(ResourceType type) const;
|
IResourceLoader* GetLoader(ResourceType type) const;
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:**
|
- 若 `m_loaders` 中存在该 `ResourceType`,返回对应 `IResourceLoader*`
|
||||||
- `type` - 参数语义详见头文件声明。
|
- 否则返回 `nullptr`
|
||||||
|
|
||||||
**返回:** `IResourceLoader*` - 返回值语义详见头文件声明。
|
## 当前语义
|
||||||
|
|
||||||
**示例:**
|
- 返回的是非拥有型原始指针。
|
||||||
|
- `LoadResource()` 正是通过它决定某种资源类型该交给哪个 loader。
|
||||||
```cpp
|
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::GetLoader(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [RegisterLoader](RegisterLoader.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [UnregisterLoader](UnregisterLoader.md)
|
||||||
|
- [Load](Load.md)
|
||||||
|
|||||||
@@ -1,30 +1,17 @@
|
|||||||
# ResourceManager::GetMemoryBudget
|
# ResourceManager::GetMemoryBudget
|
||||||
|
|
||||||
获取相关状态或对象。
|
返回当前配置的资源缓存内存预算。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
size_t GetMemoryBudget() const;
|
size_t GetMemoryBudget() const;
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:** 无。
|
- 直接返回 `m_memoryBudget`
|
||||||
|
|
||||||
**返回:** `size_t` - 返回值语义详见头文件声明。
|
|
||||||
|
|
||||||
**示例:**
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::GetMemoryBudget(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [SetMemoryBudget](SetMemoryBudget.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [GetMemoryUsage](GetMemoryUsage.md)
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
|||||||
@@ -1,30 +1,22 @@
|
|||||||
# ResourceManager::GetMemoryUsage
|
# ResourceManager::GetMemoryUsage
|
||||||
|
|
||||||
获取相关状态或对象。
|
返回当前 `ResourceManager` 跟踪到的缓存资源内存使用量。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
size_t GetMemoryUsage() const;
|
size_t GetMemoryUsage() const;
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:** 无。
|
- 直接返回 `m_memoryUsage`
|
||||||
|
|
||||||
**返回:** `size_t` - 返回值语义详见头文件声明。
|
## 当前语义
|
||||||
|
|
||||||
**示例:**
|
- 这个值反映的是 `AddToCache()` / `Unload*()` 更新的资源缓存字节数。
|
||||||
|
- 它不是整个进程的真实内存占用,也不是 GPU 侧显存统计。
|
||||||
```cpp
|
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::GetMemoryUsage(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [GetMemoryBudget](GetMemoryBudget.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [SetMemoryBudget](SetMemoryBudget.md)
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# ResourceManager::GetProjectLibraryRoot
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Containers::String GetProjectLibraryRoot() const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
返回当前项目 `Library` 目录的根路径。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 直接转发到 `m_assetImportService.GetLibraryRoot()`。
|
||||||
|
- 返回值是一个按值复制出来的 `Containers::String`,不是内部成员引用。
|
||||||
|
- 如果当前没有绑定项目根,通常会返回空字符串。
|
||||||
|
|
||||||
|
## 主要用途
|
||||||
|
|
||||||
|
- 用于测试或工具层定位当前项目的 `Library` 目录。
|
||||||
|
- 在执行 [RebuildProjectAssetCache](RebuildProjectAssetCache.md) 前后,可以用它确认实际操作的缓存目录。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
- [RebuildProjectAssetCache](RebuildProjectAssetCache.md)
|
||||||
|
- [AssetImportService::GetLibraryRoot](../AssetImportService/GetLibraryRoot.md)
|
||||||
@@ -1,31 +1,22 @@
|
|||||||
# ResourceManager::GetRefCount
|
# ResourceManager::GetRefCount
|
||||||
|
|
||||||
获取相关状态或对象。
|
查询指定资源 GUID 的当前句柄引用计数。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
Core::uint32 GetRefCount(ResourceGUID guid) const;
|
Core::uint32 GetRefCount(ResourceGUID guid) const;
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:**
|
- 若 `m_refCounts` 中存在该 GUID,返回当前计数
|
||||||
- `guid` - 参数语义详见头文件声明。
|
- 否则返回 `0`
|
||||||
|
|
||||||
**返回:** `Core::uint32` - 返回值语义详见头文件声明。
|
## 当前语义
|
||||||
|
|
||||||
**示例:**
|
- 这里返回的是 `ResourceHandle` 侧维护的引用计数,不是资源对象内部的引用计数,也不是缓存命中次数。
|
||||||
|
|
||||||
```cpp
|
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::GetRefCount(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [AddRef](AddRef.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [Release](Release.md)
|
||||||
|
- [ResourceHandle](../ResourceHandle/ResourceHandle.md)
|
||||||
|
|||||||
@@ -1,30 +1,23 @@
|
|||||||
# ResourceManager::GetResourcePaths
|
# ResourceManager::GetResourcePaths
|
||||||
|
|
||||||
获取相关状态或对象。
|
返回当前运行时缓存里已知资源路径集合。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
Containers::Array<Containers::String> GetResourcePaths() const;
|
Containers::Array<Containers::String> GetResourcePaths() const;
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:** 无。
|
- 遍历 `m_guidToPath`
|
||||||
|
- 把每个 value 追加到返回数组
|
||||||
|
|
||||||
**返回:** `Containers::Array<Containers::String>` - 返回值语义详见头文件声明。
|
## 当前语义
|
||||||
|
|
||||||
**示例:**
|
- 它返回的是当前缓存资源对应的“原始请求路径”集合。
|
||||||
|
- 这不是项目 `Assets` 的全量清单,也不是 `AssetDatabase` 的路径索引导出接口。
|
||||||
```cpp
|
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::GetResourcePaths(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [Find](Find.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [UnloadAll](UnloadAll.md)
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
|||||||
@@ -1,30 +1,22 @@
|
|||||||
# ResourceManager::GetResourceRoot
|
# ResourceManager::GetResourceRoot
|
||||||
|
|
||||||
获取相关状态或对象。
|
返回当前绑定的项目资源根目录。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const Containers::String& GetResourceRoot() const;
|
const Containers::String& GetResourceRoot() const;
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:** 无。
|
- 直接返回 `m_resourceRoot`
|
||||||
|
|
||||||
**返回:** `const Containers::String&` - 返回值语义详见头文件声明。
|
## 当前语义
|
||||||
|
|
||||||
**示例:**
|
- 返回值为空时,通常表示当前没有处于项目资产模式。
|
||||||
|
- 这个值由 [SetResourceRoot](SetResourceRoot.md) 写入,也是 `AssetImportService` / `ProjectAssetIndex` 是否启用的根入口。
|
||||||
```cpp
|
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::GetResourceRoot(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [SetResourceRoot](SetResourceRoot.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [RefreshProjectAssets](RefreshProjectAssets.md)
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
|||||||
@@ -1,30 +1,37 @@
|
|||||||
# ResourceManager::Initialize
|
# ResourceManager::Initialize
|
||||||
|
|
||||||
初始化内部状态。
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void Initialize();
|
void Initialize();
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 作用
|
||||||
|
|
||||||
**参数:** 无。
|
初始化资源管理器的核心运行时状态。
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
## 当前实现行为
|
||||||
|
|
||||||
**示例:**
|
- 当前只是转发到内部 `EnsureInitialized()`。
|
||||||
|
- 首次初始化时会:
|
||||||
|
- 创建 `AsyncLoader` 并调用 `Initialize(2)`
|
||||||
|
- 注册内建 `MaterialLoader`、`MeshLoader`、`ShaderLoader`、`TextureLoader`
|
||||||
|
- 初始化内部 `AssetImportService`
|
||||||
|
- 如果 `m_asyncLoader` 已存在,则直接返回,不会重复构造。
|
||||||
|
|
||||||
```cpp
|
## 当前实现边界
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
- 当前 `AsyncLoader` 是否真正产生后台并发能力,仍取决于它自己的实现。
|
||||||
XCEngine::Resources::ResourceManager object;
|
- 这一步不会自动设置 `resourceRoot`;项目资产模式要到 [SetResourceRoot](SetResourceRoot.md) 之后才真正接入。
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::Initialize(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [ResourceManager](ResourceManager.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [Shutdown](Shutdown.md)
|
||||||
|
- [SetResourceRoot](SetResourceRoot.md)
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# ResourceManager::IsAsyncLoading
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool IsAsyncLoading() const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
判断异步加载器当前是否仍有活跃加载状态。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 当 `m_asyncLoader` 为空时返回 `false`。
|
||||||
|
- 否则直接返回 `m_asyncLoader->IsLoading()`。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
- [LoadAsync](LoadAsync.md)
|
||||||
|
- [GetAsyncPendingCount](GetAsyncPendingCount.md)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# ResourceManager::IsDeferredSceneLoadEnabled
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool IsDeferredSceneLoadEnabled() const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
判断当前是否处于 deferred scene load 状态。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 当前直接返回 `m_deferredSceneLoadDepth.load() > 0`。
|
||||||
|
- 这意味着它反映的是“嵌套深度是否非零”,而不是某个单独布尔开关。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
- [BeginDeferredSceneLoad](BeginDeferredSceneLoad.md)
|
||||||
|
- [EndDeferredSceneLoad](EndDeferredSceneLoad.md)
|
||||||
|
- [ScopedDeferredSceneLoad](ScopedDeferredSceneLoad.md)
|
||||||
@@ -1,32 +1,43 @@
|
|||||||
# ResourceManager::Load
|
# ResourceManager::Load
|
||||||
|
|
||||||
加载资源或数据。
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method-template`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
template<typename T> ResourceHandle<T> Load(const Containers::String& path, ImportSettings* settings = nullptr);
|
template<typename T>
|
||||||
|
ResourceHandle<T> Load(const Containers::String& path, ImportSettings* settings = nullptr);
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 作用
|
||||||
|
|
||||||
**参数:**
|
按资源类型模板参数发起同步加载,并在成功时返回对应的 `ResourceHandle<T>`。
|
||||||
- `path` - 参数语义详见头文件声明。
|
|
||||||
- `settings` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `template<typename T> ResourceHandle<T>` - 返回值语义详见头文件声明。
|
## 当前实现行为
|
||||||
|
|
||||||
**示例:**
|
- 这是对内部 `LoadResource(path, GetResourceType<T>(), settings)` 的类型安全包装。
|
||||||
|
- 若 `LoadResource(...)` 失败或返回空资源,则返回空句柄。
|
||||||
|
- 成功时把结果中的 `IResource*` 转成 `T*`,并构造 `ResourceHandle<T>`。
|
||||||
|
|
||||||
```cpp
|
## 关键语义
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
- 当 `path` 是项目资产路径且当前已设置 `resourceRoot` 时,内部实际会先经 `AssetImportService::EnsureArtifact()` 准备 `ImportedAsset`,再把其中的 `runtimeLoadPath` 交给具体 loader。
|
||||||
XCEngine::Resources::ResourceManager object;
|
- 当 `path` 是 `builtin://...` 或其他不进入项目资产数据库的路径时,会直接走 loader。
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::Load(...)。
|
- 资源对象最终暴露给调用方的 `m_path` 仍是原始请求路径,而不是 artifact 路径。
|
||||||
(void)object;
|
- `Load<T>(const AssetRef&)` 的另一组重载会先用 `TryResolveAssetPath()` 还原回主 source 路径,再复用这条普通 `Load(path)` 链路。
|
||||||
}
|
|
||||||
```
|
## 当前限制
|
||||||
|
|
||||||
|
- `GetResourceType<T>()` 需要存在对应特化;否则并不会自动推断资源类型。
|
||||||
|
- 当前只适合当作同步加载主路径;异步版本的能力仍未完全闭环。
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [ResourceManager](ResourceManager.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [TryResolveAssetPath](TryResolveAssetPath.md)
|
||||||
|
- [TryGetAssetRef](TryGetAssetRef.md)
|
||||||
|
- [AssetDatabase::EnsureArtifact](../AssetDatabase/EnsureArtifact.md)
|
||||||
|
|||||||
@@ -1,49 +1,45 @@
|
|||||||
# ResourceManager::LoadAsync
|
# ResourceManager::LoadAsync
|
||||||
|
|
||||||
加载资源或数据。
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
该方法在 `XCEngine/Core/Asset/ResourceManager.h` 中提供了 2 个重载,当前页面统一汇总这些公开声明。
|
**类型**: `method`
|
||||||
|
|
||||||
## 重载 1: 声明
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void LoadAsync(const Containers::String& path, ResourceType type, std::function<void(LoadResult)> callback);
|
void LoadAsync(
|
||||||
|
const Containers::String& path,
|
||||||
|
ResourceType type,
|
||||||
|
std::function<void(LoadResult)> callback);
|
||||||
|
|
||||||
|
void LoadAsync(
|
||||||
|
const Containers::String& path,
|
||||||
|
ResourceType type,
|
||||||
|
ImportSettings* settings,
|
||||||
|
std::function<void(LoadResult)> callback);
|
||||||
```
|
```
|
||||||
|
|
||||||
**参数:**
|
## 作用
|
||||||
- `path` - 参数语义详见头文件声明。
|
|
||||||
- `type` - 参数语义详见头文件声明。
|
|
||||||
- `callback` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
把一次资源加载请求提交给异步加载器。
|
||||||
|
|
||||||
## 重载 2: 声明
|
## 当前实现行为
|
||||||
|
|
||||||
```cpp
|
- 无 `settings` 的重载只是转发到带 `settings` 的版本,并传 `nullptr`。
|
||||||
void LoadAsync(const Containers::String& path, ResourceType type, ImportSettings* settings, std::function<void(LoadResult)> callback);
|
- 正式重载会先调用 `EnsureInitialized()`。
|
||||||
```
|
- 若 `m_asyncLoader` 仍不可用,则直接用错误 `LoadResult` 触发回调。
|
||||||
|
- 否则把请求原样转发给 `m_asyncLoader->Submit(path, type, settings, callback)`。
|
||||||
|
|
||||||
**参数:**
|
## 当前实现边界
|
||||||
- `path` - 参数语义详见头文件声明。
|
|
||||||
- `type` - 参数语义详见头文件声明。
|
|
||||||
- `settings` - 参数语义详见头文件声明。
|
|
||||||
- `callback` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
- 当前异步系统的真实执行能力仍取决于 `AsyncLoader`;不能把这组 API 当成成熟的后台流式加载系统。
|
||||||
|
- 请求提交后,调用方仍需要配合 [UpdateAsyncLoads](UpdateAsyncLoads.md) 驱动完成队列更新。
|
||||||
**示例:**
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::LoadAsync(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [ResourceManager](ResourceManager.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [UpdateAsyncLoads](UpdateAsyncLoads.md)
|
||||||
|
- [IsAsyncLoading](IsAsyncLoading.md)
|
||||||
|
- [GetAsyncPendingCount](GetAsyncPendingCount.md)
|
||||||
|
|||||||
@@ -1,32 +1,36 @@
|
|||||||
# ResourceManager::LoadGroup
|
# ResourceManager::LoadGroup
|
||||||
|
|
||||||
加载资源或数据。
|
对一组路径逐个发起异步加载,并在每个资源完成时回调一次 typed handle。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
template<typename T> void LoadGroup(const Containers::Array<Containers::String>& paths, std::function<void(ResourceHandle<T>)> callback);
|
template<typename T>
|
||||||
|
void LoadGroup(
|
||||||
|
const Containers::Array<Containers::String>& paths,
|
||||||
|
std::function<void(ResourceHandle<T>)> callback);
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:**
|
当前模板实现非常直接:
|
||||||
- `paths` - 参数语义详见头文件声明。
|
|
||||||
- `callback` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `template<typename T> void` - 返回值语义详见头文件声明。
|
1. 遍历 `paths`
|
||||||
|
2. 对每个路径调用 `LoadAsync(path, GetResourceType<T>(), ...)`
|
||||||
|
3. 在异步回调里:
|
||||||
|
- 成功时把 `LoadResult.resource` 包装成 `ResourceHandle<T>`
|
||||||
|
- 失败时回调空句柄
|
||||||
|
|
||||||
**示例:**
|
## 当前语义
|
||||||
|
|
||||||
```cpp
|
- `callback` 是“每个资源一次”,不是“整组全部完成一次”。
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
- 当前没有 group-level 聚合状态、完成计数或 barrier。
|
||||||
|
|
||||||
void Example() {
|
## 当前实现边界
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::LoadGroup(...)。
|
- 它的实际执行能力仍然依赖 [LoadAsync](LoadAsync.md) / [AsyncLoader](../AsyncLoader/AsyncLoader.md) 的当前完成度。
|
||||||
(void)object;
|
- 不适合把它当成成熟的批量后台流式加载系统接口。
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [LoadAsync](LoadAsync.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [UpdateAsyncLoads](UpdateAsyncLoads.md)
|
||||||
|
- [ResourceHandle](../ResourceHandle/ResourceHandle.md)
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# ResourceManager::RebuildProjectAssetCache
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool RebuildProjectAssetCache();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
清空当前运行时资源缓存,重建项目 `Library` 缓存目录,并刷新项目资产索引状态。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 如果 `m_resourceRoot` 为空,直接返回 `false`
|
||||||
|
- 否则固定按下面的顺序执行:
|
||||||
|
1. `UnloadAll()`
|
||||||
|
2. `m_assetImportService.RebuildLibraryCache()`
|
||||||
|
3. `m_projectAssetIndex.RefreshFrom(m_assetImportService)`
|
||||||
|
- 返回值直接透传 `AssetImportService::RebuildLibraryCache()` 的结果
|
||||||
|
|
||||||
|
## 当前语义
|
||||||
|
|
||||||
|
- 这是“清空并重建当前项目 Library 缓存”的高层入口,不是普通的 snapshot 刷新
|
||||||
|
- 它会丢掉当前 `ResourceManager` 中已经加载的运行时资源对象,因此比 [RefreshProjectAssets](RefreshProjectAssets.md) 更重
|
||||||
|
- `tests/core/Asset/test_resource_manager.cpp` 里的 `ResourceManager_Test.RebuildProjectAssetCacheRefreshesLookupState` 验证了重建后 `AssetRef` 查询仍能恢复,并能重新命中新建的 Library 产物
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
- [RefreshProjectAssets](RefreshProjectAssets.md)
|
||||||
|
- [GetProjectLibraryRoot](GetProjectLibraryRoot.md)
|
||||||
|
- [AssetImportService::RebuildLibraryCache](../AssetImportService/RebuildLibraryCache.md)
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# ResourceManager::RefreshProjectAssets
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void RefreshProjectAssets();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
显式刷新当前项目的资产数据库,并重建 `ProjectAssetIndex` 的本地 snapshot。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 只有在 `m_resourceRoot` 非空时才执行实际刷新。
|
||||||
|
- 固定按下面的顺序执行:
|
||||||
|
- `m_assetImportService.Refresh()`
|
||||||
|
- `m_projectAssetIndex.RefreshFrom(m_assetImportService)`
|
||||||
|
- 它不会直接重载已经在运行时缓存里的资源对象;只负责更新项目资产查询链路。
|
||||||
|
|
||||||
|
## 适用场景
|
||||||
|
|
||||||
|
- 项目里新增、删除或改写了 `Assets/...` 源文件后,需要让 `AssetRef` 查询和路径反查看到最新状态。
|
||||||
|
- `TryGetAssetRef()` 的 cache miss 自动恢复不够时,可以显式调用这条入口做一次整体刷新。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
- [SetResourceRoot](SetResourceRoot.md)
|
||||||
|
- [TryGetAssetRef](TryGetAssetRef.md)
|
||||||
|
- [AssetImportService::Refresh](../AssetImportService/Refresh.md)
|
||||||
|
- [ProjectAssetIndex::RefreshFrom](../ProjectAssetIndex/RefreshFrom.md)
|
||||||
@@ -1,31 +1,28 @@
|
|||||||
# ResourceManager::RegisterLoader
|
# ResourceManager::RegisterLoader
|
||||||
|
|
||||||
注册对象、回调或映射。
|
注册一个资源 loader,使其可按资源类型参与加载。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void RegisterLoader(IResourceLoader* loader);
|
void RegisterLoader(IResourceLoader* loader);
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:**
|
当前实现会在锁内把:
|
||||||
- `loader` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
|
||||||
|
|
||||||
**示例:**
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
loader->GetResourceType() -> loader
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::RegisterLoader(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
写入 `m_loaders` 映射。
|
||||||
|
|
||||||
|
## 当前语义
|
||||||
|
|
||||||
|
- `ResourceManager` 保存的是原始指针,不接管 loader 所有权。
|
||||||
|
- 调用方需要保证该 loader 在注册期间保持有效。
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [GetLoader](GetLoader.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [UnregisterLoader](UnregisterLoader.md)
|
||||||
|
- [IResourceLoader](../../IO/IResourceLoader/IResourceLoader.md)
|
||||||
|
|||||||
@@ -1,31 +1,34 @@
|
|||||||
# ResourceManager::Release
|
# ResourceManager::Release
|
||||||
|
|
||||||
释放引用或底层资源。
|
减少指定资源 GUID 的句柄引用计数。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void Release(ResourceGUID guid);
|
void Release(ResourceGUID guid);
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:**
|
按当前实现:
|
||||||
- `guid` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
1. 在 `m_refCounts` 中查找该 GUID
|
||||||
|
2. 若不存在,直接返回
|
||||||
|
3. 若存在,则做一次自减
|
||||||
|
4. 当计数减到 `0` 时:
|
||||||
|
- 从 `m_refCounts` 移除该 GUID
|
||||||
|
- 调用 `m_cache.OnZeroRefCount(guid)`
|
||||||
|
|
||||||
**示例:**
|
## 当前语义
|
||||||
|
|
||||||
```cpp
|
- 这条接口只负责“引用计数归零通知”,不直接执行卸载。
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
- 当前真实卸载链路是否继续发生,还取决于 [ResourceCache](../ResourceCache/ResourceCache.md) 的后续行为。
|
||||||
|
|
||||||
void Example() {
|
## 当前实现边界
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::Release(...)。
|
- `Release()` 本身不会直接从 `m_resourceCache` 中删除资源。
|
||||||
(void)object;
|
- 它也不会主动减少 `m_memoryUsage`。
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [AddRef](AddRef.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [GetRefCount](GetRefCount.md)
|
||||||
|
- [Unload](Unload.md)
|
||||||
|
|||||||
@@ -1,31 +1,34 @@
|
|||||||
# ResourceManager::ResolvePath
|
# ResourceManager::ResolvePath
|
||||||
|
|
||||||
解析并返回目标结果。
|
把一个相对资源路径拼接到当前资源根目录下。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
Containers::String ResolvePath(const Containers::String& relativePath) const;
|
Containers::String ResolvePath(const Containers::String& relativePath) const;
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:**
|
当前实现只是做简单字符串拼接:
|
||||||
- `relativePath` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `Containers::String` - 返回值语义详见头文件声明。
|
|
||||||
|
|
||||||
**示例:**
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
return m_resourceRoot + "/" + relativePath;
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::ResolvePath(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 当前语义
|
||||||
|
|
||||||
|
- 它不是 `std::filesystem` 风格的规范化解析器。
|
||||||
|
- 不检查路径是否存在。
|
||||||
|
- 不参与 `AssetDatabase` / `ProjectAssetIndex` 的项目资产解析。
|
||||||
|
|
||||||
|
因此这个接口更接近一个“当前 root 前缀拼接 helper”,而不是项目资产语义解析入口。
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
- 当前调用方应自己保证 `m_resourceRoot` 已正确设置。
|
||||||
|
- 若 `relativePath` 本身不是相对路径,这里也不会帮你修正。
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [SetResourceRoot](SetResourceRoot.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [GetResourceRoot](GetResourceRoot.md)
|
||||||
|
- [AssetDatabase::ResolvePath](../AssetDatabase/ResolvePath.md)
|
||||||
|
|||||||
@@ -6,131 +6,212 @@
|
|||||||
|
|
||||||
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
**描述**: 运行时资源系统的中心入口,负责 loader 注册、同步加载、引用计数和部分缓存管理。
|
**描述**: 运行时资源系统的中心入口,负责 loader 注册、项目资产服务桥接、同步/异步加载、句柄引用计数、in-flight 去重以及部分缓存管理。
|
||||||
|
|
||||||
## 角色概述
|
## 角色概述
|
||||||
|
|
||||||
`ResourceManager` 是当前资源模块里最像“服务定位入口”的类。上层系统通常不会直接操作 `ResourceCache` 或 `AsyncLoader`,而是通过这里来做几件事:
|
`ResourceManager` 是当前资源模块里最接近“运行时入口”的类。它当前串起四层职责:
|
||||||
|
|
||||||
- 以 `ResourceType` 为键注册和查找 `IResourceLoader`
|
- loader 注册与查找
|
||||||
- 根据路径生成 `ResourceGUID`
|
- 项目资产服务桥接
|
||||||
- 执行同步 `Load<T>()`
|
- 运行时加载与缓存
|
||||||
- 记录句柄引用计数
|
- 句柄引用计数与异步入口
|
||||||
- 暴露资源根路径、内存预算和缓存查询入口
|
|
||||||
|
|
||||||
这种设计和商业引擎里常见的资源服务层比较接近。好处是资源调用点集中,上层 API 简洁;代价是很多子系统都要依赖这个全局单例,而且当前实现里缓存、引用计数和异步加载还没有完全闭环。
|
其中项目资产桥接链路不是“直接调用 `AssetDatabase`”,而是:
|
||||||
|
|
||||||
|
```text
|
||||||
|
ResourceManager
|
||||||
|
-> AssetImportService
|
||||||
|
-> ProjectAssetIndex snapshot
|
||||||
|
-> AssetDatabase
|
||||||
|
```
|
||||||
|
|
||||||
|
这条分层决定了:
|
||||||
|
|
||||||
|
- `SetResourceRoot()` 负责绑定项目根并初始化 snapshot
|
||||||
|
- `LoadResource()` 负责在真正加载前确保 artifact 就绪
|
||||||
|
- `TryGetAssetRef()` / `TryResolveAssetPath()` 先走 snapshot,再视情况回退到服务层
|
||||||
|
|
||||||
## 生命周期
|
## 生命周期
|
||||||
|
|
||||||
### 初始化
|
### `Initialize()`
|
||||||
|
|
||||||
`Initialize()` 当前会做三件事:
|
`Initialize()` 当前只转发到内部 `EnsureInitialized()`。
|
||||||
|
|
||||||
1. 创建一个 `AsyncLoader` 实例并调用 `Initialize(2)`
|
`EnsureInitialized()` 会:
|
||||||
2. 注册内建 `MaterialLoader`
|
|
||||||
3. 注册内建 `ShaderLoader`
|
|
||||||
|
|
||||||
这里有两个实际语义需要注意:
|
1. 创建 `AsyncLoader` 并调用 `Initialize(2)`
|
||||||
|
2. 注册 builtin `MaterialLoader`、`MeshLoader`、`ShaderLoader`、`TextureLoader`
|
||||||
|
3. 初始化 `AssetImportService`
|
||||||
|
4. 持有初始化后的 `AsyncLoader`
|
||||||
|
|
||||||
- `workerThreadCount = 2` 只是传入了 `AsyncLoader`,但当前 `AsyncLoader::Initialize()` 并不会真的创建工作线程。
|
因此当前自动注册的 builtin loader 一共四类,而项目资产链路真正是否生效仍取决于后续 `SetResourceRoot()` 是否绑定项目根。
|
||||||
- 只有材质和着色器 loader 会自动注册,其他资源类型需要调用方自行注册,或者当前根本还没有成熟 loader。
|
|
||||||
|
|
||||||
### 关闭
|
### `Shutdown()`
|
||||||
|
|
||||||
`Shutdown()` 会调用:
|
`Shutdown()` 会:
|
||||||
|
|
||||||
- `UnloadAll()`
|
- `UnloadAll()`
|
||||||
- `m_asyncLoader->Shutdown()`
|
- 关闭并释放 `m_asyncLoader`
|
||||||
- `m_asyncLoader.reset()`
|
- `m_assetImportService.Shutdown()`
|
||||||
|
- `ResourceFileSystem::Get().Shutdown()`
|
||||||
|
- `m_projectAssetIndex.ResetProjectRoot()`
|
||||||
|
- 清空 `m_inFlightLoads`
|
||||||
|
|
||||||
当前没有空指针保护,所以它默认假设你已经成功调用过 `Initialize()`。把它当成“可随时重复调用的幂等 API”并不安全。
|
这不仅卸载运行时资源,也会彻底断开项目资产服务和本地 snapshot。
|
||||||
|
|
||||||
|
## 项目资产链路
|
||||||
|
|
||||||
|
### `SetResourceRoot(rootPath)`
|
||||||
|
|
||||||
|
这不是一个单纯的路径前缀 setter。
|
||||||
|
|
||||||
|
当 `rootPath` 非空时,它会:
|
||||||
|
|
||||||
|
- 写入 `m_resourceRoot`
|
||||||
|
- 初始化 `ResourceFileSystem`
|
||||||
|
- `m_assetImportService.SetProjectRoot(rootPath)`
|
||||||
|
- `m_projectAssetIndex.RefreshFrom(m_assetImportService)`
|
||||||
|
|
||||||
|
当 `rootPath` 为空时,它会:
|
||||||
|
|
||||||
|
- 清空 `AssetImportService` 的项目根
|
||||||
|
- 关闭 `ResourceFileSystem`
|
||||||
|
- 重置 `ProjectAssetIndex`
|
||||||
|
|
||||||
|
所以它实际上是“进入 / 退出项目资产模式”的总开关。
|
||||||
|
|
||||||
|
### `RefreshProjectAssets()`
|
||||||
|
|
||||||
|
这是显式重建项目资产 snapshot 的轻量入口:
|
||||||
|
|
||||||
|
```text
|
||||||
|
ResourceManager::RefreshProjectAssets
|
||||||
|
-> AssetImportService::Refresh
|
||||||
|
-> ProjectAssetIndex::RefreshFrom
|
||||||
|
```
|
||||||
|
|
||||||
|
它只在 `m_resourceRoot` 非空时生效,也不会直接重载已经在缓存里的运行时对象。
|
||||||
|
|
||||||
|
### `RebuildProjectAssetCache()`
|
||||||
|
|
||||||
|
这是更重的项目缓存重建入口:
|
||||||
|
|
||||||
|
```text
|
||||||
|
ResourceManager::RebuildProjectAssetCache
|
||||||
|
-> UnloadAll
|
||||||
|
-> AssetImportService::RebuildLibraryCache
|
||||||
|
-> ProjectAssetIndex::RefreshFrom
|
||||||
|
```
|
||||||
|
|
||||||
|
它会清掉当前运行时资源缓存并重建整个 `Library` 目录。`tests/core/Asset/test_resource_manager.cpp` 里的 `ResourceManager_Test.RebuildProjectAssetCacheRefreshesLookupState` 已经覆盖了这条链路。
|
||||||
|
|
||||||
|
### `GetProjectLibraryRoot()`
|
||||||
|
|
||||||
|
直接返回当前项目 `Library` 根目录,底层转发到 `AssetImportService::GetLibraryRoot()`。这条入口主要用于测试和调试工具。
|
||||||
|
|
||||||
|
### `TryGetAssetRef()`
|
||||||
|
|
||||||
|
当前直接委托给 `ProjectAssetIndex::TryGetAssetRef(...)`。真实行为是:
|
||||||
|
|
||||||
|
1. 先查本地 `path -> guid` snapshot
|
||||||
|
2. miss 时回退到 `AssetImportService::TryGetAssetRef(...)`
|
||||||
|
3. 如果仍失败,而且路径像项目资产路径,则触发一次:
|
||||||
|
- `importService.Refresh()`
|
||||||
|
- `ProjectAssetIndex::RefreshFrom(importService)`
|
||||||
|
- 再重试
|
||||||
|
4. 成功后再通过 `TryGetPrimaryAssetPath()` 回填本地 snapshot
|
||||||
|
|
||||||
|
这就是当前 cache miss 刷新路径的真实位置。
|
||||||
|
|
||||||
|
### `TryResolveAssetPath()`
|
||||||
|
|
||||||
|
当前委托给 `ProjectAssetIndex::TryResolveAssetPath(...)`。行为和上面不完全对称:
|
||||||
|
|
||||||
|
1. 先查本地 `guid -> path` snapshot
|
||||||
|
2. miss 时回退到 `AssetImportService::TryGetPrimaryAssetPath(...)`
|
||||||
|
3. 成功后记回 snapshot
|
||||||
|
|
||||||
|
它不会像 `TryGetAssetRef()` 那样主动刷新整份 snapshot,而是只做一次数据库回退查询。
|
||||||
|
|
||||||
## 当前加载模型
|
## 当前加载模型
|
||||||
|
|
||||||
### 同步加载
|
### 同步加载
|
||||||
|
|
||||||
模板 `Load<T>()` 是目前最可依赖的主路径。按当前实现,它会:
|
路径版模板 [Load](Load.md) 最终都会走内部 `LoadResource(path, type, settings)`。当前主流程是:
|
||||||
|
|
||||||
1. 用原始 `path` 调用 `ResourceGUID::Generate(path)`
|
1. `EnsureInitialized()`
|
||||||
2. 在 `m_resourceCache` 里查缓存
|
2. 用原始请求路径生成 `ResourceGUID`
|
||||||
3. 用 `GetResourceType<T>()` 找到资源类型,再从 `m_loaders` 找 loader
|
3. 先查运行时缓存
|
||||||
4. 直接调用 `loader->Load(path, settings)`
|
4. 做 in-flight 去重;相同 `guid + type` 的并发请求会共享一次真实加载
|
||||||
5. 加入缓存并返回 `ResourceHandle<T>`
|
5. 找到对应 `IResourceLoader`
|
||||||
|
6. 如果 `m_resourceRoot` 非空,尝试 `m_assetImportService.EnsureArtifact(path, type, resolvedAsset)`
|
||||||
|
7. 若 `artifactReady=true`:
|
||||||
|
- `m_projectAssetIndex.RememberResolvedPath(resolvedAsset.assetGuid, resolvedAsset.relativePath)`
|
||||||
|
- 把真正传给 loader 的 `loadPath` 切到 `resolvedAsset.runtimeLoadPath`
|
||||||
|
8. 调用 `loader->Load(loadPath, settings)`
|
||||||
|
9. 成功后把 `resource->m_path` 设回原始请求路径
|
||||||
|
10. 写入缓存,并把 `guid -> 原始请求路径` 记入 `m_guidToPath`
|
||||||
|
|
||||||
这里有几个重要结论:
|
这里有三个关键结论:
|
||||||
|
|
||||||
- `Load<T>()` 并不会调用 `ResolvePath()`,所以 `SetResourceRoot()` 不会自动影响同步加载路径。
|
- 项目资产路径真正被 loader 读取的通常已经是 `Library/Artifacts/.../main.*`
|
||||||
- `GetResourceType<T>()` 只有少数显式特化;对没有特化的类型使用 `Load<T>()`,并不是“自动推断资源类型”。
|
- 资源对象对外暴露的 `m_path` 仍是原始请求路径
|
||||||
- loader 查找失败时会记录 warning 并返回空句柄。
|
- `Load<T>(const AssetRef&)` 只是先用 `TryResolveAssetPath()` 还原成源路径,再复用这条普通路径加载链路
|
||||||
- loader 加载失败时会记录 error 并返回空句柄。
|
|
||||||
|
|
||||||
### 异步加载
|
### 异步加载
|
||||||
|
|
||||||
`LoadAsync()` 只是把请求转发给 `m_asyncLoader->Submit(...)`。当前版本中:
|
`LoadAsync()` 只把请求转发给 `AsyncLoader::Submit(...)`。
|
||||||
|
|
||||||
- `Submit()` 只把请求压入 `m_pendingQueue`
|
当前版本里:
|
||||||
- 没有后台线程消费这个队列
|
|
||||||
- `QueueCompleted()` 也没有真正把成功结果放回完成队列
|
|
||||||
|
|
||||||
所以它的 API 形状已经存在,但不能当成成熟的异步资源流式系统来依赖。
|
- `AsyncLoader` 会启动真实工作线程
|
||||||
|
- 后台线程实际调用 `LoadResource()`
|
||||||
|
- 结果先进入完成队列
|
||||||
|
- 只有调用 `UpdateAsyncLoads()` 时,回调才会分发到当前线程
|
||||||
|
|
||||||
## 引用计数与句柄语义
|
因此它已经是可运行的异步加载路径,但仍更接近“后台加载 + 主线程轮询分发”模型,而不是全自动流式资源系统。
|
||||||
|
|
||||||
[ResourceHandle](../ResourceHandle/ResourceHandle.md) 的构造、拷贝、析构都会调用 `AddRef()` / `Release()`。这意味着 `ResourceManager` 记录的是“句柄引用数”,不是资源对象的真实所有权。
|
## 延迟场景加载开关
|
||||||
|
|
||||||
当前实现里还有两个关键现实:
|
`ScopedDeferredSceneLoad` 是 `BeginDeferredSceneLoad()` / `EndDeferredSceneLoad()` 的 RAII 包装器:
|
||||||
|
|
||||||
- `Release()` 在引用数归零时只会调用 `m_cache.OnZeroRefCount(guid)`,而这个函数当前是空实现。
|
- 构造时递增 `m_deferredSceneLoadDepth`
|
||||||
- `AddRef()` 发现资源不在 `m_resourceCache` 时会调用 `ReloadResource(guid)`,但 `ReloadResource()` 现在基本是 stub,而且 `m_guidToPath` 在正常加载路径里也没有被填充。
|
- 析构时在非空管理器上递减
|
||||||
|
- [IsDeferredSceneLoadEnabled](IsDeferredSceneLoadEnabled.md) 通过原子计数判断是否开启
|
||||||
|
|
||||||
结果就是:
|
这条能力当前只表达“是否处于延迟场景加载区间”,不直接替代真正的异步恢复调度器。
|
||||||
|
|
||||||
- “最后一个句柄释放后自动卸载资源”当前并没有真正成立。
|
## 引用计数与缓存现状
|
||||||
- “句柄重新引用一个已卸载资源时自动重载”当前也没有真正成立。
|
|
||||||
|
|
||||||
## 缓存与内存预算
|
[ResourceHandle](../ResourceHandle/ResourceHandle.md) 的构造、拷贝、析构都会调用 `AddRef()` / `Release()`,因此 `ResourceManager` 记录的是“句柄引用数”。
|
||||||
|
|
||||||
`ResourceManager` 内部同时维护:
|
当前实现仍有几个现实限制:
|
||||||
|
|
||||||
- `m_resourceCache`
|
- `Release()` 在引用数归零时只会调用 `m_cache.OnZeroRefCount(guid)`,这条行为链还没有完全打通成真实自动卸载
|
||||||
- `m_memoryUsage`
|
- `ReloadResource()` 仍基本是 stub
|
||||||
- 一个独立的 `ResourceCache m_cache`
|
- `UnloadUnused()` 仍是空实现
|
||||||
|
- `m_resourceCache` / `m_memoryUsage` 和 `ResourceCache m_cache` 的状态并不总是严格同步
|
||||||
|
|
||||||
从设计意图上看,这是想把“管理器级索引”和“缓存策略对象”分层。但按当前实现,这两层并没有完全同步:
|
所以当前版本里,“自动卸载”“自动重载”和“缓存统计完全一致”都还不是成熟保证。
|
||||||
|
|
||||||
- `AddToCache()` 会同时写入 `m_resourceCache` 和 `m_cache`
|
## 测试锚点
|
||||||
- `Unload()` / `UnloadGroup()` 只移除 `m_resourceCache`,不会同步移除 `m_cache`
|
|
||||||
- `FlushCache()` 只调用 `m_cache.Flush()`,不会清理 `m_resourceCache` 和 `m_memoryUsage`
|
|
||||||
- `ResourceCache::Evict()` 会直接 `Release()` 资源,但不会回写 `m_resourceCache`
|
|
||||||
- `SetMemoryBudget()` 只改 `ResourceManager` 自己的预算值,没有把预算同步给 `m_cache`
|
|
||||||
|
|
||||||
这意味着当前版本里,“缓存是否存在”“管理器是否还持有指针”“内存统计是否准确”并不总是完全一致。文档和调用方都不应把这里理解成已经严密打通的商业级缓存系统。
|
`tests/core/Asset/test_resource_manager.cpp` 当前直接覆盖了几条关键语义:
|
||||||
|
|
||||||
## 查询与路径语义
|
- `ConcurrentAsyncLoadsCoalesceSameMeshPath`
|
||||||
|
- 验证相同 `guid + type` 的并发请求会共享一次实际加载
|
||||||
- `Find(path)` / `Find(guid)` 只查当前缓存,不查磁盘。
|
- `AssetLookupFallbackRefreshesSnapshotForNewProjectAsset`
|
||||||
- `Exists(path)` / `Exists(guid)` 也只代表“当前是否在缓存里”,不代表文件存在。
|
- 验证 `TryGetAssetRef()` 会在 cache miss 时刷新 snapshot 再重试
|
||||||
- `ResolvePath(relativePath)` 只是简单返回 `m_resourceRoot + "/" + relativePath`。
|
- `ResourceManager_Test.RebuildProjectAssetCacheRefreshesLookupState`
|
||||||
- `GetResourcePaths()` 读取的是 `m_guidToPath`,但当前默认加载流程没有填这个表,所以它通常不会返回你期待的完整已加载资源路径列表。
|
- 验证重建 `Library` 缓存后,查询状态仍能恢复
|
||||||
- `LoadGroup()` 会对每个路径分别发起 `LoadAsync()`,并逐个回调,不会做“整组完成后再统一通知”的聚合。
|
|
||||||
|
|
||||||
## 线程语义
|
|
||||||
|
|
||||||
- `AddRef()`、`Release()`、缓存写入和 loader 注册等路径使用了 `m_mutex`。
|
|
||||||
- 并不是所有只读接口都加了锁,例如 `GetRefCount()`、`GetMemoryUsage()`、`GetMemoryBudget()`、`GetLoader()`。
|
|
||||||
- loader 本身是否线程安全、回调在哪个线程执行,当前并没有统一契约。
|
|
||||||
- 结合 `AsyncLoader` 的现状,默认仍应按主线程驱动资源系统理解。
|
|
||||||
|
|
||||||
## 当前实现限制
|
## 当前实现限制
|
||||||
|
|
||||||
- 当前自动注册的 loader 只有 `Material` 和 `Shader`。
|
- 自动注册的 builtin loader 只有 `Material`、`Mesh`、`Shader`、`Texture`
|
||||||
- `Load<T>()` 不会自动使用 `SetResourceRoot()`。
|
- `UnloadUnused()` 是空实现
|
||||||
- `UnloadUnused()` 是空实现。
|
- `LoadAsync()` / `LoadGroup()` 仍要求主线程稳定调用 `UpdateAsyncLoads()`
|
||||||
- `UnloadAll()` 当前只是清空容器和内存计数,没有逐个释放所有资源对象。
|
- 项目资产 snapshot 的自动刷新只发生在少数显式入口,不是文件监听驱动的全局自动同步系统
|
||||||
- `ReloadResource()` 只有路径表检查,没有真正重载逻辑。
|
|
||||||
- `GetResourcePaths()` 依赖的 `m_guidToPath` 当前默认不会在同步加载时维护。
|
|
||||||
- `ResourceManager` 和 `ResourceCache` 的状态同步并不完整,存在悬空指针和统计不一致风险。
|
|
||||||
- `LoadAsync()` / `LoadGroup()` 目前不适合当成生产可用的异步加载通路。
|
|
||||||
|
|
||||||
## 相关方法
|
## 相关方法
|
||||||
|
|
||||||
@@ -141,6 +222,9 @@
|
|||||||
- [GetResourceRoot](GetResourceRoot.md)
|
- [GetResourceRoot](GetResourceRoot.md)
|
||||||
- [Load](Load.md)
|
- [Load](Load.md)
|
||||||
- [LoadAsync](LoadAsync.md)
|
- [LoadAsync](LoadAsync.md)
|
||||||
|
- [UpdateAsyncLoads](UpdateAsyncLoads.md)
|
||||||
|
- [IsAsyncLoading](IsAsyncLoading.md)
|
||||||
|
- [GetAsyncPendingCount](GetAsyncPendingCount.md)
|
||||||
- [Unload](Unload.md)
|
- [Unload](Unload.md)
|
||||||
- [UnloadUnused](UnloadUnused.md)
|
- [UnloadUnused](UnloadUnused.md)
|
||||||
- [UnloadAll](UnloadAll.md)
|
- [UnloadAll](UnloadAll.md)
|
||||||
@@ -160,6 +244,15 @@
|
|||||||
- [LoadGroup](LoadGroup.md)
|
- [LoadGroup](LoadGroup.md)
|
||||||
- [GetResourcePaths](GetResourcePaths.md)
|
- [GetResourcePaths](GetResourcePaths.md)
|
||||||
- [UnloadGroup](UnloadGroup.md)
|
- [UnloadGroup](UnloadGroup.md)
|
||||||
|
- [RefreshProjectAssets](RefreshProjectAssets.md)
|
||||||
|
- [RebuildProjectAssetCache](RebuildProjectAssetCache.md)
|
||||||
|
- [GetProjectLibraryRoot](GetProjectLibraryRoot.md)
|
||||||
|
- [TryGetAssetRef](TryGetAssetRef.md)
|
||||||
|
- [TryResolveAssetPath](TryResolveAssetPath.md)
|
||||||
|
- [ScopedDeferredSceneLoad](ScopedDeferredSceneLoad.md)
|
||||||
|
- [BeginDeferredSceneLoad](BeginDeferredSceneLoad.md)
|
||||||
|
- [EndDeferredSceneLoad](EndDeferredSceneLoad.md)
|
||||||
|
- [IsDeferredSceneLoadEnabled](IsDeferredSceneLoadEnabled.md)
|
||||||
|
|
||||||
## 相关指南
|
## 相关指南
|
||||||
|
|
||||||
@@ -168,6 +261,9 @@
|
|||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [当前模块](../Asset.md)
|
- [当前模块](../Asset.md)
|
||||||
|
- [AssetImportService](../AssetImportService/AssetImportService.md)
|
||||||
|
- [ProjectAssetIndex](../ProjectAssetIndex/ProjectAssetIndex.md)
|
||||||
|
- [AssetDatabase](../AssetDatabase/AssetDatabase.md)
|
||||||
- [ResourceHandle](../ResourceHandle/ResourceHandle.md)
|
- [ResourceHandle](../ResourceHandle/ResourceHandle.md)
|
||||||
- [ResourceCache](../ResourceCache/ResourceCache.md)
|
- [ResourceCache](../ResourceCache/ResourceCache.md)
|
||||||
- [AsyncLoader](../AsyncLoader/AsyncLoader.md)
|
- [AsyncLoader](../AsyncLoader/AsyncLoader.md)
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# ResourceManager::ScopedDeferredSceneLoad
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `nested class`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
一个 RAII helper,用于在作用域内临时启用 deferred scene load 模式。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 构造函数默认绑定 `ResourceManager::Get()`,也可以显式传入某个 `ResourceManager&`。
|
||||||
|
- 构造时立即调用 [BeginDeferredSceneLoad](BeginDeferredSceneLoad.md)。
|
||||||
|
- 析构时如果 `m_manager` 非空,则调用 [EndDeferredSceneLoad](EndDeferredSceneLoad.md)。
|
||||||
|
- 拷贝构造和拷贝赋值被显式删除,避免同一作用域令牌被意外复制。
|
||||||
|
|
||||||
|
## 当前语义
|
||||||
|
|
||||||
|
它的价值不是提供新状态,而是保证:
|
||||||
|
|
||||||
|
- 进入作用域时深度计数 `+1`
|
||||||
|
- 离开作用域时深度计数 `-1`
|
||||||
|
|
||||||
|
这样即便提前 `return` 或异常退出,也不容易漏掉结束调用。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
- [BeginDeferredSceneLoad](BeginDeferredSceneLoad.md)
|
||||||
|
- [EndDeferredSceneLoad](EndDeferredSceneLoad.md)
|
||||||
|
- [IsDeferredSceneLoadEnabled](IsDeferredSceneLoadEnabled.md)
|
||||||
@@ -1,31 +1,22 @@
|
|||||||
# ResourceManager::SetMemoryBudget
|
# ResourceManager::SetMemoryBudget
|
||||||
|
|
||||||
设置相关状态或配置。
|
设置运行时资源缓存使用的目标内存预算。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void SetMemoryBudget(size_t bytes);
|
void SetMemoryBudget(size_t bytes);
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:**
|
- 直接把 `bytes` 写入 `m_memoryBudget`
|
||||||
- `bytes` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
## 当前语义
|
||||||
|
|
||||||
**示例:**
|
- 这不会立刻触发清理。
|
||||||
|
- 当前内存压力处理主要发生在后续资源进入缓存时,由 `AddToCache()` 在 `m_memoryUsage > m_memoryBudget` 时通知 `m_cache.OnMemoryPressure(...)`。
|
||||||
```cpp
|
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::SetMemoryBudget(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [GetMemoryBudget](GetMemoryBudget.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [GetMemoryUsage](GetMemoryUsage.md)
|
||||||
|
- [FlushCache](FlushCache.md)
|
||||||
|
|||||||
@@ -1,31 +1,48 @@
|
|||||||
# ResourceManager::SetResourceRoot
|
# ResourceManager::SetResourceRoot
|
||||||
|
|
||||||
设置相关状态或配置。
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void SetResourceRoot(const Containers::String& rootPath);
|
void SetResourceRoot(const Containers::String& rootPath);
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 作用
|
||||||
|
|
||||||
**参数:**
|
切换资源根目录,并决定 `ResourceManager` 是否进入“项目资产模式”。
|
||||||
- `rootPath` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
## 当前实现行为
|
||||||
|
|
||||||
**示例:**
|
- 总是先把 `m_resourceRoot` 设为传入值。
|
||||||
|
- 当 `rootPath` 非空时:
|
||||||
|
- 初始化 `ResourceFileSystem`
|
||||||
|
- 调用 `m_assetImportService.SetProjectRoot(rootPath)`
|
||||||
|
- 调用 `m_projectAssetIndex.RefreshFrom(m_assetImportService)`
|
||||||
|
- 当 `rootPath` 为空时:
|
||||||
|
- 清空 `AssetImportService` 的项目根
|
||||||
|
- 关闭 `ResourceFileSystem`
|
||||||
|
- 重置 `ProjectAssetIndex`
|
||||||
|
|
||||||
```cpp
|
## 为什么这很重要
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
这不是一个单纯的“路径前缀 setter”。
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::SetResourceRoot(...)。
|
设置资源根之后,`ResourceManager` 才会真正接入:
|
||||||
(void)object;
|
|
||||||
}
|
- 项目资产到 artifact 的转换
|
||||||
```
|
- `AssetRef` 与 `AssetGUID` 查询
|
||||||
|
- `ProjectAssetIndex` 的初始 lookup snapshot
|
||||||
|
|
||||||
|
清空资源根则会把这整条项目资产服务链一并断开。
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [ResourceManager](ResourceManager.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [GetResourceRoot](GetResourceRoot.md)
|
||||||
|
- [RefreshProjectAssets](RefreshProjectAssets.md)
|
||||||
|
- [AssetImportService](../AssetImportService/AssetImportService.md)
|
||||||
|
|||||||
@@ -1,30 +1,35 @@
|
|||||||
# ResourceManager::Shutdown
|
# ResourceManager::Shutdown
|
||||||
|
|
||||||
关闭并清理内部状态。
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 作用
|
||||||
|
|
||||||
**参数:** 无。
|
关闭资源管理器并清理当前会话级状态。
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
## 当前实现行为
|
||||||
|
|
||||||
**示例:**
|
- 会先调用 [UnloadAll](UnloadAll.md)。
|
||||||
|
- 如果 `m_asyncLoader` 存在,再调用其 `Shutdown()` 并清空 unique ptr。
|
||||||
|
- 随后关闭 `m_assetImportService`、关闭 `ResourceFileSystem`,并把 `ProjectAssetIndex` 重置为空项目根状态。
|
||||||
|
- 还会清空 `m_inFlightLoads`。
|
||||||
|
|
||||||
```cpp
|
## 当前实现边界
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
- 这不是严格幂等的“随时安全调用”接口;当前实现仍假设资源管理器已经经历过正常初始化。
|
||||||
XCEngine::Resources::ResourceManager object;
|
- 它不会保留项目资产 snapshot,也不会保留挂起加载状态。
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::Shutdown(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [ResourceManager](ResourceManager.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [Initialize](Initialize.md)
|
||||||
|
- [UnloadAll](UnloadAll.md)
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# ResourceManager::TryGetAssetRef
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool TryGetAssetRef(
|
||||||
|
const Containers::String& path,
|
||||||
|
ResourceType resourceType,
|
||||||
|
AssetRef& outRef) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
把一条项目资产路径解析成主资产 `AssetRef`。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 当前直接委托给 `m_projectAssetIndex.TryGetAssetRef(m_assetImportService, path, resourceType, outRef)`。
|
||||||
|
- `ProjectAssetIndex` 会优先查本地 `path -> guid` snapshot。
|
||||||
|
- snapshot miss 时,会回退到 `AssetImportService::TryGetAssetRef(...)`。
|
||||||
|
- 如果第一次回退仍失败,而且路径看起来像当前项目下的 `Assets/...`,它会进一步触发:
|
||||||
|
- `importService.Refresh()`
|
||||||
|
- `ProjectAssetIndex::RefreshFrom(importService)`
|
||||||
|
- 然后再重试一次
|
||||||
|
- 成功后还会通过 `TryGetPrimaryAssetPath()` 回填本地 snapshot。
|
||||||
|
|
||||||
|
## 当前语义
|
||||||
|
|
||||||
|
- 这是当前项目资产查询接口,不适用于 `builtin://...` 这类虚拟路径。
|
||||||
|
- `resourceType` 由调用方指定,并会写入成功返回的 `AssetRef`;这里不会重新校验它是否与 importer 真实匹配。
|
||||||
|
- 真正的类型匹配要到 `AssetImportService::EnsureArtifact()` / `LoadResource()` 阶段才会检查。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
- [TryResolveAssetPath](TryResolveAssetPath.md)
|
||||||
|
- [ProjectAssetIndex](../ProjectAssetIndex/ProjectAssetIndex.md)
|
||||||
|
- [AssetDatabase::TryGetAssetRef](../AssetDatabase/TryGetAssetRef.md)
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# ResourceManager::TryResolveAssetPath
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool TryResolveAssetPath(
|
||||||
|
const AssetRef& assetRef,
|
||||||
|
Containers::String& outPath) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
把一个主资产 `AssetRef` 反查回其 source 资产路径,通常是 `Assets/...`。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 当前直接委托给 `m_projectAssetIndex.TryResolveAssetPath(m_assetImportService, assetRef, outPath)`。
|
||||||
|
- `ProjectAssetIndex` 会优先使用本地 `guid -> path` snapshot。
|
||||||
|
- snapshot miss 时,会回退到 `AssetImportService::TryGetPrimaryAssetPath(...)`。
|
||||||
|
- 如果回退成功,会把结果通过 `RememberResolvedPath()` 回写到本地 snapshot。
|
||||||
|
|
||||||
|
## 和 `TryGetAssetRef()` 的差异
|
||||||
|
|
||||||
|
这条路径和 `TryGetAssetRef()` 并不完全对称:
|
||||||
|
|
||||||
|
- `TryGetAssetRef()` 在 cache miss 时可能触发一次 `Refresh() + RefreshFrom()`。
|
||||||
|
- `TryResolveAssetPath()` 当前不会主动刷新整份 snapshot;它只做一次数据库回退查询。
|
||||||
|
|
||||||
|
因此它更像“guid -> path 的轻量回填路径”,而不是带自动刷新能力的发现入口。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
- [TryGetAssetRef](TryGetAssetRef.md)
|
||||||
|
- [ProjectAssetIndex](../ProjectAssetIndex/ProjectAssetIndex.md)
|
||||||
|
- [AssetImportService](../AssetImportService/AssetImportService.md)
|
||||||
@@ -1,44 +1,37 @@
|
|||||||
# ResourceManager::Unload
|
# ResourceManager::Unload
|
||||||
|
|
||||||
卸载资源或释放缓存。
|
把一个资源从当前运行时缓存中移除,并释放资源对象引用。
|
||||||
|
|
||||||
该方法在 `XCEngine/Core/Asset/ResourceManager.h` 中提供了 2 个重载,当前页面统一汇总这些公开声明。
|
|
||||||
|
|
||||||
## 重载 1: 声明
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void Unload(const Containers::String& path);
|
void Unload(const Containers::String& path);
|
||||||
```
|
|
||||||
|
|
||||||
**参数:**
|
|
||||||
- `path` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
|
||||||
|
|
||||||
## 重载 2: 声明
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void Unload(ResourceGUID guid);
|
void Unload(ResourceGUID guid);
|
||||||
```
|
```
|
||||||
|
|
||||||
**参数:**
|
## 当前行为
|
||||||
- `guid` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
### `Unload(path)`
|
||||||
|
|
||||||
**示例:**
|
- 先把路径转成 `ResourceGUID::Generate(path)`
|
||||||
|
- 再转发到 `Unload(guid)`
|
||||||
|
|
||||||
```cpp
|
### `Unload(guid)`
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
按当前实现:
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::Unload(...)。
|
1. 在锁内从 `m_resourceCache` 里查找目标资源
|
||||||
(void)object;
|
2. 若找到:
|
||||||
}
|
- 从 `m_resourceCache` 移除
|
||||||
```
|
- 从 `m_guidToPath` 移除
|
||||||
|
- 从 `m_memoryUsage` 中扣除该资源大小
|
||||||
|
3. 解锁后对资源对象执行 `resource->Release()`
|
||||||
|
|
||||||
|
## 当前实现边界
|
||||||
|
|
||||||
|
- 当前 `Unload(guid)` 不会同步清掉 `m_refCounts`。
|
||||||
|
- 因此它更像“强制从缓存摘掉对象”,而不是一次完整的引用计数收口。
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [UnloadAll](UnloadAll.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [UnloadGroup](UnloadGroup.md)
|
||||||
|
- [Release](Release.md)
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
# ResourceManager::UnloadAll
|
# ResourceManager::UnloadAll
|
||||||
|
|
||||||
卸载资源或释放缓存。
|
清空当前运行时缓存中的全部资源。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void UnloadAll();
|
void UnloadAll();
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:** 无。
|
按当前实现:
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
1. 在锁内收集当前 `m_resourceCache` 中所有非空资源指针
|
||||||
|
2. 清空:
|
||||||
|
- `m_resourceCache`
|
||||||
|
- `m_refCounts`
|
||||||
|
- `m_guidToPath`
|
||||||
|
3. 把 `m_memoryUsage` 归零
|
||||||
|
4. 解锁后逐个对收集到的资源执行 `Release()`
|
||||||
|
|
||||||
**示例:**
|
## 当前语义
|
||||||
|
|
||||||
```cpp
|
- 这是 `Shutdown()` 关闭阶段使用的主清理入口。
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
- 它会直接丢弃当前所有缓存与计数状态,不保留增量信息。
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::UnloadAll(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [Unload](Unload.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [UnloadGroup](UnloadGroup.md)
|
||||||
|
- [Shutdown](Shutdown.md)
|
||||||
|
|||||||
@@ -1,31 +1,30 @@
|
|||||||
# ResourceManager::UnloadGroup
|
# ResourceManager::UnloadGroup
|
||||||
|
|
||||||
卸载资源或释放缓存。
|
按 GUID 列表批量把资源从运行时缓存中移除。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void UnloadGroup(const Containers::Array<ResourceGUID>& guids);
|
void UnloadGroup(const Containers::Array<ResourceGUID>& guids);
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:**
|
按当前实现:
|
||||||
- `guids` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
1. 在锁内遍历 `guids`
|
||||||
|
2. 对每个命中的缓存项:
|
||||||
|
- 从 `m_resourceCache` 移除
|
||||||
|
- 从 `m_guidToPath` 移除
|
||||||
|
- 从 `m_memoryUsage` 中扣除资源大小
|
||||||
|
- 把资源指针加入待释放数组
|
||||||
|
3. 解锁后逐个对这些资源执行 `Release()`
|
||||||
|
|
||||||
**示例:**
|
## 当前实现边界
|
||||||
|
|
||||||
```cpp
|
- 和 [Unload](Unload.md) 一样,它当前不会同步清掉 `m_refCounts`。
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
- 这是“缓存批量摘除”接口,不是完整的引用计数批量回收接口。
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::UnloadGroup(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [Unload](Unload.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [UnloadAll](UnloadAll.md)
|
||||||
|
- [GetResourcePaths](GetResourcePaths.md)
|
||||||
|
|||||||
@@ -1,30 +1,22 @@
|
|||||||
# ResourceManager::UnloadUnused
|
# ResourceManager::UnloadUnused
|
||||||
|
|
||||||
卸载资源或释放缓存。
|
尝试卸载未使用资源。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void UnloadUnused();
|
void UnloadUnused();
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:** 无。
|
当前实现为空函数,不执行任何操作。
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
## 当前语义
|
||||||
|
|
||||||
**示例:**
|
- 这个 API 形状已经存在,但“按引用计数或缓存策略自动清理未使用资源”的逻辑目前还没有落地。
|
||||||
|
- 如果调用方需要确定性释放,当前仍应使用 [Unload](Unload.md)、[UnloadGroup](UnloadGroup.md) 或 [UnloadAll](UnloadAll.md)。
|
||||||
```cpp
|
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::UnloadUnused(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [Unload](Unload.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [UnloadAll](UnloadAll.md)
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
|||||||
@@ -1,31 +1,22 @@
|
|||||||
# ResourceManager::UnregisterLoader
|
# ResourceManager::UnregisterLoader
|
||||||
|
|
||||||
取消注册对象、回调或映射。
|
移除某个资源类型对应的 loader 注册。
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void UnregisterLoader(ResourceType type);
|
void UnregisterLoader(ResourceType type);
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Core/Asset/ResourceManager.h`,当前页面用于固定 `ResourceManager` 类目录下的方法级 canonical 路径。
|
## 当前行为
|
||||||
|
|
||||||
**参数:**
|
- 直接从 `m_loaders` 映射里删除指定 `ResourceType`
|
||||||
- `type` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
## 当前语义
|
||||||
|
|
||||||
**示例:**
|
- 这里只移除 `ResourceManager` 的类型到指针映射。
|
||||||
|
- 不会销毁 loader 对象本身。
|
||||||
```cpp
|
|
||||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
||||||
|
|
||||||
void Example() {
|
|
||||||
XCEngine::Resources::ResourceManager object;
|
|
||||||
// 根据上下文补齐参数后调用 ResourceManager::UnregisterLoader(...)。
|
|
||||||
(void)object;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](ResourceManager.md)
|
- [RegisterLoader](RegisterLoader.md)
|
||||||
- [返回模块目录](../Asset.md)
|
- [GetLoader](GetLoader.md)
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# ResourceManager::UpdateAsyncLoads
|
||||||
|
|
||||||
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
|
**类型**: `method`
|
||||||
|
|
||||||
|
**头文件**: `XCEngine/Core/Asset/ResourceManager.h`
|
||||||
|
|
||||||
|
## 签名
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void UpdateAsyncLoads();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
推进一次异步加载器的更新循环。
|
||||||
|
|
||||||
|
## 当前实现行为
|
||||||
|
|
||||||
|
- 若 `m_asyncLoader` 存在,则调用 `m_asyncLoader->Update()`。
|
||||||
|
- 若异步加载器尚未初始化,则安全地什么都不做。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [ResourceManager](ResourceManager.md)
|
||||||
|
- [LoadAsync](LoadAsync.md)
|
||||||
|
- [IsAsyncLoading](IsAsyncLoading.md)
|
||||||
@@ -1,14 +1,34 @@
|
|||||||
# Material
|
# Material
|
||||||
|
|
||||||
**命名空间**: `XCEngine::Resources::Material`
|
**命名空间**: `XCEngine::Resources`
|
||||||
|
|
||||||
**类型**: `submodule`
|
**类型**: `submodule`
|
||||||
|
|
||||||
**描述**: 材质资源与材质加载器。
|
**描述**: 材质运行时对象、材质 source 文件解析,以及 `.xcmat` artifact 回读链路所在子模块。
|
||||||
|
|
||||||
## 概览
|
## 概览
|
||||||
|
|
||||||
该目录与 `XCEngine/Resources/Material` 对应的 public headers 保持平行,用于承载唯一的 canonical API 文档入口。
|
`Resources/Material` 当前已经把三层语义收在同一目录里:
|
||||||
|
|
||||||
|
- [Material](Material/Material.md)
|
||||||
|
运行时材质对象,负责 shader schema、render metadata、数值属性、texture binding 元数据和 packed constant buffer。
|
||||||
|
- [MaterialLoader](MaterialLoader/MaterialLoader.md)
|
||||||
|
负责 source 材质与 `.xcmat` artifact 的加载。
|
||||||
|
- 与项目资产链路的接缝
|
||||||
|
通过 `AssetRef`、texture path 和 `ResourceManager` 的异步加载,把材质纹理绑定从“稳定身份”兑现成运行时句柄。
|
||||||
|
|
||||||
|
当前材质链路的关键点是:
|
||||||
|
|
||||||
|
- source 材质里的 texture path 会进入 `AssetDatabase` 的依赖快照
|
||||||
|
- `.xcmat` v2 会同时保存编码 `AssetRef` 与可选 path
|
||||||
|
- `Material::GetTexture(...)` / `GetTextureBindingTexture(...)` 会在首次访问时启动异步纹理兑现
|
||||||
|
|
||||||
|
## 当前主链路
|
||||||
|
|
||||||
|
1. `MaterialLoader` 读取 `.mat` / `.material` / `.json` 或 `.xcmat`。
|
||||||
|
2. `Material` 保存 render metadata、数值属性和 texture binding 元数据。
|
||||||
|
3. 若 texture binding 只有 path / `AssetRef`,首次读取时才通过 `ResourceManager` 启动异步加载。
|
||||||
|
4. `AssetDatabase` 写出新的 `.xcmat` 时,会把这套元数据重新编码进 artifact。
|
||||||
|
|
||||||
## 头文件
|
## 头文件
|
||||||
|
|
||||||
@@ -17,5 +37,8 @@
|
|||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
|
- [ArtifactFormats](../../Core/Asset/ArtifactFormats/ArtifactFormats.md)
|
||||||
|
- [AssetDatabase](../../Core/Asset/AssetDatabase/AssetDatabase.md)
|
||||||
|
- [Asset](../../Core/Asset/Asset.md)
|
||||||
- [上级目录](../Resources.md)
|
- [上级目录](../Resources.md)
|
||||||
- [API 总索引](../../../main.md)
|
- [API 总索引](../../../main.md)
|
||||||
|
|||||||
@@ -1,30 +1,39 @@
|
|||||||
# Material::ClearAllProperties
|
# Material::ClearAllProperties
|
||||||
|
|
||||||
清空内部数据。
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void ClearAllProperties();
|
void ClearAllProperties();
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Resources/Material/Material.h`,当前页面用于固定 `Material` 类目录下的方法级 canonical 路径。
|
## 作用
|
||||||
|
|
||||||
**参数:** 无。
|
清空当前材质持有的属性、texture binding 和常量缓冲数据,然后按当前 shader schema 重新同步默认值。
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
## 当前行为
|
||||||
|
|
||||||
**示例:**
|
1. 清空 `m_properties`
|
||||||
|
2. 清空 `m_textureBindings`
|
||||||
|
3. 清空 `m_constantBufferData`
|
||||||
|
4. 调用 `SyncShaderSchemaProperties(false)`
|
||||||
|
5. 调用 `MarkChanged(true)`
|
||||||
|
|
||||||
```cpp
|
如果当前绑定了 shader,`SyncShaderSchemaProperties(false)` 会把 shader schema 中声明的属性重新补回默认值;如果当前没有 shader,则清空后的空状态会被直接保留。
|
||||||
#include <XCEngine/Resources/Material/Material.h>
|
|
||||||
|
|
||||||
void Example() {
|
## 关键语义
|
||||||
XCEngine::Resources::Material object;
|
|
||||||
// 根据上下文补齐参数后调用 Material::ClearAllProperties(...)。
|
- 它不是简单的“全部删除后什么都不剩”
|
||||||
(void)object;
|
- 对带 shader schema 的材质来说,它更接近“恢复到当前 shader 默认材质状态”
|
||||||
}
|
- 现有 texture binding 会全部被丢弃;即使 shader schema 里仍声明 texture property,也只会恢复属性默认值,不会保留旧的 loaded texture / `AssetRef` / path
|
||||||
```
|
- 因为最终走 `MarkChanged(true)`,所以它也会触发常量缓冲重打包和 `changeVersion` 递增
|
||||||
|
|
||||||
|
## 测试覆盖
|
||||||
|
|
||||||
|
`tests/Resources/Material/test_material.cpp` 当前覆盖了两类语义:
|
||||||
|
|
||||||
|
- 无 shader 时,`ClearAllProperties()` 会让原有数值属性全部消失
|
||||||
|
- 有 shader schema 时,`ClearAllProperties()` 会恢复 schema 默认值,而不是保持完全空白
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](Material.md)
|
- [Material](Material.md)
|
||||||
- [返回模块目录](../Material.md)
|
- [SetShader](SetShader.md)
|
||||||
|
- [RemoveProperty](RemoveProperty.md)
|
||||||
|
|||||||
@@ -1,31 +1,49 @@
|
|||||||
# Material::GetTexture
|
# Material::GetTexture
|
||||||
|
|
||||||
获取相关状态或对象。
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
ResourceHandle<Texture> GetTexture(const Containers::String& name) const;
|
ResourceHandle<Texture> GetTexture(const Containers::String& name) const;
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Resources/Material/Material.h`,当前页面用于固定 `Material` 类目录下的方法级 canonical 路径。
|
## 作用
|
||||||
|
|
||||||
**参数:**
|
按 texture property 名称读取纹理句柄,并在需要时启动一次懒加载。
|
||||||
- `name` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `ResourceHandle<Texture>` - 返回值语义详见头文件声明。
|
## 当前行为
|
||||||
|
|
||||||
**示例:**
|
1. 先调用 `ResolvePendingTextureBindings()`,把已完成的异步加载结果并回 binding。
|
||||||
|
2. 查找同名 texture binding。
|
||||||
|
3. 如果当前还没有 loaded handle,且:
|
||||||
|
- `pendingLoad == nullptr`
|
||||||
|
- `texturePath` 非空,或 `textureRef` 有效
|
||||||
|
则调用 `BeginAsyncTextureLoad(...)` 启动异步加载。
|
||||||
|
4. 返回当前 `binding.texture`。
|
||||||
|
|
||||||
```cpp
|
## 关键语义
|
||||||
#include <XCEngine/Resources/Material/Material.h>
|
|
||||||
|
|
||||||
void Example() {
|
- 第一次调用时,如果 binding 只有 path / `AssetRef`,通常会返回空句柄,同时把异步加载排进 `ResourceManager`。
|
||||||
XCEngine::Resources::Material object;
|
- 如果 binding 只有 `AssetRef` 没有 path,`BeginAsyncTextureLoad(...)` 会先通过 `ResourceManager::TryResolveAssetPath(...)` 反查 path。
|
||||||
// 根据上下文补齐参数后调用 Material::GetTexture(...)。
|
- 要让异步加载真正完成,调用方仍需要驱动 `ResourceManager::UpdateAsyncLoads()`。
|
||||||
(void)object;
|
- 想只看“当前是否已经有 loaded handle”,而不触发新的加载,应改用 [GetTextureBindingLoadedTexture](GetTextureBindingLoadedTexture.md)。
|
||||||
}
|
|
||||||
```
|
## 参数
|
||||||
|
|
||||||
|
- `name` - 目标 texture property 名称。
|
||||||
|
|
||||||
|
## 返回值
|
||||||
|
|
||||||
|
- 返回当前 binding 的 loaded texture。
|
||||||
|
- 若尚未加载完成,可能返回空句柄。
|
||||||
|
|
||||||
|
## 测试覆盖
|
||||||
|
|
||||||
|
`tests/Resources/Material/test_material_loader.cpp` 当前验证了:
|
||||||
|
|
||||||
|
- source 材质与 `.xcmat` artifact 中的 texture binding 都可以先以空句柄状态加载
|
||||||
|
- 首次访问会把纹理异步加载排进 `ResourceManager`
|
||||||
|
- 完成 `UpdateAsyncLoads()` 后再次访问能拿到真实纹理
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](Material.md)
|
- [Material](Material.md)
|
||||||
- [返回模块目录](../Material.md)
|
- [GetTextureBindingLoadedTexture](GetTextureBindingLoadedTexture.md)
|
||||||
|
- [GetTextureBindingTexture](GetTextureBindingTexture.md)
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Material::GetTextureBindingAssetRef
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
AssetRef GetTextureBindingAssetRef(Core::uint32 index) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
读取指定 binding 当前保存的稳定 `AssetRef`。
|
||||||
|
|
||||||
|
## 当前语义
|
||||||
|
|
||||||
|
- `index` 有效时,返回该 binding 的 `textureRef`
|
||||||
|
- 越界时返回默认构造的无效 `AssetRef`
|
||||||
|
|
||||||
|
这个访问器不会触发纹理加载,也不会解析 path。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [Material](Material.md)
|
||||||
|
- [SetTextureAssetRef](SetTextureAssetRef.md)
|
||||||
|
- [GetTextureBindingPath](GetTextureBindingPath.md)
|
||||||
@@ -1,30 +1,32 @@
|
|||||||
# Material::GetTextureBindingCount
|
# Material::GetTextureBindingCount
|
||||||
|
|
||||||
获取相关状态或对象。
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
Core::uint32 GetTextureBindingCount() const;
|
Core::uint32 GetTextureBindingCount() const;
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Resources/Material/Material.h`,当前页面用于固定 `Material` 类目录下的方法级 canonical 路径。
|
## 作用
|
||||||
|
|
||||||
**参数:** 无。
|
返回当前材质持有的 texture binding 元数据条目数。
|
||||||
|
|
||||||
**返回:** `Core::uint32` - 返回值语义详见头文件声明。
|
## 当前语义
|
||||||
|
|
||||||
**示例:**
|
这里统计的是 `m_textureBindings` 的数量,而不是 shader schema 中声明的 texture property 总数。
|
||||||
|
|
||||||
```cpp
|
因此它反映的是“当前真的有 binding 元数据”的槽位数,包括:
|
||||||
#include <XCEngine/Resources/Material/Material.h>
|
|
||||||
|
|
||||||
void Example() {
|
- 已加载纹理的 binding
|
||||||
XCEngine::Resources::Material object;
|
- 只有 `AssetRef` 的 binding
|
||||||
// 根据上下文补齐参数后调用 Material::GetTextureBindingCount(...)。
|
- 只有 path 的 binding
|
||||||
(void)object;
|
|
||||||
}
|
如果某个 texture property 被删除、被标量属性替换,或被空 `AssetRef + emptyPath` 清空,对应数量也会减少。
|
||||||
```
|
|
||||||
|
## 返回值
|
||||||
|
|
||||||
|
- 当前 texture binding 元数据条目数。
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](Material.md)
|
- [Material](Material.md)
|
||||||
- [返回模块目录](../Material.md)
|
- [GetTextureBindingAssetRef](GetTextureBindingAssetRef.md)
|
||||||
|
- [GetTextureBindingPath](GetTextureBindingPath.md)
|
||||||
|
- [GetTextureBindingLoadedTexture](GetTextureBindingLoadedTexture.md)
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Material::GetTextureBindingLoadedTexture
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
ResourceHandle<Texture> GetTextureBindingLoadedTexture(Core::uint32 index) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
只读取指定 binding 当前已经兑现完成的纹理句柄,不触发新的加载。
|
||||||
|
|
||||||
|
## 当前语义
|
||||||
|
|
||||||
|
- `index` 有效时,直接返回该 binding 的 `texture`
|
||||||
|
- 越界时返回空句柄
|
||||||
|
|
||||||
|
它和 [GetTextureBindingTexture](GetTextureBindingTexture.md) 的区别是:
|
||||||
|
|
||||||
|
- 这个方法只看当前已加载状态
|
||||||
|
- 不会去 resolve pending load
|
||||||
|
- 不会去启动新的异步加载
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [Material](Material.md)
|
||||||
|
- [GetTexture](GetTexture.md)
|
||||||
|
- [GetTextureBindingTexture](GetTextureBindingTexture.md)
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# Material::GetTextureBindingName
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Containers::String GetTextureBindingName(Core::uint32 index) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
读取指定 texture binding 当前保存的名字。
|
||||||
|
|
||||||
|
## 当前语义
|
||||||
|
|
||||||
|
- `index` 有效时,返回该 binding 的 `name`
|
||||||
|
- 越界时返回默认构造的空 `Containers::String`
|
||||||
|
|
||||||
|
这个访问器只读取 `m_textureBindings[index].name`,不会触发纹理加载,也不会解析 `AssetRef` 或 path。
|
||||||
|
|
||||||
|
## 测试覆盖
|
||||||
|
|
||||||
|
当前至少有两条直接调用链:
|
||||||
|
|
||||||
|
- `tests/Resources/Material/test_material.cpp`
|
||||||
|
在 `SetTextureAssetRefStoresStableBindingMetadata` 里验证写入后名字保持为 `"uDiffuse"`
|
||||||
|
- `tests/Resources/Material/test_material_loader.cpp`
|
||||||
|
在材质 artifact 回读后验证首个 binding 名字为 `"baseColorTexture"`
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [Material](Material.md)
|
||||||
|
- [GetTextureBindingCount](GetTextureBindingCount.md)
|
||||||
|
- [GetTextureBindingAssetRef](GetTextureBindingAssetRef.md)
|
||||||
|
- [GetTextureBindingPath](GetTextureBindingPath.md)
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# Material::GetTextureBindingPath
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Containers::String GetTextureBindingPath(Core::uint32 index) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
读取指定 binding 当前保存的 path 元数据。
|
||||||
|
|
||||||
|
## 当前语义
|
||||||
|
|
||||||
|
- `index` 有效时,返回该 binding 的 `texturePath`
|
||||||
|
- 越界时返回空字符串
|
||||||
|
|
||||||
|
注意它返回的是当前 `Material` 持有的 path 字段:
|
||||||
|
|
||||||
|
- 可能是 source 材质解析出的路径
|
||||||
|
- 也可能是 `.xcmat` 回读或后续懒解析 `AssetRef` 后补回的路径
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [Material](Material.md)
|
||||||
|
- [SetTexturePath](SetTexturePath.md)
|
||||||
|
- [GetTextureBindingAssetRef](GetTextureBindingAssetRef.md)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Material::GetTextureBindingTexture
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
ResourceHandle<Texture> GetTextureBindingTexture(Core::uint32 index) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
按 binding index 读取纹理句柄,并在需要时启动一次懒加载。
|
||||||
|
|
||||||
|
## 当前行为
|
||||||
|
|
||||||
|
1. 先对该 index 执行 `ResolvePendingTextureBinding(index)`。
|
||||||
|
2. 若 binding 仍未持有 loaded texture,且:
|
||||||
|
- `pendingLoad == nullptr`
|
||||||
|
- `texturePath` 非空,或 `textureRef` 有效
|
||||||
|
则调用 `BeginAsyncTextureLoad(index)`。
|
||||||
|
3. 返回当前 `binding.texture`。
|
||||||
|
|
||||||
|
## 关键语义
|
||||||
|
|
||||||
|
- 这是 [GetTexture](GetTexture.md) 的 index 版入口。
|
||||||
|
- 第一次调用时可能只会把加载任务排进 `ResourceManager`,并返回空句柄。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [Material](Material.md)
|
||||||
|
- [GetTexture](GetTexture.md)
|
||||||
|
- [GetTextureBindingLoadedTexture](GetTextureBindingLoadedTexture.md)
|
||||||
@@ -6,56 +6,140 @@
|
|||||||
|
|
||||||
**头文件**: `XCEngine/Resources/Material/Material.h`
|
**头文件**: `XCEngine/Resources/Material/Material.h`
|
||||||
|
|
||||||
**描述**: 定义 `XCEngine/Resources/Material` 子目录中的 `Material` public API。
|
**描述**: 运行时材质资源,统一承载 shader schema、render metadata、数值属性、texture binding 元数据以及延迟纹理兑现逻辑。
|
||||||
|
|
||||||
## 概述
|
## 概览
|
||||||
|
|
||||||
`Material.h` 是 `XCEngine/Resources/Material` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。
|
`Material` 当前同时维护五类状态:
|
||||||
|
|
||||||
## 声明概览
|
1. 资源身份
|
||||||
|
`name`、`path`、`guid`、`isValid`、`memorySize`
|
||||||
|
2. 渲染元数据
|
||||||
|
`shader`、`renderQueue`、`renderState`、`shaderPass`、`tags`
|
||||||
|
3. 数值属性
|
||||||
|
`Float` / `Float2` / `Float3` / `Float4` / `Int` / `Bool`
|
||||||
|
4. texture binding 元数据
|
||||||
|
`name`、`slot`、已加载 `Texture` 句柄、稳定 `AssetRef`、path、pending async load 状态
|
||||||
|
5. packed constant buffer
|
||||||
|
`m_constantBufferData`
|
||||||
|
|
||||||
| 声明 | 类型 | 说明 |
|
## shader schema 与默认值
|
||||||
|------|------|------|
|
|
||||||
| `MaterialPropertyType` | `enum class` | 头文件中的公开声明。 |
|
|
||||||
| `MaterialProperty` | `struct` | 头文件中的公开声明。 |
|
|
||||||
| `Material` | `class` | 继承自 `IResource` 的公开声明。 |
|
|
||||||
|
|
||||||
## 公共方法
|
当 `SetShader(...)` 绑定 shader 后,`Material` 会按 shader property schema 做一次同步:
|
||||||
|
|
||||||
| 方法 | 描述 |
|
- 为 schema 中缺失的属性补默认值
|
||||||
|
- 清理不再存在的旧属性
|
||||||
|
- 如果现有属性类型和新 schema 不兼容,则重置回 shader 默认值
|
||||||
|
- texture / cubemap 属性保留在 texture binding 通道,不写进 numeric property packing
|
||||||
|
|
||||||
|
`tests/Resources/Material/test_material.cpp` 当前明确覆盖了:
|
||||||
|
|
||||||
|
- `SetShader()` 会 seed shader 默认值
|
||||||
|
- `RemoveProperty()` 会把 schema 内属性恢复到 shader 默认值
|
||||||
|
- `ClearAllProperties()` 在有 shader schema 时会恢复整套默认值
|
||||||
|
- 切换 shader 时会清理旧 schema 属性并补齐新 schema 默认值
|
||||||
|
|
||||||
|
## texture binding 的当前模型
|
||||||
|
|
||||||
|
### 两层状态
|
||||||
|
|
||||||
|
每个 texture binding 现在同时有两层语义:
|
||||||
|
|
||||||
|
- 稳定元数据
|
||||||
|
`AssetRef` + path
|
||||||
|
- 已加载句柄
|
||||||
|
`ResourceHandle<Texture>`
|
||||||
|
|
||||||
|
### 三种写入入口
|
||||||
|
|
||||||
|
- [SetTexture](SetTexture.md)
|
||||||
|
直接写入已加载纹理,并尽量补齐 `AssetRef`
|
||||||
|
- [SetTextureAssetRef](SetTextureAssetRef.md)
|
||||||
|
直接写入稳定 `AssetRef` 与可选 path,同时清空 loaded handle
|
||||||
|
- [SetTexturePath](SetTexturePath.md)
|
||||||
|
只保留 path 元数据,同时清空 `AssetRef` 和 loaded handle
|
||||||
|
|
||||||
|
### 两种读取入口
|
||||||
|
|
||||||
|
- [GetTexture](GetTexture.md)
|
||||||
|
按名称读纹理,并在需要时启动异步加载
|
||||||
|
- [GetTextureBindingTexture](GetTextureBindingTexture.md)
|
||||||
|
按 binding index 做同样的懒加载入口
|
||||||
|
|
||||||
|
如果只想看“当前是否已经加载完成”,而不想触发新的加载,应改用:
|
||||||
|
|
||||||
|
- [GetTextureBindingLoadedTexture](GetTextureBindingLoadedTexture.md)
|
||||||
|
|
||||||
|
### `AssetRef` 与 path 的边界
|
||||||
|
|
||||||
|
- `AssetRef` 是更稳定的项目资产身份
|
||||||
|
- path 是可选的辅助定位信息
|
||||||
|
- `.xcmat` v2 当前会尽量把两者都保存进 artifact
|
||||||
|
- 如果只有 `AssetRef` 没有 path,首次访问纹理时会先通过 `ResourceManager::TryResolveAssetPath(...)` 反查 path,再启动异步加载
|
||||||
|
- source 材质解析出来的 binding path 可能是项目内绝对路径;而只带 `AssetRef` 的 `.xcmat` 绑定在首次兑现后,通常会补回 `Assets/...` 形式的主 source 路径
|
||||||
|
|
||||||
|
## 常量缓冲打包语义
|
||||||
|
|
||||||
|
[UpdateConstantBuffer](UpdateConstantBuffer.md) 当前只打包数值属性:
|
||||||
|
|
||||||
|
- `Float*`
|
||||||
|
- `Int*`
|
||||||
|
- `Bool`
|
||||||
|
|
||||||
|
texture / cubemap 属性不会写进 `m_constantBufferData`。
|
||||||
|
|
||||||
|
当前打包顺序分两种路径:
|
||||||
|
|
||||||
|
- 如果当前绑定了 shader 且 shader property 列表非空:
|
||||||
|
- 只按 shader schema 中声明顺序收集兼容的数值属性
|
||||||
|
- 如果当前没有 shader schema:
|
||||||
|
- 按属性名字典序排序
|
||||||
|
|
||||||
|
两种路径下都遵守:
|
||||||
|
|
||||||
|
- 每个属性固定占 `16` 字节槽位
|
||||||
|
- `Bool` 写成 `uint32 0/1`
|
||||||
|
|
||||||
|
## 当前实现边界
|
||||||
|
|
||||||
|
- `GetTexture(...)` / `GetTextureBindingTexture(...)` 只会启动异步加载,不会自己 pump `ResourceManager` 完成队列
|
||||||
|
- `SetTexture(...)` 只有在纹理路径非空且不是虚拟路径时,才会尝试反查 `AssetRef`
|
||||||
|
- `GetTextureBindingLoadedTexture(...)` 只返回当前已兑现的句柄,不会触发新的加载
|
||||||
|
- constant buffer 在“有 shader schema”和“无 shader schema”两种情况下采用不同排序规则;不要把无 shader 时的字典序行为误解成通用规则
|
||||||
|
|
||||||
|
## 关键声明
|
||||||
|
|
||||||
|
| 声明 | 角色 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| [Material()](Constructor.md) | 构造对象。 |
|
| `MaterialRenderQueue` | 内建 render queue 常量 |
|
||||||
| [~Material()](Destructor.md) | 销毁对象并释放相关资源。 |
|
| `MaterialRenderState` | blend / depth / cull 等 runtime render state |
|
||||||
| [GetType](GetType.md) | 获取相关状态或对象。 |
|
| `MaterialPropertyType` | 数值属性与 texture/cubemap 属性的区分枚举 |
|
||||||
| [GetName](GetName.md) | 获取相关状态或对象。 |
|
| `MaterialProperty` | 单个属性的名称、类型和值 |
|
||||||
| [GetPath](GetPath.md) | 获取相关状态或对象。 |
|
| `MaterialTextureBinding` | 单个 texture binding 的 loaded handle、`AssetRef`、path 与 pending load 状态 |
|
||||||
| [GetGUID](GetGUID.md) | 获取相关状态或对象。 |
|
|
||||||
| [IsValid](IsValid.md) | 查询当前状态。 |
|
## 重点方法
|
||||||
| [GetMemorySize](GetMemorySize.md) | 获取相关状态或对象。 |
|
|
||||||
| [Release](Release.md) | 释放引用或底层资源。 |
|
| 方法 | 说明 |
|
||||||
| [SetShader](SetShader.md) | 设置相关状态或配置。 |
|
|------|------|
|
||||||
| [SetFloat](SetFloat.md) | 设置相关状态或配置。 |
|
| [SetShader](SetShader.md) | 绑定 shader,并按 shader schema 同步属性集。 |
|
||||||
| [SetFloat2](SetFloat2.md) | 设置相关状态或配置。 |
|
| [SetTexture](SetTexture.md) | 直接写入已加载纹理,并尽量补 `AssetRef` 元数据。 |
|
||||||
| [SetFloat3](SetFloat3.md) | 设置相关状态或配置。 |
|
| [SetTextureAssetRef](SetTextureAssetRef.md) | 只写 texture 资产身份与可选 path。 |
|
||||||
| [SetFloat4](SetFloat4.md) | 设置相关状态或配置。 |
|
| [SetTexturePath](SetTexturePath.md) | 只写 path 元数据。 |
|
||||||
| [SetInt](SetInt.md) | 设置相关状态或配置。 |
|
| [GetTexture](GetTexture.md) | 按名称读纹理,并在需要时启动懒加载。 |
|
||||||
| [SetBool](SetBool.md) | 设置相关状态或配置。 |
|
| [GetTextureBindingCount](GetTextureBindingCount.md) | 返回当前 texture binding 元数据数量。 |
|
||||||
| [SetTexture](SetTexture.md) | 设置相关状态或配置。 |
|
| [GetTextureBindingName](GetTextureBindingName.md) | 读取某个 binding 的名字。 |
|
||||||
| [GetFloat](GetFloat.md) | 获取相关状态或对象。 |
|
| [GetTextureBindingAssetRef](GetTextureBindingAssetRef.md) | 读取某个 binding 的稳定 `AssetRef`。 |
|
||||||
| [GetFloat2](GetFloat2.md) | 获取相关状态或对象。 |
|
| [GetTextureBindingPath](GetTextureBindingPath.md) | 读取某个 binding 当前保存的 path。 |
|
||||||
| [GetFloat3](GetFloat3.md) | 获取相关状态或对象。 |
|
| [GetTextureBindingLoadedTexture](GetTextureBindingLoadedTexture.md) | 只看已加载句柄,不触发新的加载。 |
|
||||||
| [GetFloat4](GetFloat4.md) | 获取相关状态或对象。 |
|
| [GetTextureBindingTexture](GetTextureBindingTexture.md) | 按 index 读取纹理,并在需要时启动懒加载。 |
|
||||||
| [GetInt](GetInt.md) | 获取相关状态或对象。 |
|
| [ClearAllProperties](ClearAllProperties.md) | 清空当前属性集,再按 shader schema 回填默认值。 |
|
||||||
| [GetBool](GetBool.md) | 获取相关状态或对象。 |
|
| [UpdateConstantBuffer](UpdateConstantBuffer.md) | 重新打包数值属性常量缓冲。 |
|
||||||
| [GetTexture](GetTexture.md) | 获取相关状态或对象。 |
|
|
||||||
| [GetTextureBindingCount](GetTextureBindingCount.md) | 获取相关状态或对象。 |
|
|
||||||
| [GetConstantBufferData](GetConstantBufferData.md) | 获取相关状态或对象。 |
|
|
||||||
| [UpdateConstantBuffer](UpdateConstantBuffer.md) | 更新运行时状态。 |
|
|
||||||
| [HasProperty](HasProperty.md) | 判断是否具备指定状态或能力。 |
|
|
||||||
| [RemoveProperty](RemoveProperty.md) | 移除元素或解除关联。 |
|
|
||||||
| [ClearAllProperties](ClearAllProperties.md) | 清空内部数据。 |
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [当前目录](../Material.md) - 返回 `Material` 平行目录
|
- [当前目录](../Material.md)
|
||||||
- [API 总索引](../../../../main.md) - 返回顶层索引
|
- [MaterialLoader](../MaterialLoader/MaterialLoader.md)
|
||||||
|
- [ArtifactFormats](../../../Core/Asset/ArtifactFormats/ArtifactFormats.md)
|
||||||
|
- [AssetRef](../../../Core/Asset/AssetRef/AssetRef.md)
|
||||||
|
- [ResourceManager](../../../Core/Asset/ResourceManager/ResourceManager.md)
|
||||||
|
- [API 总索引](../../../../main.md)
|
||||||
|
|||||||
@@ -1,31 +1,43 @@
|
|||||||
# Material::SetShader
|
# Material::SetShader
|
||||||
|
|
||||||
设置相关状态或配置。
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void SetShader(const ResourceHandle<class Shader>& shader);
|
void SetShader(const ResourceHandle<class Shader>& shader);
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Resources/Material/Material.h`,当前页面用于固定 `Material` 类目录下的方法级 canonical 路径。
|
## 作用
|
||||||
|
|
||||||
**参数:**
|
为材质绑定 shader,并让当前属性集与新的 shader property schema 重新对齐。
|
||||||
- `shader` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
## 当前行为
|
||||||
|
|
||||||
**示例:**
|
1. 把 `m_shader` 设为传入句柄
|
||||||
|
2. 调用 `SyncShaderSchemaProperties(true)`
|
||||||
|
3. 调用 `MarkChanged(true)`
|
||||||
|
|
||||||
```cpp
|
`SyncShaderSchemaProperties(true)` 的当前行为包括:
|
||||||
#include <XCEngine/Resources/Material/Material.h>
|
|
||||||
|
|
||||||
void Example() {
|
- 删除新 shader schema 里不存在的旧属性
|
||||||
XCEngine::Resources::Material object;
|
- 对缺失的 schema 属性补默认值
|
||||||
// 根据上下文补齐参数后调用 Material::SetShader(...)。
|
- 对类型与 schema 不兼容的属性重置为 shader 默认值
|
||||||
(void)object;
|
- 对数值属性移除残留的 texture binding
|
||||||
}
|
|
||||||
```
|
## 关键语义
|
||||||
|
|
||||||
|
- 这不是单纯的指针替换;它会主动重塑材质当前的属性布局
|
||||||
|
- 切换 shader 后,旧 schema 的遗留属性不会被继续保留
|
||||||
|
- 如果某个属性名在新旧 shader 中都存在且类型兼容,当前值会尽量被保留
|
||||||
|
- 因为最终走 `MarkChanged(true)`,所以它会触发常量缓冲重打包,并递增 `changeVersion`
|
||||||
|
|
||||||
|
## 测试覆盖
|
||||||
|
|
||||||
|
`tests/Resources/Material/test_material.cpp` 当前验证了:
|
||||||
|
|
||||||
|
- 首次绑定 shader 会补齐 shader 默认属性
|
||||||
|
- `RemoveProperty()` 在有 shader schema 时会恢复默认值
|
||||||
|
- 切换到新 shader 时,旧 schema 属性会被剔除,新 schema 属性会被补齐
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](Material.md)
|
- [Material](Material.md)
|
||||||
- [返回模块目录](../Material.md)
|
- [ClearAllProperties](ClearAllProperties.md)
|
||||||
|
- [UpdateConstantBuffer](UpdateConstantBuffer.md)
|
||||||
|
|||||||
@@ -1,32 +1,42 @@
|
|||||||
# Material::SetTexture
|
# Material::SetTexture
|
||||||
|
|
||||||
设置相关状态或配置。
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void SetTexture(const Containers::String& name, const ResourceHandle<Texture>& texture);
|
void SetTexture(const Containers::String& name, const ResourceHandle<Texture>& texture);
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Resources/Material/Material.h`,当前页面用于固定 `Material` 类目录下的方法级 canonical 路径。
|
## 作用
|
||||||
|
|
||||||
**参数:**
|
直接把一个已加载 `Texture` 句柄挂到指定 texture property 上,并同步更新 binding 的稳定元数据。
|
||||||
- `name` - 参数语义详见头文件声明。
|
|
||||||
- `texture` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
## 当前行为
|
||||||
|
|
||||||
**示例:**
|
1. 先根据当前 shader schema 判断 `name` 是否允许写成 `Texture` / `Cubemap` 属性。
|
||||||
|
2. 确保 `m_properties` 中存在对应的 texture property。
|
||||||
|
3. 如果传入纹理带有非空、非虚拟路径,会尝试通过 `ResourceManager::TryGetAssetRef(...)` 反查稳定 `AssetRef`。
|
||||||
|
4. 若同名 binding 已存在,则原地替换 `texture`、`textureRef`、`texturePath` 和 `pendingLoad`。
|
||||||
|
5. 若不存在,则在 `m_textureBindings` 末尾追加一个新的 binding。
|
||||||
|
|
||||||
```cpp
|
## 关键语义
|
||||||
#include <XCEngine/Resources/Material/Material.h>
|
|
||||||
|
|
||||||
void Example() {
|
- 这是“直接注入已加载纹理”的入口。
|
||||||
XCEngine::Resources::Material object;
|
- 如果纹理路径能映射到项目资产,当前实现会尽量补齐 `AssetRef`,这样后续写 `.xcmat` 时能保留更稳定的引用。
|
||||||
// 根据上下文补齐参数后调用 Material::SetTexture(...)。
|
- 如果后续对同名属性写入标量值,旧 texture binding 会被移除。
|
||||||
(void)object;
|
|
||||||
}
|
## 参数
|
||||||
```
|
|
||||||
|
- `name` - 目标 texture property 名称。
|
||||||
|
- `texture` - 已加载纹理句柄。
|
||||||
|
|
||||||
|
## 测试覆盖
|
||||||
|
|
||||||
|
`tests/Resources/Material/test_material.cpp` 当前覆盖了:
|
||||||
|
|
||||||
|
- 设置后可通过 [GetTexture](GetTexture.md) 取回同一纹理
|
||||||
|
- 同名 `SetTexture(...)` 会替换旧 binding
|
||||||
|
- 同名标量属性写入会移除旧 texture binding
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](Material.md)
|
- [Material](Material.md)
|
||||||
- [返回模块目录](../Material.md)
|
- [SetTextureAssetRef](SetTextureAssetRef.md)
|
||||||
|
- [GetTexture](GetTexture.md)
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# Material::SetTextureAssetRef
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void SetTextureAssetRef(
|
||||||
|
const Containers::String& name,
|
||||||
|
const AssetRef& textureRef,
|
||||||
|
const Containers::String& texturePath = Containers::String());
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
为指定 texture property 写入稳定 `AssetRef` 与可选 path,而不立即持有 loaded texture 句柄。
|
||||||
|
|
||||||
|
## 当前行为
|
||||||
|
|
||||||
|
- 如果 `textureRef` 无效且 `texturePath` 为空,直接退化成删除该属性。
|
||||||
|
- 否则会确保该属性在 `m_properties` 中以 texture / cubemap 形式存在。
|
||||||
|
- 如果同名 binding 已存在,会:
|
||||||
|
- 清空 `texture`
|
||||||
|
- 写入新的 `textureRef`
|
||||||
|
- 写入新的 `texturePath`
|
||||||
|
- 清空 `pendingLoad`
|
||||||
|
- 如果 binding 不存在,则创建新的 binding。
|
||||||
|
|
||||||
|
## 关键语义
|
||||||
|
|
||||||
|
- 这是当前 `.xcmat` v2 回读最重要的 texture binding 写入口。
|
||||||
|
- 它保存的是“稳定身份 + 可选定位信息”,不是即时可用的纹理句柄。
|
||||||
|
- 后续第一次访问纹理时,`Material` 才会再根据 `AssetRef` / path 启动异步加载。
|
||||||
|
|
||||||
|
## 测试覆盖
|
||||||
|
|
||||||
|
`tests/Resources/Material/test_material.cpp` 当前验证了:
|
||||||
|
|
||||||
|
- `AssetRef`、path 和 binding 名称都会被稳定保存
|
||||||
|
- 初始时 [GetTextureBindingLoadedTexture](GetTextureBindingLoadedTexture.md) 仍为空句柄
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [Material](Material.md)
|
||||||
|
- [SetTexturePath](SetTexturePath.md)
|
||||||
|
- [GetTextureBindingAssetRef](GetTextureBindingAssetRef.md)
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Material::SetTexturePath
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void SetTexturePath(const Containers::String& name, const Containers::String& texturePath);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 作用
|
||||||
|
|
||||||
|
只为指定 texture property 保存 path 元数据,不保留稳定 `AssetRef` 或 loaded texture 句柄。
|
||||||
|
|
||||||
|
## 当前行为
|
||||||
|
|
||||||
|
- 若 `texturePath` 为空,则退化成删除该属性。
|
||||||
|
- 否则会确保该属性以 texture / cubemap 形式存在。
|
||||||
|
- 同名 binding 已存在时,会:
|
||||||
|
- 清空 `texture`
|
||||||
|
- `textureRef.Reset()`
|
||||||
|
- 写入新的 `texturePath`
|
||||||
|
- 清空 `pendingLoad`
|
||||||
|
- 若不存在,则创建新的 binding。
|
||||||
|
|
||||||
|
## 关键语义
|
||||||
|
|
||||||
|
- 这是没有稳定 `AssetRef` 时的退化路径。
|
||||||
|
- 后续首次访问纹理时,仍可按 path 启动异步加载。
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [Material](Material.md)
|
||||||
|
- [SetTextureAssetRef](SetTextureAssetRef.md)
|
||||||
|
- [GetTextureBindingPath](GetTextureBindingPath.md)
|
||||||
@@ -1,30 +1,59 @@
|
|||||||
# Material::UpdateConstantBuffer
|
# Material::UpdateConstantBuffer
|
||||||
|
|
||||||
更新运行时状态。
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void UpdateConstantBuffer();
|
void UpdateConstantBuffer();
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Resources/Material/Material.h`,当前页面用于固定 `Material` 类目录下的方法级 canonical 路径。
|
## 作用
|
||||||
|
|
||||||
**参数:** 无。
|
重新根据当前数值属性生成 `m_constantBufferData`。
|
||||||
|
|
||||||
**返回:** `void` - 无返回值。
|
## 当前打包规则
|
||||||
|
|
||||||
**示例:**
|
当前实现会先收集“可打包”的数值属性:
|
||||||
|
|
||||||
```cpp
|
- `Float`
|
||||||
#include <XCEngine/Resources/Material/Material.h>
|
- `Float2`
|
||||||
|
- `Float3`
|
||||||
|
- `Float4`
|
||||||
|
- `Int`
|
||||||
|
- `Int2`
|
||||||
|
- `Int3`
|
||||||
|
- `Int4`
|
||||||
|
- `Bool`
|
||||||
|
|
||||||
void Example() {
|
随后分两条路径打包:
|
||||||
XCEngine::Resources::Material object;
|
|
||||||
// 根据上下文补齐参数后调用 Material::UpdateConstantBuffer(...)。
|
1. 如果当前绑定了 shader,且 shader property 列表非空
|
||||||
(void)object;
|
- 按 shader property 声明顺序遍历
|
||||||
}
|
- 只收集在 `m_properties` 中存在、类型可打包、并且与 shader property 兼容的属性
|
||||||
```
|
2. 如果当前没有 shader schema
|
||||||
|
- 从 `m_properties` 里收集所有可打包属性
|
||||||
|
- 再按属性名字典序排序
|
||||||
|
|
||||||
|
最后会:
|
||||||
|
|
||||||
|
3. 为每个属性分配固定 `16` 字节槽位
|
||||||
|
4. 依类型把值写进槽位前部,其余字节补零
|
||||||
|
|
||||||
|
texture / cubemap 属性不会写入这个常量缓冲镜像。
|
||||||
|
|
||||||
|
## 关键语义
|
||||||
|
|
||||||
|
- 常量缓冲布局不取决于属性写入顺序
|
||||||
|
- 但它也不总是按名字典序决定: 有 shader schema 时,以 shader schema 顺序为准
|
||||||
|
- `Bool` 会被写成 `uint32 0/1`
|
||||||
|
- 方法结束时还会更新 `memorySize`
|
||||||
|
|
||||||
|
## 测试覆盖
|
||||||
|
|
||||||
|
`tests/Resources/Material/test_material.cpp` 当前验证了:
|
||||||
|
|
||||||
|
- 在无 shader schema 时,`alpha` / `beta` / `gamma` 会按名字典序落位
|
||||||
|
- 每个属性固定占一个 `16` 字节槽位
|
||||||
|
- 在有 shader schema 时,buffer 顺序跟随 schema 声明顺序,而不是名字典序
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](Material.md)
|
- [Material](Material.md)
|
||||||
- [返回模块目录](../Material.md)
|
- [GetConstantBufferData](GetConstantBufferData.md)
|
||||||
|
|||||||
@@ -1,31 +1,39 @@
|
|||||||
# MaterialLoader::CanLoad
|
# MaterialLoader::CanLoad
|
||||||
|
|
||||||
判断当前条件下是否可执行。
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
bool CanLoad(const Containers::String& path) const override;
|
bool CanLoad(const Containers::String& path) const override;
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Resources/Material/MaterialLoader.h`,当前页面用于固定 `MaterialLoader` 类目录下的方法级 canonical 路径。
|
## 作用
|
||||||
|
|
||||||
**参数:**
|
判断给定路径是否应交给当前材质加载器处理。
|
||||||
- `path` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `bool` - 返回值语义详见头文件声明。
|
## 当前规则
|
||||||
|
|
||||||
**示例:**
|
- `builtin://...` 材质路径直接返回 `true`
|
||||||
|
- 扩展名为以下任一值时返回 `true`
|
||||||
|
- `.mat`
|
||||||
|
- `.material`
|
||||||
|
- `.json`
|
||||||
|
- `.xcmat`
|
||||||
|
- 其他扩展名返回 `false`
|
||||||
|
|
||||||
```cpp
|
## 关键语义
|
||||||
#include <XCEngine/Resources/Material/MaterialLoader.h>
|
|
||||||
|
|
||||||
void Example() {
|
- `.xcmat` 当前代表材质 artifact,而不是普通 source 文件。
|
||||||
XCEngine::Resources::MaterialLoader object;
|
- `CanLoad()` 只按路径协议和扩展名判断,不提前校验文件内容是否真能成功解析。
|
||||||
// 根据上下文补齐参数后调用 MaterialLoader::CanLoad(...)。
|
|
||||||
(void)object;
|
## 测试覆盖
|
||||||
}
|
|
||||||
```
|
`tests/Resources/Material/test_material_loader.cpp` 当前验证了:
|
||||||
|
|
||||||
|
- `test.mat`
|
||||||
|
- `test.json`
|
||||||
|
- `test.xcmat`
|
||||||
|
|
||||||
|
都能被接受,而 `.txt` / `.png` 会被拒绝。
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](MaterialLoader.md)
|
- [MaterialLoader](MaterialLoader.md)
|
||||||
- [返回模块目录](../Material.md)
|
- [Load](Load.md)
|
||||||
|
|||||||
@@ -1,32 +1,87 @@
|
|||||||
# MaterialLoader::Load
|
# MaterialLoader::Load
|
||||||
|
|
||||||
加载资源或数据。
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
LoadResult Load(const Containers::String& path, const ImportSettings* settings = nullptr) override;
|
LoadResult Load(const Containers::String& path, const ImportSettings* settings = nullptr) override;
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法声明于 `XCEngine/Resources/Material/MaterialLoader.h`,当前页面用于固定 `MaterialLoader` 类目录下的方法级 canonical 路径。
|
## 作用
|
||||||
|
|
||||||
**参数:**
|
把 builtin 材质路径、source 材质文件或 `.xcmat` artifact 加载成 [Material](../Material/Material.md)。
|
||||||
- `path` - 参数语义详见头文件声明。
|
|
||||||
- `settings` - 参数语义详见头文件声明。
|
|
||||||
|
|
||||||
**返回:** `LoadResult` - 返回值语义详见头文件声明。
|
## 当前分派逻辑
|
||||||
|
|
||||||
**示例:**
|
1. 如果 `path` 是 builtin 材质路径,直接转到内建材质资源工厂。
|
||||||
|
2. 否则按扩展名分支:
|
||||||
|
- `.xcmat` -> 走 artifact 回读
|
||||||
|
- 其他支持扩展 -> 读 source 文件并做轻量解析
|
||||||
|
3. 成功后补 `m_path`、`m_name`、`m_guid`、`m_isValid`,再返回 `LoadResult(material)`。
|
||||||
|
|
||||||
```cpp
|
## source 材质分支
|
||||||
#include <XCEngine/Resources/Material/MaterialLoader.h>
|
|
||||||
|
|
||||||
void Example() {
|
对 `.mat` / `.material` / `.json`,当前会解析:
|
||||||
XCEngine::Resources::MaterialLoader object;
|
|
||||||
// 根据上下文补齐参数后调用 MaterialLoader::Load(...)。
|
- `shader`
|
||||||
(void)object;
|
- `shaderPass` 或 `pass`
|
||||||
}
|
- `renderQueue`
|
||||||
```
|
支持整数或名字
|
||||||
|
- `tags`
|
||||||
|
- `renderState`
|
||||||
|
- texture 路径
|
||||||
|
|
||||||
|
遇到这些情况会失败:
|
||||||
|
|
||||||
|
- 文件不存在
|
||||||
|
- `renderQueue` 名字非法
|
||||||
|
- `renderState` 枚举值非法
|
||||||
|
- 结构化对象提取失败
|
||||||
|
|
||||||
|
## `.xcmat` artifact 分支
|
||||||
|
|
||||||
|
当前 `.xcmat` 回读顺序是:
|
||||||
|
|
||||||
|
1. 读取 `MaterialArtifactFileHeader`
|
||||||
|
2. 校验 magic 必须是 `XCMAT02`
|
||||||
|
3. 读取材质名、source path、shader path、shader pass
|
||||||
|
4. 读取 `MaterialArtifactHeader`
|
||||||
|
5. 恢复 tags
|
||||||
|
6. 恢复非 texture 属性
|
||||||
|
7. 恢复每个 texture binding 的:
|
||||||
|
- binding name
|
||||||
|
- 编码 `AssetRef` 字符串
|
||||||
|
- 可选 texture path
|
||||||
|
|
||||||
|
texture binding 恢复时:
|
||||||
|
|
||||||
|
- 有效 `AssetRef` 优先走 `SetTextureAssetRef(...)`
|
||||||
|
- 否则有 path 时走 `SetTexturePath(...)`
|
||||||
|
|
||||||
|
因此 artifact 加载完成后的材质,texture binding 通常先只有元数据,没有立即兑现的纹理句柄。
|
||||||
|
|
||||||
|
## 与延迟纹理加载的关系
|
||||||
|
|
||||||
|
`Load()` 本身不会等待纹理依赖同步完成。
|
||||||
|
|
||||||
|
后续真正访问:
|
||||||
|
|
||||||
|
- [Material::GetTexture](../Material/GetTexture.md)
|
||||||
|
- [Material::GetTextureBindingTexture](../Material/GetTextureBindingTexture.md)
|
||||||
|
|
||||||
|
时,`Material` 才会根据 path / `AssetRef` 启动异步纹理加载。
|
||||||
|
|
||||||
|
## 测试覆盖
|
||||||
|
|
||||||
|
`tests/Resources/Material/test_material_loader.cpp` 当前覆盖了:
|
||||||
|
|
||||||
|
- source 材质的 render metadata 解析
|
||||||
|
- shader manifest + `shaderPass` 解析
|
||||||
|
- 非法 `renderQueue` / render state 拒绝
|
||||||
|
- `resourceRoot` 下相对材质加载
|
||||||
|
- `AssetDatabase` 产出的 `main.xcmat` 能成功回读
|
||||||
|
- `.xcmat` 中仅保存 texture `AssetRef` 时,首次访问才触发异步纹理加载
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [返回类总览](MaterialLoader.md)
|
- [MaterialLoader](MaterialLoader.md)
|
||||||
- [返回模块目录](../Material.md)
|
- [CanLoad](CanLoad.md)
|
||||||
|
- [Material](../Material/Material.md)
|
||||||
|
- [ArtifactFormats](../../../Core/Asset/ArtifactFormats/ArtifactFormats.md)
|
||||||
|
|||||||
@@ -6,31 +6,56 @@
|
|||||||
|
|
||||||
**头文件**: `XCEngine/Resources/Material/MaterialLoader.h`
|
**头文件**: `XCEngine/Resources/Material/MaterialLoader.h`
|
||||||
|
|
||||||
**描述**: 定义 `XCEngine/Resources/Material` 子目录中的 `MaterialLoader` public API。
|
**描述**: 材质 source 文件与 `.xcmat` artifact 的统一加载器。
|
||||||
|
|
||||||
## 概述
|
## 概览
|
||||||
|
|
||||||
`MaterialLoader.h` 是 `XCEngine/Resources/Material` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。
|
`MaterialLoader` 当前要处理三类输入:
|
||||||
|
|
||||||
## 声明概览
|
1. `builtin://` 材质路径
|
||||||
|
2. source 材质文件
|
||||||
|
`.mat` / `.material` / `.json`
|
||||||
|
3. 材质 artifact
|
||||||
|
`.xcmat`
|
||||||
|
|
||||||
| 声明 | 类型 | 说明 |
|
其中 `.xcmat` 已经是当前材质 artifact v2:
|
||||||
|------|------|------|
|
|
||||||
| `MaterialLoader` | `class` | 继承自 `IResourceLoader` 的公开声明。 |
|
|
||||||
|
|
||||||
## 公共方法
|
- magic `XCMAT02`
|
||||||
|
- texture binding 保存的是“binding name + 编码 `AssetRef` + 可选 path”
|
||||||
|
- 回读后默认只恢复绑定元数据,不会立即同步加载全部纹理 payload
|
||||||
|
|
||||||
| 方法 | 描述 |
|
## source 材质解析能力
|
||||||
|
|
||||||
|
对 source 文件,loader 当前支持解析:
|
||||||
|
|
||||||
|
- `shader`
|
||||||
|
- `shaderPass` / `pass`
|
||||||
|
- `renderQueue`
|
||||||
|
支持整数或名字
|
||||||
|
- `tags`
|
||||||
|
- `renderState`
|
||||||
|
- texture 声明
|
||||||
|
包括 known key 和 `textures { ... }` 字典
|
||||||
|
|
||||||
|
相对 texture 路径会按材质文件目录或当前 `resourceRoot` 解析。
|
||||||
|
|
||||||
|
## 当前实现边界
|
||||||
|
|
||||||
|
- source 解析仍是轻量手写 JSON-like parser,不是完整 JSON AST。
|
||||||
|
- `.xcmat` 分支显式检查的是 magic,不是 `schemaVersion` 分支分发。
|
||||||
|
- 异步纹理兑现由 `Material` 在后续访问时触发,而不是在 `Load()` 内一次性完成。
|
||||||
|
|
||||||
|
## 重点方法
|
||||||
|
|
||||||
|
| 方法 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| [MaterialLoader()](Constructor.md) | 构造对象。 |
|
| [CanLoad](CanLoad.md) | 判断路径是否属于 builtin 材质、source 材质或 `.xcmat` artifact。 |
|
||||||
| [~MaterialLoader()](Destructor.md) | 销毁对象并释放相关资源。 |
|
| [Load](Load.md) | 按输入类型分派到 builtin 材质、source 解析或 `.xcmat` artifact 回读。 |
|
||||||
| [GetResourceType](GetResourceType.md) | 获取相关状态或对象。 |
|
|
||||||
| [GetSupportedExtensions](GetSupportedExtensions.md) | 获取相关状态或对象。 |
|
|
||||||
| [CanLoad](CanLoad.md) | 判断当前条件下是否可执行。 |
|
|
||||||
| [Load](Load.md) | 加载资源或数据。 |
|
|
||||||
| [GetDefaultSettings](GetDefaultSettings.md) | 获取相关状态或对象。 |
|
|
||||||
|
|
||||||
## 相关文档
|
## 相关文档
|
||||||
|
|
||||||
- [当前目录](../Material.md) - 返回 `Material` 平行目录
|
- [Material](../Material/Material.md)
|
||||||
- [API 总索引](../../../../main.md) - 返回顶层索引
|
- [ArtifactFormats](../../../Core/Asset/ArtifactFormats/ArtifactFormats.md)
|
||||||
|
- [AssetDatabase](../../../Core/Asset/AssetDatabase/AssetDatabase.md)
|
||||||
|
- [当前目录](../Material.md)
|
||||||
|
- [API 总索引](../../../../main.md)
|
||||||
|
|||||||
Reference in New Issue
Block a user