diff --git a/src/GameCult.Caching/CultInspectorAttributes.cs b/src/GameCult.Caching/CultInspectorAttributes.cs index 881208ea..2ae523e0 100644 --- a/src/GameCult.Caching/CultInspectorAttributes.cs +++ b/src/GameCult.Caching/CultInspectorAttributes.cs @@ -64,12 +64,13 @@ namespace GameCult.Caching public float Max { get; } } - // A string member holding an engine asset path. AssetType is the engine's asset type, named by the consumer - // (typeof(UnityEngine.Texture2D) in a Unity assembly); a lowering that does not know the type ignores it. + // A string member holding an engine asset's stable identity; in Unity, the `.meta` GUID. AssetType is the + // engine's asset type, named by the consumer (typeof(UnityEngine.Texture2D) in a Unity assembly); a lowering + // that does not know the type ignores it. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, Inherited = true)] - public sealed class CultInspectorAssetPathAttribute : Attribute + public sealed class CultInspectorAssetGuidAttribute : Attribute { - public CultInspectorAssetPathAttribute(Type? assetType = null) + public CultInspectorAssetGuidAttribute(Type? assetType = null) { AssetType = assetType; } diff --git a/src/GameCult.Caching/CultInspectorModel.cs b/src/GameCult.Caching/CultInspectorModel.cs index 6a86f5ee..e5b5581f 100644 --- a/src/GameCult.Caching/CultInspectorModel.cs +++ b/src/GameCult.Caching/CultInspectorModel.cs @@ -41,7 +41,7 @@ namespace GameCult.Caching Order = Find()?.Order; Range = Find(); TextArea = Find(); - AssetPath = Find(); + AssetGuid = Find(); } public IReadOnlyList Attributes { get; } @@ -53,7 +53,7 @@ namespace GameCult.Caching public int? Order { get; } public CultInspectorRangeAttribute? Range { get; } public CultInspectorTextAreaAttribute? TextArea { get; } - public CultInspectorAssetPathAttribute? AssetPath { get; } + public CultInspectorAssetGuidAttribute? AssetGuid { get; } public T? Find() where T : Attribute => Attributes.OfType().FirstOrDefault(); } diff --git a/src/GameCult.Unity/Assets/Caching/Editor/CultCacheStudioDrawers.cs b/src/GameCult.Unity/Assets/Caching/Editor/CultCacheStudioDrawers.cs index 2b4a87cb..ab1b1e84 100644 --- a/src/GameCult.Unity/Assets/Caching/Editor/CultCacheStudioDrawers.cs +++ b/src/GameCult.Unity/Assets/Caching/Editor/CultCacheStudioDrawers.cs @@ -167,12 +167,13 @@ namespace GameCult.Unity.Caching.Editor private static string DrawString(string label, string value, CultInspectorMetadata metadata) { - if (metadata.AssetPath != null) + if (metadata.AssetGuid != null) { - var assetType = metadata.AssetPath.AssetType != null && typeof(Object).IsAssignableFrom(metadata.AssetPath.AssetType) ? metadata.AssetPath.AssetType : typeof(Object); - var asset = string.IsNullOrEmpty(value) ? null : AssetDatabase.LoadAssetAtPath(value, assetType); + var assetType = metadata.AssetGuid.AssetType != null && typeof(Object).IsAssignableFrom(metadata.AssetGuid.AssetType) ? metadata.AssetGuid.AssetType : typeof(Object); + var path = string.IsNullOrEmpty(value) ? string.Empty : AssetDatabase.GUIDToAssetPath(value); + var asset = string.IsNullOrEmpty(path) ? null : AssetDatabase.LoadAssetAtPath(path, assetType); var next = EditorGUILayout.ObjectField(label, asset, assetType, false); - return next == asset ? value : next == null ? string.Empty : AssetDatabase.GetAssetPath(next); + return next == asset ? value : next == null ? string.Empty : AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(next)); } var textArea = metadata.TextArea; diff --git a/src/GameCult.Unity/Assets/Caching/README.md b/src/GameCult.Unity/Assets/Caching/README.md index d96f674f..49348452 100644 --- a/src/GameCult.Unity/Assets/Caching/README.md +++ b/src/GameCult.Unity/Assets/Caching/README.md @@ -150,8 +150,8 @@ public sealed class ItemData public string Notes = string.Empty; [Key(3)] - [CultInspectorAssetPath] - public string IconPath = string.Empty; + [CultInspectorAssetGuid] + public string IconGuid = string.Empty; } ``` @@ -161,8 +161,9 @@ public sealed class ItemData - `CultInspectorOrder` - `CultInspectorTextArea` - `CultInspectorRange` -- `CultInspectorAssetPath` (optional engine asset `Type`, named by the - consumer; the Studio uses it when it is a `UnityEngine.Object` type) +- `CultInspectorAssetGuid` (a string member holding an engine asset's stable + identity, in Unity the `.meta` GUID; optional engine asset `Type`, named by + the consumer; the Studio uses it when it is a `UnityEngine.Object` type) - `CultInspectorDrawer` (on drawer classes) CultMesh collaboration should feed the same CultCache mutation surface rather diff --git a/tests/GameCult.Caching.Tests/CultInspectorModelTests.cs b/tests/GameCult.Caching.Tests/CultInspectorModelTests.cs index 7ce19824..5c2c171b 100644 --- a/tests/GameCult.Caching.Tests/CultInspectorModelTests.cs +++ b/tests/GameCult.Caching.Tests/CultInspectorModelTests.cs @@ -42,6 +42,15 @@ namespace GameCult.Caching.Tests Assert.That(hidden.ValueType, Is.EqualTo(typeof(string))); } + [Test] + public void AssetGuidMemberExposesItsAttributeAndDeclaredType() + { + var member = Model().MembersOf(typeof(InspectAsset)).Single(); + + Assert.That(member.Metadata.AssetGuid, Is.Not.Null); + Assert.That(member.Metadata.AssetGuid!.AssetType, Is.EqualTo(typeof(Uri))); + } + [Test] public void ClaimsResolveAttributeThenTypeThenBuiltIn() { @@ -321,6 +330,14 @@ namespace GameCult.Caching.Tests public string Name = string.Empty; } + [CultDocument("tests.inspect_asset", "tests.inspect_asset.v1")] + [MessagePackObject] + public sealed class InspectAsset + { + [Key(0)] [CultInspectorAssetGuid(typeof(Uri))] + public string Guid = string.Empty; + } + [CultDocument("tests.inspect_fixed", "tests.inspect_fixed.v1")] [MessagePackObject] public sealed class InspectFixed