optima 0.0.4

An easy to set up and easy optimization and planning toolbox, particularly for robotics.
Documentation
use bevy::ecs::component::Component;
use bevy::prelude::{Assets, Color, Handle, Query, ResMut, StandardMaterial};
use crate::optima_bevy::optima_bevy_utils::generic_item::GenericItemSignature;

pub struct MaterialSystems;
impl MaterialSystems {
    pub fn update_optima_bevy_material_components_from_change_requests(material_change_request_container: ResMut<MaterialChangeRequestContainer>,
                                                                       mut query: Query<(&mut OptimaBevyMaterialComponent, &GenericItemSignature)>) {
        for (mut optima_bevy_material_component_, signature_) in &mut query {
            let optima_bevy_material_component: &mut OptimaBevyMaterialComponent = &mut optima_bevy_material_component_;
            let signature: &GenericItemSignature = &signature_;

            let binary_search_res = material_change_request_container.material_change_requests.binary_search_by(|x| x.signature.partial_cmp(&signature).unwrap());
            match binary_search_res {
                Ok(idx) => {
                    let material_change_request = &material_change_request_container.material_change_requests[idx];
                    optima_bevy_material_component.updated = true;
                    match &material_change_request.material_change_request_type {
                        MaterialChangeRequestType::Reset => {
                            optima_bevy_material_component.curr_material = optima_bevy_material_component.base_material.clone();
                            optima_bevy_material_component.material_auto_update_mode = MaterialAutoUpdateMode::None;
                        }
                        MaterialChangeRequestType::Change { material } => {
                            optima_bevy_material_component.curr_material = material.clone();
                            optima_bevy_material_component.material_auto_update_mode = MaterialAutoUpdateMode::None;
                        }
                        MaterialChangeRequestType::ChangeButResetInNFrames { material, n } => {
                            optima_bevy_material_component.curr_material = material.clone();
                            optima_bevy_material_component.material_auto_update_mode = MaterialAutoUpdateMode::ResetInNFrames { n: *n + 1 };
                        }
                    }
                }
                Err(_) => {
                    optima_bevy_material_component.updated = false;
                }
            }
        }
    }
    pub fn update_optima_bevy_material_components_from_auto_update(mut query: Query<&mut OptimaBevyMaterialComponent>) {
        for mut q in query.iter_mut() {
            match &mut q.material_auto_update_mode {
                MaterialAutoUpdateMode::ResetInNFrames { n } => {
                    *n -= 1;
                    if *n == 0 {
                        q.curr_material = q.base_material.clone();
                        q.material_auto_update_mode = MaterialAutoUpdateMode::None;
                        q.updated = true;
                    }
                }
                MaterialAutoUpdateMode::None => {}
            }
        }
    }
    pub fn update_materials(mut query: Query<(&Handle<StandardMaterial>, &mut OptimaBevyMaterialComponent)>,
                            mut materials: ResMut<Assets<StandardMaterial>>,
                            mut material_change_request_container: ResMut<MaterialChangeRequestContainer>) {
        for (standard_material_, mut optima_bevy_material_component_) in &mut query {
            let standard_material: &Handle<StandardMaterial> = &standard_material_;
            let optima_bevy_material_component: &mut OptimaBevyMaterialComponent = &mut optima_bevy_material_component_;

            if optima_bevy_material_component.updated {
                let m = materials.get_mut(standard_material).unwrap();
                *m = optima_bevy_material_component.curr_material.map_to_color().into();
            }
        }

        material_change_request_container.flush();
    }
}

#[derive(Debug, Clone)]
pub enum OptimaBevyMaterial {
    Color(Color)
}
impl OptimaBevyMaterial {
    pub fn map_to_type(&self) -> OptimaBevyMaterialType {
        match self {
            OptimaBevyMaterial::Color(_) => { OptimaBevyMaterialType::Color }
        }
    }
    pub fn map_to_color(&self) -> Color {
        match self {
            OptimaBevyMaterial::Color(c) => {c.clone()}
        }
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum OptimaBevyMaterialType {
    Color
}

#[derive(Debug, Clone)]
pub enum MaterialAutoUpdateMode {
    None,
    ResetInNFrames { n: usize }
}

#[derive(Component, Debug, Clone)]
pub struct OptimaBevyMaterialComponent {
    curr_material: OptimaBevyMaterial,
    base_material: OptimaBevyMaterial,
    material_auto_update_mode: MaterialAutoUpdateMode,
    updated: bool
}
impl OptimaBevyMaterialComponent {
    pub fn new(material: OptimaBevyMaterial) -> Self {
        Self {
            curr_material: material.clone(),
            base_material: material,
            material_auto_update_mode: MaterialAutoUpdateMode::None,
            updated: false
        }
    }
    pub fn base_material(&self) -> &OptimaBevyMaterial {
        &self.base_material
    }
    pub fn curr_material(&self) -> &OptimaBevyMaterial {
        &self.curr_material
    }
}

#[derive(Debug, Clone)]
pub struct MaterialChangeRequest {
    signature: GenericItemSignature,
    importance: usize,
    material_change_request_type: MaterialChangeRequestType
}
impl MaterialChangeRequest {
    pub fn new(signature: GenericItemSignature, importance: usize, material_change_request_type: MaterialChangeRequestType) -> Self {
        Self {
            signature,
            importance,
            material_change_request_type
        }
    }
}

#[derive(Debug, Clone)]
pub enum MaterialChangeRequestType {
    Reset,
    Change {material: OptimaBevyMaterial},
    ChangeButResetInNFrames { material: OptimaBevyMaterial, n: usize }
}

pub struct MaterialChangeRequestContainer {
    material_change_requests: Vec<MaterialChangeRequest>
}
impl MaterialChangeRequestContainer {
    pub fn new() -> Self {
        Self {
            material_change_requests: vec![]
        }
    }
    pub fn add_request(&mut self, request: MaterialChangeRequest) {
        let binary_search_result = self.material_change_requests.binary_search_by(|x| x.signature.partial_cmp(&request.signature).unwrap());

        match binary_search_result {
            Ok(idx) => {
                let curr_importance = self.material_change_requests[idx].importance;
                let new_importance = request.importance;

                if new_importance > curr_importance { self.material_change_requests[idx] = request; }
            }
            Err(idx) => {
                self.material_change_requests.insert(idx, request);
            }
        }
    }
    pub fn flush(&mut self) { self.material_change_requests.clear(); }
}