Sfoglia il codice sorgente

Merge branch 'master' into input-overhaul

rdb 9 anni fa
parent
commit
d0e9f136c0
100 ha cambiato i file con 1961 aggiunte e 1069 eliminazioni
  1. 52 4
      .gitignore
  2. 1 1
      .travis.yml
  3. 0 9
      contrib/.gitignore
  4. 0 4
      contrib/src/ai/aiBehaviors.h
  5. 0 5
      contrib/src/ai/aiCharacter.h
  6. 0 4
      contrib/src/ai/aiGlobals.h
  7. 0 5
      contrib/src/ai/aiWorld.h
  8. 3 3
      contrib/src/ai/obstacleAvoidance.cxx
  9. 0 2
      contrib/src/panda3dtoolsgui/.gitignore
  10. 0 9
      direct/.gitignore
  11. 0 1
      direct/src/configfiles/.gitignore
  12. 1 1
      direct/src/controls/BattleWalker.py
  13. 1 1
      direct/src/controls/NonPhysicsWalker.py
  14. 0 3
      direct/src/dcparser/.gitignore
  15. 1 1
      direct/src/dcparser/dcArrayParameter.h
  16. 1 1
      direct/src/dcparser/dcAtomicField.h
  17. 1 1
      direct/src/dcparser/dcClass.h
  18. 1 1
      direct/src/dcparser/dcClassParameter.h
  19. 1 1
      direct/src/dcparser/dcDeclaration.h
  20. 1 1
      direct/src/dcparser/dcField.h
  21. 1 1
      direct/src/dcparser/dcFile.h
  22. 1 1
      direct/src/dcparser/dcKeyword.h
  23. 1 1
      direct/src/dcparser/dcKeywordList.h
  24. 1 1
      direct/src/dcparser/dcMolecularField.h
  25. 1 1
      direct/src/dcparser/dcPackData.h
  26. 2 2
      direct/src/dcparser/dcPacker.h
  27. 1 1
      direct/src/dcparser/dcPackerCatalog.h
  28. 1 1
      direct/src/dcparser/dcPackerInterface.h
  29. 1 1
      direct/src/dcparser/dcParameter.h
  30. 1 1
      direct/src/dcparser/dcSimpleParameter.h
  31. 1 1
      direct/src/dcparser/dcSwitch.h
  32. 1 1
      direct/src/dcparser/dcSwitchParameter.h
  33. 1 1
      direct/src/dcparser/dcTypedef.h
  34. 1 1
      direct/src/distributed/CartesianGridBase.py
  35. 2 1
      direct/src/distributed/ClientRepositoryBase.py
  36. 2 1
      direct/src/distributed/ConnectionRepository.py
  37. 2 1
      direct/src/distributed/DistributedCamera.py
  38. 2 1
      direct/src/distributed/DistributedCameraOV.py
  39. 2 1
      direct/src/distributed/DistributedCartesianGrid.py
  40. 2 1
      direct/src/distributed/DistributedCartesianGridAI.py
  41. 1 1
      direct/src/distributed/DistributedNodeAI.py
  42. 3 7
      direct/src/distributed/DistributedObjectGlobalUD.py
  43. 2 1
      direct/src/distributed/DistributedObjectUD.py
  44. 2 1
      direct/src/distributed/DistributedSmoothNode.py
  45. 2 1
      direct/src/distributed/DoInterestManager.py
  46. 2 1
      direct/src/distributed/GridParent.py
  47. 2 1
      direct/src/distributed/ServerRepository.py
  48. 1 1
      direct/src/distributed/TimeManager.py
  49. 1 1
      direct/src/distributed/TimeManagerAI.py
  50. 22 2
      direct/src/distributed/cConnectionRepository.cxx
  51. 0 1
      direct/src/extensions_native/.gitignore
  52. 10 10
      direct/src/fsm/FSM.py
  53. 0 2
      direct/src/gui/.gitignore
  54. 3 3
      direct/src/gui/DirectScrolledList.py
  55. 0 8
      direct/src/p3d/.gitignore
  56. 4 4
      direct/src/p3d/FileSpec.py
  57. 11 1
      direct/src/p3d/Packager.py
  58. 7 0
      direct/src/p3d/panda3d.pdef
  59. 0 1
      direct/src/plugin/.gitignore
  60. 0 2
      direct/src/plugin/p3dCInstance.h
  61. 11 0
      direct/src/plugin/p3dInstanceManager.cxx
  62. 0 1
      direct/src/plugin_activex/.gitignore
  63. 0 1
      direct/src/plugin_npapi/.gitignore
  64. 0 2
      direct/src/plugin_standalone/.gitignore
  65. 12 3
      direct/src/showbase/BufferViewer.py
  66. 1 0
      direct/src/showbase/ExceptionVarDump.py
  67. 1 1
      direct/src/showbase/LeakDetectors.py
  68. 108 42
      direct/src/showbase/Loader.py
  69. 1 1
      direct/src/showbase/MirrorDemo.py
  70. 1 1
      direct/src/showbase/ShadowDemo.py
  71. 1 1
      direct/src/showbase/ShadowPlacer.py
  72. 0 4
      direct/src/showbase/ShowBase.py
  73. 0 1
      direct/src/showutil/.gitignore
  74. 4 1
      direct/src/showutil/FreezeTool.py
  75. 10 10
      direct/src/stdpy/thread.py
  76. 4 1
      direct/src/task/Task.py
  77. 0 7
      dmodels/.gitignore
  78. 0 6
      dmodels/src/.gitignore
  79. 32 0
      doc/ReleaseNotes
  80. 0 7
      dtool/.gitignore
  81. 0 2
      dtool/src/cppparser/.gitignore
  82. 10 1
      dtool/src/cppparser/cppArrayType.cxx
  83. 1 0
      dtool/src/cppparser/cppArrayType.h
  84. 555 491
      dtool/src/cppparser/cppBison.cxx.prebuilt
  85. 264 228
      dtool/src/cppparser/cppBison.h.prebuilt
  86. 370 106
      dtool/src/cppparser/cppBison.yxx
  87. 26 3
      dtool/src/cppparser/cppClassTemplateParameter.cxx
  88. 1 0
      dtool/src/cppparser/cppClassTemplateParameter.h
  89. 42 1
      dtool/src/cppparser/cppConstType.cxx
  90. 5 0
      dtool/src/cppparser/cppConstType.h
  91. 8 2
      dtool/src/cppparser/cppDeclaration.cxx
  92. 70 1
      dtool/src/cppparser/cppDeclaration.h
  93. 1 0
      dtool/src/cppparser/cppEnumType.h
  94. 212 7
      dtool/src/cppparser/cppExpression.cxx
  95. 9 2
      dtool/src/cppparser/cppExpression.h
  96. 23 3
      dtool/src/cppparser/cppExtensionType.cxx
  97. 2 0
      dtool/src/cppparser/cppExtensionType.h
  98. 1 1
      dtool/src/cppparser/cppFile.h
  99. 8 3
      dtool/src/cppparser/cppFunctionType.cxx
  100. 3 0
      dtool/src/cppparser/cppFunctionType.h

+ 52 - 4
.gitignore

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

+ 1 - 1
.travis.yml

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

+ 0 - 9
contrib/.gitignore

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 0 - 9
direct/.gitignore

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 3 - 7
direct/src/distributed/DistributedObjectGlobalUD.py

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 7 - 0
direct/src/p3d/panda3d.pdef

@@ -56,6 +56,9 @@ class panda3d(package):
            'direct.stdpy.*',
            'direct.task.*')
 
