bevy-trait-resource 0.2.1

Get resources by trait
Documentation
use super::*;

#[trait_resource]
pub trait IncrementTrait {
    fn value(&self) -> i32;
    fn increment(&mut self);
}

#[trait_resource]
pub trait IncrementStringTrait {
    fn string_value(&self) -> String;
    fn increment_string(&mut self);
}

#[derive(Resource, Default)]
struct NumberValueResource {
    value: i32,
}

#[derive(Resource)]
struct NumberValueResource2 {
    string_value: String,
    value: i32,
}

impl Default for NumberValueResource2 {
    fn default() -> Self {
        NumberValueResource2 {
            string_value: "0".to_owned(),
            value: 0,
        }
    }
}

impl IncrementTrait for NumberValueResource {
    fn value(&self) -> i32 {
        self.value
    }
    fn increment(&mut self) {
        self.value += 1;
    }
}

impl IncrementTrait for NumberValueResource2 {
    fn value(&self) -> i32 {
        self.value
    }
    fn increment(&mut self) {
        self.value += 1;
    }
}

impl IncrementStringTrait for NumberValueResource2 {
    fn string_value(&self) -> String {
        self.string_value.clone()
    }

    fn increment_string(&mut self) {
        let i: i32 = self.string_value.parse().unwrap();
        self.string_value = (i + 1).to_string();
    }
}

pub fn increment_value_test_system(world: &mut World) {
    for res_opt in world.get_resources_trait_mut::<dyn IncrementTrait>() {
        if let Some(res) = res_opt {
            res.increment();
        }
    }
}

pub fn increment_string_value_test_system(world: &mut World) {
    for res_opt in world.get_resources_trait_mut::<dyn IncrementStringTrait>() {
        if let Some(res) = res_opt {
            res.increment_string();
        }
    }
}

#[test]
fn increment() {
    let mut world = World::new();
    world.init_resource_as::<dyn IncrementTrait, NumberValueResource>();

    let mut schedule = Schedule::new(Update);

    schedule.add_systems(increment_value_test_system);

    schedule.run(&mut world);
    schedule.run(&mut world);

    assert_eq!(world.resource::<NumberValueResource>().value(), 2);
}

#[test]
fn increment_multiple() {
    let mut world = World::new();
    world.init_resource_as::<dyn IncrementTrait, NumberValueResource>();
    world.insert_resource_as::<dyn IncrementTrait, NumberValueResource2>(NumberValueResource2 {
        string_value: "0".to_owned(),
        value: 3,
    });

    let mut schedule = Schedule::new(Update);

    schedule.add_systems(increment_value_test_system);

    schedule.run(&mut world);
    schedule.run(&mut world);

    assert_eq!(world.resource::<NumberValueResource>().value(), 2);

    assert_eq!(world.resource::<NumberValueResource2>().value(), 5);
    assert_eq!(world.resource::<NumberValueResource2>().string_value, "0");
}


#[test]
fn getting_removed_resource_should_not_panic() {
    let mut world = World::new();
    world.init_resource_as::<dyn IncrementTrait, NumberValueResource>();
    world.insert_resource_as::<dyn IncrementTrait, NumberValueResource2>(NumberValueResource2 {
        string_value: "1".to_owned(),
        value: 3,
    });

    let mut schedule = Schedule::new(Update);

    schedule.add_systems(increment_value_test_system);

    schedule.run(&mut world);

    assert_eq!(world.resource::<NumberValueResource>().value(), 1);

    assert_eq!(world.resource::<NumberValueResource2>().value(), 4);
    assert_eq!(world.resource::<NumberValueResource2>().string_value, "1");


    world.remove_resource::<NumberValueResource2>();

    schedule.run(&mut world);

    assert_eq!(world.resource::<NumberValueResource>().value(), 2);
    assert!(world.get_resource::<NumberValueResource2>().is_none());
}


#[test]
#[should_panic(expected = "Trying to register a nonexistent resource")]
fn registering_non_existing_resource_should_panic() {
    let mut world = World::new();
    world.register_resource_as::<dyn IncrementTrait, NumberValueResource>();
}

#[test]
fn register_resource_trait() {
    let mut world = World::new();
    world.init_resource::<NumberValueResource>();
    world.register_resource_as::<dyn IncrementTrait, NumberValueResource>();

    let mut schedule = Schedule::new(Update);

    schedule.add_systems(increment_value_test_system);

    schedule.run(&mut world);
    assert_eq!(world.resource::<NumberValueResource>().value(), 1);

    schedule.run(&mut world);
    assert_eq!(world.resource::<NumberValueResource>().value(), 2);
}

#[test]
fn register_multiple_traits_on_resource() {
    let mut world = World::new();
    world.init_resource::<NumberValueResource2>();
    world.register_resource_as::<dyn IncrementTrait, NumberValueResource2>()
         .register_resource_as::<dyn IncrementStringTrait, NumberValueResource2>();

    let mut schedule = Schedule::new(Update);

    schedule.add_systems(increment_value_test_system);
    schedule.add_systems(increment_string_value_test_system);

    schedule.run(&mut world);
    assert_eq!(world.resource::<NumberValueResource2>().value(), 1);
    assert_eq!(world.resource::<NumberValueResource2>().string_value(), "1");

    schedule.run(&mut world);
    assert_eq!(world.resource::<NumberValueResource2>().value(), 2);
    assert_eq!(world.resource::<NumberValueResource2>().string_value(), "2");
}

#[test]
fn unregister_trait_from_resource() {
    let mut world = World::new();
    world.init_resource::<NumberValueResource>();
    world.init_resource::<NumberValueResource2>();

    world.register_resource_as::<dyn IncrementStringTrait, NumberValueResource2>();
    world.register_resource_as::<dyn IncrementTrait, NumberValueResource2>();
    world.register_resource_as::<dyn IncrementTrait, NumberValueResource>();

    match world.get_resource::<TraitResourceRegistry<dyn IncrementTrait>>() {
        Some(registry) => {
            assert_eq!(registry.trait_data.len(), 2);
        },
        None => panic!("Registry should exist"),
    }

    world.unregister_resource_from_trait::<dyn IncrementTrait, NumberValueResource2>();

    match world.get_resource::<TraitResourceRegistry<dyn IncrementTrait>>() {
        Some(registry) => {
            assert_eq!(registry.trait_data.len(), 1);
        },
        None => panic!("Registry should exist"),
    }

    world.unregister_resource_from_trait::<dyn IncrementTrait, NumberValueResource>();

    assert!(world.get_resource::<TraitResourceRegistry<dyn IncrementTrait>>().is_none());
    assert!(world.get_resource::<TraitResourceRegistry<dyn IncrementStringTrait>>().is_some());
}