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

Added shared UI library and finished the ColorPicker

This commit is contained in:
Robert 2019-12-09 19:25:45 +01:00
parent 515348241a
commit cec6fb45dc
30 changed files with 875 additions and 321 deletions

View File

@ -164,6 +164,7 @@
<Compile Include="Extensions\RgbDeviceExtensions.cs" />
<Compile Include="Extensions\RgbRectangleExtensions.cs" />
<Compile Include="Extensions\TypeExtensions.cs" />
<Compile Include="JsonConverters\SKColorConverter.cs" />
<Compile Include="Models\DataModelDescription.cs" />
<Compile Include="Models\Surface\ArtemisLed.cs" />
<Compile Include="Models\Surface\ArtemisSurface.cs" />

View File

@ -0,0 +1,24 @@
using System;
using Newtonsoft.Json;
using SkiaSharp;
namespace Artemis.Core.JsonConverters
{
public class SKColorConverter : JsonConverter<SKColor>
{
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;
}
}
}

View File

@ -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<Module>();
_pluginService.PluginDisabled += (sender, args) => _modules = _pluginService.GetPluginsOfType<Module>();
ConfigureJsonConvert();
Task.Run(Initialize);
}
private void ConfigureJsonConvert()
{
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new SKColorConverter() }
};
}
public void Dispose()
{
// Dispose services

View File

@ -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,8 +45,20 @@ namespace Artemis.Core.Services
$"Settings where provided but layer element of type {layerElementDescriptor.LayerElementType.Name} has no Settings property."
);
}
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)
{

View File

@ -100,6 +100,10 @@
<Name>Artemis.Core</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj">
<Project>{adb357e6-151d-4d0d-87cb-68fd0bc29812}</Project>
<Name>Artemis.UI.Shared</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />

View File

@ -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);
}

View File

@ -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);
}
}
}

View File

@ -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}}">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Teal.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Teal.xaml" />
</ResourceDictionary.MergedDictionaries>
<converters:SKColorToColorConverter x:Key="SKColorToColorConverter" />
</ResourceDictionary>
</UserControl.Resources>
@ -29,6 +28,24 @@
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}" Text="Noise color" />
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<artemis:ColorPicker Color="{Binding LayerElement.Settings.Color, Converter={StaticResource SKColorToColorConverter}}" Width="100" />
</StackPanel>
<Separator Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Style="{StaticResource MaterialDesignSeparator}" />
</Grid>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition />
@ -38,17 +55,21 @@
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}">Blend mode</TextBlock>
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}" Foreground="{DynamicResource MaterialDesignCheckBoxDisabled}">Affects how the noise is rendered on the rest of the layer</TextBlock>
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}">
<Run Text="Blend mode" />
</TextBlock>
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}" Foreground="{DynamicResource MaterialDesignCheckBoxDisabled}">
<Run Text="Affects how the noise is rendered on the rest of the layer" />
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<ComboBox HorizontalAlignment="Left"
ItemsSource="{Binding Path=BlendModes}"
ItemsSource="{Binding BlendModes}"
SelectedValuePath="Value"
DisplayMemberPath="Description"
Width="100"
SelectedValue="{Binding Path=LayerElement.Settings.BlendMode}" />
SelectedValue="{Binding LayerElement.Settings.BlendMode}" />
</StackPanel>
<Separator Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Style="{StaticResource MaterialDesignSeparator}" />
</Grid>
@ -62,8 +83,10 @@
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}">X Scale</TextBlock>
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}">
<Run Text="X Scale" />
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<Slider Orientation="Horizontal" TickFrequency="0.5" Minimum="0.5" Maximum="40" Value="{Binding LayerElement.Settings.XScale}" Width="100" />
@ -81,8 +104,10 @@
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}">Y Scale</TextBlock>
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}">
<Run Text="Y Scale" />
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<Slider Orientation="Horizontal" TickFrequency="0.5" Minimum="0.5" Maximum="40" Value="{Binding LayerElement.Settings.YScale}" Width="100" />
@ -100,10 +125,13 @@
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}">Animation speed</TextBlock>
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}">
<Run Text="Animation speed" />
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<Slider Orientation="Horizontal" TickFrequency="1" Minimum="1" Maximum="100" Value="{Binding LayerElement.Settings.AnimationSpeed}" Width="100" />
</StackPanel>
<Separator Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Style="{StaticResource MaterialDesignSeparator}" />

View File

@ -82,7 +82,6 @@
<ItemGroup>
<Compile Include="GeneralDataModel.cs" />
<Compile Include="GeneralModule.cs" />
<Compile Include="ColorHelpers.cs" />
<Compile Include="ViewModels\GeneralViewModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>

View File

@ -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);
}
}
}

View File

@ -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<ArtemisDevice, SKShader>();
RainbowColors = new List<SKColor>();
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<ArtemisDevice, SKShader> DeviceShaders { get; set; }
public List<SKColor> 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<ModuleViewModel> GetViewModels()
{
return new List<ModuleViewModel> {new GeneralViewModel(this)};

View File

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{ADB357E6-151D-4D0D-87CB-68FD0BC29812}</ProjectGuid>
<OutputType>library</OutputType>
<RootNamespace>Artemis.UI.Shared</RootNamespace>
<AssemblyName>Artemis.UI.Shared</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="MaterialDesignColors, Version=1.2.0.325, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MaterialDesignColors.1.2.0\lib\net45\MaterialDesignColors.dll</HintPath>
</Reference>
<Reference Include="MaterialDesignThemes.Wpf, Version=2.6.0.325, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MaterialDesignThemes.2.6.0\lib\net45\MaterialDesignThemes.Wpf.dll</HintPath>
</Reference>
<Reference Include="SkiaSharp, Version=1.68.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\SkiaSharp.1.68.1\lib\net45\SkiaSharp.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<Page Include="ColorPicker.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UserControl1.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="ColorPicker.xaml.cs">
<DependentUpon>ColorPicker.xaml</DependentUpon>
</Compile>
<Compile Include="Converters\ColorToSKColorConverter.cs" />
<Compile Include="Converters\ColorToSolidColorConverter.cs" />
<Compile Include="Converters\ColorToStringConverter.cs" />
<Compile Include="UserControl1.xaml.cs">
<DependentUpon>UserControl1.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\SkiaSharp.1.68.1\build\net45\SkiaSharp.targets" Condition="Exists('..\packages\SkiaSharp.1.68.1\build\net45\SkiaSharp.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>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}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\SkiaSharp.1.68.1\build\net45\SkiaSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SkiaSharp.1.68.1\build\net45\SkiaSharp.targets'))" />
</Target>
</Project>

View File

@ -1,19 +1,23 @@
<UserControl x:Class="Artemis.UI.Controls.ColorPicker"
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:wpf="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters" x:Class="Artemis.UI.Shared.ColorPicker"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
d:DesignHeight="101.848" d:DesignWidth="242.956">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.ColorPicker.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
</ResourceDictionary.MergedDictionaries>
<VisualBrush x:Key="Checkerboard" TileMode="Tile" Stretch="Uniform" ViewportUnits="Absolute">
<converters:ColorToStringConverter x:Key="ColorToStringConverter" />
<converters:ColorToSolidColorConverter x:Key="ColorToSolidColorConverter" />
<VisualBrush x:Key="Checkerboard" TileMode="Tile" Stretch="Uniform" ViewportUnits="Absolute" Viewport="0,0,10,10">
<VisualBrush.Visual>
<Grid Width="25" Height="25">
<Grid Width="10" Height="10">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
@ -22,10 +26,10 @@
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Rectangle Grid.Row="0" Grid.Column="0" Fill="White" />
<Rectangle Grid.Row="0" Grid.Column="1" />
<Rectangle Grid.Row="1" Grid.Column="0" />
<Rectangle Grid.Row="1" Grid.Column="1" Fill="White" />
<Rectangle Grid.Row="0" Grid.Column="0" Fill="Gray" />
<Rectangle Grid.Row="0" Grid.Column="1" Fill="White" />
<Rectangle Grid.Row="1" Grid.Column="0" Fill="White" />
<Rectangle Grid.Row="1" Grid.Column="1" Fill="Gray" />
</Grid>
</VisualBrush.Visual>
</VisualBrush>
@ -42,18 +46,13 @@
<RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border
Grid.Row="1"
Height="8"
CornerRadius="4"
Background="{StaticResource Checkerboard}">
<Border
Height="8"
CornerRadius="4">
<Border Grid.Row="1" Height="8" CornerRadius="4" Background="{StaticResource Checkerboard}">
<Border Height="8" CornerRadius="4">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Offset="0" Color="Transparent" />
<GradientStop Offset="1.0" Color="{Binding SolidColor}" />
<GradientStop Offset="1.0"
Color="{Binding Color, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource ColorToSolidColorConverter}}" />
</LinearGradientBrush>
</Border.Background>
</Border>
@ -78,7 +77,8 @@
OverridesDefaultStyle="True"
Template="{StaticResource MaterialDesignColorSliderThumb}">
<Thumb.Foreground>
<SolidColorBrush Color="{Binding SolidColor}" />
<SolidColorBrush
Color="{Binding Color, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Mode=OneWay, Converter={StaticResource ColorToSolidColorConverter}}" />
</Thumb.Foreground>
</Thumb>
</Track.Thumb>
@ -88,47 +88,46 @@
</ControlTemplate>
</ResourceDictionary>
</UserControl.Resources>
<StackPanel Orientation="Horizontal">
<Grid HorizontalAlignment="Stretch">
<TextBox x:Name="ColorCodeTextBox"
wpf:HintAssist.Hint="Noise color"
wpf:TextFieldAssist.TextBoxViewMargin="1 0 1 0"
materialDesign:TextFieldAssist.TextBoxViewMargin="1 0 1 0"
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
Text="{Binding ColorCode}"
Margin="0,0,-15,0"
Padding="0 0 18 0"
MinWidth="95" />
Text="{Binding Color, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource ColorToStringConverter}}"
MinWidth="95"
Padding="0 0 10 0"
HorizontalAlignment="Stretch" />
<Border Width="15" Height="15" CornerRadius="15" Margin="0,0,0,5" VerticalAlignment="Bottom" HorizontalAlignment="Right" Background="{StaticResource Checkerboard}">
<Ellipse Stroke="{StaticResource NormalBorderBrush}" Cursor="Hand" MouseUp="UIElement_OnMouseUp">
<Ellipse Stroke="{DynamicResource NormalBorderBrush}" Cursor="Hand" MouseUp="UIElement_OnMouseUp">
<Ellipse.Fill>
<SolidColorBrush Color="{Binding Color, Mode=OneWay}" />
<SolidColorBrush Color="{Binding Color, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Mode=OneWay}" />
</Ellipse.Fill>
</Ellipse>
</Border>
<Popup x:Name="ColorCodePopup"
AllowsTransparency="True"
<Popup AllowsTransparency="True"
Placement="Bottom"
CustomPopupPlacementCallback="{x:Static wpf:CustomPopupPlacementCallbackHelper.LargePopupCallback}"
CustomPopupPlacementCallback="{x:Static materialDesign:CustomPopupPlacementCallbackHelper.LargePopupCallback}"
PlacementTarget="{Binding ElementName=PART_TextBox}"
StaysOpen="False"
PopupAnimation="Fade"
IsOpen="{Binding PopupOpen}">
<wpf:Card Width="200" Height="200" Margin="0 5 0 0">
IsOpen="{Binding PopupOpen, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}">
<materialDesign:Card Width="200" Height="200" Margin="30" materialDesign:ShadowAssist.ShadowDepth="Depth4">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="160" />
<RowDefinition />
</Grid.RowDefinitions>
<wpf:ColorPicker Grid.Row="0" Color="{Binding Color, RelativeSource={RelativeSource AncestorType=UserControl}}" />
<materialDesign:ColorPicker Grid.Row="0" Color="{Binding Color, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
<Slider Grid.Row="1" Margin="8"
IsMoveToPointEnabled="True"
Orientation="Horizontal"
Style="{StaticResource MaterialDesignColorSlider}"
Template="{StaticResource MaterialDesignOpacitySlider}"
Value="{Binding ColorOpacity}" Maximum="255" />
Value="{Binding ColorOpacity, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
Maximum="255" />
</Grid>
</wpf:Card>
</materialDesign:Card>
</Popup>
</StackPanel>
</Grid>
</UserControl>

