Work on events for the input stuff
This commit is contained in:
parent
5a37fcf1e6
commit
77053d56ad
|
@ -0,0 +1,53 @@
|
||||||
|
use std::{collections::VecDeque, ops::{Deref, DerefMut}};
|
||||||
|
|
||||||
|
use super::Resource;
|
||||||
|
|
||||||
|
pub trait Event: Clone + Send + Sync + 'static {}
|
||||||
|
impl<T: Clone + Send + Sync + 'static> Event for T {}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Events<T: Event> {
|
||||||
|
inner: VecDeque<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Event> Events<T> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: VecDeque::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Event> Deref for Events<T> {
|
||||||
|
type Target = VecDeque<T>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Event> DerefMut for Events<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Event> Resource for Events<T> {
|
||||||
|
fn as_any(&self) -> &dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait EventHolder {
|
||||||
|
fn get_data<T>() -> T;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EventStorage<T> {
|
||||||
|
data: T,
|
||||||
|
is_future: bool,
|
||||||
|
}
|
|
@ -5,6 +5,9 @@ use winit::event::WindowEvent;
|
||||||
pub mod window_state;
|
pub mod window_state;
|
||||||
pub use window_state::*;
|
pub use window_state::*;
|
||||||
|
|
||||||
|
pub mod events;
|
||||||
|
pub use events::*;
|
||||||
|
|
||||||
pub trait Resource: Send + Sync + 'static {
|
pub trait Resource: Send + Sync + 'static {
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
use std::{any::{TypeId, Any}, collections::{HashMap, HashSet}, ops::{Deref, DerefMut}};
|
use std::{any::{TypeId, Any}, collections::{HashMap, HashSet, VecDeque}, ops::{Deref, DerefMut}};
|
||||||
|
|
||||||
use super::resources::Resource;
|
use super::resources::{Resource, Events};
|
||||||
|
|
||||||
pub struct World {
|
pub struct World {
|
||||||
inner: hecs::World,
|
inner: hecs::World,
|
||||||
resources: HashMap<TypeId, Box<dyn Resource>>,
|
resources: HashMap<TypeId, Box<dyn Resource>>,
|
||||||
updated_resources: HashSet<TypeId>,
|
updated_resources: HashSet<TypeId>,
|
||||||
|
|
||||||
|
// a boolean that flip flops to clear events every other frame
|
||||||
|
events_flipflop: bool,
|
||||||
|
events: HashMap<TypeId, Box<dyn Resource>>,
|
||||||
|
event_write_queue: HashMap<TypeId, Box<dyn Resource>>,//VecDeque<(TypeId, Box<dyn Resource>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for World {
|
impl Deref for World {
|
||||||
|
@ -33,8 +38,26 @@ impl World {
|
||||||
inner: hecs_world,
|
inner: hecs_world,
|
||||||
resources: HashMap::new(),
|
resources: HashMap::new(),
|
||||||
updated_resources: HashSet::new(),
|
updated_resources: HashSet::new(),
|
||||||
|
events_flipflop: false,
|
||||||
|
events: HashMap::new(),
|
||||||
|
event_write_queue: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempts to query a resource, or will create it when its not found.
|
||||||
|
///
|
||||||
|
/// The resource will be created by a function passed in `default`.
|
||||||
|
pub fn query_or_insert_res<R>(&mut self, default: impl Fn() -> Box<dyn Resource + 'static>) -> &mut R
|
||||||
|
where
|
||||||
|
R: Resource,
|
||||||
|
{
|
||||||
|
let type_id = TypeId::of::<R>();
|
||||||
|
self.resources.entry(type_id)
|
||||||
|
.or_insert_with(default)
|
||||||
|
.as_any_mut()
|
||||||
|
.downcast_mut()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
/// Insert a resource into the World. You can only have one resource of the same type.
|
/// Insert a resource into the World. You can only have one resource of the same type.
|
||||||
/// If you attempt to add another resource of the same type, it will be replaced.
|
/// If you attempt to add another resource of the same type, it will be replaced.
|
||||||
|
@ -61,6 +84,48 @@ impl World {
|
||||||
self.updated_resources.clear();
|
self.updated_resources.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trigger an event
|
||||||
|
pub fn trigger_event<E>(&mut self, event: E)
|
||||||
|
where
|
||||||
|
E: Clone + Send + Sync + 'static
|
||||||
|
{
|
||||||
|
// the compiler wants me to explicit right here for some reason
|
||||||
|
let default = || Box::new(Events::<E>::new()) as Box<(dyn Resource + 'static)>;
|
||||||
|
|
||||||
|
// Get, or create, a list of events of this type
|
||||||
|
let type_id = TypeId::of::<E>();
|
||||||
|
let events: &mut Events<E> = self.event_write_queue.entry(type_id)
|
||||||
|
.or_insert_with(default)
|
||||||
|
.as_any_mut()
|
||||||
|
.downcast_mut()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
events.push_back(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clear events, this should happen at the start of every tick since events are cloned
|
||||||
|
/// before being given to the reader.
|
||||||
|
pub fn clear_events(&mut self) {
|
||||||
|
self.events.clear();
|
||||||
|
|
||||||
|
// get all keys of events
|
||||||
|
let keys: Vec<TypeId> = self.event_write_queue.keys().map(|k| k.clone()).collect();
|
||||||
|
|
||||||
|
// remove all elements from self.event_write_queue and insert them to events
|
||||||
|
for k in keys.into_iter() {
|
||||||
|
self.events.insert(k, self.event_write_queue.remove(&k).unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_events<E>(&self) -> Option<&Events<E>>
|
||||||
|
where
|
||||||
|
E: Clone + Send + Sync + 'static
|
||||||
|
{
|
||||||
|
self.events.get(&TypeId::of::<E>())
|
||||||
|
.map(|r| r.as_any().downcast_ref::<Events<E>>())
|
||||||
|
.flatten()
|
||||||
|
}
|
||||||
|
|
||||||
/// Query a resource.
|
/// Query a resource.
|
||||||
///
|
///
|
||||||
/// This is O(1), resources are stored in HashMaps.
|
/// This is O(1), resources are stored in HashMaps.
|
||||||
|
|
24
src/game.rs
24
src/game.rs
|
@ -14,7 +14,7 @@ use tracing_subscriber::{
|
||||||
|
|
||||||
use winit::{window::{WindowBuilder, Window}, event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, DeviceEvent}, event_loop::{EventLoop, ControlFlow}};
|
use winit::{window::{WindowBuilder, Window}, event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, DeviceEvent}, event_loop::{EventLoop, ControlFlow}};
|
||||||
|
|
||||||
use crate::{render::{renderer::{Renderer, BasicRenderer}, render_job::RenderJob}, input_event::InputEvent, ecs::{components::{mesh::MeshComponent, transform::TransformComponent}, SimpleSystem, SystemDispatcher, world::World, resources::WindowState}, input::Input};
|
use crate::{render::{renderer::{Renderer, BasicRenderer}, render_job::RenderJob}, input_event::InputEvent, ecs::{components::{mesh::MeshComponent, transform::TransformComponent}, SimpleSystem, SystemDispatcher, world::World, resources::{WindowState, Events}}, input::Input};
|
||||||
|
|
||||||
pub struct Controls<'a> {
|
pub struct Controls<'a> {
|
||||||
pub world: &'a mut World,
|
pub world: &'a mut World,
|
||||||
|
@ -114,6 +114,8 @@ impl GameLoop {
|
||||||
let mut world = self.world.lock().await;
|
let mut world = self.world.lock().await;
|
||||||
let mut resources = self.resources.lock().await;
|
let mut resources = self.resources.lock().await;
|
||||||
|
|
||||||
|
world.clear_events();
|
||||||
|
|
||||||
let mut controls = Controls {
|
let mut controls = Controls {
|
||||||
world: &mut world,
|
world: &mut world,
|
||||||
resources: &mut resources
|
resources: &mut resources
|
||||||
|
@ -210,16 +212,9 @@ impl GameLoop {
|
||||||
// make sure that the mouse is inside the window and the mouse has focus before reporting mouse motion
|
// make sure that the mouse is inside the window and the mouse has focus before reporting mouse motion
|
||||||
if let Some(window_state) = world.query_res::<WindowState>() {
|
if let Some(window_state) = world.query_res::<WindowState>() {
|
||||||
if window_state.is_focused && window_state.is_cursor_inside_window {
|
if window_state.is_focused && window_state.is_cursor_inside_window {
|
||||||
|
|
||||||
let event_queue = match world.query_res_mut::<VecDeque<InputEvent>>() {
|
let event_queue = world.query_or_insert_res::<Events<InputEvent>>
|
||||||
Some(i) => i,
|
(|| Box::new(Events::<InputEvent>::new()));
|
||||||
None => {
|
|
||||||
world.insert_resource(VecDeque::<InputEvent>::new());
|
|
||||||
|
|
||||||
// must succeed since it was just added
|
|
||||||
world.query_res_mut::<VecDeque<InputEvent>>().unwrap()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let input_event = InputEvent::MouseMotion { device_id, delta, };
|
let input_event = InputEvent::MouseMotion { device_id, delta, };
|
||||||
event_queue.push_back(input_event);
|
event_queue.push_back(input_event);
|
||||||
|
@ -240,17 +235,18 @@ impl GameLoop {
|
||||||
// the InputSystem is called, so we must use a queue for the events.
|
// the InputSystem is called, so we must use a queue for the events.
|
||||||
{
|
{
|
||||||
let mut world = self.world.lock().await;
|
let mut world = self.world.lock().await;
|
||||||
let event_queue = match world.query_res_mut::<VecDeque<InputEvent>>() {
|
world.trigger_event(input_event.clone());
|
||||||
|
/* let event_queue = match world.query_res_mut::<Events<InputEvent>>() {
|
||||||
Some(i) => i,
|
Some(i) => i,
|
||||||
None => {
|
None => {
|
||||||
world.insert_resource(VecDeque::<InputEvent>::new());
|
world.insert_resource(VecDeque::<InputEvent>::new());
|
||||||
|
|
||||||
// must succeed since it was just added
|
// must succeed since it was just added
|
||||||
world.query_res_mut::<VecDeque<InputEvent>>().unwrap()
|
world.query_res_mut::<Events<InputEvent>>().unwrap()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
event_queue.push_back(input_event.clone());
|
event_queue.push_back(input_event.clone()); */
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(new_control) = self.input_update(&input_event).await {
|
if let Some(new_control) = self.input_update(&input_event).await {
|
||||||
|
|
270
src/input.rs
270
src/input.rs
|
@ -3,9 +3,9 @@ use std::{any::{Any, TypeId}, collections::{HashMap, hash_map::DefaultHasher, Ve
|
||||||
use gilrs_core::Gilrs;
|
use gilrs_core::Gilrs;
|
||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
use tracing::{warn, debug};
|
use tracing::{warn, debug};
|
||||||
use winit::event::{VirtualKeyCode, ElementState};
|
use winit::event::{VirtualKeyCode, ElementState, MouseScrollDelta};
|
||||||
|
|
||||||
use crate::{ecs::{SimpleSystem, resources::Resource}, input_event::InputEvent};
|
use crate::{ecs::{SimpleSystem, resources::{Resource, Events}, world::World}, input_event::InputEvent};
|
||||||
|
|
||||||
pub type KeyCode = winit::event::VirtualKeyCode;
|
pub type KeyCode = winit::event::VirtualKeyCode;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ impl SimpleSystem for InputSystem {
|
||||||
fn execute_mut(&mut self, controls: &mut crate::game::Controls) -> anyhow::Result<()> {
|
fn execute_mut(&mut self, controls: &mut crate::game::Controls) -> anyhow::Result<()> {
|
||||||
let world = &mut controls.world;
|
let world = &mut controls.world;
|
||||||
|
|
||||||
if let Some(queue) = world.query_res_mut::<VecDeque<InputEvent>>() {
|
if let Some(queue) = world.query_res_mut::<Events<InputEvent>>() {
|
||||||
// Clone the queue, then clear it
|
// Clone the queue, then clear it
|
||||||
let mut queue = {
|
let mut queue = {
|
||||||
let a = queue.clone();
|
let a = queue.clone();
|
||||||
|
@ -42,7 +42,7 @@ impl SimpleSystem for InputSystem {
|
||||||
|
|
||||||
// process the all events that happened this tick
|
// process the all events that happened this tick
|
||||||
while let Some(event) = queue.pop_front() {
|
while let Some(event) = queue.pop_front() {
|
||||||
input.update(&event);
|
input.update(&event, world);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,15 +51,104 @@ impl SimpleSystem for InputSystem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct MouseMotion {
|
pub struct MouseMotion {
|
||||||
pub delta: Vec2,
|
pub delta: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct MouseWheel {
|
||||||
|
pub delta: Vec2,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct MouseExact {
|
pub struct MouseExact {
|
||||||
pub pos: Vec2,
|
pub pos: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Hash)]
|
||||||
|
pub enum TouchPhase {
|
||||||
|
Started,
|
||||||
|
Moved,
|
||||||
|
Ended,
|
||||||
|
Cancelled,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<winit::event::TouchPhase> for TouchPhase {
|
||||||
|
fn from(value: winit::event::TouchPhase) -> Self {
|
||||||
|
match value {
|
||||||
|
winit::event::TouchPhase::Started => TouchPhase::Started,
|
||||||
|
winit::event::TouchPhase::Moved => TouchPhase::Moved,
|
||||||
|
winit::event::TouchPhase::Ended => TouchPhase::Ended,
|
||||||
|
winit::event::TouchPhase::Cancelled => TouchPhase::Cancelled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Translated `Force` from `winit` crate
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum Force {
|
||||||
|
Calibrated {
|
||||||
|
force: f64,
|
||||||
|
max_possible_force: f64,
|
||||||
|
altitude_angle: Option<f64>,
|
||||||
|
},
|
||||||
|
Normalized(f64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<winit::event::Force> for Force {
|
||||||
|
fn from(value: winit::event::Force) -> Self {
|
||||||
|
match value {
|
||||||
|
winit::event::Force::Calibrated { force, max_possible_force, altitude_angle } => Self::Calibrated { force, max_possible_force, altitude_angle },
|
||||||
|
winit::event::Force::Normalized(v) => Self::Normalized(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Translated `WindowEvent::Touch` from `winit` crate
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct Touch {
|
||||||
|
pub phase: TouchPhase,
|
||||||
|
pub location: Vec2,
|
||||||
|
pub force: Option<Force>,
|
||||||
|
pub finger_id: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct Touches {
|
||||||
|
pub touches: Vec<Touch>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A mouse button event
|
||||||
|
///
|
||||||
|
/// Translated `WindowEvent::MouseButton` from `winit` crate
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Hash)]
|
||||||
|
pub enum MouseButton {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Middle,
|
||||||
|
Other(u16),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum MouseScrollUnit {
|
||||||
|
Line(Vec2),
|
||||||
|
Pixel(Vec2)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct MouseScroll {
|
||||||
|
pub unit: MouseScrollUnit,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct CursorEnteredWindow;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct CursorLeftWindow;
|
||||||
|
|
||||||
pub struct Input {
|
pub struct Input {
|
||||||
gilrs: Option<Arc<Mutex<Gilrs>>>, // TODO
|
gilrs: Option<Arc<Mutex<Gilrs>>>, // TODO
|
||||||
// the key is a u64. This is a hash of the value stored inside of the Box
|
// the key is a u64. This is a hash of the value stored inside of the Box
|
||||||
|
@ -77,6 +166,27 @@ impl Resource for Input {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// helper function for converting
|
||||||
|
#[inline(always)]
|
||||||
|
fn button_event_retain<E>(val: &mut Box<dyn Any + Send + Sync>) -> bool
|
||||||
|
where
|
||||||
|
E: Clone + Hash + 'static,
|
||||||
|
{
|
||||||
|
if let Some(ev) = val.downcast_mut::<ButtonEvent<E>>() {
|
||||||
|
match ev {
|
||||||
|
ButtonEvent::Released(_) => {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
ButtonEvent::JustPressed(v) => {
|
||||||
|
*ev = ButtonEvent::Pressed(v.clone());
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
pub(crate) fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
let gilrs = match Gilrs::new() {
|
let gilrs = match Gilrs::new() {
|
||||||
|
@ -98,48 +208,38 @@ impl Input {
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
// Convert JustPressed inputs to Pressed, and remove Released events
|
// Convert JustPressed inputs to Pressed, and remove Released events
|
||||||
self.button_events.retain(|_, v| {
|
self.button_events.retain(|_, v| {
|
||||||
if let Some(ev) = v.downcast_mut::<ButtonEvent<KeyCode>>() {
|
if !button_event_retain::<KeyCode>(v)
|
||||||
match ev {
|
|| !button_event_retain::<MouseButton>(v)
|
||||||
ButtonEvent::Released(_) => {
|
{
|
||||||
return false;
|
return false;
|
||||||
},
|
|
||||||
ButtonEvent::JustPressed(v) => {
|
|
||||||
*ev = ButtonEvent::Pressed(*v);
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
|
||||||
self.typed_events.retain(|_, v| {
|
self.typed_events.retain(|_, v| {
|
||||||
//if v.is::<MouseExact>() {
|
if v.downcast_ref::<MouseMotion>().is_some()
|
||||||
if v.downcast_ref::<MouseMotion>().is_some() {
|
|| v.downcast_ref::<MouseExact>().is_some()
|
||||||
|
|| v.downcast_ref::<CursorEnteredWindow>().is_some()
|
||||||
|
|| v.downcast_ref::<CursorLeftWindow>().is_some()
|
||||||
|
|| v.downcast_ref::<MouseScroll>().is_some()
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if let Some(touches) = self.get_event_mut::<Touches>() {
|
||||||
|
touches.touches.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, event: &InputEvent) -> bool {
|
pub fn update(&mut self, event: &InputEvent, world: &mut World) -> bool {
|
||||||
match event {
|
match event {
|
||||||
InputEvent::KeyboardInput { input, .. } => {
|
InputEvent::KeyboardInput { input, .. } => {
|
||||||
if let Some(code) = input.virtual_keycode {
|
if let Some(code) = input.virtual_keycode {
|
||||||
// Get a hash of the input code
|
self.create_button_event(code, input.state);
|
||||||
let mut hasher = DefaultHasher::new();
|
|
||||||
code.hash(&mut hasher);
|
|
||||||
let code_hash = hasher.finish();
|
|
||||||
|
|
||||||
// convert state
|
|
||||||
let buttonev = Box::new(match input.state {
|
|
||||||
ElementState::Pressed if self.is_pressed(code) => ButtonEvent::Pressed(code),
|
|
||||||
ElementState::Pressed => ButtonEvent::JustPressed(code),
|
|
||||||
ElementState::Released => ButtonEvent::Released(code),
|
|
||||||
});
|
|
||||||
|
|
||||||
self.button_events.insert(code_hash, buttonev);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
InputEvent::MouseMotion { delta, .. } => {
|
InputEvent::MouseMotion { delta, .. } => {
|
||||||
|
@ -154,40 +254,111 @@ impl Input {
|
||||||
pos: Vec2::new(position.x as f32, position.y as f32)
|
pos: Vec2::new(position.x as f32, position.y as f32)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.typed_events.insert(exact.type_id(), Box::new(exact.clone()));
|
self.typed_events.insert(exact.type_id(), Box::new(exact));
|
||||||
|
},
|
||||||
|
InputEvent::CursorEntered { .. } => {
|
||||||
|
let event = CursorEnteredWindow {};
|
||||||
|
self.typed_events.insert(event.type_id(), Box::new(event));
|
||||||
|
},
|
||||||
|
InputEvent::CursorLeft { .. } => {
|
||||||
|
let event = CursorLeftWindow {};
|
||||||
|
self.typed_events.insert(event.type_id(), Box::new(event));
|
||||||
|
},
|
||||||
|
InputEvent::MouseWheel { delta, .. } => {
|
||||||
|
let event = match delta {
|
||||||
|
MouseScrollDelta::LineDelta(x, y) => MouseScroll {
|
||||||
|
unit: MouseScrollUnit::Line(Vec2::new(*x, *y)),
|
||||||
|
},
|
||||||
|
MouseScrollDelta::PixelDelta(delta) => MouseScroll {
|
||||||
|
unit: MouseScrollUnit::Pixel(Vec2::new(delta.x as f32, delta.y as f32)),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
self.typed_events.insert(event.type_id(), Box::new(event));
|
||||||
|
}, //MouseButton
|
||||||
|
InputEvent::MouseInput { button, state, .. } => {
|
||||||
|
let button = match button {
|
||||||
|
winit::event::MouseButton::Left => MouseButton::Left,
|
||||||
|
winit::event::MouseButton::Right => MouseButton::Right,
|
||||||
|
winit::event::MouseButton::Middle => MouseButton::Middle,
|
||||||
|
winit::event::MouseButton::Other(v) => MouseButton::Other(*v),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.create_button_event(button, *state);
|
||||||
|
},
|
||||||
|
InputEvent::Touch(t) => {
|
||||||
|
let touch = Touch {
|
||||||
|
phase: TouchPhase::from(t.phase),
|
||||||
|
location: Vec2::new(t.location.x as f32, t.location.y as f32),
|
||||||
|
force: match t.force {
|
||||||
|
Some(f) => Some(Force::from(f)),
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
|
finger_id: t.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
let touches = match self.get_event_mut::<Touches>() {
|
||||||
|
Some(t) => t,
|
||||||
|
None => {
|
||||||
|
let t = Touches {
|
||||||
|
touches: Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.typed_events.insert(t.type_id(), Box::new(t));
|
||||||
|
self.get_event_mut::<Touches>().unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
touches.touches.push(touch);
|
||||||
},
|
},
|
||||||
/* WindowEvent::CursorMoved { position, .. } => Some(EventType::PositionChanged(position.x, position.y, InputEventCode::CursorMoved)),
|
|
||||||
WindowEvent::CursorEntered { .. } => Some(EventType::Signal(InputEventCode::CursorEnteredWindow)),
|
|
||||||
WindowEvent::CursorLeft { .. } => Some(EventType::Signal(InputEventCode::CursorLeftWindow)), */
|
|
||||||
//WindowEvent::MouseWheel { delta, .. } => Some(EventType::AxisChanged(delta, InputEventCode::MouseWheel)),
|
|
||||||
/* WindowEvent::MouseWheel { .. } => Some(InputEventCode::MouseWheel),
|
|
||||||
WindowEvent::MouseInput { .. } => Some(InputEventCode::MouseInput),
|
|
||||||
WindowEvent::TouchpadMagnify { .. } => Some(InputEventCode::TouchpadMagnify),
|
|
||||||
WindowEvent::SmartMagnify { .. } => Some(InputEventCode::SmartMagnify),
|
|
||||||
WindowEvent::TouchpadRotate { .. } => Some(InputEventCode::TouchpadRotate),
|
|
||||||
WindowEvent::TouchpadPressure { .. } => Some(InputEventCode::TouchpadPressure),
|
|
||||||
WindowEvent::AxisMotion { .. } => Some(InputEventCode::AxisMotion),
|
|
||||||
WindowEvent::Touch { .. } => Some(InputEventCode::Touch), */
|
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_button_event<B>(&mut self, button: B, state: ElementState)
|
||||||
|
where
|
||||||
|
B: Hash + PartialEq + Clone + Copy + Sync + Send + 'static
|
||||||
|
{
|
||||||
|
// Get a hash of the button
|
||||||
|
let mut hasher = DefaultHasher::new();
|
||||||
|
button.hash(&mut hasher);
|
||||||
|
let code_hash = hasher.finish();
|
||||||
|
|
||||||
|
// convert state
|
||||||
|
let buttonev = Box::new(match state {
|
||||||
|
ElementState::Pressed if self.is_pressed(button) => ButtonEvent::Pressed(button),
|
||||||
|
ElementState::Pressed => ButtonEvent::JustPressed(button),
|
||||||
|
ElementState::Released => ButtonEvent::Released(button),
|
||||||
|
});
|
||||||
|
|
||||||
|
self.button_events.insert(code_hash, buttonev);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_event<E: 'static>(&self) -> Option<&E> {
|
pub fn get_event<E: 'static>(&self) -> Option<&E> {
|
||||||
self.typed_events.get(&TypeId::of::<E>())
|
self.typed_events.get(&TypeId::of::<E>())
|
||||||
.and_then(|e| e.as_ref()
|
.and_then(|e| e.as_ref()
|
||||||
.downcast_ref::<E>())
|
.downcast_ref::<E>())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn was_just_pressed(&self, code: VirtualKeyCode) -> bool {
|
pub(crate) fn get_event_mut<E: 'static>(&mut self) -> Option<&mut E> {
|
||||||
|
self.typed_events.get_mut(&TypeId::of::<E>())
|
||||||
|
.and_then(|e| e.as_mut()
|
||||||
|
.downcast_mut::<E>())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn was_just_pressed<T>(&self, code: T) -> bool
|
||||||
|
where
|
||||||
|
T: Hash + PartialEq + Clone + 'static
|
||||||
|
{
|
||||||
// get a hash of the key code
|
// get a hash of the key code
|
||||||
let mut hasher = DefaultHasher::new();
|
let mut hasher = DefaultHasher::new();
|
||||||
code.hash(&mut hasher);
|
code.hash(&mut hasher);
|
||||||
let inner_hash = hasher.finish();
|
let inner_hash = hasher.finish();
|
||||||
|
|
||||||
if let Some(e) = self.button_events.get(&inner_hash) {
|
if let Some(e) = self.button_events.get(&inner_hash) {
|
||||||
if let Some(ev) = e.downcast_ref::<ButtonEvent<KeyCode>>() {
|
if let Some(ev) = e.downcast_ref::<ButtonEvent<T>>() {
|
||||||
match ev {
|
match ev {
|
||||||
ButtonEvent::JustPressed(v) => {
|
ButtonEvent::JustPressed(v) => {
|
||||||
if v.clone() == code {
|
if v.clone() == code {
|
||||||
|
@ -204,14 +375,17 @@ impl Input {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_pressed(&self, code: VirtualKeyCode) -> bool {
|
pub fn is_pressed<T>(&self, code: T) -> bool
|
||||||
|
where
|
||||||
|
T: Hash + PartialEq + Clone + 'static
|
||||||
|
{
|
||||||
// get a hash of the key code
|
// get a hash of the key code
|
||||||
let mut hasher = DefaultHasher::new();
|
let mut hasher = DefaultHasher::new();
|
||||||
code.hash(&mut hasher);
|
code.hash(&mut hasher);
|
||||||
let inner_hash = hasher.finish();
|
let inner_hash = hasher.finish();
|
||||||
|
|
||||||
if let Some(e) = self.button_events.get(&inner_hash) {
|
if let Some(e) = self.button_events.get(&inner_hash) {
|
||||||
if let Some(ev) = e.downcast_ref::<ButtonEvent<KeyCode>>() {
|
if let Some(ev) = e.downcast_ref::<ButtonEvent<T>>() {
|
||||||
match ev {
|
match ev {
|
||||||
ButtonEvent::Pressed(v) | ButtonEvent::JustPressed(v) => {
|
ButtonEvent::Pressed(v) | ButtonEvent::JustPressed(v) => {
|
||||||
if v.clone() == code {
|
if v.clone() == code {
|
||||||
|
|
30
src/main.rs
30
src/main.rs
|
@ -13,7 +13,7 @@ use game::Game;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::ecs::world::World;
|
use crate::ecs::world::World;
|
||||||
use crate::input::{Input, KeyCode, InputSystem, MouseMotion};
|
use crate::input::{Input, KeyCode, InputSystem, MouseMotion, MouseExact, CursorEnteredWindow, MouseScroll, CursorLeftWindow, MouseButton};
|
||||||
use crate::render::material::Material;
|
use crate::render::material::Material;
|
||||||
use crate::render::texture::Texture;
|
use crate::render::texture::Texture;
|
||||||
use crate::ecs::components::camera::CameraComponent;
|
use crate::ecs::components::camera::CameraComponent;
|
||||||
|
@ -113,10 +113,38 @@ async fn main() {
|
||||||
dir_y += speed;
|
dir_y += speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if input.is_pressed(MouseButton::Left) {
|
||||||
|
debug!("left mouse button!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.is_pressed(MouseButton::Middle) {
|
||||||
|
debug!("middle mouse button!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.is_pressed(MouseButton::Right) {
|
||||||
|
debug!("right mouse button!");
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(motion) = input.get_event::<MouseMotion>() {
|
if let Some(motion) = input.get_event::<MouseMotion>() {
|
||||||
debug!("delta: {}", motion.delta);
|
debug!("delta: {}", motion.delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(exact) = input.get_event::<MouseExact>() {
|
||||||
|
debug!("exact pos: {:?}", exact);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(scroll) = input.get_event::<MouseScroll>() {
|
||||||
|
debug!("scrolled: {:?}", scroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.get_event::<CursorEnteredWindow>().is_some() {
|
||||||
|
debug!("cursor entered window!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.get_event::<CursorLeftWindow>().is_some() {
|
||||||
|
debug!("cursor left window!");
|
||||||
|
}
|
||||||
|
|
||||||
for (_eid, (transform, )) in world.query_mut::<(&mut TransformComponent,)>() {
|
for (_eid, (transform, )) in world.query_mut::<(&mut TransformComponent,)>() {
|
||||||
let t = &mut transform.transform;
|
let t = &mut transform.transform;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue