mirror of
https://github.com/griffi-gh/hUI.git
synced 2024-11-28 18:08:42 -06:00
it kinda works
This commit is contained in:
parent
dd4d48c91c
commit
7884de5560
|
@ -42,7 +42,7 @@ pub fn ui<T>(
|
||||||
let mut hui = UiInstance::new();
|
let mut hui = UiInstance::new();
|
||||||
let mut backend = GliumUiRenderer::new(&display);
|
let mut backend = GliumUiRenderer::new(&display);
|
||||||
|
|
||||||
let result = init(&mut hui);
|
let mut result = init(&mut hui);
|
||||||
|
|
||||||
event_loop.run(|event, window_target| {
|
event_loop.run(|event, window_target| {
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
|
@ -60,7 +60,7 @@ pub fn ui<T>(
|
||||||
hui.begin();
|
hui.begin();
|
||||||
|
|
||||||
let size = UVec2::from(display.get_framebuffer_dimensions()).as_vec2();
|
let size = UVec2::from(display.get_framebuffer_dimensions()).as_vec2();
|
||||||
draw(&mut hui, size, &result);
|
draw(&mut hui, size, &mut result);
|
||||||
|
|
||||||
hui.end();
|
hui.end();
|
||||||
|
|
||||||
|
|
38
hui-examples/examples/ui_test_5_input.rs
Normal file
38
hui-examples/examples/ui_test_5_input.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
use std::time::Instant;
|
||||||
|
use hui::{
|
||||||
|
color, size,
|
||||||
|
layout::{Alignment, Direction},
|
||||||
|
element::{
|
||||||
|
container::Container,
|
||||||
|
fill_rect::FillRect,
|
||||||
|
interactable::ElementInteractableExt,
|
||||||
|
UiElementExt
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[path = "../boilerplate.rs"]
|
||||||
|
#[macro_use]
|
||||||
|
mod boilerplate;
|
||||||
|
|
||||||
|
ui_main!(
|
||||||
|
"hUI: Internal input test",
|
||||||
|
init: |_| {},
|
||||||
|
run: |ui, size, _| {
|
||||||
|
Container::default()
|
||||||
|
.with_size(size!(100%))
|
||||||
|
.with_align(Alignment::Center)
|
||||||
|
.with_background(color::WHITE)
|
||||||
|
.with_children(|ui| {
|
||||||
|
FillRect::default()
|
||||||
|
.with_size(size!(40))
|
||||||
|
.with_corner_radius(8.)
|
||||||
|
.with_background(color::DARK_RED)
|
||||||
|
.into_interactable()
|
||||||
|
.on_click(|| {
|
||||||
|
println!("clicked");
|
||||||
|
})
|
||||||
|
.add_child(ui);
|
||||||
|
})
|
||||||
|
.add_root(ui, size);
|
||||||
|
}
|
||||||
|
);
|
|
@ -1,3 +1,5 @@
|
||||||
|
// "The essentials":
|
||||||
|
|
||||||
#[cfg(feature = "builtin_container")]
|
#[cfg(feature = "builtin_container")]
|
||||||
pub mod container;
|
pub mod container;
|
||||||
|
|
||||||
|
@ -7,17 +9,24 @@ pub mod fill_rect;
|
||||||
#[cfg(feature = "builtin_elements")]
|
#[cfg(feature = "builtin_elements")]
|
||||||
pub mod spacer;
|
pub mod spacer;
|
||||||
|
|
||||||
#[cfg(feature = "builtin_elements")]
|
// "The basics":
|
||||||
pub mod progress_bar;
|
|
||||||
|
|
||||||
#[cfg(feature = "builtin_elements")]
|
#[cfg(feature = "builtin_elements")]
|
||||||
pub mod text;
|
pub mod text;
|
||||||
|
|
||||||
|
#[cfg(feature = "builtin_elements")]
|
||||||
|
pub mod image;
|
||||||
|
|
||||||
|
#[cfg(feature = "builtin_elements")]
|
||||||
|
pub mod progress_bar;
|
||||||
|
|
||||||
|
// Wrappers:
|
||||||
|
|
||||||
#[cfg(feature = "builtin_elements")]
|
#[cfg(feature = "builtin_elements")]
|
||||||
pub mod transformer;
|
pub mod transformer;
|
||||||
|
|
||||||
#[cfg(feature = "builtin_elements")]
|
#[cfg(feature = "builtin_elements")]
|
||||||
pub mod image;
|
pub mod interactable;
|
||||||
|
|
||||||
//TODO add: Image
|
//TODO add: Image
|
||||||
//TODO add: OverlayContainer (for simply laying multiple elements on top of each other)
|
//TODO add: OverlayContainer (for simply laying multiple elements on top of each other)
|
||||||
|
|
|
@ -1,55 +1,79 @@
|
||||||
//TODO this thing?
|
//! wrapper that allows adding click and hover events to any element
|
||||||
//not sure if this is a good idea...
|
|
||||||
//but having the ability to add a click event to any element would be nice, and this is a naive way to do it
|
|
||||||
|
|
||||||
// use crate::element::{UiElement, MeasureContext, ProcessContext};
|
// not sure if this is a good idea...
|
||||||
|
// but having the ability to add a click event to any element would be nice, and this is a naive way to do it
|
||||||
|
|
||||||
// pub struct Interactable<T: UiElement> {
|
use crate::element::{UiElement, MeasureContext, ProcessContext};
|
||||||
// pub element: T,
|
use std::cell::RefCell;
|
||||||
// pub hovered: Option<Box<dyn FnOnce()>>,
|
|
||||||
// pub clicked: Option<Box<dyn FnOnce()>>,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl<T: UiElement> Interactable<T> {
|
/// Wrapper that allows adding click and hover events to any element
|
||||||
// pub fn new(element: T) -> Self {
|
pub struct Interactable {
|
||||||
// Self {
|
/// The wrapped element that will be interactable
|
||||||
// element,
|
pub element: Box<dyn UiElement>,
|
||||||
// hovered: None,
|
/// Function that will be called if the element is hovered in the current frame
|
||||||
// clicked: None,
|
///
|
||||||
// }
|
/// Will be consumed after the first time it's called
|
||||||
// }
|
pub hovered: RefCell<Option<Box<dyn FnOnce()>>>,
|
||||||
|
/// Function that will be called if the element was clicked in the current frame
|
||||||
|
///
|
||||||
|
/// Will be consumed after the first time it's called
|
||||||
|
pub clicked: RefCell<Option<Box<dyn FnOnce()>>>,
|
||||||
|
}
|
||||||
|
|
||||||
// pub fn on_click(self, clicked: impl FnOnce() + 'static) -> Self {
|
impl Interactable {
|
||||||
// Self {
|
pub fn new(element: Box<dyn UiElement>) -> Self {
|
||||||
// clicked: Some(Box::new(clicked)),
|
Self {
|
||||||
// ..self
|
element,
|
||||||
// }
|
hovered: RefCell::new(None),
|
||||||
// }
|
clicked: RefCell::new(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// pub fn on_hover(self, clicked: impl FnOnce() + 'static) -> Self {
|
pub fn on_click(self, clicked: impl FnOnce() + 'static) -> Self {
|
||||||
// Self {
|
Self {
|
||||||
// clicked: Some(Box::new(clicked)),
|
clicked: RefCell::new(Some(Box::new(clicked))),
|
||||||
// ..self
|
..self
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// impl<T: UiElement> UiElement for Interactable<T> {
|
pub fn on_hover(self, clicked: impl FnOnce() + 'static) -> Self {
|
||||||
// fn measure(&self, ctx: MeasureContext) -> crate::measure::Response {
|
Self {
|
||||||
// self.element.measure(ctx)
|
clicked: RefCell::new(Some(Box::new(clicked))),
|
||||||
// }
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// fn process(&self, ctx: ProcessContext) {
|
impl UiElement for Interactable {
|
||||||
// self.element.process(ctx)
|
fn name(&self) -> &'static str {
|
||||||
// }
|
"Interactable"
|
||||||
// }
|
}
|
||||||
|
|
||||||
// pub trait IntoInteractable<T: UiElement>: UiElement {
|
fn measure(&self, ctx: MeasureContext) -> crate::measure::Response {
|
||||||
// fn into_interactable(self) -> Interactable<T>;
|
self.element.measure(ctx)
|
||||||
// }
|
}
|
||||||
|
|
||||||
// impl<T: UiElement> IntoInteractable<T> for T {
|
fn process(&self, ctx: ProcessContext) {
|
||||||
// fn into_interactable(self) -> Interactable<Self> {
|
let rect = ctx.measure.rect(ctx.layout.position);
|
||||||
// Interactable::new(self)
|
|
||||||
// }
|
//XXX: should we do this AFTER normal process call of wrapped element?
|
||||||
// }
|
//TODO other events...
|
||||||
|
if ctx.input.check_click(rect) {
|
||||||
|
//TODO better error message
|
||||||
|
let clicked = self.clicked.borrow_mut().take().expect("you fucked up");
|
||||||
|
clicked();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.element.process(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ElementInteractableExt: UiElement {
|
||||||
|
fn into_interactable(self) -> Interactable;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: UiElement + 'static> ElementInteractableExt for T {
|
||||||
|
fn into_interactable(self) -> Interactable {
|
||||||
|
Interactable::new(Box::new(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -203,7 +203,9 @@ impl UiInputState {
|
||||||
button.start_position = self.mouse_pointer.current_position;
|
button.start_position = self.mouse_pointer.current_position;
|
||||||
},
|
},
|
||||||
ButtonState::Released => {
|
ButtonState::Released => {
|
||||||
|
//log::trace!("Button {:?} was released", button);
|
||||||
if let Some(button_meta) = self.mouse_pointer.buttons.remove(button) {
|
if let Some(button_meta) = self.mouse_pointer.buttons.remove(button) {
|
||||||
|
//log::trace!("start pos was: {:?} current pos is: {:?}", button_meta.start_position, self.mouse_pointer.current_position);
|
||||||
self.mouse_pointer.released_buttons.insert(*button, button_meta);
|
self.mouse_pointer.released_buttons.insert(*button, button_meta);
|
||||||
} else {
|
} else {
|
||||||
//huh
|
//huh
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! element measurement, hints and responses
|
//! element measurement, hints and responses
|
||||||
|
|
||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
|
use crate::rectangle::Rect;
|
||||||
|
|
||||||
// #[non_exhaustive]
|
// #[non_exhaustive]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -27,3 +28,12 @@ pub struct Response {
|
||||||
/// You should almost never set this, and the exact behavior may change in the future
|
/// You should almost never set this, and the exact behavior may change in the future
|
||||||
pub should_wrap: bool,
|
pub should_wrap: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Response {
|
||||||
|
pub fn rect(&self, position: Vec2) -> Rect {
|
||||||
|
Rect {
|
||||||
|
position,
|
||||||
|
size: self.size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue