Skip to content

Commit

Permalink
JointFollower data set with datum properties
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmed-shariff committed Jan 16, 2024
1 parent e9e949c commit 6379889
Show file tree
Hide file tree
Showing 14 changed files with 179 additions and 104 deletions.
31 changes: 0 additions & 31 deletions Editor/ConditionalFieldAttributeDrawer.cs

This file was deleted.

35 changes: 35 additions & 0 deletions Editor/JointFollowerDataPropertyDrawer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using UnityEditor;
using ubco.ovilab.HPUI.Tracking;
using UnityEngine;

namespace ubco.ovilab.HPUI.Editor
{
[CustomPropertyDrawer(typeof(JointFollowerData))]
public class JointFollowerDataPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);

position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);

EditorGUI.indentLevel++;

EditorGUILayout.PropertyField(property.FindPropertyRelative("handedness"));
EditorGUILayout.PropertyField(property.FindPropertyRelative("jointID"));
SerializedProperty useSecondJointIDProp = property.FindPropertyRelative("useSecondJointID");
EditorGUILayout.PropertyField(useSecondJointIDProp);
bool guiEnabled = GUI.enabled;
GUI.enabled = useSecondJointIDProp.boolValue;
EditorGUILayout.PropertyField(property.FindPropertyRelative("secondJointID"));
GUI.enabled = guiEnabled;
EditorGUILayout.PropertyField(property.FindPropertyRelative("defaultJointRadius"));
EditorGUILayout.PropertyField(property.FindPropertyRelative("offsetAngle"));
EditorGUILayout.PropertyField(property.FindPropertyRelative("offsetAsRatioToRadius"));
EditorGUILayout.PropertyField(property.FindPropertyRelative("longitudinalOffset"));

EditorGUI.indentLevel--;
EditorGUI.EndProperty();
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions Editor/JointFollowerDatumPropertyDrawer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using UnityEditor;
using Unity.XR.CoreUtils.Datums.Editor;
using ubco.ovilab.HPUI.Tracking;

