Skip to content

Commit

Permalink
Flags are now customizable. Images are loaded in the backend.
Browse files Browse the repository at this point in the history
Issue #123
  • Loading branch information
pre-martin committed Sep 8, 2024
2 parents 321b77f + e2913b0 commit 0b073fa
Show file tree
Hide file tree
Showing 9 changed files with 295 additions and 248 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<ItemGroup>
<PackageReference Include="Nerdbank.GitVersioning" Condition="!Exists('packages.config')">
<PrivateAssets>all</PrivateAssets>
<Version>3.6.133</Version>
<Version>3.6.143</Version>
</PackageReference>
</ItemGroup>
</Project>
4 changes: 3 additions & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ image::images/teaser/Teaser-2.png[Teaser 2,800]

== Installation

WARNING: To download, do not use the green button! Instead click on "Releases" on the right side and download the file with extension `streamDeckPlugin`.
WARNING: To download, do not use the green button! Instead, click on "Releases" on the right side and download the file with extension `streamDeckPlugin`.

Be sure to have the SimHub Property Server plugin installed into SimHub (see above). When updating this plugin, be sure to also check the SimHub Property Server plugin for updates.

TIP: For the usage of this plugin, the https://dotnet.microsoft.com/en-us/download/dotnet/8.0[.NET Runtime 8.0] has to be installed. Without this, the plugin won't even start. Download ".NET Desktop Runtime 8.0.x (x64)" from Microsoft.

Download the file `net.planetrenner.simhub.streamDeckPlugin` from the GitHub "Releases" page and double-click it to install it into Stream Deck.


Expand Down
184 changes: 104 additions & 80 deletions StreamDeckSimHub.Plugin/Actions/FlagsAction.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// Copyright (C) 2023 Martin Renner
// Copyright (C) 2024 Martin Renner
// LGPL-3.0-or-later (see file COPYING and COPYING.LESSER)

using Microsoft.Extensions.Logging;
using SharpDeck;
using SharpDeck.Events.Received;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using StreamDeckSimHub.Plugin.SimHub;
using StreamDeckSimHub.Plugin.Tools;

Expand All @@ -14,13 +16,13 @@ namespace StreamDeckSimHub.Plugin.Actions;
/// </summary>
internal class FlagState
{
internal bool black;
internal bool blue;
internal bool checkered;
internal bool green;
internal bool orange;
internal bool white;
internal bool yellow;
internal bool Black;
internal bool Blue;
internal bool Checkered;
internal bool Green;
internal bool Orange;
internal bool White;
internal bool Yellow;
}

/// <summary>
Expand All @@ -32,52 +34,55 @@ public class FlagsAction : StreamDeckAction<FlagsSettings>
private readonly SimHubConnection _simHubConnection;
private readonly ImageManager _imageManager;
private readonly IPropertyChangedReceiver _propertyChangedReceiver;
private DeviceInfo? _deviceInfo;
private StreamDeckKeyInfo? _sdKeyInfo;
private bool _gameRunning;
private FlagState _flagState = new();
private readonly string _noFlag;
private readonly string _blackFlag;
private readonly string _blueFlag;
private readonly string _checkeredFlag;
private readonly string _greenFlag;
private readonly string _orangeFlag;
private readonly string _whiteFlag;
private readonly string _yellowFlag;
private Image _noFlag;
private Image _blackFlag;
private Image _blueFlag;
private Image _checkeredFlag;
private Image _greenFlag;
private Image _orangeFlag;
private Image _whiteFlag;
private Image _yellowFlag;

