diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/RemapEditorMaterial.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/RemapEditorMaterial.cs index f31edc23a..ba961a78b 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/RemapEditorMaterial.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/RemapEditorMaterial.cs @@ -102,7 +102,7 @@ namespace UniGLTF ); } - public void ExtractMaterials(ScriptedImporter importer, Func materialDir) + public static void ExtractMaterials(ScriptedImporter importer, Func materialDir) { if (string.IsNullOrEmpty(importer.assetPath)) { diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/TextureExtractor.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/TextureExtractor.cs index 262c1dea2..d59c81b3c 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/TextureExtractor.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/TextureExtractor.cs @@ -60,7 +60,7 @@ namespace UniGLTF } else { - throw new Exception($"{texture} is not converted."); + throw new Exception($"{key} is not converted."); } } @@ -95,7 +95,7 @@ namespace UniGLTF var externalObject = targetPath.LoadAsset(); #if VRM_DEVELOP // Debug.Log($"remap: {targetPath} => {externalObject}"); -#endif +#endif if (externalObject != null) { addRemap(key, externalObject); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index 644fed31d..814eac7b2 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -16,7 +16,8 @@ namespace UniGLTF public IMaterialDescriptorGenerator MaterialDescriptorGenerator { get; protected set; } public TextureFactory TextureFactory { get; } public MaterialFactory MaterialFactory { get; } - IReadOnlyDictionary _externalObjectMap; + public AnimationClipFactory AnimationClipFactory { get; } + public IReadOnlyDictionary ExternalObjectMap; public ImporterContext( GltfData data, @@ -27,16 +28,19 @@ namespace UniGLTF TextureDescriptorGenerator = new GltfTextureDescriptorGenerator(Data); MaterialDescriptorGenerator = new GltfMaterialDescriptorGenerator(); - _externalObjectMap = externalObjectMap ?? new Dictionary(); + ExternalObjectMap = externalObjectMap ?? new Dictionary(); textureDeserializer = textureDeserializer ?? new UnityTextureDeserializer(); - TextureFactory = new TextureFactory(textureDeserializer, _externalObjectMap + TextureFactory = new TextureFactory(textureDeserializer, ExternalObjectMap .Where(x => x.Value is Texture) .ToDictionary(x => x.Key, x => (Texture)x.Value), Data.MigrationFlags.IsRoughnessTextureValueSquared); - MaterialFactory = new MaterialFactory(_externalObjectMap + MaterialFactory = new MaterialFactory(ExternalObjectMap .Where(x => x.Value is Material) .ToDictionary(x => x.Key, x => (Material)x.Value)); + AnimationClipFactory = new AnimationClipFactory(ExternalObjectMap + .Where(x => x.Value is AnimationClip) + .ToDictionary(x => x.Key, x => (AnimationClip)x.Value)); } #region Source @@ -113,27 +117,16 @@ namespace UniGLTF return RuntimeGltfInstance.AttachTo(Root, this); } - /// - /// ImporterContext.AnimationClips に AnimationClip を読み込むところまでが責務 - /// - /// - /// - protected virtual async Task LoadAnimationAsync(IAwaitCaller awaitCaller) + public virtual async Task LoadAnimationAsync(IAwaitCaller awaitCaller) { if (GLTF.animations != null && GLTF.animations.Any()) { foreach (var (key, gltfAnimation) in Enumerable.Zip(AnimationImporterUtil.EnumerateSubAssetKeys(GLTF), GLTF.animations, (x, y) => (x, y))) { - AnimationInfo animation = default; - if (_externalObjectMap.TryGetValue(key, out UnityEngine.Object value)) + await AnimationClipFactory.LoadAnimationClipAsync(key, async () => { - animation = new AnimationInfo(key, value as AnimationClip, true); - } - else - { - animation = new AnimationInfo(key, AnimationImporterUtil.ConvertAnimationClip(GLTF, gltfAnimation, InvertAxis.Create()), false); - } - AnimationClips.Add(animation); + return AnimationImporterUtil.ConvertAnimationClip(GLTF, gltfAnimation, InvertAxis.Create()); + }); } await awaitCaller.NextFrame(); @@ -145,16 +138,16 @@ namespace UniGLTF /// protected virtual async Task SetupAnimationsAsync(IAwaitCaller awaitCaller) { - if (AnimationClips.Count == 0) - { - return; - } + if (AnimationClipFactory.LoadedClipKeys.Count == 0) return; + var animation = Root.AddComponent(); - for (int i = 0; i < AnimationClips.Count; ++i) + for (var clipIdx = 0; clipIdx < AnimationClipFactory.LoadedClipKeys.Count; ++clipIdx) { - var clip = AnimationClips[i].Clip; - animation.AddClip(clip, clip.name); - if (i == 0) + var key = AnimationClipFactory.LoadedClipKeys[clipIdx]; + var clip = AnimationClipFactory.GetAnimationClip(key); + animation.AddClip(clip, key.Name); + + if (clipIdx == 0) { animation.clip = clip; } @@ -285,22 +278,6 @@ namespace UniGLTF public List Nodes = new List(); public List Meshes = new List(); - - public struct AnimationInfo - { - public readonly SubAssetKey Key; - public readonly AnimationClip Clip; - public readonly bool IsExternal; - - public AnimationInfo(SubAssetKey key, AnimationClip clip, bool isExternal) - { - Key = key; - Clip = clip; - IsExternal = isExternal; - } - } - - public List AnimationClips = new List(); #endregion /// @@ -308,23 +285,13 @@ namespace UniGLTF /// public virtual void Dispose() { - foreach (var info in AnimationClips) - { - if (info.IsExternal) - { - // external は削除不要 - continue; - } - UnityObjectDestoyer.DestroyRuntimeOrEditor(info.Clip); - } - AnimationClips.Clear(); - foreach (var x in Meshes) { UnityObjectDestoyer.DestroyRuntimeOrEditor(x.Mesh); } Meshes.Clear(); + AnimationClipFactory?.Dispose(); MaterialFactory?.Dispose(); TextureFactory?.Dispose(); } @@ -341,20 +308,9 @@ namespace UniGLTF Meshes.Remove(mesh); } + AnimationClipFactory.TransferOwnership(take); TextureFactory.TransferOwnership(take); MaterialFactory.TransferOwnership(take); - - foreach (var info in AnimationClips) - { - if (info.IsExternal) - { - // external は削除しないので不要 - continue; - } - take(info.Key, info.Clip); - } - - AnimationClips.Clear(); } } } diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/AnimationClipFactory.cs b/Assets/VRMShaders/GLTF/IO/Runtime/AnimationClipFactory.cs new file mode 100644 index 000000000..b6ff3fa92 --- /dev/null +++ b/Assets/VRMShaders/GLTF/IO/Runtime/AnimationClipFactory.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using UnityEngine; + +namespace VRMShaders +{ + public class AnimationClipFactory : IResponsibilityForDestroyObjects + { + private readonly IReadOnlyDictionary _externalClips; + private readonly Dictionary _runtimeClips = new Dictionary(); + private readonly List _loadedClipKeys = new List(); + + /// + /// 外部アセットとして渡された AnimationClip + /// + public IReadOnlyDictionary ExternalClips => _externalClips; + + /// + /// ImporterContext によって Runtime に生成された AnimationClip + /// + public IReadOnlyDictionary RuntimeGeneratedClips => _runtimeClips; + + /// + /// ImporterContext によって必要とされた AnimationClip の SubAssetKey. + /// 必ずしも ExternalClips と RuntimeGeneratedClips の集合とは限らない. + /// + public IReadOnlyList LoadedClipKeys => _loadedClipKeys; + + public AnimationClipFactory(IReadOnlyDictionary externalClips) + { + _externalClips = externalClips; + } + + public void Dispose() + { + foreach (var kv in _runtimeClips) + { + UnityObjectDestoyer.DestroyRuntimeOrEditor(kv.Value); + } + _runtimeClips.Clear(); + } + + public void TransferOwnership(TakeResponsibilityForDestroyObjectFunc take) + { + foreach (var (key, o) in _runtimeClips.ToArray()) + { + take(key, o); + _runtimeClips.Remove(key); + } + } + + public AnimationClip GetAnimationClip(SubAssetKey key) + { + if (_externalClips.TryGetValue(key, out var clip)) + { + return clip; + } + + if (_runtimeClips.TryGetValue(key, out clip)) + { + return clip; + } + + return null; + } + + public async Task LoadAnimationClipAsync(SubAssetKey key, Func> loadAnimationClip) + { + if (!_loadedClipKeys.Contains(key)) + { + _loadedClipKeys.Add(key); + } + + var clip = GetAnimationClip(key); + if (clip != null) + { + return clip; + } + + clip = await loadAnimationClip(); + _runtimeClips.Add(key, clip); + return clip; + } + } +} diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/AnimationClipFactory.cs.meta b/Assets/VRMShaders/GLTF/IO/Runtime/AnimationClipFactory.cs.meta new file mode 100644 index 000000000..d84c86460 --- /dev/null +++ b/Assets/VRMShaders/GLTF/IO/Runtime/AnimationClipFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c82f7416fc3e8a44da2fe940bdb57281 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: