Skip to content
Open
6 changes: 6 additions & 0 deletions DS4Windows/DS4Control/ControlService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,9 @@ public bool CheckForSupportedDevice(HidDevice device, VidPidInfo metaInfo)
case InputDevices.InputDeviceType.DS3:
result = deviceOptions.DS3DeviceOpts.Enabled;
break;
case InputDevices.InputDeviceType.Vader4Pro:
result = deviceOptions.Vader4ProDeviceOpts.Enabled;
break;
default:
break;
}
Expand Down Expand Up @@ -802,6 +805,9 @@ private List<DS4Controls> GetKnownExtraButtons(DS4Device dev)
case InputDevices.InputDeviceType.SwitchPro:
result.AddRange(new DS4Controls[] { DS4Controls.Capture });
break;
case InputDevices.InputDeviceType.Vader4Pro:
result.AddRange(new DS4Controls[] { DS4Controls.FnL, DS4Controls.FnR, DS4Controls.BLP, DS4Controls.BRP, DS4Controls.SideL, DS4Controls.SideR, DS4Controls.Capture });
break;
default:
break;
}
Expand Down
103 changes: 103 additions & 0 deletions DS4Windows/DS4Control/ControlServiceDeviceOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ public class ControlServiceDeviceOptions
private DS3DeviceOptions dS3DeviceOpts = new DS3DeviceOptions();
public DS3DeviceOptions DS3DeviceOpts { get => dS3DeviceOpts; }

private Vader4ProDeviceOptions vader4proDeviceOpts = new Vader4ProDeviceOptions();
public Vader4ProDeviceOptions Vader4ProDeviceOpts { get => vader4proDeviceOpts; }

private bool verboseLogMessages;
public bool VerboseLogMessages { get => verboseLogMessages; set => verboseLogMessages = value; }

Expand Down Expand Up @@ -557,4 +560,104 @@ public override void LoadSettings(XmlDocument xmlDoc, XmlNode node)
}
}
}

public class Vader4ProDeviceOptions
{
public const bool DEFAULT_ENABLE = true;
private bool enabled = DEFAULT_ENABLE;
public bool Enabled
{
get => enabled;
set
{
if (enabled == value) return;
enabled = value;
EnabledChanged?.Invoke(this, EventArgs.Empty);
}
}
public event EventHandler EnabledChanged;
}

public class Vader4ProControllerOptions : ControllerOptionsStore
{
public const string XML_ELEMENT_NAME = "Vader4ProSupportSettings";

private bool enableHomeLED = true;
public bool EnableHomeLED
{
get => enableHomeLED;
set
{
if (enableHomeLED == value) return;
enableHomeLED = value;
EnableHomeLEDChanged?.Invoke(this, EventArgs.Empty);
}
}
public event EventHandler EnableHomeLEDChanged;

public Vader4ProControllerOptions(InputDeviceType deviceType) : base(deviceType)
{
}

public override void PersistSettings(XmlDocument xmlDoc, XmlNode node)
{
string testStr = string.Empty;
XmlSerializer serializer = new XmlSerializer(typeof(Vader4ProControllerOptsDTO));

using (Utf8StringWriter strWriter = new Utf8StringWriter())
{
using XmlWriter xmlWriter = XmlWriter.Create(strWriter,
new XmlWriterSettings()
{
Encoding = Encoding.UTF8,
Indent = false,
OmitXmlDeclaration = true, // only partial XML with no declaration
});

// Write root element and children
Vader4ProControllerOptsDTO dto = new Vader4ProControllerOptsDTO();
dto.MapFrom(this);
// Omit xmlns:xsi and xmlns:xsd from output
serializer.Serialize(xmlWriter, dto,
new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
xmlWriter.Flush();
xmlWriter.Close();

testStr = strWriter.ToString();
//Trace.WriteLine("TEST OUTPUT");
//Trace.WriteLine(testStr);
}

XmlNode tempSwitchProNode = xmlDoc.CreateDocumentFragment();
tempSwitchProNode.InnerXml = testStr;

XmlNode tempOptsNode = node.SelectSingleNode(XML_ELEMENT_NAME);
if (tempOptsNode != null)
{
node.RemoveChild(tempOptsNode);
}

tempOptsNode = tempSwitchProNode;
node.AppendChild(tempOptsNode);
}

public override void LoadSettings(XmlDocument xmlDoc, XmlNode node)
{
XmlSerializer serializer = new XmlSerializer(typeof(Vader4ProControllerOptsDTO));
XmlNode baseNode = node.SelectSingleNode(XML_ELEMENT_NAME);
if (baseNode == null)
return;

try
{
using var stringReader = new StringReader(baseNode.OuterXml);
using var xmlReader = XmlReader.Create(stringReader);
Vader4ProControllerOptsDTO dto = serializer.Deserialize(xmlReader) as Vader4ProControllerOptsDTO;
dto.MapTo(this);
}
catch (InvalidOperationException)
{
}
}
}
}
58 changes: 58 additions & 0 deletions DS4Windows/DS4Control/DTOXml/Vader4ProControllerOptsDTO.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
DS4Windows
Copyright (C) 2023 Travis Nickles

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using DS4Windows;

