Panda3D

buttonThrower.cxx

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 }
 All Classes Functions Variables Enumerations