using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using System; using System.Collections.Generic; namespace OpenMacroBoard.SDK { /// /// Macro board adapter that implements a software button press effect. /// /// /// This vaguely mimics the perspective of a real button being pushed /// and provides better feedback to the user that a button push was registered. /// public class ButtonPressEffectAdapter : MacroBoardAdapter { private readonly Dictionary mostRecentKeyBitmaps = new(); private readonly Dictionary keyPressedState = new(); /// /// Initializes a new instance of the class. /// /// The this effect should be applied to. public ButtonPressEffectAdapter(IMacroBoard macroBoard) : this(macroBoard, null) { } /// /// Initializes a new instance of the class. /// /// The board that is wrapped with the button press effect. /// The configuration that should be used. If null the default configuration will be used. public ButtonPressEffectAdapter(IMacroBoard macroBoard, ButtonPressEffectConfig config) : base(macroBoard) { this.ButtonPressed += this.ButtonPressEffectAdapter_ButtonPressed; this.ButtonReleased += this.ButtonPressEffectAdapter_ButtonReleased; //KeyStateChanged += SoftwareButtonFeature_KeyStateChanged; Config = config ?? new ButtonPressEffectConfig(); } private void ButtonPressEffectAdapter_ButtonReleased(Object sender, KeyPressEvent e) { this.keyPressedState[e.Key] = false; this.UpdateKeyBitmap(e.Key); } private void ButtonPressEffectAdapter_ButtonPressed(Object sender, KeyPressEvent e) { this.keyPressedState[e.Key] = true; this.UpdateKeyBitmap(e.Key); } /// /// The configuration that controls the behavior of the button press effect feature. /// public ButtonPressEffectConfig Config { get; } /// public override void SetButtonImage(int keyId, KeyBitmap bitmapData) { mostRecentKeyBitmaps[keyId] = bitmapData; UpdateKeyBitmap(keyId); } private void UpdateKeyBitmap(int keyId) { var bitmap = GetBitmapForKey(keyId); if(bitmap != null) { base.SetButtonImage(keyId, bitmap); } } private bool IsKeyPressed(int keyId) { if(keyPressedState.TryGetValue(keyId, out var keyPressed)) { return keyPressed; } return false; } private KeyBitmap GetBitmapForKey(int keyId) { if(!mostRecentKeyBitmaps.TryGetValue(keyId, out var bitmap)) { return null; } return IsKeyPressed(keyId) ? ResizeBitmap(bitmap) : bitmap; } private KeyBitmap ResizeBitmap(KeyBitmap keyBitmap) { var bitmapDataAccess = (IKeyBitmapDataAccess)keyBitmap; if(bitmapDataAccess.IsEmpty) { return KeyBitmap.Black; } var targetWidth = (int)Math.Round(Config.Scale * keyBitmap.Width); var targetHeight = (int)Math.Round(Config.Scale * keyBitmap.Height); var smallerImage = bitmapDataAccess.ToImage(); smallerImage.Mutate(x => x.Resize(targetWidth, targetHeight)); var offsetLeft = (int)Math.Round((keyBitmap.Width - targetWidth) * Config.OriginX); var offsetTop = (int)Math.Round((keyBitmap.Height - targetHeight) * Config.OriginY); var color = Color.FromPixel(new Rgb24( Config.BackgroundColor.R, Config.BackgroundColor.G, Config.BackgroundColor.B) ); var newImage = new Image(keyBitmap.Width, keyBitmap.Height); newImage.Mutate(x => { x.BackgroundColor(color); x.DrawImage(smallerImage, new Point(offsetLeft, offsetTop), 1); }); return KeyBitmap.Create.FromImageSharpImage(newImage); } } }