use std::sync::atomic::{AtomicU32, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};
use bevy::prelude::*;
use bevy::remote::BrpResult;
use serde_json::{json, Value};
use crate::plugin::commands::DebugCommands;
use crate::plugin::scene::{SceneRejected, ScenePlayback};
#[derive(Resource)]
pub struct DebugReady(pub bool);
#[derive(Resource, Default)]
pub(crate) struct FrameTicks(pub u32);
#[derive(Resource, Clone, Debug, PartialEq, Eq)]
pub(crate) struct GameInstance(pub String);
impl GameInstance {
pub(crate) fn new() -> Self {
static STARTED_IN_THIS_PROCESS: AtomicU32 = AtomicU32::new(0);
let nanos = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_or(0, |since| since.as_nanos());
let nth = STARTED_IN_THIS_PROCESS.fetch_add(1, Ordering::Relaxed);
Self(format!("{}-{nanos:x}-{nth}", std::process::id()))
}
}
pub(crate) fn tick_frames(mut ticks: ResMut<FrameTicks>) {
ticks.0 = ticks.0.wrapping_add(1);
}
pub(crate) fn handle_status(
In(_): In<Option<Value>>,
ready: Res<DebugReady>,
ticks: Res<FrameTicks>,
instance: Res<GameInstance>,
commands: Res<DebugCommands>,
playback: Option<Res<ScenePlayback>>,
rejected: Option<Res<SceneRejected>>,
#[cfg(feature = "plugin-screenshot")] target: Option<Res<crate::plugin::screenshot::DebugCaptureTarget>>,
#[cfg(feature = "plugin-screenshot")] windows: Query<(), With<bevy::window::PrimaryWindow>>,
) -> BrpResult {
let replay = match (playback, rejected) {
(Some(p), _) => json!({
"path": p.path,
"done": p.next,
"total": p.steps.len(),
"failed": p.failed,
}),
(None, Some(r)) => json!({
"path": r.path,
"rejected": r.why,
}),
(None, None) => Value::Null,
};
Ok(json!({
"ready": ready.0,
"instance": instance.0,
"frame": ticks.0,
"commands": commands.iter().count(),
"capture": capture_kind(
#[cfg(feature = "plugin-screenshot")]
target.is_some(),
#[cfg(feature = "plugin-screenshot")]
!windows.is_empty(),
),
"replay": replay,
}))
}
fn capture_kind(
#[cfg(feature = "plugin-screenshot")] offscreen: bool,
#[cfg(feature = "plugin-screenshot")] window: bool,
) -> &'static str {
#[cfg(feature = "plugin-screenshot")]
{
if offscreen {
return "offscreen";
}
if window {
return "window";
}
}
"none"
}