mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-05-14 22:50:08 -05:00
Merge pull request #998 from ousttrue/feature/animation_extract
Feature/animation extract
This commit is contained in:
commit
1cec8cfcea
|
|
@ -1,16 +1,63 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Experimental.AssetImporters;
|
||||
using UnityEngine;
|
||||
using VRMShaders;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public static class EditorAnimation
|
||||
{
|
||||
public static void OnGUIAnimation(GltfParser parser)
|
||||
public static void OnGUIAnimation(ScriptedImporter importer, GltfParser parser)
|
||||
{
|
||||
for (int i = 0; i < parser.GLTF.animations.Count; ++i)
|
||||
var hasExternal = importer.GetExternalObjectMap().Any(x => x.Value is AnimationClip);
|
||||
using (new EditorGUI.DisabledScope(hasExternal))
|
||||
{
|
||||
var a = parser.GLTF.animations[i];
|
||||
GUILayout.Label($"{i}: {a.name}");
|
||||
if (GUILayout.Button("Extract Animation ..."))
|
||||
{
|
||||
Extract(importer, parser);
|
||||
}
|
||||
}
|
||||
|
||||
importer.DrawRemapGUI<AnimationClip>(parser.GLTF.animations.Select(x => new SubAssetKey(typeof(AnimationClip), x.name)));
|
||||
|
||||
if (GUILayout.Button("Clear"))
|
||||
{
|
||||
importer.ClearExternalObjects(
|
||||
typeof(UnityEngine.AnimationClip)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static string GetAndCreateFolder(string assetPath, string suffix)
|
||||
{
|
||||
var path = $"{Path.GetDirectoryName(assetPath)}/{Path.GetFileNameWithoutExtension(assetPath)}{suffix}";
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
public static void Extract(ScriptedImporter importer, GltfParser parser)
|
||||
{
|
||||
if (string.IsNullOrEmpty(importer.assetPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
var path = GetAndCreateFolder(importer.assetPath, ".Animations");
|
||||
foreach (var (key, asset) in importer.GetSubAssets<AnimationClip>(importer.assetPath))
|
||||
{
|
||||
asset.ExtractSubAsset($"{path}/{asset.name}.asset", false);
|
||||
}
|
||||
}
|
||||
|
||||
AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,20 +14,6 @@ using UnityEditor.Experimental.AssetImporters;
|
|||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public class TmpGuiEnable : IDisposable
|
||||
{
|
||||
bool m_backup;
|
||||
public TmpGuiEnable(bool enable)
|
||||
{
|
||||
m_backup = GUI.enabled;
|
||||
GUI.enabled = enable;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GUI.enabled = m_backup;
|
||||
}
|
||||
}
|
||||
public static class EditorMaterial
|
||||
{
|
||||
static bool s_foldMaterials = true;
|
||||
|
|
@ -36,7 +22,7 @@ namespace UniGLTF
|
|||
public static void OnGUI(ScriptedImporter importer, GltfParser parser, ITextureDescriptorGenerator textureDescriptorGenerator, Func<string, string> textureDir, Func<string, string> materialDir)
|
||||
{
|
||||
var hasExternal = importer.GetExternalObjectMap().Any(x => x.Value is Material || x.Value is Texture2D);
|
||||
using (new TmpGuiEnable(!hasExternal))
|
||||
using (new EditorGUI.DisabledScope(hasExternal))
|
||||
{
|
||||
if (GUILayout.Button("Extract Materials And Textures ..."))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace UniGLTF
|
|||
break;
|
||||
|
||||
case Tabs.Animation:
|
||||
EditorAnimation.OnGUIAnimation(m_parser);
|
||||
EditorAnimation.OnGUIAnimation(m_importer, m_parser);
|
||||
break;
|
||||
|
||||
case Tabs.Materials:
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace UniGLTF
|
|||
break;
|
||||
|
||||
case Tabs.Animation:
|
||||
EditorAnimation.OnGUIAnimation(m_parser);
|
||||
EditorAnimation.OnGUIAnimation(m_importer, m_parser);
|
||||
break;
|
||||
|
||||
case Tabs.Materials:
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using VRMShaders;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public interface IAnimationImporter
|
||||
{
|
||||
List<AnimationClip> Import(glTF gltf, GameObject root, List<Transform> nodes, Axes invertAxis);
|
||||
AnimationClip Import(glTF gltf, int i, Axes invertAxis);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,53 +1,12 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public sealed class RootAnimationImporter : IAnimationImporter
|
||||
{
|
||||
public List<AnimationClip> Import(glTF gltf, GameObject root, List<Transform> _nodes, Axes invertAxis)
|
||||
public AnimationClip Import(glTF gltf, int i, Axes invertAxis)
|
||||
{
|
||||
var animationClips = new List<AnimationClip>();
|
||||
if (gltf.animations != null && gltf.animations.Any())
|
||||
{
|
||||
var animation = root.AddComponent<Animation>();
|
||||
animationClips.AddRange(ImportAnimationClips(gltf, invertAxis));
|
||||
|
||||
foreach (var clip in animationClips)
|
||||
{
|
||||
animation.AddClip(clip, clip.name);
|
||||
}
|
||||
if (animationClips.Count > 0)
|
||||
{
|
||||
animation.clip = animationClips.First();
|
||||
}
|
||||
}
|
||||
return animationClips;
|
||||
}
|
||||
|
||||
private IEnumerable<AnimationClip> ImportAnimationClips(glTF gltf, Axes invertAxis)
|
||||
{
|
||||
for (var i = 0; i < gltf.animations.Count; ++i)
|
||||
{
|
||||
var clip = new AnimationClip();
|
||||
clip.ClearCurves();
|
||||
clip.legacy = true;
|
||||
clip.name = gltf.animations[i].name;
|
||||
if (string.IsNullOrEmpty(clip.name))
|
||||
{
|
||||
clip.name = $"legacy_{i}";
|
||||
}
|
||||
clip.wrapMode = WrapMode.Loop;
|
||||
|
||||
var animation = gltf.animations[i];
|
||||
if (string.IsNullOrEmpty(animation.name))
|
||||
{
|
||||
animation.name = $"animation:{i}";
|
||||
}
|
||||
|
||||
yield return AnimationImporterUtil.ConvertAnimationClip(gltf, animation, invertAxis.Create());
|
||||
}
|
||||
return AnimationImporterUtil.ConvertAnimationClip(gltf, gltf.animations[i], invertAxis.Create());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,13 +130,14 @@ namespace UniGLTF
|
|||
RestoreOlderVersionValues();
|
||||
|
||||
FixMeshNameUnique();
|
||||
foreach(var image in GLTF.images)
|
||||
foreach (var image in GLTF.images)
|
||||
{
|
||||
image.uri = PrepareUri(image.uri);
|
||||
}
|
||||
FixTextureNameUnique();
|
||||
FixMaterialNameUnique();
|
||||
FixNodeName();
|
||||
FixAnimationNameUnique();
|
||||
|
||||
// parepare byte buffer
|
||||
//GLTF.baseDir = System.IO.Path.GetDirectoryName(Path);
|
||||
|
|
@ -308,6 +309,34 @@ namespace UniGLTF
|
|||
}
|
||||
}
|
||||
|
||||
void FixAnimationNameUnique()
|
||||
{
|
||||
var used = new HashSet<string>();
|
||||
for (int i = 0; i < GLTF.animations.Count; ++i)
|
||||
{
|
||||
var animation = GLTF.animations[i];
|
||||
var originalName = animation.name;
|
||||
int j = 2;
|
||||
|
||||
if (string.IsNullOrEmpty(animation.name))
|
||||
{
|
||||
animation.name = $"animation_{i}";
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (used.Add(animation.name))
|
||||
{
|
||||
#if VRM_DEVELOP
|
||||
// Debug.Log($"Material: {material.name}");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
animation.name = string.Format("{0}({1})", originalName, j++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RestoreOlderVersionValues()
|
||||
{
|
||||
var parsed = UniJSON.JsonParser.Parse(Json);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ namespace UniGLTF
|
|||
public IMaterialDescriptorGenerator MaterialDescriptorGenerator { get; protected set; }
|
||||
public TextureFactory TextureFactory { get; }
|
||||
public MaterialFactory MaterialFactory { get; }
|
||||
IReadOnlyDictionary<SubAssetKey, UnityEngine.Object> _externalObjectMap;
|
||||
|
||||
public ImporterContext(
|
||||
GltfParser parser,
|
||||
|
|
@ -46,13 +47,13 @@ namespace UniGLTF
|
|||
TextureDescriptorGenerator = new GltfTextureDescriptorGenerator(Parser);
|
||||
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));
|
||||
MaterialFactory = new MaterialFactory(externalObjectMap
|
||||
MaterialFactory = new MaterialFactory(_externalObjectMap
|
||||
.Where(x => x.Value is Material)
|
||||
.ToDictionary(x => x.Key, x => (Material)x.Value));
|
||||
}
|
||||
|
|
@ -122,7 +123,30 @@ namespace UniGLTF
|
|||
|
||||
using (MeasureTime("AnimationImporter"))
|
||||
{
|
||||
AnimationClips.AddRange(AnimationImporter.Import(GLTF, Root, null, InvertAxis));
|
||||
if (GLTF.animations != null && GLTF.animations.Any())
|
||||
{
|
||||
var animation = Root.AddComponent<Animation>();
|
||||
for (int i = 0; i < GLTF.animations.Count; ++i)
|
||||
{
|
||||
var gltfAnimation = GLTF.animations[i];
|
||||
AnimationClip clip = default;
|
||||
if (_externalObjectMap.TryGetValue(new SubAssetKey(typeof(AnimationClip), gltfAnimation.name), out UnityEngine.Object value))
|
||||
{
|
||||
clip = value as AnimationClip;
|
||||
}
|
||||
else
|
||||
{
|
||||
clip = AnimationImporter.Import(GLTF, i, InvertAxis);
|
||||
AnimationClips.Add(clip);
|
||||
}
|
||||
|
||||
animation.AddClip(clip, clip.name);
|
||||
if (i == 0)
|
||||
{
|
||||
animation.clip = clip;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await OnLoadHierarchy(awaitCaller, MeasureTime);
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ namespace UniVRM10
|
|||
public override void OnInspectorGUI()
|
||||
{
|
||||
// select sub editor
|
||||
using (new EditorGUI.DisabledGroupScope(false))
|
||||
using (new EditorGUI.DisabledScope(false))
|
||||
{
|
||||
_tab = (Tabs)EditorGUILayout.EnumPopup("Select GUI", _tab);
|
||||
EditorGUILayout.Separator();
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ namespace UniVRM10
|
|||
}
|
||||
}
|
||||
|
||||
using (new EditorGUI.DisabledGroupScope(true))
|
||||
using (new EditorGUI.DisabledScope(true))
|
||||
{
|
||||
if (m_constraints != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace UniVRM10
|
|||
public static void OnGUI(ScriptedImporter importer, GltfParser parser, UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm)
|
||||
{
|
||||
var hasExternal = importer.GetExternalObjectMap().Any(x => x.Value is VRM10MetaObject || x.Value is VRM10ExpressionAvatar || x.Value is VRM10Expression);
|
||||
using (new TmpGuiEnable(!hasExternal))
|
||||
using (new EditorGUI.DisabledScope(hasExternal))
|
||||
{
|
||||
if (GUILayout.Button("Extract Meta And Expressions ..."))
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user