@@ -41,12 +41,36 @@ use std::ffi::{CStr, CString};
4141
4242use bevy:: log:: warn;
4343use gltf:: Gltf ;
44- use std:: cell:: RefCell ;
44+ use std:: cell:: { Cell , RefCell } ;
4545use std:: collections:: HashMap ;
4646use std:: env;
4747
48+ #[ derive( Clone , Copy ) ]
49+ struct LoopState {
50+ looping : bool ,
51+ redraw_requested : bool ,
52+ }
53+
54+ impl Default for LoopState {
55+ fn default ( ) -> Self {
56+ Self {
57+ looping : true ,
58+ redraw_requested : true ,
59+ }
60+ }
61+ }
62+
4863thread_local ! {
4964 static LAST_GLOBALS : RefCell <HashMap <& ' static str , Py <PyAny >>> = RefCell :: new( HashMap :: new( ) ) ;
65+ static LOOP_STATE : Cell <LoopState > = Cell :: new( LoopState :: default ( ) ) ;
66+ }
67+
68+ fn update_loop_state ( f : impl FnOnce ( & mut LoopState ) ) {
69+ LOOP_STATE . with ( |s| {
70+ let mut state = s. get ( ) ;
71+ f ( & mut state) ;
72+ s. set ( state) ;
73+ } ) ;
5074}
5175
5276/// Writes a new value to globals, iff the new value does not match a previous tracked value.
@@ -710,9 +734,26 @@ mod mewnala {
710734 }
711735
712736 #[ pyfunction]
713- #[ pyo3( pass_module) ]
714- fn redraw ( module : & Bound < ' _ , PyModule > ) -> PyResult < ( ) > {
715- graphics ! ( module) . present ( )
737+ fn redraw ( ) -> PyResult < ( ) > {
738+ update_loop_state ( |s| {
739+ if !s. looping {
740+ s. redraw_requested = true ;
741+ }
742+ } ) ;
743+ Ok ( ( ) )
744+ }
745+
746+ #[ pyfunction]
747+ #[ pyo3( name = "loop" ) ]
748+ fn loop_ ( ) -> PyResult < ( ) > {
749+ update_loop_state ( |s| s. looping = true ) ;
750+ Ok ( ( ) )
751+ }
752+
753+ #[ pyfunction]
754+ fn no_loop ( ) -> PyResult < ( ) > {
755+ update_loop_state ( |s| s. looping = false ) ;
756+ Ok ( ( ) )
716757 }
717758
718759 #[ pyfunction]
@@ -856,14 +897,28 @@ mod mewnala {
856897 if !graphics. surface . poll_events ( ) {
857898 break ;
858899 }
859- graphics. begin_draw ( ) ?;
860900 }
861901
902+ dispatch_event_callbacks ( & locals) ?;
903+
904+ let should_draw = LOOP_STATE . with ( |s| {
905+ let state = s. get ( ) ;
906+ state. looping || state. redraw_requested
907+ } ) ;
908+
909+ if !should_draw {
910+ std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 16 ) ) ;
911+ continue ;
912+ }
913+
914+ get_graphics_mut ( module) ?
915+ . ok_or_else ( || PyRuntimeError :: new_err ( "call size() first" ) ) ?
916+ . begin_draw ( ) ?;
917+
862918 processing:: prelude:: advance_frame_count ( )
863919 . map_err ( |e| PyRuntimeError :: new_err ( format ! ( "{e}" ) ) ) ?;
864920
865921 sync_globals ( module, & globals) ?;
866- dispatch_event_callbacks ( & locals) ?;
867922
868923 draw_fn
869924 . call0 ( )
@@ -872,6 +927,8 @@ mod mewnala {
872927 get_graphics ( module) ?
873928 . ok_or_else ( || PyRuntimeError :: new_err ( "call size() first" ) ) ?
874929 . end_draw ( ) ?;
930+
931+ update_loop_state ( |s| s. redraw_requested = false ) ;
875932 }
876933
877934 Ok ( ( ) )
0 commit comments