Browse Source

Merge remote-tracking branch 'origin/master' into deploy-ng

Mitchell Stokes 8 years ago
parent
commit
c155e840b3
100 changed files with 1409 additions and 1058 deletions
  1. 7 0
      direct/src/actor/__init__.py
  2. 4 0
      direct/src/controls/__init__.py
  3. 16 1
      direct/src/directbase/DirectStart.py
  4. 12 0
      direct/src/directbase/__init__.py
  5. 51 28
      direct/src/directdevices/DirectDeviceManager.py
  6. 1 1
      direct/src/directdevices/DirectRadamec.py
  7. 5 0
      direct/src/directdevices/__init__.py
  8. 3 0
      direct/src/directnotify/__init__.py
  9. 8 0
      direct/src/directtools/__init__.py
  10. 3 0
      direct/src/directutil/__init__.py
  11. 8 6
      direct/src/distributed/DistributedSmoothNode.py
  12. 5 0
      direct/src/distributed/__init__.py
  13. 4 1
      direct/src/extensions_native/__init__.py
  14. 11 0
      direct/src/filter/__init__.py
  15. 6 6
      direct/src/fsm/ClassicFSM.py
  16. 1 1
      direct/src/fsm/FSM.py
  17. 2 4
      direct/src/fsm/FourState.py
  18. 2 4
      direct/src/fsm/FourStateAI.py
  19. 6 0
      direct/src/fsm/__init__.py
  20. 1 1
      direct/src/gui/DirectButton.py
  21. 3 1
      direct/src/gui/DirectCheckButton.py
  22. 1 1
      direct/src/gui/DirectDialog.py
  23. 2 1
      direct/src/gui/DirectEntry.py
  24. 14 9
      direct/src/gui/DirectFrame.py
  25. 24 25
      direct/src/gui/DirectGuiBase.py
  26. 3 5
      direct/src/gui/DirectGuiGlobals.py
  27. 1 1
      direct/src/gui/DirectLabel.py
  28. 1 1
      direct/src/gui/DirectOptionMenu.py
  29. 4 1
      direct/src/gui/DirectRadioButton.py
  30. 1 1
      direct/src/gui/DirectScrollBar.py
  31. 1 1
      direct/src/gui/DirectScrolledFrame.py
  32. 1 1
      direct/src/gui/DirectScrolledList.py
  33. 1 1
      direct/src/gui/DirectSlider.py
  34. 1 1
      direct/src/gui/DirectWaitBar.py
  35. 12 0
      direct/src/gui/__init__.py
  36. 4 1
      direct/src/interval/IntervalGlobal.py
  37. 3 3
      direct/src/interval/IntervalManager.py
  38. 4 1
      direct/src/interval/MetaInterval.py
  39. 2 4
      direct/src/interval/ParticleInterval.py
  40. 3 5
      direct/src/interval/TestInterval.py
  41. 12 0
      direct/src/interval/__init__.py
  42. 3 0
      direct/src/motiontrail/__init__.py
  43. 5 2
      direct/src/p3d/AppRunner.py
  44. 4 0
      direct/src/p3d/__init__.py
  45. 7 0
      direct/src/particles/__init__.py
  46. 2 0
      direct/src/showbase/AppRunnerGlobal.py
  47. 1 1
      direct/src/showbase/Audio3DManager.py
  48. 3 1
      direct/src/showbase/BufferViewer.py
  49. 1 1
      direct/src/showbase/BulletinBoard.py
  50. 1 1
      direct/src/showbase/BulletinBoardWatcher.py
  51. 2 1
      direct/src/showbase/DirectObject.py
  52. 1 1
      direct/src/showbase/EventGroup.py
  53. 2 1
      direct/src/showbase/EventManager.py
  54. 2 1
      direct/src/showbase/EventManagerGlobal.py
  55. 1 1
      direct/src/showbase/Factory.py
  56. 2 4
      direct/src/showbase/FindCtaPaths.py
  57. 1 1
      direct/src/showbase/Finder.py
  58. 1 1
      direct/src/showbase/GarbageReport.py
  59. 2 1
      direct/src/showbase/Messenger.py
  60. 2 4
      direct/src/showbase/MirrorDemo.py
  61. 1 1
      direct/src/showbase/ObjectPool.py
  62. 10 12
      direct/src/showbase/ObjectReport.py
  63. 1 1
      direct/src/showbase/OnScreenDebug.py
  64. 7 10
      direct/src/showbase/Pool.py
  65. 2 4
      direct/src/showbase/SfxPlayer.py
  66. 2 5
      direct/src/showbase/ShadowDemo.py
  67. 2 4
      direct/src/showbase/ShadowPlacer.py
  68. 4 1
      direct/src/showbase/TaskThreaded.py
  69. 2 1
      direct/src/showbase/ThreeUpShow.py
  70. 3 1
      direct/src/showbase/Transitions.py
  71. 4 1
      direct/src/showbase/VerboseImport.py
  72. 90 83
      direct/src/showutil/pfreeze.py
  73. 5 0
      direct/src/stdpy/__init__.py
  74. 1 0
      direct/src/task/TaskManagerGlobal.py
  75. 4 3
      direct/src/task/TaskTester.py
  76. 1 1
      direct/src/task/Timer.py
  77. 8 0
      direct/src/task/__init__.py
  78. 1 1
      direct/src/tkpanels/NotifyPanel.py
  79. 4 1
      direct/src/tkwidgets/SceneGraphExplorer.py
  80. 1 1
      direct/src/tkwidgets/Tree.py
  81. 1 1
      direct/src/tkwidgets/WidgetPropertiesDialog.py
  82. 671 706
      dtool/src/cppparser/cppBison.cxx.prebuilt
  83. 11 2
      dtool/src/cppparser/cppBison.yxx
  84. 1 3
      dtool/src/dtoolbase/dtool_platform.h
  85. 1 0
      dtool/src/dtoolbase/typeHandle.N
  86. 0 0
      dtool/src/dtoolbase/typeHandle_ext.cxx
  87. 0 0
      dtool/src/dtoolbase/typeHandle_ext.h
  88. 2 0
      dtool/src/dtoolbase/typedObject.h
  89. 9 0
      dtool/src/dtoolutil/config_dtoolutil.N
  90. 3 0
      dtool/src/dtoolutil/config_dtoolutil.h
  91. 0 0
      dtool/src/dtoolutil/filename_ext.cxx
  92. 0 0
      dtool/src/dtoolutil/filename_ext.h
  93. 0 0
      dtool/src/dtoolutil/globPattern_ext.cxx
  94. 0 0
      dtool/src/dtoolutil/globPattern_ext.h
  95. 2 0
      dtool/src/dtoolutil/p3dtoolutil_ext_composite.cxx
  96. 2 2
      dtool/src/dtoolutil/pfstream.h
  97. 23 6
      dtool/src/interrogate/functionRemap.cxx
  98. 204 68
      dtool/src/interrogate/interfaceMakerPythonNative.cxx
  99. 8 0
      dtool/src/interrogate/interrogateBuilder.cxx
  100. 21 0
      dtool/src/interrogate/typeManager.cxx

+ 7 - 0
direct/src/actor/__init__.py

@@ -0,0 +1,7 @@
+"""
+This package contains the :class:`.Actor` class as well as a
+distributed variant thereof.  Actor is a high-level interface around
+the lower-level :class:`panda3d.core.Character` implementation.
+It loads and controls an animated character and manages the animations
+playing on it.
+"""

+ 4 - 0
direct/src/controls/__init__.py

@@ -0,0 +1,4 @@
+"""
+This package contains various types of character controllers, handling basic
+control mechanics and setting up collisions for them.
+"""

+ 16 - 1
direct/src/directbase/DirectStart.py

@@ -1,4 +1,19 @@
-""" This is a deprecated module that creates a global instance of ShowBase. """
+"""
+This is a shortcut that instantiates ShowBase automatically on import,
+opening a graphical window and setting up the scene graph.
+This example demonstrates its use:
+
+   import direct.directbase.DirectStart
+   run()
+
+While it may be considered useful for quick prototyping in the interactive
+Python shell, using it in applications is not considered good style.
+As such, it has been deprecated starting with Panda3D 1.9.  It is equivalent
+to and may be replaced by the following code:
+
+   from direct.showbase.ShowBase import ShowBase
+   base = ShowBase()
+"""
 
 
 __all__ = []
 __all__ = []
 
 

+ 12 - 0
direct/src/directbase/__init__.py

@@ -0,0 +1,12 @@
+"""
+This package contains modules to quickly set up a Panda environment for
+quick prototyping in the interactive Python shell.  Merely importing
+one of these modules will create a :class:`.ShowBase` instance, opening
+a graphical window and setting up the scene graph.
+
+The most commonly used module from this package is :mod:`.DirectStart`,
+importing which executes the following code::
+
+   from direct.showbase.ShowBase import ShowBase
+   base = ShowBase()
+"""

+ 51 - 28
direct/src/directdevices/DirectDeviceManager.py

@@ -9,10 +9,6 @@ ANALOG_MAX = 0.95
 ANALOG_DEADBAND = 0.125
 ANALOG_DEADBAND = 0.125
 ANALOG_CENTER = 0.0
 ANALOG_CENTER = 0.0
 
 
-try:
-    myBase = base
-except:
-    myBase = simbase
 
 
 class DirectDeviceManager(VrpnClient, DirectObject):
 class DirectDeviceManager(VrpnClient, DirectObject):
     def __init__(self, server = None):
     def __init__(self, server = None):
@@ -52,8 +48,13 @@ class DirectButtons(ButtonNode, DirectObject):
         ButtonNode.__init__(self, vrpnClient, device)
         ButtonNode.__init__(self, vrpnClient, device)
         # Create a unique name for this button object
         # Create a unique name for this button object
         self.name = 'DirectButtons-' + repr(DirectButtons.buttonCount)
         self.name = 'DirectButtons-' + repr(DirectButtons.buttonCount)
+
         # Attach node to data graph
         # Attach node to data graph
-        self.nodePath = myBase.dataRoot.attachNewNode(self)
+        try:
+            self._base = base
+        except:
+            self._base = simbase
+        self.nodePath = self._base.dataRoot.attachNewNode(self)
 
 
     def __getitem__(self, index):
     def __getitem__(self, index):
         if (index < 0) or (index >= self.getNumButtons()):
         if (index < 0) or (index >= self.getNumButtons()):
@@ -64,10 +65,10 @@ class DirectButtons(ButtonNode, DirectObject):
         return self.getNumButtons()
         return self.getNumButtons()
 
 
     def enable(self):
     def enable(self):
-        self.nodePath.reparentTo(myBase.dataRoot)
+        self.nodePath.reparentTo(self._base.dataRoot)
 
 
     def disable(self):
     def disable(self):
-        self.nodePath.reparentTo(myBase.dataUnused)
+        self.nodePath.reparentTo(self._base.dataUnused)
 
 
     def getName(self):
     def getName(self):
         return self.name
         return self.name
@@ -83,6 +84,12 @@ class DirectButtons(ButtonNode, DirectObject):
 
 
 class DirectAnalogs(AnalogNode, DirectObject):
 class DirectAnalogs(AnalogNode, DirectObject):
     analogCount = 0
     analogCount = 0
+
+    _analogDeadband = ConfigVariableDouble('vrpn-analog-deadband', ANALOG_DEADBAND)
+    _analogMin = ConfigVariableDouble('vrpn-analog-min', ANALOG_MIN)
+    _analogMax = ConfigVariableDouble('vrpn-analog-max', ANALOG_MAX)
+    _analogCenter = ConfigVariableDouble('vrpn-analog-center', ANALOG_CENTER)
+
     def __init__(self, vrpnClient, device):
     def __init__(self, vrpnClient, device):
         # Keep track of number of analogs created
         # Keep track of number of analogs created
         DirectAnalogs.analogCount += 1
         DirectAnalogs.analogCount += 1
@@ -90,20 +97,21 @@ class DirectAnalogs(AnalogNode, DirectObject):
         AnalogNode.__init__(self, vrpnClient, device)
         AnalogNode.__init__(self, vrpnClient, device)
         # Create a unique name for this analog object
         # Create a unique name for this analog object
         self.name = 'DirectAnalogs-' + repr(DirectAnalogs.analogCount)
         self.name = 'DirectAnalogs-' + repr(DirectAnalogs.analogCount)
+
         # Attach node to data graph
         # Attach node to data graph
-        self.nodePath = myBase.dataRoot.attachNewNode(self)
+        try:
+            self._base = base
+        except:
+            self._base = simbase
+        self.nodePath = self._base.dataRoot.attachNewNode(self)
+
         # See if any of the general analog parameters are dconfig'd
         # See if any of the general analog parameters are dconfig'd
-        self.analogDeadband = myBase.config.GetFloat('vrpn-analog-deadband',
-                                                     ANALOG_DEADBAND)
-        self.analogMin = myBase.config.GetFloat('vrpn-analog-min',
-                                                ANALOG_MIN)
-        self.analogMax = myBase.config.GetFloat('vrpn-analog-max',
-                                                ANALOG_MAX)
-        self.analogCenter = myBase.config.GetFloat('vrpn-analog-center',
-                                                   ANALOG_CENTER)
+        self.analogDeadband = self._analogDeadband.getValue()
+        self.analogMin = self._analogMin.getValue()
+        self.analogMax = self._analogMax.getValue()
+        self.analogCenter = self._analogCenter.getValue()
         self.analogRange = self.analogMax - self.analogMin
         self.analogRange = self.analogMax - self.analogMin
 
 
-
     def __getitem__(self, index):
     def __getitem__(self, index):
         if (index < 0) or (index >= self.getNumControls()):
         if (index < 0) or (index >= self.getNumControls()):
             raise IndexError
             raise IndexError
@@ -113,10 +121,10 @@ class DirectAnalogs(AnalogNode, DirectObject):
         return self.getNumControls()
         return self.getNumControls()
 
 
     def enable(self):
     def enable(self):
-        self.nodePath.reparentTo(myBase.dataRoot)
+        self.nodePath.reparentTo(self._base.dataRoot)
 
 
     def disable(self):
     def disable(self):
-        self.nodePath.reparentTo(myBase.dataUnused)
+        self.nodePath.reparentTo(self._base.dataUnused)
 
 
     def normalizeWithoutCentering(self, val, minVal = -1, maxVal = 1):
     def normalizeWithoutCentering(self, val, minVal = -1, maxVal = 1):
         #
         #
@@ -186,14 +194,19 @@ class DirectTracker(TrackerNode, DirectObject):
         TrackerNode.__init__(self, vrpnClient, device)
         TrackerNode.__init__(self, vrpnClient, device)
         # Create a unique name for this tracker object
         # Create a unique name for this tracker object
         self.name = 'DirectTracker-' + repr(DirectTracker.trackerCount)
         self.name = 'DirectTracker-' + repr(DirectTracker.trackerCount)
+
         # Attach node to data graph
         # Attach node to data graph
-        self.nodePath = myBase.dataRoot.attachNewNode(self)
+        try:
+            self._base = base
+        except:
+            self._base = simbase
+        self.nodePath = self._base.dataRoot.attachNewNode(self)
 
 
     def enable(self):
     def enable(self):
-        self.nodePath.reparentTo(myBase.dataRoot)
+        self.nodePath.reparentTo(self._base.dataRoot)
 
 
     def disable(self):
     def disable(self):
-        self.nodePath.reparentTo(myBase.dataUnused)
+        self.nodePath.reparentTo(self._base.dataUnused)
 
 
     def getName(self):
     def getName(self):
         return self.name
         return self.name
@@ -213,8 +226,13 @@ class DirectDials(DialNode, DirectObject):
         DialNode.__init__(self, vrpnClient, device)
         DialNode.__init__(self, vrpnClient, device)
         # Create a unique name for this dial object
         # Create a unique name for this dial object
         self.name = 'DirectDials-' + repr(DirectDials.dialCount)
         self.name = 'DirectDials-' + repr(DirectDials.dialCount)
+
         # Attach node to data graph
         # Attach node to data graph
-        self.nodePath = myBase.dataRoot.attachNewNode(self)
+        try:
+            self._base = base
+        except:
+            self._base = simbase
+        self.nodePath = self._base.dataRoot.attachNewNode(self)
 
 
     def __getitem__(self, index):
     def __getitem__(self, index):
         """
         """
@@ -227,10 +245,10 @@ class DirectDials(DialNode, DirectObject):
         return self.getNumDials()
         return self.getNumDials()
 
 
     def enable(self):
     def enable(self):
-        self.nodePath.reparentTo(myBase.dataRoot)
+        self.nodePath.reparentTo(self._base.dataRoot)
 
 
     def disable(self):
     def disable(self):
-        self.nodePath.reparentTo(myBase.dataUnused)
+        self.nodePath.reparentTo(self._base.dataUnused)
 
 
     def getName(self):
     def getName(self):
         return self.name
         return self.name
@@ -259,14 +277,19 @@ class DirectTimecodeReader(AnalogNode, DirectObject):
         self.seconds = 0
         self.seconds = 0
         self.minutes = 0
         self.minutes = 0
         self.hours = 0
         self.hours = 0
+
         # Attach node to data graph
         # Attach node to data graph
-        self.nodePath = myBase.dataRoot.attachNewNode(self)
+        try:
+            self._base = base
+        except:
+            self._base = simbase
+        self.nodePath = self._base.dataRoot.attachNewNode(self)
 
 
     def enable(self):
     def enable(self):
-        self.nodePath.reparentTo(myBase.dataRoot)
+        self.nodePath.reparentTo(self._base.dataRoot)
 
 
     def disable(self):
     def disable(self):
-        self.nodePath.reparentTo(myBase.dataUnused)
+        self.nodePath.reparentTo(self._base.dataUnused)
 
 
     def getName(self):
     def getName(self):
         return self.name
         return self.name

+ 1 - 1
direct/src/directdevices/DirectRadamec.py

@@ -21,7 +21,7 @@ class DirectRadamec(DirectObject):
     radamecCount = 0
     radamecCount = 0
     notify = DirectNotifyGlobal.directNotify.newCategory('DirectRadamec')
     notify = DirectNotifyGlobal.directNotify.newCategory('DirectRadamec')
 
 
-    def __init__(self, device = 'Analog0', nodePath = base.direct.camera):
+    def __init__(self, device = 'Analog0', nodePath = None):
         # See if device manager has been initialized
         # See if device manager has been initialized
         if base.direct.deviceManager == None:
         if base.direct.deviceManager == None:
             base.direct.deviceManager = DirectDeviceManager()
             base.direct.deviceManager = DirectDeviceManager()

+ 5 - 0
direct/src/directdevices/__init__.py

@@ -0,0 +1,5 @@
+"""
+This package contains a high-level interface for VRPN devices.
+
+Also see the :mod:`panda3d.vprn` module.
+"""

+ 3 - 0
direct/src/directnotify/__init__.py

@@ -0,0 +1,3 @@
+"""
+This package contains notification and logging utilities for Python code.
+"""

+ 8 - 0
direct/src/directtools/__init__.py

@@ -0,0 +1,8 @@
+"""
+This package contains the DIRECT tools, a set of tkinter tools for exploring
+and manipulating the Panda3D scene graph.  By default, these are disabled,
+but they can be explicitly enabled using the following PRC configuration::
+
+   want-directtools true
+   want-tk true
+"""

+ 3 - 0
direct/src/directutil/__init__.py

@@ -0,0 +1,3 @@
+"""
+This package contains assorted utility classes.
+"""

+ 8 - 6
direct/src/distributed/DistributedSmoothNode.py

@@ -7,19 +7,21 @@ from . import DistributedNode
 from . import DistributedSmoothNodeBase
 from . import DistributedSmoothNodeBase
 from direct.task.Task import cont
 from direct.task.Task import cont
 
 
+config = get_config_showbase()
+
 # This number defines our tolerance for out-of-sync telemetry packets.
 # This number defines our tolerance for out-of-sync telemetry packets.
 # If a packet appears to have originated from more than MaxFuture
 # If a packet appears to have originated from more than MaxFuture
 # seconds in the future, assume we're out of sync with the other
 # seconds in the future, assume we're out of sync with the other
 # avatar and suggest a resync for both.
 # avatar and suggest a resync for both.
-MaxFuture = base.config.GetFloat("smooth-max-future", 0.2)
+MaxFuture = config.GetFloat("smooth-max-future", 0.2)
 
 
 # How frequently can we suggest a resynchronize with another client?
 # How frequently can we suggest a resynchronize with another client?
-MinSuggestResync = base.config.GetFloat("smooth-min-suggest-resync", 15)
+MinSuggestResync = config.GetFloat("smooth-min-suggest-resync", 15)
 
 
 # These flags indicate whether global smoothing and/or prediction is
 # These flags indicate whether global smoothing and/or prediction is
 # allowed or disallowed.
 # allowed or disallowed.
-EnableSmoothing = base.config.GetBool("smooth-enable-smoothing", 1)
-EnablePrediction = base.config.GetBool("smooth-enable-prediction", 1)
+EnableSmoothing = config.GetBool("smooth-enable-smoothing", 1)
+EnablePrediction = config.GetBool("smooth-enable-prediction", 1)
 
 
 # These values represent the amount of time, in seconds, to delay the
 # These values represent the amount of time, in seconds, to delay the
 # apparent position of other avatars, when non-predictive and
 # apparent position of other avatars, when non-predictive and
@@ -27,8 +29,8 @@ EnablePrediction = base.config.GetBool("smooth-enable-prediction", 1)
 # addition to the automatic delay of the observed average latency from
 # addition to the automatic delay of the observed average latency from
 # each avatar, which is intended to compensate for relative clock
 # each avatar, which is intended to compensate for relative clock
 # skew.
 # skew.
-Lag = base.config.GetDouble("smooth-lag", 0.2)
-PredictionLag = base.config.GetDouble("smooth-prediction-lag", 0.0)
+Lag = config.GetDouble("smooth-lag", 0.2)
+PredictionLag = config.GetDouble("smooth-prediction-lag", 0.0)
 
 
 
 
 GlobalSmoothing = 0
 GlobalSmoothing = 0

+ 5 - 0
direct/src/distributed/__init__.py

@@ -0,0 +1,5 @@
+"""
+This package contains an implementation of the Distributed Networking
+API, a high-level networking system that automatically propagates
+changes made on distributed objects to interested clients.
+"""

+ 4 - 1
direct/src/extensions_native/__init__.py

@@ -1 +1,4 @@
-
+"""
+This package contains various Python methods that extend some of Panda's
+underlying C++ classes.
+"""

+ 11 - 0
direct/src/filter/__init__.py

@@ -0,0 +1,11 @@
+"""
+This package contains functionality for applying post-processing
+filters to the result of rendering a 3-D scene.  This is done by
+rendering the scene to an off-screen buffer, and then applying this to
+a full-screen card that has a shader applied which manipulates the
+texture values as desired.
+
+The :class:`.CommonFilters` class contains various filters that are
+provided out of the box, whereas the :class:`.FilterManager` class
+is a lower-level class that allows you to set up your own filters.
+"""

+ 6 - 6
direct/src/fsm/ClassicFSM.py

@@ -1,13 +1,13 @@
-"""Undocumented Module"""
-
-__all__ = ['ClassicFSM']
-
 """Finite State Machine module: contains the ClassicFSM class.
 """Finite State Machine module: contains the ClassicFSM class.
 
 
-This module and class exist only for backward compatibility with
-existing code.  New code should use the FSM module instead.
+.. note::
+
+   This module and class exist only for backward compatibility with
+   existing code.  New code should use the :mod:`.FSM` module instead.
 """
 """
 
 
+__all__ = ['ClassicFSM']
+
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
 import weakref
 import weakref

+ 1 - 1
direct/src/fsm/FSM.py

