bevy_variable_property 0.5.0

A generic way to define properties as static, random, or randomized on an interval
Documentation
use array_macro::array;
use bevy_reflect::TypePath;
use paste::paste;

pub trait VariableProperty {
    type Output: TypePath;
    fn get_value(&self) -> Self::Output;
}

impl<T: TypePath, U: VariableProperty<Output = T>, const N: usize> VariableProperty for [U; N] {
    type Output = [T; N];

    fn get_value(&self) -> [T; N] {
        array![i => self[i].get_value(); N]
    }
}

macro_rules! reverse_types_output {
    () => {};
    ([$($list:tt,)*], $head:tt, $($tail:tt,)*) => {
       reverse_types_output!([$head, $($list,)*], $($tail,)*)
    };
    ([$($list:tt,)+],) => {
        paste! {(
            $($list::Output,)+
        )}
    };
}

macro_rules! reverse_get_value {
    () => {};
    ($self:ident, [$($list:literal,)*], $head:literal, $($tail:literal,)*) => {
       reverse_get_value!($self, [$head, $($list,)*], $($tail,)*)
    };
    ($self:ident, [$($list:literal,)+],) => {
        paste! {(
            $($self.$list.get_value(),)+
        )}
    };
}

macro_rules! reverse_types {
    () => {};
    ([$($list:expr,)*], $head:expr, $($tail:expr,)*) => {
       reverse_types!([$head, $($list,)*], $($tail,)*)
    };
    ([$($list:expr,)+],) => {
        paste! {(
            $($list,)+
        )}
    };
}

macro_rules! variable_property_impls {
    () => {};
    ($head_idx:literal $head_type:tt, $($idx:literal $type:tt,)*) => {

        impl<$head_type: VariableProperty,$($type: VariableProperty,)*> VariableProperty for reverse_types!([], $head_type, $($type,)*) {
            type Output = reverse_types_output!([], $head_type, $($type,)*);
            fn get_value(&self) -> Self::Output {
                reverse_get_value!(self, [], $head_idx, $($idx,)*)
            }
        }


        variable_property_impls!($($idx $type,)*);
    };
}

variable_property_impls!(11 L,  10 K,  9 J, 8 I, 7 H, 6 G, 5 F, 4 E, 3 D, 2 C, 1 B, 0 A,);