Path: blob/main/crates/bevy_render/src/extract_resource.rs
9550 views
use core::marker::PhantomData;12use bevy_app::{App, Plugin};3use bevy_ecs::prelude::*;4pub use bevy_render_macros::ExtractResource;5use bevy_utils::once;67use crate::{Extract, ExtractSchedule, RenderApp};89/// Describes how a resource gets extracted for rendering.10///11/// Therefore the resource is transferred from the "main world" into the "render world"12/// in the [`ExtractSchedule`] step.13///14/// The marker type `F` is only used as a way to bypass the orphan rules. To15/// implement the trait for a foreign type you can use a local type as the16/// marker, e.g. the type of the plugin that calls [`ExtractResourcePlugin`].17pub trait ExtractResource<F = ()>: Resource {18type Source: Resource;1920/// Defines how the resource is transferred into the "render world".21fn extract_resource(source: &Self::Source) -> Self;22}2324/// This plugin extracts the resources into the "render world".25///26/// Therefore it sets up the[`ExtractSchedule`] step27/// for the specified [`Resource`].28///29/// The marker type `F` is only used as a way to bypass the orphan rules. To30/// implement the trait for a foreign type you can use a local type as the31/// marker, e.g. the type of the plugin that calls [`ExtractResourcePlugin`].32pub struct ExtractResourcePlugin<R: ExtractResource<F>, F = ()>(PhantomData<(R, F)>);3334impl<R: ExtractResource<F>, F> Default for ExtractResourcePlugin<R, F> {35fn default() -> Self {36Self(PhantomData)37}38}3940impl<R: ExtractResource<F>, F: 'static + Send + Sync> Plugin for ExtractResourcePlugin<R, F> {41fn build(&self, app: &mut App) {42if let Some(render_app) = app.get_sub_app_mut(RenderApp) {43render_app.add_systems(ExtractSchedule, extract_resource::<R, F>);44} else {45once!(bevy_log::error!(46"Render app did not exist when trying to add `extract_resource` for <{}>.",47core::any::type_name::<R>()48));49}50}51}5253/// This system extracts the resource of the corresponding [`Resource`] type54pub fn extract_resource<R: ExtractResource<F>, F>(55mut commands: Commands,56main_resource: Extract<Option<Res<R::Source>>>,57target_resource: Option<ResMut<R>>,58) {59if let Some(main_resource) = main_resource.as_ref() {60if let Some(mut target_resource) = target_resource {61if main_resource.is_changed() {62*target_resource = R::extract_resource(main_resource);63}64} else {65#[cfg(debug_assertions)]66if !main_resource.is_added() {67once!(bevy_log::warn!(68"Removing resource {} from render world not expected, adding using `Commands`.69This may decrease performance",70core::any::type_name::<R>()71));72}7374commands.insert_resource(R::extract_resource(main_resource));75}76}77}787980