1
0
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:
SpoinkyNL 2020-04-22 19:55:23 +02:00
parent 341eb99489
commit 8bc33de401
17 changed files with 337 additions and 99 deletions

View File

@ -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)

View File

@ -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();
}

View File

@ -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)

View File

@ -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>

View File

@ -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>

View File

@ -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"

View File

@ -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>

View File

@ -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();
}
}
}

View File

@ -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

View File

@ -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>

View File

@ -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)

View File

@ -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" />

View File

@ -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);
}
}
}

View File

@ -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">

View File

@ -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
}
}

View File

@ -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="*" />

View File

@ -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),