1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

UI - Performance improvements

This commit is contained in:
Robert 2021-09-04 20:52:03 +02:00
parent 7ad7eaad89
commit 13a16a1830
9 changed files with 165 additions and 135 deletions

View File

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel; using System.ComponentModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -9,15 +11,15 @@ using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Artemis.Core; using Artemis.Core;
using Stylet;
namespace Artemis.UI.Shared namespace Artemis.UI.Shared
{ {
/// <summary> /// <summary>
/// Visualizes an <see cref="ArtemisDevice" /> with optional per-LED colors /// Visualizes an <see cref="ArtemisDevice" /> with optional per-LED colors
/// </summary> /// </summary>
public class DeviceVisualizer : FrameworkElement, IDisposable public class DeviceVisualizer : FrameworkElement
{ {
/// <summary> /// <summary>
/// The device to visualize /// The device to visualize
@ -34,14 +36,16 @@ namespace Artemis.UI.Shared
/// <summary> /// <summary>
/// A list of LEDs to highlight /// A list of LEDs to highlight
/// </summary> /// </summary>
public static readonly DependencyProperty HighlightedLedsProperty = DependencyProperty.Register(nameof(HighlightedLeds), typeof(IEnumerable<ArtemisLed>), typeof(DeviceVisualizer), public static readonly DependencyProperty HighlightedLedsProperty = DependencyProperty.Register(nameof(HighlightedLeds), typeof(ObservableCollection<ArtemisLed>), typeof(DeviceVisualizer),
new FrameworkPropertyMetadata(default(IEnumerable<ArtemisLed>))); new FrameworkPropertyMetadata(default(ObservableCollection<ArtemisLed>), HighlightedLedsPropertyChanged));
private readonly DrawingGroup _backingStore; private readonly DrawingGroup _backingStore;
private readonly List<DeviceVisualizerLed> _deviceVisualizerLeds; private readonly List<DeviceVisualizerLed> _deviceVisualizerLeds;
private readonly Timer _timer; private readonly DispatcherTimer _timer;
private BitmapImage? _deviceImage; private BitmapImage? _deviceImage;
private ArtemisDevice? _oldDevice; private ArtemisDevice? _oldDevice;
private List<DeviceVisualizerLed> _highlightedLeds;
private List<DeviceVisualizerLed> _dimmedLeds;
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="DeviceVisualizer" /> class /// Creates a new instance of the <see cref="DeviceVisualizer" /> class
@ -50,9 +54,10 @@ namespace Artemis.UI.Shared
{ {
_backingStore = new DrawingGroup(); _backingStore = new DrawingGroup();
_deviceVisualizerLeds = new List<DeviceVisualizerLed>(); _deviceVisualizerLeds = new List<DeviceVisualizerLed>();
_dimmedLeds = new List<DeviceVisualizerLed>();
// Run an update timer at 25 fps // Run an update timer at 25 fps
_timer = new Timer(40); _timer = new DispatcherTimer(DispatcherPriority.Render) {Interval = TimeSpan.FromMilliseconds(40)};
MouseLeftButtonUp += OnMouseLeftButtonUp; MouseLeftButtonUp += OnMouseLeftButtonUp;
Loaded += OnLoaded; Loaded += OnLoaded;
@ -80,9 +85,9 @@ namespace Artemis.UI.Shared
/// <summary> /// <summary>
/// Gets or sets a list of LEDs to highlight /// Gets or sets a list of LEDs to highlight
/// </summary> /// </summary>
public IEnumerable<ArtemisLed>? HighlightedLeds public ObservableCollection<ArtemisLed>? HighlightedLeds
{ {
get => (IEnumerable<ArtemisLed>) GetValue(HighlightedLedsProperty); get => (ObservableCollection<ArtemisLed>) GetValue(HighlightedLedsProperty);
set => SetValue(HighlightedLedsProperty, value); set => SetValue(HighlightedLedsProperty, value);
} }
@ -158,10 +163,9 @@ namespace Artemis.UI.Shared
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
if (disposing) if (disposing)
_timer.Dispose(); _timer.Stop();
} }
private static Size ResizeKeepAspect(Size src, double maxWidth, double maxHeight) private static Size ResizeKeepAspect(Size src, double maxWidth, double maxHeight)
{ {
double scale; double scale;
@ -191,8 +195,10 @@ namespace Artemis.UI.Shared
private void OnUnloaded(object? sender, RoutedEventArgs e) private void OnUnloaded(object? sender, RoutedEventArgs e)
{ {
_timer.Stop(); _timer.Stop();
_timer.Elapsed -= TimerOnTick; _timer.Tick -= TimerOnTick;
if (HighlightedLeds != null)
HighlightedLeds.CollectionChanged -= HighlightedLedsChanged;
if (_oldDevice != null) if (_oldDevice != null)
{ {
if (Device != null) if (Device != null)
@ -223,16 +229,34 @@ namespace Artemis.UI.Shared
private void OnLoaded(object? sender, RoutedEventArgs e) private void OnLoaded(object? sender, RoutedEventArgs e)
{ {
_timer.Start(); _timer.Start();
_timer.Elapsed += TimerOnTick; _timer.Tick += TimerOnTick;
} }
private void TimerOnTick(object? sender, EventArgs e) private void TimerOnTick(object? sender, EventArgs e)
{ {
Execute.PostToUIThread(() => if (ShowColors && Visibility == Visibility.Visible)
Render();
}
private void Render()
{
DrawingContext drawingContext = _backingStore.Append();
if (_highlightedLeds.Any())
{ {
if (ShowColors && Visibility == Visibility.Visible) foreach (DeviceVisualizerLed deviceVisualizerLed in _highlightedLeds)
Render(); deviceVisualizerLed.RenderColor(_backingStore, drawingContext, false);
});
foreach (DeviceVisualizerLed deviceVisualizerLed in _dimmedLeds)
deviceVisualizerLed.RenderColor(_backingStore, drawingContext, true);
}
else
{
foreach (DeviceVisualizerLed deviceVisualizerLed in _deviceVisualizerLeds)
deviceVisualizerLed.RenderColor(_backingStore, drawingContext, false);
}
drawingContext.Close();
} }
private void UpdateTransform() private void UpdateTransform()
@ -241,22 +265,12 @@ namespace Artemis.UI.Shared
InvalidateMeasure(); InvalidateMeasure();
} }
private static void DevicePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DeviceVisualizer deviceVisualizer = (DeviceVisualizer) d;
deviceVisualizer.Dispatcher.Invoke(() => { deviceVisualizer.SetupForDevice(); });
}
private static void ShowColorsPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DeviceVisualizer deviceVisualizer = (DeviceVisualizer) d;
deviceVisualizer.Dispatcher.Invoke(() => { deviceVisualizer.SetupForDevice(); });
}
private void SetupForDevice() private void SetupForDevice()
{ {
_deviceImage = null; _deviceImage = null;
_deviceVisualizerLeds.Clear(); _deviceVisualizerLeds.Clear();
_highlightedLeds = new List<DeviceVisualizerLed>();
_dimmedLeds = new List<DeviceVisualizerLed>();
if (Device == null) if (Device == null)
return; return;
@ -319,40 +333,47 @@ namespace Artemis.UI.Shared
private void DeviceUpdated(object? sender, EventArgs e) private void DeviceUpdated(object? sender, EventArgs e)
{ {
Execute.PostToUIThread(SetupForDevice); Dispatcher.Invoke(SetupForDevice);
} }
private void DevicePropertyChanged(object? sender, PropertyChangedEventArgs e) private void DevicePropertyChanged(object? sender, PropertyChangedEventArgs e)
{ {
Execute.PostToUIThread(SetupForDevice); Dispatcher.Invoke(SetupForDevice);
} }
private void Render() private static void DevicePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{ {
DrawingContext drawingContext = _backingStore.Append(); DeviceVisualizer deviceVisualizer = (DeviceVisualizer) d;
deviceVisualizer.Dispatcher.Invoke(() => { deviceVisualizer.SetupForDevice(); });
}
if (HighlightedLeds != null && HighlightedLeds.Any()) private static void ShowColorsPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DeviceVisualizer deviceVisualizer = (DeviceVisualizer) d;
deviceVisualizer.Dispatcher.Invoke(() => { deviceVisualizer.SetupForDevice(); });
}
private static void HighlightedLedsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DeviceVisualizer deviceVisualizer = (DeviceVisualizer) d;
if (e.OldValue is ObservableCollection<ArtemisLed> oldCollection)
oldCollection.CollectionChanged -= deviceVisualizer.HighlightedLedsChanged;
if (e.NewValue is ObservableCollection<ArtemisLed> newCollection)
newCollection.CollectionChanged += deviceVisualizer.HighlightedLedsChanged;
}
private void HighlightedLedsChanged(object? sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
{
if (HighlightedLeds != null)
{ {
// Faster on large devices, maybe a bit slower on smaller ones but that's ok _highlightedLeds = _deviceVisualizerLeds.Where(l => HighlightedLeds.Contains(l.Led)).ToList();
ILookup<ArtemisLed, ArtemisLed> toHighlight = HighlightedLeds.ToLookup(l => l); _dimmedLeds = _deviceVisualizerLeds.Where(l => !HighlightedLeds.Contains(l.Led)).ToList();
foreach (DeviceVisualizerLed deviceVisualizerLed in _deviceVisualizerLeds)
deviceVisualizerLed.RenderColor(_backingStore, drawingContext, !toHighlight.Contains(deviceVisualizerLed.Led));
} }
else else
{ {
foreach (DeviceVisualizerLed deviceVisualizerLed in _deviceVisualizerLeds) _highlightedLeds = new List<DeviceVisualizerLed>();
deviceVisualizerLed.RenderColor(_backingStore, drawingContext, false); _dimmedLeds = new List<DeviceVisualizerLed>();
} }
drawingContext.Close();
}
/// <inheritdoc />
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
} }
} }
} }

View File

@ -12,7 +12,6 @@ using Ninject.Parameters;
using Serilog; using Serilog;
using SkiaSharp; using SkiaSharp;
using SkiaSharp.Views.WPF; using SkiaSharp.Views.WPF;
using Stylet;
namespace Artemis.UI.Shared.Services namespace Artemis.UI.Shared.Services
{ {
@ -45,9 +44,11 @@ namespace Artemis.UI.Shared.Services
private void CoreServiceOnFrameRendered(object? sender, FrameRenderedEventArgs e) private void CoreServiceOnFrameRendered(object? sender, FrameRenderedEventArgs e)
{ {
if (!_doTick) return; if (!_doTick)
return;
_doTick = false; _doTick = false;
Execute.PostToUIThread(OnProfilePreviewUpdated);
OnProfilePreviewUpdated();
} }
private void ReloadProfile() private void ReloadProfile()
@ -144,6 +145,7 @@ namespace Artemis.UI.Shared.Services
{ {
if (_currentTime.Equals(value)) return; if (_currentTime.Equals(value)) return;
_currentTime = value; _currentTime = value;
Tick(); Tick();
OnCurrentTimeChanged(); OnCurrentTimeChanged();
} }

View File

@ -25,7 +25,8 @@ namespace Artemis.UI.Shared
HitTestResultBehavior ResultCallback(HitTestResult r) => HitTestResultBehavior.Continue; HitTestResultBehavior ResultCallback(HitTestResult r) => HitTestResultBehavior.Continue;
HitTestFilterBehavior FilterCallback(DependencyObject e) HitTestFilterBehavior FilterCallback(DependencyObject e)
{ {
if (e is FrameworkElement fe && fe.DataContext is T context && !result.Contains(context)) result.Add(context); if (e is FrameworkElement fe && fe.DataContext is T context && !result.Contains(context))
result.Add(context);
return HitTestFilterBehavior.Continue; return HitTestFilterBehavior.Continue;
} }

View File

@ -583,30 +583,28 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
return; return;
} }
Execute.PostToUIThread(() => TimeSpan newTime = ProfileEditorService.CurrentTime.Add(TimeSpan.FromSeconds(e.DeltaTime));
if (SelectedProfileElement != null)
{ {
TimeSpan newTime = ProfileEditorService.CurrentTime.Add(TimeSpan.FromSeconds(e.DeltaTime)); if (Repeating && RepeatTimeline)
if (SelectedProfileElement != null)
{ {
if (Repeating && RepeatTimeline) if (newTime > SelectedProfileElement.Timeline.Length)
{ newTime = TimeSpan.Zero;
if (newTime > SelectedProfileElement.Timeline.Length)
newTime = TimeSpan.Zero;
}
else if (Repeating && RepeatSegment)
{
if (newTime > GetCurrentSegmentEnd())
newTime = GetCurrentSegmentStart();
}
else if (newTime > SelectedProfileElement.Timeline.Length)
{
newTime = SelectedProfileElement.Timeline.Length;
Pause();
}
} }
else if (Repeating && RepeatSegment)
{
if (newTime > GetCurrentSegmentEnd())
newTime = GetCurrentSegmentStart();
}
else if (newTime > SelectedProfileElement.Timeline.Length)
{
newTime = SelectedProfileElement.Timeline.Length;
Pause();
}
}
ProfileEditorService.CurrentTime = newTime; // Update current time on high priority to keep things buttery smooth as if you're using the mouse ༼ つ ◕_◕ ༽つ
}); Execute.OnUIThreadSync(() => ProfileEditorService.CurrentTime = newTime);
} }
#endregion #endregion

View File

@ -8,6 +8,8 @@ using Artemis.UI.Extensions;
using Artemis.UI.Screens.Shared; using Artemis.UI.Screens.Shared;
using Artemis.UI.Services; using Artemis.UI.Services;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
using SkiaSharp;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.Visualization namespace Artemis.UI.Screens.ProfileEditor.Visualization
{ {
@ -95,6 +97,16 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
CreateViewportRectangle(); CreateViewportRectangle();
} }
#region Updating
private LayerShape _lastShape;
private Rect _lastBounds;
private SKPoint _lastAnchor;
private SKPoint _lastPosition;
private double _lastRotation;
private SKSize _lastScale;
private void CreateShapeGeometry() private void CreateShapeGeometry()
{ {
if (Layer.LayerShape == null || !Layer.Leds.Any()) if (Layer.LayerShape == null || !Layer.Leds.Any())
@ -104,21 +116,22 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
} }
Rect bounds = _layerEditorService.GetLayerBounds(Layer); Rect bounds = _layerEditorService.GetLayerBounds(Layer);
Geometry shapeGeometry = Geometry.Empty;
switch (Layer.LayerShape) // Only bother the UI thread for both of these if we're sure
if (HasShapeChanged(bounds))
{ {
case EllipseShape _: Execute.OnUIThreadSync(() =>
shapeGeometry = new EllipseGeometry(bounds); {
break; if (Layer.LayerShape is RectangleShape)
case RectangleShape _: ShapeGeometry = new RectangleGeometry(bounds);
shapeGeometry = new RectangleGeometry(bounds); if (Layer.LayerShape is EllipseShape)
break; ShapeGeometry = new EllipseGeometry(bounds);
});
}
if ((Layer.LayerBrush == null || Layer.LayerBrush.SupportsTransformation) && HasTransformationChanged())
{
Execute.OnUIThreadSync(() => ShapeGeometry.Transform = _layerEditorService.GetLayerTransformGroup(Layer));
} }
if (Layer.LayerBrush == null || Layer.LayerBrush.SupportsTransformation)
shapeGeometry.Transform = _layerEditorService.GetLayerTransformGroup(Layer);
ShapeGeometry = shapeGeometry;
} }
private void CreateViewportRectangle() private void CreateViewportRectangle()
@ -132,44 +145,30 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
ViewportRectangle = _layerEditorService.GetLayerBounds(Layer); ViewportRectangle = _layerEditorService.GetLayerBounds(Layer);
} }
private Geometry CreateRectangleGeometry(ArtemisLed led) private bool HasShapeChanged(Rect bounds)
{ {
Rect rect = led.RgbLed.AbsoluteBoundary.ToWindowsRect(1); bool result = !Equals(_lastBounds, bounds) || !Equals(_lastShape, Layer.LayerShape);
return new RectangleGeometry(rect); _lastShape = Layer.LayerShape;
_lastBounds = bounds;
return result;
} }
private Geometry CreateCircleGeometry(ArtemisLed led) private bool HasTransformationChanged()
{ {
Rect rect = led.RgbLed.AbsoluteBoundary.ToWindowsRect(1); bool result = _lastAnchor != Layer.Transform.AnchorPoint.CurrentValue ||
return new EllipseGeometry(rect); _lastPosition != Layer.Transform.Position.CurrentValue ||
_lastRotation != Layer.Transform.Rotation.CurrentValue ||
_lastScale != Layer.Transform.Scale.CurrentValue;
_lastAnchor = Layer.Transform.AnchorPoint.CurrentValue;
_lastPosition = Layer.Transform.Position.CurrentValue;
_lastRotation = Layer.Transform.Rotation.CurrentValue;
_lastScale = Layer.Transform.Scale.CurrentValue;
return result;
} }
private Geometry CreateCustomGeometry(ArtemisLed led, double deflateAmount) #endregion
{
Rect rect = led.RgbLed.AbsoluteBoundary.ToWindowsRect(1);
try
{
PathGeometry geometry = Geometry.Combine(
Geometry.Empty,
Geometry.Parse(led.RgbLed.ShapeData),
GeometryCombineMode.Union,
new TransformGroup
{
Children = new TransformCollection
{
new ScaleTransform(rect.Width, rect.Height),
new TranslateTransform(rect.X, rect.Y)
}
}
);
return geometry;
}
catch (Exception)
{
return CreateRectangleGeometry(led);
}
}
#region Overrides of Screen #region Overrides of Screen

