Browse Source

Merge branch 'master' into webgl-port

rdb 8 years ago
parent
commit
980da4da71
100 changed files with 533 additions and 1665 deletions
  1. 52 4
      .gitignore
  2. 1 1
      .travis.yml
  3. 28 8
      README.md
  4. 0 9
      contrib/.gitignore
  5. 0 4
      contrib/src/ai/aiBehaviors.h
  6. 0 5
      contrib/src/ai/aiCharacter.h
  7. 0 4
      contrib/src/ai/aiGlobals.h
  8. 0 5
      contrib/src/ai/aiWorld.h
  9. 3 3
      contrib/src/ai/obstacleAvoidance.cxx
  10. 0 2
      contrib/src/panda3dtoolsgui/.gitignore
  11. 0 9
      direct/.gitignore
  12. 0 1
      direct/src/configfiles/.gitignore
  13. 1 1
      direct/src/controls/BattleWalker.py
  14. 1 1
      direct/src/controls/NonPhysicsWalker.py
  15. 0 3
      direct/src/dcparser/.gitignore
  16. 1 1
      direct/src/dcparser/dcArrayParameter.h
  17. 1 1
      direct/src/dcparser/dcAtomicField.h
  18. 1 1
      direct/src/dcparser/dcClass.h
  19. 1 1
      direct/src/dcparser/dcClassParameter.h
  20. 1 1
      direct/src/dcparser/dcDeclaration.h
  21. 1 1
      direct/src/dcparser/dcField.h
  22. 1 1
      direct/src/dcparser/dcFile.h
  23. 1 1
      direct/src/dcparser/dcKeyword.h
  24. 1 1
      direct/src/dcparser/dcKeywordList.h
  25. 1 1
      direct/src/dcparser/dcMolecularField.h
  26. 1 1
      direct/src/dcparser/dcPackData.h
  27. 2 2
      direct/src/dcparser/dcPacker.h
  28. 1 1
      direct/src/dcparser/dcPackerCatalog.h
  29. 1 1
      direct/src/dcparser/dcPackerInterface.h
  30. 1 1
      direct/src/dcparser/dcParameter.h
  31. 1 1
      direct/src/dcparser/dcSimpleParameter.h
  32. 1 1
      direct/src/dcparser/dcSwitch.h
  33. 1 1
      direct/src/dcparser/dcSwitchParameter.h
  34. 1 1
      direct/src/dcparser/dcTypedef.h
  35. 0 106
      direct/src/directbase/ppython.cxx
  36. 10 1
      direct/src/directscripts/eggcacher.py
  37. 0 831
      direct/src/directscripts/packpanda.nsi
  38. 0 421
      direct/src/directscripts/packpanda.py
  39. 1 1
      direct/src/directtools/DirectCameraControl.py
  40. 3 3
      direct/src/directtools/DirectManipulation.py
  41. 1 1
      direct/src/directtools/DirectSession.py
  42. 1 1
      direct/src/distributed/CartesianGridBase.py
  43. 2 1
      direct/src/distributed/ClientRepositoryBase.py
  44. 2 1
      direct/src/distributed/ConnectionRepository.py
  45. 2 1
      direct/src/distributed/DistributedCamera.py
  46. 2 1
      direct/src/distributed/DistributedCameraOV.py
  47. 2 1
      direct/src/distributed/DistributedCartesianGrid.py
  48. 2 1
      direct/src/distributed/DistributedCartesianGridAI.py
  49. 1 1
      direct/src/distributed/DistributedNodeAI.py
  50. 4 2
      direct/src/distributed/DistributedObject.py
  51. 0 1
      direct/src/distributed/DistributedObjectBase.py
  52. 6 6
      direct/src/distributed/DistributedObjectGlobalUD.py
  53. 2 1
      direct/src/distributed/DistributedObjectUD.py
  54. 2 1
      direct/src/distributed/DistributedSmoothNode.py
  55. 0 1
      direct/src/distributed/DoCollectionManager.py
  56. 2 1
      direct/src/distributed/DoInterestManager.py
  57. 2 1
      direct/src/distributed/GridParent.py
  58. 2 1
      direct/src/distributed/ServerRepository.py
  59. 0 7
      direct/src/distributed/StagedObject.py
  60. 1 1
      direct/src/distributed/TimeManager.py
  61. 1 1
      direct/src/distributed/TimeManagerAI.py
  62. 22 2
      direct/src/distributed/cConnectionRepository.cxx
  63. 0 1
      direct/src/extensions_native/.gitignore
  64. 10 10
      direct/src/fsm/FSM.py
  65. 17 17
      direct/src/fsm/FourState.py
  66. 23 23
      direct/src/fsm/FourStateAI.py
  67. 0 2
      direct/src/gui/.gitignore
  68. 3 3
      direct/src/gui/DirectScrolledList.py
  69. 0 8
      direct/src/p3d/.gitignore
  70. 4 4
      direct/src/p3d/FileSpec.py
  71. 12 1
      direct/src/p3d/Packager.py
  72. 6 1
      direct/src/p3d/SeqValue.py
  73. 15 3
      direct/src/p3d/panda3d.pdef
  74. 0 1
      direct/src/plugin/.gitignore
  75. 0 2
      direct/src/plugin/p3dCInstance.h
  76. 4 4
      direct/src/plugin/p3dInstance.cxx
  77. 11 0
      direct/src/plugin/p3dInstanceManager.cxx
  78. 8 8
      direct/src/plugin/p3dOsxSplashWindow.cxx
  79. 18 0
      direct/src/plugin/p3dPythonRun.cxx
  80. 0 1
      direct/src/plugin_activex/.gitignore
  81. 0 1
      direct/src/plugin_npapi/.gitignore
  82. 0 2
      direct/src/plugin_standalone/.gitignore
  83. 12 3
      direct/src/showbase/BufferViewer.py
  84. 10 6
      direct/src/showbase/DistancePhasedNode.py
  85. 1 0
      direct/src/showbase/ExceptionVarDump.py
  86. 1 1
      direct/src/showbase/LeakDetectors.py
  87. 108 42
      direct/src/showbase/Loader.py
  88. 1 1
      direct/src/showbase/MirrorDemo.py
  89. 36 1
      direct/src/showbase/PythonUtil.py
  90. 1 1
      direct/src/showbase/ShadowDemo.py
  91. 1 1
      direct/src/showbase/ShadowPlacer.py
  92. 22 9
      direct/src/showbase/ShowBase.py
  93. 2 4
      direct/src/showbase/VFSImporter.py
  94. 0 1
      direct/src/showutil/.gitignore
  95. 5 2
      direct/src/showutil/FreezeTool.py
  96. 10 10
      direct/src/stdpy/thread.py
  97. 7 7
      direct/src/task/Task.py
  98. 2 2
      direct/src/tkpanels/DirectSessionPanel.py
  99. 3 3
      direct/src/tkpanels/ParticlePanel.py
  100. 1 1
      direct/src/tkwidgets/MemoryExplorer.py

+ 52 - 4
.gitignore

@@ -1,4 +1,52 @@
-/built_x64
-/built
-/thirdparty
-/targetroot
+# makepanda directories
+/built*/
+/thirdparty/
+/targetroot/
+/dstroot/
+
+# Core dumps
+core
+core.*
+vgcore.*
+
+# Editor files/directories
+*.save
+*.save.1
+*.sublime-workspace
+.vscode/
+
+# Temporary build files
+/_vfsimporter.*
+*.pdb
+*.obj
+*.o
+*.gch
+*.pch
+
+# Produced installer/executables
+/*.exe
+/*.deb
+/*.rpm
+/*.app
+/*.pkg
+/*.dmg
+/*.whl
+
+# CMake
+/build/
+CMakeCache.txt
+CMakeFiles/
+CMakeScripts/
+Makefile
+cmake_install.cmake
+install_manifest.txt
+CTestTestfile.cmake
+
+# Windows
+Thumbs.db
+ehthumbs.db
+
+# Python
+__pycache__
+*.pyc
+*.pyo

+ 1 - 1
.travis.yml

@@ -3,7 +3,7 @@ sudo: false
 matrix:
 matrix:
   include:
   include:
     - compiler: gcc
     - compiler: gcc
-      env: PYTHONV=python2.7 FLAGS=
+      env: PYTHONV=python2.7 FLAGS=--optimize=4
     - compiler: clang
     - compiler: clang
       env: PYTHONV=python3 FLAGS=--installer
       env: PYTHONV=python3 FLAGS=--installer
     - compiler: clang
     - compiler: clang

+ 28 - 8
README.md

@@ -18,6 +18,23 @@ resources. If you get stuck, ask for help from our active
 Panda3D is licensed under the Modified BSD License.  See the LICENSE file for
 Panda3D is licensed under the Modified BSD License.  See the LICENSE file for
 more details.
 more details.
 
 
+Installing Panda3D
+==================
+
+By far, the easiest way to install the latest development build of Panda3D
+into an existing Python installation is using the following command:
+
+```bash
+pip install --pre --extra-index-url https://archive.panda3d.org/ panda3d
+```
+
+If you prefer to install the full SDK with all tools, the latest development
+builds can be obtained from this page:
+
+https://www.panda3d.org/download.php?sdk&version=devel
+
+These are automatically kept up-to-date with the latest GitHub version of Panda.
+
 Building Panda3D
 Building Panda3D
 ================
 ================
 
 
@@ -31,8 +48,8 @@ are included as part of the Windows 7.1 SDK.
 You will also need to have the third-party dependency libraries available for
 You will also need to have the third-party dependency libraries available for
 the build scripts to use.  These are available from one of these two URLs,
 the build scripts to use.  These are available from one of these two URLs,
 depending on whether you are on a 32-bit or 64-bit system:
 depending on whether you are on a 32-bit or 64-bit system:
-https://www.panda3d.org/download/panda3d-1.9.2/panda3d-1.9.2-tools-win32.zip
-https://www.panda3d.org/download/panda3d-1.9.2/panda3d-1.9.2-tools-win64.zip
+https://www.panda3d.org/download/panda3d-1.9.4/panda3d-1.9.4-tools-win32.zip
+https://www.panda3d.org/download/panda3d-1.9.4/panda3d-1.9.4-tools-win64.zip
 
 
 After acquiring these dependencies, you may simply build Panda3D from the
 After acquiring these dependencies, you may simply build Panda3D from the
 command prompt using the following command:
 command prompt using the following command:
@@ -64,7 +81,7 @@ for you to install, depending on your distribution).
 The following command illustrates how to build Panda3D with some common
 The following command illustrates how to build Panda3D with some common
 options:
 options:
 ```bash
 ```bash
-python2.7 makepanda/makepanda.py --everything --installer --no-egl --no-gles --no-gles2
+python makepanda/makepanda.py --everything --installer --no-egl --no-gles --no-gles2 --no-opencv
 ```
 ```
 
 
 You will probably see some warnings saying that it's unable to find several
 You will probably see some warnings saying that it's unable to find several
@@ -93,11 +110,14 @@ may have to use the installpanda.py script instead, which will directly copy the
 files into the appropriate locations on your computer.  You may have to run the
 files into the appropriate locations on your computer.  You may have to run the
 `ldconfig` tool in order to update your library cache after installing Panda3D.
 `ldconfig` tool in order to update your library cache after installing Panda3D.
 
 
-Mac OS X
---------
+Alternatively, you can add the `--wheel` option, which will produce a .whl
+file that can be installed into a Python installation using `pip`.
+
+macOS
+-----
 
 
-On Mac OS X, you will need to download a set of precompiled thirdparty packages in order to
-compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.9.2/panda3d-1.9.2-tools-mac.tar.gz).
+On macOS, you will need to download a set of precompiled thirdparty packages in order to
+compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.9.4/panda3d-1.9.4-tools-mac.tar.gz).
 
 
 After placing the thirdparty directory inside the panda3d source directory,
 After placing the thirdparty directory inside the panda3d source directory,
 you may build Panda3D using a command like the following:
 you may build Panda3D using a command like the following:
@@ -107,7 +127,7 @@ python makepanda/makepanda.py --everything --installer
 ```
 ```
 
 
 In order to make a universal build, pass the --universal flag.  You may also
 In order to make a universal build, pass the --universal flag.  You may also
-target a specific minimum Mac OS X version using the --osxtarget flag followed
+target a specific minimum macOS version using the --osxtarget flag followed
 by the release number, eg. 10.6 or 10.7.
 by the release number, eg. 10.6 or 10.7.
 
 
 If the build was successful, makepanda will have generated a .dmg file in
 If the build was successful, makepanda will have generated a .dmg file in

+ 0 - 9
contrib/.gitignore

@@ -1,9 +0,0 @@
-*.pyc
-*.pyo
-/__init__.py
-# These are files that are generated within the source tree by the
-# ppremake system.
-Makefile
-pp.dep
-/built/
-Opt?-*

+ 0 - 4
contrib/src/ai/aiBehaviors.h

@@ -11,10 +11,6 @@
  * @date 2009-09-08
  * @date 2009-09-08
  */
  */
 
 
-#pragma warning (disable:4996)
-#pragma warning (disable:4005)
-#pragma warning(disable:4275)
-
 #ifndef _AIBEHAVIORS_H
 #ifndef _AIBEHAVIORS_H
 #define _AIBEHAVIORS_H
 #define _AIBEHAVIORS_H
 
 

+ 0 - 5
contrib/src/ai/aiCharacter.h

@@ -11,11 +11,6 @@
  * @date 2009-09-08
  * @date 2009-09-08
  */
  */
 
 
-#pragma warning (disable:4996)
-#pragma warning (disable:4005)
-#pragma warning(disable:4275)
-
-
 #ifndef _AICHARACTER_H
 #ifndef _AICHARACTER_H
 #define _AICHARACTER_H
 #define _AICHARACTER_H
 
 

+ 0 - 4
contrib/src/ai/aiGlobals.h

@@ -11,10 +11,6 @@
  * @date 2009-09-08
  * @date 2009-09-08
  */
  */
 
 
-#pragma warning (disable:4996)
-#pragma warning (disable:4005)
-#pragma warning(disable:4275)
-
 #ifndef _AI_GLOBALS_H
 #ifndef _AI_GLOBALS_H
 #define _AI_GLOBALS_H
 #define _AI_GLOBALS_H
 
 

+ 0 - 5
contrib/src/ai/aiWorld.h

@@ -11,11 +11,6 @@
  * @date 2009-09-08
  * @date 2009-09-08
  */
  */
 
 
-#pragma warning (disable:4996)
-#pragma warning (disable:4005)
-#pragma warning(disable:4275)
-
-
 #ifndef _AIWORLD_H
 #ifndef _AIWORLD_H
 #define _AIWORLD_H
 #define _AIWORLD_H
 
 

+ 3 - 3
contrib/src/ai/obstacleAvoidance.cxx

