Add additional bone proxy validation

Closes: #85
This commit is contained in:
bd_ 2022-11-19 19:12:13 -08:00
parent 999add24c9
commit 4ce3223844
4 changed files with 46 additions and 4 deletions

View File

@ -28,13 +28,20 @@ namespace nadena.dev.modular_avatar.core.editor
{ {
internal class BoneProxyProcessor internal class BoneProxyProcessor
{ {
internal enum ValidationResult
{
OK,
MovingTarget,
NotInAvatar
}
internal void OnPreprocessAvatar(GameObject avatarGameObject) internal void OnPreprocessAvatar(GameObject avatarGameObject)
{ {
var boneProxies = avatarGameObject.GetComponentsInChildren<ModularAvatarBoneProxy>(true); var boneProxies = avatarGameObject.GetComponentsInChildren<ModularAvatarBoneProxy>(true);
foreach (var proxy in boneProxies) foreach (var proxy in boneProxies)
{ {
if (proxy.target != null) if (proxy.target != null && ValidateTarget(avatarGameObject, proxy.target) == ValidationResult.OK)
{ {
var oldPath = RuntimeUtil.AvatarRootPath(proxy.gameObject); var oldPath = RuntimeUtil.AvatarRootPath(proxy.gameObject);
Transform transform = proxy.transform; Transform transform = proxy.transform;
@ -51,5 +58,25 @@ namespace nadena.dev.modular_avatar.core.editor
Object.DestroyImmediate(proxy); Object.DestroyImmediate(proxy);
} }
} }
internal static ValidationResult ValidateTarget(GameObject avatarGameObject, Transform proxyTarget)
{
var avatar = avatarGameObject.transform;
var node = proxyTarget;
while (node != null && node != avatar)
{
if (node.GetComponent<ModularAvatarMergeArmature>() != null ||
node.GetComponent<ModularAvatarBoneProxy>() != null)
{
return ValidationResult.MovingTarget;
}
node = node.parent;
}
if (node == null) return ValidationResult.NotInAvatar;
else return ValidationResult.OK;
}
} }
} }

View File

@ -55,6 +55,15 @@ namespace nadena.dev.modular_avatar.core.editor
var virtObj = new SerializedObject(objRefs); var virtObj = new SerializedObject(objRefs);
var virtProp = virtObj.FindProperty(nameof(TempObjRef.target)); 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(); EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(virtProp, G("boneproxy.target")); EditorGUILayout.PropertyField(virtProp, G("boneproxy.target"));
@ -65,7 +74,9 @@ namespace nadena.dev.modular_avatar.core.editor
{ {
var t = (ModularAvatarBoneProxy) targets[i]; var t = (ModularAvatarBoneProxy) targets[i];
Undo.RecordObjects(targets, "Set targets"); Undo.RecordObjects(targets, "Set targets");
t.target = ((TempObjRef) objRefs[i]).target; var xform = ((TempObjRef) objRefs[i]).target;
if (RuntimeUtil.FindAvatarInParents(xform)?.gameObject != parentAvatar) continue;
t.target = xform;
} }
} }
} }

View File

@ -45,5 +45,7 @@
"blendshape.mesh": "Mesh", "blendshape.mesh": "Mesh",
"blendshape.source": "Source blendshape", "blendshape.source": "Source blendshape",
"blendshape.target": "Target blendshape", "blendshape.target": "Target blendshape",
"hint.not_in_avatar": "This component needs to be placed inside your avatar to work properly." "hint.not_in_avatar": "This component needs to be placed inside your avatar to work properly.",
"boneproxy.err.MovingTarget": "You cannot specify a target object that will be moved by other Modular Avatar components",
"boneproxy.err.NotInAvatar": "You must specify an object that is in the avatar"
} }

View File

@ -45,5 +45,7 @@
"blendshape.mesh": "メッシュ", "blendshape.mesh": "メッシュ",
"blendshape.source": "元メッシュのブレンドシェープ", "blendshape.source": "元メッシュのブレンドシェープ",
"blendshape.target": "このメッシュのブレンドシェープ", "blendshape.target": "このメッシュのブレンドシェープ",
"hint.not_in_avatar": "このコンポーネントが正しく動作するには、アバター内に配置する必要があります。" "hint.not_in_avatar": "このコンポーネントが正しく動作するには、アバター内に配置する必要があります。",
"boneproxy.err.MovingTarget": "他のモジュラーアバターコンポーネントで移動されるオブジェクトを指定できません。",
"boneproxy.err.NotInAvatar": "アバター内のオブジェクトを指定してください。"
} }