initial mask impl

This commit is contained in:
2025-11-10 14:45:22 -05:00
parent 5c2022396a
commit 1c49db1b89
15 changed files with 398 additions and 74 deletions

View File

@@ -3,13 +3,14 @@ use crate::{
Layers, Modules, TextAttrs, TextBuffer, TextData, TextTexture, TextureHandle, Textures,
UiRegion, UiVec2, Vec2, WidgetId, Widgets,
},
render::{Primitive, PrimitiveHandle},
util::{HashMap, HashSet, Id},
render::{Mask, MaskIdx, Primitive, PrimitiveHandle, PrimitiveInst},
util::{HashMap, HashSet, Id, TrackedArena},
};
pub struct Painter<'a, 'c> {
ctx: &'a mut PainterCtx<'c>,
region: UiRegion,
mask: MaskIdx,
textures: Vec<TextureHandle>,
primitives: Vec<PrimitiveHandle>,
children: Vec<Id>,
@@ -25,6 +26,7 @@ pub struct PainterCtx<'a> {
pub active: &'a mut HashMap<Id, WidgetInstance>,
pub layers: &'a mut Layers,
pub textures: &'a mut Textures,
pub masks: &'a mut TrackedArena<Mask, u32>,
pub text: &'a mut TextData,
pub screen_size: Vec2,
pub modules: &'a mut Modules,
@@ -40,9 +42,11 @@ pub struct WidgetInstance {
pub primitives: Vec<PrimitiveHandle>,
pub children: Vec<Id>,
pub resize: Option<(Id, UiVec2)>,
pub mask: MaskIdx,
pub layer: usize,
}
#[derive(Default)]
pub struct PainterData {
pub widgets: Widgets,
pub active: HashMap<Id, WidgetInstance>,
@@ -52,21 +56,7 @@ pub struct PainterData {
pub output_size: Vec2,
pub modules: Modules,
pub px_dependent: HashSet<Id>,
}
impl Default for PainterData {
fn default() -> Self {
Self {
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(),
}
}
pub masks: TrackedArena<Mask, u32>,
}
impl<'a> PainterCtx<'a> {
@@ -80,6 +70,7 @@ impl<'a> PainterCtx<'a> {
screen_size: data.output_size,
modules: &mut data.modules,
px_dependent: &mut data.px_dependent,
masks: &mut data.masks,
draw_started: HashSet::default(),
}
}
@@ -122,6 +113,7 @@ impl<'a> PainterCtx<'a> {
id,
active.region,
active.parent,
active.mask,
Some(active.children),
);
self.active.get_mut(&id).unwrap().resize = active.resize;
@@ -130,7 +122,7 @@ impl<'a> PainterCtx<'a> {
pub fn draw(&mut self, id: Id) {
self.draw_started.clear();
self.layers.clear();
self.draw_inner(0, id, UiRegion::full(), None, None);
self.draw_inner(0, id, UiRegion::full(), None, MaskIdx::NONE, None);
}
fn draw_inner(
@@ -139,6 +131,7 @@ impl<'a> PainterCtx<'a> {
id: Id,
region: UiRegion,
parent: Option<Id>,
mask: MaskIdx,
old_children: Option<Vec<Id>>,
) {
// I have no idea if these checks work lol
@@ -173,6 +166,7 @@ impl<'a> PainterCtx<'a> {
let mut painter = Painter {
region,
mask,
layer,
id,
textures: Vec::new(),
@@ -196,6 +190,7 @@ impl<'a> PainterCtx<'a> {
primitives: painter.primitives,
children: painter.children,
resize,
mask: painter.mask,
layer,
};
for (cid, size) in sized_children {
@@ -238,7 +233,10 @@ impl<'a> PainterCtx<'a> {
let mut inst = self.active.remove(&id);
if let Some(inst) = &mut inst {
for h in &inst.primitives {
self.layers.free(h);
let mask = self.layers.free(h);
if mask != MaskIdx::NONE {
self.masks.remove(mask);
}
}
inst.textures.clear();
self.textures.free();
@@ -263,10 +261,19 @@ impl<'a> PainterCtx<'a> {
impl<'a, 'c> Painter<'a, 'c> {
fn primitive_at<P: Primitive>(&mut self, primitive: P, region: UiRegion) {
let h = self
.ctx
.layers
.write(self.layer, self.id, primitive, region);
let h = self.ctx.layers.write(
self.layer,
PrimitiveInst {
id: self.id,
primitive,
region,
mask_idx: self.mask,
},
);
if self.mask != MaskIdx::NONE {
// TODO: I have no clue if this works at all :joy:
self.ctx.masks.push_ref(self.mask);
}
self.primitives.push(h);
}
@@ -279,6 +286,11 @@ impl<'a, 'c> Painter<'a, 'c> {
self.primitive_at(primitive, region.within(&self.region));
}
pub fn set_mask(&mut self, region: UiRegion) {
assert!(self.mask == MaskIdx::NONE);
self.mask = self.ctx.masks.push(Mask { region });
}
/// Draws a widget within this widget's region.
pub fn widget<W>(&mut self, id: &WidgetId<W>) {
self.widget_at(id, self.region);
@@ -293,7 +305,7 @@ impl<'a, 'c> Painter<'a, 'c> {
fn widget_at<W>(&mut self, id: &WidgetId<W>, region: UiRegion) {
self.children.push(id.id);
self.ctx
.draw_inner(self.layer, id.id, region, Some(self.id), None);
.draw_inner(self.layer, id.id, region, Some(self.id), self.mask, None);
}
pub fn texture_within(&mut self, handle: &TextureHandle, region: UiRegion) {