Implement Sub-App Labels (#2695)

This is a rather simple but wide change, and it involves adding a new `bevy_app_macros` crate. Let me know if there is a better way to do any of this!

---

# Objective

- Allow adding and accessing sub-apps by using a label instead of an index

## Solution

- Migrate the bevy label implementation and derive code to the `bevy_utils` and `bevy_macro_utils` crates and then add a new `SubAppLabel` trait to the `bevy_app` crate that is used when adding or getting a sub-app from an app.
This commit is contained in:
Zicklag 2021-08-24 00:31:21 +00:00
parent c3d3ae7f92
commit e290a7e29c
21 changed files with 244 additions and 168 deletions

View file

@ -23,6 +23,7 @@ bevy_derive = { path = "../bevy_derive", version = "0.5.0" }
bevy_ecs = { path = "../bevy_ecs", version = "0.5.0" } bevy_ecs = { path = "../bevy_ecs", version = "0.5.0" }
bevy_reflect = { path = "../bevy_reflect", version = "0.5.0", optional = true } bevy_reflect = { path = "../bevy_reflect", version = "0.5.0", optional = true }
bevy_utils = { path = "../bevy_utils", version = "0.5.0" } bevy_utils = { path = "../bevy_utils", version = "0.5.0" }
bevy_app_macros = { path = "./macros", version = "0.5.0" }
# other # other
serde = { version = "1.0", features = ["derive"], optional = true } serde = { version = "1.0", features = ["derive"], optional = true }

View file

@ -0,0 +1,16 @@
[package]
name = "bevy_app_macros"
version = "0.5.0"
description = "Bevy App Macros"
edition = "2018"
license = "MIT OR Apache-2.0"
[lib]
proc-macro = true
[dependencies]
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.5.0" }
syn = "1.0"
quote = "1.0"
proc-macro2 = "1.0"

View file

@ -0,0 +1,19 @@
extern crate proc_macro;
use bevy_macro_utils::{derive_label, BevyManifest};
use proc_macro::TokenStream;
use quote::format_ident;
#[proc_macro_derive(SubAppLabel)]
pub fn derive_sub_app_label(input: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(input as syn::DeriveInput);
let mut trait_path = bevy_app_path();
trait_path
.segments
.push(format_ident!("SubAppLabel").into());
derive_label(input, trait_path)
}
fn bevy_app_path() -> syn::Path {
BevyManifest::default().get_path("bevy_app")
}

View file

@ -7,12 +7,17 @@ use bevy_ecs::{
}, },
world::World, world::World,
}; };
use bevy_utils::tracing::debug; use bevy_utils::{tracing::debug, HashMap};
use std::{fmt::Debug, hash::Hash}; use std::{fmt::Debug, hash::Hash};
pub use bevy_app_macros::SubAppLabel;
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
use bevy_utils::tracing::info_span; use bevy_utils::tracing::info_span;
bevy_utils::define_label!(SubAppLabel);
type BoxedSubAppLabel = Box<dyn SubAppLabel>;
#[allow(clippy::needless_doctest_main)] #[allow(clippy::needless_doctest_main)]
/// Containers of app logic and data /// Containers of app logic and data
/// ///
@ -40,7 +45,7 @@ pub struct App {
pub world: World, pub world: World,
pub runner: Box<dyn Fn(App)>, pub runner: Box<dyn Fn(App)>,
pub schedule: Schedule, pub schedule: Schedule,
sub_apps: Vec<SubApp>, sub_apps: HashMap<BoxedSubAppLabel, SubApp>,
} }
struct SubApp { struct SubApp {
@ -77,7 +82,7 @@ impl App {
world: Default::default(), world: Default::default(),
schedule: Default::default(), schedule: Default::default(),
runner: Box::new(run_once), runner: Box::new(run_once),
sub_apps: Vec::new(), sub_apps: HashMap::default(),
} }
} }
@ -87,7 +92,7 @@ impl App {
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
let _bevy_frame_update_guard = bevy_frame_update_span.enter(); let _bevy_frame_update_guard = bevy_frame_update_span.enter();
self.schedule.run(&mut self.world); self.schedule.run(&mut self.world);
for sub_app in self.sub_apps.iter_mut() { for sub_app in self.sub_apps.values_mut() {
(sub_app.runner)(&mut self.world, &mut sub_app.app); (sub_app.runner)(&mut self.world, &mut sub_app.app);
} }
} }
@ -589,19 +594,25 @@ impl App {
pub fn add_sub_app( pub fn add_sub_app(
&mut self, &mut self,
label: impl SubAppLabel,
app: App, app: App,
f: impl Fn(&mut World, &mut App) + 'static, f: impl Fn(&mut World, &mut App) + 'static,
) -> &mut Self { ) -> &mut Self {
self.sub_apps.push(SubApp { self.sub_apps.insert(
app, Box::new(label),
runner: Box::new(f), SubApp {
}); app,
runner: Box::new(f),
},
);
self self
} }
// TODO: use labels instead of indices pub fn sub_app_mut(&mut self, label: impl SubAppLabel) -> Option<&mut App> {
pub fn sub_app_mut(&mut self, index: usize) -> &mut App { let label = Box::new(label) as BoxedSubAppLabel;
&mut self.sub_apps[index].app self.sub_apps
.get_mut(&label)
.map(|sub_app| &mut sub_app.app)
} }
} }

