using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
using UnityEngine.EventSystems;
using Rokid.UXR.Utility;
using Rokid.UXR.Module;
namespace Rokid.UXR.Interaction
{
public enum InputModuleType
{
None = 1 << 0,
ThreeDof = 1 << 1, //手机3dof 射线
Gesture = 1 << 2, //手势
Mouse = 1 << 3, // 蓝牙鼠标
ButtonMouse = 1 << 4, // 滑鼠
TouchPad = 1 << 5, // 触摸屏
}
[Flags]
public enum ActiveModuleType
{
ThreeDof = 1 << 0, //手机 3dof 射线
Gesture = 1 << 1, //手势
Mouse = 1 << 2, // 蓝牙鼠标
ButtonMouse = 1 << 3, // 滑鼠
TouchPad = 1 << 4, // 触摸屏
}
[Flags]
public enum ActiveHandType
{
LeftHand = 1 << 0, //左手
RightHand = 1 << 1, //右手
}
[Flags]
public enum ActiveHandOrientationType
{
Back = 1 << 0, //左手
Palm = 1 << 1, //右手
}
[Flags]
public enum ActiveHandInteractorType
{
Far = 1 << 0, //远场交互
Near = 1 << 1, //进场交互
}
[Flags]
public enum ActiveWatchType
{
DisableWatch = 1 << 0,
EnableWatch = 1 << 1,
}
[Flags]
public enum ActiveHeadHandType
{
NormalHand = 1 << 0,
HeadHand = 1 << 1,
}
///
/// Input Module status
///
[Serializable]
public class ActiveModuleStatus
{
public InputModuleType moduleType;
public ActiveHandStatus leftHandStatus;
public ActiveHandStatus rightHandStatus;
public ActiveHeadHandType headHandType;
public override string ToString()
{
return $"ActiveInputModuleType: {moduleType} \r\n\r\nLeftHandStatus: {leftHandStatus.ToString()} \r\n\r\nRightHandStatus: {rightHandStatus.ToString()}";
}
}
[Serializable]
public class ActiveHandStatus
{
public bool active;
public ActiveHandInteractorType handInteractorType;
public ActiveHandOrientationType handOrientationType;
public ActiveWatchType activeWatchType;
public bool handDragging;
public override string ToString()
{
return $" \r\n Active:{active} \r\n HandDragging:{handDragging}\r\n HandInteractorType:{handInteractorType.ToString()} \r\n HandOrientationType:{handOrientationType.ToString()} \r\n ActiveWatchType:{activeWatchType.ToString()}";
}
}
///
/// This script implements the IInputModuleActive interface, which allows it to register its own activation status information to the InputModuleManager for centralized management and switching.
///
public class InputModuleManager : MonoSingleton
{
///
/// The default init module
///
[SerializeField, Tooltip("默认初始化的模块")]
private ActiveModuleType defaultInitModule;
///
/// The default active module.
///
[SerializeField, Tooltip("默认激活的模块")]
private InputModuleType defaultActiveModule;
///
/// Whether to play a module switch sound.
///
[HideInInspector, SerializeField, Tooltip("是否播放模块切换提示音")]
private bool muteModuleActiveSound = false;
///
/// Optional TextUI for debugging purposes.
///
[Optional, SerializeField, Tooltip("调试Text")]
private Text logText;
[SerializeField, HideInInspector, Tooltip("模块的激活状态")]
private ActiveModuleStatus activeModuleStatus = new ActiveModuleStatus();
private bool stateChanged;
private List moduleActives = new List();
public static event Action OnObjectActive;
public static event Action OnModuleActive;
public bool GetMouseActive()
{
return activeModuleStatus.moduleType == InputModuleType.Mouse;
}
public bool GetGesActive()
{
return activeModuleStatus.moduleType == InputModuleType.Gesture;
}
public bool GetThreeDofActive()
{
return activeModuleStatus.moduleType == InputModuleType.ThreeDof;
}
public bool GetButtonMouseActive()
{
return activeModuleStatus.moduleType == InputModuleType.ButtonMouse;
}
public bool GetTouchPadActive()
{
return activeModuleStatus.moduleType == InputModuleType.TouchPad;
}
public bool GetWatchModuleActive(HandType hand)
{
if (activeModuleStatus.moduleType == InputModuleType.Gesture)
{
if (hand == HandType.LeftHand)
{
return activeModuleStatus.leftHandStatus.activeWatchType == ActiveWatchType.EnableWatch;
}
if (hand == HandType.RightHand)
{
return activeModuleStatus.rightHandStatus.activeWatchType == ActiveWatchType.EnableWatch;
}
}
return false;
}
///
/// 获取当前激活的模块
/// Gets the currently active module
///
///
public ActiveModuleStatus GetActiveModule()
{
return activeModuleStatus;
}
public void SetDefaultActiveModule(InputModuleType moduleType)
{
defaultActiveModule = moduleType;
}
public void Initialize()
{
RKLog.KeyInfo($"====InputModuleManager====: defaultInitModule : {defaultInitModule}, defaultActiveModule:{defaultActiveModule},transform:{transform.name}");
if (HasInputModuleType(defaultInitModule, ActiveModuleType.ThreeDof))
{
ThreeDofEventInput.Instance.Initialize(transform);
}
if (HasInputModuleType(defaultInitModule, ActiveModuleType.Mouse))
{
MouseEventInput.Instance.Initialize(transform);
}
if (HasInputModuleType(defaultInitModule, ActiveModuleType.ButtonMouse))
{
ButtonMouseEventInput.Instance.Initialize(transform);
}
if (HasInputModuleType(defaultInitModule, ActiveModuleType.Gesture))
{
if (Utils.IsAndroidPlatfrom())
{
if (Utils.IsAndroidPlatfrom() && FuncDeviceCheck.CheckHandTrackingFunc())
{
GesEventInput.Instance.Initialize(transform);
}
else
{
ThreeDofEventInput.Instance.Initialize(transform);
}
}
else
{
GesEventInput.Instance.Initialize(transform);
}
}
if (HasInputModuleType(defaultInitModule, ActiveModuleType.TouchPad))
{
TouchPadEventInput.Instance.Initialize(transform);
}
switch (defaultActiveModule)
{
case InputModuleType.ThreeDof:
ThreeDofEventInput.Instance.ActiveModule();
break;
case InputModuleType.Gesture:
if (Utils.IsAndroidPlatfrom())
{
if (FuncDeviceCheck.CheckHandTrackingFunc())
{
GesEventInput.Instance.ActiveModule();
}
else
{
ThreeDofEventInput.Instance.ActiveModule();
}
}
else
{
GesEventInput.Instance.ActiveModule();
}
break;
case InputModuleType.Mouse:
MouseEventInput.Instance.ActiveModule();
break;
case InputModuleType.ButtonMouse:
ButtonMouseEventInput.Instance.ActiveModule();
break;
case InputModuleType.TouchPad:
TouchPadEventInput.Instance.ActiveModule();
break;
}
if (EventSystem.current == null)
{
GameObject go = GameObject.Instantiate(Resources.Load("Prefabs/Events/RKEventSystem"));
go.name = "RKEventSystem";
go.transform.SetParent(transform);
}
InitModuleChangeAudio();
}
private void Start()
{
InteractorStateChange.OnInteractorTypeChange += OnInteractorTypeChange;
InteractorStateChange.OnHandDragStatusChanged += OnGestureDragStatusChanged;
RKHandWatch.OnActiveWatch += OnActiveWatch;
GesEventInput.OnHandOrHeadHandTypeChange += OnHandOrHeadHandTypeChange;
MouseEventInput.OnActiveMouseModule += OnActiveMouseModule;
ThreeDofEventInput.OnActiveThreeDofModule += OnActiveThreeDofModule;
GesEventInput.OnActiveGesModule += OnActiveGesModule;
ButtonMouseEventInput.OnActiveButtonMouseModule += OnActiveButtonMouseModule;
TouchPadEventInput.OnActiveTouchPadModule += OnActiveTouchPadModule;
MouseEventInput.OnReleaseMouseModule += OnReleaseMouseModule;
ThreeDofEventInput.OnReleaseThreeDofModule += OnReleaseThreeDofModule;
GesEventInput.OnReleaseGesModule += OnReleaseGesModule;
ButtonMouseEventInput.OnReleaseButtonMouseModule += OnReleaseButtonMouseModule;
TouchPadEventInput.OnReleaseTouchPadModule += OnReleaseTouchPadModule;
GesEventInput.OnTrackedSuccess += OnTrackedSuccess;
GesEventInput.OnTrackedFailed += OnTrackedFailed;
GesEventInput.OnHandOrientationUpdate += OnHandOrientationUpdate;
Initialize();
}
private void OnGestureDragStatusChanged(HandType hand, bool dragging)
{
if (hand == HandType.LeftHand)
{
if (activeModuleStatus.leftHandStatus.handDragging != dragging)
{
activeModuleStatus.leftHandStatus.handDragging = dragging;
stateChanged = true;
}
}
if (hand == HandType.RightHand)
{
if (activeModuleStatus.rightHandStatus.handDragging != dragging)
{
activeModuleStatus.rightHandStatus.handDragging = dragging;
stateChanged = true;
}
}
}
private void OnActiveWatch(HandType hand, bool active)
{
if (hand == HandType.LeftHand)
{
activeModuleStatus.leftHandStatus.activeWatchType = active ? ActiveWatchType.EnableWatch : ActiveWatchType.DisableWatch;
stateChanged = true;
}
if (hand == HandType.RightHand)
{
activeModuleStatus.rightHandStatus.activeWatchType = active ? ActiveWatchType.EnableWatch : ActiveWatchType.DisableWatch;
stateChanged = true;
}
}
private void OnHandOrientationUpdate(HandType hand, HandOrientation handOrientation)
{
if (hand == HandType.LeftHand)
{
if (activeModuleStatus.leftHandStatus.handOrientationType != ConvertType(handOrientation) && activeModuleStatus.leftHandStatus.handDragging == false)
{
activeModuleStatus.leftHandStatus.handOrientationType = ConvertType(handOrientation);
stateChanged = true;
}
}
if (hand == HandType.RightHand)
{
if (activeModuleStatus.rightHandStatus.handOrientationType != ConvertType(handOrientation) && activeModuleStatus.rightHandStatus.handDragging == false)
{
activeModuleStatus.rightHandStatus.handOrientationType = ConvertType(handOrientation);
stateChanged = true;
}
}
}
private void OnTrackedFailed(HandType hand)
{
if (hand == HandType.LeftHand || hand == HandType.None)
{
if (activeModuleStatus.leftHandStatus.active == true)
{
activeModuleStatus.leftHandStatus.active = false;
stateChanged = true;
}
}
if (hand == HandType.RightHand || hand == HandType.None)
{
if (activeModuleStatus.rightHandStatus.active == true)
{
activeModuleStatus.rightHandStatus.active = false;
stateChanged = true;
}
}
}
protected override void OnDestroy()
{
InteractorStateChange.OnInteractorTypeChange -= OnInteractorTypeChange;
InteractorStateChange.OnHandDragStatusChanged -= OnGestureDragStatusChanged;
RKHandWatch.OnActiveWatch -= OnActiveWatch;
GesEventInput.OnHandOrHeadHandTypeChange -= OnHandOrHeadHandTypeChange;
MouseEventInput.OnActiveMouseModule -= OnActiveMouseModule;
ThreeDofEventInput.OnActiveThreeDofModule -= OnActiveThreeDofModule;
GesEventInput.OnActiveGesModule -= OnActiveGesModule;
ButtonMouseEventInput.OnActiveButtonMouseModule -= OnActiveButtonMouseModule;
TouchPadEventInput.OnActiveTouchPadModule -= OnActiveTouchPadModule;
MouseEventInput.OnReleaseMouseModule -= OnReleaseMouseModule;
ThreeDofEventInput.OnReleaseThreeDofModule -= OnReleaseThreeDofModule;
GesEventInput.OnReleaseGesModule -= OnReleaseGesModule;
ButtonMouseEventInput.OnReleaseButtonMouseModule -= OnReleaseButtonMouseModule;
TouchPadEventInput.OnReleaseTouchPadModule -= OnReleaseTouchPadModule;
GesEventInput.OnTrackedSuccess -= OnTrackedSuccess;
GesEventInput.OnTrackedFailed -= OnTrackedFailed;
GesEventInput.OnHandOrientationUpdate -= OnHandOrientationUpdate;
}
private void OnInteractorTypeChange(HandType hand, InteractorType interactorType)
{
if (hand == HandType.LeftHand)
{
activeModuleStatus.leftHandStatus.handInteractorType = interactorType == InteractorType.Near ? ActiveHandInteractorType.Near : ActiveHandInteractorType.Far;
stateChanged = true;
}
if (hand == HandType.RightHand)
{
activeModuleStatus.rightHandStatus.handInteractorType = interactorType == InteractorType.Near ? ActiveHandInteractorType.Near : ActiveHandInteractorType.Far;
stateChanged = true;
}
}
private void OnHandOrHeadHandTypeChange(HandOrHeadHandType handOrHeadHandType)
{
if (handOrHeadHandType == HandOrHeadHandType.NormalHand)
{
activeModuleStatus.headHandType = ActiveHeadHandType.NormalHand;
stateChanged = true;
}
else
{
activeModuleStatus.headHandType = ActiveHeadHandType.HeadHand;
stateChanged = true;
}
}
private void OnActiveMouseModule()
{
if (!GetMouseActive())
{
activeModuleStatus.moduleType = InputModuleType.Mouse;
stateChanged = true;
PlayModuleChangeAudio(activeModuleStatus.moduleType);
OnModuleActive?.Invoke(InputModuleType.Mouse);
}
}
private void OnActiveThreeDofModule()
{
if (!GetThreeDofActive())
{
activeModuleStatus.moduleType = InputModuleType.ThreeDof;
stateChanged = true;
PlayModuleChangeAudio(activeModuleStatus.moduleType);
OnModuleActive?.Invoke(InputModuleType.ThreeDof);
}
}
private void OnActiveGesModule()
{
if (!GetGesActive())
{
activeModuleStatus.moduleType = InputModuleType.Gesture;
activeModuleStatus.leftHandStatus.handInteractorType = ConvertType(GesEventInput.Instance.GetInteractorType(HandType.LeftHand));
activeModuleStatus.leftHandStatus.handOrientationType = ConvertType(GesEventInput.Instance.GetHandOrientation(HandType.LeftHand));
activeModuleStatus.rightHandStatus.handInteractorType = ConvertType(GesEventInput.Instance.GetInteractorType(HandType.RightHand));
activeModuleStatus.rightHandStatus.handOrientationType = ConvertType(GesEventInput.Instance.GetHandOrientation(HandType.RightHand));
stateChanged = true;
PlayModuleChangeAudio(activeModuleStatus.moduleType);
OnModuleActive?.Invoke(InputModuleType.Gesture);
}
}
private void OnActiveButtonMouseModule()
{
if (!GetButtonMouseActive())
{
activeModuleStatus.moduleType = InputModuleType.ButtonMouse;
stateChanged = true;
PlayModuleChangeAudio(activeModuleStatus.moduleType);
OnModuleActive?.Invoke(InputModuleType.ButtonMouse);
}
}
private void OnActiveTouchPadModule()
{
if (!GetTouchPadActive())
{
activeModuleStatus.moduleType = InputModuleType.TouchPad;
stateChanged = true;
PlayModuleChangeAudio(activeModuleStatus.moduleType);
OnModuleActive?.Invoke(InputModuleType.TouchPad);
}
}
private void OnReleaseGesModule()
{
if (GetGesActive())
{
activeModuleStatus.moduleType = InputModuleType.None;
stateChanged = true;
}
}
private void OnReleaseThreeDofModule()
{
if (GetThreeDofActive())
{
activeModuleStatus.moduleType = InputModuleType.None;
stateChanged = true;
}
}
private void OnReleaseMouseModule()
{
if (GetMouseActive())
{
activeModuleStatus.moduleType = InputModuleType.None;
stateChanged = true;
}
}
private void OnReleaseButtonMouseModule()
{
if (GetButtonMouseActive())
{
activeModuleStatus.moduleType = InputModuleType.None;
stateChanged = true;
}
}
private void OnReleaseTouchPadModule()
{
if (GetTouchPadActive())
{
activeModuleStatus.moduleType = InputModuleType.None;
stateChanged = true;
}
}
private void OnTrackedSuccess(HandType hand)
{
if (hand == HandType.LeftHand)
{
if (activeModuleStatus.leftHandStatus.active == false)
{
activeModuleStatus.leftHandStatus.active = true;
stateChanged = true;
}
}
if (hand == HandType.RightHand)
{
if (activeModuleStatus.rightHandStatus.active == false)
{
activeModuleStatus.rightHandStatus.active = true;
stateChanged = true;
}
}
}
public void RegisterActive(IInputModuleActive moudleActive)
{
this.moduleActives.Add(moudleActive);
stateChanged = true;
RKLog.KeyInfo($"====ModuleSwitchManager====: RegisterActive {moudleActive.Go.name},{this.moduleActives.Count}");
}
public void UnRegisterActive(IInputModuleActive moudleActive)
{
this.moduleActives.Remove(moudleActive);
RKLog.KeyInfo($"====ModuleSwitchManager====: UnRegisterActive {moudleActive.Go.name},{this.moduleActives.Count}");
}
private void SetActiveEnable(IInputModuleActive active, bool enabled)
{
if (active.Behaviour != null)
{
active.Behaviour.enabled = enabled;
}
else
{
active.Go.SetActive(enabled);
OnObjectActive?.Invoke(active, enabled);
}
}
private void Update()
{
if (stateChanged)
{
RKLog.KeyInfo($"====InputModuleManager==== Current Active Status: {activeModuleStatus}");
stateChanged = false;
for (int i = 0; i < moduleActives.Count; i++)
{
IInputModuleActive active = moduleActives[i];
bool enabled = false;
switch (activeModuleStatus.moduleType)
{
case InputModuleType.Mouse:
if (HasInputModuleType(active.ActiveModuleType, ActiveModuleType.Mouse))
enabled = HasInputModuleType(active.ActiveModuleType, ActiveModuleType.Mouse);
break;
case InputModuleType.ThreeDof:
if (HasInputModuleType(active.ActiveModuleType, ActiveModuleType.ThreeDof))
enabled = HasInputModuleType(active.ActiveModuleType, ActiveModuleType.ThreeDof);
break;
case InputModuleType.Gesture:
if (HasInputModuleType(active.ActiveModuleType, ActiveModuleType.Gesture))
{
if (JudgeHandLost(active.DisableOnHandLost, activeModuleStatus.leftHandStatus.active) && HasHandType(active.ActiveHandType, ActiveHandType.LeftHand) && HasHandInteractorType(active.ActiveHandInteractorType, activeModuleStatus.leftHandStatus.handInteractorType) && HasHandOrientationType(active.ActiveHandOrientationType, activeModuleStatus.leftHandStatus.handOrientationType) &&
HasWatchType(active.ActiveWatchType, activeModuleStatus.leftHandStatus.activeWatchType) && HasHeadHandType(active.ActiveHeadHandType, activeModuleStatus.headHandType))
{
enabled = true;
}
if (JudgeHandLost(active.DisableOnHandLost, activeModuleStatus.rightHandStatus.active) && HasHandType(active.ActiveHandType, ActiveHandType.RightHand) && HasHandInteractorType(active.ActiveHandInteractorType, activeModuleStatus.rightHandStatus.handInteractorType) && HasHandOrientationType(active.ActiveHandOrientationType, activeModuleStatus.rightHandStatus.handOrientationType) &&
HasWatchType(active.ActiveWatchType, activeModuleStatus.rightHandStatus.activeWatchType) && HasHeadHandType(active.ActiveHeadHandType, activeModuleStatus.headHandType))
{
enabled = true;
}
}
break;
case InputModuleType.ButtonMouse:
if (HasInputModuleType(active.ActiveModuleType, ActiveModuleType.ButtonMouse))
enabled = HasInputModuleType(active.ActiveModuleType, ActiveModuleType.ButtonMouse);
break;
case InputModuleType.TouchPad:
if (HasInputModuleType(active.ActiveModuleType, ActiveModuleType.TouchPad))
enabled = HasInputModuleType(active.ActiveModuleType, ActiveModuleType.TouchPad);
break;
default:
enabled = false;
break;
}
SetActiveEnable(active, enabled);
}
}
if (logText != null)
{
logText.text = activeModuleStatus.ToString() + $"\r\n\r\nDragThreshold: {EventSystem.current.pixelDragThreshold}";
}
}
#region Judge Has Type
private bool HasInputModuleType(ActiveModuleType inType, ActiveModuleType targetType)
{
return (inType & targetType) == targetType;
}
private bool HasHandType(ActiveHandType inType, ActiveHandType targetType)
{
return (inType & targetType) == targetType;
}
private bool HasHandOrientationType(ActiveHandOrientationType inType, ActiveHandOrientationType targetType)
{
return (inType & targetType) == targetType;
}
private bool HasHandInteractorType(ActiveHandInteractorType inType, ActiveHandInteractorType targetType)
{
return (inType & targetType) == targetType;
}
private bool HasWatchType(ActiveWatchType inType, ActiveWatchType targetType)
{
return (inType & targetType) == targetType;
}
private bool HasHeadHandType(ActiveHeadHandType inType, ActiveHeadHandType targetType)
{
return (inType & targetType) == targetType;
}
private bool JudgeHandLost(bool disableOnHandLost, bool handLost)
{
if (disableOnHandLost == false)
{
return true;
}
else
{
return handLost;
}
}
#endregion
#region Convert
private ActiveHandInteractorType ConvertType(InteractorType interactorType)
{
switch (interactorType)
{
case InteractorType.Far:
return ActiveHandInteractorType.Far;
case InteractorType.Near:
return ActiveHandInteractorType.Near;
}
return default(ActiveHandInteractorType);
}
private ActiveHandOrientationType ConvertType(HandOrientation handOrientation)
{
switch (handOrientation)
{
case HandOrientation.Back:
return ActiveHandOrientationType.Back;
case HandOrientation.Palm:
return ActiveHandOrientationType.Palm;
}
return default(ActiveHandOrientationType);
}
#endregion
#region PlayAudio
private AudioSource _audioSource;
public void InitModuleChangeAudio()
{
if (!muteModuleActiveSound)
{
AudioClip audioClip = (AudioClip)Resources.Load("Audio/ModuleChangeAudio");
_audioSource = gameObject.AddComponent();
_audioSource.clip = audioClip;
_audioSource.playOnAwake = false;
}
}
public void PlayModuleChangeAudio(InputModuleType type)
{
if (!muteModuleActiveSound)
{
_audioSource?.Play();
}
}
#endregion
}
}