public FlagsAction(SimHubConnection simHubConnection, ImageUtils imageUtils, ImageManager imageManager)
{
_simHubConnection = simHubConnection;
_imageManager = imageManager;
_propertyChangedReceiver = new PropertyChangedDelegate(PropertyChanged);

_noFlag = imageUtils.EncodeSvg("<svg viewBox=\"0 0 70 70\" />");
_blackFlag = imageUtils.LoadSvg("images/icons/flag-black.svg");
_blueFlag = imageUtils.LoadSvg("images/icons/flag-blue.svg");
_checkeredFlag = imageUtils.LoadSvg("images/icons/flag-checkered.svg");
_greenFlag = imageUtils.LoadSvg("images/icons/flag-green.svg");
_orangeFlag = imageUtils.LoadSvg("images/icons/flag-orange.svg");
_whiteFlag = imageUtils.LoadSvg("images/icons/flag-white.svg");
_yellowFlag = imageUtils.LoadSvg("images/icons/flag-yellow.svg");
_noFlag = imageUtils.GetEmptyImage();
_blackFlag = imageUtils.GetEmptyImage();
_blueFlag = imageUtils.GetEmptyImage();
_checkeredFlag = imageUtils.GetEmptyImage();
_greenFlag = imageUtils.GetEmptyImage();
_orangeFlag = imageUtils.GetEmptyImage();
_whiteFlag = imageUtils.GetEmptyImage();
_yellowFlag = imageUtils.GetEmptyImage();
}

