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