mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 22:00:03 -04:00
Improve color picker cache (#886)
* colorpicker: try to maintain hue even when saturation goes to zero * More consistent arguments to color types * implement `Hash` for `Rgba`.
This commit is contained in:
@@ -1284,22 +1284,14 @@ impl Ui {
|
||||
/// If the user clicks the button, a full color picker is shown.
|
||||
/// The given color is in `sRGB` space.
|
||||
pub fn color_edit_button_srgb(&mut self, srgb: &mut [u8; 3]) -> Response {
|
||||
let mut hsva = Hsva::from_srgb(*srgb);
|
||||
let response =
|
||||
color_picker::color_edit_button_hsva(self, &mut hsva, color_picker::Alpha::Opaque);
|
||||
*srgb = hsva.to_srgb();
|
||||
response
|
||||
color_picker::color_edit_button_srgb(self, srgb)
|
||||
}
|
||||
|
||||
/// Shows a button with the given color.
|
||||
/// If the user clicks the button, a full color picker is shown.
|
||||
/// The given color is in linear RGB space.
|
||||
pub fn color_edit_button_rgb(&mut self, rgb: &mut [f32; 3]) -> Response {
|
||||
let mut hsva = Hsva::from_rgb(*rgb);
|
||||
let response =
|
||||
color_picker::color_edit_button_hsva(self, &mut hsva, color_picker::Alpha::Opaque);
|
||||
*rgb = hsva.to_rgb();
|
||||
response
|
||||
color_picker::color_edit_button_rgb(self, rgb)
|
||||
}
|
||||
|
||||
/// Shows a button with the given color.
|
||||
@@ -1317,24 +1309,29 @@ impl Ui {
|
||||
/// The given color is in `sRGBA` space without premultiplied alpha.
|
||||
/// If unsure, what "premultiplied alpha" is, then this is probably the function you want to use.
|
||||
pub fn color_edit_button_srgba_unmultiplied(&mut self, srgba: &mut [u8; 4]) -> Response {
|
||||
let mut hsva = Hsva::from_srgba_unmultiplied(*srgba);
|
||||
let mut rgba = Rgba::from_srgba_unmultiplied(srgba[0], srgba[1], srgba[2], srgba[3]);
|
||||
let response =
|
||||
color_picker::color_edit_button_hsva(self, &mut hsva, color_picker::Alpha::OnlyBlend);
|
||||
*srgba = hsva.to_srgba_unmultiplied();
|
||||
color_picker::color_edit_button_rgba(self, &mut rgba, color_picker::Alpha::OnlyBlend);
|
||||
*srgba = rgba.to_srgba_unmultiplied();
|
||||
response
|
||||
}
|
||||
|
||||
/// Shows a button with the given color.
|
||||
/// If the user clicks the button, a full color picker is shown.
|
||||
/// The given color is in linear RGBA space with premultiplied alpha
|
||||
pub fn color_edit_button_rgba_premultiplied(&mut self, rgba: &mut [f32; 4]) -> Response {
|
||||
let mut hsva = Hsva::from_rgba_premultiplied(*rgba);
|
||||
let response = color_picker::color_edit_button_hsva(
|
||||
pub fn color_edit_button_rgba_premultiplied(&mut self, rgba_premul: &mut [f32; 4]) -> Response {
|
||||
let mut rgba = Rgba::from_rgba_premultiplied(
|
||||
rgba_premul[0],
|
||||
rgba_premul[1],
|
||||
rgba_premul[2],
|
||||
rgba_premul[3],
|
||||
);
|
||||
let response = color_picker::color_edit_button_rgba(
|
||||
self,
|
||||
&mut hsva,
|
||||
&mut rgba,
|
||||
color_picker::Alpha::BlendOrAdditive,
|
||||
);
|
||||
*rgba = hsva.to_rgba_premultiplied();
|
||||
*rgba_premul = rgba.to_array();
|
||||
response
|
||||
}
|
||||
|
||||
@@ -1342,11 +1339,16 @@ impl Ui {
|
||||
/// If the user clicks the button, a full color picker is shown.
|
||||
/// The given color is in linear RGBA space without premultiplied alpha.
|
||||
/// If unsure, what "premultiplied alpha" is, then this is probably the function you want to use.
|
||||
pub fn color_edit_button_rgba_unmultiplied(&mut self, rgba: &mut [f32; 4]) -> Response {
|
||||
let mut hsva = Hsva::from_rgba_unmultiplied(*rgba);
|
||||
pub fn color_edit_button_rgba_unmultiplied(&mut self, rgba_unmul: &mut [f32; 4]) -> Response {
|
||||
let mut rgba = Rgba::from_rgba_unmultiplied(
|
||||
rgba_unmul[0],
|
||||
rgba_unmul[1],
|
||||
rgba_unmul[2],
|
||||
rgba_unmul[3],
|
||||
);
|
||||
let response =
|
||||
color_picker::color_edit_button_hsva(self, &mut hsva, color_picker::Alpha::OnlyBlend);
|
||||
*rgba = hsva.to_rgba_unmultiplied();
|
||||
color_picker::color_edit_button_rgba(self, &mut rgba, color_picker::Alpha::OnlyBlend);
|
||||
*rgba_unmul = rgba.to_rgba_unmultiplied();
|
||||
response
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,18 +324,10 @@ fn color_picker_hsva_2d(ui: &mut Ui, hsva: &mut Hsva, alpha: Alpha) -> bool {
|
||||
|
||||
/// Returns `true` on change.
|
||||
pub fn color_picker_color32(ui: &mut Ui, srgba: &mut Color32, alpha: Alpha) -> bool {
|
||||
// To ensure we keep hue slider when `srgba` is gray we store the
|
||||
// full `Hsva` in a cache:
|
||||
|
||||
let mut hsva = use_color_cache(ui.ctx(), |cc| cc.get(srgba).cloned())
|
||||
.unwrap_or_else(|| Hsva::from(*srgba));
|
||||
|
||||
let mut hsva = color_cache_get(ui.ctx(), *srgba);
|
||||
let response = color_picker_hsva_2d(ui, &mut hsva, alpha);
|
||||
|
||||
*srgba = Color32::from(hsva);
|
||||
|
||||
use_color_cache(ui.ctx(), |cc| cc.set(*srgba, hsva));
|
||||
|
||||
color_cache_set(ui.ctx(), *srgba, hsva);
|
||||
response
|
||||
}
|
||||
|
||||
@@ -378,21 +370,59 @@ pub fn color_edit_button_hsva(ui: &mut Ui, hsva: &mut Hsva, alpha: Alpha) -> Res
|
||||
/// Shows a button with the given color.
|
||||
/// If the user clicks the button, a full color picker is shown.
|
||||
pub fn color_edit_button_srgba(ui: &mut Ui, srgba: &mut Color32, alpha: Alpha) -> Response {
|
||||
// To ensure we keep hue slider when `srgba` is gray we store the
|
||||
// full `Hsva` in a cache:
|
||||
|
||||
let mut hsva = use_color_cache(ui.ctx(), |cc| cc.get(srgba).cloned())
|
||||
.unwrap_or_else(|| Hsva::from(*srgba));
|
||||
|
||||
let mut hsva = color_cache_get(ui.ctx(), *srgba);
|
||||
let response = color_edit_button_hsva(ui, &mut hsva, alpha);
|
||||
|
||||
*srgba = Color32::from(hsva);
|
||||
|
||||
use_color_cache(ui.ctx(), |cc| cc.set(*srgba, hsva));
|
||||
|
||||
color_cache_set(ui.ctx(), *srgba, hsva);
|
||||
response
|
||||
}
|
||||
|
||||
fn use_color_cache<R>(ctx: &Context, f: impl FnOnce(&mut FixedCache<Color32, Hsva>) -> R) -> R {
|
||||
/// Shows a button with the given color.
|
||||
/// If the user clicks the button, a full color picker is shown.
|
||||
/// The given color is in `sRGB` space.
|
||||
pub fn color_edit_button_srgb(ui: &mut Ui, srgb: &mut [u8; 3]) -> Response {
|
||||
let mut srgba = Color32::from_rgb(srgb[0], srgb[1], srgb[2]);
|
||||
let response = color_edit_button_srgba(ui, &mut srgba, Alpha::Opaque);
|
||||
srgb[0] = srgba[0];
|
||||
srgb[1] = srgba[1];
|
||||
srgb[2] = srgba[2];
|
||||
response
|
||||
}
|
||||
|
||||
/// Shows a button with the given color.
|
||||
/// If the user clicks the button, a full color picker is shown.
|
||||
pub fn color_edit_button_rgba(ui: &mut Ui, rgba: &mut Rgba, alpha: Alpha) -> Response {
|
||||
let mut hsva = color_cache_get(ui.ctx(), *rgba);
|
||||
let response = color_edit_button_hsva(ui, &mut hsva, alpha);
|
||||
*rgba = Rgba::from(hsva);
|
||||
color_cache_set(ui.ctx(), *rgba, hsva);
|
||||
response
|
||||
}
|
||||
|
||||
/// Shows a button with the given color.
|
||||
/// If the user clicks the button, a full color picker is shown.
|
||||
pub fn color_edit_button_rgb(ui: &mut Ui, rgb: &mut [f32; 3]) -> Response {
|
||||
let mut rgba = Rgba::from_rgb(rgb[0], rgb[1], rgb[2]);
|
||||
let response = color_edit_button_rgba(ui, &mut rgba, Alpha::Opaque);
|
||||
rgb[0] = rgba[0];
|
||||
rgb[1] = rgba[1];
|
||||
rgb[2] = rgba[2];
|
||||
response
|
||||
}
|
||||
|
||||
// To ensure we keep hue slider when `srgba` is gray we store the full `Hsva` in a cache:
|
||||
fn color_cache_get(ctx: &Context, rgba: impl Into<Rgba>) -> Hsva {
|
||||
let rgba = rgba.into();
|
||||
use_color_cache(ctx, |cc| cc.get(&rgba).cloned()).unwrap_or_else(|| Hsva::from(rgba))
|
||||
}
|
||||
|
||||
// To ensure we keep hue slider when `srgba` is gray we store the full `Hsva` in a cache:
|
||||
fn color_cache_set(ctx: &Context, rgba: impl Into<Rgba>, hsva: Hsva) {
|
||||
let rgba = rgba.into();
|
||||
use_color_cache(ctx, |cc| cc.set(rgba, hsva));
|
||||
}
|
||||
|
||||
// To ensure we keep hue slider when `srgba` is gray we store the full `Hsva` in a cache:
|
||||
fn use_color_cache<R>(ctx: &Context, f: impl FnOnce(&mut FixedCache<Rgba, Hsva>) -> R) -> R {
|
||||
f(ctx.memory().data.get_temp_mut_or_default(Id::null()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user