//! Demonstrates different ways of extracting components from the main world to the render world.1//!2//! This is usually done as an intermediary step for transferring data to the GPU, making3//! it accessible inside shaders.4//!5//! In this example, multiple entities are spawned, each with a different marker component: A, B, C.6//! Each component contains the current elapsed time, updated each frame on the Main World, and is7//! extracted to the render world in a different way.89use bevy::prelude::*;10use bevy::render::{11extract_component::{ExtractComponent, ExtractComponentPlugin},12sync_world::{RenderEntity, SyncToRenderWorld},13Extract, Render, RenderApp,14};1516// The A component is extracted automatically through `ExtractComponentPlugin`. For this,17// it is required to implement `ExtractComponent`. You can do a custom implementation if you wish to18// do a custom extraction instead of just cloning the entire component.19//20// To be noted that the `SyncToRenderWorld` component, which spawns the corresponding entity on the Render World,21// is automatically added as a requirement through the `ExtractComponentPlugin`.22#[derive(Component, Clone, ExtractComponent, Debug)]23struct A(pub f32);2425// The B component is extracted manually inside the `extract_components` system.26// `SyncToRenderWorld` ensures that an equivalent entity will be spawned in the Render World27// and the two will be associated in the Extract schedule through the `RenderEntity` component.28#[derive(Component, Clone, Debug)]29#[require(SyncToRenderWorld)]30struct B(pub f32);3132// The C component is the same B, but it only extracts when the `Space` key is pressed.33#[derive(Component, Clone, Debug)]34#[require(SyncToRenderWorld)]35struct C(pub f32);3637// Message sent when the `Space` key is pressed, causing the extraction of C.38#[derive(Message)]39struct ExtractMessage;4041// Resource inserted in each World, used to display its name.42#[derive(Resource)]43struct WorldName(pub String);4445fn main() {46let mut app = App::new();4748// Main World49app.insert_resource(WorldName("Main World".into()))50.add_plugins((51DefaultPlugins,52// Plugin for automatically extracting A.53ExtractComponentPlugin::<A>::default(),54))55.add_message::<ExtractMessage>()56.add_systems(Startup, setup)57.add_systems(Update, (set_time, trigger_extraction, display_state));5859let Some(render_app) = app.get_sub_app_mut(RenderApp) else {60return;61};6263// Render World64render_app65.insert_resource(WorldName("Render World".into()))66.add_systems(ExtractSchedule, extract_components)67.add_systems(Render, display_state);6869app.run();70}7172// Spawns the components on the Main World. Runs on Startup.73fn setup(mut commands: Commands, time: Res<Time>) {74commands.spawn(A(time.elapsed_secs()));75commands.spawn(B(time.elapsed_secs()));76commands.spawn(C(time.elapsed_secs()));77}7879// Sets the elapsed time on each of the components on the Main World. Runs each frame.80fn set_time(mut a: Single<&mut A>, mut b: Single<&mut B>, mut c: Single<&mut C>, time: Res<Time>) {81a.0 = time.elapsed_secs();82b.0 = time.elapsed_secs();83c.0 = time.elapsed_secs();84}8586// Displays the values from each of the components. The same system is used for both Worlds.87fn display_state(88a: Option<Single<(Entity, &A)>>,89b: Option<Single<(Entity, &B)>>,90c: Option<Single<(Entity, &C)>>,9192// Resource used to debug the name of the World.93world_name: Res<WorldName>,94) {95let (a, b, c) = (96a.map(Single::into_inner),97b.map(Single::into_inner),98c.map(Single::into_inner),99);100info!(?a, ?b, ?c, "{: >12}", world_name.0);101}102103// Writes a message when the `Space` key is pressed, which is later read by the `extract_components` system.104fn trigger_extraction(mut writer: MessageWriter<ExtractMessage>, keys: Res<ButtonInput<KeyCode>>) {105if keys.pressed(KeyCode::Space) {106writer.write(ExtractMessage);107}108}109110// System that Extracts B each frame, and C only when the `Space` key was just pressed (see the `trigger_extraction` system).111// Extraction is done by inserting a clone of the component on the corresponding Render World entity.112fn extract_components(113b: Extract<Query<(RenderEntity, &B)>>,114c: Extract<Query<(RenderEntity, &C)>>,115mut reader: Extract<MessageReader<ExtractMessage>>,116mut commands: Commands,117) {118for (entity, b) in &b {119commands.entity(entity).insert(b.clone());120}121122if !reader.is_empty() {123for (entity, c) in &c {124commands.entity(entity).insert(c.clone());125}126reader.clear();127}128}129130131