This repository has been archived on 2024-11-20. You can view files and clone it, but cannot push or open issues or pull requests.
colourmeok/ColourMeOKGame/Assets/Scripts/OklchColourPickerUI.cs

130 lines
3.9 KiB
C#
Raw Normal View History

using System;
using UnityEngine;
using UnityEngine.UIElements;
2024-11-17 07:29:22 +08:00
/// <summary>
/// class to handle the oklch colour picker ui
/// </summary>
public class OklchColourPickerUI : MonoBehaviour
{
/// <summary>
/// perceptual lightness value of the colour (0-100)
/// </summary>
public double lightness;
/// <summary>
/// chroma value of the colour (0-0.5)
/// </summary>
public double chroma;
/// <summary>
/// hue value of the colour (0-360)
/// </summary>
public double hue;
/// <summary>
/// slider for the chroma value
/// </summary>
private Slider _chromaSlider;
/// <summary>
/// slider for the hue value
/// </summary>
private Slider _hueSlider;
/// <summary>
/// slider for the lightness value
/// </summary>
private Slider _lightnessSlider;
/// <summary>
/// visual element for the response colour preview
/// </summary>
private VisualElement _responseColour;
/// <summary>
/// function to set the initial values of the sliders
/// </summary>
private void Start()
{
_lightnessSlider.value = 74.61f;
_chromaSlider.value = 0.0868f;
_hueSlider.value = 335.72f;
}
/// <summary>
/// function to subscribe slider events to their respective functions
/// </summary>
public void OnEnable()
{
var ui = GetComponent<UIDocument>().rootVisualElement;
_lightnessSlider = ui.Q<Slider>("ResponseLightnessSlider");
_lightnessSlider.RegisterCallback<ChangeEvent<float>>(OnLightnessChange);
_chromaSlider = ui.Q<Slider>("ResponseChromaSlider");
_chromaSlider.RegisterCallback<ChangeEvent<float>>(OnChromaChange);
_hueSlider = ui.Q<Slider>("ResponseHueSlider");
_hueSlider.RegisterCallback<ChangeEvent<float>>(OnHueChange);
_responseColour = ui.Q<VisualElement>("ResponseColour");
}
/// <summary>
/// handle lightness slider change
/// </summary>
/// <param name="evt">change event</param>
private void OnLightnessChange(ChangeEvent<float> evt)
{
lightness = Math.Clamp(evt.newValue, 0d, 100d);
_responseColour.style.backgroundColor = ToColor();
}
/// <summary>
/// handle chroma slider change
/// </summary>
/// <param name="evt">change event</param>
private void OnChromaChange(ChangeEvent<float> evt)
{
chroma = Math.Clamp(evt.newValue, 0d, 0.5d);
_responseColour.style.backgroundColor = ToColor();
}
/// <summary>
/// handle hue slider change
/// </summary>
/// <param name="evt">change event</param>
private void OnHueChange(ChangeEvent<float> evt)
{
hue = Math.Clamp(evt.newValue, 0d, 360d);
_responseColour.style.backgroundColor = ToColor();
}
/// <summary>
/// convert the oklch colour to a unity rgba colour object
/// </summary>
/// <returns>a unity rgba color object</returns>
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;
}
}