feat: initial support for blendshape actions

This commit is contained in:
bd_ 2023-04-30 20:58:11 +09:00
parent 93a0171940
commit 5cba6f24cb
4 changed files with 89 additions and 7 deletions

View File

@ -88,16 +88,15 @@ namespace nadena.dev.modular_avatar.core.editor
}
var layerList = controller.layers.ToList();
layerList.Insert(0, GenerateBlendshapeBaseLayer(avatar));
rootBlendTree.defaultWeight = 1;
layerList.Insert(0, rootBlendTree);
if (layerList.Count > 1)
{
layerList[1].defaultWeight = 1;
}
rootBlendTree.defaultWeight = 1;
controller.layers = layerList.ToArray();
// Generate blendshape base layer including anything we're animating in our blendtree
layerList.Insert(0, GenerateBlendshapeBaseLayer(avatar));
controller.layers = layerList.ToArray();
foreach (var action in avatar.GetComponentsInChildren<MenuAction>(true))
{
Object.DestroyImmediate((UnityEngine.Object) action);

View File

@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using UnityEngine;
namespace nadena.dev.modular_avatar.core
{
[AddComponentMenu("Modular Avatar/MA Action Blendshape")]
[RequireComponent(typeof(ActionController))]
public class ActionBlendshape : AvatarTagComponent, SwitchedMenuAction
{
[Serializable]
public class BlendshapeSpec
{
public AvatarObjectReference target = new AvatarObjectReference();
public string blendshape;
public float value;
}
public List<BlendshapeSpec> Blendshapes;
public bool BindsParameter(TargetParameter parameter)
{
return parameter == TargetParameter.BaseParameter;
}
public ImmutableDictionary<MenuCurveBinding, AnimationCurve> GetCurves()
{
ImmutableDictionary<MenuCurveBinding, AnimationCurve>.Builder builder =
ImmutableDictionary<MenuCurveBinding, AnimationCurve>.Empty.ToBuilder();
foreach (var spec in Blendshapes)
{
var target = spec.target?.Get(this);
if (target == null) continue;
if (string.IsNullOrWhiteSpace(spec.blendshape)) continue;
builder.Add(
new MenuCurveBinding(target, typeof(SkinnedMeshRenderer), "blendShape." + spec.blendshape),
AnimationCurve.Constant(0, 1, spec.value)
);
}
return builder.ToImmutable();
}
public ImmutableDictionary<MenuCurveBinding, AnimationCurve> GetInactiveCurves()
{
ImmutableDictionary<MenuCurveBinding, AnimationCurve>.Builder builder =
ImmutableDictionary<MenuCurveBinding, AnimationCurve>.Empty.ToBuilder();
foreach (var spec in Blendshapes)
{
var target = spec.target?.Get(this);
if (target == null) continue;
var targetRenderer = target.GetComponent<SkinnedMeshRenderer>();
if (targetRenderer == null) continue;
var mesh = targetRenderer.sharedMesh;
if (mesh == null) continue;
if (string.IsNullOrWhiteSpace(spec.blendshape)) continue;
var blendshapeIndex = mesh.GetBlendShapeIndex(spec.blendshape);
if (blendshapeIndex < 0) continue;
var value = targetRenderer.GetBlendShapeWeight(blendshapeIndex);
builder.Add(
new MenuCurveBinding(target, typeof(SkinnedMeshRenderer), "blendShape." + spec.blendshape),
AnimationCurve.Constant(0, 1, value)
);
}
return builder.ToImmutable();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b91a8e5892cd4d2c85fcd0b2f2c570e1
timeCreated: 1682852930

View File

@ -14,7 +14,7 @@ namespace nadena.dev.modular_avatar.core
[Serializable]
public class ObjectEntry
{
public AvatarObjectReference target;
public AvatarObjectReference target = new AvatarObjectReference();
public bool Active;
}