Skip to content

Commit

Permalink
Revert "applied parameter compression"
Browse files Browse the repository at this point in the history
This reverts commit df7376f.
  • Loading branch information
cstria0106 committed Mar 2, 2024
1 parent 6e0ec6f commit 5d59263
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 179 deletions.
189 changes: 55 additions & 134 deletions Editor/Generator/AnimationGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Collections.Immutable;
using System.Linq;
using dog.miruku.inventory.runtime;
using PlasticGui.Configuration.OAuth;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
Expand All @@ -26,8 +25,8 @@ public static IEnumerable<AnimatorController> GenerateControllers(InventoryNode
}
else
{
var clips = GenerateNonUniqueClips(node);
controllers = GenerateNonUniqueAnimatorControllers(clips);
var (enabledClips, disabledClips) = GenerateNonUniqueClips(node);
controllers = GenerateNonUniqueAnimatorControllers(enabledClips, disabledClips);
}
}

Expand Down Expand Up @@ -132,20 +131,22 @@ private static AnimationClip GenerateAnimationClip(
return clip;
}

private static Dictionary<InventoryNode, (AnimationClip, AnimationClip)> GenerateNonUniqueClips(InventoryNode node)

private static (Dictionary<InventoryNode, AnimationClip>, Dictionary<InventoryNode, AnimationClip>) GenerateNonUniqueClips(InventoryNode node)
{
var clips = new Dictionary<InventoryNode, (AnimationClip, AnimationClip)>();
var enabledClips = new Dictionary<InventoryNode, AnimationClip>();
var disabledClips = new Dictionary<InventoryNode, AnimationClip>();

foreach (var child in node.Children)
{
var enabledClip = GenerateAnimationClip($"{child.Key}_enabled", child.Avatar, child.Value.GameObjects, child.Value.ObjectsToDisable, child.Value.AdditionalAnimations, child.Value.BlendShapesToChange, child.Value.MaterialsToReplace);
var disabledClip = GenerateAnimationClip($"{child.Key}_disabled", child.Avatar, new GameObject[] { }, child.Value.GameObjects);
clips.Add(child, (enabledClip, disabledClip));
enabledClips.Add(child, GenerateAnimationClip($"{child.Key}_enabled", child.Avatar, child.Value.GameObjects, child.Value.ObjectsToDisable, child.Value.AdditionalAnimations, child.Value.BlendShapesToChange, child.Value.MaterialsToReplace));
disabledClips.Add(child, GenerateAnimationClip($"{child.Key}_disabled", child.Avatar, new GameObject[] { }, child.Value.GameObjects));
}

return clips;
return (enabledClips, disabledClips);
}


