feat: add API to trigger Setup Outfit processing (#1018)

Closes: #907
This commit is contained in:
bd_ 2024-08-19 20:08:36 -07:00 committed by GitHub
parent a42295e0e6
commit 8ed649f9a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 59 additions and 40 deletions

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using nadena.dev.modular_avatar.ui;
using UnityEditor;
using UnityEngine;
@ -113,25 +114,37 @@ namespace nadena.dev.modular_avatar.core.editor
}
}
internal static class EasySetupOutfit
public static class SetupOutfit
{
private static string[] errorMessageGroups;
private static string errorHeader;
[MenuItem(UnityMenuItems.GameObject_SetupOutfit, false, UnityMenuItems.GameObject_SetupOutfitOrder)]
internal static void SetupOutfit(MenuCommand cmd)
internal static void SetupOutfitMenu(MenuCommand cmd)
{
if (!ValidateSetupOutfit())
var outfitRoot = cmd.context as GameObject;
SetupOutfitUI(outfitRoot);
}
/// <summary>
/// Executes the `Setup Outfit` operation, as if the user selected `outfitRoot` and ran Setup Outfit from the
/// context menu. Any errors encountered will trigger a popup error window.
/// </summary>
/// <param name="outfitRoot"></param>
[PublicAPI]
public static void SetupOutfitUI(GameObject outfitRoot)
{
if (!ValidateSetupOutfit(outfitRoot))
{
ESOErrorWindow.Show(errorHeader, errorMessageGroups);
return;
}
if (!FindBones(cmd.context,
if (!FindBones(outfitRoot,
out var avatarRoot, out var avatarHips, out var outfitHips)
) return;
var outfitRoot = cmd.context as GameObject;
var avatarArmature = avatarHips.transform.parent;
var outfitArmature = outfitHips.transform.parent;
@ -362,14 +375,21 @@ namespace nadena.dev.modular_avatar.core.editor
foreach (var obj in Selection.objects)
{
errorHeader = S_f("setup_outfit.err.header", obj.name);
if (!(obj is GameObject gameObj)) return false;
if (!ValidateSetupOutfit(gameObj)) return false;
}
return true;
}
private static bool ValidateSetupOutfit(GameObject gameObj)
{
Object obj;
errorHeader = S_f("setup_outfit.err.header", gameObj.name);
var xform = gameObj.transform;
if (!FindBones(obj, out var _, out var _, out var outfitHips))
{
return false;
}
if (!FindBones(gameObj, out var _, out var _, out var outfitHips)) return false;
// Some users have been accidentally running Setup Outfit on the avatar itself, and/or nesting avatar
// descriptors when transplanting outfits. Block this (and require that there be only one avdesc) by
@ -378,7 +398,7 @@ namespace nadena.dev.modular_avatar.core.editor
var nearestAvatarTransform = RuntimeUtil.FindAvatarTransformInParents(xform);
if (nearestAvatarTransform == null)
{
errorMessageGroups = new string[]
errorMessageGroups = new[]
{
S_f("setup_outfit.err.no_avatar_descriptor", xform.gameObject.name)
};
@ -387,7 +407,7 @@ namespace nadena.dev.modular_avatar.core.editor
if (nearestAvatarTransform == xform)
{
errorMessageGroups = new string[]
errorMessageGroups = new[]
{ S_f("setup_outfit.err.run_on_avatar_itself", xform.gameObject.name) };
return false;
}
@ -395,13 +415,12 @@ namespace nadena.dev.modular_avatar.core.editor
var parent = nearestAvatarTransform.parent;
if (parent != null && RuntimeUtil.FindAvatarTransformInParents(parent) != null)
{
errorMessageGroups = new string[]
errorMessageGroups = new[]
{
S_f("setup_outfit.err.multiple_avatar_descriptors", xform.gameObject.name)
};
return false;
}
}
return true;
}

View File

@ -55,7 +55,7 @@ public class ArmatureConfusionTest : TestBase
// Now do a setup outfit operation
Selection.activeGameObject = inner;
EasySetupOutfit.SetupOutfit(new MenuCommand(inner));
SetupOutfit.SetupOutfitUI(inner);
// Verify that we're not confused anymore
Assert.AreSame(

View File

@ -22,7 +22,7 @@ public class PreferFirstHipsMatch : TestBase
var outfit_armature = CreateChild(outfit, "Armature");
var outfit_hips = CreateChild(outfit_armature, "Hips");
Assert.IsTrue(EasySetupOutfit.FindBones(outfit, out var det_av_root, out var det_av_hips, out var det_outfit_hips));
Assert.IsTrue(SetupOutfit.FindBones(outfit, out var det_av_root, out var det_av_hips, out var det_outfit_hips));
Assert.AreSame(root, det_av_root);
Assert.AreSame(root_hips, det_av_hips);
Assert.AreSame(outfit_hips, det_outfit_hips);