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 "log.hpp"
23 #include "resources.hpp"
25 
26 #include <iostream>
27 
28 static lg::log_domain log_engine("engine");
29 #define DBG_NG LOG_STREAM(debug, log_engine)
30 #define LOG_NG LOG_STREAM(info, log_engine)
31 #define WRN_NG LOG_STREAM(warn, log_engine)
32 
33 static lg::log_domain log_event_handler("event_handler");
34 #define DBG_EH LOG_STREAM(debug, log_event_handler)
35 
36 namespace game_events
37 {
38 /** Create an event handler. */
39 void manager::add_event_handler(const config& handler, bool is_menu_item)
40 {
41  event_handlers_->add_event_handler(handler, is_menu_item);
42 }
43 
44 /** Removes an event handler. */
46 {
47  event_handlers_->remove_event_handler(id);
48 }
49 
50 /** Gets an event handler by id */
52 {
53  return event_handlers_->get_event_handler_by_id(id);
54 }
55 
56 /* ** manager ** */
57 
59  : event_handlers_(new event_handlers())
60  , unit_wml_ids_()
61  , pump_(new game_events::wml_event_pump(*this))
62  , wml_menu_items_()
63 {
64 }
65 
66 void manager::read_scenario(const config& scenario_cfg)
67 {
68  for(const config& ev : scenario_cfg.child_range("event")) {
70  }
71 
72  for(const std::string& id : utils::split(scenario_cfg["unit_wml_ids"])) {
73  unit_wml_ids_.insert(id);
74  }
75 
76  wml_menu_items_.set_menu_items(scenario_cfg);
77 
78  // Create the event handlers for menu items.
80 }
81 
83 {
84 }
85 
86 /* ** manager::iteration ** */
87 
88 /**
89  * Event-specific constructor.
90  * This iteration will go through all event handlers matching the given name
91  * (including those defined via menu items).
92  * An empty @a event_name will automatically match nothing.
93  */
95  : main_list_(man.event_handlers_->get(event_name))
96  , var_list_(man.event_handlers_->get_dynamic())
97  , event_name_(event_name)
98  , current_is_known_(false)
99  , main_is_current_(false)
100  , main_it_(main_list_.begin())
101  , var_it_(event_name.empty() ? var_list_.end() : var_list_.begin())
102  , gamedata_(resources::gamedata)
103 {
104 }
105 
106 /**
107  * Increment
108  * Incrementing guarantees that the next dereference will differ from the
109  * previous dereference (unless the iteration is exhausted). However, multiple
110  * increments between dereferences are allowed to have the same effect as a
111  * single increment.
112  */
114 {
115  if(!current_is_known_) {
116  // Either *this has never been dereferenced, or we already incremented
117  // since the last dereference. We are allowed to ignore this increment.
118  return *this;
119  }
120 
121  // Guarantee a different element next dereference.
122  if(main_is_current_) {
123  ++main_it_;
124  } else {
125  ++var_it_; // (We'll check for a name match when we dereference.)
126  }
127 
128  // We no longer know which list is current.
129  current_is_known_ = false;
130 
131  // Done.
132  return *this;
133 }
134 
135 // Small helper function to ensure we don't try to dereference an invalid iterator.
137 {
138  if(iter != list.end()) {
139  if(handler_ptr ptr = iter->lock()) {
140  return ptr;
141  }
142  }
143 
144  return nullptr;
145 }
146 
147 /**
148  * Dereference
149  * Will return a null pointer when the end of the iteration is reached.
150  */
152 {
153  // Get the candidate for the current element from the main list.
154  handler_ptr main_ptr = lock_ptr(main_list_, main_it_);
155 
156  // Get the candidate for the current element from the var list.
157  handler_ptr var_ptr = lock_ptr(var_list_, var_it_);
158 
159  // If we have a variable-name event but its name doesn't match event_name_,
160  // keep iterating until we find a match. If we reach var_list_ end var_ptr
161  // will be nullptr.
162  while(var_ptr && !var_ptr->matches_name(event_name_, gamedata_)) {
163  var_ptr = lock_ptr(var_list_, ++var_it_);
164  }
165 
166  // Are either of the handler ptrs valid?
167  current_is_known_ = main_ptr != nullptr || var_ptr != nullptr;
168 
169  // If var_ptr is invalid, we use the ptr from the main list.
170  main_is_current_ = var_ptr == nullptr;
171 
172  if(!current_is_known_) {
173  return nullptr; // End of list; return a null pointer.
174  }
175 
176  return main_is_current_ ? main_ptr : var_ptr;
177 }
178 
180 {
181  if(!type.empty()) {
182  if(std::find(unit_wml_ids_.begin(), unit_wml_ids_.end(), type) != unit_wml_ids_.end()) {
183  return;
184  }
185 
186  unit_wml_ids_.insert(type);
187  }
188 
189  for(const config& new_ev : cfgs) {
190  if(type.empty() && new_ev["id"].empty()) {
191  WRN_NG << "attempt to add an [event] with empty id=, ignoring " << std::endl;
192  continue;
193  }
194 
195  add_event_handler(new_ev);
196  }
197 }
198 
200 {
201  for(const handler_ptr& eh : event_handlers_->get_active()) {
202  if(!eh || eh->is_menu_item()) {
203  continue;
204  }
205 
206  cfg.add_child("event", eh->get_config());
207  }
208 
209  cfg["unit_wml_ids"] = utils::join(unit_wml_ids_);
211 }
212 
214 {
215  iteration iter(event_id, *this);
216 
217  while(handler_ptr hand = *iter) {
218  func(*this, hand);
219  ++iter;
220  }
221 
222  // Clean up expired ptrs. This saves us effort later since it ensures every ptr is valid.
223  event_handlers_->clean_up_expired_handlers(event_id);
224 }
225 
227 {
228  return *pump_;
229 }
230 
231 } // end namespace game_events
void remove_event_handler(const std::string &id)
Removes an event handler.
Definition: manager.cpp:45
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:343
void write_events(config &cfg) const
Definition: manager.cpp:199
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:66
#define WRN_NG
Definition: manager.cpp:31
game_events::wmi_manager wml_menu_items_
Definition: manager.hpp:94
std::set< std::string > unit_wml_ids_
Definition: manager.hpp:91
const handler_ptr get_event_handler_by_id(const std::string &id)
Gets an event handler by ID.
Definition: manager.cpp:51
std::function< void(game_events::manager &, handler_ptr &)> event_func_t
Definition: manager.hpp:117
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:90
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
const std::unique_ptr< game_events::wml_event_pump > pump_
Definition: manager.hpp:93
void add_event_handler(const config &handler, bool is_menu_item=false)
Create an event handler.
Definition: manager.cpp:39
Define the game's event mechanism.
CURSOR_TYPE get()
Definition: cursor.cpp:194
The game event manager loads the scenario configuration object, and ensures that events are handled a...
Definition: manager.hpp:43
This class is similar to an input iterator through event handlers, except each instance knows its own...
Definition: manager.hpp:59
config & add_child(config_key_type key)
Definition: config.cpp:456
iteration(const std::string &event_name, manager &)
Event-specific constructor.
Definition: manager.cpp:94
std::list< weak_handler_ptr > handler_list
Definition: fwd.hpp:26
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:151
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 dereference...
Definition: manager.cpp:113
game_events::wml_event_pump & pump()
Definition: manager.cpp:226
std::shared_ptr< event_handler > handler_ptr
Definition: fwd.hpp:24
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:213
void add_events(const config::const_child_itors &cfgs, const std::string &type=std::string())
Definition: manager.cpp:179
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
static lg::log_domain log_event_handler("event_handler")
static handler_ptr lock_ptr(const handler_list &list, handler_list::iterator iter)
Definition: manager.cpp:136