New background api

This commit is contained in:
griffi-gh 2024-02-20 20:56:58 +01:00
parent bc40d4c8cc
commit ff448ed393
10 changed files with 118 additions and 51 deletions

View file

@ -77,23 +77,23 @@ fn main() {
elements: vec![ elements: vec![
Box::new(Rect { Box::new(Rect {
size: (UiSize::Fraction(0.5), UiSize::Static(30.)), 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 { Box::new(Rect {
size: (UiSize::Fraction(z / 2. + 0.5), UiSize::Static(30.)), 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() ..Default::default()
}), }),
Box::new(Rect { Box::new(Rect {
size: (UiSize::Fraction(z / 2. + 0.5), UiSize::Static(30.)), 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 { Box::new(Container {
gap: 5., gap: 5.,
padding: Sides::all(5.), padding: Sides::all(5.),
background: vec4(0., 0., 0., 0.5), background: vec4(0., 0., 0., 0.5).into(),
direction: UiDirection::Horizontal, direction: UiDirection::Horizontal,
elements: { elements: {
let mut x: Vec<Box<dyn UiElement>> = vec![]; let mut x: Vec<Box<dyn UiElement>> = vec![];
@ -101,9 +101,9 @@ fn main() {
x.push(Box::new(Rect { x.push(Box::new(Rect {
size: (UiSize::Static(50.), UiSize::Static(50.)), size: (UiSize::Static(50.), UiSize::Static(50.)),
color: if i == 1 { 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 { } 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() ..Default::default()
}), }),
Box::new(Container { Box::new(Container {
background: vec4(1., 0., 0., 1.), background: vec4(1., 0., 0., 1.).into(),
padding: Sides { padding: Sides {
top: 10., top: 10.,
bottom: 20., bottom: 20.,
@ -128,7 +128,7 @@ fn main() {
elements: vec![ elements: vec![
Box::new(Rect { Box::new(Rect {
size: (UiSize::Static(50.), UiSize::Static(50.)), 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() ..Default::default()

View file

@ -50,12 +50,12 @@ fn main() {
hui.add(Container { hui.add(Container {
align: Alignment::Center.into(), align: Alignment::Center.into(),
size: (UiSize::Fraction(1.), UiSize::Fraction(1.)), 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 { elements: vec![Box::new(Container {
gap: 5., gap: 5.,
padding: Sides::all(10.), padding: Sides::all(10.),
size: (UiSize::Static(450.), UiSize::Auto), 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.), corner_radius: Corners::all(8.),
elements: elements(|el| { elements: elements(|el| {
if instant.elapsed().as_secs_f32() < 5. { if instant.elapsed().as_secs_f32() < 5. {

View file

@ -43,7 +43,7 @@ fn main() {
elements: vec![Box::new(Container { elements: vec![Box::new(Container {
align: Alignment::Center.into(), align: Alignment::Center.into(),
size: (UiSize::Fraction(0.5), UiSize::Fraction(0.5)), 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 { corner_radius: Corners {
top_left: 10., top_left: 10.,
top_right: 20., top_right: 20.,
@ -56,7 +56,7 @@ fn main() {
direction: UiDirection::Horizontal, direction: UiDirection::Horizontal,
align: Alignment::Center.into(), align: Alignment::Center.into(),
size: (UiSize::Auto, UiSize::Auto), 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.), corner_radius: Corners::all(8.),
elements: vec![ elements: vec![
Box::new(Text { Box::new(Text {

View file

@ -44,7 +44,7 @@ fn main() {
hui.add(Container { hui.add(Container {
size: (UiSize::Fraction(1.), UiSize::Fraction(1.)), 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| { elements: elements(|elem| {
elem.add(Text { elem.add(Text {
text: "THIS LINE SHOULD BE SHARP!".into(), text: "THIS LINE SHOULD BE SHARP!".into(),
@ -68,11 +68,11 @@ fn main() {
} }
elem.add(Rect { elem.add(Rect {
size: (UiSize::Fraction(1.), UiSize::Static(10.)), size: (UiSize::Fraction(1.), UiSize::Static(10.)),
color: Some(vec4(0., 0., 1., 1.)), color: vec4(0., 0., 1., 1.).into(),
}); });
elem.add(Rect { elem.add(Rect {
size: (UiSize::Fraction(1.), UiSize::Static(10.)), size: (UiSize::Fraction(1.), UiSize::Static(10.)),
color: Some(vec4(1., 1., 0., 1.)), color: vec4(1., 1., 0., 1.).into(),
}); });
elem.add(Text { elem.add(Text {
text: "Hello, world!\nżółty liść. życie nie ma sensu i wszyscy zginemy;\nтест кирилиці їїїїїїїїїїї\njapanese text: テスト".into(), 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 { if instant.elapsed().as_secs() & 1 != 0 {
elem.add(Rect { elem.add(Rect {
size: (UiSize::Fraction(1.), UiSize::Static(10.)), size: (UiSize::Fraction(1.), UiSize::Static(10.)),
color: Some(vec4(1., 0., 0., 1.)), color: vec4(1., 0., 0., 1.).into(),
}); });
elem.add(Rect { elem.add(Rect {
size: (UiSize::Fraction(1.), UiSize::Static(10.)), 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(Spacer(100.));
elem.add(Text { elem.add(Text {

68
hui/src/background.rs Normal file
View file

@ -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<Vec4>),
}
impl From<Vec4> for Background {
fn from(color: Vec4) -> Self {
Self::Solid(color)
}
}
impl From<Option<Vec4>> for Background {
fn from(color: Option<Vec4>) -> 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<Corners<Vec4>> {
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)
// }
// }

View file

@ -1,6 +1,10 @@
//! Stuff related to tesselation and UI rendering. //! Stuff related to tesselation and UI rendering.
use crate::{IfModified, text::{TextRenderer, FontHandle}}; use crate::{
rectangle::Corners,
text::{FontHandle, TextRenderer},
IfModified
};
mod corner_radius; mod corner_radius;
@ -22,7 +26,7 @@ pub enum UiDrawCommand {
///Size in pixels ///Size in pixels
size: Vec2, size: Vec2,
///Color (RGBA) ///Color (RGBA)
color: Vec4, color: Corners<Vec4>,
///Rounded corners ///Rounded corners
rounded_corners: Option<RoundedCorners>, rounded_corners: Option<RoundedCorners>,
}, },
@ -181,7 +185,7 @@ impl UiDrawPlan {
//lol //lol
swapper.current_mut().vertices.push(UiVertex { swapper.current_mut().vertices.push(UiVertex {
position: *position + *size * vec2(0.5, 0.5), 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.), uv: vec2(0., 0.),
}); });
@ -195,25 +199,25 @@ impl UiDrawPlan {
//Top-right corner //Top-right corner
swapper.current_mut().vertices.push(UiVertex { swapper.current_mut().vertices.push(UiVertex {
position: *position + vec2(x, 1. - y) * corner.radius.top_right + vec2(size.x - corner.radius.top_right, 0.), 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), uv: vec2(0.0, 0.0),
}); });
//Bottom-right corner //Bottom-right corner
swapper.current_mut().vertices.push(UiVertex { 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), 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), uv: vec2(0.0, 0.0),
}); });
//Bottom-left corner //Bottom-left corner
swapper.current_mut().vertices.push(UiVertex { swapper.current_mut().vertices.push(UiVertex {
position: *position + vec2(1. - x, y) * corner.radius.bottom_left + vec2(0., size.y - corner.radius.bottom_left), 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), uv: vec2(0.0, 0.0),
}); });
//Top-left corner //Top-left corner
swapper.current_mut().vertices.push(UiVertex { swapper.current_mut().vertices.push(UiVertex {
position: *position + vec2(1. - x, 1. - y) * corner.radius.top_left, position: *position + vec2(1. - x, 1. - y) * corner.radius.top_left,
color: *color, color: color.top_left,
uv: vec2(0.0, 0.0), uv: vec2(0.0, 0.0),
}); });
// mental illness: // mental illness:
@ -263,22 +267,22 @@ impl UiDrawPlan {
swapper.current_mut().vertices.extend([ swapper.current_mut().vertices.extend([
UiVertex { UiVertex {
position: *position, position: *position,
color: *color, color: color.top_left,
uv: vec2(0.0, 0.0), uv: vec2(0.0, 0.0),
}, },
UiVertex { UiVertex {
position: *position + vec2(size.x, 0.0), position: *position + vec2(size.x, 0.0),
color: *color, color: color.top_right,
uv: vec2(1.0, 0.0), uv: vec2(1.0, 0.0),
}, },
UiVertex { UiVertex {
position: *position + *size, position: *position + *size,
color: *color, color: color.bottom_right,
uv: vec2(1.0, 1.0), uv: vec2(1.0, 1.0),
}, },
UiVertex { UiVertex {
position: *position + vec2(0.0, size.y), position: *position + vec2(0.0, size.y),
color: *color, color: color.bottom_left,
uv: vec2(0.0, 1.0), uv: vec2(0.0, 1.0),
}, },
]); ]);

View file

@ -1,6 +1,6 @@
use glam::{Vec2, vec2, Vec4}; use glam::{Vec2, vec2, Vec4};
use crate::{ 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 { // pub struct Border {
@ -9,38 +9,30 @@ use crate::{
// } // }
///XXX: add Order/Direction::Forward/Reverse or sth? ///XXX: add Order/Direction::Forward/Reverse or sth?
//TODO: clip children flag
//TODO: borders
//TODO: min/max size
pub struct Container { pub struct Container {
//TODO: min/max size
// pub min_size: (UiSize, UiSize),
// pub max_size: (UiSize, UiSize),
pub size: (UiSize, UiSize), pub size: (UiSize, UiSize),
pub direction: UiDirection, pub direction: UiDirection,
pub gap: f32, pub gap: f32,
pub padding: Sides<f32>, pub padding: Sides<f32>,
///Primary/secondary axis
pub align: Alignment2d, pub align: Alignment2d,
pub background: Vec4, pub background: Background,
//TODO: borders
//pub borders: Sides<Option<Border>>,
pub corner_radius: Corners<f32>, pub corner_radius: Corners<f32>,
//TODO: clip children
//pub clip: bool,
pub elements: Vec<Box<dyn UiElement>>, pub elements: Vec<Box<dyn UiElement>>,
} }
impl Default for Container { impl Default for Container {
fn default() -> Self { fn default() -> Self {
Self { Self {
// min_size: (UiSize::Auto, UiSize::Auto),
// max_size: (UiSize::Auto, UiSize::Auto),
size: (UiSize::Auto, UiSize::Auto), size: (UiSize::Auto, UiSize::Auto),
direction: UiDirection::Vertical, direction: UiDirection::Vertical,
gap: 0., gap: 0.,
padding: Sides::all(0.), padding: Sides::all(0.),
align: Alignment2d::default(), align: Alignment2d::default(),
background: Default::default(), background: Default::default(),
//borders: Default::default(),
elements: Vec::new(), elements: Vec::new(),
corner_radius: Corners::all(0.), corner_radius: Corners::all(0.),
} }
@ -69,7 +61,6 @@ impl Container {
impl UiElement for Container { impl UiElement for Container {
fn measure(&self, ctx: MeasureContext) -> Response { fn measure(&self, ctx: MeasureContext) -> Response {
let mut size = Vec2::ZERO; let mut size = Vec2::ZERO;
//if matches!(self.size.0, UiSize::Auto) || matches!(self.size.1, UiSize::Auto) {
let mut leftover_gap = Vec2::ZERO; let mut leftover_gap = Vec2::ZERO;
for element in &self.elements { for element in &self.elements {
let measure = element.measure(MeasureContext{ let measure = element.measure(MeasureContext{
@ -128,11 +119,12 @@ impl UiElement for Container {
let mut position = ctx.layout.position; let mut position = ctx.layout.position;
//background //background
if self.background.w > 0. { if !self.background.is_transparent() {
let corner_colors = self.background.corners().unwrap();
ctx.draw.add(UiDrawCommand::Rectangle { ctx.draw.add(UiDrawCommand::Rectangle {
position, position,
size: ctx.measure.size, size: ctx.measure.size,
color: self.background, color: corner_colors,
rounded_corners: (self.corner_radius.max_f32() > 0.).then_some({ rounded_corners: (self.corner_radius.max_f32() > 0.).then_some({
RoundedCorners::from_radius(self.corner_radius) RoundedCorners::from_radius(self.corner_radius)
}), }),

View file

@ -71,7 +71,7 @@ impl UiElement for ProgressBar {
ctx.draw.add(UiDrawCommand::Rectangle { ctx.draw.add(UiDrawCommand::Rectangle {
position: ctx.layout.position, position: ctx.layout.position,
size: ctx.measure.size, size: ctx.measure.size,
color: self.color_background, color: Corners::all(self.color_background),
rounded_corners rounded_corners
}); });
} }
@ -79,7 +79,7 @@ impl UiElement for ProgressBar {
ctx.draw.add(UiDrawCommand::Rectangle { ctx.draw.add(UiDrawCommand::Rectangle {
position: ctx.layout.position, position: ctx.layout.position,
size: ctx.measure.size * vec2(value, 1.0), size: ctx.measure.size * vec2(value, 1.0),
color: self.color_foreground, color: Corners::all(self.color_foreground),
rounded_corners, rounded_corners,
}); });
} }

View file

@ -1,21 +1,23 @@
use glam::{vec2, Vec4}; use glam::{vec2, Vec4};
use crate::{ use crate::{
background::Background,
draw::UiDrawCommand, draw::UiDrawCommand,
element::{MeasureContext, ProcessContext, UiElement}, element::{MeasureContext, ProcessContext, UiElement},
layout::UiSize,
measure::Response, measure::Response,
layout::UiSize rectangle::Corners
}; };
pub struct Rect { pub struct Rect {
pub size: (UiSize, UiSize), pub size: (UiSize, UiSize),
pub color: Option<Vec4>, pub color: Background,
} }
impl Default for Rect { impl Default for Rect {
fn default() -> Self { fn default() -> Self {
Self { Self {
size: (UiSize::Static(10.), UiSize::Static(10.)), 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) { fn process(&self, ctx: ProcessContext) {
if let Some(color) = self.color { if !self.color.is_transparent() {
ctx.draw.add(UiDrawCommand::Rectangle { ctx.draw.add(UiDrawCommand::Rectangle {
position: ctx.layout.position, position: ctx.layout.position,
size: ctx.measure.size, size: ctx.measure.size,
color, color: self.color.corners().unwrap(),
rounded_corners: None, rounded_corners: None,
}); });
} }

View file

@ -12,6 +12,7 @@
mod instance; mod instance;
pub mod layout; pub mod layout;
pub mod rectangle; pub mod rectangle;
pub mod background;
pub mod element; pub mod element;
pub mod event; pub mod event;
pub mod input; pub mod input;