diff --git a/Editor/Inspector/MergeArmatureEditor.cs b/Editor/Inspector/MergeArmatureEditor.cs index 3785a608..0fd215b4 100644 --- a/Editor/Inspector/MergeArmatureEditor.cs +++ b/Editor/Inspector/MergeArmatureEditor.cs @@ -84,6 +84,7 @@ namespace nadena.dev.modular_avatar.core.editor } private bool posResetOptionFoldout = false; + private bool posReset_convertATPose = true; private bool posReset_adjustRotation = false; private bool posReset_adjustScale = false; private bool posReset_heuristicRootScale = true; @@ -134,14 +135,17 @@ namespace nadena.dev.modular_avatar.core.editor MessageType.Info ); + posReset_heuristicRootScale = EditorGUILayout.ToggleLeft( + G("merge_armature.reset_pos.heuristic_scale"), + posReset_heuristicRootScale); + posReset_convertATPose = EditorGUILayout.ToggleLeft( + G("merge_armature.reset_pos.convert_atpose"), + posReset_convertATPose); posReset_adjustRotation = EditorGUILayout.ToggleLeft( G("merge_armature.reset_pos.adjust_rotation"), posReset_adjustRotation); posReset_adjustScale = EditorGUILayout.ToggleLeft(G("merge_armature.reset_pos.adjust_scale"), posReset_adjustScale); - posReset_heuristicRootScale = EditorGUILayout.ToggleLeft( - G("merge_armature.reset_pos.heuristic_scale"), - posReset_heuristicRootScale); if (GUILayout.Button(G("merge_armature.reset_pos.execute"))) { @@ -188,6 +192,11 @@ namespace nadena.dev.modular_avatar.core.editor } } + if (posReset_convertATPose) + { + SetupOutfit.FixAPose(RuntimeUtil.FindAvatarTransformInParents(mergeTarget.transform).gameObject, mama.transform, false); + } + if (posReset_heuristicRootScale && !suppressRootScale) { AdjustRootScale(); @@ -279,4 +288,4 @@ namespace nadena.dev.modular_avatar.core.editor } } } -} \ No newline at end of file +} diff --git a/Editor/Localization/en-US.json b/Editor/Localization/en-US.json index bc7e8ec8..8d84f379 100644 --- a/Editor/Localization/en-US.json +++ b/Editor/Localization/en-US.json @@ -86,6 +86,7 @@ "merge_armature.lockmode.bidirectional.body": "The base armature and the merged armature will always have the same position. This is useful when creating animations that are meant to target the base armature. In order to activate this, your armatures must already be in the exact same position.", "merge_armature.reset_pos": "Reset position to base avatar", "merge_armature.reset_pos.info": "This command will force the position of all bones in the outfit to match that of the base avatar. This can be helpful as a starting point for installing outfits not set up for your current avatar.", + "merge_armature.reset_pos.convert_atpose": "Convert A-Pose/T-Pose to match base avatar", "merge_armature.reset_pos.adjust_rotation": "Also set rotation to base avatar", "merge_armature.reset_pos.adjust_scale": "Also set local scale to base avatar", "merge_armature.reset_pos.execute": "Do it!", diff --git a/Editor/Localization/ja-JP.json b/Editor/Localization/ja-JP.json index 94c6022a..95c10a1b 100644 --- a/Editor/Localization/ja-JP.json +++ b/Editor/Localization/ja-JP.json @@ -82,6 +82,7 @@ "merge_armature.lockmode.bidirectional.body": "アバターと統合されるアーマチュアは常に同じ位置になります。元のアバターを操作するアニメーションを作る時に便利かもしれません。有効にするためには、統合されるアーマチュアの位置を統合先と同じにしておく必要があります。", "merge_armature.reset_pos": "位置を元アバターに合わせてリセット", "merge_armature.reset_pos.info": "衣装のボーンの位置をアバターのボーンの位置に合わせます。非対応衣装を導入する際、アバウトに位置を合わせるのに便利です。", + "merge_armature.reset_pos.convert_atpose": "Aポーズ/Tポーズを合わせる", "merge_armature.reset_pos.adjust_rotation": "回転も合わせる", "merge_armature.reset_pos.adjust_scale": "スケールも合わせる", "merge_armature.reset_pos.execute": "実行", diff --git a/Editor/SetupOutfit.cs b/Editor/SetupOutfit.cs index 922fbc74..ba69ed9f 100644 --- a/Editor/SetupOutfit.cs +++ b/Editor/SetupOutfit.cs @@ -229,7 +229,7 @@ namespace nadena.dev.modular_avatar.core.editor } } - private static void FixAPose(GameObject avatarRoot, Transform outfitArmature) + internal static void FixAPose(GameObject avatarRoot, Transform outfitArmature, bool strictMode = true) { var mergeArmature = outfitArmature.GetComponent(); if (mergeArmature == null) return; @@ -249,7 +249,7 @@ namespace nadena.dev.modular_avatar.core.editor { var lowerArm = (HumanBodyBones)((int)arm + 2); - // check if the rotation of the arm differs, but distances and origin point are the same + // check if the rotation of the arm differs(, but distances and origin point are the same when strictMode) var avatarArm = rootAnimator.GetBoneTransform(arm); var outfitArm = avatarToOutfit(avatarArm); @@ -259,22 +259,27 @@ namespace nadena.dev.modular_avatar.core.editor if (outfitArm == null) return; if (outfitLowerArm == null) return; - if ((avatarArm.position - outfitArm.position).magnitude > 0.001f) return; + if (strictMode) + { + if ((avatarArm.position - outfitArm.position).magnitude > 0.001f) return; - // check relative distance to lower arm as well - var avatarArmLength = (avatarLowerArm.position - avatarArm.position).magnitude; - var outfitArmLength = (outfitLowerArm.position - outfitArm.position).magnitude; + // check relative distance to lower arm as well + var avatarArmLength = (avatarLowerArm.position - avatarArm.position).magnitude; + var outfitArmLength = (outfitLowerArm.position - outfitArm.position).magnitude; - if (Mathf.Abs(avatarArmLength - outfitArmLength) > 0.001f) return; + if (Mathf.Abs(avatarArmLength - outfitArmLength) > 0.001f) return; + } else { + if (Vector3.Dot((outfitLowerArm.position - outfitArm.position).normalized, (avatarLowerArm.position - avatarArm.position).normalized) > 0.999f) return; + } - // Rotate the outfit arm to ensure these two points match. + // Rotate the outfit arm to ensure these two bone orientations match. + Undo.RecordObject(outfitArm, "Convert A/T Pose"); var relRot = Quaternion.FromToRotation( outfitLowerArm.position - outfitArm.position, avatarLowerArm.position - avatarArm.position ); outfitArm.rotation = relRot * outfitArm.rotation; PrefabUtility.RecordPrefabInstancePropertyModifications(outfitArm); - EditorUtility.SetDirty(outfitArm); } Transform avatarToOutfit(Transform avBone)