Browse Source

Merge branch 'master' into shaderpipeline

rdb 3 years ago
parent
commit
fe8dc7c41d
100 changed files with 2684 additions and 1534 deletions
  1. 4 4
      README.md
  2. 1 1
      contrib/src/rplight/gpuCommandList.cxx
  3. 1 1
      contrib/src/rplight/gpuCommandList.h
  4. 5 5
      contrib/src/rplight/pssmCameraRig.I
  5. 5 5
      contrib/src/rplight/pssmCameraRig.h
  6. 2 2
      contrib/src/rplight/tagStateManager.I
  7. 1 1
      contrib/src/rplight/tagStateManager.h
  8. 8 8
      direct/src/actor/Actor.py
  9. 1 1
      direct/src/dcparser/dcPacker_ext.cxx
  10. 16 7
      direct/src/deadrec/smoothMover.I
  11. 21 6
      direct/src/dist/FreezeTool.py
  12. 27 1
      direct/src/filter/CommonFilters.py
  13. 4 4
      direct/src/showbase/BufferViewer.py
  14. 56 0
      doc/ReleaseNotes
  15. 301 1
      dtool/metalibs/dtoolconfig/pydtool.cxx
  16. 2 0
      dtool/src/cppparser/CMakeLists.txt
  17. 5 0
      dtool/src/cppparser/cppArrayType.cxx
  18. 196 0
      dtool/src/cppparser/cppAttributeList.cxx
  19. 65 0
      dtool/src/cppparser/cppAttributeList.h
  20. 916 952
      dtool/src/cppparser/cppBison.cxx.prebuilt
  21. 6 3
      dtool/src/cppparser/cppBison.h.prebuilt
  22. 256 203
      dtool/src/cppparser/cppBison.yxx
  23. 2 0
      dtool/src/cppparser/cppBisonDefs.h
  24. 4 0
      dtool/src/cppparser/cppClosureType.cxx
  25. 22 3
      dtool/src/cppparser/cppDeclaration.cxx
  26. 8 3
      dtool/src/cppparser/cppDeclaration.h
  27. 23 12
      dtool/src/cppparser/cppEnumType.cxx
  28. 6 3
      dtool/src/cppparser/cppEnumType.h
  29. 5 1
      dtool/src/cppparser/cppExtensionType.cxx
  30. 1 1
      dtool/src/cppparser/cppExtensionType.h
  31. 20 9
      dtool/src/cppparser/cppFunctionType.cxx
  32. 8 0
      dtool/src/cppparser/cppIdentifier.cxx
  33. 2 0
      dtool/src/cppparser/cppIdentifier.h
  34. 11 15
      dtool/src/cppparser/cppInstance.cxx
  35. 1 1
      dtool/src/cppparser/cppInstance.h
  36. 40 16
      dtool/src/cppparser/cppInstanceIdentifier.cxx
  37. 22 8
      dtool/src/cppparser/cppInstanceIdentifier.h
  38. 12 6
      dtool/src/cppparser/cppNamespace.cxx
  39. 1 1
      dtool/src/cppparser/cppNamespace.h
  40. 6 0
      dtool/src/cppparser/cppPointerType.cxx
  41. 2 2
      dtool/src/cppparser/cppPreprocessor.h
  42. 9 6
      dtool/src/cppparser/cppReferenceType.cxx
  43. 9 5
      dtool/src/cppparser/cppStructType.cxx
  44. 2 1
      dtool/src/cppparser/cppStructType.h
  45. 13 2
      dtool/src/cppparser/cppTypedefType.cxx
  46. 2 1
      dtool/src/cppparser/cppTypedefType.h
  47. 1 1
      dtool/src/cppparser/p3cppParser_composite1.cxx
  48. 9 5
      dtool/src/dtoolbase/CMakeLists.txt
  49. 52 0
      dtool/src/dtoolbase/deletedBufferChain.I
  50. 41 12
      dtool/src/dtoolbase/deletedBufferChain.cxx
  51. 17 3
      dtool/src/dtoolbase/deletedBufferChain.h
  52. 4 5
      dtool/src/dtoolbase/deletedChain.I
  53. 1 1
      dtool/src/dtoolbase/deletedChain.h
  54. 3 0
      dtool/src/dtoolbase/dtool_platform.h
  55. 5 21
      dtool/src/dtoolbase/dtoolbase.cxx
  56. 6 0
      dtool/src/dtoolbase/memoryHook.I
  57. 25 62
      dtool/src/dtoolbase/memoryHook.cxx
  58. 10 15
      dtool/src/dtoolbase/memoryHook.h
  59. 2 0
      dtool/src/dtoolbase/mutexSpinlockImpl.cxx
  60. 0 1
      dtool/src/dtoolbase/typeRegistry.cxx
  61. 2 2
      dtool/src/dtoolutil/dSearchPath.h
  62. 1 1
      dtool/src/dtoolutil/filename.h
  63. 16 0
      dtool/src/interrogate/functionRemap.cxx
  64. 1 1
      dtool/src/interrogate/interfaceMakerPythonNative.cxx
  65. 9 10
      dtool/src/interrogate/interrogate.cxx
  66. 5 1
      dtool/src/interrogate/interrogateBuilder.cxx
  67. 32 0
      dtool/src/interrogatedb/interrogateFunctionWrapper.I
  68. 9 1
      dtool/src/interrogatedb/interrogateFunctionWrapper.h
  69. 10 0
      dtool/src/interrogatedb/interrogateType.I
  70. 2 0
      dtool/src/interrogatedb/interrogateType.h
  71. 102 0
      dtool/src/interrogatedb/interrogate_interface.cxx
  72. 28 0
      dtool/src/interrogatedb/interrogate_interface.h
  73. 0 4
      dtool/src/parser-inc/stdtypedefs.h
  74. 1 1
      dtool/src/prc/configVariableBool.h
  75. 1 1
      dtool/src/prc/configVariableDouble.h
  76. 1 1
      dtool/src/prc/configVariableFilename.h
  77. 1 1
      dtool/src/prc/configVariableInt.h
  78. 1 1
      dtool/src/prc/configVariableInt64.h
  79. 0 1
      dtool/src/prc/configVariableManager.cxx
  80. 0 1
      dtool/src/prc/notify.cxx
  81. 4 2
      makepanda/makepanda.py
  82. 4 0
      panda/src/audio/audioSound.h
  83. 8 0
      panda/src/audio/nullAudioSound.cxx
  84. 3 0
      panda/src/audio/nullAudioSound.h
  85. 43 0
      panda/src/audiotraits/fmodAudioSound.cxx
  86. 4 0
      panda/src/audiotraits/fmodAudioSound.h
  87. 34 3
      panda/src/audiotraits/openalAudioSound.cxx
  88. 8 3
      panda/src/audiotraits/openalAudioSound.h
  89. 1 4
      panda/src/bullet/bulletAllHitsRayResult.I
  90. 1 1
      panda/src/bullet/bulletContactResult.I
  91. 8 8
      panda/src/bullet/bulletContactResult.cxx
  92. 2 1
      panda/src/bullet/bulletContactResult.h
  93. 0 8
      panda/src/bullet/bulletManifoldPoint.I
  94. 0 19
      panda/src/bullet/bulletManifoldPoint.cxx
  95. 3 3
      panda/src/bullet/bulletManifoldPoint.h
  96. 0 14
      panda/src/bullet/bulletWheel.I
  97. 13 0
      panda/src/bullet/bulletWheel.cxx
  98. 1 1
      panda/src/bullet/bulletWheel.h
  99. 5 4
      panda/src/bullet/bullet_utils.cxx
  100. 14 9
      panda/src/cocoadisplay/cocoaGraphicsWindow.mm

+ 4 - 4
README.md

@@ -24,7 +24,7 @@ Installing Panda3D
 ==================
 ==================
 
 
 The latest Panda3D SDK can be downloaded from
 The latest Panda3D SDK can be downloaded from
-[this page](https://www.panda3d.org/download/sdk-1-10-11/).
+[this page](https://www.panda3d.org/download/sdk-1-10-12/).
 If you are familiar with installing Python packages, you can use
 If you are familiar with installing Python packages, you can use
 the following command:
 the following command:
 
 
@@ -64,8 +64,8 @@ depending on whether you are on a 32-bit or 64-bit system, or you can
 [click here](https://github.com/rdb/panda3d-thirdparty) for instructions on
 [click here](https://github.com/rdb/panda3d-thirdparty) for instructions on
 building them from source.
 building them from source.
 
 
-- https://www.panda3d.org/download/panda3d-1.10.11/panda3d-1.10.11-tools-win64.zip
-- https://www.panda3d.org/download/panda3d-1.10.11/panda3d-1.10.11-tools-win32.zip
+- https://www.panda3d.org/download/panda3d-1.10.12/panda3d-1.10.12-tools-win64.zip
+- https://www.panda3d.org/download/panda3d-1.10.12/panda3d-1.10.12-tools-win32.zip
 
 
 After acquiring these dependencies, you can build Panda3D from the command
 After acquiring these dependencies, you can build Panda3D from the command
 prompt using the following command.  Change the `--msvc-version` option based
 prompt using the following command.  Change the `--msvc-version` option based
@@ -136,7 +136,7 @@ macOS
 -----
 -----
 
 
 On macOS, you will need to download a set of precompiled thirdparty packages in order to
 On macOS, you will need to download a set of precompiled thirdparty packages in order to
-compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.10.11/panda3d-1.10.11-tools-mac.tar.gz).
+compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.10.12/panda3d-1.10.12-tools-mac.tar.gz).
 
 
 After placing the thirdparty directory inside the panda3d source directory,
 After placing the thirdparty directory inside the panda3d source directory,
 you may build Panda3D using a command like the following:
 you may build Panda3D using a command like the following:

+ 1 - 1
contrib/src/rplight/gpuCommandList.cxx

@@ -51,7 +51,7 @@ void GPUCommandList::add_command(const GPUCommand& cmd) {
  *   list, and are waiting to get processed.
  *   list, and are waiting to get processed.
  * @return Amount of commands
  * @return Amount of commands
  */
  */
-size_t GPUCommandList::get_num_commands() {
+size_t GPUCommandList::get_num_commands() const {
   return _commands.size();
   return _commands.size();
 }
 }
 
 

+ 1 - 1
contrib/src/rplight/gpuCommandList.h

@@ -42,7 +42,7 @@ PUBLISHED:
   GPUCommandList();
   GPUCommandList();
 
 
   void add_command(const GPUCommand& cmd);
   void add_command(const GPUCommand& cmd);
-  size_t get_num_commands();
+  size_t get_num_commands() const;
   size_t write_commands_to(const PTA_uchar &dest, size_t limit = 32);
   size_t write_commands_to(const PTA_uchar &dest, size_t limit = 32);
 
 
   MAKE_PROPERTY(num_commands, get_num_commands);
   MAKE_PROPERTY(num_commands, get_num_commands);

+ 5 - 5
contrib/src/rplight/pssmCameraRig.I

@@ -175,7 +175,7 @@ inline void PSSMCameraRig::reset_film_size_cache() {
  * @param index Index of the camera.
  * @param index Index of the camera.
  * @return [description]
  * @return [description]
  */
  */
-inline NodePath PSSMCameraRig::get_camera(size_t index) {
+inline NodePath PSSMCameraRig::get_camera(size_t index) const {
   nassertr(index >= 0 && index < _cam_nodes.size(), NodePath());
   nassertr(index >= 0 && index < _cam_nodes.size(), NodePath());
   return _cam_nodes[index];
   return _cam_nodes[index];
 }
 }
@@ -193,7 +193,7 @@ inline NodePath PSSMCameraRig::get_camera(size_t index) {
  * @param split_index The index of the split
  * @param split_index The index of the split
  * @return Distance of the split, ranging from 0 .. 1
  * @return Distance of the split, ranging from 0 .. 1
  */
  */
-inline float PSSMCameraRig::get_split_start(size_t split_index) {
+inline float PSSMCameraRig::get_split_start(size_t split_index) const {
   float x = (float)split_index / (float)_cam_nodes.size();
   float x = (float)split_index / (float)_cam_nodes.size();
   return (exp(_logarithmic_factor*x)-1) / (exp(_logarithmic_factor)-1);
   return (exp(_logarithmic_factor*x)-1) / (exp(_logarithmic_factor)-1);
 }
 }
@@ -209,7 +209,7 @@ inline float PSSMCameraRig::get_split_start(size_t split_index) {
  *
  *
  * @return interpolated point in world space
  * @return interpolated point in world space
  */
  */
-inline LPoint3 PSSMCameraRig::get_interpolated_point(CoordinateOrigin origin, float depth) {
+inline LPoint3 PSSMCameraRig::get_interpolated_point(CoordinateOrigin origin, float depth) const {
   nassertr(depth >= 0.0 && depth <= 1.0, LPoint3());
   nassertr(depth >= 0.0 && depth <= 1.0, LPoint3());
   return _curr_near_points[origin] * (1.0 - depth) + _curr_far_points[origin] * depth;
   return _curr_near_points[origin] * (1.0 - depth) + _curr_far_points[origin] * depth;
 }
 }
@@ -222,7 +222,7 @@ inline LPoint3 PSSMCameraRig::get_interpolated_point(CoordinateOrigin origin, fl
  *
  *
  * @return view-projection matrix array
  * @return view-projection matrix array
  */
  */
-inline const PTA_LMatrix4 &PSSMCameraRig::get_mvp_array() {
+inline const PTA_LMatrix4 &PSSMCameraRig::get_mvp_array() const {
   return _camera_mvps;
   return _camera_mvps;
 }
 }
 
 
@@ -238,6 +238,6 @@ inline const PTA_LMatrix4 &PSSMCameraRig::get_mvp_array() {
  *
  *
  * @return Array of near and far planes
  * @return Array of near and far planes
  */
  */
-inline const PTA_LVecBase2 &PSSMCameraRig::get_nearfar_array() {
+inline const PTA_LVecBase2 &PSSMCameraRig::get_nearfar_array() const {
   return _camera_nearfar;
   return _camera_nearfar;
 }
 }

+ 5 - 5
contrib/src/rplight/pssmCameraRig.h

@@ -72,11 +72,11 @@ PUBLISHED:
   void update(NodePath cam_node, const LVecBase3 &light_vector);
   void update(NodePath cam_node, const LVecBase3 &light_vector);
   inline void reset_film_size_cache();
   inline void reset_film_size_cache();
 
 
-  inline NodePath get_camera(size_t index);
+  inline NodePath get_camera(size_t index) const;
 
 
   void reparent_to(NodePath parent);
   void reparent_to(NodePath parent);
-  inline const PTA_LMatrix4 &get_mvp_array();
-  inline const PTA_LVecBase2 &get_nearfar_array();
+  inline const PTA_LMatrix4 &get_mvp_array() const;
+  inline const PTA_LVecBase2 &get_nearfar_array() const;
 
 
 public:
 public:
   // Used to access the near and far points in the array
   // Used to access the near and far points in the array
@@ -91,9 +91,9 @@ protected:
   void init_cam_nodes();
   void init_cam_nodes();
   void compute_pssm_splits(const LMatrix4& transform, float max_distance,
   void compute_pssm_splits(const LMatrix4& transform, float max_distance,
                const LVecBase3 &light_vector);
                const LVecBase3 &light_vector);
-  inline float get_split_start(size_t split_index);
+  inline float get_split_start(size_t split_index) const;
   LMatrix4 compute_mvp(size_t cam_index);
   LMatrix4 compute_mvp(size_t cam_index);
-  inline LPoint3 get_interpolated_point(CoordinateOrigin origin, float depth);
+  inline LPoint3 get_interpolated_point(CoordinateOrigin origin, float depth) const;
   LVecBase3 get_snap_offset(const LMatrix4& mat, size_t resolution);
   LVecBase3 get_snap_offset(const LMatrix4& mat, size_t resolution);
 
 
   std::vector<NodePath> _cam_nodes;
   std::vector<NodePath> _cam_nodes;

+ 2 - 2
contrib/src/rplight/tagStateManager.I

@@ -83,11 +83,11 @@ apply_state(const std::string& state, NodePath np, Shader* shader,
  * @return Bit mask of the render pass
  * @return Bit mask of the render pass
  */
  */
 inline BitMask32 TagStateManager::
 inline BitMask32 TagStateManager::
-get_mask(const std::string &container_name) {
+get_mask(const std::string &container_name) const {
   if (container_name == "gbuffer") {
   if (container_name == "gbuffer") {
     return BitMask32::bit(1);
     return BitMask32::bit(1);
   }
   }
-  ContainerList::iterator entry = _containers.find(container_name);
+  ContainerList::const_iterator entry = _containers.find(container_name);
   nassertr(entry != _containers.end(), BitMask32());
   nassertr(entry != _containers.end(), BitMask32());
   return entry->second.mask;
   return entry->second.mask;
 }
 }

+ 1 - 1
contrib/src/rplight/tagStateManager.h

@@ -57,7 +57,7 @@ PUBLISHED:
 
 
   inline void register_camera(const std::string& state, Camera* source);
   inline void register_camera(const std::string& state, Camera* source);
   inline void unregister_camera(const std::string& state, Camera* source);
   inline void unregister_camera(const std::string& state, Camera* source);
-  inline BitMask32 get_mask(const std::string &container_name);
+  inline BitMask32 get_mask(const std::string &container_name) const;
 
 
 private:
 private:
   typedef std::vector<Camera*> CameraList;
   typedef std::vector<Camera*> CameraList;

+ 8 - 8
direct/src/actor/Actor.py

@@ -424,7 +424,7 @@ class Actor(DirectObject, NodePath):
                             subpartDef.subset.isIncludeEmpty(), subpartDef.subset)
                             subpartDef.subset.isIncludeEmpty(), subpartDef.subset)
 
 
     def __doListJoints(self, indentLevel, part, isIncluded, subset):
     def __doListJoints(self, indentLevel, part, isIncluded, subset):
-        name = part.getName()
+        name = part.name
         if subset.matchesInclude(name):
         if subset.matchesInclude(name):
             isIncluded = True
             isIncluded = True
         elif subset.matchesExclude(name):
         elif subset.matchesExclude(name):
@@ -437,9 +437,9 @@ class Actor(DirectObject, NodePath):
                 part.outputValue(lineStream)
                 part.outputValue(lineStream)
                 value = lineStream.getLine()
                 value = lineStream.getLine()
 
 
-            print(' '.join((' ' * indentLevel, part.getName(), value)))
+            print(' '.join((' ' * indentLevel, name, value)))
 
 
-        for child in part.getChildren():
+        for child in part.children:
             self.__doListJoints(indentLevel + 2, child, isIncluded, subset)
             self.__doListJoints(indentLevel + 2, child, isIncluded, subset)
 
 
 
 
@@ -1206,11 +1206,11 @@ class Actor(DirectObject, NodePath):
 
 
         return jointsA & jointsB
         return jointsA & jointsB
 
 
-    def __getPartJoints(self, joints, pattern, partNode, subset, isIncluded):
+    def __getPartJoints(self, joints, pattern, part, subset, isIncluded):
         """ Recursively walks the joint hierarchy to look for matching
         """ Recursively walks the joint hierarchy to look for matching
         joint names, implementing getJoints(). """
         joint names, implementing getJoints(). """
 
 
-        name = partNode.getName()
+        name = part.name
         if subset:
         if subset:
             # Constrain the traversal just to the named subset.
             # Constrain the traversal just to the named subset.
             if subset.matchesInclude(name):
             if subset.matchesInclude(name):
@@ -1218,10 +1218,10 @@ class Actor(DirectObject, NodePath):
             elif subset.matchesExclude(name):
             elif subset.matchesExclude(name):
                 isIncluded = False
                 isIncluded = False
 
 
-        if isIncluded and pattern.matches(name) and isinstance(partNode, MovingPartBase):
-            joints.append(partNode)
+        if isIncluded and pattern.matches(name) and isinstance(part, MovingPartBase):
+            joints.append(part)
 
 
-        for child in partNode.getChildren():
+        for child in part.children:
             self.__getPartJoints(joints, pattern, child, subset, isIncluded)
             self.__getPartJoints(joints, pattern, child, subset, isIncluded)
 
 
     def getJointTransform(self, partName, jointName, lodName='lodRoot'):
     def getJointTransform(self, partName, jointName, lodName='lodRoot'):

+ 1 - 1
direct/src/dcparser/dcPacker_ext.cxx

@@ -195,7 +195,7 @@ unpack_object() {
   case PT_uint:
   case PT_uint:
     {
     {
       unsigned int value = _this->unpack_uint();
       unsigned int value = _this->unpack_uint();
-      object = PyLong_FromLong(value);
+      object = PyLong_FromUnsignedLong(value);
     }
     }
     break;
     break;
 
 

+ 16 - 7
direct/src/deadrec/smoothMover.I

@@ -23,7 +23,7 @@
  */
  */
 INLINE bool SmoothMover::
 INLINE bool SmoothMover::
 set_pos(const LVecBase3 &pos) {
 set_pos(const LVecBase3 &pos) {
-  return set_x(pos[0]) | set_y(pos[1]) | set_z(pos[2]);
+  return set_pos(pos[0], pos[1], pos[2]);
 }
 }
 
 
 /**
 /**
@@ -38,7 +38,10 @@ set_pos(const LVecBase3 &pos) {
  */
  */
 INLINE bool SmoothMover::
 INLINE bool SmoothMover::
 set_pos(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) {
 set_pos(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) {
-  return set_x(x) | set_y(y) | set_z(z);
+  bool x_changed = set_x(x);
+  bool y_changed = set_y(y);
+  bool z_changed = set_z(z);
+  return x_changed || y_changed || z_changed;
 }
 }
 
 
 /**
 /**
@@ -98,7 +101,7 @@ set_z(PN_stdfloat z) {
  */
  */
 INLINE bool SmoothMover::
 INLINE bool SmoothMover::
 set_hpr(const LVecBase3 &hpr) {
 set_hpr(const LVecBase3 &hpr) {
-  return set_h(hpr[0]) | set_p(hpr[1]) | set_r(hpr[2]);
+  return set_hpr(hpr[0], hpr[1], hpr[2]);
 }
 }
 
 
 /**
 /**
@@ -113,7 +116,10 @@ set_hpr(const LVecBase3 &hpr) {
  */
  */
 INLINE bool SmoothMover::
 INLINE bool SmoothMover::
 set_hpr(PN_stdfloat h, PN_stdfloat p, PN_stdfloat r) {
 set_hpr(PN_stdfloat h, PN_stdfloat p, PN_stdfloat r) {
-  return set_h(h) | set_p(p) | set_r(r);
+  bool h_changed = set_h(h);
+  bool p_changed = set_p(p);
+  bool r_changed = set_r(r);
+  return h_changed || p_changed || r_changed;
 }
 }
 
 
 /**
 /**
@@ -173,8 +179,9 @@ set_r(PN_stdfloat r) {
  */
  */
 INLINE bool SmoothMover::
 INLINE bool SmoothMover::
 set_pos_hpr(const LVecBase3 &pos, const LVecBase3 &hpr) {
 set_pos_hpr(const LVecBase3 &pos, const LVecBase3 &hpr) {
-  return (set_x(pos[0]) | set_y(pos[1]) | set_z(pos[2]) |
-          set_h(hpr[0]) | set_p(hpr[1]) | set_r(hpr[2]));
+  bool pos_changed = set_pos(pos);
+  bool hpr_changed = set_hpr(hpr);
+  return pos_changed || hpr_changed;
 }
 }
 
 
 /**
 /**
@@ -189,7 +196,9 @@ set_pos_hpr(const LVecBase3 &pos, const LVecBase3 &hpr) {
  */
  */
 INLINE bool SmoothMover::
 INLINE bool SmoothMover::
 set_pos_hpr(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat h, PN_stdfloat p, PN_stdfloat r) {
 set_pos_hpr(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat h, PN_stdfloat p, PN_stdfloat r) {
-  return set_x(x) | set_y(y) | set_z(z) | set_h(h) | set_p(p) | set_r(r);
+  bool pos_changed = set_pos(x, y, z);
+  bool hpr_changed = set_hpr(h, p, r);
+  return pos_changed || hpr_changed;
 }
 }
 
 
 /**
 /**

+ 21 - 6
direct/src/dist/FreezeTool.py

@@ -81,6 +81,12 @@ defaultHiddenImports = {
     'pandas.compat': ['lzma', 'cmath'],
     'pandas.compat': ['lzma', 'cmath'],
     'pandas._libs.tslibs.conversion': ['pandas._libs.tslibs.base'],
     'pandas._libs.tslibs.conversion': ['pandas._libs.tslibs.base'],
     'plyer': ['plyer.platforms'],
     'plyer': ['plyer.platforms'],
+    'scipy.linalg': ['scipy.linalg.cython_blas', 'scipy.linalg.cython_lapack'],
+    'scipy.sparse.csgraph': ['scipy.sparse.csgraph._validation'],
+    'scipy.spatial._qhull': ['scipy._lib.messagestream'],
+    'scipy.spatial.transform._rotation': ['scipy.spatial.transform._rotation_groups'],
+    'scipy.special._ufuncs': ['scipy.special._ufuncs_cxx'],
+    'scipy.stats._stats': ['scipy.special.cython_special'],
 }
 }
 
 
 
 
@@ -1189,22 +1195,31 @@ class Freezer:
 
 
         # Special case for sysconfig, which depends on a platform-specific
         # Special case for sysconfig, which depends on a platform-specific
         # sysconfigdata module on POSIX systems.
         # sysconfigdata module on POSIX systems.
-        if 'sysconfig' in self.mf.modules:
+        missing = []
+        if 'sysconfig' in self.mf.modules and \
+           ('linux' in self.platform or 'mac' in self.platform):
+            modname = '_sysconfigdata'
             if sys.version_info >= (3, 6):
             if sys.version_info >= (3, 6):
+                modname += '_'
+                if sys.version_info < (3, 8):
+                    modname += 'm'
+
                 if 'linux' in self.platform:
                 if 'linux' in self.platform:
                     arch = self.platform.split('_', 1)[1]
                     arch = self.platform.split('_', 1)[1]
-                    self.__loadModule(self.ModuleDef('_sysconfigdata__linux_' + arch + '-linux-gnu', implicit=True))
+                    modname += '_linux_' + arch + '-linux-gnu'
                 elif 'mac' in self.platform:
                 elif 'mac' in self.platform:
-                    self.__loadModule(self.ModuleDef('_sysconfigdata__darwin_darwin', implicit=True))
-            elif 'linux' in self.platform or 'mac' in self.platform:
-                self.__loadModule(self.ModuleDef('_sysconfigdata', implicit=True))
+                    modname += '_darwin_darwin'
+
+            try:
+                self.__loadModule(self.ModuleDef(modname, implicit=True))
+            except:
+                missing.append(modname)
 
 
         # Now, any new modules we found get added to the export list.
         # Now, any new modules we found get added to the export list.
         for origName in list(self.mf.modules.keys()):
         for origName in list(self.mf.modules.keys()):
             if origName not in origToNewName:
             if origName not in origToNewName:
                 self.modules[origName] = self.ModuleDef(origName, implicit = True)
                 self.modules[origName] = self.ModuleDef(origName, implicit = True)
 
 
-        missing = []
         for origName in self.mf.any_missing_maybe()[0]:
         for origName in self.mf.any_missing_maybe()[0]:
             if origName in startupModules:
             if origName in startupModules:
                 continue
                 continue

+ 27 - 1
direct/src/filter/CommonFilters.py

@@ -17,7 +17,7 @@ These filters are written in the Cg shading language.
 # clunky approach.  - Josh
 # clunky approach.  - Josh
 
 
 from panda3d.core import LVecBase4, LPoint2
 from panda3d.core import LVecBase4, LPoint2
-from panda3d.core import AuxBitplaneAttrib
+from panda3d.core import AuxBitplaneAttrib, AntialiasAttrib
 from panda3d.core import Texture, Shader, ATSNone
 from panda3d.core import Texture, Shader, ATSNone
 from panda3d.core import FrameBufferProperties
 from panda3d.core import FrameBufferProperties
 from panda3d.core import getDefaultCoordinateSystem, CS_zup_right, CS_zup_left
 from panda3d.core import getDefaultCoordinateSystem, CS_zup_right, CS_zup_left
@@ -189,11 +189,22 @@ class CommonFilters:
                 fbprops.setSrgbColor(False)
                 fbprops.setSrgbColor(False)
                 clamping = False
                 clamping = False
 
 
+            if "MSAA" in configuration:
+                if fbprops is None:
+                    fbprops = FrameBufferProperties()
+                fbprops.setMultisamples(configuration["MSAA"].samples)
+
             self.finalQuad = self.manager.renderSceneInto(textures = self.textures, auxbits=auxbits, fbprops=fbprops, clamping=clamping)
             self.finalQuad = self.manager.renderSceneInto(textures = self.textures, auxbits=auxbits, fbprops=fbprops, clamping=clamping)
             if self.finalQuad is None:
             if self.finalQuad is None:
                 self.cleanup()
                 self.cleanup()
                 return False
                 return False
 
 
+            if "MSAA" in configuration:
+                camNode = self.manager.camera.node()
+                state = camNode.getInitialState()
+                state.setAttrib(AntialiasAttrib.make(AntialiasAttrib.M_multisample))
+                camNode.setInitialState(state)
+
             if "BlurSharpen" in configuration:
             if "BlurSharpen" in configuration:
                 blur0 = self.textures["blur0"]
                 blur0 = self.textures["blur0"]
                 blur1 = self.textures["blur1"]
                 blur1 = self.textures["blur1"]
@@ -454,6 +465,19 @@ class CommonFilters:
         if task is not None:
         if task is not None:
             return task.cont
             return task.cont
 
 
+    def setMSAA(self, samples):
+        fullrebuild = "MSAA" not in self.configuration or self.configuration["MSAA"].samples != samples
+        newconfig = FilterConfig()
+        newconfig.samples = samples
+        self.configuration["MSAA"] = newconfig
+        return self.reconfigure(fullrebuild, "MSAA")
+
+    def delMSAA(self):
+        if "MSAA" in self.configuration:
+            del self.configuration["MSAA"]
+            return self.reconfigure(True, "MSAA")
+        return True
+
     def setCartoonInk(self, separation=1, color=(0, 0, 0, 1)):
     def setCartoonInk(self, separation=1, color=(0, 0, 0, 1)):
         fullrebuild = ("CartoonInk" not in self.configuration)
         fullrebuild = ("CartoonInk" not in self.configuration)
         newconfig = FilterConfig()
         newconfig = FilterConfig()
@@ -679,6 +703,8 @@ class CommonFilters:
         return True
         return True
 
 
     #snake_case alias:
     #snake_case alias:
+    set_msaa = setMSAA
+    del_msaa = delMSAA
     del_cartoon_ink = delCartoonInk
     del_cartoon_ink = delCartoonInk
     set_half_pixel_shift = setHalfPixelShift
     set_half_pixel_shift = setHalfPixelShift
     del_half_pixel_shift = delHalfPixelShift
     del_half_pixel_shift = delHalfPixelShift

+ 4 - 4
direct/src/showbase/BufferViewer.py

@@ -240,10 +240,10 @@ class BufferViewer(DirectObject):
             offsetx = (ringoffset[ring]*2.0) / float(sizex)
             offsetx = (ringoffset[ring]*2.0) / float(sizex)
             offsety = (ringoffset[ring]*2.0) / float(sizey)
             offsety = (ringoffset[ring]*2.0) / float(sizey)
             bright = ringbright[ring]
             bright = ringbright[ring]
-            vwriter.addData3f(Vec3.rfu(-1 - offsetx, 0, -1 - offsety))
-            vwriter.addData3f(Vec3.rfu( 1 + offsetx, 0, -1 - offsety))
-            vwriter.addData3f(Vec3.rfu( 1 + offsetx, 0,  1 + offsety))
-            vwriter.addData3f(Vec3.rfu(-1 - offsetx, 0,  1 + offsety))
+            vwriter.addData3f(Vec3F.rfu(-1 - offsetx, 0, -1 - offsety))
+            vwriter.addData3f(Vec3F.rfu( 1 + offsetx, 0, -1 - offsety))
+            vwriter.addData3f(Vec3F.rfu( 1 + offsetx, 0,  1 + offsety))
+            vwriter.addData3f(Vec3F.rfu(-1 - offsetx, 0,  1 + offsety))
             cwriter.addData3f(bright, bright, bright)
             cwriter.addData3f(bright, bright, bright)
             cwriter.addData3f(bright, bright, bright)
             cwriter.addData3f(bright, bright, bright)
             cwriter.addData3f(bright, bright, bright)
             cwriter.addData3f(bright, bright, bright)

+ 56 - 0
doc/ReleaseNotes

@@ -1,3 +1,59 @@
+-----------------------  RELEASE 1.10.12  -----------------------
+
+Recommended maintenance release containing primarily bug fixes.
+
+Windowing
+* Windows: Fix origin not respected when switching to windowed mode
+* macOS: Fix origin not being updated when resizing window
+* macOS: Fix off-by-one errors with mouse cursor position
+* macOS: Fix issues with confined mouse mode
+* macOS: Fix events being suppressed when moving the mouse pointer
+* macOS: Invert horizontal scroll, set `cocoa-invert-wheel-x true` to revert
+
+Rendering
+* Add `shadow-cube-map-filter` setting to enable cube map shadow filtering
+* Support floating-point FBOs in OpenGL ES 2+
+* Fix texture format selection in OpenGL with T_half_float component type
+* Added `egl-device-index` config var to select EGL device
+* Offscreen windows in tinydisplay renderer are now resizeable
+* CommonFilters now supports alternative coordinate systems
+* Fix BufferViewer frame when using a different coordinate system
+
+Deployment
+* Fix _bootlocale error in deployed application on Windows with Python 3.10
+* Include _sysconfigdata module properly when using sysconfig module
+* Fix building deploy-stub on platforms that use DT_RUNPATH instead of DT_RPATH
+* `sys.flags.optimize` is now set to 2 in Python 3.2 and above
+* Fix import errors when using scipy
+
+Miscellaneous
+* `Texture::get_ram_image_as()` fixed for 3D textures
+* Fix PStats GPU timing not working with newer NVIDIA drivers
+* Fix false negative in collision test when sphere is fully inside box
+* Resolve segmentation fault when statically linking ffmpeg module
+* Fix issue with failed mmap when using WebcamVideo on Linux
+* macOS: Keyboard/mouse devices are no longer enumerated by default
+* Fix repr of LPlane class
+* Remove dependency on ShowBase in FilterManager
+* Many new functions added to interrogatedb module to query additional info
+* Interrogate no longer writes wrappers with rvalue references to interrogatedb
+* PStats on Linux: Fix mouse motion detected outside strip chart graph area
+* Fix assertion when reading bam file with Bullet convex hull shape
+* Fix memory leak when specifying owner of a task
+* Add additional helpful debug/spam prints to display code
+
+Build
+* Support building with Python 3.11
+* Support building with OpenSSL 1.1.1 on Windows
+* Support building with OpenEXR 3.0 or 3.1 on Windows
+* Fix errors when compiling Panda headers with MinGW
+* Allow compiling Panda headers on Windows without NOMINMAX set
+* Fix wheel platform tag on manylinux aarch64
+* Experimentally allow building with mimalloc on Windows
+* Makepanda records cache timestamps as integers instead of floats
+* Makepanda can now also build tinydisplay on Linux without X11
+* Fix naming of built wheels when building for macOS 12
+
 -----------------------  RELEASE 1.10.11  -----------------------
 -----------------------  RELEASE 1.10.11  -----------------------
 
 
 Maintenance release containing assorted bug fixes and minor improvements.
 Maintenance release containing assorted bug fixes and minor improvements.

+ 301 - 1
dtool/metalibs/dtoolconfig/pydtool.cxx

@@ -45,6 +45,17 @@ static PyObject *_inP07ytDId0(PyObject *self, PyObject *args);
 static PyObject *_inP07ytHuAm(PyObject *self, PyObject *args);
 static PyObject *_inP07ytHuAm(PyObject *self, PyObject *args);
 static PyObject *_inP07yt_xr0(PyObject *self, PyObject *args);
 static PyObject *_inP07yt_xr0(PyObject *self, PyObject *args);
 static PyObject *_inP07ytH5qp(PyObject *self, PyObject *args);
 static PyObject *_inP07ytH5qp(PyObject *self, PyObject *args);
+static PyObject *_inP07ytLfJw(PyObject *self, PyObject *args);
+static PyObject *_inP07yt_Atg(PyObject *self, PyObject *args);
+static PyObject *_inP07ytlBqc(PyObject *self, PyObject *args);
+static PyObject *_inP07ytNdUp(PyObject *self, PyObject *args);
+static PyObject *_inP07ytlS0p(PyObject *self, PyObject *args);
+static PyObject *_inP07ytZZe7(PyObject *self, PyObject *args);
+static PyObject *_inP07ytV5S_(PyObject *self, PyObject *args);
+static PyObject *_inP07yto9vD(PyObject *self, PyObject *args);
+static PyObject *_inP07ytv7tF(PyObject *self, PyObject *args);
+static PyObject *_inP07ythOg6(PyObject *self, PyObject *args);
+static PyObject *_inP07ytoZUn(PyObject *self, PyObject *args);
 static PyObject *_inP07ytq45U(PyObject *self, PyObject *args);
 static PyObject *_inP07ytq45U(PyObject *self, PyObject *args);
 static PyObject *_inP07yt6IPa(PyObject *self, PyObject *args);
 static PyObject *_inP07yt6IPa(PyObject *self, PyObject *args);
 static PyObject *_inP07ytU2_B(PyObject *self, PyObject *args);
 static PyObject *_inP07ytU2_B(PyObject *self, PyObject *args);
@@ -74,7 +85,12 @@ static PyObject *_inP07yt3zru(PyObject *self, PyObject *args);
 static PyObject *_inP07ytRrg2(PyObject *self, PyObject *args);
 static PyObject *_inP07ytRrg2(PyObject *self, PyObject *args);
 static PyObject *_inP07ytEJCx(PyObject *self, PyObject *args);
 static PyObject *_inP07ytEJCx(PyObject *self, PyObject *args);
 static PyObject *_inP07ytWAZr(PyObject *self, PyObject *args);
 static PyObject *_inP07ytWAZr(PyObject *self, PyObject *args);
+static PyObject *_inP07ytHQi6(PyObject *self, PyObject *args);
 static PyObject *_inP07ytrD_M(PyObject *self, PyObject *args);
 static PyObject *_inP07ytrD_M(PyObject *self, PyObject *args);
+static PyObject *_inP07ytYaah(PyObject *self, PyObject *args);
+static PyObject *_inP07yt2otr(PyObject *self, PyObject *args);
+static PyObject *_inP07ytNP_b(PyObject *self, PyObject *args);
+static PyObject *_inP07ytrrrN(PyObject *self, PyObject *args);
 static PyObject *_inP07ytjolz(PyObject *self, PyObject *args);
 static PyObject *_inP07ytjolz(PyObject *self, PyObject *args);
 static PyObject *_inP07ytt_JD(PyObject *self, PyObject *args);
 static PyObject *_inP07ytt_JD(PyObject *self, PyObject *args);
 static PyObject *_inP07ytwEts(PyObject *self, PyObject *args);
 static PyObject *_inP07ytwEts(PyObject *self, PyObject *args);
@@ -107,6 +123,7 @@ static PyObject *_inP07ytNHcs(PyObject *self, PyObject *args);
 static PyObject *_inP07ytqHrb(PyObject *self, PyObject *args);
 static PyObject *_inP07ytqHrb(PyObject *self, PyObject *args);
 static PyObject *_inP07ytaOqq(PyObject *self, PyObject *args);
 static PyObject *_inP07ytaOqq(PyObject *self, PyObject *args);
 static PyObject *_inP07ytpTBb(PyObject *self, PyObject *args);
 static PyObject *_inP07ytpTBb(PyObject *self, PyObject *args);
+static PyObject *_inP07ytZUkn(PyObject *self, PyObject *args);
 static PyObject *_inP07ytqWOw(PyObject *self, PyObject *args);
 static PyObject *_inP07ytqWOw(PyObject *self, PyObject *args);
 static PyObject *_inP07ytHu7x(PyObject *self, PyObject *args);
 static PyObject *_inP07ytHu7x(PyObject *self, PyObject *args);
 static PyObject *_inP07ytwGnA(PyObject *self, PyObject *args);
 static PyObject *_inP07ytwGnA(PyObject *self, PyObject *args);
@@ -583,6 +600,184 @@ _inP07ytH5qp(PyObject *, PyObject *args) {
   return nullptr;
   return nullptr;
 }
 }
 
 
+/*
+ * Python simple wrapper for
+ * bool interrogate_element_has_has_function(ElementIndex element)
+ */
+static PyObject *
+_inP07ytLfJw(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = (::interrogate_element_has_has_function)((ElementIndex)param0);
+    return PyBool_FromLong(return_value);
+  }
+  return nullptr;
+}
+
+/*
+ * Python simple wrapper for
+ * FunctionIndex interrogate_element_has_function(ElementIndex element)
+ */
+static PyObject *
+_inP07yt_Atg(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    FunctionIndex return_value = (::interrogate_element_has_function)((ElementIndex)param0);
+#if PY_MAJOR_VERSION >= 3
+    return PyLong_FromLong(return_value);
+#else
+    return PyInt_FromLong(return_value);
+#endif
+  }
+  return nullptr;
+}
+
+/*
+ * Python simple wrapper for
+ * bool interrogate_element_has_clear_function(ElementIndex element)
+ */
+static PyObject *
+_inP07ytlBqc(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = (::interrogate_element_has_clear_function)((ElementIndex)param0);
+    return PyBool_FromLong(return_value);
+  }
+  return nullptr;
+}
+
+/*
+ * Python simple wrapper for
+ * FunctionIndex interrogate_element_clear_function(ElementIndex element)
+ */
+static PyObject *
+_inP07ytNdUp(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    FunctionIndex return_value = (::interrogate_element_clear_function)((ElementIndex)param0);
+#if PY_MAJOR_VERSION >= 3
+    return PyLong_FromLong(return_value);
+#else
+    return PyInt_FromLong(return_value);
+#endif
+  }
+  return nullptr;
+}
+
+/*
+ * Python simple wrapper for
+ * bool interrogate_element_has_del_function(ElementIndex element)
+ */
+static PyObject *
+_inP07ytlS0p(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = (::interrogate_element_has_del_function)((ElementIndex)param0);
+    return PyBool_FromLong(return_value);
+  }
+  return nullptr;
+}
+
+/*
+ * Python simple wrapper for
+ * FunctionIndex interrogate_element_del_function(ElementIndex element)
+ */
+static PyObject *
+_inP07ytZZe7(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    FunctionIndex return_value = (::interrogate_element_del_function)((ElementIndex)param0);
+#if PY_MAJOR_VERSION >= 3
+    return PyLong_FromLong(return_value);
+#else
+    return PyInt_FromLong(return_value);
+#endif
+  }
+  return nullptr;
+}
+
+/*
+ * Python simple wrapper for
+ * bool interrogate_element_has_insert_function(ElementIndex element)
+ */
+static PyObject *
+_inP07ytV5S_(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = (::interrogate_element_has_insert_function)((ElementIndex)param0);
+    return PyBool_FromLong(return_value);
+  }
+  return nullptr;
+}
+
+/*
+ * Python simple wrapper for
+ * FunctionIndex interrogate_element_insert_function(ElementIndex element)
+ */
+static PyObject *
+_inP07yto9vD(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    FunctionIndex return_value = (::interrogate_element_insert_function)((ElementIndex)param0);
+#if PY_MAJOR_VERSION >= 3
+    return PyLong_FromLong(return_value);
+#else
+    return PyInt_FromLong(return_value);
+#endif
+  }
+  return nullptr;
+}
+
+/*
+ * Python simple wrapper for
+ * bool interrogate_element_has_getkey_function(ElementIndex element)
+ */
+static PyObject *
+_inP07ytv7tF(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = (::interrogate_element_has_getkey_function)((ElementIndex)param0);
+    return PyBool_FromLong(return_value);
+  }
+  return nullptr;
+}
+
+/*
+ * Python simple wrapper for
+ * FunctionIndex interrogate_element_getkey_function(ElementIndex element)
+ */
+static PyObject *
+_inP07ythOg6(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    FunctionIndex return_value = (::interrogate_element_getkey_function)((ElementIndex)param0);
+#if PY_MAJOR_VERSION >= 3
+    return PyLong_FromLong(return_value);
+#else
+    return PyInt_FromLong(return_value);
+#endif
+  }
+  return nullptr;
+}
+
+/*
+ * Python simple wrapper for
+ * FunctionIndex interrogate_element_length_function(ElementIndex element)
+ */
+static PyObject *
+_inP07ytoZUn(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    FunctionIndex return_value = (::interrogate_element_length_function)((ElementIndex)param0);
+#if PY_MAJOR_VERSION >= 3
+    return PyLong_FromLong(return_value);
+#else
+    return PyInt_FromLong(return_value);
+#endif
+  }
+  return nullptr;
+}
+
 /*
 /*
  * Python simple wrapper for
  * Python simple wrapper for
  * bool interrogate_element_is_sequence(ElementIndex element)
  * bool interrogate_element_is_sequence(ElementIndex element)
@@ -1060,6 +1255,24 @@ _inP07ytWAZr(PyObject *, PyObject *args) {
   return nullptr;
   return nullptr;
 }
 }
 
 
+/*
+ * Python simple wrapper for
+ * FunctionIndex interrogate_wrapper_function(FunctionWrapperIndex wrapper)
+ */
+static PyObject *
+_inP07ytHQi6(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    FunctionIndex return_value = (::interrogate_wrapper_function)((FunctionWrapperIndex)param0);
+#if PY_MAJOR_VERSION >= 3
+    return PyLong_FromLong(return_value);
+#else
+    return PyInt_FromLong(return_value);
+#endif
+  }
+  return nullptr;
+}
+
 /*
 /*
  * Python simple wrapper for
  * Python simple wrapper for
  * bool interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper)
  * bool interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper)
@@ -1074,6 +1287,62 @@ _inP07ytrD_M(PyObject *, PyObject *args) {
   return nullptr;
   return nullptr;
 }
 }
 
 
+/*
+ * Python simple wrapper for
+ * bool interrogate_wrapper_is_copy_constructor(FunctionWrapperIndex wrapper)
+ */
+static PyObject *
+_inP07ytYaah(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = (::interrogate_wrapper_is_copy_constructor)((FunctionWrapperIndex)param0);
+    return PyBool_FromLong(return_value);
+  }
+  return nullptr;
+}
+
+/*
+ * Python simple wrapper for
+ * bool interrogate_wrapper_is_coerce_constructor(FunctionWrapperIndex wrapper)
+ */
+static PyObject *
+_inP07yt2otr(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = (::interrogate_wrapper_is_coerce_constructor)((FunctionWrapperIndex)param0);
+    return PyBool_FromLong(return_value);
+  }
+  return nullptr;
+}
+
+/*
+ * Python simple wrapper for
+ * bool interrogate_wrapper_is_extension(FunctionWrapperIndex wrapper)
+ */
+static PyObject *
+_inP07ytNP_b(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = (::interrogate_wrapper_is_extension)((FunctionWrapperIndex)param0);
+    return PyBool_FromLong(return_value);
+  }
+  return nullptr;
+}
+
+/*
+ * Python simple wrapper for
+ * bool interrogate_wrapper_is_deprecated(FunctionWrapperIndex wrapper)
+ */
+static PyObject *
+_inP07ytrrrN(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = (::interrogate_wrapper_is_deprecated)((FunctionWrapperIndex)param0);
+    return PyBool_FromLong(return_value);
+  }
+  return nullptr;
+}
+
 /*
 /*
  * Python simple wrapper for
  * Python simple wrapper for
  * bool interrogate_wrapper_has_comment(FunctionWrapperIndex wrapper)
  * bool interrogate_wrapper_has_comment(FunctionWrapperIndex wrapper)
@@ -1613,6 +1882,20 @@ _inP07ytpTBb(PyObject *, PyObject *args) {
   return nullptr;
   return nullptr;
 }
 }
 
 
+/*
+ * Python simple wrapper for
+ * bool interrogate_type_is_deprecated(TypeIndex type)
+ */
+static PyObject *
+_inP07ytZUkn(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = (::interrogate_type_is_deprecated)((TypeIndex)param0);
+    return PyBool_FromLong(return_value);
+  }
+  return nullptr;
+}
+
 /*
 /*
  * Python simple wrapper for
  * Python simple wrapper for
  * char const *interrogate_type_name(TypeIndex type)
  * char const *interrogate_type_name(TypeIndex type)
@@ -2652,6 +2935,17 @@ static PyMethodDef python_simple_funcs[] = {
   { "interrogate_element_getter", &_inP07ytHuAm, METH_VARARGS, nullptr },
   { "interrogate_element_getter", &_inP07ytHuAm, METH_VARARGS, nullptr },
   { "interrogate_element_has_setter", &_inP07yt_xr0, METH_VARARGS, nullptr },
   { "interrogate_element_has_setter", &_inP07yt_xr0, METH_VARARGS, nullptr },
   { "interrogate_element_setter", &_inP07ytH5qp, METH_VARARGS, nullptr },
   { "interrogate_element_setter", &_inP07ytH5qp, METH_VARARGS, nullptr },
+  { "interrogate_element_has_has_function", &_inP07ytLfJw, METH_VARARGS, nullptr },
+  { "interrogate_element_has_function", &_inP07yt_Atg, METH_VARARGS, nullptr },
+  { "interrogate_element_has_clear_function", &_inP07ytlBqc, METH_VARARGS, nullptr },
+  { "interrogate_element_clear_function", &_inP07ytNdUp, METH_VARARGS, nullptr },
+  { "interrogate_element_has_del_function", &_inP07ytlS0p, METH_VARARGS, nullptr },
+  { "interrogate_element_del_function", &_inP07ytZZe7, METH_VARARGS, nullptr },
+  { "interrogate_element_has_insert_function", &_inP07ytV5S_, METH_VARARGS, nullptr },
+  { "interrogate_element_insert_function", &_inP07yto9vD, METH_VARARGS, nullptr },
+  { "interrogate_element_has_getkey_function", &_inP07ytv7tF, METH_VARARGS, nullptr },
+  { "interrogate_element_getkey_function", &_inP07ythOg6, METH_VARARGS, nullptr },
+  { "interrogate_element_length_function", &_inP07ytoZUn, METH_VARARGS, nullptr },
   { "interrogate_element_is_sequence", &_inP07ytq45U, METH_VARARGS, nullptr },
   { "interrogate_element_is_sequence", &_inP07ytq45U, METH_VARARGS, nullptr },
   { "interrogate_element_is_mapping", &_inP07yt6IPa, METH_VARARGS, nullptr },
   { "interrogate_element_is_mapping", &_inP07yt6IPa, METH_VARARGS, nullptr },
   { "interrogate_number_of_globals", &_inP07ytU2_B, METH_VARARGS, nullptr },
   { "interrogate_number_of_globals", &_inP07ytU2_B, METH_VARARGS, nullptr },
@@ -2681,7 +2975,12 @@ static PyMethodDef python_simple_funcs[] = {
   { "interrogate_function_number_of_python_wrappers", &_inP07ytRrg2, METH_VARARGS, nullptr },
   { "interrogate_function_number_of_python_wrappers", &_inP07ytRrg2, METH_VARARGS, nullptr },
   { "interrogate_function_python_wrapper", &_inP07ytEJCx, METH_VARARGS, nullptr },
   { "interrogate_function_python_wrapper", &_inP07ytEJCx, METH_VARARGS, nullptr },
   { "interrogate_wrapper_name", &_inP07ytWAZr, METH_VARARGS, nullptr },
   { "interrogate_wrapper_name", &_inP07ytWAZr, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_function", &_inP07ytHQi6, METH_VARARGS, nullptr },
   { "interrogate_wrapper_is_callable_by_name", &_inP07ytrD_M, METH_VARARGS, nullptr },
   { "interrogate_wrapper_is_callable_by_name", &_inP07ytrD_M, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_is_copy_constructor", &_inP07ytYaah, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_is_coerce_constructor", &_inP07yt2otr, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_is_extension", &_inP07ytNP_b, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_is_deprecated", &_inP07ytrrrN, METH_VARARGS, nullptr },
   { "interrogate_wrapper_has_comment", &_inP07ytjolz, METH_VARARGS, nullptr },
   { "interrogate_wrapper_has_comment", &_inP07ytjolz, METH_VARARGS, nullptr },
   { "interrogate_wrapper_comment", &_inP07ytt_JD, METH_VARARGS, nullptr },
   { "interrogate_wrapper_comment", &_inP07ytt_JD, METH_VARARGS, nullptr },
   { "interrogate_wrapper_has_return_value", &_inP07ytwEts, METH_VARARGS, nullptr },
   { "interrogate_wrapper_has_return_value", &_inP07ytwEts, METH_VARARGS, nullptr },
@@ -2714,6 +3013,7 @@ static PyMethodDef python_simple_funcs[] = {
   { "interrogate_get_type_by_scoped_name", &_inP07ytqHrb, METH_VARARGS, nullptr },
   { "interrogate_get_type_by_scoped_name", &_inP07ytqHrb, METH_VARARGS, nullptr },
   { "interrogate_get_type_by_true_name", &_inP07ytaOqq, METH_VARARGS, nullptr },
   { "interrogate_get_type_by_true_name", &_inP07ytaOqq, METH_VARARGS, nullptr },
   { "interrogate_type_is_global", &_inP07ytpTBb, METH_VARARGS, nullptr },
   { "interrogate_type_is_global", &_inP07ytpTBb, METH_VARARGS, nullptr },
+  { "interrogate_type_is_deprecated", &_inP07ytZUkn, METH_VARARGS, nullptr },
   { "interrogate_type_name", &_inP07ytqWOw, METH_VARARGS, nullptr },
   { "interrogate_type_name", &_inP07ytqWOw, METH_VARARGS, nullptr },
   { "interrogate_type_scoped_name", &_inP07ytHu7x, METH_VARARGS, nullptr },
   { "interrogate_type_scoped_name", &_inP07ytHu7x, METH_VARARGS, nullptr },
   { "interrogate_type_true_name", &_inP07ytwGnA, METH_VARARGS, nullptr },
   { "interrogate_type_true_name", &_inP07ytwGnA, METH_VARARGS, nullptr },
@@ -2782,7 +3082,7 @@ static PyMethodDef python_simple_funcs[] = {
 #if PY_MAJOR_VERSION >= 3
 #if PY_MAJOR_VERSION >= 3
 static struct PyModuleDef python_simple_module = {
 static struct PyModuleDef python_simple_module = {
   PyModuleDef_HEAD_INIT,
   PyModuleDef_HEAD_INIT,
-  "interrogatedb",
+  "panda3d.interrogatedb",
   nullptr,
   nullptr,
   -1,
   -1,
   python_simple_funcs,
   python_simple_funcs,

+ 2 - 0
dtool/src/cppparser/CMakeLists.txt

@@ -1,4 +1,5 @@
 set(P3CPPPARSER_HEADERS
 set(P3CPPPARSER_HEADERS
+  cppAttributeList.h
   cppArrayType.h cppBison.yxx cppBisonDefs.h
   cppArrayType.h cppBison.yxx cppBisonDefs.h
   cppClassTemplateParameter.h cppCommentBlock.h
   cppClassTemplateParameter.h cppCommentBlock.h
   cppClosureType.h cppConstType.h
   cppClosureType.h cppConstType.h
@@ -17,6 +18,7 @@ set(P3CPPPARSER_HEADERS
 )
 )
 
 
 set(P3CPPPARSER_SOURCES
 set(P3CPPPARSER_SOURCES
+  cppAttributeList.cxx
   cppArrayType.cxx ${CMAKE_CURRENT_BINARY_DIR}/cppBison.cxx
   cppArrayType.cxx ${CMAKE_CURRENT_BINARY_DIR}/cppBison.cxx
   cppClassTemplateParameter.cxx
   cppClassTemplateParameter.cxx
   cppCommentBlock.cxx cppClosureType.cxx cppConstType.cxx cppDeclaration.cxx
   cppCommentBlock.cxx cppClosureType.cxx cppConstType.cxx cppDeclaration.cxx

+ 5 - 0
dtool/src/cppparser/cppArrayType.cxx

@@ -189,6 +189,11 @@ output_instance(std::ostream &out, int indent_level, CPPScope *scope,
     brackets << *_bounds;
     brackets << *_bounds;
   }
   }
   brackets << "]";
   brackets << "]";
+
+  if (!_attributes.is_empty()) {
+    brackets << " " << _attributes;
+  }
+
   std::string bracketsstr = brackets.str();
   std::string bracketsstr = brackets.str();
 
 
   _element_type->output_instance(out, indent_level, scope, complete,
   _element_type->output_instance(out, indent_level, scope, complete,

+ 196 - 0
dtool/src/cppparser/cppAttributeList.cxx

@@ -0,0 +1,196 @@
+/**
+ * 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 cppAttributeList.cxx
+ * @author rdb
+ * @date 2022-10-23
+ */
+
+#include "cppAttributeList.h"
+#include "cppExpression.h"
+#include "cppIdentifier.h"
+#include "cppType.h"
+
+/**
+ * Returns true if no attributes have been defined.
+ */
+bool CPPAttributeList::
+is_empty() const {
+  return _attributes.empty() && _alignas == nullptr;
+}
+
+/**
+ * Returns true if the attribute list has an attribute with the given name.
+ */
+bool CPPAttributeList::
+has_attribute(const std::string &name) const {
+  for (const Attribute &attr : _attributes) {
+    if (attr._ident->get_fully_scoped_name() == name) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ *
+ */
+bool CPPAttributeList::
+operator == (const CPPAttributeList &other) const {
+  if (_attributes.size() != other._attributes.size()) {
+    return false;
+  }
+  if ((_alignas != nullptr) != (other._alignas != nullptr)) {
+    return false;
+  }
+  if (_alignas != nullptr && *_alignas != *other._alignas) {
+    return false;
+  }
+  for (size_t i = 0; i < _attributes.size(); ++i) {
+    if (_attributes[i]._ident != other._attributes[i]._ident) {
+      return false;
+    }
+    if (_attributes[i]._reason != other._attributes[i]._reason) {
+      return false;
+    }
+  }
+  return true;
+}
+
+/**
+ *
+ */
+bool CPPAttributeList::
+operator != (const CPPAttributeList &other) const {
+  return !(*this == other);
+}
+
+/**
+ *
+ */
+bool CPPAttributeList::
+operator < (const CPPAttributeList &other) const {
+  if (_attributes.size() != other._attributes.size()) {
+    return _attributes.size() < other._attributes.size();
+  }
+  if ((_alignas != nullptr) != (other._alignas != nullptr)) {
+    return _alignas == nullptr;
+  }
+  if (_alignas != nullptr && *_alignas != *other._alignas) {
+    return *_alignas < *other._alignas;
+  }
+  for (size_t i = 0; i < _attributes.size(); ++i) {
+    if (_attributes[i]._ident != other._attributes[i]._ident) {
+      return _attributes[i]._ident < other._attributes[i]._ident;
+    }
+    if (_attributes[i]._reason != other._attributes[i]._reason) {
+      return _attributes[i]._reason < other._attributes[i]._reason;
+    }
+  }
+  return false;
+}
+
+/**
+ * Adds an attribute.
+ */
+void CPPAttributeList::
+add_attribute(CPPIdentifier *ident) {
+  _attributes.push_back({ident});
+}
+
+/**
+ * Adds an attribute.
+ */
+void CPPAttributeList::
+add_attribute(CPPIdentifier *ident, std::string reason) {
+  _attributes.push_back({ident, std::move(reason)});
+}
+
+/**
+ * Adds an alignas specifier.
+ */
+void CPPAttributeList::
+add_alignas(int size) {
+  if (_alignas == nullptr || size >= _alignas->evaluate().as_integer()) {
+    _alignas = new CPPExpression(size);
+  }
+}
+
+/**
+ * Adds an alignas specifier.
+ */
+void CPPAttributeList::
+add_alignas(CPPType *type) {
+  CPPExpression expr = CPPExpression::alignof_func(type);
+  if (_alignas == nullptr || expr.evaluate().as_integer() > _alignas->evaluate().as_integer()) {
+    _alignas = new CPPExpression(expr);
+  }
+}
+
+/**
+ * Adds an alignas specifier.
+ */
+void CPPAttributeList::
+add_alignas(CPPExpression *expr) {
+  if (_alignas == nullptr || expr->evaluate().as_integer() > _alignas->evaluate().as_integer()) {
+    _alignas = expr;
+  }
+}
+
+/**
+ * Merges the other list into this one.
+ */
+void CPPAttributeList::
+add_attributes_from(const CPPAttributeList &other) {
+  for (const Attribute &attr : other._attributes) {
+    _attributes.push_back(attr);
+  }
+
+  if (other._alignas != nullptr) {
+    add_alignas(other._alignas);
+  }
+}
+
+/**
+ *
+ */
+void CPPAttributeList::
+output(std::ostream &out, CPPScope *scope) const {
+  Attributes::const_iterator it = _attributes.begin();
+  if (it != _attributes.end()) {
+    out << "[[";
+    (*it)._ident->output(out, scope);
+    if (!(*it)._reason.empty()) {
+      out << "(" << (*it)._reason << ")";
+    }
+
+    for (++it; it != _attributes.end(); ++it) {
+      out << ", ";
+      (*it)._ident->output(out, scope);
+      if (!(*it)._reason.empty()) {
+        out << "(" << (*it)._reason << ")";
+      }
+    }
+
+    out << "]]";
+
+    if (_alignas != nullptr) {
+      out << " ";
+    }
+  }
+
+  if (_alignas != nullptr) {
+    out << "alignas(";
+    if (_alignas->_type == CPPExpression::T_alignof) {
+      _alignas->_u._typecast._to->output(out, 0, scope, false);
+    } else {
+      _alignas->output(out, 0, scope, false);
+    }
+    out << ")";
+  }
+}

+ 65 - 0
dtool/src/cppparser/cppAttributeList.h

@@ -0,0 +1,65 @@
+/**
+ * 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 cppAttributeList.h
+ * @author rdb
+ * @date 2022-10-23
+ */
+
+#ifndef CPPATTRIBUTELIST_H
+#define CPPATTRIBUTELIST_H
+
+#include "dtoolbase.h"
+
+#include <vector>
+
+class CPPExpression;
+class CPPIdentifier;
+class CPPScope;
+class CPPType;
+
+/**
+ * A list of square-bracket attributes and/or alignas specifiers.
+ */
+class CPPAttributeList {
+public:
+  bool is_empty() const;
+  bool has_attribute(const std::string &name) const;
+
+  bool operator == (const CPPAttributeList &other) const;
+  bool operator != (const CPPAttributeList &other) const;
+  bool operator < (const CPPAttributeList &other) const;
+
+  void add_attribute(CPPIdentifier *ident);
+  void add_attribute(CPPIdentifier *ident, std::string reason);
+
+  void add_alignas(int size);
+  void add_alignas(CPPType *type);
+  void add_alignas(CPPExpression *expr);
+
+  void add_attributes_from(const CPPAttributeList &other);
+
+  struct Attribute {
+    CPPIdentifier *_ident;
+    std::string _reason;
+  };
+
+  typedef std::vector<Attribute> Attributes;
+  Attributes _attributes;
+  CPPExpression *_alignas = nullptr;
+
+  void output(std::ostream &out, CPPScope *scope) const;
+};
+
+inline std::ostream &
+operator << (std::ostream &out, const CPPAttributeList &alist) {
+  alist.output(out, nullptr);
+  return out;
+}
+
+#endif

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


+ 6 - 3
dtool/src/cppparser/cppBison.h.prebuilt

@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.7.3.  */
+/* A Bison parser, made by GNU Bison 3.8.2.  */
 
 
 /* Bison interface for Yacc-like parsers in C
 /* Bison interface for Yacc-like parsers in C
 
 
-   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
    Inc.
    Inc.
 
 
    This program is free software: you can redistribute it and/or modify
    This program is free software: you can redistribute it and/or modify
@@ -16,7 +16,7 @@
    GNU General Public License for more details.
    GNU General Public License for more details.
 
 
    You should have received a copy of the GNU General Public License
    You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
 
 /* As a special exception, you may create a larger work that contains
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
    part or all of the Bison parser skeleton and distribute that work
@@ -208,6 +208,7 @@ extern int cppyydebug;
   typedef enum yytokentype yytoken_kind_t;
   typedef enum yytokentype yytoken_kind_t;
 #endif
 #endif
 /* Token kinds.  */
 /* Token kinds.  */
+#define YYEMPTY -2
 #define YYEOF 0
 #define YYEOF 0
 #define YYerror 256
 #define YYerror 256
 #define YYUNDEF 257
 #define YYUNDEF 257
@@ -380,6 +381,8 @@ struct YYLTYPE
 
 
 
 
 
 
+
 int cppyyparse (void);
 int cppyyparse (void);
 
 
+
 #endif /* !YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED  */
 #endif /* !YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED  */

File diff suppressed because it is too large
+ 256 - 203
dtool/src/cppparser/cppBison.yxx


+ 2 - 0
dtool/src/cppparser/cppBisonDefs.h

@@ -23,6 +23,7 @@
 
 
 #include <string>
 #include <string>
 
 
+#include "cppAttributeList.h"
 #include "cppClosureType.h"
 #include "cppClosureType.h"
 #include "cppExtensionType.h"
 #include "cppExtensionType.h"
 #include "cppFile.h"
 #include "cppFile.h"
@@ -65,6 +66,7 @@ extern CPPPreprocessor *current_lexer;
 class cppyystype {
 class cppyystype {
 public:
 public:
   std::string str;
   std::string str;
+  CPPAttributeList attr_list;
   union {
   union {
     unsigned long long integer;
     unsigned long long integer;
     long double real;
     long double real;

+ 4 - 0
dtool/src/cppparser/cppClosureType.cxx

@@ -152,6 +152,10 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) cons
     out << " noexcept";
     out << " noexcept";
   }
   }
 
 
+  if (!_attributes.is_empty()) {
+    out << " " << _attributes;
+  }
+
   if (_return_type != nullptr) {
   if (_return_type != nullptr) {
     out << " -> ";
     out << " -> ";
     _return_type->output(out, indent_level, scope, false);
     _return_type->output(out, indent_level, scope, false);

+ 22 - 3
dtool/src/cppparser/cppDeclaration.cxx

@@ -18,8 +18,9 @@
  *
  *
  */
  */
 CPPDeclaration::
 CPPDeclaration::
-CPPDeclaration(const CPPFile &file) :
-  _file(file)
+CPPDeclaration(const CPPFile &file, CPPAttributeList attr) :
+  _file(file),
+  _attributes(std::move(attr))
 {
 {
   _vis = V_unknown;
   _vis = V_unknown;
   _template_scope = nullptr;
   _template_scope = nullptr;
@@ -34,7 +35,8 @@ CPPDeclaration(const CPPDeclaration &copy) :
   _vis(copy._vis),
   _vis(copy._vis),
   _template_scope(copy._template_scope),
   _template_scope(copy._template_scope),
   _file(copy._file),
   _file(copy._file),
-  _leading_comment(copy._leading_comment)
+  _leading_comment(copy._leading_comment),
+  _attributes(copy._attributes)
 {
 {
 }
 }
 
 
@@ -47,6 +49,7 @@ operator = (const CPPDeclaration &copy) {
   _template_scope = copy._template_scope;
   _template_scope = copy._template_scope;
   _file = copy._file;
   _file = copy._file;
   _leading_comment = copy._leading_comment;
   _leading_comment = copy._leading_comment;
+  _attributes = copy._attributes;
   return *this;
   return *this;
 }
 }
 
 
@@ -135,6 +138,22 @@ substitute_decl(SubstDecl &subst, CPPScope *, CPPScope *) {
   return this;
   return this;
 }
 }
 
 
+/**
+ *
+ */
+void CPPDeclaration::
+output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const {
+  out << _attributes;
+}
+
+/**
+ *
+ */
+CPPDeclaration::SubType CPPDeclaration::
+get_subtype() const {
+  return ST_empty;
+}
+
 /**
 /**
  *
  *
  */
  */

+ 8 - 3
dtool/src/cppparser/cppDeclaration.h

@@ -19,6 +19,7 @@
 #include "cppVisibility.h"
 #include "cppVisibility.h"
 #include "cppFile.h"
 #include "cppFile.h"
 #include "cppCommentBlock.h"
 #include "cppCommentBlock.h"
+#include "cppAttributeList.h"
 
 
 #include <string>
 #include <string>
 #include <vector>
 #include <vector>
@@ -59,6 +60,9 @@ class CPPPreprocessor;
 class CPPDeclaration {
 class CPPDeclaration {
 public:
 public:
   enum SubType {
   enum SubType {
+    // Empty declaration
+    ST_empty,
+
     // Subtypes of CPPDeclaration
     // Subtypes of CPPDeclaration
     ST_instance,
     ST_instance,
     ST_type_declaration,
     ST_type_declaration,
@@ -87,7 +91,7 @@ public:
     ST_closure,
     ST_closure,
   };
   };
 
 
-  CPPDeclaration(const CPPFile &file);
+  CPPDeclaration(const CPPFile &file, CPPAttributeList attr = CPPAttributeList());
   CPPDeclaration(const CPPDeclaration &copy);
   CPPDeclaration(const CPPDeclaration &copy);
   virtual ~CPPDeclaration() {};
   virtual ~CPPDeclaration() {};
 
 
@@ -114,9 +118,9 @@ public:
   Instantiations _instantiations;
   Instantiations _instantiations;
 
 
   virtual void output(std::ostream &out, int indent_level, CPPScope *scope,
   virtual void output(std::ostream &out, int indent_level, CPPScope *scope,
-                      bool complete) const=0;
+                      bool complete) const;
 
 
-  virtual SubType get_subtype() const=0;
+  virtual SubType get_subtype() const;
 
 
   virtual CPPInstance *as_instance();
   virtual CPPInstance *as_instance();
   virtual CPPClassTemplateParameter *as_class_template_parameter();
   virtual CPPClassTemplateParameter *as_class_template_parameter();
@@ -216,6 +220,7 @@ public:
   CPPTemplateScope *_template_scope;
   CPPTemplateScope *_template_scope;
   CPPFile _file;
   CPPFile _file;
   CPPCommentBlock *_leading_comment;
   CPPCommentBlock *_leading_comment;
+  CPPAttributeList _attributes;
 
 
 protected:
 protected:
   virtual bool is_equal(const CPPDeclaration *other) const;
   virtual bool is_equal(const CPPDeclaration *other) const;

+ 23 - 12
dtool/src/cppparser/cppEnumType.cxx

@@ -26,8 +26,8 @@
  */
  */
 CPPEnumType::
 CPPEnumType::
 CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
 CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
-            CPPScope *scope, const CPPFile &file) :
-  CPPExtensionType(type, ident, current_scope, file),
+            CPPScope *scope, const CPPFile &file, CPPAttributeList attr) :
+  CPPExtensionType(type, ident, current_scope, file, std::move(attr)),
   _scope(scope),
   _scope(scope),
   _element_type(nullptr),
   _element_type(nullptr),
   _last_value(nullptr)
   _last_value(nullptr)
@@ -44,8 +44,9 @@ CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
  */
  */
 CPPEnumType::
 CPPEnumType::
 CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type,
 CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type,
-            CPPScope *current_scope, CPPScope *scope, const CPPFile &file) :
-  CPPExtensionType(type, ident, current_scope, file),
+            CPPScope *current_scope, CPPScope *scope, const CPPFile &file,
+            CPPAttributeList attr) :
+  CPPExtensionType(type, ident, current_scope, file, std::move(attr)),
   _scope(scope),
   _scope(scope),
   _element_type(element_type),
   _element_type(element_type),
   _last_value(nullptr)
   _last_value(nullptr)
@@ -89,7 +90,9 @@ get_underlying_type() {
  *
  *
  */
  */
 CPPInstance *CPPEnumType::
 CPPInstance *CPPEnumType::
-add_element(const std::string &name, CPPExpression *value, CPPPreprocessor *preprocessor, const cppyyltype &pos) {
+add_element(const std::string &name, CPPExpression *value,
+            CPPPreprocessor *preprocessor, const cppyyltype &pos,
+            CPPAttributeList attr) {
   CPPIdentifier *ident = new CPPIdentifier(name);
   CPPIdentifier *ident = new CPPIdentifier(name);
   ident->_native_scope = _parent_scope;
   ident->_native_scope = _parent_scope;
 
 
@@ -102,6 +105,7 @@ add_element(const std::string &name, CPPExpression *value, CPPPreprocessor *prep
     inst = new CPPInstance(this, ident);
     inst = new CPPInstance(this, ident);
   }
   }
   inst->_storage_class |= CPPInstance::SC_constexpr;
   inst->_storage_class |= CPPInstance::SC_constexpr;
+  inst->_attributes = std::move(attr);
   _elements.push_back(inst);
   _elements.push_back(inst);
 
 
   if (value == nullptr) {
   if (value == nullptr) {
@@ -269,9 +273,12 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) cons
       out << _type << " ";
       out << _type << " ";
     }
     }
     out << _ident->get_local_name(scope);
     out << _ident->get_local_name(scope);
-
-  } else {
+  }
+  else {
     out << _type;
     out << _type;
+    if (!_attributes.is_empty()) {
+      out << " " << _attributes;
+    }
     if (_ident != nullptr) {
     if (_ident != nullptr) {
       out << " " << _ident->get_local_name(scope);
       out << " " << _ident->get_local_name(scope);
     }
     }
@@ -280,11 +287,15 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) cons
     }
     }
 
 
     out << " {\n";
     out << " {\n";
-    Elements::const_iterator ei;
-    for (ei = _elements.begin(); ei != _elements.end(); ++ei) {
-      indent(out, indent_level + 2) << (*ei)->get_local_name();
-      if ((*ei)->_initializer != nullptr) {
-        out << " = " << *(*ei)->_initializer;
+    for (CPPInstance *element : _elements) {
+      indent(out, indent_level + 2) << element->get_local_name();
+
+      if (!element->_attributes.is_empty()) {
+        out << " " << element->_attributes;
+      }
+
+      if (element->_initializer != nullptr) {
+        out << " = " << *element->_initializer;
       }
       }
       out << ",\n";
       out << ",\n";
     }
     }

+ 6 - 3
dtool/src/cppparser/cppEnumType.h

@@ -32,15 +32,18 @@ class CPPScope;
 class CPPEnumType : public CPPExtensionType {
 class CPPEnumType : public CPPExtensionType {
 public:
 public:
   CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
   CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
-              CPPScope *scope, const CPPFile &file);
+              CPPScope *scope, const CPPFile &file,
+              CPPAttributeList attr = CPPAttributeList());
   CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type,
   CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type,
-              CPPScope *current_scope, CPPScope *scope, const CPPFile &file);
+              CPPScope *current_scope, CPPScope *scope, const CPPFile &file,
+              CPPAttributeList attr = CPPAttributeList());
 
 
   bool is_scoped() const;
   bool is_scoped() const;
   CPPType *get_underlying_type();
   CPPType *get_underlying_type();
 
 
   CPPInstance *add_element(const std::string &name, CPPExpression *value,
   CPPInstance *add_element(const std::string &name, CPPExpression *value,
-                           CPPPreprocessor *preprocessor, const cppyyltype &pos);
+                           CPPPreprocessor *preprocessor, const cppyyltype &pos,
+                           CPPAttributeList attr = CPPAttributeList());
 
 
   virtual bool is_incomplete() const;
   virtual bool is_incomplete() const;
 
 

