diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index ab3b4c4f5..7aafd5db4 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -166,6 +166,11 @@ + + + + + @@ -180,16 +185,16 @@ - - - - - + + + + + - + diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs index c23d6bf1d..561754017 100644 --- a/src/Artemis.Core/Models/Profile/Folder.cs +++ b/src/Artemis.Core/Models/Profile/Folder.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using Artemis.Core.Models.Profile.Abstract; using Artemis.Core.Models.Surface; using Artemis.Storage.Entities.Profile; using SkiaSharp; @@ -92,7 +91,7 @@ namespace Artemis.Core.Models.Profile public override string ToString() { - return $"Folder - {nameof(Name)}: {Name}, {nameof(Order)}: {Order}"; + return $"[Folder] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}"; } } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 7a1ab2b63..c3f93c7df 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using Artemis.Core.Extensions; -using Artemis.Core.Models.Profile.Abstract; +using Artemis.Core.Models.Profile.LayerShapes; using Artemis.Core.Models.Surface; -using Artemis.Core.Plugins.LayerElement; +using Artemis.Core.Plugins.LayerBrush; using Artemis.Storage.Entities.Profile; using Newtonsoft.Json; using SkiaSharp; @@ -14,7 +14,7 @@ namespace Artemis.Core.Models.Profile { public sealed class Layer : ProfileElement { - private readonly List _layerElements; + private LayerShape _layerShape; private List _leds; public Layer(Profile profile, ProfileElement parent, string name) @@ -27,7 +27,6 @@ namespace Artemis.Core.Models.Profile Name = name; _leds = new List(); - _layerElements = new List(); } internal Layer(Profile profile, ProfileElement parent, LayerEntity layerEntity) @@ -40,61 +39,98 @@ namespace Artemis.Core.Models.Profile Name = layerEntity.Name; Order = layerEntity.Order; + switch (layerEntity.ShapeEntity?.Type) + { + case ShapeEntityType.Ellipse: + LayerShape = new Ellipse(this, layerEntity.ShapeEntity); + break; + case ShapeEntityType.Fill: + LayerShape = new Fill(this, layerEntity.ShapeEntity); + break; + case ShapeEntityType.Polygon: + LayerShape = new Polygon(this, layerEntity.ShapeEntity); + break; + case ShapeEntityType.Rectangle: + LayerShape = new Rectangle(this, layerEntity.ShapeEntity); + break; + case null: + LayerShape = null; + break; + default: + throw new ArgumentOutOfRangeException(); + } + _leds = new List(); - _layerElements = new List(); } internal LayerEntity LayerEntity { get; set; } + /// + /// A collection of all the LEDs this layer is assigned to. + /// public ReadOnlyCollection Leds => _leds.AsReadOnly(); - public ReadOnlyCollection LayerElements => _layerElements.AsReadOnly(); - public SKRect RenderRectangle { get; set; } - public SKRect AbsoluteRenderRectangle { get; set; } - public SKPath RenderPath { get; set; } + /// + /// A rectangle relative to the surface that contains all the LEDs in this layer. + /// For rendering, use the RenderRectangle on . + /// + public SKRect Rectangle { get; private set; } + + /// + /// A zero-based absolute rectangle that contains all the LEDs in this layer. + /// For rendering, use the RenderRectangle on . + /// + public SKRect AbsoluteRectangle { get; private set; } + + /// + /// A path containing all the LEDs this layer is applied to. + /// For rendering, use the RenderPath on . + /// + public SKPath Path { get; private set; } + + /// + /// Defines the shape that is rendered by the . + /// + public LayerShape LayerShape + { + get => _layerShape; + set + { + _layerShape = value; + _layerShape.CalculateRenderProperties(); + } + } + + /// + /// The brush that will fill the . + /// + public LayerBrush LayerBrush { get; internal set; } public override void Update(double deltaTime) { - lock (_layerElements) - { - foreach (var layerElement in LayerElements) - layerElement.Update(deltaTime); - } + LayerBrush?.Update(deltaTime); } public override void Render(double deltaTime, SKCanvas canvas) { - if (RenderPath == null) + if (Path == null) return; - lock (_layerElements) - { - canvas.Save(); - using (var framePath = new SKPath(RenderPath)) - { - canvas.ClipPath(framePath); - - foreach (var layerElement in LayerElements) - layerElement.RenderPreProcess(framePath, canvas); - foreach (var layerElement in LayerElements) - layerElement.Render(framePath, canvas); - foreach (var layerElement in LayerElements) - layerElement.RenderPostProcess(framePath, canvas); - } - canvas.Restore(); - } + canvas.Save(); + LayerBrush?.Render(canvas); + canvas.Restore(); } internal override void ApplyToEntity() { + // Properties LayerEntity.Id = EntityId; LayerEntity.ParentId = Parent?.EntityId ?? new Guid(); - LayerEntity.Order = Order; LayerEntity.Name = Name; - LayerEntity.ProfileId = Profile.EntityId; + // LEDs LayerEntity.Leds.Clear(); foreach (var artemisLed in Leds) { @@ -106,62 +142,60 @@ namespace Artemis.Core.Models.Profile LayerEntity.Leds.Add(ledEntity); } + // Conditions TODO LayerEntity.Condition.Clear(); - LayerEntity.Elements.Clear(); - foreach (var layerElement in LayerElements) + // Brush + LayerEntity.BrushEntity = new BrushEntity { - var layerElementEntity = new LayerElementEntity - { - Id = layerElement.Guid, - PluginGuid = layerElement.Descriptor.LayerElementProvider.PluginInfo.Guid, - LayerElementType = layerElement.GetType().Name, - Configuration = JsonConvert.SerializeObject(layerElement.Settings) - }; - LayerEntity.Elements.Add(layerElementEntity); - } + BrushPluginGuid = LayerBrush.Descriptor.LayerBrushProvider.PluginInfo.Guid, + BrushType = LayerBrush.GetType().Name, + Configuration = JsonConvert.SerializeObject(LayerBrush.Settings) + }; + + // Shape + LayerShape.ApplyToEntity(); } + /// + /// Adds a new to the layer and updates the render properties. + /// + /// The LED to add public void AddLed(ArtemisLed led) { _leds.Add(led); CalculateRenderProperties(); } + /// + /// Adds a collection of new s to the layer and updates the render properties. + /// + /// The LEDs to add public void AddLeds(IEnumerable leds) { _leds.AddRange(leds); CalculateRenderProperties(); } + /// + /// Removes a from the layer and updates the render properties. + /// + /// The LED to remove public void RemoveLed(ArtemisLed led) { _leds.Remove(led); CalculateRenderProperties(); } + /// + /// Removes all s from the layer and updates the render properties. + /// public void ClearLeds() { _leds.Clear(); CalculateRenderProperties(); } - internal void AddLayerElement(LayerElement layerElement) - { - lock (_layerElements) - { - _layerElements.Add(layerElement); - } - } - - internal void RemoveLayerElement(LayerElement layerElement) - { - lock (_layerElements) - { - _layerElements.Remove(layerElement); - } - } - internal void PopulateLeds(ArtemisSurface surface) { var leds = new List(); @@ -191,20 +225,20 @@ namespace Artemis.Core.Models.Profile var maxX = Leds.Max(l => l.AbsoluteRenderRectangle.Right); var maxY = Leds.Max(l => l.AbsoluteRenderRectangle.Bottom); - RenderRectangle = SKRect.Create(minX, minY, maxX - minX, maxY - minY); - AbsoluteRenderRectangle = SKRect.Create(0, 0, maxX - minX, maxY - minY); + Rectangle = SKRect.Create(minX, minY, maxX - minX, maxY - minY); + AbsoluteRectangle = SKRect.Create(0, 0, maxX - minX, maxY - minY); var path = new SKPath {FillType = SKPathFillType.Winding}; foreach (var artemisLed in Leds) path.AddRect(artemisLed.AbsoluteRenderRectangle); - RenderPath = path; + Path = path; OnRenderPropertiesUpdated(); } public override string ToString() { - return $"Layer - {nameof(Name)}: {Name}, {nameof(Order)}: {Order}"; + return $"[Layer] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}"; } #region Events diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs b/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs new file mode 100644 index 000000000..9cb1095e9 --- /dev/null +++ b/src/Artemis.Core/Models/Profile/LayerShapes/Ellipse.cs @@ -0,0 +1,35 @@ +using Artemis.Storage.Entities.Profile; +using SkiaSharp; + +namespace Artemis.Core.Models.Profile.LayerShapes +{ + public class Ellipse : LayerShape + { + public Ellipse(Layer layer) : base(layer) + { + } + + internal Ellipse(Layer layer, ShapeEntity shapeEntity) : base(layer, shapeEntity) + { + } + + public override void CalculateRenderProperties() + { + var width = Layer.AbsoluteRectangle.Width; + var height = Layer.AbsoluteRectangle.Height; + var rect = SKRect.Create(Position.X * width, Position.Y * height, Size.Width * width, Size.Height * height); + + var path = new SKPath(); + path.AddOval(rect); + + RenderPath = path; + RenderRectangle = path.GetRect(); + } + + public override void ApplyToEntity() + { + base.ApplyToEntity(); + Layer.LayerEntity.ShapeEntity.Type = ShapeEntityType.Ellipse; + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/Fill.cs b/src/Artemis.Core/Models/Profile/LayerShapes/Fill.cs new file mode 100644 index 000000000..d1b05f776 --- /dev/null +++ b/src/Artemis.Core/Models/Profile/LayerShapes/Fill.cs @@ -0,0 +1,26 @@ +using Artemis.Storage.Entities.Profile; + +namespace Artemis.Core.Models.Profile.LayerShapes +{ + public class Fill : LayerShape + { + public Fill(Layer layer) : base(layer) + { + } + internal Fill(Layer layer, ShapeEntity shapeEntity) : base(layer, shapeEntity) + { + } + + public override void CalculateRenderProperties() + { + RenderPath = Layer.Path; + RenderRectangle = Layer.Path.GetRect(); + } + + public override void ApplyToEntity() + { + base.ApplyToEntity(); + Layer.LayerEntity.ShapeEntity.Type = ShapeEntityType.Fill; + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs b/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs new file mode 100644 index 000000000..32ccdd6e0 --- /dev/null +++ b/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs @@ -0,0 +1,74 @@ +using System; +using Artemis.Storage.Entities.Profile; +using SkiaSharp; + +namespace Artemis.Core.Models.Profile.LayerShapes +{ + public abstract class LayerShape + { + protected LayerShape(Layer layer) + { + Layer = layer; + + Layer.RenderPropertiesUpdated += LayerOnRenderPropertiesUpdated; + } + + protected LayerShape(Layer layer, ShapeEntity shapeEntity) + { + Layer = layer; + 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(); + } + + /// + /// The layer this shape is attached to + /// + public Layer Layer { get; set; } + + /// + /// At which position the shape is attached to the layer + /// + public SKPoint Anchor { get; set; } + + /// + /// The position of the shape + /// + public SKPoint Position { get; set; } + + /// + /// The size of the shape + /// + public SKSize Size { get; set; } + + /// + /// A render rectangle relative to the layer + /// + public SKRect RenderRectangle { get; protected set; } + + /// + /// A path relative to the layer + /// + public SKPath RenderPath { get; protected set; } + + public abstract void CalculateRenderProperties(); + + public virtual void ApplyToEntity() + { + Layer.LayerEntity.ShapeEntity = new ShapeEntity + { + Anchor = new ShapePointEntity { X = Anchor.X, Y = Anchor.Y }, + Position = new ShapePointEntity { X = Position.X, Y = Position.Y }, + Width = Size.Width, + Height = Size.Height + }; + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/Polygon.cs b/src/Artemis.Core/Models/Profile/LayerShapes/Polygon.cs new file mode 100644 index 000000000..a3444285f --- /dev/null +++ b/src/Artemis.Core/Models/Profile/LayerShapes/Polygon.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.Linq; +using Artemis.Storage.Entities.Profile; +using SkiaSharp; + +namespace Artemis.Core.Models.Profile.LayerShapes +{ + public class Polygon : LayerShape + { + + public Polygon(Layer layer) : base(layer) + { + } + + internal Polygon(Layer layer, ShapeEntity shapeEntity) : base(layer, shapeEntity) + { + } + + /// + /// The points of this polygon + /// + public List Points { get; set; } + + /// + /// The points of this polygon where they need to be rendered inside the layer + /// + public List RenderPoints => Points.Select(p => new SKPoint(p.X * Layer.AbsoluteRectangle.Width, p.Y * Layer.AbsoluteRectangle.Height)).ToList(); + + public override void CalculateRenderProperties() + { + var path = new SKPath(); + path.AddPoly(RenderPoints.ToArray()); + + RenderPath = path; + RenderRectangle = path.GetRect(); + } + + public override void ApplyToEntity() + { + base.ApplyToEntity(); + Layer.LayerEntity.ShapeEntity.Type = ShapeEntityType.Polygon; + Layer.LayerEntity.ShapeEntity.Points = Points.Select(p => new ShapePointEntity { X = p.X, Y = p.Y }).ToList(); + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs b/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs new file mode 100644 index 000000000..1e911dc0f --- /dev/null +++ b/src/Artemis.Core/Models/Profile/LayerShapes/Rectangle.cs @@ -0,0 +1,34 @@ +using Artemis.Storage.Entities.Profile; +using SkiaSharp; + +namespace Artemis.Core.Models.Profile.LayerShapes +{ + public class Rectangle : LayerShape + { + public Rectangle(Layer layer) : base(layer) + { + } + + internal Rectangle(Layer layer, ShapeEntity shapeEntity) : base(layer, shapeEntity) + { + } + + public override void CalculateRenderProperties() + { + var width = Layer.AbsoluteRectangle.Width; + var height = Layer.AbsoluteRectangle.Height; + var rect = SKRect.Create(Position.X * width, Position.Y * height, Size.Width * width, Size.Height * height); + var path = new SKPath(); + path.AddRect(rect); + + RenderPath = path; + RenderRectangle = path.GetRect(); + } + + public override void ApplyToEntity() + { + base.ApplyToEntity(); + Layer.LayerEntity.ShapeEntity.Type = ShapeEntityType.Rectangle; + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs index bd0c57909..be8df1869 100644 --- a/src/Artemis.Core/Models/Profile/Profile.cs +++ b/src/Artemis.Core/Models/Profile/Profile.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using Artemis.Core.Exceptions; -using Artemis.Core.Models.Profile.Abstract; using Artemis.Core.Models.Surface; using Artemis.Core.Plugins.Models; using Artemis.Storage.Entities.Profile; @@ -109,17 +108,17 @@ namespace Artemis.Core.Models.Profile } } - public override string ToString() - { - return $"{nameof(Order)}: {Order}, {nameof(Name)}: {Name}, {nameof(PluginInfo)}: {PluginInfo}"; - } - internal void PopulateLeds(ArtemisSurface surface) { foreach (var layer in GetAllLayers()) layer.PopulateLeds(surface); } + public override string ToString() + { + return $"[Profile] {nameof(Name)}: {Name}, {nameof(IsActivated)}: {IsActivated}, {nameof(PluginInfo)}: {PluginInfo}"; + } + #region Events /// diff --git a/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs b/src/Artemis.Core/Models/Profile/ProfileElement.cs similarity index 98% rename from src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs rename to src/Artemis.Core/Models/Profile/ProfileElement.cs index d007b077b..a927a9fd6 100644 --- a/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs +++ b/src/Artemis.Core/Models/Profile/ProfileElement.cs @@ -2,11 +2,10 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using Artemis.Core.Models.Surface; using SkiaSharp; using Stylet; -namespace Artemis.Core.Models.Profile.Abstract +namespace Artemis.Core.Models.Profile { public abstract class ProfileElement : PropertyChangedBase { @@ -132,5 +131,7 @@ namespace Artemis.Core.Models.Profile.Abstract child.Parent = null; } } + + } } \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs new file mode 100644 index 000000000..95adbc215 --- /dev/null +++ b/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs @@ -0,0 +1,48 @@ +using System; +using Artemis.Core.Models.Profile; +using SkiaSharp; + +namespace Artemis.Core.Plugins.LayerBrush +{ + public abstract class LayerBrush : IDisposable + { + protected LayerBrush(Layer layer, LayerBrushSettings settings, LayerBrushDescriptor descriptor) + { + Layer = layer; + Settings = settings; + Descriptor = descriptor; + } + + public Layer Layer { get; } + public LayerBrushSettings Settings { get; } + public LayerBrushDescriptor Descriptor { get; } + + public virtual void Dispose() + { + } + + /// + /// Called by the profile editor to populate the brush properties panel + /// + /// + public abstract LayerBrushViewModel GetViewModel(); + + /// + /// Called before rendering every frame, write your update logic here + /// + /// + public virtual void Update(double deltaTime) + { + } + + /// + /// The main method of rendering anything to the layer. The provided is specific to the layer + /// and matches it's width and height. + /// Called during rendering, in the order configured on the layer + /// + /// The layer canvas + public virtual void Render(SKCanvas canvas) + { + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/LayerBrush/LayerBrushDescriptor.cs b/src/Artemis.Core/Plugins/LayerBrush/LayerBrushDescriptor.cs new file mode 100644 index 000000000..057ea173e --- /dev/null +++ b/src/Artemis.Core/Plugins/LayerBrush/LayerBrushDescriptor.cs @@ -0,0 +1,22 @@ +using System; + +namespace Artemis.Core.Plugins.LayerBrush +{ + public class LayerBrushDescriptor + { + internal LayerBrushDescriptor(string displayName, string description, string icon, Type layerBrushType, LayerBrushProvider layerBrushProvider) + { + DisplayName = displayName; + Description = description; + Icon = icon; + LayerBrushType = layerBrushType; + LayerBrushProvider = layerBrushProvider; + } + + public string DisplayName { get; } + public string Description { get; } + public string Icon { get; } + public Type LayerBrushType { get; } + public LayerBrushProvider LayerBrushProvider { get; } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/LayerBrush/LayerBrushProvider.cs b/src/Artemis.Core/Plugins/LayerBrush/LayerBrushProvider.cs new file mode 100644 index 000000000..65d73d17d --- /dev/null +++ b/src/Artemis.Core/Plugins/LayerBrush/LayerBrushProvider.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Artemis.Core.Plugins.Abstract; +using Artemis.Core.Plugins.Models; + +namespace Artemis.Core.Plugins.LayerBrush +{ + /// + /// + /// Allows you to create one or more s usable by profile layers. + /// + public abstract class LayerBrushProvider : Plugin + { + private readonly List _layerBrushDescriptors; + + protected LayerBrushProvider(PluginInfo pluginInfo) : base(pluginInfo) + { + _layerBrushDescriptors = new List(); + } + + public ReadOnlyCollection LayerBrushDescriptors => _layerBrushDescriptors.AsReadOnly(); + + protected void AddLayerBrushDescriptor(string displayName, string description, string icon) where T : LayerBrush + { + _layerBrushDescriptors.Add(new LayerBrushDescriptor(displayName, description, icon, typeof(T), this)); + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/LayerElement/LayerElementSettings.cs b/src/Artemis.Core/Plugins/LayerBrush/LayerBrushSettings.cs similarity index 84% rename from src/Artemis.Core/Plugins/LayerElement/LayerElementSettings.cs rename to src/Artemis.Core/Plugins/LayerBrush/LayerBrushSettings.cs index 2d19bc172..000944f99 100644 --- a/src/Artemis.Core/Plugins/LayerElement/LayerElementSettings.cs +++ b/src/Artemis.Core/Plugins/LayerBrush/LayerBrushSettings.cs @@ -1,9 +1,9 @@ using System; using Stylet; -namespace Artemis.Core.Plugins.LayerElement +namespace Artemis.Core.Plugins.LayerBrush { - public abstract class LayerElementSettings : PropertyChangedBase + public abstract class LayerBrushSettings : PropertyChangedBase { private Action _propertyChangedDispatcher = Execute.DefaultPropertyChangedDispatcher; diff --git a/src/Artemis.Core/Plugins/LayerBrush/LayerBrushViewModel.cs b/src/Artemis.Core/Plugins/LayerBrush/LayerBrushViewModel.cs new file mode 100644 index 000000000..21eee433c --- /dev/null +++ b/src/Artemis.Core/Plugins/LayerBrush/LayerBrushViewModel.cs @@ -0,0 +1,14 @@ +using Stylet; + +namespace Artemis.Core.Plugins.LayerBrush +{ + public abstract class LayerBrushViewModel : PropertyChangedBase + { + protected LayerBrushViewModel(LayerBrush brush) + { + Brush = brush; + } + + public LayerBrush Brush { get; } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/LayerElement/LayerElement.cs b/src/Artemis.Core/Plugins/LayerElement/LayerElement.cs deleted file mode 100644 index bb5701182..000000000 --- a/src/Artemis.Core/Plugins/LayerElement/LayerElement.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using Artemis.Core.Models.Profile; -using SkiaSharp; - -namespace Artemis.Core.Plugins.LayerElement -{ - public abstract class LayerElement : IDisposable - { - protected LayerElement(Layer layer, Guid guid, LayerElementSettings settings, LayerElementDescriptor descriptor) - { - Layer = layer; - Guid = guid; - Settings = settings; - Descriptor = descriptor; - } - - public Layer Layer { get; } - public Guid Guid { get; } - public LayerElementSettings Settings { get; } - public LayerElementDescriptor Descriptor { get; } - - public virtual void Dispose() - { - } - - /// - /// Called by the profile editor to populate the layer element properties panel - /// - /// - public abstract LayerElementViewModel GetViewModel(); - - /// - /// Called before rendering every frame, write your update logic here - /// - /// - public virtual void Update(double deltaTime) - { - } - - /// - /// Allows you to perform rendering on the surface before any layer-clipping is applied - /// Called before rendering, in the order configured on the layer - /// - /// - /// The entire surface canvas - public virtual void RenderPreProcess(SKPath framePath, SKCanvas canvas) - { - } - - /// - /// The main method of rendering anything to the layer. The provided is specific to the layer - /// and matches it's width and height. - /// Called during rendering, in the order configured on the layer - /// - /// - /// The layer canvas - public virtual void Render(SKPath framePath, SKCanvas canvas) - { - } - - /// - /// Allows you to modify the used to draw the layer's on the - /// . - /// Called after rendering, in the order configured on the layer. - /// - /// - /// - /// The bitmap created from the layer canvas - /// The current shader used to draw the bitmap on the surface canvas - /// The resulting shader used to draw the bitmap on the surface canvas - public virtual void RenderPostProcess(SKPath framePath, SKCanvas canvas) - { - } - } -} \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/LayerElement/LayerElementDescriptor.cs b/src/Artemis.Core/Plugins/LayerElement/LayerElementDescriptor.cs deleted file mode 100644 index ee94d20b4..000000000 --- a/src/Artemis.Core/Plugins/LayerElement/LayerElementDescriptor.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Artemis.Core.Plugins.LayerElement -{ - public class LayerElementDescriptor - { - internal LayerElementDescriptor(string displayName, string description, string icon, Type layerElementType, LayerElementProvider layerElementProvider) - { - DisplayName = displayName; - Description = description; - Icon = icon; - LayerElementType = layerElementType; - LayerElementProvider = layerElementProvider; - } - - public string DisplayName { get; } - public string Description { get; } - public string Icon { get; } - public Type LayerElementType { get; } - public LayerElementProvider LayerElementProvider { get; } - } -} \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/LayerElement/LayerElementProvider.cs b/src/Artemis.Core/Plugins/LayerElement/LayerElementProvider.cs deleted file mode 100644 index 699e2a86b..000000000 --- a/src/Artemis.Core/Plugins/LayerElement/LayerElementProvider.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using Artemis.Core.Plugins.Abstract; -using Artemis.Core.Plugins.Models; - -namespace Artemis.Core.Plugins.LayerElement -{ - /// - /// - /// Allows you to create one or more s usable by profile layers. - /// - public abstract class LayerElementProvider : Plugin - { - private readonly List _layerElementDescriptors; - - protected LayerElementProvider(PluginInfo pluginInfo) : base(pluginInfo) - { - _layerElementDescriptors = new List(); - } - - public ReadOnlyCollection LayerElementDescriptors => _layerElementDescriptors.AsReadOnly(); - - protected void AddLayerElementDescriptor(string displayName, string description, string icon) where T : LayerElement - { - _layerElementDescriptors.Add(new LayerElementDescriptor(displayName, description, icon, typeof(T), this)); - } - } -} \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/LayerElement/LayerElementViewModel.cs b/src/Artemis.Core/Plugins/LayerElement/LayerElementViewModel.cs deleted file mode 100644 index 125d0c37f..000000000 --- a/src/Artemis.Core/Plugins/LayerElement/LayerElementViewModel.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Stylet; - -namespace Artemis.Core.Plugins.LayerElement -{ - public abstract class LayerElementViewModel : PropertyChangedBase - { - protected LayerElementViewModel(LayerElement layerElement) - { - LayerElement = layerElement; - } - - public LayerElement LayerElement { get; } - } -} \ No newline at end of file diff --git a/src/Artemis.Core/Services/Interfaces/ILayerService.cs b/src/Artemis.Core/Services/Interfaces/ILayerService.cs index ff0bcd19c..73c4a6ef4 100644 --- a/src/Artemis.Core/Services/Interfaces/ILayerService.cs +++ b/src/Artemis.Core/Services/Interfaces/ILayerService.cs @@ -1,21 +1,18 @@ -using System; -using Artemis.Core.Models.Profile; -using Artemis.Core.Plugins.LayerElement; +using Artemis.Core.Models.Profile; +using Artemis.Core.Plugins.LayerBrush; namespace Artemis.Core.Services.Interfaces { public interface ILayerService : IArtemisService { /// - /// Instantiates and adds the described by the provided - /// to the provided . + /// Instantiates and adds the described by the provided + /// to the provided . /// /// The layer to add the new layer element to - /// The descriptor of the new layer element - /// JSON settings to be deserialized and injected into the layer element + /// The descriptor of the new layer brush + /// JSON settings to be deserialized and injected into the layer brush /// - LayerElement InstantiateLayerElement(Layer layer, LayerElementDescriptor layerElementDescriptor, string settings = null, Guid? guid = null); - - void RemoveLayerElement(Layer layer, LayerElement layerElement); + LayerBrush InstantiateLayerBrush(Layer layer, LayerBrushDescriptor brushDescriptor, string settings = null); } } \ No newline at end of file diff --git a/src/Artemis.Core/Services/LayerService.cs b/src/Artemis.Core/Services/LayerService.cs index cc8211dc3..17f52dc5a 100644 --- a/src/Artemis.Core/Services/LayerService.cs +++ b/src/Artemis.Core/Services/LayerService.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Reflection; using Artemis.Core.Models.Profile; using Artemis.Core.Plugins.Exceptions; -using Artemis.Core.Plugins.LayerElement; +using Artemis.Core.Plugins.LayerBrush; using Artemis.Core.Services.Interfaces; using Newtonsoft.Json; using Ninject; @@ -23,16 +23,13 @@ namespace Artemis.Core.Services _logger = logger; } - public LayerElement InstantiateLayerElement(Layer layer, LayerElementDescriptor layerElementDescriptor, string settings, Guid? guid) + public LayerBrush InstantiateLayerBrush(Layer layer, LayerBrushDescriptor brushDescriptor, string settings) { - if (guid == null) - guid = Guid.NewGuid(); - // Determine the settings type declared by the layer element object settingsInstance = null; - var properties = layerElementDescriptor.LayerElementType.GetProperties(); + var properties = brushDescriptor.LayerBrushType.GetProperties(); var settingsType = properties.FirstOrDefault(p => p.Name == "Settings" && - p.DeclaringType == layerElementDescriptor.LayerElementType)?.PropertyType; + p.DeclaringType == brushDescriptor.LayerBrushType)?.PropertyType; // Deserialize the settings if provided, check for null in JSON as well if (settings != null && settings != "null") @@ -41,8 +38,8 @@ namespace Artemis.Core.Services if (settingsType == null) { throw new ArtemisPluginException( - layerElementDescriptor.LayerElementProvider.PluginInfo, - $"Settings where provided but layer element of type {layerElementDescriptor.LayerElementType.Name} has no Settings property." + brushDescriptor.LayerBrushProvider.PluginInfo, + $"Settings where provided but layer element of type {brushDescriptor.LayerBrushType.Name} has no Settings property." ); } @@ -53,8 +50,8 @@ namespace Artemis.Core.Services catch (JsonSerializationException e) { _logger.Warning(e, "Failed to deserialize settings for layer type {type}, resetting element settings - Plugin info: {pluginInfo}", - layerElementDescriptor.LayerElementType.Name, - layerElementDescriptor.LayerElementProvider.PluginInfo); + brushDescriptor.LayerBrushType.Name, + brushDescriptor.LayerBrushProvider.PluginInfo); settingsInstance = Activator.CreateInstance(settingsType); } @@ -68,20 +65,20 @@ namespace Artemis.Core.Services var arguments = new IParameter[] { new ConstructorArgument("layer", layer), - new ConstructorArgument("guid", guid.Value), new ConstructorArgument("settings", settingsInstance), - new ConstructorArgument("descriptor", layerElementDescriptor) + new ConstructorArgument("descriptor", brushDescriptor) }; - var layerElement = (LayerElement) _kernel.Get(layerElementDescriptor.LayerElementType, arguments); - layer.AddLayerElement(layerElement); + var layerElement = (LayerBrush) _kernel.Get(brushDescriptor.LayerBrushType, arguments); + layer.LayerBrush = (layerElement); return layerElement; } - public void RemoveLayerElement(Layer layer, LayerElement layerElement) + public void RemoveLayerBrush(Layer layer, LayerBrush layerElement) { - layer.RemoveLayerElement(layerElement); - layerElement.Dispose(); + var brush = layer.LayerBrush; + layer.LayerBrush = null; + brush.Dispose(); } } } \ No newline at end of file diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs index e59d187ea..c396206d2 100644 --- a/src/Artemis.Core/Services/Storage/ProfileService.cs +++ b/src/Artemis.Core/Services/Storage/ProfileService.cs @@ -4,7 +4,7 @@ using Artemis.Core.Events; using Artemis.Core.Models.Profile; using Artemis.Core.Models.Surface; using Artemis.Core.Plugins.Abstract; -using Artemis.Core.Plugins.LayerElement; +using Artemis.Core.Plugins.LayerBrush; using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Storage.Interfaces; using Artemis.Storage.Repositories.Interfaces; @@ -16,10 +16,10 @@ namespace Artemis.Core.Services.Storage /// public class ProfileService : IProfileService { + private readonly ILayerService _layerService; private readonly IPluginService _pluginService; private readonly IProfileRepository _profileRepository; private readonly ISurfaceService _surfaceService; - private readonly ILayerService _layerService; internal ProfileService(IPluginService pluginService, ISurfaceService surfaceService, ILayerService layerService, IProfileRepository profileRepository) { @@ -78,7 +78,7 @@ namespace Artemis.Core.Services.Storage { module.ChangeActiveProfile(profile, _surfaceService.ActiveSurface); if (profile != null) - InstantiateProfileLayerElements(profile); + InstantiateProfileLayerBrushes(profile); } public void DeleteProfile(Profile profile) @@ -102,27 +102,22 @@ namespace Artemis.Core.Services.Storage _profileRepository.Save(profile.ProfileEntity); } - private void InstantiateProfileLayerElements(Profile profile) + + private void InstantiateProfileLayerBrushes(Profile profile) { - var layerElementProviders = _pluginService.GetPluginsOfType(); - var descriptors = layerElementProviders.SelectMany(l => l.LayerElementDescriptors).ToList(); + var layerBrushProviders = _pluginService.GetPluginsOfType(); + var descriptors = layerBrushProviders.SelectMany(l => l.LayerBrushDescriptors).ToList(); - foreach (var layer in profile.GetAllLayers()) + // Only instantiate brushes for layers without an existing brush instance + foreach (var layer in profile.GetAllLayers().Where(l => l.LayerBrush == null && l.LayerEntity.BrushEntity != null)) { - foreach (var elementEntity in layer.LayerEntity.Elements) - { - // Skip already instantiated layer elements - if (layer.LayerElements.Any(e => e.Guid == elementEntity.Id)) - continue; + // Get a matching descriptor + var descriptor = descriptors.FirstOrDefault(d => d.LayerBrushProvider.PluginInfo.Guid == layer.LayerEntity.BrushEntity.BrushPluginGuid && + d.LayerBrushType.Name == layer.LayerEntity.BrushEntity.BrushType); - // Get a matching descriptor - var descriptor = descriptors.FirstOrDefault(d => d.LayerElementProvider.PluginInfo.Guid == elementEntity.PluginGuid && - d.LayerElementType.Name == elementEntity.LayerElementType); - - // If a descriptor that matches if found, instantiate it with the GUID of the element entity - if (descriptor != null) - _layerService.InstantiateLayerElement(layer, descriptor, elementEntity.Configuration, elementEntity.Id); - } + // If a descriptor that matches if found, instantiate it with the GUID of the element entity + if (descriptor != null) + _layerService.InstantiateLayerBrush(layer, descriptor, layer.LayerEntity.BrushEntity.Configuration); } } @@ -133,11 +128,11 @@ namespace Artemis.Core.Services.Storage profileModule.ActiveProfile.PopulateLeds(surface); } - private void ActiveProfilesInstantiateProfileLayerElements() + private void ActiveProfilesInstantiateProfileLayerBrushes() { var profileModules = _pluginService.GetPluginsOfType(); foreach (var profileModule in profileModules.Where(p => p.ActiveProfile != null).ToList()) - InstantiateProfileLayerElements(profileModule.ActiveProfile); + InstantiateProfileLayerBrushes(profileModule.ActiveProfile); } #region Event handlers @@ -155,8 +150,8 @@ namespace Artemis.Core.Services.Storage private void OnPluginLoaded(object sender, PluginEventArgs e) { - if (e.PluginInfo.Instance is LayerElementProvider) - ActiveProfilesInstantiateProfileLayerElements(); + if (e.PluginInfo.Instance is LayerBrushProvider) + ActiveProfilesInstantiateProfileLayerBrushes(); } #endregion diff --git a/src/Artemis.Plugins.LayerElements.Animations/AnimationLayerElementProvider.cs b/src/Artemis.Plugins.LayerElements.Animations/AnimationBrushProvider.cs similarity index 78% rename from src/Artemis.Plugins.LayerElements.Animations/AnimationLayerElementProvider.cs rename to src/Artemis.Plugins.LayerElements.Animations/AnimationBrushProvider.cs index 11ed3bf09..ba10bedfa 100644 --- a/src/Artemis.Plugins.LayerElements.Animations/AnimationLayerElementProvider.cs +++ b/src/Artemis.Plugins.LayerElements.Animations/AnimationBrushProvider.cs @@ -3,9 +3,9 @@ using Artemis.Core.Plugins.Models; namespace Artemis.Plugins.LayerElements.Animations { - public class AnimationLayerElementProvider : LayerElementProvider + public class AnimationBrushProvider : BrushProvider { - public AnimationLayerElementProvider(PluginInfo pluginInfo) : base(pluginInfo) + public AnimationBrushProvider(PluginInfo pluginInfo) : base(pluginInfo) { AddLayerElementDescriptor("Slide animation", "A sliding animation", "ArrowAll"); AddLayerElementDescriptor("Rotation animation", "A rotation animation", "CropRotate"); diff --git a/src/Artemis.Plugins.LayerElements.Animations/Artemis.Plugins.LayerElements.Animations.csproj b/src/Artemis.Plugins.LayerElements.Animations/Artemis.Plugins.LayerElements.Animations.csproj index d8e14bc49..ac15258da 100644 --- a/src/Artemis.Plugins.LayerElements.Animations/Artemis.Plugins.LayerElements.Animations.csproj +++ b/src/Artemis.Plugins.LayerElements.Animations/Artemis.Plugins.LayerElements.Animations.csproj @@ -59,7 +59,7 @@ - + diff --git a/src/Artemis.Plugins.LayerElements.Animations/RotationLayerElement.cs b/src/Artemis.Plugins.LayerElements.Animations/RotationLayerElement.cs index 08f4f9953..6a96b8d0b 100644 --- a/src/Artemis.Plugins.LayerElements.Animations/RotationLayerElement.cs +++ b/src/Artemis.Plugins.LayerElements.Animations/RotationLayerElement.cs @@ -7,13 +7,13 @@ namespace Artemis.Plugins.LayerElements.Animations { public class RotationLayerElement : LayerElement { - public RotationLayerElement(Layer layer, Guid guid, LayerElementSettings settings, LayerElementDescriptor descriptor) : base(layer, guid, settings, descriptor) + public RotationLayerElement(Layer layer, Guid guid, BrushSettings settings, BrushDescriptor descriptor) : base(layer, guid, settings, descriptor) { } public float Rotation { get; set; } - public override LayerElementViewModel GetViewModel() + public override BrushViewModel GetViewModel() { return null; } diff --git a/src/Artemis.Plugins.LayerElements.Animations/SlideLayerElement.cs b/src/Artemis.Plugins.LayerElements.Animations/SlideLayerElement.cs index 9eb9bd5dd..c86b91aa8 100644 --- a/src/Artemis.Plugins.LayerElements.Animations/SlideLayerElement.cs +++ b/src/Artemis.Plugins.LayerElements.Animations/SlideLayerElement.cs @@ -7,13 +7,13 @@ namespace Artemis.Plugins.LayerElements.Animations { public class SlideLayerElement : LayerElement { - public SlideLayerElement(Layer layer, Guid guid, LayerElementSettings settings, LayerElementDescriptor descriptor) : base(layer, guid, settings, descriptor) + public SlideLayerElement(Layer layer, Guid guid, BrushSettings settings, BrushDescriptor descriptor) : base(layer, guid, settings, descriptor) { } public int MovePercentage { get; set; } - public override LayerElementViewModel GetViewModel() + public override BrushViewModel GetViewModel() { return null; } diff --git a/src/Artemis.Plugins.LayerElements.Noise/Artemis.Plugins.LayerElements.Noise.csproj b/src/Artemis.Plugins.LayerElements.Noise/Artemis.Plugins.LayerBrushes.Noise.csproj similarity index 93% rename from src/Artemis.Plugins.LayerElements.Noise/Artemis.Plugins.LayerElements.Noise.csproj rename to src/Artemis.Plugins.LayerElements.Noise/Artemis.Plugins.LayerBrushes.Noise.csproj index 8b2af9e34..2fbe7e331 100644 --- a/src/Artemis.Plugins.LayerElements.Noise/Artemis.Plugins.LayerElements.Noise.csproj +++ b/src/Artemis.Plugins.LayerElements.Noise/Artemis.Plugins.LayerBrushes.Noise.csproj @@ -7,8 +7,8 @@ {7F4C7AB0-4C9B-452D-AFED-34544C903DEF} Library Properties - Artemis.Plugins.LayerElements.Noise - Artemis.Plugins.LayerElements.Noise + Artemis.Plugins.LayerBrushes.Noise + Artemis.Plugins.LayerBrushes.Noise v4.7.2 512 true @@ -87,11 +87,11 @@ - - - - - + + + + + @@ -113,7 +113,7 @@ - + Designer MSBuild:Compile diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElement.cs b/src/Artemis.Plugins.LayerElements.Noise/NoiseBrush.cs similarity index 75% rename from src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElement.cs rename to src/Artemis.Plugins.LayerElements.Noise/NoiseBrush.cs index 3160b907b..094b9d2a4 100644 --- a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElement.cs +++ b/src/Artemis.Plugins.LayerElements.Noise/NoiseBrush.cs @@ -1,26 +1,27 @@ using System; using Artemis.Core.Models.Profile; -using Artemis.Core.Plugins.LayerElement; +using Artemis.Core.Plugins.LayerBrush; +using Artemis.Plugins.LayerBrushes.Noise.Utilities; using SkiaSharp; -namespace Artemis.Plugins.LayerElements.Noise +namespace Artemis.Plugins.LayerBrushes.Noise { - public class NoiseLayerElement : LayerElement + public class NoiseBrush : LayerBrush { private const int Scale = 6; private static readonly Random Rand = new Random(); private readonly OpenSimplexNoise _noise; private float _z; - public NoiseLayerElement(Layer layer, Guid guid, NoiseLayerElementSettings settings, LayerElementDescriptor descriptor) : base(layer, guid, settings, descriptor) + public NoiseBrush(Layer layer, NoiseBrushSettings settings, LayerBrushDescriptor descriptor) : base(layer, settings, descriptor) { Settings = settings; _z = Rand.Next(0, 4096); - _noise = new OpenSimplexNoise(Guid.GetHashCode()); + _noise = new OpenSimplexNoise(Rand.Next(0, 4096)); } - public new NoiseLayerElementSettings Settings { get; } + public new NoiseBrushSettings Settings { get; } public override void Update(double deltaTime) @@ -34,16 +35,16 @@ namespace Artemis.Plugins.LayerElements.Noise base.Update(deltaTime); } - public override LayerElementViewModel GetViewModel() + public override LayerBrushViewModel GetViewModel() { - return new NoiseLayerElementViewModel(this); + return new NoiseBrushViewModel(this); } - public override void Render(SKPath framePath, SKCanvas canvas) + public override void Render(SKCanvas canvas) { // Scale down the render path to avoid computing a value for every pixel - var width = (int) (Math.Max(Layer.RenderRectangle.Width, Layer.RenderRectangle.Height) / Scale); - var height = (int) (Math.Max(Layer.RenderRectangle.Width, Layer.RenderRectangle.Height) / Scale); + var width = (int) (Math.Max(Layer.Rectangle.Width, Layer.Rectangle.Height) / Scale); + var height = (int) (Math.Max(Layer.Rectangle.Width, Layer.Rectangle.Height) / Scale); var opacity = (float) Math.Round(Settings.Color.Alpha / 255.0, 2, MidpointRounding.AwayFromZero); using (var bitmap = new SKBitmap(new SKImageInfo(width, height))) { @@ -76,7 +77,7 @@ namespace Artemis.Plugins.LayerElements.Noise using (var sh = SKShader.CreateBitmap(bitmap, SKShaderTileMode.Mirror, SKShaderTileMode.Mirror, SKMatrix.MakeScale(Scale, Scale))) using (var paint = new SKPaint {Shader = sh, BlendMode = Settings.BlendMode}) { - canvas.DrawPath(framePath, paint); + canvas.DrawPath(Layer.LayerShape.RenderPath, paint); } } } diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseBrushProvider.cs b/src/Artemis.Plugins.LayerElements.Noise/NoiseBrushProvider.cs new file mode 100644 index 000000000..6d3f71307 --- /dev/null +++ b/src/Artemis.Plugins.LayerElements.Noise/NoiseBrushProvider.cs @@ -0,0 +1,26 @@ + +using Artemis.Core.Plugins.LayerBrush; +using Artemis.Core.Plugins.Models; + +namespace Artemis.Plugins.LayerBrushes.Noise +{ + public class NoiseBrushProvider : LayerBrushProvider + { + public NoiseBrushProvider(PluginInfo pluginInfo) : base(pluginInfo) + { + AddLayerBrushDescriptor("Noise", "A brush of that shows an animated random noise", "ScatterPlot"); + } + + public override void EnablePlugin() + { + } + + public override void DisablePlugin() + { + } + + public override void Dispose() + { + } + } +} \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementSettings.cs b/src/Artemis.Plugins.LayerElements.Noise/NoiseBrushSettings.cs similarity index 84% rename from src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementSettings.cs rename to src/Artemis.Plugins.LayerElements.Noise/NoiseBrushSettings.cs index cbe481616..2f045ba4a 100644 --- a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementSettings.cs +++ b/src/Artemis.Plugins.LayerElements.Noise/NoiseBrushSettings.cs @@ -1,9 +1,9 @@ -using Artemis.Core.Plugins.LayerElement; +using Artemis.Core.Plugins.LayerBrush; using SkiaSharp; -namespace Artemis.Plugins.LayerElements.Noise +namespace Artemis.Plugins.LayerBrushes.Noise { - public class NoiseLayerElementSettings : LayerElementSettings + public class NoiseBrushSettings : LayerBrushSettings { private float _animationSpeed; private SKBlendMode _blendMode; @@ -11,7 +11,7 @@ namespace Artemis.Plugins.LayerElements.Noise private float _xScale; private float _yScale; - public NoiseLayerElementSettings() + public NoiseBrushSettings() { // Color = new SKColor(0, 0, 0); // BlendMode = SKBlendMode.Color; diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementView.xaml b/src/Artemis.Plugins.LayerElements.Noise/NoiseBrushView.xaml similarity index 88% rename from src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementView.xaml rename to src/Artemis.Plugins.LayerElements.Noise/NoiseBrushView.xaml index 2123a0c1c..b642495ee 100644 --- a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementView.xaml +++ b/src/Artemis.Plugins.LayerElements.Noise/NoiseBrushView.xaml @@ -1,14 +1,14 @@ - + d:DataContext="{d:DesignInstance {x:Type noiseBrush:NoiseBrushViewModel}}"> @@ -41,7 +41,7 @@ - + @@ -69,7 +69,7 @@ SelectedValuePath="Value" DisplayMemberPath="Description" Width="100" - SelectedValue="{Binding LayerElement.Settings.BlendMode}" /> + SelectedValue="{Binding Brush.Settings.BlendMode}" /> @@ -89,7 +89,7 @@ - + @@ -110,7 +110,7 @@ - + @@ -132,7 +132,7 @@ - + diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseBrushViewModel.cs b/src/Artemis.Plugins.LayerElements.Noise/NoiseBrushViewModel.cs new file mode 100644 index 000000000..577728125 --- /dev/null +++ b/src/Artemis.Plugins.LayerElements.Noise/NoiseBrushViewModel.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Artemis.Core.Plugins.LayerBrush; +using Artemis.Core.Utilities; +using SkiaSharp; + +namespace Artemis.Plugins.LayerBrushes.Noise +{ + public class NoiseBrushViewModel : LayerBrushViewModel + { + public NoiseBrushViewModel(NoiseBrush brush) : base(brush) + { + Brush = brush; + } + + public new NoiseBrush Brush { get; } + public IEnumerable BlendModes => EnumUtilities.GetAllValuesAndDescriptions(typeof(SKBlendMode)); + } +} \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementProvider.cs b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementProvider.cs deleted file mode 100644 index f58fa5444..000000000 --- a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementProvider.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Artemis.Core.Plugins.LayerElement; -using Artemis.Core.Plugins.Models; - -namespace Artemis.Plugins.LayerElements.Noise -{ - public class NoiseLayerElementProvider : LayerElementProvider - { - public NoiseLayerElementProvider(PluginInfo pluginInfo) : base(pluginInfo) - { - AddLayerElementDescriptor("Noise", "A brush of that shows an animated random noise", "ScatterPlot"); - } - - public override void EnablePlugin() - { - } - - public override void DisablePlugin() - { - } - - public override void Dispose() - { - } - } -} \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementViewModel.cs b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementViewModel.cs deleted file mode 100644 index dd113db8a..000000000 --- a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementViewModel.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; -using Artemis.Core.Plugins.LayerElement; -using Artemis.Core.Utilities; -using SkiaSharp; - -namespace Artemis.Plugins.LayerElements.Noise -{ - public class NoiseLayerElementViewModel : LayerElementViewModel - { - public NoiseLayerElementViewModel(NoiseLayerElement layerElement) : base(layerElement) - { - LayerElement = layerElement; - } - - public new NoiseLayerElement LayerElement { get; } - public IEnumerable BlendModes => EnumUtilities.GetAllValuesAndDescriptions(typeof(SKBlendMode)); - } -} \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerElements.Noise/Properties/AssemblyInfo.cs b/src/Artemis.Plugins.LayerElements.Noise/Properties/AssemblyInfo.cs index b4c93e2c5..4da3ae745 100644 --- a/src/Artemis.Plugins.LayerElements.Noise/Properties/AssemblyInfo.cs +++ b/src/Artemis.Plugins.LayerElements.Noise/Properties/AssemblyInfo.cs @@ -5,7 +5,7 @@ using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("Artemis.Plugins.LayerElements.Noise")] +[assembly: AssemblyTitle("Artemis.Plugins.LayerBrushes.Noise")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] diff --git a/src/Artemis.Plugins.LayerElements.Noise/OpenSimplexNoise.cs b/src/Artemis.Plugins.LayerElements.Noise/Utilities/OpenSimplexNoise.cs similarity index 99% rename from src/Artemis.Plugins.LayerElements.Noise/OpenSimplexNoise.cs rename to src/Artemis.Plugins.LayerElements.Noise/Utilities/OpenSimplexNoise.cs index 0bcbdfad7..9917f7b5e 100644 --- a/src/Artemis.Plugins.LayerElements.Noise/OpenSimplexNoise.cs +++ b/src/Artemis.Plugins.LayerElements.Noise/Utilities/OpenSimplexNoise.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.CompilerServices; -namespace Artemis.Plugins.LayerElements.Noise +namespace Artemis.Plugins.LayerBrushes.Noise.Utilities { public class OpenSimplexNoise { diff --git a/src/Artemis.Plugins.LayerElements.Noise/plugin.json b/src/Artemis.Plugins.LayerElements.Noise/plugin.json index ad1c2a5c1..361bd77b4 100644 --- a/src/Artemis.Plugins.LayerElements.Noise/plugin.json +++ b/src/Artemis.Plugins.LayerElements.Noise/plugin.json @@ -1,10 +1,10 @@ { "Guid": "61cbbf01-8d69-4ede-a972-f3f269da66d9", - "Name": "Noise layer elements", + "Name": "Noise layer brush", "Version": { "Major": 1, "Minor": 0, "Build": 0 }, - "Main": "Artemis.Plugins.LayerElements.Noise.dll" + "Main": "Artemis.Plugins.LayerBrushes.Noise.dll" } \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerElements.Brush.csproj b/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerBrushes.Color.csproj similarity index 94% rename from src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerElements.Brush.csproj rename to src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerBrushes.Color.csproj index 9eb1b9e6a..345b42e67 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerElements.Brush.csproj +++ b/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerBrushes.Color.csproj @@ -7,8 +7,8 @@ {0F288A66-6EB0-4589-8595-E33A3A3EAEA2} Library Properties - Artemis.Plugins.LayerElements.Brush - Artemis.Plugins.LayerElements.Brush + Artemis.Plugins.LayerBrushes.Color + Artemis.Plugins.LayerBrushes.Color v4.7.2 512 true @@ -87,10 +87,10 @@ - - - - + + + + @@ -108,7 +108,7 @@ - + Designer MSBuild:Compile diff --git a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementProvider.cs b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementProvider.cs deleted file mode 100644 index 3d124573b..000000000 --- a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementProvider.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Artemis.Core.Plugins.LayerElement; -using Artemis.Core.Plugins.Models; - -namespace Artemis.Plugins.LayerElements.Brush -{ - public class BrushLayerElementProvider : LayerElementProvider - { - public BrushLayerElementProvider(PluginInfo pluginInfo) : base(pluginInfo) - { - AddLayerElementDescriptor("Brush", "A brush of a specific type and colors", "Brush"); - } - - public override void EnablePlugin() - { - } - - public override void DisablePlugin() - { - } - - public override void Dispose() - { - } - } -} \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementViewModel.cs b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementViewModel.cs deleted file mode 100644 index f47bdaf83..000000000 --- a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementViewModel.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; -using Artemis.Core.Plugins.LayerElement; -using Artemis.Core.Utilities; - -namespace Artemis.Plugins.LayerElements.Brush -{ - public class BrushLayerElementViewModel : LayerElementViewModel - { - public BrushLayerElementViewModel(BrushLayerElement layerElement) : base(layerElement) - { - LayerElement = layerElement; - } - - public new BrushLayerElement LayerElement { get; } - public IEnumerable BrushTypes => EnumUtilities.GetAllValuesAndDescriptions(typeof(BrushType)); - } -} \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs b/src/Artemis.Plugins.LayerTypes.Brush/ColorBrush.cs similarity index 59% rename from src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs rename to src/Artemis.Plugins.LayerTypes.Brush/ColorBrush.cs index b0571d11d..1d54fe85c 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs +++ b/src/Artemis.Plugins.LayerTypes.Brush/ColorBrush.cs @@ -2,19 +2,18 @@ using System.Collections.Generic; using System.Linq; using Artemis.Core.Models.Profile; -using Artemis.Core.Models.Surface; -using Artemis.Core.Plugins.LayerElement; +using Artemis.Core.Plugins.LayerBrush; using SkiaSharp; -namespace Artemis.Plugins.LayerElements.Brush +namespace Artemis.Plugins.LayerBrushes.Color { - public class BrushLayerElement : LayerElement + public class ColorBrush : LayerBrush { private SKShader _shader; private List _testColors; private SKPaint _paint; - public BrushLayerElement(Layer layer, Guid guid, BrushLayerElementSettings settings, LayerElementDescriptor descriptor) : base(layer, guid, settings, descriptor) + public ColorBrush(Layer layer, ColorBrushSettings settings, LayerBrushDescriptor descriptor) : base(layer, settings, descriptor) { Settings = settings; @@ -34,20 +33,20 @@ namespace Artemis.Plugins.LayerElements.Brush private void CreateShader() { - var center = new SKPoint(Layer.RenderRectangle.MidX, Layer.RenderRectangle.MidY); + var center = new SKPoint(Layer.Rectangle.MidX, Layer.Rectangle.MidY); SKShader shader; - switch (Settings.BrushType) + switch (Settings.GradientType) { - case BrushType.Solid: + case GradientType.Solid: shader = SKShader.CreateColor(_testColors.First()); break; - case BrushType.LinearGradient: - shader = SKShader.CreateLinearGradient(new SKPoint(0, 0), new SKPoint(Layer.RenderRectangle.Width, 0), _testColors.ToArray(), SKShaderTileMode.Repeat); + case GradientType.LinearGradient: + shader = SKShader.CreateLinearGradient(new SKPoint(0, 0), new SKPoint(Layer.Rectangle.Width, 0), _testColors.ToArray(), SKShaderTileMode.Repeat); break; - case BrushType.RadialGradient: - shader = SKShader.CreateRadialGradient(center, Math.Min(Layer.RenderRectangle.Width, Layer.RenderRectangle.Height), _testColors.ToArray(), SKShaderTileMode.Repeat); + case GradientType.RadialGradient: + shader = SKShader.CreateRadialGradient(center, Math.Min(Layer.Rectangle.Width, Layer.Rectangle.Height), _testColors.ToArray(), SKShaderTileMode.Repeat); break; - case BrushType.SweepGradient: + case GradientType.SweepGradient: shader = SKShader.CreateSweepGradient(center, _testColors.ToArray(), null, SKShaderTileMode.Clamp, 0, 360); break; default: @@ -62,16 +61,16 @@ namespace Artemis.Plugins.LayerElements.Brush oldPaint?.Dispose(); } - public new BrushLayerElementSettings Settings { get; } + public new ColorBrushSettings Settings { get; } - public override LayerElementViewModel GetViewModel() + public override LayerBrushViewModel GetViewModel() { - return new BrushLayerElementViewModel(this); + return new ColorBrushViewModel(this); } - public override void Render(SKPath framePath, SKCanvas canvas) + public override void Render(SKCanvas canvas) { - canvas.DrawPath(framePath, _paint); + canvas.DrawPath(Layer.LayerShape.RenderPath, _paint); } } } \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerTypes.Brush/ColorBrushProvider.cs b/src/Artemis.Plugins.LayerTypes.Brush/ColorBrushProvider.cs new file mode 100644 index 000000000..f6997a637 --- /dev/null +++ b/src/Artemis.Plugins.LayerTypes.Brush/ColorBrushProvider.cs @@ -0,0 +1,25 @@ +using Artemis.Core.Plugins.LayerBrush; +using Artemis.Core.Plugins.Models; + +namespace Artemis.Plugins.LayerBrushes.Color +{ + public class ColorBrushProvider : LayerBrushProvider + { + public ColorBrushProvider(PluginInfo pluginInfo) : base(pluginInfo) + { + AddLayerBrushDescriptor("Color", "A color with an (optional) gradient", "Brush"); + } + + public override void EnablePlugin() + { + } + + public override void DisablePlugin() + { + } + + public override void Dispose() + { + } + } +} \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementSettings.cs b/src/Artemis.Plugins.LayerTypes.Brush/ColorBrushSettings.cs similarity index 58% rename from src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementSettings.cs rename to src/Artemis.Plugins.LayerTypes.Brush/ColorBrushSettings.cs index ddaae693e..78d46cc17 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementSettings.cs +++ b/src/Artemis.Plugins.LayerTypes.Brush/ColorBrushSettings.cs @@ -1,25 +1,25 @@ using System.Collections.Generic; using System.ComponentModel; -using Artemis.Core.Plugins.LayerElement; +using Artemis.Core.Plugins.LayerBrush; using SkiaSharp; -namespace Artemis.Plugins.LayerElements.Brush +namespace Artemis.Plugins.LayerBrushes.Color { - public class BrushLayerElementSettings : LayerElementSettings + public class ColorBrushSettings : LayerBrushSettings { - private BrushType _brushType; private List _colors; + private GradientType _gradientType; - public BrushLayerElementSettings() + public ColorBrushSettings() { - BrushType = BrushType.Solid; + GradientType = GradientType.Solid; Colors = new List(); } - public BrushType BrushType + public GradientType GradientType { - get => _brushType; - set => SetAndNotify(ref _brushType, value); + get => _gradientType; + set => SetAndNotify(ref _gradientType, value); } public List Colors @@ -29,7 +29,7 @@ namespace Artemis.Plugins.LayerElements.Brush } } - public enum BrushType + public enum GradientType { [Description("Solid")] Solid, diff --git a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementView.xaml b/src/Artemis.Plugins.LayerTypes.Brush/ColorBrushView.xaml similarity index 94% rename from src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementView.xaml rename to src/Artemis.Plugins.LayerTypes.Brush/ColorBrushView.xaml index b9bb5e796..2a038da7b 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementView.xaml +++ b/src/Artemis.Plugins.LayerTypes.Brush/ColorBrushView.xaml @@ -1,13 +1,12 @@ - + d:DataContext="{d:DesignInstance {x:Type colorBrush:ColorBrushViewModel}}"> @@ -47,7 +46,7 @@ ItemsSource="{Binding Path=BrushTypes}" SelectedValuePath="Value" DisplayMemberPath="Description" - SelectedValue="{Binding Path=LayerElement.Settings.BrushType}" /> + SelectedValue="{Binding Path=ColorBrush.Settings.GradientType}" /> diff --git a/src/Artemis.Plugins.LayerTypes.Brush/ColorBrushViewModel.cs b/src/Artemis.Plugins.LayerTypes.Brush/ColorBrushViewModel.cs new file mode 100644 index 000000000..437b22ae8 --- /dev/null +++ b/src/Artemis.Plugins.LayerTypes.Brush/ColorBrushViewModel.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using Artemis.Core.Plugins.LayerBrush; +using Artemis.Core.Utilities; + +namespace Artemis.Plugins.LayerBrushes.Color +{ + public class ColorBrushViewModel : LayerBrushViewModel + { + public ColorBrushViewModel(ColorBrush element) : base(element) + { + ColorBrush = element; + } + + public new ColorBrush ColorBrush { get; } + public IEnumerable BrushTypes => EnumUtilities.GetAllValuesAndDescriptions(typeof(GradientType)); + } +} \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerTypes.Brush/Properties/AssemblyInfo.cs b/src/Artemis.Plugins.LayerTypes.Brush/Properties/AssemblyInfo.cs index 54e9088c8..bdee98c07 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/Properties/AssemblyInfo.cs +++ b/src/Artemis.Plugins.LayerTypes.Brush/Properties/AssemblyInfo.cs @@ -4,7 +4,7 @@ using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("Artemis.Plugins.LayerElements.Brush")] +[assembly: AssemblyTitle("Artemis.Plugins.LayerBrushes.Color")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] diff --git a/src/Artemis.Plugins.LayerTypes.Brush/plugin.json b/src/Artemis.Plugins.LayerTypes.Brush/plugin.json index 95eee07a0..72b94b411 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/plugin.json +++ b/src/Artemis.Plugins.LayerTypes.Brush/plugin.json @@ -1,10 +1,10 @@ { "Guid": "92a9d6ba-6f7a-4937-94d5-c1d715b4141a", - "Name": "Brush layer elements", + "Name": "Color layer brush", "Version": { "Major": 1, "Minor": 0, "Build": 0 }, - "Main": "Artemis.Plugins.LayerElements.Brush.dll" + "Main": "Artemis.Plugins.LayerBrushes.Color.dll" } \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Profile/BrushEntity.cs b/src/Artemis.Storage/Entities/Profile/BrushEntity.cs new file mode 100644 index 000000000..99101eb4a --- /dev/null +++ b/src/Artemis.Storage/Entities/Profile/BrushEntity.cs @@ -0,0 +1,11 @@ +using System; + +namespace Artemis.Storage.Entities.Profile +{ + public class BrushEntity + { + public Guid BrushPluginGuid { get; set; } + public string BrushType { get; set; } + public string Configuration { get; set; } + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Profile/LayerElementEntity.cs b/src/Artemis.Storage/Entities/Profile/LayerElementEntity.cs deleted file mode 100644 index d05fda48a..000000000 --- a/src/Artemis.Storage/Entities/Profile/LayerElementEntity.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace Artemis.Storage.Entities.Profile -{ - public class LayerElementEntity - { - public Guid Id { get; set; } - - public Guid PluginGuid { get; set; } - public string LayerElementType { get; set; } - public string Configuration { get; set; } - } -} \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Profile/LayerEntity.cs b/src/Artemis.Storage/Entities/Profile/LayerEntity.cs index 59d1ed26c..5b49bb2a0 100644 --- a/src/Artemis.Storage/Entities/Profile/LayerEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/LayerEntity.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Drawing; using LiteDB; namespace Artemis.Storage.Entities.Profile @@ -10,7 +11,6 @@ namespace Artemis.Storage.Entities.Profile { Leds = new List(); Condition = new List(); - Elements = new List(); } public Guid Id { get; set; } @@ -21,11 +21,12 @@ namespace Artemis.Storage.Entities.Profile public List Leds { get; set; } public List Condition { get; set; } - public List Elements { get; set; } + + public ShapeEntity ShapeEntity { get; set; } + public BrushEntity BrushEntity { get; set; } [BsonRef("ProfileEntity")] public ProfileEntity Profile { get; set; } - public Guid ProfileId { get; set; } } } \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Profile/ShapeEntity.cs b/src/Artemis.Storage/Entities/Profile/ShapeEntity.cs new file mode 100644 index 000000000..4427b4354 --- /dev/null +++ b/src/Artemis.Storage/Entities/Profile/ShapeEntity.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; + +namespace Artemis.Storage.Entities.Profile +{ + public class ShapeEntity + { + public ShapeEntityType Type { get; set; } + public ShapePointEntity Anchor { get; set; } + public float Width { get; set; } + public float Height { get; set; } + public ShapePointEntity Position { get; set; } + + public List Points { get; set; } + } + + public class ShapePointEntity + { + public float X { get; set; } + public float Y { get; set; } + } + + public enum ShapeEntityType + { + Ellipse, + Fill, + Polygon, + Rectangle + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index 3f531c5a7..950c80899 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -174,7 +174,48 @@ - + + LayerPropertiesView.xaml + + + + LayerPropertiesTimelineView.xaml + + + + + EllipseToolView.xaml + + + + FillToolView.xaml + + + + PolygonToolView.xaml + + + + RectangleToolView.xaml + + + + SelectionAddToolView.xaml + + + + SelectionRemoveToolView.xaml + + + + SelectionToolView.xaml + + + + ViewpointMoveToolView.xaml + + + SidebarView.xaml @@ -202,9 +243,6 @@ - - - @@ -269,15 +307,11 @@ Designer MSBuild:Compile - + Designer MSBuild:Compile - - Designer - MSBuild:Compile - - + Designer MSBuild:Compile @@ -301,6 +335,38 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -436,7 +502,24 @@ - + + + + + + + + + + + + + + + + + + diff --git a/src/Artemis.UI/Ninject/Factories/IViewModelFactory.cs b/src/Artemis.UI/Ninject/Factories/IViewModelFactory.cs index f13888a18..d171e66fa 100644 --- a/src/Artemis.UI/Ninject/Factories/IViewModelFactory.cs +++ b/src/Artemis.UI/Ninject/Factories/IViewModelFactory.cs @@ -1,4 +1,4 @@ -using Artemis.Core.Models.Profile.Abstract; +using Artemis.Core.Models.Profile; using Artemis.Core.Models.Surface; using Artemis.Core.Plugins.Abstract; using Artemis.UI.Screens.Module; diff --git a/src/Artemis.UI/Properties/Resources.Designer.cs b/src/Artemis.UI/Properties/Resources.Designer.cs index 43833c3a3..da2a448eb 100644 --- a/src/Artemis.UI/Properties/Resources.Designer.cs +++ b/src/Artemis.UI/Properties/Resources.Designer.cs @@ -60,6 +60,66 @@ namespace Artemis.UI.Properties { } } + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] aero_crosshair { + get { + object obj = ResourceManager.GetObject("aero_crosshair", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] aero_crosshair_minus { + get { + object obj = ResourceManager.GetObject("aero_crosshair_minus", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] aero_crosshair_plus { + get { + object obj = ResourceManager.GetObject("aero_crosshair_plus", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] aero_fill { + get { + object obj = ResourceManager.GetObject("aero_fill", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] aero_pen_min { + get { + object obj = ResourceManager.GetObject("aero_pen_min", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] aero_pen_plus { + get { + object obj = ResourceManager.GetObject("aero_pen_plus", resourceCulture); + return ((byte[])(obj)); + } + } + /// /// Looks up a localized resource of type System.Byte[]. /// diff --git a/src/Artemis.UI/Properties/Resources.resx b/src/Artemis.UI/Properties/Resources.resx index 224201a95..d7077ea48 100644 --- a/src/Artemis.UI/Properties/Resources.resx +++ b/src/Artemis.UI/Properties/Resources.resx @@ -118,6 +118,24 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\aero_crosshair.cur;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\aero_crosshair_minus.cur;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\aero_crosshair_plus.cur;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\aero_fill.cur;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\aero_pen_min.cur;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\aero_pen_plus.cur;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + ..\Resources\aero_rotate_bl.cur;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 diff --git a/src/Artemis.UI/Resources/aero_crosshair.cur b/src/Artemis.UI/Resources/aero_crosshair.cur new file mode 100644 index 000000000..53d8b0296 Binary files /dev/null and b/src/Artemis.UI/Resources/aero_crosshair.cur differ diff --git a/src/Artemis.UI/Resources/aero_crosshair_minus.cur b/src/Artemis.UI/Resources/aero_crosshair_minus.cur new file mode 100644 index 000000000..1e7f9be49 Binary files /dev/null and b/src/Artemis.UI/Resources/aero_crosshair_minus.cur differ diff --git a/src/Artemis.UI/Resources/aero_crosshair_plus.cur b/src/Artemis.UI/Resources/aero_crosshair_plus.cur new file mode 100644 index 000000000..7e16757eb Binary files /dev/null and b/src/Artemis.UI/Resources/aero_crosshair_plus.cur differ diff --git a/src/Artemis.UI/Resources/aero_fill.cur b/src/Artemis.UI/Resources/aero_fill.cur new file mode 100644 index 000000000..cef61ab1f Binary files /dev/null and b/src/Artemis.UI/Resources/aero_fill.cur differ diff --git a/src/Artemis.UI/Resources/aero_pen_min.cur b/src/Artemis.UI/Resources/aero_pen_min.cur new file mode 100644 index 000000000..25c34b32b Binary files /dev/null and b/src/Artemis.UI/Resources/aero_pen_min.cur differ diff --git a/src/Artemis.UI/Resources/aero_pen_plus.cur b/src/Artemis.UI/Resources/aero_pen_plus.cur new file mode 100644 index 000000000..07e29f3be Binary files /dev/null and b/src/Artemis.UI/Resources/aero_pen_plus.cur differ diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameViewModel.cs index 49a180f9f..3bfeca8c6 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameViewModel.cs @@ -1,5 +1,5 @@ using System.Threading.Tasks; -using Artemis.Core.Models.Profile.Abstract; +using Artemis.Core.Models.Profile; using Artemis.UI.ViewModels.Dialogs; using FluentValidation; using Stylet; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesView.xaml deleted file mode 100644 index 118740370..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesView.xaml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - Layer element properties - - - - - - - - - \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesViewModel.cs deleted file mode 100644 index 0ec5ab7c5..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesViewModel.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.ComponentModel; -using Artemis.Core.Plugins.LayerElement; -using Artemis.UI.Services.Interfaces; - -namespace Artemis.UI.Screens.Module.ProfileEditor.ElementProperties -{ - public class ElementPropertiesViewModel : ProfileEditorPanelViewModel - { - private readonly IProfileEditorService _profileEditorService; - - public ElementPropertiesViewModel(IProfileEditorService profileEditorService) - { - _profileEditorService = profileEditorService; - - _profileEditorService.SelectedLayerElementChanged += OnSelectedLayerElementChanged; - } - - public LayerElementViewModel LayerElementViewModel { get; set; } - - private void OnSelectedLayerElementChanged(object sender, EventArgs e) - { - if (LayerElementViewModel?.LayerElement?.Settings != null) - LayerElementViewModel.LayerElement.Settings.PropertyChanged -= SettingsOnPropertyChanged; - - LayerElementViewModel = _profileEditorService.SelectedLayerElement?.GetViewModel(); - - if (LayerElementViewModel?.LayerElement?.Settings != null) - LayerElementViewModel.LayerElement.Settings.PropertyChanged += SettingsOnPropertyChanged; - } - - private void SettingsOnPropertyChanged(object sender, PropertyChangedEventArgs e) - { - _profileEditorService.UpdateSelectedProfileElement(); - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/Dialogs/AddLayerElementView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/Dialogs/AddLayerElementView.xaml deleted file mode 100644 index 775b422a1..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/Dialogs/AddLayerElementView.xaml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - Select a new layer element below - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/Dialogs/AddLayerElementViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/Dialogs/AddLayerElementViewModel.cs deleted file mode 100644 index eb1af8461..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/Dialogs/AddLayerElementViewModel.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Windows.Input; -using Artemis.Core.Models.Profile; -using Artemis.Core.Plugins.LayerElement; -using Artemis.Core.Services.Interfaces; -using Artemis.UI.ViewModels.Dialogs; -using Stylet; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerElements.Dialogs -{ - public class AddLayerElementViewModel : DialogViewModelBase - { - private readonly ILayerService _layerService; - - - public AddLayerElementViewModel(IPluginService pluginService, ILayerService layerService, Layer layer) - { - _layerService = layerService; - Layer = layer; - - LayerElementDescriptors = new BindableCollection(); - var layerElementProviders = pluginService.GetPluginsOfType(); - foreach (var layerElementProvider in layerElementProviders) - LayerElementDescriptors.AddRange(layerElementProvider.LayerElementDescriptors); - } - - public Layer Layer { get; } - - public LayerElementDescriptor SelectedLayerElementDescriptor { get; set; } - public BindableCollection LayerElementDescriptors { get; set; } - public bool CanAccept => SelectedLayerElementDescriptor != null; - - public void Accept() - { - if (Session.IsEnded) - return; - var layerElement = _layerService.InstantiateLayerElement(Layer, SelectedLayerElementDescriptor); - Session.Close(layerElement); - } - - public void Cancel() - { - if (Session.IsEnded) - return; - Session.Close(); - } - - #region View event handlers - - public void ListBoxItemMouseClick(object sender, MouseButtonEventArgs args) - { - if (args.ClickCount > 1 && SelectedLayerElementDescriptor != null) - Accept(); - } - - #endregion - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementViewModel.cs deleted file mode 100644 index 62ad2762a..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementViewModel.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Artemis.Core.Models.Profile; -using Artemis.Core.Plugins.LayerElement; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerElements -{ - public class LayerElementViewModel - { - public LayerElementViewModel(LayerElement layerElement) - { - Layer = layerElement.Layer; - LayerElement = layerElement; - LayerElementDescriptor = layerElement.Descriptor; - } - - public Layer Layer { get; set; } - public LayerElement LayerElement { get; set; } - public LayerElementDescriptor LayerElementDescriptor { get; set; } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsView.xaml deleted file mode 100644 index a48a84a99..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsView.xaml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - Layer elements - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsViewModel.cs deleted file mode 100644 index 93ded24a4..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsViewModel.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Artemis.Core.Models.Profile; -using Artemis.Core.Models.Profile.Abstract; -using Artemis.Core.Plugins.LayerElement; -using Artemis.Core.Services.Interfaces; -using Artemis.UI.Screens.Module.ProfileEditor.LayerElements.Dialogs; -using Artemis.UI.Services.Interfaces; -using Stylet; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerElements -{ - public class LayerElementsViewModel : ProfileEditorPanelViewModel - { - private readonly IDialogService _dialogService; - private readonly IProfileEditorService _profileEditorService; - private readonly ILayerService _layerService; - private LayerElementViewModel _selectedLayerElement; - - public LayerElementsViewModel(IProfileEditorService profileEditorService, ILayerService layerService, IDialogService dialogService) - { - _profileEditorService = profileEditorService; - _layerService = layerService; - _dialogService = dialogService; - - LayerElements = new BindableCollection(); - SelectedProfileElement = _profileEditorService.SelectedProfileElement; - PopulateLayerElements(); - - _profileEditorService.SelectedProfileElementChanged += OnSelectedProfileElementChanged; - _profileEditorService.SelectedLayerElementChanged += OnSelectedLayerElementChanged; - } - - public ProfileElement SelectedProfileElement { get; private set; } - public BindableCollection LayerElements { get; set; } - - public LayerElementViewModel SelectedLayerElement - { - get => _selectedLayerElement; - set - { - _selectedLayerElement = value; - _profileEditorService.ChangeSelectedLayerElement(value?.LayerElement); - } - } - - public bool CanAddLayerElement => SelectedProfileElement is Layer; - public bool CanDeleteSelectedLayerElement => SelectedLayerElement != null; - - private void OnSelectedLayerElementChanged(object sender, EventArgs e) - { - _selectedLayerElement = LayerElements.FirstOrDefault(l => l.LayerElement == _profileEditorService.SelectedLayerElement); - NotifyOfPropertyChange(() => SelectedLayerElement); - } - - private void OnSelectedProfileElementChanged(object sender, EventArgs e) - { - SelectedProfileElement = _profileEditorService.SelectedProfileElement; - PopulateLayerElements(); - } - - private void PopulateLayerElements() - { - LayerElements.Clear(); - if (SelectedProfileElement is Layer layer) - { - foreach (var layerElement in layer.LayerElements) - LayerElements.Add(new LayerElementViewModel(layerElement)); - } - } - - public async void AddLayerElement() - { - var result = await _dialogService.ShowDialogAt( - "LayerElementsDialogHost", - new Dictionary {{"layer", (Layer) SelectedProfileElement}} - ); - - if (!(result is LayerElement layerElement)) - return; - - LayerElements.Add(new LayerElementViewModel(layerElement)); - _profileEditorService.UpdateSelectedProfileElement(); - } - - public async void DeleteSelectedLayerElement() - { - if (SelectedLayerElement == null) - return; - - var result = await _dialogService.ShowConfirmDialogAt( - "LayerElementsDialogHost", - "Delete layer element", - "Are you sure you want to delete the selected layer element?" - ); - - if (!result) - return; - - var layerElement = SelectedLayerElement.LayerElement; - var layer = (Layer) SelectedProfileElement; - - LayerElements.Remove(SelectedLayerElement); - SelectedLayerElement = null; - - _layerService.RemoveLayerElement(layer, layerElement); - _profileEditorService.UpdateSelectedProfileElement(); - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml new file mode 100644 index 000000000..bd434fc98 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml.cs new file mode 100644 index 000000000..2ae9f3467 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties +{ + /// + /// Interaction logic for LayerPropertiesView.xaml + /// + public partial class LayerPropertiesView : UserControl + { + public LayerPropertiesView() + { + InitializeComponent(); + } + } +} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs new file mode 100644 index 000000000..0b460a8af --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties +{ + public class LayerPropertiesViewModel : ProfileEditorPanelViewModel + { + } +} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/LayerPropertiesTimelineView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/LayerPropertiesTimelineView.xaml new file mode 100644 index 000000000..efece35e0 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/LayerPropertiesTimelineView.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/LayerPropertiesTimelineView.xaml.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/LayerPropertiesTimelineView.xaml.cs new file mode 100644 index 000000000..04537617f --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/LayerPropertiesTimelineView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline +{ + /// + /// Interaction logic for LayerPropertiesTimelineView.xaml + /// + public partial class LayerPropertiesTimelineView : UserControl + { + public LayerPropertiesTimelineView() + { + InitializeComponent(); + } + } +} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/LayerPropertiesTimelineViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/LayerPropertiesTimelineViewModel.cs new file mode 100644 index 000000000..4c5ca963f --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/LayerPropertiesTimelineViewModel.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline +{ + class LayerPropertiesTimelineViewModel + { + } +} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorView.xaml index 4ee4b2843..fe14e5d48 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorView.xaml @@ -80,7 +80,7 @@ - + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs index cdad6a569..01dac87de 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs @@ -10,8 +10,7 @@ using Artemis.Core.Services; using Artemis.Core.Services.Storage.Interfaces; using Artemis.UI.Screens.Module.ProfileEditor.Dialogs; using Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions; -using Artemis.UI.Screens.Module.ProfileEditor.ElementProperties; -using Artemis.UI.Screens.Module.ProfileEditor.LayerElements; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties; using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree; using Artemis.UI.Screens.Module.ProfileEditor.Visualization; using Artemis.UI.Services.Interfaces; @@ -41,8 +40,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor DialogService = dialogService; DisplayConditionsViewModel = (DisplayConditionsViewModel) viewModels.First(vm => vm is DisplayConditionsViewModel); - ElementPropertiesViewModel = (ElementPropertiesViewModel) viewModels.First(vm => vm is ElementPropertiesViewModel); - LayerElementsViewModel = (LayerElementsViewModel) viewModels.First(vm => vm is LayerElementsViewModel); + LayerPropertiesViewModel = (LayerPropertiesViewModel) viewModels.First(vm => vm is LayerPropertiesViewModel); ProfileTreeViewModel = (ProfileTreeViewModel) viewModels.First(vm => vm is ProfileTreeViewModel); ProfileViewModel = (ProfileViewModel) viewModels.First(vm => vm is ProfileViewModel); Profiles = new BindableCollection(); @@ -55,8 +53,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor public ProfileModule Module { get; } public IDialogService DialogService { get; } public DisplayConditionsViewModel DisplayConditionsViewModel { get; } - public ElementPropertiesViewModel ElementPropertiesViewModel { get; } - public LayerElementsViewModel LayerElementsViewModel { get; } + public LayerPropertiesViewModel LayerPropertiesViewModel { get; } public ProfileTreeViewModel ProfileTreeViewModel { get; } public ProfileViewModel ProfileViewModel { get; } public BindableCollection Profiles { get; set; } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/FolderViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/FolderViewModel.cs index 0a148fa99..3ba3e3db2 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/FolderViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/FolderViewModel.cs @@ -1,4 +1,4 @@ -using Artemis.Core.Models.Profile.Abstract; +using Artemis.Core.Models.Profile; using Artemis.UI.Ninject.Factories; using Artemis.UI.Services.Interfaces; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerViewModel.cs index 016ef7332..7be6ebf61 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerViewModel.cs @@ -1,4 +1,4 @@ -using Artemis.Core.Models.Profile.Abstract; +using Artemis.Core.Models.Profile; using Artemis.UI.Ninject.Factories; using Artemis.UI.Services.Interfaces; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs index 3c48babf9..a6799d99a 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading.Tasks; using Artemis.Core.Models.Profile; -using Artemis.Core.Models.Profile.Abstract; using Artemis.UI.Exceptions; using Artemis.UI.Ninject.Factories; using Artemis.UI.Screens.Module.ProfileEditor.Dialogs; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/CanvasViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/CanvasViewModel.cs new file mode 100644 index 000000000..6cdf3689b --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/CanvasViewModel.cs @@ -0,0 +1,10 @@ +using Stylet; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization +{ + public class CanvasViewModel : PropertyChangedBase + { + public double X { get; set; } + public double Y { get; set; } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileDeviceView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileDeviceView.xaml index 21b97be25..1d30533fc 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileDeviceView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileDeviceView.xaml @@ -21,8 +21,8 @@ - Device.X; set => Device.X = value; } - public double Y + public new double Y { get => Device.Y; set => Device.Y = value; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml index 0bd189dab..bbb7aade4 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml @@ -23,7 +23,7 @@ - + @@ -39,164 +39,151 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Highlight selected layer - - - Pause visualization on focus loss - - - - - - - - - - - - - - - Initializing LED visualization... - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Highlight selected layer + + + Pause visualization on focus loss + + + + + + + + + + + + + + Initializing LED visualization... + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs index 570649c94..b79c23b41 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using System.Windows; using System.Windows.Input; using System.Windows.Media; using Artemis.Core.Events; @@ -12,13 +11,11 @@ using Artemis.Core.Plugins.Models; using Artemis.Core.Services; using Artemis.Core.Services.Storage.Interfaces; using Artemis.UI.Events; -using Artemis.UI.Extensions; +using Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools; using Artemis.UI.Screens.Shared; -using Artemis.UI.Screens.SurfaceEditor; using Artemis.UI.Services.Interfaces; using RGB.NET.Core; using Stylet; -using Point = System.Windows.Point; namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization { @@ -29,25 +26,21 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization private readonly ISurfaceService _surfaceService; private TimerUpdateTrigger _updateTrigger; - public ProfileViewModel(IProfileEditorService profileEditorService, - ISurfaceService surfaceService, - ISettingsService settingsService, - IEventAggregator eventAggregator) + public ProfileViewModel(IProfileEditorService profileEditorService, ISurfaceService surfaceService, ISettingsService settingsService, IEventAggregator eventAggregator) { _profileEditorService = profileEditorService; _surfaceService = surfaceService; _settingsService = settingsService; - Devices = new ObservableCollection(); - Cursor = null; - Execute.PostToUIThread(() => + Execute.OnUIThreadSync(() => { - SelectionRectangle = new RectangleGeometry(); + CanvasViewModels = new ObservableCollection(); PanZoomViewModel = new PanZoomViewModel(); }); ApplySurfaceConfiguration(surfaceService.ActiveSurface); CreateUpdateTrigger(); + ActivateToolByIndex(0); _profileEditorService.SelectedProfileElementChanged += OnSelectedProfileElementChanged; _profileEditorService.SelectedProfileElementUpdated += OnSelectedProfileElementChanged; @@ -55,13 +48,42 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization } public bool IsInitializing { get; private set; } - public ObservableCollection Devices { get; set; } - public RectangleGeometry SelectionRectangle { get; set; } + public ObservableCollection CanvasViewModels { get; set; } public PanZoomViewModel PanZoomViewModel { get; set; } public PluginSetting HighlightSelectedLayer { get; set; } public PluginSetting PauseRenderingOnFocusLoss { get; set; } - public Cursor Cursor { get; set; } + public ReadOnlyCollection Devices => CanvasViewModels + .Where(vm => vm is ProfileDeviceViewModel) + .Cast() + .ToList() + .AsReadOnly(); + + public VisualizationToolViewModel ActiveToolViewModel + { + get => _activeToolViewModel; + set + { + // Remove the tool from the canvas + if (_activeToolViewModel != null) + CanvasViewModels.Remove(_activeToolViewModel); + // Set the new tool + _activeToolViewModel = value; + // Add the new tool to the canvas + if (_activeToolViewModel != null) + CanvasViewModels.Add(_activeToolViewModel); + } + } + + public int ActiveToolIndex + { + get => _activeToolIndex; + set + { + _activeToolIndex = value; + ActivateToolByIndex(value); + } + } private void CreateUpdateTrigger() { @@ -82,12 +104,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization private void ApplySurfaceConfiguration(ArtemisSurface surface) { - List devices; - lock (Devices) - { - devices = new List(); - devices.AddRange(surface.Devices); - } + var devices = new List(); + devices.AddRange(surface.Devices); // Make sure all devices have an up-to-date VM foreach (var surfaceDeviceConfiguration in devices) @@ -102,9 +120,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization { // Gotta call IsInitializing on the UI thread or its never gets picked up IsInitializing = true; - lock (Devices) + lock (CanvasViewModels) { - Devices.Add(profileDeviceViewModel); + CanvasViewModels.Add(profileDeviceViewModel); } }); } @@ -112,21 +130,22 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization else viewModel.Device = surfaceDeviceConfiguration; } - + + // Sort the devices by ZIndex Execute.PostToUIThread(() => { - lock (Devices) + lock (CanvasViewModels) { foreach (var device in Devices.OrderBy(d => d.ZIndex).ToList()) - Devices.Move(Devices.IndexOf(device), device.ZIndex - 1); + CanvasViewModels.Move(CanvasViewModels.IndexOf(device), device.ZIndex - 1); } }); } private void UpdateLeds(object sender, CustomUpdateData customUpdateData) { - lock (Devices) + lock (CanvasViewModels) { if (IsInitializing) IsInitializing = Devices.Any(d => !d.AddedLeds); @@ -165,11 +184,83 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization { HighlightSelectedLayer.Save(); PauseRenderingOnFocusLoss.Save(); - - _updateTrigger.Stop(); + + try + { + _updateTrigger.Stop(); + } + catch (NullReferenceException) + { + // TODO: Remove when fixed in RGB.NET, or avoid double stopping + } + base.OnDeactivate(); } + #region Buttons + + private void ActivateToolByIndex(int value) + { + switch (value) + { + case 0: + ActiveToolViewModel = new ViewpointMoveToolViewModel(this, _profileEditorService); + break; + case 1: + ActiveToolViewModel = new SelectionToolViewModel(this, _profileEditorService); + break; + case 2: + ActiveToolViewModel = new SelectionAddToolViewModel(this, _profileEditorService); + break; + case 3: + ActiveToolViewModel = new SelectionRemoveToolViewModel(this, _profileEditorService); + break; + case 4: + ActiveToolViewModel = new EllipseToolViewModel(this, _profileEditorService); + break; + case 5: + ActiveToolViewModel = new RectangleToolViewModel(this, _profileEditorService); + break; + case 6: + ActiveToolViewModel = new PolygonToolViewModel(this, _profileEditorService); + break; + case 7: + ActiveToolViewModel = new FillToolViewModel(this, _profileEditorService); + break; + } + } + + public void ResetZoomAndPan() + { + PanZoomViewModel.Reset(); + } + + #endregion + + #region Mouse + + public void CanvasMouseDown(object sender, MouseButtonEventArgs e) + { + ActiveToolViewModel?.MouseDown(sender, e); + } + + public void CanvasMouseUp(object sender, MouseButtonEventArgs e) + { + ActiveToolViewModel?.MouseUp(sender, e); + } + + public void CanvasMouseMove(object sender, MouseEventArgs e) + { + ActiveToolViewModel?.MouseMove(sender, e); + } + + public void CanvasMouseWheel(object sender, MouseWheelEventArgs e) + { + ActiveToolViewModel?.MouseWheel(sender, e); + } + + #endregion + #region Context menu actions public bool CanApplyToLayer { get; set; } @@ -209,123 +300,23 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization #endregion - #region Selection + #region Keys - private MouseDragStatus _mouseDragStatus; - private Point _mouseDragStartPoint; + private int _previousTool; + private int _activeToolIndex; + private VisualizationToolViewModel _activeToolViewModel; - // ReSharper disable once UnusedMember.Global - Called from view - public void EditorGridMouseClick(object sender, MouseButtonEventArgs e) - { - if (IsPanKeyDown() || e.ChangedButton == MouseButton.Right) - return; - - var position = e.GetPosition((IInputElement) sender); - var relative = PanZoomViewModel.GetRelativeMousePosition(sender, e); - if (e.LeftButton == MouseButtonState.Pressed) - StartMouseDrag(position, relative); - else - StopMouseDrag(position); - } - - // ReSharper disable once UnusedMember.Global - Called from view - public void EditorGridMouseMove(object sender, MouseEventArgs e) - { - // If holding down Ctrl, pan instead of move/select - if (IsPanKeyDown()) - { - Pan(sender, e); - return; - } - - var position = e.GetPosition((IInputElement) sender); - if (_mouseDragStatus == MouseDragStatus.Selecting) - UpdateSelection(position); - } - - private void StartMouseDrag(Point position, Point relative) - { - _mouseDragStatus = MouseDragStatus.Selecting; - _mouseDragStartPoint = position; - - // Any time dragging starts, start with a new rect - SelectionRectangle.Rect = new Rect(); - } - - private void StopMouseDrag(Point position) - { - var selectedRect = new Rect(_mouseDragStartPoint, position); - foreach (var device in Devices) - { - foreach (var profileLedViewModel in device.Leds) - { - if (PanZoomViewModel.TransformContainingRect(profileLedViewModel.Led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1)).IntersectsWith(selectedRect)) - profileLedViewModel.IsSelected = true; - else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) - profileLedViewModel.IsSelected = false; - } - } - - _mouseDragStatus = MouseDragStatus.None; - } - - private void UpdateSelection(Point position) - { - if (IsPanKeyDown()) - return; - - var selectedRect = new Rect(_mouseDragStartPoint, position); - SelectionRectangle.Rect = selectedRect; - - foreach (var device in Devices) - { - foreach (var profileLedViewModel in device.Leds) - { - if (PanZoomViewModel.TransformContainingRect(profileLedViewModel.Led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1)).IntersectsWith(selectedRect)) - profileLedViewModel.IsSelected = true; - else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) - profileLedViewModel.IsSelected = false; - } - } - } - - #endregion - - #region Panning and zooming - - public void EditorGridMouseWheel(object sender, MouseWheelEventArgs e) - { - PanZoomViewModel.ProcessMouseScroll(sender, e); - } - - public void EditorGridKeyDown(object sender, KeyEventArgs e) + public void CanvasKeyDown(object sender, KeyEventArgs e) { + _previousTool = ActiveToolIndex; if ((e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl) && e.IsDown) - Cursor = Cursors.ScrollAll; + ActiveToolViewModel = new ViewpointMoveToolViewModel(this, _profileEditorService); } - public void EditorGridKeyUp(object sender, KeyEventArgs e) + public void CanvasKeyUp(object sender, KeyEventArgs e) { if ((e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl) && e.IsUp) - Cursor = null; - } - - public void Pan(object sender, MouseEventArgs e) - { - PanZoomViewModel.ProcessMouseMove(sender, e); - - // Empty the selection rect since it's shown while mouse is down - SelectionRectangle.Rect = Rect.Empty; - } - - public void ResetZoomAndPan() - { - PanZoomViewModel.Reset(); - } - - private bool IsPanKeyDown() - { - return Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl); + ActivateToolByIndex(_previousTool); } #endregion @@ -348,10 +339,17 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization if (PauseRenderingOnFocusLoss == null || ScreenState != ScreenState.Active) return; - if (PauseRenderingOnFocusLoss.Value && !message.IsFocused) - _updateTrigger.Stop(); - else if (PauseRenderingOnFocusLoss.Value && message.IsFocused) - _updateTrigger.Start(); + try + { + if (PauseRenderingOnFocusLoss.Value && !message.IsFocused) + _updateTrigger.Stop(); + else if (PauseRenderingOnFocusLoss.Value && message.IsFocused) + _updateTrigger.Start(); + } + catch (NullReferenceException) + { + // TODO: Remove when fixed in RGB.NET, or avoid double stopping + } } #endregion diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolView.xaml new file mode 100644 index 000000000..869d0d643 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolView.xaml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolView.xaml.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolView.xaml.cs new file mode 100644 index 000000000..0e1f9d1f8 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + /// + /// Interaction logic for EllipseToolView.xaml + /// + public partial class EllipseToolView : UserControl + { + public EllipseToolView() + { + InitializeComponent(); + } + } +} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolViewModel.cs new file mode 100644 index 000000000..51eebd5db --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EllipseToolViewModel.cs @@ -0,0 +1,18 @@ +using System.IO; +using System.Windows.Input; +using Artemis.UI.Properties; +using Artemis.UI.Services.Interfaces; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + public class EllipseToolViewModel : VisualizationToolViewModel + { + public EllipseToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService) + { + using (var stream = new MemoryStream(Resources.aero_crosshair)) + { + Cursor = new Cursor(stream); + } + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/FillToolView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/FillToolView.xaml new file mode 100644 index 000000000..7fd55cde8 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/FillToolView.xaml @@ -0,0 +1,9 @@ + + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/FillToolView.xaml.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/FillToolView.xaml.cs new file mode 100644 index 000000000..41ae6b8bb --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/FillToolView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + /// + /// Interaction logic for FillToolView.xaml + /// + public partial class FillToolView : UserControl + { + public FillToolView() + { + InitializeComponent(); + } + } +} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/FillToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/FillToolViewModel.cs new file mode 100644 index 000000000..6368d5e4d --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/FillToolViewModel.cs @@ -0,0 +1,39 @@ +using System.IO; +using System.Linq; +using System.Windows; +using System.Windows.Input; +using Artemis.Core.Models.Profile.LayerShapes; +using Artemis.UI.Properties; +using Artemis.UI.Services.Interfaces; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + public class FillToolViewModel : VisualizationToolViewModel + { + public FillToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService) + { + using (var stream = new MemoryStream(Resources.aero_fill)) + { + Cursor = new Cursor(stream); + } + } + + public override void MouseUp(object sender, MouseButtonEventArgs e) + { + base.MouseUp(sender, e); + + // Find out if the click is inside a layer and if so, fill it + var position = e.GetPosition((IInputElement) sender); + var panZoomVm = ProfileViewModel.PanZoomViewModel; + + var layer = ProfileEditorService.SelectedProfile + .GetAllLayers() + .FirstOrDefault(l => l.Leds.Any( + led => panZoomVm.TransformContainingRect(led.RgbLed.AbsoluteLedRectangle).Contains(position)) + ); + + if (layer != null) + layer.LayerShape = new Fill(layer); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/PolygonToolView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/PolygonToolView.xaml new file mode 100644 index 000000000..06e4f4c34 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/PolygonToolView.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/PolygonToolView.xaml.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/PolygonToolView.xaml.cs new file mode 100644 index 000000000..474e29284 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/PolygonToolView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + /// + /// Interaction logic for PolygonToolView.xaml + /// + public partial class PolygonToolView : UserControl + { + public PolygonToolView() + { + InitializeComponent(); + } + } +} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/PolygonToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/PolygonToolViewModel.cs new file mode 100644 index 000000000..7916d925b --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/PolygonToolViewModel.cs @@ -0,0 +1,18 @@ +using System.IO; +using System.Windows.Input; +using Artemis.UI.Properties; +using Artemis.UI.Services.Interfaces; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + public class PolygonToolViewModel : VisualizationToolViewModel + { + public PolygonToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService) + { + using (var stream = new MemoryStream(Resources.aero_crosshair)) + { + Cursor = new Cursor(stream); + } + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/RectangleToolView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/RectangleToolView.xaml new file mode 100644 index 000000000..62cd40ae9 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/RectangleToolView.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/RectangleToolView.xaml.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/RectangleToolView.xaml.cs new file mode 100644 index 000000000..8b4ea29f8 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/RectangleToolView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + /// + /// Interaction logic for RectangleToolView.xaml + /// + public partial class RectangleToolView : UserControl + { + public RectangleToolView() + { + InitializeComponent(); + } + } +} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/RectangleToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/RectangleToolViewModel.cs new file mode 100644 index 000000000..ad74e3bdb --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/RectangleToolViewModel.cs @@ -0,0 +1,18 @@ +using System.IO; +using System.Windows.Input; +using Artemis.UI.Properties; +using Artemis.UI.Services.Interfaces; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + public class RectangleToolViewModel : VisualizationToolViewModel + { + public RectangleToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService) + { + using (var stream = new MemoryStream(Resources.aero_crosshair)) + { + Cursor = new Cursor(stream); + } + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionAddToolView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionAddToolView.xaml new file mode 100644 index 000000000..f259e7a54 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionAddToolView.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionAddToolView.xaml.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionAddToolView.xaml.cs new file mode 100644 index 000000000..579d26b00 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionAddToolView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + /// + /// Interaction logic for SelectionAddToolView.xaml + /// + public partial class SelectionAddToolView : UserControl + { + public SelectionAddToolView() + { + InitializeComponent(); + } + } +} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionAddToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionAddToolViewModel.cs new file mode 100644 index 000000000..decdc6e5c --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionAddToolViewModel.cs @@ -0,0 +1,36 @@ +using System.IO; +using System.Windows; +using System.Windows.Input; +using Artemis.UI.Properties; +using Artemis.UI.Services.Interfaces; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + public class SelectionAddToolViewModel : VisualizationToolViewModel + { + public SelectionAddToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService) + { + using (var stream = new MemoryStream(Resources.aero_pen_plus)) + { + Cursor = new Cursor(stream); + } + } + + public override void MouseUp(object sender, MouseButtonEventArgs e) + { + base.MouseUp(sender, e); + + var position = e.GetPosition((IInputElement) sender); + var selectedRect = new Rect(MouseDownStartPosition, position); + + foreach (var device in ProfileViewModel.Devices) + { + foreach (var ledViewModel in device.Leds) + { + if (ProfileViewModel.PanZoomViewModel.TransformContainingRect(ledViewModel.Led.RgbLed.AbsoluteLedRectangle).IntersectsWith(selectedRect)) + ledViewModel.IsSelected = true; + } + } + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolView.xaml new file mode 100644 index 000000000..abca091af --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolView.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolView.xaml.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolView.xaml.cs new file mode 100644 index 000000000..a8a4c5974 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + /// + /// Interaction logic for SelectionRemoveToolView.xaml + /// + public partial class SelectionRemoveToolView : UserControl + { + public SelectionRemoveToolView() + { + InitializeComponent(); + } + } +} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs new file mode 100644 index 000000000..b0f8d7fa2 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs @@ -0,0 +1,36 @@ +using System.IO; +using System.Windows; +using System.Windows.Input; +using Artemis.UI.Properties; +using Artemis.UI.Services.Interfaces; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + public class SelectionRemoveToolViewModel : VisualizationToolViewModel + { + public SelectionRemoveToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService) + { + using (var stream = new MemoryStream(Resources.aero_pen_min)) + { + Cursor = new Cursor(stream); + } + } + + public override void MouseUp(object sender, MouseButtonEventArgs e) + { + base.MouseUp(sender, e); + + var position = e.GetPosition((IInputElement)sender); + var selectedRect = new Rect(MouseDownStartPosition, position); + + foreach (var device in ProfileViewModel.Devices) + { + foreach (var ledViewModel in device.Leds) + { + if (ProfileViewModel.PanZoomViewModel.TransformContainingRect(ledViewModel.Led.RgbLed.AbsoluteLedRectangle).IntersectsWith(selectedRect)) + ledViewModel.IsSelected = false; + } + } + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolView.xaml new file mode 100644 index 000000000..55faa6787 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolView.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolView.xaml.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolView.xaml.cs new file mode 100644 index 000000000..61f781a69 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + /// + /// Interaction logic for SelectionToolView.xaml + /// + public partial class SelectionToolView : UserControl + { + public SelectionToolView() + { + InitializeComponent(); + } + } +} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs new file mode 100644 index 000000000..aded6d1e3 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs @@ -0,0 +1,64 @@ +using System.IO; +using System.Windows; +using System.Windows.Input; +using Artemis.UI.Properties; +using Artemis.UI.Services.Interfaces; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + public class SelectionToolViewModel : VisualizationToolViewModel + { + public SelectionToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService) + { + using (var stream = new MemoryStream(Resources.aero_crosshair)) + { + Cursor = new Cursor(stream); + } + } + + public override void MouseDown(object sender, MouseButtonEventArgs e) + { + base.MouseDown(sender, e); +// ProfileViewModel.SelectionRectangle.Rect = new Rect(); + } + + public override void MouseUp(object sender, MouseButtonEventArgs e) + { + base.MouseUp(sender, e); + + var position = e.GetPosition((IInputElement) sender); + var selectedRect = new Rect(MouseDownStartPosition, position); + + foreach (var device in ProfileViewModel.Devices) + { + foreach (var ledViewModel in device.Leds) + { + if (ProfileViewModel.PanZoomViewModel.TransformContainingRect(ledViewModel.Led.RgbLed.AbsoluteLedRectangle).IntersectsWith(selectedRect)) + ledViewModel.IsSelected = true; + else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) + ledViewModel.IsSelected = false; + } + } + } + + public override void MouseMove(object sender, MouseEventArgs e) + { + base.MouseMove(sender, e); + + var position = e.GetPosition((IInputElement) sender); + var selectedRect = new Rect(MouseDownStartPosition, position); +// ProfileViewModel.SelectionRectangle.Rect = selectedRect; + + foreach (var device in ProfileViewModel.Devices) + { + foreach (var ledViewModel in device.Leds) + { + if (ProfileViewModel.PanZoomViewModel.TransformContainingRect(ledViewModel.Led.RgbLed.AbsoluteLedRectangle).IntersectsWith(selectedRect)) + ledViewModel.IsSelected = true; + else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) + ledViewModel.IsSelected = false; + } + } + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/ViewpointMoveToolView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/ViewpointMoveToolView.xaml new file mode 100644 index 000000000..c385c260a --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/ViewpointMoveToolView.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/ViewpointMoveToolView.xaml.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/ViewpointMoveToolView.xaml.cs new file mode 100644 index 000000000..b9ae6452e --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/ViewpointMoveToolView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + /// + /// Interaction logic for ViewpointMoveToolView.xaml + /// + public partial class ViewpointMoveToolView : UserControl + { + public ViewpointMoveToolView() + { + InitializeComponent(); + } + } +} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/ViewpointMoveToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/ViewpointMoveToolViewModel.cs new file mode 100644 index 000000000..5205f0a76 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/ViewpointMoveToolViewModel.cs @@ -0,0 +1,26 @@ +using System.Windows.Input; +using Artemis.UI.Services.Interfaces; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + public class ViewpointMoveToolViewModel : VisualizationToolViewModel + { + public ViewpointMoveToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService) + { + Cursor = Cursors.Hand; + } + + public override void MouseMove(object sender, MouseEventArgs e) + { + base.MouseMove(sender, e); + if (IsMouseDown) + ProfileViewModel.PanZoomViewModel.ProcessMouseMove(sender, e); + } + + public override void MouseWheel(object sender, MouseWheelEventArgs e) + { + base.MouseWheel(sender, e); + ProfileViewModel.PanZoomViewModel.ProcessMouseScroll(sender, e); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/VisualizationToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/VisualizationToolViewModel.cs new file mode 100644 index 000000000..c109ac901 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/VisualizationToolViewModel.cs @@ -0,0 +1,45 @@ +using System.Windows; +using System.Windows.Input; +using Artemis.UI.Services.Interfaces; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools +{ + public abstract class VisualizationToolViewModel : CanvasViewModel + { + protected VisualizationToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) + { + // Not relevant for visualization tools as they overlay the entire canvas + X = 0; + Y = 0; + + ProfileViewModel = profileViewModel; + ProfileEditorService = profileEditorService; + Cursor = Cursors.Arrow; + } + + public ProfileViewModel ProfileViewModel { get; } + public IProfileEditorService ProfileEditorService { get; } + public Cursor Cursor { get; protected set; } + public bool IsMouseDown { get; protected set; } + public Point MouseDownStartPosition { get; protected set; } + + public virtual void MouseDown(object sender, MouseButtonEventArgs e) + { + IsMouseDown = true; + MouseDownStartPosition = e.GetPosition((IInputElement) sender); + } + + public virtual void MouseUp(object sender, MouseButtonEventArgs e) + { + IsMouseDown = false; + } + + public virtual void MouseMove(object sender, MouseEventArgs e) + { + } + + public virtual void MouseWheel(object sender, MouseWheelEventArgs e) + { + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs b/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs index 9b4ffe838..2b88d9e43 100644 --- a/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs +++ b/src/Artemis.UI/Screens/Shared/PanZoomViewModel.cs @@ -3,7 +3,10 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; +using Artemis.UI.Extensions; +using RGB.NET.Core; using Stylet; +using Point = System.Windows.Point; namespace Artemis.UI.Screens.Shared { @@ -71,6 +74,11 @@ namespace Artemis.UI.Screens.Shared PanY = 0; } + public Rect TransformContainingRect(Rectangle rect) + { + return TransformContainingRect(rect.ToWindowsRect(1)); + } + public Rect TransformContainingRect(Rect rect) { // Create the same transform group the view is using diff --git a/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml b/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml index 72c3b2c7a..f6c507589 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml +++ b/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml @@ -26,8 +26,8 @@ -