Browse Source

tform: allow calling MouseWatcher::add_region with same region twice

Previously, this was an error.  Now, it will simply silently be ignored, making it behave more like a set.
rdb 7 years ago
parent
commit
65217a258d
2 changed files with 38 additions and 36 deletions
  1. 33 32
      panda/src/tform/mouseWatcherBase.cxx
  2. 5 4
      panda/src/tform/mouseWatcherBase.h

+ 33 - 32
panda/src/tform/mouseWatcherBase.cxx

@@ -40,34 +40,31 @@ MouseWatcherBase::
 }
 
 /**
- * Adds the indicated region to the set of regions in the group.  It is an
- * error to add the same region to the set more than once.
+ * Adds the indicated region to the set of regions in the group.  It is no
+ * longer an error to call this for the same region more than once.
  */
 void MouseWatcherBase::
-add_region(MouseWatcherRegion *region) {
-  PT(MouseWatcherRegion) pt = region;
-
+add_region(PT(MouseWatcherRegion) region) {
   LightMutexHolder holder(_lock);
 
-  // We will only bother to check for duplicates in the region list if we are
-  // building a development Panda.  The overhead for doing this may be too
-  // high if we have many regions.
-#ifdef _DEBUG
-  // See if the region is in the setvector already
-  Regions::const_iterator ri =
-    find(_regions.begin(), _regions.end(), pt);
-  nassertv(ri == _regions.end());
-#endif  // _DEBUG
-
 #ifndef NDEBUG
   // Also add it to the vizzes if we have them.
-  if (_show_regions) {
-    nassertv(_vizzes.size() == _regions.size());
-    _vizzes.push_back(make_viz_region(pt));
+  if (UNLIKELY(_show_regions)) {
+    // We need to check whether it is already in the set, so that we don't
+    // create a duplicate viz.
+    Regions::const_iterator ri =
+      std::find(_regions.begin(), _regions.end(), region);
+
+    if (ri == _regions.end()) {
+      nassertv(_vizzes.size() == _regions.size());
+      _vizzes.push_back(make_viz_region(region));
+    } else {
+      return;
+    }
   }
 #endif  // NDEBUG
 
-  _regions.push_back(pt);
+  _regions.push_back(std::move(region));
   _sorted = false;
 }
 
@@ -111,9 +108,7 @@ MouseWatcherRegion *MouseWatcherBase::
 find_region(const string &name) const {
   LightMutexHolder holder(_lock);
 
-  Regions::const_iterator ri;
-  for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
-    MouseWatcherRegion *region = (*ri);
+  for (MouseWatcherRegion *region : _regions) {
     if (region->get_name() == name) {
       return region;
     }
@@ -162,10 +157,13 @@ is_sorted() const {
 /**
  * Returns the number of regions in the group.
  */
-int MouseWatcherBase::
+size_t MouseWatcherBase::
 get_num_regions() const {
   LightMutexHolder holder(_lock);
-
+  if (!_sorted) {
+    // Remove potential duplicates to get an accurate count.
+    ((MouseWatcherBase *)this)->do_sort_regions();
+  }
   return _regions.size();
 }
 
@@ -175,9 +173,12 @@ get_num_regions() const {
  * removed the nth region before you called this method.
  */
 MouseWatcherRegion *MouseWatcherBase::
-get_region(int n) const {
+get_region(size_t n) const {
   LightMutexHolder holder(_lock);
-  if (n >= 0 && n < (int)_regions.size()) {
+  if (!_sorted) {
+    ((MouseWatcherBase *)this)->do_sort_regions();
+  }
+  if (n < _regions.size()) {
     return _regions[n];
   }
   return nullptr;
@@ -198,9 +199,7 @@ void MouseWatcherBase::
 write(ostream &out, int indent_level) const {
   LightMutexHolder holder(_lock);
 
-  Regions::const_iterator ri;
-  for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
-    MouseWatcherRegion *region = (*ri);
+  for (MouseWatcherRegion *region : _regions) {
     region->write(out, indent_level);
   }
 }
@@ -345,13 +344,15 @@ do_update_regions() {
   nassertv(_lock.debug_is_locked());
 
   if (_show_regions) {
+    // Make sure we have no duplicates.
+    do_sort_regions();
+
     _show_regions_root.node()->remove_all_children();
     _vizzes.clear();
     _vizzes.reserve(_regions.size());
 
-    Regions::const_iterator ri;
-    for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
-      _vizzes.push_back(make_viz_region(*ri));
+    for (MouseWatcherRegion *region : _regions) {
+      _vizzes.push_back(make_viz_region(region));
     }
   }
 }

+ 5 - 4
panda/src/tform/mouseWatcherBase.h

@@ -21,6 +21,7 @@
 #include "pvector.h"
 #include "nodePath.h"
 #include "lightMutex.h"
+#include "ordered_vector.h"
 
 /**
  * This represents a collection of MouseWatcherRegions that may be managed as
@@ -34,7 +35,7 @@ public:
   virtual ~MouseWatcherBase();
 
 PUBLISHED:
-  void add_region(MouseWatcherRegion *region);
+  void add_region(PT(MouseWatcherRegion) region);
   bool has_region(MouseWatcherRegion *region) const;
   bool remove_region(MouseWatcherRegion *region);
   MouseWatcherRegion *find_region(const std::string &name) const;
@@ -44,8 +45,8 @@ PUBLISHED:
   bool is_sorted() const;
   MAKE_PROPERTY(sorted, is_sorted);
 
-  int get_num_regions() const;
-  MouseWatcherRegion *get_region(int n) const;
+  size_t get_num_regions() const;
+  MouseWatcherRegion *get_region(size_t n) const;
   MAKE_SEQ(get_regions, get_num_regions, get_region);
   MAKE_SEQ_PROPERTY(regions, get_num_regions, get_region);
 
@@ -73,7 +74,7 @@ protected:
 #endif  // NDEBUG
 
 protected:
-  typedef pvector< PT(MouseWatcherRegion) > Regions;
+  typedef ov_set< PT(MouseWatcherRegion) > Regions;
   Regions _regions;
   bool _sorted;