Browse Source

add groove, ridge; prevent circular ref counts

David Rose 24 năm trước cách đây
mục cha
commit
ef25e2597d

+ 3 - 0
panda/src/pgui/Sources.pp

@@ -12,6 +12,7 @@
   #define SOURCES  \
   #define SOURCES  \
     config_pgui.h \
     config_pgui.h \
     pgButton.I pgButton.h \
     pgButton.I pgButton.h \
+    pgMouseWatcherGroup.I pgMouseWatcherGroup.h \
     pgMouseWatcherParameter.I pgMouseWatcherParameter.h \
     pgMouseWatcherParameter.I pgMouseWatcherParameter.h \
     pgFrameStyle.I pgFrameStyle.h \
     pgFrameStyle.I pgFrameStyle.h \
     pgItem.I pgItem.h \
     pgItem.I pgItem.h \
@@ -22,6 +23,7 @@
   #define SOURCES $[SOURCES] \
   #define SOURCES $[SOURCES] \
     config_pgui.cxx \
     config_pgui.cxx \
     pgButton.cxx \
     pgButton.cxx \
+    pgMouseWatcherGroup.cxx \
     pgMouseWatcherParameter.cxx \
     pgMouseWatcherParameter.cxx \
     pgFrameStyle.cxx \
     pgFrameStyle.cxx \
     pgItem.cxx \
     pgItem.cxx \
@@ -30,6 +32,7 @@
 
 
   #define INSTALL_HEADERS \
   #define INSTALL_HEADERS \
     pgButton.I pgButton.h \
     pgButton.I pgButton.h \
+    pgMouseWatcherGroup.I pgMouseWatcherGroup.h \
     pgMouseWatcherParameter.I pgMouseWatcherParameter.h \
     pgMouseWatcherParameter.I pgMouseWatcherParameter.h \
     pgFrameStyle.I pgFrameStyle.h \
     pgFrameStyle.I pgFrameStyle.h \
     pgItem.I pgItem.h \
     pgItem.I pgItem.h \

+ 12 - 0
panda/src/pgui/pgButton.I

@@ -66,6 +66,18 @@ set_active(bool active) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PGButton::get_click_prefix
+//       Access: Published, Static
+//  Description: Returns the prefix that is used to define the click
+//               event for all PGButtons.  The click event is the
+//               concatenation of this string followed by get_id().
+////////////////////////////////////////////////////////////////////
+INLINE string PGButton::
+get_click_prefix() {
+  return "click-";
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PGButton::get_click_event
 //     Function: PGButton::get_click_event
 //       Access: Published
 //       Access: Published

+ 1 - 0
panda/src/pgui/pgButton.h

@@ -72,6 +72,7 @@ PUBLISHED:
   bool remove_click_button(const ButtonHandle &button);
   bool remove_click_button(const ButtonHandle &button);
   bool has_click_button(const ButtonHandle &button);
   bool has_click_button(const ButtonHandle &button);
 
 
+  INLINE static string get_click_prefix();
   INLINE string get_click_event(const ButtonHandle &button) const;
   INLINE string get_click_event(const ButtonHandle &button) const;
 
 
 private:
 private:

+ 245 - 0
panda/src/pgui/pgFrameStyle.cxx

@@ -39,6 +39,12 @@ operator << (ostream &out, PGFrameStyle::Type type) {
 
 
   case PGFrameStyle::T_bevel_in:
   case PGFrameStyle::T_bevel_in:
     return out << "bevel_in";
     return out << "bevel_in";
+
+  case PGFrameStyle::T_groove:
+    return out << "groove";
+
+  case PGFrameStyle::T_ridge:
+    return out << "ridge";
   }
   }
 
 
   return out << "**unknown(" << (int)type << ")**";
   return out << "**unknown(" << (int)type << ")**";
@@ -84,6 +90,8 @@ xform(const LMatrix4f &mat) {
 
 
   case T_bevel_out:
   case T_bevel_out:
   case T_bevel_in:
   case T_bevel_in:
+  case T_groove:
+  case T_ridge:
     return true;
     return true;
   }
   }
 
 
@@ -122,6 +130,14 @@ generate_into(Node *node, const LVecBase4f &frame) {
     gnode = generate_bevel_geom(frame, true);
     gnode = generate_bevel_geom(frame, true);
     break;
     break;
 
 
+  case T_groove:
+    gnode = generate_groove_geom(frame, true);
+    break;
+
+  case T_ridge:
+    gnode = generate_groove_geom(frame, false);
+    break;
+
   default:
   default:
     break;
     break;
   }
   }
@@ -338,3 +354,232 @@ generate_bevel_geom(const LVecBase4f &frame, bool in) {
   
   
   return gnode.p();
   return gnode.p();
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: PGFrameStyle::generate_groove_geom
+//       Access: Private
+//  Description: Generates the GeomNode appropriate to a T_groove or
+//               T_ridge frame.
+////////////////////////////////////////////////////////////////////
+PT_Node PGFrameStyle::
+generate_groove_geom(const LVecBase4f &frame, bool in) {
+  //
+  // Colors:
+  //
+  // 
+  //  * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  //  * *                                               * *
+  //  *   *                   ctop                    *   *
+  //  *     *                                       *     *
+  //  *       * * * * * * * * * * * * * * * * * * *       *
+  //  *       * *                               * *       *
+  //  *       *   *          cbottom          *   *       *
+  //  *       *     *                       *     *       *
+  //  *       *       * * * * * * * * * * *       *       *
+  //  *       *       *                   *       *       *
+  //  *       *       *                   *       *       *
+  //  * cleft * cright*      _color       * cleft * cright*
+  //  *       *       *                   *       *       *
+  //  *       *       *                   *       *       *
+  //  *       *       * * * * * * * * * * *       *       *
+  //  *       *     *                       *     *       *
+  //  *       *   *           ctop            *   *       *
+  //  *       * *                               * *       *
+  //  *       * * * * * * * * * * * * * * * * * * *       *
+  //  *     *                                       *     *
+  //  *   *                  cbottom                  *   *
+  //  * *                                               * *
+  //  * * * * * * * * * * * * * * * * * * * * * * * * * * *
+  //
+  //
+  // Vertices:
+  //
+  //  tristrip 1:
+  //  4 * * * * * * * * * * * * * * * * * * * * * * * * * 6
+  //  * *                                               *
+  //  *   *                                           *
+  //  *     *                                       *
+  //  *       5 * * * * * * * * * * * * * * * * * 7
+  //  *       *
+  //  *       *
+  //  *       *
+  //  *       *
+  //  *       *
+  //  *       *
+  //  *       *
+  //  *       *
+  //  *       *
+  //  *       *
+  //  *       *
+  //  *       *
+  //  *       *
+  //  *       3 * * * * * * * * * * * * * * * * * 1
+  //  *     *                                       *
+  //  *   *                                           *
+  //  * *                                               *
+  //  2 * * * * * * * * * * * * * * * * * * * * * * * * * 0
+  //
+  //  tristrip 2:
+  //          4 * * * * * * * * * * * * * * * * * 6
+  //          * *                               *
+  //          *   *                           *
+  //          *     *                       *
+  //          *       5 * * * * * * * * * 7
+  //          *       *
+  //          *       *
+  //          *       *
+  //          *       *
+  //          *       *
+  //          *       3 * * * * * * * * * 1
+  //          *     *                       *
+  //          *   *                           *
+  //          * *                               *
+  //          2 * * * * * * * * * * * * * * * * * 0
+  // 
+  //  tristrip 3:
+  //                                                      1
+  //                                                    * *
+  //                                                  *   *
+  //                                                *     *
+  //                                              3       *
+  //                                            * *       *
+  //                                          *   *       *
+  //                                        *     *       *
+  //                  7 * * * * * * * * * 5       *       *
+  //                  *                   *       *       *
+  //                  *                   *       *       *
+  //                  *                   *       *       *
+  //                  *                   *       *       *
+  //                  *                   *       *       *
+  //                  6 * * * * * * * * * 4       *       *
+  //                                        *     *       *
+  //                                          *   *       *
+  //                                            * *       *
+  //                                              2       *
+  //                                                *     *
+  //                                                  *   *
+  //                                                    * *
+  //                                                      0
+
+  PT(GeomNode) gnode = new GeomNode("groove");
+
+  float left = frame[0];
+  float right = frame[1];
+  float bottom = frame[2];
+  float top = frame[3];
+
+  float mid_left = left + 0.5 * _width[0];
+  float mid_right = right - 0.5 * _width[0];
+  float mid_bottom = bottom + 0.5 * _width[1];
+  float mid_top = top - 0.5 * _width[1];
+
+  float inner_left = left + _width[0];
+  float inner_right = right - _width[0];
+  float inner_bottom = bottom + _width[1];
+  float inner_top = top - _width[1];
+
+  float left_color_scale = 1.2;
+  float right_color_scale = 0.8;
+  float bottom_color_scale = 0.7;
+  float top_color_scale = 1.3;
+
+  if (in) {
+    right_color_scale = 1.2;
+    left_color_scale = 0.8;
+    top_color_scale = 0.7;
+    bottom_color_scale = 1.3;
+  }
+
+  // Clamp all colors at white, and don't scale the alpha.
+  Colorf cleft(min(_color[0] * left_color_scale, 1.0f),
+               min(_color[1] * left_color_scale, 1.0f),
+               min(_color[2] * left_color_scale, 1.0f),
+               _color[3]);
+
+  Colorf cright(min(_color[0] * right_color_scale, 1.0f),
+                min(_color[1] * right_color_scale, 1.0f),
+                min(_color[2] * right_color_scale, 1.0f),
+                _color[3]);
+
+  Colorf cbottom(min(_color[0] * bottom_color_scale, 1.0f),
+                 min(_color[1] * bottom_color_scale, 1.0f),
+                 min(_color[2] * bottom_color_scale, 1.0f),
+                 _color[3]);
+
+  Colorf ctop(min(_color[0] * top_color_scale, 1.0f),
+              min(_color[1] * top_color_scale, 1.0f),
+              min(_color[2] * top_color_scale, 1.0f),
+              _color[3]);
+
+  // Now make the tristrips.
+  Geom *geom = new GeomTristrip;
+  gnode->add_geom(geom);
+    
+  PTA_int lengths;
+  PTA_Vertexf verts;
+  PTA_Colorf colors;
+
+  // Tristrip 1.
+  lengths.push_back(8);
+    
+  verts.push_back(Vertexf(right, 0.0, bottom));
+  verts.push_back(Vertexf(mid_right, 0.0, mid_bottom));
+  verts.push_back(Vertexf(left, 0.0, bottom));
+  verts.push_back(Vertexf(mid_left, 0.0, mid_bottom));
+  verts.push_back(Vertexf(left, 0.0, top));
+  verts.push_back(Vertexf(mid_left, 0.0, mid_top));
+  verts.push_back(Vertexf(right, 0.0, top));
+  verts.push_back(Vertexf(mid_right, 0.0, mid_top));
+  
+  colors.push_back(cbottom);
+  colors.push_back(cbottom);
+  colors.push_back(cleft);
+  colors.push_back(cleft);
+  colors.push_back(ctop);
+  colors.push_back(ctop);
+
+  // Tristrip 2.
+  lengths.push_back(8);
+    
+  verts.push_back(Vertexf(mid_right, 0.0, mid_bottom));
+  verts.push_back(Vertexf(inner_right, 0.0, inner_bottom));
+  verts.push_back(Vertexf(mid_left, 0.0, mid_bottom));
+  verts.push_back(Vertexf(inner_left, 0.0, inner_bottom));
+  verts.push_back(Vertexf(mid_left, 0.0, mid_top));
+  verts.push_back(Vertexf(inner_left, 0.0, inner_top));
+  verts.push_back(Vertexf(mid_right, 0.0, mid_top));
+  verts.push_back(Vertexf(inner_right, 0.0, inner_top));
+  
+  colors.push_back(ctop);
+  colors.push_back(ctop);
+  colors.push_back(cright);
+  colors.push_back(cright);
+  colors.push_back(cbottom);
+  colors.push_back(cbottom);
+
+  // Tristrip 3.
+  lengths.push_back(8);
+
+  verts.push_back(Vertexf(right, 0.0, bottom));
+  verts.push_back(Vertexf(right, 0.0, top));
+  verts.push_back(Vertexf(mid_right, 0.0, mid_bottom));
+  verts.push_back(Vertexf(mid_right, 0.0, mid_top));
+  verts.push_back(Vertexf(inner_right, 0.0, inner_bottom));
+  verts.push_back(Vertexf(inner_right, 0.0, inner_top));
+  verts.push_back(Vertexf(inner_left, 0.0, inner_bottom));
+  verts.push_back(Vertexf(inner_left, 0.0, inner_top));
+
+  colors.push_back(cright);
+  colors.push_back(cright);
+  colors.push_back(cleft);
+  colors.push_back(cleft);
+  colors.push_back(_color);
+  colors.push_back(_color);
+
+  geom->set_num_prims(3);
+  geom->set_lengths(lengths);
+  geom->set_coords(verts, G_PER_VERTEX);
+  geom->set_colors(colors, G_PER_COMPONENT);
+  
+  return gnode.p();
+}

+ 4 - 1
panda/src/pgui/pgFrameStyle.h

@@ -43,7 +43,9 @@ PUBLISHED:
     T_none,
     T_none,
     T_flat,
     T_flat,
     T_bevel_out,
     T_bevel_out,
-    T_bevel_in
+    T_bevel_in,
+    T_groove,
+    T_ridge
   };
   };
 
 
   INLINE void set_type(Type type);
   INLINE void set_type(Type type);
@@ -66,6 +68,7 @@ public:
 private:
 private:
   PT_Node generate_flat_geom(const LVecBase4f &frame);
   PT_Node generate_flat_geom(const LVecBase4f &frame);
   PT_Node generate_bevel_geom(const LVecBase4f &frame, bool in);
   PT_Node generate_bevel_geom(const LVecBase4f &frame, bool in);
+  PT_Node generate_groove_geom(const LVecBase4f &frame, bool in);
 
 
 private:
 private:
   Type _type;
   Type _type;

+ 54 - 4
panda/src/pgui/pgItem.I

@@ -163,6 +163,56 @@ get_id() const {
   return _region->get_name();
   return _region->get_name();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PGItem::get_enter_prefix
+//       Access: Published, Static
+//  Description: Returns the prefix that is used to define the enter
+//               event for all PGItems.  The enter event is the
+//               concatenation of this string followed by get_id().
+////////////////////////////////////////////////////////////////////
+INLINE string PGItem::
+get_enter_prefix() {
+  return "enter-";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PGItem::get_exit_prefix
+//       Access: Published, Static
+//  Description: Returns the prefix that is used to define the exit
+//               event for all PGItems.  The exit event is the
+//               concatenation of this string followed by get_id().
+////////////////////////////////////////////////////////////////////
+INLINE string PGItem::
+get_exit_prefix() {
+  return "exit-";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PGItem::get_press_prefix
+//       Access: Published, Static
+//  Description: Returns the prefix that is used to define the press
+//               event for all PGItems.  The press event is the
+//               concatenation of this string followed by a button
+//               name, followed by a hyphen and get_id().
+////////////////////////////////////////////////////////////////////
+INLINE string PGItem::
+get_press_prefix() {
+  return "press-";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PGItem::get_release_prefix
+//       Access: Published, Static
+//  Description: Returns the prefix that is used to define the release
+//               event for all PGItems.  The release event is the
+//               concatenation of this string followed by a button
+//               name, followed by a hyphen and get_id().
+////////////////////////////////////////////////////////////////////
+INLINE string PGItem::
+get_release_prefix() {
+  return "release-";
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PGItem::get_enter_event
 //     Function: PGItem::get_enter_event
 //       Access: Published
 //       Access: Published
@@ -171,7 +221,7 @@ get_id() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE string PGItem::
 INLINE string PGItem::
 get_enter_event() const {
 get_enter_event() const {
-  return "enter-" + get_id();
+  return get_enter_prefix() + get_id();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -182,7 +232,7 @@ get_enter_event() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE string PGItem::
 INLINE string PGItem::
 get_exit_event() const {
 get_exit_event() const {
-  return "exit-" + get_id();
+  return get_exit_prefix() + get_id();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -195,7 +245,7 @@ get_exit_event() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE string PGItem::
 INLINE string PGItem::
 get_press_event(const ButtonHandle &button) const {
 get_press_event(const ButtonHandle &button) const {
-  return "press-" + button.get_name() + "-" + get_id();
+  return get_press_prefix() + button.get_name() + "-" + get_id();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -208,7 +258,7 @@ get_press_event(const ButtonHandle &button) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE string PGItem::
 INLINE string PGItem::
 get_release_event(const ButtonHandle &button) const {
 get_release_event(const ButtonHandle &button) const {
-  return "release-" + button.get_name() + "-" + get_id();
+  return get_release_prefix() + button.get_name() + "-" + get_id();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

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

@@ -92,6 +92,11 @@ PUBLISHED:
   void set_frame_style(int state, const PGFrameStyle &style);
   void set_frame_style(int state, const PGFrameStyle &style);
 
 
   INLINE const string &get_id() const;
   INLINE const string &get_id() const;
+  INLINE static string get_enter_prefix();
+  INLINE static string get_exit_prefix();
+  INLINE static string get_press_prefix();
+  INLINE static string get_release_prefix();
+
   INLINE string get_enter_event() const;
   INLINE string get_enter_event() const;
   INLINE string get_exit_event() const;
   INLINE string get_exit_event() const;
   INLINE string get_press_event(const ButtonHandle &button) const;
   INLINE string get_press_event(const ButtonHandle &button) const;

+ 40 - 0
panda/src/pgui/pgMouseWatcherGroup.I

@@ -0,0 +1,40 @@
+// Filename: pgMouseWatcherGroup.I
+// Created by:  drose (09Jul01)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PGMouseWatcherGroup::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE PGMouseWatcherGroup::
+PGMouseWatcherGroup(PGTop *top) : _top(top) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PGMouseWatcherGroup::clear_top
+//       Access: Public
+//  Description: Called by the PGTop object to indicate that it is no
+//               longer keeping the pointer to the PGMouseWatcherGroup
+//               object.
+////////////////////////////////////////////////////////////////////
+INLINE void PGMouseWatcherGroup::
+clear_top(PGTop *top) {
+  nassertv(_top == top);
+  _top = (PGTop *)NULL;
+}

+ 38 - 0
panda/src/pgui/pgMouseWatcherGroup.cxx

@@ -0,0 +1,38 @@
+// Filename: pgMouseWatcherGroup.cxx
+// Created by:  drose (09Jul01)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pgMouseWatcherGroup.h"
+#include "pgTop.h"
+
+TypeHandle PGMouseWatcherGroup::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: PGMouseWatcherGroup::Destructor
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+PGMouseWatcherGroup::
+~PGMouseWatcherGroup() {
+  cerr << "~PGMouseWatcherGroup()\n";
+  // When the MouseWatcherGroup destructs for whatever reason, the
+  // PGTop object should lose its MouseWatcher.
+  if (_top != (PGTop *)NULL) {
+    _top->_watcher_group = (PGMouseWatcherGroup *)NULL;
+    _top->set_mouse_watcher((MouseWatcher *)NULL);
+  }
+}

+ 67 - 0
panda/src/pgui/pgMouseWatcherGroup.h

@@ -0,0 +1,67 @@
+// Filename: pgMouseWatcherGroup.h
+// Created by:  drose (09Jul01)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef PGMOUSEWATCHERGROUP_H
+#define PGMOUSEWATCHERGROUP_H
+
+#include "pandabase.h"
+
+#include "mouseWatcherGroup.h"
+#include "pointerTo.h"
+
+class PGTop;
+
+////////////////////////////////////////////////////////////////////
+//       Class : PGMouseWatcherGroup
+// Description : This is a specialization on MouseWatcherGroup, to
+//               associate it with a PGTop.  Originally we had PGTop
+//               multiply inheriting from NamedNode and
+//               MouseWatcherGroup, but this causes problems with
+//               circular reference counts.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA PGMouseWatcherGroup : public MouseWatcherGroup {
+public:
+  INLINE PGMouseWatcherGroup(PGTop *top);
+  virtual ~PGMouseWatcherGroup();
+
+  INLINE void clear_top(PGTop *top);
+
+private:
+  PGTop *_top;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    MouseWatcherGroup::init_type();
+    register_type(_type_handle, "PGMouseWatcherGroup",
+                  MouseWatcherGroup::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "pgMouseWatcherGroup.I"
+
+#endif

+ 1 - 1
panda/src/pgui/pgMouseWatcherRegion.cxx

@@ -21,8 +21,8 @@
 
 
 #include "string_utils.h"
 #include "string_utils.h"
 
 
-TypeHandle PGMouseWatcherRegion::_type_handle;
 int PGMouseWatcherRegion::_next_index = 0;
 int PGMouseWatcherRegion::_next_index = 0;
+TypeHandle PGMouseWatcherRegion::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PGMouseWatcherRegion::Constructor
 //     Function: PGMouseWatcherRegion::Constructor

+ 1 - 1
panda/src/pgui/pgMouseWatcherRegion.h

@@ -44,6 +44,7 @@ public:
 
 
 private:
 private:
   PGItem *_item;
   PGItem *_item;
+  static int _next_index;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
@@ -61,7 +62,6 @@ public:
 
 
 private:
 private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;
-  static int _next_index;
 
 
   friend class PGItem;
   friend class PGItem;
 };
 };

+ 28 - 0
panda/src/pgui/pgTop.I

@@ -54,3 +54,31 @@ INLINE MouseWatcher *PGTop::
 get_mouse_watcher() const {
 get_mouse_watcher() const {
   return _watcher;
   return _watcher;
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: PGTop::add_region
+//       Access: Published
+//  Description: Adds the indicated region to the set of regions in
+//               the group.  Returns true if it was successfully
+//               added, or false if it was already on the list.
+////////////////////////////////////////////////////////////////////
+INLINE bool PGTop::
+add_region(MouseWatcherRegion *region) {
+  if (_watcher_group == (PGMouseWatcherGroup *)NULL) {
+    return false;
+  }
+  return _watcher_group->add_region(region);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PGTop::clear_regions
+//       Access: Published
+//  Description: Removes all the regions from the group.
+////////////////////////////////////////////////////////////////////
+INLINE void PGTop::
+clear_regions() {
+  if (_watcher_group == (PGMouseWatcherGroup *)NULL) {
+    return;
+  }
+  _watcher_group->clear_regions();
+}

+ 14 - 2
panda/src/pgui/pgTop.cxx

@@ -18,6 +18,7 @@
 
 
 #include "pgTop.h"
 #include "pgTop.h"
 #include "pgItem.h"
 #include "pgItem.h"
+#include "pgMouseWatcherGroup.h"
 
 
 #include "arcChain.h"
 #include "arcChain.h"
 #include "graphicsStateGuardian.h"
 #include "graphicsStateGuardian.h"
@@ -44,6 +45,7 @@ TypeHandle PGTop::_type_handle;
 PGTop::
 PGTop::
 PGTop(const string &name) : NamedNode(name)
 PGTop(const string &name) : NamedNode(name)
 {
 {
+  _watcher_group = (PGMouseWatcherGroup *)NULL;
   _gsg = (GraphicsStateGuardian *)NULL;
   _gsg = (GraphicsStateGuardian *)NULL;
   _trav = (RenderTraverser *)NULL;
   _trav = (RenderTraverser *)NULL;
 
 
@@ -60,6 +62,7 @@ PGTop(const string &name) : NamedNode(name)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PGTop::
 PGTop::
 ~PGTop() {
 ~PGTop() {
+  set_mouse_watcher((MouseWatcher *)NULL);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -136,12 +139,21 @@ has_sub_render() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PGTop::
 void PGTop::
 set_mouse_watcher(MouseWatcher *watcher) {
 set_mouse_watcher(MouseWatcher *watcher) {
+  if (_watcher_group != (PGMouseWatcherGroup *)NULL) {
+    _watcher_group->clear_top(this);
+  }
   if (_watcher != (MouseWatcher *)NULL) {
   if (_watcher != (MouseWatcher *)NULL) {
-    _watcher->remove_group(this);
+    _watcher->remove_group(_watcher_group);
   }
   }
+
   _watcher = watcher;
   _watcher = watcher;
+  _watcher_group = (PGMouseWatcherGroup *)NULL;
+
   if (_watcher != (MouseWatcher *)NULL) {
   if (_watcher != (MouseWatcher *)NULL) {
-    _watcher->add_group(this);
+    // We create a new PGMouseWatcherGroup, but we don't own the
+    // reference count; the watcher will own this for us.
+    _watcher_group = new PGMouseWatcherGroup(this);
+    _watcher->add_group(_watcher_group);
   }
   }
 }
 }
 
 

+ 12 - 2
panda/src/pgui/pgTop.h

@@ -21,8 +21,9 @@
 
 
 #include "pandabase.h"
 #include "pandabase.h"
 
 
+#include "pgMouseWatcherGroup.h"
+
 #include "namedNode.h"
 #include "namedNode.h"
-#include "mouseWatcherGroup.h"
 #include "mouseWatcher.h"
 #include "mouseWatcher.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
 #include "allAttributesWrapper.h"
 #include "allAttributesWrapper.h"
@@ -30,6 +31,7 @@
 class GraphicsStateGuardian;
 class GraphicsStateGuardian;
 class RenderTraverser;
 class RenderTraverser;
 class ArcChain;
 class ArcChain;
+class PGMouseWatcherGroup;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : PGTop
 //       Class : PGTop
@@ -45,7 +47,7 @@ class ArcChain;
 //               depth-first, left-to-right order, appropriate for 2-d
 //               depth-first, left-to-right order, appropriate for 2-d
 //               objects.
 //               objects.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA PGTop : public NamedNode, public MouseWatcherGroup {
+class EXPCL_PANDA PGTop : public NamedNode {
 PUBLISHED:
 PUBLISHED:
   PGTop(const string &name = "");
   PGTop(const string &name = "");
   virtual ~PGTop();
   virtual ~PGTop();
@@ -65,10 +67,16 @@ PUBLISHED:
   void set_mouse_watcher(MouseWatcher *watcher);
   void set_mouse_watcher(MouseWatcher *watcher);
   INLINE MouseWatcher *get_mouse_watcher() const;
   INLINE MouseWatcher *get_mouse_watcher() const;
 
 
+private:
+  // These methods duplicate the functionality of MouseWatcherGroup.
+  INLINE bool add_region(MouseWatcherRegion *region);
+  INLINE void clear_regions();
+
 private:
 private:
   void r_traverse(Node *node, const ArcChain &chain);
   void r_traverse(Node *node, const ArcChain &chain);
 
 
   PT(MouseWatcher) _watcher;
   PT(MouseWatcher) _watcher;
+  PGMouseWatcherGroup *_watcher_group;
   GraphicsStateGuardian *_gsg;
   GraphicsStateGuardian *_gsg;
   RenderTraverser *_trav;
   RenderTraverser *_trav;
   AllAttributesWrapper _attrib;
   AllAttributesWrapper _attrib;
@@ -92,6 +100,8 @@ public:
 
 
 private:
 private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;
+
+  friend class PGMouseWatcherGroup;
 };
 };
 
 
 #include "pgTop.I"
 #include "pgTop.I"