Browse Source

Various substantial changes to Interrogate:
* Allow arbitrary selection of optional keyword arguments in some cases
* Reduce code bloat of generated bindings
* Work around awkward resolution of set_shader_input overloads
* Document the code a bit better
* Make coercion a bit cleaner for reference counted types
* A few optimization tweaks
* Use generic errors in NDEBUG build to reduce size of string pool

rdb 11 years ago
parent
commit
9513046e59

+ 29 - 2
dtool/src/cppparser/cppExpression.cxx

@@ -147,6 +147,30 @@ as_pointer() const {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CPPExpression::Result::as_boolean
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool CPPExpression::Result::
+as_boolean() const {
+  switch (_type) {
+  case RT_integer:
+    return (_u._integer != 0);
+
+  case RT_real:
+    return (_u._real != 0.0);
+
+  case RT_pointer:
+    return (_u._pointer != NULL);
+
+  default:
+    cerr << "Invalid type\n";
+    assert(false);
+    return false;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CPPExpression::Result::output
 //     Function: CPPExpression::Result::output
 //       Access: Public
 //       Access: Public
@@ -1098,8 +1122,12 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
     break;
     break;
 
 
   case T_variable:
   case T_variable:
+    // We can just refer to the variable by name, except if it's a
+    // private constant, in which case we have to compute the value,
+    // since we may have to use it in generated code.
     if (_u._variable->_type != NULL &&
     if (_u._variable->_type != NULL &&
-        _u._variable->_initializer != NULL) {
+        _u._variable->_initializer != NULL &&
+        _u._variable->_vis > V_public) {
       // A const variable.  Fetch its assigned value.
       // A const variable.  Fetch its assigned value.
       CPPConstType *const_type = _u._variable->_type->as_const_type();
       CPPConstType *const_type = _u._variable->_type->as_const_type();
       if (const_type != NULL) {
       if (const_type != NULL) {
@@ -1536,4 +1564,3 @@ is_less(const CPPDeclaration *other) const {
 
 
   return false;
   return false;
 }
 }
-

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

@@ -63,6 +63,7 @@ public:
     int as_integer() const;
     int as_integer() const;
     double as_real() const;
     double as_real() const;
     void *as_pointer() const;
     void *as_pointer() const;
+    bool as_boolean() const;
     void output(ostream &out) const;
     void output(ostream &out) const;
 
 
     ResultType _type;
     ResultType _type;

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

@@ -796,9 +796,14 @@ get_local_name(CPPScope *scope) const {
   }
   }
   */
   */
 
 
-  if (scope != NULL && _parent_scope != NULL && _parent_scope != scope) {
-    return _parent_scope->get_local_name(scope) + "::" +
-      _name.get_name_with_templ();
+  if (scope != NULL && _parent_scope != NULL/* && _parent_scope != scope*/) {
+    string parent_scope_name = _parent_scope->get_local_name(scope);
+    if (parent_scope_name.empty()) {
+      return _name.get_name_with_templ();
+    } else {
+      return parent_scope_name + "::" +
+        _name.get_name_with_templ();
+    }
   } else {
   } else {
     return _name.get_name_with_templ();
     return _name.get_name_with_templ();
   }
   }
@@ -1040,6 +1045,10 @@ copy_substitute_decl(CPPScope *to_scope, CPPDeclaration::SubstDecl &subst,
       (*vi).second->substitute_decl(subst, to_scope, global_scope)->as_instance();
       (*vi).second->substitute_decl(subst, to_scope, global_scope)->as_instance();
     to_scope->_variables.insert(Variables::value_type((*vi).first, inst));
     to_scope->_variables.insert(Variables::value_type((*vi).first, inst));
     if (inst != (*vi).second) {
     if (inst != (*vi).second) {
+      // I don't know if this _native_scope assignment is right, but it
+      // fixes some issues with variables in instantiated template scopes
+      // being printed out with an uninstantiated template scope prefix. ~rdb
+      inst->_ident->_native_scope = to_scope;
       anything_changed = true;
       anything_changed = true;
     }
     }
   }
   }
@@ -1126,6 +1135,13 @@ handle_declaration(CPPDeclaration *decl, CPPScope *global_scope,
   if (inst != NULL) {
   if (inst != NULL) {
     inst->check_for_constructor(this, global_scope);
     inst->check_for_constructor(this, global_scope);
 
 
+    if (inst->_ident != NULL) {
+      // Not sure if this is the best place to assign this.  However,
+      // this fixes a bug with variables in expressions not having
+      // the proper scoping prefix. ~rdb
+      inst->_ident->_native_scope = this;
+    }
+
     string name = inst->get_simple_name();
     string name = inst->get_simple_name();
     if (!name.empty() && inst->get_scope(this, global_scope) == this) {
     if (!name.empty() && inst->get_scope(this, global_scope) == this) {
       if (inst->_type->as_function_type()) {
       if (inst->_type->as_function_type()) {

+ 14 - 7
dtool/src/interrogate/functionRemap.cxx

@@ -200,7 +200,7 @@ call_function(ostream &out, int indent_level, bool convert_result,
 
 
       // Now a simple special-case test.  Often, we will have converted
       // Now a simple special-case test.  Often, we will have converted
       // the reference-returning assignment operator to a pointer.  In
       // the reference-returning assignment operator to a pointer.  In
-      // this case, we might inadventent generate code like "return
+      // this case, we might inadvertently generate code like "return
       // &(*this)", when "return this" would do.  We check for this here
       // &(*this)", when "return this" would do.  We check for this here
       // and undo it as a special case.
       // and undo it as a special case.
 
 
@@ -234,8 +234,14 @@ call_function(ostream &out, int indent_level, bool convert_result,
                                                            &parser);
                                                            &parser);
         out << " = " << call << ";\n";
         out << " = " << call << ";\n";
 
 
+        // MOVE() expands to std::move() when we are compiling with a
+        // compiler that supports rvalue references.  It basically turns
+        // an lvalue into an rvalue, allowing a move constructor to be
+        // called instead of a copy constructor (since we won't be using
+        // the return value any more), which is usually more efficient if
+        // it exists.  If it doesn't, it shouldn't do any harm.
         string new_str =
         string new_str =
-          _return_type->prepare_return_expr(out, indent_level, "result");
+          _return_type->prepare_return_expr(out, indent_level, "MOVE(result)");
         return_expr = _return_type->get_return_expr(new_str);
         return_expr = _return_type->get_return_expr(new_str);
 
 
       } else {
       } else {
@@ -258,11 +264,11 @@ call_function(ostream &out, int indent_level, bool convert_result,
 //               comment.
 //               comment.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void FunctionRemap::
 void FunctionRemap::
-write_orig_prototype(ostream &out, int indent_level, bool local) const {
+write_orig_prototype(ostream &out, int indent_level, bool local, int num_default_args) const {
   if (local) {
   if (local) {
-    _cppfunc->output(out, indent_level, NULL, false, _num_default_parameters);
+    _cppfunc->output(out, indent_level, NULL, false, num_default_args);
   } else {
   } else {
-    _cppfunc->output(out, indent_level, &parser, false, _num_default_parameters);
+    _cppfunc->output(out, indent_level, &parser, false, num_default_args);
   }
   }
 }
 }
 
 
@@ -426,7 +432,7 @@ get_call_str(const string &container, const vector_string &pexprs) const {
     }
     }
 
 
     int pn = _first_true_parameter;
     int pn = _first_true_parameter;
-    int num_parameters = _parameters.size();
+    int num_parameters = pexprs.size();
 
 
     if (_type == T_item_assignment_operator) {
     if (_type == T_item_assignment_operator) {
       // The last parameter is the value to set.
       // The last parameter is the value to set.
@@ -716,7 +722,8 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
 
 
   if ((int)_parameters.size() == first_param) {
   if ((int)_parameters.size() == first_param) {
     _args_type = InterfaceMaker::AT_no_args;
     _args_type = InterfaceMaker::AT_no_args;
-  } else if ((int)_parameters.size() == first_param + 1) {
+  } else if ((int)_parameters.size() == first_param + 1 &&
+             _parameters[first_param]._remap->get_default_value() == NULL) {
     _args_type = InterfaceMaker::AT_single_arg;
     _args_type = InterfaceMaker::AT_single_arg;
   } else {
   } else {
     _args_type = InterfaceMaker::AT_varargs;
     _args_type = InterfaceMaker::AT_varargs;

+ 3 - 2
dtool/src/interrogate/functionRemap.h

@@ -52,11 +52,12 @@ public:
   ~FunctionRemap();
   ~FunctionRemap();
 
 
   string get_parameter_name(int n) const;
   string get_parameter_name(int n) const;
-  string call_function(ostream &out, int indent_level, 
+  string call_function(ostream &out, int indent_level,
                        bool convert_result, const string &container,
                        bool convert_result, const string &container,
                        const vector_string &pexprs = vector_string()) const;
                        const vector_string &pexprs = vector_string()) const;
 
 
-  void write_orig_prototype(ostream &out, int indent_level, bool local=false) const;
+  void write_orig_prototype(ostream &out, int indent_level, bool local=false,
+                            int num_default_args=0) const;
 
 
   FunctionWrapperIndex make_wrapper_entry(FunctionIndex function_index);
   FunctionWrapperIndex make_wrapper_entry(FunctionIndex function_index);
 
 

+ 12 - 0
dtool/src/interrogate/interfaceMaker.cxx

@@ -871,6 +871,12 @@ delete_return_value(ostream &out, int indent_level,
 void InterfaceMaker::
 void InterfaceMaker::
 output_ref(ostream &out, int indent_level, FunctionRemap *remap,
 output_ref(ostream &out, int indent_level, FunctionRemap *remap,
            const string &varname) const {
            const string &varname) const {
+
+  if (TypeManager::is_pointer_to_base(remap->_return_type->get_temporary_type())) {
+    // Actually, we have it stored in a PointerTo.  No need to do anything.
+    return;
+  }
+
   if (remap->_type == FunctionRemap::T_constructor ||
   if (remap->_type == FunctionRemap::T_constructor ||
       remap->_type == FunctionRemap::T_typecast) {
       remap->_type == FunctionRemap::T_typecast) {
     // In either of these cases, we can safely assume the pointer will
     // In either of these cases, we can safely assume the pointer will
@@ -901,6 +907,12 @@ output_ref(ostream &out, int indent_level, FunctionRemap *remap,
 void InterfaceMaker::
 void InterfaceMaker::
 output_unref(ostream &out, int indent_level, FunctionRemap *remap,
 output_unref(ostream &out, int indent_level, FunctionRemap *remap,
              const string &varname) const {
              const string &varname) const {
+
+  if (TypeManager::is_pointer_to_base(remap->_return_type->get_temporary_type())) {
+    // Actually, we have it stored in a PointerTo.  No need to do anything.
+    return;
+  }
+
   if (remap->_type == FunctionRemap::T_constructor ||
   if (remap->_type == FunctionRemap::T_constructor ||
       remap->_type == FunctionRemap::T_typecast) {
       remap->_type == FunctionRemap::T_typecast) {
     // In either of these cases, we can safely assume the pointer will
     // In either of these cases, we can safely assume the pointer will

File diff suppressed because it is too large
+ 374 - 168
dtool/src/interrogate/interfaceMakerPythonNative.cxx


+ 8 - 1
dtool/src/interrogate/interfaceMakerPythonNative.h

@@ -46,6 +46,7 @@ public:
   virtual void write_sub_module(ostream &out, Object *obj);
   virtual void write_sub_module(ostream &out, Object *obj);
 
 
   virtual bool synthesize_this_parameter();
   virtual bool synthesize_this_parameter();
+  virtual bool separate_overloading();
 
 
   virtual Object *record_object(TypeIndex type_index);
   virtual Object *record_object(TypeIndex type_index);
 
 
@@ -127,15 +128,21 @@ private:
                                ArgsType args_type, int return_flags);
                                ArgsType args_type, int return_flags);
   void write_coerce_constructor(ostream &out, Object *obj, bool is_const);
   void write_coerce_constructor(ostream &out, Object *obj, bool is_const);
 
 
+  int collapse_default_remaps(std::map<int, std::set<FunctionRemap *> > &map_sets,
+                              int max_required_args);
+
   void write_function_forset(ostream &out,
   void write_function_forset(ostream &out,
                              const std::set<FunctionRemap*> &remaps,
                              const std::set<FunctionRemap*> &remaps,
+                             int min_num_args, int max_num_args,
                              string &expected_params, int indent_level,
                              string &expected_params, int indent_level,
                              bool coercion_allowed, bool report_errors,
                              bool coercion_allowed, bool report_errors,
                              ArgsType args_type, int return_flags,
                              ArgsType args_type, int return_flags,
                              bool check_exceptions = true,
                              bool check_exceptions = true,
+                             bool verify_const = false,
                              const string &first_expr = string());
                              const string &first_expr = string());
 
 
   void write_function_instance(ostream &out, FunctionRemap *remap,
   void write_function_instance(ostream &out, FunctionRemap *remap,
+                               int min_num_args, int max_num_args,
                                string &expected_params, int indent_level,
                                string &expected_params, int indent_level,
                                bool coercion_allowed, bool report_errors,
                                bool coercion_allowed, bool report_errors,
                                ArgsType args_type, int return_flags,
                                ArgsType args_type, int return_flags,
@@ -144,7 +151,7 @@ private:
 
 
   void error_return(ostream &out, int indent_level, int return_flags);
   void error_return(ostream &out, int indent_level, int return_flags);
   void pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
   void pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
-                         const std::string &return_expr);
+                         std::string return_expr);
 
 
   void write_make_seq(ostream &out, Object *obj, const std::string &ClassName,
   void write_make_seq(ostream &out, Object *obj, const std::string &ClassName,
                       MakeSeq *make_seq);
                       MakeSeq *make_seq);

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

@@ -670,7 +670,11 @@ bool TypeManager::
 is_const_char_pointer(CPPType *type) {
 is_const_char_pointer(CPPType *type) {
   switch (type->get_subtype()) {
   switch (type->get_subtype()) {
   case CPPDeclaration::ST_const:
   case CPPDeclaration::ST_const:
-    return is_char_pointer(type->as_const_type()->_wrapped_around);
+    return is_const_char_pointer(type->as_const_type()->_wrapped_around);
+
+  case CPPDeclaration::ST_pointer:
+    return (is_const(type->as_pointer_type()->_pointing_at) &&
+            is_char(type->as_pointer_type()->_pointing_at));
 
 
   case CPPDeclaration::ST_typedef:
   case CPPDeclaration::ST_typedef:
     return is_const_char_pointer(type->as_typedef_type()->_type);
     return is_const_char_pointer(type->as_typedef_type()->_type);

+ 100 - 11
dtool/src/interrogatedb/py_panda.cxx

@@ -19,16 +19,20 @@
 
 
 PyMemberDef standard_type_members[] = {
 PyMemberDef standard_type_members[] = {
   {(char *)"this", (sizeof(void*) == sizeof(int)) ? T_UINT : T_ULONGLONG, offsetof(Dtool_PyInstDef, _ptr_to_object), READONLY, (char *)"C++ 'this' pointer, if any"},
   {(char *)"this", (sizeof(void*) == sizeof(int)) ? T_UINT : T_ULONGLONG, offsetof(Dtool_PyInstDef, _ptr_to_object), READONLY, (char *)"C++ 'this' pointer, if any"},
-//  {(char *)"this_ownership", T_INT, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"},
-//  {(char *)"this_const", T_INT, offsetof(Dtool_PyInstDef, _is_const), READONLY, (char *)"C++ 'this' const flag"},
+  {(char *)"this_ownership", T_BOOL, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"},
+  {(char *)"this_const", T_BOOL, offsetof(Dtool_PyInstDef, _is_const), READONLY, (char *)"C++ 'this' const flag"},
 //  {(char *)"this_signature", T_INT, offsetof(Dtool_PyInstDef, _signature), READONLY, (char *)"A type check signature"},
 //  {(char *)"this_signature", T_INT, offsetof(Dtool_PyInstDef, _signature), READONLY, (char *)"A type check signature"},
   {(char *)"this_metatype", T_OBJECT, offsetof(Dtool_PyInstDef, _My_Type), READONLY, (char *)"The dtool meta object"},
   {(char *)"this_metatype", T_OBJECT, offsetof(Dtool_PyInstDef, _My_Type), READONLY, (char *)"The dtool meta object"},
   {NULL}  /* Sentinel */
   {NULL}  /* Sentinel */
 };
 };
 
 
-////////////////////////////////////////////////////////////////////////
-/// Simple Recognition Functions..
-////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////
+//     Function: DtoolCanThisBeAPandaInstance
+//  Description: Given a valid (non-NULL) PyObject, does a simple
+//               check to see if it might be an instance of a Panda
+//               type.  It does this using a signature that is
+//               encoded on each instance.
+////////////////////////////////////////////////////////////////////
 bool DtoolCanThisBeAPandaInstance(PyObject *self) {
 bool DtoolCanThisBeAPandaInstance(PyObject *self) {
   // simple sanity check for the class type..size.. will stop basic foobars..
   // simple sanity check for the class type..size.. will stop basic foobars..
   // It is arguably better to use something like this:
   // It is arguably better to use something like this:
@@ -58,6 +62,53 @@ void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *c
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: Dtool_Call_ExtractThisPointer
+//  Description: This is a support function for the Python bindings:
+//               it extracts the underlying C++ pointer of the given
+//               type for a given Python object.  If it was of the
+//               wrong type, raises an AttributeError.
+////////////////////////////////////////////////////////////////////
+bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer) {
+  if (self != NULL && DtoolCanThisBeAPandaInstance(self)) {
+    *answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, &classdef);
+    return true;
+  }
+
+  PyErr_SetString(PyExc_AttributeError, "C++ object is not yet constructed, or already destructed.");
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Dtool_Call_ExtractThisPointer_NonConst
+//  Description: The same thing as Dtool_Call_ExtractThisPointer,
+//               except that it performs the additional check that
+//               the pointer is a non-const pointer.  This is called
+//               by function wrappers for functions of which all
+//               overloads are non-const, and saves a bit of code.
+//
+//               The extra method_name argument is used in formatting
+//               the error message.
+////////////////////////////////////////////////////////////////////
+bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
+                                            void **answer, const char *method_name) {
+
+  if (self != NULL && DtoolCanThisBeAPandaInstance(self)) {
+    *answer = ((Dtool_PyInstDef *)self)->_My_Type->_Dtool_UpcastInterface(self, &classdef);
+    return true;
+  }
+
+  if (((Dtool_PyInstDef *)self)->_is_const) {
+    // All overloads of this function are non-const.
+    PyErr_Format(PyExc_TypeError,
+                 "Cannot call %s() on a const object.",
+                 method_name);
+    return false;
+  }
+
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DTOOL_Call_GetPointerThisClass
 //     Function: DTOOL_Call_GetPointerThisClass
 //  Description: Extracts the C++ pointer for an object, given its
 //  Description: Extracts the C++ pointer for an object, given its
@@ -118,12 +169,8 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
   }
   }
 
 
   if (report_errors) {
   if (report_errors) {
-    PyTypeObject *tp = Py_TYPE(self);
-
-    PyErr_Format(PyExc_TypeError,
-                 "%s() argument %d must be %s, not %s",
-                 function_name.c_str(), param,
-                 classdef->_PyType.tp_name, tp->tp_name);
+    Dtool_Raise_ArgTypeError(self, param, function_name.c_str(), classdef->_PyType.tp_name);
+    return NULL;
   }
   }
 
 
   return NULL;
   return NULL;
@@ -140,6 +187,48 @@ void *DTOOL_Call_GetPointerThis(PyObject *self) {
   return NULL;
   return NULL;
 }
 }
 
 
+#ifndef NDEBUG
+////////////////////////////////////////////////////////////////////
+//     Function: Dtool_CheckErrorOccurred
+//  Description: This is similar to a PyErr_Occurred() check, except
+//               that it also checks Notify to see if an assertion
+//               has occurred.  If that is the case, then it raises
+//               an AssertionError.
+//
+//               Returns true if there is an active exception, false
+//               otherwise.
+//
+//               In the NDEBUG case, this is simply a #define to
+//               _PyErr_OCCURRED() (which is an undocumented inline
+//               version of PyErr_Occurred()).
+////////////////////////////////////////////////////////////////////
+bool Dtool_CheckErrorOccurred() {
+  if (_PyErr_OCCURRED()) {
+    return true;
+  }
+  Notify *notify = Notify::ptr();
+  if (notify->has_assert_failed()) {
+    PyErr_SetString(PyExc_AssertionError, notify->get_assert_error_message().c_str());
+    notify->clear_assert_failed();
+    return true;
+  }
+  return false;
+}
+#endif  // NDEBUG
+
+////////////////////////////////////////////////////////////////////
+//     Function: Dtool_Raise_ArgTypeError
+//  Description: Raises a TypeError of the form:
+//               function_name() argument n must be type, not type
+//               for a given object passed to a function.
+////////////////////////////////////////////////////////////////////
+void Dtool_Raise_ArgTypeError(PyObject *obj, int param, const char *function_name, const char *type_name) {
+  PyErr_Format(PyExc_TypeError,
+               "%s() argument %d must be %s, not %s",
+               function_name, param, type_name,
+               Py_TYPE(obj)->tp_name);
+}
+
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
 //  Function : DTool_CreatePyInstanceTyped
 //  Function : DTool_CreatePyInstanceTyped
 //
 //

+ 33 - 3
dtool/src/interrogatedb/py_panda.h

@@ -110,6 +110,7 @@ inline PyObject* doPy_RETURN_FALSE()
 #define nb_divide nb_true_divide
 #define nb_divide nb_true_divide
 #define nb_inplace_divide nb_inplace_true_divide
 #define nb_inplace_divide nb_inplace_true_divide
 
 
+#define PyLongOrInt_Check(x) PyLong_Check(x)
 #define PyLongOrInt_FromSize_t PyLong_FromSize_t
 #define PyLongOrInt_FromSize_t PyLong_FromSize_t
 #define PyLongOrInt_FromLong PyLong_FromLong
 #define PyLongOrInt_FromLong PyLong_FromLong
 #define PyLongOrInt_FromUnsignedLong PyLong_FromUnsignedLong
 #define PyLongOrInt_FromUnsignedLong PyLong_FromUnsignedLong
@@ -117,6 +118,7 @@ inline PyObject* doPy_RETURN_FALSE()
 #define PyInt_AsLong PyLong_Aslong
 #define PyInt_AsLong PyLong_Aslong
 #define PyInt_AS_LONG PyLong_AS_LONG
 #define PyInt_AS_LONG PyLong_AS_LONG
 #else
 #else
+#define PyLongOrInt_Check(x) (PyInt_Check(x) || PyLong_Check(x))
 // PyInt_FromSize_t automatically picks the right type.
 // PyInt_FromSize_t automatically picks the right type.
 #define PyLongOrInt_FromSize_t PyInt_FromSize_t
 #define PyLongOrInt_FromSize_t PyInt_FromSize_t
 #define PyLongOrInt_FromLong PyInt_FromLong
 #define PyLongOrInt_FromLong PyInt_FromLong
@@ -160,14 +162,26 @@ typedef void *(*DowncastFunction)(void *, Dtool_PyTypedObject *);
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
 // THIS IS THE INSTANCE CONTAINER FOR ALL panda py objects....
 // THIS IS THE INSTANCE CONTAINER FOR ALL panda py objects....
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
-// this should save   8 bytes per object ....
 struct Dtool_PyInstDef {
 struct Dtool_PyInstDef {
   PyObject_HEAD
   PyObject_HEAD
+
+  // Pointer to the underlying C++ object.
   void *_ptr_to_object;
   void *_ptr_to_object;
+
+  // This is a pointer to the Dtool_PyTypedObject type.  It's tempting
+  // not to store this and to instead use PY_TYPE(self) and upcast that,
+  // but that breaks when someone inherits from our class in Python.
   struct Dtool_PyTypedObject *_My_Type;
   struct Dtool_PyTypedObject *_My_Type;
+
+  // This is always set to PY_PANDA_SIGNATURE, so that we can quickly
+  // detect whether an object is a Panda object.
   unsigned short _signature;
   unsigned short _signature;
-  int _memory_rules : 1;   // true if we own the pointer and should delete it or unref it
-  int _is_const     : 1;       // true if this is a "const" pointer.
+
+  // True if we own the pointer and should delete it or unref it.
+  bool _memory_rules;
+
+  // True if this is a "const" pointer.
+  bool _is_const;
 };
 };
 
 
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
@@ -345,6 +359,11 @@ EXPCL_DTOOLCONFIG void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyT
 
 
 EXPCL_DTOOLCONFIG void *DTOOL_Call_GetPointerThis(PyObject *self);
 EXPCL_DTOOLCONFIG void *DTOOL_Call_GetPointerThis(PyObject *self);
 
 
+EXPCL_DTOOLCONFIG bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer);
+
+EXPCL_DTOOLCONFIG bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
+                                                              void **answer, const char *method_name);
+
 template<class T> INLINE bool DTOOL_Call_ExtractThisPointer(PyObject *self, T *&into) {
 template<class T> INLINE bool DTOOL_Call_ExtractThisPointer(PyObject *self, T *&into) {
   if (DtoolCanThisBeAPandaInstance(self)) {
   if (DtoolCanThisBeAPandaInstance(self)) {
     Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
     Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
@@ -357,6 +376,17 @@ template<class T> INLINE bool DTOOL_Call_ExtractThisPointer(PyObject *self, T *&
   return false;
   return false;
 }
 }
 
 
+// Functions related to error reporting.
+
+#ifdef NDEBUG
+// _PyErr_OCCURRED is an undocumented inline version of PyErr_Occurred.
+#define Dtool_CheckErrorOccurred() (_PyErr_OCCURRED() != NULL)
+#else
+EXPCL_DTOOLCONFIG bool Dtool_CheckErrorOccurred();
+#endif
+
+EXPCL_DTOOLCONFIG void Dtool_Raise_ArgTypeError(PyObject *obj, int param, const char *function_name, const char *type_name);
+
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
 //  Function : DTool_CreatePyInstanceTyped
 //  Function : DTool_CreatePyInstanceTyped
 //
 //

+ 15 - 0
dtool/src/parser-inc/Python.h

@@ -33,6 +33,21 @@ class PyThreadState;
 typedef int Py_ssize_t;
 typedef int Py_ssize_t;
 struct Py_buffer;
 struct Py_buffer;
 
 
+// We need to define these accurately since interrogate may want to
+// write these out to default value assignments.
+PyObject _Py_NoneStruct;
+PyObject _Py_TrueStruct;
+#define Py_None (&_Py_NoneStruct)
+#define Py_True ((PyObject *) &_Py_TrueStruct)
+
+#if PY_MAJOR_VERSION >= 3
+PyObject _Py_ZeroStruct;
+#define Py_False ((PyObject *) &_Py_ZeroStruct)
+#else
+PyObject _Py_FalseStruct;
+#define Py_False ((PyObject *) &_Py_FalseStruct)
+#endif
+
 // This file defines PY_VERSION_HEX, which is used in some places.
 // This file defines PY_VERSION_HEX, which is used in some places.
 #include "patchlevel.h"
 #include "patchlevel.h"
 
 

+ 7 - 0
dtool/src/parser-inc/iostream

@@ -36,6 +36,13 @@ __published:
   };
   };
   enum openmode {
   enum openmode {
   };
   };
+  // Don't define these lest interrogate get tempted to actually
+  // substitute in the values, which are implementation-defined.
+  static const openmode app;
+  static const openmode binary;
+  static const openmode in;
+  static const openmode out;
+  static const openmode trunc;
 };
 };
 class ios : public ios_base {
 class ios : public ios_base {
 __published:
 __published:

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

@@ -38,7 +38,11 @@ typedef unsigned long ulong;
 typedef unsigned short ushort;
 typedef unsigned short ushort;
 typedef unsigned char uchar;
 typedef unsigned char uchar;
 
 
+#ifdef __cplusplus
+#define NULL 0
+#else
 #define NULL ((void *)0)
 #define NULL ((void *)0)
+#endif
 
 
 typedef int fd_set;
 typedef int fd_set;
 
 

+ 1 - 1
dtool/src/parser-inc/string

@@ -26,7 +26,7 @@ template<class ctype>
 class basic_string {
 class basic_string {
 public:
 public:
   typedef typename size_t size_type;
   typedef typename size_t size_type;
-  static const size_t npos = (size_t)-1;
+  static const size_t npos;
 
 
   basic_string();
   basic_string();
   basic_string(const basic_string &copy);
   basic_string(const basic_string &copy);

+ 3 - 51
dtool/src/prc/notify.cxx

@@ -182,54 +182,6 @@ get_assert_handler() const {
   return _assert_handler;
   return _assert_handler;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: Notify::has_assert_failed
-//       Access: Public
-//  Description: Returns true if an assertion test has failed (and not
-//               been ignored) since the last call to
-//               clear_assert_failed().
-//
-//               When an assertion test fails, the assert handler
-//               may decide either to abort, return, or ignore the
-//               assertion.  Naturally, if it decides to abort, this
-//               flag is irrelevant.  If it chooses to ignore the
-//               assertion, the flag is not set.  However, if the
-//               assert handler chooses to return out of the
-//               function (the normal case), it will also set this
-//               flag to indicate that an assertion failure has
-//               occurred.
-//
-//               This will also be the behavior in the absence of a
-//               user-defined assert handler.
-////////////////////////////////////////////////////////////////////
-bool Notify::
-has_assert_failed() const {
-  return _assert_failed;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Notify::get_assert_error_message
-//       Access: Public
-//  Description: Returns the error message that corresponds to the
-//               assertion that most recently failed.
-////////////////////////////////////////////////////////////////////
-const string &Notify::
-get_assert_error_message() const {
-  return _assert_error_message;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Notify::clear_assert_failed
-//       Access: Public
-//  Description: Resets the assert_failed flag that is set whenever an
-//               assertion test fails.  See has_assert_failed().
-////////////////////////////////////////////////////////////////////
-void Notify::
-clear_assert_failed() {
-  _assert_failed = false;
-}
-
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: Notify::get_top_category
 //     Function: Notify::get_top_category
 //       Access: Public
 //       Access: Public
@@ -269,7 +221,7 @@ get_category(const string &basename, NotifyCategory *parent_category) {
     }
     }
   }
   }
 
 
-  pair<Categories::iterator, bool> result = 
+  pair<Categories::iterator, bool> result =
     _categories.insert(Categories::value_type(fullname, (NotifyCategory *)NULL));
     _categories.insert(Categories::value_type(fullname, (NotifyCategory *)NULL));
 
 
   bool inserted = result.second;
   bool inserted = result.second;
@@ -458,7 +410,7 @@ assert_failure(const char *expression, int line,
     // the debugger?  abort() doesn't do it.  We used to be able to
     // the debugger?  abort() doesn't do it.  We used to be able to
     // assert(false), but in VC++ 7 that just throws an exception, and
     // assert(false), but in VC++ 7 that just throws an exception, and
     // an uncaught exception just exits, without offering to open the
     // an uncaught exception just exits, without offering to open the
-    // debugger.  
+    // debugger.
 
 
     // DebugBreak() seems to be provided for this purpose, but it
     // DebugBreak() seems to be provided for this purpose, but it
     // doesn't seem to work properly either, since we don't seem to
     // doesn't seem to work properly either, since we don't seem to
@@ -567,7 +519,7 @@ config_initialized() {
           dup2(logfile_fd, STDOUT_FILENO);
           dup2(logfile_fd, STDOUT_FILENO);
           dup2(logfile_fd, STDERR_FILENO);
           dup2(logfile_fd, STDERR_FILENO);
           close(logfile_fd);
           close(logfile_fd);
-          
+
           set_ostream_ptr(&cerr, false);
           set_ostream_ptr(&cerr, false);
         }
         }
 #else
 #else

+ 47 - 0
dtool/src/prc/pnotify.I

@@ -12,3 +12,50 @@
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
+
+////////////////////////////////////////////////////////////////////
+//     Function: Notify::has_assert_failed
+//       Access: Public
+//  Description: Returns true if an assertion test has failed (and not
+//               been ignored) since the last call to
+//               clear_assert_failed().
+//
+//               When an assertion test fails, the assert handler
+//               may decide either to abort, return, or ignore the
+//               assertion.  Naturally, if it decides to abort, this
+//               flag is irrelevant.  If it chooses to ignore the
+//               assertion, the flag is not set.  However, if the
+//               assert handler chooses to return out of the
+//               function (the normal case), it will also set this
+//               flag to indicate that an assertion failure has
+//               occurred.
+//
+//               This will also be the behavior in the absence of a
+//               user-defined assert handler.
+////////////////////////////////////////////////////////////////////
+INLINE bool Notify::
+has_assert_failed() const {
+  return _assert_failed;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Notify::get_assert_error_message
+//       Access: Public
+//  Description: Returns the error message that corresponds to the
+//               assertion that most recently failed.
+////////////////////////////////////////////////////////////////////
+INLINE const string &Notify::
+get_assert_error_message() const {
+  return _assert_error_message;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Notify::clear_assert_failed
+//       Access: Public
+//  Description: Resets the assert_failed flag that is set whenever an
+//               assertion test fails.  See has_assert_failed().
+////////////////////////////////////////////////////////////////////
+INLINE void Notify::
+clear_assert_failed() {
+  _assert_failed = false;
+}

+ 3 - 3
dtool/src/prc/pnotify.h

@@ -51,9 +51,9 @@ PUBLISHED:
   bool has_assert_handler() const;
   bool has_assert_handler() const;
   AssertHandler *get_assert_handler() const;
   AssertHandler *get_assert_handler() const;
 
 
-  bool has_assert_failed() const;
-  const string &get_assert_error_message() const;
-  void clear_assert_failed();
+  INLINE bool has_assert_failed() const;
+  INLINE const string &get_assert_error_message() const;
+  INLINE void clear_assert_failed();
 
 
   NotifyCategory *get_top_category();
   NotifyCategory *get_top_category();
   NotifyCategory *get_category(const string &basename,
   NotifyCategory *get_category(const string &basename,

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

@@ -194,6 +194,7 @@ extern "C" {
   EXPCL_PYSTUB extern void *PyExc_SystemExit;
   EXPCL_PYSTUB extern void *PyExc_SystemExit;
   EXPCL_PYSTUB extern void *PyExc_TypeError;
   EXPCL_PYSTUB extern void *PyExc_TypeError;
   EXPCL_PYSTUB extern void *PyExc_ValueError;
   EXPCL_PYSTUB extern void *PyExc_ValueError;
+  EXPCL_PYSTUB extern void *_PyThreadState_Current;
   EXPCL_PYSTUB extern void *_Py_FalseStruct;
   EXPCL_PYSTUB extern void *_Py_FalseStruct;
   EXPCL_PYSTUB extern void *_Py_NoneStruct;
   EXPCL_PYSTUB extern void *_Py_NoneStruct;
   EXPCL_PYSTUB extern void *_Py_NotImplementedStruct;
   EXPCL_PYSTUB extern void *_Py_NotImplementedStruct;
@@ -386,6 +387,7 @@ void *PyExc_StopIteration = (void *)NULL;
 void *PyExc_SystemExit = (void *)NULL;
 void *PyExc_SystemExit = (void *)NULL;
 void *PyExc_TypeError = (void *)NULL;
 void *PyExc_TypeError = (void *)NULL;
 void *PyExc_ValueError = (void *)NULL;
 void *PyExc_ValueError = (void *)NULL;
+void *_PyThreadState_Current = (void *)NULL;
 void *_Py_FalseStruct = (void *)NULL;
 void *_Py_FalseStruct = (void *)NULL;
 void *_Py_NoneStruct = (void *)NULL;
 void *_Py_NoneStruct = (void *)NULL;
 void *_Py_NotImplementedStruct = (void *)NULL;
 void *_Py_NotImplementedStruct = (void *)NULL;

+ 110 - 3
panda/src/display/graphicsWindowInputDevice.I

@@ -84,7 +84,7 @@ get_raw_pointer() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::set_device_index
 //     Function: GraphicsWindowInputDevice::set_device_index
 //       Access: Public
 //       Access: Public
-//  Description: Set the device index.  This is reported in pointer 
+//  Description: Set the device index.  This is reported in pointer
 //               events.  The device index will be equal to the position
 //               events.  The device index will be equal to the position
 //               of the GraphicsWindowInputDevice in the window's list.
 //               of the GraphicsWindowInputDevice in the window's list.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -117,9 +117,116 @@ disable_pointer_events() {
   _pointer_events.clear();
   _pointer_events.clear();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::button_down
+//       Access: Published
+//  Description: Records that the indicated button has been depressed.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindowInputDevice::
+button_down(ButtonHandle button) {
+  button_down(button, ClockObject::get_global_clock()->get_frame_time());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::button_resume_down
+//       Access: Published
+//  Description: Records that the indicated button was depressed
+//               earlier, and we only just detected the event after
+//               the fact.  This is mainly useful for tracking the
+//               state of modifier keys.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindowInputDevice::
+button_resume_down(ButtonHandle button) {
+  button_resume_down(button, ClockObject::get_global_clock()->get_frame_time());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::button_up
+//       Access: Published
+//  Description: Records that the indicated button has been released.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindowInputDevice::
+button_up(ButtonHandle button) {
+  button_up(button, ClockObject::get_global_clock()->get_frame_time());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::keystroke
+//       Access: Published
+//  Description: Records that the indicated keystroke has been
+//               generated.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindowInputDevice::
+keystroke(int keycode) {
+  keystroke(keycode, ClockObject::get_global_clock()->get_frame_time());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::focus_lost
+//       Access: Published
+//  Description: This should be called when the window focus is lost,
+//               so that we may miss upcoming button events
+//               (especially "up" events) for the next period of time.
+//               It generates keyboard and mouse "up" events for those
+//               buttons that we previously sent unpaired "down"
+//               events, so that the Panda application will believe
+//               all buttons are now released.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindowInputDevice::
+focus_lost() {
+  focus_lost(ClockObject::get_global_clock()->get_frame_time());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::raw_button_down
+//       Access: Published
+//  Description: Records that the indicated button has been depressed.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindowInputDevice::
+raw_button_down(ButtonHandle button) {
+  raw_button_down(button, ClockObject::get_global_clock()->get_frame_time());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::raw_button_up
+//       Access: Published
+//  Description: Records that the indicated button has been released.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindowInputDevice::
+raw_button_up(ButtonHandle button) {
+  raw_button_up(button, ClockObject::get_global_clock()->get_frame_time());
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::set_pointer_in_window
 //     Function: GraphicsWindowInputDevice::set_pointer_in_window
-//       Access: Public
+//       Access: Published
+//  Description: To be called by a particular kind of GraphicsWindow
+//               to indicate that the pointer is within the window, at
+//               the given pixel coordinates.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindowInputDevice::
+set_pointer_in_window(double x, double y) {
+  // mutex is handled in set pointer .. convience function
+  set_pointer(true, x, y, ClockObject::get_global_clock()->get_frame_time());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::set_pointer_out_of_window
+//       Access: Published
+//  Description: To be called by a particular kind of GraphicsWindow
+//               to indicate that the pointer is no longer within the
+//               window.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsWindowInputDevice::
+set_pointer_out_of_window() {
+ // mutex is handled in set pointer .. convience function
+  set_pointer(false, _mouse_data._xpos, _mouse_data._ypos,
+              ClockObject::get_global_clock()->get_frame_time());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindowInputDevice::set_pointer_in_window
+//       Access: Published
 //  Description: To be called by a particular kind of GraphicsWindow
 //  Description: To be called by a particular kind of GraphicsWindow
 //               to indicate that the pointer is within the window, at
 //               to indicate that the pointer is within the window, at
 //               the given pixel coordinates.
 //               the given pixel coordinates.
@@ -132,7 +239,7 @@ set_pointer_in_window(double x, double y, double time) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::set_pointer_out_of_window
 //     Function: GraphicsWindowInputDevice::set_pointer_out_of_window
-//       Access: Public
+//       Access: Published
 //  Description: To be called by a particular kind of GraphicsWindow
 //  Description: To be called by a particular kind of GraphicsWindow
 //               to indicate that the pointer is no longer within the
 //               to indicate that the pointer is no longer within the
 //               window.
 //               window.

+ 16 - 17
panda/src/display/graphicsWindowInputDevice.cxx

@@ -94,7 +94,7 @@ pointer_and_keyboard(GraphicsWindow *host, const string &name) {
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 GraphicsWindowInputDevice::
 GraphicsWindowInputDevice::
-GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy) 
+GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy)
 {
 {
     *this = copy;
     *this = copy;
 }
 }
@@ -105,7 +105,7 @@ GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy)
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsWindowInputDevice::
 void GraphicsWindowInputDevice::
-operator = (const GraphicsWindowInputDevice &copy) 
+operator = (const GraphicsWindowInputDevice &copy)
 {
 {
   LightMutexHolder holder(_lock);
   LightMutexHolder holder(_lock);
   LightMutexHolder holder1(copy._lock);
   LightMutexHolder holder1(copy._lock);
@@ -165,7 +165,7 @@ get_button_event() {
 //     Function: GraphicsWindowInputDevice::has_pointer_event
 //     Function: GraphicsWindowInputDevice::has_pointer_event
 //       Access: Public
 //       Access: Public
 //  Description: Returns true if this device has a pending pointer
 //  Description: Returns true if this device has a pending pointer
-//               event (a mouse movement), or false otherwise.  If 
+//               event (a mouse movement), or false otherwise.  If
 //               this returns true, the particular event may be
 //               this returns true, the particular event may be
 //               extracted via get_pointer_event().
 //               extracted via get_pointer_event().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -234,7 +234,7 @@ disable_pointer_mode() {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::set_pointer
 //     Function: GraphicsWindowInputDevice::set_pointer
-//       Access: Public
+//       Access: Published
 //  Description: Records that a mouse movement has taken place.
 //  Description: Records that a mouse movement has taken place.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsWindowInputDevice::
 void GraphicsWindowInputDevice::
@@ -264,7 +264,7 @@ set_pointer(bool inwin, double x, double y, double time) {
   } else {
   } else {
     _mouse_data = _true_mouse_data;
     _mouse_data = _true_mouse_data;
   }
   }
-  
+
   if (_enable_pointer_events) {
   if (_enable_pointer_events) {
     int seq = _event_sequence++;
     int seq = _event_sequence++;
     if (_pointer_events == 0) {
     if (_pointer_events == 0) {
@@ -279,7 +279,7 @@ set_pointer(bool inwin, double x, double y, double time) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::button_down
 //     Function: GraphicsWindowInputDevice::button_down
-//       Access: Public
+//       Access: Published
 //  Description: Records that the indicated button has been depressed.
 //  Description: Records that the indicated button has been depressed.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsWindowInputDevice::
 void GraphicsWindowInputDevice::
@@ -291,7 +291,7 @@ button_down(ButtonHandle button, double time) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::button_resume_down
 //     Function: GraphicsWindowInputDevice::button_resume_down
-//       Access: Public
+//       Access: Published
 //  Description: Records that the indicated button was depressed
 //  Description: Records that the indicated button was depressed
 //               earlier, and we only just detected the event after
 //               earlier, and we only just detected the event after
 //               the fact.  This is mainly useful for tracking the
 //               the fact.  This is mainly useful for tracking the
@@ -300,14 +300,13 @@ button_down(ButtonHandle button, double time) {
 void GraphicsWindowInputDevice::
 void GraphicsWindowInputDevice::
 button_resume_down(ButtonHandle button, double time) {
 button_resume_down(ButtonHandle button, double time) {
   LightMutexHolder holder(_lock);
   LightMutexHolder holder(_lock);
-  _button_events.push_back(ButtonEvent(button, ButtonEvent::T_resume_down, time)
-);
+  _button_events.push_back(ButtonEvent(button, ButtonEvent::T_resume_down, time));
   _buttons_held.insert(button);
   _buttons_held.insert(button);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::button_up
 //     Function: GraphicsWindowInputDevice::button_up
-//       Access: Public
+//       Access: Published
 //  Description: Records that the indicated button has been released.
 //  Description: Records that the indicated button has been released.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsWindowInputDevice::
 void GraphicsWindowInputDevice::
@@ -319,7 +318,7 @@ button_up(ButtonHandle button, double time) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::keystroke
 //     Function: GraphicsWindowInputDevice::keystroke
-//       Access: Public
+//       Access: Published
 //  Description: Records that the indicated keystroke has been
 //  Description: Records that the indicated keystroke has been
 //               generated.
 //               generated.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -331,24 +330,24 @@ keystroke(int keycode, double time) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::candidate
 //     Function: GraphicsWindowInputDevice::candidate
-//       Access: Public
+//       Access: Published
 //  Description: Records that the indicated candidate string has been
 //  Description: Records that the indicated candidate string has been
 //               highlighted.  This is used to implement IME support
 //               highlighted.  This is used to implement IME support
 //               for typing in international languages, especially
 //               for typing in international languages, especially
 //               Chinese/Japanese/Korean.
 //               Chinese/Japanese/Korean.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsWindowInputDevice::
 void GraphicsWindowInputDevice::
-candidate(const wstring &candidate_string, size_t highlight_start, 
+candidate(const wstring &candidate_string, size_t highlight_start,
           size_t highlight_end, size_t cursor_pos) {
           size_t highlight_end, size_t cursor_pos) {
   LightMutexHolder holder(_lock);
   LightMutexHolder holder(_lock);
-  _button_events.push_back(ButtonEvent(candidate_string, 
+  _button_events.push_back(ButtonEvent(candidate_string,
                                        highlight_start, highlight_end,
                                        highlight_start, highlight_end,
                                        cursor_pos));
                                        cursor_pos));
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::focus_lost
 //     Function: GraphicsWindowInputDevice::focus_lost
-//       Access: Public
+//       Access: Published
 //  Description: This should be called when the window focus is lost,
 //  Description: This should be called when the window focus is lost,
 //               so that we may miss upcoming button events
 //               so that we may miss upcoming button events
 //               (especially "up" events) for the next period of time.
 //               (especially "up" events) for the next period of time.
@@ -369,7 +368,7 @@ focus_lost(double time) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::raw_button_down
 //     Function: GraphicsWindowInputDevice::raw_button_down
-//       Access: Public
+//       Access: Published
 //  Description: Records that the indicated button has been depressed.
 //  Description: Records that the indicated button has been depressed.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsWindowInputDevice::
 void GraphicsWindowInputDevice::
@@ -380,7 +379,7 @@ raw_button_down(ButtonHandle button, double time) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindowInputDevice::raw_button_up
 //     Function: GraphicsWindowInputDevice::raw_button_up
-//       Access: Public
+//       Access: Published
 //  Description: Records that the indicated button has been released.
 //  Description: Records that the indicated button has been released.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsWindowInputDevice::
 void GraphicsWindowInputDevice::

+ 20 - 10
panda/src/display/graphicsWindowInputDevice.h

@@ -76,18 +76,28 @@ public:
 PUBLISHED:
 PUBLISHED:
   // The following interface is for the various kinds of
   // The following interface is for the various kinds of
   // GraphicsWindows to record the data incoming on the device.
   // GraphicsWindows to record the data incoming on the device.
-  void button_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
-  void button_resume_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
-  void button_up(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
-  void keystroke(int keycode, double time = ClockObject::get_global_clock()->get_frame_time());
-  void candidate(const wstring &candidate_string, size_t highlight_start, 
+  INLINE void button_down(ButtonHandle button);
+  INLINE void button_resume_down(ButtonHandle button);
+  INLINE void button_up(ButtonHandle button);
+  INLINE void keystroke(int keycode);
+  INLINE void focus_lost();
+  INLINE void raw_button_down(ButtonHandle button);
+  INLINE void raw_button_up(ButtonHandle button);
+  INLINE void set_pointer_in_window(double x, double y);
+  INLINE void set_pointer_out_of_window();
+
+  void button_down(ButtonHandle button, double time);
+  void button_resume_down(ButtonHandle button, double time);
+  void button_up(ButtonHandle button, double time);
+  void keystroke(int keycode, double time);
+  void candidate(const wstring &candidate_string, size_t highlight_start,
                  size_t highlight_end, size_t cursor_pos);
                  size_t highlight_end, size_t cursor_pos);
-  void focus_lost(double time = ClockObject::get_global_clock()->get_frame_time());
-  void raw_button_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
-  void raw_button_up(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
+  void focus_lost(double time);
+  void raw_button_down(ButtonHandle button, double time);
+  void raw_button_up(ButtonHandle button, double time);
 
 
-  INLINE void set_pointer_in_window(double x, double y, double time = ClockObject::get_global_clock()->get_frame_time());
-  INLINE void set_pointer_out_of_window(double time = ClockObject::get_global_clock()->get_frame_time());
+  INLINE void set_pointer_in_window(double x, double y, double time);
+  INLINE void set_pointer_out_of_window(double time);
   void set_pointer(bool inwin, double x, double y, double time);
   void set_pointer(bool inwin, double x, double y, double time);
 
 
 public:
 public:

+ 32 - 1
panda/src/express/pointerTo.I

@@ -109,6 +109,22 @@ operator T * () const {
   return (To *)(this->_void_ptr);
   return (To *)(this->_void_ptr);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PointerTo::cheat
+//       Access: Public
+//  Description: Returns a reference to the underlying pointer.  This
+//               is a very unsafe method.  It's only used by some
+//               interrogate code.  If you think this method might be
+//               useful to you, you're probably wrong.
+//
+//               Promise me you won't use this, okay?
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE T *&PointerTo<T>::
+cheat() {
+  return (To *&)(this->_void_ptr);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PointerTo::p
 //     Function: PointerTo::p
 //       Access: Published
 //       Access: Published
@@ -274,13 +290,28 @@ operator -> () const {
 //               don't care which way it goes because either will be
 //               don't care which way it goes because either will be
 //               correct.
 //               correct.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-
 template<class T>
 template<class T>
 INLINE ConstPointerTo<T>::
 INLINE ConstPointerTo<T>::
 operator const T * () const {
 operator const T * () const {
 return (To *)(this->_void_ptr);
 return (To *)(this->_void_ptr);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ConstPointerTo::cheat
+//       Access: Public
+//  Description: Returns a reference to the underlying pointer.  This
+//               is a very unsafe method.  It's only used by some
+//               interrogate code.  If you think this method might be
+//               useful to you, you're probably wrong.
+//
+//               Promise me you won't use this, okay?
+////////////////////////////////////////////////////////////////////
+template<class T>
+INLINE const T *&ConstPointerTo<T>::
+cheat() {
+  return (const To *&)(this->_void_ptr);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ConstPointerTo::p
 //     Function: ConstPointerTo::p
 //       Access: Published
 //       Access: Published

+ 4 - 0
panda/src/express/pointerTo.h

@@ -95,6 +95,8 @@ public:
   // MSVC.NET 2005 insists that we use T *, and not To *, here.
   // MSVC.NET 2005 insists that we use T *, and not To *, here.
   INLINE operator T *() const;
   INLINE operator T *() const;
 
 
+  INLINE T *&cheat();
+
 PUBLISHED:
 PUBLISHED:
   // When downcasting to a derived class from a PointerTo<BaseClass>,
   // When downcasting to a derived class from a PointerTo<BaseClass>,
   // C++ would normally require you to cast twice: once to an actual
   // C++ would normally require you to cast twice: once to an actual
@@ -160,6 +162,8 @@ public:
   INLINE const To *operator -> () const;
   INLINE const To *operator -> () const;
   INLINE operator const T *() const;
   INLINE operator const T *() const;
 
 
+  INLINE const T *&cheat();
+
 PUBLISHED:
 PUBLISHED:
   INLINE const To *p() const;
   INLINE const To *p() const;
 
 

+ 4 - 5
panda/src/express/referenceCount.I

@@ -89,7 +89,7 @@ operator = (const ReferenceCount &) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ReferenceCount::Destructor
 //     Function: ReferenceCount::Destructor
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 ReferenceCount::
 ReferenceCount::
 ~ReferenceCount() {
 ~ReferenceCount() {
@@ -182,7 +182,7 @@ ref() const {
   nassertv(test_ref_count_integrity());
   nassertv(test_ref_count_integrity());
 #endif
 #endif
 
 
-  AtomicAdjust::inc(((ReferenceCount *)this)->_ref_count);
+  AtomicAdjust::inc(_ref_count);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -221,10 +221,9 @@ unref() const {
   // directly?  Are you sure you can't use PointerTo's?
   // directly?  Are you sure you can't use PointerTo's?
   nassertr(_ref_count > 0, 0);
   nassertr(_ref_count > 0, 0);
 #endif
 #endif
-  return AtomicAdjust::dec(((ReferenceCount *)this)->_ref_count);
+  return AtomicAdjust::dec(_ref_count);
 }
 }
 
 
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ReferenceCount::test_ref_count_integrity
 //     Function: ReferenceCount::test_ref_count_integrity
 //       Access: Published
 //       Access: Published
@@ -360,7 +359,7 @@ unref_delete(RefCountType *ptr) {
   if (!ptr->unref()) {
   if (!ptr->unref()) {
     // If the reference count has gone to zero, delete the object.
     // If the reference count has gone to zero, delete the object.
     delete ptr;
     delete ptr;
-  } 
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 2
panda/src/express/referenceCount.h

@@ -71,7 +71,7 @@ private:
   void create_weak_list();
   void create_weak_list();
 
 
 private:
 private:
-  enum { 
+  enum {
     // We use this value as a flag to indicate an object has been
     // We use this value as a flag to indicate an object has been
     // indicated as a local object, and should not be deleted except
     // indicated as a local object, and should not be deleted except
     // by its own destructor.  Really, any nonzero value would do, but
     // by its own destructor.  Really, any nonzero value would do, but
@@ -87,7 +87,7 @@ private:
     deleted_ref_count = -100,
     deleted_ref_count = -100,
   };
   };
 
 
-  AtomicAdjust::Integer _ref_count;
+  mutable AtomicAdjust::Integer _ref_count;
   AtomicAdjust::Pointer _weak_list;  // WeakReferenceList *
   AtomicAdjust::Pointer _weak_list;  // WeakReferenceList *
 
 
 public:
 public:

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