mirror of
https://github.com/bevyengine/bevy
synced 2024-11-26 06:30:19 +00:00
Adding Debug implementations for App, Stage, Schedule, Query, QueryState, etc. (#6214)
# Objective - Adding Debug implementations for App, Stage, Schedule, Query, QueryState. - Fixes #1130. ## Solution - Implemented std::fmt::Debug for a number of structures. --- ## Changelog Also added Debug implementations for ParallelSystemExecutor, SingleThreadedExecutor, various RunCriteria structures, SystemContainer, and SystemDescriptor. Opinions are sure to differ as to what information to provide in a Debug implementation. Best guess was taken for this initial version for these structures. Co-authored-by: targrub <62773321+targrub@users.noreply.github.com>
This commit is contained in:
parent
55d126cab9
commit
9a597b758e
10 changed files with 202 additions and 6 deletions
|
@ -70,12 +70,32 @@ pub struct App {
|
|||
sub_apps: HashMap<AppLabelId, SubApp>,
|
||||
}
|
||||
|
||||
impl Debug for App {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "App {{ sub_apps: ")?;
|
||||
f.debug_map()
|
||||
.entries(self.sub_apps.iter().map(|(k, v)| (k, v)))
|
||||
.finish()?;
|
||||
write!(f, "}}")
|
||||
}
|
||||
}
|
||||
|
||||
/// Each `SubApp` has its own [`Schedule`] and [`World`], enabling a separation of concerns.
|
||||
struct SubApp {
|
||||
app: App,
|
||||
runner: Box<dyn Fn(&mut World, &mut App)>,
|
||||
}
|
||||
|
||||
impl Debug for SubApp {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "SubApp {{ app: ")?;
|
||||
f.debug_map()
|
||||
.entries(self.app.sub_apps.iter().map(|(k, v)| (k, v)))
|
||||
.finish()?;
|
||||
write!(f, "}}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for App {
|
||||
fn default() -> Self {
|
||||
let mut app = App::empty();
|
||||
|
|
|
@ -35,6 +35,17 @@ pub struct QueryState<Q: WorldQuery, F: ReadOnlyWorldQuery = ()> {
|
|||
pub(crate) filter_state: F::State,
|
||||
}
|
||||
|
||||
impl<Q: WorldQuery, F: ReadOnlyWorldQuery> std::fmt::Debug for QueryState<Q, F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"QueryState<Q, F> matched_table_ids: {} matched_archetype_ids: {}",
|
||||
self.matched_table_ids.len(),
|
||||
self.matched_archetype_ids.len()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Q: WorldQuery, F: ReadOnlyWorldQuery> FromWorld for QueryState<Q, F> {
|
||||
fn from_world(world: &mut World) -> Self {
|
||||
world.query_filtered()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::{schedule::SystemContainer, world::World};
|
||||
use core::fmt::Debug;
|
||||
use downcast_rs::{impl_downcast, Downcast};
|
||||
|
||||
pub trait ParallelSystemExecutor: Downcast + Send + Sync {
|
||||
|
@ -8,9 +9,15 @@ pub trait ParallelSystemExecutor: Downcast + Send + Sync {
|
|||
fn run_systems(&mut self, systems: &mut [SystemContainer], world: &mut World);
|
||||
}
|
||||
|
||||
impl Debug for dyn ParallelSystemExecutor {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "dyn ParallelSystemExecutor")
|
||||
}
|
||||
}
|
||||
|
||||
impl_downcast!(ParallelSystemExecutor);
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct SingleThreadedExecutor;
|
||||
|
||||
impl ParallelSystemExecutor for SingleThreadedExecutor {
|
||||
|
|
|
@ -37,7 +37,7 @@ use bevy_utils::HashMap;
|
|||
/// In this way, the properties of the child schedule can be set differently from the parent.
|
||||
/// For example, it can be set to run only once during app execution, while the parent schedule
|
||||
/// runs indefinitely.
|
||||
#[derive(Default)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Schedule {
|
||||
stages: HashMap<StageLabelId, Box<dyn Stage>>,
|
||||
stage_order: Vec<StageLabelId>,
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use crate::{
|
||||
prelude::System,
|
||||
schedule::{GraphNode, RunCriteriaLabel, RunCriteriaLabelId},
|
||||
system::{BoxedSystem, IntoSystem, Local},
|
||||
world::World,
|
||||
};
|
||||
use core::fmt::Debug;
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// Determines whether a system should be executed or not, and how many times it should be ran each
|
||||
|
@ -66,7 +68,7 @@ impl From<bool> for ShouldRun {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct BoxedRunCriteria {
|
||||
criteria_system: Option<BoxedSystem<(), ShouldRun>>,
|
||||
initialized: bool,
|
||||
|
@ -93,6 +95,7 @@ impl BoxedRunCriteria {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum RunCriteriaInner {
|
||||
Single(BoxedSystem<(), ShouldRun>),
|
||||
Piped {
|
||||
|
@ -101,6 +104,7 @@ pub(crate) enum RunCriteriaInner {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct RunCriteriaContainer {
|
||||
pub(crate) should_run: ShouldRun,
|
||||
pub(crate) inner: RunCriteriaInner,
|
||||
|
@ -165,17 +169,19 @@ impl GraphNode for RunCriteriaContainer {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RunCriteriaDescriptorOrLabel {
|
||||
Descriptor(RunCriteriaDescriptor),
|
||||
Label(RunCriteriaLabelId),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub(crate) enum DuplicateLabelStrategy {
|
||||
Panic,
|
||||
Discard,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RunCriteriaDescriptor {
|
||||
pub(crate) system: RunCriteriaSystem,
|
||||
pub(crate) label: Option<RunCriteriaLabelId>,
|
||||
|
@ -184,6 +190,7 @@ pub struct RunCriteriaDescriptor {
|
|||
pub(crate) after: Vec<RunCriteriaLabelId>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum RunCriteriaSystem {
|
||||
Single(BoxedSystem<(), ShouldRun>),
|
||||
Piped(BoxedSystem<ShouldRun, ShouldRun>),
|
||||
|
@ -326,6 +333,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RunCriteria {
|
||||
label: RunCriteriaLabelId,
|
||||
}
|
||||
|
@ -346,3 +354,49 @@ impl RunCriteria {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for dyn System<In = (), Out = ShouldRun> + 'static {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"System {} with In=(), Out=ShouldRun: {{{}}}",
|
||||
self.name(),
|
||||
{
|
||||
if self.is_send() {
|
||||
if self.is_exclusive() {
|
||||
"is_send is_exclusive"
|
||||
} else {
|
||||
"is_send"
|
||||
}
|
||||
} else if self.is_exclusive() {
|
||||
"is_exclusive"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for dyn System<In = ShouldRun, Out = ShouldRun> + 'static {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"System {} with In=ShouldRun, Out=ShouldRun: {{{}}}",
|
||||
self.name(),
|
||||
{
|
||||
if self.is_send() {
|
||||
if self.is_exclusive() {
|
||||
"is_send is_exclusive"
|
||||
} else {
|
||||
"is_send"
|
||||
}
|
||||
} else if self.is_exclusive() {
|
||||
"is_exclusive"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,9 +14,10 @@ use crate::{
|
|||
};
|
||||
use bevy_ecs_macros::Resource;
|
||||
use bevy_utils::{tracing::warn, HashMap, HashSet};
|
||||
use core::fmt::Debug;
|
||||
use downcast_rs::{impl_downcast, Downcast};
|
||||
|
||||
use super::IntoSystemDescriptor;
|
||||
use super::{IntoSystemDescriptor, Schedule};
|
||||
|
||||
/// A type that can run as a step of a [`Schedule`](super::Schedule).
|
||||
pub trait Stage: Downcast + Send + Sync {
|
||||
|
@ -25,6 +26,18 @@ pub trait Stage: Downcast + Send + Sync {
|
|||
fn run(&mut self, world: &mut World);
|
||||
}
|
||||
|
||||
impl Debug for dyn Stage {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if let Some(as_systemstage) = self.as_any().downcast_ref::<SystemStage>() {
|
||||
write!(f, "{:?}", as_systemstage)
|
||||
} else if let Some(as_schedule) = self.as_any().downcast_ref::<Schedule>() {
|
||||
write!(f, "{:?}", as_schedule)
|
||||
} else {
|
||||
write!(f, "Unknown dyn Stage")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_downcast!(Stage);
|
||||
|
||||
/// When this resource is present in the `App`'s `Resources`,
|
||||
|
@ -584,6 +597,64 @@ impl SystemStage {
|
|||
}
|
||||
Ok(labels)
|
||||
}
|
||||
|
||||
pub fn vec_system_container_debug(
|
||||
&self,
|
||||
name: &str,
|
||||
v: &Vec<SystemContainer>,
|
||||
f: &mut std::fmt::Formatter<'_>,
|
||||
) -> std::fmt::Result {
|
||||
write!(f, "{}: ", name)?;
|
||||
if v.len() > 1 {
|
||||
writeln!(f, "[")?;
|
||||
for sc in v.iter() {
|
||||
writeln!(f, "{:?},", sc)?;
|
||||
}
|
||||
write!(f, "], ")
|
||||
} else {
|
||||
write!(f, "{:?}, ", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for SystemStage {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "SystemStage: {{ ")?;
|
||||
write!(
|
||||
f,
|
||||
"world_id: {:?}, executor: {:?}, stage_run_criteria: {:?}, run_criteria: {:?}, ",
|
||||
self.world_id, self.executor, self.stage_run_criteria, self.run_criteria
|
||||
)?;
|
||||
self.vec_system_container_debug("exclusive_at_start", &self.exclusive_at_start, f)?;
|
||||
self.vec_system_container_debug(
|
||||
"exclusive_before_commands",
|
||||
&self.exclusive_before_commands,
|
||||
f,
|
||||
)?;
|
||||
self.vec_system_container_debug("exclusive_at_end", &self.exclusive_at_end, f)?;
|
||||
self.vec_system_container_debug("parallel", &self.parallel, f)?;
|
||||
write!(
|
||||
f,
|
||||
"systems_modified: {:?}, uninitialized_run_criteria: {:?}, ",
|
||||
self.systems_modified, self.uninitialized_run_criteria
|
||||
)?;
|
||||
write!(
|
||||
f,
|
||||
"uninitialized_at_start: {:?}, uninitialized_before_commands: {:?}, ",
|
||||
self.uninitialized_at_start, self.uninitialized_before_commands
|
||||
)?;
|
||||
write!(
|
||||
f,
|
||||
"uninitialized_at_end: {:?}, uninitialized_parallel: {:?}, ",
|
||||
self.uninitialized_at_end, self.uninitialized_parallel
|
||||
)?;
|
||||
write!(
|
||||
f,
|
||||
"last_tick_check: {:?}, apply_buffers: {:?}, ",
|
||||
self.last_tick_check, self.apply_buffers
|
||||
)?;
|
||||
write!(f, "must_read_resource: {:?}}}", self.must_read_resource)
|
||||
}
|
||||
}
|
||||
|
||||
/// Sorts given system containers topologically, populates their resolved dependencies
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
|||
},
|
||||
system::System,
|
||||
};
|
||||
use core::fmt::Debug;
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub struct SystemContainer {
|
||||
|
@ -83,6 +84,12 @@ impl SystemContainer {
|
|||
}
|
||||
}
|
||||
|
||||
impl Debug for SystemContainer {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{{{:?}}}", &self.system())
|
||||
}
|
||||
}
|
||||
|
||||
impl GraphNode for SystemContainer {
|
||||
type Label = SystemLabelId;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
};
|
||||
|
||||
/// Configures ambiguity detection for a single system.
|
||||
#[derive(Default)]
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) enum AmbiguityDetection {
|
||||
#[default]
|
||||
Check,
|
||||
|
@ -41,6 +41,7 @@ pub(crate) enum AmbiguityDetection {
|
|||
/// .with_system(do_the_other_thing.after(Something))
|
||||
/// .with_system(do_something_else.at_end());
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct SystemDescriptor {
|
||||
pub(crate) system: BoxedSystem<(), ()>,
|
||||
pub(crate) exclusive_insertion_point: Option<ExclusiveInsertionPoint>,
|
||||
|
|
|
@ -280,6 +280,12 @@ pub struct Query<'world, 'state, Q: WorldQuery, F: ReadOnlyWorldQuery = ()> {
|
|||
pub(crate) change_tick: u32,
|
||||
}
|
||||
|
||||
impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> std::fmt::Debug for Query<'w, 's, Q, F> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Query {{ matched entities: {}, world: {:?}, state: {:?}, last_change_tick: {}, change_tick: {} }}", self.iter().count(), self.world, self.state, self.last_change_tick, self.change_tick)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> {
|
||||
/// Creates a new query.
|
||||
///
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use bevy_utils::tracing::warn;
|
||||
use core::fmt::Debug;
|
||||
|
||||
use crate::{
|
||||
archetype::ArchetypeComponentId, change_detection::MAX_CHANGE_AGE, component::ComponentId,
|
||||
|
@ -95,3 +96,21 @@ pub(crate) fn check_system_change_tick(
|
|||
*last_change_tick = change_tick.wrapping_sub(MAX_CHANGE_AGE);
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for dyn System<In = (), Out = ()> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "System {}: {{{}}}", self.name(), {
|
||||
if self.is_send() {
|
||||
if self.is_exclusive() {
|
||||
"is_send is_exclusive"
|
||||
} else {
|
||||
"is_send"
|
||||
}
|
||||
} else if self.is_exclusive() {
|
||||
"is_exclusive"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
},)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue