فهرست منبع

Reimplement EventParameter to be a more generic Parameter class

rdb 11 سال پیش
والد
کامیت
55bfd10737
50فایلهای تغییر یافته به همراه2053 افزوده شده و 618 حذف شده
  1. 2 12
      direct/src/showbase/EventManager.py
  2. 2 2
      panda/src/awesomium/AwMouseAndKeyboard.cxx
  3. 5 5
      panda/src/collide/collisionEntry.h
  4. 9 7
      panda/src/dgraph/dataNode.cxx
  5. 16 0
      panda/src/dgraph/dataNodeTransmit.I
  6. 5 5
      panda/src/dgraph/dataNodeTransmit.cxx
  7. 5 1
      panda/src/dgraph/dataNodeTransmit.h
  8. 1 7
      panda/src/display/graphicsOutput.h
  9. 3 3
      panda/src/event/Sources.pp
  10. 2 2
      panda/src/event/buttonEvent.h
  11. 0 4
      panda/src/event/config_event.cxx
  12. 11 0
      panda/src/event/event.cxx
  13. 4 0
      panda/src/event/event.h
  14. 0 297
      panda/src/event/eventParameter.I
  15. 0 41
      panda/src/event/eventParameter.cxx
  16. 4 66
      panda/src/event/eventParameter.h
  17. 0 1
      panda/src/event/p3event_composite2.cxx
  18. 25 1
      panda/src/express/referenceCount.I
  19. 8 1
      panda/src/express/referenceCount.h
  20. 24 0
      panda/src/express/typedReferenceCount.I
  21. 4 1
      panda/src/express/typedReferenceCount.h
  22. 13 13
      panda/src/framework/pandaFramework.cxx
  23. 6 6
      panda/src/framework/windowFramework.h
  24. 5 5
      panda/src/gsgbase/graphicsOutputBase.h
  25. 2 0
      panda/src/linmath/lvecBase4.h
  26. 20 0
      panda/src/linmath/lvecBase4_src.I
  27. 2 0
      panda/src/linmath/lvecBase4_src.h
  28. 2 9
      panda/src/pgraph/renderEffects.cxx
  29. 1 1
      panda/src/pgraph/renderState.h
  30. 6 6
      panda/src/pgui/pgMouseWatcherParameter.h
  31. 2 1
      panda/src/putil/config_util.cxx
  32. 1 0
      panda/src/putil/p3putil_composite2.cxx
  33. 299 28
      panda/src/putil/paramValue.I
  34. 0 25
      panda/src/putil/paramValue.cxx
  35. 11 38
      panda/src/putil/paramValue.h
  36. 980 0
      panda/src/putil/parameter.I
  37. 285 0
      panda/src/putil/parameter.cxx
  38. 231 0
      panda/src/putil/parameter.h
  39. 26 1
      panda/src/putil/typedWritableReferenceCount.I
  40. 3 1
      panda/src/putil/typedWritableReferenceCount.h
  41. 3 3
      panda/src/recorder/mouseRecorder.cxx
  42. 2 2
      panda/src/rocket/rocketInputHandler.cxx
  43. 3 3
      panda/src/testbed/pview.cxx
  44. 1 1
      panda/src/tform/buttonThrower.cxx
  45. 2 2
      panda/src/tform/driveInterface.cxx
  46. 2 2
      panda/src/tform/mouseInterfaceNode.cxx
  47. 5 5
      panda/src/tform/mouseSubregion.cxx
  48. 5 5
      panda/src/tform/mouseWatcher.cxx
  49. 4 4
      panda/src/tform/trackball.cxx
  50. 1 1
      panda/src/tform/transform2sg.cxx

+ 2 - 12
direct/src/showbase/EventManager.py

@@ -57,22 +57,12 @@ class EventManager:
         """
         """
         Extract the actual data from the eventParameter
         Extract the actual data from the eventParameter
         """
         """
-        if (eventParameter.isInt()):
-            return eventParameter.getIntValue()
-        elif (eventParameter.isDouble()):
-            return eventParameter.getDoubleValue()
-        elif (eventParameter.isString()):
+        if (eventParameter.isString()):
             return eventParameter.getStringValue()
             return eventParameter.getStringValue()
         elif (eventParameter.isWstring()):
         elif (eventParameter.isWstring()):
             return eventParameter.getWstringValue()
             return eventParameter.getWstringValue()
-        elif (eventParameter.isTypedRefCount()):
-            return eventParameter.getTypedRefCountValue()
-        elif (eventParameter.isEmpty()):
-            return None
         else:
         else:
-            # Must be some user defined type, return the ptr
-            # which will be downcast to that type.
-            return eventParameter.getPtr()
+            return eventParameter.value
         
         
     def processEvent(self, event):
     def processEvent(self, event):
         """
         """

+ 2 - 2
panda/src/awesomium/AwMouseAndKeyboard.cxx

@@ -30,8 +30,8 @@ void AwMouseAndKeyboard::do_transmit_data(DataGraphTraverser *trav, const DataNo
 
 
   if (input.has_data(_button_events_input)) {
   if (input.has_data(_button_events_input)) {
     const ButtonEventList *button_events;
     const ButtonEventList *button_events;
-    DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_ptr());
-    
+    DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_typed_object());
+
     int num_events = button_events->get_num_events();
     int num_events = button_events->get_num_events();
     for (int i = 0; i < num_events; i++) {
     for (int i = 0; i < num_events; i++) {
       const ButtonEvent &be = button_events->get_event(i);
       const ButtonEvent &be = button_events->get_event(i);

+ 5 - 5
panda/src/collide/collisionEntry.h

@@ -23,7 +23,7 @@
 #include "collisionRecorder.h"
 #include "collisionRecorder.h"
 
 
 #include "transformState.h"
 #include "transformState.h"
-#include "typedWritableReferenceCount.h"
+#include "typedReferenceCount.h"
 #include "luse.h"
 #include "luse.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
 #include "pandaNode.h"
 #include "pandaNode.h"
@@ -43,7 +43,7 @@
 //               is up to the handler to determine what information is
 //               is up to the handler to determine what information is
 //               known and to do the right thing with it.
 //               known and to do the right thing with it.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA_COLLIDE CollisionEntry : public TypedWritableReferenceCount {
+class EXPCL_PANDA_COLLIDE CollisionEntry : public TypedReferenceCount {
 public:
 public:
   INLINE CollisionEntry();
   INLINE CollisionEntry();
   CollisionEntry(const CollisionEntry &copy);
   CollisionEntry(const CollisionEntry &copy);
@@ -141,15 +141,15 @@ private:
 
 
   LPoint3 _contact_pos;
   LPoint3 _contact_pos;
   LVector3 _contact_normal;
   LVector3 _contact_normal;
-  
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    TypedWritableReferenceCount::init_type();
+    TypedReferenceCount::init_type();
     register_type(_type_handle, "CollisionEntry",
     register_type(_type_handle, "CollisionEntry",
-                  TypedWritableReferenceCount::get_class_type());
+                  TypedReferenceCount::get_class_type());
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 9 - 7
panda/src/dgraph/dataNode.cxx

@@ -156,7 +156,7 @@ write_connections(ostream &out) const {
       const string &name = (*wi).first;
       const string &name = (*wi).first;
       const WireDef &def = (*wi).second;
       const WireDef &def = (*wi).second;
       if (def._index == connect._input_index) {
       if (def._index == connect._input_index) {
-        out << name << " " << def._data_type << " from " 
+        out << name << " " << def._data_type << " from "
             << *get_parent(connect._parent_index) << "\n";
             << *get_parent(connect._parent_index) << "\n";
         found = true;
         found = true;
       }
       }
@@ -170,9 +170,10 @@ write_connections(ostream &out) const {
 //       Access: Protected
 //       Access: Protected
 //  Description: Adds a new input wire with the given name and the
 //  Description: Adds a new input wire with the given name and the
 //               indicated data type.  The data type should be the
 //               indicated data type.  The data type should be the
-//               TypeHandle for some type that derives from
-//               TypedReferenceCount, e.g. EventStoreInt,
-//               EventStoreDouble, or some fancier data type like
+//               TypeHandle for some type that can be stored in a
+//               Parameter, which includes simple types like int,
+//               float, bool, and double, or a fancier type that
+//               derives from TypedWritableReferenceCount, like
 //               Texture.
 //               Texture.
 //
 //
 //               If there is already an input wire defined with the
 //               If there is already an input wire defined with the
@@ -209,9 +210,10 @@ define_input(const string &name, TypeHandle data_type) {
 //       Access: Protected
 //       Access: Protected
 //  Description: Adds a new output wire with the given name and the
 //  Description: Adds a new output wire with the given name and the
 //               indicated data type.  The data type should be the
 //               indicated data type.  The data type should be the
-//               TypeHandle for some type that derives from
-//               TypedReferenceCount, e.g. EventStoreInt,
-//               EventStoreDouble, or some fancier data type like
+//               TypeHandle for some type that can be stored in a
+//               Parameter, which includes simple types like int,
+//               float, bool, and double, or a fancier type that
+//               derives from TypedWritableReferenceCount, like
 //               Texture.
 //               Texture.
 //
 //
 //               If there is already an output wire defined with the
 //               If there is already an output wire defined with the

+ 16 - 0
panda/src/dgraph/dataNodeTransmit.I

@@ -96,3 +96,19 @@ set_data(int index, const EventParameter &data) {
   nassertv(index >= 0 && index < (int)_data.size());
   nassertv(index >= 0 && index < (int)_data.size());
   _data[index] = data;
   _data[index] = data;
 }
 }
+
+#ifdef USE_MOVE_SEMANTICS
+////////////////////////////////////////////////////////////////////
+//     Function: DataNodeTransmit::set_data
+//       Access: Public
+//  Description: Sets the data for the indicated parameter.
+////////////////////////////////////////////////////////////////////
+INLINE void DataNodeTransmit::
+set_data(int index, EventParameter &&data) {
+  if (index >= (int)_data.size()) {
+    slot_data(index);
+  }
+  nassertv(index >= 0 && index < (int)_data.size());
+  _data[index] = move(data);
+}
+#endif  // USE_MOVE_SEMANTICS

+ 5 - 5
panda/src/dgraph/dataNodeTransmit.cxx

@@ -66,8 +66,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   Data::const_iterator di;
   Data::const_iterator di;
   for (di = _data.begin(); di != _data.end(); ++di) {
   for (di = _data.begin(); di != _data.end(); ++di) {
     const EventParameter &param = (*di);
     const EventParameter &param = (*di);
-    TypedWritableReferenceCount *ptr = param.get_ptr();
-    manager->write_pointer(dg, ptr);
+    param.write_datagram(manager, dg);
   }
   }
 }
 }
 
 
@@ -84,7 +83,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
 
 
   Data::iterator di;
   Data::iterator di;
   for (di = _data.begin(); di != _data.end(); ++di) {
   for (di = _data.begin(); di != _data.end(); ++di) {
-    (*di) = EventParameter(DCAST(TypedWritableReferenceCount, p_list[pi++]));
+    (*di).complete_pointers(&p_list[pi++], manager);
   }
   }
 
 
   return pi;
   return pi;
@@ -124,7 +123,8 @@ fillin(DatagramIterator &scan, BamReader *manager) {
   int num_params = scan.get_uint16();
   int num_params = scan.get_uint16();
   _data.reserve(num_params);
   _data.reserve(num_params);
   for (int i = 0; i < num_params; i++) {
   for (int i = 0; i < num_params; i++) {
-    manager->read_pointer(scan);
-    _data.push_back(EventParameter());
+    EventParameter param;
+    param.read_datagram(scan, manager);
+    _data.push_back(param);
   }
   }
 }
 }

+ 5 - 1
panda/src/dgraph/dataNodeTransmit.h

@@ -46,6 +46,10 @@ public:
   INLINE bool has_data(int index) const;
   INLINE bool has_data(int index) const;
   INLINE void set_data(int index, const EventParameter &data);
   INLINE void set_data(int index, const EventParameter &data);
 
 
+#ifdef USE_MOVE_SEMANTICS
+  INLINE void set_data(int index, EventParameter &&data);
+#endif
+
 private:
 private:
   void slot_data(int index);
   void slot_data(int index);
 
 
@@ -61,7 +65,7 @@ public:
 protected:
 protected:
   static TypedWritable *make_from_bam(const FactoryParams &params);
   static TypedWritable *make_from_bam(const FactoryParams &params);
   void fillin(DatagramIterator &scan, BamReader *manager);
   void fillin(DatagramIterator &scan, BamReader *manager);
-  
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 1 - 7
panda/src/display/graphicsOutput.h

@@ -25,7 +25,7 @@
 #include "renderBuffer.h"
 #include "renderBuffer.h"
 #include "graphicsOutputBase.h"
 #include "graphicsOutputBase.h"
 #include "luse.h"
 #include "luse.h"
-#include "typedWritableReferenceCount.h"
+#include "typedReferenceCount.h"
 #include "pandaNode.h"
 #include "pandaNode.h"
 #include "pStatCollector.h"
 #include "pStatCollector.h"
 #include "pnotify.h"
 #include "pnotify.h"
@@ -58,12 +58,6 @@ class GraphicsEngine;
 //               the graphics context itself, is managed by the
 //               the graphics context itself, is managed by the
 //               associated GraphicsStateGuardian (which might output
 //               associated GraphicsStateGuardian (which might output
 //               to multiple GraphicsOutput objects).
 //               to multiple GraphicsOutput objects).
-//
-//               GraphicsOutputs are not actually writable to bam
-//               files, of course, but they may be passed as event
-//               parameters, so they inherit from
-//               TypedWritableReferenceCount instead of
-//               TypedReferenceCount for that convenience.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_DISPLAY GraphicsOutput : public GraphicsOutputBase, public DrawableRegion {
 class EXPCL_PANDA_DISPLAY GraphicsOutput : public GraphicsOutputBase, public DrawableRegion {
 protected:
 protected:

+ 3 - 3
panda/src/event/Sources.pp

@@ -22,7 +22,7 @@
     pointerEventList.I pointerEventList.h \
     pointerEventList.I pointerEventList.h \
     pythonTask.h pythonTask.I \
     pythonTask.h pythonTask.I \
     event.I event.h eventHandler.h eventHandler.I \
     event.I event.h eventHandler.h eventHandler.I \
-    eventParameter.I eventParameter.h \
+    eventParameter.h \
     eventQueue.I eventQueue.h eventReceiver.h \
     eventQueue.I eventQueue.h eventReceiver.h \
     pt_Event.h throw_event.I throw_event.h 
     pt_Event.h throw_event.I throw_event.h 
     
     
@@ -40,7 +40,7 @@
     pointerEventList.cxx \
     pointerEventList.cxx \
     pythonTask.cxx \
     pythonTask.cxx \
     config_event.cxx event.cxx eventHandler.cxx \ 
     config_event.cxx event.cxx eventHandler.cxx \ 
-    eventParameter.cxx eventQueue.cxx eventReceiver.cxx \
+    eventQueue.cxx eventReceiver.cxx \
     pt_Event.cxx
     pt_Event.cxx
 
 
   #define INSTALL_HEADERS \
   #define INSTALL_HEADERS \
@@ -57,7 +57,7 @@
     pointerEventList.I pointerEventList.h \
     pointerEventList.I pointerEventList.h \
     pythonTask.h pythonTask.I \
     pythonTask.h pythonTask.I \
     event.I event.h eventHandler.h eventHandler.I \
     event.I event.h eventHandler.h eventHandler.I \
-    eventParameter.I eventParameter.h \
+    eventParameter.h \
     eventQueue.I eventQueue.h eventReceiver.h \
     eventQueue.I eventQueue.h eventReceiver.h \
     pt_Event.h throw_event.I throw_event.h 
     pt_Event.h throw_event.I throw_event.h 
 
 

+ 2 - 2
panda/src/event/buttonEvent.h

@@ -37,7 +37,7 @@ class DatagramIterator;
 //               combination of buttons (e.g. "A" is the result of
 //               combination of buttons (e.g. "A" is the result of
 //               shift + "a"); and (b) it does not manage separate
 //               shift + "a"); and (b) it does not manage separate
 //               "up" and "down" events, but is itself an
 //               "up" and "down" events, but is itself an
-//               instantaneous event.  
+//               instantaneous event.
 //
 //
 //               Normal up/down button events can be used to track the
 //               Normal up/down button events can be used to track the
 //               state of a particular button on the keyboard, while
 //               state of a particular button on the keyboard, while
@@ -97,7 +97,7 @@ public:
   INLINE ButtonEvent();
   INLINE ButtonEvent();
   INLINE ButtonEvent(ButtonHandle button, Type type, double time = ClockObject::get_global_clock()->get_frame_time());
   INLINE ButtonEvent(ButtonHandle button, Type type, double time = ClockObject::get_global_clock()->get_frame_time());
   INLINE ButtonEvent(short keycode, double time = ClockObject::get_global_clock()->get_frame_time());
   INLINE ButtonEvent(short keycode, double time = ClockObject::get_global_clock()->get_frame_time());
-  INLINE ButtonEvent(const wstring &candidate_string, size_t highlight_start, 
+  INLINE ButtonEvent(const wstring &candidate_string, size_t highlight_start,
                      size_t highlight_end, size_t cursor_pos);
                      size_t highlight_end, size_t cursor_pos);
   INLINE ButtonEvent(const ButtonEvent &copy);
   INLINE ButtonEvent(const ButtonEvent &copy);
   INLINE void operator = (const ButtonEvent &copy);
   INLINE void operator = (const ButtonEvent &copy);

+ 0 - 4
panda/src/event/config_event.cxx

@@ -42,14 +42,10 @@ ConfigureFn(config_event) {
   PointerEventList::init_type();
   PointerEventList::init_type();
   Event::init_type();
   Event::init_type();
   EventHandler::init_type();
   EventHandler::init_type();
-  EventStoreInt::init_type("EventStoreInt");
-  EventStoreDouble::init_type("EventStoreDouble");
   GenericAsyncTask::init_type();
   GenericAsyncTask::init_type();
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
   PythonTask::init_type();
   PythonTask::init_type();
 #endif
 #endif
 
 
   ButtonEventList::register_with_read_factory();
   ButtonEventList::register_with_read_factory();
-  EventStoreInt::register_with_read_factory();
-  EventStoreDouble::register_with_read_factory();
 }
 }

+ 11 - 0
panda/src/event/event.cxx

@@ -73,6 +73,17 @@ add_parameter(const EventParameter &obj) {
   _parameters.push_back(obj);
   _parameters.push_back(obj);
 }
 }
 
 
+#ifdef USE_MOVE_SEMANTICS
+////////////////////////////////////////////////////////////////////
+//     Function: Event::add_parameter
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void Event::
+add_parameter(EventParameter &&obj) {
+  _parameters.push_back(move(obj));
+}
+#endif  // USE_MOVE_SEMANTICS
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: Event::get_num_parameters
 //     Function: Event::get_num_parameters

+ 4 - 0
panda/src/event/event.h

@@ -47,6 +47,10 @@ PUBLISHED:
 
 
   void add_parameter(const EventParameter &obj);
   void add_parameter(const EventParameter &obj);
 
 
+#ifdef USE_MOVE_SEMANTICS
+  void add_parameter(EventParameter &&obj);
+#endif
+
   int get_num_parameters() const;
   int get_num_parameters() const;
   EventParameter get_parameter(int n) const;
   EventParameter get_parameter(int n) const;
   MAKE_SEQ(get_parameters, get_num_parameters, get_parameter);
   MAKE_SEQ(get_parameters, get_num_parameters, get_parameter);

+ 0 - 297
panda/src/event/eventParameter.I

@@ -1,297 +0,0 @@
-// Filename: eventParameter.I
-// Created by:  drose (08Feb99)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) Carnegie Mellon University.  All rights reserved.
-//
-// All use of this software is subject to the terms of the revised BSD
-// license.  You should have received a copy of this license along
-// with this source code in a file named "LICENSE."
-//
-////////////////////////////////////////////////////////////////////
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::Default constructor
-//       Access: Published
-//  Description: Defines an EventParameter that stores nothing: the
-//               "empty" parameter.
-////////////////////////////////////////////////////////////////////
-INLINE EventParameter::
-EventParameter() {
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::Pointer constructor
-//       Access: Published
-//  Description: Defines an EventParameter that stores a pointer to
-//               any kind of TypedWritableReferenceCount object.  This
-//               is the most general constructor.
-//
-//               This accepts a const pointer, even though it stores
-//               (and eventually returns) a non-const pointer.  This
-//               is just the simplest way to allow both const and
-//               non-const pointers to be stored, but it does lose the
-//               constness.  Be careful.
-////////////////////////////////////////////////////////////////////
-INLINE EventParameter::
-EventParameter(const TypedWritableReferenceCount *ptr) : _ptr((TypedWritableReferenceCount *)ptr) { }
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::Pointer constructor
-//       Access: Published
-//  Description: Defines an EventParameter that stores a pointer to
-//               a TypedReferenceCount object.  Note that a
-//               TypedReferenceCount is not the same kind of pointer
-//               as a TypedWritableReferenceCount, hence we require
-//               both constructors.
-//
-//               This accepts a const pointer, even though it stores
-//               (and eventually returns) a non-const pointer.  This
-//               is just the simplest way to allow both const and
-//               non-const pointers to be stored, but it does lose the
-//               constness.  Be careful.
-////////////////////////////////////////////////////////////////////
-INLINE EventParameter::
-EventParameter(const TypedReferenceCount *ptr) : _ptr(new EventStoreTypedRefCount((TypedReferenceCount *)ptr)) { }
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::Integer constructor
-//       Access: Published
-//  Description: Defines an EventParameter that stores an integer
-//               value.
-////////////////////////////////////////////////////////////////////
-INLINE EventParameter::
-EventParameter(int value) : _ptr(new EventStoreInt(value)) { }
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::Double constructor
-//       Access: Published
-//  Description: Defines an EventParameter that stores a
-//               floating-point value.
-////////////////////////////////////////////////////////////////////
-INLINE EventParameter::
-EventParameter(double value) : _ptr(new EventStoreDouble(value)) { }
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::String constructor
-//       Access: Published
-//  Description: Defines an EventParameter that stores a string value.
-////////////////////////////////////////////////////////////////////
-INLINE EventParameter::
-EventParameter(const string &value) : _ptr(new EventStoreString(value)) { }
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::Wstring constructor
-//       Access: Published
-//  Description: Defines an EventParameter that stores a wstring value.
-////////////////////////////////////////////////////////////////////
-INLINE EventParameter::
-EventParameter(const wstring &value) : _ptr(new EventStoreWstring(value)) { }
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::Copy constructor
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE EventParameter::
-EventParameter(const EventParameter &other) : _ptr(other._ptr) { }
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::Copy assignment operator
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE EventParameter &EventParameter::
-operator = (const EventParameter &other) {
-  _ptr = other._ptr;
-  return *this;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::Destructor
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE EventParameter::
-~EventParameter() {
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::is_empty
-//       Access: Published
-//  Description: Returns true if the EventParameter is the empty
-//               parameter, storing nothing, or false otherwise.
-////////////////////////////////////////////////////////////////////
-INLINE bool EventParameter::
-is_empty() const {
-  return (_ptr == (TypedWritableReferenceCount *)NULL);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::is_int
-//       Access: Published
-//  Description: Returns true if the EventParameter stores an integer
-//               value, false otherwise.
-////////////////////////////////////////////////////////////////////
-INLINE bool EventParameter::
-is_int() const {
-  if (is_empty()) {
-    return false;
-  }
-  return _ptr->is_of_type(EventStoreInt::get_class_type());
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::get_int_value
-//       Access: Published
-//  Description: Retrieves the value stored in the EventParameter.  It
-//               is only valid to call this if is_int() has already
-//               returned true.
-////////////////////////////////////////////////////////////////////
-INLINE int EventParameter::
-get_int_value() const {
-  nassertr(is_int(), 0);
-  // We can't use DCAST, because EventStoreValue::init_type() breaks
-  // convention and takes a parameter.  But the above assertion should
-  // protect us.
-  return ((const EventStoreInt *)_ptr.p())->get_value();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::is_double
-//       Access: Published
-//  Description: Returns true if the EventParameter stores a double
-//               floating-point value, false otherwise.
-////////////////////////////////////////////////////////////////////
-INLINE bool EventParameter::
-is_double() const {
-  if (is_empty()) {
-    return false;
-  }
-  return _ptr->is_of_type(EventStoreDouble::get_class_type());
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::get_double_value
-//       Access: Published
-//  Description: Retrieves the value stored in the EventParameter.  It
-//               is only valid to call this if is_double() has already
-//               returned true.
-////////////////////////////////////////////////////////////////////
-INLINE double EventParameter::
-get_double_value() const {
-  nassertr(is_double(), 0.0);
-  return ((const EventStoreDouble *)_ptr.p())->get_value();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::is_string
-//       Access: Published
-//  Description: Returns true if the EventParameter stores a string
-//               value, false otherwise.
-////////////////////////////////////////////////////////////////////
-INLINE bool EventParameter::
-is_string() const {
-  if (is_empty()) {
-    return false;
-  }
-  return _ptr->is_of_type(EventStoreString::get_class_type());
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::get_string_value
-//       Access: Published
-//  Description: Retrieves the value stored in the EventParameter.  It
-//               is only valid to call this if is_string() has already
-//               returned true.
-////////////////////////////////////////////////////////////////////
-INLINE string EventParameter::
-get_string_value() const {
-  nassertr(is_string(), "");
-  return ((const EventStoreString *)_ptr.p())->get_value();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::is_wstring
-//       Access: Published
-//  Description: Returns true if the EventParameter stores a wstring
-//               value, false otherwise.
-////////////////////////////////////////////////////////////////////
-INLINE bool EventParameter::
-is_wstring() const {
-  if (is_empty()) {
-    return false;
-  }
-  return _ptr->is_of_type(EventStoreWstring::get_class_type());
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::get_wstring_value
-//       Access: Published
-//  Description: Retrieves the value stored in the EventParameter.  It
-//               is only valid to call this if is_wstring() has already
-//               returned true.
-////////////////////////////////////////////////////////////////////
-INLINE wstring EventParameter::
-get_wstring_value() const {
-  nassertr(is_wstring(), wstring());
-  return ((const EventStoreWstring *)_ptr.p())->get_value();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::is_typed_ref_count
-//       Access: Published
-//  Description: Returns true if the EventParameter stores a
-//               TypedReferenceCount pointer, false otherwise.  Note
-//               that a TypedReferenceCount is not exactly the same
-//               kind of pointer as a TypedWritableReferenceCount,
-//               hence the need for this separate call.
-////////////////////////////////////////////////////////////////////
-INLINE bool EventParameter::
-is_typed_ref_count() const {
-  if (is_empty()) {
-    return false;
-  }
-  return _ptr->is_of_type(EventStoreTypedRefCount::get_class_type());
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::get_typed_ref_count_value
-//       Access: Published
-//  Description: Retrieves the value stored in the EventParameter.  It
-//               is only valid to call this if is_typed_ref_count()
-//               has already returned true.
-////////////////////////////////////////////////////////////////////
-INLINE TypedReferenceCount *EventParameter::
-get_typed_ref_count_value() const {
-  nassertr(is_typed_ref_count(), NULL);
-  return ((const EventStoreTypedRefCount *)_ptr.p())->get_value();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::get_ptr
-//       Access: Published
-//  Description: Retrieves a pointer to the actual value stored in the
-//               parameter.  The TypeHandle of this pointer may be
-//               examined to determine the actual type of parameter it
-//               contains.  This is the only way to retrieve the value
-//               when it is not one of the above predefined types.
-////////////////////////////////////////////////////////////////////
-INLINE TypedWritableReferenceCount *EventParameter::
-get_ptr() const {
-  return _ptr;
-}
-
-INLINE ostream &
-operator << (ostream &out, const EventParameter &param) {
-  param.output(out);
-  return out;
-}

+ 0 - 41
panda/src/event/eventParameter.cxx

@@ -1,41 +0,0 @@
-// Filename: eventParameter.cxx
-// Created by:  drose (08Feb99)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) Carnegie Mellon University.  All rights reserved.
-//
-// All use of this software is subject to the terms of the revised BSD
-// license.  You should have received a copy of this license along
-// with this source code in a file named "LICENSE."
-//
-////////////////////////////////////////////////////////////////////
-
-#include "eventParameter.h"
-#include "dcast.h"
-
-// Tell GCC that we'll take care of the instantiation explicitly here.
-#ifdef __GNUC__
-#pragma implementation
-#endif
-
-////////////////////////////////////////////////////////////////////
-//     Function: EventParameter::output
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-void EventParameter::
-output(ostream &out) const {
-  if (_ptr == (TypedWritableReferenceCount *)NULL) {
-    out << "(empty)";
-
-  } else if (_ptr->is_of_type(ParamValueBase::get_class_type())) {
-    const ParamValueBase *sv_ptr;
-    DCAST_INTO_V(sv_ptr, _ptr);
-    sv_ptr->output(out);
-
-  } else {
-    out << _ptr->get_type();
-  }
-}

+ 4 - 66
panda/src/event/eventParameter.h

@@ -18,77 +18,15 @@
 #include "pandabase.h"
 #include "pandabase.h"
 
 
 #include "typedef.h"
 #include "typedef.h"
-#include "typedObject.h"
-#include "typedWritableReferenceCount.h"
-#include "pointerTo.h"
-#include "bamReader.h"
-#include "bamWriter.h"
-#include "paramValue.h"
+#include "parameter.h"
 
 
-////////////////////////////////////////////////////////////////////
-//       Class : EventParameter
-// Description : An optional parameter associated with an event.  Each
-//               event may have zero or more of these.  Each parameter
-//               stores a pointer to a TypedWritableReferenceCount
-//               object, which of course could be pretty much
-//               anything.  To store a simple value like a double or a
-//               string, the EventParameter constructors transparently
-//               use the ParamValue template class from paramValue.h.
-////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA_EVENT EventParameter {
-PUBLISHED:
-  INLINE EventParameter();
-  INLINE EventParameter(const TypedWritableReferenceCount *ptr);
-  INLINE EventParameter(const TypedReferenceCount *ptr);
-  INLINE EventParameter(int value);
-  INLINE EventParameter(double value);
-  INLINE EventParameter(const string &value);
-  INLINE EventParameter(const wstring &value);
-
-  INLINE EventParameter(const EventParameter &copy);
-  INLINE EventParameter &operator = (const EventParameter &copy);
-  INLINE ~EventParameter();
-
-  // These functions are conveniences to easily determine if the
-  // EventParameter is one of the predefined parameter types, and
-  // retrieve the corresponding value.  Of course, it is possible that
-  // the EventParameter is some user-defined type, and is none of
-  // these.
-  INLINE bool is_empty() const;
-  INLINE bool is_int() const;
-  INLINE int get_int_value() const;
-  INLINE bool is_double() const;
-  INLINE double get_double_value() const;
-  INLINE bool is_string() const;
-  INLINE string get_string_value() const;
-  INLINE bool is_wstring() const;
-  INLINE wstring get_wstring_value() const;
-
-  INLINE bool is_typed_ref_count() const;
-  INLINE TypedReferenceCount *get_typed_ref_count_value() const;
-
-  INLINE TypedWritableReferenceCount *get_ptr() const;
+// Some typedefs for backward compatibility.
+typedef Parameter EventParameter;
 
 
-  void output(ostream &out) const;
-
-private:
-  PT(TypedWritableReferenceCount) _ptr;
-};
-
-INLINE ostream &operator << (ostream &out, const EventParameter &param);
-
-typedef ParamTypedRefCount EventStoreTypedRefCount;
-
-EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_EVENT, EXPTP_PANDA_EVENT, ParamValue<int>);
-EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_EVENT, EXPTP_PANDA_EVENT, ParamValue<double>);
-
-typedef ParamValue<int> EventStoreInt;
-typedef ParamValue<double> EventStoreDouble;
+typedef ParamValueBase EventStoreValueBase;
 typedef ParamString EventStoreString;
 typedef ParamString EventStoreString;
 typedef ParamWstring EventStoreWstring;
 typedef ParamWstring EventStoreWstring;
 
 
-#include "eventParameter.I"
-
 // Tell GCC that we'll take care of the instantiation explicitly here.
 // Tell GCC that we'll take care of the instantiation explicitly here.
 #ifdef __GNUC__
 #ifdef __GNUC__
 #pragma interface
 #pragma interface

+ 0 - 1
panda/src/event/p3event_composite2.cxx

@@ -1,7 +1,6 @@
 #include "config_event.cxx"
 #include "config_event.cxx"
 #include "event.cxx"
 #include "event.cxx"
 #include "eventHandler.cxx"
 #include "eventHandler.cxx"
-#include "eventParameter.cxx"
 #include "eventQueue.cxx"
 #include "eventQueue.cxx"
 #include "eventReceiver.cxx"
 #include "eventReceiver.cxx"
 #include "pt_Event.cxx"
 #include "pt_Event.cxx"

+ 25 - 1
panda/src/express/referenceCount.I

@@ -337,6 +337,30 @@ weak_unref(WeakPointerToVoid *ptv) {
   ((WeakReferenceList *)_weak_list)->clear_reference(ptv);
   ((WeakReferenceList *)_weak_list)->clear_reference(ptv);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ReferenceCount::as_typed_object
+//       Access: Public
+//  Description: If this object derives from TypedReferenceCount or
+//               TypedWritableReferenceCount, returns a pointer to
+//               the base TypedObject.  Otherwise, returns NULL.
+////////////////////////////////////////////////////////////////////
+INLINE TypedObject *ReferenceCount::
+as_typed_object() {
+  return NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ReferenceCount::as_typed_object
+//       Access: Public
+//  Description: If this object derives from TypedReferenceCount or
+//               TypedWritableReferenceCount, returns a pointer to
+//               the base TypedObject.  Otherwise, returns NULL.
+////////////////////////////////////////////////////////////////////
+INLINE const TypedObject *ReferenceCount::
+as_typed_object() const {
+  return NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: unref_delete
 //     Function: unref_delete
 //  Description: This global helper function will unref the given
 //  Description: This global helper function will unref the given
@@ -360,7 +384,7 @@ unref_delete(RefCountType *ptr) {
   if (!ptr->unref()) {
   if (!ptr->unref()) {
     // If the reference count has gone to zero, delete the object.
     // If the reference count has gone to zero, delete the object.
     delete ptr;
     delete ptr;
-  } 
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 8 - 1
panda/src/express/referenceCount.h

@@ -63,6 +63,13 @@ public:
   INLINE void weak_ref(WeakPointerToVoid *ptv);
   INLINE void weak_ref(WeakPointerToVoid *ptv);
   INLINE void weak_unref(WeakPointerToVoid *ptv);
   INLINE void weak_unref(WeakPointerToVoid *ptv);
 
 
+  // These convenience methods are defined to resolve the cast from
+  // ReferenceCount to TypedObject through TypedReferenceCount
+  // or TypedWritableReferenceCount, since the latter does not
+  // directly derive from the former.
+  virtual INLINE TypedObject *as_typed_object();
+  virtual INLINE const TypedObject *as_typed_object() const;
+
 protected:
 protected:
   bool do_test_ref_count_integrity() const;
   bool do_test_ref_count_integrity() const;
   bool do_test_ref_count_nonzero() const;
   bool do_test_ref_count_nonzero() const;
@@ -71,7 +78,7 @@ private:
   void create_weak_list();
   void create_weak_list();
 
 
 private:
 private:
-  enum { 
+  enum {
     // We use this value as a flag to indicate an object has been
     // We use this value as a flag to indicate an object has been
     // indicated as a local object, and should not be deleted except
     // indicated as a local object, and should not be deleted except
     // by its own destructor.  Really, any nonzero value would do, but
     // by its own destructor.  Really, any nonzero value would do, but

+ 24 - 0
panda/src/express/typedReferenceCount.I

@@ -50,3 +50,27 @@ operator = (const TypedReferenceCount &copy) {
   TypedObject::operator = (copy);
   TypedObject::operator = (copy);
   ReferenceCount::operator = (copy);
   ReferenceCount::operator = (copy);
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: TypedReferenceCount::as_typed_object
+//       Access: Public
+//  Description: If this object derives from TypedReferenceCount or
+//               TypedWritableReferenceCount, returns a pointer to
+//               the base TypedObject.  Otherwise, returns NULL.
+////////////////////////////////////////////////////////////////////
+INLINE TypedObject *TypedReferenceCount::
+as_typed_object() {
+  return this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TypedReferenceCount::as_typed_object
+//       Access: Public
+//  Description: If this object derives from TypedReferenceCount or
+//               TypedWritableReferenceCount, returns a pointer to
+//               the base TypedObject.  Otherwise, returns NULL.
+////////////////////////////////////////////////////////////////////
+INLINE const TypedObject *TypedReferenceCount::
+as_typed_object() const {
+  return this;
+}

+ 4 - 1
panda/src/express/typedReferenceCount.h

@@ -29,7 +29,7 @@
 //               each time they are needed, so that we can sensibly
 //               each time they are needed, so that we can sensibly
 //               pass around pointers to things which are both
 //               pass around pointers to things which are both
 //               TypedObjects and ReferenceCounters.
 //               TypedObjects and ReferenceCounters.
-//               
+//
 //               See also TypedObject for detailed instructions.
 //               See also TypedObject for detailed instructions.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDAEXPRESS TypedReferenceCount : public TypedObject, public ReferenceCount {
 class EXPCL_PANDAEXPRESS TypedReferenceCount : public TypedObject, public ReferenceCount {
@@ -38,6 +38,9 @@ public:
   INLINE TypedReferenceCount(const TypedReferenceCount &copy);
   INLINE TypedReferenceCount(const TypedReferenceCount &copy);
   INLINE void operator = (const TypedReferenceCount &copy);
   INLINE void operator = (const TypedReferenceCount &copy);
 
 
+  virtual INLINE TypedObject *as_typed_object();
+  virtual INLINE const TypedObject *as_typed_object() const;
+
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 13 - 13
panda/src/framework/pandaFramework.cxx

@@ -960,7 +960,7 @@ event_esc(const Event *event, void *data) {
   if (event->get_num_parameters() == 1) {
   if (event->get_num_parameters() == 1) {
     EventParameter param = event->get_parameter(0);
     EventParameter param = event->get_parameter(0);
     WindowFramework *wf;
     WindowFramework *wf;
-    DCAST_INTO_V(wf, param.get_ptr());
+    DCAST_INTO_V(wf, param.get_typed_object());
 
 
     PT(GraphicsOutput) win = wf->get_graphics_output();
     PT(GraphicsOutput) win = wf->get_graphics_output();
 
 
@@ -1010,7 +1010,7 @@ event_w(const Event *event, void *) {
   if (event->get_num_parameters() == 1) {
   if (event->get_num_parameters() == 1) {
     EventParameter param = event->get_parameter(0);
     EventParameter param = event->get_parameter(0);
     WindowFramework *wf;
     WindowFramework *wf;
-    DCAST_INTO_V(wf, param.get_ptr());
+    DCAST_INTO_V(wf, param.get_typed_object());
 
 
     wf->set_wireframe(!wf->get_wireframe());
     wf->set_wireframe(!wf->get_wireframe());
   }
   }
@@ -1026,7 +1026,7 @@ event_t(const Event *event, void *) {
   if (event->get_num_parameters() == 1) {
   if (event->get_num_parameters() == 1) {
     EventParameter param = event->get_parameter(0);
     EventParameter param = event->get_parameter(0);
     WindowFramework *wf;
     WindowFramework *wf;
-    DCAST_INTO_V(wf, param.get_ptr());
+    DCAST_INTO_V(wf, param.get_typed_object());
 
 
     wf->set_texture(!wf->get_texture());
     wf->set_texture(!wf->get_texture());
   }
   }
@@ -1043,7 +1043,7 @@ event_b(const Event *event, void *) {
   if (event->get_num_parameters() == 1) {
   if (event->get_num_parameters() == 1) {
     EventParameter param = event->get_parameter(0);
     EventParameter param = event->get_parameter(0);
     WindowFramework *wf;
     WindowFramework *wf;
-    DCAST_INTO_V(wf, param.get_ptr());
+    DCAST_INTO_V(wf, param.get_typed_object());
 
 
     wf->set_two_sided(!wf->get_two_sided());
     wf->set_two_sided(!wf->get_two_sided());
   }
   }
@@ -1059,7 +1059,7 @@ event_i(const Event *event, void *) {
   if (event->get_num_parameters() == 1) {
   if (event->get_num_parameters() == 1) {
     EventParameter param = event->get_parameter(0);
     EventParameter param = event->get_parameter(0);
     WindowFramework *wf;
     WindowFramework *wf;
-    DCAST_INTO_V(wf, param.get_ptr());
+    DCAST_INTO_V(wf, param.get_typed_object());
 
 
     wf->set_one_sided_reverse(!wf->get_one_sided_reverse());
     wf->set_one_sided_reverse(!wf->get_one_sided_reverse());
   }
   }
@@ -1075,7 +1075,7 @@ event_l(const Event *event, void *) {
   if (event->get_num_parameters() == 1) {
   if (event->get_num_parameters() == 1) {
     EventParameter param = event->get_parameter(0);
     EventParameter param = event->get_parameter(0);
     WindowFramework *wf;
     WindowFramework *wf;
-    DCAST_INTO_V(wf, param.get_ptr());
+    DCAST_INTO_V(wf, param.get_typed_object());
 
 
     wf->set_lighting(!wf->get_lighting());
     wf->set_lighting(!wf->get_lighting());
   }
   }
@@ -1091,7 +1091,7 @@ event_p(const Event *event, void *) {
   if (event->get_num_parameters() == 1) {
   if (event->get_num_parameters() == 1) {
     EventParameter param = event->get_parameter(0);
     EventParameter param = event->get_parameter(0);
     WindowFramework *wf;
     WindowFramework *wf;
-    DCAST_INTO_V(wf, param.get_ptr());
+    DCAST_INTO_V(wf, param.get_typed_object());
 
 
     wf->set_perpixel(!wf->get_perpixel());
     wf->set_perpixel(!wf->get_perpixel());
   }
   }
@@ -1108,7 +1108,7 @@ event_c(const Event *event, void *data) {
   if (event->get_num_parameters() == 1) {
   if (event->get_num_parameters() == 1) {
     EventParameter param = event->get_parameter(0);
     EventParameter param = event->get_parameter(0);
     WindowFramework *wf;
     WindowFramework *wf;
-    DCAST_INTO_V(wf, param.get_ptr());
+    DCAST_INTO_V(wf, param.get_typed_object());
 
 
     PandaFramework *self = (PandaFramework *)data;
     PandaFramework *self = (PandaFramework *)data;
 
 
@@ -1131,7 +1131,7 @@ event_a(const Event *event, void *data) {
   if (event->get_num_parameters() == 1) {
   if (event->get_num_parameters() == 1) {
     EventParameter param = event->get_parameter(0);
     EventParameter param = event->get_parameter(0);
     WindowFramework *wf;
     WindowFramework *wf;
-    DCAST_INTO_V(wf, param.get_ptr());
+    DCAST_INTO_V(wf, param.get_typed_object());
 
 
     wf->next_anim_control();
     wf->next_anim_control();
   }
   }
@@ -1360,7 +1360,7 @@ event_f9(const Event *event, void *data) {
   if (event->get_num_parameters() == 1) {
   if (event->get_num_parameters() == 1) {
     EventParameter param = event->get_parameter(0);
     EventParameter param = event->get_parameter(0);
     WindowFramework *wf;
     WindowFramework *wf;
-    DCAST_INTO_V(wf, param.get_ptr());
+    DCAST_INTO_V(wf, param.get_typed_object());
 
 
     if (self->clear_text()) {
     if (self->clear_text()) {
       // Render one more frame to remove the text.
       // Render one more frame to remove the text.
@@ -1407,7 +1407,7 @@ event_comma(const Event *event, void *) {
   if (event->get_num_parameters() == 1) {
   if (event->get_num_parameters() == 1) {
     EventParameter param = event->get_parameter(0);
     EventParameter param = event->get_parameter(0);
     WindowFramework *wf;
     WindowFramework *wf;
-    DCAST_INTO_V(wf, param.get_ptr());
+    DCAST_INTO_V(wf, param.get_typed_object());
 
 
     switch (wf->get_background_type()) {
     switch (wf->get_background_type()) {
     case WindowFramework::BT_other:
     case WindowFramework::BT_other:
@@ -1435,7 +1435,7 @@ event_question(const Event *event, void *data) {
   if (event->get_num_parameters() == 1) {
   if (event->get_num_parameters() == 1) {
     EventParameter param = event->get_parameter(0);
     EventParameter param = event->get_parameter(0);
     WindowFramework *wf;
     WindowFramework *wf;
-    DCAST_INTO_V(wf, param.get_ptr());
+    DCAST_INTO_V(wf, param.get_typed_object());
 
 
     self->_screenshot_text.remove_node();
     self->_screenshot_text.remove_node();
 
 
@@ -1494,7 +1494,7 @@ event_window_event(const Event *event, void *data) {
     // of the keyboard events).
     // of the keyboard events).
     EventParameter param = event->get_parameter(0);
     EventParameter param = event->get_parameter(0);
     const GraphicsOutput *win;
     const GraphicsOutput *win;
-    DCAST_INTO_V(win, param.get_ptr());
+    DCAST_INTO_V(win, param.get_typed_object());
 
 
     // Is this a window we've heard about?
     // Is this a window we've heard about?
     int window_index = self->find_window(win);
     int window_index = self->find_window(win);

+ 6 - 6
panda/src/framework/windowFramework.h

@@ -28,7 +28,7 @@
 #include "pointerTo.h"
 #include "pointerTo.h"
 #include "partGroup.h"
 #include "partGroup.h"
 #include "pvector.h"
 #include "pvector.h"
-#include "typedWritableReferenceCount.h"
+#include "typedReferenceCount.h"
 #include "loaderOptions.h"
 #include "loaderOptions.h"
 #include "pgSliderBar.h"
 #include "pgSliderBar.h"
 #include "textNode.h"
 #include "textNode.h"
@@ -52,7 +52,7 @@ class DisplayRegion;
 //               the same GraphicsOutput pointer, but reference
 //               the same GraphicsOutput pointer, but reference
 //               different display regions within that window).
 //               different display regions within that window).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_FRAMEWORK WindowFramework : public TypedWritableReferenceCount {
+class EXPCL_FRAMEWORK WindowFramework : public TypedReferenceCount {
 protected:
 protected:
   WindowFramework(PandaFramework *panda_framework);
   WindowFramework(PandaFramework *panda_framework);
   WindowFramework(const WindowFramework &copy, DisplayRegion *display_region);
   WindowFramework(const WindowFramework &copy, DisplayRegion *display_region);
@@ -194,7 +194,7 @@ private:
 
 
   NodePath _alight;
   NodePath _alight;
   NodePath _dlight;
   NodePath _dlight;
-  
+
   bool _got_keyboard;
   bool _got_keyboard;
   bool _got_trackball;
   bool _got_trackball;
   bool _got_lights;
   bool _got_lights;
@@ -210,7 +210,7 @@ private:
   PT(SceneGraphAnalyzerMeter) _scene_graph_analyzer_meter;
   PT(SceneGraphAnalyzerMeter) _scene_graph_analyzer_meter;
 
 
   BackgroundType _background_type;
   BackgroundType _background_type;
-  
+
   static PT(TextFont) _shuttle_controls_font;
   static PT(TextFont) _shuttle_controls_font;
 
 
 public:
 public:
@@ -218,9 +218,9 @@ public:
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    TypedWritableReferenceCount::init_type();
+    TypedReferenceCount::init_type();
     register_type(_type_handle, "WindowFramework",
     register_type(_type_handle, "WindowFramework",
-                  TypedWritableReferenceCount::get_class_type());
+                  TypedReferenceCount::get_class_type());
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 5 - 5
panda/src/gsgbase/graphicsOutputBase.h

@@ -16,7 +16,7 @@
 #define GRAPHICSOUTPUTBASE_H
 #define GRAPHICSOUTPUTBASE_H
 
 
 #include "pandabase.h"
 #include "pandabase.h"
-#include "typedWritableReferenceCount.h"
+#include "typedReferenceCount.h"
 
 
 class Texture;
 class Texture;
 
 
@@ -25,19 +25,19 @@ class Texture;
 // Description : An abstract base class for GraphicsOutput, for all
 // Description : An abstract base class for GraphicsOutput, for all
 //               the usual reasons.
 //               the usual reasons.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA_GSGBASE GraphicsOutputBase : public TypedWritableReferenceCount {
+class EXPCL_PANDA_GSGBASE GraphicsOutputBase : public TypedReferenceCount {
 PUBLISHED:
 PUBLISHED:
   virtual void set_sort(int sort)=0;
   virtual void set_sort(int sort)=0;
   virtual Texture *get_texture(int i=0) const=0;
   virtual Texture *get_texture(int i=0) const=0;
-  
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    TypedWritableReferenceCount::init_type();
+    TypedReferenceCount::init_type();
     register_type(_type_handle, "GraphicsOutputBase",
     register_type(_type_handle, "GraphicsOutputBase",
-                  TypedWritableReferenceCount::get_class_type());
+                  TypedReferenceCount::get_class_type());
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 2 - 0
panda/src/linmath/lvecBase4.h

@@ -24,6 +24,8 @@
 #include "checksumHashGenerator.h"
 #include "checksumHashGenerator.h"
 #include "lvecBase2.h"
 #include "lvecBase2.h"
 #include "lvecBase3.h"
 #include "lvecBase3.h"
+#include "lpoint3.h"
+#include "lvector3.h"
 
 
 #include "cmath.h"
 #include "cmath.h"
 #include "nearly_zero.h"
 #include "nearly_zero.h"

+ 20 - 0
panda/src/linmath/lvecBase4_src.I

@@ -106,6 +106,26 @@ FLOATNAME(LVecBase4)(const FLOATNAME(LVecBase3) &copy, FLOATTYPE w) {
   set(copy[0], copy[1], copy[2], w);
   set(copy[0], copy[1], copy[2], w);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATNAME(LVecBase4)::
+FLOATNAME(LVecBase4)(const FLOATNAME(LPoint3) &point) {
+  set(point[0], point[1], point[2], 1);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LVecBase4::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_LINMATH FLOATNAME(LVecBase4)::
+FLOATNAME(LVecBase4)(const FLOATNAME(LVector3) &vector) {
+  set(vector[0], vector[1], vector[2], 0);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: LVecBase4::Destructor
 //     Function: LVecBase4::Destructor
 //       Access: Published
 //       Access: Published

+ 2 - 0
panda/src/linmath/lvecBase4_src.h

@@ -35,6 +35,8 @@ PUBLISHED:
   INLINE_LINMATH FLOATNAME(LVecBase4)(FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LVecBase4)(FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LVecBase4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w);
   INLINE_LINMATH FLOATNAME(LVecBase4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w);
   INLINE_LINMATH FLOATNAME(LVecBase4)(const FLOATNAME(LVecBase3) &copy, FLOATTYPE w);
   INLINE_LINMATH FLOATNAME(LVecBase4)(const FLOATNAME(LVecBase3) &copy, FLOATTYPE w);
+  INLINE_LINMATH FLOATNAME(LVecBase4)(const FLOATNAME(LPoint3) &point);
+  INLINE_LINMATH FLOATNAME(LVecBase4)(const FLOATNAME(LVector3) &vector);
   ALLOC_DELETED_CHAIN(FLOATNAME(LVecBase4));
   ALLOC_DELETED_CHAIN(FLOATNAME(LVecBase4));
 
 
   INLINE_LINMATH static const FLOATNAME(LVecBase4) &zero();
   INLINE_LINMATH static const FLOATNAME(LVecBase4) &zero();

+ 2 - 9
panda/src/pgraph/renderEffects.cxx

@@ -391,13 +391,6 @@ get_effect(TypeHandle type) const {
 //               breaks a cycle in the cache involving this object.
 //               breaks a cycle in the cache involving this object.
 //               This is designed to prevent leaks from cyclical
 //               This is designed to prevent leaks from cyclical
 //               references within the cache.
 //               references within the cache.
-//
-//               Note that this is not a virtual method, and cannot be
-//               because ReferenceCount itself declares no virtual
-//               methods (it avoids the overhead of a virtual function
-//               pointer).  But this doesn't matter, because
-//               PT(TransformState) is a template class, and will call
-//               the appropriate method even though it is non-virtual.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool RenderEffects::
 bool RenderEffects::
 unref() const {
 unref() const {
@@ -412,14 +405,14 @@ unref() const {
   // is removed from the global object pool, before anyone else finds
   // is removed from the global object pool, before anyone else finds
   // it and tries to ref it.
   // it and tries to ref it.
   ((RenderEffects *)this)->release_new();
   ((RenderEffects *)this)->release_new();
-  
+
   return false;
   return false;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: RenderEffects::output
 //     Function: RenderEffects::output
 //       Access: Published, Virtual
 //       Access: Published, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void RenderEffects::
 void RenderEffects::
 output(ostream &out) const {
 output(ostream &out) const {

+ 1 - 1
panda/src/pgraph/renderState.h

@@ -50,7 +50,7 @@ class ShaderAttrib;
 //               instead of modifying a RenderState object, create a
 //               instead of modifying a RenderState object, create a
 //               new one.
 //               new one.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA_PGRAPH RenderState : public NodeCachedReferenceCount {
+class EXPCL_PANDA_PGRAPH RenderState FINAL : public NodeCachedReferenceCount {
 protected:
 protected:
   RenderState();
   RenderState();
 
 

+ 6 - 6
panda/src/pgui/pgMouseWatcherParameter.h

@@ -25,11 +25,11 @@
 // Description : This specialization on MouseWatcherParameter allows
 // Description : This specialization on MouseWatcherParameter allows
 //               us to tag on additional elements to events for the
 //               us to tag on additional elements to events for the
 //               gui system, and also inherits from
 //               gui system, and also inherits from
-//               TypedWritableReferenceCount so we can attach this thing to an
-//               event.
+//               TypedReferenceCount so we can attach this thing to
+//               an event.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA_PGUI PGMouseWatcherParameter : public TypedWritableReferenceCount, public MouseWatcherParameter {
-  // For now, this must inherit from TypedWritableReferenceCount on
+class EXPCL_PANDA_PGUI PGMouseWatcherParameter : public TypedReferenceCount, public MouseWatcherParameter {
+  // For now, this must inherit from TypedReferenceCount on
   // the left, because MSVC++ wants to make that base class be the one
   // the left, because MSVC++ wants to make that base class be the one
   // at the front of the structure, not MouseWatcherParameter for some
   // at the front of the structure, not MouseWatcherParameter for some
   // reason, and interrogate assumes that whichever base class is on
   // reason, and interrogate assumes that whichever base class is on
@@ -48,9 +48,9 @@ public:
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    TypedWritableReferenceCount::init_type();
+    TypedReferenceCount::init_type();
     register_type(_type_handle, "PGMouseWatcherParameter",
     register_type(_type_handle, "PGMouseWatcherParameter",
-                  TypedWritableReferenceCount::get_class_type());
+                  TypedReferenceCount::get_class_type());
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 2 - 1
panda/src/putil/config_util.cxx

@@ -34,6 +34,7 @@
 #include "factoryParam.h"
 #include "factoryParam.h"
 #include "namable.h"
 #include "namable.h"
 #include "nodeCachedReferenceCount.h"
 #include "nodeCachedReferenceCount.h"
+#include "parameter.h"
 #include "paramValue.h"
 #include "paramValue.h"
 #include "pythonCallbackObject.h"
 #include "pythonCallbackObject.h"
 #include "referenceCount.h"
 #include "referenceCount.h"
@@ -199,12 +200,12 @@ init_libputil() {
   FactoryParam::init_type();
   FactoryParam::init_type();
   Namable::init_type();
   Namable::init_type();
   NodeCachedReferenceCount::init_type();
   NodeCachedReferenceCount::init_type();
+  Parameter::init_type();
   ParamMatrix3d::init_type("ParamMatrix3d");
   ParamMatrix3d::init_type("ParamMatrix3d");
   ParamMatrix3f::init_type("ParamMatrix3f");
   ParamMatrix3f::init_type("ParamMatrix3f");
   ParamMatrix4d::init_type("ParamMatrix4d");
   ParamMatrix4d::init_type("ParamMatrix4d");
   ParamMatrix4f::init_type("ParamMatrix4f");
   ParamMatrix4f::init_type("ParamMatrix4f");
   ParamString::init_type("ParamString");
   ParamString::init_type("ParamString");
-  ParamTypedRefCount::init_type();
   ParamValueBase::init_type();
   ParamValueBase::init_type();
   ParamVecBase2d::init_type("ParamVecBase2d");
   ParamVecBase2d::init_type("ParamVecBase2d");
   ParamVecBase2f::init_type("ParamVecBase2f");
   ParamVecBase2f::init_type("ParamVecBase2f");

+ 1 - 0
panda/src/putil/p3putil_composite2.cxx

@@ -12,6 +12,7 @@
 #include "mouseData.cxx"
 #include "mouseData.cxx"
 #include "nameUniquifier.cxx"
 #include "nameUniquifier.cxx"
 #include "nodeCachedReferenceCount.cxx"
 #include "nodeCachedReferenceCount.cxx"
+#include "parameter.cxx"
 #include "paramValue.cxx"
 #include "paramValue.cxx"
 #include "pbitops.cxx"
 #include "pbitops.cxx"
 #include "pta_ushort.cxx"
 #include "pta_ushort.cxx"

+ 299 - 28
panda/src/putil/paramValue.I

@@ -19,7 +19,7 @@ TypeHandle ParamValue<Type>::_type_handle;
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ParamValueBase::Constructor
 //     Function: ParamValueBase::Constructor
 //       Access: Public
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE ParamValueBase::
 INLINE ParamValueBase::
 ParamValueBase() {
 ParamValueBase() {
@@ -36,39 +36,48 @@ get_value_type() const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: ParamTypedRefCount::Constructor
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE ParamTypedRefCount::
-ParamTypedRefCount(const TypedReferenceCount *value) :
-  _value((TypedReferenceCount *)value)
-{
+//     Function: ParamValueBase::extract_data
+//       Access: Public, Virtual
+//  Description: This is a convenience function for the graphics
+//               backend.  It can be used for numeric types to
+//               convert this value to an array of integers matching
+//               the given description.  If this is not possible,
+//               returns false (after which the array may or may not
+//               contain meaningful data).
+////////////////////////////////////////////////////////////////////
+INLINE bool ParamValueBase::
+extract_data(int *data, int width, size_t count) const {
+  return false;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: ParamTypedRefCount::get_value_type
-//       Access: Published
-//  Description: Retrieves the type of the value stored in the
-//               parameter.
-////////////////////////////////////////////////////////////////////
-INLINE TypeHandle ParamTypedRefCount::
-get_value_type() const {
-  if (_value == NULL) {
-    return TypeHandle::none();
-  } else {
-    return _value->get_type();
-  }
+//     Function: ParamValueBase::extract_data
+//       Access: Public, Virtual
+//  Description: This is a convenience function for the graphics
+//               backend.  It can be used for numeric types to
+//               convert this value to an array of floats matching
+//               the given description.  If this is not possible,
+//               returns false (after which the array may or may not
+//               contain meaningful data).
+////////////////////////////////////////////////////////////////////
+INLINE bool ParamValueBase::
+extract_data(float *data, int width, size_t count) const {
+  return false;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: ParamTypedRefCount::get_value
-//       Access: Published
-//  Description: Retrieves the value stored in the parameter.
-////////////////////////////////////////////////////////////////////
-INLINE TypedReferenceCount *ParamTypedRefCount::
-get_value() const {
-  return _value;
+//     Function: ParamValueBase::extract_data
+//       Access: Public, Virtual
+//  Description: This is a convenience function for the graphics
+//               backend.  It can be used for numeric types to
+//               convert this value to an array of doubles matching
+//               the given description.  If this is not possible,
+//               returns false (after which the array may or may not
+//               contain meaningful data).
+////////////////////////////////////////////////////////////////////
+INLINE bool ParamValueBase::
+extract_data(double *data, int width, size_t count) const {
+  return false;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -148,6 +157,54 @@ output(ostream &out) const {
   out << _value;
   out << _value;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ParamValue::extract_data
+//       Access: Public, Virtual
+//  Description: This is a convenience function for the graphics
+//               backend.  It can be used for numeric types to
+//               convert this value to an array of integers matching
+//               the given description.  If this is not possible,
+//               returns false (after which the array may or may not
+//               contain meaningful data).
+////////////////////////////////////////////////////////////////////
+template<class Type>
+INLINE bool ParamValue<Type>::
+extract_data(int *data, int width, size_t count) const {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ParamValue::extract_data
+//       Access: Public, Virtual
+//  Description: This is a convenience function for the graphics
+//               backend.  It can be used for numeric types to
+//               convert this value to an array of floats matching
+//               the given description.  If this is not possible,
+//               returns false (after which the array may or may not
+//               contain meaningful data).
+////////////////////////////////////////////////////////////////////
+template<class Type>
+INLINE bool ParamValue<Type>::
+extract_data(float *data, int width, size_t count) const {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ParamValue::extract_data
+//       Access: Public, Virtual
+//  Description: This is a convenience function for the graphics
+//               backend.  It can be used for numeric types to
+//               convert this value to an array of doubles matching
+//               the given description.  If this is not possible,
+//               returns false (after which the array may or may not
+//               contain meaningful data).
+////////////////////////////////////////////////////////////////////
+template<class Type>
+INLINE bool ParamValue<Type>::
+extract_data(double *data, int width, size_t count) const {
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ParamValue::register_with_read_factory
 //     Function: ParamValue::register_with_read_factory
 //       Access: Public, Static
 //       Access: Public, Static
@@ -207,3 +264,217 @@ fillin(DatagramIterator &scan, BamReader *manager) {
   TypedWritable::fillin(scan, manager);
   TypedWritable::fillin(scan, manager);
   generic_read_datagram(_value, scan);
   generic_read_datagram(_value, scan);
 }
 }
+
+// Now follow specializations of extract_data for the various types.
+#ifndef CPPPARSER
+template<>
+INLINE bool ParamValue<string>::
+extract_data(int *data, int width, size_t count) const {
+  if (width != 1) {
+    return false;
+  }
+
+  size_t maxnum = min(_value.size(), count);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = _value[i];
+  }
+  return (count <= _value.size());
+}
+
+template<>
+INLINE bool ParamValue<wstring>::
+extract_data(int *data, int width, size_t count) const {
+  if (width != 1) {
+    return false;
+  }
+
+  size_t maxnum = min(_value.size(), count);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = _value[i];
+  }
+  return (count <= _value.size());
+}
+
+template<>
+INLINE bool ParamValue<LVecBase2i>::
+extract_data(int *data, int width, size_t count) const {
+  memcpy((void *)data, (const void *)_value.get_data(), min(width, 2) * sizeof(int));
+  return (count == 1) && (width <= 2);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase3i>::
+extract_data(int *data, int width, size_t count) const {
+  memcpy((void *)data, (const void *)_value.get_data(), min(width, 3) * sizeof(int));
+  return (count == 1) && (width <= 3);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase4i>::
+extract_data(int *data, int width, size_t count) const {
+  memcpy((void *)data, (const void *)_value.get_data(), min(width, 4) * sizeof(int));
+  return (count == 1) && (width <= 4);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase2d>::
+extract_data(float *data, int width, size_t count) const {
+  size_t maxnum = min(width, 2);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = (float)_value[i];
+  }
+  return (count == 1) && (width <= 2);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase2f>::
+extract_data(float *data, int width, size_t count) const {
+  memcpy((void *)data, (const void *)_value.get_data(), min(width, 2) * sizeof(float));
+  return (count == 1) && (width <= 2);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase2i>::
+extract_data(float *data, int width, size_t count) const {
+  size_t maxnum = min(width, 2);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = (float)_value[i];
+  }
+  return (count == 1) && (width <= 2);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase3d>::
+extract_data(float *data, int width, size_t count) const {
+  size_t maxnum = min(width, 3);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = (float)_value[i];
+  }
+  return (count == 1) && (width <= 3);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase3f>::
+extract_data(float *data, int width, size_t count) const {
+  memcpy((void *)data, (const void *)_value.get_data(), min(width, 3) * sizeof(float));
+  return (count == 1) && (width <= 3);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase3i>::
+extract_data(float *data, int width, size_t count) const {
+  size_t maxnum = min(width, 3);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = (float)_value[i];
+  }
+  return (count == 1) && (width <= 3);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase4d>::
+extract_data(float *data, int width, size_t count) const {
+  size_t maxnum = min(width, 4);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = (float)_value[i];
+  }
+  return (count == 1) && (width <= 4);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase4f>::
+extract_data(float *data, int width, size_t count) const {
+  memcpy((void *)data, (const void *)_value.get_data(), min(width, 4) * sizeof(float));
+  return (count == 1) && (width <= 4);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase4i>::
+extract_data(float *data, int width, size_t count) const {
+  size_t maxnum = min(width, 4);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = (float)_value[i];
+  }
+  return (count == 1) && (width <= 4);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase2d>::
+extract_data(double *data, int width, size_t count) const {
+  memcpy((void *)data, (const void *)_value.get_data(), min(width, 2) * sizeof(double));
+  return (count == 1) && (width <= 2);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase2f>::
+extract_data(double *data, int width, size_t count) const {
+  size_t maxnum = min(width, 2);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = (double)_value[i];
+  }
+  return (count == 1) && (width <= 2);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase2i>::
+extract_data(double *data, int width, size_t count) const {
+  size_t maxnum = min(width, 2);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = (double)_value[i];
+  }
+  return (count == 1) && (width <= 2);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase3d>::
+extract_data(double *data, int width, size_t count) const {
+  memcpy((void *)data, (const void *)_value.get_data(), min(width, 3) * sizeof(double));
+  return (count == 1) && (width <= 3);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase3f>::
+extract_data(double *data, int width, size_t count) const {
+  size_t maxnum = min(width, 3);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = (double)_value[i];
+  }
+  return (count == 1) && (width <= 3);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase3i>::
+extract_data(double *data, int width, size_t count) const {
+  size_t maxnum = min(width, 3);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = (double)_value[i];
+  }
+  return (count == 1) && (width <= 3);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase4d>::
+extract_data(double *data, int width, size_t count) const {
+  memcpy((void *)data, (const void *)_value.get_data(), min(width, 4) * sizeof(double));
+  return (count == 1) && (width <= 4);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase4f>::
+extract_data(double *data, int width, size_t count) const {
+  size_t maxnum = min(width, 4);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = (double)_value[i];
+  }
+  return (count == 1) && (width <= 4);
+}
+
+template<>
+INLINE bool ParamValue<LVecBase4i>::
+extract_data(double *data, int width, size_t count) const {
+  size_t maxnum = min(width, 4);
+  for (int i = 0; i < maxnum; ++i) {
+    data[i] = (double)_value[i];
+  }
+  return (count == 1) && (width <= 4);
+}
+#endif  // CPPPARSER

+ 0 - 25
panda/src/putil/paramValue.cxx

@@ -21,7 +21,6 @@
 #endif
 #endif
 
 
 TypeHandle ParamValueBase::_type_handle;
 TypeHandle ParamValueBase::_type_handle;
-TypeHandle ParamTypedRefCount::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ParamValueBase::Destructor
 //     Function: ParamValueBase::Destructor
@@ -31,27 +30,3 @@ TypeHandle ParamTypedRefCount::_type_handle;
 ParamValueBase::
 ParamValueBase::
 ~ParamValueBase() {
 ~ParamValueBase() {
 }
 }
-
-////////////////////////////////////////////////////////////////////
-//     Function: ParamTypedRefCount::Destructor
-//       Access: Published, Virtual
-//  Description:
-////////////////////////////////////////////////////////////////////
-ParamTypedRefCount::
-~ParamTypedRefCount() {
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ParamTypedRefCount::output
-//       Access: Published, Virtual
-//  Description:
-////////////////////////////////////////////////////////////////////
-void ParamTypedRefCount::
-output(ostream &out) const {
-  if (_value == (TypedReferenceCount *)NULL) {
-    out << "(empty)";
-
-  } else {
-    out << _value->get_type();
-  }
-}

+ 11 - 38
panda/src/putil/paramValue.h

@@ -40,6 +40,11 @@ PUBLISHED:
   INLINE virtual TypeHandle get_value_type() const;
   INLINE virtual TypeHandle get_value_type() const;
   virtual void output(ostream &out) const=0;
   virtual void output(ostream &out) const=0;
 
 
+public:
+  INLINE virtual bool extract_data(int *data, int width, size_t count) const;
+  INLINE virtual bool extract_data(float *data, int width, size_t count) const;
+  INLINE virtual bool extract_data(double *data, int width, size_t count) const;
+
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();
@@ -58,43 +63,6 @@ private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;
 };
 };
 
 
-////////////////////////////////////////////////////////////////////
-//       Class : ParamTypedRefCount
-// Description : A class object for storing specifically objects of
-//               type TypedReferenceCount, which is different than
-//               TypedWritableReferenceCount.
-////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA_PUTIL ParamTypedRefCount : public ParamValueBase {
-PUBLISHED:
-  INLINE ParamTypedRefCount(const TypedReferenceCount *value);
-  virtual ~ParamTypedRefCount();
-
-  INLINE virtual TypeHandle get_value_type() const;
-  INLINE TypedReferenceCount *get_value() const;
-
-  virtual void output(ostream &out) const;
-
-private:
-  PT(TypedReferenceCount) _value;
-
-public:
-  virtual TypeHandle get_type() const {
-    return get_class_type();
-  }
-  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
-  static TypeHandle get_class_type() {
-    return _type_handle;
-  }
-  static void init_type() {
-    ParamValueBase::init_type();
-    register_type(_type_handle, "ParamTypedRefCount",
-                  ParamValueBase::get_class_type());
-  }
-
-private:
-  static TypeHandle _type_handle;
-};
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : ParamValue
 //       Class : ParamValue
 // Description : A handy class object for storing simple values (like
 // Description : A handy class object for storing simple values (like
@@ -106,7 +74,7 @@ private:
 //               passed along inside an EventParameter or ShaderInput.
 //               passed along inside an EventParameter or ShaderInput.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class Type>
 template<class Type>
-class ParamValue : public ParamValueBase {
+class ParamValue FINAL : public ParamValueBase {
 protected:
 protected:
   INLINE ParamValue();
   INLINE ParamValue();
 
 
@@ -120,6 +88,11 @@ PUBLISHED:
 
 
   INLINE virtual void output(ostream &out) const;
   INLINE virtual void output(ostream &out) const;
 
 
+public:
+  INLINE virtual bool extract_data(int *data, int width, size_t count) const;
+  INLINE virtual bool extract_data(float *data, int width, size_t count) const;
+  INLINE virtual bool extract_data(double *data, int width, size_t count) const;
+
 private:
 private:
   Type _value;
   Type _value;
 
 

+ 980 - 0
panda/src/putil/parameter.I

@@ -0,0 +1,980 @@
+// Filename: parameter.I
+// Created by:  drose (08Feb99)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Default constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores nothing: the
+//               "empty" parameter, ie. a NULL pointer.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter() {
+  // The empty parameter is a NULL pointer.
+  _v._packed._type = T_pointer;
+
+#if NATIVE_WORDSIZE == 64
+  _v._ptr = NULL;
+#else
+  _v._packed._ptr = NULL;
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Pointer constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a pointer to
+//               any kind of TypedWritableReferenceCount object.  This
+//               is the most general constructor.
+//
+//               This accepts a const pointer, even though it stores
+//               (and eventually returns) a non-const pointer.  This
+//               is just the simplest way to allow both const and
+//               non-const pointers to be stored, but it does lose the
+//               constness.  Be careful.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const TypedWritableReferenceCount *ptr) {
+  do_set_ptr((TypedWritableReferenceCount *)ptr);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Pointer constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a pointer to
+//               a TypedReferenceCount object.  Note that a
+//               TypedReferenceCount is not the same kind of pointer
+//               as a TypedWritableReferenceCount, hence we require
+//               both constructors.
+//
+//               This accepts a const pointer, even though it stores
+//               (and eventually returns) a non-const pointer.  This
+//               is just the simplest way to allow both const and
+//               non-const pointers to be stored, but it does lose the
+//               constness.  Be careful.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const TypedReferenceCount *ptr) {
+  do_set_ptr((TypedReferenceCount *)ptr);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Integer constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores an integer
+//               value.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(int value) {
+  _v._packed._int = value;
+  _v._packed._type = T_int;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Float constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a
+//               floating-point value.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(float value) {
+  _v._packed._float = value;
+  _v._packed._type = T_float;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Double constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a
+//               double-precision floating-point value.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(double value) {
+  do_set_double(value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Vector constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a vector.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LVecBase2i &value) {
+  do_set_ptr(new ParamVecBase2i(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Vector constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a vector.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LVecBase2f &value) {
+  do_set_ptr(new ParamVecBase2f(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Vector constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a vector.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LVecBase2d &value) {
+  do_set_ptr(new ParamVecBase2d(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Vector constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a vector.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LVecBase3i &value) {
+  do_set_ptr(new ParamVecBase3i(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Vector constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a vector.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LVecBase3f &value) {
+  do_set_ptr(new ParamVecBase3f(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Vector constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a vector.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LVecBase3d &value) {
+  do_set_ptr(new ParamVecBase3d(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Vector constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a vector.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LVecBase4i &value) {
+  do_set_ptr(new ParamVecBase4i(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Vector constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a vector.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LVecBase4f &value) {
+  do_set_ptr(new ParamVecBase4f(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Vector constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a vector.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LVecBase4d &value) {
+  do_set_ptr(new ParamVecBase4d(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Vector constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a point.  Actually
+//               stores it as an LVecBase4 with the w coordinate
+//               set to 1.0.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LPoint3f &value) {
+  do_set_ptr(new ParamVecBase4f(LVecBase4f(value)));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Vector constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a point.  Actually
+//               stores it as an LVecBase4 with the w coordinate
+//               set to 1.0.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LPoint3d &value) {
+  do_set_ptr(new ParamVecBase4d(LVecBase4d(value)));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Vector constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a vector.  Actually
+//               stores it as an LVecBase4 with the w coordinate
+//               set to 0.0.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LVector3f &value) {
+  do_set_ptr(new ParamVecBase4f(LVecBase4f(value)));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Vector constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a vector.  Actually
+//               stores it as an LVecBase4 with the w coordinate
+//               set to 0.0.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LVector3d &value) {
+  do_set_ptr(new ParamVecBase4d(LVecBase4d(value)));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Matrix constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a matrix.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LMatrix3f &value) {
+  do_set_ptr(new ParamMatrix3f(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Matrix constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a matrix.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LMatrix3d &value) {
+  do_set_ptr(new ParamMatrix3d(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Matrix constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a matrix.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LMatrix4f &value) {
+  do_set_ptr(new ParamMatrix4f(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Matrix constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a matrix.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const LMatrix4d &value) {
+  do_set_ptr(new ParamMatrix4d(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::String constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a string value.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const string &value) {
+  do_set_ptr(new ParamString(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Wstring constructor
+//       Access: Published
+//  Description: Defines a Parameter that stores a wstring value.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const wstring &value) {
+  do_set_ptr(new ParamWstring(value));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Copy constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(const Parameter &other) :
+  _v(other._v) {
+
+  if (do_get_type() == T_pointer &&
+      do_get_ptr() != (ReferenceCount *)NULL) {
+    do_get_ptr()->ref();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Copy assignment operator
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE Parameter &Parameter::
+operator = (const Parameter &other) {
+  if (do_get_type() == T_pointer &&
+      do_get_ptr() != (ReferenceCount *)NULL) {
+    if ((other.do_get_type()) == T_pointer && do_get_ptr() == other.do_get_ptr()){
+      // The new pointer is the same as the old, so don't do anything.
+      return *this;
+    }
+    unref_delete(do_get_ptr());
+  }
+
+  _v = other._v;
+
+  if (do_get_type() == T_pointer &&
+      do_get_ptr() != (ReferenceCount *)NULL) {
+    do_get_ptr()->ref();
+  }
+
+  return *this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+~Parameter() {
+  if (do_get_type() == T_pointer &&
+      do_get_ptr() != (ReferenceCount *)NULL) {
+    // Dereference the assigned pointer, if we had one.
+    unref_delete(do_get_ptr());
+  }
+}
+
+#ifdef USE_MOVE_SEMANTICS
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Move constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::
+Parameter(Parameter &&from) :
+  _v(from._v) {
+
+  // Clear the other pointer.
+  from._v._packed._type = T_pointer;
+
+#if NATIVE_WORDSIZE == 64
+  from._v._ptr = NULL;
+#else
+  from._v._packed._ptr = NULL;
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::Move assignment operator
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE Parameter &Parameter::
+operator = (Parameter &&from) {
+  if (do_get_type() == T_pointer &&
+      do_get_ptr() != (ReferenceCount *)NULL) {
+    // If we had a pointer, dereference it.
+    unref_delete(do_get_ptr());
+  }
+
+  _v = from._v;
+  from._v._packed._type = T_pointer;
+
+#if NATIVE_WORDSIZE == 64
+  from._v._ptr = NULL;
+#else
+  from._v._packed._ptr = NULL;
+#endif
+
+  return *this;
+}
+#endif  // USE_MOVE_SEMANTICS
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::clear
+//       Access: Published
+//  Description: Clears the parameter (equivalent to setting it to
+//               a NULL/None pointer).  is_empty() will return true.
+////////////////////////////////////////////////////////////////////
+INLINE void Parameter::
+clear() {
+  if (do_get_type() == T_pointer &&
+      do_get_ptr() != (ReferenceCount *)NULL) {
+    unref_delete(do_get_ptr());
+  }
+
+  do_set_ptr((ReferenceCount *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::is_empty
+//       Access: Published
+//  Description: Returns true if the Parameter is the empty
+//               parameter, storing nothing, or false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool Parameter::
+is_empty() const {
+  return (do_get_type() == T_pointer &&
+          do_get_ptr() == (ReferenceCount *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::swap
+//       Access: Published
+//  Description: Swaps the value of this parameter with the other.
+////////////////////////////////////////////////////////////////////
+INLINE void Parameter::
+swap(Parameter &other) NOEXCEPT {
+  Value temp = other._v;
+  other._v = _v;
+  _v = temp;
+}
+
+#ifndef CPPPARSER
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::set_value
+//       Access: Published
+//  Description: Changes the value associated with this Parameter.
+////////////////////////////////////////////////////////////////////
+INLINE void Parameter::
+set_value(const TypedWritableReferenceCount *value) {
+  if (do_get_type() == T_pointer &&
+      do_get_ptr() != (ReferenceCount *)NULL) {
+    if (do_get_ptr() == value){
+      return;
+    }
+    unref_delete(do_get_ptr());
+  }
+
+  do_set_ptr((TypedWritableReferenceCount*) value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::set_value
+//       Access: Published
+//  Description: Changes the value associated with this Parameter.
+////////////////////////////////////////////////////////////////////
+INLINE void Parameter::
+set_value(const TypedReferenceCount *value) {
+  if (do_get_type() == T_pointer &&
+      do_get_ptr() != (ReferenceCount *)NULL) {
+    if (do_get_ptr() == value){
+      return;
+    }
+    unref_delete(do_get_ptr());
+  }
+
+  do_set_ptr((TypedReferenceCount*) value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::set_value
+//       Access: Published
+//  Description: Changes the value associated with this Parameter.
+////////////////////////////////////////////////////////////////////
+INLINE void Parameter::
+set_value(int value) {
+  if (do_get_type() == T_pointer &&
+      do_get_ptr() != (ReferenceCount *)NULL) {
+    unref_delete(do_get_ptr());
+  }
+
+  _v._packed._type = T_int;
+  _v._packed._int = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::set_value
+//       Access: Published
+//  Description: Changes the value associated with this Parameter.
+////////////////////////////////////////////////////////////////////
+INLINE void Parameter::
+set_value(bool value) {
+  if (do_get_type() == T_pointer &&
+      do_get_ptr() != (ReferenceCount *)NULL) {
+    unref_delete(do_get_ptr());
+  }
+
+  _v._packed._type = T_bool;
+  _v._packed._bool = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::set_value
+//       Access: Published
+//  Description: Changes the value associated with this Parameter.
+////////////////////////////////////////////////////////////////////
+INLINE void Parameter::
+set_value(float value) {
+  if (do_get_type() == T_pointer &&
+      do_get_ptr() != (ReferenceCount *)NULL) {
+    unref_delete(do_get_ptr());
+  }
+
+  _v._packed._type = T_float;
+  _v._packed._float = value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::set_value
+//       Access: Published
+//  Description: Changes the value associated with this Parameter.
+////////////////////////////////////////////////////////////////////
+INLINE void Parameter::
+set_value(double value) {
+  if (do_get_type() == T_pointer &&
+      do_get_ptr() != (ReferenceCount *)NULL) {
+    unref_delete(do_get_ptr());
+  }
+
+  do_set_double(value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::set_value
+//       Access: Published
+//  Description: Changes the value associated with this Parameter.
+////////////////////////////////////////////////////////////////////
+INLINE void Parameter::
+set_value(const LVecBase3f &value) {
+  set_value(new ParamVecBase3f(value));
+}
+#endif  // CPPPARSER
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::get_value_type
+//       Access: Published
+//  Description: Returns the TypeHandle corresponding to the type
+//               of this parameter's value.
+////////////////////////////////////////////////////////////////////
+INLINE TypeHandle Parameter::
+get_value_type() const {
+  switch (do_get_type()) {
+  case T_pointer:
+    {
+      TypedObject *obj = get_typed_object();
+      if (obj != (TypedObject *)NULL) {
+        return obj->get_type();
+      }
+    }
+    break;
+
+  case T_int:
+    return int_type_handle;
+
+  case T_bool:
+    return bool_type_handle;
+
+  case T_float:
+    return float_type_handle;
+
+  default:
+    return double_type_handle;
+  }
+
+  return TypeHandle::none();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::is_int
+//       Access: Published
+//  Description: Returns true if the Parameter stores an integer
+//               value, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool Parameter::
+is_int() const {
+  return (do_get_type() == T_int);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::get_int_value
+//       Access: Published
+//  Description: Retrieves the value stored in the Parameter.  It
+//               is only valid to call this if is_int() has already
+//               returned true.
+////////////////////////////////////////////////////////////////////
+INLINE int Parameter::
+get_int_value() const {
+  nassertr(is_int(), 0);
+  return _v._packed._int;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::is_float
+//       Access: Published
+//  Description: Returns true if the Parameter stores a single
+//               floating-point value, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool Parameter::
+is_float() const {
+  return (do_get_type() == T_float);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::get_float_value
+//       Access: Published
+//  Description: Retrieves the value stored in the Parameter.  If it
+//               is of a different numeric type, it will be converted.
+//               It is an error to call this on non-numeric parameters.
+////////////////////////////////////////////////////////////////////
+INLINE float Parameter::
+get_float_value() const {
+  switch (do_get_type()) {
+  case T_float:
+    return _v._packed._float;
+
+  case T_int:
+    return (float) _v._packed._int;
+
+  case T_bool:
+    return (float) (int) _v._packed._bool;
+
+  case T_pointer:
+    nassertr(do_get_type() != T_pointer, do_get_double());
+    // Fall through - do_get_double() will produce NaN
+
+  default:
+    return (float) do_get_double();
+  }
+  return 0.0f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::is_double
+//       Access: Published
+//  Description: Returns true if the Parameter stores a single
+//               double-precision float, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool Parameter::
+is_double() const {
+  return (do_get_type() > T_MAX);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::get_double_value
+//       Access: Published
+//  Description: Retrieves the value stored in the Parameter.  If it
+//               is of a different numeric type, it will be converted.
+//               It is an error to call this on non-numeric parameters.
+////////////////////////////////////////////////////////////////////
+INLINE double Parameter::
+get_double_value() const {
+  switch (do_get_type()) {
+  case T_float:
+    return (double) _v._packed._float;
+
+  case T_int:
+    return (double) _v._packed._int;
+
+  case T_bool:
+    return (double) (int) _v._packed._bool;
+
+  case T_pointer:
+    nassertr(do_get_type() != T_pointer, do_get_double());
+    // Fall through - do_get_double() will produce NaN
+
+  default:
+    return do_get_double();
+  }
+  return 0.0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::is_string
+//       Access: Published
+//  Description: Returns true if the Parameter stores a string
+//               value, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool Parameter::
+is_string() const {
+  if (do_get_type() != T_pointer || do_get_ptr() == (ReferenceCount *)NULL){
+    return false;
+  }
+  return (get_typed_object()->get_type() == ParamString::get_class_type());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::get_string_value
+//       Access: Published
+//  Description: Retrieves the value stored in the Parameter.  It
+//               is only valid to call this if is_string() has already
+//               returned true.
+////////////////////////////////////////////////////////////////////
+INLINE const string &Parameter::
+get_string_value() const {
+  static const string empty_string;
+  nassertr(is_string(), empty_string);
+  // We can't use DCAST, because ParamValue::init_type() breaks
+  // convention and takes a parameter.  But the above assertion should
+  // protect us.
+  return ((const ParamString *)do_get_ptr())->get_value();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::is_wstring
+//       Access: Published
+//  Description: Returns true if the Parameter stores a wstring
+//               value, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool Parameter::
+is_wstring() const {
+  if (do_get_type() != T_pointer || do_get_ptr() == (ReferenceCount *)NULL){
+    return false;
+  }
+  return (get_typed_object()->get_type() == ParamWstring::get_class_type());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::get_wstring_value
+//       Access: Published
+//  Description: Retrieves the value stored in the Parameter.  It
+//               is only valid to call this if is_wstring() has already
+//               returned true.
+////////////////////////////////////////////////////////////////////
+INLINE const wstring &Parameter::
+get_wstring_value() const {
+  static const wstring empty_wstring;
+  nassertr(is_wstring(), empty_wstring);
+  return ((const ParamWstring *)do_get_ptr())->get_value();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::is_typed_ref_count
+//       Access: Published
+//  Description: Returns true if the Parameter stores a
+//               TypedReferenceCount pointer, false otherwise.  Note
+//               that TypedReferenceCount is not a base class of
+//               TypedWritableReferenceCount, hence the need for
+//               this separate call.
+////////////////////////////////////////////////////////////////////
+INLINE bool Parameter::
+is_typed_ref_count() const {
+  if (do_get_type() != T_pointer || do_get_ptr() == (ReferenceCount *)NULL){
+    return false;
+  }
+  return get_typed_object()->is_of_type(TypedReferenceCount::get_class_type());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::get_typed_ref_count_value
+//       Access: Published
+//  Description: Retrieves the value stored in the Parameter.  It
+//               is only valid to call this if is_typed_ref_count()
+//               has already returned true.
+////////////////////////////////////////////////////////////////////
+INLINE TypedReferenceCount *Parameter::
+get_typed_ref_count_value() const {
+  return DCAST(TypedReferenceCount, get_typed_object());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::get_typed_object
+//       Access: Published
+//  Description: Retrieves the pointer stored in the Parameter as a
+//               TypedObject pointer.  It is only valid to call this
+//               if is_pointer() has already returned true.
+//               If this is the empty parameter, returns NULL without
+//               raising an error.
+////////////////////////////////////////////////////////////////////
+INLINE TypedObject *Parameter::
+get_typed_object() const {
+  nassertr(do_get_type() == T_pointer, NULL);
+  ReferenceCount *ptr = do_get_ptr();
+  if (ptr == (ReferenceCount *)NULL) {
+    // Empty parameter.
+    return (TypedObject *)NULL;
+  }
+  TypedObject *obj = ptr->as_typed_object();
+  nassertr(obj != NULL, NULL);
+  return obj;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::write_datagram
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void Parameter::
+write_datagram(BamWriter *manager, Datagram &destination) const {
+  switch (do_get_type()) {
+  case T_pointer:
+    {
+      TypedWritable *writable = NULL;
+      DCAST_INTO_V(writable, get_typed_object());
+      destination.add_uint8(0);
+      manager->write_pointer(destination, writable);
+      break;
+    }
+  case T_int:
+    destination.add_uint8(1);
+    destination.add_int32(_v._packed._int);
+    break;
+
+  case T_bool:
+    destination.add_uint8(2);
+    destination.add_bool(_v._packed._bool);
+    break;
+
+  case T_float:
+    destination.add_uint8(3);
+    destination.add_float32(_v._packed._float);
+    break;
+
+  default:
+    destination.add_uint8(4);
+    destination.add_float64(do_get_double());
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::read_datagram
+//       Access: Published
+//  Description: It is up to the caller to make sure to also call
+//               complete_pointers.
+////////////////////////////////////////////////////////////////////
+INLINE void Parameter::
+read_datagram(DatagramIterator &source, BamReader *manager) {
+  memset(&_v, 0, sizeof(_v));
+
+  unsigned char type = source.get_uint8();
+
+  switch (type) {
+  case 0:
+    clear();
+    manager->read_pointer(source);
+    break;
+
+  case 1:
+    set_value(source.get_int32());
+    break;
+
+  case 2:
+    set_value(source.get_bool());
+    break;
+
+  case 3:
+    set_value(source.get_float32());
+    break;
+
+  case 4:
+    set_value(source.get_float64());
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::complete_pointers
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE int Parameter::
+complete_pointers(TypedWritable **plist, BamReader *manager) {
+  if (do_get_type() == T_pointer) {
+    do_set_ptr(DCAST(TypedWritableReferenceCount, plist[0]));
+    return 1;
+  }
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::do_get_double
+//       Access: Private
+//  Description: Returns the double value without type checking.
+//               Returns NaN if it is not a double.
+////////////////////////////////////////////////////////////////////
+INLINE double Parameter::
+do_get_double() const {
+  // We just have to flip the exponent space.
+  Value v = _v;
+  v._packed._type ^= T_MASK;
+  return v._double;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::do_set_double
+//       Access: Private
+//  Description: Sets the double value without regard for what is
+//               currently being stored.
+////////////////////////////////////////////////////////////////////
+INLINE void Parameter::
+do_set_double(double value) {
+  _v._double = value;
+  _v._packed._type ^= T_MASK;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::do_get_ptr
+//       Access: Private
+//  Description: Returns the pointer value without type checking.
+////////////////////////////////////////////////////////////////////
+INLINE ReferenceCount *Parameter::
+do_get_ptr() const {
+#if NATIVE_WORDSIZE == 64
+  return _v._ptr;
+#else
+  return _v._packed._ptr;
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::do_set_ptr
+//       Access: Private
+//  Description: Changes the pointer value.  Warning: does not
+//               decref the previous value, if any.
+////////////////////////////////////////////////////////////////////
+INLINE void Parameter::
+do_set_ptr(ReferenceCount *ptr) {
+  if (ptr != (ReferenceCount *)NULL) {
+    ptr->ref();
+  }
+
+  _v._packed._type = T_pointer;
+
+#if NATIVE_WORDSIZE == 64
+  _v._ptr = ptr;
+#else
+  _v._packed._ptr = ptr;
+#endif
+
+  if (do_get_type() != 0) {
+    cerr << "do_set_ptr " << ptr << " -> " << _v._ptr << "\n";
+    cerr << _v._packed._type << "\n";
+  }
+
+  nassertv(do_get_type() == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::do_get_type
+//       Access: Private
+//  Description: Returns the type tag.
+////////////////////////////////////////////////////////////////////
+INLINE Parameter::Type Parameter::
+do_get_type() const {
+  return (Type)(_v._packed._type & T_MASK);
+}
+
+INLINE void
+swap(Parameter &one, Parameter &two) NOEXCEPT {
+  one.swap(two);
+}
+
+INLINE ostream &
+operator << (ostream &out, const Parameter &param) {
+  param.output(out);
+  return out;
+}

+ 285 - 0
panda/src/putil/parameter.cxx

@@ -0,0 +1,285 @@
+// Filename: parameter.cxx
+// Created by:  drose (08Feb99)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "parameter.h"
+#include "dcast.h"
+
+#include "py_panda.h"
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma implementation
+#endif
+
+#ifdef HAVE_PYTHON
+#ifndef CPPPARSER
+IMPORT_THIS struct Dtool_PyTypedObject Dtool_TypedObject;
+#endif
+#endif
+
+TypeHandle Parameter::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::set_value
+//       Access: Published
+//  Description: Changes the value associated with this Parameter.
+////////////////////////////////////////////////////////////////////
+void Parameter::
+set_value(PyObject *value) {
+  if (value == Py_None) {
+    clear();
+
+  } else if (DtoolCanThisBeAPandaInstance(value)) {
+    //
+
+  } else if (value == Py_True) {
+    set_value(true);
+
+  } else if (value == Py_False) {
+    set_value(false);
+
+  } else if (PyFloat_CheckExact(value)) {
+    set_value(PyFloat_AS_DOUBLE(value));
+
+#if PY_MAJOR_VERSION < 3
+  } else if (PyInt_CheckExact(value)) {
+    set_value((int) PyInt_AS_LONG(value));
+#endif
+
+  } else if (PyLong_CheckExact(value)) {
+    set_value((int) PyLong_AsLong(value));
+
+  } else {
+    nassertv(false);
+    // raise TypeError;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::get_value
+//       Access: Published
+//  Description: Returns the value associated with this Parameter.
+////////////////////////////////////////////////////////////////////
+PyObject *Parameter::
+get_value() const {
+  switch (do_get_type()) {
+  case T_pointer:
+    {
+      ReferenceCount *ptr = do_get_ptr();
+
+      if (ptr != (ReferenceCount *)NULL) {
+        ptr->ref();
+
+        TypedObject *obj = ptr->as_typed_object();
+        nassertr(obj != NULL, NULL);
+        //return DTool_CreatePyInstanceTyped(obj, true);
+        return DTool_CreatePyInstanceTyped((void *)obj, Dtool_TypedObject, true,
+                                           false, obj->get_type().get_index());
+      }
+      break;
+    }
+
+  case T_bool:
+    {
+      PyObject *value = _v._packed._bool ? Py_True : Py_False;
+      Py_INCREF(value);
+      return value;
+    }
+
+  case T_int:
+#if PY_MAJOR_VERSION >= 3
+    return PyLong_FromLong(_v._packed._int);
+#else
+    return PyInt_FromLong(_v._packed._int);
+#endif
+
+  case T_float:
+    return PyFloat_FromDouble(_v._packed._float);
+
+  default:
+    return PyFloat_FromDouble(do_get_double());
+  }
+
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::output
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+void Parameter::
+output(ostream &out) const {
+  switch (do_get_type()) {
+  case T_pointer:
+    {
+      TypedObject *obj = get_typed_object();
+
+      if (obj == (TypedObject *)NULL) {
+        out << "(empty)";
+
+      } else if (obj->is_of_type(ParamValueBase::get_class_type())) {
+        ((const ParamValueBase *)obj)->output(out);
+
+      } else {
+        out << obj->get_type();
+      }
+    }
+    break;
+
+  case T_int:
+    out << _v._packed._int;
+    break;
+
+  case T_bool:
+    out << (_v._packed._bool ? "true" : "false");
+    break;
+
+  case T_float:
+    out << _v._packed._float << "f";
+    break;
+
+  default:
+    out << do_get_double();
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::extract_data
+//       Access: Public, Virtual
+//  Description: This is a convenience function for the graphics
+//               backend.  It can be used for numeric types to
+//               convert this value to an array of ints matching
+//               the given description.  If this is not possible,
+//               returns false (after which the array may or may not
+//               contain meaningful data).
+////////////////////////////////////////////////////////////////////
+INLINE bool Parameter::
+extract_data(int *data, int width, size_t count) const {
+  nassertr(count > 0 && width > 0, false);
+
+  switch (do_get_type()) {
+  case T_pointer:
+    {
+      TypedObject *obj = get_typed_object();
+      if (obj != (TypedObject *)NULL && obj->is_of_type(ParamValueBase::get_class_type())) {
+        return ((const ParamValueBase *)obj)->extract_data(data, width, count);
+      }
+    }
+    return false;
+
+  case T_int:
+    data[0] = _v._packed._int;
+    return (width == 1 && count == 1);
+
+  case T_bool:
+    data[0] = (int) _v._packed._bool;
+    return (width == 1 && count == 1);
+
+  default:
+    return false;
+  }
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::extract_data
+//       Access: Public, Virtual
+//  Description: This is a convenience function for the graphics
+//               backend.  It can be used for numeric types to
+//               convert this value to an array of floats matching
+//               the given description.  If this is not possible,
+//               returns false (after which the array may or may not
+//               contain meaningful data).
+////////////////////////////////////////////////////////////////////
+INLINE bool Parameter::
+extract_data(float *data, int width, size_t count) const {
+  nassertr(count > 0 && width > 0, false);
+
+  switch (do_get_type()) {
+  case T_pointer:
+    {
+      TypedObject *obj = get_typed_object();
+      if (obj != (TypedObject *)NULL && obj->is_of_type(ParamValueBase::get_class_type())) {
+        return ((const ParamValueBase *)obj)->extract_data(data, width, count);
+      }
+    }
+    return false;
+
+  case T_int:
+    data[0] = (float) _v._packed._int;
+    return (width == 1 && count == 1);
+
+  case T_bool:
+    data[0] = (float) (int) _v._packed._bool;
+    return (width == 1 && count == 1);
+
+  case T_float:
+    data[0] = _v._packed._float;
+    return (width == 1 && count == 1);
+
+  default:
+    data[0] = (float) do_get_double();
+    return (width == 1 && count == 1);
+  }
+
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Parameter::extract_data
+//       Access: Public, Virtual
+//  Description: This is a convenience function for the graphics
+//               backend.  It can be used for numeric types to
+//               convert this value to an array of doubles matching
+//               the given description.  If this is not possible,
+//               returns false (after which the array may or may not
+//               contain meaningful data).
+////////////////////////////////////////////////////////////////////
+INLINE bool Parameter::
+extract_data(double *data, int width, size_t count) const {
+  nassertr(count > 0 && width > 0, false);
+
+  switch (do_get_type()) {
+  case T_pointer:
+    {
+      TypedObject *obj = get_typed_object();
+      if (obj != (TypedObject *)NULL && obj->is_of_type(ParamValueBase::get_class_type())) {
+        return ((const ParamValueBase *)obj)->extract_data(data, width, count);
+      }
+    }
+    return false;
+
+  case T_int:
+    data[0] = (double) _v._packed._int;
+    return (width == 1 && count == 1);
+
+  case T_bool:
+    data[0] = (double) (int) _v._packed._bool;
+    return (width == 1 && count == 1);
+
+  case T_float:
+    data[0] = (double) _v._packed._float;
+    return (width == 1 && count == 1);
+
+  default:
+    data[0] = do_get_double();
+    return (width == 1 && count == 1);
+  }
+
+  return false;
+}

+ 231 - 0
panda/src/putil/parameter.h

@@ -0,0 +1,231 @@
+// Filename: parameter.h
+// Created by:  drose (08Feb99)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef PARAMETER_H
+#define PARAMETER_H
+
+#include "pandabase.h"
+
+#include "typedef.h"
+#include "typedObject.h"
+#include "typedReferenceCount.h"
+#include "typedWritableReferenceCount.h"
+#include "paramValue.h"
+#include "pointerTo.h"
+#include "py_panda.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : Parameter
+// Description : A generic parameter object that may be used as a
+//               shader input or an event parameter.  Each parameter
+//               stores either a primitive type or a pointer to a
+//               TypedWritableReferenceCount or TypedReferenceCount
+//               object, which of course could be pretty much
+//               anything.
+//
+//               This class is optimized to be able to be passed
+//               around on the stack as it is only 8 bytes.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA_EVENT Parameter {
+PUBLISHED:
+  INLINE Parameter();
+  //EXTENSION(INLINE Parameter(PyObject *value));
+
+public:
+  INLINE Parameter(const TypedWritableReferenceCount *ptr);
+  INLINE Parameter(const TypedReferenceCount *ptr);
+  INLINE Parameter(int value);
+  INLINE Parameter(float value);
+  INLINE Parameter(double value);
+  INLINE Parameter(const LVecBase2i &value);
+  INLINE Parameter(const LVecBase2f &value);
+  INLINE Parameter(const LVecBase2d &value);
+  INLINE Parameter(const LVecBase3i &value);
+  INLINE Parameter(const LVecBase3f &value);
+  INLINE Parameter(const LVecBase3d &value);
+  INLINE Parameter(const LVecBase4i &value);
+  INLINE Parameter(const LVecBase4f &value);
+  INLINE Parameter(const LVecBase4d &value);
+  INLINE Parameter(const LPoint3f &value);
+  INLINE Parameter(const LPoint3d &value);
+  INLINE Parameter(const LVector3f &value);
+  INLINE Parameter(const LVector3d &value);
+  INLINE Parameter(const LMatrix3f &value);
+  INLINE Parameter(const LMatrix3d &value);
+  INLINE Parameter(const LMatrix4f &value);
+  INLINE Parameter(const LMatrix4d &value);
+  INLINE Parameter(const string &value);
+  INLINE Parameter(const wstring &value);
+
+  INLINE Parameter(const Parameter &copy);
+  INLINE Parameter &operator = (const Parameter &copy);
+  INLINE ~Parameter();
+
+#ifdef USE_MOVE_SEMANTICS
+  INLINE Parameter(Parameter &&from);
+  INLINE Parameter &operator = (Parameter &&from);
+#endif
+
+PUBLISHED:
+  INLINE void clear();
+  INLINE bool is_empty() const;
+
+public:
+  INLINE void swap(Parameter &other) NOEXCEPT;
+
+  INLINE void set_value(const TypedWritableReferenceCount *ptr);
+  INLINE void set_value(const TypedReferenceCount *ptr);
+  INLINE void set_value(int value);
+  INLINE void set_value(bool value);
+  INLINE void set_value(float value);
+  INLINE void set_value(double value);
+  INLINE void set_value(const LVecBase3f &value);
+
+PUBLISHED:
+  void set_value(PyObject *value);
+  PyObject *get_value() const;
+
+  MAKE_PROPERTY(value, get_value, set_value);
+
+  INLINE TypeHandle get_value_type() const;
+
+  // These functions are conveniences to easily determine if the
+  // Parameter is one of the predefined parameter types, and
+  // retrieve the corresponding value.  Of course, it is possible that
+  // the Parameter is some user-defined type, and is none of
+  // these.
+  INLINE bool is_int() const;
+  INLINE int get_int_value() const;
+  INLINE bool is_float() const;
+  INLINE float get_float_value() const;
+  INLINE bool is_double() const;
+  INLINE double get_double_value() const;
+
+  INLINE bool is_string() const;
+  INLINE const string &get_string_value() const;
+  INLINE bool is_wstring() const;
+  INLINE const wstring &get_wstring_value() const;
+
+  INLINE bool is_typed_ref_count() const;
+  INLINE TypedReferenceCount *get_typed_ref_count_value() const;
+
+  INLINE TypedObject *get_typed_object() const;
+
+  void output(ostream &out) const;
+
+  INLINE void write_datagram(BamWriter *manager, Datagram &destination) const;
+  INLINE void read_datagram(DatagramIterator &source, BamReader *manager);
+  INLINE int complete_pointers(TypedWritable **plist, BamReader *manager);
+
+public:
+  // These functions are used by the graphics back-end to extract
+  // underlying numeric data.  They may convert data if appropriate.
+  bool extract_data(int *data, int width, size_t count) const;
+  bool extract_data(float *data, int width, size_t count) const;
+  bool extract_data(double *data, int width, size_t count) const;
+
+private:
+  INLINE double do_get_double() const;
+  INLINE void do_set_double(double value);
+
+  INLINE ReferenceCount *do_get_ptr() const;
+  INLINE void do_set_ptr(ReferenceCount *ptr);
+
+  // I used a classic pointer-preferred NaN-boxing implementation
+  // to avoid the overhead of using a ParamValue for the simple
+  // types.  This means that this class can hold doubles and
+  // pointers while still taking up only 8 bytes on the stack.
+  //
+  // All known 64-bit platforms only use the lower 48 bits for
+  // (most) user-space addressing, which perfectly overlaps with
+  // NaN-payload space of IEEE-754 doubles.  So, we invert the
+  // exponent space of doubles and extend it with a type indicator.
+  //
+  // Some day, another developer is going to find this and
+  // subject me to some well-deserved flogging.
+  enum Type {
+    T_pointer = 0x00000000,
+    T_int     = 0x00010000,
+    T_bool    = 0x00020000,
+    T_float   = 0x00030000,
+    T_MAX     = T_float,
+
+    // These are used to mask out the enum bits in case that
+    // they overlap with that of the pointer on 64-bit systems.
+    // Flipping the type values by T_MASK also results in a
+    // non-canonical NaN representation so that we can distinguish
+    // it easily from an actual double value.
+    T_MASK    = 0x7fff0000,
+  };
+
+  INLINE Type do_get_type() const;
+
+  union Value {
+    // This is either a TypedWritableReferenceCount or a
+    // TypedReferenceCount, but we have to pick a common base.
+    //
+    // Note: C++ doesn't allow us to put a PointerTo in a union,
+    // so we have to manage the reference count ourselves.
+#if NATIVE_WORDSIZE == 64
+    ReferenceCount *_ptr;
+#endif
+    double _double;
+
+    struct Packed {
+#ifdef WORDS_BIGENDIAN
+      PN_uint32 _type;
+#endif
+
+      union {
+        bool _bool;
+        float _float;
+        int _int;
+#if NATIVE_WORDSIZE != 64
+        // On a 32-bits system, pointers don't have to overlap with
+        // the type enum, since they fit comfortably in this union.
+        ReferenceCount *_ptr;
+#endif
+      };
+
+#ifndef WORDS_BIGENDIAN
+      PN_uint32 _type;
+#endif
+    } _packed;
+  } _v;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    register_type(_type_handle, "Parameter");
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+nassert_static(sizeof(Parameter) == 8);
+
+INLINE void swap(Parameter &one, Parameter &two) NOEXCEPT;
+INLINE ostream &operator << (ostream &out, const Parameter &param);
+
+#include "parameter.I"
+
+// Tell GCC that we'll take care of the instantiation explicitly here.
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#endif

+ 26 - 1
panda/src/putil/typedWritableReferenceCount.I

@@ -33,7 +33,8 @@ TypedWritableReferenceCount() {
 INLINE TypedWritableReferenceCount::
 INLINE TypedWritableReferenceCount::
 TypedWritableReferenceCount(const TypedWritableReferenceCount &copy) :
 TypedWritableReferenceCount(const TypedWritableReferenceCount &copy) :
   TypedWritable(copy),
   TypedWritable(copy),
-  ReferenceCount(copy) {
+  ReferenceCount(copy)
+{
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
   MemoryUsage::update_type(this, this);
   MemoryUsage::update_type(this, this);
 #endif
 #endif
@@ -49,3 +50,27 @@ operator = (const TypedWritableReferenceCount &copy) {
   TypedWritable::operator = (copy);
   TypedWritable::operator = (copy);
   ReferenceCount::operator = (copy);
   ReferenceCount::operator = (copy);
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: TypedWritableReferenceCount::as_typed_object
+//       Access: Public
+//  Description: If this object derives from TypedReferenceCount or
+//               TypedWritableReferenceCount, returns a pointer to
+//               the base TypedObject.  Otherwise, returns NULL.
+////////////////////////////////////////////////////////////////////
+INLINE TypedObject *TypedWritableReferenceCount::
+as_typed_object() {
+  return this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TypedWritableReferenceCount::as_typed_object
+//       Access: Public
+//  Description: If this object derives from TypedReferenceCount or
+//               TypedWritableReferenceCount, returns a pointer to
+//               the base TypedObject.  Otherwise, returns NULL.
+////////////////////////////////////////////////////////////////////
+INLINE const TypedObject *TypedWritableReferenceCount::
+as_typed_object() const {
+  return this;
+}

+ 3 - 1
panda/src/putil/typedWritableReferenceCount.h

@@ -29,7 +29,7 @@
 //               each time they are needed, so that we can sensibly
 //               each time they are needed, so that we can sensibly
 //               pass around pointers to things which are both
 //               pass around pointers to things which are both
 //               TypedWritables and ReferenceCounters.
 //               TypedWritables and ReferenceCounters.
-//               
+//
 //               See also TypedObject for detailed instructions.
 //               See also TypedObject for detailed instructions.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_PUTIL TypedWritableReferenceCount : public TypedWritable, public ReferenceCount {
 class EXPCL_PANDA_PUTIL TypedWritableReferenceCount : public TypedWritable, public ReferenceCount {
@@ -39,6 +39,8 @@ public:
   INLINE void operator = (const TypedWritableReferenceCount &copy);
   INLINE void operator = (const TypedWritableReferenceCount &copy);
 
 
   virtual ReferenceCount *as_reference_count();
   virtual ReferenceCount *as_reference_count();
+  virtual INLINE TypedObject *as_typed_object();
+  virtual INLINE const TypedObject *as_typed_object() const;
 
 
 PUBLISHED:
 PUBLISHED:
   static PT(TypedWritableReferenceCount) decode_from_bam_stream(const string &data, BamReader *reader = NULL);
   static PT(TypedWritableReferenceCount) decode_from_bam_stream(const string &data, BamReader *reader = NULL);

+ 3 - 3
panda/src/recorder/mouseRecorder.cxx

@@ -153,9 +153,9 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
     if (input.has_data(_xy_input)) {
     if (input.has_data(_xy_input)) {
       // The mouse is within the window.  Get the current mouse position.
       // The mouse is within the window.  Get the current mouse position.
       const EventStoreVec2 *xy;
       const EventStoreVec2 *xy;
-      DCAST_INTO_V(xy, input.get_data(_xy_input).get_ptr());
+      DCAST_INTO_V(xy, input.get_data(_xy_input).get_typed_object());
       mouse_xy = xy->get_value();
       mouse_xy = xy->get_value();
-      DCAST_INTO_V(xy, input.get_data(_pixel_xy_input).get_ptr());
+      DCAST_INTO_V(xy, input.get_data(_pixel_xy_input).get_typed_object());
       mouse_pixel_xy = xy->get_value();
       mouse_pixel_xy = xy->get_value();
       has_mouse = true;
       has_mouse = true;
     }
     }
@@ -163,7 +163,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
     // Look for button events.
     // Look for button events.
     if (input.has_data(_button_events_input)) {
     if (input.has_data(_button_events_input)) {
       const ButtonEventList *button_events;
       const ButtonEventList *button_events;
-      DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_ptr());
+      DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_typed_object());
       _live_button_events->add_events(*button_events);
       _live_button_events->add_events(*button_events);
     }
     }
   }
   }

+ 2 - 2
panda/src/rocket/rocketInputHandler.cxx

@@ -149,7 +149,7 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
   if (input.has_data(_pixel_xy_input)) {
   if (input.has_data(_pixel_xy_input)) {
     // The mouse is within the window.  Get the current mouse position.
     // The mouse is within the window.  Get the current mouse position.
     const EventStoreVec2 *pixel_xy;
     const EventStoreVec2 *pixel_xy;
-    DCAST_INTO_V(pixel_xy, input.get_data(_pixel_xy_input).get_ptr());
+    DCAST_INTO_V(pixel_xy, input.get_data(_pixel_xy_input).get_typed_object());
     LVecBase2 p = pixel_xy->get_value();
     LVecBase2 p = pixel_xy->get_value();
 
 
     // Determine if mouse moved from last position
     // Determine if mouse moved from last position
@@ -164,7 +164,7 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
   // Look for new button events.
   // Look for new button events.
   if (input.has_data(_button_events_input)) {
   if (input.has_data(_button_events_input)) {
     const ButtonEventList *this_button_events;
     const ButtonEventList *this_button_events;
-    DCAST_INTO_V(this_button_events, input.get_data(_button_events_input).get_ptr());
+    DCAST_INTO_V(this_button_events, input.get_data(_button_events_input).get_typed_object());
     int num_events = this_button_events->get_num_events();
     int num_events = this_button_events->get_num_events();
     for (int i = 0; i < num_events; i++) {
     for (int i = 0; i < num_events; i++) {
       const ButtonEvent &be = this_button_events->get_event(i);
       const ButtonEvent &be = this_button_events->get_event(i);

+ 3 - 3
panda/src/testbed/pview.cxx

@@ -111,7 +111,7 @@ event_Enter(const Event *, void *) {
   // set the toggle
   // set the toggle
   props.set_fullscreen(!props.get_fullscreen());
   props.set_fullscreen(!props.get_fullscreen());
   int flags = GraphicsPipe::BF_require_window;
   int flags = GraphicsPipe::BF_require_window;
-  
+
   WindowFramework *window = framework.open_window(props, flags, pipe, gsg);
   WindowFramework *window = framework.open_window(props, flags, pipe, gsg);
   if (window != (WindowFramework *)NULL) {
   if (window != (WindowFramework *)NULL) {
     window->enable_keyboard();
     window->enable_keyboard();
@@ -126,7 +126,7 @@ event_2(const Event *event, void *) {
 
 
   EventParameter param = event->get_parameter(0);
   EventParameter param = event->get_parameter(0);
   WindowFramework *wf;
   WindowFramework *wf;
-  DCAST_INTO_V(wf, param.get_ptr());
+  DCAST_INTO_V(wf, param.get_typed_object());
 
 
   WindowFramework *split = wf->split_window();
   WindowFramework *split = wf->split_window();
   if (split != (WindowFramework *)NULL) {
   if (split != (WindowFramework *)NULL) {
@@ -141,7 +141,7 @@ event_0(const Event *event, void *) {
   // 0: run hacky test.
   // 0: run hacky test.
   EventParameter param = event->get_parameter(0);
   EventParameter param = event->get_parameter(0);
   WindowFramework *wf;
   WindowFramework *wf;
-  DCAST_INTO_V(wf, param.get_ptr());
+  DCAST_INTO_V(wf, param.get_typed_object());
 
 
   // Create a new offscreen buffer.
   // Create a new offscreen buffer.
   GraphicsOutput *win = wf->get_graphics_output();
   GraphicsOutput *win = wf->get_graphics_output();

+ 1 - 1
panda/src/tform/buttonThrower.cxx

@@ -392,7 +392,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
 
 
   if (input.has_data(_button_events_input)) {
   if (input.has_data(_button_events_input)) {
     const ButtonEventList *button_events;
     const ButtonEventList *button_events;
-    DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_ptr());
+    DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_typed_object());
 
 
     int num_events = button_events->get_num_events();
     int num_events = button_events->get_num_events();
     for (int i = 0; i < num_events; i++) {
     for (int i = 0; i < num_events; i++) {

+ 2 - 2
panda/src/tform/driveInterface.cxx

@@ -403,7 +403,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
 
 
   if (required_buttons_match && input.has_data(_xy_input)) {
   if (required_buttons_match && input.has_data(_xy_input)) {
     const EventStoreVec2 *xy;
     const EventStoreVec2 *xy;
-    DCAST_INTO_V(xy, input.get_data(_xy_input).get_ptr());
+    DCAST_INTO_V(xy, input.get_data(_xy_input).get_typed_object());
     const LVecBase2 &p = xy->get_value();
     const LVecBase2 &p = xy->get_value();
     x = p[0];
     x = p[0];
     y = p[1];
     y = p[1];
@@ -419,7 +419,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
       const ButtonEvent &be = button_events->get_event(i);
       const ButtonEvent &be = button_events->get_event(i);
       if (be._type != ButtonEvent::T_keystroke) {
       if (be._type != ButtonEvent::T_keystroke) {
         bool down = (be._type != ButtonEvent::T_up);
         bool down = (be._type != ButtonEvent::T_up);
-        
+
         if (be._button == KeyboardButton::up()) {
         if (be._button == KeyboardButton::up()) {
           _up_arrow.set_key(down);
           _up_arrow.set_key(down);
         } else if (be._button == KeyboardButton::down()) {
         } else if (be._button == KeyboardButton::down()) {

+ 2 - 2
panda/src/tform/mouseInterfaceNode.cxx

@@ -140,11 +140,11 @@ check_button_events(const DataNodeTransmit &input,
   const ButtonEventList *button_events = NULL;
   const ButtonEventList *button_events = NULL;
 
 
   if (input.has_data(_button_events_input)) {
   if (input.has_data(_button_events_input)) {
-    DCAST_INTO_R(button_events, input.get_data(_button_events_input).get_ptr(), NULL);
+    DCAST_INTO_R(button_events, input.get_data(_button_events_input).get_typed_object(), NULL);
     button_events->update_mods(_current_button_state);
     button_events->update_mods(_current_button_state);
   }
   }
 
 
-  required_buttons_match = 
+  required_buttons_match =
     (_current_button_state & _required_buttons_mask) == _required_buttons_state;
     (_current_button_state & _required_buttons_mask) == _required_buttons_state;
 
 
   return button_events;
   return button_events;

+ 5 - 5
panda/src/tform/mouseSubregion.cxx

@@ -71,7 +71,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
 
 
   if (input.has_data(_xy_input)) {
   if (input.has_data(_xy_input)) {
     const EventStoreVec2 *xy;
     const EventStoreVec2 *xy;
-    DCAST_INTO_V(xy, input.get_data(_xy_input).get_ptr());
+    DCAST_INTO_V(xy, input.get_data(_xy_input).get_typed_object());
     const LVecBase2 &p = xy->get_value();
     const LVecBase2 &p = xy->get_value();
 
 
     // Scale the old value into the new range.
     // Scale the old value into the new range.
@@ -87,12 +87,12 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
       // pixel_size.
       // pixel_size.
       if (input.has_data(_pixel_size_input)) {
       if (input.has_data(_pixel_size_input)) {
         const EventStoreVec2 *pixel_size;
         const EventStoreVec2 *pixel_size;
-        DCAST_INTO_V(pixel_size, input.get_data(_pixel_size_input).get_ptr());
+        DCAST_INTO_V(pixel_size, input.get_data(_pixel_size_input).get_typed_object());
         const LVecBase2 &s = pixel_size->get_value();
         const LVecBase2 &s = pixel_size->get_value();
 
 
         PN_stdfloat xf = (1.0f + n[0]) * 0.5f * s[0];
         PN_stdfloat xf = (1.0f + n[0]) * 0.5f * s[0];
         PN_stdfloat yf = (1.0f - n[1]) * 0.5f * s[1];
         PN_stdfloat yf = (1.0f - n[1]) * 0.5f * s[1];
-        
+
         _pixel_xy->set_value(LPoint2(xf, yf));
         _pixel_xy->set_value(LPoint2(xf, yf));
         output.set_data(_pixel_xy_output, EventParameter(_pixel_xy));
         output.set_data(_pixel_xy_output, EventParameter(_pixel_xy));
       }
       }
@@ -110,7 +110,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
 
 
     if (input.has_data(_button_events_input)) {
     if (input.has_data(_button_events_input)) {
       const ButtonEventList *button_events;
       const ButtonEventList *button_events;
-      DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_ptr());
+      DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_typed_object());
       int num_events = button_events->get_num_events();
       int num_events = button_events->get_num_events();
       for (int i = 0; i < num_events; i++) {
       for (int i = 0; i < num_events; i++) {
         const ButtonEvent &be = button_events->get_event(i);
         const ButtonEvent &be = button_events->get_event(i);
@@ -130,7 +130,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
   // Now scale the window size.
   // Now scale the window size.
   if (input.has_data(_pixel_size_input)) {
   if (input.has_data(_pixel_size_input)) {
     const EventStoreVec2 *pixel_size;
     const EventStoreVec2 *pixel_size;
-    DCAST_INTO_V(pixel_size, input.get_data(_pixel_size_input).get_ptr());
+    DCAST_INTO_V(pixel_size, input.get_data(_pixel_size_input).get_typed_object());
     const LVecBase2 &s = pixel_size->get_value();
     const LVecBase2 &s = pixel_size->get_value();
 
 
     LVecBase2 n(s[0] * (_r - _l), s[1] * (_t - _b));
     LVecBase2 n(s[0] * (_r - _l), s[1] * (_t - _b));

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

@@ -1407,15 +1407,15 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
 
 
   // We always pass the pixel_size data through.
   // We always pass the pixel_size data through.
   EventStoreVec2 *pixel_size;
   EventStoreVec2 *pixel_size;
-  DCAST_INTO_V(pixel_size, input.get_data(_pixel_size_input).get_ptr());
+  DCAST_INTO_V(pixel_size, input.get_data(_pixel_size_input).get_typed_object());
   output.set_data(_pixel_size_output, pixel_size);
   output.set_data(_pixel_size_output, pixel_size);
   _pixel_size = pixel_size;
   _pixel_size = pixel_size;
 
 
   if (input.has_data(_xy_input)) {
   if (input.has_data(_xy_input)) {
     // The mouse is within the window.  Get the current mouse position.
     // The mouse is within the window.  Get the current mouse position.
     const EventStoreVec2 *xy, *pixel_xy;
     const EventStoreVec2 *xy, *pixel_xy;
-    DCAST_INTO_V(xy, input.get_data(_xy_input).get_ptr());
-    DCAST_INTO_V(pixel_xy, input.get_data(_pixel_xy_input).get_ptr());
+    DCAST_INTO_V(xy, input.get_data(_xy_input).get_typed_object());
+    DCAST_INTO_V(pixel_xy, input.get_data(_pixel_xy_input).get_typed_object());
 
 
     LVecBase2 f = xy->get_value();
     LVecBase2 f = xy->get_value();
     LVecBase2 p = pixel_xy->get_value();
     LVecBase2 p = pixel_xy->get_value();
@@ -1451,7 +1451,7 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
   _num_trail_recent = 0;
   _num_trail_recent = 0;
   if (input.has_data(_pointer_events_input) && (_trail_log_duration > 0.0)) {
   if (input.has_data(_pointer_events_input) && (_trail_log_duration > 0.0)) {
     const PointerEventList *this_pointer_events;
     const PointerEventList *this_pointer_events;
-    DCAST_INTO_V(this_pointer_events, input.get_data(_pointer_events_input).get_ptr());
+    DCAST_INTO_V(this_pointer_events, input.get_data(_pointer_events_input).get_typed_object());
     _num_trail_recent = this_pointer_events->get_num_events();
     _num_trail_recent = this_pointer_events->get_num_events();
     for (int i = 0; i < _num_trail_recent; i++) {
     for (int i = 0; i < _num_trail_recent; i++) {
       bool in_win = this_pointer_events->get_in_window(i);
       bool in_win = this_pointer_events->get_in_window(i);
@@ -1482,7 +1482,7 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
   // Look for new button events.
   // Look for new button events.
   if (input.has_data(_button_events_input)) {
   if (input.has_data(_button_events_input)) {
     const ButtonEventList *this_button_events;
     const ButtonEventList *this_button_events;
-    DCAST_INTO_V(this_button_events, input.get_data(_button_events_input).get_ptr());
+    DCAST_INTO_V(this_button_events, input.get_data(_button_events_input).get_typed_object());
     int num_events = this_button_events->get_num_events();
     int num_events = this_button_events->get_num_events();
     for (int i = 0; i < num_events; i++) {
     for (int i = 0; i < num_events; i++) {
       const ButtonEvent &be = this_button_events->get_event(i);
       const ButtonEvent &be = this_button_events->get_event(i);

+ 4 - 4
panda/src/tform/trackball.cxx

@@ -604,12 +604,12 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
   // Now, check for mouse motion.
   // Now, check for mouse motion.
   if (required_buttons_match && input.has_data(_pixel_xy_input)) {
   if (required_buttons_match && input.has_data(_pixel_xy_input)) {
     const EventStoreVec2 *pixel_xy;
     const EventStoreVec2 *pixel_xy;
-    DCAST_INTO_V(pixel_xy, input.get_data(_pixel_xy_input).get_ptr());
+    DCAST_INTO_V(pixel_xy, input.get_data(_pixel_xy_input).get_typed_object());
     const LVecBase2 &p = pixel_xy->get_value();
     const LVecBase2 &p = pixel_xy->get_value();
     PN_stdfloat this_x = p[0];
     PN_stdfloat this_x = p[0];
     PN_stdfloat this_y = p[1];
     PN_stdfloat this_y = p[1];
     int this_button = 0;
     int this_button = 0;
-    
+
     if (is_down(MouseButton::one())) {
     if (is_down(MouseButton::one())) {
       if (is_down(KeyboardButton::alt())) {
       if (is_down(KeyboardButton::alt())) {
         // B1 + alt (option) = B2.
         // B1 + alt (option) = B2.
@@ -633,14 +633,14 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
     if (is_down(MouseButton::three())) {
     if (is_down(MouseButton::three())) {
       this_button |= B3_MASK;
       this_button |= B3_MASK;
     }
     }
-    
+
     PN_stdfloat x = this_x - _lastx;
     PN_stdfloat x = this_x - _lastx;
     PN_stdfloat y = this_y - _lasty;
     PN_stdfloat y = this_y - _lasty;
 
 
     if (this_button == _last_button) {
     if (this_button == _last_button) {
       apply(x, y, this_button);
       apply(x, y, this_button);
     }
     }
-    
+
     _last_button = this_button;
     _last_button = this_button;
     _lastx = this_x;
     _lastx = this_x;
     _lasty = this_y;
     _lasty = this_y;

+ 1 - 1
panda/src/tform/transform2sg.cxx

@@ -76,7 +76,7 @@ do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
 
 
   if (input.has_data(_transform_input)) {
   if (input.has_data(_transform_input)) {
     const TransformState *transform;
     const TransformState *transform;
-    DCAST_INTO_V(transform, input.get_data(_transform_input).get_ptr());
+    DCAST_INTO_V(transform, input.get_data(_transform_input).get_typed_object());
     if (_node != (PandaNode *)NULL) {
     if (_node != (PandaNode *)NULL) {
       _node->set_transform(transform, current_thread);
       _node->set_transform(transform, current_thread);
     }
     }