mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-01-17 11:50:11 +08:00
ui: add action blendshape editor
This commit is contained in:
parent
1175e43bfd
commit
5a36db7b7f
@ -112,6 +112,17 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
|
||||
if (_columns.Count == 0)
|
||||
{
|
||||
if (_elementWidth < 1.0f)
|
||||
{
|
||||
if (rect.width < 1.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_elementWidth = rect.width - 10f;
|
||||
Repaint();
|
||||
}
|
||||
|
||||
_columnPos = 0;
|
||||
_remainingWidth = _elementWidth;
|
||||
OnGenerateColumns(_elementWidth);
|
||||
|
@ -0,0 +1,188 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace nadena.dev.modular_avatar.core.editor
|
||||
{
|
||||
[CustomEditor(typeof(ActionBlendshape))]
|
||||
internal class ActionBlendshapeEditor : MAEditorBase
|
||||
{
|
||||
private ColumnReorderableList _list;
|
||||
private SerializedProperty _listProp;
|
||||
private Dictionary<Mesh, string[]> _blendshapeNamesCache = new Dictionary<Mesh, string[]>();
|
||||
private Transform _avatarRoot;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_listProp = serializedObject.FindProperty(nameof(ActionBlendshape.Blendshapes));
|
||||
_list = new ColumnReorderableList(
|
||||
serializedObject,
|
||||
_listProp,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
_list.Repaint = Repaint;
|
||||
_list.OnGenerateColumns = BuildColumns;
|
||||
_list.onRemoveCallback += OnRemoveElement;
|
||||
_list.onAddCallback += OnAddElement;
|
||||
|
||||
_list.elementHeight += 2;
|
||||
|
||||
if (targets.Length == 1)
|
||||
{
|
||||
_avatarRoot = RuntimeUtil.FindAvatarInParents(((Component) target).transform).transform;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAddElement(ReorderableList list)
|
||||
{
|
||||
_listProp.arraySize++;
|
||||
}
|
||||
|
||||
private void OnRemoveElement(ReorderableList reorderableList)
|
||||
{
|
||||
if (reorderableList.index < _listProp.arraySize)
|
||||
{
|
||||
_listProp.DeleteArrayElementAtIndex(reorderableList.index);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderBlendshapeColumn(Rect rect, SerializedProperty elem)
|
||||
{
|
||||
var prop_obj = elem.FindPropertyRelative(nameof(ActionBlendshape.BlendshapeSpec.target))
|
||||
?.FindPropertyRelative(nameof(AvatarObjectReference.referencePath));
|
||||
var prop_blendshape = elem.FindPropertyRelative(nameof(ActionBlendshape.BlendshapeSpec.blendshape));
|
||||
|
||||
SkinnedMeshRenderer targetRenderer = null;
|
||||
|
||||
if (_avatarRoot != null)
|
||||
{
|
||||
var targetObj = _avatarRoot.Find(prop_obj.stringValue);
|
||||
if (targetObj != null)
|
||||
{
|
||||
targetRenderer = targetObj.GetComponent<SkinnedMeshRenderer>();
|
||||
}
|
||||
}
|
||||
|
||||
if (targetRenderer == null || targetRenderer.sharedMesh == null)
|
||||
{
|
||||
EditorGUI.PropertyField(rect, prop_blendshape, GUIContent.none);
|
||||
return;
|
||||
}
|
||||
|
||||
var sharedMesh = targetRenderer.sharedMesh;
|
||||
|
||||
if (!_blendshapeNamesCache.TryGetValue(sharedMesh, out var names))
|
||||
{
|
||||
names = new string[sharedMesh.blendShapeCount + 1];
|
||||
names[0] = "";
|
||||
for (var i = 1; i < sharedMesh.blendShapeCount; i++)
|
||||
{
|
||||
names[i] = sharedMesh.GetBlendShapeName(i - 1);
|
||||
}
|
||||
|
||||
_blendshapeNamesCache[sharedMesh] = names;
|
||||
}
|
||||
|
||||
var blendshapeIndex = Array.IndexOf(names, prop_blendshape.stringValue);
|
||||
var style = new GUIStyle(EditorStyles.popup);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
blendshapeIndex = EditorGUI.Popup(rect, blendshapeIndex, names, style);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
prop_blendshape.stringValue = names[blendshapeIndex];
|
||||
}
|
||||
else if (blendshapeIndex < 0)
|
||||
{
|
||||
var toDisplay = prop_blendshape.stringValue;
|
||||
|
||||
UpdateAllStates(style, s => s.textColor = Color.Lerp(s.textColor, Color.red, 0.85f));
|
||||
|
||||
GUI.Label(rect, toDisplay, style);
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateAllStates(GUIStyle style, Action<GUIStyleState> action)
|
||||
{
|
||||
var state = style.normal;
|
||||
action(state);
|
||||
style.normal = state;
|
||||
|
||||
state = style.hover;
|
||||
action(state);
|
||||
style.hover = state;
|
||||
|
||||
state = style.active;
|
||||
action(state);
|
||||
style.active = state;
|
||||
|
||||
state = style.focused;
|
||||
action(state);
|
||||
style.focused = state;
|
||||
|
||||
state = style.onNormal;
|
||||
action(state);
|
||||
style.onNormal = state;
|
||||
|
||||
state = style.onHover;
|
||||
action(state);
|
||||
style.onHover = state;
|
||||
|
||||
state = style.onActive;
|
||||
action(state);
|
||||
style.onActive = state;
|
||||
|
||||
state = style.onFocused;
|
||||
action(state);
|
||||
style.onFocused = state;
|
||||
}
|
||||
|
||||
private void BuildColumns(float width)
|
||||
{
|
||||
GUIContent testValueContent = new GUIContent("100");
|
||||
var valueFieldSize = EditorStyles.textField.CalcSize(testValueContent);
|
||||
var remainingWidth = width - valueFieldSize.x - _list.margin;
|
||||
var fieldWidth = (remainingWidth - _list.margin) / 2;
|
||||
|
||||
_list.AddColumn(fieldWidth, "action.blendshape.header.object", (rect, elem) =>
|
||||
{
|
||||
var targetProp = elem.FindPropertyRelative(nameof(ActionBlendshape.BlendshapeSpec.target));
|
||||
EditorGUI.PropertyField(rect, targetProp, GUIContent.none);
|
||||
});
|
||||
|
||||
_list.AddColumn(fieldWidth, "action.blendshape.header.blendshape", RenderBlendshapeColumn);
|
||||
|
||||
_list.AddColumn(valueFieldSize.x, "action.blendshape.header.value", (rect, elem) =>
|
||||
{
|
||||
var valueProp = elem.FindPropertyRelative(nameof(ActionBlendshape.BlendshapeSpec.value));
|
||||
EditorGUI.PropertyField(rect, valueProp, GUIContent.none);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void OnInnerInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
Rect rect = GUILayoutUtility.GetRect(
|
||||
10f,
|
||||
_list.headerHeight + _list.elementHeight * Math.Max(1, _list.serializedProperty.arraySize) +
|
||||
_list.footerHeight,
|
||||
GUILayout.ExpandWidth(true)
|
||||
);
|
||||
|
||||
_list.DoList(rect);
|
||||
|
||||
EditorGUILayout.Space(8);
|
||||
|
||||
Localization.ShowLanguageUI();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78859e260e8e426bb4673c9077ed5d7b
|
||||
timeCreated: 1683272729
|
Loading…
Reference in New Issue
Block a user