using System;
using UnityEngine;
using UnityEngine.UIElements;
///
/// class to handle the oklch colour picker ui
///
public class OklchColourPickerUI : MonoBehaviour
{
///
/// perceptual lightness value of the colour (0-100)
///
public double lightness;
///
/// chroma value of the colour (0-0.5)
///
public double chroma;
///
/// hue value of the colour (0-360)
///
public double hue;
///
/// slider for the chroma value
///
private Slider _chromaSlider;
///
/// slider for the hue value
///
private Slider _hueSlider;
///
/// slider for the lightness value
///
private Slider _lightnessSlider;
///
/// visual element for the response colour preview
///
private VisualElement _responseColour;
///
/// function to set the initial values of the sliders
///
private void Start()
{
_lightnessSlider.value = 74.61f;
_chromaSlider.value = 0.0868f;
_hueSlider.value = 335.72f;
}
///
/// function to subscribe slider events to their respective functions
///
public void OnEnable()
{
var ui = GetComponent().rootVisualElement;
_lightnessSlider = ui.Q("ResponseLightnessSlider");
_lightnessSlider.RegisterCallback>(OnLightnessChange);
_chromaSlider = ui.Q("ResponseChromaSlider");
_chromaSlider.RegisterCallback>(OnChromaChange);
_hueSlider = ui.Q("ResponseHueSlider");
_hueSlider.RegisterCallback>(OnHueChange);
_responseColour = ui.Q("ResponseColour");
}
///
/// handle lightness slider change
///
/// change event
private void OnLightnessChange(ChangeEvent evt)
{
lightness = Math.Clamp(evt.newValue, 0d, 100d);
_responseColour.style.backgroundColor = ToColor();
}
///
/// handle chroma slider change
///
/// change event
private void OnChromaChange(ChangeEvent evt)
{
chroma = Math.Clamp(evt.newValue, 0d, 0.5d);
_responseColour.style.backgroundColor = ToColor();
}
///
/// handle hue slider change
///
/// change event
private void OnHueChange(ChangeEvent evt)
{
hue = Math.Clamp(evt.newValue, 0d, 360d);
_responseColour.style.backgroundColor = ToColor();
}
///
/// convert the oklch colour to a unity rgba colour object
///
/// a unity rgba color object
private Color ToColor()
{
// clamp values
var cL = Math.Clamp(lightness / 100.0d, 0d, 1d);
var cC = Math.Clamp(chroma, 0d, 0.5d);
var cH = Math.Clamp(hue, 0d, 360d);
// convert [OKL]Ch to [OKL]ab
var hueRadians = cH * Math.PI / 180.0d;
var a = cC * Math.Cos(hueRadians);
var b = cC * Math.Sin(hueRadians);
// bring it to linear sRGB, clip it, then bring it back to non-linear sRGB
var lsrgb = Colorimetry.oklab_to_linear_srgb(new Colorimetry.Lab((float)cL, (float)a, (float)b));
var clippedLsrgb = Colorimetry.gamut_clip_preserve_chroma(lsrgb);
var srgb = new Color(
Math.Clamp((float)Colorimetry.srgb_nonlinear_transform_f(clippedLsrgb.r), 0.0f, 1.0f),
Math.Clamp((float)Colorimetry.srgb_nonlinear_transform_f(clippedLsrgb.g), 0.0f, 1.0f),
Math.Clamp((float)Colorimetry.srgb_nonlinear_transform_f(clippedLsrgb.b), 0.0f, 1.0f));
return srgb;
}
}