diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index 00c4b7a28..de5d77946 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -164,6 +164,7 @@ + diff --git a/src/Artemis.Core/JsonConverters/SKColorConverter.cs b/src/Artemis.Core/JsonConverters/SKColorConverter.cs new file mode 100644 index 000000000..d3fe0f69e --- /dev/null +++ b/src/Artemis.Core/JsonConverters/SKColorConverter.cs @@ -0,0 +1,24 @@ +using System; +using Newtonsoft.Json; +using SkiaSharp; + +namespace Artemis.Core.JsonConverters +{ + public class SKColorConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, SKColor value, JsonSerializer serializer) + { + writer.WriteValue(value.ToString()); + } + + public override SKColor ReadJson(JsonReader reader, Type objectType, SKColor existingValue, bool hasExistingValue, JsonSerializer serializer) + { + if (reader.Value is string value && !string.IsNullOrWhiteSpace(value)) + { + return SKColor.Parse(value); + } + + return SKColor.Empty; + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs index f784b2c65..606f5ccb3 100644 --- a/src/Artemis.Core/Services/CoreService.cs +++ b/src/Artemis.Core/Services/CoreService.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Threading.Tasks; using Artemis.Core.Events; using Artemis.Core.Exceptions; +using Artemis.Core.JsonConverters; using Artemis.Core.Plugins.Abstract; using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Storage.Interfaces; +using Newtonsoft.Json; using RGB.NET.Core; using Serilog; using SkiaSharp; @@ -36,9 +38,18 @@ namespace Artemis.Core.Services _pluginService.PluginEnabled += (sender, args) => _modules = _pluginService.GetPluginsOfType(); _pluginService.PluginDisabled += (sender, args) => _modules = _pluginService.GetPluginsOfType(); + ConfigureJsonConvert(); Task.Run(Initialize); } + private void ConfigureJsonConvert() + { + JsonConvert.DefaultSettings = () => new JsonSerializerSettings + { + Converters = new List { new SKColorConverter() } + }; + } + public void Dispose() { // Dispose services diff --git a/src/Artemis.Core/Services/LayerService.cs b/src/Artemis.Core/Services/LayerService.cs index 3ad30d676..cc8211dc3 100644 --- a/src/Artemis.Core/Services/LayerService.cs +++ b/src/Artemis.Core/Services/LayerService.cs @@ -8,16 +8,19 @@ using Artemis.Core.Services.Interfaces; using Newtonsoft.Json; using Ninject; using Ninject.Parameters; +using Serilog; namespace Artemis.Core.Services { public class LayerService : ILayerService { private readonly IKernel _kernel; + private readonly ILogger _logger; - public LayerService(IKernel kernel) + public LayerService(IKernel kernel, ILogger logger) { _kernel = kernel; + _logger = logger; } public LayerElement InstantiateLayerElement(Layer layer, LayerElementDescriptor layerElementDescriptor, string settings, Guid? guid) @@ -42,7 +45,19 @@ namespace Artemis.Core.Services $"Settings where provided but layer element of type {layerElementDescriptor.LayerElementType.Name} has no Settings property." ); } - settingsInstance = JsonConvert.DeserializeObject(settings, settingsType); + + try + { + settingsInstance = JsonConvert.DeserializeObject(settings, settingsType); + } + 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); + + settingsInstance = Activator.CreateInstance(settingsType); + } } // If no settings found, provide a fresh instance of the settings type else if (settingsType != null) diff --git a/src/Artemis.Plugins.LayerElements.Noise/Artemis.Plugins.LayerElements.Noise.csproj b/src/Artemis.Plugins.LayerElements.Noise/Artemis.Plugins.LayerElements.Noise.csproj index 811d6582c..8b2af9e34 100644 --- a/src/Artemis.Plugins.LayerElements.Noise/Artemis.Plugins.LayerElements.Noise.csproj +++ b/src/Artemis.Plugins.LayerElements.Noise/Artemis.Plugins.LayerElements.Noise.csproj @@ -100,6 +100,10 @@ Artemis.Core False + + {adb357e6-151d-4d0d-87cb-68fd0bc29812} + Artemis.UI.Shared + diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElement.cs b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElement.cs index 8d128de48..3160b907b 100644 --- a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElement.cs +++ b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElement.cs @@ -44,9 +44,10 @@ namespace Artemis.Plugins.LayerElements.Noise // 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 opacity = (float) Math.Round(Settings.Color.Alpha / 255.0, 2, MidpointRounding.AwayFromZero); using (var bitmap = new SKBitmap(new SKImageInfo(width, height))) { + bitmap.Erase(new SKColor(0, 0, 0, 0)); // Only compute pixels inside LEDs, due to scaling there may be some rounding issues but it's neglect-able foreach (var artemisLed in Layer.Leds) { @@ -60,13 +61,20 @@ namespace Artemis.Plugins.LayerElements.Noise for (var y = yStart; y < yEnd; y++) { var v = _noise.Evaluate(Settings.XScale * x / width, Settings.YScale * y / height, _z); - bitmap.SetPixel((int) x, (int) y, new SKColor(0, 0, 0, (byte) ((v + 1) * 127))); + var alpha = (byte) ((v + 1) * 127 * opacity); + // There's some fun stuff we can do here, like creating hard lines + // if (alpha > 128) + // alpha = 255; + // else + // alpha = 0; + var color = new SKColor(Settings.Color.Red, Settings.Color.Green, Settings.Color.Blue, alpha); + bitmap.SetPixel((int) x, (int) y, color); } } } using (var sh = SKShader.CreateBitmap(bitmap, SKShaderTileMode.Mirror, SKShaderTileMode.Mirror, SKMatrix.MakeScale(Scale, Scale))) - using (var paint = new SKPaint {Shader = sh}) + using (var paint = new SKPaint {Shader = sh, BlendMode = Settings.BlendMode}) { canvas.DrawPath(framePath, paint); } diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementSettings.cs b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementSettings.cs index bee90789f..cbe481616 100644 --- a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementSettings.cs +++ b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementSettings.cs @@ -5,18 +5,31 @@ namespace Artemis.Plugins.LayerElements.Noise { public class NoiseLayerElementSettings : LayerElementSettings { + private float _animationSpeed; private SKBlendMode _blendMode; + private SKColor _color; private float _xScale; private float _yScale; - private float _animationSpeed; - - + public NoiseLayerElementSettings() { - BlendMode = SKBlendMode.Color; - XScale = 0.5f; - YScale = 0.5f; - AnimationSpeed = 50f; +// Color = new SKColor(0, 0, 0); +// BlendMode = SKBlendMode.Color; +// XScale = 0.5f; +// YScale = 0.5f; +// AnimationSpeed = 50f; + } + + public SKColor Color + { + get => _color; + set => SetAndNotify(ref _color, value); + } + + public SKBlendMode BlendMode + { + get => _blendMode; + set => SetAndNotify(ref _blendMode, value); } public float XScale @@ -36,11 +49,5 @@ namespace Artemis.Plugins.LayerElements.Noise get => _animationSpeed; set => SetAndNotify(ref _animationSpeed, value); } - - public SKBlendMode BlendMode - { - get => _blendMode; - set => SetAndNotify(ref _blendMode, value); - } } } \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementView.xaml b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementView.xaml index 4e37292d2..2123a0c1c 100644 --- a/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementView.xaml +++ b/src/Artemis.Plugins.LayerElements.Noise/NoiseLayerElementView.xaml @@ -3,19 +3,18 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:noiseLayer="clr-namespace:Artemis.Plugins.LayerElements.Noise" + xmlns:artemis="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared" + xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance {x:Type noiseLayer:NoiseLayerElementViewModel}}"> - - - + @@ -29,6 +28,24 @@ + + + + + + + + + + + + + + + + + + @@ -38,17 +55,21 @@ - - Blend mode - Affects how the noise is rendered on the rest of the layer + + + + + + + + SelectedValue="{Binding LayerElement.Settings.BlendMode}" /> @@ -62,11 +83,13 @@ - - X Scale + + + + - + @@ -81,11 +104,13 @@ - - Y Scale + + + + - + @@ -100,11 +125,14 @@ - - Animation speed + + + + - + + diff --git a/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj b/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj index af8d5a9fa..c7accaf55 100644 --- a/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj +++ b/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj @@ -82,7 +82,6 @@ - diff --git a/src/Artemis.Plugins.Modules.General/ColorHelpers.cs b/src/Artemis.Plugins.Modules.General/ColorHelpers.cs deleted file mode 100644 index df07d6012..000000000 --- a/src/Artemis.Plugins.Modules.General/ColorHelpers.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace Artemis.Plugins.Modules.General -{ - public static class ColorHelpers - { - private static readonly Random Rand = new Random(); - - public static int GetRandomHue() - { - return Rand.Next(0, 360); - } - } -} \ No newline at end of file diff --git a/src/Artemis.Plugins.Modules.General/GeneralModule.cs b/src/Artemis.Plugins.Modules.General/GeneralModule.cs index 8d91df18a..c807b6878 100644 --- a/src/Artemis.Plugins.Modules.General/GeneralModule.cs +++ b/src/Artemis.Plugins.Modules.General/GeneralModule.cs @@ -1,11 +1,8 @@ using System; using System.Collections.Generic; -using Artemis.Core.Models.Surface; using Artemis.Core.Plugins.Abstract; using Artemis.Core.Plugins.Models; -using Artemis.Core.Services.Storage.Interfaces; using Artemis.Plugins.Modules.General.ViewModels; -using SkiaSharp; namespace Artemis.Plugins.Modules.General { @@ -13,31 +10,15 @@ namespace Artemis.Plugins.Modules.General { private readonly PluginSettings _settings; - public GeneralModule(PluginInfo pluginInfo, PluginSettings settings, ISurfaceService surfaceService) : base(pluginInfo) + public GeneralModule(PluginInfo pluginInfo, PluginSettings settings) : base(pluginInfo) { _settings = settings; DisplayName = "General"; ExpandsMainDataModel = true; - DeviceShaders = new Dictionary(); - RainbowColors = new List(); - for (var i = 0; i < 9; i++) - { - if (i != 8) - RainbowColors.Add(SKColor.FromHsv(i * 32, 100, 100)); - else - RainbowColors.Add(SKColor.FromHsv(0, 100, 100)); - } - - surfaceService.SurfaceConfigurationUpdated += (sender, args) => DeviceShaders.Clear(); var testSetting = _settings.GetSetting("TestSetting", DateTime.Now); } - public int MovePercentage { get; set; } - - public Dictionary DeviceShaders { get; set; } - public List RainbowColors { get; set; } - public override void EnablePlugin() { } @@ -46,59 +27,6 @@ namespace Artemis.Plugins.Modules.General { } - public override void Update(double deltaTime) - { - MovePercentage++; - if (MovePercentage > 100) - MovePercentage = 0; - - base.Update(deltaTime); - } - - - public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas) - { - base.Render(deltaTime, surface, canvas); - return; - - foreach (var device in surface.Devices) - { - using (var bitmap = new SKBitmap(new SKImageInfo((int) device.RenderRectangle.Width, (int) device.RenderRectangle.Height))) - { - using (var layerCanvas = new SKCanvas(bitmap)) - { - layerCanvas.Clear(); - SKShader shader; - if (DeviceShaders.ContainsKey(device)) - shader = DeviceShaders[device]; - else - { - shader = SKShader.CreateLinearGradient( - new SKPoint(0, 0), - new SKPoint(device.RenderRectangle.Width, 0), - RainbowColors.ToArray(), - null, - SKShaderTileMode.Clamp); - DeviceShaders.Add(device, shader); - } - - using (var paint = new SKPaint {Shader = shader, FilterQuality = SKFilterQuality.Low}) - { - layerCanvas.DrawRect(0, 0, device.RenderRectangle.Width, device.RenderRectangle.Height, paint); - } - } - - using (var bitmapShader = SKShader.CreateBitmap(bitmap, SKShaderTileMode.Repeat, SKShaderTileMode.Repeat)) - using (var translated = SKShader.CreateLocalMatrix(bitmapShader, SKMatrix.MakeTranslation(device.RenderRectangle.Width / 100 * MovePercentage * -1, 0))) - using (var translatedPaint = new SKPaint {Shader = translated, FilterQuality = SKFilterQuality.Low}) - { - // Here we can let each module modify the shader as needed - canvas.DrawRect(device.RenderRectangle, translatedPaint); - } - } - } - } - public override IEnumerable GetViewModels() { return new List {new GeneralViewModel(this)}; diff --git a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj new file mode 100644 index 000000000..e27d3449d --- /dev/null +++ b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj @@ -0,0 +1,127 @@ + + + + + Debug + AnyCPU + {ADB357E6-151D-4D0D-87CB-68FD0BC29812} + library + Artemis.UI.Shared + Artemis.UI.Shared + v4.7.2 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\MaterialDesignColors.1.2.0\lib\net45\MaterialDesignColors.dll + + + ..\packages\MaterialDesignThemes.2.6.0\lib\net45\MaterialDesignThemes.Wpf.dll + + + ..\packages\SkiaSharp.1.68.1\lib\net45\SkiaSharp.dll + + + + ..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll + + + + ..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll + + + + ..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + + + + + + + + 4.0 + + + + + + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + ColorPicker.xaml + + + + + + UserControl1.xaml + Code + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Controls/ColorPicker.xaml b/src/Artemis.UI.Shared/ColorPicker.xaml similarity index 62% rename from src/Artemis.UI/Controls/ColorPicker.xaml rename to src/Artemis.UI.Shared/ColorPicker.xaml index 13fe03f15..05e8a582a 100644 --- a/src/Artemis.UI/Controls/ColorPicker.xaml +++ b/src/Artemis.UI.Shared/ColorPicker.xaml @@ -1,19 +1,23 @@ - + + - + + + - + @@ -22,10 +26,10 @@ - - - - + + + + @@ -42,18 +46,13 @@ - - + + - + @@ -78,7 +77,8 @@ OverridesDefaultStyle="True" Template="{StaticResource MaterialDesignColorSliderThumb}"> - + @@ -88,47 +88,46 @@ - + + Text="{Binding Color, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource ColorToStringConverter}}" + MinWidth="95" + Padding="0 0 10 0" + HorizontalAlignment="Stretch" /> - + - + - - + IsOpen="{Binding PopupOpen, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"> + - + + Value="{Binding ColorOpacity, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" + Maximum="255" /> - + - + \ No newline at end of file diff --git a/src/Artemis.UI.Shared/ColorPicker.xaml.cs b/src/Artemis.UI.Shared/ColorPicker.xaml.cs new file mode 100644 index 000000000..a0e6e3a35 --- /dev/null +++ b/src/Artemis.UI.Shared/ColorPicker.xaml.cs @@ -0,0 +1,119 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Media; + +namespace Artemis.UI.Shared +{ + /// + /// Interaction logic for ColorPicker.xaml + /// + public partial class ColorPicker : UserControl, INotifyPropertyChanged + { + public static readonly DependencyProperty ColorProperty = DependencyProperty.Register(nameof(Color), typeof(Color), typeof(ColorPicker), + new FrameworkPropertyMetadata(default(Color), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, ColorPropertyChangedCallback)); + + public static readonly DependencyProperty PopupOpenProperty = DependencyProperty.Register(nameof(PopupOpen), typeof(bool), typeof(ColorPicker), + new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, PopupOpenPropertyChangedCallback)); + + + internal static readonly DependencyProperty ColorOpacityProperty = DependencyProperty.Register(nameof(ColorOpacity), typeof(byte), typeof(ColorPicker), + new FrameworkPropertyMetadata((byte) 255, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, ColorOpacityPropertyChangedCallback)); + + public static readonly RoutedEvent ColorChangedEvent = + EventManager.RegisterRoutedEvent( + nameof(Color), + RoutingStrategy.Bubble, + typeof(RoutedPropertyChangedEventHandler), + typeof(ColorPicker)); + + public static readonly RoutedEvent PopupOpenChangedEvent = + EventManager.RegisterRoutedEvent( + nameof(PopupOpen), + RoutingStrategy.Bubble, + typeof(RoutedPropertyChangedEventHandler), + typeof(ColorPicker)); + + private bool _inCallback; + + public ColorPicker() + { + InitializeComponent(); + } + + public Color Color + { + get => (Color) GetValue(ColorProperty); + set => SetValue(ColorProperty, value); + } + + public bool PopupOpen + { + get => (bool) GetValue(PopupOpenProperty); + set => SetValue(PopupOpenProperty, value); + } + + internal byte ColorOpacity + { + get => (byte) GetValue(ColorOpacityProperty); + set => SetValue(ColorOpacityProperty, value); + } + + private static void ColorPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var colorPicker = (ColorPicker) d; + if (colorPicker._inCallback) + return; + + colorPicker._inCallback = true; + + colorPicker.SetCurrentValue(ColorOpacityProperty, ((Color) e.NewValue).A); + colorPicker.OnPropertyChanged(nameof(Color)); + + colorPicker._inCallback = false; + } + + private static void PopupOpenPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var colorPicker = (ColorPicker) d; + if (colorPicker._inCallback) + return; + + colorPicker._inCallback = true; + colorPicker.OnPropertyChanged(nameof(PopupOpen)); + colorPicker._inCallback = false; + } + + private static void ColorOpacityPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var colorPicker = (ColorPicker) d; + if (colorPicker._inCallback) + return; + + colorPicker._inCallback = true; + + var color = colorPicker.Color; + if (e.NewValue is byte opacity) + color = Color.FromArgb(opacity, color.R, color.G, color.B); + colorPicker.SetCurrentValue(ColorProperty, color); + colorPicker.OnPropertyChanged(nameof(ColorOpacity)); + + colorPicker._inCallback = false; + } + + private void UIElement_OnMouseUp(object sender, MouseButtonEventArgs e) + { + PopupOpen = !PopupOpen; + } + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Converters/ColorToSKColorConverter.cs b/src/Artemis.UI.Shared/Converters/ColorToSKColorConverter.cs new file mode 100644 index 000000000..372ed8fa4 --- /dev/null +++ b/src/Artemis.UI.Shared/Converters/ColorToSKColorConverter.cs @@ -0,0 +1,28 @@ +using System; +using System.Globalization; +using System.Windows.Data; +using System.Windows.Media; +using SkiaSharp; + +namespace Artemis.UI.Shared.Converters +{ + /// + /// + /// Converts into a . + /// + [ValueConversion(typeof(Color), typeof(SKColor))] + public class SKColorToColorConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var skColor = (SKColor) value; + return Color.FromArgb(skColor.Alpha, skColor.Red, skColor.Green, skColor.Blue); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + var color = (Color) value; + return new SKColor(color.R, color.G, color.B, color.A); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Converters/ColorToSolidColorConverter.cs b/src/Artemis.UI.Shared/Converters/ColorToSolidColorConverter.cs new file mode 100644 index 000000000..570412502 --- /dev/null +++ b/src/Artemis.UI.Shared/Converters/ColorToSolidColorConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Windows.Data; +using System.Windows.Media; + +namespace Artemis.UI.Shared.Converters +{ + /// + /// + /// Converts into a with full opacity. + /// + [ValueConversion(typeof(Color), typeof(string))] + internal class ColorToSolidColorConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var color = (Color) value; + return Color.FromRgb(color.R, color.G, color.B); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Converters/ColorToStringConverter.cs b/src/Artemis.UI.Shared/Converters/ColorToStringConverter.cs new file mode 100644 index 000000000..e01ac78a3 --- /dev/null +++ b/src/Artemis.UI.Shared/Converters/ColorToStringConverter.cs @@ -0,0 +1,39 @@ +using System; +using System.Globalization; +using System.Windows.Data; +using System.Windows.Media; + +namespace Artemis.UI.Shared.Converters +{ + /// + /// + /// Converts into . + /// + [ValueConversion(typeof(Color), typeof(string))] + internal class ColorToStringConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return value?.ToString(); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + try + { + if (string.IsNullOrWhiteSpace((string) value)) + return default(Color); + + var color = ColorConverter.ConvertFromString((string) value); + if (color is Color c) + return c; + + return default(Color); + } + catch (FormatException) + { + return default(Color); + } + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Properties/AssemblyInfo.cs b/src/Artemis.UI.Shared/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..1f6408856 --- /dev/null +++ b/src/Artemis.UI.Shared/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// 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.UI.Shared")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("HP Inc.")] +[assembly: AssemblyProduct("Artemis.UI.Shared")] +[assembly: AssemblyCopyright("Copyright © HP Inc. 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly:ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Artemis.UI.Shared/Properties/Resources.Designer.cs b/src/Artemis.UI.Shared/Properties/Resources.Designer.cs new file mode 100644 index 000000000..f931adadc --- /dev/null +++ b/src/Artemis.UI.Shared/Properties/Resources.Designer.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Artemis.UI.Shared.Properties { + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if ((resourceMan == null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Artemis.UI.Shared.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/src/Artemis.UI.Shared/Properties/Resources.resx b/src/Artemis.UI.Shared/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/src/Artemis.UI.Shared/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Properties/Settings.Designer.cs b/src/Artemis.UI.Shared/Properties/Settings.Designer.cs new file mode 100644 index 000000000..d2346eb37 --- /dev/null +++ b/src/Artemis.UI.Shared/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Artemis.UI.Shared.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/src/Artemis.UI.Shared/Properties/Settings.settings b/src/Artemis.UI.Shared/Properties/Settings.settings new file mode 100644 index 000000000..033d7a5e9 --- /dev/null +++ b/src/Artemis.UI.Shared/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI.Shared/UserControl1.xaml b/src/Artemis.UI.Shared/UserControl1.xaml new file mode 100644 index 000000000..1bb466275 --- /dev/null +++ b/src/Artemis.UI.Shared/UserControl1.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/src/Artemis.UI.Shared/UserControl1.xaml.cs b/src/Artemis.UI.Shared/UserControl1.xaml.cs new file mode 100644 index 000000000..ee4b9f7db --- /dev/null +++ b/src/Artemis.UI.Shared/UserControl1.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.Shared +{ + /// + /// Interaction logic for UserControl1.xaml + /// + public partial class UserControl1 : UserControl + { + public UserControl1() + { + InitializeComponent(); + } + } +} diff --git a/src/Artemis.UI.Shared/packages.config b/src/Artemis.UI.Shared/packages.config new file mode 100644 index 000000000..2c6820adf --- /dev/null +++ b/src/Artemis.UI.Shared/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index 67e4c9841..2cbb9f949 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -171,9 +171,6 @@ Designer - - ColorPicker.xaml - @@ -250,10 +247,6 @@ Code - - Designer - MSBuild:Compile - Designer MSBuild:Compile @@ -409,6 +402,10 @@ {9b811f9b-86b9-4771-87af-72bae7078a36} Artemis.Core + + {adb357e6-151d-4d0d-87cb-68fd0bc29812} + Artemis.UI.Shared + diff --git a/src/Artemis.UI/Controls/ColorPicker.xaml.cs b/src/Artemis.UI/Controls/ColorPicker.xaml.cs deleted file mode 100644 index eea2f5cb1..000000000 --- a/src/Artemis.UI/Controls/ColorPicker.xaml.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using System.ComponentModel; -using System.Runtime.CompilerServices; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Media; - -namespace Artemis.UI.Controls -{ - /// - /// Interaction logic for ColorPicker.xaml - /// - public partial class ColorPicker : UserControl, INotifyPropertyChanged - { - public static readonly DependencyProperty ColorProperty = DependencyProperty.Register( - "Color", - typeof(Color), - typeof(ColorPicker), - new FrameworkPropertyMetadata(default(Color), OnColorPropertyChanged) - ); - - private byte _colorOpacity; - - private static void OnColorPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) - { - if (sender is ColorPicker colorPicker) - { - colorPicker.OnPropertyChanged(nameof(Color)); - colorPicker.OnPropertyChanged(nameof(ColorCode)); - colorPicker.OnPropertyChanged(nameof(SolidColor)); - colorPicker.OnPropertyChanged(nameof(ColorOpacity)); - } - } - - public ColorPicker() - { - InitializeComponent(); - PropertyChanged += OnPropertyChanged; - } - - private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(Color)) - { - if (Color.A != _colorOpacity) - Color = Color.FromArgb(_colorOpacity, Color.R, Color.G, Color.B); - } - } - - public Color Color - { - get => (Color) GetValue(ColorProperty); - set => SetValue(ColorProperty, value); - } - - public string ColorCode - { - get => Color.ToString(); - set - { - try - { - if (string.IsNullOrWhiteSpace(value)) - Color = new Color(); - else - { - var color = ColorConverter.ConvertFromString(value); - if (color is Color c) - { - _colorOpacity = c.A; - Color = c; - } - } - } - catch (FormatException) - { - // ignored - } - } - } - - public Color? SolidColor => Color.FromRgb(Color.R, Color.G, Color.B); - - public byte ColorOpacity - { - get => _colorOpacity; - set - { - _colorOpacity = value; - if (Color.A != _colorOpacity) - { - Color = Color.FromArgb(_colorOpacity, Color.R, Color.G, Color.B); - OnPropertyChanged(nameof(Color)); - } - } - } - - public bool PopupOpen { get; set; } - - private void UIElement_OnMouseUp(object sender, MouseButtonEventArgs e) - { - PopupOpen = !PopupOpen; - } - - #region Events - - public event PropertyChangedEventHandler PropertyChanged; - - protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - - #endregion - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Workshop/WorkshopView.xaml b/src/Artemis.UI/Screens/Workshop/WorkshopView.xaml index c7d9f6c9b..6251da775 100644 --- a/src/Artemis.UI/Screens/Workshop/WorkshopView.xaml +++ b/src/Artemis.UI/Screens/Workshop/WorkshopView.xaml @@ -5,11 +5,25 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Artemis.UI.Screens.Workshop" xmlns:s="https://github.com/canton7/Stylet" - xmlns:controls="clr-namespace:Artemis.UI.Controls" + xmlns:controls="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> - - - - + + + + + + + + + + Test + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Workshop/WorkshopViewModel.cs b/src/Artemis.UI/Screens/Workshop/WorkshopViewModel.cs index 3b3b267a1..64ea22105 100644 --- a/src/Artemis.UI/Screens/Workshop/WorkshopViewModel.cs +++ b/src/Artemis.UI/Screens/Workshop/WorkshopViewModel.cs @@ -1,38 +1,18 @@ -using System; -using System.ComponentModel; -using System.Windows.Media; +using System.Windows.Media; using Stylet; namespace Artemis.UI.Screens.Workshop { public class WorkshopViewModel : Screen, IScreenViewModel { + public Color TestColor { get; set; } + public bool TestPopupOpen { get; set; } public string Title => "Workshop"; - public WorkshopViewModel() + public void UpdateValues() { - PropertyChanged += OnPropertyChanged; - } - - private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) - { - Console.WriteLine("Property changed:" + e.PropertyName); - Console.WriteLine(TestColor); - } - - public Color TestColor { get; set; } - - - protected override void OnActivate() - { - TestColor = Color.FromRgb(255, 0, 0); - base.OnActivate(); - } - - protected override void OnDeactivate() - { - Console.WriteLine(TestColor); - base.OnDeactivate(); + TestPopupOpen = !TestPopupOpen; + TestColor = Color.FromRgb(5, 174, 255); } } } \ No newline at end of file diff --git a/src/Artemis.sln b/src/Artemis.sln index ddd50d604..4b9e686f8 100644 --- a/src/Artemis.sln +++ b/src/Artemis.sln @@ -31,6 +31,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.Plugins.LayerElemen EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.Plugins.LayerElements.Noise", "Artemis.Plugins.LayerElements.Noise\Artemis.Plugins.LayerElements.Noise.csproj", "{7F4C7AB0-4C9B-452D-AFED-34544C903DEF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.UI.Shared", "Artemis.UI.Shared\Artemis.UI.Shared.csproj", "{ADB357E6-151D-4D0D-87CB-68FD0BC29812}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -111,6 +113,14 @@ Global {7F4C7AB0-4C9B-452D-AFED-34544C903DEF}.Release|Any CPU.Build.0 = Release|Any CPU {7F4C7AB0-4C9B-452D-AFED-34544C903DEF}.Release|x64.ActiveCfg = Release|Any CPU {7F4C7AB0-4C9B-452D-AFED-34544C903DEF}.Release|x64.Build.0 = Release|Any CPU + {ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Debug|x64.ActiveCfg = Debug|Any CPU + {ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Debug|x64.Build.0 = Debug|Any CPU + {ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Release|Any CPU.Build.0 = Release|Any CPU + {ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Release|x64.ActiveCfg = Release|Any CPU + {ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE