Browse Source

weak pointers, and FadeLODNode fixes for instances/multiple cameras

David Rose 21 years ago
parent
commit
557060cb1d
53 changed files with 2947 additions and 663 deletions
  1. 1 0
      panda/src/display/graphicsEngine.cxx
  2. 24 2
      panda/src/express/Sources.pp
  3. 8 0
      panda/src/express/express_composite2.cxx
  4. 10 334
      panda/src/express/pointerTo.I
  5. 19 0
      panda/src/express/pointerTo.cxx
  6. 2 72
      panda/src/express/pointerTo.h
  7. 102 103
      panda/src/express/pointerToArray.I
  8. 19 0
      panda/src/express/pointerToArray.cxx
  9. 2 0
      panda/src/express/pointerToArray.h
  10. 339 0
      panda/src/express/pointerToBase.I
  11. 19 0
      panda/src/express/pointerToBase.cxx
  12. 93 0
      panda/src/express/pointerToBase.h
  13. 38 0
      panda/src/express/pointerToVoid.I
  14. 19 0
      panda/src/express/pointerToVoid.cxx
  15. 56 0
      panda/src/express/pointerToVoid.h
  16. 62 0
      panda/src/express/referenceCount.I
  17. 12 2
      panda/src/express/referenceCount.h
  18. 319 0
      panda/src/express/weakPointerTo.I
  19. 19 0
      panda/src/express/weakPointerTo.cxx
  20. 108 0
      panda/src/express/weakPointerTo.h
  21. 430 0
      panda/src/express/weakPointerToBase.I
  22. 19 0
      panda/src/express/weakPointerToBase.cxx
  23. 99 0
      panda/src/express/weakPointerToBase.h
  24. 53 0
      panda/src/express/weakPointerToVoid.I
  25. 19 0
      panda/src/express/weakPointerToVoid.cxx
  26. 47 0
      panda/src/express/weakPointerToVoid.h
  27. 18 0
      panda/src/express/weakReferenceList.I
  28. 77 0
      panda/src/express/weakReferenceList.cxx
  29. 52 0
      panda/src/express/weakReferenceList.h
  30. 6 3
      panda/src/pgraph/Sources.pp
  31. 72 4
      panda/src/pgraph/auxSceneData.I
  32. 21 0
      panda/src/pgraph/auxSceneData.cxx
  33. 22 3
      panda/src/pgraph/auxSceneData.h
  34. 98 0
      panda/src/pgraph/camera.cxx
  35. 9 3
      panda/src/pgraph/camera.h
  36. 6 0
      panda/src/pgraph/config_pgraph.cxx
  37. 1 0
      panda/src/pgraph/config_pgraph.h
  38. 0 16
      panda/src/pgraph/fadeLodNode.I
  39. 106 74
      panda/src/pgraph/fadeLodNode.cxx
  40. 1 11
      panda/src/pgraph/fadeLodNode.h
  41. 38 0
      panda/src/pgraph/fadeLodNodeData.cxx
  42. 59 0
      panda/src/pgraph/fadeLodNodeData.h
  43. 29 3
      panda/src/pgraph/nodePath.I
  44. 0 26
      panda/src/pgraph/nodePath.cxx
  45. 2 1
      panda/src/pgraph/nodePath.h
  46. 1 0
      panda/src/pgraph/pgraph_composite1.cxx
  47. 1 0
      panda/src/pgraph/pgraph_composite2.cxx
  48. 2 2
      panda/src/pgraph/sceneSetup.I
  49. 3 3
      panda/src/pgraph/sceneSetup.h
  50. 256 0
      panda/src/pgraph/weakNodePath.I
  51. 33 0
      panda/src/pgraph/weakNodePath.cxx
  52. 79 0
      panda/src/pgraph/weakNodePath.h
  53. 17 1
      panda/src/testbed/test_lod.cxx

+ 1 - 0
panda/src/display/graphicsEngine.cxx

@@ -960,6 +960,7 @@ setup_scene(const NodePath &camera, GraphicsStateGuardian *gsg) {
     // Camera inactive, no draw.
     return NULL;
   }
