UINavigator.lua.txt 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. local UINavigator = {}
  2. local INPUT_TYPE = {
  3. REMOTE = "REMOTE", -- 遥控
  4. MOUSE = "MOUSE", -- 鼠标
  5. GESTURE = "GESTURE" -- 手势
  6. }
  7. local nGestureScale = 1.2
  8. local nFrameCount = 10
  9. local nRemoteInputTime = 5
  10. local nGestureInputTime = 0.2
  11. local lastMousePos
  12. local nLastGestureInputTime
  13. local nLastRemoteInputTime
  14. local lastSelectedObj
  15. local originalScale
  16. local currentInputType
  17. local function ChangeInputType(INPUT_TYPE)
  18. currentInputType = INPUT_TYPE
  19. end
  20. local function UpdateLastRemoteTime()
  21. nLastRemoteInputTime = CS.UnityEngine.Time.unscaledTime
  22. end
  23. local function UpdateLastGestureTime()
  24. nLastGestureInputTime = CS.UnityEngine.Time.unscaledTime
  25. end
  26. local function SelectButton(selectable)
  27. if nil == selectable then
  28. CS.UnityEngine.EventSystems.EventSystem.current:SetSelectedGameObject(nil)
  29. return
  30. end
  31. selectable.gameObject:SetActive(true)
  32. selectable.transform:GetComponent("Selectable"):Select()
  33. end
  34. local function SetEntryButton(button)
  35. ChangeInputType(INPUT_TYPE.REMOTE)
  36. UpdateLastRemoteTime()
  37. SelectButton(button)
  38. end
  39. local function SetGestureInputType()
  40. UpdateLastGestureTime()
  41. if currentInputType == INPUT_TYPE.GESTURE then return end
  42. ChangeInputType(INPUT_TYPE.GESTURE)
  43. -- 手势输入时 ui从缩放动画变成放大效果
  44. if lastSelectedObj
  45. and not lastSelectedObj:IsDestroyed()
  46. and not lastSelectedObj.transform:CompareTag("CommonUtilsMenu") then
  47. lastSelectedObj.transform:DOKill()
  48. lastSelectedObj.transform.localScale = nGestureScale * originalScale
  49. end
  50. end
  51. local function CheckInput()
  52. local Input = CS.UnityEngine.Input
  53. local KeyCode = CS.UnityEngine.KeyCode
  54. if Input.GetKeyDown(KeyCode.Escape) then
  55. local eventManager = require('Base/ZEventDispatchCenter.lua')
  56. eventManager:DispatchEvent(eventManager.EventType.COMMON_REMOTE_RETURN)
  57. end
  58. end
  59. local function GetSelected()
  60. local selected = CS.UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject
  61. if selected and not selected:Equals(nil) and selected.activeInHierarchy then
  62. return selected:GetComponent("Selectable")
  63. end
  64. return nil
  65. end
  66. local function ResetLastSelectedTransform()
  67. if lastSelectedObj and not lastSelectedObj:IsDestroyed() then
  68. lastSelectedObj.transform:DOKill()
  69. lastSelectedObj.transform.localScale = originalScale
  70. end
  71. end
  72. local function DispatchEventSelectBtn(selected)
  73. local eventManager = require('Base/ZEventDispatchCenter.lua')
  74. eventManager:DispatchEvent(eventManager.EventType.COMMON_SELECT_BUTTON, lastSelectedObj, selected)
  75. end
  76. local function MakeButtonFlash(selected)
  77. selected.transform:DOKill()
  78. selected.transform.localScale = originalScale
  79. selected.transform:DOScale(1.2, 1):SetLoops(-1, CS.DG.Tweening.LoopType.Yoyo)
  80. end
  81. local function SetSelectData(selected)
  82. if not selected then return end
  83. originalScale = selected.transform.localScale
  84. if selected.transform:CompareTag("CommonUtilsMenu") then
  85. local eventManager = require('Base/ZEventDispatchCenter.lua')
  86. eventManager:DispatchEvent(eventManager.EventType.COMMON_UI_NAVIGATOR_SELECT_MENU, selected)
  87. return
  88. end
  89. MakeButtonFlash(selected)
  90. end
  91. local function IsRemoteKeyDown()
  92. local Input = CS.UnityEngine.Input
  93. local KeyCode = CS.UnityEngine.KeyCode
  94. return Input.GetKeyDown(KeyCode.LeftArrow)
  95. or Input.GetKeyDown(KeyCode.RightArrow)
  96. or Input.GetKeyDown(KeyCode.UpArrow)
  97. or Input.GetKeyDown(KeyCode.DownArrow)
  98. or Input.GetKeyDown(KeyCode.Return)
  99. or Input.GetKeyDown(KeyCode.Joystick1Button0)
  100. end
  101. local function UpdateSelectableBehaviour()
  102. local selected = GetSelected()
  103. if selected ~= lastSelectedObj then
  104. ResetLastSelectedTransform()
  105. DispatchEventSelectBtn(selected)
  106. SetSelectData(selected)
  107. lastSelectedObj = selected
  108. return
  109. end
  110. end
  111. local function CheckRemoteKeyDown()
  112. if IsRemoteKeyDown() then
  113. ChangeInputType(INPUT_TYPE.REMOTE)
  114. return
  115. end
  116. local Time = CS.UnityEngine.Time
  117. local Input = CS.UnityEngine.Input
  118. local mouseMove = CS.UnityEngine.Vector3.SqrMagnitude(Input.mousePosition - lastMousePos)
  119. if Time.frameCount > nFrameCount
  120. and (mouseMove > 0.1 or Input.GetMouseButtonDown(0)) then
  121. ChangeInputType(INPUT_TYPE.MOUSE)
  122. end
  123. lastMousePos = Input.mousePosition
  124. end
  125. local function Select(selected)
  126. if selected then
  127. selected.gameObject:SetActive(true)
  128. selected:Select()
  129. return
  130. end
  131. CS.UnityEngine.EventSystems.EventSystem.current:SetSelectedGameObject(nil)
  132. end
  133. local function GetKeyCode()
  134. local KeyCode = CS.UnityEngine.KeyCode
  135. local Input = CS.UnityEngine.Input
  136. if Input.GetKeyDown(KeyCode.LeftArrow) then
  137. return KeyCode.LeftArrow
  138. end
  139. if Input.GetKeyDown(KeyCode.RightArrow) then
  140. return KeyCode.RightArrow
  141. end
  142. if Input.GetKeyDown(KeyCode.UpArrow) then
  143. return KeyCode.UpArrow
  144. end
  145. if Input.GetKeyDown(KeyCode.DownArrow) then
  146. return KeyCode.DownArrow
  147. end
  148. return KeyCode.None
  149. end
  150. local function SetKeyboardSelected(selected)
  151. -- 没有选中的UI 寻找第一个
  152. if nil == selected
  153. or not selected.isActiveAndEnabled
  154. then
  155. local Navigation = CS.UnityEngine.UI.Navigation
  156. local allSelectablesArray = CS.UnityEngine.UI.Selectable.allSelectablesArray
  157. local nLen = allSelectablesArray.Length
  158. for nIndex = 0, nLen - 1, 1 do
  159. if nil ~= allSelectablesArray[nIndex]:IsDestroyed()
  160. and Navigation.Mode.None ~= allSelectablesArray[nIndex].navigation.mode
  161. then
  162. Select(allSelectablesArray[nIndex])
  163. break
  164. end
  165. end
  166. return
  167. end
  168. if 1 == CS.UnityEngine.Selectable.allSelectableCount
  169. and CS.UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject
  170. then
  171. Select(nil)
  172. end
  173. end
  174. local function UpdateKeyboardSelection()
  175. local selected = GetSelected()
  176. local Navigation = CS.UnityEngine.UI.Navigation
  177. if selected and selected.navigation.mode == Navigation.Mode.None then
  178. Select(nil)
  179. return
  180. end
  181. local KeyCode = CS.UnityEngine.KeyCode
  182. local currentKeyCode = GetKeyCode()
  183. if KeyCode.None ~= currentKeyCode then
  184. SetKeyboardSelected(selected)
  185. UpdateLastRemoteTime()
  186. return
  187. end
  188. if 1 == CS.UnityEngine.Selectable.allSelectableCount
  189. and CS.UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject
  190. and CS.UnityEngine.Time.unscaledTime - nLastRemoteInputTime > nRemoteInputTime
  191. then
  192. Select(nil)
  193. end
  194. end
  195. local function UpdateMouseSelection()
  196. local EventSystems = CS.UnityEngine.EventSystems
  197. if not EventSystems.EventSystem.current:IsPointerOverGameObject() then
  198. Select(nil)
  199. return
  200. end
  201. local pointerEventData = EventSystems.PointerEventData(EventSystems.EventSystem.current)
  202. local mousePosition = CS.UnityEngine.Input.mousePosition
  203. local mousePos = CS.UnityEngine.Vector2(mousePosition.x, mousePosition.y)
  204. pointerEventData.position = mousePos
  205. local listRaycast = CS.System.Collections.Generic.List(CS.UnityEngine.EventSystems.RaycastResult)()
  206. EventSystems.EventSystem.current:RaycastAll(pointerEventData, listRaycast)
  207. local tPointSelect = {}
  208. for _, tRaycast in pairs(listRaycast) do
  209. local selectable = tRaycast.gameObject:GetComponent("Selectable")
  210. if selectable and selectable.navigation.mode ~= CS.UnityEngine.UI.Navigation.Mode.None then
  211. table.insert(tPointSelect, selectable)
  212. end
  213. end
  214. if 0 == #tPointSelect then
  215. Select(nil)
  216. return
  217. end
  218. local firstSeleted = tPointSelect[1]
  219. if EventSystems.EventSystem.current.currentSelectedGameObject == firstSeleted.gameObject then
  220. return
  221. end
  222. Select(firstSeleted)
  223. end
  224. local function UpdateGestureSelection()
  225. if CS.UnityEngine.Time.unscaledTime - nLastGestureInputTime > nGestureInputTime then
  226. ChangeInputType(INPUT_TYPE.GESTURE)
  227. if lastSelectedObj
  228. and not lastSelectedObj:IsDestroyed()
  229. and not lastSelectedObj.transform:CompareTag("CommonUtilsMenu") then
  230. MakeButtonFlash(lastSelectedObj)
  231. end
  232. end
  233. end
  234. local function SwitchInputType()
  235. if INPUT_TYPE.REMOTE == currentInputType then
  236. UpdateKeyboardSelection()
  237. return
  238. end
  239. if INPUT_TYPE.MOUSE == currentInputType then
  240. UpdateMouseSelection()
  241. return
  242. end
  243. if INPUT_TYPE.GESTURE == currentInputType then
  244. UpdateGestureSelection()
  245. return
  246. end
  247. end
  248. local function RegisterEvent()
  249. local eventManager = require('Base/ZEventDispatchCenter.lua')
  250. eventManager:RegisterEvent(eventManager.EventType.COMMON_SET_ENTRY_BUTTON, SetEntryButton)
  251. eventManager:RegisterEvent(eventManager.EventType.COMMON_SET_GESTUREINPUT, SetGestureInputType)
  252. eventManager:RegisterEvent(eventManager.EventType.COMMON_UI_NAVIGATOR_ANIM, MakeButtonFlash)
  253. eventManager:RegisterEvent(eventManager.EventType.COMMON_UI_NAVIGATOR_SELECT, Select)
  254. end
  255. local function UnregisterEvent()
  256. local eventManager = require('Base/ZEventDispatchCenter.lua')
  257. eventManager:UnregisterEvent(eventManager.EventType.COMMON_UI_NAVIGATOR_SELECT, Select)
  258. eventManager:UnregisterEvent(eventManager.EventType.COMMON_UI_NAVIGATOR_ANIM, MakeButtonFlash)
  259. eventManager:UnregisterEvent(eventManager.EventType.COMMON_SET_GESTUREINPUT, SetGestureInputType)
  260. eventManager:UnregisterEvent(eventManager.EventType.COMMON_SET_ENTRY_BUTTON, SetEntryButton)
  261. end
  262. function UINavigator.Awake(luaRoot)
  263. UINavigator.luaRoot = luaRoot
  264. local canvas = CS.UnityEngine.GameObject.Find('Canvas')
  265. UINavigator._rootCanvas = canvas
  266. lastMousePos = CS.UnityEngine.Input.mousePosition
  267. end
  268. function UINavigator.Start()
  269. RegisterEvent()
  270. end
  271. function UINavigator.Update()
  272. CheckInput()
  273. UpdateSelectableBehaviour()
  274. CheckRemoteKeyDown()
  275. SwitchInputType()
  276. end
  277. function UINavigator.OnDestroy()
  278. UnregisterEvent()
  279. CS.UnityEngine.GameObject.Destroy(UINavigator.rootPanel)
  280. end
  281. return UINavigator