Skip to content
This repository has been archived by the owner on May 25, 2023. It is now read-only.

Commit

Permalink
Merge pull request #20 from killfrenzy96/master
Browse files Browse the repository at this point in the history
Various fixes and improvements
  • Loading branch information
imagitama authored Aug 10, 2022
2 parents 07333ee + e862f1d commit 3e536c5
Showing 1 changed file with 206 additions and 44 deletions.
250 changes: 206 additions & 44 deletions Editor/VRC3CVR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,17 @@ void OnGUI()
CustomGUI.LineGap();

CustomGUI.HorizontalRule();

CustomGUI.LineGap();

CustomGUI.BoldLabel("Step 1: Select your avatar");

CustomGUI.SmallLineGap();

vrcAvatarDescriptor = (VRCAvatarDescriptor)EditorGUILayout.ObjectField("Avatar", vrcAvatarDescriptor, typeof(VRCAvatarDescriptor));

CustomGUI.SmallLineGap();

CustomGUI.BoldLabel("Step 2: Configure settings");

CustomGUI.SmallLineGap();
Expand All @@ -84,9 +84,9 @@ void OnGUI()
CustomGUI.ItalicLabel("Always deletes contact receivers and senders");

CustomGUI.SmallLineGap();

CustomGUI.BoldLabel("Step 3: Convert");

CustomGUI.SmallLineGap();

EditorGUI.BeginDisabledGroup(GetIsReadyForConvert() == false);
Expand Down Expand Up @@ -141,7 +141,7 @@ void CreateChilloutAvatar() {
chilloutAvatarGameObject = vrcAvatarDescriptor.gameObject;
}
}

void HideOriginalAvatar() {
vrcAvatarDescriptor.gameObject.SetActive(false);
}
Expand Down Expand Up @@ -221,7 +221,7 @@ void BuildChilloutAnimatorWithParams()
void DeleteVrcComponents()
{
Debug.Log("Deleting VRC components...");

DestroyImmediate(chilloutAvatarGameObject.GetComponent(typeof(VRC.Core.PipelineManager)));

var vrcComponents = chilloutAvatarGameObject.GetComponentsInChildren(typeof(Component), true).ToList().Where(c => c.GetType().Name.StartsWith("VRC")).ToList();
Expand All @@ -231,11 +231,11 @@ void DeleteVrcComponents()

foreach (var component in vrcComponents) {
string componentName = component.GetType().Name;

if (!shouldDeletePhysBones && componentName.Contains("PhysBone")) {
continue;
}

Debug.Log(component.name + "." + componentName);

DestroyImmediate(component);
Expand Down Expand Up @@ -468,62 +468,218 @@ AnimatorControllerParameter[] GetParametersWithoutDupes(AnimatorControllerParame
return finalParams.ToArray();
}

AnimatorTransition[] ProcessTransitions(AnimatorTransition[] transitions)
{
return ProcessTransitions<AnimatorTransition>(transitions);
}

AnimatorStateTransition[] ProcessTransitions(AnimatorStateTransition[] transitions)
{
List<AnimatorStateTransition> transitionsToAdd = new List<AnimatorStateTransition>();
return ProcessTransitions<AnimatorStateTransition>(transitions);
}

AnimatorTranstitionType[] ProcessTransitions<AnimatorTranstitionType>(AnimatorTranstitionType[] transitions) where AnimatorTranstitionType : AnimatorTransitionBase, new()
{
List<AnimatorTranstitionType> transitionsToAdd = new List<AnimatorTranstitionType>();

for (int t = 0; t < transitions.Length; t++)
{
List<AnimatorCondition> conditionsToAdd = new List<AnimatorCondition>();
AnimatorTranstitionType transition = transitions[t];

// Debug.Log(transitions[t].conditions.Length + " conditions");

for (int c = 0; c < transitions[t].conditions.Length; c++)
ProcessTransition(transition, transitionsToAdd, conditionsToAdd);
}

AnimatorTranstitionType[] newTransitions = new AnimatorTranstitionType[transitions.Length + transitionsToAdd.Count];

transitions.CopyTo(newTransitions, 0);
transitionsToAdd.ToArray().CopyTo(newTransitions, transitions.Length);

return newTransitions;
}

void ProcessTransition<AnimatorTranstitionType>(AnimatorTranstitionType transition, List<AnimatorTranstitionType> transitionsToAdd, List<AnimatorCondition> conditionsToAdd, bool isDuplicate = false) where AnimatorTranstitionType : AnimatorTransitionBase, new()
{
// Convert GestureLeft/GestureRight to ChilloutVR
for (int c = 0; c < transition.conditions.Length; c++)
{
AnimatorCondition condition = transition.conditions[c];

if (condition.parameter == "GestureLeft" || condition.parameter == "GestureRight")
{
AnimatorCondition condition = transitions[t].conditions[c];
float chilloutGestureNumber = GetChilloutGestureNumberForVrchatGestureNumber(condition.threshold);

if (condition.parameter == "GestureLeft" || condition.parameter == "GestureRight")
if (condition.mode == AnimatorConditionMode.Equals)
{
float chilloutGestureNumber = GetChilloutGestureNumberForVrchatGestureNumber(condition.threshold);
float thresholdLow = (float)(chilloutGestureNumber - 0.1);
float thresholdHigh = (float)(chilloutGestureNumber + 0.1);

if (condition.mode == AnimatorConditionMode.Equals)
// Look for GestureWeight and adjust threshold
if (chilloutGestureNumber == 1f) // Fist only
{
AnimatorCondition newConditionLessThan = new AnimatorCondition();
newConditionLessThan.parameter = condition.parameter;
newConditionLessThan.mode = AnimatorConditionMode.Less;
newConditionLessThan.threshold = (float)(chilloutGestureNumber + 0.1);
thresholdLow = 0.01f;

for (int w = 0; w < transition.conditions.Length; w++)
{
AnimatorCondition conditionW = transition.conditions[w];
if (
(condition.parameter == "GestureLeft" && conditionW.parameter == "GestureLeftWeight") ||
(condition.parameter == "GestureRight" && conditionW.parameter == "GestureRightWeight")
) {
if (conditionW.mode == AnimatorConditionMode.Less)
{
thresholdHigh = conditionW.threshold;
}
else
{
thresholdLow = conditionW.threshold;
}
}
}
}

conditionsToAdd.Add(newConditionLessThan);
// Create replace conditions for ChilloutVR
AnimatorCondition newConditionLessThan = new AnimatorCondition();
newConditionLessThan.parameter = condition.parameter;
newConditionLessThan.mode = AnimatorConditionMode.Less;
newConditionLessThan.threshold = thresholdHigh;

conditionsToAdd.Add(newConditionLessThan);

AnimatorCondition newConditionGreaterThan = new AnimatorCondition();
newConditionGreaterThan.parameter = condition.parameter;
newConditionGreaterThan.mode = AnimatorConditionMode.Greater;
newConditionGreaterThan.threshold = thresholdLow;

conditionsToAdd.Add(newConditionGreaterThan);
}
else if (condition.mode == AnimatorConditionMode.NotEqual)
{
float thresholdLow = (float)(chilloutGestureNumber - 0.1);
float thresholdHigh = (float)(chilloutGestureNumber + 0.1);

if (chilloutGestureNumber == 1f) // Fist only
{
thresholdLow = 0.01f;
}

if (isDuplicate) {
// Add greater than transition to duplicate
AnimatorCondition newConditionGreaterThan = new AnimatorCondition();
newConditionGreaterThan.parameter = condition.parameter;
newConditionGreaterThan.mode = AnimatorConditionMode.Greater;
newConditionGreaterThan.threshold = (float)(chilloutGestureNumber - 0.1);
newConditionGreaterThan.threshold = thresholdHigh;

conditionsToAdd.Add(newConditionGreaterThan);
} else if (condition.mode == AnimatorConditionMode.NotEqual)
{

} else {
// Change transition to use less than
AnimatorCondition newConditionLessThan = new AnimatorCondition();
newConditionLessThan.parameter = condition.parameter;
newConditionLessThan.mode = AnimatorConditionMode.Less;
newConditionLessThan.threshold = (float)(chilloutGestureNumber - 0.1);
newConditionLessThan.threshold = thresholdLow;

conditionsToAdd.Add(newConditionLessThan);

// Duplicate transition to create the "or greater than" transition
AnimatorTranstitionType newTransition = new AnimatorTranstitionType();
if (newTransition is AnimatorStateTransition) {
AnimatorStateTransition newTransitionTyped = newTransition as AnimatorStateTransition;
AnimatorStateTransition transitionTyped = transition as AnimatorStateTransition;
newTransitionTyped.duration = transitionTyped.duration;
newTransitionTyped.canTransitionToSelf = transitionTyped.canTransitionToSelf;
newTransitionTyped.exitTime = transitionTyped.exitTime;
newTransitionTyped.hasExitTime = transitionTyped.hasExitTime;
newTransitionTyped.hasFixedDuration = transitionTyped.hasFixedDuration;
newTransitionTyped.interruptionSource = transitionTyped.interruptionSource;
newTransitionTyped.offset = transitionTyped.offset;
newTransitionTyped.orderedInterruption = transitionTyped.orderedInterruption;
}

newTransition.name = transition.name;
newTransition.destinationState = transition.destinationState;
newTransition.destinationStateMachine = transition.destinationStateMachine;
newTransition.hideFlags = transition.hideFlags;
newTransition.isExit = transition.isExit;
newTransition.solo = transition.solo;
newTransition.mute = transition.mute;

for (int c2 = 0; c2 < transition.conditions.Length; c2++)
{
newTransition.AddCondition(transition.conditions[c2].mode, transition.conditions[c2].threshold, transition.conditions[c2].parameter);
}

List<AnimatorTranstitionType> transitionsToAdd2 = new List<AnimatorTranstitionType>();
List<AnimatorCondition> conditionsToAdd2 = new List<AnimatorCondition>();

ProcessTransition(newTransition, transitionsToAdd2, conditionsToAdd2, true);
newTransition.conditions = conditionsToAdd2.ToArray();

transitionsToAdd.Add(newTransition);
}
} else {
conditionsToAdd.Add(condition);
}
}
else if (condition.parameter == "GestureLeftWeight" || condition.parameter == "GestureRightWeight")
{
// Look for fist gesture and create condition if needed
bool gestureFound = false;

transitions[t].conditions = conditionsToAdd.ToArray();
}
for (int w = 0; w < transition.conditions.Length; w++)
{
AnimatorCondition conditionW = transition.conditions[w];
if (
(condition.parameter == "GestureLeftWeight" && conditionW.parameter == "GestureLeft") ||
(condition.parameter == "GestureRightWeight" && conditionW.parameter == "GestureRight")
) {
if (conditionW.threshold == 1f) {
gestureFound = true;
break;
}
}
}

AnimatorStateTransition[] newTransitions = new AnimatorStateTransition[transitions.Length + transitionsToAdd.Count];
// Create condition if gesture weight is used by itself
if (!gestureFound)
{
float thresholdLow = -0.1f;
float thresholdHigh = 1.1f;

transitions.CopyTo(newTransitions, 0);
transitionsToAdd.ToArray().CopyTo(newTransitions, transitions.Length);
if (condition.mode == AnimatorConditionMode.Less)
{
thresholdHigh = condition.threshold;
}
else
{
thresholdLow = condition.threshold;
}

return newTransitions;
string parameterName = condition.parameter == "GestureLeftWeight" ? "GestureLeft" : "GestureRight";

// Create replace conditions for ChilloutVR
AnimatorCondition newConditionLessThan = new AnimatorCondition();
newConditionLessThan.parameter = parameterName;
newConditionLessThan.mode = AnimatorConditionMode.Less;
newConditionLessThan.threshold = thresholdHigh;

conditionsToAdd.Add(newConditionLessThan);

AnimatorCondition newConditionGreaterThan = new AnimatorCondition();
newConditionGreaterThan.parameter = parameterName;
newConditionGreaterThan.mode = AnimatorConditionMode.Greater;
newConditionGreaterThan.threshold = thresholdLow;

conditionsToAdd.Add(newConditionGreaterThan);
}
}
else
{
conditionsToAdd.Add(condition);
}
}

transition.conditions = conditionsToAdd.ToArray();
}

void ProcessStateMachine(AnimatorStateMachine stateMachine)
Expand Down Expand Up @@ -555,7 +711,8 @@ void ProcessStateMachine(AnimatorStateMachine stateMachine)
state.transitions = newTransitions;
}

ProcessTransitions(stateMachine.anyStateTransitions);
stateMachine.anyStateTransitions = ProcessTransitions(stateMachine.anyStateTransitions);
stateMachine.entryTransitions = ProcessTransitions(stateMachine.entryTransitions);

if (stateMachine.stateMachines.Length > 0)
{
Expand Down Expand Up @@ -639,22 +796,27 @@ void MergeVrcAnimatorIntoChilloutAnimator(AnimatorController originalAnimatorCon

for (int i = 0; i < existingLayers.Length; i++)
{
newLayers[newLayersIdx] = existingLayers[i];
newLayersIdx++;
if (existingLayers[i].stateMachine.states.Length > 0) { // Do not copy empty layers
newLayers[newLayersIdx] = existingLayers[i];
newLayersIdx++;
}
}

for (int i = 0; i < layersToMerge.Length; i++)
{
AnimatorControllerLayer layer = layersToMerge[i];

Debug.Log("Layer \"" + layer.name + "\" with " + layer.stateMachine.states.Length + " states");
if (layer.stateMachine.states.Length > 0) { // Do not copy empty layers
Debug.Log("Layer \"" + layer.name + "\" with " + layer.stateMachine.states.Length + " states");

ProcessStateMachine(layer.stateMachine);
ProcessStateMachine(layer.stateMachine);

newLayers[newLayersIdx] = layer;
newLayersIdx++;
newLayers[newLayersIdx] = layer;
newLayersIdx++;
}
}

Array.Resize(ref newLayers, newLayersIdx);
chilloutAnimatorController.layers = newLayers;

Debug.Log("Merged");
Expand Down Expand Up @@ -721,7 +883,7 @@ void CreateEmptyChilloutAnimator()
List<AnimatorControllerLayer> newLayers = new List<AnimatorControllerLayer>();

string[] allowedLayerNames;

if (shouldDeleteCvrHandLayers) {
Debug.Log("Deleting CVR hand layers...");
allowedLayerNames = new string[] { "Locomotion/Emotes" };
Expand Down Expand Up @@ -781,12 +943,12 @@ void GetValuesFromVrcAvatar()
}

int[] eyelidsBlendshapes = vrcAvatarDescriptor.customEyeLookSettings.eyelidsBlendshapes;

if (eyelidsBlendshapes.Length >= 1 && eyelidsBlendshapes[0] != -1) {
if (bodySkinnedMeshRenderer != null) {
int blinkBlendshapeIdx = eyelidsBlendshapes[0];
Mesh mesh = bodySkinnedMeshRenderer.sharedMesh;

if (blinkBlendshapeIdx > mesh.blendShapeCount) {
Debug.LogWarning("Could not use eyelid blendshape at index " + blinkBlendshapeIdx.ToString() + ": does not exist in mesh!");
} else {
Expand Down Expand Up @@ -815,7 +977,7 @@ SkinnedMeshRenderer GetSkinnedMeshRendererInCVRAvatar() {
string pathToSkinnedMeshRenderer = GetPathToGameObjectInsideAvatar(bodySkinnedMeshRenderer.gameObject);

Debug.Log("Path to body skinned mesh renderer: " + pathToSkinnedMeshRenderer);

var match = cvrAvatar.transform.Find(pathToSkinnedMeshRenderer.Remove(0, 1));

if (match == null) {
Expand All @@ -831,7 +993,7 @@ SkinnedMeshRenderer GetSkinnedMeshRendererInCVRAvatar() {
}

return skinnedMeshRenderer;
}
}

public static string GetPathToGameObjectInsideAvatar(GameObject obj)
{
Expand Down

0 comments on commit 3e536c5

Please sign in to comment.