use infinity_rs::nvg::*;
use infinity_rs::prelude::*;
use std::f32::consts::PI;
pub struct AttitudeGauge {
nvg: Option<NvgContext>,
font: Option<i32>,
image: Option<i32>,
pitch_var: AVar,
bank_var: AVar,
}
impl AttitudeGauge {
pub fn new() -> Self {
Self {
nvg: None,
font: None,
image: None,
pitch_var: AVar::new("ATTITUDE INDICATOR PITCH DEGREES", "DEGREES")
.expect("Failed to create pitch AVar"),
bank_var: AVar::new("ATTITUDE INDICATOR BANK DEGREES", "DEGREES")
.expect("Failed to create bank AVar"),
}
}
}
impl Gauge for AttitudeGauge {
fn init(&mut self, ctx: &Context, _install: &mut GaugeInstall) -> bool {
let nvg = match NvgContext::new(ctx) {
Some(n) => n,
None => return false,
};
self.font = nvg.create_font("sans", "./data/Roboto-Regular.ttf");
self.image = nvg.create_image("./data/image.png", ImageFlags::NONE);
self.nvg = Some(nvg);
true
}
fn update(&mut self, _ctx: &Context, _dt: f32) -> bool {
true
}
fn draw(&mut self, _ctx: &Context, draw: &mut GaugeDraw) -> bool {
let nvg = match &self.nvg {
Some(n) => n,
None => return false,
};
let pitch = self.pitch_var.get().unwrap_or(0.0) as f32;
let bank = self.bank_var.get().unwrap_or(0.0) as f32;
let win_w = draw.winWidth as f32;
let win_h = draw.winHeight as f32;
let px_ratio = draw.fbWidth as f32 / win_w;
let size = (win_w * win_w + win_h * win_h).sqrt() * 1.1;
nvg.frame(win_w, win_h, px_ratio, |nvg| {
let half = size * 0.5;
let fh = half * (1.0 - (pitch * PI / 180.0).sin());
nvg.scoped(|nvg| {
nvg.translate(win_w * 0.5, win_h * 0.5);
nvg.rotate(bank * PI / 180.0);
Shape::rect(-half, -half, size, fh)
.fill(Color::rgb(0, 191, 255))
.draw(nvg);
Shape::rect(-half, -half + fh, size, size - fh)
.fill(Color::rgb(210, 103, 30))
.draw(nvg);
});
nvg.scoped(|nvg| {
nvg.translate(win_w * 0.5, win_h * 0.5);
nvg.stroke_color(Color::rgb(255, 255, 0));
nvg.stroke_width(15.0);
nvg.begin_path();
nvg.move_to(-win_w * 0.2, 0.0);
nvg.line_to(-win_w * 0.05, 0.0);
nvg.arc(0.0, 0.0, win_w * 0.05, PI, 0.0, Winding::Ccw);
nvg.line_to(win_w * 0.2, 0.0);
nvg.stroke();
Shape::circle(0.0, 0.0, win_w * 0.01)
.fill(Color::rgb(255, 255, 0))
.draw(nvg);
});
if let Some(img) = self.image {
let (img_w, img_h) = nvg.image_size(img);
let (iw, ih) = (img_w as f32, img_h as f32);
let x = win_w - iw - 10.0;
let y = win_h - ih - 10.0;
let pattern = ImagePattern::new(nvg, x, y, iw, ih, 0.0, img, 1.0);
Shape::rect(x, y, iw, ih).fill(pattern).draw(nvg);
}
});
true
}
fn kill(&mut self, _ctx: &Context) -> bool {
self.nvg = None; true
}
}
infinity_rs::export_gauge!(
name = attitude_gauge,
state = AttitudeGauge,
ctor = AttitudeGauge::new()
);