Enable Color Pickers with Defined HSV Subspace. ( New Feature Request )

In many situations I want to limit a color picker to an HSV subspace, particularly a simple rectangular subspace defined by lower and upper bounds on H, S, and V. Having an optional parameter in the ColorPicker constructor that facilitates this would be extremely helpful.

There are many use cases where restricting a user to an HSV subspace makes sense. In fact, I would say that this would apply to a majority of cases involving layperson facing applications where users should not be expected to be mindful of color theory, palettes, visual accessibility, … . To that end, we shouldn’t have to clamp the user input after the fact. The limited color space choice should be readily visible and facilitated by the color picker UI element itself.


Just to confirm, you are speaking about the GUI color Picker ?

Let me add @msDestiny14 to the thread and @PatrickRyan for the design.

Also would you be willing to contribute the feature ?


Thanks @sebavan. Yes, I am referring to the GUI color Picker. I am willing to contribute to the feature.

AMAZING, Lets s see if @patrick has a design idea and then you could introduce the option, Thanks a lot !!!

So as it stands, the current color picker could drive HSV output since the three channels are representing through degrees on the wheel and the X/Y axes in the box. But you want an upper and lower limit on all three axes, correct?

So, the only way to do that on our current control without needing a new control design would be to only display the values between lower and upper. So the wheel could have far fewer colors represented as a remapping of the allowed colors to the entire wheel range. Same with saturation and value. It would look a little strange if you limit any axis to a single option. For example, having the wheel show only red as it was the only allowed hue would make clicking anywhere on the wheel only produce red. Not idea UX, but without a new control, it may be what we are limited to.


Every other iteration of an HSV picker I have seen requires sliders or a split view where you have hue and saturation on X and Y and a separate part to the control with value mapped along the Y axis. There is one other that I have seen that isn’t quite helpful which is in Photoshop:

This one is problematic because the picker can’t choose a color that has both saturation and value at non-zero and non-one values at the same time. If you click on the top half to choose saturation, you get a value of 1.0 and vice versa. So you can’t have a dark, desaturated color in this picker. The only other way to represent an HSV picker would be like:

Is this what you are talking about?

Are you seeing this as redesign of the current color picker or just making a different type option?

I am seeing the solution restricting the user to picking a color from a predetermined subset of the HSV space. The current design could be tweaked to intuitively convey a possibly restricted range of Hue in the ring region and the slice of the HSV space at the chosen Hue within the square region.

I am talking about adding an additional optional parameter to the ColorPicker constructor which will restrict the H, S, and V values that are visualized and can be chosen by the user. This additional optional parameter would define Hmin, Hmax, Smin, Smax, and Vmin, Vmax.

@SirFizX, this sounds like the only requirement beyond adding the min/max for each channel in the constructor would be for the picker that renders to the screen to remap the available range between min/max to fit the picker wheel and value/saturation box.

Sounds great to me. Looking forward to seeing what you come up with. Thanks for contributing!

1 Like

Thanks @PatrickRyan ! Have a wonderful weekend!

A few type aliases can be added:

 * Alias type for number that represents a minimum value
 * @ignorenaming
 type min = number;

 * Alias type for number that represents a maximum value
 * @ignorenaming
type max = number;

 * Alias type for array that represents a range
 * @ignorenaming
type range = [min,max];

 * Alias type for array that represents an array of range types
 * @ignorenaming
type hsvRanges = [range,range,range];

A few private properties can be added:

private _hRange: range = [0, 360];
private _sRange: range = [0, 1];
private _vRange: range = [0, 1];

The ColorPicker constructor can be adapted as:

 * Creates a new ColorPicker
 * @param name defines the control name
constructor(public name?: string, hsvRanges?: hsvRanges) {
    this._hRange = (hsvRanges) ? hsvRanges[0] : this._hRange;
    this._sRange = (hsvRanges) ? hsvRanges[1] : this._sRange;
    this._vRange = (hsvRanges) ? hsvRanges[2] : this._vRange;
    this.value = new Color3(.88, .1, .1);
    this.size = "200px";
    this.isPointerBlocker = true; 

The ColorWheelCanvas can be adapted as:

// ang is in radians from -PI to PI
var hDeg = ang * 180 / Math.PI + 180; // degrees from 0 to 360
var hDegPrime = hDeg * (this._hRange[1] - this._hRange[0]) / 360 + this._hRange[0]; // map range

Color3.HSVtoRGBToRef(hDegPrime, dist / radius, 1, color);

For picking within the specified range, the same mapping can be applied in the updateValueFromPointer function. (NOT IMPLEMENTED)

Finally, the _sRange and _vRange values would be used to restrict their respective domains. (NOT IMPLEMENTED)



@PatrickRyan Your thoughts?

@SirFizX, this seems reasonable to me, but I would like to hear what @sebavan thinks since there is another thread talking about HSV in the node material editor and there have been suggestions to go with a different color space that works similarly to HSV but does not have some of the branching logic when converting between spaces which are a killer in shaders. It would make sense if we adopt a new color space in one part of the engine that we use that same space everywhere.

@PatrickRyan Why would it need to use a single color space? Every other software (Photoshop, GIMP, Blender, Unreal, etc.) allow for multiple different color spaces for the color picker: the user can simply choose which color space they want. Everything is converted to RGB regardless. It’s also quite common for other programs to have multiple different UIs (color triangle, color square, color circle, etc.)

All colors, attributes representing colors, sent within shader source chunks should already be in RGB.

@Pauan, yes I understand that pickers in other DCC applications allow for multiple color spaces and have UI affordance so that the user always knows at a glance what color space they are in. What we are talking about here is a GUI control that simply displays as:


and the request it to put limits into the constructor to only display colors on the control within a specified HSV range. If in one part of the engine we are using HSV space as a limit on the display of a GUI control and in another you are requesting to use Oklab space do a similar task (simplifying how color is controlled with a friendly mental model), we need to have clear documentation around why we made the choice in engine as this affects the developer, not the end user with GUI affordances.

We also need to defend why we would make a developer using both GUI and Node Materials convert their code into different color spaces if they want to do something like create a high-contrast mode for their materials and GUI to be accessible. Like I mentioned in the other thread, we don’t like to make quick decisions on implementations in the engine because we are taking on backward compatibility overhead with everything we add. So taking some time to think through ramifications from both the end user and the developer perspective makes sense to us.

We can certainly support multiple color spaces in our tools, but we want to be deliberate about the decision and know that we have at least identified any potential usability issues so we know how it may affect the future roadmap.

About this change, it only provide customization of the UI to limit what we can select so I am totally ok with it as it does not break any back compat or introduce slower path :slight_smile: