@@ -1693,6 +1693,142 @@ public IEnumerator UI_CanDriveUIFromMultipleTouches()
16931693 Assert . That ( scene . leftChildReceiver . events , Is . Empty ) ;
16941694 }
16951695
1696+ // https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-845
1697+ // This tests that we can release and press touches on the same frame with the expected events and touchIds.
1698+ [ UnityTest ]
1699+ [ Category ( "UI" ) ]
1700+ public IEnumerator UI_CanReleaseAndPressTouchesOnSameFrame ( )
1701+ {
1702+ var touchScreen = InputSystem . AddDevice < Touchscreen > ( ) ;
1703+
1704+ // Prevent default selection of left object. This means that we will not have to contend with selections at all
1705+ // in this test as they are driven from UI objects and not by the input module itself.
1706+ var scene = CreateTestUI ( noFirstSelected : true ) ;
1707+
1708+ var asset = ScriptableObject . CreateInstance < InputActionAsset > ( ) ;
1709+ var map = asset . AddActionMap ( "map" ) ;
1710+ var pointAction = map . AddAction ( "point" , type : InputActionType . PassThrough , binding : "<Touchscreen>/touch*/position" ) ;
1711+ var leftClickAction = map . AddAction ( "leftClick" , type : InputActionType . PassThrough , binding : "<Touchscreen>/touch*/press" ) ;
1712+
1713+ scene . uiModule . point = InputActionReference . Create ( pointAction ) ;
1714+ scene . uiModule . leftClick = InputActionReference . Create ( leftClickAction ) ;
1715+
1716+ map . Enable ( ) ;
1717+
1718+ yield return null ;
1719+
1720+ scene . leftChildReceiver . events . Clear ( ) ;
1721+
1722+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( ) , Is . False ) ;
1723+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( touchScreen . deviceId ) , Is . False ) ;
1724+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( 1 ) , Is . False ) ;
1725+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( 2 ) , Is . False ) ;
1726+
1727+ // Touch left object.
1728+ var firstPosition = scene . From640x480ToScreen ( 100 , 100 ) ;
1729+ BeginTouch ( 1 , firstPosition ) ;
1730+ yield return null ;
1731+
1732+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( ) , Is . True ) ;
1733+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( touchScreen . deviceId ) , Is . True ) ;
1734+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( 1 ) , Is . True ) ;
1735+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( 2 ) , Is . False ) ;
1736+
1737+ Assert . That ( scene . leftChildReceiver . events ,
1738+ Has . Exactly ( 1 ) . With . Property ( "type" ) . EqualTo ( EventType . PointerEnter ) . And
1739+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . device == touchScreen ) . And
1740+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . touchId == 1 ) . And
1741+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . pointerType == UIPointerType . Touch ) . And
1742+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . position == firstPosition ) ) ;
1743+ Assert . That ( scene . leftChildReceiver . events ,
1744+ Has . Exactly ( 1 ) . With . Property ( "type" ) . EqualTo ( EventType . PointerDown ) . And
1745+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . device == touchScreen ) . And
1746+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . touchId == 1 ) . And
1747+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . pointerType == UIPointerType . Touch ) . And
1748+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . position == firstPosition ) ) ;
1749+ Assert . That ( scene . rightChildReceiver . events , Is . Empty ) ;
1750+
1751+ scene . leftChildReceiver . events . Clear ( ) ;
1752+ scene . rightChildReceiver . events . Clear ( ) ;
1753+
1754+ // Release left object and Touch right object on the same frame.
1755+ var secondPosition = scene . From640x480ToScreen ( 350 , 200 ) ;
1756+ EndTouch ( 1 , firstPosition ) ;
1757+ BeginTouch ( 2 , secondPosition ) ;
1758+ yield return null ;
1759+
1760+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( ) , Is . True ) ;
1761+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( touchScreen . deviceId ) , Is . True ) ;
1762+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( 1 ) , Is . True ) ;
1763+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( 2 ) , Is . True ) ;
1764+
1765+ Assert . That ( scene . leftChildReceiver . events ,
1766+ Has . Exactly ( 1 ) . With . Property ( "type" ) . EqualTo ( EventType . PointerUp ) . And
1767+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . device == touchScreen ) . And
1768+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . touchId == 1 ) . And
1769+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . pointerType == UIPointerType . Touch ) . And
1770+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . position == firstPosition ) ) ;
1771+
1772+ Assert . That ( scene . rightChildReceiver . events ,
1773+ Has . Exactly ( 1 ) . With . Property ( "type" ) . EqualTo ( EventType . PointerEnter ) . And
1774+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . device == touchScreen ) . And
1775+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . touchId == 2 ) . And
1776+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . pointerType == UIPointerType . Touch ) . And
1777+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . position == secondPosition ) ) ;
1778+
1779+ Assert . That ( scene . rightChildReceiver . events ,
1780+ Has . Exactly ( 1 ) . With . Property ( "type" ) . EqualTo ( EventType . PointerDown ) . And
1781+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . device == touchScreen ) . And
1782+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . touchId == 2 ) . And
1783+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . pointerType == UIPointerType . Touch ) . And
1784+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . position == secondPosition ) ) ;
1785+
1786+ scene . leftChildReceiver . events . Clear ( ) ;
1787+ scene . rightChildReceiver . events . Clear ( ) ;
1788+
1789+ // End second touch.
1790+ EndTouch ( 2 , secondPosition ) ;
1791+ yield return null ;
1792+
1793+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( ) , Is . True ) ;
1794+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( touchScreen . deviceId ) , Is . True ) ;
1795+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( 1 ) , Is . True ) ;
1796+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( 2 ) , Is . True ) ;
1797+
1798+ Assert . That ( scene . leftChildReceiver . events ,
1799+ Has . Exactly ( 1 ) . With . Property ( "type" ) . EqualTo ( EventType . PointerExit ) . And
1800+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . device == touchScreen ) . And
1801+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . touchId == 1 ) . And
1802+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . pointerType == UIPointerType . Touch ) . And
1803+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . position == firstPosition ) ) ;
1804+
1805+ Assert . That ( scene . rightChildReceiver . events ,
1806+ Has . Exactly ( 1 ) . With . Property ( "type" ) . EqualTo ( EventType . PointerUp ) . And
1807+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . device == touchScreen ) . And
1808+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . touchId == 2 ) . And
1809+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . pointerType == UIPointerType . Touch ) . And
1810+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . position == secondPosition ) ) ;
1811+
1812+ scene . leftChildReceiver . events . Clear ( ) ;
1813+ scene . rightChildReceiver . events . Clear ( ) ;
1814+
1815+ // Next frame
1816+ yield return null ;
1817+
1818+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( ) , Is . False ) ;
1819+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( touchScreen . deviceId ) , Is . False ) ;
1820+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( 1 ) , Is . False ) ;
1821+ Assert . That ( scene . eventSystem . IsPointerOverGameObject ( 2 ) , Is . False ) ;
1822+
1823+ Assert . That ( scene . leftChildReceiver . events , Is . Empty ) ;
1824+ Assert . That ( scene . rightChildReceiver . events ,
1825+ Has . Exactly ( 1 ) . With . Property ( "type" ) . EqualTo ( EventType . PointerExit ) . And
1826+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . device == touchScreen ) . And
1827+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . touchId == 2 ) . And
1828+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . pointerType == UIPointerType . Touch ) . And
1829+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . position == secondPosition ) ) ;
1830+ }
1831+
16961832 // https://fogbugz.unity3d.com/f/cases/1190150/
16971833 [ UnityTest ]
16981834 [ Category ( "UI" ) ]
0 commit comments