mirror of
https://github.com/griffi-gh/hUI.git
synced 2024-11-22 07:08:42 -06:00
refactor
This commit is contained in:
parent
778ae751e7
commit
ad0e6fd7e6
54
hui-examples/boilerplate.rs
Normal file
54
hui-examples/boilerplate.rs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
use glam::{UVec2, Vec2};
|
||||||
|
use glium::{backend::glutin::SimpleWindowBuilder, Surface};
|
||||||
|
use winit::{
|
||||||
|
event::{Event, WindowEvent},
|
||||||
|
event_loop::{EventLoopBuilder, ControlFlow}
|
||||||
|
};
|
||||||
|
use hui::UiInstance;
|
||||||
|
use hui_glium::GliumUiRenderer;
|
||||||
|
|
||||||
|
/// Generates a `main` function that initializes glium renderer, `UiInstance`, and runs the event loop.
|
||||||
|
macro_rules! ui_main {
|
||||||
|
($closure: expr) => {
|
||||||
|
fn main() {
|
||||||
|
$crate::boilerplate::ui($closure);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initializes glium renderer, `UiInstance`, and runs the event loop.
|
||||||
|
pub fn ui(mut x: impl FnMut(&mut UiInstance, Vec2)) {
|
||||||
|
kubi_logging::init();
|
||||||
|
|
||||||
|
let event_loop = EventLoopBuilder::new().build().unwrap();
|
||||||
|
let (_window, display) = SimpleWindowBuilder::new().build(&event_loop);
|
||||||
|
|
||||||
|
let mut hui = UiInstance::new();
|
||||||
|
let mut backend = GliumUiRenderer::new(&display);
|
||||||
|
|
||||||
|
event_loop.run(|event, window_target| {
|
||||||
|
window_target.set_control_flow(ControlFlow::Poll);
|
||||||
|
match event {
|
||||||
|
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
|
||||||
|
window_target.exit();
|
||||||
|
},
|
||||||
|
Event::AboutToWait => {
|
||||||
|
let mut frame = display.draw();
|
||||||
|
frame.clear_color_srgb(0.5, 0.5, 0.5, 0.);
|
||||||
|
|
||||||
|
hui.begin();
|
||||||
|
|
||||||
|
let size = UVec2::from(display.get_framebuffer_dimensions()).as_vec2();
|
||||||
|
x(&mut hui, size);
|
||||||
|
|
||||||
|
hui.end();
|
||||||
|
|
||||||
|
backend.update(&hui);
|
||||||
|
backend.draw(&mut frame, size);
|
||||||
|
|
||||||
|
frame.finish().unwrap();
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}).unwrap();
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
//WARNING: THIS EXAMPLE IS EXTREMELY OUTDATED AND USES DEPRECATED API
|
||||||
|
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use glam::{UVec2, vec4};
|
use glam::{UVec2, vec4};
|
||||||
use glium::{backend::glutin::SimpleWindowBuilder, Surface};
|
use glium::{backend::glutin::SimpleWindowBuilder, Surface};
|
||||||
|
@ -7,7 +9,7 @@ use winit::{
|
||||||
};
|
};
|
||||||
use hui::{
|
use hui::{
|
||||||
element::{
|
element::{
|
||||||
container::Container, progress_bar::ProgressBar, rect::Rect, ElementList, UiElement
|
container::Container, progress_bar::ProgressBar, fill_rect::FillRect, ElementList, UiElement
|
||||||
}, layout::{Alignment, UiDirection, Size}, rectangle::{Corners, Sides}, UiInstance
|
}, layout::{Alignment, UiDirection, Size}, rectangle::{Corners, Sides}, UiInstance
|
||||||
};
|
};
|
||||||
use hui_glium::GliumUiRenderer;
|
use hui_glium::GliumUiRenderer;
|
||||||
|
@ -69,23 +71,26 @@ fn main() {
|
||||||
padding: Sides::all(5.),
|
padding: Sides::all(5.),
|
||||||
gap: 10.,
|
gap: 10.,
|
||||||
children: ElementList(vec![
|
children: ElementList(vec![
|
||||||
Box::new(Rect {
|
Box::new(FillRect {
|
||||||
size: (Size::Fraction(0.5), Size::Static(30.)),
|
size: (Size::Fraction(0.5), Size::Static(30.)).into(),
|
||||||
color: vec4(0.75, 0., 0., 1.).into()
|
background: vec4(0.75, 0., 0., 1.).into(),
|
||||||
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
Box::new(Rect {
|
Box::new(FillRect {
|
||||||
size: (Size::Fraction(z / 2. + 0.5), Size::Static(30.)),
|
size: (Size::Fraction(z / 2. + 0.5), Size::Static(30.)).into(),
|
||||||
color: Corners::left_right(
|
background: Corners::left_right(
|
||||||
vec4(1., 0., 0., 1.),
|
vec4(1., 0., 0., 1.),
|
||||||
vec4(0., 1., 0., 1.)
|
vec4(0., 1., 0., 1.)
|
||||||
).into(),
|
).into(),
|
||||||
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
Box::new(Rect {
|
Box::new(FillRect {
|
||||||
size: (Size::Fraction(z / 2. + 0.5), Size::Static(30.)),
|
size: (Size::Fraction(z / 2. + 0.5), Size::Static(30.)).into(),
|
||||||
color: vec4(0., 0.75, 0., 1.).into()
|
background: vec4(0., 0.75, 0., 1.).into(),
|
||||||
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
Box::new(Container {
|
Box::new(Container {
|
||||||
gap: 5.,
|
gap: 5.,
|
||||||
|
@ -95,13 +100,14 @@ fn main() {
|
||||||
children: {
|
children: {
|
||||||
let mut x: Vec<Box<dyn UiElement>> = vec![];
|
let mut x: Vec<Box<dyn UiElement>> = vec![];
|
||||||
for i in 0..10 {
|
for i in 0..10 {
|
||||||
x.push(Box::new(Rect {
|
x.push(Box::new(FillRect {
|
||||||
size: (Size::Static(50.), Size::Static(50.)),
|
size: (Size::Static(50.), Size::Static(50.)).into(),
|
||||||
color: if i == 1 {
|
background: if i == 1 {
|
||||||
vec4(0.75, 0.75, 0.75, 0.75).into()
|
vec4(0.75, 0.75, 0.75, 0.75).into()
|
||||||
} else {
|
} else {
|
||||||
vec4(0.5, 0.5, 0.5, 0.75).into()
|
vec4(0.5, 0.5, 0.5, 0.75).into()
|
||||||
}
|
},
|
||||||
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
ElementList(x)
|
ElementList(x)
|
||||||
|
@ -123,9 +129,10 @@ fn main() {
|
||||||
bottom_right: 0.,
|
bottom_right: 0.,
|
||||||
},
|
},
|
||||||
children: ElementList(vec![
|
children: ElementList(vec![
|
||||||
Box::new(Rect {
|
Box::new(FillRect {
|
||||||
size: (Size::Static(50.), Size::Static(50.)),
|
size: (Size::Static(50.), Size::Static(50.)).into(),
|
||||||
color: vec4(1., 1., 1., 0.75).into()
|
background: vec4(1., 1., 1., 0.75).into(),
|
||||||
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
use glam::UVec2;
|
|
||||||
use glium::{backend::glutin::SimpleWindowBuilder, Surface};
|
|
||||||
use winit::{
|
|
||||||
event::{Event, WindowEvent},
|
|
||||||
event_loop::{EventLoopBuilder, ControlFlow}
|
|
||||||
};
|
|
||||||
use hui::{
|
|
||||||
UiInstance, color, size,
|
|
||||||
layout::Alignment,
|
|
||||||
element::{
|
|
||||||
container::Container, text::Text, UiElementExt
|
|
||||||
},
|
|
||||||
};
|
|
||||||
use hui_glium::GliumUiRenderer;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
kubi_logging::init();
|
|
||||||
|
|
||||||
let event_loop = EventLoopBuilder::new().build().unwrap();
|
|
||||||
let (_window, display) = SimpleWindowBuilder::new().build(&event_loop);
|
|
||||||
|
|
||||||
let mut hui = UiInstance::new();
|
|
||||||
let mut backend = GliumUiRenderer::new(&display);
|
|
||||||
|
|
||||||
event_loop.run(|event, window_target| {
|
|
||||||
window_target.set_control_flow(ControlFlow::Poll);
|
|
||||||
match event {
|
|
||||||
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
|
|
||||||
window_target.exit();
|
|
||||||
},
|
|
||||||
Event::AboutToWait => {
|
|
||||||
let mut frame = display.draw();
|
|
||||||
frame.clear_color_srgb(0.5, 0.5, 0.5, 0.);
|
|
||||||
|
|
||||||
let resolution = UVec2::from(display.get_framebuffer_dimensions()).as_vec2();
|
|
||||||
|
|
||||||
hui.begin();
|
|
||||||
|
|
||||||
Container::default()
|
|
||||||
.with_size(size!(100%, 50%))
|
|
||||||
.with_align(Alignment::Center)
|
|
||||||
.with_padding(5.)
|
|
||||||
.with_gap(10.)
|
|
||||||
.with_corner_radius(10.)
|
|
||||||
.with_background(color::WHITE)
|
|
||||||
.with_children(|ui| {
|
|
||||||
Text::default()
|
|
||||||
.with_text("Hello, world")
|
|
||||||
.with_text_size(100)
|
|
||||||
.with_color(color::BLACK)
|
|
||||||
.add_child(ui);
|
|
||||||
Container::default()
|
|
||||||
.with_padding((10., 20.))
|
|
||||||
.with_corner_radius((2.5, 30., 2.5, 2.5))
|
|
||||||
.with_background(color::DARK_RED)
|
|
||||||
.with_children(|ui| {
|
|
||||||
Text::default()
|
|
||||||
.with_text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
|
|
||||||
.with_text_size(24)
|
|
||||||
.add_child(ui);
|
|
||||||
})
|
|
||||||
.add_child(ui);
|
|
||||||
})
|
|
||||||
.add_root(&mut hui, resolution);
|
|
||||||
|
|
||||||
hui.end();
|
|
||||||
|
|
||||||
backend.update(&hui);
|
|
||||||
backend.draw(&mut frame, resolution);
|
|
||||||
|
|
||||||
frame.finish().unwrap();
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}).unwrap();
|
|
||||||
}
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//WARNING: THIS EXAMPLE IS EXTREMELY OUTDATED AND USES DEPRECATED API
|
||||||
|
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use glam::{UVec2, vec4};
|
use glam::{UVec2, vec4};
|
||||||
use glium::{backend::glutin::SimpleWindowBuilder, Surface};
|
use glium::{backend::glutin::SimpleWindowBuilder, Surface};
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//WARNING: THIS EXAMPLE IS EXTREMELY OUTDATED AND USES DEPRECATED API
|
||||||
|
|
||||||
use glam::{vec4, UVec2};
|
use glam::{vec4, UVec2};
|
||||||
use glium::{backend::glutin::SimpleWindowBuilder, Surface};
|
use glium::{backend::glutin::SimpleWindowBuilder, Surface};
|
||||||
use winit::{
|
use winit::{
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//WARNING: THIS EXAMPLE IS EXTREMELY OUTDATED AND USES DEPRECATED API
|
||||||
|
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use glam::{UVec2, vec4};
|
use glam::{UVec2, vec4};
|
||||||
use glium::{backend::glutin::SimpleWindowBuilder, Surface};
|
use glium::{backend::glutin::SimpleWindowBuilder, Surface};
|
||||||
|
@ -7,7 +9,7 @@ use winit::{
|
||||||
};
|
};
|
||||||
use hui::{
|
use hui::{
|
||||||
element::{
|
element::{
|
||||||
container::Container, rect::Rect, spacer::Spacer, text::Text, ElementList
|
container::Container, fill_rect::FillRect, spacer::Spacer, text::Text, ElementList
|
||||||
}, layout::Size, UiInstance
|
}, layout::Size, UiInstance
|
||||||
};
|
};
|
||||||
use hui_glium::GliumUiRenderer;
|
use hui_glium::GliumUiRenderer;
|
||||||
|
@ -69,13 +71,15 @@ fn main() {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
elem.push(Box::new(Rect {
|
elem.push(Box::new(FillRect {
|
||||||
size: (Size::Fraction(1.), Size::Static(10.)),
|
size: (Size::Fraction(1.), Size::Static(10.)).into(),
|
||||||
color: vec4(0., 0., 1., 1.).into(),
|
background: vec4(0., 0., 1., 1.).into(),
|
||||||
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
elem.push(Box::new(Rect {
|
elem.push(Box::new(FillRect {
|
||||||
size: (Size::Fraction(1.), Size::Static(10.)),
|
size: (Size::Fraction(1.), Size::Static(10.)).into(),
|
||||||
color: vec4(1., 1., 0., 1.).into(),
|
background: vec4(1., 1., 0., 1.).into(),
|
||||||
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
elem.push(Box::new(Text {
|
elem.push(Box::new(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(),
|
||||||
|
@ -84,13 +88,15 @@ fn main() {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
if instant.elapsed().as_secs() & 1 != 0 {
|
if instant.elapsed().as_secs() & 1 != 0 {
|
||||||
elem.push(Box::new(Rect {
|
elem.push(Box::new(FillRect {
|
||||||
size: (Size::Fraction(1.), Size::Static(10.)),
|
size: (Size::Fraction(1.), Size::Static(10.)).into(),
|
||||||
color: vec4(1., 0., 0., 1.).into(),
|
background: vec4(1., 0., 0., 1.).into(),
|
||||||
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
elem.push(Box::new(Rect {
|
elem.push(Box::new(FillRect {
|
||||||
size: (Size::Fraction(1.), Size::Static(10.)),
|
size: (Size::Fraction(1.), Size::Static(10.)).into(),
|
||||||
color: vec4(0., 0., 0., 1.).into(),
|
background: vec4(0., 0., 0., 1.).into(),
|
||||||
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
elem.push(Box::new(Spacer(100.)));
|
elem.push(Box::new(Spacer(100.)));
|
||||||
elem.push(Box::new(Text {
|
elem.push(Box::new(Text {
|
||||||
|
|
38
hui-examples/examples/ui_test.rs
Normal file
38
hui-examples/examples/ui_test.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
use hui::{
|
||||||
|
color, size,
|
||||||
|
layout::Alignment,
|
||||||
|
element::{UiElementExt, container::Container, text::Text},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[path = "../boilerplate.rs"]
|
||||||
|
#[macro_use]
|
||||||
|
mod boilerplate;
|
||||||
|
|
||||||
|
ui_main!(|ui, size| {
|
||||||
|
Container::default()
|
||||||
|
.with_size(size!(100%, 50%))
|
||||||
|
.with_align(Alignment::Center)
|
||||||
|
.with_padding(5.)
|
||||||
|
.with_gap(10.)
|
||||||
|
.with_corner_radius(10.)
|
||||||
|
.with_background(color::WHITE)
|
||||||
|
.with_children(|ui| {
|
||||||
|
Text::default()
|
||||||
|
.with_text("Hello, world")
|
||||||
|
.with_text_size(100)
|
||||||
|
.with_color(color::BLACK)
|
||||||
|
.add_child(ui);
|
||||||
|
Container::default()
|
||||||
|
.with_padding((10., 20.))
|
||||||
|
.with_corner_radius((2.5, 30., 2.5, 2.5))
|
||||||
|
.with_background(color::DARK_RED)
|
||||||
|
.with_children(|ui| {
|
||||||
|
Text::default()
|
||||||
|
.with_text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
|
||||||
|
.with_text_size(24)
|
||||||
|
.add_child(ui);
|
||||||
|
})
|
||||||
|
.add_child(ui);
|
||||||
|
})
|
||||||
|
.add_root(ui, size);
|
||||||
|
});
|
|
@ -26,7 +26,7 @@ nz = "0.3"
|
||||||
document-features = "0.2"
|
document-features = "0.2"
|
||||||
derive_setters = "0.1"
|
derive_setters = "0.1"
|
||||||
#smallvec = "1.13"
|
#smallvec = "1.13"
|
||||||
#tinyset = "0.4"
|
tinyset = "0.4"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["builtin_elements", "builtin_font", "pixel_perfect_text"]
|
default = ["builtin_elements", "builtin_font", "pixel_perfect_text"]
|
||||||
|
|
|
@ -9,27 +9,28 @@ use crate::rectangle::Corners;
|
||||||
// pub texture: Option<TextureH>
|
// pub texture: Option<TextureH>
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
//TODO: move this into the color module?
|
||||||
#[derive(Clone, Copy, Default, Debug, PartialEq)]
|
#[derive(Clone, Copy, Default, Debug, PartialEq)]
|
||||||
pub enum BackgroundColor {
|
pub enum RectBackground {
|
||||||
#[default]
|
#[default]
|
||||||
Transparent,
|
Transparent,
|
||||||
Solid(Vec4),
|
Solid(Vec4),
|
||||||
Gradient(Corners<Vec4>),
|
Gradient(Corners<Vec4>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(f32, f32, f32, f32)> for BackgroundColor {
|
impl From<(f32, f32, f32, f32)> for RectBackground {
|
||||||
fn from(color: (f32, f32, f32, f32)) -> Self {
|
fn from(color: (f32, f32, f32, f32)) -> Self {
|
||||||
Self::Solid(vec4(color.0, color.1, color.2, color.3))
|
Self::Solid(vec4(color.0, color.1, color.2, color.3))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Corners<Vec4>> for BackgroundColor {
|
impl From<Corners<Vec4>> for RectBackground {
|
||||||
fn from(corners: Corners<Vec4>) -> Self {
|
fn from(corners: Corners<Vec4>) -> Self {
|
||||||
Self::Gradient(corners)
|
Self::Gradient(corners)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Option<Vec4>> for BackgroundColor {
|
impl From<Option<Vec4>> for RectBackground {
|
||||||
fn from(color: Option<Vec4>) -> Self {
|
fn from(color: Option<Vec4>) -> Self {
|
||||||
match color {
|
match color {
|
||||||
Some(color) => Self::Solid(color),
|
Some(color) => Self::Solid(color),
|
||||||
|
@ -38,19 +39,19 @@ impl From<Option<Vec4>> for BackgroundColor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec4> for BackgroundColor {
|
impl From<Vec4> for RectBackground {
|
||||||
fn from(color: Vec4) -> Self {
|
fn from(color: Vec4) -> Self {
|
||||||
Self::Solid(color)
|
Self::Solid(color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(f32, f32, f32)> for BackgroundColor {
|
impl From<(f32, f32, f32)> for RectBackground {
|
||||||
fn from(color: (f32, f32, f32)) -> Self {
|
fn from(color: (f32, f32, f32)) -> Self {
|
||||||
Self::Solid(vec4(color.0, color.1, color.2, 1.))
|
Self::Solid(vec4(color.0, color.1, color.2, 1.))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Corners<Vec3>> for BackgroundColor {
|
impl From<Corners<Vec3>> for RectBackground {
|
||||||
fn from(corners: Corners<Vec3>) -> Self {
|
fn from(corners: Corners<Vec3>) -> Self {
|
||||||
Self::Gradient(Corners {
|
Self::Gradient(Corners {
|
||||||
top_left: corners.top_left.extend(1.),
|
top_left: corners.top_left.extend(1.),
|
||||||
|
@ -61,7 +62,7 @@ impl From<Corners<Vec3>> for BackgroundColor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Option<Vec3>> for BackgroundColor {
|
impl From<Option<Vec3>> for RectBackground {
|
||||||
fn from(color: Option<Vec3>) -> Self {
|
fn from(color: Option<Vec3>) -> Self {
|
||||||
match color {
|
match color {
|
||||||
Some(color) => Self::Solid(color.extend(1.)),
|
Some(color) => Self::Solid(color.extend(1.)),
|
||||||
|
@ -70,13 +71,13 @@ impl From<Option<Vec3>> for BackgroundColor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec3> for BackgroundColor {
|
impl From<Vec3> for RectBackground {
|
||||||
fn from(color: Vec3) -> Self {
|
fn from(color: Vec3) -> Self {
|
||||||
Self::Solid(color.extend(1.))
|
Self::Solid(color.extend(1.))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackgroundColor {
|
impl RectBackground {
|
||||||
/// Currently, never returns None.\
|
/// Currently, never returns None.\
|
||||||
/// `Option` has been added in preparation for future changes.\
|
/// `Option` has been added in preparation for future changes.\
|
||||||
/// (`Background::Texture` etc)
|
/// (`Background::Texture` etc)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
pub mod container;
|
pub mod container;
|
||||||
|
|
||||||
#[cfg(feature = "builtin_elements")]
|
#[cfg(feature = "builtin_elements")]
|
||||||
pub mod rect;
|
pub mod fill_rect;
|
||||||
|
|
||||||
#[cfg(feature = "builtin_elements")]
|
#[cfg(feature = "builtin_elements")]
|
||||||
pub mod spacer;
|
pub mod spacer;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use derive_setters::Setters;
|
use derive_setters::Setters;
|
||||||
use glam::{Vec2, vec2};
|
use glam::{Vec2, vec2};
|
||||||
use crate::{
|
use crate::{
|
||||||
background::BackgroundColor,
|
background::RectBackground,
|
||||||
draw::{RoundedCorners, UiDrawCommand},
|
draw::{RoundedCorners, UiDrawCommand},
|
||||||
element::{ElementList, MeasureContext, ProcessContext, UiElement},
|
element::{ElementList, MeasureContext, ProcessContext, UiElement},
|
||||||
layout::{Alignment, Alignment2d, LayoutInfo, UiDirection, Size, Size2d},
|
layout::{Alignment, Alignment2d, LayoutInfo, UiDirection, Size, Size2d},
|
||||||
|
@ -31,7 +31,7 @@ pub struct Container {
|
||||||
#[setters(into)]
|
#[setters(into)]
|
||||||
pub align: Alignment2d,
|
pub align: Alignment2d,
|
||||||
#[setters(into)]
|
#[setters(into)]
|
||||||
pub background: BackgroundColor,
|
pub background: RectBackground,
|
||||||
#[setters(into)]
|
#[setters(into)]
|
||||||
pub corner_radius: Corners<f32>,
|
pub corner_radius: Corners<f32>,
|
||||||
#[setters(skip)]
|
#[setters(skip)]
|
||||||
|
|
75
hui/src/element/builtin/fill_rect.rs
Normal file
75
hui/src/element/builtin/fill_rect.rs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
//! Simple filled rectangle with the specified size, background and corner radius
|
||||||
|
|
||||||
|
use derive_setters::Setters;
|
||||||
|
use glam::{vec2, Vec4};
|
||||||
|
use crate::{
|
||||||
|
background::RectBackground,
|
||||||
|
draw::{UiDrawCommand, RoundedCorners},
|
||||||
|
element::{UiElement, MeasureContext, ProcessContext},
|
||||||
|
layout::{Size, Size2d},
|
||||||
|
measure::Response,
|
||||||
|
rectangle::Corners,
|
||||||
|
size,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Simple filled rectangle with the specified size, background, and corner radius
|
||||||
|
#[derive(Debug, Clone, Copy, Setters)]
|
||||||
|
#[setters(prefix = "with_")]
|
||||||
|
pub struct FillRect {
|
||||||
|
/// Size of the rectangle
|
||||||
|
#[setters(into)]
|
||||||
|
pub size: Size2d,
|
||||||
|
|
||||||
|
/// Background color of the rectangle
|
||||||
|
#[setters(into)]
|
||||||
|
pub background: RectBackground,
|
||||||
|
|
||||||
|
/// Corner radius of the rectangle
|
||||||
|
#[setters(into)]
|
||||||
|
pub corner_radius: Corners<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FillRect {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
size: size!(10, 10),
|
||||||
|
background: Vec4::new(0., 0., 0., 0.5).into(),
|
||||||
|
corner_radius: Corners::all(0.),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UiElement for FillRect {
|
||||||
|
fn measure(&self, ctx: MeasureContext) -> Response {
|
||||||
|
Response {
|
||||||
|
size: vec2(
|
||||||
|
match self.size.width {
|
||||||
|
Size::Auto => ctx.layout.max_size.x,
|
||||||
|
Size::Fraction(percentage) => ctx.layout.max_size.x * percentage,
|
||||||
|
Size::Static(pixels) => pixels,
|
||||||
|
},
|
||||||
|
match self.size.height {
|
||||||
|
Size::Auto => ctx.layout.max_size.y,
|
||||||
|
Size::Fraction(percentage) => ctx.layout.max_size.y * percentage,
|
||||||
|
Size::Static(pixels) => pixels,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
hints: Default::default(),
|
||||||
|
user_data: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&self, ctx: ProcessContext) {
|
||||||
|
if !self.background.is_transparent() {
|
||||||
|
ctx.draw.add(UiDrawCommand::Rectangle {
|
||||||
|
position: ctx.layout.position,
|
||||||
|
size: ctx.measure.size,
|
||||||
|
color: self.background.corners().unwrap(),
|
||||||
|
texture: None,
|
||||||
|
rounded_corners: (self.corner_radius.max_f32() > 0.).then_some({
|
||||||
|
RoundedCorners::from_radius(self.corner_radius)
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,25 @@
|
||||||
use glam::{vec2, Vec4, vec4};
|
use derive_setters::Setters;
|
||||||
|
use glam::{vec2, vec4};
|
||||||
use crate::{
|
use crate::{
|
||||||
draw::{RoundedCorners, UiDrawCommand}, element::{MeasureContext, ProcessContext, UiElement}, layout::Size, measure::Response, rectangle::Corners
|
background::RectBackground,
|
||||||
|
draw::{RoundedCorners, UiDrawCommand},
|
||||||
|
element::{MeasureContext, ProcessContext, UiElement},
|
||||||
|
layout::{Size, Size2d},
|
||||||
|
measure::Response,
|
||||||
|
rectangle::Corners
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, Setters)]
|
||||||
|
#[setters(prefix = "with_")]
|
||||||
pub struct ProgressBar {
|
pub struct ProgressBar {
|
||||||
pub size: (Size, Size),
|
|
||||||
pub value: f32,
|
pub value: f32,
|
||||||
pub color_foreground: Vec4,
|
#[setters(into)]
|
||||||
pub color_background: Vec4,
|
pub size: Size2d,
|
||||||
|
#[setters(into)]
|
||||||
|
pub foreground: RectBackground,
|
||||||
|
#[setters(into)]
|
||||||
|
pub background: RectBackground,
|
||||||
|
#[setters(into)]
|
||||||
pub corner_radius: Corners<f32>,
|
pub corner_radius: Corners<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,10 +30,10 @@ impl ProgressBar {
|
||||||
impl Default for ProgressBar {
|
impl Default for ProgressBar {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
size: (Size::Auto, Size::Auto),
|
|
||||||
value: 0.,
|
value: 0.,
|
||||||
color_foreground: vec4(0.0, 0.0, 1.0, 1.0),
|
size: Size::Auto.into(),
|
||||||
color_background: vec4(0.0, 0.0, 0.0, 1.0),
|
foreground: vec4(0.0, 0.0, 1.0, 1.0).into(),
|
||||||
|
background: vec4(0.0, 0.0, 0.0, 1.0).into(),
|
||||||
corner_radius: Corners::all(0.),
|
corner_radius: Corners::all(0.),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,12 +45,12 @@ impl UiElement for ProgressBar {
|
||||||
fn measure(&self, ctx: MeasureContext) -> Response {
|
fn measure(&self, ctx: MeasureContext) -> Response {
|
||||||
Response {
|
Response {
|
||||||
size: vec2(
|
size: vec2(
|
||||||
match self.size.0 {
|
match self.size.width {
|
||||||
Size::Auto => ctx.layout.max_size.x.max(300.),
|
Size::Auto => ctx.layout.max_size.x.max(300.),
|
||||||
Size::Fraction(p) => ctx.layout.max_size.x * p,
|
Size::Fraction(p) => ctx.layout.max_size.x * p,
|
||||||
Size::Static(p) => p,
|
Size::Static(p) => p,
|
||||||
},
|
},
|
||||||
match self.size.1 {
|
match self.size.height {
|
||||||
Size::Auto => Self::DEFAULT_HEIGHT,
|
Size::Auto => Self::DEFAULT_HEIGHT,
|
||||||
Size::Fraction(p) => ctx.layout.max_size.y * p,
|
Size::Fraction(p) => ctx.layout.max_size.y * p,
|
||||||
Size::Static(p) => p,
|
Size::Static(p) => p,
|
||||||
|
@ -71,7 +82,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: Corners::all(self.color_background),
|
color: self.background.corners().unwrap(),
|
||||||
texture: None,
|
texture: None,
|
||||||
rounded_corners
|
rounded_corners
|
||||||
});
|
});
|
||||||
|
@ -80,7 +91,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: Corners::all(self.color_foreground),
|
color: self.foreground.corners().unwrap(),
|
||||||
texture: None,
|
texture: None,
|
||||||
rounded_corners,
|
rounded_corners,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
use glam::{vec2, Vec4};
|
|
||||||
use crate::{
|
|
||||||
background::BackgroundColor,
|
|
||||||
draw::UiDrawCommand,
|
|
||||||
element::{MeasureContext, ProcessContext, UiElement},
|
|
||||||
layout::Size,
|
|
||||||
measure::Response
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct Rect {
|
|
||||||
pub size: (Size, Size),
|
|
||||||
pub color: BackgroundColor,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Rect {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
size: (Size::Static(10.), Size::Static(10.)),
|
|
||||||
color: Vec4::new(0., 0., 0., 0.5).into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UiElement for Rect {
|
|
||||||
fn measure(&self, ctx: MeasureContext) -> Response {
|
|
||||||
Response {
|
|
||||||
size: vec2(
|
|
||||||
match self.size.0 {
|
|
||||||
Size::Auto => ctx.layout.max_size.x,
|
|
||||||
Size::Fraction(percentage) => ctx.layout.max_size.x * percentage,
|
|
||||||
Size::Static(pixels) => pixels,
|
|
||||||
},
|
|
||||||
match self.size.1 {
|
|
||||||
Size::Auto => ctx.layout.max_size.y,
|
|
||||||
Size::Fraction(percentage) => ctx.layout.max_size.y * percentage,
|
|
||||||
Size::Static(pixels) => pixels,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
hints: Default::default(),
|
|
||||||
user_data: None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process(&self, ctx: ProcessContext) {
|
|
||||||
if !self.color.is_transparent() {
|
|
||||||
ctx.draw.add(UiDrawCommand::Rectangle {
|
|
||||||
position: ctx.layout.position,
|
|
||||||
size: ctx.measure.size,
|
|
||||||
color: self.color.corners().unwrap(),
|
|
||||||
texture: None,
|
|
||||||
rounded_corners: None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Adds spacing between elements in a layout
|
||||||
|
|
||||||
use glam::vec2;
|
use glam::vec2;
|
||||||
use crate::{
|
use crate::{
|
||||||
element::{MeasureContext, ProcessContext, UiElement},
|
element::{MeasureContext, ProcessContext, UiElement},
|
||||||
|
@ -5,6 +7,8 @@ use crate::{
|
||||||
layout::UiDirection
|
layout::UiDirection
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Adds spacing between elements in a layout\
|
||||||
|
/// (depending on the current layout direction)
|
||||||
pub struct Spacer(pub f32);
|
pub struct Spacer(pub f32);
|
||||||
|
|
||||||
impl Default for Spacer {
|
impl Default for Spacer {
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::hash::{Hash, Hasher};
|
||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use nohash_hasher::BuildNoHashHasher;
|
use nohash_hasher::BuildNoHashHasher;
|
||||||
|
use tinyset::{SetU32, SetUsize};
|
||||||
use crate::rectangle::Rect;
|
use crate::rectangle::Rect;
|
||||||
|
|
||||||
/// Represents a mouse button.
|
/// Represents a mouse button.
|
||||||
|
@ -110,6 +111,15 @@ pub(crate) enum Pointer {
|
||||||
TouchFinger(TouchFinger),
|
TouchFinger(TouchFinger),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Pointer {
|
||||||
|
pub fn current_position(&self) -> Vec2 {
|
||||||
|
match self {
|
||||||
|
Pointer::MousePointer(mouse) => mouse.current_position,
|
||||||
|
Pointer::TouchFinger(touch) => touch.current_position,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ActiveMouseButton {
|
impl ActiveMouseButton {
|
||||||
/// Check if the pointer (mouse or touch) was just pressed\
|
/// Check if the pointer (mouse or touch) was just pressed\
|
||||||
/// (i.e. it was not pressed in the previous frame, but is pressed now)
|
/// (i.e. it was not pressed in the previous frame, but is pressed now)
|
||||||
|
@ -128,8 +138,38 @@ impl ActiveMouseButton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PointerQuery<'a> {
|
||||||
|
pointers: &'a [Pointer],
|
||||||
|
/// Set of pointer IDs to filter **out**
|
||||||
|
filter_out: SetUsize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PointerQuery<'a> {
|
||||||
|
fn new(pointers: &'a [Pointer]) -> Self {
|
||||||
|
Self {
|
||||||
|
pointers,
|
||||||
|
filter_out: SetUsize::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Filter pointers that are *currently* located within the specified rectangle
|
||||||
|
pub fn within_rect(&mut self, rect: Rect) -> &mut Self {
|
||||||
|
for (idx, pointer) in self.pointers.iter().enumerate() {
|
||||||
|
if !rect.contains_point(pointer.current_position()) {
|
||||||
|
self.filter_out.insert(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if any pointers matched the filter
|
||||||
|
pub fn any_matched(&self) -> bool {
|
||||||
|
self.filter_out.len() != self.pointers.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct UiInputState {
|
pub(crate) struct UiInputState {
|
||||||
pointers: Vec<ActiveMouseButton>,
|
pointers: Vec<Pointer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiInputState {
|
impl UiInputState {
|
||||||
|
@ -139,7 +179,7 @@ impl UiInputState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn query_pointer(&self, area: Rect) -> bool {
|
pub fn query_pointer(&self) -> PointerQuery {
|
||||||
todo!()
|
PointerQuery::new(&self.pointers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,11 @@ pub struct Rect {
|
||||||
pub size: Vec2,
|
pub size: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Rect {
|
||||||
|
pub fn contains_point(&self, point: Vec2) -> bool {
|
||||||
|
point.cmpge(self.position).all() && point.cmple(self.position + self.size).all()
|
||||||
|
}
|
||||||
|
}
|
||||||
/// Represents 4 sides of a rectangular shape.
|
/// Represents 4 sides of a rectangular shape.
|
||||||
#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
pub struct Sides<T> {
|
pub struct Sides<T> {
|
||||||
|
|
Loading…
Reference in a new issue