Device visualizer - Added support for rotation and scale

Profile editor - Fixed keyframe context menu actions
This commit is contained in:
SpoinkyNL committed 2020-06-22 17:43:04 +02:00
1 parent 6504c621c6
commit 35944e064d
15 files changed
+185 -78

No files matched your search

@@ -1,16 +1,15 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Artemis.Core.Models.Surface;
using RGB.NET.Core;
using Point = System.Windows.Point;
using Size = System.Windows.Size;
namespace Artemis.UI.Shared.Controls
{
@@ -29,6 +28,7 @@ namespace Artemis.UI.Shared.Controls
private readonly List<DeviceVisualizerLed> _deviceVisualizerLeds;
private BitmapImage _deviceImage;
private bool _subscribed;
private ArtemisDevice _oldDevice;
public DeviceVisualizer()
{
@@ -38,7 +38,7 @@ namespace Artemis.UI.Shared.Controls
Loaded += (sender, args) => SubscribeToUpdate(true);
Unloaded += (sender, args) => SubscribeToUpdate(false);
}
public ArtemisDevice Device
{
get => (ArtemisDevice) GetValue(DeviceProperty);
@@ -68,9 +68,10 @@ namespace Artemis.UI.Shared.Controls
return;
// Determine the scale required to fit the desired size of the control
var scale = Math.Min(DesiredSize.Width / Device.RgbDevice.Size.Width, DesiredSize.Height / Device.RgbDevice.Size.Height);
var scaledRect = new Rect(0, 0, Device.RgbDevice.Size.Width * scale, Device.RgbDevice.Size.Height * scale);
var measureSize = MeasureOverride(Size.Empty);
var scale = Math.Min(DesiredSize.Width / measureSize.Width, DesiredSize.Height / measureSize.Height);
var scaledRect = new Rect(0, 0, measureSize.Width * scale, measureSize.Height * scale);
// Center and scale the visualization in the desired bounding box
if (DesiredSize.Width > 0 && DesiredSize.Height > 0)
{
@@ -78,16 +79,45 @@ namespace Artemis.UI.Shared.Controls
drawingContext.PushTransform(new ScaleTransform(scale, scale));
}
// Determine the offset required to rotate within bounds
var rotationRect = new Rect(0, 0, Device.RgbDevice.ActualSize.Width, Device.RgbDevice.ActualSize.Height);
rotationRect.Transform(new RotateTransform(Device.Rotation).Value);
// Apply device rotation
drawingContext.PushTransform(new TranslateTransform(0 - rotationRect.Left, 0 - rotationRect.Top));
drawingContext.PushTransform(new RotateTransform(Device.Rotation));
// Apply device scale
drawingContext.PushTransform(new ScaleTransform(Device.Scale, Device.Scale));
// Render device and LED images
if (_deviceImage != null)
drawingContext.DrawImage(_deviceImage, new Rect(0, 0, Device.RgbDevice.Size.Width, Device.RgbDevice.Size.Height));
foreach (var deviceVisualizerLed in _deviceVisualizerLeds)
deviceVisualizerLed.RenderImage(drawingContext);
drawingContext.DrawDrawing(_backingStore);
}
protected override Size MeasureOverride(Size availableSize)
{
if (Device == null)
return Size.Empty;
var rotationRect = new Rect(0, 0, Device.RgbDevice.ActualSize.Width, Device.RgbDevice.ActualSize.Height);
rotationRect.Transform(new RotateTransform(Device.Rotation).Value);
return rotationRect.Size;
}
private void UpdateTransform()
{
InvalidateVisual();
InvalidateMeasure();
}
private void SubscribeToUpdate(bool subscribe)
{
if (_subscribed == subscribe)
@@ -121,6 +151,13 @@ namespace Artemis.UI.Shared.Controls
if (Device == null)
return;
if (_oldDevice != null)
Device.RgbDevice.PropertyChanged -= DevicePropertyChanged;
_oldDevice = Device;
Device.RgbDevice.PropertyChanged += DevicePropertyChanged;
UpdateTransform();
// Load the device main image
if (Device.RgbDevice?.DeviceInfo?.Image?.AbsolutePath != null && File.Exists(Device.RgbDevice.DeviceInfo.Image.AbsolutePath))
_deviceImage = new BitmapImage(Device.RgbDevice.DeviceInfo.Image);
@@ -130,7 +167,10 @@ namespace Artemis.UI.Shared.Controls
_deviceVisualizerLeds.Add(new DeviceVisualizerLed(artemisLed));
if (!ShowColors)
{
InvalidateMeasure();
return;
}
// Create the opacity drawing group
var opacityDrawingGroup = new DrawingGroup();
@@ -157,6 +197,14 @@ namespace Artemis.UI.Shared.Controls
var bitmapBrush = new ImageBrush(bitmap);
bitmapBrush.Freeze();
_backingStore.OpacityMask = bitmapBrush;
InvalidateMeasure();
}
private void DevicePropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Device.RgbDevice.Scale) || e.PropertyName == nameof(Device.RgbDevice.Rotation))
UpdateTransform();
}
private void RgbSurfaceOnUpdated(UpdatedEventArgs e)
@@ -13,12 +13,14 @@ namespace Artemis.UI.Shared.Controls
{
public DeviceVisualizerLed(ArtemisLed led)
{
if (led.Device.Scale != 1)
Console.WriteLine();
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
Led.RgbLed.Location.X,
Led.RgbLed.Location.Y,
Led.RgbLed.Size.Width,
Led.RgbLed.Size.Height
);
if (Led.RgbLed.Image != null && File.Exists(Led.RgbLed.Image.AbsolutePath))
@@ -97,7 +99,7 @@ namespace Artemis.UI.Shared.Controls
}
// Stroke geometry is the display geometry excluding the inner geometry
DisplayGeometry.Transform = new TranslateTransform(Led.RgbLed.LedRectangle.Location.X, Led.RgbLed.LedRectangle.Location.Y);
DisplayGeometry.Transform = new TranslateTransform(Led.RgbLed.Location.X, Led.RgbLed.Location.Y);
// Try to gain some performance
DisplayGeometry.Freeze();
}
@@ -12,7 +12,7 @@
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource MaterialDesignValidationErrorTemplate}" />
</Style>
</UserControl.Style>
<StackPanel>
<Grid>
<!-- Drag handle -->
<Border x:Name="DragHandle" BorderThickness="0,0,0,1" Height="19">
<Border.BorderBrush>
@@ -28,8 +28,8 @@
<TextBlock Style="{x:Null}"
Width="60"
Height="17"
Padding="1 0"
Margin="0 4 0 0"
Padding="2 0"
Margin="0 3 0 0"
Text="{Binding Value, StringFormat=N3, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
Cursor="/Resources/Cursors/aero_drag_ew.cur"
Foreground="{DynamicResource SecondaryAccentBrush}"
@@ -42,11 +42,13 @@
<!-- Input -->
<TextBox x:Name="Input"
Width="60"
Height="20"
Height="21"
Padding="0 0 -2 0"
HorizontalAlignment="Left"
Text="{Binding Value, StringFormat=N3, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
LostFocus="InputLostFocus"
KeyDown="InputKeyDown"
Visibility="Collapsed"
RequestBringIntoView="Input_OnRequestBringIntoView" />
</StackPanel>
</Grid>
</UserControl>