#![crate_name = "input"]
#![deny(missing_docs)]
#![deny(missing_copy_implementations)]
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate viewport;
use std::fmt;
use std::any::Any;
use std::sync::Arc;
use std::path::PathBuf;
use std::cmp::Ordering;
pub use mouse::MouseButton;
pub use keyboard::Key;
pub use controller::{ControllerAxisArgs, ControllerButton, ControllerHat};
pub mod controller;
pub mod keyboard;
pub mod mouse;
pub use after_render::{AfterRenderArgs, AfterRenderEvent};
pub use close::{CloseArgs, CloseEvent};
pub use controller::ControllerAxisEvent;
pub use cursor::CursorEvent;
pub use focus::FocusEvent;
pub use generic_event::GenericEvent;
pub use idle::{IdleArgs, IdleEvent};
pub use mouse::{MouseCursorEvent, MouseRelativeEvent, MouseScrollEvent};
pub use button::{ButtonState, ButtonArgs, ButtonEvent, PressEvent, ReleaseEvent};
pub use resize::{ResizeArgs, ResizeEvent};
pub use render::{RenderArgs, RenderEvent};
pub use text::TextEvent;
pub use touch::{Touch, TouchArgs, TouchEvent};
pub use update::{UpdateArgs, UpdateEvent};
use event_id::EventId;
pub mod event_id;
pub mod generic_event;
mod after_render;
mod button;
mod close;
mod cursor;
mod focus;
mod idle;
mod render;
mod resize;
mod text;
mod touch;
mod update;
pub type TimeStamp = u32;
#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, PartialOrd, Ord, Eq, Hash, Debug)]
pub enum Button {
Keyboard(Key),
Mouse(MouseButton),
Controller(ControllerButton),
Hat(ControllerHat),
}
#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, PartialOrd, Debug)]
pub enum Motion {
MouseCursor([f64; 2]),
MouseRelative([f64; 2]),
MouseScroll([f64; 2]),
ControllerAxis(ControllerAxisArgs),
Touch(TouchArgs),
}
#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum HatState {
Centered,
Up,
Right,
Down,
Left,
RightUp,
RightDown,
LeftUp,
LeftDown,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, Hash)]
pub enum FileDrag {
Hover(PathBuf),
Drop(PathBuf),
Cancel,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Deserialize, Serialize)]
pub enum Input {
Button(ButtonArgs),
Move(Motion),
Text(String),
Resize(ResizeArgs),
Focus(bool),
Cursor(bool),
FileDrag(FileDrag),
Close(CloseArgs),
}
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Deserialize, Serialize)]
pub enum Loop {
Render(RenderArgs),
AfterRender(AfterRenderArgs),
Update(UpdateArgs),
Idle(IdleArgs),
}
#[derive(Clone)]
pub enum Event {
Input(Input, Option<TimeStamp>),
Loop(Loop),
Custom(EventId, Arc<dyn Any + Send + Sync>, Option<TimeStamp>),
}
impl fmt::Debug for Event {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Event::Input(ref input, _) => write!(f, "{:?}", input),
Event::Loop(ref l) => write!(f, "{:?}", l),
Event::Custom(ref id, _, _) => write!(f, "Custom({:?}, _)", id),
}
}
}
impl PartialEq for Event {
fn eq(&self, other: &Event) -> bool {
use Event::*;
match (self, other) {
(&Input(ref a, _), &Input(ref b, _)) => a == b,
(&Loop(ref a), &Loop(ref b)) => a == b,
(_, _) => false,
}
}
}
impl PartialOrd for Event {
fn partial_cmp(&self, other: &Event) -> Option<Ordering> {
use Event::*;
match (self, other) {
(&Input(ref a, _), &Input(ref b, _)) => a.partial_cmp(b),
(&Loop(ref a), &Loop(ref b)) => a.partial_cmp(b),
(&Custom(ref a_id, _, _), &Custom(ref b_id, _, _)) => {
let res = a_id.partial_cmp(b_id);
if res == Some(Ordering::Equal) {None}
else {res}
}
(&Input(_, _), _) => Some(Ordering::Less),
(_, &Input(_, _)) => Some(Ordering::Greater),
(&Loop(_), &Custom(_, _, _)) => Some(Ordering::Less),
(&Custom(_, _, _), &Loop(_)) => Some(Ordering::Greater),
}
}
}
impl From<Key> for Button {
fn from(key: Key) -> Self {
Button::Keyboard(key)
}
}
impl From<MouseButton> for Button {
fn from(btn: MouseButton) -> Self {
Button::Mouse(btn)
}
}
impl From<ControllerButton> for Button {
fn from(btn: ControllerButton) -> Self {
Button::Controller(btn)
}
}
impl From<ButtonArgs> for Input {
fn from(args: ButtonArgs) -> Self {
Input::Button(args)
}
}
impl From<ControllerAxisArgs> for Motion {
fn from(args: ControllerAxisArgs) -> Self {
Motion::ControllerAxis(args)
}
}
impl From<ControllerAxisArgs> for Input {
fn from(args: ControllerAxisArgs) -> Self {
Input::Move(Motion::ControllerAxis(args))
}
}
impl From<TouchArgs> for Motion {
fn from(args: TouchArgs) -> Self {
Motion::Touch(args)
}
}
impl From<TouchArgs> for Input {
fn from(args: TouchArgs) -> Self {
Input::Move(Motion::Touch(args))
}
}
impl From<Motion> for Input {
fn from(motion: Motion) -> Self {
Input::Move(motion)
}
}
impl From<RenderArgs> for Loop {
fn from(args: RenderArgs) -> Self {
Loop::Render(args)
}
}
impl From<RenderArgs> for Event {
fn from(args: RenderArgs) -> Self {
Event::Loop(Loop::Render(args))
}
}
impl From<AfterRenderArgs> for Loop {
fn from(args: AfterRenderArgs) -> Self {
Loop::AfterRender(args)
}
}
impl From<AfterRenderArgs> for Event {
fn from(args: AfterRenderArgs) -> Self {
Event::Loop(Loop::AfterRender(args))
}
}
impl From<UpdateArgs> for Loop {
fn from(args: UpdateArgs) -> Self {
Loop::Update(args)
}
}
impl From<UpdateArgs> for Event {
fn from(args: UpdateArgs) -> Self {
Event::Loop(Loop::Update(args))
}
}
impl From<IdleArgs> for Loop {
fn from(args: IdleArgs) -> Self {
Loop::Idle(args)
}
}
impl From<IdleArgs> for Event {
fn from(args: IdleArgs) -> Self {
Event::Loop(Loop::Idle(args))
}
}
impl From<CloseArgs> for Input {
fn from(args: CloseArgs) -> Self {
Input::Close(args)
}
}
impl<T> From<T> for Event
where Input: From<T>
{
fn from(args: T) -> Self {
Event::Input(args.into(), None)
}
}
impl<T> From<(T, Option<TimeStamp>)> for Event
where Input: From<T>
{
fn from(args: (T, Option<TimeStamp>)) -> Self {
Event::Input(args.0.into(), args.1)
}
}
impl From<Loop> for Event {
fn from(l: Loop) -> Self {
Event::Loop(l)
}
}
impl Into<Option<Input>> for Event {
fn into(self) -> Option<Input> {
if let Event::Input(input, _) = self {
Some(input)
} else {
None
}
}
}
impl Into<Option<Loop>> for Event {
fn into(self) -> Option<Loop> {
if let Event::Loop(l) = self {
Some(l)
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_input_sync_send() {
fn chk<T: Sync + Send>() {}
chk::<Input>();
chk::<Loop>();
chk::<Event>();
}
}