From 2ffb09bef09b409bb9bda470562f3e0e9a92256f Mon Sep 17 00:00:00 2001 From: Shadow Cat Date: Sat, 23 Aug 2025 15:20:25 -0400 Subject: [PATCH] made painter actually how I wanted it (draw now takes in an owned painter) --- src/core/frame.rs | 5 ++- src/core/image.rs | 4 +-- src/core/rect.rs | 2 +- src/core/span.rs | 2 +- src/core/stack.rs | 4 +-- src/layout/painter.rs | 68 ++++++++++++++++++++--------------------- src/layout/ui.rs | 7 +++-- src/layout/widget.rs | 2 +- src/render/primitive.rs | 12 ++++++++ src/testing/mod.rs | 4 +-- 10 files changed, 60 insertions(+), 50 deletions(-) diff --git a/src/core/frame.rs b/src/core/frame.rs index a28c130..473780e 100644 --- a/src/core/frame.rs +++ b/src/core/frame.rs @@ -6,9 +6,8 @@ pub struct Regioned { } impl Widget for Regioned { - fn draw(&self, painter: &mut Painter) { - painter.region.select(&self.region); - painter.draw_inner(&self.inner); + fn draw(&self, mut painter: Painter) { + painter.draw_within(&self.inner, self.region); } } diff --git a/src/core/image.rs b/src/core/image.rs index 1c3f5ff..74933db 100644 --- a/src/core/image.rs +++ b/src/core/image.rs @@ -1,13 +1,13 @@ use image::DynamicImage; -use crate::{Color, TextureHandle, Widget, WidgetFnRet, render::RectPrimitive}; +use crate::{Color, Painter, TextureHandle, Widget, WidgetFnRet, render::RectPrimitive}; pub struct Image { handle: Option, } impl Widget for Image { - fn draw(&self, painter: &mut crate::Painter) { + fn draw(&self, mut painter: Painter) { if let Some(handle) = &self.handle { painter.draw_texture(handle); } else { diff --git a/src/core/rect.rs b/src/core/rect.rs index 0787073..24a840a 100644 --- a/src/core/rect.rs +++ b/src/core/rect.rs @@ -28,7 +28,7 @@ impl Rect { } impl Widget for Rect { - fn draw(&self, painter: &mut Painter) { + fn draw(&self, mut painter: Painter) { painter.write(RectPrimitive { color: self.color, radius: self.radius, diff --git a/src/core/span.rs b/src/core/span.rs index 14398dd..0c9da6a 100644 --- a/src/core/span.rs +++ b/src/core/span.rs @@ -6,7 +6,7 @@ pub struct Span { } impl Widget for Span { - fn draw(&self, painter: &mut Painter) { + fn draw(&self, mut painter: Painter) { let total = self.sums(); let mut start = UIScalar::min(); for (child, length) in &self.children { diff --git a/src/core/stack.rs b/src/core/stack.rs index 855c7ea..d63127c 100644 --- a/src/core/stack.rs +++ b/src/core/stack.rs @@ -1,11 +1,11 @@ -use crate::{Widget, WidgetId}; +use crate::{Painter, Widget, WidgetId}; pub struct Stack { pub children: Vec, } impl Widget for Stack { - fn draw(&self, painter: &mut crate::Painter) { + fn draw(&self, mut painter: Painter) { for child in &self.children { painter.draw(child); } diff --git a/src/layout/painter.rs b/src/layout/painter.rs index 0b6ea09..81c55c1 100644 --- a/src/layout/painter.rs +++ b/src/layout/painter.rs @@ -6,17 +6,18 @@ use crate::{ pub struct Painter<'a, Ctx: 'static> { nodes: &'a Widgets, ctx: &'a mut Ctx, - sensors_map: &'a mut SensorMap, + sensors_map: &'a SensorMap, active_sensors: &'a mut ActiveSensors, - primitives: Primitives, - pub region: UiRegion, + primitives: &'a mut Primitives, + region: UiRegion, } impl<'a, Ctx> Painter<'a, Ctx> { pub fn new( nodes: &'a Widgets, + primitives: &'a mut Primitives, ctx: &'a mut Ctx, - sensors_map: &'a mut SensorMap, + sensors_map: &'a SensorMap, active_sensors: &'a mut ActiveSensors, ) -> Self { Self { @@ -24,59 +25,56 @@ impl<'a, Ctx> Painter<'a, Ctx> { ctx, active_sensors, sensors_map, - primitives: Primitives::default(), + primitives, region: UiRegion::full(), } } + + /// Writes a primitive to be rendered pub fn write(&mut self, data: P) { self.primitives.write(data, self.region); } - /// Draws a widget but does NOT maintain the region. - /// Useful if you only have a single widget to draw. - pub fn draw_inner(&mut self, id: &WidgetId) - where - Ctx: 'static, - { - if self.sensors_map.get(&id.id).is_some() { - self.active_sensors.push((self.region, id.id.duplicate())); - } - self.nodes.get_dyn(id).draw(self); - } - - /// Draws a widget and maintains the original region. - /// Useful if you need to draw multiple overlapping child widgets. + /// Draws a widget within this widget's region. pub fn draw(&mut self, id: &WidgetId) where Ctx: 'static, { - let old = self.region; - self.draw_inner(id); - self.region = old; + self.draw_at(id, self.region); } - /// Draws a widget within an inner region and maintains the original region. - /// Useful if you need to draw multiple child widgets in select areas within the original - /// region. - pub fn draw_within(&mut self, id: &WidgetId, region: UiRegion) + /// Draws a widget somewhere within this one. + /// Useful for drawing child widgets in select areas. + pub fn draw_within(&mut self, id: &WidgetId, region: UiRegion) where Ctx: 'static, { - let old = self.region; - self.region.select(®ion); - self.draw_inner(id); - self.region = old; + self.draw_at(id, region.within(&self.region)); + } + + /// Draws a widget in an arbitrary region. + pub fn draw_at(&mut self, id: &WidgetId, region: UiRegion) + where + Ctx: 'static, + { + if self.sensors_map.get(&id.id).is_some() { + self.active_sensors.push((region, id.id.duplicate())); + } + self.nodes.get_dyn(id).draw(Painter { + nodes: self.nodes, + ctx: self.ctx, + sensors_map: self.sensors_map, + active_sensors: self.active_sensors, + primitives: self.primitives, + region, + }); } pub fn draw_texture(&mut self, handle: &TextureHandle) { self.write(handle.inner); } - pub fn finish(self) -> Primitives { - self.primitives - } - - pub fn ctx_mut(&mut self) -> &mut Ctx { + pub fn ctx(&mut self) -> &mut Ctx { self.ctx } } diff --git a/src/layout/ui.rs b/src/layout/ui.rs index 4a9faca..531d63d 100644 --- a/src/layout/ui.rs +++ b/src/layout/ui.rs @@ -93,16 +93,17 @@ impl Ui { Ctx: 'static, { self.active_sensors.clear(); + self.primitives.clear(); let mut painter = Painter::new( &self.widgets, + &mut self.primitives, ctx, - &mut self.sensor_map, + &self.sensor_map, &mut self.active_sensors, ); if let Some(base) = &self.base { - painter.draw_inner(base); + painter.draw(base); } - self.primitives = painter.finish(); } pub fn update(&mut self, ctx: &mut Ctx) diff --git a/src/layout/widget.rs b/src/layout/widget.rs index 8894f47..dd6e425 100644 --- a/src/layout/widget.rs +++ b/src/layout/widget.rs @@ -2,7 +2,7 @@ use crate::{Painter, Ui, WidgetId, WidgetIdFnRet}; use std::{any::Any, marker::PhantomData}; pub trait Widget: Any { - fn draw(&self, painter: &mut Painter); + fn draw(&self, painter: Painter); } pub struct WidgetTag; diff --git a/src/render/primitive.rs b/src/render/primitive.rs index 9779de7..d022264 100644 --- a/src/render/primitive.rs +++ b/src/render/primitive.rs @@ -61,6 +61,12 @@ macro_rules! primitives { } } + impl PrimitiveData { + pub fn clear(&mut self) { + $(self.$name.clear();)* + } + } + $( unsafe impl bytemuck::Pod for $ty {} unsafe impl bytemuck::Zeroable for $ty {} @@ -87,6 +93,12 @@ impl Primitives { }); vec.push(data); } + + pub(crate) fn clear(&mut self) { + self.updated = true; + self.instances.clear(); + self.data.clear(); + } } primitives!( diff --git a/src/testing/mod.rs b/src/testing/mod.rs index b06794d..794e0f7 100644 --- a/src/testing/mod.rs +++ b/src/testing/mod.rs @@ -89,10 +89,10 @@ impl Client { ctx.ui[id].color = color.add_rgb(-0.2); }) .edit_on(Sense::HoverStart, move |r, _| { - r.color = color.add_rgb(0.1); + r.color = color.add_rgb(0.4); }) .edit_on(Sense::PressEnd, move |r, _| { - r.color = color.add_rgb(0.1); + r.color = color.add_rgb(0.4); }) .edit_on(Sense::HoverEnd, move |r, _| { r.color = color;