This commit is contained in:
2025-08-16 14:43:36 -04:00
parent b0fe7310eb
commit b2acbcc189

107
:w
View File

@@ -1,107 +0,0 @@
use crate::{HashMap, Ui, UiRegion, Vec2, WidgetId, util::Id};
pub trait SenseCtx: 'static {
fn cursor_state(&self) -> CursorState;
fn window_size(&self) -> Vec2;
fn active(&mut self, trigger: &SenseTrigger) -> bool;
}
#[derive(Clone, Copy, PartialEq)]
pub enum Sense {
PressStart,
Pressing,
PressEnd,
HoverStart,
Hovering,
HoverEnd,
NotHovering,
}
pub struct CursorState {
pos: Vec2,
exists: bool,
primary: ActivationState,
}
#[derive(Debug, Clone, Copy, Default)]
pub enum ActivationState {
Start,
On,
End,
#[default]
Off,
}
pub struct Sensor<Ctx> {
pub sense: Sense,
pub f: Box<dyn SenseFn<Ctx>>,
}
impl<Ctx: 'static> Clone for SensorGroup<Ctx> {
fn clone(&self) -> Self {
Self {
shape: self.shape.clone(),
hover: self.hover.clone(),
f: self.f.box_clone(),
}
}
}
pub type SensorMap<Ctx> = HashMap<Id, Vec<Sensor<Ctx>>>;
pub type ActiveSensors<Ctx> = Vec<SensorGroup<Ctx>>;
pub trait SenseFn_<Ctx> = FnMut(&mut Ui<Ctx>, &mut Ctx) + 'static;
pub type SenseShape = UiRegion;
#[derive(Clone)]
pub struct SenseTrigger {
pub shape: SenseShape,
pub sense: Sense,
}
pub struct SensorGroup<Ctx> {
pub shape: SenseShape,
pub hover: ActivationState,
pub sensors: Vec<Sensor<Ctx>>,
}
pub trait SenseFn<Ctx>: SenseFn_<Ctx> {
fn box_clone(&self) -> Box<dyn SenseFn<Ctx>>;
}
impl<F: SenseFn_<Ctx> + Clone, Ctx> SenseFn<Ctx> for F {
fn box_clone(&self) -> Box<dyn SenseFn<Ctx>> {
Box::new(self.clone())
}
}
impl<Ctx> Ui<Ctx> {
pub fn add_sensor<W>(&mut self, id: &WidgetId<W>, f: Sensor<Ctx>) {
self.sensor_map
.entry(id.id.duplicate())
.or_default()
.push(f);
}
pub fn run_sensors(&mut self, ctx: &mut Ctx, cursor: &CursorState, window_size: Vec2)
where
Ctx: SenseCtx + 'static,
{
let mut groups = std::mem::take(&mut self.active_sensors_swap);
groups.clone_from(&self.active_sensors);
for (hover, sensors) in groups.drain(..).rev() {
for mut sensor in sensors {
if should_run(sensor.trigger, cursor, hover, window_size) {
(sensor.f)(self, ctx);
}
}
}
self.active_sensors_swap = groups;
}
}
pub fn should_run(
trigger: SenseTrigger,
cursor: &CursorState,
hover: ActivationState,
window_size: Vec2,
) -> bool {
let region = trigger.shape.to_screen(window_size);
if !cursor.exists || !region.contains(cursor.pos) {
return trigger.sense == Sense::NotHovering;
}
}