Ver Fonte

Merge branch 'master' into webgl-port

rdb há 8 anos atrás
pai
commit
d7f0f82859
100 ficheiros alterados com 1510 adições e 1026 exclusões
  1. 5 0
      .gitignore
  2. 9 2
      .travis.yml
  3. 22 0
      README.md
  4. 94 0
      direct/src/actor/Actor.py
  5. 7 0
      direct/src/actor/__init__.py
  6. 13 0
      direct/src/controls/InputState.py
  7. 4 0
      direct/src/controls/__init__.py
  8. 16 1
      direct/src/directbase/DirectStart.py
  9. 12 0
      direct/src/directbase/__init__.py
  10. 51 28
      direct/src/directdevices/DirectDeviceManager.py
  11. 1 1
      direct/src/directdevices/DirectRadamec.py
  12. 5 0
      direct/src/directdevices/__init__.py
  13. 3 0
      direct/src/directnotify/__init__.py
  14. 8 0
      direct/src/directtools/__init__.py
  15. 3 0
      direct/src/directutil/__init__.py
  16. 8 6
      direct/src/distributed/DistributedSmoothNode.py
  17. 5 0
      direct/src/distributed/__init__.py
  18. 4 1
      direct/src/extensions_native/__init__.py
  19. 21 0
      direct/src/filter/CommonFilters.py
  20. 12 0
      direct/src/filter/FilterManager.py
  21. 11 0
      direct/src/filter/__init__.py
  22. 3 2
      direct/src/filter/filter-bloomx.sha
  23. 3 2
      direct/src/filter/filter-bloomy.sha
  24. 6 4
      direct/src/filter/filter-blurx.sha
  25. 6 4
      direct/src/filter/filter-blury.sha
  26. 6 6
      direct/src/fsm/ClassicFSM.py
  27. 1 1
      direct/src/fsm/FSM.py
  28. 2 4
      direct/src/fsm/FourState.py
  29. 2 4
      direct/src/fsm/FourStateAI.py
  30. 6 0
      direct/src/fsm/__init__.py
  31. 1 1
      direct/src/gui/DirectButton.py
  32. 3 1
      direct/src/gui/DirectCheckButton.py
  33. 1 1
      direct/src/gui/DirectDialog.py
  34. 2 1
      direct/src/gui/DirectEntry.py
  35. 14 9
      direct/src/gui/DirectFrame.py
  36. 24 25
      direct/src/gui/DirectGuiBase.py
  37. 3 5
      direct/src/gui/DirectGuiGlobals.py
  38. 1 1
      direct/src/gui/DirectLabel.py
  39. 1 1
      direct/src/gui/DirectOptionMenu.py
  40. 4 1
      direct/src/gui/DirectRadioButton.py
  41. 1 1
      direct/src/gui/DirectScrollBar.py
  42. 1 1
      direct/src/gui/DirectScrolledFrame.py
  43. 1 1
      direct/src/gui/DirectScrolledList.py
  44. 1 1
      direct/src/gui/DirectSlider.py
  45. 1 1
      direct/src/gui/DirectWaitBar.py
  46. 16 1
      direct/src/gui/OnscreenText.py
  47. 12 0
      direct/src/gui/__init__.py
  48. 4 1
      direct/src/interval/IntervalGlobal.py
  49. 3 3
      direct/src/interval/IntervalManager.py
  50. 4 1
      direct/src/interval/MetaInterval.py
  51. 2 4
      direct/src/interval/ParticleInterval.py
  52. 3 5
      direct/src/interval/TestInterval.py
  53. 12 0
      direct/src/interval/__init__.py
  54. 3 0
      direct/src/motiontrail/__init__.py
  55. 5 2
      direct/src/p3d/AppRunner.py
  56. 4 0
      direct/src/p3d/__init__.py
  57. 7 0
      direct/src/particles/__init__.py
  58. 2 0
      direct/src/showbase/AppRunnerGlobal.py
  59. 25 1
      direct/src/showbase/Audio3DManager.py
  60. 3 1
      direct/src/showbase/BufferViewer.py
  61. 1 1
      direct/src/showbase/BulletinBoard.py
  62. 1 1
      direct/src/showbase/BulletinBoardWatcher.py
  63. 14 1
      direct/src/showbase/DirectObject.py
  64. 1 1
      direct/src/showbase/EventGroup.py
  65. 2 1
      direct/src/showbase/EventManager.py
  66. 2 1
      direct/src/showbase/EventManagerGlobal.py
  67. 1 1
      direct/src/showbase/Factory.py
  68. 2 4
      direct/src/showbase/FindCtaPaths.py
  69. 1 1
      direct/src/showbase/Finder.py
  70. 1 1
      direct/src/showbase/GarbageReport.py
  71. 15 3
      direct/src/showbase/Messenger.py
  72. 2 4
      direct/src/showbase/MirrorDemo.py
  73. 1 1
      direct/src/showbase/ObjectPool.py
  74. 10 12
      direct/src/showbase/ObjectReport.py
  75. 1 1
      direct/src/showbase/OnScreenDebug.py
  76. 7 10
      direct/src/showbase/Pool.py
  77. 2 4
      direct/src/showbase/SfxPlayer.py
  78. 2 5
      direct/src/showbase/ShadowDemo.py
  79. 2 4
      direct/src/showbase/ShadowPlacer.py
  80. 4 1
      direct/src/showbase/TaskThreaded.py
  81. 2 1
      direct/src/showbase/ThreeUpShow.py
  82. 3 1
      direct/src/showbase/Transitions.py
  83. 4 1
      direct/src/showbase/VerboseImport.py
  84. 90 83
      direct/src/showutil/pfreeze.py
  85. 5 0
      direct/src/stdpy/__init__.py
  86. 35 11
      direct/src/stdpy/thread.py
  87. 33 11
      direct/src/stdpy/threading.py
  88. 43 26
      direct/src/stdpy/threading2.py
  89. 1 0
      direct/src/task/TaskManagerGlobal.py
  90. 4 3
      direct/src/task/TaskTester.py
  91. 1 1
      direct/src/task/Timer.py
  92. 8 0
      direct/src/task/__init__.py
  93. 1 1
      direct/src/tkpanels/NotifyPanel.py
  94. 4 1
      direct/src/tkwidgets/SceneGraphExplorer.py
  95. 1 1
      direct/src/tkwidgets/Tree.py
  96. 1 1
      direct/src/tkwidgets/WidgetPropertiesDialog.py
  97. 671 683
      dtool/src/cppparser/cppBison.cxx.prebuilt
  98. 15 2
      dtool/src/cppparser/cppBison.yxx
  99. 2 2
      dtool/src/dtoolbase/deletedBufferChain.cxx
  100. 1 3
      dtool/src/dtoolbase/dtool_platform.h

