Browse Source

sort MouseWatcherGroup regions. Maybe fix for scroll bar getting stuck.

David Rose 17 years ago
parent
commit
f9cbb6f984

+ 5 - 0
panda/src/tform/mouseWatcher.cxx

@@ -199,6 +199,8 @@ remove_group(MouseWatcherGroup *group) {
   MutexHolder holder(_lock);
   MutexHolder holder(_lock);
   MutexHolder holder2(group->_lock);
   MutexHolder holder2(group->_lock);
 
 
+  group->do_sort_regions();
+
   Regions only_a, only_b, both;
   Regions only_a, only_b, both;
   intersect_regions(only_a, only_b, both,
   intersect_regions(only_a, only_b, both,
                     _current_regions, group->_regions);
                     _current_regions, group->_regions);
@@ -258,6 +260,9 @@ replace_group(MouseWatcherGroup *old_group, MouseWatcherGroup *new_group) {
   MutexHolder holder2(old_group->_lock);
   MutexHolder holder2(old_group->_lock);
   MutexHolder holder3(new_group->_lock);
   MutexHolder holder3(new_group->_lock);
 
 
+  old_group->do_sort_regions();
+  new_group->do_sort_regions();
+
 #ifndef NDEBUG
 #ifndef NDEBUG
   if (!_show_regions_render2d.is_empty()) {
   if (!_show_regions_render2d.is_empty()) {
     old_group->do_hide_regions();
     old_group->do_hide_regions();

+ 67 - 14
panda/src/tform/mouseWatcherGroup.cxx

@@ -28,6 +28,7 @@ MouseWatcherGroup::
 MouseWatcherGroup() :
 MouseWatcherGroup() :
   _lock("MouseWatcherGroup")
   _lock("MouseWatcherGroup")
 {
 {
+  _sorted = true;
 #ifndef NDEBUG
 #ifndef NDEBUG
   _show_regions = false;
   _show_regions = false;
   _color.set(0.4f, 0.6f, 1.0f, 1.0f);
   _color.set(0.4f, 0.6f, 1.0f, 1.0f);
@@ -59,12 +60,14 @@ add_region(MouseWatcherRegion *region) {
   // We will only bother to check for duplicates in the region list if
   // We will only bother to check for duplicates in the region list if
   // we are building a development Panda.  The overhead for doing this
   // we are building a development Panda.  The overhead for doing this
   // may be too high if we have many regions.
   // may be too high if we have many regions.
-#ifndef NDEBUG
+#ifdef _DEBUG
   // See if the region is in the set/vector already
   // See if the region is in the set/vector already
   Regions::const_iterator ri = 
   Regions::const_iterator ri = 
     find(_regions.begin(), _regions.end(), pt);
     find(_regions.begin(), _regions.end(), pt);
   nassertv(ri == _regions.end());
   nassertv(ri == _regions.end());
+#endif  // _DEBUG
 
 
+#ifndef NDEBUG
   // Also add it to the vizzes if we have them.
   // Also add it to the vizzes if we have them.
   if (_show_regions) {
   if (_show_regions) {
     nassertv(_vizzes.size() == _regions.size());
     nassertv(_vizzes.size() == _regions.size());
@@ -73,6 +76,7 @@ add_region(MouseWatcherRegion *region) {
 #endif  // NDEBUG
 #endif  // NDEBUG
 
 
   _regions.push_back(pt);
   _regions.push_back(pt);
+  _sorted = false;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -85,16 +89,17 @@ bool MouseWatcherGroup::
 has_region(MouseWatcherRegion *region) const {
 has_region(MouseWatcherRegion *region) const {
   MutexHolder holder(_lock);
   MutexHolder holder(_lock);
 
 
-  // See if the region is in the vector.
-  PT(MouseWatcherRegion) pt = region;
-  Regions::const_iterator ri = 
-    find(_regions.begin(), _regions.end(), pt);
-  if (ri != _regions.end()) {
-    // Found it
-    return true;
+  PT(MouseWatcherRegion) ptr = region;
+
+  if (_sorted) {
+    // If the vector is already sorted, we can do this the quick way.
+    Regions::const_iterator ri = lower_bound(_regions.begin(), _regions.end(), ptr);
+    return (ri != _regions.end() && (*ri) == ptr);
   }
   }
-  // Did not find the region 
-  return false;
+
+  // If the vector isn't sorted, do a linear scan.
+  Regions::const_iterator ri = find(_regions.begin(), _regions.end(), ptr);
+  return (ri != _regions.end());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -142,6 +147,7 @@ clear_regions() {
   MutexHolder holder(_lock);
   MutexHolder holder(_lock);
 
 
   _regions.clear();
   _regions.clear();
+  _sorted = true;
 
 
 #ifndef NDEBUG
 #ifndef NDEBUG
   if (_show_regions) {
   if (_show_regions) {
@@ -151,6 +157,31 @@ clear_regions() {
 #endif  // NDEBUG
 #endif  // NDEBUG
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: MouseWatcherGroup::sort_regions
+//       Access: Published
+//  Description: Sorts all the regions in this group into pointer
+//               order.
+////////////////////////////////////////////////////////////////////
+void MouseWatcherGroup::
+sort_regions() {
+  MutexHolder holder(_lock);
+  do_sort_regions();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MouseWatcherGroup::is_sorted
+//       Access: Published
+//  Description: Returns true if the group has already been sorted,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+bool MouseWatcherGroup::
+is_sorted() const {
+  MutexHolder holder(_lock);
+
+  return _sorted;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: MouseWatcherGroup::get_num_regions
 //     Function: MouseWatcherGroup::get_num_regions
 //       Access: Published
 //       Access: Published
@@ -268,6 +299,20 @@ update_regions() {
 #endif  // NDEBUG
 #endif  // NDEBUG
 
 
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: MouseWatcherGroup::do_sort_regions
+//       Access: Protected
+//  Description: Sorts all the regions in this group into pointer
+//               order.  Assumes the lock is already held.
+////////////////////////////////////////////////////////////////////
+void MouseWatcherGroup::
+do_sort_regions() {
+  if (!_sorted) {
+    sort(_regions.begin(), _regions.end());
+    _sorted = true;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: MouseWatcherGroup::do_remove_region
 //     Function: MouseWatcherGroup::do_remove_region
 //       Access: Protected
 //       Access: Protected
@@ -277,10 +322,18 @@ update_regions() {
 bool MouseWatcherGroup::
 bool MouseWatcherGroup::
 do_remove_region(MouseWatcherRegion *region) {
 do_remove_region(MouseWatcherRegion *region) {
   // See if the region is in the vector.
   // See if the region is in the vector.
-  PT(MouseWatcherRegion) pt = region;
-  Regions::iterator ri = 
-    find(_regions.begin(), _regions.end(), pt);
-  if (ri != _regions.end()) {
+  PT(MouseWatcherRegion) ptr = region;
+  Regions::iterator ri;
+
+  if (_sorted) {
+    // Faster, binary search
+    ri = lower_bound(_regions.begin(), _regions.end(), ptr);
+  } else {
+    // Unsorted, so use slower linear scan
+    ri = find(_regions.begin(), _regions.end(), ptr);
+  }
+
+  if (ri != _regions.end() && (*ri) == ptr) {
     // Found it, now erase it
     // Found it, now erase it
 #ifndef NDEBUG
 #ifndef NDEBUG
     // Also remove it from the vizzes.
     // Also remove it from the vizzes.

+ 5 - 0
panda/src/tform/mouseWatcherGroup.h

@@ -41,6 +41,9 @@ PUBLISHED:
   MouseWatcherRegion *find_region(const string &name) const;
   MouseWatcherRegion *find_region(const string &name) const;
   void clear_regions();
   void clear_regions();
 
 
+  void sort_regions();
+  bool is_sorted() const;
+
   int get_num_regions() const;
   int get_num_regions() const;
   MouseWatcherRegion *get_region(int n) const;
   MouseWatcherRegion *get_region(int n) const;
 
 
@@ -57,6 +60,7 @@ PUBLISHED:
 #endif  // NDEBUG
 #endif  // NDEBUG
 
 
 protected:
 protected:
+  void do_sort_regions();
   bool do_remove_region(MouseWatcherRegion *region);
   bool do_remove_region(MouseWatcherRegion *region);
 
 
 #ifndef NDEBUG
 #ifndef NDEBUG
@@ -69,6 +73,7 @@ protected:
 protected:
 protected:
   typedef pvector< PT(MouseWatcherRegion) > Regions;
   typedef pvector< PT(MouseWatcherRegion) > Regions;
   Regions _regions;
   Regions _regions;
+  bool _sorted;
 
 
   // This mutex protects the above list of regions, as well as the
   // This mutex protects the above list of regions, as well as the
   // below list of vizzes.  It is also referenced directly by
   // below list of vizzes.  It is also referenced directly by