The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
manager.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2017 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "game_events/manager.hpp"
16 
17 #include "game_events/handlers.hpp"
20 #include "game_events/pump.hpp"
21 
22 #include "filter_context.hpp"
23 #include "formula/string_utils.hpp"
24 #include "game_data.hpp"
25 #include "log.hpp"
26 #include "reports.hpp"
27 #include "resources.hpp"
30 #include "soundsource.hpp"
31 
32 #include <iostream>
33 
34 static lg::log_domain log_engine("engine");
35 #define DBG_NG LOG_STREAM(debug, log_engine)
36 #define LOG_NG LOG_STREAM(info, log_engine)
37 #define WRN_NG LOG_STREAM(warn, log_engine)
38 
39 static lg::log_domain log_event_handler("event_handler");
40 #define DBG_EH LOG_STREAM(debug, log_event_handler)
41 
42 namespace game_events
43 {
44 /** Create an event handler. */
45 void manager::add_event_handler(const config& handler, bool is_menu_item)
46 {
47  event_handlers_->add_event_handler(handler, *this, is_menu_item);
48 }
49 
50 /** Removes an event handler. */
52 {
53  event_handlers_->remove_event_handler(id);
54 }
55 
56 /** Gets an event handler by id */
58 {
59  return event_handlers_->get_event_handler_by_id(id);
60 }
61 
62 /* ** manager ** */
63 
65  : event_handlers_(new event_handlers())
66  , unit_wml_ids_()
67  , pump_(new game_events::wml_event_pump(*this))
68  , wml_menu_items_()
69 {
70 }
71 
72 void manager::read_scenario(const config& scenario_cfg)
73 {
74  for(const config& ev : scenario_cfg.child_range("event")) {
76  }
77 
78  for(const std::string& id : utils::split(scenario_cfg["unit_wml_ids"])) {
79  unit_wml_ids_.insert(id);
80  }
81 
82  wml_menu_items_.set_menu_items(scenario_cfg);
83 
84  // Create the event handlers for menu items.
86 }
87 
89 {
90 }
91 
92 /* ** manager::iteration ** */
93 
94 /**
95  * Event-specific constructor.
96  * This iteration will go through all event handlers matching the given name
97  * (including those defined via menu items).
98  * An empty @a event_name will automatically match nothing.
99  */
101  : main_list_(man.event_handlers_->get(event_name))
102  , var_list_(man.event_handlers_->get_dynamic())
103  , event_name_(event_name)
104  , end_(man.event_handlers_->size())
105  , current_is_known_(false)
106  , main_is_current_(false)
107  , main_it_(main_list_.begin())
108  , var_it_(event_name.empty() ? var_list_.end() : var_list_.begin())
109  , gamedata_(resources::gamedata)
110 {
111 }
112 
113 /**
114  * Increment
115  * Incrementing guarantees that the next dereference will differ from the
116  * previous derference (unless the iteration is exhausted). However, multiple
117  * increments between dereferences are allowed to have the same effect as a
118  * single increment.
119  */
121 {
122  if(!current_is_known_) {
123  // Either *this has never been dereferenced, or we already incremented
124  // since the last dereference. We are allowed to ignore this increment.
125  return *this;
126  }
127 
128  // Guarantee a different element next dereference.
129  if(main_is_current_) {
130  ++main_it_;
131  } else {
132  ++var_it_; // (We'll check for a name match when we dereference.)
133  }
134 
135  // We no longer know which list is current.
136  current_is_known_ = false;
137 
138  // Done.
139  return *this;
140 }
141 
142 /**
143  * Dereference
144  * Will return a null pointer when the end of the iteration is reached.
145  */
147 {
148  // Get the candidate for the current element from the main list.
149  handler_ptr main_ptr = *main_it_;
150  handler_vec::size_type main_index = ptr_index(main_ptr);
151 
152  // Get the candidate for the current element from the var list.
153  handler_ptr var_ptr = *var_it_;
154 
155  // (Loop while var_ptr would be chosen over main_ptr, but the name does not match.)
156  while(var_ptr && var_ptr->index() < main_index && !var_ptr->matches_name(event_name_, gamedata_)) {
157  var_ptr = *++var_it_;
158  }
159 
160  handler_vec::size_type var_index = ptr_index(var_ptr);
161 
162  // Which list? (Index ties go to the main list.)
163  current_is_known_ = main_index < end_ || var_index < end_;
164  main_is_current_ = main_index <= var_index;
165 
166  if(!current_is_known_) {
167  return nullptr; // End of list; return a null pointer.
168  }
169 
170  return main_is_current_ ? main_ptr : var_ptr;
171 }
172 
174 {
175  if(!type.empty()) {
176  if(std::find(unit_wml_ids_.begin(), unit_wml_ids_.end(), type) != unit_wml_ids_.end()) {
177  return;
178  }
179 
180  unit_wml_ids_.insert(type);
181  }
182 
183  for(const config& new_ev : cfgs) {
184  if(type.empty() && new_ev["id"].empty()) {
185  WRN_NG << "attempt to add an [event] with empty id=, ignoring " << std::endl;
186  continue;
187  }
188 
189  add_event_handler(new_ev);
190  }
191 }
192 
194 {
195  for(const handler_ptr& eh : event_handlers_->get_active()) {
196  if(!eh || eh->is_menu_item()) {
197  continue;
198  }
199 
200  cfg.add_child("event", eh->get_config());
201  }
202 
203  cfg["unit_wml_ids"] = utils::join(unit_wml_ids_);
205 }
206 
208 {
209  iteration iter(event_id, *this);
210 
211  while(handler_ptr hand = *iter) {
212  func(*this, hand);
213  ++iter;
214  }
215 }
216 
218 {
219  return *pump_;
220 }
221 
222 } // end namespace game_events
void remove_event_handler(const std::string &id)
Removes an event handler.
Definition: manager.cpp:51
std::vector< char_t > string
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
child_itors child_range(config_key_type key)
Definition: config.cpp:295
void write_events(config &cfg) const
Definition: manager.cpp:193
std::vector< std::string > split(const std::string &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
game_data * gamedata
Definition: resources.cpp:22
void read_scenario(const config &scenario_cfg)
Definition: manager.cpp:72
#define WRN_NG
Definition: manager.cpp:37
game_events::wmi_manager wml_menu_items_
Definition: manager.hpp:109
std::set< std::string > unit_wml_ids_
Definition: manager.hpp:106
const handler_ptr get_event_handler_by_id(const std::string &id)
Gets an event handler by ID.
Definition: manager.cpp:57
std::function< void(game_events::manager &, handler_ptr &)> event_func_t
Definition: manager.hpp:132
void set_menu_items(const config &cfg)
Sets the current menu items to the "menu_item" children of cfg.
const std::unique_ptr< event_handlers > event_handlers_
Definition: manager.hpp:105
void to_config(config &cfg) const
boost::iterator_range< const_child_iterator > const_child_itors
Definition: config.hpp:236
Domain specific events.
Definition: action_wml.cpp:88
size_t size(const utf8::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
const std::unique_ptr< game_events::wml_event_pump > pump_
Definition: manager.hpp:108
void add_event_handler(const config &handler, bool is_menu_item=false)
Create an event handler.
Definition: manager.cpp:45
Define the game's event mechanism.
CURSOR_TYPE get()
Definition: cursor.cpp:194
std::shared_ptr< event_handler > handler_ptr
Shared pointer to handler objects.
Definition: handlers.hpp:40
The game event manager loads the scenario configuration object, and ensures that events are handled a...
Definition: manager.hpp:45
This class is similar to an input iterator through event handlers, except each instance knows its own...
Definition: manager.hpp:61
config & add_child(config_key_type key)
Definition: config.cpp:408
iteration(const std::string &event_name, manager &)
Event-specific constructor.
Definition: manager.cpp:100
Define the handlers for the game's events mechanism.
handler_ptr operator*()
Dereference Will return a null pointer when the end of the iteration is reached.
Definition: manager.cpp:146
bool find(E event, F functor)
Tests whether an event handler is available.
Standard logging facilities (interface).
void init_handlers() const
Initializes the implicit event handlers for inlined [command]s.
iteration & operator++()
Increment Incrementing guarantees that the next dereference will differ from the previous derference ...
Definition: manager.cpp:120
game_events::wml_event_pump & pump()
Definition: manager.cpp:217
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
static lg::log_domain log_engine("engine")
void execute_on_events(const std::string &event_id, event_func_t func)
Definition: manager.cpp:207
void add_events(const config::const_child_itors &cfgs, const std::string &type=std::string())
Definition: manager.cpp:173
static lg::log_domain log_event_handler("event_handler")