BetterJoy/BetterJoyForCemu/Controller/OutputControllerDualShock4.cs
Robert Borg a8396554e7
Fix input delay 2 (#357)
* extract xboxc360ontroller

* extracts DualShock4Controller

* Revert "ensures we get the latest available HID data (#345)"

This reverts commit cd659366b5.

* Revert "fixes cpu busy spinning when there is no hid data available (#356)"

This reverts commit c4f5bbdc56.
2020-05-20 19:58:40 +01:00

192 lines
6.8 KiB
C#

using Nefarius.ViGEm.Client.Targets;
using Nefarius.ViGEm.Client.Targets.DualShock4;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms.VisualStyles;
using System.Xml.Serialization;
namespace BetterJoyForCemu.Controller
{
public enum DpadDirection
{
None,
Northwest,
West,
Southwest,
South,
Southeast,
East,
Northeast,
North,
}
public struct OutputControllerDualShock4InputState
{
public bool triangle;
public bool circle;
public bool cross;
public bool square;
public bool trigger_left;
public bool trigger_right;
public bool shoulder_left;
public bool shoulder_right;
public bool options;
public bool share;
public bool ps;
public bool touchpad;
public bool thumb_left;
public bool thumb_right;
public DpadDirection dPad;
public byte thumb_left_x;
public byte thumb_left_y;
public byte thumb_right_x;
public byte thumb_right_y;
public byte trigger_left_value;
public byte trigger_right_value;
public bool IsEqual(OutputControllerDualShock4InputState other) {
bool buttons = triangle == other.triangle
&& circle == other.circle
&& cross == other.cross
&& square == other.square
&& trigger_left == other.trigger_left
&& trigger_right == other.trigger_right
&& shoulder_left == other.shoulder_left
&& shoulder_right == other.shoulder_right
&& options == other.options
&& share == other.share
&& ps == other.ps
&& touchpad == other.touchpad
&& thumb_left == other.thumb_left
&& thumb_right == other.thumb_right
&& dPad == other.dPad;
bool axis = thumb_left_x == other.thumb_left_x
&& thumb_left_y == other.thumb_left_y
&& thumb_right_x == other.thumb_right_x
&& thumb_right_y == other.thumb_right_y;
bool triggers = trigger_left_value == other.trigger_left_value
&& trigger_right_value == other.trigger_right_value;
return buttons && axis && triggers;
}
}
public class OutputControllerDualShock4
{
private IDualShock4Controller controller;
private OutputControllerDualShock4InputState current_state;
public delegate void DualShock4FeedbackReceivedEventHandler(DualShock4FeedbackReceivedEventArgs e);
public event DualShock4FeedbackReceivedEventHandler FeedbackReceived;
public OutputControllerDualShock4()
{
controller = Program.emClient.CreateDualShock4Controller();
Init();
}
public OutputControllerDualShock4(ushort vendor_id, ushort product_id)
{
controller = Program.emClient.CreateDualShock4Controller(vendor_id, product_id);
Init();
}
private void Init()
{
controller.AutoSubmitReport = false;
controller.FeedbackReceived += FeedbackReceivedRcv;
}
private void FeedbackReceivedRcv(object _sender, DualShock4FeedbackReceivedEventArgs e)
{
FeedbackReceived(e);
}
public void Connect() {
controller.Connect();
}
public void Disconnect() {
controller.Disconnect();
}
public bool UpdateInput(OutputControllerDualShock4InputState new_state)
{
if(current_state.IsEqual(new_state))
{
return false;
}
DoUpdateInput(new_state);
return true;
}
private void DoUpdateInput(OutputControllerDualShock4InputState new_state)
{
controller.SetButtonState(DualShock4Button.Triangle, new_state.triangle);
controller.SetButtonState(DualShock4Button.Circle, new_state.circle);
controller.SetButtonState(DualShock4Button.Cross, new_state.cross);
controller.SetButtonState(DualShock4Button.Square, new_state.square);
controller.SetButtonState(DualShock4Button.ShoulderLeft, new_state.shoulder_left);
controller.SetButtonState(DualShock4Button.ShoulderRight, new_state.shoulder_right);
controller.SetButtonState(DualShock4Button.TriggerLeft, new_state.trigger_left);
controller.SetButtonState(DualShock4Button.TriggerRight, new_state.trigger_right);
controller.SetButtonState(DualShock4Button.ThumbLeft, new_state.thumb_left);
controller.SetButtonState(DualShock4Button.ThumbRight, new_state.thumb_left);
controller.SetButtonState(DualShock4Button.Share, new_state.share);
controller.SetButtonState(DualShock4Button.Options, new_state.options);
controller.SetButtonState(DualShock4SpecialButton.Ps, new_state.ps);
controller.SetButtonState(DualShock4SpecialButton.Touchpad, new_state.touchpad);
controller.SetDPadDirection(MapDPadDirection(new_state.dPad));
controller.SetAxisValue(DualShock4Axis.LeftThumbX, new_state.thumb_left_x);
controller.SetAxisValue(DualShock4Axis.LeftThumbY, new_state.thumb_left_y);
controller.SetAxisValue(DualShock4Axis.RightThumbX, new_state.thumb_right_x);
controller.SetAxisValue(DualShock4Axis.RightThumbY, new_state.thumb_right_y);
controller.SetSliderValue(DualShock4Slider.LeftTrigger, new_state.trigger_left_value);
controller.SetSliderValue(DualShock4Slider.RightTrigger, new_state.trigger_right_value);
controller.SubmitReport();
current_state = new_state;
}
private DualShock4DPadDirection MapDPadDirection(DpadDirection dPad)
{
switch(dPad)
{
case DpadDirection.None: return DualShock4DPadDirection.None;
case DpadDirection.North: return DualShock4DPadDirection.North;
case DpadDirection.Northeast: return DualShock4DPadDirection.Northeast;
case DpadDirection.East: return DualShock4DPadDirection.East;
case DpadDirection.Southeast: return DualShock4DPadDirection.Southeast;
case DpadDirection.South: return DualShock4DPadDirection.South;
case DpadDirection.Southwest: return DualShock4DPadDirection.Southwest;
case DpadDirection.West: return DualShock4DPadDirection.West;
case DpadDirection.Northwest: return DualShock4DPadDirection.Northwest;
default: throw new NotImplementedException();
}
}
}
}