private static (Dictionary<InventoryNode, AnimationClip>, AnimationClip) GenerateUniqueClips(InventoryNode node)
{
var allObjects = node.Children.SelectMany(child => child.Value.GameObjects).ToImmutableHashSet();
Expand Down Expand Up @@ -193,63 +194,63 @@ private static void SetupParameterDrivers(AnimatorState state, InventoryNode nod
driver.parameters.AddRange(node.Value.ParameterDriverBindings.Select(e => e.parameter));
}

private static void AddEncodedEqualsConditions(AnimatorStateTransition transition, string parameterName, int value, int bits, Action<string, AnimatorControllerParameterType> addParameter)
{
foreach (var (name, bit) in Encode(parameterName, bits, value))
{
transition.AddCondition(bit == 1 ? AnimatorConditionMode.If : AnimatorConditionMode.IfNot, 0, name);
addParameter(name, AnimatorControllerParameterType.Bool);
}
}

private static List<AnimatorStateTransition> AddTransitionsToDisable(InventoryNode node, Func<AnimatorStateTransition> addTransition, Action<string, AnimatorControllerParameterType> addParameter, bool recursive = true)
private static void AddTransitionsToDisable(InventoryNode node, Func<AnimatorStateTransition> addTransition, Action<string, AnimatorControllerParameterType> addParameter)
{
var transitions = new List<AnimatorStateTransition>();
if (node.IsItem)
{
foreach (var (name, bit) in Encode(node.ParameterName, node.ParameterBits, node.ParameterValue))
var transition = addTransition();
SetupTransition(transition);
if (node.ParentIsUnique)
{
var transition = addTransition();
SetupTransition(transition);
transition.AddCondition(bit == 0 ? AnimatorConditionMode.If : AnimatorConditionMode.IfNot, 0, name);
addParameter(name, AnimatorControllerParameterType.Bool);
transitions.Add(transition);
transition.AddCondition(AnimatorConditionMode.NotEqual, node.Index, node.ParameterName);
addParameter(node.ParameterName, AnimatorControllerParameterType.Int);
}
else
{
transition.AddCondition(AnimatorConditionMode.IfNot, 0, node.ParameterName);
addParameter(node.ParameterName, AnimatorControllerParameterType.Bool);
}
}

if (recursive && node.Parent != null)
if (node.Parent != null)
{
transitions.AddRange(AddTransitionsToDisable(node.Parent, addTransition, addParameter));
AddTransitionsToDisable(node.Parent, addTransition, addParameter);
}

return transitions;
}

private static void SetupTransitionConditionsToEnable(InventoryNode node, AnimatorStateTransition transition, Action<string, AnimatorControllerParameterType> addParameter, bool recursive = true)
private static void SetupTransitionConditionsToEnable(InventoryNode node, AnimatorStateTransition transition, Action<string, AnimatorControllerParameterType> addParameter)
{
if (node.IsItem)
{
AddEncodedEqualsConditions(transition, node.ParameterName, node.ParameterValue, node.ParameterBits, addParameter);
if (node.ParentIsUnique)
{
transition.AddCondition(AnimatorConditionMode.Equals, node.Index, node.ParameterName);
addParameter(node.ParameterName, AnimatorControllerParameterType.Int);
}
else
{
transition.AddCondition(AnimatorConditionMode.If, 0, node.ParameterName);
addParameter(node.ParameterName, AnimatorControllerParameterType.Bool);
}
}

if (recursive && node.Parent != null)
if (node.Parent != null)
{
SetupTransitionConditionsToEnable(node.Parent, transition, addParameter);
}
}

private static AnimatorStateTransition AddTransitionToEnable(InventoryNode node, Func<AnimatorStateTransition> addTransition, Action<string, AnimatorControllerParameterType> addParameter, bool recursive = true)
private static AnimatorStateTransition AddTransitionToEnable(InventoryNode node, Func<AnimatorStateTransition> addTransition, Action<string, AnimatorControllerParameterType> addParameter)
{
var transition = addTransition();
SetupTransition(transition);
SetupTransitionConditionsToEnable(node, transition, addParameter, recursive);
SetupTransitionConditionsToEnable(node, transition, addParameter);
return transition;
}

// generate animations for node itself
private static AnimatorController GenerateNonUniqueAnimatorController(InventoryNode node, AnimationClip enabledClip, AnimationClip disabledClip)
{
var path = AssetUtil.GetPath($"Controllers/{node.Key}/Toggle.controller");
var path = AssetUtil.GetPath($"Controllers/{node.Key}.controller");
var controller = AnimatorController.CreateAnimatorControllerAtPath(path);
controller.RemoveLayer(0);
controller.AddLayer(node.Key);
Expand All @@ -258,7 +259,6 @@ private static AnimatorController GenerateNonUniqueAnimatorController(InventoryN
layer.stateMachine.anyStatePosition = new Vector3(-200, 50);

var parameters = new Dictionary<string, AnimatorControllerParameterType>();
parameters[node.ParameterName] = AnimatorControllerParameterType.Int;

{
// setup idle
Expand All @@ -281,43 +281,37 @@ private static AnimatorController GenerateNonUniqueAnimatorController(InventoryN
(name, type) => parameters[name] = type);
SetupParameterDrivers(enabledState, node);
}

{
disabledState.motion = disabledClip;
var transitions = AddTransitionsToDisable(node,
var transition = AddTransitionToEnable(node.Parent,
() => layer.stateMachine.AddAnyStateTransition(disabledState),
(name, type) => parameters[name] = type,
recursive: false);
// this state requires parent to be enabled
foreach (var transition in transitions)
{
SetupTransitionConditionsToEnable(node.Parent, transition, (name, type) => parameters[name] = type, recursive: true);
}
(name, type) => parameters[name] = type);
transition.AddCondition(AnimatorConditionMode.IfNot, 0, node.ParameterName);
}

foreach (var parameter in parameters)
{
controller.AddParameter(parameter.Key, parameter.Value);
}

SetupEncoder(controller, node.ParameterName, 1, 1);
SetupDecoder(controller, node.ParameterName, 1, 1);

EditorUtility.SetDirty(controller);
AssetDatabase.SaveAssets();
return controller;
}

// generate animations for node.Children
private static List<AnimatorController> GenerateNonUniqueAnimatorControllers(
Dictionary<InventoryNode, (AnimationClip, AnimationClip)> clips
) => clips.Keys
Dictionary<InventoryNode, AnimationClip> enabledClips,
Dictionary<InventoryNode, AnimationClip> disabledClips
) => enabledClips.Keys
.Where(node => node.IsItem)
.Select(node => GenerateNonUniqueAnimatorController(node, clips[node].Item1, clips[node].Item2))
.Select(node => GenerateNonUniqueAnimatorController(node, enabledClips[node], disabledClips[node]))
.ToList();

// generate animations for node.Children
private static AnimatorController GenerateUniqueAnimatorController(InventoryNode node, Dictionary<InventoryNode, AnimationClip> clips, AnimationClip disableAllClip)
{
var path = AssetUtil.GetPath($"Controllers/{node.Key}.controller");
var path = AssetUtil.GetPath($"Controllers/{node.Key}_select.controller");
var controller = AnimatorController.CreateAnimatorControllerAtPath(path);
controller.RemoveLayer(0);
controller.AddLayer(node.Key);
Expand All @@ -326,7 +320,6 @@ private static AnimatorController GenerateUniqueAnimatorController(InventoryNode
layer.stateMachine.anyStatePosition = new Vector3(-200, 50);

var parameters = new Dictionary<string, AnimatorControllerParameterType>();
parameters[node.Key] = AnimatorControllerParameterType.Int;

{
// setup idle
Expand Down Expand Up @@ -355,12 +348,13 @@ private static AnimatorController GenerateUniqueAnimatorController(InventoryNode
defaultState.motion = disableAllClip;
}

var transition = layer.stateMachine.AddAnyStateTransition(defaultState);
SetupTransition(transition);
// conditions of parents to be enabled
SetupTransitionConditionsToEnable(node, transition, (name, type) => parameters[name] = type);
// and itself
AddEncodedEqualsConditions(transition, node.Key, 0, node.ChildrenBits, (name, type) => parameters[name] = type);
parameters[node.IndexKey] = AnimatorControllerParameterType.Int;

// transition to default when parent is enabled and index is 0 (default)
var enableTransition = AddTransitionToEnable(node,
() => layer.stateMachine.AddAnyStateTransition(defaultState),
(name, type) => parameters[name] = type);
enableTransition.AddCondition(AnimatorConditionMode.Equals, 0, node.IndexKey);
}

var position = new Vector3(0, 100);
Expand All @@ -385,82 +379,9 @@ private static AnimatorController GenerateUniqueAnimatorController(InventoryNode
controller.AddParameter(parameter.Key, parameter.Value);
}

SetupEncoder(controller, node.Key, node.ChildrenBits, node.MaxChildrenIndex);
SetupDecoder(controller, node.Key, node.ChildrenBits, node.MaxChildrenIndex);

EditorUtility.SetDirty(controller);
AssetDatabase.SaveAssets();
return controller;
}

private static string GetEncodedParameterName(string parameterName, int bit) => $"{parameterName}/Bits/{bit}";

public static List<(string, int)> Encode(string parameterName, int bits, int value)
{
var list = new List<(string, int)>();
for (int i = 0; i < bits; i++)
{
int bit = (value >> (bits - 1 - i)) & 1;
list.Add((GetEncodedParameterName(parameterName, i), bit));
}
return list;
}

private static void SetupEncoder(AnimatorController controller, string parameterName, int bits, int maxIndex)
{
controller.AddLayer("Encoder");
var layer = controller.layers[controller.layers.Length - 1];

layer.stateMachine.entryPosition = new Vector3(0, 0);
layer.stateMachine.anyStatePosition = new Vector3(0, 50);

for (int i = 0; i <= maxIndex; i++)
{
var state = layer.stateMachine.AddState(i.ToString(), new Vector3(200, i * 50));
if (i == 0) layer.stateMachine.defaultState = state;
var transition = layer.stateMachine.AddAnyStateTransition(state);
SetupTransition(transition);

transition.AddCondition(AnimatorConditionMode.Equals, i, parameterName);
var driver = state.AddStateMachineBehaviour<VRCAvatarParameterDriver>();
foreach (var (name, value) in Encode(parameterName, bits, i))
{
driver.parameters.Add(new VRC_AvatarParameterDriver.Parameter()
{
name = name,
value = value
});
}
}
}

private static void SetupDecoder(AnimatorController controller, string parameterName, int bits, int maxIndex)
{
controller.AddLayer("Decoder");
var layer = controller.layers[controller.layers.Length - 1];

layer.stateMachine.entryPosition = new Vector3(0, 0);
layer.stateMachine.anyStatePosition = new Vector3(0, 50);

for (int i = 0; i <= maxIndex; i++)
{
var state = layer.stateMachine.AddState(i.ToString(), new Vector3(200, i * 50));
if (i == 0) layer.stateMachine.defaultState = state;
var transition = layer.stateMachine.AddAnyStateTransition(state);
SetupTransition(transition);

foreach (var (name, value) in Encode(parameterName, bits, i))
{
transition.AddCondition(value == 1 ? AnimatorConditionMode.If : AnimatorConditionMode.IfNot, 0, name);
}

var driver = state.AddStateMachineBehaviour<VRCAvatarParameterDriver>();
driver.parameters.Add(new VRC_AvatarParameterDriver.Parameter()
{
name = parameterName,
value = i
});
}
}
}
}
41 changes: 14 additions & 27 deletions Editor/Generator/MenuGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,56 +52,43 @@ private static void CreateMAMenu(InventoryNode node, Transform parent)
if (node.IsInventory)
{
var submenu = AddSubmenu(node.Value.Name, node.Value.Icon, parent);
if (node.IsItem) AddToggleMenu(Localization.Get("enable"), node.Value.Icon, node.ParameterName, node.ParameterValue, submenu.transform);
if (node.IsItem) AddToggleMenu(Localization.Get("enable"), node.Value.Icon, node.ParameterName, node.ParameterIntValue, submenu.transform);
foreach (var child in node.Children)
{
CreateMAMenu(child, submenu.transform);
}
}
else if (node.IsItem)
{
AddToggleMenu(node.Value.Name, node.Value.Icon, node.ParameterName, node.ParameterValue, parent);
AddToggleMenu(node.Value.Name, node.Value.Icon, node.ParameterName, node.ParameterIntValue, parent);
}
}