protected override async Task OnWillAppear(ActionEventArgs<AppearancePayload> args)
{
var settings = args.Payload.GetSettings<FlagsSettings>();
Logger.LogInformation("OnWillAppear ({coords}): {settings}", args.Payload.Coordinates, settings);

_deviceInfo = StreamDeck.Info.Devices.FirstOrDefault(deviceInfo => deviceInfo.Id == args.Device);
_sdKeyInfo = StreamDeckKeyInfoBuilder.Build(StreamDeck.Info, args.Device, args.Payload.Controller);
PopulateImages(settings, _sdKeyInfo);

var checkeredFlag = _imageManager.GetCustomImageEncoded(settings.CheckeredFlag, _deviceInfo);
await SetImageAsync(checkeredFlag);
await SetImageAsync(_checkeredFlag.ToBase64String(PngFormat.Instance));

await _simHubConnection.Subscribe("dcp.GameRunning", _propertyChangedReceiver);
await _simHubConnection.Subscribe("dcp.gd.Flag_Black", _propertyChangedReceiver);
await _simHubConnection.Subscribe("dcp.gd.Flag_Blue", _propertyChangedReceiver);
await _simHubConnection.Subscribe("dcp.gd.Flag_Checkered", _propertyChangedReceiver);
await _simHubConnection.Subscribe("dcp.gd.Flag_Green", _propertyChangedReceiver);
await _simHubConnection.Subscribe("dcp.gd.Flag_Orange", _propertyChangedReceiver);
await _simHubConnection.Subscribe("dcp.gd.Flag_White", _propertyChangedReceiver);
await _simHubConnection.Subscribe("dcp.gd.Flag_Yellow", _propertyChangedReceiver);
await _simHubConnection.Subscribe("DataCorePlugin.GameRunning", _propertyChangedReceiver);
await _simHubConnection.Subscribe("DataCorePlugin.GameData.Flag_Black", _propertyChangedReceiver);
await _simHubConnection.Subscribe("DataCorePlugin.GameData.Flag_Blue", _propertyChangedReceiver);
await _simHubConnection.Subscribe("DataCorePlugin.GameData.Flag_Checkered", _propertyChangedReceiver);
await _simHubConnection.Subscribe("DataCorePlugin.GameData.Flag_Green", _propertyChangedReceiver);
await _simHubConnection.Subscribe("DataCorePlugin.GameData.Flag_Orange", _propertyChangedReceiver);
await _simHubConnection.Subscribe("DataCorePlugin.GameData.Flag_White", _propertyChangedReceiver);
await _simHubConnection.Subscribe("DataCorePlugin.GameData.Flag_Yellow", _propertyChangedReceiver);
await _simHubConnection.Subscribe("DataCorePlugin.GameRawData.Graphics.globalYellow1", _propertyChangedReceiver);
await _simHubConnection.Subscribe("DataCorePlugin.GameRawData.Graphics.globalYellow2", _propertyChangedReceiver);
await _simHubConnection.Subscribe("DataCorePlugin.GameRawData.Graphics.globalYellow3", _propertyChangedReceiver);

await base.OnWillAppear(args);
}
Expand All @@ -86,24 +91,30 @@ protected override async Task OnWillDisappear(ActionEventArgs<AppearancePayload>
{
Logger.LogInformation("OnWillDisappear ({coords}): {settings}", args.Payload.Coordinates, args.Payload.GetSettings<DialActionSettings>());

await _simHubConnection.Unsubscribe("dcp.GameRunning", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("dcp.gd.Flag_Black", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("dcp.gd.Flag_Blue", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("dcp.gd.Flag_Checkered", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("dcp.gd.Flag_Green", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("dcp.gd.Flag_Orange", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("dcp.gd.Flag_White", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("dcp.gd.Flag_Yellow", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("DataCorePlugin.GameRunning", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("DataCorePlugin.GameData.Flag_Black", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("DataCorePlugin.GameData.Flag_Blue", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("DataCorePlugin.GameData.Flag_Checkered", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("DataCorePlugin.GameData.Flag_Green", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("DataCorePlugin.GameData.Flag_Orange", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("DataCorePlugin.GameData.Flag_White", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("DataCorePlugin.GameData.Flag_Yellow", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("DataCorePlugin.GameRawData.Graphics.globalYellow1", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("DataCorePlugin.GameRawData.Graphics.globalYellow2", _propertyChangedReceiver);
await _simHubConnection.Unsubscribe("DataCorePlugin.GameRawData.Graphics.globalYellow3", _propertyChangedReceiver);

await SetImageAsync(_checkeredFlag);
await SetImageAsync(_checkeredFlag.ToBase64String(PngFormat.Instance));

await base.OnWillAppear(args);
}

protected override async Task OnDidReceiveSettings(ActionEventArgs<ActionPayload> args, FlagsSettings settings)
{
Logger.LogInformation("OnDidReceiveSettings ({coords}): {settings}", args.Payload.Coordinates, settings);
// TODO load images from settings

PopulateImages(settings, _sdKeyInfo!);

await SetImageAsync(_checkeredFlag.ToBase64String(PngFormat.Instance));

await base.OnDidReceiveSettings(args, settings);
}
Expand All @@ -121,76 +132,89 @@ protected override async Task OnPropertyInspectorDidAppear(ActionEventArgs args)
/// </summary>
private async Task PropertyChanged(PropertyChangedArgs args)
{
if (args.PropertyName == "dcp.GameRunning")
if (args.PropertyName == "DataCorePlugin.GameRunning")
{
_gameRunning = Equals(args.PropertyValue, true);
_gameRunning = Equals(args.PropertyValue, 1);
}

if (!_gameRunning)
{
// game not running, show checked flag as placeholder
_flagState = new();
await SetImageAsync(_checkeredFlag);
_flagState = new FlagState();
await SetImageAsync(_checkeredFlag.ToBase64String(PngFormat.Instance));
return;
}


switch (args.PropertyName)
{
case "dcp.gd.Flag_Black":
_flagState.black = Equals(args.PropertyValue, 1);
case "DataCorePlugin.GameData.Flag_Black":
_flagState.Black = Equals(args.PropertyValue, 1);
break;
case "dcp.gd.Flag_Blue":
_flagState.blue = Equals(args.PropertyValue, 1);
case "DataCorePlugin.GameData.Flag_Blue":
_flagState.Blue = Equals(args.PropertyValue, 1);
break;
case "dcp.gd.Flag_Checkered":
_flagState.checkered = Equals(args.PropertyValue, 1);
case "DataCorePlugin.GameData.Flag_Checkered":
_flagState.Checkered = Equals(args.PropertyValue, 1);
break;
case "dcp.gd.Flag_Green":
_flagState.green = Equals(args.PropertyValue, 1);
case "DataCorePlugin.GameData.Flag_Green":
_flagState.Green = Equals(args.PropertyValue, 1);
break;
case "dcp.gd.Flag_Orange":
_flagState.orange = Equals(args.PropertyValue, 1);
case "DataCorePlugin.GameData.Flag_Orange":
_flagState.Orange = Equals(args.PropertyValue, 1);
break;
case "dcp.gd.Flag_White":
_flagState.white = Equals(args.PropertyValue, 1);
case "DataCorePlugin.GameData.Flag_White":
_flagState.White = Equals(args.PropertyValue, 1);
break;
case "dcp.gd.Flag_Yellow":
_flagState.yellow = Equals(args.PropertyValue, 1);
case "DataCorePlugin.GameData.Flag_Yellow":
_flagState.Yellow = Equals(args.PropertyValue, 1);
break;
}

if (_flagState.black)
// "Green" must be after other flags, because several flags can be "on" in the same time. We want to have
// "Green" after "Yellow".
if (_flagState.Black)
{
await SetImageAsync(_blackFlag);
await SetImageAsync(_blackFlag.ToBase64String(PngFormat.Instance));
}
else if (_flagState.blue)
else if (_flagState.Blue)
{
await SetImageAsync(_blueFlag);
await SetImageAsync(_blueFlag.ToBase64String(PngFormat.Instance));
}
else if (_flagState.checkered)
else if (_flagState.Checkered)
{
await SetImageAsync(_checkeredFlag);
await SetImageAsync(_checkeredFlag.ToBase64String(PngFormat.Instance));
}
else if (_flagState.green)
else if (_flagState.Orange)
{
await SetImageAsync(_greenFlag);
await SetImageAsync(_orangeFlag.ToBase64String(PngFormat.Instance));
}
else if (_flagState.orange)
else if (_flagState.White)
{
await SetImageAsync(_orangeFlag);
await SetImageAsync(_whiteFlag.ToBase64String(PngFormat.Instance));
}
else if (_flagState.white)
else if (_flagState.Yellow)
{
await SetImageAsync(_whiteFlag);
await SetImageAsync(_yellowFlag.ToBase64String(PngFormat.Instance));
}
else if (_flagState.yellow)
else if (_flagState.Green)
{
await SetImageAsync(_yellowFlag);
await SetImageAsync(_greenFlag.ToBase64String(PngFormat.Instance));
}
else
{
await SetImageAsync(_noFlag);
await SetImageAsync(_noFlag.ToBase64String(PngFormat.Instance));
}
}

private void PopulateImages(FlagsSettings settings, StreamDeckKeyInfo sdKeyInfo)
{
_noFlag = _imageManager.GetCustomImage(settings.NoFlag, sdKeyInfo);
_blackFlag = _imageManager.GetCustomImage(settings.BlackFlag, sdKeyInfo);
_blueFlag = _imageManager.GetCustomImage(settings.BlueFlag, sdKeyInfo);
_checkeredFlag = _imageManager.GetCustomImage(settings.CheckeredFlag, sdKeyInfo);
_greenFlag = _imageManager.GetCustomImage(settings.GreenFlag, sdKeyInfo);
_orangeFlag = _imageManager.GetCustomImage(settings.OrangeFlag, sdKeyInfo);
_whiteFlag = _imageManager.GetCustomImage(settings.WhiteFlag, sdKeyInfo);
_yellowFlag = _imageManager.GetCustomImage(settings.YellowFlag, sdKeyInfo);
}
}
17 changes: 12 additions & 5 deletions StreamDeckSimHub.Plugin/StreamDeckSimHub.Plugin.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<PublishSingleFile>false</PublishSingleFile>
<SelfContained>true</SelfContained>
<TargetFramework>net8.0</TargetFramework>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>false</SelfContained>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>StreamDeckSimHub</AssemblyName>
<LangVersion>11</LangVersion>
<LangVersion>12</LangVersion>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>embedded</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>embedded</DebugType>
</PropertyGroup>

<ItemGroup>
Expand All @@ -18,7 +25,7 @@
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.3.2" />
<PackageReference Include="NLog" Version="5.3.3" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.10" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.4" />
<PackageReference Include="Svg.Skia" Version="2.0.0.1" />
Expand Down
Loading

0 comments on commit 0b073fa

Please sign in to comment.