From 6181b2bce343204f7594f5c559d9b7ee09525abe Mon Sep 17 00:00:00 2001 From: Dan Amlund Date: Sat, 3 Feb 2018 16:29:30 +0100 Subject: [PATCH] Add tweak that replaces dwarf mode FPS counter with one that does not count when paused --- dfhack.init-example | 3 + plugins/tweak/tweak.cpp | 7 ++ plugins/tweak/tweaks/pausing-fps-counter.h | 137 +++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 plugins/tweak/tweaks/pausing-fps-counter.h diff --git a/dfhack.init-example b/dfhack.init-example index 82210a2a6..fb846a47f 100644 --- a/dfhack.init-example +++ b/dfhack.init-example @@ -202,6 +202,9 @@ tweak hotkey-clear # Allows lowercase letters in embark profile names, and allows exiting the name prompt without saving tweak embark-profile-name +# dwarf mode FPS counter that does not jump to FPS_CAP when paused +tweak pausing-fps-counter + # Misc. UI tweaks tweak block-labors # Prevents labors that can't be used from being toggled tweak burrow-name-cancel diff --git a/plugins/tweak/tweak.cpp b/plugins/tweak/tweak.cpp index 252f4c738..6b5b1f687 100644 --- a/plugins/tweak/tweak.cpp +++ b/plugins/tweak/tweak.cpp @@ -98,6 +98,7 @@ #include "tweaks/kitchen-prefs-empty.h" #include "tweaks/max-wheelbarrow.h" #include "tweaks/military-assign.h" +#include "tweaks/pausing-fps-counter.h" #include "tweaks/nestbox-color.h" #include "tweaks/shift-8-scroll.h" #include "tweaks/stable-cursor.h" @@ -232,6 +233,9 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector 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);