 dc3f801239
			
		
	
	
		dc3f801239
		
	
	
	
	
		
			
			# Objective The [Stageless RFC](https://github.com/bevyengine/rfcs/pull/45) involves allowing exclusive systems to be referenced and ordered relative to parallel systems. We've agreed that unifying systems under `System` is the right move. This is an alternative to #4166 (see rationale in the comments I left there). Note that this builds on the learnings established there (and borrows some patterns). ## Solution This unifies parallel and exclusive systems under the shared `System` trait, removing the old `ExclusiveSystem` trait / impls. This is accomplished by adding a new `ExclusiveFunctionSystem` impl similar to `FunctionSystem`. It is backed by `ExclusiveSystemParam`, which is similar to `SystemParam`. There is a new flattened out SystemContainer api (which cuts out a lot of trait and type complexity). This means you can remove all cases of `exclusive_system()`: ```rust // before commands.add_system(some_system.exclusive_system()); // after commands.add_system(some_system); ``` I've also implemented `ExclusiveSystemParam` for `&mut QueryState` and `&mut SystemState`, which makes this possible in exclusive systems: ```rust fn some_exclusive_system( world: &mut World, transforms: &mut QueryState<&Transform>, state: &mut SystemState<(Res<Time>, Query<&Player>)>, ) { for transform in transforms.iter(world) { println!("{transform:?}"); } let (time, players) = state.get(world); for player in players.iter() { println!("{player:?}"); } } ``` Note that "exclusive function systems" assume `&mut World` is present (and the first param). I think this is a fair assumption, given that the presence of `&mut World` is what defines the need for an exclusive system. I added some targeted SystemParam `static` constraints, which removed the need for this: ``` rust fn some_exclusive_system(state: &mut SystemState<(Res<'static, Time>, Query<&'static Player>)>) {} ``` ## Related - #2923 - #3001 - #3946 ## Changelog - `ExclusiveSystem` trait (and implementations) has been removed in favor of sharing the `System` trait. - `ExclusiveFunctionSystem` and `ExclusiveSystemParam` were added, enabling flexible exclusive function systems - `&mut SystemState` and `&mut QueryState` now implement `ExclusiveSystemParam` - Exclusive and parallel System configuration is now done via a unified `SystemDescriptor`, `IntoSystemDescriptor`, and `SystemContainer` api. ## Migration Guide Calling `.exclusive_system()` is no longer required (or supported) for converting exclusive system functions to exclusive systems: ```rust // Old (0.8) app.add_system(some_exclusive_system.exclusive_system()); // New (0.9) app.add_system(some_exclusive_system); ``` Converting "normal" parallel systems to exclusive systems is done by calling the exclusive ordering apis: ```rust // Old (0.8) app.add_system(some_system.exclusive_system().at_end()); // New (0.9) app.add_system(some_system.at_end()); ``` Query state in exclusive systems can now be cached via ExclusiveSystemParams, which should be preferred for clarity and performance reasons: ```rust // Old (0.8) fn some_system(world: &mut World) { let mut transforms = world.query::<&Transform>(); for transform in transforms.iter(world) { } } // New (0.9) fn some_system(world: &mut World, transforms: &mut QueryState<&Transform>) { for transform in transforms.iter(world) { } } ```
		
			
				
	
	
		
			86 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| mod error;
 | |
| mod font;
 | |
| mod font_atlas;
 | |
| mod font_atlas_set;
 | |
| mod font_loader;
 | |
| mod glyph_brush;
 | |
| mod pipeline;
 | |
| mod text;
 | |
| mod text2d;
 | |
| 
 | |
| pub use error::*;
 | |
| pub use font::*;
 | |
| pub use font_atlas::*;
 | |
| pub use font_atlas_set::*;
 | |
| pub use font_loader::*;
 | |
| pub use glyph_brush::*;
 | |
| pub use pipeline::*;
 | |
| pub use text::*;
 | |
| pub use text2d::*;
 | |
| 
 | |
| pub mod prelude {
 | |
|     #[doc(hidden)]
 | |
|     pub use crate::{
 | |
|         Font, HorizontalAlign, Text, Text2dBundle, TextAlignment, TextError, TextSection,
 | |
|         TextStyle, VerticalAlign,
 | |
|     };
 | |
| }
 | |
| 
 | |
| use bevy_app::prelude::*;
 | |
| use bevy_asset::AddAsset;
 | |
| use bevy_ecs::{schedule::IntoSystemDescriptor, system::Resource};
 | |
| use bevy_render::{RenderApp, RenderStage};
 | |
| use bevy_sprite::SpriteSystem;
 | |
| use bevy_window::ModifiesWindows;
 | |
| use std::num::NonZeroUsize;
 | |
| 
 | |
| #[derive(Default)]
 | |
| pub struct TextPlugin;
 | |
| 
 | |
| /// [`TextPlugin`] settings
 | |
| #[derive(Resource)]
 | |
| pub struct TextSettings {
 | |
|     /// Maximum number of font atlases supported in a ['FontAtlasSet']
 | |
|     pub max_font_atlases: NonZeroUsize,
 | |
|     /// Allows font size to be set dynamically exceeding the amount set in max_font_atlases.
 | |
|     /// Note each font size has to be generated which can have a strong performance impact.
 | |
|     pub allow_dynamic_font_size: bool,
 | |
| }
 | |
| 
 | |
| impl Default for TextSettings {
 | |
|     fn default() -> Self {
 | |
|         Self {
 | |
|             max_font_atlases: NonZeroUsize::new(16).unwrap(),
 | |
|             allow_dynamic_font_size: false,
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl Plugin for TextPlugin {
 | |
|     fn build(&self, app: &mut App) {
 | |
|         app.add_asset::<Font>()
 | |
|             .add_asset::<FontAtlasSet>()
 | |
|             .register_type::<Text>()
 | |
|             .register_type::<TextSection>()
 | |
|             .register_type::<Vec<TextSection>>()
 | |
|             .register_type::<TextStyle>()
 | |
|             .register_type::<TextAlignment>()
 | |
|             .register_type::<VerticalAlign>()
 | |
|             .register_type::<HorizontalAlign>()
 | |
|             .init_asset_loader::<FontLoader>()
 | |
|             .init_resource::<TextSettings>()
 | |
|             .insert_resource(TextPipeline::default())
 | |
|             .add_system_to_stage(
 | |
|                 CoreStage::PostUpdate,
 | |
|                 update_text2d_layout.after(ModifiesWindows),
 | |
|             );
 | |
| 
 | |
|         if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
 | |
|             render_app.add_system_to_stage(
 | |
|                 RenderStage::Extract,
 | |
|                 extract_text2d_sprite.after(SpriteSystem::ExtractSprites),
 | |
|             );
 | |
|         }
 | |
|     }
 | |
| }
 |