diff --git a/.gitignore b/.gitignore index bd07a94..a97bd77 100644 --- a/.gitignore +++ b/.gitignore @@ -396,3 +396,6 @@ VRC.Enums* /Assets /Assembly-CSharp.csproj /Assembly-CSharp-Editor.csproj +/Packages +*.csproj +.history \ No newline at end of file diff --git a/.vsconfig b/.vsconfig new file mode 100644 index 0000000..d70cd98 --- /dev/null +++ b/.vsconfig @@ -0,0 +1,6 @@ +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Workload.ManagedGame" + ] +} diff --git a/Assets/OSCmooth/Editor/OSCmoothAnimationHandler.cs b/Assets/OSCmooth/Editor/OSCmoothAnimationHandler.cs index 9b05f65..0d851b0 100644 --- a/Assets/OSCmooth/Editor/OSCmoothAnimationHandler.cs +++ b/Assets/OSCmooth/Editor/OSCmoothAnimationHandler.cs @@ -15,43 +15,38 @@ public static class OSCmoothAnimationHandler public static List _parameters; public static bool _writeDefaults; public static string _animExportDirectory; + public static string _binaryExportDirectory; public static void RemoveAllOSCmoothFromController() - { + { AnimUtil.RevertStateMachineParameters(_animatorController); AnimUtil.RemoveExtendedParametersInController("OSCm", _animatorController); AnimUtil.RemoveContainingLayersInController("OSCm", _animatorController); } + + public static void RemoveAllBinaryFromController() + { + + } + public static void CreateSmoothAnimationLayer() { - // Cleanup Animator before applying OSCmooth: - OSCmoothAnimationHandler.RemoveAllOSCmoothFromController(); // Creating new OSCmooth setup. AnimatorControllerLayer animLayer; - if (_writeDefaults) - animLayer = AnimUtil.CreateAnimLayerInController("_OSCmooth_Smoothing_WD_Gen", _animatorController); - else animLayer = AnimUtil.CreateAnimLayerInController("_OSCmooth_Smoothing_Gen", _animatorController); + animLayer = AnimUtil.CreateAnimLayerInController("_OSCmooth_Smoothing_Gen", _animatorController); // Creating a Direct BlendTree that will hold all of the smooth driver animations. This is to effectively create a 'sublayer' // system within the Direct BlendTree to tidy up the animator base layers from bloating up visually. AnimatorState[] state = new AnimatorState[2]; - if (_writeDefaults) - { - state[0] = animLayer.stateMachine.AddState("OSCmooth_Local_WD", new Vector3(30, 170, 0)); - state[1] = animLayer.stateMachine.AddState("OSCmooth_Net_WD", new Vector3(30, 170 + 60, 0)); - } - else - { - state[0] = animLayer.stateMachine.AddState("OSCmooth_Local", new Vector3(30, 170, 0)); - state[1] = animLayer.stateMachine.AddState("OSCmooth_Net", new Vector3(30, 170 + 60, 0)); - } + state[0] = animLayer.stateMachine.AddState("OSCmooth_Local", new Vector3(30, 170, 0)); + state[1] = animLayer.stateMachine.AddState("OSCmooth_Net", new Vector3(30, 170 + 60, 0)); - state[0].writeDefaultValues = _writeDefaults; - state[1].writeDefaultValues = _writeDefaults; + state[0].writeDefaultValues = true; + state[1].writeDefaultValues = true; var toRemoteState = state[0].AddTransition(state[1]); toRemoteState.duration = 0; @@ -68,12 +63,6 @@ public static void CreateSmoothAnimationLayer() var nameLocalWD = "OSCm_Local"; var nameRemoteWD = "OSCm_Remote"; - if (_writeDefaults) - { - nameLocalWD = "OSCm_Local_WD"; - nameRemoteWD = "OSCm_Remote_WD"; - } - var basisLocalBlendTree = new BlendTree() { blendType = BlendTreeType.Direct, @@ -101,14 +90,7 @@ public static void CreateSmoothAnimationLayer() // Creating a '1Set' parameter that holds a value of one at all times for the Direct BlendTree - if (_writeDefaults) - { - ParameterUtil.CheckAndCreateParameter("OSCm/BlendSet", _animatorController, AnimatorControllerParameterType.Float, 1f); - } - else - { - ParameterUtil.CheckAndCreateParameter("OSCm/BlendSet", _animatorController, AnimatorControllerParameterType.Float, 1f / (float)_parameters.Count); - } + ParameterUtil.CheckAndCreateParameter("OSCm/BlendSet", _animatorController, AnimatorControllerParameterType.Float, 1f); List localChildMotion = new List(); @@ -122,13 +104,8 @@ public static void CreateSmoothAnimationLayer() AnimUtil.RenameAllStateMachineInstancesOfBlendParameter(_animatorController, p.paramName, "OSCm/Proxy/" + p.paramName); } - var motionLocal = AnimUtil.CreateSmoothingBlendTree(_animatorController, animLayer.stateMachine, p.localSmoothness, p.paramName, p.flipInputOutput, (float)_parameters.Count, _animExportDirectory, "OSCm/Local/", "Smoother", "OSCm/Proxy/", "Proxy"); - var motionRemote = AnimUtil.CreateSmoothingBlendTree(_animatorController, animLayer.stateMachine, p.remoteSmoothness, p.paramName, p.flipInputOutput, (float)_parameters.Count, _animExportDirectory, "OSCm/Remote/", "SmootherRemote", "OSCm/Proxy/", "Proxy"); - if (_writeDefaults) - { - motionLocal = AnimUtil.CreateSmoothingBlendTree(_animatorController, animLayer.stateMachine, p.localSmoothness, p.paramName, p.flipInputOutput, 1f, _animExportDirectory, "OSCm/Local/", "SmootherWD", "OSCm/Proxy/", "Proxy"); - motionRemote = AnimUtil.CreateSmoothingBlendTree(_animatorController, animLayer.stateMachine, p.remoteSmoothness, p.paramName, p.flipInputOutput, 1f, _animExportDirectory, "OSCm/Remote/", "SmootherRemoteWD", "OSCm/Proxy/", "Proxy"); - } + var motionLocal = AnimUtil.CreateSmoothingBlendTree(_animatorController, animLayer.stateMachine, p.localSmoothness, p.paramName, p.flipInputOutput, 1f, _animExportDirectory, "OSCm/Local/", "SmootherWD", "OSCm/Proxy/", "Proxy"); + var motionRemote = AnimUtil.CreateSmoothingBlendTree(_animatorController, animLayer.stateMachine, p.remoteSmoothness, p.paramName, p.flipInputOutput, 1f, _animExportDirectory, "OSCm/Remote/", "SmootherRemoteWD", "OSCm/Proxy/", "Proxy"); localChildMotion.Add(new ChildMotion { @@ -148,5 +125,67 @@ public static void CreateSmoothAnimationLayer() basisLocalBlendTree.children = localChildMotion.ToArray(); basisRemoteBlendTree.children = remoteChildMotion.ToArray(); } + + public static void CreateBinaryLayer() + { + + // Creating new Binary setup. + AnimatorControllerLayer animLayer; + + animLayer = AnimUtil.CreateAnimLayerInController("_OSCmooth_Binary_Gen", _animatorController); + + // Creating a Direct BlendTree that will hold all of the binary decode driver animations. This is to effectively create a 'sublayer' + // system within the Direct BlendTree to tidy up the animator base layers from bloating up visually. + AnimatorState[] state = new AnimatorState[1]; + + + state[0] = animLayer.stateMachine.AddState("Binary_Parameters_Blendtree", new Vector3(30, 170, 0)); + state[0].writeDefaultValues = true; + + // Creating BlendTree objects to better customize them in the AC Editor + + var binaryTreeRoot = new BlendTree() + { + blendType = BlendTreeType.Direct, + hideFlags = HideFlags.HideInHierarchy, + name = "Binary_Root", + useAutomaticThresholds = false + + }; + + // Stuffing the BlendTrees into their designated state. Also stuffing them so that they + // retain serialization. + state[0].motion = binaryTreeRoot; + AssetDatabase.AddObjectToAsset(binaryTreeRoot, AssetDatabase.GetAssetPath(animLayer.stateMachine)); + + // Creating a '1Set' parameter that holds a value of one at all times for the Direct BlendTree + + ParameterUtil.CheckAndCreateParameter("OSCm/BlendSet", _animatorController, AnimatorControllerParameterType.Float, 1f); + + + List childBinary = new List(); + + // Go through each parameter and create each child to eventually stuff into the Direct BlendTrees. + foreach (OSCmoothParameter p in _parameters) + { + + var decodeBinary = AnimUtil.CreateBinaryBlendTree(_animatorController, animLayer.stateMachine, p.paramName, _binaryExportDirectory, p.binarySizeSelection, p.combinedParameter); + + if (p.binarySizeSelection != 0) + { + childBinary.Add(new ChildMotion + { + directBlendParameter = "OSCm/BlendSet", + motion = decodeBinary, + timeScale = 1 + }); + } + + + } + + binaryTreeRoot.children = childBinary.ToArray(); + } + } } \ No newline at end of file diff --git a/Assets/OSCmooth/Editor/OSCmoothFilters.cs b/Assets/OSCmooth/Editor/OSCmoothFilters.cs index 5c3500f..b6fd124 100644 --- a/Assets/OSCmooth/Editor/OSCmoothFilters.cs +++ b/Assets/OSCmooth/Editor/OSCmoothFilters.cs @@ -10,7 +10,7 @@ public static class OSCmoothFilters { public static readonly string[] BlackList = { - "OSCm/", "IsLocal", "Smooth", "Proxy", "Proxy/", "_Float", "_Normalizer", "_FTI", "OSCm_BlendSet", "BlendSet", "Blend" + "OSCm/", "IsLocal", "Smooth", "Proxy", "Proxy/", "_Float", "_Normalizer", "_FTI", "OSCm_BlendSet", "BlendSet", "Blend", "Binary/" }; public static readonly string[] AllLayerNames = { diff --git a/Assets/OSCmooth/Editor/OSCmoothLayer.cs b/Assets/OSCmooth/Editor/OSCmoothLayer.cs new file mode 100644 index 0000000..80b969f --- /dev/null +++ b/Assets/OSCmooth/Editor/OSCmoothLayer.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace OSCTools.OSCmooth.Types +{ + [Serializable] + public class OSCmoothLayer : ScriptableObject + { + public List parameters; + public OSCmoothParameter configuration; + + public OSCmoothLayer() + { + parameters = new List(); + configuration = new OSCmoothParameter(); + } + public OSCmoothLayer(List parameters, OSCmoothParameter configuration) + { + this.parameters = parameters; + this.configuration = configuration; + } + } +} + diff --git a/Assets/OSCmooth/Editor/OSCmoothType.cs b/Assets/OSCmooth/Editor/OSCmoothParameter.cs similarity index 71% rename from Assets/OSCmooth/Editor/OSCmoothType.cs rename to Assets/OSCmooth/Editor/OSCmoothParameter.cs index 474eb56..e040519 100644 --- a/Assets/OSCmooth/Editor/OSCmoothType.cs +++ b/Assets/OSCmooth/Editor/OSCmoothParameter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using UnityEngine; @@ -23,6 +23,11 @@ public class OSCmoothParameter // WARNING. Please be considerate with this setting. public bool convertToProxy = true; + // Resolution of parameters for binaries and disable binary + public int binarySizeSelection = 0; + // Combined parameter for positive and negative + public bool combinedParameter = false; + // for Editor window visibility public bool isVisible; @@ -31,32 +36,15 @@ public OSCmoothParameter(string paramName) { this.paramName = paramName; } - public OSCmoothParameter(string paramName, float localSmoothness, float remoteSmoothness, bool convertToProxy, bool flipInputOutput) + public OSCmoothParameter(string paramName, float localSmoothness, float remoteSmoothness, bool convertToProxy, bool flipInputOutput, int binarySizeSelection, bool combinedParameter) { this.paramName = paramName; this.localSmoothness = localSmoothness; this.remoteSmoothness = remoteSmoothness; this.convertToProxy = convertToProxy; this.flipInputOutput = flipInputOutput; + this.binarySizeSelection = binarySizeSelection; + this.combinedParameter = combinedParameter; } } - - [Serializable] - public class OSCmoothLayer : ScriptableObject - { - public List parameters; - public OSCmoothParameter configuration; - - public OSCmoothLayer() - { - parameters = new List(); - configuration = new OSCmoothParameter(); - } - public OSCmoothLayer(List parameters, OSCmoothParameter configuration) - { - this.parameters = parameters; - this.configuration = configuration; - } - } -} - +} \ No newline at end of file diff --git a/Assets/OSCmooth/Editor/OSCmoothUtil.cs b/Assets/OSCmooth/Editor/OSCmoothUtil.cs index 2038244..37da809 100644 --- a/Assets/OSCmooth/Editor/OSCmoothUtil.cs +++ b/Assets/OSCmooth/Editor/OSCmoothUtil.cs @@ -28,7 +28,7 @@ public static string NameNoSymbol(string name) public static void CleanAnimatorBlendTreeBloat(AnimatorController animatorController, string filter) { - Object[] animatorAssets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(animatorController)); + Object[] animatorAssets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(animatorController)); foreach (Object asset in animatorAssets) { @@ -41,6 +41,7 @@ public static void CleanAnimatorBlendTreeBloat(AnimatorController animatorContro } } } + public static void RenameAllStateMachineInstancesOfBlendParameter(AnimatorController animatorController, string initParameter, string newParameter) { Object[] animatorAssets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(animatorController)); @@ -49,7 +50,7 @@ public static void RenameAllStateMachineInstancesOfBlendParameter(AnimatorContro { if (asset?.GetType() == typeof(BlendTree)) { - if(((BlendTree)asset).blendParameter == initParameter) + if (((BlendTree)asset).blendParameter == initParameter) ((BlendTree)asset).blendParameter = newParameter; if (((BlendTree)asset).blendParameterY == initParameter) @@ -131,7 +132,7 @@ public static void RevertStateMachineParameters(AnimatorController animatorContr foreach (var oscmParam in OSCmoothFilters.ParameterExtensions) { - foreach (var stateParam in stateParams) + foreach (var stateParam in stateParams) { if (stateParam.Contains(oscmParam)) { @@ -151,7 +152,7 @@ public static void RemoveExtendedParametersInController(string name, AnimatorCon continue; } i++; - } + } } public static void RemoveContainingLayersInController(string name, AnimatorController animatorController) @@ -188,7 +189,6 @@ public static AnimatorControllerLayer CreateAnimLayerInController(string layerNa defaultWeight = 1f }; - CleanAnimatorBlendTreeBloat(animatorController, "OSCm_"); // Store Layer into Animator Controller, as creating a Layer object is not serialized unless we store it inside an asset. if (AssetDatabase.GetAssetPath(animatorController) != string.Empty) @@ -215,7 +215,7 @@ public static AnimationClip[] CreateFloatSmootherAnimation(AnimatorController an long id; AssetDatabase.TryGetGUIDAndLocalFileIdentifier(animatorController, out animatorGUID, out id); - + AnimationClip _animationClipInit = new AnimationClip(); AnimationClip _animationClipFinal = new AnimationClip(); @@ -261,7 +261,7 @@ public static AnimationClip[] CreateFloatSmootherAnimation(AnimatorController an AssetDatabase.SaveAssets(); } - return new AnimationClip[]{ _animationClipInit, _animationClipFinal }; + return new AnimationClip[] { _animationClipInit, _animationClipFinal }; } private static void SaveAnimationAsset(ref AnimationClip clip, string name, string directory) @@ -302,7 +302,7 @@ public static BlendTree CreateSmoothingBlendTree(AnimatorController animatorCont { blendType = BlendTreeType.Simple1D, hideFlags = HideFlags.HideInHierarchy, - blendParameter = driveBase ? paramName: proxyPrefix + paramName, + blendParameter = driveBase ? paramName : proxyPrefix + paramName, name = "OSCm_Driver", useAutomaticThresholds = false }; @@ -327,5 +327,189 @@ public static BlendTree CreateSmoothingBlendTree(AnimatorController animatorCont return rootTree; } + + public static BlendTree CreateBinaryBlendTree(AnimatorController animatorController, AnimatorStateMachine stateMachine, string paramName, string directory, int binarySizeSelection, bool combinedParameter) + { + // Create each binary step decode layer. This using type casting of bools to float. Parameters will be bools but will be floats in the animator. + // This is way to take typically transition type binaries and stuff them inside direct blendtree to reduce the visual overhead with using binaries in layers. + // There is 20% performance gain by stuffing into direct blend trees. + + + //Create Root to for each binary parameter + var blendRootPara = "OSCm/BlendSet"; + if (combinedParameter) + { + ParameterUtil.CheckAndCreateParameter(paramName + "Negative", animatorController, AnimatorControllerParameterType.Float); + blendRootPara = paramName + "Negative"; + } + + BlendTree decodeBinaryRoot = new BlendTree + { + blendType = BlendTreeType.Simple1D, + hideFlags = HideFlags.HideInHierarchy, + blendParameter = blendRootPara, + name = "Binary_" + paramName + "_Root", + useAutomaticThresholds = false + }; + + + BlendTree decodeBinaryPositiveTree = new BlendTree + { + blendType = BlendTreeType.Direct, + hideFlags = HideFlags.HideInHierarchy, + name = "Binary_" + paramName + "_Positive", + useAutomaticThresholds = false + }; + + + BlendTree decodeBinaryNegativeTree = new BlendTree + { + blendType = BlendTreeType.Direct, + hideFlags = HideFlags.HideInHierarchy, + name = "Binary_" + paramName + "_Negative", + useAutomaticThresholds = false + }; + + + List childBinaryPositiveDecode = new List(); + List childBinaryNegativeDecode = new List(); + + + // Go through binary steps and create each child to eventually stuff into the Direct BlendTrees. + + for (int i = 0; i < binarySizeSelection; i++) + { + + var decodeBinaryPositive = CreateBinaryDecode(animatorController, stateMachine, paramName, directory, i, binarySizeSelection, false); + + childBinaryPositiveDecode.Add(new ChildMotion + { + directBlendParameter = "OSCm/BlendSet", + motion = decodeBinaryPositive, + timeScale = 1 + }); + + } + + if (combinedParameter) + { + for (int i = 0; i < binarySizeSelection; i++) + { + + var decodeBinaryNegative = CreateBinaryDecode(animatorController, stateMachine, paramName, directory, i, binarySizeSelection, true); + + childBinaryNegativeDecode.Add(new ChildMotion + { + directBlendParameter = "OSCm/BlendSet", + motion = decodeBinaryNegative, + timeScale = 1 + }); + + } + + + } + + + decodeBinaryPositiveTree.children = childBinaryPositiveDecode.ToArray(); + decodeBinaryNegativeTree.children = childBinaryNegativeDecode.ToArray(); + + + decodeBinaryRoot.AddChild(decodeBinaryPositiveTree, 0f); + if (combinedParameter) + { + decodeBinaryRoot.AddChild(decodeBinaryNegativeTree, 1f); + } + + + AssetDatabase.AddObjectToAsset(decodeBinaryPositiveTree, AssetDatabase.GetAssetPath(animatorController)); + AssetDatabase.AddObjectToAsset(decodeBinaryNegativeTree, AssetDatabase.GetAssetPath(animatorController)); + AssetDatabase.AddObjectToAsset(decodeBinaryRoot, AssetDatabase.GetAssetPath(animatorController)); + + AssetDatabase.SaveAssets(); + + return decodeBinaryRoot; + } + + public static AnimationClip[] CreateBinaryAnimation(AnimatorController animatorController, string paramName, string directory, float weight = 1, int step = 1) + { + string animatorGUID; + long id; + + AssetDatabase.TryGetGUIDAndLocalFileIdentifier(animatorController, out animatorGUID, out id); + + AnimationClip _animationClipInit = new AnimationClip(); + AnimationClip _animationClipFinal = new AnimationClip(); + + AnimationCurve _curvesInit = new AnimationCurve(new Keyframe(0.0f, 0.0f)); + AnimationCurve _curvesFinal = new AnimationCurve(new Keyframe(0.0f, weight)); + + _animationClipInit.SetCurve("", typeof(Animator), paramName, _curvesInit); + _animationClipFinal.SetCurve("", typeof(Animator), paramName, _curvesFinal); + + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + string[] guid = (AssetDatabase.FindAssets(NameNoSymbol(paramName) + "_FALSE_" + step.ToString() + "_" + (weight < 0 ? "Negative_" : "Positive_") + animatorGUID + ".anim")); + + if (guid.Length == 0) + { + AssetDatabase.CreateAsset(_animationClipInit, directory + NameNoSymbol(paramName) + "_False_" + step.ToString() + "_" + (weight < 0 ? "Negative_" : "Positive_") + animatorGUID + ".anim"); + AssetDatabase.SaveAssets(); + } + + else + { + AssetDatabase.DeleteAsset(AssetDatabase.GUIDToAssetPath(guid[0])); + AssetDatabase.CreateAsset(_animationClipInit, directory + NameNoSymbol(paramName) + "_False_" + step.ToString() + "_" + (weight < 0 ? "Negative_" : "Positive_") + animatorGUID + ".anim"); + AssetDatabase.SaveAssets(); + + } + + guid = (AssetDatabase.FindAssets(NameNoSymbol(paramName) + "_True_" + step.ToString() + (weight < 0 ? "Negative_" : "Positive_") + animatorGUID + ".anim")); + + if (guid.Length == 0) + { + AssetDatabase.CreateAsset(_animationClipFinal, directory + NameNoSymbol(paramName) + "_True_" + step.ToString() + "_" + (weight < 0 ? "Negative_" : "Positive_") + animatorGUID + ".anim"); + AssetDatabase.SaveAssets(); + } + + else + { + + AssetDatabase.DeleteAsset(AssetDatabase.GUIDToAssetPath(guid[0])); + AssetDatabase.CreateAsset(_animationClipFinal, "Assets/Binary/Generated/Binary/" + NameNoSymbol(paramName) + "_True_" + animatorGUID + ".anim"); + AssetDatabase.SaveAssets(); + } + + return new AnimationClip[] { _animationClipInit, _animationClipFinal }; + } + + public static BlendTree CreateBinaryDecode(AnimatorController animatorController, AnimatorStateMachine stateMachine, string paramName, string directory, int binaryPow, int binarySize, bool negative) + { + + ParameterUtil.CheckAndCreateParameter(paramName + Mathf.Pow(2, binaryPow).ToString(), animatorController, AnimatorControllerParameterType.Float); + + BlendTree decodeBinary = new BlendTree + { + blendType = BlendTreeType.Simple1D, + hideFlags = HideFlags.HideInHierarchy, + blendParameter = paramName + Mathf.Pow(2, binaryPow).ToString(), + name = "Binary_" + paramName + "_Decode_" + Mathf.Pow(2, binaryPow).ToString(), + useAutomaticThresholds = false + }; + + // Create Decode anims and weight per binary + AnimationClip[] decodeAnims = AnimUtil.CreateBinaryAnimation(animatorController, paramName, directory, (negative ? -0.5f : 0.5f) * Mathf.Pow(2, binaryPow + 1) / (Mathf.Pow(2, binarySize) - 1f), binaryPow); + decodeBinary.AddChild(decodeAnims[0], 0f); + decodeBinary.AddChild(decodeAnims[1], 1f); + + AssetDatabase.AddObjectToAsset(decodeBinary, AssetDatabase.GetAssetPath(animatorController)); + + return decodeBinary; + + } } } \ No newline at end of file diff --git a/Assets/OSCmooth/Editor/OSCmoothWindow.cs b/Assets/OSCmooth/Editor/OSCmoothWindow.cs index ea291f0..f4f5f97 100644 --- a/Assets/OSCmooth/Editor/OSCmoothWindow.cs +++ b/Assets/OSCmooth/Editor/OSCmoothWindow.cs @@ -22,9 +22,13 @@ public class OSCmoothWindow : EditorWindow private bool _showParameters = true; private bool _showGlobalConfiguration = false; - private bool _writeDefaults = false; private Vector2 paramMenuScroll; + readonly public string[] binarySizeOptions = new string[] + { + "OFF","2 (1 Bit)","4 (2 Bit)","8 (3 Bit)","16 (4 Bit)","32 (5 Bit)", "64 (6 Bit)", "128 (7 Bit)" + }; + //readonly private string[] _humanoidLayers = { "Base", "Additive", "Gesture", "Action", "FX" }; [MenuItem("Tools/OSCmooth")] @@ -37,12 +41,13 @@ public static void ShowWindow() window.Show(); } - private void OnGUI() + private void OnGUI() { DrawGUI(); } - void DrawGUI() - { + + void DrawGUI() + { _avDescriptor = (VRCAvatarDescriptor)EditorGUILayout.ObjectField ( new GUIContent @@ -66,7 +71,7 @@ void DrawGUI() // Making sure the selector never goes beyond the length of the selection if (_layerSelect > layers.Count) _layerSelect = layers.Count - 1; - + _layerSelect = EditorGUILayout.Popup ( new GUIContent @@ -84,15 +89,15 @@ void DrawGUI() _parameterAsset = (OSCmoothLayer)EditorGUILayout.ObjectField ( - new GUIContent - ( - "Config", - "A preset configuration that stores Parameter Configuration data. " + - "This is intended for saving configurations for use later or sharing." - ), - _parameterAsset, - typeof(OSCmoothLayer), - false + new GUIContent + ( + "Config", + "A preset configuration that stores Parameter Configuration data. " + + "This is intended for saving configurations for use later or sharing." + ), + _parameterAsset, + typeof(OSCmoothLayer), + false ); if (_parameterAsset == null) @@ -106,12 +111,12 @@ void DrawGUI() if (GUILayout.Button ( - new GUIContent - ( - "Save Config", - "Saves Parameter configuration into a JSON readable text file." - ), - GUILayout.MaxWidth((float)Screen.width - 159f) + new GUIContent + ( + "Save Config", + "Saves Parameter configuration into a JSON readable text file." + ), + GUILayout.MaxWidth((float)Screen.width - 159f) )) { if (AssetDatabase.GetAssetPath(_parameterAsset) == string.Empty) @@ -123,16 +128,6 @@ void DrawGUI() EditorGUILayout.EndHorizontal(); - _writeDefaults = EditorGUILayout.Toggle - ( - new GUIContent - ( - "Write Defaults", - "Sets whether the generated OSCmooth layer will have write defaults on or off. Set true for WD on, false for WD off" - ), - _writeDefaults - ); - _animatorController = AssetDatabase.LoadAssetAtPath(AssetDatabase.GetAssetPath(_avDescriptor.baseAnimationLayers[_layerSelect].animatorController)); if (_animatorController == null) @@ -163,7 +158,9 @@ void DrawGUI() localSmoothness = _basisConfigurationParameter.localSmoothness, remoteSmoothness = _basisConfigurationParameter.remoteSmoothness, flipInputOutput = _basisConfigurationParameter.flipInputOutput, - convertToProxy = _basisConfigurationParameter.convertToProxy + convertToProxy = _basisConfigurationParameter.convertToProxy, + binarySizeSelection = _basisConfigurationParameter.binarySizeSelection, + combinedParameter = _basisConfigurationParameter.combinedParameter }); } } @@ -185,8 +182,10 @@ void DrawGUI() EditorGUI.indentLevel = 0; _showParameters = EditorGUILayout.Foldout(_showParameters, "Parameter Configuration"); - if (_parameterAsset.parameters != null && _parameterAsset.parameters.Count() > 0) { - if (GUILayout.Button("Remove All")) { + if (_parameterAsset.parameters != null && _parameterAsset.parameters.Count() > 0) + { + if (GUILayout.Button("Remove All")) + { Undo.RecordObject(_parameterAsset, "Remove All Parameters"); _parameterAsset.parameters = new List(); return; @@ -197,7 +196,7 @@ void DrawGUI() paramMenuScroll = EditorGUILayout.BeginScrollView(paramMenuScroll); if (_showParameters && _parameterAsset != null) - { + { foreach (OSCmoothParameter parameter in _parameterAsset.parameters) { if (parameter == null) @@ -206,7 +205,8 @@ void DrawGUI() EditorGUI.indentLevel = 0; using (new EditorGUILayout.HorizontalScope()) { - if (GUILayout.Button(parameter.isVisible ? "v" : ">", GUILayout.Width(20))) { + if (GUILayout.Button(parameter.isVisible ? "v" : ">", GUILayout.Width(20))) + { Undo.RecordObject(_parameterAsset, "Set Parameter Visible"); parameter.isVisible = !parameter.isVisible; } @@ -214,14 +214,15 @@ void DrawGUI() EditorGUI.BeginChangeCheck(); string paramName = parameter.paramName; paramName = EditorGUILayout.TextField(paramName); - if (EditorGUI.EndChangeCheck() && parameter != null) { + if (EditorGUI.EndChangeCheck() && parameter != null) + { Undo.RecordObject(_parameterAsset, "Change Parameter Name"); parameter.paramName = paramName; return; } GUI.color = Color.red; - if (GUILayout.Button("X", GUILayout.Width(40))) + if (GUILayout.Button("X", GUILayout.Width(40))) { Undo.RecordObject(_parameterAsset, "Remove Parameter"); _parameterAsset.parameters.Remove(parameter); @@ -231,7 +232,8 @@ void DrawGUI() GUI.color = Color.white; } EditorGUI.indentLevel = 2; - if (parameter.isVisible) { + if (parameter.isVisible) + { DrawParameterConfiguration(parameter); } } @@ -254,7 +256,9 @@ void DrawGUI() localSmoothness = _basisConfigurationParameter.localSmoothness, remoteSmoothness = _basisConfigurationParameter.remoteSmoothness, flipInputOutput = _basisConfigurationParameter.flipInputOutput, - convertToProxy = _basisConfigurationParameter.convertToProxy + convertToProxy = _basisConfigurationParameter.convertToProxy, + binarySizeSelection = _basisConfigurationParameter.binarySizeSelection, + combinedParameter = _basisConfigurationParameter.combinedParameter }; _parameterAsset.parameters.Add(param); @@ -283,10 +287,14 @@ void DrawGUI() OSCmoothAnimationHandler._animatorController = _animatorController; OSCmoothAnimationHandler._parameters = _parameterAsset.parameters; - OSCmoothAnimationHandler._writeDefaults = _writeDefaults; - OSCmoothAnimationHandler._animExportDirectory = "Assets/OSCmooth/Generated/Anims/" + "Animator_" + animatorGUID + "/"; + OSCmoothAnimationHandler._animExportDirectory = "Assets/OSCmooth/Generated/Smooth/" + "Animator_" + animatorGUID + "/"; + OSCmoothAnimationHandler._binaryExportDirectory = "Assets/OSCmooth/Generated/Binary/" + "Animator_" + animatorGUID + "/"; Undo.RecordObject(OSCmoothAnimationHandler._animatorController, "Apply OSCmooth to Layer"); + + OSCmoothAnimationHandler.RemoveAllBinaryFromController(); + OSCmoothAnimationHandler.RemoveAllOSCmoothFromController(); + OSCmoothAnimationHandler.CreateBinaryLayer(); OSCmoothAnimationHandler.CreateSmoothAnimationLayer(); } @@ -311,10 +319,14 @@ void DrawGUI() OSCmoothAnimationHandler._parameters = _parameterAsset.parameters; Undo.RecordObject(OSCmoothAnimationHandler._animatorController, "Revert OSCmooth in Layer"); + OSCmoothAnimationHandler.RemoveAllBinaryFromController(); OSCmoothAnimationHandler.RemoveAllOSCmoothFromController(); - FileUtil.DeleteFileOrDirectory("Assets/OSCmooth/Generated/Anims/" + "Animator_" + animatorGUID); - FileUtil.DeleteFileOrDirectory("Assets/OSCmooth/Generated/Anims/" + "Animator_" + animatorGUID + ".meta"); + FileUtil.DeleteFileOrDirectory("Assets/OSCmooth/Generated/Smooth/" + "Animator_" + animatorGUID); + FileUtil.DeleteFileOrDirectory("Assets/OSCmooth/Generated/Smooth/" + "Animator_" + animatorGUID + ".meta"); + FileUtil.DeleteFileOrDirectory("Assets/OSCmooth/Generated/Binary/" + "Animator_" + animatorGUID); + FileUtil.DeleteFileOrDirectory("Assets/OSCmooth/Generated/Binary/" + "Animator_" + animatorGUID + ".meta"); + AssetDatabase.Refresh(); } @@ -337,12 +349,14 @@ public void DrawParameterConfiguration(OSCmoothParameter parameter, bool removab ); EditorGUI.indentLevel = 3; - EditorGUIUtility.labelWidth = 200; + EditorGUIUtility.labelWidth = 220; float localSmoothness = parameter.localSmoothness; float remoteSmoothness = parameter.remoteSmoothness; bool convertToProxy = parameter.convertToProxy; bool flipIO = parameter.flipInputOutput; + int binarySizeSelection = parameter.binarySizeSelection; + bool combinedParameter = parameter.combinedParameter; EditorGUI.BeginChangeCheck(); { @@ -389,13 +403,45 @@ public void DrawParameterConfiguration(OSCmoothParameter parameter, bool removab ), flipIO ); + + binarySizeSelection = EditorGUILayout.Popup + ( + new GUIContent + ( + "Binary Resolution", + "How many steps a Binary Parameter can make. Higher values are more accurate, " + + "while lower values are more economic for parameter space. Recommended to use a " + + "Resolution of 16 or less for more space savings." + ), + binarySizeSelection, + binarySizeOptions + ); + + + combinedParameter = EditorGUILayout.Toggle + ( + new GUIContent + ( + "Combined Parameter (+1 Bit)", + "Does this parameter go from positive to negative? " + + "This option will add an extra bool to keep track of the " + + "positive/negative of the parameter." + ), + combinedParameter + ); + + + } - if (EditorGUI.EndChangeCheck()) { + if (EditorGUI.EndChangeCheck()) + { Undo.RecordObject(_parameterAsset, "Change Parameter Values"); parameter.localSmoothness = localSmoothness; parameter.remoteSmoothness = remoteSmoothness; parameter.convertToProxy = convertToProxy; parameter.flipInputOutput = flipIO; + parameter.binarySizeSelection = binarySizeSelection; + parameter.combinedParameter = combinedParameter; } EditorGUILayout.BeginHorizontal(); diff --git a/README.md b/README.md index 86404d2..2ce3a3a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# OSCmooth +# OSCmooth [![Github Releases](https://img.shields.io/github/downloads/YukihoAA/OSCmooth/total.svg)](https://github.com/YukihoAA/OSCmooth/releases) > Create smoothed out animations that mimics IK Sync on avatars for OSC controlled parameters for VRChat. https://user-images.githubusercontent.com/74634856/183157866-37a20b11-20b5-4cfe-a356-e2acfea23a68.mp4