@@ -929,6 +929,89 @@ public IEnumerator CombinedConstraintFarNear()
929
929
TestUtilities . AssertAboutEqual ( originalPosition , testObject . transform . position , "Position should be equal for far interaction" ) ;
930
930
}
931
931
932
+ /// <summary>
933
+ /// Tests that multiple constraints obey their relative execution order priorities
934
+ /// </summary>
935
+ [ UnityTest ]
936
+ public IEnumerator ConstraintExecutionOrder ( )
937
+ {
938
+ TestUtilities . PlayspaceToArbitraryPose ( ) ;
939
+
940
+ var testObject = GameObject . CreatePrimitive ( PrimitiveType . Cube ) ;
941
+ testObject . transform . localScale = Vector3 . one * 0.2f ;
942
+ Vector3 originalPosition = TestUtilities . PositionRelativeToPlayspace ( Vector3 . forward ) ;
943
+ testObject . transform . position = originalPosition ;
944
+ Quaternion originalRotation = Quaternion . identity ;
945
+ testObject . transform . rotation = originalRotation ;
946
+ var manipHandler = testObject . AddComponent < ObjectManipulator > ( ) ;
947
+ manipHandler . HostTransform = testObject . transform ;
948
+ manipHandler . SmoothingFar = false ;
949
+ manipHandler . SmoothingNear = false ;
950
+ manipHandler . OneHandRotationModeFar = ObjectManipulator . RotateInOneHandType . RotateAboutGrabPoint ;
951
+
952
+ // Add every-axis rotation constraint
953
+ var rotateConstraint = manipHandler . EnsureComponent < RotationAxisConstraint > ( ) ;
954
+ rotateConstraint . UseLocalSpaceForConstraint = false ;
955
+ rotateConstraint . ConstraintOnRotation = AxisFlags . XAxis | AxisFlags . YAxis | AxisFlags . ZAxis ;
956
+ rotateConstraint . ProximityType = ManipulationProximityFlags . Far ;
957
+
958
+ // Add a face user constraint.
959
+ var faceUserConstraint = manipHandler . EnsureComponent < FaceUserConstraint > ( ) ;
960
+ faceUserConstraint . FaceAway = true ;
961
+ faceUserConstraint . ProximityType = ManipulationProximityFlags . Far ;
962
+
963
+ // First, we'll test the rotate constraint executing first.
964
+ // Expected behavior: cube will still rotate to face user, because
965
+ // the FaceUserConstraint will execute second.
966
+ rotateConstraint . ExecutionPriority = 0 ;
967
+ faceUserConstraint . ExecutionPriority = 1 ;
968
+ yield return null ;
969
+
970
+ const int numHandSteps = 1 ;
971
+
972
+ TestHand rightHand = new TestHand ( Handedness . Right ) ;
973
+
974
+ yield return rightHand . Show ( TestUtilities . PositionRelativeToPlayspace ( new Vector3 ( 0.05f , - 0.1f , 0.45f ) ) ) ;
975
+ yield return null ;
976
+
977
+ // Pinch and rotate hand.
978
+ yield return rightHand . SetGesture ( ArticulatedHandPose . GestureId . Pinch ) ;
979
+ yield return null ;
980
+ yield return rightHand . SetRotation ( Quaternion . Euler ( 0 , 45 , 0 ) , numHandSteps ) ;
981
+ yield return null ;
982
+
983
+ // With this execution order, the faceUser constraint should still be setting the cube's rotation.
984
+ TestUtilities . AssertAboutEqual ( testObject . transform . forward . normalized , ( testObject . transform . position - CameraCache . Main . transform . position ) . normalized , "Cube should have faced away from user." ) ;
985
+
986
+ // Reset hand position + gesture
987
+ yield return rightHand . SetGesture ( ArticulatedHandPose . GestureId . Open ) ;
988
+ yield return null ;
989
+ yield return rightHand . SetRotation ( Quaternion . identity , numHandSteps ) ;
990
+ yield return null ;
991
+
992
+ // Reset cube position+rotation
993
+ testObject . transform . position = originalPosition ;
994
+ testObject . transform . rotation = originalRotation ;
995
+
996
+ // Now, we'll switch the execution order of the two constraints.
997
+ // With the rotation constraint executing *after* the faceUser constraint,
998
+ // the rotation of the cube should now be properly locked.
999
+
1000
+ // This also tests whether setting these priorities
1001
+ // properly re-sorts the ConstraintManager's priority list.
1002
+ rotateConstraint . ExecutionPriority = 1 ;
1003
+ faceUserConstraint . ExecutionPriority = 0 ;
1004
+
1005
+ // Pinch and rotate hand.
1006
+ yield return rightHand . SetGesture ( ArticulatedHandPose . GestureId . Pinch ) ;
1007
+ yield return null ;
1008
+ yield return rightHand . SetRotation ( Quaternion . Euler ( 0 , 45 , 0 ) , numHandSteps ) ;
1009
+ yield return null ;
1010
+
1011
+ // With this execution order, the rotation constraint should be properly constraining rotation.
1012
+ TestUtilities . AssertAboutEqual ( testObject . transform . rotation , originalRotation , "Cube should not have been able to rotate." ) ;
1013
+ }
1014
+
932
1015
/// <summary>
933
1016
/// Tests that FaceUserConstraint updates the rotation to face the user
934
1017
/// </summary>
0 commit comments