sense specific buttons

This commit is contained in:
2025-09-15 22:22:52 -04:00
parent 21aa2b3501
commit b48acccb8d
8 changed files with 167 additions and 107 deletions

View File

@@ -1,21 +1,68 @@
use std::ops::{BitOr, Deref, DerefMut};
use crate::{
layout::{Ui, UiRegion, Vec2},
util::{HashMap, Id, IdVec, bitflags},
util::{HashMap, Id, IdVec},
};
bitflags!(Sense, Senses, senses {
1 << 0; PressStart, PRESS_START,
1 << 1; Pressing, PRESSING,
1 << 2; PressEnd, PRESS_END,
1 << 3; HoverStart, HOVER_START,
1 << 4; Hovering, HOVERING,
1 << 5; HoverEnd, HOVER_END,
});
pub trait CursorCtx {
fn cursor_state(&self) -> &CursorState;
}
pub enum Button {
Left,
Right,
Middle,
}
pub enum Sense {
PressStart(Button),
Pressing(Button),
PressEnd(Button),
HoverStart,
Hovering,
HoverEnd,
}
pub struct Senses(Vec<Sense>);
impl Sense {
pub fn click() -> Self {
Self::PressStart(Button::Left)
}
pub fn unclick() -> Self {
Self::PressEnd(Button::Left)
}
}
#[derive(Default, Clone)]
pub struct CursorState {
pub pos: Vec2,
pub exists: bool,
pub pressed: bool,
pub buttons: CursorButtons,
}
#[derive(Default, Clone)]
pub struct CursorButtons {
pub left: ActivationState,
pub middle: ActivationState,
pub right: ActivationState,
}
impl CursorButtons {
pub fn select(&self, button: &Button) -> &ActivationState {
match button {
Button::Left => &self.left,
Button::Right => &self.right,
Button::Middle => &self.middle,
}
}
pub fn end_frame(&mut self) {
self.left.end_frame();
self.middle.end_frame();
self.right.end_frame();
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
@@ -37,7 +84,6 @@ pub type ActiveSensors = IdVec<SenseShape>;
pub type SenseShape = UiRegion;
pub struct SensorGroup<Ctx> {
pub hover: ActivationState,
pub cursor: ActivationState,
pub sensors: Vec<Sensor<Ctx>>,
}
@@ -63,11 +109,13 @@ pub fn run_sensors<Ctx: UiCtx>(ctx: &mut Ctx, cursor: &CursorState, window_size:
let region = shape.to_screen(window_size);
let in_shape = cursor.exists && region.contains(cursor.pos);
group.hover.update(in_shape);
group.cursor.update(cursor.pressed && in_shape);
if group.hover == ActivationState::Off {
continue;
}
let mut ran = false;
for sensor in &mut group.sensors {
if should_run(sensor.senses, group.cursor, group.hover) {
if should_run(&sensor.senses, &cursor.buttons, group.hover) {
ran = true;
let sctx = SenseCtx {
cursor: cursor.pos - region.top_left,
@@ -84,12 +132,12 @@ pub fn run_sensors<Ctx: UiCtx>(ctx: &mut Ctx, cursor: &CursorState, window_size:
ctx.ui().active.sensors = active;
}
pub fn should_run(senses: Senses, cursor: ActivationState, hover: ActivationState) -> bool {
pub fn should_run(senses: &Senses, cursor: &CursorButtons, hover: ActivationState) -> bool {
for sense in senses.iter() {
if match sense {
Sense::PressStart => cursor.is_start(),
Sense::Pressing => cursor.is_on(),
Sense::PressEnd => cursor.is_end(),
Sense::PressStart(button) => cursor.select(button).is_start(),
Sense::Pressing(button) => cursor.select(button).is_on(),
Sense::PressEnd(button) => cursor.select(button).is_end(),
Sense::HoverStart => hover.is_start(),
Sense::Hovering => hover.is_on(),
Sense::HoverEnd => hover.is_end(),
@@ -133,14 +181,58 @@ impl ActivationState {
},
}
}
pub fn end_frame(&mut self) {
match self {
Self::Start => *self = Self::On,
Self::End => *self = Self::Off,
_ => (),
}
}
}
impl<Ctx> Default for SensorGroup<Ctx> {
fn default() -> Self {
Self {
hover: Default::default(),
cursor: Default::default(),
sensors: Default::default(),
}
}
}
impl Deref for Senses {
type Target = Vec<Sense>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Senses {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl From<Sense> for Senses {
fn from(val: Sense) -> Self {
Senses(vec![val])
}
}
impl BitOr for Sense {
type Output = Senses;
fn bitor(self, rhs: Self) -> Self::Output {
Senses(vec![self, rhs])
}
}
impl BitOr<Sense> for Senses {
type Output = Self;
fn bitor(mut self, rhs: Sense) -> Self::Output {
self.0.push(rhs);
self
}
}