mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 20:53:53 +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>,
|
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.
|
/// Each `SubApp` has its own [`Schedule`] and [`World`], enabling a separation of concerns.
|
||||||
struct SubApp {
|
struct SubApp {
|
||||||
app: App,
|
app: App,
|
||||||
runner: Box<dyn Fn(&mut World, &mut 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 {
|
impl Default for App {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mut app = App::empty();
|
let mut app = App::empty();
|
||||||
|
|
|
@ -35,6 +35,17 @@ pub struct QueryState<Q: WorldQuery, F: ReadOnlyWorldQuery = ()> {
|
||||||
pub(crate) filter_state: F::State,
|
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> {
|
impl<Q: WorldQuery, F: ReadOnlyWorldQuery> FromWorld for QueryState<Q, F> {
|
||||||
fn from_world(world: &mut World) -> Self {
|
fn from_world(world: &mut World) -> Self {
|
||||||
world.query_filtered()
|
world.query_filtered()
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{schedule::SystemContainer, world::World};
|
use crate::{schedule::SystemContainer, world::World};
|
||||||
|
use core::fmt::Debug;
|
||||||
use downcast_rs::{impl_downcast, Downcast};
|
use downcast_rs::{impl_downcast, Downcast};
|
||||||
|
|
||||||
pub trait ParallelSystemExecutor: Downcast + Send + Sync {
|
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);
|
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);
|
impl_downcast!(ParallelSystemExecutor);
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct SingleThreadedExecutor;
|
pub struct SingleThreadedExecutor;
|
||||||
|
|
||||||
impl ParallelSystemExecutor for 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.
|
/// 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
|
/// For example, it can be set to run only once during app execution, while the parent schedule
|
||||||
/// runs indefinitely.
|
/// runs indefinitely.
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Schedule {
|
pub struct Schedule {
|
||||||
stages: HashMap<StageLabelId, Box<dyn Stage>>,
|
stages: HashMap<StageLabelId, Box<dyn Stage>>,
|
||||||
stage_order: Vec<StageLabelId>,
|
stage_order: Vec<StageLabelId>,
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
|
prelude::System,
|
||||||
schedule::{GraphNode, RunCriteriaLabel, RunCriteriaLabelId},
|
schedule::{GraphNode, RunCriteriaLabel, RunCriteriaLabelId},
|
||||||
system::{BoxedSystem, IntoSystem, Local},
|
system::{BoxedSystem, IntoSystem, Local},
|
||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
|
use core::fmt::Debug;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
/// Determines whether a system should be executed or not, and how many times it should be ran each
|
/// 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 {
|
pub(crate) struct BoxedRunCriteria {
|
||||||
criteria_system: Option<BoxedSystem<(), ShouldRun>>,
|
criteria_system: Option<BoxedSystem<(), ShouldRun>>,
|
||||||
initialized: bool,
|
initialized: bool,
|
||||||
|
@ -93,6 +95,7 @@ impl BoxedRunCriteria {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub(crate) enum RunCriteriaInner {
|
pub(crate) enum RunCriteriaInner {
|
||||||
Single(BoxedSystem<(), ShouldRun>),
|
Single(BoxedSystem<(), ShouldRun>),
|
||||||
Piped {
|
Piped {
|
||||||
|
@ -101,6 +104,7 @@ pub(crate) enum RunCriteriaInner {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub(crate) struct RunCriteriaContainer {
|
pub(crate) struct RunCriteriaContainer {
|
||||||
pub(crate) should_run: ShouldRun,
|
pub(crate) should_run: ShouldRun,
|
||||||
pub(crate) inner: RunCriteriaInner,
|
pub(crate) inner: RunCriteriaInner,
|
||||||
|
@ -165,17 +169,19 @@ impl GraphNode for RunCriteriaContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum RunCriteriaDescriptorOrLabel {
|
pub enum RunCriteriaDescriptorOrLabel {
|
||||||
Descriptor(RunCriteriaDescriptor),
|
Descriptor(RunCriteriaDescriptor),
|
||||||
Label(RunCriteriaLabelId),
|
Label(RunCriteriaLabelId),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub(crate) enum DuplicateLabelStrategy {
|
pub(crate) enum DuplicateLabelStrategy {
|
||||||
Panic,
|
Panic,
|
||||||
Discard,
|
Discard,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct RunCriteriaDescriptor {
|
pub struct RunCriteriaDescriptor {
|
||||||
pub(crate) system: RunCriteriaSystem,
|
pub(crate) system: RunCriteriaSystem,
|
||||||
pub(crate) label: Option<RunCriteriaLabelId>,
|
pub(crate) label: Option<RunCriteriaLabelId>,
|
||||||
|
@ -184,6 +190,7 @@ pub struct RunCriteriaDescriptor {
|
||||||
pub(crate) after: Vec<RunCriteriaLabelId>,
|
pub(crate) after: Vec<RunCriteriaLabelId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub(crate) enum RunCriteriaSystem {
|
pub(crate) enum RunCriteriaSystem {
|
||||||
Single(BoxedSystem<(), ShouldRun>),
|
Single(BoxedSystem<(), ShouldRun>),
|
||||||
Piped(BoxedSystem<ShouldRun, ShouldRun>),
|
Piped(BoxedSystem<ShouldRun, ShouldRun>),
|
||||||
|
@ -326,6 +333,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct RunCriteria {
|
pub struct RunCriteria {
|
||||||
label: RunCriteriaLabelId,
|
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_ecs_macros::Resource;
|
||||||
use bevy_utils::{tracing::warn, HashMap, HashSet};
|
use bevy_utils::{tracing::warn, HashMap, HashSet};
|
||||||
|
use core::fmt::Debug;
|
||||||
use downcast_rs::{impl_downcast, Downcast};
|
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).
|
/// A type that can run as a step of a [`Schedule`](super::Schedule).
|
||||||
pub trait Stage: Downcast + Send + Sync {
|
pub trait Stage: Downcast + Send + Sync {
|
||||||
|
@ -25,6 +26,18 @@ pub trait Stage: Downcast + Send + Sync {
|
||||||
fn run(&mut self, world: &mut World);
|
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);
|
impl_downcast!(Stage);
|
||||||
|
|
||||||
/// When this resource is present in the `App`'s `Resources`,
|
/// When this resource is present in the `App`'s `Resources`,
|
||||||
|
@ -584,6 +597,64 @@ impl SystemStage {
|
||||||
}
|
}
|
||||||
Ok(labels)
|
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
|
/// Sorts given system containers topologically, populates their resolved dependencies
|
||||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
system::System,
|
system::System,
|
||||||
};
|
};
|
||||||
|
use core::fmt::Debug;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
pub struct SystemContainer {
|
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 {
|
impl GraphNode for SystemContainer {
|
||||||
type Label = SystemLabelId;
|
type Label = SystemLabelId;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Configures ambiguity detection for a single system.
|
/// Configures ambiguity detection for a single system.
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
pub(crate) enum AmbiguityDetection {
|
pub(crate) enum AmbiguityDetection {
|
||||||
#[default]
|
#[default]
|
||||||
Check,
|
Check,
|
||||||
|
@ -41,6 +41,7 @@ pub(crate) enum AmbiguityDetection {
|
||||||
/// .with_system(do_the_other_thing.after(Something))
|
/// .with_system(do_the_other_thing.after(Something))
|
||||||
/// .with_system(do_something_else.at_end());
|
/// .with_system(do_something_else.at_end());
|
||||||
/// ```
|
/// ```
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct SystemDescriptor {
|
pub struct SystemDescriptor {
|
||||||
pub(crate) system: BoxedSystem<(), ()>,
|
pub(crate) system: BoxedSystem<(), ()>,
|
||||||
pub(crate) exclusive_insertion_point: Option<ExclusiveInsertionPoint>,
|
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,
|
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> {
|
impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> {
|
||||||
/// Creates a new query.
|
/// Creates a new query.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use bevy_utils::tracing::warn;
|
use bevy_utils::tracing::warn;
|
||||||
|
use core::fmt::Debug;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
archetype::ArchetypeComponentId, change_detection::MAX_CHANGE_AGE, component::ComponentId,
|
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);
|
*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