View file

@ -2,10 +2,6 @@
name = "bevy_ecs_macros" name = "bevy_ecs_macros"
version = "0.5.0" version = "0.5.0"
description = "Bevy ECS Macros" description = "Bevy ECS Macros"
authors = [
"Bevy Contributors <bevyengine@gmail.com>",
"Carter Anderson <mcanders1@gmail.com>",
]
edition = "2018" edition = "2018"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"

View file

@ -1,8 +1,8 @@
extern crate proc_macro; extern crate proc_macro;
use bevy_macro_utils::BevyManifest; use bevy_macro_utils::{derive_label, BevyManifest};
use proc_macro::TokenStream; use proc_macro::TokenStream;
use proc_macro2::{Span, TokenStream as TokenStream2}; use proc_macro2::Span;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
use syn::{ use syn::{
parse::{Parse, ParseStream}, parse::{Parse, ParseStream},
@ -10,7 +10,7 @@ use syn::{
punctuated::Punctuated, punctuated::Punctuated,
token::Comma, token::Comma,
Data, DataStruct, DeriveInput, Field, Fields, GenericParam, Ident, Index, Lifetime, LitInt, Data, DataStruct, DeriveInput, Field, Fields, GenericParam, Ident, Index, Lifetime, LitInt,
Path, Result, Token, Result, Token,
}; };
struct AllTuples { struct AllTuples {
@ -436,46 +436,43 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
#[proc_macro_derive(SystemLabel)] #[proc_macro_derive(SystemLabel)]
pub fn derive_system_label(input: TokenStream) -> TokenStream { pub fn derive_system_label(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput); let input = parse_macro_input!(input as DeriveInput);
let mut trait_path = bevy_ecs_path();
derive_label(input, Ident::new("SystemLabel", Span::call_site())).into() trait_path.segments.push(format_ident!("schedule").into());
trait_path
.segments
.push(format_ident!("SystemLabel").into());
derive_label(input, trait_path)
} }
#[proc_macro_derive(StageLabel)] #[proc_macro_derive(StageLabel)]
pub fn derive_stage_label(input: TokenStream) -> TokenStream { pub fn derive_stage_label(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput); let input = parse_macro_input!(input as DeriveInput);
derive_label(input, Ident::new("StageLabel", Span::call_site())).into() let mut trait_path = bevy_ecs_path();
trait_path.segments.push(format_ident!("schedule").into());
trait_path.segments.push(format_ident!("StageLabel").into());
derive_label(input, trait_path)
} }
#[proc_macro_derive(AmbiguitySetLabel)] #[proc_macro_derive(AmbiguitySetLabel)]
pub fn derive_ambiguity_set_label(input: TokenStream) -> TokenStream { pub fn derive_ambiguity_set_label(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput); let input = parse_macro_input!(input as DeriveInput);
derive_label(input, Ident::new("AmbiguitySetLabel", Span::call_site())).into() let mut trait_path = bevy_ecs_path();
trait_path.segments.push(format_ident!("schedule").into());
trait_path
.segments
.push(format_ident!("AmbiguitySetLabel").into());
derive_label(input, trait_path)
} }
#[proc_macro_derive(RunCriteriaLabel)] #[proc_macro_derive(RunCriteriaLabel)]
pub fn derive_run_criteria_label(input: TokenStream) -> TokenStream { pub fn derive_run_criteria_label(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput); let input = parse_macro_input!(input as DeriveInput);
derive_label(input, Ident::new("RunCriteriaLabel", Span::call_site())).into() let mut trait_path = bevy_ecs_path();
} trait_path.segments.push(format_ident!("schedule").into());
trait_path
fn derive_label(input: DeriveInput, label_type: Ident) -> TokenStream2 { .segments
let ident = input.ident; .push(format_ident!("RunCriteriaLabel").into());
let ecs_path: Path = bevy_ecs_path(); derive_label(input, trait_path)
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let mut where_clause = where_clause.cloned().unwrap_or_else(|| syn::WhereClause {
where_token: Default::default(),
predicates: Default::default(),
});
where_clause.predicates.push(syn::parse2(quote! { Self: Eq + ::std::fmt::Debug + ::std::hash::Hash + Clone + Send + Sync + 'static }).unwrap());
quote! {
impl #impl_generics #ecs_path::schedule::#label_type for #ident #ty_generics #where_clause {
fn dyn_clone(&self) -> Box<dyn #ecs_path::schedule::#label_type> {
Box::new(Clone::clone(self))
}
}
}
} }
fn bevy_ecs_path() -> syn::Path { fn bevy_ecs_path() -> syn::Path {

View file

@ -1,115 +1,15 @@
pub use bevy_ecs_macros::{AmbiguitySetLabel, RunCriteriaLabel, StageLabel, SystemLabel}; pub use bevy_ecs_macros::{AmbiguitySetLabel, RunCriteriaLabel, StageLabel, SystemLabel};
use std::{ use bevy_utils::define_label;
any::Any,
borrow::Cow,
fmt::Debug,
hash::{Hash, Hasher},
};
pub trait DynEq: Any { define_label!(StageLabel);
fn as_any(&self) -> &dyn Any;
fn dyn_eq(&self, other: &dyn DynEq) -> bool;
}
impl<T> DynEq for T
where
T: Any + Eq,
{
fn as_any(&self) -> &dyn Any {
self
}
fn dyn_eq(&self, other: &dyn DynEq) -> bool {
if let Some(other) = other.as_any().downcast_ref::<T>() {
return self == other;
}
false
}
}
pub trait DynHash: DynEq {
fn as_dyn_eq(&self) -> &dyn DynEq;
fn dyn_hash(&self, state: &mut dyn Hasher);
}
impl<T> DynHash for T
where
T: DynEq + Hash,
{
fn as_dyn_eq(&self) -> &dyn DynEq {
self
}
fn dyn_hash(&self, mut state: &mut dyn Hasher) {
T::hash(self, &mut state);
self.type_id().hash(&mut state);
}
}
pub trait StageLabel: DynHash + Debug + Send + Sync + 'static {
#[doc(hidden)]
fn dyn_clone(&self) -> Box<dyn StageLabel>;
}
pub(crate) type BoxedStageLabel = Box<dyn StageLabel>; pub(crate) type BoxedStageLabel = Box<dyn StageLabel>;
pub trait SystemLabel: DynHash + Debug + Send + Sync + 'static { define_label!(SystemLabel);
#[doc(hidden)]
fn dyn_clone(&self) -> Box<dyn SystemLabel>;
}
pub(crate) type BoxedSystemLabel = Box<dyn SystemLabel>; pub(crate) type BoxedSystemLabel = Box<dyn SystemLabel>;
pub trait AmbiguitySetLabel: DynHash + Debug + Send + Sync + 'static { define_label!(AmbiguitySetLabel);
#[doc(hidden)]
fn dyn_clone(&self) -> Box<dyn AmbiguitySetLabel>;
}
pub(crate) type BoxedAmbiguitySetLabel = Box<dyn AmbiguitySetLabel>; pub(crate) type BoxedAmbiguitySetLabel = Box<dyn AmbiguitySetLabel>;
pub trait RunCriteriaLabel: DynHash + Debug + Send + Sync + 'static { define_label!(RunCriteriaLabel);
#[doc(hidden)]
fn dyn_clone(&self) -> Box<dyn RunCriteriaLabel>;
}
pub(crate) type BoxedRunCriteriaLabel = Box<dyn RunCriteriaLabel>; pub(crate) type BoxedRunCriteriaLabel = Box<dyn RunCriteriaLabel>;
macro_rules! impl_label {
($trait_name:ident) => {
impl PartialEq for dyn $trait_name {
fn eq(&self, other: &Self) -> bool {
self.dyn_eq(other.as_dyn_eq())
}
}
impl Eq for dyn $trait_name {}
impl Hash for dyn $trait_name {
fn hash<H: Hasher>(&self, state: &mut H) {
self.dyn_hash(state);
}
}
impl Clone for Box<dyn $trait_name> {
fn clone(&self) -> Self {
self.dyn_clone()
}
}
impl $trait_name for Cow<'static, str> {
fn dyn_clone(&self) -> Box<dyn $trait_name> {
Box::new(self.clone())
}
}
impl $trait_name for &'static str {
fn dyn_clone(&self) -> Box<dyn $trait_name> {
Box::new(<&str>::clone(self))
}
}
};
}
impl_label!(StageLabel);
impl_label!(SystemLabel);
impl_label!(AmbiguitySetLabel);
impl_label!(RunCriteriaLabel);

