The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
replay_controller.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2015 - 2016 by the Battle for Wesnoth Project
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 2 of the License, or
7  (at your option) any later version.
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY.
10 
11  See the COPYING file for more details.
12 */
13 
14 #include "global.hpp"
15 
16 #include "replay_controller.hpp"
17 
18 #include "game_config_manager.hpp"
19 #include "gettext.hpp"
20 #include "log.hpp"
21 #include "replay.hpp"
22 #include "resources.hpp"
23 #include "config_assign.hpp"
25 
26 #include <boost/scoped_ptr.hpp>
27 
28 static lg::log_domain log_engine("engine");
29 #define DBG_NG LOG_STREAM(debug, log_engine)
30 
31 static lg::log_domain log_replay("replay");
32 #define DBG_REPLAY LOG_STREAM(debug, log_replay)
33 #define LOG_REPLAY LOG_STREAM(info, log_replay)
34 #define ERR_REPLAY LOG_STREAM(err, log_replay)
35 
36 namespace
37 {
38 struct replay_play_nostop : public replay_controller::replay_stop_condition
39 {
40  replay_play_nostop() {}
41  virtual bool should_stop() { return false; }
42 };
43 
44 struct replay_play_moves : public replay_controller::replay_stop_condition
45 {
46  int moves_todo_;
47  replay_play_moves(int moves_todo) : moves_todo_(moves_todo) {}
48  virtual void move_done() { --moves_todo_; }
49  virtual bool should_stop() { return moves_todo_ == 0; }
50 };
51 
52 struct replay_play_turn : public replay_controller::replay_stop_condition
53 {
54  int turn_begin_;
55  int turn_current_;
56  replay_play_turn(int turn_begin) : turn_begin_(turn_begin), turn_current_(turn_begin) {}
57  virtual void new_side_turn(int , int turn) { turn_current_ = turn; }
58  virtual bool should_stop() { return turn_begin_ != turn_current_; }
59 };
60 
61 struct replay_play_side : public replay_controller::replay_stop_condition
62 {
63  bool next_side_;
64  replay_play_side() : next_side_(false) {}
65  virtual void new_side_turn(int , int) { next_side_ = true; }
66  virtual bool should_stop() { return next_side_; }
67 };
68 }
69 
70 replay_controller::replay_controller(play_controller& controller, bool control_view, const boost::shared_ptr<config>& reset_state, const std::function<void()>& on_end_replay)
71  : controller_(controller)
72  , stop_condition_(new replay_stop_condition())
73  , disabler_()
74  , vision_()
75  , reset_state_(reset_state)
76  , on_end_replay_(on_end_replay)
77  , return_to_play_side_(false)
78 {
79  if(control_view) {
81  }
85 }
87 {
90  }
95 }
97 {
99  if (const config &res = theme_cfg.child("resolution"))
100  {
101  if (const config &replay_theme_cfg = res.child("replay")) {
102  controller_.get_display().get_theme().modify(replay_theme_cfg);
103  }
104  //Make sure we get notified if the theme is redrawn completely. That way we have
105  //a chance to restore the replay controls of the theme as well.
107  }
108 }
109 
110 
112 {
114  if (const config &res = theme_cfg.child("resolution"))
115  {
116  if (const config &replay_theme_cfg = res.child("replay")) {
117  controller_.get_display().get_theme().modify(replay_theme_cfg);
118  }
119  controller_.get_display().get_theme().modify_label("time-icon", _ ("current local time"));
120  //Make sure we get notified if the theme is redrawn completely. That way we have
121  //a chance to restore the replay controls of the theme as well.
123  }
124 }
125 
126 std::shared_ptr<gui::button> replay_controller::play_button()
127 {
128  return controller_.get_display().find_action_button("button-playreplay");
129 }
130 
131 std::shared_ptr<gui::button> replay_controller::stop_button()
132 {
133  return controller_.get_display().find_action_button("button-stopreplay");
134 }
135 
136 std::shared_ptr<gui::button> replay_controller::reset_button()
137 {
138  return controller_.get_display().find_action_button("button-resetreplay");
139 }
140 
141 std::shared_ptr<gui::button> replay_controller::play_turn_button()
142 {
143  return controller_.get_display().find_action_button("button-nextturn");
144 }
145 
146 std::shared_ptr<gui::button> replay_controller::play_side_button()
147 {
148  return controller_.get_display().find_action_button("button-nextside");
149 }
150 
151 std::shared_ptr<gui::button> replay_controller::play_move_button()
152 {
153  return controller_.get_display().find_action_button("button-nextmove");
154 }
155 
157 {
158  //check if we have all buttons - if someone messed with theme then some buttons may be missing
159  //if any of the buttons is missing, we just disable every one
161  std::shared_ptr<gui::button> play_b = play_button(), stop_b = stop_button(),
162  reset_b = reset_button(), play_turn_b = play_turn_button(),
163  play_side_b = play_side_button(), play_move_b = play_move_button();
164 
165  if(play_b) {
166  play_b->enable(false);
167  }
168 
169  if(stop_b) {
170  stop_b->enable(false);
171  }
172 
173  if(reset_b) {
174  reset_b->enable(false);
175  }
176 
177  if(play_turn_b) {
178  play_turn_b->enable(false);
179  }
180 
181  if(play_side_b) {
182  play_side_b->enable(false);
183  }
184 
185  if (play_move_b) {
186  play_move_b->enable(false);
187  }
188  }
189 }
190 
192 {
194  return;
195 
196  play_button()->enable(false);
197  reset_button()->enable(false);
198  play_turn_button()->enable(false);
199  play_side_button()->enable(false);
200  play_move_button()->enable(false);
201 }
202 
204 {
206  return;
207 
208  if(!resources::recorder->at_end()) {
209  play_button()->enable(true);
210  reset_button()->enable(true);
211  play_turn_button()->enable(true);
212  play_side_button()->enable(true);
213  play_move_button()->enable(true);
214 
215  play_button()->release();
216  play_turn_button()->release();
217  play_side_button()->release();
218  play_move_button()->release();
219  } else {
220  reset_button()->enable(true);
221  stop_button()->enable(false);
222  }
223 
224  if(stop_condition_->should_stop()) {
225  //user interrupted
226  stop_button()->release();
227  }
228 }
229 
231 {
233  return;
234 
235  play_button()->enable(true);
236  stop_button()->enable(true);
237  reset_button()->enable(true);
238  play_turn_button()->enable(true);
239  play_side_button()->enable(true);
240 }
241 
242 
244 {
246 }
247 
249 {
250  stop_condition_.reset(new replay_play_turn(controller_.gamestate().tod_manager_.turn()));
251 }
252 
254 {
255  stop_condition_.reset(new replay_play_side());
256 }
257 
259 {
260  stop_condition_.reset(new replay_play_moves(1));
261 }
262 
263 //move all sides till stop/end
265 {
266  stop_condition_.reset(new replay_play_nostop());
267 }
268 
270 {
276 }
277 
279 {
280 
281  if( name == "completely_redrawn" ) {
283  } else {
285  }
286  if(std::shared_ptr<gui::button> skip_animation_button = controller_.get_display().find_action_button("skip-animation")) {
287  skip_animation_button->set_check(controller_.is_skipping_replay());
288  }
289 }
290 
292 {
293  return resources::recorder->at_end();
294 }
295 
297 {
298  while(!return_to_play_side_ && !static_cast<playsingle_controller&>(controller_).get_player_type_changed())
299  {
300  if(!stop_condition_->should_stop())
301  {
302  if(resources::recorder->at_end()) {
303  //Gather more replay data
304  on_end_replay_();
305  }
306  else {
307  REPLAY_RETURN res = do_replay(true);
308  if(res == REPLAY_FOUND_END_MOVE) {
309  stop_condition_->move_done();
310  }
311  if(res == REPLAY_FOUND_END_TURN) {
312  return res;
313  }
314  if(res == REPLAY_RETURN_AT_END) {
315  stop_replay();
316  }
317  if(res == REPLAY_FOUND_INIT_TURN)
318  {
320  }
321  }
322  controller_.play_slice(false);
323  }
324  else
325  {
326  controller_.play_slice(true);
328  }
329  }
330  return REPLAY_FOUND_END_MOVE;
331 }
333 {
334  hotkey::HOTKEY_COMMAND command = cmd.id;
335 
336  switch(command) {
338  return true;
342  return is_controlling_view();
343  //commands we only can do before the end of the replay
345  return !recorder_at_end();
350  //we have one events_disabler when starting the replay_controller and a second when entering the synced context.
351  return should_stop() && (events::commands_disabled <= 1 ) && !recorder_at_end();
354  default:
355  assert(false);
356  return false;
357  }
358 }
359 
361 {
362  vision_ = SHOW_ALL;
363  update_teams();
364 }
365 
367 {
369  update_teams();
370 }
371 
373 {
375  update_teams();
376 }
377 
379 {
382  update_gui();
383 }
384 
386 {
387  assert(vision_);
389 }
static const config & get_theme(const config &game_config, std::string theme_name)
std::shared_ptr< gui::button > find_action_button(const std::string &id)
Retrieves a pointer to a theme UI button.
Definition: display.cpp:826
std::function< void()> on_end_replay_
boost::optional< REPLAY_VISION > vision_
theme & get_theme()
Definition: display.hpp:385
static lg::log_domain log_engine("engine")
int first_human_team_
Definition: game_state.hpp:72
void redraw_everything()
Invalidates entire screen, including all tiles and sidebar.
Definition: display.cpp:2650
Stores all information related to functions that can be bound to hotkeys.
void play_slice(bool is_delay_enabled=true)
Replay control code.
bool is_skipping_replay() const
virtual void draw()
Draws invalidated items.
Definition: display.cpp:2706
REPLAY_RETURN do_replay(bool one_move)
Definition: replay.cpp:659
bool is_controlling_view() const
void redraw_minimap()
Schedule the minimap to be redrawn.
Definition: display.hpp:629
std::shared_ptr< gui::button > play_button()
bool recorder_at_end() const
boost::scoped_ptr< replay_stop_condition > stop_condition_
void handle_generic_event(const std::string &name) override
REPLAY_RETURN
Definition: replay.hpp:155
static game_config_manager * get()
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:82
int current_side() const
Returns the number of the side whose turn it is.
std::shared_ptr< gui::button > play_turn_button()
void recalculate_minimap()
Schedule the minimap for recalculation.
Definition: display.hpp:623
events::generic_event & theme_reset_event()
Definition: theme.hpp:294
std::shared_ptr< gui::button > stop_button()
void modify(const config &cfg)
Definition: theme.cpp:833
tod_manager tod_manager_
Definition: game_state.hpp:50
replay * recorder
Definition: resources.cpp:30
void create_buttons()
Definition: display.cpp:897
REPLAY_RETURN play_side_impl()
replay_controller(play_controller &controller, bool control_view, const boost::shared_ptr< config > &reset_state, const std::function< void()> &on_end_replay=nop)
void invalidate_all()
Function to invalidate all tiles.
Definition: display.cpp:3525
void raise_draw_event()
Definition: events.cpp:565
void update_gui_to_player(const int team_index, const bool observe=false)
Changes the UI for this client to the passed side index.
bool allow_reset_replay() const
GLuint res
Definition: glew.h:9258
virtual bool attach_handler(observer *obs)
static lg::log_domain log_replay("replay")
Game configuration data as global variables.
Definition: build_info.cpp:38
void modify_label(const std::string &id, const std::string &text)
Definition: theme.cpp:992
int turn() const
GLuint const GLchar * name
Definition: glew.h:1782
std::shared_ptr< gui::button > play_side_button()
void replay_ui_playback_should_start()
game_state & gamestate()
const hotkey::HOTKEY_COMMAND id
the names are strange: the "hotkey::HOTKEY_COMMAND" is named id, and the string to identify the objec...
bool at_end() const
Definition: replay.cpp:611
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:658
play_controller & controller_
Standard logging facilities (interface).
game_display & get_display()
Get a reference to a display member a derived class uses.
virtual bool detach_handler(observer *obs)
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
std::string theme()
bool can_execute_command(const hotkey::hotkey_command &cmd, int index) const
std::shared_ptr< gui::button > reset_button()
GLsizei const GLcharARB ** string
Definition: glew.h:4503
void invalidate_theme()
Definition: display.hpp:408
bool should_stop() const
std::shared_ptr< gui::button > play_move_button()