agb_eb_ext 0.25.0

AGB Extension methods
use agb::display::GraphicsFrame;
use agb::display::tiled::BackgroundId;
use agb::fixnum::{Num, num};

/// Representations each step in a fade transition
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub enum Fade {
    Start,
    Step1,
    Step2,
    Step3,
    Step4,
    Step5,
    End,
}

impl Fade {
    pub fn next(self) -> Option<Self> {
        match self {
            Fade::Start => Some(Fade::Step1),
            Fade::Step1 => Some(Fade::Step2),
            Fade::Step2 => Some(Fade::Step3),
            Fade::Step3 => Some(Fade::Step4),
            Fade::Step4 => Some(Fade::Step5),
            Fade::Step5 => Some(Fade::End),
            Fade::End => None,
        }
    }
}

impl From<Fade> for FadeAmount {
    // FadeAmount only has 4 fractional bits, so amounts are multiples of 1/16
    fn from(value: Fade) -> Self {
        match value {
            Fade::Start => num!(0),
            Fade::Step1 => num!(0.1875),
            Fade::Step2 => num!(0.3125),
            Fade::Step3 => num!(0.5),
            Fade::Step4 => num!(0.6875),
            Fade::Step5 => num!(0.8125),
            Fade::End => num!(1),
        }
    }
}

pub type FadeAmount = Num<u8, 4>;

enum FadeKind {
    Darken,
    Brighten,
}

fn apply_fade(
    kind: FadeKind,
    amount: FadeAmount,
    bg_ids: &[BackgroundId],
    frame: &mut GraphicsFrame,
) {
    let mut effect = match kind {
        FadeKind::Darken => frame.blend().darken(amount),
        FadeKind::Brighten => frame.blend().brighten(amount),
    };
    effect.enable_object();
    for id in bg_ids {
        effect.enable_background(*id);
    }
}

/// Fade to fully black
/// Start with Fade::Start
pub fn fade_to_black<A: Into<FadeAmount>>(
    amount: A,
    bg_ids: &[BackgroundId],
    frame: &mut GraphicsFrame,
) {
    apply_fade(FadeKind::Darken, amount.into(), bg_ids, frame);
}

/// Fade from fully black
/// Start with Fade::Start
pub fn fade_from_black<A: Into<FadeAmount>>(
    amount: A,
    bg_ids: &[BackgroundId],
    frame: &mut GraphicsFrame,
) {
    apply_fade(FadeKind::Darken, num!(1) - amount.into(), bg_ids, frame);
}

/// Fade to fully white
/// Start with Fade::Start
pub fn fade_to_white<A: Into<FadeAmount>>(
    amount: A,
    bg_ids: &[BackgroundId],
    frame: &mut GraphicsFrame,
) {
    apply_fade(FadeKind::Brighten, amount.into(), bg_ids, frame);
}

/// Fade from fully white
/// Start with Fade::Start
pub fn fade_from_white<A: Into<FadeAmount>>(
    amount: A,
    bg_ids: &[BackgroundId],
    frame: &mut GraphicsFrame,
) {
    apply_fade(FadeKind::Brighten, num!(1) - amount.into(), bg_ids, frame);
}

pub fn reset_fade(bg_ids: &[BackgroundId], frame: &mut GraphicsFrame) {
    apply_fade(FadeKind::Brighten, num!(0), bg_ids, frame);
}