 01649f13e2
			
		
	
	
		01649f13e2
		
			
		
	
	
	
	
		
			
			# Objective This is a necessary precursor to #9122 (this was split from that PR to reduce the amount of code to review all at once). Moving `!Send` resource ownership to `App` will make it unambiguously `!Send`. `SubApp` must be `Send`, so it can't wrap `App`. ## Solution Refactor `App` and `SubApp` to not have a recursive relationship. Since `SubApp` no longer wraps `App`, once `!Send` resources are moved out of `World` and into `App`, `SubApp` will become unambiguously `Send`. There could be less code duplication between `App` and `SubApp`, but that would break `App` method chaining. ## Changelog - `SubApp` no longer wraps `App`. - `App` fields are no longer publicly accessible. - `App` can no longer be converted into a `SubApp`. - Various methods now return references to a `SubApp` instead of an `App`. ## Migration Guide - To construct a sub-app, use `SubApp::new()`. `App` can no longer convert into `SubApp`. - If you implemented a trait for `App`, you may want to implement it for `SubApp` as well. - If you're accessing `app.world` directly, you now have to use `app.world()` and `app.world_mut()`. - `App::sub_app` now returns `&SubApp`. - `App::sub_app_mut` now returns `&mut SubApp`. - `App::get_sub_app` now returns `Option<&SubApp>.` - `App::get_sub_app_mut` now returns `Option<&mut SubApp>.`
		
			
				
	
	
		
			60 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			60 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use crate::{
 | |
|     render_resource::{GpuArrayBuffer, GpuArrayBufferable},
 | |
|     renderer::{RenderDevice, RenderQueue},
 | |
|     Render, RenderApp, RenderSet,
 | |
| };
 | |
| use bevy_app::{App, Plugin};
 | |
| use bevy_ecs::{
 | |
|     prelude::{Component, Entity},
 | |
|     schedule::IntoSystemConfigs,
 | |
|     system::{Commands, Query, Res, ResMut},
 | |
| };
 | |
| use std::marker::PhantomData;
 | |
| 
 | |
| /// This plugin prepares the components of the corresponding type for the GPU
 | |
| /// by storing them in a [`GpuArrayBuffer`].
 | |
| pub struct GpuComponentArrayBufferPlugin<C: Component + GpuArrayBufferable>(PhantomData<C>);
 | |
| 
 | |
| impl<C: Component + GpuArrayBufferable> Plugin for GpuComponentArrayBufferPlugin<C> {
 | |
|     fn build(&self, app: &mut App) {
 | |
|         if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
 | |
|             render_app.add_systems(
 | |
|                 Render,
 | |
|                 prepare_gpu_component_array_buffers::<C>.in_set(RenderSet::PrepareResources),
 | |
|             );
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     fn finish(&self, app: &mut App) {
 | |
|         if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
 | |
|             render_app.insert_resource(GpuArrayBuffer::<C>::new(
 | |
|                 render_app.world().resource::<RenderDevice>(),
 | |
|             ));
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl<C: Component + GpuArrayBufferable> Default for GpuComponentArrayBufferPlugin<C> {
 | |
|     fn default() -> Self {
 | |
|         Self(PhantomData::<C>)
 | |
|     }
 | |
| }
 | |
| 
 | |
| fn prepare_gpu_component_array_buffers<C: Component + GpuArrayBufferable>(
 | |
|     mut commands: Commands,
 | |
|     render_device: Res<RenderDevice>,
 | |
|     render_queue: Res<RenderQueue>,
 | |
|     mut gpu_array_buffer: ResMut<GpuArrayBuffer<C>>,
 | |
|     components: Query<(Entity, &C)>,
 | |
| ) {
 | |
|     gpu_array_buffer.clear();
 | |
| 
 | |
|     let entities = components
 | |
|         .iter()
 | |
|         .map(|(entity, component)| (entity, gpu_array_buffer.push(component.clone())))
 | |
|         .collect::<Vec<_>>();
 | |
|     commands.insert_or_spawn_batch(entities);
 | |
| 
 | |
|     gpu_array_buffer.write_buffer(&render_device, &render_queue);
 | |
| }
 |