Add Android touch handler.

This commit is contained in:
2023-04-22 21:17:00 +08:00
parent 72a93721f9
commit 6d276c99ac
3 changed files with 104 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
using System;
using UnityEngine;
namespace Cryville.Common.Unity.Input {
public class AndroidTouchHandler : InputHandler {
readonly AndroidTouchListener _listener;
readonly AndroidJavaClass _systemClock;
public AndroidTouchHandler() {
if (Environment.OSVersion.Platform != PlatformID.Unix)
throw new NotSupportedException("Android touch is not supported on this device");
_systemClock = new AndroidJavaClass("android.os.SystemClock");
new AndroidJavaClass("com.unity3d.player.UnityPlayer")
.GetStatic<AndroidJavaObject>("currentActivity")
.Get<AndroidJavaObject>("mUnityPlayer")
.Call("setOnTouchListener", _listener = new AndroidTouchListener(this));
}
protected override void Activate() {
_listener.Activated = true;
}
protected override void Deactivate() {
_listener.Activated = false;
}
public override void Dispose(bool disposing) {
if (disposing) {
Deactivate();
}
}
public override bool IsNullable(int type) {
if (type != 0) throw new ArgumentOutOfRangeException("type");
return true;
}
public override byte GetDimension(int type) {
if (type != 0) throw new ArgumentOutOfRangeException("type");
return 2;
}
public override string GetTypeName(int type) {
switch (type) {
case 0: return "Android Touch";
default: throw new ArgumentOutOfRangeException("type");
}
}
public override double GetCurrentTimestamp() {
return _systemClock.CallStatic<long>("uptimeMillis") / 1000.0;
}
class AndroidTouchListener : AndroidJavaProxy {
public bool Activated { get; set; }
readonly AndroidTouchHandler _handler;
public AndroidTouchListener(AndroidTouchHandler handler) : base("android.view.View$OnTouchListener") {
_handler = handler;
}
#pragma warning disable IDE1006
#pragma warning disable IDE0060
public bool onTouch(AndroidJavaObject v, AndroidJavaObject e) {
if (!Activated) return false;
try {
int pointerCount = e.Call<int>("getPointerCount");
for (int i = 0; i < pointerCount; i++) {
int id = e.Call<int>("getPointerId", i);
double time = e.Call<long>("getEventTime") / 1000.0;
int action = e.Call<int>("getActionMasked");
Vector2 pos = UnityCameraUtils.ScreenToWorldPoint(new Vector2(
e.Call<float>("getX", i),
e.Call<float>("getY", i)
));
_handler.Feed(0, id, new InputVector(time, pos));
if (action == 1 /*ACTION_UP*/ || action == 3 /*ACTION_CANCEL*/ || (action == 6 /*ACTION_POINTER_UP*/ && e.Call<int>("getActionIndex") == i)) {
_handler.Feed(0, id, new InputVector(time));
}
}
}
catch (Exception ex) {
Logger.Log("main", 4, "Input", "An error occured while handling an Android touch event: {0}", ex);
}
return false;
}
#pragma warning restore IDE0060
#pragma warning restore IDE1006
}
}
}

View File

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

View File

@@ -6,6 +6,7 @@ namespace Cryville.Common.Unity.Input {
public class InputManager {
static readonly HashSet<Type> HandlerRegistries = new HashSet<Type> {
typeof(WindowsPointerHandler),
typeof(AndroidTouchHandler),
typeof(UnityKeyHandler<UnityKeyboardReceiver>),
typeof(UnityKeyHandler<UnityMouseButtonReceiver>),
typeof(UnityMouseHandler),