Skip to content

Commit

Permalink
Merge 9cc7f47 into d14ad5b
Browse files Browse the repository at this point in the history
  • Loading branch information
dragostis committed Apr 28, 2016
2 parents d14ad5b + 9cc7f47 commit 8e4c265
Show file tree
Hide file tree
Showing 15 changed files with 892 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ keywords = ["anima", "anima-engine", "game", "engine"]
license = "MPL-2.0"

[dependencies]
glium = "0.14.0"
mrusty = "0.4.3"
time = "0.1.35"

Expand Down
17 changes: 17 additions & 0 deletions src/input/input_event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Anima Engine. The quirky game engine
// Copyright (C) 2016 Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use glium::glutin::Event;

use super::IntermediateEvent;

/// A `trait` that contains all either `Raw` or `Intermediate` input events.
#[derive(Debug)]
pub enum InputEvent {
Raw(Event),
Intermediate(IntermediateEvent)
}
14 changes: 14 additions & 0 deletions src/input/intermediate/area/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Anima Engine. The quirky game engine
// Copyright (C) 2016 Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! A `mod` containing intermediate `InputEvent` generators that work on specific areas of the
//! screen.

mod selectable_area;

pub use self::selectable_area::SelectableArea;
pub use self::selectable_area::SpecialSelect;
136 changes: 136 additions & 0 deletions src/input/intermediate/area/selectable_area.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Anima Engine. The quirky game engine
// Copyright (C) 2016 Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::time::Duration;

use glium::glutin::MouseButton;

use super::super::Intermediate;
use super::super::super::{InputEvent, IntermediateEvent};

pub struct SelectableArea {
pub id: u32,
pub x: i32,
pub y: i32,
pub width: i32,
pub height: i32,
special: Option<SpecialSelect>,
pressed: Option<(i32, i32)>,
special_pressed: Option<(i32, i32)>
}

impl SelectableArea {
pub fn new(id: u32, x: i32, y: i32, width: i32, height: i32,
special: Option<SpecialSelect>) -> SelectableArea {
SelectableArea {
id: id,
x: x,
y: y,
width: width,
height: height,
special: special,
pressed: None,
special_pressed: None
}
}

fn inside(&self, x: i32, y: i32) -> bool {
let dx = x - self.x;
let dy = y - self.y;

0 <= dx && dx <= self.width &&
0 <= dy && dy <= self.height
}
}

impl<'a> Intermediate for &'a mut SelectableArea {
fn process(self, input: Vec<InputEvent>, dt: Duration) -> Vec<InputEvent> {
input.into_iter().filter_map(|event| {
match event {
InputEvent::Intermediate(
IntermediateEvent::CursorPressed(x, y, MouseButton::Left)
) if self.pressed.is_none() && self.inside(x, y) => {
self.pressed = Some((x, y));

Some(InputEvent::Intermediate(
IntermediateEvent::SelectablePressed(self.id, x, y)
))
},
InputEvent::Intermediate(
IntermediateEvent::CursorPressed(x, y, MouseButton::Left)
) if self.inside(x, y) => {
let old = self.pressed.unwrap();

if old == (x, y) {
Some(InputEvent::Intermediate(
IntermediateEvent::SelectablePressed(self.id, x, y)
))
} else {
Some(InputEvent::Intermediate(
IntermediateEvent::SelectableDragged(self.id, x, y)
))
}
},
InputEvent::Intermediate(
IntermediateEvent::CursorReleased(x, y, MouseButton::Left)
) if self.pressed.is_some() && self.inside(x, y) => {
self.pressed = None;

Some(InputEvent::Intermediate(
IntermediateEvent::SelectableReleased(self.id, x, y)
))
},
InputEvent::Intermediate(
IntermediateEvent::CursorPressed(x, y, button)
) if self.special_pressed.is_none() && self.inside(x, y) &&
self.special.is_some() && self.special.unwrap().button == button => {

self.special_pressed = Some((x, y));

Some(InputEvent::Intermediate(
IntermediateEvent::SelectableSpecialPressed(self.id, x, y)
))
},
InputEvent::Intermediate(
IntermediateEvent::CursorPressed(x, y, button)
) if self.inside(x, y) &&
self.special.is_some() && self.special.unwrap().button == button => {

let old = self.special_pressed.unwrap();

if old == (x, y) {
Some(InputEvent::Intermediate(
IntermediateEvent::SelectableSpecialPressed(self.id, x, y)
))
} else {
Some(InputEvent::Intermediate(
IntermediateEvent::SelectableSpecialDragged(self.id, x, y)
))
}
},
InputEvent::Intermediate(
IntermediateEvent::CursorReleased(x, y, button)
) if self.special_pressed.is_some() && self.inside(x, y) &&
self.special.is_some() && self.special.unwrap().button == button => {

self.special_pressed = None;

Some(InputEvent::Intermediate(
IntermediateEvent::SelectableSpecialReleased(self.id, x, y)
))
},
event => Some(event)
}
}).collect()
}
}

#[derive(Clone, Copy)]
pub struct SpecialSelect {
pub button: MouseButton,
pub touch_time: Duration
}
141 changes: 141 additions & 0 deletions src/input/intermediate/button.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// Anima Engine. The quirky game engine
// Copyright (C) 2016 Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::time::Duration;

use glium::glutin::{Event, MouseButton, TouchPhase};

