regzo2 / BinaryParameterTool

Create animations for Binary Parameters for VRCFaceTracking
16 stars 4 forks source link

Add Required Parameters to ExpressionParameters #2

Closed 200Tigersbloxed closed 2 years ago

200Tigersbloxed commented 2 years ago

Just a quick little snippet of code from my other project that will add a Parameter to an avatar's expressionParameters


⚠️ WARNING ⚠️

This is only a method! This PR itself will NOT change anything!

I am unaware of how the codebase works, so I just left the method here for you to design with your code.


Essentially, all you need to do is pass through the GameObject's VRCAvatarDescriptor (SDK3, not SDKBase!), then a List of Parameters to add. The following is an example of a bool parameter called isAzmidiCool, which defaults to true, and is saved:

VRCExpressionParameters.Parameter azmidiParameter = new VRCExpressionParameters.Parameter
{
    name = "isAzmidiCool",
    defaultValue = 1f,
    saved = true,
    valueType = VRCExpressionParameters.ValueType.Bool
}

then, push all parameters to a list (even if there's only one)

List<VRCExpressionParameters.Parameter> parametersList = new List<VRCExpressionParameters.Parameter>
{
    azmidiParameter
}

(or with List<T>.Add())

finally, pass that through to the ParameterTools.AddVRCParameter(VRCAvatarDescriptor, List<VRCExpressionParameters.Parameter>)

ParameterTools.AddVRCParameter(avatarDescriptor, parametersList)

Done!


📝 NOTE📝

Don't run this in a loop with only one parameter. It needs to cache the AvatarDescriptor's parameters, delete the SerializableObject (from the Assets folder), create a new one, then write it to the Assets folder. This has to be done for it to save properly and not corrupt.


regzo2 commented 2 years ago

Thanks! I'll bundle this method call with the CheckAndCreateParameter method and add a way for that method to call this one (since some things like BinaryBlend and the upcoming ...Proxy and ...Smooth parameters do not need to be in the Descriptor). I'll also make the ObjectField at the top take either an Animator Controller or Avatar Descriptor, and change functionality accordingly (or just Avatar Descriptor, that might be simpler lol)

200Tigersbloxed commented 2 years ago

I'll also make the ObjectField at the top take either an Animator Controller or Avatar Descriptor

Note that the animator controllers in the VRCAvatarDescriptor are RuntimeAnimatorControllers, NOT AnimatorControllers, so you may need to still take both

regzo2 commented 2 years ago

Note that the animator controllers in the VRCAvatarDescriptor are RuntimeAnimatorControllers, NOT AnimatorControllers, so you may need to still take both

You are correct, however we can use the RuntimeAnimatorController version of the Animator to search the asset database in the Editor and having it cast to an Animator will search for the AnimatorController within the project.

Here is small snippet of code I wrote to handle the animation layers.

foreach (VRCAvatarDescriptor.CustomAnimLayer layer in _avdescriptor.baseAnimationLayers)
{
     var controller = UnityEditor.AssetDatabase.LoadAssetAtPath<AnimatorController>(UnityEditor.AssetDatabase.GetAssetPath(layer.animatorController));
     if (controller == null)
          continue;
     EditorGUILayout.TextArea(controller.ToString());
}

A controller field within the layers can be null, so we actually can also see if a user has even populated their playable layers correctly. Hopefully you find this useful too in your own project!