diff --git a/hui/src/element.rs b/hui/src/element.rs index 0fe4689..59935a7 100644 --- a/hui/src/element.rs +++ b/hui/src/element.rs @@ -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 { 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 { 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> { 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); } impl UiElementExt for T { @@ -116,7 +95,7 @@ impl 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) { + ui.add(self, rect); } } diff --git a/hui/src/instance.rs b/hui/src/instance.rs index a06cf95..4cf4126 100644 --- a/hui/src/instance.rs +++ b/hui/src/instance.rs @@ -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(&mut self, element: T, max_size: Vec2) { + pub fn add(&mut self, element: impl UiElement, rect: impl Into) { 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, }; diff --git a/hui/src/rect/rect.rs b/hui/src/rect/rect.rs index 902a7af..2d07a04 100644 --- a/hui/src/rect/rect.rs +++ b/hui/src/rect/rect.rs @@ -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 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) + } +}