@@ -34,7 +34,7 @@ obstacle_detection() {
   CPT(BoundingSphere) np_sphere = np_bounds->as_bounding_sphere();
   CPT(BoundingSphere) np_sphere = np_bounds->as_bounding_sphere();
   LVecBase3 avoidance(0.0, 0.0, 0.0);
   LVecBase3 avoidance(0.0, 0.0, 0.0);
   double distance = 0x7fff ;
   double distance = 0x7fff ;
-  double expanded_radius;
+  double expanded_radius = 0;
   LVecBase3 to_obstacle;
   LVecBase3 to_obstacle;
   LVecBase3 prev_avoidance;
   LVecBase3 prev_avoidance;
   for(unsigned int i = 0; i < _ai_char->_world->_obstacles.size(); ++i) {
   for(unsigned int i = 0; i < _ai_char->_world->_obstacles.size(); ++i) {
@@ -89,8 +89,8 @@ do_obstacle_avoidance() {
   CPT(BoundingSphere) bsphere = bounds->as_bounding_sphere();
   CPT(BoundingSphere) bsphere = bounds->as_bounding_sphere();
   PT(BoundingVolume) np_bounds = _ai_char->get_node_path().get_bounds();
   PT(BoundingVolume) np_bounds = _ai_char->get_node_path().get_bounds();
   CPT(BoundingSphere) np_sphere = np_bounds->as_bounding_sphere();
   CPT(BoundingSphere) np_sphere = np_bounds->as_bounding_sphere();
-  double distance_needed = offset.length() - bsphere->get_radius() - np_sphere->get_radius();
-  if((obstacle_detection())) {
+
+  if (obstacle_detection()) {
     LVecBase3 direction = _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3::forward());
     LVecBase3 direction = _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3::forward());
     direction.normalize();
     direction.normalize();
     float forward_component = offset.dot(direction);
     float forward_component = offset.dot(direction);

+ 0 - 2
contrib/src/panda3dtoolsgui/.gitignore

@@ -1,2 +0,0 @@
-/build
-/dist

+ 0 - 9
direct/.gitignore

@@ -1,9 +0,0 @@
-*.pyc
-*.pyo
-/__init__.py
-# These are files that are generated within the source tree by the
-# ppremake system.
-Makefile
-pp.dep
-/built/
-Opt?-*

+ 0 - 1
direct/src/configfiles/.gitignore

@@ -1 +0,0 @@
-/40_direct.prc

+ 1 - 1
direct/src/controls/BattleWalker.py

@@ -1,7 +1,7 @@
 
 
 from direct.showbase.InputStateGlobal import inputState
 from direct.showbase.InputStateGlobal import inputState
 from direct.task.Task import Task
 from direct.task.Task import Task
-from pandac.PandaModules import *
+from panda3d.core import *
 from . import GravityWalker
 from . import GravityWalker
 
 
 BattleStrafe = 0
 BattleStrafe = 0

+ 1 - 1
direct/src/controls/NonPhysicsWalker.py

@@ -19,7 +19,7 @@ from direct.showbase import DirectObject
 from direct.controls.ControlManager import CollisionHandlerRayStart
 from direct.controls.ControlManager import CollisionHandlerRayStart
 from direct.showbase.InputStateGlobal import inputState
 from direct.showbase.InputStateGlobal import inputState
 from direct.task.Task import Task
 from direct.task.Task import Task
-from pandac.PandaModules import *
+from panda3d.core import *
 
 
 class NonPhysicsWalker(DirectObject.DirectObject):
 class NonPhysicsWalker(DirectObject.DirectObject):
     notify = DirectNotifyGlobal.directNotify.newCategory("NonPhysicsWalker")
     notify = DirectNotifyGlobal.directNotify.newCategory("NonPhysicsWalker")

+ 0 - 3
direct/src/dcparser/.gitignore

@@ -1,3 +0,0 @@
-/dcLexer.cxx
-/dcParser.cxx
-/dcParser.h

+ 1 - 1
direct/src/dcparser/dcArrayParameter.h

@@ -23,7 +23,7 @@
  * parameter type accepts an arbitrary (or possibly fixed) number of nested
  * parameter type accepts an arbitrary (or possibly fixed) number of nested
  * fields, all of which are of the same type.
  * fields, all of which are of the same type.
  */
  */
-class EXPCL_DIRECT DCArrayParameter : public DCParameter {
+class DCArrayParameter : public DCParameter {
 public:
 public:
   DCArrayParameter(DCParameter *element_type,
   DCArrayParameter(DCParameter *element_type,
                    const DCUnsignedIntRange &size = DCUnsignedIntRange());
                    const DCUnsignedIntRange &size = DCUnsignedIntRange());

+ 1 - 1
direct/src/dcparser/dcAtomicField.h

@@ -27,7 +27,7 @@
  * This defines an interface to the Distributed Class, and is always
  * This defines an interface to the Distributed Class, and is always
  * implemented as a remote procedure method.
  * implemented as a remote procedure method.
  */
  */
-class EXPCL_DIRECT DCAtomicField : public DCField {
+class DCAtomicField : public DCField {
 public:
 public:
   DCAtomicField(const string &name, DCClass *dclass, bool bogus_field);
   DCAtomicField(const string &name, DCClass *dclass, bool bogus_field);
   virtual ~DCAtomicField();
   virtual ~DCAtomicField();

+ 1 - 1
direct/src/dcparser/dcClass.h

@@ -41,7 +41,7 @@ class DCParameter;
 /**
 /**
  * Defines a particular DistributedClass as read from an input .dc file.
  * Defines a particular DistributedClass as read from an input .dc file.
  */
  */
-class EXPCL_DIRECT DCClass : public DCDeclaration {
+class DCClass : public DCDeclaration {
 public:
 public:
   DCClass(DCFile *dc_file, const string &name,
   DCClass(DCFile *dc_file, const string &name,
           bool is_struct, bool bogus_class);
           bool is_struct, bool bogus_class);

+ 1 - 1
direct/src/dcparser/dcClassParameter.h

@@ -23,7 +23,7 @@ class DCClass;
  * This represents a class (or struct) object used as a parameter itself.
  * This represents a class (or struct) object used as a parameter itself.
  * This means that all the fields of the class get packed into the message.
  * This means that all the fields of the class get packed into the message.
  */
  */
-class EXPCL_DIRECT DCClassParameter : public DCParameter {
+class DCClassParameter : public DCParameter {
 public:
 public:
   DCClassParameter(const DCClass *dclass);
   DCClassParameter(const DCClass *dclass);
   DCClassParameter(const DCClassParameter &copy);
   DCClassParameter(const DCClassParameter &copy);

+ 1 - 1
direct/src/dcparser/dcDeclaration.h

@@ -26,7 +26,7 @@ class DCSwitch;
  * only purpose is so that classes and typedefs can be stored in one list
  * only purpose is so that classes and typedefs can be stored in one list
  * together so they can be ordered correctly on output.
  * together so they can be ordered correctly on output.
  */
  */
-class EXPCL_DIRECT DCDeclaration {
+class DCDeclaration {
 public:
 public:
   virtual ~DCDeclaration();
   virtual ~DCDeclaration();
 
 

+ 1 - 1
direct/src/dcparser/dcField.h

@@ -34,7 +34,7 @@ class HashGenerator;
 /**
 /**
  * A single field of a Distributed Class, either atomic or molecular.
  * A single field of a Distributed Class, either atomic or molecular.
  */
  */
-class EXPCL_DIRECT DCField : public DCPackerInterface, public DCKeywordList {
+class DCField : public DCPackerInterface, public DCKeywordList {
 public:
 public:
   DCField();
   DCField();
   DCField(const string &name, DCClass *dclass);
   DCField(const string &name, DCClass *dclass);

+ 1 - 1
direct/src/dcparser/dcFile.h

@@ -29,7 +29,7 @@ class DCDeclaration;
  * Represents the complete list of Distributed Class descriptions as read from
  * Represents the complete list of Distributed Class descriptions as read from
  * a .dc file.
  * a .dc file.
  */
  */
-class EXPCL_DIRECT DCFile {
+class DCFile {
 PUBLISHED:
 PUBLISHED:
   DCFile();
   DCFile();
   ~DCFile();
   ~DCFile();

+ 1 - 1
direct/src/dcparser/dcKeyword.h

@@ -25,7 +25,7 @@ class HashGenerator;
  * define a communication property associated with a field, for instance
  * define a communication property associated with a field, for instance
  * "broadcast" or "airecv".
  * "broadcast" or "airecv".
  */
  */
-class EXPCL_DIRECT DCKeyword : public DCDeclaration {
+class DCKeyword : public DCDeclaration {
 public:
 public:
   DCKeyword(const string &name, int historical_flag = ~0);
   DCKeyword(const string &name, int historical_flag = ~0);
   virtual ~DCKeyword();
   virtual ~DCKeyword();

+ 1 - 1
direct/src/dcparser/dcKeywordList.h

@@ -23,7 +23,7 @@ class HashGenerator;
  * This is a list of keywords (see DCKeyword) that may be set on a particular
  * This is a list of keywords (see DCKeyword) that may be set on a particular
  * field.
  * field.
  */
  */
-class EXPCL_DIRECT DCKeywordList {
+class DCKeywordList {
 public:
 public:
   DCKeywordList();
   DCKeywordList();
   DCKeywordList(const DCKeywordList &copy);
   DCKeywordList(const DCKeywordList &copy);

+ 1 - 1
direct/src/dcparser/dcMolecularField.h

@@ -25,7 +25,7 @@ class DCParameter;
  * This represents a combination of two or more related atomic fields, that
  * This represents a combination of two or more related atomic fields, that
  * will often be treated as a unit.
  * will often be treated as a unit.
  */
  */
-class EXPCL_DIRECT DCMolecularField : public DCField {
+class DCMolecularField : public DCField {
 public:
 public:
   DCMolecularField(const string &name, DCClass *dclass);
   DCMolecularField(const string &name, DCClass *dclass);
 
 

+ 1 - 1
direct/src/dcparser/dcPackData.h

@@ -19,7 +19,7 @@
 /**
 /**
  * This is a block of data that receives the results of DCPacker.
  * This is a block of data that receives the results of DCPacker.
  */
  */
-class EXPCL_DIRECT DCPackData {
+class DCPackData {
 PUBLISHED:
 PUBLISHED:
   INLINE DCPackData();
   INLINE DCPackData();
   INLINE ~DCPackData();
   INLINE ~DCPackData();

+ 2 - 2
direct/src/dcparser/dcPacker.h

@@ -31,7 +31,7 @@ class DCSwitchParameter;
  * See also direct/src/doc/dcPacker.txt for a more complete description and
  * See also direct/src/doc/dcPacker.txt for a more complete description and
  * examples of using this class.
  * examples of using this class.
  */
  */
-class EXPCL_DIRECT DCPacker {
+class DCPacker {
 PUBLISHED:
 PUBLISHED:
   DCPacker();
   DCPacker();
   ~DCPacker();
   ~DCPacker();
@@ -216,7 +216,7 @@ private:
   const DCPackerCatalog *_catalog;
   const DCPackerCatalog *_catalog;
   const DCPackerCatalog::LiveCatalog *_live_catalog;
   const DCPackerCatalog::LiveCatalog *_live_catalog;
 
 
-  class EXPCL_DIRECT StackElement {
+  class StackElement {
   public:
   public:
     // As an optimization, we implement operator new and delete here to
     // As an optimization, we implement operator new and delete here to
     // minimize allocation overhead during push() and pop().
     // minimize allocation overhead during push() and pop().

+ 1 - 1
direct/src/dcparser/dcPackerCatalog.h

@@ -26,7 +26,7 @@ class DCSwitchParameter;
  * requested from a particular field; its ownership is retained by the field
  * requested from a particular field; its ownership is retained by the field
  * so it must not be deleted.
  * so it must not be deleted.
  */
  */
-class EXPCL_DIRECT DCPackerCatalog {
+class DCPackerCatalog {
 private:
 private:
   DCPackerCatalog(const DCPackerInterface *root);
   DCPackerCatalog(const DCPackerInterface *root);
   DCPackerCatalog(const DCPackerCatalog &copy);
   DCPackerCatalog(const DCPackerCatalog &copy);

+ 1 - 1
direct/src/dcparser/dcPackerInterface.h

@@ -64,7 +64,7 @@ END_PUBLISH
  * Normally these methods are called only by the DCPacker object; the user
  * Normally these methods are called only by the DCPacker object; the user
  * wouldn't normally call these directly.
  * wouldn't normally call these directly.
  */
  */
-class EXPCL_DIRECT DCPackerInterface {
+class DCPackerInterface {
 public:
 public:
   DCPackerInterface(const string &name = string());
   DCPackerInterface(const string &name = string());
   DCPackerInterface(const DCPackerInterface &copy);
   DCPackerInterface(const DCPackerInterface &copy);

+ 1 - 1
direct/src/dcparser/dcParameter.h

@@ -32,7 +32,7 @@ class HashGenerator;
  * This may also be a typedef reference to another type, which has the same
  * This may also be a typedef reference to another type, which has the same
  * properties as the referenced type, but a different name.
  * properties as the referenced type, but a different name.
  */
  */
-class EXPCL_DIRECT DCParameter : public DCField {
+class DCParameter : public DCField {
 protected:
 protected:
   DCParameter();
   DCParameter();
   DCParameter(const DCParameter &copy);
   DCParameter(const DCParameter &copy);

+ 1 - 1
direct/src/dcparser/dcSimpleParameter.h

@@ -25,7 +25,7 @@
  * divisor, which is meaningful only for the numeric type elements (and
  * divisor, which is meaningful only for the numeric type elements (and
  * represents a fixed-point numeric convention).
  * represents a fixed-point numeric convention).
  */
  */
-class EXPCL_DIRECT DCSimpleParameter : public DCParameter {
+class DCSimpleParameter : public DCParameter {
 public:
 public:
   DCSimpleParameter(DCSubatomicType type, unsigned int divisor = 1);
   DCSimpleParameter(DCSubatomicType type, unsigned int divisor = 1);
   DCSimpleParameter(const DCSimpleParameter &copy);
   DCSimpleParameter(const DCSimpleParameter &copy);

+ 1 - 1
direct/src/dcparser/dcSwitch.h

@@ -27,7 +27,7 @@ class DCField;
  * and represents two or more alternative unpacking schemes based on the first
  * and represents two or more alternative unpacking schemes based on the first
  * field read.
  * field read.
  */
  */
-class EXPCL_DIRECT DCSwitch : public DCDeclaration {
+class DCSwitch : public DCDeclaration {
 public:
 public:
   DCSwitch(const string &name, DCField *key_parameter);
   DCSwitch(const string &name, DCField *key_parameter);
   virtual ~DCSwitch();
   virtual ~DCSwitch();

+ 1 - 1
direct/src/dcparser/dcSwitchParameter.h

@@ -23,7 +23,7 @@ class DCSwitch;
  * This represents a switch object used as a parameter itself, which packs the
  * This represents a switch object used as a parameter itself, which packs the
  * appropriate fields of the switch into the message.
  * appropriate fields of the switch into the message.
  */
  */
-class EXPCL_DIRECT DCSwitchParameter : public DCParameter {
+class DCSwitchParameter : public DCParameter {
 public:
 public:
   DCSwitchParameter(const DCSwitch *dswitch);
   DCSwitchParameter(const DCSwitch *dswitch);
   DCSwitchParameter(const DCSwitchParameter &copy);
   DCSwitchParameter(const DCSwitchParameter &copy);

+ 1 - 1
direct/src/dcparser/dcTypedef.h

@@ -23,7 +23,7 @@ class DCParameter;
  * This represents a single typedef declaration in the dc file.  It assigns a
  * This represents a single typedef declaration in the dc file.  It assigns a
  * particular type to a new name, just like a C typedef.
  * particular type to a new name, just like a C typedef.
  */
  */
-class EXPCL_DIRECT DCTypedef : public DCDeclaration {
+class DCTypedef : public DCDeclaration {
 public:
 public:
   DCTypedef(DCParameter *parameter, bool implicit = false);
   DCTypedef(DCParameter *parameter, bool implicit = false);
   DCTypedef(const string &name);
   DCTypedef(const string &name);

+ 0 - 106
direct/src/directbase/ppython.cxx

@@ -1,106 +0,0 @@
-// This is a little wrapper to make it easy to run a python program from the
-// command line.  Basically, it just interfaces to the Python API and imports
-// the module that was specified by the IMPORT_MODULE preprocessor definition
-// when it was compiled.
-
-#include "dtoolbase.h"
-
-#undef _POSIX_C_SOURCE
-#undef _XOPEN_SOURCE
-#include <Python.h>
-#if PY_MAJOR_VERSION >= 3
-#include <wchar.h>
-#endif
-
-#ifndef IMPORT_MODULE
-#error IMPORT_MODULE must be defined when compiling ppython.cxx !
-#endif
-
-#define _STRINGIFY(s) #s
-#define STRINGIFY(s) _STRINGIFY(s)
-#define IMPORT_MODULE_STR STRINGIFY(IMPORT_MODULE)
-
-#if defined(_WIN32) && PY_MAJOR_VERSION >= 3
-// As Py_SetProgramName expects a wchar_t*, it's easiest to just use the wmain
-// entry point.
-int wmain(int argc, wchar_t *argv[]) {
-  Py_SetProgramName(argv[0]);
-
-#elif PY_MAJOR_VERSION >= 3
-// Convert from UTF-8 to wchar_t*.
-int main(int argc, char *mb_argv[]) {
-  wchar_t **argv = new wchar_t*[argc + 1];
-  for (int i = 0; i < argc; ++i) {
-    size_t len = mbstowcs(NULL, mb_argv[i], 0);
-    argv[i] = new wchar_t[len + 1];
-    mbstowcs(argv[i], mb_argv[i], len);
-    argv[i][len] = 0;
-  }
-  // Just for good measure
-  argv[argc] = NULL;
-
-  Py_SetProgramName(argv[0]);
-
-#else
-// Python 2.
-int main(int argc, char *argv[]) {
-  Py_SetProgramName(argv[0]);
-#endif
-
-  // On Windows, we need to set pythonhome correctly.  We'll try to find
-  // ppython.exe on the path and set pythonhome to its location.
-#ifdef _WIN32
-#if PY_MAJOR_VERSION >= 3
-  // Py_SetPythonHome expects a wchar_t in Python 3.
-  wchar_t *path = _wgetenv(L"PATH");
-  wchar_t *result = wcstok(path, L";");
-  while (result != NULL) {
-    struct _stat st;
-    wchar_t *ppython = (wchar_t*) malloc(wcslen(result) * 2 + 26);
-    wcscpy(ppython, result);
-    wcscat(ppython, L"\\python.exe");
-    if (_wstat(ppython, &st) == 0) {
-      Py_SetPythonHome(result);
-      free(ppython);
-      break;
-    }
-    result = wcstok(NULL, L";");
-    free(ppython);
-  }
-#else
-  char *path = getenv("PATH");
-  char *result = strtok(path, ";");
-  while (result != NULL) {
-    struct stat st;
-    char *ppython = (char*) malloc(strlen(result) + 13);
-    strcpy(ppython, result);
-    strcat(ppython, "\\ppython.exe");
-    if (stat(ppython, &st) == 0) {
-      Py_SetPythonHome(result);
-      free(ppython);
-      break;
-    }
-    result = strtok(NULL, ";");
-    free(ppython);
-  }
-#endif
-#endif
-
-  Py_Initialize();
-
-  if (Py_VerboseFlag) {
-    fprintf(stderr, "Python %s\\n%s\\n", Py_GetVersion(), Py_GetCopyright());
-  }
-
-  PySys_SetArgv(argc, argv);
-
-  int sts = 0;
-  PyObject* m = PyImport_ImportModule(IMPORT_MODULE_STR);
-  if (m <= 0) {
-    PyErr_Print();
-    sts = 1;
-  }
-
-  Py_Finalize();
-  return sts;
-}

+ 10 - 1
direct/src/directscripts/eggcacher.py

@@ -87,4 +87,13 @@ class EggCacher:
             TexturePool.releaseAllTextures()
             TexturePool.releaseAllTextures()
             progress += size
             progress += size
 
 
-cacher = EggCacher(sys.argv[1:])
+
+def main(args=None):
+    if args is None:
+        args = sys.argv[1:]
+
+    cacher = EggCacher(args)
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(main())

+ 0 - 831
direct/src/directscripts/packpanda.nsi

@@ -1,831 +0,0 @@
-; Panda3D installation script for the Nullsoft Installation System (NSIS).
-; Jon Parise <[email protected]>
-; with Ben Johnson <[email protected]>
-; with Jason Pratt <[email protected]>
-; mangled by Josh Yelon <[email protected]>
-
-; Caller needs to define these variables:
-;
-;   COMPRESSOR    - either zlib or lzma
-;   NAME          - name of what we're building                 (ie, "Panda3D" or "Airblade")
-;   SMDIRECTORY   - where to put this in the start menu         (ie, "Panda3D 1.1.0" or "Airblade 1.1.0")
-;   INSTALLDIR    - where to install the program                (ie, "C:\Program Files\Panda3D-1.1.0")
-;   OUTFILE       - where to put the output file                (ie, "..\nsis-output.exe")
-;   LICENSE       - location of the license file                (ie, "C:\Airblade\LICENSE.TXT")
-;   LANGUAGE      - name of the Language file to use            (ie, "English" or "Panda3DEnglish")
-;   RUNTEXT       - text for run-box at end of installation     (ie, "Run the Panda Greeting Card")
-;   IBITMAP       - name of installer bitmap                    (ie, "C:\Airblade\Airblade.bmp")
-;   UBITMAP       - name of uninstaller bitmap                  (ie, "C:\Airblade\Airblade.bmp")
-;
-;   PANDA         - location of panda install tree.
-;   PYVER         - version of Python that Panda was built with (ie, "2.7")
-;   PANDACONF     - name of panda config directory - usually $PANDA\etc 
-;   PSOURCE       - location of the panda source-tree if available, OR location of panda install tree.
-;   PYEXTRAS      - directory containing python extras, if any.
-;   REGVIEW       - either 32 or 64, depending on the build architecture.
-;
-;   PPGAME      - directory containing prepagaged game, if any        (ie, "C:\My Games\Airblade")
-;   PPMAIN      - python program containing prepackaged game, if any  (ie, "Airblade.py")
-;   PPICON      - file containing icon of prepackaged game.
-;
-
-!include "MUI.nsh"
-!include "WinMessages.nsh"
-Name "${NAME}"
-InstallDir "${INSTALLDIR}"
-OutFile "${OUTFILE}"
-
-SetCompress auto
-SetCompressor ${COMPRESSOR}
-
-!define MUI_WELCOMEFINISHPAGE_BITMAP "${IBITMAP}"
-!define MUI_UNWELCOMEFINISHPAGE_BITMAP "${UBITMAP}"
-
-!define MUI_ABORTWARNING
-!define MUI_FINISHPAGE_NOREBOOTSUPPORT
-!define MUI_FINISHPAGE_RUN
-!define MUI_FINISHPAGE_RUN_FUNCTION runFunction
-!define MUI_FINISHPAGE_RUN_TEXT "${RUNTEXT}"
-
-!insertmacro MUI_PAGE_WELCOME
-!insertmacro MUI_PAGE_LICENSE "${LICENSE}"
-!insertmacro MUI_PAGE_DIRECTORY
-!insertmacro MUI_PAGE_INSTFILES
-!insertmacro MUI_PAGE_FINISH
-
-!insertmacro MUI_UNPAGE_WELCOME
-!insertmacro MUI_UNPAGE_CONFIRM
-!insertmacro MUI_UNPAGE_INSTFILES
-!insertmacro MUI_UNPAGE_FINISH
-
-!insertmacro MUI_LANGUAGE "${LANGUAGE}"
-
-ShowInstDetails nevershow
-ShowUninstDetails nevershow
-
-LicenseData "${LICENSE}"
-
-InstType "Typical"
-
-!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
-
-var READABLE
-var MANPAGE
-var TUTNAME
-
-Function runFunction
-        !ifdef PPGAME
-        ExecShell "open" "$SMPROGRAMS\${SMDIRECTORY}\Play ${NAME}.lnk"
-        !else
-        ExecShell "open" "$SMPROGRAMS\${SMDIRECTORY}\Panda Manual.lnk"
-        !endif
-FunctionEnd
-
-Section "${SMDIRECTORY}" SecCore
-        SectionIn 1 2 3 RO
-
-        SetDetailsPrint none
-        SetOutPath $INSTDIR
-        SetOverwrite try
-
-        SetOutPath $INSTDIR
-        File "${PANDA}\LICENSE"
-        SetOutPath $INSTDIR\bin
-        File /r "${PANDA}\bin\*.dll"
-        File /nonfatal /r "${PANDA}\bin\*.pyd"
-        File /nonfatal /r "${PANDA}\bin\Microsoft.*.manifest"
-        SetOutPath $INSTDIR\etc
-        File /r "${PANDACONF}\*"
-        SetOutPath $INSTDIR\direct\directscripts
-        File /r /x CVS /x Opt?-Win32 "${PANDA}\direct\directscripts\*"
-        SetOutPath $INSTDIR\direct\filter
-        File /r /x CVS /x Opt?-Win32 "${PANDA}\direct\filter\*.sha"
-        SetOutPath $INSTDIR\direct
-        File /r /x CVS /x Opt?-Win32 "${PANDA}\direct\*.py"
-        Delete "$INSTDIR\panda3d.py"
-        Delete "$INSTDIR\panda3d.pyc"
-        Delete "$INSTDIR\panda3d.pyo"
-        SetOutPath $INSTDIR\pandac
-        File /r "${PANDA}\pandac\*.py"
-        SetOutPath $INSTDIR\panda3d
-        File /r "${PANDA}\panda3d\*.py"
-        File /r "${PANDA}\panda3d\*.pyd"
-        SetOutPath $INSTDIR\python
-        File /r "${PANDA}\python\*"
-        RMDir /r "$SMPROGRAMS\${SMDIRECTORY}"
-        CreateDirectory "$SMPROGRAMS\${SMDIRECTORY}"
-
-        !ifdef PPGAME
-
-            SetOutPath $INSTDIR\models
-            File /r /x CVS "${PANDA}\models\*"
-            SetOutPath $INSTDIR\bin
-            File /r "${PANDA}\bin\eggcacher.exe"
-            SetOutpath $INSTDIR\game
-            File /r "${PPGAME}\*"
-            CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Play ${NAME}.lnk" "$INSTDIR\python\ppython.exe" "-E ${PPMAIN}" "$INSTDIR\${PPICON}" 0 SW_SHOWMINIMIZED "" "Play ${NAME}"
-            # Preload all EGG files into the model-cache
-            SetOutPath $INSTDIR
-            SetDetailsPrint textonly
-            SetDetailsView show
-            nsExec::ExecToLog '"$INSTDIR\bin\eggcacher.exe" --concise game'
-            SetDetailsPrint none
-            SetDetailsView hide
-
-        !else
-
-            SetOutPath $INSTDIR\plugins
-            File /nonfatal /r "${PANDA}\plugins\*.dle"
-            File /nonfatal /r "${PANDA}\plugins\*.dlo"
-            File /nonfatal /r "${PANDA}\plugins\*.mll"
-            File /nonfatal /r "${PANDA}\plugins\*.mel"
-            File /nonfatal /r "${PANDA}\plugins\*.ms"
-            File "${PSOURCE}\doc\INSTALLING-PLUGINS.TXT"
-            SetOutPath $INSTDIR\pandac\input
-            File /r "${PANDA}\pandac\input\*"
-            SetOutPath $INSTDIR\bin
-            File /r "${PANDA}\bin\*.exe"
-            File /nonfatal /r "${PANDA}\bin\*.p3d"
-            SetOutPath $INSTDIR\lib
-            File /r /x *.exp "${PANDA}\lib\*"
-            SetOutPath $INSTDIR\include
-            File /r /x *.exp "${PANDA}\include\*"
-            SetOutPath $INSTDIR\Pmw
-            File /r /x CVS "${PANDA}\Pmw\*"
-            SetOutPath $INSTDIR\NSIS
-            File /r /x CVS "${NSISDIR}\*"
-            SetOutPath $INSTDIR
-            File /r /x CVS "${PANDA}\ReleaseNotes"
-            !ifdef PYEXTRAS
-            SetOutPath $INSTDIR\python\lib
-            File /nonfatal /r "${PYEXTRAS}\*"
-            !endif
-            SetOutPath $INSTDIR\models
-            File /r /x CVS "${PANDA}\models\*"
-            SetOutPath $INSTDIR\samples
-            File /nonfatal /r /x CVS "${PSOURCE}\samples\*"
-            MessageBox MB_YESNO|MB_ICONQUESTION \
-               "EGG caching is about to begin.$\nThis process may take a couple minute and approximately 270 MB of RAM.$\nWARNING : It might stuck if your computer resources are low.$\n$\nDo you really want to do this optional step ?" \
-               IDNO SkipCaching
-            # Preload all EGG files into the model-cache
-            SetOutPath $INSTDIR
-            SetDetailsPrint both
-            SetDetailsView show
-            nsExec::ExecToLog '"$INSTDIR\bin\eggcacher.exe" --concise models samples'
-            SetDetailsPrint none
-            SetDetailsView hide
-            SkipCaching:
-
-            SetOutPath $INSTDIR
-            WriteINIStr $INSTDIR\Website.url "InternetShortcut" "URL" "http://panda3d.org/"
-            WriteINIStr $INSTDIR\Manual.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php"
-            WriteINIStr $INSTDIR\Samples.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php/Sample_Programs_in_the_Distribution"
-            SetOutPath $INSTDIR
-            CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Panda Manual.lnk" "$INSTDIR\Manual.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Panda Manual"
-            CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Panda Website.lnk" "$INSTDIR\Website.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Panda Website"
-            CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Program Manual.lnk" "$INSTDIR\Samples.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Sample Program Manual"
-
-            FindFirst $0 $1 $INSTDIR\samples\*
-            loop:
-                StrCmp $1 "" done
-                StrCmp $1 "." next
-                StrCmp $1 ".." next
-    Push $1
-          Push "-"
-                Push " "
-                Call StrRep
-                Pop $R0
-                StrCpy $READABLE $R0
-    Push $1
-          Push "-"
-                Push "_"
-                Call StrRep
-                Pop $R0
-                StrCpy $MANPAGE $R0
-                CreateDirectory "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE"
-                SetOutPath $INSTDIR\samples\$1
-                WriteINIStr $INSTDIR\samples\$1\ManualPage.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php/Sample_Programs:_$MANPAGE"
-                CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE\Manual Page.lnk" "$INSTDIR\samples\$1\ManualPage.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Manual Entry on this Sample Program"
-                CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE\View Source Code.lnk" "$INSTDIR\samples\$1"
-                FindFirst $2 $3 $INSTDIR\samples\$1\Tut-*.py
-                iloop:
-                    StrCmp $3 "" idone
-                    StrCpy $TUTNAME $3 -3 4
-                    Push $TUTNAME
-                    Push "-"
-                    Push " "
-                    Call StrRep
-                    Pop $R0
-                    StrCpy $TUTNAME $R0
-                    CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE\Run $TUTNAME.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\bin\eggcacher.exe" 0 SW_SHOWMINIMIZED "" "Run $TUTNAME"
-                    CreateShortCut "$INSTDIR\samples\$1\Run $TUTNAME.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\bin\eggcacher.exe" 0 SW_SHOWMINIMIZED "" "Run $TUTNAME"
-                    FindNext $2 $3
-                    goto iloop
-                idone:
-            next:
-                FindNext $0 $1
-                Goto loop
-            done:
-
-        !endif
-
-SectionEnd
-
-
-Section -post
-
-        !ifdef REGVIEW
-        SetRegView ${REGVIEW}
-        !endif
-
-        !ifndef PPGAME
-
-        # Add the "bin" directory to the PATH.
-        Push "$INSTDIR\python"
-        Call RemoveFromPath
-        Push "$INSTDIR\python\Scripts"
-        Call RemoveFromPath
-        Push "$INSTDIR\bin"
-        Call RemoveFromPath
-        Push "$INSTDIR\python"
-        Call AddToPath
-        Push "$INSTDIR\python\Scripts"
-        Call AddToPath
-        Push "$INSTDIR\bin"
-        Call AddToPath
-
-        ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
-        StrCmp $0 "$INSTDIR\python" RegPath 0
-        StrCmp $0 "" RegPath 0
-
-        MessageBox MB_YESNO|MB_ICONQUESTION \
-                "Your system already has a copy of Python installed. Panda3D installs its own copy of Python ${PYVER}, which will install alongside your existing copy. Would you like to make Panda's copy the default Python? If you choose 'No', you will have to configure your existing copy of Python to use the Panda3D libraries, keeping in mind that this version of Panda3D can only run with Python ${PYVER}." \
-                IDNO SkipRegPath
-
-        RegPath:
-        DetailPrint "Adding registry keys for python..."
-        WriteRegStr HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" "" "$INSTDIR\python"
-        SkipRegPath:
-        !endif
-
-        DetailPrint "Adding the uninstaller ..."
-        Delete "$INSTDIR\uninst.exe"
-        WriteUninstaller "$INSTDIR\uninst.exe"
-        WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SMDIRECTORY}" "DisplayName" "${SMDIRECTORY}"
-        WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SMDIRECTORY}" "UninstallString" '"$INSTDIR\uninst.exe"'
-        SetOutPath $INSTDIR
-        CreateShortcut "$SMPROGRAMS\${SMDIRECTORY}\Uninstall ${NAME}.lnk" "$INSTDIR\uninst.exe" ""
-
-SectionEnd
-
-Section Uninstall
-
-        !ifdef REGVIEW
-        SetRegView ${REGVIEW}
-        !endif
-
-        !ifndef PPGAME
-        Push "$INSTDIR\python"
-        Call un.RemoveFromPath
-        Push "$INSTDIR\python\Scripts"
-        Call un.RemoveFromPath
-        Push "$INSTDIR\bin"
-        Call un.RemoveFromPath
-
-        ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
-        StrCmp $0 "$INSTDIR\python" 0 SkipUnReg
-        DeleteRegKey HKLM "Software\Python\PythonCore\${PYVER}"
-        SkipUnReg:
-        !endif
-
-        Delete "$INSTDIR\uninst.exe"
-        RMDir /r "$SMPROGRAMS\${SMDIRECTORY}"
-        RMDir /r "$INSTDIR"
-        DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SMDIRECTORY}"
-
-SectionEnd
-
-# --[ Utility Functions ]------------------------------------------------------
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-Function IsNT
-        Push $0
-        ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
-        StrCmp $0 "" 0 IsNT_yes
-        ; we are not NT.
-        Pop $0
-        Push 0
-        Return
-        IsNT_yes:
-                ; NT!!!
-                Pop $0
-                Push 1
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-Function un.IsNT
-        Push $0
-        ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
-        StrCmp $0 "" 0 unIsNT_yes
-        ; we are not NT.
-        Pop $0
-        Push 0
-        Return
-        unIsNT_yes:
-                ; NT!!!
-                Pop $0
-                Push 1
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-Function StrStr
-        Push $0
-        Exch
-        Pop $0 ; $0 now have the string to find
-        Push $1
-        Exch 2
-        Pop $1 ; $1 now have the string to find in
-        Exch
-        Push $2
-        Push $3
-        Push $4
-        Push $5
-        StrCpy $2 -1
-        StrLen $3 $0
-        StrLen $4 $1
-        IntOp $4 $4 - $3
-        unStrStr_loop:
-                IntOp $2 $2 + 1
-                IntCmp $2 $4 0 0 unStrStrReturn_notFound
-                StrCpy $5 $1 $3 $2
-                StrCmp $5 $0 unStrStr_done unStrStr_loop
-        unStrStrReturn_notFound:
-                StrCpy $2 -1
-        unStrStr_done:
-                Pop $5
-                Pop $4
-                Pop $3
-                Exch $2
-                Exch 2
-                Pop $0
-                Pop $1
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-Function un.StrStr
-        Push $0
-        Exch
-        Pop $0 ; $0 now have the string to find
-        Push $1
-        Exch 2
-        Pop $1 ; $1 now have the string to find in
-        Exch
-        Push $2
-        Push $3
-        Push $4
-        Push $5
-        StrCpy $2 -1
-        StrLen $3 $0
-        StrLen $4 $1
-        IntOp $4 $4 - $3
-        unStrStr_loop:
-                IntOp $2 $2 + 1
-                IntCmp $2 $4 0 0 unStrStrReturn_notFound
-                StrCpy $5 $1 $3 $2
-                StrCmp $5 $0 unStrStr_done unStrStr_loop
-        unStrStrReturn_notFound:
-                StrCpy $2 -1
-        unStrStr_done:
-                Pop $5
-                Pop $4
-                Pop $3
-                Exch $2
-                Exch 2
-                Pop $0
-                Pop $1
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-; Commentary and smarter ';' checking by Jon Parise <[email protected]>
-Function AddToPath
-        Exch $0
-        Push $1
-        Push $2
-        Push $3
-        Call IsNT
-        Pop $1
-
-        StrCmp $1 1 AddToPath_NT
-                ; We're not on NT, so modify the AUTOEXEC.BAT file.
-                StrCpy $1 $WINDIR 2
-                FileOpen $1 "$1\autoexec.bat" a
-                FileSeek $1 0 END
-                GetFullPathName /SHORT $0 $0
-                FileWrite $1 "$\r$\nSET PATH=%PATH%;$0$\r$\n"
-                FileClose $1
-                Goto AddToPath_done
-        
-        AddToPath_NT:
-                ReadRegStr $1 HKCU "Environment" "PATH"
-                Call IsUserAdmin
-                Pop $3
-                ; If this is an Admin user, use the System env. variable instead of the user's env. variable
-                StrCmp $3 1 0 +2
-                        ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
-
-                ; If the PATH string is empty, jump over the mangling routines.
-                StrCmp $1 "" AddToPath_NTdoIt
-
-                ; Pull off the last character of the PATH string.  If it's a semicolon,
-                ; we don't need to add another one, so jump to the section where we
-                ; append the new PATH component(s).
-                StrCpy $2 $1 1 -1
-                StrCmp $2 ";" AddToPath_NTAddPath AddToPath_NTAddSemi
-
-                AddToPath_NTAddSemi:
-                        StrCpy $1 "$1;"
-                        Goto AddToPath_NTAddPath
-                AddToPath_NTAddPath:
-                        StrCpy $0 "$1$0"
-                        Goto AddToPath_NTdoIt
-                AddToPath_NTdoIt:
-                        Call IsUserAdmin
-                        Pop $3
-                        StrCmp $3 1 0 NotAdmin
-                                WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $0
-                                Goto AddToPath_done
-                        
-                        NotAdmin:
-                                WriteRegExpandStr HKCU "Environment" "PATH" $0
-        AddToPath_done:
-                SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
-                Pop $3
-                Pop $2
-                Pop $1
-                Pop $0
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-Function RemoveFromPath
-        Exch $0
-        Push $1
-        Push $2
-        Push $3
-        Push $4
-        Push $5
-        Call IsNT
-        Pop $1
-        StrCmp $1 1 unRemoveFromPath_NT
-                ; Not on NT
-                StrCpy $1 $WINDIR 2
-                FileOpen $1 "$1\autoexec.bat" r
-                GetTempFileName $4
-                FileOpen $2 $4 w
-                GetFullPathName /SHORT $0 $0
-                StrCpy $0 "SET PATH=%PATH%;$0"
-                SetRebootFlag true
-                Goto unRemoveFromPath_dosLoop
-
-                unRemoveFromPath_dosLoop:
-                        FileRead $1 $3
-                        StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoop
-                        StrCmp $3 "$0$\n" unRemoveFromPath_dosLoop
-                        StrCmp $3 "$0" unRemoveFromPath_dosLoop
-                        StrCmp $3 "" unRemoveFromPath_dosLoopEnd
-                        FileWrite $2 $3
-                        Goto unRemoveFromPath_dosLoop
-
-                unRemoveFromPath_dosLoopEnd:
-                        FileClose $2
-                        FileClose $1
-                        StrCpy $1 $WINDIR 2
-                        Delete "$1\autoexec.bat"
-                        CopyFiles /SILENT $4 "$1\autoexec.bat"
-                        Delete $4
-                        Goto unRemoveFromPath_done
-
-                unRemoveFromPath_NT:
-                        StrLen $2 $0
-                        Call IsUserAdmin
-                        Pop $5
-                        StrCmp $5 1 0 NotAdmin
-                                ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
-                                Push $1
-                                Push $0
-                                Call StrStr ; Find $0 in $1
-                                Pop $0 ; pos of our dir
-                                IntCmp $0 -1 unRemoveFromPath_done
-                                        ; else, it is in path
-                                        StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir
-                                        IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';')
-                                        IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.
-                                        StrLen $0 $1
-                                        StrCpy $1 $1 $0 $2
-                                        StrCpy $3 "$3$1"
-                                        WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $3
-                                        SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
-                                        Goto unRemoveFromPath_done
-                        
-                        
-                        NotAdmin:               
-                                ReadRegStr $1 HKCU "Environment" "PATH"
-                                Push $1
-                                Push $0
-                                Call StrStr ; Find $0 in $1
-                                Pop $0 ; pos of our dir
-                                IntCmp $0 -1 unRemoveFromPath_done
-                                        ; else, it is in path
-                                        StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir
-                                        IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';')
-                                        IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.
-                                        StrLen $0 $1
-                                        StrCpy $1 $1 $0 $2
-                                        StrCpy $3 "$3$1"
-                                        WriteRegExpandStr HKCU "Environment" "PATH" $3
-                                        SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
-
-                unRemoveFromPath_done:
-                        Pop $5
-                        Pop $4
-                        Pop $3
-                        Pop $2
-                        Pop $1
-                        Pop $0
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
-Function un.RemoveFromPath
-        Exch $0
-        Push $1
-        Push $2
-        Push $3
-        Push $4
-        Push $5
-        Call un.IsNT
-        Pop $1
-        StrCmp $1 1 unRemoveFromPath_NT
-                ; Not on NT
-                StrCpy $1 $WINDIR 2
-                FileOpen $1 "$1\autoexec.bat" r
-                GetTempFileName $4
-                FileOpen $2 $4 w
-                GetFullPathName /SHORT $0 $0
-                StrCpy $0 "SET PATH=%PATH%;$0"
-                SetRebootFlag true
-                Goto unRemoveFromPath_dosLoop
-
-                unRemoveFromPath_dosLoop:
-                        FileRead $1 $3
-                        StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoop
-                        StrCmp $3 "$0$\n" unRemoveFromPath_dosLoop
-                        StrCmp $3 "$0" unRemoveFromPath_dosLoop
-                        StrCmp $3 "" unRemoveFromPath_dosLoopEnd
-                        FileWrite $2 $3
-                        Goto unRemoveFromPath_dosLoop
-
-                unRemoveFromPath_dosLoopEnd:
-                        FileClose $2
-                        FileClose $1
-                        StrCpy $1 $WINDIR 2
-                        Delete "$1\autoexec.bat"
-                        CopyFiles /SILENT $4 "$1\autoexec.bat"
-                        Delete $4
-                        Goto unRemoveFromPath_done
-
-                unRemoveFromPath_NT:
-                        StrLen $2 $0
-                        Call un.IsUserAdmin
-                        Pop $5
-                        StrCmp $5 1 0 NotAdmin
-                                ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
-                                Push $1
-                                Push $0
-                                Call un.StrStr ; Find $0 in $1
-                                Pop $0 ; pos of our dir
-                                IntCmp $0 -1 unRemoveFromPath_done
-                                        ; else, it is in path
-                                        StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir
-                                        IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';')
-                                        IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.
-                                        StrLen $0 $1
-                                        StrCpy $1 $1 $0 $2
-                                        StrCpy $3 "$3$1"
-                                        WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $3
-                                        SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
-                                        Goto unRemoveFromPath_done
-                        
-                        
-                        NotAdmin:               
-                                ReadRegStr $1 HKCU "Environment" "PATH"
-                                Push $1
-                                Push $0
-                                Call un.StrStr ; Find $0 in $1
-                                Pop $0 ; pos of our dir
-                                IntCmp $0 -1 unRemoveFromPath_done
-                                        ; else, it is in path
-                                        StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir
-                                        IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';')
-                                        IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.
-                                        StrLen $0 $1
-                                        StrCpy $1 $1 $0 $2
-                                        StrCpy $3 "$3$1"
-                                        WriteRegExpandStr HKCU "Environment" "PATH" $3
-                                        SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
-
-                unRemoveFromPath_done:
-                        Pop $5
-                        Pop $4
-                        Pop $3
-                        Pop $2
-                        Pop $1
-                        Pop $0
-FunctionEnd
-
-; From: http://nsis.sourceforge.net/archive/nsisweb.php?page=329&instances=0,11
-; Localized by Ben Johnson ([email protected])
-Function IsUserAdmin
-        Push $0
-        Push $1
-        Push $2
-        Push $3
-        Call IsNT
-        Pop $1
-
-        ClearErrors
-        UserInfo::GetName
-        ;IfErrors Win9x
-        Pop $2
-        UserInfo::GetAccountType
-        Pop $3
-
-        ; Compare results of IsNT with "1"
-        StrCmp $1 1 0 NotNT
-                ;This is NT
-                
-
-                StrCmp $3 "Admin" 0 NotAdmin
-                        ; Observation: I get here when running Win98SE. (Lilla)
-                        ; The functions UserInfo.dll looks for are there on Win98 too, 
-                        ; but just don't work. So UserInfo.dll, knowing that admin isn't required
-                        ; on Win98, returns admin anyway. (per kichik)
-                        ; MessageBox MB_OK 'User "$R1" is in the Administrators group'
-                        Pop $3
-                        Pop $2
-                        Pop $1
-                        Pop $0
-
-                        Push 1
-                        Return
-
-                NotAdmin:
-                        ; You should still check for an empty string because the functions
-                        ; UserInfo.dll looks for may not be present on Windows 95. (per kichik)
-                
-                        #StrCmp $2 "" Win9x
-                        #StrCpy $0 0
-                        ;MessageBox MB_OK 'User "$2" is in the "$3" group'
-                        Pop $3
-                        Pop $2
-                        Pop $1
-                        Pop $0
-
-                        Push 0
-                        Return
-
-        ;Because we use IsNT, this is redundant.
-        #Win9x:
-        #       ; comment/message below is by UserInfo.nsi author:
-        #       ; This one means you don't need to care about admin or
-        #       ; not admin because Windows 9x doesn't either
-        #       ;MessageBox MB_OK "Error! This DLL can't run under Windows 9x!"
-        #       StrCpy $0 0
-
-        NotNT:
-                ;We are not NT
-                ;Win9x doesn't have "admin" users.
-                ;Let the user do whatever.
-                Pop $3
-                Pop $2
-                Pop $1
-                Pop $0
-
-                Push 1
-
-FunctionEnd
-
-Function un.IsUserAdmin
-        Push $0
-        Push $1
-        Push $2
-        Push $3
-        Call un.IsNT
-        Pop $1
-
-        ClearErrors
-        UserInfo::GetName
-        ;IfErrors Win9x
-        Pop $2
-        UserInfo::GetAccountType
-        Pop $3
-
-        ; Compare results of IsNT with "1"
-        StrCmp $1 1 0 NotNT
-                ;This is NT
-                
-
-                StrCmp $3 "Admin" 0 NotAdmin
-                        ; Observation: I get here when running Win98SE. (Lilla)
-                        ; The functions UserInfo.dll looks for are there on Win98 too, 
-                        ; but just don't work. So UserInfo.dll, knowing that admin isn't required
-                        ; on Win98, returns admin anyway. (per kichik)
-                        ; MessageBox MB_OK 'User "$R1" is in the Administrators group'
-                        Pop $3
-                        Pop $2
-                        Pop $1
-                        Pop $0
-
-                        Push 1
-                        Return
-
-                NotAdmin:
-                        ; You should still check for an empty string because the functions
-                        ; UserInfo.dll looks for may not be present on Windows 95. (per kichik)
-                
-                        #StrCmp $2 "" Win9x
-                        #StrCpy $0 0
-                        ;MessageBox MB_OK 'User "$2" is in the "$3" group'
-                        Pop $3
-                        Pop $2
-                        Pop $1
-                        Pop $0
-
-                        Push 0
-                        Return
-
-        ;Because we use IsNT, this is redundant.
-        #Win9x:
-        #       ; comment/message below is by UserInfo.nsi author:
-        #       ; This one means you don't need to care about admin or
-        #       ; not admin because Windows 9x doesn't either
-        #       ;MessageBox MB_OK "Error! This DLL can't run under Windows 9x!"
-        #       StrCpy $0 0
-
-        NotNT:
-                ;We are not NT
-                ;Win9x doesn't have "admin" users.
-                ;Let the user do whatever.
-                Pop $3
-                Pop $2
-                Pop $1
-                Pop $0
-
-                Push 1
-
-FunctionEnd
-
-Function StrRep
-
-  ;Written by dirtydingus 2003-02-20 04:30:09 
-  ; USAGE
-  ;Push String to do replacement in (haystack)
-  ;Push String to replace (needle)
-  ;Push Replacement
-  ;Call StrRep
-  ;Pop $R0 result
-  ;StrCpy $Result STR $R0
-
-  Exch $R4 ; $R4 = Replacement String
-  Exch
-  Exch $R3 ; $R3 = String to replace (needle)
-  Exch 2
-  Exch $R1 ; $R1 = String to do replacement in (haystack)
-  Push $R2 ; Replaced haystack
-  Push $R5 ; Len (needle)
-  Push $R6 ; len (haystack)
-  Push $R7 ; Scratch reg
-  StrCpy $R2 ""
-  StrLen $R5 $R3
-  StrLen $R6 $R1
-loop:
-  StrCpy $R7 $R1 $R5
-  StrCmp $R7 $R3 found
-  StrCpy $R7 $R1 1 ; - optimization can be removed if U know len needle=1
-  StrCpy $R2 "$R2$R7"
-  StrCpy $R1 $R1 $R6 1
-  StrCmp $R1 "" done loop
-found:
-  StrCpy $R2 "$R2$R4"
-  StrCpy $R1 $R1 $R6 $R5
-  StrCmp $R1 "" done loop
-done:
-  StrCpy $R3 $R2
-  Pop $R7
-  Pop $R6
-  Pop $R5
-  Pop $R2
-  Pop $R1
-  Pop $R4
-  Exch $R3
-  
-FunctionEnd
-

+ 0 - 421
direct/src/directscripts/packpanda.py

@@ -1,421 +0,0 @@
-#############################################################################
-#
-# packpanda - this is a tool that packages up a panda game into a
-# convenient, easily-downloaded windows executable.  Packpanda runs on linux
-# and windows - on linux, it builds .debs and .rpms, on windows it relies on
-# NSIS, the nullsoft scriptable install system, to do the hard work.
-#
-# This is intentionally a very simplistic game-packer with very
-# limited options.  The goal is simplicity, not feature richness.
-# There are dozens of complex, powerful packaging tools already out
-# there.  This one is for people who just want to do it quick and
-# easy.
-#
-##############################################################################
-
-import sys, os, getopt, shutil, py_compile, subprocess
-
-OPTIONLIST = [
-("dir",       1, "Name of directory containing game"),
-("name",      1, "Human-readable name of the game"),
-("version",   1, "Version number to add to game name"),
-("rmdir",     2, "Delete all directories with given name"),
-("rmext",     2, "Delete all files with given extension"),
-("fast",      0, "Use fast compression instead of good compression"),
-("bam",       0, "Generate BAM files, change default-model-extension to BAM"),
-("pyc",       0, "Generate PYC files"),
-]
-
-def ParseFailure():
-  print("")
-  print("packpanda usage:")
-  print("")
-  for (opt, hasval, explanation) in OPTIONLIST:
-    if (hasval):
-      print("  --%-10s    %s"%(opt+" x", explanation))
-    else:
-      print("  --%-10s    %s"%(opt+"  ", explanation))
-  sys.exit(1)
-
-def ParseOptions(args):
-  try:
-    options = {}
-    longopts = []
-    for (opt, hasval, explanation) in OPTIONLIST:
-      if (hasval==2):
-        longopts.append(opt+"=")
-        options[opt] = []
-      elif (hasval==1):
-        longopts.append(opt+"=")
-        options[opt] = ""
-      else:
-        longopts.append(opt)
-        options[opt] = 0
-    opts, extras = getopt.getopt(args, "", longopts)
-    for option, value in opts:
-      for (opt, hasval, explanation) in OPTIONLIST:
-        if (option == "--"+opt):
-          if (hasval==2): options[opt].append(value)
-          elif (hasval==1): options[opt] = value
-          else: options[opt] = 1
-    return options
-  except: ParseFailure();
-
-OPTIONS = ParseOptions(sys.argv[1:])
-
-##############################################################################
-#
-# Locate the relevant trees.
-#
-##############################################################################
-
-PANDA=None
-for dir in sys.path:
-    if (dir != "") and os.path.exists(os.path.join(dir,"direct")) and os.path.exists(os.path.join(dir,"pandac")):
-        PANDA=os.path.abspath(dir)
-if (PANDA is None):
-  sys.exit("Cannot locate the panda root directory in the python path (cannot locate directory containing direct and pandac).")
-print("PANDA located at "+PANDA)
-
-if (os.path.exists(os.path.join(PANDA,"..","makepanda","makepanda.py"))) and (sys.platform != "win32" or os.path.exists(os.path.join(PANDA,"..","thirdparty","win-nsis","makensis.exe"))):
-  PSOURCE=os.path.abspath(os.path.join(PANDA,".."))
-  if (sys.platform == "win32"):
-    NSIS=os.path.abspath(os.path.join(PANDA,"..","thirdparty","win-nsis"))
-else:
-  PSOURCE=PANDA
-  if (sys.platform == "win32"):
-    NSIS=os.path.join(PANDA,"nsis")
-
-##############################################################################
-#
-# Identify the main parts of the game: DIR, NAME, MAIN, ICON, BITMAP, etc
-#
-##############################################################################
-
-VER=OPTIONS["version"]
-DIR=OPTIONS["dir"]
-if (DIR==""):
-  print("You must specify the --dir option.")
-  ParseFailure()
-DIR=os.path.abspath(DIR)
-MYDIR=os.path.abspath(os.getcwd())
-BASENAME=os.path.basename(DIR)
-if (OPTIONS["name"] != ""):
-  NAME=OPTIONS["name"]
-else:
-  NAME=BASENAME
-SMDIRECTORY=NAME
-if (VER!=""): SMDIRECTORY=SMDIRECTORY+" "+VER
-PYTHONV="python"+sys.version[:3]
-LICENSE=os.path.join(DIR, "license.txt")
-OUTFILE=os.path.basename(DIR)
-if (VER!=""): OUTFILE=OUTFILE+"-"+VER
-if (sys.platform == "win32"):
-  ICON=os.path.join(DIR, "icon.ico")
-  BITMAP=os.path.join(DIR, "installer.bmp")
-  OUTFILE=os.path.abspath(OUTFILE+".exe")
-  INSTALLDIR='C:\\'+os.path.basename(DIR)
-  if (VER!=""): INSTALLDIR=INSTALLDIR+"-"+VER
-  COMPRESS="lzma"
-  if (OPTIONS["fast"]): COMPRESS="zlib"
-if (OPTIONS["pyc"]): MAIN="main.pyc"
-else: MAIN="main.py"
-
-def PrintFileStatus(label, file):
-  if (os.path.exists(file)):
-    print("%-15s: %s"%(label, file))
-  else:
-    print("%-15s: %s (MISSING)"%(label, file))
-
-PrintFileStatus("Dir", DIR)
-print("%-15s: %s"%("Name", NAME))
-print("%-15s: %s"%("Start Menu", SMDIRECTORY))
-PrintFileStatus("Main", os.path.join(DIR, MAIN))
-if (sys.platform == "win32"):
-  PrintFileStatus("Icon", ICON)
-  PrintFileStatus("Bitmap", BITMAP)
-PrintFileStatus("License", LICENSE)
-print("%-15s: %s"%("Output", OUTFILE))
-if (sys.platform == "win32"):
-  print("%-15s: %s"%("Install Dir", INSTALLDIR))
-
-if (os.path.isdir(DIR)==0):
-  sys.exit("Difficulty reading "+DIR+". Cannot continue.")
-
-if (os.path.isfile(os.path.join(DIR, "main.py"))==0):
-  sys.exit("Difficulty reading main.py. Cannot continue.")
-
-if (os.path.isfile(LICENSE)==0):
-  LICENSE=os.path.join(PANDA,"LICENSE")
-
-if (sys.platform == "win32") and (os.path.isfile(BITMAP)==0):
-  BITMAP=os.path.join(NSIS,"Contrib","Graphics","Wizard","nsis.bmp")
-
-if (sys.platform == "win32"):
-  if (os.path.isfile(ICON)==0):
-    PPICON="bin\\ppython.exe"
-  else:
-    PPICON="game\\icon.ico"
-
-##############################################################################
-#
-# Copy the game to a temporary directory, so we can modify it safely.
-#
-##############################################################################
-
-def limitedCopyTree(src, dst, rmdir):
-    if (os.path.isdir(src)):
-        if (os.path.basename(src) in rmdir):
-            return
-        if (not os.path.isdir(dst)): os.mkdir(dst)
-        for x in os.listdir(src):
-            limitedCopyTree(os.path.join(src,x), os.path.join(dst,x), rmdir)
-    else:
-        shutil.copyfile(src, dst)
-
-
-TMPDIR=os.path.abspath("packpanda-TMP")
-if (sys.platform == "win32"):
-  TMPGAME=os.path.join(TMPDIR,"game")
-  TMPETC=os.path.join(TMPDIR,"etc")
-else:
-  TMPGAME=os.path.join(TMPDIR,"usr","share","games",BASENAME,"game")
-  TMPETC=os.path.join(TMPDIR,"usr","share","games",BASENAME,"etc")
-print("")
-print("Copying the game to "+TMPDIR+"...")
-if (os.path.exists(TMPDIR)):
-    try: shutil.rmtree(TMPDIR)
-    except: sys.exit("Cannot delete "+TMPDIR)
-try:
-    os.mkdir(TMPDIR)
-    rmdir = {}
-    for x in OPTIONS["rmdir"]:
-        rmdir[x] = 1
-    if not os.path.isdir( TMPGAME ):
-        os.makedirs(TMPGAME)
-    limitedCopyTree(DIR, TMPGAME, rmdir)
-    if not os.path.isdir( TMPETC ):
-        os.makedirs(TMPETC)
-    if sys.platform == "win32":
-      limitedCopyTree(os.path.join(PANDA, "etc"), TMPETC, {})
-    else:
-      shutil.copyfile("/etc/Config.prc", os.path.join(TMPETC, "Config.prc"))
-      shutil.copyfile("/etc/Confauto.prc", os.path.join(TMPETC, "Confauto.prc"))
-except: sys.exit("Cannot copy game to "+TMPDIR)
-
-##############################################################################
-#
-# If --bam requested, change default-model-extension .egg to bam.
-#
-##############################################################################
-
-def ReadFile(wfile):
-    try:
-        srchandle = open(wfile, "rb")
-        data = srchandle.read()
-        srchandle.close()
-        return data
-    except: exit("Cannot read "+wfile)
-
-def WriteFile(wfile,data):
-    try:
-        dsthandle = open(wfile, "wb")
-        dsthandle.write(data)
-        dsthandle.close()
-    except: exit("Cannot write "+wfile)
-
-if OPTIONS["bam"]:
-    CONF=ReadFile(os.path.join(TMPETC,"Confauto.prc"))
-    CONF=CONF.replace("default-model-extension .egg","default-model-extension .bam")
-    WriteFile(os.path.join(TMPETC,"Confauto.prc"), CONF)
-
-##############################################################################
-#
-# Compile all py files, convert all egg files.
-#
-# We do this as a sanity check, even if the user
-# hasn't requested that his files be compiled.
-#
-##############################################################################
-
-if (sys.platform == "win32"):
-  EGG2BAM=os.path.join(PANDA,"bin","egg2bam.exe")
-else:
-  EGG2BAM=os.path.join(PANDA,"bin","egg2bam")
-
-def egg2bam(file,bam):
-    present = os.path.exists(bam)
-    if (present): bam = "packpanda-TMP.bam";
-    cmd = 'egg2bam -noabs -ps rel -pd . "'+file+'" -o "'+bam+'"'
-    print("Executing: "+cmd)
-    if (sys.platform == "win32"):
-      res = os.spawnl(os.P_WAIT, EGG2BAM, cmd)
-    else:
-      res = os.system(cmd)
-    if (res != 0): sys.exit("Problem in egg file: "+file)
-    if (present) or (OPTIONS["bam"]==0):
-        os.unlink(bam)
-
-def py2pyc(file):
-    print("Compiling python "+file)
-    pyc = file[:-3]+'.pyc'
-    pyo = file[:-3]+'.pyo'
-    if (os.path.exists(pyc)): os.unlink(pyc)
-    if (os.path.exists(pyo)): os.unlink(pyo)
-    try: py_compile.compile(file)
-    except: sys.exit("Cannot compile "+file)
-    if (OPTIONS["pyc"]==0):
-        if (os.path.exists(pyc)):
-            os.unlink(pyc)
-        if (os.path.exists(pyo)):
-            os.unlink(pyo)
-
-def CompileFiles(file):
-    if (os.path.isfile(file)):
-        if (file.endswith(".egg")):
-            egg2bam(file, file[:-4]+'.bam')
-        elif (file.endswith(".egg.pz") or file.endswith(".egg.gz")):
-            egg2bam(file, file[:-7]+'.bam')
-        elif (file.endswith(".py")):
-            py2pyc(file)
-        else: pass
-    elif (os.path.isdir(file)):
-        for x in os.listdir(file):
-            CompileFiles(os.path.join(file, x))
-
-def DeleteFiles(file):
-    base = os.path.basename(file).lower()
-    if (os.path.isdir(file)):
-        for pattern in OPTIONS["rmdir"]:
-            if pattern.lower() == base:
-                print("Deleting "+file)
-                shutil.rmtree(file)
-                return
-        for x in os.listdir(file):
-            DeleteFiles(os.path.join(file, x))
-    else:
-        for ext in OPTIONS["rmext"]:
-            if base[-(len(ext) + 1):] == ("." + ext).lower():
-                print("Deleting "+file)
-                os.unlink(file)
-                return
-
-print("")
-print("Compiling BAM and PYC files...")
-os.chdir(TMPGAME)
-CompileFiles(".")
-DeleteFiles(".")
-
-##############################################################################
-#
-# Now make the installer. Yay!
-#
-##############################################################################
-
-INSTALLER_DEB_FILE="""
-Package: BASENAME
-Version: VERSION
-Section: games
-Priority: optional
-Architecture: ARCH
-Essential: no
-Depends: PYTHONV
-Provides: BASENAME
-Description: NAME
-Maintainer: Unknown
-"""
-
-INSTALLER_SPEC_FILE="""
-Summary: NAME
-Name: BASENAME
-Version: VERSION
-Release: 1
-Group: Amusement/Games
-License: See license file
-BuildRoot: TMPDIR
-BuildRequires: PYTHONV
-%description
-NAME
-%files
-%defattr(-,root,root)
-/usr/bin/BASENAME
-/usr/lib/games/BASENAME
-/usr/share/games/BASENAME
-"""
-
-RUN_SCRIPT="""
-#!/bin/sh
-cd /usr/share/games/BASENAME/game
-PYTHONPATH=/usr/lib/games/BASENAME:/usr/share/games/BASENAME
-LD_LIBRARY_PATH=/usr/lib/games/BASENAME
-PYTHONV MAIN
-"""
-
-if (sys.platform == "win32"):
-    CMD="\""+NSIS+"\\makensis.exe\" /V2 "
-    CMD=CMD+'/DCOMPRESSOR="'+COMPRESS+'" '
-    CMD=CMD+'/DNAME="'+NAME+'" '
-    CMD=CMD+'/DSMDIRECTORY="'+SMDIRECTORY+'" '
-    CMD=CMD+'/DINSTALLDIR="'+INSTALLDIR+'" '
-    CMD=CMD+'/DOUTFILE="'+OUTFILE+'" '
-    CMD=CMD+'/DLICENSE="'+LICENSE+'" '
-    CMD=CMD+'/DLANGUAGE="English" '
-    CMD=CMD+'/DRUNTEXT="Play '+NAME+'" '
-    CMD=CMD+'/DIBITMAP="'+BITMAP+'" '
-    CMD=CMD+'/DUBITMAP="'+BITMAP+'" '
-    CMD=CMD+'/DPANDA="'+PANDA+'" '
-    CMD=CMD+'/DPANDACONF="'+TMPETC+'" '
-    CMD=CMD+'/DPSOURCE="'+PSOURCE+'" '
-    CMD=CMD+'/DPPGAME="'+TMPGAME+'" '
-    CMD=CMD+'/DPPMAIN="'+MAIN+'" '
-    CMD=CMD+'/DPPICON="'+PPICON+'" '
-    CMD=CMD+'"'+PSOURCE+'\\direct\\directscripts\\packpanda.nsi"'
-
-    print("")
-    print(CMD)
-    print("packing...")
-    subprocess.call(CMD)
-else:
-    os.chdir(MYDIR)
-    os.system("mkdir -p %s/usr/bin" % TMPDIR)
-    os.system("mkdir -p %s/usr/share/games/%s" % (TMPDIR, BASENAME))
-    os.system("mkdir -p %s/usr/lib/games/%s" % (TMPDIR, BASENAME))
-    os.system("cp --recursive %s/direct          %s/usr/share/games/%s/direct" % (PANDA, TMPDIR, BASENAME))
-    os.system("cp --recursive %s/pandac          %s/usr/share/games/%s/pandac" % (PANDA, TMPDIR, BASENAME))
-    os.system("cp --recursive %s/models          %s/usr/share/games/%s/models" % (PANDA, TMPDIR, BASENAME))
-    os.system("cp --recursive %s/Pmw             %s/usr/share/games/%s/Pmw" % (PANDA, TMPDIR, BASENAME))
-    os.system("cp %s                             %s/usr/share/games/%s/LICENSE" % (LICENSE, TMPDIR, BASENAME))
-    os.system("cp --recursive /usr/lib/panda3d/* %s/usr/lib/games/%s/" % (TMPDIR, BASENAME))
-
-    # Make the script to run the game
-    txt = RUN_SCRIPT[1:].replace("BASENAME",BASENAME).replace("PYTHONV",PYTHONV).replace("MAIN",MAIN)
-    WriteFile(TMPDIR+"/usr/bin/"+BASENAME, txt)
-    os.system("chmod +x "+TMPDIR+"/usr/bin/"+BASENAME)
-
-    if (os.path.exists("/usr/bin/rpmbuild")):
-        os.system("rm -rf %s/DEBIAN" % TMPDIR)
-        os.system("rpm -E '%_target_cpu' > packpanda-TMP.txt")
-        ARCH=ReadFile("packpanda-TMP.txt").strip()
-        os.remove("packpanda-TMP.txt")
-        txt = INSTALLER_SPEC_FILE[1:].replace("VERSION",VER).replace("TMPDIR",TMPDIR)
-        txt = txt.replace("BASENAME",BASENAME).replace("NAME",NAME).replace("PYTHONV",PYTHONV)
-        WriteFile("packpanda-TMP.spec", txt)
-        os.system("rpmbuild --define '_rpmdir "+TMPDIR+"' -bb packpanda-TMP.spec")
-        os.system("mv "+ARCH+"/"+BASENAME+"-"+VER+"-1."+ARCH+".rpm .")
-        os.rmdir(ARCH)
-        os.remove("packpanda-TMP.spec")
-
-    if (os.path.exists("/usr/bin/dpkg-deb")):
-        os.system("dpkg --print-architecture > packpanda-TMP.txt")
-        ARCH=ReadFile("packpanda-TMP.txt").strip()
-        os.remove("packpanda-TMP.txt")
-        txt = INSTALLER_DEB_FILE[1:].replace("VERSION",str(VER)).replace("PYTHONV",PYTHONV)
-        txt = txt.replace("BASENAME",BASENAME).replace("NAME",NAME).replace("ARCH",ARCH)
-        os.system("mkdir -p %s/DEBIAN" % TMPDIR)
-        os.system("cd %s ; (find usr -type f -exec md5sum {} \;) >  DEBIAN/md5sums" % TMPDIR)
-        WriteFile(TMPDIR+"/DEBIAN/control",txt)
-        os.system("dpkg-deb -b "+TMPDIR+" "+BASENAME+"_"+VER+"_"+ARCH+".deb")
-
-    if not(os.path.exists("/usr/bin/rpmbuild") or os.path.exists("/usr/bin/dpkg-deb")):
-        exit("To build an installer, either rpmbuild or dpkg-deb must be present on your system!")
-

+ 1 - 1
direct/src/directtools/DirectCameraControl.py

@@ -413,7 +413,7 @@ class DirectCameraControl(DirectObject):
                 np = NodePath('temp')
                 np = NodePath('temp')
                 np.setPos(base.direct.camera, hitPt)
                 np.setPos(base.direct.camera, hitPt)
                 self.coaMarkerPos = np.getPos()
                 self.coaMarkerPos = np.getPos()
-                np.remove()
+                np.removeNode()
                 self.coaMarker.setPos(self.coaMarkerPos)
                 self.coaMarker.setPos(self.coaMarkerPos)
 
 
             iRay.collisionNodePath.removeNode()
             iRay.collisionNodePath.removeNode()

+ 3 - 3
direct/src/directtools/DirectManipulation.py

@@ -186,7 +186,7 @@ class DirectManipulationControl(DirectObject):
 
 
     def drawMarquee(self, startX, startY):
     def drawMarquee(self, startX, startY):
         if self.marquee:
         if self.marquee:
-            self.marquee.remove()
+            self.marquee.removeNode()
             self.marquee = None
             self.marquee = None
 
 
         if base.direct.cameraControl.useMayaCamControls and base.direct.fAlt:
         if base.direct.cameraControl.useMayaCamControls and base.direct.fAlt:
@@ -228,7 +228,7 @@ class DirectManipulationControl(DirectObject):
             skipFlags |= SKIP_CAMERA * (1 - base.getControl())
             skipFlags |= SKIP_CAMERA * (1 - base.getControl())
 
 
             if self.marquee:
             if self.marquee:
-                self.marquee.remove()
+                self.marquee.removeNode()
                 self.marquee = None
                 self.marquee = None
                 base.direct.deselectAll()
                 base.direct.deselectAll()
 
 
@@ -1691,7 +1691,7 @@ class ObjectHandles(NodePath, DirectObject):
         np.setPos(base.direct.camera, hitPt)
         np.setPos(base.direct.camera, hitPt)
         resultPt = Point3(0)
         resultPt = Point3(0)
         resultPt.assign(np.getPos())
         resultPt.assign(np.getPos())
-        np.remove()
+        np.removeNode()
         del iRay
         del iRay
         return resultPt
         return resultPt
 
 

+ 1 - 1
direct/src/directtools/DirectSession.py

@@ -900,7 +900,7 @@ class DirectSession(DirectObject):
             # If nothing specified, try selected node path
             # If nothing specified, try selected node path
             nodePath = self.selected.last
             nodePath = self.selected.last
         if nodePath:
         if nodePath:
-            nodePath.remove()
+            nodePath.removeNode()
 
 
     def removeAllSelected(self):
     def removeAllSelected(self):
         self.selected.removeAll()
         self.selected.removeAll()

+ 1 - 1
direct/src/distributed/CartesianGridBase.py

@@ -1,4 +1,4 @@
-from pandac.PandaModules import Vec3
+from panda3d.core import Vec3
 # Utility functions that are useful to both AI and client CartesianGrid code
 # Utility functions that are useful to both AI and client CartesianGrid code
 
 
 class CartesianGridBase:
 class CartesianGridBase:

+ 2 - 1
direct/src/distributed/ClientRepositoryBase.py

@@ -1,4 +1,5 @@
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 from .MsgTypes import *
 from .MsgTypes import *
 from direct.task import Task
 from direct.task import Task
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal

+ 2 - 1
direct/src/distributed/ConnectionRepository.py

@@ -1,4 +1,5 @@
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 from direct.task import Task
 from direct.task import Task
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.distributed.DoInterestManager import DoInterestManager
 from direct.distributed.DoInterestManager import DoInterestManager

+ 2 - 1
direct/src/distributed/DistributedCamera.py

@@ -1,4 +1,5 @@
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 from direct.fsm.FSM import FSM
 from direct.fsm.FSM import FSM
 from direct.interval.IntervalGlobal import *
 from direct.interval.IntervalGlobal import *
 from direct.distributed.DistributedObject import DistributedObject
 from direct.distributed.DistributedObject import DistributedObject

+ 2 - 1
direct/src/distributed/DistributedCameraOV.py

@@ -1,4 +1,5 @@
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 from direct.distributed.DistributedObjectOV import DistributedObjectOV
 from direct.distributed.DistributedObjectOV import DistributedObjectOV
 
 
 class DistributedCameraOV(DistributedObjectOV):
 class DistributedCameraOV(DistributedObjectOV):

+ 2 - 1
direct/src/distributed/DistributedCartesianGrid.py

@@ -1,5 +1,6 @@
 
 
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 from direct.interval.IntervalGlobal import *
 from direct.interval.IntervalGlobal import *
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
 
 

+ 2 - 1
direct/src/distributed/DistributedCartesianGridAI.py

@@ -1,5 +1,6 @@
 
 
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.task import Task
 from direct.task import Task
 from .DistributedNodeAI import DistributedNodeAI
 from .DistributedNodeAI import DistributedNodeAI

+ 1 - 1
direct/src/distributed/DistributedNodeAI.py

@@ -1,4 +1,4 @@
-from pandac.PandaModules import NodePath
+from panda3d.core import NodePath
 from . import DistributedObjectAI
 from . import DistributedObjectAI
 from . import GridParent
 from . import GridParent
 
 

+ 4 - 2
direct/src/distributed/DistributedObject.py

@@ -4,7 +4,6 @@ from panda3d.core import *
 from panda3d.direct import *
 from panda3d.direct import *
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.distributed.DistributedObjectBase import DistributedObjectBase
 from direct.distributed.DistributedObjectBase import DistributedObjectBase
-from direct.showbase.PythonUtil import StackTrace
 #from PyDatagram import PyDatagram
 #from PyDatagram import PyDatagram
 #from PyDatagramIterator import PyDatagramIterator
 #from PyDatagramIterator import PyDatagramIterator
 
 
@@ -259,7 +258,10 @@ class DistributedObject(DistributedObjectBase):
     def _destroyDO(self):
     def _destroyDO(self):
         # after this is called, the object is no longer a DistributedObject
         # after this is called, the object is no longer a DistributedObject
         # but may still be used as a DelayDeleted object
         # but may still be used as a DelayDeleted object
-        self.destroyDoStackTrace = StackTrace()
+        if __debug__:
+            # StackTrace is omitted in packed versions
+            from direct.showbase.PythonUtil import StackTrace
+            self.destroyDoStackTrace = StackTrace()
         # check for leftover cached data that was not retrieved or flushed by this object
         # check for leftover cached data that was not retrieved or flushed by this object
         # this will catch typos in the data name in calls to get/setCachedData
         # this will catch typos in the data name in calls to get/setCachedData
         if hasattr(self, '_cachedData'):
         if hasattr(self, '_cachedData'):

+ 0 - 1
direct/src/distributed/DistributedObjectBase.py

@@ -13,7 +13,6 @@ class DistributedObjectBase(DirectObject):
     def __init__(self, cr):
     def __init__(self, cr):
         assert self.notify.debugStateCall(self)
         assert self.notify.debugStateCall(self)
         self.cr = cr
         self.cr = cr
-        self.children = {}
         self.parentId = None
         self.parentId = None
         self.zoneId = None
         self.zoneId = None
 
 

+ 6 - 6
direct/src/distributed/DistributedObjectGlobalUD.py

@@ -26,16 +26,16 @@ class DistributedObjectGlobalUD(DistributedObjectUD):
 
 
     def execCommand(self, command, mwMgrId, avId, zoneId):
     def execCommand(self, command, mwMgrId, avId, zoneId):
         text = str(self.__execMessage(command))[:config.GetInt("ai-debug-length",300)]
         text = str(self.__execMessage(command))[:config.GetInt("ai-debug-length",300)]
-
-        dclass = uber.air.dclassesByName.get("PiratesMagicWordManagerAI")
-        dg = dclass.aiFormatUpdate(
-            "setMagicWordResponse", mwMgrId, (1<<32)+avId, uber.air.ourChannel, [text])
-        uber.air.send(dg)
+        self.notify.info(text)
 
 
     def __execMessage(self, message):
     def __execMessage(self, message):
         if not self.ExecNamespace:
         if not self.ExecNamespace:
             # Import some useful variables into the ExecNamespace initially.
             # Import some useful variables into the ExecNamespace initially.
-            exec('from pandac.PandaModules import *', globals(), self.ExecNamespace)
+            import panda3d.core
+
+            for key, value in panda3d.core.__dict__.items():
+                if not key.startswith('__'):
+                    self.ExecNamespace[key] = value
             #self.importExecNamespace()
             #self.importExecNamespace()
 
 
         # Now try to evaluate the expression using ChatInputNormal.ExecNamespace as
         # Now try to evaluate the expression using ChatInputNormal.ExecNamespace as

+ 2 - 1
direct/src/distributed/DistributedObjectUD.py

@@ -3,7 +3,8 @@
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.distributed.DistributedObjectBase import DistributedObjectBase
 from direct.distributed.DistributedObjectBase import DistributedObjectBase
 from direct.showbase import PythonUtil
 from direct.showbase import PythonUtil
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 #from PyDatagram import PyDatagram
 #from PyDatagram import PyDatagram
 #from PyDatagramIterator import PyDatagramIterator
 #from PyDatagramIterator import PyDatagramIterator
 
 

+ 2 - 1
direct/src/distributed/DistributedSmoothNode.py

@@ -1,6 +1,7 @@
 """DistributedSmoothNode module: contains the DistributedSmoothNode class"""
 """DistributedSmoothNode module: contains the DistributedSmoothNode class"""
 
 
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 from .ClockDelta import *
 from .ClockDelta import *
 from . import DistributedNode
 from . import DistributedNode
 from . import DistributedSmoothNodeBase
 from . import DistributedSmoothNodeBase

+ 0 - 1
direct/src/distributed/DoCollectionManager.py

@@ -312,7 +312,6 @@ class DoCollectionManager:
         else:
         else:
             self.notify.warning('handleSetLocation: object %s not present' % self.getMsgChannel())
             self.notify.warning('handleSetLocation: object %s not present' % self.getMsgChannel())
 
 
-    @exceptionLogged()
     def storeObjectLocation(self, object, parentId, zoneId):
     def storeObjectLocation(self, object, parentId, zoneId):
         oldParentId = object.parentId
         oldParentId = object.parentId
         oldZoneId = object.zoneId
         oldZoneId = object.zoneId

+ 2 - 1
direct/src/distributed/DoInterestManager.py

@@ -7,7 +7,8 @@ zone, remove interest in that zone.
 p.s. A great deal of this code is just code moved from ClientRepository.py.
 p.s. A great deal of this code is just code moved from ClientRepository.py.
 """
 """
 
 
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 from .MsgTypes import *
 from .MsgTypes import *
 from direct.showbase.PythonUtil import *
 from direct.showbase.PythonUtil import *
 from direct.showbase import DirectObject
 from direct.showbase import DirectObject

+ 2 - 1
direct/src/distributed/GridParent.py

@@ -1,5 +1,6 @@
 
 
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 
 
 #
 #
 # GridParent.py
 # GridParent.py

+ 2 - 1
direct/src/distributed/ServerRepository.py

@@ -1,6 +1,7 @@
 """ServerRepository module: contains the ServerRepository class"""
 """ServerRepository module: contains the ServerRepository class"""
 
 
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 from direct.distributed.MsgTypesCMU import *
 from direct.distributed.MsgTypesCMU import *
 from direct.task import Task
 from direct.task import Task
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal

+ 0 - 7
direct/src/distributed/StagedObject.py

@@ -17,7 +17,6 @@ class StagedObject:
         call any "handle" functions.
         call any "handle" functions.
         """
         """
         self.__state = initState
         self.__state = initState
-        pass
 
 
     def goOnStage(self, *args, **kw):
     def goOnStage(self, *args, **kw):
         """
         """
@@ -29,8 +28,6 @@ class StagedObject:
 
 
         if not self.isOnStage():
         if not self.isOnStage():
             self.handleOnStage(*args, **kw)
             self.handleOnStage(*args, **kw)
-            pass
-        pass
 
 
     def handleOnStage(self):
     def handleOnStage(self):
         """
         """
@@ -39,7 +36,6 @@ class StagedObject:
         Don't forget to call down to this one, though.
         Don't forget to call down to this one, though.
         """
         """
         self.__state = StagedObject.ON
         self.__state = StagedObject.ON
-        pass
 
 
     def goOffStage(self, *args, **kw):
     def goOffStage(self, *args, **kw):
         """
         """
@@ -51,8 +47,6 @@ class StagedObject:
 
 
         if not self.isOffStage():
         if not self.isOffStage():
             self.handleOffStage(*args, **kw)
             self.handleOffStage(*args, **kw)
-            pass
-        pass
 
 
     def handleOffStage(self):
     def handleOffStage(self):
         """
         """
@@ -61,7 +55,6 @@ class StagedObject:
         Don't forget to call down to this one, though.
         Don't forget to call down to this one, though.
         """
         """
         self.__state = StagedObject.OFF
         self.__state = StagedObject.OFF
-        pass
 
 
     def isOnStage(self):
     def isOnStage(self):
         return self.__state == StagedObject.ON
         return self.__state == StagedObject.ON

+ 1 - 1
direct/src/distributed/TimeManager.py

@@ -1,5 +1,5 @@
 from direct.showbase.DirectObject import *
 from direct.showbase.DirectObject import *
-from pandac.PandaModules import *
+from panda3d.core import *
 from direct.task import Task
 from direct.task import Task
 from direct.distributed import DistributedObject
 from direct.distributed import DistributedObject
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal

+ 1 - 1
direct/src/distributed/TimeManagerAI.py

@@ -1,5 +1,5 @@
 from direct.distributed.ClockDelta import *
 from direct.distributed.ClockDelta import *
-from pandac.PandaModules import *
+from panda3d.core import *
 from direct.distributed import DistributedObjectAI
 from direct.distributed import DistributedObjectAI
 
 
 class TimeManagerAI(DistributedObjectAI.DistributedObjectAI):
 class TimeManagerAI(DistributedObjectAI.DistributedObjectAI):

+ 22 - 2
direct/src/distributed/cConnectionRepository.cxx

@@ -402,8 +402,28 @@ send_datagram(const Datagram &dg) {
   }
   }
 
 
 #ifdef WANT_NATIVE_NET
 #ifdef WANT_NATIVE_NET
-  if(_native)
-    return _bdc.SendMessage(dg);
+  if (_native) {
+    bool result = _bdc.SendMessage(dg);
+    if (!result && _bdc.IsConnected()) {
+#ifdef HAVE_PYTHON
+      ostringstream s;
+
+#if PY_VERSION_HEX >= 0x03030000
+      PyObject *exc_type = PyExc_ConnectionError;
+#else
+      PyObject *exc_type = PyExc_OSError;
+#endif
+
+      s << endl << "Error sending message: " << endl;
+      dg.dump_hex(s);
+      s << "Message data: " << dg.get_data() << endl;
+
+      string message = s.str();
+      PyErr_SetString(exc_type, message.c_str());
+#endif
+    }
+    return result;
+  }
 #endif
 #endif
 
 
 #ifdef HAVE_NET
 #ifdef HAVE_NET

+ 0 - 1
direct/src/extensions_native/.gitignore

@@ -1 +0,0 @@
-/extensions_darwin.py

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

@@ -149,7 +149,7 @@ class FSM(DirectObject):
 
 
     def __init__(self, name):
     def __init__(self, name):
         self.fsmLock = RLock()
         self.fsmLock = RLock()
-        self.name = name
+        self._name = name
         self.stateArray = []
         self.stateArray = []
         self._serialNum = FSM.SerialNum
         self._serialNum = FSM.SerialNum
         FSM.SerialNum += 1
         FSM.SerialNum += 1
@@ -185,7 +185,7 @@ class FSM(DirectObject):
         # the messenger on every state change. The new and old states are
         # the messenger on every state change. The new and old states are
         # accessible as self.oldState and self.newState, and the transition
         # accessible as self.oldState and self.newState, and the transition
         # functions will already have been called.
         # functions will already have been called.
-        return 'FSM-%s-%s-stateChange' % (self._serialNum, self.name)
+        return 'FSM-%s-%s-stateChange' % (self._serialNum, self._name)
 
 
     def getCurrentFilter(self):
     def getCurrentFilter(self):
         if not self.state:
         if not self.state:
@@ -240,7 +240,7 @@ class FSM(DirectObject):
         try:
         try:
             assert isinstance(request, str)
             assert isinstance(request, str)
             self.notify.debug("%s.forceTransition(%s, %s" % (
             self.notify.debug("%s.forceTransition(%s, %s" % (
-                self.name, request, str(args)[1:]))
+                self._name, request, str(args)[1:]))
 
 
             if not self.state:
             if not self.state:
                 # Queue up the request.
                 # Queue up the request.
@@ -268,7 +268,7 @@ class FSM(DirectObject):
         try:
         try:
             assert isinstance(request, str)
             assert isinstance(request, str)
             self.notify.debug("%s.demand(%s, %s" % (
             self.notify.debug("%s.demand(%s, %s" % (
-                self.name, request, str(args)[1:]))
+                self._name, request, str(args)[1:]))
             if not self.state:
             if not self.state:
                 # Queue up the request.
                 # Queue up the request.
                 self.__requestQueue.append(PythonUtil.Functor(
                 self.__requestQueue.append(PythonUtil.Functor(
@@ -307,7 +307,7 @@ class FSM(DirectObject):
         try:
         try:
             assert isinstance(request, str)
             assert isinstance(request, str)
             self.notify.debug("%s.request(%s, %s" % (
             self.notify.debug("%s.request(%s, %s" % (
-                self.name, request, str(args)[1:]))
+                self._name, request, str(args)[1:]))
 
 
             filter = self.getCurrentFilter()
             filter = self.getCurrentFilter()
             result = filter(request, args)
             result = filter(request, args)
@@ -385,7 +385,7 @@ class FSM(DirectObject):
 
 
         # In either case, we quietly ignore unhandled command
         # In either case, we quietly ignore unhandled command
         # (lowercase) requests.
         # (lowercase) requests.
-        assert self.notify.debug("%s ignoring request %s from state %s." % (self.name, request, self.state))
+        assert self.notify.debug("%s ignoring request %s from state %s." % (self._name, request, self.state))
         return None
         return None
 
 
     def filterOff(self, request, args):
     def filterOff(self, request, args):
@@ -444,7 +444,7 @@ class FSM(DirectObject):
         # Internal function to change unconditionally to the indicated
         # Internal function to change unconditionally to the indicated
         # state.
         # state.
         assert self.state
         assert self.state
-        assert self.notify.debug("%s to state %s." % (self.name, newState))
+        assert self.notify.debug("%s to state %s." % (self._name, newState))
 
 
         self.oldState = self.state
         self.oldState = self.state
         self.newState = newState
         self.newState = newState
@@ -476,7 +476,7 @@ class FSM(DirectObject):
 
 
         if self.__requestQueue:
         if self.__requestQueue:
             request = self.__requestQueue.pop(0)
             request = self.__requestQueue.pop(0)
-            assert self.notify.debug("%s continued queued request." % (self.name))
+            assert self.notify.debug("%s continued queued request." % (self._name))
             request()
             request()
 
 
     def __callEnterFunc(self, name, *args):
     def __callEnterFunc(self, name, *args):
@@ -525,9 +525,9 @@ class FSM(DirectObject):
         try:
         try:
             className = self.__class__.__name__
             className = self.__class__.__name__
             if self.state:
             if self.state:
-                str = ('%s FSM:%s in state "%s"' % (className, self.name, self.state))
+                str = ('%s FSM:%s in state "%s"' % (className, self._name, self.state))
             else:
             else:
-                str = ('%s FSM:%s in transition from \'%s\' to \'%s\'' % (className, self.name, self.oldState, self.newState))
+                str = ('%s FSM:%s in transition from \'%s\' to \'%s\'' % (className, self._name, self.oldState, self.newState))
             return str
             return str
         finally:
         finally:
             self.fsmLock.release()
             self.fsmLock.release()

+ 17 - 17
direct/src/fsm/FourState.py

@@ -90,7 +90,8 @@ class FourState:
         off (and so is state 2 which is oposite of 4 and therefore
         off (and so is state 2 which is oposite of 4 and therefore
         oposite of 'on').
         oposite of 'on').
         """
         """
-        assert self.debugPrint("FourState(names=%s)"%(names))
+        self.stateIndex = 0
+        assert self.__debugPrint("FourState(names=%s)"%(names))
         self.track = None
         self.track = None
         self.stateTime = 0.0
         self.stateTime = 0.0
         self.names = names
         self.names = names
@@ -120,7 +121,6 @@ class FourState:
                            self.exitState4,
                            self.exitState4,
                            [names[1]]),
                            [names[1]]),
             }
             }
-        self.stateIndex = 0
         self.fsm = ClassicFSM.ClassicFSM('FourState',
         self.fsm = ClassicFSM.ClassicFSM('FourState',
                            list(self.states.values()),
                            list(self.states.values()),
                            # Initial State
                            # Initial State
@@ -131,7 +131,7 @@ class FourState:
         self.fsm.enterInitialState()
         self.fsm.enterInitialState()
 
 
     def setTrack(self, track):
     def setTrack(self, track):
-        assert self.debugPrint("setTrack(track=%s)"%(track,))
+        assert self.__debugPrint("setTrack(track=%s)"%(track,))
         if self.track is not None:
         if self.track is not None:
             self.track.pause()
             self.track.pause()
             self.track = None
             self.track = None
@@ -147,27 +147,27 @@ class FourState:
     # If the client wants the state changed it needs to
     # If the client wants the state changed it needs to
     # send a request to the AI.
     # send a request to the AI.
     #def setIsOn(self, isOn):
     #def setIsOn(self, isOn):
-    #    assert self.debugPrint("setIsOn(isOn=%s)"%(isOn,))
+    #    assert self.__debugPrint("setIsOn(isOn=%s)"%(isOn,))
     #    pass
     #    pass
 
 
     def isOn(self):
     def isOn(self):
-        assert self.debugPrint("isOn() returning %s (stateIndex=%s)"%(self.stateIndex==4, self.stateIndex))
+        assert self.__debugPrint("isOn() returning %s (stateIndex=%s)"%(self.stateIndex==4, self.stateIndex))
         return self.stateIndex==4
         return self.stateIndex==4
 
 
     def changedOnState(self, isOn):
     def changedOnState(self, isOn):
         """
         """
         Allow derived classes to overide this.
         Allow derived classes to overide this.
         """
         """
-        assert self.debugPrint("changedOnState(isOn=%s)"%(isOn,))
+        assert self.__debugPrint("changedOnState(isOn=%s)"%(isOn,))
 
 
     ##### state 0 #####
     ##### state 0 #####
 
 
     def enterState0(self):
     def enterState0(self):
-        assert self.debugPrint("enter0()")
+        assert self.__debugPrint("enter0()")
         self.enterStateN(0)
         self.enterStateN(0)
 
 
     def exitState0(self):
     def exitState0(self):
-        assert self.debugPrint("exit0()")
+        assert self.__debugPrint("exit0()")
         # It's important for FourStates to broadcast their state
         # It's important for FourStates to broadcast their state
         # when they are generated on the client. Before I put this in,
         # when they are generated on the client. Before I put this in,
         # if a door was generated and went directly to an 'open' state,
         # if a door was generated and went directly to an 'open' state,
@@ -177,43 +177,43 @@ class FourState:
     ##### state 1 #####
     ##### state 1 #####
 
 
     def enterState1(self):
     def enterState1(self):
-        assert self.debugPrint("enterState1()")
+        assert self.__debugPrint("enterState1()")
         self.enterStateN(1)
         self.enterStateN(1)
 
 
     def exitState1(self):
     def exitState1(self):
-        assert self.debugPrint("exitState1()")
+        assert self.__debugPrint("exitState1()")
 
 
     ##### state 2 #####
     ##### state 2 #####
 
 
     def enterState2(self):
     def enterState2(self):
-        assert self.debugPrint("enterState2()")
+        assert self.__debugPrint("enterState2()")
         self.enterStateN(2)
         self.enterStateN(2)
 
 
     def exitState2(self):
     def exitState2(self):
-        assert self.debugPrint("exitState2()")
+        assert self.__debugPrint("exitState2()")
 
 
     ##### state 3 #####
     ##### state 3 #####
 
 
     def enterState3(self):
     def enterState3(self):
-        assert self.debugPrint("enterState3()")
+        assert self.__debugPrint("enterState3()")
         self.enterStateN(3)
         self.enterStateN(3)
 
 
     def exitState3(self):
     def exitState3(self):
-        assert self.debugPrint("exitState3()")
+        assert self.__debugPrint("exitState3()")
 
 
     ##### state 4 #####
     ##### state 4 #####
 
 
     def enterState4(self):
     def enterState4(self):
-        assert self.debugPrint("enterState4()")
+        assert self.__debugPrint("enterState4()")
         self.enterStateN(4)
         self.enterStateN(4)
         self.changedOnState(1)
         self.changedOnState(1)
 
 
     def exitState4(self):
     def exitState4(self):
-        assert self.debugPrint("exitState4()")
+        assert self.__debugPrint("exitState4()")
         self.changedOnState(0)
         self.changedOnState(0)
 
 
     if __debug__:
     if __debug__:
-        def debugPrint(self, message):
+        def __debugPrint(self, message):
             """for debugging"""
             """for debugging"""
             return self.notify.debug("%d (%d) %s"%(
             return self.notify.debug("%d (%d) %s"%(
                     id(self), self.stateIndex==4, message))
                     id(self), self.stateIndex==4, message))

+ 23 - 23
direct/src/fsm/FourStateAI.py

@@ -93,11 +93,11 @@ class FourStateAI:
         off (and so is state 2 which is oposite of state 4 and therefore
         off (and so is state 2 which is oposite of state 4 and therefore
         oposite of 'on').
         oposite of 'on').
         """
         """
-        assert self.debugPrint(
+        self.stateIndex = 0
+        assert self.__debugPrint(
                 "FourStateAI(names=%s, durations=%s)"
                 "FourStateAI(names=%s, durations=%s)"
                 %(names, durations))
                 %(names, durations))
         self.doLaterTask = None
         self.doLaterTask = None
-        self.stateIndex = 0
         assert len(names) == 5
         assert len(names) == 5
         assert len(names) == len(durations)
         assert len(names) == len(durations)
         self.names = names
         self.names = names
@@ -137,7 +137,7 @@ class FourStateAI:
         self.fsm.enterInitialState()
         self.fsm.enterInitialState()
 
 
     def delete(self):
     def delete(self):
-        assert self.debugPrint("delete()")
+        assert self.__debugPrint("delete()")
         if self.doLaterTask is not None:
         if self.doLaterTask is not None:
             self.doLaterTask.remove()
             self.doLaterTask.remove()
             del self.doLaterTask
             del self.doLaterTask
@@ -145,15 +145,15 @@ class FourStateAI:
         del self.fsm
         del self.fsm
 
 
     def getState(self):
     def getState(self):
-        assert self.debugPrint("getState() returning %s"%(self.stateIndex,))
+        assert self.__debugPrint("getState() returning %s"%(self.stateIndex,))
         return [self.stateIndex]
         return [self.stateIndex]
 
 
     def sendState(self):
     def sendState(self):
-        assert self.debugPrint("sendState()")
+        assert self.__debugPrint("sendState()")
         self.sendUpdate('setState', self.getState())
         self.sendUpdate('setState', self.getState())
 
 
     def setIsOn(self, isOn):
     def setIsOn(self, isOn):
-        assert self.debugPrint("setIsOn(isOn=%s)"%(isOn,))
+        assert self.__debugPrint("setIsOn(isOn=%s)"%(isOn,))
         if isOn:
         if isOn:
             if self.stateIndex != 4:
             if self.stateIndex != 4:
                 # ...if it's not On; request turning on:
                 # ...if it's not On; request turning on:
@@ -170,7 +170,7 @@ class FourStateAI:
         #    self.fsm.request(self.states[nextState])
         #    self.fsm.request(self.states[nextState])
 
 
     def isOn(self):
     def isOn(self):
-        assert self.debugPrint("isOn() returning %s (stateIndex=%s)"%(self.stateIndex==4, self.stateIndex))
+        assert self.__debugPrint("isOn() returning %s (stateIndex=%s)"%(self.stateIndex==4, self.stateIndex))
         return self.stateIndex==4
         return self.stateIndex==4
 
 
     def changedOnState(self, isOn):
     def changedOnState(self, isOn):
@@ -179,12 +179,12 @@ class FourStateAI:
         The self.isOn value has toggled.  Call getIsOn() to
         The self.isOn value has toggled.  Call getIsOn() to
         get the current state.
         get the current state.
         """
         """
-        assert self.debugPrint("changedOnState(isOn=%s)"%(isOn,))
+        assert self.__debugPrint("changedOnState(isOn=%s)"%(isOn,))
 
 
     ##### states #####
     ##### states #####
 
 
     def switchToNextStateTask(self, task):
     def switchToNextStateTask(self, task):
-        assert self.debugPrint("switchToNextStateTask()")
+        assert self.__debugPrint("switchToNextStateTask()")
         self.fsm.request(self.states[self.nextStateIndex])
         self.fsm.request(self.states[self.nextStateIndex])
         return Task.done
         return Task.done
 
 
@@ -193,11 +193,11 @@ class FourStateAI:
         This function is intentionaly simple so that derived classes
         This function is intentionaly simple so that derived classes
         may easily alter the network message.
         may easily alter the network message.
         """
         """
-        assert self.debugPrint("distributeStateChange()")
+        assert self.__debugPrint("distributeStateChange()")
         self.sendState()
         self.sendState()
 
 
     def enterStateN(self, stateIndex, nextStateIndex):
     def enterStateN(self, stateIndex, nextStateIndex):
-        assert self.debugPrint(
+        assert self.__debugPrint(
             "enterStateN(stateIndex=%s, nextStateIndex=%s)"%
             "enterStateN(stateIndex=%s, nextStateIndex=%s)"%
             (stateIndex, nextStateIndex))
             (stateIndex, nextStateIndex))
         self.stateIndex = stateIndex
         self.stateIndex = stateIndex
@@ -211,7 +211,7 @@ class FourStateAI:
                 "enterStateN-timer-%s"%id(self))
                 "enterStateN-timer-%s"%id(self))
 
 
     def exitStateN(self):
     def exitStateN(self):
-        assert self.debugPrint("exitStateN()")
+        assert self.__debugPrint("exitStateN()")
         if self.doLaterTask:
         if self.doLaterTask:
             taskMgr.remove(self.doLaterTask)
             taskMgr.remove(self.doLaterTask)
             self.doLaterTask=None
             self.doLaterTask=None
@@ -219,56 +219,56 @@ class FourStateAI:
     ##### state 0 #####
     ##### state 0 #####
 
 
     def enterState0(self):
     def enterState0(self):
-        assert self.debugPrint("enter0()")
+        assert self.__debugPrint("enter0()")
         self.enterStateN(0, 0)
         self.enterStateN(0, 0)
 
 
     def exitState0(self):
     def exitState0(self):
-        assert self.debugPrint("exit0()")
+        assert self.__debugPrint("exit0()")
 
 
     ##### state 1 #####
     ##### state 1 #####
 
 
     def enterState1(self):
     def enterState1(self):
-        #assert self.debugPrint("enterState1()")
+        #assert self.__debugPrint("enterState1()")
         self.enterStateN(1, 2)
         self.enterStateN(1, 2)
 
 
     def exitState1(self):
     def exitState1(self):
-        assert self.debugPrint("exitState1()")
+        assert self.__debugPrint("exitState1()")
         self.exitStateN()
         self.exitStateN()
 
 
     ##### state 2 #####
     ##### state 2 #####
 
 
     def enterState2(self):
     def enterState2(self):
-        #assert self.debugPrint("enterState2()")
+        #assert self.__debugPrint("enterState2()")
         self.enterStateN(2, 3)
         self.enterStateN(2, 3)
 
 
     def exitState2(self):
     def exitState2(self):
-        assert self.debugPrint("exitState2()")
+        assert self.__debugPrint("exitState2()")
         self.exitStateN()
         self.exitStateN()
 
 
     ##### state 3 #####
     ##### state 3 #####
 
 
     def enterState3(self):
     def enterState3(self):
-        #assert self.debugPrint("enterState3()")
+        #assert self.__debugPrint("enterState3()")
         self.enterStateN(3, 4)
         self.enterStateN(3, 4)
 
 
     def exitState3(self):
     def exitState3(self):
-        assert self.debugPrint("exitState3()")
+        assert self.__debugPrint("exitState3()")
         self.exitStateN()
         self.exitStateN()
 
 
     ##### state 4 #####
     ##### state 4 #####
 
 
     def enterState4(self):
     def enterState4(self):
-        assert self.debugPrint("enterState4()")
+        assert self.__debugPrint("enterState4()")
         self.enterStateN(4, 1)
         self.enterStateN(4, 1)
         self.changedOnState(1)
         self.changedOnState(1)
 
 
     def exitState4(self):
     def exitState4(self):
-        assert self.debugPrint("exitState4()")
+        assert self.__debugPrint("exitState4()")
         self.exitStateN()
         self.exitStateN()
         self.changedOnState(0)
         self.changedOnState(0)
 
 
     if __debug__:
     if __debug__:
-        def debugPrint(self, message):
+        def __debugPrint(self, message):
             """for debugging"""
             """for debugging"""
             return self.notify.debug("%d (%d) %s"%(
             return self.notify.debug("%d (%d) %s"%(
                     id(self), self.stateIndex==4, message))
                     id(self), self.stateIndex==4, message))

+ 0 - 2
direct/src/gui/.gitignore

@@ -1,2 +0,0 @@
-/NL*
-/Nested*

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

@@ -20,7 +20,7 @@ class DirectScrolledListItem(DirectButton):
 
 
     def __init__(self, parent=None, **kw):
     def __init__(self, parent=None, **kw):
         assert self.notify.debugStateCall(self)
         assert self.notify.debugStateCall(self)
-        self.parent = parent
+        self._parent = parent
         if "command" in kw:
         if "command" in kw:
             self.nextCommand = kw.get("command")
             self.nextCommand = kw.get("command")
             del kw["command"]
             del kw["command"]
@@ -28,7 +28,7 @@ class DirectScrolledListItem(DirectButton):
             self.nextCommandExtraArgs = kw.get("extraArgs")
             self.nextCommandExtraArgs = kw.get("extraArgs")
             del kw["extraArgs"]
             del kw["extraArgs"]
         optiondefs = (
         optiondefs = (
-            ('parent', self.parent,    None),
+            ('parent', self._parent,    None),
             ('command', self.select, None),
             ('command', self.select, None),
             )
             )
         # Merge keyword options with default options
         # Merge keyword options with default options
@@ -39,7 +39,7 @@ class DirectScrolledListItem(DirectButton):
     def select(self):
     def select(self):
         assert self.notify.debugStateCall(self)
         assert self.notify.debugStateCall(self)
         self.nextCommand(*self.nextCommandExtraArgs)
         self.nextCommand(*self.nextCommandExtraArgs)
-        self.parent.selectListItem(self)
+        self._parent.selectListItem(self)
 
 
 
 
 class DirectScrolledList(DirectFrame):
 class DirectScrolledList(DirectFrame):

+ 0 - 8
direct/src/p3d/.gitignore

@@ -1,8 +0,0 @@
-/_vfsimporter.exp
-/_vfsimporter.lib
-/_vfsimporter.pyd
-/_vfsimporter.pyd.manifest
-/packp3d
-/ppackage
-/ppatcher
-/vc90.pdb

+ 4 - 4
direct/src/p3d/FileSpec.py

@@ -33,7 +33,7 @@ class FileSpec:
         if st is None:
         if st is None:
             st = os.stat(pathname.toOsSpecific())
             st = os.stat(pathname.toOsSpecific())
         self.size = st.st_size
         self.size = st.st_size
-        self.timestamp = st.st_mtime
+        self.timestamp = int(st.st_mtime)
 
 
         self.readHash(pathname)
         self.readHash(pathname)
 
 
@@ -124,7 +124,7 @@ class FileSpec:
                 self.__correctHash(packageDir, pathname, st, notify)
                 self.__correctHash(packageDir, pathname, st, notify)
             return False
             return False
 
 
-        if st.st_mtime == self.timestamp:
+        if int(st.st_mtime) == self.timestamp:
             # If the size is right and the timestamp is right, the
             # If the size is right and the timestamp is right, the
             # file passes.
             # file passes.
             if notify:
             if notify:
@@ -198,7 +198,7 @@ class FileSpec:
         # The hash is OK.  If the timestamp is wrong, change it back
         # The hash is OK.  If the timestamp is wrong, change it back
         # to what we expect it to be, so we can quick-verify it
         # to what we expect it to be, so we can quick-verify it
         # successfully next time.
         # successfully next time.
-        if st.st_mtime != self.timestamp:
+        if int(st.st_mtime) != self.timestamp:
             self.__updateTimestamp(pathname, st)
             self.__updateTimestamp(pathname, st)
 
 
         return True
         return True
@@ -219,7 +219,7 @@ class FileSpec:
         if notify:
         if notify:
             notify.info("Correcting timestamp of %s to %d (%s)" % (
             notify.info("Correcting timestamp of %s to %d (%s)" % (
                 self.filename, st.st_mtime, time.asctime(time.localtime(st.st_mtime))))
                 self.filename, st.st_mtime, time.asctime(time.localtime(st.st_mtime))))
-        self.timestamp = st.st_mtime
+        self.timestamp = int(st.st_mtime)
 
 
     def checkHash(self, packageDir, pathname, st):
     def checkHash(self, packageDir, pathname, st):
         """ Returns true if the file has the expected md5 hash, false
         """ Returns true if the file has the expected md5 hash, false

+ 12 - 1
direct/src/p3d/Packager.py

@@ -1848,7 +1848,7 @@ class Packager:
 
 
         def addEggFile(self, file):
         def addEggFile(self, file):
             # Precompile egg files to bam's.
             # Precompile egg files to bam's.
-            np = self.packager.loader.loadModel(file.filename)
+            np = self.packager.loader.loadModel(file.filename, self.packager.loaderOptions)
             if not np:
             if not np:
                 raise Exception('Could not read egg file %s' % (file.filename))
                 raise Exception('Could not read egg file %s' % (file.filename))
 
 
@@ -1862,6 +1862,8 @@ class Packager:
             if not bamFile.openRead(file.filename):
             if not bamFile.openRead(file.filename):
                 raise Exception('Could not read bam file %s' % (file.filename))
                 raise Exception('Could not read bam file %s' % (file.filename))
 
 
+            bamFile.getReader().setLoaderOptions(self.packager.loaderOptions)
+
             if not bamFile.resolve():
             if not bamFile.resolve():
                 raise Exception('Could not resolve bam file %s' % (file.filename))
                 raise Exception('Could not resolve bam file %s' % (file.filename))
 
 
@@ -2484,6 +2486,7 @@ class Packager:
             GlobPattern('libthr.so*'),
             GlobPattern('libthr.so*'),
             GlobPattern('ld-linux.so*'),
             GlobPattern('ld-linux.so*'),
             GlobPattern('ld-linux-*.so*'),
             GlobPattern('ld-linux-*.so*'),
+            GlobPattern('librt.so*'),
             ]
             ]
 
 
         # A Loader for loading models.
         # A Loader for loading models.
@@ -2491,6 +2494,14 @@ class Packager:
         self.sfxManagerList = None
         self.sfxManagerList = None
         self.musicManager = None
         self.musicManager = None
 
 
+        # These options will be used when loading models and textures.  By
+        # default we don't load textures beyond the header and don't store
+        # models in the RAM cache in order to conserve on memory usage.
+        opts = LoaderOptions()
+        opts.setFlags(opts.getFlags() | LoaderOptions.LFNoRamCache)
+        opts.setTextureFlags(opts.getTextureFlags() & ~LoaderOptions.TFPreload)
+        self.loaderOptions = opts
+
         # This is filled in during readPackageDef().
         # This is filled in during readPackageDef().
         self.packageList = []
         self.packageList = []
 
 

+ 6 - 1
direct/src/p3d/SeqValue.py

@@ -77,9 +77,14 @@ class SeqValue:
         """ Compares to another seq value. """
         """ Compares to another seq value. """
         return cmp(self.value, other.value)
         return cmp(self.value, other.value)
 
 
+    def __lt__(self, other):
+        return self.value < other.value
+
+    def __gt__(self, other):
+        return self.value > other.value
+
     def __bool__(self):
     def __bool__(self):
         return bool(self.value)
         return bool(self.value)
 
 
     def __str__(self):
     def __str__(self):
         return 'SeqValue%s' % (repr(self.value))
         return 'SeqValue%s' % (repr(self.value))
-

+ 15 - 3
direct/src/p3d/panda3d.pdef

@@ -56,6 +56,9 @@ class panda3d(package):
            'direct.stdpy.*',
            'direct.stdpy.*',
            'direct.task.*')
            'direct.task.*')
 
 
+    # Keep these modules for backward compatibility.
+    module('pandac.PandaModules', 'pandac.extension_native_helpers')
+
     module('panda3d.core',
     module('panda3d.core',
            'panda3d.direct',
            'panda3d.direct',
            'panda3d.fx',
            'panda3d.fx',
@@ -63,8 +66,10 @@ class panda3d(package):
 
 
     # Include various standard Python encodings.  The rest is in morepy.
     # Include various standard Python encodings.  The rest is in morepy.
     module('encodings', 'encodings.aliases', 'encodings.undefined',
     module('encodings', 'encodings.aliases', 'encodings.undefined',
-           'encodings.utf_8', 'encodings.ascii', 'encodings.string_escape',
-           'encodings.mbcs', 'encodings.latin_1', 'io')
+           'encodings.utf_8', 'encodings.ascii', 'encodings.mbcs',
+           'encodings.latin_1', 'io')
+    if sys.version_info < (3, 0):
+        module('encodings.string_escape')
 
 
     # Pick up the shader files that appear in direct/src/filter.
     # Pick up the shader files that appear in direct/src/filter.
     import direct
     import direct
@@ -241,7 +246,10 @@ class models(package):
     # we assume this is the models directory.
     # we assume this is the models directory.
     pathname = getModelPath().findFile('cmss12.egg')
     pathname = getModelPath().findFile('cmss12.egg')
     if pathname:
     if pathname:
-        dir(pathname.getDirname(), newDir = '')
+        dir(pathname.getDirname(), newDir = 'models')
+
+    # Some people are used to loading the models without models/ prefix.
+    file('models.prc', extract = True, text = "model-path $MODELS_ROOT/models")
 
 
 
 
 class fmod(package):
 class fmod(package):
@@ -457,6 +465,8 @@ class packp3d(p3d):
 
 
     mainModule('direct.p3d.packp3d')
     mainModule('direct.p3d.packp3d')
 
 
+    file('packp3d.prc', extract = True, text = "preload-textures false")
+
 
 
 class ppackage(p3d):
 class ppackage(p3d):
     # As above, a packaging utility.  This is the fully-general ppackage
     # As above, a packaging utility.  This is the fully-general ppackage
@@ -470,6 +480,8 @@ class ppackage(p3d):
 
 
     mainModule('direct.p3d.ppackage')
     mainModule('direct.p3d.ppackage')
 
 
+    file('ppackage.prc', extract = True, text = "preload-textures false")
+
 
 
 class ppatcher(p3d):
 class ppatcher(p3d):
     # A handy utility to go along with ppackage.  This builds
     # A handy utility to go along with ppackage.  This builds

+ 0 - 1
direct/src/plugin/.gitignore

@@ -1 +0,0 @@
-/p3d_plugin_config.h

+ 0 - 2
direct/src/plugin/p3dCInstance.h

@@ -21,8 +21,6 @@
 #include "get_tinyxml.h"
 #include "get_tinyxml.h"
 #include "windowHandle.h"
 #include "windowHandle.h"
 
 
-#include <Python.h>
-
 class P3DSession;
 class P3DSession;
 
 
 /**
 /**

+ 4 - 4
direct/src/plugin/p3dInstance.cxx

@@ -3450,8 +3450,8 @@ paint_window_osx_port() {
   int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
   int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
   size_t rowsize = _swbuffer->get_row_size();
   size_t rowsize = _swbuffer->get_row_size();
 
 
-  Rect src_rect = {0, 0, y_size, x_size};
-  Rect ddrc_rect = {0, 0, y_size, x_size};
+  Rect src_rect = {0, 0, (short)y_size, (short)x_size};
+  Rect ddrc_rect = {0, 0, (short)y_size, (short)x_size};
 
 
   QDErr err;
   QDErr err;
 
 
@@ -3502,7 +3502,7 @@ paint_window_osx_cgcontext(CGContextRef context) {
   int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
   int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
 
 
   if (_buffer_image != NULL) {
   if (_buffer_image != NULL) {
-    CGRect region = { { 0, 0 }, { x_size, y_size } };
+    CGRect region = { { 0, 0 }, { (CGFloat)x_size, (CGFloat)y_size } };
     CGContextDrawImage(context, region, _buffer_image);
     CGContextDrawImage(context, region, _buffer_image);
   }
   }
 }
 }
@@ -3538,7 +3538,7 @@ handle_event_osx_event_record(const P3D_event_data &event) {
     // First, convert the coordinates from screen coordinates to browser
     // First, convert the coordinates from screen coordinates to browser
     // window coordinates.
     // window coordinates.
     WindowRef window = handle._handle._osx_cgcontext._window;
     WindowRef window = handle._handle._osx_cgcontext._window;
-    CGPoint cgpt = { pt.h, pt.v };
+    CGPoint cgpt = { (CGFloat)pt.h, (CGFloat)pt.v };
     HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL,
     HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL,
                    kHICoordSpaceWindow, window);
                    kHICoordSpaceWindow, window);
 
 

+ 11 - 0
direct/src/plugin/p3dInstanceManager.cxx

@@ -1421,6 +1421,17 @@ create_runtime_environment() {
     }
     }
   }
   }
 
 
+#ifndef _WIN32
+  // If we're running from the console, make sure that terminating the parent
+  // process will cause the child process to terminate as well.
+  if (_console_environment) {
+    struct sigaction ignore;
+    memset(&ignore, 0, sizeof(ignore));
+    ignore.sa_handler = SIG_IGN;
+    sigaction(SIGINT, &ignore, NULL);
+  }
+#endif
+
   _created_runtime_environment = true;
   _created_runtime_environment = true;
 }
 }
 
 

+ 8 - 8
direct/src/plugin/p3dOsxSplashWindow.cxx

@@ -267,7 +267,7 @@ refresh() {
     return;
     return;
   }
   }
   if (_toplevel_window != NULL) {
   if (_toplevel_window != NULL) {
-    Rect r = { 0, 0, _win_height, _win_width };
+    Rect r = { 0, 0, (short)_win_height, (short)_win_width };
     InvalWindowRect(_toplevel_window, &r);
     InvalWindowRect(_toplevel_window, &r);
 
 
   } else {
   } else {
@@ -345,7 +345,7 @@ paint_window_osx_cgcontext(CGContextRef context) {
   CGColorSpaceRef rgb_space = CGColorSpaceCreateDeviceRGB();
   CGColorSpaceRef rgb_space = CGColorSpaceCreateDeviceRGB();
   CGColorRef bg = CGColorCreate(rgb_space, bg_components);
   CGColorRef bg = CGColorCreate(rgb_space, bg_components);
 
 
-  CGRect region = { { 0, 0 }, { _win_width, _win_height } };
+  CGRect region = { { 0, 0 }, { (CGFloat)_win_width, (CGFloat)_win_height } };
   CGContextSetFillColorWithColor(context, bg);
   CGContextSetFillColorWithColor(context, bg);
   CGContextFillRect(context, region);
   CGContextFillRect(context, region);
 
 
@@ -407,7 +407,7 @@ handle_event_osx_event_record(const P3D_event_data &event) {
     // First, convert the coordinates from screen coordinates to browser
     // First, convert the coordinates from screen coordinates to browser
     // window coordinates.
     // window coordinates.
     WindowRef window = handle._handle._osx_cgcontext._window;
     WindowRef window = handle._handle._osx_cgcontext._window;
-    CGPoint cgpt = { pt.h, pt.v };
+    CGPoint cgpt = { (CGFloat)pt.h, (CGFloat)pt.v };
     HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL,
     HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL,
                    kHICoordSpaceWindow, window);
                    kHICoordSpaceWindow, window);
 
 
@@ -617,7 +617,7 @@ paint_progress_bar(CGContextRef context) {
   int bar_x, bar_y, bar_width, bar_height;
   int bar_x, bar_y, bar_width, bar_height;
   get_bar_placement(bar_x, bar_y, bar_width, bar_height);
   get_bar_placement(bar_x, bar_y, bar_width, bar_height);
 
 
-  CGRect bar_rect = { { bar_x, bar_y }, { bar_width, bar_height } };
+  CGRect bar_rect = { { (CGFloat)bar_x, (CGFloat)bar_y }, { (CGFloat)bar_width, (CGFloat)bar_height } };
 
 
   // Clear the entire progress bar to white (or the background color).
   // Clear the entire progress bar to white (or the background color).
   CGContextSetFillColorWithColor(context, bar_bg);
   CGContextSetFillColorWithColor(context, bar_bg);
@@ -627,7 +627,7 @@ paint_progress_bar(CGContextRef context) {
   if (_progress_known) {
   if (_progress_known) {
     int progress_width = (int)(bar_width * _install_progress + 0.5);
     int progress_width = (int)(bar_width * _install_progress + 0.5);
     if (progress_width != 0) {
     if (progress_width != 0) {
-      CGRect prog = { { bar_x, bar_y }, { progress_width, bar_height } };
+      CGRect prog = { { (CGFloat)bar_x, (CGFloat)bar_y }, { (CGFloat)progress_width, (CGFloat)bar_height } };
       CGContextSetFillColorWithColor(context, bar);
       CGContextSetFillColorWithColor(context, bar);
       CGContextFillRect(context, prog);
       CGContextFillRect(context, prog);
     }
     }
@@ -642,7 +642,7 @@ paint_progress_bar(CGContextRef context) {
       progress = block_travel * 2 - progress;
       progress = block_travel * 2 - progress;
     }
     }
 
 
-    CGRect prog = { { bar_x + progress, bar_y }, { block_width, bar_height } };
+    CGRect prog = { { (CGFloat)(bar_x + progress), (CGFloat)bar_y }, { (CGFloat)block_width, (CGFloat)bar_height } };
     CGContextSetFillColorWithColor(context, bar);
     CGContextSetFillColorWithColor(context, bar);
     CGContextFillRect(context, prog);
     CGContextFillRect(context, prog);
   }
   }
@@ -652,8 +652,8 @@ paint_progress_bar(CGContextRef context) {
     // We offset the border by half a pixel, so we'll be drawing the one-pixel
     // We offset the border by half a pixel, so we'll be drawing the one-pixel
     // line through the middle of a pixel, and it won't try to antialias
     // line through the middle of a pixel, and it won't try to antialias
     // itself into a half-black two-pixel line.
     // itself into a half-black two-pixel line.
-    CGRect border_rect = { { bar_x - 0.5, bar_y - 0.5 },
-                           { bar_width + 1, bar_height + 1 } };
+    CGRect border_rect = { { (CGFloat)(bar_x - 0.5), (CGFloat)(bar_y - 0.5) },
+                           { (CGFloat)(bar_width + 1), (CGFloat)(bar_height + 1) } };
 
 
     CGContextBeginPath(context);
     CGContextBeginPath(context);
     CGContextSetLineWidth(context, 1);
     CGContextSetLineWidth(context, 1);

+ 18 - 0
direct/src/plugin/p3dPythonRun.cxx

@@ -217,6 +217,24 @@ run_python() {
     PyModule_AddStringConstant(showbase_module, "__package__", "direct.showbase");
     PyModule_AddStringConstant(showbase_module, "__package__", "direct.showbase");
   }
   }
 
 
+  PyObject *stdpy_module = PyImport_AddModule("direct.stdpy");
+  if (stdpy_module != NULL) {
+    Filename stdpy_dir(direct_dir, "stdpy");
+    dir_str = stdpy_dir.to_os_specific();
+    PyModule_AddObject(stdpy_module, "__path__", Py_BuildValue("[s#]", dir_str.data(), dir_str.length()));
+    PyModule_AddStringConstant(stdpy_module, "__package__", "direct.stdpy");
+  }
+
+  // And the encodings package as well, since we've presumably picked up a
+  // bunch of encodings modules as part of the frozen bundle.
+  Filename encodings_dir(dir, "encodings");
+  PyObject *encodings_module = PyImport_AddModule("encodings");
+  if (encodings_module != NULL) {
+    dir_str = encodings_dir.to_os_specific();
+    PyModule_AddObject(encodings_module, "__path__", Py_BuildValue("[s#]", dir_str.data(), dir_str.length()));
+    PyModule_AddStringConstant(encodings_module, "__package__", "encodings");
+  }
+
   // And register the VFSImporter.
   // And register the VFSImporter.
   PyObject *result = PyObject_CallMethod(vfsimporter_module, (char *)"register", (char *)"");
   PyObject *result = PyObject_CallMethod(vfsimporter_module, (char *)"register", (char *)"");
   if (result == NULL) {
   if (result == NULL) {

+ 0 - 1
direct/src/plugin_activex/.gitignore

@@ -1 +0,0 @@
-/P3DActiveX.rc

+ 0 - 1
direct/src/plugin_npapi/.gitignore

@@ -1 +0,0 @@
-/nppanda3d.rc

+ 0 - 2
direct/src/plugin_standalone/.gitignore

@@ -1,2 +0,0 @@
-/p3d_plugin_config.h
-/panda3d.rc

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

@@ -278,6 +278,15 @@ class BufferViewer(DirectObject):
         self.analyzeTextureSet(self.exclude, exclude)
         self.analyzeTextureSet(self.exclude, exclude)
         self.analyzeTextureSet(self.include, include)
         self.analyzeTextureSet(self.include, include)
 
 
+        # Use a custom sampler when applying the textures.  This fixes
+        # wrap issues and prevents depth compare on shadow maps.
+        sampler = SamplerState()
+        sampler.setWrapU(SamplerState.WM_clamp)
+        sampler.setWrapV(SamplerState.WM_clamp)
+        sampler.setWrapW(SamplerState.WM_clamp)
+        sampler.setMinfilter(SamplerState.FT_linear)
+        sampler.setMagfilter(SamplerState.FT_nearest)
+
         # Generate a list of cards and the corresponding windows.
         # Generate a list of cards and the corresponding windows.
         cards = []
         cards = []
         wins = []
         wins = []
@@ -290,7 +299,7 @@ class BufferViewer(DirectObject):
                         for face in range(6):
                         for face in range(6):
                             self.cardmaker.setUvRangeCube(face)
                             self.cardmaker.setUvRangeCube(face)
                             card = NodePath(self.cardmaker.generate())
                             card = NodePath(self.cardmaker.generate())
-                            card.setTexture(tex)
+                            card.setTexture(tex, sampler)
                             cards.append(card)
                             cards.append(card)
                     elif (tex.getTextureType() == Texture.TT2dTextureArray):
                     elif (tex.getTextureType() == Texture.TT2dTextureArray):
                         for layer in range(tex.getZSize()):
                         for layer in range(tex.getZSize()):
@@ -301,11 +310,11 @@ class BufferViewer(DirectObject):
                             # the fixed-function pipeline, so we need to
                             # the fixed-function pipeline, so we need to
                             # enable the shader generator to view them.
                             # enable the shader generator to view them.
                             card.setShaderAuto()
                             card.setShaderAuto()
-                            card.setTexture(tex)
+                            card.setTexture(tex, sampler)
                             cards.append(card)
                             cards.append(card)
                     else:
                     else:
                         card = win.getTextureCard()
                         card = win.getTextureCard()
-                        card.setTexture(tex)
+                        card.setTexture(tex, sampler)
                         cards.append(card)
                         cards.append(card)
                     wins.append(win)
                     wins.append(win)
                     exclude[tex] = 1
                     exclude[tex] = 1

+ 10 - 6
direct/src/showbase/DistancePhasedNode.py

@@ -106,10 +106,12 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath):
 
 
     def __repr__(self):
     def __repr__(self):
         outStr = 'DistancePhasedObject('
         outStr = 'DistancePhasedObject('
-        outStr += '%s' % repr(self.getName())
+        outStr += repr(self.getName())
         for param, value in zip(('phaseParamMap', 'autoCleanup', 'enterPrefix', 'exitPrefix', 'phaseCollideMask', 'fromCollideNode'),
         for param, value in zip(('phaseParamMap', 'autoCleanup', 'enterPrefix', 'exitPrefix', 'phaseCollideMask', 'fromCollideNode'),
-                                ('{}', 'True','\'enter\'','\'exit\'','BitMask32.allOn()','None')):
-            outStr += eval('(\', ' + param + ' = %s\' % repr(self.' + param + '),\'\')[self.' + param + ' == ' + value + ']')
+                                ({}, True, 'enter', 'exit', BitMask32.allOn(), None)):
+            pv = getattr(self, param)
+            if pv != value:
+                outStr += ', %s = %r' % (param, pv)
         outStr += ')'
         outStr += ')'
         return outStr
         return outStr
 
 
@@ -287,10 +289,12 @@ class BufferedDistancePhasedNode(DistancePhasedNode):
 
 
     def __repr__(self):
     def __repr__(self):
         outStr = 'BufferedDistancePhasedNode('
         outStr = 'BufferedDistancePhasedNode('
-        outStr += '%s' % repr(self.getName())
+        outStr += repr(self.getName())
         for param, value in zip(('bufferParamMap', 'autoCleanup', 'enterPrefix', 'exitPrefix', 'phaseCollideMask', 'fromCollideNode'),
         for param, value in zip(('bufferParamMap', 'autoCleanup', 'enterPrefix', 'exitPrefix', 'phaseCollideMask', 'fromCollideNode'),
-                                ('{}', 'True','\'enter\'','\'exit\'','BitMask32.allOn()', 'None')):
-            outStr += eval('(\', ' + param + ' = %s\' % repr(self.' + param + '),\'\')[self.' + param + ' == ' + value + ']')
+                                ({}, True, 'enter', 'exit', BitMask32.allOn(), None)):
+            pv = getattr(self, param)
+            if pv != value:
+                outStr += ', %s = %r' % (param, pv)
         outStr += ')'
         outStr += ')'
         return outStr
         return outStr
 
 

+ 1 - 0
direct/src/showbase/ExceptionVarDump.py

@@ -1,5 +1,6 @@
 __all__ = ["install"]
 __all__ = ["install"]
 
 
+from panda3d.core import *
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.showbase.PythonUtil import fastRepr
 from direct.showbase.PythonUtil import fastRepr
 import sys
 import sys

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

@@ -1,6 +1,6 @@
 # objects that report different types of leaks to the ContainerLeakDetector
 # objects that report different types of leaks to the ContainerLeakDetector
 
 
-from pandac.PandaModules import *
+from panda3d.core import *
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.Job import Job
 from direct.showbase.Job import Job
 import gc, sys
 import gc, sys

+ 108 - 42
direct/src/showbase/Loader.py

@@ -28,7 +28,7 @@ class Loader(DirectObject):
             self.extraArgs = extraArgs
             self.extraArgs = extraArgs
             self.numRemaining = numObjects
             self.numRemaining = numObjects
             self.cancelled = False
             self.cancelled = False
-            self.requests = {}
+            self.requests = set()
 
 
         def gotObject(self, index, object):
         def gotObject(self, index, object):
             self.objects[index] = object
             self.objects[index] = object
@@ -45,6 +45,8 @@ class Loader(DirectObject):
         self.base = base
         self.base = base
         self.loader = PandaLoader.getGlobalPtr()
         self.loader = PandaLoader.getGlobalPtr()
 
 
+        self.__requests = {}
+
         self.hook = "async_loader_%s" % (Loader.loaderIndex)
         self.hook = "async_loader_%s" % (Loader.loaderIndex)
         Loader.loaderIndex += 1
         Loader.loaderIndex += 1
         self.accept(self.hook, self.__gotAsyncObject)
         self.accept(self.hook, self.__gotAsyncObject)
@@ -116,7 +118,7 @@ class Loader(DirectObject):
         """
         """
 
 
         assert Loader.notify.debug("Loading model: %s" % (modelPath))
         assert Loader.notify.debug("Loading model: %s" % (modelPath))
-        if loaderOptions == None:
+        if loaderOptions is None:
             loaderOptions = LoaderOptions()
             loaderOptions = LoaderOptions()
         else:
         else:
             loaderOptions = LoaderOptions(loaderOptions)
             loaderOptions = LoaderOptions(loaderOptions)
@@ -156,7 +158,7 @@ class Loader(DirectObject):
             result = []
             result = []
             for modelPath in modelList:
             for modelPath in modelList:
                 node = self.loader.loadSync(Filename(modelPath), loaderOptions)
                 node = self.loader.loadSync(Filename(modelPath), loaderOptions)
-                if (node != None):
+                if node is not None:
                     nodePath = NodePath(node)
                     nodePath = NodePath(node)
                 else:
                 else:
                     nodePath = None
                     nodePath = None
@@ -179,16 +181,16 @@ class Loader(DirectObject):
             # callback (passing it the models on the parameter list).
             # callback (passing it the models on the parameter list).
 
 
             cb = Loader.Callback(len(modelList), gotList, callback, extraArgs)
             cb = Loader.Callback(len(modelList), gotList, callback, extraArgs)
-            i=0
+            i = 0
             for modelPath in modelList:
             for modelPath in modelList:
                 request = self.loader.makeAsyncRequest(Filename(modelPath), loaderOptions)
                 request = self.loader.makeAsyncRequest(Filename(modelPath), loaderOptions)
                 if priority is not None:
                 if priority is not None:
                     request.setPriority(priority)
                     request.setPriority(priority)
                 request.setDoneEvent(self.hook)
                 request.setDoneEvent(self.hook)
-                request.setPythonObject((cb, i))
-                i+=1
                 self.loader.loadAsync(request)
                 self.loader.loadAsync(request)
-                cb.requests[request] = True
+                cb.requests.add(request)
+                self.__requests[request] = (cb, i)
+                i += 1
             return cb
             return cb
 
 
     def cancelRequest(self, cb):
     def cancelRequest(self, cb):
@@ -200,6 +202,7 @@ class Loader(DirectObject):
             cb.cancelled = True
             cb.cancelled = True
             for request in cb.requests:
             for request in cb.requests:
                 self.loader.remove(request)
                 self.loader.remove(request)
+                del self.__requests[request]
             cb.requests = None
             cb.requests = None
 
 
     def isRequestPending(self, cb):
     def isRequestPending(self, cb):
@@ -273,7 +276,7 @@ class Loader(DirectObject):
             # to resolve it for us.
             # to resolve it for us.
             options = LoaderOptions(LoaderOptions.LFSearch | LoaderOptions.LFNoDiskCache | LoaderOptions.LFCacheOnly)
             options = LoaderOptions(LoaderOptions.LFSearch | LoaderOptions.LFNoDiskCache | LoaderOptions.LFCacheOnly)
             modelNode = self.loader.loadSync(Filename(model), options)
             modelNode = self.loader.loadSync(Filename(model), options)
-            if modelNode == None:
+            if modelNode is None:
                 # Model not found.
                 # Model not found.
                 assert Loader.notify.debug("Unloading model not loaded: %s" % (model))
                 assert Loader.notify.debug("Unloading model not loaded: %s" % (model))
                 return
                 return
@@ -293,7 +296,7 @@ class Loader(DirectObject):
         a callback is used, the model is saved asynchronously, and the
         a callback is used, the model is saved asynchronously, and the
         true/false status is passed to the callback function. """
         true/false status is passed to the callback function. """
 
 
-        if loaderOptions == None:
+        if loaderOptions is None:
             loaderOptions = LoaderOptions()
             loaderOptions = LoaderOptions()
         else:
         else:
             loaderOptions = LoaderOptions(loaderOptions)
             loaderOptions = LoaderOptions(loaderOptions)
@@ -342,16 +345,16 @@ class Loader(DirectObject):
             # callback (passing it the models on the parameter list).
             # callback (passing it the models on the parameter list).
 
 
             cb = Loader.Callback(len(modelList), gotList, callback, extraArgs)
             cb = Loader.Callback(len(modelList), gotList, callback, extraArgs)
-            i=0
+            i = 0
             for modelPath, node in modelList:
             for modelPath, node in modelList:
                 request = self.loader.makeAsyncSaveRequest(Filename(modelPath), loaderOptions, node)
                 request = self.loader.makeAsyncSaveRequest(Filename(modelPath), loaderOptions, node)
                 if priority is not None:
                 if priority is not None:
                     request.setPriority(priority)
                     request.setPriority(priority)
                 request.setDoneEvent(self.hook)
                 request.setDoneEvent(self.hook)
-                request.setPythonObject((cb, i))
-                i+=1
                 self.loader.saveAsync(request)
                 self.loader.saveAsync(request)
-                cb.requests[request] = True
+                cb.requests.add(request)
+                self.__requests[request] = (cb, i)
+                i += 1
             return cb
             return cb
 
 
 
 
@@ -496,7 +499,7 @@ class Loader(DirectObject):
             phaseChecker(modelPath, loaderOptions)
             phaseChecker(modelPath, loaderOptions)
 
 
         font = FontPool.loadFont(modelPath)
         font = FontPool.loadFont(modelPath)
-        if font == None:
+        if font is None:
             if not okMissing:
             if not okMissing:
                 message = 'Could not load font file: %s' % (modelPath)
                 message = 'Could not load font file: %s' % (modelPath)
                 raise IOError(message)
                 raise IOError(message)
@@ -506,21 +509,21 @@ class Loader(DirectObject):
 
 
         # The following properties may only be set for dynamic fonts.
         # The following properties may only be set for dynamic fonts.
         if hasattr(font, "setPointSize"):
         if hasattr(font, "setPointSize"):
-            if pointSize != None:
+            if pointSize is not None:
                 font.setPointSize(pointSize)
                 font.setPointSize(pointSize)
-            if pixelsPerUnit != None:
+            if pixelsPerUnit is not None:
                 font.setPixelsPerUnit(pixelsPerUnit)
                 font.setPixelsPerUnit(pixelsPerUnit)
-            if scaleFactor != None:
+            if scaleFactor is not None:
                 font.setScaleFactor(scaleFactor)
                 font.setScaleFactor(scaleFactor)
-            if textureMargin != None:
+            if textureMargin is not None:
                 font.setTextureMargin(textureMargin)
                 font.setTextureMargin(textureMargin)
-            if polyMargin != None:
+            if polyMargin is not None:
                 font.setPolyMargin(polyMargin)
                 font.setPolyMargin(polyMargin)
-            if minFilter != None:
+            if minFilter is not None:
                 font.setMinfilter(minFilter)
                 font.setMinfilter(minFilter)
-            if magFilter != None:
+            if magFilter is not None:
                 font.setMagfilter(magFilter)
                 font.setMagfilter(magFilter)
-            if anisotropicDegree != None:
+            if anisotropicDegree is not None:
                 font.setAnisotropicDegree(anisotropicDegree)
                 font.setAnisotropicDegree(anisotropicDegree)
             if color:
             if color:
                 font.setFg(color)
                 font.setFg(color)
@@ -577,10 +580,10 @@ class Loader(DirectObject):
         the texture and the number of expected mipmap images.
         the texture and the number of expected mipmap images.
 
 
         If minfilter or magfilter is not None, they should be a symbol
         If minfilter or magfilter is not None, they should be a symbol
-        like Texture.FTLinear or Texture.FTNearest.  (minfilter may be
-        further one of the Mipmap filter type symbols.)  These specify
-        the filter mode that will automatically be applied to the
-        texture when it is loaded.  Note that this setting may
+        like SamplerState.FTLinear or SamplerState.FTNearest.  (minfilter
+        may be further one of the Mipmap filter type symbols.)  These
+        specify the filter mode that will automatically be applied to
+        the texture when it is loaded.  Note that this setting may
         override the texture's existing settings, even if it has
         override the texture's existing settings, even if it has
         already been loaded.  See egg-texture-cards for a more robust
         already been loaded.  See egg-texture-cards for a more robust
         way to apply per-texture filter types and settings.
         way to apply per-texture filter types and settings.
@@ -596,7 +599,7 @@ class Loader(DirectObject):
         left image and '1' for the right image.  Larger numbers are
         left image and '1' for the right image.  Larger numbers are
         also allowed if you need more than two views.
         also allowed if you need more than two views.
         """
         """
-        if loaderOptions == None:
+        if loaderOptions is None:
             loaderOptions = LoaderOptions()
             loaderOptions = LoaderOptions()
         else:
         else:
             loaderOptions = LoaderOptions(loaderOptions)
             loaderOptions = LoaderOptions(loaderOptions)
@@ -657,7 +660,7 @@ class Loader(DirectObject):
         numbered 8 - 15 will be part of the right eye view.
         numbered 8 - 15 will be part of the right eye view.
         """
         """
         assert Loader.notify.debug("Loading 3-D texture: %s" % (texturePattern))
         assert Loader.notify.debug("Loading 3-D texture: %s" % (texturePattern))
-        if loaderOptions == None:
+        if loaderOptions is None:
             loaderOptions = LoaderOptions()
             loaderOptions = LoaderOptions()
         else:
         else:
             loaderOptions = LoaderOptions(loaderOptions)
             loaderOptions = LoaderOptions(loaderOptions)
@@ -684,6 +687,63 @@ class Loader(DirectObject):
 
 
         return texture
         return texture
 
 
+    def load2DTextureArray(self, texturePattern, readMipmaps = False, okMissing = False,
+                      minfilter = None, magfilter = None, anisotropicDegree = None,
+                      loaderOptions = None, multiview = None, numViews = 2):
+        """
+        texturePattern is a string that contains a sequence of one or
+        more hash characters ('#'), which will be filled in with the
+        z-height number.  Returns a 2-D Texture array object, suitable
+        for rendering array of textures.
+
+        okMissing should be True to indicate the method should return
+        None if the texture file is not found.  If it is False, the
+        method will raise an exception if the texture file is not
+        found or cannot be loaded.
+
+        If readMipmaps is True, then the filename string must contain
+        two sequences of hash characters; the first group is filled in
+        with the z-height number, and the second group with the mipmap
+        index number.
+
+        If multiview is true, it indicates to load a multiview or
+        stereo texture.  In this case, numViews should also be
+        specified (the default is 2), and the sequence of texture
+        images will be divided into numViews views.  The total
+        z-height will be (numImages / numViews).  For instance, if you
+        read 16 images with numViews = 2, then you have created a
+        stereo multiview image, with z = 8.  In this example, images
+        numbered 0 - 7 will be part of the left eye view, and images
+        numbered 8 - 15 will be part of the right eye view.
+        """
+        assert Loader.notify.debug("Loading 2-D texture array: %s" % (texturePattern))
+        if loaderOptions is None:
+            loaderOptions = LoaderOptions()
+        else:
+            loaderOptions = LoaderOptions(loaderOptions)
+        if multiview is not None:
+            flags = loaderOptions.getTextureFlags()
+            if multiview:
+                flags |= LoaderOptions.TFMultiview
+            else:
+                flags &= ~LoaderOptions.TFMultiview
+            loaderOptions.setTextureFlags(flags)
+            loaderOptions.setTextureNumViews(numViews)
+
+        texture = TexturePool.load2dTextureArray(texturePattern, readMipmaps, loaderOptions)
+        if not texture and not okMissing:
+            message = 'Could not load 2-D texture array: %s' % (texturePattern)
+            raise IOError(message)
+
+        if minfilter is not None:
+            texture.setMinfilter(minfilter)
+        if magfilter is not None:
+            texture.setMagfilter(magfilter)
+        if anisotropicDegree is not None:
+            texture.setAnisotropicDegree(anisotropicDegree)
+
+        return texture
+
     def loadCubeMap(self, texturePattern, readMipmaps = False, okMissing = False,
     def loadCubeMap(self, texturePattern, readMipmaps = False, okMissing = False,
                     minfilter = None, magfilter = None, anisotropicDegree = None,
                     minfilter = None, magfilter = None, anisotropicDegree = None,
                     loaderOptions = None, multiview = None):
                     loaderOptions = None, multiview = None):
@@ -711,7 +771,7 @@ class Loader(DirectObject):
         and each six images will define a new view.
         and each six images will define a new view.
         """
         """
         assert Loader.notify.debug("Loading cube map: %s" % (texturePattern))
         assert Loader.notify.debug("Loading cube map: %s" % (texturePattern))
-        if loaderOptions == None:
+        if loaderOptions is None:
             loaderOptions = LoaderOptions()
             loaderOptions = LoaderOptions()
         else:
         else:
             loaderOptions = LoaderOptions(loaderOptions)
             loaderOptions = LoaderOptions(loaderOptions)
@@ -821,13 +881,12 @@ class Loader(DirectObject):
             # callback (passing it the sounds on the parameter list).
             # callback (passing it the sounds on the parameter list).
 
 
             cb = Loader.Callback(len(soundList), gotList, callback, extraArgs)
             cb = Loader.Callback(len(soundList), gotList, callback, extraArgs)
-            for i in range(len(soundList)):
-                soundPath = soundList[i]
+            for i, soundPath in enumerate(soundList):
                 request = AudioLoadRequest(manager, soundPath, positional)
                 request = AudioLoadRequest(manager, soundPath, positional)
                 request.setDoneEvent(self.hook)
                 request.setDoneEvent(self.hook)
-                request.setPythonObject((cb, i))
                 self.loader.loadAsync(request)
                 self.loader.loadAsync(request)
-                cb.requests[request] = True
+                cb.requests.add(request)
+                self.__requests[request] = (cb, i)
             return cb
             return cb
 
 
     def unloadSfx(self, sfx):
     def unloadSfx(self, sfx):
@@ -852,7 +911,7 @@ class Loader(DirectObject):
         return shader
         return shader
 
 
     def unloadShader(self, shaderPath):
     def unloadShader(self, shaderPath):
-        if (shaderPath != None):
+        if shaderPath is not None:
             ShaderPool.releaseShader(shaderPath)
             ShaderPool.releaseShader(shaderPath)
 
 
     def asyncFlattenStrong(self, model, inPlace = True,
     def asyncFlattenStrong(self, model, inPlace = True,
@@ -886,14 +945,14 @@ class Loader(DirectObject):
             gotList = True
             gotList = True
 
 
         cb = Loader.Callback(len(modelList), gotList, callback, extraArgs)
         cb = Loader.Callback(len(modelList), gotList, callback, extraArgs)
-        i=0
+        i = 0
         for model in modelList:
         for model in modelList:
             request = ModelFlattenRequest(model.node())
             request = ModelFlattenRequest(model.node())
             request.setDoneEvent(self.hook)
             request.setDoneEvent(self.hook)
-            request.setPythonObject((cb, i))
-            i+=1
             self.loader.loadAsync(request)
             self.loader.loadAsync(request)
-            cb.requests[request] = True
+            cb.requests.add(request)
+            self.__requests[request] = (cb, i)
+            i += 1
         return cb
         return cb
 
 
     def __asyncFlattenDone(self, models,
     def __asyncFlattenDone(self, models,
@@ -907,7 +966,7 @@ class Loader(DirectObject):
             orig = origModelList[i].node()
             orig = origModelList[i].node()
             flat = models[i].node()
             flat = models[i].node()
             orig.copyAllProperties(flat)
             orig.copyAllProperties(flat)
-            orig.replaceNode(flat)
+            flat.replaceNode(orig)
 
 
         if callback:
         if callback:
             if gotList:
             if gotList:
@@ -921,16 +980,23 @@ class Loader(DirectObject):
         of loaded objects, and call the appropriate callback when it's
         of loaded objects, and call the appropriate callback when it's
         time."""
         time."""
 
 
-        cb, i = request.getPythonObject()
+        if request not in self.__requests:
+            return
+
+        cb, i = self.__requests[request]
         if cb.cancelled:
         if cb.cancelled:
+            # Shouldn't be here.
+            del self.__requests[request]
             return
             return
 
 
-        del cb.requests[request]
+        cb.requests.discard(request)
+        if not cb.requests:
+            del self.__requests[request]
 
 
         object = None
         object = None
         if hasattr(request, "getModel"):
         if hasattr(request, "getModel"):
             node = request.getModel()
             node = request.getModel()
-            if (node != None):
+            if node is not None:
                 object = NodePath(node)
                 object = NodePath(node)
 
 
         elif hasattr(request, "getSound"):
         elif hasattr(request, "getSound"):

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

@@ -23,7 +23,7 @@ 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."""
 
 
-from pandac.PandaModules import *
+from panda3d.core import *
 from direct.task import Task
 from direct.task import Task
 
 
 def setupMirror(name, width, height, rootCamera = None):
 def setupMirror(name, width, height, rootCamera = None):

+ 36 - 1
direct/src/showbase/PythonUtil.py

@@ -38,7 +38,6 @@ import os
 import sys
 import sys
 import random
 import random
 import time
 import time
-import importlib
 
 
 __report_indent = 3
 __report_indent = 3
 
 
@@ -61,6 +60,42 @@ def Functor(function, *args, **kArgs):
     return functor
     return functor
 """
 """
 
 
+try:
+    import importlib
+except ImportError:
+    # Backward compatibility for Python 2.6.
+    def _resolve_name(name, package, level):
+        if not hasattr(package, 'rindex'):
+            raise ValueError("'package' not set to a string")
+        dot = len(package)
+        for x in xrange(level, 1, -1):
+            try:
+                dot = package.rindex('.', 0, dot)
+            except ValueError:
+                raise ValueError("attempted relative import beyond top-level "
+                                  "package")
+        return "%s.%s" % (package[:dot], name)
+
+    def import_module(name, package=None):
+        if name.startswith('.'):
+            if not package:
+                raise TypeError("relative imports require the 'package' argument")
+            level = 0
+            for character in name:
+                if character != '.':
+                    break
+                level += 1
+            name = _resolve_name(name[level:], package, level)
+        __import__(name)
+        return sys.modules[name]
+
+    imp = import_module('imp')
+    importlib = imp.new_module("importlib")
+    importlib._resolve_name = _resolve_name
+    importlib.import_module = import_module
+    sys.modules['importlib'] = importlib
+
+
 class Functor:
 class Functor:
     def __init__(self, function, *args, **kargs):
     def __init__(self, function, *args, **kargs):
         assert callable(function), "function should be a callable obj"
         assert callable(function), "function should be a callable obj"

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

@@ -14,7 +14,7 @@ multitexture rendering techniques.  It's not a particularly great
 way to do shadows.
 way to do shadows.
 """
 """
 
 
-from pandac.PandaModules import *
+from panda3d.core import *
 from direct.task import Task
 from direct.task import Task
 
 
 sc = None
 sc = None

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

@@ -12,7 +12,7 @@ the its parent node.
 
 
 from direct.controls.ControlManager import CollisionHandlerRayStart
 from direct.controls.ControlManager import CollisionHandlerRayStart
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
-from pandac.PandaModules import *
+from panda3d.core import *
 from . import DirectObject
 from . import DirectObject
 
 
 class ShadowPlacer(DirectObject.DirectObject):
 class ShadowPlacer(DirectObject.DirectObject):

+ 22 - 9
direct/src/showbase/ShowBase.py

@@ -127,10 +127,6 @@ class ShowBase(DirectObject.DirectObject):
         ## just before Python is about to shut down.
         ## just before Python is about to shut down.
         self.finalExitCallbacks = []
         self.finalExitCallbacks = []
 
 
-        Task.TaskManager.taskTimerVerbose = self.config.GetBool('task-timer-verbose', 0)
-        Task.TaskManager.extendedExceptions = self.config.GetBool('extended-exceptions', 0)
-        Task.TaskManager.pStatsTasks = self.config.GetBool('pstats-tasks', 0)
-
         # Set up the TaskManager to reset the PStats clock back
         # Set up the TaskManager to reset the PStats clock back
         # whenever we resume from a pause.  This callback function is
         # whenever we resume from a pause.  This callback function is
         # a little hacky, but we can't call it directly from within
         # a little hacky, but we can't call it directly from within
@@ -201,7 +197,9 @@ class ShowBase(DirectObject.DirectObject):
         ## This is used to store the wx.Application object used when want-wx is
         ## This is used to store the wx.Application object used when want-wx is
         ## set or base.startWx() is called.
         ## set or base.startWx() is called.
         self.wxApp = None
         self.wxApp = None
+        self.wxAppCreated = False
         self.tkRoot = None
         self.tkRoot = None
+        self.tkRootCreated = False
 
 
         # This is used for syncing multiple PCs in a distributed cluster
         # This is used for syncing multiple PCs in a distributed cluster
         try:
         try:
@@ -259,6 +257,17 @@ class ShowBase(DirectObject.DirectObject):
             random.seed(seed)
             random.seed(seed)
             #whrandom.seed(seed & 0xff, (seed >> 8) & 0xff, (seed >> 16) & 0xff)
             #whrandom.seed(seed & 0xff, (seed >> 8) & 0xff, (seed >> 16) & 0xff)
 
 
+        # For some reason, wx needs to be initialized before the graphics window
+        if sys.platform == "darwin":
+            if self.config.GetBool("want-wx", 0):
+                wx = importlib.import_module('wx')
+                self.wxApp = wx.App()
+
+            # Same goes for Tk, which uses a conflicting NSApplication
+            if self.config.GetBool("want-tk", 0):
+                Pmw = importlib.import_module('Pmw')
+                self.tkRoot = Pmw.initialise()
+
         # Open the default rendering window.
         # Open the default rendering window.
         if self.windowType != 'none':
         if self.windowType != 'none':
             props = WindowProperties.getDefault()
             props = WindowProperties.getDefault()
@@ -2821,7 +2830,7 @@ class ShowBase(DirectObject.DirectObject):
         updated, but wxPython owns the main loop (which seems to make
         updated, but wxPython owns the main loop (which seems to make
         it happier than the other way around). """
         it happier than the other way around). """
 
 
-        if self.wxApp:
+        if self.wxAppCreated:
             # Don't do this twice.
             # Don't do this twice.
             return
             return
 
 
@@ -2831,8 +2840,9 @@ class ShowBase(DirectObject.DirectObject):
         # by modulefinder when packaging an application.
         # by modulefinder when packaging an application.
         wx = importlib.import_module('wx')
         wx = importlib.import_module('wx')
 
 
-        # Create a new base.wxApp.
-        self.wxApp = wx.PySimpleApp(redirect = False)
+        if not self.wxApp:
+            # Create a new base.wxApp.
+            self.wxApp = wx.PySimpleApp(redirect = False)
 
 
         if ConfigVariableBool('wx-main-loop', True):
         if ConfigVariableBool('wx-main-loop', True):
             # Put wxPython in charge of the main loop.  It really
             # Put wxPython in charge of the main loop.  It really
@@ -2867,6 +2877,7 @@ class ShowBase(DirectObject.DirectObject):
                 return task.again
                 return task.again
 
 
             self.taskMgr.add(wxLoop, 'wxLoop')
             self.taskMgr.add(wxLoop, 'wxLoop')
+        self.wxAppCreated = True
 
 
     def __wxTimerCallback(self, event):
     def __wxTimerCallback(self, event):
         if Thread.getCurrentThread().getCurrentTask():
         if Thread.getCurrentThread().getCurrentTask():
@@ -2901,7 +2912,7 @@ class ShowBase(DirectObject.DirectObject):
         updated, but Tkinter owns the main loop (which seems to make
         updated, but Tkinter owns the main loop (which seems to make
         it happier than the other way around). """
         it happier than the other way around). """
 
 
-        if self.tkRoot:
+        if self.tkRootCreated:
             # Don't do this twice.
             # Don't do this twice.
             return
             return
 
 
@@ -2911,7 +2922,8 @@ class ShowBase(DirectObject.DirectObject):
         Pmw = importlib.import_module('Pmw')
         Pmw = importlib.import_module('Pmw')
 
 
         # Create a new Tk root.
         # Create a new Tk root.
-        self.tkRoot = Pmw.initialise()
+        if not self.tkRoot:
+            self.tkRoot = Pmw.initialise()
         builtins.tkroot = self.tkRoot
         builtins.tkroot = self.tkRoot
 
 
         init_app_for_gui()
         init_app_for_gui()
@@ -2947,6 +2959,7 @@ class ShowBase(DirectObject.DirectObject):
                 return task.again
                 return task.again
 
 
             self.taskMgr.add(tkLoop, 'tkLoop')
             self.taskMgr.add(tkLoop, 'tkLoop')
+        self.tkRootCreated = True
 
 
     def __tkTimerCallback(self):
     def __tkTimerCallback(self):
         if not Thread.getCurrentThread().getCurrentTask():
         if not Thread.getCurrentThread().getCurrentTask():

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

@@ -2,6 +2,7 @@ __all__ = ['register', 'sharedPackages',
            'reloadSharedPackage', 'reloadSharedPackages']
            'reloadSharedPackage', 'reloadSharedPackages']
 
 
 from panda3d.core import Filename, VirtualFileSystem, VirtualFileMountSystem, OFileStream, copyStream
 from panda3d.core import Filename, VirtualFileSystem, VirtualFileMountSystem, OFileStream, copyStream
+from direct.stdpy.file import open
 import sys
 import sys
 import marshal
 import marshal
 import imp
 import imp
@@ -173,10 +174,7 @@ class VFSLoader:
         filename = Filename(self.filename)
         filename = Filename(self.filename)
         filename.setExtension('py')
         filename.setExtension('py')
         filename.setText()
         filename.setText()
-        vfile = vfs.getFile(filename)
-        if not vfile:
-            raise IOError("Could not find '%s'" % (filename))
-        return vfile.readFile(True)
+        return open(self.filename, self.desc[1]).read()
 
 
     def _import_extension_module(self, fullname):
     def _import_extension_module(self, fullname):
         """ Loads the binary shared object as a Python module, and
         """ Loads the binary shared object as a Python module, and

+ 0 - 1
direct/src/showutil/.gitignore

@@ -1 +0,0 @@
-/runp3d

+ 5 - 2
direct/src/showutil/FreezeTool.py

@@ -984,7 +984,10 @@ class Freezer:
             try:
             try:
                 self.__loadModule(mdef)
                 self.__loadModule(mdef)
             except ImportError as ex:
             except ImportError as ex:
-                print("Unknown module: %s (%s)" % (mdef.moduleName, str(ex)))
+                message = "Unknown module: %s" % (mdef.moduleName)
+                if str(ex) != "No module named " + str(mdef.moduleName):
+                    message += " (%s)" % (ex)
+                print(message)
 
 
         # Also attempt to import any implicit modules.  If any of
         # Also attempt to import any implicit modules.  If any of
         # these fail to import, we don't really care.
         # these fail to import, we don't really care.
@@ -1190,7 +1193,7 @@ class Freezer:
 
 
             if self.storePythonSource:
             if self.storePythonSource:
                 filename += '.py'
                 filename += '.py'
-                stream = StringStream('')
+                stream = StringStream(b'')
                 if multifile.findSubfile(filename) < 0:
                 if multifile.findSubfile(filename) < 0:
                     multifile.addSubfile(filename, stream, 0)
                     multifile.addSubfile(filename, stream, 0)
                     multifile.flush()
                     multifile.flush()

+ 10 - 10
direct/src/stdpy/thread.py

@@ -102,7 +102,7 @@ def start_new_thread(function, args, kwargs = {}, name = None):
             name = 'PythonThread-%s' % (threadId)
             name = 'PythonThread-%s' % (threadId)
 
 
         thread = core.PythonThread(threadFunc, [threadId], name, name)
         thread = core.PythonThread(threadFunc, [threadId], name, name)
-        thread.setPythonData(threadId)
+        thread.setPythonIndex(threadId)
         _threads[threadId] = (thread, {}, None)
         _threads[threadId] = (thread, {}, None)
 
 
         thread.start(core.TPNormal, False)
         thread.start(core.TPNormal, False)
@@ -121,7 +121,7 @@ def _add_thread(thread, wrapper):
         threadId = _nextThreadId
         threadId = _nextThreadId
         _nextThreadId += 1
         _nextThreadId += 1
 
 
-        thread.setPythonData(threadId)
+        thread.setPythonIndex(threadId)
         _threads[threadId] = (thread, {}, wrapper)
         _threads[threadId] = (thread, {}, wrapper)
         return threadId
         return threadId
 
 
@@ -133,8 +133,8 @@ def _get_thread_wrapper(thread, wrapperClass):
     is not one, creates an instance of the indicated wrapperClass
     is not one, creates an instance of the indicated wrapperClass
     instead. """
     instead. """
 
 
-    threadId = thread.getPythonData()
-    if threadId is None:
+    threadId = thread.getPythonIndex()
+    if threadId == -1:
         # The thread has never been assigned a threadId.  Go assign one.
         # The thread has never been assigned a threadId.  Go assign one.
 
 
         global _nextThreadId
         global _nextThreadId
@@ -143,7 +143,7 @@ def _get_thread_wrapper(thread, wrapperClass):
             threadId = _nextThreadId
             threadId = _nextThreadId
             _nextThreadId += 1
             _nextThreadId += 1
 
 
-            thread.setPythonData(threadId)
+            thread.setPythonIndex(threadId)
             wrapper = wrapperClass(thread, threadId)
             wrapper = wrapperClass(thread, threadId)
             _threads[threadId] = (thread, {}, wrapper)
             _threads[threadId] = (thread, {}, wrapper)
             return wrapper
             return wrapper
@@ -169,8 +169,8 @@ def _get_thread_locals(thread, i):
     """ Returns the locals dictionary for the indicated thread.  If
     """ Returns the locals dictionary for the indicated thread.  If
     there is not one, creates an empty dictionary. """
     there is not one, creates an empty dictionary. """
 
 
-    threadId = thread.getPythonData()
-    if threadId is None:
+    threadId = thread.getPythonIndex()
+    if threadId == -1:
         # The thread has never been assigned a threadId.  Go assign one.
         # The thread has never been assigned a threadId.  Go assign one.
 
 
         global _nextThreadId
         global _nextThreadId
@@ -179,7 +179,7 @@ def _get_thread_locals(thread, i):
             threadId = _nextThreadId
             threadId = _nextThreadId
             _nextThreadId += 1
             _nextThreadId += 1
 
 
-            thread.setPythonData(threadId)
+            thread.setPythonIndex(threadId)
             locals = {}
             locals = {}
             _threads[threadId] = (thread, locals, None)
             _threads[threadId] = (thread, locals, None)
             return locals.setdefault(i, {})
             return locals.setdefault(i, {})
@@ -205,9 +205,9 @@ def _remove_thread_id(threadId):
     _threadsLock.acquire()
     _threadsLock.acquire()
     try:
     try:
         thread, locals, wrapper = _threads[threadId]
         thread, locals, wrapper = _threads[threadId]
-        assert thread.getPythonData() == threadId
+        assert thread.getPythonIndex() == threadId
         del _threads[threadId]
         del _threads[threadId]
-        thread.setPythonData(None)
+        thread.setPythonIndex(-1)
 
 
     finally:
     finally:
         _threadsLock.release()
         _threadsLock.release()

+ 7 - 7
direct/src/task/Task.py

@@ -102,7 +102,10 @@ Task.DtoolClassDict['loop'] = staticmethod(loop)
 class TaskManager:
 class TaskManager:
     notify = directNotify.newCategory("TaskManager")
     notify = directNotify.newCategory("TaskManager")
 
 
-    extendedExceptions = False
+    taskTimerVerbose = ConfigVariableBool('task-timer-verbose', False)
+    extendedExceptions = ConfigVariableBool('extended-exceptions', False)
+    pStatsTasks = ConfigVariableBool('pstats-tasks', False)
+
     MaxEpochSpeed = 1.0/30.0
     MaxEpochSpeed = 1.0/30.0
 
 
     def __init__(self):
     def __init__(self):
@@ -397,7 +400,6 @@ class TaskManager:
                 'Task %s does not accept arguments.' % (repr(task)))
                 'Task %s does not accept arguments.' % (repr(task)))
 
 
         if name is not None:
         if name is not None:
-            assert isinstance(name, str), 'Name must be a string type'
             task.setName(name)
             task.setName(name)
         assert task.hasName()
         assert task.hasName()
 
 
@@ -431,16 +433,14 @@ class TaskManager:
         all tasks with the indicated name are removed.  Returns the
         all tasks with the indicated name are removed.  Returns the
         number of tasks removed. """
         number of tasks removed. """
 
 
-        if isinstance(taskOrName, str):
-            tasks = self.mgr.findTasks(taskOrName)
-            return self.mgr.remove(tasks)
-        elif isinstance(taskOrName, AsyncTask):
+        if isinstance(taskOrName, AsyncTask):
             return self.mgr.remove(taskOrName)
             return self.mgr.remove(taskOrName)
         elif isinstance(taskOrName, list):
         elif isinstance(taskOrName, list):
             for task in taskOrName:
             for task in taskOrName:
                 self.remove(task)
                 self.remove(task)
         else:
         else:
-            self.notify.error('remove takes a string or a Task')
+            tasks = self.mgr.findTasks(taskOrName)
+            return self.mgr.remove(tasks)
 
 
     def removeTasksMatching(self, taskPattern):
     def removeTasksMatching(self, taskPattern):
         """Removes all tasks whose names match the pattern, which can
         """Removes all tasks whose names match the pattern, which can

+ 2 - 2
direct/src/tkpanels/DirectSessionPanel.py

@@ -177,8 +177,8 @@ class DirectSessionPanel(AppShell):
             sgeFrame, nodePath = render,
             sgeFrame, nodePath = render,
             scrolledCanvas_hull_width = 250,
             scrolledCanvas_hull_width = 250,
             scrolledCanvas_hull_height = 300)
             scrolledCanvas_hull_height = 300)
-        self.SGE.pack(fill = BOTH, expand = 0)
-        sgeFrame.pack(side = LEFT, fill = 'both', expand = 0)
+        self.SGE.pack(fill = BOTH, expand = 1)
+        sgeFrame.pack(side = LEFT, fill = 'both', expand = 1)
 
 
         # Create the notebook pages
         # Create the notebook pages
         notebook = Pmw.NoteBook(notebookFrame)
         notebook = Pmw.NoteBook(notebookFrame)

+ 3 - 3
direct/src/tkpanels/ParticlePanel.py

@@ -1976,9 +1976,9 @@ class ParticlePanel(AppShell):
         self.particles.renderer.setAlphaDisable(
         self.particles.renderer.setAlphaDisable(
             self.getVariable('Sprite Renderer', 'Alpha Disable').get())
             self.getVariable('Sprite Renderer', 'Alpha Disable').get())
     def setRendererColorBlendAttrib(self, rendererName, blendMethodStr, incomingOperandStr, fbufferOperandStr):
     def setRendererColorBlendAttrib(self, rendererName, blendMethodStr, incomingOperandStr, fbufferOperandStr):
-        self.particles.getRenderer().setColorBlendMode(eval('ColorBlendAttrib.'+blendMethodStr),
-                                                       eval('ColorBlendAttrib.'+incomingOperandStr),
-                                                       eval('ColorBlendAttrib.'+fbufferOperandStr))
+        self.particles.getRenderer().setColorBlendMode(getattr(ColorBlendAttrib, blendMethodStr),
+                                                       getattr(ColorBlendAttrib, incomingOperandStr),
+                                                       getattr(ColorBlendAttrib, fbufferOperandStr))
 
 
         if(blendMethodStr in ['MAdd','MSubtract','MInvSubtract']):
         if(blendMethodStr in ['MAdd','MSubtract','MInvSubtract']):
             self.getWidget(rendererName,'Incoming Op.').pack(fill = X)
             self.getWidget(rendererName,'Incoming Op.').pack(fill = X)

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

@@ -284,7 +284,7 @@ class MemoryExplorerItem:
     def getNumChildren(self):
     def getNumChildren(self):
         return len(self.children)
         return len(self.children)
 
 
-    def getChildrenAsList(self):
+    def getChildren(self):
         return self.children
         return self.children
 
 
     def getName(self):
     def getName(self):

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