11use crate :: { executor, sys} ;
22
3+ impl sys:: sGaugeInstallData {
4+ /// Get the width of the target gauge texture.
5+ pub fn width ( & self ) -> usize {
6+ self . iSizeX as usize
7+ }
8+
9+ /// Get the height of the target gauge texture.
10+ pub fn height ( & self ) -> usize {
11+ self . iSizeY as usize
12+ }
13+
14+ /// Get the optional parameter string passed to the gauge.
15+ pub fn parameters ( & self ) -> Option < & std:: ffi:: CStr > {
16+ if self . strParameters . is_null ( ) {
17+ None
18+ } else {
19+ Some ( unsafe { std:: ffi:: CStr :: from_ptr ( self . strParameters ) } )
20+ }
21+ }
22+ }
23+
324impl sys:: sGaugeDrawData {
425 /// Get the width of the target instrument texture.
526 pub fn width ( & self ) -> usize {
@@ -18,7 +39,7 @@ impl sys::sGaugeDrawData {
1839}
1940
2041use crate :: sim_connect:: { SimConnect , SimConnectRecv } ;
21- pub use msfs_derive:: { gauge, standalone_module, system} ;
42+ pub use msfs_derive:: { gauge, gauge2024 , standalone_module, system} ;
2243
2344/// Used in Gauges to dispatch lifetime events, mouse events, and SimConnect events.
2445#[ derive( Debug ) ]
@@ -243,6 +264,152 @@ impl GaugeExecutor {
243264 }
244265}
245266
267+ /// Event data for MSFS 2024 gauges, containing delta time and the event type.
268+ pub struct Gauge2024Data < ' a > {
269+ pub delta_time : f32 ,
270+ pub event : Gauge2024Event < ' a > ,
271+ }
272+
273+ /// Events dispatched to MSFS 2024 gauges.
274+ #[ derive( Debug ) ]
275+ pub enum Gauge2024Event < ' a > {
276+ /// Gauge initialization event with install data.
277+ Init ( & ' a sys:: sGaugeInstallData ) ,
278+ /// Gauge update event (called each frame, no drawing allowed).
279+ Update ,
280+ /// Gauge draw event (called each frame, drawing is allowed).
281+ Draw ( & ' a sys:: sGaugeDrawData ) ,
282+ /// Gauge kill/cleanup event.
283+ Kill ,
284+ /// Mouse input event.
285+ Mouse { x : f32 , y : f32 , flags : i32 } ,
286+ /// SimConnect event.
287+ SimConnect ( SimConnectRecv < ' a > ) ,
288+ }
289+
290+ /// Handle to an MSFS 2024 gauge used in async gauge callbacks.
291+ pub struct Gauge2024 {
292+ executor : * mut Gauge2024Executor ,
293+ rx : futures:: channel:: mpsc:: Receiver < Gauge2024Data < ' static > > ,
294+ }
295+
296+ impl Gauge2024 {
297+ /// Send a request to the Microsoft Flight Simulator server to open up communications with a new client.
298+ pub fn open_simconnect < ' a > (
299+ & self ,
300+ name : & str ,
301+ ) -> Result < std:: pin:: Pin < Box < crate :: sim_connect:: SimConnect < ' a > > > , Box < dyn std:: error:: Error > >
302+ {
303+ let executor = self . executor ;
304+ let sim = crate :: sim_connect:: SimConnect :: open ( name, move |_sim, recv| {
305+ let executor = unsafe { & mut * executor } ;
306+ let recv =
307+ unsafe { std:: mem:: transmute :: < SimConnectRecv < ' _ > , SimConnectRecv < ' static > > ( recv) } ;
308+ let data = Gauge2024Data {
309+ delta_time : 0. ,
310+ event : Gauge2024Event :: SimConnect ( recv) ,
311+ } ;
312+ executor
313+ . executor
314+ . send ( Some ( data) )
315+ . unwrap ( ) ;
316+ } ) ?;
317+ Ok ( sim)
318+ }
319+
320+ /// Create a NanoVG rendering context. See `Context` for more details.
321+ #[ cfg( any( target_arch = "wasm32" , doc) ) ]
322+ pub fn create_nanovg ( & self ) -> Option < crate :: nvg:: Context > {
323+ crate :: nvg:: Context :: create ( unsafe { ( * self . executor ) . fs_ctx . unwrap ( ) } )
324+ }
325+
326+ /// Consume the next event from MSFS.
327+ pub fn next_event ( & mut self ) -> impl futures:: Future < Output = Option < Gauge2024Data < ' _ > > > + ' _ {
328+ use futures:: stream:: StreamExt ;
329+ async move { self . rx . next ( ) . await }
330+ }
331+ }
332+
333+ #[ doc( hidden) ]
334+ pub struct Gauge2024Executor {
335+ pub fs_ctx : Option < sys:: FsContext > ,
336+ pub executor : executor:: Executor < Gauge2024 , Gauge2024Data < ' static > > ,
337+ }
338+
339+ #[ doc( hidden) ]
340+ impl Gauge2024Executor {
341+ pub fn handle_gauge_init (
342+ & mut self ,
343+ ctx : sys:: FsContext ,
344+ p_install_data : * const sys:: sGaugeInstallData ,
345+ ) -> bool {
346+ let executor = self as * mut Gauge2024Executor ;
347+ self . fs_ctx = Some ( ctx) ;
348+ if self . executor
349+ . start ( Box :: new ( move |rx| Gauge2024 { executor, rx } ) )
350+ . is_err ( )
351+ {
352+ return false ;
353+ }
354+ let data = Gauge2024Data {
355+ delta_time : 0. ,
356+ event : Gauge2024Event :: Init ( unsafe { & * p_install_data } ) ,
357+ } ;
358+ // Transmute to static lifetime - safe because we process synchronously
359+ let data = unsafe { std:: mem:: transmute :: < Gauge2024Data < ' _ > , Gauge2024Data < ' static > > ( data) } ;
360+ self . executor . send ( Some ( data) ) . is_ok ( )
361+ }
362+
363+ pub fn handle_gauge_update (
364+ & mut self ,
365+ ctx : sys:: FsContext ,
366+ delta_time : f32 ,
367+ ) -> bool {
368+ self . fs_ctx = Some ( ctx) ;
369+ let data = Gauge2024Data {
370+ delta_time,
371+ event : Gauge2024Event :: Update ,
372+ } ;
373+ self . executor . send ( Some ( data) ) . is_ok ( )
374+ }
375+
376+ pub fn handle_gauge_draw (
377+ & mut self ,
378+ ctx : sys:: FsContext ,
379+ p_draw_data : * const sys:: sGaugeDrawData ,
380+ ) -> bool {
381+ self . fs_ctx = Some ( ctx) ;
382+ let data = Gauge2024Data {
383+ delta_time : unsafe { ( * p_draw_data) . dt as f32 } ,
384+ event : Gauge2024Event :: Draw ( unsafe { & * p_draw_data } ) ,
385+ } ;
386+ // Transmute to static lifetime - safe because we process synchronously
387+ let data = unsafe { std:: mem:: transmute :: < Gauge2024Data < ' _ > , Gauge2024Data < ' static > > ( data) } ;
388+ self . executor . send ( Some ( data) ) . is_ok ( )
389+ }
390+
391+ pub fn handle_gauge_kill ( & mut self , ctx : sys:: FsContext ) -> bool {
392+ self . fs_ctx = Some ( ctx) ;
393+ let data = Gauge2024Data {
394+ delta_time : 0. ,
395+ event : Gauge2024Event :: Kill ,
396+ } ;
397+ if !self . executor . send ( Some ( data) ) . is_ok ( ) {
398+ return false ;
399+ }
400+ self . executor . send ( None ) . is_ok ( )
401+ }
402+
403+ pub fn handle_mouse ( & mut self , ctx : sys:: FsContext , x : f32 , y : f32 , flags : i32 ) {
404+ self . fs_ctx = Some ( ctx) ;
405+ let data = Gauge2024Data {
406+ delta_time : 0. ,
407+ event : Gauge2024Event :: Mouse { x, y, flags } ,
408+ } ;
409+ let _ = self . executor . send ( Some ( data) ) ;
410+ }
411+ }
412+
246413pub struct StandaloneModule {
247414 executor : * mut StandaloneModuleExecutor ,
248415 rx : futures:: channel:: mpsc:: Receiver < SimConnectRecv < ' static > > ,
0 commit comments