+ 5 - 1
dtool/src/cppparser/cppExtensionType.cxx

@@ -23,7 +23,7 @@
 CPPExtensionType::
 CPPExtensionType::
 CPPExtensionType(CPPExtensionType::Type type,
 CPPExtensionType(CPPExtensionType::Type type,
                  CPPIdentifier *ident, CPPScope *current_scope,
                  CPPIdentifier *ident, CPPScope *current_scope,
-                 const CPPFile &file) :
+                 const CPPFile &file, CPPAttributeList attr) :
   CPPType(file),
   CPPType(file),
   _type(type), _ident(ident),
   _type(type), _ident(ident),
   _alignment(nullptr)
   _alignment(nullptr)
@@ -31,6 +31,7 @@ CPPExtensionType(CPPExtensionType::Type type,
   if (_ident != nullptr) {
   if (_ident != nullptr) {
     _ident->_native_scope = current_scope;
     _ident->_native_scope = current_scope;
   }
   }
+  _attributes = std::move(attr);
 }
 }
 
 
 /**
 /**
@@ -215,6 +216,9 @@ output(std::ostream &out, int, CPPScope *scope, bool complete) const {
     if (complete || cppparser_output_class_keyword) {
     if (complete || cppparser_output_class_keyword) {
       out << _type << " ";
       out << _type << " ";
     }
     }
+    if (complete && !_attributes.is_empty()) {
+      out << _attributes << " ";
+    }
     out << _ident->get_local_name(scope);
     out << _ident->get_local_name(scope);
 
 
   } else if (!_typedefs.empty()) {
   } else if (!_typedefs.empty()) {

+ 1 - 1
dtool/src/cppparser/cppExtensionType.h

@@ -39,7 +39,7 @@ public:
   };
   };
 
 
   CPPExtensionType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
   CPPExtensionType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
-                   const CPPFile &file);
+                   const CPPFile &file, CPPAttributeList attr = CPPAttributeList());
 
 
   virtual std::string get_simple_name() const;
   virtual std::string get_simple_name() const;
   virtual std::string get_local_name(CPPScope *scope = nullptr) const;
   virtual std::string get_local_name(CPPScope *scope = nullptr) const;

+ 20 - 9
dtool/src/cppparser/cppFunctionType.cxx

@@ -224,10 +224,13 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete,
     if (_flags & F_override) {
     if (_flags & F_override) {
       out << " override";
       out << " override";
     }
     }
+    if (!_attributes.is_empty()) {
+      out << " " << _attributes;
+    }
     out << " -> ";
     out << " -> ";
     _return_type->output(out, indent_level, scope, false);
     _return_type->output(out, indent_level, scope, false);
-
-  } else {
+  }
+  else {
     _return_type->output(out, indent_level, scope, complete);
     _return_type->output(out, indent_level, scope, complete);
     out << "(";
     out << "(";
     _parameters->output(out, scope, true, num_default_parameters);
     _parameters->output(out, scope, true, num_default_parameters);
@@ -244,6 +247,9 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete,
     if (_flags & F_override) {
     if (_flags & F_override) {
       out << " override";
       out << " override";
     }
     }
+    if (!_attributes.is_empty()) {
+      out << " " << _attributes;
+    }
   }
   }
 }
 }
 
 
@@ -278,8 +284,8 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
   if (_flags & (F_constructor | F_destructor)) {
   if (_flags & (F_constructor | F_destructor)) {
     // No return type for constructors and destructors.
     // No return type for constructors and destructors.
     out << prename << name << str;
     out << prename << name << str;
-
-  } else if (_flags & F_trailing_return_type) {
+  }
+  else if (_flags & F_trailing_return_type) {
     // It was declared using trailing return type, so let's format it that
     // It was declared using trailing return type, so let's format it that
     // way.
     // way.
     out << "auto ";
     out << "auto ";
@@ -291,12 +297,13 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
     }
     }
 
 
     out << str;
     out << str;
-
-  } else if (_flags & F_operator_typecast) {
+  }
+  else if (_flags & F_operator_typecast) {
     out << "operator ";
     out << "operator ";
-    _return_type->output_instance(out, indent_level, scope, complete, "", prename + str);
-
-  } else {
+    _return_type->output_instance(out, indent_level, scope, complete,
+                                  "", prename + str);
+  }
+  else {
     if (prename.empty()) {
     if (prename.empty()) {
       _return_type->output_instance(out, indent_level, scope, complete,
       _return_type->output_instance(out, indent_level, scope, complete,
                                     "", prename + name + str);
                                     "", prename + name + str);
@@ -322,6 +329,10 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
     out << " override";
     out << " override";
   }
   }
 
 
+  if (!_attributes.is_empty()) {
+    out << " " << _attributes;
+  }
+
   if (_flags & F_trailing_return_type) {
   if (_flags & F_trailing_return_type) {
     out << " -> ";
     out << " -> ";
     _return_type->output(out, indent_level, scope, false);
     _return_type->output(out, indent_level, scope, false);

+ 8 - 0
dtool/src/cppparser/cppIdentifier.cxx

@@ -84,6 +84,14 @@ add_name(const CPPNameComponent &name) {
   _names.push_back(name);
   _names.push_back(name);
 }
 }
 
 
+/**
+ *
+ */
+void CPPIdentifier::
+prepend(CPPIdentifier *ident) {
+  _names.insert(_names.begin(), ident->_names.begin(), ident->_names.end());
+}
+
 /**
 /**
  *
  *
  */
  */

+ 2 - 0
dtool/src/cppparser/cppIdentifier.h

@@ -41,6 +41,8 @@ public:
   void add_name(const std::string &name);
   void add_name(const std::string &name);
   void add_name(const CPPNameComponent &name);
   void add_name(const CPPNameComponent &name);
 
 
+  void prepend(CPPIdentifier *ident);
+
   bool operator == (const CPPIdentifier &other) const;
   bool operator == (const CPPIdentifier &other) const;
   bool operator != (const CPPIdentifier &other) const;
   bool operator != (const CPPIdentifier &other) const;
   bool operator < (const CPPIdentifier &other) const;
   bool operator < (const CPPIdentifier &other) const;

+ 11 - 15
dtool/src/cppparser/cppInstance.cxx

@@ -37,7 +37,6 @@ CPPInstance(CPPType *type, const string &name, int storage_class) :
   _type(type),
   _type(type),
   _ident(new CPPIdentifier(name)),
   _ident(new CPPIdentifier(name)),
   _storage_class(storage_class),
   _storage_class(storage_class),
-  _alignment(nullptr),
   _bit_width(-1)
   _bit_width(-1)
 {
 {
   _initializer = nullptr;
   _initializer = nullptr;
@@ -52,7 +51,6 @@ CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class) :
   _type(type),
   _type(type),
   _ident(ident),
   _ident(ident),
   _storage_class(storage_class),
   _storage_class(storage_class),
-  _alignment(nullptr),
   _bit_width(-1)
   _bit_width(-1)
 {
 {
   _initializer = nullptr;
   _initializer = nullptr;
@@ -66,11 +64,11 @@ CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class) :
 CPPInstance::
 CPPInstance::
 CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
 CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
             const CPPFile &file) :
             const CPPFile &file) :
