mirror of
https://github.com/ayufan/steam-deck-tools.git
synced 2026-03-17 10:14:46 +01:00
Add Haptic feedback and selectable profiles
This commit is contained in:
parent
d0b6fb93b0
commit
bad617549e
42
CommonHelpers/Extensions.cs
Normal file
42
CommonHelpers/Extensions.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using RTSSSharedMemoryNET;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CommonHelpers
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static String JoinWith0(this IEnumerable<String> list)
|
||||
{
|
||||
return String.Join('\0', list);
|
||||
}
|
||||
|
||||
public static String JoinWith0<TSource>(this IEnumerable<TSource> list, Func<TSource, String> selector)
|
||||
{
|
||||
return list.Select(selector).JoinWith0();
|
||||
}
|
||||
|
||||
public static String[] SplitWith0(this String str)
|
||||
{
|
||||
return str.Split('\0', StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
public static String JoinWithN(this IEnumerable<String> list)
|
||||
{
|
||||
return String.Join('\n', list);
|
||||
}
|
||||
|
||||
public static String JoinWithN<TSource>(this IEnumerable<TSource> list, Func<TSource, String> selector)
|
||||
{
|
||||
return list.Select(selector).JoinWithN();
|
||||
}
|
||||
|
||||
public static String[] SplitWithN(this String str)
|
||||
{
|
||||
return str.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -53,4 +53,17 @@ namespace CommonHelpers
|
|||
{
|
||||
public PowerControlVisible Current;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct SteamControllerSetting
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public String CurrentProfile;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2048)]
|
||||
public String SelectableProfiles;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public String DesiredProfile;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,14 +9,18 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace CommonHelpers
|
||||
{
|
||||
public class SharedData<T> : IDisposable where T : unmanaged
|
||||
public class SharedData<T> : IDisposable where T : struct
|
||||
{
|
||||
const int MMF_MAX_SIZE = 256;
|
||||
const int MMF_MAX_SIZE = 16384;
|
||||
const int MMF_ALIGN_SIZE = 256;
|
||||
|
||||
private MemoryMappedFile mmf;
|
||||
private int size;
|
||||
|
||||
private SharedData()
|
||||
{ }
|
||||
private SharedData(int size)
|
||||
{
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public T NewValue()
|
||||
{
|
||||
|
|
@ -32,7 +36,7 @@ namespace CommonHelpers
|
|||
if (!mmvStream.CanRead)
|
||||
return false;
|
||||
|
||||
byte[] buffer = new byte[MMF_MAX_SIZE];
|
||||
byte[] buffer = new byte[size];
|
||||
mmvStream.Read(buffer, 0, buffer.Length);
|
||||
|
||||
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
||||
|
|
@ -63,7 +67,7 @@ namespace CommonHelpers
|
|||
if (!mmvStream.CanWrite)
|
||||
return false;
|
||||
|
||||
byte[] buffer = new byte[MMF_MAX_SIZE];
|
||||
byte[] buffer = new byte[size];
|
||||
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
||||
try
|
||||
{
|
||||
|
|
@ -126,17 +130,30 @@ namespace CommonHelpers
|
|||
return String.Format("Global_{0}_Setting", typeof(T).Name);
|
||||
}
|
||||
|
||||
private static int AlignedSize()
|
||||
{
|
||||
int size = Marshal.SizeOf<T>();
|
||||
size = (size + MMF_ALIGN_SIZE - 1) / MMF_ALIGN_SIZE * MMF_ALIGN_SIZE;
|
||||
if (size > MMF_MAX_SIZE)
|
||||
throw new ArgumentException();
|
||||
return size;
|
||||
}
|
||||
|
||||
public static SharedData<T> CreateNew(String? name = null)
|
||||
{
|
||||
return new SharedData<T>()
|
||||
int size = AlignedSize();
|
||||
|
||||
return new SharedData<T>(size)
|
||||
{
|
||||
mmf = MemoryMappedFile.CreateOrOpen(name ?? GetUniqueName(), MMF_MAX_SIZE)
|
||||
mmf = MemoryMappedFile.CreateOrOpen(name ?? GetUniqueName(), size)
|
||||
};
|
||||
}
|
||||
|
||||
public static SharedData<T> OpenExisting(String? name = null)
|
||||
{
|
||||
return new SharedData<T>()
|
||||
int size = AlignedSize();
|
||||
|
||||
return new SharedData<T>(size)
|
||||
{
|
||||
mmf = MemoryMappedFile.OpenExisting(name ?? GetUniqueName())
|
||||
};
|
||||
|
|
|
|||
|
|
@ -455,6 +455,32 @@ namespace PowerControl
|
|||
return null;
|
||||
return selected;
|
||||
}
|
||||
},
|
||||
new Menu.MenuItemWithOptions()
|
||||
{
|
||||
Name = "Controller",
|
||||
ApplyDelay = 500,
|
||||
OptionsValues = delegate()
|
||||
{
|
||||
if (SharedData<SteamControllerSetting>.GetExistingValue(out var value))
|
||||
return value.SelectableProfiles.SplitWithN();
|
||||
return null;
|
||||
},
|
||||
CurrentValue = delegate()
|
||||
{
|
||||
if (SharedData<SteamControllerSetting>.GetExistingValue(out var value))
|
||||
return value.CurrentProfile.Length > 0 ? value.CurrentProfile : null;
|
||||
return null;
|
||||
},
|
||||
ApplyValue = delegate(object selected)
|
||||
{
|
||||
if (!SharedData<SteamControllerSetting>.GetExistingValue(out var value))
|
||||
return null;
|
||||
value.DesiredProfile = (String)selected;
|
||||
if (!SharedData<SteamControllerSetting>.SetExistingValue(value))
|
||||
return null;
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -82,6 +82,19 @@ namespace SteamController
|
|||
}
|
||||
}
|
||||
|
||||
public Profiles.Profile? GetCurrentProfile()
|
||||
{
|
||||
foreach (var profile in OrderedProfiles)
|
||||
{
|
||||
if (profile.Selected(this))
|
||||
{
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool Update()
|
||||
{
|
||||
Steam.BeforeUpdate();
|
||||
|
|
@ -91,13 +104,10 @@ namespace SteamController
|
|||
|
||||
try
|
||||
{
|
||||
foreach (var profile in OrderedProfiles)
|
||||
var profile = GetCurrentProfile();
|
||||
if (profile is not null)
|
||||
{
|
||||
if (profile.Selected(this))
|
||||
{
|
||||
profile.Run(this);
|
||||
break;
|
||||
}
|
||||
profile.Run(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -130,6 +140,8 @@ namespace SteamController
|
|||
var list = OrderedProfiles;
|
||||
list.Remove(profile);
|
||||
list.Insert(0, profile);
|
||||
RequestDesktopMode = profile.IsDesktop;
|
||||
Beep();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -151,10 +163,16 @@ namespace SteamController
|
|||
|
||||
list.Remove(profile);
|
||||
list.Insert(0, profile);
|
||||
Beep();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Beep()
|
||||
{
|
||||
X360.Beep();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,11 @@ namespace SteamController
|
|||
Context context = new Context()
|
||||
{
|
||||
Profiles = {
|
||||
new Profiles.DesktopProfile(),
|
||||
new Profiles.SteamProfile(),
|
||||
new Profiles.X360Profile(),
|
||||
new Profiles.DesktopProfile() { Name = "Desktop" },
|
||||
new Profiles.SteamProfile() { Name = "Steam", Visible = false },
|
||||
new Profiles.SteamWithShorcutsProfile() { Name = "Steam with Shortcuts", Visible = false },
|
||||
new Profiles.X360Profile() { Name = "X360" },
|
||||
new Profiles.X360RumbleProfile() { Name = "X360 with Rumble" }
|
||||
},
|
||||
Managers = {
|
||||
new Managers.ProcessManager(),
|
||||
|
|
@ -37,6 +39,8 @@ namespace SteamController
|
|||
TimeSpan lastUpdatesReset;
|
||||
readonly TimeSpan updateResetInterval = TimeSpan.FromSeconds(1);
|
||||
|
||||
SharedData<SteamControllerSetting> sharedData = SharedData<SteamControllerSetting>.CreateNew();
|
||||
|
||||
public Controller()
|
||||
{
|
||||
Instance.RunOnce(TitleWithVersion, "Global\\SteamController");
|
||||
|
|
@ -48,12 +52,34 @@ namespace SteamController
|
|||
enabledItem.Click += delegate { context.RequestEnable = !context.RequestEnable; };
|
||||
contextMenu.Opening += delegate { enabledItem.Checked = context.RequestEnable; };
|
||||
contextMenu.Items.Add(enabledItem);
|
||||
contextMenu.Items.Add(new ToolStripSeparator());
|
||||
|
||||
var desktopModeItem = new ToolStripMenuItem("&Desktop Mode");
|
||||
desktopModeItem.Checked = context.RequestDesktopMode;
|
||||
desktopModeItem.Click += delegate { context.RequestDesktopMode = !context.RequestDesktopMode; };
|
||||
contextMenu.Opening += delegate { desktopModeItem.Checked = context.RequestDesktopMode; };
|
||||
contextMenu.Items.Add(desktopModeItem);
|
||||
foreach (var profile in context.Profiles)
|
||||
{
|
||||
if (profile.Name == "" || !profile.Visible)
|
||||
continue;
|
||||
|
||||
var profileItem = new ToolStripMenuItem(profile.Name);
|
||||
profileItem.Click += delegate { lock (context) { context.SelectProfile(profile.Name); } };
|
||||
contextMenu.Opening += delegate { profileItem.Checked = context.GetCurrentProfile() == profile; };
|
||||
contextMenu.Items.Add(profileItem);
|
||||
}
|
||||
|
||||
contextMenu.Items.Add(new ToolStripSeparator());
|
||||
|
||||
var lizardMouseItem = new ToolStripMenuItem("Use Lizard &Mouse");
|
||||
lizardMouseItem.Checked = DefaultGuideShortcutsProfile.SteamModeLizardMouse;
|
||||
lizardMouseItem.Click += delegate { DefaultGuideShortcutsProfile.SteamModeLizardMouse = !DefaultGuideShortcutsProfile.SteamModeLizardMouse; };
|
||||
contextMenu.Opening += delegate { lizardMouseItem.Checked = DefaultGuideShortcutsProfile.SteamModeLizardMouse; };
|
||||
contextMenu.Items.Add(lizardMouseItem);
|
||||
|
||||
var lizardButtonsItem = new ToolStripMenuItem("Use Lizard &Buttons");
|
||||
lizardButtonsItem.Checked = DefaultGuideShortcutsProfile.SteamModeLizardButtons;
|
||||
lizardButtonsItem.Click += delegate { DefaultGuideShortcutsProfile.SteamModeLizardButtons = !DefaultGuideShortcutsProfile.SteamModeLizardButtons; };
|
||||
contextMenu.Opening += delegate { lizardButtonsItem.Checked = DefaultGuideShortcutsProfile.SteamModeLizardButtons; };
|
||||
contextMenu.Items.Add(lizardButtonsItem);
|
||||
|
||||
contextMenu.Items.Add(new ToolStripSeparator());
|
||||
|
||||
var steamDetectionItem = new ToolStripMenuItem("Auto-disable on &Steam");
|
||||
steamDetectionItem.Checked = Settings.Default.EnableSteamDetection;
|
||||
|
|
@ -64,21 +90,6 @@ namespace SteamController
|
|||
};
|
||||
contextMenu.Opening += delegate { steamDetectionItem.Checked = Settings.Default.EnableSteamDetection; };
|
||||
contextMenu.Items.Add(steamDetectionItem);
|
||||
contextMenu.Items.Add(new ToolStripSeparator());
|
||||
|
||||
var lizardMouseItem = new ToolStripMenuItem("Use Lizard &Mouse");
|
||||
lizardMouseItem.Checked = SteamShortcutsProfile.SteamModeLizardMouse;
|
||||
lizardMouseItem.Click += delegate { SteamShortcutsProfile.SteamModeLizardMouse = !SteamShortcutsProfile.SteamModeLizardMouse; };
|
||||
contextMenu.Opening += delegate { lizardMouseItem.Checked = SteamShortcutsProfile.SteamModeLizardMouse; };
|
||||
contextMenu.Items.Add(lizardMouseItem);
|
||||
|
||||
var lizardButtonsItem = new ToolStripMenuItem("Use Lizard &Buttons");
|
||||
lizardButtonsItem.Checked = SteamShortcutsProfile.SteamModeLizardButtons;
|
||||
lizardButtonsItem.Click += delegate { SteamShortcutsProfile.SteamModeLizardButtons = !SteamShortcutsProfile.SteamModeLizardButtons; };
|
||||
contextMenu.Opening += delegate { lizardButtonsItem.Checked = SteamShortcutsProfile.SteamModeLizardButtons; };
|
||||
contextMenu.Items.Add(lizardButtonsItem);
|
||||
|
||||
contextMenu.Items.Add(new ToolStripSeparator());
|
||||
|
||||
if (startupManager.IsAvailable)
|
||||
{
|
||||
|
|
@ -139,6 +150,23 @@ namespace SteamController
|
|||
}
|
||||
}
|
||||
|
||||
private void SharedData_Update()
|
||||
{
|
||||
if (sharedData.GetValue(out var value) && value.DesiredProfile != "")
|
||||
{
|
||||
lock (context)
|
||||
{
|
||||
context.SelectProfile(value.DesiredProfile);
|
||||
}
|
||||
}
|
||||
|
||||
sharedData.SetValue(new SteamControllerSetting()
|
||||
{
|
||||
CurrentProfile = context.Profiles.FirstOrDefault((profile) => profile.Selected(context))?.Name,
|
||||
SelectableProfiles = context.Profiles.Where((profile) => profile.Selected(context) || profile.Visible).JoinWithN((profile) => profile.Name),
|
||||
});
|
||||
}
|
||||
|
||||
private void ContextStateUpdate_Tick(object? sender, EventArgs e)
|
||||
{
|
||||
lock (context)
|
||||
|
|
@ -146,6 +174,8 @@ namespace SteamController
|
|||
context.Tick();
|
||||
}
|
||||
|
||||
SharedData_Update();
|
||||
|
||||
if (!context.Mouse.Valid)
|
||||
{
|
||||
notifyIcon.Text = TitleWithVersion + ". Cannot send input.";
|
||||
|
|
@ -165,6 +195,10 @@ namespace SteamController
|
|||
{
|
||||
notifyIcon.Icon = context.DesktopMode ? Resources.monitor : Resources.microsoft_xbox_controller;
|
||||
notifyIcon.Text = TitleWithVersion;
|
||||
|
||||
var profile = context.GetCurrentProfile();
|
||||
if (profile is not null)
|
||||
notifyIcon.Text = TitleWithVersion + ". Profile: " + profile.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
38
SteamController/Devices/SteamControllerHaptic.cs
Normal file
38
SteamController/Devices/SteamControllerHaptic.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using CommonHelpers;
|
||||
using hidapi;
|
||||
using PowerControl.External;
|
||||
using static CommonHelpers.Log;
|
||||
|
||||
namespace SteamController.Devices
|
||||
{
|
||||
public partial class SteamController
|
||||
{
|
||||
public bool SetHaptic(byte position, ushort amplitude, ushort period, ushort count = 0)
|
||||
{
|
||||
var haptic = new SDCHapticPacket()
|
||||
{
|
||||
packet_type = (byte)SDCPacketType.PT_FEEDBACK,
|
||||
len = (byte)SDCPacketLength.PL_FEEDBACK,
|
||||
position = position,
|
||||
amplitude = amplitude,
|
||||
period = period,
|
||||
count = count
|
||||
};
|
||||
|
||||
var bytes = new byte[Marshal.SizeOf<SDCHapticPacket>()];
|
||||
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
||||
try
|
||||
{
|
||||
Marshal.StructureToPtr(haptic, handle.AddrOfPinnedObject(), false);
|
||||
neptuneDevice.RequestFeatureReport(bytes);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.TraceLine("STEAM: Haptic: Exception: {0}", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,8 @@ namespace SteamController.Devices
|
|||
{
|
||||
public class Xbox360Controller : IDisposable
|
||||
{
|
||||
public readonly TimeSpan FeedbackTimeout = TimeSpan.FromMilliseconds(1000);
|
||||
|
||||
private ViGEmClient? client;
|
||||
private IXbox360Controller? device;
|
||||
private bool isConnected;
|
||||
|
|
@ -49,8 +51,9 @@ namespace SteamController.Devices
|
|||
|
||||
if (!isConnected)
|
||||
{
|
||||
FeedbackLargeMotor = 0;
|
||||
FeedbackSmallMotor = 0;
|
||||
FeedbackLargeMotor = null;
|
||||
FeedbackSmallMotor = null;
|
||||
FeedbackReceived = null;
|
||||
LedNumber = 0;
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +80,32 @@ namespace SteamController.Devices
|
|||
isConnected = Connected;
|
||||
}
|
||||
|
||||
internal void Disconnect()
|
||||
{
|
||||
if (!isConnected)
|
||||
return;
|
||||
|
||||
device?.Disconnect();
|
||||
isConnected = false;
|
||||
}
|
||||
|
||||
internal void Beep()
|
||||
{
|
||||
// TODO: reconnect to beep
|
||||
if (isConnected)
|
||||
{
|
||||
device?.Disconnect();
|
||||
Thread.Sleep(100);
|
||||
device?.Connect();
|
||||
}
|
||||
else
|
||||
{
|
||||
device?.Connect();
|
||||
Thread.Sleep(100);
|
||||
device?.Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
internal void Update()
|
||||
{
|
||||
UpdateConnected();
|
||||
|
|
@ -85,6 +114,13 @@ namespace SteamController.Devices
|
|||
{
|
||||
device?.SubmitReport();
|
||||
}
|
||||
|
||||
if (FeedbackReceived is not null && FeedbackReceived.Value.Add(FeedbackTimeout) < DateTime.Now)
|
||||
{
|
||||
FeedbackLargeMotor = null;
|
||||
FeedbackSmallMotor = null;
|
||||
FeedbackReceived = null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Valid
|
||||
|
|
@ -93,9 +129,10 @@ namespace SteamController.Devices
|
|||
}
|
||||
|
||||
public bool Connected { get; set; }
|
||||
public byte FeedbackLargeMotor { get; internal set; }
|
||||
public byte FeedbackSmallMotor { get; internal set; }
|
||||
public byte? FeedbackLargeMotor { get; internal set; }
|
||||
public byte? FeedbackSmallMotor { get; internal set; }
|
||||
public byte LedNumber { get; internal set; }
|
||||
public DateTime? FeedbackReceived { get; set; }
|
||||
|
||||
public bool this[Xbox360Button button]
|
||||
{
|
||||
|
|
@ -150,11 +187,17 @@ namespace SteamController.Devices
|
|||
submitReport = true;
|
||||
}
|
||||
|
||||
public void ResetFeedback()
|
||||
{
|
||||
FeedbackReceived = null;
|
||||
}
|
||||
|
||||
private void X360Device_FeedbackReceived(object sender, Xbox360FeedbackReceivedEventArgs e)
|
||||
{
|
||||
FeedbackLargeMotor = e.LargeMotor;
|
||||
FeedbackSmallMotor = e.SmallMotor;
|
||||
LedNumber = e.LedNumber;
|
||||
FeedbackReceived = DateTime.Now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using WindowsInput;
|
|||
|
||||
namespace SteamController.Profiles
|
||||
{
|
||||
public abstract class SteamShortcutsProfile : DefaultShortcutsProfile
|
||||
public abstract class DefaultGuideShortcutsProfile : DefaultShortcutsProfile
|
||||
{
|
||||
public static bool SteamModeLizardButtons = false;
|
||||
public static bool SteamModeLizardMouse = true;
|
||||
|
|
@ -2,12 +2,13 @@ using WindowsInput;
|
|||
|
||||
namespace SteamController.Profiles
|
||||
{
|
||||
public sealed class DesktopProfile : SteamShortcutsProfile
|
||||
public sealed class DesktopProfile : DefaultGuideShortcutsProfile
|
||||
{
|
||||
private const String Consumed = "DesktopProfileOwner";
|
||||
|
||||
public DesktopProfile()
|
||||
{
|
||||
IsDesktop = true;
|
||||
}
|
||||
|
||||
public override bool Selected(Context context)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ namespace SteamController.Profiles
|
|||
}
|
||||
|
||||
public String Name { get; set; } = "";
|
||||
public bool Visible { get; set; } = true;
|
||||
public bool IsDesktop { get; set; }
|
||||
|
||||
public abstract bool Selected(Context context);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ namespace SteamController.Profiles
|
|||
{
|
||||
public sealed class SteamProfile : DefaultShortcutsProfile
|
||||
{
|
||||
public SteamProfile()
|
||||
{
|
||||
}
|
||||
|
||||
public override bool Selected(Context context)
|
||||
{
|
||||
return context.Enabled && context.SteamUsesController;
|
||||
|
|
|
|||
30
SteamController/Profiles/SteamWithShorcutsProfile.cs
Normal file
30
SteamController/Profiles/SteamWithShorcutsProfile.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
using Nefarius.ViGEm.Client.Targets.Xbox360;
|
||||
|
||||
namespace SteamController.Profiles
|
||||
{
|
||||
public sealed class SteamWithShorcutsProfile : DefaultGuideShortcutsProfile
|
||||
{
|
||||
public SteamWithShorcutsProfile()
|
||||
{
|
||||
}
|
||||
|
||||
public override bool Selected(Context context)
|
||||
{
|
||||
return context.Enabled && context.SteamUsesController;
|
||||
}
|
||||
|
||||
public override Status Run(Context context)
|
||||
{
|
||||
// Steam does not use Lizard
|
||||
context.Steam.LizardButtons = false;
|
||||
context.Steam.LizardMouse = false;
|
||||
|
||||
if (base.Run(context).IsDone)
|
||||
{
|
||||
return Status.Done;
|
||||
}
|
||||
|
||||
return Status.Continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ using Nefarius.ViGEm.Client.Targets.Xbox360;
|
|||
|
||||
namespace SteamController.Profiles
|
||||
{
|
||||
public sealed class X360Profile : SteamShortcutsProfile
|
||||
public class X360Profile : DefaultGuideShortcutsProfile
|
||||
{
|
||||
public override bool Selected(Context context)
|
||||
{
|
||||
|
|
|
|||
43
SteamController/Profiles/X360RumbleProfile.cs
Normal file
43
SteamController/Profiles/X360RumbleProfile.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
using CommonHelpers;
|
||||
using Nefarius.ViGEm.Client.Targets.Xbox360;
|
||||
|
||||
namespace SteamController.Profiles
|
||||
{
|
||||
public class X360RumbleProfile : X360Profile
|
||||
{
|
||||
public const ushort FeedbackMaxAmplitude = 255;
|
||||
public const ushort FeedbackPeriod = 10;
|
||||
public const ushort FeedbackCount = 1;
|
||||
|
||||
public override Status Run(Context context)
|
||||
{
|
||||
if (base.Run(context).IsDone)
|
||||
{
|
||||
return Status.Done;
|
||||
}
|
||||
|
||||
if (context.X360.FeedbackLargeMotor.HasValue)
|
||||
{
|
||||
Log.TraceLine("X360: Feedback Large: {0}", context.X360.FeedbackLargeMotor.Value);
|
||||
context.Steam.SetHaptic(
|
||||
1, GetHapticAmplitude(context.X360.FeedbackLargeMotor), FeedbackPeriod, FeedbackCount);
|
||||
context.X360.FeedbackLargeMotor = null;
|
||||
}
|
||||
|
||||
if (context.X360.FeedbackSmallMotor.HasValue)
|
||||
{
|
||||
Log.TraceLine("X360: Feedback Small: {0}", context.X360.FeedbackSmallMotor.Value);
|
||||
context.Steam.SetHaptic(
|
||||
0, GetHapticAmplitude(context.X360.FeedbackSmallMotor), FeedbackPeriod, FeedbackCount);
|
||||
context.X360.FeedbackSmallMotor = null;
|
||||
}
|
||||
|
||||
return Status.Continue;
|
||||
}
|
||||
|
||||
private ushort GetHapticAmplitude(byte? value)
|
||||
{
|
||||
return (ushort)(FeedbackMaxAmplitude * (value ?? 0) / byte.MaxValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue