diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/EditorAnimation.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/EditorAnimation.cs index 821939c3d..b17706477 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/EditorAnimation.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/EditorAnimation.cs @@ -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(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(importer.assetPath)) + { + asset.ExtractSubAsset($"{path}/{asset.name}.asset", false); + } + } + + AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate); } } } diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/EditorMaterial.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/EditorMaterial.cs index 5a252d62c..60a93285d 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/EditorMaterial.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/EditorMaterial.cs @@ -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 textureDir, Func 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 ...")) { diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GlbScriptedImporterEditorGUI.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GlbScriptedImporterEditorGUI.cs index d3503df95..f762ebfd3 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GlbScriptedImporterEditorGUI.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GlbScriptedImporterEditorGUI.cs @@ -45,7 +45,7 @@ namespace UniGLTF break; case Tabs.Animation: - EditorAnimation.OnGUIAnimation(m_parser); + EditorAnimation.OnGUIAnimation(m_importer, m_parser); break; case Tabs.Materials: diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterEditorGUI.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterEditorGUI.cs index cc5a2c6fa..150d94f11 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterEditorGUI.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterEditorGUI.cs @@ -45,7 +45,7 @@ namespace UniGLTF break; case Tabs.Animation: - EditorAnimation.OnGUIAnimation(m_parser); + EditorAnimation.OnGUIAnimation(m_importer, m_parser); break; case Tabs.Materials: diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/AnimationIO/IAnimationImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/AnimationIO/IAnimationImporter.cs index 4ea8f4ba2..6e9a2f773 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/AnimationIO/IAnimationImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/AnimationIO/IAnimationImporter.cs @@ -1,10 +1,11 @@ using System.Collections.Generic; using UnityEngine; +using VRMShaders; namespace UniGLTF { public interface IAnimationImporter { - List Import(glTF gltf, GameObject root, List nodes, Axes invertAxis); + AnimationClip Import(glTF gltf, int i, Axes invertAxis); } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/AnimationIO/RootAnimationImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/AnimationIO/RootAnimationImporter.cs index 53f7016d6..980caec8a 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/AnimationIO/RootAnimationImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/AnimationIO/RootAnimationImporter.cs @@ -1,53 +1,12 @@ -using System.Collections.Generic; -using System.Linq; -using UnityEngine; +using UnityEngine; namespace UniGLTF { public sealed class RootAnimationImporter : IAnimationImporter { - public List Import(glTF gltf, GameObject root, List _nodes, Axes invertAxis) + public AnimationClip Import(glTF gltf, int i, Axes invertAxis) { - var animationClips = new List(); - if (gltf.animations != null && gltf.animations.Any()) - { - var animation = root.AddComponent(); - 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 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()); } } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfParser.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfParser.cs index cc561be08..cc086a741 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfParser.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfParser.cs @@ -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(); + 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); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index 0ba65fb02..f513391e3 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -36,6 +36,7 @@ namespace UniGLTF public IMaterialDescriptorGenerator MaterialDescriptorGenerator { get; protected set; } public TextureFactory TextureFactory { get; } public MaterialFactory MaterialFactory { get; } + IReadOnlyDictionary _externalObjectMap; public ImporterContext( GltfParser parser, @@ -46,13 +47,13 @@ namespace UniGLTF TextureDescriptorGenerator = new GltfTextureDescriptorGenerator(Parser); 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)); - 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(); + 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); diff --git a/Assets/VRM10/Editor/Components/VRM10ControllerEditor.cs b/Assets/VRM10/Editor/Components/VRM10ControllerEditor.cs index 739bb52c0..e696cf205 100644 --- a/Assets/VRM10/Editor/Components/VRM10ControllerEditor.cs +++ b/Assets/VRM10/Editor/Components/VRM10ControllerEditor.cs @@ -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(); diff --git a/Assets/VRM10/Editor/Components/VRM10Window.cs b/Assets/VRM10/Editor/Components/VRM10Window.cs index 8c0070939..1fcb55578 100644 --- a/Assets/VRM10/Editor/Components/VRM10Window.cs +++ b/Assets/VRM10/Editor/Components/VRM10Window.cs @@ -173,7 +173,7 @@ namespace UniVRM10 } } - using (new EditorGUI.DisabledGroupScope(true)) + using (new EditorGUI.DisabledScope(true)) { if (m_constraints != null) { diff --git a/Assets/VRM10/Editor/ScriptedImporter/EditorVrm.cs b/Assets/VRM10/Editor/ScriptedImporter/EditorVrm.cs index 0c25c3e47..37e0d03f9 100644 --- a/Assets/VRM10/Editor/ScriptedImporter/EditorVrm.cs +++ b/Assets/VRM10/Editor/ScriptedImporter/EditorVrm.cs @@ -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 ...")) {