Switch to sdl3
This commit is contained in:
parent
fcf246b2cb
commit
0adaffb27e
11 changed files with 117 additions and 250 deletions
|
@ -49,7 +49,7 @@ hostname = { version = "0.4.0" }
|
||||||
trust-dns-resolver = { version = "0.23.2" }
|
trust-dns-resolver = { version = "0.23.2" }
|
||||||
openxr = { version = "0.19.0", default-features = false, features = ["static"] }
|
openxr = { version = "0.19.0", default-features = false, features = ["static"] }
|
||||||
openvr = { version = "0.7.0" }
|
openvr = { version = "0.7.0" }
|
||||||
sdl2 = { version = "0.37.0" }
|
sdl3 = { version = "0.14.19" }
|
||||||
syn = { version = "2.0.67", features = ["extra-traits", "full"] }
|
syn = { version = "2.0.67", features = ["extra-traits", "full"] }
|
||||||
quote = "1.0.35"
|
quote = "1.0.35"
|
||||||
proc-macro2 = "1.0.86"
|
proc-macro2 = "1.0.86"
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use crate::prelude::*;
|
|
||||||
use presentation::wsi::windowsystemintegration::WindowSystemIntegration;
|
use presentation::wsi::windowsystemintegration::WindowSystemIntegration;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
@ -59,10 +58,6 @@ impl<'a> WindowConfig<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn displays(&self) -> &[Display] {
|
|
||||||
self.wsi.displays()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clipboard_content(&self) -> Result<Option<String>> {
|
pub fn clipboard_content(&self) -> Result<Option<String>> {
|
||||||
self.wsi.clipboard_content()
|
self.wsi.clipboard_content()
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,7 +236,6 @@ impl Default for ContextBuilder {
|
||||||
width: 800,
|
width: 800,
|
||||||
height: 600,
|
height: 600,
|
||||||
fullscreen: false,
|
fullscreen: false,
|
||||||
requested_display: None,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// os specifics
|
// os specifics
|
||||||
|
@ -425,14 +424,6 @@ impl ContextBuilder {
|
||||||
presentation.event_system_mut().enable_mouse();
|
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 {
|
Ok(Context {
|
||||||
core,
|
core,
|
||||||
presentation,
|
presentation,
|
||||||
|
|
|
@ -48,7 +48,6 @@ impl<'a> Default for EngineCreateInfo<'a> {
|
||||||
width: 1600,
|
width: 1600,
|
||||||
height: 900,
|
height: 900,
|
||||||
fullscreen: false,
|
fullscreen: false,
|
||||||
requested_display: None,
|
|
||||||
},
|
},
|
||||||
os_specific_config: OsSpecificConfig {
|
os_specific_config: OsSpecificConfig {
|
||||||
enable_game_mode: true,
|
enable_game_mode: true,
|
||||||
|
|
|
@ -7,7 +7,7 @@ edition = "2024"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
vulkan-rs = { workspace = true }
|
vulkan-rs = { workspace = true }
|
||||||
ui = { workspace = true }
|
ui = { workspace = true }
|
||||||
sdl2 = { workspace = true }
|
sdl3 = { workspace = true }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
|
|
||||||
openxr = { workspace = true, optional = true }
|
openxr = { workspace = true, optional = true }
|
||||||
|
@ -18,5 +18,5 @@ ecs = { workspace = true }
|
||||||
[features]
|
[features]
|
||||||
OpenXR = ["openxr"]
|
OpenXR = ["openxr"]
|
||||||
OpenVR = ["openvr"]
|
OpenVR = ["openvr"]
|
||||||
BundleSDL = ["sdl2/bundled", "sdl2/static-link"]
|
BundleSDL = ["sdl3/build-from-source-static"]
|
||||||
sound = ["ui/audio"]
|
sound = ["ui/audio"]
|
||||||
|
|
|
@ -3,7 +3,7 @@ use ui::prelude::*;
|
||||||
|
|
||||||
use super::controlleraxis::ControllerAxis;
|
use super::controlleraxis::ControllerAxis;
|
||||||
|
|
||||||
use sdl2::{self, GameControllerSubsystem};
|
use sdl3::{self, GamepadSubsystem};
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
enum State {
|
enum State {
|
||||||
|
@ -32,7 +32,7 @@ impl Default for ControllerDeadzones {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Controller {
|
pub struct Controller {
|
||||||
_sdl2_controller: sdl2::controller::GameController,
|
_sdl2_controller: sdl3::gamepad::Gamepad,
|
||||||
name: String,
|
name: String,
|
||||||
id: u32,
|
id: u32,
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ pub struct Controller {
|
||||||
|
|
||||||
impl Controller {
|
impl Controller {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
controller_subsystem: &GameControllerSubsystem,
|
controller_subsystem: &GamepadSubsystem,
|
||||||
id: u32,
|
id: u32,
|
||||||
deadzones: ControllerDeadzones,
|
deadzones: ControllerDeadzones,
|
||||||
) -> Result<Controller> {
|
) -> Result<Controller> {
|
||||||
|
|
|
@ -1,30 +1,27 @@
|
||||||
use sdl2;
|
use sdl3::{
|
||||||
use sdl2::EventPump;
|
self, EventPump, EventSubsystem, GamepadSubsystem, JoystickSubsystem, Sdl,
|
||||||
use sdl2::EventSubsystem;
|
event::{Event as SdlEvent, WindowEvent},
|
||||||
use sdl2::GameControllerSubsystem;
|
gamepad::{Axis, Button},
|
||||||
use sdl2::JoystickSubsystem;
|
keyboard::Keycode,
|
||||||
use sdl2::Sdl;
|
mouse::{MouseButton as SdlMouseButton, MouseUtil, MouseWheelDirection},
|
||||||
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 ui::prelude::*;
|
use ui::prelude::*;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
|
||||||
use super::controller::{Controller, ControllerDeadzones};
|
use super::controller::{Controller, ControllerDeadzones};
|
||||||
use super::joystick::Joystick;
|
use super::joystick::Joystick;
|
||||||
|
|
||||||
fn convert_button(button: Button) -> ControllerButton {
|
fn convert_button(button: Button) -> ControllerButton {
|
||||||
match button {
|
match button {
|
||||||
Button::A => ControllerButton::A,
|
Button::South => ControllerButton::A,
|
||||||
Button::B => ControllerButton::B,
|
Button::East => ControllerButton::B,
|
||||||
Button::Y => ControllerButton::Y,
|
Button::North => ControllerButton::Y,
|
||||||
Button::X => ControllerButton::X,
|
Button::West => ControllerButton::X,
|
||||||
|
|
||||||
Button::Start => ControllerButton::Start,
|
Button::Start => ControllerButton::Start,
|
||||||
Button::Back => ControllerButton::Select,
|
Button::Back => ControllerButton::Select,
|
||||||
|
@ -44,10 +41,10 @@ fn convert_button(button: Button) -> ControllerButton {
|
||||||
|
|
||||||
Button::Misc1 => ControllerButton::Misc,
|
Button::Misc1 => ControllerButton::Misc,
|
||||||
|
|
||||||
Button::Paddle1 => ControllerButton::Paddle1,
|
Button::RightPaddle1 => ControllerButton::Paddle1,
|
||||||
Button::Paddle2 => ControllerButton::Paddle2,
|
Button::RightPaddle2 => ControllerButton::Paddle2,
|
||||||
Button::Paddle3 => ControllerButton::Paddle3,
|
Button::LeftPaddle1 => ControllerButton::Paddle3,
|
||||||
Button::Paddle4 => ControllerButton::Paddle4,
|
Button::LeftPaddle2 => ControllerButton::Paddle4,
|
||||||
|
|
||||||
Button::Touchpad => ControllerButton::Touchpad,
|
Button::Touchpad => ControllerButton::Touchpad,
|
||||||
}
|
}
|
||||||
|
@ -87,7 +84,7 @@ pub enum Event<'a> {
|
||||||
pub struct EventSystem {
|
pub struct EventSystem {
|
||||||
event_pump: EventPump,
|
event_pump: EventPump,
|
||||||
mouse: MouseUtil,
|
mouse: MouseUtil,
|
||||||
controller_subsystem: GameControllerSubsystem,
|
controller_subsystem: GamepadSubsystem,
|
||||||
joystick_subsystem: JoystickSubsystem,
|
joystick_subsystem: JoystickSubsystem,
|
||||||
event_subsystem: EventSubsystem,
|
event_subsystem: EventSubsystem,
|
||||||
|
|
||||||
|
@ -104,9 +101,7 @@ impl EventSystem {
|
||||||
.event_pump()
|
.event_pump()
|
||||||
.map_err(|s| anyhow::Error::msg(s))?,
|
.map_err(|s| anyhow::Error::msg(s))?,
|
||||||
mouse: sdl2_context.mouse(),
|
mouse: sdl2_context.mouse(),
|
||||||
controller_subsystem: sdl2_context
|
controller_subsystem: sdl2_context.gamepad().map_err(|s| anyhow::Error::msg(s))?,
|
||||||
.game_controller()
|
|
||||||
.map_err(|s| anyhow::Error::msg(s))?,
|
|
||||||
joystick_subsystem: sdl2_context.joystick().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))?,
|
event_subsystem: sdl2_context.event().map_err(|s| anyhow::Error::msg(s))?,
|
||||||
|
|
||||||
|
@ -116,17 +111,22 @@ impl EventSystem {
|
||||||
connected_joysticks: HashMap::new(),
|
connected_joysticks: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
event_system.connected_joysticks = (0..event_system
|
event_system.connected_joysticks = event_system
|
||||||
.joystick_subsystem
|
.joystick_subsystem
|
||||||
.num_joysticks()
|
.joysticks()
|
||||||
.map_err(|s| anyhow::Error::msg(s))?)
|
.map_err(|s| anyhow::Error::msg(s))?
|
||||||
.into_iter()
|
.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::<Result<HashMap<_, _>>>()?;
|
.collect::<Result<HashMap<_, _>>>()?;
|
||||||
|
|
||||||
event_system.connected_controllers = (0..event_system
|
event_system.connected_controllers = (0..event_system
|
||||||
.controller_subsystem
|
.controller_subsystem
|
||||||
.num_joysticks()
|
.num_gamepads()
|
||||||
.map_err(|s| anyhow::Error::msg(s))?)
|
.map_err(|s| anyhow::Error::msg(s))?)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|i| event_system.controller_subsystem.is_game_controller(*i))
|
.filter(|i| event_system.controller_subsystem.is_game_controller(*i))
|
||||||
|
@ -143,56 +143,18 @@ impl EventSystem {
|
||||||
.collect::<Result<HashMap<_, _>>>()?;
|
.collect::<Result<HashMap<_, _>>>()?;
|
||||||
|
|
||||||
event_system.disable_mouse();
|
event_system.disable_mouse();
|
||||||
event_system.disable_keyboard();
|
|
||||||
event_system.disable_controller();
|
|
||||||
|
|
||||||
Ok(event_system)
|
Ok(event_system)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_mouse(&mut self) {
|
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);
|
self.mouse.show_cursor(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_mouse(&mut self) {
|
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);
|
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) {
|
pub fn set_controller_axis_enable_deadzone(&mut self, deadzone: f32) {
|
||||||
self.controller_deadzones.axis_enable_deadzone = deadzone;
|
self.controller_deadzones.axis_enable_deadzone = deadzone;
|
||||||
}
|
}
|
||||||
|
@ -224,7 +186,7 @@ impl EventSystem {
|
||||||
for event in self.event_pump.poll_iter() {
|
for event in self.event_pump.poll_iter() {
|
||||||
match event {
|
match event {
|
||||||
SdlEvent::Window { win_event, .. } => match win_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)?;
|
resize(w as u32, h as u32)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +224,7 @@ impl EventSystem {
|
||||||
SdlEvent::MouseWheel {
|
SdlEvent::MouseWheel {
|
||||||
x, y, direction, ..
|
x, y, direction, ..
|
||||||
} => {
|
} => {
|
||||||
event_callback(Event::MouseWheel(x, y, direction))?;
|
event_callback(Event::MouseWheel(x as i32, y as i32, direction))?;
|
||||||
}
|
}
|
||||||
// ------------------- Key Events ---------------------
|
// ------------------- Key Events ---------------------
|
||||||
SdlEvent::KeyDown {
|
SdlEvent::KeyDown {
|
||||||
|
@ -370,11 +332,19 @@ impl EventSystem {
|
||||||
event_callback(Event::ControllerAxis(&*controller))?;
|
event_callback(Event::ControllerAxis(&*controller))?;
|
||||||
}
|
}
|
||||||
SdlEvent::JoyDeviceAdded { which, .. } => {
|
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))?;
|
event_callback(Event::JoystickAdded(&joystick))?;
|
||||||
self.connected_joysticks.insert(joystick.id(), joystick);
|
self.connected_joysticks.insert(joystick.id(), joystick);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
SdlEvent::JoyDeviceRemoved { which, .. } => {
|
SdlEvent::JoyDeviceRemoved { which, .. } => {
|
||||||
if let Some(joysticks) = self.connected_joysticks.remove(&which) {
|
if let Some(joysticks) = self.connected_joysticks.remove(&which) {
|
||||||
event_callback(Event::JoystickRemoved(&joysticks))?;
|
event_callback(Event::JoystickRemoved(&joysticks))?;
|
||||||
|
|
|
@ -1,25 +1,24 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use sdl2::JoystickSubsystem;
|
use sdl3::{JoystickSubsystem, joystick::JoystickInstance};
|
||||||
|
|
||||||
pub struct Joystick {
|
pub struct Joystick {
|
||||||
_sdl2_joystick: sdl2::joystick::Joystick,
|
sdl2_joystick: sdl3::joystick::Joystick,
|
||||||
id: u32,
|
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Joystick {
|
impl Joystick {
|
||||||
pub fn new(joystick_subsystem: &JoystickSubsystem, id: u32) -> Result<Self> {
|
pub fn new(joystick_subsystem: &JoystickSubsystem, instance: JoystickInstance) -> Result<Self> {
|
||||||
let sdl2_joystick = joystick_subsystem.open(id)?;
|
let sdl2_joystick = joystick_subsystem.open(instance)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
name: sdl2_joystick.name(),
|
name: sdl2_joystick.name(),
|
||||||
id,
|
sdl2_joystick,
|
||||||
_sdl2_joystick: sdl2_joystick,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id(&self) -> u32 {
|
pub fn id(&self) -> u32 {
|
||||||
self.id
|
self.sdl2_joystick.instance_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &str {
|
||||||
|
@ -30,7 +29,7 @@ impl Joystick {
|
||||||
impl std::fmt::Debug for Joystick {
|
impl std::fmt::Debug for Joystick {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("Joystick")
|
f.debug_struct("Joystick")
|
||||||
.field("id", &self.id)
|
.field("id", &self.id())
|
||||||
.field("name", &self.name)
|
.field("name", &self.name)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub use crate::input::{
|
||||||
// wsi
|
// wsi
|
||||||
pub use crate::wsi::windowsystemintegration::{Display, WindowCreateInfo};
|
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::*;
|
pub use vulkan_rs::prelude::*;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::xri::openxrintegration::OpenXRIntegration;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use vulkan_rs::prelude::*;
|
use vulkan_rs::prelude::*;
|
||||||
|
|
||||||
use sdl2::Sdl;
|
use sdl3::Sdl;
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
@ -88,8 +88,8 @@ impl PresentationCore {
|
||||||
window_create_info: &WindowCreateInfo,
|
window_create_info: &WindowCreateInfo,
|
||||||
appl_info: ApplicationInfo,
|
appl_info: ApplicationInfo,
|
||||||
) -> Result<PresentationCore> {
|
) -> Result<PresentationCore> {
|
||||||
// create sdl2 context
|
// create sdl3 context
|
||||||
let context = sdl2::init().map_err(|s| anyhow::Error::msg(s))?;
|
let context = sdl3::init().map_err(|s| anyhow::Error::msg(s))?;
|
||||||
|
|
||||||
Ok(PresentationCore {
|
Ok(PresentationCore {
|
||||||
event_system: EventSystem::new(&context)?,
|
event_system: EventSystem::new(&context)?,
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
// needed since RLS won't accept #[repr(C)]
|
// needed since RLS won't accept #[repr(C)]
|
||||||
#![allow(improper_ctypes)]
|
#![allow(improper_ctypes)]
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::{Error, anyhow};
|
||||||
use sdl2;
|
|
||||||
use sdl2::Sdl;
|
use sdl3::{
|
||||||
use sdl2::clipboard::ClipboardUtil;
|
self, Sdl,
|
||||||
use sdl2::messagebox::{MessageBoxFlag, show_simple_message_box};
|
clipboard::ClipboardUtil,
|
||||||
use sdl2::mouse::Cursor;
|
messagebox::{MessageBoxFlag, show_simple_message_box},
|
||||||
use sdl2::surface::Surface as SDL_Surface;
|
mouse::Cursor,
|
||||||
use sdl2::sys::SDL_Window;
|
surface::Surface as SDL_Surface,
|
||||||
use sdl2::video::{FullscreenType, WindowPos};
|
video::{FullscreenType, WindowPos},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use vulkan_rs::prelude::*;
|
use vulkan_rs::prelude::*;
|
||||||
|
|
||||||
use std::mem::MaybeUninit;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::{
|
use std::sync::{
|
||||||
|
@ -22,30 +22,12 @@ use std::sync::{
|
||||||
atomic::{AtomicI32, AtomicU32, Ordering::SeqCst},
|
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)]
|
#[derive(Default, Debug, Clone)]
|
||||||
pub struct WindowCreateInfo {
|
pub struct WindowCreateInfo {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub width: u32,
|
pub width: u32,
|
||||||
pub height: u32,
|
pub height: u32,
|
||||||
pub fullscreen: bool,
|
pub fullscreen: bool,
|
||||||
pub requested_display: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -57,8 +39,6 @@ pub struct Display {
|
||||||
pub y: i32,
|
pub y: i32,
|
||||||
pub w: u32,
|
pub w: u32,
|
||||||
pub h: u32,
|
pub h: u32,
|
||||||
|
|
||||||
pub dpi: [f32; 3],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
|
@ -70,7 +50,7 @@ struct CellRect {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 (w, h) = window.size();
|
||||||
let (x, y) = window.position();
|
let (x, y) = window.position();
|
||||||
|
|
||||||
|
@ -80,7 +60,7 @@ impl CellRect {
|
||||||
self.height.store(h, SeqCst);
|
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))?;
|
set_window_size(window, self.width.load(SeqCst), self.height.load(SeqCst))?;
|
||||||
window.set_position(
|
window.set_position(
|
||||||
WindowPos::Positioned(self.x.load(SeqCst)),
|
WindowPos::Positioned(self.x.load(SeqCst)),
|
||||||
|
@ -93,15 +73,12 @@ impl CellRect {
|
||||||
|
|
||||||
pub struct WindowSystemIntegration {
|
pub struct WindowSystemIntegration {
|
||||||
// sdl
|
// sdl
|
||||||
_video_subsystem: Mutex<sdl2::VideoSubsystem>,
|
_video_subsystem: Mutex<sdl3::VideoSubsystem>,
|
||||||
window: Mutex<sdl2::video::Window>,
|
window: Mutex<sdl3::video::Window>,
|
||||||
clipboard_util: ClipboardUtil,
|
clipboard_util: ClipboardUtil,
|
||||||
|
|
||||||
cursor: Mutex<Option<Cursor>>,
|
cursor: Mutex<Option<Cursor>>,
|
||||||
|
|
||||||
displays: Vec<Display>,
|
|
||||||
_enabled_display_index: usize,
|
|
||||||
|
|
||||||
pre_fullscreen_rect: CellRect,
|
pre_fullscreen_rect: CellRect,
|
||||||
|
|
||||||
surface: Mutex<Option<Arc<Surface>>>,
|
surface: Mutex<Option<Arc<Surface>>>,
|
||||||
|
@ -119,8 +96,8 @@ impl WindowSystemIntegration {
|
||||||
let video_subsystem = context.video().map_err(|s| anyhow::Error::msg(s))?;
|
let video_subsystem = context.video().map_err(|s| anyhow::Error::msg(s))?;
|
||||||
|
|
||||||
// query display count
|
// query display count
|
||||||
let display_count = match video_subsystem.num_video_displays() {
|
let display_count = match video_subsystem.displays() {
|
||||||
Ok(num_displays) => num_displays,
|
Ok(displays) => displays.len(),
|
||||||
Err(_) => 0,
|
Err(_) => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -128,78 +105,35 @@ impl WindowSystemIntegration {
|
||||||
return Err(anyhow::Error::msg("No display where detected!"));
|
return Err(anyhow::Error::msg("No display where detected!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// query display information
|
// // query display information
|
||||||
let mut displays = Vec::with_capacity(display_count as usize);
|
// let mut displays = Vec::with_capacity(display_count as usize);
|
||||||
|
|
||||||
for i in 0..display_count {
|
// for display in video_subsystem
|
||||||
let rect = video_subsystem
|
// .displays()
|
||||||
.display_bounds(i)
|
// .map_err(|_| anyhow!("failed querying displays"))?
|
||||||
.map_err(|s| anyhow::Error::msg(s))?;
|
// {
|
||||||
let name = video_subsystem
|
// let rect = display.get_bounds().map_err(|s| anyhow::Error::msg(s))?;
|
||||||
.display_name(i)
|
// let name = display.get_name().map_err(|s| anyhow::Error::msg(s))?;
|
||||||
.map_err(|s| anyhow::Error::msg(s))?;
|
|
||||||
|
|
||||||
let (dpi0, dpi1, dpi2) = match video_subsystem.display_dpi(i) {
|
// let display = Display {
|
||||||
Ok(dpis) => dpis,
|
// name,
|
||||||
Err(msg) => {
|
|
||||||
println!("failed getting dpi for display {} ({}): {}", i, name, msg);
|
|
||||||
(0.0, 0.0, 0.0)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let display = Display {
|
// x: rect.x(),
|
||||||
name,
|
// y: rect.y(),
|
||||||
|
// w: rect.width(),
|
||||||
|
// h: rect.height(),
|
||||||
|
// };
|
||||||
|
|
||||||
x: rect.x(),
|
// displays.push(display);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// build window
|
// build window
|
||||||
let mut window_builder =
|
let mut window_builder =
|
||||||
video_subsystem.window(&create_info.title, create_info.width, create_info.height);
|
video_subsystem.window(&create_info.title, create_info.width, create_info.height);
|
||||||
window_builder.resizable().vulkan();
|
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()?;
|
let window = window_builder.build()?;
|
||||||
|
|
||||||
display_index = Some(window.display_index().map_err(|s| anyhow::Error::msg(s))? as usize);
|
|
||||||
|
|
||||||
let rect = CellRect::default();
|
let rect = CellRect::default();
|
||||||
rect.update_from_window(&window);
|
rect.update_from_window(&window);
|
||||||
|
|
||||||
|
@ -210,10 +144,6 @@ impl WindowSystemIntegration {
|
||||||
|
|
||||||
cursor: Mutex::new(None),
|
cursor: Mutex::new(None),
|
||||||
|
|
||||||
displays,
|
|
||||||
|
|
||||||
_enabled_display_index: display_index.expect("display index not set"),
|
|
||||||
|
|
||||||
pre_fullscreen_rect: rect,
|
pre_fullscreen_rect: rect,
|
||||||
|
|
||||||
surface: Mutex::new(None),
|
surface: Mutex::new(None),
|
||||||
|
@ -246,20 +176,21 @@ impl WindowSystemIntegration {
|
||||||
self.pre_fullscreen_rect.update_from_window(&window);
|
self.pre_fullscreen_rect.update_from_window(&window);
|
||||||
|
|
||||||
// set fullscreen size to fit display
|
// set fullscreen size to fit display
|
||||||
let display =
|
let display = window.get_display().map_err(|s| anyhow!(s))?;
|
||||||
&self.displays[window.display_index().map_err(|s| anyhow::Error::msg(s))? as usize];
|
let rect = display.get_bounds().map_err(|s| anyhow!(s))?;
|
||||||
set_window_size(&mut window, display.w, display.h)?;
|
|
||||||
|
set_window_size(&mut window, rect.w as u32, rect.h as u32)?;
|
||||||
|
|
||||||
window.set_bordered(false);
|
window.set_bordered(false);
|
||||||
|
|
||||||
// change fullscreen mode
|
// change fullscreen mode
|
||||||
window
|
window
|
||||||
.set_fullscreen(FullscreenType::True)
|
.set_fullscreen(true)
|
||||||
.map_err(|s| anyhow::Error::msg(s))?;
|
.map_err(|s| anyhow::Error::msg(s))?;
|
||||||
} else {
|
} else {
|
||||||
// change fullscreen mode
|
// change fullscreen mode
|
||||||
window
|
window
|
||||||
.set_fullscreen(FullscreenType::Off)
|
.set_fullscreen(false)
|
||||||
.map_err(|s| anyhow::Error::msg(s))?;
|
.map_err(|s| anyhow::Error::msg(s))?;
|
||||||
|
|
||||||
// force window borders
|
// force window borders
|
||||||
|
@ -371,22 +302,16 @@ impl WindowSystemIntegration {
|
||||||
Ok(())
|
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<Instance>) -> Result<()> {
|
pub fn create_vulkan_surface(&self, instance: &Arc<Instance>) -> Result<()> {
|
||||||
let vk_surface = self
|
let vk_surface = unsafe {
|
||||||
.window
|
core::mem::transmute(
|
||||||
|
self.window
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.vulkan_create_surface(instance.vk_handle().raw())
|
.vulkan_create_surface(core::mem::transmute(instance.vk_handle().raw()))
|
||||||
.map_err(|s| anyhow::Error::msg(s))?
|
.map_err(|s| anyhow::Error::msg(s))?,
|
||||||
.into();
|
)
|
||||||
|
};
|
||||||
|
|
||||||
*self.surface.lock().unwrap() = Some(Surface::from_vk_surface(vk_surface, instance));
|
*self.surface.lock().unwrap() = Some(Surface::from_vk_surface(vk_surface, instance));
|
||||||
|
|
||||||
|
@ -401,28 +326,16 @@ impl WindowSystemIntegration {
|
||||||
&self,
|
&self,
|
||||||
extensions: &mut InstanceExtensions,
|
extensions: &mut InstanceExtensions,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let sys_wm_info: SdlSysWmInfo = unsafe {
|
let driver = self._video_subsystem.lock().unwrap().current_video_driver();
|
||||||
let tmp = MaybeUninit::zeroed();
|
|
||||||
let mut ret: SdlSysWmInfo = tmp.assume_init();
|
|
||||||
ret.version = sdl2::version::version();
|
|
||||||
|
|
||||||
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
|
_ => panic!("unsupported video driver: {driver}"),
|
||||||
};
|
|
||||||
|
|
||||||
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
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extensions.surface = true;
|
extensions.surface = true;
|
||||||
|
@ -448,7 +361,7 @@ impl std::fmt::Debug for WindowSystemIntegration {
|
||||||
|
|
||||||
/// helper function to wrap SDL2 error types
|
/// helper function to wrap SDL2 error types
|
||||||
#[inline]
|
#[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)?;
|
window.set_size(width, height)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in a new issue