Explorar el Código

Merge branch 'master' into cmake

Sam Edwards hace 8 años
padre
commit
ed4725afa2
Se han modificado 98 ficheros con 2499 adiciones y 2240 borrados
  1. 7 7
      README.md
  2. 1 1
      direct/src/directtools/DirectCameraControl.py
  3. 3 3
      direct/src/directtools/DirectManipulation.py
  4. 1 1
      direct/src/directtools/DirectSession.py
  5. 2 2
      direct/src/tkpanels/DirectSessionPanel.py
  6. 1 1
      direct/src/tkwidgets/MemoryExplorer.py
  7. 483 469
      dtool/src/cppparser/cppBison.cxx.prebuilt
  8. 198 194
      dtool/src/cppparser/cppBison.h.prebuilt
  9. 183 38
      dtool/src/cppparser/cppBison.yxx
  10. 4 0
      dtool/src/cppparser/cppBisonDefs.h
  11. 196 0
      dtool/src/cppparser/cppClosureType.cxx
  12. 65 0
      dtool/src/cppparser/cppClosureType.h
  13. 8 0
      dtool/src/cppparser/cppDeclaration.cxx
  14. 6 0
      dtool/src/cppparser/cppDeclaration.h
  15. 97 3
      dtool/src/cppparser/cppExpression.cxx
  16. 6 0
      dtool/src/cppparser/cppExpression.h
  17. 53 8
      dtool/src/cppparser/cppFunctionType.cxx
  18. 2 0
      dtool/src/cppparser/cppFunctionType.h
  19. 70 5
      dtool/src/cppparser/cppPreprocessor.cxx
  20. 2 0
      dtool/src/cppparser/cppPreprocessor.h
  21. 8 0
      dtool/src/cppparser/cppToken.cxx
  22. 1 0
      dtool/src/cppparser/p3cppParser_composite1.cxx
  23. 4 4
      dtool/src/dtoolbase/deletedBufferChain.cxx
  24. 60 85
      dtool/src/dtoolbase/deletedChain.T
  25. 6 0
      dtool/src/dtoolbase/dtoolbase.h
  26. 34 4
      dtool/src/dtoolbase/dtoolbase_cc.h
  27. 36 67
      dtool/src/dtoolbase/memoryHook.I
  28. 29 17
      dtool/src/dtoolbase/memoryHook.cxx
  29. 19 2
      dtool/src/dtoolbase/memoryHook.h
  30. 3 17
      dtool/src/dtoolbase/mutexDummyImpl.I
  31. 9 5
      dtool/src/dtoolbase/mutexDummyImpl.h
  32. 8 10
      dtool/src/dtoolbase/mutexPosixImpl.I
  33. 15 1
      dtool/src/dtoolbase/mutexPosixImpl.h
  34. 2 10
      dtool/src/dtoolbase/mutexSpinlockImpl.I
  35. 6 2
      dtool/src/dtoolbase/mutexSpinlockImpl.h
  36. 5 0
      dtool/src/dtoolbase/mutexWin32Impl.h
  37. 25 26
      dtool/src/dtoolbase/pallocator.T
  38. 4 4
      dtool/src/dtoolbase/pallocator.h
  39. 0 1
      dtool/src/dtoolbase/pdeque.h
  40. 0 1
      dtool/src/dtoolbase/plist.h
  41. 0 4
      dtool/src/dtoolbase/pmap.h
  42. 0 4
      dtool/src/dtoolbase/pset.h
  43. 0 15
      dtool/src/dtoolbase/pvector.h
  44. 0 21
      dtool/src/dtoolbase/typedObject.I
  45. 37 17
      dtool/src/dtoolbase/typedObject.h
  46. 10 1
      dtool/src/interrogate/functionRemap.cxx
  47. 1 0
      dtool/src/interrogate/functionRemap.h
  48. 32 11
      dtool/src/interrogate/interfaceMakerPythonNative.cxx
  49. 3 0
      dtool/src/prc/streamWrapper.h
  50. 1 1
      dtool/src/prckeys/makePrcKey.cxx
  51. 14 0
      dtool/src/pystub/pystub.cxx
  52. 145 128
      makepanda/makepanda.py
  53. 21 17
      makepanda/makepandacore.py
  54. 21 73
      panda/src/display/displayInformation.cxx
  55. 5 13
      panda/src/display/displayInformation.h
  56. 157 16
      panda/src/display/graphicsPipe.cxx
  57. 2 2
      panda/src/display/graphicsPipe.h
  58. 5 2
      panda/src/display/graphicsStateGuardian.cxx
  59. 8 0
      panda/src/downloader/httpChannel.cxx
  60. 4 27
      panda/src/express/datagramIterator.I
  61. 0 3
      panda/src/express/datagramIterator.h
  62. 0 7
      panda/src/express/hashGeneratorBase.I
  63. 0 1
      panda/src/express/hashGeneratorBase.h
  64. 0 29
      panda/src/express/namable.I
  65. 0 6
      panda/src/express/namable.h
  66. 0 20
      panda/src/express/nodePointerTo.I
  67. 0 2
      panda/src/express/nodePointerTo.h
  68. 0 70
      panda/src/express/ordered_vector.I
  69. 0 7
      panda/src/express/ordered_vector.h
  70. 18 34
      panda/src/express/pointerTo.I
  71. 55 41
      panda/src/express/pointerTo.h
  72. 22 0
      panda/src/express/pointerToArray.I
  73. 2 0
      panda/src/express/pointerToArray.h
  74. 4 13
      panda/src/express/pointerToArrayBase.I
  75. 1 2
      panda/src/express/pointerToArrayBase.h
  76. 1 1
      panda/src/express/pointerToBase.h
  77. 8 17
      panda/src/express/pointerToVoid.I
  78. 4 4
      panda/src/express/pointerToVoid.h
  79. 3 10
      panda/src/express/weakPointerToVoid.I
  80. 0 1
      panda/src/express/weakPointerToVoid.h
  81. 18 10
      panda/src/gobj/vertexDataBuffer.I
  82. 2 2
      panda/src/parametrics/parametricCurveCollection.h
  83. 2 0
      panda/src/pgraph/nodePath.h
  84. 216 0
      panda/src/pgraph/nodePath_ext.cxx
  85. 2 0
      panda/src/pgraph/nodePath_ext.h
  86. 3 0
      panda/src/pgraph/shaderAttrib.h
  87. 0 27
      panda/src/putil/bitArray.I
  88. 0 4
      panda/src/putil/bitArray.h
  89. 0 28
      panda/src/putil/bitMask.I
  90. 0 4
      panda/src/putil/bitMask.h
  91. 0 7
      panda/src/putil/buttonHandle.I
  92. 0 1
      panda/src/putil/buttonHandle.h
  93. 4 6
      panda/src/putil/iterator_types.h
  94. 3 28
      panda/src/putil/sparseArray.I
  95. 0 4
      panda/src/putil/sparseArray.h
  96. 0 16
      panda/src/putil/writableParam.I
  97. 1 2
      panda/src/putil/writableParam.h
  98. 2 493
      panda/src/windisplay/winGraphicsPipe.cxx

+ 7 - 7
README.md

@@ -31,8 +31,8 @@ are included as part of the Windows 7.1 SDK.
 You will also need to have the third-party dependency libraries available for
 the build scripts to use.  These are available from one of these two URLs,
 depending on whether you are on a 32-bit or 64-bit system:
-https://www.panda3d.org/download/panda3d-1.9.2/panda3d-1.9.2-tools-win32.zip
-https://www.panda3d.org/download/panda3d-1.9.2/panda3d-1.9.2-tools-win64.zip
+https://www.panda3d.org/download/panda3d-1.9.3/panda3d-1.9.3-tools-win32.zip
+https://www.panda3d.org/download/panda3d-1.9.3/panda3d-1.9.3-tools-win64.zip
 
 After acquiring these dependencies, you may simply build Panda3D from the
 command prompt using the following command:
@@ -93,11 +93,11 @@ may have to use the installpanda.py script instead, which will directly copy the
 files into the appropriate locations on your computer.  You may have to run the
 `ldconfig` tool in order to update your library cache after installing Panda3D.
 
-Mac OS X
---------
+macOS
+-----
 
-On Mac OS X, you will need to download a set of precompiled thirdparty packages in order to
-compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.9.2/panda3d-1.9.2-tools-mac.tar.gz).
+On macOS, you will need to download a set of precompiled thirdparty packages in order to
+compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.9.3/panda3d-1.9.3-tools-mac.tar.gz).
 
 After placing the thirdparty directory inside the panda3d source directory,
 you may build Panda3D using a command like the following:
@@ -107,7 +107,7 @@ python makepanda/makepanda.py --everything --installer
 ```
 
 In order to make a universal build, pass the --universal flag.  You may also
-target a specific minimum Mac OS X version using the --osxtarget flag followed
+target a specific minimum macOS version using the --osxtarget flag followed
 by the release number, eg. 10.6 or 10.7.
 
 If the build was successful, makepanda will have generated a .dmg file in

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

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

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

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

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

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

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

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

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

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

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 483 - 469
dtool/src/cppparser/cppBison.cxx.prebuilt


+ 198 - 194
dtool/src/cppparser/cppBison.h.prebuilt

@@ -89,103 +89,105 @@ extern int cppyydebug;
     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
+    ATTR_LEFT = 302,
+    ATTR_RIGHT = 303,
+    KW_ALIGNAS = 304,
+    KW_ALIGNOF = 305,
+    KW_AUTO = 306,
+    KW_BEGIN_PUBLISH = 307,
+    KW_BLOCKING = 308,
+    KW_BOOL = 309,
+    KW_CATCH = 310,
+    KW_CHAR = 311,
+    KW_CHAR16_T = 312,
+    KW_CHAR32_T = 313,
+    KW_CLASS = 314,
+    KW_CONST = 315,
+    KW_CONSTEXPR = 316,
+    KW_CONST_CAST = 317,
+    KW_DECLTYPE = 318,
+    KW_DEFAULT = 319,
+    KW_DELETE = 320,
+    KW_DOUBLE = 321,
+    KW_DYNAMIC_CAST = 322,
+    KW_ELSE = 323,
+    KW_END_PUBLISH = 324,
+    KW_ENUM = 325,
+    KW_EXTENSION = 326,
+    KW_EXTERN = 327,
+    KW_EXPLICIT = 328,
+    KW_PUBLISHED = 329,
+    KW_FALSE = 330,
+    KW_FINAL = 331,
+    KW_FLOAT = 332,
+    KW_FRIEND = 333,
+    KW_FOR = 334,
+    KW_GOTO = 335,
+    KW_HAS_VIRTUAL_DESTRUCTOR = 336,
+    KW_IF = 337,
+    KW_INLINE = 338,
+    KW_INT = 339,
+    KW_IS_ABSTRACT = 340,
+    KW_IS_BASE_OF = 341,
+    KW_IS_CLASS = 342,
+    KW_IS_CONSTRUCTIBLE = 343,
+    KW_IS_CONVERTIBLE_TO = 344,
+    KW_IS_DESTRUCTIBLE = 345,
+    KW_IS_EMPTY = 346,
+    KW_IS_ENUM = 347,
+    KW_IS_FINAL = 348,
+    KW_IS_FUNDAMENTAL = 349,
+    KW_IS_POD = 350,
+    KW_IS_POLYMORPHIC = 351,
+    KW_IS_STANDARD_LAYOUT = 352,
+    KW_IS_TRIVIAL = 353,
+    KW_IS_UNION = 354,
+    KW_LONG = 355,
+    KW_MAKE_MAP_PROPERTY = 356,
+    KW_MAKE_PROPERTY = 357,
+    KW_MAKE_PROPERTY2 = 358,
+    KW_MAKE_SEQ = 359,
+    KW_MAKE_SEQ_PROPERTY = 360,
+    KW_MUTABLE = 361,
+    KW_NAMESPACE = 362,
+    KW_NEW = 363,
+    KW_NOEXCEPT = 364,
+    KW_NULLPTR = 365,
+    KW_OPERATOR = 366,
+    KW_OVERRIDE = 367,
+    KW_PRIVATE = 368,
+    KW_PROTECTED = 369,
+    KW_PUBLIC = 370,
+    KW_REGISTER = 371,
+    KW_REINTERPRET_CAST = 372,
+    KW_RETURN = 373,
+    KW_SHORT = 374,
+    KW_SIGNED = 375,
+    KW_SIZEOF = 376,
+    KW_STATIC = 377,
+    KW_STATIC_ASSERT = 378,
+    KW_STATIC_CAST = 379,
+    KW_STRUCT = 380,
+    KW_TEMPLATE = 381,
+    KW_THREAD_LOCAL = 382,
+    KW_THROW = 383,
+    KW_TRUE = 384,
+    KW_TRY = 385,
+    KW_TYPEDEF = 386,
+    KW_TYPEID = 387,
+    KW_TYPENAME = 388,
+    KW_UNDERLYING_TYPE = 389,
+    KW_UNION = 390,
+    KW_UNSIGNED = 391,
+    KW_USING = 392,
+    KW_VIRTUAL = 393,
+    KW_VOID = 394,
+    KW_VOLATILE = 395,
+    KW_WCHAR_T = 396,
+    KW_WHILE = 397,
+    START_CPP = 398,
+    START_CONST_EXPR = 399,
+    START_TYPE = 400
   };
 #endif
 /* Tokens.  */
@@ -233,103 +235,105 @@ extern int cppyydebug;
 #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
+#define ATTR_LEFT 302
+#define ATTR_RIGHT 303
+#define KW_ALIGNAS 304
+#define KW_ALIGNOF 305
+#define KW_AUTO 306
+#define KW_BEGIN_PUBLISH 307
+#define KW_BLOCKING 308
+#define KW_BOOL 309
+#define KW_CATCH 310
+#define KW_CHAR 311
+#define KW_CHAR16_T 312
+#define KW_CHAR32_T 313
+#define KW_CLASS 314
+#define KW_CONST 315
+#define KW_CONSTEXPR 316
+#define KW_CONST_CAST 317
+#define KW_DECLTYPE 318
+#define KW_DEFAULT 319
+#define KW_DELETE 320
+#define KW_DOUBLE 321
+#define KW_DYNAMIC_CAST 322
+#define KW_ELSE 323
+#define KW_END_PUBLISH 324
+#define KW_ENUM 325
+#define KW_EXTENSION 326
+#define KW_EXTERN 327
+#define KW_EXPLICIT 328
+#define KW_PUBLISHED 329
+#define KW_FALSE 330
+#define KW_FINAL 331
+#define KW_FLOAT 332
+#define KW_FRIEND 333
+#define KW_FOR 334
+#define KW_GOTO 335
+#define KW_HAS_VIRTUAL_DESTRUCTOR 336
+#define KW_IF 337
+#define KW_INLINE 338
+#define KW_INT 339
+#define KW_IS_ABSTRACT 340
+#define KW_IS_BASE_OF 341
+#define KW_IS_CLASS 342
+#define KW_IS_CONSTRUCTIBLE 343
+#define KW_IS_CONVERTIBLE_TO 344
+#define KW_IS_DESTRUCTIBLE 345
+#define KW_IS_EMPTY 346
+#define KW_IS_ENUM 347
+#define KW_IS_FINAL 348
+#define KW_IS_FUNDAMENTAL 349
+#define KW_IS_POD 350
+#define KW_IS_POLYMORPHIC 351
+#define KW_IS_STANDARD_LAYOUT 352
+#define KW_IS_TRIVIAL 353
+#define KW_IS_UNION 354
+#define KW_LONG 355
+#define KW_MAKE_MAP_PROPERTY 356
+#define KW_MAKE_PROPERTY 357
+#define KW_MAKE_PROPERTY2 358
+#define KW_MAKE_SEQ 359
+#define KW_MAKE_SEQ_PROPERTY 360
+#define KW_MUTABLE 361
+#define KW_NAMESPACE 362
+#define KW_NEW 363
+#define KW_NOEXCEPT 364
+#define KW_NULLPTR 365
+#define KW_OPERATOR 366
+#define KW_OVERRIDE 367
+#define KW_PRIVATE 368
+#define KW_PROTECTED 369
+#define KW_PUBLIC 370
+#define KW_REGISTER 371
+#define KW_REINTERPRET_CAST 372
+#define KW_RETURN 373
+#define KW_SHORT 374
+#define KW_SIGNED 375
+#define KW_SIZEOF 376
+#define KW_STATIC 377
+#define KW_STATIC_ASSERT 378
+#define KW_STATIC_CAST 379
+#define KW_STRUCT 380
+#define KW_TEMPLATE 381
+#define KW_THREAD_LOCAL 382
+#define KW_THROW 383
+#define KW_TRUE 384
+#define KW_TRY 385
+#define KW_TYPEDEF 386
+#define KW_TYPEID 387
+#define KW_TYPENAME 388
+#define KW_UNDERLYING_TYPE 389
+#define KW_UNION 390
+#define KW_UNSIGNED 391
+#define KW_USING 392
+#define KW_VIRTUAL 393
+#define KW_VOID 394
+#define KW_VOLATILE 395
+#define KW_WCHAR_T 396
+#define KW_WHILE 397
+#define START_CPP 398
+#define START_CONST_EXPR 399
+#define START_TYPE 400
 
 /* Value type.  */
 

+ 183 - 38
dtool/src/cppparser/cppBison.yxx

@@ -8,6 +8,7 @@
 
 #include "cppBisonDefs.h"
 #include "cppParser.h"
+#include "cppClosureType.h"
 #include "cppExpression.h"
 #include "cppSimpleType.h"
 #include "cppExtensionType.h"
@@ -44,6 +45,7 @@ static CPPEnumType *current_enum = NULL;
 static int current_storage_class = 0;
 static CPPType *current_type = NULL;
 static CPPExpression *current_expr = NULL;
+static CPPClosureType *current_closure = NULL;
 static int publish_nest_level = 0;
 static CPPVisibility publish_previous;
 static YYLTYPE publish_loc;
@@ -247,6 +249,8 @@ pop_struct() {
 %token XOREQUAL
 %token LSHIFTEQUAL
 %token RSHIFTEQUAL
+%token ATTR_LEFT
+%token ATTR_RIGHT
 
 %token KW_ALIGNAS
 %token KW_ALIGNOF
@@ -363,6 +367,8 @@ pop_struct() {
 %type <u.param_list> function_parameters
 %type <u.param_list> formal_parameter_list
 %type <u.param_list> formal_parameters
+%type <u.closure_type> capture_list
+%type <u.capture> capture
 %type <u.expr> template_parameter_maybe_initialize
 %type <u.expr> maybe_initialize
 %type <u.expr> maybe_initialize_or_constructor_body
@@ -870,10 +876,18 @@ storage_class:
 {
   $$ = $2 | (int)CPPInstance::SC_thread_local;
 }
-        | '[' '[' attribute_specifiers ']' ']' storage_class
+        | ATTR_LEFT attribute_specifiers ATTR_RIGHT storage_class
 {
   // Ignore attribute specifiers for now.
-  $$ = $6;
+  $$ = $4;
+}
+        | KW_ALIGNAS '(' const_expr ')' storage_class
+{
+  $$ = $5;
+}
+        | KW_ALIGNAS '(' type_decl ')' storage_class
+{
+  $$ = $5;
 }
         ;
 
@@ -885,6 +899,7 @@ attribute_specifiers:
 attribute_specifier:
         name
         | name '(' formal_parameter_list ')'
+        | KW_USING name ':' attribute_specifier
         ;
 
 type_like_declaration:
@@ -1221,6 +1236,15 @@ function_post:
 {
   $$ = $1 | (int)CPPFunctionType::F_noexcept;
 }
+/*        | function_post KW_NOEXCEPT '(' const_expr ')'
+{
+  CPPExpression::Result result = $4->evaluate();
+  if (result._type == CPPExpression::RT_error) {
+    yywarning("noexcept requires a constant expression", @4);
+  } else if (result.as_boolean()) {
+    $$ = $1 | (int)CPPFunctionType::F_noexcept;
+  }
+}*/
         | function_post KW_FINAL
 {
   $$ = $1 | (int)CPPFunctionType::F_final;
@@ -1241,6 +1265,11 @@ function_post:
 {
   // Used for lambdas, currently ignored.
   $$ = $1;
+}
+        | function_post KW_CONSTEXPR
+{
+  // Used for lambdas in C++17, currently ignored.
+  $$ = $1;
 }
         | function_post KW_THROW '(' ')'
 {
@@ -1254,10 +1283,10 @@ function_post:
 {
   $$ = $1;
 }
-/*        | function_post '[' '[' attribute_specifiers ']' ']'
+        | function_post ATTR_LEFT attribute_specifiers ATTR_RIGHT
 {
   $$ = $1;
-}*/
+}
         ;
 
 function_operator:
@@ -1422,10 +1451,12 @@ function_operator:
 more_template_declaration:
         type_like_declaration
         | template_declaration
+        | friend_declaration
         ;
 
 template_declaration:
-        KW_TEMPLATE
+        KW_EXTERN template_declaration
+        | KW_TEMPLATE
 {
   push_scope(new CPPTemplateScope(current_scope));
 }
@@ -1433,7 +1464,8 @@ template_declaration:
 {
   pop_scope();
 }
-	| KW_TEMPLATE type_like_declaration
+        | KW_TEMPLATE type_like_declaration
+        | KW_TEMPLATE friend_declaration
         ;
 
 template_formal_parameters:
@@ -1885,6 +1917,10 @@ function_parameter:
         | KW_REGISTER function_parameter
 {
   $$ = $2;
+}
+        | ATTR_LEFT attribute_specifiers ATTR_RIGHT function_parameter
+{
+  $$ = $4;
 }
         ;
 
@@ -2228,16 +2264,16 @@ type:
 {
   $$ = CPPType::new_type($1);
 }
-        | struct_keyword name
+        | struct_keyword struct_attributes name
 {
-  CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
+  CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer);
   if (type != NULL) {
     $$ = type;
   } else {
     CPPExtensionType *et =
-      CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
+      CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file))
       ->as_extension_type();
-    CPPScope *scope = $2->get_scope(current_scope, global_scope);
+    CPPScope *scope = $3->get_scope(current_scope, global_scope);
     if (scope != NULL) {
       scope->define_extension_type(et);
     }
@@ -2268,6 +2304,10 @@ type:
     str << *$3;
     yyerror("could not determine type of " + str.str(), @3);
   }
+}
+        | KW_DECLTYPE '(' KW_AUTO ')'
+{
+  $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto));
 }
         | KW_UNDERLYING_TYPE '(' full_type ')'
 {
@@ -2325,16 +2365,16 @@ type_decl:
 {
   $$ = new CPPTypeDeclaration(CPPType::new_type($1));
 }
-        | struct_keyword name
+        | struct_keyword struct_attributes name
 {
-  CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
+  CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer);
   if (type != NULL) {
     $$ = type;
   } else {
     CPPExtensionType *et =
-      CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
+      CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file))
       ->as_extension_type();
-    CPPScope *scope = $2->get_scope(current_scope, global_scope);
+    CPPScope *scope = $3->get_scope(current_scope, global_scope);
     if (scope != NULL) {
       scope->define_extension_type(et);
     }
@@ -2383,6 +2423,10 @@ type_decl:
     str << *$3;
     yyerror("could not determine type of " + str.str(), @3);
   }
+}
+        | KW_DECLTYPE '(' KW_AUTO ')'
+{
+  $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto));
 }
         | KW_UNDERLYING_TYPE '(' full_type ')'
 {
@@ -2417,16 +2461,16 @@ predefined_type:
 {
   $$ = CPPType::new_type(new CPPTBDType($2));
 }
-        | struct_keyword name
+        | struct_keyword struct_attributes name
 {
-  CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
+  CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer);
   if (type != NULL) {
     $$ = type;
   } else {
     CPPExtensionType *et =
-      CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
+      CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file))
       ->as_extension_type();
-    CPPScope *scope = $2->get_scope(current_scope, global_scope);
+    CPPScope *scope = $3->get_scope(current_scope, global_scope);
     if (scope != NULL) {
       scope->define_extension_type(et);
     }
@@ -2507,8 +2551,15 @@ full_type:
 }
         ;
 
+struct_attributes:
+        empty
+        | struct_attributes ATTR_LEFT attribute_specifiers ATTR_RIGHT
+        | struct_attributes KW_ALIGNAS '(' const_expr ')'
+        | struct_attributes KW_ALIGNAS '(' type_decl ')'
+        ;
+
 anonymous_struct:
-        struct_keyword '{'
+        struct_keyword struct_attributes '{'
 {
   CPPVisibility starting_vis =
   ($1 == CPPExtensionType::T_class) ? V_private : V_public;
@@ -2532,19 +2583,19 @@ anonymous_struct:
         ;
 
 named_struct:
-        struct_keyword name_no_final
+        struct_keyword struct_attributes name_no_final
 {
   CPPVisibility starting_vis =
   ($1 == CPPExtensionType::T_class) ? V_private : V_public;
 
-  CPPScope *scope = $2->get_scope(current_scope, global_scope, current_lexer);
+  CPPScope *scope = $3->get_scope(current_scope, global_scope, current_lexer);
   if (scope == NULL) {
     scope = current_scope;
   }
-  CPPScope *new_scope = new CPPScope(scope, $2->_names.back(),
+  CPPScope *new_scope = new CPPScope(scope, $3->_names.back(),
                                      starting_vis);
 
-  CPPStructType *st = new CPPStructType($1, $2, current_scope,
+  CPPStructType *st = new CPPStructType($1, $3, current_scope,
                                         new_scope, @1.file);
   new_scope->set_struct_type(st);
   current_scope->define_extension_type(st);
@@ -2927,6 +2978,7 @@ element:
         | SCOPE | PLUSPLUS | MINUSMINUS
         | TIMESEQUAL | DIVIDEEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL
         | OREQUAL | ANDEQUAL | XOREQUAL | LSHIFTEQUAL | RSHIFTEQUAL
+        | ATTR_LEFT | ATTR_RIGHT
         | KW_ALIGNAS | KW_ALIGNOF | KW_AUTO | KW_BOOL | KW_CATCH
         | KW_CHAR | KW_CHAR16_T | KW_CHAR32_T | KW_CLASS | KW_CONST
         | KW_CONSTEXPR | KW_CONST_CAST | KW_DECLTYPE | KW_DEFAULT
@@ -3010,6 +3062,18 @@ no_angle_bracket_const_expr:
         | KW_SIZEOF '(' full_type ')' %prec UNARY
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
+}
+        | KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
+{
+  CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
+  if (arg == (CPPDeclaration *)NULL) {
+    yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
+  } else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
+    CPPInstance *inst = arg->as_instance();
+    $$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
+  } else {
+    $$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
+  }
 }
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
 {
@@ -3172,6 +3236,16 @@ const_expr:
   }
   assert(type != NULL);
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+        | TYPENAME_IDENTIFIER '{' optional_const_expr_comma '}'
+{
+  // Aggregate initialization.
+  CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
+  if (type == NULL) {
+    yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
+  }
+  assert(type != NULL);
+  $$ = new CPPExpression(CPPExpression::aggregate_init_op(type, $3));
 }
         | KW_INT '(' optional_const_expr_comma ')'
 {
@@ -3252,6 +3326,18 @@ const_expr:
         | KW_SIZEOF '(' full_type ')' %prec UNARY
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
+}
+        | KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
+{
+  CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
+  if (arg == (CPPDeclaration *)NULL) {
+    yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
+  } else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
+    CPPInstance *inst = arg->as_instance();
+    $$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
+  } else {
+    $$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
+  }
 }
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
 {
@@ -3468,11 +3554,16 @@ const_operand:
 }
         | '[' capture_list ']' function_post maybe_trailing_return_type '{' code '}'
 {
-  $$ = NULL;
+  $2->_flags = $4;
+  $2->_return_type = $5;
+  $$ = new CPPExpression(CPPExpression::lambda($2));
 }
         | '[' capture_list ']' '(' function_parameter_list ')' function_post maybe_trailing_return_type '{' code '}'
 {
-  $$ = NULL;
+  $2->_parameters = $5;
+  $2->_flags = $7;
+  $2->_return_type = $8;
+  $$ = new CPPExpression(CPPExpression::lambda($2));
 }
         | KW_HAS_VIRTUAL_DESTRUCTOR '(' full_type ')'
 {
@@ -3579,6 +3670,18 @@ formal_const_expr:
         | KW_SIZEOF '(' full_type ')' %prec UNARY
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
+}
+        | KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
+{
+  CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
+  if (arg == (CPPDeclaration *)NULL) {
+    yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
+  } else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
+    CPPInstance *inst = arg->as_instance();
+    $$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
+  } else {
+    $$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
+  }
 }
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
 {
@@ -3794,15 +3897,65 @@ formal_const_operand:
 /* The contents of the [] list preceding a lambda expression. */
 capture_list:
         empty
-        | capture
-        | capture ',' capture_list
+{
+  $$ = new CPPClosureType();
+}
+        | '='
+{
+  $$ = new CPPClosureType(CPPClosureType::CT_by_value);
+}
+        | '&'
+{
+  $$ = new CPPClosureType(CPPClosureType::CT_by_reference);
+}
+        | capture maybe_initialize
+{
+  $$ = new CPPClosureType();
+  $1->_initializer = $2;
+  $$->_captures.push_back(*$1);
+  delete $1;
+}
+        | capture_list ',' capture maybe_initialize
+{
+  $$ = $1;
+  $3->_initializer = $4;
+  $$->_captures.push_back(*$3);
+  delete $3;
+}
         ;
 
 capture:
-        '&'
-        | '='
-        | '&' name
+        '&' name
+{
+  $$ = new CPPClosureType::Capture;
+  $$->_name = $2->get_simple_name();
+  $$->_type = CPPClosureType::CT_by_reference;
+}
+        | '&' name ELLIPSIS
+{
+  $$ = new CPPClosureType::Capture;
+  $$->_name = $2->get_simple_name();
+  $$->_type = CPPClosureType::CT_by_reference;
+}
         | name
+{
+  $$ = new CPPClosureType::Capture;
+  $$->_name = $1->get_simple_name();
+  if ($$->_name == "this") {
+    $$->_type = CPPClosureType::CT_by_reference;
+  } else {
+    $$->_type = CPPClosureType::CT_by_value;
+  }
+}
+        | '*' name
+{
+  $$ = new CPPClosureType::Capture;
+  $$->_name = $2->get_simple_name();
+  $$->_type = CPPClosureType::CT_by_value;
+  if ($$->_name != "this") {
+    yywarning("only capture name 'this' may be preceded by an asterisk", @2);
+  }
+}
         ;
 
 class_derivation_name:
@@ -3813,14 +3966,6 @@ class_derivation_name:
     type = CPPType::new_type(new CPPTBDType($1));
   }
   $$ = type;
-}
-        | struct_keyword name
-{
-  CPPType *type = $2->find_type(current_scope, global_scope, true, current_lexer);
-  if (type == NULL) {
-    type = CPPType::new_type(new CPPTBDType($2));
-  }
-  $$ = type;
 }
         | KW_TYPENAME name
 {

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

@@ -23,6 +23,7 @@
 
 #include <string>
 
+#include "cppClosureType.h"
 #include "cppExtensionType.h"
 #include "cppFile.h"
 
@@ -42,6 +43,7 @@ class CPPParameterList;
 class CPPTemplateParameterList;
 class CPPScope;
 class CPPIdentifier;
+class CPPCaptureType;
 
 void parse_cpp(CPPParser *cp);
 CPPExpression *parse_const_expr(CPPPreprocessor *pp,
@@ -81,6 +83,8 @@ public:
     CPPExtensionType::Type extension_enum;
     CPPExpression *expr;
     CPPIdentifier *identifier;
+    CPPClosureType *closure_type;
+    CPPClosureType::Capture *capture;
   } u;
 };
 #define YYSTYPE cppyystype

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

@@ -0,0 +1,196 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file cppClosureType.cxx
+ * @author rdb
+ * @date 2017-01-14
+ */
+
+#include "cppClosureType.h"
+#include "cppParameterList.h"
+#include "cppExpression.h"
+
+/**
+ *
+ */
+CPPClosureType::
+CPPClosureType(CaptureType default_capture) :
+  CPPFunctionType(NULL, NULL, 0),
+  _default_capture(default_capture) {
+}
+
+/**
+ *
+ */
+CPPClosureType::
+CPPClosureType(const CPPClosureType &copy) :
+  CPPFunctionType(copy),
+  _captures(copy._captures),
+  _default_capture(copy._default_capture)
+{
+}
+
+/**
+ *
+ */
+void CPPClosureType::
+operator = (const CPPClosureType &copy) {
+  CPPFunctionType::operator = (copy);
+  _captures = copy._captures;
+  _default_capture = copy._default_capture;
+}
+
+/**
+ * Adds a new capture to the beginning of the capture list.
+ */
+void CPPClosureType::
+add_capture(string name, CaptureType type, CPPExpression *initializer) {
+  if (type == CT_none) {
+    if (name == "this") {
+      type = CT_by_reference;
+    } else {
+      type = CT_by_value;
+    }
+  }
+
+  Capture capture = {move(name), type, initializer};
+  _captures.insert(_captures.begin(), move(capture));
+}
+
+/**
+ * Returns true if this declaration is an actual, factual declaration, or
+ * false if some part of the declaration depends on a template parameter which
+ * has not yet been instantiated.
+ */
+bool CPPClosureType::
+is_fully_specified() const {
+  return CPPFunctionType::is_fully_specified();
+}
+
+/**
+ * Returns true if the type is default-constructible.
+ */
+bool CPPClosureType::
+is_default_constructible() const {
+  return false;
+}
+
+/**
+ * Returns true if the type is copy-constructible.
+ */
+bool CPPClosureType::
+is_copy_constructible() const {
+  return true;
+}
+
+/**
+ * Returns true if the type is destructible.
+ */
+bool CPPClosureType::
+is_destructible() const {
+  return true;
+}
+
+/**
+ *
+ */
+void CPPClosureType::
+output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
+  out.put('[');
+
+  bool have_capture = false;
+  switch (_default_capture) {
+  case CT_none:
+    break;
+  case CT_by_reference:
+    out.put('&');
+    have_capture = true;
+    break;
+  case CT_by_value:
+    out.put('=');
+    have_capture = true;
+    break;
+  }
+
+  Captures::const_iterator it;
+  for (it = _captures.begin(); it != _captures.end(); ++it) {
+    const Capture &capture = *it;
+    if (have_capture) {
+      out << ", ";
+    }
+    if (capture._name == "this") {
+      if (capture._type == CT_by_value) {
+        out.put('*');
+      }
+    } else {
+      if (capture._type == CT_by_reference) {
+        out.put('&');
+      }
+    }
+    out << capture._name;
+
+    if (capture._initializer != NULL) {
+      out << " = " << *capture._initializer;
+    }
+
+    have_capture = true;
+  }
+  out.put(']');
+
+  if (_parameters != NULL) {
+    out.put('(');
+    _parameters->output(out, scope, true, -1);
+    out.put(')');
+  }
+
+  if (_flags & F_noexcept) {
+    out << " noexcept";
+  }
+
+  if (_return_type != NULL) {
+    out << " -> ";
+    _return_type->output(out, indent_level, scope, false);
+  }
+
+  out << " {}";
+}
+
+/**
+ *
+ */
+CPPDeclaration::SubType CPPClosureType::
+get_subtype() const {
+  return ST_closure;
+}
+
+/**
+ *
+ */
+CPPClosureType *CPPClosureType::
+as_closure_type() {
+  return this;
+}
+
+/**
+ * Called by CPPDeclaration() to determine whether this type is equivalent to
+ * another type of the same type.
+ */
+bool CPPClosureType::
+is_equal(const CPPDeclaration *other) const {
+  return (this == other);
+}
+
+
+/**
+ * Called by CPPDeclaration() to determine whether this type should be ordered
+ * before another type of the same type, in an arbitrary but fixed ordering.
+ */
+bool CPPClosureType::
+is_less(const CPPDeclaration *other) const {
+  return (this < other);
+}

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

@@ -0,0 +1,65 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file cppClosureType.h
+ * @author rdb
+ * @date 2017-01-14
+ */
+
+#ifndef CPPCLOSURETYPE_H
+#define CPPCLOSURETYPE_H
+
+#include "dtoolbase.h"
+
+#include "cppFunctionType.h"
+
+/**
+ * The type of a lambda expression.  This is like a function, but with
+ * additional captures defined.
+ */
+class CPPClosureType : public CPPFunctionType {
+public:
+  enum CaptureType {
+    CT_none,
+    CT_by_reference,
+    CT_by_value,
+  };
+
+  CPPClosureType(CaptureType default_capture = CT_none);
+  CPPClosureType(const CPPClosureType &copy);
+  void operator = (const CPPClosureType &copy);
+
+  struct Capture {
+    string _name;
+    CaptureType _type;
+    CPPExpression *_initializer;
+  };
+  typedef vector<Capture> Captures;
+  Captures _captures;
+
+  CaptureType _default_capture;
+
+  void add_capture(string name, CaptureType type, CPPExpression *initializer = NULL);
+
+  virtual bool is_fully_specified() const;
+
+  virtual bool is_default_constructible() const;
+  virtual bool is_copy_constructible() const;
+  virtual bool is_destructible() const;
+
+  virtual void output(ostream &out, int indent_level, CPPScope *scope,
+                      bool complete) const;
+  virtual SubType get_subtype() const;
+  virtual CPPClosureType *as_closure_type();
+
+protected:
+  virtual bool is_equal(const CPPDeclaration *other) const;
+  virtual bool is_less(const CPPDeclaration *other) const;
+};
+
+#endif

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

@@ -311,6 +311,14 @@ as_make_seq() {
   return (CPPMakeSeq *)NULL;
 }
 
+/**
+ *
+ */
+CPPClosureType *CPPDeclaration::
+as_closure_type() {
+  return (CPPClosureType *)NULL;
+}
+
 /**
  * Called by CPPDeclaration to determine whether this type is equivalent to
  * another type of the same type.

+ 6 - 0
dtool/src/cppparser/cppDeclaration.h

@@ -48,6 +48,7 @@ class CPPEnumType;
 class CPPTypeProxy;
 class CPPMakeProperty;
 class CPPMakeSeq;
+class CPPClosureType;
 class CPPClassTemplateParameter;
 class CPPTBDType;
 class CPPScope;
@@ -85,6 +86,7 @@ public:
     ST_tbd,
     ST_type_proxy,
     ST_typedef,
+    ST_closure,
   };
 
   CPPDeclaration(const CPPFile &file);
@@ -140,6 +142,7 @@ public:
   virtual CPPTypeProxy *as_type_proxy();
   virtual CPPMakeProperty *as_make_property();
   virtual CPPMakeSeq *as_make_seq();
+  virtual CPPClosureType *as_closure_type();
 
   inline const CPPInstance *as_instance() const {
     return ((CPPDeclaration *)this)->as_instance();
@@ -207,6 +210,9 @@ public:
   inline const CPPMakeSeq *as_make_seq() const {
     return ((CPPDeclaration *)this)->as_make_seq();
   }
+  inline const CPPClosureType *as_closure_type() const {
+    return ((CPPDeclaration *)this)->as_closure_type();
+  }
 
   CPPVisibility _vis;
   CPPTemplateScope *_template_scope;

+ 97 - 3
dtool/src/cppparser/cppExpression.cxx

@@ -24,6 +24,7 @@
 #include "cppInstance.h"
 #include "cppFunctionGroup.h"
 #include "cppFunctionType.h"
+#include "cppClosureType.h"
 #include "cppStructType.h"
 #include "cppBison.h"
 #include "pdtoa.h"
@@ -256,13 +257,12 @@ CPPExpression(CPPIdentifier *ident, CPPScope *current_scope,
       _u._variable = inst;
       return;
     }
-    // Actually, we can't scope function groups.
-    /*CPPFunctionGroup *fgroup = decl->as_function_group();
+    CPPFunctionGroup *fgroup = decl->as_function_group();
     if (fgroup != NULL) {
       _type = T_function;
       _u._fgroup = fgroup;
       return;
-    }*/
+    }
   }
 
   _type = T_unknown_ident;
@@ -346,6 +346,22 @@ construct_op(CPPType *type, CPPExpression *op1) {
   return expr;
 }
 
+/**
+ * Creates an expression that represents an aggregate initialization.
+ */
+CPPExpression CPPExpression::
+aggregate_init_op(CPPType *type, CPPExpression *op1) {
+  CPPExpression expr(0);
+  if (op1 == NULL) {
+    expr._type = T_empty_aggregate_init;
+  } else {
+    expr._type = T_aggregate_init;
+  }
+  expr._u._typecast._to = type;
+  expr._u._typecast._op1 = op1;
+  return expr;
+}
+
 /**
  * Creates an expression that represents a use of the new operator.
  */
@@ -438,6 +454,17 @@ alignof_func(CPPType *type) {
   return expr;
 }
 
+/**
+ *
+ */
+CPPExpression CPPExpression::
+lambda(CPPClosureType *type) {
+  CPPExpression expr(0);
+  expr._type = T_lambda;
+  expr._u._closure_type = type;
+  return expr;
+}
+
 /**
  *
  */
@@ -594,6 +621,8 @@ evaluate() const {
 
   case T_construct:
   case T_default_construct:
+  case T_aggregate_init:
+  case T_empty_aggregate_init:
   case T_new:
   case T_default_new:
   case T_sizeof:
@@ -1017,6 +1046,8 @@ determine_type() const {
   case T_reinterpret_cast:
   case T_construct:
   case T_default_construct:
+  case T_aggregate_init:
+  case T_empty_aggregate_init:
     return _u._typecast._to;
 
   case T_new:
@@ -1135,10 +1166,28 @@ determine_type() const {
 
     case 'f': // Function evaluation
       if (t1 != NULL) {
+        // Easy case, function with only a single overload.
         CPPFunctionType *ftype = t1->as_function_type();
         if (ftype != (CPPFunctionType *)NULL) {
           return ftype->_return_type;
         }
+      } else if (_u._op._op1->_type == T_function) {
+        CPPFunctionGroup *fgroup = _u._op._op1->_u._fgroup;
+        if (_u._op._op2 == NULL) {
+          // If we are passing no args, look for an overload that has takes no
+          // args.
+          for (auto it = fgroup->_instances.begin(); it != fgroup->_instances.end(); ++it) {
+            CPPInstance *inst = *it;
+            if (inst != NULL && inst->_type != NULL) {
+              CPPFunctionType *type = inst->_type->as_function_type();
+              if (type != NULL && type->accepts_num_parameters(0)) {
+                return type->_return_type;
+              }
+            }
+          }
+        } else {
+          //TODO
+        }
       }
       return NULL;
 
@@ -1169,6 +1218,9 @@ determine_type() const {
   case T_type_trait:
     return bool_type;
 
+  case T_lambda:
+    return _u._closure_type;
+
   default:
     cerr << "**invalid operand**\n";
     abort();
@@ -1215,11 +1267,13 @@ is_fully_specified() const {
   case T_const_cast:
   case T_reinterpret_cast:
   case T_construct:
+  case T_aggregate_init:
   case T_new:
     return (_u._typecast._to->is_fully_specified() &&
             _u._typecast._op1->is_fully_specified());
 
   case T_default_construct:
+  case T_empty_aggregate_init:
   case T_default_new:
   case T_sizeof:
   case T_alignof:
@@ -1259,6 +1313,9 @@ is_fully_specified() const {
   case T_type_trait:
     return _u._type_trait._type->is_fully_specified();
 
+  case T_lambda:
+    return _u._closure_type->is_fully_specified();
+
   default:
     return true;
   }
@@ -1342,6 +1399,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
   case T_const_cast:
   case T_reinterpret_cast:
   case T_construct:
+  case T_aggregate_init:
   case T_new:
     rep->_u._typecast._op1 =
       _u._typecast._op1->substitute_decl(subst, current_scope, global_scope)
@@ -1350,6 +1408,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
     // fall through
 
   case T_default_construct:
+  case T_empty_aggregate_init:
   case T_default_new:
   case T_sizeof:
   case T_alignof:
@@ -1444,6 +1503,8 @@ is_tbd() const {
   case T_const_cast:
   case T_reinterpret_cast:
   case T_construct:
+  case T_aggregate_init:
+  case T_empty_aggregate_init:
   case T_new:
   case T_default_construct:
   case T_default_new:
@@ -1478,6 +1539,9 @@ is_tbd() const {
   case T_type_trait:
     return _u._type_trait._type->is_tbd();
 
+  case T_lambda:
+    return _u._closure_type->is_tbd();
+
   default:
     return false;
   }
@@ -1558,6 +1622,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
           out << "\\\"";
           break;
 
+        case '\\':
+          out << "\\\\";
+          break;
+
         default:
           if (isprint(*si)) {
             out << *si;
@@ -1649,6 +1717,18 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
     out << "()";
     break;
 
+  case T_aggregate_init:
+    _u._typecast._to->output(out, indent_level, scope, false);
+    out << "{";
+    _u._typecast._op1->output(out, indent_level, scope, false);
+    out << "}";
+    break;
+
+  case T_empty_aggregate_init:
+    _u._typecast._to->output(out, indent_level, scope, false);
+    out << "{}";
+    break;
+
   case T_new:
     out << "(new ";
     _u._typecast._to->output(out, indent_level, scope, false);
@@ -1946,6 +2026,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
     out << ')';
     break;
 
+  case T_lambda:
+    _u._closure_type->output(out, indent_level, scope, false);
+    break;
+
   default:
     out << "(** invalid operand type " << (int)_type << " **)";
   }
@@ -2066,11 +2150,13 @@ is_equal(const CPPDeclaration *other) const {
   case T_const_cast:
   case T_reinterpret_cast:
   case T_construct:
+  case T_aggregate_init:
   case T_new:
     return _u._typecast._to == ot->_u._typecast._to &&
       *_u._typecast._op1 == *ot->_u._typecast._op1;
 
   case T_default_construct:
+  case T_empty_aggregate_init:
   case T_default_new:
   case T_sizeof:
   case T_alignof:
@@ -2105,6 +2191,9 @@ is_equal(const CPPDeclaration *other) const {
     return _u._type_trait._trait == ot->_u._type_trait._trait &&
            _u._type_trait._type == ot->_u._type_trait._type;
 
+  case T_lambda:
+    return _u._closure_type == ot->_u._closure_type;
+
   default:
     cerr << "(** invalid operand type " << (int)_type << " **)";
   }
@@ -2161,6 +2250,7 @@ is_less(const CPPDeclaration *other) const {
   case T_const_cast:
   case T_reinterpret_cast:
   case T_construct:
+  case T_aggregate_init:
   case T_new:
     if (_u._typecast._to != ot->_u._typecast._to) {
       return _u._typecast._to < ot->_u._typecast._to;
@@ -2168,6 +2258,7 @@ is_less(const CPPDeclaration *other) const {
     return *_u._typecast._op1 < *ot->_u._typecast._op1;
 
   case T_default_construct:
+  case T_empty_aggregate_init:
   case T_default_new:
   case T_sizeof:
   case T_alignof:
@@ -2212,6 +2303,9 @@ is_less(const CPPDeclaration *other) const {
     }
     return *_u._type_trait._type < *ot->_u._type_trait._type;
 
+  case T_lambda:
+    return _u._closure_type < ot->_u._closure_type;
+
   default:
     cerr << "(** invalid operand type " << (int)_type << " **)";
   }

+ 6 - 0
dtool/src/cppparser/cppExpression.h

@@ -48,6 +48,8 @@ public:
     T_reinterpret_cast,
     T_construct,
     T_default_construct,
+    T_aggregate_init,
+    T_empty_aggregate_init,
     T_new,
     T_default_new,
     T_sizeof,
@@ -61,6 +63,7 @@ public:
     T_typeid_type,
     T_typeid_expr,
     T_type_trait,
+    T_lambda,
 
     // These are used when parsing =default and =delete methods.
     T_default,
@@ -80,6 +83,7 @@ public:
 
   static CPPExpression typecast_op(CPPType *type, CPPExpression *op1, Type cast_type = T_typecast);
   static CPPExpression construct_op(CPPType *type, CPPExpression *op1);
+  static CPPExpression aggregate_init_op(CPPType *type, CPPExpression *op1);
   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);
@@ -87,6 +91,7 @@ public:
   static CPPExpression sizeof_func(CPPType *type);
   static CPPExpression sizeof_ellipsis_func(CPPIdentifier *ident);
   static CPPExpression alignof_func(CPPType *type);
+  static CPPExpression lambda(CPPClosureType *type);
 
   static CPPExpression literal(unsigned long long value, CPPInstance *lit_op);
   static CPPExpression literal(long double value, CPPInstance *lit_op);
@@ -150,6 +155,7 @@ public:
     CPPInstance *_variable;
     CPPFunctionGroup *_fgroup;
     CPPIdentifier *_ident;
+    CPPClosureType *_closure_type;
     struct {
       union {
         CPPType *_type;

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

@@ -31,7 +31,8 @@ CPPFunctionType(CPPType *return_type, CPPParameterList *parameters,
 
   // If the parameter list contains just the token "void", it means no
   // parameters.
-  if (_parameters->_parameters.size() == 1 &&
+  if (_parameters != NULL &&
+      _parameters->_parameters.size() == 1 &&
       _parameters->_parameters.front()->_type->as_simple_type() != NULL &&
       _parameters->_parameters.front()->_type->as_simple_type()->_type ==
       CPPSimpleType::T_void &&
@@ -65,6 +66,31 @@ operator = (const CPPFunctionType &copy) {
   _class_owner = copy._class_owner;
 }
 
+/**
+ * Returns true if the function accepts the given number of parameters.
+ */
+bool CPPFunctionType::
+accepts_num_parameters(int num_parameters) {
+  if (_parameters == NULL) {
+    return (num_parameters == 0);
+  }
+  size_t actual_num_parameters = _parameters->_parameters.size();
+  // If we passed too many parameters, it must have an ellipsis.
+  if (num_parameters > actual_num_parameters) {
+    return _parameters->_includes_ellipsis;
+  }
+
+  // Make sure all superfluous parameters have a default value.
+  for (size_t i = num_parameters; i < actual_num_parameters; ++i) {
+    CPPInstance *param = _parameters->_parameters[i];
+    if (param->_initializer == NULL) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 /**
  * Returns true if this declaration is an actual, factual declaration, or
  * false if some part of the declaration depends on a template parameter which
@@ -95,8 +121,10 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
       ->as_type();
   }
 
-  rep->_parameters =
-    _parameters->substitute_decl(subst, current_scope, global_scope);
+  if (_parameters != NULL) {
+    rep->_parameters =
+      _parameters->substitute_decl(subst, current_scope, global_scope);
+  }
 
   if (rep->_return_type == _return_type &&
       rep->_parameters == _parameters) {
@@ -117,8 +145,12 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
 CPPType *CPPFunctionType::
 resolve_type(CPPScope *current_scope, CPPScope *global_scope) {
   CPPType *rtype = _return_type->resolve_type(current_scope, global_scope);
-  CPPParameterList *params =
-    _parameters->resolve_type(current_scope, global_scope);
+  CPPParameterList *params;
+  if (_parameters == NULL) {
+    params = NULL;
+  } else {
+    params = _parameters->resolve_type(current_scope, global_scope);
+  }
 
   if (rtype != _return_type || params != _parameters) {
     CPPFunctionType *rep = new CPPFunctionType(*this);
@@ -139,7 +171,7 @@ is_tbd() const {
   if (_return_type->is_tbd()) {
     return true;
   }
-  return _parameters->is_tbd();
+  return _parameters == NULL || _parameters->is_tbd();
 }
 
 /**
@@ -294,6 +326,10 @@ get_num_default_parameters() const {
   // The trick is just to count, beginning from the end and working towards
   // the front, the number of parameters that have some initializer.
 
+  if (_parameters == NULL) {
+    return 0;
+  }
+
   const CPPParameterList::Parameters &params = _parameters->_parameters;
   CPPParameterList::Parameters::const_reverse_iterator pi;
   int count = 0;
@@ -362,7 +398,11 @@ is_equal(const CPPDeclaration *other) const {
   if (_flags != ot->_flags) {
     return false;
   }
-  if (*_parameters != *ot->_parameters) {
+  if (_parameters == ot->_parameters) {
+    return true;
+  }
+  if (_parameters == NULL || ot->_parameters == NULL ||
+      *_parameters != *ot->_parameters) {
     return false;
   }
   return true;
@@ -384,6 +424,11 @@ is_less(const CPPDeclaration *other) const {
   if (_flags != ot->_flags) {
     return _flags < ot->_flags;
   }
-
+  if (_parameters == ot->_parameters) {
+    return 0;
+  }
+  if (_parameters == NULL || ot->_parameters == NULL) {
+    return _parameters < ot->_parameters;
+  }
   return *_parameters < *ot->_parameters;
 }

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

@@ -50,6 +50,8 @@ public:
   CPPFunctionType(const CPPFunctionType &copy);
   void operator = (const CPPFunctionType &copy);
 
+  bool accepts_num_parameters(int num_parameters);
+
   CPPType *_return_type;
   CPPParameterList *_parameters;
   int _flags;

+ 70 - 5
dtool/src/cppparser/cppPreprocessor.cxx

@@ -209,6 +209,7 @@ CPPPreprocessor() {
   _state = S_eof;
   _paren_nesting = 0;
   _parsing_template_params = false;
+  _parsing_attribute = false;
   _unget = '\0';
   _last_c = '\0';
   _start_of_line = true;
@@ -986,6 +987,13 @@ internal_get_next_token() {
         return CPPToken(0, loc);
       }
     }
+  } else if (_parsing_attribute) {
+    // If we're parsing an attribute, also keep track of the paren nesting.
+    if (c == '[' || c == '(') {
+      ++_paren_nesting;
+    } else if (c == ']' || c == ')') {
+      --_paren_nesting;
+    }
   }
 
   // Look for an end-of-line comment, and parse it before we finish this
@@ -1090,6 +1098,20 @@ check_digraph(int c) {
     if (next_c == '=') return MODEQUAL;
     if (next_c == '>') return '}';
     break;
+
+  case '[':
+    if (next_c == '[' && !_parsing_attribute) {
+      _parsing_attribute = true;
+      return ATTR_LEFT;
+    }
+    break;
+
+  case ']':
+    if (next_c == ']' && _parsing_attribute && _paren_nesting == 0) {
+      _parsing_attribute = false;
+      return ATTR_RIGHT;
+    }
+    break;
   }
 
   return 0;
@@ -1870,11 +1892,19 @@ get_identifier(int c) {
   loc.last_column = get_col_number();
 
   if ((c == '\'' || c == '"') &&
-      (name == "L" || name == "u8" ||
-       name == "u" || name == "U")) {
+      (name == "L" || name == "u8" || name == "u" || name == "U" ||
+       name == "R" || name == "LR" || name == "u8R" || name == "uR" || name == "UR")) {
     // This is actually a wide-character or wide-string literal or some such.
-    // Figure out the correct character type to use.
+    get();
+    string str;
+    if (name[name.size() - 1] == 'R') {
+      name.resize(name.size() - 1);
+      str = scan_raw(c);
+    } else {
+      str = scan_quoted(c);
+    }
 
+    // Figure out the correct character type to use.
     CPPExpression::Type type;
     if (name == "L") {
       type = CPPExpression::T_wstring;
@@ -1887,8 +1917,6 @@ get_identifier(int c) {
     } else {
       type = CPPExpression::T_string;
     }
-    get();
-    string str = scan_quoted(c);
 
     loc.last_line = get_line_number();
     loc.last_column = get_col_number();
@@ -2772,6 +2800,43 @@ scan_quoted(int c) {
   return str;
 }
 
+/**
+ * Parses a C++11 raw string.
+ */
+string CPPPreprocessor::
+scan_raw(int c) {
+  int quote_mark = c;
+
+  string delimiter = ")";
+
+  string str;
+  c = get();
+  while (c != EOF && c != '(') {
+    delimiter += c;
+    c = get();
+  }
+
+  // OK, now start parsing the string, until we see the delimiter again.
+  c = get();
+  while (c != EOF) {
+    if (c == quote_mark) {
+      // We encountered a quote mark - did the last part of the string end
+      // with the given delimiter?  If so, we've reached the end.
+      if (str.compare(str.size() - delimiter.size(), delimiter.size(), delimiter) == 0) {
+        str.resize(str.size() - delimiter.size());
+        break;
+      }
+    }
+    str += c;
+    c = get();
+  }
+
+  if (c != quote_mark) {
+    warning("Unclosed string");
+  }
+  return str;
+}
+
 /**
  * Returns true if the manifest is one that is being ignored right now
  * (presumably because we are presently expanding it).

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

@@ -166,6 +166,7 @@ private:
   static int check_keyword(const string &name);
   int scan_escape_sequence(int c);
   string scan_quoted(int c);
+  string scan_raw(int c);
 
   bool should_ignore_manifest(const CPPManifest *manifest) const;
   bool should_ignore_preprocessor() const;
@@ -212,6 +213,7 @@ private:
   State _state;
   int _paren_nesting;
   bool _parsing_template_params;
+  bool _parsing_attribute;
 
   bool _start_of_line;
   int _unget;

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

@@ -252,6 +252,14 @@ output(ostream &out) const {
     out << "RSHIFTEQUAL";
     break;
 
+  case ATTR_LEFT:
+    out << "ATTR_LEFT";
+    break;
+
+  case ATTR_RIGHT:
+    out << "ATTR_RIGHT";
+    break;
+
   case KW_BOOL:
     out << "KW_BOOL";
     break;

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

@@ -2,6 +2,7 @@
 #include "cppFunctionType.cxx"
 #include "cppGlobals.cxx"
 #include "cppCommentBlock.cxx"
+#include "cppClosureType.cxx"
 #include "cppConstType.cxx"
 #include "cppDeclaration.cxx"
 #include "cppMakeProperty.cxx"

+ 4 - 4
dtool/src/dtoolbase/deletedBufferChain.cxx

@@ -39,7 +39,7 @@ allocate(size_t size, TypeHandle type_handle) {
   assert(size <= _buffer_size);
 
   // Determine how much space to allocate.
-  const size_t alloc_size = _buffer_size + flag_reserved_bytes + MemoryHook::get_memory_alignment() - 1;
+  const size_t alloc_size = _buffer_size + flag_reserved_bytes + MEMORY_HOOK_ALIGNMENT - 1;
 
   ObjectNode *obj;
 
@@ -71,8 +71,8 @@ allocate(size_t size, TypeHandle type_handle) {
 
   // Allocate memory, and make sure the object starts at the proper alignment.
   void *mem = NeverFreeMemory::alloc(alloc_size);
-  intptr_t pad = (-(intptr_t)flag_reserved_bytes - (intptr_t)mem) % MemoryHook::get_memory_alignment();
-  obj = (ObjectNode *)((uintptr_t)mem + pad);
+  uintptr_t aligned = ((uintptr_t)mem + flag_reserved_bytes + MEMORY_HOOK_ALIGNMENT - 1) & ~(MEMORY_HOOK_ALIGNMENT - 1);
+  obj = (ObjectNode *)(aligned - flag_reserved_bytes);
 
 #ifdef USE_DELETEDCHAINFLAG
   obj->_flag = DCF_alive;
@@ -81,7 +81,7 @@ allocate(size_t size, TypeHandle type_handle) {
   void *ptr = node_to_buffer(obj);
 
 #ifndef NDEBUG
-  assert(((uintptr_t)ptr % MemoryHook::get_memory_alignment()) == 0);
+  assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0);
 #endif
 
 #ifdef DO_MEMORY_USAGE

+ 60 - 85
dtool/src/dtoolbase/deletedChain.T

@@ -1,25 +1,22 @@
-// Filename: deletedChain.T
-// Created by:  drose (01Apr06)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) Carnegie Mellon University.  All rights reserved.
-//
-// All use of this software is subject to the terms of the revised BSD
-// license.  You should have received a copy of this license along
-// with this source code in a file named "LICENSE."
-//
-////////////////////////////////////////////////////////////////////
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file deletedChain.T
+ * @author drose
+ * @date 2006-04-01
+ */
 
 template<class Type>
 DeletedChain<Type> StaticDeletedChain<Type>::_chain;
 
-////////////////////////////////////////////////////////////////////
-//     Function: DeletedChain::allocate
-//       Access: Public
-//  Description: Allocates the memory for a new object of Type.
-////////////////////////////////////////////////////////////////////
+/**
+ * Allocates the memory for a new object of Type.
+ */
 template<class Type>
 INLINE Type *DeletedChain<Type>::
 allocate(size_t size, TypeHandle type_handle) {
@@ -31,14 +28,12 @@ allocate(size_t size, TypeHandle type_handle) {
   memory_hook->mark_pointer(ptr, _chain->get_buffer_size(), make_ref_ptr(ptr));
 #endif  // DO_MEMORY_USAGE
 
-  return (Type *)ptr;
+  return (Type *)ASSUME_ALIGNED(ptr, MEMORY_HOOK_ALIGNMENT);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DeletedChain::deallocate
-//       Access: Public
-//  Description: Frees the memory for an object of Type.
-////////////////////////////////////////////////////////////////////
+/**
+ * Frees the memory for an object of Type.
+ */
 template<class Type>
 INLINE void DeletedChain<Type>::
 deallocate(Type *ptr, TypeHandle type_handle) {
@@ -57,16 +52,13 @@ deallocate(Type *ptr, TypeHandle type_handle) {
   _chain->deallocate(ptr, type_handle);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DeletedChain::validate
-//       Access: Public
-//  Description: Returns true if the pointer is valid, false if it has
-//               been deleted or if it was never a valid pointer.
-//
-//               This is only meaningful in debug mode, where
-//               USE_DELETEDCHAINFLAG is defined.  If not, this
-//               trivially returns true.
-////////////////////////////////////////////////////////////////////
+/**
+ * Returns true if the pointer is valid, false if it has been deleted or if it
+ * was never a valid pointer.
+ *
+ * This is only meaningful in debug mode, where USE_DELETEDCHAINFLAG is
+ * defined.  If not, this trivially returns true.
+ */
 template<class Type>
 INLINE bool DeletedChain<Type>::
 validate(const Type *ptr) {
@@ -80,48 +72,37 @@ validate(const Type *ptr) {
 #endif  // USE_DELETEDCHAINFLAG
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DeletedChain::make_ref_ptr
-//       Access: Public, Static
-//  Description: This method has two overloads: one that accepts a
-//               void *, and one that accepts a ReferenceCount *.  We
-//               rely on the C++ compiler to select the most
-//               appropriate one for a given type to return the
-//               ReferenceCount pointer that corresponds to a
-//               particular type, or NULL if the type does not inherit
-//               from ReferenceCount.
-////////////////////////////////////////////////////////////////////
+/**
+ * This method has two overloads: one that accepts a void *, and one that
+ * accepts a ReferenceCount *.  We rely on the C++ compiler to select the most
+ * appropriate one for a given type to return the ReferenceCount pointer that
+ * corresponds to a particular type, or NULL if the type does not inherit from
+ * ReferenceCount.
+ */
 template<class Type>
 INLINE ReferenceCount *DeletedChain<Type>::
 make_ref_ptr(void *) {
   return NULL;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DeletedChain::make_ref_ptr
-//       Access: Public, Static
-//  Description: This method has two overloads: one that accepts a
-//               void *, and one that accepts a ReferenceCount *.  We
-//               rely on the C++ compiler to select the most
-//               appropriate one for a given type to return the
-//               ReferenceCount pointer that corresponds to a
-//               particular type, or NULL if the type does not inherit
-//               from ReferenceCount.
-////////////////////////////////////////////////////////////////////
+/**
+ * This method has two overloads: one that accepts a void *, and one that
+ * accepts a ReferenceCount *.  We rely on the C++ compiler to select the most
+ * appropriate one for a given type to return the ReferenceCount pointer that
+ * corresponds to a particular type, or NULL if the type does not inherit from
+ * ReferenceCount.
+ */
 template<class Type>
 INLINE ReferenceCount *DeletedChain<Type>::
 make_ref_ptr(ReferenceCount *ptr) {
   return ptr;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: DeletedChain::init_deleted_chain
-//       Access: Private
-//  Description: Assigns the _chain pointer if it is not already
-//               assigned.  This can't be done by a constructor, since
-//               often the DeletedChain instance is used before its
-//               static construct has had a chance to be called.
-////////////////////////////////////////////////////////////////////
+/**
+ * Assigns the _chain pointer if it is not already assigned.  This can't be
+ * done by a constructor, since often the DeletedChain instance is used before
+ * its static construct has had a chance to be called.
+ */
 template<class Type>
 void DeletedChain<Type>::
 init_deleted_chain() {
@@ -131,38 +112,32 @@ init_deleted_chain() {
   }
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: StaticDeletedChain::allocate
-//       Access: Public, Static
-//  Description: Allocates the memory for a new object of Type.
-////////////////////////////////////////////////////////////////////
+/**
+ * Allocates the memory for a new object of Type.
+ */
 template<class Type>
 INLINE Type *StaticDeletedChain<Type>::
 allocate(size_t size, TypeHandle type_handle) {
-  return _chain.allocate(size, type_handle);
+  Type *ptr = _chain.allocate(size, type_handle);
+  return (Type *)ASSUME_ALIGNED(ptr, MEMORY_HOOK_ALIGNMENT);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: StaticDeletedChain::deallocate
-//       Access: Public
-//  Description: Frees the memory for an object of Type.
-////////////////////////////////////////////////////////////////////
+/**
+ * Frees the memory for an object of Type.
+ */
 template<class Type>
 INLINE void StaticDeletedChain<Type>::
 deallocate(Type *ptr, TypeHandle type_handle) {
   _chain.deallocate(ptr, type_handle);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: StaticDeletedChain::validate
-//       Access: Public
-//  Description: Returns true if the pointer is valid, false if it has
-//               been deleted or if it was never a valid pointer.
-//
-//               This is only meaningful in debug mode, where
-//               USE_DELETEDCHAINFLAG is defined.  If not, this
-//               trivially returns true.
-////////////////////////////////////////////////////////////////////
+/**
+ * Returns true if the pointer is valid, false if it has been deleted or if it
+ * was never a valid pointer.
+ *
+ * This is only meaningful in debug mode, where USE_DELETEDCHAINFLAG is
+ * defined.  If not, this trivially returns true.
+ */
 template<class Type>
 INLINE bool StaticDeletedChain<Type>::
 validate(const Type *ptr) {

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

@@ -89,6 +89,12 @@
 #define NODEFAULT
 #endif
 
+// Use this to hint the compiler that a memory address is aligned.
+#if __has_builtin(__builtin_assume_aligned) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
+#define ASSUME_ALIGNED(x, y) (__builtin_assume_aligned(x, y))
+#else
+#define ASSUME_ALIGNED(x, y) (x)
+#endif
 
 /*
   include win32 defns for everything up to WinServer2003, and assume

+ 34 - 4
dtool/src/dtoolbase/dtoolbase_cc.h

@@ -39,6 +39,10 @@ using namespace std;
 #define OVERRIDE override
 #define MOVE(x) x
 #define DEFAULT_CTOR = default
+#define DEFAULT_DTOR = default
+#define DEFAULT_ASSIGN = default
+#define DELETED = delete
+#define DELETED_ASSIGN = delete
 
 #define EXPORT_TEMPLATE_CLASS(expcl, exptp, classname)
 
@@ -166,6 +170,11 @@ template<class T> typename remove_reference<T>::type &&move(T &&t) {
 #  endif
 #  if __has_extension(cxx_defaulted_functions)
 #     define DEFAULT_CTOR = default
+#     define DEFAULT_DTOR = default
+#     define DEFAULT_ASSIGN = default
+#  endif
+#  if __has_extension(cxx_deleted_functions)
+#     define DELETED = delete
 #  endif
 #elif defined(__GNUC__) && (__cplusplus >= 201103L) // GCC
 
@@ -178,6 +187,9 @@ template<class T> typename remove_reference<T>::type &&move(T &&t) {
 // Starting at GCC 4.4
 #  if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
 #  define DEFAULT_CTOR = default
+#  define DEFAULT_DTOR = default
+#  define DEFAULT_ASSIGN = default
+#  define DELETED = delete
 #  endif
 
 // Starting at GCC 4.6
@@ -200,7 +212,6 @@ template<class T> typename remove_reference<T>::type &&move(T &&t) {
 #  define FINAL final
 #  define OVERRIDE override
 #  define MOVE(x) move(x)
-#  define DEFAULT_CTOR = default
 #elif defined(_MSC_VER) && _MSC_VER >= 1600 // Visual Studio 2010
 #  define NOEXCEPT throw()
 #  define OVERRIDE override
@@ -209,6 +220,13 @@ template<class T> typename remove_reference<T>::type &&move(T &&t) {
 #  define MOVE(x) move(x)
 #endif
 
+#if defined(_MSC_VER) && _MSC_VER >= 1800 // Visual Studio 2013
+#  define DEFAULT_CTOR = default
+#  define DEFAULT_DTOR = default
+#  define DEFAULT_ASSIGN = default
+#  define DELETED = delete
+#endif
+
 // Fallbacks if features are not supported
 #ifndef CONSTEXPR
 #  define CONSTEXPR INLINE
@@ -228,6 +246,18 @@ template<class T> typename remove_reference<T>::type &&move(T &&t) {
 #ifndef DEFAULT_CTOR
 #  define DEFAULT_CTOR {}
 #endif
+#ifndef DEFAULT_DTOR
+#  define DEFAULT_DTOR {}
+#endif
+#ifndef DEFAULT_ASSIGN
+#  define DEFAULT_ASSIGN {return *this;}
+#endif
+#ifndef DELETED
+#  define DELETED {assert(false);}
+#  define DELETED_ASSIGN {assert(false);return *this;}
+#else
+#  define DELETED_ASSIGN DELETED
+#endif
 
 
 #if !defined(LINK_ALL_STATIC) && defined(EXPORT_TEMPLATES)
@@ -260,10 +290,10 @@ EXPCL_DTOOL void init_memory_hook();
 
 // Now redefine some handy macros to hook into the above MemoryHook object.
 #ifndef USE_MEMORY_NOWRAPPERS
-#define PANDA_MALLOC_SINGLE(size) (memory_hook->heap_alloc_single(size))
+#define PANDA_MALLOC_SINGLE(size) (ASSUME_ALIGNED(memory_hook->heap_alloc_single(size), MEMORY_HOOK_ALIGNMENT))
 #define PANDA_FREE_SINGLE(ptr) memory_hook->heap_free_single(ptr)
-#define PANDA_MALLOC_ARRAY(size) (memory_hook->heap_alloc_array(size))
-#define PANDA_REALLOC_ARRAY(ptr, size) (memory_hook->heap_realloc_array(ptr, size))
+#define PANDA_MALLOC_ARRAY(size) (ASSUME_ALIGNED(memory_hook->heap_alloc_array(size), MEMORY_HOOK_ALIGNMENT))
+#define PANDA_REALLOC_ARRAY(ptr, size) (ASSUME_ALIGNED(memory_hook->heap_realloc_array(ptr, size), MEMORY_HOOK_ALIGNMENT))
 #define PANDA_FREE_ARRAY(ptr) memory_hook->heap_free_array(ptr)
 #else
 #define PANDA_MALLOC_SINGLE(size) ::malloc(size)

+ 36 - 67
dtool/src/dtoolbase/memoryHook.I

@@ -38,57 +38,9 @@ dec_heap(size_t size) {
  * Returns the global memory alignment.  This is the number of bytes at which
  * each allocated memory pointer will be aligned.
  */
-INLINE size_t MemoryHook::
+CONSTEXPR size_t MemoryHook::
 get_memory_alignment() {
-#ifdef LINMATH_ALIGN
-  // We require 16-byte alignment of certain structures, to support SSE2.  We
-  // don't strictly have to align *everything*, but it's just easier to do so.
-#ifdef __AVX__
-  // Eigen requires 32-byte alignment when using AVX instructions.
-  const size_t alignment_size = 32;
-#else
-  const size_t alignment_size = 16;
-#endif
-#else
-  // Otherwise, align to two words.  This seems to be pretty standard to the
-  // point where some code may rely on this being the case.
-  const size_t alignment_size = sizeof(void *) * 2;
-#endif
-  return alignment_size;
-}
-
-/**
- * Returns the number of additional bytes that are reserved at the beginning
- * of every allocated block to store a size_t.
- */
-INLINE size_t MemoryHook::
-get_header_reserved_bytes() {
-  // We need to figure out the minimum amount of additional space we need in
-  // order to place a single word at the start of each allocated block, to
-  // store the size of the block.
-
-#ifdef LINMATH_ALIGN
-  // If we're doing SSE2 alignment, we must reserve a full 16-byte block,
-  // since anything less than that will spoil the alignment.
-#ifdef __AVX__
-  // Eigen requires 32-byte alignment when using AVX instructions.
-  static const size_t header_reserved_bytes = 32;
-#else
-  static const size_t header_reserved_bytes = 16;
-#endif
-
-#elif defined(MEMORY_HOOK_DO_ALIGN)
-  // If we're just aligning to words, we reserve a block as big as two words,
-  // to allow us wiggle room to align the word precisely within that block.
-  static const size_t header_reserved_bytes = sizeof(size_t) + sizeof(size_t);
-
-#else
-  // Virtually all allocators align to two words, so we make sure we preserve
-  // that alignment for the benefit of anyone who relies upon that.
-  static const size_t header_reserved_bytes = sizeof(void *) * 2;
-#endif
-
-  return header_reserved_bytes;
+  return MEMORY_HOOK_ALIGNMENT;
 }
 
 /**
@@ -109,6 +61,24 @@ round_up_to_page_size(size_t size) const {
   return  ((size + _page_size - 1) / _page_size) * _page_size;
 }
 
+/**
+ * Given a pointer that was returned by a MemoryHook allocation, returns the
+ * number of bytes that were allocated for it.  Returns 0 if not compiling
+ * with DO_MEMORY_USAGE.
+ */
+INLINE size_t MemoryHook::
+get_ptr_size(void *ptr) {
+#if defined(MEMORY_HOOK_DO_ALIGN)
+  uintptr_t *root = (uintptr_t *)ptr;
+  return (size_t)root[-2];
+#elif defined(DO_MEMORY_USAGE)
+  size_t *root = (size_t *)((char *)ptr - MEMORY_HOOK_ALIGNMENT);
+  return *root;
+#else
+  return 0;
+#endif  // DO_MEMORY_USAGE
+}
+
 /**
  * Increments the amount of requested size as necessary to accommodate the
  * extra data we might piggyback on each allocated block.
@@ -118,12 +88,13 @@ inflate_size(size_t size) {
 #if defined(MEMORY_HOOK_DO_ALIGN)
   // If we're aligning, we need to request the header size, plus extra bytes
   // to give us wiggle room to adjust the pointer.
-  return size + get_header_reserved_bytes() + get_memory_alignment() - 1;
+  return size + sizeof(uintptr_t) * 2 + MEMORY_HOOK_ALIGNMENT - 1;
 #elif defined(DO_MEMORY_USAGE)
   // If we're not aligning, but we're tracking memory allocations, we just
   // need the header size extra (this gives us a place to store the size of
-  // the allocated block).
-  return size + get_header_reserved_bytes();
+  // the allocated block).  However, we do need to make sure that any
+  // alignment guarantee is kept.
+  return size + MEMORY_HOOK_ALIGNMENT;
 #else
   // If we're not doing any of that, we can just allocate the precise
   // requested amount.
@@ -138,17 +109,17 @@ inflate_size(size_t size) {
 INLINE void *MemoryHook::
 alloc_to_ptr(void *alloc, size_t size) {
 #if defined(MEMORY_HOOK_DO_ALIGN)
-  size_t alignment = get_memory_alignment();
-  // Move the allocated pointer up to the next even alignment.
-  size_t *root = (size_t *)((((size_t)alloc + alignment - 1) / alignment) * alignment);
-  assert(alloc <= root && (size_t)((char *)root - (char *)alloc) < alignment);
-  root[0] = size;
-  root[1] = (size_t)alloc;  // Save the pointer we originally allocated.
-  return (void *)((char *)root + get_header_reserved_bytes());
+  // Add room for two uintptr_t values.
+  uintptr_t *root = (uintptr_t *)((char *)alloc + sizeof(uintptr_t) * 2);
+  // Align this to the requested boundary.
+  root = (uintptr_t *)(((uintptr_t)root + MEMORY_HOOK_ALIGNMENT - 1) & ~(MEMORY_HOOK_ALIGNMENT - 1));
+  root[-2] = size;
+  root[-1] = (uintptr_t)alloc;  // Save the pointer we originally allocated.
+  return (void *)root;
 #elif defined(DO_MEMORY_USAGE)
   size_t *root = (size_t *)alloc;
   root[0] = size;
-  return (void *)((char *)root + get_header_reserved_bytes());
+  return (void *)((char *)root + MEMORY_HOOK_ALIGNMENT);
 #else
   return alloc;
 #endif  // DO_MEMORY_USAGE
@@ -161,13 +132,11 @@ alloc_to_ptr(void *alloc, size_t size) {
 INLINE void *MemoryHook::
 ptr_to_alloc(void *ptr, size_t &size) {
 #if defined(MEMORY_HOOK_DO_ALIGN)
-  size_t *root = (size_t *)((char *)ptr - get_header_reserved_bytes());
-  size = root[0];
-  void *alloc = (void *)root[1]; // Get the pointer we originally allocated.
-  assert(alloc <= root && (size_t)((char *)root - (char *)alloc) < get_memory_alignment());
-  return alloc;
+  uintptr_t *root = (uintptr_t *)ptr;
+  size = root[-2];
+  return (void *)root[-1]; // Get the pointer we originally allocated.
 #elif defined(DO_MEMORY_USAGE)
-  size_t *root = (size_t *)((char *)ptr - get_header_reserved_bytes());
+  size_t *root = (size_t *)((char *)ptr - MEMORY_HOOK_ALIGNMENT);
   size = root[0];
   return (void *)root;
 #else

+ 29 - 17
dtool/src/dtoolbase/memoryHook.cxx

@@ -36,6 +36,15 @@
 
 #endif  // WIN32
 
+// Ensure we made the right decisions about the alignment size.
+static_assert(MEMORY_HOOK_ALIGNMENT >= sizeof(size_t),
+              "MEMORY_HOOK_ALIGNMENT should at least be sizeof(size_t)");
+static_assert(MEMORY_HOOK_ALIGNMENT >= sizeof(void *),
+              "MEMORY_HOOK_ALIGNMENT should at least be sizeof(void *)");
+static_assert(MEMORY_HOOK_ALIGNMENT * 8 >= NATIVE_WORDSIZE,
+              "MEMORY_HOOK_ALIGNMENT * 8 should at least be NATIVE_WORDSIZE");
+static_assert((MEMORY_HOOK_ALIGNMENT & (MEMORY_HOOK_ALIGNMENT - 1)) == 0,
+              "MEMORY_HOOK_ALIGNMENT should be a power of two");
 
 #if defined(USE_MEMORY_DLMALLOC)
 
@@ -49,17 +58,8 @@
 #ifdef _DEBUG
   #define DEBUG 1
 #endif
-#ifdef LINMATH_ALIGN
-// drose: We require 16-byte alignment of certain structures, to
-// support SSE2.  We don't strictly have to align *everything*, but
-// it's just easier to do so.
-#ifdef __AVX__
-// Eigen requires 32-byte alignment when using AVX instructions.
-#define MALLOC_ALIGNMENT ((size_t)32U)
-#else
-#define MALLOC_ALIGNMENT ((size_t)16U)
-#endif
-#endif
+// dlmalloc can do the alignment we ask for.
+#define MALLOC_ALIGNMENT MEMORY_HOOK_ALIGNMENT
 
 #include "dlmalloc_src.cxx"
 
@@ -204,6 +204,7 @@ heap_alloc_single(size_t size) {
 #endif  // DO_MEMORY_USAGE
 
   void *ptr = alloc_to_ptr(alloc, size);
+  assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0);
   assert(ptr >= alloc && (char *)ptr + size <= (char *)alloc + inflated_size);
   return ptr;
 }
@@ -273,6 +274,7 @@ heap_alloc_array(size_t size) {
 #endif  // DO_MEMORY_USAGE
 
   void *ptr = alloc_to_ptr(alloc, size);
+  assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0);
   assert(ptr >= alloc && (char *)ptr + size <= (char *)alloc + inflated_size);
   return ptr;
 }
@@ -316,17 +318,27 @@ heap_realloc_array(void *ptr, size_t size) {
 #endif
   }
 
-  void *ptr1 = alloc_to_ptr(alloc1, size);
-  assert(ptr1 >= alloc1 && (char *)ptr1 + size <= (char *)alloc1 + inflated_size);
-#if defined(MEMORY_HOOK_DO_ALIGN)
-  // We might have to shift the memory to account for the new offset due to
-  // the alignment.
+  // Align this to the requested boundary.
+#ifdef MEMORY_HOOK_DO_ALIGN
+  // This copies the code from alloc_to_ptr, since we can't write the size and
+  // pointer until after we have done the memmove.
+  uintptr_t *root = (uintptr_t *)((char *)alloc1 + sizeof(uintptr_t) * 2);
+  root = (uintptr_t *)(((uintptr_t)root + MEMORY_HOOK_ALIGNMENT - 1) & ~(MEMORY_HOOK_ALIGNMENT - 1));
+  void *ptr1 = (void *)root;
+
   size_t orig_delta = (char *)ptr - (char *)alloc;
   size_t new_delta = (char *)ptr1 - (char *)alloc1;
   if (orig_delta != new_delta) {
     memmove((char *)alloc1 + new_delta, (char *)alloc1 + orig_delta, min(size, orig_size));
   }
-#endif  // MEMORY_HOOK_DO_ALIGN
+
+  root[-2] = size;
+  root[-1] = (uintptr_t)alloc1;  // Save the pointer we originally allocated.
+#else
+  void *ptr1 = alloc_to_ptr(alloc1, size);
+#endif
+  assert(ptr1 >= alloc1 && (char *)ptr1 + size <= (char *)alloc1 + inflated_size);
+  assert(((uintptr_t)ptr1 % MEMORY_HOOK_ALIGNMENT) == 0);
   return ptr1;
 }
 

+ 19 - 2
dtool/src/dtoolbase/memoryHook.h

@@ -20,6 +20,22 @@
 #include "mutexImpl.h"
 #include <map>
 
+#ifdef LINMATH_ALIGN
+// We require 16-byte alignment of certain structures, to support SSE2.  We
+// don't strictly have to align *everything*, but it's just easier to do so.
+#ifdef __AVX__
+#define MEMORY_HOOK_ALIGNMENT 32
+#else
+#define MEMORY_HOOK_ALIGNMENT 16
+#endif
+// Otherwise, align to two words.  This seems to be pretty standard to the
+// point where some code may rely on this being the case.
+#elif defined(IS_OSX) || NATIVE_WORDSIZE >= 64
+#define MEMORY_HOOK_ALIGNMENT 16
+#else
+#define MEMORY_HOOK_ALIGNMENT 8
+#endif
+
 class DeletedBufferChain;
 
 /**
@@ -52,8 +68,7 @@ public:
 
   bool heap_trim(size_t pad);
 
-  INLINE static size_t get_memory_alignment();
-  INLINE static size_t get_header_reserved_bytes();
+  CONSTEXPR static size_t get_memory_alignment();
 
   virtual void *mmap_alloc(size_t size, bool allow_exec);
   virtual void mmap_free(void *ptr, size_t size);
@@ -66,6 +81,8 @@ public:
 
   virtual void alloc_fail(size_t attempted_size);
 
+  INLINE static size_t get_ptr_size(void *ptr);
+
 private:
   INLINE static size_t inflate_size(size_t size);
   INLINE static void *alloc_to_ptr(void *alloc, size_t size);

+ 3 - 17
dtool/src/dtoolbase/mutexDummyImpl.I

@@ -14,28 +14,14 @@
 /**
  *
  */
-INLINE MutexDummyImpl::
-MutexDummyImpl() {
-}
-
-/**
- *
- */
-INLINE MutexDummyImpl::
-~MutexDummyImpl() {
-}
-
-/**
- *
- */
-INLINE void MutexDummyImpl::
+ALWAYS_INLINE void MutexDummyImpl::
 acquire() {
 }
 
 /**
  *
  */
-INLINE bool MutexDummyImpl::
+ALWAYS_INLINE bool MutexDummyImpl::
 try_acquire() {
   return true;
 }
@@ -43,6 +29,6 @@ try_acquire() {
 /**
  *
  */
-INLINE void MutexDummyImpl::
+ALWAYS_INLINE void MutexDummyImpl::
 release() {
 }

+ 9 - 5
dtool/src/dtoolbase/mutexDummyImpl.h

@@ -23,12 +23,16 @@
  */
 class EXPCL_DTOOL MutexDummyImpl {
 public:
-  INLINE MutexDummyImpl();
-  INLINE ~MutexDummyImpl();
+  CONSTEXPR MutexDummyImpl() DEFAULT_CTOR;
 
-  INLINE void acquire();
-  INLINE bool try_acquire();
-  INLINE void release();
+private:
+  MutexDummyImpl(const MutexDummyImpl &copy) DELETED;
+  MutexDummyImpl &operator = (const MutexDummyImpl &copy) DELETED_ASSIGN;
+
+public:
+  ALWAYS_INLINE void acquire();
+  ALWAYS_INLINE bool try_acquire();
+  ALWAYS_INLINE void release();
 };
 
 #include "mutexDummyImpl.I"

+ 8 - 10
dtool/src/dtoolbase/mutexPosixImpl.I

@@ -14,16 +14,8 @@
 /**
  *
  */
-INLINE MutexPosixImpl::
-MutexPosixImpl() {
-  TAU_PROFILE("MutexPosixImpl::MutexPosixImpl", " ", TAU_USER);
-  pthread_mutexattr_t attr;
-  pthread_mutexattr_init(&attr);
-  // The symbol PTHREAD_MUTEX_DEFAULT isn't always available?
-  // pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
-  int result = pthread_mutex_init(&_lock, &attr);
-  pthread_mutexattr_destroy(&attr);
-  assert(result == 0);
+CONSTEXPR MutexPosixImpl::
+MutexPosixImpl() NOEXCEPT : _lock(PTHREAD_MUTEX_INITIALIZER) {
 }
 
 /**
@@ -78,6 +70,11 @@ get_posix_lock() {
 /**
  *
  */
+#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+CONSTEXPR ReMutexPosixImpl::
+ReMutexPosixImpl() NOEXCEPT : _lock(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) {
+}
+#else
 INLINE ReMutexPosixImpl::
 ReMutexPosixImpl() {
   TAU_PROFILE("ReMutexPosixImpl::ReMutexPosixImpl", " ", TAU_USER);
@@ -88,6 +85,7 @@ ReMutexPosixImpl() {
   pthread_mutexattr_destroy(&attr);
   assert(result == 0);
 }
+#endif
 
 /**
  *

+ 15 - 1
dtool/src/dtoolbase/mutexPosixImpl.h

@@ -28,9 +28,14 @@
  */
 class EXPCL_DTOOL MutexPosixImpl {
 public:
-  INLINE MutexPosixImpl();
+  CONSTEXPR MutexPosixImpl() NOEXCEPT;
   INLINE ~MutexPosixImpl();
 
+private:
+  MutexPosixImpl(const MutexPosixImpl &copy) DELETED;
+  MutexPosixImpl &operator = (const MutexPosixImpl &copy) DELETED_ASSIGN;
+
+public:
   INLINE void acquire();
   INLINE bool try_acquire();
   INLINE void release();
@@ -47,9 +52,18 @@ private:
  */
 class EXPCL_DTOOL ReMutexPosixImpl {
 public:
+#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+  CONSTEXPR ReMutexPosixImpl() NOEXCEPT;
+#else
   INLINE ReMutexPosixImpl();
+#endif
   INLINE ~ReMutexPosixImpl();
 
+private:
+  ReMutexPosixImpl(const ReMutexPosixImpl &copy) DELETED;
+  ReMutexPosixImpl &operator = (const ReMutexPosixImpl &copy) DELETED;
+
+public:
   INLINE void acquire();
   INLINE bool try_acquire();
   INLINE void release();

+ 2 - 10
dtool/src/dtoolbase/mutexSpinlockImpl.I

@@ -14,16 +14,8 @@
 /**
  *
  */
-INLINE MutexSpinlockImpl::
-MutexSpinlockImpl() {
-  _lock = 0;
-}
-
-/**
- *
- */
-INLINE MutexSpinlockImpl::
-~MutexSpinlockImpl() {
+CONSTEXPR MutexSpinlockImpl::
+MutexSpinlockImpl() : _lock(0) {
 }
 
 /**

+ 6 - 2
dtool/src/dtoolbase/mutexSpinlockImpl.h

@@ -29,9 +29,13 @@
  */
 class EXPCL_DTOOL MutexSpinlockImpl {
 public:
-  INLINE MutexSpinlockImpl();
-  INLINE ~MutexSpinlockImpl();
+  CONSTEXPR MutexSpinlockImpl();
 
+private:
+  MutexSpinlockImpl(const MutexSpinlockImpl &copy) DELETED;
+  MutexSpinlockImpl &operator = (const MutexSpinlockImpl &copy) DELETED_ASSIGN;
+
+public:
   INLINE void acquire();
   INLINE bool try_acquire();
   INLINE void release();

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

@@ -31,6 +31,11 @@ public:
   MutexWin32Impl();
   INLINE ~MutexWin32Impl();
 
+private:
+  MutexWin32Impl(const MutexWin32Impl &copy) DELETED;
+  MutexWin32Impl &operator = (const MutexWin32Impl &copy) DELETED_ASSIGN;
+
+public:
   INLINE void acquire();
   INLINE bool try_acquire();
   INLINE void release();

+ 25 - 26
dtool/src/dtoolbase/pallocator.T

@@ -1,20 +1,19 @@
-// Filename: pallocator.T
-// Created by:  drose (05Jun01)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) Carnegie Mellon University.  All rights reserved.
-//
-// All use of this software is subject to the terms of the revised BSD
-// license.  You should have received a copy of this license along
-// with this source code in a file named "LICENSE."
-//
-////////////////////////////////////////////////////////////////////
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file pallocator.T
+ * @author drose
+ * @date 2001-06-05
+ */
 
 template<class Type>
 INLINE pallocator_single<Type>::
-pallocator_single(TypeHandle type_handle) throw() :
+pallocator_single(TypeHandle type_handle) NOEXCEPT :
   _type_handle(type_handle)
 {
 }
@@ -25,7 +24,8 @@ allocate(TYPENAME pallocator_single<Type>::size_type n, TYPENAME allocator<void>
   TAU_PROFILE("pallocator_single:allocate()", " ", TAU_USER);
   // This doesn't support allocating arrays.
   assert(n == 1);
-  return StaticDeletedChain<Type>::allocate(sizeof(Type), _type_handle);
+  return (Type *)ASSUME_ALIGNED(StaticDeletedChain<Type>::allocate(sizeof(Type), _type_handle),
+                                MEMORY_HOOK_ALIGNMENT);
 }
 
 template<class Type>
@@ -37,7 +37,7 @@ deallocate(TYPENAME pallocator_single<Type>::pointer p, TYPENAME pallocator_sing
 
 template<class Type>
 INLINE pallocator_array<Type>::
-pallocator_array(TypeHandle type_handle) throw() :
+pallocator_array(TypeHandle type_handle) NOEXCEPT :
   _type_handle(type_handle)
 {
 }
@@ -47,14 +47,13 @@ INLINE TYPENAME pallocator_array<Type>::pointer pallocator_array<Type>::
 allocate(TYPENAME pallocator_array<Type>::size_type n, TYPENAME allocator<void>::const_pointer) {
   TAU_PROFILE("pallocator_array:allocate()", " ", TAU_USER);
 #ifdef DO_MEMORY_USAGE
-  const size_t header_reserved_bytes = MemoryHook::get_header_reserved_bytes();
   size_t alloc_size = n * sizeof(Type);
-  // We also need to store the total number of bytes we allocated.
-  alloc_size += header_reserved_bytes;
-  _type_handle.inc_memory_usage(TypeHandle::MC_array, alloc_size);
   void *ptr = (TYPENAME pallocator_array<Type>::pointer)PANDA_MALLOC_ARRAY(alloc_size);
-  *((size_t *)ptr) = alloc_size;
-  return (TYPENAME pallocator_array<Type>::pointer)(((char *)ptr) + header_reserved_bytes);
+#ifdef _DEBUG
+  assert(alloc_size == MemoryHook::get_ptr_size(ptr));
+#endif
+  _type_handle.inc_memory_usage(TypeHandle::MC_array, alloc_size);
+  return (TYPENAME pallocator_array<Type>::pointer)ASSUME_ALIGNED(ptr, MEMORY_HOOK_ALIGNMENT);
 #else
   return (TYPENAME pallocator_array<Type>::pointer)PANDA_MALLOC_ARRAY(n * sizeof(Type));
 #endif  // DO_MEMORY_USAGE
@@ -65,10 +64,10 @@ INLINE void pallocator_array<Type>::
 deallocate(TYPENAME pallocator_array<Type>::pointer p, TYPENAME pallocator_array<Type>::size_type) {
   TAU_PROFILE("pallocator_array:deallocate()", " ", TAU_USER);
 #ifdef DO_MEMORY_USAGE
-  // Now we need to recover the total number of bytes.
-  const size_t header_reserved_bytes = MemoryHook::get_header_reserved_bytes();
-  void *ptr = (void *)((char *)p - header_reserved_bytes);
-  size_t alloc_size = *((size_t *)ptr);
+  // Now we need to recover the total number of bytes.  Fortunately, in the
+  // case of DO_MEMORY_USAGE, MemoryHook already keeps track of this.
+  void *ptr = (void *)p;
+  size_t alloc_size = MemoryHook::get_ptr_size(ptr);
   _type_handle.dec_memory_usage(TypeHandle::MC_array, alloc_size);
   PANDA_FREE_ARRAY(ptr);
 #else

+ 4 - 4
dtool/src/dtoolbase/pallocator.h

@@ -52,11 +52,11 @@ public:
   typedef TYPENAME allocator<Type>::const_reference const_reference;
   typedef TYPENAME allocator<Type>::size_type size_type;
 
-  INLINE pallocator_single(TypeHandle type_handle) throw();
+  INLINE pallocator_single(TypeHandle type_handle) NOEXCEPT;
 
   // template member functions in VC++ can only be defined in-class.
   template<class U>
-  INLINE pallocator_single(const pallocator_single<U> &copy) throw() :
+  INLINE pallocator_single(const pallocator_single<U> &copy) NOEXCEPT :
     _type_handle(copy._type_handle) { }
 
   INLINE pointer allocate(size_type n, allocator<void>::const_pointer hint = 0);
@@ -80,11 +80,11 @@ public:
   typedef TYPENAME allocator<Type>::const_reference const_reference;
   typedef TYPENAME allocator<Type>::size_type size_type;
 
-  INLINE pallocator_array(TypeHandle type_handle = TypeHandle::none()) throw();
+  INLINE pallocator_array(TypeHandle type_handle = TypeHandle::none()) NOEXCEPT;
 
   // template member functions in VC++ can only be defined in-class.
   template<class U>
-  INLINE pallocator_array(const pallocator_array<U> &copy) throw() :
+  INLINE pallocator_array(const pallocator_array<U> &copy) NOEXCEPT :
     _type_handle(copy._type_handle) { }
 
   INLINE pointer allocate(size_type n, allocator<void>::const_pointer hint = 0);

+ 0 - 1
dtool/src/dtoolbase/pdeque.h

@@ -37,7 +37,6 @@ public:
   typedef pallocator_array<Type> allocator;
   typedef TYPENAME deque<Type, allocator>::size_type size_type;
   pdeque(TypeHandle type_handle = pdeque_type_handle) : deque<Type, pallocator_array<Type> >(allocator(type_handle)) { }
-  pdeque(const pdeque<Type> &copy) : deque<Type, pallocator_array<Type> >(copy) { }
   pdeque(size_type n, TypeHandle type_handle = pdeque_type_handle) : deque<Type, pallocator_array<Type> >(n, Type(), allocator(type_handle)) { }
   pdeque(size_type n, const Type &value, TypeHandle type_handle = pdeque_type_handle) : deque<Type, pallocator_array<Type> >(n, value, allocator(type_handle)) { }
 };

+ 0 - 1
dtool/src/dtoolbase/plist.h

@@ -38,7 +38,6 @@ public:
   typedef list<Type, allocator> base_class;
   typedef TYPENAME base_class::size_type size_type;
   plist(TypeHandle type_handle = plist_type_handle) : base_class(allocator(type_handle)) { }
-  plist(const plist<Type> &copy) : base_class(copy) { }
   plist(size_type n, TypeHandle type_handle = plist_type_handle) : base_class(n, Type(), allocator(type_handle)) { }
   plist(size_type n, const Type &value, TypeHandle type_handle = plist_type_handle) : base_class(n, value, allocator(type_handle)) { }
 

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

@@ -52,7 +52,6 @@ public:
   typedef map<Key, Value, Compare, allocator> base_class;
 
   pmap(TypeHandle type_handle = pmap_type_handle) : base_class(Compare(), allocator(type_handle)) { }
-  pmap(const pmap<Key, Value, Compare> &copy) : base_class(copy) { }
   pmap(const Compare &comp, TypeHandle type_handle = pmap_type_handle) : base_class(comp, allocator(type_handle)) { }
 
 #ifdef USE_TAU
@@ -118,7 +117,6 @@ class pmultimap : public multimap<Key, Value, Compare, pallocator_single<pair<co
 public:
   typedef pallocator_single<pair<const Key, Value> > allocator;
   pmultimap(TypeHandle type_handle = pmap_type_handle) : multimap<Key, Value, Compare, allocator>(Compare(), allocator(type_handle)) { }
-  pmultimap(const pmultimap<Key, Value, Compare> &copy) : multimap<Key, Value, Compare, allocator>(copy) { }
   pmultimap(const Compare &comp, TypeHandle type_handle = pmap_type_handle) : multimap<Key, Value, Compare, allocator>(comp, allocator(type_handle)) { }
 };
 
@@ -132,7 +130,6 @@ template<class Key, class Value, class Compare = method_hash<Key, less<Key> > >
 class phash_map : public stdext::hash_map<Key, Value, Compare, pallocator_array<pair<const Key, Value> > > {
 public:
   phash_map() : stdext::hash_map<Key, Value, Compare, pallocator_array<pair<const Key, Value> > >() { }
-  phash_map(const phash_map<Key, Value, Compare> &copy) : stdext::hash_map<Key, Value, Compare, pallocator_array<pair<const Key, Value> > >(copy) { }
   phash_map(const Compare &comp) : stdext::hash_map<Key, Value, Compare, pallocator_array<pair<const Key, Value> > >(comp) { }
 };
 
@@ -145,7 +142,6 @@ template<class Key, class Value, class Compare = method_hash<Key, less<Key> > >
 class phash_multimap : public stdext::hash_multimap<Key, Value, Compare, pallocator_array<pair<const Key, Value> > > {
 public:
   phash_multimap() : stdext::hash_multimap<Key, Value, Compare, pallocator_array<pair<const Key, Value> > >() { }
-  phash_multimap(const phash_multimap<Key, Value, Compare> &copy) : stdext::hash_multimap<Key, Value, Compare, pallocator_array<pair<const Key, Value> > >(copy) { }
   phash_multimap(const Compare &comp) : stdext::hash_multimap<Key, Value, Compare, pallocator_array<pair<const Key, Value> > >(comp) { }
 };
 

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

@@ -51,7 +51,6 @@ public:
   typedef pallocator_single<Key> allocator;
   typedef set<Key, Compare, allocator> base_class;
   pset(TypeHandle type_handle = pset_type_handle) : base_class(Compare(), allocator(type_handle)) { }
-  pset(const pset<Key, Compare> &copy) : base_class(copy) { }
   pset(const Compare &comp, TypeHandle type_handle = pset_type_handle) : base_class(comp, type_handle) { }
 
 #ifdef USE_TAU
@@ -110,7 +109,6 @@ class pmultiset : public multiset<Key, Compare, pallocator_single<Key> > {
 public:
   typedef pallocator_single<Key> allocator;
   pmultiset(TypeHandle type_handle = pset_type_handle) : multiset<Key, Compare, allocator>(Compare(), allocator(type_handle)) { }
-  pmultiset(const pmultiset<Key, Compare> &copy) : multiset<Key, Compare, allocator>(copy) { }
   pmultiset(const Compare &comp, TypeHandle type_handle = pset_type_handle) : multiset<Key, Compare, allocator>(comp, type_handle) { }
 };
 
@@ -124,7 +122,6 @@ template<class Key, class Compare = method_hash<Key, less<Key> > >
 class phash_set : public stdext::hash_set<Key, Compare, pallocator_array<Key> > {
 public:
   phash_set() : stdext::hash_set<Key, Compare, pallocator_array<Key> >() { }
-  phash_set(const phash_set<Key, Compare> &copy) : stdext::hash_set<Key, Compare, pallocator_array<Key> >(copy) { }
   phash_set(const Compare &comp) : stdext::hash_set<Key, Compare, pallocator_array<Key> >(comp) { }
 };
 
@@ -137,7 +134,6 @@ template<class Key, class Compare = method_hash<Key, less<Key> > >
 class phash_multiset : public stdext::hash_multiset<Key, Compare, pallocator_array<Key> > {
 public:
   phash_multiset() : stdext::hash_multiset<Key, Compare, pallocator_array<Key> >() { }
-  phash_multiset(const phash_multiset<Key, Compare> &copy) : stdext::hash_multiset<Key, Compare, pallocator_array<Key> >(copy) { }
   phash_multiset(const Compare &comp) : stdext::hash_multiset<Key, Compare, pallocator_array<Key> >(comp) { }
 };
 

+ 0 - 15
dtool/src/dtoolbase/pvector.h

@@ -46,24 +46,9 @@ public:
   typedef TYPENAME base_class::size_type size_type;
 
   explicit pvector(TypeHandle type_handle = pvector_type_handle) : base_class(allocator(type_handle)) { }
-  pvector(const pvector<Type> &copy) : base_class(copy) { }
   explicit pvector(size_type n, TypeHandle type_handle = pvector_type_handle) : base_class(n, Type(), allocator(type_handle)) { }
   explicit pvector(size_type n, const Type &value, TypeHandle type_handle = pvector_type_handle) : base_class(n, value, allocator(type_handle)) { }
   pvector(const Type *begin, const Type *end, TypeHandle type_handle = pvector_type_handle) : base_class(begin, end, allocator(type_handle)) { }
-
-#ifdef USE_MOVE_SEMANTICS
-  pvector(pvector<Type> &&from) NOEXCEPT : base_class(move(from)) {};
-
-  pvector<Type> &operator =(pvector<Type> &&from) NOEXCEPT {
-    base_class::operator =(move(from));
-    return *this;
-  }
-#endif
-
-  pvector<Type> &operator =(const pvector<Type> &copy) {
-    base_class::operator =(copy);
-    return *this;
-  }
 };
 
 #endif  // USE_STL_ALLOCATOR

+ 0 - 21
dtool/src/dtoolbase/typedObject.I

@@ -11,27 +11,6 @@
  * @date 2001-05-11
  */
 
-/**
- *
- */
-INLINE TypedObject::
-TypedObject() {
-}
-
-/**
- *
- */
-INLINE TypedObject::
-TypedObject(const TypedObject &) {
-}
-
-/**
- *
- */
-INLINE void TypedObject::
-operator = (const TypedObject &) {
-}
-
 /**
  * Returns the internal index number associated with this object's TypeHandle,
  * a unique number for each different type.  This is equivalent to

+ 37 - 17
dtool/src/dtoolbase/typedObject.h

@@ -47,29 +47,49 @@
  * What follows are some examples that can be used in new classes that you
  * create.
  *
- * @par In the class definition (.h file): @code public: static TypeHandle
- * get_class_type() { return _type_handle; } static void init_type() {
- * <<<BaseClassOne>>>::init_type(); <<<BaseClassTwo>>>::init_type();
- * <<<BaseClassN>>>::init_type(); register_type(_type_handle,
- * "<<<ThisClassStringName>>>", <<<BaseClassOne>>>::get_class_type(),
- * <<<BaseClassTwo>>>::get_class_type(), <<<BaseClassN>>>::get_class_type());
- * } virtual TypeHandle get_type() const { return get_class_type(); } virtual
- * TypeHandle force_init_type() {init_type(); return get_class_type();}
+ * @par In the class definition (.h file):
+ * @code
+ * public:
+ *   static TypeHandle get_class_type() {
+ *     return _type_handle;
+ *   }
+ *   static void init_type() {
+ *     <<<BaseClassOne>>>::init_type();
+ *     <<<BaseClassTwo>>>::init_type();
+ *     <<<BaseClassN>>>::init_type();
+ *     register_type(_type_handle, "<<<ThisClassStringName>>>",
+ *                   <<<BaseClassOne>>>::get_class_type(),
+ *                   <<<BaseClassTwo>>>::get_class_type(),
+ *                   <<<BaseClassN>>>::get_class_type());
+ *   }
+ *   virtual TypeHandle get_type() const {
+ *     return get_class_type();
+ *   }
+ *   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
  *
- * private: static TypeHandle _type_handle; @endcode
+ * private:
+ *   static TypeHandle _type_handle;
+ * @endcode
  *
- * @par In the class .cxx file: @code TypeHandle
- * <<<ThisClassStringName>>>::_type_handle; @endcode
+ * @par In the class .cxx file:
+ * @code
+ * TypeHandle <<<ThisClassStringName>>>::_type_handle;
+ * @endcode
  *
- * @par In the class config_<<<PackageName>>>.cxx file: @code
- * ConfigureFn(config_<<<PackageName>>>) { <<<ClassOne>>>::init_type();
- * <<<ClassTwo>>>::init_type(); <<<ClassN>>>::init_type(); } @endcode
+ * @par In the class config_<<<PackageName>>>.cxx file:
+ * @code
+ * ConfigureFn(config_<<<PackageName>>>) {
+ *   <<<ClassOne>>>::init_type();
+ *   <<<ClassTwo>>>::init_type();
+ *   <<<ClassN>>>::init_type();
+ * }
+ * @endcode
  */
 class EXPCL_DTOOL TypedObject : public MemoryBase {
 public:
-  INLINE TypedObject();
-  INLINE TypedObject(const TypedObject &copy);
-  INLINE void operator = (const TypedObject &copy);
+  INLINE TypedObject() DEFAULT_CTOR;
+  INLINE TypedObject(const TypedObject &copy) DEFAULT_CTOR;
+  INLINE TypedObject &operator = (const TypedObject &copy) DEFAULT_ASSIGN;
 
 PUBLISHED:
   // A virtual destructor is just a good idea.

+ 10 - 1
dtool/src/interrogate/functionRemap.cxx

@@ -791,6 +791,15 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
     _args_type = InterfaceMaker::AT_single_arg;
   } else {
     _args_type = InterfaceMaker::AT_varargs;
+
+    // If the arguments are named "args" and "kwargs", we will be directly
+    // passing the argument tuples to the function.
+    if (_parameters.size() == first_param + 2 &&
+        _parameters[first_param]._name == "args" &&
+        (_parameters[first_param + 1]._name == "kwargs" ||
+          _parameters[first_param + 1]._name == "kwds")) {
+      _flags |= F_explicit_args;
+    }
   }
 
   switch (_type) {
@@ -890,7 +899,7 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
       if (_args_type == InterfaceMaker::AT_varargs) {
         // Every other method can take keyword arguments, if they take more
         // than one argument.
-        _args_type = InterfaceMaker::AT_keyword_args;
+        _args_type |= InterfaceMaker::AT_keyword_args;
       }
     }
     break;

+ 1 - 0
dtool/src/interrogate/functionRemap.h

@@ -100,6 +100,7 @@ public:
     F_coerce_constructor = 0x1000,
     F_divide_float       = 0x2000,
     F_hash               = 0x4000,
+    F_explicit_args      = 0x8000,
   };
 
   typedef vector<Parameter> Parameters;

+ 32 - 11
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -3453,7 +3453,13 @@ write_function_for_name(ostream &out, Object *obj,
     max_required_args = collapse_default_remaps(map_sets, max_required_args);
   }
 
-  if (map_sets.size() > 1 && (args_type == AT_varargs || args_type == AT_keyword_args)) {
+  if (remap->_flags & FunctionRemap::F_explicit_args) {
+    // We have a remap that wants to handle the wrapper itself.
+    string expected_params;
+    write_function_instance(out, remap, 0, 0, expected_params, 2, true, true,
+                            args_type, return_flags);
+
+  } else if (map_sets.size() > 1 && (args_type == AT_varargs || args_type == AT_keyword_args)) {
     switch (args_type) {
     case AT_keyword_args:
       indent(out, 2) << "int parameter_count = (int)PyTuple_Size(args);\n";
@@ -4536,19 +4542,23 @@ write_function_instance(ostream &out, FunctionRemap *remap,
   expected_params += methodNameFromCppName(remap, "", false);
   expected_params += "(";
 
-  int num_params = max_num_args;
-  if (remap->_has_this) {
-    num_params += 1;
-  }
-  if (num_params > (int)remap->_parameters.size()) {
-    // Limit to how many parameters this remap actually has.
-    num_params = (int)remap->_parameters.size();
-    max_num_args = num_params;
+  int num_params = 0;
+
+  if ((remap->_flags & FunctionRemap::F_explicit_args) == 0) {
+    num_params = max_num_args;
     if (remap->_has_this) {
-      --max_num_args;
+      num_params += 1;
     }
+    if (num_params > (int)remap->_parameters.size()) {
+      // Limit to how many parameters this remap actually has.
+      num_params = (int)remap->_parameters.size();
+      max_num_args = num_params;
+      if (remap->_has_this) {
+        --max_num_args;
+      }
+    }
+    nassertv(num_params <= (int)remap->_parameters.size());
   }
-  nassertv(num_params <= (int)remap->_parameters.size());
 
   bool only_pyobjects = true;
 
@@ -4584,6 +4594,17 @@ write_function_instance(ostream &out, FunctionRemap *remap,
     }
   }
 
+  if (remap->_flags & FunctionRemap::F_explicit_args) {
+    // The function handles the arguments by itself.
+    expected_params += "*args";
+    pexprs.push_back("args");
+    if (args_type == AT_keyword_args) {
+      expected_params += ", **kwargs";
+      pexprs.push_back("kwds");
+    }
+    num_params = 0;
+  }
+
   // Now convert (the rest of the) actual arguments, one by one.
   for (; pn < num_params; ++pn) {
     ParameterRemap *param = remap->_parameters[pn]._remap;

+ 3 - 0
dtool/src/prc/streamWrapper.h

@@ -25,6 +25,9 @@ class EXPCL_DTOOLCONFIG StreamWrapperBase {
 protected:
   INLINE StreamWrapperBase();
 
+private:
+  INLINE StreamWrapperBase(const StreamWrapperBase &copy) DELETED;
+
 PUBLISHED:
   INLINE void acquire();
   INLINE void release();

+ 1 - 1
dtool/src/prckeys/makePrcKey.cxx

@@ -161,7 +161,7 @@ write_public_keys(Filename outfile) {
       }
 
       output_c_string(out, "prc_pubkey", i, mbio);
-      BIO_reset(mbio);
+      (void)BIO_reset(mbio);
       out << "\n";
     }
   }

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

@@ -90,6 +90,7 @@ extern "C" {
   EXPCL_PYSTUB int PyModule_AddObject(...);
   EXPCL_PYSTUB int PyModule_AddStringConstant(...);
   EXPCL_PYSTUB int PyModule_Create2(...);
+  EXPCL_PYSTUB int PyModule_Create2TraceRefs(...);
   EXPCL_PYSTUB int PyNumber_Check(...);
   EXPCL_PYSTUB int PyNumber_Float(...);
   EXPCL_PYSTUB int PyNumber_Int(...);
@@ -175,6 +176,7 @@ extern "C" {
   EXPCL_PYSTUB int Py_InitModule4(...);
   EXPCL_PYSTUB int Py_InitModule4_64(...);
   EXPCL_PYSTUB int Py_InitModule4TraceRefs(...);
+  EXPCL_PYSTUB int Py_InitModule4TraceRefs_64(...);
   EXPCL_PYSTUB int _PyArg_ParseTuple_SizeT(...);
   EXPCL_PYSTUB int _PyArg_ParseTupleAndKeywords_SizeT(...);
   EXPCL_PYSTUB int _PyArg_Parse_SizeT(...);
@@ -184,9 +186,14 @@ extern "C" {
   EXPCL_PYSTUB int _PyObject_Del(...);
   EXPCL_PYSTUB int _PyUnicode_AsString(...);
   EXPCL_PYSTUB int _PyUnicode_AsStringAndSize(...);
+  EXPCL_PYSTUB int _Py_AddToAllObjects(...);
   EXPCL_PYSTUB int _Py_BuildValue_SizeT(...);
   EXPCL_PYSTUB int _Py_Dealloc(...);
+  EXPCL_PYSTUB int _Py_ForgetReference(...);
   EXPCL_PYSTUB int _Py_NegativeRefcount(...);
+  EXPCL_PYSTUB int _Py_NewReference(...);
+  EXPCL_PYSTUB int _Py_PrintReferenceAddresses(...);
+  EXPCL_PYSTUB int _Py_PrintReferences(...);
   EXPCL_PYSTUB int _Py_RefTotal(...);
 
   EXPCL_PYSTUB void Py_Initialize();
@@ -292,6 +299,7 @@ int PyModule_AddIntConstant(...) { return 0; };
 int PyModule_AddObject(...) { return 0; };
 int PyModule_AddStringConstant(...) { return 0; };
 int PyModule_Create2(...) { return 0; };
+int PyModule_Create2TraceRefs(...) { return 0; };
 int PyNumber_Check(...) { return 0; }
 int PyNumber_Float(...) { return 0; }
 int PyNumber_Int(...) { return 0; }
@@ -377,6 +385,7 @@ int Py_BuildValue(...) { return 0; }
 int Py_InitModule4(...) { return 0; }
 int Py_InitModule4_64(...) { return 0; }
 int Py_InitModule4TraceRefs(...) { return 0; };
+int Py_InitModule4TraceRefs_64(...) { return 0; };
 int _PyArg_ParseTuple_SizeT(...) { return 0; };
 int _PyArg_ParseTupleAndKeywords_SizeT(...) { return 0; };
 int _PyArg_Parse_SizeT(...) { return 0; };
@@ -386,9 +395,14 @@ int _PyObject_DebugFree(...) { return 0; };
 int _PyObject_Del(...) { return 0; };
 int _PyUnicode_AsString(...) { return 0; };
 int _PyUnicode_AsStringAndSize(...) { return 0; };
+int _Py_AddToAllObjects(...) { return 0; };
 int _Py_BuildValue_SizeT(...) { return 0; };
 int _Py_Dealloc(...) { return 0; };
+int _Py_ForgetReference(...) { return 0; };
 int _Py_NegativeRefcount(...) { return 0; };
+int _Py_NewReference(...) { return 0; };
+int _Py_PrintReferenceAddresses(...) { return 0; };
+int _Py_PrintReferences(...) { return 0; };
 int _Py_RefTotal(...) { return 0; };
 
 // We actually might call this one.

+ 145 - 128
makepanda/makepanda.py

@@ -81,7 +81,7 @@ PkgListSet(["PYTHON", "DIRECT",                        # Python support
   "ODE", "PHYSX", "BULLET", "PANDAPHYSICS",            # Physics
   "SPEEDTREE",                                         # SpeedTree
   "ZLIB", "PNG", "JPEG", "TIFF", "OPENEXR", "SQUISH", "FREETYPE", # 2D Formats support
-  ] + MAYAVERSIONS + MAXVERSIONS + [ "FCOLLADA", "ASSIMP", # 3D Formats support
+  ] + MAYAVERSIONS + MAXVERSIONS + [ "FCOLLADA", "ASSIMP", "EGG", # 3D Formats support
   "VRPN", "OPENSSL",                                   # Transport
   "FFTW",                                              # Algorithm helpers
   "ARTOOLKIT", "OPENCV", "DIRECTCAM", "VISION",        # Augmented Reality
@@ -840,7 +840,7 @@ if (COMPILER=="GCC"):
             if not RTDIST:
                 # We don't link anything in the SDK with libpython.
                 python_lib = ""
-            SmartPkgEnable("PYTHON", "", python_lib, (SDK["PYTHONVERSION"], SDK["PYTHONVERSION"] + "/Python.h"), tool = SDK["PYTHONVERSION"] + "-config")
+            SmartPkgEnable("PYTHON", "", python_lib, (SDK["PYTHONVERSION"], SDK["PYTHONVERSION"] + "/Python.h"))
 
     SmartPkgEnable("OPENSSL",   "openssl",   ("ssl", "crypto"), ("openssl/ssl.h", "openssl/crypto.h"))
     SmartPkgEnable("ZLIB",      "zlib",      ("z"), "zlib.h")
@@ -2235,7 +2235,6 @@ DTOOL_CONFIG=[
     ("HAVE_NET",                       'UNDEF',                  'UNDEF'),
     ("WANT_NATIVE_NET",                '1',                      '1'),
     ("SIMULATE_NETWORK_DELAY",         'UNDEF',                  'UNDEF'),
-    ("HAVE_EGG",                       '1',                      '1'),
     ("HAVE_CG",                        'UNDEF',                  'UNDEF'),
     ("HAVE_CGGL",                      'UNDEF',                  'UNDEF'),
     ("HAVE_CGDX9",                     'UNDEF',                  'UNDEF'),
@@ -2711,7 +2710,8 @@ if not PkgSkip("VISION"):
     panda_modules.append('vision')
 if not PkgSkip("SKEL"):
     panda_modules.append('skel')
-panda_modules.append('egg')
+if not PkgSkip("EGG"):
+    panda_modules.append('egg')
 if not PkgSkip("AWESOMIUM"):
     panda_modules.append('awesomium')
 if not PkgSkip("ODE"):
@@ -3065,15 +3065,17 @@ CopyAllHeaders('panda/src/downloadertools')
 CopyAllHeaders('panda/src/windisplay')
 CopyAllHeaders('panda/src/dxgsg9')
 CopyAllHeaders('panda/metalibs/pandadx9')
-CopyAllHeaders('panda/src/egg')
-CopyAllHeaders('panda/src/egg2pg')
+if not PkgSkip("EGG"):
+    CopyAllHeaders('panda/src/egg')
+    CopyAllHeaders('panda/src/egg2pg')
 CopyAllHeaders('panda/src/framework')
 CopyAllHeaders('panda/metalibs/pandafx')
 CopyAllHeaders('panda/src/glstuff')
 CopyAllHeaders('panda/src/glgsg')
 CopyAllHeaders('panda/src/glesgsg')
 CopyAllHeaders('panda/src/gles2gsg')
-CopyAllHeaders('panda/metalibs/pandaegg')
+if not PkgSkip("EGG"):
+    CopyAllHeaders('panda/metalibs/pandaegg')
 if GetTarget() == 'windows':
     CopyAllHeaders('panda/src/wgldisplay')
 elif GetTarget() == 'darwin':
@@ -4462,7 +4464,7 @@ if GetTarget() == 'windows' and PkgSkip("DX9")==0 and not RUNTIME:
 # DIRECTORY: panda/src/egg/
 #
 
-if (not RUNTIME):
+if not RUNTIME and not PkgSkip("EGG"):
   OPTS=['DIR:panda/src/egg', 'BUILDING:PANDAEGG', 'ZLIB', 'BISONPREFIX_eggyy', 'FLEXDASHI']
   CreateFile(GetOutputDir()+"/include/parser.h")
   TargetAdd('p3egg_parser.obj', opts=OPTS, input='parser.yxx')
@@ -4483,7 +4485,7 @@ if (not RUNTIME):
 # DIRECTORY: panda/src/egg2pg/
 #
 
-if (not RUNTIME):
+if not RUNTIME and not PkgSkip("EGG"):
   OPTS=['DIR:panda/src/egg2pg', 'BUILDING:PANDAEGG']
   TargetAdd('p3egg2pg_composite1.obj', opts=OPTS, input='p3egg2pg_composite1.cxx')
   TargetAdd('p3egg2pg_composite2.obj', opts=OPTS, input='p3egg2pg_composite2.cxx')
@@ -4502,11 +4504,13 @@ if (not RUNTIME):
   deps = []
   # Framework wants to link in a renderer when building statically, so tell it what is available.
   if GetLinkAllStatic():
-    deps = ['dtool_have_gl.dat', 'dtool_have_tinydisplay.dat']
+    deps = ['dtool_have_gl.dat', 'dtool_have_tinydisplay.dat', 'dtool_have_egg.dat']
     if not PkgSkip("GL"):
       DefSymbol("FRAMEWORK", "HAVE_GL")
     if not PkgSkip("TINYDISPLAY"):
       DefSymbol("FRAMEWORK", "HAVE_TINYDISPLAY")
+    if not PkgSkip("EGG"):
+      DefSymbol("FRAMEWORK", "HAVE_EGG")
 
   OPTS=['DIR:panda/src/framework', 'BUILDING:FRAMEWORK', 'FRAMEWORK']
   TargetAdd('p3framework_composite1.obj', opts=OPTS, input='p3framework_composite1.cxx', dep=deps)
@@ -4545,7 +4549,7 @@ if (not RUNTIME and PkgSkip("GLES2")==0):
 # DIRECTORY: panda/metalibs/pandaegg/
 #
 
-if (not RUNTIME):
+if not RUNTIME and not PkgSkip("EGG"):
   OPTS=['DIR:panda/metalibs/pandaegg', 'DIR:panda/src/egg', 'BUILDING:PANDAEGG']
   TargetAdd('pandaegg_pandaegg.obj', opts=OPTS, input='pandaegg.cxx')
 
@@ -4915,7 +4919,8 @@ if (not RTDIST and not RUNTIME and PkgSkip("PVIEW")==0 and GetTarget() != 'andro
   TargetAdd('pview_pview.obj', opts=OPTS, input='pview.cxx')
   TargetAdd('pview.exe', input='pview_pview.obj')
   TargetAdd('pview.exe', input='libp3framework.dll')
-  TargetAdd('pview.exe', input='libpandaegg.dll')
+  if not PkgSkip("EGG"):
+    TargetAdd('pview.exe', input='libpandaegg.dll')
   TargetAdd('pview.exe', input=COMMON_PANDA_LIBS)
   TargetAdd('pview.exe', opts=['ADVAPI', 'WINSOCK2', 'WINSHELL'])
 
@@ -4941,7 +4946,8 @@ if (not RUNTIME and GetTarget() == 'android'):
     TargetAdd('pview.exe', input='android_main.obj')
     TargetAdd('pview.exe', input='pview_pview.obj')
     TargetAdd('pview.exe', input='libp3framework.dll')
-    TargetAdd('pview.exe', input='libpandaegg.dll')
+    if not PkgSkip("EGG"):
+      TargetAdd('pview.exe', input='libpandaegg.dll')
     TargetAdd('pview.exe', input='libp3android.dll')
     TargetAdd('pview.exe', input=COMMON_PANDA_LIBS)
     TargetAdd('AndroidManifest.xml', opts=OPTS, input='pview_manifest.xml')
@@ -5495,7 +5501,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/converter/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/converter']
   TargetAdd('p3converter_somethingToEggConverter.obj', opts=OPTS, input='somethingToEggConverter.cxx')
   TargetAdd('p3converter_eggToSomethingConverter.obj', opts=OPTS, input='eggToSomethingConverter.cxx')
@@ -5506,7 +5512,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/progbase/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
   OPTS=['DIR:pandatool/src/progbase', 'ZLIB']
   TargetAdd('p3progbase_composite1.obj', opts=OPTS, input='p3progbase_composite1.cxx')
   TargetAdd('libp3progbase.lib', input='p3progbase_composite1.obj')
@@ -5515,7 +5521,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/eggbase/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/eggbase']
   TargetAdd('p3eggbase_composite1.obj', opts=OPTS, input='p3eggbase_composite1.cxx')
   TargetAdd('libp3eggbase.lib', input='p3eggbase_composite1.obj')
@@ -5524,31 +5530,31 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/bam/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
   OPTS=['DIR:pandatool/src/bam']
   TargetAdd('bam-info_bamInfo.obj', opts=OPTS, input='bamInfo.cxx')
   TargetAdd('bam-info.exe', input='bam-info_bamInfo.obj')
   TargetAdd('bam-info.exe', input='libp3progbase.lib')
   TargetAdd('bam-info.exe', input='libp3pandatoolbase.lib')
-  TargetAdd('bam-info.exe', input='libpandaegg.dll')
   TargetAdd('bam-info.exe', input=COMMON_PANDA_LIBS)
   TargetAdd('bam-info.exe', opts=['ADVAPI', 'FFTW'])
 
-  TargetAdd('bam2egg_bamToEgg.obj', opts=OPTS, input='bamToEgg.cxx')
-  TargetAdd('bam2egg.exe', input='bam2egg_bamToEgg.obj')
-  TargetAdd('bam2egg.exe', input=COMMON_EGG2X_LIBS)
-  TargetAdd('bam2egg.exe', opts=['ADVAPI',  'FFTW'])
+  if not PkgSkip("EGG"):
+    TargetAdd('bam2egg_bamToEgg.obj', opts=OPTS, input='bamToEgg.cxx')
+    TargetAdd('bam2egg.exe', input='bam2egg_bamToEgg.obj')
+    TargetAdd('bam2egg.exe', input=COMMON_EGG2X_LIBS)
+    TargetAdd('bam2egg.exe', opts=['ADVAPI',  'FFTW'])
 
-  TargetAdd('egg2bam_eggToBam.obj', opts=OPTS, input='eggToBam.cxx')
-  TargetAdd('egg2bam.exe', input='egg2bam_eggToBam.obj')
-  TargetAdd('egg2bam.exe', input=COMMON_EGG2X_LIBS)
-  TargetAdd('egg2bam.exe', opts=['ADVAPI',  'FFTW'])
+    TargetAdd('egg2bam_eggToBam.obj', opts=OPTS, input='eggToBam.cxx')
+    TargetAdd('egg2bam.exe', input='egg2bam_eggToBam.obj')
+    TargetAdd('egg2bam.exe', input=COMMON_EGG2X_LIBS)
+    TargetAdd('egg2bam.exe', opts=['ADVAPI',  'FFTW'])
 
 #
 # DIRECTORY: pandatool/src/cvscopy/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
   OPTS=['DIR:pandatool/src/cvscopy']
   TargetAdd('p3cvscopy_composite1.obj', opts=OPTS, input='p3cvscopy_composite1.cxx')
   TargetAdd('libp3cvscopy.lib', input='p3cvscopy_composite1.obj')
@@ -5556,7 +5562,7 @@ if (PkgSkip("PANDATOOL")==0):
 #
 # DIRECTORY: pandatool/src/daeegg/
 #
-if (PkgSkip("PANDATOOL")==0 and PkgSkip("FCOLLADA")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("FCOLLADA") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/daeegg', 'FCOLLADA']
   TargetAdd('p3daeegg_composite1.obj', opts=OPTS, input='p3daeegg_composite1.cxx')
   TargetAdd('libp3daeegg.lib', input='p3daeegg_composite1.obj')
@@ -5565,7 +5571,7 @@ if (PkgSkip("PANDATOOL")==0 and PkgSkip("FCOLLADA")==0):
 #
 # DIRECTORY: pandatool/src/assimp
 #
-if (PkgSkip("PANDATOOL") == 0 and PkgSkip("ASSIMP")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("ASSIMP"):
   OPTS=['DIR:pandatool/src/assimp', 'BUILDING:ASSIMP', 'ASSIMP', 'MODULE']
   TargetAdd('p3assimp_composite1.obj', opts=OPTS, input='p3assimp_composite1.cxx')
   TargetAdd('libp3assimp.dll', input='p3assimp_composite1.obj')
@@ -5575,7 +5581,7 @@ if (PkgSkip("PANDATOOL") == 0 and PkgSkip("ASSIMP")==0):
 #
 # DIRECTORY: pandatool/src/daeprogs/
 #
-if (PkgSkip("PANDATOOL")==0 and PkgSkip("FCOLLADA")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("FCOLLADA") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/daeprogs', 'FCOLLADA']
   TargetAdd('dae2egg_daeToEgg.obj', opts=OPTS, input='daeToEgg.cxx')
   TargetAdd('dae2egg.exe', input='dae2egg_daeToEgg.obj')
@@ -5587,7 +5593,7 @@ if (PkgSkip("PANDATOOL")==0 and PkgSkip("FCOLLADA")==0):
 # DIRECTORY: pandatool/src/dxf/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
   OPTS=['DIR:pandatool/src/dxf']
   TargetAdd('p3dxf_composite1.obj', opts=OPTS, input='p3dxf_composite1.cxx')
   TargetAdd('libp3dxf.lib', input='p3dxf_composite1.obj')
@@ -5596,7 +5602,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/dxfegg/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/dxfegg']
   TargetAdd('p3dxfegg_dxfToEggConverter.obj', opts=OPTS, input='dxfToEggConverter.cxx')
   TargetAdd('p3dxfegg_dxfToEggLayer.obj', opts=OPTS, input='dxfToEggLayer.cxx')
@@ -5607,7 +5613,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/dxfprogs/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
   OPTS=['DIR:pandatool/src/dxfprogs']
   TargetAdd('dxf-points_dxfPoints.obj', opts=OPTS, input='dxfPoints.cxx')
   TargetAdd('dxf-points.exe', input='dxf-points_dxfPoints.obj')
@@ -5617,26 +5623,27 @@ if (PkgSkip("PANDATOOL")==0):
   TargetAdd('dxf-points.exe', input=COMMON_PANDA_LIBS)
   TargetAdd('dxf-points.exe', opts=['ADVAPI',  'FFTW'])
 
-  TargetAdd('dxf2egg_dxfToEgg.obj', opts=OPTS, input='dxfToEgg.cxx')
-  TargetAdd('dxf2egg.exe', input='dxf2egg_dxfToEgg.obj')
-  TargetAdd('dxf2egg.exe', input='libp3dxfegg.lib')
-  TargetAdd('dxf2egg.exe', input='libp3dxf.lib')
-  TargetAdd('dxf2egg.exe', input=COMMON_EGG2X_LIBS)
-  TargetAdd('dxf2egg.exe', opts=['ADVAPI',  'FFTW'])
+  if not PkgSkip("EGG"):
+    TargetAdd('dxf2egg_dxfToEgg.obj', opts=OPTS, input='dxfToEgg.cxx')
+    TargetAdd('dxf2egg.exe', input='dxf2egg_dxfToEgg.obj')
+    TargetAdd('dxf2egg.exe', input='libp3dxfegg.lib')
+    TargetAdd('dxf2egg.exe', input='libp3dxf.lib')
+    TargetAdd('dxf2egg.exe', input=COMMON_EGG2X_LIBS)
+    TargetAdd('dxf2egg.exe', opts=['ADVAPI',  'FFTW'])
 
-  TargetAdd('egg2dxf_eggToDXF.obj', opts=OPTS, input='eggToDXF.cxx')
-  TargetAdd('egg2dxf_eggToDXFLayer.obj', opts=OPTS, input='eggToDXFLayer.cxx')
-  TargetAdd('egg2dxf.exe', input='egg2dxf_eggToDXF.obj')
-  TargetAdd('egg2dxf.exe', input='egg2dxf_eggToDXFLayer.obj')
-  TargetAdd('egg2dxf.exe', input='libp3dxf.lib')
-  TargetAdd('egg2dxf.exe', input=COMMON_EGG2X_LIBS)
-  TargetAdd('egg2dxf.exe', opts=['ADVAPI',  'FFTW'])
+    TargetAdd('egg2dxf_eggToDXF.obj', opts=OPTS, input='eggToDXF.cxx')
+    TargetAdd('egg2dxf_eggToDXFLayer.obj', opts=OPTS, input='eggToDXFLayer.cxx')
+    TargetAdd('egg2dxf.exe', input='egg2dxf_eggToDXF.obj')
+    TargetAdd('egg2dxf.exe', input='egg2dxf_eggToDXFLayer.obj')
+    TargetAdd('egg2dxf.exe', input='libp3dxf.lib')
+    TargetAdd('egg2dxf.exe', input=COMMON_EGG2X_LIBS)
+    TargetAdd('egg2dxf.exe', opts=['ADVAPI',  'FFTW'])
 
 #
 # DIRECTORY: pandatool/src/objegg/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/objegg']
   TargetAdd('p3objegg_objToEggConverter.obj', opts=OPTS, input='objToEggConverter.cxx')
   TargetAdd('p3objegg_eggToObjConverter.obj', opts=OPTS, input='eggToObjConverter.cxx')
@@ -5649,7 +5656,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/objprogs/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/objprogs']
   TargetAdd('obj2egg_objToEgg.obj', opts=OPTS, input='objToEgg.cxx')
   TargetAdd('obj2egg.exe', input='obj2egg_objToEgg.obj')
@@ -5665,7 +5672,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/palettizer/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/palettizer']
   TargetAdd('p3palettizer_composite1.obj', opts=OPTS, input='p3palettizer_composite1.cxx')
   TargetAdd('libp3palettizer.lib', input='p3palettizer_composite1.obj')
@@ -5674,7 +5681,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/egg-mkfont/
 #
 
-if (PkgSkip("FREETYPE")==0) and (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("FREETYPE") and not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/egg-mkfont', 'DIR:pandatool/src/palettizer', 'FREETYPE']
   TargetAdd('egg-mkfont_eggMakeFont.obj', opts=OPTS, input='eggMakeFont.cxx')
   TargetAdd('egg-mkfont_rangeDescription.obj', opts=OPTS, input='rangeDescription.cxx')
@@ -5690,7 +5697,7 @@ if (PkgSkip("FREETYPE")==0) and (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/eggcharbase/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/eggcharbase', 'ZLIB']
   TargetAdd('p3eggcharbase_composite1.obj', opts=OPTS, input='p3eggcharbase_composite1.cxx')
   TargetAdd('libp3eggcharbase.lib', input='p3eggcharbase_composite1.obj')
@@ -5699,7 +5706,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/egg-optchar/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/egg-optchar']
   TargetAdd('egg-optchar_config_egg_optchar.obj', opts=OPTS, input='config_egg_optchar.cxx')
   TargetAdd('egg-optchar_eggOptchar.obj', opts=OPTS, input='eggOptchar.cxx')
@@ -5717,7 +5724,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/egg-palettize/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/egg-palettize', 'DIR:pandatool/src/palettizer']
   TargetAdd('egg-palettize_eggPalettize.obj', opts=OPTS, input='eggPalettize.cxx')
   TargetAdd('egg-palettize.exe', input='egg-palettize_eggPalettize.obj')
@@ -5729,7 +5736,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/egg-qtess/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/egg-qtess']
   TargetAdd('egg-qtess_composite1.obj', opts=OPTS, input='egg-qtess_composite1.cxx')
   TargetAdd('egg-qtess.exe', input='egg-qtess_composite1.obj')
@@ -5743,7 +5750,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/eggprogs/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/eggprogs']
   TargetAdd('egg-crop_eggCrop.obj', opts=OPTS, input='eggCrop.cxx')
   TargetAdd('egg-crop.exe', input='egg-crop_eggCrop.obj')
@@ -5796,7 +5803,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/flt/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
   OPTS=['DIR:pandatool/src/flt', 'ZLIB']
   TargetAdd('p3flt_composite1.obj', opts=OPTS, input='p3flt_composite1.cxx')
   TargetAdd('libp3flt.lib', input=['p3flt_composite1.obj'])
@@ -5805,7 +5812,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/fltegg/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/fltegg']
   TargetAdd('p3fltegg_fltToEggConverter.obj', opts=OPTS, input='fltToEggConverter.cxx')
   TargetAdd('p3fltegg_fltToEggLevelState.obj', opts=OPTS, input='fltToEggLevelState.cxx')
@@ -5815,46 +5822,52 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/fltprogs/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
   OPTS=['DIR:pandatool/src/fltprogs', 'DIR:pandatool/src/flt', 'DIR:pandatool/src/cvscopy']
-  TargetAdd('egg2flt_eggToFlt.obj', opts=OPTS, input='eggToFlt.cxx')
-  TargetAdd('egg2flt.exe', input='egg2flt_eggToFlt.obj')
-  TargetAdd('egg2flt.exe', input='libp3flt.lib')
-  TargetAdd('egg2flt.exe', input=COMMON_EGG2X_LIBS)
-  TargetAdd('egg2flt.exe', opts=['ADVAPI'])
-
   TargetAdd('flt-info_fltInfo.obj', opts=OPTS, input='fltInfo.cxx')
   TargetAdd('flt-info.exe', input='flt-info_fltInfo.obj')
   TargetAdd('flt-info.exe', input='libp3flt.lib')
-  TargetAdd('flt-info.exe', input=COMMON_EGG2X_LIBS)
+  TargetAdd('flt-info.exe', input='libp3progbase.lib')
+  TargetAdd('flt-info.exe', input='libp3pandatoolbase.lib')
+  TargetAdd('flt-info.exe', input=COMMON_PANDA_LIBS)
   TargetAdd('flt-info.exe', opts=['ADVAPI'])
 
   TargetAdd('flt-trans_fltTrans.obj', opts=OPTS, input='fltTrans.cxx')
   TargetAdd('flt-trans.exe', input='flt-trans_fltTrans.obj')
   TargetAdd('flt-trans.exe', input='libp3flt.lib')
-  TargetAdd('flt-trans.exe', input=COMMON_EGG2X_LIBS)
+  TargetAdd('flt-trans.exe', input='libp3progbase.lib')
+  TargetAdd('flt-trans.exe', input='libp3pandatoolbase.lib')
+  TargetAdd('flt-trans.exe', input=COMMON_PANDA_LIBS)
   TargetAdd('flt-trans.exe', opts=['ADVAPI'])
 
-  TargetAdd('flt2egg_fltToEgg.obj', opts=OPTS, input='fltToEgg.cxx')
-  TargetAdd('flt2egg.exe', input='flt2egg_fltToEgg.obj')
-  TargetAdd('flt2egg.exe', input='libp3flt.lib')
-  TargetAdd('flt2egg.exe', input='libp3fltegg.lib')
-  TargetAdd('flt2egg.exe', input=COMMON_EGG2X_LIBS)
-  TargetAdd('flt2egg.exe', opts=['ADVAPI'])
-
   TargetAdd('fltcopy_fltCopy.obj', opts=OPTS, input='fltCopy.cxx')
   TargetAdd('fltcopy.exe', input='fltcopy_fltCopy.obj')
   TargetAdd('fltcopy.exe', input='libp3cvscopy.lib')
   TargetAdd('fltcopy.exe', input='libp3flt.lib')
-  TargetAdd('fltcopy.exe', input=COMMON_EGG2X_LIBS)
+  TargetAdd('fltcopy.exe', input='libp3progbase.lib')
+  TargetAdd('fltcopy.exe', input='libp3pandatoolbase.lib')
+  TargetAdd('fltcopy.exe', input=COMMON_PANDA_LIBS)
   TargetAdd('fltcopy.exe', opts=['ADVAPI'])
 
+  if not PkgSkip("EGG"):
+    TargetAdd('egg2flt_eggToFlt.obj', opts=OPTS, input='eggToFlt.cxx')
+    TargetAdd('egg2flt.exe', input='egg2flt_eggToFlt.obj')
+    TargetAdd('egg2flt.exe', input='libp3flt.lib')
+    TargetAdd('egg2flt.exe', input=COMMON_EGG2X_LIBS)
+    TargetAdd('egg2flt.exe', opts=['ADVAPI'])
+
+    TargetAdd('flt2egg_fltToEgg.obj', opts=OPTS, input='fltToEgg.cxx')
+    TargetAdd('flt2egg.exe', input='flt2egg_fltToEgg.obj')
+    TargetAdd('flt2egg.exe', input='libp3flt.lib')
+    TargetAdd('flt2egg.exe', input='libp3fltegg.lib')
+    TargetAdd('flt2egg.exe', input=COMMON_EGG2X_LIBS)
+    TargetAdd('flt2egg.exe', opts=['ADVAPI'])
 
 #
 # DIRECTORY: pandatool/src/imagebase/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
   OPTS=['DIR:pandatool/src/imagebase']
   TargetAdd('p3imagebase_composite1.obj', opts=OPTS, input='p3imagebase_composite1.cxx')
   TargetAdd('libp3imagebase.lib', input='p3imagebase_composite1.obj')
@@ -5863,14 +5876,13 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/imageprogs/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
   OPTS=['DIR:pandatool/src/imageprogs']
   TargetAdd('image-info_imageInfo.obj', opts=OPTS, input='imageInfo.cxx')
   TargetAdd('image-info.exe', input='image-info_imageInfo.obj')
   TargetAdd('image-info.exe', input='libp3imagebase.lib')
   TargetAdd('image-info.exe', input='libp3progbase.lib')
   TargetAdd('image-info.exe', input='libp3pandatoolbase.lib')
-  TargetAdd('image-info.exe', input='libpandaegg.dll')
   TargetAdd('image-info.exe', input=COMMON_PANDA_LIBS)
   TargetAdd('image-info.exe', opts=['ADVAPI'])
 
@@ -5879,7 +5891,6 @@ if (PkgSkip("PANDATOOL")==0):
   TargetAdd('image-resize.exe', input='libp3imagebase.lib')
   TargetAdd('image-resize.exe', input='libp3progbase.lib')
   TargetAdd('image-resize.exe', input='libp3pandatoolbase.lib')
-  TargetAdd('image-resize.exe', input='libpandaegg.dll')
   TargetAdd('image-resize.exe', input=COMMON_PANDA_LIBS)
   TargetAdd('image-resize.exe', opts=['ADVAPI'])
 
@@ -5888,7 +5899,6 @@ if (PkgSkip("PANDATOOL")==0):
   TargetAdd('image-trans.exe', input='libp3imagebase.lib')
   TargetAdd('image-trans.exe', input='libp3progbase.lib')
   TargetAdd('image-trans.exe', input='libp3pandatoolbase.lib')
-  TargetAdd('image-trans.exe', input='libpandaegg.dll')
   TargetAdd('image-trans.exe', input=COMMON_PANDA_LIBS)
   TargetAdd('image-trans.exe', opts=['ADVAPI'])
 
@@ -5896,7 +5906,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/pfmprogs/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
   OPTS=['DIR:pandatool/src/pfmprogs']
   TargetAdd('pfm-trans_pfmTrans.obj', opts=OPTS, input='pfmTrans.cxx')
   TargetAdd('pfm-trans.exe', input='pfm-trans_pfmTrans.obj')
@@ -5918,7 +5928,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/lwo/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
   OPTS=['DIR:pandatool/src/lwo']
   TargetAdd('p3lwo_composite1.obj', opts=OPTS, input='p3lwo_composite1.cxx')
   TargetAdd('libp3lwo.lib', input='p3lwo_composite1.obj')
@@ -5927,7 +5937,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/lwoegg/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/lwoegg']
   TargetAdd('p3lwoegg_composite1.obj', opts=OPTS, input='p3lwoegg_composite1.cxx')
   TargetAdd('libp3lwoegg.lib', input='p3lwoegg_composite1.obj')
@@ -5936,23 +5946,23 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/lwoprogs/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
   OPTS=['DIR:pandatool/src/lwoprogs', 'DIR:pandatool/src/lwo']
   TargetAdd('lwo-scan_lwoScan.obj', opts=OPTS, input='lwoScan.cxx')
   TargetAdd('lwo-scan.exe', input='lwo-scan_lwoScan.obj')
   TargetAdd('lwo-scan.exe', input='libp3lwo.lib')
   TargetAdd('lwo-scan.exe', input='libp3progbase.lib')
   TargetAdd('lwo-scan.exe', input='libp3pandatoolbase.lib')
-  TargetAdd('lwo-scan.exe', input='libpandaegg.dll')
   TargetAdd('lwo-scan.exe', input=COMMON_PANDA_LIBS)
   TargetAdd('lwo-scan.exe', opts=['ADVAPI'])
 
-  TargetAdd('lwo2egg_lwoToEgg.obj', opts=OPTS, input='lwoToEgg.cxx')
-  TargetAdd('lwo2egg.exe', input='lwo2egg_lwoToEgg.obj')
-  TargetAdd('lwo2egg.exe', input='libp3lwo.lib')
-  TargetAdd('lwo2egg.exe', input='libp3lwoegg.lib')
-  TargetAdd('lwo2egg.exe', input=COMMON_EGG2X_LIBS)
-  TargetAdd('lwo2egg.exe', opts=['ADVAPI'])
+  if not PkgSkip("EGG"):
+    TargetAdd('lwo2egg_lwoToEgg.obj', opts=OPTS, input='lwoToEgg.cxx')
+    TargetAdd('lwo2egg.exe', input='lwo2egg_lwoToEgg.obj')
+    TargetAdd('lwo2egg.exe', input='libp3lwo.lib')
+    TargetAdd('lwo2egg.exe', input='libp3lwoegg.lib')
+    TargetAdd('lwo2egg.exe', input=COMMON_EGG2X_LIBS)
+    TargetAdd('lwo2egg.exe', opts=['ADVAPI'])
 
 #
 # DIRECTORY: pandatool/src/maya/
@@ -5960,7 +5970,7 @@ if (PkgSkip("PANDATOOL")==0):
 
 for VER in MAYAVERSIONS:
   VNUM=VER[4:]
-  if (PkgSkip(VER)==0) and (PkgSkip("PANDATOOL")==0):
+  if not PkgSkip(VER) and not PkgSkip("PANDATOOL"):
     OPTS=['DIR:pandatool/src/maya', VER]
     TargetAdd('maya'+VNUM+'_composite1.obj', opts=OPTS, input='p3maya_composite1.cxx')
     TargetAdd('libmaya'+VNUM+'.lib', input='maya'+VNUM+'_composite1.obj')
@@ -5971,7 +5981,7 @@ for VER in MAYAVERSIONS:
 
 for VER in MAYAVERSIONS:
   VNUM=VER[4:]
-  if (PkgSkip(VER)==0) and (PkgSkip("PANDATOOL")==0):
+  if not PkgSkip(VER) and not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
     OPTS=['DIR:pandatool/src/mayaegg', 'DIR:pandatool/src/maya', VER]
     TargetAdd('mayaegg'+VNUM+'_loader.obj', opts=OPTS, input='mayaEggLoader.cxx')
     TargetAdd('mayaegg'+VNUM+'_composite1.obj', opts=OPTS, input='p3mayaegg_composite1.cxx')
@@ -5984,7 +5994,7 @@ for VER in MAYAVERSIONS:
 
 for VER in MAXVERSIONS:
   VNUM=VER[3:]
-  if (PkgSkip(VER)==0) and (PkgSkip("PANDATOOL")==0):
+  if not PkgSkip(VER) and not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
     OPTS=['DIR:pandatool/src/maxegg', VER,  "WINCOMCTL", "WINCOMDLG", "WINUSER", "MSFORSCOPE", "RTTI"]
     TargetAdd('maxEgg'+VNUM+'.res', opts=OPTS, input='maxEgg.rc')
     TargetAdd('maxegg'+VNUM+'_loader.obj', opts=OPTS, input='maxEggLoader.cxx')
@@ -6001,7 +6011,7 @@ for VER in MAXVERSIONS:
 
 for VER in MAXVERSIONS:
   VNUM=VER[3:]
-  if (PkgSkip(VER)==0) and (PkgSkip("PANDATOOL")==0):
+  if not PkgSkip(VER) and not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
     OPTS=['DIR:pandatool/src/maxprogs', VER,  "WINCOMCTL", "WINCOMDLG", "WINUSER", "MSFORSCOPE", "RTTI"]
     TargetAdd('maxImportRes.res', opts=OPTS, input='maxImportRes.rc')
     TargetAdd('maxprogs'+VNUM+'_maxeggimport.obj', opts=OPTS, input='maxEggImport.cxx')
@@ -6019,7 +6029,7 @@ for VER in MAXVERSIONS:
 # DIRECTORY: pandatool/src/vrml/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
   OPTS=['DIR:pandatool/src/vrml', 'ZLIB', 'BISONPREFIX_vrmlyy']
   CreateFile(GetOutputDir()+"/include/vrmlParser.h")
   TargetAdd('p3vrml_vrmlParser.obj', opts=OPTS, input='vrmlParser.yxx')
@@ -6040,7 +6050,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/vrmlegg/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
   OPTS=['DIR:pandatool/src/vrmlegg', 'DIR:pandatool/src/vrml']
   TargetAdd('p3vrmlegg_indexedFaceSet.obj', opts=OPTS, input='indexedFaceSet.cxx')
   TargetAdd('p3vrmlegg_vrmlAppearance.obj', opts=OPTS, input='vrmlAppearance.cxx')
@@ -6053,7 +6063,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/xfile/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
     OPTS=['DIR:pandatool/src/xfile', 'ZLIB', 'BISONPREFIX_xyy', 'FLEXDASHI']
     CreateFile(GetOutputDir()+"/include/xParser.h")
     TargetAdd('p3xfile_xParser.obj', opts=OPTS, input='xParser.yxx')
@@ -6068,7 +6078,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/xfileegg/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
     OPTS=['DIR:pandatool/src/xfileegg', 'DIR:pandatool/src/xfile']
     TargetAdd('p3xfileegg_composite1.obj', opts=OPTS, input='p3xfileegg_composite1.cxx')
     TargetAdd('libp3xfileegg.lib', input='p3xfileegg_composite1.obj')
@@ -6077,7 +6087,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/ptloader/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
     if not PkgSkip("FCOLLADA"):
         DefSymbol("FCOLLADA", "HAVE_FCOLLADA")
 
@@ -6143,7 +6153,6 @@ if (PkgSkip("PANDATOOL")==0):
     TargetAdd('softcvs.exe', input='softcvs_softFilename.obj')
     TargetAdd('softcvs.exe', input='libp3progbase.lib')
     TargetAdd('softcvs.exe', input='libp3pandatoolbase.lib')
-    TargetAdd('softcvs.exe', input='libpandaegg.dll')
     TargetAdd('softcvs.exe', input=COMMON_PANDA_LIBS)
     TargetAdd('softcvs.exe', opts=['ADVAPI'])
 
@@ -6160,7 +6169,6 @@ if (PkgSkip("PANDATOOL")==0):
     TargetAdd('text-stats.exe', input='libp3progbase.lib')
     TargetAdd('text-stats.exe', input='libp3pstatserver.lib')
     TargetAdd('text-stats.exe', input='libp3pandatoolbase.lib')
-    TargetAdd('text-stats.exe', input='libpandaegg.dll')
     TargetAdd('text-stats.exe', input=COMMON_PANDA_LIBS)
     TargetAdd('text-stats.exe', opts=['ADVAPI'])
 
@@ -6168,7 +6176,7 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/vrmlprogs/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
     OPTS=['DIR:pandatool/src/vrmlprogs', 'DIR:pandatool/src/vrml', 'DIR:pandatool/src/vrmlegg']
     TargetAdd('vrml-trans_vrmlTrans.obj', opts=OPTS, input='vrmlTrans.cxx')
     TargetAdd('vrml-trans.exe', input='vrml-trans_vrmlTrans.obj')
@@ -6178,12 +6186,13 @@ if (PkgSkip("PANDATOOL")==0):
     TargetAdd('vrml-trans.exe', input=COMMON_PANDA_LIBS)
     TargetAdd('vrml-trans.exe', opts=['ADVAPI'])
 
-    TargetAdd('vrml2egg_vrmlToEgg.obj', opts=OPTS, input='vrmlToEgg.cxx')
-    TargetAdd('vrml2egg.exe', input='vrml2egg_vrmlToEgg.obj')
-    TargetAdd('vrml2egg.exe', input='libp3vrmlegg.lib')
-    TargetAdd('vrml2egg.exe', input='libp3vrml.lib')
-    TargetAdd('vrml2egg.exe', input=COMMON_EGG2X_LIBS)
-    TargetAdd('vrml2egg.exe', opts=['ADVAPI'])
+    if not PkgSkip("EGG"):
+        TargetAdd('vrml2egg_vrmlToEgg.obj', opts=OPTS, input='vrmlToEgg.cxx')
+        TargetAdd('vrml2egg.exe', input='vrml2egg_vrmlToEgg.obj')
+        TargetAdd('vrml2egg.exe', input='libp3vrmlegg.lib')
+        TargetAdd('vrml2egg.exe', input='libp3vrml.lib')
+        TargetAdd('vrml2egg.exe', input=COMMON_EGG2X_LIBS)
+        TargetAdd('vrml2egg.exe', opts=['ADVAPI'])
 
 #
 # DIRECTORY: pandatool/src/win-stats/
@@ -6208,15 +6217,8 @@ if (PkgSkip("PANDATOOL")==0 and (GetTarget() == 'windows' or PkgSkip("GTK2")==0)
 # DIRECTORY: pandatool/src/xfileprogs/
 #
 
-if (PkgSkip("PANDATOOL")==0):
+if not PkgSkip("PANDATOOL"):
     OPTS=['DIR:pandatool/src/xfileprogs', 'DIR:pandatool/src/xfile', 'DIR:pandatool/src/xfileegg']
-    TargetAdd('egg2x_eggToX.obj', opts=OPTS, input='eggToX.cxx')
-    TargetAdd('egg2x.exe', input='egg2x_eggToX.obj')
-    TargetAdd('egg2x.exe', input='libp3xfileegg.lib')
-    TargetAdd('egg2x.exe', input='libp3xfile.lib')
-    TargetAdd('egg2x.exe', input=COMMON_EGG2X_LIBS)
-    TargetAdd('egg2x.exe', opts=['ADVAPI'])
-
     TargetAdd('x-trans_xFileTrans.obj', opts=OPTS, input='xFileTrans.cxx')
     TargetAdd('x-trans.exe', input='x-trans_xFileTrans.obj')
     TargetAdd('x-trans.exe', input='libp3progbase.lib')
@@ -6225,12 +6227,20 @@ if (PkgSkip("PANDATOOL")==0):
     TargetAdd('x-trans.exe', input=COMMON_PANDA_LIBS)
     TargetAdd('x-trans.exe', opts=['ADVAPI'])
 
-    TargetAdd('x2egg_xFileToEgg.obj', opts=OPTS, input='xFileToEgg.cxx')
-    TargetAdd('x2egg.exe', input='x2egg_xFileToEgg.obj')
-    TargetAdd('x2egg.exe', input='libp3xfileegg.lib')
-    TargetAdd('x2egg.exe', input='libp3xfile.lib')
-    TargetAdd('x2egg.exe', input=COMMON_EGG2X_LIBS)
-    TargetAdd('x2egg.exe', opts=['ADVAPI'])
+    if not PkgSkip("EGG"):
+        TargetAdd('egg2x_eggToX.obj', opts=OPTS, input='eggToX.cxx')
+        TargetAdd('egg2x.exe', input='egg2x_eggToX.obj')
+        TargetAdd('egg2x.exe', input='libp3xfileegg.lib')
+        TargetAdd('egg2x.exe', input='libp3xfile.lib')
+        TargetAdd('egg2x.exe', input=COMMON_EGG2X_LIBS)
+        TargetAdd('egg2x.exe', opts=['ADVAPI'])
+
+        TargetAdd('x2egg_xFileToEgg.obj', opts=OPTS, input='xFileToEgg.cxx')
+        TargetAdd('x2egg.exe', input='x2egg_xFileToEgg.obj')
+        TargetAdd('x2egg.exe', input='libp3xfileegg.lib')
+        TargetAdd('x2egg.exe', input='libp3xfile.lib')
+        TargetAdd('x2egg.exe', input=COMMON_EGG2X_LIBS)
+        TargetAdd('x2egg.exe', opts=['ADVAPI'])
 
 #
 # DIRECTORY: pandatool/src/mayaprogs/
@@ -6238,7 +6248,7 @@ if (PkgSkip("PANDATOOL")==0):
 
 for VER in MAYAVERSIONS:
   VNUM = VER[4:]
-  if not PkgSkip(VER) and not PkgSkip("PANDATOOL"):
+  if not PkgSkip(VER) and not PkgSkip("PANDATOOL") and not PkgSkip("EGG"):
     if GetTarget() == 'darwin' and int(VNUM) >= 2012:
       ARCH_OPTS = ['NOARCH:PPC', 'NOARCH:I386']
       if len(OSX_ARCHS) != 0 and 'x86_64' not in OSX_ARCHS:
@@ -6374,8 +6384,9 @@ if (PkgSkip("CONTRIB")==0 and not RUNTIME):
 # Generate the models directory and samples directory
 #
 
-if (PkgSkip("DIRECT")==0 and not RUNTIME):
+if not PkgSkip("DIRECT") and not RUNTIME and not PkgSkip("EGG"):
   model_extensions = ["*.egg"]
+
   # Check if we have access to an flt2egg utility, either self-compiled or on the system.
   if ((PkgSkip("PANDATOOL")==0 and GetHost()==GetTarget()) or LocateBinary('flt2egg')):
       model_extensions.append("*.flt")
@@ -6401,6 +6412,7 @@ if (PkgSkip("DIRECT")==0 and not RUNTIME):
           newname = model[:-4] + ".egg"
       TargetAdd(GetOutputDir()+"/models/"+newname, input="models/"+model)
 
+if not PkgSkip("DIRECT") and not RUNTIME:
   CopyAllFiles(GetOutputDir()+"/models/audio/sfx/",  "dmodels/src/audio/sfx/", ".wav")
   CopyAllFiles(GetOutputDir()+"/models/icons/",      "dmodels/src/icons/",     ".gif")
 
@@ -6813,7 +6825,7 @@ deps: {DEPENDS}
 
 def MakeInstallerLinux():
     if not RUNTIME and not PkgSkip("PYTHON"):
-        PYTHONV = SDK["PYTHONVERSION"]
+        PYTHONV = SDK["PYTHONVERSION"].rstrip('dmu')
     else:
         PYTHONV = "python"
     PV = PYTHONV.replace("python", "")
@@ -6968,8 +6980,13 @@ def MakeInstallerOSX():
         oscmd(cmdstr)
         return
 
+    dmg_name = "Panda3D-" + VERSION
+    if not SDK["PYTHONVERSION"].startswith("python2."):
+        dmg_name += '-py' + SDK["PYTHONVERSION"][6:9]
+    dmg_name += ".dmg"
+
     import compileall
-    if (os.path.isfile("Panda3D-%s.dmg" % VERSION)): oscmd("rm -f Panda3D-%s.dmg" % VERSION)
+    if (os.path.isfile(dmg_name)): oscmd("rm -f %s" % dmg_name)
     if (os.path.exists("dstroot")): oscmd("rm -rf dstroot")
     if (os.path.exists("Panda3D-rw.dmg")): oscmd('rm -f Panda3D-rw.dmg')
 
@@ -7010,7 +7027,7 @@ def MakeInstallerOSX():
         oscmd("cp -R " + GetOutputDir() + "/bin/" + base + " " + binname)
 
     if PkgSkip("PYTHON")==0:
-        PV = SDK["PYTHONVERSION"].replace("python", "")
+        PV = SDK["PYTHONVERSION"][6:9]
         oscmd("mkdir -p dstroot/pythoncode/usr/local/bin")
         oscmd("mkdir -p dstroot/pythoncode/Developer/Panda3D/panda3d")
         oscmd("mkdir -p dstroot/pythoncode/Library/Python/%s/site-packages" % PV)
@@ -7165,7 +7182,7 @@ def MakeInstallerOSX():
     dist.close()
 
     oscmd('hdiutil create Panda3D-rw.dmg -volname "Panda3D SDK %s" -srcfolder dstroot/Panda3D' % (VERSION))
-    oscmd('hdiutil convert Panda3D-rw.dmg -format UDBZ -o Panda3D-%s.dmg' % (VERSION))
+    oscmd('hdiutil convert Panda3D-rw.dmg -format UDBZ -o %s' % (dmg_name))
     oscmd('rm -f Panda3D-rw.dmg')
 
 def MakeInstallerFreeBSD():

+ 21 - 17
makepanda/makepandacore.py

@@ -1928,6 +1928,8 @@ def SdkLocatePython(prefer_thirdparty_python=False):
         SDK["PYTHONEXEC"] = os.path.realpath(sys.executable)
         return
 
+    abiflags = getattr(sys, 'abiflags', '')
+
     if GetTarget() == 'windows':
         sdkdir = GetThirdpartyBase() + "/win-python"
 
@@ -1992,26 +1994,28 @@ def SdkLocatePython(prefer_thirdparty_python=False):
         SDK["PYTHON"] = tp_python + "/include/" + SDK["PYTHONVERSION"]
 
     elif GetTarget() == 'darwin':
-         # On Mac OS X, use the system Python framework.
-         py_fwx = SDK.get("MACOSX", "") + "/System/Library/Frameworks/Python.framework/Versions/Current"
+        # On macOS, search for the Python framework directory matching the
+        # version number of our current Python version.
+        sysroot = SDK.get("MACOSX", "")
+        version = sysconfig.get_python_version()
 
-         if not os.path.islink(py_fwx):
-             exit("Could not locate Python installation at %s" % (py_fwx))
+        py_fwx = "{0}/System/Library/Frameworks/Python.framework/Versions/{1}".format(sysroot, version)
 
-         ver = os.path.basename(os.readlink(py_fwx))
-         py_fwx = SDK.get("MACOSX", "") + "/System/Library/Frameworks/Python.framework/Versions/%s" % ver
+        if not os.path.exists(py_fwx):
+            # Fall back to looking on the system.
+            py_fwx = "/Library/Frameworks/Python.framework/Versions/" + version
 
-         SDK["PYTHON"] = py_fwx + "/Headers"
-         SDK["PYTHONVERSION"] = "python" + ver
-         SDK["PYTHONEXEC"] = "/System/Library/Frameworks/Python.framework/Versions/" + ver + "/bin/python" + ver
+        if not os.path.exists(py_fwx):
+            exit("Could not locate Python installation at %s" % (py_fwx))
 
-         # Avoid choosing the one in the thirdparty package dir.
-         PkgSetCustomLocation("PYTHON")
-         IncDirectory("PYTHON", py_fwx + "/include")
-         LibDirectory("PYTHON", "%s/usr/lib" % (SDK.get("MACOSX", "")))
+        SDK["PYTHON"] = py_fwx + "/Headers"
+        SDK["PYTHONVERSION"] = "python" + version + abiflags
+        SDK["PYTHONEXEC"] = py_fwx + "/bin/python" + version
 
-         if sys.version[:3] != ver:
-             print("Warning: building with Python %s instead of %s since you targeted a specific Mac OS X version." % (ver, sys.version[:3]))
+        # Avoid choosing the one in the thirdparty package dir.
+        PkgSetCustomLocation("PYTHON")
+        IncDirectory("PYTHON", py_fwx + "/include")
+        LibDirectory("PYTHON", py_fwx + "/lib")
 
     #elif GetTarget() == 'windows':
     #    SDK["PYTHON"] = os.path.dirname(sysconfig.get_python_inc())
@@ -2020,13 +2024,13 @@ def SdkLocatePython(prefer_thirdparty_python=False):
 
     else:
         SDK["PYTHON"] = sysconfig.get_python_inc()
-        SDK["PYTHONVERSION"] = "python" + sysconfig.get_python_version()
+        SDK["PYTHONVERSION"] = "python" + sysconfig.get_python_version() + abiflags
         SDK["PYTHONEXEC"] = os.path.realpath(sys.executable)
 
     if CrossCompiling():
         # We need a version of Python we can run.
         SDK["PYTHONEXEC"] = sys.executable
-        host_version = "python" + sysconfig.get_python_version()
+        host_version = "python" + sysconfig.get_python_version() + abiflags
         if SDK["PYTHONVERSION"] != host_version:
             exit("Host Python version (%s) must be the same as target Python version (%s)!" % (host_version, SDK["PYTHONVERSION"]))
 

+ 21 - 73
panda/src/display/displayInformation.cxx

@@ -14,6 +14,13 @@
 #include "graphicsStateGuardian.h"
 #include "displayInformation.h"
 
+// For __rdtsc
+#ifdef _MSC_VER
+#include <intrin.h>
+#elif defined(__GNUC__) && !defined(__clang__)
+#include <x86intrin.h>
+#endif
+
 /**
  * Returns true if these two DisplayModes are identical.
  */
@@ -58,12 +65,6 @@ DisplayInformation::
   if (_display_mode_array != NULL) {
     delete[] _display_mode_array;
   }
-  if (_cpu_id_data != NULL) {
-    delete _cpu_id_data;
-  }
-  if (_cpu_brand_string != NULL) {
-    delete _cpu_brand_string;
-  }
 }
 
 /**
@@ -134,12 +135,6 @@ DisplayInformation() {
   _driver_date_day = 0;
   _driver_date_year = 0;
 
-  _cpu_id_version = 1;
-  _cpu_id_size = 0;
-  _cpu_id_data = 0;
-
-  _cpu_vendor_string = 0;
-  _cpu_brand_string = 0;
   _cpu_version_information = 0;
   _cpu_brand_index = 0;
 
@@ -152,7 +147,6 @@ DisplayInformation() {
   _num_logical_cpus = 0;
 
   _get_memory_information_function = 0;
-  _cpu_time_function = 0;
   _update_cpu_frequency_function = 0;
 
   _os_version_major = -1;
@@ -493,62 +487,17 @@ get_driver_date_year() {
 /**
  *
  */
-int DisplayInformation::
-get_cpu_id_version() {
-  return _cpu_id_version;
-}
-
-/**
- * Returns the number of 32-bit values for cpu id binary data.
- */
-int DisplayInformation::
-get_cpu_id_size() {
-  return _cpu_id_size;
-}
-
-/**
- * Returns part of cpu id binary data based on the index.
- */
-unsigned int DisplayInformation::
-get_cpu_id_data(int index) {
-  unsigned int data;
-
-  data = 0;
-  if (index >= 0 && index < _cpu_id_size) {
-    data = _cpu_id_data [index];
-  }
-
-  return data;
+const string &DisplayInformation::
+get_cpu_vendor_string() const {
+  return _cpu_vendor_string;
 }
 
 /**
  *
  */
-const char *DisplayInformation::
-get_cpu_vendor_string() {
-  const char *string;
-
-  string = _cpu_vendor_string;
-  if (string == 0) {
-    string = "";
-  }
-
-  return string;
-}
-
-/**
- *
- */
-const char *DisplayInformation::
-get_cpu_brand_string() {
-  const char *string;
-
-  string = _cpu_brand_string;
-  if (string == 0) {
-    string = "";
-  }
-
-  return string;
+const string &DisplayInformation::
+get_cpu_brand_string() const {
+  return _cpu_brand_string;
 }
 
 /**
@@ -576,18 +525,17 @@ get_cpu_frequency() {
 }
 
 /**
- *
+ * Equivalent to the rdtsc processor instruction.
  */
 uint64_t DisplayInformation::
 get_cpu_time() {
-  uint64_t cpu_time;
-
-  cpu_time = 0;
-  if (_cpu_time_function) {
-    cpu_time = _cpu_time_function();
-  }
-
-  return cpu_time;
+#if defined(_MSC_VER) || (defined(__GNUC__) && !defined(__clang__))
+  return __rdtsc();
+#else
+  unsigned int lo, hi = 0;
+  __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+  return ((uint64_t)hi << 32) | lo;
+#endif
 }
 
 /**

+ 5 - 13
panda/src/display/displayInformation.h

@@ -94,17 +94,13 @@ PUBLISHED:
   int get_driver_date_day();
   int get_driver_date_year();
 
-  int get_cpu_id_version();
-  int get_cpu_id_size();
-  unsigned int get_cpu_id_data(int index);
-
-  const char *get_cpu_vendor_string();
-  const char *get_cpu_brand_string();
+  const string &get_cpu_vendor_string() const;
+  const string &get_cpu_brand_string() const;
   unsigned int get_cpu_version_information();
   unsigned int get_cpu_brand_index();
 
   uint64_t get_cpu_frequency();
-  uint64_t get_cpu_time();
+  static uint64_t get_cpu_time();
 
   uint64_t get_maximum_cpu_frequency();
   uint64_t get_current_cpu_frequency();
@@ -158,12 +154,9 @@ public:
   int _driver_date_day;
   int _driver_date_year;
 
-  int _cpu_id_version;
-  int _cpu_id_size;
-  unsigned int *_cpu_id_data;
 
-  char *_cpu_vendor_string;
-  char *_cpu_brand_string;
+  string _cpu_vendor_string;
+  string _cpu_brand_string;
   unsigned int _cpu_version_information;
   unsigned int _cpu_brand_index;
 
@@ -176,7 +169,6 @@ public:
   int _num_logical_cpus;
 
   void (*_get_memory_information_function) (DisplayInformation *display_information);
-  uint64_t (*_cpu_time_function) (void);
   int (*_update_cpu_frequency_function) (int processor_number, DisplayInformation *display_information);
 
   int _os_version_major;

+ 157 - 16
panda/src/display/graphicsPipe.cxx

@@ -18,6 +18,92 @@
 #include "mutexHolder.h"
 #include "displayInformation.h"
 
+#ifdef IS_LINUX
+#include <sys/sysinfo.h>
+#include <unistd.h>
+#endif
+
+#ifdef IS_OSX
+#include <sys/sysctl.h>
+#endif
+
+#ifdef IS_FREEBSD
+#include <unistd.h>
+#endif
+
+#if defined(__GNUC__) && !defined(__APPLE__)
+// GCC and Clang offer a useful cpuid.h header.
+#include <cpuid.h>
+#endif
+
+#ifdef _MSC_VER
+// MSVC has a __cpuid intrinsic.
+#include <intrin.h>
+#endif
+
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
+#endif
+
+union cpuid_info {
+  char str[16];
+  struct {
+    uint32_t eax, ebx, ecx, edx;
+  };
+};
+
+/**
+ * Returns the highest cpuid leaf that is supported by the CPU.
+ */
+static inline uint32_t get_cpuid_max(uint32_t leaf) {
+#if defined(__GNUC__) && !defined(__APPLE__)
+  return __get_cpuid_max(leaf, 0);
+#elif defined(_MSC_VER)
+  uint32_t p[4] = {0};
+  __cpuid((int *)p, leaf);
+  return p[0];
+#else
+  unsigned int eax = 0;
+  __asm__ ("cpuid\n\t"
+           : "=a" (eax)
+           : "0" (leaf));
+  return eax;
+#endif
+}
+
+/**
+ * Gets cpuid info for the given leaf.
+ */
+static inline void get_cpuid(uint32_t leaf, cpuid_info &info) {
+#if defined(__GNUC__) && !defined(__APPLE__)
+  __cpuid(leaf, info.eax, info.ebx, info.ecx, info.edx);
+#elif defined(_MSC_VER)
+  __cpuid((int *)info.str, leaf);
+#else
+  __asm__ ("cpuid\n\t"
+           : "=a" (info.eax), "=b" (info.ebx), "=c" (info.ecx), "=d" (info.edx)
+           : "0" (leaf));
+#endif
+}
+
+#ifdef IS_LINUX
+/**
+ * Updates the current memory usage statistics in the DisplayInformation.
+ */
+static void update_memory_info(DisplayInformation *info) {
+  struct sysinfo meminfo;
+  if (sysinfo(&meminfo) == 0) {
+    info->_physical_memory = meminfo.totalram;
+    info->_available_physical_memory = meminfo.freeram;
+    info->_page_file_size = meminfo.totalswap;
+    info->_available_page_file_size = meminfo.freeswap;
+  }
+}
+#endif
+
 TypeHandle GraphicsPipe::_type_handle;
 
 /**
@@ -38,24 +124,79 @@ GraphicsPipe() :
   _display_width = 0;
   _display_height = 0;
 
-  _display_information = new DisplayInformation ( );
-}
+  _display_information = new DisplayInformation();
 
-/**
- * Don't try to copy GraphicsPipes.
- */
-GraphicsPipe::
-GraphicsPipe(const GraphicsPipe &) {
-  _is_valid = false;
-  nassertv(false);
-}
+  cpuid_info info;
+  const uint32_t max_cpuid = get_cpuid_max(0);
+  const uint32_t max_extended = get_cpuid_max(0x80000000);
 
-/**
- * Don't try to copy GraphicsPipes.
- */
-void GraphicsPipe::
-operator = (const GraphicsPipe &) {
-  nassertv(false);
+  if (max_cpuid >= 1) {
+    get_cpuid(0, info);
+    swap(info.ecx, info.edx);
+    _display_information->_cpu_vendor_string = string(info.str + 4, 12);
+
+    get_cpuid(1, info);
+    _display_information->_cpu_version_information = info.eax;
+    _display_information->_cpu_brand_index = info.ebx & 0xff;
+  }
+
+  if (max_extended >= 0x80000004) {
+    char brand[49];
+    get_cpuid(0x80000002, info);
+    memcpy(brand, info.str, 16);
+    get_cpuid(0x80000003, info);
+    memcpy(brand + 16, info.str, 16);
+    get_cpuid(0x80000004, info);
+    memcpy(brand + 32, info.str, 16);
+    brand[48] = 0;
+    _display_information->_cpu_brand_string = brand;
+  }
+
+#if defined(IS_OSX)
+  // macOS exposes a lot of useful information through sysctl.
+  size_t len = sizeof(uint64_t);
+  sysctlbyname("hw.memsize", &_display_information->_physical_memory, &len, NULL, 0);
+  len = sizeof(uint64_t);
+  sysctlbyname("hw.cpufrequency", &_display_information->_cpu_frequency, &len, NULL, 0);
+  len = sizeof(uint64_t);
+  sysctlbyname("hw.cpufrequency", &_display_information->_current_cpu_frequency, &len, NULL, 0);
+  len = sizeof(uint64_t);
+  sysctlbyname("hw.cpufrequency_max", &_display_information->_maximum_cpu_frequency, &len, NULL, 0);
+  len = sizeof(int);
+  sysctlbyname("hw.physicalcpu", &_display_information->_num_cpu_cores, &len, NULL, 0);
+  len = sizeof(int);
+  sysctlbyname("hw.logicalcpu", &_display_information->_num_logical_cpus, &len, NULL, 0);
+
+#elif defined(IS_LINUX)
+  _display_information->_get_memory_information_function = &update_memory_info;
+  update_memory_info(_display_information);
+
+#elif defined(IS_FREEBSD)
+  size_t len = sizeof(uint64_t);
+  sysctlbyname("hw.physmem", &_display_information->_physical_memory, &len, NULL, 0);
+  len = sizeof(uint64_t);
+  sysctlbyname("vm.swap_total", &_display_information->_page_file_size, &len, NULL, 0);
+
+#elif defined(_WIN32)
+  MEMORYSTATUSEX status;
+  status.dwLength = sizeof(MEMORYSTATUSEX);
+  if (GlobalMemoryStatusEx(&status)) {
+    _display_information->_physical_memory = status.ullTotalPhys;
+    _display_information->_available_physical_memory = status.ullAvailPhys;
+    _display_information->_page_file_size = status.ullTotalPageFile;
+    _display_information->_available_page_file_size = status.ullAvailPageFile;
+    _display_information->_process_virtual_memory = status.ullTotalVirtual;
+    _display_information->_available_process_virtual_memory = status.ullAvailVirtual;
+    _display_information->_memory_load = status.dwMemoryLoad;
+  }
+#endif
+
+#if defined(IS_LINUX) || defined(IS_FREEBSD)
+  long nproc = sysconf(_SC_NPROCESSORS_CONF);
+  if (nproc > 0) {
+    _display_information->_num_logical_cpus = nproc;
+  }
+#endif
 }
 
 /**

+ 2 - 2
panda/src/display/graphicsPipe.h

@@ -53,8 +53,8 @@ class EXPCL_PANDA_DISPLAY GraphicsPipe : public TypedReferenceCount {
 protected:
   GraphicsPipe();
 private:
-  GraphicsPipe(const GraphicsPipe &copy);
-  void operator = (const GraphicsPipe &copy);
+  GraphicsPipe(const GraphicsPipe &copy) DELETED;
+  GraphicsPipe &operator = (const GraphicsPipe &copy) DELETED_ASSIGN;
 
 PUBLISHED:
   virtual ~GraphicsPipe();

+ 5 - 2
panda/src/display/graphicsStateGuardian.cxx

@@ -1684,8 +1684,11 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
     t = get_external_transform()->get_mat() *
       get_scene()->get_camera_transform()->get_mat() *
       np.get_net_transform()->get_inverse()->get_mat() *
-      LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system()) *
-      lens->get_projection_mat() * biasmat;
+      LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system());
+
+    if (!node->is_of_type(PointLight::get_class_type())) {
+      t *= lens->get_projection_mat() * biasmat;
+    }
     return &t;
 
   } else {

+ 8 - 0
panda/src/downloader/httpChannel.cxx

@@ -1474,6 +1474,14 @@ run_setup_ssl() {
     return false;
   }
 
+  string hostname = _request.get_url().get_server();
+  result = SSL_set_tlsext_host_name(ssl, hostname.c_str());
+  if (result == 0) {
+    downloader_cat.error()
+      << _NOTIFY_HTTP_CHANNEL_ID
+      << "Could not set TLS SNI hostname to '" << hostname << "'\n";
+  }
+
 /*
  * It would be nice to use something like SSL_set_client_cert_cb() here to set
  * a callback to provide the certificate should it be requested, or even to

+ 4 - 27
panda/src/express/datagramIterator.I

@@ -30,36 +30,13 @@ DatagramIterator(const Datagram &datagram, size_t offset) :
   nassertv(_current_index <= _datagram->get_length());
 }
 
-/**
- *
- */
-INLINE DatagramIterator::
-DatagramIterator(const DatagramIterator &copy) :
-    _datagram(copy._datagram),
-  _current_index(copy._current_index) {
-}
-
-/**
- *
- */
-INLINE void DatagramIterator::
-operator = (const DatagramIterator &copy) {
-  _datagram = copy._datagram;
-  _current_index = copy._current_index;
-}
 /**
  * direct Assignment to a Datagram
  */
-INLINE void DatagramIterator::assign(Datagram &datagram, size_t offset)
-{
-    _datagram =&datagram;
-    _current_index = offset;
-}
-/**
- *
- */
-INLINE DatagramIterator::
-~DatagramIterator() {
+INLINE void DatagramIterator::
+assign(Datagram &datagram, size_t offset) {
+  _datagram = &datagram;
+  _current_index = offset;
 }
 
 // Various ways to get data and increment the iterator... Cut-and-paste-orama

+ 0 - 3
panda/src/express/datagramIterator.h

@@ -31,9 +31,6 @@ public:
 PUBLISHED:
   INLINE DatagramIterator();
   INLINE DatagramIterator(const Datagram &datagram, size_t offset = 0);
-  INLINE DatagramIterator(const DatagramIterator &copy);
-  INLINE void operator = (const DatagramIterator &copy);
-  INLINE ~DatagramIterator();
 
   INLINE bool get_bool();
   INLINE int8_t get_int8();

+ 0 - 7
panda/src/express/hashGeneratorBase.I

@@ -19,13 +19,6 @@ HashGeneratorBase() {
   _hash = 0;
 }
 
-/**
- *
- */
-INLINE HashGeneratorBase::
-~HashGeneratorBase() {
-}
-
 /**
  * Returns the hash number generated.
  */

+ 0 - 1
panda/src/express/hashGeneratorBase.h

@@ -30,7 +30,6 @@
 class EXPCL_PANDAEXPRESS HashGeneratorBase {
 public:
   INLINE HashGeneratorBase();
-  INLINE ~HashGeneratorBase();
 
   INLINE size_t get_hash() const;
 

+ 0 - 29
panda/src/express/namable.I

@@ -20,35 +20,6 @@ Namable(const string &initial_name) :
 {
 }
 
-/**
- *
- */
-INLINE Namable::
-Namable(const Namable &copy) :
-  _name(copy._name)
-{
-}
-
-/**
- *
- */
-INLINE Namable &Namable::
-operator = (const Namable &other) {
-  _name = other._name;
-  return *this;
-}
-
-#ifdef USE_MOVE_SEMANTICS
-/**
- *
- */
-INLINE Namable &Namable::
-operator = (Namable &&other) NOEXCEPT {
-  _name = MOVE(other._name);
-  return *this;
-}
-#endif
-
 /**
  *
  */

+ 0 - 6
panda/src/express/namable.h

@@ -26,12 +26,6 @@
 class EXPCL_PANDAEXPRESS Namable : public MemoryBase {
 PUBLISHED:
   INLINE explicit Namable(const string &initial_name = "");
-  INLINE Namable(const Namable &copy);
-  INLINE Namable &operator = (const Namable &other);
-
-#ifdef USE_MOVE_SEMANTICS
-  INLINE Namable &operator = (Namable &&other) NOEXCEPT;
-#endif
 
   INLINE void set_name(const string &name);
   INLINE void clear_name();

+ 0 - 20
panda/src/express/nodePointerTo.I

@@ -33,16 +33,6 @@ NodePointerTo(const NodePointerTo<T> &copy) :
 }
 #endif  // CPPPARSER
 
-#ifndef CPPPARSER
-/**
- *
- */
-template<class T>
-INLINE NodePointerTo<T>::
-~NodePointerTo() {
-}
-#endif  // CPPPARSER
-
 #ifdef USE_MOVE_SEMANTICS
 #ifndef CPPPARSER
 /**
@@ -177,16 +167,6 @@ NodeConstPointerTo(const NodeConstPointerTo<T> &copy) :
 }
 #endif  // CPPPARSER
 
-#ifndef CPPPARSER
-/**
- *
- */
-template<class T>
-INLINE NodeConstPointerTo<T>::
-~NodeConstPointerTo() {
-}
-#endif  // CPPPARSER
-
 #ifdef USE_MOVE_SEMANTICS
 #ifndef CPPPARSER
 /**

+ 0 - 2
panda/src/express/nodePointerTo.h

@@ -31,7 +31,6 @@ public:
   typedef TYPENAME NodePointerToBase<T>::To To;
   INLINE NodePointerTo(To *ptr = (To *)NULL);
   INLINE NodePointerTo(const NodePointerTo<T> &copy);
-  INLINE ~NodePointerTo();
 
 #ifdef USE_MOVE_SEMANTICS
   INLINE NodePointerTo(NodePointerTo<T> &&from) NOEXCEPT;
@@ -66,7 +65,6 @@ public:
   INLINE NodeConstPointerTo(const To *ptr = (const To *)NULL);
   INLINE NodeConstPointerTo(const NodePointerTo<T> &copy);
   INLINE NodeConstPointerTo(const NodeConstPointerTo<T> &copy);
-  INLINE ~NodeConstPointerTo();
 
 #ifdef USE_MOVE_SEMANTICS
   INLINE NodeConstPointerTo(NodePointerTo<T> &&from) NOEXCEPT;

+ 0 - 70
panda/src/express/ordered_vector.I

@@ -33,36 +33,6 @@ ordered_vector(const Compare &compare, TypeHandle type_handle) :
 {
 }
 
-/**
- *
- */
-template<class Key, class Compare, class Vector>
-INLINE ordered_vector<Key, Compare, Vector>::
-ordered_vector(const ordered_vector<Key, Compare, Vector> &copy) :
-  _compare(copy._compare),
-  _vector(copy._vector)
-{
-}
-
-/**
- *
- */
-template<class Key, class Compare, class Vector>
-INLINE ordered_vector<Key, Compare, Vector> &ordered_vector<Key, Compare, Vector>::
-operator = (const ordered_vector<Key, Compare, Vector> &copy) {
-  _compare = copy._compare;
-  _vector = copy._vector;
-  return *this;
-}
-
-/**
- *
- */
-template<class Key, class Compare, class Vector>
-INLINE ordered_vector<Key, Compare, Vector>::
-~ordered_vector() {
-}
-
 /**
  * Returns the iterator that marks the first element in the ordered vector.
  */
@@ -636,26 +606,6 @@ ov_set(const Compare &compare, TypeHandle type_handle) :
 {
 }
 
-/**
- *
- */
-template<class Key, class Compare, class Vector>
-INLINE ov_set<Key, Compare, Vector>::
-ov_set(const ov_set<Key, Compare, Vector> &copy) :
-  ordered_vector<Key, Compare, Vector>(copy)
-{
-}
-
-/**
- *
- */
-template<class Key, class Compare, class Vector>
-INLINE ov_set<Key, Compare, Vector> &ov_set<Key, Compare, Vector>::
-operator = (const ov_set<Key, Compare, Vector> &copy) {
-  ordered_vector<Key, Compare, Vector>::operator = (copy);
-  return *this;
-}
-
 /**
  * Maps to insert_unique().
  */
@@ -713,26 +663,6 @@ ov_multiset(const Compare &compare, TypeHandle type_handle) :
 {
 }
 
-/**
- *
- */
-template<class Key, class Compare, class Vector>
-INLINE ov_multiset<Key, Compare, Vector>::
-ov_multiset(const ov_multiset<Key, Compare, Vector> &copy) :
-  ordered_vector<Key, Compare, Vector>(copy)
-{
-}
-
-/**
- *
- */
-template<class Key, class Compare, class Vector>
-INLINE ov_multiset<Key, Compare, Vector> &ov_multiset<Key, Compare, Vector>::
-operator = (const ov_multiset<Key, Compare, Vector> &copy) {
-  ordered_vector<Key, Compare, Vector>::operator = (copy);
-  return *this;
-}
-
 /**
  * Maps to insert_nonunique().
  */

+ 0 - 7
panda/src/express/ordered_vector.h

@@ -135,9 +135,6 @@ public:
   INLINE ordered_vector(TypeHandle type_handle = ov_set_type_handle);
   INLINE ordered_vector(const Compare &compare,
                         TypeHandle type_handle = ov_set_type_handle);
-  INLINE ordered_vector(const ordered_vector<Key, Compare, Vector> &copy);
-  INLINE ordered_vector<Key, Compare, Vector> &operator = (const ordered_vector<Key, Compare, Vector> &copy);
-  INLINE ~ordered_vector();
 
   // Iterator access.
   INLINE ITERATOR begin();
@@ -265,8 +262,6 @@ public:
   INLINE ov_set(TypeHandle type_handle = ov_set_type_handle);
   INLINE ov_set(const Compare &compare,
                 TypeHandle type_handle = ov_set_type_handle);
-  INLINE ov_set(const ov_set<Key, Compare, Vector> &copy);
-  INLINE ov_set<Key, Compare, Vector> &operator = (const ov_set<Key, Compare, Vector> &copy);
 
   INLINE ITERATOR insert(ITERATOR position, const VALUE_TYPE &key0);
   INLINE pair<ITERATOR, bool> insert(const VALUE_TYPE &key0);
@@ -288,8 +283,6 @@ public:
   INLINE ov_multiset(TypeHandle type_handle = ov_set_type_handle);
   INLINE ov_multiset(const Compare &compare,
                      TypeHandle type_handle = ov_set_type_handle);
-  INLINE ov_multiset(const ov_multiset<Key, Compare, Vector> &copy);
-  INLINE ov_multiset<Key, Compare, Vector> &operator = (const ov_multiset<Key, Compare, Vector> &copy);
 
   INLINE ITERATOR insert(ITERATOR position, const VALUE_TYPE &key);
   INLINE ITERATOR insert(const VALUE_TYPE &key);

+ 18 - 34
panda/src/express/pointerTo.I

@@ -16,7 +16,7 @@
  */
 template<class T>
 ALWAYS_INLINE PointerTo<T>::
-PointerTo(To *ptr) : PointerToBase<T>(ptr) {
+PointerTo(To *ptr) NOEXCEPT : PointerToBase<T>(ptr) {
 }
 
 /**
@@ -55,16 +55,8 @@ operator = (PointerTo<T> &&from) NOEXCEPT {
  *
  */
 template<class T>
-INLINE PointerTo<T>::
-~PointerTo() {
-}
-
-/**
- *
- */
-template<class T>
-INLINE TYPENAME PointerTo<T>::To &PointerTo<T>::
-operator *() const {
+CONSTEXPR TYPENAME PointerTo<T>::To &PointerTo<T>::
+operator *() const NOEXCEPT {
   return *((To *)(this->_void_ptr));
 }
 
@@ -72,8 +64,8 @@ operator *() const {
  *
  */
 template<class T>
-INLINE TYPENAME PointerTo<T>::To *PointerTo<T>::
-operator -> () const {
+CONSTEXPR TYPENAME PointerTo<T>::To *PointerTo<T>::
+operator -> () const NOEXCEPT {
   return (To *)(this->_void_ptr);
 }
 
@@ -84,8 +76,8 @@ operator -> () const {
  * goes because either will be correct.
  */
 template<class T>
-INLINE PointerTo<T>::
-operator T * () const {
+CONSTEXPR PointerTo<T>::
+operator T * () const NOEXCEPT {
   return (To *)(this->_void_ptr);
 }
 
@@ -107,8 +99,8 @@ cheat() {
  * compiler problems, particularly for implicit upcasts.
  */
 template<class T>
-INLINE TYPENAME PointerTo<T>::To *PointerTo<T>::
-p() const {
+CONSTEXPR TYPENAME PointerTo<T>::To *PointerTo<T>::
+p() const NOEXCEPT {
   return (To *)(this->_void_ptr);
 }
 
@@ -137,7 +129,7 @@ operator = (const PointerTo<T> &copy) {
  */
 template<class T>
 ALWAYS_INLINE ConstPointerTo<T>::
-ConstPointerTo(const TYPENAME ConstPointerTo<T>::To *ptr) :
+ConstPointerTo(const TYPENAME ConstPointerTo<T>::To *ptr) NOEXCEPT :
   PointerToBase<T>((TYPENAME ConstPointerTo<T>::To *)ptr)
 {
 }
@@ -152,14 +144,6 @@ ConstPointerTo(const PointerTo<T> &copy) :
 {
 }
 
-/**
- *
- */
-template<class T>
-INLINE ConstPointerTo<T>::
-~ConstPointerTo() {
-}
-
 /**
  *
  */
@@ -216,8 +200,8 @@ operator = (ConstPointerTo<T> &&from) NOEXCEPT {
  *
  */
 template<class T>
-INLINE const TYPENAME ConstPointerTo<T>::To &ConstPointerTo<T>::
-operator *() const {
+CONSTEXPR const TYPENAME ConstPointerTo<T>::To &ConstPointerTo<T>::
+operator *() const NOEXCEPT {
   return *((To *)(this->_void_ptr));
 }
 
@@ -225,8 +209,8 @@ operator *() const {
  *
  */
 template<class T>
-INLINE const TYPENAME ConstPointerTo<T>::To *ConstPointerTo<T>::
-operator -> () const {
+CONSTEXPR const TYPENAME ConstPointerTo<T>::To *ConstPointerTo<T>::
+operator -> () const NOEXCEPT {
   return (To *)(this->_void_ptr);
 }
 
@@ -237,8 +221,8 @@ operator -> () const {
  * don't care which way it goes because either will be correct.
  */
 template<class T>
-INLINE ConstPointerTo<T>::
-operator const T * () const {
+CONSTEXPR ConstPointerTo<T>::
+operator const T * () const NOEXCEPT {
 return (To *)(this->_void_ptr);
 }
 
@@ -260,8 +244,8 @@ cheat() {
  * around compiler problems, particularly for implicit upcasts.
  */
 template<class T>
-INLINE const TYPENAME ConstPointerTo<T>::To *ConstPointerTo<T>::
-p() const {
+CONSTEXPR const TYPENAME ConstPointerTo<T>::To *ConstPointerTo<T>::
+p() const NOEXCEPT {
   return (To *)(this->_void_ptr);
 }
 

+ 55 - 41
panda/src/express/pointerTo.h

@@ -14,35 +14,47 @@
 #ifndef POINTERTO_H
 #define POINTERTO_H
 
-/*
+/**
  * This file defines the classes PointerTo and ConstPointerTo (and their
  * abbreviations, PT and CPT).  These should be used in place of traditional
- * C-style pointers wherever implicit reference counting is desired.  The
- * syntax is:                     instead of: PointerTo<MyClass> p;
- * MyClass *p; PT(MyClass) p; ConstPointerTo<MyClass> p;       const MyClass
- * *p; CPT(MyClass) p; PointerTo and ConstPointerTo will automatically
- * increment the object's reference count while the pointer is kept.  When the
- * PointerTo object is reassigned or goes out of scope, the reference count is
- * automatically decremented.  If the reference count reaches zero, the object
- * is freed.  Note that const PointerTo<MyClass> is different from
+ * C-style pointers wherever implicit reference counting is desired.
+ *
+ * The syntax is:                     instead of:
+ *
+ *    PointerTo<MyClass> p;            MyClass *p;
+ *    PT(MyClass) p;
+ *
+ *    ConstPointerTo<MyClass> p;       const MyClass *p;
+ *    CPT(MyClass) p;
+ *
+ * PointerTo and ConstPointerTo will automatically increment the object's
+ * reference count while the pointer is kept.  When the PointerTo object is
+ * reassigned or goes out of scope, the reference count is automatically
+ * decremented.  If the reference count reaches zero, the object is freed.
+ *
+ * Note that const PointerTo<MyClass> is different from
  * ConstPointerTo<MyClass>.  A const PointerTo may not reassign its pointer,
  * but it may still modify the contents at that address.  On the other hand, a
  * ConstPointerTo may reassign its pointer at will, but may not modify the
- * contents.  It is like the difference between (MyClass * const) and (const
- * MyClass *). In order to use PointerTo, it is necessary that the thing
- * pointed to--MyClass in the above example--either inherits from
- * ReferenceCount, or is a proxy built with RefCountProxy or RefCountObj (see
- * referenceCount.h).  However, also see PointerToArray, which does not have
- * this restriction.  It is crucial that the PointerTo object is only used to
- * refer to objects allocated from the free store, for which delete is a
- * sensible thing to do.  If you assign a PointerTo to an automatic variable
- * (allocated from the stack, for instance), bad things will certainly happen
- * when the reference count reaches zero and it tries to delete it.  It's also
- * important to remember that, as always, a virtual destructor is required if
- * you plan to support polymorphism.  That is, if you define a PointerTo to
- * some base type, and assign to it instances of a class derived from that
- * base class, the base class must have a virtual destructor in order to
- * properly destruct the derived object when it is deleted.
+ * contents.  It is like the difference between (MyClass * const) and
+ * (const MyClass *).
+ *
+ * In order to use PointerTo, it is necessary that the thing pointed to
+ * --MyClass in the above example--either inherits from ReferenceCount, or is
+ * a proxy built with RefCountProxy or RefCountObj (see referenceCount.h).
+ * However, also see PointerToArray, which does not have this restriction.
+ *
+ * It is crucial that the PointerTo object is only used to refer to objects
+ * allocated from the free store, for which delete is a sensible thing to do.
+ * If you assign a PointerTo to an automatic variable (allocated from the
+ * stack, for instance), bad things will certainly happen when the reference
+ * count reaches zero and it tries to delete it.
+ *
+ * It's also important to remember that, as always, a virtual destructor is
+ * required if you plan to support polymorphism.  That is, if you define a
+ * PointerTo to some base type, and assign to it instances of a class derived
+ * from that base class, the base class must have a virtual destructor in
+ * order to properly destruct the derived object when it is deleted.
  */
 
 #include "pandabase.h"
@@ -58,10 +70,9 @@ class PointerTo : public PointerToBase<T> {
 public:
   typedef TYPENAME PointerToBase<T>::To To;
 PUBLISHED:
-  ALWAYS_INLINE PointerTo() DEFAULT_CTOR;
-  ALWAYS_INLINE PointerTo(To *ptr);
+  CONSTEXPR PointerTo() NOEXCEPT DEFAULT_CTOR;
+  ALWAYS_INLINE PointerTo(To *ptr) NOEXCEPT;
   INLINE PointerTo(const PointerTo<T> &copy);
-  INLINE ~PointerTo();
 
 public:
 #ifdef USE_MOVE_SEMANTICS
@@ -69,10 +80,10 @@ public:
   INLINE PointerTo<T> &operator = (PointerTo<T> &&from) NOEXCEPT;
 #endif
 
-  INLINE To &operator *() const;
-  INLINE To *operator -> () const;
+  CONSTEXPR To &operator *() const NOEXCEPT;
+  CONSTEXPR To *operator -> () const NOEXCEPT;
   // MSVC.NET 2005 insists that we use T *, and not To *, here.
-  INLINE operator T *() const;
+  CONSTEXPR operator T *() const NOEXCEPT;
 
   INLINE T *&cheat();
 
@@ -89,7 +100,7 @@ PUBLISHED:
   // the DCAST macro defined in typedObject.h instead, e.g.  DCAST(MyType,
   // ptr).  This provides a clean downcast that doesn't require .p() or any
   // double-casting, and it can be run-time checked for correctness.
-  INLINE To *p() const;
+  CONSTEXPR To *p() const NOEXCEPT;
 
   INLINE PointerTo<T> &operator = (To *ptr);
   INLINE PointerTo<T> &operator = (const PointerTo<T> &copy);
@@ -98,8 +109,10 @@ PUBLISHED:
   // anyway just to help out interrogate (which doesn't seem to want to
   // automatically export the PointerToBase class).  When this works again in
   // interrogate, we can remove these.
-  INLINE bool is_null() const { return PointerToBase<T>::is_null(); }
-  INLINE void clear() { PointerToBase<T>::clear(); }
+#ifdef CPPPARSER
+  INLINE bool is_null() const;
+  INLINE void clear();
+#endif
 };
 
 
@@ -120,11 +133,10 @@ class ConstPointerTo : public PointerToBase<T> {
 public:
   typedef TYPENAME PointerToBase<T>::To To;
 PUBLISHED:
-  ALWAYS_INLINE ConstPointerTo() DEFAULT_CTOR;
-  ALWAYS_INLINE ConstPointerTo(const To *ptr);
+  CONSTEXPR ConstPointerTo() NOEXCEPT DEFAULT_CTOR;
+  ALWAYS_INLINE ConstPointerTo(const To *ptr) NOEXCEPT;
   INLINE ConstPointerTo(const PointerTo<T> &copy);
   INLINE ConstPointerTo(const ConstPointerTo<T> &copy);
-  INLINE ~ConstPointerTo();
 
 public:
 #ifdef USE_MOVE_SEMANTICS
@@ -134,14 +146,14 @@ public:
   INLINE ConstPointerTo<T> &operator = (ConstPointerTo<T> &&from) NOEXCEPT;
 #endif
 
-  INLINE const To &operator *() const;
-  INLINE const To *operator -> () const;
-  INLINE operator const T *() const;
+  CONSTEXPR const To &operator *() const NOEXCEPT;
+  CONSTEXPR const To *operator -> () const NOEXCEPT;
+  CONSTEXPR operator const T *() const NOEXCEPT;
 
   INLINE const T *&cheat();
 
 PUBLISHED:
-  INLINE const To *p() const;
+  CONSTEXPR const To *p() const NOEXCEPT;
 
   INLINE ConstPointerTo<T> &operator = (const To *ptr);
   INLINE ConstPointerTo<T> &operator = (const PointerTo<T> &copy);
@@ -151,7 +163,9 @@ PUBLISHED:
   // anyway just to help out interrogate (which doesn't seem to want to
   // automatically export the PointerToBase class).  When this works again in
   // interrogate, we can remove this.
-  INLINE void clear() { PointerToBase<T>::clear(); }
+#ifdef CPPPARSER
+  INLINE void clear();
+#endif
 };
 
 

+ 22 - 0
panda/src/express/pointerToArray.I

@@ -68,6 +68,17 @@ PointerToArray(const PointerToArray<Element> &copy) :
 {
 }
 
+/**
+ * Initializes a PointerToArray by copying existing elements.
+ */
+template<class Element>
+INLINE PointerToArray<Element>::
+PointerToArray(const Element *begin, const Element *end, TypeHandle type_handle) :
+  PointerToArrayBase<Element>(new ReferenceCountedVector<Element>(begin, end, type_handle)),
+  _type_handle(type_handle)
+{
+}
+
 #ifdef USE_MOVE_SEMANTICS
 /**
  *
@@ -627,6 +638,17 @@ ConstPointerToArray(TypeHandle type_handle) :
 {
 }
 
+/**
+ * Initializes a ConstPointerToArray by copying existing elements.
+ */
+template<class Element>
+INLINE ConstPointerToArray<Element>::
+ConstPointerToArray(const Element *begin, const Element *end, TypeHandle type_handle) :
+  PointerToArrayBase<Element>(new ReferenceCountedVector<Element>(begin, end, type_handle)),
+  _type_handle(type_handle)
+{
+}
+
 /**
  *
  */

+ 2 - 0
panda/src/express/pointerToArray.h

@@ -134,6 +134,7 @@ public:
   INLINE PointerToArray(TypeHandle type_handle = get_type_handle(Element));
   INLINE static PointerToArray<Element> empty_array(size_type n, TypeHandle type_handle = get_type_handle(Element));
   INLINE PointerToArray(size_type n, const Element &value, TypeHandle type_handle = get_type_handle(Element));
+  INLINE PointerToArray(const Element *begin, const Element *end, TypeHandle type_handle = get_type_handle(Element));
   INLINE PointerToArray(const PointerToArray<Element> &copy);
 
 #ifdef USE_MOVE_SEMANTICS
@@ -289,6 +290,7 @@ PUBLISHED:
   typedef TYPENAME pvector<Element>::size_type size_type;
 
   INLINE ConstPointerToArray(TypeHandle type_handle = get_type_handle(Element));
+  INLINE ConstPointerToArray(const Element *begin, const Element *end, TypeHandle type_handle = get_type_handle(Element));
   INLINE ConstPointerToArray(const PointerToArray<Element> &copy);
   INLINE ConstPointerToArray(const ConstPointerToArray<Element> &copy);
 

+ 4 - 13
panda/src/express/pointerToArrayBase.I

@@ -19,17 +19,6 @@ INLINE ReferenceCountedVector<Element>::
 ReferenceCountedVector(TypeHandle type_handle) : pvector<Element>(type_handle) {
 }
 
-/**
- *
- */
-template<class Element>
-INLINE ReferenceCountedVector<Element>::
-ReferenceCountedVector(const ReferenceCountedVector<Element> &copy) :
-  NodeReferenceCount(copy),
-  pvector<Element>(copy)
-{
-}
-
 /**
  * Creates an array of initial_size elements.
  */
@@ -41,11 +30,13 @@ ReferenceCountedVector(TYPENAME ReferenceCountedVector<Element>::size_type initi
 }
 
 /**
- *
+ * Creates an array with all elements from begin up to but not including end.
  */
 template<class Element>
 INLINE ReferenceCountedVector<Element>::
-~ReferenceCountedVector() {
+ReferenceCountedVector(const Element *begin, const Element *end, TypeHandle type_handle) :
+  pvector<Element>(begin, end, type_handle)
+{
 }
 
 /**

+ 1 - 2
panda/src/express/pointerToArrayBase.h

@@ -41,9 +41,8 @@ public:
   typedef TYPENAME pvector<Element>::size_type size_type;
 
   INLINE ReferenceCountedVector(TypeHandle type_handle);
-  INLINE ReferenceCountedVector(const ReferenceCountedVector<Element> &copy);
   INLINE ReferenceCountedVector(size_type initial_size, TypeHandle type_handle);
-  INLINE ~ReferenceCountedVector();
+  INLINE ReferenceCountedVector(const Element *begin, const Element *end, TypeHandle type_handle);
   ALLOC_DELETED_CHAIN(ReferenceCountedVector<Element>);
 
   INLINE size_type size() const;

+ 1 - 1
panda/src/express/pointerToBase.h

@@ -31,7 +31,7 @@ public:
   typedef T To;
 
 protected:
-  ALWAYS_INLINE PointerToBase() DEFAULT_CTOR;
+  CONSTEXPR PointerToBase() NOEXCEPT DEFAULT_CTOR;
   INLINE PointerToBase(To *ptr);
   INLINE PointerToBase(const PointerToBase<T> &copy);
   INLINE ~PointerToBase();

+ 8 - 17
panda/src/express/pointerToVoid.I

@@ -14,34 +14,25 @@
 /**
  *
  */
-INLINE PointerToVoid::
-PointerToVoid() {
-  _void_ptr = (void *)NULL;
+CONSTEXPR PointerToVoid::
+PointerToVoid() NOEXCEPT : _void_ptr(nullptr) {
 }
 
 /**
  *
  */
-INLINE PointerToVoid::
-~PointerToVoid() {
-  nassertv(_void_ptr == (void *)NULL);
-}
-
-/**
- * Don't use this constructor.
- */
-INLINE PointerToVoid::
-PointerToVoid(const PointerToVoid &) {
-  nassertv(false);
-}
+//INLINE PointerToVoid::
+//~PointerToVoid() {
+//  nassertv(_void_ptr == nullptr);
+//}
 
 /**
  * Returns true if the PointerTo is a NULL pointer, false otherwise.  (Direct
  * comparison to a NULL pointer also works.)
  */
-ALWAYS_INLINE bool PointerToVoid::
+CONSTEXPR bool PointerToVoid::
 is_null() const {
-  return (_void_ptr == (void *)NULL);
+  return _void_ptr == nullptr;
 }
 
 /**

+ 4 - 4
panda/src/express/pointerToVoid.h

@@ -32,14 +32,14 @@
  */
 class EXPCL_PANDAEXPRESS PointerToVoid : public MemoryBase {
 protected:
-  INLINE PointerToVoid();
-  INLINE ~PointerToVoid();
+  CONSTEXPR PointerToVoid() NOEXCEPT;
+  //INLINE ~PointerToVoid();
 
 private:
-  INLINE PointerToVoid(const PointerToVoid &copy);
+  PointerToVoid(const PointerToVoid &copy) DELETED;
 
 PUBLISHED:
-  ALWAYS_INLINE bool is_null() const;
+  CONSTEXPR bool is_null() const;
   INLINE size_t get_hash() const;
 
 public:

+ 3 - 10
panda/src/express/weakPointerToVoid.I

@@ -15,16 +15,9 @@
  *
  */
 INLINE WeakPointerToVoid::
-WeakPointerToVoid() {
-  _ptr_was_deleted = false;
-  _callback = NULL;
-}
-
-/**
- *
- */
-INLINE WeakPointerToVoid::
-~WeakPointerToVoid() {
+WeakPointerToVoid() :
+  _ptr_was_deleted(false),
+  _callback(NULL) {
 }
 
 /**

+ 0 - 1
panda/src/express/weakPointerToVoid.h

@@ -25,7 +25,6 @@
 class EXPCL_PANDAEXPRESS WeakPointerToVoid : public PointerToVoid {
 protected:
   INLINE WeakPointerToVoid();
-  INLINE ~WeakPointerToVoid();
 
 public:
   INLINE void mark_deleted();

+ 18 - 10
panda/src/gobj/vertexDataBuffer.I

@@ -67,17 +67,22 @@ INLINE const unsigned char *VertexDataBuffer::
 get_read_pointer(bool force) const {
   LightMutexHolder holder(_lock);
 
+  const unsigned char *ptr;
   if (_resident_data != (unsigned char *)NULL || _size == 0) {
-    return _resident_data;
+    ptr = _resident_data;
+  } else {
+    nassertr(_block != (VertexDataBlock *)NULL, NULL);
+    nassertr(_reserved_size >= _size, NULL);
+
+    // We don't necessarily need to page the buffer all the way into independent
+    // status; it's sufficient just to return the block's pointer, which will
+    // force its page to resident status.
+    ptr = _block->get_pointer(force);
   }
-
-  nassertr(_block != (VertexDataBlock *)NULL, NULL);
-  nassertr(_reserved_size >= _size, NULL);
-
-  // We don't necessarily need to page the buffer all the way into independent
-  // status; it's sufficient just to return the block's pointer, which will
-  // force its page to resident status.
-  return _block->get_pointer(force);
+#ifdef _DEBUG
+  assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0);
+#endif
+  return (const unsigned char *)ASSUME_ALIGNED(ptr, MEMORY_HOOK_ALIGNMENT);
 }
 
 /**
@@ -91,7 +96,10 @@ get_write_pointer() {
     do_page_in();
   }
   nassertr(_reserved_size >= _size, NULL);
-  return _resident_data;
+#ifdef _DEBUG
+  assert(((uintptr_t)_resident_data % MEMORY_HOOK_ALIGNMENT) == 0);
+#endif
+  return (unsigned char *)ASSUME_ALIGNED(_resident_data, MEMORY_HOOK_ALIGNMENT);
 }
 
 /**

+ 2 - 2
panda/src/parametrics/parametricCurveCollection.h

@@ -11,8 +11,8 @@
  * @date 2001-03-04
  */
 
-#ifndef NODEPATHCOLLECTION_H
-#define NODEPATHCOLLECTION_H
+#ifndef PARAMETRICCURVECOLLECTION_H
+#define PARAMETRICCURVECOLLECTION_H
 
 #include "pandabase.h"
 

+ 2 - 0
panda/src/pgraph/nodePath.h

@@ -659,6 +659,8 @@ PUBLISHED:
   INLINE void set_shader_input(CPT_InternalName id, PN_stdfloat n1, PN_stdfloat n2=0,
                                PN_stdfloat n3=0, PN_stdfloat n4=0, int priority=0);
 
+  EXTENSION(void set_shader_inputs(PyObject *args, PyObject *kwargs));
+
   void clear_shader_input(CPT_InternalName id);
   void set_instance_count(int instance_count);
 

+ 216 - 0
panda/src/pgraph/nodePath_ext.cxx

@@ -13,6 +13,7 @@
 
 #include "nodePath_ext.h"
 #include "typedWritable_ext.h"
+#include "shaderAttrib.h"
 
 #ifdef HAVE_PYTHON
 
@@ -24,6 +25,35 @@ extern struct Dtool_PyTypedObject Dtool_LPoint3d;
 #else
 extern struct Dtool_PyTypedObject Dtool_LPoint3f;
 #endif
+extern struct Dtool_PyTypedObject Dtool_Texture;
+extern struct Dtool_PyTypedObject Dtool_NodePath;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_float;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_double;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_int;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLVecBase4f;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase3f;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase2f;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLMatrix4f;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LMatrix3f;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLVecBase4d;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase3d;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase2d;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLMatrix4d;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LMatrix3d;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLVecBase4i;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase3i;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase2i;
+extern struct Dtool_PyTypedObject Dtool_LVecBase4f;
+extern struct Dtool_PyTypedObject Dtool_LVecBase3f;
+extern struct Dtool_PyTypedObject Dtool_LVecBase2f;
+extern struct Dtool_PyTypedObject Dtool_LVecBase4d;
+extern struct Dtool_PyTypedObject Dtool_LVecBase3d;
+extern struct Dtool_PyTypedObject Dtool_LVecBase2d;
+extern struct Dtool_PyTypedObject Dtool_LVecBase4i;
+extern struct Dtool_PyTypedObject Dtool_LVecBase3i;
+extern struct Dtool_PyTypedObject Dtool_LVecBase2i;
+extern struct Dtool_PyTypedObject Dtool_ShaderBuffer;
+extern struct Dtool_PyTypedObject Dtool_ParamValueBase;
 #endif  // CPPPARSER
 
 /**
@@ -211,6 +241,192 @@ py_decode_NodePath_from_bam_stream_persist(PyObject *unpickler, const string &da
   return NodePath::decode_from_bam_stream(data, reader);
 }
 
+/**
+ * Sets multiple shader inputs at the same time.  This can be significantly
+ * more efficient if many inputs need to be set at the same time.
+ */
+void Extension<NodePath>::
+set_shader_inputs(PyObject *args, PyObject *kwargs) {
+  if (PyObject_Size(args) > 0) {
+    Dtool_Raise_TypeError("NodePath.set_shader_inputs takes only keyword arguments");
+    return;
+  }
+
+  PT(PandaNode) node = _this->node();
+  CPT(RenderAttrib) prev_attrib = node->get_attrib(ShaderAttrib::get_class_slot());
+  PT(ShaderAttrib) attrib;
+  if (prev_attrib == nullptr) {
+    attrib = new ShaderAttrib();
+  } else {
+    attrib = new ShaderAttrib(*(const ShaderAttrib *)prev_attrib.p());
+  }
+
+  PyObject *key, *value;
+  Py_ssize_t pos = 0;
+
+  while (PyDict_Next(kwargs, &pos, &key, &value)) {
+    char *buffer;
+    Py_ssize_t length;
+#if PY_MAJOR_VERSION >= 3
+    buffer = (char *)PyUnicode_AsUTF8AndSize(key, &length);
+    if (buffer == nullptr) {
+#else
+    if (PyString_AsStringAndSize(key, &buffer, &length) == -1) {
+#endif
+      Dtool_Raise_TypeError("NodePath.set_shader_inputs accepts only string keywords");
+      return;
+    }
+
+    CPT_InternalName name(string(buffer, length));
+    ShaderInput *input = nullptr;
+
+    if (PyTuple_CheckExact(value)) {
+      // A tuple is interpreted as a vector.
+      Py_ssize_t size = PyTuple_GET_SIZE(value);
+      if (size > 4) {
+        Dtool_Raise_TypeError("NodePath.set_shader_inputs tuple input should not have more than 4 scalars");
+        return;
+      }
+      // If any of them is a float, we are storing it as a float vector.
+      bool is_float = false;
+      for (Py_ssize_t i = 0; i < size; ++i) {
+        if (PyFloat_CheckExact(PyTuple_GET_ITEM(value, i))) {
+          is_float = true;
+          break;
+        }
+      }
+      if (is_float) {
+        LVecBase4 vec(0);
+        for (Py_ssize_t i = 0; i < size; ++i) {
+          vec[i] = (PN_stdfloat)PyFloat_AsDouble(PyTuple_GET_ITEM(value, i));
+        }
+        input = new ShaderInput(name, vec);
+      } else {
+        LVecBase4i vec(0);
+        for (Py_ssize_t i = 0; i < size; ++i) {
+          vec[i] = (int)PyLong_AsLong(PyTuple_GET_ITEM(value, i));
+        }
+        input = new ShaderInput(name, vec);
+      }
+
+    } else if (DtoolCanThisBeAPandaInstance(value)) {
+      Dtool_PyInstDef *inst = (Dtool_PyInstDef *)value;
+      void *ptr;
+
+      if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_Texture))) {
+        input = new ShaderInput(name, (Texture *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_NodePath))) {
+        input = new ShaderInput(name, *(const NodePath *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_float))) {
+        input = new ShaderInput(name, *(const PTA_float *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_double))) {
+        input = new ShaderInput(name, *(const PTA_double *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_int))) {
+        input = new ShaderInput(name, *(const PTA_int *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4f))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase4f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3f))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase3f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2f))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase2f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4f))) {
+        input = new ShaderInput(name, *(const PTA_LMatrix4f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3f))) {
+        input = new ShaderInput(name, *(const PTA_LMatrix3f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4d))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase4d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3d))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase3d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2d))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase2d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4d))) {
+        input = new ShaderInput(name, *(const PTA_LMatrix4d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3d))) {
+        input = new ShaderInput(name, *(const PTA_LMatrix3d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4i))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase4i *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3i))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase3i *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2i))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase2i *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4f))) {
+        input = new ShaderInput(name, *(const LVecBase4f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3f))) {
+        input = new ShaderInput(name, *(const LVecBase3f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2f))) {
+        input = new ShaderInput(name, *(const LVecBase2f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4d))) {
+        input = new ShaderInput(name, *(const LVecBase4d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3d))) {
+        input = new ShaderInput(name, *(const LVecBase3d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2d))) {
+        input = new ShaderInput(name, *(const LVecBase2d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4i))) {
+        input = new ShaderInput(name, *(const LVecBase4i *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3i))) {
+        input = new ShaderInput(name, *(const LVecBase3i *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2i))) {
+        input = new ShaderInput(name, *(const LVecBase2i *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ShaderBuffer))) {
+        input = new ShaderInput(name, (ShaderBuffer *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ParamValueBase))) {
+        input = new ShaderInput(name, (ParamValueBase *)ptr);
+
+      } else {
+        Dtool_Raise_TypeError("unknown type passed to NodePath.set_shader_inputs");
+        return;
+      }
+
+    } else if (PyFloat_Check(value)) {
+      input = new ShaderInput(name, LVecBase4(PyFloat_AS_DOUBLE(value), 0, 0, 0));
+
+#if PY_MAJOR_VERSION < 3
+    } else if (PyInt_Check(value)) {
+      input = new ShaderInput(name, LVecBase4i((int)PyInt_AS_LONG(value), 0, 0, 0));
+#endif
+
+    } else if (PyLong_Check(value)) {
+      input = new ShaderInput(name, LVecBase4i((int)PyLong_AsLong(value), 0, 0, 0));
+
+    } else {
+      Dtool_Raise_TypeError("unknown type passed to NodePath.set_shader_inputs");
+      return;
+    }
+
+    attrib->_inputs[move(name)] = input;
+  }
+
+  node->set_attrib(ShaderAttrib::return_new(attrib));
+}
+
 /**
  * Returns the tight bounds as a 2-tuple of LPoint3 objects.  This is a
  * convenience function for Python users, among which the use of

+ 2 - 0
panda/src/pgraph/nodePath_ext.h

@@ -49,6 +49,8 @@ public:
   // This is defined to implement cycle detection in Python tags.
   INLINE int __traverse__(visitproc visit, void *arg);
 
+  void set_shader_inputs(PyObject *args, PyObject *kwargs);
+
   PyObject *get_tight_bounds(const NodePath &other = NodePath()) const;
 };
 

+ 3 - 0
panda/src/pgraph/shaderAttrib.h

@@ -31,6 +31,7 @@
 #include "pta_LVecBase4.h"
 #include "pta_LVecBase3.h"
 #include "pta_LVecBase2.h"
+#include "extension.h"
 
 /**
  *
@@ -147,6 +148,8 @@ private:
   typedef pmap<CPT_InternalName, CPT(ShaderInput)> Inputs;
   Inputs _inputs;
 
+  friend class Extension<NodePath>;
+
 PUBLISHED:
   static int get_class_slot() {
     return _attrib_slot;

+ 0 - 27
panda/src/putil/bitArray.I

@@ -30,26 +30,6 @@ BitArray(WordType init_value) {
   _highest_bits = 0;
 }
 
-/**
- *
- */
-INLINE BitArray::
-BitArray(const BitArray &copy) :
-  _array(copy._array),
-  _highest_bits(copy._highest_bits)
-{
-}
-
-/**
- *
- */
-INLINE BitArray &BitArray::
-operator = (const BitArray &copy) {
-  _array = copy._array;
-  _highest_bits = copy._highest_bits;
-  return *this;
-}
-
 /**
  * Returns a BitArray with an infinite array of bits, all on.
  */
@@ -98,13 +78,6 @@ range(int low_bit, int size) {
   return result;
 }
 
-/**
- *
- */
-INLINE BitArray::
-~BitArray() {
-}
-
 /**
  * Returns true if there is a maximum number of bits that may be stored in
  * this structure, false otherwise.  If this returns true, the number may be

+ 0 - 4
panda/src/putil/bitArray.h

@@ -46,8 +46,6 @@ PUBLISHED:
 
   INLINE BitArray();
   INLINE BitArray(WordType init_value);
-  INLINE BitArray(const BitArray &copy);
-  INLINE BitArray &operator = (const BitArray &copy);
   BitArray(const SparseArray &from);
 
   INLINE static BitArray all_on();
@@ -56,8 +54,6 @@ PUBLISHED:
   INLINE static BitArray bit(int index);
   INLINE static BitArray range(int low_bit, int size);
 
-  INLINE ~BitArray();
-
   CONSTEXPR static bool has_max_num_bits();
   CONSTEXPR static int get_max_num_bits();
 

+ 0 - 28
panda/src/putil/bitMask.I

@@ -34,26 +34,6 @@ BitMask(WordType init_value) :
 {
 }
 
-/**
- *
- */
-template<class WType, int nbits>
-INLINE BitMask<WType, nbits>::
-BitMask(const BitMask<WType, nbits> &copy) :
-  _word(copy._word)
-{
-}
-
-/**
- *
- */
-template<class WType, int nbits>
-INLINE BitMask<WType, nbits> &BitMask<WType, nbits>::
-operator = (const BitMask<WType, nbits> &copy) {
-  _word = copy._word;
-  return *this;
-}
-
 /**
  * Returns a BitMask whose bits are all on.
  */
@@ -121,14 +101,6 @@ range(int low_bit, int size) {
   return result;
 }
 
-/**
- *
- */
-template<class WType, int nbits>
-INLINE BitMask<WType, nbits>::
-~BitMask() {
-}
-
 /**
  * Returns true if there is a maximum number of bits that may be stored in
  * this structure, false otherwise.  If this returns true, the number may be

+ 0 - 4
panda/src/putil/bitMask.h

@@ -38,8 +38,6 @@ PUBLISHED:
 
   INLINE BitMask();
   INLINE BitMask(WordType init_value);
-  INLINE BitMask(const BitMask<WType, nbits> &copy);
-  INLINE BitMask<WType, nbits> &operator = (const BitMask<WType, nbits> &copy);
 
   INLINE static BitMask<WType, nbits> all_on();
   INLINE static BitMask<WType, nbits> all_off();
@@ -47,8 +45,6 @@ PUBLISHED:
   INLINE static BitMask<WType, nbits> bit(int index);
   INLINE static BitMask<WType, nbits> range(int low_bit, int size);
 
-  INLINE ~BitMask();
-
   CONSTEXPR static bool has_max_num_bits();
   CONSTEXPR static int get_max_num_bits();
 

+ 0 - 7
panda/src/putil/buttonHandle.I

@@ -19,13 +19,6 @@ CONSTEXPR ButtonHandle::
 ButtonHandle(int index) : _index(index) {
 }
 
-/**
- *
- */
-INLINE ButtonHandle::
-ButtonHandle(const ButtonHandle &copy) : _index(copy._index) {
-}
-
 /**
  *
  */

+ 0 - 1
panda/src/putil/buttonHandle.h

@@ -31,7 +31,6 @@ PUBLISHED:
   // previously by another static initializer!
   INLINE ButtonHandle() DEFAULT_CTOR;
   CONSTEXPR ButtonHandle(int index);
-  INLINE ButtonHandle(const ButtonHandle &copy);
   ButtonHandle(const string &name);
 
 PUBLISHED:

+ 4 - 6
panda/src/putil/iterator_types.h

@@ -14,6 +14,7 @@
 #ifndef ITERATOR_TYPES_H
 #define ITERATOR_TYPES_H
 
+#include "dtoolbase.h"
 
 /**
  * This is an iterator adaptor that converts any iterator that returns a pair
@@ -25,9 +26,8 @@ class first_of_pair_iterator : public pair_iterator {
 public:
   typedef TYPENAME pair_iterator::value_type::first_type value_type;
 
-  first_of_pair_iterator() { }
+  first_of_pair_iterator() DEFAULT_CTOR;
   first_of_pair_iterator(const pair_iterator &init) : pair_iterator(init) { }
-  first_of_pair_iterator(const first_of_pair_iterator<pair_iterator> &copy) : pair_iterator(copy) { }
 
   value_type operator *() {
     return pair_iterator::operator *().first;
@@ -44,9 +44,8 @@ class second_of_pair_iterator : public pair_iterator {
 public:
   typedef TYPENAME pair_iterator::value_type::second_type value_type;
 
-  second_of_pair_iterator() { }
+  second_of_pair_iterator() DEFAULT_CTOR;
   second_of_pair_iterator(const pair_iterator &init) : pair_iterator(init) { }
-  second_of_pair_iterator(const second_of_pair_iterator<pair_iterator> &copy) : pair_iterator(copy) { }
 
   value_type operator *() {
     return pair_iterator::operator *().second;
@@ -62,9 +61,8 @@ class typecast_iterator : public base_iterator {
 public:
   typedef new_type value_type;
 
-  typecast_iterator() { }
+  typecast_iterator() DEFAULT_CTOR;
   typecast_iterator(const base_iterator &init) : base_iterator(init) { }
-  typecast_iterator(const typecast_iterator<base_iterator, new_type> &copy) : base_iterator(copy) { }
 
   value_type operator *() {
     return (new_type)base_iterator::operator *();

+ 3 - 28
panda/src/putil/sparseArray.I

@@ -18,26 +18,6 @@ INLINE SparseArray::
 SparseArray() : _inverse(false) {
 }
 
-/**
- *
- */
-INLINE SparseArray::
-SparseArray(const SparseArray &copy) :
-  _subranges(copy._subranges),
-  _inverse(copy._inverse)
-{
-}
-
-/**
- *
- */
-INLINE SparseArray &SparseArray::
-operator = (const SparseArray &copy) {
-  _subranges = copy._subranges;
-  _inverse = copy._inverse;
-  return *this;
-}
-
 /**
  * Returns a SparseArray with an infinite array of bits, all on.
  */
@@ -62,7 +42,9 @@ all_off() {
 INLINE SparseArray SparseArray::
 lower_on(int on_bits) {
   SparseArray result;
-  result.set_range(0, on_bits);
+  if (on_bits > 0) {
+    result._subranges.push_back(Subrange(0, on_bits));
+  }
   return result;
 }
 
@@ -86,13 +68,6 @@ range(int low_bit, int size) {
   return result;
 }
 
-/**
- *
- */
-INLINE SparseArray::
-~SparseArray() {
-}
-
 /**
  * Returns true if there is a maximum number of bits that may be stored in
  * this structure, false otherwise.  If this returns true, the number may be

+ 0 - 4
panda/src/putil/sparseArray.h

@@ -42,8 +42,6 @@ class DatagramIterator;
 class EXPCL_PANDA_PUTIL SparseArray {
 PUBLISHED:
   INLINE SparseArray();
-  INLINE SparseArray(const SparseArray &copy);
-  INLINE SparseArray &operator = (const SparseArray &copy);
   SparseArray(const BitArray &from);
 
   INLINE static SparseArray all_on();
@@ -52,8 +50,6 @@ PUBLISHED:
   INLINE static SparseArray bit(int index);
   INLINE static SparseArray range(int low_bit, int size);
 
-  INLINE ~SparseArray();
-
   INLINE static bool has_max_num_bits();
   INLINE static int get_max_num_bits();
 

+ 0 - 16
panda/src/putil/writableParam.I

@@ -30,22 +30,6 @@ WritableParam(const WritableParam &copy) :
 {
 }
 
-/**
- *
- */
-INLINE WritableParam::
-~WritableParam() {
-}
-
-/**
- *
- */
-INLINE void WritableParam::
-operator = (const WritableParam &) {
-  // The assignment operator cannot be used for this class.
-  nassertv(false);
-}
-
 /**
  *
  */

+ 1 - 2
panda/src/putil/writableParam.h

@@ -36,11 +36,10 @@ private:
 public:
   INLINE WritableParam(const Datagram &datagram);
   INLINE WritableParam(const WritableParam &other);
-  INLINE ~WritableParam();
 
 private:
   // The assignment operator cannot be used for this class.
-  INLINE void operator = (const WritableParam &other);
+  WritableParam &operator = (const WritableParam &other) DELETED_ASSIGN;
 
 public:
   virtual TypeHandle get_type() const {

+ 2 - 493
panda/src/windisplay/winGraphicsPipe.cxx

@@ -20,10 +20,7 @@
 
 #include "psapi.h"
 #include "powrprof.h"
-
-#ifdef _WIN64
 #include <intrin.h>
-#endif
 
 TypeHandle WinGraphicsPipe::_type_handle;
 
@@ -99,443 +96,6 @@ void get_memory_information (DisplayInformation *display_information) {
   }
 }
 
-typedef union {
-  uint64_t long_integer;
-}
-LONG_INTEGER;
-
-uint64_t cpu_time_function (void) {
-#ifdef _WIN64
-  return __rdtsc();
-#else
-  LONG_INTEGER long_integer;
-  LONG_INTEGER *long_integer_pointer;
-
-  long_integer_pointer = &long_integer;
-
-  __asm {
-      mov   ebx,[long_integer_pointer]
-      rdtsc
-      mov   [ebx + 0], eax
-      mov   [ebx + 4], edx
-  }
-
-  return long_integer.long_integer;
-#endif
-}
-
-typedef union {
-  struct {
-    union {
-      struct {
-        unsigned char al;
-        unsigned char ah;
-      };
-      unsigned int eax;
-    };
-    unsigned int ebx;
-    unsigned int ecx;
-    unsigned int edx;
-  };
-} CPU_ID_REGISTERS;
-
-typedef struct {
-  union {
-    struct {
-      int maximum_cpu_id_input;
-      char cpu_vendor [16];
-    };
-
-    CPU_ID_REGISTERS cpu_id_registers_0;
-  };
-
-  union {
-    CPU_ID_REGISTERS cpu_id_registers_1;
-
-    struct {
-      // eax
-      union {
-        unsigned int eax;
-        unsigned int version_information;
-        struct {
-          unsigned int stepping_id : 4;
-          unsigned int model : 4;
-          unsigned int family : 4;
-          unsigned int processor_type : 2;
-          unsigned int reserved_0 : 2;
-          unsigned int extended_model_id : 4;
-          unsigned int extended_family_id : 8;
-          unsigned int reserved_1 : 4;
-        };
-      };
-
-      // ebx
-      union {
-        unsigned int ebx;
-        struct {
-          unsigned int brand_index : 8;
-          unsigned int clflush : 8;
-          unsigned int maximum_logical_processors : 8;
-          unsigned int initial_apic_id : 8;
-        };
-      };
-
-      // ecx
-      union {
-        unsigned int ecx;
-        struct {
-          unsigned int sse3 : 1;
-          unsigned int reserved_1_to_2 : 2;
-          unsigned int monitor : 1;
-          unsigned int ds_cpl : 1;
-          unsigned int vmx : 1;
-          unsigned int reserved_6 : 1;
-          unsigned int est : 1;
-          unsigned int tm2 : 1;
-          unsigned int reserved_9 : 1;
-          unsigned int cnxt_id : 1;
-          unsigned int reserved_11_to_12 : 2;
-          unsigned int cmpxchg16b : 1;
-          unsigned int xtpr_disable : 1;
-          unsigned int reserved_15_to_31 : 17;
-        };
-      };
-
-      // edx
-      union {
-        unsigned int edx;
-        struct {
-          unsigned int fpu : 1;
-          unsigned int vme : 1;
-          unsigned int de : 1;
-          unsigned int pse : 1;
-          unsigned int tsc : 1;
-          unsigned int msr : 1;
-          unsigned int pae : 1;
-          unsigned int mce : 1;
-          unsigned int cx8 : 1;
-          unsigned int apic : 1;
-          unsigned int reserved_10 : 1;
-          unsigned int sep : 1;
-          unsigned int mtrr : 1;
-          unsigned int pge : 1;
-          unsigned int mca : 1;
-          unsigned int cmov : 1;
-          unsigned int pat : 1;
-          unsigned int pse_36 : 1;
-          unsigned int psn : 1;
-          unsigned int cflush : 1;
-          unsigned int reserved_20 : 1;
-          unsigned int ds : 1;
-          unsigned int acpi : 1;
-          unsigned int mmx : 1;
-          unsigned int fxsr : 1;
-          unsigned int sse : 1;
-          unsigned int sse2 : 1;
-          unsigned int ss : 1;
-          unsigned int htt : 1;
-          unsigned int tm : 1;
-          unsigned int reserved_30 : 1;
-          unsigned int pbe : 1;
-        };
-      };
-    };
-  };
-
-  #define MAXIMUM_2 8
-  #define MAXIMUM_CHARACTERS (MAXIMUM_2 * sizeof(CPU_ID_REGISTERS))
-
-  union {
-    CPU_ID_REGISTERS cpu_id_registers_2;
-    unsigned char character_array_2 [MAXIMUM_CHARACTERS];
-    CPU_ID_REGISTERS cpu_id_registers_2_array [MAXIMUM_2];
-  };
-
-  union {
-    CPU_ID_REGISTERS cpu_id_registers_0x80000000;
-  };
-
-  union {
-    CPU_ID_REGISTERS cpu_id_registers_0x80000001;
-  };
-
-  union {
-    char cpu_brand_string [sizeof(CPU_ID_REGISTERS) * 3];
-    struct {
-      CPU_ID_REGISTERS cpu_id_registers_0x80000002;
-      CPU_ID_REGISTERS cpu_id_registers_0x80000003;
-      CPU_ID_REGISTERS cpu_id_registers_0x80000004;
-    };
-  };
-
-  union {
-    struct {
-      unsigned int eax;
-      unsigned int ebx;
-      union {
-        unsigned int ecx;
-        struct {
-          unsigned int l1_data_cache_line_size : 8;
-          unsigned int l1_data_reserved_8_to_15 : 8;
-          unsigned int l1_data_associativity : 8;
-          unsigned int l1_data_cache_size : 8;
-        };
-      };
-      union {
-        unsigned int edx;
-        struct {
-          unsigned int l1_code_cache_line_size : 8;
-          unsigned int l1_code_reserved_8_to_15 : 8;
-          unsigned int l1_code_associativity : 8;
-          unsigned int l1_code_cache_size : 8;
-        };
-      };
-    };
-    CPU_ID_REGISTERS cpu_id_registers_0x80000005;
-  };
-
-  union {
-    struct {
-      unsigned int eax;
-      unsigned int ebx;
-      union {
-        unsigned int ecx;
-        struct {
-          unsigned int l2_cache_line_size : 8;
-          unsigned int l2_reserved_8_to_11 : 4;
-          unsigned int l2_associativity : 4;
-          unsigned int l2_cache_size : 16;
-        };
-      };
-      unsigned int edx;
-    };
-    CPU_ID_REGISTERS cpu_id_registers_0x80000006;
-  };
-
-  CPU_ID_REGISTERS cpu_id_registers_0x80000008;
-
-  unsigned int cache_line_size;
-  unsigned int log_base_2_cache_line_size;
-} CPU_ID;
-
-typedef struct {
-  CPU_ID_REGISTERS cpu_id_registers_0;
-  CPU_ID_REGISTERS cpu_id_registers_1;
-
-  CPU_ID_REGISTERS cpu_id_registers_0x80000000;
-  CPU_ID_REGISTERS cpu_id_registers_0x80000001;
-  CPU_ID_REGISTERS cpu_id_registers_0x80000002;
-  CPU_ID_REGISTERS cpu_id_registers_0x80000003;
-  CPU_ID_REGISTERS cpu_id_registers_0x80000004;
-
-  CPU_ID_REGISTERS cpu_id_registers_0x80000006;
-
-  CPU_ID_REGISTERS cpu_id_registers_0x80000008;
-} CPU_ID_BINARY_DATA;
-
-void cpu_id_to_cpu_id_binary_data (CPU_ID *cpu_id, CPU_ID_BINARY_DATA *cpu_id_binary_data) {
-  cpu_id_binary_data->cpu_id_registers_0 = cpu_id->cpu_id_registers_0;
-  cpu_id_binary_data->cpu_id_registers_1 = cpu_id->cpu_id_registers_1;
-  cpu_id_binary_data->cpu_id_registers_0x80000000 = cpu_id->cpu_id_registers_0x80000000;
-  cpu_id_binary_data->cpu_id_registers_0x80000001 = cpu_id->cpu_id_registers_0x80000001;
-  cpu_id_binary_data->cpu_id_registers_0x80000002 = cpu_id->cpu_id_registers_0x80000002;
-  cpu_id_binary_data->cpu_id_registers_0x80000003 = cpu_id->cpu_id_registers_0x80000003;
-  cpu_id_binary_data->cpu_id_registers_0x80000004 = cpu_id->cpu_id_registers_0x80000004;
-  cpu_id_binary_data->cpu_id_registers_0x80000006 = cpu_id->cpu_id_registers_0x80000006;
-  cpu_id_binary_data->cpu_id_registers_0x80000008 = cpu_id->cpu_id_registers_0x80000008;
-}
-
-void cpu_id_binary_data_to_cpu_id (CPU_ID_BINARY_DATA *cpu_id_binary_data, CPU_ID *cpu_id) {
-  memset (cpu_id, 0, sizeof(CPU_ID));
-
-  cpu_id->cpu_id_registers_0 = cpu_id_binary_data->cpu_id_registers_0;
-  cpu_id->cpu_id_registers_1 = cpu_id_binary_data->cpu_id_registers_1;
-  cpu_id->cpu_id_registers_0x80000000 = cpu_id_binary_data->cpu_id_registers_0x80000000;
-  cpu_id->cpu_id_registers_0x80000001 = cpu_id_binary_data->cpu_id_registers_0x80000001;
-  cpu_id->cpu_id_registers_0x80000002 = cpu_id_binary_data->cpu_id_registers_0x80000002;
-  cpu_id->cpu_id_registers_0x80000003 = cpu_id_binary_data->cpu_id_registers_0x80000003;
-  cpu_id->cpu_id_registers_0x80000004 = cpu_id_binary_data->cpu_id_registers_0x80000004;
-  cpu_id->cpu_id_registers_0x80000006 = cpu_id_binary_data->cpu_id_registers_0x80000006;
-  cpu_id->cpu_id_registers_0x80000008 = cpu_id_binary_data->cpu_id_registers_0x80000008;
-}
-
-int cpuid(int input_eax, CPU_ID_REGISTERS *cpu_id_registers) {
-  int state;
-
-  state = false;
-  __try {
-    if (input_eax == 0) {
-      // the order of ecx and edx is swapped when saved to make a proper
-      // vendor string
-#ifdef _WIN64
-      __cpuid((int*)cpu_id_registers, input_eax);
-      unsigned int tmp = cpu_id_registers->edx;
-      cpu_id_registers->edx = cpu_id_registers->ecx;
-      cpu_id_registers->ecx = tmp;
-#else
-      __asm {
-          mov   eax, [input_eax]
-          mov   edi, [cpu_id_registers]
-
-          cpuid
-
-          mov   [edi + 0], eax
-          mov   [edi + 4], ebx
-          mov   [edi + 8], edx
-          mov   [edi + 12], ecx
-      }
-#endif
-    } else {
-#ifdef _WIN64
-      __cpuid((int*)cpu_id_registers, input_eax);
-#else
-      __asm {
-          mov   eax, [input_eax]
-          mov   edi, [cpu_id_registers]
-
-          cpuid
-
-          mov   [edi + 0], eax
-          mov   [edi + 4], ebx
-          mov   [edi + 8], ecx
-          mov   [edi + 12], edx
-      }
-#endif
-    }
-
-    state = true;
-  }
-  __except (1) {
-    state = false;
-  }
-
-  return state;
-}
-
-void parse_cpu_id(CPU_ID *cpu_id) {
-  printf("CPUID\n");
-  printf("  vendor = %s\n", cpu_id->cpu_vendor);
-  printf("  brand string %s\n", cpu_id->cpu_brand_string);
-  printf("  maximum_cpu_id_input = %u\n", cpu_id->maximum_cpu_id_input);
-  printf("  maximum extended information = 0x%X\n", cpu_id->cpu_id_registers_0x80000000.eax);
-
-  printf("  MMX  = %u\n", cpu_id->mmx);
-  printf("  SSE  = %u\n", cpu_id->sse);
-  printf("  SSE2 = %u\n", cpu_id->sse2);
-  printf("  SSE3 = %u\n", cpu_id->sse3);
-
-  printf("  EST  = %u\n", cpu_id->est);
-
-  if (cpu_id->maximum_cpu_id_input >= 1) {
-    printf("  version_information\n");
-    printf("    stepping_id %u\n", cpu_id->stepping_id);
-    printf("    model %u\n", cpu_id->model);
-    printf("    family %u\n", cpu_id->family);
-    printf("    processor_type %u\n", cpu_id->processor_type);
-    printf("    extended_model_id %u\n", cpu_id->extended_model_id);
-    printf("    extended_family_id %u\n", cpu_id->extended_family_id);
-
-    printf("    brand_index %u\n", cpu_id->brand_index);
-    printf("    clflush %u\n", cpu_id->clflush);
-    printf("    maximum_logical_processors %u\n", cpu_id->maximum_logical_processors);
-    printf("    initial_apic_id %u\n", cpu_id->initial_apic_id);
-
-// printf("  cache_line_size %u\n", cpu_id->cache_line_size); printf("
-// log_base_2_cache_line_size %u\n", cpu_id->log_base_2_cache_line_size);
-  }
-
-  if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000005) {
-    printf("  l1_data_cache_line_size %d\n", cpu_id->l1_data_cache_line_size);
-    printf("  l1_data_associativity %d\n", cpu_id->l1_data_associativity);
-    printf("  l1_data_cache_size %dK\n", cpu_id->l1_data_cache_size);
-
-    printf("  l1_code_cache_line_size %d\n", cpu_id->l1_code_cache_line_size);
-    printf("  l1_code_associativity %d\n", cpu_id->l1_code_associativity);
-    printf("  l1_code_cache_size %dK\n", cpu_id->l1_code_cache_size);
-  }
-
-  if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000006) {
-    printf("  l2_cache_line_size %d\n", cpu_id->l2_cache_line_size);
-    printf("  l2_associativity %d\n", cpu_id->l2_associativity);
-    printf("  l2_cache_size %dK\n", cpu_id->l2_cache_size);
-  }
-}
-
-int initialize_cpu_id(CPU_ID *cpu_id) {
-  int debug = false;
-  memset(cpu_id, 0, sizeof(CPU_ID));
-
-  if (cpuid(0, &cpu_id->cpu_id_registers_0)) {
-    if (cpu_id->maximum_cpu_id_input >= 1) {
-      cpuid(1, &cpu_id->cpu_id_registers_1);
-    }
-    if (cpu_id->maximum_cpu_id_input >= 2) {
-      unsigned int index;
-
-      cpuid(2, &cpu_id->cpu_id_registers_2);
-      if (debug) {
-        printf("  al = %u\n", cpu_id->cpu_id_registers_2.al);
-      }
-
-      for (index = 1; index < cpu_id->cpu_id_registers_2.al && index < MAXIMUM_2; index++) {
-        cpuid(2, &cpu_id->cpu_id_registers_2_array [index]);
-      }
-
-      for (index = 1; index < MAXIMUM_CHARACTERS; index++) {
-        if (cpu_id->character_array_2 [index]) {
-          if (debug) {
-            printf("  cache/TLB byte = %X\n", cpu_id->character_array_2 [index]);
-          }
-          switch (cpu_id->character_array_2 [index]) {
-          case 0x0A:
-          case 0x0C:
-            cpu_id->cache_line_size = 32;
-            cpu_id->log_base_2_cache_line_size = 5;
-            break;
-
-          case 0x2C:
-          case 0x60:
-          case 0x66:
-          case 0x67:
-          case 0x68:
-            cpu_id->cache_line_size = 64;
-            cpu_id->log_base_2_cache_line_size = 6;
-            break;
-          }
-        }
-      }
-    }
-
-    cpuid(0x80000000, &cpu_id->cpu_id_registers_0x80000000);
-
-    if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000001) {
-      cpuid(0x80000001, &cpu_id->cpu_id_registers_0x80000001);
-    }
-
-    if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000004) {
-      cpuid(0x80000002, &cpu_id->cpu_id_registers_0x80000002);
-      cpuid(0x80000003, &cpu_id->cpu_id_registers_0x80000003);
-      cpuid(0x80000004, &cpu_id->cpu_id_registers_0x80000004);
-    }
-
-    if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000005) {
-      cpuid(0x80000005, &cpu_id->cpu_id_registers_0x80000005);
-    }
-
-    if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000006) {
-      cpuid(0x80000006, &cpu_id->cpu_id_registers_0x80000006);
-    }
-
-    if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000008) {
-      cpuid(0x80000008, &cpu_id->cpu_id_registers_0x80000008);
-    }
-
-    return true;
-  }
-
-  return false;
-}
-
 int update_cpu_frequency_function(int processor_number, DisplayInformation *display_information) {
   int update;
 
@@ -776,9 +336,6 @@ lookup_cpu_data() {
   // set callback for memory function
   _display_information->_get_memory_information_function = get_memory_information;
 
-  // set callback for cpu time function
-  _display_information->_cpu_time_function = cpu_time_function;
-
   // determine CPU frequency
   uint64_t time;
   uint64_t end_time;
@@ -803,12 +360,12 @@ lookup_cpu_data() {
   if (QueryPerformanceFrequency(&frequency)) {
     if (frequency.QuadPart > 0) {
       if (QueryPerformanceCounter (&counter)) {
-        time = cpu_time_function();
+        time = __rdtsc();
         end.QuadPart = counter.QuadPart + frequency.QuadPart;
         while (QueryPerformanceCounter (&counter) && counter.QuadPart < end.QuadPart) {
 
         }
-        end_time = cpu_time_function();
+        end_time = __rdtsc();
 
         _display_information->_cpu_frequency = end_time - time;
       }
@@ -821,54 +378,6 @@ lookup_cpu_data() {
   sprintf(string, "CPU frequency: %I64d\n", _display_information->_cpu_frequency);
   windisplay_cat.info() << string;
 
-
-  // CPUID
-  CPU_ID cpu_id;
-
-  windisplay_cat.info() << "start CPU ID\n";
-
-  if (initialize_cpu_id(&cpu_id)) {
-    CPU_ID_BINARY_DATA *cpu_id_binary_data;
-
-    cpu_id_binary_data = new (CPU_ID_BINARY_DATA);
-    if (cpu_id_binary_data) {
-      cpu_id_to_cpu_id_binary_data(&cpu_id, cpu_id_binary_data);
-      _display_information->_cpu_id_size = sizeof(CPU_ID_BINARY_DATA) / sizeof(unsigned int);
-      _display_information->_cpu_id_data = (unsigned int *) cpu_id_binary_data;
-
-      _display_information->_cpu_vendor_string = strdup(cpu_id.cpu_vendor);
-      _display_information->_cpu_brand_string = strdup(cpu_id.cpu_brand_string);
-      _display_information->_cpu_version_information = cpu_id.version_information;
-      _display_information->_cpu_brand_index = cpu_id.brand_index;
-
-      if (windisplay_cat.is_debug()) {
-        windisplay_cat.debug()
-          << hex << _display_information->_cpu_id_version << dec << "|";
-
-        int index;
-        for (index = 0; index < _display_information->_cpu_id_size; ++index) {
-          unsigned int data;
-          data = _display_information->_cpu_id_data[index];
-
-          windisplay_cat.debug(false)
-            << hex << data << dec;
-          if (index < _display_information->_cpu_id_size - 1) {
-            windisplay_cat.debug(false)
-              << "|";
-          }
-        }
-        windisplay_cat.debug(false)
-          << "\n";
-      }
-    }
-
-    if (windisplay_cat.is_debug()) {
-      parse_cpu_id(&cpu_id);
-    }
-  }
-
-  windisplay_cat.info() << "end CPU ID\n";
-
   // Number of CPU's
   count_number_of_cpus(_display_information);
 }

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio