mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Profile editor - Clarified which LEDs are part of the selected layer
Profile editor - Re-implemented LED dimming Profile editor - Hide layer bounds of unselected layers Profile editor - Dim layer shapes of unselected layers (option to hide them NYI) Profile editor - Disable edit tool when no layer is selected or the selected layer has no LEDs Gradient picker - Fixed the preview being at a slight angle Color brush - Fixed the gradient being at a 45 degree angle Settings - Added color scheme option to manually switch between light and dark
This commit is contained in:
parent
341eb99489
commit
8bc33de401
@ -40,26 +40,29 @@ namespace Artemis.Core.Models.Profile
|
||||
// Ensure order integrity, should be unnecessary but no one is perfect specially me
|
||||
_children = _children.OrderBy(c => c.Order).ToList();
|
||||
for (var index = 0; index < _children.Count; index++)
|
||||
{
|
||||
var profileElement = _children[index];
|
||||
profileElement.Order = index + 1;
|
||||
}
|
||||
_children[index].Order = index + 1;
|
||||
}
|
||||
|
||||
internal FolderEntity FolderEntity { get; set; }
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
// Folders don't update but their children do
|
||||
foreach (var profileElement in Children)
|
||||
// Iterate the children in reverse because that's how they must be rendered too
|
||||
for (var index = Children.Count - 1; index > -1; index--)
|
||||
{
|
||||
var profileElement = Children[index];
|
||||
profileElement.Update(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo)
|
||||
{
|
||||
// Folders don't render but their children do
|
||||
foreach (var profileElement in Children)
|
||||
// Iterate the children in reverse because the first layer must be rendered last to end up on top
|
||||
for (var index = Children.Count - 1; index > -1; index--)
|
||||
{
|
||||
var profileElement = Children[index];
|
||||
profileElement.Render(deltaTime, canvas, canvasInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public Folder AddFolder(string name)
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Artemis.Core.Models.Surface;
|
||||
using RGB.NET.Core;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Shared.Controls
|
||||
{
|
||||
@ -18,6 +20,9 @@ namespace Artemis.UI.Shared.Controls
|
||||
public static readonly DependencyProperty ShowColorsProperty = DependencyProperty.Register(nameof(ShowColors), typeof(bool), typeof(DeviceVisualizer),
|
||||
new FrameworkPropertyMetadata(default(bool), FrameworkPropertyMetadataOptions.AffectsRender, ShowColorsPropertyChangedCallback));
|
||||
|
||||
public static readonly DependencyProperty HighlightedLedsProperty = DependencyProperty.Register(nameof(HighlightedLeds), typeof(IEnumerable<ArtemisLed>), typeof(DeviceVisualizer),
|
||||
new FrameworkPropertyMetadata(default(IEnumerable<ArtemisLed>)));
|
||||
|
||||
private readonly DrawingGroup _backingStore;
|
||||
private readonly List<DeviceVisualizerLed> _deviceVisualizerLeds;
|
||||
private BitmapImage _deviceImage;
|
||||
@ -57,6 +62,12 @@ namespace Artemis.UI.Shared.Controls
|
||||
set => SetValue(ShowColorsProperty, value);
|
||||
}
|
||||
|
||||
public IEnumerable<ArtemisLed> HighlightedLeds
|
||||
{
|
||||
get => (IEnumerable<ArtemisLed>) GetValue(HighlightedLedsProperty);
|
||||
set => SetValue(HighlightedLedsProperty, value);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
RGBSurface.Instance.Updated -= RgbSurfaceOnUpdated;
|
||||
@ -159,8 +170,17 @@ namespace Artemis.UI.Shared.Controls
|
||||
{
|
||||
var drawingContext = _backingStore.Open();
|
||||
|
||||
foreach (var deviceVisualizerLed in _deviceVisualizerLeds)
|
||||
deviceVisualizerLed.RenderColor(drawingContext);
|
||||
if (HighlightedLeds.Any())
|
||||
{
|
||||
foreach (var deviceVisualizerLed in _deviceVisualizerLeds)
|
||||
deviceVisualizerLed.RenderColor(drawingContext, !HighlightedLeds.Contains(deviceVisualizerLed.Led));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var deviceVisualizerLed in _deviceVisualizerLeds)
|
||||
deviceVisualizerLed.RenderColor(drawingContext, false);
|
||||
}
|
||||
|
||||
|
||||
drawingContext.Close();
|
||||
}
|
||||
|
||||
@ -23,11 +23,11 @@ namespace Artemis.UI.Shared.Controls
|
||||
|
||||
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; }
|
||||
@ -60,7 +60,6 @@ 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);
|
||||
// Try to gain some performance
|
||||
DisplayGeometry = DisplayGeometry.GetFlattenedPathGeometry();
|
||||
DisplayGeometry.Freeze();
|
||||
}
|
||||
|
||||
@ -103,7 +102,7 @@ namespace Artemis.UI.Shared.Controls
|
||||
}
|
||||
}
|
||||
|
||||
public void RenderColor(DrawingContext drawingContext)
|
||||
public void RenderColor(DrawingContext drawingContext, bool isDimmed)
|
||||
{
|
||||
if (DisplayGeometry == null)
|
||||
return;
|
||||
@ -111,8 +110,10 @@ namespace Artemis.UI.Shared.Controls
|
||||
var r = Led.RgbLed.Color.GetR();
|
||||
var g = Led.RgbLed.Color.GetG();
|
||||
var b = Led.RgbLed.Color.GetB();
|
||||
|
||||
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromRgb(r, g, b)), null, LedRect);
|
||||
|
||||
drawingContext.DrawRectangle(isDimmed
|
||||
? new SolidColorBrush(Color.FromArgb(100, r, g, b))
|
||||
: new SolidColorBrush(Color.FromRgb(r, g, b)), null, LedRect);
|
||||
}
|
||||
|
||||
public void RenderImage(DrawingContext drawingContext)
|
||||
|
||||
@ -41,7 +41,9 @@
|
||||
Background="{StaticResource Checkerboard}">
|
||||
<Rectangle Stroke="{DynamicResource NormalBorderBrush}" Cursor="Hand" MouseUp="UIElement_OnMouseUp">
|
||||
<Rectangle.Fill>
|
||||
<LinearGradientBrush GradientStops="{Binding ColorGradient.Stops, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource ColorGradientToGradientStopsConverter}}" />
|
||||
<LinearGradientBrush GradientStops="{Binding ColorGradient.Stops, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource ColorGradientToGradientStopsConverter}}"
|
||||
EndPoint="1,0"
|
||||
StartPoint="0,0"/>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
</Border>
|
||||
|
||||
@ -53,7 +53,9 @@
|
||||
utilities:SizeObserver.ObservedWidth="{Binding PreviewWidth, Mode=OneWayToSource}">
|
||||
<Rectangle.Fill>
|
||||
<LinearGradientBrush
|
||||
GradientStops="{Binding ColorGradient.Stops, Converter={StaticResource ColorGradientToGradientStopsConverter}}" />
|
||||
GradientStops="{Binding ColorGradient.Stops, Converter={StaticResource ColorGradientToGradientStopsConverter}}"
|
||||
EndPoint="1,0"
|
||||
StartPoint="0,0"/>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
|
||||
@ -121,7 +121,7 @@
|
||||
</DockPanel>
|
||||
|
||||
<!-- Properties tree -->
|
||||
<materialDesign:DialogHost Identifier="PropertyTreeDialogHost" CloseOnClickAway="True" Grid.Row="1">
|
||||
<materialDesign:DialogHost Identifier="PropertyTreeDialogHost" DialogTheme="Inherit" CloseOnClickAway="True" Grid.Row="1">
|
||||
<ScrollViewer x:Name="PropertyTreeScrollViewer"
|
||||
HorizontalScrollBarVisibility="Hidden"
|
||||
VerticalScrollBarVisibility="Hidden"
|
||||
|
||||
@ -10,22 +10,42 @@
|
||||
d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance {x:Type local:ProfileLayerViewModel}}">
|
||||
<UserControl.Resources>
|
||||
<Style TargetType="{x:Type Canvas}" x:Key="SelectedStyle">
|
||||
<Style TargetType="{x:Type Path}" x:Key="SelectedShapeStyle">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsSelected}" Value="False">
|
||||
<DataTrigger.EnterActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Opacity)" To="0.8"
|
||||
Duration="0:0:0.25" />
|
||||
<ColorAnimation Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)" To="Gray" Duration="0:0:0.5"/>
|
||||
<DoubleAnimation Storyboard.TargetProperty="(Path.StrokeThickness)" To="0.5" Duration="0:0:0.5" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
<DataTrigger.ExitActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Opacity)" To="1"
|
||||
Duration="0:0:0.25" />
|
||||
<ColorAnimation Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)" To="{StaticResource Accent700}" Duration="0:0:0.5"/>
|
||||
<DoubleAnimation Storyboard.TargetProperty="(Path.StrokeThickness)" To="1" Duration="0:0:0.5" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.ExitActions>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style TargetType="{x:Type Path}" x:Key="SelectedLayerStyle">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsSelected}" Value="False">
|
||||
<DataTrigger.EnterActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetProperty="(Path.Opacity)" To="0" Duration="0:0:0.5" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
<DataTrigger.ExitActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetProperty="(Path.Opacity)" To="1" Duration="0:0:0.5" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.ExitActions>
|
||||
@ -33,29 +53,23 @@
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
<Canvas Style="{StaticResource SelectedStyle}">
|
||||
|
||||
|
||||
<!-- The part of the layer's shape that is inside the layer -->
|
||||
<Path Data="{Binding ShapeGeometry, Mode=OneWay}">
|
||||
<Path.Fill>
|
||||
<SolidColorBrush Color="{StaticResource Accent700}" Opacity="0.15" />
|
||||
</Path.Fill>
|
||||
<Canvas>
|
||||
<!-- The part of the layer's shape that falls outside the layer -->
|
||||
<Path Data="{Binding ShapeGeometry, Mode=OneWay}"
|
||||
StrokeThickness="0.5"
|
||||
Style="{StaticResource SelectedShapeStyle}">
|
||||
<Path.Stroke>
|
||||
<SolidColorBrush Color="{StaticResource Accent700}" />
|
||||
<SolidColorBrush Color="{StaticResource Primary700}" />
|
||||
</Path.Stroke>
|
||||
</Path>
|
||||
|
||||
<Rectangle Width="{Binding LayerRect.Width}"
|
||||
Height="{Binding LayerRect.Height}"
|
||||
Margin="{Binding LayerRectMargin}"
|
||||
StrokeThickness="1"
|
||||
StrokeDashArray="4 2"
|
||||
StrokeLineJoin="Round"
|
||||
x:Name="LayerPath">
|
||||
<Rectangle.Stroke>
|
||||
<SolidColorBrush Color="{StaticResource Accent400}" />
|
||||
</Rectangle.Stroke>
|
||||
</Rectangle>
|
||||
<Path Data="{Binding LayerGeometry, Mode=OneWay}"
|
||||
ClipToBounds="False"
|
||||
Stroke="#A7A7A7"
|
||||
StrokeThickness="1"
|
||||
StrokeLineJoin="Round"
|
||||
x:Name="LayerPath"
|
||||
Style="{StaticResource SelectedLayerStyle}">
|
||||
</Path>
|
||||
</Canvas>
|
||||
</UserControl>
|
||||
@ -1,15 +0,0 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ProfileLayerView.xaml
|
||||
/// </summary>
|
||||
public partial class ProfileLayerView : UserControl
|
||||
{
|
||||
public ProfileLayerView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,17 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Artemis.Core.Models.Profile;
|
||||
using Artemis.Core.Models.Profile.LayerShapes;
|
||||
using Artemis.Core.Models.Surface;
|
||||
using Artemis.UI.Extensions;
|
||||
using Artemis.UI.Services.Interfaces;
|
||||
using RGB.NET.Core;
|
||||
using Stylet;
|
||||
using Rectangle = Artemis.Core.Models.Profile.LayerShapes.Rectangle;
|
||||
|
||||
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||
{
|
||||
@ -28,10 +34,14 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||
}
|
||||
|
||||
public Layer Layer { get; }
|
||||
public Rect LayerRect { get; set; }
|
||||
public Thickness LayerRectMargin => LayerRect == Rect.Empty ? new Thickness() : new Thickness(LayerRect.Left, LayerRect.Top, 0, 0);
|
||||
public bool IsSelected { get; set; }
|
||||
|
||||
public Geometry LayerGeometry { get; set; }
|
||||
public Geometry OpacityGeometry { get; set; }
|
||||
public Geometry ShapeGeometry { get; set; }
|
||||
public RenderTargetBitmap LayerGeometryBitmap { get; set; }
|
||||
public Rect ViewportRectangle { get; set; }
|
||||
public Thickness LayerPosition => new Thickness(ViewportRectangle.Left, ViewportRectangle.Top, 0, 0);
|
||||
public bool IsSelected { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
@ -44,12 +54,68 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||
private void Update()
|
||||
{
|
||||
IsSelected = _profileEditorService.SelectedProfileElement == Layer;
|
||||
if (!Layer.Leds.Any() || Layer.LayerShape == null)
|
||||
LayerRect = Rect.Empty;
|
||||
else
|
||||
LayerRect = _layerEditorService.GetLayerBounds(Layer);
|
||||
|
||||
CreateLayerGeometry();
|
||||
CreateShapeGeometry();
|
||||
CreateViewportRectangle();
|
||||
}
|
||||
|
||||
private void CreateLayerGeometry()
|
||||
{
|
||||
if (!Layer.Leds.Any())
|
||||
{
|
||||
LayerGeometry = Geometry.Empty;
|
||||
OpacityGeometry = Geometry.Empty;
|
||||
ViewportRectangle = Rect.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
var group = new GeometryGroup();
|
||||
group.FillRule = FillRule.Nonzero;
|
||||
|
||||
foreach (var led in Layer.Leds)
|
||||
{
|
||||
Geometry geometry;
|
||||
switch (led.RgbLed.Shape)
|
||||
{
|
||||
case Shape.Custom:
|
||||
if (led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
|
||||
geometry = CreateCustomGeometry(led, 2);
|
||||
else
|
||||
geometry = CreateCustomGeometry(led, 1);
|
||||
break;
|
||||
case Shape.Rectangle:
|
||||
geometry = CreateRectangleGeometry(led);
|
||||
break;
|
||||
case Shape.Circle:
|
||||
geometry = CreateCircleGeometry(led);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
group.Children.Add(geometry);
|
||||
}
|
||||
|
||||
var layerGeometry = group.GetOutlinedPathGeometry();
|
||||
var opacityGeometry = Geometry.Combine(Geometry.Empty, layerGeometry, GeometryCombineMode.Exclude, new TranslateTransform());
|
||||
|
||||
LayerGeometry = layerGeometry;
|
||||
OpacityGeometry = opacityGeometry;
|
||||
|
||||
// Render the store as a bitmap
|
||||
var drawingImage = new DrawingImage(new GeometryDrawing(new SolidColorBrush(Colors.Black), null, LayerGeometry));
|
||||
var image = new Image {Source = drawingImage};
|
||||
var bitmap = new RenderTargetBitmap(
|
||||
(int) (LayerGeometry.Bounds.Width * 2.5),
|
||||
(int) (LayerGeometry.Bounds.Height * 2.5),
|
||||
96,
|
||||
96,
|
||||
PixelFormats.Pbgra32
|
||||
);
|
||||
image.Arrange(new Rect(0, 0, bitmap.Width, bitmap.Height));
|
||||
bitmap.Render(image);
|
||||
bitmap.Freeze();
|
||||
LayerGeometryBitmap = bitmap;
|
||||
}
|
||||
|
||||
private void CreateShapeGeometry()
|
||||
@ -79,6 +145,59 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||
});
|
||||
}
|
||||
|
||||
private void CreateViewportRectangle()
|
||||
{
|
||||
if (!Layer.Leds.Any() || Layer.LayerShape == null)
|
||||
{
|
||||
ViewportRectangle = Rect.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
ViewportRectangle = _layerEditorService.GetLayerBounds(Layer);
|
||||
}
|
||||
|
||||
private Geometry CreateRectangleGeometry(ArtemisLed led)
|
||||
{
|
||||
var rect = led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1);
|
||||
rect.Inflate(1, 1);
|
||||
return new RectangleGeometry(rect);
|
||||
}
|
||||
|
||||
private Geometry CreateCircleGeometry(ArtemisLed led)
|
||||
{
|
||||
var rect = led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1);
|
||||
rect.Inflate(1, 1);
|
||||
return new EllipseGeometry(rect);
|
||||
}
|
||||
|
||||
private Geometry CreateCustomGeometry(ArtemisLed led, double deflateAmount)
|
||||
{
|
||||
var rect = led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1);
|
||||
rect.Inflate(1, 1);
|
||||
try
|
||||
{
|
||||
var 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 Event handlers
|
||||
|
||||
private void LayerOnRenderPropertiesUpdated(object sender, EventArgs e)
|
||||
@ -98,7 +217,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||
|
||||
private void ProfileEditorServiceOnProfilePreviewUpdated(object sender, EventArgs e)
|
||||
{
|
||||
Update();
|
||||
CreateShapeGeometry();
|
||||
CreateViewportRectangle();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -57,7 +57,7 @@
|
||||
<ListBoxItem ToolTip="Pan over different parts of the surface">
|
||||
<materialDesign:PackIcon Kind="HandLeft" />
|
||||
</ListBoxItem>
|
||||
<ListBoxItem ToolTip="Edit shape in layer">
|
||||
<ListBoxItem ToolTip="Edit shape in layer" IsEnabled="{Binding CanSelectEditTool}">
|
||||
<materialDesign:PackIcon Kind="Edit" />
|
||||
</ListBoxItem>
|
||||
<ListBoxItem ToolTip="Change layer selection (hold SHIFT to add to existing selection)">
|
||||
@ -122,7 +122,9 @@
|
||||
</ItemsControl.ItemContainerStyle>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:DeviceVisualizer Device="{Binding}" ShowColors="True"/>
|
||||
<controls:DeviceVisualizer Device="{Binding}"
|
||||
ShowColors="True"
|
||||
HighlightedLeds="{Binding DataContext.HighlightedLeds, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Mode=OneWay}"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
@ -158,11 +160,11 @@
|
||||
<StackPanel ZIndex="1" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="10">
|
||||
<materialDesign:Card Padding="8">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<CheckBox Style="{StaticResource MaterialDesignCheckBox}" IsChecked="{Binding HighlightSelectedLayer.Value}">
|
||||
Dim LEDs outside selected layer
|
||||
<CheckBox Style="{StaticResource MaterialDesignCheckBox}" IsChecked="{Binding OnlyShowSelectedShape.Value}" IsEnabled="False">
|
||||
Only show shape of selected layer (NYI)
|
||||
</CheckBox>
|
||||
<CheckBox Style="{StaticResource MaterialDesignCheckBox}" Margin="10 0 0 0" IsChecked="{Binding PauseRenderingOnFocusLoss.Value}">
|
||||
Pause visualization on focus loss
|
||||
<CheckBox Style="{StaticResource MaterialDesignCheckBox}" Margin="10 0 0 0" IsChecked="{Binding HighlightSelectedLayer.Value}">
|
||||
Highlight LEDs of selected layer
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
</materialDesign:Card>
|
||||
|
||||
@ -51,7 +51,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||
|
||||
CanvasViewModels = new BindableCollection<CanvasViewModel>();
|
||||
Devices = new BindableCollection<ArtemisDevice>();
|
||||
DimmedLeds = new BindableCollection<ArtemisLed>();
|
||||
HighlightedLeds = new BindableCollection<ArtemisLed>();
|
||||
SelectedLeds = new BindableCollection<ArtemisLed>();
|
||||
});
|
||||
|
||||
@ -64,21 +64,22 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||
|
||||
|
||||
public bool IsInitializing { get; private set; }
|
||||
public bool CanSelectEditTool { get; set; }
|
||||
|
||||
public PanZoomViewModel PanZoomViewModel { get; set; }
|
||||
|
||||
public BindableCollection<CanvasViewModel> CanvasViewModels { get; set; }
|
||||
public BindableCollection<ArtemisDevice> Devices { get; set; }
|
||||
public BindableCollection<ArtemisLed> DimmedLeds { get; set; }
|
||||
public BindableCollection<ArtemisLed> HighlightedLeds { get; set; }
|
||||
public BindableCollection<ArtemisLed> SelectedLeds { get; set; }
|
||||
|
||||
public PluginSetting<bool> OnlyShowSelectedShape { get; set; }
|
||||
public PluginSetting<bool> HighlightSelectedLayer { get; set; }
|
||||
public PluginSetting<bool> PauseRenderingOnFocusLoss { get; set; }
|
||||
|
||||
public VisualizationToolViewModel ActiveToolViewModel
|
||||
{
|
||||
get => _activeToolViewModel;
|
||||
set
|
||||
private set
|
||||
{
|
||||
// Remove the tool from the canvas
|
||||
if (_activeToolViewModel != null)
|
||||
@ -120,8 +121,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||
|
||||
protected override void OnInitialActivate()
|
||||
{
|
||||
OnlyShowSelectedShape = _settingsService.GetSetting("ProfileEditor.OnlyShowSelectedShape", true);
|
||||
HighlightSelectedLayer = _settingsService.GetSetting("ProfileEditor.HighlightSelectedLayer", true);
|
||||
PauseRenderingOnFocusLoss = _settingsService.GetSetting("ProfileEditor.PauseRenderingOnFocusLoss", true);
|
||||
|
||||
HighlightSelectedLayer.SettingChanged += HighlightSelectedLayerOnSettingChanged;
|
||||
_surfaceService.ActiveSurfaceConfigurationSelected += OnActiveSurfaceConfigurationSelected;
|
||||
@ -131,7 +132,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||
|
||||
base.OnInitialActivate();
|
||||
}
|
||||
|
||||
|
||||
protected override void OnClose()
|
||||
{
|
||||
HighlightSelectedLayer.SettingChanged -= HighlightSelectedLayerOnSettingChanged;
|
||||
@ -140,8 +141,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||
_profileEditorService.ProfileElementSelected -= OnProfileElementSelected;
|
||||
_profileEditorService.SelectedProfileElementUpdated -= OnSelectedProfileElementUpdated;
|
||||
|
||||
OnlyShowSelectedShape.Save();
|
||||
HighlightSelectedLayer.Save();
|
||||
PauseRenderingOnFocusLoss.Save();
|
||||
|
||||
base.OnClose();
|
||||
}
|
||||
@ -183,9 +184,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||
|
||||
private void UpdateLedsDimStatus()
|
||||
{
|
||||
DimmedLeds.Clear();
|
||||
HighlightedLeds.Clear();
|
||||
if (HighlightSelectedLayer.Value && _profileEditorService.SelectedProfileElement is Layer layer)
|
||||
DimmedLeds.AddRange(layer.Leds);
|
||||
HighlightedLeds.AddRange(layer.Leds);
|
||||
}
|
||||
|
||||
#region Buttons
|
||||
@ -300,14 +301,38 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
|
||||
private void OnProfileElementSelected(object sender, EventArgs e)
|
||||
{
|
||||
UpdateLedsDimStatus();
|
||||
CanApplyToLayer = _profileEditorService.SelectedProfileElement is Layer;
|
||||
if (_profileEditorService.SelectedProfileElement is Layer layer)
|
||||
{
|
||||
CanApplyToLayer = true;
|
||||
CanSelectEditTool = layer.Leds.Any();
|
||||
}
|
||||
else
|
||||
{
|
||||
CanApplyToLayer = false;
|
||||
CanSelectEditTool = false;
|
||||
}
|
||||
if (CanSelectEditTool == false && ActiveToolIndex == 1)
|
||||
ActivateToolByIndex(2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void OnSelectedProfileElementUpdated(object sender, EventArgs e)
|
||||
{
|
||||
ApplyActiveProfile();
|
||||
UpdateLedsDimStatus();
|
||||
CanApplyToLayer = _profileEditorService.SelectedProfileElement is Layer;
|
||||
if (_profileEditorService.SelectedProfileElement is Layer layer)
|
||||
{
|
||||
CanApplyToLayer = true;
|
||||
CanSelectEditTool = layer.Leds.Any();
|
||||
}
|
||||
else
|
||||
{
|
||||
CanApplyToLayer = false;
|
||||
CanSelectEditTool = false;
|
||||
}
|
||||
if (CanSelectEditTool == false && ActiveToolIndex == 1)
|
||||
ActivateToolByIndex(2);
|
||||
}
|
||||
|
||||
public void Handle(MainWindowFocusChangedEvent message)
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</mde:MaterialWindow.Resources>
|
||||
<materialDesign:DialogHost Identifier="RootDialog">
|
||||
<materialDesign:DialogHost Identifier="RootDialog" DialogTheme="Inherit">
|
||||
<materialDesign:DrawerHost IsLeftDrawerOpen="{Binding IsSidebarVisible}">
|
||||
<materialDesign:DrawerHost.LeftDrawerContent>
|
||||
<ContentControl s:View.Model="{Binding SidebarViewModel}" Width="220" ClipToBounds="False" />
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
using System.ComponentModel;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using Artemis.Core.Plugins.Models;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Events;
|
||||
using Artemis.UI.Screens.Settings;
|
||||
using Artemis.UI.Screens.Sidebar;
|
||||
using Artemis.UI.Utilities;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
@ -14,15 +18,19 @@ namespace Artemis.UI.Screens
|
||||
{
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private bool _lostFocus;
|
||||
private PluginSetting<ApplicationColorScheme> _colorScheme;
|
||||
private ThemeWatcher _themeWatcher;
|
||||
|
||||
public RootViewModel(IEventAggregator eventAggregator, SidebarViewModel sidebarViewModel)
|
||||
public RootViewModel(IEventAggregator eventAggregator, SidebarViewModel sidebarViewModel, ISettingsService settingsService)
|
||||
{
|
||||
SidebarViewModel = sidebarViewModel;
|
||||
_eventAggregator = eventAggregator;
|
||||
|
||||
var themeWatcher = new ThemeWatcher();
|
||||
themeWatcher.ThemeChanged += (sender, args) => ApplyWindowsTheme(args.Theme);
|
||||
ApplyWindowsTheme(themeWatcher.GetWindowsTheme());
|
||||
_colorScheme = settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic);
|
||||
_colorScheme.SettingChanged += (sender, args) => ApplyColorSchemeSetting();
|
||||
_themeWatcher = new ThemeWatcher();
|
||||
_themeWatcher.ThemeChanged += (sender, args) => ApplyWindowsTheme(args.Theme);
|
||||
ApplyColorSchemeSetting();
|
||||
|
||||
ActiveItem = SidebarViewModel.SelectedItem;
|
||||
ActiveItemReady = true;
|
||||
@ -79,18 +87,34 @@ namespace Artemis.UI.Screens
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyColorSchemeSetting()
|
||||
{
|
||||
if (_colorScheme.Value == ApplicationColorScheme.Automatic)
|
||||
ApplyWindowsTheme(_themeWatcher.GetWindowsTheme());
|
||||
else
|
||||
ChangeMaterialColors(_colorScheme.Value);
|
||||
}
|
||||
|
||||
private void ApplyWindowsTheme(ThemeWatcher.WindowsTheme windowsTheme)
|
||||
{
|
||||
if (_colorScheme.Value != ApplicationColorScheme.Automatic)
|
||||
return;
|
||||
|
||||
if (windowsTheme == ThemeWatcher.WindowsTheme.Dark)
|
||||
ChangeMaterialColors(ApplicationColorScheme.Dark);
|
||||
else
|
||||
ChangeMaterialColors(ApplicationColorScheme.Light);
|
||||
}
|
||||
|
||||
private void ChangeMaterialColors(ApplicationColorScheme colorScheme)
|
||||
{
|
||||
var paletteHelper = new PaletteHelper();
|
||||
var theme = paletteHelper.GetTheme();
|
||||
theme.SetBaseTheme(windowsTheme == ThemeWatcher.WindowsTheme.Dark ? Theme.Dark : Theme.Light);
|
||||
theme.SetBaseTheme(colorScheme == ApplicationColorScheme.Dark ? Theme.Dark : Theme.Light);
|
||||
paletteHelper.SetTheme(theme);
|
||||
|
||||
var extensionsPaletteHelper = new MaterialDesignExtensions.Themes.PaletteHelper();
|
||||
// That's nice, then don't use it in your own examples and provide a working alternative
|
||||
#pragma warning disable 612
|
||||
extensionsPaletteHelper.SetLightDark(windowsTheme == ThemeWatcher.WindowsTheme.Dark);
|
||||
#pragma warning restore 612
|
||||
extensionsPaletteHelper.SetLightDark(colorScheme == ApplicationColorScheme.Dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,6 +62,27 @@
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Color scheme</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
|
||||
Pick between a light and dark color scheme, the automatic option copies your Windows settings.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<ComboBox Width="80" SelectedValue="{Binding SelectedColorScheme}" ItemsSource="{Binding ColorSchemes}" SelectedValuePath="Value" DisplayMemberPath="Description" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
@ -143,7 +164,7 @@
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Log level</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
|
||||
Sets the logging level, a verbose logging level will result in more log files.
|
||||
Sets the logging level, a higher logging level will result in more log files.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
|
||||
@ -57,6 +57,7 @@ namespace Artemis.UI.Screens.Settings
|
||||
Plugins = new BindableCollection<PluginSettingsViewModel>();
|
||||
|
||||
LogLevels = EnumUtilities.GetAllValuesAndDescriptions(typeof(LogEventLevel));
|
||||
ColorSchemes = EnumUtilities.GetAllValuesAndDescriptions(typeof(ApplicationColorScheme));
|
||||
RenderScales = new List<Tuple<string, double>> {new Tuple<string, double>("10%", 0.1)};
|
||||
for (var i = 25; i <= 100; i += 25)
|
||||
RenderScales.Add(new Tuple<string, double>(i + "%", i / 100.0));
|
||||
@ -72,6 +73,7 @@ namespace Artemis.UI.Screens.Settings
|
||||
public List<Tuple<string, int>> TargetFrameRates { get; set; }
|
||||
public List<Tuple<string, double>> RenderScales { get; set; }
|
||||
public IEnumerable<ValueDescription> LogLevels { get; }
|
||||
public IEnumerable<ValueDescription> ColorSchemes { get; }
|
||||
|
||||
public List<int> SampleSizes { get; set; }
|
||||
public BindableCollection<DeviceSettingsViewModel> DeviceSettingsViewModels { get; set; }
|
||||
@ -118,6 +120,16 @@ namespace Artemis.UI.Screens.Settings
|
||||
_settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Information).Value = value;
|
||||
_settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Information).Save();
|
||||
}
|
||||
}
|
||||
|
||||
public ApplicationColorScheme SelectedColorScheme
|
||||
{
|
||||
get => _settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic).Value;
|
||||
set
|
||||
{
|
||||
_settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic).Value = value;
|
||||
_settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic).Save();
|
||||
}
|
||||
}
|
||||
|
||||
public double RenderScale
|
||||
@ -218,4 +230,11 @@ namespace Artemis.UI.Screens.Settings
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ApplicationColorScheme
|
||||
{
|
||||
Light,
|
||||
Dark,
|
||||
Automatic
|
||||
}
|
||||
}
|
||||
@ -190,7 +190,7 @@
|
||||
<GridSplitter Grid.Column="1" Grid.Row="1" Width="5" HorizontalAlignment="Stretch" Cursor="SizeWE" />
|
||||
|
||||
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" Grid.Row="1" Grid.Column="2" VerticalAlignment="Stretch" Margin="5,0,0,0">
|
||||
<materialDesign:DialogHost Identifier="SurfaceListDialogHost" CloseOnClickAway="True">
|
||||
<materialDesign:DialogHost Identifier="SurfaceListDialogHost" DialogTheme="Inherit" CloseOnClickAway="True">
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
|
||||
@ -78,7 +78,7 @@ namespace Artemis.Plugins.LayerBrushes.Color
|
||||
GradientType.Solid => SKShader.CreateColor(_color),
|
||||
GradientType.LinearGradient => SKShader.CreateLinearGradient(
|
||||
new SKPoint(_shaderBounds.Left, _shaderBounds.Top),
|
||||
new SKPoint(_shaderBounds.Right, _shaderBounds.Bottom),
|
||||
new SKPoint(_shaderBounds.Right, _shaderBounds.Top),
|
||||
GradientProperty.Value.GetColorsArray(),
|
||||
GradientProperty.Value.GetPositionsArray(),
|
||||
SKShaderTileMode.Repeat),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user