use super::Intermediate;
use super::super::InputEvent;
use super::super::IntermediateEvent;

/// A `struct` that converts cursor events to button events.
pub struct Button {
pub id: u32,
pub x: i32,
pub y: i32,
pub width: i32,
pub height: i32,
pressed: bool
}

impl Button {
/// Creates a rectangular `Button` with ID `id`.
pub fn new(id: u32, x: i32, y: i32, width: i32, height: i32) -> Button {
Button {
id: id,
x: x,
y: y,
width: width,
height: height,
pressed: false
}
}

fn inside(&self, x: i32, y: i32) -> bool {
let dx = x - self.x;
let dy = y - self.y;

0 <= dx && dx <= self.width &&
0 <= dy && dy <= self.height
}
}

impl<'a> Intermediate for &'a mut Button {
fn process(self, input: Vec<InputEvent>, _dt: Duration) -> Vec<InputEvent> {
input.into_iter().filter_map(|event| {
match event {
InputEvent::Intermediate(
IntermediateEvent::CursorPressed(x, y, MouseButton::Left)
) if self.inside(x, y) => {
self.pressed = true;

Some(InputEvent::Intermediate(IntermediateEvent::ButtonPressed(self.id)))
},
InputEvent::Intermediate(
IntermediateEvent::CursorPressed(_, _, MouseButton::Left)
) if self.pressed => {
Some(InputEvent::Intermediate(IntermediateEvent::ButtonPressed(self.id)))
},
InputEvent::Intermediate(
IntermediateEvent::CursorReleased(x, y, MouseButton::Left)
) if self.pressed => {
self.pressed = false;

if self.inside(x, y) {
Some(InputEvent::Intermediate(IntermediateEvent::ButtonReleased(self.id)))
} else {
Some(InputEvent::Intermediate(IntermediateEvent::ButtonCanceled(self.id)))
}
},
InputEvent::Raw(Event::Touch(touch)) => {
match touch.phase {
TouchPhase::Started => {
if self.pressed {
Some(InputEvent::Intermediate(
IntermediateEvent::ButtonPressed(self.id))
)
} else {
let (x, y) = touch.location;
let (x, y) = (x as i32, y as i32);

if self.inside(x, y) {
self.pressed = true;

Some(InputEvent::Intermediate(
IntermediateEvent::ButtonPressed(self.id))
)
} else {
Some(InputEvent::Raw(Event::Touch(touch)))
}
}
},
TouchPhase::Moved => {
if self.pressed {
Some(InputEvent::Intermediate(
IntermediateEvent::ButtonPressed(self.id))
)
} else {
Some(InputEvent::Raw(Event::Touch(touch)))
}
},
TouchPhase::Ended => {
if self.pressed {
self.pressed = false;

let (x, y) = touch.location;
let (x, y) = (x as i32, y as i32);

if self.inside(x, y) {
Some(InputEvent::Intermediate(
IntermediateEvent::ButtonReleased(self.id))
)
} else {
Some(InputEvent::Intermediate(
IntermediateEvent::ButtonCanceled(self.id))
)
}
} else {
Some(InputEvent::Raw(Event::Touch(touch)))
}
},
TouchPhase::Cancelled => {
if self.pressed {
Some(InputEvent::Intermediate(
IntermediateEvent::ButtonCanceled(self.id))
)
} else {
Some(InputEvent::Raw(Event::Touch(touch)))
}
}
}
},
event => Some(event)
}
}).collect()
}
}
73 changes: 73 additions & 0 deletions src/input/intermediate/cursor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Anima Engine. The quirky game engine
// Copyright (C) 2016 Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::collections::HashMap;
use std::time::Duration;

use glium::glutin::{Event, ElementState, MouseButton};

use super::Intermediate;
use super::super::{InputEvent, IntermediateEvent};

/// A `struct` that converts raw mouse inputs to cursor events.
pub struct Cursor {
pub pos: Option<(i32, i32)>,
pub pressed : HashMap<MouseButton, bool>
}

impl Cursor {
/// Creates a `Cursor` without an initial position and without any pressed buttons.
pub fn new() -> Cursor {
Cursor {
pos: None,
pressed: HashMap::new()
}
}
}

impl<'a> Intermediate for &'a mut Cursor {
fn process(self, input: Vec<InputEvent>, _dt: Duration) -> Vec<InputEvent> {
let mut output = input.into_iter().filter_map(|event| {
match event {
InputEvent::Raw(Event::MouseMoved(x, y)) => {
self.pos = Some((x, y));

None
},
InputEvent::Raw(Event::MouseInput(ElementState::Pressed, button)) => {
self.pressed.insert(button, true);

None
},
InputEvent::Raw(Event::MouseInput(ElementState::Released, button)) => {
self.pressed.insert(button, false);

if let Some((x, y)) = self.pos {
Some(InputEvent::Intermediate(
IntermediateEvent::CursorReleased(x, y, button)
))
} else {
None
}
},
event => Some(event)
}
}).collect::<Vec<_>>();

if let Some((x, y)) = self.pos {
for (button, pressed) in self.pressed.iter() {
if *pressed {
output.push(InputEvent::Intermediate(
IntermediateEvent::CursorPressed(x, y, *button))
);
}
}
}

output
}
}

0 comments on commit 8e4c265

Please sign in to comment.