FIX SIZE CACHE

This commit is contained in:
2025-12-17 00:09:20 -05:00
parent ecbb9e56e2
commit 1363f31fcd
9 changed files with 144 additions and 178 deletions

View File

@@ -1,16 +1,12 @@
use crate::{
ActiveData, Len, Painter, SizeCtx, Ui, UiRegion, UiVec2, WidgetId,
render::MaskIdx,
ui::ResizeRef,
util::{HashMap, HashSet},
ActiveData, Axis, Painter, SizeCtx, Ui, UiRegion, UiVec2, WidgetId, render::MaskIdx,
util::HashSet,
};
use std::ops::{Deref, DerefMut};
/// state maintained between widgets during painting
pub struct DrawState<'a, State> {
pub(super) ui: &'a mut Ui<State>,
cache_width: HashMap<WidgetId, (UiVec2, Len)>,
cache_height: HashMap<WidgetId, (UiVec2, Len)>,
draw_started: HashSet<WidgetId>,
}
@@ -18,8 +14,6 @@ impl<'a, State: 'static> DrawState<'a, State> {
pub fn new(ui: &'a mut Ui<State>) -> Self {
Self {
ui,
cache_width: Default::default(),
cache_height: Default::default(),
draw_started: Default::default(),
}
}
@@ -39,64 +33,23 @@ impl<'a, State: 'static> DrawState<'a, State> {
if self.draw_started.contains(&id) {
return;
}
let Some(active) = self.ui.active.get(&id) else {
// check if parent depends on the desired size of this, if so then redraw it first
for axis in [Axis::X, Axis::Y] {
if let Some(&(outer, old)) = self.cache.size.axis_dyn(axis).get(&id)
&& let Some(current) = self.active.get(&id)
&& let Some(pid) = current.parent
{
self.cache.size.axis_dyn(axis).remove(&id);
let new = self.size_ctx(id, outer).len_axis(id, axis);
self.cache.size.axis_dyn(axis).insert(id, (outer, new));
if new != old {
self.redraw(pid);
}
}
}
if self.draw_started.contains(&id) {
return;
};
let mut resize = active.resize;
// set resize back after redrawing
let finish = |s: &mut Self, resize| {
if let Some(active) = s.active.get_mut(&id) {
// might need to get_or_insert here instead of just assuming
active.resize = resize;
}
};
// check if a parent depends on the desired size of this, if so then redraw it first
// TODO: this is stupid having 2 of these, don't ask me what the consequences are
let mut ret = false;
if let Some((rid, (outer, old_desired))) = &mut resize.x {
let new_desired = self
.size_ctx(
id,
*outer,
id,
&mut Default::default(),
&mut Default::default(),
)
.width_inner(id);
if new_desired != *old_desired {
// unsure if I need to walk down the tree here
self.redraw(*rid);
*old_desired = new_desired;
if self.draw_started.contains(&id) {
ret = true;
}
}
}
if let Some((rid, (outer, old_desired))) = &mut resize.y {
// NOTE: might need hack in Span here (or also do it properly here)
let new_desired = self
.size_ctx(
id,
*outer,
id,
&mut Default::default(),
&mut Default::default(),
)
.height_inner(id);
if new_desired != *old_desired {
self.redraw(*rid);
*old_desired = new_desired;
if self.draw_started.contains(&id) {
ret = true;
}
}
}
if ret {
return finish(self, resize);
}
let Some(active) = self.remove(id, false) else {
@@ -111,43 +64,36 @@ impl<'a, State: 'static> DrawState<'a, State> {
active.mask,
Some(active.children),
);
finish(self, resize);
}
pub(super) fn size_ctx<'b>(
&'b mut self,
source: WidgetId,
outer: UiVec2,
id: WidgetId,
checked_width: &'b mut HashMap<WidgetId, (UiVec2, Len)>,
checked_height: &'b mut HashMap<WidgetId, (UiVec2, Len)>,
) -> SizeCtx<'b, State> {
SizeCtx {
source,
cache_width: &mut self.cache_width,
cache_height: &mut self.cache_height,
cache: &mut self.ui.cache,
text: &mut self.ui.text,
textures: &mut self.ui.textures,
widgets: &self.ui.widgets,
outer,
output_size: self.ui.output_size,
checked_width,
checked_height,
id,
id: source,
}
}
pub fn redraw_all(&mut self) {
// update event managers
// free all resources & cache
for (id, active) in self.ui.active.drain() {
let data = self.ui.widgets.data(id).unwrap();
self.ui.events.undraw(data, &active);
}
// free before bc nothing should exist
self.ui.cache.clear();
self.free();
self.layers.clear();
self.widgets.needs_redraw.clear();
if let Some(id) = &self.ui.root {
self.draw_inner(0, id.id(), UiRegion::FULL, None, MaskIdx::NONE, None);
}
@@ -175,7 +121,6 @@ impl<'a, State: 'static> DrawState<'a, State> {
// );
// }
let mut old_children = old_children.unwrap_or_default();
let mut resize = ResizeRef::default();
if let Some(active) = self.ui.active.get_mut(&id)
&& !self.ui.widgets.needs_redraw.contains(&id)
{
@@ -194,7 +139,6 @@ impl<'a, State: 'static> DrawState<'a, State> {
// if not, then maintain resize and track old children to remove unneeded
let active = self.remove(id, false).unwrap();
old_children = active.children;
resize = active.resize;
}
// draw widget
@@ -209,8 +153,6 @@ impl<'a, State: 'static> DrawState<'a, State> {
textures: Vec::new(),
primitives: Vec::new(),
children: Vec::new(),
children_width: Default::default(),
children_height: Default::default(),
};
let mut widget = painter.state.widgets.get_dyn_dynamic(id);
@@ -224,8 +166,6 @@ impl<'a, State: 'static> DrawState<'a, State> {
textures,
primitives,
children,
children_width,
children_height,
layer,
id,
} = painter;
@@ -238,27 +178,10 @@ impl<'a, State: 'static> DrawState<'a, State> {
textures,
primitives,
children,
resize,
mask,
layer,
};
// set resize for children who's size this widget depends on
for (cid, outer) in children_width {
if let Some(w) = self.active.get_mut(&cid)
&& w.resize.x.is_none()
{
w.resize.x = Some((id, outer))
}
}
for (cid, outer) in children_height {
if let Some(w) = self.active.get_mut(&cid)
&& w.resize.y.is_none()
{
w.resize.y = Some((id, outer))
}
}
// remove old children that weren't kept
for c in &old_children {
if !active.children.contains(c) {
@@ -308,6 +231,7 @@ impl<'a, State: 'static> DrawState<'a, State> {
}
fn remove_rec(&mut self, id: WidgetId) -> Option<ActiveData> {
self.cache.remove(id);
let inst = self.remove(id, true);
if let Some(inst) = &inst {
for c in &inst.children {