#![warn(missing_docs)]
#[cfg(feature = "enabled")]
pub mod settings_window;
#[cfg(feature = "enabled")]
mod systems;
#[cfg(feature = "enabled")]
mod utils;
#[cfg(feature = "enabled")]
use std::{any::type_name, collections::BTreeMap};
use std::{marker::PhantomData, path::PathBuf};
use bevy::{log::Level, prelude::*};
#[cfg(feature = "enabled")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "enabled")]
use systems::{log_component, log_event, log_message, register_event};
#[cfg(feature = "enabled")]
use utils::{deserialize_level, serialize_level, trigger_name};
pub mod prelude {
pub use super::{
EventSettings, LogEvent, LogEventsPlugin, LogEventsPluginSettings, LogMessagesSystems,
LoggedEventSettings,
};
}
pub struct LogEventsPlugin {
pub settings_path: PathBuf,
}
impl LogEventsPlugin {
pub fn new(settings_path: impl Into<PathBuf>) -> Self {
Self {
settings_path: settings_path.into(),
}
}
}
impl Default for LogEventsPlugin {
fn default() -> Self {
Self {
settings_path: "assets/log_settings.ron".into(),
}
}
}
#[cfg(not(feature = "enabled"))]
impl Plugin for LogEventsPlugin {
fn build(&self, _app: &mut App) {}
}
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
pub struct LogMessagesSystems;
#[derive(Clone, Copy)]
#[cfg_attr(feature = "enabled", derive(Deserialize, Serialize))]
pub struct EventSettings {
pub enabled: bool,
pub pretty: bool,
#[cfg_attr(
feature = "enabled",
serde(
serialize_with = "serialize_level",
deserialize_with = "deserialize_level"
)
)]
pub level: Level,
}
impl Default for EventSettings {
fn default() -> Self {
Self {
enabled: true,
pretty: true,
level: Level::INFO,
}
}
}
#[derive(Resource)]
pub struct LogEventsPluginSettings {
pub enabled: bool,
pub show_window: bool,
#[cfg(feature = "enabled")]
saved_settings: PathBuf,
#[cfg(feature = "enabled")]
previous_settings: BTreeMap<String, EventSettings>,
}
#[derive(Resource, Deref, DerefMut)]
pub struct LoggedEventSettings<E, C = ()> {
#[deref]
pub settings: EventSettings,
_phantom: PhantomData<(E, C)>,
}
impl<E, C> Default for LoggedEventSettings<E, C> {
fn default() -> Self {
Self {
settings: EventSettings::default(),
_phantom: PhantomData,
}
}
}
pub trait LogEvent {
fn log_message<M>(&mut self) -> &mut Self
where
M: Message + std::fmt::Debug;
fn add_and_log_message<M>(&mut self) -> &mut Self
where
M: Message + std::fmt::Debug;
fn log_event<E>(&mut self) -> &mut Self
where
E: Event + std::fmt::Debug;
fn log_trigger<E, C>(&mut self) -> &mut Self
where
E: EntityEvent,
C: Component + std::fmt::Debug;
fn log_component_lifecycle<C>(&mut self) -> &mut Self
where
C: Component + std::fmt::Debug,
{
self.log_trigger::<Add, C>()
.log_trigger::<Insert, C>()
.log_trigger::<Replace, C>()
.log_trigger::<Remove, C>()
.log_trigger::<Despawn, C>()
}
}
impl LogEvent for App {
fn log_message<M>(&mut self) -> &mut Self
where
M: Message + std::fmt::Debug,
{
#[cfg(feature = "enabled")]
{
let name = type_name::<M>();
if register_event::<LoggedEventSettings<M>>(self.world_mut(), name.to_string()) {
self.add_systems(Last, log_message::<M>.in_set(LogMessagesSystems));
} else {
warn!("You tried to use log_message twice for the message \"{name}\"");
}
}
self
}
fn add_and_log_message<M>(&mut self) -> &mut Self
where
M: Message + std::fmt::Debug,
{
self.add_message::<M>().log_message::<M>()
}
fn log_event<E>(&mut self) -> &mut Self
where
E: Event + std::fmt::Debug,
{
#[cfg(feature = "enabled")]
{
let name = type_name::<E>();
if register_event::<LoggedEventSettings<E>>(self.world_mut(), name.to_string()) {
let observer = Observer::new(log_event::<E>);
self.world_mut()
.spawn((observer, Name::new(format!("LogEvent<{name}>"))));
} else {
warn!("You tried to use log_event twice for the event \"{name}\"");
}
}
self
}
fn log_trigger<E, C>(&mut self) -> &mut Self
where
E: EntityEvent,
C: Component + std::fmt::Debug,
{
#[cfg(feature = "enabled")]
{
let name = trigger_name::<E, C>();
if register_event::<LoggedEventSettings<E, C>>(self.world_mut(), name.to_string()) {
let observer = Observer::new(log_component::<E, C>);
self.world_mut()
.spawn((observer, Name::new(format!("Log{name}"))));
} else {
warn!("You tried to use log_trigger twice for the trigger \"{name}\"");
}
}
self
}
}