nightshade 0.13.3

A cross-platform data-oriented game engine.
Documentation
use nalgebra_glm::Vec2;

use crate::ecs::ui::components::*;
use crate::ecs::ui::state::UiStateTrait;

pub(crate) struct RangeSliderVisualUpdate {
    pub fill_entity: freecs::Entity,
    pub low_thumb: freecs::Entity,
    pub high_thumb: freecs::Entity,
    pub text_slot: usize,
    pub precision: usize,
    pub low_normalized: f32,
    pub high_normalized: f32,
    pub low_value: f32,
    pub high_value: f32,
    pub thumb_half: f32,
}

pub(crate) fn update_range_slider_visuals(
    world: &mut crate::ecs::world::World,
    update: &RangeSliderVisualUpdate,
) {
    let RangeSliderVisualUpdate {
        fill_entity,
        low_thumb,
        high_thumb,
        text_slot,
        precision,
        low_normalized,
        high_normalized,
        low_value,
        high_value,
        thumb_half,
    } = *update;
    use crate::ecs::ui::layout_types::UiLayoutType;
    use crate::ecs::ui::state::UiBase;
    use crate::ecs::ui::units::{Ab, Rl};

    if let Some(fill_node) = world.ui.get_ui_layout_node_mut(fill_entity)
        && let Some(UiLayoutType::Boundary(boundary)) = fill_node.layouts[UiBase::INDEX].as_mut()
    {
        boundary.position_1 = Rl(Vec2::new(low_normalized * 100.0, 0.0)).into();
        boundary.position_2 = Rl(Vec2::new(high_normalized * 100.0, 100.0)).into();
    }

    if let Some(low_node) = world.ui.get_ui_layout_node_mut(low_thumb)
        && let Some(UiLayoutType::Boundary(boundary)) = low_node.layouts[UiBase::INDEX].as_mut()
    {
        boundary.position_1 =
            Rl(Vec2::new(low_normalized * 100.0, 0.0)) + Ab(Vec2::new(-thumb_half, 0.0));
        boundary.position_2 =
            Rl(Vec2::new(low_normalized * 100.0, 100.0)) + Ab(Vec2::new(thumb_half, 0.0));
    }

    if let Some(high_node) = world.ui.get_ui_layout_node_mut(high_thumb)
        && let Some(UiLayoutType::Boundary(boundary)) = high_node.layouts[UiBase::INDEX].as_mut()
    {
        boundary.position_1 =
            Rl(Vec2::new(high_normalized * 100.0, 0.0)) + Ab(Vec2::new(-thumb_half, 0.0));
        boundary.position_2 =
            Rl(Vec2::new(high_normalized * 100.0, 100.0)) + Ab(Vec2::new(thumb_half, 0.0));
    }

    world.resources.text_cache.set_text(
        text_slot,
        format!(
            "{:.prec$} - {:.prec$}",
            low_value,
            high_value,
            prec = precision,
        ),
    );
}

pub(super) fn find_widget_content_in_defs(
    defs: &[ContextMenuItemDef],
    command_id: usize,
) -> Option<freecs::Entity> {
    for def in defs {
        if def.command_id == Some(command_id)
            && let ContextMenuItemKind::Widget { content_entity } = &def.kind
        {
            return Some(*content_entity);
        }
        if let ContextMenuItemKind::Submenu { children, .. } = &def.kind
            && let Some(found) = find_widget_content_in_defs(children, command_id)
        {
            return Some(found);
        }
    }
    None
}