using System;
using System.Collections;
using System.Collections.Generic;
using EZXR.Glass.Core;
using EZXR.Glass.Inputs;
using EZXR.Glass.SixDof;
using UnityEngine;
namespace EZXR.Glass.Inputs
{
[ScriptExecutionOrder(-48)]
public class ControllerInfo : InputInfoBase
{
public Transform handleOrigin;
public Transform tipPoint;
///
/// 手柄当前是否已配对
///
protected bool isBinding = false;
public bool IsBinding
{
get
{
return isBinding;
}
}
///
/// 手柄当前是否已连接
///
protected bool isConnected = false;
public bool IsConnected
{
get
{
return isConnected;
}
}
///
/// 手柄当前电量
///
protected float powerStats = 0.0f;
public float PowerStats
{
get
{
return powerStats;
}
}
///
/// 手柄当前是否被握持
///
protected bool isHeld;
public bool IsHeld
{
get
{
return isHeld;
}
}
///
/// 手柄当前是否被静置
///
protected bool isSilent;
public bool IsSilent
{
get
{
return isSilent;
}
}
protected Vector2 axis2DCoord;
///
/// 监听手柄的生命状态改变(立即发生)
///
private bool bindingChanged = false;
private bool connectedChanged = false;
private bool powerChanged = false;
private bool holdChanged = false;
private bool silenceChanged = false;
///
/// 监听到生命状态改变的回调(在Update中发生)
/// 可能立即发生也可能滞后一帧
///
private Action bindingAction;
private Action connectedAction;
private Action powerChangedAction;
private Action holdChangedAction;
private Action silenceChangedAction;
/// 保存按键状态(在Update中发生,可能立即发生也可能滞后一帧)
private Dictionary buttonState;
/// 监听按键状态的改变(立即发生)
private Dictionary buttonStateChanged;
//private Dictionary buttonDownTimeSpan;
private bool isPaused = false;
///
/// 当前眼镜视野中是否存在这个手
///
public override bool Exist
{
get
{
if (Application.isEditor)
{
return true;
}
return isConnected;
}
}
///
/// 手掌正在朝向头部
///
///
///
public override bool isPalmFacingHead(float angle = 90) { return false; }
#region 手交互能力开关
///
/// 设置或获得当前手的显示状态(仅仅影响显示,并不影响交互)
///
private bool visibility = true;
public override bool Visibility
{
get
{
/*if (handType == HandType.Left) return false;
else */return visibility;
}
set
{
// 判断是否开发者自定义了手柄模型
//if (handType == HandType.Right)
{
var dummy = handType == HandType.Left ? "LeftDummy" : "RightDummy";
// 若在handleOrigin下添加自定义的手柄模型,则隐藏默认手柄
var hasAlter = handleOrigin.GetComponentsInChildren().Length > 0;
if (!hasAlter) transform.Find(dummy).gameObject.SetActive(value);
else handleOrigin.gameObject.SetActive(value);
visibility = value;
}
}
}
///
/// 设置或获得远距离射线交互状态
///
public override bool RaycastInteraction
{
get
{
return GetComponent().enabled;
}
set
{
GetComponent().enabled = value;
}
}
///
/// 设置或获得近距离交互状态
///
public override bool TouchInteraction
{
get
{
return false;
}
set
{
}
}
///
/// 设置或获得手部的物理碰撞交互状态
///
public override bool PhysicsInteraction
{
get
{
return false;
}
set
{
}
}
#endregion
protected override void Awake()
{
base.Awake();
buttonState = new Dictionary();
//buttonDownTimeSpan = new Dictionary();
buttonStateChanged = new Dictionary();
}
protected override void Update()
{
base.Update();
UpdateStatus();
if (handleOrigin != null)
{
//射线方向
if (!(HandleControllerManager.SetRayDirByExternal != null && HandleControllerManager.SetRayDirByExternal(this, ref rayDirection)))
{
rayDirection = handleOrigin.forward;
}
//射线起点
if (!(HandleControllerManager.SetRayStartPointByExternal != null && HandleControllerManager.SetRayStartPointByExternal(this, ref rayPoint_Start)))
{
rayPoint_Start = handleOrigin.position + rayDirection * rayStartDistance;
}
}
}
private void OnApplicationPause(bool pause)
{
//Debug.Log($"HandleControllerInfo, OnApplicationPause: pause = {pause} handType = {this.handType} isBinding = {isBinding}, isConnected = {isConnected}, powerStats = {powerStats} ({Time.frameCount})");
if (!pause)
{
isBinding = HandleControllerManager.Instance.GetBindState(handType);
isConnected = HandleControllerManager.Instance.GetConnectState(handType);
powerStats = HandleControllerManager.Instance.GetPowerStats(handType);
Debug.Log($"HandleControllerInfo, OnApplicationPause: pause = {pause} handType = {this.handType} isBinding = {isBinding}, isConnected = {isConnected}, powerStats = {powerStats}");
}
isPaused = pause;
//UpdatePinching();
buttonState.Clear(); buttonStateChanged.Clear();
startPinch = false; endPinch = false; isPinching = false;
}
private void OnEnable()
{
//Debug.Log($"HandleControllerInfo, OnEnable: handType = {this.handType} isBinding = {isBinding}, isConnected = {isConnected}, powerStats = {powerStats} ({Time.frameCount})");
isBinding = HandleControllerManager.Instance.GetBindState(handType);
isConnected = HandleControllerManager.Instance.GetConnectState(handType);
powerStats = HandleControllerManager.Instance.GetPowerStats(handType);
Debug.Log($"HandleControllerInfo, OnEnable: handType = {this.handType} isBinding = {isBinding}, isConnected = {isConnected}, powerStats = {powerStats}");
//UpdatePinching();
buttonState.Clear(); buttonStateChanged.Clear();
startPinch = false; endPinch = false; isPinching = false;
}
private void OnDisable()
{
//UpdatePinching();
buttonState.Clear(); buttonStateChanged.Clear();
startPinch = false; endPinch = false; isPinching = false;
Debug.Log($"HandleControllerInfo, OnDisable: handType = {this.handType} isBinding = {isBinding}, isConnected = {isConnected}, powerStats = {powerStats} ({Time.frameCount})");
}
public override void Init(HandType handType)
{
base.Init(handType);
//if (handType == HandType.Right)
{
// 若在handleOrigin下添加自定义的手柄模型,则隐藏默认手柄
var hasAlter = handleOrigin.GetComponentsInChildren().Length > 0;
// fix: 控制器切换时不能任意设置手柄显示
if (hasAlter) transform.Find(handType == HandType.Left ? "LeftDummy" : "RightDummy").gameObject.SetActive(!hasAlter);
}
isBinding = HandleControllerManager.Instance.GetBindState(handType);
isConnected = HandleControllerManager.Instance.GetConnectState(handType);
powerStats = HandleControllerManager.Instance.GetPowerStats(handType);
Debug.Log($"HandleControllerInfo, Init: handType = {this.handType} isBinding = {isBinding}, isConnected = {isConnected}, powerStats = {powerStats}");
StartCoroutine(CheckStatus());
}
public void UpdateBindingState(bool status, Action callback)
{
if (isBinding == status) return;
isBinding = status;
bindingChanged = true;
bindingAction = callback;
Debug.Log($"HandleControllerInfo, UpdateBinding: handType = {this.handType} isBinding = {status}");
if (isPaused || !gameObject.activeInHierarchy) UpdateStatus();
}
public void UpdateConnectedState(bool connected, Action callback)
{
if (isConnected == connected) return;
isConnected = connected;
connectedChanged = true;
connectedAction = callback;
Debug.Log($"HandleControllerInfo, UpdateConnectedState: handType = {this.handType} isConnected = {connected}");
if (!connected) { buttonState.Clear(); buttonStateChanged.Clear(); }
if (!connected) { startPinch = false; endPinch = false; isPinching = false; }
if (isPaused || !gameObject.activeInHierarchy) UpdateStatus();
}
public void UpdatePowerStats(float power, Action callback)
{
Debug.Log($"HandleControllerInfo, UpdatePowerStats: handType = {this.handType} power = {power}");
if (powerStats == power) return;
powerStats = power;
powerChanged = true;
powerChangedAction = callback;
if (isPaused || !gameObject.activeInHierarchy) UpdateStatus();
}
public void UpdateButtonState(HandleKeyCode keyCode, bool pressed)
{
if (isPaused || !gameObject.activeInHierarchy) return;
//Debug.Log($"HandleControllerInfo, {handType} {keyCode} StateChanged to {(pressed ? "pressed" : "released")} ({Time.frameCount})");
if (!buttonState.ContainsKey(keyCode))
{
buttonState[keyCode] = pressed ? HandleKeyEvent.Idle : HandleKeyEvent.Pressing;
buttonStateChanged[keyCode] = true;
}
else if ((pressed && buttonState[keyCode] == HandleKeyEvent.Idle) || (!pressed && buttonState[keyCode] == HandleKeyEvent.Pressing))
{
buttonStateChanged[keyCode] = true;
}
}
public void UpdateAxis2D(Vector2 coord)
{
if (isPaused || !gameObject.activeInHierarchy) return;
axis2DCoord = coord;
}
public void UpdateHoldState(bool isHeld, Action callback)
{
if (this.isHeld == isHeld) return;
this.isHeld = isHeld;
holdChanged = true;
holdChangedAction = callback;
//Debug.Log($"HandleControllerInfo, UpdateHoldState: handType = {this.handType} isHeld = {isHeld} ({Time.frameCount})");
if (isPaused || !gameObject.activeInHierarchy) UpdateStatus();
}
public void UpdateSilenceState(bool isSilent, Action callback)
{
if (this.isSilent == isSilent) return;
this.isSilent = isSilent;
silenceChanged = true;
silenceChangedAction = callback;
//Debug.Log($"HandleControllerInfo, UpdateSilenceState: handType = {this.handType} isSilent = {isSilent} ({Time.frameCount})");
if (isPaused || !gameObject.activeInHierarchy) UpdateStatus();
}
public bool GetButtonDown(HandleKeyCode keyCode)
{
if (!isPaused && isConnected && buttonState.ContainsKey(keyCode))
return buttonState[keyCode] == HandleKeyEvent.Down;
return false;
}
public bool GetButtonUp(HandleKeyCode keyCode)
{
if (!isPaused && isConnected && buttonState.ContainsKey(keyCode))
return buttonState[keyCode] == HandleKeyEvent.Up;
return false;
}
public bool GetButton(HandleKeyCode keyCode)
{
if (!isPaused && isConnected && buttonState.ContainsKey(keyCode))
return buttonState[keyCode] == HandleKeyEvent.Pressing;
return false;
}
public Vector2 GetAxis2D()
{
return axis2DCoord;
}
protected override void UpdatePinching()
{
var keys = new List(buttonStateChanged.Keys);
for (int j = 0; j < keys.Count; ++j)
{
var keyCode = keys[j];
if (!buttonStateChanged[keyCode]) continue;
if (buttonState[keyCode] == HandleKeyEvent.Idle)
{
buttonState[keyCode] = HandleKeyEvent.Down;
//Debug.Log($"HandleControllerInfo, {handType} {keyCode} change to Down from Idle ({Time.frameCount})");
//按下扳机键触发开始捏合动作
if (keyCode == HandleKeyCode.Trigger) startPinch = true;
}
else if (buttonState[keyCode] == HandleKeyEvent.Pressing)
{
buttonState[keyCode] = HandleKeyEvent.Up;
//Debug.Log($"HandleControllerInfo, {handType} {keyCode} change to Up from Pressing ({Time.frameCount})");
//松开扳机键触发结束捏合动作
if (keyCode == HandleKeyCode.Trigger) endPinch = true;
}
//buttonStateChanged.Remove(keyCode);
}
keys = new List(buttonState.Keys);
for (int i = 0; i < keys.Count; ++i)
{
var keyCode = keys[i];
if (buttonStateChanged.ContainsKey(keyCode))
{
buttonStateChanged.Remove(keyCode);
continue;
}
if (buttonState[keyCode] == HandleKeyEvent.Down)
{
buttonState[keyCode] = HandleKeyEvent.Pressing;
//Debug.Log($"HandleControllerInfo, {handType} {keyCode} change to Pressing from Down ({Time.frameCount})");
// startPinch结束,触发持续捏合
if (keyCode == HandleKeyCode.Trigger) { startPinch = false; isPinching = true; }
}
else if (buttonState[keyCode] == HandleKeyEvent.Up)
{
buttonState[keyCode] = HandleKeyEvent.Idle;
//Debug.Log($"HandleControllerInfo, {handType} {keyCode} change to Idle from Up ({Time.frameCount})");
// endPinch结束,触发结束捏合
if (keyCode == HandleKeyCode.Trigger) { endPinch = false; isPinching = false; }
}
}
}
private void UpdateStatus()
{
if (bindingChanged)
{
if (bindingAction != null) bindingAction(isBinding);
bindingChanged = false;
}
if (connectedChanged)
{
if (connectedAction != null) connectedAction(isConnected);
connectedChanged = false;
Visibility = isConnected;
RaycastInteraction = isConnected;
TouchInteraction = isConnected;
PhysicsInteraction = isConnected;
}
if (powerChanged)
{
if (powerChangedAction != null) powerChangedAction(powerStats);
powerChanged = false;
}
if (holdChanged)
{
if (holdChangedAction != null) holdChangedAction(isHeld);
holdChanged = false;
}
if (silenceChanged)
{
if (silenceChangedAction != null) silenceChangedAction(isSilent);
silenceChanged = false;
}
}
// for fix
public IEnumerator CheckStatus()
{
yield return new WaitUntil(() => SessionManager.Instance != null && SessionManager.Instance.IsInited);
isBinding = HandleControllerManager.Instance.GetBindState(handType);
isConnected = HandleControllerManager.Instance.GetConnectState(handType);
powerStats = HandleControllerManager.Instance.GetPowerStats(handType);
Debug.Log($"HandleControllerInfo, Check: handType = {this.handType} isBinding = {isBinding}, isConnected = {isConnected}, powerStats = {powerStats} ({Time.frameCount})");
Visibility = isConnected;
RaycastInteraction = isConnected;
TouchInteraction = isConnected;
PhysicsInteraction = isConnected;
}
}
}