diff --git a/egui/src/containers/frame.rs b/egui/src/containers/frame.rs index b4db3101..0cc49b64 100644 --- a/egui/src/containers/frame.rs +++ b/egui/src/containers/frame.rs @@ -18,7 +18,7 @@ impl Frame { margin: style.window_padding, corner_radius: style.window.corner_radius, fill: Some(style.background_fill), - outline: style.interact.inactive.rect_outline, // because we can resize windows + outline: style.interact.inactive.bg_outline, // because we can resize windows } } diff --git a/egui/src/containers/scroll_area.rs b/egui/src/containers/scroll_area.rs index 193e0841..a33271c8 100644 --- a/egui/src/containers/scroll_area.rs +++ b/egui/src/containers/scroll_area.rs @@ -237,8 +237,8 @@ impl Prepared { } let style = ui.style(); - let handle_fill = style.interact(&response).fill; - let handle_outline = style.interact(&response).rect_outline; + let handle_fill = style.interact(&response).main_fill; + let handle_outline = style.interact(&response).bg_outline; ui.painter().add(paint::PaintCmd::Rect { rect: outer_scroll_rect, diff --git a/egui/src/containers/window.rs b/egui/src/containers/window.rs index a4c9bd7f..0c11324d 100644 --- a/egui/src/containers/window.rs +++ b/egui/src/containers/window.rs @@ -567,7 +567,7 @@ fn paint_frame_interaction( path, closed: false, fill: None, - outline: style.rect_outline, + outline: style.bg_outline, }); } @@ -671,7 +671,7 @@ impl TitleBar { let y = content_rect.top() + ui.style().item_spacing.y * 0.5; ui.painter().line_segment( [pos2(left, y), pos2(right, y)], - ui.style().interact.inactive.rect_outline.unwrap(), + ui.style().interact.inactive.bg_outline.unwrap(), ); } diff --git a/egui/src/menu.rs b/egui/src/menu.rs index 1c495cf3..93a70338 100644 --- a/egui/src/menu.rs +++ b/egui/src/menu.rs @@ -63,11 +63,11 @@ pub fn bar(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Rect) let mut style = ui.style().clone(); style.button_padding = vec2(2.0, 0.0); // style.interact.active.bg_fill = None; - style.interact.active.rect_outline = None; + style.interact.active.bg_outline = None; // style.interact.hovered.bg_fill = None; - style.interact.hovered.rect_outline = None; + style.interact.hovered.bg_outline = None; style.interact.inactive.bg_fill = None; - style.interact.inactive.rect_outline = None; + style.interact.inactive.bg_outline = None; ui.set_style(style); // Take full width and fixed height: @@ -108,7 +108,7 @@ fn menu_impl<'c>( let mut button = Button::new(title); if bar_state.open_menu == Some(menu_id) { - button = button.fill(Some(ui.style().interact.active.fill)); + button = button.fill(Some(ui.style().interact.active.main_fill)); } let button_response = ui.add(button); @@ -129,11 +129,11 @@ fn menu_impl<'c>( let mut style = ui.style().clone(); style.button_padding = vec2(2.0, 0.0); // style.interact.active.bg_fill = None; - style.interact.active.rect_outline = None; + style.interact.active.bg_outline = None; // style.interact.hovered.bg_fill = None; - style.interact.hovered.rect_outline = None; + style.interact.hovered.bg_outline = None; style.interact.inactive.bg_fill = None; - style.interact.inactive.rect_outline = None; + style.interact.inactive.bg_outline = None; ui.set_style(style); ui.set_layout(Layout::justified(Direction::Vertical)); add_contents(ui) diff --git a/egui/src/paint/color.rs b/egui/src/paint/color.rs index ab613242..4580aa59 100644 --- a/egui/src/paint/color.rs +++ b/egui/src/paint/color.rs @@ -7,7 +7,7 @@ pub struct Srgba { pub r: u8, pub g: u8, pub b: u8, - /// Linear space (not subject to sRGBA gamma conversion) + /// Alpha is in linear space (not subject to sRGBA gamma conversion) pub a: u8, } /// 0-1 linear space `RGBA` color with premultiplied alpha. @@ -110,7 +110,42 @@ impl Srgba { } } +// ---------------------------------------------------------------------------- + +pub const TRANSPARENT: Srgba = srgba(0, 0, 0, 0); +pub const BLACK: Srgba = srgba(0, 0, 0, 255); +pub const LIGHT_GRAY: Srgba = srgba(220, 220, 220, 255); +pub const GRAY: Srgba = srgba(160, 160, 160, 255); +pub const WHITE: Srgba = srgba(255, 255, 255, 255); +pub const RED: Srgba = srgba(255, 0, 0, 255); +pub const GREEN: Srgba = srgba(0, 255, 0, 255); +pub const BLUE: Srgba = srgba(0, 0, 255, 255); +pub const YELLOW: Srgba = srgba(255, 255, 0, 255); +pub const LIGHT_BLUE: Srgba = srgba(140, 160, 255, 255); + +// ---------------------------------------------------------------------------- + impl Rgba { + pub const TRANSPARENT: Rgba = Rgba::new(0.0, 0.0, 0.0, 0.0); + pub const BLACK: Rgba = Rgba::new(0.0, 0.0, 0.0, 1.0); + pub const WHITE: Rgba = Rgba::new(1.0, 1.0, 1.0, 1.0); + pub const RED: Rgba = Rgba::new(1.0, 0.0, 0.0, 1.0); + pub const GREEN: Rgba = Rgba::new(0.0, 1.0, 0.0, 1.0); + pub const BLUE: Rgba = Rgba::new(0.0, 0.0, 1.0, 1.0); + + pub const fn new(r: f32, g: f32, b: f32, a: f32) -> Self { + Self { r, g, b, a } + } + + pub const fn gray(l: f32) -> Self { + Self { + r: l, + g: l, + b: l, + a: 1.0, + } + } + pub fn luminance_alpha(l: f32, a: f32) -> Self { debug_assert!(0.0 <= l && l <= 1.0); debug_assert!(0.0 <= a && a <= 1.0); @@ -122,13 +157,14 @@ impl Rgba { } } - pub fn white_alpha(l: f32) -> Self { - debug_assert!(0.0 <= l && l <= 1.0); + /// Transparent white + pub fn white_alpha(a: f32) -> Self { + debug_assert!(0.0 <= a && a <= 1.0); Self { - r: l, - g: l, - b: l, - a: l, + r: a, + g: a, + b: a, + a, } } @@ -143,13 +179,38 @@ impl Rgba { } } -pub const TRANSPARENT: Srgba = srgba(0, 0, 0, 0); -pub const BLACK: Srgba = srgba(0, 0, 0, 255); -pub const LIGHT_GRAY: Srgba = srgba(220, 220, 220, 255); -pub const GRAY: Srgba = srgba(160, 160, 160, 255); -pub const WHITE: Srgba = srgba(255, 255, 255, 255); -pub const RED: Srgba = srgba(255, 0, 0, 255); -pub const GREEN: Srgba = srgba(0, 255, 0, 255); -pub const BLUE: Srgba = srgba(0, 0, 255, 255); -pub const YELLOW: Srgba = srgba(255, 255, 0, 255); -pub const LIGHT_BLUE: Srgba = srgba(140, 160, 255, 255); +impl std::ops::Add for Rgba { + type Output = Rgba; + fn add(self, rhs: Rgba) -> Rgba { + Rgba { + r: self.r + rhs.r, + g: self.g + rhs.g, + b: self.b + rhs.b, + a: self.a + rhs.a, + } + } +} + +impl std::ops::Mul for Rgba { + type Output = Rgba; + fn mul(self, factor: f32) -> Rgba { + Rgba { + r: self.r * factor, + g: self.g * factor, + b: self.b * factor, + a: self.a * factor, + } + } +} + +impl std::ops::Mul for f32 { + type Output = Rgba; + fn mul(self, rgba: Rgba) -> Rgba { + Rgba { + r: self * rgba.r, + g: self * rgba.g, + b: self * rgba.b, + a: self * rgba.a, + } + } +} diff --git a/egui/src/style.rs b/egui/src/style.rs index a521941e..b9a40052 100644 --- a/egui/src/style.rs +++ b/egui/src/style.rs @@ -117,35 +117,35 @@ impl Default for Interact { Self { active: WidgetStyle { bg_fill: Some(Srgba::black_alpha(128)), - fill: srgba(120, 120, 200, 255), + bg_outline: Some(LineStyle::new(2.0, WHITE)), + corner_radius: 0.0, + main_fill: srgba(120, 120, 200, 255), stroke_color: WHITE, stroke_width: 2.0, - rect_outline: Some(LineStyle::new(2.0, WHITE)), - corner_radius: 0.0, }, hovered: WidgetStyle { bg_fill: None, - fill: srgba(100, 100, 150, 255), + bg_outline: Some(LineStyle::new(1.0, WHITE)), + corner_radius: 2.0, + main_fill: srgba(100, 100, 150, 255), stroke_color: Srgba::gray(240), stroke_width: 1.5, - rect_outline: Some(LineStyle::new(1.0, WHITE)), - corner_radius: 2.0, }, inactive: WidgetStyle { bg_fill: None, - fill: srgba(60, 60, 80, 255), + bg_outline: Some(LineStyle::new(1.0, Srgba::gray(128))), + corner_radius: 4.0, + main_fill: srgba(60, 60, 80, 255), stroke_color: Srgba::gray(200), // Mustn't look grayed out! stroke_width: 1.0, - rect_outline: Some(LineStyle::new(1.0, Srgba::gray(128))), - corner_radius: 4.0, }, disabled: WidgetStyle { bg_fill: None, - fill: srgba(50, 50, 50, 255), + bg_outline: Some(LineStyle::new(0.5, Srgba::gray(128))), + corner_radius: 4.0, + main_fill: srgba(50, 50, 50, 255), stroke_color: Srgba::gray(128), // Should look grayed out stroke_width: 0.5, - rect_outline: Some(LineStyle::new(0.5, Srgba::gray(128))), - corner_radius: 4.0, }, } } @@ -171,22 +171,28 @@ pub struct WidgetStyle { /// Background color of widget pub bg_fill: Option, + /// For surrounding rectangle of things that need it, + /// like buttons, the box of the checkbox, etc. + pub bg_outline: Option, + + /// Button frames etc + pub corner_radius: f32, + /// Fill color of the interactive part of a component (slider grab, checkbox, ...) /// When you need a fill. - pub fill: Srgba, + pub main_fill: Srgba, /// Stroke and text color of the interactive part of a component (button, slider grab, checkbox, ...) pub stroke_color: Srgba, /// For lines etc pub stroke_width: f32, +} - /// For surrounding rectangle of things that need it, - /// like buttons, the box of the checkbox, etc. - pub rect_outline: Option, - - /// Button frames etc - pub corner_radius: f32, +impl WidgetStyle { + pub fn line_style(&self) -> LineStyle { + LineStyle::new(self.stroke_width, self.stroke_color) + } } #[derive(Clone, Copy, Debug)] diff --git a/egui/src/widgets.rs b/egui/src/widgets.rs index 094f31f4..8ef89eb7 100644 --- a/egui/src/widgets.rs +++ b/egui/src/widgets.rs @@ -292,7 +292,7 @@ impl Widget for Button { rect: response.rect, corner_radius: ui.style().interact(&response).corner_radius, fill: bg_fill, - outline: ui.style().interact(&response).rect_outline, + outline: ui.style().interact(&response).bg_outline, }); let stroke_color = ui.style().interact(&response).stroke_color; let text_color = text_color.unwrap_or(stroke_color); @@ -356,7 +356,7 @@ impl<'a> Widget for Checkbox<'a> { rect: big_icon_rect, corner_radius: ui.style().interact(&response).corner_radius, fill: ui.style().interact(&response).bg_fill, - outline: ui.style().interact(&response).rect_outline, + outline: ui.style().interact(&response).bg_outline, }); let stroke_color = ui.style().interact(&response).stroke_color; @@ -437,7 +437,7 @@ impl Widget for RadioButton { center: big_icon_rect.center(), radius: big_icon_rect.width() / 2.0, fill: bg_fill, - outline: ui.style().interact(&response).rect_outline, // TODO + outline: ui.style().interact(&response).bg_outline, }); if checked { diff --git a/egui/src/widgets/slider.rs b/egui/src/widgets/slider.rs index 56605519..1ee23211 100644 --- a/egui/src/widgets/slider.rs +++ b/egui/src/widgets/slider.rs @@ -171,7 +171,7 @@ impl<'a> Slider<'a> { ui.painter().add(PaintCmd::Circle { center: pos2(marker_center_x, rail_rect.center().y), radius: handle_radius(rect), - fill: Some(ui.style().interact(response).fill), + fill: Some(ui.style().interact(response).main_fill), outline: Some(LineStyle::new( ui.style().interact(response).stroke_width, ui.style().interact(response).stroke_color, diff --git a/egui/src/widgets/text_edit.rs b/egui/src/widgets/text_edit.rs index 1c255136..69608861 100644 --- a/egui/src/widgets/text_edit.rs +++ b/egui/src/widgets/text_edit.rs @@ -184,7 +184,7 @@ impl<'t> Widget for TextEdit<'t> { rect: bg_rect, corner_radius: ui.style().interact(&response).corner_radius, fill: Some(ui.style().dark_bg_color), - outline: ui.style().interact(&response).rect_outline, + outline: ui.style().interact(&response).bg_outline, }); }