diff --git a/BetterJoyForCemu/BetterJoyForCemu.csproj b/BetterJoyForCemu/BetterJoyForCemu.csproj index dd50a6a..c41e23a 100644 --- a/BetterJoyForCemu/BetterJoyForCemu.csproj +++ b/BetterJoyForCemu/BetterJoyForCemu.csproj @@ -190,7 +190,7 @@ - PreserveNewest + Always diff --git a/BetterJoyForCemu/Config.cs b/BetterJoyForCemu/Config.cs index 9ebe2e8..ecf962e 100644 --- a/BetterJoyForCemu/Config.cs +++ b/BetterJoyForCemu/Config.cs @@ -25,7 +25,7 @@ namespace BetterJoyForCemu { } public static void Init(List> caliData) { - foreach (string s in new string[] { "ProgressiveScan", "StartInTray", "capture", "home", "sl_l", "sl_r", "sr_l", "sr_r", "reset_mouse" }) + foreach (string s in new string[] { "ProgressiveScan", "StartInTray", "capture", "home", "sl_l", "sl_r", "sr_l", "sr_r", "reset_mouse", "active_gyro" }) variables[s] = GetDefaultValue(s); if (File.Exists(PATH)) { diff --git a/BetterJoyForCemu/Joycon.cs b/BetterJoyForCemu/Joycon.cs index fc64621..e15be2f 100644 --- a/BetterJoyForCemu/Joycon.cs +++ b/BetterJoyForCemu/Joycon.cs @@ -518,11 +518,28 @@ namespace BetterJoyForCemu { return ret; } - private void Simulate(string s) { - if (s.StartsWith("key_")) - WindowsInput.Simulate.Events().Click((WindowsInput.Events.KeyCode) Int32.Parse(s.Substring(4))).Invoke(); - else if (s.StartsWith("mse_")) - WindowsInput.Simulate.Events().Click((WindowsInput.Events.ButtonCode) Int32.Parse(s.Substring(4))).Invoke(); + private void Simulate(string s, bool click=true, bool up=false) { + if (s.StartsWith("key_")) { + if (click) { + WindowsInput.Simulate.Events().Click((WindowsInput.Events.KeyCode)Int32.Parse(s.Substring(4))).Invoke(); + } else { + if (up) { + WindowsInput.Simulate.Events().Release((WindowsInput.Events.KeyCode)Int32.Parse(s.Substring(4))).Invoke(); + } else { + WindowsInput.Simulate.Events().Hold((WindowsInput.Events.KeyCode)Int32.Parse(s.Substring(4))).Invoke(); + } + } + } else if (s.StartsWith("mse_")) { + if (click) { + WindowsInput.Simulate.Events().Click((WindowsInput.Events.ButtonCode)Int32.Parse(s.Substring(4))).Invoke(); + } else { + if (up) { + WindowsInput.Simulate.Events().Release((WindowsInput.Events.ButtonCode)Int32.Parse(s.Substring(4))).Invoke(); + } else { + WindowsInput.Simulate.Events().Hold((WindowsInput.Events.ButtonCode)Int32.Parse(s.Substring(4))).Invoke(); + } + } + } } string extraGyroFeature = ConfigurationManager.AppSettings["GyroToJoyOrMouse"]; @@ -533,13 +550,21 @@ namespace BetterJoyForCemu { if (buttons_down[(int)Button.HOME]) Simulate(Config.Value("home")); if (isLeft && buttons_down[(int)Button.SL]) - Simulate(Config.Value("sl_l")); + Simulate(Config.Value("sl_l"), false, false); + if (isLeft && buttons_up[(int)Button.SL]) + Simulate(Config.Value("sl_l"), false, true); if (isLeft && buttons_down[(int)Button.SR]) - Simulate(Config.Value("sr_l")); + Simulate(Config.Value("sr_l"), false, false); + if (isLeft && buttons_up[(int)Button.SR]) + Simulate(Config.Value("sr_l"), false, true); if (!isLeft && buttons_down[(int)Button.SL]) - Simulate(Config.Value("sl_r")); + Simulate(Config.Value("sl_r"), false, false); + if (!isLeft && buttons_up[(int)Button.SL]) + Simulate(Config.Value("sl_r"), false, true); if (!isLeft && buttons_down[(int)Button.SR]) - Simulate(Config.Value("sr_r")); + Simulate(Config.Value("sr_r"), false, false); + if (!isLeft && buttons_up[(int)Button.SR]) + Simulate(Config.Value("sr_r"), false, true); if (extraGyroFeature == "joy") { // TODO @@ -553,8 +578,10 @@ namespace BetterJoyForCemu { WindowsInput.Simulate.Events().MoveBy(dx, dy).Invoke(); // reset mouse position to centre of primary monitor - if (buttons_down[(int)Button.STICK] || buttons_down[(int)Button.STICK2]) - WindowsInput.Simulate.Events().MoveTo(Screen.PrimaryScreen.Bounds.Width / 2, Screen.PrimaryScreen.Bounds.Height / 2).Invoke(); + string res_val = Config.Value("reset_mouse"); + if (res_val.StartsWith("joy_")) + if (buttons_down[Int32.Parse(res_val.Substring(4))]) + WindowsInput.Simulate.Events().MoveTo(Screen.PrimaryScreen.Bounds.Width / 2, Screen.PrimaryScreen.Bounds.Height / 2).Invoke(); } } diff --git a/BetterJoyForCemu/Program.cs b/BetterJoyForCemu/Program.cs index ac31281..00b74c0 100644 --- a/BetterJoyForCemu/Program.cs +++ b/BetterJoyForCemu/Program.cs @@ -2,9 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; -using System.Numerics; using System.Threading; using System.Runtime.InteropServices; using System.Timers; @@ -14,7 +12,6 @@ using System.Diagnostics; using static BetterJoyForCemu.HIDapi; using Nefarius.ViGEm.Client; -using Nefarius.ViGEm.Client.Targets; using System.Net; using System.Configuration; using System.Net.Http; @@ -356,6 +353,9 @@ namespace BetterJoyForCemu { static public bool useHIDG = Boolean.Parse(ConfigurationManager.AppSettings["UseHIDG"]); + private static WindowsInput.Events.Sources.IKeyboardEventSource keyboard; + private static WindowsInput.Events.Sources.IMouseEventSource mouse; + public static void Start() { pid = Process.GetCurrentProcess().Id.ToString(); // get current process id for HidCerberus.Srv @@ -363,17 +363,17 @@ namespace BetterJoyForCemu { try { var HidCerberusService = new ServiceController("HidCerberus Service"); if (HidCerberusService.Status == ServiceControllerStatus.Stopped) { - form.console.Text += "HidGuardian was stopped. Starting...\r\n"; + form.console.AppendText("HidGuardian was stopped. Starting...\r\n"); try { HidCerberusService.Start(); } catch (Exception e) { - form.console.Text += "Unable to start HidGuardian - everything should work fine without it, but if you need it, run the app again as an admin.\r\n"; + form.console.AppendText("Unable to start HidGuardian - everything should work fine without it, but if you need it, run the app again as an admin.\r\n"); useHIDG = false; } } } catch (Exception e) { - form.console.Text += "Unable to start HidGuardian - everything should work fine without it, but if you need it, install it properly as admin.\r\n"; + form.console.AppendText("Unable to start HidGuardian - everything should work fine without it, but if you need it, install it properly as admin.\r\n"); useHIDG = false; } @@ -382,7 +382,7 @@ namespace BetterJoyForCemu { try { response = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/whitelist/purge/").GetResponse(); // remove all programs allowed to see controller } catch (Exception e) { - form.console.Text += "Unable to purge whitelist.\r\n"; + form.console.AppendText("Unable to purge whitelist.\r\n"); useHIDG = false; } } @@ -390,14 +390,20 @@ namespace BetterJoyForCemu { try { response = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/whitelist/add/" + pid).GetResponse(); // add BetterJoyForCemu to allowed processes } catch (Exception e) { - form.console.Text += "Unable to add program to whitelist.\r\n"; + form.console.AppendText("Unable to add program to whitelist.\r\n"); useHIDG = false; } } else { - form.console.Text += "HidGuardian is disabled.\r\n"; + form.console.AppendText("HidGuardian is disabled.\r\n"); } - emClient = new ViGEmClient(); // Manages emulated XInput + if (Boolean.Parse(ConfigurationManager.AppSettings["ShowAsXInput"])) { + try { + emClient = new ViGEmClient(); // Manages emulated XInput + } catch (Nefarius.ViGEm.Client.Exceptions.VigemBusNotFoundException) { + form.console.AppendText("Could not start VigemBus. Make sure drivers are installed correctly.\r\n"); + } + } foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) { // Get local BT host MAC @@ -421,7 +427,31 @@ namespace BetterJoyForCemu { timer = new HighResTimer(pollsPerSecond, new HighResTimer.ActionDelegate(mgr.Update)); timer.Start(); - form.console.Text += "All systems go\r\n"; + // Capture keyboard + mouse events for binding's sake + keyboard = WindowsInput.Capture.Global.KeyboardAsync(); + keyboard.KeyEvent += Keyboard_KeyEvent; + mouse = WindowsInput.Capture.Global.MouseAsync(); + mouse.MouseEvent += Mouse_MouseEvent; + + form.console.AppendText("All systems go\r\n"); + } + + private static void Mouse_MouseEvent(object sender, WindowsInput.Events.Sources.EventSourceEventArgs e) { + if (e.Data.ButtonDown != null) { + string res_val = Config.Value("reset_mouse"); + if (res_val.StartsWith("mse_")) + if ((int)e.Data.ButtonDown.Button == Int32.Parse(res_val.Substring(4))) + WindowsInput.Simulate.Events().MoveTo(Screen.PrimaryScreen.Bounds.Width / 2, Screen.PrimaryScreen.Bounds.Height / 2).Invoke(); + } + } + + private static void Keyboard_KeyEvent(object sender, WindowsInput.Events.Sources.EventSourceEventArgs e) { + if (e.Data.KeyDown != null) { + string res_val = Config.Value("reset_mouse"); + if (res_val.StartsWith("key_")) + if ((int)e.Data.KeyDown.Key == Int32.Parse(res_val.Substring(4))) + WindowsInput.Simulate.Events().MoveTo(Screen.PrimaryScreen.Bounds.Width / 2, Screen.PrimaryScreen.Bounds.Height / 2).Invoke(); + } } public static void Stop() { @@ -429,7 +459,7 @@ namespace BetterJoyForCemu { try { HttpWebResponse response = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/whitelist/remove/" + pid).GetResponse(); } catch (Exception e) { - form.console.Text += "Unable to remove program from whitelist.\r\n"; + form.console.AppendText("Unable to remove program from whitelist.\r\n"); } } @@ -439,6 +469,7 @@ namespace BetterJoyForCemu { } catch { } } + keyboard.Dispose(); mouse.Dispose(); server.Stop(); timer.Stop(); mgr.OnApplicationQuit(); diff --git a/BetterJoyForCemu/Reassign.Designer.cs b/BetterJoyForCemu/Reassign.Designer.cs index b76b286..1ac2fc4 100644 --- a/BetterJoyForCemu/Reassign.Designer.cs +++ b/BetterJoyForCemu/Reassign.Designer.cs @@ -4,6 +4,7 @@ using System.Drawing.Drawing2D; using System.Windows.Forms; namespace BetterJoyForCemu { + // from https://stackoverflow.com/a/27173509 public class SplitButton : Button { [DefaultValue(null), Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] @@ -47,7 +48,7 @@ namespace BetterJoyForCemu { int lineX = ClientRectangle.Width - this.SplitWidth; int lineYFrom = arrowY - 4; int lineYTo = arrowY + 8; - using (var separatorPen = new Pen(Brushes.DarkGray) { DashStyle = DashStyle.Dot }) { + using (var separatorPen = new Pen(Brushes.DarkGray) { DashStyle = System.Drawing.Drawing2D.DashStyle.Dot }) { pevent.Graphics.DrawLine(separatorPen, lineX, lineYFrom, lineX, lineYTo); } } @@ -80,23 +81,25 @@ namespace BetterJoyForCemu { private void InitializeComponent() { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Reassign)); - this.btn_capture = new SplitButton(); + this.btn_capture = new BetterJoyForCemu.SplitButton(); this.lbl_capture = new System.Windows.Forms.Label(); this.lbl_home = new System.Windows.Forms.Label(); - this.btn_home = new SplitButton(); + this.btn_home = new BetterJoyForCemu.SplitButton(); this.lbl_sl_l = new System.Windows.Forms.Label(); - this.btn_sl_l = new SplitButton(); + this.btn_sl_l = new BetterJoyForCemu.SplitButton(); this.lbl_sr_l = new System.Windows.Forms.Label(); - this.btn_sr_l = new SplitButton(); + this.btn_sr_l = new BetterJoyForCemu.SplitButton(); this.lbl_sl_r = new System.Windows.Forms.Label(); - this.btn_sl_r = new SplitButton(); + this.btn_sl_r = new BetterJoyForCemu.SplitButton(); this.lbl_sr_r = new System.Windows.Forms.Label(); - this.btn_sr_r = new SplitButton(); - this.btn_close = new SplitButton(); - this.btn_apply = new SplitButton(); + this.btn_sr_r = new BetterJoyForCemu.SplitButton(); + this.btn_close = new BetterJoyForCemu.SplitButton(); + this.btn_apply = new BetterJoyForCemu.SplitButton(); this.tip_reassign = new System.Windows.Forms.ToolTip(this.components); this.lbl_reset_mouse = new System.Windows.Forms.Label(); - this.btn_reset_mouse = new SplitButton(); + this.btn_reset_mouse = new BetterJoyForCemu.SplitButton(); + this.lbl_activate_gyro = new System.Windows.Forms.Label(); + this.btn_active_gyro = new SplitButton(); this.SuspendLayout(); // // btn_capture @@ -209,7 +212,7 @@ namespace BetterJoyForCemu { // // btn_close // - this.btn_close.Location = new System.Drawing.Point(15, 231); + this.btn_close.Location = new System.Drawing.Point(15, 257); this.btn_close.Name = "btn_close"; this.btn_close.Size = new System.Drawing.Size(75, 23); this.btn_close.TabIndex = 13; @@ -219,7 +222,7 @@ namespace BetterJoyForCemu { // // btn_apply // - this.btn_apply.Location = new System.Drawing.Point(105, 231); + this.btn_apply.Location = new System.Drawing.Point(105, 257); this.btn_apply.Name = "btn_apply"; this.btn_apply.Size = new System.Drawing.Size(75, 23); this.btn_apply.TabIndex = 14; @@ -245,11 +248,31 @@ namespace BetterJoyForCemu { this.btn_reset_mouse.TabIndex = 15; this.btn_reset_mouse.UseVisualStyleBackColor = true; // + // lbl_activate_gyro + // + this.lbl_activate_gyro.AutoSize = true; + this.lbl_activate_gyro.Location = new System.Drawing.Point(14, 220); + this.lbl_activate_gyro.Name = "lbl_activate_gyro"; + this.lbl_activate_gyro.Size = new System.Drawing.Size(71, 13); + this.lbl_activate_gyro.TabIndex = 17; + this.lbl_activate_gyro.Text = "Activate Gyro"; + this.lbl_activate_gyro.TextAlign = System.Drawing.ContentAlignment.TopCenter; + // + // btn_active_gyro + // + this.btn_active_gyro.Location = new System.Drawing.Point(105, 215); + this.btn_active_gyro.Name = "btn_active_gyro"; + this.btn_active_gyro.Size = new System.Drawing.Size(75, 23); + this.btn_active_gyro.TabIndex = 18; + this.btn_active_gyro.UseVisualStyleBackColor = true; + // // Reassign // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(192, 266); + this.ClientSize = new System.Drawing.Size(192, 292); + this.Controls.Add(this.btn_active_gyro); + this.Controls.Add(this.lbl_activate_gyro); this.Controls.Add(this.lbl_reset_mouse); this.Controls.Add(this.btn_reset_mouse); this.Controls.Add(this.btn_apply); @@ -298,5 +321,7 @@ namespace BetterJoyForCemu { private System.Windows.Forms.ToolTip tip_reassign; private System.Windows.Forms.Label lbl_reset_mouse; private SplitButton btn_reset_mouse; + private Label lbl_activate_gyro; + private SplitButton btn_active_gyro; } } \ No newline at end of file diff --git a/BetterJoyForCemu/Reassign.cs b/BetterJoyForCemu/Reassign.cs index 7e6de89..122e3d8 100644 --- a/BetterJoyForCemu/Reassign.cs +++ b/BetterJoyForCemu/Reassign.cs @@ -29,7 +29,7 @@ namespace BetterJoyForCemu { menu_joy_buttons.ItemClicked += Menu_joy_buttons_ItemClicked; - foreach (SplitButton c in new SplitButton[] { btn_capture, btn_home, btn_sl_l, btn_sl_r, btn_sr_l, btn_sr_r, btn_reset_mouse }) { + foreach (SplitButton c in new SplitButton[] { btn_capture, btn_home, btn_sl_l, btn_sl_r, btn_sr_l, btn_sr_r, btn_reset_mouse , btn_active_gyro}) { c.Tag = c.Name.Substring(4); GetPrettyName(c); @@ -78,6 +78,7 @@ namespace BetterJoyForCemu { Config.SetValue((string)curAssignment.Tag, "mse_" + ((int)e.Data.ButtonDown.Button)); AsyncPrettyName(curAssignment); curAssignment = null; + e.Next_Hook_Enabled = false; } } @@ -86,6 +87,7 @@ namespace BetterJoyForCemu { Config.SetValue((string)curAssignment.Tag, "key_" + ((int)e.Data.KeyDown.Key)); AsyncPrettyName(curAssignment); curAssignment = null; + e.Next_Hook_Enabled = false; } }