Implement an optional FPS counter (#850)

Shows a counter at the top of the screen, indicating the number of frames drawn per second, based on std::chrono.
This commit is contained in:
Aaron van Geffen 2021-03-27 01:06:24 +01:00 committed by GitHub
parent 6d5b481b61
commit 86de7364ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 107 additions and 10 deletions

View File

@ -1,5 +1,6 @@
21.03+ (???)
------------------------------------------------------------------------
- Feature: [#451] Optionally show an FPS counter at the top of the screen.
- Fix: [#804] Enter key not confirming save prompt.
- Fix: [#809] Audio calculation not using the z axis.
- Fix: [#825] Potential crash when opening town rename prompt.

View File

@ -2213,3 +2213,5 @@ strings:
2158: "Enable sandbox mode"
2159: "Allow manual driving"
2160: "Allow building while paused"
2161: "Show FPS counter"
2162: "{SMALLFONT}{COLOUR BLACK}This shows a counter at the top of the screen, indicating the number of frames drawn per second."

View File

@ -93,6 +93,8 @@ namespace OpenLoco::Config
_new_config.autosave_frequency = config["autosave_frequency"].as<int32_t>();
if (config["autosave_amount"])
_new_config.autosave_amount = config["autosave_amount"].as<int32_t>();
if (config["showFPS"])
_new_config.showFPS = config["showFPS"].as<bool>();
return _new_config;
}
@ -141,6 +143,7 @@ namespace OpenLoco::Config
node["zoom_to_cursor"] = _new_config.zoom_to_cursor;
node["autosave_frequency"] = _new_config.autosave_frequency;
node["autosave_amount"] = _new_config.autosave_amount;
node["showFPS"] = _new_config.showFPS;
std::ofstream stream(configPath);
if (stream.is_open())

View File

@ -156,6 +156,7 @@ namespace OpenLoco::Config
bool zoom_to_cursor = true;
int32_t autosave_frequency = 1;
int32_t autosave_amount = 12;
bool showFPS = false;
};
#pragma pack(pop)

View File

@ -0,0 +1,61 @@
#include "FPSCounter.h"
#include "../Graphics/Colour.h"
#include "../Graphics/Gfx.h"
#include "../Localisation/StringManager.h"
#include "../Ui.h"
#include <chrono>
#include <stdio.h>
namespace OpenLoco::Drawing
{
using Clock_t = std::chrono::high_resolution_clock;
using TimePoint_t = Clock_t::time_point;
static TimePoint_t _referenceTime;
static uint32_t _currentFrameCount;
static float _currentFPS;
static float measureFPS()
{
_currentFrameCount++;
auto currentTime = Clock_t::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - _referenceTime).count() / 1000.0;
if (elapsed > 1.0)
{
_currentFPS = _currentFrameCount / elapsed;
_currentFrameCount = 0;
_referenceTime = currentTime;
}
return _currentFPS;
}
void drawFPS()
{
// Measure FPS
const float fps = measureFPS();
// Format string
char buffer[64];
buffer[0] = ControlCodes::font_bold;
buffer[1] = ControlCodes::outline;
buffer[2] = ControlCodes::colour_white;
const char* formatString = (_currentFPS >= 10.0f ? "%.0f" : "%.1f");
snprintf(&buffer[3], std::size(buffer) - 3, formatString, fps);
auto& dpi = Gfx::screenDpi();
// Draw text
const int stringWidth = Gfx::getStringWidth(buffer);
const auto x = Ui::width() / 2 - (stringWidth / 2);
const auto y = 2;
Gfx::drawString(&dpi, x, y, Colour::black, buffer);
// Make area dirty so the text doesn't get drawn over the last
Gfx::setDirtyBlocks(x - 16, y - 4, x + 16, 16);
}
}

View File

@ -0,0 +1,4 @@
namespace OpenLoco::Drawing
{
void drawFPS();
}

View File

@ -1500,4 +1500,6 @@ namespace OpenLoco::StringIds
constexpr string_id cheat_enable_sandbox_mode = 2158;
constexpr string_id cheat_allow_manual_driving = 2159;
constexpr string_id cheat_allow_building_while_paused = 2160;
constexpr string_id option_show_fps_counter = 2161;
constexpr string_id option_show_fps_counter_tooltip = 2162;
}

View File

@ -31,6 +31,7 @@
#include "Config.h"
#include "Console.h"
#include "Drawing/FPSCounter.h"
#include "GameCommands.h"
#include "Graphics/Gfx.h"
#include "Gui.h"
@ -432,6 +433,12 @@ namespace OpenLoco::Ui
}
}
// Draw FPS counter?
if (Config::getNew().showFPS)
{
Drawing::drawFPS();
}
// Copy pixels from the virtual screen buffer to the surface
auto& dpi = Gfx::screenDpi();
if (dpi.bits != nullptr)

View File

@ -166,7 +166,7 @@ namespace OpenLoco::Ui::Options
namespace Display
{
static const Gfx::ui_size_t _window_size = { 400, 184 };
static const Gfx::ui_size_t _window_size = { 400, 199 };
namespace Widx
{
@ -179,6 +179,7 @@ namespace OpenLoco::Ui::Options
display_scale,
display_scale_down_btn,
display_scale_up_btn,
show_fps,
landscape_smoothing,
gridlines_on_landscape,
vehicles_min_scale,
@ -197,20 +198,18 @@ namespace OpenLoco::Ui::Options
makeWidget({ 235, 64 }, { 156, 12 }, widget_type::wt_18, 1, StringIds::display_resolution_label_format),
makeWidget({ 379, 65 }, { 11, 10 }, widget_type::wt_11, 1, StringIds::dropdown),
makeStepperWidgets({ 235, 79 }, { 156, 12 }, widget_type::wt_17, 1, StringIds::empty),
makeWidget({ 10, 99 }, { 346, 12 }, widget_type::checkbox, 1, StringIds::landscape_smoothing, StringIds::landscape_smoothing_tip),
makeWidget({ 10, 114 }, { 346, 12 }, widget_type::checkbox, 1, StringIds::gridlines_on_landscape, StringIds::gridlines_on_landscape_tip),
makeWidget({ 235, 133 }, { 156, 12 }, widget_type::wt_18, 1, StringIds::empty, StringIds::vehicles_min_scale_tip),
makeWidget({ 379, 134 }, { 11, 10 }, widget_type::wt_11, 1, StringIds::dropdown, StringIds::vehicles_min_scale_tip),
makeWidget({ 235, 148 }, { 156, 12 }, widget_type::wt_18, 1, StringIds::empty, StringIds::station_names_min_scale_tip),
makeWidget({ 379, 149 }, { 11, 10 }, widget_type::wt_11, 1, StringIds::dropdown, StringIds::station_names_min_scale_tip),
makeWidget({ 235, 163 }, { 156, 12 }, widget_type::wt_18, 1, StringIds::empty),
makeWidget({ 379, 164 }, { 11, 10 }, widget_type::wt_11, 1, StringIds::dropdown),
makeWidget({ 10, 99 }, { 346, 12 }, widget_type::checkbox, 1, StringIds::option_show_fps_counter, StringIds::option_show_fps_counter_tooltip),
makeWidget({ 10, 114 }, { 346, 12 }, widget_type::checkbox, 1, StringIds::landscape_smoothing, StringIds::landscape_smoothing_tip),
makeWidget({ 10, 129 }, { 346, 12 }, widget_type::checkbox, 1, StringIds::gridlines_on_landscape, StringIds::gridlines_on_landscape_tip),
makeDropdownWidgets({ 235, 148 }, { 156, 12 }, widget_type::wt_18, 1, StringIds::empty, StringIds::vehicles_min_scale_tip),
makeDropdownWidgets({ 235, 163 }, { 156, 12 }, widget_type::wt_18, 1, StringIds::empty, StringIds::station_names_min_scale_tip),
makeDropdownWidgets({ 235, 178 }, { 156, 12 }, widget_type::wt_18, 1, StringIds::empty),
widgetEnd(),
};
static window_event_list _events;
static constexpr uint64_t enabledWidgets = Common::enabledWidgets | (1 << Display::Widx::landscape_smoothing) | (1 << Display::Widx::gridlines_on_landscape) | (1 << Display::Widx::vehicles_min_scale) | (1 << Display::Widx::vehicles_min_scale_btn) | (1 << Display::Widx::station_names_min_scale) | (1 << Display::Widx::station_names_min_scale_btn) | (1 << Display::Widx::construction_marker) | (1 << Display::Widx::construction_marker_btn) | (1 << Display::Widx::display_scale_up_btn) | (1 << Display::Widx::display_scale_down_btn);
static constexpr uint64_t enabledWidgets = Common::enabledWidgets | (1 << Widx::show_fps) | (1 << Display::Widx::landscape_smoothing) | (1 << Display::Widx::gridlines_on_landscape) | (1 << Display::Widx::vehicles_min_scale) | (1 << Display::Widx::vehicles_min_scale_btn) | (1 << Display::Widx::station_names_min_scale) | (1 << Display::Widx::station_names_min_scale_btn) | (1 << Display::Widx::construction_marker) | (1 << Display::Widx::construction_marker_btn) | (1 << Display::Widx::display_scale_up_btn) | (1 << Display::Widx::display_scale_down_btn);
// 0x004BFB8C
static void onMouseUp(window* w, widget_index wi)
@ -230,6 +229,15 @@ namespace OpenLoco::Ui::Options
Options::tabOnMouseUp(w, wi);
return;
case Widx::show_fps:
{
auto& cfg = OpenLoco::Config::getNew();
cfg.showFPS ^= 1;
OpenLoco::Config::writeNewConfig();
Gfx::invalidateScreen();
return;
}
case Widx::landscape_smoothing:
{
auto& cfg = OpenLoco::Config::get();
@ -556,6 +564,12 @@ namespace OpenLoco::Ui::Options
w->widgets[Widx::vehicles_min_scale].text = scale_string_ids[Config::get().vehicles_min_scale];
w->widgets[Widx::station_names_min_scale].text = scale_string_ids[Config::get().station_names_min_scale];
w->activated_widgets &= ~(1 << Widx::show_fps);
if (Config::getNew().showFPS)
{
w->activated_widgets |= (1 << Widx::show_fps);
}
w->activated_widgets &= ~(1 << Widx::landscape_smoothing);
if ((Config::get().flags & Config::flags::landscape_smoothing) == 0)
{

View File

@ -24,6 +24,7 @@
<ClCompile Include="Config.cpp" />
<ClCompile Include="Console.cpp" />
<ClCompile Include="Date.cpp" />
<ClCompile Include="Drawing\FPSCounter.cpp" />
<ClCompile Include="Drawing\SoftwareDrawingEngine.cpp" />
<ClCompile Include="Economy.cpp" />
<ClCompile Include="EditorController.cpp" />
@ -206,6 +207,7 @@
<ClInclude Include="Core\Span.hpp" />
<ClInclude Include="Currency.h" />
<ClInclude Include="Date.h" />
<ClInclude Include="Drawing\FPSCounter.h" />
<ClInclude Include="Drawing\SoftwareDrawingEngine.h" />
<ClInclude Include="Economy.h" />
<ClInclude Include="EditorController.h" />