View File

@ -51,7 +51,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools
private void Update() private void Update()
{ {
if (!(ProfileEditorService.SelectedProfileElement is Layer layer)) if (ProfileEditorService.SelectedProfileElement is not Layer layer)
return; return;
ShapePath = _layerEditorService.GetLayerPath(layer, true, true, true); ShapePath = _layerEditorService.GetLayerPath(layer, true, true, true);

View File

@ -152,11 +152,6 @@ namespace Artemis.UI.Screens.Shared
PanY = rect.Top * -1 * Zoom; PanY = rect.Top * -1 * Zoom;
} }
public Rect TransformContainingRect(Rectangle rect)
{
return TransformContainingRect(rect.ToWindowsRect(1));
}
public Rect TransformContainingRect(Rect rect) public Rect TransformContainingRect(Rect rect)
{ {
// Create the same transform group the view is using // Create the same transform group the view is using
@ -168,6 +163,17 @@ namespace Artemis.UI.Screens.Shared
return transformGroup.TransformBounds(rect); return transformGroup.TransformBounds(rect);
} }
public Rect UnTransformContainingRect(Rect rect)
{
// Create the same transform group the view is using
TransformGroup transformGroup = new();
transformGroup.Children.Add(new TranslateTransform(PanX * -1, PanY * -1));
transformGroup.Children.Add(new ScaleTransform(1 / Zoom, 1 / Zoom));
// Apply it to the device rect
return transformGroup.TransformBounds(rect);
}
public Point GetRelativeMousePosition(object container, MouseEventArgs e) public Point GetRelativeMousePosition(object container, MouseEventArgs e)
{ {
// Get the mouse position relative to the panned / zoomed panel, not very MVVM but I can't find a better way // Get the mouse position relative to the panned / zoomed panel, not very MVVM but I can't find a better way

View File

@ -188,8 +188,7 @@
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>
</ItemsControl> </ItemsControl>
<Canvas> <Canvas>
<Rectangle ClipToBounds="False" <Rectangle Width="{Binding MaxTextureSize}"
Width="{Binding MaxTextureSize}"
Height="{Binding MaxTextureSize}" Height="{Binding MaxTextureSize}"
Stroke="{DynamicResource SecondaryHueMidBrush}" Stroke="{DynamicResource SecondaryHueMidBrush}"
StrokeThickness="{Binding MaxTextureSizeIndicatorThickness}" StrokeThickness="{Binding MaxTextureSizeIndicatorThickness}"

View File

@ -18,6 +18,7 @@ using Artemis.UI.Screens.SurfaceEditor.Visualization;
using Artemis.UI.Shared; using Artemis.UI.Shared;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
using SkiaSharp; using SkiaSharp;
using SkiaSharp.Views.WPF;
using Stylet; using Stylet;
using MouseButton = System.Windows.Input.MouseButton; using MouseButton = System.Windows.Input.MouseButton;
@ -305,7 +306,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
if (e.LeftButton == MouseButtonState.Pressed) if (e.LeftButton == MouseButtonState.Pressed)
StartMouseDrag(sender, position, relative); StartMouseDrag(sender, position, relative);
else else
StopMouseDrag(sender, position); StopMouseDrag(position);
} }
// ReSharper disable once UnusedMember.Global - Called from view // ReSharper disable once UnusedMember.Global - Called from view
@ -323,7 +324,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
if (_mouseDragStatus == MouseDragStatus.Dragging) if (_mouseDragStatus == MouseDragStatus.Dragging)
MoveSelected(relative); MoveSelected(relative);
else if (_mouseDragStatus == MouseDragStatus.Selecting) else if (_mouseDragStatus == MouseDragStatus.Selecting)
UpdateSelection(sender, position); UpdateSelection(position);
} }
private void StartMouseDrag(object sender, Point position, Point relative) private void StartMouseDrag(object sender, Point position, Point relative)
@ -360,17 +361,18 @@ namespace Artemis.UI.Screens.SurfaceEditor
ApplySurfaceSelection(); ApplySurfaceSelection();
} }
private void StopMouseDrag(object sender, Point position) private void StopMouseDrag(Point position)
{ {
if (_mouseDragStatus != MouseDragStatus.Dragging) if (_mouseDragStatus != MouseDragStatus.Dragging)
{ {
RectangleGeometry selectedRect = new(new Rect(_mouseDragStartPoint, position)); SKRect hitTestRect = PanZoomViewModel.UnTransformContainingRect(new Rect(_mouseDragStartPoint, position)).ToSKRect();
List<SurfaceDeviceViewModel> devices = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, selectedRect);
foreach (SurfaceDeviceViewModel device in SurfaceDeviceViewModels) foreach (SurfaceDeviceViewModel device in SurfaceDeviceViewModels)
if (devices.Contains(device)) {
if (device.Device.Rectangle.IntersectsWith(hitTestRect))
device.SelectionStatus = SelectionStatus.Selected; device.SelectionStatus = SelectionStatus.Selected;
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
device.SelectionStatus = SelectionStatus.None; device.SelectionStatus = SelectionStatus.None;
}
} }
else else
{ {
@ -382,7 +384,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
ApplySurfaceSelection(); ApplySurfaceSelection();
} }
private void UpdateSelection(object sender, Point position) private void UpdateSelection(Point position)
{ {
if (IsPanKeyDown()) if (IsPanKeyDown())
return; return;
@ -390,12 +392,14 @@ namespace Artemis.UI.Screens.SurfaceEditor
Rect selectedRect = new(_mouseDragStartPoint, position); Rect selectedRect = new(_mouseDragStartPoint, position);
SelectionRectangle.Rect = selectedRect; SelectionRectangle.Rect = selectedRect;
List<SurfaceDeviceViewModel> devices = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, SelectionRectangle); SKRect hitTestRect = PanZoomViewModel.UnTransformContainingRect(new Rect(_mouseDragStartPoint, position)).ToSKRect();
foreach (SurfaceDeviceViewModel device in SurfaceDeviceViewModels) foreach (SurfaceDeviceViewModel device in SurfaceDeviceViewModels)
if (devices.Contains(device)) {
if (device.Device.Rectangle.IntersectsWith(hitTestRect))
device.SelectionStatus = SelectionStatus.Selected; device.SelectionStatus = SelectionStatus.Selected;
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
device.SelectionStatus = SelectionStatus.None; device.SelectionStatus = SelectionStatus.None;
}
ApplySurfaceSelection(); ApplySurfaceSelection();
} }