VRDash/VRDash/Overlay/Config/OverlayLocation/ControllerLocation.cs

124 lines
4.5 KiB
C#

using Newtonsoft.Json;
using OpenTK;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Valve.VR;
using VRDash.UI.LocationEditors;
using VRDash.Utilities;
namespace VRDash.Overlay.Config.OverlayLocation
{
[OverlayLocationInfo("Controller", typeof(ControllerLocationEditor))]
public class ControllerLocation : IOverlayLocation
{
public ControllerHand Controller { get; set; } = ControllerHand.Left;
[JsonIgnore]
public Matrix3x4 Location { get; private set; } = new Matrix3x4(new Vector4(1, 0, 0, 0),
new Vector4(0, 1, 0, 0),
new Vector4(0, 0, 1, 0));
public float PosX { get; set; } = 0;
public float PosY { get; set; } = 0;
public float PosZ { get; set; } = 0;
public float RotP { get; set; } = 0;
public float RotY { get; set; } = 0;
public float RotR { get; set; } = 0;
public float ScaleX { get; set; } = 1;
public float ScaleY { get; set; } = 1;
public float ScaleZ { get; set; } = 1;
uint m_ControllerIndex = OpenVR.k_unTrackedDeviceIndexInvalid;
DateTime m_LastCheck = DateTime.MinValue;
IOverlay m_Overlay = null;
public OverlayHandles CreateOverlay(string key, string name, IOverlay overlay)
{
ulong overlayHandle = 0;
EVROverlayError err = OpenVR.Overlay.CreateOverlay(key, name, ref overlayHandle);
if (err != EVROverlayError.None){
throw new Exception($"Error creating overlay: {err}");
}
ETrackedDeviceClass type = OpenVR.System.GetTrackedDeviceClass(0);
overlay.Update += Overlay_Update;
m_Overlay = overlay;
return new OverlayHandles(overlayHandle, 0);
}
private void Overlay_Update(object sender, EventArgs e)
{
//Check if handle is invalid or if we should just refresh just in case.
if(m_ControllerIndex == OpenVR.k_unTrackedDeviceIndexInvalid || DateTime.Now.Subtract(m_LastCheck).TotalSeconds >= 1)
{
//Get proper hand
ETrackedControllerRole role = Controller == ControllerHand.Left ? ETrackedControllerRole.LeftHand : ETrackedControllerRole.RightHand;
uint controllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(role);
MathHelper.DegreesToRadians(RotP);
var quat = Quaternion.FromEulerAngles(MathHelper.DegreesToRadians(RotP), MathHelper.DegreesToRadians(RotY), MathHelper.DegreesToRadians(RotR));
Location = Matrix3x4.Mult(Matrix3x4.CreateTranslation(PosX, PosY, PosZ), Matrix3x4.Mult(Matrix3x4.CreateFromQuaternion(quat), Matrix3x4.CreateScale(ScaleX, ScaleY, ScaleZ)));
if (m_Overlay.OverlayHandle == OpenVR.k_ulOverlayHandleInvalid) { return; }
//Index changed, need to update the overlay
if (controllerIndex != m_ControllerIndex)
{
m_ControllerIndex = controllerIndex;
var matrix = Location.ToOpenVRMatrix();
var err = OpenVR.Overlay.SetOverlayTransformTrackedDeviceRelative(m_Overlay.OverlayHandle, m_ControllerIndex, ref matrix);
if (err != EVROverlayError.None)
{
this.GetLogger(m_Overlay).Warn($"Error setting tracked device relative to {Controller} hand: {err}");
}
else
{
this.GetLogger(m_Overlay).Info($"Controller index updated.");
}
}
else
{
//Update the location
var matrix = Location.ToOpenVRMatrix();
var err = OpenVR.Overlay.SetOverlayTransformTrackedDeviceRelative(m_Overlay.OverlayHandle, m_ControllerIndex, ref matrix);
if (err != EVROverlayError.None)
{
this.GetLogger(m_Overlay).Warn($"Error updating tracked device relative to {Controller} hand: {err}");
}
}
m_LastCheck = DateTime.Now;
}
}
public void ResetCheckTimer()
{
m_LastCheck = DateTime.MinValue;
}
public enum ControllerHand
{
Left = 0,
Right = 1
}
}
}