+ 5 - 0
.gitignore

@@ -8,6 +8,7 @@
 core
 core.*
 vgcore.*
+*.core
 
 # Editor files/directories
 *.save
@@ -22,6 +23,9 @@ vgcore.*
 *.o
 *.gch
 *.pch
+/+DESC
+/+MANIFEST
+/pkg-plist
 
 # Produced installer/executables
 /*.exe
@@ -31,6 +35,7 @@ vgcore.*
 /*.pkg
 /*.dmg
 /*.whl
+/*.txz
 
 # CMake
 /build/

+ 9 - 2
.travis.yml

@@ -2,15 +2,22 @@ language: cpp
 sudo: false
 matrix:
   include:
-    - compiler: gcc
-      env: PYTHONV=python2.7 FLAGS=--optimize=4
     - compiler: clang
       env: PYTHONV=python3 FLAGS=--installer
     - compiler: clang
       env: PYTHONV=python2.7 FLAGS=--override=STDFLOAT_DOUBLE=1
+    - compiler: gcc
+      env: PYTHONV=python2.7 FLAGS=--optimize=4
+      before_install:
+        - export CC=gcc-4.7
+        - export CXX=g++-4.7
 addons:
   apt:
+    sources:
+    - ubuntu-toolchain-r-test
     packages:
+    - gcc-4.7
+    - g++-4.7
     - bison
     - flex
     - libfreetype6-dev

+ 22 - 0
README.md

@@ -134,6 +134,28 @@ If the build was successful, makepanda will have generated a .dmg file in
 the source directory containing the installer.  Simply open it and run the
 package file in order to install the SDK onto your system.
 
+FreeBSD
+-------
+
+Building on FreeBSD is very similar to building on Linux.  You will need to
+install the requisite packages using the system package manager.  To install
+the recommended set of dependencies, you can use this command:
+
+```bash
+pkg install pkgconf png jpeg-turbo tiff freetype2 eigen squish openal opusfile libvorbis libX11 libGL ode bullet assimp openexr
+```
+
+You will also need to choose which version of Python you want to use.
+Install the appropriate package for it (such as `python2` or `python36`) and
+run the makepanda script with your chosen Python version:
+
+```bash
+python3.6 makepanda/makepanda.py --everything --installer --no-egl --no-gles --no-gles2
+```
+
+If successful, this will produce a .pkg file in the root of the source
+directory which you can install using `pkg install`.
+
 Reporting Issues
 ================
 

+ 94 - 0
direct/src/actor/Actor.py

@@ -50,6 +50,10 @@ class Actor(DirectObject, NodePath):
         def __repr__(self):
             return 'Actor.PartDef(%s, %s)' % (repr(self.partBundleNP), repr(self.partModel))
 
+
+        #snake_case alias:
+        get_bundle = getBundle
+
     class AnimDef:
 
         """Instances of this class are stored within the
@@ -72,6 +76,10 @@ class Actor(DirectObject, NodePath):
         def __repr__(self):
             return 'Actor.AnimDef(%s)' % (repr(self.filename))
 
+
+        #snake_case alias:
+        make_copy = makeCopy
+
     class SubpartDef:
 
         """Instances of this class are stored within the SubpartDict
@@ -2549,3 +2557,89 @@ class Actor(DirectObject, NodePath):
         for partBundleDict in self.__partBundleDict.values():
             partDef = partBundleDict.get(subpartDef.truePartName)
             partDef.getBundle().setName(newBundleName)
+
+    #snake_case alias:
+    control_joint = controlJoint
+    set_lod_animation = setLODAnimation
+    get_anim_control_dict = getAnimControlDict
+    get_actor_info = getActorInfo
+    clear_lod_animation = clearLODAnimation
+    reset_lod = resetLOD
+    fix_bounds = fixBounds
+    get_anim_filename = getAnimFilename
+    get_subparts_complete = getSubpartsComplete
+    verify_subparts_complete = verifySubpartsComplete
+    get_play_rate = getPlayRate
+    clear_python_data = clearPythonData
+    load_anims = loadAnims
+    set_subparts_complete = setSubpartsComplete
+    draw_in_front = drawInFront
+    get_lod_node = getLODNode
+    hide_part = hidePart
+    get_joint_transform_state = getJointTransformState
+    set_control_effect = setControlEffect
+    get_anim_controls = getAnimControls
+    release_joint = releaseJoint
+    print_anim_blends = printAnimBlends
+    get_lod = getLOD
+    disable_blend = disableBlend
+    show_part = showPart
+    get_joint_transform = getJointTransform
+    face_away_from_viewer = faceAwayFromViewer
+    set_lod = setLOD
+    osd_anim_blends = osdAnimBlends
+    get_current_frame = getCurrentFrame
+    set_play_rate = setPlayRate
+    bind_all_anims = bindAllAnims
+    unload_anims = unloadAnims
+    remove_part = removePart
+    use_lod = useLOD
+    get_anim_blends = getAnimBlends
+    get_lod_index = getLODIndex
+    get_num_frames = getNumFrames
+    post_flatten = postFlatten
+    get_lod_names = getLODNames
+    list_joints = listJoints
+    make_subpart = makeSubpart
+    get_anim_control = getAnimControl
+    get_part_bundle = getPartBundle
+    get_part_bundle_dict = getPartBundleDict
+    get_duration = getDuration
+    has_lod = hasLOD
+    print_lod = printLOD
+    fix_bounds_old = fixBounds_old
+    get_anim_names = getAnimNames
+    get_part_bundles = getPartBundles
+    anim_panel = animPanel
+    stop_joint = stopJoint
+    actor_interval = actorInterval
+    hide_all_bounds = hideAllBounds
+    show_all_bounds = showAllBounds
+    init_anims_on_all_lods = initAnimsOnAllLODs
+    get_part = getPart
+    add_lod = addLOD
+    show_all_parts = showAllParts
+    get_joints = getJoints
+    get_overlapping_joints = getOverlappingJoints
+    enable_blend = enableBlend
+    face_towards_viewer = faceTowardsViewer
+    bind_anim = bindAnim
+    set_blend = setBlend
+    get_frame_time = getFrameTime
+    remove_node = removeNode
+    wait_pending = waitPending
+    expose_joint = exposeJoint
+    set_lod_node = setLODNode
+    get_frame_rate = getFrameRate
+    get_current_anim = getCurrentAnim
+    get_part_names = getPartNames
+    freeze_joint = freezeJoint
+    set_center = setCenter
+    rename_part_bundles = renamePartBundles
+    get_geom_node = getGeomNode
+    set_geom_node = setGeomNode
+    load_model = loadModel
+    copy_actor = copyActor
+    get_base_frame_rate = getBaseFrameRate
+    remove_anim_control_dict = removeAnimControlDict
+    load_anims_on_all_lods = loadAnimsOnAllLODs

+ 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.
+"""

+ 13 - 0
direct/src/controls/InputState.py

@@ -21,6 +21,9 @@ class InputStateToken:
     def __hash__(self):
         return self._hash
 
+    #snake_case alias:
+    is_valid = isValid
+
 class InputStateWatchToken(InputStateToken, DirectObject.DirectObject):
     def release(self):
         self._inputState._ignore(self)
@@ -39,6 +42,9 @@ class InputStateTokenGroup:
             token.release()
         self._tokens = []
 
+    #snake_case alias:
+    add_token = addToken
+
 class InputState(DirectObject.DirectObject):
     """
     InputState is for tracking the on/off state of some events.
@@ -235,3 +241,10 @@ class InputState(DirectObject.DirectObject):
         """for debugging"""
         return self.notify.debug(
             "%s (%s) %s"%(id(self), len(self._state), message))
+
+    #snake_case alias:
+    watch_with_modifiers = watchWithModifiers
+    is_set = isSet
+    get_event_name = getEventName
+    debug_print = debugPrint
+    release_inputs = releaseInputs

+ 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__ = []
 

+ 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_CENTER = 0.0
 
-try:
-    myBase = base
-except:
-    myBase = simbase
 
 class DirectDeviceManager(VrpnClient, DirectObject):
     def __init__(self, server = None):
@@ -52,8 +48,13 @@ class DirectButtons(ButtonNode, DirectObject):
         ButtonNode.__init__(self, vrpnClient, device)
         # Create a unique name for this button object
         self.name = 'DirectButtons-' + repr(DirectButtons.buttonCount)
+
         # 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):
         if (index < 0) or (index >= self.getNumButtons()):
@@ -64,10 +65,10 @@ class DirectButtons(ButtonNode, DirectObject):
         return self.getNumButtons()
 
     def enable(self):
-        self.nodePath.reparentTo(myBase.dataRoot)
+        self.nodePath.reparentTo(self._base.dataRoot)
 
     def disable(self):
-        self.nodePath.reparentTo(myBase.dataUnused)
+        self.nodePath.reparentTo(self._base.dataUnused)
 
     def getName(self):
         return self.name
@@ -83,6 +84,12 @@ class DirectButtons(ButtonNode, DirectObject):
 
 class DirectAnalogs(AnalogNode, DirectObject):
     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):
         # Keep track of number of analogs created
         DirectAnalogs.analogCount += 1
@@ -90,20 +97,21 @@ class DirectAnalogs(AnalogNode, DirectObject):
         AnalogNode.__init__(self, vrpnClient, device)
         # Create a unique name for this analog object
         self.name = 'DirectAnalogs-' + repr(DirectAnalogs.analogCount)
+
         # 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
-        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
 
-
     def __getitem__(self, index):
         if (index < 0) or (index >= self.getNumControls()):
             raise IndexError
@@ -113,10 +121,10 @@ class DirectAnalogs(AnalogNode, DirectObject):
         return self.getNumControls()
 
     def enable(self):
-        self.nodePath.reparentTo(myBase.dataRoot)
+        self.nodePath.reparentTo(self._base.dataRoot)
 
     def disable(self):
-        self.nodePath.reparentTo(myBase.dataUnused)
+        self.nodePath.reparentTo(self._base.dataUnused)
 
     def normalizeWithoutCentering(self, val, minVal = -1, maxVal = 1):
         #
@@ -186,14 +194,19 @@ class DirectTracker(TrackerNode, DirectObject):
         TrackerNode.__init__(self, vrpnClient, device)
         # Create a unique name for this tracker object
         self.name = 'DirectTracker-' + repr(DirectTracker.trackerCount)
+
         # 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):
-        self.nodePath.reparentTo(myBase.dataRoot)
+        self.nodePath.reparentTo(self._base.dataRoot)
 
     def disable(self):
-        self.nodePath.reparentTo(myBase.dataUnused)
+        self.nodePath.reparentTo(self._base.dataUnused)
 
     def getName(self):
         return self.name
@@ -213,8 +226,13 @@ class DirectDials(DialNode, DirectObject):
         DialNode.__init__(self, vrpnClient, device)
         # Create a unique name for this dial object
         self.name = 'DirectDials-' + repr(DirectDials.dialCount)
+
         # 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):
         """
@@ -227,10 +245,10 @@ class DirectDials(DialNode, DirectObject):
         return self.getNumDials()
 
     def enable(self):
-        self.nodePath.reparentTo(myBase.dataRoot)
+        self.nodePath.reparentTo(self._base.dataRoot)
 
     def disable(self):
-        self.nodePath.reparentTo(myBase.dataUnused)
+        self.nodePath.reparentTo(self._base.dataUnused)
 
     def getName(self):
         return self.name
@@ -259,14 +277,19 @@ class DirectTimecodeReader(AnalogNode, DirectObject):
         self.seconds = 0
         self.minutes = 0
         self.hours = 0
+
         # 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):
-        self.nodePath.reparentTo(myBase.dataRoot)
+        self.nodePath.reparentTo(self._base.dataRoot)
 
     def disable(self):
-        self.nodePath.reparentTo(myBase.dataUnused)
+        self.nodePath.reparentTo(self._base.dataUnused)
 
     def getName(self):
         return self.name

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

@@ -21,7 +21,7 @@ class DirectRadamec(DirectObject):
     radamecCount = 0
     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
         if base.direct.deviceManager == None:
             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 direct.task.Task import cont
 
+config = get_config_showbase()
+
 # This number defines our tolerance for out-of-sync telemetry packets.
 # If a packet appears to have originated from more than MaxFuture
 # seconds in the future, assume we're out of sync with the other
 # 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?
-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
 # 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
 # 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
 # each avatar, which is intended to compensate for relative clock
 # 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

+ 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.
+"""

+ 21 - 0
direct/src/filter/CommonFilters.py

@@ -536,3 +536,24 @@ class CommonFilters:
             del self.configuration["GammaAdjust"]
             return self.reconfigure((old_gamma != 1.0), "GammaAdjust")
         return True
+
+    #snake_case alias:
+    del_cartoon_ink = delCartoonInk
+    set_half_pixel_shift = setHalfPixelShift
+    del_half_pixel_shift = delHalfPixelShift
+    set_inverted = setInverted
+    del_inverted = delInverted
+    del_view_glow = delViewGlow
+    set_volumetric_lighting = setVolumetricLighting
+    del_gamma_adjust = delGammaAdjust
+    set_bloom = setBloom
+    set_view_glow = setViewGlow
+    set_ambient_occlusion = setAmbientOcclusion
+    set_cartoon_ink = setCartoonInk
+    del_bloom = delBloom
+    del_ambient_occlusion = delAmbientOcclusion
+    load_shader = loadShader
+    set_blur_sharpen = setBlurSharpen
+    del_blur_sharpen = delBlurSharpen
+    del_volumetric_lighting = delVolumetricLighting
+    set_gamma_adjust = setGammaAdjust

+ 12 - 0
direct/src/filter/FilterManager.py

@@ -349,3 +349,15 @@ class FilterManager(DirectObject):
         self.nextsort = self.win.getSort() - 1000
         self.basex = 0
         self.basey = 0
+
+    #snake_case alias:
+    is_fullscreen = isFullscreen
+    resize_buffers = resizeBuffers
+    set_stacked_clears = setStackedClears
+    render_scene_into = renderSceneInto
+    get_scaled_size = getScaledSize
+    render_quad_into = renderQuadInto
+    get_clears = getClears
+    set_clears = setClears
+    create_buffer = createBuffer
+    window_event = windowEvent

+ 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.
+"""

+ 3 - 2
direct/src/filter/filter-bloomx.sha

@@ -12,8 +12,9 @@ void vshader(float4 vtx_position : POSITION,
   l_position=mul(mat_modelproj, vtx_position);
   float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy;
   float offset = texpix_src.x;
-  l_texcoord0 = float4(c.x-offset* -4, c.x-offset* -3, c.x-offset* -2, c.y);
-  l_texcoord1 = float4(c.x-offset* -1, c.x-offset*  0, c.x-offset*  1, c.y);
+  float pad = texpad_src.x * 2;
+  l_texcoord0 = float4(min(c.x-offset* -4, pad), min(c.x-offset* -3, pad), min(c.x-offset* -2, pad), c.y);
+  l_texcoord1 = float4(min(c.x-offset* -1, pad), c.x-offset*  0, c.x-offset*  1, c.y);
   l_texcoord2 = float4(c.x-offset*  2, c.x-offset*  3, c.x-offset*  4, c.y);
 }
 

+ 3 - 2
direct/src/filter/filter-bloomy.sha

@@ -12,8 +12,9 @@ void vshader(float4 vtx_position : POSITION,
   l_position=mul(mat_modelproj, vtx_position);
   float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy;
   float offset = texpix_src.y;
-  l_texcoord0 = float4(c.y-offset* -4, c.y-offset* -3, c.y-offset* -2, c.x);
-  l_texcoord1 = float4(c.y-offset* -1, c.y-offset*  0, c.y-offset*  1, c.x);
+  float pad = texpad_src.y * 2;
+  l_texcoord0 = float4(min(c.y-offset* -4, pad), min(c.y-offset* -3, pad), min(c.y-offset* -2, pad), c.x);
+  l_texcoord1 = float4(min(c.y-offset* -1, pad), c.y-offset*  0, c.y-offset*  1, c.x);
   l_texcoord2 = float4(c.y-offset*  2, c.y-offset*  3, c.y-offset*  4, c.x);
 }
 

+ 6 - 4
direct/src/filter/filter-blurx.sha

@@ -2,7 +2,7 @@
 //
 //Cg profile arbvp1 arbfp1
 
-void vshader(float4 vtx_position : POSITION, 
+void vshader(float4 vtx_position : POSITION,
              float2 vtx_texcoord0 : TEXCOORD0,
              out float4 l_position : POSITION,
       	     out float2 l_texcoord0 : TEXCOORD0,
@@ -17,16 +17,18 @@ void vshader(float4 vtx_position : POSITION,
 void fshader(float2 l_texcoord0 : TEXCOORD0,
              out float4 o_color : COLOR,
              uniform float2 texpix_src,
+             uniform float4 texpad_src,
              uniform sampler2D k_src : TEXUNIT0)
 {
+  float pad = texpad_src.x * 2;
   float3 offset = float3(1.0*texpix_src.x, 2.0*texpix_src.x, 3.0*texpix_src.x);
   o_color  = tex2D(k_src, l_texcoord0);
   o_color += tex2D(k_src, float2(l_texcoord0.x - offset.z, l_texcoord0.y));
   o_color += tex2D(k_src, float2(l_texcoord0.x - offset.y, l_texcoord0.y));
   o_color += tex2D(k_src, float2(l_texcoord0.x - offset.x, l_texcoord0.y));
-  o_color += tex2D(k_src, float2(l_texcoord0.x + offset.x, l_texcoord0.y));
-  o_color += tex2D(k_src, float2(l_texcoord0.x + offset.y, l_texcoord0.y));
-  o_color += tex2D(k_src, float2(l_texcoord0.x + offset.z, l_texcoord0.y));
+  o_color += tex2D(k_src, float2(min(l_texcoord0.x + offset.x, pad), l_texcoord0.y));
+  o_color += tex2D(k_src, float2(min(l_texcoord0.x + offset.y, pad), l_texcoord0.y));
+  o_color += tex2D(k_src, float2(min(l_texcoord0.x + offset.z, pad), l_texcoord0.y));
   o_color /= 7;
   o_color.w = 1;
 }

+ 6 - 4
direct/src/filter/filter-blury.sha

@@ -2,7 +2,7 @@
 //
 //Cg profile arbvp1 arbfp1
 
-void vshader(float4 vtx_position : POSITION, 
+void vshader(float4 vtx_position : POSITION,
              float2 vtx_texcoord0 : TEXCOORD0,
              out float4 l_position : POSITION,
       	     out float2 l_texcoord0 : TEXCOORD0,
@@ -17,16 +17,18 @@ void vshader(float4 vtx_position : POSITION,
 void fshader(float2 l_texcoord0 : TEXCOORD0,
              out float4 o_color : COLOR,
              uniform float2 texpix_src,
+             uniform float4 texpad_src,
              uniform sampler2D k_src : TEXUNIT0)
 {
+  float pad = texpad_src.y * 2;
   float3 offset = float3(1.0*texpix_src.y, 2.0*texpix_src.y, 3.0*texpix_src.y);
   o_color  = tex2D(k_src, l_texcoord0);
   o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y - offset.z));
   o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y - offset.y));
   o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y - offset.x));
-  o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y + offset.x));
-  o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y + offset.y));
-  o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y + offset.z));
+  o_color += tex2D(k_src, float2(l_texcoord0.x, min(l_texcoord0.y + offset.x, pad)));
+  o_color += tex2D(k_src, float2(l_texcoord0.x, min(l_texcoord0.y + offset.y, pad)));
+  o_color += tex2D(k_src, float2(l_texcoord0.x, min(l_texcoord0.y + offset.z, pad)));
   o_color /= 7;
   o_color.w = 1;
 }

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

@@ -1,13 +1,13 @@
-"""Undocumented Module"""
-
-__all__ = ['ClassicFSM']
-
 """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.showbase.DirectObject import DirectObject
 import weakref

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

@@ -1,5 +1,5 @@
 """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']

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

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

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

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

+ 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']
 

+ 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']
 

+ 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']
 

+ 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']
 
@@ -19,14 +32,6 @@ class DirectFrame(DirectGuiWidget):
     DefDynGroups = ('text', 'geom', 'image')
     def __init__(self, parent = None, **kw):
         # 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 = (
             # Define type of DirectGuiWidget
             ('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
 command line argument parsing.
-"""
 
-"""
 Code Overview:
 
 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.
 """
 
+__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):
+    """Base class of all DirectGUI widgets."""
+
     def __init__(self):
         # Default id of all gui object, subclasses should override this
         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
 that can be used during widget construction
 """
+
+__all__ = []
+
 from panda3d.core import *
 
 defaultFont = None

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

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the DirectLabel class."""
 
 __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']
 

+ 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']
 

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

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

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

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

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

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

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

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Defines the DirectSlider class."""
 
 __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']
 

+ 16 - 1
direct/src/gui/OnscreenText.py

@@ -35,7 +35,8 @@ class OnscreenText(NodePath):
                  font = None,
                  parent = None,
                  sort = 0,
-                 mayChange = True):
+                 mayChange = True,
+                 direction = None):
         """
         Make a text node from string, put it into the 2d sg and set it
         up with all the indicated parameters.
@@ -95,6 +96,9 @@ class OnscreenText(NodePath):
           mayChange: pass true if the text or its properties may need
               to be changed at runtime, false if it is static once
               created (which leads to better memory optimization).
+
+          direction: this can be set to 'ltr' or 'rtl' to override the
+              direction of the text.
         """
         if parent == None:
             parent = aspect2d
@@ -192,6 +196,17 @@ class OnscreenText(NodePath):
             textNode.setFrameColor(frame[0], frame[1], frame[2], frame[3])
             textNode.setFrameAsMargin(0.1, 0.1, 0.1, 0.1)
 
+        if direction is not None:
+            if isinstance(direction, str):
+                direction = direction.lower()
+                if direction == 'rtl':
+                    direction = TextProperties.D_rtl
+                elif direction == 'ltr':
+                    direction = TextProperties.D_ltr
+                else:
+                    raise ValueError('invalid direction')
+            textNode.setDirection(direction)
+
         # Create a transform for the text for our scale and position.
         # We'd rather do it here, on the text itself, rather than on
         # our NodePath, so we have one fewer transforms in the scene

+ 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__,
 # 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']
 
@@ -136,6 +137,5 @@ class IntervalManager(CIntervalManager):
         assert self.ivals[index] == None or self.ivals[index] == interval
         self.ivals[index] = interval
 
-# The global IntervalManager object.
+#: The global IntervalManager object.
 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']
 

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

@@ -1,11 +1,9 @@
-"""Undocumented Module"""
-
-__all__ = ['ParticleInterval']
-
 """
 Contains the ParticleInterval class
 """
 
+__all__ = ['ParticleInterval']
+
 from panda3d.core import *
 from panda3d.direct import *
 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.direct import *
 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
 distributable, to execute a packaged p3d application, but it can also
 be run directly via the Python interpreter (if the current Panda3D and
 Python versions match the version expected by the application).  See
 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"]

+ 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
 the AppRunner at startup. """
 
+#: Contains the global AppRunner instance, or None if this application
+#: was not run from the runtime environment.
 appRunner = None

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

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the Audio3DManager class."""
 
 __all__ = ['Audio3DManager']
 
@@ -289,3 +289,27 @@ class Audio3DManager:
             for sound in self.sound_dict[object]:
                 self.detachSound(sound)
 
+    #snake_case alias:
+    get_doppler_factor = getDopplerFactor
+    set_listener_velocity_auto = setListenerVelocityAuto
+    attach_listener = attachListener
+    set_distance_factor = setDistanceFactor
+    attach_sound_to_object = attachSoundToObject
+    get_drop_off_factor = getDropOffFactor
+    set_doppler_factor = setDopplerFactor
+    get_sounds_on_object = getSoundsOnObject
+    set_sound_velocity_auto = setSoundVelocityAuto
+    get_sound_max_distance = getSoundMaxDistance
+    load_sfx = loadSfx
+    get_distance_factor = getDistanceFactor
+    set_listener_velocity = setListenerVelocity
+    set_sound_max_distance = setSoundMaxDistance
+    get_sound_velocity = getSoundVelocity
+    get_listener_velocity = getListenerVelocity
+    set_sound_velocity = setSoundVelocity
+    set_sound_min_distance = setSoundMinDistance
+    get_sound_min_distance = getSoundMinDistance
+    detach_listener = detachListener
+    set_drop_off_factor = setDropOffFactor
+    detach_sound = detachSound
+

+ 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']
 

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

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

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

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

+ 14 - 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']
 
@@ -100,3 +101,15 @@ class DirectObject:
             func = choice(getRepository()._crashOnProactiveLeakDetect,
                           self.notify.error, self.notify.warning)
             func('destroyed %s instance is still %s%s' % (self.__class__.__name__, estr, tstr))
+
+    #snake_case alias:
+    add_task = addTask
+    do_method_later = doMethodLater
+    detect_leaks = detectLeaks
+    accept_once = acceptOnce
+    ignore_all = ignoreAll
+    get_all_accepting = getAllAccepting
+    is_ignoring = isIgnoring
+    remove_all_tasks = removeAllTasks
+    remove_task = removeTask
+    is_accepting = isAccepting

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

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""This module defines the EventGroup class."""
 
 __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']
 

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

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

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

@@ -1,4 +1,4 @@
-"""Undocumented Module"""
+"""Contains the Factory class."""
 
 __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
 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.
@@ -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,
 which you will presumably have already on your PYTHONPATH. """
 
+__all__ = ['deCygwinify', 'getPaths']
+
 import os
 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']
 

+ 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']
 

+ 15 - 3
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']
 
@@ -531,7 +532,6 @@ class Messenger:
         keys.sort()
         for event in keys:
             if repr(event).find(needle) >= 0:
-                print(self.__eventRepr(event))
                 return {event: self.__callbacks[event]}
 
     def findAll(self, needle, limit=None):
@@ -545,7 +545,6 @@ class Messenger:
         keys.sort()
         for event in keys:
             if repr(event).find(needle) >= 0:
-                print(self.__eventRepr(event))
                 matches[event] = self.__callbacks[event]
                 # if the limit is not None, decrement and
                 # check for break:
@@ -636,3 +635,16 @@ class Messenger:
         str = str + '='*50 + '\n'
         return str
 
+    #snake_case alias:
+    get_events = getEvents
+    is_ignoring = isIgnoring
+    who_accepts = whoAccepts
+    find_all = findAll
+    replace_method = replaceMethod
+    ignore_all = ignoreAll
+    is_accepting = isAccepting
+    is_empty = isEmpty
+    detailed_repr = detailedRepr
+    get_all_accepting = getAllAccepting
+    toggle_verbose = toggleVerbose
+

+ 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.
 Call setupMirror() to create a mirror in the world that reflects
 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
 reflections, you will need to use a sphere map or a cube map."""
 
+__all__ = ['setupMirror', 'showFrustum']
+
 from panda3d.core import *
 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']
 

+ 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']
 
@@ -13,17 +22,6 @@ if sys.version_info >= (3, 0):
 else:
     import __builtin__ as builtins
 
-"""
->>> from direct.showbase import ObjectReport
-
->>> o=ObjectReport.ObjectReport('baseline')
->>> run()
-...
-
->>> o2=ObjectReport.ObjectReport('')
->>> o.diff(o2)
-"""
-
 class ExclusiveObjectPool(DirectObject.DirectObject):
     # ObjectPool specialization that excludes particular objects
     # 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']
 

+ 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
 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
@@ -12,12 +7,16 @@ or be the same type.
 
 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
 
@@ -116,5 +115,3 @@ class Pool:
 
     def __repr__(self):
         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']
 
@@ -95,6 +96,3 @@ class SfxPlayer:
             if node is not None:
                 finalVolume *= node.getNetAudioVolume()
             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
 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
@@ -14,6 +9,8 @@ multitexture rendering techniques.  It's not a particularly great
 way to do shadows.
 """
 
+__all__ = ['ShadowCaster', 'avatarShadow', 'piratesAvatarShadow', 'arbitraryShadow']
+
 from panda3d.core import *
 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.
 
@@ -10,6 +6,8 @@ Or it may do that later, right now it puts a node on the surface under
 the its parent node.
 """
 
+__all__ = ['ShadowPlacer']
+
 from direct.controls.ControlManager import CollisionHandlerRayStart
 from direct.directnotify import DirectNotifyGlobal
 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']
 
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.task import Task
 
+from .PythonUtil import SerialNumGen
+
+
 class TaskThreaded:
     """ 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

+ 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']
 

+ 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']
 

+ 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__ = []
 

+ 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
 imported directly or indirectly by the original startfile.py.
 
-Usage:
+Usage::
 
   pfreeze.py [opts] [startfile]
 
-Options:
+Options::
 
   -o output
      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.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.
+"""

+ 35 - 11
direct/src/stdpy/thread.py

@@ -11,18 +11,32 @@ __all__ = [
     'interrupt_main',
     'exit', 'allocate_lock', 'get_ident',
     'stack_size',
+    'force_yield', 'consider_yield',
     'forceYield', 'considerYield',
+    'TIMEOUT_MAX'
     ]
 
 from panda3d import core
+import sys
+
+if sys.platform == "win32":
+    TIMEOUT_MAX = float(0xffffffff // 1000)
+else:
+    TIMEOUT_MAX = float(0x7fffffffffffffff // 1000000000)
 
 # These methods are defined in Panda, and are particularly useful if
 # you may be running in Panda's SIMPLE_THREADS compilation mode.
-forceYield = core.Thread.forceYield
-considerYield = core.Thread.considerYield
+force_yield = core.Thread.force_yield
+consider_yield = core.Thread.consider_yield
 
-class error(Exception):
-    pass
+forceYield = force_yield
+considerYield = consider_yield
+
+if sys.version_info >= (3, 3):
+    error = RuntimeError
+else:
+    class error(Exception):
+        pass
 
 class LockType:
     """ Implements a mutex lock.  Instead of directly subclassing
@@ -36,13 +50,18 @@ class LockType:
         self.__cvar = core.ConditionVar(self.__lock)
         self.__locked = False
 
-    def acquire(self, waitflag = 1):
+    def acquire(self, waitflag = 1, timeout = -1):
         self.__lock.acquire()
         try:
             if self.__locked and not waitflag:
                 return False
-            while self.__locked:
-                self.__cvar.wait()
+
+            if timeout >= 0:
+                while self.__locked:
+                    self.__cvar.wait(timeout)
+            else:
+                while self.__locked:
+                    self.__cvar.wait()
 
             self.__locked = True
             return True
@@ -202,12 +221,17 @@ def _get_thread_locals(thread, i):
 def _remove_thread_id(threadId):
     """ Removes the thread with the indicated ID from the thread list. """
 
+    # On interpreter shutdown, Python may set module globals to None.
+    if _threadsLock is None or _threads is None:
+        return
+
     _threadsLock.acquire()
     try:
-        thread, locals, wrapper = _threads[threadId]
-        assert thread.getPythonIndex() == threadId
-        del _threads[threadId]
-        thread.setPythonIndex(-1)
+        if threadId in _threads:
+            thread, locals, wrapper = _threads[threadId]
+            assert thread.getPythonIndex() == threadId
+            del _threads[threadId]
+            thread.setPythonIndex(-1)
 
     finally:
         _threadsLock.release()

+ 33 - 11
direct/src/stdpy/threading.py

@@ -35,11 +35,15 @@ __all__ = [
     'Event',
     'Timer',
     'local',
-    'current_thread', 'currentThread',
-    'enumerate', 'active_count', 'activeCount',
+    'current_thread',
+    'main_thread',
+    'enumerate', 'active_count',
     'settrace', 'setprofile', 'stack_size',
+    'TIMEOUT_MAX',
     ]
 
+TIMEOUT_MAX = _thread.TIMEOUT_MAX
+
 local = _thread._local
 _newname = _thread._newname
 
@@ -98,7 +102,15 @@ class Thread(ThreadBase):
         self.__dict__['daemon'] = current.daemon
         self.__dict__['name'] = name
 
-        self.__thread = core.PythonThread(self.run, None, name, name)
+        def call_run():
+            # As soon as the thread is done, break the circular reference.
+            try:
+                self.run()
+            finally:
+                self.__thread = None
+                _thread._remove_thread_id(self.ident)
+
+        self.__thread = core.PythonThread(call_run, None, name, name)
         threadId = _thread._add_thread(self.__thread, weakref.proxy(self))
         self.__dict__['ident'] = threadId
 
@@ -109,16 +121,17 @@ class Thread(ThreadBase):
             _thread._remove_thread_id(self.ident)
 
     def is_alive(self):
-        return self.__thread.isStarted()
+        thread = self.__thread
+        return thread is not None and thread.is_started()
 
-    def isAlive(self):
-        return self.__thread.isStarted()
+    isAlive = is_alive
 
     def start(self):
-        if self.__thread.isStarted():
+        thread = self.__thread
+        if thread is None or thread.is_started():
             raise RuntimeError
 
-        if not self.__thread.start(core.TPNormal, True):
+        if not thread.start(core.TPNormal, True):
             raise RuntimeError
 
     def run(self):
@@ -132,8 +145,12 @@ class Thread(ThreadBase):
     def join(self, timeout = None):
         # We don't support a timed join here, sorry.
         assert timeout is None
-        self.__thread.join()
-        self.__thread = None
+        thread = self.__thread
+        if thread is not None:
+            thread.join()
+            # Clear the circular reference.
+            self.__thread = None
+            _thread._remove_thread_id(self.ident)
 
     def setName(self, name):
         self.__dict__['name'] = name
@@ -379,6 +396,10 @@ def current_thread():
     t = core.Thread.getCurrentThread()
     return _thread._get_thread_wrapper(t, _create_thread_wrapper)
 
+def main_thread():
+    t = core.Thread.getMainThread()
+    return _thread._get_thread_wrapper(t, _create_thread_wrapper)
+
 currentThread = current_thread
 
 def enumerate():
@@ -386,7 +407,7 @@ def enumerate():
     _thread._threadsLock.acquire()
     try:
         for thread, locals, wrapper in list(_thread._threads.values()):
-            if wrapper and thread.isStarted():
+            if wrapper and wrapper.is_alive():
                 tlist.append(wrapper)
         return tlist
     finally:
@@ -394,6 +415,7 @@ def enumerate():
 
 def active_count():
     return len(enumerate())
+
 activeCount = active_count
 
 _settrace_func = None

+ 43 - 26
direct/src/stdpy/threading2.py

@@ -15,7 +15,7 @@ implementation. """
 
 import sys as _sys
 
-from direct.stdpy import thread
+from direct.stdpy import thread as _thread
 from direct.stdpy.thread import stack_size, _newname, _local as local
 from panda3d import core
 _sleep = core.Thread.sleep
@@ -23,16 +23,19 @@ _sleep = core.Thread.sleep
 from time import time as _time
 from traceback import format_exc as _format_exc
 
-# Rename some stuff so "from threading import *" is safe
-__all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event',
-           'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread',
-           'Timer', 'setprofile', 'settrace', 'local', 'stack_size']
+__all__ = ['get_ident', 'active_count', 'Condition', 'current_thread',
+           'enumerate', 'main_thread', 'TIMEOUT_MAX',
+           'Event', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread',
+           'Timer', 'ThreadError',
+           'setprofile', 'settrace', 'local', 'stack_size']
 
-_start_new_thread = thread.start_new_thread
-_allocate_lock = thread.allocate_lock
-_get_ident = thread.get_ident
-ThreadError = thread.error
-del thread
+# Rename some stuff so "from threading import *" is safe
+_start_new_thread = _thread.start_new_thread
+_allocate_lock = _thread.allocate_lock
+get_ident = _thread.get_ident
+ThreadError = _thread.error
+TIMEOUT_MAX = _thread.TIMEOUT_MAX
+del _thread
 
 
 # Debug support (adapted from ihooks.py).
@@ -446,7 +449,7 @@ class Thread(_Verbose):
         try:
             self.__started = True
             _active_limbo_lock.acquire()
-            _active[_get_ident()] = self
+            _active[get_ident()] = self
             del _limbo[self]
             _active_limbo_lock.release()
             if __debug__:
@@ -537,7 +540,7 @@ class Thread(_Verbose):
         _active_limbo_lock.acquire()
         try:
             try:
-                del _active[_get_ident()]
+                del _active[get_ident()]
             except KeyError:
                 if 'dummy_threading' not in _sys.modules:
                     raise
@@ -581,10 +584,12 @@ class Thread(_Verbose):
         assert self.__initialized, "Thread.__init__() not called"
         self.__name = str(name)
 
-    def isAlive(self):
+    def is_alive(self):
         assert self.__initialized, "Thread.__init__() not called"
         return self.__started and not self.__stopped
 
+    isAlive = is_alive
+
     def isDaemon(self):
         assert self.__initialized, "Thread.__init__() not called"
         return self.__daemonic
@@ -634,7 +639,7 @@ class _MainThread(Thread):
         Thread.__init__(self, name="MainThread")
         self._Thread__started = True
         _active_limbo_lock.acquire()
-        _active[_get_ident()] = self
+        _active[get_ident()] = self
         _active_limbo_lock.release()
 
     def _set_daemon(self):
@@ -653,12 +658,6 @@ class _MainThread(Thread):
             self._note("%s: exiting", self)
         self._Thread__delete()
 
-def _pickSomeNonDaemonThread():
-    for t in enumerate():
-        if not t.isDaemon() and t.isAlive():
-            return t
-    return None
-
 
 # Dummy thread class to represent threads not started here.
 # These aren't garbage collected when they die, nor can they be waited for.
@@ -680,7 +679,7 @@ class _DummyThread(Thread):
 
         self._Thread__started = True
         _active_limbo_lock.acquire()
-        _active[_get_ident()] = self
+        _active[get_ident()] = self
         _active_limbo_lock.release()
 
     def _set_daemon(self):
@@ -692,19 +691,23 @@ class _DummyThread(Thread):
 
 # Global API functions
 
-def currentThread():
+def current_thread():
     try:
-        return _active[_get_ident()]
+        return _active[get_ident()]
     except KeyError:
-        ##print "currentThread(): no current thread for", _get_ident()
+        ##print "current_thread(): no current thread for", get_ident()
         return _DummyThread()
 
-def activeCount():
+currentThread = current_thread
+
+def active_count():
     _active_limbo_lock.acquire()
     count = len(_active) + len(_limbo)
     _active_limbo_lock.release()
     return count
 
+activeCount = active_count
+
 def enumerate():
     _active_limbo_lock.acquire()
     active = list(_active.values()) + list(_limbo.values())
@@ -717,7 +720,21 @@ def enumerate():
 # and make it available for the interpreter
 # (Py_Main) as threading._shutdown.
 
-_shutdown = _MainThread()._exitfunc
+_main_thread = _MainThread()
+_shutdown = _main_thread._exitfunc
+
+def _pickSomeNonDaemonThread():
+    for t in enumerate():
+        if not t.isDaemon() and t.isAlive():
+            return t
+    return None
+
+def main_thread():
+    """Return the main thread object.
+    In normal conditions, the main thread is the thread from which the
+    Python interpreter was started.
+    """
+    return _main_thread
 
 # get thread-local implementation, either from the thread
 # module, or from the python fallback

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

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

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

@@ -24,7 +24,8 @@ def taskCallback(task):
     spawnNewTask()
     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']
 

+ 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']
 

+ 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']
 

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

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

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

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

Diff do ficheiro suprimidas por serem muito extensas
+ 671 - 683
dtool/src/cppparser/cppBison.cxx.prebuilt


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

@@ -928,12 +928,21 @@ type_like_declaration:
 
   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) {
+    // 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);
+  }
+}
+        maybe_initialize_or_constructor_body
+{
+  if ($2 != (CPPInstance *)NULL) {
+    pop_scope();
     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
@@ -4042,6 +4051,10 @@ name:
         | KW_STATIC
 {
   $$ = new CPPIdentifier("static", @1);
+}
+        | KW_DEFAULT
+{
+  $$ = new CPPIdentifier("default", @1);
 }
         ;
 

+ 2 - 2
dtool/src/dtoolbase/deletedBufferChain.cxx

@@ -106,8 +106,8 @@ deallocate(void *ptr, TypeHandle type_handle) {
   assert(ptr != (void *)NULL);
 
 #ifdef DO_MEMORY_USAGE
-  type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_active,
-                               _buffer_size + flag_reserved_bytes);
+  const size_t alloc_size = _buffer_size + flag_reserved_bytes + MEMORY_HOOK_ALIGNMENT - 1;
+  type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
   // type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_inactive,
   // _buffer_size + flag_reserved_bytes);
 

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

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

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff