using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEditor; #if UNITY_2020_2_OR_NEWER using UnityEditor.AssetImporters; #else using UnityEditor.Experimental.AssetImporters; #endif namespace UniVRM10 { [ScriptedImporter(1, "vrm")] public class VrmScriptedImporter : ScriptedImporter, IExternalUnityObject { const string TextureDirName = "Textures"; const string MaterialDirName = "Materials"; const string MetaDirName = "MetaObjects"; const string ExpressionDirName = "Expressions"; public override void OnImportAsset(AssetImportContext ctx) { Debug.Log("OnImportAsset to " + ctx.assetPath); try { // Create Vrm Model VrmLib.Model model = VrmLoader.CreateVrmModel(ctx.assetPath); if (model == null) { // maybe VRM-0.X return; } Debug.Log($"VrmLoader.CreateVrmModel: {model}"); // Build Unity Model var assets = EditorUnityBuilder.ToUnityAsset(model, assetPath, this); ComponentBuilder.Build10(model, assets); // Texture var externalTextures = this.GetExternalUnityObjects(); foreach (var texture in assets.Textures) { if (texture == null) continue; if (externalTextures.ContainsValue(texture)) { } else { ctx.AddObjectToAsset(texture.name, texture); } } // Material var externalMaterials = this.GetExternalUnityObjects(); foreach (var material in assets.Materials) { if (material == null) continue; if (externalMaterials.ContainsValue(material)) { } else { ctx.AddObjectToAsset(material.name, material); } } // Mesh foreach (var mesh in assets.Meshes) { ctx.AddObjectToAsset(mesh.name, mesh); } //// ScriptableObject // avatar ctx.AddObjectToAsset("avatar", assets.HumanoidAvatar); // meta { var external = this.GetExternalUnityObjects().FirstOrDefault(); if (external.Value != null) { var controller = assets.Root.GetComponent(); if (controller != null) { controller.Meta = external.Value; } } else { var meta = assets.ScriptableObjects .FirstOrDefault(x => x.GetType() == typeof(UniVRM10.VRM10MetaObject)) as UniVRM10.VRM10MetaObject; if (meta != null) { meta.name = "meta"; ctx.AddObjectToAsset(meta.name, meta); } } } // expression { var external = this.GetExternalUnityObjects(); if (external.Any()) { } else { var expression = assets.ScriptableObjects .Where(x => x.GetType() == typeof(UniVRM10.VRM10Expression)) .Select(x => x as UniVRM10.VRM10Expression); foreach (var clip in expression) { clip.name = clip.ExpressionName; ctx.AddObjectToAsset(clip.ExpressionName, clip); } } } { var external = this.GetExternalUnityObjects().FirstOrDefault(); if (external.Value != null) { var controller = assets.Root.GetComponent(); if (controller != null) { controller.Expression.ExpressionAvatar = external.Value; } } else { var expressionAvatar = assets.ScriptableObjects .FirstOrDefault(x => x.GetType() == typeof(UniVRM10.VRM10ExpressionAvatar)) as UniVRM10.VRM10ExpressionAvatar; if (expressionAvatar != null) { expressionAvatar.name = "expressionAvatar"; ctx.AddObjectToAsset(expressionAvatar.name, expressionAvatar); } } } // Root ctx.AddObjectToAsset(assets.Root.name, assets.Root); ctx.SetMainObject(assets.Root); } catch (System.Exception ex) { Debug.LogError(ex); } } public void ExtractTextures() { this.ExtractTextures(TextureDirName, (path) => { return VrmLoader.CreateVrmModel(path); }); AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate); } public void ExtractMaterials() { this.ExtractAssets(MaterialDirName, ".mat"); AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate); } public void ExtractMaterialsAndTextures() { this.ExtractTextures(TextureDirName, (path) => { return VrmLoader.CreateVrmModel(path); }, () => { this.ExtractAssets(MaterialDirName, ".mat"); }); AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate); } public void ExtractMeta() { this.ExtractAssets(MetaDirName, ".asset"); var metaObject = this.GetExternalUnityObjects().FirstOrDefault(); var metaObjectPath = AssetDatabase.GetAssetPath(metaObject.Value); if (!string.IsNullOrEmpty(metaObjectPath)) { EditorUtility.SetDirty(metaObject.Value); AssetDatabase.WriteImportSettingsIfDirty(metaObjectPath); } AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate); } public void ExtractExpressions() { this.ExtractAssets(ExpressionDirName, ".asset"); this.ExtractAssets(ExpressionDirName, ".asset"); var expressionAvatar = this.GetExternalUnityObjects().FirstOrDefault(); var expressions = this.GetExternalUnityObjects(); expressionAvatar.Value.Clips = expressions.Select(x => x.Value).ToList(); var avatarPath = AssetDatabase.GetAssetPath(expressionAvatar.Value); if (!string.IsNullOrEmpty(avatarPath)) { EditorUtility.SetDirty(expressionAvatar.Value); AssetDatabase.WriteImportSettingsIfDirty(avatarPath); } AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate); } public Dictionary GetExternalUnityObjects() where T : UnityEngine.Object { return this.GetExternalObjectMap().Where(x => x.Key.type == typeof(T)).ToDictionary(x => x.Key.name, x => (T)x.Value); } public void SetExternalUnityObject(UnityEditor.AssetImporter.SourceAssetIdentifier sourceAssetIdentifier, T obj) where T : UnityEngine.Object { this.AddRemap(sourceAssetIdentifier, obj); AssetDatabase.WriteImportSettingsIfDirty(this.assetPath); AssetDatabase.ImportAsset(this.assetPath, ImportAssetOptions.ForceUpdate); } } }