namespace DS4WinWPF.DS4Control.DTOXml
{
[XmlRoot(Vader4ProControllerOptions.XML_ELEMENT_NAME)]
public class Vader4ProControllerOptsDTO : IDTO<Vader4ProControllerOptions>
{
[XmlElement("EnableHomeLED")]
public string EnableHomeLEDString
{
get => EnableHomeLED.ToString();
set
{
EnableHomeLED = XmlDataUtilities.StrToBool(value);
}
}

[XmlIgnore]
public bool EnableHomeLED
{
get; set;
}

public void MapFrom(Vader4ProControllerOptions source)
{
EnableHomeLED = source.EnableHomeLED;
}

public void MapTo(Vader4ProControllerOptions destination)
{
destination.EnableHomeLED = EnableHomeLED;
}
}
}
1 change: 1 addition & 0 deletions DS4Windows/DS4Forms/ControllerRegisterOptionsWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<CheckBox Content="{lex:Loc ControllerSupportSwitchPro}" IsChecked="{Binding SwitchProDeviceOpts.Enabled}" />
<CheckBox Content="{lex:Loc ControllerSupportJoyCon}" IsChecked="{Binding JoyConDeviceOpts.Enabled}" />
<CheckBox Content="{lex:Loc ControllerSupportDS3}" IsChecked="{Binding DS3DeviceOpts.Enabled}" />
<CheckBox Content="{lex:Loc ControllerSupportVader4Pro}" IsChecked="{Binding Vader4ProDeviceOpts.Enabled}" />
<CheckBox Content="{lex:Loc ControllerSupportMoonlight}" IsChecked="{Binding UseMoonlight}" />
<CheckBox Content="{lex:Loc AdvancedSupport}" IsChecked="{Binding UseAdvancedMoonlight}"
Visibility="{Binding Path=UseMoonlight, Converter={StaticResource BooleanToVisibilityConverter}}" Margin="20 0 0 0"/>
Expand Down
16 changes: 10 additions & 6 deletions DS4Windows/DS4Forms/ProfileEditor.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,15 @@
</StackPanel>
<TabControl x:Name="sidebarTabControl" Width="480" DockPanel.Dock="Left" SelectionChanged="SidebarTabControl_SelectionChanged">
<TabItem Header="{lex:Loc Controls}">
<DockPanel Width="470" LastChildFill="False">
<DockPanel.Background>
<Grid Width="470">
<Grid.Background>
<SolidColorBrush Color="DimGray"/>
</DockPanel.Background>
<Canvas x:Name="conCanvas" Width="440" Height="240" Margin="0,10,0,0" DockPanel.Dock="Top" >
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="240" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Canvas Grid.Row="0" x:Name="conCanvas" Width="440" Margin="0,10,0,0" DockPanel.Dock="Top" >
<Canvas.Resources>
<ContextMenu x:Key="presetMenu">
<MenuItem x:Name="controlNameItem" Header="Name" IsEnabled="False" />
Expand Down Expand Up @@ -193,7 +197,7 @@
</Label>
</Canvas>

<ListBox x:Name="mappingListBox" DockPanel.Dock="Bottom" Height="200" ItemsSource="{Binding Mappings}"
<ListBox Grid.Row="1" x:Name="mappingListBox" DockPanel.Dock="Bottom" ItemsSource="{Binding Mappings}"
SelectedIndex="{Binding SelectedIndex}" Margin="6" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
MouseDoubleClick="MappingListBox_MouseDoubleClick">
<ListBox.ItemTemplate>
Expand All @@ -205,7 +209,7 @@
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</Grid>
</TabItem>
<TabItem x:Name="specialActionsTab" Header="Special Actions">
<DockPanel x:Name="specialActionDockPanel">
Expand Down
28 changes: 28 additions & 0 deletions DS4Windows/DS4Forms/ViewModels/ControllerRegDeviceOptsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@ public class ControllerRegDeviceOptsViewModel
public bool EnableJoyCon { get => serviceDeviceOpts.JoyConDeviceOpts.Enabled; }

public bool EnableDS3 { get => serviceDeviceOpts.DS3DeviceOpts.Enabled; }
public bool EnableVader4Pro { get => serviceDeviceOpts.Vader4ProDeviceOpts.Enabled; }

public DS4DeviceOptions DS4DeviceOpts { get => serviceDeviceOpts.DS4DeviceOpts; }
public DS3DeviceOptions DS3DeviceOpts { get => serviceDeviceOpts.DS3DeviceOpts; }
public DualSenseDeviceOptions DSDeviceOpts { get => serviceDeviceOpts.DualSenseOpts; }
public SwitchProDeviceOptions SwitchProDeviceOpts { get => serviceDeviceOpts.SwitchProDeviceOpts; }
public JoyConDeviceOptions JoyConDeviceOpts { get => serviceDeviceOpts.JoyConDeviceOpts; }
public Vader4ProDeviceOptions Vader4ProDeviceOpts { get => serviceDeviceOpts.Vader4ProDeviceOpts; }

public bool UseMoonlightChanged
{
Expand Down Expand Up @@ -118,6 +120,10 @@ public JoyConControllerOptions CurrentJoyConOptions
get => controllerOptionsStores[controllerSelectedIndex] as JoyConControllerOptions;
}

public Vader4ProControllerOptions CurrentVader4ProOptions {
get => controllerOptionsStores[controllerSelectedIndex] as Vader4ProControllerOptions;
}

private int currentTabSelectedIndex = 0;
public int CurrentTabSelectedIndex
{
Expand Down Expand Up @@ -176,6 +182,9 @@ public int FindTabOptionsIndex()
case DS4Windows.InputDevices.InputDeviceType.JoyConR:
result = 4;
break;
case DS4Windows.InputDevices.InputDeviceType.Vader4Pro:
result = 5;
break;
default:
// Default to empty control
result = 0;
Expand Down Expand Up @@ -208,6 +217,9 @@ public void FindFittingDataContext()
case DS4Windows.InputDevices.InputDeviceType.JoyConR:
dataContextObject = new JoyConControllerOptionsWrapper(CurrentJoyConOptions, serviceDeviceOpts.JoyConDeviceOpts);
break;
case DS4Windows.InputDevices.InputDeviceType.Vader4Pro:
dataContextObject = new Vader4ProControllerOptionsWrapper(CurrentVader4ProOptions, serviceDeviceOpts.Vader4ProDeviceOpts);
break;
default:
break;
}
Expand Down Expand Up @@ -312,6 +324,22 @@ public SwitchProControllerOptionsWrapper(SwitchProControllerOptions options,
}
}

public class Vader4ProControllerOptionsWrapper {
private Vader4ProControllerOptions options;
public Vader4ProControllerOptions Options { get => options; }

private Vader4ProDeviceOptions parentOptions;
public bool Visible { get => parentOptions.Enabled; }
public event EventHandler VisibleChanged;

public Vader4ProControllerOptionsWrapper(Vader4ProControllerOptions options,
Vader4ProDeviceOptions parentOpts) {
this.options = options;
this.parentOptions = parentOpts;
parentOptions.EnabledChanged += (sender, e) => { VisibleChanged?.Invoke(this, EventArgs.Empty); };
}
}

public class JoyConControllerOptionsWrapper
{
private JoyConControllerOptions options;
Expand Down
Loading