@@ -1,5 +1,5 @@
 """The new Finite State Machine module. This replaces the module
 """The new Finite State Machine module. This replaces the module
-previously called FSM.py (now called ClassicFSM.py).
+previously called FSM (now called :mod:`.ClassicFSM`).
 """
 """
 
 
 __all__ = ['FSMException', 'FSM']
 __all__ = ['FSMException', 'FSM']

+ 2 - 4
direct/src/fsm/FourState.py

@@ -1,9 +1,7 @@
-"""Undocumented Module"""
+"""Contains the FourState class."""
 
 
 __all__ = ['FourState']
 __all__ = ['FourState']
 
 
-
-
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
 #import DistributedObject
 #import DistributedObject
 from . import ClassicFSM
 from . import ClassicFSM
@@ -20,7 +18,7 @@ class FourState:
     Inherit from FourStateFSM and pass in your states.  Two of
     Inherit from FourStateFSM and pass in your states.  Two of
     the states should be oposites of each other and the other
     the states should be oposites of each other and the other
     two should be the transition states between the first two.
     two should be the transition states between the first two.
-    E.g.
+    E.g::
 
 
                     +--------+
                     +--------+
                  -->| closed | --
                  -->| closed | --

+ 2 - 4
direct/src/fsm/FourStateAI.py

@@ -1,9 +1,7 @@
-"""Undocumented Module"""
+"""Contains the FourStateAI class.  See also :mod:`.FourState`."""
 
 
 __all__ = ['FourStateAI']
 __all__ = ['FourStateAI']
 
 
-
-
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
 #import DistributedObjectAI
 #import DistributedObjectAI
 from . import ClassicFSM
 from . import ClassicFSM
@@ -21,7 +19,7 @@ class FourStateAI:
     Inherit from FourStateFSM and pass in your states.  Two of
     Inherit from FourStateFSM and pass in your states.  Two of
     the states should be oposites of each other and the other
     the states should be oposites of each other and the other
     two should be the transition states between the first two.
     two should be the transition states between the first two.
-    E.g.
+    E.g::
 
 
                     +--------+
                     +--------+
                  -->| closed | --
                  -->| closed | --

+ 6 - 0
direct/src/fsm/__init__.py

@@ -0,0 +1,6 @@
+"""
+This package contains implementations of a Finite State Machine, an
+abstract construct that holds a particular state and can transition
+between several defined states.  These are useful for a range of logic
+programming tasks.
+"""

+ 1 - 1
direct/src/gui/DirectButton.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""This module contains the DirectButton class."""
 
 
 __all__ = ['DirectButton']
 __all__ = ['DirectButton']
 
 

+ 3 - 1
direct/src/gui/DirectCheckButton.py

@@ -1,4 +1,6 @@
-"""Undocumented Module"""
+"""A DirectCheckButton is a type of button that toggles between two states
+when clicked.  It also has a separate indicator that can be modified
+separately."""
 
 
 __all__ = ['DirectCheckButton']
 __all__ = ['DirectCheckButton']
 
 

+ 1 - 1
direct/src/gui/DirectDialog.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""This module defines various dialog windows for the DirectGUI system."""
 
 
 __all__ = ['findDialog', 'cleanupDialog', 'DirectDialog', 'OkDialog', 'OkCancelDialog', 'YesNoDialog', 'YesNoCancelDialog', 'RetryCancelDialog']
 __all__ = ['findDialog', 'cleanupDialog', 'DirectDialog', 'OkDialog', 'OkCancelDialog', 'YesNoDialog', 'YesNoCancelDialog', 'RetryCancelDialog']
 
 

+ 2 - 1
direct/src/gui/DirectEntry.py

@@ -1,4 +1,5 @@
-"""Undocumented Module"""
+"""Contains the DirectEntry class, a type of DirectGUI widget that accepts
+text entered using the keyboard."""
 
 
 __all__ = ['DirectEntry']
 __all__ = ['DirectEntry']
 
 

+ 14 - 9
direct/src/gui/DirectFrame.py

@@ -1,4 +1,17 @@
-"""Undocumented Module"""
+"""A DirectFrame is a basic DirectGUI component that acts as the base
+class for various other components, and can also serve as a basic
+container to hold other DirectGUI components.
+
+A DirectFrame can have:
+
+* A background texture (pass in path to image, or Texture Card)
+* A midground geometry item (pass in geometry)
+* A foreground text Node (pass in text string or OnscreenText)
+
+Each of these has 1 or more states.  The same object can be used for
+all states or each state can have a different text/geom/image (for
+radio button and check button indicators, for example).
+"""
 
 
 __all__ = ['DirectFrame']
 __all__ = ['DirectFrame']
 
 
@@ -19,14 +32,6 @@ class DirectFrame(DirectGuiWidget):
     DefDynGroups = ('text', 'geom', 'image')
     DefDynGroups = ('text', 'geom', 'image')
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
         # Inherits from DirectGuiWidget
         # Inherits from DirectGuiWidget
