Kaynağa Gözat

selectively eat mouse/keyboard buttons with MouseWatcherRegions

David Rose 24 yıl önce
ebeveyn
işleme
86d1254c50

+ 10 - 10
panda/src/gui/guiButton.cxx

@@ -175,7 +175,7 @@ void GuiButton::switch_state(GuiButton::States nstate) {
   case NONE:
     if (_mgr->has_region(_rgn))
       _mgr->remove_region(_rgn);
-    _rgn->set_suppress_below(false);
+    _rgn->set_suppress_flags(0);
     break;
   case UP:
     if (!(_mgr->has_region(_rgn)))
@@ -199,7 +199,7 @@ void GuiButton::switch_state(GuiButton::States nstate) {
 #else /* _DEBUG */
     }
 #endif /* _DEBUG */
-    _rgn->set_suppress_below(true);
+    _rgn->set_suppress_flags(MouseWatcherRegion::SF_mouse_position);
     break;
   case UP_ROLLOVER:
     if (!(_mgr->has_region(_rgn)))
@@ -248,7 +248,7 @@ void GuiButton::switch_state(GuiButton::States nstate) {
 #endif /* _DEBUG */
       _state = UP;
     }
-    _rgn->set_suppress_below(true);
+    _rgn->set_suppress_flags(MouseWatcherRegion::SF_mouse_position);
     if ((ostate == UP) &&
     (_rollover_functor != (GuiBehavior::BehaviorFunctor*)0L))
       _rollover_functor->doit(this);
@@ -276,7 +276,7 @@ void GuiButton::switch_state(GuiButton::States nstate) {
 #else /* _DEBUG */
     }
 #endif /* _DEBUG */
-    _rgn->set_suppress_below(true);
+    _rgn->set_suppress_flags(MouseWatcherRegion::SF_mouse_position);
     break;
   case DOWN_ROLLOVER:
     if (!(_mgr->has_region(_rgn)))
@@ -325,7 +325,7 @@ void GuiButton::switch_state(GuiButton::States nstate) {
 #endif /* _DEBUG */
       _state = DOWN;
     }
-    _rgn->set_suppress_below(true);
+    _rgn->set_suppress_flags(MouseWatcherRegion::SF_mouse_position);
     break;
   case INACTIVE:
     if (_mgr->has_region(_rgn))
@@ -347,7 +347,7 @@ void GuiButton::switch_state(GuiButton::States nstate) {
     my_throw(_mgr, _inactive_event, paramthis);
       }
     }
-    _rgn->set_suppress_below(false);
+    _rgn->set_suppress_flags(0);
     break;
   case INACTIVE_ROLLOVER:
     if (_mgr->has_region(_rgn))
@@ -369,7 +369,7 @@ void GuiButton::switch_state(GuiButton::States nstate) {
     my_throw(_mgr, _inactive_event, paramthis);
       }
     }
-    _rgn->set_suppress_below(false);
+    _rgn->set_suppress_flags(0);
     break;
   default:
     gui_cat->warning() << "switched to invalid state (" << (int)_state << ")"
@@ -503,7 +503,7 @@ GuiButton::GuiButton(const string& name, GuiLabel* up, GuiLabel* down)
          _bottom, _top);
   _rgn = new MouseWatcherRegion("button-" + name, _left, _right, _bottom,
                 _top);
-  _rgn->set_suppress_below(true);
+  _rgn->set_suppress_flags(MouseWatcherRegion::SF_mouse_position);
   buttons[this->_rgn.p()] = this;
 }
 
@@ -523,7 +523,7 @@ GuiButton::GuiButton(const string& name, GuiLabel* up, GuiLabel* down,
          _bottom, _top);
   _rgn = new MouseWatcherRegion("button-" + name, _left, _right, _bottom,
                 _top);
-  _rgn->set_suppress_below(true);
+  _rgn->set_suppress_flags(MouseWatcherRegion::SF_mouse_position);
   buttons[this->_rgn.p()] = this;
 }
 
@@ -544,7 +544,7 @@ GuiButton::GuiButton(const string& name, GuiLabel* up, GuiLabel* up_roll,
          _top);
   _rgn = new MouseWatcherRegion("button-" + name, _left, _right, _bottom,
                 _top);
-  _rgn->set_suppress_below(true);
+  _rgn->set_suppress_flags(MouseWatcherRegion::SF_mouse_position);
   buttons[this->_rgn.p()] = this;
 }
 

+ 1 - 1
panda/src/gui/guiRollover.cxx

@@ -87,7 +87,7 @@ GuiRollover::GuiRollover(const string& name, GuiLabel* off, GuiLabel* on)
   GetExtents(off, on, _left, _right, _bottom, _top);
   _rgn = new MouseWatcherRegion("rollover-" + name, _left, _right, _bottom,
                                 _top);
-  _rgn->set_suppress_below(false);
+  _rgn->set_suppress_flags(0);
   rollovers[this->_rgn.p()] = this;
 }
 

+ 24 - 0
panda/src/pgui/pgItem.I

@@ -158,6 +158,30 @@ get_background_focus() const {
   return (_flags & F_background_focus) != 0;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PGItem::set_suppress_flags
+//       Access: Published
+//  Description: This is just an interface to set the suppress flags
+//               on the underlying MouseWatcherRegion.  See
+//               MouseWatcherRegion::set_suppress_flags().
+////////////////////////////////////////////////////////////////////
+INLINE void PGItem::
+set_suppress_flags(int suppress_flags) {
+  _region->set_suppress_flags(suppress_flags);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PGItem::get_suppress_flags
+//       Access: Published
+//  Description: This is just an interface to get the suppress flags
+//               on the underlying MouseWatcherRegion.  See
+//               MouseWatcherRegion::get_suppress_flags().
+////////////////////////////////////////////////////////////////////
+INLINE int PGItem::
+get_suppress_flags() const {
+  return _region->get_suppress_flags();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PGItem::get_id
 //       Access: Published

+ 3 - 0
panda/src/pgui/pgItem.h

@@ -102,6 +102,9 @@ PUBLISHED:
   void set_background_focus(bool focus);
   INLINE bool get_background_focus() const;
 
+  INLINE void set_suppress_flags(int suppress_flags);
+  INLINE int get_suppress_flags() const;
+
   int get_num_state_defs() const;
   void clear_state_def(int state);
   bool has_state_def(int state) const;

+ 1 - 1
panda/src/tform/mouseWatcher.I

@@ -38,7 +38,7 @@ has_mouse() const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool MouseWatcher::
 is_mouse_open() const {
-  return _has_mouse && !_suppressed;
+  return _has_mouse && (_suppress_flags & MouseWatcherRegion::SF_mouse_position) == 0;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 53 - 15
panda/src/tform/mouseWatcher.cxx

@@ -43,7 +43,7 @@ TypeHandle MouseWatcher::_button_events_type;
 MouseWatcher::
 MouseWatcher(const string &name) : DataNode(name) {
   _has_mouse = false;
-  _suppressed = false;
+  _suppress_flags = 0;
   _current_region = (MouseWatcherRegion *)NULL;
   _button_down_region = (MouseWatcherRegion *)NULL;
   _button_down = false;
@@ -337,11 +337,14 @@ press(ButtonHandle button) {
       // keyboard flag.
       _current_region->press(param);
     }
-    
-    // All the other regions only get the keyboard events if
-    // they set their global keyboard flag.
-    param.set_outside(true);
-    global_keyboard_press(param);
+
+    if ((_suppress_flags & MouseWatcherRegion::SF_other_button) == 0) {
+      // All the other regions only get the keyboard events if they
+      // set their global keyboard flag, *and* the current region does
+      // not suppress keyboard buttons.
+      param.set_outside(true);
+      global_keyboard_press(param);
+    }
   }
 }
 
@@ -506,6 +509,11 @@ transmit_data(AllTransitionsWrapper &data) {
     }
   }
 
+  _suppress_flags = 0;
+  if (_current_region != (MouseWatcherRegion *)NULL) {
+    _suppress_flags = _current_region->get_suppress_flags();
+  }
+
   // Look for button events.
   const ButtonEventDataTransition *b;
   if (get_transition_into(b, data, _button_events_type)) {
@@ -522,18 +530,48 @@ transmit_data(AllTransitionsWrapper &data) {
     }
   }
 
-  _suppressed = false;
-  if (_current_region != (MouseWatcherRegion *)NULL) {
-    _suppressed = _current_region->get_suppress_below();
+  if ((_suppress_flags & MouseWatcherRegion::SF_mouse_position) != 0) {
+    // Suppress the mouse position.
+    data.clear_transition(_xyz_type);
+    data.clear_transition(_pixel_xyz_type);
   }
+  int suppress_buttons = (_suppress_flags & MouseWatcherRegion::SF_any_button);
+  if (suppress_buttons == MouseWatcherRegion::SF_any_button) {
+    // Suppress all buttons.
+    data.clear_transition(_button_events_type);
+
+  } else if (suppress_buttons != 0) {
+    // Suppress some buttons.
+    const ButtonEventDataTransition *b;
+    ButtonEventDataTransition *new_b = (ButtonEventDataTransition *)NULL;
+
+    if (get_transition_into(b, data, _button_events_type)) {
+      ButtonEventDataTransition::const_iterator bi;
+      for (bi = b->begin(); bi != b->end(); ++bi) {
+        const ButtonEvent &be = (*bi);
+        bool suppress = true;
+
+        if (MouseButton::is_mouse_button(be._button)) {
+          suppress = ((suppress_buttons & MouseWatcherRegion::SF_mouse_button) != 0);
+        } else {
+          suppress = ((suppress_buttons & MouseWatcherRegion::SF_other_button) != 0);
+        }
 
-  if (_suppressed) {
-    // We used to suppress *everything* below, but on reflection we
-    // really only want to suppress the mouse position information.
-    // Button events must still get through.
+        if (!suppress) {
+          // Don't suppress this button event; pass it through.
+          if (new_b == (ButtonEventDataTransition *)NULL) {
+            new_b = new ButtonEventDataTransition;
+          }
+          new_b->push_back(be);
+        }
+      }
+    }
 
-    data.clear_transition(_xyz_type);
-    data.clear_transition(_pixel_xyz_type);
+    if (new_b == (ButtonEventDataTransition *)NULL) {
+      data.clear_transition(_button_events_type);
+    } else {
+      data.set_transition(_button_events_type, new_b);
+    }
   }
 }
 

+ 1 - 1
panda/src/tform/mouseWatcher.h

@@ -122,7 +122,7 @@ private:
   Groups _groups;
 
   bool _has_mouse;
-  bool _suppressed;
+  int _suppress_flags;
   LPoint2f _mouse;
 
   PT(MouseWatcherRegion) _current_region;

+ 20 - 20
panda/src/tform/mouseWatcherRegion.I

@@ -29,7 +29,7 @@ MouseWatcherRegion(const string &name, float left, float right,
   _frame(left, right, bottom, top)
 {
   _sort = 0;
-  _flags = F_active | F_suppress_below;
+  _flags = F_active;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -43,7 +43,7 @@ MouseWatcherRegion(const string &name, const LVecBase4f &frame) :
   _frame(frame)
 {
   _sort = 0;
-  _flags = F_active | F_suppress_below;
+  _flags = F_active;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -174,32 +174,32 @@ get_keyboard() const {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: MouseWatcherRegion::set_suppress_below
+//     Function: MouseWatcherRegion::set_suppress_flags
 //       Access: Published
-//  Description: Sets the suppress_below flag.  When this is true, and
-//               the region is active, then whenever the mouse is
-//               within the region the MouseWatcher will suppress any
-//               mouse and keyboard events further down in the data
-//               graph.
+//  Description: Sets which events are suppressed when the mouse is
+//               over the region.  This is the union of zero or more
+//               various SF_* values.  Normally, this is 0, indicating
+//               that no events are suppressed.
+//
+//               If you set this to a non-zero value, for instance
+//               SF_mouse_position, then the mouse position will not
+//               be sent along the data graph when the mouse is over
+//               this particular region.
 ////////////////////////////////////////////////////////////////////
 INLINE void MouseWatcherRegion::
-set_suppress_below(bool suppress_below) {
-  if (suppress_below) {
-    _flags |= F_suppress_below;
-  } else {
-    _flags &= ~F_suppress_below;
-  }
+set_suppress_flags(int suppress_flags) {
+  _flags = ((_flags & ~F_suppress_flags) | (suppress_flags & F_suppress_flags));
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: MouseWatcherRegion::get_suppress_below
+//     Function: MouseWatcherRegion::get_suppress_flags
 //       Access: Published
-//  Description: Returns the suppress_below flag.  See
-//               set_suppress_below().
+//  Description: Returns the current suppress_flags.  See
+//               set_suppress_flags().
 ////////////////////////////////////////////////////////////////////
-INLINE bool MouseWatcherRegion::
-get_suppress_below() const {
-  return ((_flags & F_suppress_below) != 0);
+INLINE int MouseWatcherRegion::
+get_suppress_flags() const {
+  return (_flags & F_suppress_flags);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 14 - 5
panda/src/tform/mouseWatcherRegion.h

@@ -54,8 +54,15 @@ PUBLISHED:
   INLINE void set_keyboard(bool keyboard);
   INLINE bool get_keyboard() const;
 
-  INLINE void set_suppress_below(bool suppress_below);
-  INLINE bool get_suppress_below() const;
+  enum SuppressFlags {
+    SF_mouse_button       = 0x001,
+    SF_other_button       = 0x002,
+    SF_any_button         = 0x003,
+    SF_mouse_position     = 0x004,
+  };
+
+  INLINE void set_suppress_flags(int suppress_flags);
+  INLINE int get_suppress_flags() const;
 
   void output(ostream &out) const;
   void write(ostream &out, int indent_level = 0) const;
@@ -74,9 +81,11 @@ private:
   int _sort;
 
   enum Flags {
-    F_active         = 0x001,
-    F_keyboard       = 0x002,
-    F_suppress_below = 0x004,
+    // F_suppress_flags is the union of all of the SuppressFlags,
+    // above.  Presently, we reserve 8 bits for suppress flags.
+    F_suppress_flags = 0x0ff,
+    F_active         = 0x100,
+    F_keyboard       = 0x200,
   };
   int _flags;
   ModifierButtons _mods;