nightshade 0.13.0

A cross-platform data-oriented game engine.
Documentation
use crate::ecs::ui::state::UiStateTrait;

pub(crate) fn format_month_year(year: i32, month: u32) -> String {
    let month_name = match month {
        1 => "January",
        2 => "February",
        3 => "March",
        4 => "April",
        5 => "May",
        6 => "June",
        7 => "July",
        8 => "August",
        9 => "September",
        10 => "October",
        11 => "November",
        12 => "December",
        _ => "???",
    };
    format!("{month_name} {year}")
}

pub(crate) fn days_in_month(year: i32, month: u32) -> u32 {
    match month {
        1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
        4 | 6 | 9 | 11 => 30,
        2 => {
            if (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 {
                29
            } else {
                28
            }
        }
        _ => 30,
    }
}

pub(crate) fn day_of_week(year: i32, month: u32, day: u32) -> u32 {
    let (adjusted_year, adjusted_month) = if month <= 2 {
        (year - 1, month + 12)
    } else {
        (year, month)
    };
    let q = day as i32;
    let m = adjusted_month as i32;
    let k = adjusted_year % 100;
    let j = adjusted_year / 100;
    let h = (q + (13 * (m + 1)) / 5 + k + k / 4 + j / 4 - 2 * j).rem_euclid(7);
    ((h + 6) % 7) as u32
}

pub(crate) fn populate_calendar_grid(
    world: &mut crate::ecs::world::World,
    year: i32,
    month: u32,
    selected_day: u32,
    day_text_slots: &[usize],
    day_entities: &[freecs::Entity],
    accent_color: nalgebra_glm::Vec4,
) {
    let dim_color = nalgebra_glm::Vec4::new(0.5, 0.5, 0.5, 0.3);
    let clear_color = nalgebra_glm::Vec4::new(0.0, 0.0, 0.0, 0.0);

    let first_dow = day_of_week(year, month, 1);
    let days = days_in_month(year, month);

    let (prev_year, prev_month) = if month == 1 {
        (year - 1, 12)
    } else {
        (year, month - 1)
    };
    let prev_days = days_in_month(prev_year, prev_month);

    for cell_index in 0..42 {
        let (day_num, is_current_month) = if (cell_index as u32) < first_dow {
            let d = prev_days - first_dow + cell_index as u32 + 1;
            (d, false)
        } else {
            let d = cell_index as u32 - first_dow + 1;
            if d <= days {
                (d, true)
            } else {
                let d = d - days;
                (d, false)
            }
        };

        world
            .resources
            .text_cache
            .set_text(day_text_slots[cell_index], day_num.to_string());

        let is_selected = is_current_month && day_num == selected_day;
        let base_color = if is_selected {
            accent_color
        } else if is_current_month {
            clear_color
        } else {
            dim_color
        };
        if let Some(color) = world.ui.get_ui_node_color_mut(day_entities[cell_index]) {
            color.colors[crate::ecs::ui::state::UiBase::INDEX] = Some(base_color);
        }
    }
}