private static Dictionary<string, ParameterConfig> GetMAParameterConfigs(InventoryNode node, Dictionary<string, ParameterConfig> configs = null)
{
if (configs == null) configs = new Dictionary<string, ParameterConfig>();

if (node.IsItem)
if (node.ParameterName != null && !configs.ContainsKey(node.ParameterName))
{
configs[node.ParameterName] = new ParameterConfig()
{
nameOrPrefix = node.ParameterName,
syncType = ParameterSyncType.NotSynced,
defaultValue = node.ParameterDefault,
saved = false,
localOnly = false,
};

foreach (var (name, defaultValue) in AnimationGenerator.Encode(node.ParameterName, node.ParameterBits, node.ParameterDefault))
{
configs[name] =
new ParameterConfig()
{
nameOrPrefix = name,
syncType = ParameterSyncType.Bool,
defaultValue = defaultValue,
saved = true,
localOnly = false
};
}
configs[node.ParameterName] =
new ParameterConfig()
{
nameOrPrefix = node.ParameterName,
syncType = node.ParameterIsIndex ? ParameterSyncType.Int : ParameterSyncType.Bool,
defaultValue = node.ParameterDefaultValue,
saved = true,
localOnly = false
};
}


foreach (var child in node.Children) configs = GetMAParameterConfigs(child, configs);

return configs;
}

private static void CreateMAParameters(InventoryNode node)
{
var parametersObject = new GameObject($"Parameters");
var parametersObject = new GameObject($"{node.Root.Index}_parameters");
parametersObject.transform.SetParent(node.Root.Value.transform, false);
var parameters = parametersObject.AddComponent<ModularAvatarParameters>();
var configs = GetMAParameterConfigs(node);
Expand All @@ -118,7 +105,7 @@ private static void CreateMAMergeAnimator(InventoryNode node, IEnumerable<Animat
mergeAnimator.layerType = VRCAvatarDescriptor.AnimLayerType.FX;
mergeAnimator.deleteAttachedAnimator = true;
mergeAnimator.pathMode = MergeAnimatorPathMode.Absolute;
mergeAnimator.matchAvatarWriteDefaults = false;
mergeAnimator.matchAvatarWriteDefaults = true;
mergeAnimator.layerPriority = node.Value.LayerPriority;
}
}
Expand Down
Loading

0 comments on commit 5d59263

Please sign in to comment.