An applicaiton and simulator for a bike lighting system #245
|
@ -7,31 +7,30 @@ mod types;
|
||||||
pub use types::{DashboardPattern, Pattern, RGB};
|
pub use types::{DashboardPattern, Pattern, RGB};
|
||||||
|
|
||||||
pub trait UI {
|
pub trait UI {
|
||||||
|
fn check_event(&self) -> Option<Event>;
|
||||||
fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern);
|
fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Animation {
|
pub trait Animation {
|
||||||
fn tick(&self, frame: Duration) -> (DashboardPattern, Pattern);
|
fn tick(&self, time: std::time::Instant) -> (DashboardPattern, Pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DefaultAnimation {}
|
pub struct DefaultAnimation {}
|
||||||
|
|
||||||
impl Animation for DefaultAnimation {
|
impl Animation for DefaultAnimation {
|
||||||
fn tick(&self, _: Duration) -> (DashboardPattern, Pattern) {
|
fn tick(&self, time: std::time::Instant) -> (DashboardPattern, Pattern) {
|
||||||
(PRIDE_DASHBOARD, PRIDE)
|
(PRIDE_DASHBOARD, PRIDE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
Brake,
|
Brake,
|
||||||
BrakeRelease,
|
BrakeRelease,
|
||||||
LeftBlinker,
|
LeftBlinker,
|
||||||
LeftBlinkerRelease,
|
|
||||||
NextPattern,
|
NextPattern,
|
||||||
PreviousPattern,
|
PreviousPattern,
|
||||||
RightBlinker,
|
RightBlinker,
|
||||||
RightBlinkerRelease,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -63,8 +62,12 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(&mut self, frame: Duration) {
|
pub fn tick(&mut self, time: std::time::Instant) {
|
||||||
let (dashboard, lights) = self.current_animation.tick(frame);
|
match self.ui.check_event() {
|
||||||
|
Some(event) => println!("event received: {:?}", event),
|
||||||
|
None => (),
|
||||||
|
};
|
||||||
|
let (dashboard, lights) = self.current_animation.tick(time);
|
||||||
self.dashboard_lights = dashboard.clone();
|
self.dashboard_lights = dashboard.clone();
|
||||||
self.lights = lights.clone();
|
self.lights = lights.clone();
|
||||||
self.ui.update_lights(dashboard, lights);
|
self.ui.update_lights(dashboard, lights);
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use glib::{Object, Sender};
|
use glib::{Object, Sender};
|
||||||
use gtk::subclass::prelude::*;
|
use gtk::subclass::prelude::*;
|
||||||
use lights_core::{App, DashboardPattern, Pattern, RGB, UI};
|
use lights_core::{App, DashboardPattern, Event, Pattern, RGB, UI};
|
||||||
use std::{cell::RefCell, env, rc::Rc};
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
env,
|
||||||
|
rc::Rc,
|
||||||
|
sync::mpsc::{Receiver, TryRecvError},
|
||||||
|
};
|
||||||
|
|
||||||
const WIDTH: i32 = 640;
|
const WIDTH: i32 = 640;
|
||||||
const HEIGHT: i32 = 480;
|
const HEIGHT: i32 = 480;
|
||||||
|
@ -202,19 +207,27 @@ impl BikeLights {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GTKUI {
|
struct GTKUI {
|
||||||
tx: Rc<RefCell<Option<Sender<Update>>>>,
|
tx: Sender<Update>,
|
||||||
|
rx: Receiver<Event>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UI for GTKUI {
|
impl UI for GTKUI {
|
||||||
|
fn check_event(&self) -> Option<Event> {
|
||||||
|
match self.rx.try_recv() {
|
||||||
|
Ok(event) => Some(event),
|
||||||
|
Err(TryRecvError::Empty) => None,
|
||||||
|
Err(TryRecvError::Disconnected) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern) {
|
fn update_lights(&self, dashboard_lights: DashboardPattern, lights: Pattern) {
|
||||||
if let Some(tx) = self.tx.borrow().as_ref() {
|
self.tx
|
||||||
tx.send(Update {
|
.send(Update {
|
||||||
dashboard: dashboard_lights,
|
dashboard: dashboard_lights,
|
||||||
lights,
|
lights,
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -223,14 +236,17 @@ fn main() {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
adw_app.connect_activate(move |adw_app| {
|
adw_app.connect_activate(move |adw_app| {
|
||||||
let (tx, rx) = gtk::glib::MainContext::channel::<Update>(gtk::glib::Priority::DEFAULT);
|
let (update_tx, update_rx) =
|
||||||
|
gtk::glib::MainContext::channel::<Update>(gtk::glib::Priority::DEFAULT);
|
||||||
|
let (event_tx, event_rx) = std::sync::mpsc::channel();
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
let mut bike_app = App::new(Box::new(GTKUI {
|
let mut bike_app = App::new(Box::new(GTKUI {
|
||||||
tx: Rc::new(RefCell::new(Some(tx))),
|
tx: update_tx,
|
||||||
|
rx: event_rx,
|
||||||
}));
|
}));
|
||||||
loop {
|
loop {
|
||||||
bike_app.tick(std::time::Duration::from_millis(0));
|
bike_app.tick(std::time::Instant::now());
|
||||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -254,6 +270,27 @@ fn main() {
|
||||||
let brake_button = gtk::Button::builder().label("Brakes").build();
|
let brake_button = gtk::Button::builder().label("Brakes").build();
|
||||||
let right_button = gtk::Button::builder().label("R").build();
|
let right_button = gtk::Button::builder().label("R").build();
|
||||||
|
|
||||||
|
left_button.connect_clicked({
|
||||||
|
let event_tx = event_tx.clone();
|
||||||
|
move |_| {
|
||||||
|
let _ = event_tx.send(Event::LeftBlinker);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
brake_button.connect_clicked({
|
||||||
|
let event_tx = event_tx.clone();
|
||||||
|
move |_| {
|
||||||
|
let _ = event_tx.send(Event::Brake);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
right_button.connect_clicked({
|
||||||
|
let event_tx = event_tx.clone();
|
||||||
|
move |_| {
|
||||||
|
let _ = event_tx.send(Event::RightBlinker);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
controls.append(&left_button);
|
controls.append(&left_button);
|
||||||
controls.append(&brake_button);
|
controls.append(&brake_button);
|
||||||
controls.append(&right_button);
|
controls.append(&right_button);
|
||||||
|
@ -273,7 +310,7 @@ fn main() {
|
||||||
layout.append(&dashboard_lights);
|
layout.append(&dashboard_lights);
|
||||||
layout.append(&bike_lights);
|
layout.append(&bike_lights);
|
||||||
|
|
||||||
rx.attach(None, {
|
update_rx.attach(None, {
|
||||||
let dashboard_lights = dashboard_lights.clone();
|
let dashboard_lights = dashboard_lights.clone();
|
||||||
let bike_lights = bike_lights.clone();
|
let bike_lights = bike_lights.clone();
|
||||||
move |Update { dashboard, lights }| {
|
move |Update { dashboard, lights }| {
|
||||||
|
|
Loading…
Reference in New Issue