Files
crtr/Assets/Cryville/Common/Unity/Input/AndroidTouchHandler.cs
2023-04-22 21:17:00 +08:00

93 lines
2.8 KiB
C#

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
}
}
}