Encapsulated winit into solar_engine. No winit is required anymore within the API

This commit is contained in:
Verox001 2025-05-05 17:34:45 +02:00
parent 9a81d6d474
commit 03c061839c
5 changed files with 256 additions and 53 deletions

View File

@ -5,7 +5,6 @@ edition = "2021"
[dependencies] [dependencies]
solar_engine = { path = "../solar_engine" } solar_engine = { path = "../solar_engine" }
winit = "0.30.10"
log = "0.4" log = "0.4"
env_logger = "0.11.8" env_logger = "0.11.8"
pollster = "0.4.0" pollster = "0.4.0"

View File

@ -1,16 +1,9 @@
use cgmath::Rotation3; use cgmath::Rotation3;
use solar_engine::{Application, Body, Simulator}; use solar_engine::{Application, Body, Key, KeyState, Simulator};
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use std::thread; use std::thread;
use winit::event::ElementState;
use winit::event::WindowEvent::KeyboardInput;
use winit::event_loop::EventLoop;
use winit::keyboard::Key;
use winit::platform::modifier_supplement::KeyEventExtModifierSupplement;
pub async fn run() { pub async fn run() {
let event_loop = EventLoop::new().unwrap();
let simulator = Arc::new(RwLock::new(Simulator::new())); let simulator = Arc::new(RwLock::new(Simulator::new()));
{ {
let mut sim = simulator.write().unwrap(); let mut sim = simulator.write().unwrap();
@ -49,7 +42,8 @@ pub async fn run() {
let simulator_clone = simulator.clone(); let simulator_clone = simulator.clone();
let mut window_state = Application::new().on_update(move |state| { Application::new()
.on_update(move |state| {
let sim = simulator_clone.read().unwrap(); let sim = simulator_clone.read().unwrap();
let bodies = &sim.bodies; let bodies = &sim.bodies;
@ -76,32 +70,30 @@ pub async fn run() {
.collect(); .collect();
state.set_instances(instances); state.set_instances(instances);
}).on_input(move |_state, event| { })
if let KeyboardInput { event, .. } = event { .on_input(move |_state, event| {
if event.state == ElementState::Pressed { if event.state == KeyState::Pressed {
return match event.key_without_modifiers().as_ref() { return match event.key {
Key::Character(".") => { Key::Period => {
let mut sim = simulator.write().unwrap(); let mut sim = simulator.write().unwrap();
sim.increase_timewarp(); sim.increase_timewarp();
println!("Timewarp: {}", sim.get_timewarp()); println!("Timewarp: {}", sim.get_timewarp());
} }
Key::Character(",") => { Key::Comma => {
let mut sim = simulator.write().unwrap(); let mut sim = simulator.write().unwrap();
sim.decrease_timewarp(); sim.decrease_timewarp();
println!("Timewarp: {}", sim.get_timewarp()); println!("Timewarp: {}", sim.get_timewarp());
} }
Key::Character("-") => { Key::Minus => {
let mut sim = simulator.write().unwrap(); let mut sim = simulator.write().unwrap();
sim.reset_timewarp(); sim.reset_timewarp();
println!("Timewarp: {}", sim.get_timewarp()); println!("Timewarp: {}", sim.get_timewarp());
} }
_ => {} _ => {}
};
} }
} })
} .run();
});
let _ = event_loop.run_app(&mut window_state);
} }
fn main() { fn main() {

View File

@ -1,17 +1,19 @@
use winit::application::ApplicationHandler; use winit::application::ApplicationHandler;
use winit::event::WindowEvent; use winit::event::{Modifiers, WindowEvent};
use winit::event_loop::ActiveEventLoop; use winit::event_loop::ActiveEventLoop;
use winit::window::{Window, WindowId}; use winit::window::{Window, WindowId};
use crate::input::{from_winit_input, InputEvent};
pub struct StateApplication<'a> { pub struct StateApplication<'a> {
state: Option<crate::state::State<'a>>, state: Option<crate::state::State<'a>>,
modifiers: Modifiers,
update_fn: Option<Box<dyn FnMut(&mut crate::state::State<'a>) + 'a>>, update_fn: Option<Box<dyn FnMut(&mut crate::state::State<'a>) + 'a>>,
input_fn: Option<Box<dyn FnMut(&mut crate::state::State<'a>, &WindowEvent) + 'a>>, input_fn: Option<Box<dyn FnMut(&mut crate::state::State<'a>, &InputEvent) + 'a>>,
} }
impl<'a> StateApplication<'a> { impl<'a> StateApplication<'a> {
pub fn new() -> Self { pub fn new() -> Self {
Self { state: None, update_fn: None, input_fn: None } Self { state: None, update_fn: None, input_fn: None, modifiers: Modifiers::default() }
} }
pub fn on_update<F: FnMut(&mut crate::state::State<'a>) + 'a>(mut self, func: F) -> Self { pub fn on_update<F: FnMut(&mut crate::state::State<'a>) + 'a>(mut self, func: F) -> Self {
@ -19,10 +21,15 @@ impl<'a> StateApplication<'a> {
self self
} }
pub fn on_input<F: FnMut(&mut crate::state::State<'a>, &WindowEvent) + 'a>(mut self, func: F) -> Self { pub fn on_input<F: FnMut(&mut crate::state::State<'a>, &InputEvent) + 'a>(mut self, func: F) -> Self {
self.input_fn = Some(Box::new(func)); self.input_fn = Some(Box::new(func));
self self
} }
pub fn run(mut self) {
let event_loop = winit::event_loop::EventLoop::new().unwrap();
let _ = event_loop.run_app(&mut self);
}
} }
impl<'a> ApplicationHandler for StateApplication<'a> { impl<'a> ApplicationHandler for StateApplication<'a> {
@ -56,13 +63,17 @@ impl<'a> ApplicationHandler for StateApplication<'a> {
self.state.as_mut().unwrap().render().unwrap(); self.state.as_mut().unwrap().render().unwrap();
} }
WindowEvent::KeyboardInput { .. } => { WindowEvent::KeyboardInput { event, .. } => {
if let Some(state) = self.state.as_mut() { if let Some(state) = self.state.as_mut() {
if let Some(input_fn) = self.input_fn.as_mut() { if let Some(input_fn) = self.input_fn.as_mut() {
input_fn(state, &event); let key_event = from_winit_input(&event, self.modifiers);
input_fn(state, &key_event);
} }
} }
} }
WindowEvent::ModifiersChanged(modifiers) => {
self.modifiers = modifiers;
}
_ => {} _ => {}
} }
} }

191
solar_engine/src/input.rs Normal file
View File

@ -0,0 +1,191 @@
use winit::event::{ElementState, KeyEvent, Modifiers};
use winit::keyboard::{Key as WinitKey, ModifiersKeyState};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Key {
// Symbols
Comma, Period, Minus, Plus, Slash, Backslash, Semicolon, Apostrophe,
LeftBracket, RightBracket, Grave, Equal,
// Digits
Num0, Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9,
// Letters
A, B, C, D, E, F, G, H, I, J, K, L, M,
N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
// Arrows
ArrowUp, ArrowDown, ArrowLeft, ArrowRight,
// Controls
Escape, Enter, Space, Tab, Backspace,
Insert, Delete, Home, End, PageUp, PageDown,
// Modifier keys
Shift, Control, Alt, Super,
// Function keys
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
// Numpad
Numpad0, Numpad1, Numpad2, Numpad3, Numpad4,
Numpad5, Numpad6, Numpad7, Numpad8, Numpad9,
NumpadAdd, NumpadSubtract, NumpadMultiply, NumpadDivide, NumpadEnter,
// Unknown
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KeyState {
Pressed,
Released,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct KeyModifiers {
pub lshift: bool,
pub rshift: bool,
pub lcontrol: bool,
pub rcontrol: bool,
pub lalt: bool,
pub ralt: bool,
pub rsuper_key: bool,
pub lsuper_key: bool,
}
#[derive(Debug, Clone)]
pub struct InputEvent {
pub key: Key,
pub state: KeyState,
pub text: String,
pub modifiers: KeyModifiers,
}
pub fn from_winit_input(event: &KeyEvent, modifiers: Modifiers) -> InputEvent {
InputEvent {
key: map_winit_key(&event.logical_key),
state: match event.state {
ElementState::Pressed => KeyState::Pressed,
ElementState::Released => KeyState::Released,
},
text: event.text.clone().unwrap_or_default().into(),
modifiers: KeyModifiers {
lshift: modifiers.lshift_state() == ModifiersKeyState::Pressed,
rshift: modifiers.rshift_state() == ModifiersKeyState::Pressed,
lcontrol: modifiers.lcontrol_state() == ModifiersKeyState::Pressed,
rcontrol: modifiers.rcontrol_state() == ModifiersKeyState::Pressed,
lalt: modifiers.lalt_state() == ModifiersKeyState::Pressed,
ralt: modifiers.ralt_state() == ModifiersKeyState::Pressed,
rsuper_key: modifiers.rsuper_state() == ModifiersKeyState::Pressed,
lsuper_key: modifiers.lsuper_state() == ModifiersKeyState::Pressed,
},
}
}
pub fn map_winit_key(key: &WinitKey) -> Key {
use Key::*;
match key {
WinitKey::Character(s) => match s.as_str() {
"a" | "A" => A,
"b" | "B" => B,
"c" | "C" => C,
"d" | "D" => D,
"e" | "E" => E,
"f" | "F" => F,
"g" | "G" => G,
"h" | "H" => H,
"i" | "I" => I,
"j" | "J" => J,
"k" | "K" => K,
"l" | "L" => L,
"m" | "M" => M,
"n" | "N" => N,
"o" | "O" => O,
"p" | "P" => P,
"q" | "Q" => Q,
"r" | "R" => R,
"s" | "S" => S,
"t" | "T" => T,
"u" | "U" => U,
"v" | "V" => V,
"w" | "W" => W,
"x" | "X" => X,
"y" | "Y" => Y,
"z" | "Z" => Z,
"0" => Num0,
"1" => Num1,
"2" => Num2,
"3" => Num3,
"4" => Num4,
"5" => Num5,
"6" => Num6,
"7" => Num7,
"8" => Num8,
"9" => Num9,
"," => Comma,
"." => Period,
"-" => Minus,
"+" => Plus,
"/" => Slash,
"\\" => Backslash,
";" => Semicolon,
"'" => Apostrophe,
"[" => LeftBracket,
"]" => RightBracket,
"`" => Grave,
"=" => Equal,
_ => Unknown,
},
WinitKey::Named(n) => match n.to_text().unwrap_or("") {
"ArrowUp" => ArrowUp,
"ArrowDown" => ArrowDown,
"ArrowLeft" => ArrowLeft,
"ArrowRight" => ArrowRight,
"Escape" => Escape,
"Enter" => Enter,
"Tab" => Tab,
"Space" => Space,
"Backspace" => Backspace,
"Insert" => Insert,
"Delete" => Delete,
"Home" => Home,
"End" => End,
"PageUp" => PageUp,
"PageDown" => PageDown,
"Shift" => Shift,
"Control" => Control,
"Alt" => Alt,
"Super" => Super,
"F1" => F1,
"F2" => F2,
"F3" => F3,
"F4" => F4,
"F5" => F5,
"F6" => F6,
"F7" => F7,
"F8" => F8,
"F9" => F9,
"F10" => F10,
"F11" => F11,
"F12" => F12,
"Numpad0" => Numpad0,
"Numpad1" => Numpad1,
"Numpad2" => Numpad2,
"Numpad3" => Numpad3,
"Numpad4" => Numpad4,
"Numpad5" => Numpad5,
"Numpad6" => Numpad6,
"Numpad7" => Numpad7,
"Numpad8" => Numpad8,
"Numpad9" => Numpad9,
"NumpadAdd" => NumpadAdd,
"NumpadSubtract" => NumpadSubtract,
"NumpadMultiply" => NumpadMultiply,
"NumpadDivide" => NumpadDivide,
"NumpadEnter" => NumpadEnter,
_ => Unknown,
},
_ => Unknown,
}
}

View File

@ -3,11 +3,21 @@ mod simulator;
mod state; mod state;
mod render; mod render;
mod application; mod application;
mod input;
pub use body::Body; pub use body::Body;
pub use simulator::Simulator; pub use simulator::Simulator;
pub use simulator::distance_squared; pub use simulator::distance_squared;
pub use application::StateApplication as Application; pub use application::StateApplication as Application;
pub use render::RenderInstance; pub use render::RenderInstance;
pub use render::Shape; pub use render::Shape;
pub use state::State; pub use state::State;
pub use input::Key;
pub use input::map_winit_key;
pub use input::InputEvent;
pub use input::KeyState;