/// <summary> /// Clear all the registered callbacks. You cannot clear callbacks while still in <see cref="Start(StartOption)"> state. /// You have to <see cref="Stop"> first. /// </summary> public static void ClearCallbacks() { if (started) { throw new InvalidOperationException("Clearing or changing callback targets while Native Touch is running is not allowed. Please call NativeTouch.Stop() first."); } NativeTouchInterface.ClearCallbacks(); }
/// <summary> /// Use this to ask the time on the same timeline as the timestamp that comes together with your touch, which is not the same between devices. /// /// Unity's input system does not provide you with the touch timestamp. The best you can do is to use the time at beginning of the frame which is /// still not the real performance of your players. /// /// With this and an anchor <see cref="Time.realtimeSinceStartup"> remembered you should be able to convert those timestamp to meaningful time for your game. /// /// [iOS] Based on `ProcessInfo.systemUptime` in iOS's API. The unit is **SECONDS**. [See documentation](https://developer.apple.com/documentation/foundation/nsprocessinfo/1414553-systemuptime) /// /// The API returns `double` and it is retured as-is. /// /// [Android] Based on `SystemClock.uptimeMillis();` in Android's API. The unit is **MILLISECONDS**. /// /// The API actually returns `long`, but converted to `double` to be in line with iOS. /// </summary> /// <returns></returns> public static double GetNativeTouchTime() { #if UNITY_IOS double doubleTime = NativeTouchInterface._GetNativeTouchTime(); return(doubleTime); #elif UNITY_ANDROID return (double) NativeTouchInterface.androidClassBridge.CallStatic <long>(NativeTouchInterface.AndroidTouchTimeMethodName); #else return -1; #endif }
/// <summary> /// Advanced function. From what I observed, /// The static callback will be slow only on the first time unfortunately. Maybe because of how C# event invoking works. /// And also maybe caused by JIT compilation on platform like Android Mono is JITing codes for the first time. /// /// Moreover there's no way to "pre-warm" this because the callback has to be triggered by player. If player did not /// touch the screen after <see cref="Start(StartOption)"> until the crucial moment the lag might be detrimental to the game. /// (e.g. In music games if you start Native Touch every time the game start, it would be difficult to perfect the first note.) /// /// It might irritates your player that the first touch is always slow, so calling this will force invoke on every registered /// static callbacks with a fake touch struct once. (all default values) Also can be used to warm-up your other things /// that you have put in the static callback as well. /// /// Check and ignore this fake touch in your callback with if on <see cref="NativeTouchData.WarmUpTouch"> property. /// Real touch created from native side always has this property as `false`. /// </summary> public static void WarmUp() { if (IsFullMode) { NativeTouchInterface.NativeTouchFullCallback(new NativeTouchDataFull()); } else { NativeTouchInterface.NativeTouchMinimalCallback(new NativeTouchData()); } }
/// <summary> /// Stop calling the static callback on touch. /// /// [Android] It removes the touch listener from the view. /// /// [iOS] The touch recognizer is not actually removed, since there is a strange bug that replays all the touches on remove. /// Instead I just temporartly disable it and returned to only normal Unity path. /// /// [Editor] This method is a stub that does nothing. /// </summary> /// <exception cref="InvalidOperationException">Thrown when you stop while not in <see cref="Started"> state.</exception> public static void Stop() { if (Application.isEditor) { return; } if (!started) { throw new InvalidOperationException("You can only Stop Native Touch while it is in Started state."); } UnsupportedCheck(); #if UNITY_IOS NativeTouchInterface._StopNativeTouch(); #elif UNITY_ANDROID NativeTouchInterface.androidClassBridge.CallStatic(NativeTouchInterface.AndroidStop); #endif Deallocate(); started = false; }
RealScreenResolution() { return(new #if UNITY_2017_2_OR_NEWER Vector2Int( #else Vector2( #endif #if !UNITY_EDITOR #if UNITY_IOS NativeTouchInterface._RealScreenWidth(), NativeTouchInterface._RealScreenHeight() #elif UNITY_ANDROID NativeTouchInterface.androidClassBridge.CallStatic <int>(NativeTouchInterface.AndroidRealWidth), NativeTouchInterface.androidClassBridge.CallStatic <int>(NativeTouchInterface.AndroidRealHeight) #else 0, 0 #endif #else //if in editor 0, 0 #endif )); }
/// <summary> /// After starting it will call the static callback method you have registered with timing explained in the [Callback Details](http://exceed7.com/native-touch/callback-details) page. It won't allow you to start without registering any callbacks, unless you have <see cref="StartOption.noCallback"> in the <paramref name="startOption">. /// /// [Editor] This method is a stub that does nothing. /// </summary> /// <param name="startOption">See the <see cref="StartOption"> class's member for definition of each options.</param> /// <exception cref="InvalidOperationException">Thrown when you start while already in <see cref="Started"> state, start without any callback while not in <see cref="StartOption.noCallback"> mode, or start in an unsupported platform.</exception> public static void Start(StartOption startOption = default(StartOption)) { if (Application.isEditor) { return; } if (started) { throw new InvalidOperationException("You cannot start again (with or without different start option) while you are still in Started state. Call NativeTouch.Stop() first then you can start again with new options if you want."); } UnsupportedCheck(); if (startOption == null) { startOption = new StartOption(); } if (startOption.noCallback == false && NativeTouchInterface.AreSomeCallbacksNull(startOption.fullMode)) { throw new InvalidOperationException(string.Format("Native Touch Start() aborted because you start while not registered any callback of the mode : {0}. Native Touch does not use null-check on event invoke for performance reason, and when the native side call you will get a null reference exception if Native Touch allows you to start like this. If you are intended to use ring buffer iteration based API, use `noCallback` in your `StartOption` to bypass this check.", startOption.fullMode ? "Full" : "Minimal") ); } AllocateIfNotYet(startOption); #if UNITY_IOS //On iOS everything goes to statically linked C NativeTouchInterface._StartNativeTouch( fullMode: startOption.fullMode ? 1 : 0, disableUnityTouch: startOption.disableUnityTouch ? 1 : 0, noCallback: startOption.noCallback ? 1 : 0, fullDelegate: NativeTouchInterface.NativeTouchFullCallbackRingBuffer, minimalDelegate: NativeTouchInterface.NativeTouchMinimalCallbackRingBuffer, fullRingBuffer: ntdFullRingBufferHandle.AddrOfPinnedObject(), minimalRingBuffer: ntdRingBufferHandle.AddrOfPinnedObject(), finalCursorHandle: finalCursorHandle.AddrOfPinnedObject(), dekkerHandle: dekkerHandle.AddrOfPinnedObject(), ringBufferSize: startOption.ringBufferSize ); #elif UNITY_ANDROID //This goes to Java NativeTouchInterface.androidClassBridge.CallStatic(NativeTouchInterface.AndroidStart, new object[] { startOption.fullMode, startOption.disableUnityTouch, startOption.noCallback }); //This goes to C directly, but dynamically linked. //(If UT allow statically linked lib on Android callback performance could be much better since IL2CPP could touch it.) NativeTouchInterface.registerCallbacksCheckRingBuffer( fullDelegate: NativeTouchInterface.NativeTouchFullCallbackRingBuffer, minimalDelegate: NativeTouchInterface.NativeTouchMinimalCallbackRingBuffer, fullRingBuffer: ntdFullRingBufferHandle.AddrOfPinnedObject(), minimalRingBuffer: ntdRingBufferHandle.AddrOfPinnedObject(), finalCursorHandle: finalCursorHandle.AddrOfPinnedObject(), dekkerHandle: dekkerHandle.AddrOfPinnedObject(), ringBufferSize: startOption.ringBufferSize ); #endif started = true; isFullMode = startOption.fullMode; }