Update Cryville.Input.

This commit is contained in:
2023-05-07 13:42:53 +08:00
parent fa9303c0a1
commit bd028c1b72
17 changed files with 1336 additions and 579 deletions

View File

@@ -62,15 +62,15 @@ namespace Cryville.Crtr {
GameDataPath = Settings.Default.GameDataPath;
unity::Input.simulateMouseWithTouches = false;
//InputManager.HandlerRegistries.Add(typeof(AndroidAccelerometerHandler));
//InputManager.HandlerRegistries.Add(typeof(AndroidAccelerometerUncalibratedHandler));
//InputManager.HandlerRegistries.Add(typeof(AndroidGameRotationVectorHandler));
//InputManager.HandlerRegistries.Add(typeof(AndroidGravityHandler));
//InputManager.HandlerRegistries.Add(typeof(AndroidGyroscopeHandler));
//InputManager.HandlerRegistries.Add(typeof(AndroidLinearAccelerationHandler));
//InputManager.HandlerRegistries.Add(typeof(AndroidMagneticFieldHandler));
//InputManager.HandlerRegistries.Add(typeof(AndroidMagneticFieldUncalibratedHandler));
//InputManager.HandlerRegistries.Add(typeof(AndroidRotationVectorHandler));
InputManager.HandlerRegistries.Add(typeof(AndroidAccelerometerHandler));
InputManager.HandlerRegistries.Add(typeof(AndroidAccelerometerUncalibratedHandler));
InputManager.HandlerRegistries.Add(typeof(AndroidGameRotationVectorHandler));
InputManager.HandlerRegistries.Add(typeof(AndroidGravityHandler));
InputManager.HandlerRegistries.Add(typeof(AndroidGyroscopeHandler));
InputManager.HandlerRegistries.Add(typeof(AndroidLinearAccelerationHandler));
InputManager.HandlerRegistries.Add(typeof(AndroidMagneticFieldHandler));
InputManager.HandlerRegistries.Add(typeof(AndroidMagneticFieldUncalibratedHandler));
InputManager.HandlerRegistries.Add(typeof(AndroidRotationVectorHandler));
InputManager.HandlerRegistries.Add(typeof(AndroidTouchHandler));
InputManager.HandlerRegistries.Add(typeof(UnityGuiInputHandler<UnityKeyReceiver>));
InputManager.HandlerRegistries.Add(typeof(UnityGuiInputHandler<UnityMouseReceiver>));

View File

@@ -2,9 +2,10 @@ using System;
using UnityEngine;
namespace Cryville.Input.Unity.Android {
public abstract class AndroidInputHandler<TSelf> : InputHandler where TSelf : AndroidInputHandler<TSelf> {
protected static TSelf Instance { get; private set; }
/// <summary>
/// An <see cref="InputHandler" /> that handles Android input.
/// </summary>
public abstract class AndroidInputHandler : InputHandler {
readonly IntPtr _t_T;
static readonly jvalue[] _p_void = new jvalue[0];
readonly IntPtr _i_T;
@@ -14,12 +15,15 @@ namespace Cryville.Input.Unity.Android {
bool _activated;
/// <summary>
/// Creates an instance of the <see cref="AndroidInputHandler{TSelf}" /> class.
/// </summary>
/// <param name="className">The full name of the Java class that performs the low-level jobs.</param>
/// <exception cref="InvalidOperationException">An instance of this class have already been created.</exception>
/// <exception cref="NotSupportedException">Android input is not supported on the current device.</exception>
public AndroidInputHandler(string className) {
if (Instance != null)
throw new InvalidOperationException("AndroidInputHandler already created");
if (Environment.OSVersion.Platform != PlatformID.Unix)
throw new NotSupportedException("Android input is not supported on this device");
Instance = (TSelf)this;
JavaStaticMethods.Init();
@@ -36,24 +40,24 @@ namespace Cryville.Input.Unity.Android {
_m_T_activate = AndroidJNI.GetMethodID(_t_T, "activate", "()V");
_m_T_deactivate = AndroidJNI.GetMethodID(_t_T, "deactivate", "()V");
NativeMethods.AndroidInputProxy_RegisterCallback(
AndroidJNI.CallIntMethod(_i_T, _m_T_getId, _p_void),
Callback
);
AndroidInputPoller.Instance.Register(AndroidJNI.CallIntMethod(_i_T, _m_T_getId, _p_void), this);
}
/// <inheritdoc />
protected override void Activate() {
if (_activated) return;
_activated = true;
AndroidJNI.CallVoidMethod(_i_T, _m_T_activate, _p_void);
}
/// <inheritdoc />
protected override void Deactivate() {
if (!_activated) return;
_activated = false;
AndroidJNI.CallVoidMethod(_i_T, _m_T_deactivate, _p_void);
}
/// <inheritdoc />
public override void Dispose(bool disposing) {
if (disposing) {
Deactivate();
@@ -62,6 +66,6 @@ namespace Cryville.Input.Unity.Android {
}
}
private protected abstract AndroidInputProxy_Callback Callback { get; }
internal abstract void OnFeed(int id, int action, long time, float x, float y, float z, float w);
}
}

View File

@@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.Threading;
namespace Cryville.Input.Unity.Android {
internal class AndroidInputPoller {
static AndroidInputPoller m_instance;
public static AndroidInputPoller Instance {
get {
if (m_instance == null) m_instance = new AndroidInputPoller();
return m_instance;
}
}
readonly Thread _thread;
private AndroidInputPoller() {
_thread = new Thread(ThreadLogic);
_thread.Start();
}
readonly Dictionary<int, AndroidInputHandler> _handlers = new Dictionary<int, AndroidInputHandler>();
public void Register(int id, AndroidInputHandler handler) {
_handlers[id] = handler;
}
void ThreadLogic() {
while (true) {
while (NativeMethods.AndroidInputProxy_Poll(out var frame) == 1) {
_handlers[frame.hid].OnFeed(frame.id, frame.action, frame.time, frame.x, frame.y, frame.z, frame.w);
}
Thread.Sleep(1);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9b69004cd86eb0b42bfa2bcf3d1f7e87
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,21 +1,31 @@
using Cryville.Common.Interop;
using Cryville.Common.Logging;
using System;
using System.Text.RegularExpressions;
namespace Cryville.Input.Unity.Android {
public abstract class AndroidSensorHandler<TSelf> : AndroidInputHandler<AndroidSensorHandler<TSelf>> where TSelf : AndroidSensorHandler<TSelf> {
/// <summary>
/// An <see cref="InputHandler" /> that handles Android sensor input.
/// </summary>
public abstract class AndroidSensorHandler : AndroidInputHandler {
/// <summary>
/// Creates an instance of the <see cref="AndroidSensorHandler{TSelf}" /> class.
/// </summary>
/// <param name="typeName">The name of the Java class nested in <c>world/cryville/input/unity/android/SensorProxy</c> that performs the low-level jobs.</param>
/// <param name="dimension">The dimension.</param>
public AndroidSensorHandler(string typeName, byte dimension) : base("world/cryville/input/unity/android/SensorProxy$" + typeName) {
m_typeName = Regex.Replace(typeName, @"(?<=[a-z])(?=[A-Z])", " ");
m_dimension = dimension;
}
/// <inheritdoc />
public override bool IsNullable => false;
readonly byte m_dimension;
/// <inheritdoc />
public override byte Dimension => m_dimension;
readonly string m_typeName;
/// <inheritdoc />
public override string GetTypeName(int type) {
switch (type) {
case 0: return m_typeName;
@@ -23,17 +33,15 @@ namespace Cryville.Input.Unity.Android {
}
}
/// <inheritdoc />
public override double GetCurrentTimestamp() {
return JavaStaticMethods.SystemClock_elapsedRealtimeNanos() / 1e9;
}
private protected sealed override AndroidInputProxy_Callback Callback { get { return OnFeed; } }
[MonoPInvokeCallback]
static void OnFeed(int id, int action, long time, float x, float y, float z, float w) {
internal override void OnFeed(int id, int action, long time, float x, float y, float z, float w) {
try {
double timeSecs = time / 1e9;
Instance.Feed(0, id, new InputFrame(timeSecs, new InputVector(x, y, z, w)));
Feed(0, id, new InputFrame(timeSecs, new InputVector(x, y, z, w)));
}
catch (Exception ex) {
Logger.Log("main", 4, "Input", "An error occurred while handling an Android sensor event: {0}", ex);
@@ -41,67 +49,130 @@ namespace Cryville.Input.Unity.Android {
}
}
public class AndroidAccelerometerHandler : AndroidSensorHandler<AndroidAccelerometerHandler> {
/// <summary>
/// An <see cref="InputHandler" /> that handles Android accelerometer sensor input.
/// </summary>
public class AndroidAccelerometerHandler : AndroidSensorHandler {
/// <summary>
/// Creates an instance of the <see cref="AndroidAccelerometerHandler" /> class.
/// </summary>
public AndroidAccelerometerHandler() : base("Accelerometer", 3) { }
readonly static ReferenceCue _refCue = new ReferenceCue {
static readonly ReferenceCue _refCue = new ReferenceCue {
PhysicalDimension = new PhysicalDimension { Length = 1, Time = -2 },
};
/// <inheritdoc />
public override ReferenceCue ReferenceCue => _refCue;
}
public class AndroidAccelerometerUncalibratedHandler : AndroidSensorHandler<AndroidAccelerometerUncalibratedHandler> {
/// <summary>
/// An <see cref="InputHandler" /> that handles Android accelerometer (uncalibrated) sensor input.
/// </summary>
public class AndroidAccelerometerUncalibratedHandler : AndroidSensorHandler {
/// <summary>
/// Creates an instance of the <see cref="AndroidAccelerometerUncalibratedHandler" /> class.
/// </summary>
public AndroidAccelerometerUncalibratedHandler() : base("AccelerometerUncalibrated", 3) { }
readonly static ReferenceCue _refCue = new ReferenceCue {
static readonly ReferenceCue _refCue = new ReferenceCue {
PhysicalDimension = new PhysicalDimension { Length = 1, Time = -2 },
};
/// <inheritdoc />
public override ReferenceCue ReferenceCue => _refCue;
}
public class AndroidGameRotationVectorHandler : AndroidSensorHandler<AndroidGameRotationVectorHandler> {
/// <summary>
/// An <see cref="InputHandler" /> that handles Android game rotation vector sensor input.
/// </summary>
public class AndroidGameRotationVectorHandler : AndroidSensorHandler {
/// <summary>
/// Creates an instance of the <see cref="AndroidGameRotationVectorHandler" /> class.
/// </summary>
public AndroidGameRotationVectorHandler() : base("GameRotationVector", 4) { }
readonly static ReferenceCue _refCue = new ReferenceCue {
static readonly ReferenceCue _refCue = new ReferenceCue {
PhysicalDimension = new PhysicalDimension(),
};
/// <inheritdoc />
public override ReferenceCue ReferenceCue => _refCue;
}
public class AndroidGravityHandler : AndroidSensorHandler<AndroidGravityHandler> {
/// <summary>
/// An <see cref="InputHandler" /> that handles Android gravity sensor input.
/// </summary>
public class AndroidGravityHandler : AndroidSensorHandler {
/// <summary>
/// Creates an instance of the <see cref="AndroidGravityHandler" /> class.
/// </summary>
public AndroidGravityHandler() : base("Gravity", 3) { }
readonly static ReferenceCue _refCue = new ReferenceCue {
static readonly ReferenceCue _refCue = new ReferenceCue {
PhysicalDimension = new PhysicalDimension { Length = 1, Time = -2 },
};
/// <inheritdoc />
public override ReferenceCue ReferenceCue => _refCue;
}
public class AndroidGyroscopeHandler : AndroidSensorHandler<AndroidGyroscopeHandler> {
/// <summary>
/// An <see cref="InputHandler" /> that handles Android gyroscope sensor input.
/// </summary>
public class AndroidGyroscopeHandler : AndroidSensorHandler {
/// <summary>
/// Creates an instance of the <see cref="AndroidGyroscopeHandler" /> class.
/// </summary>
public AndroidGyroscopeHandler() : base("Gyroscope", 3) { }
readonly static ReferenceCue _refCue = new ReferenceCue {
static readonly ReferenceCue _refCue = new ReferenceCue {
PhysicalDimension = new PhysicalDimension { Time = -1 },
};
/// <inheritdoc />
public override ReferenceCue ReferenceCue => _refCue;
}
public class AndroidLinearAccelerationHandler : AndroidSensorHandler<AndroidLinearAccelerationHandler> {
/// <summary>
/// An <see cref="InputHandler" /> that handles Android linear acceleration sensor input.
/// </summary>
public class AndroidLinearAccelerationHandler : AndroidSensorHandler {
/// <summary>
/// Creates an instance of the <see cref="AndroidLinearAccelerationHandler" /> class.
/// </summary>
public AndroidLinearAccelerationHandler() : base("LinearAcceleration", 3) { }
readonly static ReferenceCue _refCue = new ReferenceCue {
static readonly ReferenceCue _refCue = new ReferenceCue {
PhysicalDimension = new PhysicalDimension { Length = 1, Time = -2 },
};
/// <inheritdoc />
public override ReferenceCue ReferenceCue => _refCue;
}
public class AndroidMagneticFieldHandler : AndroidSensorHandler<AndroidMagneticFieldHandler> {
/// <summary>
/// An <see cref="InputHandler" /> that handles Android magnetic field sensor input.
/// </summary>
public class AndroidMagneticFieldHandler : AndroidSensorHandler {
/// <summary>
/// Creates an instance of the <see cref="AndroidMagneticFieldHandler" /> class.
/// </summary>
public AndroidMagneticFieldHandler() : base("MagneticField", 3) { }
readonly static ReferenceCue _refCue = new ReferenceCue {
static readonly ReferenceCue _refCue = new ReferenceCue {
PhysicalDimension = new PhysicalDimension { Mass = 1, Time = -2, ElectricCurrent = -1 },
};
/// <inheritdoc />
public override ReferenceCue ReferenceCue => _refCue;
}
public class AndroidMagneticFieldUncalibratedHandler : AndroidSensorHandler<AndroidMagneticFieldUncalibratedHandler> {
/// <summary>
/// An <see cref="InputHandler" /> that handles Android magnetic field (uncalibrated) sensor input.
/// </summary>
public class AndroidMagneticFieldUncalibratedHandler : AndroidSensorHandler {
/// <summary>
/// Creates an instance of the <see cref="AndroidMagneticFieldUncalibratedHandler" /> class.
/// </summary>
public AndroidMagneticFieldUncalibratedHandler() : base("MagneticFieldUncalibrated", 3) { }
readonly static ReferenceCue _refCue = new ReferenceCue {
static readonly ReferenceCue _refCue = new ReferenceCue {
PhysicalDimension = new PhysicalDimension { Mass = 1, Time = -2, ElectricCurrent = -1 },
};
/// <inheritdoc />
public override ReferenceCue ReferenceCue => _refCue;
}
public class AndroidRotationVectorHandler : AndroidSensorHandler<AndroidRotationVectorHandler> {
/// <summary>
/// An <see cref="InputHandler" /> that handles Android rotation vector sensor input.
/// </summary>
public class AndroidRotationVectorHandler : AndroidSensorHandler {
/// <summary>
/// Creates an instance of the <see cref="AndroidRotationVectorHandler" /> class.
/// </summary>
public AndroidRotationVectorHandler() : base("RotationVector", 4) { }
readonly static ReferenceCue _refCue = new ReferenceCue {
static readonly ReferenceCue _refCue = new ReferenceCue {
PhysicalDimension = new PhysicalDimension(),
};
/// <inheritdoc />
public override ReferenceCue ReferenceCue => _refCue;
}
}

View File

@@ -1,23 +1,32 @@
using Cryville.Common.Interop;
using Cryville.Common.Logging;
using System;
namespace Cryville.Input.Unity.Android {
public class AndroidTouchHandler : AndroidInputHandler<AndroidTouchHandler> {
/// <summary>
/// An <see cref="InputHandler" /> that handles Android touch input.
/// </summary>
public class AndroidTouchHandler : AndroidInputHandler {
/// <summary>
/// Creates an instance of the <see cref="AndroidTouchHandler" /> class.
/// </summary>
public AndroidTouchHandler() : base("world/cryville/input/unity/android/TouchProxy") { }
/// <inheritdoc />
public override bool IsNullable => true;
/// <inheritdoc />
public override byte Dimension => 2;
readonly static ReferenceCue _refCue = new ReferenceCue {
static readonly ReferenceCue _refCue = new ReferenceCue {
PhysicalDimension = new PhysicalDimension { Length = 1 },
RelativeUnit = RelativeUnit.Pixel,
Flags = ReferenceFlag.FlipY,
Pivot = new InputVector(0, 1),
};
/// <inheritdoc />
public override ReferenceCue ReferenceCue => _refCue;
/// <inheritdoc />
public override string GetTypeName(int type) {
switch (type) {
case 0: return "Android Touch";
@@ -25,19 +34,17 @@ namespace Cryville.Input.Unity.Android {
}
}
/// <inheritdoc />
public override double GetCurrentTimestamp() {
return JavaStaticMethods.SystemClock_uptimeMillis() / 1000.0;
}
private protected override AndroidInputProxy_Callback Callback { get { return OnFeed; } }
[MonoPInvokeCallback]
static void OnFeed(int id, int action, long time, float x, float y, float z, float w) {
internal override void OnFeed(int id, int action, long time, float x, float y, float z, float w) {
try {
double timeSecs = time / 1000.0;
Instance.Feed(0, id, new InputFrame(timeSecs, new InputVector(x, y)));
Feed(0, id, new InputFrame(timeSecs, new InputVector(x, y)));
if (action == 1 /*ACTION_UP*/ || action == 3 /*ACTION_CANCEL*/ || action == 6 /*ACTION_POINTER_UP*/)
Instance.Feed(0, id, new InputFrame(timeSecs));
Feed(0, id, new InputFrame(timeSecs));
}
catch (Exception ex) {
Logger.Log("main", 4, "Input", "An error occurred while handling an Android touch event: {0}", ex);

View File

@@ -1,9 +1,19 @@
using System.Runtime.InteropServices;
namespace Cryville.Input.Unity.Android {
internal delegate void AndroidInputProxy_Callback(int id, int action, long time, float x, float y, float z, float w);
struct ProxiedInputFrame {
public int hid;
public int id;
public int action;
public long time;
public float x;
public float y;
public float z;
public float w;
};
internal static class NativeMethods {
[DllImport("AndroidInputProxy")]
public static extern void AndroidInputProxy_RegisterCallback(int hid, AndroidInputProxy_Callback cb);
[PreserveSig]
public static extern int AndroidInputProxy_Poll(out ProxiedInputFrame frame);
}
}

View File

@@ -3,63 +3,97 @@ using System.Collections.Generic;
using UnityEngine;
namespace Cryville.Input.Unity {
/// <summary>
/// An <see cref="InputHandler" /> that handles Unity GUI input.
/// </summary>
/// <typeparam name="T">The GUI event receiver type.</typeparam>
public class UnityGuiInputHandler<T> : InputHandler where T : UnityGuiEventReceiver {
GameObject _receiver;
T _recvComp;
/// <summary>
/// Creates an instance of the <see cref="UnityGuiInputHandler{T}" /> class.
/// </summary>
public UnityGuiInputHandler() { }
/// <inheritdoc />
protected override void Activate() {
_receiver = new GameObject("__guiRecv__");
_recvComp = _receiver.AddComponent<T>();
_recvComp.SetCallback(Feed);
}
/// <inheritdoc />
protected override void Deactivate() {
if (_receiver) GameObject.Destroy(_receiver);
}
/// <inheritdoc />
public override void Dispose(bool disposing) {
if (disposing) {
Deactivate();
}
}
/// <inheritdoc />
public override bool IsNullable { get { return true; } }
/// <inheritdoc />
public override byte Dimension { get { return 0; } }
readonly static ReferenceCue _refCue = new ReferenceCue { };
static readonly ReferenceCue _refCue = new ReferenceCue { };
/// <inheritdoc />
public override ReferenceCue ReferenceCue => _refCue;
/// <inheritdoc />
public override string GetTypeName(int type) {
return _recvComp.GetKeyName(type);
}
/// <inheritdoc />
public override double GetCurrentTimestamp() {
return Time.realtimeSinceStartupAsDouble;
}
}
/// <summary>
/// Unity GUI event receiver.
/// </summary>
public abstract class UnityGuiEventReceiver : MonoBehaviour {
/// <summary>
/// The callback function to be called when a new input frame is received.
/// </summary>
protected Action<int, int, InputFrame> Callback;
protected readonly HashSet<int> Keys = new HashSet<int>();
/// <summary>
/// The set of currently active keys.
/// </summary>
protected readonly HashSet<int> ActiveKeys = new HashSet<int>();
/// <summary>
/// Sets the callback function to be called when a new input frame is received.
/// </summary>
/// <param name="h">The callback function to be called when a new input frame is received.</param>
public void SetCallback(Action<int, int, InputFrame> h) {
Callback = h;
}
public abstract string GetKeyName(int type);
/// <summary>
/// Gets the friendly name of the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <returns>The friendly name of the specified key.</returns>
public abstract string GetKeyName(int key);
void Awake() {
useGUILayout = false;
}
void Update() {
double time = Time.realtimeSinceStartupAsDouble;
foreach (var k in Keys) {
foreach (var k in ActiveKeys) {
Callback(k, 0, new InputFrame(time, new InputVector()));
}
}
}
public class UnityKeyReceiver : UnityGuiEventReceiver {
/// <inheritdoc />
public override string GetKeyName(int type) {
return Enum.GetName(typeof(KeyCode), type);
}
@@ -70,13 +104,13 @@ namespace Cryville.Input.Unity {
var key = (int)e.keyCode;
switch (e.type) {
case EventType.KeyDown:
if (!Keys.Contains(key)) {
if (!ActiveKeys.Contains(key)) {
Callback(key, 0, new InputFrame(time, new InputVector()));
Keys.Add(key);
ActiveKeys.Add(key);
}
break;
case EventType.KeyUp:
Keys.Remove(key);
ActiveKeys.Remove(key);
Callback(key, 0, new InputFrame(time));
break;
}
@@ -84,6 +118,7 @@ namespace Cryville.Input.Unity {
}
public class UnityMouseReceiver : UnityGuiEventReceiver {
/// <inheritdoc />
public override string GetKeyName(int type) {
switch (type) {
case 0: return "Mouse Left Button";
@@ -98,13 +133,13 @@ namespace Cryville.Input.Unity {
var key = e.button;
switch (e.type) {
case EventType.MouseDown:
if (!Keys.Contains(key)) {
if (!ActiveKeys.Contains(key)) {
Callback(key, 0, new InputFrame(time, new InputVector()));
Keys.Add(key);
ActiveKeys.Add(key);
}
break;
case EventType.MouseUp:
Keys.Remove(key);
ActiveKeys.Remove(key);
Callback(key, 0, new InputFrame(time));
break;
}

View File

@@ -3,40 +3,54 @@ using UnityEngine;
using unity = UnityEngine;
namespace Cryville.Input.Unity {
/// <summary>
/// An <see cref="InputHandler" /> that handles Unity mouse input.
/// </summary>
public class UnityMouseHandler : InputHandler {
GameObject _receiver;
/// <summary>
/// Creates an instance of the <see cref="UnityMouseHandler" /> class.
/// </summary>
/// <exception cref="NotSupportedException">Unity mouse is not supported on the current device.</exception>
public UnityMouseHandler() {
if (!unity::Input.mousePresent) {
throw new NotSupportedException("Unity mouse is not supported on this device");
}
}
/// <inheritdoc />
protected override void Activate() {
_receiver = new GameObject("__mouseRecv__");
_receiver.AddComponent<UnityMouseReceiver>().SetHandler(this);
}
/// <inheritdoc />
protected override void Deactivate() {
if (_receiver) GameObject.Destroy(_receiver);
}
/// <inheritdoc />
public override void Dispose(bool disposing) {
if (disposing) {
Deactivate();
}
}
/// <inheritdoc />
public override bool IsNullable { get { return false; } }
/// <inheritdoc />
public override byte Dimension { get { return 2; } }
readonly static ReferenceCue _refCue = new ReferenceCue {
static readonly ReferenceCue _refCue = new ReferenceCue {
PhysicalDimension = new PhysicalDimension { Length = 1 },
RelativeUnit = RelativeUnit.Pixel,
};
/// <inheritdoc />
public override ReferenceCue ReferenceCue => _refCue;
/// <inheritdoc />
public override string GetTypeName(int type) {
switch (type) {
case 0: return "Mouse Position";
@@ -44,12 +58,20 @@ namespace Cryville.Input.Unity {
}
}
/// <inheritdoc />
public override double GetCurrentTimestamp() {
return Time.realtimeSinceStartupAsDouble;
}
/// <summary>
/// Unity mouse receiver.
/// </summary>
public class UnityMouseReceiver : MonoBehaviour {
UnityMouseHandler _handler;
/// <summary>
/// Sets the <see cref="UnityMouseHandler" />.
/// </summary>
/// <param name="h">The <see cref="UnityMouseHandler" />.</param>
public void SetHandler(UnityMouseHandler h) {
_handler = h;
}

View File

@@ -3,40 +3,54 @@ using UnityEngine;
using unity = UnityEngine;
namespace Cryville.Input.Unity {
/// <summary>
/// An <see cref="InputHandler" /> that handles Unity touch input.
/// </summary>
public class UnityTouchHandler : InputHandler {
GameObject _receiver;
/// <summary>
/// Creates an instance of the <see cref="UnityTouchHandler" /> class.
/// </summary>
/// <exception cref="NotSupportedException">Unity touch is not supported on the current device.</exception>
public UnityTouchHandler() {
if (!unity::Input.touchSupported) {
throw new NotSupportedException("Unity touch is not supported on this device");
}
}
/// <inheritdoc />
protected override void Activate() {
_receiver = new GameObject("__touchRecv__");
_receiver.AddComponent<UnityPointerReceiver>().SetHandler(this);
_receiver.AddComponent<UnityTouchReceiver>().SetHandler(this);
}
/// <inheritdoc />
protected override void Deactivate() {
if (_receiver) GameObject.Destroy(_receiver);
}
/// <inheritdoc />
public override void Dispose(bool disposing) {
if (disposing) {
Deactivate();
}
}
/// <inheritdoc />
public override bool IsNullable { get { return true; } }
/// <inheritdoc />
public override byte Dimension { get { return 2; } }
readonly static ReferenceCue _refCue = new ReferenceCue {
static readonly ReferenceCue _refCue = new ReferenceCue {
PhysicalDimension = new PhysicalDimension { Length = 1 },
RelativeUnit = RelativeUnit.Pixel,
};
/// <inheritdoc />
public override ReferenceCue ReferenceCue => _refCue;
/// <inheritdoc />
public override string GetTypeName(int type) {
switch (type) {
case 0: return "Touch";
@@ -44,12 +58,20 @@ namespace Cryville.Input.Unity {
}
}
/// <inheritdoc />
public override double GetCurrentTimestamp() {
return Time.realtimeSinceStartupAsDouble;
}
public class UnityPointerReceiver : MonoBehaviour {
/// <summary>
/// Unity touch receiver.
/// </summary>
public class UnityTouchReceiver : MonoBehaviour {
UnityTouchHandler _handler;
/// <summary>
/// Sets the <see cref="UnityTouchHandler" />.
/// </summary>
/// <param name="h">The <see cref="UnityTouchHandler" />.</param>
public void SetHandler(UnityTouchHandler h) {
_handler = h;
}

Binary file not shown.

View File

@@ -0,0 +1,513 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Cryville.Input</name>
</assembly>
<members>
<member name="T:Cryville.Input.InputEvent">
<summary>
Input event.
</summary>
</member>
<member name="P:Cryville.Input.InputEvent.Identifier">
<summary>
The input identifier.
</summary>
</member>
<member name="P:Cryville.Input.InputEvent.From">
<summary>
The input frame last received.
</summary>
</member>
<member name="P:Cryville.Input.InputEvent.To">
<summary>
The new input frame received.
</summary>
</member>
<member name="M:Cryville.Input.InputEvent.ToString">
<inheritdoc />
</member>
<member name="T:Cryville.Input.InputFrameHandler">
<summary>
Represents the method that will handle the <see cref="E:Cryville.Input.InputHandler.OnInput" /> event.
</summary>
<param name="identifier">The input identifier of <paramref name="frame" />.</param>
<param name="frame">The new input frame.</param>
</member>
<member name="T:Cryville.Input.InputHandler">
<summary>
Input handler.
</summary>
</member>
<member name="E:Cryville.Input.InputHandler.OnInput">
<summary>
Occurs when a new input frame is sent.
</summary>
</member>
<member name="M:Cryville.Input.InputHandler.Finalize">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputHandler.Dispose">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputHandler.Activate">
<summary>
Activates the input handler and starts receiving new input frames.
</summary>
</member>
<member name="M:Cryville.Input.InputHandler.Deactivate">
<summary>
Deactivates the input handler and stops receiving new input frames.
</summary>
</member>
<member name="M:Cryville.Input.InputHandler.Dispose(System.Boolean)">
<summary>
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
</summary>
<param name="disposing">Whether disposing or finalizing.</param>
</member>
<member name="P:Cryville.Input.InputHandler.IsNullable">
<summary>
Whether null input frames may be sent by the input handler.
</summary>
<remarks>
<para>See <see cref="P:Cryville.Input.InputFrame.IsNull" /> for more information.</para>
</remarks>
</member>
<member name="P:Cryville.Input.InputHandler.Dimension">
<summary>
The dimension of the vectors sent by the input handler.
</summary>
<remarks>
<para>Dimension must be an integer from 0 (inclusive) to 4 (inclusive.) The components of the <see cref="T:Cryville.Input.InputVector" /> whose indices are beyond the dimension should be set to 0.</para>
</remarks>
</member>
<member name="P:Cryville.Input.InputHandler.ReferenceCue">
<summary>
The reference cue for the vectors sent by the input handler.
</summary>
</member>
<member name="M:Cryville.Input.InputHandler.GetTypeName(System.Int32)">
<summary>
Gets the friendly name of the specified type.
</summary>
<param name="type">The type.</param>
<returns>The friendly name of the specified type.</returns>
<remarks>
<para>See <see cref="P:Cryville.Input.InputSource.Type"/> for more information.</para>
</remarks>
</member>
<member name="M:Cryville.Input.InputHandler.GetCurrentTimestamp">
<summary>
Gets the current timestamp of the input handler.
</summary>
<returns>The current timestamp of the input handler in seconds.</returns>
<remarks>
<para>The timestamp returned by this method is obtained from the same source as the <see cref="P:Cryville.Input.InputFrame.Time" /> of the frame the handler sends whenever possible. However, there is no guarantee that, when calling this method, all the frames whose <see cref="P:Cryville.Input.InputFrame.Time" /> is less than the timestamp returned by this method have been sent.</para>
</remarks>
</member>
<member name="M:Cryville.Input.InputHandler.Feed(System.Int32,System.Int32,Cryville.Input.InputFrame)">
<summary>
Sends a new input frame.
</summary>
<param name="type">The type of the input frame.</param>
<param name="id">The ID of the input frame.</param>
<param name="frame">The input frame.</param>
</member>
<member name="T:Cryville.Input.InputIdentifier">
<summary>
Input identifier.
</summary>
</member>
<member name="P:Cryville.Input.InputIdentifier.Source">
<summary>
The input source.
</summary>
</member>
<member name="P:Cryville.Input.InputIdentifier.Id">
<summary>
The input ID.
</summary>
<remarks>
<para>This property is used to distinguish different inputs on the input source. For example, a touch screen that supports simultaneous touches may assign a unique ID to each finger.</para>
</remarks>
</member>
<member name="M:Cryville.Input.InputIdentifier.Equals(System.Object)">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputIdentifier.Equals(Cryville.Input.InputIdentifier)">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputIdentifier.GetHashCode">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputIdentifier.ToString">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputIdentifier.op_Equality(Cryville.Input.InputIdentifier,Cryville.Input.InputIdentifier)">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputIdentifier.op_Inequality(Cryville.Input.InputIdentifier,Cryville.Input.InputIdentifier)">
<inheritdoc />
</member>
<member name="T:Cryville.Input.InputManager">
<summary>
Input manager.
</summary>
</member>
<member name="F:Cryville.Input.InputManager.HandlerRegistries">
<summary>
A set of handler types to be initialized.
</summary>
</member>
<member name="M:Cryville.Input.InputManager.#ctor">
<summary>
Creates an instance of the <see cref="T:Cryville.Input.InputManager" /> class and tries to initialize all the handlers in <see cref="F:Cryville.Input.InputManager.HandlerRegistries" />.
</summary>
</member>
<member name="M:Cryville.Input.InputManager.GetHandlerByTypeName(System.String)">
<summary>
Gets the handler with the specified type name.
</summary>
<param name="typeName">The type name.</param>
<returns>The handler with the specified type name. <see langword="null" /> if not found or not initialized.</returns>
</member>
<member name="M:Cryville.Input.InputManager.EnumerateHandlers(System.Action{Cryville.Input.InputHandler})">
<summary>
Enumerates all initialized handlers and passes each of them into a callback function.
</summary>
<param name="cb">The callback function.</param>
</member>
<member name="T:Cryville.Input.InputSource">
<summary>
Input source.
</summary>
</member>
<member name="P:Cryville.Input.InputSource.Handler">
<summary>
The input handler.
</summary>
</member>
<member name="P:Cryville.Input.InputSource.Type">
<summary>
The type of the input source as an identifier of a component of the input handler.
</summary>
<remarks>
<para>This property is used to distinguish different components of the input handler. For example, each key on the keyboard is assigned a unique type number. Use <see cref="M:Cryville.Input.InputHandler.GetTypeName(System.Int32)" /> to get a friendly name of a specific type.</para>
</remarks>
</member>
<member name="M:Cryville.Input.InputSource.Equals(System.Object)">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputSource.Equals(Cryville.Input.InputSource)">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputSource.GetHashCode">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputSource.ToString">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputSource.op_Equality(Cryville.Input.InputSource,Cryville.Input.InputSource)">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputSource.op_Inequality(Cryville.Input.InputSource,Cryville.Input.InputSource)">
<inheritdoc />
</member>
<member name="T:Cryville.Input.InputFrame">
<summary>
Input frame.
</summary>
</member>
<member name="P:Cryville.Input.InputFrame.Time">
<summary>
The timestamp in seconds.
</summary>
</member>
<member name="P:Cryville.Input.InputFrame.IsNull">
<summary>
Whether the vector is null.
</summary>
<remarks>
<para>An input frame with this property set to <see langword="true" /> marks the end of life of an input ID (see <see cref="P:Cryville.Input.InputIdentifier.Id" />.) This usually occurs when, for example, the button of the device is released.</para>
<para>When this property is set to <see langword="true" />, all the components of <see cref="P:Cryville.Input.InputFrame.Vector" /> is meaningless and should be set to 0.</para>
</remarks>
</member>
<member name="P:Cryville.Input.InputFrame.Vector">
<summary>
The input vector.
</summary>
</member>
<member name="M:Cryville.Input.InputFrame.#ctor(System.Double)">
<summary>
Creates an instance of the <see cref="T:Cryville.Input.InputFrame" /> struct with <see cref="P:Cryville.Input.InputFrame.IsNull" /> set to <see langword="true" />.
</summary>
<param name="time">The timestamp in seconds.</param>
</member>
<member name="M:Cryville.Input.InputFrame.#ctor(System.Double,Cryville.Input.InputVector)">
<summary>
Creates an instance of the <see cref="T:Cryville.Input.InputFrame" /> struct.
</summary>
<param name="time">The timestamp in seconds.</param>
<param name="vector">The input vector.</param>
</member>
<member name="M:Cryville.Input.InputFrame.ToString">
<inheritdoc />
</member>
<member name="T:Cryville.Input.InputVector">
<summary>
Input vector.
</summary>
</member>
<member name="P:Cryville.Input.InputVector.X">
<summary>
The first component of the vector.
</summary>
</member>
<member name="P:Cryville.Input.InputVector.Y">
<summary>
The second component of the vector.
</summary>
</member>
<member name="P:Cryville.Input.InputVector.Z">
<summary>
The third component of the vector.
</summary>
</member>
<member name="P:Cryville.Input.InputVector.W">
<summary>
The fourth component of the vector.
</summary>
</member>
<member name="M:Cryville.Input.InputVector.#ctor(System.Single)">
<summary>
Creates an instance of the <see cref="T:Cryville.Input.InputVector" /> struct of one dimension.
</summary>
<param name="x">The first component of the vector.</param>
</member>
<member name="M:Cryville.Input.InputVector.#ctor(System.Single,System.Single)">
<summary>
Creates an instance of the <see cref="T:Cryville.Input.InputVector" /> struct of two dimensions.
</summary>
<param name="x">The first component of the vector.</param>
<param name="y">The second component of the vector.</param>
</member>
<member name="M:Cryville.Input.InputVector.#ctor(System.Single,System.Single,System.Single)">
<summary>
Creates an instance of the <see cref="T:Cryville.Input.InputVector" /> struct of three dimensions.
</summary>
<param name="x">The first component of the vector.</param>
<param name="y">The second component of the vector.</param>
<param name="z">The third component of the vector.</param>
</member>
<member name="M:Cryville.Input.InputVector.#ctor(System.Single,System.Single,System.Single,System.Single)">
<summary>
Creates an instance of the <see cref="T:Cryville.Input.InputVector" /> struct of four dimensions.
</summary>
<param name="x">The first component of the vector.</param>
<param name="y">The second component of the vector.</param>
<param name="z">The third component of the vector.</param>
<param name="w">The fourth component of the vector.</param>
</member>
<member name="M:Cryville.Input.InputVector.op_Addition(Cryville.Input.InputVector,Cryville.Input.InputVector)">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputVector.op_Subtraction(Cryville.Input.InputVector,Cryville.Input.InputVector)">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputVector.op_Multiply(System.Single,Cryville.Input.InputVector)">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputVector.op_UnaryNegation(Cryville.Input.InputVector)">
<inheritdoc />
</member>
<member name="M:Cryville.Input.InputVector.ToString">
<inheritdoc />
</member>
<member name="T:Cryville.Input.ReferenceCue">
<summary>
Provides cues about the frame of reference.
</summary>
</member>
<member name="P:Cryville.Input.ReferenceCue.PhysicalDimension">
<summary>
The physical dimension.
</summary>
</member>
<member name="P:Cryville.Input.ReferenceCue.RelativeUnit">
<summary>
The additional relative unit.
</summary>
</member>
<member name="P:Cryville.Input.ReferenceCue.Flags">
<summary>
The reference flags.
</summary>
</member>
<member name="P:Cryville.Input.ReferenceCue.Origin">
<summary>
The origin.
</summary>
</member>
<member name="P:Cryville.Input.ReferenceCue.Pivot">
<summary>
The pivot.
</summary>
</member>
<member name="M:Cryville.Input.ReferenceCue.Transform(Cryville.Input.InputFrame)">
<summary>
Transforms a frame into the reference by applying the offset specified by <see cref="P:Cryville.Input.ReferenceCue.Origin" />.
</summary>
<param name="frame">The input frame.</param>
<returns>The transformed input frame.</returns>
</member>
<member name="M:Cryville.Input.ReferenceCue.InverseTransform(Cryville.Input.InputFrame)">
<summary>
Transforms a frame out of the reference by removing the offset specified by <see cref="P:Cryville.Input.ReferenceCue.Origin" />.
</summary>
<param name="frame">The input frame.</param>
<returns>The transformed input frame.</returns>
</member>
<member name="M:Cryville.Input.ReferenceCue.Transform(Cryville.Input.InputFrame,Cryville.Input.InputVector)">
<summary>
Transforms a frame into the reference by applying the offset specified by <see cref="P:Cryville.Input.ReferenceCue.Origin" /> and <see cref="P:Cryville.Input.ReferenceCue.Pivot" />.
</summary>
<param name="frame">The input frame.</param>
<param name="universe">The universe size.</param>
<returns>The transformed input frame.</returns>
</member>
<member name="M:Cryville.Input.ReferenceCue.InverseTransform(Cryville.Input.InputFrame,Cryville.Input.InputVector)">
<summary>
Transforms a frame out of the reference by removing the offset specified by <see cref="P:Cryville.Input.ReferenceCue.Origin" /> and <see cref="P:Cryville.Input.ReferenceCue.Pivot" />.
</summary>
<param name="frame">The input frame.</param>
<param name="universe">The universe size.</param>
<returns>The transformed input frame.</returns>
</member>
<member name="T:Cryville.Input.PhysicalDimension">
<summary>
Physical dimension.
</summary>
</member>
<member name="P:Cryville.Input.PhysicalDimension.Time">
<summary>
The dimensions of time.
</summary>
</member>
<member name="P:Cryville.Input.PhysicalDimension.Length">
<summary>
The dimensions of length.
</summary>
</member>
<member name="P:Cryville.Input.PhysicalDimension.Mass">
<summary>
The dimensions of mass.
</summary>
</member>
<member name="P:Cryville.Input.PhysicalDimension.ElectricCurrent">
<summary>
The dimensions of electric current.
</summary>
</member>
<member name="P:Cryville.Input.PhysicalDimension.ThermodynamicTemperature">
<summary>
The dimensions of thermodynamic temperature.
</summary>
</member>
<member name="P:Cryville.Input.PhysicalDimension.AmountOfSubstance">
<summary>
The dimensions of amount of substance.
</summary>
</member>
<member name="P:Cryville.Input.PhysicalDimension.LuminousIntensity">
<summary>
The dimensions of luminous intensity.
</summary>
</member>
<member name="T:Cryville.Input.RelativeUnit">
<summary>
Relative unit.
</summary>
</member>
<member name="F:Cryville.Input.RelativeUnit.None">
<summary>
None.
</summary>
</member>
<member name="F:Cryville.Input.RelativeUnit.Pixel">
<summary>
Pixel.
</summary>
</member>
<member name="T:Cryville.Input.ReferenceFlag">
<summary>
Reference flag.
</summary>
</member>
<member name="F:Cryville.Input.ReferenceFlag.None">
<summary>
None.
</summary>
</member>
<member name="F:Cryville.Input.ReferenceFlag.FlipX">
<summary>
The X axis is flipped.
</summary>
</member>
<member name="F:Cryville.Input.ReferenceFlag.FlipY">
<summary>
The Y axis is flipped.
</summary>
</member>
<member name="F:Cryville.Input.ReferenceFlag.FlipZ">
<summary>
The Z axis is flipped.
</summary>
</member>
<member name="F:Cryville.Input.ReferenceFlag.FlipW">
<summary>
The W axis is flipped.
</summary>
</member>
<member name="T:Cryville.Input.SimpleInputConsumer">
<summary>
A simple input consumer that receives input frames.
</summary>
</member>
<member name="M:Cryville.Input.SimpleInputConsumer.#ctor(Cryville.Input.InputManager)">
<summary>
Creates an instance of the <see cref="T:Cryville.Input.SimpleInputConsumer" /> class.
</summary>
<param name="manager">The input manager.</param>
</member>
<member name="M:Cryville.Input.SimpleInputConsumer.Activate">
<summary>
Activates all the input handlers.
</summary>
</member>
<member name="M:Cryville.Input.SimpleInputConsumer.Deactivate">
<summary>
Deactivates all the input handlers.
</summary>
</member>
<member name="M:Cryville.Input.SimpleInputConsumer.OnInput(Cryville.Input.InputIdentifier,Cryville.Input.InputFrame)">
<summary>
Called when a new input frame is received.
</summary>
<param name="identifier">The input identifier.</param>
<param name="frame">The new input frame.</param>
</member>
<member name="M:Cryville.Input.SimpleInputConsumer.EnumerateEvents(System.Action{Cryville.Input.InputEvent})">
<summary>
Enumerates all the input events in the queue, passes each of them into the given callback function, and then flushes the queue.
</summary>
<param name="cb">The callback function.</param>
</member>
<member name="M:Cryville.Input.SimpleInputConsumer.EnumerateActiveIdentifiers(System.Action{Cryville.Input.InputIdentifier,Cryville.Input.InputFrame})">
<summary>
Enumerates all the active identifiers and passes each of them into the given callback function with its current frame.
</summary>
<param name="cb">The callback function.</param>
</member>
</members>
</doc>

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 26d2baa850dc4bb4db5489359d92b61b
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -244,7 +244,7 @@ PlayerSettings:
clonedFromGUID: 00000000000000000000000000000000
templatePackageId:
templateDefaultScene:
useCustomMainManifest: 0
useCustomMainManifest: 1
useCustomLauncherManifest: 0
useCustomMainGradleTemplate: 0
useCustomLauncherGradleManifest: 0