Skip to content

Commit

Permalink
Implement 'inherited' parent map; mode profiles and mode activation b…
Browse files Browse the repository at this point in the history
…utton list need to be passed into HOTASQueue; improved some tests; fixed namespace problem;
  • Loading branch information
joekolodz committed Oct 9, 2021
1 parent f22b43f commit c08ee38
Show file tree
Hide file tree
Showing 23 changed files with 441 additions and 147 deletions.
20 changes: 11 additions & 9 deletions src/Models/HOTASCollection.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Newtonsoft.Json;
using SharpDX.DirectInput;
using SierraHOTAS.ModeProfileWindow.ViewModels;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
Expand Down Expand Up @@ -86,6 +85,7 @@ private void RebuildMapForNewDevice(IHOTASDevice device, IHOTASDevice newDevice)
{
newDevice.ApplyButtonMap(device.ButtonMap.ToObservableCollection());
newDevice.SetModeProfile(device.ModeProfiles);
newDevice.SetModeActivation(ModeProfileActivationButtons);
Devices.Add(newDevice);
}

Expand Down Expand Up @@ -159,6 +159,8 @@ public void ListenToDevice(IHOTASDevice device)
device.ModeProfileSelected += Device_ModeProfileSelected;
device.ShiftReleased += Device_ShiftReleased;
device.LostConnectionToDevice += Device_LostConnectionToDevice;

device.SetModeActivation(ModeProfileActivationButtons);
device.ListenAsync();
}

Expand Down Expand Up @@ -349,16 +351,16 @@ public bool RemoveModeProfile(ModeActivationItem item)

foreach (var d in Devices)
{
d.ModeProfiles.Remove(item.Mode);
}
d.RemoveModeProfile(item.Mode);
}

Logging.Log.Debug($"DELETED Mode {item.Mode}!");
if (ModeProfileActivationButtons.Count > 0)
{
var firstMode = ModeProfileActivationButtons.Keys.FirstOrDefault();
SetMode(firstMode);
Logging.Log.Debug($"Setting Mode to {firstMode}!");
}

if (ModeProfileActivationButtons.Count <= 0) return true;

var firstMode = ModeProfileActivationButtons.Keys.FirstOrDefault();
SetMode(firstMode);
Logging.Log.Debug($"Setting Mode to {firstMode}!");
return true;
}
return false;
Expand Down
36 changes: 29 additions & 7 deletions src/Models/HOTASDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class HOTASDevice : IHOTASDevice
private readonly IDirectInput _directInput;
private IJoystick Joystick { get; set; }
private IHOTASQueue _hotasQueue;
private Dictionary<int, ModeActivationItem> _modeProfileActivationButtons;

public HOTASDevice() { }

Expand All @@ -60,10 +61,11 @@ public HOTASDevice(IDirectInput directInput, Guid productGuid, Guid deviceId, st
DeviceId = deviceId;
ProductId = productGuid;
Name = name;
ModeProfiles.Add(1, ButtonMap);
InitializeModeProfile();
}

public HOTASDevice(IDirectInput directInput, JoystickFactory joystickFactory, Guid productGuid, Guid deviceId, string name, IHOTASQueue hotasQueue) : this(directInput, productGuid, deviceId, name, hotasQueue)
public HOTASDevice(IDirectInput directInput, JoystickFactory joystickFactory, Guid productGuid, Guid deviceId, string name, IHOTASQueue hotasQueue) :
this(directInput, productGuid, deviceId, name, hotasQueue)
{
_directInput = directInput ?? throw new ArgumentNullException(nameof(directInput));
_joystickFactory = joystickFactory ?? throw new ArgumentNullException(nameof(joystickFactory));
Expand All @@ -76,6 +78,20 @@ public HOTASDevice(IDirectInput directInput, JoystickFactory joystickFactory, Gu
LoadCapabilitiesMapping();
}

public void RemoveModeProfile(int mode)
{
ModeProfiles.Remove(mode);
if (ModeProfiles.Count == 0)
{
InitializeModeProfile();
}
}

private void InitializeModeProfile()
{
ModeProfiles.Add(1, ButtonMap);
}

public void SetModeProfile(Dictionary<int, ObservableCollection<IHotasBaseMap>> profile)
{
ModeProfiles = profile;
Expand Down Expand Up @@ -199,12 +215,14 @@ private void AcquireJoystick()
Joystick.Acquire();
}


public void ListenAsync()
{
if (_modeProfileActivationButtons == null) throw new InvalidOperationException("ModeProfileActivationButtons must be set before listening to device");

RemoveQueueHandlers();
AddQueueHandlers();

_hotasQueue.Listen(Joystick, ButtonMap);
_hotasQueue.Listen(Joystick, ModeProfiles, _modeProfileActivationButtons);
}

private void AddQueueHandlers()
Expand Down Expand Up @@ -241,7 +259,6 @@ public void OverlayAllProfilesToDevice()

foreach (var p in ModeProfiles)
{
if (p.Value.Count == 0) continue;
var d = deviceButtons.ToObservableCollection();//make a copy since we could have more than 1 profile and we don't need to rescan caps
mergedModeProfiles.Add(p.Key, MergeMaps(d, p.Value));
}
Expand Down Expand Up @@ -297,11 +314,16 @@ public void SetMode(int mode)
{
if (!ModeProfiles.ContainsKey(mode))
{
Logging.Log.Warn($"Tried to change device to Mode {mode}, but there was no profile for it. Profile will remain unchanged. Device ID: {DeviceId}, Device Name: {Name}");
Logging.Log.Debug($"Tried to change device to Mode {mode}, but there was no profile for it. Profile will remain unchanged. Device ID: {DeviceId}, Device Name: {Name}");
return;
}
ButtonMap = ModeProfiles[mode];
_hotasQueue.SetButtonMap(ButtonMap);
_hotasQueue.SetMode(mode);
}

public void SetModeActivation(Dictionary<int, ModeActivationItem> modeProfileActivationButtons)
{
_modeProfileActivationButtons = modeProfileActivationButtons;
}

public void ForceButtonPress(JoystickOffset offset, bool isDown)
Expand Down
62 changes: 57 additions & 5 deletions src/Models/HOTASQueue.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using SharpDX.DirectInput;
//todo can remove sharpdx dependency...replace JoystickUpdate with custom array. can do this in the joystickwrapper for the call to GetCurrentState
using SharpDX.DirectInput;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -29,20 +31,28 @@ public class HOTASQueue : IHOTASQueue

private Dictionary<int, JitterDetection> _jitterDetectionDictionary;

private Dictionary<int, ModeActivationItem> _modeProfileActivationButtons;

private int _mode;

private IKeyboard Keyboard { get; set; }
private IJoystick Joystick { get; set; }
private ObservableCollection<IHotasBaseMap> _buttonMap;
private Dictionary<int, ObservableCollection<IHotasBaseMap>> _modeProfiles;

public HOTASQueue(IKeyboard keyboard)
{
Keyboard = keyboard;
}

public void Listen(IJoystick joystick, ObservableCollection<IHotasBaseMap> buttonMap)
public void Listen(IJoystick joystick, Dictionary<int, ObservableCollection<IHotasBaseMap>> modeProfiles, Dictionary<int, ModeActivationItem> modeProfileActivationButtons)
{
Joystick = joystick;
_buttonMap = buttonMap;
_modeProfiles = modeProfiles;
_modeProfileActivationButtons = modeProfileActivationButtons;

if (_modeProfiles.Count > 0) _buttonMap = _modeProfiles[1];

_jitterDetectionDictionary = new Dictionary<int, JitterDetection>();

_actionJobs = new BlockingCollection<ActionJobItem>();
Expand Down Expand Up @@ -225,6 +235,19 @@ private void HandleStandardButton(int offset, int value)
//if action list has a timer in it, then it is a macro and executes on another thread independently. does not interrupt other buttons
HandleButtonPressed(map, offset);
}
else
{
if (_modeProfileActivationButtons.ContainsKey(_mode) &&
_modeProfileActivationButtons[_mode].InheritFromMode>0)
{
map = GetMapFromParentMode(_modeProfileActivationButtons[_mode].InheritFromMode, offset) as HOTASButton;
if (map != null)
{
HandleButtonPressed(map, offset);
}
}
}

OnButtonPress(offset);
}
else
Expand Down Expand Up @@ -279,14 +302,15 @@ private async Task PlayMacroOnce(int offset, ObservableCollection<ButtonAction>
foreach (var action in actions)
{
if (_activeMacros.ContainsKey(offset) == false) break;

if (action.TimeInMilliseconds > 0)
{
//yes this is precise only to the nearest KeyDownRepeatDelay milliseconds. repeated keys are on a 60 millisecond boundary, so the UI could be locked to 60ms increments only
var timeLeft = action.TimeInMilliseconds;
while (timeLeft > 0)
{
await Task.Delay(Keyboard.KeyDownRepeatDelay);
if (!_activeMacros.ContainsKey(offset)) return;
timeLeft -= Keyboard.KeyDownRepeatDelay;
}
}
Expand Down Expand Up @@ -339,9 +363,30 @@ private void OnAxisChanged(JoystickUpdate state)
AxisChanged?.Invoke(this, new AxisChangedEventArgs() { AxisId = (int)state.Offset, Value = state.Value, Device = null });
}

//public IHotasBaseMap GetMap(int buttonOffset)
//{
// return _buttonMap.FirstOrDefault(m => m.MapId == buttonOffset);
//}

public IHotasBaseMap GetMap(int buttonOffset)
{
return _buttonMap.FirstOrDefault(m => m.MapId == buttonOffset);
var map = _buttonMap.FirstOrDefault(m => m.MapId == buttonOffset);
if (map == null)
{
Debug.WriteLine("fuck");
}
return map;
}

private IHotasBaseMap GetMapFromParentMode(int parentModeId, int buttonOffset)
{
var parentMode = _modeProfiles[parentModeId];
var map = parentMode.FirstOrDefault(m => m.MapId == buttonOffset) as HOTASButton;
//if (map.ActionCatalogItem.Actions.Count > 0 && map.ShiftModePage <= 0)
//{
// ModeProfileSelected?.Invoke(this, new ModeProfileSelectedEventArgs(){IsShift = true, Mode = parentModeId });
//}
return map;
}

private void OnButtonPress(int buttonId)
Expand All @@ -354,10 +399,17 @@ private void OnButtonRelease(int buttonId)
ButtonReleased?.Invoke(this, new ButtonPressedEventArgs() { ButtonId = buttonId, Device = null });
}

[Obsolete]
public void SetButtonMap(ObservableCollection<IHotasBaseMap> buttonMap)
{
_buttonMap = buttonMap;
}

public void SetMode(int mode)
{
_mode = mode;
_buttonMap = _modeProfiles[_mode];
}
}

}
2 changes: 0 additions & 2 deletions src/Models/IHOTASCollection.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using SharpDX.DirectInput;
using SierraHOTAS.ModeProfileWindow.ViewModels;

namespace SierraHOTAS.Models
{
Expand Down
3 changes: 2 additions & 1 deletion src/Models/IHOTASDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,16 @@ public interface IHOTASDevice
void SetModeProfile(Dictionary<int, ObservableCollection<IHotasBaseMap>> profile);
int SetupNewModeProfile();
void CopyModeProfileFromTemplate(int templateModeSource, int destinationMode);
//void ReAcquireJoystick();
void ListenAsync();
void OverlayAllProfilesToDevice();
void ApplyButtonMap(ObservableCollection<IHotasBaseMap> existingButtonMap);
void SetMode(int mode);
void ForceButtonPress(JoystickOffset offset, bool isDown);
void Stop();
void ClearUnassignedActions();
void RemoveModeProfile(int mode);
void ClearButtonMap();
bool GetButtonState(int mapId);
void SetModeActivation(Dictionary<int, ModeActivationItem> modeProfileActivationButtons);
}
}
5 changes: 3 additions & 2 deletions src/Models/IHOTASQueue.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using SharpDX.DirectInput;

namespace SierraHOTAS.Models
{
Expand All @@ -16,10 +16,11 @@ public interface IHOTASQueue
event EventHandler<ModeProfileSelectedEventArgs> ModeProfileSelected;
event EventHandler<EventArgs> ShiftReleased;
event EventHandler<EventArgs> LostConnectionToDevice;
void Listen(IJoystick joystick, ObservableCollection<IHotasBaseMap> buttonMap);
void Listen(IJoystick joystick, Dictionary<int, ObservableCollection<IHotasBaseMap>> modeProfiles, Dictionary<int, ModeActivationItem> modeProfileActivationButtons);
void ForceButtonPress(JoystickOffset offset, bool isDown);
void Stop();
IHotasBaseMap GetMap(int buttonOffset);
void SetButtonMap(ObservableCollection<IHotasBaseMap> buttonMap);
void SetMode(int mode);
}
}
3 changes: 2 additions & 1 deletion src/Models/ModeActivationItem.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using System;
using Newtonsoft.Json;

namespace SierraHOTAS.ModeProfileWindow.ViewModels
namespace SierraHOTAS.Models
{
public class ModeActivationItem
{
public int Mode { get; set; }
public int InheritFromMode { get; set; }
public bool IsShift { get; set; }
public string ProfileName { get; set; }
public string DeviceName { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion src/ViewModels/DeleteModeProfileEvent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using SierraHOTAS.ModeProfileWindow.ViewModels;
using SierraHOTAS.Models;

namespace SierraHOTAS.ViewModels
{
Expand Down
1 change: 0 additions & 1 deletion src/ViewModels/HOTASCollectionViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using SierraHOTAS.Annotations;
using SierraHOTAS.Factories;
using SierraHOTAS.Models;
using SierraHOTAS.ModeProfileWindow.ViewModels;
using SierraHOTAS.ViewModels.Commands;
using System;
using System.Collections.ObjectModel;
Expand Down
Loading

0 comments on commit c08ee38

Please sign in to comment.