mouse stuff
This commit is contained in:
11
Cargo.lock
generated
11
Cargo.lock
generated
@@ -2787,6 +2787,7 @@ dependencies = [
|
|||||||
"embedded-graphics",
|
"embedded-graphics",
|
||||||
"g13-driver",
|
"g13-driver",
|
||||||
"mlua",
|
"mlua",
|
||||||
|
"time",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3448,15 +3449,6 @@ dependencies = [
|
|||||||
"imgref",
|
"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]]
|
[[package]]
|
||||||
name = "mach2"
|
name = "mach2"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
@@ -3587,7 +3579,6 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"luau0-src",
|
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name = "DVD"
|
name = "DVD"
|
||||||
authors = {"AviiNL"}
|
authors = { "AviiNL" }
|
||||||
description = "Bouncing 'dvd' Logo"
|
description = "Bouncing 'dvd' Logo"
|
||||||
|
|
||||||
local width = g13.display_width
|
local width = g13.display_width
|
||||||
@@ -19,7 +19,7 @@ function setup()
|
|||||||
joy.deadzone = 40
|
joy.deadzone = 40
|
||||||
end
|
end
|
||||||
|
|
||||||
function update(delta: number)
|
function update(delta)
|
||||||
x = x + speed * delta * joy.x * 1.2
|
x = x + speed * delta * joy.x * 1.2
|
||||||
y = y + speed * delta * joy.y
|
y = y + speed * delta * joy.y
|
||||||
|
|
||||||
@@ -29,26 +29,26 @@ function update(delta: number)
|
|||||||
|
|
||||||
g13.clear()
|
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)
|
g13.text("Hello World!", 1, 1, true, 0, 0, 1)
|
||||||
|
|
||||||
for sy = -size,size do
|
for sy = -size, size do
|
||||||
for sx = -size,size do
|
for sx = -size, size do
|
||||||
g13.set_pixel(x + sx, y + sy, true)
|
g13.set_pixel(x + sx, y + sy, true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function dump(o)
|
function dump(o)
|
||||||
if type(o) == 'table' then
|
if type(o) == 'table' then
|
||||||
local s = '{ '
|
local s = '{ '
|
||||||
for k,v in pairs(o) do
|
for k, v in pairs(o) do
|
||||||
if type(k) ~= 'number' then k = '"'..k..'"' end
|
if type(k) ~= 'number' then k = '"' .. k .. '"' end
|
||||||
s = s .. '['..k..'] = ' .. dump(v) .. ','
|
s = s .. '[' .. k .. '] = ' .. dump(v) .. ','
|
||||||
end
|
end
|
||||||
return s .. '} '
|
return s .. '} '
|
||||||
else
|
else
|
||||||
return tostring(o)
|
return tostring(o)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -4,12 +4,8 @@ version.workspace = true
|
|||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
g13-driver.workspace = true
|
|
||||||
embedded-graphics = "0.8"
|
|
||||||
mlua = { version = "0.11.6", features = [
|
|
||||||
"luau-jit",
|
|
||||||
"async",
|
|
||||||
"macros",
|
|
||||||
"serde",
|
|
||||||
] }
|
|
||||||
ctrlc = "3.5"
|
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 g13_driver::{G13, G13_LCD_COLUMNS, G13_LCD_ROWS};
|
||||||
use mlua::{Error, ExternalResult, Lua};
|
use mlua::{Error, ExternalResult, Lua};
|
||||||
use std::{
|
use std::{
|
||||||
@@ -10,14 +13,18 @@ use std::{
|
|||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::os::G13Os;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let running = Arc::new(AtomicBool::new(true));
|
let running = Arc::new(AtomicBool::new(true));
|
||||||
|
|
||||||
let _running = running.clone();
|
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 lua = Lua::new();
|
||||||
let globals = lua.globals();
|
let globals = lua.globals();
|
||||||
let g13_table = lua.create_table()?;
|
let g13_table = lua.create_table()?;
|
||||||
@@ -172,11 +179,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
joy.set("deadzone", 40)?;
|
joy.set("deadzone", 40)?;
|
||||||
globals.set("joy", joy)?;
|
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
|
// 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()? {
|
if lua.load("setup ~= nil").eval()? {
|
||||||
lua.load("setup()").exec()?;
|
lua.load("setup()").exec()?;
|
||||||
@@ -239,6 +246,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
running.store(false, Ordering::SeqCst);
|
running.store(false, Ordering::SeqCst);
|
||||||
|
*/
|
||||||
Ok(())
|
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