@@ -52,17 +52,17 @@ void OnGUI()
52
52
CustomGUI . LineGap ( ) ;
53
53
54
54
CustomGUI . HorizontalRule ( ) ;
55
-
55
+
56
56
CustomGUI . LineGap ( ) ;
57
57
58
58
CustomGUI . BoldLabel ( "Step 1: Select your avatar" ) ;
59
59
60
60
CustomGUI . SmallLineGap ( ) ;
61
61
62
62
vrcAvatarDescriptor = ( VRCAvatarDescriptor ) EditorGUILayout . ObjectField ( "Avatar" , vrcAvatarDescriptor , typeof ( VRCAvatarDescriptor ) ) ;
63
-
63
+
64
64
CustomGUI . SmallLineGap ( ) ;
65
-
65
+
66
66
CustomGUI . BoldLabel ( "Step 2: Configure settings" ) ;
67
67
68
68
CustomGUI . SmallLineGap ( ) ;
@@ -84,9 +84,9 @@ void OnGUI()
84
84
CustomGUI . ItalicLabel ( "Always deletes contact receivers and senders" ) ;
85
85
86
86
CustomGUI . SmallLineGap ( ) ;
87
-
87
+
88
88
CustomGUI . BoldLabel ( "Step 3: Convert" ) ;
89
-
89
+
90
90
CustomGUI . SmallLineGap ( ) ;
91
91
92
92
EditorGUI . BeginDisabledGroup ( GetIsReadyForConvert ( ) == false ) ;
@@ -141,7 +141,7 @@ void CreateChilloutAvatar() {
141
141
chilloutAvatarGameObject = vrcAvatarDescriptor . gameObject ;
142
142
}
143
143
}
144
-
144
+
145
145
void HideOriginalAvatar ( ) {
146
146
vrcAvatarDescriptor . gameObject . SetActive ( false ) ;
147
147
}
@@ -221,7 +221,7 @@ void BuildChilloutAnimatorWithParams()
221
221
void DeleteVrcComponents ( )
222
222
{
223
223
Debug . Log ( "Deleting VRC components..." ) ;
224
-
224
+
225
225
DestroyImmediate ( chilloutAvatarGameObject . GetComponent ( typeof ( VRC . Core . PipelineManager ) ) ) ;
226
226
227
227
var vrcComponents = chilloutAvatarGameObject . GetComponentsInChildren ( typeof ( Component ) , true ) . ToList ( ) . Where ( c => c . GetType ( ) . Name . StartsWith ( "VRC" ) ) . ToList ( ) ;
@@ -231,11 +231,11 @@ void DeleteVrcComponents()
231
231
232
232
foreach ( var component in vrcComponents ) {
233
233
string componentName = component . GetType ( ) . Name ;
234
-
234
+
235
235
if ( ! shouldDeletePhysBones && componentName . Contains ( "PhysBone" ) ) {
236
236
continue ;
237
237
}
238
-
238
+
239
239
Debug . Log ( component . name + "." + componentName ) ;
240
240
241
241
DestroyImmediate ( component ) ;
@@ -468,62 +468,218 @@ AnimatorControllerParameter[] GetParametersWithoutDupes(AnimatorControllerParame
468
468
return finalParams . ToArray ( ) ;
469
469
}
470
470
471
+ AnimatorTransition [ ] ProcessTransitions ( AnimatorTransition [ ] transitions )
472
+ {
473
+ return ProcessTransitions < AnimatorTransition > ( transitions ) ;
474
+ }
475
+
471
476
AnimatorStateTransition [ ] ProcessTransitions ( AnimatorStateTransition [ ] transitions )
472
477
{
473
- List < AnimatorStateTransition > transitionsToAdd = new List < AnimatorStateTransition > ( ) ;
478
+ return ProcessTransitions < AnimatorStateTransition > ( transitions ) ;
479
+ }
480
+
481
+ AnimatorTranstitionType [ ] ProcessTransitions < AnimatorTranstitionType > ( AnimatorTranstitionType [ ] transitions ) where AnimatorTranstitionType : AnimatorTransitionBase , new ( )
482
+ {
483
+ List < AnimatorTranstitionType > transitionsToAdd = new List < AnimatorTranstitionType > ( ) ;
474
484
475
485
for ( int t = 0 ; t < transitions . Length ; t ++ )
476
486
{
477
487
List < AnimatorCondition > conditionsToAdd = new List < AnimatorCondition > ( ) ;
488
+ AnimatorTranstitionType transition = transitions [ t ] ;
478
489
479
490
// Debug.Log(transitions[t].conditions.Length + " conditions");
480
491
481
- for ( int c = 0 ; c < transitions [ t ] . conditions . Length ; c ++ )
492
+ ProcessTransition ( transition , transitionsToAdd , conditionsToAdd ) ;
493
+ }
494
+
495
+ AnimatorTranstitionType [ ] newTransitions = new AnimatorTranstitionType [ transitions . Length + transitionsToAdd . Count ] ;
496
+
497
+ transitions . CopyTo ( newTransitions , 0 ) ;
498
+ transitionsToAdd . ToArray ( ) . CopyTo ( newTransitions , transitions . Length ) ;
499
+
500
+ return newTransitions ;
501
+ }
502
+
503
+ void ProcessTransition < AnimatorTranstitionType > ( AnimatorTranstitionType transition , List < AnimatorTranstitionType > transitionsToAdd , List < AnimatorCondition > conditionsToAdd , bool isDuplicate = false ) where AnimatorTranstitionType : AnimatorTransitionBase , new ( )
504
+ {
505
+ // Convert GestureLeft/GestureRight to ChilloutVR
506
+ for ( int c = 0 ; c < transition . conditions . Length ; c ++ )
507
+ {
508
+ AnimatorCondition condition = transition . conditions [ c ] ;
509
+
510
+ if ( condition . parameter == "GestureLeft" || condition . parameter == "GestureRight" )
482
511
{
483
- AnimatorCondition condition = transitions [ t ] . conditions [ c ] ;
512
+ float chilloutGestureNumber = GetChilloutGestureNumberForVrchatGestureNumber ( condition . threshold ) ;
484
513
485
- if ( condition . parameter == "GestureLeft" || condition . parameter == "GestureRight" )
514
+ if ( condition . mode == AnimatorConditionMode . Equals )
486
515
{
487
- float chilloutGestureNumber = GetChilloutGestureNumberForVrchatGestureNumber ( condition . threshold ) ;
516
+ float thresholdLow = ( float ) ( chilloutGestureNumber - 0.1 ) ;
517
+ float thresholdHigh = ( float ) ( chilloutGestureNumber + 0.1 ) ;
488
518
489
- if ( condition . mode == AnimatorConditionMode . Equals )
519
+ // Look for GestureWeight and adjust threshold
520
+ if ( chilloutGestureNumber == 1f ) // Fist only
490
521
{
491
- AnimatorCondition newConditionLessThan = new AnimatorCondition ( ) ;
492
- newConditionLessThan . parameter = condition . parameter ;
493
- newConditionLessThan . mode = AnimatorConditionMode . Less ;
494
- newConditionLessThan . threshold = ( float ) ( chilloutGestureNumber + 0.1 ) ;
522
+ thresholdLow = 0.01f ;
523
+
524
+ for ( int w = 0 ; w < transition . conditions . Length ; w ++ )
525
+ {
526
+ AnimatorCondition conditionW = transition . conditions [ w ] ;
527
+ if (
528
+ ( condition . parameter == "GestureLeft" && conditionW . parameter == "GestureLeftWeight" ) ||
529
+ ( condition . parameter == "GestureRight" && conditionW . parameter == "GestureRightWeight" )
530
+ ) {
531
+ if ( conditionW . mode == AnimatorConditionMode . Less )
532
+ {
533
+ thresholdHigh = conditionW . threshold ;
534
+ }
535
+ else
536
+ {
537
+ thresholdLow = conditionW . threshold ;
538
+ }
539
+ }
540
+ }
541
+ }
495
542
496
- conditionsToAdd . Add ( newConditionLessThan ) ;
543
+ // Create replace conditions for ChilloutVR
544
+ AnimatorCondition newConditionLessThan = new AnimatorCondition ( ) ;
545
+ newConditionLessThan . parameter = condition . parameter ;
546
+ newConditionLessThan . mode = AnimatorConditionMode . Less ;
547
+ newConditionLessThan . threshold = thresholdHigh ;
548
+
549
+ conditionsToAdd . Add ( newConditionLessThan ) ;
550
+
551
+ AnimatorCondition newConditionGreaterThan = new AnimatorCondition ( ) ;
552
+ newConditionGreaterThan . parameter = condition . parameter ;
553
+ newConditionGreaterThan . mode = AnimatorConditionMode . Greater ;
554
+ newConditionGreaterThan . threshold = thresholdLow ;
555
+
556
+ conditionsToAdd . Add ( newConditionGreaterThan ) ;
557
+ }
558
+ else if ( condition . mode == AnimatorConditionMode . NotEqual )
559
+ {
560
+ float thresholdLow = ( float ) ( chilloutGestureNumber - 0.1 ) ;
561
+ float thresholdHigh = ( float ) ( chilloutGestureNumber + 0.1 ) ;
562
+
563
+ if ( chilloutGestureNumber == 1f ) // Fist only
564
+ {
565
+ thresholdLow = 0.01f ;
566
+ }
497
567
568
+ if ( isDuplicate ) {
569
+ // Add greater than transition to duplicate
498
570
AnimatorCondition newConditionGreaterThan = new AnimatorCondition ( ) ;
499
571
newConditionGreaterThan . parameter = condition . parameter ;
500
572
newConditionGreaterThan . mode = AnimatorConditionMode . Greater ;
501
- newConditionGreaterThan . threshold = ( float ) ( chilloutGestureNumber - 0.1 ) ;
573
+ newConditionGreaterThan . threshold = thresholdHigh ;
502
574
503
575
conditionsToAdd . Add ( newConditionGreaterThan ) ;
504
- } else if ( condition . mode == AnimatorConditionMode . NotEqual )
505
- {
576
+
577
+ } else {
578
+ // Change transition to use less than
506
579
AnimatorCondition newConditionLessThan = new AnimatorCondition ( ) ;
507
580
newConditionLessThan . parameter = condition . parameter ;
508
581
newConditionLessThan . mode = AnimatorConditionMode . Less ;
509
- newConditionLessThan . threshold = ( float ) ( chilloutGestureNumber - 0.1 ) ;
582
+ newConditionLessThan . threshold = thresholdLow ;
510
583
511
584
conditionsToAdd . Add ( newConditionLessThan ) ;
585
+
586
+ // Duplicate transition to create the "or greater than" transition
587
+ AnimatorTranstitionType newTransition = new AnimatorTranstitionType ( ) ;
588
+ if ( newTransition is AnimatorStateTransition ) {
589
+ AnimatorStateTransition newTransitionTyped = newTransition as AnimatorStateTransition ;
590
+ AnimatorStateTransition transitionTyped = transition as AnimatorStateTransition ;
591
+ newTransitionTyped . duration = transitionTyped . duration ;
592
+ newTransitionTyped . canTransitionToSelf = transitionTyped . canTransitionToSelf ;
593
+ newTransitionTyped . exitTime = transitionTyped . exitTime ;
594
+ newTransitionTyped . hasExitTime = transitionTyped . hasExitTime ;
595
+ newTransitionTyped . hasFixedDuration = transitionTyped . hasFixedDuration ;
596
+ newTransitionTyped . interruptionSource = transitionTyped . interruptionSource ;
597
+ newTransitionTyped . offset = transitionTyped . offset ;
598
+ newTransitionTyped . orderedInterruption = transitionTyped . orderedInterruption ;
599
+ }
600
+
601
+ newTransition . name = transition . name ;
602
+ newTransition . destinationState = transition . destinationState ;
603
+ newTransition . destinationStateMachine = transition . destinationStateMachine ;
604
+ newTransition . hideFlags = transition . hideFlags ;
605
+ newTransition . isExit = transition . isExit ;
606
+ newTransition . solo = transition . solo ;
607
+ newTransition . mute = transition . mute ;
608
+
609
+ for ( int c2 = 0 ; c2 < transition . conditions . Length ; c2 ++ )
610
+ {
611
+ newTransition . AddCondition ( transition . conditions [ c2 ] . mode , transition . conditions [ c2 ] . threshold , transition . conditions [ c2 ] . parameter ) ;
612
+ }
613
+
614
+ List < AnimatorTranstitionType > transitionsToAdd2 = new List < AnimatorTranstitionType > ( ) ;
615
+ List < AnimatorCondition > conditionsToAdd2 = new List < AnimatorCondition > ( ) ;
616
+
617
+ ProcessTransition ( newTransition , transitionsToAdd2 , conditionsToAdd2 , true ) ;
618
+ newTransition . conditions = conditionsToAdd2 . ToArray ( ) ;
619
+
620
+ transitionsToAdd . Add ( newTransition ) ;
512
621
}
513
- } else {
514
- conditionsToAdd . Add ( condition ) ;
515
622
}
516
623
}
624
+ else if ( condition . parameter == "GestureLeftWeight" || condition . parameter == "GestureRightWeight" )
625
+ {
626
+ // Look for fist gesture and create condition if needed
627
+ bool gestureFound = false ;
517
628
518
- transitions [ t ] . conditions = conditionsToAdd . ToArray ( ) ;
519
- }
629
+ for ( int w = 0 ; w < transition . conditions . Length ; w ++ )
630
+ {
631
+ AnimatorCondition conditionW = transition . conditions [ w ] ;
632
+ if (
633
+ ( condition . parameter == "GestureLeftWeight" && conditionW . parameter == "GestureLeft" ) ||
634
+ ( condition . parameter == "GestureRightWeight" && conditionW . parameter == "GestureRight" )
635
+ ) {
636
+ if ( conditionW . threshold == 1f ) {
637
+ gestureFound = true ;
638
+ break ;
639
+ }
640
+ }
641
+ }
520
642
521
- AnimatorStateTransition [ ] newTransitions = new AnimatorStateTransition [ transitions . Length + transitionsToAdd . Count ] ;
643
+ // Create condition if gesture weight is used by itself
644
+ if ( ! gestureFound )
645
+ {
646
+ float thresholdLow = - 0.1f ;
647
+ float thresholdHigh = 1.1f ;
522
648
523
- transitions . CopyTo ( newTransitions , 0 ) ;
524
- transitionsToAdd . ToArray ( ) . CopyTo ( newTransitions , transitions . Length ) ;
649
+ if ( condition . mode == AnimatorConditionMode . Less )
650
+ {
651
+ thresholdHigh = condition . threshold ;
652
+ }
653
+ else
654
+ {
655
+ thresholdLow = condition . threshold ;
656
+ }
525
657
526
- return newTransitions ;
658
+ string parameterName = condition . parameter == "GestureLeftWeight" ? "GestureLeft" : "GestureRight" ;
659
+
660
+ // Create replace conditions for ChilloutVR
661
+ AnimatorCondition newConditionLessThan = new AnimatorCondition ( ) ;
662
+ newConditionLessThan . parameter = parameterName ;
663
+ newConditionLessThan . mode = AnimatorConditionMode . Less ;
664
+ newConditionLessThan . threshold = thresholdHigh ;
665
+
666
+ conditionsToAdd . Add ( newConditionLessThan ) ;
667
+
668
+ AnimatorCondition newConditionGreaterThan = new AnimatorCondition ( ) ;
669
+ newConditionGreaterThan . parameter = parameterName ;
670
+ newConditionGreaterThan . mode = AnimatorConditionMode . Greater ;
671
+ newConditionGreaterThan . threshold = thresholdLow ;
672
+
673
+ conditionsToAdd . Add ( newConditionGreaterThan ) ;
674
+ }
675
+ }
676
+ else
677
+ {
678
+ conditionsToAdd . Add ( condition ) ;
679
+ }
680
+ }
681
+
682
+ transition . conditions = conditionsToAdd . ToArray ( ) ;
527
683
}
528
684
529
685
void ProcessStateMachine ( AnimatorStateMachine stateMachine )
@@ -555,7 +711,8 @@ void ProcessStateMachine(AnimatorStateMachine stateMachine)
555
711
state . transitions = newTransitions ;
556
712
}
557
713
558
- ProcessTransitions ( stateMachine . anyStateTransitions ) ;
714
+ stateMachine . anyStateTransitions = ProcessTransitions ( stateMachine . anyStateTransitions ) ;
715
+ stateMachine . entryTransitions = ProcessTransitions ( stateMachine . entryTransitions ) ;
559
716
560
717
if ( stateMachine . stateMachines . Length > 0 )
561
718
{
@@ -639,22 +796,27 @@ void MergeVrcAnimatorIntoChilloutAnimator(AnimatorController originalAnimatorCon
639
796
640
797
for ( int i = 0 ; i < existingLayers . Length ; i ++ )
641
798
{
642
- newLayers [ newLayersIdx ] = existingLayers [ i ] ;
643
- newLayersIdx ++ ;
799
+ if ( existingLayers [ i ] . stateMachine . states . Length > 0 ) { // Do not copy empty layers
800
+ newLayers [ newLayersIdx ] = existingLayers [ i ] ;
801
+ newLayersIdx ++ ;
802
+ }
644
803
}
645
804
646
805
for ( int i = 0 ; i < layersToMerge . Length ; i ++ )
647
806
{
648
807
AnimatorControllerLayer layer = layersToMerge [ i ] ;
649
808
650
- Debug . Log ( "Layer \" " + layer . name + "\" with " + layer . stateMachine . states . Length + " states" ) ;
809
+ if ( layer . stateMachine . states . Length > 0 ) { // Do not copy empty layers
810
+ Debug . Log ( "Layer \" " + layer . name + "\" with " + layer . stateMachine . states . Length + " states" ) ;
651
811
652
- ProcessStateMachine ( layer . stateMachine ) ;
812
+ ProcessStateMachine ( layer . stateMachine ) ;
653
813
654
- newLayers [ newLayersIdx ] = layer ;
655
- newLayersIdx ++ ;
814
+ newLayers [ newLayersIdx ] = layer ;
815
+ newLayersIdx ++ ;
816
+ }
656
817
}
657
818
819
+ Array . Resize ( ref newLayers , newLayersIdx ) ;
658
820
chilloutAnimatorController . layers = newLayers ;
659
821
660
822
Debug . Log ( "Merged" ) ;
@@ -721,7 +883,7 @@ void CreateEmptyChilloutAnimator()
721
883
List < AnimatorControllerLayer > newLayers = new List < AnimatorControllerLayer > ( ) ;
722
884
723
885
string [ ] allowedLayerNames ;
724
-
886
+
725
887
if ( shouldDeleteCvrHandLayers ) {
726
888
Debug . Log ( "Deleting CVR hand layers..." ) ;
727
889
allowedLayerNames = new string [ ] { "Locomotion/Emotes" } ;
@@ -781,12 +943,12 @@ void GetValuesFromVrcAvatar()
781
943
}
782
944
783
945
int [ ] eyelidsBlendshapes = vrcAvatarDescriptor . customEyeLookSettings . eyelidsBlendshapes ;
784
-
946
+
785
947
if ( eyelidsBlendshapes . Length >= 1 && eyelidsBlendshapes [ 0 ] != - 1 ) {
786
948
if ( bodySkinnedMeshRenderer != null ) {
787
949
int blinkBlendshapeIdx = eyelidsBlendshapes [ 0 ] ;
788
950
Mesh mesh = bodySkinnedMeshRenderer . sharedMesh ;
789
-
951
+
790
952
if ( blinkBlendshapeIdx > mesh . blendShapeCount ) {
791
953
Debug . LogWarning ( "Could not use eyelid blendshape at index " + blinkBlendshapeIdx . ToString ( ) + ": does not exist in mesh!" ) ;
792
954
} else {
@@ -815,7 +977,7 @@ SkinnedMeshRenderer GetSkinnedMeshRendererInCVRAvatar() {
815
977
string pathToSkinnedMeshRenderer = GetPathToGameObjectInsideAvatar ( bodySkinnedMeshRenderer . gameObject ) ;
816
978
817
979
Debug . Log ( "Path to body skinned mesh renderer: " + pathToSkinnedMeshRenderer ) ;
818
-
980
+
819
981
var match = cvrAvatar . transform . Find ( pathToSkinnedMeshRenderer . Remove ( 0 , 1 ) ) ;
820
982
821
983
if ( match == null ) {
@@ -831,7 +993,7 @@ SkinnedMeshRenderer GetSkinnedMeshRendererInCVRAvatar() {
831
993
}
832
994
833
995
return skinnedMeshRenderer ;
834
- }
996
+ }
835
997
836
998
public static string GetPathToGameObjectInsideAvatar ( GameObject obj )
837
999
{
0 commit comments