2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
8 /** @file texteff.cpp Handling of text effects. */
11 #include "texteff.hpp"
12 #include "transparency.h"
13 #include "strings_func.h"
14 #include "viewport_func.h"
15 #include "settings_type.h"
16 #include "command_type.h"
17 #include "timer/timer.h"
18 #include "timer/timer_window.h"
20 #include "safeguards.h"
22 /** Container for all information about a text effect */
23 struct TextEffect
: public ViewportSign
{
24 std::vector
<StringParameterData
> params
; ///< Backup of string parameters
25 StringID string_id
; ///< String to draw for the text effect, if INVALID_STRING_ID then it's not valid
26 uint8_t duration
; ///< How long the text effect should stay, in ticks (applies only when mode == TE_RISING)
27 TextEffectMode mode
; ///< Type of text effect
29 /** Reset the text effect */
33 this->width_normal
= 0;
34 this->string_id
= INVALID_STRING_ID
;
38 static std::vector
<struct TextEffect
> _text_effects
; ///< Text effects are stored there
41 TextEffectID
AddTextEffect(StringID msg
, int center
, int y
, uint8_t duration
, TextEffectMode mode
)
43 if (_game_mode
== GM_MENU
) return INVALID_TE_ID
;
45 auto it
= std::find_if(std::begin(_text_effects
), std::end(_text_effects
), [](const TextEffect
&te
) { return te
.string_id
== INVALID_STRING_ID
; });
46 if (it
== std::end(_text_effects
)) {
47 /* _text_effects.size() is the maximum ID + 1 that has been allocated. We should not allocate INVALID_TE_ID or beyond. */
48 if (_text_effects
.size() >= INVALID_TE_ID
) return INVALID_TE_ID
;
49 it
= _text_effects
.emplace(std::end(_text_effects
));
54 /* Start defining this object */
56 te
.duration
= duration
;
57 CopyOutDParam(te
.params
, 2);
60 /* Make sure we only dirty the new area */
62 te
.UpdatePosition(center
, y
, msg
);
64 return static_cast<TextEffectID
>(it
- std::begin(_text_effects
));
67 void UpdateTextEffect(TextEffectID te_id
, StringID msg
)
70 TextEffect
&te
= _text_effects
[te_id
];
71 if (msg
== te
.string_id
&& !HaveDParamChanged(te
.params
)) return;
73 CopyOutDParam(te
.params
, 2);
75 te
.UpdatePosition(te
.center
, te
.top
, te
.string_id
, te
.string_id
- 1);
78 void UpdateAllTextEffectVirtCoords()
80 for (auto &te
: _text_effects
) {
81 if (te
.string_id
== INVALID_STRING_ID
) continue;
82 CopyInDParam(te
.params
);
83 te
.UpdatePosition(te
.center
, te
.top
, te
.string_id
, te
.string_id
- 1);
87 void RemoveTextEffect(TextEffectID te_id
)
89 _text_effects
[te_id
].Reset();
92 /** Slowly move text effects upwards. */
93 IntervalTimer
<TimerWindow
> move_all_text_effects_interval
= {std::chrono::milliseconds(30), [](uint count
) {
94 if (_pause_mode
&& _game_mode
!= GM_EDITOR
&& _settings_game
.construction
.command_pause_level
<= CMDPL_NO_CONSTRUCTION
) return;
96 for (TextEffect
&te
: _text_effects
) {
97 if (te
.string_id
== INVALID_STRING_ID
) continue;
98 if (te
.mode
!= TE_RISING
) continue;
100 if (te
.duration
< count
) {
105 te
.MarkDirty(ZOOM_LVL_TEXT_EFFECT
);
106 te
.duration
-= count
;
107 te
.top
-= count
* ZOOM_BASE
;
108 te
.MarkDirty(ZOOM_LVL_TEXT_EFFECT
);
112 void InitTextEffects()
114 _text_effects
.clear();
115 _text_effects
.shrink_to_fit();
118 void DrawTextEffects(DrawPixelInfo
*dpi
)
120 /* Don't draw the text effects when zoomed out a lot */
121 if (dpi
->zoom
> ZOOM_LVL_TEXT_EFFECT
) return;
122 if (IsTransparencySet(TO_TEXT
)) return;
123 for (TextEffect
&te
: _text_effects
) {
124 if (te
.string_id
== INVALID_STRING_ID
) continue;
125 if (te
.mode
== TE_RISING
|| _settings_client
.gui
.loading_indicators
) {
126 CopyInDParam(te
.params
);
127 ViewportAddString(dpi
, ZOOM_LVL_TEXT_EFFECT
, &te
, te
.string_id
, te
.string_id
- 1, STR_NULL
);