mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Core - Change default rendering to Software, quicker in most setups
Surface editor - Added remaining missing functionality
This commit is contained in:
parent
a06bc68046
commit
4809ebf969
@ -43,7 +43,7 @@ namespace Artemis.Core.Services
|
|||||||
_deviceRepository = deviceRepository;
|
_deviceRepository = deviceRepository;
|
||||||
_targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 30);
|
_targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 30);
|
||||||
_renderScaleSetting = settingsService.GetSetting("Core.RenderScale", 0.25);
|
_renderScaleSetting = settingsService.GetSetting("Core.RenderScale", 0.25);
|
||||||
_preferredGraphicsContext = _settingsService.GetSetting("Core.PreferredGraphicsContext", "Vulkan");
|
_preferredGraphicsContext = _settingsService.GetSetting("Core.PreferredGraphicsContext", "Software");
|
||||||
|
|
||||||
Surface = new RGBSurface();
|
Surface = new RGBSurface();
|
||||||
Utilities.RenderScaleMultiplier = (int) (1 / _renderScaleSetting.Value);
|
Utilities.RenderScaleMultiplier = (int) (1 / _renderScaleSetting.Value);
|
||||||
|
|||||||
@ -133,7 +133,7 @@ namespace Artemis.UI.Screens.Settings
|
|||||||
public PluginSetting<ApplicationColorScheme> UIColorScheme => _settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic);
|
public PluginSetting<ApplicationColorScheme> UIColorScheme => _settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic);
|
||||||
public PluginSetting<bool> ProfileEditorShowDataModelValues => _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
|
public PluginSetting<bool> ProfileEditorShowDataModelValues => _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
|
||||||
public PluginSetting<LogEventLevel> CoreLoggingLevel => _settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Information);
|
public PluginSetting<LogEventLevel> CoreLoggingLevel => _settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Information);
|
||||||
public PluginSetting<string> CorePreferredGraphicsContext => _settingsService.GetSetting("Core.PreferredGraphicsContext", "Vulkan");
|
public PluginSetting<string> CorePreferredGraphicsContext => _settingsService.GetSetting("Core.PreferredGraphicsContext", "Software");
|
||||||
public PluginSetting<double> CoreRenderScale => _settingsService.GetSetting("Core.RenderScale", 0.25);
|
public PluginSetting<double> CoreRenderScale => _settingsService.GetSetting("Core.RenderScale", 0.25);
|
||||||
public PluginSetting<int> CoreTargetFrameRate => _settingsService.GetSetting("Core.TargetFrameRate", 30);
|
public PluginSetting<int> CoreTargetFrameRate => _settingsService.GetSetting("Core.TargetFrameRate", 30);
|
||||||
public PluginSetting<int> WebServerPort => _settingsService.GetSetting("WebServer.Port", 9696);
|
public PluginSetting<int> WebServerPort => _settingsService.GetSetting("WebServer.Port", 9696);
|
||||||
|
|||||||
@ -2,7 +2,16 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||||
|
xmlns:surfaceEditor="clr-namespace:Artemis.UI.Screens.SurfaceEditor"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.SurfaceEditor.ListDeviceView">
|
x:Class="Artemis.UI.Screens.SurfaceEditor.ListDeviceView"
|
||||||
Welcome to Avalonia!
|
x:DataType="surfaceEditor:ListDeviceViewModel">
|
||||||
|
<Grid ColumnDefinitions="Auto,*,Auto" RowDefinitions="*,*">
|
||||||
|
<Border Grid.Column="0" Grid.RowSpan="2" Width="64" Height="50" Margin="0 0 10 0">
|
||||||
|
<shared:DeviceVisualizer Device="{CompiledBinding Device}" ShowColors="True" VerticalAlignment="Center" HorizontalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
<TextBlock Grid.Column="1" Grid.Row="0" Text="{CompiledBinding Device.RgbDevice.DeviceInfo.DeviceName}" VerticalAlignment="Bottom" />
|
||||||
|
<TextBlock Grid.Column="1" Grid.Row="1" Classes="subtitle" Text="{CompiledBinding Device.RgbDevice.DeviceInfo.Manufacturer}" VerticalAlignment="Top" />
|
||||||
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using Artemis.Core;
|
using System;
|
||||||
|
using Artemis.Core;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
@ -6,6 +7,8 @@ namespace Artemis.UI.Screens.SurfaceEditor;
|
|||||||
|
|
||||||
public class ListDeviceViewModel : ViewModelBase
|
public class ListDeviceViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
|
private static readonly Random Random = new();
|
||||||
|
|
||||||
private SKColor _color;
|
private SKColor _color;
|
||||||
private bool _isSelected;
|
private bool _isSelected;
|
||||||
|
|
||||||
@ -13,6 +16,7 @@ public class ListDeviceViewModel : ViewModelBase
|
|||||||
{
|
{
|
||||||
Device = device;
|
Device = device;
|
||||||
SurfaceEditorViewModel = surfaceEditorViewModel;
|
SurfaceEditorViewModel = surfaceEditorViewModel;
|
||||||
|
Color = SKColor.FromHsv(Random.NextSingle() * 360, 95, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArtemisDevice Device { get; }
|
public ArtemisDevice Device { get; }
|
||||||
|
|||||||
@ -1,14 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Ninject.Factories;
|
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
|
||||||
using ReactiveUI;
|
|
||||||
using RGB.NET.Core;
|
using RGB.NET.Core;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
using Point = Avalonia.Point;
|
using Point = Avalonia.Point;
|
||||||
@ -17,35 +12,21 @@ namespace Artemis.UI.Screens.SurfaceEditor;
|
|||||||
|
|
||||||
public class SurfaceDeviceViewModel : ActivatableViewModelBase
|
public class SurfaceDeviceViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
private readonly IDeviceService _deviceService;
|
|
||||||
private readonly IDeviceVmFactory _deviceVmFactory;
|
|
||||||
private readonly IRgbService _rgbService;
|
private readonly IRgbService _rgbService;
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
private readonly IWindowService _windowService;
|
|
||||||
private double _dragOffsetX;
|
private double _dragOffsetX;
|
||||||
private double _dragOffsetY;
|
private double _dragOffsetY;
|
||||||
private bool _isSelected;
|
private bool _isSelected;
|
||||||
|
|
||||||
public SurfaceDeviceViewModel(ArtemisDevice device, SurfaceEditorViewModel surfaceEditorViewModel, IRgbService rgbService, IDeviceService deviceService, ISettingsService settingsService,
|
public SurfaceDeviceViewModel(ArtemisDevice device, SurfaceEditorViewModel surfaceEditorViewModel, IRgbService rgbService, ISettingsService settingsService)
|
||||||
IDeviceVmFactory deviceVmFactory,
|
|
||||||
IWindowService windowService)
|
|
||||||
{
|
{
|
||||||
_rgbService = rgbService;
|
_rgbService = rgbService;
|
||||||
_deviceService = deviceService;
|
|
||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
_deviceVmFactory = deviceVmFactory;
|
|
||||||
_windowService = windowService;
|
|
||||||
|
|
||||||
Device = device;
|
Device = device;
|
||||||
SurfaceEditorViewModel = surfaceEditorViewModel;
|
SurfaceEditorViewModel = surfaceEditorViewModel;
|
||||||
|
|
||||||
IdentifyDevice = ReactiveCommand.Create<ArtemisDevice>(ExecuteIdentifyDevice);
|
|
||||||
ViewProperties = ReactiveCommand.CreateFromTask<ArtemisDevice>(ExecuteViewProperties);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactiveCommand<ArtemisDevice, Unit> IdentifyDevice { get; }
|
|
||||||
public ReactiveCommand<ArtemisDevice, Unit> ViewProperties { get; }
|
|
||||||
|
|
||||||
public ArtemisDevice Device { get; }
|
public ArtemisDevice Device { get; }
|
||||||
public SurfaceEditorViewModel SurfaceEditorViewModel { get; }
|
public SurfaceEditorViewModel SurfaceEditorViewModel { get; }
|
||||||
|
|
||||||
@ -96,16 +77,6 @@ public class SurfaceDeviceViewModel : ActivatableViewModelBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExecuteIdentifyDevice(ArtemisDevice device)
|
|
||||||
{
|
|
||||||
_deviceService.IdentifyDevice(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ExecuteViewProperties(ArtemisDevice device)
|
|
||||||
{
|
|
||||||
await _windowService.ShowDialogAsync(_deviceVmFactory.DevicePropertiesViewModel(device));
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool Fits(float x, float y, bool ignoreOverlap)
|
private bool Fits(float x, float y, bool ignoreOverlap)
|
||||||
{
|
{
|
||||||
if (x < 0 || y < 0)
|
if (x < 0 || y < 0)
|
||||||
|
|||||||
@ -5,8 +5,10 @@
|
|||||||
xmlns:paz="clr-namespace:Avalonia.Controls.PanAndZoom;assembly=Avalonia.Controls.PanAndZoom"
|
xmlns:paz="clr-namespace:Avalonia.Controls.PanAndZoom;assembly=Avalonia.Controls.PanAndZoom"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||||
|
xmlns:surfaceEditor="clr-namespace:Artemis.UI.Screens.SurfaceEditor"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.SurfaceEditor.SurfaceEditorView">
|
x:Class="Artemis.UI.Screens.SurfaceEditor.SurfaceEditorView"
|
||||||
|
x:DataType="surfaceEditor:SurfaceEditorViewModel">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<VisualBrush x:Key="LargeCheckerboardBrush" TileMode="Tile" Stretch="Uniform" SourceRect="0,0,20,20">
|
<VisualBrush x:Key="LargeCheckerboardBrush" TileMode="Tile" Stretch="Uniform" SourceRect="0,0,20,20">
|
||||||
<VisualBrush.Visual>
|
<VisualBrush.Visual>
|
||||||
@ -18,106 +20,132 @@
|
|||||||
</Canvas>
|
</Canvas>
|
||||||
</VisualBrush.Visual>
|
</VisualBrush.Visual>
|
||||||
</VisualBrush>
|
</VisualBrush>
|
||||||
|
<MenuFlyout x:Key="DeviceMenuFlyout">
|
||||||
|
<MenuItem Header="Identify" Command="{Binding $parent[surfaceEditor:SurfaceEditorView].DataContext.IdentifyDevice}" CommandParameter="{Binding Device}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<avalonia:MaterialIcon Kind="AlarmLight" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem Header="-" />
|
||||||
|
<MenuItem Header="Bring to Front" Command="{Binding $parent[surfaceEditor:SurfaceEditorView].DataContext.BringToFront}" CommandParameter="{Binding Device}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<avalonia:MaterialIcon Kind="ArrangeBringToFront" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem Header="Bring Forward" Command="{Binding $parent[surfaceEditor:SurfaceEditorView].DataContext.BringForward}" CommandParameter="{Binding Device}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<avalonia:MaterialIcon Kind="ArrangeBringForward" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem Header="Send to Back" Command="{Binding $parent[surfaceEditor:SurfaceEditorView].DataContext.SendToBack}" CommandParameter="{Binding Device}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<avalonia:MaterialIcon Kind="ArrangeSendToBack" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem Header="Send Backward" Command="{Binding $parent[surfaceEditor:SurfaceEditorView].DataContext.SendBackward}" CommandParameter="{Binding Device}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<avalonia:MaterialIcon Kind="ArrangeSendBackward" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem Header="-" />
|
||||||
|
<MenuItem Header="Identify input"
|
||||||
|
Command="{Binding DetectInput}"
|
||||||
|
CommandParameter="{Binding Device}"
|
||||||
|
ToolTip.Tip="Teach Artemis which keypresses and/or button presses belong to this device">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<avalonia:MaterialIcon Kind="GestureDoubleTap" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem Header="View properties" Command="{Binding $parent[surfaceEditor:SurfaceEditorView].DataContext.ViewProperties}" CommandParameter="{Binding Device}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<avalonia:MaterialIcon Kind="Gear" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
</MenuFlyout>
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
<Border Classes="router-container">
|
<Grid Margin="0 0 15 15" ColumnDefinitions="*,400">
|
||||||
<paz:ZoomBorder Name="ZoomBorder"
|
<Border Grid.Column="0" Classes="card-condensed">
|
||||||
Stretch="None"
|
<paz:ZoomBorder Name="ZoomBorder"
|
||||||
ClipToBounds="True"
|
Stretch="None"
|
||||||
Focusable="True"
|
ClipToBounds="True"
|
||||||
VerticalAlignment="Stretch"
|
Focusable="True"
|
||||||
HorizontalAlignment="Stretch"
|
VerticalAlignment="Stretch"
|
||||||
Background="{StaticResource LargeCheckerboardBrush}"
|
HorizontalAlignment="Stretch"
|
||||||
ZoomChanged="ZoomBorder_OnZoomChanged"
|
Background="{StaticResource LargeCheckerboardBrush}"
|
||||||
PointerReleased="ZoomBorder_OnPointerReleased">
|
ZoomChanged="ZoomBorder_OnZoomChanged"
|
||||||
<Grid Name="ContainerGrid" Background="Transparent">
|
PointerReleased="ZoomBorder_OnPointerReleased">
|
||||||
<Grid.Transitions>
|
<Grid Name="ContainerGrid" Background="Transparent">
|
||||||
<Transitions>
|
<Grid.Transitions>
|
||||||
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.2" Easing="CubicEaseOut" />
|
<Transitions>
|
||||||
</Transitions>
|
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.2" Easing="CubicEaseOut" />
|
||||||
</Grid.Transitions>
|
</Transitions>
|
||||||
<ItemsControl Name="DeviceContainer" Items="{Binding SurfaceDeviceViewModels}" ClipToBounds="False">
|
</Grid.Transitions>
|
||||||
<ItemsControl.Styles>
|
<ItemsControl Name="DeviceContainer" Items="{CompiledBinding SurfaceDeviceViewModels}" ClipToBounds="False">
|
||||||
<Style Selector="ContentPresenter">
|
<ItemsControl.Styles>
|
||||||
<Setter Property="Canvas.Left" Value="{Binding Device.X}" />
|
<Style Selector="ContentPresenter">
|
||||||
<Setter Property="Canvas.Top" Value="{Binding Device.Y}" />
|
<Setter Property="Canvas.Left" Value="{Binding Device.X}" />
|
||||||
</Style>
|
<Setter Property="Canvas.Top" Value="{Binding Device.Y}" />
|
||||||
</ItemsControl.Styles>
|
</Style>
|
||||||
<ItemsControl.ItemsPanel>
|
</ItemsControl.Styles>
|
||||||
<ItemsPanelTemplate>
|
<ItemsControl.ItemsPanel>
|
||||||
<Canvas />
|
<ItemsPanelTemplate>
|
||||||
</ItemsPanelTemplate>
|
<Canvas />
|
||||||
</ItemsControl.ItemsPanel>
|
</ItemsPanelTemplate>
|
||||||
<ItemsControl.ItemTemplate>
|
</ItemsControl.ItemsPanel>
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<ContentControl Content="{Binding}" ContextFlyout="{StaticResource DeviceMenuFlyout}" />
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
|
||||||
|
<shared:SelectionRectangle Name="SelectionRectangle"
|
||||||
|
InputElement="{Binding #ZoomBorder}"
|
||||||
|
SelectionUpdated="SelectionRectangle_OnSelectionUpdated"
|
||||||
|
BorderBrush="{DynamicResource SystemAccentColor}"
|
||||||
|
BorderRadius="8">
|
||||||
|
<shared:SelectionRectangle.Background>
|
||||||
|
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2" />
|
||||||
|
</shared:SelectionRectangle.Background>
|
||||||
|
</shared:SelectionRectangle>
|
||||||
|
|
||||||
|
<Border Name="SurfaceBounds"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Width="{Binding MaxTextureSize}"
|
||||||
|
Height="{Binding MaxTextureSize}"
|
||||||
|
BorderThickness="2"
|
||||||
|
BorderBrush="{DynamicResource SystemAccentColorLight1}"
|
||||||
|
BorderDashArray="6,2"
|
||||||
|
Opacity="0.5" />
|
||||||
|
</Grid>
|
||||||
|
</paz:ZoomBorder>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<Border Grid.Column="1" Classes="card-condensed" Margin="15 0 0 0">
|
||||||
|
<Grid RowDefinitions="*,Auto,Auto" ColumnDefinitions="*,*">
|
||||||
|
<ListBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Items="{CompiledBinding ListDeviceViewModels}">
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<ContentControl Content="{Binding}">
|
<ContentControl Content="{Binding}" ContextFlyout="{StaticResource DeviceMenuFlyout}"></ContentControl>
|
||||||
<ContentControl.ContextFlyout>
|
|
||||||
<MenuFlyout>
|
|
||||||
<MenuItem Header="Identify" Command="{Binding IdentifyDevice}" CommandParameter="{Binding Device}">
|
|
||||||
<MenuItem.Icon>
|
|
||||||
<avalonia:MaterialIcon Kind="AlarmLight" />
|
|
||||||
</MenuItem.Icon>
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem Header="-" />
|
|
||||||
<MenuItem Header="Bring to Front" Command="{Binding $parent[4].DataContext.BringToFront}" CommandParameter="{Binding Device}">
|
|
||||||
<MenuItem.Icon>
|
|
||||||
<avalonia:MaterialIcon Kind="ArrangeBringToFront" />
|
|
||||||
</MenuItem.Icon>
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem Header="Bring Forward" Command="{Binding $parent[4].DataContext.BringForward}" CommandParameter="{Binding Device}">
|
|
||||||
<MenuItem.Icon>
|
|
||||||
<avalonia:MaterialIcon Kind="ArrangeBringForward" />
|
|
||||||
</MenuItem.Icon>
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem Header="Send to Back" Command="{Binding $parent[4].DataContext.SendToBack}" CommandParameter="{Binding Device}">
|
|
||||||
<MenuItem.Icon>
|
|
||||||
<avalonia:MaterialIcon Kind="ArrangeSendToBack" />
|
|
||||||
</MenuItem.Icon>
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem Header="Send Backward" Command="{Binding $parent[4].DataContext.SendBackward}" CommandParameter="{Binding Device}">
|
|
||||||
<MenuItem.Icon>
|
|
||||||
<avalonia:MaterialIcon Kind="ArrangeSendBackward" />
|
|
||||||
</MenuItem.Icon>
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem Header="-" />
|
|
||||||
<MenuItem Header="Identify input"
|
|
||||||
Command="{Binding DetectInput}"
|
|
||||||
CommandParameter="{Binding Device}"
|
|
||||||
ToolTip.Tip="Teach Artemis which keypresses and/or button presses belong to this device">
|
|
||||||
<MenuItem.Icon>
|
|
||||||
<avalonia:MaterialIcon Kind="GestureDoubleTap" />
|
|
||||||
</MenuItem.Icon>
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem Header="View properties" Command="{Binding ViewProperties}" CommandParameter="{Binding Device}">
|
|
||||||
<MenuItem.Icon>
|
|
||||||
<avalonia:MaterialIcon Kind="Gear" />
|
|
||||||
</MenuItem.Icon>
|
|
||||||
</MenuItem>
|
|
||||||
</MenuFlyout>
|
|
||||||
</ContentControl.ContextFlyout>
|
|
||||||
</ContentControl>
|
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ListBox.ItemTemplate>
|
||||||
</ItemsControl>
|
</ListBox>
|
||||||
|
<CheckBox Grid.Row="1"
|
||||||
<shared:SelectionRectangle Name="SelectionRectangle"
|
Grid.Column="0"
|
||||||
InputElement="{Binding #ZoomBorder}"
|
IsChecked="{CompiledBinding ColorDevices}"
|
||||||
SelectionUpdated="SelectionRectangle_OnSelectionUpdated"
|
ToolTip.Tip="Draws a random color on each device allowing you to identify them">
|
||||||
BorderBrush="{DynamicResource SystemAccentColor}"
|
Color overlay devices
|
||||||
BorderRadius="8">
|
</CheckBox>
|
||||||
<shared:SelectionRectangle.Background>
|
<CheckBox Grid.Row="1"
|
||||||
<SolidColorBrush Color="{DynamicResource SystemAccentColorLight1}" Opacity="0.2" />
|
Grid.Column="1"
|
||||||
</shared:SelectionRectangle.Background>
|
IsChecked="{CompiledBinding ColorFirstLedOnly}"
|
||||||
</shared:SelectionRectangle>
|
IsEnabled="{CompiledBinding ColorDevices}"
|
||||||
|
ToolTip.Tip="Draws the overlay only on the first LED of each device">
|
||||||
<Border Name="SurfaceBounds"
|
Overlay first LED only
|
||||||
VerticalAlignment="Top"
|
</CheckBox>
|
||||||
HorizontalAlignment="Left"
|
<Button Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" Margin="0 10 0 0" Command="{CompiledBinding AutoArrange}">Auto-arrange</Button>
|
||||||
Width="{Binding MaxTextureSize}"
|
|
||||||
Height="{Binding MaxTextureSize}"
|
|
||||||
BorderThickness="2"
|
|
||||||
BorderBrush="{DynamicResource SystemAccentColorLight3}"
|
|
||||||
CornerRadius="8" />
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</paz:ZoomBorder>
|
</Border>
|
||||||
</Border>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -3,13 +3,16 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Extensions;
|
using Artemis.UI.Extensions;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.SurfaceEditor;
|
namespace Artemis.UI.Screens.SurfaceEditor;
|
||||||
|
|
||||||
@ -17,29 +20,67 @@ public class SurfaceEditorViewModel : MainScreenViewModel
|
|||||||
{
|
{
|
||||||
private readonly IRgbService _rgbService;
|
private readonly IRgbService _rgbService;
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
|
private readonly IDeviceVmFactory _deviceVmFactory;
|
||||||
|
private readonly IWindowService _windowService;
|
||||||
|
private readonly IDeviceService _deviceService;
|
||||||
private List<SurfaceDeviceViewModel>? _initialSelection;
|
private List<SurfaceDeviceViewModel>? _initialSelection;
|
||||||
private bool _saving;
|
private bool _saving;
|
||||||
|
private bool _colorFirstLedOnly;
|
||||||
|
private bool _colorDevices;
|
||||||
|
private double _overlayOpacity;
|
||||||
|
|
||||||
public SurfaceEditorViewModel(IScreen hostScreen,
|
public SurfaceEditorViewModel(IScreen hostScreen,
|
||||||
|
ICoreService coreService,
|
||||||
IRgbService rgbService,
|
IRgbService rgbService,
|
||||||
ISurfaceVmFactory surfaceVmFactory,
|
ISurfaceVmFactory surfaceVmFactory,
|
||||||
ISettingsService settingsService) : base(hostScreen, "surface-editor")
|
ISettingsService settingsService,
|
||||||
|
IDeviceVmFactory deviceVmFactory,
|
||||||
|
IWindowService windowService,
|
||||||
|
IDeviceService deviceService) : base(hostScreen, "surface-editor")
|
||||||
{
|
{
|
||||||
_rgbService = rgbService;
|
_rgbService = rgbService;
|
||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
|
_deviceVmFactory = deviceVmFactory;
|
||||||
|
_windowService = windowService;
|
||||||
|
_deviceService = deviceService;
|
||||||
|
|
||||||
DisplayName = "Surface Editor";
|
DisplayName = "Surface Editor";
|
||||||
SurfaceDeviceViewModels = new ObservableCollection<SurfaceDeviceViewModel>(rgbService.EnabledDevices.OrderBy(d => d.ZIndex).Select(d => surfaceVmFactory.SurfaceDeviceViewModel(d, this)));
|
SurfaceDeviceViewModels = new ObservableCollection<SurfaceDeviceViewModel>(rgbService.EnabledDevices.OrderBy(d => d.ZIndex).Select(d => surfaceVmFactory.SurfaceDeviceViewModel(d, this)));
|
||||||
ListDeviceViewModels = new ObservableCollection<ListDeviceViewModel>(rgbService.EnabledDevices.OrderBy(d => d.ZIndex).Select(d => surfaceVmFactory.ListDeviceViewModel(d, this)));
|
ListDeviceViewModels = new ObservableCollection<ListDeviceViewModel>(rgbService.EnabledDevices.OrderBy(d => d.ZIndex).Select(d => surfaceVmFactory.ListDeviceViewModel(d, this)));
|
||||||
|
|
||||||
|
AutoArrange = ReactiveCommand.CreateFromTask(ExecuteAutoArrange);
|
||||||
|
IdentifyDevice = ReactiveCommand.Create<ArtemisDevice>(ExecuteIdentifyDevice);
|
||||||
|
ViewProperties = ReactiveCommand.CreateFromTask<ArtemisDevice>(ExecuteViewProperties);
|
||||||
BringToFront = ReactiveCommand.Create<ArtemisDevice>(ExecuteBringToFront);
|
BringToFront = ReactiveCommand.Create<ArtemisDevice>(ExecuteBringToFront);
|
||||||
BringForward = ReactiveCommand.Create<ArtemisDevice>(ExecuteBringForward);
|
BringForward = ReactiveCommand.Create<ArtemisDevice>(ExecuteBringForward);
|
||||||
SendToBack = ReactiveCommand.Create<ArtemisDevice>(ExecuteSendToBack);
|
SendToBack = ReactiveCommand.Create<ArtemisDevice>(ExecuteSendToBack);
|
||||||
SendBackward = ReactiveCommand.Create<ArtemisDevice>(ExecuteSendBackward);
|
SendBackward = ReactiveCommand.Create<ArtemisDevice>(ExecuteSendBackward);
|
||||||
|
|
||||||
|
this.WhenActivated(d =>
|
||||||
|
{
|
||||||
|
coreService.FrameRendering += CoreServiceOnFrameRendering;
|
||||||
|
Disposable.Create(() => coreService.FrameRendering -= CoreServiceOnFrameRendering).DisposeWith(d);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ColorDevices
|
||||||
|
{
|
||||||
|
get => _colorDevices;
|
||||||
|
set => RaiseAndSetIfChanged(ref _colorDevices, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ColorFirstLedOnly
|
||||||
|
{
|
||||||
|
get => _colorFirstLedOnly;
|
||||||
|
set => RaiseAndSetIfChanged(ref _colorFirstLedOnly, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableCollection<SurfaceDeviceViewModel> SurfaceDeviceViewModels { get; }
|
public ObservableCollection<SurfaceDeviceViewModel> SurfaceDeviceViewModels { get; }
|
||||||
public ObservableCollection<ListDeviceViewModel> ListDeviceViewModels { get; }
|
public ObservableCollection<ListDeviceViewModel> ListDeviceViewModels { get; }
|
||||||
|
|
||||||
|
public ReactiveCommand<Unit, Unit> AutoArrange { get; }
|
||||||
|
public ReactiveCommand<ArtemisDevice, Unit> IdentifyDevice { get; }
|
||||||
|
public ReactiveCommand<ArtemisDevice, Unit> ViewProperties { get; }
|
||||||
public ReactiveCommand<ArtemisDevice, Unit> BringToFront { get; }
|
public ReactiveCommand<ArtemisDevice, Unit> BringToFront { get; }
|
||||||
public ReactiveCommand<ArtemisDevice, Unit> BringForward { get; }
|
public ReactiveCommand<ArtemisDevice, Unit> BringForward { get; }
|
||||||
public ReactiveCommand<ArtemisDevice, Unit> SendToBack { get; }
|
public ReactiveCommand<ArtemisDevice, Unit> SendToBack { get; }
|
||||||
@ -108,15 +149,63 @@ public class SurfaceEditorViewModel : MainScreenViewModel
|
|||||||
foreach (SurfaceDeviceViewModel surfaceDeviceViewModel in SurfaceDeviceViewModels)
|
foreach (SurfaceDeviceViewModel surfaceDeviceViewModel in SurfaceDeviceViewModels)
|
||||||
surfaceDeviceViewModel.UpdateMouseDrag(mousePosition, round, ignoreOverlap);
|
surfaceDeviceViewModel.UpdateMouseDrag(mousePosition, round, ignoreOverlap);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplySurfaceSelection()
|
private async Task ExecuteAutoArrange()
|
||||||
{
|
{
|
||||||
foreach (ListDeviceViewModel viewModel in ListDeviceViewModels)
|
bool confirmed = await _windowService.ShowConfirmContentDialog("Auto-arrange layout", "Are you sure you want to auto-arrange your layout? Your current settings will be overwritten.");
|
||||||
viewModel.IsSelected = SurfaceDeviceViewModels.Any(s => s.Device == viewModel.Device && s.IsSelected);
|
if (!confirmed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_rgbService.AutoArrangeDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CoreServiceOnFrameRendering(object? sender, FrameRenderingEventArgs e)
|
||||||
|
{
|
||||||
|
// Animate the overlay because I'm vain
|
||||||
|
if (ColorDevices && _overlayOpacity < 1)
|
||||||
|
_overlayOpacity = Math.Min(1, _overlayOpacity + e.DeltaTime * 3);
|
||||||
|
else if (!ColorDevices && _overlayOpacity > 0)
|
||||||
|
_overlayOpacity = Math.Max(0, _overlayOpacity - e.DeltaTime * 3);
|
||||||
|
|
||||||
|
if (_overlayOpacity == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
using SKPaint paint = new();
|
||||||
|
byte alpha = (byte) (Easings.CubicEaseInOut(_overlayOpacity) * 255);
|
||||||
|
|
||||||
|
// Fill the entire canvas with a black backdrop
|
||||||
|
paint.Color = SKColors.Black.WithAlpha(alpha);
|
||||||
|
e.Canvas.DrawRect(e.Canvas.LocalClipBounds, paint);
|
||||||
|
|
||||||
|
// Draw a rectangle for each LED
|
||||||
|
foreach (ListDeviceViewModel listDeviceViewModel in ListDeviceViewModels)
|
||||||
|
{
|
||||||
|
// Order by position to accurately get the first LED
|
||||||
|
List<ArtemisLed> leds = listDeviceViewModel.Device.Leds.OrderBy(l => l.RgbLed.Location.Y).ThenBy(l => l.RgbLed.Location.X).ToList();
|
||||||
|
for (int index = 0; index < leds.Count; index++)
|
||||||
|
{
|
||||||
|
ArtemisLed artemisLed = leds[index];
|
||||||
|
if (ColorFirstLedOnly && index == 0 || !ColorFirstLedOnly)
|
||||||
|
{
|
||||||
|
paint.Color = listDeviceViewModel.Color.WithAlpha(alpha);
|
||||||
|
e.Canvas.DrawRect(artemisLed.AbsoluteRectangle, paint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Context menu commands
|
#region Context menu commands
|
||||||
|
|
||||||
|
private void ExecuteIdentifyDevice(ArtemisDevice device)
|
||||||
|
{
|
||||||
|
_deviceService.IdentifyDevice(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ExecuteViewProperties(ArtemisDevice device)
|
||||||
|
{
|
||||||
|
await _windowService.ShowDialogAsync(_deviceVmFactory.DevicePropertiesViewModel(device));
|
||||||
|
}
|
||||||
|
|
||||||
private void ExecuteBringToFront(ArtemisDevice device)
|
private void ExecuteBringToFront(ArtemisDevice device)
|
||||||
{
|
{
|
||||||
SurfaceDeviceViewModel surfaceDeviceViewModel = SurfaceDeviceViewModels.First(d => d.Device == device);
|
SurfaceDeviceViewModel surfaceDeviceViewModel = SurfaceDeviceViewModels.First(d => d.Device == device);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user