local UINavigator = {} local INPUT_TYPE = { REMOTE = "REMOTE", -- 遥控 MOUSE = "MOUSE", -- 鼠标 GESTURE = "GESTURE" -- 手势 } local nGestureScale = 1.2 local nFrameCount = 10 local nRemoteInputTime = 5 local nGestureInputTime = 0.2 local lastMousePos local nLastGestureInputTime local nLastRemoteInputTime local lastSelectedObj local originalScale local currentInputType local function ChangeInputType(INPUT_TYPE) currentInputType = INPUT_TYPE end local function UpdateLastRemoteTime() nLastRemoteInputTime = CS.UnityEngine.Time.unscaledTime end local function UpdateLastGestureTime() nLastGestureInputTime = CS.UnityEngine.Time.unscaledTime end local function SelectButton(selectable) if nil == selectable then CS.UnityEngine.EventSystems.EventSystem.current:SetSelectedGameObject(nil) return end selectable.gameObject:SetActive(true) selectable.transform:GetComponent("Selectable"):Select() end local function SetEntryButton(button) ChangeInputType(INPUT_TYPE.REMOTE) UpdateLastRemoteTime() SelectButton(button) end local function SetGestureInputType() UpdateLastGestureTime() if currentInputType == INPUT_TYPE.GESTURE then return end ChangeInputType(INPUT_TYPE.GESTURE) -- 手势输入时 ui从缩放动画变成放大效果 if lastSelectedObj and not lastSelectedObj:IsDestroyed() and not lastSelectedObj.transform:CompareTag("CommonUtilsMenu") then lastSelectedObj.transform:DOKill() lastSelectedObj.transform.localScale = nGestureScale * originalScale end end local function CheckInput() local Input = CS.UnityEngine.Input local KeyCode = CS.UnityEngine.KeyCode if Input.GetKeyDown(KeyCode.Escape) then local eventManager = require('Base/ZEventDispatchCenter.lua') eventManager:DispatchEvent(eventManager.EventType.COMMON_REMOTE_RETURN) end end local function GetSelected() local selected = CS.UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject if selected and not selected:Equals(nil) and selected.activeInHierarchy then return selected:GetComponent("Selectable") end return nil end local function ResetLastSelectedTransform() if lastSelectedObj and not lastSelectedObj:IsDestroyed() then lastSelectedObj.transform:DOKill() lastSelectedObj.transform.localScale = originalScale end end local function DispatchEventSelectBtn(selected) local eventManager = require('Base/ZEventDispatchCenter.lua') eventManager:DispatchEvent(eventManager.EventType.COMMON_SELECT_BUTTON, lastSelectedObj, selected) end local function MakeButtonFlash(selected) selected.transform:DOKill() selected.transform.localScale = originalScale selected.transform:DOScale(1.2, 1):SetLoops(-1, CS.DG.Tweening.LoopType.Yoyo) end local function SetSelectData(selected) if not selected then return end originalScale = selected.transform.localScale if selected.transform:CompareTag("CommonUtilsMenu") then local eventManager = require('Base/ZEventDispatchCenter.lua') eventManager:DispatchEvent(eventManager.EventType.COMMON_UI_NAVIGATOR_SELECT_MENU, selected) return end MakeButtonFlash(selected) end local function IsRemoteKeyDown() local Input = CS.UnityEngine.Input local KeyCode = CS.UnityEngine.KeyCode return Input.GetKeyDown(KeyCode.LeftArrow) or Input.GetKeyDown(KeyCode.RightArrow) or Input.GetKeyDown(KeyCode.UpArrow) or Input.GetKeyDown(KeyCode.DownArrow) or Input.GetKeyDown(KeyCode.Return) or Input.GetKeyDown(KeyCode.Joystick1Button0) end local function UpdateSelectableBehaviour() local selected = GetSelected() if selected ~= lastSelectedObj then ResetLastSelectedTransform() DispatchEventSelectBtn(selected) SetSelectData(selected) lastSelectedObj = selected return end end local function CheckRemoteKeyDown() if IsRemoteKeyDown() then ChangeInputType(INPUT_TYPE.REMOTE) return end local Time = CS.UnityEngine.Time local Input = CS.UnityEngine.Input local mouseMove = CS.UnityEngine.Vector3.SqrMagnitude(Input.mousePosition - lastMousePos) if Time.frameCount > nFrameCount and (mouseMove > 0.1 or Input.GetMouseButtonDown(0)) then ChangeInputType(INPUT_TYPE.MOUSE) end lastMousePos = Input.mousePosition end local function Select(selected) if selected then selected.gameObject:SetActive(true) selected:Select() return end CS.UnityEngine.EventSystems.EventSystem.current:SetSelectedGameObject(nil) end local function GetKeyCode() local KeyCode = CS.UnityEngine.KeyCode local Input = CS.UnityEngine.Input if Input.GetKeyDown(KeyCode.LeftArrow) then return KeyCode.LeftArrow end if Input.GetKeyDown(KeyCode.RightArrow) then return KeyCode.RightArrow end if Input.GetKeyDown(KeyCode.UpArrow) then return KeyCode.UpArrow end if Input.GetKeyDown(KeyCode.DownArrow) then return KeyCode.DownArrow end return KeyCode.None end local function SetKeyboardSelected(selected) -- 没有选中的UI 寻找第一个 if nil == selected or not selected.isActiveAndEnabled then local Navigation = CS.UnityEngine.UI.Navigation local allSelectablesArray = CS.UnityEngine.UI.Selectable.allSelectablesArray local nLen = allSelectablesArray.Length for nIndex = 0, nLen - 1, 1 do if nil ~= allSelectablesArray[nIndex]:IsDestroyed() and Navigation.Mode.None ~= allSelectablesArray[nIndex].navigation.mode then Select(allSelectablesArray[nIndex]) break end end return end if 1 == CS.UnityEngine.Selectable.allSelectableCount and CS.UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject then Select(nil) end end local function UpdateKeyboardSelection() local selected = GetSelected() local Navigation = CS.UnityEngine.UI.Navigation if selected and selected.navigation.mode == Navigation.Mode.None then Select(nil) return end local KeyCode = CS.UnityEngine.KeyCode local currentKeyCode = GetKeyCode() if KeyCode.None ~= currentKeyCode then SetKeyboardSelected(selected) UpdateLastRemoteTime() return end if 1 == CS.UnityEngine.Selectable.allSelectableCount and CS.UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject and CS.UnityEngine.Time.unscaledTime - nLastRemoteInputTime > nRemoteInputTime then Select(nil) end end local function UpdateMouseSelection() local EventSystems = CS.UnityEngine.EventSystems if not EventSystems.EventSystem.current:IsPointerOverGameObject() then Select(nil) return end local pointerEventData = EventSystems.PointerEventData(EventSystems.EventSystem.current) local mousePosition = CS.UnityEngine.Input.mousePosition local mousePos = CS.UnityEngine.Vector2(mousePosition.x, mousePosition.y) pointerEventData.position = mousePos local listRaycast = CS.System.Collections.Generic.List(CS.UnityEngine.EventSystems.RaycastResult)() EventSystems.EventSystem.current:RaycastAll(pointerEventData, listRaycast) local tPointSelect = {} for _, tRaycast in pairs(listRaycast) do local selectable = tRaycast.gameObject:GetComponent("Selectable") if selectable and selectable.navigation.mode ~= CS.UnityEngine.UI.Navigation.Mode.None then table.insert(tPointSelect, selectable) end end if 0 == #tPointSelect then Select(nil) return end local firstSeleted = tPointSelect[1] if EventSystems.EventSystem.current.currentSelectedGameObject == firstSeleted.gameObject then return end Select(firstSeleted) end local function UpdateGestureSelection() if CS.UnityEngine.Time.unscaledTime - nLastGestureInputTime > nGestureInputTime then ChangeInputType(INPUT_TYPE.GESTURE) if lastSelectedObj and not lastSelectedObj:IsDestroyed() and not lastSelectedObj.transform:CompareTag("CommonUtilsMenu") then MakeButtonFlash(lastSelectedObj) end end end local function SwitchInputType() if INPUT_TYPE.REMOTE == currentInputType then UpdateKeyboardSelection() return end if INPUT_TYPE.MOUSE == currentInputType then UpdateMouseSelection() return end if INPUT_TYPE.GESTURE == currentInputType then UpdateGestureSelection() return end end local function RegisterEvent() local eventManager = require('Base/ZEventDispatchCenter.lua') eventManager:RegisterEvent(eventManager.EventType.COMMON_SET_ENTRY_BUTTON, SetEntryButton) eventManager:RegisterEvent(eventManager.EventType.COMMON_SET_GESTUREINPUT, SetGestureInputType) eventManager:RegisterEvent(eventManager.EventType.COMMON_UI_NAVIGATOR_ANIM, MakeButtonFlash) eventManager:RegisterEvent(eventManager.EventType.COMMON_UI_NAVIGATOR_SELECT, Select) end local function UnregisterEvent() local eventManager = require('Base/ZEventDispatchCenter.lua') eventManager:UnregisterEvent(eventManager.EventType.COMMON_UI_NAVIGATOR_SELECT, Select) eventManager:UnregisterEvent(eventManager.EventType.COMMON_UI_NAVIGATOR_ANIM, MakeButtonFlash) eventManager:UnregisterEvent(eventManager.EventType.COMMON_SET_GESTUREINPUT, SetGestureInputType) eventManager:UnregisterEvent(eventManager.EventType.COMMON_SET_ENTRY_BUTTON, SetEntryButton) end function UINavigator.Awake(luaRoot) UINavigator.luaRoot = luaRoot local canvas = CS.UnityEngine.GameObject.Find('Canvas') UINavigator._rootCanvas = canvas lastMousePos = CS.UnityEngine.Input.mousePosition end function UINavigator.Start() RegisterEvent() end function UINavigator.Update() CheckInput() UpdateSelectableBehaviour() CheckRemoteKeyDown() SwitchInputType() end function UINavigator.OnDestroy() UnregisterEvent() CS.UnityEngine.GameObject.Destroy(UINavigator.rootPanel) end return UINavigator