mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-13 06:20:01 -05:00
Merge pull request #1082 from Santarh/followV
AnimationClip import with AnimationClipFactory
This commit is contained in:
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
87
Assets/VRMShaders/GLTF/IO/Runtime/AnimationClipFactory.cs
Normal file
87
Assets/VRMShaders/GLTF/IO/Runtime/AnimationClipFactory.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c82f7416fc3e8a44da2fe940bdb57281
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user