00001 // Filename: buttonThrower.cxx 00002 // Created by: drose (12Mar02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "buttonThrower.h" 00020 00021 #include "buttonEvent.h" 00022 #include "buttonEventList.h" 00023 #include "dataNodeTransmit.h" 00024 #include "throw_event.h" 00025 #include "event.h" 00026 #include "indent.h" 00027 #include "dcast.h" 00028 00029 TypeHandle ButtonThrower::_type_handle; 00030 00031 00032 //////////////////////////////////////////////////////////////////// 00033 // Function: ButtonThrower::Constructor 00034 // Access: Public 00035 // Description: 00036 //////////////////////////////////////////////////////////////////// 00037 ButtonThrower:: 00038 ButtonThrower(const string &name) : 00039 DataNode(name) 00040 { 00041 _button_events_input = define_input("button_events", ButtonEventList::get_class_type()); 00042 _button_events_output = define_output("button_events", ButtonEventList::get_class_type()); 00043 00044 _button_events = new ButtonEventList; 00045 00046 _throw_buttons_active = false; 00047 } 00048 00049 //////////////////////////////////////////////////////////////////// 00050 // Function: ButtonThrower::Destructor 00051 // Access: Published, Virtual 00052 // Description: 00053 //////////////////////////////////////////////////////////////////// 00054 ButtonThrower:: 00055 ~ButtonThrower() { 00056 } 00057 00058 00059 //////////////////////////////////////////////////////////////////// 00060 // Function: ButtonThrower::set_prefix 00061 // Access: Published 00062 // Description: Sets the prefix which is prepended to all event names 00063 // thrown by this object. 00064 //////////////////////////////////////////////////////////////////// 00065 void ButtonThrower:: 00066 set_prefix(const string &prefix) { 00067 _prefix = prefix; 00068 } 00069 00070 00071 //////////////////////////////////////////////////////////////////// 00072 // Function: ButtonThrower::has_prefix 00073 // Access: Published 00074 // Description: Returns true if the ButtonThrower has a prefix set, 00075 // false otherwise. 00076 //////////////////////////////////////////////////////////////////// 00077 bool ButtonThrower:: 00078 has_prefix() const { 00079 return !_prefix.empty(); 00080 } 00081 00082 //////////////////////////////////////////////////////////////////// 00083 // Function: ButtonThrower::get_prefix 00084 // Access: Published 00085 // Description: Returns the prefix that has been set on this 00086 // ButtonThrower. See set_prefix(). 00087 //////////////////////////////////////////////////////////////////// 00088 string ButtonThrower:: 00089 get_prefix() const { 00090 return _prefix; 00091 } 00092 00093 //////////////////////////////////////////////////////////////////// 00094 // Function: ButtonThrower::add_parameter 00095 // Access: Public 00096 // Description: Adds the indicated parameter to the list of 00097 // parameters that will be passed with each event 00098 // generated by this ButtonThrower. 00099 //////////////////////////////////////////////////////////////////// 00100 void ButtonThrower:: 00101 add_parameter(const EventParameter &obj) { 00102 _parameters.push_back(obj); 00103 } 00104 00105 00106 //////////////////////////////////////////////////////////////////// 00107 // Function: ButtonThrower::get_num_parameters 00108 // Access: Public 00109 // Description: Returns the number of parameters that have been added 00110 // to the list of parameters to be passed with each 00111 // event generated by this ButtonThrower. 00112 //////////////////////////////////////////////////////////////////// 00113 int ButtonThrower:: 00114 get_num_parameters() const { 00115 return _parameters.size(); 00116 } 00117 00118 //////////////////////////////////////////////////////////////////// 00119 // Function: ButtonThrower::get_parameter 00120 // Access: Public 00121 // Description: Returns the nth parameter that has been added to the 00122 // list of parameters passed with each event generated 00123 // by this ButtonThrower. 00124 //////////////////////////////////////////////////////////////////// 00125 EventParameter ButtonThrower:: 00126 get_parameter(int n) const { 00127 nassertr(n >= 0 && n < (int)_parameters.size(), EventParameter(0)); 00128 return _parameters[n]; 00129 } 00130 00131 //////////////////////////////////////////////////////////////////// 00132 // Function: ButtonThrower::get_modifier_buttons 00133 // Access: Published 00134 // Description: Returns the set of ModifierButtons that the 00135 // ButtonThrower will consider important enough to 00136 // prepend the event name with. Normally, this set will 00137 // be empty, and the ButtonThrower will therefore ignore 00138 // all ModifierButtons attached to the key events, but 00139 // if one or more buttons have been added to this set, 00140 // and those modifier buttons are set on the button 00141 // event, then the event name will be prepended with the 00142 // names of the modifier buttons. 00143 //////////////////////////////////////////////////////////////////// 00144 const ModifierButtons &ButtonThrower:: 00145 get_modifier_buttons() const { 00146 return _mods; 00147 } 00148 00149 //////////////////////////////////////////////////////////////////// 00150 // Function: ButtonThrower::set_modifier_buttons 00151 // Access: Published 00152 // Description: Changes the set of ModifierButtons that the 00153 // ButtonThrower will consider important enough to 00154 // prepend the event name with. Normally, this set will 00155 // be empty, and the ButtonThrower will therefore ignore 00156 // all ModifierButtons attached to the key events, but 00157 // if one or more buttons have been added to this set, 00158 // then the event name will be prepended with the names 00159 // of the modifier buttons. 00160 // 00161 // It is recommended that you change this setting by 00162 // first calling get_modifier_buttons(), making 00163 // adjustments, and passing the new value to 00164 // set_modifier_buttons(). This way the current state 00165 // of the modifier buttons will not be lost. 00166 //////////////////////////////////////////////////////////////////// 00167 void ButtonThrower:: 00168 set_modifier_buttons(const ModifierButtons &mods) { 00169 _mods = mods; 00170 } 00171 00172 //////////////////////////////////////////////////////////////////// 00173 // Function: ButtonThrower::set_throw_buttons_active 00174 // Access: Published 00175 // Description: Sets the flag that indicates whether the 00176 // ButtonThrower will only process events for the 00177 // explicitly named buttons or not. Normally this is 00178 // false, meaning all buttons are processed; set it true 00179 // to indicate that only some buttons should be 00180 // processed. See add_throw_button(). 00181 //////////////////////////////////////////////////////////////////// 00182 void ButtonThrower:: 00183 set_throw_buttons_active(bool flag) { 00184 _throw_buttons_active = flag; 00185 } 00186 00187 //////////////////////////////////////////////////////////////////// 00188 // Function: ButtonThrower::get_throw_buttons_active 00189 // Access: Published 00190 // Description: Returns the flag that indicates whether the 00191 // ButtonThrower will only process events for the 00192 // explicitly named buttons or not. See 00193 // set_throw_buttons_active(). 00194 //////////////////////////////////////////////////////////////////// 00195 bool ButtonThrower:: 00196 get_throw_buttons_active() const { 00197 return _throw_buttons_active; 00198 } 00199 00200 //////////////////////////////////////////////////////////////////// 00201 // Function: ButtonThrower::add_throw_button 00202 // Access: Published 00203 // Description: Adds a new button to the set of buttons that the 00204 // ButtonThrower explicitly processes. 00205 // 00206 // If set_throw_buttons_active is false (which is the 00207 // default), the ButtonThrower will process all buttons. 00208 // Otherwise, the ButtonThrower will only process events 00209 // for the button(s) explicitly named by this function; 00210 // buttons not on the list will be ignored by this 00211 // object and passed on downstream to the child node(s) 00212 // in the data graph. A button that *is* on the list 00213 // will be processed by the ButtonThrower and not passed 00214 // on to the child node(s). 00215 // 00216 // The return value is true if the button is added, or 00217 // false if it was already in the set. 00218 //////////////////////////////////////////////////////////////////// 00219 bool ButtonThrower:: 00220 add_throw_button(const ModifierButtons &mods, const ButtonHandle &button) { 00221 ThrowButtonDef &def = _throw_buttons[button]; 00222 00223 // This is a vector of ModifierButtons for which the indicated 00224 // button is handled. Make sure the current ModifierButtons object 00225 // is not already on the list. 00226 ThrowButtonDef::iterator di; 00227 for (di = def.begin(); di != def.end(); ++di) { 00228 if (mods.matches(*di)) { 00229 return false; 00230 } 00231 } 00232 00233 def.push_back(mods); 00234 return true; 00235 } 00236 00237 //////////////////////////////////////////////////////////////////// 00238 // Function: ButtonThrower::remove_throw_button 00239 // Access: Published 00240 // Description: Removes the indicated button from the set of buttons 00241 // that the ButtonThrower explicitly processes. See 00242 // add_throw_button(). 00243 // 00244 // The return value is true if the button is removed, or 00245 // false if it was not on the set. 00246 //////////////////////////////////////////////////////////////////// 00247 bool ButtonThrower:: 00248 remove_throw_button(const ModifierButtons &mods, const ButtonHandle &button) { 00249 ThrowButtons::iterator ti = _throw_buttons.find(button); 00250 if (ti == _throw_buttons.end()) { 00251 // No buttons of this kind are in the set. 00252 return false; 00253 } 00254 00255 ThrowButtonDef &def = (*ti).second; 00256 00257 // This is a vector of ModifierButtons for which the indicated 00258 // button is handled. 00259 ThrowButtonDef::iterator di; 00260 for (di = def.begin(); di != def.end(); ++di) { 00261 if (mods.matches(*di)) { 00262 def.erase(di); 00263 if (def.empty()) { 00264 _throw_buttons.erase(ti); 00265 } 00266 return true; 00267 } 00268 } 00269 00270 // The indicated ModifierButtons are not applied to this button in 00271 // the set. 00272 return false; 00273 } 00274 00275 //////////////////////////////////////////////////////////////////// 00276 // Function: ButtonThrower::has_throw_button 00277 // Access: Published 00278 // Description: Returns true if the indicated button is on the set of 00279 // buttons that will be processed by the ButtonThrower, 00280 // false otherwise. See add_throw_button(). 00281 //////////////////////////////////////////////////////////////////// 00282 bool ButtonThrower:: 00283 has_throw_button(const ModifierButtons &mods, const ButtonHandle &button) const { 00284 ThrowButtons::const_iterator ti = _throw_buttons.find(button); 00285 if (ti == _throw_buttons.end()) { 00286 // No buttons of this kind are in the set. 00287 return false; 00288 } 00289 00290 const ThrowButtonDef &def = (*ti).second; 00291 00292 // This is a vector of ModifierButtons for which the indicated 00293 // button is handled. 00294 ThrowButtonDef::const_iterator di; 00295 for (di = def.begin(); di != def.end(); ++di) { 00296 if (mods.matches(*di)) { 00297 return true; 00298 } 00299 } 00300 00301 // The indicated ModifierButtons are not applied to this button in 00302 // the set. 00303 return false; 00304 } 00305 00306 //////////////////////////////////////////////////////////////////// 00307 // Function: ButtonThrower::has_throw_button 00308 // Access: Published 00309 // Description: Returns true if the indicated button, in conjunction 00310 // with any nonspecified modifier buttons, is on the set 00311 // of buttons that will be processed by the 00312 // ButtonThrower. That is to say, returns true if this 00313 // button was ever passed as the second parameter 00314 // add_throw_button(), regardless of what the first 00315 // parameter was. 00316 //////////////////////////////////////////////////////////////////// 00317 bool ButtonThrower:: 00318 has_throw_button(const ButtonHandle &button) const { 00319 ThrowButtons::const_iterator ti = _throw_buttons.find(button); 00320 if (ti == _throw_buttons.end()) { 00321 // No buttons of this kind are in the set. 00322 return false; 00323 } 00324 00325 const ThrowButtonDef &def = (*ti).second; 00326 return !def.empty(); 00327 } 00328 00329 //////////////////////////////////////////////////////////////////// 00330 // Function: ButtonThrower::clear_throw_buttons 00331 // Access: Published 00332 // Description: Empties the set of buttons that were added via 00333 // add_throw_button(). See add_throw_button(). 00334 //////////////////////////////////////////////////////////////////// 00335 void ButtonThrower:: 00336 clear_throw_buttons() { 00337 _throw_buttons.clear(); 00338 } 00339 00340 //////////////////////////////////////////////////////////////////// 00341 // Function: ButtonThrower::write 00342 // Access: Public, Virtual 00343 // Description: Throw all events for button events found in the data 00344 // element. 00345 //////////////////////////////////////////////////////////////////// 00346 void ButtonThrower:: 00347 write(ostream &out, int indent_level) const { 00348 DataNode::write(out, indent_level); 00349 if (_throw_buttons_active) { 00350 indent(out, indent_level) 00351 << "Processing keys:\n"; 00352 // Write the list of buttons that we're processing too. 00353 ThrowButtons::const_iterator ti; 00354 for (ti = _throw_buttons.begin(); ti != _throw_buttons.end(); ++ti) { 00355 ButtonHandle button = (*ti).first; 00356 const ThrowButtonDef &def = (*ti).second; 00357 ThrowButtonDef::const_iterator di; 00358 for (di = def.begin(); di != def.end(); ++di) { 00359 indent(out, indent_level + 2) 00360 << (*di).get_prefix() << button.get_name() << "\n"; 00361 } 00362 } 00363 } 00364 } 00365 00366 //////////////////////////////////////////////////////////////////// 00367 // Function: ButtonThrower::do_throw_event 00368 // Access: Private 00369 // Description: Generates an event of the indicated name, adding on 00370 // all of the user-requested parameters. 00371 //////////////////////////////////////////////////////////////////// 00372 void ButtonThrower:: 00373 do_throw_event(const string &event_name) { 00374 Event *event = new Event(_prefix + event_name); 00375 00376 ParameterList::const_iterator pi; 00377 for (pi = _parameters.begin(); pi != _parameters.end(); ++pi) { 00378 event->add_parameter(*pi); 00379 } 00380 00381 throw_event(event); 00382 } 00383 00384 //////////////////////////////////////////////////////////////////// 00385 // Function: ButtonThrower::do_transmit_data 00386 // Access: Protected, Virtual 00387 // Description: The virtual implementation of transmit_data(). This 00388 // function receives an array of input parameters and 00389 // should generate an array of output parameters. The 00390 // input parameters may be accessed with the index 00391 // numbers returned by the define_input() calls that 00392 // were made earlier (presumably in the constructor); 00393 // likewise, the output parameters should be set with 00394 // the index numbers returned by the define_output() 00395 // calls. 00396 //////////////////////////////////////////////////////////////////// 00397 void ButtonThrower:: 00398 do_transmit_data(const DataNodeTransmit &input, DataNodeTransmit &output) { 00399 // Clear our outgoing button events. We'll fill it up again with 00400 // just those events that want to carry on. 00401 _button_events->clear(); 00402 00403 if (input.has_data(_button_events_input)) { 00404 const ButtonEventList *button_events; 00405 DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_ptr()); 00406 00407 int num_events = button_events->get_num_events(); 00408 for (int i = 0; i < num_events; i++) { 00409 const ButtonEvent &be = button_events->get_event(i); 00410 string event_name = be._button.get_name(); 00411 00412 if (be._type == ButtonEvent::T_down) { 00413 // Button down. 00414 if (!_mods.button_down(be._button)) { 00415 // We only prepend modifier names on the button-down events, 00416 // and only for buttons which are not themselves modifiers. 00417 event_name = _mods.get_prefix() + event_name; 00418 } 00419 00420 if (!_throw_buttons_active || has_throw_button(_mods, be._button)) { 00421 // Process this button. 00422 do_throw_event(event_name); 00423 00424 } else { 00425 // Don't process this button; instead, pass it down to future 00426 // generations. 00427 _button_events->add_event(be); 00428 } 00429 00430 } else if (be._type == ButtonEvent::T_resume_down) { 00431 // Button resume down. The button was pressed at some earlier 00432 // time, and the event was only just now detected. Don't 00433 // throw an event now (since we already missed it), but do 00434 // make sure our modifiers are up-to-date. 00435 _mods.button_down(be._button); 00436 00437 } else if (be._type == ButtonEvent::T_up) { 00438 // Button up. 00439 _mods.button_up(be._button); 00440 00441 // We always throw button "up" events if we have any 00442 // definition for the button at all, regardless of the state 00443 // of the modifier keys. 00444 if (!_throw_buttons_active || has_throw_button(be._button)) { 00445 do_throw_event(event_name + "-up"); 00446 } 00447 if (_throw_buttons_active) { 00448 // Now pass the event on to future generations. We always 00449 // pass "up" events, even if we are intercepting this 00450 // particular button; unless we're processing all buttons in 00451 // which case it doesn't matter. 00452 _button_events->add_event(be); 00453 } 00454 00455 } else { 00456 // Some other kind of button event (e.g. keypress). Don't 00457 // throw an event for this, but do pass it down. 00458 _button_events->add_event(be); 00459 } 00460 } 00461 } 00462 00463 output.set_data(_button_events_output, EventParameter(_button_events)); 00464 }