From 1ba4dcc92458b078dc869d381075b6c071221950 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 13 Apr 2023 17:18:27 +0200 Subject: [PATCH] Codechange: migrate all Window-related timers to the new framework This means we also say goodbye to GUITimers. --- src/CMakeLists.txt | 1 - src/company_gui.cpp | 18 +++++---- src/console_gui.cpp | 13 +++---- src/error.h | 7 ++-- src/error_gui.cpp | 41 ++++++++++++--------- src/framerate_gui.cpp | 31 +++++++--------- src/game/game_gui.cpp | 20 +++++----- src/graph_gui.cpp | 16 ++++++-- src/guitimer_func.h | 63 -------------------------------- src/industry_gui.cpp | 13 ++++--- src/main_gui.cpp | 38 +++++++++++-------- src/misc_gui.cpp | 33 +++++++---------- src/network/network_chat_gui.cpp | 9 +++-- src/network/network_func.h | 1 - src/network/network_gui.cpp | 16 +++----- src/newgrf_gui.cpp | 18 ++++----- src/news_gui.cpp | 28 ++++++-------- src/script/script_gui.cpp | 20 +++++----- src/signs_gui.cpp | 8 ++-- src/smallmap_gui.cpp | 28 ++++++++++---- src/smallmap_gui.h | 21 ++++++++--- src/statusbar_gui.cpp | 38 ++++++++----------- src/texteff.cpp | 14 +++---- src/texteff.hpp | 1 - src/toolbar_gui.cpp | 29 ++++----------- src/town_gui.cpp | 14 ++++--- src/widgets/dropdown.cpp | 26 ++++++------- src/window.cpp | 23 ++++-------- src/window_gui.h | 7 ---- 29 files changed, 259 insertions(+), 336 deletions(-) delete mode 100644 src/guitimer_func.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2af0f95b2e..b251378fad 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -192,7 +192,6 @@ add_files( group_gui.h group_type.h gui.h - guitimer_func.h heightmap.cpp heightmap.h highscore.cpp diff --git a/src/company_gui.cpp b/src/company_gui.cpp index dfb1415fcf..1d923c6d61 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -42,6 +42,8 @@ #include "group_cmd.h" #include "misc_cmd.h" #include "object_cmd.h" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "widgets/company_widget.h" @@ -519,15 +521,18 @@ struct CompanyFinancesWindow : Window { } } - void OnHundredthTick() override - { + /** + * Check on a regular interval if the maximum amount of money has changed. + * If it has, rescale the window to fit the new amount. + */ + IntervalTimer rescale_interval = {std::chrono::seconds(3), [this](auto) { const Company *c = Company::Get((CompanyID)this->window_number); if (c->money > CompanyFinancesWindow::max_money) { CompanyFinancesWindow::max_money = std::max(c->money * 2, CompanyFinancesWindow::max_money * 4); this->SetupWidgets(); this->ReInit(); } - } + }}; }; /** First conservative estimate of the maximum amount of money */ @@ -2679,11 +2684,10 @@ struct CompanyWindow : Window } } - void OnHundredthTick() override - { - /* redraw the window every now and then */ + /** Redraw the window on a regular interval. */ + IntervalTimer redraw_interval = {std::chrono::seconds(3), [this](auto) { this->SetDirty(); - } + }}; void OnPlaceObject(Point pt, TileIndex tile) override { diff --git a/src/console_gui.cpp b/src/console_gui.cpp index 972ef23b24..270d005d0e 100644 --- a/src/console_gui.cpp +++ b/src/console_gui.cpp @@ -12,7 +12,6 @@ #include "window_gui.h" #include "console_gui.h" #include "console_internal.h" -#include "guitimer_func.h" #include "window_func.h" #include "string_func.h" #include "strings_func.h" @@ -21,6 +20,8 @@ #include "console_func.h" #include "rev.h" #include "video/video_driver.hpp" +#include "timer/timer.h" +#include "timer/timer_window.h" #include #include @@ -115,14 +116,12 @@ struct IConsoleWindow : Window static size_t scroll; int line_height; ///< Height of one line of text in the console. int line_offset; - GUITimer truncate_timer; IConsoleWindow() : Window(&_console_window_desc) { _iconsole_mode = ICONSOLE_OPENED; this->InitNested(0); - this->truncate_timer.SetInterval(3000); ResizeWindow(this, _screen.width, _screen.height / 3); } @@ -186,10 +185,8 @@ struct IConsoleWindow : Window } } - void OnRealtimeTick(uint delta_ms) override - { - if (this->truncate_timer.CountElapsed(delta_ms) == 0) return; - + /** Check on a regular interval if the console buffer needs truncating. */ + IntervalTimer truncate_interval = {std::chrono::seconds(3), [this](auto) { assert(this->height >= 0 && this->line_height > 0); size_t visible_lines = (size_t)(this->height / this->line_height); @@ -198,7 +195,7 @@ struct IConsoleWindow : Window IConsoleWindow::scroll = std::min(IConsoleWindow::scroll, max_scroll); this->SetDirty(); } - } + }}; void OnMouseLoop() override { diff --git a/src/error.h b/src/error.h index 51b164c432..cac0c503bf 100644 --- a/src/error.h +++ b/src/error.h @@ -15,7 +15,8 @@ #include "company_type.h" #include "command_type.h" #include "core/geometry_type.hpp" -#include "guitimer_func.h" + +#include struct GRFFile; @@ -30,7 +31,7 @@ enum WarningLevel { /** The data of the error message. */ class ErrorMessageData { protected: - GUITimer display_timer; ///< Timer before closing the message. + bool is_critical; ///< Whether the error message is critical. uint64 decode_params[20]; ///< Parameters of the message strings. const char *strings[20]; ///< Copies of raw strings that were used. const GRFFile *textref_stack_grffile; ///< NewGRF that filled the #TextRefStack for the error message. @@ -45,7 +46,7 @@ protected: public: ErrorMessageData(const ErrorMessageData &data); ~ErrorMessageData(); - ErrorMessageData(StringID summary_msg, StringID detailed_msg, uint duration = 0, int x = 0, int y = 0, const GRFFile *textref_stack_grffile = nullptr, uint textref_stack_size = 0, const uint32 *textref_stack = nullptr, StringID extra_msg = INVALID_STRING_ID); + ErrorMessageData(StringID summary_msg, StringID detailed_msg, bool is_critical = false, int x = 0, int y = 0, const GRFFile *textref_stack_grffile = nullptr, uint textref_stack_size = 0, const uint32 *textref_stack = nullptr, StringID extra_msg = INVALID_STRING_ID); /* Remove the copy assignment, as the default implementation will not do the right thing. */ ErrorMessageData &operator=(ErrorMessageData &rhs) = delete; diff --git a/src/error_gui.cpp b/src/error_gui.cpp index 6d05d24395..b682e7e257 100644 --- a/src/error_gui.cpp +++ b/src/error_gui.cpp @@ -21,6 +21,8 @@ #include "window_func.h" #include "console_func.h" #include "window_gui.h" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "widgets/error_widget.h" @@ -71,7 +73,7 @@ static WindowDesc _errmsg_face_desc( * @param data The data to copy. */ ErrorMessageData::ErrorMessageData(const ErrorMessageData &data) : - display_timer(data.display_timer), textref_stack_grffile(data.textref_stack_grffile), textref_stack_size(data.textref_stack_size), + is_critical(data.is_critical), textref_stack_grffile(data.textref_stack_grffile), textref_stack_size(data.textref_stack_size), summary_msg(data.summary_msg), detailed_msg(data.detailed_msg), extra_msg(data.extra_msg), position(data.position), face(data.face) { memcpy(this->textref_stack, data.textref_stack, sizeof(this->textref_stack)); @@ -95,7 +97,7 @@ ErrorMessageData::~ErrorMessageData() * Display an error message in a window. * @param summary_msg General error message showed in first line. Must be valid. * @param detailed_msg Detailed error message showed in second line. Can be INVALID_STRING_ID. - * @param duration The amount of time to show this error message. + * @param is_critical Whether the error is critical. Critical messages never go away on their own. * @param x World X position (TileVirtX) of the error location. Set both x and y to 0 to just center the message when there is no related error tile. * @param y World Y position (TileVirtY) of the error location. Set both x and y to 0 to just center the message when there is no related error tile. * @param textref_stack_grffile NewGRF that provides the #TextRefStack for the error message. @@ -103,7 +105,8 @@ ErrorMessageData::~ErrorMessageData() * @param textref_stack Values to put on the #TextRefStack. * @param extra_msg Extra error message showed in third line. Can be INVALID_STRING_ID. */ -ErrorMessageData::ErrorMessageData(StringID summary_msg, StringID detailed_msg, uint duration, int x, int y, const GRFFile *textref_stack_grffile, uint textref_stack_size, const uint32 *textref_stack, StringID extra_msg) : +ErrorMessageData::ErrorMessageData(StringID summary_msg, StringID detailed_msg, bool is_critical, int x, int y, const GRFFile *textref_stack_grffile, uint textref_stack_size, const uint32 *textref_stack, StringID extra_msg) : + is_critical(is_critical), textref_stack_grffile(textref_stack_grffile), textref_stack_size(textref_stack_size), summary_msg(summary_msg), @@ -120,8 +123,6 @@ ErrorMessageData::ErrorMessageData(StringID summary_msg, StringID detailed_msg, if (textref_stack_size > 0) MemCpyT(this->textref_stack, textref_stack, textref_stack_size); assert(summary_msg != INVALID_STRING_ID); - - this->display_timer.SetInterval(duration * 3000); } /** @@ -187,11 +188,22 @@ private: uint height_summary; ///< Height of the #summary_msg string in pixels in the #WID_EM_MESSAGE widget. uint height_detailed; ///< Height of the #detailed_msg string in pixels in the #WID_EM_MESSAGE widget. uint height_extra; ///< Height of the #extra_msg string in pixels in the #WID_EM_MESSAGE widget. + TimeoutTimer display_timeout; public: - ErrmsgWindow(const ErrorMessageData &data) : Window(data.HasFace() ? &_errmsg_face_desc : &_errmsg_desc), ErrorMessageData(data) + ErrmsgWindow(const ErrorMessageData &data) : + Window(data.HasFace() ? &_errmsg_face_desc : &_errmsg_desc), + ErrorMessageData(data), + display_timeout(std::chrono::seconds(3 * _settings_client.gui.errmsg_duration), [this]() { + this->Close(); + }) { this->InitNested(); + + /* Only start the timeout if the message is not critical. */ + if (!this->is_critical) { + this->display_timeout.Reset(); + } } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -316,14 +328,7 @@ public: void OnMouseLoop() override { /* Disallow closing the window too easily, if timeout is disabled */ - if (_right_button_down && !this->display_timer.HasElapsed()) this->Close(); - } - - void OnRealtimeTick(uint delta_ms) override - { - if (this->display_timer.CountElapsed(delta_ms) == 0) return; - - this->Close(); + if (_right_button_down && !this->is_critical) this->Close(); } void Close() override @@ -339,7 +344,7 @@ public: */ bool IsCritical() { - return this->display_timer.HasElapsed(); + return this->is_critical; } }; @@ -428,12 +433,12 @@ void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel IConsolePrint(wl == WL_WARNING ? CC_WARNING : CC_ERROR, buf); } - bool no_timeout = wl == WL_CRITICAL; + bool is_critical = wl == WL_CRITICAL; if (_game_mode == GM_BOOTSTRAP) return; - if (_settings_client.gui.errmsg_duration == 0 && !no_timeout) return; + if (_settings_client.gui.errmsg_duration == 0 && !is_critical) return; - ErrorMessageData data(summary_msg, detailed_msg, no_timeout ? 0 : _settings_client.gui.errmsg_duration, x, y, textref_stack_grffile, textref_stack_size, textref_stack, extra_msg); + ErrorMessageData data(summary_msg, detailed_msg, is_critical, x, y, textref_stack_grffile, textref_stack_size, textref_stack, extra_msg); data.CopyOutDParams(); ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0); diff --git a/src/framerate_gui.cpp b/src/framerate_gui.cpp index 1a676933ee..e4db1ee341 100644 --- a/src/framerate_gui.cpp +++ b/src/framerate_gui.cpp @@ -17,12 +17,13 @@ #include "strings_func.h" #include "console_func.h" #include "console_type.h" -#include "guitimer_func.h" #include "company_base.h" #include "ai/ai_info.hpp" #include "ai/ai_instance.hpp" #include "game/game.hpp" #include "game/game_instance.hpp" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "widgets/framerate_widget.h" @@ -410,7 +411,6 @@ static const NWidgetPart _framerate_window_widgets[] = { struct FramerateWindow : Window { bool small; bool showing_memory; - GUITimer next_update; int num_active; int num_displayed; @@ -456,7 +456,6 @@ struct FramerateWindow : Window { this->showing_memory = true; this->UpdateData(); this->num_displayed = this->num_active; - this->next_update.SetInterval(100); /* Window is always initialised to MIN_ELEMENTS height, resize to contain num_displayed */ ResizeWindow(this, 0, (std::max(MIN_ELEMENTS, this->num_displayed) - MIN_ELEMENTS) * FONT_HEIGHT_NORMAL); @@ -464,22 +463,21 @@ struct FramerateWindow : Window { void OnRealtimeTick(uint delta_ms) override { - bool elapsed = this->next_update.Elapsed(delta_ms); - /* Check if the shaded state has changed, switch caption text if it has */ if (this->small != this->IsShaded()) { this->small = this->IsShaded(); this->GetWidget(WID_FRW_CAPTION)->SetDataTip(this->small ? STR_FRAMERATE_CAPTION_SMALL : STR_FRAMERATE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS); - elapsed = true; - } - - if (elapsed) { this->UpdateData(); this->SetDirty(); - this->next_update.SetInterval(100); } } + /** Update the window on a regular interval. */ + IntervalTimer update_interval = {std::chrono::milliseconds(100), [this](auto) { + this->UpdateData(); + this->SetDirty(); + }}; + void UpdateData() { double gl_rate = _pf_data[PFE_GAMELOOP].GetRate(); @@ -754,7 +752,6 @@ static const NWidgetPart _frametime_graph_window_widgets[] = { struct FrametimeGraphWindow : Window { int vertical_scale; ///< number of TIMESTAMP_PRECISION units vertically int horizontal_scale; ///< number of half-second units horizontally - GUITimer next_scale_update; ///< interval for next scale update PerformanceElement element; ///< what element this window renders graph for Dimension graph_size; ///< size of the main graph area (excluding axis labels) @@ -764,9 +761,9 @@ struct FrametimeGraphWindow : Window { this->element = (PerformanceElement)number; this->horizontal_scale = 4; this->vertical_scale = TIMESTAMP_PRECISION / 10; - this->next_scale_update.SetInterval(1); this->InitNested(number); + this->UpdateScale(); } void SetStringParameters(int widget) const override @@ -882,14 +879,14 @@ struct FrametimeGraphWindow : Window { this->SelectVerticalScale(peak_value); } + /** Update the scaling on a regular interval. */ + IntervalTimer update_interval = {std::chrono::milliseconds(500), [this](auto) { + this->UpdateScale(); + }}; + void OnRealtimeTick(uint delta_ms) override { this->SetDirty(); - - if (this->next_scale_update.Elapsed(delta_ms)) { - this->next_scale_update.SetInterval(500); - this->UpdateScale(); - } } /** Scale and interpolate a value from a source range into a destination range */ diff --git a/src/game/game_gui.cpp b/src/game/game_gui.cpp index fc53f9a43a..0d941d884a 100644 --- a/src/game/game_gui.cpp +++ b/src/game/game_gui.cpp @@ -15,6 +15,8 @@ #include "../network/network.h" #include "../network/network_content.h" #include "../widgets/dropdown_func.h" +#include "../timer/timer.h" +#include "../timer/timer_window.h" #include "game.hpp" #include "game_gui.hpp" @@ -83,7 +85,6 @@ struct GSConfigWindow : public Window { bool clicked_increase; ///< Whether we clicked the increase or decrease button. bool clicked_dropdown; ///< Whether the dropdown is open. bool closing_dropdown; ///< True, if the dropdown list is currently closing. - GUITimer timeout; ///< Timeout for unclicking the button. int clicked_row; ///< The clicked row of settings. Scrollbar *vscroll; ///< Cache of the vertical scrollbar. typedef std::vector VisibleSettingsList; ///< typdef for a vector of script settings @@ -92,8 +93,7 @@ struct GSConfigWindow : public Window { GSConfigWindow() : Window(&_gs_config_desc), clicked_button(-1), clicked_dropdown(false), - closing_dropdown(false), - timeout(0) + closing_dropdown(false) { this->gs_config = GameConfig::GetConfig(); @@ -336,7 +336,7 @@ struct GSConfigWindow : public Window { if (new_val != old_val) { this->gs_config->SetSetting(config_item.name, new_val); this->clicked_button = num; - this->timeout.SetInterval(150); + this->unclick_timeout.Reset(); } } else if (!bool_item && !config_item.complete_labels) { /* Display a query box so users can enter a custom value. */ @@ -387,13 +387,11 @@ struct GSConfigWindow : public Window { this->vscroll->SetCapacityFromWidget(this, WID_GSC_SETTINGS); } - void OnRealtimeTick(uint delta_ms) override - { - if (this->timeout.Elapsed(delta_ms)) { - this->clicked_button = -1; - this->SetDirty(); - } - } + /** When reset, unclick the button after a small timeout. */ + TimeoutTimer unclick_timeout = {std::chrono::milliseconds(150), [this]() { + this->clicked_button = -1; + this->SetDirty(); + }}; /** * Some data on this window has become invalid. diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index edc9b88d05..5ac49097bf 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -20,6 +20,8 @@ #include "gfx_func.h" #include "core/geometry_func.hpp" #include "currency.h" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "zoom_func.h" #include "widgets/graph_widget.h" @@ -892,7 +894,7 @@ struct PaymentRatesGraphWindow : BaseGraphWindow { this->vscroll->SetCount(static_cast(_sorted_standard_cargo_specs.size())); /* Initialise the dataset */ - this->OnHundredthTick(); + this->UpdatePaymentRates(); this->FinishInitNested(window_number); } @@ -1030,10 +1032,18 @@ struct PaymentRatesGraphWindow : BaseGraphWindow { void OnInvalidateData(int data = 0, bool gui_scope = true) override { if (!gui_scope) return; - this->OnHundredthTick(); + this->UpdatePaymentRates(); } - void OnHundredthTick() override + /** Update the payment rates on a regular interval. */ + IntervalTimer update_payment_interval = {std::chrono::seconds(3), [this](auto) { + this->UpdatePaymentRates(); + }}; + + /** + * Update the payment rates according to the latest information. + */ + void UpdatePaymentRates() { this->UpdateExcludedData(); diff --git a/src/guitimer_func.h b/src/guitimer_func.h deleted file mode 100644 index f37bd5dbbc..0000000000 --- a/src/guitimer_func.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/** @file guitimer_func.h GUI Timers. */ - -#ifndef GUITIMER_FUNC_H -#define GUITIMER_FUNC_H - -class GUITimer -{ -protected: - uint timer; - uint interval; - -public: - GUITimer() : timer(0), interval(0) { } - explicit GUITimer(uint interval) : timer(0), interval(interval) { } - - inline bool HasElapsed() const - { - return this->interval == 0; - } - - inline void SetInterval(uint interval) - { - this->timer = 0; - this->interval = interval; - } - - /** - * Count how many times the interval has elapsed. - * Use to ensure a specific amount of events happen within a timeframe, e.g. for animation. - * @param delta Time since last test. - * @return Number of times the interval has elapsed. - */ - inline uint CountElapsed(uint delta) - { - if (this->interval == 0) return 0; - uint count = delta / this->interval; - if (this->timer + (delta % this->interval) >= this->interval) count++; - this->timer = (this->timer + delta) % this->interval; - return count; - } - - /** - * Test if a timer has elapsed. - * Use to ensure an event happens only once within a timeframe, e.g. for window updates. - * @param delta Time since last test. - * @return True iff the timer has elapsed. - */ - inline bool Elapsed(uint delta) - { - if (this->CountElapsed(delta) == 0) return false; - this->SetInterval(0); - return true; - } -}; - -#endif /* GUITIMER_FUNC_H */ diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index b1aa3dc4e1..1773012568 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -42,6 +42,8 @@ #include "industry_cmd.h" #include "querystring_gui.h" #include "stringfilter_type.h" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "table/strings.h" @@ -723,8 +725,7 @@ public: if (success && !_settings_client.gui.persistent_buildingtools) ResetObjectToPlace(); } - void OnHundredthTick() override - { + IntervalTimer update_interval = {std::chrono::seconds(3), [this](auto) { if (_game_mode == GM_EDITOR) return; if (this->count == 0) return; const IndustrySpec *indsp = GetIndustrySpec(this->selected_type); @@ -739,7 +740,7 @@ public: this->SetDirty(); } } - } + }}; void OnTimeout() override { @@ -1820,11 +1821,11 @@ public: this->DrawWidgets(); } - void OnHundredthTick() override - { + /** Rebuild the industry list on a regular interval. */ + IntervalTimer rebuild_interval = {std::chrono::seconds(3), [this](auto) { this->industries.ForceResort(); this->BuildSortIndustriesList(); - } + }}; /** * Some data on this window has become invalid. diff --git a/src/main_gui.cpp b/src/main_gui.cpp index bdecd07ba5..fd6c0c1054 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -30,10 +30,11 @@ #include "linkgraph/linkgraph_gui.h" #include "tilehighlight_func.h" #include "hotkeys.h" -#include "guitimer_func.h" #include "error.h" #include "news_gui.h" #include "misc_cmd.h" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "saveload/saveload.h" @@ -209,12 +210,6 @@ enum { struct MainWindow : Window { - GUITimer refresh; - - /* Refresh times in milliseconds */ - static const uint LINKGRAPH_REFRESH_PERIOD = 7650; - static const uint LINKGRAPH_DELAY = 450; - MainWindow(WindowDesc *desc) : Window(desc) { this->InitNested(0); @@ -225,15 +220,12 @@ struct MainWindow : Window nvp->InitializeViewport(this, TileXY(32, 32), ScaleZoomGUI(ZOOM_LVL_VIEWPORT)); this->viewport->overlay = std::make_shared(this, WID_M_VIEWPORT, 0, 0, 2); - this->refresh.SetInterval(LINKGRAPH_DELAY); + this->refresh_timeout.Reset(); } - void OnRealtimeTick(uint delta_ms) override + /** Refresh the link-graph overlay. */ + void RefreshLinkGraph() { - if (!this->refresh.Elapsed(delta_ms)) return; - - this->refresh.SetInterval(LINKGRAPH_REFRESH_PERIOD); - if (this->viewport->overlay->GetCargoMask() == 0 || this->viewport->overlay->GetCompanyMask() == 0) { return; @@ -243,6 +235,22 @@ struct MainWindow : Window this->GetWidget(WID_M_VIEWPORT)->SetDirty(this); } + /** Refresh the link-graph overlay on a regular interval. */ + IntervalTimer refresh_interval = {std::chrono::milliseconds(7650), [this](auto) { + RefreshLinkGraph(); + }}; + + /** + * Sometimes when something happened, force an update to the link-graph a bit sooner. + * + * We don't do it instantly on those changes, as for example when you are scrolling, + * constantly refreshing the link-graph would be very slow. So we delay it a bit, + * and only draw it once the scrolling settles down. + */ + TimeoutTimer refresh_timeout = {std::chrono::milliseconds(450), [this]() { + RefreshLinkGraph(); + }}; + void OnPaint() override { this->DrawWidgets(); @@ -416,7 +424,7 @@ struct MainWindow : Window this->viewport->scrollpos_y += ScaleByZoom(delta.y, this->viewport->zoom); this->viewport->dest_scrollpos_x = this->viewport->scrollpos_x; this->viewport->dest_scrollpos_y = this->viewport->scrollpos_y; - this->refresh.SetInterval(LINKGRAPH_DELAY); + this->refresh_timeout.Reset(); } void OnMouseWheel(int wheel) override @@ -431,7 +439,7 @@ struct MainWindow : Window if (this->viewport != nullptr) { NWidgetViewport *nvp = this->GetWidget(WID_M_VIEWPORT); nvp->UpdateViewportCoordinates(this); - this->refresh.SetInterval(LINKGRAPH_DELAY); + this->refresh_timeout.Reset(); } } diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index f7567d0ed1..51541623fe 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -24,10 +24,11 @@ #include "core/geometry_func.hpp" #include "newgrf_debug.h" #include "zoom_func.h" -#include "guitimer_func.h" #include "viewport_func.h" #include "landscape_cmd.h" #include "rev.h" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "widgets/misc_widget.h" @@ -470,9 +471,6 @@ struct AboutWindow : public Window { int line_height; ///< The height of a single line static const int num_visible_lines = 19; ///< The number of lines visible simultaneously - static const uint TIMER_INTERVAL = 2100; ///< Scrolling interval, scaled by line text line height. This value chosen to maintain parity: 2100 / FONT_HEIGHT_NORMAL = 150ms - GUITimer timer; - AboutWindow() : Window(&_about_desc) { this->InitNested(WN_GAME_OPTIONS_ABOUT); @@ -500,10 +498,6 @@ struct AboutWindow : public Window { d.width = std::max(d.width, GetStringBoundingBox(_credits[i]).width); } *size = maxdim(*size, d); - - /* Set scroll interval based on required speed. To keep scrolling smooth, - * the interval is adjusted rather than the distance moved. */ - this->timer.SetInterval(TIMER_INTERVAL / FONT_HEIGHT_NORMAL); } void DrawWidget(const Rect &r, int widget) const override @@ -521,18 +515,19 @@ struct AboutWindow : public Window { } } - void OnRealtimeTick(uint delta_ms) override - { - uint count = this->timer.CountElapsed(delta_ms); - if (count > 0) { - this->text_position -= count; - /* If the last text has scrolled start a new from the start */ - if (this->text_position < (int)(this->GetWidget(WID_A_SCROLLING_TEXT)->pos_y - lengthof(_credits) * this->line_height)) { - this->text_position = this->GetWidget(WID_A_SCROLLING_TEXT)->pos_y + this->GetWidget(WID_A_SCROLLING_TEXT)->current_y; - } - this->SetWidgetDirty(WID_A_SCROLLING_TEXT); + /** + * Scroll the text in the about window slow. + * + * The interval of 2100ms is chosen to maintain parity: 2100 / FONT_HEIGHT_NORMAL = 150ms. + */ + IntervalTimer scroll_interval = {std::chrono::milliseconds(2100) / FONT_HEIGHT_NORMAL, [this](uint count) { + this->text_position -= count; + /* If the last text has scrolled start a new from the start */ + if (this->text_position < (int)(this->GetWidget(WID_A_SCROLLING_TEXT)->pos_y - lengthof(_credits) * this->line_height)) { + this->text_position = this->GetWidget(WID_A_SCROLLING_TEXT)->pos_y + this->GetWidget(WID_A_SCROLLING_TEXT)->current_y; } - } + this->SetWidgetDirty(WID_A_SCROLLING_TEXT); + }}; }; void ShowAboutWindow() diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp index ffea399e29..2ed59e9a52 100644 --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -18,6 +18,8 @@ #include "../toolbar_gui.h" #include "../core/geometry_func.hpp" #include "../zoom_func.h" +#include "../timer/timer.h" +#include "../timer/timer_window.h" #include "network.h" #include "network_client.h" #include "network_base.h" @@ -170,9 +172,8 @@ void NetworkUndrawChatMessage() } } -/** Check if a message is expired. */ -void NetworkChatMessageLoop() -{ +/** Check if a message is expired on a regular interval. */ +static IntervalTimer network_message_expired_interval(std::chrono::seconds(1), [](auto) { auto now = std::chrono::steady_clock::now(); for (auto &cmsg : _chatmsg_list) { /* Message has expired, remove from the list */ @@ -182,7 +183,7 @@ void NetworkChatMessageLoop() break; } } -} +}); /** Draw the chat message-box */ void NetworkDrawChatMessage() diff --git a/src/network/network_func.h b/src/network/network_func.h index 63d3d0cdc0..618adc1949 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -89,7 +89,6 @@ void NetworkInitChatMessage(); void NetworkReInitChatBoxSize(); void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const std::string &message); void NetworkUndrawChatMessage(); -void NetworkChatMessageLoop(); void NetworkAfterNewGRFScan(); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index cf79efea32..c2a0b8027f 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -32,11 +32,12 @@ #include "../core/geometry_func.hpp" #include "../genworld.h" #include "../map_type.h" -#include "../guitimer_func.h" #include "../zoom_func.h" #include "../sprite.h" #include "../settings_internal.h" #include "../company_cmd.h" +#include "../timer/timer.h" +#include "../timer/timer_window.h" #include "../widgets/network_widget.h" @@ -55,8 +56,6 @@ static void ShowNetworkStartServerWindow(); -static const int NETWORK_LIST_REFRESH_DELAY = 30; ///< Time, in seconds, between updates of the network list. - static ClientID _admin_client_id = INVALID_CLIENT_ID; ///< For what client a confirmation window is open. static CompanyID _admin_company_id = INVALID_COMPANY; ///< For what company a confirmation window is open. @@ -229,7 +228,6 @@ protected: Scrollbar *vscroll; ///< Vertical scrollbar of the list of servers. QueryString name_editbox; ///< Client name editbox. QueryString filter_editbox; ///< Editbox for filter on servers. - GUITimer requery_timer; ///< Timer for network requery. bool searched_internet = false; ///< Did we ever press "Search Internet" button? int lock_offset; ///< Left offset for lock icon. @@ -499,8 +497,6 @@ public: this->last_joined = NetworkAddServer(_settings_client.network.last_joined, false); this->server = this->last_joined; - this->requery_timer.SetInterval(NETWORK_LIST_REFRESH_DELAY * 1000); - this->servers.SetListing(this->last_sorting); this->servers.SetSortFuncs(this->sorter_funcs); this->servers.SetFilterFuncs(this->filter_funcs); @@ -891,14 +887,12 @@ public: this->vscroll->SetCapacityFromWidget(this, WID_NG_MATRIX); } - void OnRealtimeTick(uint delta_ms) override - { + /** Refresh the online servers on a regular interval. */ + IntervalTimer refresh_interval = {std::chrono::seconds(30), [this](uint count) { if (!this->searched_internet) return; - if (!this->requery_timer.Elapsed(delta_ms)) return; - this->requery_timer.SetInterval(NETWORK_LIST_REFRESH_DELAY * 1000); _network_coordinator_client.GetListing(); - } + }}; }; Listing NetworkGameWindow::last_sorting = {false, 5}; diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index 23f8816ec1..991c9f3e23 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -28,7 +28,8 @@ #include "textfile_gui.h" #include "tilehighlight_func.h" #include "fios.h" -#include "guitimer_func.h" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "widgets/newgrf_widget.h" #include "widgets/misc_widget.h" @@ -155,7 +156,6 @@ struct NewGRFParametersWindow : public Window { bool clicked_increase; ///< True if the increase button was clicked, false for the decrease button. bool clicked_dropdown; ///< Whether the dropdown is open. bool closing_dropdown; ///< True, if the dropdown list is currently closing. - GUITimer timeout; ///< How long before we unpress the last-pressed button? uint clicked_row; ///< The selected parameter int line_height; ///< Height of a row in the matrix widget. Scrollbar *vscroll; @@ -404,7 +404,7 @@ struct NewGRFParametersWindow : public Window { par_info->SetValue(this->grf_config, val); this->clicked_button = num; - this->timeout.SetInterval(150); + this->unclick_timeout.Reset(); } } else if (par_info->type == PTYPE_UINT_ENUM && !par_info->complete_labels && click_count >= 2) { /* Display a query box so users can enter a custom value. */ @@ -484,13 +484,11 @@ struct NewGRFParametersWindow : public Window { } } - void OnRealtimeTick(uint delta_ms) override - { - if (timeout.Elapsed(delta_ms)) { - this->clicked_button = UINT_MAX; - this->SetDirty(); - } - } + /** When reset, unclick the button after a small timeout. */ + TimeoutTimer unclick_timeout = {std::chrono::milliseconds(150), [this]() { + this->clicked_button = UINT_MAX; + this->SetDirty(); + }}; }; GRFParameterInfo NewGRFParametersWindow::dummy_parameter_info(0); diff --git a/src/news_gui.cpp b/src/news_gui.cpp index ab3bfadb92..841c0db352 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -32,10 +32,11 @@ #include "command_func.h" #include "company_base.h" #include "settings_internal.h" -#include "guitimer_func.h" #include "group_gui.h" #include "zoom_func.h" #include "news_cmd.h" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "widgets/news_widget.h" @@ -267,9 +268,6 @@ struct NewsWindow : Window { const NewsItem *ni; ///< News item to display. static int duration; ///< Remaining time for showing the current news message (may only be access while a news item is displayed). - static const uint TIMER_INTERVAL = 210; ///< Scrolling interval, scaled by line text line height. This value chosen to maintain the 15ms at normal zoom. - GUITimer timer; - NewsWindow(WindowDesc *desc, const NewsItem *ni) : Window(desc), ni(ni) { NewsWindow::duration = 16650; @@ -322,11 +320,6 @@ struct NewsWindow : Window { PositionNewsMessage(this); } - void OnInit() override - { - this->timer.SetInterval(TIMER_INTERVAL / FONT_HEIGHT_NORMAL); - } - void DrawNewsBorder(const Rect &r) const { Rect ir = r.Shrink(WidgetDimensions::scaled.bevel); @@ -554,18 +547,21 @@ struct NewsWindow : Window { void OnRealtimeTick(uint delta_ms) override { - int count = this->timer.CountElapsed(delta_ms); - if (count > 0) { - /* Scroll up newsmessages from the bottom */ - int newtop = std::max(this->top - 2 * count, _screen.height - this->height - this->status_height - this->chat_height); - this->SetWindowTop(newtop); - } - /* Decrement the news timer. We don't need to action an elapsed event here, * so no need to use TimerElapsed(). */ if (NewsWindow::duration > 0) NewsWindow::duration -= delta_ms; } + /** + * Scroll the news message slowly up from the bottom. + * + * The interval of 210ms is chosen to maintain 15ms at normal zoom: 210 / FONT_HEIGHT_NORMAL = 15ms. + */ + IntervalTimer scroll_interval = {std::chrono::milliseconds(210) / FONT_HEIGHT_NORMAL, [this](uint count) { + int newtop = std::max(this->top - 2 * static_cast(count), _screen.height - this->height - this->status_height - this->chat_height); + this->SetWindowTop(newtop); + }}; + private: /** * Moves the window to a new #top coordinate. Makes screen dirty where needed. diff --git a/src/script/script_gui.cpp b/src/script/script_gui.cpp index fd4017c48b..bee329596b 100644 --- a/src/script/script_gui.cpp +++ b/src/script/script_gui.cpp @@ -21,6 +21,8 @@ #include "../hotkeys.h" #include "../company_cmd.h" #include "../misc_cmd.h" +#include "../timer/timer.h" +#include "../timer/timer_window.h" #include "script_gui.h" #include "script_log.hpp" @@ -288,7 +290,6 @@ struct ScriptSettingsWindow : public Window { bool clicked_increase; ///< Whether we clicked the increase or decrease button. bool clicked_dropdown; ///< Whether the dropdown is open. bool closing_dropdown; ///< True, if the dropdown list is currently closing. - GUITimer timeout; ///< Timeout for unclicking the button. int clicked_row; ///< The clicked row of settings. int line_height; ///< Height of a row in the matrix widget. Scrollbar *vscroll; ///< Cache of the vertical scrollbar. @@ -304,8 +305,7 @@ struct ScriptSettingsWindow : public Window { slot(slot), clicked_button(-1), clicked_dropdown(false), - closing_dropdown(false), - timeout(0) + closing_dropdown(false) { this->script_config = GetConfig(slot); @@ -499,7 +499,7 @@ struct ScriptSettingsWindow : public Window { if (new_val != old_val) { this->script_config->SetSetting(config_item.name, new_val); this->clicked_button = num; - this->timeout.SetInterval(150); + this->unclick_timeout.Reset(); } } else if (!bool_item && !config_item.complete_labels) { /* Display a query box so users can enter a custom value. */ @@ -551,13 +551,11 @@ struct ScriptSettingsWindow : public Window { this->vscroll->SetCapacityFromWidget(this, WID_SCRS_BACKGROUND); } - void OnRealtimeTick(uint delta_ms) override - { - if (this->timeout.Elapsed(delta_ms)) { - this->clicked_button = -1; - this->SetDirty(); - } - } + /** When reset, unclick the button after a small timeout. */ + TimeoutTimer unclick_timeout = {std::chrono::milliseconds(150), [this]() { + this->clicked_button = -1; + this->SetDirty(); + }}; /** * Some data on this window has become invalid. diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp index 911e0c9363..a5c78a6645 100644 --- a/src/signs_gui.cpp +++ b/src/signs_gui.cpp @@ -27,6 +27,8 @@ #include "transparency.h" #include "gui.h" #include "signs_cmd.h" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "widgets/sign_widget.h" @@ -312,11 +314,11 @@ struct SignListWindow : Window, SignList { this->SortSignsList(); } - void OnHundredthTick() override - { + /** Resort the sign listing on a regular interval. */ + IntervalTimer rebuild_interval = {std::chrono::seconds(3), [this](auto) { this->BuildSortSignList(); this->SetDirty(); - } + }}; /** * Some data on this window has become invalid. diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 4e448a05c2..c98fee110a 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -22,7 +22,6 @@ #include "sound_func.h" #include "window_func.h" #include "company_base.h" -#include "guitimer_func.h" #include "zoom_func.h" #include "smallmap_gui.h" @@ -1072,7 +1071,7 @@ void SmallMapWindow::SetupWidgetData() this->GetWidget(WID_SM_SELECT_BUTTONS)->SetDisplayedPlane(plane); } -SmallMapWindow::SmallMapWindow(WindowDesc *desc, int window_number) : Window(desc), refresh(GUITimer(FORCE_REFRESH_PERIOD)) +SmallMapWindow::SmallMapWindow(WindowDesc *desc, int window_number) : Window(desc) { _smallmap_industry_highlight = INVALID_INDUSTRYTYPE; this->overlay = new LinkGraphOverlay(this, WID_SM_MAP, 0, this->GetOverlayCompanyMask(), 1); @@ -1416,7 +1415,6 @@ int SmallMapWindow::GetPositionOnLegend(Point pt) } if (new_highlight != _smallmap_industry_highlight) { _smallmap_industry_highlight = new_highlight; - this->refresh.SetInterval(_smallmap_industry_highlight != INVALID_INDUSTRYTYPE ? BLINK_PERIOD : FORCE_REFRESH_PERIOD); _smallmap_industry_highlight_state = true; this->SetDirty(); } @@ -1588,11 +1586,9 @@ int SmallMapWindow::GetPositionOnLegend(Point pt) } } -/* virtual */ void SmallMapWindow::OnRealtimeTick(uint delta_ms) +/** Update all the links on the map. */ +void SmallMapWindow::UpdateLinks() { - /* Update the window every now and then */ - if (!this->refresh.Elapsed(delta_ms)) return; - if (this->map_type == SMT_LINKSTATS) { CompanyMask company_mask = this->GetOverlayCompanyMask(); if (this->overlay->GetCompanyMask() != company_mask) { @@ -1601,9 +1597,25 @@ int SmallMapWindow::GetPositionOnLegend(Point pt) this->overlay->SetDirty(); } } +} + +/** Blink the industries (if hover over an industry). */ +void SmallMapWindow::Blink() +{ + if (_smallmap_industry_highlight == INVALID_INDUSTRYTYPE) return; + _smallmap_industry_highlight_state = !_smallmap_industry_highlight_state; - this->refresh.SetInterval(_smallmap_industry_highlight != INVALID_INDUSTRYTYPE ? BLINK_PERIOD : FORCE_REFRESH_PERIOD); + this->UpdateLinks(); + this->SetDirty(); +} + +/** Force a full refresh of the map. */ +void SmallMapWindow::ForceRefresh() +{ + if (_smallmap_industry_highlight != INVALID_INDUSTRYTYPE) return; + + this->UpdateLinks(); this->SetDirty(); } diff --git a/src/smallmap_gui.h b/src/smallmap_gui.h index 774a42a841..11a08b83a4 100644 --- a/src/smallmap_gui.h +++ b/src/smallmap_gui.h @@ -17,7 +17,8 @@ #include "blitter/factory.hpp" #include "linkgraph/linkgraph_gui.h" #include "widgets/smallmap_widget.h" -#include "guitimer_func.h" +#include "timer/timer.h" +#include "timer/timer_window.h" /* set up the cargos to be displayed in the smallmap's route legend */ void BuildLinkStatsLegend(); @@ -74,8 +75,6 @@ protected: static int map_height_limit; ///< Currently used/cached map height limit. static const uint INDUSTRY_MIN_NUMBER_OF_COLUMNS = 2; ///< Minimal number of columns in the #WID_SM_LEGEND widget for the #SMT_INDUSTRY legend. - static const uint FORCE_REFRESH_PERIOD = 930; ///< map is redrawn after that many milliseconds. - static const uint BLINK_PERIOD = 450; ///< highlight blinking interval in milliseconds. uint min_number_of_columns; ///< Minimal number of columns in legends. uint min_number_of_fixed_rows; ///< Minimal number of rows in the legends for the fixed layouts only (all except #SMT_INDUSTRY). @@ -87,7 +86,6 @@ protected: int32 subscroll; ///< Number of pixels (0..3) between the right end of the base tile and the pixel at the top-left corner of the smallmap display. int zoom; ///< Zoom level. Bigger number means more zoom-out (further away). - GUITimer refresh; ///< Refresh timer. LinkGraphOverlay *overlay; static void BreakIndustryChainLink(); @@ -156,6 +154,16 @@ protected: return Company::IsValidID(_local_company) ? 1U << _local_company : MAX_UVALUE(CompanyMask); } + /** Blink the industries (if selected) on a regular interval. */ + IntervalTimer blink_interval = {std::chrono::milliseconds(450), [this](auto) { + Blink(); + }}; + + /** Update the whole map on a regular interval. */ + IntervalTimer refresh_interval = {std::chrono::milliseconds(930), [this](auto) { + ForceRefresh(); + }}; + void RebuildColourIndexIfNecessary(); uint GetNumberRowsLegend(uint columns) const; void SelectLegendItem(int click_pos, LegendAndColour *legend, int end_legend_item, int begin_legend_item = 0); @@ -178,6 +186,10 @@ protected: int GetPositionOnLegend(Point pt); + void UpdateLinks(); + void Blink(); + void ForceRefresh(); + public: friend class NWidgetSmallmapDisplay; @@ -196,7 +208,6 @@ public: void OnInvalidateData(int data = 0, bool gui_scope = true) override; bool OnRightClick(Point pt, int widget) override; void OnMouseWheel(int wheel) override; - void OnRealtimeTick(uint delta_ms) override; void OnScroll(Point delta) override; void OnMouseOver(Point pt, int widget) override; }; diff --git a/src/statusbar_gui.cpp b/src/statusbar_gui.cpp index 69a71b75f7..021025ddaa 100644 --- a/src/statusbar_gui.cpp +++ b/src/statusbar_gui.cpp @@ -25,8 +25,9 @@ #include "statusbar_gui.h" #include "toolbar_gui.h" #include "core/geometry_func.hpp" -#include "guitimer_func.h" #include "zoom_func.h" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "widgets/statusbar_widget.h" @@ -78,19 +79,14 @@ static bool DrawScrollingStatusText(const NewsItem *ni, int scroll_pos, int left struct StatusBarWindow : Window { bool saving; int ticker_scroll; - GUITimer ticker_timer; - GUITimer reminder_timeout; static const int TICKER_STOP = 1640; ///< scrolling is finished when counter reaches this value - static const int REMINDER_START = 1350; ///< time in ms for reminder notification (red dot on the right) to stay - static const int REMINDER_STOP = 0; ///< reminder disappears when counter reaches this value static const int COUNTER_STEP = 2; ///< this is subtracted from active counters every tick + static constexpr auto REMINDER_START = std::chrono::milliseconds(1350); ///< time in ms for reminder notification (red dot on the right) to stay StatusBarWindow(WindowDesc *desc) : Window(desc) { this->ticker_scroll = TICKER_STOP; - this->ticker_timer.SetInterval(15); - this->reminder_timeout.SetInterval(REMINDER_STOP); this->InitNested(); CLRBITS(this->flags, WF_WHITE_BORDER); @@ -186,7 +182,7 @@ struct StatusBarWindow : Window { } } - if (!this->reminder_timeout.HasElapsed()) { + if (!this->reminder_timeout.HasFired()) { Dimension icon_size = GetSpriteSize(SPR_UNREAD_NEWS); DrawSprite(SPR_UNREAD_NEWS, PAL_NONE, tr.right - icon_size.width, CenterBounds(r.top, r.bottom, icon_size.height)); } @@ -207,10 +203,10 @@ struct StatusBarWindow : Window { case SBI_SAVELOAD_START: this->saving = true; break; case SBI_SAVELOAD_FINISH: this->saving = false; break; case SBI_SHOW_TICKER: this->ticker_scroll = 0; break; - case SBI_SHOW_REMINDER: this->reminder_timeout.SetInterval(REMINDER_START); break; + case SBI_SHOW_REMINDER: this->reminder_timeout.Reset(); break; case SBI_NEWS_DELETED: this->ticker_scroll = TICKER_STOP; // reset ticker ... - this->reminder_timeout.SetInterval(REMINDER_STOP); // ... and reminder + this->reminder_timeout.Abort(); // ... and reminder break; } } @@ -224,23 +220,19 @@ struct StatusBarWindow : Window { } } - void OnRealtimeTick(uint delta_ms) override - { + /** Move information on the ticker slowly from one side to the other. */ + IntervalTimer ticker_scroll_interval = {std::chrono::milliseconds(15), [this](uint count) { if (_pause_mode != PM_UNPAUSED) return; - if (this->ticker_scroll < TICKER_STOP) { // Scrolling text - uint count = this->ticker_timer.CountElapsed(delta_ms); - if (count > 0) { - this->ticker_scroll += count; - this->SetWidgetDirty(WID_S_MIDDLE); - } - } - - // Red blot to show there are new unread newsmessages - if (this->reminder_timeout.Elapsed(delta_ms)) { + if (this->ticker_scroll < TICKER_STOP) { + this->ticker_scroll += count; this->SetWidgetDirty(WID_S_MIDDLE); } - } + }}; + + TimeoutTimer reminder_timeout = {REMINDER_START, [this]() { + this->SetWidgetDirty(WID_S_MIDDLE); + }}; }; static const NWidgetPart _nested_main_status_widgets[] = { diff --git a/src/texteff.cpp b/src/texteff.cpp index 1c4722ae61..3235b8720d 100644 --- a/src/texteff.cpp +++ b/src/texteff.cpp @@ -14,7 +14,9 @@ #include "core/smallvec_type.hpp" #include "viewport_func.h" #include "settings_type.h" -#include "guitimer_func.h" +#include "command_type.h" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "safeguards.h" @@ -91,11 +93,9 @@ void RemoveTextEffect(TextEffectID te_id) _text_effects[te_id].Reset(); } -void MoveAllTextEffects(uint delta_ms) -{ - static GUITimer texteffecttimer = GUITimer(MILLISECONDS_PER_TICK); - uint count = texteffecttimer.CountElapsed(delta_ms); - if (count == 0) return; +/** Slowly move text effects upwards. */ +IntervalTimer move_all_text_effects_interval = {std::chrono::milliseconds(30), [](uint count) { + if (_pause_mode && _game_mode != GM_EDITOR && _settings_game.construction.command_pause_level <= CMDPL_NO_CONSTRUCTION) return; for (TextEffect &te : _text_effects) { if (te.string_id == INVALID_STRING_ID) continue; @@ -111,7 +111,7 @@ void MoveAllTextEffects(uint delta_ms) te.top -= count * ZOOM_LVL_BASE; te.MarkDirty(ZOOM_LVL_OUT_8X); } -} +}}; void InitTextEffects() { diff --git a/src/texteff.hpp b/src/texteff.hpp index 56b5933926..f684c3d955 100644 --- a/src/texteff.hpp +++ b/src/texteff.hpp @@ -26,7 +26,6 @@ enum TextEffectMode { typedef size_t TextEffectID; -void MoveAllTextEffects(uint delta_ms); TextEffectID AddTextEffect(StringID msg, int x, int y, uint8 duration, TextEffectMode mode); void InitTextEffects(); void DrawTextEffects(DrawPixelInfo *dpi); diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index b00a8154c2..157a09b59e 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -49,11 +49,12 @@ #include "story_base.h" #include "toolbar_gui.h" #include "framerate_type.h" -#include "guitimer_func.h" #include "screenshot_gui.h" #include "misc_cmd.h" #include "league_gui.h" #include "league_base.h" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "widgets/toolbar_widget.h" @@ -1992,8 +1993,6 @@ static ToolbarButtonProc * const _toolbar_button_procs[] = { /** Main toolbar. */ struct MainToolbarWindow : Window { - GUITimer timer; - MainToolbarWindow(WindowDesc *desc) : Window(desc) { this->InitNested(0); @@ -2004,8 +2003,6 @@ struct MainToolbarWindow : Window { this->SetWidgetDisabledState(WID_TN_FAST_FORWARD, _networking); // if networking, disable fast-forward button PositionMainToolbar(this); DoZoomInOutWindow(ZOOM_NONE, this); - - this->timer.SetInterval(MILLISECONDS_PER_TICK); } void FindWindowPlacementAndResize(int def_width, int def_height) override @@ -2109,11 +2106,8 @@ struct MainToolbarWindow : Window { _last_started_action = CBF_NONE; } - void OnRealtimeTick(uint delta_ms) override - { - if (!this->timer.Elapsed(delta_ms)) return; - this->timer.SetInterval(MILLISECONDS_PER_TICK); - + /** Refresh the state of pause / game-speed on a regular interval.*/ + IntervalTimer refresh_interval = {std::chrono::milliseconds(30), [this](auto) { if (this->IsWidgetLowered(WID_TN_PAUSE) != !!_pause_mode) { this->ToggleWidgetLoweredState(WID_TN_PAUSE); this->SetWidgetDirty(WID_TN_PAUSE); @@ -2123,7 +2117,7 @@ struct MainToolbarWindow : Window { this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD); this->SetWidgetDirty(WID_TN_FAST_FORWARD); } - } + }}; void OnTimeout() override { @@ -2353,8 +2347,6 @@ enum MainToolbarEditorHotkeys { }; struct ScenarioEditorToolbarWindow : Window { - GUITimer timer; - ScenarioEditorToolbarWindow(WindowDesc *desc) : Window(desc) { this->InitNested(0); @@ -2363,8 +2355,6 @@ struct ScenarioEditorToolbarWindow : Window { CLRBITS(this->flags, WF_WHITE_BORDER); PositionMainToolbar(this); DoZoomInOutWindow(ZOOM_NONE, this); - - this->timer.SetInterval(MILLISECONDS_PER_TICK); } void FindWindowPlacementAndResize(int def_width, int def_height) override @@ -2495,11 +2485,8 @@ struct ScenarioEditorToolbarWindow : Window { this->SetWidgetDirty(WID_TE_DATE_FORWARD); } - void OnRealtimeTick(uint delta_ms) override - { - if (!this->timer.Elapsed(delta_ms)) return; - this->timer.SetInterval(MILLISECONDS_PER_TICK); - + /** Refresh the state of pause / game-speed on a regular interval.*/ + IntervalTimer refresh_interval = {std::chrono::milliseconds(30), [this](auto) { if (this->IsWidgetLowered(WID_TE_PAUSE) != !!_pause_mode) { this->ToggleWidgetLoweredState(WID_TE_PAUSE); this->SetDirty(); @@ -2509,7 +2496,7 @@ struct ScenarioEditorToolbarWindow : Window { this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD); this->SetDirty(); } - } + }}; /** * Some data on this window has become invalid. diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 9076b0b56d..c655fdb3a2 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -34,6 +34,8 @@ #include "widgets/dropdown_func.h" #include "town_kdtree.h" #include "town_cmd.h" +#include "timer/timer.h" +#include "timer/timer_window.h" #include "widgets/town_widget.h" @@ -307,10 +309,10 @@ public: } } - void OnHundredthTick() override - { + /** Redraw the whole window on a regular interval. */ + IntervalTimer redraw_interval = {std::chrono::seconds(3), [this](auto) { this->SetDirty(); - } + }}; void OnInvalidateData(int data = 0, bool gui_scope = true) override { @@ -966,11 +968,11 @@ public: this->DrawWidgets(); } - void OnHundredthTick() override - { + /** Redraw the whole window on a regular interval. */ + IntervalTimer rebuild_interval = {std::chrono::seconds(3), [this](auto) { this->BuildSortTownList(); this->SetDirty(); - } + }}; void OnResize() override { diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index d036f3f694..a217e8a850 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -12,8 +12,9 @@ #include "../string_func.h" #include "../strings_func.h" #include "../window_func.h" -#include "../guitimer_func.h" #include "../zoom_func.h" +#include "../timer/timer.h" +#include "../timer/timer_window.h" #include "dropdown_type.h" #include "dropdown_widget.h" @@ -126,7 +127,6 @@ struct DropdownWindow : Window { bool drag_mode; bool instant_close; ///< Close the window when the mouse button is raised. int scrolling; ///< If non-zero, auto-scroll the item list (one time). - GUITimer scrolling_timer; ///< Timer for auto-scroll of the item list. Point position; ///< Position of the topleft corner of the window. Scrollbar *vscroll; @@ -183,7 +183,6 @@ struct DropdownWindow : Window { this->click_delay = 0; this->drag_mode = true; this->instant_close = instant_close; - this->scrolling_timer = GUITimer(MILLISECONDS_PER_TICK); } void Close() override @@ -278,22 +277,19 @@ struct DropdownWindow : Window { } } - void OnRealtimeTick(uint delta_ms) override - { - if (!this->scrolling_timer.Elapsed(delta_ms)) return; - this->scrolling_timer.SetInterval(MILLISECONDS_PER_TICK); + /** Rate limit how fast scrolling happens. */ + IntervalTimer scroll_interval = {std::chrono::milliseconds(30), [this](auto) { + if (this->scrolling == 0) return; - if (this->scrolling != 0) { - int pos = this->vscroll->GetPosition(); + int pos = this->vscroll->GetPosition(); - this->vscroll->UpdatePosition(this->scrolling); - this->scrolling = 0; + this->vscroll->UpdatePosition(this->scrolling); + this->scrolling = 0; - if (pos != this->vscroll->GetPosition()) { - this->SetDirty(); - } + if (pos != this->vscroll->GetPosition()) { + this->SetDirty(); } - } + }}; void OnMouseLoop() override { diff --git a/src/window.cpp b/src/window.cpp index e7db416316..e8bbfbf5d6 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -37,7 +37,6 @@ #include "video/video_driver.hpp" #include "framerate_type.h" #include "network/network_func.h" -#include "guitimer_func.h" #include "news_func.h" #include "timer/timer.h" #include "timer/timer_window.h" @@ -1888,14 +1887,9 @@ void ResetWindowSystem() static void DecreaseWindowCounters() { - static byte hundredth_tick_timeout = 100; - if (_scroller_click_timeout != 0) _scroller_click_timeout--; - if (hundredth_tick_timeout != 0) hundredth_tick_timeout--; for (Window *w : Window::Iterate()) { - if (!_network_dedicated && hundredth_tick_timeout == 0) w->OnHundredthTick(); - if (_scroller_click_timeout == 0) { /* Unclick scrollbar buttons if they are pressed. */ for (uint i = 0; i < w->nested_array_size; i++) { @@ -1927,8 +1921,6 @@ static void DecreaseWindowCounters() w->RaiseButtons(true); } } - - if (hundredth_tick_timeout == 0) hundredth_tick_timeout = 100; } static void HandlePlacePresize() @@ -3111,20 +3103,21 @@ static IntervalTimer white_border_interval(std::chrono::millisecond */ void UpdateWindows() { - static std::chrono::steady_clock::time_point last_time = std::chrono::steady_clock::now(); - uint delta_ms = std::chrono::duration_cast(std::chrono::steady_clock::now() - last_time).count(); + static auto last_time = std::chrono::steady_clock::now(); + auto now = std::chrono::steady_clock::now(); + auto delta_ms = std::chrono::duration_cast(now - last_time); - if (delta_ms == 0) return; + if (delta_ms.count() == 0) return; - last_time = std::chrono::steady_clock::now(); + last_time = now; PerformanceMeasurer framerate(PFE_DRAWING); PerformanceAccumulator::Reset(PFE_DRAWWORLD); ProcessPendingPerformanceMeasurements(); - TimerManager::Elapsed(std::chrono::milliseconds(delta_ms)); - CallWindowRealtimeTickEvent(delta_ms); + TimerManager::Elapsed(delta_ms); + CallWindowRealtimeTickEvent(delta_ms.count()); /* Process invalidations before anything else. */ for (Window *w : Window::Iterate()) { @@ -3132,8 +3125,6 @@ void UpdateWindows() w->ProcessHighlightedInvalidations(); } - if (!_pause_mode || _game_mode == GM_EDITOR || _settings_game.construction.command_pause_level > CMDPL_NO_CONSTRUCTION) MoveAllTextEffects(delta_ms); - /* Skip the actual drawing on dedicated servers without screen. * But still empty the invalidation queues above. */ if (_network_dedicated) return; diff --git a/src/window_gui.h b/src/window_gui.h index 00dfd9960a..c9825ab686 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -621,13 +621,6 @@ public: */ virtual void OnGameTick() {} - /** - * Called once every 100 (game) ticks, or once every 3s, whichever comes last. - * In normal game speed the frequency is 1 call every 100 ticks (can be more than 3s). - * In fast-forward the frequency is 1 call every ~3s (can be more than 100 ticks). - */ - virtual void OnHundredthTick() {} - /** * Called periodically. */