From f9c8f511fd50d5d2321464ef5889d33ae8eba72f Mon Sep 17 00:00:00 2001 From: Jerome Humbert Date: Tue, 24 Dec 2024 18:26:32 +0000 Subject: [PATCH] Add `SubApp::take_extract()` (#16862) # Objective Fixes #16850 ## Solution Add a new function `SubApp::take_extract()`, similar to `Option::take()`, which allows stealing the currently installed extract function of a sub-app, with the intent to replace it with a custom one calling the original one via `set_extract()`. This pattern enables registering a custom "world sync" function similar to the existing one `entity_sync_system()`, to run custom world sync logic with mutable access to both the main and render worlds. ## Testing `cargo r -p ci` currently doesn't build locally, event after upgrading rustc to latest and doing a `cargo update`. --- crates/bevy_app/src/sub_app.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/crates/bevy_app/src/sub_app.rs b/crates/bevy_app/src/sub_app.rs index b921956a6d..ab7f00750b 100644 --- a/crates/bevy_app/src/sub_app.rs +++ b/crates/bevy_app/src/sub_app.rs @@ -166,6 +166,35 @@ impl SubApp { self } + /// Take the function that will be called by [`extract`](Self::extract) out of the app, if any was set, + /// and replace it with `None`. + /// + /// If you use Bevy, `bevy_render` will set a default extract function used to extract data from + /// the main world into the render world as part of the Extract phase. In that case, you cannot replace + /// it with your own function. Instead, take the Bevy default function with this, and install your own + /// instead which calls the Bevy default. + /// + /// ``` + /// # use bevy_app::SubApp; + /// # let mut app = SubApp::new(); + /// let default_fn = app.take_extract(); + /// app.set_extract(move |main, render| { + /// // Do pre-extract custom logic + /// // [...] + /// + /// // Call Bevy's default, which executes the Extract phase + /// if let Some(f) = default_fn.as_ref() { + /// f(main, render); + /// } + /// + /// // Do post-extract custom logic + /// // [...] + /// }); + /// ``` + pub fn take_extract(&mut self) -> Option { + self.extract.take() + } + /// See [`App::insert_resource`]. pub fn insert_resource(&mut self, resource: R) -> &mut Self { self.world.insert_resource(resource);