Browse Source

Implemented camera movement with mouse

raster
Bergmann89 3 years ago
parent
commit
98b4445769
7 changed files with 182 additions and 53 deletions
  1. +13
    -1
      space-crush-app/src/error.rs
  2. +2
    -2
      space-crush-app/src/lib.rs
  3. +69
    -7
      space-crush-app/src/misc/events.rs
  4. +3
    -1
      space-crush-app/src/misc/mod.rs
  5. +22
    -0
      space-crush-app/src/misc/window.rs
  6. +35
    -16
      space-crush-app/src/render/init.rs
  7. +38
    -26
      space-crush-app/src/resources/config.rs

+ 13
- 1
space-crush-app/src/error.rs View File

@@ -1,7 +1,10 @@
use std::io::Error as IoError;

use glc::error::Error as GlcError;
use glutin::{ContextError as GlutinContextError, CreationError as GlutinCreationError};
use glutin::{
error::ExternalError as GlutinExternalError, ContextError as GlutinContextError,
CreationError as GlutinCreationError,
};
use glyph_brush::ab_glyph::InvalidFont;
use serde_json::Error as JsonError;
use space_crush_common::{misc::VfsError, Error as CommonError};
@@ -24,6 +27,9 @@ pub enum Error {
#[error("glutin Creation Error: {0}")]
GlutinCreationError(GlutinCreationError),

#[error("glutin External Error: {0}")]
GlutinExternalError(GlutinExternalError),

#[error("Invalid Font: {0}")]
InvalidFont(InvalidFont),

@@ -73,6 +79,12 @@ impl From<GlutinCreationError> for Error {
}
}

impl From<GlutinExternalError> for Error {
fn from(err: GlutinExternalError) -> Self {
Self::GlutinExternalError(err)
}
}

impl From<InvalidFont> for Error {
fn from(err: InvalidFont) -> Self {
Self::InvalidFont(err)


+ 2
- 2
space-crush-app/src/lib.rs View File

@@ -26,7 +26,7 @@ pub struct App<'a, 'b> {
impl<'a, 'b> App<'a, 'b> {
pub fn new(world: &mut World) -> Result<Self, Error> {
let config = Config::new(world)?;
let events = Events::new(world);
let events = Events::new(world)?;
let window = Window::new(events.handle(), &config)?;

let state = State::default();
@@ -67,7 +67,7 @@ impl<'a, 'b> App<'a, 'b> {
}

pub fn process(&mut self, world: &World) -> Result<(), Error> {
self.events.process(world);
self.events.process(world, &self.window);
self.dispatcher.dispatch(world);

self.window.swap_buffers()?;


+ 69
- 7
space-crush-app/src/misc/events.rs View File

@@ -7,26 +7,38 @@ use glutin::{
event_loop::{ControlFlow, EventLoop},
platform::desktop::EventLoopExtDesktop,
};
use shrev::EventChannel;
use shrev::{EventChannel, ReaderId};
use space_crush_common::misc::{LogResult, WorldHelper};
use specs::World;

use crate::{misc::Window, Error};

pub use glutin::event::{MouseButton, VirtualKeyCode};

pub struct Events {
keys: HashSet<VirtualKeyCode>,
event_loop: EventLoop<()>,
mouse_pos: Option<(f64, f64)>,
mouse_lock: Option<(f64, f64)>,
control_event_id: ReaderId<ControlEvent>,
}

impl Events {
pub fn new(world: &mut World) -> Self {
pub fn new(world: &mut World) -> Result<Self, Error> {
world.insert(EventChannel::<ControlEvent>::default());
world.insert(EventChannel::<MouseEvent>::default());
world.insert(EventChannel::<WindowEvent>::default());
world.insert(EventChannel::<KeyboardEvent>::default());

Self {
let control_event_id = world.register_event_reader::<ControlEvent>()?;

Ok(Self {
keys: HashSet::new(),
event_loop: EventLoop::new(),
}
mouse_pos: None,
mouse_lock: None,
control_event_id,
})
}
}

@@ -35,14 +47,36 @@ impl Events {
&self.event_loop
}

pub fn process(&mut self, world: &World) {
pub fn process(&mut self, world: &World, window: &Window) {
let control_events = world.fetch::<EventChannel<ControlEvent>>();
let mut mouse_events = world.fetch_mut::<EventChannel<MouseEvent>>();
let mut window_events = world.fetch_mut::<EventChannel<WindowEvent>>();
let mut keyboard_events = world.fetch_mut::<EventChannel<KeyboardEvent>>();

let keys = &mut self.keys;
let mouse_pos = &mut self.mouse_pos;
let event_loop = &mut self.event_loop;
let mouse_lock = &mut self.mouse_lock;

let events = control_events.read(&mut self.control_event_id);
for event in events {
match event {
ControlEvent::LockMouse => {
*mouse_lock = *mouse_pos;
window
.set_mouse_locked(true)
.warn("Unable to lock mouse to window");
}
ControlEvent::UnlockMouse => {
*mouse_lock = None;
window
.set_mouse_locked(false)
.warn("Unable to lock mouse to window");
}
}
}

let mut has_mouse_moved = false;
event_loop.run_return(|event, _target, flow_control| {
*flow_control = ControlFlow::Poll;

@@ -53,8 +87,20 @@ impl Events {
Event::WindowEvent { event, .. } => match event {
/* Mouse Events */
GlutinWindowEvent::CursorMoved { position, .. } => {
mouse_events
.single_write(MouseEvent::Move(position.x as _, position.y as _));
if mouse_lock.is_none() {
mouse_events
.single_write(MouseEvent::Move(position.x as _, position.y as _));
}

if let Some((x, y)) = mouse_pos {
let dx = position.x - *x;
let dy = position.y - *y;

mouse_events.single_write(MouseEvent::Delta(dx as _, dy as _));
}

has_mouse_moved = true;
*mouse_pos = Some((position.x as _, position.y as _));
}
GlutinWindowEvent::MouseInput {
state: ElementState::Pressed,
@@ -82,6 +128,9 @@ impl Events {
mouse_events.single_write(MouseEvent::ScrollY(y));
}
}
GlutinWindowEvent::CursorLeft { .. } => {
*mouse_pos = None;
}

/* Key Event */
GlutinWindowEvent::KeyboardInput {
@@ -127,9 +176,21 @@ impl Events {
_ => (),
}
});

if let Some((x, y)) = self.mouse_lock {
if has_mouse_moved {
window.set_mouse_pos(x, y).warn("Unable to set mouse pos");
self.mouse_pos = Some((x, y));
}
}
}
}

pub enum ControlEvent {
LockMouse,
UnlockMouse,
}

pub enum WindowEvent {
Resize(u32, u32),
Close,
@@ -137,6 +198,7 @@ pub enum WindowEvent {

pub enum MouseEvent {
Move(f32, f32),
Delta(f32, f32),
ButtonDown(MouseButton),
ButtonUp(MouseButton),
ScrollX(f32),


+ 3
- 1
space-crush-app/src/misc/mod.rs View File

@@ -3,7 +3,9 @@ mod text;
mod window;
mod world;

pub use events::{Events, KeyboardEvent, MouseButton, MouseEvent, VirtualKeyCode, WindowEvent};
pub use events::{
ControlEvent, Events, KeyboardEvent, MouseButton, MouseEvent, VirtualKeyCode, WindowEvent,
};
pub use text::{Text, TextCache, TextManager};
pub use window::Window;
pub use world::WorldHelper;

+ 22
- 0
space-crush-app/src/misc/window.rs View File

@@ -99,6 +99,7 @@ impl Window {
(monitor_size.width - window_size.width) / 2,
(monitor_size.height - window_size.height) / 2,
));
window.set_cursor_grab(true).unwrap();

let context = unsafe { context.make_current().unwrap() };
gl::load_with(|s| context.get_proc_address(s));
@@ -116,4 +117,25 @@ impl Window {

Ok(())
}

pub fn set_mouse_locked(&self, value: bool) -> Result<(), Error> {
let window = self.context.window();

window.set_cursor_grab(value)?;

if !value {
window.set_cursor_visible(true);
}

Ok(())
}

pub fn set_mouse_pos(&self, x: f64, y: f64) -> Result<(), Error> {
let window = self.context.window();

window.set_cursor_visible(false);
window.set_cursor_position(PhysicalPosition { x, y })?;

Ok(())
}
}

+ 35
- 16
space-crush-app/src/render/init.rs View File

@@ -13,7 +13,7 @@ use specs::{prelude::*, ReadExpect, System, World, WriteExpect};

use crate::{
constants::{UNIFORM_BUFFER_INDEX_CAMERA, UNIFORM_BUFFER_INDEX_UNIFORM},
misc::{MouseEvent, WorldHelper},
misc::{ControlEvent, MouseButton, MouseEvent, WorldHelper},
resources::{Camera, Config, Geometry, State, Uniform},
Error,
};
@@ -52,6 +52,8 @@ impl Init {
pub struct InitData<'a> {
camera: WriteExpect<'a, Camera>,
uniform: WriteExpect<'a, Uniform>,
control_events: WriteExpect<'a, EventChannel<ControlEvent>>,

state: ReadExpect<'a, State>,
global: ReadExpect<'a, Global>,
config: ReadExpect<'a, Config>,
@@ -66,6 +68,7 @@ impl<'a> System<'a> for Init {
let InitData {
mut camera,
mut uniform,
mut control_events,
state,
global,
config,
@@ -87,27 +90,43 @@ impl<'a> System<'a> for Init {
/* zoom */
let events = mouse_events.read(&mut self.mouse_event_id);
for event in events {
if let MouseEvent::ScrollY(delta) = event {
let s = config.input.speed_camera_zoom;
let z = s / (s - delta);
let m = Matrix4f::translate((state.mouse_pos.0, state.mouse_pos.1, 0.0).into())
* Matrix4f::scale(z.into())
* Matrix4f::translate((-state.mouse_pos.0, -state.mouse_pos.1, 0.0).into());

camera
.update_with(move |v| m * v)
.error("Error while zooming camera");
match event {
MouseEvent::ScrollY(delta) => {
let s = config.input.camera_zoom_speed;
let z = s / (s - delta);
let m = Matrix4f::translate((state.mouse_pos.0, state.mouse_pos.1, 0.0).into())
* Matrix4f::scale(z.into())
* Matrix4f::translate((-state.mouse_pos.0, -state.mouse_pos.1, 0.0).into());

camera
.update_with(move |v| m * v)
.error("Error while zooming camera");
}
MouseEvent::Delta(x, y) if state.button_state(&[MouseButton::Right]) => {
let m = Matrix4f::translate((*x, -*y, 0.0).into());

camera
.update_with(move |v| m * v)
.error("Error while zooming camera");
}
MouseEvent::ButtonDown(b) if b == &config.input.camera_move_button => {
control_events.single_write(ControlEvent::LockMouse);
}
MouseEvent::ButtonUp(b) if b == &config.input.camera_move_button => {
control_events.single_write(ControlEvent::UnlockMouse);
}
_ => (),
}
}

/* move camera */
let up = state.key_state(&config.input.key_camera_move_up);
let down = state.key_state(&config.input.key_camera_move_down);
let left = state.key_state(&config.input.key_camera_move_left);
let right = state.key_state(&config.input.key_camera_move_right);
let up = state.key_state(&config.input.camera_move_key_up);
let down = state.key_state(&config.input.camera_move_key_down);
let left = state.key_state(&config.input.camera_move_key_left);
let right = state.key_state(&config.input.camera_move_key_right);

if up || down || left || right {
let s = config.input.speed_camera_move * global.delta;
let s = config.input.camera_move_speed * global.delta;
let translate = Vector3f::new(
if left { s } else { 0.0 } + if right { -s } else { 0.0 },
if up { -s } else { 0.0 } + if down { s } else { 0.0 },


+ 38
- 26
space-crush-app/src/resources/config.rs View File

@@ -5,7 +5,10 @@ use smallvec::{smallvec, SmallVec};
use space_crush_common::misc::{Vfs, WorldHelper as _};
use specs::World;

use crate::{misc::VirtualKeyCode, Error};
use crate::{
misc::{MouseButton, VirtualKeyCode},
Error,
};

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct Config {
@@ -30,19 +33,22 @@ pub struct Video {

#[derive(Debug, Serialize, Deserialize)]
pub struct Input {
#[serde(default = "defaults::key_camera_move_up")]
pub key_camera_move_up: VirtualKeyCodes,
#[serde(default = "defaults::key_camera_move_down")]
pub key_camera_move_down: VirtualKeyCodes,
#[serde(default = "defaults::key_camera_move_left")]
pub key_camera_move_left: VirtualKeyCodes,
#[serde(default = "defaults::key_camera_move_right")]
pub key_camera_move_right: VirtualKeyCodes,

#[serde(default = "defaults::speed_camera_move")]
pub speed_camera_move: f32,
#[serde(default = "defaults::speed_camera_zoom")]
pub speed_camera_zoom: f32,
#[serde(default = "defaults::camera_move_key_up")]
pub camera_move_key_up: VirtualKeyCodes,
#[serde(default = "defaults::camera_move_key_down")]
pub camera_move_key_down: VirtualKeyCodes,
#[serde(default = "defaults::camera_move_key_left")]
pub camera_move_key_left: VirtualKeyCodes,
#[serde(default = "defaults::camera_move_key_right")]
pub camera_move_key_right: VirtualKeyCodes,

#[serde(default = "defaults::camera_move_button")]
pub camera_move_button: MouseButton,

#[serde(default = "defaults::camera_move_speed")]
pub camera_move_speed: f32,
#[serde(default = "defaults::camera_zoom_speed")]
pub camera_zoom_speed: f32,
}

type VirtualKeyCodes = SmallVec<[VirtualKeyCode; 2]>;
@@ -80,13 +86,15 @@ impl Default for Video {
impl Default for Input {
fn default() -> Self {
Self {
key_camera_move_up: defaults::key_camera_move_up(),
key_camera_move_down: defaults::key_camera_move_down(),
key_camera_move_left: defaults::key_camera_move_left(),
key_camera_move_right: defaults::key_camera_move_right(),
camera_move_key_up: defaults::camera_move_key_up(),
camera_move_key_down: defaults::camera_move_key_down(),
camera_move_key_left: defaults::camera_move_key_left(),
camera_move_key_right: defaults::camera_move_key_right(),

speed_camera_move: defaults::speed_camera_move(),
speed_camera_zoom: defaults::speed_camera_zoom(),
camera_move_button: defaults::camera_move_button(),

camera_move_speed: defaults::camera_move_speed(),
camera_zoom_speed: defaults::camera_zoom_speed(),
}
}
}
@@ -110,27 +118,31 @@ mod defaults {
true
}

pub fn key_camera_move_up() -> VirtualKeyCodes {
pub fn camera_move_key_up() -> VirtualKeyCodes {
smallvec![VirtualKeyCode::W, VirtualKeyCode::Up]
}

pub fn key_camera_move_down() -> VirtualKeyCodes {
pub fn camera_move_key_down() -> VirtualKeyCodes {
smallvec![VirtualKeyCode::S, VirtualKeyCode::Down]
}

pub fn key_camera_move_left() -> VirtualKeyCodes {
pub fn camera_move_key_left() -> VirtualKeyCodes {
smallvec![VirtualKeyCode::A, VirtualKeyCode::Left]
}

pub fn key_camera_move_right() -> VirtualKeyCodes {
pub fn camera_move_key_right() -> VirtualKeyCodes {
smallvec![VirtualKeyCode::D, VirtualKeyCode::Right]
}

pub fn speed_camera_move() -> f32 {
pub fn camera_move_button() -> MouseButton {
MouseButton::Right
}

pub fn camera_move_speed() -> f32 {
500.0
}

pub fn speed_camera_zoom() -> f32 {
pub fn camera_zoom_speed() -> f32 {
100.0
}
}

Loading…
Cancel
Save