avatar/Assets/VRCFury/Scripts/Editor/VF/Builder/VRCAvatarUtils.cs

97 lines
4.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Animations;
using VF.Builder.Exceptions;
using VRC.SDK3.Avatars.Components;
using VRC.SDK3.Avatars.ScriptableObjects;
namespace VF.Builder {
public class VRCAvatarUtils {
private static
IEnumerable<Tuple<AnimatorController, Action<AnimatorController>, VRCAvatarDescriptor.AnimLayerType>>
GetAllControllers(VRCAvatarDescriptor avatar, VRCAvatarDescriptor.CustomAnimLayer[] layers) {
var output =
new List<Tuple<AnimatorController, Action<AnimatorController>, VRCAvatarDescriptor.AnimLayerType>>();
for (var i = 0; i < layers.Length; i++) {
var layerNum = i;
var layer = layers[layerNum];
var type = layer.type;
var controller = (avatar.customizeAnimationLayers && !layer.isDefault)
? layer.animatorController as AnimatorController
: null;
Action<AnimatorController> Set = c => {
avatar.customizeAnimationLayers = true;
layer.isDefault = c == null;
layer.animatorController = c;
layers[layerNum] = layer;
EditorUtility.SetDirty(avatar);
};
output.Add(Tuple.Create(controller, Set, type));
}
return output;
}
public static IEnumerable<Tuple<AnimatorController, Action<AnimatorController>, VRCAvatarDescriptor.AnimLayerType>> GetAllControllers(VRCAvatarDescriptor avatar) {
return Enumerable.Concat(
GetAllControllers(avatar, avatar.baseAnimationLayers),
GetAllControllers(avatar, avatar.specialAnimationLayers));
}
public static AnimatorController GetAvatarController(VRCAvatarDescriptor avatar, VRCAvatarDescriptor.AnimLayerType type) {
AnimatorController foundLayer = null;
foreach (var layer in GetAllControllers(avatar)) {
if (layer.Item3 == type && layer.Item1 != null) {
if (foundLayer != null && foundLayer != layer.Item1) {
throw new VRCFBuilderException(
"Avatar contains multiple expression layers of type " + type +
" with different animators for each!" +
" This is a VRChat bug. You may need to 'reset' the playable layers on the avatar descriptor.");
}
foundLayer = layer.Item1;
}
}
return foundLayer;
}
public static void SetAvatarController(VRCAvatarDescriptor avatar, VRCAvatarDescriptor.AnimLayerType type, AnimatorController controller) {
var setOne = false;
foreach (var layer in GetAllControllers(avatar)) {
if (layer.Item3 == type) {
setOne = true;
layer.Item2.Invoke(controller);
}
}
if (!setOne) {
throw new VRCFBuilderException(
"Failed to find " + type +
" layer on avatar. You may need to 'reset' the playable layers on the avatar descriptor, or your FBX may not be configured with a 'humanoid' rig.");
}
}
public static VRCExpressionsMenu GetAvatarMenu(VRCAvatarDescriptor avatar) {
return avatar.customExpressions ? avatar.expressionsMenu : null;
}
public static void SetAvatarMenu(VRCAvatarDescriptor avatar, VRCExpressionsMenu menu) {
avatar.customExpressions = true;
avatar.expressionsMenu = menu;
EditorUtility.SetDirty(avatar);
}
public static VRCExpressionParameters GetAvatarParams(VRCAvatarDescriptor avatar) {
return avatar.customExpressions ? avatar.expressionParameters : null;
}
public static void SetAvatarParams(VRCAvatarDescriptor avatar, VRCExpressionParameters prms) {
avatar.customExpressions = true;
avatar.expressionParameters = prms;
EditorUtility.SetDirty(avatar);
}
}
}