diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index ae98da40c..16e9663df 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -494,13 +494,13 @@ - - - AngularBrushPropertiesView.xaml + + + ConicalBrushPropertiesView.xaml - - - + + + @@ -872,7 +872,7 @@ MSBuild:Compile Designer - + Designer MSBuild:Compile diff --git a/Artemis/Artemis/Profiles/Layers/Types/AngularBrush/AngularBrushPropertiesView.xaml.cs b/Artemis/Artemis/Profiles/Layers/Types/AngularBrush/AngularBrushPropertiesView.xaml.cs deleted file mode 100644 index e5edeea15..000000000 --- a/Artemis/Artemis/Profiles/Layers/Types/AngularBrush/AngularBrushPropertiesView.xaml.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Windows.Controls; - -namespace Artemis.Profiles.Layers.Types.AngularBrush -{ - public partial class AngularBrushPropertiesView : UserControl - { - public AngularBrushPropertiesView() - { - InitializeComponent(); - } - } -} diff --git a/Artemis/Artemis/Profiles/Layers/Types/AngularBrush/AngularBrushPropertiesModel.cs b/Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/ConicalBrushPropertiesModel.cs similarity index 62% rename from Artemis/Artemis/Profiles/Layers/Types/AngularBrush/AngularBrushPropertiesModel.cs rename to Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/ConicalBrushPropertiesModel.cs index 58fdce801..a7a63c3db 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/AngularBrush/AngularBrushPropertiesModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/ConicalBrushPropertiesModel.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using System.Windows.Media; using Artemis.Profiles.Layers.Models; -namespace Artemis.Profiles.Layers.Types.AngularBrush +namespace Artemis.Profiles.Layers.Types.ConicalBrush { - public class AngularBrushPropertiesModel : LayerPropertiesModel + public class ConicalBrushPropertiesModel : LayerPropertiesModel { #region Properties & Fields @@ -15,14 +15,10 @@ namespace Artemis.Profiles.Layers.Types.AngularBrush #region Constructors - public AngularBrushPropertiesModel(LayerPropertiesModel properties = null) + public ConicalBrushPropertiesModel(LayerPropertiesModel properties = null) : base(properties) { } #endregion - - #region Methods - - #endregion } } diff --git a/Artemis/Artemis/Profiles/Layers/Types/AngularBrush/AngularBrushPropertiesView.xaml b/Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/ConicalBrushPropertiesView.xaml similarity index 97% rename from Artemis/Artemis/Profiles/Layers/Types/AngularBrush/AngularBrushPropertiesView.xaml rename to Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/ConicalBrushPropertiesView.xaml index b93018706..d2a9ad61b 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/AngularBrush/AngularBrushPropertiesView.xaml +++ b/Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/ConicalBrushPropertiesView.xaml @@ -1,4 +1,4 @@ -(editorVm.LayerAnimations); diff --git a/Artemis/Artemis/Profiles/Layers/Types/AngularBrush/AngularBrushType.cs b/Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/ConicalBrushType.cs similarity index 69% rename from Artemis/Artemis/Profiles/Layers/Types/AngularBrush/AngularBrushType.cs rename to Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/ConicalBrushType.cs index 0bdf2775e..347f56c59 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/AngularBrush/AngularBrushType.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/ConicalBrushType.cs @@ -7,40 +7,42 @@ using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Animations; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; -using Artemis.Profiles.Layers.Types.AngularBrush.Drawing; +using Artemis.Profiles.Layers.Types.ConicalBrush.Drawing; using Artemis.ViewModels; -namespace Artemis.Profiles.Layers.Types.AngularBrush +namespace Artemis.Profiles.Layers.Types.ConicalBrush { - public class AngularBrushType : ILayerType + public class ConicalBrushType : ILayerType { #region Properties & Fields - private GradientDrawer _gradientDrawer; + private ConicalGradientDrawer _conicalGradientDrawer; + private ConicalGradientDrawer _conicalGradientDrawerThumbnail; - public string Name => "Angular Brush"; + public string Name => "Conical Brush"; public bool ShowInEdtor => true; public DrawType DrawType => DrawType.Keyboard; #endregion - public AngularBrushType() + public ConicalBrushType() { - _gradientDrawer = new GradientDrawer(); + _conicalGradientDrawer = new ConicalGradientDrawer(); + _conicalGradientDrawerThumbnail = new ConicalGradientDrawer(18, 18); } #region Methods public ImageSource DrawThumbnail(LayerModel layer) { - //TODO DarthAffe 14.01.2017: This could be replaced with the real brush but it complaints about the thread too + _conicalGradientDrawerThumbnail.GradientStops = GetGradientStops(layer.Brush).Select(x => new Tuple(x.Offset, x.Color)).ToList(); + _conicalGradientDrawerThumbnail.Update(); + Rect thumbnailRect = new Rect(0, 0, 18, 18); DrawingVisual visual = new DrawingVisual(); using (DrawingContext c = visual.RenderOpen()) - if (layer.Properties.Brush != null) - c.DrawRectangle(layer.Properties.Brush, - new Pen(new SolidColorBrush(Colors.White), 1), - thumbnailRect); + if (_conicalGradientDrawerThumbnail.Brush != null) + c.DrawRectangle(_conicalGradientDrawerThumbnail.Brush.Clone(), new Pen(new SolidColorBrush(Colors.White), 1), thumbnailRect); DrawingImage image = new DrawingImage(visual.Drawing); return image; @@ -48,15 +50,14 @@ namespace Artemis.Profiles.Layers.Types.AngularBrush public void Draw(LayerModel layerModel, DrawingContext c) { - AngularBrushPropertiesModel properties = layerModel.Properties as AngularBrushPropertiesModel; + ConicalBrushPropertiesModel properties = layerModel.Properties as ConicalBrushPropertiesModel; if (properties == null) return; Brush origBrush = layerModel.Brush; - //TODO DarthAffe 14.01.2017: Check if an update is needed - _gradientDrawer.GradientStops = GetGradientStops(layerModel.Brush).Select(x => new Tuple(x.Offset, x.Color)).ToList(); - _gradientDrawer.Update(); - layerModel.Brush = _gradientDrawer.Brush.Clone(); + _conicalGradientDrawer.GradientStops = GetGradientStops(layerModel.Brush).Select(x => new Tuple(x.Offset, x.Color)).ToList(); + _conicalGradientDrawer.Update(); + layerModel.Brush = _conicalGradientDrawer.Brush; // If an animation is present, let it handle the drawing if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation)) @@ -97,15 +98,15 @@ namespace Artemis.Profiles.Layers.Types.AngularBrush public void SetupProperties(LayerModel layerModel) { - if (layerModel.Properties is AngularBrushPropertiesModel) + if (layerModel.Properties is ConicalBrushPropertiesModel) return; - layerModel.Properties = new AngularBrushPropertiesModel(layerModel.Properties); + layerModel.Properties = new ConicalBrushPropertiesModel(layerModel.Properties); } public LayerPropertiesViewModel SetupViewModel(LayerEditorViewModel layerEditorViewModel, LayerPropertiesViewModel layerPropertiesViewModel) { - return (layerPropertiesViewModel as AngularBrushPropertiesViewModel) ?? new AngularBrushPropertiesViewModel(layerEditorViewModel); + return (layerPropertiesViewModel as ConicalBrushPropertiesViewModel) ?? new ConicalBrushPropertiesViewModel(layerEditorViewModel); } private GradientStopCollection GetGradientStops(Brush brush) diff --git a/Artemis/Artemis/Profiles/Layers/Types/AngularBrush/Drawing/GradientDrawer.cs b/Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/Drawing/ConicalGradientDrawer.cs similarity index 64% rename from Artemis/Artemis/Profiles/Layers/Types/AngularBrush/Drawing/GradientDrawer.cs rename to Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/Drawing/ConicalGradientDrawer.cs index fd3d7e8c2..a68d93028 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/AngularBrush/Drawing/GradientDrawer.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/ConicalBrush/Drawing/ConicalGradientDrawer.cs @@ -1,38 +1,86 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; +using Brush = System.Windows.Media.Brush; +using Color = System.Windows.Media.Color; -namespace Artemis.Profiles.Layers.Types.AngularBrush.Drawing +namespace Artemis.Profiles.Layers.Types.ConicalBrush.Drawing { - public class GradientDrawer + public class ConicalGradientDrawer { #region Constants private static readonly double ORIGIN = Math.Atan2(-1, 0); - #endregion + #endregion #region Properties & Fields + private int _width; + private int _height; + + private bool _isDirty = true; + private int _lastGradientHash; + private WriteableBitmap _bitmap; private IList> _gradientStops; public IList> GradientStops { - set { _gradientStops = FixGradientStops(value); } + set + { + int hash = GetHash(value); + if (_lastGradientHash != hash) + { + _gradientStops = FixGradientStops(value); + _lastGradientHash = hash; + _isDirty = true; + } + } + } + + private PointF _center = new PointF(0.5f, 0.5f); + public PointF Center + { + get { return _center; } + set + { + if (_center != value) + { + _center = value; + _isDirty = true; + } + } } public Brush Brush { get; private set; } #endregion + #region Constructors + + public ConicalGradientDrawer() + : this(100, 100) + { } + + public ConicalGradientDrawer(int width, int height) + { + this._width = width; + this._height = height; + } + + #endregion + #region Methods - public void Update() + public void Update(bool force = false) { + if (!_isDirty && !force) return; + if (_bitmap == null) CreateBrush(); @@ -41,31 +89,27 @@ namespace Artemis.Profiles.Layers.Types.AngularBrush.Drawing _bitmap.Lock(); byte* buffer = (byte*)_bitmap.BackBuffer.ToPointer(); - int width = _bitmap.PixelWidth; - double widthHalf = width / 2.0; - - int height = _bitmap.PixelHeight; - double heightHalf = height / 2.0; - - for (int y = 0; y < height; y++) - for (int x = 0; x < width; x++) + for (int y = 0; y < _height; y++) + for (int x = 0; x < _width; x++) { - int offset = (((y * width) + x) * 4); + int offset = (((y * _width) + x) * 4); - double gradientOffset = CalculateGradientOffset(x, y, widthHalf, heightHalf); + double gradientOffset = CalculateGradientOffset(x, y, _width * Center.X, _height * Center.Y); GetColor(_gradientStops, gradientOffset, ref buffer[offset + 3], ref buffer[offset + 2], ref buffer[offset + 1], ref buffer[offset]); } - _bitmap.AddDirtyRect(new Int32Rect(0, 0, width, height)); + _bitmap.AddDirtyRect(new Int32Rect(0, 0, _width, _height)); _bitmap.Unlock(); } + + _isDirty = false; } private void CreateBrush() { - _bitmap = new WriteableBitmap(100, 100, 96, 96, PixelFormats.Bgra32, null); + _bitmap = new WriteableBitmap(_width, _height, 96, 96, PixelFormats.Bgra32, null); Brush = new ImageBrush(_bitmap) { Stretch = Stretch.UniformToFill }; } @@ -127,7 +171,7 @@ namespace Artemis.Profiles.Layers.Types.AngularBrush.Drawing colB = (byte)((afterColor.B - beforeColor.B) * blendFactor + beforeColor.B); } - private IList> FixGradientStops(IList> gradientStops) + private static IList> FixGradientStops(IList> gradientStops) { if (gradientStops == null) return new List>(); @@ -144,6 +188,14 @@ namespace Artemis.Profiles.Layers.Types.AngularBrush.Drawing return stops; } + private static int GetHash(IList> sequence) + { + unchecked + { + return sequence.Aggregate(487, (current, item) => (((current * 31) + item.Item1.GetHashCode()) * 31) + item.Item2.GetHashCode()); + } + } + #endregion } }