Merge pull request #1082 from Santarh/followV

AnimationClip import with AnimationClipFactory
This commit is contained in:
ousttrue
2021-06-30 13:48:28 +09:00
committed by GitHub
5 changed files with 123 additions and 69 deletions

View File

@@ -102,7 +102,7 @@ namespace UniGLTF
);
}
public void ExtractMaterials(ScriptedImporter importer, Func<string, string> materialDir)
public static void ExtractMaterials(ScriptedImporter importer, Func<string, string> materialDir)
{
if (string.IsNullOrEmpty(importer.assetPath))
{

View File

@@ -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<Texture2D>();
#if VRM_DEVELOP
// Debug.Log($"remap: {targetPath} => {externalObject}");
#endif
#endif
if (externalObject != null)
{
addRemap(key, externalObject);

View File

@@ -16,7 +16,8 @@ namespace UniGLTF
public IMaterialDescriptorGenerator MaterialDescriptorGenerator { get; protected set; }
public TextureFactory TextureFactory { get; }
public MaterialFactory MaterialFactory { get; }
IReadOnlyDictionary<SubAssetKey, UnityEngine.Object> _externalObjectMap;
public AnimationClipFactory AnimationClipFactory { get; }
public IReadOnlyDictionary<SubAssetKey, UnityEngine.Object> ExternalObjectMap;
public ImporterContext(
GltfData data,
@@ -27,16 +28,19 @@ namespace UniGLTF
TextureDescriptorGenerator = new GltfTextureDescriptorGenerator(Data);
MaterialDescriptorGenerator = new GltfMaterialDescriptorGenerator();
_externalObjectMap = externalObjectMap ?? new Dictionary<SubAssetKey, UnityEngine.Object>();
ExternalObjectMap = externalObjectMap ?? new Dictionary<SubAssetKey, UnityEngine.Object>();
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);
}
/// <summary>
/// ImporterContext.AnimationClips に AnimationClip を読み込むところまでが責務
/// </summary>
/// <param name="awaitCaller"></param>
/// <returns></returns>
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
/// </summary>
protected virtual async Task SetupAnimationsAsync(IAwaitCaller awaitCaller)
{
if (AnimationClips.Count == 0)
{
return;
}
if (AnimationClipFactory.LoadedClipKeys.Count == 0) return;
var animation = Root.AddComponent<Animation>();
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<Transform> Nodes = new List<Transform>();
public List<MeshWithMaterials> Meshes = new List<MeshWithMaterials>();
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<AnimationInfo> AnimationClips = new List<AnimationInfo>();
#endregion
/// <summary>
@@ -308,23 +285,13 @@ namespace UniGLTF
/// </summary>
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();
}
}
}

View File

@@ -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<SubAssetKey, AnimationClip> _externalClips;
private readonly Dictionary<SubAssetKey, AnimationClip> _runtimeClips = new Dictionary<SubAssetKey, AnimationClip>();
private readonly List<SubAssetKey> _loadedClipKeys = new List<SubAssetKey>();
/// <summary>
/// 外部アセットとして渡された AnimationClip
/// </summary>
public IReadOnlyDictionary<SubAssetKey, AnimationClip> ExternalClips => _externalClips;
/// <summary>
/// ImporterContext によって Runtime に生成された AnimationClip
/// </summary>
public IReadOnlyDictionary<SubAssetKey, AnimationClip> RuntimeGeneratedClips => _runtimeClips;
/// <summary>
/// ImporterContext によって必要とされた AnimationClip の SubAssetKey.
/// 必ずしも ExternalClips と RuntimeGeneratedClips の集合とは限らない.
/// </summary>
public IReadOnlyList<SubAssetKey> LoadedClipKeys => _loadedClipKeys;
public AnimationClipFactory(IReadOnlyDictionary<SubAssetKey, AnimationClip> 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<AnimationClip> LoadAnimationClipAsync(SubAssetKey key, Func<Task<AnimationClip>> 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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c82f7416fc3e8a44da2fe940bdb57281
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: