mouse stuff
This commit is contained in:
11
Cargo.lock
generated
11
Cargo.lock
generated
@@ -2787,6 +2787,7 @@ dependencies = [
|
||||
"embedded-graphics",
|
||||
"g13-driver",
|
||||
"mlua",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3448,15 +3449,6 @@ dependencies = [
|
||||
"imgref",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "luau0-src"
|
||||
version = "0.18.2+luau708"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eed3214ab526e7e7b76c3f324a965d363db94a99ae67f65e67ec6fc499eb5e6d"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mach2"
|
||||
version = "0.4.3"
|
||||
@@ -3587,7 +3579,6 @@ dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"luau0-src",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name = "DVD"
|
||||
authors = {"AviiNL"}
|
||||
authors = { "AviiNL" }
|
||||
description = "Bouncing 'dvd' Logo"
|
||||
|
||||
local width = g13.display_width
|
||||
@@ -19,7 +19,7 @@ function setup()
|
||||
joy.deadzone = 40
|
||||
end
|
||||
|
||||
function update(delta: number)
|
||||
function update(delta)
|
||||
x = x + speed * delta * joy.x * 1.2
|
||||
y = y + speed * delta * joy.y
|
||||
|
||||
@@ -29,26 +29,26 @@ function update(delta: number)
|
||||
|
||||
g13.clear()
|
||||
|
||||
g13.set_color(color_x/2, color_y/2, color_z/2)
|
||||
g13.set_color(color_x / 2, color_y / 2, color_z / 2)
|
||||
|
||||
g13.text("Hello World!", 1, 1, true, 0, 0, 1)
|
||||
|
||||
for sy = -size,size do
|
||||
for sx = -size,size do
|
||||
for sy = -size, size do
|
||||
for sx = -size, size do
|
||||
g13.set_pixel(x + sx, y + sy, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function dump(o)
|
||||
if type(o) == 'table' then
|
||||
local s = '{ '
|
||||
for k,v in pairs(o) do
|
||||
if type(k) ~= 'number' then k = '"'..k..'"' end
|
||||
s = s .. '['..k..'] = ' .. dump(v) .. ','
|
||||
end
|
||||
return s .. '} '
|
||||
else
|
||||
return tostring(o)
|
||||
end
|
||||
if type(o) == 'table' then
|
||||
local s = '{ '
|
||||
for k, v in pairs(o) do
|
||||
if type(k) ~= 'number' then k = '"' .. k .. '"' end
|
||||
s = s .. '[' .. k .. '] = ' .. dump(v) .. ','
|
||||
end
|
||||
return s .. '} '
|
||||
else
|
||||
return tostring(o)
|
||||
end
|
||||
end
|
||||
@@ -4,12 +4,8 @@ version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
g13-driver.workspace = true
|
||||
embedded-graphics = "0.8"
|
||||
mlua = { version = "0.11.6", features = [
|
||||
"luau-jit",
|
||||
"async",
|
||||
"macros",
|
||||
"serde",
|
||||
] }
|
||||
ctrlc = "3.5"
|
||||
embedded-graphics = "0.8"
|
||||
g13-driver.workspace = true
|
||||
mlua = { version = "0.11.6", features = ["lua54", "async", "macros", "serde"] }
|
||||
time = { version = "0.3.47", features = ["formatting", "macros"] }
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
pub mod mouse;
|
||||
mod os;
|
||||
|
||||
use g13_driver::{G13, G13_LCD_COLUMNS, G13_LCD_ROWS};
|
||||
use mlua::{Error, ExternalResult, Lua};
|
||||
use std::{
|
||||
@@ -10,14 +13,18 @@ use std::{
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use crate::os::G13Os;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
|
||||
let _running = running.clone();
|
||||
ctrlc::set_handler(move || _running.store(false, Ordering::SeqCst))
|
||||
.expect("Error setting Ctrl-C handler");
|
||||
|
||||
let g13 = G13::new()?;
|
||||
let os = G13Os::new();
|
||||
|
||||
os.run();
|
||||
|
||||
/*
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
let g13_table = lua.create_table()?;
|
||||
@@ -172,11 +179,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
joy.set("deadzone", 40)?;
|
||||
globals.set("joy", joy)?;
|
||||
|
||||
// load all files from dir `./scripts` for now, user configurable later or ~/.config/g13-os/*.<lua[u]>
|
||||
// load all files from dir `./scripts` for now, user configurable later or ~/.config/g13-os/\*.<lua>
|
||||
// for now, just main.luau
|
||||
let main = fs::read_to_string("./scripts/main.luau")?;
|
||||
let main = fs::read_to_string("./scripts/main.lua")?;
|
||||
|
||||
lua.load(main).set_name("main.luau").exec()?;
|
||||
lua.load(main).set_name("main.lua").exec()?;
|
||||
|
||||
if lua.load("setup ~= nil").eval()? {
|
||||
lua.load("setup()").exec()?;
|
||||
@@ -239,6 +246,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
|
||||
running.store(false, Ordering::SeqCst);
|
||||
|
||||
*/
|
||||
Ok(())
|
||||
}
|
||||
|
||||
92
g13-os/src/mouse.rs
Normal file
92
g13-os/src/mouse.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
use std::cell::RefCell;
|
||||
|
||||
use embedded_graphics::{Drawable, Pixel, pixelcolor::BinaryColor, prelude::Point};
|
||||
use g13_driver::{G13, G13_LCD_COLUMNS, G13_LCD_ROWS, State};
|
||||
|
||||
#[rustfmt::skip]
|
||||
const MOUSE_CURSOR: &[u8] = &[
|
||||
2, 0, 0, 0, 0,
|
||||
2, 2, 0, 0, 0,
|
||||
2, 1, 2, 0, 0,
|
||||
2, 1, 1, 2, 0,
|
||||
2, 1, 2, 2, 2,
|
||||
2, 2, 0, 0, 0,
|
||||
];
|
||||
|
||||
pub struct Mouse {
|
||||
deadzone: i32,
|
||||
speed: f32,
|
||||
x: RefCell<f32>,
|
||||
y: RefCell<f32>,
|
||||
}
|
||||
|
||||
impl Default for Mouse {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Mouse {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
deadzone: 40,
|
||||
speed: 20.0,
|
||||
x: RefCell::new(G13_LCD_COLUMNS as f32 / 2.0 - 2.0),
|
||||
y: RefCell::new(G13_LCD_ROWS as f32 / 2.0 - 3.0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&self, state: State, delta: f32) {
|
||||
let offset: i32 = 512 - self.deadzone;
|
||||
let mut x = state.x;
|
||||
let mut y = state.y;
|
||||
|
||||
x = if x.abs() < self.deadzone {
|
||||
0
|
||||
} else {
|
||||
x - self.deadzone * x.signum()
|
||||
};
|
||||
|
||||
y = if y.abs() < self.deadzone {
|
||||
0
|
||||
} else {
|
||||
y - self.deadzone * y.signum()
|
||||
};
|
||||
|
||||
let x = x as f32 / offset as f32;
|
||||
let y = y as f32 / offset as f32;
|
||||
|
||||
let mut sx = self.x.borrow_mut();
|
||||
let mut sy = self.y.borrow_mut();
|
||||
|
||||
*sx = (*sx + x * delta * self.speed * 1.2).clamp(0., (G13_LCD_COLUMNS - 1) as f32);
|
||||
*sy = (*sy + y * delta * self.speed).clamp(0., (G13_LCD_ROWS - 1) as f32);
|
||||
}
|
||||
|
||||
pub fn get_x(&self) -> i32 {
|
||||
*self.x.borrow() as i32
|
||||
}
|
||||
|
||||
pub fn get_y(&self) -> i32 {
|
||||
*self.y.borrow() as i32
|
||||
}
|
||||
|
||||
pub fn render(&self, g13: &mut G13) {
|
||||
for (i, value) in MOUSE_CURSOR.iter().enumerate() {
|
||||
let x = i as i32 % 5;
|
||||
let y = i as i32 / 5;
|
||||
|
||||
let color = if *value == 1 {
|
||||
BinaryColor::Off
|
||||
} else if *value == 2 {
|
||||
BinaryColor::On
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
Pixel(Point::new(self.get_x() + x, self.get_y() + y), color)
|
||||
.draw(g13)
|
||||
.expect("G13 to be Connected");
|
||||
}
|
||||
}
|
||||
}
|
||||
231
g13-os/src/os.rs
Normal file
231
g13-os/src/os.rs
Normal file
@@ -0,0 +1,231 @@
|
||||
use std::{
|
||||
fs::read_dir,
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use embedded_graphics::{
|
||||
Drawable,
|
||||
mono_font::ascii::*,
|
||||
pixelcolor::BinaryColor,
|
||||
prelude::{DrawTarget, Point, Primitive, Size},
|
||||
primitives::{Line, PrimitiveStyle, PrimitiveStyleBuilder, Rectangle},
|
||||
text::{Alignment, Baseline, Text, TextStyleBuilder},
|
||||
};
|
||||
use g13_driver::{G13, G13_LCD_COLUMNS, G13_LCD_ROWS};
|
||||
use mlua::Lua;
|
||||
use time::{OffsetDateTime, macros::offset};
|
||||
|
||||
use crate::mouse::Mouse;
|
||||
|
||||
pub struct App {
|
||||
name: String,
|
||||
}
|
||||
|
||||
pub struct Button {
|
||||
label: String,
|
||||
action: Option<fn()>,
|
||||
}
|
||||
|
||||
pub struct G13Os {
|
||||
g13: G13,
|
||||
lua: Lua,
|
||||
running: Arc<AtomicBool>,
|
||||
apps: Vec<App>,
|
||||
running_app: Option<App>,
|
||||
buttons: [Option<Button>; 4],
|
||||
mouse: Mouse,
|
||||
}
|
||||
|
||||
impl G13Os {
|
||||
pub fn new() -> Self {
|
||||
let g13 = G13::new().expect("G13 to be connected");
|
||||
let lua = Lua::new();
|
||||
let running = Arc::new(AtomicBool::new(false));
|
||||
let mut apps = Vec::new();
|
||||
|
||||
let buttons = [
|
||||
Some(Button {
|
||||
label: "Settings".to_owned(),
|
||||
action: None,
|
||||
}),
|
||||
// Some(Button {
|
||||
// label: "Down".to_owned(),
|
||||
// action: None,
|
||||
// }),
|
||||
None,
|
||||
// Some(Button {
|
||||
// label: "Up".to_owned(),
|
||||
// action: None,
|
||||
// }),
|
||||
None,
|
||||
Some(Button {
|
||||
label: "00:00".to_owned(),
|
||||
action: None,
|
||||
}),
|
||||
];
|
||||
|
||||
for entry in read_dir("./apps").unwrap() {
|
||||
apps.push(App {
|
||||
name: entry.unwrap().file_name().into_string().unwrap(),
|
||||
});
|
||||
}
|
||||
|
||||
Self {
|
||||
g13,
|
||||
lua,
|
||||
running,
|
||||
apps,
|
||||
running_app: None,
|
||||
buttons,
|
||||
mouse: Mouse::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(&self) {
|
||||
let running = self.running.clone();
|
||||
running.store(true, Ordering::SeqCst);
|
||||
|
||||
ctrlc::set_handler(move || running.store(false, Ordering::SeqCst))
|
||||
.expect("Error setting Ctrl-C handler");
|
||||
|
||||
self.start_input_thread();
|
||||
|
||||
let mut g13 = self.g13.clone();
|
||||
let mut delta = 0.0;
|
||||
while self.running.load(Ordering::SeqCst) {
|
||||
let start = Instant::now();
|
||||
g13.clear(BinaryColor::Off).expect("G13 to be connected");
|
||||
|
||||
let mut show_mouse = false;
|
||||
|
||||
if self.running_app.is_none() {
|
||||
self.render_menu();
|
||||
show_mouse = true;
|
||||
} else {
|
||||
// render app
|
||||
// if app.is_init == false
|
||||
// app.is_init = true
|
||||
// app.init()
|
||||
// ..
|
||||
// app.update();
|
||||
}
|
||||
|
||||
if show_mouse {
|
||||
self.mouse.update(g13.state(), delta);
|
||||
self.mouse.render(&mut g13);
|
||||
}
|
||||
|
||||
g13.render().expect("G13 to be connected");
|
||||
|
||||
delta = (Instant::now() - start).as_secs_f32();
|
||||
}
|
||||
}
|
||||
|
||||
fn render_menu(&self) {
|
||||
let mut g13 = self.g13.clone();
|
||||
|
||||
// todo: const
|
||||
let button_count = 4;
|
||||
let button_width = G13_LCD_COLUMNS / button_count;
|
||||
|
||||
let fill = PrimitiveStyleBuilder::new()
|
||||
.fill_color(BinaryColor::On)
|
||||
.build();
|
||||
|
||||
let stroke = PrimitiveStyleBuilder::new()
|
||||
.stroke_color(BinaryColor::On)
|
||||
.stroke_width(1)
|
||||
.build();
|
||||
|
||||
let character_style =
|
||||
embedded_graphics::mono_font::MonoTextStyle::new(&FONT_4X6, BinaryColor::On);
|
||||
let character_style_inv =
|
||||
embedded_graphics::mono_font::MonoTextStyle::new(&FONT_4X6, BinaryColor::Off);
|
||||
let textstyle = TextStyleBuilder::new()
|
||||
.alignment(Alignment::Center)
|
||||
.baseline(Baseline::Top)
|
||||
.build();
|
||||
|
||||
for (i, btn) in self.buttons.iter().enumerate() {
|
||||
let Some(btn) = btn else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let line_x = i as i32 * button_width;
|
||||
|
||||
Line::new(Point::new(line_x, 8), Point::new(line_x + button_width, 8))
|
||||
.into_styled(stroke)
|
||||
.draw(&mut g13)
|
||||
.expect("G13 to be connected");
|
||||
|
||||
if i > 0 && i < 4 {
|
||||
Line::new(Point::new(line_x, 0), Point::new(line_x, 8))
|
||||
.into_styled(stroke)
|
||||
.draw(&mut g13)
|
||||
.expect("G13 to be connected");
|
||||
}
|
||||
|
||||
Line::new(
|
||||
Point::new(line_x + button_width, 0),
|
||||
Point::new(line_x + button_width, 8),
|
||||
)
|
||||
.into_styled(stroke)
|
||||
.draw(&mut g13)
|
||||
.expect("G13 to be connected");
|
||||
|
||||
let i = i as i32;
|
||||
let text_x = ((i + 1) * button_width) - (button_width / 2);
|
||||
|
||||
let mut label = btn.label.clone();
|
||||
if label.len() > 8 {
|
||||
let _ = label.split_off(8);
|
||||
}
|
||||
|
||||
if label == "00:00" {
|
||||
let now = OffsetDateTime::now_utc().to_offset(offset!(+1)); // GMT+1
|
||||
|
||||
// Render
|
||||
label = format!(
|
||||
"{:0>2}:{:0>2}:{:0>2}",
|
||||
now.hour(),
|
||||
now.minute(),
|
||||
now.second()
|
||||
);
|
||||
}
|
||||
|
||||
let style = if self.mouse.get_x() > i * button_width
|
||||
&& self.mouse.get_x() < (i + 1) * button_width
|
||||
&& self.mouse.get_y() < 8
|
||||
{
|
||||
Rectangle::new(
|
||||
Point::new(i * button_width, 0),
|
||||
Size::new(button_width as u32, 8),
|
||||
)
|
||||
.into_styled(fill)
|
||||
.draw(&mut g13)
|
||||
.expect("G13 to be Connected");
|
||||
|
||||
character_style_inv
|
||||
} else {
|
||||
character_style
|
||||
};
|
||||
Text::with_text_style(&label, Point::new(text_x, 1), style, textstyle)
|
||||
.draw(&mut g13)
|
||||
.expect("G13 to be connected");
|
||||
}
|
||||
}
|
||||
|
||||
fn start_input_thread(&self) {
|
||||
let g13 = self.g13.clone();
|
||||
let running = self.running.clone();
|
||||
std::thread::spawn(move || {
|
||||
while running.load(Ordering::SeqCst) {
|
||||
let _ = g13.read();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user