mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-01-01 12:15:05 +08:00
6c4c0afb06
Closes: #655
162 lines
5.8 KiB
C#
162 lines
5.8 KiB
C#
#region
|
|
|
|
using System;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using static nadena.dev.modular_avatar.core.editor.Localization;
|
|
using Object = UnityEngine.Object;
|
|
|
|
#endregion
|
|
|
|
namespace nadena.dev.modular_avatar.core.editor
|
|
{
|
|
internal class TempObjRef : ScriptableObject
|
|
{
|
|
public Transform target;
|
|
}
|
|
|
|
[CustomPropertyDrawer(typeof(BoneProxyAttachmentMode))]
|
|
internal class BoneProxyAttachmentModeDrawer : EnumDrawer<BoneProxyAttachmentMode>
|
|
{
|
|
protected override string localizationPrefix => "boneproxy.attachment";
|
|
|
|
protected override Array enumValues => new object[]
|
|
{
|
|
BoneProxyAttachmentMode.AsChildAtRoot,
|
|
BoneProxyAttachmentMode.AsChildKeepWorldPose,
|
|
BoneProxyAttachmentMode.AsChildKeepRotation,
|
|
BoneProxyAttachmentMode.AsChildKeepPosition,
|
|
};
|
|
}
|
|
|
|
[CustomEditor(typeof(ModularAvatarBoneProxy))]
|
|
[CanEditMultipleObjects]
|
|
internal class BoneProxyEditor : MAEditorBase
|
|
{
|
|
private bool foldout = false;
|
|
|
|
private Object[] objRefs;
|
|
|
|
private void OnEnable()
|
|
{
|
|
objRefs = new Object[targets.Length];
|
|
for (int i = 0; i < targets.Length; i++)
|
|
{
|
|
objRefs[i] = CreateInstance<TempObjRef>();
|
|
}
|
|
}
|
|
|
|
protected override void OnInnerInspectorGUI()
|
|
{
|
|
GameObject parentAvatar = null;
|
|
|
|
bool suppressTarget = false;
|
|
for (int i = 0; i < targets.Length; i++)
|
|
{
|
|
var t = (ModularAvatarBoneProxy) targets[i];
|
|
var avTr = RuntimeUtil.FindAvatarTransformInParents(t.transform);
|
|
|
|
if (avTr != null && parentAvatar == null) parentAvatar = avTr.gameObject;
|
|
if (avTr == null || parentAvatar != avTr.gameObject)
|
|
{
|
|
suppressTarget = true;
|
|
break;
|
|
}
|
|
|
|
((TempObjRef) objRefs[i]).target = t.target;
|
|
}
|
|
|
|
if (suppressTarget)
|
|
{
|
|
foldout = true;
|
|
}
|
|
else
|
|
{
|
|
var virtObj = new SerializedObject(objRefs);
|
|
var virtProp = virtObj.FindProperty(nameof(TempObjRef.target));
|
|
|
|
if (virtProp.objectReferenceValue is Transform targetTransform)
|
|
{
|
|
var validationResult = BoneProxyProcessor.ValidateTarget(parentAvatar, targetTransform);
|
|
if (validationResult != BoneProxyProcessor.ValidationResult.OK)
|
|
{
|
|
EditorGUILayout.HelpBox(S("boneproxy.err." + validationResult), MessageType.Error);
|
|
}
|
|
}
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
EditorGUILayout.PropertyField(virtProp, G("boneproxy.target"));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
virtObj.ApplyModifiedPropertiesWithoutUndo();
|
|
for (int i = 0; i < targets.Length; i++)
|
|
{
|
|
var t = (ModularAvatarBoneProxy) targets[i];
|
|
Undo.RecordObjects(targets, "Set targets");
|
|
var xform = ((TempObjRef) objRefs[i]).target;
|
|
if (RuntimeUtil.FindAvatarTransformInParents(xform)?.gameObject != parentAvatar) continue;
|
|
t.target = xform;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < targets.Length; i++)
|
|
{
|
|
CheckAttachmentMode(targets[i] as ModularAvatarBoneProxy);
|
|
}
|
|
|
|
serializedObject.UpdateIfRequiredOrScript();
|
|
var p_attachmentMode = serializedObject.FindProperty(nameof(ModularAvatarBoneProxy.attachmentMode));
|
|
EditorGUI.BeginChangeCheck();
|
|
EditorGUILayout.PropertyField(p_attachmentMode, G("boneproxy.attachment"));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
serializedObject.ApplyModifiedProperties();
|
|
foreach (var target in targets)
|
|
{
|
|
var t = (ModularAvatarBoneProxy)target;
|
|
Undo.RecordObject(t.transform, "");
|
|
t.Update();
|
|
}
|
|
}
|
|
|
|
foldout = EditorGUILayout.Foldout(foldout, G("boneproxy.foldout.advanced"));
|
|
if (foldout)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
|
|
var p_boneReference = serializedObject.FindProperty(nameof(ModularAvatarBoneProxy.boneReference));
|
|
var p_subPath = serializedObject.FindProperty(nameof(ModularAvatarBoneProxy.subPath));
|
|
|
|
EditorGUILayout.PropertyField(p_boneReference, new GUIContent("Bone reference"));
|
|
EditorGUILayout.PropertyField(p_subPath, new GUIContent("Sub path"));
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
ShowLanguageUI();
|
|
}
|
|
|
|
private void CheckAttachmentMode(ModularAvatarBoneProxy boneProxy)
|
|
{
|
|
if (boneProxy.attachmentMode == BoneProxyAttachmentMode.Unset && boneProxy.target != null)
|
|
{
|
|
float posDelta = Vector3.Distance(boneProxy.transform.position, boneProxy.target.position);
|
|
float rotDelta = Quaternion.Angle(boneProxy.transform.rotation, boneProxy.target.rotation);
|
|
|
|
Undo.RecordObject(boneProxy, "Configuring bone proxy attachment mode");
|
|
if (posDelta > 0.001f || rotDelta > 0.001f)
|
|
{
|
|
boneProxy.attachmentMode = BoneProxyAttachmentMode.AsChildKeepWorldPose;
|
|
}
|
|
else
|
|
{
|
|
boneProxy.attachmentMode = BoneProxyAttachmentMode.AsChildAtRoot;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |