mirror of
https://github.com/griffi-gh/hUI.git
synced 2025-04-10 01:46:28 -05:00
wip rewrite/restructure
This commit is contained in:
parent
13503dbcb0
commit
b49f0c2dba
hui-examples
hui-glium/src
hui-painter
hui
|
@ -60,7 +60,7 @@ pub fn ui<T>(
|
||||||
let mut frame = display.draw();
|
let mut frame = display.draw();
|
||||||
frame.clear_color_srgb(0.5, 0.5, 0.5, 1.);
|
frame.clear_color_srgb(0.5, 0.5, 0.5, 1.);
|
||||||
|
|
||||||
hui.begin();
|
hui.begin_frame();
|
||||||
|
|
||||||
let size = UVec2::from(display.get_framebuffer_dimensions()).as_vec2();
|
let size = UVec2::from(display.get_framebuffer_dimensions()).as_vec2();
|
||||||
draw(&mut hui, size, &mut result);
|
draw(&mut hui, size, &mut result);
|
||||||
|
|
|
@ -36,7 +36,7 @@ fn main() {
|
||||||
|
|
||||||
let resolution = UVec2::from(display.get_framebuffer_dimensions()).as_vec2();
|
let resolution = UVec2::from(display.get_framebuffer_dimensions()).as_vec2();
|
||||||
|
|
||||||
hui.begin();
|
hui.begin_frame();
|
||||||
|
|
||||||
let z = instant.elapsed().as_secs_f32().sin().powi(2);
|
let z = instant.elapsed().as_secs_f32().sin().powi(2);
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ fn main() {
|
||||||
|
|
||||||
let resolution = UVec2::from(display.get_framebuffer_dimensions()).as_vec2();
|
let resolution = UVec2::from(display.get_framebuffer_dimensions()).as_vec2();
|
||||||
|
|
||||||
hui.begin();
|
hui.begin_frame();
|
||||||
|
|
||||||
hui.add(Container {
|
hui.add(Container {
|
||||||
size: (Size::Relative(1.), Size::Relative(1.)).into(),
|
size: (Size::Relative(1.), Size::Relative(1.)).into(),
|
||||||
|
|
|
@ -1,11 +1,27 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
use glium::{
|
use glium::{
|
||||||
backend::{Context, Facade}, implement_vertex, index::PrimitiveType, texture::{RawImage2d, Texture2d}, uniform, uniforms::{MagnifySamplerFilter, MinifySamplerFilter, Sampler, SamplerBehavior, SamplerWrapFunction}, Api, Blend, DrawParameters, IndexBuffer, Program, Surface, VertexBuffer
|
backend::{Context, Facade},
|
||||||
};
|
index::PrimitiveType,
|
||||||
use hui::{
|
texture::{RawImage2d, Texture2d},
|
||||||
draw::{TextureAtlasMeta, UiDrawCall, UiVertex}, UiInstance
|
uniforms::{
|
||||||
|
MagnifySamplerFilter,
|
||||||
|
MinifySamplerFilter,
|
||||||
|
Sampler,
|
||||||
|
SamplerBehavior,
|
||||||
|
SamplerWrapFunction
|
||||||
|
},
|
||||||
|
Api,
|
||||||
|
Blend,
|
||||||
|
DrawParameters,
|
||||||
|
IndexBuffer,
|
||||||
|
Program,
|
||||||
|
Surface,
|
||||||
|
VertexBuffer,
|
||||||
|
implement_vertex,
|
||||||
|
uniform,
|
||||||
};
|
};
|
||||||
|
use hui::UiInstance;
|
||||||
|
|
||||||
const VERTEX_SHADER_GLES3: &str = include_str!("../shaders/vertex.es.vert");
|
const VERTEX_SHADER_GLES3: &str = include_str!("../shaders/vertex.es.vert");
|
||||||
const FRAGMENT_SHADER_GLES3: &str = include_str!("../shaders/fragment.es.frag");
|
const FRAGMENT_SHADER_GLES3: &str = include_str!("../shaders/fragment.es.frag");
|
||||||
|
|
|
@ -8,7 +8,7 @@ rust-version = "1.85"
|
||||||
version = "0.1.0-alpha.6"
|
version = "0.1.0-alpha.6"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
publish = false # TODO: change to true once ready
|
publish = true
|
||||||
include = [
|
include = [
|
||||||
"src/**/*.rs",
|
"src/**/*.rs",
|
||||||
"Cargo.toml",
|
"Cargo.toml",
|
||||||
|
|
|
@ -1,3 +1,114 @@
|
||||||
// pub struct BackendData<'a> {
|
use crate::{
|
||||||
// pub
|
paint::{buffer::PaintBuffer, command::{PaintCommand, PaintRoot}},
|
||||||
// }
|
texture::TextureAtlasBackendData,
|
||||||
|
PainterInstance,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Presentatation {
|
||||||
|
current_buffer: PaintBuffer,
|
||||||
|
cur_hash: Option<u64>,
|
||||||
|
prev_hash: Option<u64>,
|
||||||
|
version_counter: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Presentatation {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
current_buffer: PaintBuffer::new(),
|
||||||
|
cur_hash: None,
|
||||||
|
prev_hash: None,
|
||||||
|
version_counter: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If the paint command has changed since the last draw call, draw it and return true.\
|
||||||
|
/// Otherwise, returns false.
|
||||||
|
pub fn draw(&mut self, painter: &mut PainterInstance, cmd: &impl PaintRoot) -> bool {
|
||||||
|
self.prev_hash = self.cur_hash;
|
||||||
|
self.cur_hash = Some(cmd.cache_hash());
|
||||||
|
|
||||||
|
if self.prev_hash == self.cur_hash {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current_buffer.clear();
|
||||||
|
cmd.paint_root(painter, &mut self.current_buffer);
|
||||||
|
|
||||||
|
self.version_counter = self.version_counter.wrapping_add(1);
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the current paint buffer
|
||||||
|
pub fn buffer(&self) -> &PaintBuffer {
|
||||||
|
&self.current_buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the complete backend data for the current presentation
|
||||||
|
///
|
||||||
|
/// It contains the current paint buffer and the hash of the presentation\
|
||||||
|
/// Unlike the `TextureAtlasBackendData`, the version is non-incremental
|
||||||
|
pub fn backend_data(&self) -> PresentatationBackendData {
|
||||||
|
PresentatationBackendData {
|
||||||
|
buffer: &self.current_buffer,
|
||||||
|
version: self.version_counter,
|
||||||
|
hash: self.cur_hash.unwrap_or(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Presentatation {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Backend data for the Presentation
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct PresentatationBackendData<'a> {
|
||||||
|
/// The current paint buffer
|
||||||
|
pub buffer: &'a PaintBuffer,
|
||||||
|
|
||||||
|
/// The version of the presentation
|
||||||
|
///
|
||||||
|
/// This is incremented every time the buffer hash changes
|
||||||
|
pub version: u64,
|
||||||
|
|
||||||
|
/// Unique hash of current paint buffer commands
|
||||||
|
pub hash: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct BackendData<'a> {
|
||||||
|
pub presentation: PresentatationBackendData<'a>,
|
||||||
|
pub atlas: TextureAtlasBackendData<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PainterInstance {
|
||||||
|
pub fn backend_data<'a>(&'a self, presentation: &'a Presentatation) -> BackendData<'a> {
|
||||||
|
BackendData {
|
||||||
|
presentation: presentation.backend_data(),
|
||||||
|
atlas: self.textures.backend_data(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub trait HasPainter {
|
||||||
|
// fn painter(&self) -> &PainterInstance;
|
||||||
|
// fn painter_mut(&self) -> &mut PainterInstance;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub trait PresentFrontend: HasPainter {
|
||||||
|
// fn commands(&self) -> &dyn PaintCommand;
|
||||||
|
|
||||||
|
// fn present(&self, backend: &mut dyn PresentBackend) {
|
||||||
|
// backend.presentation().draw(
|
||||||
|
// self.painter_mut(),
|
||||||
|
// self.commands(),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub trait RenderBackend {
|
||||||
|
fn presentation(&self) -> &mut Presentatation;
|
||||||
|
}
|
||||||
|
|
|
@ -38,20 +38,4 @@ impl PainterInstance {
|
||||||
pub fn fonts_mut(&mut self) -> &mut FontManager {
|
pub fn fonts_mut(&mut self) -> &mut FontManager {
|
||||||
&mut self.fonts
|
&mut self.fonts
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn atlas(&self) -> &TextureAtlas {
|
|
||||||
// &self.atlas
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn atlas_mut(&mut self) -> &mut TextureAtlas {
|
|
||||||
// &mut self.atlas
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn fonts(&self) -> &FontManager {
|
|
||||||
// &self.fonts
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn fonts_mut(&mut self) -> &mut FontManager {
|
|
||||||
// &mut self.fonts
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,10 @@ use crate::{
|
||||||
paint::{
|
paint::{
|
||||||
buffer::{PaintBuffer, Vertex},
|
buffer::{PaintBuffer, Vertex},
|
||||||
command::PaintCommand,
|
command::PaintCommand,
|
||||||
}, text::FontHandle, PainterInstance
|
},
|
||||||
|
text::FontHandle,
|
||||||
|
util::hash_vec4,
|
||||||
|
PainterInstance,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO align, multichunk etc
|
// TODO align, multichunk etc
|
||||||
|
@ -145,9 +148,23 @@ impl PaintCommand for PaintText {
|
||||||
|
|
||||||
fn cache_hash(&self) -> u64 {
|
fn cache_hash(&self) -> u64 {
|
||||||
let mut hasher = rustc_hash::FxHasher::default();
|
let mut hasher = rustc_hash::FxHasher::default();
|
||||||
|
|
||||||
|
// cache font/size/color
|
||||||
self.text.font.hash(&mut hasher);
|
self.text.font.hash(&mut hasher);
|
||||||
hasher.write_u32(self.text.size.to_bits());
|
hasher.write_u32(self.text.size.to_bits());
|
||||||
hasher.write(self.text.text.as_bytes());
|
hash_vec4(&mut hasher, self.text.color);
|
||||||
|
|
||||||
|
// cache text content
|
||||||
|
match self.text.text {
|
||||||
|
Cow::Owned(ref s) => hasher.write(s.as_bytes()),
|
||||||
|
Cow::Borrowed(s) => {
|
||||||
|
// since the lifetime is 'static, the str is guaranteed to never change
|
||||||
|
// so we can safely compare the ptr + len instead of the content
|
||||||
|
hasher.write_usize(s.as_ptr() as usize);
|
||||||
|
hasher.write_usize(s.len());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hasher.finish()
|
hasher.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,7 @@ impl TextureAllocation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
pub struct TextureAtlasBackendData<'a> {
|
pub struct TextureAtlasBackendData<'a> {
|
||||||
pub data: &'a [u8],
|
pub data: &'a [u8],
|
||||||
pub size: UVec2,
|
pub size: UVec2,
|
||||||
|
|
|
@ -38,12 +38,6 @@ default = ["el_all", "image", "builtin_font", "derive"]
|
||||||
## Enable derive macros
|
## Enable derive macros
|
||||||
derive = ["dep:hui-derive"]
|
derive = ["dep:hui-derive"]
|
||||||
|
|
||||||
## Enable image loading support using the `image` crate
|
|
||||||
image = ["dep:image"]
|
|
||||||
|
|
||||||
## Enable the built-in font (ProggyTiny, adds *35kb* to the executable)
|
|
||||||
builtin_font = []
|
|
||||||
|
|
||||||
#! #### Built-in elements:
|
#! #### Built-in elements:
|
||||||
|
|
||||||
## Enable all built-in elements
|
## Enable all built-in elements
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
use hui_painter::{
|
use hui_painter::{
|
||||||
paint::{buffer::PaintBuffer, command::{PaintCommand, PaintList, PaintRoot}},
|
backend::{BackendData, Presentatation}, paint::{buffer::PaintBuffer, command::{PaintCommand, PaintList, PaintRoot}}, text::FontHandle, texture::{SourceTextureFormat, TextureAtlasBackendData, TextureHandle}, PainterInstance
|
||||||
text::FontHandle,
|
|
||||||
texture::{SourceTextureFormat, TextureAtlasBackendData, TextureHandle},
|
|
||||||
PainterInstance,
|
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
element::{MeasureContext, ProcessContext, UiElement},
|
element::{MeasureContext, ProcessContext, UiElement},
|
||||||
|
@ -21,17 +18,12 @@ use crate::{
|
||||||
/// (Please note that it's possible to render multiple UI "roots" using a single instance)
|
/// (Please note that it's possible to render multiple UI "roots" using a single instance)
|
||||||
pub struct UiInstance {
|
pub struct UiInstance {
|
||||||
painter: PainterInstance,
|
painter: PainterInstance,
|
||||||
prev_draw_command_hash: Option<u64>,
|
paint_commands: PaintList,
|
||||||
cur_draw_command_hash: Option<u64>,
|
|
||||||
draw_commands: PaintList,
|
|
||||||
paint_buffer: PaintBuffer,
|
|
||||||
stateful_state: StateRepo,
|
stateful_state: StateRepo,
|
||||||
events: EventQueue,
|
events: EventQueue,
|
||||||
input: UiInputState,
|
input: UiInputState,
|
||||||
signal: SignalStore,
|
signal: SignalStore,
|
||||||
font_stack: FontStack,
|
font_stack: FontStack,
|
||||||
/// True if in the middle of a laying out a frame
|
|
||||||
state: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiInstance {
|
impl UiInstance {
|
||||||
|
@ -41,16 +33,12 @@ impl UiInstance {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
UiInstance {
|
UiInstance {
|
||||||
painter: PainterInstance::new(),
|
painter: PainterInstance::new(),
|
||||||
prev_draw_command_hash: None,
|
paint_commands: PaintList::default(),
|
||||||
cur_draw_command_hash: None,
|
|
||||||
draw_commands: PaintList::default(),
|
|
||||||
paint_buffer: PaintBuffer::new(),
|
|
||||||
font_stack: FontStack::new(),
|
font_stack: FontStack::new(),
|
||||||
stateful_state: StateRepo::new(),
|
stateful_state: StateRepo::new(),
|
||||||
events: EventQueue::new(),
|
events: EventQueue::new(),
|
||||||
input: UiInputState::new(),
|
input: UiInputState::new(),
|
||||||
signal: SignalStore::new(),
|
signal: SignalStore::new(),
|
||||||
state: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +76,8 @@ impl UiInstance {
|
||||||
/// # Panics:
|
/// # Panics:
|
||||||
/// - If the file exists but contains invalid image data\
|
/// - If the file exists but contains invalid image data\
|
||||||
/// (this will change to a soft error in the future)
|
/// (this will change to a soft error in the future)
|
||||||
|
///
|
||||||
|
/// Deprecated.
|
||||||
#[cfg(feature = "image")]
|
#[cfg(feature = "image")]
|
||||||
#[deprecated]
|
#[deprecated]
|
||||||
pub fn add_image_file_path(&mut self, path: impl AsRef<std::path::Path>) -> Result<TextureHandle, std::io::Error> {
|
pub fn add_image_file_path(&mut self, path: impl AsRef<std::path::Path>) -> Result<TextureHandle, std::io::Error> {
|
||||||
|
@ -148,7 +138,6 @@ impl UiInstance {
|
||||||
/// ## Panics:
|
/// ## Panics:
|
||||||
/// If called while the UI is not active (call [`UiInstance::begin`] first)
|
/// If called while the UI is not active (call [`UiInstance::begin`] first)
|
||||||
pub fn add(&mut self, element: impl UiElement, rect: impl Into<Rect>) {
|
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 rect: Rect = rect.into();
|
||||||
let layout = LayoutInfo {
|
let layout = LayoutInfo {
|
||||||
position: rect.position,
|
position: rect.position,
|
||||||
|
@ -169,79 +158,28 @@ impl UiInstance {
|
||||||
measure: &measure,
|
measure: &measure,
|
||||||
state: &mut self.stateful_state,
|
state: &mut self.stateful_state,
|
||||||
layout: &layout,
|
layout: &layout,
|
||||||
paint_target: &mut self.draw_commands,
|
paint_target: &mut self.paint_commands,
|
||||||
input: self.input.ctx(),
|
input: self.input.ctx(),
|
||||||
signal: &mut self.signal,
|
signal: &mut self.signal,
|
||||||
current_font,
|
current_font,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepare the UI for layout and processing\
|
/// Reset the state from the previous frame, and prepare the UI for layout and processing\
|
||||||
/// You must call this function at the beginning of the frame, before adding any elements\
|
/// You must call this function at the start of the frame, before adding any elements\
|
||||||
///
|
///
|
||||||
/// ## Panics:
|
/// ## Panics:
|
||||||
/// If called twice in a row (for example, if you forget to call [`UiInstance::end`])\
|
/// If called twice in a row (for example, if you forget to call [`UiInstance::end`])\
|
||||||
/// This is an indication of a bug in your code and should be fixed.
|
/// This is an indication of a bug in your code and should be fixed.
|
||||||
pub fn begin(&mut self) {
|
pub fn begin_frame(&mut self) {
|
||||||
//check and update current state
|
|
||||||
assert!(!self.state, "must call UiInstance::end before calling UiInstance::begin again");
|
|
||||||
self.state = true;
|
|
||||||
|
|
||||||
//first, drain and process the event queue
|
//first, drain and process the event queue
|
||||||
self.input.update_state(&mut self.events);
|
self.input.update_state(&mut self.events);
|
||||||
|
|
||||||
//then, reset the (remaining) signals
|
//then, reset the (remaining) signals
|
||||||
self.signal.clear();
|
self.signal.clear();
|
||||||
|
|
||||||
// Compute the hash of the current commands
|
|
||||||
self.prev_draw_command_hash = Some(self.draw_commands.cache_hash());
|
|
||||||
|
|
||||||
// Clear the draw commands
|
// Clear the draw commands
|
||||||
self.draw_commands.clear();
|
self.paint_commands.clear();
|
||||||
|
|
||||||
//then, reset the draw commands
|
|
||||||
// std::mem::swap(&mut self.prev_draw_commands, &mut self.draw_commands);
|
|
||||||
// self.draw_commands.commands.clear();
|
|
||||||
// self.draw_call_modified = false;
|
|
||||||
|
|
||||||
//reset atlas modification flag
|
|
||||||
// self.atlas.reset_modified();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// End the frame and prepare the UI for rendering\
|
|
||||||
/// You must call this function at the end of the frame, before rendering the UI
|
|
||||||
///
|
|
||||||
/// ## Panics:
|
|
||||||
/// If called without calling [`UiInstance::begin`] first. (or if called twice)\
|
|
||||||
/// This is an indication of a bug in your code and should be fixed.
|
|
||||||
pub fn end(&mut self) {
|
|
||||||
//check and update current state
|
|
||||||
assert!(self.state, "must call UiInstance::begin before calling UiInstance::end");
|
|
||||||
self.state = false;
|
|
||||||
|
|
||||||
//check if the draw commands have been modified
|
|
||||||
if let Some(prev_hash) = self.prev_draw_command_hash {
|
|
||||||
let cur_hash = self.draw_commands.cache_hash();
|
|
||||||
self.cur_draw_command_hash = Some(cur_hash);
|
|
||||||
if cur_hash == prev_hash {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//if they have, rebuild the draw call and set the modified flag
|
|
||||||
self.paint_buffer.clear();
|
|
||||||
self.draw_commands.paint_root(&mut self.painter, &mut self.paint_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get data intended for rendering backend
|
|
||||||
///
|
|
||||||
/// You should call this function *before* calling [`UiInstance::begin`] or after calling [`UiInstance::end`]\
|
|
||||||
///
|
|
||||||
/// This function should only be used by the rendering backend.\
|
|
||||||
/// You should not call this directly unless you're implementing a custom render backend
|
|
||||||
/// or have a very specific usecase (not using one)
|
|
||||||
fn backend_data(&self) -> (&TextureAtlasBackendData, &PaintBuffer) {
|
|
||||||
(&self.painter, &self.paint_buffer)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push a platform event to the UI event queue
|
/// Push a platform event to the UI event queue
|
||||||
|
@ -256,9 +194,6 @@ impl UiInstance {
|
||||||
/// You should not call this directly unless you're implementing a custom platform backend
|
/// You should not call this directly unless you're implementing a custom platform backend
|
||||||
/// or have a very specific usecase (not using one)
|
/// or have a very specific usecase (not using one)
|
||||||
pub fn push_event(&mut self, event: UiEvent) {
|
pub fn push_event(&mut self, event: UiEvent) {
|
||||||
if self.state {
|
|
||||||
log::warn!("UiInstance::push_event called while in the middle of a frame, this is probably a mistake");
|
|
||||||
}
|
|
||||||
self.events.push(event);
|
self.events.push(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,6 +210,11 @@ impl UiInstance {
|
||||||
pub fn process_signals<T: Signal + 'static>(&mut self, f: impl FnMut(T)) {
|
pub fn process_signals<T: Signal + 'static>(&mut self, f: impl FnMut(T)) {
|
||||||
self.signal.drain::<T>().for_each(f);
|
self.signal.drain::<T>().for_each(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the paint commands needed to render the UI
|
||||||
|
pub fn paint_command(&self) -> &impl PaintCommand {
|
||||||
|
&self.paint_commands
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for UiInstance {
|
impl Default for UiInstance {
|
||||||
|
|
Loading…
Reference in a new issue