Giant refactor for a better event-driven architecture
This commit is contained in:
parent
341d531db3
commit
88a21040cd
22 changed files with 936 additions and 67 deletions
|
|
@ -5,4 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
winit = "0.30"
|
||||
glam = "0.30.4"
|
||||
glam = "0.30.4"
|
||||
hecs = "0.10.5"
|
||||
raidillon_core = { path = "../raidillon_core" }
|
||||
raidillon_render = { path = "../raidillon_render" }
|
||||
109
raidillon_input/src/camera_system.rs
Normal file
109
raidillon_input/src/camera_system.rs
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
use hecs::{Entity, World};
|
||||
use raidillon_core::{EventHandler, GameEvent, InputAction, System, AssetManager, Model, Material, EventBus};
|
||||
use raidillon_render::Camera;
|
||||
use crate::FPSCameraController;
|
||||
use glam::Vec3;
|
||||
|
||||
pub struct CameraSystem {
|
||||
controller: FPSCameraController,
|
||||
camera_entity: Entity,
|
||||
yaw: f32,
|
||||
pitch: f32,
|
||||
}
|
||||
|
||||
impl CameraSystem {
|
||||
pub fn new(camera_entity: Entity) -> Self {
|
||||
Self {
|
||||
controller: FPSCameraController::new(Vec3::new(0.0, 0.0, 2.0)),
|
||||
camera_entity,
|
||||
yaw: -90.0,
|
||||
pitch: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, world: &mut World, dt: f32, mouse_delta: (f64, f64)) {
|
||||
// Apply mouse movement if there's any
|
||||
if mouse_delta.0 != 0.0 || mouse_delta.1 != 0.0 {
|
||||
self.yaw += mouse_delta.0 as f32 * self.controller.sensitivity;
|
||||
self.pitch -= mouse_delta.1 as f32 * self.controller.sensitivity;
|
||||
self.pitch = self.pitch.clamp(-89.0, 89.0);
|
||||
|
||||
// Update front vector based on new yaw/pitch
|
||||
let yaw_rad = self.yaw.to_radians();
|
||||
let pitch_rad = self.pitch.to_radians();
|
||||
let front = Vec3::new(
|
||||
yaw_rad.cos() * pitch_rad.cos(),
|
||||
pitch_rad.sin(),
|
||||
yaw_rad.sin() * pitch_rad.cos(),
|
||||
).normalize();
|
||||
}
|
||||
|
||||
// Update camera component in the world
|
||||
if let Ok(cam) = world.query_one_mut::<&mut Camera>(self.camera_entity) {
|
||||
cam.eye = self.controller.position;
|
||||
cam.center = self.controller.position + self.controller.front();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_input_action(&mut self, action: InputAction, dt: f32) {
|
||||
let front = self.controller.front();
|
||||
let right = front.cross(Vec3::Y).normalize();
|
||||
let frame_speed = self.controller.speed * dt;
|
||||
|
||||
match action {
|
||||
InputAction::MoveForward => {
|
||||
self.controller.position += front * frame_speed;
|
||||
}
|
||||
InputAction::MoveBackward => {
|
||||
self.controller.position -= front * frame_speed;
|
||||
}
|
||||
InputAction::MoveLeft => {
|
||||
self.controller.position -= right * frame_speed;
|
||||
}
|
||||
InputAction::MoveRight => {
|
||||
self.controller.position += right * frame_speed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resize_camera(&mut self, world: &mut World, width: u32, height: u32) {
|
||||
if let Ok(cam) = world.query_one_mut::<&mut Camera>(self.camera_entity) {
|
||||
cam.aspect = width as f32 / height as f32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EventHandler for CameraSystem {
|
||||
fn handle(&mut self, event: &GameEvent) {
|
||||
match event {
|
||||
GameEvent::InputAction(_action) => {
|
||||
// Movement will be handled separately with delta time
|
||||
// This is just for event registration
|
||||
}
|
||||
GameEvent::WindowResize { width: _, height: _ } => {
|
||||
// Window resize will be handled separately with world access
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl System for CameraSystem {
|
||||
fn update(&mut self, world: &mut World, _resources: &AssetManager<dyn Model, dyn Material>, _events: &mut EventBus, _dt: f32) {
|
||||
// Camera update logic is handled separately with mouse input
|
||||
// This system mainly responds to events
|
||||
}
|
||||
|
||||
fn handle_event(&mut self, event: &GameEvent, world: &mut World) {
|
||||
match event {
|
||||
GameEvent::WindowResize { width, height } => {
|
||||
self.resize_camera(world, *width, *height);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"CameraSystem"
|
||||
}
|
||||
}
|
||||
64
raidillon_input/src/input_system.rs
Normal file
64
raidillon_input/src/input_system.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
use raidillon_core::{EventBus, GameEvent, InputAction, System, AssetManager, Model, Material};
|
||||
use crate::Input;
|
||||
use hecs::World;
|
||||
|
||||
pub struct InputSystem {
|
||||
input: Input<InputAction>,
|
||||
}
|
||||
|
||||
impl InputSystem {
|
||||
pub fn new() -> Self {
|
||||
let mut input = Input::<InputAction>::new();
|
||||
input.map_key(winit::keyboard::KeyCode::KeyW, InputAction::MoveForward);
|
||||
input.map_key(winit::keyboard::KeyCode::KeyS, InputAction::MoveBackward);
|
||||
input.map_key(winit::keyboard::KeyCode::KeyA, InputAction::MoveLeft);
|
||||
input.map_key(winit::keyboard::KeyCode::KeyD, InputAction::MoveRight);
|
||||
|
||||
Self { input }
|
||||
}
|
||||
|
||||
pub fn handle_event<T>(&mut self, event: &winit::event::Event<T>) {
|
||||
self.input.handle_event(event);
|
||||
}
|
||||
|
||||
pub fn update(&mut self, event_bus: &mut EventBus, right_mouse_held: bool) {
|
||||
if right_mouse_held {
|
||||
if self.input.action_held(InputAction::MoveForward) {
|
||||
event_bus.emit(GameEvent::InputAction(InputAction::MoveForward));
|
||||
}
|
||||
if self.input.action_held(InputAction::MoveBackward) {
|
||||
event_bus.emit(GameEvent::InputAction(InputAction::MoveBackward));
|
||||
}
|
||||
if self.input.action_held(InputAction::MoveLeft) {
|
||||
event_bus.emit(GameEvent::InputAction(InputAction::MoveLeft));
|
||||
}
|
||||
if self.input.action_held(InputAction::MoveRight) {
|
||||
event_bus.emit(GameEvent::InputAction(InputAction::MoveRight));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end_frame(&mut self) {
|
||||
self.input.end_frame();
|
||||
}
|
||||
|
||||
pub fn mouse_delta(&self) -> (f64, f64) {
|
||||
self.input.mouse_delta()
|
||||
}
|
||||
}
|
||||
|
||||
impl System for InputSystem {
|
||||
fn update(&mut self, _world: &mut World, _resources: &AssetManager<dyn Model, dyn Material>, _events: &mut EventBus, _dt: f32) {
|
||||
// Input processing is handled separately in the main loop
|
||||
// This system mainly generates events based on input state
|
||||
}
|
||||
|
||||
fn handle_event(&mut self, _event: &GameEvent, _world: &mut World) {
|
||||
// InputSystem doesn't need to respond to events
|
||||
// It generates events based on input state
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"InputSystem"
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,12 @@ use winit::event::{DeviceEvent, ElementState, Event, WindowEvent};
|
|||
use winit::keyboard::{KeyCode, PhysicalKey};
|
||||
|
||||
pub mod camera;
|
||||
pub mod input_system;
|
||||
pub mod camera_system;
|
||||
|
||||
pub use camera::FPSCameraController;
|
||||
pub use input_system::InputSystem;
|
||||
pub use camera_system::CameraSystem;
|
||||
|
||||
pub struct Input<A: Copy + Eq + Hash> {
|
||||
pressed_keys: HashSet<KeyCode>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue