mirror of
https://github.com/griffi-gh/hUI.git
synced 2024-11-25 16:38:42 -06:00
refactor
This commit is contained in:
parent
cd589d29ae
commit
45bbdd57fd
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 glam::{UVec2, vec4};
|
||||
use glium::{backend::glutin::SimpleWindowBuilder, Surface};
|
||||
|
@ -7,7 +9,7 @@ use winit::{
|
|||
};
|
||||
use hui::{
|
||||
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
|
||||
};
|
||||
use hui_glium::GliumUiRenderer;
|
||||
|
@ -69,23 +71,26 @@ fn main() {
|
|||
padding: Sides::all(5.),
|
||||
gap: 10.,
|
||||
children: ElementList(vec![
|
||||
Box::new(Rect {
|
||||
size: (Size::Fraction(0.5), Size::Static(30.)),
|
||||
color: vec4(0.75, 0., 0., 1.).into()
|
||||
Box::new(FillRect {
|
||||
size: (Size::Fraction(0.5), Size::Static(30.)).into(),
|
||||
background: vec4(0.75, 0., 0., 1.).into(),
|
||||
..Default::default()
|
||||
}),
|
||||
Box::new(Rect {
|
||||
size: (Size::Fraction(z / 2. + 0.5), Size::Static(30.)),
|
||||
color: Corners::left_right(
|
||||
Box::new(FillRect {
|
||||
size: (Size::Fraction(z / 2. + 0.5), Size::Static(30.)).into(),
|
||||
background: Corners::left_right(
|
||||
vec4(1., 0., 0., 1.),
|
||||
vec4(0., 1., 0., 1.)
|
||||
).into(),
|
||||
..Default::default()
|
||||
}),
|
||||
]),
|
||||
..Default::default()
|
||||
}),
|
||||
Box::new(Rect {
|
||||
size: (Size::Fraction(z / 2. + 0.5), Size::Static(30.)),
|
||||
color: vec4(0., 0.75, 0., 1.).into()
|
||||
Box::new(FillRect {
|
||||
size: (Size::Fraction(z / 2. + 0.5), Size::Static(30.)).into(),
|
||||
background: vec4(0., 0.75, 0., 1.).into(),
|
||||
..Default::default()
|
||||
}),
|
||||
Box::new(Container {
|
||||
gap: 5.,
|
||||
|
@ -95,13 +100,14 @@ fn main() {
|
|||
children: {
|
||||
let mut x: Vec<Box<dyn UiElement>> = vec![];
|
||||
for i in 0..10 {
|
||||
x.push(Box::new(Rect {
|
||||
size: (Size::Static(50.), Size::Static(50.)),
|
||||
color: if i == 1 {
|
||||
x.push(Box::new(FillRect {
|
||||
size: (Size::Static(50.), Size::Static(50.)).into(),
|
||||
background: if i == 1 {
|
||||
vec4(0.75, 0.75, 0.75, 0.75).into()
|
||||
} else {
|
||||
vec4(0.5, 0.5, 0.5, 0.75).into()
|
||||
}
|
||||
},
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
ElementList(x)
|
||||
|
@ -123,9 +129,10 @@ fn main() {
|
|||
bottom_right: 0.,
|
||||
},
|
||||
children: ElementList(vec![
|
||||
Box::new(Rect {
|
||||
size: (Size::Static(50.), Size::Static(50.)),
|
||||
color: vec4(1., 1., 1., 0.75).into()
|
||||
Box::new(FillRect {
|
||||
size: (Size::Static(50.), Size::Static(50.)).into(),
|
||||
background: vec4(1., 1., 1., 0.75).into(),
|
||||
..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 glam::{UVec2, vec4};
|
||||
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 glium::{backend::glutin::SimpleWindowBuilder, Surface};
|
||||
use winit::{
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//WARNING: THIS EXAMPLE IS EXTREMELY OUTDATED AND USES DEPRECATED API
|
||||
|
||||
use std::time::Instant;
|
||||
use glam::{UVec2, vec4};
|
||||
use glium::{backend::glutin::SimpleWindowBuilder, Surface};
|
||||
|
@ -7,7 +9,7 @@ use winit::{
|
|||
};
|
||||
use hui::{
|
||||
element::{
|
||||
container::Container, rect::Rect, spacer::Spacer, text::Text, ElementList
|
||||
container::Container, fill_rect::FillRect, spacer::Spacer, text::Text, ElementList
|
||||
}, layout::Size, UiInstance
|
||||
};
|
||||
use hui_glium::GliumUiRenderer;
|
||||
|
@ -69,13 +71,15 @@ fn main() {
|
|||
..Default::default()
|
||||
}));
|
||||
}
|
||||
elem.push(Box::new(Rect {
|
||||
size: (Size::Fraction(1.), Size::Static(10.)),
|
||||
color: vec4(0., 0., 1., 1.).into(),
|
||||
elem.push(Box::new(FillRect {
|
||||
size: (Size::Fraction(1.), Size::Static(10.)).into(),
|
||||
background: vec4(0., 0., 1., 1.).into(),
|
||||
..Default::default()
|
||||
}));
|
||||
elem.push(Box::new(Rect {
|
||||
size: (Size::Fraction(1.), Size::Static(10.)),
|
||||
color: vec4(1., 1., 0., 1.).into(),
|
||||
elem.push(Box::new(FillRect {
|
||||
size: (Size::Fraction(1.), Size::Static(10.)).into(),
|
||||
background: vec4(1., 1., 0., 1.).into(),
|
||||
..Default::default()
|
||||
}));
|
||||
elem.push(Box::new(Text {
|
||||
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()
|
||||
}));
|
||||
if instant.elapsed().as_secs() & 1 != 0 {
|
||||
elem.push(Box::new(Rect {
|
||||
size: (Size::Fraction(1.), Size::Static(10.)),
|
||||
color: vec4(1., 0., 0., 1.).into(),
|
||||
elem.push(Box::new(FillRect {
|
||||
size: (Size::Fraction(1.), Size::Static(10.)).into(),
|
||||
background: vec4(1., 0., 0., 1.).into(),
|
||||
..Default::default()
|
||||
}));
|
||||
elem.push(Box::new(Rect {
|
||||
size: (Size::Fraction(1.), Size::Static(10.)),
|
||||
color: vec4(0., 0., 0., 1.).into(),
|
||||
elem.push(Box::new(FillRect {
|
||||
size: (Size::Fraction(1.), Size::Static(10.)).into(),
|
||||
background: vec4(0., 0., 0., 1.).into(),
|
||||
..Default::default()
|
||||
}));
|
||||
elem.push(Box::new(Spacer(100.)));
|
||||
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"
|
||||
derive_setters = "0.1"
|
||||
#smallvec = "1.13"
|
||||
#tinyset = "0.4"
|
||||
tinyset = "0.4"
|
||||
|
||||
[features]
|
||||
default = ["builtin_elements", "builtin_font", "pixel_perfect_text"]
|
||||
|
|
|
@ -9,27 +9,28 @@ use crate::rectangle::Corners;
|
|||
// pub texture: Option<TextureH>
|
||||
// }
|
||||
|
||||
//TODO: move this into the color module?
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq)]
|
||||
pub enum BackgroundColor {
|
||||
pub enum RectBackground {
|
||||
#[default]
|
||||
Transparent,
|
||||
Solid(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 {
|
||||
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 {
|
||||
Self::Gradient(corners)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Option<Vec4>> for BackgroundColor {
|
||||
impl From<Option<Vec4>> for RectBackground {
|
||||
fn from(color: Option<Vec4>) -> Self {
|
||||
match 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 {
|
||||
Self::Solid(color)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(f32, f32, f32)> for BackgroundColor {
|
||||
impl From<(f32, f32, f32)> for RectBackground {
|
||||
fn from(color: (f32, f32, f32)) -> Self {
|
||||
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 {
|
||||
Self::Gradient(Corners {
|
||||
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 {
|
||||
match color {
|
||||
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 {
|
||||
Self::Solid(color.extend(1.))
|
||||
}
|
||||
}
|
||||
|
||||
impl BackgroundColor {
|
||||
impl RectBackground {
|
||||
/// Currently, never returns None.\
|
||||
/// `Option` has been added in preparation for future changes.\
|
||||
/// (`Background::Texture` etc)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
pub mod container;
|
||||
|
||||
#[cfg(feature = "builtin_elements")]
|
||||
pub mod rect;
|
||||
pub mod fill_rect;
|
||||
|
||||
#[cfg(feature = "builtin_elements")]
|
||||
pub mod spacer;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use derive_setters::Setters;
|
||||
use glam::{Vec2, vec2};
|
||||
use crate::{
|
||||
background::BackgroundColor,
|
||||
background::RectBackground,
|
||||
draw::{RoundedCorners, UiDrawCommand},
|
||||
element::{ElementList, MeasureContext, ProcessContext, UiElement},
|
||||
layout::{Alignment, Alignment2d, LayoutInfo, UiDirection, Size, Size2d},
|
||||
|
@ -31,7 +31,7 @@ pub struct Container {
|
|||
#[setters(into)]
|
||||
pub align: Alignment2d,
|
||||
#[setters(into)]
|
||||
pub background: BackgroundColor,
|
||||
pub background: RectBackground,
|
||||
#[setters(into)]
|
||||
pub corner_radius: Corners<f32>,
|
||||
#[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::{
|
||||
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 size: (Size, Size),
|
||||
pub value: f32,
|
||||
pub color_foreground: Vec4,
|
||||
pub color_background: Vec4,
|
||||
#[setters(into)]
|
||||
pub size: Size2d,
|
||||
#[setters(into)]
|
||||
pub foreground: RectBackground,
|
||||
#[setters(into)]
|
||||
pub background: RectBackground,
|
||||
#[setters(into)]
|
||||
pub corner_radius: Corners<f32>,
|
||||
}
|
||||
|
||||
|
@ -19,10 +30,10 @@ impl ProgressBar {
|
|||
impl Default for ProgressBar {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
size: (Size::Auto, Size::Auto),
|
||||
value: 0.,
|
||||
color_foreground: vec4(0.0, 0.0, 1.0, 1.0),
|
||||
color_background: vec4(0.0, 0.0, 0.0, 1.0),
|
||||
size: Size::Auto.into(),
|
||||
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.),
|
||||
}
|
||||
}
|
||||
|
@ -34,12 +45,12 @@ impl UiElement for ProgressBar {
|
|||
fn measure(&self, ctx: MeasureContext) -> Response {
|
||||
Response {
|
||||
size: vec2(
|
||||
match self.size.0 {
|
||||
match self.size.width {
|
||||
Size::Auto => ctx.layout.max_size.x.max(300.),
|
||||
Size::Fraction(p) => ctx.layout.max_size.x * p,
|
||||
Size::Static(p) => p,
|
||||
},
|
||||
match self.size.1 {
|
||||
match self.size.height {
|
||||
Size::Auto => Self::DEFAULT_HEIGHT,
|
||||
Size::Fraction(p) => ctx.layout.max_size.y * p,
|
||||
Size::Static(p) => p,
|
||||
|
@ -71,7 +82,7 @@ impl UiElement for ProgressBar {
|
|||
ctx.draw.add(UiDrawCommand::Rectangle {
|
||||
position: ctx.layout.position,
|
||||
size: ctx.measure.size,
|
||||
color: Corners::all(self.color_background),
|
||||
color: self.background.corners().unwrap(),
|
||||
texture: None,
|
||||
rounded_corners
|
||||
});
|
||||
|
@ -80,7 +91,7 @@ impl UiElement for ProgressBar {
|
|||
ctx.draw.add(UiDrawCommand::Rectangle {
|
||||
position: ctx.layout.position,
|
||||
size: ctx.measure.size * vec2(value, 1.0),
|
||||
color: Corners::all(self.color_foreground),
|
||||
color: self.foreground.corners().unwrap(),
|
||||
texture: None,
|
||||
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 crate::{
|
||||
element::{MeasureContext, ProcessContext, UiElement},
|
||||
|
@ -5,6 +7,8 @@ use crate::{
|
|||
layout::UiDirection
|
||||
};
|
||||
|
||||
/// Adds spacing between elements in a layout\
|
||||
/// (depending on the current layout direction)
|
||||
pub struct Spacer(pub f32);
|
||||
|
||||
impl Default for Spacer {
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::hash::{Hash, Hasher};
|
|||
use glam::Vec2;
|
||||
use hashbrown::HashMap;
|
||||
use nohash_hasher::BuildNoHashHasher;
|
||||
use tinyset::{SetU32, SetUsize};
|
||||
use crate::rectangle::Rect;
|
||||
|
||||
/// Represents a mouse button.
|
||||
|
@ -110,6 +111,15 @@ pub(crate) enum Pointer {
|
|||
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 {
|
||||
/// Check if the pointer (mouse or touch) was just pressed\
|
||||
/// (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 {
|
||||
pointers: Vec<ActiveMouseButton>,
|
||||
pointers: Vec<Pointer>,
|
||||
}
|
||||
|
||||
impl UiInputState {
|
||||
|
@ -139,7 +179,7 @@ impl UiInputState {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn query_pointer(&self, area: Rect) -> bool {
|
||||
todo!()
|
||||
pub fn query_pointer(&self) -> PointerQuery {
|
||||
PointerQuery::new(&self.pointers)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,11 @@ pub struct Rect {
|
|||
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.
|
||||
#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct Sides<T> {
|
||||
|
|
Loading…
Reference in a new issue