use std::{
ffi::CString,
path::{Path, PathBuf},
ptr::null,
};
use crate::{RaylibHandle, ffi};
#[derive(Debug, Clone)]
pub struct AutomationEventIter<'a> {
iter: std::slice::Iter<'a, ffi::AutomationEvent>,
}
impl AutomationEventIter<'_> {
#[must_use]
unsafe fn new(events: *mut ffi::AutomationEvent, count: u32) -> Self {
assert!(!events.is_null(), "automation event array cannot be null");
assert!(
events.is_aligned(),
"automation event array must be aligned"
);
let iter = unsafe { std::slice::from_raw_parts(events, count as usize) }.iter();
Self { iter }
}
fn func(e: &ffi::AutomationEvent) -> AutomationEvent {
AutomationEvent(*e)
}
}
impl Iterator for AutomationEventIter<'_> {
type Item = AutomationEvent;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(Self::func)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
#[inline]
fn count(self) -> usize {
self.len()
}
fn last(self) -> Option<Self::Item> {
self.iter.last().map(Self::func)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.iter.nth(n).map(Self::func)
}
}
impl DoubleEndedIterator for AutomationEventIter<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(Self::func)
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.iter.nth_back(n).map(Self::func)
}
}
impl ExactSizeIterator for AutomationEventIter<'_> {
#[inline]
fn len(&self) -> usize {
self.iter.len()
}
}
make_thin_wrapper!(
AutomationEventList,
ffi::AutomationEventList,
ffi::UnloadAutomationEventList,
false
);
impl AutomationEventList {
#[inline]
#[must_use]
pub const fn count(&self) -> u32 {
self.0.count
}
#[inline]
#[must_use]
pub const fn capacity(&self) -> u32 {
self.0.capacity
}
#[must_use]
pub fn events(&self) -> Vec<AutomationEvent> {
unsafe { std::slice::from_raw_parts(self.0.events, self.count() as usize) }
.iter()
.map(|f| AutomationEvent(*f))
.collect()
}
#[must_use]
pub fn iter(&self) -> AutomationEventIter<'_> {
unsafe { AutomationEventIter::new(self.0.events, self.count()) }
}
pub fn export(&self, file_name: impl AsRef<Path>) -> bool {
let c_str = CString::new(file_name.as_ref().to_string_lossy().as_bytes()).unwrap();
unsafe { ffi::ExportAutomationEventList(self.0, c_str.as_ptr()) }
}
}
make_thin_wrapper!(
AutomationEvent,
ffi::AutomationEvent,
unload_automation_event,
false
);
impl AutomationEvent {
#[inline]
#[must_use]
pub const fn frame(&self) -> u32 {
self.0.frame
}
#[inline]
#[must_use]
pub const fn get_type(&self) -> u32 {
self.0.type_
}
#[inline]
#[must_use]
pub const fn params(&self) -> [i32; 4] {
self.0.params
}
}
impl AutomationEvent {
#[inline]
pub fn play(&self) {
unsafe { ffi::PlayAutomationEvent(self.0) }
}
}
fn unload_automation_event(_s: ffi::AutomationEvent) {
}
impl RaylibHandle {
#[must_use]
pub fn load_automation_event_list(&self, file_name: Option<PathBuf>) -> AutomationEventList {
match file_name {
Some(a) => {
let c_str = CString::new(a.to_string_lossy().as_bytes()).unwrap();
AutomationEventList(unsafe { ffi::LoadAutomationEventList(c_str.as_ptr()) })
}
None => AutomationEventList(unsafe { ffi::LoadAutomationEventList(null()) }),
}
}
#[inline]
pub fn set_automation_event_list(&self, l: &mut AutomationEventList) {
unsafe {
ffi::SetAutomationEventList(&mut l.0 as *mut ffi::AutomationEventList);
}
}
#[inline]
pub fn set_automation_event_base_frame(&self, b: i32) {
unsafe { ffi::SetAutomationEventBaseFrame(b) };
}
#[inline]
pub fn start_automation_event_recording(&self) {
unsafe { ffi::StartAutomationEventRecording() };
}
#[inline]
pub fn stop_automation_event_recording(&self) {
unsafe { ffi::StopAutomationEventRecording() };
}
}