mod action;
pub mod subtype;
use subtype::Alarm;
use subtype::Collision;
use subtype::Draw;
use subtype::Gesture;
use subtype::Key;
use subtype::Mouse;
use subtype::Other;
use subtype::Step;
pub use self::action::Action;
use crate::gml::GMCode;
use crate::prelude::*;
use crate::util::assert;
use crate::util::fmt::typename;
use crate::wad::deserialize::reader::DataReader;
use crate::wad::elements::GMElement;
use crate::wad::serialize::builder::DataBuilder;
#[derive(Debug, Clone, PartialEq)]
pub struct Events {
pub create_handlers: Vec<Action>,
pub destroy_handlers: Vec<Action>,
pub alarm: Event<Alarm>,
pub step: Event<Step>,
pub collision: Event<Collision>,
pub keyboard: Event<Key>,
pub mouse: Event<Mouse>,
pub other: Event<Other>,
pub draw: Event<Draw>,
pub key_press: Event<Key>,
pub key_release: Event<Key>,
pub trigger_handlers: Vec<Action>,
pub cleanup_handlers: Vec<Action>,
pub gesture: Event<Gesture>,
pub pre_create_handlers: Vec<Action>,
}
impl GMElement for Events {
fn deserialize(reader: &mut DataReader) -> Result<Self> {
let pointers: Vec<u32> = reader
.read_simple_list()
.context("reading outer event pointer list")?;
let count = pointers.len() as u32;
let expected_count = type_count_by_wad(reader.general_info.wad_version);
let ctx = || {
format!(
"validating event type count for game with GM Version {} and WAD Version {}",
reader.general_info.version, reader.general_info.wad_version,
)
};
reader
.assert_int(count, expected_count, "event type count")
.with_context(ctx)?;
let create: Vec<SubEvent<()>> = reader.read_pointer_list()?;
let destroy: Vec<SubEvent<()>> = reader.read_pointer_list()?;
let alarm: Vec<SubEvent<Alarm>> = reader.read_pointer_list()?;
let step: Vec<SubEvent<Step>> = reader.read_pointer_list()?;
let collision: Vec<SubEvent<Collision>> = reader.read_pointer_list()?;
let keyboard: Vec<SubEvent<Key>> = reader.read_pointer_list()?;
let mouse: Vec<SubEvent<Mouse>> = reader.read_pointer_list()?;
let other: Vec<SubEvent<Other>> = reader.read_pointer_list()?;
let draw: Vec<SubEvent<Draw>> = reader.read_pointer_list()?;
let key_press: Vec<SubEvent<Key>> = reader.read_pointer_list()?;
let key_release: Vec<SubEvent<Key>> = reader.read_pointer_list()?;
let trigger: Vec<SubEvent<()>> = reader.read_pointer_list()?;
let mut cleanup: Vec<SubEvent<()>> = Vec::new();
let mut gesture: Vec<SubEvent<Gesture>> = Vec::new();
let mut pre_create: Vec<SubEvent<()>> = Vec::new();
if count > 12 {
cleanup = reader.read_pointer_list()?;
}
if count > 13 {
gesture = reader.read_pointer_list()?;
}
if count > 14 {
pre_create = reader.read_pointer_list()?;
}
Ok(Self {
create_handlers: dedup_events_no_subtype(create),
destroy_handlers: dedup_events_no_subtype(destroy),
alarm: Event::new(alarm),
step: Event::new(step),
collision: Event::new(collision),
keyboard: Event::new(keyboard),
mouse: Event::new(mouse),
other: Event::new(other),
draw: Event::new(draw),
key_press: Event::new(key_press),
key_release: Event::new(key_release),
trigger_handlers: dedup_events_no_subtype(trigger),
cleanup_handlers: dedup_events_no_subtype(cleanup),
gesture: Event::new(gesture),
pre_create_handlers: dedup_events_no_subtype(pre_create),
})
}
fn serialize(&self, builder: &mut DataBuilder) -> Result<()> {
let count: u32 = type_count_by_wad(builder.wad_version());
builder.write_u32(count);
let pointer_list_pos = builder.len();
for _ in 0..count {
builder.write_u32(0xDEAD_C0DE);
}
let create = vec![SubEvent::unit(self.create_handlers.clone())];
let destroy = vec![SubEvent::unit(self.destroy_handlers.clone())];
let alarm = &self.alarm.0;
let step = &self.step.0;
let collision = &self.collision.0;
let keyboard = &self.keyboard.0;
let mouse = &self.mouse.0;
let other = &self.other.0;
let draw = &self.draw.0;
let key_press = &self.key_press.0;
let key_release = &self.key_release.0;
let trigger = vec![SubEvent::unit(self.trigger_handlers.clone())];
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 0)?;
builder.write_pointer_list(&create)?;
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 1)?;
builder.write_pointer_list(&destroy)?;
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 2)?;
builder.write_pointer_list(alarm)?;
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 3)?;
builder.write_pointer_list(step)?;
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 4)?;
builder.write_pointer_list(collision)?;
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 5)?;
builder.write_pointer_list(keyboard)?;
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 6)?;
builder.write_pointer_list(mouse)?;
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 7)?;
builder.write_pointer_list(other)?;
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 8)?;
builder.write_pointer_list(draw)?;
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 9)?;
builder.write_pointer_list(key_press)?;
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 10)?;
builder.write_pointer_list(key_release)?;
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 11)?;
builder.write_pointer_list(&trigger)?;
if count > 12 {
let cleanup = vec![SubEvent::unit(self.cleanup_handlers.clone())];
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 12)?;
builder.write_pointer_list(&cleanup)?;
}
if count > 13 {
let gesture = &self.gesture.0;
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 13)?;
builder.write_pointer_list(gesture)?;
}
if count > 14 {
let pre_create = vec![SubEvent::unit(self.pre_create_handlers.clone())];
builder.overwrite_pointer_with_cur_pos(pointer_list_pos, 14)?;
builder.write_pointer_list(&pre_create)?;
}
Ok(())
}
}
#[must_use]
const fn type_count_by_wad(wad_version: u8) -> u32 {
if wad_version < 16 {
return 12;
}
if wad_version == 16 {
return 13;
}
15
}
fn dedup_events<T: EventSubtype>(events: &mut Vec<SubEvent<T>>) -> bool {
let mut i: usize = 0;
let mut changed: bool = false;
while i < events.len() {
let sub: T = events[i].subtype;
if let Some(j) = events[i + 1..].iter().position(|e| e.subtype == sub) {
let dupe = events.remove(i + 1 + j);
events[i].actions.extend(dupe.actions);
changed = true;
} else {
i += 1;
}
}
changed
}
#[must_use]
fn dedup_events_no_subtype(events: Vec<SubEvent<()>>) -> Vec<Action> {
events.into_iter().flat_map(|e| e.actions).collect()
}
pub trait EventSubtype: std::fmt::Debug + Copy + PartialEq {
fn parse(subtype: u32) -> Result<Self>;
fn build(self) -> u32;
}
impl EventSubtype for () {
fn parse(subtype: u32) -> Result<Self> {
assert::int(subtype, 0, "Event Subtype for event with no data")?;
Ok(())
}
fn build(self) -> u32 {
0
}
}
#[derive(Debug, Clone, PartialEq)]
struct SubEvent<T: EventSubtype> {
pub subtype: T,
pub actions: Vec<Action>,
}
impl<T: EventSubtype> SubEvent<T> {
#[must_use]
const fn new(subtype: T) -> Self {
Self { subtype, actions: Vec::new() }
}
}
impl SubEvent<()> {
#[must_use]
const fn unit(actions: Vec<Action>) -> Self {
Self { subtype: (), actions }
}
}
impl<T: EventSubtype> GMElement for SubEvent<T> {
fn deserialize(reader: &mut DataReader) -> Result<Self> {
let subtype: u32 = reader.read_u32()?;
let subtype: T = T::parse(subtype)
.with_context(|| format!("parsing Event subtype {}", typename::<T>()))?;
let mut actions: Vec<Action> = reader.read_pointer_list()?;
actions.retain(|x| x.__exists);
Ok(Self { subtype, actions })
}
fn serialize(&self, builder: &mut DataBuilder) -> Result<()> {
let subtype: u32 = self.subtype.build();
builder.write_u32(subtype);
builder.write_pointer_list(&self.actions)?;
Ok(())
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Event<T: EventSubtype>(Vec<SubEvent<T>>);
impl<T: EventSubtype> Event<T> {
#[must_use]
fn new(mut subevents: Vec<SubEvent<T>>) -> Self {
dedup_events(&mut subevents);
Self(subevents)
}
pub fn get_handlers_for(&self, subtype: T) -> Result<&Vec<Action>> {
if let Some(sub_event) = self.0.iter().find(|e| e.subtype == subtype) {
return Ok(&sub_event.actions);
}
Err(err!(
"Could not find any event handlers for subtype {subtype:?}"
))
}
#[must_use = "if you only want to make sure a handler exists, use `make_handler_for()`"]
pub fn handlers_for(&mut self, subtype: T) -> &mut Vec<Action> {
for (idx, event) in self.0.iter().enumerate() {
if event.subtype == subtype {
let event = &mut self.0[idx];
return &mut event.actions;
}
}
let idx: usize = self.0.len();
self.0.push(SubEvent::new(subtype));
&mut self.0[idx].actions
}
pub fn make_handler_for(&mut self, subtype: T, code: GMRef<GMCode>) {
let actions = self.handlers_for(subtype);
actions.push(Action::new(code));
}
pub fn all_actions(&self) -> impl Iterator<Item = &Action> {
self.0.iter().flat_map(|e| &e.actions)
}
pub fn all_actions_mut(&mut self) -> impl Iterator<Item = &mut Action> {
self.0.iter_mut().flat_map(|e| &mut e.actions)
}
}