Git Product home page Git Product logo

iyes_loopless's Issues

Bevy 0.9 support

I attempted to update my project to Bevy 0.9, which was just released a few days ago, and the majority of the iyes_loopless functionality broke.

Specifically, it seems most of the new methods added to App are not being found, like add_loopless_state, add_exit_system and add_enter_system. These all have the very simple error in the form:

no method named `add_loopless_state` found for struct `bevy::prelude::App` in the current scope

It also can't find the run_in_state method when I try to call it on one of my systems when adding it to the app. It works when called directly on a ConditionSet (or at least I'm not seeing a compilation error on it yet). The error I get on this is much more complicated and hard to make sense of, given the extensive layered generics. This is an example:

the method `run_in_state` exists for fn item `for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7> fn(bevy::prelude::Commands<'r, 's>, bevy::prelude::Query<'t0, 't1, (&'t2 mut ButtonInteraction, &'t3 PowerButton)>, bevy::prelude::Query<'t4, 't5, &'t6 mut PowerMenu>, bevy::prelude::Res<'t7, bevy::prelude::Input<bevy::prelude::KeyCode>>) {power_menu_ui_system}`, but its trait bounds were not satisfied
the following trait bounds were not satisfied:
`for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7> fn(bevy::prelude::Commands<'r, 's>, bevy::prelude::Query<'t0, 't1, (&'t2 mut ButtonInteraction, &'t3 PowerButton)>, bevy::prelude::Query<'t4, 't5, &'t6 mut PowerMenu>, bevy::prelude::Res<'t7, bevy::prelude::Input<bevy::prelude::KeyCode>>) {power_menu_ui_system}: bevy_ecs::system::function_system::IntoSystem<(), (), _>`
which is required by `for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7> fn(bevy::prelude::Commands<'r, 's>, bevy::prelude::Query<'t0, 't1, (&'t2 mut ButtonInteraction, &'t3 PowerButton)>, bevy::prelude::Query<'t4, 't5, &'t6 mut PowerMenu>, bevy::prelude::Res<'t7, bevy::prelude::Input<bevy::prelude::KeyCode>>) {power_menu_ui_system}: iyes_loopless::condition::IntoConditionalSystem<_>`
`&for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7> fn(bevy::prelude::Commands<'r, 's>, bevy::prelude::Query<'t0, 't1, (&'t2 mut ButtonInteraction, &'t3 PowerButton)>, bevy::prelude::Query<'t4, 't5, &'t6 mut PowerMenu>, bevy::prelude::Res<'t7, bevy::prelude::Input<bevy::prelude::KeyCode>>) {power_menu_ui_system}: bevy_ecs::system::function_system::IntoSystem<(), (), _>`
which is required by `&for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7> fn(bevy::prelude::Commands<'r, 's>, bevy::prelude::Query<'t0, 't1, (&'t2 mut ButtonInteraction, &'t3 PowerButton)>, bevy::prelude::Query<'t4, 't5, &'t6 mut PowerMenu>, bevy::prelude::Res<'t7, bevy::prelude::Input<bevy::prelude::KeyCode>>) {power_menu_ui_system}: iyes_loopless::condition::IntoConditionalSystem<_>`
`&mut for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7> fn(bevy::prelude::Commands<'r, 's>, bevy::prelude::Query<'t0, 't1, (&'t2 mut ButtonInteraction, &'t3 PowerButton)>, bevy::prelude::Query<'t4, 't5, &'t6 mut PowerMenu>, bevy::prelude::Res<'t7, bevy::prelude::Input<bevy::prelude::KeyCode>>) {power_menu_ui_system}: bevy_ecs::system::function_system::IntoSystem<(), (), _>`
which is required by `&mut for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7> fn(bevy::prelude::Commands<'r, 's>, bevy::prelude::Query<'t0, 't1, (&'t2 mut ButtonInteraction, &'t3 PowerButton)>, bevy::prelude::Query<'t4, 't5, &'t6 mut PowerMenu>, bevy::prelude::Res<'t7, bevy::prelude::Input<bevy::prelude::KeyCode>>) {power_menu_ui_system}: iyes_loopless::condition::IntoConditionalSystem<_>`

Also, Bevy now requires all resources to explicitly #[derive(Resource)]. This is breaking the NextState resource.

Further, the trait bounds that ConditionalSet::with_system uses seems to be broken, as every single system I try to add that way is now generating an error that it does not implement the required trait bounds. The error message is again a mess of layered generics that's hard to make sense of, but this is an example, pulled from one of my simplest systems:

the trait bound `for<'r, 's, 't0, 't1, 't2> fn(bevy::prelude::Res<'r, bevy::prelude::Time>, bevy::prelude::Query<'s, 't0, (&'t1 Drag, &'t2 mut Velocity)>) {drag_system}: bevy_ecs::system::function_system::IntoSystem<(), (), _>` is not satisfied
the trait `AddConditionalToSet<ConditionSystemSet, ()>` is implemented for `ConditionalSystemDescriptor`
required for `for<'r, 's, 't0, 't1, 't2> fn(bevy::prelude::Res<'r, bevy::prelude::Time>, bevy::prelude::Query<'s, 't0, (&'t1 Drag, &'t2 mut Velocity)>) {drag_system}` to implement `iyes_loopless::condition::IntoConditionalSystem<_>`
required for `for<'r, 's, 't0, 't1, 't2> fn(bevy::prelude::Res<'r, bevy::prelude::Time>, bevy::prelude::Query<'s, 't0, (&'t1 Drag, &'t2 mut Velocity)>) {drag_system}` to implement `AddConditionalToSet<ConditionSystemSet, _>`r

I'm sure there are other incompatibilities as well, but these are the ones I'm currently seeing.

Do not require `.into_conditional()`

Do some trait magic to expose .run_if (and any other methods added for #1 and #2, and states, etc) directly on anything that impls IntoSystem, as well as on ConditionalSystem.

This will eliminate the need for .into_conditional(), making the user-facing API simpler.

Mass-applying conditions

Currently, conditions have to be applied to each individual system, resulting in a lot of repetitive boilerplate.

Investigate what could be done to make it possible to apply conditions to many systems at once.

Bevy's system labeling apis may be a source of inspiration.

Missing Downcast: StateTransitionStageLabel

Whenever I start up my game, I get a message in the console about how my states are missing downcasts. I have no idea what it means, and I'm not sure it causes problems.

Cannot use Run_If with systems taking Local<LocalStateType>

I would love it if run_if could take Local Arguments in. With the below code I get the following error:
.add_system(self::gamelobby::lobby.run_if(show_lobby_screen))

System:

use super::{UIState, UIStateRes};

pub struct LobbyStateRes{
    pub selected_map: String
}

pub fn lobby(mut egui_context: ResMut<EguiContext>, mut ui_state: ResMut<UIStateRes>, mut maps_manifest: ResMut<MapManifest>, mut lobby_state: Local<LobbyStateRes>) {
    Window::new("Game Lobby")
        .anchor(Align2::CENTER_CENTER, egui::vec2(0.0, -50.0))
        .show(egui_context.ctx_mut(), |ui| {
            egui::ScrollArea::vertical().show(ui, |ui|{
                for map in &maps_manifest.map_files{
                    let sel_map_btn = ui.radio_value(&mut lobby_state.selected_map, map.clone(), map);
                }
            });

            let play_btn = ui.button("Launch Game");

            if play_btn.clicked() && lobby_state.selected_map != *"".to_string(){ //Such unrust shall not stand!
                ui_state.current_state = UIState::Game
            }

            let back_btn = ui.button("Main Menu");

            if back_btn.clicked() {
                ui_state.current_state = UIState::MainMenu;
            }
        });
}

Error

[{
	"resource": "/e:/rust/macrophage/src/ui/mod.rs",
	"owner": "rustc",
	"code": {
		"value": "E0599",
		"target": {
			"$mid": 1,
			"external": "https://doc.rust-lang.org/error-index.html#E0599",
			"path": "/error-index.html",
			"scheme": "https",
			"authority": "doc.rust-lang.org",
			"fragment": "E0599"
		}
	},
	"severity": 8,
	"message": "the method `run_if` exists for fn item `for<'r, 's, 't0, 't1> fn(bevy::prelude::ResMut<'r, bevy_egui::EguiContext>, bevy::prelude::ResMut<'s, ui::UIStateRes>, bevy::prelude::ResMut<'t0, util::MapManifest>, bevy::prelude::Local<'t1, ui::gamelobby::LobbyStateRes>) {ui::gamelobby::lobby}`, but its trait bounds were not satisfied\nthe following trait bounds were not satisfied:\n`for<'r, 's, 't0, 't1> fn(bevy::prelude::ResMut<'r, bevy_egui::EguiContext>, bevy::prelude::ResMut<'s, ui::UIStateRes>, bevy::prelude::ResMut<'t0, util::MapManifest>, bevy::prelude::Local<'t1, ui::gamelobby::LobbyStateRes>) {ui::gamelobby::lobby}: bevy::prelude::IntoSystem<(), (), _>`\nwhich is required by `for<'r, 's, 't0, 't1> fn(bevy::prelude::ResMut<'r, bevy_egui::EguiContext>, bevy::prelude::ResMut<'s, ui::UIStateRes>, bevy::prelude::ResMut<'t0, util::MapManifest>, bevy::prelude::Local<'t1, ui::gamelobby::LobbyStateRes>) {ui::gamelobby::lobby}: iyes_loopless::condition::IntoConditionalSystem<_>`\n`&for<'r, 's, 't0, 't1> fn(bevy::prelude::ResMut<'r, bevy_egui::EguiContext>, bevy::prelude::ResMut<'s, ui::UIStateRes>, bevy::prelude::ResMut<'t0, util::MapManifest>, bevy::prelude::Local<'t1, ui::gamelobby::LobbyStateRes>) {ui::gamelobby::lobby}: bevy::prelude::IntoSystem<(), (), _>`\nwhich is required by `&for<'r, 's, 't0, 't1> fn(bevy::prelude::ResMut<'r, bevy_egui::EguiContext>, bevy::prelude::ResMut<'s, ui::UIStateRes>, bevy::prelude::ResMut<'t0, util::MapManifest>, bevy::prelude::Local<'t1, ui::gamelobby::LobbyStateRes>) {ui::gamelobby::lobby}: iyes_loopless::condition::IntoConditionalSystem<_>`\n`&mut for<'r, 's, 't0, 't1> fn(bevy::prelude::ResMut<'r, bevy_egui::EguiContext>, bevy::prelude::ResMut<'s, ui::UIStateRes>, bevy::prelude::ResMut<'t0, util::MapManifest>, bevy::prelude::Local<'t1, ui::gamelobby::LobbyStateRes>) {ui::gamelobby::lobby}: bevy::prelude::IntoSystem<(), (), _>`\nwhich is required by `&mut for<'r, 's, 't0, 't1> fn(bevy::prelude::ResMut<'r, bevy_egui::EguiContext>, bevy::prelude::ResMut<'s, ui::UIStateRes>, bevy::prelude::ResMut<'t0, util::MapManifest>, bevy::prelude::Local<'t1, ui::gamelobby::LobbyStateRes>) {ui::gamelobby::lobby}: iyes_loopless::condition::IntoConditionalSystem<_>`",
	"source": "rustc",
	"startLineNumber": 45,
	"startColumn": 44,
	"endLineNumber": 45,
	"endColumn": 50,
	"relatedInformation": [
		{
			"startLineNumber": 45,
			"startColumn": 21,
			"endLineNumber": 45,
			"endColumn": 43,
			"message": "this is a function, perhaps you wish to call it",
			"resource": "/e:/rust/macrophage/src/ui/mod.rs"
		}
	]
}]

Change fixed timestep duration at runtime

My problem is that I need to be able to change the simulation speed of my game but it seems there is no way of changing the timestep after creating the FixedTimestepStage.

.add_stage_before(
    CoreStage::Update,
    "Enviroment",
    FixedTimestepStage::from_stage(Duration::from_millis( 1.0 / BASE_FPS), enviromentStage),
)
fn sync_game_speed(
    game_speed: Res<GameSpeed>,
    mut rapier_config: ResMut<RapierConfiguration>,
){
    rapier_config.timestep_mode = TimestepMode::Interpolated { dt: 1.0 / BASE_FPS as f32, time_scale: game_speed.0, substeps: 1 }
 <<HERE I NEED TO CHANGE THE FixedTimestepStage TO THE SAME SPEED AS THE PHYSICS>>
}

Is this possible to do? Or should one use somthing like:

.add_system_set(
            ConditionSet::new()
                .run_in_state(AppState::Gaming)
                .run_if(shouldRunSimulationTick) <- manual accumulator that can be dependent on GameSpeed resource
                .with_system(simulation_system1)
                .with_system(simulation_system2...)
                .into()

RC Helpers

Implement some helper methods to easily add common Run Conditions.

  • .run_on_event::<Event>()
  • .run_if_resource_exists::<Res>()
  • .run_if_resource_equals(value)
  • .run_unless_resource_exists::<Res>()
  • .run_unless_resource_equals(value)

Explore how to make APIs play nicer with Plugins

Because of how our fixed timestep and states implementations rely on the user adding custom stages, that nest other stages, it is difficult to make this play nicely with Bevy's Plugin API.

If a plugin needs to add stuff to happen on state transitions, or on fixed timestep, it has no way of accessing the actual SystemStages to add systems to. Labels don't help, because Bevy's SystemLabels are a top-level Schedule thing, and cannot refer to nested stages.

The only way right now seems to be to sidestep the Plugin API altogether, and just use functions that take &mut SystemStage (for whatever they need access to) instead.

This might not be solvable while our stuff is in an external crate, and I cannot think of a better design. I'm open to ideas.

Adding systems to one of the stages in a `FixedTimestepStage`?

TL;DR: Is there a way to add system sets to the stages of a FixedTimestepStage that has been added to my App elsewhere?

How I understand the documentation one adds the FixedTimestepStage into the scheduler, e.g. before the CoreStage::Update. Then FixedTimestepStage has sub-stages which are executed at the time-step. In a sub-stage, I can use labels to order the execution of my systems using before or after. But say I want to make a plugin that adds a system set to one of these sub-stages, to be able to have access to these labels, how do I do that?

More concretely: I'm looking after a design in which I can have a plugin handling A components, one plugin handling B, and then one plugin handling their interaction. The interaction should take place after A and B have both been updated, so I can label the ConditionSets I have defined for A and B, but to have access to those labels it appears that all systems needs to be part of the same sub-stage. That is I imagine to be able to do something along these lines

impl Plugin for InitFixedTimestepStage {
    fn build(&self, app: &mut App) {
        app.add_stage_before(
            CoreStage::Update,
            "ft_label",
            FixedTimestepStage::new(Duration::from_secs_f32(TIME_STEP))
                .add_stage_with_label( // suggested method
                    "interaction_label",
                    SystemStage::parallel() // adding empty stage to add systems to later
                )
        )
    }
}

impl Plugin for UpdateComponentA {
    fn build(&self, app: &mut App) {
        app.schedule
            .get_stage_mut("ft_label").unwrap()
            .get_stage_mut("interaction_label").unwrap() // suggested method
            .add_system_set(
                ConditionSet::new()
                    .label("update_A")
                    .with_system(update_A)
                    .into()
            );
    }
}

// same for B... then:

impl Plugin for InteractionAB {
    fn build(&self, app: &mut App) {
        app.schedule
            .get_stage_mut("ft_label").unwrap()
            .get_stage_mut("interaction_label").unwrap() // suggested method
            .add_system_set(
                ConditionSet::new()
                    .after("update_A") // This label...
                    .after("update_B") // ... and this label is now available as we are in stage "interaction_label"
                    .label("interact_AB")
                    .with_system(interact_AB)
                    .into()
            );
    }
}

This would make the plugins more modular, otherwise I'd have to design large plugins that has access to all systems at once.

Or is there a way to do this that I'm just missing?

Ambiguity when mixing exclusive and normal systems

It seems I must manually bring in iyes_loopless::condition::IntoConditionalExclusiveSystem to support exclusive systems with conditions, however this appears to cause an ambiguity problem with non-exclusive systems if I bring it into the same scope. This example demonstrates my issue:

use bevy::prelude::*;
use iyes_loopless::prelude::*;
use iyes_loopless::condition::IntoConditionalExclusiveSystem;

fn main() {
    App::new()
        .add_plugins(MinimalPlugins)
        .add_loopless_state(DevState::Loading)
        .add_enter_system(DevState::Loading, setup)
        .add_system(ready
            .run_in_state(DevState::Ready)
            .run_unless_resource_exists::<Thing>()
        )
        .add_system(process
            .run_in_state(DevState::Loading)
            .run_if_resource_exists::<Thing>()
            .at_end()
        )
        .run()
    ;
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DevState {
    Loading,
    Ready,
}

#[derive(Debug, Clone, Copy)]
pub struct Thing(pub u32);

fn setup(mut commands: Commands) {
    commands.insert_resource(Thing(1));
}

fn ready(mut commands: Commands) {
    println!("ready");
    commands.insert_resource(Thing(2));
}

fn process(mut world: &mut World) {
    println!("removed {:?}", world.remove_resource::<Thing>());
    world.insert_resource(NextState(DevState::Ready));
}
   --> examples\test.rs:11:14
    |
11  |             .run_in_state(DevState::Loading)
    |              ^^^^^^^^^^^^ multiple `run_in_state` found
    |
    = note: candidate #1 is defined in an impl of the trait `iyes_loopless::condition::IntoConditionalSystem` for the type `S`
    = note: candidate #2 is defined in an impl of the trait `IntoConditionalExclusiveSystem` for the type `S`
note: candidate #3 is defined in the trait `iyes_loopless::condition::ConditionHelpers`
   --> C:\Users\s33n\.cargo\registry\src\github.com-1ecc6299db9ec823\iyes_loopless-0.5.1\src\condition.rs:366:5
    |
366 |     fn run_in_state<T: bevy_ecs::schedule::StateData>(self, state: T) -> Self {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #1
    |
10  |         .add_system(iyes_loopless::condition::IntoConditionalSystem::run_in_state(ready, DevState::Loading)
    |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
help: disambiguate the associated function for candidate #2
    |
10  |         .add_system(IntoConditionalExclusiveSystem::run_in_state(ready, DevState::Loading)
    |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
help: disambiguate the associated function for candidate #3
    |
10  |         .add_system(iyes_loopless::condition::ConditionHelpers::run_in_state(ready, DevState::Loading)
    |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

One option I see is to fully qualify the extension for each exclusive system I add. This works, but seems verbose and ugly:

.add_system(iyes_loopless::condition::IntoConditionalExclusiveSystem::run_in_state(process,DevState::Loading)
    .run_if_resource_exists::<Thing>()
    .at_end()
)

Another option I've found is to scope the exclusive trait. This at least preserves the look and feel of the builder API, but still feels quite verbose:

use bevy::prelude::*;
use iyes_loopless::prelude::*;

fn main() {
    let mut app = App::new();
    app.add_plugins(MinimalPlugins)
        .add_loopless_state(DevState::Loading)
        .add_enter_system(DevState::Loading, setup)
        .add_system(ready
            .run_in_state(DevState::Ready)
            .run_unless_resource_exists::<Thing>()
        )
    ;
    // scope for exclusive systems
    {
        use iyes_loopless::condition::IntoConditionalExclusiveSystem;

        app.add_system(process
            .run_in_state(DevState::Loading)
            .run_if_resource_exists::<Thing>()
            .at_end()
        );
    }
    app.run();
}

Any better options?

Build fails without "states" feature

   Compiling iyes_loopless v0.7.1
error[E0433]: failed to resolve: could not find `state` in the crate root
  --> C:\Users\Johan\.cargo\registry\src\github.com-1ecc6299db9ec823\iyes_loopless-0.7.1\src\lib.rs:13:20
   |
13 |     pub use crate::state::schedule::ScheduleLooplessStateExt;
   |                    ^^^^^ could not find `state` in the crate root

For more information about this error, try `rustc --explain E0433`.
error: could not compile `iyes_loopless` due to previous error
Error: cargo command failed
error: process didn't exit successfully: `target\debug\xtask.exe dist ultra_bevy` (exit code: 1)
\"[Finished running. Exit status: 0]\"

ConditionSet::label does not compile

Using the .label method of ConditionSet, using either a string or a basic derived SystemLabel, results in a compile-time error:

the method `label` exists for struct `ConditionSystemSet`, but its trait bounds were not satisfied

To reproduce, add a .label call to a ConditionSet.

Discussed previously in this Discord thread.

Is there alternative to bevy's state stack?

I've switched from bevy state system into loopless, because there wasn't any information about "setup" systems in it, only loop, but I've found such implementation there. But after I found out such realization in bevy cheatbook (which I've not remarked somehow), I've also seen such thing as "stacks" which lets you make implementation of "pause" state etc. Does similar thing exists in loopless, or I need to get back to bevy systems?

P.S.: Or is there another way to implement pause menu or smth like this? Thx

Tick timers

It would be cool to provide a "tick timers" implementation that works with our FixedTimestep. Timers/Stopwatches that count timesteps, instead of real time durations.

Loopless Stage

Implement an alternative to use instead of Bevy's SystemStage, which:

  • does not support Bevy Run Criteria
  • natively supports our Run Conditions
  • evaluates run conditions in-line and removes the perf overhead of unnecessarily spawning tasks

Can't use system.after() within a ConditionSet

Hello, I have an issue with systems ordering within a ConditionSet.

With a standard SystemSet, this works:

.with_system_set(
    SystemSet::new()
        .label("update")
        .with_system(movement::apply_velocity)
        .with_system(movement::constrain_entities.after(movement::apply_velocity)),
)

But with a ConditionSet this doesn't:

.with_system_set(
    ConditionSet::new()
        .label("update")
        .run_if(state_is_in_game)
        .with_system(movement::apply_velocity)
        .with_system(movement::constrain_entities.after(movement::apply_velocity)) // Error on this line
        .into(),
)

the trait bound ParallelSystemDescriptor: IntoSystem<(), (), _> is not satisfied
the trait AddConditionalToSet<ConditionSystemSet, ()> is implemented for ConditionalSystemDescriptor
required because of the requirements on the impl of IntoConditionalSystem<_> for ParallelSystemDescriptor
required because of the requirements on the impl of AddConditionalToSet<ConditionSystemSet, _> for ParallelSystemDescriptorrustcE0277

If I use a .into() after the .after(), the error changes to

type annotations needed
cannot infer type of the type parameter S declared on the associated function with_systemrustcE0282
mod.rs(52, 37): consider specifying the generic arguments: ::<S, P>

Edit: I can use .chain() for this specific case, but being able to use .after() and .before() within a ConditionSet would be better

Possible for ConditionSet on exit?

In bevy you can have a system set run on state exit like so:

.add_system_set(
    SystemSet::on_exit(GameState::MainMenu)
        .label("spawn")
        .with_system(spawn_player)
        .with_system(spawn_enemies),
);

I couldnt find a way to do this with ConditionSet without having to add multiple exist systems

app
    .add_exit_system(GameState::MainMenu, spawn_player)
    .add_exit_system(GameState::MainMenu, spawn_enemies)

Cannot use before/after in ConditionSet

I don't know if it's expected, but it looks like we cannot use the before/after functions inside a condition set?

If i try to run

.add_system_set(
                ConditionSet::new()
                    .run_in_state(InGameState::Game)
                    .with_system(food_contact_event)
                    .with_system(grow_snake_event.after(food_contact_event))
                    .into()
            );

I get the error:

the trait `IntoSystem<(), (), _>` is not implemented for `SystemDescriptor`

631 |         S: AddConditionalToSet<ConditionSystemSet, P>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ConditionSystemSet::with_system`

Looks like it's because some trait bounds are missing?

Maybe i'm approaching things incorrectly and there's a different way to do this.

Panic: State Transition Stage not found (assuming auto-added label)

After upgrade from 0.7 to 0.8 I started to get the following error:

thread 'main' panicked at 'State Transition Stage not found (assuming auto-added label)', /home/indy/.cargo/registry/src/github.com-1ecc6299db9ec823/iyes_loopless-0.8.0/src/state.rs:343:25
stack backtrace:
   0: rust_begin_unwind
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/std/src/panicking.rs:584:5
   1: core::panicking::panic_fmt
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/panicking.rs:142:14
   2: core::panicking::panic_display
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/panicking.rs:72:5
   3: core::panicking::panic_str
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/panicking.rs:56:5
   4: core::option::expect_failed
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/option.rs:1880:5
   5: core::option::Option<T>::expect
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/option.rs:738:21
   6: <bevy_app::app::App as iyes_loopless::state::app::AppLooplessStateExt>::add_enter_system
             at /home/indy/.cargo/registry/src/github.com-1ecc6299db9ec823/iyes_loopless-0.8.0/src/state.rs:343:25
   7: <de_menu::mainmenu::MainMenuPlugin as bevy_app::plugin::Plugin>::build
             at ./crates/menu/src/mainmenu.rs:16:9
   8: bevy_app::plugin_group::PluginGroupBuilder::finish
             at /home/indy/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_app-0.8.1/src/plugin_group.rs:135:21
   9: bevy_app::app::App::add_plugins
             at /home/indy/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_app-0.8.1/src/app.rs:810:9
  10: de_game::main
             at ./src/main.rs:27:5
  11: core::ops::function::FnOnce::call_once
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/ops/function.rs:248:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Note that I do this in a plugin (which is executed first):

app.add_loopless_state(AppState::InMenu)
    .add_loopless_state(GameState::None);

and this in another plugin (which executes later):

app.add_enter_system(AppState::InMenu, setup)
    .add_exit_system(AppState::InMenu, cleanup)

Do not remove `NextState`

Actually ... the NextState resource doesn't have to keep being inserted/removed ... it can just be kept at all times. Just perform state transitions when its value is changed.

"State Transition not found" when adding an enter_system

I have a barebones StatePlugin that crashes whenever I try to add_enter_system(). I saw another opened issue mentioning that the API may have some issue with the Plugin architecture, so I tried moving the add_enter_system to main but did not work either.

this is the error I get:

thread 'main' panicked at 'State Transiton Stage not found (assuming auto-added label)', /{my_directory}/github.com-1ecc6299db9ec823/iyes_loopless-0.6.1/src/state.rs:306:18

Here's a snippet of my main.rs file

fn main() {
    let mut app = App::new();
    app.insert_resource(WindowDescriptor {
        // some not relevant code
    })
    .add_plugins(DefaultPlugins)
    .add_plugin(CameraPlugin)
    .add_plugin(StatePlugin)
    .add_plugin(UiPlugin)
    .add_plugin(GamePlugin);

    app.run();
}

and the StatePlugin file:

use bevy::prelude::*;
use iyes_loopless::prelude::*;

pub const STARTING_GAME_STATE: GameState = GameState::MainMenu;

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum GameState {
    MainMenu,
    Options,
    InGame,
}

pub struct StatePlugin;
impl Plugin for StatePlugin {
    fn build(&self, app: &mut App) {
        app
            .add_loopless_state(STARTING_GAME_STATE)
            .add_system(stage_key_bindings)
            .add_enter_system(&GameState::InGame, setup_game); // adding this line crashes the game
    }
}

// This works fine
fn stage_key_bindings(mut commands: Commands, kb_input: Res<Input<KeyCode>>) {
    if kb_input.just_pressed(KeyCode::Escape) {
        commands.insert_resource(NextState(GameState::MainMenu));
    }
}

// Mockup reset_game function when entering a new game
fn setup_game(mut commands: Commands) {
    dbg!("reset_game!");
    commands.insert_resource(NextState(GameState::InGame));
}

What am I doing wrong? Thanks!

ConditionSet systems without run_if conditions require into_conditional

I'm migrating a playground project to use this library and I have a set of systems that run using a fixed timer only during a state, previously using a SystemSet. The systems run in a certain order using labels, but they don't have conditionals on them.

app
    .add_system_set(
        ConditionSet::new()
            .after("FixedTimestep")
            .run_in_state(AppState::Playing)
            .with_system(snake_movement.label(SnakeMovement::Movement))
            .with_system(
                snake_eating
                    .label(SnakeMovement::Eating)
                    .after(SnakeMovement::Movement),
            )
            .with_system(
                snake_growth
                    .label(SnakeMovement::Growth)
                    .after(SnakeMovement::Eating),
            )
            .into(),
    )

It causes this error:

error[E0277]: the trait bound `ParallelSystemDescriptor: IntoSystem<(), (), _>` is not satisfied

error[E0277]: the trait bound `ParallelSystemDescriptor: IntoSystem<(), (), _>` is not satisfied
   --> src\main.rs:442:30
    |
442 |                 .with_system(snake_movement.label(SnakeMovement::Movement))
    |                  ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoSystem<(), (), _>` is not implemented for `ParallelSystemDescriptor`
    |                  |
    |                  required by a bound introduced by this call
    |
    = help: the trait `AddConditionalToSet` is implemented for `ConditionalSystemDescriptor`
    = note: required for `ParallelSystemDescriptor` to implement `iyes_loopless::condition::IntoConditionalSystem<_>`
    = note: required for `ParallelSystemDescriptor` to implement `AddConditionalToSet`
note: required by a bound in `iyes_loopless::condition::ConditionSet::with_system`
   --> C:\Users\osbornm\scoop\persist\rustup\.cargo\registry\src\github.com-1ecc6299db9ec823\iyes_loopless-0.7.1\src\condition.rs:652:12
    |
652 |         S: AddConditionalToSet,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `iyes_loopless::condition::ConditionSet::with_system`

For more information about this error, try rustc --explain E0277.

The solution I found is to add into_conditional() to each system:

app
    .add_system_set(
        ConditionSet::new()
            .after("FixedTimestep")
            .run_in_state(AppState::Playing)
            .with_system(
                snake_movement
                    .into_conditional()
                    .label(SnakeMovement::Movement)
            )
            .with_system(
                snake_eating
                    .into_conditional()
                    .label(SnakeMovement::Eating)
                    .after(SnakeMovement::Movement),
            )
            .with_system(
                snake_growth
                    .into_conditional()
                    .label(SnakeMovement::Growth)
                    .after(SnakeMovement::Eating),
            )
            .into(),
    )

But that seems kind of clunky and like it may be able to be fixed easily.

How to get the new methods on App

Hello

Some background first; Im pretty new to Rust and Bevy.

I've added iyes_loopless to my dependencies (0.3.0 as I use bevy 0.6 still).

However, when trying to use a method like .add_enter_system or add_loopless_state on the App::new() from Bevy I get this error from the compiler:
no method named add_enter_system found for mutable reference &mut bevy::prelude::App in the current scope

I've looked at your examples in this repository and I can't see anything specific I'm missing. My dependency is specified like this:
[dependencies.iyes_loopless] version = "0.3.0"
in my Cargo.toml

I did a cargo tree -f "{p} {f}" just to see if there was maybe something with the features, but this was the output:
├── iyes_loopless v0.3.0 bevy-compat,bevy_core,bevy_utils,default,fixedtimestep,states │ ├── bevy_core v0.6.0 (*) │ ├── bevy_ecs v0.6.1 bevy_reflect,default (*) │ └── bevy_utils v0.6.0 (*)

Am a bit lost now, would really like to try this way of doing it before just using the Bevy built-in way of doing it.

Support for Custom Command Queues? ( I have an Implementation )

Hey there!

For my game I implemented a custom command queue that can be used to flush certain sets of commands before the end of the frame. This is something that was mentioned in the Bevy stageless design, and I wasn't sure if it was something you might want to add to this crate.

I feel like it's a feature other people might want to use, and it'd be good to have in a crate, but I wasn't sure if a new crate would be warranted, or if it'd fit in here, because it's kind of a preview to the stageless bevy design.

Here's a gist with the implementation and usage example. It's really quite simple:

https://gist.github.com/zicklag/3446143d563657d54e292cc7e2c15378

Trait bounds not satisfied in main?

Using bevy main and the bevy_main branch together I get:

   |                 ------------------- this is a function, perhaps you wish to call it
35 |                     .run_on_event::<WindowResized>()
   |                      ^^^^^^^^^^^^ method cannot be called on `for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6> fn(bevy::prelude::Commands<'r, 's>, bevy::prelude::EventReader<'t0, 't1, WindowResized>, bevy::prelude::ResMut<'t2, bevy::prelude::Assets<bevy::prelude::Image>>, std::option::Option<bevy::prelude::Res<'t3, OutputImage>>, bevy::prelude::Query<'t4, 't5, &'t6 mut bevy::prelude::Sprite, bevy::prelude::With<output_image::RenderTarget>>) {resize_output_image}` due to unsatisfied trait bounds

The code causing this is fairly simple:

        app.add_plugin(ExtractResourcePlugin::<OutputImage>::default())
            .add_system(
                resize_output_image
                    .run_on_event::<WindowResized>()
                    .run_if_resource_exists::<OutputImage>(),
            )
            .add_system(
                create_output_image
                    .run_on_event::<WindowResized>()
                    .run_unless_resource_exists::<OutputImage>(),
            );
    }

Where I'm playing around with having different things happen if a particular resource already exists or not.

I'm relatively new to rust, so am not sure if I'm doing something wrong here.

Compile failure when default features are turned off

When trying to compile the crate without default features this error shows up.

  --> iyes_loopless/src/lib.rs:13:20
13 |     pub use crate::state::schedule::ScheduleLooplessStateExt;
   |                    ^^^^^ could not find `state` in the crate root

The #cfg(feature = "app") in lib.rs only applies to the first import. So the socond one gets included even if app isn't enabled.
Also the app feature should depend on the states feature because the crate also does not compile when only app is enabled.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.