From ff448ed3938e037d451c0014a5edaed1b1d4933a Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Tue, 20 Feb 2024 20:56:58 +0100 Subject: [PATCH] New background api --- hui-examples/examples/align_test.rs | 16 +++--- hui-examples/examples/mom_downloader.rs | 4 +- hui-examples/examples/rounded_rect.rs | 4 +- hui-examples/examples/text_weird.rs | 10 ++-- hui/src/background.rs | 68 +++++++++++++++++++++++++ hui/src/draw.rs | 26 ++++++---- hui/src/element/builtin/container.rs | 24 +++------ hui/src/element/builtin/progress_bar.rs | 4 +- hui/src/element/builtin/rect.rs | 12 +++-- hui/src/lib.rs | 1 + 10 files changed, 118 insertions(+), 51 deletions(-) create mode 100644 hui/src/background.rs diff --git a/hui-examples/examples/align_test.rs b/hui-examples/examples/align_test.rs index f52431d..e43418f 100644 --- a/hui-examples/examples/align_test.rs +++ b/hui-examples/examples/align_test.rs @@ -77,23 +77,23 @@ fn main() { elements: vec![ Box::new(Rect { size: (UiSize::Fraction(0.5), UiSize::Static(30.)), - color: Some(vec4(0.75, 0., 0., 1.)) + color: vec4(0.75, 0., 0., 1.).into() }), Box::new(Rect { size: (UiSize::Fraction(z / 2. + 0.5), UiSize::Static(30.)), - color: Some(vec4(0., 0.75, 0., 1.)) + color: vec4(0., 0.75, 0., 1.).into() }), ], ..Default::default() }), Box::new(Rect { size: (UiSize::Fraction(z / 2. + 0.5), UiSize::Static(30.)), - color: Some(vec4(0., 0.75, 0., 1.)) + color: vec4(0., 0.75, 0., 1.).into() }), Box::new(Container { gap: 5., padding: Sides::all(5.), - background: vec4(0., 0., 0., 0.5), + background: vec4(0., 0., 0., 0.5).into(), direction: UiDirection::Horizontal, elements: { let mut x: Vec> = vec![]; @@ -101,9 +101,9 @@ fn main() { x.push(Box::new(Rect { size: (UiSize::Static(50.), UiSize::Static(50.)), color: if i == 1 { - Some(vec4(0.75, 0.75, 0.75, 0.75)) + vec4(0.75, 0.75, 0.75, 0.75).into() } else { - Some(vec4(0.5, 0.5, 0.5, 0.75)) + vec4(0.5, 0.5, 0.5, 0.75).into() } })); } @@ -112,7 +112,7 @@ fn main() { ..Default::default() }), Box::new(Container { - background: vec4(1., 0., 0., 1.), + background: vec4(1., 0., 0., 1.).into(), padding: Sides { top: 10., bottom: 20., @@ -128,7 +128,7 @@ fn main() { elements: vec![ Box::new(Rect { size: (UiSize::Static(50.), UiSize::Static(50.)), - color: Some(vec4(1., 1., 1., 0.75)) + color: vec4(1., 1., 1., 0.75).into() }), ], ..Default::default() diff --git a/hui-examples/examples/mom_downloader.rs b/hui-examples/examples/mom_downloader.rs index 9839c8c..61b3de8 100644 --- a/hui-examples/examples/mom_downloader.rs +++ b/hui-examples/examples/mom_downloader.rs @@ -50,12 +50,12 @@ fn main() { hui.add(Container { align: Alignment::Center.into(), size: (UiSize::Fraction(1.), UiSize::Fraction(1.)), - background: vec4(0.1, 0.1, 0.1, 1.), + background: vec4(0.1, 0.1, 0.1, 1.).into(), elements: vec![Box::new(Container { gap: 5., padding: Sides::all(10.), size: (UiSize::Static(450.), UiSize::Auto), - background: vec4(0.2, 0.2, 0.5, 1.), + background: vec4(0.2, 0.2, 0.5, 1.).into(), corner_radius: Corners::all(8.), elements: elements(|el| { if instant.elapsed().as_secs_f32() < 5. { diff --git a/hui-examples/examples/rounded_rect.rs b/hui-examples/examples/rounded_rect.rs index 317a4d5..0242c73 100644 --- a/hui-examples/examples/rounded_rect.rs +++ b/hui-examples/examples/rounded_rect.rs @@ -43,7 +43,7 @@ fn main() { elements: vec![Box::new(Container { align: Alignment::Center.into(), size: (UiSize::Fraction(0.5), UiSize::Fraction(0.5)), - background: vec4(1., 0., 0., 1.), + background: vec4(1., 0., 0., 1.).into(), corner_radius: Corners { top_left: 10., top_right: 20., @@ -56,7 +56,7 @@ fn main() { direction: UiDirection::Horizontal, align: Alignment::Center.into(), size: (UiSize::Auto, UiSize::Auto), - background: vec4(0.1, 0.1, 0.1, 0.5), + background: vec4(0.1, 0.1, 0.1, 0.5).into(), corner_radius: Corners::all(8.), elements: vec![ Box::new(Text { diff --git a/hui-examples/examples/text_weird.rs b/hui-examples/examples/text_weird.rs index b90c66c..2c08937 100644 --- a/hui-examples/examples/text_weird.rs +++ b/hui-examples/examples/text_weird.rs @@ -44,7 +44,7 @@ fn main() { hui.add(Container { size: (UiSize::Fraction(1.), UiSize::Fraction(1.)), - background: vec4(0.1, 0.1, 0.1, 1.), + background: vec4(0.1, 0.1, 0.1, 1.).into(), elements: elements(|elem| { elem.add(Text { text: "THIS LINE SHOULD BE SHARP!".into(), @@ -68,11 +68,11 @@ fn main() { } elem.add(Rect { size: (UiSize::Fraction(1.), UiSize::Static(10.)), - color: Some(vec4(0., 0., 1., 1.)), + color: vec4(0., 0., 1., 1.).into(), }); elem.add(Rect { size: (UiSize::Fraction(1.), UiSize::Static(10.)), - color: Some(vec4(1., 1., 0., 1.)), + color: vec4(1., 1., 0., 1.).into(), }); elem.add(Text { text: "Hello, world!\nżółty liść. życie nie ma sensu i wszyscy zginemy;\nтест кирилиці їїїїїїїїїїї\njapanese text: テスト".into(), @@ -83,11 +83,11 @@ fn main() { if instant.elapsed().as_secs() & 1 != 0 { elem.add(Rect { size: (UiSize::Fraction(1.), UiSize::Static(10.)), - color: Some(vec4(1., 0., 0., 1.)), + color: vec4(1., 0., 0., 1.).into(), }); elem.add(Rect { size: (UiSize::Fraction(1.), UiSize::Static(10.)), - color: Some(vec4(0., 0., 0., 1.)), + color: vec4(0., 0., 0., 1.).into(), }); elem.add(Spacer(100.)); elem.add(Text { diff --git a/hui/src/background.rs b/hui/src/background.rs new file mode 100644 index 0000000..09fc821 --- /dev/null +++ b/hui/src/background.rs @@ -0,0 +1,68 @@ +use glam::Vec4; +use crate::rectangle::Corners; + +// #[derive(Clone, Copy, PartialEq, Eq, Debug)] +// pub enum GradientDirection { +// ToRight = 0b00, +// ToLeft = 0b01, +// ToBottom = 0b10, +// ToTop = 0b11, +// } + +#[derive(Clone, Copy, Default, Debug, PartialEq)] +pub enum Background { + #[default] + Transparent, + Solid(Vec4), + Gradient(Corners), +} + +impl From for Background { + fn from(color: Vec4) -> Self { + Self::Solid(color) + } +} + +impl From> for Background { + fn from(color: Option) -> Self { + match color { + Some(color) => Self::Solid(color), + None => Self::Transparent, + } + } +} + +impl Background { + /// Currently, never returns None.\ + /// `Option` has been added in preparation for future changes.\ + /// (`Background::Texture` etc) + pub fn corners(&self) -> Option> { + match *self { + Self::Transparent => Some(Corners::all(Vec4::ZERO)), + Self::Solid(color) => Some(Corners::all(color)), + Self::Gradient(corners) => Some(corners), + } + } + + /// Returns `true` if the background is `Transparent` or all corners have an alpha value of `0`. + pub fn is_transparent(&self) -> bool { + match *self { + Self::Transparent => true, + Self::Solid(color) => color.w == 0., + Self::Gradient(corners) => { + let max_alpha = + corners.top_left.w + .max(corners.top_right.w) + .max(corners.bottom_left.w) + .max(corners.bottom_right.w); + max_alpha == 0. + }, + } + } +} + +// impl From<(GradientDirection, Vec4, Vec4)> for Background { +// fn from(gradient: (GradientDirection, Vec4, Vec4)) -> Self { +// Self::Gradient(gradient.0, gradient.1, gradient.2) +// } +// } diff --git a/hui/src/draw.rs b/hui/src/draw.rs index 51d82b4..99f2077 100644 --- a/hui/src/draw.rs +++ b/hui/src/draw.rs @@ -1,6 +1,10 @@ //! Stuff related to tesselation and UI rendering. -use crate::{IfModified, text::{TextRenderer, FontHandle}}; +use crate::{ + rectangle::Corners, + text::{FontHandle, TextRenderer}, + IfModified +}; mod corner_radius; @@ -22,7 +26,7 @@ pub enum UiDrawCommand { ///Size in pixels size: Vec2, ///Color (RGBA) - color: Vec4, + color: Corners, ///Rounded corners rounded_corners: Option, }, @@ -181,7 +185,7 @@ impl UiDrawPlan { //lol swapper.current_mut().vertices.push(UiVertex { position: *position + *size * vec2(0.5, 0.5), - color: *color, + color: (color.bottom_left + color.bottom_right + color.top_left + color.top_right) / 4., uv: vec2(0., 0.), }); @@ -195,25 +199,25 @@ impl UiDrawPlan { //Top-right corner swapper.current_mut().vertices.push(UiVertex { position: *position + vec2(x, 1. - y) * corner.radius.top_right + vec2(size.x - corner.radius.top_right, 0.), - color: *color, + color: color.top_right, uv: vec2(0.0, 0.0), }); //Bottom-right corner swapper.current_mut().vertices.push(UiVertex { position: *position + vec2(x - 1., y) * corner.radius.bottom_right + vec2(size.x, size.y - corner.radius.bottom_right), - color: *color, + color: color.bottom_right, uv: vec2(0.0, 0.0), }); //Bottom-left corner swapper.current_mut().vertices.push(UiVertex { position: *position + vec2(1. - x, y) * corner.radius.bottom_left + vec2(0., size.y - corner.radius.bottom_left), - color: *color, + color: color.bottom_left, uv: vec2(0.0, 0.0), }); //Top-left corner swapper.current_mut().vertices.push(UiVertex { position: *position + vec2(1. - x, 1. - y) * corner.radius.top_left, - color: *color, + color: color.top_left, uv: vec2(0.0, 0.0), }); // mental illness: @@ -263,22 +267,22 @@ impl UiDrawPlan { swapper.current_mut().vertices.extend([ UiVertex { position: *position, - color: *color, + color: color.top_left, uv: vec2(0.0, 0.0), }, UiVertex { position: *position + vec2(size.x, 0.0), - color: *color, + color: color.top_right, uv: vec2(1.0, 0.0), }, UiVertex { position: *position + *size, - color: *color, + color: color.bottom_right, uv: vec2(1.0, 1.0), }, UiVertex { position: *position + vec2(0.0, size.y), - color: *color, + color: color.bottom_left, uv: vec2(0.0, 1.0), }, ]); diff --git a/hui/src/element/builtin/container.rs b/hui/src/element/builtin/container.rs index 5183063..23ce8eb 100644 --- a/hui/src/element/builtin/container.rs +++ b/hui/src/element/builtin/container.rs @@ -1,6 +1,6 @@ use glam::{Vec2, vec2, Vec4}; use crate::{ - draw::{RoundedCorners, UiDrawCommand}, element::{MeasureContext, ProcessContext, UiElement}, layout::{Alignment, Alignment2d, LayoutInfo, UiDirection, UiSize}, measure::{Hints, Response}, rectangle::{Corners, Sides} + background::Background, draw::{RoundedCorners, UiDrawCommand}, element::{MeasureContext, ProcessContext, UiElement}, layout::{Alignment, Alignment2d, LayoutInfo, UiDirection, UiSize}, measure::{Hints, Response}, rectangle::{Corners, Sides} }; // pub struct Border { @@ -9,38 +9,30 @@ use crate::{ // } ///XXX: add Order/Direction::Forward/Reverse or sth? +//TODO: clip children flag +//TODO: borders +//TODO: min/max size pub struct Container { - //TODO: min/max size - // pub min_size: (UiSize, UiSize), - // pub max_size: (UiSize, UiSize), pub size: (UiSize, UiSize), pub direction: UiDirection, pub gap: f32, pub padding: Sides, - ///Primary/secondary axis pub align: Alignment2d, - pub background: Vec4, - //TODO: borders - //pub borders: Sides>, + pub background: Background, pub corner_radius: Corners, - //TODO: clip children - //pub clip: bool, pub elements: Vec>, } impl Default for Container { fn default() -> Self { Self { - // min_size: (UiSize::Auto, UiSize::Auto), - // max_size: (UiSize::Auto, UiSize::Auto), size: (UiSize::Auto, UiSize::Auto), direction: UiDirection::Vertical, gap: 0., padding: Sides::all(0.), align: Alignment2d::default(), background: Default::default(), - //borders: Default::default(), elements: Vec::new(), corner_radius: Corners::all(0.), } @@ -69,7 +61,6 @@ impl Container { impl UiElement for Container { fn measure(&self, ctx: MeasureContext) -> Response { let mut size = Vec2::ZERO; - //if matches!(self.size.0, UiSize::Auto) || matches!(self.size.1, UiSize::Auto) { let mut leftover_gap = Vec2::ZERO; for element in &self.elements { let measure = element.measure(MeasureContext{ @@ -128,11 +119,12 @@ impl UiElement for Container { let mut position = ctx.layout.position; //background - if self.background.w > 0. { + if !self.background.is_transparent() { + let corner_colors = self.background.corners().unwrap(); ctx.draw.add(UiDrawCommand::Rectangle { position, size: ctx.measure.size, - color: self.background, + color: corner_colors, rounded_corners: (self.corner_radius.max_f32() > 0.).then_some({ RoundedCorners::from_radius(self.corner_radius) }), diff --git a/hui/src/element/builtin/progress_bar.rs b/hui/src/element/builtin/progress_bar.rs index 840138e..96b6ea5 100644 --- a/hui/src/element/builtin/progress_bar.rs +++ b/hui/src/element/builtin/progress_bar.rs @@ -71,7 +71,7 @@ impl UiElement for ProgressBar { ctx.draw.add(UiDrawCommand::Rectangle { position: ctx.layout.position, size: ctx.measure.size, - color: self.color_background, + color: Corners::all(self.color_background), rounded_corners }); } @@ -79,7 +79,7 @@ impl UiElement for ProgressBar { ctx.draw.add(UiDrawCommand::Rectangle { position: ctx.layout.position, size: ctx.measure.size * vec2(value, 1.0), - color: self.color_foreground, + color: Corners::all(self.color_foreground), rounded_corners, }); } diff --git a/hui/src/element/builtin/rect.rs b/hui/src/element/builtin/rect.rs index 1d65b2c..5e4c989 100644 --- a/hui/src/element/builtin/rect.rs +++ b/hui/src/element/builtin/rect.rs @@ -1,21 +1,23 @@ use glam::{vec2, Vec4}; use crate::{ + background::Background, draw::UiDrawCommand, element::{MeasureContext, ProcessContext, UiElement}, + layout::UiSize, measure::Response, - layout::UiSize + rectangle::Corners }; pub struct Rect { pub size: (UiSize, UiSize), - pub color: Option, + pub color: Background, } impl Default for Rect { fn default() -> Self { Self { size: (UiSize::Static(10.), UiSize::Static(10.)), - color: Some(Vec4::new(0., 0., 0., 0.5)), + color: Vec4::new(0., 0., 0., 0.5).into(), } } } @@ -41,11 +43,11 @@ impl UiElement for Rect { } fn process(&self, ctx: ProcessContext) { - if let Some(color) = self.color { + if !self.color.is_transparent() { ctx.draw.add(UiDrawCommand::Rectangle { position: ctx.layout.position, size: ctx.measure.size, - color, + color: self.color.corners().unwrap(), rounded_corners: None, }); } diff --git a/hui/src/lib.rs b/hui/src/lib.rs index de72bd4..0bcd95a 100644 --- a/hui/src/lib.rs +++ b/hui/src/lib.rs @@ -12,6 +12,7 @@ mod instance; pub mod layout; pub mod rectangle; +pub mod background; pub mod element; pub mod event; pub mod input;