-  CPPDeclaration(file),
-  _alignment(nullptr)
+  CPPDeclaration(file)
 {
 {
   _type = ii->unroll_type(type);
   _type = ii->unroll_type(type);
   _ident = ii->_ident;
   _ident = ii->_ident;
+  _attributes = ii->_attributes;
   ii->_ident = nullptr;
   ii->_ident = nullptr;
   _storage_class = storage_class;
   _storage_class = storage_class;
   _initializer = nullptr;
   _initializer = nullptr;
@@ -111,7 +109,6 @@ CPPInstance(const CPPInstance &copy) :
   _ident(copy._ident),
   _ident(copy._ident),
   _initializer(copy._initializer),
   _initializer(copy._initializer),
   _storage_class(copy._storage_class),
   _storage_class(copy._storage_class),
-  _alignment(copy._alignment),
   _bit_width(copy._bit_width)
   _bit_width(copy._bit_width)
 {
 {
   assert(_type != nullptr);
   assert(_type != nullptr);
@@ -156,7 +153,7 @@ operator == (const CPPInstance &other) const {
   if (_storage_class != other._storage_class) {
   if (_storage_class != other._storage_class) {
     return false;
     return false;
   }
   }
-  if (_alignment != other._alignment) {
+  if (_attributes != other._attributes) {
     return false;
     return false;
   }
   }
 
 
@@ -200,8 +197,8 @@ operator < (const CPPInstance &other) const {
   if (_storage_class != other._storage_class) {
   if (_storage_class != other._storage_class) {
     return _storage_class < other._storage_class;
     return _storage_class < other._storage_class;
   }
   }
-  if (_alignment != other._alignment) {
-    return _alignment < other._alignment;
+  if (_attributes != other._attributes) {
+    return _attributes < other._attributes;
   }
   }
 
 
   // We *do* care about the identifier.  We need to differentiate types of
   // We *do* care about the identifier.  We need to differentiate types of
@@ -264,7 +261,7 @@ set_initializer(CPPExpression *initializer) {
  */
  */
 void CPPInstance::
 void CPPInstance::
 set_alignment(int align) {
 set_alignment(int align) {
-  _alignment = new CPPExpression(align);
+  _attributes.add_alignas(align);
 }
 }
 
 
 /**
 /**
@@ -274,7 +271,7 @@ set_alignment(int align) {
  */
  */
 void CPPInstance::
 void CPPInstance::
 set_alignment(CPPExpression *const_expr) {
 set_alignment(CPPExpression *const_expr) {
-  _alignment = const_expr;
+  _attributes.add_alignas(const_expr);
 }
 }
 
 
 /**
 /**
@@ -544,8 +541,8 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete,
     indent(out, indent_level);
     indent(out, indent_level);
   }
   }
 
 
-  if (_alignment != nullptr) {
-    out << "alignas(" << *_alignment << ") ";
+  if (!_attributes.is_empty()) {
+    out << _attributes << " ";
   }
   }
 
 
   if (_storage_class & SC_static) {
   if (_storage_class & SC_static) {
@@ -600,8 +597,8 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete,
     _type->as_function_type()->
     _type->as_function_type()->
       output_instance(out, indent_level, scope, complete, "", name,
       output_instance(out, indent_level, scope, complete, "", name,
                       num_default_parameters);
                       num_default_parameters);
-
-  } else {
+  }
+  else {
     _type->output_instance(out, indent_level, scope, complete, "", name);
     _type->output_instance(out, indent_level, scope, complete, "", name);
   }
   }
 
 
@@ -623,7 +620,6 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete,
   }
   }
 }
 }
 
 
-
 /**
 /**
  *
  *
  */
  */

+ 1 - 1
dtool/src/cppparser/cppInstance.h

@@ -19,6 +19,7 @@
 #include "cppDeclaration.h"
 #include "cppDeclaration.h"
 #include "cppType.h"
 #include "cppType.h"
 #include "cppTemplateParameterList.h"
 #include "cppTemplateParameterList.h"
+#include "cppAttributeList.h"
 
 
 class CPPInstanceIdentifier;
 class CPPInstanceIdentifier;
 class CPPIdentifier;
 class CPPIdentifier;
@@ -127,7 +128,6 @@ public:
   CPPExpression *_initializer;
   CPPExpression *_initializer;
 
 
   int _storage_class;
   int _storage_class;
-  CPPExpression *_alignment;
   int _bit_width;
   int _bit_width;
 
 
 private:
 private:

+ 40 - 16
dtool/src/cppparser/cppInstanceIdentifier.cxx

@@ -25,20 +25,22 @@
  *
  *
  */
  */
 CPPInstanceIdentifier::Modifier::
 CPPInstanceIdentifier::Modifier::
-Modifier(CPPInstanceIdentifierType type) :
+Modifier(CPPInstanceIdentifierType type, CPPAttributeList attr) :
   _type(type),
   _type(type),
   _func_params(nullptr),
   _func_params(nullptr),
   _func_flags(0),
   _func_flags(0),
   _scoping(nullptr),
   _scoping(nullptr),
-  _expr(nullptr) {
+  _expr(nullptr),
+  _attributes(std::move(attr)) {
 }
 }
 
 
 /**
 /**
  *
  *
  */
  */
 CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier::
 CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier::
-func_type(CPPParameterList *params, int flags, CPPType *trailing_return_type) {
-  Modifier mod(IIT_func);
+func_type(CPPParameterList *params, int flags, CPPType *trailing_return_type,
+          CPPAttributeList attr) {
+  Modifier mod(IIT_func, std::move(attr));
   mod._func_params = params;
   mod._func_params = params;
   mod._func_flags = flags;
   mod._func_flags = flags;
   mod._trailing_return_type = trailing_return_type;
   mod._trailing_return_type = trailing_return_type;
@@ -49,8 +51,8 @@ func_type(CPPParameterList *params, int flags, CPPType *trailing_return_type) {
  *
  *
  */
  */
 CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier::
 CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier::
-array_type(CPPExpression *expr) {
-  Modifier mod(IIT_array);
+array_type(CPPExpression *expr, CPPAttributeList attr) {
+  Modifier mod(IIT_array, std::move(attr));
   mod._expr = expr;
   mod._expr = expr;
   return mod;
   return mod;
 }
 }
@@ -59,8 +61,8 @@ array_type(CPPExpression *expr) {
  *
  *
  */
  */
 CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier::
 CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier::
-scoped_pointer_type(CPPIdentifier *scoping) {
-  Modifier mod(IIT_scoped_pointer);
+scoped_pointer_type(CPPIdentifier *scoping, CPPAttributeList attr) {
+  Modifier mod(IIT_scoped_pointer, std::move(attr));
   mod._scoping = scoping;
   mod._scoping = scoping;
   return mod;
   return mod;
 }
 }
@@ -86,6 +88,17 @@ CPPInstanceIdentifier(CPPIdentifier *ident) :
   _packed(false) {
   _packed(false) {
 }
 }
 
 
+/**
+ *
+ */
+CPPInstanceIdentifier::
+CPPInstanceIdentifier(CPPIdentifier *ident, CPPAttributeList attributes) :
+  _ident(ident),
+  _attributes(std::move(attributes)),
+  _bit_width(nullptr),
+  _packed(false) {
+}
+
 /**
 /**
  * Unrolls the list of type punctuation on either side of the identifier to
  * Unrolls the list of type punctuation on either side of the identifier to
  * determine the actual type represented by the identifier, given the
  * determine the actual type represented by the identifier, given the
@@ -103,15 +116,16 @@ unroll_type(CPPType *start_type) {
  *
  *
  */
  */
 void CPPInstanceIdentifier::
 void CPPInstanceIdentifier::
-add_modifier(CPPInstanceIdentifierType type) {
-  _modifiers.push_back(Modifier(type));
+add_modifier(CPPInstanceIdentifierType type, CPPAttributeList attr) {
+  _modifiers.push_back(Modifier(type, std::move(attr)));
 }
 }
 
 
 /**
 /**
  *
  *
  */
  */
 void CPPInstanceIdentifier::
 void CPPInstanceIdentifier::
-add_func_modifier(CPPParameterList *params, int flags, CPPType *trailing_return_type) {
+add_func_modifier(CPPParameterList *params, int flags,
+                  CPPType *trailing_return_type, CPPAttributeList attr) {
   // As a special hack, if we added a parameter list to an operator function,
   // As a special hack, if we added a parameter list to an operator function,
   // check if the parameter list is empty.  If it is, this is really a unary
   // check if the parameter list is empty.  If it is, this is really a unary
   // operator, so set the unary_op flag.  Operators () and [] are never
   // operator, so set the unary_op flag.  Operators () and [] are never
@@ -134,22 +148,22 @@ add_func_modifier(CPPParameterList *params, int flags, CPPType *trailing_return_
     flags |= CPPFunctionType::F_trailing_return_type;
     flags |= CPPFunctionType::F_trailing_return_type;
   }
   }
 
 
-  _modifiers.push_back(Modifier::func_type(params, flags, trailing_return_type));
+  _modifiers.push_back(Modifier::func_type(params, flags, trailing_return_type, std::move(attr)));
 }
 }
 
 
 /**
 /**
  *
  *
  */
  */
 void CPPInstanceIdentifier::
 void CPPInstanceIdentifier::
-add_scoped_pointer_modifier(CPPIdentifier *scoping) {
-  _modifiers.push_back(Modifier::scoped_pointer_type(scoping));
+add_scoped_pointer_modifier(CPPIdentifier *scoping, CPPAttributeList attr) {
+  _modifiers.push_back(Modifier::scoped_pointer_type(scoping, std::move(attr)));
 }
 }
 
 
 /**
 /**
  *
  *
  */
  */
 void CPPInstanceIdentifier::
 void CPPInstanceIdentifier::
-add_array_modifier(CPPExpression *expr) {
+add_array_modifier(CPPExpression *expr, CPPAttributeList attr) {
   // Special case for operator new[] and delete[].  We're not really adding an
   // Special case for operator new[] and delete[].  We're not really adding an
   // array modifier to them, but appending [] to the identifier.  This is to
   // array modifier to them, but appending [] to the identifier.  This is to
   // work around a parser ambiguity.
   // work around a parser ambiguity.
@@ -158,7 +172,7 @@ add_array_modifier(CPPExpression *expr) {
 
 
     _ident->_names.back().append_name("[]");
     _ident->_names.back().append_name("[]");
   } else {
   } else {
-    _modifiers.push_back(Modifier::array_type(expr));
+    _modifiers.push_back(Modifier::array_type(expr, std::move(attr)));
   }
   }
 }
 }
 
 
@@ -187,6 +201,14 @@ add_trailing_return_type(CPPType *type) {
   std::cerr << "trailing return type can only be added to a function\n";
   std::cerr << "trailing return type can only be added to a function\n";
 }
 }
 
 
+/**
+ * Add attributes to the instance (not the type).
+ */
+void CPPInstanceIdentifier::
+add_attributes(const CPPAttributeList &attributes) {
+  _attributes.add_attributes_from(attributes);
+}
+
 /**
 /**
  * Returns the initializer parameter list that was set for this particular
  * Returns the initializer parameter list that was set for this particular
  * instance, e.g.  if the instance were:
  * instance, e.g.  if the instance were:
@@ -316,5 +338,7 @@ r_unroll_type(CPPType *start_type,
     abort();
     abort();
   }
   }
 
 
+  result->_attributes = mod._attributes;
+
   return CPPType::new_type(result);
   return CPPType::new_type(result);
 }
 }

+ 22 - 8
dtool/src/cppparser/cppInstanceIdentifier.h

@@ -15,6 +15,7 @@
 #define CPPINSTANCEIDENTIFIER_H
 #define CPPINSTANCEIDENTIFIER_H
 
 
 #include "dtoolbase.h"
 #include "dtoolbase.h"
+#include "cppAttributeList.h"
 
 
 #include <vector>
 #include <vector>
 #include <string>
 #include <string>
@@ -48,18 +49,25 @@ enum CPPInstanceIdentifierType {
 class CPPInstanceIdentifier {
 class CPPInstanceIdentifier {
 public:
 public:
   CPPInstanceIdentifier(CPPIdentifier *ident);
   CPPInstanceIdentifier(CPPIdentifier *ident);
+  CPPInstanceIdentifier(CPPIdentifier *ident, CPPAttributeList attributes);
 
 
   CPPType *unroll_type(CPPType *start_type);
   CPPType *unroll_type(CPPType *start_type);
 
 
-  void add_modifier(CPPInstanceIdentifierType type);
+  void add_modifier(CPPInstanceIdentifierType type,
+                    CPPAttributeList attr = CPPAttributeList());
   void add_func_modifier(CPPParameterList *params, int flags,
   void add_func_modifier(CPPParameterList *params, int flags,
-                         CPPType *trailing_return_type = nullptr);
-  void add_scoped_pointer_modifier(CPPIdentifier *scoping);
-  void add_array_modifier(CPPExpression *expr);
+                         CPPType *trailing_return_type = nullptr,
+                         CPPAttributeList attr = CPPAttributeList());
+  void add_scoped_pointer_modifier(CPPIdentifier *scoping,
+                                   CPPAttributeList attr = CPPAttributeList());
+  void add_array_modifier(CPPExpression *expr,
+                          CPPAttributeList attr = CPPAttributeList());
   void add_initializer_modifier(CPPParameterList *params);
   void add_initializer_modifier(CPPParameterList *params);
 
 
   void add_trailing_return_type(CPPType *type);
   void add_trailing_return_type(CPPType *type);
 
 
+  void add_attributes(const CPPAttributeList &attributes);
+
   CPPParameterList *get_initializer() const;
   CPPParameterList *get_initializer() const;
 
 
   CPPScope *get_scope(CPPScope *current_scope, CPPScope *global_scope,
   CPPScope *get_scope(CPPScope *current_scope, CPPScope *global_scope,
@@ -69,11 +77,14 @@ public:
 
 
   class Modifier {
   class Modifier {
   public:
   public:
-    Modifier(CPPInstanceIdentifierType type);
+    Modifier(CPPInstanceIdentifierType type,
+             CPPAttributeList attr = CPPAttributeList());
     static Modifier func_type(CPPParameterList *params, int flags,
     static Modifier func_type(CPPParameterList *params, int flags,
-                              CPPType *trailing_return_type);
-    static Modifier array_type(CPPExpression *expr);
-    static Modifier scoped_pointer_type(CPPIdentifier *scoping);
+                              CPPType *trailing_return_type,
+                              CPPAttributeList attr);
+    static Modifier array_type(CPPExpression *expr, CPPAttributeList attr);
+    static Modifier scoped_pointer_type(CPPIdentifier *scoping,
+                                        CPPAttributeList attr);
     static Modifier initializer_type(CPPParameterList *params);
     static Modifier initializer_type(CPPParameterList *params);
 
 
     CPPInstanceIdentifierType _type;
     CPPInstanceIdentifierType _type;
@@ -82,10 +93,13 @@ public:
     CPPIdentifier *_scoping;
     CPPIdentifier *_scoping;
     CPPExpression *_expr;
     CPPExpression *_expr;
     CPPType *_trailing_return_type;
     CPPType *_trailing_return_type;
+    CPPAttributeList _attributes;
   };
   };
   typedef std::vector<Modifier> Modifiers;
   typedef std::vector<Modifier> Modifiers;
   Modifiers _modifiers;
   Modifiers _modifiers;
 
 
+  CPPAttributeList _attributes;
+
   // If not null, indicates a bitfield
   // If not null, indicates a bitfield
   CPPExpression *_bit_width;
   CPPExpression *_bit_width;
 
 

+ 12 - 6
dtool/src/cppparser/cppNamespace.cxx

@@ -20,8 +20,9 @@
  *
  *
  */
  */
 CPPNamespace::
 CPPNamespace::
-CPPNamespace(CPPIdentifier *ident, CPPScope *scope, const CPPFile &file) :
-  CPPDeclaration(file),
+CPPNamespace(CPPIdentifier *ident, CPPScope *scope, const CPPFile &file,
+             CPPAttributeList attr) :
+  CPPDeclaration(file, std::move(attr)),
   _is_inline(false),
   _is_inline(false),
   _ident(ident),
   _ident(ident),
   _scope(scope)
   _scope(scope)
@@ -77,15 +78,20 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) cons
   if (_is_inline) {
   if (_is_inline) {
     out << "inline ";
     out << "inline ";
   }
   }
+  out << "namespace ";
+
   if (!complete && _ident != nullptr) {
   if (!complete && _ident != nullptr) {
     // If we have a name, use it.
     // If we have a name, use it.
     out << "namespace " << _ident->get_local_name(scope);
     out << "namespace " << _ident->get_local_name(scope);
-
-  } else {
+  }
+  else {
+    if (!_attributes.is_empty()) {
+      out << _attributes << " ";
+    }
     if (_ident != nullptr) {
     if (_ident != nullptr) {
-      out << "namespace " << _ident->get_local_name(scope) << " {\n";
+      out << _ident->get_local_name(scope) << " {\n";
     } else {
     } else {
-      out << "namespace {\n";
+      out << "{\n";
     }
     }
 
 
     _scope->write(out, indent_level + 2, _scope);
     _scope->write(out, indent_level + 2, _scope);

+ 1 - 1
dtool/src/cppparser/cppNamespace.h

@@ -27,7 +27,7 @@ class CPPScope;
 class CPPNamespace : public CPPDeclaration {
 class CPPNamespace : public CPPDeclaration {
 public:
 public:
   CPPNamespace(CPPIdentifier *ident, CPPScope *scope,
   CPPNamespace(CPPIdentifier *ident, CPPScope *scope,
-               const CPPFile &file);
+               const CPPFile &file, CPPAttributeList attr = CPPAttributeList());
 
 
   std::string get_simple_name() const;
   std::string get_simple_name() const;
   std::string get_local_name(CPPScope *scope = nullptr) const;
   std::string get_local_name(CPPScope *scope = nullptr) const;

+ 6 - 0
dtool/src/cppparser/cppPointerType.cxx

@@ -247,6 +247,12 @@ output_instance(std::ostream &out, int indent_level, CPPScope *scope,
     star = ftype->_class_owner->get_fully_scoped_name() + "::*";
     star = ftype->_class_owner->get_fully_scoped_name() + "::*";
   }
   }
 
 
+  if (!_attributes.is_empty()) {
+    std::ostringstream strm;
+    strm << star << _attributes << " ";
+    star = strm.str();
+  }
+
   _pointing_at->output_instance(out, indent_level, scope, complete,
   _pointing_at->output_instance(out, indent_level, scope, complete,
                                 star + prename, name);
                                 star + prename, name);
 }
 }

+ 2 - 2
dtool/src/cppparser/cppPreprocessor.h

@@ -72,10 +72,10 @@ public:
   typedef std::map<std::string, CPPManifest *> Manifests;
   typedef std::map<std::string, CPPManifest *> Manifests;
   Manifests _manifests;
   Manifests _manifests;
 
 
-  typedef pvector<CPPManifest *> ManifestStack;
+  typedef std::vector<CPPManifest *> ManifestStack;
   std::map<std::string, ManifestStack> _manifest_stack;
   std::map<std::string, ManifestStack> _manifest_stack;
 
 
-  pvector<CPPFile::Source> _quote_include_kind;
+  std::vector<CPPFile::Source> _quote_include_kind;
   DSearchPath _quote_include_path;
   DSearchPath _quote_include_path;
   DSearchPath _angle_include_path;
   DSearchPath _angle_include_path;
   bool _noangles;
   bool _noangles;

+ 9 - 6
dtool/src/cppparser/cppReferenceType.cxx

@@ -228,13 +228,16 @@ output_instance(std::ostream &out, int indent_level, CPPScope *scope,
                 bool complete, const std::string &prename,
                 bool complete, const std::string &prename,
                 const std::string &name) const {
                 const std::string &name) const {
 
 
-  if (_value_category == VC_rvalue) {
-    _pointing_at->output_instance(out, indent_level, scope, complete,
-                                  "&&" + prename, name);
-  } else {
-    _pointing_at->output_instance(out, indent_level, scope, complete,
-                                  "&" + prename, name);
+  std::string prefix((_value_category == VC_rvalue) ? "&&" : "&");
+
+  if (!_attributes.is_empty()) {
+    std::ostringstream strm;
+    strm << prefix << _attributes << " ";
+    prefix = strm.str();
   }
   }
+
+  _pointing_at->output_instance(out, indent_level, scope, complete,
+                                prefix + prename, name);
 }
 }
 
 
 /**
 /**

+ 9 - 5
dtool/src/cppparser/cppStructType.cxx

@@ -41,8 +41,8 @@ output(std::ostream &out) const {
 CPPStructType::
 CPPStructType::
 CPPStructType(CPPStructType::Type type, CPPIdentifier *ident,
 CPPStructType(CPPStructType::Type type, CPPIdentifier *ident,
               CPPScope *current_scope, CPPScope *scope,
               CPPScope *current_scope, CPPScope *scope,
-              const CPPFile &file) :
-  CPPExtensionType(type, ident, current_scope, file),
+              const CPPFile &file, CPPAttributeList attr) :
+  CPPExtensionType(type, ident, current_scope, file, std::move(attr)),
   _scope(scope),
   _scope(scope),
   _final(false)
   _final(false)
 {
 {
@@ -1261,10 +1261,14 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) cons
       get_template_scope()->_parameters.write_formal(out, scope);
       get_template_scope()->_parameters.write_formal(out, scope);
       indent(out, indent_level);
       indent(out, indent_level);
     }
     }
+    out << _type;
+
+    if (!_attributes.is_empty()) {
+      out << " " << _attributes;
+    }
+
     if (_ident != nullptr) {
     if (_ident != nullptr) {
-      out << _type << " " << _ident->get_local_name(scope);
-    } else {
-      out << _type;
+      out << " " << _ident->get_local_name(scope);
     }
     }
 
 
     if (_final) {
     if (_final) {

+ 2 - 1
dtool/src/cppparser/cppStructType.h

@@ -35,7 +35,8 @@ public:
   CPPStructType(Type type, CPPIdentifier *ident,
   CPPStructType(Type type, CPPIdentifier *ident,
                 CPPScope *current_scope,
                 CPPScope *current_scope,
                 CPPScope *scope,
                 CPPScope *scope,
-                const CPPFile &file);
+                const CPPFile &file,
+                CPPAttributeList attr = CPPAttributeList());
   CPPStructType(const CPPStructType &copy);
   CPPStructType(const CPPStructType &copy);
   void operator = (const CPPStructType &copy);
   void operator = (const CPPStructType &copy);
 
 

+ 13 - 2
dtool/src/cppparser/cppTypedefType.cxx

@@ -43,7 +43,8 @@ CPPTypedefType(CPPType *type, const string &name, CPPScope *current_scope) :
  *
  *
  */
  */
 CPPTypedefType::
 CPPTypedefType::
-CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope) :
+CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope,
+               CPPAttributeList attr) :
   CPPType(CPPFile()),
   CPPType(CPPFile()),
   _type(type),
   _type(type),
   _ident(ident),
   _ident(ident),
@@ -53,6 +54,8 @@ CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope) :
     _ident->_native_scope = current_scope;
     _ident->_native_scope = current_scope;
   }
   }
   _subst_decl_recursive_protect = false;
   _subst_decl_recursive_protect = false;
+
+  _attributes = std::move(attr);
 }
 }
 
 
 /**
 /**
@@ -69,6 +72,7 @@ CPPTypedefType(CPPType *type, CPPInstanceIdentifier *ii,
   assert(ii != nullptr);
   assert(ii != nullptr);
   _type = ii->unroll_type(type);
   _type = ii->unroll_type(type);
   _ident = ii->_ident;
   _ident = ii->_ident;
+  _attributes = std::move(ii->_attributes);
   ii->_ident = nullptr;
   ii->_ident = nullptr;
   delete ii;
   delete ii;
 
 
@@ -388,9 +392,16 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) cons
         get_template_scope()->_parameters.write_formal(out, scope);
         get_template_scope()->_parameters.write_formal(out, scope);
         indent(out, indent_level);
         indent(out, indent_level);
       }
       }
-      out << "using " << name << " = ";
+      out << "using " << name;
+      if (!_attributes.is_empty()) {
+        out << " " << _attributes;
+      }
+      out << " = ";
       _type->output(out, 0, scope, false);
       _type->output(out, 0, scope, false);
     } else {
     } else {
+      if (!_attributes.is_empty()) {
+        out << _attributes << " ";
+      }
       out << "typedef ";
       out << "typedef ";
       _type->output_instance(out, indent_level, scope, false, "", name);
       _type->output_instance(out, indent_level, scope, false, "", name);
     }
     }

+ 2 - 1
dtool/src/cppparser/cppTypedefType.h

@@ -28,7 +28,8 @@ class CPPInstanceIdentifier;
 class CPPTypedefType : public CPPType {
 class CPPTypedefType : public CPPType {
 public:
 public:
   CPPTypedefType(CPPType *type, const std::string &name, CPPScope *current_scope);
   CPPTypedefType(CPPType *type, const std::string &name, CPPScope *current_scope);
-  CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope);
+  CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope,
+                 CPPAttributeList attr = CPPAttributeList());
   CPPTypedefType(CPPType *type, CPPInstanceIdentifier *ii,
   CPPTypedefType(CPPType *type, CPPInstanceIdentifier *ii,
                  CPPScope *current_scope, const CPPFile &file);
                  CPPScope *current_scope, const CPPFile &file);
 
 

+ 1 - 1
dtool/src/cppparser/p3cppParser_composite1.cxx

@@ -1,4 +1,4 @@
-
+#include "cppAttributeList.cxx"
 #include "cppFunctionType.cxx"
 #include "cppFunctionType.cxx"
 #include "cppGlobals.cxx"
 #include "cppGlobals.cxx"
 #include "cppCommentBlock.cxx"
 #include "cppCommentBlock.cxx"

+ 9 - 5
dtool/src/dtoolbase/CMakeLists.txt

@@ -21,7 +21,7 @@ set(P3DTOOLBASE_HEADERS
   atomicAdjustWin32Impl.h atomicAdjustWin32Impl.I
   atomicAdjustWin32Impl.h atomicAdjustWin32Impl.I
   cmath.I cmath.h
   cmath.I cmath.h
   deletedBufferChain.h deletedBufferChain.I
   deletedBufferChain.h deletedBufferChain.I
-  deletedChain.h deletedChain.T
+  deletedChain.h deletedChain.I
   dtoolbase.h dtoolbase_cc.h dtoolsymbols.h
   dtoolbase.h dtoolbase_cc.h dtoolsymbols.h
   dtool_platform.h
   dtool_platform.h
   fakestringstream.h
   fakestringstream.h
@@ -94,12 +94,16 @@ add_component_library(p3dtoolbase NOINIT SYMBOL BUILDING_DTOOL_DTOOLBASE
 target_include_directories(p3dtoolbase PUBLIC
 target_include_directories(p3dtoolbase PUBLIC
   $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
   $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
   $<BUILD_INTERFACE:${PANDA_OUTPUT_DIR}/include>)
   $<BUILD_INTERFACE:${PANDA_OUTPUT_DIR}/include>)
-target_link_libraries(p3dtoolbase PKG::EIGEN PKG::THREADS PKG::MIMALLOC)
+target_link_libraries(p3dtoolbase PKG::EIGEN PKG::THREADS)
 target_interrogate(p3dtoolbase ${P3DTOOLBASE_SOURCES} EXTENSIONS ${P3DTOOLBASE_IGATEEXT})
 target_interrogate(p3dtoolbase ${P3DTOOLBASE_SOURCES} EXTENSIONS ${P3DTOOLBASE_IGATEEXT})
 
 
-if(HAVE_MIMALLOC AND CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang)$")
-  # Do not re-export symbols from these libraries.
-  target_link_options(p3dtoolbase PRIVATE "LINKER:--exclude-libs,libmimalloc.a")
+if(HAVE_MIMALLOC AND USE_MEMORY_MIMALLOC)
+  target_link_libraries(p3dtoolbase PKG::MIMALLOC)
+
+  if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang)$")
+    # Do not re-export symbols from these libraries.
+    target_link_options(p3dtoolbase PRIVATE "LINKER:--exclude-libs,libmimalloc.a")
+  endif()
 endif()
 endif()
 
 
 if(NOT BUILD_METALIBS)
 if(NOT BUILD_METALIBS)

+ 52 - 0
dtool/src/dtoolbase/deletedBufferChain.I

@@ -11,6 +11,34 @@
  * @date 2007-07-20
  * @date 2007-07-20
  */
  */
 
 
+/**
+ * Use get_deleted_chain() to get a new DeletedBufferChain of the appropriate
+ * size.
+ */
+constexpr DeletedBufferChain::
+DeletedBufferChain(size_t buffer_size) : _buffer_size(buffer_size) {
+}
+
+/**
+ * Move constructor.
+ */
+INLINE DeletedBufferChain::
+DeletedBufferChain(DeletedBufferChain &&from) noexcept :
+  _deleted_chain(from._deleted_chain),
+  _buffer_size(from._buffer_size) {
+  from._deleted_chain = nullptr;
+}
+
+/**
+ * Copy constructor.
+ */
+INLINE DeletedBufferChain::
+DeletedBufferChain(const DeletedBufferChain &copy) :
+  _deleted_chain(nullptr),
+  _buffer_size(copy._buffer_size) {
+  assert(copy._deleted_chain == nullptr);
+}
+
 /**
 /**
  * Returns true if the pointer is valid, false if it has been deleted or if it
  * Returns true if the pointer is valid, false if it has been deleted or if it
  * was never a valid pointer.
  * was never a valid pointer.
@@ -41,6 +69,30 @@ get_buffer_size() const {
   return _buffer_size;
   return _buffer_size;
 }
 }
 
 
+/**
+ *
+ */
+INLINE bool DeletedBufferChain::
+operator < (const DeletedBufferChain &other) const {
+  return _buffer_size < other._buffer_size;
+}
+
+/**
+ * Returns a deleted chain of the given size.
+ */
+INLINE DeletedBufferChain *DeletedBufferChain::
+get_deleted_chain(size_t buffer_size) {
+  // We must allocate at least this much space for bookkeeping reasons.
+  buffer_size = (std::max)(buffer_size, sizeof(ObjectNode));
+
+  size_t index = ((buffer_size + sizeof(void *) - 1) / sizeof(void *)) - 1;
+  if (index < num_small_deleted_chains) {
+    return &_small_deleted_chains[index];
+  } else {
+    return get_large_deleted_chain((index + 1) * sizeof(void *));
+  }
+}
+
 /**
 /**
  * Casts an ObjectNode* to a void* buffer.
  * Casts an ObjectNode* to a void* buffer.
  */
  */

+ 41 - 12
dtool/src/dtoolbase/deletedBufferChain.cxx

@@ -14,18 +14,34 @@
 #include "deletedBufferChain.h"
 #include "deletedBufferChain.h"
 #include "memoryHook.h"
 #include "memoryHook.h"
 
 
-/**
- * Use the global MemoryHook to get a new DeletedBufferChain of the
- * appropriate size.
- */
-DeletedBufferChain::
-DeletedBufferChain(size_t buffer_size) {
-  _deleted_chain = nullptr;
-  _buffer_size = buffer_size;
-
-  // We must allocate at least this much space for bookkeeping reasons.
-  _buffer_size = std::max(_buffer_size, sizeof(ObjectNode));
-}
+#include <set>
+
+DeletedBufferChain DeletedBufferChain::_small_deleted_chains[DeletedBufferChain::num_small_deleted_chains] = {
+  DeletedBufferChain(sizeof(void *)),
+  DeletedBufferChain(sizeof(void *) * 2),
+  DeletedBufferChain(sizeof(void *) * 3),
+  DeletedBufferChain(sizeof(void *) * 4),
+  DeletedBufferChain(sizeof(void *) * 5),
+  DeletedBufferChain(sizeof(void *) * 6),
+  DeletedBufferChain(sizeof(void *) * 7),
+  DeletedBufferChain(sizeof(void *) * 8),
+  DeletedBufferChain(sizeof(void *) * 9),
+  DeletedBufferChain(sizeof(void *) * 10),
+  DeletedBufferChain(sizeof(void *) * 11),
+  DeletedBufferChain(sizeof(void *) * 12),
+  DeletedBufferChain(sizeof(void *) * 13),
+  DeletedBufferChain(sizeof(void *) * 14),
+  DeletedBufferChain(sizeof(void *) * 15),
+  DeletedBufferChain(sizeof(void *) * 16),
+  DeletedBufferChain(sizeof(void *) * 17),
+  DeletedBufferChain(sizeof(void *) * 18),
+  DeletedBufferChain(sizeof(void *) * 19),
+  DeletedBufferChain(sizeof(void *) * 20),
+  DeletedBufferChain(sizeof(void *) * 21),
+  DeletedBufferChain(sizeof(void *) * 22),
+  DeletedBufferChain(sizeof(void *) * 23),
+  DeletedBufferChain(sizeof(void *) * 24),
+};
 
 
 /**
 /**
  * Allocates the memory for a new buffer of the indicated size (which must be
  * Allocates the memory for a new buffer of the indicated size (which must be
@@ -139,3 +155,16 @@ deallocate(void *ptr, TypeHandle type_handle) {
   PANDA_FREE_SINGLE(ptr);
   PANDA_FREE_SINGLE(ptr);
 #endif  // USE_DELETED_CHAIN
 #endif  // USE_DELETED_CHAIN
 }
 }
+
+/**
+ * Returns a new DeletedBufferChain.
+ */
+DeletedBufferChain *DeletedBufferChain::
+get_large_deleted_chain(size_t buffer_size) {
+  static MutexImpl lock;
+  lock.lock();
+  static std::set<DeletedBufferChain> deleted_chains;
+  DeletedBufferChain *result = (DeletedBufferChain *)&*deleted_chains.insert(DeletedBufferChain(buffer_size)).first;
+  lock.unlock();
+  return result;
+}

+ 17 - 3
dtool/src/dtoolbase/deletedBufferChain.h

