#![warn(missing_docs)]
#[cfg(feature = "enabled")]
#[cfg(feature = "editor_window")]
compile_error!(
"The \"editor_window\" feature is not yet available for Bevy 0.15.
It will be made available again when the \"bevy_editor_pls\" has been updated to Bevy 0.15."
);
#[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::*, state::state::FreelyMutableState};
#[cfg(feature = "enabled")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "enabled")]
use systems::{log_component, log_event, log_triggered, register_component, register_event};
#[cfg(feature = "enabled")]
use utils::{deserialize_level, serialize_level, trigger_name};
pub mod prelude {
pub use super::{
EventSettings, LogEvent, LogEventsPlugin, LogEventsPluginSettings, LogEventsSet,
LoggedEventSettings, RegisterEventsSet,
};
}
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 RegisterEventsSet;
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
pub struct LogEventsSet;
#[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,
#[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_event<E>(&mut self) -> &mut Self
where
E: Event + std::fmt::Debug;
fn add_and_log_event<E>(&mut self) -> &mut Self
where
E: Event + std::fmt::Debug;
fn add_and_log_state_scoped_event<E>(&mut self, state: impl FreelyMutableState) -> &mut Self
where
E: Event + std::fmt::Debug;
fn log_triggered<E>(&mut self) -> &mut Self
where
E: Event + std::fmt::Debug;
fn log_trigger<E, C>(&mut self) -> &mut Self
where
E: Event,
C: Component + std::fmt::Debug;
}
impl LogEvent for App {
fn log_event<E>(&mut self) -> &mut Self
where
E: Event + std::fmt::Debug,
{
#[cfg(feature = "enabled")]
{
if !self.world().contains_resource::<LoggedEventSettings<E>>() {
self.insert_resource(LoggedEventSettings::<E>::default())
.add_systems(Startup, register_event::<E>.in_set(RegisterEventsSet))
.add_systems(Last, log_event::<E>.in_set(LogEventsSet));
} else {
warn!(
"You tried to use log_event twice for the event \"{}\"",
type_name::<E>()
);
}
}
self
}
fn add_and_log_event<E>(&mut self) -> &mut Self
where
E: Event + std::fmt::Debug,
{
self.add_event::<E>().log_event::<E>()
}
fn add_and_log_state_scoped_event<E>(&mut self, state: impl FreelyMutableState) -> &mut Self
where
E: Event + std::fmt::Debug,
{
self.add_state_scoped_event::<E>(state).log_event::<E>()
}
fn log_triggered<E>(&mut self) -> &mut Self
where
E: Event + std::fmt::Debug,
{
#[cfg(feature = "enabled")]
{
if !self.world().contains_resource::<LoggedEventSettings<E>>() {
let observer = Observer::new(log_triggered::<E>);
self.world_mut().spawn((
observer,
Name::new(format!("LogTrigger<{}>", type_name::<E>())),
));
self.insert_resource(LoggedEventSettings::<E>::default())
.add_systems(Startup, register_event::<E>.in_set(RegisterEventsSet));
} else {
warn!(
"You tried to use log_triggered twice for the event \"{}\"",
type_name::<E>()
);
}
}
self
}
fn log_trigger<E, C>(&mut self) -> &mut Self
where
E: Event,
C: Component + std::fmt::Debug,
{
#[cfg(feature = "enabled")]
{
if !self
.world()
.contains_resource::<LoggedEventSettings<E, C>>()
{
let observer = Observer::new(log_component::<E, C>);
self.world_mut().spawn((
observer,
Name::new(format!("Log{}", trigger_name::<E, C>())),
));
self.insert_resource(LoggedEventSettings::<E, C>::default())
.add_systems(
Startup,
register_component::<E, C>.in_set(RegisterEventsSet),
);
} else {
warn!(
"You tried to use log_trigger twice for the trigger \"{}\"",
trigger_name::<E, C>()
);
}
}
self
}
}