7878#include " editor/project_manager.h"
7979#endif
8080
81+ #include < stdint.h>
82+
8183/* Static members */
8284
8385// Singletons
@@ -1026,6 +1028,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
10261028 Engine::get_singleton ()->set_iterations_per_second (GLOBAL_DEF (" physics/common/physics_fps" , 60 ));
10271029 ProjectSettings::get_singleton ()->set_custom_property_info (" physics/common/physics_fps" , PropertyInfo (Variant::INT, " physics/common/physics_fps" , PROPERTY_HINT_RANGE, " 1,120,1,or_greater" ));
10281030 Engine::get_singleton ()->set_physics_jitter_fix (GLOBAL_DEF (" physics/common/physics_jitter_fix" , 0.5 ));
1031+ GLOBAL_DEF (" physics/common/timestep/method" , " Jitter Fix" );
1032+ ProjectSettings::get_singleton ()->set_custom_property_info (" physics/common/timestep/method" , PropertyInfo (Variant::STRING, " physics/common/timestep/method" , PROPERTY_HINT_ENUM, " Jitter Fix,Fixed,Semi Fixed" ));
1033+ Engine::get_singleton ()->_physics_stretch_ticks = GLOBAL_DEF (" physics/common/timestep/timescale_stretch_ticks" , true );
1034+
10291035 Engine::get_singleton ()->set_target_fps (GLOBAL_DEF (" debug/settings/fps/force_fps" , 0 ));
10301036 ProjectSettings::get_singleton ()->set_custom_property_info (" debug/settings/fps/force_fps" , PropertyInfo (Variant::INT, " debug/settings/fps/force_fps" , PROPERTY_HINT_RANGE, " 0,120,1,or_greater" ));
10311037
@@ -1856,6 +1862,35 @@ bool Main::is_iterating() {
18561862static uint64_t physics_process_max = 0 ;
18571863static uint64_t idle_process_max = 0 ;
18581864
1865+ // returns usecs taken by the physics tick
1866+ uint64_t Main::physics_tick (float p_physics_delta) {
1867+ uint64_t physics_begin = OS::get_singleton ()->get_ticks_usec ();
1868+
1869+ PhysicsServer::get_singleton ()->sync ();
1870+ PhysicsServer::get_singleton ()->flush_queries ();
1871+
1872+ Physics2DServer::get_singleton ()->sync ();
1873+ Physics2DServer::get_singleton ()->flush_queries ();
1874+
1875+ if (OS::get_singleton ()->get_main_loop ()->iteration (p_physics_delta)) {
1876+ // UINT64_MAX indicates we want to stop the loop through the physics iterations
1877+ return UINT64_MAX;
1878+ }
1879+
1880+ message_queue->flush ();
1881+
1882+ PhysicsServer::get_singleton ()->step (p_physics_delta);
1883+
1884+ Physics2DServer::get_singleton ()->end_sync ();
1885+ Physics2DServer::get_singleton ()->step (p_physics_delta);
1886+
1887+ message_queue->flush ();
1888+
1889+ Engine::get_singleton ()->_physics_frames ++;
1890+
1891+ return OS::get_singleton ()->get_ticks_usec () - physics_begin;
1892+ }
1893+
18591894bool Main::iteration () {
18601895
18611896 // for now do not error on this
@@ -1865,21 +1900,21 @@ bool Main::iteration() {
18651900
18661901 uint64_t ticks = OS::get_singleton ()->get_ticks_usec ();
18671902 Engine::get_singleton ()->_frame_ticks = ticks;
1868- main_timer_sync.set_cpu_ticks_usec (ticks);
1869- main_timer_sync.set_fixed_fps (fixed_fps);
18701903
18711904 uint64_t ticks_elapsed = ticks - last_ticks;
18721905
18731906 int physics_fps = Engine::get_singleton ()->get_iterations_per_second ();
1874- float frame_slice = 1.0 / physics_fps;
18751907
1876- float time_scale = Engine::get_singleton ()->get_time_scale ();
1908+ // main_timer_sync will deal with time_scale and limiting the max number of physics ticks
1909+ MainFrameTime advance;
1910+ main_timer_sync.advance (advance, physics_fps, ticks, fixed_fps);
18771911
1878- MainFrameTime advance = main_timer_sync.advance (frame_slice, physics_fps);
1879- double step = advance.idle_step ;
1880- double scaled_step = step * time_scale;
1912+ double scaled_step = advance.scaled_frame_delta ;
18811913
1882- Engine::get_singleton ()->_frame_step = step;
1914+ // Note Engine::_frame_step was previously the step unadjusted for timescale.
1915+ // It was unused within Godot, although perhaps used in custom Modules, I'm assuming this was a bug
1916+ // as scaled step makes more sense.
1917+ Engine::get_singleton ()->_frame_step = scaled_step;
18831918 Engine::get_singleton ()->_physics_interpolation_fraction = advance.interpolation_fraction ;
18841919
18851920 uint64_t physics_process_ticks = 0 ;
@@ -1889,50 +1924,40 @@ bool Main::iteration() {
18891924
18901925 last_ticks = ticks;
18911926
1892- static const int max_physics_steps = 8 ;
1893- if (fixed_fps == -1 && advance.physics_steps > max_physics_steps) {
1894- step -= (advance.physics_steps - max_physics_steps) * frame_slice;
1895- advance.physics_steps = max_physics_steps;
1896- }
1897-
18981927 bool exit = false ;
18991928
19001929 Engine::get_singleton ()->_in_physics = true ;
19011930
1902- for ( int iters = 0 ; iters < advance.physics_steps ; ++iters) {
1931+ float physics_delta = advance.physics_fixed_step_delta ;
19031932
1904- uint64_t physics_begin = OS::get_singleton ()-> get_ticks_usec ();
1933+ for ( int iters = 0 ; iters < advance. physics_steps ; ++iters) {
19051934
1906- PhysicsServer::get_singleton ()->sync ();
1907- PhysicsServer::get_singleton ()->flush_queries ();
1935+ // special case, if using variable physics timestep and the last physics step
1936+ if (advance.physics_variable_step && (iters == (advance.physics_steps - 1 ))) {
1937+ // substitute the variable delta
1938+ physics_delta = advance.physics_variable_step_delta ;
1939+ }
19081940
1909- Physics2DServer::get_singleton ()-> sync ();
1910- Physics2DServer::get_singleton ()-> flush_queries ( );
1941+ // returns the time taken by the physics tick
1942+ uint64_t physics_usecs = physics_tick (physics_delta );
19111943
1912- if (OS::get_singleton ()->get_main_loop ()->iteration (frame_slice * time_scale)) {
1944+ // in the special case of wanting to exit the loop we are passing
1945+ // UINT64_MAX which will never occur normally.
1946+ if (physics_usecs == UINT64_MAX) {
19131947 exit = true ;
19141948 break ;
19151949 }
19161950
1917- message_queue->flush ();
1918-
1919- PhysicsServer::get_singleton ()->step (frame_slice * time_scale);
1920-
1921- Physics2DServer::get_singleton ()->end_sync ();
1922- Physics2DServer::get_singleton ()->step (frame_slice * time_scale);
1923-
1924- message_queue->flush ();
1925-
1926- physics_process_ticks = MAX (physics_process_ticks, OS::get_singleton ()->get_ticks_usec () - physics_begin); // keep the largest one for reference
1927- physics_process_max = MAX (OS::get_singleton ()->get_ticks_usec () - physics_begin, physics_process_max);
1928- Engine::get_singleton ()->_physics_frames ++;
1951+ // performance stats
1952+ physics_process_ticks = MAX (physics_process_ticks, physics_usecs); // keep the largest one for reference
1953+ physics_process_max = MAX (physics_usecs, physics_process_max);
19291954 }
19301955
19311956 Engine::get_singleton ()->_in_physics = false ;
19321957
19331958 uint64_t idle_begin = OS::get_singleton ()->get_ticks_usec ();
19341959
1935- if (OS::get_singleton ()->get_main_loop ()->idle (step * time_scale )) {
1960+ if (OS::get_singleton ()->get_main_loop ()->idle (scaled_step )) {
19361961 exit = true ;
19371962 }
19381963 message_queue->flush ();
@@ -1965,6 +1990,8 @@ bool Main::iteration() {
19651990
19661991 if (script_debugger) {
19671992 if (script_debugger->is_profiling ()) {
1993+ // note that frame_slice is original physics delta, before time_scale applied
1994+ float frame_slice = 1.0 / physics_fps;
19681995 script_debugger->profiling_set_frame_times (USEC_TO_SEC (frame_time), USEC_TO_SEC (idle_process_ticks), USEC_TO_SEC (physics_process_ticks), frame_slice);
19691996 }
19701997 script_debugger->idle_poll ();
0 commit comments