Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/putil/modifierButtons.cxx

Go to the documentation of this file.
00001 // Filename: modifierButtons.cxx
00002 // Created by:  drose (01Mar00)
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 "modifierButtons.h"
00020 
00021 #include <notify.h>
00022 
00023 ////////////////////////////////////////////////////////////////////
00024 //     Function: ModifierButtons::Constructor
00025 //       Access: Published
00026 //  Description:
00027 ////////////////////////////////////////////////////////////////////
00028 ModifierButtons::
00029 ModifierButtons() :
00030   _state(0)
00031 {
00032    _button_list= PTA(ButtonHandle)::empty_array(0);
00033 }
00034 
00035 ////////////////////////////////////////////////////////////////////
00036 //     Function: ModifierButtons::Copy Constructor
00037 //       Access: Published
00038 //  Description:
00039 ////////////////////////////////////////////////////////////////////
00040 ModifierButtons::
00041 ModifierButtons(const ModifierButtons &copy) :
00042   _button_list(copy._button_list),
00043   _state(copy._state)
00044 {
00045 }
00046 
00047 ////////////////////////////////////////////////////////////////////
00048 //     Function: ModifierButtons::Destructor
00049 //       Access: Published
00050 //  Description:
00051 ////////////////////////////////////////////////////////////////////
00052 ModifierButtons::
00053 ~ModifierButtons() {
00054 }
00055 
00056 ////////////////////////////////////////////////////////////////////
00057 //     Function: ModifierButtons::matches
00058 //       Access: Published
00059 //  Description: Returns true if the set of buttons indicated as down
00060 //               by this ModifierButtons object is the same set of
00061 //               buttons indicated as down by the other
00062 //               ModifierButtons object.  The buttons indicated as up
00063 //               are not relevant.
00064 ////////////////////////////////////////////////////////////////////
00065 bool ModifierButtons::
00066 matches(const ModifierButtons &other) const {
00067   if (_button_list == other._button_list) {
00068     // If the two objects share the same array, we only need to check
00069     // the bitmask.  This is a simple optimization.
00070     return (_state == other._state);
00071   }
00072 
00073   // The two objects do not share the same array; thus we have to do
00074   // this one button at a time.  This is an n-squared operation, but
00075   // presumably there will not be hundreds of buttons to compare.
00076 
00077   // First, check that all the buttons indicated as down in our object
00078   // are also indicated as down in the other object.
00079   int num_down = 0;
00080 
00081   int i;
00082   for (i = 0; i < (int)_button_list.size(); i++) {
00083     if (is_down(i)) {
00084       if (!other.is_down(_button_list[i])) {
00085         return false;
00086       }
00087       num_down++;
00088     }
00089   }
00090 
00091   // Now make sure the total number of buttons indicated as down in
00092   // our object matches the number indicated as down in the other
00093   // object.  This ensures there aren't any additional buttons
00094   // indicated down in the other object.
00095   int num_other_buttons = other.get_num_buttons();
00096   int num_other_down = 0;
00097   for (i = 0; i < num_other_buttons; i++) {
00098     if (other.is_down(i)) {
00099       num_other_down++;
00100     }
00101   }
00102 
00103   return (num_down == num_other_down);
00104 }
00105 
00106 ////////////////////////////////////////////////////////////////////
00107 //     Function: ModifierButtons::add_button
00108 //       Access: Published
00109 //  Description: Adds the indicated button to the set of buttons that
00110 //               will be monitored for upness and downness.  Returns
00111 //               true if the button was added, false if it was already
00112 //               being monitored or if too many buttons are currently
00113 //               being monitored.
00114 ////////////////////////////////////////////////////////////////////
00115 bool ModifierButtons::
00116 add_button(ButtonHandle button) {
00117   nassertr(button != ButtonHandle::none(), false);
00118 
00119   static const int max_buttons = sizeof(BitmaskType) * 8;
00120 
00121   if ((int)_button_list.size() >= max_buttons) {
00122     return false;
00123   }
00124 
00125   // First, check to see if the button is already being monitored.
00126   if (has_button(button)) {
00127     return false;
00128   }
00129 
00130   // Ok, it's not; add it.
00131   modify_button_list();
00132   _button_list.push_back(button);
00133 
00134   return true;
00135 }
00136 
00137 ////////////////////////////////////////////////////////////////////
00138 //     Function: ModifierButtons::has_button
00139 //       Access: Published
00140 //  Description: Returns true if the indicated button is in the set of
00141 //               buttons being monitored, false otherwise.
00142 ////////////////////////////////////////////////////////////////////
00143 bool ModifierButtons::
00144 has_button(ButtonHandle button) const {
00145   PTA(ButtonHandle)::const_iterator bi;
00146   for (bi = _button_list.begin(); bi != _button_list.end(); ++bi) {
00147     if (button == (*bi)) {
00148       return true;
00149     }
00150   }
00151 
00152   return false;
00153 }
00154 
00155 ////////////////////////////////////////////////////////////////////
00156 //     Function: ModifierButtons::remove_button
00157 //       Access: Published
00158 //  Description: Removes the indicated button from the set of buttons
00159 //               being monitored.  Returns true if the button was
00160 //               removed, false if it was not being monitored in the
00161 //               first place.
00162 ////////////////////////////////////////////////////////////////////
00163 bool ModifierButtons::
00164 remove_button(ButtonHandle button) {
00165   // We use i instead of an iterator, because we need to call
00166   // modify_button_list() just before we remove the button, and that
00167   // may invalidate all of the iterators.
00168 
00169   for (int i = 0; i < (int)_button_list.size(); i++) {
00170     if (button == _button_list[i]) {
00171       modify_button_list();
00172       _button_list.erase(_button_list.begin() + i);
00173 
00174       // Now remove the corresponding bit from the bitmask and shift
00175       // all the bits above it down.
00176       BitmaskType mask = ((BitmaskType)1 << i);
00177       BitmaskType below = mask - 1;
00178       BitmaskType above = (~below) & (~mask);
00179 
00180       _state = ((_state & above) >> 1) | (_state & below);
00181       return true;
00182     }
00183   }
00184 
00185   return false;
00186 }
00187 
00188 ////////////////////////////////////////////////////////////////////
00189 //     Function: ModifierButtons::button_down
00190 //       Access: Published
00191 //  Description: Records that a particular button has been pressed.
00192 //               If the given button is one of the buttons that is
00193 //               currently being monitored, this will update the
00194 //               internal state appropriately; otherwise, it will do
00195 //               nothing.  Returns true if the button is one that was
00196 //               monitored, or false otherwise.
00197 ////////////////////////////////////////////////////////////////////
00198 bool ModifierButtons::
00199 button_down(ButtonHandle button) {
00200   for (int i = 0; i < (int)_button_list.size(); i++) {
00201     if (button == _button_list[i]) {
00202       _state |= ((BitmaskType)1 << i);
00203       return true;
00204     }
00205   }
00206 
00207   return false;
00208 }
00209 
00210 ////////////////////////////////////////////////////////////////////
00211 //     Function: ModifierButtons::button_up
00212 //       Access: Published
00213 //  Description: Records that a particular button has been released.
00214 //               If the given button is one of the buttons that is
00215 //               currently being monitored, this will update the
00216 //               internal state appropriately; otherwise, it will do
00217 //               nothing.  Returns true if the button is one that was
00218 //               monitored, or false otherwise.
00219 ////////////////////////////////////////////////////////////////////
00220 bool ModifierButtons::
00221 button_up(ButtonHandle button) {
00222   for (int i = 0; i < (int)_button_list.size(); i++) {
00223     if (button == _button_list[i]) {
00224       _state &= ~((BitmaskType)1 << i);
00225       return true;
00226     }
00227   }
00228 
00229   return false;
00230 }
00231 
00232 ////////////////////////////////////////////////////////////////////
00233 //     Function: ModifierButtons::is_down
00234 //       Access: Published
00235 //  Description: Returns true if the indicated button is known to be
00236 //               down, or false if it is known to be up or if it is
00237 //               not in the set of buttons being tracked.
00238 ////////////////////////////////////////////////////////////////////
00239 bool ModifierButtons::
00240 is_down(ButtonHandle button) const {
00241   for (int i = 0; i < (int)_button_list.size(); i++) {
00242     if (button == _button_list[i]) {
00243       return ((_state & ((BitmaskType)1 << i)) != 0);
00244     }
00245   }
00246 
00247   return false;
00248 }
00249 
00250 ////////////////////////////////////////////////////////////////////
00251 //     Function: ModifierButtons::get_prefix
00252 //       Access: Published
00253 //  Description: Returns a string which can be used to prefix any
00254 //               button name or event name with the unique set of
00255 //               modifier buttons currently being held.
00256 ////////////////////////////////////////////////////////////////////
00257 string ModifierButtons::
00258 get_prefix() const {
00259   string prefix;
00260   for (int i = 0; i < (int)_button_list.size(); i++) {
00261     if ((_state & ((BitmaskType)1 << i)) != 0) {
00262       prefix += _button_list[i].get_name();
00263       prefix += '-';
00264     }
00265   }
00266 
00267   return prefix;
00268 }
00269 
00270 ////////////////////////////////////////////////////////////////////
00271 //     Function: ModifierButtons::output
00272 //       Access: Published
00273 //  Description: Writes a one-line summary of the buttons known to be
00274 //               down.
00275 ////////////////////////////////////////////////////////////////////
00276 void ModifierButtons::
00277 output(ostream &out) const {
00278   out << "[";
00279   for (int i = 0; i < (int)_button_list.size(); i++) {
00280     if ((_state & ((BitmaskType)1 << i)) != 0) {
00281       out << " " << _button_list[i];
00282     }
00283   }
00284   out << " ]";
00285 }
00286 
00287 ////////////////////////////////////////////////////////////////////
00288 //     Function: ModifierButtons::write
00289 //       Access: Published
00290 //  Description: Writes a multi-line summary including all of the
00291 //               buttons being monitored and which ones are known to
00292 //               be down.
00293 ////////////////////////////////////////////////////////////////////
00294 void ModifierButtons::
00295 write(ostream &out) const {
00296   out << "ModifierButtons:\n";
00297   for (int i = 0; i < (int)_button_list.size(); i++) {
00298     out << "  " << _button_list[i];
00299     if ((_state & ((BitmaskType)1 << i)) != 0) {
00300       out << " (down)";
00301     }
00302     out << "\n";
00303   }
00304 }
00305 
00306 ////////////////////////////////////////////////////////////////////
00307 //     Function: ModifierButtons::modify_button_list
00308 //       Access: Private
00309 //  Description: Implements a poor-man's copy-on-write for the
00310 //               ModifierButtons class.  If any reference counts are
00311 //               held on our _button_list, besides ourselves, then
00312 //               allocates and copies a brand new copy of the
00313 //               _button_list.  This should be done in preparation for
00314 //               any modifications to the _button_list, since multiple
00315 //               instances of the ModifierButtons object may share the
00316 //               same _button_list pointer.
00317 ////////////////////////////////////////////////////////////////////
00318 void ModifierButtons::
00319 modify_button_list() {
00320   if (_button_list.get_ref_count() > 1) {
00321     PTA(ButtonHandle) old_list = _button_list;
00322 
00323     _button_list = PTA(ButtonHandle)::empty_array(0);
00324 
00325     // This forces a new allocation and memberwise copy, instead of
00326     // just a reference-counting pointer copy.
00327     _button_list.v() = old_list.v();
00328   }
00329 
00330   // Now we should be the only ones holding a count.
00331   nassertv(_button_list.get_ref_count() == 1);
00332 }

Generated on Fri May 2 00:43:40 2003 for Panda by doxygen1.3