+    # Keep these modules for backward compatibility.
+    module('pandac.PandaModules', 'pandac.extension_native_helpers')
+
     module('panda3d.core',
            'panda3d.direct',
            'panda3d.fx',
@@ -462,6 +465,8 @@ class packp3d(p3d):
 
     mainModule('direct.p3d.packp3d')
 
+    file('packp3d.prc', extract = True, text = "preload-textures false")
+
 
 class ppackage(p3d):
     # As above, a packaging utility.  This is the fully-general ppackage
@@ -475,6 +480,8 @@ class ppackage(p3d):
 
     mainModule('direct.p3d.ppackage')
 
+    file('ppackage.prc', extract = True, text = "preload-textures false")
+
 
 class ppatcher(p3d):
     # A handy utility to go along with ppackage.  This builds

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@@ -23,7 +23,7 @@ surface are possible, like a funhouse mirror.  However, the reflection
 itself is always basically planar; for more accurate convex
 reflections, you will need to use a sphere map or a cube map."""
 
-from pandac.PandaModules import *
+from panda3d.core import *
 from direct.task import Task
 
 def setupMirror(name, width, height, rootCamera = None):

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

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

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

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

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

@@ -127,10 +127,6 @@ class ShowBase(DirectObject.DirectObject):
         ## just before Python is about to shut down.
         self.finalExitCallbacks = []
 
-        Task.TaskManager.taskTimerVerbose = self.config.GetBool('task-timer-verbose', 0)
-        Task.TaskManager.extendedExceptions = self.config.GetBool('extended-exceptions', 0)
-        Task.TaskManager.pStatsTasks = self.config.GetBool('pstats-tasks', 0)
-
         # Set up the TaskManager to reset the PStats clock back
         # whenever we resume from a pause.  This callback function is
         # a little hacky, but we can't call it directly from within

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

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

+ 4 - 1
direct/src/showutil/FreezeTool.py

@@ -984,7 +984,10 @@ class Freezer:
             try:
                 self.__loadModule(mdef)
             except ImportError as ex:
-                print("Unknown module: %s (%s)" % (mdef.moduleName, str(ex)))
+                message = "Unknown module: %s" % (mdef.moduleName)
+                if str(ex) != "No module named " + str(mdef.moduleName):
+                    message += " (%s)" % (ex)
+                print(message)
 
         # Also attempt to import any implicit modules.  If any of
         # these fail to import, we don't really care.

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

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

+ 4 - 1
direct/src/task/Task.py

@@ -102,7 +102,10 @@ Task.DtoolClassDict['loop'] = staticmethod(loop)
 class TaskManager:
     notify = directNotify.newCategory("TaskManager")
 
-    extendedExceptions = False
+    taskTimerVerbose = ConfigVariableBool('task-timer-verbose', False)
+    extendedExceptions = ConfigVariableBool('extended-exceptions', False)
+    pStatsTasks = ConfigVariableBool('pstats-tasks', False)
+
     MaxEpochSpeed = 1.0/30.0
 
     def __init__(self):

+ 0 - 7
dmodels/.gitignore

@@ -1,7 +0,0 @@
-*.egg
-*.pt
-/built/
-Makefile
-bams/
-optchar/
-pal_egg/

+ 0 - 6
dmodels/src/.gitignore

@@ -1,6 +0,0 @@
-/*.buildings
-/game_options.txt
-/prefixstrip
-/retarget/
-/textures.boo
-/topstrip/

+ 32 - 0
doc/ReleaseNotes

@@ -6,15 +6,47 @@ This issue fixes several bugs that were still found in 1.9.2.
 * Fix crash using wx/tkinter on Mac as long as want-wx/tk is set
 * Fix loading models from 'models' package with models/ prefix
 * Fix random crashes in task system
+* Fix various race conditions causing threading issues
 * Fix memory leaks in BulletTriangleMesh
 * Fix loading old models with MovingPart<LMatrix4f>
 * Improve performance of CPU vertex animation somewhat
 * Show framebuffer properties when fbprop request fails
+* Show error instead of crash on use of object before __init__
 * Fix hang on exit when using Python task on threaded task chain
 * Fix inability to get RGBA renderbuffer in certain cases
 * Work around GLSL issue with #pragma and certain Intel drivers
 * Improve performance of texture load and store operations
 * Fix crashes with pbuffers on Intel cards on Windows
+* Support for Autodesk Maya 2016.5
+* Add shadow-depth-bits config var to control shadow map depth
+* Fix cull issue when rendering cube map (or any multi-lens setup)
+* Fix crash rendering with the same camera to different contexts
+* Fix compile error when making static build with DX9 renderer
+* Fix assertion when using aux render targets in DX9
+* Work around Cg bug generating invalid ASM for saturated tex loads
+* Fix issues with certain Cg shader inputs in DX9
+* Support uint8 index buffers in DX9
+* Fix occasional frame lag when loading a big model asynchronously
+* Fix interrogate parsing issue with "const static"
+* Add back missing libp3pystub.a to Mac OS X SDK
+* Fix RAM caching of 2D texture arrays
+* Fix Ctrl+C interrupt propagation to runtime applications
+* Support for InvSphere, Box and Tube solids in bam2egg
+* Preserve "intangible" and "level" collide flags in bam2egg
+* Add normalized() method to vectors
+* asyncFlattenStrong with inPlace=True caused node to disappear
+* Fix asyncFlattenStrong called on nodes without parent
+* Fix is_playing() check when playing an animation backwards
+* Windows installer no longer clears %PATH% if longer than 1024 chars
+* Fix inoperative -tbn/-tbnall/-tbnauto options in egg-optchar
+* Fix tinydisplay texture errors on shutdown
+* Fix mipmap filtering issues in tinydisplay renderer
+* Fix exception when creating intervals before ShowBase is started
+* Fix rare X11 .ico cursor bug; also now supports PNG-compressed icons
+* Add keyword argument support to make() methods such as Shader.make()
+* Fix compilation errors with Bullet 2.84
+* Fix exception when trying to pickle NodePathCollection objects
+* Fix error when trying to raise vectors to a power
 
 ------------------------  RELEASE 1.9.2  ------------------------
 

+ 0 - 7
dtool/.gitignore

@@ -1,7 +0,0 @@
-/dtool_config.h
-# These are files that are generated within the source tree by the
-# ppremake system.
-Makefile
-pp.dep
-/built/
-Opt?-*

+ 0 - 2
dtool/src/cppparser/.gitignore

@@ -1,2 +0,0 @@
-/cppBison.cxx
-/cppBison.h

+ 10 - 1
dtool/src/cppparser/cppArrayType.cxx

@@ -13,6 +13,7 @@
 
 #include "cppArrayType.h"
 #include "cppExpression.h"
+#include "cppPointerType.h"
 
 /**
  *
@@ -63,6 +64,14 @@ is_tbd() const {
   return _element_type->is_tbd();
 }
 
+/**
+ * Returns true if the type is considered a standard layout type.
+ */
+bool CPPArrayType::
+is_standard_layout() const {
+  return _element_type->is_standard_layout();
+}
+
 /**
  * Returns true if the type is considered a Plain Old Data (POD) type.
  */
@@ -76,7 +85,7 @@ is_trivial() const {
  */
 bool CPPArrayType::
 is_default_constructible() const {
-  return _element_type->is_default_constructible();
+  return _bounds != NULL && _element_type->is_default_constructible();
 }
 
 /**

+ 1 - 0
dtool/src/cppparser/cppArrayType.h

@@ -38,6 +38,7 @@ public:
   virtual CPPType *resolve_type(CPPScope *current_scope,
                                 CPPScope *global_scope);
   virtual bool is_tbd() const;
+  virtual bool is_standard_layout() const;
   virtual bool is_trivial() const;
   virtual bool is_default_constructible() const;
   virtual bool is_copy_constructible() const;

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


+ 264 - 228
dtool/src/cppparser/cppBison.h.prebuilt

@@ -54,120 +54,138 @@ extern int cppyydebug;
     CUSTOM_LITERAL = 264,
     IDENTIFIER = 265,
     TYPENAME_IDENTIFIER = 266,
-    SCOPING = 267,
-    TYPEDEFNAME = 268,
-    ELLIPSIS = 269,
-    OROR = 270,
-    ANDAND = 271,
-    EQCOMPARE = 272,
-    NECOMPARE = 273,
-    LECOMPARE = 274,
-    GECOMPARE = 275,
-    LSHIFT = 276,
-    RSHIFT = 277,
-    POINTSAT_STAR = 278,
-    DOT_STAR = 279,
-    UNARY = 280,
-    UNARY_NOT = 281,
-    UNARY_NEGATE = 282,
-    UNARY_MINUS = 283,
-    UNARY_PLUS = 284,
-    UNARY_STAR = 285,
-    UNARY_REF = 286,
-    POINTSAT = 287,
-    SCOPE = 288,
-    PLUSPLUS = 289,
-    MINUSMINUS = 290,
-    TIMESEQUAL = 291,
-    DIVIDEEQUAL = 292,
-    MODEQUAL = 293,
-    PLUSEQUAL = 294,
-    MINUSEQUAL = 295,
-    OREQUAL = 296,
-    ANDEQUAL = 297,
-    XOREQUAL = 298,
-    LSHIFTEQUAL = 299,
-    RSHIFTEQUAL = 300,
-    KW_ALIGNAS = 301,
-    KW_ALIGNOF = 302,
-    KW_AUTO = 303,
-    KW_BEGIN_PUBLISH = 304,
-    KW_BLOCKING = 305,
-    KW_BOOL = 306,
-    KW_CATCH = 307,
-    KW_CHAR = 308,
-    KW_CHAR16_T = 309,
-    KW_CHAR32_T = 310,
-    KW_CLASS = 311,
-    KW_CONST = 312,
-    KW_CONSTEXPR = 313,
-    KW_CONST_CAST = 314,
-    KW_DECLTYPE = 315,
-    KW_DEFAULT = 316,
-    KW_DELETE = 317,
-    KW_DOUBLE = 318,
-    KW_DYNAMIC_CAST = 319,
-    KW_ELSE = 320,
-    KW_END_PUBLISH = 321,
-    KW_ENUM = 322,
-    KW_EXTENSION = 323,
-    KW_EXTERN = 324,
-    KW_EXPLICIT = 325,
-    KW_PUBLISHED = 326,
-    KW_FALSE = 327,
-    KW_FINAL = 328,
-    KW_FLOAT = 329,
-    KW_FRIEND = 330,
-    KW_FOR = 331,
-    KW_GOTO = 332,
-    KW_IF = 333,
-    KW_INLINE = 334,
-    KW_INT = 335,
-    KW_LONG = 336,
-    KW_MAKE_MAP_PROPERTY = 337,
-    KW_MAKE_PROPERTY = 338,
-    KW_MAKE_PROPERTY2 = 339,
-    KW_MAKE_SEQ = 340,
-    KW_MAKE_SEQ_PROPERTY = 341,
-    KW_MUTABLE = 342,
-    KW_NAMESPACE = 343,
-    KW_NEW = 344,
-    KW_NOEXCEPT = 345,
-    KW_NULLPTR = 346,
-    KW_OPERATOR = 347,
-    KW_OVERRIDE = 348,
-    KW_PRIVATE = 349,
-    KW_PROTECTED = 350,
-    KW_PUBLIC = 351,
-    KW_REGISTER = 352,
-    KW_REINTERPRET_CAST = 353,
-    KW_RETURN = 354,
-    KW_SHORT = 355,
-    KW_SIGNED = 356,
-    KW_SIZEOF = 357,
-    KW_STATIC = 358,
-    KW_STATIC_ASSERT = 359,
-    KW_STATIC_CAST = 360,
-    KW_STRUCT = 361,
-    KW_TEMPLATE = 362,
-    KW_THREAD_LOCAL = 363,
-    KW_THROW = 364,
-    KW_TRUE = 365,
-    KW_TRY = 366,
-    KW_TYPEDEF = 367,
-    KW_TYPEID = 368,
-    KW_TYPENAME = 369,
-    KW_UNION = 370,
-    KW_UNSIGNED = 371,
-    KW_USING = 372,
-    KW_VIRTUAL = 373,
-    KW_VOID = 374,
-    KW_VOLATILE = 375,
-    KW_WCHAR_T = 376,
-    KW_WHILE = 377,
-    START_CPP = 378,
-    START_CONST_EXPR = 379,
-    START_TYPE = 380
+    TYPEPACK_IDENTIFIER = 267,
+    SCOPING = 268,
+    TYPEDEFNAME = 269,
+    ELLIPSIS = 270,
+    OROR = 271,
+    ANDAND = 272,
+    EQCOMPARE = 273,
+    NECOMPARE = 274,
+    LECOMPARE = 275,
+    GECOMPARE = 276,
+    LSHIFT = 277,
+    RSHIFT = 278,
+    POINTSAT_STAR = 279,
+    DOT_STAR = 280,
+    UNARY = 281,
+    UNARY_NOT = 282,
+    UNARY_NEGATE = 283,
+    UNARY_MINUS = 284,
+    UNARY_PLUS = 285,
+    UNARY_STAR = 286,
+    UNARY_REF = 287,
+    POINTSAT = 288,
+    SCOPE = 289,
+    PLUSPLUS = 290,
+    MINUSMINUS = 291,
+    TIMESEQUAL = 292,
+    DIVIDEEQUAL = 293,
+    MODEQUAL = 294,
+    PLUSEQUAL = 295,
+    MINUSEQUAL = 296,
+    OREQUAL = 297,
+    ANDEQUAL = 298,
+    XOREQUAL = 299,
+    LSHIFTEQUAL = 300,
+    RSHIFTEQUAL = 301,
+    KW_ALIGNAS = 302,
+    KW_ALIGNOF = 303,
+    KW_AUTO = 304,
+    KW_BEGIN_PUBLISH = 305,
+    KW_BLOCKING = 306,
+    KW_BOOL = 307,
+    KW_CATCH = 308,
+    KW_CHAR = 309,
+    KW_CHAR16_T = 310,
+    KW_CHAR32_T = 311,
+    KW_CLASS = 312,
+    KW_CONST = 313,
+    KW_CONSTEXPR = 314,
+    KW_CONST_CAST = 315,
+    KW_DECLTYPE = 316,
+    KW_DEFAULT = 317,
+    KW_DELETE = 318,
+    KW_DOUBLE = 319,
+    KW_DYNAMIC_CAST = 320,
+    KW_ELSE = 321,
+    KW_END_PUBLISH = 322,
+    KW_ENUM = 323,
+    KW_EXTENSION = 324,
+    KW_EXTERN = 325,
+    KW_EXPLICIT = 326,
+    KW_PUBLISHED = 327,
+    KW_FALSE = 328,
+    KW_FINAL = 329,
+    KW_FLOAT = 330,
+    KW_FRIEND = 331,
+    KW_FOR = 332,
+    KW_GOTO = 333,
+    KW_HAS_VIRTUAL_DESTRUCTOR = 334,
+    KW_IF = 335,
+    KW_INLINE = 336,
+    KW_INT = 337,
+    KW_IS_ABSTRACT = 338,
+    KW_IS_BASE_OF = 339,
+    KW_IS_CLASS = 340,
+    KW_IS_CONSTRUCTIBLE = 341,
+    KW_IS_CONVERTIBLE_TO = 342,
+    KW_IS_DESTRUCTIBLE = 343,
+    KW_IS_EMPTY = 344,
+    KW_IS_ENUM = 345,
+    KW_IS_FINAL = 346,
+    KW_IS_FUNDAMENTAL = 347,
+    KW_IS_POD = 348,
+    KW_IS_POLYMORPHIC = 349,
+    KW_IS_STANDARD_LAYOUT = 350,
+    KW_IS_TRIVIAL = 351,
+    KW_IS_UNION = 352,
+    KW_LONG = 353,
+    KW_MAKE_MAP_PROPERTY = 354,
+    KW_MAKE_PROPERTY = 355,
+    KW_MAKE_PROPERTY2 = 356,
+    KW_MAKE_SEQ = 357,
+    KW_MAKE_SEQ_PROPERTY = 358,
+    KW_MUTABLE = 359,
+    KW_NAMESPACE = 360,
+    KW_NEW = 361,
+    KW_NOEXCEPT = 362,
+    KW_NULLPTR = 363,
+    KW_OPERATOR = 364,
+    KW_OVERRIDE = 365,
+    KW_PRIVATE = 366,
+    KW_PROTECTED = 367,
+    KW_PUBLIC = 368,
+    KW_REGISTER = 369,
+    KW_REINTERPRET_CAST = 370,
+    KW_RETURN = 371,
+    KW_SHORT = 372,
+    KW_SIGNED = 373,
+    KW_SIZEOF = 374,
+    KW_STATIC = 375,
+    KW_STATIC_ASSERT = 376,
+    KW_STATIC_CAST = 377,
+    KW_STRUCT = 378,
+    KW_TEMPLATE = 379,
+    KW_THREAD_LOCAL = 380,
+    KW_THROW = 381,
+    KW_TRUE = 382,
+    KW_TRY = 383,
+    KW_TYPEDEF = 384,
+    KW_TYPEID = 385,
+    KW_TYPENAME = 386,
+    KW_UNDERLYING_TYPE = 387,
+    KW_UNION = 388,
+    KW_UNSIGNED = 389,
+    KW_USING = 390,
+    KW_VIRTUAL = 391,
+    KW_VOID = 392,
+    KW_VOLATILE = 393,
+    KW_WCHAR_T = 394,
+    KW_WHILE = 395,
+    START_CPP = 396,
+    START_CONST_EXPR = 397,
+    START_TYPE = 398
   };
 #endif
 /* Tokens.  */
@@ -180,120 +198,138 @@ extern int cppyydebug;
 #define CUSTOM_LITERAL 264
 #define IDENTIFIER 265
 #define TYPENAME_IDENTIFIER 266
-#define SCOPING 267
-#define TYPEDEFNAME 268
-#define ELLIPSIS 269
-#define OROR 270
-#define ANDAND 271
-#define EQCOMPARE 272
-#define NECOMPARE 273
-#define LECOMPARE 274
-#define GECOMPARE 275
-#define LSHIFT 276
-#define RSHIFT 277
-#define POINTSAT_STAR 278
-#define DOT_STAR 279
-#define UNARY 280
-#define UNARY_NOT 281
-#define UNARY_NEGATE 282
-#define UNARY_MINUS 283
-#define UNARY_PLUS 284
-#define UNARY_STAR 285
-#define UNARY_REF 286
-#define POINTSAT 287
-#define SCOPE 288
-#define PLUSPLUS 289
-#define MINUSMINUS 290
-#define TIMESEQUAL 291
-#define DIVIDEEQUAL 292
-#define MODEQUAL 293
-#define PLUSEQUAL 294
-#define MINUSEQUAL 295
-#define OREQUAL 296
-#define ANDEQUAL 297
-#define XOREQUAL 298
-#define LSHIFTEQUAL 299
-#define RSHIFTEQUAL 300
-#define KW_ALIGNAS 301
-#define KW_ALIGNOF 302
-#define KW_AUTO 303
-#define KW_BEGIN_PUBLISH 304
-#define KW_BLOCKING 305
-#define KW_BOOL 306
-#define KW_CATCH 307
-#define KW_CHAR 308
-#define KW_CHAR16_T 309
-#define KW_CHAR32_T 310
-#define KW_CLASS 311
-#define KW_CONST 312
-#define KW_CONSTEXPR 313
-#define KW_CONST_CAST 314
-#define KW_DECLTYPE 315
-#define KW_DEFAULT 316
-#define KW_DELETE 317
-#define KW_DOUBLE 318
-#define KW_DYNAMIC_CAST 319
-#define KW_ELSE 320
-#define KW_END_PUBLISH 321
-#define KW_ENUM 322
-#define KW_EXTENSION 323
-#define KW_EXTERN 324
-#define KW_EXPLICIT 325
-#define KW_PUBLISHED 326
-#define KW_FALSE 327
-#define KW_FINAL 328
-#define KW_FLOAT 329
-#define KW_FRIEND 330
-#define KW_FOR 331
-#define KW_GOTO 332
-#define KW_IF 333
-#define KW_INLINE 334
-#define KW_INT 335
-#define KW_LONG 336
-#define KW_MAKE_MAP_PROPERTY 337
-#define KW_MAKE_PROPERTY 338
-#define KW_MAKE_PROPERTY2 339
-#define KW_MAKE_SEQ 340
-#define KW_MAKE_SEQ_PROPERTY 341
-#define KW_MUTABLE 342
-#define KW_NAMESPACE 343
-#define KW_NEW 344
-#define KW_NOEXCEPT 345
-#define KW_NULLPTR 346
-#define KW_OPERATOR 347
-#define KW_OVERRIDE 348
-#define KW_PRIVATE 349
-#define KW_PROTECTED 350
-#define KW_PUBLIC 351
-#define KW_REGISTER 352
-#define KW_REINTERPRET_CAST 353
-#define KW_RETURN 354
-#define KW_SHORT 355
-#define KW_SIGNED 356
-#define KW_SIZEOF 357
-#define KW_STATIC 358
-#define KW_STATIC_ASSERT 359
-#define KW_STATIC_CAST 360
-#define KW_STRUCT 361
-#define KW_TEMPLATE 362
-#define KW_THREAD_LOCAL 363
-#define KW_THROW 364
-#define KW_TRUE 365
-#define KW_TRY 366
-#define KW_TYPEDEF 367
-#define KW_TYPEID 368
-#define KW_TYPENAME 369
-#define KW_UNION 370
-#define KW_UNSIGNED 371
-#define KW_USING 372
-#define KW_VIRTUAL 373
-#define KW_VOID 374
-#define KW_VOLATILE 375
-#define KW_WCHAR_T 376
-#define KW_WHILE 377
-#define START_CPP 378
-#define START_CONST_EXPR 379
-#define START_TYPE 380
+#define TYPEPACK_IDENTIFIER 267
+#define SCOPING 268
+#define TYPEDEFNAME 269
+#define ELLIPSIS 270
+#define OROR 271
+#define ANDAND 272
+#define EQCOMPARE 273
+#define NECOMPARE 274
+#define LECOMPARE 275
+#define GECOMPARE 276
+#define LSHIFT 277
+#define RSHIFT 278
+#define POINTSAT_STAR 279
+#define DOT_STAR 280
+#define UNARY 281
+#define UNARY_NOT 282
+#define UNARY_NEGATE 283
+#define UNARY_MINUS 284
+#define UNARY_PLUS 285
+#define UNARY_STAR 286
+#define UNARY_REF 287
+#define POINTSAT 288
+#define SCOPE 289
+#define PLUSPLUS 290
+#define MINUSMINUS 291
+#define TIMESEQUAL 292
+#define DIVIDEEQUAL 293
+#define MODEQUAL 294
+#define PLUSEQUAL 295
+#define MINUSEQUAL 296
+#define OREQUAL 297
+#define ANDEQUAL 298
+#define XOREQUAL 299
+#define LSHIFTEQUAL 300
+#define RSHIFTEQUAL 301
+#define KW_ALIGNAS 302
+#define KW_ALIGNOF 303
+#define KW_AUTO 304
+#define KW_BEGIN_PUBLISH 305
+#define KW_BLOCKING 306
+#define KW_BOOL 307
+#define KW_CATCH 308
+#define KW_CHAR 309
+#define KW_CHAR16_T 310
+#define KW_CHAR32_T 311
+#define KW_CLASS 312
+#define KW_CONST 313
+#define KW_CONSTEXPR 314
+#define KW_CONST_CAST 315
+#define KW_DECLTYPE 316
+#define KW_DEFAULT 317
+#define KW_DELETE 318
+#define KW_DOUBLE 319
+#define KW_DYNAMIC_CAST 320
+#define KW_ELSE 321
+#define KW_END_PUBLISH 322
+#define KW_ENUM 323
+#define KW_EXTENSION 324
+#define KW_EXTERN 325
+#define KW_EXPLICIT 326
+#define KW_PUBLISHED 327
+#define KW_FALSE 328
+#define KW_FINAL 329
+#define KW_FLOAT 330
+#define KW_FRIEND 331
+#define KW_FOR 332
+#define KW_GOTO 333
+#define KW_HAS_VIRTUAL_DESTRUCTOR 334
+#define KW_IF 335
+#define KW_INLINE 336
+#define KW_INT 337
+#define KW_IS_ABSTRACT 338
+#define KW_IS_BASE_OF 339
+#define KW_IS_CLASS 340
+#define KW_IS_CONSTRUCTIBLE 341
+#define KW_IS_CONVERTIBLE_TO 342
+#define KW_IS_DESTRUCTIBLE 343
+#define KW_IS_EMPTY 344
+#define KW_IS_ENUM 345
+#define KW_IS_FINAL 346
+#define KW_IS_FUNDAMENTAL 347
+#define KW_IS_POD 348
+#define KW_IS_POLYMORPHIC 349
+#define KW_IS_STANDARD_LAYOUT 350
+#define KW_IS_TRIVIAL 351
+#define KW_IS_UNION 352
+#define KW_LONG 353
+#define KW_MAKE_MAP_PROPERTY 354
+#define KW_MAKE_PROPERTY 355
+#define KW_MAKE_PROPERTY2 356
+#define KW_MAKE_SEQ 357
+#define KW_MAKE_SEQ_PROPERTY 358
+#define KW_MUTABLE 359
+#define KW_NAMESPACE 360
+#define KW_NEW 361
+#define KW_NOEXCEPT 362
+#define KW_NULLPTR 363
+#define KW_OPERATOR 364
+#define KW_OVERRIDE 365
+#define KW_PRIVATE 366
+#define KW_PROTECTED 367
+#define KW_PUBLIC 368
+#define KW_REGISTER 369
+#define KW_REINTERPRET_CAST 370
+#define KW_RETURN 371
+#define KW_SHORT 372
+#define KW_SIGNED 373
+#define KW_SIZEOF 374
+#define KW_STATIC 375
+#define KW_STATIC_ASSERT 376
+#define KW_STATIC_CAST 377
+#define KW_STRUCT 378
+#define KW_TEMPLATE 379
+#define KW_THREAD_LOCAL 380
+#define KW_THROW 381
+#define KW_TRUE 382
+#define KW_TRY 383
+#define KW_TYPEDEF 384
+#define KW_TYPEID 385
+#define KW_TYPENAME 386
+#define KW_UNDERLYING_TYPE 387
+#define KW_UNION 388
+#define KW_UNSIGNED 389
+#define KW_USING 390
+#define KW_VIRTUAL 391
+#define KW_VOID 392
+#define KW_VOLATILE 393
+#define KW_WCHAR_T 394
+#define KW_WHILE 395
+#define START_CPP 396
+#define START_CONST_EXPR 397
+#define START_TYPE 398
 
 /* Value type.  */
 

+ 370 - 106
dtool/src/cppparser/cppBison.yxx

@@ -212,7 +212,7 @@ pop_struct() {
 %token <u.integer> CHAR_TOK
 %token <str> SIMPLE_STRING SIMPLE_IDENTIFIER
 %token <u.expr> STRING_LITERAL CUSTOM_LITERAL
-%token <u.identifier> IDENTIFIER TYPENAME_IDENTIFIER SCOPING
+%token <u.identifier> IDENTIFIER TYPENAME_IDENTIFIER TYPEPACK_IDENTIFIER SCOPING
 %token <u.type> TYPEDEFNAME
 
 %token ELLIPSIS
@@ -280,9 +280,25 @@ pop_struct() {
 %token KW_FRIEND
 %token KW_FOR
 %token KW_GOTO
+%token KW_HAS_VIRTUAL_DESTRUCTOR
 %token KW_IF
 %token KW_INLINE
 %token KW_INT
+%token KW_IS_ABSTRACT
+%token KW_IS_BASE_OF
+%token KW_IS_CLASS
+%token KW_IS_CONSTRUCTIBLE
+%token KW_IS_CONVERTIBLE_TO
+%token KW_IS_DESTRUCTIBLE
+%token KW_IS_EMPTY
+%token KW_IS_ENUM
+%token KW_IS_FINAL
+%token KW_IS_FUNDAMENTAL
+%token KW_IS_POD
+%token KW_IS_POLYMORPHIC
+%token KW_IS_STANDARD_LAYOUT
+%token KW_IS_TRIVIAL
+%token KW_IS_UNION
 %token KW_LONG
 %token KW_MAKE_MAP_PROPERTY
 %token KW_MAKE_PROPERTY
@@ -317,6 +333,7 @@ pop_struct() {
 %token KW_TYPEDEF
 %token KW_TYPEID
 %token KW_TYPENAME
+%token KW_UNDERLYING_TYPE
 %token KW_UNION
 %token KW_UNSIGNED
 %token KW_USING
@@ -354,9 +371,10 @@ pop_struct() {
 %type <u.instance> formal_parameter
 %type <u.inst_ident> not_paren_formal_parameter_identifier
 %type <u.inst_ident> formal_parameter_identifier
+%type <u.inst_ident> parameter_pack_identifier
 %type <u.inst_ident> not_paren_empty_instance_identifier
 %type <u.inst_ident> empty_instance_identifier
-%type <u.type> type
+%type <u.type> type type_pack
 %type <u.decl> type_decl
 %type <u.decl> var_type_decl
 %type <u.type> predefined_type
@@ -447,6 +465,10 @@ constructor_init:
         name '(' optional_const_expr_comma ')'
 {
   delete $3;
+}
+        | name '(' optional_const_expr_comma ')' ELLIPSIS
+{
+  delete $3;
 }
         | name '{' optional_const_expr_comma '}'
 {
@@ -783,6 +805,11 @@ storage_class:
         empty
 {
   $$ = 0;
+}
+        | KW_CONST storage_class
+{
+  // This isn't really a storage class, but it helps with parsing.
+  $$ = $2 | (int)CPPInstance::SC_const;
 }
         | KW_EXTERN storage_class
 {
@@ -861,10 +888,22 @@ attribute_specifier:
         ;
 
 type_like_declaration:
-        multiple_var_declaration
+        storage_class var_type_decl
+{
+  // We don't need to push/pop type, because we can't nest
+  // type_like_declaration.
+  if ($2->as_type_declaration()) {
+    current_type = $2->as_type_declaration()->_type;
+  } else {
+    current_type = $2->as_type();
+  }
+  push_storage_class($1);
+}
+        multiple_instance_identifiers
 {
-  /* multiple_var_declaration adds itself to the scope. */
+  pop_storage_class();
 }
+
         | storage_class type_decl ';'
 {
   // We don't really care about the storage class here.  In fact, it's
@@ -891,39 +930,6 @@ type_like_declaration:
   }
 }
         | using_declaration
-        ;
-
-multiple_var_declaration:
-        storage_class var_type_decl
-{
-  // We don't need to push/pop type, because we can't nest
-  // multiple_var_declarations.
-  if ($2->as_type_declaration()) {
-    current_type = $2->as_type_declaration()->_type;
-  } else {
-    current_type = $2->as_type();
-  }
-  push_storage_class($1);
-}
-        multiple_instance_identifiers
-{
-  pop_storage_class();
-}
-        | storage_class KW_CONST var_type_decl
-{
-  // We don't need to push/pop type, because we can't nest
-  // multiple_var_declarations.
-  if ($3->as_type_declaration()) {
-    current_type = $3->as_type_declaration()->_type;
-  } else {
-    current_type = $3->as_type();
-  }
-  push_storage_class($1);
-}
-        multiple_const_instance_identifiers
-{
-  pop_storage_class();
-}
 
         /* We don't need to include a rule for variables that point to
            functions, because we get those from the function_prototype
@@ -933,6 +939,9 @@ multiple_var_declaration:
 multiple_instance_identifiers:
         instance_identifier_and_maybe_trailing_return_type maybe_initialize_or_function_body
 {
+  if (current_storage_class & CPPInstance::SC_const) {
+    $1->add_modifier(IIT_const);
+  }
   CPPInstance *inst = new CPPInstance(current_type, $1,
                                       current_storage_class,
                                       @1.file);
@@ -941,27 +950,9 @@ multiple_instance_identifiers:
 }
         | instance_identifier_and_maybe_trailing_return_type maybe_initialize ',' multiple_instance_identifiers
 {
-  CPPInstance *inst = new CPPInstance(current_type, $1,
-                                      current_storage_class,
-                                      @1.file);
-  inst->set_initializer($2);
-  current_scope->add_declaration(inst, global_scope, current_lexer, @1);
-}
-        ;
-
-multiple_const_instance_identifiers:
-        instance_identifier_and_maybe_trailing_return_type maybe_initialize_or_function_body
-{
-  $1->add_modifier(IIT_const);
-  CPPInstance *inst = new CPPInstance(current_type, $1,
-                                      current_storage_class,
-                                      @1.file);
-  inst->set_initializer($2);
-  current_scope->add_declaration(inst, global_scope, current_lexer, @1);
-}
-        | instance_identifier_and_maybe_trailing_return_type maybe_initialize ',' multiple_const_instance_identifiers
-{
-  $1->add_modifier(IIT_const);
+  if (current_storage_class & CPPInstance::SC_const) {
+    $1->add_modifier(IIT_const);
+  }
   CPPInstance *inst = new CPPInstance(current_type, $1,
                                       current_storage_class,
                                       @1.file);
@@ -986,21 +977,6 @@ typedef_declaration:
         typedef_instance_identifiers
 {
   pop_storage_class();
-}
-        | storage_class KW_CONST var_type_decl
-{
-  // We don't need to push/pop type, because we can't nest
-  // multiple_var_declarations.
-  if ($3->as_type_declaration()) {
-    current_type = $3->as_type_declaration()->_type;
-  } else {
-    current_type = $3->as_type();
-  }
-  push_storage_class($1);
-}
-        typedef_const_instance_identifiers
-{
-  pop_storage_class();
 }
         | storage_class function_prototype maybe_initialize_or_function_body
 {
@@ -1019,29 +995,18 @@ typedef_declaration:
 typedef_instance_identifiers:
         instance_identifier_and_maybe_trailing_return_type maybe_initialize_or_function_body
 {
+  if (current_storage_class & CPPInstance::SC_const) {
+    $1->add_modifier(IIT_const);
+  }
   CPPType *target_type = current_type;
   CPPTypedefType *typedef_type = new CPPTypedefType(target_type, $1, current_scope, @1.file);
   current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, @1);
 }
         | instance_identifier_and_maybe_trailing_return_type maybe_initialize ',' typedef_instance_identifiers
 {
-  CPPType *target_type = current_type;
-  CPPTypedefType *typedef_type = new CPPTypedefType(target_type, $1, current_scope, @1.file);
-  current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, @1);
-}
-        ;
-
-typedef_const_instance_identifiers:
-        instance_identifier_and_maybe_trailing_return_type maybe_initialize_or_function_body
-{
-  $1->add_modifier(IIT_const);
-  CPPType *target_type = current_type;
-  CPPTypedefType *typedef_type = new CPPTypedefType(target_type, $1, current_scope, @1.file);
-  current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, @1);
-}
-        | instance_identifier_and_maybe_trailing_return_type maybe_initialize ',' typedef_const_instance_identifiers
-{
-  $1->add_modifier(IIT_const);
+  if (current_storage_class & CPPInstance::SC_const) {
+    $1->add_modifier(IIT_const);
+  }
   CPPType *target_type = current_type;
   CPPTypedefType *typedef_type = new CPPTypedefType(target_type, $1, current_scope, @1.file);
   current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, @1);
@@ -1244,26 +1209,38 @@ function_post:
 {
   $$ = 0;
 }
-        | KW_CONST
+        | function_post KW_CONST
+{
+  $$ = $1 | (int)CPPFunctionType::F_const_method;
+}
+        | function_post KW_VOLATILE
 {
-  $$ = (int)CPPFunctionType::F_const_method;
+  $$ = $1 | (int)CPPFunctionType::F_volatile_method;
 }
         | function_post KW_NOEXCEPT
 {
-  $$ = (int)CPPFunctionType::F_noexcept;
+  $$ = $1 | (int)CPPFunctionType::F_noexcept;
 }
         | function_post KW_FINAL
 {
-  $$ = (int)CPPFunctionType::F_final;
+  $$ = $1 | (int)CPPFunctionType::F_final;
 }
         | function_post KW_OVERRIDE
 {
-  $$ = (int)CPPFunctionType::F_override;
+  $$ = $1 | (int)CPPFunctionType::F_override;
+}
+        | function_post '&'
+{
+  $$ = $1 | (int)CPPFunctionType::F_lvalue_method;
+}
+        | function_post ANDAND
+{
+  $$ = $1 | (int)CPPFunctionType::F_rvalue_method;
 }
         | function_post KW_MUTABLE
 {
   // Used for lambdas, currently ignored.
-  $$ = 0;
+  $$ = $1;
 }
         | function_post KW_THROW '(' ')'
 {
@@ -1272,6 +1249,10 @@ function_post:
         | function_post KW_THROW '(' name ')'
 {
   $$ = $1;
+}
+        | function_post KW_THROW '(' name ELLIPSIS ')'
+{
+  $$ = $1;
 }
 /*        | function_post '[' '[' attribute_specifiers ']' ']'
 {
@@ -1475,22 +1456,35 @@ template_nonempty_formal_parameters:
 }
         ;
 
+typename_keyword:
+        KW_CLASS
+        | KW_TYPENAME
+        ;
+
 template_formal_parameter:
-        KW_CLASS name
+        typename_keyword
+{
+  $$ = CPPType::new_type(new CPPClassTemplateParameter((CPPIdentifier *)NULL));
+}
+        | typename_keyword name
 {
   $$ = CPPType::new_type(new CPPClassTemplateParameter($2));
 }
-        | KW_CLASS name '=' full_type
+        | typename_keyword name '=' full_type
 {
   $$ = CPPType::new_type(new CPPClassTemplateParameter($2, $4));
 }
-        | KW_TYPENAME name
+        | typename_keyword ELLIPSIS
 {
-  $$ = CPPType::new_type(new CPPClassTemplateParameter($2));
+  CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter((CPPIdentifier *)NULL);
+  ctp->_packed = true;
+  $$ = CPPType::new_type(ctp);
 }
-        | KW_TYPENAME name '=' full_type
+        | typename_keyword ELLIPSIS name
 {
-  $$ = CPPType::new_type(new CPPClassTemplateParameter($2, $4));
+  CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter($3);
+  ctp->_packed = true;
+  $$ = CPPType::new_type(ctp);
 }
         | template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize
 {
@@ -1504,6 +1498,17 @@ template_formal_parameter:
   CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file);
   inst->set_initializer($4);
   $$ = inst;
+}
+        | template_formal_parameter_type parameter_pack_identifier
+{
+  CPPInstance *inst = new CPPInstance($1, $2, 0, @2.file);
+  $$ = inst;
+}
+        | KW_CONST template_formal_parameter_type parameter_pack_identifier
+{
+  $3->add_modifier(IIT_const);
+  CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file);
+  $$ = inst;
 }
         ;
 
@@ -1524,6 +1529,14 @@ template_formal_parameter_type:
     yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
   }
   assert($$ != NULL);
+}
+        | TYPEPACK_IDENTIFIER
+{
+  $$ = $1->find_type(current_scope, global_scope, false, current_lexer);
+  if ($$ == NULL) {
+    yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
+  }
+  assert($$ != NULL);
 }
         ;
 
@@ -1604,7 +1617,16 @@ instance_identifier:
 }
         | instance_identifier '('
 {
-  push_scope($1->get_scope(current_scope, global_scope));
+  // Create a scope for this function (in case it is a function)
+  CPPScope *scope = new CPPScope($1->get_scope(current_scope, global_scope),
+                                 CPPNameComponent(""), V_private);
+
+  // It still needs to be able to pick up any template arguments, if this is
+  // a definition for a method template.  Add a fake "using" declaration to
+  // accomplish this.
+  scope->_using.insert(current_scope);
+
+  push_scope(scope);
 }
         formal_parameter_list ')' function_post
 {
@@ -1842,6 +1864,23 @@ function_parameter:
   $4->add_modifier(IIT_const);
   $$ = new CPPInstance($3, $4, 0, @3.file);
   $$->set_initializer($5);
+}
+        | type_pack parameter_pack_identifier maybe_initialize
+{
+  $$ = new CPPInstance($1, $2, 0, @2.file);
+  $$->set_initializer($3);
+}
+        | KW_CONST type_pack parameter_pack_identifier maybe_initialize
+{
+  $3->add_modifier(IIT_const);
+  $$ = new CPPInstance($2, $3, 0, @3.file);
+  $$->set_initializer($4);
+}
+        | KW_CONST KW_REGISTER type_pack parameter_pack_identifier maybe_initialize
+{
+  $4->add_modifier(IIT_const);
+  $$ = new CPPInstance($3, $4, 0, @3.file);
+  $$->set_initializer($5);
 }
         | KW_REGISTER function_parameter
 {
@@ -1970,10 +2009,79 @@ formal_parameter_identifier:
 }
         ;
 
+parameter_pack_identifier:
+        ELLIPSIS
+{
+  $$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
+  $$->_packed = true;
+}
+        | ELLIPSIS name
+{
+  $$ = new CPPInstanceIdentifier($2);
+  $$->_packed = true;
+}
+        | KW_CONST parameter_pack_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_const);
+}
+        | KW_VOLATILE parameter_pack_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_volatile);
+}
+        | '*' parameter_pack_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_pointer);
+}
+        | '&' parameter_pack_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_reference);
+}
+        | ANDAND parameter_pack_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_rvalue_reference);
+}
+        | SCOPING '*' parameter_pack_identifier  %prec UNARY
+{
+  $$ = $3;
+  $$->add_scoped_pointer_modifier($1);
+}
+        | parameter_pack_identifier '[' optional_const_expr ']'
+{
+  $$ = $1;
+  $$->add_array_modifier($3);
+}
+        | '(' parameter_pack_identifier ')' '(' function_parameter_list ')' function_post
+{
+  $$ = $2;
+  $$->add_modifier(IIT_paren);
+  $$->add_func_modifier($5, $7);
+}
+        | '(' parameter_pack_identifier ')'
+{
+  $$ = $2;
+  $$->add_modifier(IIT_paren);
+}
+        ;
+
 not_paren_empty_instance_identifier:
         empty
 {
   $$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
+}
+        | ELLIPSIS
+{
+  $$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
+  $$->_packed = true;
+}
+        | ELLIPSIS name
+{
+  $$ = new CPPInstanceIdentifier($2);
+  $$->_packed = true;
 }
         | KW_CONST not_paren_empty_instance_identifier  %prec UNARY
 {
@@ -2016,6 +2124,16 @@ empty_instance_identifier:
         empty
 {
   $$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
+}
+        | ELLIPSIS
+{
+  $$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
+  $$->_packed = true;
+}
+        | ELLIPSIS name
+{
+  $$ = new CPPInstanceIdentifier($2);
+  $$->_packed = true;
 }
         | KW_CONST empty_instance_identifier  %prec UNARY
 {
@@ -2150,6 +2268,16 @@ type:
     str << *$3;
     yyerror("could not determine type of " + str.str(), @3);
   }
+}
+        | KW_UNDERLYING_TYPE '(' full_type ')'
+{
+  CPPEnumType *enum_type = $3->as_enum_type();
+  if (enum_type == NULL) {
+    yyerror("an enumeration type is required", @3);
+    $$ = $3;
+  } else {
+    $$ = enum_type->get_underlying_type();
+  }
 }
         | KW_AUTO
 {
@@ -2157,6 +2285,17 @@ type:
 }
         ;
 
+type_pack:
+        TYPEPACK_IDENTIFIER
+{
+  $$ = $1->find_type(current_scope, global_scope, false, current_lexer);
+  if ($$ == NULL) {
+    yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
+  }
+  assert($$ != NULL);
+}
+        ;
+
 type_decl:
         simple_type
 {
@@ -2244,6 +2383,16 @@ type_decl:
     str << *$3;
     yyerror("could not determine type of " + str.str(), @3);
   }
+}
+        | KW_UNDERLYING_TYPE '(' full_type ')'
+{
+  CPPEnumType *enum_type = $3->as_enum_type();
+  if (enum_type == NULL) {
+    yyerror("an enumeration type is required", @3);
+    $$ = $3;
+  } else {
+    $$ = enum_type->get_underlying_type();
+  }
 }
         | KW_AUTO
 {
@@ -2308,6 +2457,16 @@ predefined_type:
     str << *$3;
     yyerror("could not determine type of " + str.str(), @3);
   }
+}
+        | KW_UNDERLYING_TYPE '(' full_type ')'
+{
+  CPPEnumType *enum_type = $3->as_enum_type();
+  if (enum_type == NULL) {
+    yyerror("an enumeration type is required", @3);
+    $$ = $3;
+  } else {
+    $$ = enum_type->get_underlying_type();
+  }
 }
         | KW_AUTO
 {
@@ -2336,6 +2495,15 @@ full_type:
 {
   $3->add_modifier(IIT_const);
   $$ = $3->unroll_type($2);
+}
+        | type_pack empty_instance_identifier
+{
+  $$ = $2->unroll_type($1);
+}
+        | KW_CONST type_pack empty_instance_identifier
+{
+  $3->add_modifier(IIT_const);
+  $$ = $3->unroll_type($2);
 }
         ;
 
@@ -2750,6 +2918,7 @@ element:
         | CHAR_TOK
         | IDENTIFIER
         | TYPENAME_IDENTIFIER
+        | TYPEPACK_IDENTIFIER
         | SCOPING
         | SIMPLE_IDENTIFIER
         | ELLIPSIS | OROR | ANDAND
@@ -2768,10 +2937,11 @@ element:
         | KW_OPERATOR | KW_OVERRIDE | KW_PRIVATE | KW_PROTECTED
         | KW_PUBLIC | KW_PUBLISHED | KW_REGISTER | KW_REINTERPRET_CAST
         | KW_RETURN | KW_SHORT | KW_SIGNED | KW_SIZEOF | KW_STATIC
-        | KW_STATIC_ASSERT | KW_STATIC_CAST | KW_STRUCT
+        | KW_STATIC_ASSERT | KW_STATIC_CAST | KW_STRUCT | KW_TEMPLATE
         | KW_THREAD_LOCAL | KW_THROW | KW_TRUE | KW_TRY | KW_TYPEDEF
-        | KW_TYPEID | KW_TYPENAME | KW_UNION | KW_UNSIGNED | KW_USING
-        | KW_VIRTUAL | KW_VOID | KW_VOLATILE | KW_WCHAR_T | KW_WHILE
+        | KW_TYPEID | KW_TYPENAME | KW_UNDERLYING_TYPE | KW_UNION
+        | KW_UNSIGNED | KW_USING | KW_VIRTUAL | KW_VOID | KW_VOLATILE
+        | KW_WCHAR_T | KW_WHILE
 {
 }
         | '+' | '-' | '*' | '/' | '&' | '|' | '^' | '!' | '~' | '=' | '%'
@@ -2840,6 +3010,10 @@ no_angle_bracket_const_expr:
         | KW_SIZEOF '(' full_type ')' %prec UNARY
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
+}
+        | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
+{
+  $$ = new CPPExpression(CPPExpression::sizeof_ellipsis_func($4));
 }
         | KW_ALIGNOF '(' full_type ')' %prec UNARY
 {
@@ -3078,6 +3252,10 @@ const_expr:
         | KW_SIZEOF '(' full_type ')' %prec UNARY
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
+}
+        | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
+{
+  $$ = new CPPExpression(CPPExpression::sizeof_ellipsis_func($4));
 }
         | KW_ALIGNOF '(' full_type ')' %prec UNARY
 {
@@ -3295,6 +3473,74 @@ const_operand:
         | '[' capture_list ']' '(' function_parameter_list ')' function_post maybe_trailing_return_type '{' code '}'
 {
   $$ = NULL;
+}
+        | KW_HAS_VIRTUAL_DESTRUCTOR '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_HAS_VIRTUAL_DESTRUCTOR, $3));
+}
+        | KW_IS_ABSTRACT '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_ABSTRACT, $3));
+}
+        | KW_IS_BASE_OF '(' full_type ',' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CLASS, $3, $5));
+}
+        | KW_IS_CLASS '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CLASS, $3));
+}
+        | KW_IS_CONSTRUCTIBLE '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CONSTRUCTIBLE, $3));
+}
+        | KW_IS_CONSTRUCTIBLE '(' full_type ',' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CONSTRUCTIBLE, $3, $5));
+}
+        | KW_IS_CONVERTIBLE_TO '(' full_type ',' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CONVERTIBLE_TO, $3, $5));
+}
+        | KW_IS_DESTRUCTIBLE '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_DESTRUCTIBLE, $3));
+}
+        | KW_IS_EMPTY '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_EMPTY, $3));
+}
+        | KW_IS_ENUM '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_ENUM, $3));
+}
+        | KW_IS_FINAL '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_FINAL, $3));
+}
+        | KW_IS_FUNDAMENTAL '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_FUNDAMENTAL, $3));
+}
+        | KW_IS_POD '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_POD, $3));
+}
+        | KW_IS_POLYMORPHIC '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_POLYMORPHIC, $3));
+}
+        | KW_IS_STANDARD_LAYOUT '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_STANDARD_LAYOUT, $3));
+}
+        | KW_IS_TRIVIAL '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_TRIVIAL, $3));
+}
+        | KW_IS_UNION '(' full_type ')'
+{
+  $$ = new CPPExpression(CPPExpression::type_trait(KW_IS_UNION, $3));
 }
         ;
 
@@ -3333,6 +3579,10 @@ formal_const_expr:
         | KW_SIZEOF '(' full_type ')' %prec UNARY
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
+}
+        | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
+{
+  $$ = new CPPExpression(CPPExpression::sizeof_ellipsis_func($4));
 }
         | KW_ALIGNOF '(' full_type ')' %prec UNARY
 {
@@ -3575,6 +3825,12 @@ class_derivation_name:
         | KW_TYPENAME name
 {
   $$ = CPPType::new_type(new CPPTBDType($2));
+}
+        | name ELLIPSIS
+{
+  CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter($1);
+  ctp->_packed = true;
+  $$ = CPPType::new_type(ctp);
 }
         ;
 
@@ -3607,6 +3863,10 @@ name:
         | TYPENAME_IDENTIFIER
 {
   $$ = $1;
+}
+        | TYPEPACK_IDENTIFIER
+{
+  $$ = $1;
 }
         | KW_FINAL
 {
@@ -3652,6 +3912,10 @@ name_no_final:
         | TYPENAME_IDENTIFIER
 {
   $$ = $1;
+}
+        | TYPEPACK_IDENTIFIER
+{
+  $$ = $1;
 }
         | KW_OVERRIDE
 {

+ 26 - 3
dtool/src/cppparser/cppClassTemplateParameter.cxx

@@ -21,7 +21,8 @@ CPPClassTemplateParameter::
 CPPClassTemplateParameter(CPPIdentifier *ident, CPPType *default_type) :
   CPPType(CPPFile()),
   _ident(ident),
-  _default_type(default_type)
+  _default_type(default_type),
+  _packed(false)
 {
 }
 
@@ -41,8 +42,14 @@ is_fully_specified() const {
 void CPPClassTemplateParameter::
 output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
   if (complete) {
-    out << "class ";
-    _ident->output(out, scope);
+    out << "class";
+    if (_packed) {
+      out << "...";
+    }
+    if (_ident != NULL) {
+      out << " ";
+      _ident->output(out, scope);
+    }
     if (_default_type) {
       out << " = ";
       _default_type->output(out, indent_level, scope, false);
@@ -82,6 +89,14 @@ is_equal(const CPPDeclaration *other) const {
     return false;
   }
 
+  if (_packed != ot->_packed) {
+    return false;
+  }
+
+  if (_ident == NULL || ot->_ident == NULL) {
+    return _ident == ot->_ident;
+  }
+
   return *_ident == *ot->_ident;
 }
 
@@ -99,5 +114,13 @@ is_less(const CPPDeclaration *other) const {
     return _default_type < ot->_default_type;
   }
 
+  if (_packed != ot->_packed) {
+    return _packed < ot->_packed;
+  }
+
+  if (_ident == NULL || ot->_ident == NULL) {
+    return _ident < ot->_ident;
+  }
+
   return *_ident < *ot->_ident;
 }

+ 1 - 0
dtool/src/cppparser/cppClassTemplateParameter.h

@@ -37,6 +37,7 @@ public:
 
   CPPIdentifier *_ident;
   CPPType *_default_type;
+  bool _packed;
 
 protected:
   virtual bool is_equal(const CPPDeclaration *other) const;

+ 42 - 1
dtool/src/cppparser/cppConstType.cxx

@@ -86,6 +86,22 @@ is_tbd() const {
   return _wrapped_around->is_tbd();
 }
 
+/**
+ * Returns true if the type is considered a fundamental type.
+ */
+bool CPPConstType::
+is_fundamental() const {
+  return _wrapped_around->is_fundamental();
+}
+
+/**
+ * Returns true if the type is considered a standard layout type.
+ */
+bool CPPConstType::
+is_standard_layout() const {
+  return _wrapped_around->is_standard_layout();
+}
+
 /**
  * Returns true if the type is considered a Plain Old Data (POD) type.
  */
@@ -94,12 +110,20 @@ is_trivial() const {
   return _wrapped_around->is_trivial();
 }
 
+/**
+ * Returns true if the type can be constructed using the given argument.
+ */
+bool CPPConstType::
+is_constructible(const CPPType *given_type) const {
+  return _wrapped_around->is_constructible(given_type);
+}
+
 /**
  * Returns true if the type is default-constructible.
  */
 bool CPPConstType::
 is_default_constructible() const {
-  return false;
+  return _wrapped_around->is_default_constructible();
 }
 
 /**
@@ -110,6 +134,23 @@ is_copy_constructible() const {
   return _wrapped_around->is_copy_constructible();
 }
 
+/**
+ * Returns true if the type is destructible.
+ */
+bool CPPConstType::
+is_destructible() const {
+  return _wrapped_around->is_destructible();
+}
+
+/**
+ * Returns true if variables of this type may be implicitly converted to
+ * the other type.
+ */
+bool CPPConstType::
+is_convertible_to(const CPPType *other) const {
+  return _wrapped_around->is_convertible_to(other);
+}
+
 /**
  * This is a little more forgiving than is_equal(): it returns true if the
  * types appear to be referring to the same thing, even if they may have

+ 5 - 0
dtool/src/cppparser/cppConstType.h

@@ -36,9 +36,14 @@ public:
                                 CPPScope *global_scope);
 
   virtual bool is_tbd() const;
+  virtual bool is_fundamental() const;
+  virtual bool is_standard_layout() const;
   virtual bool is_trivial() const;
+  virtual bool is_constructible(const CPPType *type) const;
   virtual bool is_default_constructible() const;
   virtual bool is_copy_constructible() const;
+  virtual bool is_destructible() const;
+  virtual bool is_convertible_to(const CPPType *other) const;
   virtual bool is_equivalent(const CPPType &other) const;
 
   virtual void output(ostream &out, int indent_level, CPPScope *scope,

+ 8 - 2
dtool/src/cppparser/cppDeclaration.cxx

@@ -41,8 +41,13 @@ CPPDeclaration(const CPPDeclaration &copy) :
 /**
  *
  */
-CPPDeclaration::
-~CPPDeclaration() {
+CPPDeclaration &CPPDeclaration::
+operator = (const CPPDeclaration &copy) {
+  _vis = copy._vis;
+  _template_scope = copy._template_scope;
+  _file = copy._file;
+  _leading_comment = copy._leading_comment;
+  return *this;
 }
 
 /**
@@ -124,6 +129,7 @@ CPPDeclaration *CPPDeclaration::
 substitute_decl(SubstDecl &subst, CPPScope *, CPPScope *) {
   SubstDecl::const_iterator si = subst.find(this);
   if (si != subst.end()) {
+    assert((*si).second != NULL);
     return (*si).second;
   }
   return this;

+ 70 - 1
dtool/src/cppparser/cppDeclaration.h

@@ -89,7 +89,9 @@ public:
 
   CPPDeclaration(const CPPFile &file);
   CPPDeclaration(const CPPDeclaration &copy);
-  virtual ~CPPDeclaration();
+  virtual ~CPPDeclaration() {};
+
+  CPPDeclaration &operator = (const CPPDeclaration &copy);
 
   bool operator == (const CPPDeclaration &other) const;
   bool operator != (const CPPDeclaration &other) const;
@@ -139,6 +141,73 @@ public:
   virtual CPPMakeProperty *as_make_property();
   virtual CPPMakeSeq *as_make_seq();
 
+  inline const CPPInstance *as_instance() const {
+    return ((CPPDeclaration *)this)->as_instance();
+  }
+  inline const CPPClassTemplateParameter *as_class_template_parameter() const {
+    return ((CPPDeclaration *)this)->as_class_template_parameter();
+  }
+  inline const CPPTypedefType *as_typedef_type() const {
+    return ((CPPDeclaration *)this)->as_typedef_type();
+  }
+  inline const CPPTypeDeclaration *as_type_declaration() const {
+    return ((CPPDeclaration *)this)->as_type_declaration();
+  }
+  inline const CPPExpression *as_expression() const {
+    return ((CPPDeclaration *)this)->as_expression();
+  }
+  inline const CPPType *as_type() const {
+    return ((CPPDeclaration *)this)->as_type();
+  }
+  inline const CPPNamespace *as_namespace() const {
+    return ((CPPDeclaration *)this)->as_namespace();
+  }
+  inline const CPPUsing *as_using() const {
+    return ((CPPDeclaration *)this)->as_using();
+  }
+  inline const CPPSimpleType *as_simple_type() const {
+    return ((CPPDeclaration *)this)->as_simple_type();
+  }
+  inline const CPPPointerType *as_pointer_type() const {
+    return ((CPPDeclaration *)this)->as_pointer_type();
+  }
+  inline const CPPReferenceType *as_reference_type() const {
+    return ((CPPDeclaration *)this)->as_reference_type();
+  }
+  inline const CPPArrayType *as_array_type() const {
+    return ((CPPDeclaration *)this)->as_array_type();
+  }
+  inline const CPPConstType *as_const_type() const {
+    return ((CPPDeclaration *)this)->as_const_type();
+  }
+  inline const CPPFunctionType *as_function_type() const {
+    return ((CPPDeclaration *)this)->as_function_type();
+  }
+  inline const CPPFunctionGroup *as_function_group() const {
+    return ((CPPDeclaration *)this)->as_function_group();
+  }
+  inline const CPPExtensionType *as_extension_type() const {
+    return ((CPPDeclaration *)this)->as_extension_type();
+  }
+  inline const CPPStructType *as_struct_type() const {
+    return ((CPPDeclaration *)this)->as_struct_type();
+  }
+  inline const CPPEnumType *as_enum_type() const {
+    return ((CPPDeclaration *)this)->as_enum_type();
+  }
+  inline const CPPTBDType *as_tbd_type() const {
+    return ((CPPDeclaration *)this)->as_tbd_type();
+  }
+  inline const CPPTypeProxy *as_type_proxy() const {
+    return ((CPPDeclaration *)this)->as_type_proxy();
+  }
+  inline const CPPMakeProperty *as_make_property() const {
+    return ((CPPDeclaration *)this)->as_make_property();
+  }
+  inline const CPPMakeSeq *as_make_seq() const {
+    return ((CPPDeclaration *)this)->as_make_seq();
+  }
+
   CPPVisibility _vis;
   CPPTemplateScope *_template_scope;
   CPPFile _file;

+ 1 - 0
dtool/src/cppparser/cppEnumType.h

@@ -16,6 +16,7 @@
 
 #include "dtoolbase.h"
 
+#include "cppBisonDefs.h"
 #include "cppExtensionType.h"
 
 #include <vector>

+ 212 - 7
dtool/src/cppparser/cppExpression.cxx

@@ -24,6 +24,7 @@
 #include "cppInstance.h"
 #include "cppFunctionGroup.h"
 #include "cppFunctionType.h"
+#include "cppStructType.h"
 #include "cppBison.h"
 #include "pdtoa.h"
 
@@ -389,6 +390,19 @@ typeid_op(CPPExpression *op1, CPPType *std_type_info) {
   return expr;
 }
 
+/**
+ * Creates an expression that returns a particular type trait.
+ */
+CPPExpression CPPExpression::
+type_trait(int trait, CPPType *type, CPPType *arg) {
+  CPPExpression expr(0);
+  expr._type = T_type_trait;
+  expr._u._type_trait._trait = trait;
+  expr._u._type_trait._type = type;
+  expr._u._type_trait._arg = arg;
+  return expr;
+}
+
 /**
  *
  */
@@ -401,6 +415,17 @@ sizeof_func(CPPType *type) {
   return expr;
 }
 
+/**
+ *
+ */
+CPPExpression CPPExpression::
+sizeof_ellipsis_func(CPPIdentifier *ident) {
+  CPPExpression expr(0);
+  expr._type = T_sizeof_ellipsis;
+  expr._u._ident = ident;
+  return expr;
+}
+
 /**
  *
  */
@@ -492,13 +517,6 @@ get_delete() {
   return expr;
 }
 
-/**
- *
- */
-CPPExpression::
-~CPPExpression() {
-}
-
 /**
  *
  */
@@ -579,6 +597,7 @@ evaluate() const {
   case T_new:
   case T_default_new:
   case T_sizeof:
+  case T_sizeof_ellipsis:
     return Result();
 
   case T_alignof:
@@ -801,6 +820,95 @@ evaluate() const {
   case T_typeid_expr:
     return Result();
 
+  case T_type_trait:
+    switch (_u._type_trait._trait) {
+    case KW_HAS_VIRTUAL_DESTRUCTOR:
+      {
+        CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
+        return Result(struct_type != NULL && struct_type->has_virtual_destructor());
+      }
+
+    case KW_IS_ABSTRACT:
+      {
+        CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
+        return Result(struct_type != NULL && struct_type->is_abstract());
+      }
+
+    case KW_IS_BASE_OF:
+      {
+        CPPStructType *struct_type1 = _u._type_trait._type->as_struct_type();
+        CPPStructType *struct_type2 = _u._type_trait._arg->as_struct_type();
+        return Result(struct_type1 != NULL && struct_type2 != NULL && struct_type1->is_base_of(struct_type2));
+      }
+
+    case KW_IS_CLASS:
+      {
+        CPPExtensionType *ext_type = _u._type_trait._type->as_extension_type();
+        return Result(ext_type != NULL && (
+          ext_type->_type == CPPExtensionType::T_class ||
+          ext_type->_type == CPPExtensionType::T_struct));
+      }
+
+    case KW_IS_CONSTRUCTIBLE:
+      if (_u._type_trait._arg == NULL) {
+        return Result(_u._type_trait._type->is_default_constructible());
+      } else {
+        return Result(_u._type_trait._type->is_constructible(_u._type_trait._arg));
+      }
+
+    case KW_IS_CONVERTIBLE_TO:
+      assert(_u._type_trait._arg != NULL);
+      return Result(_u._type_trait._type->is_convertible_to(_u._type_trait._arg));
+
+    case KW_IS_DESTRUCTIBLE:
+      return Result(_u._type_trait._type->is_destructible());
+
+    case KW_IS_EMPTY:
+      {
+        CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
+        return Result(struct_type != NULL && struct_type->is_empty());
+      }
+
+    case KW_IS_ENUM:
+      return Result(_u._type_trait._type->is_enum());
+
+    case KW_IS_FINAL:
+      {
+        CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
+        return Result(struct_type != NULL && struct_type->is_final());
+      }
+
+    case KW_IS_FUNDAMENTAL:
+      return Result(_u._type_trait._type->is_fundamental());
+
+    case KW_IS_POD:
+      return Result(_u._type_trait._type->is_trivial() &&
+                    _u._type_trait._type->is_standard_layout());
+
+    case KW_IS_POLYMORPHIC:
+      {
+        CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
+        return Result(struct_type != NULL && struct_type->is_polymorphic());
+      }
+
+    case KW_IS_STANDARD_LAYOUT:
+      return Result(_u._type_trait._type->is_standard_layout());
+
+    case KW_IS_TRIVIAL:
+      return Result(_u._type_trait._type->is_trivial());
+
+    case KW_IS_UNION:
+      {
+        CPPExtensionType *ext_type = _u._type_trait._type->as_extension_type();
+        return Result(ext_type != NULL &&
+          ext_type->_type == CPPExtensionType::T_union);
+      }
+
+    default:
+      cerr << "**unexpected type trait**\n";
+      abort();
+    }
+
   default:
     cerr << "**invalid operand**\n";
     abort();
@@ -916,6 +1024,7 @@ determine_type() const {
     return CPPType::new_type(new CPPPointerType(_u._typecast._to));
 
   case T_sizeof:
+  case T_sizeof_ellipsis:
   case T_alignof:
     // Note: this should actually be size_t, but that is defined as a typedef
     // in parser-inc.  We could try to resolve it, but that's hacky.  Eh, it's
@@ -1057,6 +1166,9 @@ determine_type() const {
   case T_typeid_expr:
     return _u._typeid._std_type_info;
 
+  case T_type_trait:
+    return bool_type;
+
   default:
     cerr << "**invalid operand**\n";
     abort();
@@ -1113,6 +1225,9 @@ is_fully_specified() const {
   case T_alignof:
     return _u._typecast._to->is_fully_specified();
 
+  case T_sizeof_ellipsis:
+    return _u._ident->is_fully_specified();
+
   case T_trinary_operation:
     if (!_u._op._op3->is_fully_specified()) {
       return false;
@@ -1141,6 +1256,9 @@ is_fully_specified() const {
   case T_typeid_expr:
     return _u._typeid._expr->is_fully_specified();
 
+  case T_type_trait:
+    return _u._type_trait._type->is_fully_specified();
+
   default:
     return true;
   }
@@ -1276,6 +1394,13 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
     any_changed = any_changed || (rep->_u._typeid._expr != _u._typeid._expr);
     break;
 
+  case T_type_trait:
+    rep->_u._type_trait._type =
+      _u._type_trait._type->substitute_decl(subst, current_scope, global_scope)
+      ->as_type();
+    any_changed = any_changed || (rep->_u._type_trait._type != _u._type_trait._type);
+    break;
+
   default:
     break;
   }
@@ -1350,6 +1475,9 @@ is_tbd() const {
   case T_typeid_expr:
     return _u._typeid._expr->is_tbd();
 
+  case T_type_trait:
+    return _u._type_trait._type->is_tbd();
+
   default:
     return false;
   }
@@ -1541,6 +1669,12 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
     out << ")";
     break;
 
+  case T_sizeof_ellipsis:
+    out << "sizeof...(";
+    _u._ident->output(out, scope);
+    out << ")";
+    break;
+
   case T_alignof:
     out << "alignof(";
     _u._typecast._to->output(out, indent_level, scope, false);
@@ -1753,6 +1887,65 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
     out << "delete";
     break;
 
+  case T_type_trait:
+    switch (_u._type_trait._trait) {
+    case KW_HAS_VIRTUAL_DESTRUCTOR:
+      out << "__has_virtual_destructor";
+      break;
+    case KW_IS_ABSTRACT:
+      out << "__is_abstract";
+      break;
+    case KW_IS_BASE_OF:
+      out << "__is_base_of";
+      break;
+    case KW_IS_CLASS:
+      out << "__is_class";
+      break;
+    case KW_IS_CONSTRUCTIBLE:
+      out << "__is_constructible";
+      break;
+    case KW_IS_CONVERTIBLE_TO:
+      out << "__is_convertible_to";
+      break;
+    case KW_IS_DESTRUCTIBLE:
+      out << "__is_destructible";
+      break;
+    case KW_IS_EMPTY:
+      out << "__is_empty";
+      break;
+    case KW_IS_ENUM:
+      out << "__is_enum";
+      break;
+    case KW_IS_FINAL:
+      out << "__is_final";
+      break;
+    case KW_IS_FUNDAMENTAL:
+      out << "__is_fundamental";
+      break;
+    case KW_IS_POD:
+      out << "__is_pod";
+      break;
+    case KW_IS_POLYMORPHIC:
+      out << "__is_polymorphic";
+      break;
+    case KW_IS_STANDARD_LAYOUT:
+      out << "__is_standard_layout";
+      break;
+    case KW_IS_TRIVIAL:
+      out << "__is_trivial";
+      break;
+    case KW_IS_UNION:
+      out << "__is_union";
+      break;
+    default:
+      out << (evaluate().as_boolean() ? "true" : "false");
+      return;
+    }
+    out << '(';
+    _u._type_trait._type->output(out, indent_level, scope, false);
+    out << ')';
+    break;
+
   default:
     out << "(** invalid operand type " << (int)_type << " **)";
   }
@@ -1864,6 +2057,7 @@ is_equal(const CPPDeclaration *other) const {
     return _u._fgroup == ot->_u._fgroup;
 
   case T_unknown_ident:
+  case T_sizeof_ellipsis:
     return *_u._ident == *ot->_u._ident;
 
   case T_typecast:
@@ -1907,6 +2101,10 @@ is_equal(const CPPDeclaration *other) const {
   case T_typeid_expr:
     return _u._typeid._expr == ot->_u._typeid._expr;
 
+  case T_type_trait:
+    return _u._type_trait._trait == ot->_u._type_trait._trait &&
+           _u._type_trait._type == ot->_u._type_trait._type;
+
   default:
     cerr << "(** invalid operand type " << (int)_type << " **)";
   }
@@ -1954,6 +2152,7 @@ is_less(const CPPDeclaration *other) const {
     return *_u._fgroup < *ot->_u._fgroup;
 
   case T_unknown_ident:
+  case T_sizeof_ellipsis:
     return *_u._ident < *ot->_u._ident;
 
   case T_typecast:
@@ -2007,6 +2206,12 @@ is_less(const CPPDeclaration *other) const {
   case T_typeid_expr:
     return *_u._typeid._expr < *ot->_u._typeid._expr;
 
+  case T_type_trait:
+    if (_u._type_trait._trait != ot->_u._type_trait._trait) {
+      return _u._type_trait._trait < ot->_u._type_trait._trait;
+    }
+    return *_u._type_trait._type < *ot->_u._type_trait._type;
+
   default:
     cerr << "(** invalid operand type " << (int)_type << " **)";
   }

+ 9 - 2
dtool/src/cppparser/cppExpression.h

@@ -51,6 +51,7 @@ public:
     T_new,
     T_default_new,
     T_sizeof,
+    T_sizeof_ellipsis,
     T_alignof,
     T_unary_operation,
     T_binary_operation,
@@ -59,6 +60,7 @@ public:
     T_raw_literal,
     T_typeid_type,
     T_typeid_expr,
+    T_type_trait,
 
     // These are used when parsing =default and =delete methods.
     T_default,
@@ -81,7 +83,9 @@ public:
   static CPPExpression new_op(CPPType *type, CPPExpression *op1 = NULL);
   static CPPExpression typeid_op(CPPType *type, CPPType *std_type_info);
   static CPPExpression typeid_op(CPPExpression *op1, CPPType *std_type_info);
+  static CPPExpression type_trait(int trait, CPPType *type, CPPType *arg = NULL);
   static CPPExpression sizeof_func(CPPType *type);
+  static CPPExpression sizeof_ellipsis_func(CPPIdentifier *ident);
   static CPPExpression alignof_func(CPPType *type);
 
   static CPPExpression literal(unsigned long long value, CPPInstance *lit_op);
@@ -93,8 +97,6 @@ public:
   static const CPPExpression &get_default();
   static const CPPExpression &get_delete();
 
-  ~CPPExpression();
-
   enum ResultType {
     RT_integer,
     RT_real,
@@ -170,6 +172,11 @@ public:
       CPPInstance *_operator;
       CPPExpression *_value;
     } _literal;
+    struct {
+      int _trait;
+      CPPType *_type;
+      CPPType *_arg;
+    } _type_trait;
   } _u;
 
 protected:

+ 23 - 3
dtool/src/cppparser/cppExtensionType.cxx

@@ -87,12 +87,32 @@ is_tbd() const {
   return false;
 }
 
+/**
+ * Returns true if the type is considered a standard layout type.
+ */
+bool CPPExtensionType::
+is_standard_layout() const {
+  return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
+}
+
 /**
  * Returns true if the type is considered a Plain Old Data (POD) type.
  */
 bool CPPExtensionType::
 is_trivial() const {
-  return (_type == T_enum);
+  return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
+}
+
+/**
+ * Returns true if the type can be constructed using the given argument.
+ */
+bool CPPExtensionType::
+is_constructible(const CPPType *given_type) const {
+  if (_type == T_enum || _type == T_enum_class || _type == T_enum_struct) {
+    const CPPExtensionType *other = ((CPPType *)given_type)->remove_reference()->remove_const()->as_extension_type();
+    return other != NULL && is_equal(other);
+  }
+  return false;
 }
 
 /**
@@ -100,7 +120,7 @@ is_trivial() const {
  */
 bool CPPExtensionType::
 is_default_constructible() const {
-  return (_type == T_enum);
+  return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
 }
 
 /**
@@ -108,7 +128,7 @@ is_default_constructible() const {
  */
 bool CPPExtensionType::
 is_copy_constructible() const {
-  return (_type == T_enum);
+  return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
 }
 
 /**

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

@@ -47,7 +47,9 @@ public:
 
   virtual bool is_incomplete() const;
   virtual bool is_tbd() const;
+  virtual bool is_standard_layout() const;
   virtual bool is_trivial() const;
+  virtual bool is_constructible(const CPPType *type) const;
   virtual bool is_default_constructible() const;
   virtual bool is_copy_constructible() const;
 

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

@@ -55,7 +55,7 @@ public:
 
   Filename _filename;
   Filename _filename_as_referenced;
-  Source _source;
+  mutable Source _source;
   mutable bool _pragma_once;
 };
 

+ 8 - 3
dtool/src/cppparser/cppFunctionType.cxx

@@ -89,9 +89,11 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
   }
 
   CPPFunctionType *rep = new CPPFunctionType(*this);
-  rep->_return_type =
-    _return_type->substitute_decl(subst, current_scope, global_scope)
-    ->as_type();
+  if (_return_type != NULL) {
+    rep->_return_type =
+      _return_type->substitute_decl(subst, current_scope, global_scope)
+      ->as_type();
+  }
 
   rep->_parameters =
     _parameters->substitute_decl(subst, current_scope, global_scope);
@@ -265,6 +267,9 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
   if (_flags & F_const_method) {
     out << " const";
   }
+  if (_flags & F_volatile_method) {
+    out << " volatile";
+  }
   if (_flags & F_noexcept) {
     out << " noexcept";
   }

+ 3 - 0
dtool/src/cppparser/cppFunctionType.h

@@ -40,6 +40,9 @@ public:
     F_trailing_return_type = 0x800,
     F_final             = 0x1000,
     F_override          = 0x2000,
+    F_volatile_method   = 0x4000,
+    F_lvalue_method     = 0x8000,
+    F_rvalue_method     = 0x10000,
   };
 
   CPPFunctionType(CPPType *return_type, CPPParameterList *parameters,

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