Merge remote-tracking branch 'danamlund/better-fps-counter' into develop
						commit
						3a122d7391
					
				| @ -0,0 +1,137 @@ | ||||
| #include "df/global_objects.h" | ||||
| #include "modules/Gui.h" | ||||
| #include "modules/Screen.h" | ||||
| #include "df/enabler.h" | ||||
| #include "df/viewscreen_dwarfmodest.h" | ||||
| #include "df/viewscreen_titlest.h" | ||||
| 
 | ||||
| struct dwarfmode_pausing_fps_counter_hook : df::viewscreen_dwarfmodest { | ||||
|     typedef df::viewscreen_dwarfmodest interpose_base; | ||||
| 
 | ||||
|     static const uint32_t history_length = 3; | ||||
| 
 | ||||
|     // whether init.txt have [FPS:YES]
 | ||||
|     static bool init_have_fps_yes() | ||||
|     { | ||||
|         static bool first = true; | ||||
|         static bool init_have_fps_yes; | ||||
| 
 | ||||
|         if (first && df::global::gps) | ||||
|         { | ||||
|             // if first time called, then display_frames is set iff init.txt have [FPS:YES]
 | ||||
|             first = false; | ||||
|             init_have_fps_yes = (df::global::gps->display_frames == 1); | ||||
|         } | ||||
|         return init_have_fps_yes; | ||||
|     } | ||||
| 
 | ||||
|     DEFINE_VMETHOD_INTERPOSE(void, render, ()) | ||||
|     { | ||||
|         INTERPOSE_NEXT(render)(); | ||||
| 
 | ||||
|         if (!df::global::pause_state || !df::global::enabler || !df::global::world | ||||
|             || !df::global::gps || !df::global::pause_state) | ||||
|             return; | ||||
| 
 | ||||
|         // if init.txt does not have [FPS:YES] then dont show this FPS counter
 | ||||
|         if (!dwarfmode_pausing_fps_counter_hook::init_have_fps_yes()) | ||||
|             return; | ||||
| 
 | ||||
|         static bool prev_paused = true; | ||||
|         static uint32_t prev_clock = 0; | ||||
|         static int32_t prev_frames = 0; | ||||
|         static uint32_t elapsed_clock = 0; | ||||
|         static uint32_t elapsed_frames = 0; | ||||
|         static double history[history_length]; | ||||
| 
 | ||||
|         if (prev_clock == 0) | ||||
|         { | ||||
|             // init
 | ||||
|             for (int i = 0; i < history_length; i++) | ||||
|                 history[i] = 0.0; | ||||
|         } | ||||
| 
 | ||||
|         // disable default FPS counter because it is rendered on top of this FPS counter.
 | ||||
|         if (df::global::gps->display_frames == 1) | ||||
|             df::global::gps->display_frames = 0; | ||||
| 
 | ||||
|         if (*df::global::pause_state) | ||||
|             prev_paused = true; | ||||
|         else | ||||
|         { | ||||
|             uint32_t clock = df::global::enabler->clock; | ||||
|             int32_t frames = df::global::world->frame_counter; | ||||
| 
 | ||||
|             if (!prev_paused && prev_clock != 0 | ||||
|                 && clock >= prev_clock && frames >= prev_frames) | ||||
|             { | ||||
|                 // if we were previously paused, then dont add clock/frames,
 | ||||
|                 // but wait for the next time render is called.
 | ||||
|                 elapsed_clock += clock - prev_clock; | ||||
|                 elapsed_frames += frames - prev_frames; | ||||
|             } | ||||
| 
 | ||||
|             prev_paused = false; | ||||
|             prev_clock = clock; | ||||
|             prev_frames = frames; | ||||
| 
 | ||||
|             // add FPS to history every second or after at least one frame.
 | ||||
|             if (elapsed_clock >= 1000 && elapsed_frames >= 1) | ||||
|             { | ||||
|                 double fps = elapsed_frames / (elapsed_clock / 1000.0); | ||||
|                 for (int i = history_length - 1; i >= 1; i--) | ||||
|                     history[i] = history[i - 1]; | ||||
|                 history[0] = fps; | ||||
| 
 | ||||
|                 elapsed_clock = 0; | ||||
|                 elapsed_frames = 0; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // average fps over a few seconds to stabilize the counter.
 | ||||
|         double fps_sum = 0.0; | ||||
|         int fps_count = 0; | ||||
|         for (int i = 0; i < history_length; i++) | ||||
|         { | ||||
|             if (history[i] > 0.0) | ||||
|             { | ||||
|                 fps_sum += history[i]; | ||||
|                 fps_count++; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         double fps = fps_count == 0 ? 1.0 : fps_sum / fps_count; | ||||
|         double gfps = df::global::enabler->calculated_gfps; | ||||
| 
 | ||||
|         std::stringstream fps_counter; | ||||
|         fps_counter << "FPS:" | ||||
|                     << setw(4) << fixed << setprecision(fps >= 1.0 ? 0 : 2) << fps | ||||
|                     << " (" << gfps << ")"; | ||||
| 
 | ||||
|         // show this FPS counter same as the default counter.
 | ||||
|         int x = 10; | ||||
|         int y = 0; | ||||
|         OutputString(COLOR_WHITE, x, y, fps_counter.str(), | ||||
|                      false, 0, COLOR_CYAN, false); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| struct title_pausing_fps_counter_hook : df::viewscreen_titlest { | ||||
|     typedef df::viewscreen_titlest interpose_base; | ||||
| 
 | ||||
|     DEFINE_VMETHOD_INTERPOSE(void, render, ()) | ||||
|     { | ||||
|         INTERPOSE_NEXT(render)(); | ||||
| 
 | ||||
|         // if init.txt have FPS:YES then enable default FPS counter when exiting dwarf mode.
 | ||||
|         // So it is enabled if starting adventure mode without exiting dwarf fortress.
 | ||||
|         if (dwarfmode_pausing_fps_counter_hook::init_have_fps_yes() | ||||
|             && df::global::gps && df::global::gps->display_frames == 0) | ||||
|             df::global::gps->display_frames = 1; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| IMPLEMENT_VMETHOD_INTERPOSE(dwarfmode_pausing_fps_counter_hook, render); | ||||
| 
 | ||||
| IMPLEMENT_VMETHOD_INTERPOSE(title_pausing_fps_counter_hook, render); | ||||
		Loading…
	
		Reference in New Issue