use crate::*;
use bitflags::bitflags;
bitflags! {
pub struct EventInFlags: ae_sys::A_long {
const NONE = ae_sys::PF_EI_NONE as ae_sys::A_long;
const DONT_DRAW = ae_sys::PF_EI_DONT_DRAW as ae_sys::A_long;
}
}
bitflags! {
pub struct EventOutFlags: ae_sys::A_long {
const NONE = ae_sys::PF_EO_NONE as ae_sys::A_long;
const HANDLED_EVENT = ae_sys::PF_EO_HANDLED_EVENT as ae_sys::A_long;
const ALWAYS_UPDATE = ae_sys::PF_EO_ALWAYS_UPDATE as ae_sys::A_long;
const NEVER_UPDATE = ae_sys::PF_EO_NEVER_UPDATE as ae_sys::A_long;
const UPDATE_NOW = ae_sys::PF_EO_UPDATE_NOW as ae_sys::A_long;
}
}
define_struct_wrapper!(ClickEventInfo, PF_DoClickEventInfo);
impl ClickEventInfo {
pub fn screen_point(&self) -> Point {
self.as_ref().screen_point.into()
}
pub fn num_clicks(&self) -> u32 {
self.as_ref().num_clicks as _
}
}
impl std::fmt::Debug for ClickEventInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("ClickEventInfo")
}
}
define_struct_wrapper!(DrawEventInfo, PF_DrawEventInfo);
impl std::fmt::Debug for DrawEventInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("DrawEventInfo")
}
}
define_struct_wrapper!(KeyDownEventInfo, PF_KeyDownEvent);
impl std::fmt::Debug for KeyDownEventInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("KeyDownEventInfo")
}
}
define_struct_wrapper!(AdjustCursorEventInfo, PF_AdjustCursorEventInfo);
impl std::fmt::Debug for AdjustCursorEventInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("AdjustCursorEventInfo")
}
}
#[derive(Clone, Copy, Debug)]
pub enum Event {
None,
NewContext,
Activate,
Click(ClickEventInfo),
Drag(ClickEventInfo),
Draw(DrawEventInfo),
Deactivate,
CloseContext,
Idle,
AdjustCursor(AdjustCursorEventInfo), Keydown(KeyDownEventInfo), MouseExited, }
define_struct_wrapper!(EventExtra, PF_EventExtra);
impl std::fmt::Debug for EventExtra {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut dbg = f.debug_struct("EventExtra");
dbg.field("event", &self.event());
dbg.field("window_type", &self.window_type());
dbg.field("param_index", &self.param_index());
dbg.field("effect_area", &self.effect_area());
dbg.field("current_frame", &self.current_frame());
dbg.field("param_title_frame", &self.param_title_frame());
dbg.field("horiz_offset", &self.horiz_offset());
if [ae_sys::PF_Event_DO_CLICK, ae_sys::PF_Event_DRAG, ae_sys::PF_Event_ADJUST_CURSOR].contains(&self.as_ref().e_type) {
dbg.field("modifiers", &self.modifiers());
}
if [ae_sys::PF_Event_DO_CLICK, ae_sys::PF_Event_DRAG].contains(&self.as_ref().e_type) {
dbg.field("last_time", &self.last_time());
}
dbg.finish()
}
}
define_enum! {
ae_sys::PF_EffectArea,
EffectArea {
Mone = ae_sys::PF_EA_NONE,
Title = ae_sys::PF_EA_PARAM_TITLE,
Control = ae_sys::PF_EA_CONTROL,
}
}
define_enum! {
ae_sys::PF_WindowType,
WindowType {
Comp = ae_sys::PF_Window_COMP,
Layer = ae_sys::PF_Window_LAYER,
Effect = ae_sys::PF_Window_EFFECT,
}
}
impl EventExtra {
pub fn context_handle(&self) -> ContextHandle {
ContextHandle::from_raw(self.as_ref().contextH)
}
pub fn event(&self) -> Event {
match self.as_ref().e_type {
ae_sys::PF_Event_NEW_CONTEXT => Event::NewContext,
ae_sys::PF_Event_ACTIVATE => Event::Activate,
ae_sys::PF_Event_DO_CLICK => {
Event::Click(ClickEventInfo::from_raw(unsafe { &self.as_ref().u.do_click as *const _ as *mut _ }))
}
ae_sys::PF_Event_DRAG => {
Event::Drag(ClickEventInfo::from_raw(unsafe { &self.as_ref().u.do_click as *const _ as *mut _ }))
}
ae_sys::PF_Event_DRAW => Event::Draw(DrawEventInfo::from_raw(unsafe { &self.as_ref().u.draw as *const _ as *mut _ })),
ae_sys::PF_Event_DEACTIVATE => Event::Deactivate,
ae_sys::PF_Event_CLOSE_CONTEXT => Event::CloseContext,
ae_sys::PF_Event_IDLE => Event::Idle,
ae_sys::PF_Event_ADJUST_CURSOR => {
Event::AdjustCursor(AdjustCursorEventInfo::from_raw(unsafe {
&self.as_ref().u.adjust_cursor as *const _ as *mut _
}))
}
ae_sys::PF_Event_KEYDOWN => {
Event::Keydown(KeyDownEventInfo::from_raw(unsafe { &self.as_ref().u.key_down as *const _ as *mut _ }))
}
ae_sys::PF_Event_MOUSE_EXITED => Event::MouseExited,
_ => unreachable!(),
}
}
pub fn set_cursor(&mut self, cursor: CursorType) {
self.as_mut().u.adjust_cursor.set_cursor = cursor.into();
}
pub fn window_type(&self) -> WindowType {
unsafe { **self.as_ref().contextH }.w_type.into()
}
pub fn set_event_out_flags(&mut self, flags: EventOutFlags) {
self.as_mut().evt_out_flags = flags.bits() as _;
}
pub fn param_index(&self) -> usize {
self.as_ref().effect_win.index as _
}
pub fn effect_area(&self) -> EffectArea {
self.as_ref().effect_win.area.into()
}
pub fn current_frame(&self) -> Rect {
self.as_ref().effect_win.current_frame.into()
}
pub fn param_title_frame(&self) -> Rect {
self.as_ref().effect_win.param_title_frame.into()
}
pub fn horiz_offset(&self) -> i32 {
self.as_ref().effect_win.horiz_offset
}
pub fn modifiers(&self) -> Modifiers {
debug_assert!(
[ae_sys::PF_Event_DO_CLICK, ae_sys::PF_Event_DRAG, ae_sys::PF_Event_ADJUST_CURSOR].contains(&self.as_ref().e_type),
"The modifiers() method is only valid if event() is Click, Drag or AdjustCursor."
);
if self.as_ref().e_type == ae_sys::PF_Event_ADJUST_CURSOR {
return unsafe { Modifiers::from_bits_truncate(self.as_ref().u.adjust_cursor.modifiers as _) }
}
unsafe { Modifiers::from_bits_truncate(self.as_ref().u.do_click.modifiers as _) }
}
pub fn set_continue_refcon(&mut self, index: usize, value: ae_sys::A_intptr_t) {
debug_assert!(
[ae_sys::PF_Event_DO_CLICK, ae_sys::PF_Event_DRAG].contains(&self.as_ref().e_type),
"The continue_refcon() method is only valid if event() is Click or Drag."
);
debug_assert!(index < 4);
unsafe {
self.as_mut().u.do_click.continue_refcon[index] = value;
}
}
pub fn continue_refcon(&self, index: usize) -> ae_sys::A_intptr_t {
debug_assert!(
[ae_sys::PF_Event_DO_CLICK, ae_sys::PF_Event_DRAG].contains(&self.as_ref().e_type),
"The get_continue_refcon() method is only valid if event() is Click or Drag."
);
debug_assert!(index < 4);
unsafe { self.as_ref().u.do_click.continue_refcon[index] }
}
pub fn send_drag(&mut self) -> bool {
debug_assert!(
[ae_sys::PF_Event_DO_CLICK, ae_sys::PF_Event_DRAG].contains(&self.as_ref().e_type),
"The send_drag() method is only valid if event() is Click or Drag."
);
unsafe { self.as_mut().u.do_click.send_drag != 0 }
}
pub fn set_send_drag(&mut self, send: bool) {
debug_assert!(
[ae_sys::PF_Event_DO_CLICK, ae_sys::PF_Event_DRAG].contains(&self.as_ref().e_type),
"The send_drag() method is only valid if event() is Click or Drag."
);
self.as_mut().u.do_click.send_drag = send as _;
}
pub fn last_time(&self) -> bool {
debug_assert!(
[ae_sys::PF_Event_DO_CLICK, ae_sys::PF_Event_DRAG].contains(&self.as_ref().e_type),
"The last_time() method is only valid if event() is Click or Drag."
);
unsafe { self.as_ref().u.do_click.last_time != 0 }
}
pub fn screen_point(&self) -> Point {
match self.as_ref().e_type {
ae_sys::PF_Event_DO_CLICK | ae_sys::PF_Event_DRAG => {
unsafe { self.as_ref().u.do_click.screen_point.into() }
}
ae_sys::PF_Event_ADJUST_CURSOR => {
unsafe { self.as_ref().u.adjust_cursor.screen_point.into() }
}
ae_sys::PF_Event_KEYDOWN => {
unsafe { self.as_ref().u.key_down.screen_point.into() }
}
_ => {
panic!("The screen_point() method is only valid if event() is Click, Drag, AdjustCursor or Keydown.")
}
}
}
pub fn in_flags(&self) -> EventInFlags {
EventInFlags::from_bits_truncate(self.as_ref().evt_in_flags as _)
}
pub fn callbacks(&self) -> EventCallbacks<'_> {
EventCallbacks {
ptr: &self.as_ref().cbs,
ctx: self.as_ref().contextH
}
}
}
pub struct EventCallbacks<'a> {
ptr: &'a ae_sys::PF_EventCallbacks,
ctx: ae_sys::PF_ContextH
}
impl<'a> EventCallbacks<'a> {
pub fn layer_to_comp(&self, curr_time: i32, time_scale: u32, pt: &mut ae_sys::PF_FixedPoint) -> Result<(), Error> {
let ret = unsafe {
((*self.ptr).layer_to_comp.unwrap())((*self.ptr).refcon, self.ctx, curr_time, time_scale as _, pt)
};
match ret {
0 => Ok(()),
e => Err(Error::from(e))
}
}
pub fn comp_to_layer(&self, curr_time: i32, time_scale: u32, pt: &mut ae_sys::PF_FixedPoint) -> Result<(), Error> {
let ret = unsafe {
((*self.ptr).comp_to_layer.unwrap())((*self.ptr).refcon, self.ctx, curr_time, time_scale as _, pt)
};
match ret {
0 => Ok(()),
e => Err(Error::from(e))
}
}
pub fn source_to_frame(&self, pt: &mut ae_sys::PF_FixedPoint) -> Result<(), Error> {
let ret = unsafe {
((*self.ptr).source_to_frame.unwrap())((*self.ptr).refcon, self.ctx, pt)
};
match ret {
0 => Ok(()),
e => Err(Error::from(e))
}
}
pub fn frame_to_source(&self, pt: &mut ae_sys::PF_FixedPoint) -> Result<(), Error> {
let ret = unsafe {
((*self.ptr).frame_to_source.unwrap())((*self.ptr).refcon, self.ctx, pt)
};
match ret {
0 => Ok(()),
e => Err(Error::from(e))
}
}
pub fn comp2layer_xform(&self, curr_time: i32, time_scale: u32) -> Result<Option<Matrix3>, Error> {
let mut exists: ae_sys::A_long = 0;
let mut matrix: ae_sys::PF_FloatMatrix = unsafe { std::mem::zeroed() };
let ret = unsafe {
((*self.ptr).get_comp2layer_xform.unwrap())((*self.ptr).refcon, self.ctx, curr_time, time_scale as _, &mut exists, &mut matrix)
};
match ret {
0 => Ok(if exists == 1 { Some(unsafe { std::mem::transmute(matrix) }) } else { None }),
e => Err(Error::from(e))
}
}
pub fn layer2comp_xform(&self, curr_time: i32, time_scale: u32) -> Result<Matrix3, Error> {
let mut matrix: ae_sys::PF_FloatMatrix = unsafe { std::mem::zeroed() };
let ret = unsafe {
((*self.ptr).get_layer2comp_xform.unwrap())((*self.ptr).refcon, self.ctx, curr_time, time_scale as _, &mut matrix)
};
match ret {
0 => Ok(unsafe { std::mem::transmute(matrix) }),
e => Err(Error::from(e))
}
}
pub fn info_draw_color(&self, color: Pixel8) -> Result<(), Error> {
let ret = unsafe {
((*self.ptr).info_draw_color.unwrap())((*self.ptr).refcon, color)
};
match ret {
0 => Ok(()),
e => Err(Error::from(e))
}
}
pub fn info_draw_text(&self, text1: &str, text2: &str) -> Result<(), Error> {
let text1 = std::ffi::CString::new(text1).unwrap();
let text2 = std::ffi::CString::new(text2).unwrap();
let ret = unsafe {
((*self.ptr).info_draw_text.unwrap())((*self.ptr).refcon, text1.as_ptr(), text2.as_ptr())
};
match ret {
0 => Ok(()),
e => Err(Error::from(e))
}
}
}