senses are now bitflags
This commit is contained in:
@@ -1,27 +1,27 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub trait Sensable<W, Tag> {
|
||||
fn on(self, sense: Sense, f: impl SenseFn) -> WidgetIdFnRet!(W);
|
||||
fn on(self, sense: Senses, f: impl SenseFn) -> WidgetIdFnRet!(W);
|
||||
fn id_on(
|
||||
self,
|
||||
sense: Sense,
|
||||
senses: Senses,
|
||||
f: impl FnMut(&WidgetId<W>, &mut Ui) + 'static + Clone,
|
||||
) -> WidgetIdFnRet!(W)
|
||||
where
|
||||
W: Widget;
|
||||
fn edit_on(self, sense: Sense, f: impl FnMut(&mut W) + 'static + Clone) -> WidgetIdFnRet!(W)
|
||||
fn edit_on(self, senses: Senses, f: impl FnMut(&mut W) + 'static + Clone) -> WidgetIdFnRet!(W)
|
||||
where
|
||||
W: Widget;
|
||||
}
|
||||
|
||||
impl<W: WidgetLike<Tag>, Tag> Sensable<W::Widget, Tag> for W {
|
||||
fn on(self, sense: Sense, f: impl SenseFn) -> WidgetIdFnRet!(W::Widget) {
|
||||
fn on(self, senses: Senses, f: impl SenseFn) -> WidgetIdFnRet!(W::Widget) {
|
||||
move |ui| {
|
||||
let id = self.add(ui);
|
||||
ui.add_sensor(
|
||||
&id,
|
||||
Sensor {
|
||||
sense,
|
||||
senses,
|
||||
f: Box::new(f),
|
||||
},
|
||||
);
|
||||
@@ -30,7 +30,7 @@ impl<W: WidgetLike<Tag>, Tag> Sensable<W::Widget, Tag> for W {
|
||||
}
|
||||
fn id_on(
|
||||
self,
|
||||
sense: Sense,
|
||||
senses: Senses,
|
||||
mut f: impl FnMut(&WidgetId<W::Widget>, &mut Ui) + 'static + Clone,
|
||||
) -> WidgetIdFnRet!(W::Widget)
|
||||
where
|
||||
@@ -38,17 +38,17 @@ impl<W: WidgetLike<Tag>, Tag> Sensable<W::Widget, Tag> for W {
|
||||
{
|
||||
self.with_id(move |ui, id| {
|
||||
let id2 = id.clone();
|
||||
ui.add(id.on(sense, move |ui| f(&id2, ui)))
|
||||
ui.add(id.on(senses, move |ui| f(&id2, ui)))
|
||||
})
|
||||
}
|
||||
fn edit_on(
|
||||
self,
|
||||
sense: Sense,
|
||||
senses: Senses,
|
||||
mut f: impl FnMut(&mut W::Widget) + 'static + Clone,
|
||||
) -> WidgetIdFnRet!(W::Widget)
|
||||
where
|
||||
W::Widget: Widget,
|
||||
{
|
||||
self.id_on(sense, move |id, ui| f(&mut ui[id]))
|
||||
self.id_on(senses, move |id, ui| f(&mut ui[id]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
use crate::{
|
||||
layout::{Ui, UiRegion, Vec2, WidgetId},
|
||||
util::HashMap,
|
||||
util::Id,
|
||||
util::{HashMap, Id, bitflags},
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum Sense {
|
||||
PressStart,
|
||||
Pressing,
|
||||
PressEnd,
|
||||
HoverStart,
|
||||
Hovering,
|
||||
HoverEnd,
|
||||
NotHovering,
|
||||
}
|
||||
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,
|
||||
1 << 6; NotHovering, NOT_HOVERING,
|
||||
});
|
||||
|
||||
pub struct CursorState {
|
||||
pub pos: Vec2,
|
||||
@@ -31,18 +29,13 @@ pub enum ActivationState {
|
||||
}
|
||||
|
||||
pub struct Sensor {
|
||||
pub sense: Sense,
|
||||
pub senses: Senses,
|
||||
pub f: Box<dyn SenseFn>,
|
||||
}
|
||||
|
||||
pub type SensorMap = HashMap<Id, SensorGroup>;
|
||||
pub type ActiveSensors = HashMap<Id, SenseShape>;
|
||||
pub type SenseShape = UiRegion;
|
||||
#[derive(Clone)]
|
||||
pub struct SenseTrigger {
|
||||
pub shape: SenseShape,
|
||||
pub sense: Sense,
|
||||
}
|
||||
#[derive(Default)]
|
||||
pub struct SensorGroup {
|
||||
pub hover: ActivationState,
|
||||
@@ -78,7 +71,7 @@ impl Ui {
|
||||
group.cursor.update(cursor.pressed && in_shape);
|
||||
|
||||
for sensor in &mut group.sensors {
|
||||
if should_run(sensor.sense, group.cursor, group.hover) {
|
||||
if should_run(sensor.senses, group.cursor, group.hover) {
|
||||
(sensor.f.box_clone())(self);
|
||||
}
|
||||
}
|
||||
@@ -88,16 +81,21 @@ impl Ui {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn should_run(sense: Sense, cursor: ActivationState, hover: ActivationState) -> bool {
|
||||
match sense {
|
||||
Sense::PressStart => cursor.is_start(),
|
||||
Sense::Pressing => cursor.is_on(),
|
||||
Sense::PressEnd => cursor.is_end(),
|
||||
Sense::HoverStart => hover.is_start(),
|
||||
Sense::Hovering => hover.is_on(),
|
||||
Sense::HoverEnd => hover.is_end(),
|
||||
Sense::NotHovering => hover.is_off(),
|
||||
pub fn should_run(senses: Senses, cursor: ActivationState, 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::HoverStart => hover.is_start(),
|
||||
Sense::Hovering => hover.is_on(),
|
||||
Sense::HoverEnd => hover.is_end(),
|
||||
Sense::NotHovering => hover.is_off(),
|
||||
} {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
impl ActivationState {
|
||||
@@ -147,7 +145,7 @@ impl Clone for SensorGroup {
|
||||
impl Clone for Sensor {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
sense: self.sense,
|
||||
senses: self.senses,
|
||||
f: self.f.box_clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ use std::sync::Arc;
|
||||
|
||||
use app::App;
|
||||
use render::Renderer;
|
||||
use senses::*;
|
||||
use ui::prelude::*;
|
||||
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
|
||||
|
||||
@@ -29,22 +30,19 @@ impl Client {
|
||||
|
||||
let mut ui = Ui::new();
|
||||
let rect = Rect {
|
||||
color: UiColor::WHITE,
|
||||
color: Color::WHITE,
|
||||
radius: 20.0,
|
||||
thickness: 0.0,
|
||||
inner_radius: 0.0,
|
||||
};
|
||||
let pad_test = ui.add_static(
|
||||
(
|
||||
rect.color(UiColor::BLUE),
|
||||
rect.color(Color::BLUE),
|
||||
(
|
||||
rect.color(UiColor::RED).center((100.0, 100.0)),
|
||||
(
|
||||
rect.color(UiColor::ORANGE),
|
||||
rect.color(UiColor::LIME).pad(10.0),
|
||||
)
|
||||
rect.color(Color::RED).center((100.0, 100.0)),
|
||||
(rect.color(Color::ORANGE), rect.color(Color::LIME).pad(10.0))
|
||||
.span(Dir::RIGHT, [1, 1]),
|
||||
rect.color(UiColor::YELLOW),
|
||||
rect.color(Color::YELLOW),
|
||||
)
|
||||
.span(Dir::RIGHT, [2, 2, 1])
|
||||
.pad(10),
|
||||
@@ -53,12 +51,12 @@ impl Client {
|
||||
);
|
||||
let span_test = ui.add_static(
|
||||
(
|
||||
rect.color(UiColor::GREEN),
|
||||
rect.color(UiColor::ORANGE),
|
||||
rect.color(UiColor::CYAN),
|
||||
rect.color(UiColor::BLUE),
|
||||
rect.color(UiColor::MAGENTA),
|
||||
rect.color(UiColor::RED),
|
||||
rect.color(Color::GREEN),
|
||||
rect.color(Color::ORANGE),
|
||||
rect.color(Color::CYAN),
|
||||
rect.color(Color::BLUE),
|
||||
rect.color(Color::MAGENTA),
|
||||
rect.color(Color::RED),
|
||||
)
|
||||
.span(
|
||||
Dir::LEFT,
|
||||
@@ -77,17 +75,14 @@ impl Client {
|
||||
|
||||
let switch_button = |color, to, label| {
|
||||
let rect = Rect::new(color)
|
||||
.id_on(Sense::PressStart, move |id, ui| {
|
||||
.id_on(PRESS_START, move |id, ui| {
|
||||
ui[main].inner.set_static(to);
|
||||
ui[id].color = color.add_rgb(-0.2);
|
||||
})
|
||||
.edit_on(Sense::HoverStart, move |r| {
|
||||
.edit_on(HOVER_START | PRESS_END, move |r| {
|
||||
r.color = color.add_rgb(0.4);
|
||||
})
|
||||
.edit_on(Sense::PressEnd, move |r| {
|
||||
r.color = color.add_rgb(0.4);
|
||||
})
|
||||
.edit_on(Sense::HoverEnd, move |r| {
|
||||
.edit_on(HOVER_END, move |r| {
|
||||
r.color = color;
|
||||
});
|
||||
(rect, text(label).size(30)).stack()
|
||||
@@ -95,15 +90,15 @@ impl Client {
|
||||
|
||||
let tabs = ui.add(
|
||||
(
|
||||
switch_button(UiColor::RED, pad_test, "pad test"),
|
||||
switch_button(UiColor::GREEN, span_test, "span test"),
|
||||
switch_button(UiColor::BLUE, span_add, "span add test"),
|
||||
switch_button(Color::RED, pad_test, "pad test"),
|
||||
switch_button(Color::GREEN, span_test, "span test"),
|
||||
switch_button(Color::BLUE, span_add, "span add test"),
|
||||
)
|
||||
.span(Dir::RIGHT, [1, 1, 1]),
|
||||
);
|
||||
let add_button = Rect::new(Color::LIME)
|
||||
.radius(30)
|
||||
.on(Sense::PressStart, move |ui| {
|
||||
.on(PRESS_START, move |ui| {
|
||||
let child = ui
|
||||
.add(image(include_bytes!("assets/sungals.png")))
|
||||
.erase_type();
|
||||
@@ -117,7 +112,7 @@ impl Client {
|
||||
|
||||
let del_button = Rect::new(Color::RED)
|
||||
.radius(30)
|
||||
.on(Sense::PressStart, move |ui| {
|
||||
.on(PRESS_START, move |ui| {
|
||||
ui[span_add].children.pop();
|
||||
})
|
||||
.region(
|
||||
|
||||
52
src/util/bitflags.rs
Normal file
52
src/util/bitflags.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
macro_rules! bitflags {
|
||||
($enum:ident, $struct:ident, $mod:ident {$($val:expr; $ename:ident, $sname:ident,)*}) => {
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum $enum {
|
||||
$($ename = $val,)*
|
||||
}
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub struct $struct(u32);
|
||||
#[allow(non_upper_case_globals)]
|
||||
impl $struct {
|
||||
$(pub const $sname: Self = Self($enum::$ename as u32);)*
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = $enum> {
|
||||
$crate::util::Biterator::new(self.0).map(|v| unsafe {std::mem::transmute(v)})
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitOr for $struct {
|
||||
type Output = Self;
|
||||
fn bitor(self, rhs: $struct) -> Self {
|
||||
Self(self.0 | rhs.0)
|
||||
}
|
||||
}
|
||||
pub mod $mod {
|
||||
use super::*;
|
||||
$(pub const $sname: $struct = $struct::$sname;)*
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use bitflags;
|
||||
|
||||
pub struct Biterator(u32);
|
||||
|
||||
impl Iterator for Biterator {
|
||||
type Item = u32;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.0 == 0 {
|
||||
return None;
|
||||
}
|
||||
let val = 1 << self.0.trailing_zeros();
|
||||
self.0 &= !val;
|
||||
Some(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl Biterator {
|
||||
pub fn new(val: u32) -> Self {
|
||||
Self(val)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
mod id;
|
||||
mod math;
|
||||
mod refcount;
|
||||
mod bitflags;
|
||||
|
||||
pub(crate) use id::*;
|
||||
pub(crate) use math::*;
|
||||
pub(crate) use refcount::*;
|
||||
pub(crate) use bitflags::*;
|
||||
|
||||
pub type HashMap<K, V> = std::collections::HashMap<K, V>;
|
||||
pub type HashSet<K> = std::collections::HashSet<K>;
|
||||
|
||||
Reference in New Issue
Block a user