using System.Collections.Generic;
using UnityEngine;
using Rokid.UXR.Config;
using Rokid.UXR.Utility;
namespace Rokid.UXR.Interaction
{
public class HandRender : AutoInjectBehaviour
{
///
/// Is handtype
///
public HandType handType;
///
/// Is draw handmesh
///
public bool drawMesh = false;
///
/// Is draw skeleton
///
public bool drawSkeleton = true;
///
/// Is draw skeleton line only drawSkeleton is true will draw
///
public bool drawSkeletonLine = false;
///
/// Is draw hand root axis
///
public bool drawHandRootAxis = false;
///
/// Is show debugtext
///
public bool showDebugText = false;
///
/// Bone node templates are used to generate bone
///
public GameObject skeletonNode;
///
/// The bone alignment template is used to create the lines before the bone
///
public LineRenderer skeletonLine;
///
/// Coordinate axis
/// s
[SerializeField, Autowrited("HandRootAxis")]
private Transform handRootAxis;
///
/// 手的渲染
///
[SerializeField, Autowrited("RKHandVisual")]
private HandVisual handVisual;
///
/// 调试模式的手
///
[SerializeField, Autowrited("HandGestureInEditor")]
private Transform handVisualInEditor;
private TextMesh debugText;
private Dictionary skeletonLineDict = new Dictionary();
private Dictionary skeletonDict = new Dictionary();
private void Start()
{
GesEventInput.OnTrackedFailed += OnTrackedFailed;
Init();
#if UNITY_EDITOR
handVisualInEditor?.gameObject.SetActive(true);
#else
Destroy(handVisualInEditor?.gameObject);
#endif
}
private void OnEnable()
{
GesEventInput.OnRenderHand += OnRenderHand;
}
private void OnDisable()
{
GesEventInput.OnRenderHand -= OnRenderHand;
}
private void Init()
{
if (Utils.IsAndroidPlatfrom() && drawMesh == false)
{
Destroy(handVisual.GetComponent());
handVisual.gameObject.SetActive(false);
}
if (UXRSDKConfig.Instance.URPActive)
{
handVisual.UpdateHandMeshMaterials(new Material[]{
Resources.Load("Materials/URP/RokidHand"), Resources.Load("Materials/URP/HandMesh_Finger")
});
}
if (showDebugText)
{
if (debugText == null)
{
debugText = new GameObject("_debug_text").AddComponent();
debugText.fontSize = 120;
debugText.characterSize = 0.001f;
debugText.transform.parent = transform;
debugText.color = Color.green;
debugText.transform.localScale = Vector3.one;
debugText.transform.localRotation = Quaternion.Euler(0.0f, 0.0f, 0.0f);
}
debugText.gameObject.SetActive(false);
}
}
private void OnDestroy()
{
GesEventInput.OnTrackedFailed -= OnTrackedFailed;
}
private void OnTrackedFailed(HandType handType)
{
if (handType == this.handType || handType == HandType.None)
{
if (drawHandRootAxis)
handRootAxis.gameObject.SetActive(false);
if (showDebugText)
debugText.gameObject.SetActive(false);
}
}
private void OnRenderHand(HandType handType, GestureBean bean)
{
if (handType == this.handType)
{
if (bean.skeletons != null && bean.skeletons.Length > 0)
{
if (drawSkeleton)
DrawSkeleton(bean.skeletons, bean.skeletonsRot);
if (drawHandRootAxis)
{
handRootAxis.gameObject.SetActive(true);
handRootAxis.transform.SetPose(GesEventInput.Instance.GetHandPose(handType));
}
}
}
}
void DrawSkeleton(Vector3[] skeletons, Quaternion[] rotations)
{
if (skeletons.Length == 0 || drawSkeleton == false)
{
return;
}
//绘制骨骼点
for (int i = 0; i < skeletons.Length; i++)
{
GameObject go = null;
SkeletonIndexFlag indexFlag = (SkeletonIndexFlag)i;
if (skeletonDict.ContainsKey(indexFlag))
{
go = skeletonDict[indexFlag];
}
else
{
go = GameObject.Instantiate(skeletonNode);
go.GetComponent().enabled = true;
go.name = indexFlag.ToString();
go.transform.SetParent(transform);
skeletonDict.Add(indexFlag, go);
}
go.gameObject.SetActive(true);
go.transform.position = skeletons[i];
go.transform.rotation = rotations[i];
}
if (drawSkeletonLine)
{
for (int i = 0; i < 5; i++)
{
LineRenderer skeletonLine = null;
string lineName = handType == HandType.RightHand ? "right_skeletonLine" + i : "left_skeletonLine" + i;
if (skeletonLineDict.ContainsKey(lineName))
{
skeletonLine = skeletonLineDict[lineName];
}
else
{
skeletonLine = GameObject.Instantiate(this.skeletonLine);
skeletonLine.name = lineName;
skeletonLineDict.Add(lineName, skeletonLine);
}
skeletonLine.gameObject.SetActive(true);
skeletonLine.transform.SetParent(transform);
for (int j = 0; j < 5; j++)
{
int index = j == 0 ? 0 : i * 4 + j;
skeletonLine.SetPosition(j, skeletons[index]);
}
}
}
}
private void Update()
{
if (showDebugText)
{
debugText.gameObject.SetActive(true);
debugText.transform.SetPose(GesEventInput.Instance.GetHandPose(handType));
if (handType == HandType.RightHand)
{
debugText.transform.position += new Vector3(-0.05f, 0.1f, 0.0f);
debugText.alignment = TextAlignment.Right;
debugText.anchor = TextAnchor.UpperRight;
}
else
{
debugText.transform.position += new Vector3(0.05f, 0.1f, 0.0f);
debugText.alignment = TextAlignment.Left;
debugText.anchor = TextAnchor.UpperLeft;
}
debugText.text = string.Format(
"WristPos: {0}\n" +
"GestureType: {1}\n" +
"HandType: {2}\n" +
"HandOrientation: {3}\n" +
"HandRotation: {4}\n",
GesEventInput.Instance.GetSkeletonPose(SkeletonIndexFlag.WRIST, handType).position.ToString("0.000"),
GesEventInput.Instance.GetGesture(handType).gesType.ToString(),
handType.ToString(),
GesEventInput.Instance.GetGesture(handType).handOrientation == 0 ? HandOrientation.Palm : HandOrientation.Back,
GesEventInput.Instance.GetHandPose(handType).rotation.eulerAngles.ToString("0.000"));
}
else
{
if (debugText != null)
{
Destroy(debugText.gameObject);
}
}
}
}
}