-1

there are lot of functions

fn add_people(mut commands: Commands) {
    commands.spawn((Person, Name("A".to_string())));
    commands.spawn((Person, Name("B".to_string())));
    commands.spawn((Person, Name("C".to_string())));
    commands.spawn((Person, Name("D".to_string())));
}

fn greet_people(query: Query<&Name, With<Person>>) {
    for name in query.iter() {
        println!("hello {}!", name.0);
    }
}
fn hello_world() {
    println!("hello world");
}

these are the functions i want to invoke

pub fn add_startup_system<Params>(&mut self, system: impl IntoSystemDescriptor<Params>)

pub fn add_system<Params>(&mut self, system: impl IntoSystemDescriptor<Params>)

like this

    App::new()
        .add_plugins(DefaultPlugins)
        .add_startup_system(hello_world)
        .add_startup_system(add_people)
        .add_system(greet_people)
        .run();

the types of funtions above are fn(Commands) fn(Query<&Name, With<Person>>) fn(),and all of them satisfay the tarit IntoSystemDescriptor<Params>

the definiton of tarit IntoSystemDescriptor<Params> is

pub trait IntoSystemDescriptor<Params> {
    fn into_descriptor(self) -> SystemDescriptor;
    /// Assigns a run criteria to the system. Can be a new descriptor or a label of a
    /// run criteria defined elsewhere.
    fn with_run_criteria<Marker>(
        self,
        run_criteria: impl IntoRunCriteria<Marker>,
    ) -> SystemDescriptor;

    /// Assigns a label to the system; there can be more than one, and it doesn't have to be unique.
    fn label(self, label: impl SystemLabel) -> SystemDescriptor;

    /// Specifies that the system should run before systems with the given label.
    fn before<Marker>(self, label: impl AsSystemLabel<Marker>) -> SystemDescriptor;

    /// Specifies that the system should run after systems with the given label.
    fn after<Marker>(self, label: impl AsSystemLabel<Marker>) -> SystemDescriptor;

    /// Marks this system as ambiguous with any system with the specified label.
    /// This means that execution order between these systems does not matter,
    /// which allows [some warnings](crate::schedule::ReportExecutionOrderAmbiguities) to be silenced.
    fn ambiguous_with<Marker>(self, label: impl AsSystemLabel<Marker>) -> SystemDescriptor;

    /// Specifies that this system should opt out of
    /// [execution order ambiguity detection](crate::schedule::ReportExecutionOrderAmbiguities).
    fn ignore_all_ambiguities(self) -> SystemDescriptor;

    /// Specifies that the system should run with other exclusive systems at the start of stage.
    fn at_start(self) -> SystemDescriptor;

    /// Specifies that the system should run with other exclusive systems after the parallel
    /// systems and before command buffer application.
    fn before_commands(self) -> SystemDescriptor;

    /// Specifies that the system should run with other exclusive systems at the end of stage.
    fn at_end(self) -> SystemDescriptor;
}

it is difficult to understand why fn implemented the trait

it looks that both of them do not have any relationship

can anyone explain why fn satisfy the trait?

or give me a link of rust feature about it

Bruno Ranschaert
  • 7,428
  • 5
  • 36
  • 46

1 Answers1

0

It is one of core features of Bevy.

Bevy is an Entity-Component-System engine. There were other ECS engines like Amethyst before Bevy but Bevy made writing Systems easy. Unlike other engines, Systems are not some special structs but just functions. They just need to accept system params and you can give this function to Bevy. Bevy would do all scheduling and parameter passing (using Dependency injection) so you don't need to do all of this yourself.

You can read more in the docs and in the very first release notes.

AFAIK, it is implemented by implemented the trait you shown for any types F which implement any of FnMut(), FnMut(P1) where P1: IntoSystemParam, ..., FnMut(P1, ..., PN) where P1: IntoSystemPara, ..., PN: IntoSystemParam. All of those impls made by macros. You can see list of those implementations here.