View File

@ -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
{
/// <summary>
/// Interaction logic for ColorPicker.xaml
/// </summary>
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<Color>),
typeof(ColorPicker));
public static readonly RoutedEvent PopupOpenChangedEvent =
EventManager.RegisterRoutedEvent(
nameof(PopupOpen),
RoutingStrategy.Bubble,
typeof(RoutedPropertyChangedEventHandler<bool>),
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));
}
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
using SkiaSharp;
namespace Artemis.UI.Shared.Converters
{
/// <inheritdoc />
/// <summary>
/// Converts <see cref="T:SkiaSharp.SKColor" /> into a <see cref="T:System.Windows.Media.Color" />.
/// </summary>
[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);
}
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
namespace Artemis.UI.Shared.Converters
{
/// <inheritdoc />
/// <summary>
/// Converts <see cref="T:System.Windows.Media.Color" /> into a <see cref="T:System.Windows.Media.Color" /> with full opacity.
/// </summary>
[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();
}
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
namespace Artemis.UI.Shared.Converters
{
/// <inheritdoc />
/// <summary>
/// Converts <see cref="T:System.Windows.Media.Color" /> into <see cref="T:System.String" />.
/// </summary>
[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);
}
}
}
}

View File

@ -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
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> 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")]

View File

@ -0,0 +1,62 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Artemis.UI.Shared.Properties {
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// 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() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[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;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
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;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@ -0,0 +1,12 @@
<UserControl x:Class="Artemis.UI.Shared.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Shared"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
</Grid>
</UserControl>

View File

@ -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
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MaterialDesignColors" version="1.2.0" targetFramework="net472" />
<package id="MaterialDesignThemes" version="2.6.0" targetFramework="net472" />
<package id="SkiaSharp" version="1.68.1" targetFramework="net472" />
<package id="System.Buffers" version="4.4.0" targetFramework="net472" />
<package id="System.Memory" version="4.5.3" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net472" />
</packages>

View File

@ -171,9 +171,6 @@
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Bootstrapper.cs" />
<Compile Include="Controls\ColorPicker.xaml.cs">
<DependentUpon>ColorPicker.xaml</DependentUpon>
</Compile>
<Compile Include="Converters\ColorToDrawingColorConverter.cs" />
<Compile Include="Converters\ColorToSolidColorBrushConverter.cs" />
<Compile Include="Converters\EnumToCollectionConverter.cs" />
@ -250,10 +247,6 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="Screens\Settings\SettingsViewModel.cs" />
<Page Include="Controls\ColorPicker.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="ResourceDictionaries\Scrollbar.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -409,6 +402,10 @@
<Project>{9b811f9b-86b9-4771-87af-72bae7078a36}</Project>
<Name>Artemis.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj">
<Project>{adb357e6-151d-4d0d-87cb-68fd0bc29812}</Project>
<Name>Artemis.UI.Shared</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\logo-512.png" />

View File

@ -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
{
/// <summary>
/// Interaction logic for ColorPicker.xaml
/// </summary>
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
}
}

View File

@ -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">
<Grid>
<TextBlock Text="{Binding TestColor}"></TextBlock>
<controls:ColorPicker Color="{Binding TestColor}" VerticalAlignment="Center" HorizontalAlignment="Center"></controls:ColorPicker>
</Grid>
<StackPanel>
<Rectangle Width="100" Height="100" HorizontalAlignment="Left">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding TestColor}" />
</Rectangle.Fill>
</Rectangle>
<TextBlock Text="{Binding TestColor}" />
<Button Command="{s:Action UpdateValues}" Style="{StaticResource MaterialDesignRaisedButton}"
HorizontalAlignment="Left" Margin="0 10">
Update values
</Button>
<CheckBox IsChecked="{Binding TestPopupOpen}">Test</CheckBox>
<controls:ColorPicker Color="{Binding TestColor, Mode=TwoWay}" PopupOpen="{Binding TestPopupOpen}" materialDesign:HintAssist.Hint="Custom hint" />
</StackPanel>
</UserControl>

View File

@ -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);
}
}
}

View File

@ -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