- Added option to use gyro input as mouse

- Changed default of UseHIDG to false
 - Improved start-up and shut-down time
 - Added option to disable motion server
This commit is contained in:
David Khachaturov 2020-04-02 10:23:48 +01:00
parent ebc3640121
commit e579f4a94e
4 changed files with 72 additions and 18 deletions

View file

@ -10,6 +10,8 @@
<!--Motion Server port: the default is 26760; if it conflicts with another server set it to anything valid
but in that case also change the port in PadTest and cemuhook.ini accordingly. Default: 26760 -->
<add key="Port" value="26760" />
<!--Whether the Motion Server is enabled or not. Default: true -->
<add key="MotionServer" value="false" />
<!--Rumble motor period in millisec. Lower means more granular vibration, higher is more stable.-->
<!--The response of rumble does not only depend on this setting and it's always high. Default: 300 -->
<add key="RumblePeriod" value="300" />
@ -34,8 +36,8 @@
<add key="PurgeWhitelist" value="true" />
<!-- Determines whether or not to use HidGuardian (improves compatibility with other programs, like Steam, when set to "false") -->
<!-- When "true", BetterJoyForCemu will hide the Pro/Joycons from other programs to prevent glitching out on exit and to prevent DI/XI clashes in certain programs -->
<!-- Default: true -->
<add key="UseHIDG" value="true" />
<!-- Default: false -->
<add key="UseHIDG" value="false" />
<!-- Determines whether or not the program will expose detected controllers as Xbox 360 controllers -->
<!-- When "false", BetterJoyForCemu is only usable with CEMU. -->
<!-- Default: true -->
@ -45,11 +47,19 @@
<!-- Default: true -->
<add key="PurgeAffectedDevices" value="true" />
<!-- Determines whether or not to enable (experimental - currently default controller to pro) support for 3rd-party controllers. Adds a "Calibrate" button. -->
<!-- When "true", click "Calibrate" button once to get gyro calibrate data .-->
<!-- When "true", click "Calibrate" button once to get gyro calibrate data. -->
<!-- When enabled, can only calibrate one controller at a time. -->
<!-- Default: false -->
<add key="NonOriginalController" value="false" />
<!-- The program will keep the HOME button LED ring light on at all times-->
<add key="HomeLEDOn" value="false"/>
<!-- Determines whether or not to translate gyro movements into joystick ("joy") or mouse movement ("mouse"), or have no effect ("none") -->
<!-- When "joy", turn gyro movements into joystick movement (left/right depends on setting) [not yet implemented]-->
<!-- When "mouse", turn gyro movements into mouse movement. Press either stick-button to reset to middle of primary display -->
<!-- Default: none -->
<add key="GyroToJoyOrMouse" value="mouse"/>
<!-- Sensitivity of gyro-to-mouse movements -->
<!-- Default: 50 -->
<add key="GyroMouseSensitivity" value ="50"/>
</appSettings>
</configuration>

View file

@ -11,8 +11,28 @@ using System.Threading.Tasks;
using Nefarius.ViGEm.Client;
using Nefarius.ViGEm.Client.Targets;
using Nefarius.ViGEm.Client.Targets.Xbox360;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace BetterJoyForCemu {
// For mouse movement
public class Win32 {
[DllImport("User32.Dll")]
public static extern long SetCursorPos(int x, int y);
[DllImport("User32.dll")]
public static extern bool GetCursorPos(out POINT lpPoint);
[DllImport("User32.Dll")]
public static extern bool ClientToScreen(IntPtr hWnd, ref POINT point);
[StructLayout(LayoutKind.Sequential)]
public struct POINT {
public int x;
public int y;
}
}
public class Joycon {
float timing = 120.0f;
@ -445,6 +465,9 @@ namespace BetterJoyForCemu {
state = state_.NOT_ATTACHED;
}
string extraGyroFeature = ConfigurationManager.AppSettings["GyroToJoyOrMouse"];
int GyroMouseSensitivity = Int32.Parse(ConfigurationManager.AppSettings["GyroMouseSensitivity"]);
// TODO: Improve this loop, make USB not laggy
private byte ts_en;
private int ReceiveRaw() {
if (handle == IntPtr.Zero) return -2;
@ -476,6 +499,25 @@ namespace BetterJoyForCemu {
xin.SendReport(report);
}
if (extraGyroFeature == "joy") {
// TODO
} else if (extraGyroFeature == "mouse") {
Win32.POINT p;
Win32.GetCursorPos(out p);
float dt = 0.015f; // 15ms
// gyro data is in degrees/s
int dx = (int)(GyroMouseSensitivity * (gyr_g.Z * dt) * (Math.Abs(gyr_g.Z) < 1 ? 0 : 1));
int dy = (int)-(GyroMouseSensitivity * (gyr_g.Y * dt) * (Math.Abs(gyr_g.Y) < 1 ? 0 : 1));
Win32.SetCursorPos(p.x + dx, p.y + dy);
// reset mouse position to centre of primary monitor
if (buttons[(int) Button.STICK] || buttons[(int) Button.STICK2])
Win32.SetCursorPos(Screen.PrimaryScreen.Bounds.Width / 2, Screen.PrimaryScreen.Bounds.Height / 2);
}
if (ts_en == raw_buf[1] && !isSnes) {
form.AppendTextBox("Duplicate timestamp enqueued.\r\n");
DebugPrint(string.Format("Duplicate timestamp enqueued. TS: {0:X2}", ts_en), DebugType.THREADING);
@ -486,6 +528,7 @@ namespace BetterJoyForCemu {
return ret;
}
// TODO: Fix?
private Thread PollThreadObj; // pro times out over time randomly if it was USB and then bluetooth??
private void Poll() {
int attempts = 0;
@ -709,6 +752,7 @@ namespace BetterJoyForCemu {
return 0;
}
// Get Gyro/Accel data
private void ExtractIMUValues(byte[] report_buf, int n = 0) {
if (!isSnes) {
gyr_r[0] = (Int16)(report_buf[19 + n * 12] | ((report_buf[20 + n * 12] << 8) & 0xff00));
@ -718,7 +762,6 @@ namespace BetterJoyForCemu {
acc_r[1] = (Int16)(report_buf[15 + n * 12] | ((report_buf[16 + n * 12] << 8) & 0xff00));
acc_r[2] = (Int16)(report_buf[17 + n * 12] | ((report_buf[18 + n * 12] << 8) & 0xff00));
if (form.nonOriginal) {
for (int i = 0; i < 3; ++i) {
switch (i) {

View file

@ -53,7 +53,7 @@ namespace BetterJoyForCemu {
}
public void Start() {
controllerCheck = new System.Timers.Timer(2000); // check every 2 seconds
controllerCheck = new System.Timers.Timer(5000); // check for new controllers every 5 seconds
controllerCheck.Elapsed += CheckForNewControllersTime;
controllerCheck.Start();
}
@ -159,10 +159,6 @@ namespace BetterJoyForCemu {
} catch {
form.AppendTextBox("Unable to add controller to block-list.\r\n");
}
} else { // Remove affected devices from list
try {
HttpWebResponse r1 = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/affected/purge/").GetResponse();
} catch { }
}
// -------------------- //
@ -426,13 +422,15 @@ namespace BetterJoyForCemu {
}
public static void Stop() {
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";
if (Program.useHIDG) {
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";
}
}
if (Boolean.Parse(ConfigurationManager.AppSettings["PurgeAffectedDevices"])) {
if (Boolean.Parse(ConfigurationManager.AppSettings["PurgeAffectedDevices"]) && Program.useHIDG) {
try {
HttpWebResponse r1 = (HttpWebResponse)WebRequest.Create(@"http://localhost:26762/api/v1/hidguardian/affected/purge/").GetResponse();
} catch { }
@ -441,8 +439,6 @@ namespace BetterJoyForCemu {
server.Stop();
timer.Stop();
mgr.OnApplicationQuit();
form.console.Text += "";
}
static void Main(string[] args) {

View file

@ -282,6 +282,11 @@ namespace BetterJoyForCemu {
}
public void Start(IPAddress ip, int port = 26760) {
if (!Boolean.Parse(ConfigurationManager.AppSettings["MotionServer"])) {
form.console.AppendText("Motion server is OFF.\r\n");
return;
}
if (running) {
if (udpSock != null) {
udpSock.Close();
@ -295,7 +300,7 @@ namespace BetterJoyForCemu {
udpSock.Close();
udpSock = null;
form.console.Text += "Could not start server. Make sure that only one instance of the program is running at a time and no other CemuHook applications are running.\r\n";
form.console.AppendText("Could not start server. Make sure that only one instance of the program is running at a time and no other CemuHook applications are running.\r\n");
return;
}
@ -304,7 +309,7 @@ namespace BetterJoyForCemu {
serverId = BitConverter.ToUInt32(randomBuf, 0);
running = true;
form.console.Text += String.Format("Starting server on {0}:{1}\r\n", ip.ToString(), port);
form.console.AppendText(String.Format("Starting server on {0}:{1}\r\n", ip.ToString(), port));
StartReceive();
}