avatar/Assets/VRCFury/Scripts/Editor/VF/Feature/AnimatorLayerControlOffsetBuilder.cs

80 lines
3.8 KiB
C#

using System.Collections.Generic;
using System.Linq;
using UnityEditor.Animations;
using UnityEngine;
using VF.Builder;
using VF.Feature.Base;
using VRC.SDK3.Avatars.Components;
using VRC.SDKBase;
namespace VF.Feature {
/**
* This builder is responsible for correcting any AnimatorLayerControl behaviours in
* the animators which may have been broken by VRCFury adding / deleting layers
* while doing other things.
*/
public class AnimatorLayerControlOffsetBuilder : FeatureBuilder {
private Dictionary<VRCAnimatorLayerControl, AnimatorStateMachine> mapping
= new Dictionary<VRCAnimatorLayerControl, AnimatorStateMachine>();
[FeatureBuilderAction(FeatureOrder.AnimatorLayerControlRecordBase)]
public void RecordBase() {
RegisterControllerSet(manager.GetAllUsedControllers().Select(c => (c.GetType(), c.GetRaw())));
}
[FeatureBuilderAction(FeatureOrder.AnimatorLayerControlFix)]
public void Fix() {
var smToTypeAndNumber = new Dictionary<AnimatorStateMachine, (VRCAvatarDescriptor.AnimLayerType, int)>();
foreach (var c in manager.GetAllUsedControllers()) {
foreach (var (i,l) in c.GetLayers().Select((l,i) => (i,l))) {
smToTypeAndNumber[l] = (c.GetType(), i);
}
}
foreach (var c in manager.GetAllUsedControllers()) {
foreach (var l in c.GetLayers()) {
AnimatorIterator.ForEachBehaviour(l, (b, add) => {
if (!(b is VRCAnimatorLayerControl control)) return true;
if (!mapping.TryGetValue(control, out var targetSm)) {
Debug.LogError("Removing invalid AnimatorLayerControl (not found in mapping??) " + b);
return false;
}
if (!smToTypeAndNumber.TryGetValue(targetSm, out var pair)) {
Debug.LogError("Removing invalid AnimatorLayerControl (target sm has disappeared) " + b);
return false;
}
var (newType, newI) = pair;
var newCastedType = VRCFEnumUtils.Parse<VRC_AnimatorLayerControl.BlendableLayer>(
VRCFEnumUtils.GetName(newType));
Debug.LogWarning($"Rewriting {b} from {control.playable}:{control.layer} to {newCastedType}:{newI}");
control.playable = newCastedType;
control.layer = newI;
return true;
});
}
}
}
public void RegisterControllerSet(IEnumerable<(VRCAvatarDescriptor.AnimLayerType, AnimatorController)> set) {
foreach (var (type, controller) in set) {
foreach (var layer in controller.layers) {
AnimatorIterator.ForEachBehaviour(layer.stateMachine, (b, add) => {
if (b is VRCAnimatorLayerControl control) {
var targetController = set
.Where(tuple =>
VRCFEnumUtils.GetName(tuple.Item1) == VRCFEnumUtils.GetName(control.playable))
.Select(tuple => tuple.Item2)
.FirstOrDefault();
if (targetController == null) return false;
if (control.layer < 0 || control.layer >= targetController.layers.Length) return false;
var targetSm = targetController.layers[control.layer].stateMachine;
mapping[control] = targetSm;
}
return true;
});
}
}
}
}
}