#![warn(missing_docs)]
#![allow(deprecated)]
#[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\" will be updated to Bevy 0.15."
);
#[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::*, state::state::FreelyMutableState};
#[cfg(feature = "enabled")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "enabled")]
use systems::{log_component, log_event, log_triggered, register_event, EventKind};
#[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) {}
}
#[deprecated(
since = "0.4.2",
note = "This set is no longer used and will be removed in a future version. \
LoggedEventSettings can now be accessed whenever LogEvent trait functions are used."
)]
#[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,
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_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;
fn log_component_hooks<C>(&mut self) -> &mut Self
where
C: Component + std::fmt::Debug,
{
self.log_trigger::<OnAdd, C>()
.log_trigger::<OnInsert, C>()
.log_trigger::<OnReplace, C>()
.log_trigger::<OnRemove, C>()
}
}
impl LogEvent for App {
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(),
EventKind::EVENT,
) {
self.add_systems(Last, log_event::<E>.in_set(LogEventsSet));
} else {
warn!(
"You tried to use log_event twice for the event \"{}\"",
name
);
}
}
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")]
{
let name = type_name::<E>();
if register_event::<LoggedEventSettings<E>>(
self.world_mut(),
name.to_string(),
EventKind::TRIGGER,
) {
let observer = Observer::new(log_triggered::<E>);
self.world_mut()
.spawn((observer, Name::new(format!("LogTrigger<{}>", name))));
} else {
warn!(
"You tried to use log_triggered twice for the event \"{}\"",
name
);
}
}
self
}
fn log_trigger<E, C>(&mut self) -> &mut Self
where
E: Event,
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(),
EventKind::TRIGGER,
) {
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
}
}