-        # A Direct Frame can have:
-        # - A background texture (pass in path to image, or Texture Card)
-        # - A midground geometry item (pass in geometry)
-        # - A foreground text Node (pass in text string or Onscreen Text)
-        # Each of these has 1 or more states
-        # The same object can be used for all states or each
-        # state can have a different text/geom/image (for radio button
-        # and check button indicators, for example).
         optiondefs = (
         optiondefs = (
             # Define type of DirectGuiWidget
             # Define type of DirectGuiWidget
             ('pgFunc',          PGItem,     None),
             ('pgFunc',          PGItem,     None),

+ 24 - 25
direct/src/gui/DirectGuiBase.py

@@ -1,32 +1,7 @@
-"""Undocumented Module"""
-
-__all__ = ['DirectGuiBase', 'DirectGuiWidget']
-
-
-from panda3d.core import *
-from panda3d.direct import get_config_showbase
-from . import DirectGuiGlobals as DGG
-from .OnscreenText import *
-from .OnscreenGeom import *
-from .OnscreenImage import *
-from direct.directtools.DirectUtil import ROUND_TO
-from direct.showbase import DirectObject
-from direct.task import Task
-import sys
-
-if sys.version_info >= (3, 0):
-    stringType = str
-else:
-    stringType = basestring
-
-guiObjectCollector = PStatCollector("Client::GuiObjects")
-
 """
 """
 Base class for all Direct Gui items.  Handles composite widgets and
 Base class for all Direct Gui items.  Handles composite widgets and
 command line argument parsing.
 command line argument parsing.
-"""
 
 
-"""
 Code Overview:
 Code Overview:
 
 
 1   Each widget defines a set of options (optiondefs) as a list of tuples
 1   Each widget defines a set of options (optiondefs) as a list of tuples
@@ -101,7 +76,31 @@ Code Overview:
     are left unused.  If so, an error is raised.
     are left unused.  If so, an error is raised.
 """
 """
 
 
+__all__ = ['DirectGuiBase', 'DirectGuiWidget']
+
+
+from panda3d.core import *
+from panda3d.direct import get_config_showbase
+from . import DirectGuiGlobals as DGG
+from .OnscreenText import *
+from .OnscreenGeom import *
+from .OnscreenImage import *
+from direct.directtools.DirectUtil import ROUND_TO
+from direct.showbase import DirectObject
+from direct.task import Task
+import sys
+
+if sys.version_info >= (3, 0):
+    stringType = str
+else:
+    stringType = basestring
+
+guiObjectCollector = PStatCollector("Client::GuiObjects")
+
+
 class DirectGuiBase(DirectObject.DirectObject):
 class DirectGuiBase(DirectObject.DirectObject):
+    """Base class of all DirectGUI widgets."""
+
     def __init__(self):
     def __init__(self):
         # Default id of all gui object, subclasses should override this
         # Default id of all gui object, subclasses should override this
         self.guiId = 'guiObject'
         self.guiId = 'guiObject'

+ 3 - 5
direct/src/gui/DirectGuiGlobals.py

@@ -1,12 +1,10 @@
-"""Undocumented Module"""
-
-__all__ = []
-
-
 """
 """
 Global definitions used by Direct Gui Classes and handy constants
 Global definitions used by Direct Gui Classes and handy constants
 that can be used during widget construction
 that can be used during widget construction
 """
 """
+
+__all__ = []
+
 from panda3d.core import *
 from panda3d.core import *
 
 
 defaultFont = None
 defaultFont = None

+ 1 - 1
direct/src/gui/DirectLabel.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the DirectLabel class."""
 
 
 __all__ = ['DirectLabel']
 __all__ = ['DirectLabel']
 
 

+ 1 - 1
direct/src/gui/DirectOptionMenu.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Implements a pop-up menu containing multiple clickable options."""
 
 
 __all__ = ['DirectOptionMenu']
 __all__ = ['DirectOptionMenu']
 
 

+ 4 - 1
direct/src/gui/DirectRadioButton.py

@@ -1,4 +1,7 @@
-"""Undocumented Module"""
+"""A DirectRadioButton is a type of button that, similar to a
+DirectCheckButton, has a separate indicator and can be toggled between
+two states.  However, only one DirectRadioButton in a group can be enabled
+at a particular time."""
 
 
 __all__ = ['DirectRadioButton']
 __all__ = ['DirectRadioButton']
 
 

+ 1 - 1
direct/src/gui/DirectScrollBar.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Defines the DirectScrollBar class."""
 
 
 __all__ = ['DirectScrollBar']
 __all__ = ['DirectScrollBar']
 
 

+ 1 - 1
direct/src/gui/DirectScrolledFrame.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the DirectScrolledFrame class."""
 
 
 __all__ = ['DirectScrolledFrame']
 __all__ = ['DirectScrolledFrame']
 
 

+ 1 - 1
direct/src/gui/DirectScrolledList.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the DirectScrolledList class."""
 
 
 __all__ = ['DirectScrolledListItem', 'DirectScrolledList']
 __all__ = ['DirectScrolledListItem', 'DirectScrolledList']
 
 

+ 1 - 1
direct/src/gui/DirectSlider.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Defines the DirectSlider class."""
 
 
 __all__ = ['DirectSlider']
 __all__ = ['DirectSlider']
 
 

+ 1 - 1
direct/src/gui/DirectWaitBar.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the DirectWaitBar class, a progress bar widget."""
 
 
 __all__ = ['DirectWaitBar']
 __all__ = ['DirectWaitBar']
 
 

+ 12 - 0
direct/src/gui/__init__.py

@@ -0,0 +1,12 @@
+"""
+This package contains the DirectGui system, a set of classes
+responsible for drawing graphical widgets to the 2-D scene graph.
+
+It is based on the lower-level PGui system, which is implemented in
+C++.
+
+For convenience, all of the DirectGui widgets may be imported from a
+single module as follows::
+
+   from direct.gui.DirectGui import *
+"""

+ 4 - 1
direct/src/interval/IntervalGlobal.py

@@ -1,4 +1,7 @@
-"""IntervalGlobal module"""
+"""
+This module imports all of the other interval modules, to provide a
+single convenient module from which all interval types can be imported.
+"""
 
 
 # In this unusual case, I'm not going to declare __all__,
 # In this unusual case, I'm not going to declare __all__,
 # since the purpose of this module is to add up the contributions
 # since the purpose of this module is to add up the contributions

+ 3 - 3
direct/src/interval/IntervalManager.py

@@ -1,4 +1,5 @@
-"""Undocumented Module"""
+"""Defines the IntervalManager class as well as the global instance of
+this class, ivalMgr."""
 
 
 __all__ = ['IntervalManager', 'ivalMgr']
 __all__ = ['IntervalManager', 'ivalMgr']
 
 
@@ -136,6 +137,5 @@ class IntervalManager(CIntervalManager):
         assert self.ivals[index] == None or self.ivals[index] == interval
         assert self.ivals[index] == None or self.ivals[index] == interval
         self.ivals[index] = interval
         self.ivals[index] = interval
 
 
-# The global IntervalManager object.
+#: The global IntervalManager object.
 ivalMgr = IntervalManager(1)
 ivalMgr = IntervalManager(1)
-

+ 4 - 1
direct/src/interval/MetaInterval.py

@@ -1,4 +1,7 @@
-"""Undocumented Module"""
+"""
+This module defines the various "meta intervals", which execute other
+intervals either in parallel or in a specified sequential order.
+"""
 
 
 __all__ = ['MetaInterval', 'Sequence', 'Parallel', 'ParallelEndTogether', 'Track']
 __all__ = ['MetaInterval', 'Sequence', 'Parallel', 'ParallelEndTogether', 'Track']
 
 

+ 2 - 4
direct/src/interval/ParticleInterval.py

@@ -1,11 +1,9 @@
-"""Undocumented Module"""
-
-__all__ = ['ParticleInterval']
-
 """
 """
 Contains the ParticleInterval class
 Contains the ParticleInterval class
 """
 """
 
 
+__all__ = ['ParticleInterval']
+
 from panda3d.core import *
 from panda3d.core import *
 from panda3d.direct import *
 from panda3d.direct import *
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify

+ 3 - 5
direct/src/interval/TestInterval.py

@@ -1,11 +1,9 @@
-"""Undocumented Module"""
-
-__all__ = ['TestInterval']
-
 """
 """
-Contains the ParticleInterval class
+Contains the TestInterval class
 """
 """
 
 
+__all__ = ['TestInterval']
+
 from panda3d.core import *
 from panda3d.core import *
 from panda3d.direct import *
 from panda3d.direct import *
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify

+ 12 - 0
direct/src/interval/__init__.py

@@ -0,0 +1,12 @@
+"""
+This package contains the Python implementation of the interval system,
+which is a mechanism for playing back scripted actions.  A range of
+interval types has been defined to automate motion, animation, sounds,
+color, function calls, as well as other intervals and arbitrary
+properties.
+
+All interval types can be conveniently imported from the
+:mod:`.IntervalGlobal` module::
+
+   from direct.interval.IntervalGlobal import *
+"""

+ 3 - 0
direct/src/motiontrail/__init__.py

@@ -0,0 +1,3 @@
+"""
+This package contains only the :class:`.MotionTrail` class.
+"""

+ 5 - 2
direct/src/p3d/AppRunner.py

@@ -1,12 +1,15 @@
-
 """
 """
-
 This module is intended to be compiled into the Panda3D runtime
 This module is intended to be compiled into the Panda3D runtime
 distributable, to execute a packaged p3d application, but it can also
 distributable, to execute a packaged p3d application, but it can also
 be run directly via the Python interpreter (if the current Panda3D and
 be run directly via the Python interpreter (if the current Panda3D and
 Python versions match the version expected by the application).  See
 Python versions match the version expected by the application).  See
 runp3d.py for a command-line tool to invoke this module.
 runp3d.py for a command-line tool to invoke this module.
 
 
+The global AppRunner instance may be imported as follows::
+
+   from direct.showbase.AppRunnerGlobal import appRunner
+
+This will be None if Panda was not run from the runtime environment.
 """
 """
 
 
 __all__ = ["AppRunner", "dummyAppRunner", "ArgumentError"]
 __all__ = ["AppRunner", "dummyAppRunner", "ArgumentError"]

+ 4 - 0
direct/src/p3d/__init__.py

@@ -0,0 +1,4 @@
+"""
+This package provides the Python interface to functionality relating to
+the Panda3D Runtime environment.
+"""

+ 7 - 0
direct/src/particles/__init__.py

@@ -0,0 +1,7 @@
+"""
+This package contains the high-level Python interface to the particle
+system.
+
+Also see the :mod:`panda3d.physics` module, which contains the C++
+implementation of the particle system.
+"""

+ 2 - 0
direct/src/showbase/AppRunnerGlobal.py

@@ -6,4 +6,6 @@ This is needed for apps that start themselves by importing
 DirectStart; it provides a place for these apps to look for
 DirectStart; it provides a place for these apps to look for
 the AppRunner at startup. """
 the AppRunner at startup. """
 
 
+#: Contains the global AppRunner instance, or None if this application
+#: was not run from the runtime environment.
 appRunner = None
 appRunner = None

+ 1 - 1
direct/src/showbase/Audio3DManager.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the Audio3DManager class."""
 
 
 __all__ = ['Audio3DManager']
 __all__ = ['Audio3DManager']
 
 

+ 3 - 1
direct/src/showbase/BufferViewer.py

@@ -1,4 +1,6 @@
-"""Undocumented Module"""
+"""Contains the BufferViewer class, which is used as a debugging aid
+when debugging render-to-texture effects.  It shows different views at
+the bottom of the screen showing the various render targets."""
 
 
 __all__ = ['BufferViewer']
 __all__ = ['BufferViewer']
 
 

+ 1 - 1
direct/src/showbase/BulletinBoard.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the BulletinBoard class."""
 
 
 __all__ = ['BulletinBoard']
 __all__ = ['BulletinBoard']
 
 

+ 1 - 1
direct/src/showbase/BulletinBoardWatcher.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the BulletinBoardWatcher class."""
 
 
 __all__ = ['BulletinBoardWatcher']
 __all__ = ['BulletinBoardWatcher']
 
 

+ 2 - 1
direct/src/showbase/DirectObject.py

@@ -1,4 +1,5 @@
-"""Undocumented Module"""
+"""Defines the DirectObject class, a convenient class to inherit from if the
+object needs to be able to respond to events."""
 
 
 __all__ = ['DirectObject']
 __all__ = ['DirectObject']
 
 

+ 1 - 1
direct/src/showbase/EventGroup.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""This module defines the EventGroup class."""
 
 
 __all__ = ['EventGroup']
 __all__ = ['EventGroup']
 
 

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

@@ -1,4 +1,5 @@
-"""Undocumented Module"""
+"""Contains the EventManager class.  See :mod:`.EventManagerGlobal` for the
+global eventMgr instance."""
 
 
 __all__ = ['EventManager']
 __all__ = ['EventManager']
 
 

+ 2 - 1
direct/src/showbase/EventManagerGlobal.py

@@ -1,7 +1,8 @@
-"""Undocumented Module"""
+"""Contains the global :class:`.EventManager` instance."""
 
 
 __all__ = ['eventMgr']
 __all__ = ['eventMgr']
 
 
 from . import EventManager
 from . import EventManager
 
 
+#: The global event manager.
 eventMgr = EventManager.EventManager()
 eventMgr = EventManager.EventManager()

+ 1 - 1
direct/src/showbase/Factory.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the Factory class."""
 
 
 __all__ = ['Factory']
 __all__ = ['Factory']
 
 

+ 2 - 4
direct/src/showbase/FindCtaPaths.py

@@ -1,7 +1,3 @@
-"""Undocumented Module"""
-
-__all__ = ['deCygwinify', 'getPaths']
-
 """This module is used only by the VR Studio programmers who are using
 """This module is used only by the VR Studio programmers who are using
 the ctattach tools.  It is imported before any other package, and its
 the ctattach tools.  It is imported before any other package, and its
 job is to figure out the correct paths to each of the packages.
 job is to figure out the correct paths to each of the packages.
@@ -10,6 +6,8 @@ This module is not needed if you are not using ctattach; in this case
 all of the Panda packages will be collected under a common directory,
 all of the Panda packages will be collected under a common directory,
 which you will presumably have already on your PYTHONPATH. """
 which you will presumably have already on your PYTHONPATH. """
 
 
+__all__ = ['deCygwinify', 'getPaths']
+
 import os
 import os
 import sys
 import sys
 
 

+ 1 - 1
direct/src/showbase/Finder.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains various utility functions."""
 
 
 __all__ = ['findClass', 'rebindClass', 'copyFuncs', 'replaceMessengerFunc', 'replaceTaskMgrFunc', 'replaceStateFunc', 'replaceCRFunc', 'replaceAIRFunc', 'replaceIvalFunc']
 __all__ = ['findClass', 'rebindClass', 'copyFuncs', 'replaceMessengerFunc', 'replaceTaskMgrFunc', 'replaceStateFunc', 'replaceCRFunc', 'replaceAIRFunc', 'replaceIvalFunc']
 
 

+ 1 - 1
direct/src/showbase/GarbageReport.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains utility classes for debugging memory leaks."""
 
 
 __all__ = ['FakeObject', '_createGarbage', 'GarbageReport', 'GarbageLogger']
 __all__ = ['FakeObject', '_createGarbage', 'GarbageReport', 'GarbageLogger']
 
 

+ 2 - 1
direct/src/showbase/Messenger.py

@@ -1,4 +1,5 @@
-"""Undocumented Module"""
+"""This defines the Messenger class, which is responsible for most of the
+event handling that happens on the Python side."""
 
 
 __all__ = ['Messenger']
 __all__ = ['Messenger']
 
 

+ 2 - 4
direct/src/showbase/MirrorDemo.py

@@ -1,7 +1,3 @@
-"""Undocumented Module"""
-
-__all__ = ['setupMirror', 'showFrustum']
-
 """This file demonstrates one way to create a mirror effect in Panda.
 """This file demonstrates one way to create a mirror effect in Panda.
 Call setupMirror() to create a mirror in the world that reflects
 Call setupMirror() to create a mirror in the world that reflects
 everything in front of it.
 everything in front of it.
@@ -23,6 +19,8 @@ surface are possible, like a funhouse mirror.  However, the reflection
 itself is always basically planar; for more accurate convex
 itself is always basically planar; for more accurate convex
 reflections, you will need to use a sphere map or a cube map."""
 reflections, you will need to use a sphere map or a cube map."""
 
 
+__all__ = ['setupMirror', 'showFrustum']
+
 from panda3d.core import *
 from panda3d.core import *
 from direct.task import Task
 from direct.task import Task
 
 

+ 1 - 1
direct/src/showbase/ObjectPool.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the ObjectPool utility class."""
 
 
 __all__ = ['Diff', 'ObjectPool']
 __all__ = ['Diff', 'ObjectPool']
 
 

+ 10 - 12
direct/src/showbase/ObjectReport.py

@@ -1,4 +1,13 @@
-"""Undocumented Module"""
+"""
+>>> from direct.showbase import ObjectReport
+
+>>> o=ObjectReport.ObjectReport('baseline')
+>>> run()
+...
+
+>>> o2=ObjectReport.ObjectReport('')
+>>> o.diff(o2)
+"""
 
 
 __all__ = ['ExclusiveObjectPool', 'ObjectReport']
 __all__ = ['ExclusiveObjectPool', 'ObjectReport']
 
 
@@ -13,17 +22,6 @@ if sys.version_info >= (3, 0):
 else:
 else:
     import __builtin__ as builtins
     import __builtin__ as builtins
 
 
-"""
->>> from direct.showbase import ObjectReport
-
->>> o=ObjectReport.ObjectReport('baseline')
->>> run()
-...
-
->>> o2=ObjectReport.ObjectReport('')
->>> o.diff(o2)
-"""
-
 class ExclusiveObjectPool(DirectObject.DirectObject):
 class ExclusiveObjectPool(DirectObject.DirectObject):
     # ObjectPool specialization that excludes particular objects
     # ObjectPool specialization that excludes particular objects
     # IDs of objects to globally exclude from reporting
     # IDs of objects to globally exclude from reporting

+ 1 - 1
direct/src/showbase/OnScreenDebug.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the OnScreenDebug class."""
 
 
 __all__ = ['OnScreenDebug']
 __all__ = ['OnScreenDebug']
 
 

+ 7 - 10
direct/src/showbase/Pool.py

@@ -1,9 +1,4 @@
-"""Undocumented Module"""
-
-__all__ = ['Pool']
-
 """
 """
-
 Pool is a collection of python objects that you can checkin and
 Pool is a collection of python objects that you can checkin and
 checkout. This is useful for a cache of objects that are expensive to load
 checkout. This is useful for a cache of objects that are expensive to load
 and can be reused over and over, like splashes on cannonballs, or
 and can be reused over and over, like splashes on cannonballs, or
@@ -12,12 +7,16 @@ or be the same type.
 
 
 Internally the pool is implemented with 2 lists, free items and used items.
 Internally the pool is implemented with 2 lists, free items and used items.
 
 
-p = Pool([1, 2, 3, 4, 5])
-x = p.checkout()
-p.checkin(x)
+Example::
+
+   p = Pool([1, 2, 3, 4, 5])
+   x = p.checkout()
+   p.checkin(x)
 
 
 """
 """
 
 
+__all__ = ['Pool']
+
 
 
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
 
 
@@ -116,5 +115,3 @@ class Pool:
 
 
     def __repr__(self):
     def __repr__(self):
         return "free = %s\nused = %s" % (self.__free, self.__used)
         return "free = %s\nused = %s" % (self.__free, self.__used)
-
-

+ 2 - 4
direct/src/showbase/SfxPlayer.py

@@ -1,4 +1,5 @@
-"""Undocumented Module"""
+"""Contains the SfxPlayer class, a thin utility class for playing sounds at
+a particular location."""
 
 
 __all__ = ['SfxPlayer']
 __all__ = ['SfxPlayer']
 
 
@@ -95,6 +96,3 @@ class SfxPlayer:
             if node is not None:
             if node is not None:
                 finalVolume *= node.getNetAudioVolume()
                 finalVolume *= node.getNetAudioVolume()
             sfx.setVolume(finalVolume)
             sfx.setVolume(finalVolume)
-
-
-

+ 2 - 5
direct/src/showbase/ShadowDemo.py

@@ -1,8 +1,3 @@
-"""Undocumented Module"""
-
-__all__ = ['ShadowCaster', 'avatarShadow', 'piratesAvatarShadow', 'arbitraryShadow']
-
-
 """Create a cheesy shadow effect by rendering the view of an
 """Create a cheesy shadow effect by rendering the view of an
 object (e.g. the local avatar) from a special camera as seen from
 object (e.g. the local avatar) from a special camera as seen from
 above (as if from the sun), using a solid gray foreground and a
 above (as if from the sun), using a solid gray foreground and a
@@ -14,6 +9,8 @@ multitexture rendering techniques.  It's not a particularly great
 way to do shadows.
 way to do shadows.
 """
 """
 
 
+__all__ = ['ShadowCaster', 'avatarShadow', 'piratesAvatarShadow', 'arbitraryShadow']
+
 from panda3d.core import *
 from panda3d.core import *
 from direct.task import Task
 from direct.task import Task
 
 

+ 2 - 4
direct/src/showbase/ShadowPlacer.py

@@ -1,7 +1,3 @@
-"""Undocumented Module"""
-
-__all__ = ['ShadowPlacer']
-
 """
 """
 ShadowPlacer.py places a shadow.
 ShadowPlacer.py places a shadow.
 
 
@@ -10,6 +6,8 @@ Or it may do that later, right now it puts a node on the surface under
 the its parent node.
 the its parent node.
 """
 """
 
 
+__all__ = ['ShadowPlacer']
+
 from direct.controls.ControlManager import CollisionHandlerRayStart
 from direct.controls.ControlManager import CollisionHandlerRayStart
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
 from panda3d.core import *
 from panda3d.core import *

+ 4 - 1
direct/src/showbase/TaskThreaded.py

@@ -1,10 +1,13 @@
-"""Undocumented Module"""
+"""Contains the TaskThreaded and TaskThread classes."""
 
 
 __all__ = ['TaskThreaded', 'TaskThread']
 __all__ = ['TaskThreaded', 'TaskThread']
 
 
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.task import Task
 from direct.task import Task
 
 
+from .PythonUtil import SerialNumGen
+
+
 class TaskThreaded:
 class TaskThreaded:
     """ derive from this if you need to do a bunch of CPU-intensive
     """ derive from this if you need to do a bunch of CPU-intensive
     processing and you don't want to hang up the show. Lets you break
     processing and you don't want to hang up the show. Lets you break

+ 2 - 1
direct/src/showbase/ThreeUpShow.py

@@ -1,4 +1,5 @@
-"""Undocumented Module"""
+"""ThreeUpShow is a variant of ShowBase that defines three cameras covering
+different parts of the window."""
 
 
 __all__ = ['ThreeUpShow']
 __all__ = ['ThreeUpShow']
 
 

+ 3 - 1
direct/src/showbase/Transitions.py

@@ -1,4 +1,6 @@
-"""Undocumented Module"""
+"""This module defines various transition effects that can be used to
+graphically transition between two scenes, such as by fading the screen to
+a particular color."""
 
 
 __all__ = ['Transitions']
 __all__ = ['Transitions']
 
 

+ 4 - 1
direct/src/showbase/VerboseImport.py

@@ -1,4 +1,7 @@
-"""Undocumented Module"""
+"""
+This module hooks into Python's import mechanism to print out all imports to
+the standard output as they happen.
+"""
 
 
 __all__ = []
 __all__ = []
 
 

+ 90 - 83
direct/src/showutil/pfreeze.py

@@ -13,11 +13,11 @@ Python code into a standalone executable.  It also uses Python's
 built-in modulefinder module, which it uses to find all of the modules
 built-in modulefinder module, which it uses to find all of the modules
 imported directly or indirectly by the original startfile.py.
 imported directly or indirectly by the original startfile.py.
 
 
-Usage:
+Usage::
 
 
   pfreeze.py [opts] [startfile]
   pfreeze.py [opts] [startfile]
 
 
-Options:
+Options::
 
 
   -o output
   -o output
      Specifies the name of the resulting executable file to produce.
      Specifies the name of the resulting executable file to produce.
@@ -67,88 +67,95 @@ def usage(code, msg = ''):
     sys.stderr.write(str(msg) + '\n')
     sys.stderr.write(str(msg) + '\n')
     sys.exit(code)
     sys.exit(code)
 
 
-# We're not protecting the next part under a __name__ == __main__
-# check, just so we can import this file directly in ppython.cxx.
-
-freezer = FreezeTool.Freezer()
-
-basename = None
-addStartupModules = False
-
-try:
-    opts, args = getopt.getopt(sys.argv[1:], 'o:i:x:p:P:slkh')
-except getopt.error as msg:
-    usage(1, msg)
-
-for opt, arg in opts:
-    if opt == '-o':
-        basename = arg
-    elif opt == '-i':
-        for module in arg.split(','):
-            freezer.addModule(module)
-    elif opt == '-x':
-        for module in arg.split(','):
-            freezer.excludeModule(module)
-    elif opt == '-p':
-        for module in arg.split(','):
-            freezer.handleCustomPath(module)
-    elif opt == '-P':
-        sys.path.append(arg)
-    elif opt == '-s':
-        addStartupModules = True
-    elif opt == '-l':
-        freezer.linkExtensionModules = True
-    elif opt == '-k':
-        freezer.keepTemporaryFiles = True
-    elif opt == '-h':
-        usage(0)
-    else:
-        print('illegal option: ' + flag)
-        sys.exit(1)
-
-if not basename:
-    usage(1, 'You did not specify an output file.')
-
-if len(args) > 1:
-    usage(1, 'Only one main file may be specified.')
-
-outputType = 'exe'
-bl = basename.lower()
-if bl.endswith('.mf'):
-    outputType = 'mf'
-elif bl.endswith('.c'):
-    outputType = 'c'
-elif bl.endswith('.dll') or bl.endswith('.pyd') or bl.endswith('.so'):
-    basename = os.path.splitext(basename)[0]
-    outputType = 'dll'
-elif bl.endswith('.exe'):
-    basename = os.path.splitext(basename)[0]
-
-compileToExe = False
-if args:
-    startfile = args[0]
-    startmod = startfile
-    if startfile.endswith('.py') or startfile.endswith('.pyw') or \
-       startfile.endswith('.pyc') or startfile.endswith('.pyo'):
-        startmod = os.path.splitext(startfile)[0]
-
-    if outputType == 'dll' or outputType == 'c':
-        freezer.addModule(startmod, filename = startfile)
-    else:
-        freezer.addModule('__main__', filename = startfile)
-        compileToExe = True
-        addStartupModules = True
 
 
-elif outputType == 'exe':
-    # We must have a main module when making an executable.
-    usage(1, 'A main file needs to be specified when creating an executable.')
+def main(args=None):
+    if args is None:
+        args = sys.argv[1:]
+
+    freezer = FreezeTool.Freezer()
+
+    basename = None
+    addStartupModules = False
+
+    try:
+        opts, args = getopt.getopt(args, 'o:i:x:p:P:slkh')
+    except getopt.error as msg:
+        usage(1, msg)
+
+    for opt, arg in opts:
+        if opt == '-o':
+            basename = arg
+        elif opt == '-i':
+            for module in arg.split(','):
+                freezer.addModule(module)
+        elif opt == '-x':
+            for module in arg.split(','):
+                freezer.excludeModule(module)
+        elif opt == '-p':
+            for module in arg.split(','):
+                freezer.handleCustomPath(module)
+        elif opt == '-P':
+            sys.path.append(arg)
+        elif opt == '-s':
+            addStartupModules = True
+        elif opt == '-l':
+            freezer.linkExtensionModules = True
+        elif opt == '-k':
+            freezer.keepTemporaryFiles = True
+        elif opt == '-h':
+            usage(0)
+        else:
+            print('illegal option: ' + flag)
+            sys.exit(1)
+
+    if not basename:
+        usage(1, 'You did not specify an output file.')
+
+    if len(args) > 1:
+        usage(1, 'Only one main file may be specified.')
+
+    outputType = 'exe'
+    bl = basename.lower()
+    if bl.endswith('.mf'):
+        outputType = 'mf'
+    elif bl.endswith('.c'):
+        outputType = 'c'
+    elif bl.endswith('.dll') or bl.endswith('.pyd') or bl.endswith('.so'):
+        basename = os.path.splitext(basename)[0]
+        outputType = 'dll'
+    elif bl.endswith('.exe'):
+        basename = os.path.splitext(basename)[0]
+
+    compileToExe = False
+    if args:
+        startfile = args[0]
+        startmod = startfile
+        if startfile.endswith('.py') or startfile.endswith('.pyw') or \
+        startfile.endswith('.pyc') or startfile.endswith('.pyo'):
+            startmod = os.path.splitext(startfile)[0]
+
+        if outputType == 'dll' or outputType == 'c':
+            freezer.addModule(startmod, filename = startfile)
+        else:
+            freezer.addModule('__main__', filename = startfile)
+            compileToExe = True
+            addStartupModules = True
+
+    elif outputType == 'exe':
+        # We must have a main module when making an executable.
+        usage(1, 'A main file needs to be specified when creating an executable.')
+
+    freezer.done(addStartupModules = addStartupModules)
+
+    if outputType == 'mf':
+        freezer.writeMultifile(basename)
+    elif outputType == 'c':
+        freezer.writeCode(basename)
+    else:
+        freezer.generateCode(basename, compileToExe = compileToExe)
 
 
-freezer.done(addStartupModules = addStartupModules)
+    return 0
 
 
-if outputType == 'mf':
-    freezer.writeMultifile(basename)
-elif outputType == 'c':
-    freezer.writeCode(basename)
-else:
-    freezer.generateCode(basename, compileToExe = compileToExe)
 
 
+if __name__ == '__main__':
+    sys.exit(main())

+ 5 - 0
direct/src/stdpy/__init__.py

@@ -0,0 +1,5 @@
+"""
+This package contains various modules that provide a drop-in substitute
+for some of the built-in Python modules.  These substitutes make better
+use of Panda3D's virtual file system and threading system.
+"""

+ 1 - 0
direct/src/task/TaskManagerGlobal.py

@@ -4,4 +4,5 @@ __all__ = ['taskMgr']
 
 
 from . import Task
 from . import Task
 
 
+#: The global task manager.
 taskMgr = Task.TaskManager()
 taskMgr = Task.TaskManager()

+ 4 - 3
direct/src/task/TaskTester.py

@@ -24,7 +24,8 @@ def taskCallback(task):
     spawnNewTask()
     spawnNewTask()
     return Task.done
     return Task.done
 
 
-taskMgr.removeTasksMatching("taskTester*")
+if __name__ == '__main__':
+    taskMgr.removeTasksMatching("taskTester*")
 
 
-for i in range(numTasks):
-    spawnNewTask()
+    for i in range(numTasks):
+        spawnNewTask()

+ 1 - 1
direct/src/task/Timer.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the Timer class."""
 
 
 __all__ = ['Timer']
 __all__ = ['Timer']
 
 

+ 8 - 0
direct/src/task/__init__.py

@@ -0,0 +1,8 @@
+"""
+This package contains the Python interface to the task system, which
+manages scheduled functions that are executed at designated intervals.
+
+The global task manager object can be imported as a singleton::
+
+   from direct.task.TaskManagerGlobal import taskMgr
+"""

+ 1 - 1
direct/src/tkpanels/NotifyPanel.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the NotifyPanel class."""
 
 
 __all__ = ['NotifyPanel']
 __all__ = ['NotifyPanel']
 
 

+ 4 - 1
direct/src/tkwidgets/SceneGraphExplorer.py

@@ -1,4 +1,7 @@
-"""Undocumented Module"""
+"""This module defines a widget used to display a graphical overview of the
+scene graph using the tkinter GUI system.
+
+Requires Pmw."""
 
 
 __all__ = ['SceneGraphExplorer', 'SceneGraphExplorerItem', 'explore']
 __all__ = ['SceneGraphExplorer', 'SceneGraphExplorerItem', 'explore']
 
 

+ 1 - 1
direct/src/tkwidgets/Tree.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Defines tree widgets for the tkinter GUI system."""
 
 
 __all__ = ['TreeNode', 'TreeItem']
 __all__ = ['TreeNode', 'TreeItem']
 
 

+ 1 - 1
direct/src/tkwidgets/WidgetPropertiesDialog.py

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the WidgetPropertiesDialog class."""
 
 
 __all__ = ['WidgetPropertiesDialog']
 __all__ = ['WidgetPropertiesDialog']
 
 

File diff suppressed because it is too large
+ 671 - 706
dtool/src/cppparser/cppBison.cxx.prebuilt


+ 11 - 2
dtool/src/cppparser/cppBison.yxx

@@ -928,12 +928,21 @@ type_like_declaration:
 
 
   current_scope->add_declaration($2, global_scope, current_lexer, @2);
   current_scope->add_declaration($2, global_scope, current_lexer, @2);
 }
 }
-        | storage_class constructor_prototype maybe_initialize_or_constructor_body
+        | storage_class constructor_prototype
 {
 {
   if ($2 != (CPPInstance *)NULL) {
   if ($2 != (CPPInstance *)NULL) {
+    // Push the scope so that the initializers can make use of things defined
+    // in the class body.
+    push_scope($2->get_scope(current_scope, global_scope));
     $2->_storage_class |= (current_storage_class | $1);
     $2->_storage_class |= (current_storage_class | $1);
+  }
+}
+        maybe_initialize_or_constructor_body
+{
+  if ($2 != (CPPInstance *)NULL) {
+    pop_scope();
     current_scope->add_declaration($2, global_scope, current_lexer, @2);
     current_scope->add_declaration($2, global_scope, current_lexer, @2);
-    $2->set_initializer($3);
+    $2->set_initializer($4);
   }
   }
 }
 }
         | storage_class function_prototype maybe_initialize_or_function_body
         | storage_class function_prototype maybe_initialize_or_function_body

+ 1 - 3
dtool/src/dtoolbase/dtool_platform.h

@@ -72,10 +72,8 @@
 #define DTOOL_PLATFORM "linux_ppc"
 #define DTOOL_PLATFORM "linux_ppc"
 #endif
 #endif
 
 
-#ifndef DTOOL_PLATFORM
+#if !defined(DTOOL_PLATFORM) && !defined(CPPPARSER)
 #error "Can't determine platform; please define DTOOL_PLATFORM in Config.pp file."
 #error "Can't determine platform; please define DTOOL_PLATFORM in Config.pp file."
 #endif
 #endif
 
 
-
-
 #endif
 #endif

+ 1 - 0
dtool/src/dtoolbase/typeHandle.N

@@ -0,0 +1 @@
+defconstruct TypeHandle TypeHandle(TypeHandle::none())

+ 0 - 0
panda/src/express/typeHandle_ext.cxx → dtool/src/dtoolbase/typeHandle_ext.cxx


+ 0 - 0
panda/src/express/typeHandle_ext.h → dtool/src/dtoolbase/typeHandle_ext.h


+ 2 - 0
dtool/src/dtoolbase/typedObject.h

@@ -97,6 +97,8 @@ PUBLISHED:
 
 
   // Derived classes should override this function to return get_class_type().
   // Derived classes should override this function to return get_class_type().
   virtual TypeHandle get_type() const=0;
   virtual TypeHandle get_type() const=0;
+
+  // Returns the TypeHandle representing this object's type.
   MAKE_PROPERTY(type, get_type);
   MAKE_PROPERTY(type, get_type);
 
 
   INLINE int get_type_index() const;
   INLINE int get_type_index() const;

+ 9 - 0
dtool/src/dtoolutil/config_dtoolutil.N

@@ -0,0 +1,9 @@
+forcetype ofstream
+forcetype ifstream
+forcetype fstream
+
+forcetype ios_base
+forcetype ios
+forcetype istream
+forcetype ostream
+forcetype iostream

+ 3 - 0
dtool/src/dtoolutil/config_dtoolutil.h

@@ -16,4 +16,7 @@
 
 
 #include "dtoolbase.h"
 #include "dtoolbase.h"
 
 
+// Include this so interrogate can find it.
+#include <iostream>
+
 #endif
 #endif

+ 0 - 0
panda/src/express/filename_ext.cxx → dtool/src/dtoolutil/filename_ext.cxx


+ 0 - 0
panda/src/express/filename_ext.h → dtool/src/dtoolutil/filename_ext.h


+ 0 - 0
panda/src/express/globPattern_ext.cxx → dtool/src/dtoolutil/globPattern_ext.cxx


+ 0 - 0
panda/src/express/globPattern_ext.h → dtool/src/dtoolutil/globPattern_ext.h


+ 2 - 0
dtool/src/dtoolutil/p3dtoolutil_ext_composite.cxx

@@ -0,0 +1,2 @@
+#include "filename_ext.cxx"
+#include "globPattern_ext.cxx"

+ 2 - 2
dtool/src/dtoolutil/pfstream.h

@@ -17,7 +17,7 @@
 #include "pfstreamBuf.h"
 #include "pfstreamBuf.h"
 
 
 class EXPCL_DTOOL IPipeStream : public istream {
 class EXPCL_DTOOL IPipeStream : public istream {
-PUBLISHED:
+public:
   INLINE IPipeStream(const std::string);
   INLINE IPipeStream(const std::string);
 
 
 #if _MSC_VER >= 1800
 #if _MSC_VER >= 1800
@@ -33,7 +33,7 @@ private:
 };
 };
 
 
 class EXPCL_DTOOL OPipeStream : public ostream {
 class EXPCL_DTOOL OPipeStream : public ostream {
-PUBLISHED:
+public:
   INLINE OPipeStream(const std::string);
   INLINE OPipeStream(const std::string);
 
 
 #if _MSC_VER >= 1800
 #if _MSC_VER >= 1800

+ 23 - 6
dtool/src/interrogate/functionRemap.cxx

@@ -869,8 +869,14 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
       }
       }
 
 
       if (_args_type == InterfaceMaker::AT_varargs) {
       if (_args_type == InterfaceMaker::AT_varargs) {
-        // Of course methods named "make" can still take kwargs.
-        _args_type = InterfaceMaker::AT_keyword_args;
+        // Of course methods named "make" can still take kwargs, if they are
+        // named.
+        for (int i = first_param; i < _parameters.size(); ++i) {
+          if (_parameters[i]._has_name) {
+            _args_type = InterfaceMaker::AT_keyword_args;
+            break;
+          }
+        }
       }
       }
 
 
     } else if (fname == "operator /") {
     } else if (fname == "operator /") {
@@ -898,8 +904,13 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
     } else {
     } else {
       if (_args_type == InterfaceMaker::AT_varargs) {
       if (_args_type == InterfaceMaker::AT_varargs) {
         // Every other method can take keyword arguments, if they take more
         // Every other method can take keyword arguments, if they take more
-        // than one argument.
-        _args_type |= InterfaceMaker::AT_keyword_args;
+        // than one argument, and the arguments are named.
+        for (int i = first_param; i < _parameters.size(); ++i) {
+          if (_parameters[i]._has_name) {
+            _args_type |= InterfaceMaker::AT_keyword_args;
+            break;
+          }
+        }
       }
       }
     }
     }
     break;
     break;
@@ -941,8 +952,14 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
       _flags |= F_coerce_constructor;
       _flags |= F_coerce_constructor;
     }
     }
 
 
-    // Constructors always take varargs and keyword args.
-    _args_type = InterfaceMaker::AT_keyword_args;
+    // Constructors always take varargs, and possibly keyword args.
+    _args_type = InterfaceMaker::AT_varargs;
+    for (int i = first_param; i < _parameters.size(); ++i) {
+      if (_parameters[i]._has_name) {
+        _args_type = InterfaceMaker::AT_keyword_args;
+        break;
+      }
+    }
     break;
     break;
 
 
   default:
   default:

+ 204 - 68
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -3389,6 +3389,7 @@ write_function_for_name(ostream &out, Object *obj,
   FunctionRemap *remap = NULL;
   FunctionRemap *remap = NULL;
   int max_required_args = 0;
   int max_required_args = 0;
   bool all_nonconst = true;
   bool all_nonconst = true;
+  bool has_keywords = false;
 
 
   out << "/**\n * Python function wrapper for:\n";
   out << "/**\n * Python function wrapper for:\n";
   for (ri = remaps.begin(); ri != remaps.end(); ++ri) {
   for (ri = remaps.begin(); ri != remaps.end(); ++ri) {
@@ -3404,6 +3405,10 @@ write_function_for_name(ostream &out, Object *obj,
         all_nonconst = false;
         all_nonconst = false;
       }
       }
 
 
+      if (remap->_args_type == AT_keyword_args) {
+        has_keywords = true;
+      }
+
       max_required_args = max(max_num_args, max_required_args);
       max_required_args = max(max_num_args, max_required_args);
 
 
       for (int i = min_num_args; i <= max_num_args; ++i) {
       for (int i = min_num_args; i <= max_num_args; ++i) {
@@ -3450,6 +3455,19 @@ write_function_for_name(ostream &out, Object *obj,
     return;
     return;
   }
   }
 
 
+  if (args_type == AT_keyword_args && !has_keywords) {
+    // We don't actually take keyword arguments.  Make sure we didn't get any.
+    out << "  if (kwds != NULL && PyDict_Size(kwds) > 0) {\n";
+    out << "#ifdef NDEBUG\n";
+    error_raise_return(out, 4, return_flags, "TypeError", "function takes no keyword arguments");
+    out << "#else\n";
+    error_raise_return(out, 4, return_flags, "TypeError",
+      methodNameFromCppName(remap, "", false) + "() takes no keyword arguments");
+    out << "#endif\n";
+    out << "  }\n";
+    args_type = AT_varargs;
+  }
+
   if (args_type == AT_keyword_args || args_type == AT_varargs) {
   if (args_type == AT_keyword_args || args_type == AT_varargs) {
     max_required_args = collapse_default_remaps(map_sets, max_required_args);
     max_required_args = collapse_default_remaps(map_sets, max_required_args);
   }
   }
@@ -3461,6 +3479,7 @@ write_function_for_name(ostream &out, Object *obj,
                             args_type, return_flags);
                             args_type, return_flags);
 
 
   } else if (map_sets.size() > 1 && (args_type == AT_varargs || args_type == AT_keyword_args)) {
   } else if (map_sets.size() > 1 && (args_type == AT_varargs || args_type == AT_keyword_args)) {
+    // We have more than one remap.
     switch (args_type) {
     switch (args_type) {
     case AT_keyword_args:
     case AT_keyword_args:
       indent(out, 2) << "int parameter_count = (int)PyTuple_Size(args);\n";
       indent(out, 2) << "int parameter_count = (int)PyTuple_Size(args);\n";
@@ -3498,16 +3517,50 @@ write_function_for_name(ostream &out, Object *obj,
         indent(out, 2) << "case " << i << ":\n";
         indent(out, 2) << "case " << i << ":\n";
         num_args.insert(i + add_self);
         num_args.insert(i + add_self);
       }
       }
-      indent(out, 4) << "{\n";
       num_args.insert(max_args + add_self);
       num_args.insert(max_args + add_self);
 
 
-      if (min_args == 1 && max_args == 1 && args_type == AT_varargs) {
-        // Might as well, since we already checked the number of args.
-        indent(out, 6) << "  PyObject *arg = PyTuple_GET_ITEM(args, 0);\n";
+      bool strip_keyword_args = false;
+
+      // Check whether any remap actually takes keyword arguments.  If not,
+      // then we don't have to bother checking that for every remap.
+      if (args_type == AT_keyword_args && max_args > 0) {
+        strip_keyword_args = true;
+
+        std::set<FunctionRemap *>::iterator sii;
+        for (sii = mii->second.begin(); sii != mii->second.end(); ++sii) {
+          remap = (*sii);
+          int first_param = remap->_has_this ? 1 : 0;
+          for (int i = first_param; i < remap->_parameters.size(); ++i) {
+            if (remap->_parameters[i]._has_name) {
+              strip_keyword_args = false;
+              break;
+            }
+          }
+        }
+      }
+
+      if (strip_keyword_args) {
+        // None of the remaps take any keyword arguments, so let's check that
+        // we take none.  This saves some checks later on.
+        indent(out, 4) << "if (kwds == NULL || ((PyDictObject *)kwds)->ma_used == 0) {\n";
+        if (min_args == 1 && min_args == 1) {
+          indent(out, 4) << "  PyObject *arg = PyTuple_GET_ITEM(args, 0);\n";
+          write_function_forset(out, mii->second, min_args, max_args, expected_params, 6,
+                coercion_allowed, true, AT_single_arg, return_flags, true, !all_nonconst);
+        } else {
+          write_function_forset(out, mii->second, min_args, max_args, expected_params, 6,
+                coercion_allowed, true, AT_varargs, return_flags, true, !all_nonconst);
+        }
+      } else if (min_args == 1 && max_args == 1 && args_type == AT_varargs) {
+        // We already checked that the args tuple has only one argument, so
+        // we might as well extract that from the tuple now.
+        indent(out, 4) << "{\n";
+        indent(out, 4) << "  PyObject *arg = PyTuple_GET_ITEM(args, 0);\n";
 
 
         write_function_forset(out, mii->second, min_args, max_args, expected_params, 6,
         write_function_forset(out, mii->second, min_args, max_args, expected_params, 6,
                       coercion_allowed, true, AT_single_arg, return_flags, true, !all_nonconst);
                       coercion_allowed, true, AT_single_arg, return_flags, true, !all_nonconst);
       } else {
       } else {
+        indent(out, 4) << "{\n";
         write_function_forset(out, mii->second, min_args, max_args, expected_params, 6,
         write_function_forset(out, mii->second, min_args, max_args, expected_params, 6,
                       coercion_allowed, true, args_type, return_flags, true, !all_nonconst);
                       coercion_allowed, true, args_type, return_flags, true, !all_nonconst);
       }
       }
@@ -3574,14 +3627,14 @@ write_function_for_name(ostream &out, Object *obj,
     if (mii->first == 0 && args_type != AT_no_args) {
     if (mii->first == 0 && args_type != AT_no_args) {
       switch (args_type) {
       switch (args_type) {
       case AT_keyword_args:
       case AT_keyword_args:
-        out << "  if (PyTuple_Size(args) > 0 || (kwds != NULL && PyDict_Size(kwds) > 0)) {\n";
+        out << "  if (!Dtool_CheckNoArgs(args, kwds)) {\n";
         out << "    int parameter_count = (int)PyTuple_Size(args);\n";
         out << "    int parameter_count = (int)PyTuple_Size(args);\n";
         out << "    if (kwds != NULL) {\n";
         out << "    if (kwds != NULL) {\n";
         out << "      parameter_count += (int)PyDict_Size(kwds);\n";
         out << "      parameter_count += (int)PyDict_Size(kwds);\n";
         out << "    }\n";
         out << "    }\n";
         break;
         break;
       case AT_varargs:
       case AT_varargs:
-        out << "  if (PyTuple_Size(args) > 0) {\n";
+        out << "  if (!Dtool_CheckNoArgs(args)) {\n";
         out << "    const int parameter_count = (int)PyTuple_GET_SIZE(args);\n";
         out << "    const int parameter_count = (int)PyTuple_GET_SIZE(args);\n";
         break;
         break;
       case AT_single_arg:
       case AT_single_arg:
@@ -3607,14 +3660,14 @@ write_function_for_name(ostream &out, Object *obj,
     } else if (args_type == AT_keyword_args && max_required_args == 1 && mii->first == 1) {
     } else if (args_type == AT_keyword_args && max_required_args == 1 && mii->first == 1) {
       // Check this to be sure, as we handle the case of only 1 keyword arg in
       // Check this to be sure, as we handle the case of only 1 keyword arg in
       // write_function_forset (not using ParseTupleAndKeywords).
       // write_function_forset (not using ParseTupleAndKeywords).
-      out << "    int parameter_count = (int)PyTuple_Size(args);\n"
-             "    if (kwds != NULL) {\n"
-             "      parameter_count += (int)PyDict_Size(kwds);\n"
-             "    }\n"
+      out << "  int parameter_count = (int)PyTuple_Size(args);\n"
+             "  if (kwds != NULL) {\n"
+             "    parameter_count += (int)PyDict_Size(kwds);\n"
+             "  }\n"
              "  if (parameter_count != 1) {\n"
              "  if (parameter_count != 1) {\n"
              "#ifdef NDEBUG\n";
              "#ifdef NDEBUG\n";
       error_raise_return(out, 4, return_flags, "TypeError",
       error_raise_return(out, 4, return_flags, "TypeError",
-                         "function takes exactly 1 argument");
+                        "function takes exactly 1 argument");
       out << "#else\n";
       out << "#else\n";
       error_raise_return(out, 4, return_flags, "TypeError",
       error_raise_return(out, 4, return_flags, "TypeError",
         methodNameFromCppName(remap, "", false) + "() takes exactly 1 argument (%d given)",
         methodNameFromCppName(remap, "", false) + "() takes exactly 1 argument (%d given)",
@@ -4067,7 +4120,9 @@ int get_type_sort(CPPType *type) {
 // printf("    %s\n",type->get_local_name().c_str());
 // printf("    %s\n",type->get_local_name().c_str());
 
 
   // The highest numbered one will be checked first.
   // The highest numbered one will be checked first.
-  if (TypeManager::is_pointer_to_Py_buffer(type)) {
+  if (TypeManager::is_nullptr(type)) {
+    return 15;
+  } else if (TypeManager::is_pointer_to_Py_buffer(type)) {
     return 14;
     return 14;
   } else if (TypeManager::is_pointer_to_PyTypeObject(type)) {
   } else if (TypeManager::is_pointer_to_PyTypeObject(type)) {
     return 13;
     return 13;
@@ -4247,14 +4302,16 @@ write_function_forset(ostream &out,
       args_type == AT_keyword_args) {
       args_type == AT_keyword_args) {
     sii = remapsin.begin();
     sii = remapsin.begin();
     remap = (*sii);
     remap = (*sii);
-    first_param_name = remap->_parameters[(int)remap->_has_this]._name;
-    same_first_param = true;
+    if (remap->_parameters[(int)remap->_has_this]._has_name) {
+      first_param_name = remap->_parameters[(int)remap->_has_this]._name;
+      same_first_param = true;
 
 
-    for (++sii; sii != remapsin.end(); ++sii) {
-      remap = (*sii);
-      if (remap->_parameters[(int)remap->_has_this]._name != first_param_name) {
-        same_first_param = false;
-        break;
+      for (++sii; sii != remapsin.end(); ++sii) {
+        remap = (*sii);
+        if (remap->_parameters[(int)remap->_has_this]._name != first_param_name) {
+          same_first_param = false;
+          break;
+        }
       }
       }
     }
     }
   }
   }
@@ -4263,21 +4320,9 @@ write_function_forset(ostream &out,
     // Yes, they all have the same argument name (or there is only one remap).
     // Yes, they all have the same argument name (or there is only one remap).
     // Extract it from the dict so we don't have to call
     // Extract it from the dict so we don't have to call
     // ParseTupleAndKeywords.
     // ParseTupleAndKeywords.
-    indent(out, indent_level) << "PyObject *arg = NULL;\n";
-    indent(out, indent_level) << "if (PyTuple_GET_SIZE(args) == 1) {\n";
-    indent(out, indent_level) << "  arg = PyTuple_GET_ITEM(args, 0);\n";
-    indent(out, indent_level) << "} else if (kwds != NULL) {\n";
-    indent(out, indent_level) << "  arg = PyDict_GetItemString(kwds, \"" << first_param_name << "\");\n";
-    indent(out, indent_level) << "}\n";
-    if (report_errors) {
-      indent(out, indent_level) << "if (arg == (PyObject *)NULL) {\n";
-      error_raise_return(out, indent_level + 2, return_flags, "TypeError",
-        "Required argument '" + first_param_name + "' (pos 1) not found");
-      indent(out, indent_level) << "}\n";
-    } else {
-      indent(out, indent_level) << "if (arg != (PyObject *)NULL) {\n";
-      indent_level += 2;
-    }
+    indent(out, indent_level) << "PyObject *arg;\n";
+    indent(out, indent_level) << "if (Dtool_ExtractArg(&arg, args, kwds, \"" << first_param_name << "\")) {\n";
+    indent_level += 2;
     args_type = AT_single_arg;
     args_type = AT_single_arg;
   }
   }
 
 
@@ -4448,7 +4493,7 @@ write_function_forset(ostream &out,
   }
   }
 
 
   // Close the brace we opened earlier.
   // Close the brace we opened earlier.
-  if (same_first_param && !report_errors) {
+  if (same_first_param) {
     indent_level -= 2;
     indent_level -= 2;
     indent(out, indent_level) << "}\n";
     indent(out, indent_level) << "}\n";
   }
   }
@@ -4517,6 +4562,8 @@ write_function_instance(ostream &out, FunctionRemap *remap,
   string parameter_list;
   string parameter_list;
   string container;
   string container;
   string type_check;
   string type_check;
+  string param_name;
+  bool has_keywords = false;
   vector_string pexprs;
   vector_string pexprs;
   LineStream extra_convert;
   LineStream extra_convert;
   ostringstream extra_param_check;
   ostringstream extra_param_check;
@@ -4612,7 +4659,7 @@ write_function_instance(ostream &out, FunctionRemap *remap,
     CPPType *orig_type = param->get_orig_type();
     CPPType *orig_type = param->get_orig_type();
     CPPType *type = param->get_new_type();
     CPPType *type = param->get_new_type();
     CPPExpression *default_value = param->get_default_value();
     CPPExpression *default_value = param->get_default_value();
-    string param_name = remap->get_parameter_name(pn);
+    param_name = remap->get_parameter_name(pn);
 
 
     if (!is_cpp_type_legal(orig_type)) {
     if (!is_cpp_type_legal(orig_type)) {
       // We can't wrap this.  We sometimes get here for default arguments.
       // We can't wrap this.  We sometimes get here for default arguments.
@@ -4667,7 +4714,14 @@ write_function_instance(ostream &out, FunctionRemap *remap,
     }
     }
 
 
     string reported_name = remap->_parameters[pn]._name;
     string reported_name = remap->_parameters[pn]._name;
-    keyword_list += "\"" + reported_name + "\", ";
+    if (!keyword_list.empty()) {
+      keyword_list += ", \"" + reported_name + "\"";
+    } else {
+      keyword_list = "\"" + reported_name + "\"";
+    }
+    if (remap->_parameters[pn]._has_name) {
+      has_keywords = true;
+    }
 
 
     if (param->new_type_is_atomic_string()) {
     if (param->new_type_is_atomic_string()) {
 
 
@@ -4869,6 +4923,19 @@ write_function_instance(ostream &out, FunctionRemap *remap,
       pexpr_string = "(PyObject_IsTrue(" + param_name + ") != 0)";
       pexpr_string = "(PyObject_IsTrue(" + param_name + ") != 0)";
       expected_params += "bool";
       expected_params += "bool";
 
 
+    } else if (TypeManager::is_nullptr(type)) {
+      if (args_type == AT_single_arg) {
+        type_check = "arg == Py_None";
+        param_name = "arg";
+      } else {
+        indent(out, indent_level) << "PyObject *" << param_name << default_expr << ";\n";
+        extra_param_check << " && " << param_name << " == Py_None";
+        format_specifiers += "O";
+        parameter_list += ", &" + param_name;
+      }
+      pexpr_string = "NULL";
+      expected_params += "NoneType";
+
     } else if (TypeManager::is_char(type)) {
     } else if (TypeManager::is_char(type)) {
       indent(out, indent_level) << "char " << param_name << default_expr << ";\n";
       indent(out, indent_level) << "char " << param_name << default_expr << ";\n";
 
 
@@ -4907,26 +4974,42 @@ write_function_instance(ostream &out, FunctionRemap *remap,
       only_pyobjects = false;
       only_pyobjects = false;
 
 
     } else if (TypeManager::is_size(type)) {
     } else if (TypeManager::is_size(type)) {
-      // It certainly isn't the exact same thing as size_t, but Py_ssize_t
-      // should at least be the same size.  The problem with mapping this to
-      // unsigned int is that that doesn't work well on 64-bit systems, on
-      // which size_t is a 64-bit integer.
-      indent(out, indent_level) << "Py_ssize_t " << param_name << default_expr << ";\n";
-      format_specifiers += "n";
-      parameter_list += ", &" + param_name;
-      expected_params += "int";
-      only_pyobjects = false;
+      if (args_type == AT_single_arg) {
+        type_check = "PyLongOrInt_Check(arg)";
 
 
-      extra_convert
-        << "#ifndef NDEBUG\n"
-        << "if (" << param_name << " < 0) {\n";
+        extra_convert <<
+          "size_t arg_val = PyLongOrInt_AsSize_t(arg);\n"
+          "#ifndef NDEBUG\n"
+          "if (arg_val == (size_t)-1 && _PyErr_OCCURRED()) {\n";
+        error_return(extra_convert, 2, return_flags);
+        extra_convert <<
+          "}\n"
+          "#endif\n";
 
 
-      error_raise_return(extra_convert, 2, return_flags, "OverflowError",
-                         "can't convert negative value %zd to size_t",
-                         param_name);
-      extra_convert
-        << "}\n"
-        << "#endif\n";
+        pexpr_string = "arg_val";
+
+      } else {
+        // It certainly isn't the exact same thing as size_t, but Py_ssize_t
+        // should at least be the same size.  The problem with mapping this to
+        // unsigned int is that that doesn't work well on 64-bit systems, on
+        // which size_t is a 64-bit integer.
+        indent(out, indent_level) << "Py_ssize_t " << param_name << default_expr << ";\n";
+        format_specifiers += "n";
+        parameter_list += ", &" + param_name;
+
+        extra_convert
+          << "#ifndef NDEBUG\n"
+          << "if (" << param_name << " < 0) {\n";
+
+        error_raise_return(extra_convert, 2, return_flags, "OverflowError",
+                          "can't convert negative value %zd to size_t",
+                          param_name);
+        extra_convert
+          << "}\n"
+          << "#endif\n";
+      }
+      expected_params += "int";
+      only_pyobjects = false;
 
 
     } else if (TypeManager::is_longlong(type)) {
     } else if (TypeManager::is_longlong(type)) {
       // It's not trivial to do overflow checking for a long long, so we
       // It's not trivial to do overflow checking for a long long, so we
@@ -5555,15 +5638,60 @@ write_function_instance(ostream &out, FunctionRemap *remap,
     switch (args_type) {
     switch (args_type) {
     case AT_keyword_args:
     case AT_keyword_args:
       // Wrapper takes a varargs tuple and a keyword args dict.
       // Wrapper takes a varargs tuple and a keyword args dict.
-      indent(out, indent_level)
-        << "static const char *keyword_list[] = {" << keyword_list << "NULL};\n";
-      indent(out, indent_level)
-        << "if (PyArg_ParseTupleAndKeywords(args, kwds, \""
-        << format_specifiers << ":" << method_name
-        << "\", (char **)keyword_list" << parameter_list << ")) {\n";
+      if (has_keywords) {
+        if (only_pyobjects && max_num_args == 1) {
+          // But we are only expecting one object arg, which is an easy common
+          // case we have implemented ourselves.
+          if (min_num_args == 1) {
+            indent(out, indent_level)
+              << "if (Dtool_ExtractArg(&" << param_name << ", args, kwds, " << keyword_list << ")) {\n";
+          } else {
+            indent(out, indent_level)
+              << "if (Dtool_ExtractOptionalArg(&" << param_name << ", args, kwds, " << keyword_list << ")) {\n";
+          }
+        } else {
+          // We have to use the more expensive PyArg_ParseTupleAndKeywords.
+          clear_error = true;
+          indent(out, indent_level)
+            << "static const char *keyword_list[] = {" << keyword_list << ", NULL};\n";
+          indent(out, indent_level)
+            << "if (PyArg_ParseTupleAndKeywords(args, kwds, \""
+            << format_specifiers << ":" << method_name
+            << "\", (char **)keyword_list" << parameter_list << ")) {\n";
+        }
+
+      } else if (only_pyobjects) {
+        // This function actually has no named parameters, so let's not take
+        // any keyword arguments.
+        if (max_num_args == 1) {
+          if (min_num_args == 1) {
+            indent(out, indent_level)
+              << "if (Dtool_ExtractArg(&" << param_name << ", args, kwds)) {\n";
+          } else {
+            indent(out, indent_level)
+              << "if (Dtool_ExtractOptionalArg(&" << param_name << ", args, kwds)) {\n";
+          }
+        } else if (max_num_args == 0) {
+          indent(out, indent_level)
+            << "if (Dtool_CheckNoArgs(args, kwds)) {\n";
+        } else {
+          clear_error = true;
+          indent(out, indent_level)
+            << "if ((kwds == NULL || PyDict_Size(kwds) == 0) && PyArg_UnpackTuple(args, \""
+            << methodNameFromCppName(remap, "", false)
+            << "\", " << min_num_args << ", " << max_num_args
+            << parameter_list << ")) {\n";
+        }
+
+      } else {
+        clear_error = true;
+        indent(out, indent_level)
+          << "if ((kwds == NULL || PyDict_Size(kwds) == 0) && PyArg_ParseTuple(args, \""
+          << format_specifiers << ":" << method_name
+          << "\"" << parameter_list << ")) {\n";
+      }
 
 
       ++open_scopes;
       ++open_scopes;
-      clear_error = true;
       indent_level += 2;
       indent_level += 2;
       break;
       break;
 
 
@@ -5572,20 +5700,28 @@ write_function_instance(ostream &out, FunctionRemap *remap,
       if (only_pyobjects) {
       if (only_pyobjects) {
         // All parameters are PyObject*, so we can use the slightly more
         // All parameters are PyObject*, so we can use the slightly more
         // efficient PyArg_UnpackTuple function instead.
         // efficient PyArg_UnpackTuple function instead.
-        indent(out, indent_level)
-          << "if (PyArg_UnpackTuple(args, \""
-          << methodNameFromCppName(remap, "", false)
-          << "\", " << min_num_args << ", " << max_num_args
-          << parameter_list << ")) {\n";
+        if (min_num_args == 1 && max_num_args == 1) {
+          indent(out, indent_level)
+            << "if (PyTuple_GET_SIZE(args) == 1) {\n";
+          indent(out, indent_level + 2)
+            << param_name << " = PyTuple_GET_ITEM(args, 0);\n";
+        } else {
+          clear_error = true;
+          indent(out, indent_level)
+            << "if (PyArg_UnpackTuple(args, \""
+            << methodNameFromCppName(remap, "", false)
+            << "\", " << min_num_args << ", " << max_num_args
+            << parameter_list << ")) {\n";
+        }
 
 
       } else {
       } else {
+        clear_error = true;
         indent(out, indent_level)
         indent(out, indent_level)
           << "if (PyArg_ParseTuple(args, \""
           << "if (PyArg_ParseTuple(args, \""
           << format_specifiers << ":" << method_name
           << format_specifiers << ":" << method_name
           << "\"" << parameter_list << ")) {\n";
           << "\"" << parameter_list << ")) {\n";
       }
       }
       ++open_scopes;
       ++open_scopes;
-      clear_error = true;
       indent_level += 2;
       indent_level += 2;
       break;
       break;
 
 

+ 8 - 0
dtool/src/interrogate/interrogateBuilder.cxx

@@ -1966,6 +1966,10 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
   // See if there happens to be a comment before the MAKE_PROPERTY macro.
   // See if there happens to be a comment before the MAKE_PROPERTY macro.
   if (make_property->_leading_comment != (CPPCommentBlock *)NULL) {
   if (make_property->_leading_comment != (CPPCommentBlock *)NULL) {
     iproperty._comment = trim_blanks(make_property->_leading_comment->_comment);
     iproperty._comment = trim_blanks(make_property->_leading_comment->_comment);
+
+  } else if (getter->_leading_comment != (CPPCommentBlock *)NULL) {
+    // Take the comment from the getter.
+    iproperty._comment = trim_blanks(getter->_leading_comment->_comment);
   }
   }
 
 
   // Now look for setters.
   // Now look for setters.
@@ -2346,6 +2350,10 @@ define_atomic_type(InterrogateType &itype, CPPSimpleType *cpptype) {
     itype._atomic_token = AT_void;
     itype._atomic_token = AT_void;
     break;
     break;
 
 
+  case CPPSimpleType::T_nullptr:
+    itype._atomic_token = AT_null;
+    break;
+
   default:
   default:
     nout << "Type \"" << *cpptype << "\" has invalid CPPSimpleType: "
     nout << "Type \"" << *cpptype << "\" has invalid CPPSimpleType: "
          << (int)cpptype->_type << "\n";
          << (int)cpptype->_type << "\n";

+ 21 - 0
dtool/src/interrogate/typeManager.cxx

@@ -364,6 +364,27 @@ is_const_ref_to_enum(CPPType *type) {
   }
   }
 }
 }
 
 
+/**
+ * Returns true if the indicated type is nullptr_t, possibly const or a
+ * typedef to it.
+ */
+bool TypeManager::
+is_nullptr(CPPType *type) {
+  switch (type->get_subtype()) {
+  case CPPDeclaration::ST_simple:
+    return type->as_simple_type()->_type == CPPSimpleType::T_nullptr;
+
+  case CPPDeclaration::ST_const:
+    return is_nullptr(type->as_const_type()->_wrapped_around);
+
+  case CPPDeclaration::ST_typedef:
+    return is_nullptr(type->as_typedef_type()->_type);
+
+  default:
+    return false;
+  }
+}
+
 /**
 /**
  * Returns true if the indicated type is something that a scripting language
  * Returns true if the indicated type is something that a scripting language
  * can handle directly as a concrete, like an int or float, either const or
  * can handle directly as a concrete, like an int or float, either const or

Some files were not shown because too many files changed in this diff