1- use winit:: event:: { Event , WindowEvent } ;
2- use winit:: event_loop:: { ControlFlow , EventLoop } ;
3- use winit:: window:: { Window , WindowBuilder } ;
4-
51use std:: ops:: Deref ;
6- use winit:: platform:: desktop:: EventLoopExtDesktop ;
2+ use winit:: application:: ApplicationHandler ;
3+ use winit:: event:: WindowEvent ;
4+ use winit:: event_loop:: { ActiveEventLoop , ControlFlow , EventLoop } ;
5+ use winit:: window:: { Window , WindowId } ;
6+
77#[ cfg( target_os = "windows" ) ]
8- use winit:: platform:: windows:: EventLoopExtWindows ;
8+ use winit:: platform:: windows:: EventLoopBuilderExtWindows ;
99
1010#[ derive( PartialEq , Eq ) ]
1111pub enum LoopResult {
@@ -21,64 +21,147 @@ pub enum LoopResult {
2121 Exit ,
2222}
2323
24- pub fn run_window_app <
24+ struct App < Context , FnInit , FnMain , FnFinalize >
25+ where
2526 Context : ' static + crate :: interface:: UnityInterfaceBase + crate :: interface:: UnityInterfaceID ,
2627 FnInit : FnOnce ( & Window ) -> Context ,
2728 FnMain : FnMut ( & Window , & Context ) -> LoopResult ,
2829 FnFinalize : FnOnce ( & Window , & Context ) ,
29- > (
30+ {
3031 client_size : ( u32 , u32 ) ,
31- fn_initialize : FnInit ,
32- mut fn_main : FnMain ,
33- fn_finalize : FnFinalize ,
32+ fn_initialize : Option < FnInit > ,
33+ fn_main : FnMain ,
34+ fn_finalize : Option < FnFinalize > ,
3435 fn_unity_plugin_load : fn ( interfaces : & unity_native_plugin:: interface:: UnityInterfaces ) ,
35- fn_unity_plugin_unload : fn ( ) ,
36- ) {
37- let mut event_loop = EventLoop :: < u32 > :: new_any_thread ( ) ;
38- let window = WindowBuilder :: new ( )
39- . with_inner_size ( winit:: dpi:: Size :: from (
40- winit:: dpi:: PhysicalSize :: < u32 > :: from ( client_size) ,
41- ) )
42- . build ( & event_loop)
43- . unwrap ( ) ;
36+ window : Option < Window > ,
37+ context : Option < std:: rc:: Rc < Context > > ,
38+ last_result : LoopResult ,
39+ }
4440
45- let context = std:: rc:: Rc :: new ( fn_initialize ( & window) ) ;
46- unsafe {
47- crate :: interface:: get_unity_interfaces ( )
48- . register_interface :: < Context > ( Some ( context. clone ( ) ) ) ;
41+ impl < Context , FnInit , FnMain , FnFinalize > App < Context , FnInit , FnMain , FnFinalize >
42+ where
43+ Context : ' static + crate :: interface:: UnityInterfaceBase + crate :: interface:: UnityInterfaceID ,
44+ FnInit : FnOnce ( & Window ) -> Context ,
45+ FnMain : FnMut ( & Window , & Context ) -> LoopResult ,
46+ FnFinalize : FnOnce ( & Window , & Context ) ,
47+ {
48+ fn update_control_flow ( & self , event_loop : & ActiveEventLoop ) {
49+ match self . last_result {
50+ LoopResult :: Continue => {
51+ event_loop. set_control_flow ( ControlFlow :: WaitUntil (
52+ std:: time:: Instant :: now ( ) + std:: time:: Duration :: from_millis ( 50 ) ,
53+ ) ) ;
54+ }
55+ LoopResult :: ContinueOnWindowEvent => {
56+ event_loop. set_control_flow ( ControlFlow :: Wait ) ;
57+ }
58+ LoopResult :: Exit => {
59+ event_loop. exit ( ) ;
60+ }
61+ }
4962 }
63+ }
5064
51- fn_unity_plugin_load ( unity_native_plugin:: interface:: UnityInterfaces :: get ( ) ) ;
65+ impl < Context , FnInit , FnMain , FnFinalize > ApplicationHandler < u32 >
66+ for App < Context , FnInit , FnMain , FnFinalize >
67+ where
68+ Context : ' static + crate :: interface:: UnityInterfaceBase + crate :: interface:: UnityInterfaceID ,
69+ FnInit : FnOnce ( & Window ) -> Context ,
70+ FnMain : FnMut ( & Window , & Context ) -> LoopResult ,
71+ FnFinalize : FnOnce ( & Window , & Context ) ,
72+ {
73+ fn resumed ( & mut self , event_loop : & ActiveEventLoop ) {
74+ if self . window . is_some ( ) {
75+ return ;
76+ }
77+ let attrs = Window :: default_attributes ( )
78+ . with_inner_size ( winit:: dpi:: PhysicalSize :: < u32 > :: from ( self . client_size ) ) ;
79+ let window = event_loop. create_window ( attrs) . unwrap ( ) ;
5280
53- let mut last_result = LoopResult :: Continue ;
54- event_loop. run_return ( |event, _, control_flow| {
55- let instant = std:: time:: Instant :: now ( ) ;
81+ let fn_init = self . fn_initialize . take ( ) . unwrap ( ) ;
82+ let context = std:: rc:: Rc :: new ( fn_init ( & window) ) ;
83+ unsafe {
84+ crate :: interface:: get_unity_interfaces ( )
85+ . register_interface :: < Context > ( Some ( context. clone ( ) ) ) ;
86+ }
87+ ( self . fn_unity_plugin_load ) ( unity_native_plugin:: interface:: UnityInterfaces :: get ( ) ) ;
88+
89+ self . window = Some ( window) ;
90+ self . context = Some ( context) ;
91+ }
92+
93+ fn window_event (
94+ & mut self ,
95+ event_loop : & ActiveEventLoop ,
96+ window_id : WindowId ,
97+ event : WindowEvent ,
98+ ) {
99+ let Some ( window) = self . window . as_ref ( ) else {
100+ return ;
101+ } ;
102+ if window_id != window. id ( ) {
103+ return ;
104+ }
105+ let context = self . context . as_ref ( ) . unwrap ( ) ;
56106 match event {
57- Event :: WindowEvent { window_id, event } => {
58- if window_id == window. id ( ) {
59- match event {
60- WindowEvent :: CloseRequested => last_result = LoopResult :: Exit ,
61- _ => {
62- last_result = fn_main ( & window, context. deref ( ) ) ;
63- }
64- }
65- }
107+ WindowEvent :: CloseRequested => {
108+ self . last_result = LoopResult :: Exit ;
66109 }
67110 _ => {
68- if last_result == LoopResult :: Continue {
69- last_result = fn_main ( & window, context. deref ( ) ) ;
70- }
111+ self . last_result = ( self . fn_main ) ( window, context. deref ( ) ) ;
71112 }
72113 }
73- * control_flow = match last_result {
74- LoopResult :: Continue => {
75- ControlFlow :: WaitUntil ( instant + std :: time :: Duration :: from_millis ( 50 ) )
76- }
77- LoopResult :: ContinueOnWindowEvent => ControlFlow :: Wait ,
78- _ => ControlFlow :: Exit ,
114+ self . update_control_flow ( event_loop ) ;
115+ }
116+
117+ fn about_to_wait ( & mut self , event_loop : & ActiveEventLoop ) {
118+ let ( Some ( window ) , Some ( context ) ) = ( self . window . as_ref ( ) , self . context . as_ref ( ) ) else {
119+ return ;
79120 } ;
80- } ) ;
121+ if self . last_result == LoopResult :: Continue {
122+ self . last_result = ( self . fn_main ) ( window, context. deref ( ) ) ;
123+ }
124+ self . update_control_flow ( event_loop) ;
125+ }
126+ }
127+
128+ pub fn run_window_app <
129+ Context : ' static + crate :: interface:: UnityInterfaceBase + crate :: interface:: UnityInterfaceID ,
130+ FnInit : FnOnce ( & Window ) -> Context ,
131+ FnMain : FnMut ( & Window , & Context ) -> LoopResult ,
132+ FnFinalize : FnOnce ( & Window , & Context ) ,
133+ > (
134+ client_size : ( u32 , u32 ) ,
135+ fn_initialize : FnInit ,
136+ fn_main : FnMain ,
137+ fn_finalize : FnFinalize ,
138+ fn_unity_plugin_load : fn ( interfaces : & unity_native_plugin:: interface:: UnityInterfaces ) ,
139+ fn_unity_plugin_unload : fn ( ) ,
140+ ) {
141+ let mut builder = EventLoop :: < u32 > :: with_user_event ( ) ;
142+ #[ cfg( target_os = "windows" ) ]
143+ builder. with_any_thread ( true ) ;
144+ let event_loop = builder. build ( ) . unwrap ( ) ;
145+
146+ let mut app = App {
147+ client_size,
148+ fn_initialize : Some ( fn_initialize) ,
149+ fn_main,
150+ fn_finalize : Some ( fn_finalize) ,
151+ fn_unity_plugin_load,
152+ window : None ,
153+ context : None ,
154+ last_result : LoopResult :: Continue ,
155+ } ;
156+
157+ event_loop. run_app ( & mut app) . unwrap ( ) ;
81158
82159 fn_unity_plugin_unload ( ) ;
83- fn_finalize ( & window, context. deref ( ) ) ;
160+ if let ( Some ( fn_finalize) , Some ( window) , Some ( context) ) = (
161+ app. fn_finalize . take ( ) ,
162+ app. window . as_ref ( ) ,
163+ app. context . as_ref ( ) ,
164+ ) {
165+ fn_finalize ( window, context. deref ( ) ) ;
166+ }
84167}
0 commit comments