+  camera_node->cleanup_aux_scene_data();
 
   Lens *lens = camera_node->get_lens();
   if (lens == (Lens *)NULL) {

+ 24 - 2
panda/src/express/Sources.pp

@@ -45,6 +45,8 @@
     patchfile.I patchfile.h \
     pointerTo.I pointerTo.h \
     pointerToArray.I pointerToArray.h \
+    pointerToBase.I pointerToBase.h \
+    pointerToVoid.I pointerToVoid.h \
     profileTimer.I profileTimer.h \
     pta_uchar.h \
     ramfile.I ramfile.h \
@@ -72,6 +74,10 @@
     virtualFileMountMultifile.I virtualFileMountSystem.h \
     virtualFileMountSystem.I virtualFileSimple.h virtualFileSimple.I \
     virtualFileSystem.h virtualFileSystem.I \
+    weakPointerTo.I weakPointerTo.h \
+    weakPointerToBase.I weakPointerToBase.h \
+    weakPointerToVoid.I weakPointerToVoid.h \
+    weakReferenceList.I weakReferenceList.h \
     windowsRegistry.h \
     zStream.I zStream.h zStreamBuf.h
 
@@ -94,6 +100,10 @@
     ordered_vector.cxx \
     password_hash.cxx \
     patchfile.cxx \
+    pointerTo.cxx \
+    pointerToArray.cxx \
+    pointerToBase.cxx \
+    pointerToVoid.cxx \
     profileTimer.cxx \
     pta_uchar.cxx \
     ramfile.cxx \
@@ -113,6 +123,10 @@
     virtualFileMount.cxx \
     virtualFileMountMultifile.cxx virtualFileMountSystem.cxx \
     virtualFileSimple.cxx virtualFileSystem.cxx \
+    weakPointerTo.cxx \
+    weakPointerToBase.cxx \
+    weakPointerToVoid.cxx \
+    weakReferenceList.cxx \
     windowsRegistry.cxx \
     zStream.cxx zStreamBuf.cxx
 
@@ -146,8 +160,12 @@
     nativeNumericData.I nativeNumericData.h numeric_types.h \
     ordered_vector.h ordered_vector.I ordered_vector.T \
     password_hash.h \
-    patchfile.I patchfile.h pointerTo.I pointerTo.h \
-    pointerToArray.I pointerToArray.h profileTimer.I \
+    patchfile.I patchfile.h \
+    pointerTo.I pointerTo.h \
+    pointerToArray.I pointerToArray.h \
+    pointerToBase.I pointerToBase.h \
+    pointerToVoid.I pointerToVoid.h \
+    profileTimer.I \
     profileTimer.h pta_uchar.h \
     ramfile.I ramfile.h \
     referenceCount.I referenceCount.h \
@@ -174,6 +192,10 @@
     virtualFileMountMultifile.I virtualFileMountSystem.h \
     virtualFileMountSystem.I virtualFileSimple.h virtualFileSimple.I \
     virtualFileSystem.h virtualFileSystem.I \
+    weakPointerTo.I weakPointerTo.h \
+    weakPointerToBase.I weakPointerToBase.h \
+    weakPointerToVoid.I weakPointerToVoid.h \
+    weakReferenceList.I weakReferenceList.h \
     windowsRegistry.h \
     zStream.I zStream.h zStreamBuf.h
 

+ 8 - 0
panda/src/express/express_composite2.cxx

@@ -1,6 +1,10 @@
 #include "patchfile.cxx"
 #include "password_hash.cxx"
 #include "pmutex.cxx"
+#include "pointerTo.cxx"
+#include "pointerToArray.cxx"
+#include "pointerToBase.cxx"
+#include "pointerToVoid.cxx"
 #include "profileTimer.cxx"
 #include "pta_uchar.cxx"
 #include "ramfile.cxx"
@@ -32,6 +36,10 @@
 #include "virtualFileMountSystem.cxx"
 #include "virtualFileSimple.cxx"
 #include "virtualFileSystem.cxx"
+#include "weakPointerTo.cxx"
+#include "weakPointerToBase.cxx"
+#include "weakPointerToVoid.cxx"
+#include "weakReferenceList.cxx"
 #include "windowsRegistry.cxx"
 #include "zStream.cxx"
 #include "zStreamBuf.cxx"

+ 10 - 334
panda/src/express/pointerTo.I

@@ -17,330 +17,6 @@
 ////////////////////////////////////////////////////////////////////
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Constructor
-//       Access: Protected
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE PointerToBase<T>::
-PointerToBase(To *ptr) {
-  _ptr = (To *)NULL;
-  reassign(ptr);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Copy Constructor
-//       Access: Protected
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE PointerToBase<T>::
-PointerToBase(const PointerToBase<T> &copy) {
-  _ptr = (To *)NULL;
-  reassign(copy);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Destructor
-//       Access: Protected
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE PointerToBase<T>::
-~PointerToBase() {
-  reassign((To *)NULL);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::reassign
-//       Access: Protected
-//  Description: This is the main work of the PointerTo family.  When
-//               the pointer is reassigned, decrement the old
-//               reference count and increment the new one.
-////////////////////////////////////////////////////////////////////
-template<class T>
-void PointerToBase<T>::
-reassign(To *ptr) {
-  if (ptr != _ptr) {
-    // First save the old pointer; we won't delete it until we have
-    // assigned the new one.  We do this just in case there are
-    // cascading effects from deleting this pointer that might
-    // inadvertently delete the new one.  (Don't laugh--it's
-    // happened!)
-    To *old_ptr = _ptr;
-
-    _ptr = ptr;
-    if (_ptr != (To *)NULL) {
-      _ptr->ref();
-#ifdef DO_MEMORY_USAGE
-      if (MemoryUsage::get_track_memory_usage()) {
-        // Make sure the MemoryUsage record knows what the TypeHandle
-        // is, if we know it ourselves.
-        TypeHandle type = get_type_handle(To);
-        if (type == TypeHandle::none()) {
-          do_init_type(To);
-          type = get_type_handle(To);
-        }
-        if (type != TypeHandle::none()) {
-          MemoryUsage::update_type(_ptr, type);
-        }
-      }
-#endif
-    }
-
-    // Now delete the old pointer.
-    if (old_ptr != (To *)NULL) {
-      unref_delete(old_ptr);
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::reassign
-//       Access: Protected
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE void PointerToBase<T>::
-reassign(const PointerToBase<To> &copy) {
-  reassign(copy._ptr);
-}
-
-#ifndef CPPPARSER
-#ifndef WIN32_VC
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Equivalence operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator == (const To *other) const {
-  return _ptr == other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Nonequivalence operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator != (const To *other) const {
-  return _ptr != other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Greater-than operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator > (const To *other) const {
-  return _ptr > other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Less-than-or-equal operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator <= (const To *other) const {
-  return _ptr <= other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Greater-than-or-equal operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator >= (const To *other) const {
-  return _ptr >= other;
-}
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Equivalence operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator == (To *other) const {
-  return _ptr == other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Nonequivalence operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator != (To *other) const {
-  return _ptr != other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Greater-than operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator > (To *other) const {
-  return _ptr > other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Less-than-or-equal operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator <= (To *other) const {
-  return _ptr <= other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Greater-than-or-equal operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator >= (To *other) const {
-  return _ptr >= other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Equivalence operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator == (const PointerToBase<To> &other) const {
-  return _ptr == other._ptr;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Nonequivalence operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator != (const PointerToBase<To> &other) const {
-  return _ptr != other._ptr;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Greater-than operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator > (const PointerToBase<To> &other) const {
-  return _ptr > other._ptr;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Less-than-or-equal operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator <= (const PointerToBase<To> &other) const {
-  return _ptr <= other._ptr;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Greater-than-or-equal operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator >= (const PointerToBase<To> &other) const {
-  return _ptr >= other._ptr;
-}
-#endif  // WIN32_VC
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Less-than operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator < (const To *other) const {
-  return _ptr < other;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::Less-than operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-operator < (const PointerToBase<To> &other) const {
-  return _ptr < other._ptr;
-}
-
-#endif  // CPPPARSER
-
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::is_null
-//       Access: Public
-//  Description: Returns true if the PointerTo is a NULL pointer,
-//               false otherwise.  (Direct comparison to a NULL
-//               pointer also works.)
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE bool PointerToBase<T>::
-is_null() const {
-  return (_ptr == NULL);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::clear
-//       Access: Public
-//  Description: A convenient way to set the PointerTo object to NULL.
-//               (Assignment to a NULL pointer also works, of course.)
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE void PointerToBase<T>::
-clear() {
-  reassign((To *)NULL);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: PointerToBase::output
-//       Access: Public
-//  Description: A handy function to output PointerTo's as a hex
-//               pointer followed by a reference count.
-////////////////////////////////////////////////////////////////////
-template<class T>
-INLINE void PointerToBase<T>::
-output(ostream &out) const {
-  out << (void *)_ptr;
-  if (_ptr != (To *)NULL) {
-    out << ":" << _ptr->get_ref_count();
-  }
-}
-
-
 ////////////////////////////////////////////////////////////////////
 //     Function: PointerTo::Constructor
 //       Access: Public
@@ -371,7 +47,7 @@ PointerTo(const PointerTo<T> &copy) :
 template<class T>
 INLINE TYPENAME PointerTo<T>::To &PointerTo<T>::
 operator *() const {
-  return *_ptr;
+  return *((To *)_void_ptr);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -382,7 +58,7 @@ operator *() const {
 template<class T>
 INLINE TYPENAME PointerTo<T>::To *PointerTo<T>::
 operator -> () const {
-  return _ptr;
+  return (To *)_void_ptr;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -398,7 +74,7 @@ operator -> () const {
 template<class T>
 INLINE PointerTo<T>::
 operator TYPENAME PointerToBase<T>::To *() const {
-  return _ptr;
+  return (To *)_void_ptr;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -411,7 +87,7 @@ operator TYPENAME PointerToBase<T>::To *() const {
 template<class T>
 INLINE TYPENAME PointerTo<T>::To *PointerTo<T>::
 p() const {
-  return _ptr;
+  return (To *)_void_ptr;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -482,7 +158,7 @@ ConstPointerTo(const ConstPointerTo<T> &copy) :
 template<class T>
 INLINE const TYPENAME ConstPointerTo<T>::To &ConstPointerTo<T>::
 operator *() const {
-  return *_ptr;
+  return *((To *)_void_ptr);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -493,7 +169,7 @@ operator *() const {
 template<class T>
 INLINE const TYPENAME ConstPointerTo<T>::To *ConstPointerTo<T>::
 operator -> () const {
-  return _ptr;
+  return (To *)_void_ptr;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -510,7 +186,7 @@ operator -> () const {
 template<class T>
 INLINE ConstPointerTo<T>::
 operator const TYPENAME PointerToBase<T>::To *() const {
-  return _ptr;
+  return (To *)_void_ptr;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -523,7 +199,7 @@ operator const TYPENAME PointerToBase<T>::To *() const {
 template<class T>
 INLINE const TYPENAME ConstPointerTo<T>::To *ConstPointerTo<T>::
 p() const {
-  return _ptr;
+  return (To *)_void_ptr;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -545,7 +221,7 @@ operator = (const To *ptr) {
 ////////////////////////////////////////////////////////////////////
 template<class T>
 INLINE ConstPointerTo<T> &ConstPointerTo<T>::
-operator = (const ConstPointerTo<T> &copy) {
+operator = (const PointerTo<T> &copy) {
   reassign((const PointerToBase<T> &)copy);
   return *this;
 }
@@ -557,7 +233,7 @@ operator = (const ConstPointerTo<T> &copy) {
 ////////////////////////////////////////////////////////////////////
 template<class T>
 INLINE ConstPointerTo<T> &ConstPointerTo<T>::
-operator = (const PointerTo<T> &copy) {
+operator = (const ConstPointerTo<T> &copy) {
   reassign((const PointerToBase<T> &)copy);
   return *this;
 }

+ 19 - 0
panda/src/express/pointerTo.cxx

@@ -0,0 +1,19 @@
+// Filename: pointerTo.cxx
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pointerTo.h"

+ 2 - 72
panda/src/express/pointerTo.h

@@ -70,77 +70,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "pandabase.h"
-
-#include "referenceCount.h"
-#include "typedef.h"
-#include "memoryUsage.h"
-#include "config_express.h"
-
-
-////////////////////////////////////////////////////////////////////
-//       Class : PointerToBase
-// Description : This is the base class for PointerTo and
-//               ConstPointerTo.  Don't try to use it directly; use
-//               either derived class instead.
-////////////////////////////////////////////////////////////////////
-template <class T>
-class PointerToBase {
-public:
-  typedef T To;
-
-protected:
-  INLINE PointerToBase(To *ptr);
-  INLINE PointerToBase(const PointerToBase<T> &copy);
-  INLINE ~PointerToBase();
-
-  void reassign(To *ptr);
-
-  INLINE void reassign(const PointerToBase<To> &copy);
-
-  To *_ptr;
-
-  // No assignment or retrieval functions are declared in
-  // PointerToBase, because we will have to specialize on const
-  // vs. non-const later.
-
-public:
-  // These comparison functions are common to all things PointerTo, so
-  // they're defined up here.
-#ifndef CPPPARSER
-#ifndef WIN32_VC
-  INLINE bool operator == (const To *other) const;
-  INLINE bool operator != (const To *other) const;
-  INLINE bool operator > (const To *other) const;
-  INLINE bool operator <= (const To *other) const;
-  INLINE bool operator >= (const To *other) const;
-  INLINE bool operator == (To *other) const;
-  INLINE bool operator != (To *other) const;
-  INLINE bool operator > (To *other) const;
-  INLINE bool operator <= (To *other) const;
-  INLINE bool operator >= (To *other) const;
-
-  INLINE bool operator == (const PointerToBase<To> &other) const;
-  INLINE bool operator != (const PointerToBase<To> &other) const;
-  INLINE bool operator > (const PointerToBase<To> &other) const;
-  INLINE bool operator <= (const PointerToBase<To> &other) const;
-  INLINE bool operator >= (const PointerToBase<To> &other) const;
-#endif  // WIN32_VC
-  INLINE bool operator < (const To *other) const;
-  INLINE bool operator < (const PointerToBase<To> &other) const;
-#endif  // CPPPARSER
-
-PUBLISHED:
-  INLINE bool is_null() const;
-  INLINE void clear();
-
-  void output(ostream &out) const;
-};
-
-template<class T>
-INLINE ostream &operator <<(ostream &out, const PointerToBase<T> &pointer) {
-  pointer.output(out);
-  return out;
-}
+#include "pointerToBase.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : PointerTo
@@ -222,8 +152,8 @@ PUBLISHED:
   INLINE const To *p() const;
 
   INLINE ConstPointerTo<T> &operator = (const To *ptr);
-  INLINE ConstPointerTo<T> &operator = (const ConstPointerTo<T> &copy);
   INLINE ConstPointerTo<T> &operator = (const PointerTo<T> &copy);
+  INLINE ConstPointerTo<T> &operator = (const ConstPointerTo<T> &copy);
 
   // These functions normally wouldn't need to be redefined here, but
   // we do so anyway just to help out interrogate (which doesn't seem

+ 102 - 103
panda/src/express/pointerToArray.I

@@ -38,10 +38,10 @@ PointerToArray() :
 template<class Element>
 INLINE PointerToArray<Element> 
 PointerToArray<Element>::empty_array(size_type n) {
-    PointerToArray<Element> temp;
-    temp.reserve(n);
-    temp._ptr->insert(temp._ptr->begin(), n, Element());
-    return temp;
+  PointerToArray<Element> temp;
+  temp.reserve(n);
+  ((To *)temp._void_ptr)->insert(((To *)temp._void_ptr)->begin(), n, Element());
+  return temp;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -53,7 +53,7 @@ template<class Element>
 INLINE PointerToArray<Element>::
 PointerToArray(size_type n, const Element &value) :
   PointerToBase<RefCountObj<pvector<Element> > >(new RefCountObj<pvector<Element> >) {
-  _ptr->reserve(n);
+  ((To *)_void_ptr)->reserve(n);
   insert(begin(), n, value);
 }
 
@@ -77,10 +77,10 @@ PointerToArray(const PointerToArray<Element> &copy) :
 template<class Element>
 INLINE TYPENAME PointerToArray<Element>::iterator PointerToArray<Element>::
 begin() const {
-  if (_ptr == NULL) {
+  if (_void_ptr == NULL) {
     return _empty_array.begin();
   }
-  return _ptr->begin();
+  return ((To *)_void_ptr)->begin();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -91,10 +91,10 @@ begin() const {
 template<class Element>
 INLINE TYPENAME PointerToArray<Element>::iterator PointerToArray<Element>::
 end() const {
-  if (_ptr == NULL) {
+  if (_void_ptr == NULL) {
     return _empty_array.begin();
   }
-  return _ptr->end();
+  return ((To *)_void_ptr)->end();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -105,10 +105,10 @@ end() const {
 template<class Element>
 INLINE TYPENAME PointerToArray<Element>::reverse_iterator PointerToArray<Element>::
 rbegin() const {
-  if (_ptr == NULL) {
+  if (_void_ptr == NULL) {
     return _empty_array.rbegin();
   }
-  return _ptr->rbegin();
+  return ((To *)_void_ptr)->rbegin();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -119,10 +119,10 @@ rbegin() const {
 template<class Element>
 INLINE TYPENAME PointerToArray<Element>::reverse_iterator PointerToArray<Element>::
 rend() const {
-  if (_ptr == NULL) {
+  if (_void_ptr == NULL) {
     return _empty_array.rbegin();
   }
-  return _ptr->rend();
+  return ((To *)_void_ptr)->rend();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -133,7 +133,7 @@ rend() const {
 template<class Element>
 INLINE TYPENAME PointerToArray<Element>::size_type PointerToArray<Element>::
 size() const {
-  return (_ptr == NULL) ? 0 : _ptr->size();
+  return (_void_ptr == NULL) ? 0 : ((To *)_void_ptr)->size();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -144,10 +144,10 @@ size() const {
 template<class Element>
 INLINE TYPENAME PointerToArray<Element>::size_type PointerToArray<Element>::
 max_size() const {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  return _ptr->max_size();
+  return ((To *)_void_ptr)->max_size();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -158,7 +158,7 @@ max_size() const {
 template<class Element>
 INLINE bool PointerToArray<Element>::
 empty() const {
-  return (_ptr == NULL) ? true : _ptr->empty();
+  return (_void_ptr == NULL) ? true : ((To *)_void_ptr)->empty();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -169,10 +169,10 @@ empty() const {
 template<class Element>
 INLINE void PointerToArray<Element>::
 reserve(TYPENAME PointerToArray<Element>::size_type n) {
-  if (_ptr == NULL) {
+  if (_void_ptr == NULL) {
     reassign(new RefCountObj<pvector<Element> >);
   }
-  _ptr->reserve(n);
+  ((To *)_void_ptr)->reserve(n);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -183,8 +183,8 @@ reserve(TYPENAME PointerToArray<Element>::size_type n) {
 template<class Element>
 INLINE TYPENAME PointerToArray<Element>::size_type PointerToArray<Element>::
 capacity() const {
-  nassertr(_ptr != NULL, 0);
-  return _ptr->capacity();
+  nassertr(_void_ptr != NULL, 0);
+  return ((To *)_void_ptr)->capacity();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -195,13 +195,13 @@ capacity() const {
 template<class Element>
 INLINE TYPENAME PointerToArray<Element>::reference PointerToArray<Element>::
 front() const {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  nassertd(!_ptr->empty()) {
-    _ptr->push_back(Element());
+  nassertd(!((To *)_void_ptr)->empty()) {
+    ((To *)_void_ptr)->push_back(Element());
   }
-  return _ptr->front();
+  return ((To *)_void_ptr)->front();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -212,13 +212,13 @@ front() const {
 template<class Element>
 INLINE TYPENAME PointerToArray<Element>::reference PointerToArray<Element>::
 back() const {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  nassertd(!_ptr->empty()) {
-    _ptr->push_back(Element());
+  nassertd(!((To *)_void_ptr)->empty()) {
+    ((To *)_void_ptr)->push_back(Element());
   }
-  return _ptr->back();
+  return ((To *)_void_ptr)->back();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -229,10 +229,10 @@ back() const {
 template<class Element>
 INLINE TYPENAME PointerToArray<Element>::iterator PointerToArray<Element>::
 insert(iterator position, const Element &x) const {
-  nassertr(_ptr != NULL, position);
-  nassertr(position >= _ptr->begin() &&
-           position <= _ptr->end(), position);
-  return _ptr->insert(position, x);
+  nassertr(_void_ptr != NULL, position);
+  nassertr(position >= ((To *)_void_ptr)->begin() &&
+           position <= ((To *)_void_ptr)->end(), position);
+  return ((To *)_void_ptr)->insert(position, x);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -243,10 +243,10 @@ insert(iterator position, const Element &x) const {
 template<class Element>
 INLINE void PointerToArray<Element>::
 insert(iterator position, size_type n, const Element &x) const {
-  nassertv(_ptr != NULL);
-  nassertv(position >= _ptr->begin() &&
-           position <= _ptr->end());
-  _ptr->insert(position, n, x);
+  nassertv(_void_ptr != NULL);
+  nassertv(position >= ((To *)_void_ptr)->begin() &&
+           position <= ((To *)_void_ptr)->end());
+  ((To *)_void_ptr)->insert(position, n, x);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -257,12 +257,12 @@ insert(iterator position, size_type n, const Element &x) const {
 template<class Element>
 INLINE void PointerToArray<Element>::
 erase(iterator position) const {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  nassertv(position >= _ptr->begin() &&
-           position <= _ptr->end());
-  _ptr->erase(position);
+  nassertv(position >= ((To *)_void_ptr)->begin() &&
+           position <= ((To *)_void_ptr)->end());
+  ((To *)_void_ptr)->erase(position);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -273,12 +273,12 @@ erase(iterator position) const {
 template<class Element>
 INLINE void PointerToArray<Element>::
 erase(iterator first, iterator last) const {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  nassertv(first >= _ptr->begin() && first <= _ptr->end());
-  nassertv(last >= _ptr->begin() && last <= _ptr->end());
-  _ptr->erase(first, last);
+  nassertv(first >= ((To *)_void_ptr)->begin() && first <= ((To *)_void_ptr)->end());
+  nassertv(last >= ((To *)_void_ptr)->begin() && last <= ((To *)_void_ptr)->end());
+  ((To *)_void_ptr)->erase(first, last);
 }
 
 #if !defined(WIN32_VC)
@@ -290,14 +290,14 @@ erase(iterator first, iterator last) const {
 template<class Element>
 INLINE TYPENAME PointerToArray<Element>::reference PointerToArray<Element>::
 operator [](size_type n) const {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  nassertd(!_ptr->empty()) {
-    _ptr->push_back(Element());
+  nassertd(!((To *)_void_ptr)->empty()) {
+    ((To *)_void_ptr)->push_back(Element());
   }
-  nassertr(n < _ptr->size(), _ptr->operator[](0));
-  return _ptr->operator[](n);
+  nassertr(n < ((To *)_void_ptr)->size(), ((To *)_void_ptr)->operator[](0));
+  return ((To *)_void_ptr)->operator[](n);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -339,7 +339,7 @@ get_element(size_type n) const {
 template<class Element>
 INLINE void PointerToArray<Element>::
 set_element(size_type n, const_reference value) {
-  nassertv(n < _ptr->size());
+  nassertv(n < ((To *)_void_ptr)->size());
   (*this)[n] = value;
 }
 
@@ -351,10 +351,10 @@ set_element(size_type n, const_reference value) {
 template<class Element>
 INLINE void PointerToArray<Element>::
 push_back(const Element &x) {
-  if (_ptr == NULL) {
+  if (_void_ptr == NULL) {
     reassign(new RefCountObj<pvector<Element> >);
   }
-  _ptr->push_back(x);
+  ((To *)_void_ptr)->push_back(x);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -365,11 +365,11 @@ push_back(const Element &x) {
 template<class Element>
 INLINE void PointerToArray<Element>::
 pop_back() {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  nassertv(!_ptr->empty());
-  _ptr->pop_back();
+  nassertv(!((To *)_void_ptr)->empty());
+  ((To *)_void_ptr)->pop_back();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -382,11 +382,11 @@ pop_back() {
 template<class Element>
 INLINE void PointerToArray<Element>::
 make_empty() {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  nassertv(!_ptr->empty());
-  _ptr->clear();
+  nassertv(!((To *)_void_ptr)->empty());
+  ((To *)_void_ptr)->clear();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -401,7 +401,7 @@ make_empty() {
 template<class Element>
 INLINE PointerToArray<Element>::
 operator Element *() const {
-  return (_ptr == NULL) ? (Element *)NULL : &(_ptr->front());
+  return (_void_ptr == NULL) ? (Element *)NULL : &(((To *)_void_ptr)->front());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -414,7 +414,7 @@ operator Element *() const {
 template<class Element>
 INLINE Element *PointerToArray<Element>::
 p() const {
-  return (_ptr == NULL) ? (Element *)NULL : &(_ptr->front());
+  return (_void_ptr == NULL) ? (Element *)NULL : &(((To *)_void_ptr)->front());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -426,23 +426,22 @@ p() const {
 template<class Element>
 INLINE pvector<Element> &PointerToArray<Element>::
 v() const {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  return *_ptr;
+  return *((To *)_void_ptr);
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: PointerToArray::get_void_ptr
 //       Access: Public
 //  Description: Returns the reference to memory where the vector
-//               is stored.  To be used only with get_void_ptr
+//               is stored.  To be used only with set_void_ptr
 ////////////////////////////////////////////////////////////////////
 template<class Element>
-INLINE void* PointerToArray<Element>::
-get_void_ptr() const
-{
-  return PointerToBase<RefCountObj<pvector<Element> > >::_ptr;
+INLINE void *PointerToArray<Element>::
+get_void_ptr() const {
+  return _void_ptr;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -452,10 +451,10 @@ get_void_ptr() const
 ////////////////////////////////////////////////////////////////////
 template<class Element>
 INLINE void PointerToArray<Element>::
-set_void_ptr(void* p)
-{
-  reassign((RefCountObj<pvector<Element> > *)p);
+set_void_ptr(void *p) {
+  reassign((To *)p);
 }
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PointerToArray::get_ref_count
 //       Access: Public
@@ -464,7 +463,7 @@ set_void_ptr(void* p)
 template<class Element>
 INLINE int PointerToArray<Element>::
 get_ref_count() const {
-  return (_ptr == NULL) ? 0 : _ptr->get_ref_count();
+  return (_void_ptr == NULL) ? 0 : ((To *)_void_ptr)->get_ref_count();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -550,10 +549,10 @@ ConstPointerToArray(const ConstPointerToArray<Element> &copy) :
 template<class Element>
 INLINE TYPENAME ConstPointerToArray<Element>::iterator ConstPointerToArray<Element>::
 begin() const {
-  if (_ptr == NULL) {
+  if (_void_ptr == NULL) {
     return _empty_array.begin();
   }
-  return _ptr->begin();
+  return ((To *)_void_ptr)->begin();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -564,10 +563,10 @@ begin() const {
 template<class Element>
 INLINE TYPENAME ConstPointerToArray<Element>::iterator ConstPointerToArray<Element>::
 end() const {
-  if (_ptr == NULL) {
+  if (_void_ptr == NULL) {
     return _empty_array.begin();
   }
-  return _ptr->end();
+  return ((To *)_void_ptr)->end();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -578,10 +577,10 @@ end() const {
 template<class Element>
 INLINE TYPENAME ConstPointerToArray<Element>::reverse_iterator ConstPointerToArray<Element>::
 rbegin() const {
-  if (_ptr == NULL) {
+  if (_void_ptr == NULL) {
     return _empty_array.rbegin();
   }
-  return _ptr->rbegin();
+  return ((To *)_void_ptr)->rbegin();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -592,10 +591,10 @@ rbegin() const {
 template<class Element>
 INLINE TYPENAME ConstPointerToArray<Element>::reverse_iterator ConstPointerToArray<Element>::
 rend() const {
-  if (_ptr == NULL) {
+  if (_void_ptr == NULL) {
     return _empty_array.rbegin();
   }
-  return _ptr->rend();
+  return ((To *)_void_ptr)->rend();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -606,7 +605,7 @@ rend() const {
 template<class Element>
 INLINE TYPENAME ConstPointerToArray<Element>::size_type ConstPointerToArray<Element>::
 size() const {
-  return (_ptr == NULL) ? 0 : _ptr->size();
+  return (_void_ptr == NULL) ? 0 : ((To *)_void_ptr)->size();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -617,10 +616,10 @@ size() const {
 template<class Element>
 INLINE TYPENAME ConstPointerToArray<Element>::size_type ConstPointerToArray<Element>::
 max_size() const {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  return _ptr->max_size();
+  return ((To *)_void_ptr)->max_size();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -631,7 +630,7 @@ max_size() const {
 template<class Element>
 INLINE bool ConstPointerToArray<Element>::
 empty() const {
-  return (_ptr == NULL) ? true : _ptr->empty();
+  return (_void_ptr == NULL) ? true : ((To *)_void_ptr)->empty();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -642,10 +641,10 @@ empty() const {
 template<class Element>
 INLINE TYPENAME ConstPointerToArray<Element>::size_type ConstPointerToArray<Element>::
 capacity() const {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  return _ptr->capacity();
+  return ((To *)_void_ptr)->capacity();
 }
 
 #ifndef WIN32_VC
@@ -657,14 +656,14 @@ capacity() const {
 template<class Element>
 INLINE TYPENAME ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
 operator [](size_type n) const {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  nassertd(!_ptr->empty()) {
-    _ptr->push_back(Element());
+  nassertd(!((To *)_void_ptr)->empty()) {
+    ((To *)_void_ptr)->push_back(Element());
   }
-  nassertr(n < _ptr->size(), _ptr->operator[](0));
-  return _ptr->operator[](n);
+  nassertr(n < ((To *)_void_ptr)->size(), ((To *)_void_ptr)->operator[](0));
+  return ((To *)_void_ptr)->operator[](n);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -687,13 +686,13 @@ operator [](int n) const {
 template<class Element>
 INLINE TYPENAME ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
 front() const {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  nassertd(!_ptr->empty()) {
-    _ptr->push_back(Element());
+  nassertd(!((To *)_void_ptr)->empty()) {
+    ((To *)_void_ptr)->push_back(Element());
   }
-  return _ptr->front();
+  return ((To *)_void_ptr)->front();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -704,13 +703,13 @@ front() const {
 template<class Element>
 INLINE TYPENAME ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
 back() const {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
-  nassertd(!_ptr->empty()) {
-    _ptr->push_back(Element());
+  nassertd(!((To *)_void_ptr)->empty()) {
+    ((To *)_void_ptr)->push_back(Element());
   }
-  return _ptr->back();
+  return ((To *)_void_ptr)->back();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -725,7 +724,7 @@ back() const {
 template<class Element>
 INLINE ConstPointerToArray<Element>::
 operator const Element *() const {
-  return (_ptr == NULL) ? (const Element *)NULL : &(_ptr->front());
+  return (_void_ptr == NULL) ? (const Element *)NULL : &(((To *)_void_ptr)->front());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -738,7 +737,7 @@ operator const Element *() const {
 template<class Element>
 INLINE const Element *ConstPointerToArray<Element>::
 p() const {
-  return (_ptr == NULL) ? (const Element *)NULL : &(_ptr->front());
+  return (_void_ptr == NULL) ? (const Element *)NULL : &(((To *)_void_ptr)->front());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -750,7 +749,7 @@ p() const {
 template<class Element>
 INLINE const pvector<Element> &ConstPointerToArray<Element>::
 v() const {
-  nassertd(_ptr != NULL) {
+  nassertd(_void_ptr != NULL) {
     ((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
   }
   return *_ptr;
@@ -764,7 +763,7 @@ v() const {
 template<class Element>
 INLINE int ConstPointerToArray<Element>::
 get_ref_count() const {
-  return (_ptr == NULL) ? 0 : _ptr->get_ref_count();
+  return (_void_ptr == NULL) ? 0 : ((To *)_void_ptr)->get_ref_count();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 19 - 0
panda/src/express/pointerToArray.cxx

@@ -0,0 +1,19 @@
+// Filename: pointerToArray.cxx
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pointerToArray.h"

+ 2 - 0
panda/src/express/pointerToArray.h

@@ -91,6 +91,7 @@
 template <class Element>
 class PointerToArray : public PointerToBase<RefCountObj<pvector<Element> > > {
 public:
+  typedef TYPENAME PointerToBase<RefCountObj<pvector<Element> > >::To To;
   typedef TYPENAME pvector<Element>::value_type value_type;
   typedef TYPENAME pvector<Element>::reference reference;
   typedef TYPENAME pvector<Element>::const_reference const_reference;
@@ -200,6 +201,7 @@ private:
 template <class Element>
 class ConstPointerToArray : public PointerToBase<RefCountObj<pvector<Element> > > {
 public:
+  typedef TYPENAME PointerToBase<RefCountObj<pvector<Element> > >::To To;
   typedef TYPENAME pvector<Element>::value_type value_type;
   typedef TYPENAME pvector<Element>::const_reference reference;
   typedef TYPENAME pvector<Element>::const_reference const_reference;

+ 339 - 0
panda/src/express/pointerToBase.I

@@ -0,0 +1,339 @@
+// Filename: pointerToBase.I
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Constructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE PointerToBase<T>::
+PointerToBase(To *ptr) {
+  reassign(ptr);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Copy Constructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE PointerToBase<T>::
+PointerToBase(const PointerToBase<T> &copy) {
+  reassign(copy);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Destructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE PointerToBase<T>::
+~PointerToBase() {
+  reassign((To *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::reassign
+//       Access: Protected
+//  Description: This is the main work of the PointerTo family.  When
+//               the pointer is reassigned, decrement the old
+//               reference count and increment the new one.
+////////////////////////////////////////////////////////////////////
+template<class T>
+void PointerToBase<T>::
+reassign(To *ptr) {
+  if (ptr != (To *)_void_ptr) {
+    // First save the old pointer; we won't delete it until we have
+    // assigned the new one.  We do this just in case there are
+    // cascading effects from deleting this pointer that might
+    // inadvertently delete the new one.  (Don't laugh--it's
+    // happened!)
+    To *old_ptr = (To *)_void_ptr;
+
+    _void_ptr = (void *)ptr;
+    if (ptr != (To *)NULL) {
+      ptr->ref();
+#ifdef DO_MEMORY_USAGE
+      if (MemoryUsage::get_track_memory_usage()) {
+        // Make sure the MemoryUsage record knows what the TypeHandle
+        // is, if we know it ourselves.
+        TypeHandle type = get_type_handle(To);
+        if (type == TypeHandle::none()) {
+          do_init_type(To);
+          type = get_type_handle(To);
+        }
+        if (type != TypeHandle::none()) {
+          MemoryUsage::update_type(ptr, type);
+        }
+      }
+#endif
+    }
+
+    // Now delete the old pointer.
+    if (old_ptr != (To *)NULL) {
+      unref_delete(old_ptr);
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::reassign
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE void PointerToBase<T>::
+reassign(const PointerToBase<To> &copy) {
+  reassign((To *)copy._void_ptr);
+}
+
+#ifndef CPPPARSER
+#ifndef WIN32_VC
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Equivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator == (const To *other) const {
+  return (To *)_void_ptr == other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Nonequivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator != (const To *other) const {
+  return (To *)_void_ptr != other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Greater-than operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator > (const To *other) const {
+  return (To *)_void_ptr > other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Less-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator <= (const To *other) const {
+  return (To *)_void_ptr <= other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Greater-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator >= (const To *other) const {
+  return (To *)_void_ptr >= other;
+}
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Equivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator == (To *other) const {
+  return (To *)_void_ptr == other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Nonequivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator != (To *other) const {
+  return (To *)_void_ptr != other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Greater-than operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator > (To *other) const {
+  return (To *)_void_ptr > other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Less-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator <= (To *other) const {
+  return (To *)_void_ptr <= other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Greater-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator >= (To *other) const {
+  return (To *)_void_ptr >= other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Equivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator == (const PointerToBase<To> &other) const {
+  return (To *)_void_ptr == (To *)other._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Nonequivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator != (const PointerToBase<To> &other) const {
+  return (To *)_void_ptr != (To *)other._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Greater-than operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator > (const PointerToBase<To> &other) const {
+  return (To *)_void_ptr > (To *)other._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Less-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator <= (const PointerToBase<To> &other) const {
+  return (To *)_void_ptr <= (To *)other._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Greater-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator >= (const PointerToBase<To> &other) const {
+  return (To *)_void_ptr >= (To *)other._void_ptr;
+}
+#endif  // WIN32_VC
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Less-than operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator < (const To *other) const {
+  return (To *)_void_ptr < other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::Less-than operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+operator < (const PointerToBase<To> &other) const {
+  return (To *)_void_ptr < (To *)other._void_ptr;
+}
+
+#endif  // CPPPARSER
+
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::is_null
+//       Access: Public
+//  Description: Returns true if the PointerTo is a NULL pointer,
+//               false otherwise.  (Direct comparison to a NULL
+//               pointer also works.)
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool PointerToBase<T>::
+is_null() const {
+  return (_void_ptr == (void *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::clear
+//       Access: Public
+//  Description: A convenient way to set the PointerTo object to NULL.
+//               (Assignment to a NULL pointer also works, of course.)
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE void PointerToBase<T>::
+clear() {
+  reassign((To *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToBase::output
+//       Access: Public
+//  Description: A handy function to output PointerTo's as a hex
+//               pointer followed by a reference count.
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE void PointerToBase<T>::
+output(ostream &out) const {
+  out << _void_ptr;
+  if (_void_ptr != (void *)NULL) {
+    out << ":" << ((To *)_void_ptr)->get_ref_count();
+  }
+}

+ 19 - 0
panda/src/express/pointerToBase.cxx

@@ -0,0 +1,19 @@
+// Filename: pointerToBase.cxx
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pointerToBase.h"

+ 93 - 0
panda/src/express/pointerToBase.h

@@ -0,0 +1,93 @@
+// Filename: pointerToBase.h
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef POINTERTOBASE_H
+#define POINTERTOBASE_H
+
+#include "pandabase.h"
+#include "pointerToVoid.h"
+#include "referenceCount.h"
+#include "typedef.h"
+#include "memoryUsage.h"
+#include "config_express.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : PointerToBase
+// Description : This is the base class for PointerTo and
+//               ConstPointerTo.  Don't try to use it directly; use
+//               either derived class instead.
+////////////////////////////////////////////////////////////////////
+template <class T>
+class PointerToBase : public PointerToVoid {
+public:
+  typedef T To;
+
+protected:
+  INLINE PointerToBase(To *ptr);
+  INLINE PointerToBase(const PointerToBase<T> &copy);
+  INLINE ~PointerToBase();
+
+  void reassign(To *ptr);
+  INLINE void reassign(const PointerToBase<To> &copy);
+
+  // No assignment or retrieval functions are declared in
+  // PointerToBase, because we will have to specialize on const
+  // vs. non-const later.
+
+public:
+  // These comparison functions are common to all things PointerTo, so
+  // they're defined up here.
+#ifndef CPPPARSER
+#ifndef WIN32_VC
+  INLINE bool operator == (const To *other) const;
+  INLINE bool operator != (const To *other) const;
+  INLINE bool operator > (const To *other) const;
+  INLINE bool operator <= (const To *other) const;
+  INLINE bool operator >= (const To *other) const;
+  INLINE bool operator == (To *other) const;
+  INLINE bool operator != (To *other) const;
+  INLINE bool operator > (To *other) const;
+  INLINE bool operator <= (To *other) const;
+  INLINE bool operator >= (To *other) const;
+
+  INLINE bool operator == (const PointerToBase<To> &other) const;
+  INLINE bool operator != (const PointerToBase<To> &other) const;
+  INLINE bool operator > (const PointerToBase<To> &other) const;
+  INLINE bool operator <= (const PointerToBase<To> &other) const;
+  INLINE bool operator >= (const PointerToBase<To> &other) const;
+#endif  // WIN32_VC
+  INLINE bool operator < (const To *other) const;
+  INLINE bool operator < (const PointerToBase<To> &other) const;
+#endif  // CPPPARSER
+
+PUBLISHED:
+  INLINE bool is_null() const;
+  INLINE void clear();
+
+  void output(ostream &out) const;
+};
+
+template<class T>
+INLINE ostream &operator <<(ostream &out, const PointerToBase<T> &pointer) {
+  pointer.output(out);
+  return out;
+}
+
+#include "pointerToBase.I"
+
+#endif

+ 38 - 0
panda/src/express/pointerToVoid.I

@@ -0,0 +1,38 @@
+// Filename: pointerToVoid.I
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToVoid::Constructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PointerToVoid::
+PointerToVoid() {
+  _void_ptr = (void *)NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PointerToVoid::Destructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE PointerToVoid::
+~PointerToVoid() {
+  nassertv(_void_ptr == (void *)NULL);
+}

+ 19 - 0
panda/src/express/pointerToVoid.cxx

@@ -0,0 +1,19 @@
+// Filename: pointerToVoid.cxx
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pointerToVoid.h"

+ 56 - 0
panda/src/express/pointerToVoid.h

@@ -0,0 +1,56 @@
+// Filename: pointerToVoid.h
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef POINTERTOVOID_H
+#define POINTERTOVOID_H
+
+#include "pandabase.h"
+#include "notify.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : PointerToVoid
+// Description : This is the non-template part of the base class for
+//               PointerTo and ConstPointerTo.  It is necessary so we
+//               can keep a pointer to a non-template class within the
+//               ReferenceCount object, to implement weak reference
+//               pointers--we need to have something to clean up when
+//               the ReferenceCount object destructs.
+//
+//               This is the base class for PointerToBase<T>.
+////////////////////////////////////////////////////////////////////
+class PointerToVoid {
+protected:
+  INLINE PointerToVoid();
+  INLINE ~PointerToVoid();
+
+  // Within the PointerToVoid class, we only store a void pointer.
+  // This is actually the (To *) pointer that is typecast to (void *)
+  // from the derived template classes.
+
+  // It is tempting to try to store a (ReferenceCount *) pointer here,
+  // but this is not useful because it prohibits defining, say,
+  // PT(PandaNode), or a PointerTo any class that inherits virtually
+  // from ReferenceCount.  (You can't downcast past a virtual
+  // inheritance level, but you can always cross-cast from a void
+  // pointer.)
+  void *_void_ptr;
+};
+
+#include "pointerToVoid.I"
+
+#endif

+ 62 - 0
panda/src/express/referenceCount.I

@@ -37,6 +37,7 @@ TypeHandle RefCountObj<Base>::_type_handle;
 ////////////////////////////////////////////////////////////////////
 INLINE ReferenceCount::
 ReferenceCount() {
+  _weak_list = (WeakReferenceList *)NULL;
   _ref_count = 0;
 #ifdef DO_MEMORY_USAGE
   MemoryUsage::record_pointer(this);
@@ -55,6 +56,7 @@ ReferenceCount() {
 ////////////////////////////////////////////////////////////////////
 INLINE ReferenceCount::
 ReferenceCount(const ReferenceCount &) {
+  _weak_list = (WeakReferenceList *)NULL;
   _ref_count = 0;
 #ifdef DO_MEMORY_USAGE
   MemoryUsage::record_pointer(this);
@@ -129,6 +131,12 @@ INLINE ReferenceCount::
   // all--onto a locally allocated one.
   nassertv(_ref_count == 0);
 
+  // Tell our weak reference holders that we're going away now.
+  if (_weak_list != (WeakReferenceList *)NULL) {
+    delete _weak_list;
+    _weak_list = (WeakReferenceList *)NULL;
+  }
+
 #ifndef NDEBUG
   // Ok, all clear to delete.  Now set the reference count to -100,
   // so we'll have a better chance of noticing if we happen to have
@@ -271,6 +279,60 @@ test_ref_count_integrity() const {
 #endif
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ReferenceCount::has_weak_list
+//       Access: Public
+//  Description: Returns true if this particular ReferenceCount object
+//               has a WeakReferenceList created, false otherwise.  In
+//               general, this will be true if there was ever a
+//               WeakPointerTo created for this object (even if there
+//               is not any for it now).
+////////////////////////////////////////////////////////////////////
+INLINE bool ReferenceCount::
+has_weak_list() const {
+  return _weak_list != (WeakReferenceList *)NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ReferenceCount::get_weak_list
+//       Access: Public
+//  Description: Returns the WeakReferenceList associated with this
+//               ReferenceCount object.  If there has never been a
+//               WeakReferenceList associated with this object,
+//               creates one now.
+////////////////////////////////////////////////////////////////////
+INLINE WeakReferenceList *ReferenceCount::
+get_weak_list() const {
+  if (_weak_list == (WeakReferenceList *)NULL) {
+    ((ReferenceCount *)this)->_weak_list = new WeakReferenceList;
+  }
+  return _weak_list;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ReferenceCount::weak_ref
+//       Access: Public
+//  Description: Adds the indicated PointerToVoid as a weak reference
+//               to this object.
+////////////////////////////////////////////////////////////////////
+INLINE void ReferenceCount::
+weak_ref(WeakPointerToVoid *ptv) {
+  get_weak_list()->add_reference(ptv);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ReferenceCount::weak_unref
+//       Access: Public
+//  Description: Removes the indicated PointerToVoid as a weak reference
+//               to this object.  It must have previously been added
+//               via a call to weak_ref().
+////////////////////////////////////////////////////////////////////
+INLINE void ReferenceCount::
+weak_unref(WeakPointerToVoid *ptv) {
+  nassertv(has_weak_list());
+  _weak_list->clear_reference(ptv);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: unref_delete
 //  Description: This global helper function will unref the given

+ 12 - 2
panda/src/express/referenceCount.h

@@ -20,7 +20,7 @@
 #define REFERENCECOUNT_H
 
 #include "pandabase.h"
-
+#include "weakReferenceList.h"
 #include "typedObject.h"
 #include "memoryUsage.h"
 #include "config_express.h"
@@ -53,6 +53,17 @@ PUBLISHED:
 
   INLINE void test_ref_count_integrity() const;
 
+public:
+  INLINE bool has_weak_list() const;
+  INLINE WeakReferenceList *get_weak_list() const;
+
+  INLINE void weak_ref(WeakPointerToVoid *ptv);
+  INLINE void weak_unref(WeakPointerToVoid *ptv);
+
+private:
+  int _ref_count;
+  WeakReferenceList *_weak_list;
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;
@@ -62,7 +73,6 @@ public:
   }
 
 private:
-  int _ref_count;
   static TypeHandle _type_handle;
 };
 

+ 319 - 0
panda/src/express/weakPointerTo.I

@@ -0,0 +1,319 @@
+// Filename: weakPointerTo.I
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerTo::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakPointerTo<T>::
+WeakPointerTo(To *ptr) : WeakPointerToBase<T>(ptr) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerTo::Copy Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakPointerTo<T>::
+WeakPointerTo(const PointerTo<T> &copy) :
+  WeakPointerToBase<T>((const PointerToBase<T> &)copy)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerTo::Copy Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakPointerTo<T>::
+WeakPointerTo(const WeakPointerTo<T> &copy) :
+  WeakPointerToBase<T>((const PointerToBase<T> &)copy)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerTo::Dereference operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE TYPENAME WeakPointerTo<T>::To &WeakPointerTo<T>::
+operator *() const {
+  nassertr(!was_deleted(), *((To *)NULL));
+  return *((To *)_void_ptr);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerTo::Member access operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE TYPENAME WeakPointerTo<T>::To *WeakPointerTo<T>::
+operator -> () const {
+  nassertr(!was_deleted(), (To *)NULL);
+  return (To *)_void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerTo::Typecast operator
+//       Access: Public
+//  Description: We also have the typecast operator to automatically
+//               convert WeakPointerTo's to the required kind of actual
+//               pointer.  This introduces ambiguities which the
+//               compiler will resolve one way or the other, but we
+//               don't care which way it goes because either will be
+//               correct.
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakPointerTo<T>::
+operator TYPENAME WeakPointerToBase<T>::To *() const {
+  nassertr(!was_deleted(), (To *)NULL);
+  return (To *)_void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerTo::p
+//       Access: Public
+//  Description: Returns an ordinary pointer instead of a WeakPointerTo.
+//               Useful to work around compiler problems, particularly
+//               for implicit upcasts.
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE TYPENAME WeakPointerTo<T>::To *WeakPointerTo<T>::
+p() const {
+  nassertr(!was_deleted(), (To *)NULL);
+  return (To *)_void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerTo::Assignment operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakPointerTo<T> &WeakPointerTo<T>::
+operator = (To *ptr) {
+  reassign(ptr);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerTo::Assignment operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakPointerTo<T> &WeakPointerTo<T>::
+operator = (const PointerTo<T> &copy) {
+  reassign((const PointerToBase<T> &)copy);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerTo::Assignment operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakPointerTo<T> &WeakPointerTo<T>::
+operator = (const WeakPointerTo<T> &copy) {
+  reassign((const PointerToBase<T> &)copy);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakConstPointerTo<T>::
+WeakConstPointerTo(const To *ptr) :
+  WeakPointerToBase<T>((WeakConstPointerTo<T>::To *)ptr)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::Copy Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakConstPointerTo<T>::
+WeakConstPointerTo(const PointerTo<T> &copy) :
+  WeakPointerToBase<T>((const PointerToBase<T> &)copy)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::Copy Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakConstPointerTo<T>::
+WeakConstPointerTo(const ConstPointerTo<T> &copy) :
+  WeakPointerToBase<T>((const PointerToBase<T> &)copy)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::Copy Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakConstPointerTo<T>::
+WeakConstPointerTo(const WeakPointerTo<T> &copy) :
+  WeakPointerToBase<T>((const PointerToBase<T> &)copy)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::Copy Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakConstPointerTo<T>::
+WeakConstPointerTo(const WeakConstPointerTo<T> &copy) :
+  WeakPointerToBase<T>((const PointerToBase<T> &)copy)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::Dereference operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE const TYPENAME WeakConstPointerTo<T>::To &WeakConstPointerTo<T>::
+operator *() const {
+  nassertr(!was_deleted(), *((To *)NULL));
+  return *((To *)_void_ptr);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::Member access operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE const TYPENAME WeakConstPointerTo<T>::To *WeakConstPointerTo<T>::
+operator -> () const {
+  nassertr(!was_deleted(), (To *)NULL);
+  return (To *)_void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::Typecast operator
+//       Access: Public
+//  Description: We also have the typecast operator to automatically
+//               convert WeakConstPointerTo's to the required kind of actual
+//               pointer.  This introduces ambiguities which the
+//               compiler will resolve one way or the other, but we
+//               don't care which way it goes because either will be
+//               correct.
+////////////////////////////////////////////////////////////////////
+
+template<class T>
+INLINE WeakConstPointerTo<T>::
+operator const TYPENAME WeakPointerToBase<T>::To *() const {
+  nassertr(!was_deleted(), (To *)NULL);
+  return (To *)_void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::p
+//       Access: Public
+//  Description: Returns an ordinary pointer instead of a WeakConstPointerTo.
+//               Useful to work around compiler problems, particularly
+//               for implicit upcasts.
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE const TYPENAME WeakConstPointerTo<T>::To *WeakConstPointerTo<T>::
+p() const {
+  nassertr(!was_deleted(), (To *)NULL);
+  return (To *)_void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::Assignment operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakConstPointerTo<T> &WeakConstPointerTo<T>::
+operator = (const To *ptr) {
+  reassign((To *)ptr);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::Assignment operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakConstPointerTo<T> &WeakConstPointerTo<T>::
+operator = (const PointerTo<T> &copy) {
+  reassign((const PointerToBase<T> &)copy);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::Assignment operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakConstPointerTo<T> &WeakConstPointerTo<T>::
+operator = (const ConstPointerTo<T> &copy) {
+  reassign((const PointerToBase<T> &)copy);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::Assignment operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakConstPointerTo<T> &WeakConstPointerTo<T>::
+operator = (const WeakPointerTo<T> &copy) {
+  reassign((const PointerToBase<T> &)copy);
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakConstPointerTo::Assignment operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakConstPointerTo<T> &WeakConstPointerTo<T>::
+operator = (const WeakConstPointerTo<T> &copy) {
+  reassign((const PointerToBase<T> &)copy);
+  return *this;
+}

+ 19 - 0
panda/src/express/weakPointerTo.cxx

@@ -0,0 +1,19 @@
+// Filename: weakPointerTo.cxx
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "weakPointerTo.h"

+ 108 - 0
panda/src/express/weakPointerTo.h

@@ -0,0 +1,108 @@
+// Filename: weakPointerTo.h
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef WEAKPOINTERTO_H
+#define WEAKPOINTERTO_H
+
+#include "pandabase.h"
+#include "weakPointerToBase.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : WeakPointerTo
+// Description : WeakPointerTo is similar to PointerTo, except that it
+//               does not actually prevent the referenced pointer from
+//               deleting.  Instead, the referenced pointer is allowed
+//               to delete, but if this happens then was_deleted()
+//               will return true, and it will be an assertion error to
+//               dereference the pointer thereafter.
+////////////////////////////////////////////////////////////////////
+template <class T>
+class WeakPointerTo : public WeakPointerToBase<T> {
+public:
+  typedef TYPENAME WeakPointerToBase<T>::To To;
+PUBLISHED:
+  INLINE WeakPointerTo(To *ptr = (To *)NULL);
+  INLINE WeakPointerTo(const PointerTo<T> &copy);
+  INLINE WeakPointerTo(const WeakPointerTo<T> &copy);
+
+public:
+  INLINE To &operator *() const;
+  INLINE To *operator -> () const;
+  INLINE operator TYPENAME WeakPointerToBase<T>::To *() const;
+
+PUBLISHED:
+  INLINE To *p() const;
+
+  INLINE WeakPointerTo<T> &operator = (To *ptr);
+  INLINE WeakPointerTo<T> &operator = (const PointerTo<T> &copy);
+  INLINE WeakPointerTo<T> &operator = (const WeakPointerTo<T> &copy);
+
+  // These functions normally wouldn't need to be redefined here, but
+  // we do so anyway just to help out interrogate (which doesn't seem
+  // to want to automatically export the WeakPointerToBase class).  When
+  // this works again in interrogate, we can remove these.
+  INLINE bool is_null() const { return WeakPointerToBase<T>::is_null(); }
+  INLINE void clear() { WeakPointerToBase<T>::clear(); }
+};
+
+
+////////////////////////////////////////////////////////////////////
+//       Class : WeakConstPointerTo
+// Description : A WeakConstPointerTo is similar to a WeakPointerTo,
+//               except it keeps a const pointer to the thing, that
+//               will be cleared to NULL when the thing deleted.
+////////////////////////////////////////////////////////////////////
+template <class T>
+class WeakConstPointerTo : public WeakPointerToBase<T> {
+public:
+  typedef TYPENAME WeakPointerToBase<T>::To To;
+PUBLISHED:
+  INLINE WeakConstPointerTo(const To *ptr = (const To *)NULL);
+  INLINE WeakConstPointerTo(const PointerTo<T> &copy);
+  INLINE WeakConstPointerTo(const ConstPointerTo<T> &copy);
+  INLINE WeakConstPointerTo(const WeakPointerTo<T> &copy);
+  INLINE WeakConstPointerTo(const WeakConstPointerTo<T> &copy);
+
+public:
+  INLINE const To &operator *() const;
+  INLINE const To *operator -> () const;
+  INLINE operator const TYPENAME WeakPointerToBase<T>::To *() const;
+
+PUBLISHED:
+  INLINE const To *p() const;
+
+  INLINE WeakConstPointerTo<T> &operator = (const To *ptr);
+  INLINE WeakConstPointerTo<T> &operator = (const PointerTo<T> &copy);
+  INLINE WeakConstPointerTo<T> &operator = (const ConstPointerTo<T> &copy);
+  INLINE WeakConstPointerTo<T> &operator = (const WeakPointerTo<T> &copy);
+  INLINE WeakConstPointerTo<T> &operator = (const WeakConstPointerTo<T> &copy);
+
+  // These functions normally wouldn't need to be redefined here, but
+  // we do so anyway just to help out interrogate (which doesn't seem
+  // to want to automatically export the WeakPointerToBase class).  When
+  // this works again in interrogate, we can remove these.
+  INLINE bool is_null() const { return WeakPointerToBase<T>::is_null(); }
+  INLINE void clear() { WeakPointerToBase<T>::clear(); }
+};
+
+#define WPT(type) WeakPointerTo< type >
+#define WCPT(type) WeakConstPointerTo< type >
+
+#include "weakPointerTo.I"
+
+#endif

+ 430 - 0
panda/src/express/weakPointerToBase.I

@@ -0,0 +1,430 @@
+// Filename: weakPointerToBase.I
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Constructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakPointerToBase<T>::
+WeakPointerToBase(To *ptr) {
+  reassign(ptr);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Copy Constructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakPointerToBase<T>::
+WeakPointerToBase(const PointerToBase<T> &copy) {
+  reassign(copy);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Copy Constructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakPointerToBase<T>::
+WeakPointerToBase(const WeakPointerToBase<T> &copy) {
+  reassign(copy);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Destructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE WeakPointerToBase<T>::
+~WeakPointerToBase() {
+  reassign((To *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::reassign
+//       Access: Protected
+//  Description: This is the main work of the PointerTo family.  When
+//               the pointer is reassigned, decrement the old
+//               reference count and increment the new one.
+////////////////////////////////////////////////////////////////////
+template<class T>
+void WeakPointerToBase<T>::
+reassign(To *ptr) {
+  if (ptr != (To *)_void_ptr || _ptr_was_deleted) {
+    To *old_ptr = (To *)_void_ptr;
+
+    _void_ptr = (void *)ptr;
+    if (ptr != (To *)NULL) {
+      ptr->weak_ref(this);
+#ifdef DO_MEMORY_USAGE
+      if (MemoryUsage::get_track_memory_usage()) {
+        // Make sure the MemoryUsage record knows what the TypeHandle
+        // is, if we know it ourselves.
+        TypeHandle type = get_type_handle(To);
+        if (type == TypeHandle::none()) {
+          do_init_type(To);
+          type = get_type_handle(To);
+        }
+        if (type != TypeHandle::none()) {
+          MemoryUsage::update_type(ptr, type);
+        }
+      }
+#endif
+    }
+
+    // Now remove the old reference.
+    if (old_ptr != (To *)NULL && !_ptr_was_deleted) {
+      old_ptr->weak_unref(this);
+    }
+
+    _ptr_was_deleted = false;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::reassign
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE void WeakPointerToBase<T>::
+reassign(const PointerToBase<To> &copy) {
+  // This double-casting is a bit of a cheat to get around the
+  // inheritance issue--it's difficult to declare a template class to
+  // be a friend.
+  reassign((To *)((const WeakPointerToBase<To> &)copy)._void_ptr);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::reassign
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE void WeakPointerToBase<T>::
+reassign(const WeakPointerToBase<To> &copy) {
+  nassertv(!copy.was_deleted());
+  reassign((To *)copy._void_ptr);
+}
+
+#ifndef CPPPARSER
+#ifndef WIN32_VC
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Equivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator == (const To *other) const {
+  return (To *)_void_ptr == other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Nonequivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator != (const To *other) const {
+  return (To *)_void_ptr != other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Greater-than operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator > (const To *other) const {
+  return (To *)_void_ptr > other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Less-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator <= (const To *other) const {
+  return (To *)_void_ptr <= other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Greater-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator >= (const To *other) const {
+  return (To *)_void_ptr >= other;
+}
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Equivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator == (To *other) const {
+  return (To *)_void_ptr == other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Nonequivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator != (To *other) const {
+  return (To *)_void_ptr != other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Greater-than operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator > (To *other) const {
+  return (To *)_void_ptr > other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Less-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator <= (To *other) const {
+  return (To *)_void_ptr <= other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Greater-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator >= (To *other) const {
+  return (To *)_void_ptr >= other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Equivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator == (const WeakPointerToBase<To> &other) const {
+  return (To *)_void_ptr == (To *)other._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Nonequivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator != (const WeakPointerToBase<To> &other) const {
+  return (To *)_void_ptr != (To *)other._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Greater-than operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator > (const WeakPointerToBase<To> &other) const {
+  return (To *)_void_ptr > (To *)other._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Less-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator <= (const WeakPointerToBase<To> &other) const {
+  return (To *)_void_ptr <= (To *)other._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Greater-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator >= (const WeakPointerToBase<To> &other) const {
+  return (To *)_void_ptr >= (To *)other._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Equivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator == (const PointerToBase<To> &other) const {
+  return (To *)_void_ptr == (To *)((WeakPointerToBase<To> &)other)._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Nonequivalence operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator != (const PointerToBase<To> &other) const {
+  return (To *)_void_ptr != (To *)((WeakPointerToBase<To> &)other)._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Greater-than operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator > (const PointerToBase<To> &other) const {
+  return (To *)_void_ptr > (To *)((WeakPointerToBase<To> &)other)._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Less-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator <= (const PointerToBase<To> &other) const {
+  return (To *)_void_ptr <= (To *)((WeakPointerToBase<To> &)other)._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Greater-than-or-equal operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator >= (const PointerToBase<To> &other) const {
+  return (To *)_void_ptr >= (To *)((WeakPointerToBase<To> &)other)._void_ptr;
+}
+#endif  // WIN32_VC
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Less-than operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator < (const To *other) const {
+  return (To *)_void_ptr < other;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Less-than operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator < (const WeakPointerToBase<To> &other) const {
+  return (To *)_void_ptr < (To *)other._void_ptr;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::Less-than operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+operator < (const PointerToBase<To> &other) const {
+  return (To *)_void_ptr < (To *)((WeakPointerToBase<To> &)other)._void_ptr;
+}
+
+#endif  // CPPPARSER
+
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::is_null
+//       Access: Public
+//  Description: Returns true if the PointerTo is a NULL pointer,
+//               false otherwise.  (Direct comparison to a NULL
+//               pointer also works.)
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE bool WeakPointerToBase<T>::
+is_null() const {
+  return (_void_ptr == (void *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::clear
+//       Access: Public
+//  Description: A convenient way to set the PointerTo object to NULL.
+//               (Assignment to a NULL pointer also works, of course.)
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE void WeakPointerToBase<T>::
+clear() {
+  reassign((To *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToBase::output
+//       Access: Public
+//  Description: A handy function to output PointerTo's as a hex
+//               pointer followed by a reference count.
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE void WeakPointerToBase<T>::
+output(ostream &out) const {
+  out << _void_ptr;
+  if (was_deleted()) {
+    out << ":deleted";
+  } else if (_void_ptr != (void *)NULL) {
+    out << ":" << ((To *)_void_ptr)->get_ref_count();
+  }
+}

+ 19 - 0
panda/src/express/weakPointerToBase.cxx

@@ -0,0 +1,19 @@
+// Filename: weakPointerToBase.cxx
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "weakPointerToBase.h"

+ 99 - 0
panda/src/express/weakPointerToBase.h

@@ -0,0 +1,99 @@
+// Filename: weakPointerToBase.h
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef WEAKPOINTERTOBASE_H
+#define WEAKPOINTERTOBASE_H
+
+#include "pandabase.h"
+#include "pointerToBase.h"
+#include "weakPointerToVoid.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : WeakPointerToBase
+// Description : This is the base class for PointerTo and
+//               ConstPointerTo.  Don't try to use it directly; use
+//               either derived class instead.
+////////////////////////////////////////////////////////////////////
+template <class T>
+class WeakPointerToBase : public WeakPointerToVoid {
+public:
+  typedef T To;
+
+protected:
+  INLINE WeakPointerToBase(To *ptr);
+  INLINE WeakPointerToBase(const PointerToBase<T> &copy);
+  INLINE WeakPointerToBase(const WeakPointerToBase<T> &copy);
+  INLINE ~WeakPointerToBase();
+
+  void reassign(To *ptr);
+  INLINE void reassign(const PointerToBase<To> &copy);
+  INLINE void reassign(const WeakPointerToBase<To> &copy);
+
+  // No assignment or retrieval functions are declared in
+  // WeakPointerToBase, because we will have to specialize on const
+  // vs. non-const later.
+
+public:
+  // These comparison functions are common to all things PointerTo, so
+  // they're defined up here.
+#ifndef CPPPARSER
+#ifndef WIN32_VC
+  INLINE bool operator == (const To *other) const;
+  INLINE bool operator != (const To *other) const;
+  INLINE bool operator > (const To *other) const;
+  INLINE bool operator <= (const To *other) const;
+  INLINE bool operator >= (const To *other) const;
+  INLINE bool operator == (To *other) const;
+  INLINE bool operator != (To *other) const;
+  INLINE bool operator > (To *other) const;
+  INLINE bool operator <= (To *other) const;
+  INLINE bool operator >= (To *other) const;
+
+  INLINE bool operator == (const WeakPointerToBase<To> &other) const;
+  INLINE bool operator != (const WeakPointerToBase<To> &other) const;
+  INLINE bool operator > (const WeakPointerToBase<To> &other) const;
+  INLINE bool operator <= (const WeakPointerToBase<To> &other) const;
+  INLINE bool operator >= (const WeakPointerToBase<To> &other) const;
+
+  INLINE bool operator == (const PointerToBase<To> &other) const;
+  INLINE bool operator != (const PointerToBase<To> &other) const;
+  INLINE bool operator > (const PointerToBase<To> &other) const;
+  INLINE bool operator <= (const PointerToBase<To> &other) const;
+  INLINE bool operator >= (const PointerToBase<To> &other) const;
+#endif  // WIN32_VC
+  INLINE bool operator < (const To *other) const;
+  INLINE bool operator < (const WeakPointerToBase<To> &other) const;
+  INLINE bool operator < (const PointerToBase<To> &other) const;
+#endif  // CPPPARSER
+
+PUBLISHED:
+  INLINE bool is_null() const;
+  INLINE void clear();
+
+  void output(ostream &out) const;
+};
+
+template<class T>
+INLINE ostream &operator <<(ostream &out, const WeakPointerToBase<T> &pointer) {
+  pointer.output(out);
+  return out;
+}
+
+#include "weakPointerToBase.I"
+
+#endif

+ 53 - 0
panda/src/express/weakPointerToVoid.I

@@ -0,0 +1,53 @@
+// Filename: weakPointerToVoid.I
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToVoid::Constructor
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE WeakPointerToVoid::
+WeakPointerToVoid() {
+  _ptr_was_deleted = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToVoid::mark_deleted
+//       Access: Public
+//  Description: This is intended only to be called by the
+//               WeakPointerList destructor.  It indicates that the
+//               object that we were pointing to has just been
+//               deleted.
+////////////////////////////////////////////////////////////////////
+INLINE void WeakPointerToVoid::
+mark_deleted() {
+  nassertv(!_ptr_was_deleted);
+  _ptr_was_deleted = true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakPointerToVoid::was_deleted
+//       Access: Public
+//  Description: Returns true if the object we are pointing to has
+//               been deleted, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool WeakPointerToVoid::
+was_deleted() const {
+  return _ptr_was_deleted;
+}

+ 19 - 0
panda/src/express/weakPointerToVoid.cxx

@@ -0,0 +1,19 @@
+// Filename: weakPointerToVoid.cxx
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "weakPointerToVoid.h"

+ 47 - 0
panda/src/express/weakPointerToVoid.h

@@ -0,0 +1,47 @@
+// Filename: weakPointerToVoid.h
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef WEAKPOINTERTOVOID_H
+#define WEAKPOINTERTOVOID_H
+
+#include "pandabase.h"
+#include "pointerToVoid.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : WeakPointerToVoid
+// Description : This is the specialization of PointerToVoid for weak
+//               pointers.  It needs an additional flag to indicate
+//               that the pointer has been deleted.
+////////////////////////////////////////////////////////////////////
+class WeakPointerToVoid : public PointerToVoid {
+protected:
+  INLINE WeakPointerToVoid();
+
+public:
+  INLINE void mark_deleted();
+
+PUBLISHED:
+  INLINE bool was_deleted() const;
+
+protected:
+  bool _ptr_was_deleted;
+};
+
+#include "weakPointerToVoid.I"
+
+#endif

+ 18 - 0
panda/src/express/weakReferenceList.I

@@ -0,0 +1,18 @@
+// Filename: weakReferenceList.I
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+

+ 77 - 0
panda/src/express/weakReferenceList.cxx

@@ -0,0 +1,77 @@
+// Filename: weakReferenceList.cxx
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "weakReferenceList.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakReferenceList::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+WeakReferenceList::
+WeakReferenceList() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakReferenceList::Destructor
+//       Access: Public
+//  Description: The destructor tells all of the owned references that
+//               we're gone.
+////////////////////////////////////////////////////////////////////
+WeakReferenceList::
+~WeakReferenceList() {
+  Pointers::iterator pi;
+  for (pi = _pointers.begin(); pi != _pointers.end(); ++pi) {
+    (*pi)->mark_deleted();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakReferenceList::add_reference
+//       Access: Public
+//  Description: Intended to be called only by WeakPointerTo (or by
+//               any class implementing a weak reference-counting
+//               pointer), this adds the indicated PointerToVoid
+//               structure to the list of such structures that are
+//               maintaining a weak pointer to this object.
+//
+//               When the WeakReferenceList destructs (presumably
+//               because its owning object destructs), the pointer
+//               within the PointerToVoid object will be set to NULL.
+////////////////////////////////////////////////////////////////////
+void WeakReferenceList::
+add_reference(WeakPointerToVoid *ptv) {
+  bool inserted = _pointers.insert(ptv).second;
+  nassertv(inserted);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakReferenceList::clear_reference
+//       Access: Public
+//  Description: Intended to be called only by WeakPointerTo (or by
+//               any class implementing a weak reference-counting
+//               pointer), this removes the indicated PointerToVoid
+//               structure from the list of such structures that are
+//               maintaining a weak pointer to this object.
+////////////////////////////////////////////////////////////////////
+void WeakReferenceList::
+clear_reference(WeakPointerToVoid *ptv) {
+  Pointers::iterator pi = _pointers.find(ptv);
+  nassertv_always(pi != _pointers.end());
+  _pointers.erase(pi);
+}

+ 52 - 0
panda/src/express/weakReferenceList.h

@@ -0,0 +1,52 @@
+// Filename: weakReferenceList.h
+// Created by:  drose (27Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef WEAKREFERENCELIST_H
+#define WEAKREFERENCELIST_H
+
+#include "pandabase.h"
+#include "pset.h"
+
+class WeakPointerToVoid;
+
+////////////////////////////////////////////////////////////////////
+//       Class : WeakReferenceList
+// Description : This is a list of WeakPointerTo's that share a
+//               reference to a given ReferenceCount object.  It is
+//               stored in a separate class since it is assumed that
+//               most ReferenceCount objects do not need to store this
+//               list at all; this avoids bloating every
+//               ReferenceCount object in the world with the size of
+//               this object.
+////////////////////////////////////////////////////////////////////
+class WeakReferenceList {
+public:
+  WeakReferenceList();
+  ~WeakReferenceList();
+
+  void add_reference(WeakPointerToVoid *ptv);
+  void clear_reference(WeakPointerToVoid *ptv);
+
+private:  
+  typedef pset<WeakPointerToVoid *> Pointers;
+  Pointers _pointers;
+};
+
+#include "weakReferenceList.I"
+
+#endif

+ 6 - 3
panda/src/pgraph/Sources.pp

@@ -43,7 +43,7 @@
     depthWriteAttrib.I depthWriteAttrib.h \
     directionalLight.I directionalLight.h \
     drawCullHandler.I drawCullHandler.h \
-    fadeLodNode.I fadeLodNode.h \
+    fadeLodNode.I fadeLodNode.h fadeLodNodeData.h \
     findApproxLevelEntry.I findApproxLevelEntry.h \
     findApproxPath.I findApproxPath.h \
     fog.I fog.h \
@@ -97,6 +97,7 @@
     textureStageCollection.I textureStageCollection.h \
     transformState.I transformState.h \
     transparencyAttrib.I transparencyAttrib.h \
+    weakNodePath.I weakNodePath.h \
     workingNodePath.I workingNodePath.h
 
   #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
@@ -135,7 +136,7 @@
     depthWriteAttrib.cxx \
     directionalLight.cxx \
     drawCullHandler.cxx \
-    fadeLodNode.cxx \
+    fadeLodNode.cxx fadeLodNodeData.cxx \
     findApproxLevelEntry.cxx \
     findApproxPath.cxx \
     fog.cxx \
@@ -188,6 +189,7 @@
     textureStageCollection.cxx \
     transformState.cxx \
     transparencyAttrib.cxx \
+    weakNodePath.cxx \
     workingNodePath.cxx
 
   #define INSTALL_HEADERS \
@@ -225,7 +227,7 @@
     depthWriteAttrib.I depthWriteAttrib.h \
     directionalLight.I directionalLight.h \
     drawCullHandler.I drawCullHandler.h \
-    fadeLodNode.I fadeLodNode.h \
+    fadeLodNode.I fadeLodNode.h fadeLodNodeData.h \
     fog.I fog.h \
     fogAttrib.I fogAttrib.h \
     geomNode.I geomNode.h \
@@ -277,6 +279,7 @@
     textureStageCollection.I textureStageCollection.h \
     transformState.I transformState.h \
     transparencyAttrib.I transparencyAttrib.h \
+    weakNodePath.I weakNodePath.h \
     workingNodePath.I workingNodePath.h
 
 // No need to install these.

+ 72 - 4
panda/src/pgraph/auxSceneData.I

@@ -16,13 +16,81 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-
 ////////////////////////////////////////////////////////////////////
 //     Function: AuxSceneData::Constructor
-//       Access: Public
-//  Description: 
+//       Access: Protected
+//  Description: This is protected, since you normally don't want to
+//               create a plain AuxSceneData object; instead, create
+//               an instance of a derived class that actually has some
+//               useful data in it.
 ////////////////////////////////////////////////////////////////////
 INLINE AuxSceneData::
-AuxSceneData() {
+AuxSceneData(double duration) :
+  _duration(duration),
+  _last_render_time(0.0)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxSceneData::set_duration
+//       Access: Public
+//  Description: Specifies the minimum length in time, in seconds, to
+//               keep this AuxSceneData object around in the scene
+//               graph after the last time it was rendered.
+////////////////////////////////////////////////////////////////////
+INLINE void AuxSceneData::
+set_duration(double duration) {
+  _duration = duration;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxSceneData::get_duration
+//       Access: Public
+//  Description: Returns the minimum length in time, in seconds, to
+//               keep this AuxSceneData object around in the scene
+//               graph after the last time it was rendered.
+////////////////////////////////////////////////////////////////////
+INLINE double AuxSceneData::
+get_duration() const {
+  return _duration;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxSceneData::set_last_render_time
+//       Access: Public
+//  Description: Should be called with the current frame_time each
+//               time the AuxSceneData is used during traversal.
+////////////////////////////////////////////////////////////////////
+INLINE void AuxSceneData::
+set_last_render_time(double last_render_time) {
+  _last_render_time = last_render_time;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxSceneData::get_last_render_time
+//       Access: Public
+//  Description: Returns the last time this object was used during
+//               traversal (according to set_last_render_time()).
+////////////////////////////////////////////////////////////////////
+INLINE double AuxSceneData::
+get_last_render_time() const {
+  return _last_render_time;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: AuxSceneData::get_expiration_time
+//       Access: Public
+//  Description: Returns the frame_time at which this AuxSceneData
+//               object is currently scheduled to be removed from the
+//               scene graph.
+////////////////////////////////////////////////////////////////////
+INLINE double AuxSceneData::
+get_expiration_time() const {
+  return _last_render_time + _duration;
+}
+
+INLINE ostream &
+operator << (ostream &out, const AuxSceneData &data) {
+  data.output(out);
+  return out;
+}

+ 21 - 0
panda/src/pgraph/auxSceneData.cxx

@@ -17,5 +17,26 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "auxSceneData.h"
+#include "indent.h"
 
 TypeHandle AuxSceneData::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxSceneData::output
+//       Access: Published, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void AuxSceneData::
+output(ostream &out) const {
+  out << get_type() << " expires " << get_expiration_time();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxSceneData::write
+//       Access: Published, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void AuxSceneData::
+write(ostream &out, int indent_level) const {
+  indent(out, indent_level) << *this << "\n";
+}

+ 22 - 3
panda/src/pgraph/auxSceneData.h

@@ -22,6 +22,7 @@
 #include "pandabase.h"
 
 #include "typedReferenceCount.h"
+#include "clockObject.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : AuxSceneData
@@ -36,9 +37,25 @@
 //               instance and for each camera.
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA AuxSceneData : public TypedReferenceCount {
-public:
-  INLINE AuxSceneData();
-  
+protected:
+  INLINE AuxSceneData(double duration = 0.0);
+
+PUBLISHED:
+  INLINE void set_duration(double duration);
+  INLINE double get_duration() const;
+
+  INLINE void set_last_render_time(double render_time);
+  INLINE double get_last_render_time() const;
+
+  INLINE double get_expiration_time() const;
+
+  virtual void output(ostream &out) const;
+  virtual void write(ostream &out, int indent_level = 0) const;
+
+protected:
+  double _duration;
+  double _last_render_time;
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;
@@ -57,6 +74,8 @@ private:
   static TypeHandle _type_handle;
 };
 
+INLINE ostream &operator << (ostream &out, const AuxSceneData &data);
+
 #include "auxSceneData.I"
 
 #endif

+ 98 - 0
panda/src/pgraph/camera.cxx

@@ -171,6 +171,104 @@ get_tag_state(const string &tag_state) const {
   return RenderState::make_empty();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Camera::set_aux_scene_data
+//       Access: Published
+//  Description: Associates the indicated AuxSceneData object with the
+//               given NodePath, possibly replacing a previous
+//               data defined for the same NodePath, if any.
+////////////////////////////////////////////////////////////////////
+void Camera::
+set_aux_scene_data(const NodePath &node_path, AuxSceneData *data) {
+  if (data == (AuxSceneData *)NULL) {
+    clear_aux_scene_data(node_path);
+  } else {
+    _aux_data[node_path] = data;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Camera::clear_aux_scene_data
+//       Access: Published
+//  Description: Removes the AuxSceneData associated with the
+//               indicated NodePath.  Returns true if it is removed
+//               successfully, false if it was already gone.
+////////////////////////////////////////////////////////////////////
+bool Camera::
+clear_aux_scene_data(const NodePath &node_path) {
+  AuxData::iterator ai;
+  ai = _aux_data.find(node_path);
+  if (ai != _aux_data.end()) {
+    _aux_data.erase(ai);
+    return true;
+  }
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Camera::get_aux_scene_data
+//       Access: Published
+//  Description: Returns the AuxSceneData associated with the
+//               indicated NodePath, or NULL if nothing is associated.
+////////////////////////////////////////////////////////////////////
+AuxSceneData *Camera::
+get_aux_scene_data(const NodePath &node_path) const {
+  AuxData::const_iterator ai;
+  ai = _aux_data.find(node_path);
+  if (ai != _aux_data.end()) {
+    return (*ai).second;
+  }
+
+  return NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Camera::list_aux_scene_data
+//       Access: Published
+//  Description: Outputs all of the NodePaths and AuxSceneDatas in
+//               use.
+////////////////////////////////////////////////////////////////////
+void Camera::
+list_aux_scene_data(ostream &out) const {
+  out << _aux_data.size() << " data objects held:\n";
+  AuxData::const_iterator ai;
+  for (ai = _aux_data.begin(); ai != _aux_data.end(); ++ai) {
+    out << (*ai).first << " " << *(*ai).second << "\n";
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Camera::cleanup_aux_scene_data
+//       Access: Published
+//  Description: Walks through the list of currently-assigned
+//               AuxSceneData objects and releases any that are
+//               past their expiration times.  Returns the number of
+//               elements released.
+////////////////////////////////////////////////////////////////////
+int Camera::
+cleanup_aux_scene_data() {
+  int num_deleted = 0;
+
+  double now = ClockObject::get_global_clock()->get_frame_time();
+
+  AuxData::iterator ai;
+  ai = _aux_data.begin();
+  while (ai != _aux_data.end()) {
+    AuxData::iterator anext = ai;
+    ++anext;
+
+    if (now > (*ai).second->get_expiration_time()) {
+      _aux_data.erase(ai);
+      num_deleted++;
+    }
+
+    ai = anext;
+  }
+
+  return num_deleted;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Camera::add_display_region
 //       Access: Private

+ 9 - 3
panda/src/pgraph/camera.h

@@ -23,6 +23,7 @@
 
 #include "lensNode.h"
 #include "nodePath.h"
+#include "weakNodePath.h"
 #include "drawMask.h"
 #include "renderState.h"
 #include "pointerTo.h"
@@ -77,9 +78,11 @@ PUBLISHED:
   bool has_tag_state(const string &tag_state) const;
   CPT(RenderState) get_tag_state(const string &tag_state) const;
 
-public:
-  //  void set_aux_scene_data(const NodePath &node_path, AuxSceneData *data);
-  //  AuxSceneData *get_aux_scene_data(const NodePath &node_path) const;
+  void set_aux_scene_data(const NodePath &node_path, AuxSceneData *data);
+  bool clear_aux_scene_data(const NodePath &node_path);
+  AuxSceneData *get_aux_scene_data(const NodePath &node_path) const;
+  void list_aux_scene_data(ostream &out) const;
+  int cleanup_aux_scene_data();
 
 private:
   void add_display_region(DisplayRegion *display_region);
@@ -100,6 +103,9 @@ private:
   typedef pmap<string, CPT(RenderState) > TagStates;
   TagStates _tag_states;
 
+  typedef pmap<NodePath, PT(AuxSceneData) > AuxData;
+  AuxData _aux_data;
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);

+ 6 - 0
panda/src/pgraph/config_pgraph.cxx

@@ -44,6 +44,7 @@
 #include "depthWriteAttrib.h"
 #include "directionalLight.h"
 #include "fadeLodNode.h"
+#include "fadeLodNodeData.h"
 #include "fog.h"
 #include "fogAttrib.h"
 #include "geomNode.h"
@@ -138,6 +139,10 @@ const bool paranoid_const = config_pgraph.GetBool("paranoid-const", false);
 // It is helpful for debugging
 const bool polylight_info = config_pgraph.GetBool("polylight-info", false);
 
+// The default amount of time (in seconds) over which a FadeLODNode
+// transitions between its different levels.
+const double lod_fade_time = config_pgraph.GetDouble("lod-fade-time", 0.5);
+
 // Set this false to disable TransparencyAttrib::M_dual altogether
 // (and use M_alpha in its place).
 const bool m_dual = config_pgraph.GetBool("m-dual", true);
@@ -208,6 +213,7 @@ init_libpgraph() {
   DepthWriteAttrib::init_type();
   DirectionalLight::init_type();
   FadeLODNode::init_type();
+  FadeLODNodeData::init_type();
   Fog::init_type();
   FogAttrib::init_type();
   GeomNode::init_type();

+ 1 - 0
panda/src/pgraph/config_pgraph.h

@@ -38,6 +38,7 @@ extern const bool compose_componentwise;
 extern const bool paranoid_const;
 
 extern const bool polylight_info;
+extern const double lod_fade_time;
 
 extern const bool m_dual;
 extern const bool m_dual_opaque;

+ 0 - 16
panda/src/pgraph/fadeLodNode.I

@@ -16,20 +16,6 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-////////////////////////////////////////////////////////////////////
-//     Function: FadeLODNode::Constructor
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE FadeLODNode::
-FadeLODNode(const string &name) :
-  LODNode(name) 
-{
-  _fade_time = 1.0;
-  _fade_mode = false;
-  _previous_child = 0;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: FadeLODNode::Copy Constructor
 //       Access: Protected
@@ -40,8 +26,6 @@ FadeLODNode(const FadeLODNode &copy) :
   LODNode(copy)
 {
   _fade_time = copy._fade_time;
-  _fade_mode = copy._fade_mode;
-  _previous_child = copy._previous_child;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 106 - 74
panda/src/pgraph/fadeLodNode.cxx

@@ -17,6 +17,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "fadeLodNode.h"
+#include "fadeLodNodeData.h"
 #include "cullTraverserData.h"
 #include "cullTraverser.h"
 #include "clockObject.h"
@@ -26,6 +27,18 @@
 
 TypeHandle FadeLODNode::_type_handle;
 
+////////////////////////////////////////////////////////////////////
+//     Function: FadeLODNode::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+FadeLODNode::
+FadeLODNode(const string &name) :
+  LODNode(name) 
+{
+  _fade_time = lod_fade_time;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: FadeLODNode::make_copy
 //       Access: Public, Virtual
@@ -60,95 +73,114 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 bool FadeLODNode::
 cull_callback(CullTraverser *trav, CullTraverserData &data) {
-  if (_fade_mode) {
-    float now = ClockObject::get_global_clock()->get_frame_time();
-    float elapsed = now - _fade_start;
-
-    float half_fade_time = _fade_time / 2.0f;
-
-    if (elapsed < half_fade_time) { 
-      // FIRST HALF OF FADE
-      // Fade the new LOD in with z writing off
-      // Keep drawing the old LOD opaque with z writing on
-      if (_fade_out >= 0 && _fade_out < get_num_children()) {
-        CullTraverserData next_data_out(data, get_child(_fade_out));
-        trav->traverse(next_data_out);
-      }
+  Camera *camera = trav->get_scene()->get_camera_node();
+  NodePath this_np = data._node_path.get_node_path();
+  FadeLODNodeData *ldata = 
+    DCAST(FadeLODNodeData, camera->get_aux_scene_data(this_np));
 
-      if (_fade_in >= 0 && _fade_in < get_num_children()) {
-        CullTraverserData next_data_in(data, get_child(_fade_in));
+  double now = ClockObject::get_global_clock()->get_frame_time();
 
-        float in_alpha = elapsed / half_fade_time;
-        if (in_alpha > 1.0f) {
-          in_alpha = 1.0f;
-        }
-        LVecBase4f alpha_scale(1.0f, 1.0f, 1.0f, in_alpha);
+  if (ldata == (AuxSceneData *)NULL || now > ldata->get_expiration_time()) {
+    // This is the first time we have rendered this instance of this
+    // LOD node in a while.
+    ldata = new FadeLODNodeData;
+    ldata->_fade_mode = false;
+    ldata->_fade_out = -1;
+    ldata->_fade_in = compute_child(trav, data);
+    camera->set_aux_scene_data(this_np, ldata);
 
-        next_data_in._state = 
-          next_data_in._state->compose(get_fade_out_state())->compose
-          (RenderState::make(ColorScaleAttrib::make(alpha_scale)));
+  } else {
+    // We had rendered this LOD node last frame (or not too long ago,
+    // at least).
 
-        trav->traverse(next_data_in);
+    if (!ldata->_fade_mode) {
+      // We were drawing just one solid child last frame; check whether
+      // it's time to begin a transition.
+      int index = compute_child(trav, data);
+      if (index != ldata->_fade_in) {
+        // Start a transition.
+        ldata->_fade_mode = true;
+        
+        // We start the fade as of the last frame we actually rendered;
+        // that way, if the object happened to be offscreen for a large
+        // part of the fade, we'll just view the tail end of it--a
+        // little nicer.
+        ldata->_fade_start = ldata->get_last_render_time();
+        ldata->_fade_out = ldata->_fade_in; 
+        ldata->_fade_in = index;
       }
+    }
 
-    } else if (elapsed < _fade_time) {
-      //SECOND HALF OF FADE:
-      //Fade out the old LOD with z write off and 
-      //draw the opaque new LOD with z write on
-      if (_fade_in >= 0 && _fade_in < get_num_children()) {
-        CullTraverserData next_data_in(data, get_child(_fade_in));
-        trav->traverse(next_data_in);
-      }
+    if (ldata->_fade_mode) {
+      // Play the transition.
+
+      float elapsed = now - ldata->_fade_start;
+      float half_fade_time = _fade_time * 0.5f;
 
-      if (_fade_out >= 0 && _fade_out < get_num_children()) {
-        CullTraverserData next_data_out(data, get_child(_fade_out));
+      if (elapsed < half_fade_time) { 
+        // FIRST HALF OF FADE
+        // Fade the new LOD in with z writing off
+        // Keep drawing the old LOD opaque with z writing on
+        if (ldata->_fade_out >= 0 && ldata->_fade_out < get_num_children()) {
+          CullTraverserData next_data_out(data, get_child(ldata->_fade_out));
+          trav->traverse(next_data_out);
+        }
         
-        float out_alpha = 1.0f - elapsed / half_fade_time;  
-        if (out_alpha < 0.0f) {
-          out_alpha = 0.0f;
+        if (ldata->_fade_in >= 0 && ldata->_fade_in < get_num_children()) {
+          CullTraverserData next_data_in(data, get_child(ldata->_fade_in));
+          
+          float in_alpha = elapsed / half_fade_time;
+          LVecBase4f alpha_scale(1.0f, 1.0f, 1.0f, in_alpha);
+          
+          next_data_in._state = 
+            next_data_in._state->compose(get_fade_out_state())->compose
+            (RenderState::make(ColorScaleAttrib::make(alpha_scale)));
+          
+          trav->traverse(next_data_in);
         }
-        LVecBase4f alpha_scale(1.0f, 1.0f, 1.0f, out_alpha);
-
-        next_data_out._state = 
-          next_data_out._state->compose(get_fade_out_state())->compose
-          (RenderState::make(ColorScaleAttrib::make(alpha_scale)));
-
-        trav->traverse(next_data_out);
-      }
-
-    } else {
-      // Fading complete
-      _fade_mode = false;
-      
-      if (_fade_in >= 0 && _fade_in < get_num_children()) {
-        CullTraverserData next_data_in(data, get_child(_fade_in));
-        trav->traverse(next_data_in);
+        
+      } else if (elapsed < _fade_time) {
+        //SECOND HALF OF FADE:
+        //Fade out the old LOD with z write off and 
+        //draw the opaque new LOD with z write on
+        if (ldata->_fade_in >= 0 && ldata->_fade_in < get_num_children()) {
+          CullTraverserData next_data_in(data, get_child(ldata->_fade_in));
+          trav->traverse(next_data_in);
+        }
+        
+        if (ldata->_fade_out >= 0 && ldata->_fade_out < get_num_children()) {
+          CullTraverserData next_data_out(data, get_child(ldata->_fade_out));
+          
+          float out_alpha = 1.0f - (elapsed - half_fade_time) / half_fade_time;  
+          LVecBase4f alpha_scale(1.0f, 1.0f, 1.0f, out_alpha);
+          
+          next_data_out._state = 
+            next_data_out._state->compose(get_fade_out_state())->compose
+            (RenderState::make(ColorScaleAttrib::make(alpha_scale)));
+          
+          trav->traverse(next_data_out);
+        }
+        
+      } else {
+        // Transition complete.
+        ldata->_fade_mode = false;
       }
     }
+  }
 
-  } else {
-    int index = compute_child(trav, data);
-    if (index != _previous_child) { // Transition occurred
-      _fade_mode = true;
-      _fade_start = ClockObject::get_global_clock()->get_frame_time();
-      _fade_out = _previous_child; 
-      _fade_in = index;
-      _previous_child = index;
-      if (_fade_out >= 0 && _fade_out < get_num_children()) {
-        CullTraverserData next_data_transition(data, get_child(_fade_out));
-        trav->traverse(next_data_transition);
-      }
-      
-    } else {
-      if (index >= 0 && index < get_num_children()) {
-        // No transition... handle things as usual
-        // Traverse only one valid child
-        CullTraverserData next_data_normal(data, get_child(index));
-        trav->traverse(next_data_normal);
-      }
+  if (!ldata->_fade_mode) {
+    // This is the normal case: we're not in the middle of a
+    // transition; we're just drawing one child of the LOD.
+    int index = ldata->_fade_in;
+    if (index >= 0 && index < get_num_children()) {
+      CullTraverserData next_data(data, get_child(index));
+      trav->traverse(next_data);
     }
   }
 
+  ldata->set_last_render_time(now);
+  ldata->set_duration(_fade_time);
+    
   return false;
 }
 

+ 1 - 11
panda/src/pgraph/fadeLodNode.h

@@ -29,7 +29,7 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA FadeLODNode : public LODNode {
 PUBLISHED:
-  INLINE FadeLODNode(const string &name);
+  FadeLODNode(const string &name);
 
 protected:
   INLINE FadeLODNode(const FadeLODNode &copy);
@@ -47,16 +47,6 @@ private:
 
 private:
   float _fade_time;
-
-  // These values are used to implement the fade-in-transition, and
-  // really shouldn't be stored here (because it is incompatible with
-  // multiple cameras on the scene, or multiple instances of the
-  // LODNode).
-  bool _fade_mode;
-  float _fade_start;
-  int _fade_out;
-  int _fade_in;
-  int _previous_child;
   
 public:
   static void register_with_read_factory();

+ 38 - 0
panda/src/pgraph/fadeLodNodeData.cxx

@@ -0,0 +1,38 @@
+// Filename: fadeLodNodeData.cxx
+// Created by:  drose (29Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "fadeLodNodeData.h"
+
+TypeHandle FadeLODNodeData::_type_handle;
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: FadeLODNodeData::output
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void FadeLODNodeData::
+output(ostream &out) const {
+  AuxSceneData::output(out);
+  if (_fade_mode) {
+    out << " fading " << _fade_out << " to " << _fade_in << " since "
+        << _fade_start;
+  } else {
+    out << " showing " << _fade_in;
+  }
+}

+ 59 - 0
panda/src/pgraph/fadeLodNodeData.h

@@ -0,0 +1,59 @@
+// Filename: fadeLodNodeData.h
+// Created by:  drose (29Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef FADELODNODEDATA_H
+#define FADELODNODEDATA_H
+
+#include "pandabase.h"
+
+#include "auxSceneData.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : FadeLODNodeData
+// Description : This is the data that is associated with a particular
+//               instance of the FadeLODNode for the scene graph.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA FadeLODNodeData : public AuxSceneData {
+public:
+  bool _fade_mode;
+  float _fade_start;
+  int _fade_out;
+  int _fade_in;
+
+  virtual void output(ostream &out) const;
+  
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    AuxSceneData::init_type();
+    register_type(_type_handle, "FadeLODNodeData",
+                  AuxSceneData::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;
+};
+
+#endif
+

+ 29 - 3
panda/src/pgraph/nodePath.I

@@ -1504,7 +1504,7 @@ set_collide_mask(CollideMask new_mask, CollideMask bits_to_change,
 ////////////////////////////////////////////////////////////////////
 INLINE bool NodePath::
 operator == (const NodePath &other) const {
-  return (compare_to(other) == 0);
+  return _head == other._head;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1514,7 +1514,7 @@ operator == (const NodePath &other) const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool NodePath::
 operator != (const NodePath &other) const {
-  return (compare_to(other) != 0);
+  return _head != other._head;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1528,7 +1528,33 @@ operator != (const NodePath &other) const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool NodePath::
 operator < (const NodePath &other) const {
-  return (compare_to(other) < 0);
+  return _head < other._head;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePath::compare_to
+//       Access: Published
+//  Description: Returns a number less than zero if this NodePath
+//               sorts before the other one, greater than zero if it
+//               sorts after, or zero if they are equivalent.
+//
+//               Two NodePaths are considered equivalent if they
+//               consist of exactly the same list of nodes in the same
+//               order.  Otherwise, they are different; different
+//               NodePaths will be ranked in a consistent but
+//               undefined ordering; the ordering is useful only for
+//               placing the NodePaths in a sorted container like an
+//               STL set.
+////////////////////////////////////////////////////////////////////
+INLINE int NodePath::
+compare_to(const NodePath &other) const {
+  // Nowadays, the NodePathComponents at the head are pointerwise
+  // equivalent if and only if the NodePaths are equivalent.  So we
+  // only have to compare pointers.
+  if (_head != other._head) {
+    return _head < other._head ? -1 : 1;
+  }
+  return 0;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 0 - 26
panda/src/pgraph/nodePath.cxx

@@ -4265,32 +4265,6 @@ get_stashed_ancestor() const {
   return not_found();
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::compare_to
-//       Access: Published
-//  Description: Returns a number less than zero if this NodePath
-//               sorts before the other one, greater than zero if it
-//               sorts after, or zero if they are equivalent.
-//
-//               Two NodePaths are considered equivalent if they
-//               consist of exactly the same list of nodes in the same
-//               order.  Otherwise, they are different; different
-//               NodePaths will be ranked in a consistent but
-//               undefined ordering; the ordering is useful only for
-//               placing the NodePaths in a sorted container like an
-//               STL set.
-////////////////////////////////////////////////////////////////////
-int NodePath::
-compare_to(const NodePath &other) const {
-  // Nowadays, the NodePathComponents at the head are pointerwise
-  // equivalent if and only if the NodePaths are equivalent.  So we
-  // only have to compare pointers.
-  if (_head != other._head) {
-    return _head < other._head ? -1 : 1;
-  }
-  return 0;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::verify_complete
 //       Access: Published

+ 2 - 1
panda/src/pgraph/nodePath.h

@@ -655,7 +655,7 @@ PUBLISHED:
   INLINE bool operator == (const NodePath &other) const;
   INLINE bool operator != (const NodePath &other) const;
   INLINE bool operator < (const NodePath &other) const;
-  int compare_to(const NodePath &other) const;
+  INLINE int compare_to(const NodePath &other) const;
 
   // Miscellaneous
   bool verify_complete() const;
@@ -754,6 +754,7 @@ private:
 
   friend class NodePathCollection;
   friend class WorkingNodePath;
+  friend class WeakNodePath;
 };
 
 INLINE ostream &operator << (ostream &out, const NodePath &node_path);

+ 1 - 0
panda/src/pgraph/pgraph_composite1.cxx

@@ -33,6 +33,7 @@
 #include "directionalLight.cxx"
 #include "drawCullHandler.cxx"
 #include "fadeLodNode.cxx"
+#include "fadeLodNodeData.cxx"
 #include "findApproxPath.cxx"
 #include "findApproxLevelEntry.cxx"
 #include "fog.cxx"

+ 1 - 0
panda/src/pgraph/pgraph_composite2.cxx

@@ -44,4 +44,5 @@
 #include "textureStageCollection.cxx"
 #include "transformState.cxx"
 #include "transparencyAttrib.cxx"
+#include "weakNodePath.cxx"
 #include "workingNodePath.cxx"

+ 2 - 2
panda/src/pgraph/sceneSetup.I

@@ -75,7 +75,7 @@ get_camera_path() const {
 //  Description: Specifies the camera used to render the scene.
 ////////////////////////////////////////////////////////////////////
 INLINE void SceneSetup::
-set_camera_node(const Camera *camera_node) {
+set_camera_node(Camera *camera_node) {
   _camera_node = camera_node;
 }
 
@@ -84,7 +84,7 @@ set_camera_node(const Camera *camera_node) {
 //       Access: Public
 //  Description: Returns the camera used to render the scene.
 ////////////////////////////////////////////////////////////////////
-INLINE const Camera *SceneSetup::
+INLINE Camera *SceneSetup::
 get_camera_node() const {
   return _camera_node;
 }

+ 3 - 3
panda/src/pgraph/sceneSetup.h

@@ -44,8 +44,8 @@ public:
   INLINE void set_camera_path(const NodePath &camera_path);
   INLINE const NodePath &get_camera_path() const;
 
-  INLINE void set_camera_node(const Camera *camera_node);
-  INLINE const Camera *get_camera_node() const;
+  INLINE void set_camera_node(Camera *camera_node);
+  INLINE Camera *get_camera_node() const;
 
   INLINE void set_lens(const Lens *lens);
   INLINE const Lens *get_lens() const;
@@ -66,7 +66,7 @@ public:
 private:
   NodePath _scene_root;
   NodePath _camera_path;
-  CPT(Camera) _camera_node;
+  PT(Camera) _camera_node;
   CPT(Lens) _lens;
   CPT(TransformState) _camera_transform;
   CPT(TransformState) _world_transform;

+ 256 - 0
panda/src/pgraph/weakNodePath.I

@@ -0,0 +1,256 @@
+// Filename: weakNodePath.I
+// Created by:  drose (29Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE WeakNodePath::
+WeakNodePath(const NodePath &node_path) :
+  _head(node_path._head),
+  _backup_key(0)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE WeakNodePath::
+WeakNodePath(const WeakNodePath &copy) :
+  _head(copy._head),
+  _backup_key(copy._backup_key)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE WeakNodePath::
+~WeakNodePath() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::operator = 
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void WeakNodePath::
+operator = (const NodePath &node_path) {
+  _head = node_path._head;
+  _backup_key = 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::operator = 
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void WeakNodePath::
+operator = (const WeakNodePath &copy) {
+  _head = copy._head;
+  _backup_key = copy._backup_key;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::is_empty
+//       Access: Public
+//  Description: Returns true if the NodePath contains no nodes, or if
+//               it has been deleted.
+////////////////////////////////////////////////////////////////////
+INLINE bool WeakNodePath::
+is_empty() const {
+  return _head == (NodePathComponent *)NULL || _head.was_deleted();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::was_deleted
+//       Access: Public
+//  Description: Returns true if the NodePath we were referencing has
+//               been quietly deleted outside of the WeakNodePath.
+////////////////////////////////////////////////////////////////////
+INLINE bool WeakNodePath::
+was_deleted() const {
+  return _head != (NodePathComponent *)NULL && _head.was_deleted();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::get_node_path
+//       Access: Public
+//  Description: Returns the NodePath held within this object.
+////////////////////////////////////////////////////////////////////
+INLINE NodePath WeakNodePath::
+get_node_path() const {
+  nassertr_always(!was_deleted(), NodePath::fail());
+  NodePath result;
+  result._head = _head;
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::node
+//       Access: Public
+//  Description: Returns the PandaNode held within this object.
+////////////////////////////////////////////////////////////////////
+INLINE PandaNode *WeakNodePath::
+node() const {
+  nassertr_always(!is_empty(), (PandaNode *)NULL);
+  return _head->get_node();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::operator ==
+//       Access: Published
+//  Description: Returns true if the two paths are equivalent; that
+//               is, if they contain the same list of nodes in the same
+//               order.
+////////////////////////////////////////////////////////////////////
+INLINE bool WeakNodePath::
+operator == (const NodePath &other) const {
+  return _head == other._head;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::operator !=
+//       Access: Published
+//  Description: Returns true if the two paths are not equivalent.
+////////////////////////////////////////////////////////////////////
+INLINE bool WeakNodePath::
+operator != (const NodePath &other) const {
+  return _head != other._head;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::operator <
+//       Access: Published
+//  Description: Returns true if this NodePath sorts before the other
+//               one, false otherwise.  The sorting order of two
+//               nonequivalent NodePaths is consistent but undefined,
+//               and is useful only for storing NodePaths in a sorted
+//               container like an STL set.
+////////////////////////////////////////////////////////////////////
+INLINE bool WeakNodePath::
+operator < (const NodePath &other) const {
+  return _head < other._head;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::compare_to
+//       Access: Published
+//  Description: Returns a number less than zero if this NodePath
+//               sorts before the other one, greater than zero if it
+//               sorts after, or zero if they are equivalent.
+//
+//               Two NodePaths are considered equivalent if they
+//               consist of exactly the same list of nodes in the same
+//               order.  Otherwise, they are different; different
+//               NodePaths will be ranked in a consistent but
+//               undefined ordering; the ordering is useful only for
+//               placing the NodePaths in a sorted container like an
+//               STL set.
+////////////////////////////////////////////////////////////////////
+INLINE int WeakNodePath::
+compare_to(const NodePath &other) const {
+  if (_head != other._head) {
+    return _head < other._head ? -1 : 1;
+  }
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::operator ==
+//       Access: Published
+//  Description: Returns true if the two paths are equivalent; that
+//               is, if they contain the same list of nodes in the same
+//               order.
+////////////////////////////////////////////////////////////////////
+INLINE bool WeakNodePath::
+operator == (const WeakNodePath &other) const {
+  return _head == other._head;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::operator !=
+//       Access: Published
+//  Description: Returns true if the two paths are not equivalent.
+////////////////////////////////////////////////////////////////////
+INLINE bool WeakNodePath::
+operator != (const WeakNodePath &other) const {
+  return _head != other._head;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::operator <
+//       Access: Published
+//  Description: Returns true if this WeakNodePath sorts before the other
+//               one, false otherwise.  The sorting order of two
+//               nonequivalent WeakNodePaths is consistent but undefined,
+//               and is useful only for storing WeakNodePaths in a sorted
+//               container like an STL set.
+////////////////////////////////////////////////////////////////////
+INLINE bool WeakNodePath::
+operator < (const WeakNodePath &other) const {
+  return _head < other._head;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::compare_to
+//       Access: Published
+//  Description: Returns a number less than zero if this WeakNodePath
+//               sorts before the other one, greater than zero if it
+//               sorts after, or zero if they are equivalent.
+//
+//               Two WeakNodePaths are considered equivalent if they
+//               consist of exactly the same list of nodes in the same
+//               order.  Otherwise, they are different; different
+//               WeakNodePaths will be ranked in a consistent but
+//               undefined ordering; the ordering is useful only for
+//               placing the WeakNodePaths in a sorted container like an
+//               STL set.
+////////////////////////////////////////////////////////////////////
+INLINE int WeakNodePath::
+compare_to(const WeakNodePath &other) const {
+  if (_head != other._head) {
+    return _head < other._head ? -1 : 1;
+  }
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::get_key
+//       Access: Public
+//  Description: Returns the same values as NodePath::get_key().
+////////////////////////////////////////////////////////////////////
+INLINE int WeakNodePath::
+get_key() const {
+  if (is_empty() || was_deleted()) {
+    return _backup_key;
+  }
+  ((WeakNodePath *)this)->_backup_key = _head->get_key();
+  return _backup_key;
+}
+
+INLINE ostream &operator << (ostream &out, const WeakNodePath &node_path) {
+  node_path.output(out);
+  return out;
+}

+ 33 - 0
panda/src/pgraph/weakNodePath.cxx

@@ -0,0 +1,33 @@
+// Filename: weakNodePath.cxx
+// Created by:  drose (29Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "weakNodePath.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: WeakNodePath::output
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void WeakNodePath::
+output(ostream &out) const {
+  if (was_deleted()) {
+    out << "deleted";
+  } else {
+    get_node_path().output(out);
+  }
+}

+ 79 - 0
panda/src/pgraph/weakNodePath.h

@@ -0,0 +1,79 @@
+// Filename: weakNodePath.h
+// Created by:  drose (29Sep04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef WEAKNODEPATH_H
+#define WEAKNODEPATH_H
+
+#include "pandabase.h"
+
+#include "nodePath.h"
+#include "nodePathComponent.h"
+#include "weakPointerTo.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : WeakNodePath
+// Description : This class is a wrapper around a NodePath that,
+//               unlike the actual NodePath class, doesn't hold a
+//               reference count to the node.  Thus the node may be
+//               detached from the scene graph and destructed at any
+//               time.
+//
+//               You can call is_valid() or was_deleted() at any time
+//               to determine whether the node is still around; if it
+//               is, get_node_path() will return the associated
+//               NodePath.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA WeakNodePath {
+public:
+  INLINE WeakNodePath(const NodePath &node_path);
+  INLINE WeakNodePath(const WeakNodePath &copy);
+  INLINE ~WeakNodePath();
+
+  INLINE void operator = (const NodePath &node_path);
+  INLINE void operator = (const WeakNodePath &copy);
+
+  INLINE bool is_empty() const;
+  INLINE bool was_deleted() const;
+
+  INLINE NodePath get_node_path() const;
+  INLINE PandaNode *node() const;
+
+  INLINE bool operator == (const NodePath &other) const;
+  INLINE bool operator != (const NodePath &other) const;
+  INLINE bool operator < (const NodePath &other) const;
+  INLINE int compare_to(const NodePath &other) const;
+
+  INLINE bool operator == (const WeakNodePath &other) const;
+  INLINE bool operator != (const WeakNodePath &other) const;
+  INLINE bool operator < (const WeakNodePath &other) const;
+  INLINE int compare_to(const WeakNodePath &other) const;
+
+  INLINE int get_key() const;
+
+  void output(ostream &out) const;
+
+private:
+  WPT(NodePathComponent) _head;
+  int _backup_key;
+};
+
+INLINE ostream &operator << (ostream &out, const WeakNodePath &node_path);
+
+#include "weakNodePath.I"
+
+#endif

+ 17 - 1
panda/src/testbed/test_lod.cxx

@@ -43,7 +43,13 @@ create_lod_node(NodePath &models, const char *a, const char *b) {
     lod->add_switch(1000, 10);
   }
 
-  models.attach_new_node(lod);
+  NodePath instance1(models.attach_new_node("instance1"));
+  instance1.set_pos(2, 0, 0);
+  instance1.attach_new_node(lod);
+
+  NodePath instance2(models.attach_new_node("instance2"));
+  instance2.set_pos(-2, 0, 0);
+  instance2.attach_new_node(lod);
 }
 
 
@@ -66,6 +72,16 @@ main(int argc, char *argv[]) {
 
     window->center_trackball(framework.get_models());
 
+    // Open another window too.
+    WindowFramework *window2 = framework.open_window();
+    if (window2 != (WindowFramework *)NULL) {
+      window2->enable_keyboard();
+      window2->setup_trackball();
+      framework.get_models().instance_to(window2->get_render());
+      
+      window2->center_trackball(framework.get_models());
+    }
+
     framework.enable_default_keys();
     framework.main_loop();
   }