View file

@ -15,3 +15,4 @@ keywords = ["bevy"]
[dependencies] [dependencies]
cargo-manifest = "0.2.3" cargo-manifest = "0.2.3"
syn = "1.0" syn = "1.0"
quote = "1.0"

View file

@ -2,6 +2,7 @@ extern crate proc_macro;
use cargo_manifest::{DepsSet, Manifest}; use cargo_manifest::{DepsSet, Manifest};
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::quote;
use std::{env, path::PathBuf}; use std::{env, path::PathBuf};
pub struct BevyManifest { pub struct BevyManifest {
@ -59,3 +60,29 @@ fn get_path(path: &str) -> syn::Path {
fn parse_str<T: syn::parse::Parse>(path: &str) -> T { fn parse_str<T: syn::parse::Parse>(path: &str) -> T {
syn::parse(path.parse::<TokenStream>().unwrap()).unwrap() syn::parse(path.parse::<TokenStream>().unwrap()).unwrap()
} }
/// Derive a label trait
///
/// # Args
///
/// - `input`: The [`syn::DeriveInput`] for struct that is deriving the label trait
/// - `trait_path`: The path [`syn::Path`] to the label trait
pub fn derive_label(input: syn::DeriveInput, trait_path: syn::Path) -> TokenStream {
let ident = input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let mut where_clause = where_clause.cloned().unwrap_or_else(|| syn::WhereClause {
where_token: Default::default(),
predicates: Default::default(),
});
where_clause.predicates.push(syn::parse2(quote! { Self: Eq + ::std::fmt::Debug + ::std::hash::Hash + Clone + Send + Sync + 'static }).unwrap());
(quote! {
impl #impl_generics #trait_path for #ident #ty_generics #where_clause {
fn dyn_clone(&self) -> Box<dyn #trait_path> {
Box::new(Clone::clone(self))
}
}
})
.into()
}

View file

@ -0,0 +1,100 @@
//! Traits used by label implementations
use std::{
any::Any,
hash::{Hash, Hasher},
};
pub trait DynEq: Any {
fn as_any(&self) -> &dyn Any;
fn dyn_eq(&self, other: &dyn DynEq) -> bool;
}
impl<T> DynEq for T
where
T: Any + Eq,
{
fn as_any(&self) -> &dyn Any {
self
}
fn dyn_eq(&self, other: &dyn DynEq) -> bool {
if let Some(other) = other.as_any().downcast_ref::<T>() {
return self == other;
}
false
}
}
pub trait DynHash: DynEq {
fn as_dyn_eq(&self) -> &dyn DynEq;
fn dyn_hash(&self, state: &mut dyn Hasher);
}
impl<T> DynHash for T
where
T: DynEq + Hash,
{
fn as_dyn_eq(&self) -> &dyn DynEq {
self
}
fn dyn_hash(&self, mut state: &mut dyn Hasher) {
T::hash(self, &mut state);
self.type_id().hash(&mut state);
}
}
/// Macro to define a new label trait
///
/// # Example
///
/// ```
/// # use bevy_utils::define_label;
/// define_label!(MyNewLabelTrait);
/// ```
#[macro_export]
macro_rules! define_label {
($label_trait_name:ident) => {
pub trait $label_trait_name:
::bevy_utils::label::DynHash + ::std::fmt::Debug + Send + Sync + 'static
{
#[doc(hidden)]
fn dyn_clone(&self) -> Box<dyn $label_trait_name>;
}
impl PartialEq for dyn $label_trait_name {
fn eq(&self, other: &Self) -> bool {
self.dyn_eq(other.as_dyn_eq())
}
}
impl Eq for dyn $label_trait_name {}
impl ::std::hash::Hash for dyn $label_trait_name {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
self.dyn_hash(state);
}
}
impl Clone for Box<dyn $label_trait_name> {
fn clone(&self) -> Self {
self.dyn_clone()
}
}
impl $label_trait_name for ::std::borrow::Cow<'static, str> {
fn dyn_clone(&self) -> Box<dyn $label_trait_name> {
Box::new(self.clone())
}
}
impl $label_trait_name for &'static str {
fn dyn_clone(&self) -> Box<dyn $label_trait_name> {
Box::new(<&str>::clone(self))
}
}
};
}

View file

@ -1,4 +1,5 @@
mod enum_variant_meta; mod enum_variant_meta;
pub mod label;
pub mod slab; pub mod slab;
pub use ahash::AHasher; pub use ahash::AHasher;

View file

@ -20,7 +20,7 @@ use bevy_render2::{
renderer::RenderDevice, renderer::RenderDevice,
texture::TextureCache, texture::TextureCache,
view::{ExtractedView, ViewPlugin}, view::{ExtractedView, ViewPlugin},
RenderStage, RenderWorld, RenderStage, RenderSubApp, RenderWorld,
}; };
/// Resource that configures the clear color /// Resource that configures the clear color
@ -74,7 +74,7 @@ impl Plugin for CorePipelinePlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.init_resource::<ClearColor>(); app.init_resource::<ClearColor>();
let render_app = app.sub_app_mut(0); let render_app = app.sub_app_mut(RenderSubApp).unwrap();
render_app render_app
.add_system_to_stage(RenderStage::Extract, extract_clear_color) .add_system_to_stage(RenderStage::Extract, extract_clear_color)
.add_system_to_stage(RenderStage::Extract, extract_core_pipeline_camera_phases) .add_system_to_stage(RenderStage::Extract, extract_core_pipeline_camera_phases)

View file

@ -13,7 +13,7 @@ use bevy_ecs::prelude::*;
use bevy_render2::{ use bevy_render2::{
render_graph::RenderGraph, render_graph::RenderGraph,
render_phase::{sort_phase_system, DrawFunctions}, render_phase::{sort_phase_system, DrawFunctions},
RenderStage, RenderStage, RenderSubApp,
}; };
pub mod draw_3d_graph { pub mod draw_3d_graph {
@ -30,7 +30,7 @@ impl Plugin for PbrPlugin {
app.add_plugin(StandardMaterialPlugin) app.add_plugin(StandardMaterialPlugin)
.init_resource::<AmbientLight>(); .init_resource::<AmbientLight>();
let render_app = app.sub_app_mut(0); let render_app = app.sub_app_mut(RenderSubApp).unwrap();
render_app render_app
.add_system_to_stage(RenderStage::Extract, render::extract_meshes) .add_system_to_stage(RenderStage::Extract, render::extract_meshes)
.add_system_to_stage(RenderStage::Extract, render::extract_lights) .add_system_to_stage(RenderStage::Extract, render::extract_lights)

View file

@ -12,7 +12,7 @@ pub use bundle::*;
pub use camera::*; pub use camera::*;
pub use projection::*; pub use projection::*;
use crate::{view::ExtractedView, RenderStage}; use crate::{view::ExtractedView, RenderStage, RenderSubApp};
use bevy_app::{App, CoreStage, Plugin}; use bevy_app::{App, CoreStage, Plugin};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
@ -40,7 +40,7 @@ impl Plugin for CameraPlugin {
CoreStage::PostUpdate, CoreStage::PostUpdate,
crate::camera::camera_system::<PerspectiveProjection>, crate::camera::camera_system::<PerspectiveProjection>,
); );
let render_app = app.sub_app_mut(0); let render_app = app.sub_app_mut(RenderSubApp).unwrap();
render_app render_app
.init_resource::<ExtractedCameraNames>() .init_resource::<ExtractedCameraNames>()
.add_system_to_stage(RenderStage::Extract, extract_cameras); .add_system_to_stage(RenderStage::Extract, extract_cameras);

View file

@ -24,7 +24,7 @@ use crate::{
texture::ImagePlugin, texture::ImagePlugin,
view::{ViewPlugin, WindowRenderPlugin}, view::{ViewPlugin, WindowRenderPlugin},
}; };
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin, SubAppLabel};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
#[derive(Default)] #[derive(Default)]
@ -73,6 +73,10 @@ impl DerefMut for RenderWorld {
} }
} }
/// Label for the rendering sub-app
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, SubAppLabel)]
pub struct RenderSubApp;
/// A "scratch" world used to avoid allocating new worlds every frame when /// A "scratch" world used to avoid allocating new worlds every frame when
// swapping out the Render World. // swapping out the Render World.
#[derive(Default)] #[derive(Default)]
@ -114,7 +118,7 @@ impl Plugin for RenderPlugin {
.init_resource::<RenderGraph>() .init_resource::<RenderGraph>()
.init_resource::<DrawFunctions>(); .init_resource::<DrawFunctions>();
app.add_sub_app(render_app, move |app_world, render_app| { app.add_sub_app(RenderSubApp, render_app, move |app_world, render_app| {
// reserve all existing app entities for use in render_app // reserve all existing app entities for use in render_app
// they can only be spawned using `get_or_spawn()` // they can only be spawned using `get_or_spawn()`
let meta_len = app_world.entities().meta.len(); let meta_len = app_world.entities().meta.len();

View file

@ -2,7 +2,7 @@ use std::marker::PhantomData;
use crate::{ use crate::{
renderer::{RenderDevice, RenderQueue}, renderer::{RenderDevice, RenderQueue},
RenderStage, RenderStage, RenderSubApp,
}; };
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_asset::{Asset, AssetEvent, Assets, Handle}; use bevy_asset::{Asset, AssetEvent, Assets, Handle};
@ -31,7 +31,7 @@ impl<A: RenderAsset> Default for RenderAssetPlugin<A> {
impl<A: RenderAsset> Plugin for RenderAssetPlugin<A> { impl<A: RenderAsset> Plugin for RenderAssetPlugin<A> {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
let render_app = app.sub_app_mut(0); let render_app = app.sub_app_mut(RenderSubApp).unwrap();
render_app render_app
.init_resource::<ExtractedAssets<A>>() .init_resource::<ExtractedAssets<A>>()
.init_resource::<RenderAssets<A>>() .init_resource::<RenderAssets<A>>()

View file

@ -13,7 +13,7 @@ pub use hdr_texture_loader::*;
pub use image_texture_loader::*; pub use image_texture_loader::*;
pub use texture_cache::*; pub use texture_cache::*;
use crate::{render_asset::RenderAssetPlugin, RenderStage}; use crate::{render_asset::RenderAssetPlugin, RenderStage, RenderSubApp};
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_asset::AddAsset; use bevy_asset::AddAsset;
@ -30,7 +30,7 @@ impl Plugin for ImagePlugin {
app.add_plugin(RenderAssetPlugin::<Image>::default()) app.add_plugin(RenderAssetPlugin::<Image>::default())
.add_asset::<Image>(); .add_asset::<Image>();
let render_app = app.sub_app_mut(0); let render_app = app.sub_app_mut(RenderSubApp).unwrap();
render_app render_app
.init_resource::<TextureCache>() .init_resource::<TextureCache>()
.add_system_to_stage(RenderStage::Cleanup, update_texture_cache_system); .add_system_to_stage(RenderStage::Cleanup, update_texture_cache_system);

View file

@ -7,7 +7,7 @@ use crate::{
render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext}, render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext},
render_resource::DynamicUniformVec, render_resource::DynamicUniformVec,
renderer::{RenderContext, RenderDevice}, renderer::{RenderContext, RenderDevice},
RenderStage, RenderStage, RenderSubApp,
}; };
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
@ -22,7 +22,7 @@ impl ViewPlugin {
impl Plugin for ViewPlugin { impl Plugin for ViewPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
let render_app = app.sub_app_mut(0); let render_app = app.sub_app_mut(RenderSubApp).unwrap();
render_app render_app
.init_resource::<ViewMeta>() .init_resource::<ViewMeta>()
.add_system_to_stage(RenderStage::Prepare, prepare_views); .add_system_to_stage(RenderStage::Prepare, prepare_views);

View file

@ -2,7 +2,7 @@ use crate::{
render_resource::TextureView, render_resource::TextureView,
renderer::{RenderDevice, RenderInstance}, renderer::{RenderDevice, RenderInstance},
texture::BevyDefault, texture::BevyDefault,
RenderStage, RenderStage, RenderSubApp,
}; };
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
@ -19,7 +19,7 @@ pub struct WindowRenderPlugin;
impl Plugin for WindowRenderPlugin { impl Plugin for WindowRenderPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
let render_app = app.sub_app_mut(0); let render_app = app.sub_app_mut(RenderSubApp).unwrap();
render_app render_app
.init_resource::<WindowSurfaces>() .init_resource::<WindowSurfaces>()
.init_resource::<NonSendMarker>() .init_resource::<NonSendMarker>()

View file

@ -16,7 +16,9 @@ pub use texture_atlas::*;
pub use texture_atlas_builder::*; pub use texture_atlas_builder::*;
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_render2::{render_graph::RenderGraph, render_phase::DrawFunctions, RenderStage}; use bevy_render2::{
render_graph::RenderGraph, render_phase::DrawFunctions, RenderStage, RenderSubApp,
};
#[derive(Default)] #[derive(Default)]
pub struct SpritePlugin; pub struct SpritePlugin;
@ -26,7 +28,7 @@ impl Plugin for SpritePlugin {
app.add_asset::<TextureAtlas>() app.add_asset::<TextureAtlas>()
.register_type::<Sprite>() .register_type::<Sprite>()
.add_system_to_stage(CoreStage::PostUpdate, sprite_auto_resize_system); .add_system_to_stage(CoreStage::PostUpdate, sprite_auto_resize_system);
let render_app = app.sub_app_mut(0); let render_app = app.sub_app_mut(RenderSubApp).unwrap();
render_app render_app
.init_resource::<ExtractedSprites>() .init_resource::<ExtractedSprites>()
.add_system_to_stage(RenderStage::Extract, render::extract_atlases) .add_system_to_stage(RenderStage::Extract, render::extract_atlases)
@ -42,7 +44,7 @@ impl Plugin for SpritePlugin {
.unwrap() .unwrap()
.write() .write()
.add(draw_sprite); .add(draw_sprite);
let render_world = app.sub_app_mut(0).world.cell(); let render_world = app.sub_app_mut(RenderSubApp).unwrap().world.cell();
let mut graph = render_world.get_resource_mut::<RenderGraph>().unwrap(); let mut graph = render_world.get_resource_mut::<RenderGraph>().unwrap();
graph.add_node("sprite", SpriteNode); graph.add_node("sprite", SpriteNode);
graph graph

View file

@ -7,6 +7,7 @@ crates=(
bevy_tasks bevy_tasks
bevy_ecs/macros bevy_ecs/macros
bevy_ecs bevy_ecs
bevy_app/macros
bevy_app bevy_app
bevy_log bevy_log
bevy_dynamic_plugin bevy_dynamic_plugin
@ -42,4 +43,4 @@ do
done done
cd .. cd ..
cargo publish cargo publish