From 4296a6488c631f1112456c679fd9dec551f1c569 Mon Sep 17 00:00:00 2001 From: Avii Date: Mon, 23 Feb 2026 01:54:44 +0100 Subject: [PATCH] crosshair is nice --- src/kneeboardplugin.rs | 5 +- src/main.rs | 152 ++++++++++++++++++++++++++++------------- 2 files changed, 106 insertions(+), 51 deletions(-) diff --git a/src/kneeboardplugin.rs b/src/kneeboardplugin.rs index fb26ce1..340f91b 100644 --- a/src/kneeboardplugin.rs +++ b/src/kneeboardplugin.rs @@ -163,9 +163,8 @@ fn spawn_kneeboard( position: Res, ) { commands.spawn(( - WebviewSource::new("http://localhost:7878/"), // i want this to become dynamic.... from ui or something - // WebviewSource::new("https://public.avii.nl/test.html"), // i want this to become dynamic.... from ui or something - WebviewSize(Vec2::new(210.0 * 3.5, 279.0 * 3.5)), // this can also be dynamic... kinda like rotating phone + WebviewSource::new("http://localhost:7878/MOSRPRPETASPCLORWTSURDEP"), + WebviewSize(Vec2::new(210.0 * 3.5, 279.0 * 3.5)), Mesh3d(meshes.add(Cuboid::new(0.210, 0.279, 0.01))), MeshMaterial3d(materials.add(WebviewExtendStandardMaterial { base: StandardMaterial { diff --git a/src/main.rs b/src/main.rs index 02e42eb..a227aa4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,9 +30,10 @@ fn main() { .add_plugins(KneeboardPlugin) .insert_resource(ClearColor(Color::NONE)) .insert_resource(LastPenPos(None)) + .insert_resource(PenColor(css::BLACK.into())) .insert_resource(PenSize(5.0)) .add_systems(Startup, setup) - .add_systems(Update, (cursor, draw, plot).chain()) + .add_systems(Update, (color_changer, cursor, draw, plot).chain()) .run(); } @@ -42,14 +43,17 @@ struct MyProcGenImage(Handle); #[derive(Resource)] struct PenSize(f32); -const IMAGE_WIDTH: u32 = (210.0 * 3.5) as u32; -const IMAGE_HEIGHT: u32 = (279.0 * 3.5) as u32; +#[derive(Resource)] +struct PenColor(Color); + +const IMAGE_WIDTH: i32 = (210.0 * 3.5) as i32; +const IMAGE_HEIGHT: i32 = (279.0 * 3.5) as i32; fn setup(mut commands: Commands, mut images: ResMut>) { let image = Image::new_fill( Extent3d { - width: IMAGE_WIDTH, - height: IMAGE_HEIGHT, + width: IMAGE_WIDTH as u32, + height: IMAGE_HEIGHT as u32, depth_or_array_layers: 1, }, TextureDimension::D2, @@ -74,10 +78,18 @@ fn setup(mut commands: Commands, mut images: ResMut>) { struct CursorBuffer([u8; IMAGE_WIDTH as usize * IMAGE_HEIGHT as usize * 4]); impl Drawing for CursorBuffer { - fn set_color_at(&mut self, x: u32, y: u32, color: Color) { + fn set_color_at(&mut self, x: i32, y: i32, color: Color) { + if !(0..=IMAGE_WIDTH).contains(&x) || !(0..=IMAGE_HEIGHT).contains(&y) { + return; + } + let index = ((x + (IMAGE_WIDTH * y)) * 4) as usize; let srgba = Srgba::from(color); + if index >= self.0.len() { + return; + } + self.0[index] = (srgba.red * u8::MAX as f32) as u8; self.0[index + 1] = (srgba.green * u8::MAX as f32) as u8; self.0[index + 2] = (srgba.blue * u8::MAX as f32) as u8; @@ -93,13 +105,21 @@ impl Drawing for CursorBuffer { struct DrawingBuffer([u8; IMAGE_WIDTH as usize * IMAGE_HEIGHT as usize * 4]); #[derive(Resource)] -pub struct LastPenPos(pub Option<(u32, u32)>); +pub struct LastPenPos(pub Option<(i32, i32)>); impl Drawing for DrawingBuffer { - fn set_color_at(&mut self, x: u32, y: u32, color: Color) { + fn set_color_at(&mut self, x: i32, y: i32, color: Color) { + if !(0..=IMAGE_WIDTH).contains(&x) || !(0..=IMAGE_HEIGHT).contains(&y) { + return; + } + let index = ((x + (IMAGE_WIDTH * y)) * 4) as usize; let srgba = Srgba::from(color); + if index >= self.0.len() { + return; + } + self.0[index] = (srgba.red * u8::MAX as f32) as u8; self.0[index + 1] = (srgba.green * u8::MAX as f32) as u8; self.0[index + 2] = (srgba.blue * u8::MAX as f32) as u8; @@ -111,67 +131,103 @@ impl Drawing for DrawingBuffer { } } +fn color_changer(mut pen_color: ResMut, mut pen_buttons: MessageReader) { + let Some(buttons) = pen_buttons.read().next() else { + return; + }; + + pen_color.0 = css::BLACK.into(); + + if (buttons.state & 2) == 2 { + let mut t = LinearRgba::from(pen_color.0); + t.alpha = 0.0; + pen_color.0 = t.into(); + } + + if (buttons.state & 4) == 4 { + let mut t = LinearRgba::from(css::DARK_BLUE); + t.alpha = 0.5; + pen_color.0 = t.into(); + } +} + fn cursor( + pen_color: Res, mut buffer: ResMut, mut pen_size: ResMut, mut pen_buttons: MessageReader, mut pen_position: MessageReader, mut pen_pressure: MessageReader, ) { - let mut size: f32 = 4.0; + let mut size: f32 = 1.0; + let mut offset = 20.0; - for penpres in pen_pressure.read() { - size += penpres.pressure * 2.; - } + let c = pen_color.0; if let Some(buttons) = pen_buttons.read().next() && (buttons.state & 2 == 2) { - size = 40.; + offset *= 4.; }; - pen_size.0 = size; + for penpres in pen_pressure.read() { + // this needs log scaling - let color = css::BLACK.into(); + let _in = penpres.pressure; + let _out = penpres.pressure.powi(4); + + size *= 1. + (_out * offset); + } + + pen_size.0 = size.clamp(1.0, 200.0); + let s = pen_size.0 as i32; + let b = css::BLACK.into(); + + let cs = 10; + let cd = 3; for penpos in pen_position.read() { let x = (penpos.position.x * (IMAGE_WIDTH as f32)) as i32; let y = (penpos.position.y * (IMAGE_HEIGHT as f32)) as i32; buffer.clear(); - draw_circle(&mut buffer, x, y, (size) as i32, 3.0, color); + draw_line(&mut buffer, x - (cs + cd) - s, y, x - (cd) - s, y, 4.0, b); + draw_line(&mut buffer, x - (cs + cd) - s, y, x - (cd) - s, y, 1.0, c); + draw_line(&mut buffer, x + (cd) + s, y, x + (cs + cd) + s, y, 4.0, b); + draw_line(&mut buffer, x + (cd) + s, y, x + (cs + cd) + s, y, 1.0, c); + + draw_line(&mut buffer, x, y - (cs + cd) - s, x, y - (cd) - s, 4.0, b); + draw_line(&mut buffer, x, y - (cs + cd) - s, x, y - (cd) - s, 1.0, c); + draw_line(&mut buffer, x, y + (cs + cd) + s, x, y + (cd) + s, 4.0, b); + draw_line(&mut buffer, x, y + (cs + cd) + s, x, y + (cd) + s, 1.0, c); + + draw_filled_circle(&mut buffer, x, y, (pen_size.0 / 2.) as i32, c) } } fn draw( pen_size: Res, + pen_color: Res, mut lastloc: ResMut, mut buffer: ResMut, mut pen_buttons: MessageReader, mut pen_position: MessageReader, ) { - let mut color = css::TURQUOISE.into(); - let mut is_down = false; - - if let Some(buttons) = pen_buttons.read().next() { - is_down = buttons.state & 1 == 1; - if buttons.state >= 2 { - color = Color::linear_rgba(1.0, 1.0, 1.0, 0.0); - } + let Some(buttons) = pen_buttons.read().next() else { + return; }; for penpos in pen_position.read() { - let x = (penpos.position.x * (IMAGE_WIDTH as f32)) as u32; - let y = (penpos.position.y * (IMAGE_HEIGHT as f32)) as u32; + let x = (penpos.position.x * (IMAGE_WIDTH as f32)) as i32; + let y = (penpos.position.y * (IMAGE_HEIGHT as f32)) as i32; let Some(ll) = lastloc.0 else { lastloc.0 = Some((x, y)); return; }; - if is_down { - let c = if color.alpha() == 0.0 { 2.0 } else { 1.0 }; - draw_line(&mut buffer, ll.0, ll.1, x, y, pen_size.0 * c, color); + if buttons.state & 1 == 1 { + draw_line(&mut buffer, ll.0, ll.1, x, y, pen_size.0, pen_color.0); } lastloc.0 = Some((x, y)); @@ -179,21 +235,21 @@ fn draw( } trait Drawing { - fn set_color_at(&mut self, px: u32, py: u32, color: Color); + fn set_color_at(&mut self, px: i32, py: i32, color: Color); fn clear(&mut self); } -fn draw_line( - buffer: &mut ResMut, - x1: u32, - y1: u32, - x2: u32, - y2: u32, +fn draw_line( + buffer: &mut ResMut, + x1: i32, + y1: i32, + x2: i32, + y2: i32, thickness: f32, color: Color, ) { - let (mut x0, mut y0) = (x1 as i32, y1 as i32); - let (x1, y1) = (x2 as i32, y2 as i32); + let (mut x0, mut y0) = (x1, y1); + let (x1, y1) = (x2, y2); let dx = (x1 - x0).abs(); let dy = -(y1 - y0).abs(); @@ -255,7 +311,7 @@ fn draw_filled_circle( for x in start_x..=end_x { if x >= 0 { - buffer.set_color_at(x as u32, y as u32, color); + buffer.set_color_at(x, y, color); } } } @@ -310,21 +366,21 @@ fn draw_circle( // left segment for x in left_outer..left_inner { if x >= 0 { - buffer.set_color_at(x as u32, y as u32, color); + buffer.set_color_at(x, y, color); } } // right segment for x in (right_inner + 1)..=right_outer { if x >= 0 { - buffer.set_color_at(x as u32, y as u32, color); + buffer.set_color_at(x, y, color); } } } else { // fully filled span (very thin or small radius) for x in left_outer..=right_outer { if x >= 0 { - buffer.set_color_at(x as u32, y as u32, color); + buffer.set_color_at(x, y, color); } } } @@ -343,8 +399,8 @@ fn plot( image.clear(&[0, 0, 0, 0]); for (i, c) in buffer.0.chunks(4).enumerate() { - let x = i as u32 % IMAGE_WIDTH; - let y = i as u32 / IMAGE_WIDTH; + let x = i as i32 % IMAGE_WIDTH; + let y = i as i32 / IMAGE_WIDTH; let red: u8 = c[0]; let green = c[1]; @@ -353,13 +409,13 @@ fn plot( if alpha > 0 { let color = Color::srgba_u8(red, green, blue, alpha); - image.set_color_at(x, y, color).unwrap(); + image.set_color_at(x as u32, y as u32, color).unwrap(); } } for (i, c) in cursor.0.chunks(4).enumerate() { - let x = i as u32 % IMAGE_WIDTH; - let y = i as u32 / IMAGE_WIDTH; + let x = i as i32 % IMAGE_WIDTH; + let y = i as i32 / IMAGE_WIDTH; let red: u8 = c[0]; let green = c[1]; @@ -368,7 +424,7 @@ fn plot( if alpha > 0 { let color = Color::srgba_u8(red, green, blue, alpha); - image.set_color_at(x, y, color).unwrap(); + image.set_color_at(x as u32, y as u32, color).unwrap(); } }