Skip to content

Instantly share code, notes, and snippets.

@Ryochan7
Last active March 4, 2021 00:20
Show Gist options
  • Save Ryochan7/736cbd9c488e6b6409fa4757b08f0aaf to your computer and use it in GitHub Desktop.
Save Ryochan7/736cbd9c488e6b6409fa4757b08f0aaf to your computer and use it in GitHub Desktop.
diff --git a/DS4Windows/DS4Control/ControlService.cs b/DS4Windows/DS4Control/ControlService.cs
index a47dfb0b..86a9d578 100644
--- a/DS4Windows/DS4Control/ControlService.cs
+++ b/DS4Windows/DS4Control/ControlService.cs
@@ -10,6 +10,7 @@ using System.Windows.Threading;
using DS4WinWPF.DS4Control;
using Microsoft.Win32;
using Sensorit.Base;
+using System.Linq;
namespace DS4Windows
{
@@ -256,6 +257,22 @@ namespace DS4Windows
DualSenseControllerOptions dSOpts = tempDSDev.NativeOptionsStore;
dSOpts.LedModeChanged += (sender, e) => { tempDSDev.CheckControllerNumDeviceSettings(activeControllers); };
}
+ else if (device.DeviceType == InputDevices.InputDeviceType.JoyConL ||
+ device.DeviceType == InputDevices.InputDeviceType.JoyConR)
+ {
+ InputDevices.JoyConDevice tempJoyDev = device as InputDevices.JoyConDevice;
+ tempJoyDev.PerformStateMerge = true;
+ if (device.DeviceType == InputDevices.InputDeviceType.JoyConL)
+ {
+ tempJoyDev.PrimaryDevice = true;
+ tempJoyDev.OutputMapGyro = false;
+ }
+ else
+ {
+ tempJoyDev.PrimaryDevice = false;
+ tempJoyDev.OutputMapGyro = true;
+ }
+ }
}
public bool CheckForSupportedDevice(HidDevice device, VidPidInfo metaInfo)
@@ -623,7 +640,7 @@ namespace DS4Windows
return temp;
}
- private void EstablishOutFeedback(int index, OutContType contType,
+ public void EstablishOutFeedback(int index, OutContType contType,
OutputDevice outDevice, DS4Device device)
{
int devIndex = index;
@@ -638,7 +655,7 @@ namespace DS4Windows
SetDevRumble(device, args.LargeMotor, args.SmallMotor, devIndex);
};
tempXbox.cont.FeedbackReceived += p;
- tempXbox.forceFeedbackCall = p;
+ tempXbox.forceFeedbackCall.Add(index, p);
}
else if (contType == OutContType.DS4)
{
@@ -717,13 +734,15 @@ namespace DS4Windows
}
}
- public void RemoveOutFeedback(OutContType contType, OutputDevice outDevice)
+ public void RemoveOutFeedback(OutContType contType, OutputDevice outDevice, int inIdx)
{
if (contType == OutContType.X360)
{
Xbox360OutDevice tempXbox = outDevice as Xbox360OutDevice;
- tempXbox.cont.FeedbackReceived -= tempXbox.forceFeedbackCall;
- tempXbox.forceFeedbackCall = null;
+ tempXbox.cont.FeedbackReceived -= tempXbox.forceFeedbackCall[inIdx];
+ tempXbox.forceFeedbackCall.Remove(inIdx);
+ //tempXbox.cont.FeedbackReceived -= tempXbox.forceFeedbackCall;
+ //tempXbox.forceFeedbackCall = null;
}
else if (contType == OutContType.DS4)
{
@@ -790,7 +809,17 @@ namespace DS4Windows
// Enable ViGem feedback callback handler only if lightbar/rumble data output is enabled (if those are disabled then no point enabling ViGem callback handler call)
if (Global.EnableOutputDataToDS4[index])
+ {
EstablishOutFeedback(index, OutContType.X360, tempXbox, device);
+ if (device.JointDeviceSlotNumber != -1)
+ {
+ DS4Device tempDS4Device = DS4Controllers[device.JointDeviceSlotNumber];
+ if (tempDS4Device != null)
+ {
+ EstablishOutFeedback(device.JointDeviceSlotNumber, OutContType.X360, tempXbox, tempDS4Device);
+ }
+ }
+ }
outputslotMan.DeferredPlugin(tempXbox, index, outputDevices, contType);
//slotDevice.CurrentInputBound = OutSlotDevice.InputBound.Bound;
@@ -810,8 +839,19 @@ namespace DS4Windows
// Enable ViGem feedback callback handler only if lightbar/rumble data output is enabled (if those are disabled then no point enabling ViGem callback handler call)
if (Global.EnableOutputDataToDS4[index])
+ {
EstablishOutFeedback(index, OutContType.X360, tempXbox, device);
+ if (device.JointDeviceSlotNumber != -1)
+ {
+ DS4Device tempDS4Device = DS4Controllers[device.JointDeviceSlotNumber];
+ if (tempDS4Device != null)
+ {
+ EstablishOutFeedback(device.JointDeviceSlotNumber, OutContType.X360, tempXbox, tempDS4Device);
+ }
+ }
+ }
+
outputslotMan.EventDispatcher.BeginInvoke((Action)(() =>
{
outputDevices[index] = tempXbox;
@@ -838,8 +878,19 @@ namespace DS4Windows
// Enable ViGem feedback callback handler only if DS4 lightbar/rumble data output is enabled (if those are disabled then no point enabling ViGem callback handler call)
if (Global.EnableOutputDataToDS4[index])
+ {
EstablishOutFeedback(index, OutContType.DS4, tempDS4, device);
-
+
+ if (device.JointDeviceSlotNumber != -1)
+ {
+ DS4Device tempDS4Device = DS4Controllers[device.JointDeviceSlotNumber];
+ if (tempDS4Device != null)
+ {
+ EstablishOutFeedback(device.JointDeviceSlotNumber, OutContType.DS4, tempDS4, tempDS4Device);
+ }
+ }
+ }
+
outputslotMan.DeferredPlugin(tempDS4, index, outputDevices, contType);
//slotDevice.CurrentInputBound = OutSlotDevice.InputBound.Bound;
@@ -858,8 +909,19 @@ namespace DS4Windows
// Enable ViGem feedback callback handler only if lightbar/rumble data output is enabled (if those are disabled then no point enabling ViGem callback handler call)
if (Global.EnableOutputDataToDS4[index])
+ {
EstablishOutFeedback(index, OutContType.DS4, tempDS4, device);
+ if (device.JointDeviceSlotNumber != -1)
+ {
+ DS4Device tempDS4Device = DS4Controllers[device.JointDeviceSlotNumber];
+ if (tempDS4Device != null)
+ {
+ EstablishOutFeedback(device.JointDeviceSlotNumber, OutContType.DS4, tempDS4, tempDS4Device);
+ }
+ }
+ }
+
outputslotMan.EventDispatcher.BeginInvoke((Action)(() =>
{
outputDevices[index] = tempDS4;
@@ -912,7 +974,8 @@ namespace DS4Windows
{
slotDevice.CurrentInputBound = OutSlotDevice.InputBound.Unbound;
dev.ResetState();
- RemoveOutFeedback(currentType, dev);
+ dev.RemoveFeedbacks();
+ //RemoveOutFeedback(currentType, dev, index);
}
//dev.Disconnect();
//LogDebug(tempType + " Controller # " + (index + 1) + " unplugged");
@@ -974,6 +1037,7 @@ namespace DS4Windows
//for (int i = 0, devCount = devices.Count(); i < devCount; i++)
int i = 0;
+ InputDevices.JoyConDevice tempPrimaryJoyDev = null;
for (var devEnum = devices.GetEnumerator(); devEnum.MoveNext() && loopControllers; i++)
{
DS4Device device = devEnum.Current;
@@ -990,10 +1054,34 @@ namespace DS4Windows
Task task = new Task(() => { Thread.Sleep(5); WarnExclusiveModeFailure(device); });
task.Start();
+ PostDS4DeviceInit(device);
+
+ if ((device.DeviceType == InputDevices.InputDeviceType.JoyConL ||
+ device.DeviceType == InputDevices.InputDeviceType.JoyConR) && device.PerformStateMerge)
+ {
+ if (tempPrimaryJoyDev == null)
+ {
+ tempPrimaryJoyDev = device as InputDevices.JoyConDevice;
+ }
+ else
+ {
+ InputDevices.JoyConDevice currentJoyDev = device as InputDevices.JoyConDevice;
+ tempPrimaryJoyDev.JointDevice = currentJoyDev;
+ currentJoyDev.JointDevice = tempPrimaryJoyDev;
+
+ tempPrimaryJoyDev.JointState = currentJoyDev.JointState;
+
+ InputDevices.JoyConDevice parentJoy = tempPrimaryJoyDev;
+ tempPrimaryJoyDev.Removal += (sender, args) => { currentJoyDev.JointDevice = null; };
+ currentJoyDev.Removal += (sender, args) => { parentJoy.JointDevice = null; };
+
+ tempPrimaryJoyDev = null;
+ }
+ }
+
DS4Controllers[i] = device;
device.DeviceSlotNumber = i;
Global.LoadControllerConfigs(device);
- PostDS4DeviceInit(device);
device.LoadStoreSettings();
device.CheckControllerNumDeviceSettings(numControllers);
@@ -1030,7 +1118,28 @@ namespace DS4Windows
if (!getDInputOnly(i) && device.isSynced())
{
//useDInputOnly[i] = false;
- PluginOutDev(i, device);
+ if (device.PrimaryDevice)
+ {
+ PluginOutDev(i, device);
+ }
+ else if (device.JointDeviceSlotNumber != DS4Device.DEFAULT_JOINT_SLOT_NUMBER)
+ {
+ int otherIdx = device.JointDeviceSlotNumber;
+ OutputDevice tempOutDev = outputDevices[otherIdx];
+ if (tempOutDev != null)
+ {
+ OutContType tempConType = activeOutDevType[otherIdx];
+ EstablishOutFeedback(i, tempConType, tempOutDev, device);
+ outputDevices[i] = tempOutDev;
+ Global.activeOutDevType[i] = tempConType;
+
+ //useDInputOnly[i] = false;
+ //Global.activeOutDevType[i] = OutContType.X360;
+ }
+
+ //useDInputOnly[i] = true;
+ //Global.activeOutDevType[i] = OutContType.None;
+ }
}
else
{
@@ -1038,7 +1147,25 @@ namespace DS4Windows
Global.activeOutDevType[i] = OutContType.None;
}
- TouchPadOn(i, device);
+ if (device.PrimaryDevice && device.OutputMapGyro)
+ {
+ TouchPadOn(i, device);
+ }
+ else if (device.JointDeviceSlotNumber != DS4Device.DEFAULT_JOINT_SLOT_NUMBER)
+ {
+ int otherIdx = device.JointDeviceSlotNumber;
+ DS4Device tempDev = DS4Controllers[otherIdx];
+ if (tempDev != null)
+ {
+ int mappedIdx = tempDev.PrimaryDevice ? otherIdx : i;
+ DS4Device gyroDev = device.OutputMapGyro ? device : (tempDev.OutputMapGyro ? tempDev : null);
+ if (gyroDev != null)
+ {
+ TouchPadOn(mappedIdx, gyroDev);
+ }
+ }
+ }
+
CheckProfileOptions(i, device, true);
}
@@ -1048,7 +1175,7 @@ namespace DS4Windows
this.On_Report(sender, e, tempIdx);
};
- if (_udpServer != null && i < UdpServer.NUMBER_SLOTS)
+ if (_udpServer != null && i < UdpServer.NUMBER_SLOTS && device.PrimaryDevice)
{
DS4Device.ReportHandler<EventArgs> tempEvnt = (sender, args) =>
{
@@ -1287,6 +1414,13 @@ namespace DS4Windows
activeControllers = numControllers;
//foreach (DS4Device device in devices)
//for (int i = 0, devlen = devices.Count(); i < devlen; i++)
+ InputDevices.JoyConDevice tempPrimaryJoyDev = devices.Where(d =>
+ (d.DeviceType == InputDevices.InputDeviceType.JoyConL || d.DeviceType == InputDevices.InputDeviceType.JoyConR)
+ && d.PrimaryDevice && d.JointDeviceSlotNumber == -1).FirstOrDefault() as InputDevices.JoyConDevice;
+ InputDevices.JoyConDevice tempSecondaryJoyDev = devices.Where(d =>
+ (d.DeviceType == InputDevices.InputDeviceType.JoyConL || d.DeviceType == InputDevices.InputDeviceType.JoyConR)
+ && !d.PrimaryDevice && d.JointDeviceSlotNumber == -1).FirstOrDefault() as InputDevices.JoyConDevice;
+
for (var devEnum = devices.GetEnumerator(); devEnum.MoveNext() && loopControllers;)
{
DS4Device device = devEnum.Current;
@@ -1328,10 +1462,49 @@ namespace DS4Windows
Task task = new Task(() => { Thread.Sleep(5); WarnExclusiveModeFailure(device); });
task.Start();
+
+ PostDS4DeviceInit(device);
+
+ if ((device.DeviceType == InputDevices.InputDeviceType.JoyConL ||
+ device.DeviceType == InputDevices.InputDeviceType.JoyConR) && device.PerformStateMerge)
+ {
+ if (device.PrimaryDevice &&
+ tempSecondaryJoyDev != null)
+ {
+ InputDevices.JoyConDevice currentJoyDev = device as InputDevices.JoyConDevice;
+ tempSecondaryJoyDev.JointDevice = currentJoyDev;
+ currentJoyDev.JointDevice = tempSecondaryJoyDev;
+
+ tempSecondaryJoyDev.JointState = currentJoyDev.JointState;
+
+ InputDevices.JoyConDevice secondaryJoy = tempSecondaryJoyDev;
+ secondaryJoy.Removal += (sender, args) => { currentJoyDev.JointDevice = null; };
+ currentJoyDev.Removal += (sender, args) => { secondaryJoy.JointDevice = null; };
+
+ tempSecondaryJoyDev = null;
+ tempPrimaryJoyDev = null;
+ }
+ else if (!device.PrimaryDevice &&
+ tempPrimaryJoyDev != null)
+ {
+ InputDevices.JoyConDevice currentJoyDev = device as InputDevices.JoyConDevice;
+ tempPrimaryJoyDev.JointDevice = currentJoyDev;
+ currentJoyDev.JointDevice = tempPrimaryJoyDev;
+
+ tempPrimaryJoyDev.JointState = currentJoyDev.JointState;
+
+ InputDevices.JoyConDevice parentJoy = tempPrimaryJoyDev;
+ tempPrimaryJoyDev.Removal += (sender, args) => { currentJoyDev.JointDevice = null; };
+ currentJoyDev.Removal += (sender, args) => { parentJoy.JointDevice = null; };
+
+ tempPrimaryJoyDev = null;
+ }
+ }
+
+
DS4Controllers[Index] = device;
device.DeviceSlotNumber = Index;
Global.LoadControllerConfigs(device);
- PostDS4DeviceInit(device);
device.LoadStoreSettings();
device.CheckControllerNumDeviceSettings(numControllers);
@@ -1368,7 +1541,28 @@ namespace DS4Windows
if (!getDInputOnly(Index) && device.isSynced())
{
//useDInputOnly[Index] = false;
- PluginOutDev(Index, device);
+ if (device.PrimaryDevice)
+ {
+ PluginOutDev(Index, device);
+ }
+ else
+ {
+ int otherIdx = (device as InputDevices.JoyConDevice).JointDevice.DeviceSlotNumber;
+ OutputDevice tempOutDev = outputDevices[otherIdx];
+ if (tempOutDev != null)
+ {
+ OutContType tempConType = activeOutDevType[otherIdx];
+ EstablishOutFeedback(Index, tempConType, tempOutDev, device);
+ outputDevices[Index] = tempOutDev;
+ Global.activeOutDevType[Index] = tempConType;
+
+ //useDInputOnly[i] = false;
+ //Global.activeOutDevType[i] = OutContType.X360;
+ }
+
+ //useDInputOnly[Index] = true;
+ //Global.activeOutDevType[Index] = OutContType.None;
+ }
}
else
{
@@ -1376,7 +1570,25 @@ namespace DS4Windows
Global.activeOutDevType[Index] = OutContType.None;
}
- TouchPadOn(Index, device);
+ if (device.PrimaryDevice && device.OutputMapGyro)
+ {
+ TouchPadOn(Index, device);
+ }
+ else if (device.JointDeviceSlotNumber != DS4Device.DEFAULT_JOINT_SLOT_NUMBER)
+ {
+ int otherIdx = device.JointDeviceSlotNumber;
+ DS4Device tempDev = DS4Controllers[otherIdx];
+ if (tempDev != null)
+ {
+ int mappedIdx = tempDev.PrimaryDevice ? otherIdx : Index;
+ DS4Device gyroDev = device.OutputMapGyro ? device : (tempDev.OutputMapGyro ? tempDev : null);
+ if (gyroDev != null)
+ {
+ TouchPadOn(mappedIdx, gyroDev);
+ }
+ }
+ }
+
CheckProfileOptions(Index, device);
}
@@ -1386,7 +1598,7 @@ namespace DS4Windows
this.On_Report(sender, e, tempIdx);
};
- if (_udpServer != null && Index < UdpServer.NUMBER_SLOTS)
+ if (_udpServer != null && Index < UdpServer.NUMBER_SLOTS && device.PrimaryDevice)
{
DS4Device.ReportHandler<EventArgs> tempEvnt = (sender, args) =>
{
@@ -1766,6 +1978,15 @@ namespace DS4Windows
{
UnplugOutDev(ind, device);
}
+ else if (!device.PrimaryDevice)
+ {
+ OutputDevice outDev = outputDevices[ind];
+ if (outDev != null)
+ {
+ outDev.RemoveFeedback(ind);
+ outputDevices[ind] = null;
+ }
+ }
// Use Task to reset device synth state and commit it
Task.Run(() =>
@@ -1873,8 +2094,18 @@ namespace DS4Windows
}
}
- device.getCurrentState(CurrentState[ind]);
- DS4State cState = CurrentState[ind];
+ DS4State cState;
+ if (!device.PerformStateMerge)
+ {
+ cState = CurrentState[ind];
+ device.getRawCurrentState(cState);
+ }
+ else
+ {
+ cState = device.JointState;
+ device.MergeStateData(cState);
+ }
+
DS4State pState = device.getPreviousStateRef();
//device.getPreviousState(PreviousState[ind]);
//DS4State pState = PreviousState[ind];
@@ -1912,6 +2143,12 @@ namespace DS4Windows
// */
//}
+ if (!device.PrimaryDevice)
+ {
+ // Skip mapping routine if part of a joined device
+ return;
+ }
+
if (getEnableTouchToggle(ind))
CheckForTouchToggle(ind, cState, pState);
@@ -1983,6 +2220,11 @@ namespace DS4Windows
// Update the GUI/whatever.
DS4LightBar.updateLightBar(device, ind);
+
+ if (device.PerformStateMerge)
+ {
+ device.PreserveMergedStateData();
+ }
}
}
diff --git a/DS4Windows/DS4Control/DS4OutDevice.cs b/DS4Windows/DS4Control/DS4OutDevice.cs
index 8dab686a..9b1248a1 100644
--- a/DS4Windows/DS4Control/DS4OutDevice.cs
+++ b/DS4Windows/DS4Control/DS4OutDevice.cs
@@ -42,5 +42,18 @@ namespace DS4Windows
cont = null;
}
public override string GetDeviceType() => devtype;
+
+ public override void RemoveFeedbacks()
+ {
+ if (forceFeedbackCall != null)
+ {
+ cont.FeedbackReceived -= forceFeedbackCall;
+ forceFeedbackCall = null;
+ }
+ }
+
+ public override void RemoveFeedback(int inIdx)
+ {
+ }
}
}
diff --git a/DS4Windows/DS4Control/OutputDevice.cs b/DS4Windows/DS4Control/OutputDevice.cs
index ada31e46..154f650e 100644
--- a/DS4Windows/DS4Control/OutputDevice.cs
+++ b/DS4Windows/DS4Control/OutputDevice.cs
@@ -11,5 +11,9 @@ namespace DS4Windows
public abstract void Disconnect();
public abstract void ResetState(bool submit=true);
public abstract string GetDeviceType();
+
+ public abstract void RemoveFeedbacks();
+
+ public abstract void RemoveFeedback(int inIdx);
}
}
diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs
index 97380f13..c90404f6 100644
--- a/DS4Windows/DS4Control/ScpUtil.cs
+++ b/DS4Windows/DS4Control/ScpUtil.cs
@@ -5081,10 +5081,14 @@ namespace DS4Windows
// Only change xinput devices under certain conditions. Avoid
// performing this upon program startup before loading devices.
- if (xinputChange)
+ if (xinputChange && device < ControlService.CURRENT_DS4_CONTROLLER_LIMIT)
{
- CheckOldDevicestatus(device, control, oldContType,
- out xinputPlug, out xinputStatus);
+ DS4Device tempDev = control.DS4Controllers[device];
+ if (tempDev != null)
+ {
+ CheckOldDevicestatus(device, control, oldContType,
+ out xinputPlug, out xinputStatus);
+ }
}
try
@@ -7062,25 +7066,27 @@ namespace DS4Windows
{
tempDev.setIdleTimeout(idleDisconnectTimeout[device]);
tempDev.setBTPollRate(btPollRate[device]);
- if (xinputStatus && xinputPlug)
+ if (xinputStatus && tempDev.PrimaryDevice)
{
- OutputDevice tempOutDev = control.outputDevices[device];
- if (tempOutDev != null)
+ if (xinputPlug)
+ {
+ OutputDevice tempOutDev = control.outputDevices[device];
+ if (tempOutDev != null)
+ {
+ tempOutDev = null;
+ //Global.activeOutDevType[device] = OutContType.None;
+ control.UnplugOutDev(device, tempDev);
+ }
+
+ OutContType tempContType = outputDevType[device];
+ control.PluginOutDev(device, tempDev);
+ //Global.useDInputOnly[device] = false;
+ }
+ else
{
- tempOutDev = null;
//Global.activeOutDevType[device] = OutContType.None;
control.UnplugOutDev(device, tempDev);
}
-
- OutContType tempContType = outputDevType[device];
- control.PluginOutDev(device, tempDev);
- //Global.useDInputOnly[device] = false;
-
- }
- else if (xinputStatus && !xinputPlug)
- {
- //Global.activeOutDevType[device] = OutContType.None;
- control.UnplugOutDev(device, tempDev);
}
tempDev.RumbleAutostopTime = rumbleAutostopTime[device];
diff --git a/DS4Windows/DS4Control/Xbox360OutDevice.cs b/DS4Windows/DS4Control/Xbox360OutDevice.cs
index 6c4df1fc..6f736e78 100644
--- a/DS4Windows/DS4Control/Xbox360OutDevice.cs
+++ b/DS4Windows/DS4Control/Xbox360OutDevice.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
using Nefarius.ViGEm.Client;
using Nefarius.ViGEm.Client.Targets;
@@ -19,7 +20,10 @@ namespace DS4Windows
public const string devType = "X360";
public IXbox360Controller cont;
- public Xbox360FeedbackReceivedEventHandler forceFeedbackCall;
+ // Input index, Xbox360FeedbackReceivedEventHandler instance
+ public Dictionary<int, Xbox360FeedbackReceivedEventHandler> forceFeedbackCall =
+ new Dictionary<int, Xbox360FeedbackReceivedEventHandler>();
+ private ReaderWriterLockSlim lockSlim = new ReaderWriterLockSlim();
public Xbox360OutDevice(ViGEmClient client)
{
@@ -32,6 +36,7 @@ namespace DS4Windows
if (!connected) return;
//cont.ResetReport();
+
ushort tempButtons = 0;
unchecked
@@ -125,6 +130,7 @@ namespace DS4Windows
}
cont.SubmitReport();
+
}
private short AxisScale(Int32 Value, Boolean Flip)
@@ -152,8 +158,13 @@ namespace DS4Windows
{
if (forceFeedbackCall != null)
{
- cont.FeedbackReceived -= forceFeedbackCall;
- forceFeedbackCall = null;
+ foreach(KeyValuePair<int, Xbox360FeedbackReceivedEventHandler> pair in forceFeedbackCall)
+ {
+ cont.FeedbackReceived -= pair.Value;
+ }
+
+ //forceFeedbackCall = null;
+ forceFeedbackCall.Clear();
}
connected = false;
@@ -170,5 +181,25 @@ namespace DS4Windows
cont.SubmitReport();
}
}
+
+ public override void RemoveFeedbacks()
+ {
+ foreach (KeyValuePair<int, Xbox360FeedbackReceivedEventHandler> pair in forceFeedbackCall)
+ {
+ cont.FeedbackReceived -= pair.Value;
+ }
+
+ //forceFeedbackCall = null;
+ forceFeedbackCall.Clear();
+ }
+
+ public override void RemoveFeedback(int inIdx)
+ {
+ if (forceFeedbackCall.TryGetValue(inIdx, out Xbox360FeedbackReceivedEventHandler handler))
+ {
+ cont.FeedbackReceived -= handler;
+ forceFeedbackCall.Remove(inIdx);
+ }
+ }
}
}
diff --git a/DS4Windows/DS4Forms/MainWindow.xaml b/DS4Windows/DS4Forms/MainWindow.xaml
index 5c09b3e0..0064b2de 100644
--- a/DS4Windows/DS4Forms/MainWindow.xaml
+++ b/DS4Windows/DS4Forms/MainWindow.xaml
@@ -95,11 +95,11 @@
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
- <GridViewColumn x:Name="LinkProfColumn" Header="Link Profile/ID" Width="100" >
+ <GridViewColumn x:Name="LinkProfColumn" Header="Link Profile/ID" Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Width="{Binding ElementName=LinkProfColumn, Path=Width}">
- <CheckBox IsChecked="{Binding LinkedProfile}" HorizontalAlignment="Center" />
+ <CheckBox IsChecked="{Binding LinkedProfile}" HorizontalAlignment="Center" IsEnabled="{Binding PrimaryDevice}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
@@ -109,7 +109,7 @@
<DataTemplate>
<StackPanel Width="{Binding Path=Width, ElementName=selectProfileColumn, Mode=OneWay}" HorizontalAlignment="Center">
<ComboBox x:Name="selectProfCombo" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay}"
- ItemsSource="{Binding ProfileListCol}" SelectedIndex="{Binding SelectedIndex}" Height="Auto" Tag="{Binding DevIndex, Mode=OneTime}" Margin="0"
+ ItemsSource="{Binding ProfileListCol}" SelectedIndex="{Binding SelectedIndex}" IsEnabled="{Binding PrimaryDevice}" Height="Auto" Tag="{Binding DevIndex, Mode=OneTime}" Margin="0"
SelectionChanged="SelectProfCombo_SelectionChanged" KeyDown="SelectProfCombo_KeyDown">
<ComboBox.ItemTemplate>
<DataTemplate>
@@ -125,7 +125,7 @@
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Width="{Binding ElementName=editColumn, Path=Width}">
- <xctk:SplitButton x:Name="ProfEditSBtn" Content="{lex:Loc Edit}" Height="20" MinWidth="60"
+ <xctk:SplitButton x:Name="ProfEditSBtn" Content="{lex:Loc Edit}" Height="20" MinWidth="60" IsEnabled="{Binding PrimaryDevice}"
Tag="{Binding DevIndex, Mode=OneTime}" Click="ProfEditSBtn_Click" HorizontalAlignment="Center">
<xctk:SplitButton.DropDownContent>
<Button x:Name="newProfBtn" Content="{lex:Loc NewProfile}" MinWidth="120" Tag="{Binding DevIndex, Mode=OneTime}" Click="NewProfBtn_Click" />
diff --git a/DS4Windows/DS4Forms/MainWindow.xaml.cs b/DS4Windows/DS4Forms/MainWindow.xaml.cs
index a5a1ed26..d1f9e7fd 100644
--- a/DS4Windows/DS4Forms/MainWindow.xaml.cs
+++ b/DS4Windows/DS4Forms/MainWindow.xaml.cs
@@ -903,6 +903,7 @@ Suspend support not enabled.", true);
{
Image img = sender as Image;
int tag = Convert.ToInt32(img.Tag);
+ conLvViewModel.CurrentIndex = tag;
CompositeDeviceModel item = conLvViewModel.CurrentItem;
//CompositeDeviceModel item = conLvViewModel.ControllerDict[tag];
if (item != null)
diff --git a/DS4Windows/DS4Forms/ViewModels/ControllerListViewModel.cs b/DS4Windows/DS4Forms/ViewModels/ControllerListViewModel.cs
index c8e4163f..42807ed5 100644
--- a/DS4Windows/DS4Forms/ViewModels/ControllerListViewModel.cs
+++ b/DS4Windows/DS4Forms/ViewModels/ControllerListViewModel.cs
@@ -339,6 +339,11 @@ namespace DS4WinWPF.DS4Forms.ViewModels
}
}
+ public bool PrimaryDevice
+ {
+ get => device.PrimaryDevice;
+ }
+
public delegate void CustomColorHandler(CompositeDeviceModel sender);
public event CustomColorHandler RequestColorPicker;
diff --git a/DS4Windows/DS4Library/DS4Device.cs b/DS4Windows/DS4Library/DS4Device.cs
index 484e7312..a00eaac2 100644
--- a/DS4Windows/DS4Library/DS4Device.cs
+++ b/DS4Windows/DS4Library/DS4Device.cs
@@ -578,6 +578,49 @@ namespace DS4Windows
protected event EventHandler DeviceSlotNumberChanged;
protected byte deviceSlotMask = 0x00;
+ protected DS4State jointState = new DS4State();
+ protected DS4State jointPreviousState = new DS4State();
+ public DS4State JointState
+ {
+ get => jointState;
+ set => jointState = value;
+ }
+
+ public DS4State JointPreviousState
+ {
+ get => jointPreviousState;
+ set => jointPreviousState = value;
+ }
+
+ protected bool performStateMerge;
+ public bool PerformStateMerge
+ {
+ get => performStateMerge;
+ set => performStateMerge = value;
+ }
+
+ protected bool primaryDevice = true;
+ public bool PrimaryDevice
+ {
+ get => primaryDevice;
+ set => primaryDevice = value;
+ }
+
+ public const int DEFAULT_JOINT_SLOT_NUMBER = -1;
+ protected int jointDeviceSlotNumber = DEFAULT_JOINT_SLOT_NUMBER;
+ public virtual int JointDeviceSlotNumber
+ {
+ get => jointDeviceSlotNumber;
+ set => jointDeviceSlotNumber = value;
+ }
+
+ protected bool outputMapGyro = true;
+ public bool OutputMapGyro
+ {
+ get => outputMapGyro;
+ set => outputMapGyro = value;
+ }
+
public DS4Device(HidDevice hidDevice, string disName, VidPidFeatureSet featureSet = VidPidFeatureSet.DefaultDS4)
{
hDevice = hidDevice;
@@ -1904,26 +1947,40 @@ namespace DS4Windows
return pState.Clone();
}
- public void getCurrentState(DS4State state)
+ public void getRawCurrentState(DS4State state)
{
cState.CopyTo(state);
}
- public void getPreviousState(DS4State state)
+ public void getRawPreviousState(DS4State state)
{
pState.CopyTo(state);
}
- public DS4State getCurrentStateRef()
+ public virtual DS4State getCurrentStateRef()
+ {
+ return cState;
+ }
+
+ public virtual DS4State getPreviousStateRef()
+ {
+ return pState;
+ }
+
+ public DS4State GetRawCurrentStateRef()
{
return cState;
}
- public DS4State getPreviousStateRef()
+ public DS4State GetRawPreviousStateRef()
{
return pState;
}
+ public virtual void PreserveMergedStateData()
+ {
+ }
+
public bool isDS4Idle()
{
if (cState.Square || cState.Cross || cState.Circle || cState.Triangle)
@@ -2055,5 +2112,9 @@ namespace DS4Windows
PrepareOutputFeaturesByte();
}
}
+
+ public virtual void MergeStateData(DS4State dState)
+ {
+ }
}
}
diff --git a/DS4Windows/DS4Library/InputDevices/JoyConDevice.cs b/DS4Windows/DS4Library/InputDevices/JoyConDevice.cs
index 92325d77..ef5bfd56 100644
--- a/DS4Windows/DS4Library/InputDevices/JoyConDevice.cs
+++ b/DS4Windows/DS4Library/InputDevices/JoyConDevice.cs
@@ -215,6 +215,37 @@ namespace DS4Windows.InputDevices
private JoyConControllerOptions nativeOptionsStore;
+ private ReaderWriterLockSlim lockSlim = new ReaderWriterLockSlim();
+ private JoyConDevice jointDevice;
+ public JoyConDevice JointDevice
+ {
+ get => jointDevice;
+ set
+ {
+ jointDevice = value;
+ if (jointDevice == null)
+ {
+ }
+ else
+ {
+ }
+ }
+ }
+
+ public override int JointDeviceSlotNumber
+ {
+ get
+ {
+ int result = -1;
+ if (jointDevice != null)
+ {
+ result = jointDevice.deviceSlotNumber;
+ }
+
+ return result;
+ }
+ }
+
public override event ReportHandler<EventArgs> Report = null;
public override event EventHandler<EventArgs> Removal = null;
public override event EventHandler BatteryChanged;
@@ -1288,5 +1319,94 @@ namespace DS4Windows.InputDevices
enableHomeLED = nativeOptionsStore.EnableHomeLED;
}
}
+
+ public override DS4State getCurrentStateRef()
+ {
+ DS4State tempState = null;
+ if (!performStateMerge)
+ {
+ tempState = cState;
+ }
+ else
+ {
+ tempState = jointState;
+ }
+
+ return tempState;
+ }
+
+ public override DS4State getPreviousStateRef()
+ {
+ DS4State tempState = null;
+ if (!performStateMerge)
+ {
+ tempState = pState;
+ }
+ else
+ {
+ tempState = jointPreviousState;
+ }
+
+ return tempState;
+ }
+
+ public override void PreserveMergedStateData()
+ {
+ jointState.CopyTo(jointPreviousState);
+ }
+
+ public override void MergeStateData(DS4State dState)
+ {
+ using (WriteLocker locker = new WriteLocker(lockSlim))
+ {
+ if (DeviceType == InputDeviceType.JoyConL)
+ {
+ dState.LX = cState.LX;
+ dState.LY = cState.LY;
+ dState.L1 = cState.L1;
+ dState.L2 = cState.L2;
+ dState.L3 = cState.L3;
+ dState.L2Btn = cState.L2Btn;
+ dState.DpadUp = cState.DpadUp;
+ dState.DpadDown = cState.DpadDown;
+ dState.DpadLeft = cState.DpadLeft;
+ dState.DpadRight = cState.DpadRight;
+ dState.Share = cState.Share;
+ if (primaryDevice)
+ {
+ dState.elapsedTime = cState.elapsedTime;
+ dState.totalMicroSec = cState.totalMicroSec;
+ dState.ReportTimeStamp = cState.ReportTimeStamp;
+ }
+
+ if (outputMapGyro) dState.Motion = cState.Motion;
+ //dState.Motion = cState.Motion;
+ }
+ else if (DeviceType == InputDeviceType.JoyConR)
+ {
+ dState.RX = cState.RX;
+ dState.RY = cState.RY;
+ dState.R1 = cState.R1;
+ dState.R2 = cState.R2;
+ dState.R3 = cState.R3;
+ dState.R2Btn = cState.R2Btn;
+ dState.Cross = cState.Cross;
+ dState.Circle = cState.Circle;
+ dState.Triangle = cState.Triangle;
+ dState.Square = cState.Square;
+ dState.PS = cState.PS;
+ dState.Options = cState.Options;
+ if (primaryDevice)
+ {
+ dState.elapsedTime = cState.elapsedTime;
+ dState.totalMicroSec = cState.totalMicroSec;
+ dState.ReportTimeStamp = cState.ReportTimeStamp;
+ }
+
+ if (outputMapGyro) dState.Motion = cState.Motion;
+ //dState.Motion = cState.Motion;
+ }
+ }
+ }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment