use embassy_ssd1306_graphics::Graphics;
use embedded_hal_async::i2c::I2c;
use crate::draw_utils::{segment, filled_rect};
#[derive(Clone, Copy, Debug)]
pub struct Piston {
pub cx: i32,
pub cy: i32,
pub w: i32,
pub h: i32,
pub piston_h: i32,
pub pos: i32,
}
impl Piston {
pub fn new(cx: i32, cy: i32, w: i32, h: i32) -> Self {
Self {
cx,
cy,
w,
h,
piston_h: 6,
pos: 0,
}
}
#[inline]
pub fn set_pos(&mut self, pos: i32) {
let max = self.h - self.piston_h;
self.pos = pos.clamp(0, max);
}
#[inline]
pub fn normalized(&self) -> f32 {
let max = (self.h - self.piston_h).max(1);
self.pos as f32 / max as f32
}
pub fn draw<I: I2c>(
&self,
gfx: &mut Graphics<'_, I>,
_t: f32,
on: bool,
_cos_fn: fn(f32) -> f32,
_sin_fn: fn(f32) -> f32,
) {
let left = self.cx - self.w / 2;
let right = self.cx + self.w / 2;
let top = self.cy;
let bottom = self.cy + self.h;
segment(gfx, left, top, right, top, on);
segment(gfx, left, bottom, right, bottom, on);
segment(gfx, left, top, left, bottom, on);
segment(gfx, right, top, right, bottom, on);
let max = self.h - self.piston_h;
let y = self.cy + self.pos.clamp(0, max);
filled_rect(
gfx,
left + 2,
y,
self.w - 4,
self.piston_h,
on,
);
let rod_x = self.cx;
let rod_top = y + self.piston_h / 2;
let rod_bottom = bottom;
segment(gfx, rod_x, rod_top, rod_x, rod_bottom, on);
segment(gfx, left, bottom, right, bottom, on);
}
#[inline]
pub fn erase<I: I2c>(
&self,
gfx: &mut Graphics<'_, I>,
t: f32,
cos_fn: fn(f32) -> f32,
sin_fn: fn(f32) -> f32,
) {
self.draw(gfx, t, false, cos_fn, sin_fn);
}
}