An inline UI editor for colours in the editor. It draws a color swatch over a checkerboard, shows "HDR" for values >1, and opens the editor color picker when clicked, committing the selected color back to the plug.
using Editor.Prism.Core;
using Editor.Prism.Serialization;
using Editor.Prism.Ui.Adapters;
namespace Editor.Prism.Ui.InlineEditors;
/// <summary>
/// A colour swatch over a transparency checkerboard, opening the editor's colour picker on click.
/// <para>
/// The checkerboard is not decoration: a colour with alpha 0.1 and a colour that is simply very dark
/// are indistinguishable on a flat dark card, and shader authors set both all the time.
/// </para>
/// </summary>
public sealed class ColorInlineEditor : PrismInlineEditor
{
/// <summary>Bind a colour editor to a port.</summary>
public ColorInlineEditor( Plug plug, PrismPlugIn port ) : base( plug, port ) { }
/// <inheritdoc/>
protected override float PillHeight => 16f;
/// <summary>The current colour.</summary>
public Color Current
{
get
{
if ( Value is Color color ) return color;
var components = ValueCodec.ToFloats( Value );
if ( components is null || components.Length == 0 ) return Color.White;
return new Color(
components.Length > 0 ? components[0] : 0f,
components.Length > 1 ? components[1] : 0f,
components.Length > 2 ? components[2] : 0f,
components.Length > 3 ? components[3] : 1f );
}
}
/// <inheritdoc/>
protected override float MeasureWidth() => 46f;
/// <inheritdoc/>
protected override void OnPaintPill( Rect pill )
{
var hovered = Paint.HasMouseOver;
PrismPaint.Swatch( pill, Current,
hovered ? PrismTheme.BorderStrong.Lighten( 0.2f ) : PrismTheme.BorderSubtle );
// A colour whose channels leave the zero-to-one range is an HDR value, and that is worth saying.
var color = Current;
var hdr = color.r > 1.001f || color.g > 1.001f || color.b > 1.001f;
if ( !hdr ) return;
PrismPaint.Text( pill.Shrink( 3f, 0f ), "HDR", PrismTheme.TextOnAccent, 9, 700, TextFlag.RightCenter );
}
/// <inheritdoc/>
protected override void OnMousePressed( GraphicsMouseEvent e )
{
if ( !ShouldDraw || !e.LeftMouseButton ) return;
if ( !PillRect.Grow( 3f ).IsInside( e.LocalPosition ) ) return;
e.Accepted = true;
PrismLog.Guard( "Open colour picker", () =>
{
var view = Plug?.Node?.GraphicsView;
var pill = PillRect;
var screen = view is null
? Application.CursorPosition
: view.ToScreen( view.FromScene( ToScene( new Vector2( pill.Left, pill.Bottom + 4f ) ) ) );
ColorPicker.OpenColorPopup( Current, OnPicked, screen );
} );
}
void OnPicked( Color color ) => Commit( Shape( color ) );
}