mirror of
https://github.com/griffi-gh/hUI.git
synced 2024-11-22 07:08:42 -06:00
document stuff
This commit is contained in:
parent
8de7c4673e
commit
9ff9b8356d
|
@ -156,6 +156,7 @@ impl GliumUiRenderer {
|
||||||
const NO_FNT_TEX: &str = "Font texture exists in draw plan but not yet inited. Make sure to call update_font_texture() *before* update_draw_plan()";
|
const NO_FNT_TEX: &str = "Font texture exists in draw plan but not yet inited. Make sure to call update_font_texture() *before* update_draw_plan()";
|
||||||
Some(Rc::clone(self.font_texture.as_ref().expect(NO_FNT_TEX)))
|
Some(Rc::clone(self.font_texture.as_ref().expect(NO_FNT_TEX)))
|
||||||
},
|
},
|
||||||
|
Some(BindTexture::UserDefined(_)) => todo!("user defined textures are not implemented yet"),
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Stuff related to tesselation and UI rendering.
|
||||||
|
|
||||||
use crate::{IfModified, text::{TextRenderer, FontHandle}};
|
use crate::{IfModified, text::{TextRenderer, FontHandle}};
|
||||||
|
|
||||||
mod corner_radius;
|
mod corner_radius;
|
||||||
|
@ -24,6 +26,7 @@ pub enum UiDrawCommand {
|
||||||
///Rounded corners
|
///Rounded corners
|
||||||
rounded_corners: Option<RoundedCorners>,
|
rounded_corners: Option<RoundedCorners>,
|
||||||
},
|
},
|
||||||
|
/// Filled, colored circle
|
||||||
Circle {
|
Circle {
|
||||||
///Position in pixels
|
///Position in pixels
|
||||||
position: Vec2,
|
position: Vec2,
|
||||||
|
@ -32,6 +35,7 @@ pub enum UiDrawCommand {
|
||||||
///Color (RGBA)
|
///Color (RGBA)
|
||||||
color: Vec4,
|
color: Vec4,
|
||||||
},
|
},
|
||||||
|
/// Draw text using the specified font, size, color, and position
|
||||||
Text {
|
Text {
|
||||||
///Position in pixels
|
///Position in pixels
|
||||||
position: Vec2,
|
position: Vec2,
|
||||||
|
@ -56,12 +60,14 @@ impl UiDrawCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// List of draw commands
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct UiDrawCommandList {
|
pub struct UiDrawCommandList {
|
||||||
pub commands: Vec<UiDrawCommand>,
|
pub commands: Vec<UiDrawCommand>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiDrawCommandList {
|
impl UiDrawCommandList {
|
||||||
|
/// Add a draw command to the list
|
||||||
pub fn add(&mut self, command: UiDrawCommand) {
|
pub fn add(&mut self, command: UiDrawCommand) {
|
||||||
self.commands.push(command);
|
self.commands.push(command);
|
||||||
}
|
}
|
||||||
|
@ -74,12 +80,20 @@ impl UiDrawCommandList {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
/// Texture to bind for a draw call
|
||||||
|
///
|
||||||
|
/// - FontTexture: The internally managed font texture
|
||||||
|
/// - UserDefined: User-defined texture, value is user-defined and usually depends on the render backend
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum BindTexture {
|
pub enum BindTexture {
|
||||||
|
/// The internally managed font texture
|
||||||
FontTexture,
|
FontTexture,
|
||||||
//UserDefined(usize),
|
/// User-defined texture, value is user-defined and usually depends on the render backend
|
||||||
|
UserDefined(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A vertex for UI rendering
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Default)]
|
#[derive(Clone, Copy, Debug, PartialEq, Default)]
|
||||||
pub struct UiVertex {
|
pub struct UiVertex {
|
||||||
pub position: Vec2,
|
pub position: Vec2,
|
||||||
|
@ -87,6 +101,7 @@ pub struct UiVertex {
|
||||||
pub uv: Vec2,
|
pub uv: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents a single draw call, should be handled by the render backend
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct UiDrawCall {
|
pub struct UiDrawCall {
|
||||||
pub vertices: Vec<UiVertex>,
|
pub vertices: Vec<UiVertex>,
|
||||||
|
@ -94,6 +109,7 @@ pub struct UiDrawCall {
|
||||||
pub bind_texture: Option<BindTexture>,
|
pub bind_texture: Option<BindTexture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents a complete UI rendering plan (a list of optimized draw calls).
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct UiDrawPlan {
|
pub struct UiDrawPlan {
|
||||||
pub calls: Vec<UiDrawCall>
|
pub calls: Vec<UiDrawCall>
|
||||||
|
@ -131,6 +147,7 @@ impl CallSwapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiDrawPlan {
|
impl UiDrawPlan {
|
||||||
|
/// Tesselate the UI and build a complete draw plan from a list of draw commands
|
||||||
pub fn build(draw_commands: &UiDrawCommandList, tr: &mut TextRenderer) -> Self {
|
pub fn build(draw_commands: &UiDrawCommandList, tr: &mut TextRenderer) -> Self {
|
||||||
let mut swapper = CallSwapper::new();
|
let mut swapper = CallSwapper::new();
|
||||||
let mut prev_command: Option<&UiDrawCommand> = None;
|
let mut prev_command: Option<&UiDrawCommand> = None;
|
||||||
|
|
|
@ -10,12 +10,14 @@ use crate::{
|
||||||
mod builtin;
|
mod builtin;
|
||||||
pub use builtin::*;
|
pub use builtin::*;
|
||||||
|
|
||||||
|
/// Context for the `Element::measure` function
|
||||||
pub struct MeasureContext<'a> {
|
pub struct MeasureContext<'a> {
|
||||||
pub state: &'a StateRepo,
|
pub state: &'a StateRepo,
|
||||||
pub layout: &'a LayoutInfo,
|
pub layout: &'a LayoutInfo,
|
||||||
pub text_measure: TextMeasure<'a>,
|
pub text_measure: TextMeasure<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Context for the `Element::process` function
|
||||||
pub struct ProcessContext<'a> {
|
pub struct ProcessContext<'a> {
|
||||||
pub measure: &'a Response,
|
pub measure: &'a Response,
|
||||||
pub state: &'a mut StateRepo,
|
pub state: &'a mut StateRepo,
|
||||||
|
@ -25,11 +27,36 @@ pub struct ProcessContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait UiElement {
|
pub trait UiElement {
|
||||||
|
/// Get the name of the element, for example "Button" or "ProgressBar"
|
||||||
fn name(&self) -> &'static str { "UiElement" }
|
fn name(&self) -> &'static str { "UiElement" }
|
||||||
|
|
||||||
|
/// 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 }
|
fn state_id(&self) -> Option<u64> { None }
|
||||||
|
|
||||||
|
/// Check if the element has state
|
||||||
fn is_stateful(&self) -> bool { self.state_id().is_some() }
|
fn is_stateful(&self) -> bool { self.state_id().is_some() }
|
||||||
|
|
||||||
|
/// Check if the element has no state
|
||||||
fn is_stateless(&self) -> bool { self.state_id().is_none() }
|
fn is_stateless(&self) -> bool { self.state_id().is_none() }
|
||||||
|
|
||||||
|
/// 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 }
|
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.\
|
||||||
|
///
|
||||||
|
/// This function should return the size of the element along with any hints or layout metadata
|
||||||
fn measure(&self, ctx: MeasureContext) -> Response;
|
fn measure(&self, ctx: MeasureContext) -> Response;
|
||||||
|
|
||||||
|
/// Process step, guaranteed to be called after the `measure` step\
|
||||||
|
/// You should process the user inputs and render the element here.
|
||||||
fn process(&self, ctx: ProcessContext);
|
fn process(&self, ctx: ProcessContext);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ use crate:: {
|
||||||
text::{TextRenderer, FontTextureInfo, FontHandle},
|
text::{TextRenderer, FontTextureInfo, FontHandle},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The main instance of the UI system.\
|
||||||
|
/// In most cases, you should only have one instance of this struct.
|
||||||
pub struct UiInstance {
|
pub struct UiInstance {
|
||||||
//mouse_position: Vec2,
|
//mouse_position: Vec2,
|
||||||
stateful_state: StateRepo,
|
stateful_state: StateRepo,
|
||||||
|
@ -22,6 +24,9 @@ pub struct UiInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiInstance {
|
impl UiInstance {
|
||||||
|
/// Crate and initialize a new instance of the UI
|
||||||
|
///
|
||||||
|
/// In most cases, you should only do this *once*, during the initialization of your application
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
UiInstance {
|
UiInstance {
|
||||||
//mouse_position: Vec2::ZERO,
|
//mouse_position: Vec2::ZERO,
|
||||||
|
@ -38,10 +43,16 @@ impl UiInstance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse and add a font from a raw byte slice to the UI\
|
||||||
|
/// Returns a font handle.
|
||||||
pub fn add_font_from_bytes(&mut self, font: &[u8]) -> FontHandle {
|
pub fn add_font_from_bytes(&mut self, font: &[u8]) -> FontHandle {
|
||||||
self.text_renderer.add_font_from_bytes(font)
|
self.text_renderer.add_font_from_bytes(font)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add an element or an element tree to the UI
|
||||||
|
///
|
||||||
|
/// Use the `max_size` parameter to specify the maximum size of the element\
|
||||||
|
/// (usually, the size of the window/screen)
|
||||||
pub fn add<T: UiElement>(&mut self, element: T, max_size: Vec2) {
|
pub fn add<T: UiElement>(&mut self, element: T, max_size: Vec2) {
|
||||||
let layout = LayoutInfo {
|
let layout = LayoutInfo {
|
||||||
position: Vec2::ZERO,
|
position: Vec2::ZERO,
|
||||||
|
@ -62,6 +73,9 @@ impl UiInstance {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Prepare the UI for layout and processing
|
||||||
|
///
|
||||||
|
/// You must call this function at the beginning of the frame, before adding any elements
|
||||||
pub fn begin(&mut self) {
|
pub fn begin(&mut self) {
|
||||||
std::mem::swap(&mut self.prev_draw_commands, &mut self.draw_commands);
|
std::mem::swap(&mut self.prev_draw_commands, &mut self.draw_commands);
|
||||||
self.draw_plan_modified = false;
|
self.draw_plan_modified = false;
|
||||||
|
@ -69,6 +83,9 @@ impl UiInstance {
|
||||||
self.text_renderer.reset_frame();
|
self.text_renderer.reset_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// End the frame and prepare the UI for rendering
|
||||||
|
///
|
||||||
|
/// You must call this function at the end of the frame, before rendering the UI
|
||||||
pub fn end(&mut self) {
|
pub fn end(&mut self) {
|
||||||
if self.draw_commands.commands == self.prev_draw_commands.commands {
|
if self.draw_commands.commands == self.prev_draw_commands.commands {
|
||||||
return
|
return
|
||||||
|
@ -77,14 +94,32 @@ impl UiInstance {
|
||||||
self.draw_plan_modified = true;
|
self.draw_plan_modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the draw plan (a list of draw calls) for the current frame
|
||||||
|
///
|
||||||
|
/// This function should only be used by the render backend.\
|
||||||
|
/// You should not call this directly unless you're implementing a custom render backend
|
||||||
|
///
|
||||||
|
/// Returns a tuple with a boolean indicating if the draw plan was modified since the last frame
|
||||||
pub fn draw_plan(&self) -> (bool, &UiDrawPlan) {
|
pub fn draw_plan(&self) -> (bool, &UiDrawPlan) {
|
||||||
(self.draw_plan_modified, &self.draw_plan)
|
(self.draw_plan_modified, &self.draw_plan)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the font texture for the current frame
|
||||||
|
///
|
||||||
|
/// This function should only be used by the render backend.\
|
||||||
|
/// You should not call this directly unless you're implementing a custom render backend
|
||||||
|
///
|
||||||
|
/// Make sure to check `FontTextureInfo::modified` to see if the texture was modified
|
||||||
|
/// since the last frame before uploading it to the GPU
|
||||||
pub fn font_texture(&self) -> FontTextureInfo {
|
pub fn font_texture(&self) -> FontTextureInfo {
|
||||||
self.text_renderer.font_texture()
|
self.text_renderer.font_texture()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Push a platform event to the UI event queue
|
||||||
|
///
|
||||||
|
/// This function should only be used by the platform backend.\
|
||||||
|
/// You should not call this directly unless you're implementing a custom platform backend
|
||||||
|
/// or have a very specific usecase
|
||||||
pub fn push_event(&mut self, event: UiEvent) {
|
pub fn push_event(&mut self, event: UiEvent) {
|
||||||
self.events.push_back(event);
|
self.events.push_back(event);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue