Browse Source

Interrogate improvements, more properties, MAKE_SEQ_PROPERTY

rdb 9 years ago
parent
commit
ce29ae490d
98 changed files with 1675 additions and 695 deletions
  1. 478 467
      dtool/src/cppparser/cppBison.cxx.prebuilt
  2. 88 84
      dtool/src/cppparser/cppBison.h.prebuilt
  3. 118 0
      dtool/src/cppparser/cppBison.yxx
  4. 19 3
      dtool/src/cppparser/cppMakeProperty.cxx
  5. 4 0
      dtool/src/cppparser/cppMakeProperty.h
  6. 2 0
      dtool/src/cppparser/cppPreprocessor.cxx
  7. 2 0
      dtool/src/dtoolbase/dtoolbase.h
  8. 2 0
      dtool/src/dtoolbase/typeHandle.h
  9. 3 0
      dtool/src/dtoolbase/typeRegistry.h
  10. 1 0
      dtool/src/dtoolutil/dSearchPath.h
  11. 1 0
      dtool/src/dtoolutil/pandaSystem.h
  12. 3 1
      dtool/src/interrogate/interfaceMaker.cxx
  13. 2 0
      dtool/src/interrogate/interfaceMaker.h
  14. 224 54
      dtool/src/interrogate/interfaceMakerPythonNative.cxx
  15. 82 19
      dtool/src/interrogate/interrogateBuilder.cxx
  16. 1 1
      dtool/src/interrogatedb/interrogateDatabase.cxx
  17. 36 0
      dtool/src/interrogatedb/interrogateElement.I
  18. 10 1
      dtool/src/interrogatedb/interrogateElement.cxx
  19. 9 0
      dtool/src/interrogatedb/interrogateElement.h
  20. 16 0
      dtool/src/interrogatedb/py_panda.I
  21. 116 2
      dtool/src/interrogatedb/py_panda.cxx
  22. 18 0
      dtool/src/interrogatedb/py_panda.h
  23. 4 0
      dtool/src/prc/configPage.h
  24. 15 0
      dtool/src/prc/configVariableCore.h
  25. 2 0
      dtool/src/prc/configVariableManager.h
  26. 1 0
      dtool/src/prc/configVariableSearchPath.h
  27. 23 0
      dtool/src/prc/encryptStream.I
  28. 14 0
      dtool/src/prc/encryptStream.h
  29. 1 0
      dtool/src/prc/notifyCategory.h
  30. 1 0
      dtool/src/prc/streamReader.h
  31. 3 0
      dtool/src/prc/streamWrapper.h
  32. 1 0
      dtool/src/prc/streamWriter.h
  33. 2 0
      panda/src/chan/animGroup.h
  34. 6 0
      panda/src/chan/partBundle.h
  35. 2 0
      panda/src/chan/partBundleHandle.h
  36. 3 0
      panda/src/chan/partBundleNode.h
  37. 1 0
      panda/src/chan/partGroup.h
  38. 4 1
      panda/src/collide/collisionFloorMesh.h
  39. 4 0
      panda/src/collide/collisionHandlerEvent.h
  40. 1 0
      panda/src/collide/collisionHandlerQueue.h
  41. 1 0
      panda/src/collide/collisionNode.h
  42. 1 0
      panda/src/collide/collisionPolygon.h
  43. 1 0
      panda/src/collide/collisionTraverser.h
  44. 1 0
      panda/src/display/graphicsEngine.h
  45. 3 0
      panda/src/display/graphicsOutput.h
  46. 1 0
      panda/src/display/graphicsPipeSelection.h
  47. 2 0
      panda/src/egg/eggCompositePrimitive.h
  48. 39 0
      panda/src/egg/eggGroup.h
  49. 5 0
      panda/src/egg/eggNurbsCurve.h
  50. 5 5
      panda/src/egg/eggPrimitive.I
  51. 13 0
      panda/src/egg/eggPrimitive.cxx
  52. 15 3
      panda/src/egg/eggPrimitive.h
  53. 4 0
      panda/src/event/asyncTaskManager.h
  54. 4 0
      panda/src/event/event.h
  55. 1 0
      panda/src/express/virtualFileSystem.h
  56. 1 0
      panda/src/gobj/geom.h
  57. 1 0
      panda/src/gobj/geomVertexArrayFormat.h
  58. 1 0
      panda/src/gobj/geomVertexData.h
  59. 5 0
      panda/src/gobj/geomVertexFormat.h
  60. 7 1
      panda/src/gobj/transformBlendTable.h
  61. 5 1
      panda/src/gobj/transformTable.h
  62. 2 0
      panda/src/linmath/lmatrix3_src.h
  63. 2 0
      panda/src/linmath/lmatrix4_src.h
  64. 3 0
      panda/src/mathutil/boundingBox.h
  65. 3 0
      panda/src/mathutil/boundingHexahedron.h
  66. 1 0
      panda/src/mathutil/intersectionBoundingVolume.h
  67. 1 0
      panda/src/mathutil/triangulator.h
  68. 3 0
      panda/src/mathutil/triangulator3.h
  69. 1 0
      panda/src/mathutil/unionBoundingVolume.h
  70. 4 0
      panda/src/movies/microphoneAudio.h
  71. 3 0
      panda/src/net/connectionManager.h
  72. 5 0
      panda/src/parametrics/nurbsSurfaceEvaluator.h
  73. 15 0
      panda/src/parametrics/parametricCurveCollection.cxx
  74. 8 0
      panda/src/parametrics/parametricCurveCollection.h
  75. 1 0
      panda/src/pgraph/camera.h
  76. 1 0
      panda/src/pgraph/loaderFileTypeRegistry.h
  77. 10 0
      panda/src/pgraph/nodePath.h
  78. 12 3
      panda/src/pgraph/occluderNode.I
  79. 7 2
      panda/src/pgraph/occluderNode.h
  80. 13 13
      panda/src/pgraph/pandaNode.I
  81. 28 10
      panda/src/pgraph/pandaNode.h
  82. 11 0
      panda/src/pgraph/portalNode.h
  83. 23 3
      panda/src/pgraphnodes/computeNode.I
  84. 5 2
      panda/src/pgraphnodes/computeNode.h
  85. 7 0
      panda/src/pgraphnodes/lodNode.h
  86. 3 4
      panda/src/physics/forceNode.I
  87. 16 2
      panda/src/physics/forceNode.cxx
  88. 7 4
      panda/src/physics/forceNode.h
  89. 3 4
      panda/src/physics/physicalNode.I
  90. 14 2
      panda/src/physics/physicalNode.cxx
  91. 6 3
      panda/src/physics/physicalNode.h
  92. 4 0
      panda/src/pnmimage/pnmFileType.h
  93. 1 0
      panda/src/pnmimage/pnmFileTypeRegistry.h
  94. 8 0
      panda/src/pstatclient/pStatClient.h
  95. 1 0
      panda/src/putil/modifierButtons.h
  96. 1 0
      panda/src/text/dynamicTextFont.h
  97. 1 0
      panda/src/tform/buttonThrower.h
  98. 2 0
      panda/src/tform/mouseWatcherBase.h

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


+ 88 - 84
dtool/src/cppparser/cppBison.h.prebuilt

@@ -124,48 +124,50 @@ extern int cppyydebug;
     KW_INLINE = 334,
     KW_INT = 335,
     KW_LONG = 336,
-    KW_MAKE_PROPERTY = 337,
-    KW_MAKE_PROPERTY2 = 338,
-    KW_MAKE_SEQ = 339,
-    KW_MUTABLE = 340,
-    KW_NAMESPACE = 341,
-    KW_NEW = 342,
-    KW_NOEXCEPT = 343,
-    KW_NULLPTR = 344,
-    KW_OPERATOR = 345,
-    KW_OVERRIDE = 346,
-    KW_PRIVATE = 347,
-    KW_PROTECTED = 348,
-    KW_PUBLIC = 349,
-    KW_REGISTER = 350,
-    KW_REINTERPRET_CAST = 351,
-    KW_RETURN = 352,
-    KW_SHORT = 353,
-    KW_SIGNED = 354,
-    KW_SIZEOF = 355,
-    KW_STATIC = 356,
-    KW_STATIC_ASSERT = 357,
-    KW_STATIC_CAST = 358,
-    KW_STRUCT = 359,
-    KW_TEMPLATE = 360,
-    KW_THREAD_LOCAL = 361,
-    KW_THROW = 362,
-    KW_TRUE = 363,
-    KW_TRY = 364,
-    KW_TYPEDEF = 365,
-    KW_TYPEID = 366,
-    KW_TYPENAME = 367,
-    KW_UNION = 368,
-    KW_UNSIGNED = 369,
-    KW_USING = 370,
-    KW_VIRTUAL = 371,
-    KW_VOID = 372,
-    KW_VOLATILE = 373,
-    KW_WCHAR_T = 374,
-    KW_WHILE = 375,
-    START_CPP = 376,
-    START_CONST_EXPR = 377,
-    START_TYPE = 378
+    KW_MAKE_MAP_PROPERTY = 337,
+    KW_MAKE_PROPERTY = 338,
+    KW_MAKE_PROPERTY2 = 339,
+    KW_MAKE_SEQ = 340,
+    KW_MAKE_SEQ_PROPERTY = 341,
+    KW_MUTABLE = 342,
+    KW_NAMESPACE = 343,
+    KW_NEW = 344,
+    KW_NOEXCEPT = 345,
+    KW_NULLPTR = 346,
+    KW_OPERATOR = 347,
+    KW_OVERRIDE = 348,
+    KW_PRIVATE = 349,
+    KW_PROTECTED = 350,
+    KW_PUBLIC = 351,
+    KW_REGISTER = 352,
+    KW_REINTERPRET_CAST = 353,
+    KW_RETURN = 354,
+    KW_SHORT = 355,
+    KW_SIGNED = 356,
+    KW_SIZEOF = 357,
+    KW_STATIC = 358,
+    KW_STATIC_ASSERT = 359,
+    KW_STATIC_CAST = 360,
+    KW_STRUCT = 361,
+    KW_TEMPLATE = 362,
+    KW_THREAD_LOCAL = 363,
+    KW_THROW = 364,
+    KW_TRUE = 365,
+    KW_TRY = 366,
+    KW_TYPEDEF = 367,
+    KW_TYPEID = 368,
+    KW_TYPENAME = 369,
+    KW_UNION = 370,
+    KW_UNSIGNED = 371,
+    KW_USING = 372,
+    KW_VIRTUAL = 373,
+    KW_VOID = 374,
+    KW_VOLATILE = 375,
+    KW_WCHAR_T = 376,
+    KW_WHILE = 377,
+    START_CPP = 378,
+    START_CONST_EXPR = 379,
+    START_TYPE = 380
   };
 #endif
 /* Tokens.  */
@@ -248,48 +250,50 @@ extern int cppyydebug;
 #define KW_INLINE 334
 #define KW_INT 335
 #define KW_LONG 336
-#define KW_MAKE_PROPERTY 337
-#define KW_MAKE_PROPERTY2 338
-#define KW_MAKE_SEQ 339
-#define KW_MUTABLE 340
-#define KW_NAMESPACE 341
-#define KW_NEW 342
-#define KW_NOEXCEPT 343
-#define KW_NULLPTR 344
-#define KW_OPERATOR 345
-#define KW_OVERRIDE 346
-#define KW_PRIVATE 347
-#define KW_PROTECTED 348
-#define KW_PUBLIC 349
-#define KW_REGISTER 350
-#define KW_REINTERPRET_CAST 351
-#define KW_RETURN 352
-#define KW_SHORT 353
-#define KW_SIGNED 354
-#define KW_SIZEOF 355
-#define KW_STATIC 356
-#define KW_STATIC_ASSERT 357
-#define KW_STATIC_CAST 358
-#define KW_STRUCT 359
-#define KW_TEMPLATE 360
-#define KW_THREAD_LOCAL 361
-#define KW_THROW 362
-#define KW_TRUE 363
-#define KW_TRY 364
-#define KW_TYPEDEF 365
-#define KW_TYPEID 366
-#define KW_TYPENAME 367
-#define KW_UNION 368
-#define KW_UNSIGNED 369
-#define KW_USING 370
-#define KW_VIRTUAL 371
-#define KW_VOID 372
-#define KW_VOLATILE 373
-#define KW_WCHAR_T 374
-#define KW_WHILE 375
-#define START_CPP 376
-#define START_CONST_EXPR 377
-#define START_TYPE 378
+#define KW_MAKE_MAP_PROPERTY 337
+#define KW_MAKE_PROPERTY 338
+#define KW_MAKE_PROPERTY2 339
+#define KW_MAKE_SEQ 340
+#define KW_MAKE_SEQ_PROPERTY 341
+#define KW_MUTABLE 342
+#define KW_NAMESPACE 343
+#define KW_NEW 344
+#define KW_NOEXCEPT 345
+#define KW_NULLPTR 346
+#define KW_OPERATOR 347
+#define KW_OVERRIDE 348
+#define KW_PRIVATE 349
+#define KW_PROTECTED 350
+#define KW_PUBLIC 351
+#define KW_REGISTER 352
+#define KW_REINTERPRET_CAST 353
+#define KW_RETURN 354
+#define KW_SHORT 355
+#define KW_SIGNED 356
+#define KW_SIZEOF 357
+#define KW_STATIC 358
+#define KW_STATIC_ASSERT 359
+#define KW_STATIC_CAST 360
+#define KW_STRUCT 361
+#define KW_TEMPLATE 362
+#define KW_THREAD_LOCAL 363
+#define KW_THROW 364
+#define KW_TRUE 365
+#define KW_TRY 366
+#define KW_TYPEDEF 367
+#define KW_TYPEID 368
+#define KW_TYPENAME 369
+#define KW_UNION 370
+#define KW_UNSIGNED 371
+#define KW_USING 372
+#define KW_VIRTUAL 373
+#define KW_VOID 374
+#define KW_VOLATILE 375
+#define KW_WCHAR_T 376
+#define KW_WHILE 377
+#define START_CPP 378
+#define START_CONST_EXPR 379
+#define START_TYPE 380
 
 /* Value type.  */
 

+ 118 - 0
dtool/src/cppparser/cppBison.yxx

@@ -284,9 +284,11 @@ pop_struct() {
 %token KW_INLINE
 %token KW_INT
 %token KW_LONG
+%token KW_MAKE_MAP_PROPERTY
 %token KW_MAKE_PROPERTY
 %token KW_MAKE_PROPERTY2
 %token KW_MAKE_SEQ
+%token KW_MAKE_SEQ_PROPERTY
 %token KW_MUTABLE
 %token KW_NAMESPACE
 %token KW_NEW
@@ -550,6 +552,118 @@ declaration:
                                                          setter_func, current_scope, @1.file);
     current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
   }
+}
+        | KW_MAKE_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
+{
+  CPPDeclaration *getter = $5->find_symbol(current_scope, global_scope, current_lexer);
+  if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
+    yyerror("Reference to non-existent or invalid getter: " + $5->get_fully_scoped_name(), @5);
+
+  } else {
+    CPPDeclaration *setter = $7->find_symbol(current_scope, global_scope, current_lexer);
+    CPPFunctionGroup *setter_func = NULL;
+
+    if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) {
+      yyerror("Reference to non-existent or invalid setter: " + $7->get_fully_scoped_name(), @7);
+    } else {
+      setter_func = setter->as_function_group();
+    }
+
+    CPPDeclaration *deleter = $9->find_symbol(current_scope, global_scope, current_lexer);
+    if (deleter == (CPPDeclaration *)NULL || deleter->get_subtype() != CPPDeclaration::ST_function_group) {
+      yyerror("reference to non-existent or invalid delete method: " + $9->get_fully_scoped_name(), @9);
+      deleter = NULL;
+    }
+
+    CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(),
+                                                         setter_func, current_scope, @1.file);
+    if (deleter) {
+      make_property->_del_function = deleter->as_function_group();
+    }
+    current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
+  }
+}
+        | KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
+{
+  CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer);
+  if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) {
+    yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5);
+    length_getter = NULL;
+  }
+
+  CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
+  if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
+    yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
+  }
+
+  CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(), NULL, current_scope, @1.file);
+  make_property->_length_function = length_getter->as_function_group();
+  current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
+}
+        | KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
+{
+  CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer);
+  if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) {
+    yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5);
+    length_getter = NULL;
+  }
+
+  CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
+  if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
+    yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
+
+  } else {
+    CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer);
+    CPPFunctionGroup *setter_func = NULL;
+
+    if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) {
+      yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9);
+    } else {
+      setter_func = setter->as_function_group();
+    }
+
+    CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(),
+                                                         setter_func, current_scope, @1.file);
+    make_property->_length_function = length_getter->as_function_group();
+    current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
+  }
+}
+        | KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
+{
+  CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer);
+  if (length_getter == (CPPDeclaration *)NULL || length_getter->get_subtype() != CPPDeclaration::ST_function_group) {
+    yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5);
+    length_getter = NULL;
+  }
+
+  CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
+  if (getter == (CPPDeclaration *)NULL || getter->get_subtype() != CPPDeclaration::ST_function_group) {
+    yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
+
+  } else {
+    CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer);
+    CPPFunctionGroup *setter_func = NULL;
+
+    if (setter == (CPPDeclaration *)NULL || setter->get_subtype() != CPPDeclaration::ST_function_group) {
+      yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9);
+    } else {
+      setter_func = setter->as_function_group();
+    }
+
+    CPPDeclaration *deleter = $11->find_symbol(current_scope, global_scope, current_lexer);
+    if (deleter == (CPPDeclaration *)NULL || deleter->get_subtype() != CPPDeclaration::ST_function_group) {
+      yyerror("reference to non-existent or invalid delete method: " + $11->get_fully_scoped_name(), @11);
+      deleter = NULL;
+    }
+
+    CPPMakeProperty *make_property = new CPPMakeProperty($3, getter->as_function_group(),
+                                                         setter_func, current_scope, @1.file);
+    make_property->_length_function = length_getter->as_function_group();
+    if (deleter) {
+      make_property->_del_function = deleter->as_function_group();
+    }
+    current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
+  }
 }
         | KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
 {
@@ -3519,6 +3633,10 @@ name:
         | KW_PRIVATE
 {
   $$ = new CPPIdentifier("private", @1);
+}
+        | KW_STATIC
+{
+  $$ = new CPPIdentifier("static", @1);
 }
         ;
 

+ 19 - 3
dtool/src/cppparser/cppMakeProperty.cxx

@@ -23,10 +23,12 @@ CPPMakeProperty(CPPIdentifier *ident,
                 CPPScope *current_scope, const CPPFile &file) :
   CPPDeclaration(file),
   _ident(ident),
+  _length_function(NULL),
   _has_function(NULL),
   _get_function(getter),
   _set_function(setter),
-  _clear_function(NULL)
+  _clear_function(NULL),
+  _del_function(NULL)
 {
   _ident->_native_scope = current_scope;
 }
@@ -41,10 +43,12 @@ CPPMakeProperty(CPPIdentifier *ident,
                 CPPScope *current_scope, const CPPFile &file) :
   CPPDeclaration(file),
   _ident(ident),
+  _length_function(NULL),
   _has_function(hasser),
   _get_function(getter),
   _set_function(setter),
-  _clear_function(clearer)
+  _clear_function(clearer),
+  _del_function(NULL)
 {
   _ident->_native_scope = current_scope;
 }
@@ -78,7 +82,11 @@ get_fully_scoped_name() const {
  */
 void CPPMakeProperty::
 output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
-  out << "__make_property";
+  if (_length_function != NULL) {
+    out << "__make_seq_property";
+  } else {
+    out << "__make_property";
+  }
 
   if (_has_function != NULL) {
     out.put('2');
@@ -86,6 +94,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
 
   out << "(" << _ident->get_local_name(scope);
 
+  if (_length_function != NULL) {
+    out << ", " << _length_function->_name;
+  }
+
   if (_has_function != NULL) {
     out << ", " << _has_function->_name;
   }
@@ -100,6 +112,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
     out << ", " << _clear_function->_name;
   }
 
+  if (_del_function != NULL) {
+    out << ", " << _del_function->_name;
+  }
+
   out << ");";
 }
 

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

@@ -46,10 +46,14 @@ public:
   virtual CPPMakeProperty *as_make_property();
 
   CPPIdentifier *_ident;
+  // If length_function is not NULL, this is actually a sequence property,
+  // and the other functions take an additional index argument.
+  CPPFunctionGroup *_length_function;
   CPPFunctionGroup *_has_function;
   CPPFunctionGroup *_get_function;
   CPPFunctionGroup *_set_function;
   CPPFunctionGroup *_clear_function;
+  CPPFunctionGroup *_del_function;
 };
 
 #endif

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

@@ -2458,9 +2458,11 @@ check_keyword(const string &name) {
   if (name == "__inline__") return KW_INLINE;
   if (name == "int") return KW_INT;
   if (name == "long") return KW_LONG;
+  if (name == "__make_map_property") return KW_MAKE_MAP_PROPERTY;
   if (name == "__make_property") return KW_MAKE_PROPERTY;
   if (name == "__make_property2") return KW_MAKE_PROPERTY2;
   if (name == "__make_seq") return KW_MAKE_SEQ;
+  if (name == "__make_seq_property") return KW_MAKE_SEQ_PROPERTY;
   if (name == "mutable") return KW_MUTABLE;
   if (name == "namespace") return KW_NAMESPACE;
   if (name == "noexcept") return KW_NOEXCEPT;

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

@@ -415,6 +415,7 @@ typedef struct _object PyObject;
 #define MAKE_PROPERTY(property_name, ...) __make_property(property_name, __VA_ARGS__)
 #define MAKE_PROPERTY2(property_name, ...) __make_property2(property_name, __VA_ARGS__)
 #define MAKE_SEQ(seq_name, num_name, element_name) __make_seq(seq_name, num_name, element_name)
+#define MAKE_SEQ_PROPERTY(property_name, ...) __make_seq_property(property_name, __VA_ARGS__)
 #undef USE_STL_ALLOCATOR  /* Don't try to parse these template classes in interrogate. */
 #define EXTENSION(x) __extension x
 #define EXTEND __extension
@@ -425,6 +426,7 @@ typedef struct _object PyObject;
 #define MAKE_PROPERTY(property_name, ...)
 #define MAKE_PROPERTY2(property_name, ...)
 #define MAKE_SEQ(seq_name, num_name, element_name)
+#define MAKE_SEQ_PROPERTY(property_name, ...)
 #define EXTENSION(x)
 #define EXTEND
 #endif

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

@@ -114,6 +114,8 @@ PUBLISHED:
 
   MAKE_PROPERTY(index, get_index);
   MAKE_PROPERTY(name, get_name);
+  MAKE_SEQ_PROPERTY(parent_classes, get_num_parent_classes, get_parent_class);
+  MAKE_SEQ_PROPERTY(child_classes, get_num_child_classes, get_child_class);
 
 public:
   INLINE static TypeHandle from_index(int index);

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

@@ -79,6 +79,9 @@ PUBLISHED:
   // ptr() returns the pointer to the global TypeRegistry object.
   static TypeRegistry *ptr();
 
+  MAKE_SEQ_PROPERTY(typehandles, get_num_typehandles, get_typehandle);
+  MAKE_SEQ_PROPERTY(root_classes, get_num_root_classes, get_root_class);
+
 private:
   // The TypeRegistry class should never be constructed by user code.  There
   // is only one in the universe, and it constructs itself!

+ 1 - 0
dtool/src/dtoolutil/dSearchPath.h

@@ -71,6 +71,7 @@ PUBLISHED:
   size_t get_num_directories() const;
   const Filename &get_directory(size_t n) const;
   MAKE_SEQ(get_directories, get_num_directories, get_directory);
+  MAKE_SEQ_PROPERTY(directories, get_num_directories, get_directory);
 
   Filename find_file(const Filename &filename) const;
   size_t find_all_files(const Filename &filename, Results &results) const;

+ 1 - 0
dtool/src/dtoolutil/pandaSystem.h

@@ -50,6 +50,7 @@ PUBLISHED:
   size_t get_num_systems() const;
   string get_system(size_t n) const;
   MAKE_SEQ(get_systems, get_num_systems, get_system);
+  MAKE_SEQ_PROPERTY(systems, get_num_systems, get_system);
 
   string get_system_tag(const string &system, const string &tag) const;
 

+ 3 - 1
dtool/src/interrogate/interfaceMaker.cxx

@@ -86,10 +86,12 @@ MakeSeq(const string &name, const InterrogateMakeSeq &imake_seq) :
 InterfaceMaker::Property::
 Property(const InterrogateElement &ielement) :
   _ielement(ielement),
+  _length_function(NULL),
   _getter(NULL),
   _setter(NULL),
   _has_function(NULL),
-  _clear_function(NULL)
+  _clear_function(NULL),
+  _deleter(NULL)
 {
 }
 

+ 2 - 0
dtool/src/interrogate/interfaceMaker.h

@@ -126,10 +126,12 @@ public:
     Property(const InterrogateElement &ielement);
 
     const InterrogateElement &_ielement;
+    Function *_length_function;
     Function *_getter;
     Function *_setter;
     Function *_has_function;
     Function *_clear_function;
+    Function *_deleter;
   };
   typedef vector<Property *> Properties;
 

+ 224 - 54
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -1013,13 +1013,21 @@ write_class_details(ostream &out, Object *obj) {
   }
 
   // Write the constructors.
+  std::string fname = "static int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)";
   for (fi = obj->_constructors.begin(); fi != obj->_constructors.end(); ++fi) {
     Function *func = (*fi);
-    std::string fname = "static int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)";
 
     string expected_params;
     write_function_for_name(out, obj, func->_remaps, fname, expected_params, true, AT_keyword_args, RF_int);
   }
+  if (obj->_constructors.size() == 0) {
+    // We still need to write a dummy constructor to prevent inheriting the
+    // constructor from a base class.
+    out << fname << " {\n"
+      "  Dtool_Raise_TypeError(\"cannot init abstract class\");\n"
+      "  return -1;\n"
+      "}\n\n";
+  }
 
   CPPType *cpptype = TypeManager::resolve_type(obj->_itype._cpptype);
 
@@ -2618,7 +2626,8 @@ write_module_class(ostream &out, Object *obj) {
 
       string getter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter";
       string setter = "NULL";
-      if (property->_setter != NULL && is_function_legal(property->_setter)) {
+      if (property->_length_function == NULL &&
+          property->_setter != NULL && is_function_legal(property->_setter)) {
         setter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter";
       }
 
@@ -2931,11 +2940,7 @@ write_module_class(ostream &out, Object *obj) {
   // Py_ssize_t tp_dictoffset;
   out << "    0, // tp_dictoffset\n";
   // initproc tp_init;
-  if (obj->_constructors.size() > 0) {
-    out << "    Dtool_Init_" << ClassName << ",\n";
-  } else {
-    out << "    0,\n";
-  }
+  out << "    Dtool_Init_" << ClassName << ",\n";
   // allocfunc tp_alloc;
   out << "    PyType_GenericAlloc,\n";
   // newfunc tp_new;
@@ -3970,13 +3975,7 @@ collapse_default_remaps(std::map<int, std::set<FunctionRemap *> > &map_sets,
               goto abort_iteration;
             }
           }
-        } else if (TypeManager::is_bool(type)) {
-        } else if (TypeManager::is_char(type)) {
-        } else if (TypeManager::is_wchar(type)) {
-          goto abort_iteration;
-        } else if (TypeManager::is_longlong(type)) {
         } else if (TypeManager::is_integer(type)) {
-        } else if (TypeManager::is_double(type)) {
         } else if (TypeManager::is_float(type)) {
         } else if (TypeManager::is_const_char_pointer(type)) {
         } else if (TypeManager::is_pointer_to_PyTypeObject(type)) {
@@ -6138,8 +6137,9 @@ void InterfaceMakerPythonNative::
 write_make_seq(ostream &out, Object *obj, const std::string &ClassName,
                const std::string &cClassName, MakeSeq *make_seq) {
 
-  out << "/******************************************************************\n" << " * Python make_seq wrapper\n";
-  out << " *******************************************************************/\n";
+  out << "/*\n"
+         " * Python make_seq wrapper\n"
+         " */\n";
 
   out << "static PyObject *" << make_seq->_name + "(PyObject *self, PyObject *) {\n";
 
@@ -6228,10 +6228,156 @@ write_getset(ostream &out, Object *obj, Property *property) {
 
   const InterrogateElement &ielem = property->_ielement;
 
-  if (property->_getter != NULL) {
+  if (property->_length_function != NULL) {
+    // This is actually a sequence.  Wrap this with a special class.
+    FunctionRemap *len_remap = property->_length_function->_remaps.front();
+    vector_string pexprs;
+
+    out << "/**\n"
+           " * sequence length function for property " << cClassName << "::" << ielem.get_name() << "\n"
+           " */\n"
+           "static Py_ssize_t Dtool_" + ClassName + "_" + ielem.get_name() + "_Len(PyObject *self) {\n";
+    if (property->_length_function->_has_this) {
+      out <<
+        "  " << cClassName  << " *local_this = NULL;\n"
+        "  if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"
+        "    return NULL;\n"
+        "  }\n"
+        "  return (Py_ssize_t)" << len_remap->get_call_str("local_this", pexprs) << ";\n";
+    } else {
+      out << "  return (Py_ssize_t)" << len_remap->get_call_str("", pexprs) << ";\n";
+    }
+    out << "}\n\n";
+
+    // Now write out the getitem helper function.
+    if (property->_getter != NULL) {
+      out <<
+        "/**\n"
+        " * sequence getter for property " << cClassName << "::" << ielem.get_name() << "\n"
+        " */\n"
+        "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getitem(PyObject *self, Py_ssize_t index) {\n"
+        "  " << cClassName << " *local_this = NULL;\n"
+        "  if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"
+        "    return NULL;\n"
+        "  }\n";
+
+      // This is a getitem of a sequence type.  This means we *need* to raise
+      // IndexError if we're out of bounds.
+      out << "  if (index < 0 || index >= (Py_ssize_t)"
+          << len_remap->get_call_str("local_this", pexprs) << ") {\n";
+      out << "    PyErr_SetString(PyExc_IndexError, \"" << ClassName << "." << ielem.get_name() << "[] index out of range\");\n";
+      out << "    return NULL;\n";
+      out << "  }\n";
+
+      if (property->_has_function != NULL) {
+        out << "  if (!local_this->" << property->_has_function->_ifunc.get_name() << "(index)) {\n"
+            << "    Py_INCREF(Py_None);\n"
+            << "    return Py_None;\n"
+            << "  }\n";
+      }
+
+      std::set<FunctionRemap*> remaps;
+
+      // Extract only the getters that take one argument.
+      Function::Remaps::iterator it;
+      for (it = property->_getter->_remaps.begin();
+           it != property->_getter->_remaps.end();
+           ++it) {
+        FunctionRemap *remap = *it;
+        int min_num_args = remap->get_min_num_args();
+        int max_num_args = remap->get_max_num_args();
+        if (min_num_args <= 1 && max_num_args >= 1) {
+          remaps.insert(remap);
+        }
+      }
+
+      string expected_params;
+      write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true,
+                            AT_no_args, RF_pyobject | RF_err_null, false, true, "index");
+
+      out << "  if (!_PyErr_OCCURRED()) {\n";
+      out << "    return Dtool_Raise_BadArgumentsError(\n";
+      output_quoted(out, 6, expected_params);
+      out << ");\n"
+             "  }\n"
+             "}\n\n";
+    }
+
+    // Write out a setitem if this is not a read-only property.
+    if (property->_setter != NULL) {
+      out << "static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setitem(PyObject *self, Py_ssize_t index, PyObject *arg) {\n";
+      out << "  " << cClassName  << " *local_this = NULL;\n";
+      out << "  if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \""
+          << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n";
+      out << "    return -1;\n";
+      out << "  }\n\n";
+
+      out << "  if (arg == (PyObject *)NULL) {\n";
+      if (property->_deleter != NULL) {
+        out << "    local_this->" << property->_deleter->_ifunc.get_name() << "(index);\n"
+            << "    return 0;\n";
+      } else {
+        out << "    Dtool_Raise_TypeError(\"can't delete " << ielem.get_name() << "[] attribute\");\n"
+               "    return -1;\n";
+      }
+      out << "  }\n";
+
+      if (property->_clear_function != NULL) {
+        out << "  if (arg == Py_None) {\n"
+            << "    local_this->" << property->_clear_function->_ifunc.get_name() << "(index);\n"
+            << "    return 0;\n"
+            << "  }\n";
+      }
+
+      std::set<FunctionRemap*> remaps;
+
+      // Extract only the setters that take two arguments.
+      Function::Remaps::iterator it;
+      for (it = property->_setter->_remaps.begin();
+           it != property->_setter->_remaps.end();
+           ++it) {
+        FunctionRemap *remap = *it;
+        int min_num_args = remap->get_min_num_args();
+        int max_num_args = remap->get_max_num_args();
+        if (min_num_args <= 2 && max_num_args >= 2) {
+          remaps.insert(remap);
+        }
+      }
+
+      string expected_params;
+      write_function_forset(out, remaps, 2, 2,
+                            expected_params, 2, true, true, AT_single_arg,
+                            RF_int, false, false, "index");
+
+      out << "  if (!_PyErr_OCCURRED()) {\n";
+      out << "    Dtool_Raise_BadArgumentsError(\n";
+      output_quoted(out, 6, expected_params);
+      out << ");\n";
+      out << "  }\n";
+      out << "  return -1;\n";
+      out << "}\n\n";
+    }
+
+    // Now write the getter, which returns a special wrapper object.
+    out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n"
+           "  Py_INCREF(self);\n"
+           "  Dtool_SequenceWrapper *wrap = PyObject_New(Dtool_SequenceWrapper, &Dtool_SequenceWrapper_Type);\n"
+           "  wrap->_base = self;\n"
+           "  wrap->_len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n"
+           "  wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Getitem;\n";
+    if (property->_setter != NULL) {
+      out << "  wrap->_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Setitem;\n";
+    } else {
+      out << "  wrap->_setitem_func = NULL;\n";
+    }
+    out << "  return (PyObject *)wrap;\n"
+           "}\n\n";
+
+  } else if (property->_getter != NULL) {
+    // Write out a regular, unwrapped getter.
+    out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n";
     FunctionRemap *remap = property->_getter->_remaps.front();
 
-    out << "PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n";
     if (remap->_const_method) {
       out << "  const " << cClassName  << " *local_this = NULL;\n";
       out << "  if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n";
@@ -6258,50 +6404,61 @@ write_getset(ostream &out, Object *obj, Property *property) {
                           expected_params, 2, false, true, AT_no_args,
                           RF_pyobject | RF_err_null, false, false);
     out << "}\n\n";
-  }
 
-  if (property->_setter != NULL) {
-    out << "int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter(PyObject *self, PyObject *arg, void *) {\n";
-    out << "  " << cClassName  << " *local_this = NULL;\n";
-    out << "  if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \""
-        << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n";
-    out << "    return -1;\n";
-    out << "  }\n\n";
+    // Write out a setter if this is not a read-only property.
+    if (property->_setter != NULL) {
+      out << "static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter(PyObject *self, PyObject *arg, void *) {\n";
+      out << "  " << cClassName  << " *local_this = NULL;\n";
+      out << "  if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \""
+          << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n";
+      out << "    return -1;\n";
+      out << "  }\n\n";
 
-    if (property->_clear_function != NULL) {
-      out << "  if (arg == Py_None) {\n"
-          << "    local_this->" << property->_clear_function->_ifunc.get_name() << "();\n"
-          << "    return 0;\n"
-          << "  }\n";
-    }
+      out << "  if (arg == (PyObject *)NULL) {\n";
+      if (property->_deleter != NULL) {
+        out << "    local_this->" << property->_deleter->_ifunc.get_name() << "();\n"
+            << "    return 0;\n";
+      } else {
+        out << "    Dtool_Raise_TypeError(\"can't delete " << ielem.get_name() << " attribute\");\n"
+               "    return -1;\n";
+      }
+      out << "  }\n";
 
-    std::set<FunctionRemap*> remaps;
+      if (property->_clear_function != NULL) {
+        out << "  if (arg == Py_None) {\n"
+            << "    local_this->" << property->_clear_function->_ifunc.get_name() << "();\n"
+            << "    return 0;\n"
+            << "  }\n";
+      }
 
-    // Extract only the setters that take one argument.
-    Function::Remaps::iterator it;
-    for (it = property->_setter->_remaps.begin();
-         it != property->_setter->_remaps.end();
-         ++it) {
-      FunctionRemap *remap = *it;
-      int min_num_args = remap->get_min_num_args();
-      int max_num_args = remap->get_max_num_args();
-      if (min_num_args <= 1 && max_num_args >= 1) {
-        remaps.insert(remap);
+      std::set<FunctionRemap*> remaps;
+
+      // Extract only the setters that take one argument.
+      Function::Remaps::iterator it;
+      for (it = property->_setter->_remaps.begin();
+           it != property->_setter->_remaps.end();
+           ++it) {
+        FunctionRemap *remap = *it;
+        int min_num_args = remap->get_min_num_args();
+        int max_num_args = remap->get_max_num_args();
+        if (min_num_args <= 1 && max_num_args >= 1) {
+          remaps.insert(remap);
+        }
       }
-    }
 
-    string expected_params;
-    write_function_forset(out, remaps, 1, 1,
-                          expected_params, 2, true, true, AT_single_arg,
-                          RF_int, false, false);
+      string expected_params;
+      write_function_forset(out, remaps, 1, 1,
+                            expected_params, 2, true, true, AT_single_arg,
+                            RF_int, false, false);
 
-    out << "  if (!_PyErr_OCCURRED()) {\n";
-    out << "    Dtool_Raise_BadArgumentsError(\n";
-    output_quoted(out, 6, expected_params);
-    out << ");\n";
-    out << "  }\n";
-    out << "  return -1;\n";
-    out << "}\n\n";
+      out << "  if (!_PyErr_OCCURRED()) {\n";
+      out << "    Dtool_Raise_BadArgumentsError(\n";
+      output_quoted(out, 6, expected_params);
+      out << ");\n";
+      out << "  }\n";
+      out << "  return -1;\n";
+      out << "}\n\n";
+    }
   }
 }
 
@@ -6426,6 +6583,19 @@ record_object(TypeIndex type_index) {
       }
     }
 
+    if (ielement.has_del_function()) {
+      FunctionIndex func_index = ielement.get_del_function();
+      Function *del_function = record_function(itype, func_index);
+      if (is_function_legal(del_function)) {
+        property->_deleter = del_function;
+      }
+    }
+
+    if (ielement.is_sequence()) {
+      FunctionIndex func_index = ielement.get_length_function();
+      property->_length_function = record_function(itype, func_index);
+    }
+
     if (property->_getter != NULL) {
       object->_properties.push_back(property);
     } else {

+ 82 - 19
dtool/src/interrogate/interrogateBuilder.cxx

@@ -1782,9 +1782,9 @@ get_function(CPPInstance *function, string description,
 }
 
 /**
- * Adds the indicated make_property to the database, if it is not already
- * present.  In either case, returns the MakeSeqIndex of the make_seq within
- * the database.
+ * Adds the indicated make_property or make_seq_property to the database, if
+ * it is not already present.  In either case, returns the ElementIndex
+ * of the created property within the database.
  */
 ElementIndex InterrogateBuilder::
 get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CPPScope *scope) {
@@ -1805,20 +1805,58 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
     return index;
   }
 
+  // If we have a length function (ie. this is a sequence property), we should
+  // find the function that will give us the length.
+  FunctionIndex length_function = 0;
+  bool is_seq = false;
+
+  CPPFunctionGroup::Instances::const_iterator fi;
+  CPPFunctionGroup *fgroup = make_property->_length_function;
+  if (fgroup != NULL) {
+    is_seq = true;
+
+    for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
+      CPPInstance *function = (*fi);
+      CPPFunctionType *ftype =
+        function->_type->as_function_type();
+      if (ftype != NULL) {
+        length_function = get_function(function, "", struct_type,
+                                       struct_type->get_scope(), 0);
+        if (length_function != 0) {
+          break;
+        }
+      }
+    }
+    if (length_function == 0) {
+      cerr << "No instance of length method '"
+           << fgroup->_name << "' is suitable!\n";
+      return 0;
+    }
+  }
+
   // Find the getter so we can get its return type.
   CPPInstance *getter = NULL;
   CPPType *return_type = NULL;
 
-  CPPFunctionGroup *fgroup = make_property->_get_function;
+  fgroup = make_property->_get_function;
   if (fgroup != NULL) {
     CPPFunctionGroup::Instances::const_iterator fi;
     for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
       CPPInstance *function = (*fi);
       CPPFunctionType *ftype = function->_type->as_function_type();
+      if (ftype == NULL) {
+        continue;
+      }
 
       // The getter must either take no arguments, or all defaults.
-      if (ftype != NULL && (ftype->_parameters->_parameters.size() == 0 ||
-          ftype->_parameters->_parameters[0]->_initializer != NULL)) {
+      if (ftype->_parameters->_parameters.size() == (int)is_seq ||
+          (ftype->_parameters->_parameters.size() > (int)is_seq &&
+           ftype->_parameters->_parameters[(int)is_seq]->_initializer != NULL)) {
+        // If this is a sequence getter, it must take an index argument.
+        if (is_seq && !TypeManager::is_integer(ftype->_parameters->_parameters[0]->_type)) {
+          continue;
+        }
+
         getter = function;
         return_type = ftype->_return_type;
 
@@ -1860,6 +1898,28 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
     }
   }
 
+  // And the "deleter".
+  CPPInstance *deleter = NULL;
+
+  fgroup = make_property->_del_function;
+  if (fgroup != NULL) {
+    CPPFunctionGroup::Instances::const_iterator fi;
+    for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
+      CPPInstance *function = (*fi);
+      CPPFunctionType *ftype = function->_type->as_function_type();
+      if (ftype != NULL && ftype->_parameters->_parameters.size() == (int)is_seq) {
+        deleter = function;
+        break;
+      }
+    }
+
+    if (deleter == NULL || return_type == NULL) {
+      cerr << "No instance of delete-function '"
+           << fgroup->_name << "' is suitable!\n";
+      return 0;
+    }
+  }
+
   InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
   // It isn't here, so we'll have to define it.
   ElementIndex index = idb->get_next_index();
@@ -1875,22 +1935,30 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
     iproperty._type = 0;
   }
 
+  if (length_function != 0) {
+    iproperty._flags |= InterrogateElement::F_sequence;
+    iproperty._length_function = length_function;
+  }
+
   if (getter != NULL) {
     iproperty._flags |= InterrogateElement::F_has_getter;
     iproperty._getter = get_function(getter, "", struct_type,
                                      struct_type->get_scope(), 0);
-    if (iproperty._getter == 0) {
-      cerr << "failed " << *getter << "\n";
-    }
+    nassertr(iproperty._getter, 0);
   }
 
   if (hasser != NULL) {
     iproperty._flags |= InterrogateElement::F_has_has_function;
     iproperty._has_function = get_function(hasser, "", struct_type,
                                            struct_type->get_scope(), 0);
-    if (iproperty._has_function == 0) {
-      cerr << "failed " << *hasser << "\n";
-    }
+    nassertr(iproperty._has_function, 0);
+  }
+
+  if (deleter != NULL) {
+    iproperty._flags |= InterrogateElement::F_has_del_function;
+    iproperty._del_function = get_function(deleter, "", struct_type,
+                                          struct_type->get_scope(), 0);
+    nassertr(iproperty._del_function, 0);
   }
 
   // See if there happens to be a comment before the MAKE_PROPERTY macro.
@@ -1907,9 +1975,7 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
       iproperty._flags |= InterrogateElement::F_has_setter;
       iproperty._setter = get_function(function, "", struct_type,
                                        struct_type->get_scope(), 0);
-      if (iproperty._setter == 0) {
-        cerr << "failed " << *function << "\n";
-      }
+      nassertr(iproperty._setter, 0);
       break;
     }
   }
@@ -1922,15 +1988,12 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
       iproperty._flags |= InterrogateElement::F_has_clear_function;
       iproperty._clear_function = get_function(function, "", struct_type,
                                                struct_type->get_scope(), 0);
-      if (iproperty._clear_function == 0) {
-        cerr << "failed " << *function << "\n";
-      }
+      nassertr(iproperty._clear_function, 0);
       break;
     }
   }
 
   idb->add_element(index, iproperty);
-
   return index;
 }
 

+ 1 - 1
dtool/src/interrogatedb/interrogateDatabase.cxx

@@ -20,7 +20,7 @@ InterrogateDatabase *InterrogateDatabase::_global_ptr = NULL;
 int InterrogateDatabase::_file_major_version = 0;
 int InterrogateDatabase::_file_minor_version = 0;
 int InterrogateDatabase::_current_major_version = 3;
-int InterrogateDatabase::_current_minor_version = 1;
+int InterrogateDatabase::_current_minor_version = 2;
 
 /**
  *

+ 36 - 0
dtool/src/interrogatedb/interrogateElement.I

@@ -24,6 +24,8 @@ InterrogateElement(InterrogateModuleDef *def) :
   _setter = 0;
   _has_function = 0;
   _clear_function = 0;
+  _del_function = 0;
+  _length_function = 0;
 }
 
 /**
@@ -48,6 +50,8 @@ operator = (const InterrogateElement &copy) {
   _setter = copy._setter;
   _has_function = copy._has_function;
   _clear_function = copy._clear_function;
+  _del_function = copy._del_function;
+  _length_function = copy._length_function;
 }
 
 /**
@@ -163,6 +167,38 @@ get_clear_function() const {
   return _clear_function;
 }
 
+/**
+ *
+ */
+INLINE bool InterrogateElement::
+has_del_function() const {
+  return (_flags & F_has_del_function) != 0;
+}
+
+/**
+ *
+ */
+INLINE FunctionIndex InterrogateElement::
+get_del_function() const {
+  return _del_function;
+}
+
+/**
+ *
+ */
+INLINE bool InterrogateElement::
+is_sequence() const {
+  return (_flags & F_sequence) != 0;
+}
+
+/**
+ *
+ */
+INLINE FunctionIndex InterrogateElement::
+get_length_function() const {
+  return _length_function;
+}
+
 
 INLINE ostream &
 operator << (ostream &out, const InterrogateElement &element) {

+ 10 - 1
dtool/src/interrogatedb/interrogateElement.cxx

@@ -27,7 +27,9 @@ output(ostream &out) const {
       << _getter << " "
       << _setter << " "
       << _has_function << " "
-      << _clear_function << " ";
+      << _clear_function << " "
+      << _del_function << " "
+      << _length_function << " ";
   idf_output_string(out, _scoped_name);
   idf_output_string(out, _comment, '\n');
 }
@@ -41,6 +43,9 @@ input(istream &in) {
   in >> _flags >> _type >> _getter >> _setter;
   if (InterrogateDatabase::get_file_minor_version() >= 1) {
     in >> _has_function >> _clear_function;
+    if (InterrogateDatabase::get_file_minor_version() >= 2) {
+      in >> _del_function >> _length_function;
+    }
   }
   idf_input_string(in, _scoped_name);
   idf_input_string(in, _comment);
@@ -55,4 +60,8 @@ remap_indices(const IndexRemapper &remap) {
   _type = remap.map_from(_type);
   _getter = remap.map_from(_getter);
   _setter = remap.map_from(_setter);
+  _has_function = remap.map_from(_has_function);
+  _clear_function = remap.map_from(_clear_function);
+  _del_function = remap.map_from(_del_function);
+  _length_function = remap.map_from(_length_function);
 }

+ 9 - 0
dtool/src/interrogatedb/interrogateElement.h

@@ -47,6 +47,10 @@ public:
   INLINE FunctionIndex get_has_function() const;
   INLINE bool has_clear_function() const;
   INLINE FunctionIndex get_clear_function() const;
+  INLINE bool has_del_function() const;
+  INLINE FunctionIndex get_del_function() const;
+  INLINE bool is_sequence() const;
+  INLINE FunctionIndex get_length_function() const;
 
   void output(ostream &out) const;
   void input(istream &in);
@@ -60,16 +64,21 @@ private:
     F_has_setter      = 0x0004,
     F_has_has_function= 0x0008,
     F_has_clear_function= 0x0010,
+    F_has_del_function= 0x0020,
+    F_sequence        = 0x0040,
+    F_mapping         = 0x0080,
   };
 
   int _flags;
   string _scoped_name;
   string _comment;
   TypeIndex _type;
+  FunctionIndex _length_function;
   FunctionIndex _getter;
   FunctionIndex _setter;
   FunctionIndex _has_function;
   FunctionIndex _clear_function;
+  FunctionIndex _del_function;
 
   friend class InterrogateBuilder;
 };

+ 16 - 0
dtool/src/interrogatedb/py_panda.I

@@ -192,6 +192,14 @@ ALWAYS_INLINE PyObject *Dtool_WrapValue(PyObject *value) {
   return value;
 }
 
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::vector<unsigned char> &value) {
+#if PY_MAJOR_VERSION >= 3
+  return PyBytes_FromStringAndSize((char *)value.data(), (Py_ssize_t)value.size());
+#else
+  return PyString_FromStringAndSize((char *)value.data(), (Py_ssize_t)value.size());
+#endif
+}
+
 #if PY_MAJOR_VERSION >= 0x02060000
 ALWAYS_INLINE PyObject *Dtool_WrapValue(Py_buffer *value) {
   if (value == (Py_buffer *)NULL) {
@@ -201,3 +209,11 @@ ALWAYS_INLINE PyObject *Dtool_WrapValue(Py_buffer *value) {
   }
 }
 #endif
+
+template<class T1, class T2>
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::pair<T1, T2> &value) {
+  PyObject *tuple = PyTuple_New(2);
+  PyTuple_SET_ITEM(tuple, 0, Dtool_WrapValue(value.first));
+  PyTuple_SET_ITEM(tuple, 1, Dtool_WrapValue(value.second));
+  return tuple;
+}

+ 116 - 2
dtool/src/interrogatedb/py_panda.cxx

@@ -571,8 +571,19 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
     return (PyObject *)NULL;
   }
 
-  // Initialize the base class of everything.
-  Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(NULL);
+  // Initialize the types we define in py_panda.
+  static bool dtool_inited = false;
+  if (!dtool_inited) {
+    dtool_inited = true;
+
+    if (PyType_Ready(&Dtool_SequenceWrapper_Type) < 0) {
+      PyErr_SetString(PyExc_TypeError, "PyType_Ready(Dtool_SequenceWrapper)");
+      return NULL;
+    }
+
+    // Initialize the base class of everything.
+    Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(NULL);
+  }
 
   // the module level function inits....
   MethodDefmap functions;
@@ -860,4 +871,107 @@ PyObject *map_deepcopy_to_copy(PyObject *self, PyObject *args) {
   return PyObject_CallMethod(self, (char *)"__copy__", (char *)"()");
 }
 
+/**
+ * This class is returned from properties that require a settable interface,
+ * ie. something.children[i] = 3.
+ */
+static void Dtool_SequenceWrapper_dealloc(PyObject *self) {
+  Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
+  nassertv(wrap);
+  Py_DECREF(wrap->_base);
+}
+
+static Py_ssize_t Dtool_SequenceWrapper_length(PyObject *self) {
+  Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
+  nassertr(wrap, -1);
+  nassertr(wrap->_len_func, -1);
+  return wrap->_len_func(wrap->_base);
+}
+
+static PyObject *Dtool_SequenceWrapper_getitem(PyObject *self, Py_ssize_t index) {
+  Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
+  nassertr(wrap, NULL);
+  nassertr(wrap->_getitem_func, NULL);
+  return wrap->_getitem_func(wrap->_base, index);
+}
+
+static int Dtool_SequenceWrapper_setitem(PyObject *self, Py_ssize_t index, PyObject *value) {
+  Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
+  nassertr(wrap, -1);
+  nassertr(wrap->_setitem_func, -1);
+  return wrap->_setitem_func(wrap->_base, index, value);
+}
+
+static PySequenceMethods Dtool_SequenceWrapper_SequenceMethods = {
+  Dtool_SequenceWrapper_length,
+  0, // sq_concat
+  0, // sq_repeat
+  Dtool_SequenceWrapper_getitem,
+  0, // sq_slice
+  Dtool_SequenceWrapper_setitem,
+  0, // sq_ass_slice
+  0, // sq_contains
+  0, // sq_inplace_concat
+  0, // sq_inplace_repeat
+};
+
+PyTypeObject Dtool_SequenceWrapper_Type = {
+  PyVarObject_HEAD_INIT(NULL, 0)
+  "sequence wrapper",
+  sizeof(Dtool_SequenceWrapper),
+  0, // tp_itemsize
+  Dtool_SequenceWrapper_dealloc,
+  0, // tp_print
+  0, // tp_getattr
+  0, // tp_setattr
+#if PY_MAJOR_VERSION >= 3
+  0, // tp_reserved
+#else
+  0, // tp_compare
+#endif
+  0, // tp_repr
+  0, // tp_as_number
+  &Dtool_SequenceWrapper_SequenceMethods,
+  0, // tp_as_mapping
+  0, // tp_hash
+  0, // tp_call
+  0, // tp_str
+  PyObject_GenericGetAttr,
+  PyObject_GenericSetAttr,
+  0, // tp_as_buffer
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,
+  0, // tp_doc
+  0, // tp_traverse
+  0, // tp_clear
+  0, // tp_richcompare
+  0, // tp_weaklistoffset
+  0, // tp_iter
+  0, // tp_iternext
+  0, // tp_methods
+  0, // tp_members
+  0, // tp_getset
+  0, // tp_base
+  0, // tp_dict
+  0, // tp_descr_get
+  0, // tp_descr_set
+  0, // tp_dictoffset
+  0, // tp_init
+  PyType_GenericAlloc,
+  0, // tp_new
+  PyObject_Del,
+  0, // tp_is_gc
+  0, // tp_bases
+  0, // tp_mro
+  0, // tp_cache
+  0, // tp_subclasses
+  0, // tp_weaklist
+  0, // tp_del
+#if PY_VERSION_HEX >= 0x02060000
+  0, // tp_version_tag
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+  0, // tp_finalize
+#endif
+};
+
 #endif  // HAVE_PYTHON

+ 18 - 0
dtool/src/interrogatedb/py_panda.h

@@ -441,6 +441,20 @@ copy_from_copy_constructor(PyObject *self, PyObject *noargs);
 EXPCL_INTERROGATEDB PyObject *
 map_deepcopy_to_copy(PyObject *self, PyObject *args);
 
+/**
+ * This class is returned from properties that require a settable interface,
+ * ie. something.children[i] = 3.
+ */
+struct Dtool_SequenceWrapper {
+  PyObject_HEAD
+  PyObject *_base;
+  lenfunc _len_func;
+  ssizeargfunc _getitem_func;
+  ssizeobjargproc _setitem_func;
+};
+
+EXPCL_INTERROGATEDB extern PyTypeObject Dtool_SequenceWrapper_Type;
+
 /**
  * These functions convert a C++ value into the corresponding Python object.
  * This used to be generated by the code generator, but it seems more reliable
@@ -464,11 +478,15 @@ ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring *value);
 ALWAYS_INLINE PyObject *Dtool_WrapValue(char value);
 ALWAYS_INLINE PyObject *Dtool_WrapValue(wchar_t value);
 ALWAYS_INLINE PyObject *Dtool_WrapValue(PyObject *value);
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::vector<unsigned char> &value);
 
 #if PY_MAJOR_VERSION >= 0x02060000
 ALWAYS_INLINE PyObject *Dtool_WrapValue(Py_buffer *value);
 #endif
 
+template<class T1, class T2>
+ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::pair<T1, T2> &value);
+
 EXPCL_INTERROGATEDB extern struct Dtool_PyTypedObject Dtool_DTOOL_SUPER_BASE;
 EXPCL_INTERROGATEDB extern void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module);
 

+ 4 - 0
dtool/src/prc/configPage.h

@@ -44,6 +44,8 @@ PUBLISHED:
 
   INLINE bool is_special() const;
   INLINE bool is_implicit() const;
+  MAKE_PROPERTY(special, is_special);
+  MAKE_PROPERTY(implicit, is_implicit);
 
   void set_sort(int sort);
   INLINE int get_sort() const;
@@ -72,6 +74,8 @@ PUBLISHED:
   string get_string_value(size_t n) const;
   bool is_variable_used(size_t n) const;
 
+  MAKE_SEQ_PROPERTY(declarations, get_num_declarations, modify_declaration);
+
   void output(ostream &out) const;
   void output_brief_signature(ostream &out) const;
   void write(ostream &out) const;

+ 15 - 0
dtool/src/prc/configVariableCore.h

@@ -75,10 +75,25 @@ PUBLISHED:
   INLINE size_t get_num_unique_references() const;
   INLINE const ConfigDeclaration *get_unique_reference(size_t n) const;
   MAKE_SEQ(get_unique_references, get_num_unique_references, get_unique_reference);
+  MAKE_SEQ_PROPERTY(declarations, get_num_declarations, get_declaration);
 
   void output(ostream &out) const;
   void write(ostream &out) const;
 
+  MAKE_PROPERTY(name, get_name);
+  MAKE_PROPERTY(used, is_used);
+  MAKE_PROPERTY(closed, is_closed);
+  MAKE_PROPERTY(trust_level, get_trust_level);
+  MAKE_PROPERTY(dynamic, is_dynamic);
+
+  MAKE_PROPERTY(value_type, get_value_type, set_value_type);
+  MAKE_PROPERTY(description, get_description, set_description);
+  MAKE_PROPERTY(default_value, get_default_value, set_default_value);
+
+  MAKE_SEQ_PROPERTY(references, get_num_references, get_reference);
+  MAKE_SEQ_PROPERTY(trusted_references, get_num_trusted_references, get_trusted_reference);
+  MAKE_SEQ_PROPERTY(unique_references, get_num_unique_references, get_unique_reference);
+
 private:
   void add_declaration(ConfigDeclaration *decl);
   void remove_declaration(ConfigDeclaration *decl);

+ 2 - 0
dtool/src/prc/configVariableManager.h

@@ -48,6 +48,8 @@ PUBLISHED:
   string get_variable_name(size_t n) const;
   bool is_variable_used(size_t n) const;
 
+  MAKE_SEQ_PROPERTY(variables, get_num_variables, get_variable);
+
   void output(ostream &out) const;
   void write(ostream &out) const;
 

+ 1 - 0
dtool/src/prc/configVariableSearchPath.h

@@ -68,6 +68,7 @@ PUBLISHED:
   INLINE size_t get_num_directories() const;
   INLINE const Filename &get_directory(size_t n) const;
   MAKE_SEQ(get_directories, get_num_directories, get_directory);
+  MAKE_SEQ_PROPERTY(directories, get_num_directories, get_directory);
 
   INLINE Filename find_file(const Filename &filename) const;
   INLINE size_t find_all_files(const Filename &filename,

+ 23 - 0
dtool/src/prc/encryptStream.I

@@ -109,6 +109,29 @@ close() {
   return *this;
 }
 
+/**
+ * Returns the encryption algorithm that was read from the stream.
+ */
+INLINE const string &OEncryptStream::
+get_algorithm() const {
+  return _buf.get_algorithm();
+}
+
+/**
+ * Returns the encryption key length, in bits, that was read from the stream.
+ */
+INLINE int OEncryptStream::
+get_key_length() const {
+  return _buf.get_key_length();
+}
+
+/**
+ * Returns the value that was was read from the stream.
+ */
+INLINE int OEncryptStream::
+get_iteration_count() const {
+  return _buf.get_iteration_count();
+}
 
 /**
  * Specifies the encryption algorithm that should be used for future calls to

+ 14 - 0
dtool/src/prc/encryptStream.h

@@ -49,6 +49,10 @@ PUBLISHED:
   INLINE int get_key_length() const;
   INLINE int get_iteration_count() const;
 
+  MAKE_PROPERTY(algorithm, get_algorithm);
+  MAKE_PROPERTY(key_length, get_key_length);
+  MAKE_PROPERTY(iteration_count, get_iteration_count);
+
 private:
   EncryptStreamBuf _buf;
 };
@@ -76,10 +80,20 @@ PUBLISHED:
                               const string &password);
   INLINE OEncryptStream &close();
 
+public:
+  INLINE const string &get_algorithm() const;
+  INLINE int get_key_length() const;
+  INLINE int get_iteration_count() const;
+
+PUBLISHED:
   INLINE void set_algorithm(const string &algorithm);
   INLINE void set_key_length(int key_length);
   INLINE void set_iteration_count(int iteration_count);
 
+  MAKE_PROPERTY(algorithm, get_algorithm, set_algorithm);
+  MAKE_PROPERTY(key_length, get_key_length, set_key_length);
+  MAKE_PROPERTY(iteration_count, get_iteration_count, set_iteration_count);
+
 private:
   EncryptStreamBuf _buf;
 };

+ 1 - 0
dtool/src/prc/notifyCategory.h

@@ -74,6 +74,7 @@ PUBLISHED:
   size_t get_num_children() const;
   NotifyCategory *get_child(size_t i) const;
   MAKE_SEQ(get_children, get_num_children, get_child);
+  MAKE_SEQ_PROPERTY(children, get_num_children, get_child);
 
   static void set_server_delta(long delta);
 

+ 1 - 0
dtool/src/prc/streamReader.h

@@ -34,6 +34,7 @@ PUBLISHED:
   INLINE ~StreamReader();
 
   INLINE istream *get_istream() const;
+  MAKE_PROPERTY(istream, get_istream);
 
   BLOCKING INLINE bool get_bool();
   BLOCKING INLINE PN_int8 get_int8();

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

@@ -53,6 +53,7 @@ PUBLISHED:
   ~IStreamWrapper();
 
   INLINE istream *get_istream() const;
+  MAKE_PROPERTY(istream, get_istream);
 
 public:
   void read(char *buffer, streamsize num_bytes);
@@ -79,6 +80,7 @@ PUBLISHED:
   ~OStreamWrapper();
 
   INLINE ostream *get_ostream() const;
+  MAKE_PROPERTY(ostream, get_ostream);
 
 public:
   void write(const char *buffer, streamsize num_bytes);
@@ -114,6 +116,7 @@ PUBLISHED:
   ~StreamWrapper();
 
   INLINE iostream *get_iostream() const;
+  MAKE_PROPERTY(iostream, get_iostream);
 
 private:
   iostream *_iostream;

+ 1 - 0
dtool/src/prc/streamWriter.h

@@ -36,6 +36,7 @@ PUBLISHED:
   INLINE ~StreamWriter();
 
   INLINE ostream *get_ostream() const;
+  MAKE_PROPERTY(ostream, get_ostream);
 
   BLOCKING INLINE void add_bool(bool value);
   BLOCKING INLINE void add_int8(PN_int8 value);

+ 2 - 0
panda/src/chan/animGroup.h

@@ -44,6 +44,8 @@ PUBLISHED:
   AnimGroup *get_child(int n) const;
   MAKE_SEQ(get_children, get_num_children, get_child);
 
+  MAKE_SEQ_PROPERTY(children, get_num_children, get_child);
+
   AnimGroup *get_child_named(const string &name) const;
   AnimGroup *find_child(const string &name) const;
   void sort_descendants();

+ 6 - 0
panda/src/chan/partBundle.h

@@ -113,6 +113,12 @@ PUBLISHED:
   INLINE PartBundleNode *get_node(int n) const;
   MAKE_SEQ(get_nodes, get_num_nodes, get_node);
 
+  MAKE_PROPERTY(blend_type, get_blend_type, set_blend_type);
+  MAKE_PROPERTY(anim_blend_flag, get_anim_blend_flag, set_anim_blend_flag);
+  MAKE_PROPERTY(frame_blend_flag, get_frame_blend_flag, set_frame_blend_flag);
+  MAKE_PROPERTY(root_xform, get_root_xform, set_root_xform);
+  MAKE_SEQ_PROPERTY(nodes, get_num_nodes, get_node);
+
   void clear_control_effects();
   INLINE void set_control_effect(AnimControl *control, PN_stdfloat effect);
   INLINE PN_stdfloat get_control_effect(AnimControl *control) const;

+ 2 - 0
panda/src/chan/partBundleHandle.h

@@ -38,6 +38,8 @@ PUBLISHED:
   INLINE PartBundle *get_bundle();
   INLINE void set_bundle(PartBundle *bundle);
 
+  MAKE_PROPERTY(bundle, get_bundle, set_bundle);
+
 private:
   PT(PartBundle) _bundle;
 };

+ 3 - 0
panda/src/chan/partBundleNode.h

@@ -54,6 +54,9 @@ PUBLISHED:
   INLINE PartBundleHandle *get_bundle_handle(int n) const;
   MAKE_SEQ(get_bundle_handles, get_num_bundles, get_bundle_handle);
 
+  MAKE_SEQ_PROPERTY(bundles, get_num_bundles, get_bundle);
+  MAKE_SEQ_PROPERTY(bundle_handles, get_num_bundles, get_bundle_handle);
+
 protected:
   void add_bundle(PartBundle *bundle);
   void add_bundle_handle(PartBundleHandle *handle);

+ 1 - 0
panda/src/chan/partGroup.h

@@ -70,6 +70,7 @@ PUBLISHED:
   int get_num_children() const;
   PartGroup *get_child(int n) const;
   MAKE_SEQ(get_children, get_num_children, get_child);
+  MAKE_SEQ_PROPERTY(children, get_num_children, get_child);
 
   PartGroup *get_child_named(const string &name) const;
   PartGroup *find_child(const string &name) const;

+ 4 - 1
panda/src/collide/collisionFloorMesh.h

@@ -40,7 +40,6 @@ public:
   } TriangleIndices;
 
 PUBLISHED:
-
   INLINE CollisionFloorMesh();
 
   INLINE void add_vertex(const LPoint3 &vert);
@@ -55,6 +54,10 @@ PUBLISHED:
 
   virtual LPoint3 get_collision_origin() const;
 
+PUBLISHED:
+  MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex);
+  MAKE_SEQ_PROPERTY(triangles, get_num_triangles, get_triangle);
+
 public:
   CollisionFloorMesh(const CollisionFloorMesh &copy);
   virtual CollisionSolid *make_copy();

+ 4 - 0
panda/src/collide/collisionHandlerEvent.h

@@ -60,6 +60,10 @@ PUBLISHED:
   INLINE string get_out_pattern(int n) const;
   MAKE_SEQ(get_out_patterns, get_num_out_patterns, get_out_pattern);
 
+  MAKE_SEQ_PROPERTY(in_patterns, get_num_in_patterns, get_in_pattern);
+  MAKE_SEQ_PROPERTY(again_patterns, get_num_again_patterns, get_out_pattern);
+  MAKE_SEQ_PROPERTY(out_patterns, get_num_out_patterns, get_out_pattern);
+
   void clear();
   void flush();
 

+ 1 - 0
panda/src/collide/collisionHandlerQueue.h

@@ -40,6 +40,7 @@ PUBLISHED:
   int get_num_entries() const;
   CollisionEntry *get_entry(int n) const;
   MAKE_SEQ(get_entries, get_num_entries, get_entry);
+  MAKE_SEQ_PROPERTY(entries, get_num_entries, get_entry);
 
   void output(ostream &out) const;
   void write(ostream &out, int indent_level = 0) const;

+ 1 - 0
panda/src/collide/collisionNode.h

@@ -68,6 +68,7 @@ PUBLISHED:
   INLINE void set_solid(int n, CollisionSolid *solid);
   INLINE void remove_solid(int n);
   INLINE int add_solid(const CollisionSolid *solid);
+  MAKE_SEQ_PROPERTY(solids, get_num_solids, get_solid, set_solid, remove_solid);
 
   INLINE int get_collider_sort() const;
   INLINE void set_collider_sort(int sort);

+ 1 - 0
panda/src/collide/collisionPolygon.h

@@ -60,6 +60,7 @@ PUBLISHED:
   bool is_concave() const;
 
 PUBLISHED:
+  MAKE_SEQ_PROPERTY(points, get_num_points, get_point);
   MAKE_PROPERTY(valid, is_valid);
   MAKE_PROPERTY(concave, is_concave);
 

+ 1 - 0
panda/src/collide/collisionTraverser.h

@@ -60,6 +60,7 @@ PUBLISHED:
   MAKE_SEQ(get_colliders, get_num_colliders, get_collider);
   CollisionHandler *get_handler(const NodePath &collider) const;
   void clear_colliders();
+  MAKE_SEQ_PROPERTY(colliders, get_num_colliders, get_collider);
 
   void traverse(const NodePath &root);
 

+ 1 - 0
panda/src/display/graphicsEngine.h

@@ -101,6 +101,7 @@ PUBLISHED:
   int get_num_windows() const;
   GraphicsOutput *get_window(int n) const;
   MAKE_SEQ(get_windows, get_num_windows, get_window);
+  MAKE_SEQ_PROPERTY(windows, get_num_windows, get_window);
 
   BLOCKING void render_frame();
   BLOCKING void open_windows();

+ 3 - 0
panda/src/display/graphicsOutput.h

@@ -195,6 +195,7 @@ PUBLISHED:
   INLINE void set_child_sort(int child_sort);
   INLINE void clear_child_sort();
   INLINE int get_child_sort() const;
+  MAKE_PROPERTY(child_sort, get_child_sort, set_child_sort);
 
   INLINE void trigger_copy();
 
@@ -216,10 +217,12 @@ PUBLISHED:
   int get_num_display_regions() const;
   PT(DisplayRegion) get_display_region(int n) const;
   MAKE_SEQ(get_display_regions, get_num_display_regions, get_display_region);
+  MAKE_SEQ_PROPERTY(display_regions, get_num_display_regions, get_display_region);
 
   int get_num_active_display_regions() const;
   PT(DisplayRegion) get_active_display_region(int n) const;
   MAKE_SEQ(get_active_display_regions, get_num_active_display_regions, get_active_display_region);
+  MAKE_SEQ_PROPERTY(active_display_regions, get_num_active_display_regions, get_active_display_region);
 
   GraphicsOutput *make_texture_buffer(
       const string &name, int x_size, int y_size,

+ 1 - 0
panda/src/display/graphicsPipeSelection.h

@@ -39,6 +39,7 @@ PUBLISHED:
   int get_num_pipe_types() const;
   TypeHandle get_pipe_type(int n) const;
   MAKE_SEQ(get_pipe_types, get_num_pipe_types, get_pipe_type);
+  MAKE_SEQ_PROPERTY(pipe_types, get_num_pipe_types, get_pipe_type);
   void print_pipe_types() const;
 
   PT(GraphicsPipe) make_pipe(const string &type_name,

+ 2 - 0
panda/src/egg/eggCompositePrimitive.h

@@ -38,6 +38,8 @@ PUBLISHED:
   MAKE_SEQ(get_components, get_num_components, get_component);
   INLINE void set_component(int i, const EggAttributes *attrib);
 
+  MAKE_PROPERTY(components, get_num_components, get_component, set_component);
+
   INLINE bool triangulate_into(EggGroupNode *container) const;
   PT(EggCompositePrimitive) triangulate_in_place();
 

+ 39 - 0
panda/src/egg/eggGroup.h

@@ -284,6 +284,45 @@ PUBLISHED:
 
   INLINE bool has_scrolling_uvs();
 
+  MAKE_PROPERTY(group_type, get_group_type, set_group_type);
+  MAKE_PROPERTY(billboard_type, get_billboard_type, set_billboard_type);
+  MAKE_PROPERTY2(billboard_center, has_billboard_center, get_billboard_center,
+                                   set_billboard_center, clear_billboard_center);
+  MAKE_PROPERTY(cs_type, get_cs_type, set_cs_type);
+  MAKE_PROPERTY(collide_flags, get_collide_flags, set_collide_flags);
+  MAKE_PROPERTY(collision_name, get_collision_name, set_collision_name);
+  MAKE_PROPERTY(dcs_type, get_dcs_type, set_dcs_type);
+  MAKE_PROPERTY(dart_type, get_dart_type, set_dart_type);
+  MAKE_PROPERTY(switch_flag, get_switch_flag, set_switch_flag);
+  MAKE_PROPERTY(switch_fps, get_switch_fps, set_switch_fps);
+  MAKE_SEQ_PROPERTY(object_types, get_num_object_types, get_object_type);
+  MAKE_PROPERTY(model_flag, get_model_flag, set_model_flag);
+  MAKE_PROPERTY(texlist_flag, get_texlist_flag, set_texlist_flag);
+  MAKE_PROPERTY(nofog_flag, get_nofog_flag, set_nofog_flag);
+  MAKE_PROPERTY(decal_flag, get_decal_flag, set_decal_flag);
+  MAKE_PROPERTY(direct_flag, get_direct_flag, set_direct_flag);
+  MAKE_PROPERTY(portal_flag, get_portal_flag, set_portal_flag);
+  MAKE_PROPERTY(occluder_flag, get_occluder_flag, set_occluder_flag);
+  MAKE_PROPERTY2(indexed_flag, has_indexed_flag, get_indexed_flag,
+                               set_indexed_flag, clear_indexed_flag);
+  MAKE_PROPERTY2(collide_mask, has_collide_mask, get_collide_mask,
+                               set_collide_mask, clear_collide_mask);
+  MAKE_PROPERTY2(from_collide_mask, has_from_collide_mask, get_from_collide_mask,
+                                    set_from_collide_mask, clear_from_collide_mask);
+  MAKE_PROPERTY2(into_collide_mask, has_into_collide_mask, get_into_collide_mask,
+                                    set_into_collide_mask, clear_into_collide_mask);
+  MAKE_PROPERTY(blend_mode, get_blend_mode, set_blend_mode);
+  MAKE_PROPERTY(blend_operand_a, get_blend_operand_a, set_blend_operand_a);
+  MAKE_PROPERTY(blend_operand_b, get_blend_operand_b, set_blend_operand_b);
+  MAKE_PROPERTY2(blend_color, has_blend_color, get_blend_color,
+                              set_blend_color, clear_blend_color);
+  MAKE_PROPERTY2(lod, has_lod, get_lod, set_lod, clear_lod);
+  MAKE_PROPERTY(default_pose, get_default_pose, set_default_pose);
+  MAKE_PROPERTY(scroll_u, get_scroll_u, set_scroll_u);
+  MAKE_PROPERTY(scroll_v, get_scroll_v, set_scroll_v);
+  MAKE_PROPERTY(scroll_w, get_scroll_w, set_scroll_w);
+  MAKE_PROPERTY(scroll_r, get_scroll_r, set_scroll_r);
+
 public:
   INLINE TagData::const_iterator tag_begin() const;
   INLINE TagData::const_iterator tag_end() const;

+ 5 - 0
panda/src/egg/eggNurbsCurve.h

@@ -50,6 +50,11 @@ PUBLISHED:
 
   virtual void write(ostream &out, int indent_level) const;
 
+  MAKE_PROPERTY(order, get_order, set_order);
+  MAKE_PROPERTY(degree, get_degree);
+  MAKE_PROPERTY(closed, is_closed);
+  MAKE_SEQ_PROPERTY(knots, get_num_knots, get_knot, set_knot);
+
 private:
   typedef vector_double Knots;
   Knots _knots;

+ 5 - 5
panda/src/egg/eggPrimitive.I

@@ -354,7 +354,7 @@ clear() {
 /**
  *
  */
-INLINE int EggPrimitive::
+INLINE size_t EggPrimitive::
 get_num_vertices() const {
   return size();
 }
@@ -365,8 +365,8 @@ get_num_vertices() const {
  * mess with the iterators.
  */
 INLINE void EggPrimitive::
-set_vertex(int index, EggVertex *vertex) {
-  nassertv(index >= 0 && index < (int)size());
+set_vertex(size_t index, EggVertex *vertex) {
+  nassertv(index < size());
   replace(begin() + index, vertex);
 }
 
@@ -374,8 +374,8 @@ set_vertex(int index, EggVertex *vertex) {
  * Returns a particular index based on its index number.
  */
 INLINE EggVertex *EggPrimitive::
-get_vertex(int index) const {
-  nassertr(index >= 0 && index < (int)size(), NULL);
+get_vertex(size_t index) const {
+  nassertr(index < size(), NULL);
   return *(begin() + index);
 }
 

+ 13 - 0
panda/src/egg/eggPrimitive.cxx

@@ -684,6 +684,19 @@ remove_vertex(EggVertex *vertex) {
   }
 }
 
+/**
+ * Removes the indicated vertex from the primitive.
+ */
+void EggPrimitive::
+remove_vertex(size_t index) {
+  nassertv(index < size());
+  iterator i = begin() + index;
+
+  // erase() calls prepare_remove_vertex().
+  erase(i);
+
+  test_vref_integrity();
+}
 
 /**
  * Replaces the current primitive's list of vertices with a copy of the list

+ 15 - 3
panda/src/egg/eggPrimitive.h

@@ -105,6 +105,14 @@ PUBLISHED:
   INLINE void set_bface_flag(bool flag);
   INLINE bool get_bface_flag() const;
 
+  MAKE_PROPERTY(sort_name, get_sort_name);
+  MAKE_PROPERTY(shading, get_shading);
+  MAKE_PROPERTY(connected_shading, get_connected_shading);
+
+  MAKE_SEQ_PROPERTY(textures, get_num_textures, get_texture);
+  MAKE_PROPERTY2(material, has_material, get_material, set_material, clear_material);
+  MAKE_PROPERTY(bface_flag, get_bface_flag, set_bface_flag);
+
   void copy_attributes(const EggAttributes &other);
   void copy_attributes(const EggPrimitive &other);
 
@@ -166,16 +174,20 @@ PUBLISHED:
 
   EggVertex *add_vertex(EggVertex *vertex);
   EggVertex *remove_vertex(EggVertex *vertex);
+  void remove_vertex(size_t index);
   void copy_vertices(const EggPrimitive &other);
 
   // These are shorthands if you don't want to use the iterators.
-  INLINE int get_num_vertices() const;
-  INLINE void set_vertex(int index, EggVertex *vertex);
-  INLINE EggVertex *get_vertex(int index) const;
+  INLINE size_t get_num_vertices() const;
+  INLINE void set_vertex(size_t index, EggVertex *vertex);
+  INLINE EggVertex *get_vertex(size_t index) const;
   MAKE_SEQ(get_vertices, get_num_vertices, get_vertex);
 
   INLINE EggVertexPool *get_pool() const;
 
+  MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex, set_vertex, remove_vertex);
+  MAKE_PROPERTY(pool, get_pool);
+
   virtual void write(ostream &out, int indent_level) const=0;
 
 #ifdef _DEBUG

+ 4 - 0
panda/src/event/asyncTaskManager.h

@@ -82,9 +82,13 @@ PUBLISHED:
   AsyncTaskCollection get_tasks() const;
   AsyncTaskCollection get_active_tasks() const;
   AsyncTaskCollection get_sleeping_tasks() const;
+  MAKE_PROPERTY(tasks, get_tasks);
+  MAKE_PROPERTY(active_tasks, get_active_tasks);
+  MAKE_PROPERTY(sleeping_tasks, get_sleeping_tasks);
 
   void poll();
   double get_next_wake_time() const;
+  MAKE_PROPERTY(next_wake_time, get_next_wake_time);
 
   virtual void output(ostream &out) const;
   virtual void write(ostream &out, int indent_level = 0) const;

+ 4 - 0
panda/src/event/event.h

@@ -55,6 +55,10 @@ PUBLISHED:
 
   void output(ostream &out) const;
 
+  MAKE_PROPERTY(name, get_name, set_name);
+  MAKE_SEQ_PROPERTY(parameters, get_num_parameters, get_parameter);
+  MAKE_PROPERTY2(receiver, has_receiver, get_receiver, set_receiver, clear_receiver);
+
 protected:
   typedef pvector<EventParameter> ParameterList;
   ParameterList _parameters;

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

@@ -61,6 +61,7 @@ PUBLISHED:
   int get_num_mounts() const;
   PT(VirtualFileMount) get_mount(int n) const;
   MAKE_SEQ(get_mounts, get_num_mounts, get_mount);
+  MAKE_SEQ_PROPERTY(mounts, get_num_mounts, get_mount);
 
   BLOCKING bool chdir(const Filename &new_directory);
   BLOCKING Filename get_cwd() const;

+ 1 - 0
panda/src/gobj/geom.h

@@ -95,6 +95,7 @@ PUBLISHED:
   void add_primitive(const GeomPrimitive *primitive);
   void remove_primitive(int i);
   void clear_primitives();
+  MAKE_SEQ_PROPERTY(primitives, get_num_primitives, get_primitive, set_primitive, remove_primitive);
 
   INLINE PT(Geom) decompose() const;
   INLINE PT(Geom) doubleside() const;

+ 1 - 0
panda/src/gobj/geomVertexArrayFormat.h

@@ -104,6 +104,7 @@ PUBLISHED:
   INLINE int get_num_columns() const;
   INLINE const GeomVertexColumn *get_column(int i) const;
   MAKE_SEQ(get_columns, get_num_columns, get_column);
+  MAKE_SEQ_PROPERTY(columns, get_num_columns, get_column);
 
   const GeomVertexColumn *get_column(const InternalName *name) const;
   const GeomVertexColumn *get_column(int start_byte, int num_bytes) const;

+ 1 - 0
panda/src/gobj/geomVertexData.h

@@ -110,6 +110,7 @@ PUBLISHED:
   MAKE_SEQ(get_arrays, get_num_arrays, get_array);
   INLINE PT(GeomVertexArrayData) modify_array(int i);
   INLINE void set_array(int i, const GeomVertexArrayData *array);
+  MAKE_SEQ_PROPERTY(arrays, get_num_arrays, get_array, set_array);
 
   INLINE const TransformTable *get_transform_table() const;
   void set_transform_table(const TransformTable *table);

+ 5 - 0
panda/src/gobj/geomVertexFormat.h

@@ -120,6 +120,11 @@ PUBLISHED:
   MAKE_SEQ(get_morph_bases, get_num_morphs, get_morph_base);
   MAKE_SEQ(get_morph_deltas, get_num_morphs, get_morph_delta);
 
+  MAKE_SEQ_PROPERTY(arrays, get_num_arrays, get_array, set_array, remove_array);
+  MAKE_SEQ_PROPERTY(columns, get_num_columns, get_column);
+  MAKE_SEQ_PROPERTY(points, get_num_points, get_point);
+  MAKE_SEQ_PROPERTY(vectors, get_num_vectors, get_vector);
+
   void output(ostream &out) const;
   void write(ostream &out, int indent_level = 0) const;
   void write_with_data(ostream &out, int indent_level,

+ 7 - 1
panda/src/gobj/transformBlendTable.h

@@ -55,7 +55,7 @@ PUBLISHED:
   INLINE size_t get_num_blends() const;
   INLINE const TransformBlend &get_blend(size_t n) const;
   MAKE_SEQ(get_blends, get_num_blends, get_blend);
-  INLINE UpdateSeq get_modified(Thread *current_thread) const;
+  INLINE UpdateSeq get_modified(Thread *current_thread = Thread::get_current_thread()) const;
 
   void set_blend(size_t n, const TransformBlend &blend);
   void remove_blend(size_t n);
@@ -70,6 +70,12 @@ PUBLISHED:
 
   void write(ostream &out, int indent_level) const;
 
+  MAKE_SEQ_PROPERTY(blends, get_num_blends, get_blend, set_blend, remove_blend);
+  MAKE_PROPERTY(modified, get_modified);
+  MAKE_PROPERTY(num_transforms, get_num_transforms);
+  MAKE_PROPERTY(max_simultaneous_transforms, get_max_simultaneous_transforms);
+  MAKE_PROPERTY(rows, get_rows, set_rows);
+
 private:
   class CData;
 

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

@@ -48,7 +48,7 @@ PUBLISHED:
   INLINE size_t get_num_transforms() const;
   INLINE const VertexTransform *get_transform(size_t n) const;
   MAKE_SEQ(get_transforms, get_num_transforms, get_transform);
-  INLINE UpdateSeq get_modified(Thread *current_thread) const;
+  INLINE UpdateSeq get_modified(Thread *current_thread = Thread::get_current_thread()) const;
 
   void set_transform(size_t n, const VertexTransform *transform);
   void remove_transform(size_t n);
@@ -56,6 +56,10 @@ PUBLISHED:
 
   void write(ostream &out) const;
 
+  MAKE_PROPERTY(registered, is_registered);
+  MAKE_PROPERTY(modified, get_modified);
+  MAKE_SEQ_PROPERTY(transforms, get_num_transforms, get_transform, set_transform, remove_transform);
+
 private:
   void do_register();
   void do_unregister();

+ 2 - 0
panda/src/linmath/lmatrix3_src.h

@@ -86,6 +86,8 @@ PUBLISHED:
   INLINE_LINMATH FLOATNAME(LVecBase3) get_col(int col) const;
   MAKE_SEQ(get_rows, size, get_row);
   MAKE_SEQ(get_cols, size, get_col);
+  MAKE_SEQ_PROPERTY(rows, size, get_row);
+  MAKE_SEQ_PROPERTY(cols, size, get_col);
 
   INLINE_LINMATH FLOATNAME(LVecBase2) get_row2(int row) const;
   INLINE_LINMATH FLOATNAME(LVecBase2) get_col2(int col) const;

+ 2 - 0
panda/src/linmath/lmatrix4_src.h

@@ -99,6 +99,8 @@ PUBLISHED:
   MAKE_SEQ(get_rows, size, get_row);
   MAKE_SEQ(get_cols, size, get_col);
   MAKE_SEQ(get_row3s, size, get_row3);
+  MAKE_SEQ_PROPERTY(rows, size, get_row);
+  MAKE_SEQ_PROPERTY(cols, size, get_col);
 
   // these versions inline better
   INLINE_LINMATH void get_row(FLOATNAME(LVecBase4) &result_vec, int row) const;

+ 3 - 0
panda/src/mathutil/boundingBox.h

@@ -53,6 +53,9 @@ PUBLISHED:
   INLINE_MATHUTIL LPlane get_plane(int n) const;
   MAKE_SEQ(get_planes, get_num_planes, get_plane);
 
+  MAKE_SEQ_PROPERTY(points, get_num_points, get_point);
+  MAKE_SEQ_PROPERTY(planes, get_num_planes, get_plane);
+
   INLINE_MATHUTIL void set_min_max(const LPoint3 &min, const LPoint3 &max);
 
 public:

+ 3 - 0
panda/src/mathutil/boundingHexahedron.h

@@ -62,6 +62,9 @@ PUBLISHED:
   INLINE_MATHUTIL LPlane get_plane(int n) const;
   MAKE_SEQ(get_planes, get_num_planes, get_plane);
 
+  MAKE_SEQ_PROPERTY(points, get_num_points, get_point);
+  MAKE_SEQ_PROPERTY(planes, get_num_planes, get_plane);
+
 public:
   virtual const BoundingHexahedron *as_bounding_hexahedron() const;
 

+ 1 - 0
panda/src/mathutil/intersectionBoundingVolume.h

@@ -47,6 +47,7 @@ PUBLISHED:
   INLINE_MATHUTIL int get_num_components() const;
   INLINE_MATHUTIL const GeometricBoundingVolume *get_component(int n) const;
   MAKE_SEQ(get_components, get_num_components, get_component);
+  MAKE_SEQ_PROPERTY(components, get_num_components, get_component);
 
   void clear_components();
   void add_component(const GeometricBoundingVolume *component);

+ 1 - 0
panda/src/mathutil/triangulator.h

@@ -40,6 +40,7 @@ PUBLISHED:
   INLINE int get_num_vertices() const;
   INLINE const LPoint2d &get_vertex(int n) const;
   MAKE_SEQ(get_vertices, get_num_vertices, get_vertex);
+  MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex);
 
   void clear_polygon();
   void add_polygon_vertex(int index);

+ 3 - 0
panda/src/mathutil/triangulator3.h

@@ -40,6 +40,9 @@ PUBLISHED:
   void triangulate();
   INLINE const LPlaned &get_plane() const;
 
+  MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex);
+  MAKE_PROPERTY(plane, get_plane);
+
 private:
   typedef pvector<LPoint3d> Vertices3;
   Vertices3 _vertices3;

+ 1 - 0
panda/src/mathutil/unionBoundingVolume.h

@@ -46,6 +46,7 @@ PUBLISHED:
   INLINE_MATHUTIL int get_num_components() const;
   INLINE_MATHUTIL const GeometricBoundingVolume *get_component(int n) const;
   MAKE_SEQ(get_components, get_num_components, get_component);
+  MAKE_SEQ_PROPERTY(components, get_num_components, get_component);
 
   void clear_components();
   void add_component(const GeometricBoundingVolume *component);

+ 4 - 0
panda/src/movies/microphoneAudio.h

@@ -34,6 +34,10 @@ class EXPCL_PANDA_MOVIES MicrophoneAudio : public MovieAudio {
   INLINE int get_channels() const;
   INLINE int get_rate() const;
 
+  MAKE_SEQ_PROPERTY(options, get_num_options, get_option);
+  MAKE_PROPERTY(channels, get_channels);
+  MAKE_PROPERTY(rate, get_rate);
+
   virtual PT(MovieAudioCursor) open() = 0;
 
 public:

+ 3 - 0
panda/src/net/connectionManager.h

@@ -108,6 +108,9 @@ PUBLISHED:
   const Interface &get_interface(int n);
   MAKE_SEQ(get_interfaces, get_num_interfaces, get_interface);
 
+  MAKE_PROPERTY(host_name, get_host_name);
+  MAKE_SEQ_PROPERTY(interfaces, get_num_interfaces, get_interface);
+
 protected:
   void new_connection(const PT(Connection) &connection);
   virtual void flush_read_connection(Connection *connection);

+ 5 - 0
panda/src/parametrics/nurbsSurfaceEvaluator.h

@@ -79,6 +79,11 @@ PUBLISHED:
 
   void output(ostream &out) const;
 
+  MAKE_PROPERTY(u_order, get_u_order, set_u_order);
+  MAKE_PROPERTY(v_order, get_v_order, set_v_order);
+  MAKE_SEQ_PROPERTY(u_knots, get_num_u_knots, get_u_knot, set_u_knot);
+  MAKE_SEQ_PROPERTY(v_knots, get_num_v_knots, get_v_knot, set_v_knot);
+
 public:
   typedef epvector<LVecBase4> Vert4Array;
   typedef pvector<LPoint3> Vert3Array;

+ 15 - 0
panda/src/parametrics/parametricCurveCollection.cxx

@@ -87,6 +87,7 @@ remove_curve(ParametricCurve *curve) {
   return true;
 }
 
+
 /**
  * Removes the indicated ParametricCurve from the collection, by its index
  * number.
@@ -100,6 +101,20 @@ remove_curve(int index) {
   redraw();
 }
 
+
+/**
+ * Replaces the indicated ParametricCurve from the collection, by its index
+ * number.
+ */
+void ParametricCurveCollection::
+set_curve(int index, ParametricCurve *curve) {
+  nassertv(index >= 0 && index < (int)_curves.size());
+  prepare_remove_curve(_curves[index]);
+  prepare_add_curve(curve);
+  _curves[index] = curve;
+  redraw();
+}
+
 /**
  * Returns true if the indicated ParametricCurve appears in this collection,
  * false otherwise.

+ 8 - 0
panda/src/parametrics/parametricCurveCollection.h

@@ -44,6 +44,7 @@ PUBLISHED:
   int add_curves(PandaNode *node);
   bool remove_curve(ParametricCurve *curve);
   void remove_curve(int index);
+  void set_curve(int index, ParametricCurve *curve);
   bool has_curve(ParametricCurve *curve) const;
   void clear();
   void clear_timewarps();
@@ -61,6 +62,13 @@ PUBLISHED:
 
   INLINE PN_stdfloat get_max_t() const;
 
+  MAKE_SEQ_PROPERTY(curves, get_num_curves, get_curve, set_curve, remove_curve);
+  MAKE_PROPERTY(xyz_curve, get_xyz_curve);
+  MAKE_PROPERTY(hpr_curve, get_hpr_curve);
+  MAKE_PROPERTY(default_curve, get_default_curve);
+  MAKE_SEQ_PROPERTY(timewarp_curves, get_num_timewarps, get_timewarp_curve);
+  MAKE_PROPERTY(max_t, get_max_t);
+
   void make_even(PN_stdfloat max_t, PN_stdfloat segments_per_unit);
   void face_forward(PN_stdfloat segments_per_unit);
   void reset_max_t(PN_stdfloat max_t);

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

@@ -55,6 +55,7 @@ PUBLISHED:
   INLINE int get_num_display_regions() const;
   INLINE DisplayRegionBase *get_display_region(int n) const;
   MAKE_SEQ(get_display_regions, get_num_display_regions, get_display_region);
+  MAKE_SEQ_PROPERTY(display_regions, get_num_display_regions, get_display_region);
 
   INLINE void set_camera_mask(DrawMask mask);
   INLINE DrawMask get_camera_mask() const;

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

@@ -39,6 +39,7 @@ PUBLISHED:
   int get_num_types() const;
   LoaderFileType *get_type(int n) const;
   MAKE_SEQ(get_types, get_num_types, get_type);
+  MAKE_SEQ_PROPERTY(types, get_num_types, get_type);
   LoaderFileType *get_type_from_extension(const string &extension);
 
   void write(ostream &out, int indent_level = 0) const;

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

@@ -203,10 +203,13 @@ PUBLISHED:
   int get_num_nodes(Thread *current_thread = Thread::get_current_thread()) const;
   PandaNode *get_node(int index, Thread *current_thread = Thread::get_current_thread()) const;
   MAKE_SEQ(get_nodes, get_num_nodes, get_node);
+  MAKE_SEQ_PROPERTY(nodes, get_num_nodes, get_node);
   NodePath get_ancestor(int index, Thread *current_thread = Thread::get_current_thread()) const;
   MAKE_SEQ(get_ancestors, get_num_nodes, get_ancestor);
+  MAKE_SEQ_PROPERTY(ancestors, get_num_nodes, get_ancestor);
 
   INLINE ErrorType get_error_type() const;
+  MAKE_PROPERTY(error_type, get_error_type);
 
   INLINE PandaNode *get_top_node(Thread *current_thread = Thread::get_current_thread()) const;
   NodePath get_top(Thread *current_thread = Thread::get_current_thread()) const;
@@ -228,12 +231,18 @@ PUBLISHED:
   INLINE NodePath get_child(int n, Thread *current_thread = Thread::get_current_thread()) const;
   NodePathCollection get_stashed_children(Thread *current_thread = Thread::get_current_thread()) const;
 
+  MAKE_PROPERTY(children, get_children);
+  MAKE_PROPERTY(stashed_children, get_stashed_children);
+
   INLINE int count_num_descendants() const;
 
   INLINE bool has_parent(Thread *current_thread = Thread::get_current_thread()) const;
   INLINE NodePath get_parent(Thread *current_thread = Thread::get_current_thread()) const;
   int get_sort(Thread *current_thread = Thread::get_current_thread()) const;
 
+  MAKE_PROPERTY2(parent, has_parent, get_parent);
+  MAKE_PROPERTY(sort, get_sort);
+
   NodePath find(const string &path) const;
   NodePath find_path_to(PandaNode *node) const;
   NodePathCollection find_all_matches(const string &path) const;
@@ -910,6 +919,7 @@ PUBLISHED:
 
   INLINE void set_name(const string &name);
   INLINE string get_name() const;
+  MAKE_PROPERTY(name, get_name, set_name);
 
   BLOCKING bool write_bam_file(const Filename &filename) const;
   BLOCKING bool write_bam_stream(ostream &out) const;

+ 12 - 3
panda/src/pgraph/occluderNode.I

@@ -31,7 +31,7 @@ set_vertices(const LPoint3 &v0, const LPoint3 &v1,
  * Returns the number of vertices in the occluder polygon.  This should always
  * return 4.
  */
-INLINE int OccluderNode::
+INLINE size_t OccluderNode::
 get_num_vertices() const {
   return _vertices.size();
 }
@@ -40,11 +40,20 @@ get_num_vertices() const {
  * Returns the nth vertex of the occluder polygon.
  */
 INLINE const LPoint3 &OccluderNode::
-get_vertex(int n) const {
-  nassertr(n >= 0 && n < (int)_vertices.size(), LPoint3::zero());
+get_vertex(size_t n) const {
+  nassertr(n < _vertices.size(), LPoint3::zero());
   return _vertices[n];
 }
 
+/**
+ * Sets the nth vertex of the occluder polygon.
+ */
+INLINE void OccluderNode::
+set_vertex(size_t n, const LPoint3 &v) {
+  nassertv(n < _vertices.size());
+  _vertices[n] = v;
+}
+
 /**
  * If true, the back-face will also be used to occlude
  */

+ 7 - 2
panda/src/pgraph/occluderNode.h

@@ -53,10 +53,15 @@ PUBLISHED:
   INLINE PN_stdfloat get_min_coverage();
   INLINE void set_vertices(const LPoint3 &v0, const LPoint3 &v1,
                            const LPoint3 &v2, const LPoint3 &v3);
-  INLINE int get_num_vertices() const;
-  INLINE const LPoint3 &get_vertex(int n) const;
+  INLINE size_t get_num_vertices() const;
+  INLINE const LPoint3 &get_vertex(size_t n) const;
+  INLINE void set_vertex(size_t n, const LPoint3 &v);
   MAKE_SEQ(get_vertices, get_num_vertices, get_vertex);
 
+  MAKE_PROPERTY(double_sided, is_double_sided, set_double_sided);
+  MAKE_PROPERTY(min_coverage, get_min_coverage, set_min_coverage);
+  MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex, set_vertex);
+
 protected:
   virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
                                        int &internal_vertices,

+ 13 - 13
panda/src/pgraph/pandaNode.I

@@ -932,7 +932,7 @@ operator = (PandaNode::Children &&from) NOEXCEPT {
 /**
  * Returns the number of children of the node.
  */
-INLINE int PandaNode::Children::
+INLINE size_t PandaNode::Children::
 get_num_children() const {
   nassertr(_down != (Down *)NULL, 0);
   return _down->size();
@@ -942,9 +942,9 @@ get_num_children() const {
  * Returns the nth child of the node.
  */
 INLINE PandaNode *PandaNode::Children::
-get_child(int n) const {
+get_child(size_t n) const {
   nassertr(_down != (Down *)NULL, NULL);
-  nassertr(n >= 0 && n < (int)_down->size(), NULL);
+  nassertr(n < (size_t)_down->size(), NULL);
   return (*_down)[n].get_child();
 }
 
@@ -953,9 +953,9 @@ get_child(int n) const {
  * number that was passed to add_child()).  See get_num_children().
  */
 INLINE int PandaNode::Children::
-get_child_sort(int n) const {
+get_child_sort(size_t n) const {
   nassertr(_down != (Down *)NULL, -1);
-  nassertr(n >= 0 && n < (int)_down->size(), -1);
+  nassertr(n < _down->size(), -1);
   return (*_down)[n].get_sort();
 }
 
@@ -1014,7 +1014,7 @@ operator = (PandaNode::Stashed &&from) NOEXCEPT {
 /**
  * Returns the number of stashed children of the node.
  */
-INLINE int PandaNode::Stashed::
+INLINE size_t PandaNode::Stashed::
 get_num_stashed() const {
   nassertr(_stashed != (Down *)NULL, 0);
   return _stashed->size();
@@ -1024,9 +1024,9 @@ get_num_stashed() const {
  * Returns the nth stashed child of the node.
  */
 INLINE PandaNode *PandaNode::Stashed::
-get_stashed(int n) const {
+get_stashed(size_t n) const {
   nassertr(_stashed != (Down *)NULL, NULL);
-  nassertr(n >= 0 && n < (int)_stashed->size(), NULL);
+  nassertr(n < _stashed->size(), NULL);
   return (*_stashed)[n].get_child();
 }
 
@@ -1035,9 +1035,9 @@ get_stashed(int n) const {
  * number that was passed to add_child()).  See get_num_stashed().
  */
 INLINE int PandaNode::Stashed::
-get_stashed_sort(int n) const {
+get_stashed_sort(size_t n) const {
   nassertr(_stashed != (Down *)NULL, -1);
-  nassertr(n >= 0 && n < (int)_stashed->size(), -1);
+  nassertr(n < _stashed->size(), -1);
   return (*_stashed)[n].get_sort();
 }
 
@@ -1096,7 +1096,7 @@ operator = (PandaNode::Parents &&from) NOEXCEPT {
 /**
  * Returns the number of parents of the node.
  */
-INLINE int PandaNode::Parents::
+INLINE size_t PandaNode::Parents::
 get_num_parents() const {
   nassertr(_up != (Up *)NULL, 0);
   return _up->size();
@@ -1106,9 +1106,9 @@ get_num_parents() const {
  * Returns the nth parent of the node.
  */
 INLINE PandaNode *PandaNode::Parents::
-get_parent(int n) const {
+get_parent(size_t n) const {
   nassertr(_up != (Up *)NULL, NULL);
-  nassertr(n >= 0 && n < (int)_up->size(), NULL);
+  nassertr(n < _up->size(), NULL);
   return (*_up)[n].get_parent();
 }
 

+ 28 - 10
panda/src/pgraph/pandaNode.h

@@ -680,10 +680,10 @@ private:
   static PStatCollector _reset_prev_pcollector;
   static PStatCollector _update_bounds_pcollector;
 
-public:
+PUBLISHED:
   // This class is returned from get_children().  Use it to walk through the
   // list of children.  This is faster, and safer, than walking through the
-  // children one at a time via get_num_children()get_child(), since the list
+  // children one at a time via get_num_children()/get_child(), since the list
   // of children is saved out ahead of time, rather than having to reacquire
   // the lock with each iteration, or to keep the lock held for the entire
   // pass.
@@ -699,9 +699,13 @@ public:
     INLINE void operator = (Children &&from) NOEXCEPT;
 #endif
 
-    INLINE int get_num_children() const;
-    INLINE PandaNode *get_child(int n) const;
-    INLINE int get_child_sort(int n) const;
+    INLINE size_t get_num_children() const;
+    INLINE PandaNode *get_child(size_t n) const;
+    INLINE int get_child_sort(size_t n) const;
+
+  PUBLISHED:
+    INLINE PandaNode *operator [](size_t n) const { return get_child(n); }
+    INLINE size_t size() const { return get_num_children(); }
 
   private:
     CPT(Down) _down;
@@ -720,9 +724,13 @@ public:
     INLINE void operator = (Stashed &&from) NOEXCEPT;
 #endif
 
-    INLINE int get_num_stashed() const;
-    INLINE PandaNode *get_stashed(int n) const;
-    INLINE int get_stashed_sort(int n) const;
+    INLINE size_t get_num_stashed() const;
+    INLINE PandaNode *get_stashed(size_t n) const;
+    INLINE int get_stashed_sort(size_t n) const;
+
+  PUBLISHED:
+    INLINE PandaNode *operator [](size_t n) const { return get_stashed(n); }
+    INLINE size_t size() const { return get_num_stashed(); }
 
   private:
     CPT(Down) _stashed;
@@ -741,13 +749,18 @@ public:
     INLINE void operator = (Parents &&from) NOEXCEPT;
 #endif
 
-    INLINE int get_num_parents() const;
-    INLINE PandaNode *get_parent(int n) const;
+    INLINE size_t get_num_parents() const;
+    INLINE PandaNode *get_parent(size_t n) const;
+
+  PUBLISHED:
+    INLINE PandaNode *operator [](size_t n) const { return get_parent(n); }
+    INLINE size_t size() const { return get_num_parents(); }
 
   private:
     CPT(Up) _up;
   };
 
+public:
   INLINE Children get_children(Thread *current_thread = Thread::get_current_thread()) const;
   INLINE Stashed get_stashed(Thread *current_thread = Thread::get_current_thread()) const;
   INLINE Parents get_parents(Thread *current_thread = Thread::get_current_thread()) const;
@@ -755,6 +768,11 @@ public:
   typedef bool SceneRootFunc(const PandaNode *);
   static void set_scene_root_func(SceneRootFunc *func);
 
+PUBLISHED:
+  MAKE_PROPERTY(children, get_children);
+  MAKE_PROPERTY(stashed, get_stashed);
+  MAKE_PROPERTY(parents, get_parents);
+
 private:
   static SceneRootFunc *_scene_root_func;
 

+ 11 - 0
panda/src/pgraph/portalNode.h

@@ -86,6 +86,17 @@ PUBLISHED:
 
   // void draw () const;
 
+  MAKE_PROPERTY(into_portal_mask, get_into_portal_mask, set_into_portal_mask);
+  MAKE_PROPERTY(from_portal_mask, get_from_portal_mask, set_from_portal_mask);
+  MAKE_PROPERTY(portal_geom, get_portal_geom, set_portal_geom);
+  MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex);
+  MAKE_PROPERTY(cell_in, get_cell_in, set_cell_in);
+  MAKE_PROPERTY(cell_out, get_cell_out, set_cell_out);
+  MAKE_PROPERTY(clip_plane, is_clip_plane, set_clip_plane);
+  MAKE_PROPERTY(visible, is_visible, set_visible);
+  MAKE_PROPERTY(max_depth, get_max_depth, set_max_depth);
+  MAKE_PROPERTY(open, is_open, set_open);
+
 protected:
   virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
                                        int &internal_vertices,

+ 23 - 3
panda/src/pgraphnodes/computeNode.I

@@ -45,7 +45,7 @@ clear_dispatches() {
 /**
  * Returns the number of times add_dispatch has been called on this object.
  */
-INLINE int ComputeNode::
+INLINE size_t ComputeNode::
 get_num_dispatches() const {
   Dispatcher::CDReader cdata(_dispatcher->_cycler);
   return cdata->_dispatches.size();
@@ -55,12 +55,32 @@ get_num_dispatches() const {
  * Returns the group counts of the nth dispatch associated with this object.
  */
 INLINE const LVecBase3i &ComputeNode::
-get_dispatch(int n) const {
+get_dispatch(size_t n) const {
   Dispatcher::CDReader cdata(_dispatcher->_cycler);
-  nassertr(n >= 0 && (size_t)n < cdata->_dispatches.size(), LVecBase3i::zero());
+  nassertr(n < cdata->_dispatches.size(), LVecBase3i::zero());
   return cdata->_dispatches[n];
 }
 
+/**
+ * Sets the group counts of the nth dispatch associated with this object.
+ */
+INLINE void ComputeNode::
+set_dispatch(size_t n, const LVecBase3i &dispatch) {
+  Dispatcher::CDWriter cdata(_dispatcher->_cycler);
+  nassertv(n < cdata->_dispatches.size());
+  cdata->_dispatches[n] = dispatch;
+}
+
+/**
+ * Erases the given dispatch index from the list.
+ */
+INLINE void ComputeNode::
+remove_dispatch(size_t n) {
+  Dispatcher::CDWriter cdata(_dispatcher->_cycler);
+  nassertv(n < cdata->_dispatches.size());
+  cdata->_dispatches.erase(cdata->_dispatches.begin() + n);
+}
+
 /**
  *
  */

+ 5 - 2
panda/src/pgraphnodes/computeNode.h

@@ -31,11 +31,14 @@ PUBLISHED:
   INLINE void add_dispatch(const LVecBase3i &num_groups);
   INLINE void add_dispatch(int num_groups_x, int num_groups_y, int num_groups_z);
 
-  INLINE int get_num_dispatches() const;
-  INLINE const LVecBase3i &get_dispatch(int i) const;
+  INLINE size_t get_num_dispatches() const;
+  INLINE const LVecBase3i &get_dispatch(size_t i) const;
+  INLINE void set_dispatch(size_t i, const LVecBase3i &num_groups);
+  INLINE void remove_dispatch(size_t i);
   INLINE void clear_dispatches();
 
   MAKE_SEQ(get_dispatches, get_num_dispatches, get_dispatch);
+  MAKE_SEQ_PROPERTY(dispatches, get_num_dispatches, get_dispatch, set_dispatch, remove_dispatch);
 
 public:
   ComputeNode(const ComputeNode &copy);

+ 7 - 0
panda/src/pgraphnodes/lodNode.h

@@ -75,6 +75,13 @@ PUBLISHED:
   INLINE void set_center(const LPoint3 &center);
   INLINE const LPoint3 &get_center() const;
 
+  MAKE_SEQ_PROPERTY(ins, get_num_switches, get_in);
+  MAKE_SEQ_PROPERTY(outs, get_num_switches, get_out);
+  MAKE_PROPERTY(lowest_switch, get_lowest_switch);
+  MAKE_PROPERTY(highest_switch, get_highest_switch);
+  MAKE_PROPERTY(lod_scale, get_lod_scale, set_lod_scale);
+  MAKE_PROPERTY(center, get_center, set_center);
+
   void show_switch(int index);
   void show_switch(int index, const LColor &color);
   void hide_switch(int index);

+ 3 - 4
panda/src/physics/forceNode.I

@@ -23,16 +23,15 @@ clear() {
 
  */
 INLINE BaseForce *ForceNode::
-get_force(int index) const {
-  nassertr(index >= 0 && index < (int)_forces.size(),
-           (BaseForce *) NULL);
+get_force(size_t index) const {
+  nassertr(index < _forces.size(), (BaseForce *) NULL);
   return _forces[index];
 }
 
 /**
 
  */
-INLINE int ForceNode::
+INLINE size_t ForceNode::
 get_num_forces() const {
   return _forces.size();
 }

+ 16 - 2
panda/src/physics/forceNode.cxx

@@ -64,6 +64,20 @@ add_forces_from(const ForceNode &other) {
   }
 }
 
+/**
+ * replace operation
+ */
+void ForceNode::
+set_force(size_t index, BaseForce *force) {
+  nassertv(index <= _forces.size());
+
+  _forces[index]->_force_node = (ForceNode *)NULL;
+  _forces[index]->_force_node_path.clear();
+  _forces[index] = force;
+  force->_force_node = this;
+  force->_force_node_path = NodePath(this);
+}
+
 /**
  * remove operation
  */
@@ -81,8 +95,8 @@ remove_force(BaseForce *f) {
  * remove operation
  */
 void ForceNode::
-remove_force(int index) {
-  nassertv(index >= 0 && index <= (int)_forces.size());
+remove_force(size_t index) {
+  nassertv(index <= _forces.size());
 
   pvector< PT(BaseForce) >::iterator remove;
   remove = _forces.begin() + index;

+ 7 - 4
panda/src/physics/forceNode.h

@@ -28,14 +28,17 @@ class EXPCL_PANDAPHYSICS ForceNode : public PandaNode {
 PUBLISHED:
   ForceNode(const string &name);
   INLINE void clear();
-  INLINE BaseForce *get_force(int index) const;
-  INLINE int get_num_forces() const;
+  INLINE BaseForce *get_force(size_t index) const;
+  INLINE size_t get_num_forces() const;
   MAKE_SEQ(get_forces, get_num_forces, get_force);
   INLINE void add_force(BaseForce *force);
 
   void add_forces_from(const ForceNode &other);
-  void remove_force(BaseForce *f);
-  void remove_force(int index);
+  void set_force(size_t index, BaseForce *force);
+  void remove_force(BaseForce *force);
+  void remove_force(size_t index);
+
+  MAKE_SEQ_PROPERTY(forces, get_num_forces, get_force, set_force, remove_force);
 
   virtual void output(ostream &out) const;
   virtual void write_forces(ostream &out, unsigned int indent=0) const;

+ 3 - 4
panda/src/physics/physicalNode.I

@@ -23,16 +23,15 @@ clear() {
 
  */
 INLINE Physical *PhysicalNode::
-get_physical(int index) const {
-  nassertr(index >= 0 && index < (int)_physicals.size(),
-           (Physical *) NULL);
+get_physical(size_t index) const {
+  nassertr(index < _physicals.size(), (Physical *) NULL);
   return _physicals[index];
 }
 
 /**
 
  */
-INLINE int PhysicalNode::
+INLINE size_t PhysicalNode::
 get_num_physicals() const {
   return _physicals.size();
 }

+ 14 - 2
panda/src/physics/physicalNode.cxx

@@ -63,6 +63,18 @@ add_physicals_from(const PhysicalNode &other) {
   }
 }
 
+/**
+ * replace operation
+ */
+void PhysicalNode::
+set_physical(size_t index, Physical *physical) {
+  nassertv(index <= _physicals.size());
+
+  _physicals[index]->_physical_node = (PhysicalNode *) NULL;
+  _physicals[index] = physical;
+  physical->_physical_node = this;
+}
+
 /**
  * remove operation
  */
@@ -80,8 +92,8 @@ remove_physical(Physical *physical) {
  * remove operation
  */
 void PhysicalNode::
-remove_physical(int index) {
-  nassertv(index >= 0 && index <= (int)_physicals.size());
+remove_physical(size_t index) {
+  nassertv(index <= _physicals.size());
 
   pvector< PT(Physical) >::iterator remove;
   remove = _physicals.begin() + index;

+ 6 - 3
panda/src/physics/physicalNode.h

@@ -29,14 +29,17 @@ class EXPCL_PANDAPHYSICS PhysicalNode : public PandaNode {
 PUBLISHED:
   PhysicalNode(const string &name);
   INLINE void clear();
-  INLINE Physical *get_physical(int index) const;
-  INLINE int get_num_physicals() const;
+  INLINE Physical *get_physical(size_t index) const;
+  INLINE size_t get_num_physicals() const;
   MAKE_SEQ(get_physicals, get_num_physicals, get_physical);
   INLINE void add_physical(Physical *physical);
 
   void add_physicals_from(const PhysicalNode &other);
+  void set_physical(size_t index, Physical *physical);
   void remove_physical(Physical *physical);
-  void remove_physical(int index);
+  void remove_physical(size_t index);
+
+  MAKE_SEQ_PROPERTY(physicals, get_num_physicals, get_physical, set_physical, remove_physical);
 
   virtual void write(ostream &out, unsigned int indent=0) const;
 

+ 4 - 0
panda/src/pnmimage/pnmFileType.h

@@ -44,6 +44,10 @@ PUBLISHED:
   MAKE_SEQ(get_extensions, get_num_extensions, get_extension);
   virtual string get_suggested_extension() const;
 
+  MAKE_PROPERTY(name, get_name);
+  MAKE_SEQ_PROPERTY(extensions, get_num_extensions, get_extension);
+  MAKE_PROPERTY(suggested_extension, get_suggested_extension);
+
 public:
   virtual bool has_magic_number() const;
   virtual bool matches_magic_number(const string &magic_number) const;

+ 1 - 0
panda/src/pnmimage/pnmFileTypeRegistry.h

@@ -38,6 +38,7 @@ PUBLISHED:
   int get_num_types() const;
   PNMFileType *get_type(int n) const;
   MAKE_SEQ(get_types, get_num_types, get_type);
+  MAKE_SEQ_PROPERTY(types, get_num_types, get_type);
 
   PNMFileType *get_type_from_extension(const string &filename) const;
   PNMFileType *get_type_from_magic_number(const string &magic_number) const;

+ 8 - 0
panda/src/pstatclient/pStatClient.h

@@ -80,6 +80,14 @@ PUBLISHED:
 
   INLINE double get_real_time() const;
 
+  MAKE_PROPERTY(client_name, get_client_name, set_client_name);
+  MAKE_PROPERTY(max_rate, get_max_rate, set_max_rate);
+  MAKE_SEQ_PROPERTY(collectors, get_num_collectors, get_collector);
+  MAKE_SEQ_PROPERTY(threads, get_num_threads, get_thread);
+  MAKE_PROPERTY(main_thread, get_main_thread);
+  MAKE_PROPERTY(current_thread, get_current_thread);
+  MAKE_PROPERTY(real_time, get_real_time);
+
   INLINE static bool connect(const string &hostname = string(), int port = -1);
   INLINE static void disconnect();
   INLINE static bool is_connected();

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

@@ -51,6 +51,7 @@ PUBLISHED:
   INLINE int get_num_buttons() const;
   INLINE ButtonHandle get_button(int index) const;
   MAKE_SEQ(get_buttons, get_num_buttons, get_button);
+  MAKE_SEQ_PROPERTY(buttons, get_num_buttons, get_button);
 
   bool button_down(ButtonHandle button);
   bool button_up(ButtonHandle button);

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

@@ -114,6 +114,7 @@ PUBLISHED:
   int get_num_pages() const;
   DynamicTextPage *get_page(int n) const;
   MAKE_SEQ(get_pages, get_num_pages, get_page);
+  MAKE_SEQ_PROPERTY(pages, get_num_pages, get_page);
 
   int garbage_collect();
   void clear();

+ 1 - 0
panda/src/tform/buttonThrower.h

@@ -77,6 +77,7 @@ PUBLISHED:
   int get_num_parameters() const;
   EventParameter get_parameter(int n) const;
   MAKE_SEQ(get_parameters, get_num_parameters, get_parameter);
+  MAKE_SEQ_PROPERTY(parameters, get_num_parameters, get_parameter);
 
   INLINE const ModifierButtons &get_modifier_buttons() const;
   INLINE void set_modifier_buttons(const ModifierButtons &mods);

+ 2 - 0
panda/src/tform/mouseWatcherBase.h

@@ -42,10 +42,12 @@ PUBLISHED:
 
   void sort_regions();
   bool is_sorted() const;
+  MAKE_PROPERTY(sorted, is_sorted);
 
   int get_num_regions() const;
   MouseWatcherRegion *get_region(int n) const;
   MAKE_SEQ(get_regions, get_num_regions, get_region);
+  MAKE_SEQ_PROPERTY(regions, get_num_regions, get_region);
 
   void output(ostream &out) const;
   void write(ostream &out, int indent_level = 0) const;

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