diff --git a/src/core/sense.rs b/src/core/sense.rs index b5989ab..32285b0 100644 --- a/src/core/sense.rs +++ b/src/core/sense.rs @@ -169,8 +169,8 @@ impl SensorCtx for Ctx { impl CursorModule { pub fn run(ctx: &mut Ctx, cursor: &CursorState, window_size: Vec2) { - let layers = std::mem::take(&mut ctx.ui().layers); - let mut module = std::mem::take(ctx.ui().modules.get_mut::()); + let layers = std::mem::take(&mut ctx.ui().data.layers); + let mut module = std::mem::take(ctx.ui().data.modules.get_mut::()); for i in layers.indices().rev() { let Some(list) = module.active.get_mut(&i) else { @@ -203,10 +203,10 @@ impl CursorModule { } } - let ui_mod = ctx.ui().modules.get_mut::(); + let ui_mod = ctx.ui().data.modules.get_mut::(); std::mem::swap(ui_mod, &mut module); ui_mod.merge(module); - ctx.ui().layers = layers; + ctx.ui().data.layers = layers; } } diff --git a/src/core/text.rs b/src/core/text.rs index bf18fc5..58728b6 100644 --- a/src/core/text.rs +++ b/src/core/text.rs @@ -124,12 +124,8 @@ impl FnOnce<(&mut Ui,)> for TextBuilder { extern "rust-call" fn call_once(self, args: (&mut Ui,)) -> Self::Output { let mut buf = TextBuffer::new_empty(Metrics::new(self.attrs.font_size, self.attrs.line_height)); - buf.set_text( - &mut args.0.text.font_system, - &self.content, - &Attrs::new(), - Shaping::Advanced, - ); + let font_system = &mut args.0.data.text.font_system; + buf.set_text(font_system, &self.content, &Attrs::new(), Shaping::Advanced); let mut text = Text { content: self.content.into(), buf, @@ -138,8 +134,7 @@ impl FnOnce<(&mut Ui,)> for TextBuilder { size: Vec2::ZERO, }; text.content.changed = false; - self.attrs - .apply(&mut args.0.text.font_system, &mut text.buf, None); + self.attrs.apply(font_system, &mut text.buf, None); text } } diff --git a/src/core/text_edit.rs b/src/core/text_edit.rs index f200713..5b65bb0 100644 --- a/src/core/text_edit.rs +++ b/src/core/text_edit.rs @@ -322,14 +322,10 @@ impl FnOnce<(&mut Ui,)> for TextEditBuilder { cursor: None, size: Vec2::ZERO, }; - text.buf.set_text( - &mut args.0.text.font_system, - &self.content, - &Attrs::new(), - Shaping::Advanced, - ); - self.attrs - .apply(&mut args.0.text.font_system, &mut text.buf, None); + let font_system = &mut args.0.data.text.font_system; + text.buf + .set_text(font_system, &self.content, &Attrs::new(), Shaping::Advanced); + self.attrs.apply(font_system, &mut text.buf, None); text } } diff --git a/src/layout/event.rs b/src/layout/event.rs index c45bdb6..974a27b 100644 --- a/src/layout/event.rs +++ b/src/layout/event.rs @@ -55,7 +55,8 @@ impl, Tag> Eventable for W { ) -> impl WidgetIdFn { move |ui| { let id = self.add(ui); - ui.modules + ui.data + .modules .get_mut::>() .register(id.id, event, f); id @@ -180,6 +181,7 @@ impl Ui { ) { if let Some(f) = ctx .ui() + .data .modules .get_mut::>() .run(&id.id, event) diff --git a/src/layout/painter.rs b/src/layout/painter.rs index 595999e..78759c9 100644 --- a/src/layout/painter.rs +++ b/src/layout/painter.rs @@ -1,7 +1,7 @@ use crate::{ layout::{ - ActiveWidgets, Layers, Modules, TextAttrs, TextBuffer, TextData, TextOffset, TextureHandle, - Textures, UiRegion, UiVec2, Vec2, WidgetId, Widgets, + Layers, Modules, TextAttrs, TextBuffer, TextData, TextOffset, TextureHandle, Textures, + UiRegion, UiVec2, Vec2, WidgetId, Widgets, }, render::{Primitive, PrimitiveHandle}, util::{HashMap, HashSet, Id}, @@ -16,19 +16,19 @@ pub struct Painter<'a, 'c> { sized_children: HashMap, /// whether this widget depends on region's final pixel size or not /// TODO: decide if point (pt) should be used here instead of px - px_dependent: bool, pub layer: usize, id: Id, } pub struct PainterCtx<'a> { pub widgets: &'a Widgets, - pub active: &'a mut ActiveWidgets, + pub active: &'a mut HashMap, pub layers: &'a mut Layers, pub textures: &'a mut Textures, pub text: &'a mut TextData, pub screen_size: Vec2, pub modules: &'a mut Modules, + pub px_dependent: &'a mut HashSet, drawing: HashSet, } @@ -43,24 +43,43 @@ pub struct WidgetInstance { pub layer: usize, } -impl<'a> PainterCtx<'a> { - pub fn new( - widgets: &'a Widgets, - layers: &'a mut Layers, - active: &'a mut ActiveWidgets, - modules: &'a mut Modules, - textures: &'a mut Textures, - text: &'a mut TextData, - screen_size: Vec2, - ) -> Self { +pub struct PainterData { + pub widgets: Widgets, + pub active: HashMap, + pub layers: Layers, + pub textures: Textures, + pub text: TextData, + pub output_size: Vec2, + pub modules: Modules, + pub px_dependent: HashSet, +} + +impl Default for PainterData { + fn default() -> Self { Self { - widgets, - active, - layers, - textures, - text, - screen_size, - modules, + widgets: Widgets::new(), + layers: Default::default(), + textures: Textures::new(), + text: TextData::default(), + active: Default::default(), + output_size: Vec2::ZERO, + modules: Modules::default(), + px_dependent: Default::default(), + } + } +} + +impl<'a> PainterCtx<'a> { + pub fn new(data: &'a mut PainterData) -> Self { + Self { + widgets: &data.widgets, + active: &mut data.active, + layers: &mut data.layers, + textures: &mut data.textures, + text: &mut data.text, + screen_size: data.output_size, + modules: &mut data.modules, + px_dependent: &mut data.px_dependent, drawing: HashSet::default(), } } @@ -157,7 +176,6 @@ impl<'a> PainterCtx<'a> { ctx: self, children: Vec::new(), sized_children: Default::default(), - px_dependent: false, }; // draw widgets @@ -224,6 +242,7 @@ impl<'a> PainterCtx<'a> { m.on_undraw(inst); } } + self.px_dependent.remove(&id); inst } @@ -317,7 +336,7 @@ impl<'a, 'c> Painter<'a, 'c> { } pub fn px_size(&mut self) -> Vec2 { - self.px_dependent = true; + self.ctx.px_dependent.insert(self.id); self.region.in_size(self.ctx.screen_size) } diff --git a/src/layout/ui.rs b/src/layout/ui.rs index 0563ace..e4345fb 100644 --- a/src/layout/ui.rs +++ b/src/layout/ui.rs @@ -3,10 +3,9 @@ use image::DynamicImage; use crate::{ core::{TextEdit, TextEditCtx}, layout::{ - Layers, Modules, PainterCtx, StaticWidgetId, TextData, TextureHandle, Textures, Vec2, - Widget, WidgetId, WidgetInstance, WidgetLike, Widgets, + PainterCtx, PainterData, StaticWidgetId, TextureHandle, Vec2, Widget, WidgetId, WidgetLike, }, - util::{HashMap, Id}, + util::Id, }; use std::{ any::{Any, TypeId}, @@ -15,20 +14,13 @@ use std::{ }; pub struct Ui { + pub(crate) data: PainterData, root: Option, - pub(super) widgets: Widgets, updates: Vec, recv: Receiver, pub(super) send: Sender, - size: Vec2, - // TODO: make these non pub(crate) - pub(crate) layers: Layers, - pub(crate) textures: Textures, - pub(crate) text: TextData, full_redraw: bool, - - pub(crate) active: ActiveWidgets, - pub modules: Modules, + resized: bool, } impl Ui { @@ -46,11 +38,11 @@ impl Ui { /// useful for debugging pub fn set_label(&mut self, id: &WidgetId, label: String) { - self.widgets.data_mut(&id.id).unwrap().label = label; + self.data.widgets.data_mut(&id.id).unwrap().label = label; } pub fn label(&self, id: &WidgetId) -> &String { - &self.widgets.data(&id.id).unwrap().label + &self.data.widgets.data(&id.id).unwrap().label } pub fn add_widget(&mut self, w: W) -> WidgetId { @@ -59,12 +51,12 @@ impl Ui { pub fn push(&mut self, w: W) -> WidgetId { let id = self.id(); - self.widgets.insert(id.id, w); + self.data.widgets.insert(id.id, w); id } pub fn set(&mut self, id: &WidgetId, w: W) { - self.widgets.insert(id.id, w); + self.data.widgets.insert(id.id, w); } pub fn set_root(&mut self, w: impl WidgetLike) { @@ -77,16 +69,16 @@ impl Ui { } pub fn get(&self, id: &WidgetId) -> Option<&W> { - self.widgets.get(id) + self.data.widgets.get(id) } pub fn get_mut(&mut self, id: &WidgetId) -> Option<&mut W> { - self.widgets.get_mut(id) + self.data.widgets.get_mut(id) } pub fn id(&mut self) -> WidgetId { WidgetId::new( - self.widgets.reserve(), + self.data.widgets.reserve(), TypeId::of::(), self.send.clone(), false, @@ -99,26 +91,19 @@ impl Ui { } pub fn add_texture(&mut self, image: DynamicImage) -> TextureHandle { - self.textures.add(image) + self.data.textures.add(image) } pub fn resize(&mut self, size: impl Into) { - self.size = size.into(); + self.data.output_size = size.into(); + self.resized = true; } pub fn redraw_all(&mut self) { - self.active.clear(); + self.data.active.clear(); // free before bc nothing should exist self.free(); - let mut ctx = PainterCtx::new( - &self.widgets, - &mut self.layers, - &mut self.active, - &mut self.modules, - &mut self.textures, - &mut self.text, - self.size, - ); + let mut ctx = PainterCtx::new(&mut self.data); if let Some(root) = &self.root { ctx.draw(root.id); } @@ -131,18 +116,22 @@ impl Ui { } else if !self.updates.is_empty() { self.redraw_updates(); } + if self.resized { + self.resized = false; + self.redraw_size(); + } + } + + fn redraw_size(&mut self) { + let mut ctx = PainterCtx::new(&mut self.data); + let dep = ctx.px_dependent.clone(); + for id in dep { + ctx.redraw(id); + } } fn redraw_updates(&mut self) { - let mut ctx = PainterCtx::new( - &self.widgets, - &mut self.layers, - &mut self.active, - &mut self.modules, - &mut self.textures, - &mut self.text, - self.size, - ); + let mut ctx = PainterCtx::new(&mut self.data); for id in self.updates.drain(..) { ctx.redraw(id); } @@ -152,12 +141,12 @@ impl Ui { /// free any resources that don't have references anymore fn free(&mut self) { for id in self.recv.try_iter() { - for m in self.modules.iter_mut() { + for m in self.data.modules.iter_mut() { m.on_remove(&id); } - self.widgets.delete(id); + self.data.widgets.delete(id); } - self.textures.free(); + self.data.textures.free(); } pub fn needs_redraw(&self) -> bool { @@ -165,18 +154,18 @@ impl Ui { } pub fn num_widgets(&self) -> usize { - self.widgets.len() + self.data.widgets.len() } pub fn active_widgets(&self) -> usize { - self.active.len() + self.data.active.len() } pub fn text(&mut self, id: &WidgetId) -> TextEditCtx<'_> { self.updates.push(id.id); TextEditCtx { - text: self.widgets.get_mut(id).unwrap(), - font_system: &mut self.text.font_system, + text: self.data.widgets.get_mut(id).unwrap(), + font_system: &mut self.data.text.font_system, } } } @@ -200,14 +189,14 @@ impl Index> for Ui { type Output = W; fn index(&self, id: StaticWidgetId) -> &Self::Output { - self.widgets.get_static(&id).unwrap() + self.data.widgets.get_static(&id).unwrap() } } impl IndexMut> for Ui { fn index_mut(&mut self, id: StaticWidgetId) -> &mut Self::Output { self.updates.push(id.id); - self.widgets.get_static_mut(&id).unwrap() + self.data.widgets.get_static_mut(&id).unwrap() } } @@ -225,20 +214,13 @@ impl Default for Ui { fn default() -> Self { let (send, recv) = channel(); Self { + data: PainterData::default(), root: Default::default(), - widgets: Widgets::new(), updates: Default::default(), - layers: Default::default(), - textures: Textures::new(), - text: TextData::default(), full_redraw: false, - active: Default::default(), send, recv, - size: Vec2::ZERO, - modules: Modules::default(), + resized: false, } } } - -pub type ActiveWidgets = HashMap; diff --git a/src/render/mod.rs b/src/render/mod.rs index 7764cee..0d57e57 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -59,11 +59,11 @@ impl UiRenderer { pub fn update(&mut self, device: &Device, queue: &Queue, ui: &mut Ui) { self.active.clear(); - for (i, ulayer) in ui.layers.iter_mut() { + for (i, ulayer) in ui.data.layers.iter_mut() { self.active.push(i); let primitives = &mut ulayer.primitives; for change in primitives.apply_free() { - if let Some(inst) = ui.active.get_mut(&change.id) { + if let Some(inst) = ui.data.active.get_mut(&change.id) { for h in &mut inst.primitives { if h.inst_idx == change.old { h.inst_idx = change.new; @@ -98,7 +98,7 @@ impl UiRenderer { ) } } - if self.textures.update(&mut ui.textures) { + if self.textures.update(&mut ui.data.textures) { self.rsc_group = Self::rsc_group(device, &self.rsc_layout, &self.textures) } }