@@ -80,6 +80,37 @@ public void ClearEvents()
80
80
leftChildReceiver . events . Clear ( ) ;
81
81
rightChildReceiver . events . Clear ( ) ;
82
82
}
83
+
84
+ /// <summary>
85
+ /// Calculate a quaternion that will rotate a vector looking straight down the z axis around the y axis
86
+ /// to point at the specified UI object.
87
+ /// </summary>
88
+ /// <param name="from"></param>
89
+ /// <param name="uiObject"></param>
90
+ /// <param name="worldSpaceUIObjectOffset"></param>
91
+ /// <returns></returns>
92
+ public Quaternion GetLookAtQuaternion ( Vector3 from , GameObject uiObject , Vector3 worldSpaceUIObjectOffset = default )
93
+ {
94
+ var position = uiObject . GetComponent < RectTransform > ( ) . position + worldSpaceUIObjectOffset ;
95
+ var angle = Mathf . Asin ( position . x / ( from - position ) . magnitude ) ;
96
+ return Quaternion . Euler ( 0 , angle * Mathf . Rad2Deg , 0 ) ;
97
+ }
98
+
99
+ /// <summary>
100
+ /// Calculate a quaternion that will rotate a vector pointing at UI object 'from' around the y axis to point
101
+ /// at object 'to'.
102
+ /// </summary>
103
+ /// <param name="position"></param>
104
+ /// <param name="from"></param>
105
+ /// <param name="to"></param>
106
+ /// <returns></returns>
107
+ public Quaternion RotateFromTo ( Vector3 position , GameObject from , GameObject to )
108
+ {
109
+ var fromPosition = from . GetComponent < RectTransform > ( ) . position ;
110
+ var toPosition = to . GetComponent < RectTransform > ( ) . position ;
111
+ var angle = Mathf . Asin ( ( fromPosition - toPosition ) . magnitude / ( position - fromPosition ) . magnitude ) ;
112
+ return Quaternion . Euler ( 0 , angle * Mathf . Rad2Deg , 0 ) ;
113
+ }
83
114
}
84
115
85
116
[ SetUp ]
@@ -361,7 +392,7 @@ public IEnumerator UI_CanDriveUIFromPointer(string deviceLayout, UIPointerType p
361
392
}
362
393
else if ( isTracked )
363
394
{
364
- trackedOrientation = Quaternion . Euler ( 0 , - 35 , 0 ) ;
395
+ trackedOrientation = scene . GetLookAtQuaternion ( trackedPosition , scene . leftGameObject ) ;
365
396
Set ( device , "deviceRotation" , trackedOrientation , queueEventOnly : true ) ;
366
397
}
367
398
else
@@ -674,7 +705,7 @@ public IEnumerator UI_CanDriveUIFromPointer(string deviceLayout, UIPointerType p
674
705
}
675
706
else if ( isTracked )
676
707
{
677
- trackedOrientation = Quaternion . Euler ( 0 , - 30 , 0 ) ;
708
+ trackedOrientation = scene . GetLookAtQuaternion ( trackedPosition , scene . leftGameObject , new Vector3 ( 5 , 0 , 0 ) ) ;
678
709
Set ( device , "deviceRotation" , trackedOrientation , queueEventOnly : true ) ;
679
710
}
680
711
else
@@ -778,7 +809,7 @@ public IEnumerator UI_CanDriveUIFromPointer(string deviceLayout, UIPointerType p
778
809
}
779
810
else if ( isTracked )
780
811
{
781
- trackedOrientation = Quaternion . Euler ( 0 , 30 , 0 ) ;
812
+ trackedOrientation = scene . GetLookAtQuaternion ( trackedPosition , scene . rightGameObject ) ;
782
813
Set ( device , "deviceRotation" , trackedOrientation , queueEventOnly : true ) ;
783
814
}
784
815
else
@@ -1249,12 +1280,16 @@ public IEnumerator UI_CanDriveUIFromMultiplePointers(UIPointerBehavior pointerBe
1249
1280
scene . leftChildReceiver . events . Clear ( ) ;
1250
1281
scene . rightChildReceiver . events . Clear ( ) ;
1251
1282
1283
+ // the tracked device tests below don't seem to work on Android when run on the build farm. The pointer
1284
+ // positions fail the IsWithinRect checks. They work fine locally. Possibly something to do with tracked
1285
+ // devices on Shield? The build farm seems to always run them on Shield devices.
1286
+ #if ! UNITY_ANDROID
1252
1287
// Put tracked device #1 over left object and tracked device #2 over right object.
1253
1288
// Need two updates as otherwise we'd end up with just another pointer of the right object
1254
1289
// which would not result in an event.
1255
- Set ( trackedDevice1 , "deviceRotation" , Quaternion . Euler ( 0 , - 30 , 0 ) ) ;
1290
+ Set ( trackedDevice1 , "deviceRotation" , scene . GetLookAtQuaternion ( Vector3 . zero , scene . leftGameObject ) ) ;
1256
1291
yield return null ;
1257
- Set ( trackedDevice2 , "deviceRotation" , Quaternion . Euler ( 0 , 30 , 0 ) ) ;
1292
+ Set ( trackedDevice2 , "deviceRotation" , scene . GetLookAtQuaternion ( Vector3 . zero , scene . rightGameObject ) ) ;
1258
1293
yield return null ;
1259
1294
1260
1295
var leftPosition = scene . From640x480ToScreen ( 80 , 240 ) ;
@@ -1313,6 +1348,7 @@ public IEnumerator UI_CanDriveUIFromMultiplePointers(UIPointerBehavior pointerBe
1313
1348
1314
1349
scene . leftChildReceiver . events . Clear ( ) ;
1315
1350
scene . rightChildReceiver . events . Clear ( ) ;
1351
+ #endif
1316
1352
1317
1353
// Touch right object on first touchscreen and left object on second touchscreen.
1318
1354
BeginTouch ( 1 , secondPosition , screen : touch1 ) ;
@@ -1727,15 +1763,15 @@ public IEnumerator UI_CanDriveUIFromMultipleTrackedDevices()
1727
1763
scene . rightChildReceiver . events . Clear ( ) ;
1728
1764
1729
1765
// Point first device at left child.
1730
- Set ( trackedDevice1 . deviceRotation , Quaternion . Euler ( 0 , - 30 , 0 ) ) ;
1766
+ Set ( trackedDevice1 . deviceRotation , scene . GetLookAtQuaternion ( Vector3 . zero , scene . leftGameObject ) ) ;
1731
1767
yield return null ;
1732
1768
1733
1769
Assert . That ( scene . leftChildReceiver . events ,
1734
1770
EventSequence (
1735
1771
AllEvents ( "pointerType" , UIPointerType . Tracked ) ,
1736
1772
AllEvents ( "pointerId" , trackedDevice1 . deviceId ) ,
1737
1773
AllEvents ( "device" , trackedDevice1 ) ,
1738
- AllEvents ( "trackedDeviceOrientation" , Quaternion . Euler ( 0 , - 30 , 0 ) ) ,
1774
+ AllEvents ( "trackedDeviceOrientation" , scene . GetLookAtQuaternion ( Vector3 . zero , scene . leftGameObject ) ) ,
1739
1775
OneEvent ( "type" , EventType . PointerEnter )
1740
1776
#if UNITY_2021_2_OR_NEWER
1741
1777
, OneEvent ( "type" , EventType . PointerMove )
@@ -1747,15 +1783,15 @@ public IEnumerator UI_CanDriveUIFromMultipleTrackedDevices()
1747
1783
scene . leftChildReceiver . events . Clear ( ) ;
1748
1784
1749
1785
// Point second device at left child.
1750
- Set ( trackedDevice2 . deviceRotation , Quaternion . Euler ( 0 , - 31 , 0 ) ) ;
1786
+ Set ( trackedDevice2 . deviceRotation , scene . GetLookAtQuaternion ( Vector3 . zero , scene . leftGameObject , Vector3 . left ) ) ;
1751
1787
yield return null ;
1752
1788
1753
1789
Assert . That ( scene . leftChildReceiver . events ,
1754
1790
EventSequence (
1755
1791
AllEvents ( "pointerType" , UIPointerType . Tracked ) ,
1756
1792
AllEvents ( "pointerId" , trackedDevice2 . deviceId ) ,
1757
1793
AllEvents ( "device" , trackedDevice2 ) ,
1758
- AllEvents ( "trackedDeviceOrientation" , Quaternion . Euler ( 0 , - 31 , 0 ) ) ,
1794
+ AllEvents ( "trackedDeviceOrientation" , scene . GetLookAtQuaternion ( Vector3 . zero , scene . leftGameObject , Vector3 . left ) ) ,
1759
1795
OneEvent ( "type" , EventType . PointerEnter )
1760
1796
#if UNITY_2021_2_OR_NEWER
1761
1797
, OneEvent ( "type" , EventType . PointerMove )
@@ -1776,7 +1812,7 @@ public IEnumerator UI_CanDriveUIFromMultipleTrackedDevices()
1776
1812
AllEvents ( "pointerType" , UIPointerType . Tracked ) ,
1777
1813
AllEvents ( "pointerId" , trackedDevice1 . deviceId ) ,
1778
1814
AllEvents ( "device" , trackedDevice1 ) ,
1779
- AllEvents ( "trackedDeviceOrientation" , Quaternion . Euler ( 0 , - 30 , 0 ) ) ,
1815
+ AllEvents ( "trackedDeviceOrientation" , scene . GetLookAtQuaternion ( Vector3 . zero , scene . leftGameObject ) ) ,
1780
1816
OneEvent ( "type" , EventType . PointerDown ) ,
1781
1817
OneEvent ( "type" , EventType . InitializePotentialDrag ) ,
1782
1818
OneEvent ( "type" , EventType . PointerUp ) ,
@@ -1796,7 +1832,7 @@ public IEnumerator UI_CanDriveUIFromMultipleTrackedDevices()
1796
1832
AllEvents ( "pointerType" , UIPointerType . Tracked ) ,
1797
1833
AllEvents ( "pointerId" , trackedDevice2 . deviceId ) ,
1798
1834
AllEvents ( "device" , trackedDevice2 ) ,
1799
- AllEvents ( "trackedDeviceOrientation" , Quaternion . Euler ( 0 , - 31 , 0 ) ) ,
1835
+ AllEvents ( "trackedDeviceOrientation" , scene . GetLookAtQuaternion ( Vector3 . zero , scene . leftGameObject , Vector3 . left ) ) ,
1800
1836
OneEvent ( "type" , EventType . PointerDown ) ,
1801
1837
OneEvent ( "type" , EventType . InitializePotentialDrag ) ,
1802
1838
OneEvent ( "type" , EventType . PointerUp ) ,
@@ -1808,15 +1844,15 @@ public IEnumerator UI_CanDriveUIFromMultipleTrackedDevices()
1808
1844
scene . leftChildReceiver . events . Clear ( ) ;
1809
1845
1810
1846
// Point first device at right child.
1811
- Set ( trackedDevice1 . deviceRotation , Quaternion . Euler ( 0 , 30 , 0 ) ) ;
1847
+ Set ( trackedDevice1 . deviceRotation , scene . GetLookAtQuaternion ( Vector3 . zero , scene . rightGameObject ) ) ;
1812
1848
yield return null ;
1813
1849
1814
1850
Assert . That ( scene . leftChildReceiver . events ,
1815
1851
EventSequence (
1816
1852
AllEvents ( "pointerType" , UIPointerType . Tracked ) ,
1817
1853
AllEvents ( "pointerId" , trackedDevice1 . deviceId ) ,
1818
1854
AllEvents ( "device" , trackedDevice1 ) ,
1819
- AllEvents ( "trackedDeviceOrientation" , Quaternion . Euler ( 0 , 30 , 0 ) ) ,
1855
+ AllEvents ( "trackedDeviceOrientation" , scene . GetLookAtQuaternion ( Vector3 . zero , scene . rightGameObject ) ) ,
1820
1856
#if UNITY_2021_2_OR_NEWER
1821
1857
OneEvent ( "type" , EventType . PointerMove ) ,
1822
1858
#endif
@@ -1828,7 +1864,7 @@ public IEnumerator UI_CanDriveUIFromMultipleTrackedDevices()
1828
1864
AllEvents ( "pointerType" , UIPointerType . Tracked ) ,
1829
1865
AllEvents ( "pointerId" , trackedDevice1 . deviceId ) ,
1830
1866
AllEvents ( "device" , trackedDevice1 ) ,
1831
- AllEvents ( "trackedDeviceOrientation" , Quaternion . Euler ( 0 , 30 , 0 ) ) ,
1867
+ AllEvents ( "trackedDeviceOrientation" , scene . GetLookAtQuaternion ( Vector3 . zero , scene . rightGameObject ) ) ,
1832
1868
OneEvent ( "type" , EventType . PointerEnter )
1833
1869
#if UNITY_2021_2_OR_NEWER
1834
1870
, OneEvent ( "type" , EventType . PointerMove )
@@ -1840,15 +1876,15 @@ public IEnumerator UI_CanDriveUIFromMultipleTrackedDevices()
1840
1876
scene . rightChildReceiver . events . Clear ( ) ;
1841
1877
1842
1878
// Point second device at right child.
1843
- Set ( trackedDevice2 . deviceRotation , Quaternion . Euler ( 0 , 31 , 0 ) ) ;
1879
+ Set ( trackedDevice2 . deviceRotation , scene . GetLookAtQuaternion ( Vector3 . zero , scene . rightGameObject , Vector3 . right ) ) ;
1844
1880
yield return null ;
1845
1881
1846
1882
Assert . That ( scene . leftChildReceiver . events ,
1847
1883
EventSequence (
1848
1884
AllEvents ( "pointerType" , UIPointerType . Tracked ) ,
1849
1885
AllEvents ( "pointerId" , trackedDevice2 . deviceId ) ,
1850
1886
AllEvents ( "device" , trackedDevice2 ) ,
1851
- AllEvents ( "trackedDeviceOrientation" , Quaternion . Euler ( 0 , 31 , 0 ) ) ,
1887
+ AllEvents ( "trackedDeviceOrientation" , scene . GetLookAtQuaternion ( Vector3 . zero , scene . rightGameObject , Vector3 . right ) ) ,
1852
1888
#if UNITY_2021_2_OR_NEWER
1853
1889
OneEvent ( "type" , EventType . PointerMove ) ,
1854
1890
#endif
@@ -1860,7 +1896,7 @@ public IEnumerator UI_CanDriveUIFromMultipleTrackedDevices()
1860
1896
AllEvents ( "pointerType" , UIPointerType . Tracked ) ,
1861
1897
AllEvents ( "pointerId" , trackedDevice2 . deviceId ) ,
1862
1898
AllEvents ( "device" , trackedDevice2 ) ,
1863
- AllEvents ( "trackedDeviceOrientation" , Quaternion . Euler ( 0 , 31 , 0 ) ) ,
1899
+ AllEvents ( "trackedDeviceOrientation" , scene . GetLookAtQuaternion ( Vector3 . zero , scene . rightGameObject , Vector3 . right ) ) ,
1864
1900
OneEvent ( "type" , EventType . PointerEnter )
1865
1901
#if UNITY_2021_2_OR_NEWER
1866
1902
, OneEvent ( "type" , EventType . PointerMove )
@@ -2185,7 +2221,7 @@ public IEnumerator UI_CanGetRaycastResultMatchingEvent()
2185
2221
scene . rightChildReceiver . events . Clear ( ) ;
2186
2222
2187
2223
// Point device at left child.
2188
- Set ( trackedDevice . deviceRotation , Quaternion . Euler ( 0 , - 30 , 0 ) ) ;
2224
+ Set ( trackedDevice . deviceRotation , scene . GetLookAtQuaternion ( Vector3 . zero , scene . leftGameObject ) ) ;
2189
2225
yield return null ;
2190
2226
2191
2227
var raycastResult = scene . uiModule . GetLastRaycastResult ( trackedDevice . deviceId ) ;
@@ -2253,15 +2289,15 @@ public IEnumerator UI_XRTrackingOriginTransformModifiesTrackedPointers()
2253
2289
Assert . That ( trackedDeviceRaycast . isValid , Is . False ) ;
2254
2290
2255
2291
// Point device at left child.
2256
- Set ( trackedDevice . deviceRotation , Quaternion . Euler ( 0 , - 30 , 0 ) ) ;
2292
+ Set ( trackedDevice . deviceRotation , scene . GetLookAtQuaternion ( Vector3 . zero , scene . leftGameObject ) ) ;
2257
2293
yield return null ;
2258
2294
2259
2295
trackedDeviceRaycast = scene . uiModule . GetLastRaycastResult ( trackedDevice . deviceId ) ;
2260
2296
Assert . That ( trackedDeviceRaycast . isValid , Is . True ) ;
2261
2297
Assert . That ( trackedDeviceRaycast . gameObject , Is . EqualTo ( scene . leftGameObject ) ) ;
2262
2298
2263
2299
// Rotate so right object is targetted
2264
- xrTrackingOrigin . rotation = Quaternion . Euler ( 0f , 60 , 0f ) ;
2300
+ xrTrackingOrigin . rotation = scene . RotateFromTo ( Vector3 . zero , scene . leftGameObject , scene . rightGameObject ) ;
2265
2301
yield return null ;
2266
2302
2267
2303
trackedDeviceRaycast = scene . uiModule . GetLastRaycastResult ( trackedDevice . deviceId ) ;
0 commit comments