Skip to content

Commit

Permalink
Merge pull request #1 from joekolodz/buttonmap
Browse files Browse the repository at this point in the history
new method to allow device list to be passed in when overlaying maps; include ShiftModePage in json converter
  • Loading branch information
joekolodz authored Apr 6, 2022
2 parents 6ff30ee + 7b1863f commit 392b6db
Show file tree
Hide file tree
Showing 8 changed files with 530 additions and 19 deletions.
454 changes: 454 additions & 0 deletions docs/diagrams/src/puml-theme-sierrahotas.puml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/Controls/MacroTransport.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<TextBox Text="{Binding ButtonName}" HorizontalAlignment="Stretch" VerticalContentAlignment="Center" Foreground="{StaticResource TextBrush}" CaretBrush="{StaticResource TextBrush}" Margin="0,0,2,0" Width="200" Height="30" FontSize="14" Background="{StaticResource WindowBackgroundBrush}" BorderBrush="{StaticResource NormalBorderBrush}"/>

<Button Style="{StaticResource MacroButton}" Command="{Binding RecordMacroStartCommand, IsAsync=True}" Margin="0,0,1,0" ToolTip="Record a new keystroke activity" ToolTipService.InitialShowDelay="800" ToolTipService.ShowOnDisabled="True">
<Button Style="{StaticResource MacroButton}" Command="{Binding RecordMacroStartCommand, IsAsync=True}" Margin="0,0,1,0" ToolTip="Record a new keystroke or key-chord activity" ToolTipService.InitialShowDelay="800" ToolTipService.ShowOnDisabled="True">
<Image>
<Image.Style>
<Style TargetType="Image" BasedOn="{StaticResource MacroButtonImage}">
Expand Down
1 change: 1 addition & 0 deletions src/CustomJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
if (button.Type == HOTASButton.ButtonType.Button && string.CompareOrdinal(button.MapName, JoystickOffsetValues.GetName(button.MapId)) != 0 ||
button.Type == HOTASButton.ButtonType.POV && string.CompareOrdinal(button.MapName, JoystickOffsetValues.GetPOVName(button.MapId)) != 0 ||
button.ActionCatalogItem?.Actions?.Count > 0 ||
button.ShiftModePage >0 ||
button.IsShift)
{
SerializeButton(writer, serializer, button);
Expand Down
22 changes: 21 additions & 1 deletion src/Models/HOTASDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,27 @@ public void OverlayAllProfilesToDevice()
}

ModeProfiles = mergedModeProfiles;
_hotasQueue.SetModeProfiles(ModeProfiles);
_hotasQueue?.SetModeProfiles(ModeProfiles);
}

/// <summary>
/// Existing buttons in the profile will overlay buttons on the device. If a device has a button with matching profile, then we'll keep that button (otherwise we'd lose it if we just took profile buttons)
/// This allows a device to change without losing mappings (for instance when chaining a new Virpil device, or manually editing and removing buttons from the profile's JSON file)
/// </summary>
public void OverlayAllProfilesToDevice(Dictionary<int, ObservableCollection<IHotasBaseMap>> profilesToMergeIn)
{
var mergedModeProfiles = new Dictionary<int, ObservableCollection<IHotasBaseMap>>();
var deviceButtons = new ObservableCollection<IHotasBaseMap>();
SeedButtonMapProfileFromDeviceCapabilities(deviceButtons);

foreach (var p in profilesToMergeIn)
{
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));
}

ModeProfiles = mergedModeProfiles;
_hotasQueue?.SetModeProfiles(ModeProfiles);
}

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/Models/IHOTASDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public interface IHOTASDevice
void CopyModeProfileFromTemplate(int templateModeSource, int destinationMode);
void ListenAsync();
void OverlayAllProfilesToDevice();
void OverlayAllProfilesToDevice(Dictionary<int, ObservableCollection<IHotasBaseMap>> profilesToMergeIn);
void ApplyButtonMap(ObservableCollection<IHotasBaseMap> existingButtonMap);
void SetMode(int mode);
void ForceButtonPress(JoystickOffset offset, bool isDown);
Expand Down
6 changes: 6 additions & 0 deletions src/ViewModels/ActionCatalogViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ public void Add(ButtonMapViewModel buttonMap)
Logging.Log.Debug($"{item.ActionName} - {buttonMap.ButtonName} added to actions catalog");
}

public ActionCatalogItem Get(string actionName)
{
if (!Contains(actionName)) return null;
return Catalog.First(x => x.ActionName == actionName);
}

private void AddEmptyItem()
{
Add(new ActionCatalogItem() { NoAction = true, ActionName = NO_ACTION_TEXT, Actions = new ObservableCollection<ButtonAction>() });
Expand Down
19 changes: 14 additions & 5 deletions src/ViewModels/HOTASCollectionViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ private void AddActivity(IHotasBaseMap map, KeystrokeSentEventArgs e)
Activity.Insert(0, activity);
if (Activity.Count >= 200)
{
Activity.RemoveAt(Activity.Count-1);
Activity.RemoveAt(Activity.Count - 1);
}
});
}
Expand Down Expand Up @@ -405,7 +405,6 @@ private void BuildDevicesViewModelFromLoadedDevices(IHOTASCollection loadedDevic
{
Logging.Log.Warn($"Loaded mappings for {ld.Name}, but could not find the device attached!");
Logging.Log.Warn($"Mappings will be displayed, but they will not function");
//deviceVm = new DeviceViewModel(_appDispatcher, _fileSystem, _mediaPlayerFactory, ld);
deviceVm = _deviceViewModelFactory.CreateDeviceViewModel(_appDispatcher, _fileSystem, _mediaPlayerFactory, ld);
Devices.Add(deviceVm);
_deviceList.AddDevice(ld);
Expand All @@ -415,8 +414,9 @@ private void BuildDevicesViewModelFromLoadedDevices(IHOTASCollection loadedDevic
{
d = _deviceList.GetDevice(ld.DeviceId);
if (d == null) continue;
d.OverlayAllProfilesToDevice(ld.ModeProfiles);
d.ApplyButtonMap(d.ModeProfiles[d.ModeProfiles.Keys.Min()].ToObservableCollection());
}
d.SetModeProfile(ld.ModeProfiles);
deviceVm.RebuildMap(d.ButtonMap);
}
}
Expand Down Expand Up @@ -524,8 +524,6 @@ private void LoadHotas(IHOTASCollection loadedDeviceList)
AddHandlers();
ProfileSetFileName = _fileSystem.LastSavedFileName;

//since the JSON file may have less button maps than are on the device, we need to overlay them individually instead of replacing the whole collection
_deviceList.ApplyButtonMapToAllProfiles();
_deviceList.AutoSetMode();
_deviceList.ListenToAllDevices();

Expand Down Expand Up @@ -579,6 +577,11 @@ private void ReBuildActionCatalog()
}
case HOTASButton buttonMap:
{
if (ActionCatalog.Contains(buttonMap.ActionName))
{
buttonMap.ActionCatalogItem = ActionCatalog.Get(buttonMap.ActionName);
break;
}
AddButtonToCatalog(buttonMap.ActionName, buttonMap.ActionCatalogItem.Actions, buttonMap.MapName);
break;
}
Expand All @@ -592,6 +595,12 @@ private void AddButtonListToCatalog(ObservableCollection<HOTASButton> mapList)
{
foreach (var baseMap in mapList)
{
if (ActionCatalog.Contains(baseMap.ActionName))
{
//baseMap.ActionCatalogItem.Actions = ActionCatalog.Get(baseMap.ActionName).Actions;
baseMap.ActionCatalogItem = ActionCatalog.Get(baseMap.ActionName);
break;
}
AddButtonToCatalog(baseMap.ActionName, baseMap.ActionCatalogItem.Actions, baseMap.MapName);
}
}
Expand Down
44 changes: 32 additions & 12 deletions tests/HOTASCollectionViewModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ public void file_open_command_valid_file_existing_device()
existingDevice.DeviceId = existingDeviceId;
existingDevice.Name = "existing device";
existingDevice.Capabilities = new Capabilities() { AxeCount = 2, ButtonCount = 1 };


AddHotasButtonMap(existingDevice.ButtonMap, existingButtonMapId);

Expand Down Expand Up @@ -937,7 +937,7 @@ public void add_activity_keystroke_down()
{
var hotasVm = CreateHotasCollectionViewModel(out _, out var subDeviceList, out _, out _, out _, out _);
hotasVm.Initialize();

IHOTASQueue queue = new HOTASQueue(Substitute.For<IKeyboard>());
IHotasBaseMap map = new HOTASButton() { Type = HOTASButton.ButtonType.Button, ActionName = "test action" };
queue.SetButtonMap(new ObservableCollection<IHotasBaseMap>() { map });
Expand Down Expand Up @@ -1131,16 +1131,25 @@ public void load_profile()

var hotasVm = CreateHotasCollectionViewModel(out var subFileSystem, out var subQuickProfilePanelVm);

var subHotasCollection = CreateHotasCollectionSubstitute();
subHotasCollection.Devices.Add(new HOTASDevice()
var device = new HOTASDevice()
{
DeviceId = deviceId,
ButtonMap =
DeviceId = deviceId
};


var profile = new Dictionary<int, ObservableCollection<IHotasBaseMap>>();
var map = new ObservableCollection<IHotasBaseMap>()
{
new HOTASButton(){MapId = 43, Type = HOTASButton.ButtonType.Button, ActionCatalogItem = new ActionCatalogItem(){ActionName = "test action 1"}},
new HOTASButton(){MapId = 44, Type = HOTASButton.ButtonType.Button, ActionCatalogItem = new ActionCatalogItem(){ActionName = "test action 2"}},
}
});
new HOTASButton() { MapId = 43, Type = HOTASButton.ButtonType.Button, ActionCatalogItem = new ActionCatalogItem() { ActionName = "test action 1" } },
new HOTASButton() { MapId = 44, Type = HOTASButton.ButtonType.Button, ActionCatalogItem = new ActionCatalogItem() { ActionName = "test action 2" } }

};
profile.Add(1, map);

device.SetModeProfile(profile);

var subHotasCollection = CreateHotasCollectionSubstitute();
subHotasCollection.Devices.Add(device);

subFileSystem.FileOpen(Arg.Any<string>()).ReturnsForAnyArgs(subHotasCollection);
subFileSystem.LastSavedFileName.Returns("last saved file");
Expand Down Expand Up @@ -1180,11 +1189,22 @@ public void load_profile_add_button_list_to_catalog()
new HOTASAxis() {MapName = "test2", MapId = 44, Type = HOTASButton.ButtonType.AxisLinear, ButtonMap = new ObservableCollection<HOTASButton>(){new HOTASButton(){MapName = "bm2", ActionName = "abm2", ActionCatalogItem = new ActionCatalogItem(){ActionName = "action2", Actions = new ObservableCollection<ButtonAction>(){new ButtonAction(){ScanCode = 2}}}}}},
}
};
subDevice.ModeProfiles.Add(43, new ObservableCollection<IHotasBaseMap>());
subHotasCollection.Devices.Add(subDevice);




var profile = new Dictionary<int, ObservableCollection<IHotasBaseMap>>();
var map = new ObservableCollection<IHotasBaseMap>()
{
new HOTASAxis() {MapName = "test1", MapId = 43, Type = HOTASButton.ButtonType.AxisLinear, ButtonMap = new ObservableCollection<HOTASButton>(){new HOTASButton(){MapName = "bm1", ActionName = "abm1", ActionCatalogItem = new ActionCatalogItem(){ActionName = "action1", Actions = new ObservableCollection<ButtonAction>(){new ButtonAction(){ScanCode = 1}}}}}},
new HOTASAxis() {MapName = "test2", MapId = 44, Type = HOTASButton.ButtonType.AxisLinear, ButtonMap = new ObservableCollection<HOTASButton>(){new HOTASButton(){MapName = "bm2", ActionName = "abm2", ActionCatalogItem = new ActionCatalogItem(){ActionName = "action2", Actions = new ObservableCollection<ButtonAction>(){new ButtonAction(){ScanCode = 2}}}}}},
};
profile.Add(1, map);

subDevice.SetModeProfile(profile);

subHotasCollection.Devices.Add(subDevice);

subHotasCollection.ModeProfileActivationButtons.Add(1, new ModeActivationItem() { ButtonId = 43, DeviceId = deviceId });
subHotasCollection.SetupNewModeProfile();

Expand Down

0 comments on commit 392b6db

Please sign in to comment.