allow rect in add, clean up elem api

This commit is contained in:
griffi-gh 2024-04-17 15:21:17 +02:00
parent 7cfc97b434
commit 85ebf67431
3 changed files with 43 additions and 34 deletions

View file

@ -1,11 +1,11 @@
//! element API and built-in elements like `Container`, `Button`, `Text`, etc.
use std::any::Any;
use crate::{
draw::{atlas::ImageCtx, UiDrawCommandList},
input::InputCtx,
layout::{LayoutInfo, Size2d},
measure::Response,
rect::Rect,
signal::SignalStore,
state::StateRepo,
text::{FontHandle, TextMeasure},
@ -50,27 +50,6 @@ pub trait UiElement {
/// You should implement this function whenever possible, otherwise some features may not work at all, such as the `Remaining` size
fn size(&self) -> Option<Size2d> { None }
/// Get the unique id used for internal state management\
/// This value must be unique for each instance of the element
///
/// If the element is stateless, this function should return `None`
fn state_id(&self) -> Option<u64> { None }
/// Check if the element has state.\
/// Should not be overridden
fn is_stateful(&self) -> bool { self.state_id().is_some() }
/// Check if the element has no state\
/// Should not be overridden
fn is_stateless(&self) -> bool { !self.is_stateful() }
/// Initialize the state of the element\
/// This function should be called exactly once during the lifetime of the element,
/// or if the state gets reset
///
/// This function will not get called for stateless elements
fn init_state(&self) -> Option<Box<dyn Any>> { None }
/// Measure step, guaranteed to be called before the `process` step\
/// May be called multiple times per single frame, so it should not contain any expensive calls\
/// This function may not mutate any state.\
@ -108,7 +87,7 @@ pub trait UiElementExt: UiElement {
fn add_child(self, ui: &mut ElementList);
/// Add element as a ui root.
fn add_root(self, ui: &mut UiInstance, max_size: glam::Vec2);
fn add_root(self, ui: &mut UiInstance, max_size: impl Into<Rect>);
}
impl<T: UiElement + 'static> UiElementExt for T {
@ -116,7 +95,7 @@ impl<T: UiElement + 'static> UiElementExt for T {
ui.add(self)
}
fn add_root(self, ui: &mut UiInstance, max_size: glam::Vec2) {
ui.add(self, max_size);
fn add_root(self, ui: &mut UiInstance, rect: impl Into<Rect>) {
ui.add(self, rect);
}
}

View file

@ -1,16 +1,20 @@
use glam::Vec2;
use crate::{
element::{MeasureContext, ProcessContext, UiElement},
layout::{Direction, LayoutInfo},
text::{FontHandle, TextRenderer},
draw::{
ImageHandle, TextureFormat, UiDrawCall, UiDrawCommandList,
ImageHandle,
TextureFormat,
UiDrawCall,
UiDrawCommandList,
atlas::{TextureAtlasManager, TextureAtlasMeta},
},
element::{MeasureContext, ProcessContext, UiElement},
signal::{Signal, SignalStore},
event::{EventQueue, UiEvent},
input::UiInputState,
layout::{Direction, LayoutInfo},
signal::{SignalStore, Signal},
rect::Rect,
state::StateRepo,
text::{FontHandle, TextRenderer}
};
/// The main instance of the UI system.
@ -144,16 +148,17 @@ impl UiInstance {
/// Add an element or an element tree to the UI
///
/// Use the `max_size` parameter to specify the maximum size of the element\
/// Use the `rect` parameter to specify the position and size of the element\
/// (usually, the size of the window/screen)
///
/// ## Panics:
/// If called while the UI is not active (call [`UiInstance::begin`] first)
pub fn add<T: UiElement>(&mut self, element: T, max_size: Vec2) {
pub fn add(&mut self, element: impl UiElement, rect: impl Into<Rect>) {
assert!(self.state, "must call UiInstance::begin before adding elements");
let rect: Rect = rect.into();
let layout = LayoutInfo {
position: Vec2::ZERO,
max_size,
position: rect.position,
max_size: rect.size,
direction: Direction::Vertical,
remaining_space: None,
};

View file

@ -11,6 +11,24 @@ pub struct Rect {
}
impl Rect {
pub const fn new(position: Vec2, size: Vec2) -> Self {
Self { position, size }
}
pub const fn from_position(position: Vec2) -> Self {
Self {
position,
size: Vec2::ZERO,
}
}
pub const fn from_size(size: Vec2) -> Self {
Self {
position: Vec2::ZERO,
size,
}
}
/// Check if the rect contains a point.
pub fn contains_point(&self, point: Vec2) -> bool {
point.cmpge(self.position).all() && point.cmple(self.position + self.size).all()
@ -63,3 +81,10 @@ impl Rect {
}
}
}
impl From<Vec2> for Rect {
/// Create a new `Rect` from a `Vec2`, where x and y are the width and height of the rect respectively.
fn from(size: Vec2) -> Self {
Self::from_size(size)
}
}