4 releases

0.2.3 May 4, 2024
0.2.2 May 4, 2024
0.2.1 May 4, 2024
0.2.0 Mar 11, 2024
0.1.0 Mar 9, 2024

#1304 in Game dev

Download history 108/week @ 2024-03-03 287/week @ 2024-03-10 44/week @ 2024-03-17 29/week @ 2024-03-24 53/week @ 2024-03-31 13/week @ 2024-04-07 9/week @ 2024-04-14 228/week @ 2024-04-28 232/week @ 2024-05-05

470 downloads per month
Used in 8 crates (3 directly)

MIT license

24KB
322 lines

🛠️ Moonshine Utilities

crates.io downloads docs.rs license stars

Collection of utilities for Bevy.

Features

Expect<T>

A decorator for QueryData which panics if it doesn't match.

This helps avoid silent failures in systems due to missing components:

use bevy::prelude::*;
use moonshine_util::expect::Expect;

#[derive(Component)]
struct A;

#[derive(Component)]
struct B;

#[derive(Bundle)]
struct AB {
    a: A, // Every `A` is expected to have a `B`
    b: B,
}

fn bad_system(mut commands: Commands) {
    commands.spawn(A); // BUG: Spawn A witout B!
}

fn unsafe_system(mut query: Query<(&A, &B)>) {
    for (a, b) in query.iter() {
        // An instance of `A` does exist, but this system skips over it silently!
    }
}

fn safe_system(mut query: Query<(&A, Expect<&B>)>) {
    for (a, b) in query.iter() {
        // This system will panic if an `A` instance is missing a `B`!
    }
}

HierarchyQuery

A convenient SystemParam for traversing and querying entity hierarchies:

use bevy::prelude::*;
use moonshine_util::hierarchy::HierarchyQuery;

#[derive(Component)]
struct Needle;

#[derive(Component)]
struct Haystack;

fn spawn_haystack(mut commands: Commands) {
    // A complex hierarchy ...
    commands.spawn(Haystack).with_children(|x| {
        x.spawn_empty().with_children(|y| {
            y.spawn_empty().with_children(|z| {
                z.spawn(Needle);
            });
        });
    });
}

fn find_needle(
    haystack: Query<Entity, With<Haystack>>,
    needle_query: Query<Entity, With<Needle>>,
    hierarchy: HierarchyQuery
) {
    let haystack = haystack.single();
    if let Some(needle) = hierarchy.find_descendant(haystack, &needle_query) {
        // ...
    }
}

Some useful functions include:

  • fn parent(&self, Entity) -> Option<Entity>
  • fn has_parent(&self, Entity) -> bool
  • fn children(&self, Entity) -> Iterator<Item = Entity>
  • fn has_children(&self, Entity) -> bool
  • fn root(&self, Entity) -> Entity
  • fn is_root(&self, Entity) -> bool
  • fn ancestors(&self, Entity) -> Iterator<Item = Entity>
  • fn descendants(&self, Entity) -> Iterator<Item = Entity>
  • fn is_ancestor_of(&self, Entity, Entity) -> bool
  • fn is_descendant_of(&self, Entity, Entity) -> bool
  • fn find_ancestor<T, F>(&self, Entity, &Query<T, F>) -> Option<QueryItem<T>>
  • fn find_descendant<T, F>(&self, Entity, &Query<T, F>) -> Option<QueryItem<T>>

See code documentation for complete details.

RunSystemLoop

A trait similar to RunSystemOnce which allows you to run a system loop for testing purposes:

use bevy::prelude::*;
use moonshine_util::diagnostics::RunSystemLoop;

let mut world = World::new();
let outputs = world.run_system_loop(2, |mut commands: Commands| {
    commands.spawn_empty().id()
});

assert_eq!(outputs.len(), 2);

assert!(world.get_entity(outputs[0]).is_some());
assert!(world.get_entity(outputs[1]).is_some());

Utility Systems

A collection of simple and generic systems useful for constructing larger system pipelines:

  • has_event<T: Event>() -> bool
  • has_resource<T: Resource>() -> bool
  • remove_resource<T: Resource>(Commands)
  • remove_resource_immediate<T: Resource>(&mut World)

See code documentation for usage examples.

Support

Please post an issue for any bugs, questions, or suggestions.

You may also contact me on the official Bevy Discord server as @Zeenobit.

Dependencies

~11MB
~191K SLoC