Skip to content

Commit

Permalink
Add Ui::set_opacity
Browse files Browse the repository at this point in the history
Closes #3473
  • Loading branch information
YgorSouza committed Feb 4, 2024
1 parent 114f820 commit 23cc068
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 11 deletions.
44 changes: 33 additions & 11 deletions crates/egui/src/painter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ pub struct Painter {
/// If set, all shapes will have their colors modified to be closer to this.
/// This is used to implement grayed out interfaces.
fade_to_color: Option<Color32>,

/// If set, all shapes will have their colors modified with [`Color32::gamma_multiply`] with
/// this value as the factor.
/// This is used to make interfaces semi-transparent.
opacity: Option<f32>,
}

impl Painter {
Expand All @@ -38,6 +43,7 @@ impl Painter {
layer_id,
clip_rect,
fade_to_color: None,
opacity: None,
}
}

Expand All @@ -49,6 +55,7 @@ impl Painter {
layer_id,
clip_rect: self.clip_rect,
fade_to_color: None,
opacity: None,
}
}

Expand All @@ -62,6 +69,7 @@ impl Painter {
layer_id: self.layer_id,
clip_rect: rect.intersect(self.clip_rect),
fade_to_color: self.fade_to_color,
opacity: self.opacity,
}
}

Expand All @@ -75,6 +83,10 @@ impl Painter {
self.fade_to_color = fade_to_color;
}

pub(crate) fn set_opacity(&mut self, opacity: Option<f32>) {
self.opacity = opacity.filter(|f| f.is_finite()).map(|f| f.clamp(0.0, 1.0));
}

pub(crate) fn is_visible(&self) -> bool {
self.fade_to_color != Some(Color32::TRANSPARENT)
}
Expand Down Expand Up @@ -151,6 +163,9 @@ impl Painter {
if let Some(fade_to_color) = self.fade_to_color {
tint_shape_towards(shape, fade_to_color);
}
if let Some(opacity) = self.opacity {
set_shape_opacity(shape, opacity);
}
}

/// It is up to the caller to make sure there is room for this.
Expand All @@ -170,18 +185,17 @@ impl Painter {
///
/// Calling this once is generally faster than calling [`Self::add`] multiple times.
pub fn extend<I: IntoIterator<Item = Shape>>(&self, shapes: I) {
if self.fade_to_color == Some(Color32::TRANSPARENT) {
return;
match (self.fade_to_color, self.opacity) {
(None, None) => self.paint_list(|l| l.extend(self.clip_rect, shapes)),
(Some(Color32::TRANSPARENT), _) => (),
(_, Some(_)) | (Some(_), _) => {
let shapes = shapes.into_iter().map(|mut shape| {
self.transform_shape(&mut shape);
shape
});
self.paint_list(|l| l.extend(self.clip_rect, shapes));
}
}
if self.fade_to_color.is_some() {
let shapes = shapes.into_iter().map(|mut shape| {
self.transform_shape(&mut shape);
shape
});
self.paint_list(|l| l.extend(self.clip_rect, shapes));
} else {
self.paint_list(|l| l.extend(self.clip_rect, shapes));
};
}

/// Modify an existing [`Shape`].
Expand Down Expand Up @@ -496,3 +510,11 @@ fn tint_shape_towards(shape: &mut Shape, target: Color32) {
}
});
}

fn set_shape_opacity(shape: &mut Shape, opacity: f32) {
epaint::shape_transform::adjust_colors(shape, &|color| {
if *color != Color32::PLACEHOLDER {
*color = color.gamma_multiply(opacity);
}
});
}
20 changes: 20 additions & 0 deletions crates/egui/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,26 @@ impl Ui {
}
}

/// Make the widget in this [`Ui`] semi-transparent.
///
/// `opacity` must be between 0.0 and 1.0, where 0.0 means fully transparent (i.e., invisible)
/// and 1.0 means fully opaque (i.e., the same as not calling the method at all).
///
/// ### Example
/// ```
/// # egui::__run_test_ui(|ui| {
/// ui.group(|ui| {
/// ui.set_opacity(0.5);
/// if ui.button("Half-transparent button").clicked() {
/// /* … */
/// }
/// });
/// # });
/// ```
pub fn set_opacity(&mut self, opacity: f32) {
self.painter.set_opacity(Some(opacity));
}

/// Read the [`Layout`].
#[inline]
pub fn layout(&self) -> &Layout {
Expand Down
10 changes: 10 additions & 0 deletions crates/egui_demo_lib/src/demo/widget_gallery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct WidgetGallery {
enabled: bool,
visible: bool,
boolean: bool,
opacity: f32,
radio: Enum,
scalar: f32,
string: String,
Expand All @@ -28,6 +29,7 @@ impl Default for WidgetGallery {
Self {
enabled: true,
visible: true,
opacity: 1.0,
boolean: false,
radio: Enum::First,
scalar: 42.0,
Expand Down Expand Up @@ -61,6 +63,7 @@ impl super::View for WidgetGallery {
fn ui(&mut self, ui: &mut egui::Ui) {
ui.add_enabled_ui(self.enabled, |ui| {
ui.set_visible(self.visible);
ui.set_opacity(self.opacity);

egui::Grid::new("my_grid")
.num_columns(2)
Expand All @@ -79,6 +82,12 @@ impl super::View for WidgetGallery {
if self.visible {
ui.checkbox(&mut self.enabled, "Interactive")
.on_hover_text("Uncheck to inspect how the widgets look when disabled.");
(ui.add(
egui::DragValue::new(&mut self.opacity)
.speed(0.01)
.clamp_range(0.0..=1.0),
) | ui.label("Opacity"))
.on_hover_text("Reduce this value to make widgets semi-transparent");
}
});

Expand All @@ -99,6 +108,7 @@ impl WidgetGallery {
let Self {
enabled: _,
visible: _,
opacity: _,
boolean,
radio,
scalar,
Expand Down

0 comments on commit 23cc068

Please sign in to comment.