diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 1c802d465..77d179b2f 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -39,6 +39,8 @@ namespace Artemis.Core.Models.Profile Name = layerEntity.Name; Order = layerEntity.Order; + _leds = new List(); + switch (layerEntity.ShapeEntity?.Type) { case ShapeEntityType.Ellipse: @@ -59,8 +61,6 @@ namespace Artemis.Core.Models.Profile default: throw new ArgumentOutOfRangeException(); } - - _leds = new List(); } internal LayerEntity LayerEntity { get; set; } @@ -243,7 +243,7 @@ namespace Artemis.Core.Models.Profile path.AddRect(artemisLed.AbsoluteRenderRectangle); Path = path; - LayerShape.CalculateRenderProperties(); + LayerShape?.CalculateRenderProperties(); OnRenderPropertiesUpdated(); } diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs b/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs index c65552f68..1a9ec275d 100644 --- a/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs +++ b/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Artemis.Storage.Entities.Profile; using SkiaSharp; @@ -6,6 +7,9 @@ namespace Artemis.Core.Models.Profile.LayerShapes { public abstract class LayerShape { + private SKPoint _position; + private SKSize _size; + protected LayerShape(Layer layer) { Layer = layer; @@ -33,12 +37,28 @@ namespace Artemis.Core.Models.Profile.LayerShapes /// /// The position of the shape /// - public SKPoint Position { get; set; } + public SKPoint Position + { + get => _position; + set + { + _position = value; + Layer.CalculateRenderProperties(); + } + } /// /// The size of the shape /// - public SKSize Size { get; set; } + public SKSize Size + { + get => _size; + set + { + _size = value; + Layer.CalculateRenderProperties(); + } + } /// /// A render rectangle relative to the layer @@ -56,11 +76,48 @@ namespace Artemis.Core.Models.Profile.LayerShapes { Layer.LayerEntity.ShapeEntity = new ShapeEntity { - Anchor = new ShapePointEntity { X = Anchor.X, Y = Anchor.Y }, - Position = new ShapePointEntity { X = Position.X, Y = Position.Y }, + Anchor = new ShapePointEntity {X = Anchor.X, Y = Anchor.Y}, + Position = new ShapePointEntity {X = Position.X, Y = Position.Y}, Width = Size.Width, Height = Size.Height }; } + + /// + /// Updates Position and Size using the provided unscaled rectangle + /// + /// An unscaled rectangle where 1px = 1mm + public void SetFromUnscaledRectangle(SKRect rect) + { + if (!Layer.Leds.Any()) + { + Position = SKPoint.Empty; + Size = SKSize.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; + + Position = new SKPoint((float) (100f / width * (rect.Left - x)) / 100f, (float) (100f / height * (rect.Top - y)) / 100f); + Size = new SKSize((float) (100f / width * rect.Width) / 100f, (float) (100f / height * rect.Height) / 100f); + } + + public SKRect GetUnscaledRectangle() + { + 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; + + return SKRect.Create( + (float) (x + width * Position.X), + (float) (y + height * Position.Y), + (float) (width * Size.Width), + (float) (height * Size.Height) + ); + } } } \ No newline at end of file diff --git a/src/Artemis.Plugins.Devices.Wooting/Artemis.Plugins.Devices.Wooting.csproj b/src/Artemis.Plugins.Devices.Wooting/Artemis.Plugins.Devices.Wooting.csproj index 2189fd57f..b59e9e83d 100644 --- a/src/Artemis.Plugins.Devices.Wooting/Artemis.Plugins.Devices.Wooting.csproj +++ b/src/Artemis.Plugins.Devices.Wooting/Artemis.Plugins.Devices.Wooting.csproj @@ -61,9 +61,14 @@ Artemis.Core + - - + + PreserveNewest + + + PreserveNewest + diff --git a/src/Artemis.Plugins.Devices.Wooting/WootingDeviceProvider.cs b/src/Artemis.Plugins.Devices.Wooting/WootingDeviceProvider.cs index a92dddf86..01ac495f0 100644 --- a/src/Artemis.Plugins.Devices.Wooting/WootingDeviceProvider.cs +++ b/src/Artemis.Plugins.Devices.Wooting/WootingDeviceProvider.cs @@ -19,11 +19,10 @@ namespace Artemis.Plugins.Devices.Wooting public override void EnablePlugin() { - // 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); + 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() diff --git a/src/Artemis.Plugins.Devices.Wooting/x64/wooting-rgb-sdk64.dll b/src/Artemis.Plugins.Devices.Wooting/x64/wooting-rgb-sdk64.dll new file mode 100644 index 000000000..4e2894dc9 Binary files /dev/null and b/src/Artemis.Plugins.Devices.Wooting/x64/wooting-rgb-sdk64.dll differ diff --git a/src/Artemis.Plugins.Devices.Wooting/x86/wooting-rgb-sdk.dll b/src/Artemis.Plugins.Devices.Wooting/x86/wooting-rgb-sdk.dll new file mode 100644 index 000000000..cc3b64898 Binary files /dev/null and b/src/Artemis.Plugins.Devices.Wooting/x86/wooting-rgb-sdk.dll differ diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerView.xaml index ef712b146..5a8665445 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerView.xaml @@ -10,23 +10,23 @@ - + - + - + - + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs index 93d0609fd..a84b45958 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLayerViewModel.cs @@ -7,6 +7,7 @@ using Artemis.Core.Models.Profile.LayerShapes; using Artemis.Core.Models.Surface; using Artemis.UI.Extensions; using RGB.NET.Core; +using SkiaSharp.Views.WPF; using Rectangle = Artemis.Core.Models.Profile.LayerShapes.Rectangle; namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization @@ -85,17 +86,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization 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 skRect = Layer.LayerShape.GetUnscaledRectangle(); + var rect = new Rect(skRect.Left, skRect.Top, skRect.Width, skRect.Height); var shapeGeometry = Geometry.Empty; switch (Layer.LayerShape) { @@ -121,17 +113,20 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization private void CreateViewportRectangle() { - if (!Layer.Leds.Any()) + if (!Layer.Leds.Any() || Layer.LayerShape == null) { 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); + + var rect = new Rect(x, y, width, height); + ViewportRectangle = rect; } private Geometry CreateRectangleGeometry(ArtemisLed led) diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs index 46ba29001..a8d553288 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs @@ -183,7 +183,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization lock (CanvasViewModels) { foreach (var device in Devices.OrderBy(d => d.ZIndex).ToList()) - CanvasViewModels.Move(CanvasViewModels.IndexOf(device), device.ZIndex - 1); + { + var newIndex = Math.Max(device.ZIndex - 1, CanvasViewModels.Count - 1); + CanvasViewModels.Move(CanvasViewModels.IndexOf(device), newIndex); + } } }); } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolViewModel.cs index 1f0972b3d..7c066c34d 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolViewModel.cs @@ -7,6 +7,7 @@ using Artemis.Core.Models.Profile.LayerShapes; using Artemis.UI.Properties; using Artemis.UI.Services.Interfaces; using SkiaSharp; +using SkiaSharp.Views.WPF; namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools { @@ -44,8 +45,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools if (ProfileEditorService.SelectedProfileElement is Layer layer) { - GetShapePosition(out var point, out var size); - layer.LayerShape = new Ellipse(layer) {Size = size, Position = point}; + if (!(layer.LayerShape is Ellipse)) + layer.LayerShape = new Ellipse(layer); + layer.LayerShape.SetFromUnscaledRectangle(DragRectangle.ToSKRect()); ProfileEditorService.UpdateSelectedProfileElement(); } } @@ -65,25 +67,5 @@ 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)); - } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs index 7ccd141e3..c01d09a22 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs @@ -7,6 +7,7 @@ using Artemis.Core.Models.Surface; using Artemis.UI.Extensions; using Artemis.UI.Properties; using Artemis.UI.Services.Interfaces; +using SkiaSharp; namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools { @@ -46,8 +47,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools // Apply the selection to the selected layer layer if (ProfileEditorService.SelectedProfileElement is Layer layer) { + // If the layer has a shape, save it's size + var shapeSize = SKRect.Empty; + if (layer.LayerShape != null) + shapeSize = layer.LayerShape.GetUnscaledRectangle(); layer.ClearLeds(); layer.AddLeds(selectedLeds); + // Restore the saved size + if (layer.LayerShape != null) + layer.LayerShape.SetFromUnscaledRectangle(shapeSize); + ProfileEditorService.UpdateSelectedProfileElement(); } // If no layer selected, apply it to a new layer in the selected folder