Skip to content

Commit

Permalink
Merge pull request #1082 from Santarh/followV
Browse files Browse the repository at this point in the history
AnimationClip import with AnimationClipFactory
  • Loading branch information
ousttrue authored Jun 30, 2021
2 parents dfbb953 + 70c01d5 commit 164b34f
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ void ExtractMaterialsAndTextures(ScriptedImporter self, GltfData data, ITextureD
);
}

public void ExtractMaterials(ScriptedImporter importer, Func<string, string> materialDir)
public static void ExtractMaterials(ScriptedImporter importer, Func<string, string> materialDir)
{
if (string.IsNullOrEmpty(importer.assetPath))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void Extract(SubAssetKey key, TextureDescriptor texDesc)
}
else
{
throw new Exception($"{texture} is not converted.");
throw new Exception($"{key} is not converted.");
}
}

Expand Down Expand Up @@ -95,7 +95,7 @@ public static void ExtractTextures(GltfData data, UnityPath textureDirectory,
var externalObject = targetPath.LoadAsset<Texture2D>();
#if VRM_DEVELOP
// Debug.Log($"remap: {targetPath} => {externalObject}");
#endif
#endif
if (externalObject != null)
{
addRemap(key, externalObject);
Expand Down
88 changes: 22 additions & 66 deletions Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public class ImporterContext : IResponsibilityForDestroyObjects
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,
Expand All @@ -27,16 +28,19 @@ public ImporterContext(
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
Expand Down Expand Up @@ -113,27 +117,16 @@ public virtual async Task<RuntimeGltfInstance> LoadAsync(IAwaitCaller awaitCalle
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();
Expand All @@ -145,16 +138,16 @@ protected virtual async Task LoadAnimationAsync(IAwaitCaller awaitCaller)
/// </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;
}
Expand Down Expand Up @@ -285,46 +278,20 @@ async Task<MeshWithMaterials> BuildMeshAsync(IAwaitCaller awaitCaller, Func<stri
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>
/// ImporterContextが所有する UnityEngine.Object を破棄する
/// </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();
}
Expand All @@ -341,20 +308,9 @@ public virtual void TransferOwnership(TakeResponsibilityForDestroyObjectFunc tak
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();
}
}
}
87 changes: 87 additions & 0 deletions Assets/VRMShaders/GLTF/IO/Runtime/AnimationClipFactory.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
11 changes: 11 additions & 0 deletions Assets/VRMShaders/GLTF/IO/Runtime/AnimationClipFactory.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 164b34f

Please sign in to comment.