ソースを参照

Merge branch 'master' into webgl-port

rdb 8 年 前
コミット
980da4da71
100 ファイル変更533 行追加1665 行削除
  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:
   include:
     - compiler: gcc
-      env: PYTHONV=python2.7 FLAGS=
+      env: PYTHONV=python2.7 FLAGS=--optimize=4
     - compiler: clang
       env: PYTHONV=python3 FLAGS=--installer
     - 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
 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
 ================
 
@@ -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
 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:
-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
 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
 options:
 ```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
@@ -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
 `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,
 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
-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.
 
 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
  */
 
-#pragma warning (disable:4996)
-#pragma warning (disable:4005)
-#pragma warning(disable:4275)
-
 #ifndef _AIBEHAVIORS_H
 #define _AIBEHAVIORS_H
 

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

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

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

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

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

@@ -11,11 +11,6 @@
  * @date 2009-09-08
  */
 
-#pragma warning (disable:4996)
-#pragma warning (disable:4005)
-#pragma warning(disable:4275)
-
-
 #ifndef _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();
   LVecBase3 avoidance(0.0, 0.0, 0.0);
   double distance = 0x7fff ;
-  double expanded_radius;
+  double expanded_radius = 0;
   LVecBase3 to_obstacle;
   LVecBase3 prev_avoidance;
   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();
   PT(BoundingVolume) np_bounds = _ai_char->get_node_path().get_bounds();
   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());
     direction.normalize();
     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.task.Task import Task
-from pandac.PandaModules import *
+from panda3d.core import *
 from . import GravityWalker
 
 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.showbase.InputStateGlobal import inputState
 from direct.task.Task import Task
-from pandac.PandaModules import *
+from panda3d.core import *
 
 class NonPhysicsWalker(DirectObject.DirectObject):
     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
  * fields, all of which are of the same type.
  */
-class EXPCL_DIRECT DCArrayParameter : public DCParameter {
+class DCArrayParameter : public DCParameter {
 public:
   DCArrayParameter(DCParameter *element_type,
                    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
  * implemented as a remote procedure method.
  */
-class EXPCL_DIRECT DCAtomicField : public DCField {
+class DCAtomicField : public DCField {
 public:
   DCAtomicField(const string &name, DCClass *dclass, bool bogus_field);
   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.
  */
-class EXPCL_DIRECT DCClass : public DCDeclaration {
+class DCClass : public DCDeclaration {
 public:
   DCClass(DCFile *dc_file, const string &name,
           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 means that all the fields of the class get packed into the message.
  */
-class EXPCL_DIRECT DCClassParameter : public DCParameter {
+class DCClassParameter : public DCParameter {
 public:
   DCClassParameter(const DCClass *dclass);
   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
  * together so they can be ordered correctly on output.
  */
-class EXPCL_DIRECT DCDeclaration {
+class DCDeclaration {
 public:
   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.
  */
-class EXPCL_DIRECT DCField : public DCPackerInterface, public DCKeywordList {
+class DCField : public DCPackerInterface, public DCKeywordList {
 public:
   DCField();
   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
  * a .dc file.
  */
-class EXPCL_DIRECT DCFile {
+class DCFile {
 PUBLISHED:
   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
  * "broadcast" or "airecv".
  */
-class EXPCL_DIRECT DCKeyword : public DCDeclaration {
+class DCKeyword : public DCDeclaration {
 public:
   DCKeyword(const string &name, int historical_flag = ~0);
   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
  * field.
  */
-class EXPCL_DIRECT DCKeywordList {
+class DCKeywordList {
 public:
   DCKeywordList();
   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
  * will often be treated as a unit.
  */
-class EXPCL_DIRECT DCMolecularField : public DCField {
+class DCMolecularField : public DCField {
 public:
   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.
  */
-class EXPCL_DIRECT DCPackData {
+class DCPackData {
 PUBLISHED:
   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
  * examples of using this class.
  */
-class EXPCL_DIRECT DCPacker {
+class DCPacker {
 PUBLISHED:
   DCPacker();
   ~DCPacker();
@@ -216,7 +216,7 @@ private:
   const DCPackerCatalog *_catalog;
   const DCPackerCatalog::LiveCatalog *_live_catalog;
 
-  class EXPCL_DIRECT StackElement {
+  class StackElement {
   public:
     // As an optimization, we implement operator new and delete here to
     // 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
  * so it must not be deleted.
  */
-class EXPCL_DIRECT DCPackerCatalog {
+class DCPackerCatalog {
 private:
   DCPackerCatalog(const DCPackerInterface *root);
   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
  * wouldn't normally call these directly.
  */
-class EXPCL_DIRECT DCPackerInterface {
+class DCPackerInterface {
 public:
   DCPackerInterface(const string &name = string());
   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
  * properties as the referenced type, but a different name.
  */
-class EXPCL_DIRECT DCParameter : public DCField {
+class DCParameter : public DCField {
 protected:
   DCParameter();
   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
  * represents a fixed-point numeric convention).
  */
-class EXPCL_DIRECT DCSimpleParameter : public DCParameter {
+class DCSimpleParameter : public DCParameter {
 public:
   DCSimpleParameter(DCSubatomicType type, unsigned int divisor = 1);
   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
  * field read.
  */
-class EXPCL_DIRECT DCSwitch : public DCDeclaration {
+class DCSwitch : public DCDeclaration {
 public:
   DCSwitch(const string &name, DCField *key_parameter);
   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
  * appropriate fields of the switch into the message.
  */
-class EXPCL_DIRECT DCSwitchParameter : public DCParameter {
+class DCSwitchParameter : public DCParameter {
 public:
   DCSwitchParameter(const DCSwitch *dswitch);
   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
  * particular type to a new name, just like a C typedef.
  */
-class EXPCL_DIRECT DCTypedef : public DCDeclaration {
+class DCTypedef : public DCDeclaration {
 public:
   DCTypedef(DCParameter *parameter, bool implicit = false);
   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()
             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.setPos(base.direct.camera, hitPt)
                 self.coaMarkerPos = np.getPos()
-                np.remove()
+                np.removeNode()
                 self.coaMarker.setPos(self.coaMarkerPos)
 
             iRay.collisionNodePath.removeNode()

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

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

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

@@ -900,7 +900,7 @@ class DirectSession(DirectObject):
             # If nothing specified, try selected node path
             nodePath = self.selected.last
         if nodePath:
-            nodePath.remove()
+            nodePath.removeNode()
 
     def removeAllSelected(self):
         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
 
 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 direct.task import Task
 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.directnotify.DirectNotifyGlobal import directNotify
 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.interval.IntervalGlobal import *
 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
 
 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.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.task import Task
 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 GridParent
 

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

@@ -4,7 +4,6 @@ from panda3d.core import *
 from panda3d.direct import *
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.distributed.DistributedObjectBase import DistributedObjectBase
-from direct.showbase.PythonUtil import StackTrace
 #from PyDatagram import PyDatagram
 #from PyDatagramIterator import PyDatagramIterator
 
@@ -259,7 +258,10 @@ class DistributedObject(DistributedObjectBase):
     def _destroyDO(self):
         # after this is called, the object is no longer a DistributedObject
         # 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
         # this will catch typos in the data name in calls to get/setCachedData
         if hasattr(self, '_cachedData'):

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

@@ -13,7 +13,6 @@ class DistributedObjectBase(DirectObject):
     def __init__(self, cr):
         assert self.notify.debugStateCall(self)
         self.cr = cr
-        self.children = {}
         self.parentId = 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):
         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):
         if not self.ExecNamespace:
             # 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()
 
         # 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.distributed.DistributedObjectBase import DistributedObjectBase
 from direct.showbase import PythonUtil
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 #from PyDatagram import PyDatagram
 #from PyDatagramIterator import PyDatagramIterator
 

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

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

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

@@ -312,7 +312,6 @@ class DoCollectionManager:
         else:
             self.notify.warning('handleSetLocation: object %s not present' % self.getMsgChannel())
 
-    @exceptionLogged()
     def storeObjectLocation(self, object, parentId, zoneId):
         oldParentId = object.parentId
         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.
 """
 
-from pandac.PandaModules import *
+from panda3d.core import *
+from panda3d.direct import *
 from .MsgTypes import *
 from direct.showbase.PythonUtil import *
 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

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

@@ -1,6 +1,7 @@
 """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.task import Task
 from direct.directnotify import DirectNotifyGlobal

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

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

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

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

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

@@ -1,5 +1,5 @@
 from direct.distributed.ClockDelta import *
-from pandac.PandaModules import *
+from panda3d.core import *
 from direct.distributed import 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
-  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
 
 #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):
         self.fsmLock = RLock()
-        self.name = name
+        self._name = name
         self.stateArray = []
         self._serialNum = FSM.SerialNum
         FSM.SerialNum += 1
@@ -185,7 +185,7 @@ class FSM(DirectObject):
         # the messenger on every state change. The new and old states are
         # accessible as self.oldState and self.newState, and the transition
         # 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):
         if not self.state:
@@ -240,7 +240,7 @@ class FSM(DirectObject):
         try:
             assert isinstance(request, str)
             self.notify.debug("%s.forceTransition(%s, %s" % (
-                self.name, request, str(args)[1:]))
+                self._name, request, str(args)[1:]))
 
             if not self.state:
                 # Queue up the request.
@@ -268,7 +268,7 @@ class FSM(DirectObject):
         try:
             assert isinstance(request, str)
             self.notify.debug("%s.demand(%s, %s" % (
-                self.name, request, str(args)[1:]))
+                self._name, request, str(args)[1:]))
             if not self.state:
                 # Queue up the request.
                 self.__requestQueue.append(PythonUtil.Functor(
@@ -307,7 +307,7 @@ class FSM(DirectObject):
         try:
             assert isinstance(request, str)
             self.notify.debug("%s.request(%s, %s" % (
-                self.name, request, str(args)[1:]))
+                self._name, request, str(args)[1:]))
 
             filter = self.getCurrentFilter()
             result = filter(request, args)
@@ -385,7 +385,7 @@ class FSM(DirectObject):
 
         # In either case, we quietly ignore unhandled command
         # (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
 
     def filterOff(self, request, args):
@@ -444,7 +444,7 @@ class FSM(DirectObject):
         # Internal function to change unconditionally to the indicated
         # 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.newState = newState
@@ -476,7 +476,7 @@ class FSM(DirectObject):
 
         if self.__requestQueue:
             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()
 
     def __callEnterFunc(self, name, *args):
@@ -525,9 +525,9 @@ class FSM(DirectObject):
         try:
             className = self.__class__.__name__
             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:
-                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
         finally:
             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
         oposite of 'on').
         """
-        assert self.debugPrint("FourState(names=%s)"%(names))
+        self.stateIndex = 0
+        assert self.__debugPrint("FourState(names=%s)"%(names))
         self.track = None
         self.stateTime = 0.0
         self.names = names
@@ -120,7 +121,6 @@ class FourState:
                            self.exitState4,
                            [names[1]]),
             }
-        self.stateIndex = 0
         self.fsm = ClassicFSM.ClassicFSM('FourState',
                            list(self.states.values()),
                            # Initial State
@@ -131,7 +131,7 @@ class FourState:
         self.fsm.enterInitialState()
 
     def setTrack(self, track):
-        assert self.debugPrint("setTrack(track=%s)"%(track,))
+        assert self.__debugPrint("setTrack(track=%s)"%(track,))
         if self.track is not None:
             self.track.pause()
             self.track = None
@@ -147,27 +147,27 @@ class FourState:
     # If the client wants the state changed it needs to
     # send a request to the AI.
     #def setIsOn(self, isOn):
-    #    assert self.debugPrint("setIsOn(isOn=%s)"%(isOn,))
+    #    assert self.__debugPrint("setIsOn(isOn=%s)"%(isOn,))
     #    pass
 
     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
 
     def changedOnState(self, isOn):
         """
         Allow derived classes to overide this.
         """
-        assert self.debugPrint("changedOnState(isOn=%s)"%(isOn,))
+        assert self.__debugPrint("changedOnState(isOn=%s)"%(isOn,))
 
     ##### state 0 #####
 
     def enterState0(self):
-        assert self.debugPrint("enter0()")
+        assert self.__debugPrint("enter0()")
         self.enterStateN(0)
 
     def exitState0(self):
-        assert self.debugPrint("exit0()")
+        assert self.__debugPrint("exit0()")
         # It's important for FourStates to broadcast their state
         # when they are generated on the client. Before I put this in,
         # if a door was generated and went directly to an 'open' state,
@@ -177,43 +177,43 @@ class FourState:
     ##### state 1 #####
 
     def enterState1(self):
-        assert self.debugPrint("enterState1()")
+        assert self.__debugPrint("enterState1()")
         self.enterStateN(1)
 
     def exitState1(self):
-        assert self.debugPrint("exitState1()")
+        assert self.__debugPrint("exitState1()")
 
     ##### state 2 #####
 
     def enterState2(self):
-        assert self.debugPrint("enterState2()")
+        assert self.__debugPrint("enterState2()")
         self.enterStateN(2)
 
     def exitState2(self):
-        assert self.debugPrint("exitState2()")
+        assert self.__debugPrint("exitState2()")
 
     ##### state 3 #####
 
     def enterState3(self):
-        assert self.debugPrint("enterState3()")
+        assert self.__debugPrint("enterState3()")
         self.enterStateN(3)
 
     def exitState3(self):
-        assert self.debugPrint("exitState3()")
+        assert self.__debugPrint("exitState3()")
 
     ##### state 4 #####
 
     def enterState4(self):
-        assert self.debugPrint("enterState4()")
+        assert self.__debugPrint("enterState4()")
         self.enterStateN(4)
         self.changedOnState(1)
 
     def exitState4(self):
-        assert self.debugPrint("exitState4()")
+        assert self.__debugPrint("exitState4()")
         self.changedOnState(0)
 
     if __debug__:
-        def debugPrint(self, message):
+        def __debugPrint(self, message):
             """for debugging"""
             return self.notify.debug("%d (%d) %s"%(
                     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
         oposite of 'on').
         """
-        assert self.debugPrint(
+        self.stateIndex = 0
+        assert self.__debugPrint(
                 "FourStateAI(names=%s, durations=%s)"
                 %(names, durations))
         self.doLaterTask = None
-        self.stateIndex = 0
         assert len(names) == 5
         assert len(names) == len(durations)
         self.names = names
@@ -137,7 +137,7 @@ class FourStateAI:
         self.fsm.enterInitialState()
 
     def delete(self):
-        assert self.debugPrint("delete()")
+        assert self.__debugPrint("delete()")
         if self.doLaterTask is not None:
             self.doLaterTask.remove()
             del self.doLaterTask
@@ -145,15 +145,15 @@ class FourStateAI:
         del self.fsm
 
     def getState(self):
-        assert self.debugPrint("getState() returning %s"%(self.stateIndex,))
+        assert self.__debugPrint("getState() returning %s"%(self.stateIndex,))
         return [self.stateIndex]
 
     def sendState(self):
-        assert self.debugPrint("sendState()")
+        assert self.__debugPrint("sendState()")
         self.sendUpdate('setState', self.getState())
 
     def setIsOn(self, isOn):
-        assert self.debugPrint("setIsOn(isOn=%s)"%(isOn,))
+        assert self.__debugPrint("setIsOn(isOn=%s)"%(isOn,))
         if isOn:
             if self.stateIndex != 4:
                 # ...if it's not On; request turning on:
@@ -170,7 +170,7 @@ class FourStateAI:
         #    self.fsm.request(self.states[nextState])
 
     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
 
     def changedOnState(self, isOn):
@@ -179,12 +179,12 @@ class FourStateAI:
         The self.isOn value has toggled.  Call getIsOn() to
         get the current state.
         """
-        assert self.debugPrint("changedOnState(isOn=%s)"%(isOn,))
+        assert self.__debugPrint("changedOnState(isOn=%s)"%(isOn,))
 
     ##### states #####
 
     def switchToNextStateTask(self, task):
-        assert self.debugPrint("switchToNextStateTask()")
+        assert self.__debugPrint("switchToNextStateTask()")
         self.fsm.request(self.states[self.nextStateIndex])
         return Task.done
 
@@ -193,11 +193,11 @@ class FourStateAI:
         This function is intentionaly simple so that derived classes
         may easily alter the network message.
         """
-        assert self.debugPrint("distributeStateChange()")
+        assert self.__debugPrint("distributeStateChange()")
         self.sendState()
 
     def enterStateN(self, stateIndex, nextStateIndex):
-        assert self.debugPrint(
+        assert self.__debugPrint(
             "enterStateN(stateIndex=%s, nextStateIndex=%s)"%
             (stateIndex, nextStateIndex))
         self.stateIndex = stateIndex
@@ -211,7 +211,7 @@ class FourStateAI:
                 "enterStateN-timer-%s"%id(self))
 
     def exitStateN(self):
-        assert self.debugPrint("exitStateN()")
+        assert self.__debugPrint("exitStateN()")
         if self.doLaterTask:
             taskMgr.remove(self.doLaterTask)
             self.doLaterTask=None
@@ -219,56 +219,56 @@ class FourStateAI:
     ##### state 0 #####
 
     def enterState0(self):
-        assert self.debugPrint("enter0()")
+        assert self.__debugPrint("enter0()")
         self.enterStateN(0, 0)
 
     def exitState0(self):
-        assert self.debugPrint("exit0()")
+        assert self.__debugPrint("exit0()")
 
     ##### state 1 #####
 
     def enterState1(self):
-        #assert self.debugPrint("enterState1()")
+        #assert self.__debugPrint("enterState1()")
         self.enterStateN(1, 2)
 
     def exitState1(self):
-        assert self.debugPrint("exitState1()")
+        assert self.__debugPrint("exitState1()")
         self.exitStateN()
 
     ##### state 2 #####
 
     def enterState2(self):
-        #assert self.debugPrint("enterState2()")
+        #assert self.__debugPrint("enterState2()")
         self.enterStateN(2, 3)
 
     def exitState2(self):
-        assert self.debugPrint("exitState2()")
+        assert self.__debugPrint("exitState2()")
         self.exitStateN()
 
     ##### state 3 #####
 
     def enterState3(self):
-        #assert self.debugPrint("enterState3()")
+        #assert self.__debugPrint("enterState3()")
         self.enterStateN(3, 4)
 
     def exitState3(self):
-        assert self.debugPrint("exitState3()")
+        assert self.__debugPrint("exitState3()")
         self.exitStateN()
 
     ##### state 4 #####
 
     def enterState4(self):
-        assert self.debugPrint("enterState4()")
+        assert self.__debugPrint("enterState4()")
         self.enterStateN(4, 1)
         self.changedOnState(1)
 
     def exitState4(self):
-        assert self.debugPrint("exitState4()")
+        assert self.__debugPrint("exitState4()")
         self.exitStateN()
         self.changedOnState(0)
 
     if __debug__:
-        def debugPrint(self, message):
+        def __debugPrint(self, message):
             """for debugging"""
             return self.notify.debug("%d (%d) %s"%(
                     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):
         assert self.notify.debugStateCall(self)
-        self.parent = parent
+        self._parent = parent
         if "command" in kw:
             self.nextCommand = kw.get("command")
             del kw["command"]
@@ -28,7 +28,7 @@ class DirectScrolledListItem(DirectButton):
             self.nextCommandExtraArgs = kw.get("extraArgs")
             del kw["extraArgs"]
         optiondefs = (
-            ('parent', self.parent,    None),
+            ('parent', self._parent,    None),
             ('command', self.select, None),
             )
         # Merge keyword options with default options
@@ -39,7 +39,7 @@ class DirectScrolledListItem(DirectButton):
     def select(self):
         assert self.notify.debugStateCall(self)
         self.nextCommand(*self.nextCommandExtraArgs)
-        self.parent.selectListItem(self)
+        self._parent.selectListItem(self)
 
 
 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:
             st = os.stat(pathname.toOsSpecific())
         self.size = st.st_size
-        self.timestamp = st.st_mtime
+        self.timestamp = int(st.st_mtime)
 
         self.readHash(pathname)
 
@@ -124,7 +124,7 @@ class FileSpec:
                 self.__correctHash(packageDir, pathname, st, notify)
             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
             # file passes.
             if notify:
@@ -198,7 +198,7 @@ class FileSpec:
         # 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
         # successfully next time.
-        if st.st_mtime != self.timestamp:
+        if int(st.st_mtime) != self.timestamp:
             self.__updateTimestamp(pathname, st)
 
         return True
@@ -219,7 +219,7 @@ class FileSpec:
         if notify:
             notify.info("Correcting timestamp of %s to %d (%s)" % (
                 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):
         """ 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):
             # 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:
                 raise Exception('Could not read egg file %s' % (file.filename))
 
@@ -1862,6 +1862,8 @@ class Packager:
             if not bamFile.openRead(file.filename):
                 raise Exception('Could not read bam file %s' % (file.filename))
 
+            bamFile.getReader().setLoaderOptions(self.packager.loaderOptions)
+
             if not bamFile.resolve():
                 raise Exception('Could not resolve bam file %s' % (file.filename))
 
@@ -2484,6 +2486,7 @@ class Packager:
             GlobPattern('libthr.so*'),
             GlobPattern('ld-linux.so*'),
             GlobPattern('ld-linux-*.so*'),
+            GlobPattern('librt.so*'),
             ]
 
         # A Loader for loading models.
@@ -2491,6 +2494,14 @@ class Packager:
         self.sfxManagerList = 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().
         self.packageList = []
 

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

@@ -77,9 +77,14 @@ class SeqValue:
         """ Compares to another seq 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):
         return bool(self.value)
 
     def __str__(self):
         return 'SeqValue%s' % (repr(self.value))
-

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

@@ -56,6 +56,9 @@ class panda3d(package):
            'direct.stdpy.*',
            'direct.task.*')
 
+    # Keep these modules for backward compatibility.
+    module('pandac.PandaModules', 'pandac.extension_native_helpers')
+
     module('panda3d.core',
            'panda3d.direct',
            'panda3d.fx',
@@ -63,8 +66,10 @@ class panda3d(package):
 
     # Include various standard Python encodings.  The rest is in morepy.
     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.
     import direct
@@ -241,7 +246,10 @@ class models(package):
     # we assume this is the models directory.
     pathname = getModelPath().findFile('cmss12.egg')
     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):
@@ -457,6 +465,8 @@ class packp3d(p3d):
 
     mainModule('direct.p3d.packp3d')
 
+    file('packp3d.prc', extract = True, text = "preload-textures false")
+
 
 class ppackage(p3d):
     # As above, a packaging utility.  This is the fully-general ppackage
@@ -470,6 +480,8 @@ class ppackage(p3d):
 
     mainModule('direct.p3d.ppackage')
 
+    file('ppackage.prc', extract = True, text = "preload-textures false")
+
 
 class ppatcher(p3d):
     # 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 "windowHandle.h"
 
-#include <Python.h>
-
 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());
   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;
 
@@ -3502,7 +3502,7 @@ paint_window_osx_cgcontext(CGContextRef context) {
   int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
 
   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);
   }
 }
@@ -3538,7 +3538,7 @@ handle_event_osx_event_record(const P3D_event_data &event) {
     // First, convert the coordinates from screen coordinates to browser
     // window coordinates.
     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,
                    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;
 }
 

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

@@ -267,7 +267,7 @@ refresh() {
     return;
   }
   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);
 
   } else {
@@ -345,7 +345,7 @@ paint_window_osx_cgcontext(CGContextRef context) {
   CGColorSpaceRef rgb_space = CGColorSpaceCreateDeviceRGB();
   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);
   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
     // window coordinates.
     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,
                    kHICoordSpaceWindow, window);
 
@@ -617,7 +617,7 @@ paint_progress_bar(CGContextRef context) {
   int 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).
   CGContextSetFillColorWithColor(context, bar_bg);
@@ -627,7 +627,7 @@ paint_progress_bar(CGContextRef context) {
   if (_progress_known) {
     int progress_width = (int)(bar_width * _install_progress + 0.5);
     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);
       CGContextFillRect(context, prog);
     }
@@ -642,7 +642,7 @@ paint_progress_bar(CGContextRef context) {
       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);
     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
     // line through the middle of a pixel, and it won't try to antialias
     // 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);
     CGContextSetLineWidth(context, 1);

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

@@ -217,6 +217,24 @@ run_python() {
     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.
   PyObject *result = PyObject_CallMethod(vfsimporter_module, (char *)"register", (char *)"");
   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.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.
         cards = []
         wins = []
@@ -290,7 +299,7 @@ class BufferViewer(DirectObject):
                         for face in range(6):
                             self.cardmaker.setUvRangeCube(face)
                             card = NodePath(self.cardmaker.generate())
-                            card.setTexture(tex)
+                            card.setTexture(tex, sampler)
                             cards.append(card)
                     elif (tex.getTextureType() == Texture.TT2dTextureArray):
                         for layer in range(tex.getZSize()):
@@ -301,11 +310,11 @@ class BufferViewer(DirectObject):
                             # the fixed-function pipeline, so we need to
                             # enable the shader generator to view them.
                             card.setShaderAuto()
-                            card.setTexture(tex)
+                            card.setTexture(tex, sampler)
                             cards.append(card)
                     else:
                         card = win.getTextureCard()
-                        card.setTexture(tex)
+                        card.setTexture(tex, sampler)
                         cards.append(card)
                     wins.append(win)
                     exclude[tex] = 1

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

@@ -106,10 +106,12 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath):
 
     def __repr__(self):
         outStr = 'DistancePhasedObject('
-        outStr += '%s' % repr(self.getName())
+        outStr += repr(self.getName())
         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 += ')'
         return outStr
 
@@ -287,10 +289,12 @@ class BufferedDistancePhasedNode(DistancePhasedNode):
 
     def __repr__(self):
         outStr = 'BufferedDistancePhasedNode('
-        outStr += '%s' % repr(self.getName())
+        outStr += repr(self.getName())
         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 += ')'
         return outStr
 

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

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

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

@@ -1,6 +1,6 @@
 # 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.Job import Job
 import gc, sys

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

@@ -28,7 +28,7 @@ class Loader(DirectObject):
             self.extraArgs = extraArgs
             self.numRemaining = numObjects
             self.cancelled = False
-            self.requests = {}
+            self.requests = set()
 
         def gotObject(self, index, object):
             self.objects[index] = object
@@ -45,6 +45,8 @@ class Loader(DirectObject):
         self.base = base
         self.loader = PandaLoader.getGlobalPtr()
 
+        self.__requests = {}
+
         self.hook = "async_loader_%s" % (Loader.loaderIndex)
         Loader.loaderIndex += 1
         self.accept(self.hook, self.__gotAsyncObject)
@@ -116,7 +118,7 @@ class Loader(DirectObject):
         """
 
         assert Loader.notify.debug("Loading model: %s" % (modelPath))
-        if loaderOptions == None:
+        if loaderOptions is None:
             loaderOptions = LoaderOptions()
         else:
             loaderOptions = LoaderOptions(loaderOptions)
@@ -156,7 +158,7 @@ class Loader(DirectObject):
             result = []
             for modelPath in modelList:
                 node = self.loader.loadSync(Filename(modelPath), loaderOptions)
-                if (node != None):
+                if node is not None:
                     nodePath = NodePath(node)
                 else:
                     nodePath = None
@@ -179,16 +181,16 @@ class Loader(DirectObject):
             # callback (passing it the models on the parameter list).
 
             cb = Loader.Callback(len(modelList), gotList, callback, extraArgs)
-            i=0
+            i = 0
             for modelPath in modelList:
                 request = self.loader.makeAsyncRequest(Filename(modelPath), loaderOptions)
                 if priority is not None:
                     request.setPriority(priority)
                 request.setDoneEvent(self.hook)
-                request.setPythonObject((cb, i))
-                i+=1
                 self.loader.loadAsync(request)
-                cb.requests[request] = True
+                cb.requests.add(request)
+                self.__requests[request] = (cb, i)
+                i += 1
             return cb
 
     def cancelRequest(self, cb):
@@ -200,6 +202,7 @@ class Loader(DirectObject):
             cb.cancelled = True
             for request in cb.requests:
                 self.loader.remove(request)
+                del self.__requests[request]
             cb.requests = None
 
     def isRequestPending(self, cb):
@@ -273,7 +276,7 @@ class Loader(DirectObject):
             # to resolve it for us.
             options = LoaderOptions(LoaderOptions.LFSearch | LoaderOptions.LFNoDiskCache | LoaderOptions.LFCacheOnly)
             modelNode = self.loader.loadSync(Filename(model), options)
-            if modelNode == None:
+            if modelNode is None:
                 # Model not found.
                 assert Loader.notify.debug("Unloading model not loaded: %s" % (model))
                 return
@@ -293,7 +296,7 @@ class Loader(DirectObject):
         a callback is used, the model is saved asynchronously, and the
         true/false status is passed to the callback function. """
 
-        if loaderOptions == None:
+        if loaderOptions is None:
             loaderOptions = LoaderOptions()
         else:
             loaderOptions = LoaderOptions(loaderOptions)
@@ -342,16 +345,16 @@ class Loader(DirectObject):
             # callback (passing it the models on the parameter list).
 
             cb = Loader.Callback(len(modelList), gotList, callback, extraArgs)
-            i=0
+            i = 0
             for modelPath, node in modelList:
                 request = self.loader.makeAsyncSaveRequest(Filename(modelPath), loaderOptions, node)
                 if priority is not None:
                     request.setPriority(priority)
                 request.setDoneEvent(self.hook)
-                request.setPythonObject((cb, i))
-                i+=1
                 self.loader.saveAsync(request)
-                cb.requests[request] = True
+                cb.requests.add(request)
+                self.__requests[request] = (cb, i)
+                i += 1
             return cb
 
 
@@ -496,7 +499,7 @@ class Loader(DirectObject):
             phaseChecker(modelPath, loaderOptions)
 
         font = FontPool.loadFont(modelPath)
-        if font == None:
+        if font is None:
             if not okMissing:
                 message = 'Could not load font file: %s' % (modelPath)
                 raise IOError(message)
@@ -506,21 +509,21 @@ class Loader(DirectObject):
 
         # The following properties may only be set for dynamic fonts.
         if hasattr(font, "setPointSize"):
-            if pointSize != None:
+            if pointSize is not None:
                 font.setPointSize(pointSize)
-            if pixelsPerUnit != None:
+            if pixelsPerUnit is not None:
                 font.setPixelsPerUnit(pixelsPerUnit)
-            if scaleFactor != None:
+            if scaleFactor is not None:
                 font.setScaleFactor(scaleFactor)
-            if textureMargin != None:
+            if textureMargin is not None:
                 font.setTextureMargin(textureMargin)
-            if polyMargin != None:
+            if polyMargin is not None:
                 font.setPolyMargin(polyMargin)
-            if minFilter != None:
+            if minFilter is not None:
                 font.setMinfilter(minFilter)
-            if magFilter != None:
+            if magFilter is not None:
                 font.setMagfilter(magFilter)
-            if anisotropicDegree != None:
+            if anisotropicDegree is not None:
                 font.setAnisotropicDegree(anisotropicDegree)
             if color:
                 font.setFg(color)
@@ -577,10 +580,10 @@ class Loader(DirectObject):
         the texture and the number of expected mipmap images.
 
         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
         already been loaded.  See egg-texture-cards for a more robust
         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
         also allowed if you need more than two views.
         """
-        if loaderOptions == None:
+        if loaderOptions is None:
             loaderOptions = LoaderOptions()
         else:
             loaderOptions = LoaderOptions(loaderOptions)
@@ -657,7 +660,7 @@ class Loader(DirectObject):
         numbered 8 - 15 will be part of the right eye view.
         """
         assert Loader.notify.debug("Loading 3-D texture: %s" % (texturePattern))
-        if loaderOptions == None:
+        if loaderOptions is None:
             loaderOptions = LoaderOptions()
         else:
             loaderOptions = LoaderOptions(loaderOptions)
@@ -684,6 +687,63 @@ class Loader(DirectObject):
 
         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,
                     minfilter = None, magfilter = None, anisotropicDegree = None,
                     loaderOptions = None, multiview = None):
@@ -711,7 +771,7 @@ class Loader(DirectObject):
         and each six images will define a new view.
         """
         assert Loader.notify.debug("Loading cube map: %s" % (texturePattern))
-        if loaderOptions == None:
+        if loaderOptions is None:
             loaderOptions = LoaderOptions()
         else:
             loaderOptions = LoaderOptions(loaderOptions)
@@ -821,13 +881,12 @@ class Loader(DirectObject):
             # callback (passing it the sounds on the parameter list).
 
             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.setDoneEvent(self.hook)
-                request.setPythonObject((cb, i))
                 self.loader.loadAsync(request)
-                cb.requests[request] = True
+                cb.requests.add(request)
+                self.__requests[request] = (cb, i)
             return cb
 
     def unloadSfx(self, sfx):
@@ -852,7 +911,7 @@ class Loader(DirectObject):
         return shader
 
     def unloadShader(self, shaderPath):
-        if (shaderPath != None):
+        if shaderPath is not None:
             ShaderPool.releaseShader(shaderPath)
 
     def asyncFlattenStrong(self, model, inPlace = True,
@@ -886,14 +945,14 @@ class Loader(DirectObject):
             gotList = True
 
         cb = Loader.Callback(len(modelList), gotList, callback, extraArgs)
-        i=0
+        i = 0
         for model in modelList:
             request = ModelFlattenRequest(model.node())
             request.setDoneEvent(self.hook)
-            request.setPythonObject((cb, i))
-            i+=1
             self.loader.loadAsync(request)
-            cb.requests[request] = True
+            cb.requests.add(request)
+            self.__requests[request] = (cb, i)
+            i += 1
         return cb
 
     def __asyncFlattenDone(self, models,
@@ -907,7 +966,7 @@ class Loader(DirectObject):
             orig = origModelList[i].node()
             flat = models[i].node()
             orig.copyAllProperties(flat)
-            orig.replaceNode(flat)
+            flat.replaceNode(orig)
 
         if callback:
             if gotList:
@@ -921,16 +980,23 @@ class Loader(DirectObject):
         of loaded objects, and call the appropriate callback when it's
         time."""
 
-        cb, i = request.getPythonObject()
+        if request not in self.__requests:
+            return
+
+        cb, i = self.__requests[request]
         if cb.cancelled:
+            # Shouldn't be here.
+            del self.__requests[request]
             return
 
-        del cb.requests[request]
+        cb.requests.discard(request)
+        if not cb.requests:
+            del self.__requests[request]
 
         object = None
         if hasattr(request, "getModel"):
             node = request.getModel()
-            if (node != None):
+            if node is not None:
                 object = NodePath(node)
 
         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
 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
 
 def setupMirror(name, width, height, rootCamera = None):

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

@@ -38,7 +38,6 @@ import os
 import sys
 import random
 import time
-import importlib
 
 __report_indent = 3
 
@@ -61,6 +60,42 @@ def Functor(function, *args, **kArgs):
     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:
     def __init__(self, function, *args, **kargs):
         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.
 """
 
-from pandac.PandaModules import *
+from panda3d.core import *
 from direct.task import Task
 
 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.directnotify import DirectNotifyGlobal
-from pandac.PandaModules import *
+from panda3d.core import *
 from . import 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.
         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
         # whenever we resume from a pause.  This callback function is
         # 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
         ## set or base.startWx() is called.
         self.wxApp = None
+        self.wxAppCreated = False
         self.tkRoot = None
+        self.tkRootCreated = False
 
         # This is used for syncing multiple PCs in a distributed cluster
         try:
@@ -259,6 +257,17 @@ class ShowBase(DirectObject.DirectObject):
             random.seed(seed)
             #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.
         if self.windowType != 'none':
             props = WindowProperties.getDefault()
@@ -2821,7 +2830,7 @@ class ShowBase(DirectObject.DirectObject):
         updated, but wxPython owns the main loop (which seems to make
         it happier than the other way around). """
 
-        if self.wxApp:
+        if self.wxAppCreated:
             # Don't do this twice.
             return
 
@@ -2831,8 +2840,9 @@ class ShowBase(DirectObject.DirectObject):
         # by modulefinder when packaging an application.
         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):
             # Put wxPython in charge of the main loop.  It really
@@ -2867,6 +2877,7 @@ class ShowBase(DirectObject.DirectObject):
                 return task.again
 
             self.taskMgr.add(wxLoop, 'wxLoop')
+        self.wxAppCreated = True
 
     def __wxTimerCallback(self, event):
         if Thread.getCurrentThread().getCurrentTask():
@@ -2901,7 +2912,7 @@ class ShowBase(DirectObject.DirectObject):
         updated, but Tkinter owns the main loop (which seems to make
         it happier than the other way around). """
 
-        if self.tkRoot:
+        if self.tkRootCreated:
             # Don't do this twice.
             return
 
@@ -2911,7 +2922,8 @@ class ShowBase(DirectObject.DirectObject):
         Pmw = importlib.import_module('Pmw')
 
         # Create a new Tk root.
-        self.tkRoot = Pmw.initialise()
+        if not self.tkRoot:
+            self.tkRoot = Pmw.initialise()
         builtins.tkroot = self.tkRoot
 
         init_app_for_gui()
@@ -2947,6 +2959,7 @@ class ShowBase(DirectObject.DirectObject):
                 return task.again
 
             self.taskMgr.add(tkLoop, 'tkLoop')
+        self.tkRootCreated = True
 
     def __tkTimerCallback(self):
         if not Thread.getCurrentThread().getCurrentTask():

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

@@ -2,6 +2,7 @@ __all__ = ['register', 'sharedPackages',
            'reloadSharedPackage', 'reloadSharedPackages']
 
 from panda3d.core import Filename, VirtualFileSystem, VirtualFileMountSystem, OFileStream, copyStream
+from direct.stdpy.file import open
 import sys
 import marshal
 import imp
@@ -173,10 +174,7 @@ class VFSLoader:
         filename = Filename(self.filename)
         filename.setExtension('py')
         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):
         """ 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:
                 self.__loadModule(mdef)
             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
         # these fail to import, we don't really care.
@@ -1190,7 +1193,7 @@ class Freezer:
 
             if self.storePythonSource:
                 filename += '.py'
-                stream = StringStream('')
+                stream = StringStream(b'')
                 if multifile.findSubfile(filename) < 0:
                     multifile.addSubfile(filename, stream, 0)
                     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)
 
         thread = core.PythonThread(threadFunc, [threadId], name, name)
-        thread.setPythonData(threadId)
+        thread.setPythonIndex(threadId)
         _threads[threadId] = (thread, {}, None)
 
         thread.start(core.TPNormal, False)
@@ -121,7 +121,7 @@ def _add_thread(thread, wrapper):
         threadId = _nextThreadId
         _nextThreadId += 1
 
-        thread.setPythonData(threadId)
+        thread.setPythonIndex(threadId)
         _threads[threadId] = (thread, {}, wrapper)
         return threadId
 
@@ -133,8 +133,8 @@ def _get_thread_wrapper(thread, wrapperClass):
     is not one, creates an instance of the indicated wrapperClass
     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.
 
         global _nextThreadId
@@ -143,7 +143,7 @@ def _get_thread_wrapper(thread, wrapperClass):
             threadId = _nextThreadId
             _nextThreadId += 1
 
-            thread.setPythonData(threadId)
+            thread.setPythonIndex(threadId)
             wrapper = wrapperClass(thread, threadId)
             _threads[threadId] = (thread, {}, wrapper)
             return wrapper
@@ -169,8 +169,8 @@ def _get_thread_locals(thread, i):
     """ Returns the locals dictionary for the indicated thread.  If
     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.
 
         global _nextThreadId
@@ -179,7 +179,7 @@ def _get_thread_locals(thread, i):
             threadId = _nextThreadId
             _nextThreadId += 1
 
-            thread.setPythonData(threadId)
+            thread.setPythonIndex(threadId)
             locals = {}
             _threads[threadId] = (thread, locals, None)
             return locals.setdefault(i, {})
@@ -205,9 +205,9 @@ def _remove_thread_id(threadId):
     _threadsLock.acquire()
     try:
         thread, locals, wrapper = _threads[threadId]
-        assert thread.getPythonData() == threadId
+        assert thread.getPythonIndex() == threadId
         del _threads[threadId]
-        thread.setPythonData(None)
+        thread.setPythonIndex(-1)
 
     finally:
         _threadsLock.release()

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

@@ -102,7 +102,10 @@ Task.DtoolClassDict['loop'] = staticmethod(loop)
 class 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
 
     def __init__(self):
@@ -397,7 +400,6 @@ class TaskManager:
                 'Task %s does not accept arguments.' % (repr(task)))
 
         if name is not None:
-            assert isinstance(name, str), 'Name must be a string type'
             task.setName(name)
         assert task.hasName()
 
@@ -431,16 +433,14 @@ class TaskManager:
         all tasks with the indicated name are removed.  Returns the
         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)
         elif isinstance(taskOrName, list):
             for task in taskOrName:
                 self.remove(task)
         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):
         """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,
             scrolledCanvas_hull_width = 250,
             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
         notebook = Pmw.NoteBook(notebookFrame)

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

@@ -1976,9 +1976,9 @@ class ParticlePanel(AppShell):
         self.particles.renderer.setAlphaDisable(
             self.getVariable('Sprite Renderer', 'Alpha Disable').get())
     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']):
             self.getWidget(rendererName,'Incoming Op.').pack(fill = X)

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

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

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません