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);
}
}
}