use bevy::prelude::*;
use bevy::render::{
extract_component::{ExtractComponent, ExtractComponentPlugin},
sync_world::{RenderEntity, SyncToRenderWorld},
Extract, Render, RenderApp,
};
#[derive(Component, Clone, ExtractComponent, Debug)]
struct A(pub f32);
#[derive(Component, Clone, Debug)]
#[require(SyncToRenderWorld)]
struct B(pub f32);
#[derive(Component, Clone, Debug)]
#[require(SyncToRenderWorld)]
struct C(pub f32);
#[derive(Message)]
struct ExtractMessage;
#[derive(Resource)]
struct WorldName(pub String);
fn main() {
let mut app = App::new();
app.insert_resource(WorldName("Main World".into()))
.add_plugins((
DefaultPlugins,
ExtractComponentPlugin::<A>::default(),
))
.add_message::<ExtractMessage>()
.add_systems(Startup, setup)
.add_systems(Update, (set_time, trigger_extraction, display_state));
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;
};
render_app
.insert_resource(WorldName("Render World".into()))
.add_systems(ExtractSchedule, extract_components)
.add_systems(Render, display_state);
app.run();
}
fn setup(mut commands: Commands, time: Res<Time>) {
commands.spawn(A(time.elapsed_secs()));
commands.spawn(B(time.elapsed_secs()));
commands.spawn(C(time.elapsed_secs()));
}
fn set_time(mut a: Single<&mut A>, mut b: Single<&mut B>, mut c: Single<&mut C>, time: Res<Time>) {
a.0 = time.elapsed_secs();
b.0 = time.elapsed_secs();
c.0 = time.elapsed_secs();
}
fn display_state(
a: Option<Single<(Entity, &A)>>,
b: Option<Single<(Entity, &B)>>,
c: Option<Single<(Entity, &C)>>,
world_name: Res<WorldName>,
) {
let (a, b, c) = (
a.map(Single::into_inner),
b.map(Single::into_inner),
c.map(Single::into_inner),
);
info!(?a, ?b, ?c, "{: >12}", world_name.0);
}
fn trigger_extraction(mut writer: MessageWriter<ExtractMessage>, keys: Res<ButtonInput<KeyCode>>) {
if keys.pressed(KeyCode::Space) {
writer.write(ExtractMessage);
}
}
fn extract_components(
b: Extract<Query<(RenderEntity, &B)>>,
c: Extract<Query<(RenderEntity, &C)>>,
mut reader: Extract<MessageReader<ExtractMessage>>,
mut commands: Commands,
) {
for (entity, b) in &b {
commands.entity(entity).insert(b.clone());
}
if !reader.is_empty() {
for (entity, c) in &c {
commands.entity(entity).insert(c.clone());
}
reader.clear();
}
}