1 | // SuperTux |
2 | // Copyright (C) 2018 Nir <goproducti@gmail.com> |
3 | // |
4 | // This program is free software: you can redistribute it and/or modify |
5 | // it under the terms of the GNU General Public License as published by |
6 | // the Free Software Foundation, either version 3 of the License, or |
7 | // (at your option) any later version. |
8 | // |
9 | // This program is distributed in the hope that it will be useful, |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | // GNU General Public License for more details. |
13 | // |
14 | // You should have received a copy of the GNU General Public License |
15 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | |
17 | #include "object/text_array_object.hpp" |
18 | #include "control/input_manager.hpp" |
19 | |
20 | TextArrayObject::TextArrayObject(const std::string& name) : |
21 | ExposedObject<TextArrayObject, scripting::TextArray>(this), |
22 | m_isDone(false), |
23 | m_isAuto(false), |
24 | m_keepVisible(false), |
25 | m_fadeTransition(true), |
26 | m_fadetime(1.0), |
27 | m_texts(), |
28 | m_curTextIndex(0), |
29 | m_lastTextIndex(0), |
30 | m_waiting() |
31 | { |
32 | m_name = name; |
33 | } |
34 | |
35 | TextArrayObject::TextArrayObject(const ReaderMapping& reader) : |
36 | GameObject(reader), |
37 | ExposedObject<TextArrayObject, scripting::TextArray>(this), |
38 | m_isDone(false), |
39 | m_isAuto(false), |
40 | m_keepVisible(false), |
41 | m_fadeTransition(true), |
42 | m_fadetime(1.0), |
43 | m_texts(), |
44 | m_curTextIndex(0), |
45 | m_lastTextIndex(0), |
46 | m_waiting() |
47 | { |
48 | } |
49 | |
50 | void |
51 | TextArrayObject::clear() |
52 | { |
53 | m_texts.clear(); |
54 | reset_automation(); |
55 | } |
56 | |
57 | void |
58 | TextArrayObject::add_text(const std::string& text, float duration) |
59 | { |
60 | auto pText = std::make_unique<TextArrayItem>(); |
61 | assert(pText); |
62 | |
63 | pText->duration = duration; |
64 | pText->text_object.set_text(text); |
65 | |
66 | m_texts.push_back(std::move(pText)); |
67 | } |
68 | |
69 | void TextArrayObject::set_text_index(ta_index index) |
70 | { |
71 | if (index < m_texts.size()) |
72 | m_curTextIndex = index; |
73 | } |
74 | |
75 | void |
76 | TextArrayObject::set_fade_time(float fadetime) |
77 | { |
78 | m_fadetime = fadetime; |
79 | } |
80 | |
81 | void |
82 | TextArrayObject::next_text() |
83 | { |
84 | if (m_isDone) |
85 | return; |
86 | |
87 | if (m_curTextIndex+1 >= m_texts.size()) { |
88 | m_isDone = true; |
89 | return; |
90 | } |
91 | |
92 | m_lastTextIndex = m_curTextIndex++; |
93 | |
94 | override_properties(); |
95 | reset_automation(); |
96 | } |
97 | |
98 | void |
99 | TextArrayObject::prev_text() |
100 | { |
101 | if (m_isDone) |
102 | return; |
103 | |
104 | if (m_curTextIndex == 0) |
105 | return; |
106 | |
107 | m_lastTextIndex = m_curTextIndex--; |
108 | |
109 | override_properties(); |
110 | reset_automation(); |
111 | } |
112 | |
113 | void |
114 | TextArrayObject::set_keep_visible(bool keep_visible) |
115 | { |
116 | m_keepVisible = keep_visible; |
117 | } |
118 | |
119 | void |
120 | TextArrayObject::set_fade_transition(bool fade_transition) |
121 | { |
122 | m_fadeTransition = fade_transition; |
123 | } |
124 | |
125 | TextArrayItem* |
126 | TextArrayObject::get_text_item(ta_index index) |
127 | { |
128 | auto vecSize = m_texts.size(); |
129 | |
130 | if (vecSize == 0 || index >= vecSize) |
131 | return nullptr; |
132 | |
133 | return m_texts.at(index).get(); |
134 | } |
135 | |
136 | TextArrayItem* |
137 | TextArrayObject::get_current_text_item() |
138 | { |
139 | return get_text_item(m_curTextIndex); |
140 | } |
141 | |
142 | TextArrayItem* |
143 | TextArrayObject::get_last_text_item() |
144 | { |
145 | return get_text_item(m_lastTextIndex); |
146 | } |
147 | |
148 | void |
149 | TextArrayObject::set_done(bool done) |
150 | { |
151 | m_isDone = done; |
152 | } |
153 | |
154 | void |
155 | TextArrayObject::set_auto(bool is_auto) |
156 | { |
157 | m_isAuto = is_auto; |
158 | reset_automation(); |
159 | } |
160 | |
161 | void |
162 | TextArrayObject::update(float dt_sec) |
163 | { |
164 | if (m_isDone) |
165 | return; |
166 | |
167 | // make sure there's anything to update |
168 | if (m_texts.size() == 0) |
169 | return; |
170 | |
171 | // detect change request |
172 | handle_input_requests(); |
173 | |
174 | // check if if should update auto narration |
175 | if (m_isAuto && m_waiting.check()) { |
176 | next_text(); |
177 | } |
178 | |
179 | // update current |
180 | auto* curTextItem = get_current_text_item(); |
181 | if (curTextItem) |
182 | curTextItem->text_object.update(dt_sec); |
183 | |
184 | // update last (if transition is enabled) |
185 | |
186 | if (should_fade()) { |
187 | auto* lastTextItem = get_last_text_item(); |
188 | if (lastTextItem) |
189 | lastTextItem->text_object.update(dt_sec); |
190 | } |
191 | } |
192 | |
193 | void |
194 | TextArrayObject::draw(DrawingContext& context) |
195 | { |
196 | if (m_isDone) |
197 | return; |
198 | |
199 | auto* curTextItem = get_current_text_item(); |
200 | if (!curTextItem) |
201 | return; |
202 | |
203 | // draw last if transition enabled |
204 | if (should_fade()) { |
205 | auto* lastTextItem = get_last_text_item(); |
206 | if (lastTextItem) |
207 | lastTextItem->text_object.draw(context); |
208 | } |
209 | |
210 | // draw current |
211 | curTextItem->text_object.draw(context); |
212 | } |
213 | |
214 | void |
215 | TextArrayObject::override_properties() |
216 | { |
217 | if (!(should_fade() || m_keepVisible)) |
218 | return; |
219 | |
220 | auto* curTextItem = get_current_text_item(); |
221 | if (!curTextItem) |
222 | return; |
223 | |
224 | // apply overrides |
225 | if (should_fade()) { // make fade transition |
226 | auto* lastTextItem = get_last_text_item(); |
227 | if (lastTextItem) { |
228 | lastTextItem->text_object.fade_out(m_fadetime); |
229 | curTextItem->text_object.fade_in(m_fadetime); |
230 | } |
231 | } else if (m_keepVisible) { // keep visible |
232 | curTextItem->text_object.set_visible(true); |
233 | } |
234 | } |
235 | |
236 | void |
237 | TextArrayObject::reset_automation() |
238 | { |
239 | m_waiting.stop(); |
240 | |
241 | if (m_isAuto) { |
242 | auto* text = get_current_text_item(); |
243 | if (text) |
244 | m_waiting.start(text->duration); |
245 | } |
246 | } |
247 | |
248 | void |
249 | TextArrayObject::handle_input_requests() |
250 | { |
251 | const Controller& controller = InputManager::current()->get_controller(); |
252 | |
253 | if (controller.pressed(Control::MENU_SELECT)) { |
254 | m_isAuto = false; |
255 | next_text(); |
256 | } else if (controller.pressed(Control::REMOVE)) { |
257 | m_isAuto = false; |
258 | prev_text(); |
259 | } |
260 | |
261 | } |
262 | |
263 | bool |
264 | TextArrayObject::should_fade() |
265 | { |
266 | return m_fadeTransition && (m_curTextIndex != m_lastTextIndex); |
267 | } |
268 | |
269 | /* EOF */ |
270 | |