From 6f08bb84d2dfbca9e41f0f3b079d9c4d7929ee93 Mon Sep 17 00:00:00 2001 From: Lucas Franca Date: Tue, 17 Jun 2025 19:38:31 -0300 Subject: [PATCH] Exposes `Observer`'s system's name (#19611) # Objective Fixes #18726 Alternative to and closes #18797 ## Solution Create a method `Observer::system_name` to expose the name of the `Observer`'s system ## Showcase ```rust // Returns `my_crate::my_observer` let observer = Observer::new(my_observer); println!(observer.system_name()); // Returns `my_crate::method::{{closure}}` let observer = Observer::new(|_trigger: Trigger<...>|); println!(observer.system_name()); // Returns `custom_name` let observer = Observer::new(IntoSystem::into_system(my_observer).with_name("custom_name")); println!(observer.system_name()); ``` ## TODO - [ ] Achieve cart's approval --------- Co-authored-by: Alice Cecile --- crates/bevy_ecs/src/observer/runner.rs | 33 ++++++++++++++----- crates/bevy_ecs/src/system/schedule_system.rs | 2 -- .../release-notes/observer_overhaul.md | 9 +++-- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/crates/bevy_ecs/src/observer/runner.rs b/crates/bevy_ecs/src/observer/runner.rs index 4fd9f23556..b6f10de2e4 100644 --- a/crates/bevy_ecs/src/observer/runner.rs +++ b/crates/bevy_ecs/src/observer/runner.rs @@ -1,4 +1,4 @@ -use alloc::{boxed::Box, vec}; +use alloc::{borrow::Cow, boxed::Box, vec}; use core::any::Any; use crate::{ @@ -194,7 +194,7 @@ pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut, propagate: pub struct Observer { hook_on_add: ComponentHook, error_handler: Option, - system: Box, + system: Box, pub(crate) descriptor: ObserverDescriptor, pub(crate) last_trigger_id: u32, pub(crate) despawned_watched_entities: u32, @@ -232,7 +232,7 @@ impl Observer { /// Creates a new [`Observer`] with custom runner, this is mostly used for dynamic event observer pub fn with_dynamic_runner(runner: ObserverRunner) -> Self { Self { - system: Box::new(|| {}), + system: Box::new(IntoSystem::into_system(|| {})), descriptor: Default::default(), hook_on_add: |mut world, hook_context| { let default_error_handler = world.default_error_handler(); @@ -299,6 +299,11 @@ impl Observer { pub fn descriptor(&self) -> &ObserverDescriptor { &self.descriptor } + + /// Returns the name of the [`Observer`]'s system . + pub fn system_name(&self) -> Cow<'static, str> { + self.system.system_name() + } } impl Component for Observer { @@ -364,7 +369,8 @@ fn observer_system_runner>( // - observer was triggered so must have an `Observer` component. // - observer cannot be dropped or mutated until after the system pointer is already dropped. let system: *mut dyn ObserverSystem = unsafe { - let system = state.system.downcast_mut::().debug_checked_unwrap(); + let system: &mut dyn Any = state.system.as_mut(); + let system = system.downcast_mut::().debug_checked_unwrap(); &mut *system }; @@ -413,6 +419,16 @@ fn observer_system_runner>( } } +trait AnyNamedSystem: Any + Send + Sync + 'static { + fn system_name(&self) -> Cow<'static, str>; +} + +impl AnyNamedSystem for T { + fn system_name(&self) -> Cow<'static, str> { + self.name() + } +} + /// A [`ComponentHook`] used by [`Observer`] to handle its [`on-add`](`crate::lifecycle::ComponentHooks::on_add`). /// /// This function exists separate from [`Observer`] to allow [`Observer`] to have its type parameters @@ -431,11 +447,12 @@ fn hook_on_add>( B::component_ids(&mut world.components_registrator(), &mut |id| { components.push(id); }); - if let Some(mut observe) = world.get_mut::(entity) { - observe.descriptor.events.push(event_id); - observe.descriptor.components.extend(components); + if let Some(mut observer) = world.get_mut::(entity) { + observer.descriptor.events.push(event_id); + observer.descriptor.components.extend(components); - let system: *mut dyn ObserverSystem = observe.system.downcast_mut::().unwrap(); + let system: &mut dyn Any = observer.system.as_mut(); + let system: *mut dyn ObserverSystem = system.downcast_mut::().unwrap(); // SAFETY: World reference is exclusive and initialize does not touch system, so references do not alias unsafe { (*system).initialize(world); diff --git a/crates/bevy_ecs/src/system/schedule_system.rs b/crates/bevy_ecs/src/system/schedule_system.rs index ab2d9d31fb..b7b07ca184 100644 --- a/crates/bevy_ecs/src/system/schedule_system.rs +++ b/crates/bevy_ecs/src/system/schedule_system.rs @@ -137,7 +137,6 @@ where T: Send + Sync + 'static, { type In = (); - type Out = S::Out; fn name(&self) -> Cow<'static, str> { @@ -231,7 +230,6 @@ where T: FromWorld + Send + Sync + 'static, { type In = (); - type Out = S::Out; fn name(&self) -> Cow<'static, str> { diff --git a/release-content/release-notes/observer_overhaul.md b/release-content/release-notes/observer_overhaul.md index f51b138764..c01aa561e9 100644 --- a/release-content/release-notes/observer_overhaul.md +++ b/release-content/release-notes/observer_overhaul.md @@ -1,7 +1,7 @@ --- title: Observer Overhaul -authors: ["@Jondolf", "@alice-i-cecile"] -pull_requests: [19596, 19663] +authors: ["@Jondolf", "@alice-i-cecile", "@hukasu] +pull_requests: [19596, 19663, 19611] --- ## Rename `Trigger` to `On` @@ -40,3 +40,8 @@ allowing you to bubble events up your hierarchy to see if any of the parents car then act on the entity that was actually picked in the first place. This was handy! We've enabled this functionality for all entity-events: simply call `On::original_target`. + +## Expose name of the Observer's system + +The name of the Observer's system is now accessible through `Observer::system_name`, +this opens up the possibility for the debug tools to show more meaningful names for observers.