Skip to content

Improve node encapsulation in ScheduleGraph #20119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 15, 2025

Conversation

ItsDoot
Copy link
Contributor

@ItsDoot ItsDoot commented Jul 13, 2025

Objective

We want to encapsulate each part of ScheduleGraph into its own specific struct to make parts of it easier to reuse and maintain.

Solution

  • Pulled ScheduleGraph::systems and ScheduleGraph::system_conditions into a Systems struct and added a field for this new struct to ScheduleGraph
  • Broke up ScheduleGraph::uninit into Systems::uninit and SystemSets::uninit to eliminate ScheduleGraph's direct field access of these types
  • Removed node and condition accessors from ScheduleGraph; the same operations are now available on Systems and SystemSets instead (accessible via their pub fields on ScheduleGraph)
  • Moved Systems, SystemSets, SystemNode, SystemWithAccess, and ConditionWithAccess into a separate file.

Testing

Added two new tests covering the API surface of Systems and SystemSets, respectively.

@ItsDoot ItsDoot added A-ECS Entities, components, systems, and events C-Code-Quality A section of code that is hard to understand or change C-Usability A targeted quality-of-life change that makes Bevy easier to use M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Jul 13, 2025
@ItsDoot ItsDoot requested a review from chescock July 13, 2025 23:08
Copy link
Contributor

@chescock chescock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is getting much easier to understand!

}
}

impl Deref for SystemWithAccess {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought using Deref like this for "inheritence" was discouraged, and it was only supposed to be used for smart pointers.

Copy link
Contributor Author

@ItsDoot ItsDoot Jul 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it to get rid of some system.system stutter, because for practically all intents and purposes a SystemWithAccess is a System. I'll leave this up to @alice-i-cecile

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah Bevy's style guide disagrees with that advice. There's a reason we offer our own derive macros for Deref/DerefMut.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The alternative I suppose is impl System for SystemWithAccess. I just want to avoid the stutter, really.

#[derive(Default)]
pub struct Systems {
/// List of systems in the schedule.
nodes: SlotMap<SystemKey, SystemNode>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this would be more clear just storing Option<SystemWithNode> instead of using the SystemNode wrapper.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noticed this was done in a previous pr. Feel free to ignore this then.

Copy link
Contributor Author

@ItsDoot ItsDoot Jul 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SystemNode will disappear entirely in my next PR (System Arcinization), so it shouldn't be staying around too much longer anyways.

Co-authored-by: Chris Russell <[email protected]>
@ItsDoot ItsDoot added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Jul 14, 2025
Copy link
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy enough with this :) Yay for smaller files too.

@alice-i-cecile
Copy link
Member

alice-i-cecile commented Jul 14, 2025

The alternative I suppose is impl System for SystemWithAccess. I just want to avoid the stutter, really.

@ItsDoot I actually really like this idea. It's type-erased so it's not going to explode codegen. Are you willing to do that now?

@chescock
Copy link
Contributor

The alternative I suppose is impl System for SystemWithAccess. I just want to avoid the stutter, really.

Another option here is to move the access to a separate storage, like another SecondaryMap. We need to store them for the multi-threaded executor, or if the ambiguity checker is on. But if we're running single-threaded and the detector is off them we could drop them to save space, just like we do with observers and registered systems. That might be easier if they're not part of the same structure.

Either way, thank you for cleaning up the mess I made when I stuck the access there :).

@ItsDoot
Copy link
Contributor Author

ItsDoot commented Jul 15, 2025

@ItsDoot I actually really like this idea. It's type-erased so it's not going to explode codegen. Are you willing to do that now?

Done!

Another option here is to move the access to a separate storage, like another SecondaryMap. We need to store them for the multi-threaded executor, or if the ambiguity checker is on. But if we're running single-threaded and the detector is off them we could drop them to save space, just like we do with observers and registered systems. That might be easier if they're not part of the same structure.

Either way, thank you for cleaning up the mess I made when I stuck the access there :).

I quite like this idea, but I'll hold off on it at least until my next PR since those are likely to have similar blast-radii.

@alice-i-cecile alice-i-cecile added this pull request to the merge queue Jul 15, 2025
Merged via the queue into bevyengine:main with commit 2be3bc5 Jul 15, 2025
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Code-Quality A section of code that is hard to understand or change C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants