Merge pull request #2534 from ousttrue/fix/vrma_scripted_importer

[vrma][editor] VRMA の EditorImport
This commit is contained in:
ousttrue 2024-12-20 15:51:57 +09:00 committed by GitHub
commit 4e6cab5400
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 108 additions and 14 deletions

View File

@ -0,0 +1,63 @@
using UniGLTF;
using UnityEngine;
using System.Linq;
using UnityEditor.AssetImporters;
namespace UniVRM10
{
[ScriptedImporter(1, "vrma")]
public class VrmaScriptedImporter : ScriptedImporter
{
/// <summary>
/// Vrm-1.0 の Asset にアイコンを付与する
/// </summary>
static Texture2D _AssetIcon = null;
static Texture2D AssetIcon
{
get
{
if (_AssetIcon == null)
{
// try package
_AssetIcon = UnityEditor.AssetDatabase.LoadAssetAtPath<Texture2D>("Packages/com.vrmc.vrm/Icons/vrm-48x48.png");
}
if (_AssetIcon == null)
{
// try assets
_AssetIcon = UnityEditor.AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/VRM10/Icons/vrm-48x48.png");
}
return _AssetIcon;
}
}
public override void OnImportAsset(AssetImportContext context)
{
// 2 回目以降の Asset Import において、 Importer の設定で Extract した UnityEngine.Object が入る
var extractedObjects = GetExternalObjectMap()
.Where(x => x.Value != null)
.ToDictionary(kv => new SubAssetKey(kv.Value.GetType(), kv.Key.name), kv => kv.Value);
using (var data = new AutoGltfFileParser(assetPath).Parse())
using (var loader = new VrmAnimationImporter(data, extractedObjects))
{
var loaded = loader.Load();
loaded.TransferOwnership((k, o) =>
{
context.AddObjectToAsset(k.Name, o);
});
var root = loaded.Root;
GameObject.DestroyImmediate(loaded);
// var vrma = root.GetComponent<Vrm10AnimationInstance>();
// context.AddObjectToAsset("__boxman_mesh__", vrma.BoxMan.sharedMesh);
// context.AddObjectToAsset("__boxman_mesh__material__", vrma.BoxMan.sharedMaterial);
context.AddObjectToAsset(root.name, root, AssetIcon);
context.SetMainObject(root);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 19427481f19aca9429da3548d28da6f5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
icon: {fileID: 2800000, guid: ad4861e134018c948ac79793d290f48b, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -7,12 +7,15 @@ using UniGLTF.Extensions.VRMC_vrm_animation;
using UniHumanoid;
using UniJSON;
using UnityEngine;
using VrmLib;
namespace UniVRM10
{
public class VrmAnimationImporter : UniGLTF.ImporterContext
{
VRMC_vrm_animation m_vrma;
ExpressionInfo[] m_expressions;
Material m_defaultMaterial;
public VrmAnimationImporter(GltfData data,
IReadOnlyDictionary<SubAssetKey, UnityEngine.Object> externalObjectMap = null,
@ -230,8 +233,8 @@ namespace UniVRM10
{
// Expression は AnimationClip を分ける。
// glTFData から関連 Animation を取り除いて、取っておく。
var expressions = IterateExpressions().ToArray();
foreach (var channelIndex in expressions.Select(x => x.ChannelIndex).OrderByDescending(x => x))
m_expressions = IterateExpressions().ToArray();
foreach (var channelIndex in m_expressions.Select(x => x.ChannelIndex).OrderByDescending(x => x))
{
var nodeIndex = Data.GLTF.animations[0].channels[channelIndex].target.node;
Data.GLTF.nodes.RemoveAt(nodeIndex);
@ -243,11 +246,16 @@ namespace UniVRM10
Data.GLTF.scenes[0].nodes = Data.GLTF.scenes[0].nodes.Take(1).ToArray();
// 可視化メッシュ用マテリアル。base.LoadAsync を呼ぶ前に生成する。
var defaultMaterial = await MaterialFactory.GetDefaultMaterialAsync(awaitCaller);
m_defaultMaterial = await MaterialFactory.GetDefaultMaterialAsync(awaitCaller);
// Humanoid Animation が Gltf アニメーションとしてロードされる
var instance = await base.LoadAsync(awaitCaller, measureTime);
return instance;
}
protected override Task OnLoadHierarchy(IAwaitCaller awaitCaller, Func<string, IDisposable> MeasureTime)
{
// setup humanoid
var humanMap = GetHumanMap();
if (humanMap.Count > 0)
@ -256,22 +264,23 @@ namespace UniVRM10
//
// avatar
//
var avatar = description.CreateAvatar(instance.Root.transform);
var avatar = description.CreateAvatar(Root.transform);
avatar.name = "Avatar";
// AvatarDescription = description;
var animator = instance.gameObject.AddComponent<Animator>();
var animator = Root.AddComponent<Animator>();
animator.avatar = avatar;
}
if (expressions.Length > 0)
if (m_expressions.Length > 0)
{
var animation = instance.GetComponentOrThrow<Animation>();
var animation = Root.GetComponentOrThrow<Animation>();
var clip = animation.clip;
// m_expressionClip.name = "__expression__";
// Expression の float カーブを追加する
// VrmAnimationInstance の "preset_xx" field に連動する
var gltfAnimation = Data.GLTF.animations[0];
foreach (var expression in expressions)
foreach (var expression in m_expressions)
{
var channel = expression.Channel;
var sampler = gltfAnimation.samplers[channel.sampler];
@ -284,11 +293,22 @@ namespace UniVRM10
}
}
// VRMA-animation solver
var animationInstance = instance.gameObject.AddComponent<Vrm10AnimationInstance>();
animationInstance.Initialize(expressions.Select(x => x.Key), defaultMaterial);
var animationInstance = Root.AddComponent<Vrm10AnimationInstance>();
return instance;
animationInstance.Initialize(m_expressions.Select(x => x.Key), m_defaultMaterial);
return Task.CompletedTask;
}
public override void TransferOwnership(TakeResponsibilityForDestroyObjectFunc take)
{
var animationInstance = Root.GetComponent<Vrm10AnimationInstance>();
take(SubAssetKey.Create(animationInstance.BoxMan.sharedMesh), animationInstance.BoxMan.sharedMesh);
var animator = Root.GetComponent<Animator>();
take(SubAssetKey.Create(animator.avatar), animator.avatar);
base.TransferOwnership(take);
}
}
}
}