This commit is contained in:
2026-01-26 22:55:14 +09:00
parent 8d82c0a750
commit b505c7c1c0
8 changed files with 97 additions and 9 deletions

View File

@@ -7,23 +7,26 @@ This document outlines the plan for implementing the AssetDB, including its stru
- Asset Metadata: Each asset will have associated metadata, including:
- Unique Identifier (GUID)
- Version
- Version (Version of the asset pipeline, not the asset. This is primarily for migration when we redesign the asset pipeline in the future)
- Tags
- Importer Settings
An example of metadata file (filename.png.gmeta):
An simplified example of metadata file (filename.png.gmeta):
```json
{
"Guid": "123e4567-e89b-12d3-a456-426614174000",
"Version": 1,
"ImporterSettings": {
"Tags": ["Environment", "Texture"],
"ImporterSettings": [
"TextureImporter": {
"Version": 1,
"MaxSize": 2048,
"MipLevels": 1
},
"OtherImporter": {
}
}
]
}
```
@@ -38,7 +41,19 @@ An example of metadata file (filename.png.gmeta):
- Automatic asset re-importing when source files change.
- Asset tagging.
- Add type specific default importer settings for new asset.
- SQLite for persistent storage and efficient querying. (Don't use JSON or XML for the database itself, only for metadata files. Also don't use heavy)
- SQLite (`Microsoft.Data.Sqlite`) for persistent storage and efficient querying.
An simplified data model example in SQLite:
```sql
CREATE TABLE Assets (
Guid TEXT PRIMARY KEY,
Path TEXT NOT NULL,
Type INTEGER,
Version INTEGER,
Tags TEXT,
DependencyGuids TEXT
);
```
## Simplified Workflow
@@ -52,6 +67,8 @@ An example of metadata file (filename.png.gmeta):
1. A file is removed from the project directory.
2. Deletes the corresponding asset metadata.
3. Remove the asset from the database.
4. Mark dependent assets as dirty for re-importing.
### File Renaming/Moving
@@ -61,6 +78,19 @@ An example of metadata file (filename.png.gmeta):
- if not, regenerate the metadata file for the new path and update the database.
3. Delete the old metadata file if exists.
### File Modification
1. A file is modified in the project directory.
2. Check the file hash to see if it has changed.
- If changed, mark the asset as dirty for re-importing.
- If not, do nothing.
### Asset Importing (You don't need to write any assets importer right now, just write the framework and a simple test importer if it's needed for unit test)
1. An asset is marked as dirty.
2. The asset importer for that type processes the asset based on its importer settings.
3. Validate the references and dependencies, report errors if any (for example, missing dependencies).
## Features Checklist
### In Code (API)
@@ -86,3 +116,19 @@ An example of metadata file (filename.png.gmeta):
- [ ] Automatic asset re-importing when source files change (detect changes via file system watcher and quick hash comparison).
- [ ] Asset dependency management.
- [ ] Validate and fix AssetDB on project load (check for missing/corrupted assets if user add/delete/rename/move files when the editor is not running, etc.)
- [ ] Asset importer system to handle different asset types and their import settings.
## Testing
Make sure everything builds correctly at first.
Write unit tests and integration tests to ensure the AssetDB functions correctly inside the `Ghost.UnitTests` project.
## Critical Considerations
- Performance: Ensure that the AssetDB operations are efficient, especially for large projects with many assets.
- Stability: The meta data files should be the only source of truth for asset information.
The AssetDB should be able to recover from inconsistencies by re-generating data from the meta files.
We still need to trust the meta data files even if they are corrupted or missing by regenerating them when necessary.
Database is used for caching and quick lookup only.
- Asynchronous patterns: Consider using asynchronous operations for file I/O and database operations to avoid blocking the main thread.
Packages like `Microsoft.Data.Sqlite` support async operations.

View File

@@ -7,7 +7,7 @@ namespace Ghost.Editor.Core.AssetHandle;
public static partial class AssetDatabase
{
private static readonly Dictionary<string, Action<string>> _assetOpenHandlers = new(StringComparer.OrdinalIgnoreCase);
private static readonly Dictionary<string, Action<string>> s_assetOpenHandlers = new(StringComparer.OrdinalIgnoreCase);
private static void InitializeAssetHandle()
{
@@ -23,12 +23,12 @@ public static partial class AssetDatabase
var del = (Action<string>)Delegate.CreateDelegate(typeof(Action<string>), method);
foreach (var ext in attr.Extensions)
{
if (_assetOpenHandlers.ContainsKey(ext))
if (s_assetOpenHandlers.ContainsKey(ext))
{
Logger.LogError($"Duplicate asset open handler for extension '{ext}' found in method '{method.Name}'. Existing handler will be overwritten.");
}
_assetOpenHandlers[ext] = del;
s_assetOpenHandlers[ext] = del;
}
}
}
@@ -36,7 +36,7 @@ public static partial class AssetDatabase
public static void OpenAsset(string path)
{
var extension = Path.GetExtension(path);
if (_assetOpenHandlers.TryGetValue(extension, out var handler))
if (s_assetOpenHandlers.TryGetValue(extension, out var handler))
{
handler(path);
}

View File

@@ -13,6 +13,7 @@
<langversion>preview</langversion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.2" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.7463" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.8.260101001" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />