Codechange: migrate all Window-related timers to the new framework

This means we also say goodbye to GUITimers.
pull/544/head
Patric Stout 1 year ago committed by Patric Stout
parent 5e1bcee39b
commit 1ba4dcc924

@ -192,7 +192,6 @@ add_files(
group_gui.h group_gui.h
group_type.h group_type.h
gui.h gui.h
guitimer_func.h
heightmap.cpp heightmap.cpp
heightmap.h heightmap.h
highscore.cpp highscore.cpp

@ -42,6 +42,8 @@
#include "group_cmd.h" #include "group_cmd.h"
#include "misc_cmd.h" #include "misc_cmd.h"
#include "object_cmd.h" #include "object_cmd.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "widgets/company_widget.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<TimerWindow> rescale_interval = {std::chrono::seconds(3), [this](auto) {
const Company *c = Company::Get((CompanyID)this->window_number); const Company *c = Company::Get((CompanyID)this->window_number);
if (c->money > CompanyFinancesWindow::max_money) { if (c->money > CompanyFinancesWindow::max_money) {
CompanyFinancesWindow::max_money = std::max(c->money * 2, CompanyFinancesWindow::max_money * 4); CompanyFinancesWindow::max_money = std::max(c->money * 2, CompanyFinancesWindow::max_money * 4);
this->SetupWidgets(); this->SetupWidgets();
this->ReInit(); this->ReInit();
} }
} }};
}; };
/** First conservative estimate of the maximum amount of money */ /** First conservative estimate of the maximum amount of money */
@ -2679,11 +2684,10 @@ struct CompanyWindow : Window
} }
} }
void OnHundredthTick() override /** Redraw the window on a regular interval. */
{ IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(3), [this](auto) {
/* redraw the window every now and then */
this->SetDirty(); this->SetDirty();
} }};
void OnPlaceObject(Point pt, TileIndex tile) override void OnPlaceObject(Point pt, TileIndex tile) override
{ {

@ -12,7 +12,6 @@
#include "window_gui.h" #include "window_gui.h"
#include "console_gui.h" #include "console_gui.h"
#include "console_internal.h" #include "console_internal.h"
#include "guitimer_func.h"
#include "window_func.h" #include "window_func.h"
#include "string_func.h" #include "string_func.h"
#include "strings_func.h" #include "strings_func.h"
@ -21,6 +20,8 @@
#include "console_func.h" #include "console_func.h"
#include "rev.h" #include "rev.h"
#include "video/video_driver.hpp" #include "video/video_driver.hpp"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include <deque> #include <deque>
#include <string> #include <string>
@ -115,14 +116,12 @@ struct IConsoleWindow : Window
static size_t scroll; static size_t scroll;
int line_height; ///< Height of one line of text in the console. int line_height; ///< Height of one line of text in the console.
int line_offset; int line_offset;
GUITimer truncate_timer;
IConsoleWindow() : Window(&_console_window_desc) IConsoleWindow() : Window(&_console_window_desc)
{ {
_iconsole_mode = ICONSOLE_OPENED; _iconsole_mode = ICONSOLE_OPENED;
this->InitNested(0); this->InitNested(0);
this->truncate_timer.SetInterval(3000);
ResizeWindow(this, _screen.width, _screen.height / 3); ResizeWindow(this, _screen.width, _screen.height / 3);
} }
@ -186,10 +185,8 @@ struct IConsoleWindow : Window
} }
} }
void OnRealtimeTick(uint delta_ms) override /** Check on a regular interval if the console buffer needs truncating. */
{ IntervalTimer<TimerWindow> truncate_interval = {std::chrono::seconds(3), [this](auto) {
if (this->truncate_timer.CountElapsed(delta_ms) == 0) return;
assert(this->height >= 0 && this->line_height > 0); assert(this->height >= 0 && this->line_height > 0);
size_t visible_lines = (size_t)(this->height / this->line_height); size_t visible_lines = (size_t)(this->height / this->line_height);
@ -198,7 +195,7 @@ struct IConsoleWindow : Window
IConsoleWindow::scroll = std::min<size_t>(IConsoleWindow::scroll, max_scroll); IConsoleWindow::scroll = std::min<size_t>(IConsoleWindow::scroll, max_scroll);
this->SetDirty(); this->SetDirty();
} }
} }};
void OnMouseLoop() override void OnMouseLoop() override
{ {

@ -15,7 +15,8 @@
#include "company_type.h" #include "company_type.h"
#include "command_type.h" #include "command_type.h"
#include "core/geometry_type.hpp" #include "core/geometry_type.hpp"
#include "guitimer_func.h"
#include <chrono>
struct GRFFile; struct GRFFile;
@ -30,7 +31,7 @@ enum WarningLevel {
/** The data of the error message. */ /** The data of the error message. */
class ErrorMessageData { class ErrorMessageData {
protected: 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. uint64 decode_params[20]; ///< Parameters of the message strings.
const char *strings[20]; ///< Copies of raw strings that were used. 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. const GRFFile *textref_stack_grffile; ///< NewGRF that filled the #TextRefStack for the error message.
@ -45,7 +46,7 @@ protected:
public: public:
ErrorMessageData(const ErrorMessageData &data); ErrorMessageData(const ErrorMessageData &data);
~ErrorMessageData(); ~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. */ /* Remove the copy assignment, as the default implementation will not do the right thing. */
ErrorMessageData &operator=(ErrorMessageData &rhs) = delete; ErrorMessageData &operator=(ErrorMessageData &rhs) = delete;

@ -21,6 +21,8 @@
#include "window_func.h" #include "window_func.h"
#include "console_func.h" #include "console_func.h"
#include "window_gui.h" #include "window_gui.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "widgets/error_widget.h" #include "widgets/error_widget.h"
@ -71,7 +73,7 @@ static WindowDesc _errmsg_face_desc(
* @param data The data to copy. * @param data The data to copy.
*/ */
ErrorMessageData::ErrorMessageData(const ErrorMessageData &data) : 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) 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)); memcpy(this->textref_stack, data.textref_stack, sizeof(this->textref_stack));
@ -95,7 +97,7 @@ ErrorMessageData::~ErrorMessageData()
* Display an error message in a window. * Display an error message in a window.
* @param summary_msg General error message showed in first line. Must be valid. * @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 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 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 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. * @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 textref_stack Values to put on the #TextRefStack.
* @param extra_msg Extra error message showed in third line. Can be INVALID_STRING_ID. * @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_grffile(textref_stack_grffile),
textref_stack_size(textref_stack_size), textref_stack_size(textref_stack_size),
summary_msg(summary_msg), 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); if (textref_stack_size > 0) MemCpyT(this->textref_stack, textref_stack, textref_stack_size);
assert(summary_msg != INVALID_STRING_ID); 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_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_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. uint height_extra; ///< Height of the #extra_msg string in pixels in the #WID_EM_MESSAGE widget.
TimeoutTimer<TimerWindow> display_timeout;
public: 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(); 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 void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
@ -316,14 +328,7 @@ public:
void OnMouseLoop() override void OnMouseLoop() override
{ {
/* Disallow closing the window too easily, if timeout is disabled */ /* Disallow closing the window too easily, if timeout is disabled */
if (_right_button_down && !this->display_timer.HasElapsed()) this->Close(); if (_right_button_down && !this->is_critical) this->Close();
}
void OnRealtimeTick(uint delta_ms) override
{
if (this->display_timer.CountElapsed(delta_ms) == 0) return;
this->Close();
} }
void Close() override void Close() override
@ -339,7 +344,7 @@ public:
*/ */
bool IsCritical() 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); 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 (_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(); data.CopyOutDParams();
ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0); ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0);

@ -17,12 +17,13 @@
#include "strings_func.h" #include "strings_func.h"
#include "console_func.h" #include "console_func.h"
#include "console_type.h" #include "console_type.h"
#include "guitimer_func.h"
#include "company_base.h" #include "company_base.h"
#include "ai/ai_info.hpp" #include "ai/ai_info.hpp"
#include "ai/ai_instance.hpp" #include "ai/ai_instance.hpp"
#include "game/game.hpp" #include "game/game.hpp"
#include "game/game_instance.hpp" #include "game/game_instance.hpp"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "widgets/framerate_widget.h" #include "widgets/framerate_widget.h"
@ -410,7 +411,6 @@ static const NWidgetPart _framerate_window_widgets[] = {
struct FramerateWindow : Window { struct FramerateWindow : Window {
bool small; bool small;
bool showing_memory; bool showing_memory;
GUITimer next_update;
int num_active; int num_active;
int num_displayed; int num_displayed;
@ -456,7 +456,6 @@ struct FramerateWindow : Window {
this->showing_memory = true; this->showing_memory = true;
this->UpdateData(); this->UpdateData();
this->num_displayed = this->num_active; this->num_displayed = this->num_active;
this->next_update.SetInterval(100);
/* Window is always initialised to MIN_ELEMENTS height, resize to contain num_displayed */ /* 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); 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 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 */ /* Check if the shaded state has changed, switch caption text if it has */
if (this->small != this->IsShaded()) { if (this->small != this->IsShaded()) {
this->small = this->IsShaded(); this->small = this->IsShaded();
this->GetWidget<NWidgetLeaf>(WID_FRW_CAPTION)->SetDataTip(this->small ? STR_FRAMERATE_CAPTION_SMALL : STR_FRAMERATE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS); this->GetWidget<NWidgetLeaf>(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->UpdateData();
this->SetDirty(); this->SetDirty();
this->next_update.SetInterval(100);
} }
} }
/** Update the window on a regular interval. */
IntervalTimer<TimerWindow> update_interval = {std::chrono::milliseconds(100), [this](auto) {
this->UpdateData();
this->SetDirty();
}};
void UpdateData() void UpdateData()
{ {
double gl_rate = _pf_data[PFE_GAMELOOP].GetRate(); double gl_rate = _pf_data[PFE_GAMELOOP].GetRate();
@ -754,7 +752,6 @@ static const NWidgetPart _frametime_graph_window_widgets[] = {
struct FrametimeGraphWindow : Window { struct FrametimeGraphWindow : Window {
int vertical_scale; ///< number of TIMESTAMP_PRECISION units vertically int vertical_scale; ///< number of TIMESTAMP_PRECISION units vertically
int horizontal_scale; ///< number of half-second units horizontally 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 PerformanceElement element; ///< what element this window renders graph for
Dimension graph_size; ///< size of the main graph area (excluding axis labels) Dimension graph_size; ///< size of the main graph area (excluding axis labels)
@ -764,9 +761,9 @@ struct FrametimeGraphWindow : Window {
this->element = (PerformanceElement)number; this->element = (PerformanceElement)number;
this->horizontal_scale = 4; this->horizontal_scale = 4;
this->vertical_scale = TIMESTAMP_PRECISION / 10; this->vertical_scale = TIMESTAMP_PRECISION / 10;
this->next_scale_update.SetInterval(1);
this->InitNested(number); this->InitNested(number);
this->UpdateScale();
} }
void SetStringParameters(int widget) const override void SetStringParameters(int widget) const override
@ -882,14 +879,14 @@ struct FrametimeGraphWindow : Window {
this->SelectVerticalScale(peak_value); this->SelectVerticalScale(peak_value);
} }
/** Update the scaling on a regular interval. */
IntervalTimer<TimerWindow> update_interval = {std::chrono::milliseconds(500), [this](auto) {
this->UpdateScale();
}};
void OnRealtimeTick(uint delta_ms) override void OnRealtimeTick(uint delta_ms) override
{ {
this->SetDirty(); 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 */ /** Scale and interpolate a value from a source range into a destination range */

@ -15,6 +15,8 @@
#include "../network/network.h" #include "../network/network.h"
#include "../network/network_content.h" #include "../network/network_content.h"
#include "../widgets/dropdown_func.h" #include "../widgets/dropdown_func.h"
#include "../timer/timer.h"
#include "../timer/timer_window.h"
#include "game.hpp" #include "game.hpp"
#include "game_gui.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_increase; ///< Whether we clicked the increase or decrease button.
bool clicked_dropdown; ///< Whether the dropdown is open. bool clicked_dropdown; ///< Whether the dropdown is open.
bool closing_dropdown; ///< True, if the dropdown list is currently closing. 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 clicked_row; ///< The clicked row of settings.
Scrollbar *vscroll; ///< Cache of the vertical scrollbar. Scrollbar *vscroll; ///< Cache of the vertical scrollbar.
typedef std::vector<const ScriptConfigItem *> VisibleSettingsList; ///< typdef for a vector of script settings typedef std::vector<const ScriptConfigItem *> VisibleSettingsList; ///< typdef for a vector of script settings
@ -92,8 +93,7 @@ struct GSConfigWindow : public Window {
GSConfigWindow() : Window(&_gs_config_desc), GSConfigWindow() : Window(&_gs_config_desc),
clicked_button(-1), clicked_button(-1),
clicked_dropdown(false), clicked_dropdown(false),
closing_dropdown(false), closing_dropdown(false)
timeout(0)
{ {
this->gs_config = GameConfig::GetConfig(); this->gs_config = GameConfig::GetConfig();
@ -336,7 +336,7 @@ struct GSConfigWindow : public Window {
if (new_val != old_val) { if (new_val != old_val) {
this->gs_config->SetSetting(config_item.name, new_val); this->gs_config->SetSetting(config_item.name, new_val);
this->clicked_button = num; this->clicked_button = num;
this->timeout.SetInterval(150); this->unclick_timeout.Reset();
} }
} else if (!bool_item && !config_item.complete_labels) { } else if (!bool_item && !config_item.complete_labels) {
/* Display a query box so users can enter a custom value. */ /* 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); this->vscroll->SetCapacityFromWidget(this, WID_GSC_SETTINGS);
} }
void OnRealtimeTick(uint delta_ms) override /** When reset, unclick the button after a small timeout. */
{ TimeoutTimer<TimerWindow> unclick_timeout = {std::chrono::milliseconds(150), [this]() {
if (this->timeout.Elapsed(delta_ms)) { this->clicked_button = -1;
this->clicked_button = -1; this->SetDirty();
this->SetDirty(); }};
}
}
/** /**
* Some data on this window has become invalid. * Some data on this window has become invalid.

@ -20,6 +20,8 @@
#include "gfx_func.h" #include "gfx_func.h"
#include "core/geometry_func.hpp" #include "core/geometry_func.hpp"
#include "currency.h" #include "currency.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "zoom_func.h" #include "zoom_func.h"
#include "widgets/graph_widget.h" #include "widgets/graph_widget.h"
@ -892,7 +894,7 @@ struct PaymentRatesGraphWindow : BaseGraphWindow {
this->vscroll->SetCount(static_cast<int>(_sorted_standard_cargo_specs.size())); this->vscroll->SetCount(static_cast<int>(_sorted_standard_cargo_specs.size()));
/* Initialise the dataset */ /* Initialise the dataset */
this->OnHundredthTick(); this->UpdatePaymentRates();
this->FinishInitNested(window_number); this->FinishInitNested(window_number);
} }
@ -1030,10 +1032,18 @@ struct PaymentRatesGraphWindow : BaseGraphWindow {
void OnInvalidateData(int data = 0, bool gui_scope = true) override void OnInvalidateData(int data = 0, bool gui_scope = true) override
{ {
if (!gui_scope) return; if (!gui_scope) return;
this->OnHundredthTick(); this->UpdatePaymentRates();
} }
void OnHundredthTick() override /** Update the payment rates on a regular interval. */
IntervalTimer<TimerWindow> update_payment_interval = {std::chrono::seconds(3), [this](auto) {
this->UpdatePaymentRates();
}};
/**
* Update the payment rates according to the latest information.
*/
void UpdatePaymentRates()
{ {
this->UpdateExcludedData(); this->UpdateExcludedData();

@ -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 <http://www.gnu.org/licenses/>.
*/
/** @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 */

@ -42,6 +42,8 @@
#include "industry_cmd.h" #include "industry_cmd.h"
#include "querystring_gui.h" #include "querystring_gui.h"
#include "stringfilter_type.h" #include "stringfilter_type.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "table/strings.h" #include "table/strings.h"
@ -723,8 +725,7 @@ public:
if (success && !_settings_client.gui.persistent_buildingtools) ResetObjectToPlace(); if (success && !_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
} }
void OnHundredthTick() override IntervalTimer<TimerWindow> update_interval = {std::chrono::seconds(3), [this](auto) {
{
if (_game_mode == GM_EDITOR) return; if (_game_mode == GM_EDITOR) return;
if (this->count == 0) return; if (this->count == 0) return;
const IndustrySpec *indsp = GetIndustrySpec(this->selected_type); const IndustrySpec *indsp = GetIndustrySpec(this->selected_type);
@ -739,7 +740,7 @@ public:
this->SetDirty(); this->SetDirty();
} }
} }
} }};
void OnTimeout() override void OnTimeout() override
{ {
@ -1820,11 +1821,11 @@ public:
this->DrawWidgets(); this->DrawWidgets();
} }
void OnHundredthTick() override /** Rebuild the industry list on a regular interval. */
{ IntervalTimer<TimerWindow> rebuild_interval = {std::chrono::seconds(3), [this](auto) {
this->industries.ForceResort(); this->industries.ForceResort();
this->BuildSortIndustriesList(); this->BuildSortIndustriesList();
} }};
/** /**
* Some data on this window has become invalid. * Some data on this window has become invalid.

@ -30,10 +30,11 @@
#include "linkgraph/linkgraph_gui.h" #include "linkgraph/linkgraph_gui.h"
#include "tilehighlight_func.h" #include "tilehighlight_func.h"
#include "hotkeys.h" #include "hotkeys.h"
#include "guitimer_func.h"
#include "error.h" #include "error.h"
#include "news_gui.h" #include "news_gui.h"
#include "misc_cmd.h" #include "misc_cmd.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "saveload/saveload.h" #include "saveload/saveload.h"
@ -209,12 +210,6 @@ enum {
struct MainWindow : Window 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) MainWindow(WindowDesc *desc) : Window(desc)
{ {
this->InitNested(0); this->InitNested(0);
@ -225,15 +220,12 @@ struct MainWindow : Window
nvp->InitializeViewport(this, TileXY(32, 32), ScaleZoomGUI(ZOOM_LVL_VIEWPORT)); nvp->InitializeViewport(this, TileXY(32, 32), ScaleZoomGUI(ZOOM_LVL_VIEWPORT));
this->viewport->overlay = std::make_shared<LinkGraphOverlay>(this, WID_M_VIEWPORT, 0, 0, 2); this->viewport->overlay = std::make_shared<LinkGraphOverlay>(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 || if (this->viewport->overlay->GetCargoMask() == 0 ||
this->viewport->overlay->GetCompanyMask() == 0) { this->viewport->overlay->GetCompanyMask() == 0) {
return; return;
@ -243,6 +235,22 @@ struct MainWindow : Window
this->GetWidget<NWidgetBase>(WID_M_VIEWPORT)->SetDirty(this); this->GetWidget<NWidgetBase>(WID_M_VIEWPORT)->SetDirty(this);
} }
/** Refresh the link-graph overlay on a regular interval. */
IntervalTimer<TimerWindow> 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<TimerWindow> refresh_timeout = {std::chrono::milliseconds(450), [this]() {
RefreshLinkGraph();
}};
void OnPaint() override void OnPaint() override
{ {
this->DrawWidgets(); this->DrawWidgets();
@ -416,7 +424,7 @@ struct MainWindow : Window
this->viewport->scrollpos_y += ScaleByZoom(delta.y, this->viewport->zoom); this->viewport->scrollpos_y += ScaleByZoom(delta.y, this->viewport->zoom);
this->viewport->dest_scrollpos_x = this->viewport->scrollpos_x; this->viewport->dest_scrollpos_x = this->viewport->scrollpos_x;
this->viewport->dest_scrollpos_y = this->viewport->scrollpos_y; this->viewport->dest_scrollpos_y = this->viewport->scrollpos_y;
this->refresh.SetInterval(LINKGRAPH_DELAY); this->refresh_timeout.Reset();
} }
void OnMouseWheel(int wheel) override void OnMouseWheel(int wheel) override
@ -431,7 +439,7 @@ struct MainWindow : Window
if (this->viewport != nullptr) { if (this->viewport != nullptr) {
NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WID_M_VIEWPORT); NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WID_M_VIEWPORT);
nvp->UpdateViewportCoordinates(this); nvp->UpdateViewportCoordinates(this);
this->refresh.SetInterval(LINKGRAPH_DELAY); this->refresh_timeout.Reset();
} }
} }

@ -24,10 +24,11 @@
#include "core/geometry_func.hpp" #include "core/geometry_func.hpp"
#include "newgrf_debug.h" #include "newgrf_debug.h"
#include "zoom_func.h" #include "zoom_func.h"
#include "guitimer_func.h"
#include "viewport_func.h" #include "viewport_func.h"
#include "landscape_cmd.h" #include "landscape_cmd.h"
#include "rev.h" #include "rev.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "widgets/misc_widget.h" #include "widgets/misc_widget.h"
@ -470,9 +471,6 @@ struct AboutWindow : public Window {
int line_height; ///< The height of a single line int line_height; ///< The height of a single line
static const int num_visible_lines = 19; ///< The number of lines visible simultaneously 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) AboutWindow() : Window(&_about_desc)
{ {
this->InitNested(WN_GAME_OPTIONS_ABOUT); this->InitNested(WN_GAME_OPTIONS_ABOUT);
@ -500,10 +498,6 @@ struct AboutWindow : public Window {
d.width = std::max(d.width, GetStringBoundingBox(_credits[i]).width); d.width = std::max(d.width, GetStringBoundingBox(_credits[i]).width);
} }
*size = maxdim(*size, d); *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 void DrawWidget(const Rect &r, int widget) const override
@ -521,18 +515,19 @@ struct AboutWindow : public Window {
} }
} }
void OnRealtimeTick(uint delta_ms) override /**
{ * Scroll the text in the about window slow.
uint count = this->timer.CountElapsed(delta_ms); *
if (count > 0) { * The interval of 2100ms is chosen to maintain parity: 2100 / FONT_HEIGHT_NORMAL = 150ms.
this->text_position -= count; */
/* If the last text has scrolled start a new from the start */ IntervalTimer<TimerWindow> scroll_interval = {std::chrono::milliseconds(2100) / FONT_HEIGHT_NORMAL, [this](uint count) {
if (this->text_position < (int)(this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->pos_y - lengthof(_credits) * this->line_height)) { this->text_position -= count;
this->text_position = this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->pos_y + this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->current_y; /* If the last text has scrolled start a new from the start */
} if (this->text_position < (int)(this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->pos_y - lengthof(_credits) * this->line_height)) {
this->SetWidgetDirty(WID_A_SCROLLING_TEXT); this->text_position = this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->pos_y + this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->current_y;
} }
} this->SetWidgetDirty(WID_A_SCROLLING_TEXT);
}};
}; };
void ShowAboutWindow() void ShowAboutWindow()

@ -18,6 +18,8 @@
#include "../toolbar_gui.h" #include "../toolbar_gui.h"
#include "../core/geometry_func.hpp" #include "../core/geometry_func.hpp"
#include "../zoom_func.h" #include "../zoom_func.h"
#include "../timer/timer.h"
#include "../timer/timer_window.h"
#include "network.h" #include "network.h"
#include "network_client.h" #include "network_client.h"
#include "network_base.h" #include "network_base.h"
@ -170,9 +172,8 @@ void NetworkUndrawChatMessage()
} }
} }
/** Check if a message is expired. */ /** Check if a message is expired on a regular interval. */
void NetworkChatMessageLoop() static IntervalTimer<TimerWindow> network_message_expired_interval(std::chrono::seconds(1), [](auto) {
{
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
for (auto &cmsg : _chatmsg_list) { for (auto &cmsg : _chatmsg_list) {
/* Message has expired, remove from the list */ /* Message has expired, remove from the list */
@ -182,7 +183,7 @@ void NetworkChatMessageLoop()
break; break;
} }
} }
} });
/** Draw the chat message-box */ /** Draw the chat message-box */
void NetworkDrawChatMessage() void NetworkDrawChatMessage()

@ -89,7 +89,6 @@ void NetworkInitChatMessage();
void NetworkReInitChatBoxSize(); void NetworkReInitChatBoxSize();
void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const std::string &message); void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const std::string &message);
void NetworkUndrawChatMessage(); void NetworkUndrawChatMessage();
void NetworkChatMessageLoop();
void NetworkAfterNewGRFScan(); void NetworkAfterNewGRFScan();

@ -32,11 +32,12 @@
#include "../core/geometry_func.hpp" #include "../core/geometry_func.hpp"
#include "../genworld.h" #include "../genworld.h"
#include "../map_type.h" #include "../map_type.h"
#include "../guitimer_func.h"
#include "../zoom_func.h" #include "../zoom_func.h"
#include "../sprite.h" #include "../sprite.h"
#include "../settings_internal.h" #include "../settings_internal.h"
#include "../company_cmd.h" #include "../company_cmd.h"
#include "../timer/timer.h"
#include "../timer/timer_window.h"
#include "../widgets/network_widget.h" #include "../widgets/network_widget.h"
@ -55,8 +56,6 @@
static void ShowNetworkStartServerWindow(); 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 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. 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. Scrollbar *vscroll; ///< Vertical scrollbar of the list of servers.
QueryString name_editbox; ///< Client name editbox. QueryString name_editbox; ///< Client name editbox.
QueryString filter_editbox; ///< Editbox for filter on servers. 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? bool searched_internet = false; ///< Did we ever press "Search Internet" button?
int lock_offset; ///< Left offset for lock icon. int lock_offset; ///< Left offset for lock icon.
@ -499,8 +497,6 @@ public:
this->last_joined = NetworkAddServer(_settings_client.network.last_joined, false); this->last_joined = NetworkAddServer(_settings_client.network.last_joined, false);
this->server = this->last_joined; this->server = this->last_joined;
this->requery_timer.SetInterval(NETWORK_LIST_REFRESH_DELAY * 1000);
this->servers.SetListing(this->last_sorting); this->servers.SetListing(this->last_sorting);
this->servers.SetSortFuncs(this->sorter_funcs); this->servers.SetSortFuncs(this->sorter_funcs);
this->servers.SetFilterFuncs(this->filter_funcs); this->servers.SetFilterFuncs(this->filter_funcs);
@ -891,14 +887,12 @@ public:
this->vscroll->SetCapacityFromWidget(this, WID_NG_MATRIX); this->vscroll->SetCapacityFromWidget(this, WID_NG_MATRIX);
} }
void OnRealtimeTick(uint delta_ms) override /** Refresh the online servers on a regular interval. */
{ IntervalTimer<TimerWindow> refresh_interval = {std::chrono::seconds(30), [this](uint count) {
if (!this->searched_internet) return; 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(); _network_coordinator_client.GetListing();
} }};
}; };
Listing NetworkGameWindow::last_sorting = {false, 5}; Listing NetworkGameWindow::last_sorting = {false, 5};

@ -28,7 +28,8 @@
#include "textfile_gui.h" #include "textfile_gui.h"
#include "tilehighlight_func.h" #include "tilehighlight_func.h"
#include "fios.h" #include "fios.h"
#include "guitimer_func.h" #include "timer/timer.h"
#include "timer/timer_window.h"
#include "widgets/newgrf_widget.h" #include "widgets/newgrf_widget.h"
#include "widgets/misc_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_increase; ///< True if the increase button was clicked, false for the decrease button.
bool clicked_dropdown; ///< Whether the dropdown is open. bool clicked_dropdown; ///< Whether the dropdown is open.
bool closing_dropdown; ///< True, if the dropdown list is currently closing. 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 uint clicked_row; ///< The selected parameter
int line_height; ///< Height of a row in the matrix widget. int line_height; ///< Height of a row in the matrix widget.
Scrollbar *vscroll; Scrollbar *vscroll;
@ -404,7 +404,7 @@ struct NewGRFParametersWindow : public Window {
par_info->SetValue(this->grf_config, val); par_info->SetValue(this->grf_config, val);
this->clicked_button = num; 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) { } 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. */ /* 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 /** When reset, unclick the button after a small timeout. */
{ TimeoutTimer<TimerWindow> unclick_timeout = {std::chrono::milliseconds(150), [this]() {
if (timeout.Elapsed(delta_ms)) { this->clicked_button = UINT_MAX;
this->clicked_button = UINT_MAX; this->SetDirty();
this->SetDirty(); }};
}
}
}; };
GRFParameterInfo NewGRFParametersWindow::dummy_parameter_info(0); GRFParameterInfo NewGRFParametersWindow::dummy_parameter_info(0);

@ -32,10 +32,11 @@
#include "command_func.h" #include "command_func.h"
#include "company_base.h" #include "company_base.h"
#include "settings_internal.h" #include "settings_internal.h"
#include "guitimer_func.h"
#include "group_gui.h" #include "group_gui.h"
#include "zoom_func.h" #include "zoom_func.h"
#include "news_cmd.h" #include "news_cmd.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "widgets/news_widget.h" #include "widgets/news_widget.h"
@ -267,9 +268,6 @@ struct NewsWindow : Window {
const NewsItem *ni; ///< News item to display. 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 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(WindowDesc *desc, const NewsItem *ni) : Window(desc), ni(ni)
{ {
NewsWindow::duration = 16650; NewsWindow::duration = 16650;
@ -322,11 +320,6 @@ struct NewsWindow : Window {
PositionNewsMessage(this); PositionNewsMessage(this);
} }
void OnInit() override
{
this->timer.SetInterval(TIMER_INTERVAL / FONT_HEIGHT_NORMAL);
}
void DrawNewsBorder(const Rect &r) const void DrawNewsBorder(const Rect &r) const
{ {
Rect ir = r.Shrink(WidgetDimensions::scaled.bevel); Rect ir = r.Shrink(WidgetDimensions::scaled.bevel);
@ -554,18 +547,21 @@ struct NewsWindow : Window {
void OnRealtimeTick(uint delta_ms) override 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, /* Decrement the news timer. We don't need to action an elapsed event here,
* so no need to use TimerElapsed(). */ * so no need to use TimerElapsed(). */
if (NewsWindow::duration > 0) NewsWindow::duration -= delta_ms; 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<TimerWindow> scroll_interval = {std::chrono::milliseconds(210) / FONT_HEIGHT_NORMAL, [this](uint count) {
int newtop = std::max(this->top - 2 * static_cast<int>(count), _screen.height - this->height - this->status_height - this->chat_height);
this->SetWindowTop(newtop);
}};
private: private:
/** /**
* Moves the window to a new #top coordinate. Makes screen dirty where needed. * Moves the window to a new #top coordinate. Makes screen dirty where needed.

@ -21,6 +21,8 @@
#include "../hotkeys.h" #include "../hotkeys.h"
#include "../company_cmd.h" #include "../company_cmd.h"
#include "../misc_cmd.h" #include "../misc_cmd.h"
#include "../timer/timer.h"
#include "../timer/timer_window.h"
#include "script_gui.h" #include "script_gui.h"
#include "script_log.hpp" #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_increase; ///< Whether we clicked the increase or decrease button.
bool clicked_dropdown; ///< Whether the dropdown is open. bool clicked_dropdown; ///< Whether the dropdown is open.
bool closing_dropdown; ///< True, if the dropdown list is currently closing. 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 clicked_row; ///< The clicked row of settings.
int line_height; ///< Height of a row in the matrix widget. int line_height; ///< Height of a row in the matrix widget.
Scrollbar *vscroll; ///< Cache of the vertical scrollbar. Scrollbar *vscroll; ///< Cache of the vertical scrollbar.
@ -304,8 +305,7 @@ struct ScriptSettingsWindow : public Window {
slot(slot), slot(slot),
clicked_button(-1), clicked_button(-1),
clicked_dropdown(false), clicked_dropdown(false),
closing_dropdown(false), closing_dropdown(false)
timeout(0)
{ {
this->script_config = GetConfig(slot); this->script_config = GetConfig(slot);
@ -499,7 +499,7 @@ struct ScriptSettingsWindow : public Window {
if (new_val != old_val) { if (new_val != old_val) {
this->script_config->SetSetting(config_item.name, new_val); this->script_config->SetSetting(config_item.name, new_val);
this->clicked_button = num; this->clicked_button = num;
this->timeout.SetInterval(150); this->unclick_timeout.Reset();
} }
} else if (!bool_item && !config_item.complete_labels) { } else if (!bool_item && !config_item.complete_labels) {
/* Display a query box so users can enter a custom value. */ /* 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); this->vscroll->SetCapacityFromWidget(this, WID_SCRS_BACKGROUND);
} }
void OnRealtimeTick(uint delta_ms) override /** When reset, unclick the button after a small timeout. */
{ TimeoutTimer<TimerWindow> unclick_timeout = {std::chrono::milliseconds(150), [this]() {
if (this->timeout.Elapsed(delta_ms)) { this->clicked_button = -1;
this->clicked_button = -1; this->SetDirty();
this->SetDirty(); }};
}
}
/** /**
* Some data on this window has become invalid. * Some data on this window has become invalid.

@ -27,6 +27,8 @@
#include "transparency.h" #include "transparency.h"
#include "gui.h" #include "gui.h"
#include "signs_cmd.h" #include "signs_cmd.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "widgets/sign_widget.h" #include "widgets/sign_widget.h"
@ -312,11 +314,11 @@ struct SignListWindow : Window, SignList {
this->SortSignsList(); this->SortSignsList();
} }
void OnHundredthTick() override /** Resort the sign listing on a regular interval. */
{ IntervalTimer<TimerWindow> rebuild_interval = {std::chrono::seconds(3), [this](auto) {
this->BuildSortSignList(); this->BuildSortSignList();
this->SetDirty(); this->SetDirty();
} }};
/** /**
* Some data on this window has become invalid. * Some data on this window has become invalid.

@ -22,7 +22,6 @@
#include "sound_func.h" #include "sound_func.h"
#include "window_func.h" #include "window_func.h"
#include "company_base.h" #include "company_base.h"
#include "guitimer_func.h"
#include "zoom_func.h" #include "zoom_func.h"
#include "smallmap_gui.h" #include "smallmap_gui.h"
@ -1072,7 +1071,7 @@ void SmallMapWindow::SetupWidgetData()
this->GetWidget<NWidgetStacked>(WID_SM_SELECT_BUTTONS)->SetDisplayedPlane(plane); this->GetWidget<NWidgetStacked>(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; _smallmap_industry_highlight = INVALID_INDUSTRYTYPE;
this->overlay = new LinkGraphOverlay(this, WID_SM_MAP, 0, this->GetOverlayCompanyMask(), 1); 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) { if (new_highlight != _smallmap_industry_highlight) {
_smallmap_industry_highlight = new_highlight; _smallmap_industry_highlight = new_highlight;
this->refresh.SetInterval(_smallmap_industry_highlight != INVALID_INDUSTRYTYPE ? BLINK_PERIOD : FORCE_REFRESH_PERIOD);
_smallmap_industry_highlight_state = true; _smallmap_industry_highlight_state = true;
this->SetDirty(); 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) { if (this->map_type == SMT_LINKSTATS) {
CompanyMask company_mask = this->GetOverlayCompanyMask(); CompanyMask company_mask = this->GetOverlayCompanyMask();
if (this->overlay->GetCompanyMask() != company_mask) { if (this->overlay->GetCompanyMask() != company_mask) {
@ -1601,9 +1597,25 @@ int SmallMapWindow::GetPositionOnLegend(Point pt)
this->overlay->SetDirty(); 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; _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(); this->SetDirty();
} }

@ -17,7 +17,8 @@
#include "blitter/factory.hpp" #include "blitter/factory.hpp"
#include "linkgraph/linkgraph_gui.h" #include "linkgraph/linkgraph_gui.h"
#include "widgets/smallmap_widget.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 */ /* set up the cargos to be displayed in the smallmap's route legend */
void BuildLinkStatsLegend(); void BuildLinkStatsLegend();
@ -74,8 +75,6 @@ protected:
static int map_height_limit; ///< Currently used/cached map height limit. 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 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_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). 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. 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). int zoom; ///< Zoom level. Bigger number means more zoom-out (further away).
GUITimer refresh; ///< Refresh timer.
LinkGraphOverlay *overlay; LinkGraphOverlay *overlay;
static void BreakIndustryChainLink(); static void BreakIndustryChainLink();
@ -156,6 +154,16 @@ protected:
return Company::IsValidID(_local_company) ? 1U << _local_company : MAX_UVALUE(CompanyMask); return Company::IsValidID(_local_company) ? 1U << _local_company : MAX_UVALUE(CompanyMask);
} }
/** Blink the industries (if selected) on a regular interval. */
IntervalTimer<TimerWindow> blink_interval = {std::chrono::milliseconds(450), [this](auto) {
Blink();
}};
/** Update the whole map on a regular interval. */
IntervalTimer<TimerWindow> refresh_interval = {std::chrono::milliseconds(930), [this](auto) {
ForceRefresh();
}};
void RebuildColourIndexIfNecessary(); void RebuildColourIndexIfNecessary();
uint GetNumberRowsLegend(uint columns) const; uint GetNumberRowsLegend(uint columns) const;
void SelectLegendItem(int click_pos, LegendAndColour *legend, int end_legend_item, int begin_legend_item = 0); 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); int GetPositionOnLegend(Point pt);
void UpdateLinks();
void Blink();
void ForceRefresh();
public: public:
friend class NWidgetSmallmapDisplay; friend class NWidgetSmallmapDisplay;
@ -196,7 +208,6 @@ public:
void OnInvalidateData(int data = 0, bool gui_scope = true) override; void OnInvalidateData(int data = 0, bool gui_scope = true) override;
bool OnRightClick(Point pt, int widget) override; bool OnRightClick(Point pt, int widget) override;
void OnMouseWheel(int wheel) override; void OnMouseWheel(int wheel) override;
void OnRealtimeTick(uint delta_ms) override;
void OnScroll(Point delta) override; void OnScroll(Point delta) override;
void OnMouseOver(Point pt, int widget) override; void OnMouseOver(Point pt, int widget) override;
}; };

@ -25,8 +25,9 @@
#include "statusbar_gui.h" #include "statusbar_gui.h"
#include "toolbar_gui.h" #include "toolbar_gui.h"
#include "core/geometry_func.hpp" #include "core/geometry_func.hpp"
#include "guitimer_func.h"
#include "zoom_func.h" #include "zoom_func.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "widgets/statusbar_widget.h" #include "widgets/statusbar_widget.h"
@ -78,19 +79,14 @@ static bool DrawScrollingStatusText(const NewsItem *ni, int scroll_pos, int left
struct StatusBarWindow : Window { struct StatusBarWindow : Window {
bool saving; bool saving;
int ticker_scroll; 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 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 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) StatusBarWindow(WindowDesc *desc) : Window(desc)
{ {
this->ticker_scroll = TICKER_STOP; this->ticker_scroll = TICKER_STOP;
this->ticker_timer.SetInterval(15);
this->reminder_timeout.SetInterval(REMINDER_STOP);
this->InitNested(); this->InitNested();
CLRBITS(this->flags, WF_WHITE_BORDER); 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); 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)); 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_START: this->saving = true; break;
case SBI_SAVELOAD_FINISH: this->saving = false; break; case SBI_SAVELOAD_FINISH: this->saving = false; break;
case SBI_SHOW_TICKER: this->ticker_scroll = 0; 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: case SBI_NEWS_DELETED:
this->ticker_scroll = TICKER_STOP; // reset ticker ... this->ticker_scroll = TICKER_STOP; // reset ticker ...
this->reminder_timeout.SetInterval(REMINDER_STOP); // ... and reminder this->reminder_timeout.Abort(); // ... and reminder
break; 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<TimerWindow> ticker_scroll_interval = {std::chrono::milliseconds(15), [this](uint count) {
if (_pause_mode != PM_UNPAUSED) return; if (_pause_mode != PM_UNPAUSED) return;
if (this->ticker_scroll < TICKER_STOP) { // Scrolling text if (this->ticker_scroll < TICKER_STOP) {
uint count = this->ticker_timer.CountElapsed(delta_ms); this->ticker_scroll += count;
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)) {
this->SetWidgetDirty(WID_S_MIDDLE); this->SetWidgetDirty(WID_S_MIDDLE);
} }
} }};
TimeoutTimer<TimerWindow> reminder_timeout = {REMINDER_START, [this]() {
this->SetWidgetDirty(WID_S_MIDDLE);
}};
}; };
static const NWidgetPart _nested_main_status_widgets[] = { static const NWidgetPart _nested_main_status_widgets[] = {

@ -14,7 +14,9 @@
#include "core/smallvec_type.hpp" #include "core/smallvec_type.hpp"
#include "viewport_func.h" #include "viewport_func.h"
#include "settings_type.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" #include "safeguards.h"
@ -91,11 +93,9 @@ void RemoveTextEffect(TextEffectID te_id)
_text_effects[te_id].Reset(); _text_effects[te_id].Reset();
} }
void MoveAllTextEffects(uint delta_ms) /** Slowly move text effects upwards. */
{ IntervalTimer<TimerWindow> move_all_text_effects_interval = {std::chrono::milliseconds(30), [](uint count) {
static GUITimer texteffecttimer = GUITimer(MILLISECONDS_PER_TICK); if (_pause_mode && _game_mode != GM_EDITOR && _settings_game.construction.command_pause_level <= CMDPL_NO_CONSTRUCTION) return;
uint count = texteffecttimer.CountElapsed(delta_ms);
if (count == 0) return;
for (TextEffect &te : _text_effects) { for (TextEffect &te : _text_effects) {
if (te.string_id == INVALID_STRING_ID) continue; if (te.string_id == INVALID_STRING_ID) continue;
@ -111,7 +111,7 @@ void MoveAllTextEffects(uint delta_ms)
te.top -= count * ZOOM_LVL_BASE; te.top -= count * ZOOM_LVL_BASE;
te.MarkDirty(ZOOM_LVL_OUT_8X); te.MarkDirty(ZOOM_LVL_OUT_8X);
} }
} }};
void InitTextEffects() void InitTextEffects()
{ {

@ -26,7 +26,6 @@ enum TextEffectMode {
typedef size_t TextEffectID; typedef size_t TextEffectID;
void MoveAllTextEffects(uint delta_ms);
TextEffectID AddTextEffect(StringID msg, int x, int y, uint8 duration, TextEffectMode mode); TextEffectID AddTextEffect(StringID msg, int x, int y, uint8 duration, TextEffectMode mode);
void InitTextEffects(); void InitTextEffects();
void DrawTextEffects(DrawPixelInfo *dpi); void DrawTextEffects(DrawPixelInfo *dpi);

@ -49,11 +49,12 @@
#include "story_base.h" #include "story_base.h"
#include "toolbar_gui.h" #include "toolbar_gui.h"
#include "framerate_type.h" #include "framerate_type.h"
#include "guitimer_func.h"
#include "screenshot_gui.h" #include "screenshot_gui.h"
#include "misc_cmd.h" #include "misc_cmd.h"
#include "league_gui.h" #include "league_gui.h"
#include "league_base.h" #include "league_base.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "widgets/toolbar_widget.h" #include "widgets/toolbar_widget.h"
@ -1992,8 +1993,6 @@ static ToolbarButtonProc * const _toolbar_button_procs[] = {
/** Main toolbar. */ /** Main toolbar. */
struct MainToolbarWindow : Window { struct MainToolbarWindow : Window {
GUITimer timer;
MainToolbarWindow(WindowDesc *desc) : Window(desc) MainToolbarWindow(WindowDesc *desc) : Window(desc)
{ {
this->InitNested(0); this->InitNested(0);
@ -2004,8 +2003,6 @@ struct MainToolbarWindow : Window {
this->SetWidgetDisabledState(WID_TN_FAST_FORWARD, _networking); // if networking, disable fast-forward button this->SetWidgetDisabledState(WID_TN_FAST_FORWARD, _networking); // if networking, disable fast-forward button
PositionMainToolbar(this); PositionMainToolbar(this);
DoZoomInOutWindow(ZOOM_NONE, this); DoZoomInOutWindow(ZOOM_NONE, this);
this->timer.SetInterval(MILLISECONDS_PER_TICK);
} }
void FindWindowPlacementAndResize(int def_width, int def_height) override void FindWindowPlacementAndResize(int def_width, int def_height) override
@ -2109,11 +2106,8 @@ struct MainToolbarWindow : Window {
_last_started_action = CBF_NONE; _last_started_action = CBF_NONE;
} }
void OnRealtimeTick(uint delta_ms) override /** Refresh the state of pause / game-speed on a regular interval.*/
{ IntervalTimer<TimerWindow> refresh_interval = {std::chrono::milliseconds(30), [this](auto) {
if (!this->timer.Elapsed(delta_ms)) return;
this->timer.SetInterval(MILLISECONDS_PER_TICK);
if (this->IsWidgetLowered(WID_TN_PAUSE) != !!_pause_mode) { if (this->IsWidgetLowered(WID_TN_PAUSE) != !!_pause_mode) {
this->ToggleWidgetLoweredState(WID_TN_PAUSE); this->ToggleWidgetLoweredState(WID_TN_PAUSE);
this->SetWidgetDirty(WID_TN_PAUSE); this->SetWidgetDirty(WID_TN_PAUSE);
@ -2123,7 +2117,7 @@ struct MainToolbarWindow : Window {
this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD); this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD);
this->SetWidgetDirty(WID_TN_FAST_FORWARD); this->SetWidgetDirty(WID_TN_FAST_FORWARD);
} }
} }};
void OnTimeout() override void OnTimeout() override
{ {
@ -2353,8 +2347,6 @@ enum MainToolbarEditorHotkeys {
}; };
struct ScenarioEditorToolbarWindow : Window { struct ScenarioEditorToolbarWindow : Window {
GUITimer timer;
ScenarioEditorToolbarWindow(WindowDesc *desc) : Window(desc) ScenarioEditorToolbarWindow(WindowDesc *desc) : Window(desc)
{ {
this->InitNested(0); this->InitNested(0);
@ -2363,8 +2355,6 @@ struct ScenarioEditorToolbarWindow : Window {
CLRBITS(this->flags, WF_WHITE_BORDER); CLRBITS(this->flags, WF_WHITE_BORDER);
PositionMainToolbar(this); PositionMainToolbar(this);
DoZoomInOutWindow(ZOOM_NONE, this); DoZoomInOutWindow(ZOOM_NONE, this);
this->timer.SetInterval(MILLISECONDS_PER_TICK);
} }
void FindWindowPlacementAndResize(int def_width, int def_height) override void FindWindowPlacementAndResize(int def_width, int def_height) override
@ -2495,11 +2485,8 @@ struct ScenarioEditorToolbarWindow : Window {
this->SetWidgetDirty(WID_TE_DATE_FORWARD); this->SetWidgetDirty(WID_TE_DATE_FORWARD);
} }
void OnRealtimeTick(uint delta_ms) override /** Refresh the state of pause / game-speed on a regular interval.*/
{ IntervalTimer<TimerWindow> refresh_interval = {std::chrono::milliseconds(30), [this](auto) {
if (!this->timer.Elapsed(delta_ms)) return;
this->timer.SetInterval(MILLISECONDS_PER_TICK);
if (this->IsWidgetLowered(WID_TE_PAUSE) != !!_pause_mode) { if (this->IsWidgetLowered(WID_TE_PAUSE) != !!_pause_mode) {
this->ToggleWidgetLoweredState(WID_TE_PAUSE); this->ToggleWidgetLoweredState(WID_TE_PAUSE);
this->SetDirty(); this->SetDirty();
@ -2509,7 +2496,7 @@ struct ScenarioEditorToolbarWindow : Window {
this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD); this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD);
this->SetDirty(); this->SetDirty();
} }
} }};
/** /**
* Some data on this window has become invalid. * Some data on this window has become invalid.

@ -34,6 +34,8 @@
#include "widgets/dropdown_func.h" #include "widgets/dropdown_func.h"
#include "town_kdtree.h" #include "town_kdtree.h"
#include "town_cmd.h" #include "town_cmd.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "widgets/town_widget.h" #include "widgets/town_widget.h"
@ -307,10 +309,10 @@ public:
} }
} }
void OnHundredthTick() override /** Redraw the whole window on a regular interval. */
{ IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(3), [this](auto) {
this->SetDirty(); this->SetDirty();
} }};
void OnInvalidateData(int data = 0, bool gui_scope = true) override void OnInvalidateData(int data = 0, bool gui_scope = true) override
{ {
@ -966,11 +968,11 @@ public:
this->DrawWidgets(); this->DrawWidgets();
} }
void OnHundredthTick() override /** Redraw the whole window on a regular interval. */
{ IntervalTimer<TimerWindow> rebuild_interval = {std::chrono::seconds(3), [this](auto) {
this->BuildSortTownList(); this->BuildSortTownList();
this->SetDirty(); this->SetDirty();
} }};
void OnResize() override void OnResize() override
{ {

@ -12,8 +12,9 @@
#include "../string_func.h" #include "../string_func.h"
#include "../strings_func.h" #include "../strings_func.h"
#include "../window_func.h" #include "../window_func.h"
#include "../guitimer_func.h"
#include "../zoom_func.h" #include "../zoom_func.h"
#include "../timer/timer.h"
#include "../timer/timer_window.h"
#include "dropdown_type.h" #include "dropdown_type.h"
#include "dropdown_widget.h" #include "dropdown_widget.h"
@ -126,7 +127,6 @@ struct DropdownWindow : Window {
bool drag_mode; bool drag_mode;
bool instant_close; ///< Close the window when the mouse button is raised. bool instant_close; ///< Close the window when the mouse button is raised.
int scrolling; ///< If non-zero, auto-scroll the item list (one time). 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. Point position; ///< Position of the topleft corner of the window.
Scrollbar *vscroll; Scrollbar *vscroll;
@ -183,7 +183,6 @@ struct DropdownWindow : Window {
this->click_delay = 0; this->click_delay = 0;
this->drag_mode = true; this->drag_mode = true;
this->instant_close = instant_close; this->instant_close = instant_close;
this->scrolling_timer = GUITimer(MILLISECONDS_PER_TICK);
} }
void Close() override void Close() override
@ -278,22 +277,19 @@ struct DropdownWindow : Window {
} }
} }
void OnRealtimeTick(uint delta_ms) override /** Rate limit how fast scrolling happens. */
{ IntervalTimer<TimerWindow> scroll_interval = {std::chrono::milliseconds(30), [this](auto) {
if (!this->scrolling_timer.Elapsed(delta_ms)) return; if (this->scrolling == 0) return;
this->scrolling_timer.SetInterval(MILLISECONDS_PER_TICK);
if (this->scrolling != 0) { int pos = this->vscroll->GetPosition();
int pos = this->vscroll->GetPosition();
this->vscroll->UpdatePosition(this->scrolling); this->vscroll->UpdatePosition(this->scrolling);
this->scrolling = 0; this->scrolling = 0;
if (pos != this->vscroll->GetPosition()) { if (pos != this->vscroll->GetPosition()) {
this->SetDirty(); this->SetDirty();
}
} }
} }};
void OnMouseLoop() override void OnMouseLoop() override
{ {

@ -37,7 +37,6 @@
#include "video/video_driver.hpp" #include "video/video_driver.hpp"
#include "framerate_type.h" #include "framerate_type.h"
#include "network/network_func.h" #include "network/network_func.h"
#include "guitimer_func.h"
#include "news_func.h" #include "news_func.h"
#include "timer/timer.h" #include "timer/timer.h"
#include "timer/timer_window.h" #include "timer/timer_window.h"
@ -1888,14 +1887,9 @@ void ResetWindowSystem()
static void DecreaseWindowCounters() static void DecreaseWindowCounters()
{ {
static byte hundredth_tick_timeout = 100;
if (_scroller_click_timeout != 0) _scroller_click_timeout--; if (_scroller_click_timeout != 0) _scroller_click_timeout--;
if (hundredth_tick_timeout != 0) hundredth_tick_timeout--;
for (Window *w : Window::Iterate()) { for (Window *w : Window::Iterate()) {
if (!_network_dedicated && hundredth_tick_timeout == 0) w->OnHundredthTick();
if (_scroller_click_timeout == 0) { if (_scroller_click_timeout == 0) {
/* Unclick scrollbar buttons if they are pressed. */ /* Unclick scrollbar buttons if they are pressed. */
for (uint i = 0; i < w->nested_array_size; i++) { for (uint i = 0; i < w->nested_array_size; i++) {
@ -1927,8 +1921,6 @@ static void DecreaseWindowCounters()
w->RaiseButtons(true); w->RaiseButtons(true);
} }
} }
if (hundredth_tick_timeout == 0) hundredth_tick_timeout = 100;
} }
static void HandlePlacePresize() static void HandlePlacePresize()
@ -3111,20 +3103,21 @@ static IntervalTimer<TimerWindow> white_border_interval(std::chrono::millisecond
*/ */
void UpdateWindows() void UpdateWindows()
{ {
static std::chrono::steady_clock::time_point last_time = std::chrono::steady_clock::now(); static auto last_time = std::chrono::steady_clock::now();
uint delta_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - last_time).count(); auto now = std::chrono::steady_clock::now();
auto delta_ms = std::chrono::duration_cast<std::chrono::milliseconds>(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); PerformanceMeasurer framerate(PFE_DRAWING);
PerformanceAccumulator::Reset(PFE_DRAWWORLD); PerformanceAccumulator::Reset(PFE_DRAWWORLD);
ProcessPendingPerformanceMeasurements(); ProcessPendingPerformanceMeasurements();
TimerManager<TimerWindow>::Elapsed(std::chrono::milliseconds(delta_ms)); TimerManager<TimerWindow>::Elapsed(delta_ms);
CallWindowRealtimeTickEvent(delta_ms); CallWindowRealtimeTickEvent(delta_ms.count());
/* Process invalidations before anything else. */ /* Process invalidations before anything else. */
for (Window *w : Window::Iterate()) { for (Window *w : Window::Iterate()) {
@ -3132,8 +3125,6 @@ void UpdateWindows()
w->ProcessHighlightedInvalidations(); 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. /* Skip the actual drawing on dedicated servers without screen.
* But still empty the invalidation queues above. */ * But still empty the invalidation queues above. */
if (_network_dedicated) return; if (_network_dedicated) return;

@ -621,13 +621,6 @@ public:
*/ */
virtual void OnGameTick() {} 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. * Called periodically.
*/ */

Loading…
Cancel
Save