209 lines
7.9 KiB
C#

using UnityEngine;
namespace Passer.Humanoid {
using Passer.Tracking;
/// <summary>
/// A custom sensor used on the arm of a humanoid
/// </summary>
/// This tracking option supports a custom developed ControllerComponent or HandSkeleton for the hand and/or arm.
[System.Serializable]
public class CustomArm : Passer.Humanoid.ArmSensor {
/// <summary>
/// The name of this sensor
/// </summary>
public override string name => "Custom Sensor";
/// <summary>
/// THe tracker for this sensor
/// </summary>
#if hCUSTOM
public override HumanoidTracker tracker => humanoid.custom;
#endif
/// <summary>
/// The tracker controller to use for this arm
/// </summary>
protected ControllerComponent controllerComponent;
/// <summary>
/// The bone on the arm controlled by the sensor
/// </summary>
public ArmBones attachedBone = ArmBones.Hand;
/// <summary>
/// The controller input for this humanoid
/// </summary>
protected Controller controllerInput;
#region Manage
/// <summary>
/// Updates the arm targets based on the current sensor position and rotation
/// </summary>
public override void SetSensor2Target() {
if (sensorComponent == null)
return;
HumanoidTarget.TargetedBone targetBone = handTarget.GetTargetBone(attachedBone);
if (targetBone == null)
return;
sensor2TargetRotation = Quaternion.Inverse(sensorComponent.transform.rotation) * targetBone.target.transform.rotation;
sensor2TargetPosition = -targetBone.target.transform.InverseTransformPoint(sensorComponent.transform.position);
}
/// <summary>
/// Updates the sensor position and rotation based on the current position of the arm targets.
/// </summary>
/// <param name="_">Not used</param>
public override void UpdateSensorTransformFromTarget(Transform _) {
if (handTarget == null)
return;
HumanoidTarget.TargetedBone targetBone = handTarget.GetTargetBone(attachedBone);
base.UpdateSensorTransformFromTarget(targetBone.target.transform);
}
#endregion Manage
#region Start
/// <summary>
/// Prepares the arm for tracking with the tracked controller and/or skeleton
/// </summary>
/// <param name="_humanoid">The humanoid for which this arm is tracked</param>
/// <param name="targetTransform">The transform of the hand target</param>
/// This will find and initialize the controllerInput for the given humanoid.
/// It will initialize the sensor2TargetPosition and sensor2TargetRotation values.
/// It will determine whether the sensor should be shown and rendered.
/// It will start the tracking for the controller and/or hand skeleton.
public override void Start(HumanoidControl _humanoid, Transform targetTransform) {
base.Start(_humanoid, targetTransform);
if (tracker == null || !tracker.enabled || !enabled)
return;
controllerComponent = sensorComponent as ControllerComponent;
controllerInput = Controllers.GetController(0);
handSkeleton = sensorComponent as HandSkeleton;
SetSensor2Target();
ShowSensor(handTarget.humanoid.showRealObjects && target.showRealObjects);
if (controllerComponent != null) {
if (tracker.trackerComponent != null)
controllerComponent.StartComponent(tracker.trackerComponent.transform, handTarget.isLeft);
else
controllerComponent.StartComponent(controllerComponent.transform.parent, handTarget.isLeft);
}
if (handSkeleton != null) {
if (tracker.trackerComponent != null)
handSkeleton.StartComponent(tracker.trackerComponent.transform);
else
handSkeleton.StartComponent(handSkeleton.transform.parent);
}
}
#endregion Start
#region Update
/// <summary>
/// Updates the arm target based on the status of the tracked controller and/or skeleton
/// </summary>
public override void Update() {
status = Tracker.Status.Unavailable;
if (tracker == null || !tracker.enabled || !enabled)
return;
if (sensorComponent == null)
return;
sensorComponent.UpdateComponent();
status = sensorComponent.status;
if (status != Tracker.Status.Tracking)
return;
HumanoidTarget.TargetedBone targetBone = handTarget.GetTargetBone(attachedBone);
UpdateTarget(targetBone.target, sensorComponent);
UpdateControllerInput();
UpdateHandFromSkeleton();
}
#region Controller
/// <summary>
/// Updates the Controller Input for this side
/// </summary>
protected void UpdateControllerInput() {
if (handTarget.isLeft)
UpdateControllerInput(controllerInput.left);
else
UpdateControllerInput(controllerInput.right);
}
/// <summary>
/// Updates one side of the ControllerInput from the values of the tracked ControllerComponent
/// </summary>
/// <param name="controllerSide">The controller side to update</param>
/// This function does nothing when the controller is not available or not tracking.
protected virtual void UpdateControllerInput(ControllerSide controllerSide) {
if (controllerSide == null)
return;
if (controllerComponent == null || controllerComponent.status != Tracker.Status.Tracking)
return;
controllerSide.stickHorizontal += controllerComponent.primaryAxis.x;
controllerSide.stickVertical += controllerComponent.primaryAxis.y;
controllerSide.stickButton |= (controllerComponent.primaryAxis.z > 0.5F);
controllerSide.stickTouch = true;
controllerSide.buttons[0] |= controllerComponent.button1 > 0.5F;
controllerSide.buttons[1] |= controllerComponent.button2 > 0.5F;
controllerSide.buttons[2] |= controllerComponent.button3 > 0.5F;
controllerSide.buttons[3] |= controllerComponent.button4 > 0.5F;
controllerSide.trigger1 += controllerComponent.trigger1;
controllerSide.trigger2 += controllerComponent.trigger2;
controllerSide.option |= controllerComponent.option > 0.5F;
}
#endregion Controller
#region Skeleton
/// <summary>
/// This function uses the tracked HandSkeleton to update the pose of the hand
/// </summary>
/// This function does nothing when the hand skeleton is not available or not tracking.
protected override void UpdateHandFromSkeleton() {
if (handSkeleton == null || handSkeleton.status != Tracker.Status.Tracking)
return;
Transform wristBone = handSkeleton.GetWristBone();
handTarget.hand.target.transform.position = wristBone.transform.position;
if (handTarget.isLeft)
handTarget.hand.target.transform.rotation = wristBone.transform.rotation * Quaternion.Euler(-90, 0, 90);
else
handTarget.hand.target.transform.rotation = wristBone.transform.rotation * Quaternion.Euler(-90, 0, -90);
UpdateThumbFromSkeleton();
UpdateIndexFingerFromSkeleton();
UpdateMiddleFingerFromSkeleton();
UpdateRingFingerFromSkeleton();
UpdateLittleFingerFromSkeleton();
}
#endregion Skeleton
#endregion Update
}
}