diff --git a/src/layout/layer.rs b/src/layout/layer.rs index 7b7a7fd..baa16e8 100644 --- a/src/layout/layer.rs +++ b/src/layout/layer.rs @@ -1,16 +1,16 @@ use std::ops::{Index, IndexMut}; use crate::{ - layout::UiRegion, + layout::{SenseShape, UiRegion}, render::{Primitive, PrimitiveHandle, Primitives}, - util::Id, + util::{HashMap, Id}, }; -struct LayerNode { +struct LayerNode { prev: Option, next: Next, child: Option, - data: T, + data: Layer, } #[derive(Clone, Copy)] @@ -23,29 +23,29 @@ enum Next { None, } -pub struct Layers { - vec: Vec>, +pub struct Layers { + vec: Vec, } -impl Layers { - pub fn new() -> Layers - where - T: Default, - { +#[derive(Default)] +pub struct Layer { + pub primitives: Primitives, + pub sensors: HashMap, +} + +impl Layers { + pub fn new() -> Layers { Self { vec: vec![LayerNode::head()], } } - pub fn clear(&mut self) - where - T: Default, - { + pub fn clear(&mut self) { self.vec.clear(); self.vec.push(LayerNode::head()); } - fn push(&mut self, node: LayerNode) -> usize { + fn push(&mut self, node: LayerNode) -> usize { let i = self.vec.len(); self.vec.push(node); i @@ -55,7 +55,7 @@ impl Layers { if let Next::Same(i) = self.vec[i].next { return i; } - let i_next = self.push(LayerNode::new(T::default(), self.vec[i].next)); + let i_next = self.push(LayerNode::new(Layer::default(), self.vec[i].next)); self.vec[i].next = Next::Same(i_next); self.vec[i_next].prev = Some(i); i_next @@ -65,42 +65,56 @@ impl Layers { if let Some(i) = self.vec[i].child { return i; } - let i_next = self.push(LayerNode::new(T::default(), Next::Parent(i))); + let i_next = self.push(LayerNode::new(Layer::default(), Next::Parent(i))); self.vec[i].child = Some(i_next); self.vec[i_next].prev = Some(i); i_next } - pub fn iter_mut(&mut self) -> LayerIteratorMut<'_, T> { + pub fn iter_mut(&mut self) -> LayerIteratorMut<'_> { LayerIteratorMut { next: Some(0), vec: &mut self.vec, } } + + pub fn write( + &mut self, + layer: usize, + id: Id, + primitive: P, + region: UiRegion, + ) -> PrimitiveHandle { + self[layer].primitives.write(layer, id, primitive, region) + } + + pub fn free(&mut self, h: &PrimitiveHandle) { + self[h.layer].primitives.free(h) + } } -impl Default for Layers { +impl Default for Layers { fn default() -> Self { Self::new() } } -impl Index for Layers { - type Output = T; +impl Index for Layers { + type Output = Layer; fn index(&self, index: usize) -> &Self::Output { &self.vec[index].data } } -impl IndexMut for Layers { +impl IndexMut for Layers { fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut self.vec[index].data } } -impl LayerNode { - pub fn new(data: T, next: Next) -> Self { +impl LayerNode { + pub fn new(data: Layer, next: Next) -> Self { Self { prev: None, next, @@ -109,26 +123,23 @@ impl LayerNode { } } - pub fn head() -> Self - where - T: Default, - { - Self::new(T::default(), Next::None) + pub fn head() -> Self { + Self::new(Layer::default(), Next::None) } } -pub struct LayerIteratorMut<'a, T> { +pub struct LayerIteratorMut<'a> { next: Option, - vec: &'a mut Vec>, + vec: &'a mut Vec, } -impl<'a, T> Iterator for LayerIteratorMut<'a, T> { - type Item = (usize, &'a mut T); +impl<'a> Iterator for LayerIteratorMut<'a> { + type Item = (usize, &'a mut Layer); fn next(&mut self) -> Option { // chat are we cooked? (if it's not set up correctly this could be catastrophic) let ret_i = self.next?; - let node: &mut LayerNode = unsafe { std::mem::transmute(&mut self.vec[ret_i]) }; + let node: &mut LayerNode = unsafe { std::mem::transmute(&mut self.vec[ret_i]) }; self.next = if let Some(i) = node.child { Some(i) } else if let Next::Same(i) = node.next { @@ -146,19 +157,3 @@ impl<'a, T> Iterator for LayerIteratorMut<'a, T> { Some((ret_i, &mut node.data)) } } - -impl Layers { - pub fn write( - &mut self, - layer: usize, - id: Id, - primitive: P, - region: UiRegion, - ) -> PrimitiveHandle { - self[layer].write(layer, id, primitive, region) - } - - pub fn free(&mut self, h: &PrimitiveHandle) { - self[h.layer].free(h) - } -} diff --git a/src/layout/painter.rs b/src/layout/painter.rs index 79c956f..f0ee5d0 100644 --- a/src/layout/painter.rs +++ b/src/layout/painter.rs @@ -1,9 +1,9 @@ use crate::{ layout::{ - Active, Layers, TextAttrs, TextBuffer, TextData, TextOffset, TextureHandle, Textures, - UiRegion, UiVec2, Vec2, WidgetId, Widgets, + ActiveWidgets, Layers, TextAttrs, TextBuffer, TextData, TextOffset, TextureHandle, + Textures, UiRegion, UiVec2, Vec2, WidgetId, Widgets, }, - render::{Primitive, PrimitiveHandle, Primitives}, + render::{Primitive, PrimitiveHandle}, util::{HashMap, HashSet, Id, IdUtil}, }; @@ -20,8 +20,8 @@ pub struct Painter<'a, 'c> { pub struct PainterCtx<'a> { pub widgets: &'a Widgets, - pub active: &'a mut Active, - pub layers: &'a mut Layers, + pub active: &'a mut ActiveWidgets, + pub layers: &'a mut Layers, pub textures: &'a mut Textures, pub text: &'a mut TextData, pub screen_size: Vec2, @@ -42,8 +42,8 @@ pub struct WidgetInstance { impl<'a> PainterCtx<'a> { pub fn new( widgets: &'a Widgets, - layers: &'a mut Layers, - active: &'a mut Active, + layers: &'a mut Layers, + active: &'a mut ActiveWidgets, textures: &'a mut Textures, text: &'a mut TextData, screen_size: Vec2, @@ -61,7 +61,7 @@ impl<'a> PainterCtx<'a> { pub fn redraw(&mut self, id: &Id) { self.drawing.clear(); - let Some(active) = self.active.widgets.get(id) else { + let Some(active) = self.active.get(id) else { return; }; @@ -83,7 +83,7 @@ impl<'a> PainterCtx<'a> { active.parent.duplicate(), Some(active.children), ); - self.active.widgets.get_mut(id).unwrap().resize = active.resize; + self.active.get_mut(id).unwrap().resize = active.resize; } pub fn draw(&mut self, id: &Id) { @@ -111,7 +111,7 @@ 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_mut(id) { + if let Some(active) = self.active.get_mut(id) { if active.parent != parent { panic!("Cannot draw the same widget twice (2)"); } @@ -155,7 +155,7 @@ impl<'a> PainterCtx<'a> { layer, }; for (cid, size) in sized_children { - if let Some(w) = self.active.widgets.get_mut(&cid) { + if let Some(w) = self.active.get_mut(&cid) { w.resize = Some((id.duplicate(), size)) } } @@ -165,7 +165,12 @@ impl<'a> PainterCtx<'a> { } } - self.active.add(id, instance, self.widgets); + if self.widgets.data(id).is_some_and(|w| w.sensor) { + self.layers[layer] + .sensors + .insert(id.duplicate(), instance.region); + } + self.active.insert(id.duplicate(), instance); } /// NOTE: instance textures are cleared and self.textures freed @@ -177,6 +182,7 @@ impl<'a> PainterCtx<'a> { } inst.textures.clear(); self.textures.free(); + self.layers[inst.layer].sensors.remove(id); } inst } diff --git a/src/layout/sense.rs b/src/layout/sense.rs index 96f7165..c8af8f1 100644 --- a/src/layout/sense.rs +++ b/src/layout/sense.rs @@ -2,7 +2,7 @@ use std::ops::{BitOr, Deref, DerefMut}; use crate::{ layout::{Ui, UiRegion, Vec2}, - util::{HashMap, Id, IdVec}, + util::{HashMap, Id}, }; pub trait CursorCtx { @@ -80,7 +80,6 @@ pub struct Sensor { } pub type SensorMap = HashMap>; -pub type ActiveSensors = IdVec; pub type SenseShape = UiRegion; pub struct SensorGroup { pub hover: ActivationState, @@ -105,26 +104,34 @@ pub trait UiCtx { /// it extends so you can add to it, but you can't actually index sensors with it /// should something be done about this? pub fn run_sensors(ctx: &mut Ctx, cursor: &CursorState, window_size: Vec2) { - let active = std::mem::take(&mut ctx.ui().active.sensors); + let mut layers = std::mem::take(&mut ctx.ui().layers); let mut map = std::mem::take(&mut ctx.ui().sensor_map); - for (id, shape) in active.iter().rev() { - let group = &mut map.get_mut(id).unwrap(); - let region = shape.to_screen(window_size); - let in_shape = cursor.exists && region.contains(cursor.pos); - group.hover.update(in_shape); - if group.hover == ActivationState::Off { - continue; - } - + // temp solution, should probably cache somewhere + let mut bruh = Vec::new(); + for (i, _) in layers.iter_mut() { + bruh.push(i) + } + for i in bruh.into_iter().rev() { + let layer = &layers[i]; let mut ran = false; - for sensor in &mut group.sensors { - if should_run(&sensor.senses, &cursor.buttons, group.hover) { - ran = true; - let sctx = SenseCtx { - cursor: cursor.pos - region.top_left, - size: region.bot_right - region.top_left, - }; - (sensor.f)(ctx, sctx); + for (id, shape) in &layer.sensors { + let group = &mut map.get_mut(id).unwrap(); + let region = shape.to_screen(window_size); + let in_shape = cursor.exists && region.contains(cursor.pos); + group.hover.update(in_shape); + if group.hover == ActivationState::Off { + continue; + } + + for sensor in &mut group.sensors { + if should_run(&sensor.senses, &cursor.buttons, group.hover) { + ran = true; + let sctx = SenseCtx { + cursor: cursor.pos - region.top_left, + size: region.bot_right - region.top_left, + }; + (sensor.f)(ctx, sctx); + } } } if ran { @@ -133,9 +140,10 @@ pub fn run_sensors(ctx: &mut Ctx, cursor: &CursorState, window_size: } let ui = ctx.ui(); std::mem::swap(&mut ui.sensor_map, &mut map); + // TODO: this removes existing sensors (if a new one is added to an id) lol + // the proper code is easy but writing this comment is easier and I'm tired ui.sensor_map.extend(map); - assert!(ui.active.sensors.is_empty()); - ui.active.sensors = active; + ui.layers = layers; } pub fn should_run(senses: &Senses, cursor: &CursorButtons, hover: ActivationState) -> bool { diff --git a/src/layout/ui.rs b/src/layout/ui.rs index 9e14faa..f40885f 100644 --- a/src/layout/ui.rs +++ b/src/layout/ui.rs @@ -3,10 +3,9 @@ use image::DynamicImage; use crate::{ core::{TextEdit, TextEditCtx}, layout::{ - ActiveSensors, Layers, PainterCtx, Sensor, SensorMap, StaticWidgetId, TextData, - TextureHandle, Textures, Vec2, Widget, WidgetId, WidgetInstance, WidgetLike, + Layers, PainterCtx, Sensor, SensorMap, StaticWidgetId, TextData, TextureHandle, Textures, + Vec2, Widget, WidgetId, WidgetInstance, WidgetLike, }, - render::Primitives, util::{DynBorrower, HashMap, HashSet, Id, IdTracker}, }; use std::{ @@ -23,12 +22,12 @@ pub struct Ui { pub(super) send: Sender, size: Vec2, // TODO: make these non pub(crate) - pub(crate) layers: Layers, + pub(crate) layers: Layers, pub(crate) textures: Textures, pub(crate) text: TextData, full_redraw: bool, - pub(crate) active: Active, + pub(crate) active: ActiveWidgets, pub(super) sensor_map: SensorMap, } @@ -182,7 +181,7 @@ impl Ui { } pub fn active_widgets(&self) -> usize { - self.active.widgets.len() + self.active.len() } pub fn add_sensor(&mut self, id: &WidgetId, f: Sensor) { @@ -357,29 +356,3 @@ impl Default for Ui { } pub type ActiveWidgets = HashMap; - -#[derive(Default)] -pub struct Active { - pub sensors: ActiveSensors, - pub widgets: ActiveWidgets, -} - -impl Active { - pub fn clear(&mut self) { - self.sensors.clear(); - self.widgets.clear(); - } - - pub fn remove(&mut self, id: &Id) -> Option { - let instance = self.widgets.remove(id); - self.sensors.remove(id); - instance - } - - pub fn add(&mut self, id: &Id, instance: WidgetInstance, widgets: &Widgets) { - if widgets.data(id).is_some_and(|w| w.sensor) { - self.sensors.insert(id.duplicate(), instance.region); - } - self.widgets.insert(id.duplicate(), instance); - } -} diff --git a/src/render/mod.rs b/src/render/mod.rs index 2673ba6..cacceb6 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -59,10 +59,11 @@ impl UiRenderer { pub fn update(&mut self, device: &Device, queue: &Queue, ui: &mut Ui) { self.active.clear(); - for (i, primitives) in ui.layers.iter_mut() { + for (i, ulayer) in ui.layers.iter_mut() { self.active.push(i); + let primitives = &mut ulayer.primitives; for change in primitives.apply_free() { - if let Some(inst) = ui.active.widgets.get_mut(&change.id) { + if let Some(inst) = ui.active.get_mut(&change.id) { for h in &mut inst.primitives { if h.inst_idx == change.old { h.inst_idx = change.new; @@ -71,7 +72,7 @@ impl UiRenderer { } } } - let layer = self.layers.entry(i).or_insert_with(|| { + let rlayer = self.layers.entry(i).or_insert_with(|| { let primitives = PrimitiveBuffers::new(device); let primitive_group = Self::primitive_group(device, &self.primitive_layout, primitives.buffers()); @@ -86,12 +87,14 @@ impl UiRenderer { } }); if primitives.updated { - layer.instance.update(device, queue, primitives.instances()); - layer.primitives.update(device, queue, primitives.data()); - layer.primitive_group = Self::primitive_group( + rlayer + .instance + .update(device, queue, primitives.instances()); + rlayer.primitives.update(device, queue, primitives.data()); + rlayer.primitive_group = Self::primitive_group( device, &self.primitive_layout, - layer.primitives.buffers(), + rlayer.primitives.buffers(), ) } } diff --git a/src/util/idvec.rs b/src/util/idvec.rs deleted file mode 100644 index 88f8dd1..0000000 --- a/src/util/idvec.rs +++ /dev/null @@ -1,76 +0,0 @@ -use std::ops::{Deref, Index, IndexMut}; - -use crate::util::{HashMap, id::Id}; - -/// a vec that's indexed with permanent ids rather than an offset -pub struct IdVec { - map: HashMap, - vec: Vec<(Id, T)>, -} - -impl IdVec { - pub fn insert(&mut self, id: Id, v: T) { - let idx = self.vec.len(); - self.map.insert(id.duplicate(), idx); - self.vec.push((id, v)); - } - - pub fn remove(&mut self, id: &Id) -> Option { - let i = self.map.remove(id)?; - let v = self.vec.remove(i).1; - for (id, _) in &self.vec[i..] { - *self.map.get_mut(id).unwrap() -= 1; - } - Some(v) - } - - pub fn len(&self) -> usize { - self.map.len() - } - - pub fn is_empty(&self) -> bool { - self.map.is_empty() - } - - pub fn idx(&self, id: &Id) -> usize { - self.map[id] - } - - pub fn clear(&mut self) { - self.map.clear(); - self.vec.clear(); - } -} - -impl Default for IdVec { - fn default() -> Self { - Self { - map: Default::default(), - vec: Default::default(), - } - } -} - -impl Index<&Id> for IdVec { - type Output = T; - - fn index(&self, id: &Id) -> &Self::Output { - let i = self.idx(id); - &self.vec[i].1 - } -} - -impl IndexMut<&Id> for IdVec { - fn index_mut(&mut self, id: &Id) -> &mut Self::Output { - let i = self.idx(id); - &mut self.vec[i].1 - } -} - -impl Deref for IdVec { - type Target = Vec<(Id, T)>; - - fn deref(&self) -> &Self::Target { - &self.vec - } -} diff --git a/src/util/mod.rs b/src/util/mod.rs index 19d7865..f465f42 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,12 +1,10 @@ mod borrow; mod id; -mod idvec; mod math; mod refcount; pub(crate) use borrow::*; pub(crate) use id::*; -pub(crate) use idvec::*; pub(crate) use math::*; pub(crate) use refcount::*;