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 use window_state::*;
|
||||
|
||||
pub mod events;
|
||||
pub use events::*;
|
||||
|
||||
pub trait Resource: Send + Sync + 'static {
|
||||
fn as_any(&self) -> &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 {
|
||||
inner: hecs::World,
|
||||
resources: HashMap<TypeId, Box<dyn Resource>>,
|
||||
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 {
|
||||
|
@ -33,8 +38,26 @@ impl World {
|
|||
inner: hecs_world,
|
||||
resources: HashMap::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.
|
||||
/// 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();
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// 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 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 world: &'a mut World,
|
||||
|
@ -114,6 +114,8 @@ impl GameLoop {
|
|||
let mut world = self.world.lock().await;
|
||||
let mut resources = self.resources.lock().await;
|
||||
|
||||
world.clear_events();
|
||||
|
||||
let mut controls = Controls {
|
||||
world: &mut world,
|
||||
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
|
||||
if let Some(window_state) = world.query_res::<WindowState>() {
|
||||
if window_state.is_focused && window_state.is_cursor_inside_window {
|
||||
|
||||
let event_queue = match world.query_res_mut::<VecDeque<InputEvent>>() {
|
||||
Some(i) => i,
|
||||
None => {
|
||||
world.insert_resource(VecDeque::<InputEvent>::new());
|
||||
|
||||
// must succeed since it was just added
|
||||
world.query_res_mut::<VecDeque<InputEvent>>().unwrap()
|
||||
}
|
||||
};
|
||||
|
||||
let event_queue = world.query_or_insert_res::<Events<InputEvent>>
|
||||
(|| Box::new(Events::<InputEvent>::new()));
|
||||
|
||||
let input_event = InputEvent::MouseMotion { device_id, delta, };
|
||||
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.
|
||||
{
|
||||
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,
|
||||
None => {
|
||||
world.insert_resource(VecDeque::<InputEvent>::new());
|
||||
|
||||
// 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 {
|
||||
|
|
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 glam::Vec2;
|
||||
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;
|
||||
|
||||
|
@ -28,7 +28,7 @@ impl SimpleSystem for InputSystem {
|
|||
fn execute_mut(&mut self, controls: &mut crate::game::Controls) -> anyhow::Result<()> {
|
||||
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
|
||||
let mut queue = {
|
||||
let a = queue.clone();
|
||||
|
@ -42,7 +42,7 @@ impl SimpleSystem for InputSystem {
|
|||
|
||||
// process the all events that happened this tick
|
||||
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 delta: Vec2,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct MouseWheel {
|
||||
pub delta: Vec2,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct MouseExact {
|
||||
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 {
|
||||
gilrs: Option<Arc<Mutex<Gilrs>>>, // TODO
|
||||
// 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 {
|
||||
pub(crate) fn new() -> Self {
|
||||
let gilrs = match Gilrs::new() {
|
||||
|
@ -98,48 +208,38 @@ impl Input {
|
|||
pub fn clear(&mut self) {
|
||||
// Convert JustPressed inputs to Pressed, and remove Released events
|
||||
self.button_events.retain(|_, v| {
|
||||
if let Some(ev) = v.downcast_mut::<ButtonEvent<KeyCode>>() {
|
||||
match ev {
|
||||
ButtonEvent::Released(_) => {
|
||||
return false;
|
||||
},
|
||||
ButtonEvent::JustPressed(v) => {
|
||||
*ev = ButtonEvent::Pressed(*v);
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
if !button_event_retain::<KeyCode>(v)
|
||||
|| !button_event_retain::<MouseButton>(v)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 {
|
||||
InputEvent::KeyboardInput { input, .. } => {
|
||||
if let Some(code) = input.virtual_keycode {
|
||||
// Get a hash of the input code
|
||||
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);
|
||||
self.create_button_event(code, input.state);
|
||||
}
|
||||
},
|
||||
InputEvent::MouseMotion { delta, .. } => {
|
||||
|
@ -154,40 +254,111 @@ impl Input {
|
|||
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
|
||||
}
|
||||
|
||||
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> {
|
||||
self.typed_events.get(&TypeId::of::<E>())
|
||||
.and_then(|e| e.as_ref()
|
||||
.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
|
||||
let mut hasher = DefaultHasher::new();
|
||||
code.hash(&mut hasher);
|
||||
let inner_hash = hasher.finish();
|
||||
|
||||
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 {
|
||||
ButtonEvent::JustPressed(v) => {
|
||||
if v.clone() == code {
|
||||
|
@ -204,14 +375,17 @@ impl Input {
|
|||
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
|
||||
let mut hasher = DefaultHasher::new();
|
||||
code.hash(&mut hasher);
|
||||
let inner_hash = hasher.finish();
|
||||
|
||||
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 {
|
||||
ButtonEvent::Pressed(v) | ButtonEvent::JustPressed(v) => {
|
||||
if v.clone() == code {
|
||||
|
|
30
src/main.rs
30
src/main.rs
|
@ -13,7 +13,7 @@ use game::Game;
|
|||
use tracing::debug;
|
||||
|
||||
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::texture::Texture;
|
||||
use crate::ecs::components::camera::CameraComponent;
|
||||
|
@ -113,10 +113,38 @@ async fn main() {
|
|||
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>() {
|
||||
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,)>() {
|
||||
let t = &mut transform.transform;
|
||||
|
||||
|
|
Loading…
Reference in New Issue