diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs index e0b981cff..918cfdbab 100644 --- a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs +++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Windows; +using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; using Artemis.Core.Models.Surface; @@ -15,29 +16,20 @@ namespace Artemis.UI.Shared.Controls new FrameworkPropertyMetadata(default(ArtemisDevice), FrameworkPropertyMetadataOptions.AffectsRender, DevicePropertyChangedCallback)); public static readonly DependencyProperty ShowColorsProperty = DependencyProperty.Register(nameof(ShowColors), typeof(bool), typeof(DeviceVisualizer), - new FrameworkPropertyMetadata(default(bool), FrameworkPropertyMetadataOptions.AffectsRender)); + new FrameworkPropertyMetadata(default(bool), FrameworkPropertyMetadataOptions.AffectsRender, ShowColorsPropertyChangedCallback)); private readonly DrawingGroup _backingStore; private readonly List _deviceVisualizerLeds; private BitmapImage _deviceImage; - private RGBSurface _subscribedSurface; public DeviceVisualizer() { _backingStore = new DrawingGroup(); _deviceVisualizerLeds = new List(); + SubscribeToSurfaceUpdate(); Unloaded += (sender, args) => Dispose(); } - - public void Dispose() - { - if (_subscribedSurface != null) - { - _subscribedSurface.Updated -= RgbSurfaceOnUpdated; - _subscribedSurface = null; - } - } public ArtemisDevice Device { @@ -51,6 +43,11 @@ namespace Artemis.UI.Shared.Controls set => SetValue(ShowColorsProperty, value); } + public void Dispose() + { + RGBSurface.Instance.Updated -= RgbSurfaceOnUpdated; + } + protected override void OnRender(DrawingContext drawingContext) { if (Device == null) @@ -72,7 +69,7 @@ namespace Artemis.UI.Shared.Controls drawingContext.DrawImage(_deviceImage, new Rect(0, 0, Device.RgbDevice.Size.Width, Device.RgbDevice.Size.Height)); foreach (var deviceVisualizerLed in _deviceVisualizerLeds) - deviceVisualizerLed.Render(drawingContext, false); + deviceVisualizerLed.RenderImage(drawingContext); drawingContext.DrawDrawing(_backingStore); } @@ -80,15 +77,16 @@ namespace Artemis.UI.Shared.Controls private static void DevicePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { var deviceVisualizer = (DeviceVisualizer) d; - deviceVisualizer.Dispatcher.Invoke(() => - { - deviceVisualizer.SubscribeToSurfaceUpdate((ArtemisDevice) e.NewValue); - deviceVisualizer.Initialize(); - }); + deviceVisualizer.Dispatcher.Invoke(() => { deviceVisualizer.SetupForDevice(); }); } + private static void ShowColorsPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var deviceVisualizer = (DeviceVisualizer) d; + deviceVisualizer.Dispatcher.Invoke(() => { deviceVisualizer.SetupForDevice(); }); + } - private void Initialize() + private void SetupForDevice() { _deviceImage = null; _deviceVisualizerLeds.Clear(); @@ -101,29 +99,50 @@ namespace Artemis.UI.Shared.Controls _deviceImage = new BitmapImage(Device.RgbDevice.DeviceInfo.Image); // Create all the LEDs - foreach (var artemisLed in Device.Leds) _deviceVisualizerLeds.Add(new DeviceVisualizerLed(artemisLed)); - } + foreach (var artemisLed in Device.Leds) + _deviceVisualizerLeds.Add(new DeviceVisualizerLed(artemisLed)); - private void SubscribeToSurfaceUpdate(ArtemisDevice newValue) - { - if (newValue.Surface.RgbSurface == _subscribedSurface) + if (!ShowColors) return; - // Remove subscription from old surface - if (_subscribedSurface != null) - _subscribedSurface.Updated -= RgbSurfaceOnUpdated; - // Subscribe to new surface - if (newValue.Surface.RgbSurface != null) - newValue.Surface.RgbSurface.Updated += RgbSurfaceOnUpdated; + // Create the opacity drawing group + var opacityDrawingGroup = new DrawingGroup(); + var drawingContext = opacityDrawingGroup.Open(); + foreach (var deviceVisualizerLed in _deviceVisualizerLeds) + deviceVisualizerLed.RenderOpacityMask(drawingContext); + drawingContext.Close(); - _subscribedSurface = newValue.Surface.RgbSurface; + // Render the store as a bitmap + var drawingImage = new DrawingImage(opacityDrawingGroup); + var image = new Image {Source = drawingImage}; + var bitmap = new RenderTargetBitmap( + (int) (opacityDrawingGroup.Bounds.Width * 2.5), + (int) (opacityDrawingGroup.Bounds.Height * 2.5), + 96, + 96, + PixelFormats.Pbgra32 + ); + image.Arrange(new Rect(0, 0, bitmap.Width, bitmap.Height)); + bitmap.Render(image); + bitmap.Freeze(); + + // Set the bitmap as the opacity mask for the colors backing store + var bitmapBrush = new ImageBrush(bitmap); + bitmapBrush.Freeze(); + _backingStore.OpacityMask = bitmapBrush; + } + + private void SubscribeToSurfaceUpdate() + { + RGBSurface.Instance.Updated += RgbSurfaceOnUpdated; } private void RgbSurfaceOnUpdated(UpdatedEventArgs e) { Dispatcher.Invoke(() => { - if (ShowColors) Render(); + if (ShowColors && Visibility == Visibility.Visible) + Render(); }); } @@ -132,7 +151,7 @@ namespace Artemis.UI.Shared.Controls var drawingContext = _backingStore.Open(); foreach (var deviceVisualizerLed in _deviceVisualizerLeds) - deviceVisualizerLed.Render(drawingContext, true); + deviceVisualizerLed.RenderColor(drawingContext); drawingContext.Close(); } diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs index 68274afad..215e97366 100644 --- a/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs +++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs @@ -14,24 +14,26 @@ namespace Artemis.UI.Shared.Controls public DeviceVisualizerLed(ArtemisLed led) { Led = led; + LedRect = new Rect( + Led.RgbLed.LedRectangle.Location.X, + Led.RgbLed.LedRectangle.Location.Y, + Led.RgbLed.LedRectangle.Size.Width, + Led.RgbLed.LedRectangle.Size.Height + ); + if (Led.RgbLed.Image != null && File.Exists(Led.RgbLed.Image.AbsolutePath)) LedImage = new BitmapImage(Led.RgbLed.Image); + CreateLedGeometry(); } + public ArtemisLed Led { get; } + public Rect LedRect { get; set; } public BitmapImage LedImage { get; set; } public Geometry DisplayGeometry { get; private set; } - internal void Render(DrawingContext drawingContext, bool renderGeometry) - { - if (!renderGeometry) - RenderImage(drawingContext); - else - RenderGeometry(drawingContext); - } - private void CreateLedGeometry() { switch (Led.RgbLed.Shape) @@ -101,7 +103,7 @@ namespace Artemis.UI.Shared.Controls } } - private void RenderGeometry(DrawingContext drawingContext) + public void RenderColor(DrawingContext drawingContext) { if (DisplayGeometry == null) return; @@ -109,27 +111,29 @@ namespace Artemis.UI.Shared.Controls var r = Led.RgbLed.Color.GetR(); var g = Led.RgbLed.Color.GetG(); var b = Led.RgbLed.Color.GetB(); - - var fillBrush = new SolidColorBrush(Color.FromArgb(100, r,g,b)); - fillBrush.Freeze(); - var penBrush = new SolidColorBrush(Color.FromArgb(255, r, g, b)); - penBrush.Freeze(); - - drawingContext.DrawGeometry(fillBrush, new Pen(penBrush, 1), DisplayGeometry); + + drawingContext.DrawRectangle(new SolidColorBrush(Color.FromRgb(r, g, b)), null, LedRect); } - private void RenderImage(DrawingContext drawingContext) + public void RenderImage(DrawingContext drawingContext) { if (LedImage == null) return; - var ledRect = new Rect( - Led.RgbLed.LedRectangle.Location.X, - Led.RgbLed.LedRectangle.Location.Y, - Led.RgbLed.LedRectangle.Size.Width, - Led.RgbLed.LedRectangle.Size.Height - ); - drawingContext.DrawImage(LedImage, ledRect); + drawingContext.DrawImage(LedImage, LedRect); + } + + public void RenderOpacityMask(DrawingContext drawingContext) + { + if (DisplayGeometry == null) + return; + + var fillBrush = new SolidColorBrush(Color.FromArgb(100, 255, 255, 255)); + fillBrush.Freeze(); + var penBrush = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)); + penBrush.Freeze(); + + drawingContext.DrawGeometry(fillBrush, new Pen(penBrush, 1), DisplayGeometry); } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml index e14c5feca..2e4c4a4a7 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml @@ -173,7 +173,7 @@ d.ZIndex)); } private void UpdateLedsDimStatus() diff --git a/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs b/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs index 0b2e4d82e..fc2c15e17 100644 --- a/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs +++ b/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs @@ -40,8 +40,8 @@ namespace Artemis.UI.Screens.Shared else Zoom *= 0.9; - // Limit to a min of 0.1 and a max of 4 (10% - 400% in the view) - Zoom = Math.Max(0.1, Math.Min(4, Zoom)); + // Limit to a min of 0.1 and a max of 2.5 (10% - 250% in the view) + Zoom = Math.Max(0.1, Math.Min(2.5, Zoom)); // Update the PanX/Y to enable zooming relative to cursor if (LimitToZero) diff --git a/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml b/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml index 1c82952f3..b30e2916f 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml +++ b/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml @@ -26,7 +26,7 @@ - +