engine: add input module
parent
2be6a7be48
commit
6d4088a173
|
@ -13,6 +13,8 @@ rust_binary(
|
||||||
srcs = [
|
srcs = [
|
||||||
"src/main.rs",
|
"src/main.rs",
|
||||||
|
|
||||||
|
"src/input.rs",
|
||||||
|
|
||||||
"src/physics/mod.rs",
|
"src/physics/mod.rs",
|
||||||
"src/physics/color.rs",
|
"src/physics/color.rs",
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ use std::time;
|
||||||
|
|
||||||
use cgmath as cgm;
|
use cgmath as cgm;
|
||||||
|
|
||||||
|
pub mod input;
|
||||||
mod render;
|
mod render;
|
||||||
mod util;
|
mod util;
|
||||||
mod physics;
|
mod physics;
|
||||||
|
@ -158,13 +159,17 @@ impl Main {
|
||||||
struct MainData<'a> {
|
struct MainData<'a> {
|
||||||
scene_info: ecs::ReadWriteGlobal<'a, render::SceneInfo>,
|
scene_info: ecs::ReadWriteGlobal<'a, render::SceneInfo>,
|
||||||
time: ecs::ReadGlobal<'a, Time>,
|
time: ecs::ReadGlobal<'a, Time>,
|
||||||
|
input: ecs::ReadGlobal<'a, input::Input>,
|
||||||
transforms: ecs::ReadWriteComponent<'a, Transform>,
|
transforms: ecs::ReadWriteComponent<'a, Transform>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ecs::System <'a> for Main {
|
impl<'a> ecs::System <'a> for Main {
|
||||||
type SystemData = MainData<'a>;
|
type SystemData = MainData<'a>;
|
||||||
fn run(&mut self, sd: Self::SystemData) {
|
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(
|
let camera = cgm::Point3::new(
|
||||||
7.0 + (position / 4.0).sin(),
|
7.0 + (position / 4.0).sin(),
|
||||||
|
@ -209,10 +214,11 @@ fn main() {
|
||||||
p.add_system(renderer);
|
p.add_system(renderer);
|
||||||
|
|
||||||
let start = time::Instant::now();
|
let start = time::Instant::now();
|
||||||
world.set_global(Time{
|
world.set_global(Time {
|
||||||
start,
|
start,
|
||||||
now: start,
|
now: start,
|
||||||
});
|
});
|
||||||
|
world.set_global(input::Input::new());
|
||||||
loop {
|
loop {
|
||||||
world.global_mut::<Time>().get().now = time::Instant::now();
|
world.global_mut::<Time>().get().now = time::Instant::now();
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,8 @@ pub use mesh::Mesh;
|
||||||
pub use renderable::{Transform, Renderable};
|
pub use renderable::{Transform, Renderable};
|
||||||
pub use resource::{Resource, ResourceID};
|
pub use resource::{Resource, ResourceID};
|
||||||
|
|
||||||
|
use crate::input;
|
||||||
|
|
||||||
const WIDTH: u32 = 800;
|
const WIDTH: u32 = 800;
|
||||||
const HEIGHT: u32 = 600;
|
const HEIGHT: u32 = 600;
|
||||||
|
|
||||||
|
@ -57,9 +59,11 @@ pub struct Renderer {
|
||||||
rm: resource::Manager,
|
rm: resource::Manager,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Status {
|
pub struct Status {
|
||||||
pub closed: bool,
|
pub closed: bool,
|
||||||
|
pub input_device_id: u64,
|
||||||
}
|
}
|
||||||
impl ecs::Global for Status {}
|
impl ecs::Global for Status {}
|
||||||
|
|
||||||
|
@ -76,15 +80,19 @@ impl<'a> ecs::System<'a> for Renderer {
|
||||||
ecs::ReadComponent<'a, Renderable>,
|
ecs::ReadComponent<'a, Renderable>,
|
||||||
ecs::ReadWriteGlobal<'a, Status>,
|
ecs::ReadWriteGlobal<'a, Status>,
|
||||||
ecs::ReadGlobal<'a, SceneInfo>,
|
ecs::ReadGlobal<'a, SceneInfo>,
|
||||||
|
ecs::ReadWriteGlobal<'a, input::Input>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(&mut self,
|
fn run(&mut self,
|
||||||
( transforms
|
( transforms
|
||||||
, renderables
|
, renderables
|
||||||
, status
|
, status
|
||||||
, scene): Self::SystemData,
|
, scene
|
||||||
|
, input): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
let transformedRenderables = (transforms, renderables);
|
let transformedRenderables = (transforms, renderables);
|
||||||
|
let mut input = input.get();
|
||||||
|
let mut status = status.get();
|
||||||
|
|
||||||
let mut rd = vulkan::RenderData {
|
let mut rd = vulkan::RenderData {
|
||||||
meshes: BTreeMap::new(),
|
meshes: BTreeMap::new(),
|
||||||
|
@ -106,10 +114,36 @@ impl<'a> ecs::System<'a> for Renderer {
|
||||||
let view = &scene.get().view;
|
let view = &scene.get().view;
|
||||||
self.instance.flip(camera, view, &rd, &self.rm);
|
self.instance.flip(camera, view, &rd, &self.rm);
|
||||||
|
|
||||||
if self.poll_close() {
|
if status.input_device_id == 0 {
|
||||||
status.get().closed = true;
|
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 {
|
impl Renderer {
|
||||||
|
@ -120,6 +154,7 @@ impl Renderer {
|
||||||
});
|
});
|
||||||
world.set_global(Status {
|
world.set_global(Status {
|
||||||
closed: false,
|
closed: false,
|
||||||
|
input_device_id: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut instance = vulkan::Instance::new("abrasion".to_string());
|
let mut instance = vulkan::Instance::new("abrasion".to_string());
|
||||||
|
@ -143,16 +178,53 @@ impl Renderer {
|
||||||
(events_loop, surface)
|
(events_loop, surface)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_close(&mut self) -> bool {
|
fn poll_close(&mut self) -> (bool, Vec<InternalEvent>) {
|
||||||
let mut close = false;
|
let mut close = false;
|
||||||
|
|
||||||
|
let mut events = vec![];
|
||||||
// TODO(q3k): migrate to EventLoop::run
|
// TODO(q3k): migrate to EventLoop::run
|
||||||
self.events_loop.run_return(|ev, _, control_flow| {
|
self.events_loop.run_return(|ev, _, control_flow| {
|
||||||
if let Event::WindowEvent { event: WindowEvent::CloseRequested, .. } = ev {
|
match ev {
|
||||||
|
Event::WindowEvent {
|
||||||
|
event: WindowEvent::CloseRequested,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
close = true;
|
close = true;
|
||||||
}
|
},
|
||||||
|
Event::MainEventsCleared => {
|
||||||
*control_flow = winit::event_loop::ControlFlow::Exit;
|
*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;
|
||||||
|
},
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return close;
|
return (close, events);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_resource<T: Resource>(&mut self, r: T) -> ResourceID<T> {
|
pub fn add_resource<T: Resource>(&mut self, r: T) -> ResourceID<T> {
|
||||||
|
|
Loading…
Reference in New Issue