using Google.Protobuf; using WebmrAPI.Utils.Sequences; using WinIPC.Models; using WinIPC.Utils; namespace WebmrAPI.Utils { public class Key { public Button Code { get; private set; } public Key(Button code) { Code = code; } public Key(string key) { Button code; switch (key.ToLowerInvariant()) { case "-": case "_": Code = Button.Sub; break; case "+": case "=": Code = Button.Add; break; case "~": case "`": Code = Button.Tilde; break; case "<": case ",": Code = Button.Comma; break; case ">": case ".": Code = Button.Period; break; case ":": case ";": Code = Button.Colon; break; case "{": case "[": Code = Button.LBracket; break; case "}": case "]": Code = Button.RBracket; break; case "\\": case "|": Code = Button.BSol; break; case "/": case "?": Code = Button.Sol; break; case "'": case "\"": Code = Button.Quote; break; case "num+": Code = Button.NumAdd; break; case "num-": Code = Button.NumSub; break; case "num*": Code = Button.NumMul; break; case "num/": Code = Button.NumDiv; break; case "num.": Code = Button.NumDec; break; case "a": case "b": case "c": case "d": case "e": case "f": case "g": case "h": case "i": case "j": case "k": case "l": case "m": case "n": case "o": case "p": case "q": case "r": case "s": case "t": case "u": case "v": case "w": case "x": case "y": case "z": case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": if (Enum.TryParse($"Key{key}", out code)) { Code = code; break; } else goto default; case "shift": case "ctrl": case "alt": case "win": if (Enum.TryParse($"L{key}", out code)) { Code = code; break; } else goto default; default: if (Enum.TryParse(key, out code)) { Code = code; break; } else throw new ArgumentException($"Unexpected key \"{key}\""); } } } public class KeyShortcutSequence { private Queue> _queue = new(); public KeyShortcutSequence(KeyShortcut key) { Next(key); } public KeyShortcutSequence Next(KeyShortcut shortcut, int delay = 0) { _queue.Enqueue(new KeyValuePair(shortcut, (uint)delay)); return this; } public IEnumerable GetInputActions() { var actions = new InputAction[0]; do { var kvpair = _queue.Dequeue(); if (actions.Length > 0) { actions[actions.Length - 1].DelayMs += kvpair.Value; } actions = actions.Concat(kvpair.Key.GetInputActions()).ToArray(); } while (_queue.Count > 0); return actions; } } public class KeyShortcut { private readonly static DelayGenerator _dGen = new(new PerlinNumberGenerator(75, 200, Int32.MaxValue)); private Queue _queue = new(); public KeyShortcut(Key key) { And(key); } public KeyShortcut(string key) { And(key); } public KeyShortcut And(Key key) { _queue.Enqueue(key); return this; } public KeyShortcut And(string key) { return And(new Key(key)); } public IEnumerable GetHoldDownActions() { Key key; var actions = new InputAction[_queue.Count]; for (int i = 0, n = _queue.Count; i < n;) { _queue.Enqueue(key = _queue.Dequeue()); actions[i++] = new InputAction() { DelayMs = (uint)_dGen.Next().Value, Type = InputType.KeyDown, Payload = ByteString.CopyFrom(PayloadHandler.Serialize(new ButtonInput { Button = key.Code })) }; } return actions; } public IEnumerable GetHoldUpActions() { Key key; var actions = new InputAction[_queue.Count]; for (int n = _queue.Count; n > 0;) { _queue.Enqueue(key = _queue.Dequeue()); actions[--n] = new InputAction() { DelayMs = (uint)_dGen.Next().Value, Type = InputType.KeyUp, Payload = ByteString.CopyFrom(PayloadHandler.Serialize(new ButtonInput { Button = key.Code })) }; } return actions; } public IEnumerable GetInputActions() { Key key; int n = _queue.Count * 2; var actions = new InputAction[n]; for (int i = 0; i < n;) { _queue.Enqueue(key = _queue.Dequeue()); actions[i++] = new InputAction() { DelayMs = (uint)_dGen.Next().Value, Type = InputType.KeyDown, Payload = ByteString.CopyFrom(PayloadHandler.Serialize(new ButtonInput { Button = key.Code })) }; actions[--n] = new InputAction() { DelayMs = (uint)_dGen.Next().Value, Type = InputType.KeyUp, Payload = ByteString.CopyFrom(PayloadHandler.Serialize(new ButtonInput { Button = key.Code })) }; } return actions; } } }