SystemParam for the name of the system you are currently in (#5731)

# Objective
- Similar to `SystemChangeTick`, probably somewhat useful for debugging messages.

---

## Changelog

- Added `SystemName` which copies the `SystemMeta::name` field so it can be accessed within a system.
This commit is contained in:
Aceeri 2022-08-18 18:31:12 +00:00
parent 56fc1dfe77
commit f0c512731b
2 changed files with 87 additions and 0 deletions

View file

@ -59,6 +59,7 @@
//! - [`NonSendMut`] and `Option<NonSendMut>` //! - [`NonSendMut`] and `Option<NonSendMut>`
//! - [`&World`](crate::world::World) //! - [`&World`](crate::world::World)
//! - [`RemovedComponents`] //! - [`RemovedComponents`]
//! - [`SystemName`]
//! - [`SystemChangeTick`] //! - [`SystemChangeTick`]
//! - [`Archetypes`](crate::archetype::Archetypes) (Provides Archetype metadata) //! - [`Archetypes`](crate::archetype::Archetypes) (Provides Archetype metadata)
//! - [`Bundles`](crate::bundle::Bundles) (Provides Bundles metadata) //! - [`Bundles`](crate::bundle::Bundles) (Provides Bundles metadata)

View file

@ -16,6 +16,7 @@ pub use bevy_ecs_macros::SystemParam;
use bevy_ecs_macros::{all_tuples, impl_param_set}; use bevy_ecs_macros::{all_tuples, impl_param_set};
use bevy_ptr::UnsafeCellDeref; use bevy_ptr::UnsafeCellDeref;
use std::{ use std::{
borrow::Cow,
fmt::Debug, fmt::Debug,
marker::PhantomData, marker::PhantomData,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
@ -1304,6 +1305,91 @@ impl<'w, 's> SystemParamFetch<'w, 's> for SystemChangeTickState {
} }
} }
/// Name of the system that corresponds to this [`crate::system::SystemState`].
///
/// This is not a reliable identifier, it is more so useful for debugging
/// purposes of finding where a system parameter is being used incorrectly.
pub struct SystemName<'s> {
name: &'s str,
}
impl<'s> SystemName<'s> {
pub fn name(&self) -> &str {
self.name
}
}
impl<'s> Deref for SystemName<'s> {
type Target = str;
fn deref(&self) -> &Self::Target {
self.name()
}
}
impl<'s> AsRef<str> for SystemName<'s> {
fn as_ref(&self) -> &str {
self.name()
}
}
impl<'s> From<SystemName<'s>> for &'s str {
fn from(name: SystemName<'s>) -> &'s str {
name.name
}
}
impl<'s> std::fmt::Debug for SystemName<'s> {
#[inline(always)]
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_tuple("SystemName").field(&self.name()).finish()
}
}
impl<'s> std::fmt::Display for SystemName<'s> {
#[inline(always)]
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Display::fmt(&self.name(), f)
}
}
impl<'s> SystemParam for SystemName<'s> {
type Fetch = SystemNameState;
}
// SAFETY: Only reads internal system state
unsafe impl ReadOnlySystemParamFetch for SystemNameState {}
/// The [`SystemParamState`] of [`SystemName`].
#[doc(hidden)]
pub struct SystemNameState {
name: Cow<'static, str>,
}
// SAFETY: no component value access
unsafe impl SystemParamState for SystemNameState {
fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self {
Self {
name: system_meta.name.clone(),
}
}
}
impl<'w, 's> SystemParamFetch<'w, 's> for SystemNameState {
type Item = SystemName<'s>;
#[inline]
unsafe fn get_param(
state: &'s mut Self,
_system_meta: &SystemMeta,
_world: &'w World,
_change_tick: u32,
) -> Self::Item {
SystemName {
name: state.name.as_ref(),
}
}
}
macro_rules! impl_system_param_tuple { macro_rules! impl_system_param_tuple {
($($param: ident),*) => { ($($param: ident),*) => {
impl<$($param: SystemParam),*> SystemParam for ($($param,)*) { impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {