using System; using System.Threading; using System.Threading.Tasks; using UnityEngine; using UnityEngine.Events; namespace SkyHook { public class SkyHookManager : MonoBehaviour { private static SkyHookManager _instance; private static bool _isFocused; /// /// Whether or not the event will be received only if the game window is focused. /// // ReSharper disable once MemberCanBePrivate.Global // ReSharper disable once FieldCanBeMadeReadOnly.Global public static bool RequireFocus = true; public bool isHookActive; /// /// The key updated event data /// // ReSharper disable once MemberCanBePrivate.Global public static readonly UnityEvent KeyUpdated = new(); /// /// The instance of sky hook manager. The instance will be crated if it does not exist /// // ReSharper disable once MemberCanBePrivate.Global public static SkyHookManager Instance { get { if (_instance) return _instance; var obj = new GameObject("SkyHook Manager"); _instance = obj.AddComponent(); DontDestroyOnLoad(_instance); return _instance; } } private void HookCallback(SkyHookEvent ev) { if (RequireFocus && !_isFocused) { return; } KeyUpdated.Invoke(ev); } private void _StartHook() { var started = false; Exception exception = null; new Thread(() => { if (isHookActive) return; var result = SkyHookNative.StartHook(HookCallback); if (result != null) { exception = new SkyHookException(result); } isHookActive = true; started = true; while (isHookActive) { } }).Start(); while (!started && exception == null) { } if (exception != null) { throw exception; } } private void _StopHook() { if (!isHookActive) return; var result = SkyHookNative.StopHook(); if (result != null) { throw new SkyHookException(result); } isHookActive = false; } public static void StartHook() { Instance._StartHook(); } public static void StopHook() { Instance._StopHook(); } private void OnDestroy() { _StopHook(); } private void Update() { if (RequireFocus) { _isFocused = Application.isFocused; } } } }