You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
3.1 KiB
107 lines
3.1 KiB
3 months ago
|
use crate::ui::{
|
||
|
canvas::Canvas,
|
||
|
display::Color,
|
||
|
geometry::{Offset, Point, Rect},
|
||
|
shape::{DrawingCache, Renderer, Shape, ShapeClone},
|
||
|
};
|
||
|
|
||
|
use without_alloc::alloc::LocalAllocLeakExt;
|
||
|
|
||
|
use core::f32::consts::SQRT_2;
|
||
|
|
||
|
const STAR_COUNT: usize = 8;
|
||
|
const STAR_SMALL: i16 = 2;
|
||
|
const STAR_MEDIUM: i16 = 4;
|
||
|
const STAR_LARGE: i16 = 6;
|
||
|
|
||
|
const RADIUS: i16 = 13;
|
||
|
const DIAGONAL: i16 = ((RADIUS as f32 * SQRT_2) / 2_f32) as i16;
|
||
|
|
||
|
// Offset of the normal point and then the extra offset for the main point
|
||
|
static STARS: [Offset; STAR_COUNT] = [
|
||
|
Offset::y(-RADIUS),
|
||
|
Offset::new(DIAGONAL, -DIAGONAL),
|
||
|
Offset::x(RADIUS),
|
||
|
Offset::new(DIAGONAL, DIAGONAL),
|
||
|
Offset::y(RADIUS),
|
||
|
Offset::new(-DIAGONAL, DIAGONAL),
|
||
|
Offset::x(-RADIUS),
|
||
|
Offset::new(-DIAGONAL, -DIAGONAL),
|
||
|
];
|
||
|
|
||
|
/// A shape of a TS3 starry loader
|
||
|
pub struct LoaderStarry {
|
||
|
/// Position of point (0,0)
|
||
|
pos: Point,
|
||
|
/// Value 0..1000
|
||
|
value: u16,
|
||
|
/// Color
|
||
|
color: Color,
|
||
|
}
|
||
|
|
||
|
impl LoaderStarry {
|
||
|
pub fn new(pos: Point, value: u16) -> Self {
|
||
|
Self {
|
||
|
pos,
|
||
|
value,
|
||
|
color: Color::white(),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn with_color(self, color: Color) -> Self {
|
||
|
Self { color, ..self }
|
||
|
}
|
||
|
|
||
|
pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) {
|
||
|
renderer.render_shape(self);
|
||
|
}
|
||
|
|
||
|
fn draw_large_star(&self, canvas: &mut dyn Canvas, offset: Offset) {
|
||
|
let r = Rect::from_center_and_size(self.pos + offset, Offset::uniform(STAR_LARGE));
|
||
|
canvas.fill_round_rect(r, 2, self.color, 255);
|
||
|
}
|
||
|
|
||
|
fn draw_medium_star(&self, canvas: &mut dyn Canvas, offset: Offset) {
|
||
|
let r = Rect::from_center_and_size(self.pos + offset, Offset::uniform(STAR_MEDIUM));
|
||
|
canvas.fill_round_rect(r, 1, self.color, 255);
|
||
|
}
|
||
|
|
||
|
fn draw_small_star(&self, canvas: &mut dyn Canvas, offset: Offset) {
|
||
|
let r = Rect::from_center_and_size(self.pos + offset, Offset::uniform(STAR_SMALL));
|
||
|
canvas.fill_rect(r, self.color, 255);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Shape<'_> for LoaderStarry {
|
||
|
fn bounds(&self, _cache: &DrawingCache) -> Rect {
|
||
|
Rect::from_top_left_and_size(self.pos, Offset::uniform(1)).expand(RADIUS + STAR_LARGE)
|
||
|
}
|
||
|
|
||
|
fn cleanup(&mut self, _cache: &DrawingCache) {}
|
||
|
|
||
|
fn draw(&mut self, canvas: &mut dyn Canvas, _cache: &DrawingCache) {
|
||
|
// Calculate the index of the big star
|
||
|
let sel_idx = (STAR_COUNT * self.value as usize / 1000) % STAR_COUNT;
|
||
|
|
||
|
for (i, c) in STARS.iter().enumerate() {
|
||
|
if i == sel_idx {
|
||
|
self.draw_large_star(canvas, *c);
|
||
|
} else if (sel_idx + 1) % 8 == i || (sel_idx - 1) % 8 == i {
|
||
|
self.draw_medium_star(canvas, *c);
|
||
|
} else {
|
||
|
self.draw_small_star(canvas, *c);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl ShapeClone<'_> for LoaderStarry {
|
||
|
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape>
|
||
|
where
|
||
|
T: LocalAllocLeakExt<'alloc>,
|
||
|
{
|
||
|
let clone = bump.alloc_t::<LoaderStarry>()?;
|
||
|
Some(clone.uninit.init(LoaderStarry { ..self }))
|
||
|
}
|
||
|
}
|