pixelgon/Assets/Scripts/Input.cs

170 lines
No EOL
4.2 KiB
C#

using System;
using UnityEngine;
[Serializable]
public class Input
{
public OculusInject oculusInject;
// have to use a transform for the head (and put it in a rig :/)
public Transform rig, head;
// two controllers (chiral)
public bool leftHanded; // tells the input injector the handedness
public Con mainCon, offCon;
[HideInInspector]
public Vector3 twistCursor;
[HideInInspector]
public Vector3 stretchCursor;
Vector3 mainCalibDir;
Quaternion mainCalibRot;
float calibDist, calibZ;
public void Frame()
{
oculusInject.Frame(this);
// Calibrate/Recenter
if (offCon.one.held) // temporary mapping
{
rig.position = -head.localPosition; // that zeros us out for an offset
rig.position += head.localRotation * Vector3.back * 0.666f;
mainCalibDir = Vector3.zero - WorldPos(mainCon).normalized;
mainCalibRot = mainCon.physical.Rot();
calibDist = Vector3.Distance(Vector3.zero, WorldPos(mainCon));
calibZ = Vector3.Angle(
offCon.physical.Rot() * Vector3.up,
WorldPos(mainCon) - WorldPos(offCon)
) / 90f;
}
float zValue = Vector3.Angle(
offCon.physical.Rot() * Vector3.up,
WorldPos(mainCon) - WorldPos(offCon)
) / 90f; // 0in - 1neutral - 2out
zValue = 1 + zValue - calibZ;
Quaternion rot = mainCon.physical.Rot() * Quaternion.Inverse(mainCalibRot);
twistCursor = WorldPos(mainCon) + rot * mainCalibDir * calibDist * zValue;
float stretch = Vector3.Distance(WorldPos(mainCon), WorldPos(offCon));
stretchCursor = WorldPos(mainCon) + mainCon.physical.Rot() * Vector3.forward * stretch * 3;
// Some way to switch between
// based on implementation (where switching needs to occur)
}
public Vector3 WorldPos(Con con)
{
return rig.TransformPoint(con.physical.Pos());
}
}
[Serializable]
public class Con
{
public Physical physical;
public Btn trigger, one, two;
[Serializable]
public class Btn
{
public bool down, held, up;
}
}
[Serializable]
public class Physical
{
Vector3 pos, posVel;
Quaternion rot, rotVel;
public Vector3 Pos() { return pos; }
public Vector3 PosVel() { return posVel; }
public Quaternion Rot() { return rot; }
public Quaternion RotVel() { return rotVel; }
float lastSet = 0;
public void Set(Vector3 pos, Quaternion rot, float delta)
{
// Vel time since last set? and throw away anything = 0 or greater then x
float setDelta = Time.time - lastSet;
if (setDelta == 0 || setDelta > 1)
{
this.posVel = Vector3.zero;
this.rotVel = Quaternion.identity;
}
else
{
this.posVel = (pos - this.pos) / delta;
this.rotVel = Quaternion.SlerpUnclamped(Quaternion.identity, rot * Quaternion.Inverse(this.rot), 1 / delta);
}
this.pos = pos;
this.rot = rot;
lastSet = Time.time;
}
}
[Serializable]
public class OculusInject
{
float lastTime, delta;
public void Frame(Input input)
{
delta = Time.time - lastTime;
Controller(input.offCon, input.leftHanded ? OVRInput.Controller.RTouch : OVRInput.Controller.LTouch);
Controller(input.mainCon, input.leftHanded ? OVRInput.Controller.LTouch : OVRInput.Controller.RTouch);
lastTime = Time.time;
}
void Controller(Con con, OVRInput.Controller touchCon)
{
con.physical.Set(
OVRInput.GetLocalControllerPosition(touchCon),
OVRInput.GetLocalControllerRotation(touchCon),
delta
);
con.trigger.down = con.trigger.up = false;
if (OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger, touchCon))
{
if (!con.trigger.held) { con.trigger.down = true; }
con.trigger.held = true;
}
else
{
if (con.trigger.held) { con.trigger.up = true; }
con.trigger.held = false;
}
con.one.down = con.one.up = false;
if (OVRInput.Get(OVRInput.Button.One, touchCon))
{
if (!con.one.held) { con.one.down = true; }
con.one.held = true;
}
else
{
if (con.one.held) { con.one.up = true; }
con.one.held = false;
}
con.two.down = con.two.up = false;
if (OVRInput.Get(OVRInput.Button.Two, touchCon))
{
if (!con.two.held) { con.two.down = true; }
con.two.held = true;
}
else
{
if (con.two.held) { con.two.up = true; }
con.two.held = false;
}
}
}