diff --git a/Cargo.toml b/Cargo.toml index 360b6ce..c5d43ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,7 @@ hostname = { version = "0.4.0" } trust-dns-resolver = { version = "0.23.2" } openxr = { version = "0.19.0", default-features = false, features = ["static"] } openvr = { version = "0.7.0" } -sdl2 = { version = "0.37.0" } +sdl3 = { version = "0.14.19" } syn = { version = "2.0.67", features = ["extra-traits", "full"] } quote = "1.0.35" proc-macro2 = "1.0.86" diff --git a/context/src/core/configs.rs b/context/src/core/configs.rs index 0a4fbb4..5dd6a9a 100644 --- a/context/src/core/configs.rs +++ b/context/src/core/configs.rs @@ -1,4 +1,3 @@ -use crate::prelude::*; use presentation::wsi::windowsystemintegration::WindowSystemIntegration; use anyhow::Result; @@ -59,10 +58,6 @@ impl<'a> WindowConfig<'a> { Ok(()) } - pub fn displays(&self) -> &[Display] { - self.wsi.displays() - } - pub fn clipboard_content(&self) -> Result> { self.wsi.clipboard_content() } diff --git a/context/src/core/context.rs b/context/src/core/context.rs index 4a49a3a..fe9b965 100644 --- a/context/src/core/context.rs +++ b/context/src/core/context.rs @@ -236,7 +236,6 @@ impl Default for ContextBuilder { width: 800, height: 600, fullscreen: false, - requested_display: None, }, // os specifics @@ -425,14 +424,6 @@ impl ContextBuilder { presentation.event_system_mut().enable_mouse(); } - if self.enable_keyboard { - presentation.event_system_mut().enable_keyboard(); - } - - if self.enable_controller { - presentation.event_system_mut().enable_controller(); - } - Ok(Context { core, presentation, diff --git a/engine/src/engine/engine_create_info.rs b/engine/src/engine/engine_create_info.rs index 17616f8..28e3943 100644 --- a/engine/src/engine/engine_create_info.rs +++ b/engine/src/engine/engine_create_info.rs @@ -48,7 +48,6 @@ impl<'a> Default for EngineCreateInfo<'a> { width: 1600, height: 900, fullscreen: false, - requested_display: None, }, os_specific_config: OsSpecificConfig { enable_game_mode: true, diff --git a/presentation/Cargo.toml b/presentation/Cargo.toml index 6ace477..67a4e0f 100644 --- a/presentation/Cargo.toml +++ b/presentation/Cargo.toml @@ -7,7 +7,7 @@ edition = "2024" [dependencies] vulkan-rs = { workspace = true } ui = { workspace = true } -sdl2 = { workspace = true } +sdl3 = { workspace = true } anyhow = { workspace = true } openxr = { workspace = true, optional = true } @@ -18,5 +18,5 @@ ecs = { workspace = true } [features] OpenXR = ["openxr"] OpenVR = ["openvr"] -BundleSDL = ["sdl2/bundled", "sdl2/static-link"] +BundleSDL = ["sdl3/build-from-source-static"] sound = ["ui/audio"] diff --git a/presentation/src/input/controller.rs b/presentation/src/input/controller.rs index 3c9e196..c27529f 100644 --- a/presentation/src/input/controller.rs +++ b/presentation/src/input/controller.rs @@ -3,7 +3,7 @@ use ui::prelude::*; use super::controlleraxis::ControllerAxis; -use sdl2::{self, GameControllerSubsystem}; +use sdl3::{self, GamepadSubsystem}; #[derive(PartialEq)] enum State { @@ -32,7 +32,7 @@ impl Default for ControllerDeadzones { } pub struct Controller { - _sdl2_controller: sdl2::controller::GameController, + _sdl2_controller: sdl3::gamepad::Gamepad, name: String, id: u32, @@ -51,7 +51,7 @@ pub struct Controller { impl Controller { pub fn new( - controller_subsystem: &GameControllerSubsystem, + controller_subsystem: &GamepadSubsystem, id: u32, deadzones: ControllerDeadzones, ) -> Result { diff --git a/presentation/src/input/eventsystem.rs b/presentation/src/input/eventsystem.rs index d19997c..c41d6c2 100644 --- a/presentation/src/input/eventsystem.rs +++ b/presentation/src/input/eventsystem.rs @@ -1,30 +1,27 @@ -use sdl2; -use sdl2::EventPump; -use sdl2::EventSubsystem; -use sdl2::GameControllerSubsystem; -use sdl2::JoystickSubsystem; -use sdl2::Sdl; -use sdl2::controller::Axis; -use sdl2::controller::Button; -use sdl2::event::{Event as SdlEvent, EventType as SdlEventType, WindowEvent}; -use sdl2::keyboard::Keycode; -use sdl2::mouse::{MouseButton as SdlMouseButton, MouseUtil, MouseWheelDirection}; +use sdl3::{ + self, EventPump, EventSubsystem, GamepadSubsystem, JoystickSubsystem, Sdl, + event::{Event as SdlEvent, WindowEvent}, + gamepad::{Axis, Button}, + keyboard::Keycode, + mouse::{MouseButton as SdlMouseButton, MouseUtil, MouseWheelDirection}, +}; use ui::prelude::*; use std::collections::HashMap; use crate::Result; +use anyhow::anyhow; use super::controller::{Controller, ControllerDeadzones}; use super::joystick::Joystick; fn convert_button(button: Button) -> ControllerButton { match button { - Button::A => ControllerButton::A, - Button::B => ControllerButton::B, - Button::Y => ControllerButton::Y, - Button::X => ControllerButton::X, + Button::South => ControllerButton::A, + Button::East => ControllerButton::B, + Button::North => ControllerButton::Y, + Button::West => ControllerButton::X, Button::Start => ControllerButton::Start, Button::Back => ControllerButton::Select, @@ -44,10 +41,10 @@ fn convert_button(button: Button) -> ControllerButton { Button::Misc1 => ControllerButton::Misc, - Button::Paddle1 => ControllerButton::Paddle1, - Button::Paddle2 => ControllerButton::Paddle2, - Button::Paddle3 => ControllerButton::Paddle3, - Button::Paddle4 => ControllerButton::Paddle4, + Button::RightPaddle1 => ControllerButton::Paddle1, + Button::RightPaddle2 => ControllerButton::Paddle2, + Button::LeftPaddle1 => ControllerButton::Paddle3, + Button::LeftPaddle2 => ControllerButton::Paddle4, Button::Touchpad => ControllerButton::Touchpad, } @@ -87,7 +84,7 @@ pub enum Event<'a> { pub struct EventSystem { event_pump: EventPump, mouse: MouseUtil, - controller_subsystem: GameControllerSubsystem, + controller_subsystem: GamepadSubsystem, joystick_subsystem: JoystickSubsystem, event_subsystem: EventSubsystem, @@ -104,9 +101,7 @@ impl EventSystem { .event_pump() .map_err(|s| anyhow::Error::msg(s))?, mouse: sdl2_context.mouse(), - controller_subsystem: sdl2_context - .game_controller() - .map_err(|s| anyhow::Error::msg(s))?, + controller_subsystem: sdl2_context.gamepad().map_err(|s| anyhow::Error::msg(s))?, joystick_subsystem: sdl2_context.joystick().map_err(|s| anyhow::Error::msg(s))?, event_subsystem: sdl2_context.event().map_err(|s| anyhow::Error::msg(s))?, @@ -116,17 +111,22 @@ impl EventSystem { connected_joysticks: HashMap::new(), }; - event_system.connected_joysticks = (0..event_system + event_system.connected_joysticks = event_system .joystick_subsystem - .num_joysticks() - .map_err(|s| anyhow::Error::msg(s))?) + .joysticks() + .map_err(|s| anyhow::Error::msg(s))? .into_iter() - .map(|i| Ok((i, Joystick::new(&event_system.joystick_subsystem, i)?))) + .map(|instance| { + Ok(( + instance.id, + Joystick::new(&event_system.joystick_subsystem, instance)?, + )) + }) .collect::>>()?; event_system.connected_controllers = (0..event_system .controller_subsystem - .num_joysticks() + .num_gamepads() .map_err(|s| anyhow::Error::msg(s))?) .into_iter() .filter(|i| event_system.controller_subsystem.is_game_controller(*i)) @@ -143,56 +143,18 @@ impl EventSystem { .collect::>>()?; event_system.disable_mouse(); - event_system.disable_keyboard(); - event_system.disable_controller(); Ok(event_system) } pub fn enable_mouse(&mut self) { - self.event_pump.enable_event(SdlEventType::MouseMotion); - self.event_pump.enable_event(SdlEventType::MouseButtonDown); - self.event_pump.enable_event(SdlEventType::MouseButtonUp); - self.mouse.show_cursor(true); } pub fn disable_mouse(&mut self) { - self.event_pump.disable_event(SdlEventType::MouseMotion); - self.event_pump.disable_event(SdlEventType::MouseButtonDown); - self.event_pump.disable_event(SdlEventType::MouseButtonUp); - self.mouse.show_cursor(false); } - pub fn enable_keyboard(&mut self) { - self.event_pump.enable_event(SdlEventType::KeyUp); - self.event_pump.enable_event(SdlEventType::KeyDown); - } - - pub fn disable_keyboard(&mut self) { - self.event_pump.disable_event(SdlEventType::KeyUp); - self.event_pump.disable_event(SdlEventType::KeyDown); - } - - pub fn enable_controller(&mut self) { - self.event_pump - .enable_event(SdlEventType::ControllerAxisMotion); - self.event_pump - .enable_event(SdlEventType::ControllerButtonDown); - self.event_pump - .enable_event(SdlEventType::ControllerButtonUp); - } - - pub fn disable_controller(&mut self) { - self.event_pump - .disable_event(SdlEventType::ControllerAxisMotion); - self.event_pump - .disable_event(SdlEventType::ControllerButtonDown); - self.event_pump - .disable_event(SdlEventType::ControllerButtonUp); - } - pub fn set_controller_axis_enable_deadzone(&mut self, deadzone: f32) { self.controller_deadzones.axis_enable_deadzone = deadzone; } @@ -224,7 +186,7 @@ impl EventSystem { for event in self.event_pump.poll_iter() { match event { SdlEvent::Window { win_event, .. } => match win_event { - WindowEvent::Resized(w, h) | WindowEvent::SizeChanged(w, h) => { + WindowEvent::Resized(w, h) => { resize(w as u32, h as u32)?; } @@ -262,7 +224,7 @@ impl EventSystem { SdlEvent::MouseWheel { x, y, direction, .. } => { - event_callback(Event::MouseWheel(x, y, direction))?; + event_callback(Event::MouseWheel(x as i32, y as i32, direction))?; } // ------------------- Key Events --------------------- SdlEvent::KeyDown { @@ -370,10 +332,18 @@ impl EventSystem { event_callback(Event::ControllerAxis(&*controller))?; } SdlEvent::JoyDeviceAdded { which, .. } => { - let joystick = Joystick::new(&self.joystick_subsystem, which)?; + if let Some(joystick_instance) = self + .joystick_subsystem + .joysticks() + .map_err(|_| anyhow!("failed querying joysticks"))? + .into_iter() + .find(|instance| instance.id == which) + { + let joystick = Joystick::new(&self.joystick_subsystem, joystick_instance)?; - event_callback(Event::JoystickAdded(&joystick))?; - self.connected_joysticks.insert(joystick.id(), joystick); + event_callback(Event::JoystickAdded(&joystick))?; + self.connected_joysticks.insert(joystick.id(), joystick); + } } SdlEvent::JoyDeviceRemoved { which, .. } => { if let Some(joysticks) = self.connected_joysticks.remove(&which) { diff --git a/presentation/src/input/joystick.rs b/presentation/src/input/joystick.rs index 592c822..28c041d 100644 --- a/presentation/src/input/joystick.rs +++ b/presentation/src/input/joystick.rs @@ -1,25 +1,24 @@ use anyhow::Result; -use sdl2::JoystickSubsystem; +use sdl3::{JoystickSubsystem, joystick::JoystickInstance}; pub struct Joystick { - _sdl2_joystick: sdl2::joystick::Joystick, - id: u32, + sdl2_joystick: sdl3::joystick::Joystick, + name: String, } impl Joystick { - pub fn new(joystick_subsystem: &JoystickSubsystem, id: u32) -> Result { - let sdl2_joystick = joystick_subsystem.open(id)?; + pub fn new(joystick_subsystem: &JoystickSubsystem, instance: JoystickInstance) -> Result { + let sdl2_joystick = joystick_subsystem.open(instance)?; Ok(Self { name: sdl2_joystick.name(), - id, - _sdl2_joystick: sdl2_joystick, + sdl2_joystick, }) } pub fn id(&self) -> u32 { - self.id + self.sdl2_joystick.instance_id() } pub fn name(&self) -> &str { @@ -30,7 +29,7 @@ impl Joystick { impl std::fmt::Debug for Joystick { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Joystick") - .field("id", &self.id) + .field("id", &self.id()) .field("name", &self.name) .finish() } diff --git a/presentation/src/prelude.rs b/presentation/src/prelude.rs index 4291c32..76dafb0 100644 --- a/presentation/src/prelude.rs +++ b/presentation/src/prelude.rs @@ -16,7 +16,7 @@ pub use crate::input::{ // wsi pub use crate::wsi::windowsystemintegration::{Display, WindowCreateInfo}; -pub use sdl2::{keyboard::Keycode, mouse::MouseWheelDirection}; +pub use sdl3::{keyboard::Keycode, mouse::MouseWheelDirection}; pub use vulkan_rs::prelude::*; diff --git a/presentation/src/presentationcore.rs b/presentation/src/presentationcore.rs index b8e87e5..31d5794 100644 --- a/presentation/src/presentationcore.rs +++ b/presentation/src/presentationcore.rs @@ -7,7 +7,7 @@ use crate::xri::openxrintegration::OpenXRIntegration; use crate::Result; use vulkan_rs::prelude::*; -use sdl2::Sdl; +use sdl3::Sdl; use std::sync::{Arc, Mutex}; @@ -88,8 +88,8 @@ impl PresentationCore { window_create_info: &WindowCreateInfo, appl_info: ApplicationInfo, ) -> Result { - // create sdl2 context - let context = sdl2::init().map_err(|s| anyhow::Error::msg(s))?; + // create sdl3 context + let context = sdl3::init().map_err(|s| anyhow::Error::msg(s))?; Ok(PresentationCore { event_system: EventSystem::new(&context)?, diff --git a/presentation/src/wsi/windowsystemintegration.rs b/presentation/src/wsi/windowsystemintegration.rs index bad05c1..3466c03 100644 --- a/presentation/src/wsi/windowsystemintegration.rs +++ b/presentation/src/wsi/windowsystemintegration.rs @@ -1,20 +1,20 @@ // needed since RLS won't accept #[repr(C)] #![allow(improper_ctypes)] -use anyhow::Error; -use sdl2; -use sdl2::Sdl; -use sdl2::clipboard::ClipboardUtil; -use sdl2::messagebox::{MessageBoxFlag, show_simple_message_box}; -use sdl2::mouse::Cursor; -use sdl2::surface::Surface as SDL_Surface; -use sdl2::sys::SDL_Window; -use sdl2::video::{FullscreenType, WindowPos}; +use anyhow::{Error, anyhow}; + +use sdl3::{ + self, Sdl, + clipboard::ClipboardUtil, + messagebox::{MessageBoxFlag, show_simple_message_box}, + mouse::Cursor, + surface::Surface as SDL_Surface, + video::{FullscreenType, WindowPos}, +}; use crate::Result; use vulkan_rs::prelude::*; -use std::mem::MaybeUninit; use std::ops::Deref; use std::path::Path; use std::sync::{ @@ -22,30 +22,12 @@ use std::sync::{ atomic::{AtomicI32, AtomicU32, Ordering::SeqCst}, }; -const SDL_SYSWM_WINDOWS: u32 = 0x1; -const SDL_SYSWM_X11: u32 = 0x2; -const SDL_SYSWM_COCOA: u32 = 0x4; -const SDL_SYSWM_WAYLAND: u32 = 0x6; -const SDL_SYSWM_ANDROID: u32 = 0x9; - -#[repr(C)] -struct SdlSysWmInfo { - version: sdl2::version::Version, - subsystem: u32, - info: [u64; 32], -} - -unsafe extern "C" { - fn SDL_GetWindowWMInfo(window: *const sdl2::sys::SDL_Window, info: *mut SdlSysWmInfo) -> bool; -} - #[derive(Default, Debug, Clone)] pub struct WindowCreateInfo { pub title: String, pub width: u32, pub height: u32, pub fullscreen: bool, - pub requested_display: Option, } #[derive(Debug)] @@ -57,8 +39,6 @@ pub struct Display { pub y: i32, pub w: u32, pub h: u32, - - pub dpi: [f32; 3], } #[derive(Default, Debug)] @@ -70,7 +50,7 @@ struct CellRect { } impl CellRect { - fn update_from_window(&self, window: &sdl2::video::Window) { + fn update_from_window(&self, window: &sdl3::video::Window) { let (w, h) = window.size(); let (x, y) = window.position(); @@ -80,7 +60,7 @@ impl CellRect { self.height.store(h, SeqCst); } - fn update_to_window(&self, window: &mut sdl2::video::Window) -> Result<()> { + fn update_to_window(&self, window: &mut sdl3::video::Window) -> Result<()> { set_window_size(window, self.width.load(SeqCst), self.height.load(SeqCst))?; window.set_position( WindowPos::Positioned(self.x.load(SeqCst)), @@ -93,15 +73,12 @@ impl CellRect { pub struct WindowSystemIntegration { // sdl - _video_subsystem: Mutex, - window: Mutex, + _video_subsystem: Mutex, + window: Mutex, clipboard_util: ClipboardUtil, cursor: Mutex>, - displays: Vec, - _enabled_display_index: usize, - pre_fullscreen_rect: CellRect, surface: Mutex>>, @@ -119,8 +96,8 @@ impl WindowSystemIntegration { let video_subsystem = context.video().map_err(|s| anyhow::Error::msg(s))?; // query display count - let display_count = match video_subsystem.num_video_displays() { - Ok(num_displays) => num_displays, + let display_count = match video_subsystem.displays() { + Ok(displays) => displays.len(), Err(_) => 0, }; @@ -128,78 +105,35 @@ impl WindowSystemIntegration { return Err(anyhow::Error::msg("No display where detected!")); } - // query display information - let mut displays = Vec::with_capacity(display_count as usize); + // // query display information + // let mut displays = Vec::with_capacity(display_count as usize); - for i in 0..display_count { - let rect = video_subsystem - .display_bounds(i) - .map_err(|s| anyhow::Error::msg(s))?; - let name = video_subsystem - .display_name(i) - .map_err(|s| anyhow::Error::msg(s))?; + // for display in video_subsystem + // .displays() + // .map_err(|_| anyhow!("failed querying displays"))? + // { + // let rect = display.get_bounds().map_err(|s| anyhow::Error::msg(s))?; + // let name = display.get_name().map_err(|s| anyhow::Error::msg(s))?; - let (dpi0, dpi1, dpi2) = match video_subsystem.display_dpi(i) { - Ok(dpis) => dpis, - Err(msg) => { - println!("failed getting dpi for display {} ({}): {}", i, name, msg); - (0.0, 0.0, 0.0) - } - }; + // let display = Display { + // name, - let display = Display { - name, + // x: rect.x(), + // y: rect.y(), + // w: rect.width(), + // h: rect.height(), + // }; - x: rect.x(), - y: rect.y(), - w: rect.width(), - h: rect.height(), - - dpi: [dpi0, dpi1, dpi2], - }; - - displays.push(display); - } - - // check if there is an preferred display - let mut display_index = None; - - if let Some(requested_display) = &create_info.requested_display { - match displays - .iter() - .position(|display| display.name == *requested_display) - { - Some(index) => display_index = Some(index), - None => { - println!("could not find display: {}", requested_display); - println!("defaulting to display 0 ({})", displays[0].name); - } - } - } + // displays.push(display); + // } // build window let mut window_builder = video_subsystem.window(&create_info.title, create_info.width, create_info.height); window_builder.resizable().vulkan(); - - match display_index { - Some(index) => { - let display = &displays[index]; - - window_builder.position( - display.x + display.w as i32 / 2, - display.y + display.h as i32 / 2, - ); - } - None => { - window_builder.position_centered(); - } - } - + window_builder.position_centered(); let window = window_builder.build()?; - display_index = Some(window.display_index().map_err(|s| anyhow::Error::msg(s))? as usize); - let rect = CellRect::default(); rect.update_from_window(&window); @@ -210,10 +144,6 @@ impl WindowSystemIntegration { cursor: Mutex::new(None), - displays, - - _enabled_display_index: display_index.expect("display index not set"), - pre_fullscreen_rect: rect, surface: Mutex::new(None), @@ -246,20 +176,21 @@ impl WindowSystemIntegration { self.pre_fullscreen_rect.update_from_window(&window); // set fullscreen size to fit display - let display = - &self.displays[window.display_index().map_err(|s| anyhow::Error::msg(s))? as usize]; - set_window_size(&mut window, display.w, display.h)?; + let display = window.get_display().map_err(|s| anyhow!(s))?; + let rect = display.get_bounds().map_err(|s| anyhow!(s))?; + + set_window_size(&mut window, rect.w as u32, rect.h as u32)?; window.set_bordered(false); // change fullscreen mode window - .set_fullscreen(FullscreenType::True) + .set_fullscreen(true) .map_err(|s| anyhow::Error::msg(s))?; } else { // change fullscreen mode window - .set_fullscreen(FullscreenType::Off) + .set_fullscreen(false) .map_err(|s| anyhow::Error::msg(s))?; // force window borders @@ -371,22 +302,16 @@ impl WindowSystemIntegration { Ok(()) } - fn raw_sdl2_window(&self) -> *mut SDL_Window { - self.window.lock().unwrap().raw() - } - - pub fn displays(&self) -> &[Display] { - &self.displays - } - pub fn create_vulkan_surface(&self, instance: &Arc) -> Result<()> { - let vk_surface = self - .window - .lock() - .unwrap() - .vulkan_create_surface(instance.vk_handle().raw()) - .map_err(|s| anyhow::Error::msg(s))? - .into(); + let vk_surface = unsafe { + core::mem::transmute( + self.window + .lock() + .unwrap() + .vulkan_create_surface(core::mem::transmute(instance.vk_handle().raw())) + .map_err(|s| anyhow::Error::msg(s))?, + ) + }; *self.surface.lock().unwrap() = Some(Surface::from_vk_surface(vk_surface, instance)); @@ -401,28 +326,16 @@ impl WindowSystemIntegration { &self, extensions: &mut InstanceExtensions, ) -> Result<()> { - let sys_wm_info: SdlSysWmInfo = unsafe { - let tmp = MaybeUninit::zeroed(); - let mut ret: SdlSysWmInfo = tmp.assume_init(); - ret.version = sdl2::version::version(); + let driver = self._video_subsystem.lock().unwrap().current_video_driver(); - SDL_GetWindowWMInfo(self.raw_sdl2_window(), &mut ret); + match driver { + "android" => extensions.android_surface = true, + "cocoa" => extensions.macos_surface = true, + "x11" => extensions.xlib_surface = true, + "wayland" => extensions.wayland_surface = true, + "windows" => extensions.win32_surface = true, - ret - }; - - match sys_wm_info.subsystem { - SDL_SYSWM_ANDROID => extensions.android_surface = true, - SDL_SYSWM_COCOA => extensions.macos_surface = true, - SDL_SYSWM_WAYLAND => extensions.wayland_surface = true, - SDL_SYSWM_WINDOWS => extensions.win32_surface = true, - SDL_SYSWM_X11 => extensions.xlib_surface = true, - _ => { - return Err(anyhow::Error::msg(format!( - "Unsupported window subsystem flag {}", - sys_wm_info.subsystem - ))); - } + _ => panic!("unsupported video driver: {driver}"), } extensions.surface = true; @@ -448,7 +361,7 @@ impl std::fmt::Debug for WindowSystemIntegration { /// helper function to wrap SDL2 error types #[inline] -fn set_window_size(window: &mut sdl2::video::Window, width: u32, height: u32) -> Result<()> { +fn set_window_size(window: &mut sdl3::video::Window, width: u32, height: u32) -> Result<()> { window.set_size(width, height)?; Ok(())