livesplit-core 0.13.0

livesplit-core is a library that provides a lot of functionality for creating a speedrun timer.
Documentation
use crate::{
    component::detailed_timer::State,
    layout::LayoutState,
    rendering::{
        component::timer,
        consts::{vertical_padding, BOTH_PADDINGS, PADDING},
        font::CachedLabel,
        icon::Icon,
        resource::ResourceAllocator,
        scene::Layer,
        solid, RenderContext,
    },
};

pub struct Cache<I, L> {
    icon: Option<Icon<I>>,
    timer: timer::Cache<I, L>,
    segment_timer: timer::Cache<I, L>,
    segment_name: CachedLabel<L>,
    comparison1_name: CachedLabel<L>,
    comparison2_name: CachedLabel<L>,
    comparison1_time: CachedLabel<L>,
    comparison2_time: CachedLabel<L>,
}

impl<I, L> Cache<I, L> {
    pub const fn new() -> Self {
        Self {
            icon: None,
            timer: timer::Cache::new(),
            segment_timer: timer::Cache::new(),
            segment_name: CachedLabel::new(),
            comparison1_name: CachedLabel::new(),
            comparison2_name: CachedLabel::new(),
            comparison1_time: CachedLabel::new(),
            comparison2_time: CachedLabel::new(),
        }
    }
}

pub(in crate::rendering) fn render<A: ResourceAllocator>(
    cache: &mut Cache<A::Image, A::Label>,
    context: &mut RenderContext<'_, A>,
    [width, height]: [f32; 2],
    component: &State,
    layout_state: &LayoutState,
) {
    context.render_background([width, height], &component.background);

    let text_color = solid(&layout_state.text_color);

    let vertical_padding = vertical_padding(height);
    let icon_size = height - 2.0 * vertical_padding;

    if let Some(icon) = &component.icon_change {
        cache.icon = context.create_icon(icon);
    }

    let left_side = if let Some(icon) = &cache.icon {
        context.render_icon([PADDING, vertical_padding], [icon_size, icon_size], icon);
        BOTH_PADDINGS + icon_size
    } else {
        PADDING
    };

    let top_height = 0.55 * height;
    let bottom_height = height - top_height;

    let timer_end = timer::render(
        &mut cache.timer,
        context,
        [width, top_height],
        &component.timer,
    );

    if let Some(segment_name) = &component.segment_name {
        context.render_text_ellipsis(
            segment_name,
            &mut cache.segment_name,
            [left_side, 0.6 * top_height],
            0.5 * top_height,
            text_color,
            timer_end,
        );
    }

    context.translate(0.0, top_height);

    let segment_timer_end = timer::render(
        &mut cache.segment_timer,
        context,
        [width, bottom_height],
        &component.segment_timer,
    );

    context.translate(0.0, -top_height);

    let mut name_end = 0.0;
    let comparison_text_scale = 0.5 * bottom_height;
    let comparison2_y = 0.8 * bottom_height + top_height;
    let mut time_width = 0.0;

    let comparison1_y = if let Some(comparison) = &component.comparison2 {
        name_end = context
            .render_text_ellipsis(
                &comparison.name,
                &mut cache.comparison2_name,
                [left_side, comparison2_y],
                comparison_text_scale,
                text_color,
                segment_timer_end,
            )
            .max(name_end);

        time_width = context
            .measure_numbers(
                &comparison.time,
                &mut cache.comparison2_time,
                comparison_text_scale,
            )
            .max(time_width);

        comparison2_y - comparison_text_scale
    } else {
        comparison2_y
    };

    if let Some(comparison) = &component.comparison1 {
        name_end = context
            .render_text_ellipsis(
                &comparison.name,
                &mut cache.comparison1_name,
                [left_side, comparison1_y],
                comparison_text_scale,
                text_color,
                segment_timer_end,
            )
            .max(name_end);

        time_width = context
            .measure_numbers(
                &comparison.time,
                &mut cache.comparison1_time,
                comparison_text_scale,
            )
            .max(time_width);
    }

    let time_x = name_end + PADDING + time_width;

    if let Some(comparison) = &component.comparison2 {
        context.render_numbers(
            &comparison.time,
            &mut cache.comparison2_time,
            Layer::Bottom,
            [time_x, comparison2_y],
            comparison_text_scale,
            text_color,
        );
    }
    if let Some(comparison) = &component.comparison1 {
        context.render_numbers(
            &comparison.time,
            &mut cache.comparison1_time,
            Layer::Bottom,
            [time_x, comparison1_y],
            comparison_text_scale,
            text_color,
        );
    }
}