use crate::ecs::world::{Entity, World};
pub fn entity_schema() -> enum2schema::serde_json::Value {
enum2schema::serde_json::json!({
"type": "object",
"properties": {
"id": { "type": "integer" },
"generation": { "type": "integer" }
},
"required": ["id", "generation"]
})
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, enum2schema::Schema)]
pub enum Event {
Collision {
#[schema(with = crate::ecs::event::entity_schema)]
a: Entity,
#[schema(with = crate::ecs::event::entity_schema)]
b: Entity,
sensor: bool,
started: bool,
},
Despawned {
#[schema(with = crate::ecs::event::entity_schema)]
entity: Entity,
},
AnimationFinished {
#[schema(with = crate::ecs::event::entity_schema)]
entity: Entity,
},
AnimationEvent {
#[schema(with = crate::ecs::event::entity_schema)]
entity: Entity,
name: String,
},
NavigationArrived {
#[schema(with = crate::ecs::event::entity_schema)]
entity: Entity,
},
}
#[derive(Debug, Clone)]
pub struct JournalEntry {
pub cycle: u64,
pub event: Event,
}
const JOURNAL_CAPACITY: usize = 4096;
#[derive(Default)]
pub struct Events {
current: Vec<Event>,
pending: Vec<Event>,
journal: Vec<JournalEntry>,
journal_enabled: bool,
cycle: u64,
}
pub fn emit_event(world: &mut World, event: Event) {
let events = &mut world.resources.events;
if events.journal_enabled {
record(
events,
JournalEntry {
cycle: events.cycle,
event: event.clone(),
},
);
}
events.pending.push(event);
}
pub fn events(world: &World) -> &[Event] {
&world.resources.events.current
}
pub fn cycle(world: &World) -> u64 {
world.resources.events.cycle
}
pub fn journal_enabled(world: &World) -> bool {
world.resources.events.journal_enabled
}
pub fn set_journal_enabled(world: &mut World, enabled: bool) {
world.resources.events.journal_enabled = enabled;
if !enabled {
world.resources.events.journal.clear();
}
}
pub fn drain_journal(world: &mut World) -> Vec<JournalEntry> {
std::mem::take(&mut world.resources.events.journal)
}
fn record(events: &mut Events, entry: JournalEntry) {
if events.journal.len() >= JOURNAL_CAPACITY {
events.journal.remove(0);
}
events.journal.push(entry);
}
pub fn swap_events_system(world: &mut World) {
let events = &mut world.resources.events;
events.cycle = events.cycle.wrapping_add(1);
events.current.clear();
std::mem::swap(&mut events.current, &mut events.pending);
}
#[cfg(feature = "physics")]
pub fn emit_collision_events_system(world: &mut World) {
use crate::ecs::physics::events::CollisionEventKind;
let collisions =
crate::ecs::physics::resources::physics_world_collision_events(&world.resources.physics)
.to_vec();
for collision in collisions {
emit_event(
world,
Event::Collision {
a: collision.entity_a,
b: collision.entity_b,
sensor: collision.is_sensor,
started: collision.kind == CollisionEventKind::Started,
},
);
}
}