sizing actually working correctly now
This commit is contained in:
@@ -3,10 +3,10 @@ use std::ops::Range;
|
||||
use crate::{
|
||||
layout::{
|
||||
Active, TextAttrs, TextBuffer, TextData, TextOffset, TextureHandle, Textures, UiRegion,
|
||||
Vec2, WidgetId, Widgets,
|
||||
UiVec2, Vec2, WidgetId, Widgets,
|
||||
},
|
||||
render::{Primitive, PrimitiveHandle, Primitives},
|
||||
util::{HashSet, Id},
|
||||
util::{HashMap, HashSet, Id},
|
||||
};
|
||||
|
||||
pub struct Painter<'a, 'c> {
|
||||
@@ -15,7 +15,7 @@ pub struct Painter<'a, 'c> {
|
||||
textures: Vec<TextureHandle>,
|
||||
primitives: Vec<PrimitiveHandle>,
|
||||
children: Vec<Id>,
|
||||
sized_children: HashSet<Id>,
|
||||
sized_children: HashMap<Id, UiVec2>,
|
||||
id: Id,
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ pub struct WidgetInstance {
|
||||
pub textures: Vec<TextureHandle>,
|
||||
pub primitives: Vec<PrimitiveHandle>,
|
||||
pub children: Vec<Id>,
|
||||
pub resize: Option<Id>,
|
||||
pub resize: Option<(Id, UiVec2)>,
|
||||
pub span: Range<usize>,
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ impl<'a> PainterCtx<'a> {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(rid) = &active.resize {
|
||||
if let Some((rid, size)) = &active.resize {
|
||||
self.redraw(&rid.duplicate());
|
||||
if self.drawing.contains(id) {
|
||||
return;
|
||||
@@ -76,15 +76,20 @@ impl<'a> PainterCtx<'a> {
|
||||
let Some(active) = self.remove(id) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let parent = active.parent();
|
||||
drop(active.textures);
|
||||
self.textures.free();
|
||||
|
||||
self.primitives.set_pos(active.span.start);
|
||||
self.draw_inner(id, active.region, active.parent(), Some(active.children));
|
||||
self.draw_inner(id, active.region, parent, Some(active.children));
|
||||
self.active.widgets.get_mut(id).unwrap().resize = active.resize;
|
||||
|
||||
let delta = self.primitives.apply(active.span.clone());
|
||||
if delta != 0
|
||||
&& let Some(parent) = active.parent
|
||||
{
|
||||
self.shift_parent(parent, active.span.start, delta);
|
||||
self.shift_parent(id, parent, active.span.start, delta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,12 +118,12 @@ impl<'a> PainterCtx<'a> {
|
||||
}
|
||||
let mut old_children = old_children.unwrap_or_default();
|
||||
let mut resize = None;
|
||||
if let Some(active) = self.active.widgets.get(id) {
|
||||
if let Some(active) = self.active.widgets.get_mut(id) {
|
||||
if active.parent != parent {
|
||||
panic!("Cannot draw the same widget twice (2)");
|
||||
}
|
||||
if active.region == region {
|
||||
self.primitives.skip(&active.span);
|
||||
self.primitives.skip(&mut active.span);
|
||||
return;
|
||||
}
|
||||
// TODO:
|
||||
@@ -126,6 +131,8 @@ impl<'a> PainterCtx<'a> {
|
||||
let active = self.remove(id).unwrap();
|
||||
old_children = active.children;
|
||||
resize = active.resize;
|
||||
drop(active.textures);
|
||||
self.textures.free();
|
||||
}
|
||||
|
||||
let mut painter = Painter {
|
||||
@@ -135,7 +142,7 @@ impl<'a> PainterCtx<'a> {
|
||||
primitives: Vec::new(),
|
||||
ctx: self,
|
||||
children: Vec::new(),
|
||||
sized_children: HashSet::new(),
|
||||
sized_children: Default::default(),
|
||||
};
|
||||
|
||||
// draw widgets
|
||||
@@ -156,9 +163,9 @@ impl<'a> PainterCtx<'a> {
|
||||
children: painter.children,
|
||||
resize,
|
||||
};
|
||||
for cid in sized_children {
|
||||
for (cid, size) in sized_children {
|
||||
if let Some(w) = self.active.widgets.get_mut(&cid) {
|
||||
w.resize = Some(id.duplicate())
|
||||
w.resize = Some((id.duplicate(), size))
|
||||
}
|
||||
}
|
||||
for c in &old_children {
|
||||
@@ -193,28 +200,31 @@ impl<'a> PainterCtx<'a> {
|
||||
/// shifts the primitive spans for all widgets above this one in the tree
|
||||
/// also goes into children of them and modifies those that come after this one
|
||||
/// should be done after applying primitives to ensure active spans are correct
|
||||
fn shift_parent(&mut self, parent: Id, start: usize, delta: isize) {
|
||||
fn shift_parent(&mut self, original: &Id, parent: Id, start: usize, delta: isize) {
|
||||
let instance = self.active.widgets.get_mut(&parent).unwrap();
|
||||
let end = &mut instance.span.end;
|
||||
*end = end.strict_add_signed(delta);
|
||||
let parent = instance.parent();
|
||||
let parent_parent = instance.parent();
|
||||
for child in instance
|
||||
.children
|
||||
.iter()
|
||||
// skip original
|
||||
.skip_while(|id| *id != original)
|
||||
.skip(1)
|
||||
.map(|id| id.duplicate())
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
self.shift_child(&child, start, delta);
|
||||
}
|
||||
if let Some(parent) = parent {
|
||||
self.shift_parent(parent, start, delta);
|
||||
if let Some(parent_parent) = parent_parent {
|
||||
self.shift_parent(&parent, parent_parent, start, delta);
|
||||
}
|
||||
}
|
||||
|
||||
fn shift_child(&mut self, child: &Id, start: usize, delta: isize) {
|
||||
let instance = self.active.widgets.get_mut(child).unwrap();
|
||||
// = also prevents the original id from getting shifted
|
||||
if instance.span.start <= start {
|
||||
if instance.span.start < start {
|
||||
return;
|
||||
}
|
||||
instance.span.start = instance.span.start.strict_add_signed(delta);
|
||||
@@ -232,11 +242,11 @@ impl<'a> PainterCtx<'a> {
|
||||
|
||||
impl<'a, 'c> Painter<'a, 'c> {
|
||||
fn primitive_at<P: Primitive>(&mut self, primitive: P, region: UiRegion) {
|
||||
self.primitives.push(
|
||||
self.ctx
|
||||
.primitives
|
||||
.write(self.id.duplicate(), primitive, region),
|
||||
);
|
||||
let h = self
|
||||
.ctx
|
||||
.primitives
|
||||
.write(self.id.duplicate(), primitive, region);
|
||||
self.primitives.push(h);
|
||||
}
|
||||
|
||||
/// Writes a primitive to be rendered
|
||||
@@ -293,17 +303,12 @@ impl<'a, 'c> Painter<'a, 'c> {
|
||||
self.region
|
||||
}
|
||||
|
||||
pub fn size<W>(&mut self, id: &WidgetId<W>) -> Vec2 {
|
||||
self.sized_children.insert(id.id.duplicate());
|
||||
self.ctx
|
||||
.widgets
|
||||
.get_dyn_dynamic(&id.id)
|
||||
.get_size(&mut self.size_ctx())
|
||||
pub fn size<W>(&mut self, id: &WidgetId<W>) -> UiVec2 {
|
||||
self.size_ctx().size(id)
|
||||
}
|
||||
|
||||
pub fn size_ctx(&mut self) -> SizeCtx<'_> {
|
||||
SizeCtx {
|
||||
size: self.region.in_size(self.ctx.screen_size),
|
||||
text: self.ctx.text,
|
||||
textures: self.ctx.textures,
|
||||
widgets: self.ctx.widgets,
|
||||
@@ -317,17 +322,21 @@ impl<'a, 'c> Painter<'a, 'c> {
|
||||
}
|
||||
|
||||
pub struct SizeCtx<'a> {
|
||||
pub size: Vec2,
|
||||
pub text: &'a mut TextData,
|
||||
pub textures: &'a mut Textures,
|
||||
widgets: &'a Widgets,
|
||||
checked: &'a mut HashSet<Id>,
|
||||
checked: &'a mut HashMap<Id, UiVec2>,
|
||||
}
|
||||
|
||||
impl SizeCtx<'_> {
|
||||
pub fn size<W>(&mut self, id: &WidgetId<W>) -> Vec2 {
|
||||
self.checked.insert(id.id.duplicate());
|
||||
self.widgets.get_dyn_dynamic(&id.id).get_size(self)
|
||||
pub fn size<W>(&mut self, id: &WidgetId<W>) -> UiVec2 {
|
||||
// TODO: determine if this is useful
|
||||
// if let Some(size) = self.checked.get(&id.id) {
|
||||
// return Some(*size);
|
||||
// }
|
||||
let size = self.widgets.get_dyn_dynamic(&id.id).desired_size(self);
|
||||
self.checked.insert(id.id.duplicate(), size);
|
||||
size
|
||||
}
|
||||
pub fn draw_text(
|
||||
&mut self,
|
||||
|
||||
Reference in New Issue
Block a user