Skip to content

Commit

Permalink
update to .net framework 4.8
Browse files Browse the repository at this point in the history
add multi-action button (see readme.md)
  • Loading branch information
mhwlng committed Apr 6, 2022
1 parent 3a01326 commit c5f6f82
Show file tree
Hide file tree
Showing 15 changed files with 751 additions and 50 deletions.
12 changes: 4 additions & 8 deletions InputSimulatorPlus/WindowsInput/IKeyboardSimulator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,13 @@ public interface IKeyboardSimulator
/// Calls the Win32 SendInput method with a KeyUp message
/// </summary>
/// <param name="dikCode">The <see cref="DirectInputKeyCode"/> to press</param>
/// <param name="delay">Delay in ms between keydown and keyup of final keyCode.</param>
IKeyboardSimulator DelayedKeyPressUp(DirectInputKeyCode dikCode, int delay);
IKeyboardSimulator DelayedKeyPressUp(DirectInputKeyCode dikCode);

/// <summary>
/// Calls the Win32 SendInput method with a KeyDown message
/// </summary>
/// <param name="dikCode">The <see cref="DirectInputKeyCode"/> to press</param>
/// <param name="delay">Delay in ms between keydown and keyup of final keyCode.</param>
IKeyboardSimulator DelayedKeyPressDown(DirectInputKeyCode dikCode, int delay);
IKeyboardSimulator DelayedKeyPressDown(DirectInputKeyCode dikCode);


/// <summary>
Expand Down Expand Up @@ -152,8 +150,7 @@ public interface IKeyboardSimulator
/// </summary>
/// <param name="modifierDikCodes">The list of modifier keys</param>
/// <param name="dikCode">The key to simulate</param>
/// <param name="delay">Delay in ms between keydown and keyup of final keyCode.</param>
IKeyboardSimulator DelayedModifiedKeyStrokeDown(IEnumerable<DirectInputKeyCode> modifierDikCodes, DirectInputKeyCode dikCode, int delay);
IKeyboardSimulator ModifiedKeyStrokeDown(IEnumerable<DirectInputKeyCode> modifierDikCodes, DirectInputKeyCode dikCode);


/// <summary>
Expand All @@ -162,8 +159,7 @@ public interface IKeyboardSimulator
/// </summary>
/// <param name="modifierDikCodes">The list of modifier keys</param>
/// <param name="dikCode">The key to simulate</param>
/// <param name="delay">Delay in ms between keydown and keyup of final keyCode.</param>
IKeyboardSimulator DelayedModifiedKeyStrokeUp(IEnumerable<DirectInputKeyCode> modifierDikCodes, DirectInputKeyCode dikCode, int delay);
IKeyboardSimulator ModifiedKeyStrokeUp(IEnumerable<DirectInputKeyCode> modifierDikCodes, DirectInputKeyCode dikCode);

/// <summary>
/// Simulates a modified keystroke where there is one modifier and multiple keys like CTRL-K-C where CTRL is the modifierKey and K and C are the keys.
Expand Down
20 changes: 8 additions & 12 deletions InputSimulatorPlus/WindowsInput/KeyboardSimulator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -311,11 +311,11 @@ public IKeyboardSimulator KeyPress(DirectInputKeyCode dikCode)
/// <param name="delay">Delay in ms between keydown and keyup of final keyCode. 50ms should be minimum</param>
public IKeyboardSimulator DelayedKeyPress(DirectInputKeyCode dikCode, int delay)
{
DelayedKeyPressDown(dikCode, delay);
DelayedKeyPressDown(dikCode);

Thread.Sleep(delay);

DelayedKeyPressUp(dikCode, delay);
DelayedKeyPressUp(dikCode);

return this;
}
Expand All @@ -324,8 +324,7 @@ public IKeyboardSimulator DelayedKeyPress(DirectInputKeyCode dikCode, int delay)
/// Calls the Win32 SendInput method with a KeyDown message
/// </summary>
/// <param name="dikCode">The <see cref="DirectInputKeyCode"/> to press</param>
/// <param name="delay">Delay in ms between keydown and keyup of final keyCode. 50ms should be minimum</param>
public IKeyboardSimulator DelayedKeyPressDown(DirectInputKeyCode dikCode, int delay)
public IKeyboardSimulator DelayedKeyPressDown(DirectInputKeyCode dikCode)
{
var inputList1 = new InputBuilder().AddKeyDown(dikCode).ToArray();
SendSimulatedInput(inputList1);
Expand All @@ -337,8 +336,7 @@ public IKeyboardSimulator DelayedKeyPressDown(DirectInputKeyCode dikCode, int de
/// Calls the Win32 SendInput method with a KeyUp message
/// </summary>
/// <param name="dikCode">The <see cref="DirectInputKeyCode"/> to press</param>
/// <param name="delay">Delay in ms between keydown and keyup of final keyCode. 50ms should be minimum</param>
public IKeyboardSimulator DelayedKeyPressUp(DirectInputKeyCode dikCode, int delay)
public IKeyboardSimulator DelayedKeyPressUp(DirectInputKeyCode dikCode)
{
var inputList2 = new InputBuilder().AddKeyUp(dikCode).ToArray();
SendSimulatedInput(inputList2);
Expand Down Expand Up @@ -407,11 +405,11 @@ public IKeyboardSimulator ModifiedKeyStroke(IEnumerable<DirectInputKeyCode> modi
/// <param name="delay">Delay in ms between keydown and keyup of final keyCode. 50ms should be minimum</param>
public IKeyboardSimulator DelayedModifiedKeyStroke(IEnumerable<DirectInputKeyCode> modifierDikCodes, DirectInputKeyCode dikCode, int delay)
{
DelayedModifiedKeyStrokeDown(modifierDikCodes, dikCode, delay);
ModifiedKeyStrokeDown(modifierDikCodes, dikCode);

Thread.Sleep(delay);

DelayedModifiedKeyStrokeUp(modifierDikCodes, dikCode, delay);
ModifiedKeyStrokeUp(modifierDikCodes, dikCode);

return this;
}
Expand All @@ -422,8 +420,7 @@ public IKeyboardSimulator DelayedModifiedKeyStroke(IEnumerable<DirectInputKeyCod
/// </summary>
/// <param name="modifierDikCodes">The list of modifier keys</param>
/// <param name="dikCode">The list of keys to simulate</param>
/// <param name="delay">Delay in ms between keydown and keyup of final keyCode. 50ms should be minimum</param>
public IKeyboardSimulator DelayedModifiedKeyStrokeDown(IEnumerable<DirectInputKeyCode> modifierDikCodes, DirectInputKeyCode dikCode, int delay)
public IKeyboardSimulator ModifiedKeyStrokeDown(IEnumerable<DirectInputKeyCode> modifierDikCodes, DirectInputKeyCode dikCode)
{
foreach (var keyCode in modifierDikCodes)
{
Expand All @@ -442,8 +439,7 @@ public IKeyboardSimulator DelayedModifiedKeyStrokeDown(IEnumerable<DirectInputKe
/// </summary>
/// <param name="modifierDikCodes">The list of modifier keys</param>
/// <param name="dikCode">The list of keys to simulate</param>
/// <param name="delay">Delay in ms between keydown and keyup of final keyCode. 50ms should be minimum</param>
public IKeyboardSimulator DelayedModifiedKeyStrokeUp(IEnumerable<DirectInputKeyCode> modifierDikCodes, DirectInputKeyCode dikCode, int delay)
public IKeyboardSimulator ModifiedKeyStrokeUp(IEnumerable<DirectInputKeyCode> modifierDikCodes, DirectInputKeyCode dikCode)
{
KeyUp(dikCode);

Expand Down
2 changes: 1 addition & 1 deletion InputSimulatorPlus/WindowsInput/WindowsInput.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>WindowsInput</RootNamespace>
<AssemblyName>WindowsInput</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
Expand Down
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,24 @@ The bound key is shown in the dropdown, localised for the current keyboard langu

Credit goes to https://github.com/SCToolsfactory/SCJMapper-V2 for all the code to get the `defaultProfile.xml` from the p4k file etc.

The button works in a similar way, to the streamdeck 'Hotkey' button type.
The static button works in a similar way, to the streamdeck 'Hotkey' button type.
So, there is only one image and there is no game state feedback for these buttons.
The differences with the 'Hotkey' buttons are, that it gets the keyboard binding from the game.
When the stream deck button is pushed, the 'key down' event is sent to the keyboard
and only after the stream deck button is released, the 'key up' event is sent to the keyboard.

The plugin's multi-action button behaviour is different : when the stream deck button is pushed, the 'key down' event is sent to the keyboard.
After a user-definable delay (default = 40 ms) the 'key up' event is sent to the keyboard.
Nothing happens when the streamdeck button is released.

Both the static- and multi-action buttons can be used inside the streamdeck built-in multi-action button's action list.

The multi-action button can also be used as a regular streamdeck button, in case a fixed user-definable delay is required between the key down and key up events.

A sound can be played when pressing a button.

**You can clear the sound path, by clicking on the label in front of the file picker edit box.**

The buttons can also be used with multi-action buttons.

You can, for example, use the 'multi-action switch' function, that is built into the streamdeck software, to set up a toggle function.
You can add the relevant function of this plugin to both the ON-and OFF-action of the 'multi-action switch' function.
You can then set up different images for each toggle state.
Expand Down Expand Up @@ -74,7 +80,7 @@ The plugin uses all the active keyboard bindings from `defaultProfile.xml` and t

`C:\Program Files\Roberts Space Industries\StarCitizen\LIVE\USER\Client\0\Profiles\default\actionmaps.xml`

The `PropertyInspector\StarCitizen\Static.html` file is dynamically updated, in case more custom keyboard bindings were added to `actionmaps.xml`,
The `PropertyInspector\StarCitizen\Static.html` and `PropertyInspector\StarCitizen\Macro.html` file is dynamically updated, in case more custom keyboard bindings were added to `actionmaps.xml`,
that didn't have any corresponding keyboard bindings in `defaultProfile.xml`.

If nothing happens, when pressing streamdeck buttons: you could try to start streamdeck.exe as administrator.
Expand Down
6 changes: 3 additions & 3 deletions starcitizen/App.config
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
<configuration>
<appSettings configSource="appsettings.config" />
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Drawing.Common" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.2" newVersion="4.0.0.2" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
Expand All @@ -20,7 +20,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
Expand Down
159 changes: 159 additions & 0 deletions starcitizen/Buttons/Macro.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Input;
using WindowsInput.Native;
using BarRaider.SdTools;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

// ReSharper disable StringLiteralTypo

namespace starcitizen.Buttons
{

[PluginActionId("com.mhwlng.starcitizen.macro")]
public class Macro : StarCitizenBase
{
protected class PluginSettings
{
public static PluginSettings CreateDefaultSettings()
{
var instance = new PluginSettings
{
Function = string.Empty,
};

return instance;
}

[JsonProperty(PropertyName = "function")]
public string Function { get; set; }

[FilenameProperty]
[JsonProperty(PropertyName = "clickSound")]
public string ClickSoundFilename { get; set; }

[JsonProperty(PropertyName = "delay")]
public string Delay { get; set; }

}


PluginSettings settings;
private CachedSound _clickSound = null;

private int? _delay = null;


public Macro(SDConnection connection, InitialPayload payload) : base(connection, payload)
{
if (payload.Settings == null || payload.Settings.Count == 0)
{
//Logger.Instance.LogMessage(TracingLevel.DEBUG, "Repeating Macro Constructor #1");

settings = PluginSettings.CreateDefaultSettings();
Connection.SetSettingsAsync(JObject.FromObject(settings)).Wait();

}
else
{
//Logger.Instance.LogMessage(TracingLevel.DEBUG, "Repeating Macro Constructor #2");

settings = payload.Settings.ToObject<PluginSettings>();
HandleFileNames();
}

}


public override void KeyPressed(KeyPayload payload)
{
if (InputRunning || Program.dpReader == null)
{
ForceStop = true;
return;
}

ForceStop = false;

var action = Program.dpReader.GetBinding(settings.Function);
if (action != null)
{
Logger.Instance.LogMessage(TracingLevel.INFO, CommandTools.ConvertKeyString(action.Keyboard));

SendKeypress(CommandTools.ConvertKeyString(action.Keyboard), _delay ?? 40);
}

if (_clickSound != null)
{
try
{
AudioPlaybackEngine.Instance.PlaySound(_clickSound);
}
catch (Exception ex)
{
Logger.Instance.LogMessage(TracingLevel.FATAL, $"PlaySound: {ex}");
}

}

}

public override void KeyReleased(KeyPayload payload)
{


}

public override void Dispose()
{
base.Dispose();

//Logger.Instance.LogMessage(TracingLevel.DEBUG, "Destructor called #1");
}


public override void ReceivedSettings(ReceivedSettingsPayload payload)
{
//Logger.Instance.LogMessage(TracingLevel.DEBUG, "ReceivedSettings");

// New in StreamDeck-Tools v2.0:
BarRaider.SdTools.Tools.AutoPopulateSettings(settings, payload.Settings);
HandleFileNames();
}

private void HandleFileNames()
{
_delay = null;

if (!string.IsNullOrEmpty(settings.Delay))
{
var ok = int.TryParse(settings.Delay, out var delay);
if (ok && (delay > 0))
{
_delay = delay;
}
}

_clickSound = null;

if (File.Exists(settings.ClickSoundFilename))
{
try
{
_clickSound = new CachedSound(settings.ClickSoundFilename);
}
catch (Exception ex)
{
Logger.Instance.LogMessage(TracingLevel.FATAL, $"CachedSound: {settings.ClickSoundFilename} {ex}");

_clickSound = null;
settings.ClickSoundFilename = null;
}
}

Connection.SetSettingsAsync(JObject.FromObject(settings)).Wait();
}
}
}
Loading

0 comments on commit c5f6f82

Please sign in to comment.