namespace ubco.ovilab.HPUI.Editor
{
[CustomPropertyDrawer(typeof(JointFollowerDatumProperty))]
public class JointFollowerDatumPropertyDrawer : DatumPropertyDrawer
{
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Editor/ubco.ovilab.HPUI.Editor.asmdef
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"references": [
"ubco.ovilab.HPUI",
"Unity.XR.Interaction.Toolkit",
"Unity.XR.Interaction.Toolkit.Editor"
"Unity.XR.Interaction.Toolkit.Editor",
"Unity.XR.CoreUtils.Editor"
],
"includePlatforms": [
"Editor"
Expand Down
2 changes: 1 addition & 1 deletion Runtime/Interaction/HPUIContinuousInteractable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ private List<Transform> SetupKeypoints()
{
GameObject obj = new GameObject($"{Handedness}_{jointID}");
JointFollower jointFollower = obj.AddComponent<JointFollower>();
jointFollower.SetParams(Handedness, jointID, 0, 0, 0);
jointFollower.SetData(new JointFollowerData(Handedness, jointID, 0, 0, 0));

Transform keypoint = obj.transform;
keypoint.parent = this.transform;
Expand Down
71 changes: 30 additions & 41 deletions Runtime/Tracking/JointFollower.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using ubco.ovilab.HPUI.Utils;
using UnityEngine;
using UnityEngine.XR.Hands;

Expand All @@ -10,28 +9,21 @@ namespace ubco.ovilab.HPUI.Tracking
/// </summary>
public class JointFollower: MonoBehaviour
{
[Tooltip("The handedness of the joint to follow")]
public Handedness handedness;
[Tooltip("The joint to follow.")]
public XRHandJointID jointID;
[Tooltip("Should a second joint be used. If `useSecondJointID` is true, offsetAlongJoint behaves differently.")]
public bool useSecondJointID;
[Tooltip("Second joint to use as reference. If `useSecondJointID` is true, offsetAlongJoint behaves differently.")]
[ConditionalField("useSecondJointID")]
public XRHandJointID secondJointID;
[Tooltip("Default joint radius to use when joint radius is not provided by XR Hands. In unity units.")]
public float defaultJointRadius = 0.01f;

[Tooltip("(optional) The target transform to use. If not set, use this transform.")]
public Transform targetTransform;
[SerializeField]
[Tooltip("Joint follower data to use for this Joint.")]
private JointFollowerDatumProperty jointFollowerData = new JointFollowerDatumProperty(new JointFollowerData());
/// <summary>
/// Joint follower data to use for this Joint.
/// </summary>
public JointFollowerDatumProperty JointFollowerDatumProperty { get => jointFollowerData; set => jointFollowerData = value; }

[Tooltip("The offset angle.")][SerializeField]
public float offsetAngle = 0f;
[Tooltip("The offset as a ratio of the joint radius.")][SerializeField]
public float offsetAsRatioToRadius = 1f;
[Tooltip("The offset along joint (the joint's up) if no secondJoint is set. Otherwise, the position along joint as a ratio to the distance between jointID and secondJointID. In unity units.")]
[SerializeField]
public float longitudinalOffset = 0f;
[Tooltip("(optional) The target transform to use. If not set, use this transform.")]
private Transform targetTransform;
/// <summary>
/// The target transform to use. If not set, use this transform.
/// </summary>
public Transform TargetTransform { get => targetTransform; set => targetTransform = value; }

private float cachedRadius = 0f;
private XRHandSubsystem handSubsystem;
Expand Down Expand Up @@ -70,9 +62,9 @@ protected void Update()
/// <inheritdoc />
protected void OnEnable()
{
if (targetTransform == null)
if (TargetTransform == null)
{
targetTransform = transform;
TargetTransform = transform;
}

SubscribeHandSubsystem();
Expand Down Expand Up @@ -124,13 +116,9 @@ private void UnsubscribeHandSubsystem()
/// <summary>
/// Set the parameters of this JointFollower.
/// </summary>
public void SetParams(Handedness handedness, XRHandJointID jointID, float offsetAngle, float offsetAsRationToRadius, float longitudinalOffset)
public void SetData(JointFollowerData jointFollowerData)
{
this.handedness = handedness;
this.jointID = jointID;
this.offsetAngle = offsetAngle;
this.offsetAsRatioToRadius = offsetAsRationToRadius;
this.longitudinalOffset = longitudinalOffset;
this.jointFollowerData.Value = jointFollowerData;
}

private void OnUpdatedHands(XRHandSubsystem subsystem,
Expand All @@ -143,11 +131,11 @@ private void OnUpdatedHands(XRHandSubsystem subsystem,
// Update game logic that uses hand data
break;
case XRHandSubsystem.UpdateType.BeforeRender:
if (handedness == Handedness.Left)
if (jointFollowerData.Value.handedness == Handedness.Left)
{
ProcessJointData(subsystem.leftHand);
}
else if (handedness == Handedness.Right)
else if (jointFollowerData.Value.handedness == Handedness.Right)
{
ProcessJointData(subsystem.rightHand);
}
Expand All @@ -160,16 +148,17 @@ private void OnUpdatedHands(XRHandSubsystem subsystem,
/// </summary>
private void ProcessJointData(XRHand hand)
{
XRHandJoint mainJoint = hand.GetJoint(jointID);
JointFollowerData jointFollowerDataValue = jointFollowerData.Value;
XRHandJoint mainJoint = hand.GetJoint(jointFollowerDataValue.jointID);
bool mainPoseSuccess = mainJoint.TryGetPose(out Pose mainJointPose);
bool mainRadiusSuccess = mainJoint.TryGetRadius(out float mainRadius);

XRHandJoint secondJoint;
bool secondPoseSuccess = false;
Pose secondJointPose = default;
if (useSecondJointID)
if (jointFollowerDataValue.useSecondJointID)
{
secondJoint = hand.GetJoint(secondJointID);
secondJoint = hand.GetJoint(jointFollowerDataValue.secondJointID);
secondPoseSuccess = secondJoint.TryGetPose(out secondJointPose);
}

Expand All @@ -179,26 +168,26 @@ private void ProcessJointData(XRHand hand)
}
else if (cachedRadius == 0)
{
cachedRadius = defaultJointRadius;
cachedRadius = jointFollowerDataValue.defaultJointRadius;
}

if (mainPoseSuccess && (!useSecondJointID || secondPoseSuccess))
if (mainPoseSuccess && (!jointFollowerDataValue.useSecondJointID || secondPoseSuccess))
{
Vector3 poseForward = mainJointPose.forward;
Vector3 jointPlaneOffset;
if (offsetAngle == 0 || offsetAsRatioToRadius == 0)
if (jointFollowerDataValue.offsetAngle == 0 || jointFollowerDataValue.offsetAsRatioToRadius == 0)
{
jointPlaneOffset = -mainJointPose.up;
}
else
{
jointPlaneOffset = Quaternion.AngleAxis(offsetAngle, poseForward) * -mainJointPose.up;
jointPlaneOffset = Quaternion.AngleAxis(jointFollowerDataValue.offsetAngle, poseForward) * -mainJointPose.up;
}

Vector3 jointLongitudianlOffset = secondPoseSuccess ? (secondJointPose.position - mainJointPose.position) * longitudinalOffset : poseForward * longitudinalOffset;
Vector3 jointLongitudianlOffset = secondPoseSuccess ? (secondJointPose.position - mainJointPose.position) * jointFollowerDataValue.longitudinalOffset : poseForward * jointFollowerDataValue.longitudinalOffset;

targetTransform.rotation = Quaternion.LookRotation(poseForward, jointPlaneOffset);
targetTransform.position = mainJointPose.position + jointPlaneOffset * (cachedRadius * offsetAsRatioToRadius) + jointLongitudianlOffset;
TargetTransform.rotation = Quaternion.LookRotation(poseForward, jointPlaneOffset);
TargetTransform.position = mainJointPose.position + jointPlaneOffset * (cachedRadius * jointFollowerDataValue.offsetAsRatioToRadius) + jointLongitudianlOffset;
}
}
}
Expand Down
44 changes: 44 additions & 0 deletions Runtime/Tracking/JointFollowerData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using UnityEngine;
using UnityEngine.XR.Hands;

namespace ubco.ovilab.HPUI.Tracking
{
/// <summary>
/// Represents the joint follower data to be used.
/// </summary>
[Serializable]
public class JointFollowerData
{
[Tooltip("The handedness of the joint to follow")]
public Handedness handedness;
[Tooltip("The joint to follow.")]
public XRHandJointID jointID;
[Tooltip("Should a second joint be used. If `useSecondJointID` is true, offsetAlongJoint behaves differently.")]
public bool useSecondJointID;
[Tooltip("Second joint to use as reference. If `useSecondJointID` is true, offsetAlongJoint behaves differently.")]
public XRHandJointID secondJointID;
[Tooltip("Default joint radius to use when joint radius is not provided by XR Hands. In unity units.")]
public float defaultJointRadius = 0.01f;

[Tooltip("The offset angle.")][SerializeField]
public float offsetAngle = 0f;
[Tooltip("The offset as a ratio of the joint radius.")][SerializeField]
public float offsetAsRatioToRadius = 1f;
[Tooltip("The offset along joint (the joint's up) if no secondJoint is set. Otherwise, the position along joint as a ratio to the distance between jointID and secondJointID. In unity units.")]
[SerializeField]
public float longitudinalOffset = 0f;

public JointFollowerData()
{}

public JointFollowerData(Handedness handedness, XRHandJointID jointID, float offsetAngle, float offsetAsRationToRadius, float longitudinalOffset)
{
this.handedness = handedness;
this.jointID = jointID;
this.offsetAngle = offsetAngle;
this.offsetAsRatioToRadius = offsetAsRationToRadius;
this.longitudinalOffset = longitudinalOffset;
}
}
}
11 changes: 11 additions & 0 deletions Runtime/Tracking/JointFollowerData.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions Runtime/Tracking/JointFollowerDatum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using UnityEngine;
using Unity.XR.CoreUtils.Datums;

namespace ubco.ovilab.HPUI.Tracking
{
/// <summary>
/// <see cref="ScriptableObject"/> container class that holds a <see cref="JointFollowerData"/> value.
/// </summary>
[CreateAssetMenu(fileName = "JointFollowerData", menuName = "HPUI/JointFollowerData", order = 1)]
public class JointFollowerDatum: Datum<JointFollowerData>
{
}

/// <summary>
/// Serializable container class that holds a JointFollower data value or container asset reference.
/// </summary>
/// <seealso cref="JointFollowerData"/>
[Serializable]
public class JointFollowerDatumProperty: DatumProperty<JointFollowerData, JointFollowerDatum>
{
/// <inheritdoc/>
public JointFollowerDatumProperty(JointFollowerData value) : base(value)
{
}

/// <inheritdoc/>
public JointFollowerDatumProperty(JointFollowerDatum datum) : base(datum)
{
}
}
}
11 changes: 11 additions & 0 deletions Runtime/Tracking/JointFollowerDatum.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 0 additions & 8 deletions Runtime/utils.meta

This file was deleted.

20 changes: 0 additions & 20 deletions Runtime/utils/ConditionalFieldAttribute.cs

This file was deleted.

0 comments on commit 6379889

Please sign in to comment.