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 "core/smallvec_type.hpp"
15 #include "viewport_func.h"
16 #include "settings_type.h"
17 #include "guitimer_func.h"
19 #include "safeguards.h"
21 /** Container for all information about a text effect */
22 struct TextEffect
: public ViewportSign
{
23 uint64 params_1
; ///< DParam parameter
24 uint64 params_2
; ///< second DParam parameter
25 StringID string_id
; ///< String to draw for the text effect, if INVALID_STRING_ID then it's not valid
26 uint8 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 duration
, TextEffectMode mode
)
43 if (_game_mode
== GM_MENU
) return INVALID_TE_ID
;
46 for (i
= 0; i
< _text_effects
.size(); i
++) {
47 if (_text_effects
[i
].string_id
== INVALID_STRING_ID
) break;
49 if (i
== _text_effects
.size()) _text_effects
.emplace_back();
51 TextEffect
&te
= _text_effects
[i
];
53 /* Start defining this object */
55 te
.duration
= duration
;
56 te
.params_1
= GetDParam(0);
57 te
.params_2
= GetDParam(1);
60 /* Make sure we only dirty the new area */
62 te
.UpdatePosition(center
, y
, msg
);
67 void UpdateTextEffect(TextEffectID te_id
, StringID msg
)
70 TextEffect
*te
= _text_effects
.data() + te_id
;
71 if (msg
== te
->string_id
&& GetDParam(0) == te
->params_1
) return;
73 te
->params_1
= GetDParam(0);
74 te
->params_2
= GetDParam(1);
76 te
->UpdatePosition(te
->center
, te
->top
, te
->string_id
, te
->string_id
- 1);
79 void UpdateAllTextEffectVirtCoords()
81 for (auto &te
: _text_effects
) {
82 if (te
.string_id
== INVALID_STRING_ID
) continue;
83 SetDParam(0, te
.params_1
);
84 SetDParam(1, te
.params_2
);
85 te
.UpdatePosition(te
.center
, te
.top
, te
.string_id
, te
.string_id
- 1);
89 void RemoveTextEffect(TextEffectID te_id
)
91 _text_effects
[te_id
].Reset();
94 void MoveAllTextEffects(uint delta_ms
)
96 static GUITimer texteffecttimer
= GUITimer(MILLISECONDS_PER_TICK
);
97 uint count
= texteffecttimer
.CountElapsed(delta_ms
);
98 if (count
== 0) return;
100 for (TextEffect
&te
: _text_effects
) {
101 if (te
.string_id
== INVALID_STRING_ID
) continue;
102 if (te
.mode
!= TE_RISING
) continue;
104 if (te
.duration
< count
) {
109 te
.MarkDirty(ZOOM_LVL_OUT_8X
);
110 te
.duration
-= count
;
111 te
.top
-= count
* ZOOM_LVL_BASE
;
112 te
.MarkDirty(ZOOM_LVL_OUT_8X
);
116 void InitTextEffects()
118 _text_effects
.clear();
119 _text_effects
.shrink_to_fit();
122 void DrawTextEffects(DrawPixelInfo
*dpi
)
124 /* Don't draw the text effects when zoomed out a lot */
125 if (dpi
->zoom
> ZOOM_LVL_OUT_8X
) return;
127 for (TextEffect
&te
: _text_effects
) {
128 if (te
.string_id
== INVALID_STRING_ID
) continue;
129 if (te
.mode
== TE_RISING
|| (_settings_client
.gui
.loading_indicators
&& !IsTransparencySet(TO_LOADING
))) {
130 ViewportAddString(dpi
, ZOOM_LVL_OUT_8X
, &te
, te
.string_id
, te
.string_id
- 1, STR_NULL
, te
.params_1
, te
.params_2
);