Updated Color Picker [Code]
I gave the color picker example a try. (viewtopic.php?f=12&t=187&p=996&hilit=color+picker#p996) It looks like the Noesis API has changed quite a bit since the example was initially created. I ran into compiler errors.
Here is an updated version which works with Noesis 2.2.x. I added a ColorChanged event for real-time color changes.
ColorPickerControl.xaml
ColorPicker.cs
Here is an updated version which works with Noesis 2.2.x. I added a ColorChanged event for real-time color changes.
ColorPickerControl.xaml
Code: Select all
<UserControl
x:Class="Example.ColorPickerControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
UseLayoutRounding="True">
<UserControl.Resources>
<Style x:Key="SpectrumSliderButtonStyle" TargetType="{x:Type RepeatButton}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="UseLayoutRounding" Value="True"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="ClickMode" Value="Press"/>
<Setter Property="Delay" Value="250"/>
<Setter Property="Interval" Value="100"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border Background="Transparent" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="SpectrumSliderThumbTemplate" TargetType="{x:Type Thumb}">
<Grid Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="32"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Path Grid.Column="0" Data="M0,0 L16,10 0,20 z" Fill="White" HorizontalAlignment="Right" Margin="0, 0, 0, -5"/>
<Path Grid.Column="2" Data="M16,0 L0,10 16,20 z" Fill="White" HorizontalAlignment="Left" Margin="0, 0, 0, -5"/>
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="SpectrumSliderTemplate" TargetType="{x:Type Slider}">
<Grid>
<Rectangle StrokeThickness="1" Stroke="#000000" Width="32">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="#FFFF0000" Offset="0"/>
<GradientStop Color="#FFFF00FF" Offset="0.1666666"/>
<GradientStop Color="#FF0000FF" Offset="0.3333333"/>
<GradientStop Color="#FF00FFFF" Offset="0.5"/>
<GradientStop Color="#FF00FF00" Offset="0.6666666"/>
<GradientStop Color="#FFFFFF00" Offset="0.8333333"/>
<GradientStop Color="#FFFF0000" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Track x:Name="PART_Track">
<Track.Thumb>
<Thumb Template="{StaticResource SpectrumSliderThumbTemplate}" Margin="0,-4"/>
</Track.Thumb>
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource SpectrumSliderButtonStyle}" Command="Slider.DecreaseLarge" />
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource SpectrumSliderButtonStyle}" Command="Slider.IncreaseLarge" />
</Track.IncreaseRepeatButton>
</Track>
</Grid>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- Color selected -->
<Grid Grid.Row="0" Grid.ColumnSpan="2">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0">
<Rectangle Width="50" Height="50" Margin="10" StrokeThickness="1" Stroke="#000000">
<Rectangle.Fill>
<SolidColorBrush x:Name="Color" Color="#FF0000"/>
</Rectangle.Fill>
</Rectangle>
<TextBlock x:Name="Text" FontSize="30" Margin="15, 0, 0, 0" VerticalAlignment="Center" Text="Text" Foreground="White"/>
</StackPanel>
</Grid>
<!-- Picker -->
<Grid x:Name="HS" Grid.Row="1" Grid.Column="0">
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
<GradientStop Color="White" Offset="0"/>
<GradientStop x:Name="Stop" Color="Red" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle StrokeThickness="1" Stroke="#000000" Height="512" Width="512">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="1,0" EndPoint="0,0">
<GradientStop Offset="0" Color="#00000000"/>
<GradientStop Offset="1" Color="#FF000000"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Canvas Height="24" Width="24" RenderTransformOrigin="0.5,0.5" ClipToBounds="true">
<Canvas.RenderTransform>
<TranslateTransform x:Name="PickerTransform" X="0" Y="0"/>
</Canvas.RenderTransform>
<Grid>
<Ellipse Stroke="Black" Width="24" Height="24"/>
<Ellipse Stroke="White" Width="20" Height="20"/>
</Grid>
</Canvas>
</Grid>
<!-- Spectrum -->
<Grid Grid.Row="1" Grid.Column="1">
<Slider x:Name="Slider" Orientation="Vertical" IsMoveToPointEnabled="True" Minimum="0" Maximum="360" Value="0" Template="{StaticResource SpectrumSliderTemplate}" Margin="10, 0, 0, 0"/>
</Grid>
</Grid>
</UserControl>
Code: Select all
using Noesis;
using System;
using NoesisEventArgs = Noesis.EventArgs;
namespace Example
{
public class ColorPickerControl : UserControl
{
public static readonly DependencyProperty ColorBrushProperty = DependencyProperty.Register("ColorBrush",
typeof(SolidColorBrush), typeof(ColorPickerControl), new PropertyMetadata(null));
public event EventHandler<ColorEventArgs> ColorChanged;
private FrameworkElement _Root;
private Slider _Spectrum;
private Grid _HsGrid;
private TranslateTransform _PickerTransform;
private TextBlock _Text;
private SolidColorBrush _Color;
private GradientStop _Stop;
private float _Hue;
private float _Saturation;
private float _Value;
public ColorPickerControl()
{
Name = "ColorPickerControl";
InitializeComponent();
}
protected void InitializeComponent()
{
GUI.LoadComponent(this, "Assets/User Interface/Controls/Color Picker Control/ColorPickerControl.xaml");
_Root = this.Content as FrameworkElement;
_Spectrum = _Root.FindName("Slider") as Slider;
_HsGrid = _Root.FindName("HS") as Grid;
_PickerTransform = _Root.FindName("PickerTransform") as TranslateTransform;
_Text = _Root.FindName("Text") as TextBlock;
_Color = _Root.FindName("Color") as SolidColorBrush;
_Stop = _Root.FindName("Stop") as GradientStop;
_Spectrum.ValueChanged += this.OnSpectrumChange;
_HsGrid.MouseLeftButtonDown += this.OnMouseLeftButtonDown;
_HsGrid.MouseLeftButtonUp += this.OnMouseLeftButtonUp;
_HsGrid.MouseMove += this.OnMouseMove;
_HsGrid.SizeChanged += this.OnSizeChanged;
_Hue = 0.0f;
_Saturation = 0.5f;
_Value = 0.5f;
Update();
}
public SolidColorBrush ColorBrush
{
get { return (SolidColorBrush)GetValue(ColorBrushProperty); }
set { SetValue(ColorBrushProperty, value); }
}
private void OnSpectrumChange(object sender, RoutedPropertyChangedEventArgs<float> e)
{
_Hue = e.NewValue;
_Stop.Color = HSVToColor(_Hue, 1, 1);
Update();
}
private void OnMouseLeftButtonDown(Object sender, MouseButtonEventArgs args)
{
Focus();
_HsGrid.CaptureMouse();
Point point = _HsGrid.PointFromScreen(args.GetPosition(null));
UpdatePickerPosition(point);
}
private void OnMouseLeftButtonUp(Object sender, MouseButtonEventArgs args)
{
_HsGrid.ReleaseMouseCapture();
}
private void OnMouseMove(object sender, MouseEventArgs args)
{
if (_HsGrid.IsMouseCaptured)
{
Point point = _HsGrid.PointFromScreen(args.GetPosition(null));
UpdatePickerPosition(point);
}
}
private void OnSizeChanged(object sender, SizeChangedEventArgs args)
{
Size size = args.NewSize;
_PickerTransform.X = _Value * size.Width - 0.5f * size.Width;
_PickerTransform.Y = size.Height - _Saturation * size.Height - 0.5f * size.Height;
}
private void UpdatePickerPosition(Point pos)
{
Size size = _HsGrid.RenderSize;
pos.X = Math.Max(0.0f, Math.Min(size.Width, pos.X));
pos.Y = Math.Max(0.0f, Math.Min(size.Height, pos.Y));
_PickerTransform.X = pos.X - 0.5f * size.Width;
_PickerTransform.Y = pos.Y - 0.5f * size.Height;
_Value = pos.X / size.Width;
_Saturation = (size.Height - pos.Y) / size.Height;
Update();
}
private void Update()
{
Color color = HSVToColor(_Hue, _Saturation, _Value);
int red = color.R;
int green = color.G;
int blue = color.B;
_Text.Text = string.Format("#{0:X2}{1:X2}{2:X2}", red, green, blue);
_Color.Color = color;
ColorBrush = new SolidColorBrush(color);
ColorChanged?.Invoke(this, new ColorEventArgs(color));
}
private Color HSVToColor(float hue, float saturation, float value)
{
float chroma = value * saturation;
float hueTag = (hue % 360) / 60;
float x = chroma * (1 - Math.Abs(hueTag % 2.0f - 1));
float m = value - chroma;
switch ((int)hueTag)
{
case 0:
return Color.FromScRgb(1, chroma + m, x + m, m);
case 1:
return Color.FromScRgb(1, x + m, chroma + m, m);
case 2:
return Color.FromScRgb(1, m, chroma + m, x + m);
case 3:
return Color.FromScRgb(1, m, x + m, chroma + m);
case 4:
return Color.FromScRgb(1, x + m, m, chroma + m);
default:
return Color.FromScRgb(1, chroma + m, m, x + m);
}
}
}
public class ColorEventArgs : NoesisEventArgs
{
public new Color Empty { get; protected set; }
public Color Color { get; protected set; }
public ColorEventArgs(Color color)
{
Color = color;
}
}
}
Last edited by stonstad on 03 Aug 2020, 17:55, edited 1 time in total.
Re: Updated Color Picker
Related... here is logic I use to convert between Unity, Noesis, and integer representations of color.
Shaun
Stellar Conquest (https://twitter.com/stellarconquest)
Shaun
Stellar Conquest (https://twitter.com/stellarconquest)
Code: Select all
using NoesisColor = Noesis.Color;
using UnityColor = UnityEngine.Color;
using UnityColor32 = UnityEngine.Color32;
using UnityTexture2D = UnityEngine.Texture2D;
namespace Example
{
public class ColorConversionUtility
{
public static UnityColor NoesisColorToUnityColor(NoesisColor color)
{
return new UnityColor(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, color.A / 255.0f);
}
public static NoesisColor UnityColorToNoesisColor(UnityColor color)
{
return NoesisColor.FromArgb((byte)(color.a * 255), (byte)(color.r * 255), (byte)(color.g * 255), (byte)(color.b * 255));
}
public static int NoesisColorToInt(NoesisColor color)
{
return ARGBColorToInt(color.A, color.R, color.G, color.B);
}
public static NoesisColor IntToNoesisColor(int argb32)
{
const int mask = 0x000000FF;
byte a, r, g, b;
a = (byte)((argb32 >> 24) & mask);
r = (byte)((argb32 >> 16) & mask);
g = (byte)((argb32 >> 8) & mask);
b = (byte)(argb32 & mask);
return new NoesisColor() { A = a, R = r, G = g, B = b };
}
public static UnityColor IntToUnityColor(int argb32)
{
const int mask = 0x000000FF;
byte a, r, g, b;
a = (byte)((argb32 >> 24) & mask);
r = (byte)((argb32 >> 16) & mask);
g = (byte)((argb32 >> 8) & mask);
b = (byte)(argb32 & mask);
return new UnityColor(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
}
public static byte[] IntToColorBytes(int argb32)
{
const int mask = 0x000000FF;
byte a, r, g, b;
a = (byte)((argb32 >> 24) & mask);
r = (byte)((argb32 >> 16) & mask);
g = (byte)((argb32 >> 8) & mask);
b = (byte)(argb32 & mask);
return new byte[] { a, r, g, b };
}
private static int ARGBColorToInt(byte a, byte r, byte g, byte b)
{
int argb32 = a << 24 | r << 16 | g << 8 | b;
return argb32;
}
public static void ConvertToPremultipliedAlpha(UnityTexture2D source)
{
UnityColor[] colors = source.GetPixels();
for (int i = 0; i < colors.Length; i++)
{
UnityColor color = colors[i];
colors[i] = new UnityColor(color.r * color.a, color.g * color.a, color.b * color.a, color.a);
}
source.SetPixels(colors);
source.Apply();
}
public static void ConvertToPremultipliedAlpha(UnityColor[] colors)
{
for (int i = 0; i < colors.Length; i++)
{
UnityColor color = colors[i];
colors[i] = new UnityColor(color.r * color.a, color.g * color.a, color.b * color.a, color.a);
}
}
public static UnityColor32 GetAverageColor(UnityTexture2D texture)
{
UnityColor32[] texColors = texture.GetPixels32();
int n = texColors.Length;
float r = 0;
float g = 0;
float b = 0;
for (int i = 0; i < n; i++)
{
r += texColors[i].r;
g += texColors[i].g;
b += texColors[i].b;
}
return new UnityColor32((byte)(r / n), (byte)(g / n), (byte)(b / n), 0);
}
}
}
Re: Updated Color Picker
Thanks a lot for this great contribution!
- Strela_999
- Posts: 3
- Joined:
Re: Updated Color Picker
Awesome, it really makes my life easier! I already liked the way to choose colors in the base program, but this makes it even better.
Who is online
Users browsing this forum: No registered users and 4 guests