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

Need this on another PC :))

This commit is contained in:
Robert 2019-12-17 20:27:50 +01:00
parent 6cf9fb9158
commit 94df1544c5
13 changed files with 232 additions and 77 deletions

View File

@ -98,7 +98,7 @@ namespace Artemis.Core.Models.Profile
{
_layerShape = value;
if (Path != null)
_layerShape.CalculateRenderProperties();
CalculateRenderProperties();
}
}
@ -221,7 +221,13 @@ namespace Artemis.Core.Models.Profile
internal void CalculateRenderProperties()
{
if (!Leds.Any())
{
Rectangle = SKRect.Empty;
AbsoluteRectangle = SKRect.Empty;
Path = new SKPath();
OnRenderPropertiesUpdated();
return;
}
// Determine to top-left and bottom-right
var minX = Leds.Min(l => l.AbsoluteRenderRectangle.Left);
@ -237,6 +243,7 @@ namespace Artemis.Core.Models.Profile
path.AddRect(artemisLed.AbsoluteRenderRectangle);
Path = path;
LayerShape.CalculateRenderProperties();
OnRenderPropertiesUpdated();
}
@ -248,12 +255,18 @@ namespace Artemis.Core.Models.Profile
#region Events
public event EventHandler RenderPropertiesUpdated;
public event EventHandler ShapePropertiesUpdated;
private void OnRenderPropertiesUpdated()
{
RenderPropertiesUpdated?.Invoke(this, EventArgs.Empty);
}
private void OnShapePropertiesUpdated()
{
ShapePropertiesUpdated?.Invoke(this, EventArgs.Empty);
}
#endregion
}
}

View File

@ -9,8 +9,6 @@ namespace Artemis.Core.Models.Profile.LayerShapes
protected LayerShape(Layer layer)
{
Layer = layer;
Layer.RenderPropertiesUpdated += LayerOnRenderPropertiesUpdated;
}
protected LayerShape(Layer layer, ShapeEntity shapeEntity)
@ -19,14 +17,8 @@ namespace Artemis.Core.Models.Profile.LayerShapes
Anchor = new SKPoint(shapeEntity.Anchor?.X ?? 0, shapeEntity.Anchor?.Y ?? 0);
Position = new SKPoint(shapeEntity.Position?.X ?? 0, shapeEntity.Position?.Y ?? 0);
Size = new SKSize(shapeEntity.Width, shapeEntity.Height);
Layer.RenderPropertiesUpdated += LayerOnRenderPropertiesUpdated;
}
private void LayerOnRenderPropertiesUpdated(object sender, EventArgs e)
{
CalculateRenderProperties();
}
/// <summary>
/// The layer this shape is attached to

View File

@ -95,9 +95,6 @@ namespace Artemis.Core.Services.Storage
folder.ApplyToEntity();
foreach (var layer in profile.GetAllLayers())
layer.ApplyToEntity();
if (_surfaceService.ActiveSurface != null)
profile.PopulateLeds(_surfaceService.ActiveSurface);
}
_profileRepository.Save(profile.ProfileEntity);

View File

@ -19,10 +19,11 @@ namespace Artemis.Plugins.Devices.Wooting
public override void EnablePlugin()
{
PathHelper.ResolvingAbsolutePath += (sender, args) => ResolveAbsolutePath(typeof(WootingRGBDevice<>), sender, args);
RGB.NET.Devices.Wooting.WootingDeviceProvider.PossibleX64NativePaths.Add(Path.Combine(PluginInfo.Directory.FullName, "x64", "wooting-rgb-sdk64.dll"));
RGB.NET.Devices.Wooting.WootingDeviceProvider.PossibleX86NativePaths.Add(Path.Combine(PluginInfo.Directory.FullName, "x86", "wooting-rgb-sdk.dll"));
_rgbService.AddDeviceProvider(RgbDeviceProvider);
// Disabled for now because the DLLs aren't on the repo
// PathHelper.ResolvingAbsolutePath += (sender, args) => ResolveAbsolutePath(typeof(WootingRGBDevice<>), sender, args);
// RGB.NET.Devices.Wooting.WootingDeviceProvider.PossibleX64NativePaths.Add(Path.Combine(PluginInfo.Directory.FullName, "x64", "wooting-rgb-sdk64.dll"));
// RGB.NET.Devices.Wooting.WootingDeviceProvider.PossibleX86NativePaths.Add(Path.Combine(PluginInfo.Directory.FullName, "x86", "wooting-rgb-sdk.dll"));
// _rgbService.AddDeviceProvider(RgbDeviceProvider);
}
public override void DisablePlugin()

View File

@ -1,6 +1,7 @@
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using Artemis.Core.Ninject;
using Artemis.Core.Services.Interfaces;

View File

@ -2,21 +2,20 @@
using System.Linq;
using System.Windows;
using Artemis.Core.Models.Profile;
using Artemis.UI.Behaviors;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem;
using Artemis.UI.Services.Interfaces;
using GongSolutions.Wpf.DragDrop;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
{
public class ProfileTreeViewModel : ProfileEditorPanelViewModel, IDropTarget
{
private readonly IProfileEditorService _profileEditorService;
private readonly IFolderViewModelFactory _folderViewModelFactory;
private readonly ILayerViewModelFactory _layerViewModelFactory;
private readonly IProfileEditorService _profileEditorService;
private TreeItemViewModel _selectedTreeItem;
private bool _updatingTree;
public ProfileTreeViewModel(IProfileEditorService profileEditorService,
IFolderViewModelFactory folderViewModelFactory,
@ -24,7 +23,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
{
_profileEditorService = profileEditorService;
_folderViewModelFactory = folderViewModelFactory;
_layerViewModelFactory = layerViewModelFactory;
CreateRootFolderViewModel();
_profileEditorService.SelectedProfileChanged += OnSelectedProfileChanged;
@ -38,6 +36,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
get => _selectedTreeItem;
set
{
if (_updatingTree) return;
_selectedTreeItem = value;
_profileEditorService.ChangeSelectedProfileElement(value?.ProfileElement);
}
@ -98,6 +97,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
private void CreateRootFolderViewModel()
{
_updatingTree = true;
var firstChild = _profileEditorService.SelectedProfile?.Children?.FirstOrDefault();
if (!(firstChild is Folder folder))
{
@ -106,6 +106,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
}
RootFolder = _folderViewModelFactory.Create(folder);
_updatingTree = false;
}
private static DragDropType GetDragDropType(IDropInfo dropInfo)
@ -141,32 +142,26 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
private void OnSelectedElementChanged(object sender, EventArgs e)
{
var vms = RootFolder?.GetAllChildren();
if (_profileEditorService.SelectedProfileElement == SelectedTreeItem?.ProfileElement)
return;
// Don't set it using the setter or that will trigger the event again
_selectedTreeItem = vms?.FirstOrDefault(vm => vm.ProfileElement == _profileEditorService.SelectedProfileElement);
if (_selectedTreeItem == null && _profileEditorService.SelectedProfileElement != null)
if (RootFolder == null)
{
var parent = vms?.FirstOrDefault(vm => vm.ProfileElement == _profileEditorService.SelectedProfileElement.Parent);
if (parent == null)
{
// Eh.. we did our best.. start over
CreateRootFolderViewModel();
return;
}
// Create a new TreeItemViewModel for the new ProfileElement
TreeItemViewModel treeItemViewModel;
if (_profileEditorService.SelectedProfileElement is Folder folder)
treeItemViewModel = _folderViewModelFactory.Create(parent, folder);
else
treeItemViewModel = _layerViewModelFactory.Create(parent, (Layer) _profileEditorService.SelectedProfileElement);
parent.AddExistingElement(treeItemViewModel);
_selectedTreeItem = treeItemViewModel;
CreateRootFolderViewModel();
return;
}
NotifyOfPropertyChange(() => SelectedTreeItem);
_updatingTree = true;
RootFolder.UpdateProfileElements();
_updatingTree = false;
if (_profileEditorService.SelectedProfileElement == null)
SelectedTreeItem = null;
else
{
var vms = RootFolder.GetAllChildren();
vms.Add(RootFolder);
SelectedTreeItem = vms.FirstOrDefault(vm => vm.ProfileElement == _profileEditorService.SelectedProfileElement);
}
}
private void OnSelectedProfileChanged(object sender, EventArgs e)

View File

@ -21,7 +21,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
ProfileElement profileElement,
IProfileEditorService profileEditorService,
IDialogService dialogService,
IFolderViewModelFactory folderViewModelFactory,
IFolderViewModelFactory folderViewModelFactory,
ILayerViewModelFactory layerViewModelFactory)
{
_profileEditorService = profileEditorService;
@ -155,7 +155,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
_profileEditorService.UpdateSelectedProfile();
}
private void UpdateProfileElements()
public void UpdateProfileElements()
{
// Order the children
var vmsList = Children.OrderBy(v => v.ProfileElement.Order).ToList();
@ -175,13 +175,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
{
existing = Children.FirstOrDefault(p => p is FolderViewModel vm && vm.ProfileElement == folder);
if (existing == null)
Children.Add(_folderViewModelFactory.Create((FolderViewModel) this, folder));
Children.Add(_folderViewModelFactory.Create((FolderViewModel)this, folder));
}
else if (profileElement is Layer layer)
{
existing = Children.FirstOrDefault(p => p is LayerViewModel vm && vm.ProfileElement == layer);
if (existing == null)
Children.Add(_layerViewModelFactory.Create((FolderViewModel) this, layer));
Children.Add(_layerViewModelFactory.Create((FolderViewModel)this, layer));
}
existing?.UpdateProfileElements();

View File

@ -1,14 +1,43 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.Visualization.ProfileLayerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization"
mc:Ignorable="d"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Path Data="{Binding LayerGeometry, Mode=OneWay}" ClipToBounds="False" StrokeThickness="1">
<Path.Stroke>
<SolidColorBrush Color="{StaticResource Accent400}" />
</Path.Stroke>
</Path>
</UserControl>
<Canvas>
<!-- The part of the layer's shape that falls outside the layer -->
<Path Data="{Binding ShapeGeometry, Mode=OneWay}" >
<Path.Fill>
<SolidColorBrush Color="{StaticResource Accent700}" Opacity="0.25" />
</Path.Fill>
<Path.Stroke>
<SolidColorBrush Color="{StaticResource Accent700}" />
</Path.Stroke>
</Path>
<!-- 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.25" />
</Path.Fill>
<Path.Stroke>
<SolidColorBrush Color="{StaticResource Accent700}" />
</Path.Stroke>
<Path.OpacityMask>
<VisualBrush >
<VisualBrush.Visual>
<Path Data="{Binding LayerGeometry, Mode=OneWay}" ClipToBounds="False" Fill="Black" />
</VisualBrush.Visual>
</VisualBrush>
</Path.OpacityMask>
</Path>
<Path Data="{Binding LayerGeometry, Mode=OneWay}" ClipToBounds="False" StrokeThickness="1.5" StrokeLineJoin="Round" x:Name="LayerPath">
<Path.Stroke>
<SolidColorBrush Color="{StaticResource Accent400}" />
</Path.Stroke>
</Path>
</Canvas>
</UserControl>

View File

@ -3,9 +3,11 @@ using System.Linq;
using System.Windows;
using System.Windows.Media;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.LayerShapes;
using Artemis.Core.Models.Surface;
using Artemis.UI.Extensions;
using RGB.NET.Core;
using Rectangle = Artemis.Core.Models.Profile.LayerShapes.Rectangle;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{
@ -15,18 +17,35 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{
Layer = layer;
CreateLayerGeometry();
Layer.RenderPropertiesUpdated += (sender, args) => CreateLayerGeometry();
Update();
Layer.RenderPropertiesUpdated += LayerOnRenderPropertiesUpdated;
}
public Layer Layer { get; }
public Geometry LayerGeometry { get; set; }
public Geometry OpacityGeometry { get; set; }
public Geometry ShapeGeometry { get; set; }
public Rect ViewportRectangle { get; set; }
private void Update()
{
CreateLayerGeometry();
CreateShapeGeometry();
CreateViewportRectangle();
}
private void CreateLayerGeometry()
{
if (!Layer.Leds.Any())
{
LayerGeometry = Geometry.Empty;
OpacityGeometry = Geometry.Empty;
ViewportRectangle = Rect.Empty;
return;
}
var layerGeometry = Geometry.Empty;
foreach (var led in Layer.Leds)
{
Geometry geometry;
@ -34,15 +53,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{
case Shape.Custom:
if (led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
geometry = CreateCustomGeometry(led, 2.0);
geometry = CreateCustomGeometry(led, 2);
else
geometry = CreateCustomGeometry(led, 1.0);
geometry = CreateCustomGeometry(led, 1);
break;
case Shape.Rectangle:
if (led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
geometry = CreateKeyCapGeometry(led);
else
geometry = CreateRectangleGeometry(led);
geometry = CreateRectangleGeometry(led);
break;
case Shape.Circle:
geometry = CreateCircleGeometry(led);
@ -54,27 +70,88 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
layerGeometry = Geometry.Combine(layerGeometry, geometry, GeometryCombineMode.Union, null, 5, ToleranceType.Absolute);
}
var opacityGeometry = Geometry.Combine(Geometry.Empty, layerGeometry, GeometryCombineMode.Exclude, new TranslateTransform());
layerGeometry.Freeze();
opacityGeometry.Freeze();
LayerGeometry = layerGeometry;
LayerGeometry.Freeze();
OpacityGeometry = opacityGeometry;
}
private void CreateShapeGeometry()
{
if (Layer.LayerShape == null || !Layer.Leds.Any())
{
ShapeGeometry = Geometry.Empty;
return;
}
var x = Layer.Leds.Min(l => l.RgbLed.AbsoluteLedRectangle.Location.X);
var y = Layer.Leds.Min(l => l.RgbLed.AbsoluteLedRectangle.Location.Y);
var width = Layer.Leds.Max(l => l.RgbLed.AbsoluteLedRectangle.Location.X + l.RgbLed.AbsoluteLedRectangle.Size.Width) - x;
var height = Layer.Leds.Max(l => l.RgbLed.AbsoluteLedRectangle.Location.Y + l.RgbLed.AbsoluteLedRectangle.Size.Height) - y;
var rect = new Rect(
x + width * Layer.LayerShape.Position.X,
y + height * Layer.LayerShape.Position.Y,
width * Layer.LayerShape.Size.Width,
height * Layer.LayerShape.Size.Height
);
var shapeGeometry = Geometry.Empty;
switch (Layer.LayerShape)
{
case Ellipse _:
shapeGeometry = new EllipseGeometry(rect);
break;
case Fill _:
shapeGeometry = LayerGeometry;
break;
case Polygon _:
// TODO
shapeGeometry = new RectangleGeometry(rect);
break;
case Rectangle _:
shapeGeometry = new RectangleGeometry(rect);
break;
}
shapeGeometry.Freeze();
ShapeGeometry = shapeGeometry;
}
private void CreateViewportRectangle()
{
if (!Layer.Leds.Any())
{
ViewportRectangle = Rect.Empty;
return;
}
var x = Layer.Leds.Min(l => l.RgbLed.AbsoluteLedRectangle.Location.X);
var y = Layer.Leds.Min(l => l.RgbLed.AbsoluteLedRectangle.Location.Y);
var width = Layer.Leds.Max(l => l.RgbLed.AbsoluteLedRectangle.Location.X + l.RgbLed.AbsoluteLedRectangle.Size.Width) - x;
var height = Layer.Leds.Max(l => l.RgbLed.AbsoluteLedRectangle.Location.Y + l.RgbLed.AbsoluteLedRectangle.Size.Height) - y;
ViewportRectangle = new Rect(x - x * Layer.LayerShape.Position.X, y - y * Layer.LayerShape.Position.Y, width, height);
}
private Geometry CreateRectangleGeometry(ArtemisLed led)
{
return new RectangleGeometry(led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1));
var rect = led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1);
rect.Inflate(1, 1);
return new RectangleGeometry(rect);
}
private Geometry CreateCircleGeometry(ArtemisLed led)
{
return new EllipseGeometry(led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1));
}
private Geometry CreateKeyCapGeometry(ArtemisLed led)
{
return new RectangleGeometry(led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1), 1.6, 1.6);
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(
@ -85,11 +162,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{
Children = new TransformCollection
{
new ScaleTransform(led.RgbLed.ActualSize.Width - deflateAmount, led.RgbLed.ActualSize.Height - deflateAmount),
new TranslateTransform(deflateAmount / 2, deflateAmount / 2)
new ScaleTransform(rect.Width, rect.Height),
new TranslateTransform(rect.X, rect.Y)
}
}
);
return geometry;
}
catch (Exception)
@ -97,5 +175,15 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
return CreateRectangleGeometry(led);
}
}
private void LayerOnRenderPropertiesUpdated(object sender, EventArgs e)
{
Update();
}
public void Dispose()
{
Layer.RenderPropertiesUpdated -= LayerOnRenderPropertiesUpdated;
}
}
}

View File

@ -49,7 +49,7 @@
</Path>
<!-- Selection -->
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" StrokeThickness="1">
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" StrokeThickness="1" StrokeLineJoin="Round">
<Path.Style>
<Style TargetType="{x:Type Path}">
<Style.Triggers>

View File

@ -145,7 +145,7 @@
<materialDesign:Card Padding="8">
<StackPanel Orientation="Horizontal">
<CheckBox Style="{StaticResource MaterialDesignCheckBox}" IsChecked="{Binding HighlightSelectedLayer.Value}">
Highlight selected layer
Dim LEDs outside selected layer
</CheckBox>
<CheckBox Style="{StaticResource MaterialDesignCheckBox}" Margin="10 0 0 0" IsChecked="{Binding PauseRenderingOnFocusLoss.Value}">
Pause visualization on focus loss

View File

@ -139,7 +139,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
// Remove layers that no longer exist
var toRemove = layerViewModels.Where(vm => !layers.Contains(vm.Layer));
foreach (var profileLayerViewModel in toRemove)
{
profileLayerViewModel.Dispose();
CanvasViewModels.Remove(profileLayerViewModel);
}
}
});
}

View File

@ -1,8 +1,12 @@
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.LayerShapes;
using Artemis.UI.Properties;
using Artemis.UI.Services.Interfaces;
using SkiaSharp;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
@ -34,6 +38,18 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
DragRectangle = GetSquareRectBetweenPoints(MouseDownStartPosition, position);
}
public override void MouseUp(object sender, MouseButtonEventArgs e)
{
base.MouseUp(sender, e);
if (ProfileEditorService.SelectedProfileElement is Layer layer)
{
GetShapePosition(out var point, out var size);
layer.LayerShape = new Ellipse(layer) {Size = size, Position = point};
ProfileEditorService.UpdateSelectedProfileElement();
}
}
public override void KeyUp(KeyEventArgs e)
{
base.KeyUp(e);
@ -49,5 +65,25 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
_shiftDown = true;
}
private void GetShapePosition(out SKPoint point, out SKSize size)
{
var layer = (Layer) ProfileEditorService.SelectedProfileElement;
var x = layer.Leds.Min(l => l.RgbLed.AbsoluteLedRectangle.Location.X);
var y = layer.Leds.Min(l => l.RgbLed.AbsoluteLedRectangle.Location.Y);
var width = layer.Leds.Max(l => l.RgbLed.AbsoluteLedRectangle.Location.X + l.RgbLed.AbsoluteLedRectangle.Size.Width) - x;
var height = layer.Leds.Max(l => l.RgbLed.AbsoluteLedRectangle.Location.Y + l.RgbLed.AbsoluteLedRectangle.Size.Height) - y;
var widthScale = width / 100f;
var heightScale = height / 100f;
var rect = new Rect(
x - width / DragRectangle.X,
y - height / DragRectangle.Y,
width / DragRectangle.Width,
height / DragRectangle.Height
);
point = new SKPoint(0.5f,0.5f);
size = new SKSize((float) (DragRectangle.Width * widthScale), (float) (DragRectangle.Height * heightScale));
}
}
}