Browse Source

Merge branch 'master' into input-overhaul

rdb 7 years ago
parent
commit
70bfe21a63
91 changed files with 1614 additions and 1981 deletions
  1. 4 2
      .travis.yml
  2. 0 9
      direct/src/configfiles/direct.init
  3. 1 2
      direct/src/distributed/DistributedSmoothNode.py
  4. 25 0
      direct/src/showbase/DConfig.py
  5. 4 3
      direct/src/showbase/ShowBase.py
  6. 1 2
      direct/src/showbase/ShowBaseGlobal.py
  7. 0 8
      direct/src/showbase/showBase.cxx
  8. 0 1
      direct/src/showbase/showBase.h
  9. 0 21
      dtool/src/dconfig/config_dconfig.cxx
  10. 0 29
      dtool/src/dconfig/config_dconfig.h
  11. 0 42
      dtool/src/dconfig/dconfig.I
  12. 0 14
      dtool/src/dconfig/dconfig.cxx
  13. 1 26
      dtool/src/dconfig/dconfig.h
  14. 0 3
      dtool/src/dconfig/p3dconfig_composite1.cxx
  15. 0 35
      dtool/src/dconfig/test_config.cxx
  16. 0 87
      dtool/src/dconfig/test_expand.cxx
  17. 0 32
      dtool/src/dconfig/test_pfstream.cxx
  18. 0 48
      dtool/src/dconfig/test_searchpath.cxx
  19. 0 2
      dtool/src/dtoolbase/dtoolbase.h
  20. 15 0
      dtool/src/dtoolbase/typeHandle.cxx
  21. 4 0
      dtool/src/dtoolbase/typeHandle.h
  22. 2 1
      dtool/src/dtoolbase/typeHandle_ext.cxx
  23. 18 0
      dtool/src/dtoolbase/typeRegistry.cxx
  24. 3 0
      dtool/src/dtoolbase/typeRegistry.h
  25. 13 0
      dtool/src/dtoolbase/typeRegistryNode.I
  26. 23 0
      dtool/src/dtoolbase/typeRegistryNode.cxx
  27. 5 0
      dtool/src/dtoolbase/typeRegistryNode.h
  28. 75 41
      dtool/src/interrogate/interfaceMakerPythonNative.cxx
  29. 0 3
      dtool/src/interrogate/interrogate.cxx
  30. 9 14
      dtool/src/interrogate/interrogate_module.cxx
  31. 0 3
      dtool/src/interrogate/parse_file.cxx
  32. 103 91
      dtool/src/interrogatedb/dtool_super_base.cxx
  33. 0 1
      dtool/src/interrogatedb/p3interrogatedb_composite1.cxx
  34. 0 3
      dtool/src/interrogatedb/p3interrogatedb_composite2.cxx
  35. 0 7
      dtool/src/interrogatedb/py_compat.cxx
  36. 1 8
      dtool/src/interrogatedb/py_compat.h
  37. 17 12
      dtool/src/interrogatedb/py_panda.I
  38. 48 174
      dtool/src/interrogatedb/py_panda.cxx
  39. 42 53
      dtool/src/interrogatedb/py_panda.h
  40. 299 674
      dtool/src/interrogatedb/py_wrappers.cxx
  41. 6 23
      dtool/src/interrogatedb/py_wrappers.h
  42. 4 0
      dtool/src/parser-inc/vrpn_Analog.h
  43. 4 0
      dtool/src/parser-inc/vrpn_Button.h
  44. 3 0
      dtool/src/parser-inc/vrpn_Configure.h
  45. 3 0
      dtool/src/parser-inc/vrpn_Connection.h
  46. 4 0
      dtool/src/parser-inc/vrpn_Dial.h
  47. 6 0
      dtool/src/parser-inc/vrpn_Tracker.h
  48. 8 0
      dtool/src/pystub/pystub.cxx
  49. 0 3
      dtool/src/test_interrogate/test_interrogate.cxx
  50. 16 7
      makepanda/installer.nsi
  51. 6 1
      makepanda/installpanda.py
  52. 222 262
      makepanda/makepanda.py
  53. 128 9
      makepanda/makepandacore.py
  54. 1 1
      makepanda/makewheel.py
  55. 1 1
      panda/src/audiotraits/fmodAudioSound.cxx
  56. 1 1
      panda/src/audiotraits/fmodAudioSound.h
  57. 9 4
      panda/src/collide/collisionHandlerQueue.cxx
  58. 0 10
      panda/src/configfiles/panda.init
  59. 0 1
      panda/src/dxgsg9/dxgsg9base.h
  60. 8 26
      panda/src/dxgsg9/wdxGraphicsPipe9.cxx
  61. 0 1
      panda/src/dxgsg9/wdxGraphicsPipe9.h
  62. 1 2
      panda/src/dxgsg9/wdxGraphicsWindow9.cxx
  63. 1 8
      panda/src/event/asyncFuture_ext.cxx
  64. 1 1
      panda/src/event/asyncFuture_ext.h
  65. 0 8
      panda/src/express/config_express.cxx
  66. 0 5
      panda/src/express/config_express.h
  67. 2 0
      panda/src/express/virtualFileSystem.cxx
  68. 72 0
      panda/src/glstuff/glShaderContext_src.cxx
  69. 1 5
      panda/src/gobj/internalName.h
  70. 12 2
      panda/src/gobj/internalName_ext.cxx
  71. 1 5
      panda/src/gobj/internalName_ext.h
  72. 285 94
      panda/src/gobj/shader.cxx
  73. 10 3
      panda/src/gobj/shader.h
  74. 1 3
      panda/src/ode/odeBody.I
  75. 4 23
      panda/src/ode/odeBody.cxx
  76. 8 7
      panda/src/ode/odeBody.h
  77. 13 0
      panda/src/ode/odeBody_ext.I
  78. 37 0
      panda/src/ode/odeBody_ext.cxx
  79. 3 0
      panda/src/ode/odeBody_ext.h
  80. 1 0
      panda/src/ode/p3ode_ext_composite.cxx
  81. 1 0
      panda/src/pgraph/config_pgraph.h
  82. 1 0
      panda/src/physx/config_physx.h
  83. 1 1
      panda/src/pipeline/cycleData.h
  84. 2 0
      panda/src/putil/config_putil.h
  85. 6 1
      panda/src/vision/webcamVideoCursorOpenCV.cxx
  86. 1 0
      panda/src/vision/webcamVideoCursorOpenCV.h
  87. 5 0
      panda/src/vision/webcamVideoCursorV4L.cxx
  88. 0 10
      panda/src/vrpn/vrpn_interface.h
  89. 1 0
      panda/src/windisplay/winDetectDx9.cxx
  90. 0 1
      pandatool/src/configfiles/pandatool.init
  91. 0 1
      pandatool/src/progbase/programBase.cxx

+ 4 - 2
.travis.yml

@@ -11,6 +11,8 @@ matrix:
       before_install:
       before_install:
         - export CC=gcc-4.7
         - export CC=gcc-4.7
         - export CXX=g++-4.7
         - export CXX=g++-4.7
+    - compiler: clang
+      env: PYTHONV=python3 FLAGS=--no-python SKIP_TESTS=1
 addons:
 addons:
   apt:
   apt:
     sources:
     sources:
@@ -42,8 +44,8 @@ install:
     - $PYTHONV -m pip install pytest
     - $PYTHONV -m pip install pytest
 script:
 script:
     - $PYTHONV makepanda/makepanda.py --everything --git-commit $TRAVIS_COMMIT $FLAGS --threads 4
     - $PYTHONV makepanda/makepanda.py --everything --git-commit $TRAVIS_COMMIT $FLAGS --threads 4
-    - LD_LIBRARY_PATH=built/lib PYTHONPATH=built $PYTHONV makepanda/test_imports.py
-    - LD_LIBRARY_PATH=built/lib PYTHONPATH=built $PYTHONV -m pytest -v tests
+    - test -n "$SKIP_TESTS" || LD_LIBRARY_PATH=built/lib PYTHONPATH=built $PYTHONV makepanda/test_imports.py
+    - test -n "$SKIP_TESTS" || LD_LIBRARY_PATH=built/lib PYTHONPATH=built $PYTHONV -m pytest -v tests
 notifications:
 notifications:
   irc:
   irc:
     channels:
     channels:

+ 0 - 9
direct/src/configfiles/direct.init

@@ -1,9 +0,0 @@
-ATTACH dmodels
-ATTACH panda
-MODREL ETC_PATH etc
-DOCSH set parent=`dirname $DIRECT`
-DOCSH if ( ${?PANDA_ROOT} ) then
-DOCSH   setenv PYTHONPATH "${PYTHONPATH};"`cygpath -w "$parent"`
-DOCSH else
-DOCSH   setenv PYTHONPATH "${PYTHONPATH}:$parent"
-DOCSH endif

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

@@ -6,8 +6,7 @@ from .ClockDelta import *
 from . import DistributedNode
 from . import DistributedNode
 from . import DistributedSmoothNodeBase
 from . import DistributedSmoothNodeBase
 from direct.task.Task import cont
 from direct.task.Task import cont
-
-config = get_config_showbase()
+from direct.showbase import DConfig as config
 
 
 # This number defines our tolerance for out-of-sync telemetry packets.
 # This number defines our tolerance for out-of-sync telemetry packets.
 # If a packet appears to have originated from more than MaxFuture
 # If a packet appears to have originated from more than MaxFuture

+ 25 - 0
direct/src/showbase/DConfig.py

@@ -0,0 +1,25 @@
+"This module contains a deprecated shim emulating the old DConfig API."
+
+__all__ = []
+
+from panda3d.core import (ConfigFlags, ConfigVariableBool, ConfigVariableInt,
+                          ConfigVariableDouble, ConfigVariableString)
+
+
+def GetBool(sym, default=False):
+    return ConfigVariableBool(sym, default, "DConfig", ConfigFlags.F_dconfig).value
+
+
+def GetInt(sym, default=0):
+    return ConfigVariableInt(sym, default, "DConfig", ConfigFlags.F_dconfig).value
+
+
+def GetDouble(sym, default=0.0):
+    return ConfigVariableDouble(sym, default, "DConfig", ConfigFlags.F_dconfig).value
+
+
+def GetString(sym, default=""):
+    return ConfigVariableString(sym, default, "DConfig", ConfigFlags.F_dconfig).value
+
+
+GetFloat = GetDouble

+ 4 - 3
direct/src/showbase/ShowBase.py

@@ -10,8 +10,9 @@ __all__ = ['ShowBase', 'WindowControls']
 #import VerboseImport
 #import VerboseImport
 
 
 from panda3d.core import *
 from panda3d.core import *
-from panda3d.direct import get_config_showbase, throw_new_frame, init_app_for_gui
+from panda3d.direct import throw_new_frame, init_app_for_gui
 from panda3d.direct import storeAccessibilityShortcutKeys, allowAccessibilityShortcutKeys
 from panda3d.direct import storeAccessibilityShortcutKeys, allowAccessibilityShortcutKeys
+from . import DConfig
 
 
 # Register the extension methods for NodePath.
 # Register the extension methods for NodePath.
 from direct.extensions_native import NodePath_extensions
 from direct.extensions_native import NodePath_extensions
@@ -22,7 +23,7 @@ if sys.version_info >= (3, 0):
     import builtins
     import builtins
 else:
 else:
     import __builtin__ as builtins
     import __builtin__ as builtins
-builtins.config = get_config_showbase()
+builtins.config = DConfig
 
 
 from direct.directnotify.DirectNotifyGlobal import directNotify, giveNotify
 from direct.directnotify.DirectNotifyGlobal import directNotify, giveNotify
 from .MessengerGlobal import messenger
 from .MessengerGlobal import messenger
@@ -57,7 +58,7 @@ def exitfunc():
 # *seem* to cause anyone any problems.
 # *seem* to cause anyone any problems.
 class ShowBase(DirectObject.DirectObject):
 class ShowBase(DirectObject.DirectObject):
 
 
-    config = get_config_showbase()
+    config = DConfig
     notify = directNotify.newCategory("ShowBase")
     notify = directNotify.newCategory("ShowBase")
 
 
     def __init__(self, fStartDirect = True, windowType = None):
     def __init__(self, fStartDirect = True, windowType = None):

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

@@ -12,9 +12,8 @@ from direct.directnotify.DirectNotifyGlobal import directNotify, giveNotify
 from panda3d.core import VirtualFileSystem, Notify, ClockObject, PandaSystem
 from panda3d.core import VirtualFileSystem, Notify, ClockObject, PandaSystem
 from panda3d.core import ConfigPageManager, ConfigVariableManager
 from panda3d.core import ConfigPageManager, ConfigVariableManager
 from panda3d.core import NodePath, PGTop
 from panda3d.core import NodePath, PGTop
-from panda3d.direct import get_config_showbase
+from . import DConfig as config
 
 
-config = get_config_showbase()
 __dev__ = config.GetBool('want-dev', __debug__)
 __dev__ = config.GetBool('want-dev', __debug__)
 
 
 vfs = VirtualFileSystem.getGlobalPtr()
 vfs = VirtualFileSystem.getGlobalPtr()

+ 0 - 8
direct/src/showbase/showBase.cxx

@@ -61,14 +61,6 @@ throw_new_frame() {
   throw_event("NewFrame");
   throw_event("NewFrame");
 }
 }
 
 
-// Returns the configure object for accessing config variables from a
-// scripting language.
-DConfig &
-get_config_showbase() {
-  static DConfig config_showbase;
-  return config_showbase;
-}
-
 // Initialize the application for making a Gui-based app, such as wx.  At the
 // Initialize the application for making a Gui-based app, such as wx.  At the
 // moment, this is a no-op except on Mac.
 // moment, this is a no-op except on Mac.
 void
 void

+ 0 - 1
direct/src/showbase/showBase.h

@@ -38,7 +38,6 @@ EXPCL_DIRECT_SHOWBASE ConfigVariableSearchPath &get_particle_path();
 
 
 EXPCL_DIRECT_SHOWBASE void throw_new_frame();
 EXPCL_DIRECT_SHOWBASE void throw_new_frame();
 
 
-EXPCL_DIRECT_SHOWBASE DConfig &get_config_showbase();
 EXPCL_DIRECT_SHOWBASE void init_app_for_gui();
 EXPCL_DIRECT_SHOWBASE void init_app_for_gui();
 
 
 // klunky interface since we cant pass array from python->C++
 // klunky interface since we cant pass array from python->C++

+ 0 - 21
dtool/src/dconfig/config_dconfig.cxx

@@ -1,21 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file config_dconfig.cxx
- * @author drose
- * @date 2000-05-15
- */
-
-#include "config_dconfig.h"
-
-#if !defined(CPPPARSER) && !defined(LINK_ALL_STATIC) && !defined(BUILDING_DTOOL_DCONFIG)
-  #error Buildsystem error: BUILDING_DTOOL_DCONFIG not defined
-#endif
-
-NotifyCategoryDef(dconfig, "");
-NotifyCategoryDef(microconfig, "dconfig");

+ 0 - 29
dtool/src/dconfig/config_dconfig.h

@@ -1,29 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file config_dconfig.h
- * @author drose
- * @date 2000-05-15
- */
-
-#ifndef CONFIG_DCONFIG_H
-#define CONFIG_DCONFIG_H
-
-#ifdef WIN32_VC
-/* C4231: extern before template instantiation */
-/* MPG - For some reason, this one only works if it's here */
-#pragma warning (disable : 4231)
-#endif
-
-#include "dtoolbase.h"
-#include "notifyCategoryProxy.h"
-
-NotifyCategoryDecl(dconfig, EXPCL_DTOOL_DCONFIG, EXPTP_DTOOL_DCONFIG);
-NotifyCategoryDecl(microconfig, EXPCL_DTOOL_DCONFIG, EXPTP_DTOOL_DCONFIG);
-
-#endif

+ 0 - 42
dtool/src/dconfig/dconfig.I

@@ -1,42 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file dconfig.I
- * @author cary
- * @date 2000-03-20
- */
-
-bool DConfig::
-GetBool(const std::string &sym, bool def) {
-  ConfigVariableBool var(sym, def, "DConfig", ConfigFlags::F_dconfig);
-  return var.get_value();
-}
-
-int DConfig::
-GetInt(const std::string &sym, int def) {
-  ConfigVariableInt var(sym, def, "DConfig", ConfigFlags::F_dconfig);
-  return var.get_value();
-}
-
-float DConfig::
-GetFloat(const std::string &sym, float def) {
-  ConfigVariableDouble var(sym, (double)def, "DConfig", ConfigFlags::F_dconfig);
-  return (float)var.get_value();
-}
-
-double DConfig::
-GetDouble(const std::string &sym, double def) {
-  ConfigVariableDouble var(sym, def, "DConfig", ConfigFlags::F_dconfig);
-  return var.get_value();
-}
-
-std::string DConfig::
-GetString(const std::string &sym, const std::string &def) {
-  ConfigVariableString var(sym, def, "DConfig", ConfigFlags::F_dconfig);
-  return var.get_value();
-}

+ 0 - 14
dtool/src/dconfig/dconfig.cxx

@@ -1,14 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file dconfig.cxx
- * @author drose
- * @date 1999-02-08
- */
-
-#include "dconfig.h"

+ 1 - 26
dtool/src/dconfig/dconfig.h

@@ -15,32 +15,7 @@
 #define DCONFIG_H
 #define DCONFIG_H
 
 
 #include "dtoolbase.h"
 #include "dtoolbase.h"
-
-#include "config_dconfig.h"
-#include "configVariableString.h"
-#include "configVariableBool.h"
-#include "configVariableInt.h"
-#include "configVariableDouble.h"
-#include "configVariableList.h"
-#include "configFlags.h"
-
-/**
- * This class emulates the old dconfig-style interface to our Panda config
- * system.  It exists only to provide backward-compatible support, and it is
- * used primarily by Python code.  For modern code, use the new
- * ConfigVariable* interface instead of this deprecated interface.
- */
-class EXPCL_DTOOL_DCONFIG DConfig {
-PUBLISHED:
-  static INLINE bool GetBool(const std::string &sym, bool def = false);
-  static INLINE int GetInt(const std::string &sym, int def = 0);
-  static INLINE float GetFloat(const std::string &sym, float def = 0.);
-  static INLINE double GetDouble(const std::string &sym, double def = 0.);
-  static INLINE std::string GetString(const std::string &sym, const std::string &def = "");
-};
-
-#include "dconfig.I"
-
+#include "notifyCategoryProxy.h"
 
 
 // These macros are used in each directory to call an initialization function
 // These macros are used in each directory to call an initialization function
 // at static-init time.  These macros may eventually be phased out in favor of
 // at static-init time.  These macros may eventually be phased out in favor of

+ 0 - 3
dtool/src/dconfig/p3dconfig_composite1.cxx

@@ -1,3 +0,0 @@
-
-#include "config_dconfig.cxx"
-#include "dconfig.cxx"

+ 0 - 35
dtool/src/dconfig/test_config.cxx

@@ -1,35 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file test_config.cxx
- * @author cary
- * @date 1998-09-10
- */
-
-#include "dconfig.h"
-
-using std::cout;
-using std::endl;
-
-#define SNARF
-Configure(test);
-
-std::string foo = test.GetString("user");
-std::string path = test.GetString("LD_LIBRARY_PATH");
-
-ConfigureFn(test)
-{
-   cout << "AIEE!  Doing work before main()!  The sky is falling!" << endl;
-}
-
-main()
-{
-   cout << "Testing Configuration functionality:" << endl;
-   cout << "foo = " << foo << endl;
-   cout << "path = " << path << endl;
-}

+ 0 - 87
dtool/src/dconfig/test_expand.cxx

@@ -1,87 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file test_expand.cxx
- * @author cary
- * @date 1998-08-31
- */
-
-#include "expand.h"
-#include <string>
-
-using std::cout;
-using std::endl;
-
-void TestExpandFunction()
-{
-   std::string line;
-
-   line = "foo";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << Expand::Expand(line) << "'" << endl;
-   line = "'foo'";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << Expand::Expand(line) << "'" << endl;
-   line = "'$USER'";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << Expand::Expand(line) << "'" << endl;
-   line = "$USER";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << Expand::Expand(line) << "'" << endl;
-   line = "\"$USER\"";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << Expand::Expand(line) << "'" << endl;
-   line = "`ls -l`";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << Expand::Expand(line) << "'" << endl;
-   line = "~";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << Expand::Expand(line) << "'" << endl;
-   line = "~cary";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << Expand::Expand(line) << "'" << endl;
-}
-
-void TestExpandClass()
-{
-   std::string line;
-
-   line = "foo";
-   Expand::Expander ex(line);
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << ex() << "'" << endl;
-   line = "'foo'";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << ex(line) << "'" << endl;
-   line = "'$USER'";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << ex(line) << "'" << endl;
-   line = "$USER";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << ex(line) << "'" << endl;
-   line = "\"$USER\"";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << ex(line) << "'" << endl;
-   line = "`ls -l`";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << ex(line) << "'" << endl;
-   line = "~";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << ex(line) << "'" << endl;
-   line = "~cary";
-   cout << "input: '" << line << "'" << endl;
-   cout << "output: '" << ex(line) << "'" << endl;
-}
-
-main()
-{
-   cout << endl << "Testing shell expansion (function version):" << endl;
-   TestExpandFunction();
-   cout << endl << "Testing shell expansion (class version):" << endl;
-   TestExpandClass();
-}

+ 0 - 32
dtool/src/dconfig/test_pfstream.cxx

@@ -1,32 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file test_pfstream.cxx
- * @author cary
- * @date 1998-08-31
- */
-
-#include "pfstream.h"
-#include <string>
-
-void ReadIt(std::istream& ifs) {
-   std::string line;
-
-   while (!ifs.eof()) {
-      std::getline(ifs, line);
-      if (line.length() != 0)
-         std::cout << line << std::endl;
-   }
-}
-
-main()
-{
-   IPipeStream ipfs("ls -l");
-
-   ReadIt(ipfs);
-}

+ 0 - 48
dtool/src/dconfig/test_searchpath.cxx

@@ -1,48 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file test_searchpath.cxx
- * @author cary
- * @date 1998-09-01
- */
-
-#include "dSearchPath.h"
-// #include "expand.h"
-#include <string>
-
-using std::cout;
-using std::endl;
-
-void TestSearch()
-{
-   std::string line, path;
-
-// path = ".:~ etc";
-   path = ". /etc";
-// path = Expand::Expand(path);
-   line = "searchpath.h";
-   cout << "looking for file '" << line << "' in path '" << path << "': '";
-   line = DSearchPath::search_path(line, path);
-   cout << line << "'" << endl;
-
-   line = ".cshrc";
-   cout << "looking for file '" << line << "' in path '" << path << "': '";
-   line = DSearchPath::search_path(line, path);
-   cout << line << "'" << endl;
-
-   line = "passwd";
-   cout << "looking for file '" << line << "' in path '" << path << "': '";
-   line = DSearchPath::search_path(line, path);
-   cout << line << "'" << endl;
-}
-
-main()
-{
-   cout << "Testing search path:" << endl;
-   TestSearch();
-}

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

@@ -138,12 +138,10 @@
 #endif
 #endif
 #endif
 #endif
 
 
-#ifdef HAVE_PYTHON
 // Instead of including the Python headers, which will implicitly add a linker
 // Instead of including the Python headers, which will implicitly add a linker
 // flag to link in Python, we'll just excerpt the forward declaration of
 // flag to link in Python, we'll just excerpt the forward declaration of
 // PyObject.
 // PyObject.
 typedef struct _object PyObject;
 typedef struct _object PyObject;
-#endif
 
 
 #ifndef HAVE_EIGEN
 #ifndef HAVE_EIGEN
 // If we don't have the Eigen library, don't define LINMATH_ALIGN.
 // If we don't have the Eigen library, don't define LINMATH_ALIGN.

+ 15 - 0
dtool/src/dtoolbase/typeHandle.cxx

@@ -153,6 +153,21 @@ deallocate_array(void *ptr) {
   PANDA_FREE_ARRAY(ptr);
   PANDA_FREE_ARRAY(ptr);
 }
 }
 
 
+#ifdef HAVE_PYTHON
+/**
+ * Returns the internal void pointer that is stored for interrogate's benefit.
+ */
+PyObject *TypeHandle::
+get_python_type() const {
+  TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, nullptr);
+  if (rnode != nullptr) {
+    return rnode->get_python_type();
+  } else {
+    return nullptr;
+  }
+}
+#endif
+
 /**
 /**
  * Return the Index of the BEst fit Classs from a set
  * Return the Index of the BEst fit Classs from a set
  */
  */

+ 4 - 0
dtool/src/dtoolbase/typeHandle.h

@@ -138,6 +138,10 @@ PUBLISHED:
   MAKE_SEQ_PROPERTY(child_classes, get_num_child_classes, get_child_class);
   MAKE_SEQ_PROPERTY(child_classes, get_num_child_classes, get_child_class);
 
 
 public:
 public:
+#ifdef HAVE_PYTHON
+  PyObject *get_python_type() const;
+#endif
+
   void *allocate_array(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
   void *allocate_array(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
   void *reallocate_array(void *ptr, size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
   void *reallocate_array(void *ptr, size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
   void deallocate_array(void *ptr);
   void deallocate_array(void *ptr);

+ 2 - 1
dtool/src/dtoolbase/typeHandle_ext.cxx

@@ -22,7 +22,8 @@
  */
  */
 TypeHandle Extension<TypeHandle>::
 TypeHandle Extension<TypeHandle>::
 make(PyTypeObject *tp) {
 make(PyTypeObject *tp) {
-  if (!PyType_IsSubtype(tp, &Dtool_DTOOL_SUPER_BASE._PyType)) {
+  Dtool_PyTypedObject *super_base = Dtool_GetSuperBase();
+  if (!PyType_IsSubtype(tp, (PyTypeObject *)super_base)) {
     PyErr_SetString(PyExc_TypeError, "a Panda type is required");
     PyErr_SetString(PyExc_TypeError, "a Panda type is required");
     return TypeHandle::none();
     return TypeHandle::none();
   }
   }

+ 18 - 0
dtool/src/dtoolbase/typeRegistry.cxx

@@ -207,6 +207,24 @@ record_alternate_name(TypeHandle type, const string &name) {
   _lock->unlock();
   _lock->unlock();
 }
 }
 
 
+#ifdef HAVE_PYTHON
+/**
+ * Records the given Python type pointer in the type registry for the benefit
+ * of interrogate.
+ */
+void TypeRegistry::
+record_python_type(TypeHandle type, PyObject *python_type) {
+  _lock->lock();
+
+  TypeRegistryNode *rnode = look_up(type, nullptr);
+  if (rnode != nullptr) {
+    rnode->_python_type = python_type;
+  }
+
+  _lock->unlock();
+}
+#endif
+
 /**
 /**
  * Looks for a previously-registered type of the given name.  Returns its
  * Looks for a previously-registered type of the given name.  Returns its
  * TypeHandle if it exists, or TypeHandle::none() if there is no such type.
  * TypeHandle if it exists, or TypeHandle::none() if there is no such type.

+ 3 - 0
dtool/src/dtoolbase/typeRegistry.h

@@ -45,6 +45,9 @@ PUBLISHED:
 
 
   void record_derivation(TypeHandle child, TypeHandle parent);
   void record_derivation(TypeHandle child, TypeHandle parent);
   void record_alternate_name(TypeHandle type, const std::string &name);
   void record_alternate_name(TypeHandle type, const std::string &name);
+#ifdef HAVE_PYTHON
+  void record_python_type(TypeHandle type, PyObject *python_type);
+#endif
 
 
   TypeHandle find_type(const std::string &name) const;
   TypeHandle find_type(const std::string &name) const;
   TypeHandle find_type_by_id(int id) const;
   TypeHandle find_type_by_id(int id) const;

+ 13 - 0
dtool/src/dtoolbase/typeRegistryNode.I

@@ -11,6 +11,19 @@
  * @date 2001-08-06
  * @date 2001-08-06
  */
  */
 
 
+/**
+ * Returns the Python type object associated with this node.
+ */
+INLINE PyObject *TypeRegistryNode::
+get_python_type() const {
+  if (_python_type != nullptr || _parent_classes.empty()) {
+    return _python_type;
+  } else {
+    // Recurse through parent classes.
+    return r_get_python_type();
+  }
+}
+
 /**
 /**
  *
  *
  */
  */

+ 23 - 0
dtool/src/dtoolbase/typeRegistryNode.cxx

@@ -308,6 +308,29 @@ r_build_subtrees(TypeRegistryNode *top, int bit_count,
   }
   }
 }
 }
 
 
+/**
+ * Recurses through the parent nodes to find the best Python type object to
+ * represent objects of this type.
+ */
+PyObject *TypeRegistryNode::
+r_get_python_type() const {
+  Classes::const_iterator ni;
+  for (ni = _parent_classes.begin(); ni != _parent_classes.end(); ++ni) {
+    const TypeRegistryNode *parent = *ni;
+    if (parent->_python_type != nullptr) {
+      return parent->_python_type;
+
+    } else if (!parent->_parent_classes.empty()) {
+      PyObject *py_type = parent->r_get_python_type();
+      if (py_type != nullptr) {
+        return py_type;
+      }
+    }
+  }
+
+  return nullptr;
+}
+
 /**
 /**
  * A recursive function to double-check the result of is_derived_from().  This
  * A recursive function to double-check the result of is_derived_from().  This
  * is the slow, examine-the-whole-graph approach, as opposed to the clever and
  * is the slow, examine-the-whole-graph approach, as opposed to the clever and

+ 5 - 0
dtool/src/dtoolbase/typeRegistryNode.h

@@ -37,6 +37,8 @@ public:
   static TypeHandle get_parent_towards(const TypeRegistryNode *child,
   static TypeHandle get_parent_towards(const TypeRegistryNode *child,
                                        const TypeRegistryNode *base);
                                        const TypeRegistryNode *base);
 
 
+  INLINE PyObject *get_python_type() const;
+
   void clear_subtree();
   void clear_subtree();
   void define_subtree();
   void define_subtree();
 
 
@@ -46,6 +48,7 @@ public:
   typedef std::vector<TypeRegistryNode *> Classes;
   typedef std::vector<TypeRegistryNode *> Classes;
   Classes _parent_classes;
   Classes _parent_classes;
   Classes _child_classes;
   Classes _child_classes;
+  PyObject *_python_type = nullptr;
 
 
   AtomicAdjust::Integer _memory_usage[TypeHandle::MC_limit];
   AtomicAdjust::Integer _memory_usage[TypeHandle::MC_limit];
 
 
@@ -77,6 +80,8 @@ private:
   void r_build_subtrees(TypeRegistryNode *top,
   void r_build_subtrees(TypeRegistryNode *top,
                         int bit_count, SubtreeMaskType bits);
                         int bit_count, SubtreeMaskType bits);
 
 
+  PyObject *r_get_python_type() const;
+
   static bool check_derived_from(const TypeRegistryNode *child,
   static bool check_derived_from(const TypeRegistryNode *child,
                                  const TypeRegistryNode *base);
                                  const TypeRegistryNode *base);
 
 

+ 75 - 41
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -821,10 +821,54 @@ write_prototypes(ostream &out_code, ostream *out_h) {
     }
     }
   }
   }
 
 
+  out_code << "/**\n";
+  out_code << " * Declarations for exported classes\n";
+  out_code << " */\n";
+
+  out_code << "static const Dtool_TypeDef exports[] = {\n";
+
+  for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
+    Object *object = (*oi).second;
+
+    if (object->_itype.is_class() || object->_itype.is_struct()) {
+      CPPType *type = object->_itype._cpptype;
+
+      if (isExportThisRun(type) && is_cpp_type_legal(type)) {
+        string class_name = type->get_local_name(&parser);
+        string safe_name = make_safe_name(class_name);
+
+        out_code << "  {\"" << class_name << "\", &Dtool_" << safe_name << "},\n";
+      }
+    }
+  }
+
+  out_code << "  {nullptr, nullptr},\n";
+  out_code << "};\n\n";
+
   out_code << "/**\n";
   out_code << "/**\n";
   out_code << " * Extern declarations for imported classes\n";
   out_code << " * Extern declarations for imported classes\n";
   out_code << " */\n";
   out_code << " */\n";
 
 
+  // Write out a table of the externally imported types that will be filled in
+  // upon module initialization.
+  if (!_external_imports.empty()) {
+    out_code << "#ifndef LINK_ALL_STATIC\n";
+    out_code << "static Dtool_TypeDef imports[] = {\n";
+
+    int idx = 0;
+    for (CPPType *type : _external_imports) {
+      string class_name = type->get_local_name(&parser);
+      string safe_name = make_safe_name(class_name);
+
+      out_code << "  {\"" << class_name << "\", nullptr},\n";
+      out_code << "#define Dtool_Ptr_" << safe_name << " (imports[" << idx << "].type)\n";
+      ++idx;
+    }
+    out_code << "  {nullptr, nullptr},\n";
+    out_code << "};\n";
+    out_code << "#endif\n\n";
+  }
+
   for (CPPType *type : _external_imports) {
   for (CPPType *type : _external_imports) {
     string class_name = type->get_local_name(&parser);
     string class_name = type->get_local_name(&parser);
     string safe_name = make_safe_name(class_name);
     string safe_name = make_safe_name(class_name);
@@ -834,7 +878,9 @@ write_prototypes(ostream &out_code, ostream *out_h) {
     out_code << "#ifndef LINK_ALL_STATIC\n";
     out_code << "#ifndef LINK_ALL_STATIC\n";
     // out_code << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" <<
     // out_code << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" <<
     // safe_name << ";\n";
     // safe_name << ";\n";
-    out_code << "static struct Dtool_PyTypedObject *Dtool_Ptr_" << safe_name << ";\n";
+    //if (has_get_class_type_function(type)) {
+    //  out_code << "static struct Dtool_PyTypedObject *Dtool_Ptr_" << safe_name << ";\n";
+    //}
     // out_code << "#define Dtool_Ptr_" << safe_name << " &Dtool_" <<
     // out_code << "#define Dtool_Ptr_" << safe_name << " &Dtool_" <<
     // safe_name << "\n"; out_code << "IMPORT_THIS void
     // safe_name << "\n"; out_code << "IMPORT_THIS void
     // Dtool_PyModuleClassInit_" << safe_name << "(PyObject *module);\n";
     // Dtool_PyModuleClassInit_" << safe_name << "(PyObject *module);\n";
@@ -1258,36 +1304,36 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
 
 
   Objects::iterator oi;
   Objects::iterator oi;
 
 
-  out << "void Dtool_" << def->library_name << "_RegisterTypes() {\n";
+  out << "void Dtool_" << def->library_name << "_RegisterTypes() {\n"
+         "  TypeRegistry *registry = TypeRegistry::ptr();\n"
+         "  nassertv(registry != nullptr);\n";
+
   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
     Object *object = (*oi).second;
     Object *object = (*oi).second;
-    if (object->_itype.is_class() ||
-        object->_itype.is_struct()) {
-      if (is_cpp_type_legal(object->_itype._cpptype) &&
-          isExportThisRun(object->_itype._cpptype)) {
-        string class_name = make_safe_name(object->_itype.get_scoped_name());
-        bool is_typed = has_get_class_type_function(object->_itype._cpptype);
+    if (object->_itype.is_class() || object->_itype.is_struct()) {
+      CPPType *type = object->_itype._cpptype;
+      if (is_cpp_type_legal(type) && isExportThisRun(type)) {
+        string class_name = object->_itype.get_scoped_name();
+        string safe_name = make_safe_name(class_name);
+        bool is_typed = has_get_class_type_function(type);
 
 
         if (is_typed) {
         if (is_typed) {
-          if (has_init_type_function(object->_itype._cpptype)) {
+          out << "  {\n";
+          if (has_init_type_function(type)) {
             // Call the init_type function.  This isn't necessary for all
             // Call the init_type function.  This isn't necessary for all
             // types as many of them are automatically initialized at static
             // types as many of them are automatically initialized at static
             // init type, but for some extension classes it's useful.
             // init type, but for some extension classes it's useful.
-            out << "  " << object->_itype._cpptype->get_local_name(&parser)
+            out << "    " << type->get_local_name(&parser)
                 << "::init_type();\n";
                 << "::init_type();\n";
           }
           }
-          out << "  Dtool_" << class_name << "._type = "
-              << object->_itype._cpptype->get_local_name(&parser)
-              << "::get_class_type();\n"
-              << "  RegisterRuntimeTypedClass(Dtool_" << class_name << ");\n";
-
+          out << "    TypeHandle handle = " << type->get_local_name(&parser)
+              << "::get_class_type();\n";
+          out << "    Dtool_" << safe_name << "._type = handle;\n";
+          out << "    registry->record_python_type(handle, "
+                 "(PyObject *)&Dtool_" << safe_name << ");\n";
+          out << "  }\n";
         } else {
         } else {
-          out << "#ifndef LINK_ALL_STATIC\n"
-              << "  RegisterNamedClass(\"" << object->_itype.get_scoped_name()
-              << "\", Dtool_" << class_name << ");\n"
-              << "#endif\n";
-
-          if (IsPandaTypedObject(object->_itype._cpptype->as_struct_type())) {
+          if (IsPandaTypedObject(type->as_struct_type())) {
             nout << object->_itype.get_scoped_name() << " derives from TypedObject, "
             nout << object->_itype.get_scoped_name() << " derives from TypedObject, "
                  << "but does not define a get_class_type() function.\n";
                  << "but does not define a get_class_type() function.\n";
           }
           }
@@ -1297,23 +1343,6 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
   }
   }
   out << "}\n\n";
   out << "}\n\n";
 
 
-  out << "void Dtool_" << def->library_name << "_ResolveExternals() {\n";
-  out << "#ifndef LINK_ALL_STATIC\n";
-  out << "  // Resolve externally imported types.\n";
-
-  for (CPPType *type : _external_imports) {
-    string class_name = type->get_local_name(&parser);
-    string safe_name = make_safe_name(class_name);
-
-    if (has_get_class_type_function(type)) {
-      out << "  Dtool_Ptr_" << safe_name << " = LookupRuntimeTypedClass(" << class_name << "::get_class_type());\n";
-    } else {
-      out << "  Dtool_Ptr_" << safe_name << " = LookupNamedClass(\"" << class_name << "\");\n";
-    }
-  }
-  out << "#endif\n";
-  out << "}\n\n";
-
   out << "void Dtool_" << def->library_name << "_BuildInstants(PyObject *module) {\n";
   out << "void Dtool_" << def->library_name << "_BuildInstants(PyObject *module) {\n";
   out << "  (void) module;\n";
   out << "  (void) module;\n";
 
 
@@ -1466,9 +1495,14 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
 
 
   out << "  {nullptr, nullptr, 0, nullptr}\n" << "};\n\n";
   out << "  {nullptr, nullptr, 0, nullptr}\n" << "};\n\n";
 
 
-  out << "struct LibraryDef " << def->library_name << "_moddef = {python_simple_funcs};\n";
+  out << "extern const struct LibraryDef " << def->library_name << "_moddef = {python_simple_funcs, exports, ";
+  if (_external_imports.empty()) {
+    out << "nullptr};\n";
+  } else {
+    out << "imports};\n";
+  }
   if (out_h != nullptr) {
   if (out_h != nullptr) {
-    *out_h << "extern struct LibraryDef " << def->library_name << "_moddef;\n";
+    *out_h << "extern const struct LibraryDef " << def->library_name << "_moddef;\n";
   }
   }
 }
 }
 
 
@@ -3063,7 +3097,7 @@ write_module_class(ostream &out, Object *obj) {
 
 
     out << "    Dtool_" << ClassName << "._PyType.tp_bases = PyTuple_Pack(" << bases.size() << baseargs << ");\n";
     out << "    Dtool_" << ClassName << "._PyType.tp_bases = PyTuple_Pack(" << bases.size() << baseargs << ");\n";
   } else {
   } else {
-    out << "    Dtool_" << ClassName << "._PyType.tp_base = (PyTypeObject *)&Dtool_DTOOL_SUPER_BASE;\n";
+    out << "    Dtool_" << ClassName << "._PyType.tp_base = (PyTypeObject *)Dtool_GetSuperBase();\n";
   }
   }
 
 
   int num_nested = obj->_itype.number_of_nested_types();
   int num_nested = obj->_itype.number_of_nested_types();

+ 0 - 3
dtool/src/interrogate/interrogate.cxx

@@ -19,7 +19,6 @@
 #include "pnotify.h"
 #include "pnotify.h"
 #include "panda_getopt_long.h"
 #include "panda_getopt_long.h"
 #include "preprocess_argv.h"
 #include "preprocess_argv.h"
-#include "pystub.h"
 #include <time.h>
 #include <time.h>
 
 
 using std::cerr;
 using std::cerr;
@@ -309,8 +308,6 @@ predefine_macro(CPPParser& parser, const string& inoption) {
 
 
 int
 int
 main(int argc, char **argv) {
 main(int argc, char **argv) {
-  pystub();
-
   preprocess_argv(argc, argv);
   preprocess_argv(argc, argv);
   string command_line;
   string command_line;
   int i;
   int i;

+ 9 - 14
dtool/src/interrogate/interrogate_module.cxx

@@ -19,7 +19,6 @@
 #include "interrogate_interface.h"
 #include "interrogate_interface.h"
 #include "interrogate_request.h"
 #include "interrogate_request.h"
 #include "load_dso.h"
 #include "load_dso.h"
-#include "pystub.h"
 #include "pnotify.h"
 #include "pnotify.h"
 #include "panda_getopt_long.h"
 #include "panda_getopt_long.h"
 #include "preprocess_argv.h"
 #include "preprocess_argv.h"
@@ -30,6 +29,9 @@
 using std::cerr;
 using std::cerr;
 using std::string;
 using std::string;
 
 
+// This contains a big source string determined at compile time.
+extern const char interrogate_preamble_python_native[];
+
 Filename output_code_filename;
 Filename output_code_filename;
 string module_name;
 string module_name;
 string library_name;
 string library_name;
@@ -286,9 +288,8 @@ int write_python_table_native(std::ostream &out) {
   vector_string::const_iterator ii;
   vector_string::const_iterator ii;
   for (ii = libraries.begin(); ii != libraries.end(); ++ii) {
   for (ii = libraries.begin(); ii != libraries.end(); ++ii) {
     printf("Referencing Library %s\n", (*ii).c_str());
     printf("Referencing Library %s\n", (*ii).c_str());
-    out << "extern LibraryDef " << *ii << "_moddef;\n";
+    out << "extern const struct LibraryDef " << *ii << "_moddef;\n";
     out << "extern void Dtool_" << *ii << "_RegisterTypes();\n";
     out << "extern void Dtool_" << *ii << "_RegisterTypes();\n";
-    out << "extern void Dtool_" << *ii << "_ResolveExternals();\n";
     out << "extern void Dtool_" << *ii << "_BuildInstants(PyObject *module);\n";
     out << "extern void Dtool_" << *ii << "_BuildInstants(PyObject *module);\n";
   }
   }
 
 
@@ -339,12 +340,9 @@ int write_python_table_native(std::ostream &out) {
   for (ii = libraries.begin(); ii != libraries.end(); ii++) {
   for (ii = libraries.begin(); ii != libraries.end(); ii++) {
     out << "  Dtool_" << *ii << "_RegisterTypes();\n";
     out << "  Dtool_" << *ii << "_RegisterTypes();\n";
   }
   }
-  for (ii = libraries.begin(); ii != libraries.end(); ii++) {
-    out << "  Dtool_" << *ii << "_ResolveExternals();\n";
-  }
   out << "\n";
   out << "\n";
 
 
-  out << "  LibraryDef *defs[] = {";
+  out << "  const LibraryDef *defs[] = {";
   for(ii = libraries.begin(); ii != libraries.end(); ii++) {
   for(ii = libraries.begin(); ii != libraries.end(); ii++) {
     out << "&" << *ii << "_moddef, ";
     out << "&" << *ii << "_moddef, ";
   }
   }
@@ -386,12 +384,9 @@ int write_python_table_native(std::ostream &out) {
   for (ii = libraries.begin(); ii != libraries.end(); ii++) {
   for (ii = libraries.begin(); ii != libraries.end(); ii++) {
     out << "  Dtool_" << *ii << "_RegisterTypes();\n";
     out << "  Dtool_" << *ii << "_RegisterTypes();\n";
   }
   }
-  for (ii = libraries.begin(); ii != libraries.end(); ii++) {
-    out << "  Dtool_" << *ii << "_ResolveExternals();\n";
-  }
   out << "\n";
   out << "\n";
 
 
-  out << "  LibraryDef *defs[] = {";
+  out << "  const LibraryDef *defs[] = {";
   for(ii = libraries.begin(); ii != libraries.end(); ii++) {
   for(ii = libraries.begin(); ii != libraries.end(); ii++) {
     out << "&" << *ii << "_moddef, ";
     out << "&" << *ii << "_moddef, ";
   }
   }
@@ -545,8 +540,6 @@ int main(int argc, char *argv[]) {
   extern int optind;
   extern int optind;
   int flag;
   int flag;
 
 
-  pystub();
-
   preprocess_argv(argc, argv);
   preprocess_argv(argc, argv);
   flag = getopt_long_only(argc, argv, short_options, long_options, nullptr);
   flag = getopt_long_only(argc, argv, short_options, long_options, nullptr);
   while (flag != EOF) {
   while (flag != EOF) {
@@ -642,8 +635,10 @@ int main(int argc, char *argv[]) {
 
 
       if (build_python_native_wrappers) {
       if (build_python_native_wrappers) {
         write_python_table_native(output_code);
         write_python_table_native(output_code);
-      }
 
 
+        // Output the support code.
+        output_code << interrogate_preamble_python_native << "\n";
+      }
     }
     }
   }
   }
 
 

+ 0 - 3
dtool/src/interrogate/parse_file.cxx

@@ -22,7 +22,6 @@
 #include "cppGlobals.h"
 #include "cppGlobals.h"
 #include "panda_getopt_long.h"
 #include "panda_getopt_long.h"
 #include "preprocess_argv.h"
 #include "preprocess_argv.h"
-#include "pystub.h"
 #include <stdlib.h>
 #include <stdlib.h>
 
 
 using std::cerr;
 using std::cerr;
@@ -206,8 +205,6 @@ show_nested_types(const string &str) {
 
 
 int
 int
 main(int argc, char **argv) {
 main(int argc, char **argv) {
-  pystub();
-
   extern char *optarg;
   extern char *optarg;
   extern int optind;
   extern int optind;
   const char *optstr = "I:S:D:o:l:vp";
   const char *optstr = "I:S:D:o:l:vp";

+ 103 - 91
dtool/src/interrogatedb/dtool_super_base.cxx

@@ -15,120 +15,132 @@
 
 
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
 
 
-class EmptyClass {
-};
-Define_Module_Class_Private(dtoolconfig, DTOOL_SUPER_BASE, EmptyClass, DTOOL_SUPER_BASE111);
-
 static PyObject *GetSuperBase(PyObject *self) {
 static PyObject *GetSuperBase(PyObject *self) {
-  Py_INCREF((PyTypeObject *)&Dtool_DTOOL_SUPER_BASE); // order is important .. this is used for static functions
-  return (PyObject *) &Dtool_DTOOL_SUPER_BASE;
-};
-
-PyMethodDef Dtool_Methods_DTOOL_SUPER_BASE[] = {
-  { "DtoolGetSuperBase", (PyCFunction) &GetSuperBase, METH_NOARGS, "Will Return SUPERbase Class"},
-  { nullptr, nullptr, 0, nullptr }
+  Dtool_PyTypedObject *super_base = Dtool_GetSuperBase();
+  Py_XINCREF((PyTypeObject *)super_base); // order is important .. this is used for static functions
+  return (PyObject *)super_base;
 };
 };
 
 
-EXPCL_INTERROGATEDB void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module) {
-  static bool initdone = false;
-  if (!initdone) {
-
-    initdone = true;
-    Dtool_DTOOL_SUPER_BASE._PyType.tp_dict = PyDict_New();
-    PyDict_SetItemString(Dtool_DTOOL_SUPER_BASE._PyType.tp_dict, "DtoolClassDict", Dtool_DTOOL_SUPER_BASE._PyType.tp_dict);
-
-    if (PyType_Ready((PyTypeObject *)&Dtool_DTOOL_SUPER_BASE) < 0) {
-      PyErr_SetString(PyExc_TypeError, "PyType_Ready(Dtool_DTOOL_SUPER_BASE)");
-      return;
-    }
-    Py_INCREF((PyTypeObject *)&Dtool_DTOOL_SUPER_BASE);
-
-    PyDict_SetItemString(Dtool_DTOOL_SUPER_BASE._PyType.tp_dict, "DtoolGetSuperBase", PyCFunction_New(&Dtool_Methods_DTOOL_SUPER_BASE[0], (PyObject *)&Dtool_DTOOL_SUPER_BASE));
-  }
-
+static void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module) {
   if (module != nullptr) {
   if (module != nullptr) {
-    Py_INCREF((PyTypeObject *)&Dtool_DTOOL_SUPER_BASE);
-    PyModule_AddObject(module, "DTOOL_SUPER_BASE", (PyObject *)&Dtool_DTOOL_SUPER_BASE);
+    Dtool_PyTypedObject *super_base = Dtool_GetSuperBase();
+    Py_INCREF((PyTypeObject *)&super_base);
+    PyModule_AddObject(module, "DTOOL_SUPER_BASE", (PyObject *)&super_base);
   }
   }
 }
 }
 
 
-inline void *Dtool_DowncastInterface_DTOOL_SUPER_BASE(void *from_this, Dtool_PyTypedObject *from_type) {
+static void *Dtool_DowncastInterface_DTOOL_SUPER_BASE(void *from_this, Dtool_PyTypedObject *from_type) {
   return nullptr;
   return nullptr;
 }
 }
 
 
-inline void *Dtool_UpcastInterface_DTOOL_SUPER_BASE(PyObject *self, Dtool_PyTypedObject *requested_type) {
+static void *Dtool_UpcastInterface_DTOOL_SUPER_BASE(PyObject *self, Dtool_PyTypedObject *requested_type) {
   return nullptr;
   return nullptr;
 }
 }
 
 
-int Dtool_Init_DTOOL_SUPER_BASE(PyObject *self, PyObject *args, PyObject *kwds) {
+static int Dtool_Init_DTOOL_SUPER_BASE(PyObject *self, PyObject *args, PyObject *kwds) {
   assert(self != nullptr);
   assert(self != nullptr);
   PyErr_Format(PyExc_TypeError, "cannot init constant class %s", Py_TYPE(self)->tp_name);
   PyErr_Format(PyExc_TypeError, "cannot init constant class %s", Py_TYPE(self)->tp_name);
   return -1;
   return -1;
 }
 }
 
 
-EXPORT_THIS Dtool_PyTypedObject Dtool_DTOOL_SUPER_BASE = {
-  {
-    PyVarObject_HEAD_INIT(nullptr, 0)
-    "dtoolconfig.DTOOL_SUPER_BASE",
-    sizeof(Dtool_PyInstDef),
-    0, // tp_itemsize
-    &Dtool_FreeInstance_DTOOL_SUPER_BASE,
-    nullptr, // tp_print
-    nullptr, // tp_getattr
-    nullptr, // tp_setattr
+static void Dtool_FreeInstance_DTOOL_SUPER_BASE(PyObject *self) {
+  Py_TYPE(self)->tp_free(self);
+}
+
+/**
+ * Returns a pointer to the DTOOL_SUPER_BASE class that is the base class of
+ * all Panda types.  This pointer is shared by all modules.
+ */
+Dtool_PyTypedObject *Dtool_GetSuperBase() {
+  Dtool_TypeMap *type_map = Dtool_GetGlobalTypeMap();
+  auto it = type_map->find("DTOOL_SUPER_BASE");
+  if (it != type_map->end()) {
+    return it->second;
+  }
+
+  static PyMethodDef methods[] = {
+    { "DtoolGetSuperBase", (PyCFunction)&GetSuperBase, METH_NOARGS, "Will Return SUPERbase Class"},
+    { nullptr, nullptr, 0, nullptr }
+  };
+
+  static Dtool_PyTypedObject super_base_type = {
+    {
+      PyVarObject_HEAD_INIT(nullptr, 0)
+      "dtoolconfig.DTOOL_SUPER_BASE",
+      sizeof(Dtool_PyInstDef),
+      0, // tp_itemsize
+      &Dtool_FreeInstance_DTOOL_SUPER_BASE,
+      nullptr, // tp_print
+      nullptr, // tp_getattr
+      nullptr, // tp_setattr
 #if PY_MAJOR_VERSION >= 3
 #if PY_MAJOR_VERSION >= 3
-    nullptr, // tp_compare
+      nullptr, // tp_compare
 #else
 #else
-    &DtoolInstance_ComparePointers,
+      &DtoolInstance_ComparePointers,
 #endif
 #endif
-    nullptr, // tp_repr
-    nullptr, // tp_as_number
-    nullptr, // tp_as_sequence
-    nullptr, // tp_as_mapping
-    &DtoolInstance_HashPointer,
-    nullptr, // tp_call
-    nullptr, // tp_str
-    PyObject_GenericGetAttr,
-    PyObject_GenericSetAttr,
-    nullptr, // tp_as_buffer
-    (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES),
-    nullptr, // tp_doc
-    nullptr, // tp_traverse
-    nullptr, // tp_clear
+      nullptr, // tp_repr
+      nullptr, // tp_as_number
+      nullptr, // tp_as_sequence
+      nullptr, // tp_as_mapping
+      &DtoolInstance_HashPointer,
+      nullptr, // tp_call
+      nullptr, // tp_str
+      PyObject_GenericGetAttr,
+      PyObject_GenericSetAttr,
+      nullptr, // tp_as_buffer
+      (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES),
+      nullptr, // tp_doc
+      nullptr, // tp_traverse
+      nullptr, // tp_clear
 #if PY_MAJOR_VERSION >= 3
 #if PY_MAJOR_VERSION >= 3
-    &DtoolInstance_RichComparePointers,
+      &DtoolInstance_RichComparePointers,
 #else
 #else
-    nullptr, // tp_richcompare
+      nullptr, // tp_richcompare
 #endif
 #endif
-    0, // tp_weaklistoffset
-    nullptr, // tp_iter
-    nullptr, // tp_iternext
-    Dtool_Methods_DTOOL_SUPER_BASE,
-    standard_type_members,
-    nullptr, // tp_getset
-    nullptr, // tp_base
-    nullptr, // tp_dict
-    nullptr, // tp_descr_get
-    nullptr, // tp_descr_set
-    0, // tp_dictoffset
-    Dtool_Init_DTOOL_SUPER_BASE,
-    PyType_GenericAlloc,
-    Dtool_new_DTOOL_SUPER_BASE,
-    PyObject_Del,
-    nullptr, // tp_is_gc
-    nullptr, // tp_bases
-    nullptr, // tp_mro
-    nullptr, // tp_cache
-    nullptr, // tp_subclasses
-    nullptr, // tp_weaklist
-    nullptr, // tp_del
-  },
-  TypeHandle::none(),
-  Dtool_PyModuleClassInit_DTOOL_SUPER_BASE,
-  Dtool_UpcastInterface_DTOOL_SUPER_BASE,
-  Dtool_DowncastInterface_DTOOL_SUPER_BASE,
-  nullptr,
-  nullptr,
-};
+      0, // tp_weaklistoffset
+      nullptr, // tp_iter
+      nullptr, // tp_iternext
+      methods,
+      standard_type_members,
+      nullptr, // tp_getset
+      nullptr, // tp_base
+      nullptr, // tp_dict
+      nullptr, // tp_descr_get
+      nullptr, // tp_descr_set
+      0, // tp_dictoffset
+      Dtool_Init_DTOOL_SUPER_BASE,
+      PyType_GenericAlloc,
+      nullptr, // tp_new
+      PyObject_Del,
+      nullptr, // tp_is_gc
+      nullptr, // tp_bases
+      nullptr, // tp_mro
+      nullptr, // tp_cache
+      nullptr, // tp_subclasses
+      nullptr, // tp_weaklist
+      nullptr, // tp_del
+    },
+    TypeHandle::none(),
+    Dtool_PyModuleClassInit_DTOOL_SUPER_BASE,
+    Dtool_UpcastInterface_DTOOL_SUPER_BASE,
+    Dtool_DowncastInterface_DTOOL_SUPER_BASE,
+    nullptr,
+    nullptr,
+  };
+
+  super_base_type._PyType.tp_dict = PyDict_New();
+  PyDict_SetItemString(super_base_type._PyType.tp_dict, "DtoolClassDict", super_base_type._PyType.tp_dict);
+
+  if (PyType_Ready((PyTypeObject *)&super_base_type) < 0) {
+    PyErr_SetString(PyExc_TypeError, "PyType_Ready(Dtool_DTOOL_SUPER_BASE)");
+    return nullptr;
+  }
+  Py_INCREF((PyTypeObject *)&super_base_type);
+
+  PyDict_SetItemString(super_base_type._PyType.tp_dict, "DtoolGetSuperBase", PyCFunction_New(&methods[0], (PyObject *)&super_base_type));
+
+  (*type_map)["DTOOL_SUPER_BASE"] = &super_base_type;
+  return &super_base_type;
+}
 
 
 #endif  // HAVE_PYTHON
 #endif  // HAVE_PYTHON

+ 0 - 1
dtool/src/interrogatedb/p3interrogatedb_composite1.cxx

@@ -1,5 +1,4 @@
 #include "config_interrogatedb.cxx"
 #include "config_interrogatedb.cxx"
-#include "dtool_super_base.cxx"
 #include "indexRemapper.cxx"
 #include "indexRemapper.cxx"
 #include "interrogateComponent.cxx"
 #include "interrogateComponent.cxx"
 #include "interrogateDatabase.cxx"
 #include "interrogateDatabase.cxx"

+ 0 - 3
dtool/src/interrogatedb/p3interrogatedb_composite2.cxx

@@ -4,6 +4,3 @@
 #include "interrogate_datafile.cxx"
 #include "interrogate_datafile.cxx"
 #include "interrogate_interface.cxx"
 #include "interrogate_interface.cxx"
 #include "interrogate_request.cxx"
 #include "interrogate_request.cxx"
-#include "py_panda.cxx"
-#include "py_compat.cxx"
-#include "py_wrappers.cxx"

+ 0 - 7
dtool/src/interrogatedb/py_compat.cxx

@@ -1,11 +1,4 @@
 /**
 /**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
  * @file py_compat.cxx
  * @file py_compat.cxx
  * @author rdb
  * @author rdb
  * @date 2017-12-03
  * @date 2017-12-03

+ 1 - 8
dtool/src/interrogatedb/py_compat.h

@@ -1,11 +1,4 @@
 /**
 /**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
  * @file py_compat.h
  * @file py_compat.h
  * @author rdb
  * @author rdb
  * @date 2017-12-02
  * @date 2017-12-02
@@ -106,7 +99,7 @@ typedef int Py_ssize_t;
 // PyInt_FromSize_t automatically picks the right type.
 // PyInt_FromSize_t automatically picks the right type.
 #  define PyLongOrInt_AS_LONG PyInt_AsLong
 #  define PyLongOrInt_AS_LONG PyInt_AsLong
 
 
-EXPCL_INTERROGATEDB size_t PyLongOrInt_AsSize_t(PyObject *);
+size_t PyLongOrInt_AsSize_t(PyObject *);
 #endif
 #endif
 
 
 // Which character to use in PyArg_ParseTuple et al for a byte string.
 // Which character to use in PyArg_ParseTuple et al for a byte string.

+ 17 - 12
dtool/src/interrogatedb/py_panda.I

@@ -1,11 +1,4 @@
 /**
 /**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
  * @file py_panda.I
  * @file py_panda.I
  * @author rdb
  * @author rdb
  * @date 2016-06-06
  * @date 2016-06-06
@@ -26,7 +19,7 @@
 template<class T> INLINE bool
 template<class T> INLINE bool
 DtoolInstance_GetPointer(PyObject *self, T *&into) {
 DtoolInstance_GetPointer(PyObject *self, T *&into) {
   if (DtoolInstance_Check(self)) {
   if (DtoolInstance_Check(self)) {
-    Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+    Dtool_PyTypedObject *target_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
     if (target_class != nullptr) {
     if (target_class != nullptr) {
       if (_IS_FINAL(T)) {
       if (_IS_FINAL(T)) {
         if (DtoolInstance_TYPE(self) == target_class) {
         if (DtoolInstance_TYPE(self) == target_class) {
@@ -116,32 +109,44 @@ INLINE long Dtool_EnumValue_AsLong(PyObject *value) {
  */
  */
 template<class T> INLINE PyObject *
 template<class T> INLINE PyObject *
 DTool_CreatePyInstance(const T *obj, bool memory_rules) {
 DTool_CreatePyInstance(const T *obj, bool memory_rules) {
-  Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+  Dtool_PyTypedObject *known_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
   nassertr(known_class != nullptr, nullptr);
   nassertr(known_class != nullptr, nullptr);
   return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, true);
   return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, true);
 }
 }
 
 
 template<class T> INLINE PyObject *
 template<class T> INLINE PyObject *
 DTool_CreatePyInstance(T *obj, bool memory_rules) {
 DTool_CreatePyInstance(T *obj, bool memory_rules) {
-  Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+  Dtool_PyTypedObject *known_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
   nassertr(known_class != nullptr, nullptr);
   nassertr(known_class != nullptr, nullptr);
   return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, false);
   return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, false);
 }
 }
 
 
 template<class T> INLINE PyObject *
 template<class T> INLINE PyObject *
 DTool_CreatePyInstanceTyped(const T *obj, bool memory_rules) {
 DTool_CreatePyInstanceTyped(const T *obj, bool memory_rules) {
-  Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+  Dtool_PyTypedObject *known_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
   nassertr(known_class != nullptr, nullptr);
   nassertr(known_class != nullptr, nullptr);
   return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, true, obj->get_type().get_index());
   return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, true, obj->get_type().get_index());
 }
 }
 
 
 template<class T> INLINE PyObject *
 template<class T> INLINE PyObject *
 DTool_CreatePyInstanceTyped(T *obj, bool memory_rules) {
 DTool_CreatePyInstanceTyped(T *obj, bool memory_rules) {
-  Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+  Dtool_PyTypedObject *known_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
   nassertr(known_class != nullptr, nullptr);
   nassertr(known_class != nullptr, nullptr);
   return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, false, obj->get_type().get_index());
   return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, false, obj->get_type().get_index());
 }
 }
 
 
+/**
+ * Finishes initializing the Dtool_PyInstDef.
+ */
+INLINE int
+DTool_PyInit_Finalize(PyObject *self, void *local_this, Dtool_PyTypedObject *type, bool memory_rules, bool is_const) {
+  ((Dtool_PyInstDef *)self)->_My_Type = type;
+  ((Dtool_PyInstDef *)self)->_ptr_to_object = local_this;
+  ((Dtool_PyInstDef *)self)->_memory_rules = memory_rules;
+  ((Dtool_PyInstDef *)self)->_is_const = is_const;
+  return 0;
+}
+
 /**
 /**
  * Checks that the tuple is empty.
  * Checks that the tuple is empty.
  */
  */

+ 48 - 174
dtool/src/interrogatedb/py_panda.cxx

@@ -1,11 +1,4 @@
 /**
 /**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
  * @file py_panda.cxx
  * @file py_panda.cxx
  * @author drose
  * @author drose
  * @date 2005-07-04
  * @date 2005-07-04
@@ -29,10 +22,6 @@ PyMemberDef standard_type_members[] = {
   {nullptr}  /* Sentinel */
   {nullptr}  /* Sentinel */
 };
 };
 
 
-static RuntimeTypeMap runtime_type_map;
-static RuntimeTypeSet runtime_type_set;
-static NamedTypeMap named_type_map;
-
 /**
 /**
 
 
  */
  */
@@ -431,7 +420,7 @@ PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &
   // IF the class is possibly a run time typed object
   // IF the class is possibly a run time typed object
   if (type_index > 0) {
   if (type_index > 0) {
     // get best fit class...
     // get best fit class...
-    Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(type_index);
+    Dtool_PyTypedObject *target_class = (Dtool_PyTypedObject *)TypeHandle::from_index(type_index).get_python_type();
     if (target_class != nullptr) {
     if (target_class != nullptr) {
       // cast to the type...
       // cast to the type...
       void *new_local_this = target_class->_Dtool_DowncastInterface(local_this_in, &known_class_type);
       void *new_local_this = target_class->_Dtool_DowncastInterface(local_this_in, &known_class_type);
@@ -484,132 +473,26 @@ PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_class
   return (PyObject *)self;
   return (PyObject *)self;
 }
 }
 
 
-// Th Finalizer for simple instances..
-int DTool_PyInit_Finalize(PyObject *self, void *local_this, Dtool_PyTypedObject *type, bool memory_rules, bool is_const) {
-  // lets put some code in here that checks to see the memory is properly
-  // configured.. prior to my call ..
-
-  ((Dtool_PyInstDef *)self)->_My_Type = type;
-  ((Dtool_PyInstDef *)self)->_ptr_to_object = local_this;
-  ((Dtool_PyInstDef *)self)->_memory_rules = memory_rules;
-  ((Dtool_PyInstDef *)self)->_is_const = is_const;
-  return 0;
-}
-
-// A helper function to glue method definition together .. that can not be
-// done at code generation time because of multiple generation passes in
-// interrogate..
-void Dtool_Accum_MethDefs(PyMethodDef in[], MethodDefmap &themap) {
-  for (; in->ml_name != nullptr; in++) {
-    if (themap.find(in->ml_name) == themap.end()) {
-      themap[in->ml_name] = in;
-    }
-  }
-}
-
-// ** HACK ** alert.. Need to keep a runtime type dictionary ... that is
-// forward declared of typed object.  We rely on the fact that typed objects
-// are uniquly defined by an integer.
-void
-RegisterNamedClass(const string &name, Dtool_PyTypedObject &otype) {
-  std::pair<NamedTypeMap::iterator, bool> result =
-    named_type_map.insert(NamedTypeMap::value_type(name, &otype));
-
-  if (!result.second) {
-    // There was already a class with this name in the dictionary.
-    interrogatedb_cat.warning()
-      << "Double definition for class " << name << "\n";
-  }
-}
-
-void
-RegisterRuntimeTypedClass(Dtool_PyTypedObject &otype) {
-  int type_index = otype._type.get_index();
-
-  if (type_index == 0) {
-    interrogatedb_cat.warning()
-      << "Class " << otype._PyType.tp_name
-      << " has a zero TypeHandle value; check that init_type() is called.\n";
-
-  } else if (type_index < 0 || type_index >= TypeRegistry::ptr()->get_num_typehandles()) {
-    interrogatedb_cat.warning()
-      << "Class " << otype._PyType.tp_name
-      << " has an illegal TypeHandle value; check that init_type() is called.\n";
-
-  } else {
-    std::pair<RuntimeTypeMap::iterator, bool> result =
-      runtime_type_map.insert(RuntimeTypeMap::value_type(type_index, &otype));
-    if (!result.second) {
-      // There was already an entry in the dictionary for type_index.
-      Dtool_PyTypedObject *other_type = (*result.first).second;
-      interrogatedb_cat.warning()
-        << "Classes " << otype._PyType.tp_name
-        << " and " << other_type->_PyType.tp_name
-        << " share the same TypeHandle value (" << type_index
-        << "); check class definitions.\n";
-
-    } else {
-      runtime_type_set.insert(type_index);
-    }
-  }
-}
-
-Dtool_PyTypedObject *
-LookupNamedClass(const string &name) {
-  NamedTypeMap::const_iterator it;
-  it = named_type_map.find(name);
-
-  if (it == named_type_map.end()) {
-    // Find a type named like this in the type registry.
-    TypeHandle handle = TypeRegistry::ptr()->find_type(name);
-    if (handle.get_index() > 0) {
-      RuntimeTypeMap::const_iterator it2;
-      it2 = runtime_type_map.find(handle.get_index());
-      if (it2 != runtime_type_map.end()) {
-        return it2->second;
-      }
-    }
-
-    interrogatedb_cat.error()
-      << "Attempt to use type " << name << " which has not yet been defined!\n";
-    return nullptr;
-  } else {
-    return it->second;
-  }
-}
-
-Dtool_PyTypedObject *
-LookupRuntimeTypedClass(TypeHandle handle) {
-  RuntimeTypeMap::const_iterator it;
-  it = runtime_type_map.find(handle.get_index());
-
-  if (it == runtime_type_map.end()) {
-    interrogatedb_cat.error()
-      << "Attempt to use type " << handle << " which has not yet been defined!\n";
-    return nullptr;
-  } else {
-    return it->second;
-  }
-}
-
-Dtool_PyTypedObject *Dtool_RuntimeTypeDtoolType(int type) {
-  RuntimeTypeMap::iterator di = runtime_type_map.find(type);
-  if (di != runtime_type_map.end()) {
-    return di->second;
+/**
+ * Returns a borrowed reference to the global type dictionary.
+ */
+Dtool_TypeMap *Dtool_GetGlobalTypeMap() {
+  PyObject *capsule = PySys_GetObject((char *)"_interrogate_types");
+  if (capsule != nullptr) {
+    return (Dtool_TypeMap *)PyCapsule_GetPointer(capsule, nullptr);
   } else {
   } else {
-    int type2 = get_best_parent_from_Set(type, runtime_type_set);
-    di = runtime_type_map.find(type2);
-    if (di != runtime_type_map.end()) {
-      return di->second;
-    }
+    Dtool_TypeMap *type_map = new Dtool_TypeMap;
+    capsule = PyCapsule_New((void *)type_map, nullptr, nullptr);
+    PySys_SetObject((char *)"_interrogate_types", capsule);
+    Py_DECREF(capsule);
+    return type_map;
   }
   }
-  return nullptr;
 }
 }
 
 
 #if PY_MAJOR_VERSION >= 3
 #if PY_MAJOR_VERSION >= 3
-PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], PyModuleDef *module_def) {
+PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], PyModuleDef *module_def) {
 #else
 #else
-PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
+PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], const char *modulename) {
 #endif
 #endif
   // Check the version so we can print a helpful error if it doesn't match.
   // Check the version so we can print a helpful error if it doesn't match.
   string version = Py_GetVersion();
   string version = Py_GetVersion();
@@ -627,55 +510,46 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
     return nullptr;
     return nullptr;
   }
   }
 
 
-  // Initialize the types we define in py_panda.
-  static bool dtool_inited = false;
-  if (!dtool_inited) {
-    dtool_inited = true;
-
-    if (PyType_Ready(&Dtool_SequenceWrapper_Type) < 0) {
-      return Dtool_Raise_TypeError("PyType_Ready(Dtool_SequenceWrapper)");
-    }
-
-    if (PyType_Ready(&Dtool_MutableSequenceWrapper_Type) < 0) {
-      return Dtool_Raise_TypeError("PyType_Ready(Dtool_MutableSequenceWrapper)");
-    }
-
-    if (PyType_Ready(&Dtool_MappingWrapper_Type) < 0) {
-      return Dtool_Raise_TypeError("PyType_Ready(Dtool_MappingWrapper)");
-    }
-
-    if (PyType_Ready(&Dtool_MutableMappingWrapper_Type) < 0) {
-      return Dtool_Raise_TypeError("PyType_Ready(Dtool_MutableMappingWrapper)");
-    }
+  Dtool_TypeMap *type_map = Dtool_GetGlobalTypeMap();
 
 
-    if (PyType_Ready(&Dtool_MappingWrapper_Keys_Type) < 0) {
-      return Dtool_Raise_TypeError("PyType_Ready(Dtool_MappingWrapper_Keys)");
-    }
+  // the module level function inits....
+  MethodDefmap functions;
+  for (size_t i = 0; defs[i] != nullptr; i++) {
+    const LibraryDef &def = *defs[i];
 
 
-    if (PyType_Ready(&Dtool_MappingWrapper_Values_Type) < 0) {
-      return Dtool_Raise_TypeError("PyType_Ready(Dtool_MappingWrapper_Values)");
+    // Accumulate method definitions.
+    for (PyMethodDef *meth = def._methods; meth->ml_name != nullptr; meth++) {
+      if (functions.find(meth->ml_name) == functions.end()) {
+        functions[meth->ml_name] = meth;
+      }
     }
     }
 
 
-    if (PyType_Ready(&Dtool_MappingWrapper_Items_Type) < 0) {
-      return Dtool_Raise_TypeError("PyType_Ready(Dtool_MappingWrapper_Items)");
+    // Define exported types.
+    const Dtool_TypeDef *types = def._types;
+    if (types != nullptr) {
+      while (types->name != nullptr) {
+        (*type_map)[std::string(types->name)] = types->type;
+        ++types;
+      }
     }
     }
+  }
 
 
-    if (PyType_Ready(&Dtool_GeneratorWrapper_Type) < 0) {
-      return Dtool_Raise_TypeError("PyType_Ready(Dtool_GeneratorWrapper)");
-    }
+  // Resolve external types, in a second pass.
+  for (size_t i = 0; defs[i] != nullptr; i++) {
+    const LibraryDef &def = *defs[i];
 
 
-    if (PyType_Ready(&Dtool_StaticProperty_Type) < 0) {
-      return Dtool_Raise_TypeError("PyType_Ready(Dtool_StaticProperty_Type)");
+    Dtool_TypeDef *types = def._external_types;
+    if (types != nullptr) {
+      while (types->name != nullptr) {
+        auto it = type_map->find(std::string(types->name));
+        if (it != type_map->end()) {
+          types->type = it->second;
+        } else {
+          return PyErr_Format(PyExc_NameError, "name '%s' is not defined", types->name);
+        }
+        ++types;
+      }
     }
     }
-
-    // Initialize the base class of everything.
-    Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(nullptr);
-  }
-
-  // the module level function inits....
-  MethodDefmap functions;
-  for (int xx = 0; defs[xx] != nullptr; xx++) {
-    Dtool_Accum_MethDefs(defs[xx]->_methods, functions);
   }
   }
 
 
   PyMethodDef *newdef = new PyMethodDef[functions.size() + 1];
   PyMethodDef *newdef = new PyMethodDef[functions.size() + 1];
@@ -799,7 +673,7 @@ PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args) {
 
 
 // We do expose a dictionay for dtool classes .. this should be removed at
 // We do expose a dictionay for dtool classes .. this should be removed at
 // some point..
 // some point..
-EXPCL_INTERROGATEDB PyObject *Dtool_AddToDictionary(PyObject *self1, PyObject *args) {
+PyObject *Dtool_AddToDictionary(PyObject *self1, PyObject *args) {
   PyObject *self;
   PyObject *self;
   PyObject *subject;
   PyObject *subject;
   PyObject *key;
   PyObject *key;

+ 42 - 53
dtool/src/interrogatedb/py_panda.h

@@ -1,11 +1,4 @@
 /**
 /**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
  * @file py_panda.h
  * @file py_panda.h
  */
  */
 
 
@@ -43,9 +36,6 @@ using namespace std;
 #endif
 #endif
 
 
 struct Dtool_PyTypedObject;
 struct Dtool_PyTypedObject;
-typedef std::map<int, Dtool_PyTypedObject *> RuntimeTypeMap;
-typedef std::set<int> RuntimeTypeSet;
-typedef std::map<std::string, Dtool_PyTypedObject *> NamedTypeMap;
 
 
 // used to stamp dtool instance..
 // used to stamp dtool instance..
 #define PY_PANDA_SIGNATURE 0xbeaf
 #define PY_PANDA_SIGNATURE 0xbeaf
@@ -78,7 +68,7 @@ struct Dtool_PyInstDef {
 };
 };
 
 
 // A Offset Dictionary Defining How to read the Above Object..
 // A Offset Dictionary Defining How to read the Above Object..
-extern EXPCL_INTERROGATEDB PyMemberDef standard_type_members[];
+extern PyMemberDef standard_type_members[];
 
 
 // The Class Definition Structor For a Dtool python type.
 // The Class Definition Structor For a Dtool python type.
 struct Dtool_PyTypedObject {
 struct Dtool_PyTypedObject {
@@ -190,25 +180,21 @@ static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
 // forward declared of typed object.  We rely on the fact that typed objects
 // forward declared of typed object.  We rely on the fact that typed objects
 // are uniquly defined by an integer.
 // are uniquly defined by an integer.
 
 
-EXPCL_INTERROGATEDB void RegisterNamedClass(const std::string &name, Dtool_PyTypedObject &otype);
-EXPCL_INTERROGATEDB void RegisterRuntimeTypedClass(Dtool_PyTypedObject &otype);
+typedef std::map<std::string, Dtool_PyTypedObject *> Dtool_TypeMap;
 
 
-EXPCL_INTERROGATEDB Dtool_PyTypedObject *LookupNamedClass(const std::string &name);
-EXPCL_INTERROGATEDB Dtool_PyTypedObject *LookupRuntimeTypedClass(TypeHandle handle);
-
-EXPCL_INTERROGATEDB Dtool_PyTypedObject *Dtool_RuntimeTypeDtoolType(int type);
+Dtool_TypeMap *Dtool_GetGlobalTypeMap();
 
 
 /**
 /**
 
 
  */
  */
-EXPCL_INTERROGATEDB void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *classdef, void **answer);
+void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *classdef, void **answer);
 
 
-EXPCL_INTERROGATEDB void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const std::string &function_name, bool const_ok, bool report_errors);
+void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const std::string &function_name, bool const_ok, bool report_errors);
 
 
-EXPCL_INTERROGATEDB bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer);
+bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer);
 
 
-EXPCL_INTERROGATEDB bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
-                                                              void **answer, const char *method_name);
+bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
+                                            void **answer, const char *method_name);
 
 
 template<class T> INLINE bool DtoolInstance_GetPointer(PyObject *self, T *&into);
 template<class T> INLINE bool DtoolInstance_GetPointer(PyObject *self, T *&into);
 template<class T> INLINE bool DtoolInstance_GetPointer(PyObject *self, T *&into, Dtool_PyTypedObject &classdef);
 template<class T> INLINE bool DtoolInstance_GetPointer(PyObject *self, T *&into, Dtool_PyTypedObject &classdef);
@@ -218,7 +204,7 @@ INLINE int DtoolInstance_ComparePointers(PyObject *v1, PyObject *v2);
 INLINE PyObject *DtoolInstance_RichComparePointers(PyObject *v1, PyObject *v2, int op);
 INLINE PyObject *DtoolInstance_RichComparePointers(PyObject *v1, PyObject *v2, int op);
 
 
 // Functions related to error reporting.
 // Functions related to error reporting.
-EXPCL_INTERROGATEDB bool _Dtool_CheckErrorOccurred();
+bool _Dtool_CheckErrorOccurred();
 
 
 #ifdef NDEBUG
 #ifdef NDEBUG
 #define Dtool_CheckErrorOccurred() (UNLIKELY(_PyErr_OCCURRED() != nullptr))
 #define Dtool_CheckErrorOccurred() (UNLIKELY(_PyErr_OCCURRED() != nullptr))
@@ -226,12 +212,12 @@ EXPCL_INTERROGATEDB bool _Dtool_CheckErrorOccurred();
 #define Dtool_CheckErrorOccurred() (UNLIKELY(_Dtool_CheckErrorOccurred()))
 #define Dtool_CheckErrorOccurred() (UNLIKELY(_Dtool_CheckErrorOccurred()))
 #endif
 #endif
 
 
-EXPCL_INTERROGATEDB PyObject *Dtool_Raise_AssertionError();
-EXPCL_INTERROGATEDB PyObject *Dtool_Raise_TypeError(const char *message);
-EXPCL_INTERROGATEDB PyObject *Dtool_Raise_ArgTypeError(PyObject *obj, int param, const char *function_name, const char *type_name);
-EXPCL_INTERROGATEDB PyObject *Dtool_Raise_AttributeError(PyObject *obj, const char *attribute);
+PyObject *Dtool_Raise_AssertionError();
+PyObject *Dtool_Raise_TypeError(const char *message);
+PyObject *Dtool_Raise_ArgTypeError(PyObject *obj, int param, const char *function_name, const char *type_name);
+PyObject *Dtool_Raise_AttributeError(PyObject *obj, const char *attribute);
 
 
-EXPCL_INTERROGATEDB PyObject *_Dtool_Raise_BadArgumentsError();
+PyObject *_Dtool_Raise_BadArgumentsError();
 #ifdef NDEBUG
 #ifdef NDEBUG
 // Define it to a function that just prints a generic message.
 // Define it to a function that just prints a generic message.
 #define Dtool_Raise_BadArgumentsError(x) _Dtool_Raise_BadArgumentsError()
 #define Dtool_Raise_BadArgumentsError(x) _Dtool_Raise_BadArgumentsError()
@@ -243,9 +229,9 @@ EXPCL_INTERROGATEDB PyObject *_Dtool_Raise_BadArgumentsError();
 // These functions are similar to Dtool_WrapValue, except that they also
 // These functions are similar to Dtool_WrapValue, except that they also
 // contain code for checking assertions and exceptions when compiling with
 // contain code for checking assertions and exceptions when compiling with
 // NDEBUG mode on.
 // NDEBUG mode on.
-EXPCL_INTERROGATEDB PyObject *_Dtool_Return_None();
-EXPCL_INTERROGATEDB PyObject *Dtool_Return_Bool(bool value);
-EXPCL_INTERROGATEDB PyObject *_Dtool_Return(PyObject *value);
+PyObject *_Dtool_Return_None();
+PyObject *Dtool_Return_Bool(bool value);
+PyObject *_Dtool_Return(PyObject *value);
 
 
 #ifdef NDEBUG
 #ifdef NDEBUG
 #define Dtool_Return_None() (LIKELY(_PyErr_OCCURRED() == nullptr) ? (Py_INCREF(Py_None), Py_None) : nullptr)
 #define Dtool_Return_None() (LIKELY(_PyErr_OCCURRED() == nullptr) ? (Py_INCREF(Py_None), Py_None) : nullptr)
@@ -258,19 +244,19 @@ EXPCL_INTERROGATEDB PyObject *_Dtool_Return(PyObject *value);
 /**
 /**
  * Wrapper around Python 3.4's enum library, which does not have a C API.
  * Wrapper around Python 3.4's enum library, which does not have a C API.
  */
  */
-EXPCL_INTERROGATEDB PyTypeObject *Dtool_EnumType_Create(const char *name, PyObject *names,
+PyTypeObject *Dtool_EnumType_Create(const char *name, PyObject *names,
                                                         const char *module = nullptr);
                                                         const char *module = nullptr);
-EXPCL_INTERROGATEDB INLINE long Dtool_EnumValue_AsLong(PyObject *value);
+INLINE long Dtool_EnumValue_AsLong(PyObject *value);
 
 
 
 
 /**
 /**
 
 
  */
  */
-EXPCL_INTERROGATEDB PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &known_class_type, bool memory_rules, bool is_const, int RunTimeType);
+PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &known_class_type, bool memory_rules, bool is_const, int RunTimeType);
 
 
 // DTool_CreatePyInstance .. wrapper function to finalize the existance of a
 // DTool_CreatePyInstance .. wrapper function to finalize the existance of a
 // general dtool py instance..
 // general dtool py instance..
-EXPCL_INTERROGATEDB PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_classdef, bool memory_rules, bool is_const);
+PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_classdef, bool memory_rules, bool is_const);
 
 
 // These template methods allow use when the Dtool_PyTypedObject is not known.
 // These template methods allow use when the Dtool_PyTypedObject is not known.
 // They require a get_class_type() to be defined for the class.
 // They require a get_class_type() to be defined for the class.
@@ -314,43 +300,49 @@ Define_Dtool_FreeInstanceRef(CLASS_NAME,CNAME)\
 Define_Dtool_Class(MODULE_NAME,CLASS_NAME,PUBLIC_NAME)
 Define_Dtool_Class(MODULE_NAME,CLASS_NAME,PUBLIC_NAME)
 
 
 // The finalizer for simple instances.
 // The finalizer for simple instances.
-EXPCL_INTERROGATEDB int DTool_PyInit_Finalize(PyObject *self, void *This, Dtool_PyTypedObject *type, bool memory_rules, bool is_const);
+INLINE int DTool_PyInit_Finalize(PyObject *self, void *This, Dtool_PyTypedObject *type, bool memory_rules, bool is_const);
 
 
 // A heler function to glu methed definition together .. that can not be done
 // A heler function to glu methed definition together .. that can not be done
 // at code generation time becouse of multiple generation passes in
 // at code generation time becouse of multiple generation passes in
 // interigate..
 // interigate..
 typedef std::map<std::string, PyMethodDef *> MethodDefmap;
 typedef std::map<std::string, PyMethodDef *> MethodDefmap;
 
 
-EXPCL_INTERROGATEDB void Dtool_Accum_MethDefs(PyMethodDef in[], MethodDefmap &themap);
-
 // We need a way to runtime merge compile units into a python "Module" .. this
 // We need a way to runtime merge compile units into a python "Module" .. this
 // is done with the fallowing structors and code.. along with the support of
 // is done with the fallowing structors and code.. along with the support of
 // interigate_module
 // interigate_module
+
+struct Dtool_TypeDef {
+  const char *const name;
+  Dtool_PyTypedObject *type;
+};
+
 struct LibraryDef {
 struct LibraryDef {
-  PyMethodDef *_methods;
+  PyMethodDef *const _methods;
+  const Dtool_TypeDef *const _types;
+  Dtool_TypeDef *const _external_types;
 };
 };
 
 
 #if PY_MAJOR_VERSION >= 3
 #if PY_MAJOR_VERSION >= 3
-EXPCL_INTERROGATEDB PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], PyModuleDef *module_def);
+PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], PyModuleDef *module_def);
 #else
 #else
-EXPCL_INTERROGATEDB PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename);
+PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], const char *modulename);
 #endif
 #endif
 
 
 // HACK.... Be carefull Dtool_BorrowThisReference This function can be used to
 // HACK.... Be carefull Dtool_BorrowThisReference This function can be used to
 // grab the "THIS" pointer from an object and use it Required to support fom
 // grab the "THIS" pointer from an object and use it Required to support fom
 // historical inharatence in the for of "is this instance of"..
 // historical inharatence in the for of "is this instance of"..
-EXPCL_INTERROGATEDB PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args);
+PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args);
 
 
 #define DTOOL_PyObject_HashPointer DtoolInstance_HashPointer
 #define DTOOL_PyObject_HashPointer DtoolInstance_HashPointer
 #define DTOOL_PyObject_ComparePointers DtoolInstance_ComparePointers
 #define DTOOL_PyObject_ComparePointers DtoolInstance_ComparePointers
 
 
-EXPCL_INTERROGATEDB PyObject *
+PyObject *
 copy_from_make_copy(PyObject *self, PyObject *noargs);
 copy_from_make_copy(PyObject *self, PyObject *noargs);
 
 
-EXPCL_INTERROGATEDB PyObject *
+PyObject *
 copy_from_copy_constructor(PyObject *self, PyObject *noargs);
 copy_from_copy_constructor(PyObject *self, PyObject *noargs);
 
 
-EXPCL_INTERROGATEDB PyObject *
+PyObject *
 map_deepcopy_to_copy(PyObject *self, PyObject *args);
 map_deepcopy_to_copy(PyObject *self, PyObject *args);
 
 
 /**
 /**
@@ -359,13 +351,13 @@ map_deepcopy_to_copy(PyObject *self, PyObject *args);
  */
  */
 ALWAYS_INLINE bool Dtool_CheckNoArgs(PyObject *args);
 ALWAYS_INLINE bool Dtool_CheckNoArgs(PyObject *args);
 ALWAYS_INLINE bool Dtool_CheckNoArgs(PyObject *args, PyObject *kwds);
 ALWAYS_INLINE bool Dtool_CheckNoArgs(PyObject *args, PyObject *kwds);
-EXPCL_INTERROGATEDB bool Dtool_ExtractArg(PyObject **result, PyObject *args,
+bool Dtool_ExtractArg(PyObject **result, PyObject *args,
                                           PyObject *kwds, const char *keyword);
                                           PyObject *kwds, const char *keyword);
-EXPCL_INTERROGATEDB bool Dtool_ExtractArg(PyObject **result, PyObject *args,
+bool Dtool_ExtractArg(PyObject **result, PyObject *args,
                                           PyObject *kwds);
                                           PyObject *kwds);
-EXPCL_INTERROGATEDB bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args,
+bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args,
                                                   PyObject *kwds, const char *keyword);
                                                   PyObject *kwds, const char *keyword);
-EXPCL_INTERROGATEDB bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args,
+bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args,
                                                   PyObject *kwds);
                                                   PyObject *kwds);
 
 
 /**
 /**
@@ -401,10 +393,7 @@ ALWAYS_INLINE PyObject *Dtool_WrapValue(Py_buffer *value);
 template<class T1, class T2>
 template<class T1, class T2>
 ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::pair<T1, T2> &value);
 ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::pair<T1, T2> &value);
 
 
-EXPCL_INTERROGATEDB extern struct Dtool_PyTypedObject Dtool_DTOOL_SUPER_BASE;
-EXPCL_INTERROGATEDB extern void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module);
-
-#define Dtool_Ptr_DTOOL_SUPER_BASE (&Dtool_DTOOL_SUPER_BASE)
+Dtool_PyTypedObject *Dtool_GetSuperBase();
 
 
 #include "py_panda.I"
 #include "py_panda.I"
 
 

File diff suppressed because it is too large
+ 299 - 674
dtool/src/interrogatedb/py_wrappers.cxx


+ 6 - 23
dtool/src/interrogatedb/py_wrappers.h

@@ -1,11 +1,4 @@
 /**
 /**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
  * @file py_wrappers.h
  * @file py_wrappers.h
  * @author rdb
  * @author rdb
  * @date 2017-11-26
  * @date 2017-11-26
@@ -56,22 +49,12 @@ struct Dtool_GeneratorWrapper {
   iternextfunc _iternext_func;
   iternextfunc _iternext_func;
 };
 };
 
 
-EXPCL_INTERROGATEDB extern PyTypeObject Dtool_SequenceWrapper_Type;
-EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MutableSequenceWrapper_Type;
-EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MappingWrapper_Type;
-EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MutableMappingWrapper_Type;
-EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MappingWrapper_Items_Type;
-EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MappingWrapper_Keys_Type;
-EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MappingWrapper_Values_Type;
-EXPCL_INTERROGATEDB extern PyTypeObject Dtool_GeneratorWrapper_Type;
-EXPCL_INTERROGATEDB extern PyTypeObject Dtool_StaticProperty_Type;
-
-EXPCL_INTERROGATEDB Dtool_SequenceWrapper *Dtool_NewSequenceWrapper(PyObject *self, const char *name);
-EXPCL_INTERROGATEDB Dtool_MutableSequenceWrapper *Dtool_NewMutableSequenceWrapper(PyObject *self, const char *name);
-EXPCL_INTERROGATEDB Dtool_MappingWrapper *Dtool_NewMappingWrapper(PyObject *self, const char *name);
-EXPCL_INTERROGATEDB Dtool_MappingWrapper *Dtool_NewMutableMappingWrapper(PyObject *self, const char *name);
-EXPCL_INTERROGATEDB PyObject *Dtool_NewGenerator(PyObject *self, const char *name, iternextfunc func);
-EXPCL_INTERROGATEDB PyObject *Dtool_NewStaticProperty(PyTypeObject *obj, const PyGetSetDef *getset);
+Dtool_SequenceWrapper *Dtool_NewSequenceWrapper(PyObject *self, const char *name);
+Dtool_MutableSequenceWrapper *Dtool_NewMutableSequenceWrapper(PyObject *self, const char *name);
+Dtool_MappingWrapper *Dtool_NewMappingWrapper(PyObject *self, const char *name);
+Dtool_MappingWrapper *Dtool_NewMutableMappingWrapper(PyObject *self, const char *name);
+PyObject *Dtool_NewGenerator(PyObject *self, iternextfunc func);
+PyObject *Dtool_NewStaticProperty(PyTypeObject *obj, const PyGetSetDef *getset);
 
 
 #endif  // HAVE_PYTHON
 #endif  // HAVE_PYTHON
 
 

+ 4 - 0
dtool/src/parser-inc/vrpn_Analog.h

@@ -0,0 +1,4 @@
+#pragma once
+
+class vrpn_Analog_Remote;
+typedef void vrpn_ANALOGCB;

+ 4 - 0
dtool/src/parser-inc/vrpn_Button.h

@@ -0,0 +1,4 @@
+#pragma once
+
+class vrpn_Button_Remote;
+typedef void vrpn_BUTTONCB;

+ 3 - 0
dtool/src/parser-inc/vrpn_Configure.h

@@ -0,0 +1,3 @@
+#pragma once
+
+#define VRPN_CALLBACK

+ 3 - 0
dtool/src/parser-inc/vrpn_Connection.h

@@ -0,0 +1,3 @@
+#pragma once
+
+class vrpn_Connection;

+ 4 - 0
dtool/src/parser-inc/vrpn_Dial.h

@@ -0,0 +1,4 @@
+#pragma once
+
+class vrpn_Dial_Remote;
+typedef void vrpn_DIALCB;

+ 6 - 0
dtool/src/parser-inc/vrpn_Tracker.h

@@ -0,0 +1,6 @@
+#pragma once
+
+class vrpn_Tracker_Remote;
+typedef void vrpn_TRACKERCB;
+typedef void vrpn_TRACKERACCCB;
+typedef void vrpn_TRACKERVELCB;

+ 8 - 0
dtool/src/pystub/pystub.cxx

@@ -27,6 +27,8 @@ extern "C" {
   EXPCL_PYSTUB int PyCFunction_New(...);
   EXPCL_PYSTUB int PyCFunction_New(...);
   EXPCL_PYSTUB int PyCFunction_NewEx(...);
   EXPCL_PYSTUB int PyCFunction_NewEx(...);
   EXPCL_PYSTUB int PyCallable_Check(...);
   EXPCL_PYSTUB int PyCallable_Check(...);
+  EXPCL_PYSTUB int PyCapsule_GetPointer(...);
+  EXPCL_PYSTUB int PyCapsule_New(...);
   EXPCL_PYSTUB int PyDict_DelItem(...);
   EXPCL_PYSTUB int PyDict_DelItem(...);
   EXPCL_PYSTUB int PyDict_DelItemString(...);
   EXPCL_PYSTUB int PyDict_DelItemString(...);
   EXPCL_PYSTUB int PyDict_GetItem(...);
   EXPCL_PYSTUB int PyDict_GetItem(...);
@@ -133,6 +135,7 @@ extern "C" {
   EXPCL_PYSTUB int PyString_InternInPlace(...);
   EXPCL_PYSTUB int PyString_InternInPlace(...);
   EXPCL_PYSTUB int PyString_Size(...);
   EXPCL_PYSTUB int PyString_Size(...);
   EXPCL_PYSTUB int PySys_GetObject(...);
   EXPCL_PYSTUB int PySys_GetObject(...);
+  EXPCL_PYSTUB int PySys_SetObject(...);
   EXPCL_PYSTUB int PyThreadState_Clear(...);
   EXPCL_PYSTUB int PyThreadState_Clear(...);
   EXPCL_PYSTUB int PyThreadState_Delete(...);
   EXPCL_PYSTUB int PyThreadState_Delete(...);
   EXPCL_PYSTUB int PyThreadState_Get(...);
   EXPCL_PYSTUB int PyThreadState_Get(...);
@@ -216,6 +219,7 @@ extern "C" {
   EXPCL_PYSTUB extern void *PyExc_ImportError;
   EXPCL_PYSTUB extern void *PyExc_ImportError;
   EXPCL_PYSTUB extern void *PyExc_IndexError;
   EXPCL_PYSTUB extern void *PyExc_IndexError;
   EXPCL_PYSTUB extern void *PyExc_KeyError;
   EXPCL_PYSTUB extern void *PyExc_KeyError;
+  EXPCL_PYSTUB extern void *PyExc_NameError;
   EXPCL_PYSTUB extern void *PyExc_OSError;
   EXPCL_PYSTUB extern void *PyExc_OSError;
   EXPCL_PYSTUB extern void *PyExc_OverflowError;
   EXPCL_PYSTUB extern void *PyExc_OverflowError;
   EXPCL_PYSTUB extern void *PyExc_RuntimeError;
   EXPCL_PYSTUB extern void *PyExc_RuntimeError;
@@ -257,6 +261,8 @@ int PyBytes_Size(...) { return 0; }
 int PyCFunction_New(...) { return 0; };
 int PyCFunction_New(...) { return 0; };
 int PyCFunction_NewEx(...) { return 0; };
 int PyCFunction_NewEx(...) { return 0; };
 int PyCallable_Check(...) { return 0; }
 int PyCallable_Check(...) { return 0; }
+int PyCapsule_GetPointer(...) { return 0; }
+int PyCapsule_New(...) { return 0; }
 int PyDict_DelItem(...) { return 0; }
 int PyDict_DelItem(...) { return 0; }
 int PyDict_DelItemString(...) { return 0; }
 int PyDict_DelItemString(...) { return 0; }
 int PyDict_GetItem(...) { return 0; }
 int PyDict_GetItem(...) { return 0; }
@@ -363,6 +369,7 @@ int PyString_FromStringAndSize(...) { return 0; }
 int PyString_InternFromString(...) { return 0; }
 int PyString_InternFromString(...) { return 0; }
 int PyString_InternInPlace(...) { return 0; }
 int PyString_InternInPlace(...) { return 0; }
 int PySys_GetObject(...) { return 0; }
 int PySys_GetObject(...) { return 0; }
+int PySys_SetObject(...) { return 0; }
 int PyThreadState_Clear(...) { return 0; }
 int PyThreadState_Clear(...) { return 0; }
 int PyThreadState_Delete(...) { return 0; }
 int PyThreadState_Delete(...) { return 0; }
 int PyThreadState_Get(...) { return 0; }
 int PyThreadState_Get(...) { return 0; }
@@ -452,6 +459,7 @@ void *PyExc_FutureWarning = nullptr;
 void *PyExc_ImportError = nullptr;
 void *PyExc_ImportError = nullptr;
 void *PyExc_IndexError = nullptr;
 void *PyExc_IndexError = nullptr;
 void *PyExc_KeyError = nullptr;
 void *PyExc_KeyError = nullptr;
+void *PyExc_NameError = nullptr;
 void *PyExc_OSError = nullptr;
 void *PyExc_OSError = nullptr;
 void *PyExc_OverflowError = nullptr;
 void *PyExc_OverflowError = nullptr;
 void *PyExc_RuntimeError = nullptr;
 void *PyExc_RuntimeError = nullptr;

+ 0 - 3
dtool/src/test_interrogate/test_interrogate.cxx

@@ -17,7 +17,6 @@
 #include "interrogate_request.h"
 #include "interrogate_request.h"
 #include "load_dso.h"
 #include "load_dso.h"
 #include "filename.h"
 #include "filename.h"
-#include "pystub.h"
 #include "panda_getopt.h"
 #include "panda_getopt.h"
 #include "preprocess_argv.h"
 #include "preprocess_argv.h"
 
 
@@ -526,8 +525,6 @@ main(int argc, char **argv) {
   extern int optind;
   extern int optind;
   const char *optstr = "p:ftqh";
   const char *optstr = "p:ftqh";
 
 
-  pystub();
-
   bool all_functions = false;
   bool all_functions = false;
   bool all_types = false;
   bool all_types = false;
   bool quick_load = false;
   bool quick_load = false;

+ 16 - 7
makepanda/installer.nsi

@@ -331,13 +331,24 @@ SectionGroup "Python support"
         SetOutPath $INSTDIR\panda3d
         SetOutPath $INSTDIR\panda3d
         File /r "${BUILT}\panda3d\*.py"
         File /r "${BUILT}\panda3d\*.py"
 
 
-        File /r /x bullet.pyd /x ode.pyd /x physx.pyd /x rocket.pyd "${BUILT}\panda3d\*.pyd"
+        File /nonfatal /r "${BUILT}\panda3d\core${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\ai${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\awesomium${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\direct${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\egg${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\fx${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\interrogatedb${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\physics${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\_rplight${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\skel${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\vision${EXT_SUFFIX}"
+        File /nonfatal /r "${BUILT}\panda3d\vrpn${EXT_SUFFIX}"
 
 
         !ifdef HAVE_BULLET
         !ifdef HAVE_BULLET
             SectionGetFlags ${SecBullet} $R0
             SectionGetFlags ${SecBullet} $R0
             IntOp $R0 $R0 & ${SF_SELECTED}
             IntOp $R0 $R0 & ${SF_SELECTED}
             StrCmp $R0 ${SF_SELECTED} 0 SkipBulletPyd
             StrCmp $R0 ${SF_SELECTED} 0 SkipBulletPyd
-            File /nonfatal /r "${BUILT}\panda3d\bullet.pyd"
+            File /nonfatal /r "${BUILT}\panda3d\bullet${EXT_SUFFIX}"
             SkipBulletPyd:
             SkipBulletPyd:
         !endif
         !endif
 
 
@@ -345,7 +356,7 @@ SectionGroup "Python support"
             SectionGetFlags ${SecODE} $R0
             SectionGetFlags ${SecODE} $R0
             IntOp $R0 $R0 & ${SF_SELECTED}
             IntOp $R0 $R0 & ${SF_SELECTED}
             StrCmp $R0 ${SF_SELECTED} 0 SkipODEPyd
             StrCmp $R0 ${SF_SELECTED} 0 SkipODEPyd
-            File /nonfatal /r "${BUILT}\panda3d\ode.pyd"
+            File /nonfatal /r "${BUILT}\panda3d\ode${EXT_SUFFIX}"
             SkipODEPyd:
             SkipODEPyd:
         !endif
         !endif
 
 
@@ -353,7 +364,7 @@ SectionGroup "Python support"
             SectionGetFlags ${SecPhysX} $R0
             SectionGetFlags ${SecPhysX} $R0
             IntOp $R0 $R0 & ${SF_SELECTED}
             IntOp $R0 $R0 & ${SF_SELECTED}
             StrCmp $R0 ${SF_SELECTED} 0 SkipPhysXPyd
             StrCmp $R0 ${SF_SELECTED} 0 SkipPhysXPyd
-            File /nonfatal /r "${BUILT}\panda3d\physx.pyd"
+            File /nonfatal /r "${BUILT}\panda3d\physx${EXT_SUFFIX}"
             SkipPhysXPyd:
             SkipPhysXPyd:
         !endif
         !endif
 
 
@@ -361,7 +372,7 @@ SectionGroup "Python support"
             SectionGetFlags ${SecRocket} $R0
             SectionGetFlags ${SecRocket} $R0
             IntOp $R0 $R0 & ${SF_SELECTED}
             IntOp $R0 $R0 & ${SF_SELECTED}
             StrCmp $R0 ${SF_SELECTED} 0 SkipRocketPyd
             StrCmp $R0 ${SF_SELECTED} 0 SkipRocketPyd
-            File /nonfatal /r "${BUILT}\panda3d\rocket.pyd"
+            File /nonfatal /r "${BUILT}\panda3d\rocket${EXT_SUFFIX}"
             SkipRocketPyd:
             SkipRocketPyd:
         !endif
         !endif
 
 
@@ -589,7 +600,6 @@ Section "3ds Max plug-ins" SecMaxPlugins
     File /nonfatal /r "${BUILT}\plugins\*.dle"
     File /nonfatal /r "${BUILT}\plugins\*.dle"
     File /nonfatal /r "${BUILT}\plugins\*.dlo"
     File /nonfatal /r "${BUILT}\plugins\*.dlo"
     File /nonfatal /r "${BUILT}\plugins\*.ms"
     File /nonfatal /r "${BUILT}\plugins\*.ms"
-    File "${SOURCE}\doc\INSTALLING-PLUGINS.TXT"
 SectionEnd
 SectionEnd
 !endif
 !endif
 
 
@@ -604,7 +614,6 @@ Section "Maya plug-ins" SecMayaPlugins
     SetOutPath $INSTDIR\plugins
     SetOutPath $INSTDIR\plugins
     File /nonfatal /r "${BUILT}\plugins\*.mll"
     File /nonfatal /r "${BUILT}\plugins\*.mll"
     File /nonfatal /r "${BUILT}\plugins\*.mel"
     File /nonfatal /r "${BUILT}\plugins\*.mel"
-    File "${SOURCE}\doc\INSTALLING-PLUGINS.TXT"
 SectionEnd
 SectionEnd
 !endif
 !endif
 
 

+ 6 - 1
makepanda/installpanda.py

@@ -175,6 +175,7 @@ def InstallPanda(destdir="", prefix="/usr", outputdir="built", libdir=GetLibDir(
     oscmd("mkdir -m 0755 -p "+destdir+prefix+"/share/applications")
     oscmd("mkdir -m 0755 -p "+destdir+prefix+"/share/applications")
     oscmd("mkdir -m 0755 -p "+destdir+libdir+"/panda3d")
     oscmd("mkdir -m 0755 -p "+destdir+libdir+"/panda3d")
     oscmd("mkdir -m 0755 -p "+destdir+PPATH)
     oscmd("mkdir -m 0755 -p "+destdir+PPATH)
+    oscmd("mkdir -m 0755 -p "+destdir+PPATH+"/panda3d")
 
 
     if (sys.platform.startswith("freebsd")):
     if (sys.platform.startswith("freebsd")):
         oscmd("mkdir -m 0755 -p "+destdir+prefix+"/etc")
         oscmd("mkdir -m 0755 -p "+destdir+prefix+"/etc")
@@ -194,13 +195,17 @@ def InstallPanda(destdir="", prefix="/usr", outputdir="built", libdir=GetLibDir(
 
 
     oscmd("cp -R "+outputdir+"/include          "+destdir+prefix+"/include/panda3d")
     oscmd("cp -R "+outputdir+"/include          "+destdir+prefix+"/include/panda3d")
     oscmd("cp -R "+outputdir+"/pandac           "+destdir+prefix+"/share/panda3d/")
     oscmd("cp -R "+outputdir+"/pandac           "+destdir+prefix+"/share/panda3d/")
-    oscmd("cp -R "+outputdir+"/panda3d          "+destdir+PPATH+"/")
     oscmd("cp -R "+outputdir+"/models           "+destdir+prefix+"/share/panda3d/")
     oscmd("cp -R "+outputdir+"/models           "+destdir+prefix+"/share/panda3d/")
     if os.path.isdir("samples"):             oscmd("cp -R samples               "+destdir+prefix+"/share/panda3d/")
     if os.path.isdir("samples"):             oscmd("cp -R samples               "+destdir+prefix+"/share/panda3d/")
     if os.path.isdir(outputdir+"/direct"):   oscmd("cp -R "+outputdir+"/direct           "+destdir+prefix+"/share/panda3d/")
     if os.path.isdir(outputdir+"/direct"):   oscmd("cp -R "+outputdir+"/direct           "+destdir+prefix+"/share/panda3d/")
     if os.path.isdir(outputdir+"/Pmw"):      oscmd("cp -R "+outputdir+"/Pmw     "+destdir+prefix+"/share/panda3d/")
     if os.path.isdir(outputdir+"/Pmw"):      oscmd("cp -R "+outputdir+"/Pmw     "+destdir+prefix+"/share/panda3d/")
     if os.path.isdir(outputdir+"/plugins"):  oscmd("cp -R "+outputdir+"/plugins "+destdir+prefix+"/share/panda3d/")
     if os.path.isdir(outputdir+"/plugins"):  oscmd("cp -R "+outputdir+"/plugins "+destdir+prefix+"/share/panda3d/")
 
 
+    suffix = GetExtensionSuffix()
+    for base in os.listdir(outputdir + "/panda3d"):
+        if base.endswith(".py") or (base.endswith(suffix) and '.' not in base[:-len(suffix)]):
+            oscmd("cp "+outputdir+"/panda3d/"+base+" "+destdir+PPATH+"/panda3d/"+base)
+
     WriteMimeFile(destdir+prefix+"/share/mime-info/panda3d.mime", MIME_INFO)
     WriteMimeFile(destdir+prefix+"/share/mime-info/panda3d.mime", MIME_INFO)
     WriteKeysFile(destdir+prefix+"/share/mime-info/panda3d.keys", MIME_INFO)
     WriteKeysFile(destdir+prefix+"/share/mime-info/panda3d.keys", MIME_INFO)
     WriteMimeXMLFile(destdir+prefix+"/share/mime/packages/panda3d.xml", MIME_INFO)
     WriteMimeXMLFile(destdir+prefix+"/share/mime/packages/panda3d.xml", MIME_INFO)

File diff suppressed because it is too large
+ 222 - 262
makepanda/makepanda.py


+ 128 - 9
makepanda/makepandacore.py

@@ -3190,6 +3190,48 @@ def WriteResourceFile(basename, **kwargs):
     ConditionalWriteFile(basename, GenerateResourceFile(**kwargs))
     ConditionalWriteFile(basename, GenerateResourceFile(**kwargs))
     return basename
     return basename
 
 
+
+def WriteEmbeddedStringFile(basename, inputs, string_name=None):
+    if os.path.splitext(basename)[1] not in SUFFIX_INC:
+        basename += '.cxx'
+    target = GetOutputDir() + "/tmp/" + basename
+
+    if string_name is None:
+        string_name = os.path.basename(os.path.splitext(target)[0])
+        string_name = string_name.replace('-', '_')
+
+    data = bytearray()
+    for input in inputs:
+        fp = open(input, 'rb')
+
+        # Insert a #line so that we get meaningful compile/assert errors when
+        # the result is inserted by interrogate_module into generated code.
+        if os.path.splitext(input)[1] in SUFFIX_INC:
+            line = '#line 1 "%s"\n' % (input)
+            data += bytearray(line.encode('ascii', 'replace'))
+
+        data += bytearray(fp.read())
+        fp.close()
+
+    data.append(0)
+
+    output = 'extern const char %s[] = {\n' % (string_name)
+
+    i = 0
+    for byte in data:
+        if i == 0:
+            output += ' '
+
+        output += ' 0x%02x,' % (byte)
+        i += 1
+        if i >= 12:
+            output += '\n'
+            i = 0
+
+    output += '\n};\n'
+    ConditionalWriteFile(target, output)
+    return target
+
 ########################################################################
 ########################################################################
 ##
 ##
 ## FindLocation
 ## FindLocation
@@ -3197,6 +3239,8 @@ def WriteResourceFile(basename, **kwargs):
 ########################################################################
 ########################################################################
 
 
 ORIG_EXT = {}
 ORIG_EXT = {}
+PYABI_SPECIFIC = set()
+WARNED_FILES = set()
 
 
 def GetOrigExt(x):
 def GetOrigExt(x):
     return ORIG_EXT[x]
     return ORIG_EXT[x]
@@ -3207,14 +3251,42 @@ def SetOrigExt(x, v):
 def GetExtensionSuffix():
 def GetExtensionSuffix():
     if sys.version_info >= (3, 0):
     if sys.version_info >= (3, 0):
         suffix = sysconfig.get_config_var('EXT_SUFFIX')
         suffix = sysconfig.get_config_var('EXT_SUFFIX')
-        if suffix:
+        if suffix == '.so':
+            # On my FreeBSD system, this is not set correctly, but SOABI is.
+            soabi = sysconfig.get_config_var('SOABI')
+            if soabi:
+                return '.%s.so' % (soabi)
+        elif suffix:
             return suffix
             return suffix
+
     target = GetTarget()
     target = GetTarget()
     if target == 'windows':
     if target == 'windows':
         return '.pyd'
         return '.pyd'
     else:
     else:
         return '.so'
         return '.so'
 
 
+def GetPythonABI():
+    soabi = sysconfig.get_config_var('SOABI')
+    if soabi:
+        return soabi
+
+    soabi = 'cpython-%d%d' % (sys.version_info[:2])
+
+    debug_flag = sysconfig.get_config_var('Py_DEBUG')
+    if (debug_flag is None and hasattr(sys, 'gettotalrefcount')) or debug_flag:
+        soabi += 'd'
+
+    malloc_flag = sysconfig.get_config_var('WITH_PYMALLOC')
+    if malloc_flag is None or malloc_flag:
+        soabi += 'm'
+
+    if sys.version_info < (3, 3):
+        usize = sysconfig.get_config_var('Py_UNICODE_SIZE')
+        if (usize is None and sys.maxunicode == 0x10ffff) or usize == 4:
+            soabi += 'u'
+
+    return soabi
+
 def CalcLocation(fn, ipath):
 def CalcLocation(fn, ipath):
     if fn.startswith("panda3d/") and fn.endswith(".py"):
     if fn.startswith("panda3d/") and fn.endswith(".py"):
         return OUTPUTDIR + "/" + fn
         return OUTPUTDIR + "/" + fn
@@ -3285,11 +3357,25 @@ def CalcLocation(fn, ipath):
     return fn
     return fn
 
 
 
 
-def FindLocation(fn, ipath):
+def FindLocation(fn, ipath, pyabi=None):
     if (GetLinkAllStatic() and fn.endswith(".dll")):
     if (GetLinkAllStatic() and fn.endswith(".dll")):
         fn = fn[:-4] + ".lib"
         fn = fn[:-4] + ".lib"
     loc = CalcLocation(fn, ipath)
     loc = CalcLocation(fn, ipath)
     base, ext = os.path.splitext(fn)
     base, ext = os.path.splitext(fn)
+
+    # If this is a target created with PyTargetAdd, we need to make sure it
+    # it put in a Python-version-specific directory.
+    if loc in PYABI_SPECIFIC:
+        if loc.startswith(OUTPUTDIR + "/tmp"):
+            if pyabi is not None:
+                loc = OUTPUTDIR + "/tmp/" + pyabi + loc[len(OUTPUTDIR) + 4:]
+            else:
+                raise RuntimeError("%s is a Python-specific target, use PyTargetAdd instead of TargetAdd" % (fn))
+
+        elif ext != ".pyd" and loc not in WARNED_FILES:
+            WARNED_FILES.add(loc)
+            print("%sWARNING:%s file depends on Python but is not in an ABI-specific directory: %s%s%s" % (GetColor("red"), GetColor(), GetColor("green"), loc, GetColor()))
+
     ORIG_EXT[loc] = ext
     ORIG_EXT[loc] = ext
     return loc
     return loc
 
 
@@ -3335,6 +3421,11 @@ def FindLocation(fn, ipath):
 ## be inserted: bison generates an OBJ and a secondary header
 ## be inserted: bison generates an OBJ and a secondary header
 ## file, interrogate generates an IN and a secondary IGATE.OBJ.
 ## file, interrogate generates an IN and a secondary IGATE.OBJ.
 ##
 ##
+## PyTargetAdd is a special version for targets that depend on Python.
+## It will create a target for each Python version we are building with,
+## ensuring that builds with different Python versions won't conflict
+## when we build for multiple Python ABIs side-by-side.
+##
 ########################################################################
 ########################################################################
 
 
 class Target:
 class Target:
@@ -3343,7 +3434,7 @@ class Target:
 TARGET_LIST = []
 TARGET_LIST = []
 TARGET_TABLE = {}
 TARGET_TABLE = {}
 
 
-def TargetAdd(target, dummy=0, opts=[], input=[], dep=[], ipath=None, winrc=None):
+def TargetAdd(target, dummy=0, opts=[], input=[], dep=[], ipath=None, winrc=None, pyabi=None):
     if (dummy != 0):
     if (dummy != 0):
         exit("Syntax error in TargetAdd "+target)
         exit("Syntax error in TargetAdd "+target)
     if ipath is None: ipath = opts
     if ipath is None: ipath = opts
@@ -3351,11 +3442,10 @@ def TargetAdd(target, dummy=0, opts=[], input=[], dep=[], ipath=None, winrc=None
     if (type(input) == str): input = [input]
     if (type(input) == str): input = [input]
     if (type(dep) == str): dep = [dep]
     if (type(dep) == str): dep = [dep]
 
 
-    if os.path.splitext(target)[1] == '.pyd' and PkgSkip("PYTHON"):
-        # It makes no sense to build Python modules with python disabled.
-        return
+    if target.endswith(".pyd") and not pyabi:
+        raise RuntimeError("Use PyTargetAdd to build .pyd targets")
 
 
-    full = FindLocation(target, [OUTPUTDIR + "/include"])
+    full = FindLocation(target, [OUTPUTDIR + "/include"], pyabi=pyabi)
 
 
     if (full not in TARGET_TABLE):
     if (full not in TARGET_TABLE):
         t = Target()
         t = Target()
@@ -3374,7 +3464,7 @@ def TargetAdd(target, dummy=0, opts=[], input=[], dep=[], ipath=None, winrc=None
 
 
     ipath = [OUTPUTDIR + "/tmp"] + GetListOption(ipath, "DIR:") + [OUTPUTDIR+"/include"]
     ipath = [OUTPUTDIR + "/tmp"] + GetListOption(ipath, "DIR:") + [OUTPUTDIR+"/include"]
     for x in input:
     for x in input:
-        fullinput = FindLocation(x, ipath)
+        fullinput = FindLocation(x, ipath, pyabi=pyabi)
         t.inputs.append(fullinput)
         t.inputs.append(fullinput)
         # Don't re-link a library or binary if just its dependency dlls have been altered.
         # Don't re-link a library or binary if just its dependency dlls have been altered.
         # This should work out fine in most cases, and often reduces recompilation time.
         # This should work out fine in most cases, and often reduces recompilation time.
@@ -3413,7 +3503,7 @@ def TargetAdd(target, dummy=0, opts=[], input=[], dep=[], ipath=None, winrc=None
                 t.deps[fulln] = 1
                 t.deps[fulln] = 1
 
 
     for x in dep:
     for x in dep:
-        fulldep = FindLocation(x, ipath)
+        fulldep = FindLocation(x, ipath, pyabi=pyabi)
         t.deps[fulldep] = 1
         t.deps[fulldep] = 1
 
 
     if winrc and GetTarget() == 'windows':
     if winrc and GetTarget() == 'windows':
@@ -3430,3 +3520,32 @@ def TargetAdd(target, dummy=0, opts=[], input=[], dep=[], ipath=None, winrc=None
 
 
     if target.endswith(".pz") and not CrossCompiling():
     if target.endswith(".pz") and not CrossCompiling():
         t.deps[FindLocation("pzip.exe", [])] = 1
         t.deps[FindLocation("pzip.exe", [])] = 1
+
+    if target.endswith(".in"):
+        # Also add a target to compile the _igate.cxx file into an _igate.obj.
+        outbase = os.path.basename(target)[:-3]
+        woutc = OUTPUTDIR + "/tmp/" + outbase + "_igate.cxx"
+        CxxDependencyCache[woutc] = []
+        PyTargetAdd(outbase + "_igate.obj", opts=opts+['PYTHON','BIGOBJ'], input=woutc, dep=target)
+
+
+def PyTargetAdd(target, opts=[], **kwargs):
+    if PkgSkip("PYTHON"):
+        return
+
+    if 'PYTHON' not in opts:
+        opts = opts + ['PYTHON']
+
+    abi = GetPythonABI()
+
+    MakeDirectory(OUTPUTDIR + "/tmp/" + abi)
+
+    # Mark this target as being a Python-specific target.
+    orig = CalcLocation(target, [OUTPUTDIR + "/include"])
+    PYABI_SPECIFIC.add(orig)
+
+    if orig.startswith(OUTPUTDIR + "/tmp/") and os.path.exists(orig):
+        print("Removing file %s" % (orig))
+        os.unlink(orig)
+
+    TargetAdd(target, opts=opts, pyabi=abi, **kwargs)

+ 1 - 1
makepanda/makewheel.py

@@ -498,7 +498,7 @@ __version__ = '{0}'
     for file in os.listdir(panda3d_dir):
     for file in os.listdir(panda3d_dir):
         if file == '__init__.py':
         if file == '__init__.py':
             pass
             pass
-        elif file.endswith(ext_suffix) or file.endswith('.py'):
+        elif file.endswith('.py') or (file.endswith(ext_suffix) and '.' not in file[:-len(ext_suffix)]):
             source_path = os.path.join(panda3d_dir, file)
             source_path = os.path.join(panda3d_dir, file)
 
 
             if file.endswith('.pyd') and platform.startswith('cygwin'):
             if file.endswith('.pyd') and platform.startswith('cygwin'):

+ 1 - 1
panda/src/audiotraits/fmodAudioSound.cxx

@@ -651,7 +651,7 @@ get_3d_max_distance() const {
  * a balance [pan] function what is the point?
  * a balance [pan] function what is the point?
  */
  */
 PN_stdfloat FmodAudioSound::
 PN_stdfloat FmodAudioSound::
-get_speaker_mix(AudioManager::SpeakerId speaker) {
+get_speaker_mix(int speaker) {
   ReMutexHolder holder(FmodAudioManager::_lock);
   ReMutexHolder holder(FmodAudioManager::_lock);
   if (_channel == 0) {
   if (_channel == 0) {
     return 0.0;
     return 0.0;

+ 1 - 1
panda/src/audiotraits/fmodAudioSound.h

@@ -126,7 +126,7 @@ public:
 
 
   AudioSound::SoundStatus status() const;
   AudioSound::SoundStatus status() const;
 
 
-  virtual PN_stdfloat get_speaker_mix(AudioManager::SpeakerId speaker);
+  virtual PN_stdfloat get_speaker_mix(int speaker);
   virtual void set_speaker_mix(PN_stdfloat frontleft, PN_stdfloat frontright, PN_stdfloat center, PN_stdfloat sub, PN_stdfloat backleft, PN_stdfloat backright, PN_stdfloat sideleft, PN_stdfloat  sideright);
   virtual void set_speaker_mix(PN_stdfloat frontleft, PN_stdfloat frontright, PN_stdfloat center, PN_stdfloat sub, PN_stdfloat backleft, PN_stdfloat backright, PN_stdfloat sideleft, PN_stdfloat  sideright);
 
 
   void set_active(bool active=true);
   void set_active(bool active=true);

+ 9 - 4
panda/src/collide/collisionHandlerQueue.cxx

@@ -22,10 +22,15 @@ class CollisionEntrySorter {
 public:
 public:
   CollisionEntrySorter(CollisionEntry *entry) {
   CollisionEntrySorter(CollisionEntry *entry) {
     _entry = entry;
     _entry = entry;
-    LVector3 vec =
-      entry->get_surface_point(entry->get_from_node_path()) -
-      entry->get_from()->get_collision_origin();
-    _dist2 = vec.length_squared();
+    if (entry->has_surface_point()) {
+      LVector3 vec =
+        entry->get_surface_point(entry->get_from_node_path()) -
+        entry->get_from()->get_collision_origin();
+      _dist2 = vec.length_squared();
+    }
+    else {
+      _dist2 = make_inf((PN_stdfloat)0);
+    }
   }
   }
   bool operator < (const CollisionEntrySorter &other) const {
   bool operator < (const CollisionEntrySorter &other) const {
     return _dist2 < other._dist2;
     return _dist2 < other._dist2;

+ 0 - 10
panda/src/configfiles/panda.init

@@ -1,10 +0,0 @@
-SETABS PANDA_VER 0.8
-MODREL ETC_PATH built/etc
-DOCSH if ( ! $?CFG_PATH ) then
-DOCSH   setenv CFG_PATH ~
-DOCSH   setenv CFG_PATH ". ${CFG_PATH} /usr/local/etc"
-DOCSH endif
-DOSH if [ -z "$CFG_PATH" ]; then
-DOSH   CFG_PATH=". $HOME /usr/local/etc"
-DOSH   export CFG_PATH
-DOSH fi

+ 0 - 1
panda/src/dxgsg9/dxgsg9base.h

@@ -211,7 +211,6 @@ struct DXScreenData {
   bool _is_tnl_device;
   bool _is_tnl_device;
   bool _can_use_hw_vertex_shaders;
   bool _can_use_hw_vertex_shaders;
   bool _can_use_pixel_shaders;
   bool _can_use_pixel_shaders;
-  bool _is_dx9_1;
   UINT _supported_screen_depths_mask;
   UINT _supported_screen_depths_mask;
   UINT _supported_tex_formats_mask;
   UINT _supported_tex_formats_mask;
   bool _supports_rgba16f_texture_format;
   bool _supports_rgba16f_texture_format;

+ 8 - 26
panda/src/dxgsg9/wdxGraphicsPipe9.cxx

@@ -193,30 +193,10 @@ init() {
   }
   }
 
 
   // Create a Direct3D object.
   // Create a Direct3D object.
+  __d3d9 = (*_Direct3DCreate9)(D3D_SDK_VERSION);
 
 
-  // these were taken from the 8.0 and 8.1 d3d8.h SDK headers
-    __is_dx9_1 = false;
-
-#define D3D_SDK_VERSION_9_0 D3D_SDK_VERSION
-#define D3D_SDK_VERSION_9_1 D3D_SDK_VERSION
-
-  // are we using 9.0 or 9.1?
-  WIN32_FIND_DATA TempFindData;
-  HANDLE hFind;
-  char tmppath[_MAX_PATH + 128];
-  GetSystemDirectory(tmppath, MAX_PATH);
-  strcat(tmppath, "\\dpnhpast.dll");
-  hFind = FindFirstFile (tmppath, &TempFindData);
-  if (hFind != INVALID_HANDLE_VALUE) {
-    FindClose(hFind);
-// ??? This was from DX8 __is_dx9_1 = true;
-    __d3d9 = (*_Direct3DCreate9)(D3D_SDK_VERSION_9_1);
-  } else {
-    __is_dx9_1 = false;
-    __d3d9 = (*_Direct3DCreate9)(D3D_SDK_VERSION_9_0);
-  }
   if (__d3d9 == nullptr) {
   if (__d3d9 == nullptr) {
-    wdxdisplay9_cat.error() << "Direct3DCreate9(9." << (__is_dx9_1 ? "1" : "0") << ") failed!, error = " << GetLastError() << endl;
+    wdxdisplay9_cat.error() << "Direct3DCreate9 failed!, error = " << GetLastError() << endl;
     // release_gsg();
     // release_gsg();
     goto error;
     goto error;
   }
   }
@@ -361,11 +341,13 @@ find_all_card_memavails() {
       if (!ISPOW2(dwVidMemTotal)) {
       if (!ISPOW2(dwVidMemTotal)) {
         // assume they wont return a proper max value, so round up to next pow
         // assume they wont return a proper max value, so round up to next pow
         // of 2
         // of 2
-        UINT count = 0;
-        while ((dwVidMemTotal >> count) != 0x0) {
-          count++;
+        int count = get_next_higher_bit((uint32_t)(dwVidMemTotal - 1u));
+        if (count >= 32u) {
+          // Maximum value that fits in a UINT.
+          dwVidMemTotal = 0xffffffffu;
+        } else {
+          dwVidMemTotal = (1u << count);
         }
         }
-        dwVidMemTotal = (1 << count);
       }
       }
     }
     }
 
 

+ 0 - 1
panda/src/dxgsg9/wdxGraphicsPipe9.h

@@ -93,7 +93,6 @@ private:
 
 
   typedef pvector<CardID> CardIDs;
   typedef pvector<CardID> CardIDs;
   CardIDs _card_ids;
   CardIDs _card_ids;
-  bool __is_dx9_1;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 1 - 2
panda/src/dxgsg9/wdxGraphicsWindow9.cxx

@@ -878,7 +878,7 @@ choose_device() {
     LARGE_INTEGER *DrvVer = &adapter_info.DriverVersion;
     LARGE_INTEGER *DrvVer = &adapter_info.DriverVersion;
 
 
     wdxdisplay9_cat.info()
     wdxdisplay9_cat.info()
-      << "D3D9." << (dxpipe->__is_dx9_1 ?"1":"0") << " Adapter[" << i << "]: " << adapter_info.Description
+      << "D3D9 Adapter[" << i << "]: " << adapter_info.Description
       << ", Driver: " << adapter_info.Driver << ", DriverVersion: ("
       << ", Driver: " << adapter_info.Driver << ", DriverVersion: ("
       << HIWORD(DrvVer->HighPart) << "." << LOWORD(DrvVer->HighPart) << "."
       << HIWORD(DrvVer->HighPart) << "." << LOWORD(DrvVer->HighPart) << "."
       << HIWORD(DrvVer->LowPart) << "." << LOWORD(DrvVer->LowPart)
       << HIWORD(DrvVer->LowPart) << "." << LOWORD(DrvVer->LowPart)
@@ -979,7 +979,6 @@ consider_device(wdxGraphicsPipe9 *dxpipe, DXDeviceInfo *device_info) {
 
 
   nassertr(_dxgsg != nullptr, false);
   nassertr(_dxgsg != nullptr, false);
   _wcontext._d3d9 = _d3d9;
   _wcontext._d3d9 = _d3d9;
-  _wcontext._is_dx9_1 = dxpipe->__is_dx9_1;
   _wcontext._card_id = device_info->cardID;  // could this change by end?
   _wcontext._card_id = device_info->cardID;  // could this change by end?
 
 
   bool bWantStencil = (_fb_properties.get_stencil_bits() > 0);
   bool bWantStencil = (_fb_properties.get_stencil_bits() > 0);

+ 1 - 8
panda/src/event/asyncFuture_ext.cxx

@@ -168,14 +168,7 @@ static PyObject *gen_next(PyObject *self) {
  */
  */
 PyObject *Extension<AsyncFuture>::
 PyObject *Extension<AsyncFuture>::
 __await__(PyObject *self) {
 __await__(PyObject *self) {
-  Dtool_GeneratorWrapper *gen;
-  gen = (Dtool_GeneratorWrapper *)PyType_GenericAlloc(&Dtool_GeneratorWrapper_Type, 0);
-  if (gen != nullptr) {
-    Py_INCREF(self);
-    gen->_base._self = self;
-    gen->_iternext_func = &gen_next;
-  }
-  return (PyObject *)gen;
+  return Dtool_NewGenerator(self, &gen_next);
 }
 }
 
 
 /**
 /**

+ 1 - 1
panda/src/event/asyncFuture_ext.h

@@ -16,7 +16,7 @@
 
 
 #include "extension.h"
 #include "extension.h"
 #include "py_panda.h"
 #include "py_panda.h"
-#include "modelLoadRequest.h"
+#include "asyncFuture.h"
 
 
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
 
 

+ 0 - 8
panda/src/express/config_express.cxx

@@ -190,11 +190,3 @@ get_verify_dcast() {
 
 
   return *verify_dcast;
   return *verify_dcast;
 }
 }
-
-// Returns the configure object for accessing config variables from a
-// scripting language.
-DConfig &
-get_config_express() {
-  static DConfig config_express;
-  return config_express;
-}

+ 0 - 5
panda/src/express/config_express.h

@@ -54,11 +54,6 @@ extern ConfigVariableBool multifile_always_binary;
 extern EXPCL_PANDA_EXPRESS ConfigVariableBool collect_tcp;
 extern EXPCL_PANDA_EXPRESS ConfigVariableBool collect_tcp;
 extern EXPCL_PANDA_EXPRESS ConfigVariableDouble collect_tcp_interval;
 extern EXPCL_PANDA_EXPRESS ConfigVariableDouble collect_tcp_interval;
 
 
-// Expose the Config variable for Python access.
-BEGIN_PUBLISH
-EXPCL_PANDA_EXPRESS DConfig &get_config_express();
-END_PUBLISH
-
 extern EXPCL_PANDA_EXPRESS void init_libexpress();
 extern EXPCL_PANDA_EXPRESS void init_libexpress();
 
 
 #endif /* __CONFIG_UTIL_H__ */
 #endif /* __CONFIG_UTIL_H__ */

+ 2 - 0
panda/src/express/virtualFileSystem.cxx

@@ -22,6 +22,8 @@
 #include "dSearchPath.h"
 #include "dSearchPath.h"
 #include "dcast.h"
 #include "dcast.h"
 #include "config_express.h"
 #include "config_express.h"
+#include "configVariableList.h"
+#include "configVariableString.h"
 #include "executionEnvironment.h"
 #include "executionEnvironment.h"
 #include "pset.h"
 #include "pset.h"
 
 

+ 72 - 0
panda/src/glstuff/glShaderContext_src.cxx

@@ -1145,6 +1145,78 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
       }
       }
       return;
       return;
     }
     }
+    if (size > 4 && noprefix.substr(0, 4) == "Fog.") {
+      Shader::ShaderMatSpec bind;
+      bind._id = arg_id;
+      bind._func = Shader::SMF_first;
+      bind._arg[0] = nullptr;
+      bind._dep[0] = Shader::SSD_general | Shader::SSD_fog;
+      bind._part[1] = Shader::SMO_identity;
+      bind._arg[1] = nullptr;
+      bind._dep[1] = Shader::SSD_NONE;
+
+      if (noprefix == "Fog.color") {
+        bind._part[0] = Shader::SMO_attr_fogcolor;
+
+        if (param_type == GL_FLOAT_VEC3) {
+          bind._piece = Shader::SMP_row3x3;
+        } else if (param_type == GL_FLOAT_VEC4) {
+          bind._piece = Shader::SMP_row3;
+        } else {
+          GLCAT.error()
+            << "p3d_Fog.color should be vec3 or vec4\n";
+          return;
+        }
+
+      } else if (noprefix == "Fog.density") {
+        bind._part[0] = Shader::SMO_attr_fog;
+
+        if (param_type == GL_FLOAT) {
+          bind._piece = Shader::SMP_row3x1;
+        } else {
+          GLCAT.error()
+            << "p3d_Fog.density should be float\n";
+          return;
+        }
+
+      } else if (noprefix == "Fog.start") {
+        bind._part[0] = Shader::SMO_attr_fog;
+
+        if (param_type == GL_FLOAT) {
+          bind._piece = Shader::SMP_cell13;
+        } else {
+          GLCAT.error()
+            << "p3d_Fog.start should be float\n";
+          return;
+        }
+
+      } else if (noprefix == "Fog.end") {
+        bind._part[0] = Shader::SMO_attr_fog;
+
+        if (param_type == GL_FLOAT) {
+          bind._piece = Shader::SMP_cell14;
+        } else {
+          GLCAT.error()
+            << "p3d_Fog.end should be float\n";
+          return;
+        }
+
+      } else if (noprefix == "Fog.scale") {
+        bind._part[0] = Shader::SMO_attr_fog;
+
+        if (param_type == GL_FLOAT) {
+          bind._piece = Shader::SMP_cell15;
+        } else {
+          GLCAT.error()
+            << "p3d_Fog.scale should be float\n";
+          return;
+        }
+      }
+
+      _shader->_mat_spec.push_back(bind);
+      _shader->_mat_deps |= bind._dep[0];
+      return;
+    }
     if (noprefix == "LightModel.ambient") {
     if (noprefix == "LightModel.ambient") {
       Shader::ShaderMatSpec bind;
       Shader::ShaderMatSpec bind;
       bind._id = arg_id;
       bind._id = arg_id;

+ 1 - 5
panda/src/gobj/internalName.h

@@ -96,11 +96,7 @@ PUBLISHED:
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
   // These versions are exposed to Python, which have additional logic to map
   // These versions are exposed to Python, which have additional logic to map
   // from Python interned strings.
   // from Python interned strings.
-#if PY_MAJOR_VERSION >= 3
-  EXTENSION(static PT(InternalName) make(PyUnicodeObject *str));
-#else
-  EXTENSION(static PT(InternalName) make(PyStringObject *str));
-#endif
+  EXTENSION(static PT(InternalName) make(PyObject *str));
 #endif
 #endif
 
 
 public:
 public:

+ 12 - 2
panda/src/gobj/internalName_ext.cxx

@@ -24,7 +24,12 @@ using std::string;
  */
  */
 #if PY_MAJOR_VERSION >= 3
 #if PY_MAJOR_VERSION >= 3
 PT(InternalName) Extension<InternalName>::
 PT(InternalName) Extension<InternalName>::
-make(PyUnicodeObject *str) {
+make(PyObject *str) {
+  if (!PyUnicode_Check(str)) {
+    Dtool_Raise_ArgTypeError(str, 0, "InternalName.make", "str");
+    return nullptr;
+  }
+
   if (!PyUnicode_CHECK_INTERNED(str)) {
   if (!PyUnicode_CHECK_INTERNED(str)) {
     // Not an interned string; don't bother.
     // Not an interned string; don't bother.
     Py_ssize_t len = 0;
     Py_ssize_t len = 0;
@@ -50,7 +55,12 @@ make(PyUnicodeObject *str) {
 
 
 #else
 #else
 PT(InternalName) Extension<InternalName>::
 PT(InternalName) Extension<InternalName>::
-make(PyStringObject *str) {
+make(PyObject *str) {
+  if (!PyString_Check(str)) {
+    Dtool_Raise_ArgTypeError(str, 0, "InternalName.make", "str");
+    return nullptr;
+  }
+
   if (!PyString_CHECK_INTERNED(str)) {
   if (!PyString_CHECK_INTERNED(str)) {
     // Not an interned string; don't bother.
     // Not an interned string; don't bother.
     string name(PyString_AS_STRING(str), PyString_GET_SIZE(str));
     string name(PyString_AS_STRING(str), PyString_GET_SIZE(str));

+ 1 - 5
panda/src/gobj/internalName_ext.h

@@ -29,11 +29,7 @@
 template<>
 template<>
 class Extension<InternalName> : public ExtensionBase<InternalName> {
 class Extension<InternalName> : public ExtensionBase<InternalName> {
 public:
 public:
-#if PY_MAJOR_VERSION >= 3
-  static PT(InternalName) make(PyUnicodeObject *str);
-#else
-  static PT(InternalName) make(PyStringObject *str);
-#endif
+  static PT(InternalName) make(PyObject *str);
 };
 };
 
 
 #endif  // HAVE_PYTHON
 #endif  // HAVE_PYTHON

+ 285 - 94
panda/src/gobj/shader.cxx

@@ -2468,6 +2468,96 @@ read(const ShaderFile &sfile, BamCacheRecord *record) {
   return true;
   return true;
 }
 }
 
 
+/**
+ * Loads the shader from the given string(s). Returns a boolean indicating
+ * success or failure.
+ */
+bool Shader::
+load(const ShaderFile &sbody, BamCacheRecord *record) {
+  _filename = ShaderFile("created-shader");
+  _fullpath = Filename();
+  _text._separate = sbody._separate;
+
+  if (sbody._separate) {
+    if (_language == SL_none) {
+      shader_cat.error()
+        << "No shader language was specified!\n";
+      return false;
+    }
+
+    if (!sbody._vertex.empty() &&
+        !do_load_source(_text._vertex, sbody._vertex, record)) {
+      return false;
+    }
+    if (!sbody._fragment.empty() &&
+        !do_load_source(_text._fragment, sbody._fragment, record)) {
+      return false;
+    }
+    if (!sbody._geometry.empty() &&
+        !do_load_source(_text._geometry, sbody._geometry, record)) {
+      return false;
+    }
+    if (!sbody._tess_control.empty() &&
+        !do_load_source(_text._tess_control, sbody._tess_control, record)) {
+      return false;
+    }
+    if (!sbody._tess_evaluation.empty() &&
+        !do_load_source(_text._tess_evaluation, sbody._tess_evaluation, record)) {
+      return false;
+    }
+    if (!sbody._compute.empty() &&
+        !do_load_source(_text._compute, sbody._compute, record)) {
+      return false;
+    }
+
+  } else {
+    if (!do_load_source(_text._shared, sbody._shared, record)) {
+      return false;
+    }
+
+    // Determine which language the shader is written in.
+    if (_language == SL_none) {
+      string header;
+      parse_init();
+      parse_line(header, true, true);
+      if (header == "//Cg") {
+        _language = SL_Cg;
+      } else {
+        shader_cat.error()
+          << "Unable to determine shader language of " << sbody._shared << "\n";
+        return false;
+      }
+    } else if (_language == SL_GLSL) {
+      shader_cat.error()
+        << "GLSL shaders must have separate shader bodies!\n";
+      return false;
+    }
+
+    // Determine which language the shader is written in.
+    if (_language == SL_Cg) {
+#ifdef HAVE_CG
+      cg_get_profile_from_header(_default_caps);
+
+      if (!cg_analyze_shader(_default_caps)) {
+        shader_cat.error()
+          << "Shader encountered an error.\n";
+        return false;
+      }
+#else
+      shader_cat.error()
+        << "Tried to load Cg shader, but no Cg support is enabled.\n";
+#endif
+    } else {
+      shader_cat.error()
+        << "Shader is not in a supported shader-language.\n";
+      return false;
+    }
+  }
+
+  _loaded = true;
+  return true;
+}
+
 /**
 /**
  * Reads the shader file from the given path into the given string.
  * Reads the shader file from the given path into the given string.
  *
  *
@@ -2476,37 +2566,85 @@ read(const ShaderFile &sfile, BamCacheRecord *record) {
  */
  */
 bool Shader::
 bool Shader::
 do_read_source(string &into, const Filename &fn, BamCacheRecord *record) {
 do_read_source(string &into, const Filename &fn, BamCacheRecord *record) {
+  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
+  PT(VirtualFile) vf = vfs->find_file(fn, get_model_path());
+  if (vf == nullptr) {
+    shader_cat.error()
+      << "Could not find shader file: " << fn << "\n";
+    return false;
+  }
+
   if (_language == SL_GLSL && glsl_preprocess) {
   if (_language == SL_GLSL && glsl_preprocess) {
+    istream *source = vf->open_read_file(true);
+    if (source == nullptr) {
+      shader_cat.error()
+        << "Could not open shader file: " << fn << "\n";
+      return false;
+    }
+
     // Preprocess the GLSL file as we read it.
     // Preprocess the GLSL file as we read it.
+    shader_cat.info()
+      << "Preprocessing shader file: " << fn << "\n";
+
     std::set<Filename> open_files;
     std::set<Filename> open_files;
     ostringstream sstr;
     ostringstream sstr;
-    if (!r_preprocess_source(sstr, fn, Filename(), open_files, record)) {
+    if (!r_preprocess_source(sstr, *source, fn, vf->get_filename(), open_files, record)) {
+      vf->close_read_file(source);
       return false;
       return false;
     }
     }
+    vf->close_read_file(source);
     into = sstr.str();
     into = sstr.str();
 
 
   } else {
   } else {
     shader_cat.info() << "Reading shader file: " << fn << "\n";
     shader_cat.info() << "Reading shader file: " << fn << "\n";
 
 
-    VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
-    PT(VirtualFile) vf = vfs->find_file(fn, get_model_path());
-    if (vf == nullptr) {
-      shader_cat.error()
-        << "Could not find shader file: " << fn << "\n";
-      return false;
-    }
-
     if (!vf->read_file(into, true)) {
     if (!vf->read_file(into, true)) {
       shader_cat.error()
       shader_cat.error()
         << "Could not read shader file: " << fn << "\n";
         << "Could not read shader file: " << fn << "\n";
       return false;
       return false;
     }
     }
+  }
+
+  if (record != nullptr) {
+    record->add_dependent_file(vf);
+  }
 
 
-    if (record != nullptr) {
-      record->add_dependent_file(vf);
+  _last_modified = std::max(_last_modified, vf->get_timestamp());
+  _source_files.push_back(vf->get_filename());
+
+  // Strip trailing whitespace.
+  while (!into.empty() && isspace(into[into.size() - 1])) {
+    into.resize(into.size() - 1);
+  }
+
+  // Except add back a newline at the end, which is needed by Intel drivers.
+  into += "\n";
+
+  return true;
+}
+
+/**
+ * Loads the shader file from the given string into the given string,
+ * performing any pre-processing on it that may be necessary.
+ *
+ * Returns false if there was an error with this shader bad enough to consider
+ * it 'invalid'.
+ */
+bool Shader::
+do_load_source(string &into, const std::string &source, BamCacheRecord *record) {
+  if (_language == SL_GLSL && glsl_preprocess) {
+    // Preprocess the GLSL file as we read it.
+    std::set<Filename> open_files;
+    std::ostringstream sstr;
+    std::istringstream in(source);
+    if (!r_preprocess_source(sstr, in, Filename("created-shader"), Filename(),
+                             open_files, record)) {
+      return false;
     }
     }
-    _last_modified = std::max(_last_modified, vf->get_timestamp());
-    _source_files.push_back(vf->get_filename());
+    into = sstr.str();
+
+  } else {
+    into = source;
   }
   }
 
 
   // Strip trailing whitespace.
   // Strip trailing whitespace.
@@ -2528,10 +2666,10 @@ do_read_source(string &into, const Filename &fn, BamCacheRecord *record) {
  * recursive includes.
  * recursive includes.
  */
  */
 bool Shader::
 bool Shader::
-r_preprocess_source(ostream &out, const Filename &fn,
-                    const Filename &source_dir,
-                    std::set<Filename> &once_files,
-                    BamCacheRecord *record, int depth) {
+r_preprocess_include(ostream &out, const Filename &fn,
+                     const Filename &source_dir,
+                     std::set<Filename> &once_files,
+                     BamCacheRecord *record, int depth) {
 
 
   if (depth > glsl_include_recursion_limit) {
   if (depth > glsl_include_recursion_limit) {
     shader_cat.error()
     shader_cat.error()
@@ -2549,7 +2687,7 @@ r_preprocess_source(ostream &out, const Filename &fn,
   PT(VirtualFile) vf = vfs->find_file(fn, path);
   PT(VirtualFile) vf = vfs->find_file(fn, path);
   if (vf == nullptr) {
   if (vf == nullptr) {
     shader_cat.error()
     shader_cat.error()
-      << "Could not find shader file: " << fn << "\n";
+      << "Could not find shader include: " << fn << "\n";
     return false;
     return false;
   }
   }
 
 
@@ -2562,7 +2700,7 @@ r_preprocess_source(ostream &out, const Filename &fn,
   istream *source = vf->open_read_file(true);
   istream *source = vf->open_read_file(true);
   if (source == nullptr) {
   if (source == nullptr) {
     shader_cat.error()
     shader_cat.error()
-      << "Could not open shader file: " << fn << "\n";
+      << "Could not open shader include: " << fn << "\n";
     return false;
     return false;
   }
   }
 
 
@@ -2578,34 +2716,52 @@ r_preprocess_source(ostream &out, const Filename &fn,
   // than that, unfortunately.  Don't do this for the top-level file, though.
   // than that, unfortunately.  Don't do this for the top-level file, though.
   // We don't want anything to get in before a potential #version directive.
   // We don't want anything to get in before a potential #version directive.
   int fileno = 0;
   int fileno = 0;
-  if (depth > 0) {
-    fileno = 2048 + _included_files.size();
-    // Write it into the vector so that we can substitute it later when we are
-    // parsing the GLSL error log.  Don't store the full filename because it
-    // would just be too long to display.
-    _included_files.push_back(fn);
-
-    out << "#line 1 " << fileno << " // " << fn << "\n";
-    if (shader_cat.is_debug()) {
-      shader_cat.debug()
-        << "Preprocessing shader include " << fileno << ": " << fn << "\n";
-    }
-  } else {
-    shader_cat.info()
-      << "Preprocessing shader file: " << fn << "\n";
+  fileno = 2048 + _included_files.size();
+
+  // Write it into the vector so that we can substitute it later when we are
+  // parsing the GLSL error log.  Don't store the full filename because it
+  // would just be too long to display.
+  _included_files.push_back(fn);
+
+  if (shader_cat.is_debug()) {
+    shader_cat.debug()
+      << "Preprocessing shader include " << fileno << ": " << fn << "\n";
   }
   }
 
 
+  bool result = r_preprocess_source(out, *source, fn, full_fn, once_files, record, fileno, depth);
+  vf->close_read_file(source);
+  return result;
+}
+
+/**
+ * Loads a given GLSL stream line by line, processing any #pragma include and
+ * once statements, as well as removing any comments.
+ *
+ * The set keeps track of which files we have already included, for checking
+ * recursive includes.
+ */
+bool Shader::
+r_preprocess_source(ostream &out, istream &in, const Filename &fn,
+                    const Filename &full_fn, std::set<Filename> &once_files,
+                    BamCacheRecord *record, int fileno, int depth) {
+
   // Iterate over the lines for things we may need to preprocess.
   // Iterate over the lines for things we may need to preprocess.
   string line;
   string line;
   int ext_google_include = 0; // 1 = warn, 2 = enable
   int ext_google_include = 0; // 1 = warn, 2 = enable
   int ext_google_line = 0;
   int ext_google_line = 0;
   bool had_include = false;
   bool had_include = false;
   int lineno = 0;
   int lineno = 0;
-  while (std::getline(*source, line)) {
+  bool write_line_directive = (fileno != 0);
+
+  while (std::getline(in, line)) {
     ++lineno;
     ++lineno;
 
 
     if (line.empty()) {
     if (line.empty()) {
-      out.put('\n');
+      // We still write a newline to make sure the line numbering remains
+      // consistent, unless we are about to write a #line directive anyway.
+      if (!write_line_directive) {
+        out.put('\n');
+      }
       continue;
       continue;
     }
     }
 
 
@@ -2615,9 +2771,11 @@ r_preprocess_source(ostream &out, const Filename &fn,
       line.resize(line.size() - 1);
       line.resize(line.size() - 1);
       string line2;
       string line2;
 
 
-      if (std::getline(*source, line2)) {
+      if (std::getline(in, line2)) {
         line += line2;
         line += line2;
-        out.put('\n');
+        if (!write_line_directive) {
+          out.put('\n');
+        }
         ++lineno;
         ++lineno;
       } else {
       } else {
         break;
         break;
@@ -2644,8 +2802,10 @@ r_preprocess_source(ostream &out, const Filename &fn,
       size_t block_end = line2.find("*/");
       size_t block_end = line2.find("*/");
       while (block_end == string::npos) {
       while (block_end == string::npos) {
         // Didn't find it - look in the next line.
         // Didn't find it - look in the next line.
-        if (std::getline(*source, line2)) {
-          out.put('\n');
+        if (std::getline(in, line2)) {
+          if (!write_line_directive) {
+            out.put('\n');
+          }
           ++lineno;
           ++lineno;
           block_end = line2.find("*/");
           block_end = line2.find("*/");
         } else {
         } else {
@@ -2663,10 +2823,21 @@ r_preprocess_source(ostream &out, const Filename &fn,
       line.resize(line.size() - 1);
       line.resize(line.size() - 1);
     }
     }
 
 
+    if (line.empty()) {
+      if (!write_line_directive) {
+        out.put('\n');
+      }
+      continue;
+    }
+
     // Check if this line contains a #directive.
     // Check if this line contains a #directive.
     char directive[64];
     char directive[64];
     if (line.size() < 8 || sscanf(line.c_str(), " # %63s", directive) != 1) {
     if (line.size() < 8 || sscanf(line.c_str(), " # %63s", directive) != 1) {
       // Nope.  Just pass the line through unmodified.
       // Nope.  Just pass the line through unmodified.
+      if (write_line_directive) {
+        out << "#line " << lineno << " " << fileno << " // " << fn << "\n";
+        write_line_directive = false;
+      }
       out << line << "\n";
       out << line << "\n";
       continue;
       continue;
     }
     }
@@ -2703,7 +2874,7 @@ r_preprocess_source(ostream &out, const Filename &fn,
         }
         }
 
 
         // OK, great.  Process the include.
         // OK, great.  Process the include.
-        if (!r_preprocess_source(out, incfn, source_dir, once_files, record, depth + 1)) {
+        if (!r_preprocess_include(out, incfn, source_dir, once_files, record, depth + 1)) {
           // An error occurred.  Pass on the failure.
           // An error occurred.  Pass on the failure.
           shader_cat.error(false) << "included at line "
           shader_cat.error(false) << "included at line "
             << lineno << " of file " << fn << ":\n  " << line << "\n";
             << lineno << " of file " << fn << ":\n  " << line << "\n";
@@ -2711,8 +2882,9 @@ r_preprocess_source(ostream &out, const Filename &fn,
         }
         }
 
 
         // Restore the line counter.
         // Restore the line counter.
-        out << "#line " << (lineno + 1) << " " << fileno << " // " << fn << "\n";
+        write_line_directive = true;
         had_include = true;
         had_include = true;
+        continue;
 
 
       } else if (strcmp(pragma, "once") == 0) {
       } else if (strcmp(pragma, "once") == 0) {
         // Do a stricter syntax check, just to be extra safe.
         // Do a stricter syntax check, just to be extra safe.
@@ -2724,26 +2896,35 @@ r_preprocess_source(ostream &out, const Filename &fn,
           return false;
           return false;
         }
         }
 
 
-        once_files.insert(full_fn);
+        if (fileno == 0) {
+          shader_cat.warning()
+            << "#pragma once in main file at line "
+            << lineno << " of file " << fn
+#ifndef NDEBUG
+            << ":\n  " << line
+#endif
+            << "\n";
+        }
 
 
-      } else {
-        // Forward it, the driver will ignore it if it doesn't know it.
-        out << line << "\n";
+        if (!full_fn.empty()) {
+          once_files.insert(full_fn);
+        }
+        continue;
       }
       }
+      // Otherwise, just pass it through to the driver.
 
 
     } else if (strcmp(directive, "endif") == 0) {
     } else if (strcmp(directive, "endif") == 0) {
       // Check for an #endif after an include.  We have to restore the line
       // Check for an #endif after an include.  We have to restore the line
       // number in case the include happened under an #if block.
       // number in case the include happened under an #if block.
-      out << line << "\n";
       if (had_include) {
       if (had_include) {
-        out << "#line " << (lineno + 1) << " " << fileno << "\n";
+        write_line_directive = true;
       }
       }
 
 
     } else if (strcmp(directive, "extension") == 0) {
     } else if (strcmp(directive, "extension") == 0) {
       // Check for special preprocessing extensions.
       // Check for special preprocessing extensions.
       char extension[256];
       char extension[256];
       char behavior[9];
       char behavior[9];
-      if (sscanf(line.c_str(), " # extension%*[ \t]%255s%*[ \t]:%*[ \t]%8s", extension, behavior) == 2) {
+      if (sscanf(line.c_str(), " # extension%*[ \t]%255[^: \t] : %8s", extension, behavior) == 2) {
         // Parse the behavior string.
         // Parse the behavior string.
         int mode;
         int mode;
         if (strcmp(behavior, "require") == 0 || strcmp(behavior, "enable") == 0) {
         if (strcmp(behavior, "require") == 0 || strcmp(behavior, "enable") == 0) {
@@ -2769,7 +2950,8 @@ r_preprocess_source(ostream &out, const Filename &fn,
           }
           }
           ext_google_include = mode;
           ext_google_include = mode;
           ext_google_line = mode;
           ext_google_line = mode;
-          out << line << "\n";
+          // Still pass it through to the driver, so it can enable other
+          // extensions.
 
 
         } else if (strcmp(extension, "GL_GOOGLE_include_directive") == 0) {
         } else if (strcmp(extension, "GL_GOOGLE_include_directive") == 0) {
           // Enable the Google extension support for #include statements.
           // Enable the Google extension support for #include statements.
@@ -2777,14 +2959,12 @@ r_preprocess_source(ostream &out, const Filename &fn,
           // This matches the behavior of Khronos' glslang reference compiler.
           // This matches the behavior of Khronos' glslang reference compiler.
           ext_google_include = mode;
           ext_google_include = mode;
           ext_google_line = mode;
           ext_google_line = mode;
+          continue;
 
 
         } else if (strcmp(extension, "GL_GOOGLE_cpp_style_line_directive") == 0) {
         } else if (strcmp(extension, "GL_GOOGLE_cpp_style_line_directive") == 0) {
           // Enables strings in #line statements.
           // Enables strings in #line statements.
           ext_google_line = mode;
           ext_google_line = mode;
-
-        } else {
-          // It's an extension the driver should worry about.
-          out << line << "\n";
+          continue;
         }
         }
       } else {
       } else {
         shader_cat.error()
         shader_cat.error()
@@ -2792,6 +2972,7 @@ r_preprocess_source(ostream &out, const Filename &fn,
           << lineno << " of file " << fn << ":\n  " << line << "\n";
           << lineno << " of file " << fn << ":\n  " << line << "\n";
         return false;
         return false;
       }
       }
+
     } else if (ext_google_include > 0 && strcmp(directive, "include") == 0) {
     } else if (ext_google_include > 0 && strcmp(directive, "include") == 0) {
       // Warn about extension use if requested.
       // Warn about extension use if requested.
       if (ext_google_include == 1) {
       if (ext_google_include == 1) {
@@ -2821,7 +3002,7 @@ r_preprocess_source(ostream &out, const Filename &fn,
 
 
       // OK, great.  Process the include.
       // OK, great.  Process the include.
       Filename source_dir = full_fn.get_dirname();
       Filename source_dir = full_fn.get_dirname();
-      if (!r_preprocess_source(out, incfn, source_dir, once_files, record, depth + 1)) {
+      if (!r_preprocess_include(out, incfn, source_dir, once_files, record, depth + 1)) {
         // An error occurred.  Pass on the failure.
         // An error occurred.  Pass on the failure.
         shader_cat.error(false) << "included at line "
         shader_cat.error(false) << "included at line "
           << lineno << " of file " << fn << ":\n  " << line << "\n";
           << lineno << " of file " << fn << ":\n  " << line << "\n";
@@ -2829,8 +3010,9 @@ r_preprocess_source(ostream &out, const Filename &fn,
       }
       }
 
 
       // Restore the line counter.
       // Restore the line counter.
-      out << "#line " << (lineno + 1) << " " << fileno << " // " << fn << "\n";
+      write_line_directive = true;
       had_include = true;
       had_include = true;
+      continue;
 
 
     } else if (ext_google_line > 0 && strcmp(directive, "line") == 0) {
     } else if (ext_google_line > 0 && strcmp(directive, "line") == 0) {
       // It's a #line directive.  See if it uses a string instead of number.
       // It's a #line directive.  See if it uses a string instead of number.
@@ -2854,18 +3036,17 @@ r_preprocess_source(ostream &out, const Filename &fn,
         _included_files.push_back(Filename(filestr));
         _included_files.push_back(Filename(filestr));
 
 
         out << "#line " << lineno << " " << fileno << " // " << filestr << "\n";
         out << "#line " << lineno << " " << fileno << " // " << filestr << "\n";
-
-      } else {
-        // We couldn't parse the #line directive.  Pass it through unmodified.
-        out << line << "\n";
+        continue;
       }
       }
-    } else {
-      // Different directive (eg. #version).  Leave it untouched.
-      out << line << "\n";
     }
     }
+
+    if (write_line_directive) {
+      out << "#line " << lineno << " " << fileno << " // " << fn << "\n";
+      write_line_directive = false;
+    }
+    out << line << "\n";
   }
   }
 
 
-  vf->close_read_file(source);
   return true;
   return true;
 }
 }
 
 
@@ -3227,28 +3408,26 @@ make(string body, ShaderLanguage lang) {
   if (cache_generated_shaders) {
   if (cache_generated_shaders) {
     ShaderTable::const_iterator i = _make_table.find(sbody);
     ShaderTable::const_iterator i = _make_table.find(sbody);
     if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
     if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
-      return i->second;
+      // But check that someone hasn't modified its includes in the meantime.
+      if (!i->second->check_modified()) {
+        return i->second;
+      }
     }
     }
   }
   }
 
 
   PT(Shader) shader = new Shader(lang);
   PT(Shader) shader = new Shader(lang);
-  shader->_filename = ShaderFile("created-shader");
-  shader->_text = move(sbody);
-
-#ifdef HAVE_CG
-  if (lang == SL_Cg) {
-    shader->cg_get_profile_from_header(_default_caps);
-
-    if (!shader->cg_analyze_shader(_default_caps)) {
-      shader_cat.error()
-        << "Shader encountered an error.\n";
-      return nullptr;
-    }
+  if (!shader->load(sbody)) {
+    return nullptr;
   }
   }
-#endif
 
 
   if (cache_generated_shaders) {
   if (cache_generated_shaders) {
-    _make_table[shader->_text] = shader;
+    ShaderTable::const_iterator i = _make_table.find(shader->_text);
+    if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
+      shader = i->second;
+    } else {
+      _make_table[shader->_text] = shader;
+    }
+    _make_table[std::move(sbody)] = shader;
   }
   }
 
 
   if (dump_generated_shaders) {
   if (dump_generated_shaders) {
@@ -3290,26 +3469,27 @@ make(ShaderLanguage lang, string vertex, string fragment, string geometry,
   if (cache_generated_shaders) {
   if (cache_generated_shaders) {
     ShaderTable::const_iterator i = _make_table.find(sbody);
     ShaderTable::const_iterator i = _make_table.find(sbody);
     if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
     if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
-      return i->second;
+      // But check that someone hasn't modified its includes in the meantime.
+      if (!i->second->check_modified()) {
+        return i->second;
+      }
     }
     }
   }
   }
 
 
   PT(Shader) shader = new Shader(lang);
   PT(Shader) shader = new Shader(lang);
   shader->_filename = ShaderFile("created-shader");
   shader->_filename = ShaderFile("created-shader");
-  shader->_text = move(sbody);
-
-#ifdef HAVE_CG
-  if (lang == SL_Cg) {
-    if (!shader->cg_analyze_shader(_default_caps)) {
-      shader_cat.error()
-        << "Shader encountered an error.\n";
-      return nullptr;
-    }
+  if (!shader->load(sbody)) {
+    return nullptr;
   }
   }
-#endif
 
 
   if (cache_generated_shaders) {
   if (cache_generated_shaders) {
-    _make_table[shader->_text] = shader;
+    ShaderTable::const_iterator i = _make_table.find(shader->_text);
+    if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
+      shader = i->second;
+    } else {
+      _make_table[shader->_text] = shader;
+    }
+    _make_table[std::move(sbody)] = shader;
   }
   }
 
 
   return shader;
   return shader;
@@ -3333,16 +3513,27 @@ make_compute(ShaderLanguage lang, string body) {
   if (cache_generated_shaders) {
   if (cache_generated_shaders) {
     ShaderTable::const_iterator i = _make_table.find(sbody);
     ShaderTable::const_iterator i = _make_table.find(sbody);
     if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
     if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
-      return i->second;
+      // But check that someone hasn't modified its includes in the meantime.
+      if (!i->second->check_modified()) {
+        return i->second;
+      }
     }
     }
   }
   }
 
 
   PT(Shader) shader = new Shader(lang);
   PT(Shader) shader = new Shader(lang);
   shader->_filename = ShaderFile("created-shader");
   shader->_filename = ShaderFile("created-shader");
-  shader->_text = move(sbody);
+  if (!shader->load(sbody)) {
+    return nullptr;
+  }
 
 
   if (cache_generated_shaders) {
   if (cache_generated_shaders) {
-    _make_table[shader->_text] = shader;
+    ShaderTable::const_iterator i = _make_table.find(shader->_text);
+    if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
+      shader = i->second;
+    } else {
+      _make_table[shader->_text] = shader;
+    }
+    _make_table[std::move(sbody)] = shader;
   }
   }
 
 
   return shader;
   return shader;

+ 10 - 3
panda/src/gobj/shader.h

@@ -616,11 +616,18 @@ private:
   Shader(ShaderLanguage lang);
   Shader(ShaderLanguage lang);
 
 
   bool read(const ShaderFile &sfile, BamCacheRecord *record = nullptr);
   bool read(const ShaderFile &sfile, BamCacheRecord *record = nullptr);
+  bool load(const ShaderFile &sbody, BamCacheRecord *record = nullptr);
   bool do_read_source(std::string &into, const Filename &fn, BamCacheRecord *record);
   bool do_read_source(std::string &into, const Filename &fn, BamCacheRecord *record);
-  bool r_preprocess_source(std::ostream &out, const Filename &fn,
-                           const Filename &source_dir,
+  bool do_load_source(std::string &into, const std::string &source, BamCacheRecord *record);
+  bool r_preprocess_include(std::ostream &out, const Filename &fn,
+                            const Filename &source_dir,
+                            std::set<Filename> &open_files,
+                            BamCacheRecord *record, int depth);
+  bool r_preprocess_source(std::ostream &out, std::istream &in,
+                           const Filename &fn, const Filename &full_fn,
                            std::set<Filename> &open_files,
                            std::set<Filename> &open_files,
-                           BamCacheRecord *record, int depth = 0);
+                           BamCacheRecord *record,
+                           int fileno = 0, int depth = 0);
 
 
   bool check_modified() const;
   bool check_modified() const;
 
 

+ 1 - 3
panda/src/ode/odeBody.I

@@ -89,12 +89,10 @@ set_data(void *data) {
   dBodySetData(_id, data);
   dBodySetData(_id, data);
 }
 }
 
 
-#ifndef HAVE_PYTHON
-INLINE void* OdeBody::
+INLINE void *OdeBody::
 get_data() const {
 get_data() const {
   return dBodyGetData(_id);
   return dBodyGetData(_id);
 }
 }
-#endif
 
 
 INLINE void OdeBody::
 INLINE void OdeBody::
 set_position(dReal x, dReal y, dReal z) {
 set_position(dReal x, dReal y, dReal z) {

+ 4 - 23
panda/src/ode/odeBody.cxx

@@ -15,10 +15,6 @@
 #include "odeBody.h"
 #include "odeBody.h"
 #include "odeJoint.h"
 #include "odeJoint.h"
 
 
-#ifdef HAVE_PYTHON
-#include "py_panda.h"
-#endif
-
 TypeHandle OdeBody::_type_handle;
 TypeHandle OdeBody::_type_handle;
 
 
 OdeBody::
 OdeBody::
@@ -38,29 +34,14 @@ OdeBody::
 
 
 void OdeBody::
 void OdeBody::
 destroy() {
 destroy() {
-#ifdef HAVE_PYTHON
-  Py_XDECREF((PyObject*) dBodyGetData(_id));
-#endif
+  if (_destroy_callback != nullptr) {
+    _destroy_callback(*this);
+    _destroy_callback = nullptr;
+  }
   nassertv(_id);
   nassertv(_id);
   dBodyDestroy(_id);
   dBodyDestroy(_id);
 }
 }
 
 
-#ifdef HAVE_PYTHON
-void OdeBody::
-set_data(PyObject *data) {
-  Py_XDECREF((PyObject*) dBodyGetData(_id));
-  Py_XINCREF(data);
-  dBodySetData(_id, data);
-}
-
-PyObject* OdeBody::
-get_data() const {
-  PyObject* data = (PyObject*) dBodyGetData(_id);
-  Py_XINCREF(data);
-  return data;
-}
-#endif
-
 OdeJoint OdeBody::
 OdeJoint OdeBody::
 get_joint(int index) const {
 get_joint(int index) const {
   nassertr(_id != nullptr, OdeJoint(nullptr));
   nassertr(_id != nullptr, OdeJoint(nullptr));

+ 8 - 7
panda/src/ode/odeBody.h

@@ -51,9 +51,7 @@ PUBLISHED:
   INLINE void set_auto_disable_flag(int do_auto_disable);
   INLINE void set_auto_disable_flag(int do_auto_disable);
   INLINE void set_auto_disable_defaults();
   INLINE void set_auto_disable_defaults();
   INLINE void set_data(void *data);
   INLINE void set_data(void *data);
-#ifdef HAVE_PYTHON
-  void set_data(PyObject *data);
-#endif
+  EXTENSION(void set_data(PyObject *data));
 
 
   INLINE void set_position(dReal x, dReal y, dReal z);
   INLINE void set_position(dReal x, dReal y, dReal z);
   INLINE void set_position(const LVecBase3f &pos);
   INLINE void set_position(const LVecBase3f &pos);
@@ -71,11 +69,10 @@ PUBLISHED:
   INLINE int   get_auto_disable_steps() const;
   INLINE int   get_auto_disable_steps() const;
   INLINE dReal get_auto_disable_time() const;
   INLINE dReal get_auto_disable_time() const;
   INLINE int   get_auto_disable_flag() const;
   INLINE int   get_auto_disable_flag() const;
-#ifdef HAVE_PYTHON
-  PyObject* get_data() const;
-#else
-  INLINE void* get_data() const;
+#ifndef CPPPARSER
+  INLINE void *get_data() const;
 #endif
 #endif
+  EXTENSION(PyObject *get_data() const);
 
 
   INLINE LVecBase3f  get_position() const;
   INLINE LVecBase3f  get_position() const;
   INLINE LMatrix3f  get_rotation() const;
   INLINE LMatrix3f  get_rotation() const;
@@ -150,6 +147,10 @@ PUBLISHED:
 private:
 private:
   dBodyID _id;
   dBodyID _id;
 
 
+public:
+  typedef void (*DestroyCallback)(OdeBody &body);
+  DestroyCallback _destroy_callback = nullptr;
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 13 - 0
panda/src/ode/odeBody_ext.I

@@ -13,6 +13,19 @@
 
 
 #include "odeJoint_ext.h"
 #include "odeJoint_ext.h"
 
 
+/**
+ * Returns the custom data associated with the OdeBody.
+ */
+INLINE PyObject *Extension<OdeBody>::
+get_data() const {
+  PyObject *data = (PyObject *)_this->get_data();
+  if (data == nullptr) {
+    data = Py_None;
+  }
+  Py_INCREF(data);
+  return data;
+}
+
 /**
 /**
  * Equivalent to get_joint().convert()
  * Equivalent to get_joint().convert()
  */
  */

+ 37 - 0
panda/src/ode/odeBody_ext.cxx

@@ -0,0 +1,37 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file odeBody_ext.cxx
+ * @author rdb
+ * @date 2018-11-06
+ */
+
+#include "odeBody_ext.h"
+
+static void destroy_callback(OdeBody &body) {
+  Py_XDECREF((PyObject *)body.get_data());
+}
+
+/**
+ * Sets custom data to be associated with the OdeBody.
+ */
+void Extension<OdeBody>::
+set_data(PyObject *data) {
+  void *old_data = _this->get_data();
+
+  if (data != nullptr && data != Py_None) {
+    Py_INCREF(data);
+    _this->set_data((void *)data);
+    _this->_destroy_callback = &destroy_callback;
+  } else {
+    _this->set_data(nullptr);
+    _this->_destroy_callback = nullptr;
+  }
+
+  Py_XDECREF((PyObject *)old_data);
+}

+ 3 - 0
panda/src/ode/odeBody_ext.h

@@ -30,6 +30,9 @@
 template<>
 template<>
 class Extension<OdeBody> : public ExtensionBase<OdeBody> {
 class Extension<OdeBody> : public ExtensionBase<OdeBody> {
 public:
 public:
+  void set_data(PyObject *);
+  INLINE PyObject *get_data() const;
+
   INLINE PyObject *get_converted_joint(int i) const;
   INLINE PyObject *get_converted_joint(int i) const;
 };
 };
 
 

+ 1 - 0
panda/src/ode/p3ode_ext_composite.cxx

@@ -1,3 +1,4 @@
+#include "odeBody_ext.cxx"
 #include "odeGeom_ext.cxx"
 #include "odeGeom_ext.cxx"
 #include "odeJoint_ext.cxx"
 #include "odeJoint_ext.cxx"
 #include "odeSpace_ext.cxx"
 #include "odeSpace_ext.cxx"

+ 1 - 0
panda/src/pgraph/config_pgraph.h

@@ -21,6 +21,7 @@
 #include "configVariableInt.h"
 #include "configVariableInt.h"
 #include "configVariableDouble.h"
 #include "configVariableDouble.h"
 #include "configVariableList.h"
 #include "configVariableList.h"
+#include "configVariableString.h"
 
 
 class DSearchPath;
 class DSearchPath;
 
 

+ 1 - 0
panda/src/physx/config_physx.h

@@ -19,6 +19,7 @@
 #include "configVariableBool.h"
 #include "configVariableBool.h"
 #include "configVariableEnum.h"
 #include "configVariableEnum.h"
 #include "configVariableInt.h"
 #include "configVariableInt.h"
+#include "configVariableString.h"
 #include "dconfig.h"
 #include "dconfig.h"
 
 
 #include "physxEnums.h"
 #include "physxEnums.h"

+ 1 - 1
panda/src/pipeline/cycleData.h

@@ -44,7 +44,7 @@ class EXPCL_PANDA_PIPELINE CycleData : public NodeReferenceCount
 // If we are *not* compiling in pipelining support, the CycleData object is
 // If we are *not* compiling in pipelining support, the CycleData object is
 // stored directly within its containing classes, and hence should not be a
 // stored directly within its containing classes, and hence should not be a
 // ReferenceCount object.
 // ReferenceCount object.
-class EXPCL_PANDA_PIPELINE CycleData
+class EXPCL_PANDA_PIPELINE CycleData : public MemoryBase
 
 
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING
 {
 {

+ 2 - 0
panda/src/putil/config_putil.h

@@ -16,9 +16,11 @@
 
 
 #include "pandabase.h"
 #include "pandabase.h"
 #include "notifyCategoryProxy.h"
 #include "notifyCategoryProxy.h"
+#include "configVariableBool.h"
 #include "configVariableSearchPath.h"
 #include "configVariableSearchPath.h"
 #include "configVariableEnum.h"
 #include "configVariableEnum.h"
 #include "configVariableDouble.h"
 #include "configVariableDouble.h"
+#include "configVariableInt.h"
 #include "bamEnums.h"
 #include "bamEnums.h"
 #include "dconfig.h"
 #include "dconfig.h"
 
 

+ 6 - 1
panda/src/vision/webcamVideoCursorOpenCV.cxx

@@ -11,12 +11,17 @@
  * @date 2010-10-20
  * @date 2010-10-20
  */
  */
 
 
-#include "webcamVideoOpenCV.h"
+#include "webcamVideoCursorOpenCV.h"
 
 
 #ifdef HAVE_OPENCV
 #ifdef HAVE_OPENCV
 
 
+#include "webcamVideoOpenCV.h"
+#include "movieVideoCursor.h"
+
 #include "pStatTimer.h"
 #include "pStatTimer.h"
 
 
+#include <opencv2/highgui/highgui.hpp>
+
 TypeHandle WebcamVideoCursorOpenCV::_type_handle;
 TypeHandle WebcamVideoCursorOpenCV::_type_handle;
 
 
 /**
 /**

+ 1 - 0
panda/src/vision/webcamVideoCursorOpenCV.h

@@ -22,6 +22,7 @@
 #include "movieVideoCursor.h"
 #include "movieVideoCursor.h"
 
 
 class WebcamVideoOpenCV;
 class WebcamVideoOpenCV;
+struct CvCapture;
 
 
 /**
 /**
  * The Video4Linux implementation of webcams.
  * The Video4Linux implementation of webcams.

+ 5 - 0
panda/src/vision/webcamVideoCursorV4L.cxx

@@ -11,8 +11,13 @@
  * @date 2010-06-11
  * @date 2010-06-11
  */
  */
 
 
+#include "webcamVideoCursorV4L.h"
+
+#include "config_vision.h"
 #include "webcamVideoV4L.h"
 #include "webcamVideoV4L.h"
 
 
+#include "movieVideoCursor.h"
+
 #if defined(HAVE_VIDEO4LINUX) && !defined(CPPPARSER)
 #if defined(HAVE_VIDEO4LINUX) && !defined(CPPPARSER)
 
 
 #include <fcntl.h>
 #include <fcntl.h>

+ 0 - 10
panda/src/vrpn/vrpn_interface.h

@@ -16,16 +16,6 @@
 
 
 #include "pandabase.h"
 #include "pandabase.h"
 
 
-#ifdef CPPPARSER
-  // For correct interrogate parsing of UNC's vrpn library.
-  #if defined(WIN32_VC) || defined(WIN64_VC)
-    #define SOCKET int
-  #else
-    #define linux
-    typedef struct timeval timeval;
-  #endif
-#endif
-
 // VPRN misses an include to this in vrpn_Shared.h.
 // VPRN misses an include to this in vrpn_Shared.h.
 #include <stdint.h>
 #include <stdint.h>
 
 

+ 1 - 0
panda/src/windisplay/winDetectDx9.cxx

@@ -18,6 +18,7 @@
 #ifndef WIN32_LEAN_AND_MEAN
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN 1
 #define WIN32_LEAN_AND_MEAN 1
 #endif
 #endif
+#undef Configure
 #include <d3d9.h>
 #include <d3d9.h>
 #include "graphicsStateGuardian.h"
 #include "graphicsStateGuardian.h"
 #include "graphicsPipe.h"
 #include "graphicsPipe.h"

+ 0 - 1
pandatool/src/configfiles/pandatool.init

@@ -1 +0,0 @@
-ATTACH panda

+ 0 - 1
pandatool/src/progbase/programBase.cxx

@@ -19,7 +19,6 @@
 #include "dSearchPath.h"
 #include "dSearchPath.h"
 #include "coordinateSystem.h"
 #include "coordinateSystem.h"
 #include "dconfig.h"
 #include "dconfig.h"
-#include "config_dconfig.h"
 #include "string_utils.h"
 #include "string_utils.h"
 #include "vector_string.h"
 #include "vector_string.h"
 #include "configVariableInt.h"
 #include "configVariableInt.h"

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