@@ -58,16 +58,25 @@ enum DeletedChainFlag : unsigned int {
  */
  */
 class EXPCL_DTOOL_DTOOLBASE DeletedBufferChain {
 class EXPCL_DTOOL_DTOOLBASE DeletedBufferChain {
 protected:
 protected:
-  DeletedBufferChain(size_t buffer_size);
+  constexpr explicit DeletedBufferChain(size_t buffer_size);
 
 
 public:
 public:
+  INLINE DeletedBufferChain(DeletedBufferChain &&from) noexcept;
+  INLINE DeletedBufferChain(const DeletedBufferChain &copy);
+
   void *allocate(size_t size, TypeHandle type_handle);
   void *allocate(size_t size, TypeHandle type_handle);
   void deallocate(void *ptr, TypeHandle type_handle);
   void deallocate(void *ptr, TypeHandle type_handle);
 
 
   INLINE bool validate(void *ptr);
   INLINE bool validate(void *ptr);
   INLINE size_t get_buffer_size() const;
   INLINE size_t get_buffer_size() const;
 
 
+  INLINE bool operator < (const DeletedBufferChain &other) const;
+
+  static INLINE DeletedBufferChain *get_deleted_chain(size_t buffer_size);
+
 private:
 private:
+  static DeletedBufferChain *get_large_deleted_chain(size_t buffer_size);
+
   class ObjectNode {
   class ObjectNode {
   public:
   public:
 #ifdef USE_DELETEDCHAINFLAG
 #ifdef USE_DELETEDCHAINFLAG
@@ -87,10 +96,10 @@ private:
   static INLINE void *node_to_buffer(ObjectNode *node);
   static INLINE void *node_to_buffer(ObjectNode *node);
   static INLINE ObjectNode *buffer_to_node(void *buffer);
   static INLINE ObjectNode *buffer_to_node(void *buffer);
 
 
-  ObjectNode *_deleted_chain;
+  ObjectNode *_deleted_chain = nullptr;
 
 
   MutexImpl _lock;
   MutexImpl _lock;
-  size_t _buffer_size;
+  const size_t _buffer_size;
 
 
 #ifndef USE_DELETEDCHAINFLAG
 #ifndef USE_DELETEDCHAINFLAG
   // Without DELETEDCHAINFLAG, we don't even store the _flag member at all.
   // Without DELETEDCHAINFLAG, we don't even store the _flag member at all.
@@ -101,6 +110,11 @@ private:
   static const size_t flag_reserved_bytes = sizeof(AtomicAdjust::Integer);
   static const size_t flag_reserved_bytes = sizeof(AtomicAdjust::Integer);
 #endif  // USE_DELETEDCHAINFLAG
 #endif  // USE_DELETEDCHAINFLAG
 
 
+  // This array stores the deleted chains for smaller sizes, starting with
+  // sizeof(void *) and increasing in multiples thereof.
+  static const size_t num_small_deleted_chains = 24;
+  static DeletedBufferChain _small_deleted_chains[num_small_deleted_chains];
+
   friend class MemoryHook;
   friend class MemoryHook;
 };
 };
 
 

+ 4 - 5
dtool/src/dtoolbase/deletedChain.T → dtool/src/dtoolbase/deletedChain.I

@@ -6,7 +6,7 @@
  * license.  You should have received a copy of this license along
  * license.  You should have received a copy of this license along
  * with this source code in a file named "LICENSE."
  * with this source code in a file named "LICENSE."
  *
  *
- * @file deletedChain.T
+ * @file deletedChain.I
  * @author drose
  * @author drose
  * @date 2006-04-01
  * @date 2006-04-01
  */
  */
@@ -82,7 +82,7 @@ validate(const Type *ptr) {
 template<class Type>
 template<class Type>
 INLINE ReferenceCount *DeletedChain<Type>::
 INLINE ReferenceCount *DeletedChain<Type>::
 make_ref_ptr(void *) {
 make_ref_ptr(void *) {
-  return NULL;
+  return nullptr;
 }
 }
 
 
 /**
 /**
@@ -106,9 +106,8 @@ make_ref_ptr(ReferenceCount *ptr) {
 template<class Type>
 template<class Type>
 void DeletedChain<Type>::
 void DeletedChain<Type>::
 init_deleted_chain() {
 init_deleted_chain() {
-  if (_chain == (DeletedBufferChain *)NULL) {
-    init_memory_hook();
-    _chain = memory_hook->get_deleted_chain(sizeof(Type));
+  if (_chain == nullptr) {
+    _chain = DeletedBufferChain::get_deleted_chain(sizeof(Type));
   }
   }
 }
 }
 
 

+ 1 - 1
dtool/src/dtoolbase/deletedChain.h

@@ -136,6 +136,6 @@ public:
 
 
 #endif  // USE_DELETED_CHAIN
 #endif  // USE_DELETED_CHAIN
 
 
-#include "deletedChain.T"
+#include "deletedChain.I"
 
 
 #endif
 #endif

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

@@ -79,6 +79,9 @@
 
 
 #elif defined(__ppc__)
 #elif defined(__ppc__)
 #define DTOOL_PLATFORM "linux_ppc"
 #define DTOOL_PLATFORM "linux_ppc"
+
+#elif defined(__e2k__)
+#define DTOOL_PLATFORM "linux_e2k"
 #endif
 #endif
 
 
 #if !defined(DTOOL_PLATFORM) && !defined(CPPPARSER)
 #if !defined(DTOOL_PLATFORM) && !defined(CPPPARSER)

+ 5 - 21
dtool/src/dtoolbase/dtoolbase.cxx

@@ -23,34 +23,18 @@
 bool __tau_shutdown = false;
 bool __tau_shutdown = false;
 #endif
 #endif
 
 
-MemoryHook *memory_hook;
+MemoryHook default_memory_hook;
+MemoryHook *memory_hook = &default_memory_hook;
 
 
 /**
 /**
- * Any code that might need to use PANDA_MALLOC or PANDA_FREE, or any methods
- * of the global memory_hook object, at static init time, should ensure that
- * it calls init_memory_hook() first to ensure that the pointer has been
- * properly initialized.  There is no harm in calling this function more than
- * once.
- *
- * There is no need to call this function other than at static init time.
+ * It used to be necessary to call this before using operator new at static
+ * init time.  There is no need to call this function anymore.
  */
  */
 void
 void
 init_memory_hook() {
 init_memory_hook() {
-  if (memory_hook == nullptr) {
-    memory_hook = new MemoryHook;
-  }
+  assert(memory_hook != nullptr);
 }
 }
 
 
-// Here's a quick way to ensure the above function is called at least once at
-// static init time.
-class InitMemoryHook {
-public:
-  InitMemoryHook() {
-    init_memory_hook();
-  }
-};
-static InitMemoryHook _imh_object;
-
 #if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
 #if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
 
 
 static void
 static void

+ 6 - 0
dtool/src/dtoolbase/memoryHook.I

@@ -40,6 +40,9 @@ dec_heap(size_t size) {
  */
  */
 INLINE size_t MemoryHook::
 INLINE size_t MemoryHook::
 get_page_size() const {
 get_page_size() const {
+  if (_page_size == 0) {
+    determine_page_size();
+  }
   return _page_size;
   return _page_size;
 }
 }
 
 
@@ -49,6 +52,9 @@ get_page_size() const {
  */
  */
 INLINE size_t MemoryHook::
 INLINE size_t MemoryHook::
 round_up_to_page_size(size_t size) const {
 round_up_to_page_size(size_t size) const {
+  if (_page_size == 0) {
+    determine_page_size();
+  }
   return  ((size + _page_size - 1) / _page_size) * _page_size;
   return  ((size + _page_size - 1) / _page_size) * _page_size;
 }
 }
 
 

+ 25 - 62
dtool/src/dtoolbase/memoryHook.cxx

@@ -198,33 +198,6 @@ ptr_to_alloc(void *ptr, size_t &size) {
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
 }
 }
 
 
-/**
- *
- */
-MemoryHook::
-MemoryHook() {
-#ifdef _WIN32
-
-  // Windows case.
-  SYSTEM_INFO sysinfo;
-  GetSystemInfo(&sysinfo);
-
-  _page_size = (size_t)sysinfo.dwPageSize;
-
-#else
-
-  // Posix case.
-  _page_size = sysconf(_SC_PAGESIZE);
-
-#endif  // WIN32
-
-  _total_heap_single_size = 0;
-  _total_heap_array_size = 0;
-  _requested_heap_size = 0;
-  _total_mmap_size = 0;
-  _max_heap_size = ~(size_t)0;
-}
-
 /**
 /**
  *
  *
  */
  */
@@ -236,20 +209,8 @@ MemoryHook(const MemoryHook &copy) :
   _total_mmap_size(copy._total_mmap_size),
   _total_mmap_size(copy._total_mmap_size),
   _max_heap_size(copy._max_heap_size),
   _max_heap_size(copy._max_heap_size),
   _page_size(copy._page_size) {
   _page_size(copy._page_size) {
-
-  copy._lock.lock();
-  _deleted_chains = copy._deleted_chains;
-  copy._lock.unlock();
 }
 }
 
 
-/**
- *
- */
-MemoryHook::
-~MemoryHook() {
-  // Really, we only have this destructor to shut up gcc about the virtual
-  // functions warning.
-}
 
 
 /**
 /**
  * Allocates a block of memory from the heap, similar to malloc().  This will
  * Allocates a block of memory from the heap, similar to malloc().  This will
@@ -522,6 +483,9 @@ heap_trim(size_t pad) {
  */
  */
 void *MemoryHook::
 void *MemoryHook::
 mmap_alloc(size_t size, bool allow_exec) {
 mmap_alloc(size_t size, bool allow_exec) {
+  if (_page_size == 0) {
+    determine_page_size();
+  }
   assert((size % _page_size) == 0);
   assert((size % _page_size) == 0);
 
 
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
@@ -576,6 +540,7 @@ mmap_alloc(size_t size, bool allow_exec) {
  */
  */
 void MemoryHook::
 void MemoryHook::
 mmap_free(void *ptr, size_t size) {
 mmap_free(void *ptr, size_t size) {
+  assert(_page_size != 0);
   assert((size % _page_size) == 0);
   assert((size % _page_size) == 0);
 
 
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
@@ -601,29 +566,6 @@ void MemoryHook::
 mark_pointer(void *, size_t, ReferenceCount *) {
 mark_pointer(void *, size_t, ReferenceCount *) {
 }
 }
 
 
-/**
- * Returns a pointer to a global DeletedBufferChain object suitable for
- * allocating arrays of the indicated size.  There is one unique
- * DeletedBufferChain object for every different size.
- */
-DeletedBufferChain *MemoryHook::
-get_deleted_chain(size_t buffer_size) {
-  DeletedBufferChain *chain;
-
-  _lock.lock();
-  DeletedChains::iterator dci = _deleted_chains.find(buffer_size);
-  if (dci != _deleted_chains.end()) {
-    chain = (*dci).second;
-  } else {
-    // Once allocated, this DeletedBufferChain object is never deleted.
-    chain = new DeletedBufferChain(buffer_size);
-    _deleted_chains.insert(DeletedChains::value_type(buffer_size, chain));
-  }
-
-  _lock.unlock();
-  return chain;
-}
-
 /**
 /**
  * This callback method is called whenever a low-level call to call_malloc()
  * This callback method is called whenever a low-level call to call_malloc()
  * has returned NULL, indicating failure.
  * has returned NULL, indicating failure.
@@ -656,3 +598,24 @@ overflow_heap_size() {
   _max_heap_size = ~(size_t)0;
   _max_heap_size = ~(size_t)0;
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
 }
 }
+
+/**
+ * Asks the operating system for the page size.
+ */
+void MemoryHook::
+determine_page_size() const {
+#ifdef _WIN32
+  // Windows case.
+  SYSTEM_INFO sysinfo;
+  GetSystemInfo(&sysinfo);
+
+  _page_size = (size_t)sysinfo.dwPageSize;
+
+#else
+  // Posix case.
+  _page_size = sysconf(_SC_PAGESIZE);
+
+#endif  // WIN32
+
+  assert(_page_size != 0);
+}

+ 10 - 15
dtool/src/dtoolbase/memoryHook.h

@@ -20,8 +20,6 @@
 #include "mutexImpl.h"
 #include "mutexImpl.h"
 #include <map>
 #include <map>
 
 
-class DeletedBufferChain;
-
 /**
 /**
  * This class provides a wrapper around the various possible malloc schemes
  * This class provides a wrapper around the various possible malloc schemes
  * Panda might employ.  It also exists to allow the MemoryUsage class in Panda
  * Panda might employ.  It also exists to allow the MemoryUsage class in Panda
@@ -36,9 +34,9 @@ class DeletedBufferChain;
  */
  */
 class EXPCL_DTOOL_DTOOLBASE MemoryHook {
 class EXPCL_DTOOL_DTOOLBASE MemoryHook {
 public:
 public:
-  MemoryHook();
+  constexpr MemoryHook() = default;
   MemoryHook(const MemoryHook &copy);
   MemoryHook(const MemoryHook &copy);
-  virtual ~MemoryHook();
+  virtual ~MemoryHook() = default;
 
 
   virtual void *heap_alloc_single(size_t size);
   virtual void *heap_alloc_single(size_t size);
   virtual void heap_free_single(void *ptr);
   virtual void heap_free_single(void *ptr);
@@ -63,29 +61,26 @@ public:
 
 
   virtual void mark_pointer(void *ptr, size_t orig_size, ReferenceCount *ref_ptr);
   virtual void mark_pointer(void *ptr, size_t orig_size, ReferenceCount *ref_ptr);
 
 
-  DeletedBufferChain *get_deleted_chain(size_t buffer_size);
-
   virtual void alloc_fail(size_t attempted_size);
   virtual void alloc_fail(size_t attempted_size);
 
 
   INLINE static size_t get_ptr_size(void *ptr);
   INLINE static size_t get_ptr_size(void *ptr);
 
 
 protected:
 protected:
-  TVOLATILE AtomicAdjust::Integer _total_heap_single_size;
-  TVOLATILE AtomicAdjust::Integer _total_heap_array_size;
-  TVOLATILE AtomicAdjust::Integer _requested_heap_size;
-  TVOLATILE AtomicAdjust::Integer _total_mmap_size;
+  TVOLATILE AtomicAdjust::Integer _total_heap_single_size = 0;
+  TVOLATILE AtomicAdjust::Integer _total_heap_array_size = 0;
+  TVOLATILE AtomicAdjust::Integer _requested_heap_size = 0;
+  TVOLATILE AtomicAdjust::Integer _total_mmap_size = 0;
 
 
   // If the allocated heap size crosses this threshold, we call
   // If the allocated heap size crosses this threshold, we call
   // overflow_heap_size().
   // overflow_heap_size().
-  size_t _max_heap_size;
+  size_t _max_heap_size = ~(size_t)0;
 
 
   virtual void overflow_heap_size();
   virtual void overflow_heap_size();
 
 
-private:
-  size_t _page_size;
+  void determine_page_size() const;
 
 
-  typedef std::map<size_t, DeletedBufferChain *> DeletedChains;
-  DeletedChains _deleted_chains;
+private:
+  mutable size_t _page_size = 0;
 
 
   mutable MutexImpl _lock;
   mutable MutexImpl _lock;
 };
 };

+ 2 - 0
dtool/src/dtoolbase/mutexSpinlockImpl.cxx

@@ -20,6 +20,8 @@
 #if defined(__i386__) || defined(__x86_64) || defined(_M_IX86) || defined(_M_X64)
 #if defined(__i386__) || defined(__x86_64) || defined(_M_IX86) || defined(_M_X64)
 #include <emmintrin.h>
 #include <emmintrin.h>
 #define PAUSE() _mm_pause()
 #define PAUSE() _mm_pause()
+#elif defined(_WIN32)
+#define PAUSE() YieldProcessor()
 #else
 #else
 #define PAUSE()
 #define PAUSE()
 #endif
 #endif

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

@@ -539,7 +539,6 @@ TypeRegistry() {
  */
  */
 void TypeRegistry::
 void TypeRegistry::
 init_global_pointer() {
 init_global_pointer() {
-  init_memory_hook();
   _global_pointer = new TypeRegistry;
   _global_pointer = new TypeRegistry;
 }
 }
 
 

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

@@ -53,8 +53,8 @@ PUBLISHED:
   };
   };
 
 
   DSearchPath() = default;
   DSearchPath() = default;
-  DSearchPath(const std::string &path, const std::string &separator = std::string());
-  DSearchPath(const Filename &directory);
+  explicit DSearchPath(const std::string &path, const std::string &separator = std::string());
+  explicit DSearchPath(const Filename &directory);
   DSearchPath(const DSearchPath &copy) = default;
   DSearchPath(const DSearchPath &copy) = default;
   DSearchPath(DSearchPath &&from) = default;
   DSearchPath(DSearchPath &&from) = default;
   ~DSearchPath() = default;
   ~DSearchPath() = default;

+ 1 - 1
dtool/src/dtoolutil/filename.h

@@ -63,7 +63,7 @@ public:
 
 
 PUBLISHED:
 PUBLISHED:
   INLINE Filename();
   INLINE Filename();
-  Filename(const Filename &dirname, const Filename &basename);
+  explicit Filename(const Filename &dirname, const Filename &basename);
 
 
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
   EXTENSION(Filename(PyObject *path));
   EXTENSION(Filename(PyObject *path));

+ 16 - 0
dtool/src/interrogate/functionRemap.cxx

@@ -312,6 +312,22 @@ make_wrapper_entry(FunctionIndex function_index) {
     iwrapper._flags |= InterrogateFunctionWrapper::F_callable_by_name;
     iwrapper._flags |= InterrogateFunctionWrapper::F_callable_by_name;
   }
   }
 
 
+  if (_flags & F_copy_constructor) {
+    iwrapper._flags |= InterrogateFunctionWrapper::F_copy_constructor;
+  }
+
+  if (_flags & F_coerce_constructor) {
+    iwrapper._flags |= InterrogateFunctionWrapper::F_coerce_constructor;
+  }
+
+  if (_extension) {
+    iwrapper._flags |= InterrogateFunctionWrapper::F_extension;
+  }
+
+  if (_cppfunc->_attributes.has_attribute("deprecated")) {
+    iwrapper._flags |= InterrogateFunctionWrapper::F_deprecated;
+  }
+
   Parameters::const_iterator pi;
   Parameters::const_iterator pi;
   for (pi = _parameters.begin();
   for (pi = _parameters.begin();
        pi != _parameters.end();
        pi != _parameters.end();

+ 1 - 1
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -74,7 +74,7 @@ RenameSet methodRenameDictionary[] = {
   { "operator ="    , "assign",                 0 },
   { "operator ="    , "assign",                 0 },
   { "operator ()"   , "__call__",               0 },
   { "operator ()"   , "__call__",               0 },
   { "operator []"   , "__getitem__",            0 },
   { "operator []"   , "__getitem__",            0 },
-  { "operator [] =" , "__setitem__",            0 },
+  { "operator []="  , "__setitem__",            0 },
   { "operator ++unary", "increment",            0 },
   { "operator ++unary", "increment",            0 },
   { "operator ++"   , "increment",              0 },
   { "operator ++"   , "increment",              0 },
   { "operator --unary", "decrement",            0 },
   { "operator --unary", "decrement",            0 },

+ 9 - 10
dtool/src/interrogate/interrogate.cxx

@@ -417,8 +417,8 @@ main(int argc, char **argv) {
       break;
       break;
 
 
     case CO_python_native:
     case CO_python_native:
-        build_python_native = true;
-        break;
+      build_python_native = true;
+      break;
 
 
     case CO_track_interpreter:
     case CO_track_interpreter:
       track_interpreter = true;
       track_interpreter = true;
@@ -604,23 +604,22 @@ main(int argc, char **argv) {
       << " *\n"
       << " *\n"
       << " */\n\n";
       << " */\n\n";
 
 
-    if(the_output_include != nullptr)
-    {
-        output_code << "#include \""<<output_include_filename<<"\"\n";
-        *the_output_include << "#include \"" << output_include_filename.get_fullpath_wo_extension() << "_pynative.h\"\n";
+    if (the_output_include != nullptr) {
+      output_code << "#include \"" << output_include_filename << "\"\n";
+      *the_output_include << "#include \"" << output_include_filename.get_fullpath_wo_extension() << "_pynative.h\"\n";
     }
     }
 
 
     if (output_code.fail()) {
     if (output_code.fail()) {
       nout << "Unable to write to " << output_code_filename << "\n";
       nout << "Unable to write to " << output_code_filename << "\n";
       status = -1;
       status = -1;
     } else {
     } else {
-      builder.write_code(output_code,the_output_include, def);
+      builder.write_code(output_code, the_output_include, def);
     }
     }
   }
   }
 
 
-
-  if(the_output_include != nullptr)
-      *the_output_include << "#endif  // #define   " << output_include_filename.get_basename_wo_extension() << "__HH__\n";
+  if (the_output_include != nullptr) {
+    *the_output_include << "#endif  // #define   " << output_include_filename.get_basename_wo_extension() << "__HH__\n";
+  }
 
 
   // And now output the bulk of the database.
   // And now output the bulk of the database.
   if (!output_data_filename.empty()) {
   if (!output_data_filename.empty()) {

+ 5 - 1
dtool/src/interrogate/interrogateBuilder.cxx

@@ -2381,6 +2381,10 @@ get_type(CPPType *type, bool global) {
     }
     }
   }
   }
 
 
+  if (type->_attributes.has_attribute("deprecated")) {
+    itype._flags |= InterrogateType::F_deprecated;
+  }
+
   if (forced || !in_ignoretype(true_name)) {
   if (forced || !in_ignoretype(true_name)) {
     itype._flags |= InterrogateType::F_fully_defined;
     itype._flags |= InterrogateType::F_fully_defined;
 
 
@@ -3050,7 +3054,7 @@ define_method(CPPInstance *function, InterrogateType &itype,
         CPPFunctionType *ftype = new CPPFunctionType(void_type, params, 0);
         CPPFunctionType *ftype = new CPPFunctionType(void_type, params, 0);
 
 
         // Now make up an instance for the function.
         // Now make up an instance for the function.
-        CPPInstance *function = new CPPInstance(ftype, "operator [] =");
+        CPPInstance *function = new CPPInstance(ftype, "operator []=");
         function->_ident->_native_scope = scope;
         function->_ident->_native_scope = scope;
 
 
         FunctionIndex index = get_function(function, "",
         FunctionIndex index = get_function(function, "",

+ 32 - 0
dtool/src/interrogatedb/interrogateFunctionWrapper.I

@@ -63,6 +63,38 @@ is_callable_by_name() const {
   return (_flags & F_callable_by_name) != 0;
   return (_flags & F_callable_by_name) != 0;
 }
 }
 
 
+/**
+ * @since 1.10.13
+ */
+INLINE bool InterrogateFunctionWrapper::
+is_copy_constructor() const {
+  return (_flags & F_copy_constructor) != 0;
+}
+
+/**
+ * @since 1.10.13
+ */
+INLINE bool InterrogateFunctionWrapper::
+is_coerce_constructor() const {
+  return (_flags & F_coerce_constructor) != 0;
+}
+
+/**
+ * @since 1.10.13
+ */
+INLINE bool InterrogateFunctionWrapper::
+is_extension() const {
+  return (_flags & F_extension) != 0;
+}
+
+/**
+ * @since 1.11.0
+ */
+INLINE bool InterrogateFunctionWrapper::
+is_deprecated() const {
+  return (_flags & F_deprecated) != 0;
+}
+
 /**
 /**
  *
  *
  */
  */

+ 9 - 1
dtool/src/interrogatedb/interrogateFunctionWrapper.h

@@ -34,6 +34,10 @@ public:
   INLINE FunctionIndex get_function() const;
   INLINE FunctionIndex get_function() const;
 
 
   INLINE bool is_callable_by_name() const;
   INLINE bool is_callable_by_name() const;
+  INLINE bool is_copy_constructor() const;
+  INLINE bool is_coerce_constructor() const;
+  INLINE bool is_extension() const;
+  INLINE bool is_deprecated() const;
 
 
   INLINE bool has_return_value() const;
   INLINE bool has_return_value() const;
   INLINE TypeIndex get_return_type() const;
   INLINE TypeIndex get_return_type() const;
@@ -61,7 +65,11 @@ private:
   enum Flags {
   enum Flags {
     F_caller_manages   = 0x0001,
     F_caller_manages   = 0x0001,
     F_has_return       = 0x0002,
     F_has_return       = 0x0002,
-    F_callable_by_name = 0x0004
+    F_callable_by_name = 0x0004,
+    F_copy_constructor = 0x0008,
+    F_coerce_constructor = 0x0010,
+    F_extension        = 0x0020,
+    F_deprecated       = 0x0040,
   };
   };
 
 
   enum ParameterFlags {
   enum ParameterFlags {

+ 10 - 0
dtool/src/interrogatedb/interrogateType.I

@@ -20,6 +20,16 @@ is_global() const {
   return (_flags & F_global) != 0;
   return (_flags & F_global) != 0;
 }
 }
 
 
+/**
+ * Returns true if the type is marked as 'deprecated'.
+ *
+ * @since 1.11.0
+ */
+INLINE bool InterrogateType::
+is_deprecated() const {
+  return (_flags & F_deprecated) != 0;
+}
+
 /**
 /**
  *
  *
  */
  */

+ 2 - 0
dtool/src/interrogatedb/interrogateType.h

@@ -34,6 +34,7 @@ public:
   void operator = (const InterrogateType &copy);
   void operator = (const InterrogateType &copy);
 
 
   INLINE bool is_global() const;
   INLINE bool is_global() const;
+  INLINE bool is_deprecated() const;
 
 
   INLINE bool has_scoped_name() const;
   INLINE bool has_scoped_name() const;
   INLINE const std::string &get_scoped_name() const;
   INLINE const std::string &get_scoped_name() const;
@@ -141,6 +142,7 @@ private:
     F_array                = 0x400000,
     F_array                = 0x400000,
     F_scoped_enum          = 0x800000,
     F_scoped_enum          = 0x800000,
     F_final                =0x1000000,
     F_final                =0x1000000,
+    F_deprecated           =0x2000000,
   };
   };
 
 
 public:
 public:

+ 102 - 0
dtool/src/interrogatedb/interrogate_interface.cxx

@@ -176,6 +176,72 @@ interrogate_element_setter(ElementIndex element) {
   return InterrogateDatabase::get_ptr()->get_element(element).get_setter();
   return InterrogateDatabase::get_ptr()->get_element(element).get_setter();
 }
 }
 
 
+bool
+interrogate_element_has_has_function(ElementIndex element) {
+  // cerr << "interrogate_element_has_has_function(" << element << ")\n";
+  return InterrogateDatabase::get_ptr()->get_element(element).has_has_function();
+}
+
+FunctionIndex
+interrogate_element_has_function(ElementIndex element) {
+  // cerr << "interrogate_element_has_function(" << element << ")\n";
+  return InterrogateDatabase::get_ptr()->get_element(element).get_has_function();
+}
+
+bool
+interrogate_element_has_clear_function(ElementIndex element) {
+  // cerr << "interrogate_element_has_clear_function(" << element << ")\n";
+  return InterrogateDatabase::get_ptr()->get_element(element).has_clear_function();
+}
+
+FunctionIndex
+interrogate_element_clear_function(ElementIndex element) {
+  // cerr << "interrogate_element_clear_function(" << element << ")\n";
+  return InterrogateDatabase::get_ptr()->get_element(element).get_clear_function();
+}
+
+bool
+interrogate_element_has_del_function(ElementIndex element) {
+  // cerr << "interrogate_element_has_del_function(" << element << ")\n";
+  return InterrogateDatabase::get_ptr()->get_element(element).has_del_function();
+}
+
+FunctionIndex
+interrogate_element_del_function(ElementIndex element) {
+  // cerr << "interrogate_element_del_function(" << element << ")\n";
+  return InterrogateDatabase::get_ptr()->get_element(element).get_del_function();
+}
+
+bool
+interrogate_element_has_insert_function(ElementIndex element) {
+  // cerr << "interrogate_element_has_insert_function(" << element << ")\n";
+  return InterrogateDatabase::get_ptr()->get_element(element).has_insert_function();
+}
+
+FunctionIndex
+interrogate_element_insert_function(ElementIndex element) {
+  // cerr << "interrogate_element_insert_function(" << element << ")\n";
+  return InterrogateDatabase::get_ptr()->get_element(element).get_insert_function();
+}
+
+bool
+interrogate_element_has_getkey_function(ElementIndex element) {
+  // cerr << "interrogate_element_has_getkey_function(" << element << ")\n";
+  return InterrogateDatabase::get_ptr()->get_element(element).has_getkey_function();
+}
+
+FunctionIndex
+interrogate_element_getkey_function(ElementIndex element) {
+  // cerr << "interrogate_element_getkey_function(" << element << ")\n";
+  return InterrogateDatabase::get_ptr()->get_element(element).get_getkey_function();
+}
+
+FunctionIndex
+interrogate_element_length_function(ElementIndex element) {
+  // cerr << "interrogate_element_length_function(" << element << ")\n";
+  return InterrogateDatabase::get_ptr()->get_element(element).get_length_function();
+}
+
 bool
 bool
 interrogate_element_is_sequence(ElementIndex element) {
 interrogate_element_is_sequence(ElementIndex element) {
   // cerr << "interrogate_element_is_sequence(" << element << ")\n";
   // cerr << "interrogate_element_is_sequence(" << element << ")\n";
@@ -359,12 +425,42 @@ interrogate_wrapper_name(FunctionWrapperIndex wrapper) {
   return result.c_str();
   return result.c_str();
 }
 }
 
 
+FunctionIndex
+interrogate_wrapper_function(FunctionWrapperIndex wrapper) {
+  // cerr << "interrogate_wrapper_function(" << wrapper << ")\n";
+  return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).get_function();
+}
+
 bool
 bool
 interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper) {
 interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper) {
   // cerr << "interrogate_wrapper_is_callable_by_name(" << wrapper << ")\n";
   // cerr << "interrogate_wrapper_is_callable_by_name(" << wrapper << ")\n";
   return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_callable_by_name();
   return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_callable_by_name();
 }
 }
 
 
+bool
+interrogate_wrapper_is_copy_constructor(FunctionWrapperIndex wrapper) {
+  // cerr << "interrogate_wrapper_is_copy_constructor(" << wrapper << ")\n";
+  return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_copy_constructor();
+}
+
+bool
+interrogate_wrapper_is_coerce_constructor(FunctionWrapperIndex wrapper) {
+  // cerr << "interrogate_wrapper_is_coerce_constructor(" << wrapper << ")\n";
+  return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_coerce_constructor();
+}
+
+bool
+interrogate_wrapper_is_extension(FunctionWrapperIndex wrapper) {
+  // cerr << "interrogate_wrapper_is_extension(" << wrapper << ")\n";
+  return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_extension();
+}
+
+bool
+interrogate_wrapper_is_deprecated(FunctionWrapperIndex wrapper) {
+  // cerr << "interrogate_wrapper_is_deprecated(" << wrapper << ")\n";
+  return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_deprecated();
+}
+
 bool
 bool
 interrogate_wrapper_has_comment(FunctionWrapperIndex wrapper) {
 interrogate_wrapper_has_comment(FunctionWrapperIndex wrapper) {
   // cerr << "interrogate_wrapper_has_comment(" << wrapper << ")\n";
   // cerr << "interrogate_wrapper_has_comment(" << wrapper << ")\n";
@@ -571,6 +667,12 @@ interrogate_type_is_global(TypeIndex type) {
   return InterrogateDatabase::get_ptr()->get_type(type).is_global();
   return InterrogateDatabase::get_ptr()->get_type(type).is_global();
 }
 }
 
 
+bool
+interrogate_type_is_deprecated(TypeIndex type) {
+  // cerr << "interrogate_type_is_deprecated(" << type << ")\n";
+  return InterrogateDatabase::get_ptr()->get_type(type).is_deprecated();
+}
+
 const char *
 const char *
 interrogate_type_name(TypeIndex type) {
 interrogate_type_name(TypeIndex type) {
   // cerr << "interrogate_type_name(" << type << ")\n";
   // cerr << "interrogate_type_name(" << type << ")\n";

+ 28 - 0
dtool/src/interrogatedb/interrogate_interface.h

@@ -152,6 +152,17 @@ EXPCL_INTERROGATEDB bool interrogate_element_has_getter(ElementIndex element);
 EXPCL_INTERROGATEDB FunctionIndex interrogate_element_getter(ElementIndex element);
 EXPCL_INTERROGATEDB FunctionIndex interrogate_element_getter(ElementIndex element);
 EXPCL_INTERROGATEDB bool interrogate_element_has_setter(ElementIndex element);
 EXPCL_INTERROGATEDB bool interrogate_element_has_setter(ElementIndex element);
 EXPCL_INTERROGATEDB FunctionIndex interrogate_element_setter(ElementIndex element);
 EXPCL_INTERROGATEDB FunctionIndex interrogate_element_setter(ElementIndex element);
+EXPCL_INTERROGATEDB bool interrogate_element_has_has_function(ElementIndex element);
+EXPCL_INTERROGATEDB FunctionIndex interrogate_element_has_function(ElementIndex element);
+EXPCL_INTERROGATEDB bool interrogate_element_has_clear_function(ElementIndex element);
+EXPCL_INTERROGATEDB FunctionIndex interrogate_element_clear_function(ElementIndex element);
+EXPCL_INTERROGATEDB bool interrogate_element_has_del_function(ElementIndex element);
+EXPCL_INTERROGATEDB FunctionIndex interrogate_element_del_function(ElementIndex element);
+EXPCL_INTERROGATEDB bool interrogate_element_has_insert_function(ElementIndex element);
+EXPCL_INTERROGATEDB FunctionIndex interrogate_element_insert_function(ElementIndex element);
+EXPCL_INTERROGATEDB bool interrogate_element_has_getkey_function(ElementIndex element);
+EXPCL_INTERROGATEDB FunctionIndex interrogate_element_getkey_function(ElementIndex element);
+EXPCL_INTERROGATEDB FunctionIndex interrogate_element_length_function(ElementIndex element);
 
 
 EXPCL_INTERROGATEDB bool interrogate_element_is_sequence(ElementIndex element);
 EXPCL_INTERROGATEDB bool interrogate_element_is_sequence(ElementIndex element);
 EXPCL_INTERROGATEDB bool interrogate_element_is_mapping(ElementIndex element);
 EXPCL_INTERROGATEDB bool interrogate_element_is_mapping(ElementIndex element);
@@ -261,10 +272,26 @@ EXPCL_INTERROGATEDB FunctionWrapperIndex interrogate_function_python_wrapper(Fun
 // not identical.
 // not identical.
 EXPCL_INTERROGATEDB const char *interrogate_wrapper_name(FunctionWrapperIndex wrapper);
 EXPCL_INTERROGATEDB const char *interrogate_wrapper_name(FunctionWrapperIndex wrapper);
 
 
+// Returns the function that this wrapper belongs to.
+EXPCL_INTERROGATEDB FunctionIndex interrogate_wrapper_function(FunctionWrapperIndex wrapper);
+
 // This returns true if -fnames was given to interrogate, making the wrapper
 // This returns true if -fnames was given to interrogate, making the wrapper
 // function callable directly by its name.
 // function callable directly by its name.
 EXPCL_INTERROGATEDB bool interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper);
 EXPCL_INTERROGATEDB bool interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper);
 
 
+// This returns true if this is a copy constructor.
+EXPCL_INTERROGATEDB bool interrogate_wrapper_is_copy_constructor(FunctionWrapperIndex wrapper);
+
+// This returns true if this is a constructor that is not marked "explicit".
+EXPCL_INTERROGATEDB bool interrogate_wrapper_is_coerce_constructor(FunctionWrapperIndex wrapper);
+
+// This returns true if this is an extension function, rather than a real
+// function defined in the C++ code.
+EXPCL_INTERROGATEDB bool interrogate_wrapper_is_extension(FunctionWrapperIndex wrapper);
+
+// This returns true if function is marked as deprecated.
+EXPCL_INTERROGATEDB bool interrogate_wrapper_is_deprecated(FunctionWrapperIndex wrapper);
+
 // This returns the C++ comment written for the function wrapper, usually from
 // This returns the C++ comment written for the function wrapper, usually from
 // the .cpp file.  There may be a different comment for each overload of a
 // the .cpp file.  There may be a different comment for each overload of a
 // given function.
 // given function.
@@ -377,6 +404,7 @@ EXPCL_INTERROGATEDB TypeIndex interrogate_get_type_by_name(const char *type_name
 EXPCL_INTERROGATEDB TypeIndex interrogate_get_type_by_scoped_name(const char *type_name);
 EXPCL_INTERROGATEDB TypeIndex interrogate_get_type_by_scoped_name(const char *type_name);
 EXPCL_INTERROGATEDB TypeIndex interrogate_get_type_by_true_name(const char *type_name);
 EXPCL_INTERROGATEDB TypeIndex interrogate_get_type_by_true_name(const char *type_name);
 EXPCL_INTERROGATEDB bool interrogate_type_is_global(TypeIndex type);
 EXPCL_INTERROGATEDB bool interrogate_type_is_global(TypeIndex type);
+EXPCL_INTERROGATEDB bool interrogate_type_is_deprecated(TypeIndex type);
 EXPCL_INTERROGATEDB const char *interrogate_type_name(TypeIndex type);
 EXPCL_INTERROGATEDB const char *interrogate_type_name(TypeIndex type);
 EXPCL_INTERROGATEDB const char *interrogate_type_scoped_name(TypeIndex type);
 EXPCL_INTERROGATEDB const char *interrogate_type_scoped_name(TypeIndex type);
 EXPCL_INTERROGATEDB const char *interrogate_type_true_name(TypeIndex type);
 EXPCL_INTERROGATEDB const char *interrogate_type_true_name(TypeIndex type);

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

@@ -47,8 +47,4 @@ namespace std {
   typedef decltype(nullptr) nullptr_t;
   typedef decltype(nullptr) nullptr_t;
 }
 }
 
 
-// One day, we might extend interrogate to be able to parse this,
-// but we currently don't need it.
-#define alignas(x)
-
 #endif
 #endif

+ 1 - 1
dtool/src/prc/configVariableBool.h

@@ -22,7 +22,7 @@
  */
  */
 class EXPCL_DTOOL_PRC ConfigVariableBool : public ConfigVariable {
 class EXPCL_DTOOL_PRC ConfigVariableBool : public ConfigVariable {
 PUBLISHED:
 PUBLISHED:
-  INLINE ConfigVariableBool(const std::string &name);
+  INLINE explicit ConfigVariableBool(const std::string &name);
   INLINE ConfigVariableBool(const std::string &name, bool default_value,
   INLINE ConfigVariableBool(const std::string &name, bool default_value,
                             const std::string &description = std::string(), int flags = 0);
                             const std::string &description = std::string(), int flags = 0);
   INLINE ConfigVariableBool(const std::string &name, const std::string &default_value,
   INLINE ConfigVariableBool(const std::string &name, const std::string &default_value,

+ 1 - 1
dtool/src/prc/configVariableDouble.h

@@ -23,7 +23,7 @@
  */
  */
 class EXPCL_DTOOL_PRC ConfigVariableDouble : public ConfigVariable {
 class EXPCL_DTOOL_PRC ConfigVariableDouble : public ConfigVariable {
 PUBLISHED:
 PUBLISHED:
-  INLINE ConfigVariableDouble(const std::string &name);
+  INLINE explicit ConfigVariableDouble(const std::string &name);
   INLINE ConfigVariableDouble(const std::string &name, double default_value,
   INLINE ConfigVariableDouble(const std::string &name, double default_value,
                               const std::string &description = std::string(),
                               const std::string &description = std::string(),
                               int flags = 0);
                               int flags = 0);

+ 1 - 1
dtool/src/prc/configVariableFilename.h

@@ -26,7 +26,7 @@
  */
  */
 class EXPCL_DTOOL_PRC ConfigVariableFilename : public ConfigVariable {
 class EXPCL_DTOOL_PRC ConfigVariableFilename : public ConfigVariable {
 PUBLISHED:
 PUBLISHED:
-  INLINE ConfigVariableFilename(const std::string &name);
+  INLINE explicit ConfigVariableFilename(const std::string &name);
   INLINE ConfigVariableFilename(const std::string &name, const Filename &default_value,
   INLINE ConfigVariableFilename(const std::string &name, const Filename &default_value,
                                 const std::string &description = std::string(), int flags = 0);
                                 const std::string &description = std::string(), int flags = 0);
 
 

+ 1 - 1
dtool/src/prc/configVariableInt.h

@@ -23,7 +23,7 @@
  */
  */
 class EXPCL_DTOOL_PRC ConfigVariableInt : public ConfigVariable {
 class EXPCL_DTOOL_PRC ConfigVariableInt : public ConfigVariable {
 PUBLISHED:
 PUBLISHED:
-  INLINE ConfigVariableInt(const std::string &name);
+  INLINE explicit ConfigVariableInt(const std::string &name);
   INLINE ConfigVariableInt(const std::string &name, int default_value,
   INLINE ConfigVariableInt(const std::string &name, int default_value,
                            const std::string &description = std::string(),
                            const std::string &description = std::string(),
                            int flags = 0);
                            int flags = 0);

+ 1 - 1
dtool/src/prc/configVariableInt64.h

@@ -24,7 +24,7 @@
  */
  */
 class EXPCL_DTOOL_PRC ConfigVariableInt64 : public ConfigVariable {
 class EXPCL_DTOOL_PRC ConfigVariableInt64 : public ConfigVariable {
 PUBLISHED:
 PUBLISHED:
-  INLINE ConfigVariableInt64(const std::string &name);
+  INLINE explicit ConfigVariableInt64(const std::string &name);
   INLINE ConfigVariableInt64(const std::string &name, int64_t default_value,
   INLINE ConfigVariableInt64(const std::string &name, int64_t default_value,
                              const std::string &description = std::string(),
                              const std::string &description = std::string(),
                              int flags = 0);
                              int flags = 0);

+ 0 - 1
dtool/src/prc/configVariableManager.cxx

@@ -28,7 +28,6 @@ ConfigVariableManager *ConfigVariableManager::_global_ptr = nullptr;
  */
  */
 ConfigVariableManager::
 ConfigVariableManager::
 ConfigVariableManager() {
 ConfigVariableManager() {
-  init_memory_hook();
 }
 }
 
 
 /**
 /**

+ 0 - 1
dtool/src/prc/notify.cxx

@@ -291,7 +291,6 @@ write_string(const string &str) {
 Notify *Notify::
 Notify *Notify::
 ptr() {
 ptr() {
   if (_global_ptr == nullptr) {
   if (_global_ptr == nullptr) {
-    init_memory_hook();
     _global_ptr = new Notify;
     _global_ptr = new Notify;
   }
   }
   return _global_ptr;
   return _global_ptr;

+ 4 - 2
makepanda/makepanda.py

@@ -626,6 +626,7 @@ if (COMPILER == "MSVC"):
     LibName("WINSOCK2", "ws2_32.lib")
     LibName("WINSOCK2", "ws2_32.lib")
     LibName("WINCOMCTL", "comctl32.lib")
     LibName("WINCOMCTL", "comctl32.lib")
     LibName("WINCOMDLG", "comdlg32.lib")
     LibName("WINCOMDLG", "comdlg32.lib")
+    LibName("UXTHEME", "uxtheme.lib")
     LibName("WINUSER", "user32.lib")
     LibName("WINUSER", "user32.lib")
     LibName("WINMM", "winmm.lib")
     LibName("WINMM", "winmm.lib")
     LibName("WINIMM", "imm32.lib")
     LibName("WINIMM", "imm32.lib")
@@ -2417,7 +2418,7 @@ DTOOL_CONFIG=[
     ("HAVE_PROC_SELF_CMDLINE",         'UNDEF',                  '1'),
     ("HAVE_PROC_SELF_CMDLINE",         'UNDEF',                  '1'),
     ("HAVE_PROC_CURPROC_FILE",         'UNDEF',                  'UNDEF'),
     ("HAVE_PROC_CURPROC_FILE",         'UNDEF',                  'UNDEF'),
     ("HAVE_PROC_CURPROC_MAP",          'UNDEF',                  'UNDEF'),
     ("HAVE_PROC_CURPROC_MAP",          'UNDEF',                  'UNDEF'),
-    ("HAVE_PROC_SELF_CMDLINE",         'UNDEF',                  'UNDEF'),
+    ("HAVE_PROC_CURPROC_CMDLINE",      'UNDEF',                  'UNDEF'),
     ("HAVE_GLOBAL_ARGV",               '1',                      'UNDEF'),
     ("HAVE_GLOBAL_ARGV",               '1',                      'UNDEF'),
     ("PROTOTYPE_GLOBAL_ARGV",          'UNDEF',                  'UNDEF'),
     ("PROTOTYPE_GLOBAL_ARGV",          'UNDEF',                  'UNDEF'),
     ("GLOBAL_ARGV",                    '__argv',                 'UNDEF'),
     ("GLOBAL_ARGV",                    '__argv',                 'UNDEF'),
@@ -3332,6 +3333,7 @@ if not PkgSkip("DIRECT"):
     CopyAllHeaders('direct/src/distributed')
     CopyAllHeaders('direct/src/distributed')
     CopyAllHeaders('direct/src/interval')
     CopyAllHeaders('direct/src/interval')
     CopyAllHeaders('direct/src/showbase')
     CopyAllHeaders('direct/src/showbase')
+    CopyAllHeaders('direct/src/motiontrail')
     CopyAllHeaders('direct/src/dcparse')
     CopyAllHeaders('direct/src/dcparse')
 
 
 if not PkgSkip("PANDATOOL"):
 if not PkgSkip("PANDATOOL"):
@@ -5962,7 +5964,7 @@ if not PkgSkip("PANDATOOL") and (GetTarget() == 'windows' or not PkgSkip("GTK3")
     TargetAdd('pstats.exe', input='libp3progbase.lib')
     TargetAdd('pstats.exe', input='libp3progbase.lib')
     TargetAdd('pstats.exe', input='libp3pandatoolbase.lib')
     TargetAdd('pstats.exe', input='libp3pandatoolbase.lib')
     TargetAdd('pstats.exe', input=COMMON_PANDA_LIBS)
     TargetAdd('pstats.exe', input=COMMON_PANDA_LIBS)
-    TargetAdd('pstats.exe', opts=['SUBSYSTEM:WINDOWS', 'WINCOMCTL', 'WINSOCK', 'WINIMM', 'WINGDI', 'WINKERNEL', 'WINOLDNAMES', 'WINUSER', 'WINMM', 'GTK3'])
+    TargetAdd('pstats.exe', opts=['SUBSYSTEM:WINDOWS', 'WINCOMCTL', 'WINCOMDLG', 'WINSOCK', 'WINIMM', 'WINGDI', 'WINKERNEL', 'WINOLDNAMES', 'WINUSER', 'WINMM', 'UXTHEME', 'GTK3'])
 
 
 #
 #
 # DIRECTORY: pandatool/src/xfileprogs/
 # DIRECTORY: pandatool/src/xfileprogs/

+ 4 - 0
panda/src/audio/audioSound.h

@@ -42,6 +42,10 @@ PUBLISHED:
   virtual void set_loop_count(unsigned long loop_count=1) = 0;
   virtual void set_loop_count(unsigned long loop_count=1) = 0;
   virtual unsigned long get_loop_count() const = 0;
   virtual unsigned long get_loop_count() const = 0;
 
 
+  // loop_start: 0 = beginning.  expressed in seconds.  inits to 0.
+  virtual void set_loop_start(PN_stdfloat loop_start=0) = 0;
+  virtual PN_stdfloat get_loop_start() const = 0;
+
   /**
   /**
    * Control time position within the sound, in seconds.  This is similar (in
    * Control time position within the sound, in seconds.  This is similar (in
    * concept) to the seek position within a file.  The value starts at 0.0 (the
    * concept) to the seek position within a file.  The value starts at 0.0 (the

+ 8 - 0
panda/src/audio/nullAudioSound.cxx

@@ -58,6 +58,14 @@ unsigned long NullAudioSound::get_loop_count() const {
   return 0;
   return 0;
 }
 }
 
 
+void NullAudioSound::set_loop_start(PN_stdfloat) {
+  // Intentionally blank.
+}
+
+PN_stdfloat NullAudioSound::get_loop_start() const {
+  return 0;
+}
+
 void NullAudioSound::set_time(PN_stdfloat) {
 void NullAudioSound::set_time(PN_stdfloat) {
   // Intentionally blank.
   // Intentionally blank.
 }
 }

+ 3 - 0
panda/src/audio/nullAudioSound.h

@@ -37,6 +37,9 @@ public:
   void set_loop_count(unsigned long);
   void set_loop_count(unsigned long);
   unsigned long get_loop_count() const;
   unsigned long get_loop_count() const;
 
 
+  void set_loop_start(PN_stdfloat);
+  PN_stdfloat get_loop_start() const;
+
   void set_time(PN_stdfloat);
   void set_time(PN_stdfloat);
   PN_stdfloat get_time() const;
   PN_stdfloat get_time() const;
 
 

+ 43 - 0
panda/src/audiotraits/fmodAudioSound.cxx

@@ -339,6 +339,49 @@ get_loop_count() const {
   }
   }
 }
 }
 
 
+/**
+ * Sets the time at which subsequent loops will begin.
+ * A value of 0 indicates the beginning of the audio.
+ */
+void FmodAudioSound::
+set_loop_start(PN_stdfloat loop_start) {
+  ReMutexHolder holder(FmodAudioManager::_lock);
+  audio_debug("FmodAudioSound::set_loop_start()   Setting the sound's loop start to: " << loop_start);
+
+  FMOD_RESULT result;
+  unsigned int length;
+
+  result = _sound->getLength(&length, FMOD_TIMEUNIT_MS);
+  fmod_audio_errcheck("_sound->getLength()", result);
+
+  unsigned int loop_start_int = (unsigned int) (loop_start * 1000.0);
+
+  if (loop_start_int >= length) {
+    audio_debug("FmodAudioSound::set_loop_start()   Would loop after end of track, setting start to 0");
+    loop_start_int = 0;
+  }
+
+  result = _sound->setLoopPoints(loop_start_int, FMOD_TIMEUNIT_MS, length, FMOD_TIMEUNIT_MS);
+  fmod_audio_errcheck("_sound->setLoopPoints()", result);
+  audio_debug("FmodAudioSound::set_loop_start()   Sound's loop start should be set to: " << loop_start);
+}
+
+/**
+ * Return the time at which subsequent loops will begin.
+ * A value of 0 indicates the beginning of the audio.
+ */
+PN_stdfloat FmodAudioSound::
+get_loop_start() const {
+  ReMutexHolder holder(FmodAudioManager::_lock);
+  FMOD_RESULT result;
+  unsigned int loop_start;
+
+  result = _sound->getLoopPoints(&loop_start, FMOD_TIMEUNIT_MS, nullptr, FMOD_TIMEUNIT_MS);
+  fmod_audio_errcheck("_sound->getLoopPoints()", result);
+
+  return ((double)loop_start) / 1000.0;
+}
+
 /**
 /**
  * Sets the time at which the next play() operation will begin.  If we are
  * Sets the time at which the next play() operation will begin.  If we are
  * already playing, skips to that time immediatey.
  * already playing, skips to that time immediatey.

+ 4 - 0
panda/src/audiotraits/fmodAudioSound.h

@@ -91,6 +91,10 @@ public:
   void set_loop_count(unsigned long loop_count=1);
   void set_loop_count(unsigned long loop_count=1);
   unsigned long get_loop_count() const;
   unsigned long get_loop_count() const;
 
 
+  // loop_start: 0 = beginning.  expressed in seconds.  inits to 0.
+  void set_loop_start(PN_stdfloat loop_start=0);
+  PN_stdfloat get_loop_start() const;
+
   // 0 = beginning; length() = end.  inits to 0.0.
   // 0 = beginning; length() = end.  inits to 0.0.
   void set_time(PN_stdfloat start_time=0.0);
   void set_time(PN_stdfloat start_time=0.0);
   PN_stdfloat get_time() const;
   PN_stdfloat get_time() const;

+ 34 - 3
panda/src/audiotraits/openalAudioSound.cxx

@@ -53,6 +53,7 @@ OpenALAudioSound(OpenALAudioManager* manager,
   _drop_off_factor(1.0f),
   _drop_off_factor(1.0f),
   _length(0.0),
   _length(0.0),
   _loop_count(1),
   _loop_count(1),
+  _loop_start(0),
   _desired_mode(mode),
   _desired_mode(mode),
   _start_time(0.0),
   _start_time(0.0),
   _current_time(0.0),
   _current_time(0.0),
@@ -279,6 +280,36 @@ get_loop_count() const {
   return _loop_count;
   return _loop_count;
 }
 }
 
 
+/**
+ * Sets the time at which subsequent loops will begin.
+ * A value of 0 indicates the beginning of the audio.
+ */
+void OpenALAudioSound::
+set_loop_start(PN_stdfloat loop_start) {
+  ReMutexHolder holder(OpenALAudioManager::_lock);
+
+  if (!is_valid()) {
+    return;
+  }
+
+  if (loop_start >= _length) {
+    // This loop would begin after the song ends.
+    // Not a good idea.
+    loop_start = 0;
+  }
+
+  _loop_start = loop_start;
+}
+
+/**
+ * Return the time at which subsequent loops will begin.
+ * A value of 0 indicates the beginning of the audio.
+ */
+PN_stdfloat OpenALAudioSound::
+get_loop_start() const {
+  return _loop_start;
+}
+
 /**
 /**
  * When streaming audio, the computer is supposed to keep OpenAL's queue full.
  * When streaming audio, the computer is supposed to keep OpenAL's queue full.
  * However, there are times when the computer is running slow and the queue
  * However, there are times when the computer is running slow and the queue
@@ -389,7 +420,7 @@ read_stream_data(int bytelen, unsigned char *buffer) {
     int samples = (int)(remain * rate);
     int samples = (int)(remain * rate);
     if (samples <= 0) {
     if (samples <= 0) {
       _loops_completed += 1;
       _loops_completed += 1;
-      cursor->seek(0.0);
+      cursor->seek(_loop_start);
       continue;
       continue;
     }
     }
     if (_sd->_stream->ready() == 0) {
     if (_sd->_stream->ready() == 0) {
@@ -411,7 +442,7 @@ read_stream_data(int bytelen, unsigned char *buffer) {
     }
     }
     if (samples == 0) {
     if (samples == 0) {
       _loops_completed += 1;
       _loops_completed += 1;
-      cursor->seek(0.0);
+      cursor->seek(_loop_start);
       if (_playing_loops >= 1000000000) {
       if (_playing_loops >= 1000000000) {
         // Prevent infinite loop if endlessly looping empty sound
         // Prevent infinite loop if endlessly looping empty sound
         return fill;
         return fill;
@@ -535,7 +566,7 @@ push_fresh_buffers() {
   if (_sd->_sample) {
   if (_sd->_sample) {
     while ((_loops_completed < _playing_loops) &&
     while ((_loops_completed < _playing_loops) &&
            (_stream_queued.size() < 100)) {
            (_stream_queued.size() < 100)) {
-      queue_buffer(_sd->_sample, 0,_loops_completed, 0.0);
+      queue_buffer(_sd->_sample, 0,_loops_completed, _loop_start);
       _loops_completed += 1;
       _loops_completed += 1;
     }
     }
   } else {
   } else {

+ 8 - 3
panda/src/audiotraits/openalAudioSound.h

@@ -50,6 +50,10 @@ public:
   void set_loop_count(unsigned long loop_count=1);
   void set_loop_count(unsigned long loop_count=1);
   unsigned long get_loop_count() const;
   unsigned long get_loop_count() const;
 
 
+  // loop_start: 0 = beginning.  expressed in seconds.  inits to 0.
+  void set_loop_start(PN_stdfloat loop_start=0);
+  PN_stdfloat get_loop_start() const;
+
   // 0 = beginning; length() = end.  inits to 0.0.
   // 0 = beginning; length() = end.  inits to 0.0.
   void set_time(PN_stdfloat time=0.0);
   void set_time(PN_stdfloat time=0.0);
   PN_stdfloat get_time() const;
   PN_stdfloat get_time() const;
@@ -156,10 +160,11 @@ private:
   PN_stdfloat _max_dist;
   PN_stdfloat _max_dist;
   PN_stdfloat _drop_off_factor;
   PN_stdfloat _drop_off_factor;
 
 
-  double _length;
-  int    _loop_count;
+  double      _length;
+  int         _loop_count;
+  PN_stdfloat _loop_start;
 
 
-  int    _desired_mode;
+  int         _desired_mode;
 
 
   // The calibrated clock is initialized when the sound starts playing, and is
   // The calibrated clock is initialized when the sound starts playing, and is
   // periodically corrected thereafter.
   // periodically corrected thereafter.

+ 1 - 4
panda/src/bullet/bulletAllHitsRayResult.I

@@ -18,10 +18,7 @@
 INLINE BulletAllHitsRayResult BulletAllHitsRayResult::
 INLINE BulletAllHitsRayResult BulletAllHitsRayResult::
 empty() {
 empty() {
 
 
-  btVector3 from;
-  btVector3 to;
-
-  return BulletAllHitsRayResult(from, to, CollideMask::all_on());
+  return BulletAllHitsRayResult(btVector3(0, 0, 0), btVector3(0, 0, 0), CollideMask::all_on());
 }
 }
 
 
 /**
 /**

+ 1 - 1
panda/src/bullet/bulletContactResult.I

@@ -32,7 +32,7 @@ get_node1() const {
 /**
 /**
  *
  *
  */
  */
-INLINE BulletManifoldPoint &BulletContact::
+INLINE BulletManifoldPoint BulletContact::
 get_manifold_point() {
 get_manifold_point() {
 
 
   return _mp;
   return _mp;

+ 8 - 8
panda/src/bullet/bulletContactResult.cxx

@@ -21,9 +21,13 @@ BulletContact BulletContactResult::_empty;
  */
  */
 BulletContact::
 BulletContact::
 BulletContact() : _mp(_empty) {
 BulletContact() : _mp(_empty) {
+}
 
 
-  _node0 = nullptr;
-  _node1 = nullptr;
+/**
+ *
+ */
+BulletContact::
+BulletContact(btManifoldPoint &mp) : _mp(mp) {
 }
 }
 
 
 /**
 /**
@@ -93,9 +97,7 @@ addSingleResult(btManifoldPoint &mp,
   const btCollisionObject *obj0 = wrap0->getCollisionObject();
   const btCollisionObject *obj0 = wrap0->getCollisionObject();
   const btCollisionObject *obj1 = wrap1->getCollisionObject();
   const btCollisionObject *obj1 = wrap1->getCollisionObject();
 
 
-  BulletContact contact;
-
-  contact._mp = BulletManifoldPoint(mp);
+  BulletContact contact(mp);
   contact._node0 = obj0 ? (PandaNode *)obj0->getUserPointer() : nullptr;
   contact._node0 = obj0 ? (PandaNode *)obj0->getUserPointer() : nullptr;
   contact._node1 = obj1 ? (PandaNode *)obj1->getUserPointer() : nullptr;
   contact._node1 = obj1 ? (PandaNode *)obj1->getUserPointer() : nullptr;
   contact._part_id0 = part_id0;
   contact._part_id0 = part_id0;
@@ -116,9 +118,7 @@ addSingleResult(btManifoldPoint &mp,
                 const btCollisionObject *obj0, int part_id0, int idx0,
                 const btCollisionObject *obj0, int part_id0, int idx0,
                 const btCollisionObject *obj1, int part_id1, int idx1) {
                 const btCollisionObject *obj1, int part_id1, int idx1) {
 
 
-  BulletContact contact;
-
-  contact._mp = BulletManifoldPoint(mp);
+  BulletContact contact(mp);
   contact._node0 = obj0 ? (PandaNode *)obj0->getUserPointer() : nullptr;
   contact._node0 = obj0 ? (PandaNode *)obj0->getUserPointer() : nullptr;
   contact._node1 = obj1 ? (PandaNode *)obj1->getUserPointer() : nullptr;
   contact._node1 = obj1 ? (PandaNode *)obj1->getUserPointer() : nullptr;
   contact._part_id0 = part_id0;
   contact._part_id0 = part_id0;

+ 2 - 1
panda/src/bullet/bulletContactResult.h

@@ -28,10 +28,11 @@ struct EXPCL_PANDABULLET BulletContact {
 
 
 public:
 public:
   BulletContact();
   BulletContact();
+  BulletContact(btManifoldPoint &mp);
   BulletContact(const BulletContact &other);
   BulletContact(const BulletContact &other);
 
 
 PUBLISHED:
 PUBLISHED:
-  INLINE BulletManifoldPoint &get_manifold_point();
+  INLINE BulletManifoldPoint get_manifold_point();
   INLINE PandaNode *get_node0() const;
   INLINE PandaNode *get_node0() const;
   INLINE PandaNode *get_node1() const;
   INLINE PandaNode *get_node1() const;
   INLINE int get_idx0() const;
   INLINE int get_idx0() const;

+ 0 - 8
panda/src/bullet/bulletManifoldPoint.I

@@ -10,11 +10,3 @@
  * @author enn0x
  * @author enn0x
  * @date 2010-03-07
  * @date 2010-03-07
  */
  */
-
-/**
- *
- */
-INLINE BulletManifoldPoint::
-~BulletManifoldPoint() {
-
-}

+ 0 - 19
panda/src/bullet/bulletManifoldPoint.cxx

@@ -24,25 +24,6 @@ BulletManifoldPoint(btManifoldPoint &pt)
 
 
 }
 }
 
 
-/**
- *
- */
-BulletManifoldPoint::
-BulletManifoldPoint(const BulletManifoldPoint &other)
- : _pt(other._pt) {
-
-}
-
-/**
- *
- */
-BulletManifoldPoint& BulletManifoldPoint::
-operator=(const BulletManifoldPoint& other) {
-
-  this->_pt = other._pt;
-  return *this;
-}
-
 /**
 /**
  *
  *
  */
  */

+ 3 - 3
panda/src/bullet/bulletManifoldPoint.h

@@ -27,7 +27,7 @@
 class EXPCL_PANDABULLET BulletManifoldPoint {
 class EXPCL_PANDABULLET BulletManifoldPoint {
 
 
 PUBLISHED:
 PUBLISHED:
-  INLINE ~BulletManifoldPoint();
+  ~BulletManifoldPoint() = default;
 
 
   int get_life_time() const;
   int get_life_time() const;
   PN_stdfloat get_distance() const;
   PN_stdfloat get_distance() const;
@@ -95,8 +95,8 @@ PUBLISHED:
 public:
 public:
   BulletManifoldPoint(btManifoldPoint &pt);
   BulletManifoldPoint(btManifoldPoint &pt);
 
 
-  BulletManifoldPoint(const BulletManifoldPoint &other);
-  BulletManifoldPoint& operator=(const BulletManifoldPoint& other);
+  BulletManifoldPoint(const BulletManifoldPoint &other) = default;
+  BulletManifoldPoint& operator=(const BulletManifoldPoint& other) = delete;
 
 
 private:
 private:
   btManifoldPoint &_pt;
   btManifoldPoint &_pt;

+ 0 - 14
panda/src/bullet/bulletWheel.I

@@ -26,17 +26,3 @@ INLINE BulletWheelRaycastInfo::
 ~BulletWheelRaycastInfo() {
 ~BulletWheelRaycastInfo() {
 
 
 }
 }
-
-/**
- * Named constructor intended to be used for asserts with have to return a
- * concrete value.
- */
-INLINE BulletWheel BulletWheel::
-empty() {
-
-  btWheelInfoConstructionInfo ci {};
-  btWheelInfo info(ci);
-
-  return BulletWheel(info);
-}
-

+ 13 - 0
panda/src/bullet/bulletWheel.cxx

@@ -23,6 +23,19 @@ BulletWheel(btWheelInfo &info) : _info(info) {
 
 
 }
 }
 
 
+/**
+ * Named constructor intended to be used for asserts with have to return a
+ * concrete value.
+ */
+BulletWheel BulletWheel::
+empty() {
+
+  static btWheelInfoConstructionInfo ci {};
+  static btWheelInfo info(ci);
+
+  return BulletWheel(info);
+}
+
 /**
 /**
  *
  *
  */
  */

+ 1 - 1
panda/src/bullet/bulletWheel.h

@@ -143,7 +143,7 @@ PUBLISHED:
 public:
 public:
   BulletWheel(btWheelInfo &info);
   BulletWheel(btWheelInfo &info);
 
 
-  INLINE static BulletWheel empty();
+  static BulletWheel empty();
 
 
 private:
 private:
   btWheelInfo &_info;
   btWheelInfo &_info;

+ 5 - 4
panda/src/bullet/bullet_utils.cxx

@@ -60,8 +60,9 @@ LPoint3 btVector3_to_LPoint3(const btVector3 &p) {
  */
  */
 btMatrix3x3 LMatrix3_to_btMatrix3x3(const LMatrix3 &m) {
 btMatrix3x3 LMatrix3_to_btMatrix3x3(const LMatrix3 &m) {
 
 
+  LMatrix4 m4(m);
   btMatrix3x3 result;
   btMatrix3x3 result;
-  result.setFromOpenGLSubMatrix((const btScalar *)m.get_data());
+  result.setFromOpenGLSubMatrix((const btScalar *)m4.get_data());
   return result;
   return result;
 }
 }
 
 
@@ -70,11 +71,11 @@ btMatrix3x3 LMatrix3_to_btMatrix3x3(const LMatrix3 &m) {
  */
  */
 LMatrix3 btMatrix3x3_to_LMatrix3(const btMatrix3x3 &m) {
 LMatrix3 btMatrix3x3_to_LMatrix3(const btMatrix3x3 &m) {
 
 
-  btScalar cells[9];
+  btScalar cells[12];
   m.getOpenGLSubMatrix(cells);
   m.getOpenGLSubMatrix(cells);
   return LMatrix3((PN_stdfloat)cells[0], (PN_stdfloat)cells[1], (PN_stdfloat)cells[2],
   return LMatrix3((PN_stdfloat)cells[0], (PN_stdfloat)cells[1], (PN_stdfloat)cells[2],
-                  (PN_stdfloat)cells[3], (PN_stdfloat)cells[4], (PN_stdfloat)cells[5],
-                  (PN_stdfloat)cells[6], (PN_stdfloat)cells[7], (PN_stdfloat)cells[8]);
+                  (PN_stdfloat)cells[4], (PN_stdfloat)cells[5], (PN_stdfloat)cells[6],
+                  (PN_stdfloat)cells[8], (PN_stdfloat)cells[9], (PN_stdfloat)cells[10]);
 }
 }
 
 
 /**
 /**

+ 14 - 9
panda/src/cocoadisplay/cocoaGraphicsWindow.mm

@@ -137,15 +137,17 @@ move_pointer(int device, int x, int y) {
   if (device == 0) {
   if (device == 0) {
     CGPoint point;
     CGPoint point;
     if (_properties.get_fullscreen()) {
     if (_properties.get_fullscreen()) {
-      point = CGPointMake(x, y + 1);
+      point = CGPointMake(x, y);
     } else {
     } else {
       point = CGPointMake(x + _properties.get_x_origin(),
       point = CGPointMake(x + _properties.get_x_origin(),
-                          y + _properties.get_y_origin() + 1);
+                          y + _properties.get_y_origin());
     }
     }
 
 
-    // I don't know what the difference between these two methods is.  if
-    // (CGWarpMouseCursorPosition(point) == kCGErrorSuccess) {
-    if (CGDisplayMoveCursorToPoint(_display, point) == kCGErrorSuccess) {
+    if (CGWarpMouseCursorPosition(point) == kCGErrorSuccess) {
+      //After moving (or warping) the mouse position, CG starts an event
+      // suppression interval during which no more mouse events can occur
+      // This interval can be interupted by the following call :
+      CGAssociateMouseAndMouseCursorPosition(YES);
       // Generate a mouse event.
       // Generate a mouse event.
       NSPoint pos = [_window mouseLocationOutsideOfEventStream];
       NSPoint pos = [_window mouseLocationOutsideOfEventStream];
       NSPoint loc = [_view convertPoint:pos fromView:nil];
       NSPoint loc = [_view convertPoint:pos fromView:nil];
@@ -1861,9 +1863,8 @@ handle_mouse_moved_event(bool in_window, double x, double y, bool absolute) {
       }
       }
     }
     }
 
 
-    // Strangely enough, in Cocoa, mouse Y coordinates are 1-based.
     nx = x;
     nx = x;
-    ny = y - 1;
+    ny = y;
 
 
   } else {
   } else {
     // We received deltas, so add it to the current mouse position.
     // We received deltas, so add it to the current mouse position.
@@ -1880,13 +1881,17 @@ handle_mouse_moved_event(bool in_window, double x, double y, bool absolute) {
     ny = std::max(0., std::min((double) get_y_size() - 1, ny));
     ny = std::max(0., std::min((double) get_y_size() - 1, ny));
 
 
     if (_properties.get_fullscreen()) {
     if (_properties.get_fullscreen()) {
-      point = CGPointMake(nx, ny + 1);
+      point = CGPointMake(nx, ny);
     } else {
     } else {
       point = CGPointMake(nx + _properties.get_x_origin(),
       point = CGPointMake(nx + _properties.get_x_origin(),
-                          ny + _properties.get_y_origin() + 1);
+                          ny + _properties.get_y_origin());
     }
     }
 
 
     if (CGWarpMouseCursorPosition(point) == kCGErrorSuccess) {
     if (CGWarpMouseCursorPosition(point) == kCGErrorSuccess) {
+      //After moving (or warping) the mouse position, CG starts an event
+      // suppression interval during which no more mouse events can occur
+      // This interval can be interupted by the following call :
+      CGAssociateMouseAndMouseCursorPosition(YES);
       in_window = true;
       in_window = true;
     } else {
     } else {
       cocoadisplay_cat.warning() << "Failed to return mouse pointer to window\n";
       cocoadisplay_cat.warning() << "Failed to return mouse pointer to window\n";

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