diff --git a/unity-native-plugin-tester/Cargo.toml b/unity-native-plugin-tester/Cargo.toml index 0342fec..df36b14 100644 --- a/unity-native-plugin-tester/Cargo.toml +++ b/unity-native-plugin-tester/Cargo.toml @@ -27,10 +27,10 @@ d3d12 = [] [dependencies] unity-native-plugin-sys = { version = "0.9.0", path = "../unity-native-plugin-sys" } unity-native-plugin = { version = "0.9.0", path = "../unity-native-plugin", features = ["d3d11", "d3d12"] } +winit = "0.30" +raw-window-handle = "0.6" [target.'cfg(windows)'.dependencies] -winapi = { version = "0.3.9", features = ["winuser", "dxgi", "d3d11", "dxgiformat", "dxgitype", "d3dcommon"] } -winit = "0.23.0" +winapi = { version = "0.3.9", features = ["winuser", "dxgi", "d3d11", "dxgiformat", "dxgitype", "d3dcommon", "winerror", "combaseapi", "objbase"] } wio = "0.2.2" -raw-window-handle = "0.3.3" diff --git a/unity-native-plugin-tester/src/d3d11.rs b/unity-native-plugin-tester/src/d3d11.rs index d88ab7f..4a66eda 100644 --- a/unity-native-plugin-tester/src/d3d11.rs +++ b/unity-native-plugin-tester/src/d3d11.rs @@ -1,4 +1,4 @@ -use raw_window_handle::HasRawWindowHandle; +use raw_window_handle::HasWindowHandle; use unity_native_plugin::interface::UnityInterface; use unity_native_plugin_sys::*; use winapi::shared::{dxgi, dxgiformat, dxgitype, minwindef, winerror}; @@ -45,10 +45,10 @@ impl TesterContextGraphicsD3D11 { }, BufferUsage: dxgitype::DXGI_USAGE_RENDER_TARGET_OUTPUT, BufferCount: 2, - OutputWindow: match window.raw_window_handle() { - raw_window_handle::RawWindowHandle::Windows(h) => h.hwnd, + OutputWindow: match window.window_handle().unwrap().as_raw() { + raw_window_handle::RawWindowHandle::Win32(h) => h.hwnd.get() as _, _ => std::ptr::null_mut(), - } as _, + }, Windowed: minwindef::TRUE, SwapEffect: dxgi::DXGI_SWAP_EFFECT_DISCARD, Flags: dxgi::DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH, diff --git a/unity-native-plugin-tester/src/lib.rs b/unity-native-plugin-tester/src/lib.rs index 046f9a9..62d75e1 100644 --- a/unity-native-plugin-tester/src/lib.rs +++ b/unity-native-plugin-tester/src/lib.rs @@ -2,7 +2,6 @@ pub mod graphics; pub mod interface; -#[cfg(windows)] pub mod window; #[cfg(all(windows, feature = "d3d11"))] diff --git a/unity-native-plugin-tester/src/window.rs b/unity-native-plugin-tester/src/window.rs index 977ec7b..832ba6d 100644 --- a/unity-native-plugin-tester/src/window.rs +++ b/unity-native-plugin-tester/src/window.rs @@ -1,11 +1,11 @@ -use winit::event::{Event, WindowEvent}; -use winit::event_loop::{ControlFlow, EventLoop}; -use winit::window::{Window, WindowBuilder}; - use std::ops::Deref; -use winit::platform::desktop::EventLoopExtDesktop; +use winit::application::ApplicationHandler; +use winit::event::WindowEvent; +use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop}; +use winit::window::{Window, WindowId}; + #[cfg(target_os = "windows")] -use winit::platform::windows::EventLoopExtWindows; +use winit::platform::windows::EventLoopBuilderExtWindows; #[derive(PartialEq, Eq)] pub enum LoopResult { @@ -21,64 +21,147 @@ pub enum LoopResult { Exit, } -pub fn run_window_app< +struct App +where Context: 'static + crate::interface::UnityInterfaceBase + crate::interface::UnityInterfaceID, FnInit: FnOnce(&Window) -> Context, FnMain: FnMut(&Window, &Context) -> LoopResult, FnFinalize: FnOnce(&Window, &Context), ->( +{ client_size: (u32, u32), - fn_initialize: FnInit, - mut fn_main: FnMain, - fn_finalize: FnFinalize, + fn_initialize: Option, + fn_main: FnMain, + fn_finalize: Option, fn_unity_plugin_load: fn(interfaces: &unity_native_plugin::interface::UnityInterfaces), - fn_unity_plugin_unload: fn(), -) { - let mut event_loop = EventLoop::::new_any_thread(); - let window = WindowBuilder::new() - .with_inner_size(winit::dpi::Size::from( - winit::dpi::PhysicalSize::::from(client_size), - )) - .build(&event_loop) - .unwrap(); + window: Option, + context: Option>, + last_result: LoopResult, +} - let context = std::rc::Rc::new(fn_initialize(&window)); - unsafe { - crate::interface::get_unity_interfaces() - .register_interface::(Some(context.clone())); +impl App +where + Context: 'static + crate::interface::UnityInterfaceBase + crate::interface::UnityInterfaceID, + FnInit: FnOnce(&Window) -> Context, + FnMain: FnMut(&Window, &Context) -> LoopResult, + FnFinalize: FnOnce(&Window, &Context), +{ + fn update_control_flow(&self, event_loop: &ActiveEventLoop) { + match self.last_result { + LoopResult::Continue => { + event_loop.set_control_flow(ControlFlow::WaitUntil( + std::time::Instant::now() + std::time::Duration::from_millis(50), + )); + } + LoopResult::ContinueOnWindowEvent => { + event_loop.set_control_flow(ControlFlow::Wait); + } + LoopResult::Exit => { + event_loop.exit(); + } + } } +} - fn_unity_plugin_load(unity_native_plugin::interface::UnityInterfaces::get()); +impl ApplicationHandler + for App +where + Context: 'static + crate::interface::UnityInterfaceBase + crate::interface::UnityInterfaceID, + FnInit: FnOnce(&Window) -> Context, + FnMain: FnMut(&Window, &Context) -> LoopResult, + FnFinalize: FnOnce(&Window, &Context), +{ + fn resumed(&mut self, event_loop: &ActiveEventLoop) { + if self.window.is_some() { + return; + } + let attrs = Window::default_attributes() + .with_inner_size(winit::dpi::PhysicalSize::::from(self.client_size)); + let window = event_loop.create_window(attrs).unwrap(); - let mut last_result = LoopResult::Continue; - event_loop.run_return(|event, _, control_flow| { - let instant = std::time::Instant::now(); + let fn_init = self.fn_initialize.take().unwrap(); + let context = std::rc::Rc::new(fn_init(&window)); + unsafe { + crate::interface::get_unity_interfaces() + .register_interface::(Some(context.clone())); + } + (self.fn_unity_plugin_load)(unity_native_plugin::interface::UnityInterfaces::get()); + + self.window = Some(window); + self.context = Some(context); + } + + fn window_event( + &mut self, + event_loop: &ActiveEventLoop, + window_id: WindowId, + event: WindowEvent, + ) { + let Some(window) = self.window.as_ref() else { + return; + }; + if window_id != window.id() { + return; + } + let context = self.context.as_ref().unwrap(); match event { - Event::WindowEvent { window_id, event } => { - if window_id == window.id() { - match event { - WindowEvent::CloseRequested => last_result = LoopResult::Exit, - _ => { - last_result = fn_main(&window, context.deref()); - } - } - } + WindowEvent::CloseRequested => { + self.last_result = LoopResult::Exit; } _ => { - if last_result == LoopResult::Continue { - last_result = fn_main(&window, context.deref()); - } + self.last_result = (self.fn_main)(window, context.deref()); } } - *control_flow = match last_result { - LoopResult::Continue => { - ControlFlow::WaitUntil(instant + std::time::Duration::from_millis(50)) - } - LoopResult::ContinueOnWindowEvent => ControlFlow::Wait, - _ => ControlFlow::Exit, + self.update_control_flow(event_loop); + } + + fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { + let (Some(window), Some(context)) = (self.window.as_ref(), self.context.as_ref()) else { + return; }; - }); + if self.last_result == LoopResult::Continue { + self.last_result = (self.fn_main)(window, context.deref()); + } + self.update_control_flow(event_loop); + } +} + +pub fn run_window_app< + Context: 'static + crate::interface::UnityInterfaceBase + crate::interface::UnityInterfaceID, + FnInit: FnOnce(&Window) -> Context, + FnMain: FnMut(&Window, &Context) -> LoopResult, + FnFinalize: FnOnce(&Window, &Context), +>( + client_size: (u32, u32), + fn_initialize: FnInit, + fn_main: FnMain, + fn_finalize: FnFinalize, + fn_unity_plugin_load: fn(interfaces: &unity_native_plugin::interface::UnityInterfaces), + fn_unity_plugin_unload: fn(), +) { + let mut builder = EventLoop::::with_user_event(); + #[cfg(target_os = "windows")] + builder.with_any_thread(true); + let event_loop = builder.build().unwrap(); + + let mut app = App { + client_size, + fn_initialize: Some(fn_initialize), + fn_main, + fn_finalize: Some(fn_finalize), + fn_unity_plugin_load, + window: None, + context: None, + last_result: LoopResult::Continue, + }; + + event_loop.run_app(&mut app).unwrap(); fn_unity_plugin_unload(); - fn_finalize(&window, context.deref()); + if let (Some(fn_finalize), Some(window), Some(context)) = ( + app.fn_finalize.take(), + app.window.as_ref(), + app.context.as_ref(), + ) { + fn_finalize(window, context.deref()); + } } diff --git a/unity-native-plugin/src/graphics.rs b/unity-native-plugin/src/graphics.rs index 6b9b0b9..43a2be9 100644 --- a/unity-native-plugin/src/graphics.rs +++ b/unity-native-plugin/src/graphics.rs @@ -1,6 +1,6 @@ -use std::os::raw::c_int; use crate::define_unity_interface; use crate::interface::UnityInterface; +use std::os::raw::c_int; use unity_native_plugin_sys::*; pub type RenderBuffer = unity_native_plugin_sys::UnityRenderBuffer; @@ -81,6 +81,10 @@ impl UnityGraphics { } pub fn reserve_event_id_range(&self, count: c_int) -> c_int { - unsafe { self.interface().ReserveEventIDRange.expect("ReserveEventIDRange is missing")(count) } + unsafe { + self.interface() + .ReserveEventIDRange + .expect("ReserveEventIDRange is missing")(count) + } } }