Browse Source

Merge branch 'master' into deploy-ng

rdb 7 years ago
parent
commit
57b66ebeaf
59 changed files with 633 additions and 169 deletions
  1. 1 1
      direct/src/dcparser/dcArrayParameter.h
  2. 1 1
      direct/src/dcparser/dcAtomicField.h
  3. 1 1
      direct/src/dcparser/dcClass.h
  4. 1 1
      direct/src/dcparser/dcClassParameter.h
  5. 1 1
      direct/src/dcparser/dcDeclaration.h
  6. 1 1
      direct/src/dcparser/dcField.h
  7. 1 1
      direct/src/dcparser/dcFile.h
  8. 1 1
      direct/src/dcparser/dcKeyword.h
  9. 1 1
      direct/src/dcparser/dcKeywordList.h
  10. 1 1
      direct/src/dcparser/dcMolecularField.h
  11. 5 5
      direct/src/dcparser/dcNumericRange.I
  12. 6 6
      direct/src/dcparser/dcNumericRange.h
  13. 1 1
      direct/src/dcparser/dcPackData.h
  14. 1 1
      direct/src/dcparser/dcPacker.h
  15. 1 1
      direct/src/dcparser/dcPackerCatalog.h
  16. 1 1
      direct/src/dcparser/dcPackerInterface.h
  17. 1 1
      direct/src/dcparser/dcParameter.h
  18. 1 1
      direct/src/dcparser/dcParserDefs.h
  19. 1 1
      direct/src/dcparser/dcSimpleParameter.h
  20. 1 1
      direct/src/dcparser/dcSwitch.h
  21. 1 1
      direct/src/dcparser/dcSwitchParameter.h
  22. 1 1
      direct/src/dcparser/dcTypedef.h
  23. 5 0
      direct/src/dcparser/dcbase.h
  24. 1 1
      direct/src/dcparser/hashGenerator.h
  25. 1 1
      direct/src/dcparser/primeNumberGenerator.h
  26. 9 0
      direct/src/directbase/directsymbols.h
  27. 2 2
      direct/src/distributed/PyDatagram.py
  28. 2 2
      direct/src/distributed/PyDatagramIterator.py
  29. 4 0
      dtool/src/cppparser/cppFunctionType.cxx
  30. 14 14
      dtool/src/dtoolbase/atomicAdjust.h
  31. 22 4
      dtool/src/interrogate/interfaceMakerPythonNative.cxx
  32. 1 1
      makepanda/makepanda.py
  33. 61 0
      makepanda/test_wheel.py
  34. 1 0
      panda/src/collide/collisionBox.cxx
  35. 1 1
      panda/src/egg/eggPrimitive.cxx
  36. 0 1
      panda/src/egg2pg/eggLoader.cxx
  37. 36 39
      panda/src/express/datagram.I
  38. 18 3
      panda/src/express/datagram.h
  39. 21 0
      panda/src/express/datagramIterator.I
  40. 3 0
      panda/src/express/datagramIterator.h
  41. 35 0
      panda/src/express/datagram_ext.I
  42. 40 0
      panda/src/express/datagram_ext.h
  43. 1 1
      panda/src/express/zStreamBuf.h
  44. 42 0
      panda/src/linmath/lmatrix3_src.I
  45. 8 4
      panda/src/linmath/lmatrix3_src.h
  46. 51 0
      panda/src/linmath/lmatrix4_src.I
  47. 10 4
      panda/src/linmath/lmatrix4_src.h
  48. 0 1
      panda/src/pgraph/geomNode.cxx
  49. 0 1
      panda/src/pgraph/geomTransformer.cxx
  50. 1 4
      panda/src/recorder/socketStreamRecorder.cxx
  51. 0 1
      panda/src/text/dynamicTextFont.cxx
  52. 9 9
      pandatool/src/mayaegg/mayaEggLoader.cxx
  53. 2 2
      pandatool/src/mayaegg/mayaToEggConverter.cxx
  54. 3 2
      tests/egg2pg/test_egg_coordsys.py
  55. 12 6
      tests/gobj/test_texture_pool.py
  56. 62 0
      tests/linmath/test_lmatrix3.py
  57. 89 0
      tests/linmath/test_lmatrix4.py
  58. 0 20
      tests/linmath/test_matrix_invert.py
  59. 35 14
      tests/putil/test_datagram.py

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 5 - 5
direct/src/dcparser/dcNumericRange.I

@@ -52,7 +52,7 @@ operator = (const DCNumericRange<NUM> &copy) {
  * otherwise.
  * otherwise.
  */
  */
 template <class NUM>
 template <class NUM>
-bool DCNumericRange<NUM>::
+INLINE bool DCNumericRange<NUM>::
 is_in_range(Number num) const {
 is_in_range(Number num) const {
   if (_ranges.empty()) {
   if (_ranges.empty()) {
     return true;
     return true;
@@ -106,7 +106,7 @@ get_one_value() const {
  *
  *
  */
  */
 template <class NUM>
 template <class NUM>
-void DCNumericRange<NUM>::
+INLINE void DCNumericRange<NUM>::
 generate_hash(HashGenerator &hashgen) const {
 generate_hash(HashGenerator &hashgen) const {
   if (!_ranges.empty()) {
   if (!_ranges.empty()) {
     hashgen.add_int(_ranges.size());
     hashgen.add_int(_ranges.size());
@@ -124,7 +124,7 @@ generate_hash(HashGenerator &hashgen) const {
  *
  *
  */
  */
 template <class NUM>
 template <class NUM>
-void DCNumericRange<NUM>::
+INLINE void DCNumericRange<NUM>::
 output(std::ostream &out, Number divisor) const {
 output(std::ostream &out, Number divisor) const {
   if (!_ranges.empty()) {
   if (!_ranges.empty()) {
     typename Ranges::const_iterator ri;
     typename Ranges::const_iterator ri;
@@ -144,7 +144,7 @@ output(std::ostream &out, Number divisor) const {
  * characters.
  * characters.
  */
  */
 template <class NUM>
 template <class NUM>
-void DCNumericRange<NUM>::
+INLINE void DCNumericRange<NUM>::
 output_char(std::ostream &out, Number divisor) const {
 output_char(std::ostream &out, Number divisor) const {
   if (divisor != 1) {
   if (divisor != 1) {
     output(out, divisor);
     output(out, divisor);
@@ -179,7 +179,7 @@ clear() {
  * minmax overlaps an existing minmax.
  * minmax overlaps an existing minmax.
  */
  */
 template <class NUM>
 template <class NUM>
-bool DCNumericRange<NUM>::
+INLINE bool DCNumericRange<NUM>::
 add_range(Number min, Number max) {
 add_range(Number min, Number max) {
   // Check for an overlap.  This is probably indicative of a typo and should
   // Check for an overlap.  This is probably indicative of a typo and should
   // be reported.
   // be reported.

+ 6 - 6
direct/src/dcparser/dcNumericRange.h

@@ -23,7 +23,7 @@
  * to constrain simple numeric types, as well as array sizes.
  * to constrain simple numeric types, as well as array sizes.
  */
  */
 template <class NUM>
 template <class NUM>
-class DCNumericRange {
+class EXPCL_DIRECT_DCPARSER DCNumericRange {
 public:
 public:
   typedef NUM Number;
   typedef NUM Number;
 
 
@@ -32,20 +32,20 @@ public:
   INLINE DCNumericRange(const DCNumericRange &copy);
   INLINE DCNumericRange(const DCNumericRange &copy);
   INLINE void operator = (const DCNumericRange &copy);
   INLINE void operator = (const DCNumericRange &copy);
 
 
-  bool is_in_range(Number num) const;
+  INLINE bool is_in_range(Number num) const;
   INLINE void validate(Number num, bool &range_error) const;
   INLINE void validate(Number num, bool &range_error) const;
 
 
   INLINE bool has_one_value() const;
   INLINE bool has_one_value() const;
   INLINE Number get_one_value() const;
   INLINE Number get_one_value() const;
 
 
-  void generate_hash(HashGenerator &hashgen) const;
+  INLINE void generate_hash(HashGenerator &hashgen) const;
 
 
-  void output(std::ostream &out, Number divisor = 1) const;
-  void output_char(std::ostream &out, Number divisor = 1) const;
+  INLINE void output(std::ostream &out, Number divisor = 1) const;
+  INLINE void output_char(std::ostream &out, Number divisor = 1) const;
 
 
 public:
 public:
   INLINE void clear();
   INLINE void clear();
-  bool add_range(Number min, Number max);
+  INLINE bool add_range(Number min, Number max);
 
 
   INLINE bool is_empty() const;
   INLINE bool is_empty() const;
   INLINE int get_num_ranges() const;
   INLINE int get_num_ranges() const;

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

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

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

@@ -31,7 +31,7 @@ class DCSwitchParameter;
  * See also direct/src/doc/dcPacker.txt for a more complete description and
  * See also direct/src/doc/dcPacker.txt for a more complete description and
  * examples of using this class.
  * examples of using this class.
  */
  */
-class DCPacker {
+class EXPCL_DIRECT_DCPARSER DCPacker {
 PUBLISHED:
 PUBLISHED:
   DCPacker();
   DCPacker();
   ~DCPacker();
   ~DCPacker();

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

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

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

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

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

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

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

@@ -43,7 +43,7 @@ extern DCFile *dc_file;
 // that has member functions in a union), so we'll use a class instead.  That
 // that has member functions in a union), so we'll use a class instead.  That
 // means we need to declare it externally, here.
 // means we need to declare it externally, here.
 
 
-class DCTokenType {
+class EXPCL_DIRECT_DCPARSER DCTokenType {
 public:
 public:
   union U {
   union U {
     int s_int;
     int s_int;

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

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

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

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

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

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

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

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

+ 5 - 0
direct/src/dcparser/dcbase.h

@@ -70,6 +70,11 @@
 #define END_PUBLISH
 #define END_PUBLISH
 #define BLOCKING
 #define BLOCKING
 
 
+// These control the declspec(dllexport/dllimport) on Windows.  When compiling
+// outside of Panda, we assume we aren't part of a DLL.
+#define EXPCL_DIRECT_DCPARSER
+#define EXPTP_DIRECT_DCPARSER
+
 // Panda defines some assert-type macros.  We map those to the standard assert
 // Panda defines some assert-type macros.  We map those to the standard assert
 // macro outside of Panda.
 // macro outside of Panda.
 #define nassertr(condition, return_value) assert(condition)
 #define nassertr(condition, return_value) assert(condition)

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

@@ -20,7 +20,7 @@
 /**
 /**
  * This class generates an arbitrary hash number from a sequence of ints.
  * This class generates an arbitrary hash number from a sequence of ints.
  */
  */
-class HashGenerator {
+class EXPCL_DIRECT_DCPARSER HashGenerator {
 public:
 public:
   HashGenerator();
   HashGenerator();
 
 

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

@@ -30,7 +30,7 @@ typedef std::vector<int> vector_int;
  * For a given integer n, it will return the nth prime number.  This will
  * For a given integer n, it will return the nth prime number.  This will
  * involve a recompute step only if n is greater than any previous n.
  * involve a recompute step only if n is greater than any previous n.
  */
  */
-class PrimeNumberGenerator {
+class EXPCL_DIRECT_DCPARSER PrimeNumberGenerator {
 public:
 public:
   PrimeNumberGenerator();
   PrimeNumberGenerator();
 
 

+ 9 - 0
direct/src/directbase/directsymbols.h

@@ -18,6 +18,7 @@
 
 
 /* BUILDING_DIRECT is just a buildsystem shortcut for all of these: */
 /* BUILDING_DIRECT is just a buildsystem shortcut for all of these: */
 #ifdef BUILDING_DIRECT
 #ifdef BUILDING_DIRECT
+  #define BUILDING_DIRECT_DCPARSER
   #define BUILDING_DIRECT_DEADREC
   #define BUILDING_DIRECT_DEADREC
   #define BUILDING_DIRECT_DIRECTD
   #define BUILDING_DIRECT_DIRECTD
   #define BUILDING_DIRECT_INTERVAL
   #define BUILDING_DIRECT_INTERVAL
@@ -26,6 +27,14 @@
   #define BUILDING_DIRECT_DISTRIBUTED
   #define BUILDING_DIRECT_DISTRIBUTED
 #endif
 #endif
 
 
+#ifdef BUILDING_DIRECT_DCPARSER
+  #define EXPCL_DIRECT_DCPARSER EXPORT_CLASS
+  #define EXPTP_DIRECT_DCPARSER EXPORT_TEMPL
+#else
+  #define EXPCL_DIRECT_DCPARSER IMPORT_CLASS
+  #define EXPTP_DIRECT_DCPARSER IMPORT_TEMPL
+#endif
+
 #ifdef BUILDING_DIRECT_DEADREC
 #ifdef BUILDING_DIRECT_DEADREC
   #define EXPCL_DIRECT_DEADREC EXPORT_CLASS
   #define EXPCL_DIRECT_DEADREC EXPORT_CLASS
   #define EXPTP_DIRECT_DEADREC EXPORT_TEMPL
   #define EXPTP_DIRECT_DEADREC EXPORT_TEMPL

+ 2 - 2
direct/src/distributed/PyDatagram.py

@@ -25,8 +25,8 @@ class PyDatagram(Datagram):
         STUint64: (Datagram.addUint64, int),
         STUint64: (Datagram.addUint64, int),
         STFloat64: (Datagram.addFloat64, None),
         STFloat64: (Datagram.addFloat64, None),
         STString: (Datagram.addString, None),
         STString: (Datagram.addString, None),
-        STBlob: (Datagram.addString, None),
-        STBlob32: (Datagram.addString32, None),
+        STBlob: (Datagram.addBlob, None),
+        STBlob32: (Datagram.addBlob32, None),
         }
         }
 
 
     #def addChannel(self, channelId):
     #def addChannel(self, channelId):

+ 2 - 2
direct/src/distributed/PyDatagramIterator.py

@@ -23,8 +23,8 @@ class PyDatagramIterator(DatagramIterator):
         STUint64: DatagramIterator.getUint64,
         STUint64: DatagramIterator.getUint64,
         STFloat64: DatagramIterator.getFloat64,
         STFloat64: DatagramIterator.getFloat64,
         STString: DatagramIterator.getString,
         STString: DatagramIterator.getString,
-        STBlob: DatagramIterator.getString,
-        STBlob32: DatagramIterator.getString32,
+        STBlob: DatagramIterator.getBlob,
+        STBlob32: DatagramIterator.getBlob32,
         }
         }
 
 
     getChannel = DatagramIterator.getUint64
     getChannel = DatagramIterator.getUint64

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

@@ -292,6 +292,10 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
 
 
     out << str;
     out << str;
 
 
+  } else if (_flags & F_operator_typecast) {
+    out << "operator ";
+    _return_type->output_instance(out, indent_level, scope, complete, "", prename + str);
+
   } else {
   } else {
     if (prename.empty()) {
     if (prename.empty()) {
       _return_type->output_instance(out, indent_level, scope, complete,
       _return_type->output_instance(out, indent_level, scope, complete,

+ 14 - 14
dtool/src/dtoolbase/atomicAdjust.h

@@ -30,6 +30,20 @@ struct AtomicAdjust {
 #include "atomicAdjustDummyImpl.h"
 #include "atomicAdjustDummyImpl.h"
 typedef AtomicAdjustDummyImpl AtomicAdjust;
 typedef AtomicAdjustDummyImpl AtomicAdjust;
 
 
+#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))) || (defined(__clang__) && (__clang_major__ >= 3))
+// GCC 4.7 and above has built-in __atomic functions for atomic operations.
+// Clang 3.0 and above also supports them.
+
+#include "atomicAdjustGccImpl.h"
+typedef AtomicAdjustGccImpl AtomicAdjust;
+
+#if (__GCC_ATOMIC_INT_LOCK_FREE + __GCC_ATOMIC_LONG_LOCK_FREE) > 0
+#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
+#endif
+#if __GCC_ATOMIC_POINTER_LOCK_FREE > 0
+#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
+#endif
+
 #elif (defined(__i386__) || defined(_M_IX86)) && !defined(__APPLE__)
 #elif (defined(__i386__) || defined(_M_IX86)) && !defined(__APPLE__)
 // For an i386 architecture, we'll always use the i386 implementation.  It
 // For an i386 architecture, we'll always use the i386 implementation.  It
 // should be safe for any OS, and it might be a bit faster than any OS-
 // should be safe for any OS, and it might be a bit faster than any OS-
@@ -45,20 +59,6 @@ typedef AtomicAdjustI386Impl AtomicAdjust;
 #define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
 #define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
 #define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
 #define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
 
 
-#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))) || (defined(__clang__) && (__clang_major__ >= 3))
-// GCC 4.7 and above has built-in __atomic functions for atomic operations.
-// Clang 3.0 and above also supports them.
-
-#include "atomicAdjustGccImpl.h"
-typedef AtomicAdjustGccImpl AtomicAdjust;
-
-#if (__GCC_ATOMIC_INT_LOCK_FREE + __GCC_ATOMIC_INT_LOCK_FREE) > 0
-#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
-#endif
-#if __GCC_ATOMIC_POINTER_LOCK_FREE > 0
-#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
-#endif
-
 #elif defined(THREAD_WIN32_IMPL)
 #elif defined(THREAD_WIN32_IMPL)
 
 
 #include "atomicAdjustWin32Impl.h"
 #include "atomicAdjustWin32Impl.h"

+ 22 - 4
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -789,8 +789,6 @@ InterfaceMakerPythonNative::
  */
  */
 void InterfaceMakerPythonNative::
 void InterfaceMakerPythonNative::
 write_prototypes(ostream &out_code, ostream *out_h) {
 write_prototypes(ostream &out_code, ostream *out_h) {
-  Functions::iterator fi;
-
   if (out_h != nullptr) {
   if (out_h != nullptr) {
     *out_h << "#include \"py_panda.h\"\n\n";
     *out_h << "#include \"py_panda.h\"\n\n";
   }
   }
@@ -917,7 +915,6 @@ write_prototypes_class_external(ostream &out, Object *obj) {
 void InterfaceMakerPythonNative::
 void InterfaceMakerPythonNative::
 write_prototypes_class(ostream &out_code, ostream *out_h, Object *obj) {
 write_prototypes_class(ostream &out_code, ostream *out_h, Object *obj) {
   std::string ClassName = make_safe_name(obj->_itype.get_scoped_name());
   std::string ClassName = make_safe_name(obj->_itype.get_scoped_name());
-  Functions::iterator fi;
 
 
   out_code << "/**\n";
   out_code << "/**\n";
   out_code << " * Forward declarations for top-level class " << ClassName << "\n";
   out_code << " * Forward declarations for top-level class " << ClassName << "\n";
@@ -1089,6 +1086,27 @@ write_class_details(ostream &out, Object *obj) {
       }
       }
     }
     }
 
 
+    // Are there any implicit cast operators that can cast this object to our
+    // desired pointer?
+    for (Function *func : obj->_methods) {
+      for (FunctionRemap *remap : func->_remaps) {
+        if (remap->_type == FunctionRemap::T_typecast_method &&
+            is_remap_legal(remap) &&
+            !remap->_return_type->return_value_needs_management() &&
+            (remap->_cppfunc->_storage_class & CPPInstance::SC_explicit) == 0 &&
+            TypeManager::is_pointer(remap->_return_type->get_new_type())) {
+
+          CPPType *cast_type = remap->_return_type->get_orig_type();
+          CPPType *obj_type = TypeManager::unwrap(TypeManager::resolve_type(remap->_return_type->get_new_type()));
+          string return_expr = "(" + cast_type->get_local_name(&parser) + ")*local_this";
+          out << "  // " << *remap->_cppfunc << "\n";
+          out << "  if (requested_type == Dtool_Ptr_" << make_safe_name(obj_type->get_local_name(&parser)) << ") {\n";
+          out << "    return (void *)(" << remap->_return_type->get_return_expr(return_expr) << ");\n";
+          out << "  }\n";
+        }
+      }
+    }
+
     out << "  return nullptr;\n";
     out << "  return nullptr;\n";
     out << "}\n\n";
     out << "}\n\n";
 
 
@@ -3301,7 +3319,7 @@ write_prototype_for(ostream &out, InterfaceMaker::Function *func) {
  */
  */
 void InterfaceMakerPythonNative::
 void InterfaceMakerPythonNative::
 write_prototype_for_name(ostream &out, InterfaceMaker::Function *func, const std::string &function_namename) {
 write_prototype_for_name(ostream &out, InterfaceMaker::Function *func, const std::string &function_namename) {
-  Function::Remaps::const_iterator ri;
+// Function::Remaps::const_iterator ri;
 
 
 // for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
 // for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
 // FunctionRemap *remap = (*ri);
 // FunctionRemap *remap = (*ri);

+ 1 - 1
makepanda/makepanda.py

@@ -5316,7 +5316,7 @@ if (PkgSkip("DIRECT")==0):
 #
 #
 
 
 if (PkgSkip("DIRECT")==0):
 if (PkgSkip("DIRECT")==0):
-  OPTS=['DIR:direct/src/dcparser', 'WITHINPANDA', 'BISONPREFIX_dcyy', 'PYTHON']
+  OPTS=['DIR:direct/src/dcparser', 'BUILDING:DIRECT_DCPARSER', 'WITHINPANDA', 'BISONPREFIX_dcyy', 'PYTHON']
   CreateFile(GetOutputDir()+"/include/dcParser.h")
   CreateFile(GetOutputDir()+"/include/dcParser.h")
   TargetAdd('p3dcparser_dcParser.obj', opts=OPTS, input='dcParser.yxx')
   TargetAdd('p3dcparser_dcParser.obj', opts=OPTS, input='dcParser.yxx')
   TargetAdd('dcParser.h', input='p3dcparser_dcParser.obj', opts=['DEPENDENCYONLY'])
   TargetAdd('dcParser.h', input='p3dcparser_dcParser.obj', opts=['DEPENDENCYONLY'])

+ 61 - 0
makepanda/test_wheel.py

@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+"""
+Tests a .whl file by installing it and pytest into a virtual environment and
+running the test suite.
+
+Requires pip to be installed, as well as 'virtualenv' on Python 2.
+"""
+
+import os
+import sys
+import shutil
+import subprocess
+import tempfile
+from optparse import OptionParser
+
+
+def test_wheel(wheel, verbose=False):
+    envdir = tempfile.mkdtemp(prefix="venv-")
+    print("Setting up virtual environment in {0}".format(envdir))
+
+    if sys.version_info >= (3, 0):
+        subprocess.call([sys.executable, "-m", "venv", "--clear", envdir])
+    else:
+        subprocess.call([sys.executable, "-m", "virtualenv", "--clear", envdir])
+
+    # Install pytest into the environment, as well as our wheel.
+    if sys.platform == "win32":
+        pip = os.path.join(envdir, "Scripts", "pip.exe")
+    else:
+        pip = os.path.join(envdir, "bin", "pip")
+    if subprocess.call([pip, "install", "pytest", wheel]) != 0:
+        shutil.rmtree(envdir)
+        sys.exit(1)
+
+    # Run the test suite.
+    if sys.platform == "win32":
+        python = os.path.join(envdir, "Scripts", "python.exe")
+    else:
+        python = os.path.join(envdir, "bin", "python")
+    test_cmd = [python, "-m", "pytest", "tests"]
+    if verbose:
+        test_cmd.append("--verbose")
+
+    exit_code = subprocess.call(test_cmd)
+    shutil.rmtree(envdir)
+
+    if exit_code != 0:
+        sys.exit(exit_code)
+
+
+if __name__ == "__main__":
+    parser = OptionParser(usage="%prog [options] file...")
+    parser.add_option('', '--verbose', dest = 'verbose', help = 'Enable verbose output', action = 'store_true', default = False)
+    (options, args) = parser.parse_args()
+
+    if not args:
+        parser.print_usage()
+        sys.exit(1)
+
+    for arg in args:
+        test_wheel(arg, verbose=options.verbose)

+ 1 - 0
panda/src/collide/collisionBox.cxx

@@ -16,6 +16,7 @@
 #include "collisionRay.h"
 #include "collisionRay.h"
 #include "collisionSphere.h"
 #include "collisionSphere.h"
 #include "collisionSegment.h"
 #include "collisionSegment.h"
+#include "collisionTube.h"
 #include "collisionHandler.h"
 #include "collisionHandler.h"
 #include "collisionEntry.h"
 #include "collisionEntry.h"
 #include "config_collide.h"
 #include "config_collide.h"

+ 1 - 1
panda/src/egg/eggPrimitive.cxx

@@ -558,7 +558,7 @@ remove_doubled_verts(bool closed) {
  */
  */
 void EggPrimitive::
 void EggPrimitive::
 remove_nonunique_verts() {
 remove_nonunique_verts() {
-  Vertices::iterator vi, vj;
+  Vertices::iterator vi;
   Vertices new_vertices;
   Vertices new_vertices;
   int num_removed = 0;
   int num_removed = 0;
 
 

+ 0 - 1
panda/src/egg2pg/eggLoader.cxx

@@ -2661,7 +2661,6 @@ set_occluder_polygon(EggGroup *egg_group, OccluderNode *pnode) {
     } else {
     } else {
       LMatrix4d mat = poly->get_vertex_to_node();
       LMatrix4d mat = poly->get_vertex_to_node();
 
 
-      EggPolygon::const_iterator vi;
       LPoint3d v0 = (*poly)[0]->get_pos3() * mat;
       LPoint3d v0 = (*poly)[0]->get_pos3() * mat;
       LPoint3d v1 = (*poly)[1]->get_pos3() * mat;
       LPoint3d v1 = (*poly)[1]->get_pos3() * mat;
       LPoint3d v2 = (*poly)[2]->get_pos3() * mat;
       LPoint3d v2 = (*poly)[2]->get_pos3() * mat;

+ 36 - 39
panda/src/express/datagram.I

@@ -11,30 +11,11 @@
  * @date 2000-06-06
  * @date 2000-06-06
  */
  */
 
 
-/**
- * Constructs an empty datagram.
- */
-INLINE Datagram::
-Datagram() :
-#ifdef STDFLOAT_DOUBLE
-  _stdfloat_double(true)
-#else
-  _stdfloat_double(false)
-#endif
-{
-}
-
 /**
 /**
  * Constructs a datagram from an existing block of data.
  * Constructs a datagram from an existing block of data.
  */
  */
 INLINE Datagram::
 INLINE Datagram::
-Datagram(const void *data, size_t size) :
-#ifdef STDFLOAT_DOUBLE
-  _stdfloat_double(true)
-#else
-  _stdfloat_double(false)
-#endif
-{
+Datagram(const void *data, size_t size) {
   append_data(data, size);
   append_data(data, size);
 }
 }
 
 
@@ -43,13 +24,7 @@ Datagram(const void *data, size_t size) :
  */
  */
 INLINE Datagram::
 INLINE Datagram::
 Datagram(vector_uchar data) :
 Datagram(vector_uchar data) :
-  _data(std::move(data)),
-#ifdef STDFLOAT_DOUBLE
-  _stdfloat_double(true)
-#else
-  _stdfloat_double(false)
-#endif
-{
+  _data(std::move(data)) {
 }
 }
 
 
 /**
 /**
@@ -295,6 +270,35 @@ add_fixed_string(const std::string &str, size_t size) {
   }
   }
 }
 }
 
 
+/**
+ * Adds a variable-length binary blob to the datagram.  This actually adds a
+ * count followed by n bytes.
+ */
+INLINE void Datagram::
+add_blob(const vector_uchar &data) {
+  // The max sendable size for a blob is 2^16.
+  nassertv(data.size() <= (uint16_t)0xffff);
+
+  // Blobs always are preceded by their size
+  add_uint16((uint16_t)data.size());
+
+  // Add the blob
+  append_data(data.data(), data.size());
+}
+
+/**
+ * Adds a variable-length binary blob to the datagram, using a 32-bit length
+ * field to allow very long blobs.
+ */
+INLINE void Datagram::
+add_blob32(const vector_uchar &data) {
+  // Blobs always are preceded by their size
+  add_uint32((uint32_t)data.size());
+
+  // Add the blob
+  append_data(data.data(), data.size());
+}
+
 /**
 /**
  * Appends some more raw data to the end of the datagram.
  * Appends some more raw data to the end of the datagram.
  */
  */
@@ -316,18 +320,6 @@ get_message() const {
   }
   }
 }
 }
 
 
-/**
- * Returns the datagram's data as a bytes object.
- */
-INLINE vector_uchar Datagram::
-__bytes__() const {
-  if (!_data.empty()) {
-    return vector_uchar(_data.v());
-  } else {
-    return vector_uchar();
-  }
-}
-
 /**
 /**
  * Returns a pointer to the beginning of the datagram's data.
  * Returns a pointer to the beginning of the datagram's data.
  */
  */
@@ -482,3 +474,8 @@ INLINE void
 generic_write_datagram(Datagram &dest, const std::wstring &value) {
 generic_write_datagram(Datagram &dest, const std::wstring &value) {
   dest.add_wstring(value);
   dest.add_wstring(value);
 }
 }
+
+INLINE void
+generic_write_datagram(Datagram &dest, const vector_uchar &value) {
+  dest.add_blob(value);
+}

+ 18 - 3
panda/src/express/datagram.h

@@ -37,7 +37,7 @@
  */
  */
 class EXPCL_PANDA_EXPRESS Datagram : public TypedObject {
 class EXPCL_PANDA_EXPRESS Datagram : public TypedObject {
 PUBLISHED:
 PUBLISHED:
-  INLINE Datagram();
+  INLINE Datagram() = default;
   INLINE Datagram(const void *data, size_t size);
   INLINE Datagram(const void *data, size_t size);
   INLINE explicit Datagram(vector_uchar data);
   INLINE explicit Datagram(vector_uchar data);
   Datagram(const Datagram &copy) = default;
   Datagram(const Datagram &copy) = default;
@@ -81,15 +81,23 @@ PUBLISHED:
   INLINE void add_fixed_string(const std::string &str, size_t size);
   INLINE void add_fixed_string(const std::string &str, size_t size);
   void add_wstring(const std::wstring &str);
   void add_wstring(const std::wstring &str);
 
 
+  INLINE void add_blob(const vector_uchar &);
+  INLINE void add_blob32(const vector_uchar &);
+
   void pad_bytes(size_t size);
   void pad_bytes(size_t size);
   void append_data(const void *data, size_t size);
   void append_data(const void *data, size_t size);
   INLINE void append_data(const vector_uchar &data);
   INLINE void append_data(const vector_uchar &data);
 
 
+public:
   void assign(const void *data, size_t size);
   void assign(const void *data, size_t size);
 
 
   INLINE std::string get_message() const;
   INLINE std::string get_message() const;
-  INLINE vector_uchar __bytes__() const;
   INLINE const void *get_data() const;
   INLINE const void *get_data() const;
+
+PUBLISHED:
+  EXTENSION(INLINE PyObject *get_message() const);
+  EXTENSION(INLINE PyObject *__bytes__() const);
+
   INLINE size_t get_length() const;
   INLINE size_t get_length() const;
 
 
   INLINE void set_array(PTA_uchar data);
   INLINE void set_array(PTA_uchar data);
@@ -109,7 +117,12 @@ PUBLISHED:
 
 
 private:
 private:
   PTA_uchar _data;
   PTA_uchar _data;
-  bool _stdfloat_double;
+
+#ifdef STDFLOAT_DOUBLE
+  bool _stdfloat_double = true;
+#else
+  bool _stdfloat_double = false;
+#endif
 
 
 public:
 public:
 
 
@@ -148,6 +161,8 @@ INLINE void
 generic_write_datagram(Datagram &dest, const std::string &value);
 generic_write_datagram(Datagram &dest, const std::string &value);
 INLINE void
 INLINE void
 generic_write_datagram(Datagram &dest, const std::wstring &value);
 generic_write_datagram(Datagram &dest, const std::wstring &value);
+INLINE void
+generic_write_datagram(Datagram &dest, const vector_uchar &value);
 
 
 
 
 #include "datagram.I"
 #include "datagram.I"

+ 21 - 0
panda/src/express/datagramIterator.I

@@ -400,6 +400,22 @@ get_be_float64() {
   return tempvar;
   return tempvar;
 }
 }
 
 
+/**
+ * Extracts a variable-length binary blob.
+ */
+INLINE vector_uchar DatagramIterator::
+get_blob() {
+  return extract_bytes(get_uint16());
+}
+
+/**
+ * Extracts a variable-length binary blob with a 32-bit size field.
+ */
+INLINE vector_uchar DatagramIterator::
+get_blob32() {
+  return extract_bytes(get_uint32());
+}
+
 /**
 /**
  * Skips over the indicated number of bytes in the datagram.
  * Skips over the indicated number of bytes in the datagram.
  */
  */
@@ -485,3 +501,8 @@ INLINE void
 generic_read_datagram(std::wstring &result, DatagramIterator &source) {
 generic_read_datagram(std::wstring &result, DatagramIterator &source) {
   result = source.get_wstring();
   result = source.get_wstring();
 }
 }
+
+INLINE void
+generic_read_datagram(vector_uchar &result, DatagramIterator &source) {
+  result = source.get_blob();
+}

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

@@ -61,6 +61,9 @@ PUBLISHED:
   std::string get_fixed_string(size_t size);
   std::string get_fixed_string(size_t size);
   std::wstring get_wstring();
   std::wstring get_wstring();
 
 
+  INLINE vector_uchar get_blob();
+  INLINE vector_uchar get_blob32();
+
   INLINE void skip_bytes(size_t size);
   INLINE void skip_bytes(size_t size);
   vector_uchar extract_bytes(size_t size);
   vector_uchar extract_bytes(size_t size);
   size_t extract_bytes(unsigned char *into, size_t size);
   size_t extract_bytes(unsigned char *into, size_t size);

+ 35 - 0
panda/src/express/datagram_ext.I

@@ -0,0 +1,35 @@
+/**
+ * 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 datagram_ext.I
+ * @author rdb
+ * @date 2018-08-19
+ */
+
+/**
+ * Returns the datagram's data as a bytes object.
+ */
+INLINE PyObject *Extension<Datagram>::
+get_message() const {
+  const char *data = (const char *)_this->get_data();
+  size_t size = _this->get_length();
+
+#if PY_MAJOR_VERSION >= 3
+  return PyBytes_FromStringAndSize((char *)data, size);
+#else
+  return PyString_FromStringAndSize((char *)data, size);
+#endif
+}
+
+/**
+ * Returns the datagram's data as a bytes object.
+ */
+PyObject *Extension<Datagram>::
+__bytes__() const {
+  return get_message();
+}

+ 40 - 0
panda/src/express/datagram_ext.h

@@ -0,0 +1,40 @@
+/**
+ * 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 datagram_ext.h
+ * @author rdb
+ * @date 2018-08-19
+ */
+
+#ifndef DATAGRAM_EXT_H
+#define DATAGRAM_EXT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+#include "extension.h"
+#include "datagram.h"
+#include "py_panda.h"
+
+/**
+ * This class defines the extension methods for Datagram, which are called
+ * instead of any C++ methods with the same prototype.
+ */
+template<>
+class Extension<Datagram> : public ExtensionBase<Datagram> {
+public:
+  INLINE PyObject *get_message() const;
+  INLINE PyObject *__bytes__() const;
+};
+
+#include "datagram_ext.I"
+
+#endif  // HAVE_PYTHON
+
+#endif  // DATAGRAM_EXT_H

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

@@ -24,7 +24,7 @@
 /**
 /**
  * The streambuf object that implements IDecompressStream and OCompressStream.
  * The streambuf object that implements IDecompressStream and OCompressStream.
  */
  */
-class EXPCL_PANDA_DOWNLOADER ZStreamBuf : public std::streambuf {
+class EXPCL_PANDA_EXPRESS ZStreamBuf : public std::streambuf {
 public:
 public:
   ZStreamBuf();
   ZStreamBuf();
   virtual ~ZStreamBuf();
   virtual ~ZStreamBuf();

+ 42 - 0
panda/src/linmath/lmatrix3_src.I

@@ -44,6 +44,14 @@ size() {
   return 3;
   return 3;
 }
 }
 
 
+/**
+ *
+ */
+INLINE_LINMATH FLOATNAME(LMatrix3)::Row::
+operator const FLOATNAME(LVecBase3) &() const {
+  return *(const FLOATNAME(LVecBase3) *)_row;
+}
+
 /**
 /**
  * Defines a row-level constant accessor to the matrix.
  * Defines a row-level constant accessor to the matrix.
  */
  */
@@ -68,6 +76,14 @@ size() {
   return 3;
   return 3;
 }
 }
 
 
+/**
+ *
+ */
+INLINE_LINMATH FLOATNAME(LMatrix3)::CRow::
+operator const FLOATNAME(LVecBase3) &() const {
+  return *(const FLOATNAME(LVecBase3) *)_row;
+}
+
 /**
 /**
  * Returns an identity matrix.
  * Returns an identity matrix.
  *
  *
@@ -132,6 +148,32 @@ FLOATNAME(LMatrix3)(FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02,
   _m(2, 2) = e22;
   _m(2, 2) = e22;
 }
 }
 
 
+/**
+ * Constructs the matrix from three individual rows.
+ */
+INLINE_LINMATH FLOATNAME(LMatrix3)::
+FLOATNAME(LMatrix3)(const FLOATNAME(LVecBase3) &row0,
+                    const FLOATNAME(LVecBase3) &row1,
+                    const FLOATNAME(LVecBase3) &row2) {
+  TAU_PROFILE("LMatrix3::LMatrix3(const LVecBase3 &, ...)", " ", TAU_USER);
+
+#ifdef HAVE_EIGEN
+  _m.row(0) = row0._v;
+  _m.row(1) = row1._v;
+  _m.row(2) = row2._v;
+#else
+  _m(0, 0) = row0._v(0);
+  _m(0, 1) = row0._v(1);
+  _m(0, 2) = row0._v(2);
+  _m(1, 0) = row1._v(0);
+  _m(1, 1) = row1._v(1);
+  _m(1, 2) = row1._v(2);
+  _m(2, 0) = row2._v(0);
+  _m(2, 1) = row2._v(1);
+  _m(2, 2) = row2._v(2);
+#endif  // HAVE_EIGEN
+}
+
 /**
 /**
  *
  *
  */
  */

+ 8 - 4
panda/src/linmath/lmatrix3_src.h

@@ -38,6 +38,7 @@ PUBLISHED:
     INLINE_LINMATH FLOATTYPE operator [](int i) const;
     INLINE_LINMATH FLOATTYPE operator [](int i) const;
     INLINE_LINMATH FLOATTYPE &operator [](int i);
     INLINE_LINMATH FLOATTYPE &operator [](int i);
     INLINE_LINMATH static int size();
     INLINE_LINMATH static int size();
+    INLINE_LINMATH operator const FLOATNAME(LVecBase3) &() const;
   public:
   public:
     FLOATTYPE *_row;
     FLOATTYPE *_row;
     friend class FLOATNAME(LMatrix3);
     friend class FLOATNAME(LMatrix3);
@@ -48,6 +49,7 @@ PUBLISHED:
   PUBLISHED:
   PUBLISHED:
     INLINE_LINMATH FLOATTYPE operator [](int i) const;
     INLINE_LINMATH FLOATTYPE operator [](int i) const;
     INLINE_LINMATH static int size();
     INLINE_LINMATH static int size();
+    INLINE_LINMATH operator const FLOATNAME(LVecBase3) &() const;
   public:
   public:
     const FLOATTYPE *_row;
     const FLOATTYPE *_row;
     friend class FLOATNAME(LMatrix3);
     friend class FLOATNAME(LMatrix3);
@@ -58,10 +60,12 @@ PUBLISHED:
   INLINE_LINMATH FLOATNAME(LMatrix3) &operator = (
   INLINE_LINMATH FLOATNAME(LMatrix3) &operator = (
       const FLOATNAME(LMatrix3) &other);
       const FLOATNAME(LMatrix3) &other);
   INLINE_LINMATH FLOATNAME(LMatrix3) &operator = (FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LMatrix3) &operator = (FLOATTYPE fill_value);
-  INLINE_LINMATH FLOATNAME(LMatrix3)(
-    FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02,
-    FLOATTYPE e10, FLOATTYPE e11, FLOATTYPE e12,
-    FLOATTYPE e20, FLOATTYPE e21, FLOATTYPE e22);
+  INLINE_LINMATH FLOATNAME(LMatrix3)(FLOATTYPE, FLOATTYPE, FLOATTYPE,
+                                     FLOATTYPE, FLOATTYPE, FLOATTYPE,
+                                     FLOATTYPE, FLOATTYPE, FLOATTYPE);
+  INLINE_LINMATH FLOATNAME(LMatrix3)(const FLOATNAME(LVecBase3) &,
+                                     const FLOATNAME(LVecBase3) &,
+                                     const FLOATNAME(LVecBase3) &);
   ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix3));
   ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix3));
 
 
   EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const);
   EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const);

+ 51 - 0
panda/src/linmath/lmatrix4_src.I

@@ -44,6 +44,14 @@ size() {
   return 4;
   return 4;
 }
 }
 
 
+/**
+ *
+ */
+INLINE_LINMATH FLOATNAME(LMatrix4)::Row::
+operator const FLOATNAME(LVecBase4) &() const {
+  return *(const FLOATNAME(LVecBase4) *)_row;
+}
+
 /**
 /**
  * Defines a row-level constant accessor to the matrix.
  * Defines a row-level constant accessor to the matrix.
  */
  */
@@ -68,6 +76,14 @@ size() {
   return 4;
   return 4;
 }
 }
 
 
+/**
+ *
+ */
+INLINE_LINMATH FLOATNAME(LMatrix4)::CRow::
+operator const FLOATNAME(LVecBase4) &() const {
+  return *(const FLOATNAME(LVecBase4) *)_row;
+}
+
 /**
 /**
  * Returns an identity matrix.
  * Returns an identity matrix.
  *
  *
@@ -178,6 +194,41 @@ FLOATNAME(LMatrix4)(FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02, FLOATTYPE e03,
   _m(3, 3) = e33;
   _m(3, 3) = e33;
 }
 }
 
 
+/**
+ * Constructs the matrix from four individual rows.
+ */
+INLINE_LINMATH FLOATNAME(LMatrix4)::
+FLOATNAME(LMatrix4)(const FLOATNAME(LVecBase4) &row0,
+                    const FLOATNAME(LVecBase4) &row1,
+                    const FLOATNAME(LVecBase4) &row2,
+                    const FLOATNAME(LVecBase4) &row3) {
+  TAU_PROFILE("LMatrix4::LMatrix4(const LVecBase4 &, ...)", " ", TAU_USER);
+
+#ifdef HAVE_EIGEN
+  _m.row(0) = row0._v;
+  _m.row(1) = row1._v;
+  _m.row(2) = row2._v;
+  _m.row(3) = row3._v;
+#else
+  _m(0, 0) = row0._v(0);
+  _m(0, 1) = row0._v(1);
+  _m(0, 2) = row0._v(2);
+  _m(0, 3) = row0._v(3);
+  _m(1, 0) = row1._v(0);
+  _m(1, 1) = row1._v(1);
+  _m(1, 2) = row1._v(2);
+  _m(1, 3) = row1._v(3);
+  _m(2, 0) = row2._v(0);
+  _m(2, 1) = row2._v(1);
+  _m(2, 2) = row2._v(2);
+  _m(2, 3) = row2._v(3);
+  _m(3, 0) = row3._v(0);
+  _m(3, 1) = row3._v(1);
+  _m(3, 2) = row3._v(2);
+  _m(3, 3) = row3._v(3);
+#endif  // HAVE_EIGEN
+}
+
 /**
 /**
  *
  *
  */
  */

+ 10 - 4
panda/src/linmath/lmatrix4_src.h

@@ -36,6 +36,7 @@ PUBLISHED:
     INLINE_LINMATH FLOATTYPE operator [](int i) const;
     INLINE_LINMATH FLOATTYPE operator [](int i) const;
     INLINE_LINMATH FLOATTYPE &operator [](int i);
     INLINE_LINMATH FLOATTYPE &operator [](int i);
     INLINE_LINMATH static int size();
     INLINE_LINMATH static int size();
+    INLINE_LINMATH operator const FLOATNAME(LVecBase4) &() const;
   public:
   public:
     FLOATTYPE *_row;
     FLOATTYPE *_row;
     friend class FLOATNAME(LMatrix4);
     friend class FLOATNAME(LMatrix4);
@@ -46,6 +47,7 @@ PUBLISHED:
   PUBLISHED:
   PUBLISHED:
     INLINE_LINMATH FLOATTYPE operator [](int i) const;
     INLINE_LINMATH FLOATTYPE operator [](int i) const;
     INLINE_LINMATH static int size();
     INLINE_LINMATH static int size();
+    INLINE_LINMATH operator const FLOATNAME(LVecBase4) &() const;
   public:
   public:
     const FLOATTYPE *_row;
     const FLOATTYPE *_row;
     friend class FLOATNAME(LMatrix4);
     friend class FLOATNAME(LMatrix4);
@@ -60,10 +62,14 @@ PUBLISHED:
       const FLOATNAME(UnalignedLMatrix4) &other);
       const FLOATNAME(UnalignedLMatrix4) &other);
   INLINE_LINMATH FLOATNAME(LMatrix4) &operator = (FLOATTYPE fill_value);
   INLINE_LINMATH FLOATNAME(LMatrix4) &operator = (FLOATTYPE fill_value);
 
 
-  INLINE_LINMATH FLOATNAME(LMatrix4)(FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02, FLOATTYPE e03,
-                                     FLOATTYPE e10, FLOATTYPE e11, FLOATTYPE e12, FLOATTYPE e13,
-                                     FLOATTYPE e20, FLOATTYPE e21, FLOATTYPE e22, FLOATTYPE e23,
-                                     FLOATTYPE e30, FLOATTYPE e31, FLOATTYPE e32, FLOATTYPE e33);
+  INLINE_LINMATH FLOATNAME(LMatrix4)(FLOATTYPE, FLOATTYPE, FLOATTYPE, FLOATTYPE,
+                                     FLOATTYPE, FLOATTYPE, FLOATTYPE, FLOATTYPE,
+                                     FLOATTYPE, FLOATTYPE, FLOATTYPE, FLOATTYPE,
+                                     FLOATTYPE, FLOATTYPE, FLOATTYPE, FLOATTYPE);
+  INLINE_LINMATH FLOATNAME(LMatrix4)(const FLOATNAME(LVecBase4) &,
+                                     const FLOATNAME(LVecBase4) &,
+                                     const FLOATNAME(LVecBase4) &,
+                                     const FLOATNAME(LVecBase4) &);
   ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix4));
   ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix4));
 
 
   EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const);
   EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const);

+ 0 - 1
panda/src/pgraph/geomNode.cxx

@@ -115,7 +115,6 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
   Thread *current_thread = Thread::get_current_thread();
   Thread *current_thread = Thread::get_current_thread();
   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
   OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
     CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
-    GeomList::iterator gi;
     PT(GeomList) geoms = cdata->modify_geoms();
     PT(GeomList) geoms = cdata->modify_geoms();
 
 
     // Iterate based on the number of geoms, not using STL iterators.  This
     // Iterate based on the number of geoms, not using STL iterators.  This

+ 0 - 1
panda/src/pgraph/geomTransformer.cxx

@@ -742,7 +742,6 @@ make_compatible_state(GeomNode *node) {
   }
   }
 
 
   GeomNode::CDWriter cdata(node->_cycler);
   GeomNode::CDWriter cdata(node->_cycler);
-  GeomNode::GeomList::iterator gi;
   PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
   PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
 
 
   // For each geom, calculate a canonicalized RenderState, and classify all
   // For each geom, calculate a canonicalized RenderState, and classify all

+ 1 - 4
panda/src/recorder/socketStreamRecorder.cxx

@@ -82,10 +82,7 @@ play_frame(DatagramIterator &scan, BamReader *manager) {
 
 
   int num_packets = scan.get_uint16();
   int num_packets = scan.get_uint16();
   for (int i = 0; i < num_packets; i++) {
   for (int i = 0; i < num_packets; i++) {
-    size_t size = scan.get_uint16();
-    vector_uchar packet(size);
-    scan.extract_bytes(&packet[0], size);
-    _data.push_back(Datagram(std::move(packet)));
+    _data.push_back(Datagram(scan.get_blob()));
   }
   }
 }
 }
 
 

+ 0 - 1
panda/src/text/dynamicTextFont.cxx

@@ -1072,7 +1072,6 @@ render_polygon_contours(TextGlyph *glyph, bool face, bool extrude) {
     // create more vertices--they don't share the same normals.
     // create more vertices--they don't share the same normals.
     for (ci = _contours.begin(); ci != _contours.end(); ++ci) {
     for (ci = _contours.begin(); ci != _contours.end(); ++ci) {
       const Contour &contour = (*ci);
       const Contour &contour = (*ci);
-      Points::const_iterator pi;
 
 
       for (size_t i = 0; i < contour._points.size(); ++i) {
       for (size_t i = 0; i < contour._points.size(); ++i) {
         const ContourPoint &cp = contour._points[i];
         const ContourPoint &cp = contour._points[i];

+ 9 - 9
pandatool/src/mayaegg/mayaEggLoader.cxx

@@ -837,12 +837,12 @@ int MayaEggGeom::GetVert(EggVertex *vert, EggGroup *context)
 void MayaEggGeom::AssignNames(void)
 void MayaEggGeom::AssignNames(void)
 {
 {
   string name = _pool->get_name();
   string name = _pool->get_name();
-  int nsize = name.size();
-  if ((nsize > 6) && (name.rfind(".verts")==(nsize-6))) {
-    name.resize(nsize-6);
+  size_t nsize = name.size();
+  if (nsize > 6 && name.rfind(".verts") == (nsize - 6)) {
+    name.resize(nsize - 6);
   }
   }
-  if ((nsize > 4) && (name.rfind(".cvs")==(nsize-4))) {
-    name.resize(nsize-4);
+  if (nsize > 4 && name.rfind(".cvs") == (nsize - 4)) {
+    name.resize(nsize - 4);
   }
   }
 
 
   MFnDependencyNode dnshape(_shapeNode);
   MFnDependencyNode dnshape(_shapeNode);
@@ -913,7 +913,7 @@ void MayaEggGeom::AddEggFlag(MString fieldName) {
 typedef phash_map<LTexCoordd, int>             TVertTable;
 typedef phash_map<LTexCoordd, int>             TVertTable;
 typedef phash_map<LColor, int>                CVertTable;
 typedef phash_map<LColor, int>                CVertTable;
 
 
-class MayaEggMesh : public MayaEggGeom
+class MayaEggMesh final : public MayaEggGeom
 {
 {
 public:
 public:
   MColorArray         _faceColorArray;
   MColorArray         _faceColorArray;
@@ -937,7 +937,7 @@ public:
   int GetCVert(const LColor &col);
   int GetCVert(const LColor &col);
   int AddFace(unsigned numVertices, MIntArray mvertIndices, MIntArray mtvertIndices, MayaEggTex *tex);
   int AddFace(unsigned numVertices, MIntArray mvertIndices, MIntArray mtvertIndices, MayaEggTex *tex);
 
 
-  void ConnectTextures(void);
+  void ConnectTextures(void) override;
 };
 };
 
 
 int MayaEggMesh::GetTVert(const LTexCoordd &uv)
 int MayaEggMesh::GetTVert(const LTexCoordd &uv)
@@ -2012,7 +2012,7 @@ void MayaEggLoader::PrintData(MayaEggMesh *mesh)
 
 
 void MayaEggLoader::ParseFrameInfo(string comment)
 void MayaEggLoader::ParseFrameInfo(string comment)
 {
 {
-  int pos, ls, le;
+  size_t pos, ls, le;
 
 
   pos = comment.find("-fri");
   pos = comment.find("-fri");
   if (pos != string::npos) {
   if (pos != string::npos) {
@@ -2143,7 +2143,7 @@ bool MayaEggLoader::ConvertEggFile(const char *name, bool merge, bool model, boo
 MObject MayaEggLoader::GetDependencyNode(string givenName)
 MObject MayaEggLoader::GetDependencyNode(string givenName)
 {
 {
   MObject node = MObject::kNullObj;
   MObject node = MObject::kNullObj;
-  int pos;
+  size_t pos;
   string name;
   string name;
 
 
   pos = givenName.find(":");
   pos = givenName.find(":");

+ 2 - 2
pandatool/src/mayaegg/mayaToEggConverter.cxx

@@ -2742,7 +2742,7 @@ set_shader_legacy(EggPrimitive &primitive, const MayaShader &shader,
           // shader on the list is the base one, which should always pick up
           // shader on the list is the base one, which should always pick up
           // the alpha from the texture file.  But the top textures may have
           // the alpha from the texture file.  But the top textures may have
           // to strip the alpha
           // to strip the alpha
-          if (i!=shader._color.size()-1) {
+          if ((size_t)i != shader._color.size() - 1) {
             if (!i && is_interpolate) {
             if (!i && is_interpolate) {
               // this is the grass path mode where alpha on this texture
               // this is the grass path mode where alpha on this texture
               // determines whether to show layer1 or layer2. Since by now
               // determines whether to show layer1 or layer2. Since by now
@@ -2846,7 +2846,7 @@ set_shader_legacy(EggPrimitive &primitive, const MayaShader &shader,
         _textures.create_unique_texture(tex, ~0);
         _textures.create_unique_texture(tex, ~0);
 
 
       if (mesh) {
       if (mesh) {
-        if (uvset_name.find("not found") == -1) {
+        if (uvset_name.find("not found") == string::npos) {
           primitive.add_texture(new_tex);
           primitive.add_texture(new_tex);
           color_def->_uvset_name.assign(uvset_name.c_str());
           color_def->_uvset_name.assign(uvset_name.c_str());
           if (uvset_name != "map1") {
           if (uvset_name != "map1") {

+ 3 - 2
tests/egg2pg/test_egg_coordsys.py

@@ -37,7 +37,8 @@ def test_egg2pg_transform_ident(egg_coordsys, coordsys):
 @pytest.mark.parametrize("coordsys", COORD_SYSTEMS)
 @pytest.mark.parametrize("coordsys", COORD_SYSTEMS)
 def test_egg2pg_transform_mat_unchanged(coordsys):
 def test_egg2pg_transform_mat_unchanged(coordsys):
     # Ensures that the matrix remains unchanged if coordinate system is same.
     # Ensures that the matrix remains unchanged if coordinate system is same.
-    mat = (5, 2, -3, 4, 5, 6, 7, 8, 9, 1, -3, 2, 5, 2, 5, 2)
+    matv = (5, 2, -3, 4, 5, 6, 7, 8, 9, 1, -3, 2, 5, 2, 5, 2)
+    mat = core.Mat4D(*matv)
     group = egg.EggGroup("group")
     group = egg.EggGroup("group")
     group.add_matrix4(mat)
     group.add_matrix4(mat)
     assert not group.transform_is_identity()
     assert not group.transform_is_identity()
@@ -57,7 +58,7 @@ def test_egg2pg_transform_mat_unchanged(coordsys):
     assert root
     assert root
     node, = root.children
     node, = root.children
 
 
-    assert node.transform.mat == mat
+    assert node.transform.mat == core.Mat4(*matv)
 
 
 
 
 @pytest.mark.parametrize("egg_coordsys", COORD_SYSTEMS)
 @pytest.mark.parametrize("egg_coordsys", COORD_SYSTEMS)

+ 12 - 6
tests/gobj/test_texture_pool.py

@@ -22,8 +22,10 @@ def image_rgb_path():
     "Generates an RGB image."
     "Generates an RGB image."
 
 
     file = tempfile.NamedTemporaryFile(suffix='-rgb.png')
     file = tempfile.NamedTemporaryFile(suffix='-rgb.png')
-    write_image(file.name, 3)
-    yield file.name
+    path = core.Filename.from_os_specific(file.name)
+    path.make_true_case()
+    write_image(path, 3)
+    yield path
     file.close()
     file.close()
 
 
 
 
@@ -32,8 +34,10 @@ def image_rgba_path():
     "Generates an RGBA image."
     "Generates an RGBA image."
 
 
     file = tempfile.NamedTemporaryFile(suffix='-rgba.png')
     file = tempfile.NamedTemporaryFile(suffix='-rgba.png')
-    write_image(file.name, 4)
-    yield file.name
+    path = core.Filename.from_os_specific(file.name)
+    path.make_true_case()
+    write_image(path, 4)
+    yield path
     file.close()
     file.close()
 
 
 
 
@@ -42,8 +46,10 @@ def image_gray_path():
     "Generates a grayscale image."
     "Generates a grayscale image."
 
 
     file = tempfile.NamedTemporaryFile(suffix='-gray.png')
     file = tempfile.NamedTemporaryFile(suffix='-gray.png')
-    write_image(file.name, 1)
-    yield file.name
+    path = core.Filename.from_os_specific(file.name)
+    path.make_true_case()
+    write_image(path, 1)
+    yield path
     file.close()
     file.close()
 
 
 
 

+ 62 - 0
tests/linmath/test_lmatrix3.py

@@ -0,0 +1,62 @@
+import pytest
+from copy import copy
+from panda3d import core
+
+
+def test_mat3_aliases():
+    assert core.LMatrix3 is core.Mat3
+    assert core.LMatrix3f is core.Mat3F
+    assert core.LMatrix3d is core.Mat3D
+
+    assert (core.LMatrix3f is core.Mat3) != (core.LMatrix3d is core.Mat3)
+
+
[email protected]("type", (core.LMatrix3f, core.LMatrix3d))
+def test_mat3_constructor(type):
+    # Test that three ways of construction produce the same matrix.
+    mat1 = type((1, 2, 3),
+                (4, 5, 6),
+                (7, 8, 9))
+
+    mat2 = type(1, 2, 3, 4, 5, 6, 7, 8, 9)
+
+    mat3 = type((1, 2, 3, 4, 5, 6, 7, 8, 9))
+
+    assert mat1 == mat2
+    assert mat2 == mat3
+    assert mat1 == mat3
+
+
[email protected]("type", (core.LMatrix3d, core.LMatrix3f))
+def test_mat3_copy_constuctor(type):
+    mat1 = type((1, 2, 3),
+                (4, 5, 6),
+                (7, 8, 9))
+
+    # Make a copy.  Changing it should not change the original.
+    mat2 = type(mat1)
+    assert mat1 == mat2
+    mat2[0][0] = 100
+    assert mat1 != mat2
+
+    # Make a copy by unpacking.
+    mat2 = type(*mat1)
+    assert mat1 == mat2
+    mat2[0][0] = 100
+    assert mat1 != mat2
+
+    # Make a copy by calling copy.copy.
+    mat2 = copy(mat1)
+    assert mat1 == mat2
+    mat2[0][0] = 100
+    assert mat1 != mat2
+
+
[email protected]("type", (core.LMatrix3d, core.LMatrix3f))
+def test_mat3_invert_same_type(type):
+    mat = type((1, 0, 0,
+                0, 1, 0,
+                1, 2, 3))
+
+    inv = core.invert(mat)
+    assert mat.__class__ == inv.__class__

+ 89 - 0
tests/linmath/test_lmatrix4.py

@@ -0,0 +1,89 @@
+import pytest
+from copy import copy
+from panda3d import core
+
+
+def test_mat4_aliases():
+    assert core.LMatrix4 is core.Mat4
+    assert core.LMatrix4f is core.Mat4F
+    assert core.LMatrix4d is core.Mat4D
+
+    assert (core.LMatrix4f is core.Mat4) != (core.LMatrix4d is core.Mat4)
+
+
[email protected]("type", (core.LMatrix4d, core.LMatrix4f))
+def test_mat4_constructor(type):
+    # Test that three ways of construction produce the same matrix.
+    mat1 = type((1, 2, 3, 4),
+                (5, 6, 7, 8),
+                (9, 10, 11, 12),
+                (13, 14, 15, 16))
+
+    mat2 = type(1, 2, 3, 4,
+                5, 6, 7, 8,
+                9, 10, 11, 12,
+                13, 14, 15, 16)
+
+    mat3 = type((1, 2, 3, 4,
+                 5, 6, 7, 8,
+                 9, 10, 11, 12,
+                 13, 14, 15, 16))
+
+    assert mat1 == mat2
+    assert mat2 == mat3
+    assert mat1 == mat3
+
+
[email protected]("type", (core.LMatrix4d, core.LMatrix4f))
+def test_mat4_copy_constuctor(type):
+    mat1 = type((1, 2, 3, 4),
+                (5, 6, 7, 8),
+                (9, 10, 11, 12),
+                (13, 14, 15, 16))
+
+    # Make a copy.  Changing it should not change the original.
+    mat2 = type(mat1)
+    assert mat1 == mat2
+    mat2[0][0] = 100
+    assert mat1 != mat2
+
+    # Make a copy by unpacking.
+    mat2 = type(*mat1)
+    assert mat1 == mat2
+    mat2[0][0] = 100
+    assert mat1 != mat2
+
+    # Make a copy by calling copy.copy.
+    mat2 = copy(mat1)
+    assert mat1 == mat2
+    mat2[0][0] = 100
+    assert mat1 != mat2
+
+
[email protected]("type", (core.LMatrix4d, core.LMatrix4f))
+def test_mat4_invert_same_type(type):
+    mat = type((1, 0, 0, 0,
+                0, 1, 0, 0,
+                0, 0, 1, 0,
+                1, 2, 3, 1))
+
+    inv = core.invert(mat)
+    assert mat.__class__ == inv.__class__
+
+
[email protected]("type", (core.LMatrix4d, core.LMatrix4f))
+def test_mat4_invert_correct(type):
+    mat = type((1, 0, 0, 0,
+                0, 1, 0, 0,
+                0, 0, 1, 0,
+                1, 2, 3, 1))
+    inv = type()
+    assert inv.invert_from(mat)
+
+    assert inv == type(( 1,  0,  0, 0,
+                         0,  1,  0, 0,
+                         0,  0,  1, 0,
+                        -1, -2, -3, 1))
+
+    assert (mat * inv).is_identity()
+    assert (inv * mat).is_identity()

+ 0 - 20
tests/linmath/test_matrix_invert.py

@@ -1,20 +0,0 @@
-import pytest
-from panda3d import core
-
-
[email protected]("type", (core.Mat4, core.Mat4D))
-def test_mat4_invert(type):
-    mat = type((1, 0, 0, 0,
-                0, 1, 0, 0,
-                0, 0, 1, 0,
-                1, 2, 3, 1))
-    inv = type()
-    assert inv.invert_from(mat)
-
-    assert inv == type(( 1,  0,  0, 0,
-                         0,  1,  0, 0,
-                         0,  0,  1, 0,
-                        -1, -2, -3, 1))
-
-    assert (mat * inv).is_identity()
-    assert (inv * mat).is_identity()

+ 35 - 14
tests/putil/test_datagram.py

@@ -1,6 +1,7 @@
 import pytest
 import pytest
 from panda3d import core
 from panda3d import core
 import sys
 import sys
+import tempfile
 
 
 # Fixtures for generating interesting datagrams (and verification functions) on
 # Fixtures for generating interesting datagrams (and verification functions) on
 # the fly...
 # the fly...
@@ -28,6 +29,9 @@ def datagram_small(request):
     dg.add_string32('this is another string')
     dg.add_string32('this is another string')
     dg.add_string('this is yet a third string')
     dg.add_string('this is yet a third string')
 
 
+    dg.add_blob(b'blob data \x00\xf2\xa0\x00\x00')
+    dg.add_blob32(b'\xc9\x8f\x00 test blob32')
+
     dg.add_stdfloat(800.2)
     dg.add_stdfloat(800.2)
     dg.add_stdfloat(3.1415926)
     dg.add_stdfloat(3.1415926)
     dg.add_stdfloat(2.7182818)
     dg.add_stdfloat(2.7182818)
@@ -49,6 +53,9 @@ def datagram_small(request):
         assert dgi.get_string32() == 'this is another string'
         assert dgi.get_string32() == 'this is another string'
         assert dgi.get_string() == 'this is yet a third string'
         assert dgi.get_string() == 'this is yet a third string'
 
 
+        assert dgi.get_blob() == b'blob data \x00\xf2\xa0\x00\x00'
+        assert dgi.get_blob32() == b'\xc9\x8f\x00 test blob32'
+
         assert dgi.get_stdfloat() == pytest.approx(800.2)
         assert dgi.get_stdfloat() == pytest.approx(800.2)
         assert dgi.get_stdfloat() == pytest.approx(3.1415926)
         assert dgi.get_stdfloat() == pytest.approx(3.1415926)
         assert dgi.get_stdfloat() == pytest.approx(2.7182818)
         assert dgi.get_stdfloat() == pytest.approx(2.7182818)
@@ -88,6 +95,12 @@ def test_datagram_bytes():
     dgi.get_remaining_bytes() == b'abc\x00\xff123'
     dgi.get_remaining_bytes() == b'abc\x00\xff123'
 
 
 
 
+def test_datagram_get_message():
+    dg = core.Datagram(b'abc\x00')
+    dg.append_data(b'\xff123')
+    assert dg.get_message() == b'abc\x00\xff123'
+
+
 def test_iterator(datagram_small):
 def test_iterator(datagram_small):
     """This tests Datagram/DatagramIterator, and sort of serves as a self-check
     """This tests Datagram/DatagramIterator, and sort of serves as a self-check
     of the test fixtures too."""
     of the test fixtures too."""
@@ -135,30 +148,39 @@ def do_file_test(dg, verify, filename):
     dgi = core.DatagramIterator(dg2)
     dgi = core.DatagramIterator(dg2)
     verify(dgi)
     verify(dgi)
 
 
-def test_file_small(datagram_small, tmpdir):
[email protected]
+def tmpfile():
+    file = tempfile.NamedTemporaryFile(suffix='.bin')
+    yield file
+    file.close()
+
+def test_file_small(datagram_small, tmpfile):
     """This tests DatagramOutputFile/DatagramInputFile on small datagrams."""
     """This tests DatagramOutputFile/DatagramInputFile on small datagrams."""
     dg, verify = datagram_small
     dg, verify = datagram_small
 
 
-    p = tmpdir.join('datagram.bin')
-    filename = core.Filename.from_os_specific(str(p))
+    file = tempfile.NamedTemporaryFile(suffix='.bin')
+    filename = core.Filename.from_os_specific(file.name)
+    filename.make_true_case()
 
 
     do_file_test(dg, verify, filename)
     do_file_test(dg, verify, filename)
 
 
-def test_file_large(datagram_large, tmpdir):
+def test_file_large(datagram_large, tmpfile):
     """This tests DatagramOutputFile/DatagramInputFile on very large datagrams."""
     """This tests DatagramOutputFile/DatagramInputFile on very large datagrams."""
     dg, verify = datagram_large
     dg, verify = datagram_large
 
 
-    p = tmpdir.join('datagram.bin')
-    filename = core.Filename.from_os_specific(str(p))
+    file = tempfile.NamedTemporaryFile(suffix='.bin')
+    filename = core.Filename.from_os_specific(file.name)
+    filename.make_true_case()
 
 
     do_file_test(dg, verify, filename)
     do_file_test(dg, verify, filename)
 
 
-def test_file_corrupt(datagram_small, tmpdir):
+def test_file_corrupt(datagram_small, tmpfile):
     """This tests DatagramInputFile's handling of a corrupt size header."""
     """This tests DatagramInputFile's handling of a corrupt size header."""
     dg, verify = datagram_small
     dg, verify = datagram_small
 
 
-    p = tmpdir.join('datagram.bin')
-    filename = core.Filename.from_os_specific(str(p))
+    file = tempfile.NamedTemporaryFile(suffix='.bin')
+    filename = core.Filename.from_os_specific(file.name)
+    filename.make_true_case()
 
 
     dof = core.DatagramOutputFile()
     dof = core.DatagramOutputFile()
     dof.open(filename)
     dof.open(filename)
@@ -166,9 +188,9 @@ def test_file_corrupt(datagram_small, tmpdir):
     dof.close()
     dof.close()
 
 
     # Corrupt the size header to 1GB
     # Corrupt the size header to 1GB
-    with p.open(mode='r+b') as f:
-        f.seek(0)
-        f.write(b'\xFF\xFF\xFF\x4F')
+    file.seek(0)
+    file.write(b'\xFF\xFF\xFF\x4F')
+    file.flush()
 
 
     dg2 = core.Datagram()
     dg2 = core.Datagram()
     dif = core.DatagramInputFile()
     dif = core.DatagramInputFile()
@@ -178,8 +200,7 @@ def test_file_corrupt(datagram_small, tmpdir):
 
 
     # Truncate the file
     # Truncate the file
     for size in [12, 8, 4, 3, 2, 1, 0]:
     for size in [12, 8, 4, 3, 2, 1, 0]:
-        with p.open(mode='r+b') as f:
-            f.truncate(size)
+        file.truncate(size)
 
 
         dg2 = core.Datagram()
         dg2 = core.Datagram()
         dif = core.DatagramInputFile()
         dif = core.DatagramInputFile()