engine: add input module

master
q3k 2021-04-04 15:46:29 +00:00
parent 2be6a7be48
commit 6d4088a173
4 changed files with 158 additions and 10 deletions

View File

@ -13,6 +13,8 @@ rust_binary(
srcs = [
"src/main.rs",
"src/input.rs",
"src/physics/mod.rs",
"src/physics/color.rs",

68
engine/src/input.rs Normal file
View File

@ -0,0 +1,68 @@
use std::collections::{BTreeMap,BTreeSet};
#[derive(Clone, Debug)]
pub struct Input {
pub devices: BTreeMap<u64, Device>,
highest_no: u64,
}
impl ecs::Global for Input {}
impl Input {
pub fn allocate_device(&mut self) -> u64 {
self.highest_no += 1;
self.highest_no
}
pub fn new() -> Self {
Self {
devices: BTreeMap::new(),
highest_no: 0,
}
}
pub fn mouse_cursor(&self) -> Option<&MouseCursor> {
for dev in self.devices.values() {
if let &Device::MouseCursor(cursor) = &dev {
return Some(&cursor);
}
}
None
}
}
#[derive(Clone, Debug)]
pub enum Device {
MouseCursor(MouseCursor),
}
#[derive(Clone, Debug)]
pub struct MouseCursor {
// x and y coordinates [0.0, 1.0), top left at (0, 0).
pub x: f32,
pub y: f32,
pressed: BTreeSet<MouseButton>,
}
impl MouseCursor {
pub fn new() -> Self {
Self {
x: 0., y: 0.,
pressed: BTreeSet::new(),
}
}
pub fn set_mouse_pressed(&mut self, button: MouseButton) {
self.pressed.insert(button);
}
pub fn set_mouse_released(&mut self, button: MouseButton) {
self.pressed.remove(&button);
}
}
#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub enum MouseButton {
Left,
Middle,
Right,
Other,
}

View File

@ -21,6 +21,7 @@ use std::time;
use cgmath as cgm;
pub mod input;
mod render;
mod util;
mod physics;
@ -158,13 +159,17 @@ impl Main {
struct MainData<'a> {
scene_info: ecs::ReadWriteGlobal<'a, render::SceneInfo>,
time: ecs::ReadGlobal<'a, Time>,
input: ecs::ReadGlobal<'a, input::Input>,
transforms: ecs::ReadWriteComponent<'a, Transform>,
}
impl<'a> ecs::System <'a> for Main {
type SystemData = MainData<'a>;
fn run(&mut self, sd: Self::SystemData) {
let position = (sd.time.get().instant() / 10.0) * 3.14 * 2.0;
let position: f32 = match sd.input.get().mouse_cursor() {
Some(cursor) => cursor.x,
_ => (sd.time.get().instant() / 10.0) * 3.14 * 2.0,
};
let camera = cgm::Point3::new(
7.0 + (position / 4.0).sin(),
@ -209,10 +214,11 @@ fn main() {
p.add_system(renderer);
let start = time::Instant::now();
world.set_global(Time{
world.set_global(Time {
start,
now: start,
});
world.set_global(input::Input::new());
loop {
world.global_mut::<Time>().get().now = time::Instant::now();

View File

@ -48,6 +48,8 @@ pub use mesh::Mesh;
pub use renderable::{Transform, Renderable};
pub use resource::{Resource, ResourceID};
use crate::input;
const WIDTH: u32 = 800;
const HEIGHT: u32 = 600;
@ -57,9 +59,11 @@ pub struct Renderer {
rm: resource::Manager,
}
#[derive(Clone, Debug)]
pub struct Status {
pub closed: bool,
pub input_device_id: u64,
}
impl ecs::Global for Status {}
@ -76,15 +80,19 @@ impl<'a> ecs::System<'a> for Renderer {
ecs::ReadComponent<'a, Renderable>,
ecs::ReadWriteGlobal<'a, Status>,
ecs::ReadGlobal<'a, SceneInfo>,
ecs::ReadWriteGlobal<'a, input::Input>,
);
fn run(&mut self,
( transforms
, renderables
, status
, scene): Self::SystemData,
, scene
, input): Self::SystemData,
) {
let transformedRenderables = (transforms, renderables);
let mut input = input.get();
let mut status = status.get();
let mut rd = vulkan::RenderData {
meshes: BTreeMap::new(),
@ -106,12 +114,38 @@ impl<'a> ecs::System<'a> for Renderer {
let view = &scene.get().view;
self.instance.flip(camera, view, &rd, &self.rm);
if self.poll_close() {
status.get().closed = true;
if status.input_device_id == 0 {
status.input_device_id = input.allocate_device();
}
let (close, events) = self.poll_close();
if close {
status.closed = true;
} else {
let mut device = input.devices.entry(status.input_device_id).or_insert(input::Device::MouseCursor(input::MouseCursor::new()));
if let &mut input::Device::MouseCursor(cursor) = &mut device {
for event in events {
match event {
InternalEvent::MousePressed(button) => cursor.set_mouse_pressed(button),
InternalEvent::MouseReleased(button) => cursor.set_mouse_released(button),
InternalEvent::MouseMoved(x, y) => {
cursor.x = x as f32;
cursor.y = y as f32;
},
}
}
}
}
}
}
#[derive(Clone,Debug)]
enum InternalEvent {
MousePressed(input::MouseButton),
MouseReleased(input::MouseButton),
MouseMoved(f64, f64),
}
impl Renderer {
pub fn initialize(world: &mut ecs::World) -> Self {
world.set_global(SceneInfo {
@ -120,6 +154,7 @@ impl Renderer {
});
world.set_global(Status {
closed: false,
input_device_id: 0,
});
let mut instance = vulkan::Instance::new("abrasion".to_string());
@ -143,16 +178,53 @@ impl Renderer {
(events_loop, surface)
}
fn poll_close(&mut self) -> bool {
fn poll_close(&mut self) -> (bool, Vec<InternalEvent>) {
let mut close = false;
let mut events = vec![];
// TODO(q3k): migrate to EventLoop::run
self.events_loop.run_return(|ev, _, control_flow| {
if let Event::WindowEvent { event: WindowEvent::CloseRequested, .. } = ev {
close = true;
match ev {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
close = true;
},
Event::MainEventsCleared => {
*control_flow = winit::event_loop::ControlFlow::Exit;
},
Event::WindowEvent {
event: WindowEvent::CursorMoved { position, .. },
..
} => {
events.push(InternalEvent::MouseMoved(position.x, position.y));
},
Event::WindowEvent {
event: WindowEvent::MouseInput { state, button, .. },
..
} => {
let button = match button {
winit::event::MouseButton::Left => input::MouseButton::Left,
winit::event::MouseButton::Middle => input::MouseButton::Middle,
winit::event::MouseButton::Right => input::MouseButton::Right,
_ => input::MouseButton::Other,
};
match state {
winit::event::ElementState::Pressed => {
events.push(InternalEvent::MousePressed(button));
},
winit::event::ElementState::Released => {
events.push(InternalEvent::MouseReleased(button));
},
}
},
_ => {
*control_flow = winit::event_loop::ControlFlow::Poll;
},
}
*control_flow = winit::event_loop::ControlFlow::Exit;
});
return close;
return (close, events);
}
pub fn add_resource<T: Resource>(&mut self, r: T) -> ResourceID<T> {