mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-05 03:15:07 -04:00
low-level support for python copy and pickle modules
This commit is contained in:
parent
3e82b3d163
commit
816ddc0387
@ -302,6 +302,30 @@ Filename(const Filename &dirname, const Filename &basename) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: Filename::__reduce__
|
||||||
|
// Access: Published
|
||||||
|
// Description: This special Python method is implement to provide
|
||||||
|
// support for the pickle module.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *Filename::
|
||||||
|
__reduce__(PyObject *self) const {
|
||||||
|
// We should return at least a 2-tuple, (Class, (args)): the
|
||||||
|
// necessary class object whose constructor we should call
|
||||||
|
// (e.g. this), and the arguments necessary to reconstruct this
|
||||||
|
// object.
|
||||||
|
PyObject *this_class = PyObject_Type(self);
|
||||||
|
if (this_class == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *result = Py_BuildValue("(O(s))", this_class, c_str());
|
||||||
|
Py_DECREF(this_class);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: Filename::from_os_specific
|
// Function: Filename::from_os_specific
|
||||||
// Access: Published, Static
|
// Access: Published, Static
|
||||||
|
@ -66,6 +66,10 @@ PUBLISHED:
|
|||||||
Filename(const Filename &dirname, const Filename &basename);
|
Filename(const Filename &dirname, const Filename &basename);
|
||||||
INLINE ~Filename();
|
INLINE ~Filename();
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
PyObject *__reduce__(PyObject *self) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Static constructors to explicitly create a filename that refers
|
// Static constructors to explicitly create a filename that refers
|
||||||
// to a text or binary file. This is in lieu of calling set_text()
|
// to a text or binary file. This is in lieu of calling set_text()
|
||||||
// or set_binary() or set_type().
|
// or set_binary() or set_type().
|
||||||
|
@ -297,6 +297,16 @@ make_wrapper_entry(FunctionIndex function_index) {
|
|||||||
assert(!iwrapper._parameters.empty());
|
assert(!iwrapper._parameters.empty());
|
||||||
iwrapper._parameters.front()._parameter_flags |=
|
iwrapper._parameters.front()._parameter_flags |=
|
||||||
InterrogateFunctionWrapper::PF_is_this;
|
InterrogateFunctionWrapper::PF_is_this;
|
||||||
|
|
||||||
|
if (_parameters.size() >= 2 && _parameters[1]._name == "self" &&
|
||||||
|
TypeManager::is_pointer_to_PyObject(_parameters[1]._remap->get_orig_type())) {
|
||||||
|
// Here's a special case. If the first parameter of a nonstatic
|
||||||
|
// method is a PyObject * called "self", then we will
|
||||||
|
// automatically fill it in from the this pointer, and remove it
|
||||||
|
// from the generated parameter list.
|
||||||
|
_parameters.erase(_parameters.begin() + 1);
|
||||||
|
_flags |= F_explicit_self;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_void_return) {
|
if (!_void_return) {
|
||||||
@ -382,6 +392,14 @@ get_call_str(const string &container, const vector_string &pexprs) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
call << "(";
|
call << "(";
|
||||||
|
if (_flags & F_explicit_self) {
|
||||||
|
// Pass on the PyObject * that we stripped off above.
|
||||||
|
call << "self";
|
||||||
|
if (_first_true_parameter < (int)_parameters.size()) {
|
||||||
|
call << ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int pn = _first_true_parameter;
|
int pn = _first_true_parameter;
|
||||||
if (pn < (int)_parameters.size()) {
|
if (pn < (int)_parameters.size()) {
|
||||||
_parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
|
_parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
|
||||||
@ -630,6 +648,23 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
|
|||||||
// It receives no parameters, and returns an integer.
|
// It receives no parameters, and returns an integer.
|
||||||
_flags |= F_size;
|
_flags |= F_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (fname == "make_copy" ) {
|
||||||
|
if (_has_this && _parameters.size() == 1 &&
|
||||||
|
TypeManager::is_pointer(_return_type->get_new_type())) {
|
||||||
|
// It receives no parameters, and returns a pointer.
|
||||||
|
_flags |= F_make_copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (_type == T_constructor) {
|
||||||
|
if (!_has_this && _parameters.size() == 1) {
|
||||||
|
if (TypeManager::unwrap(_parameters[0]._remap->get_orig_type()) ==
|
||||||
|
TypeManager::unwrap(_return_type->get_orig_type())) {
|
||||||
|
// If this is the only parameter, and it's the same as the
|
||||||
|
// "this" type, this is a copy constructor.
|
||||||
|
_flags |= F_copy_constructor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +84,9 @@ public:
|
|||||||
F_size = 0x0004,
|
F_size = 0x0004,
|
||||||
F_setitem = 0x0008,
|
F_setitem = 0x0008,
|
||||||
F_setitem_int = 0x0010,
|
F_setitem_int = 0x0010,
|
||||||
|
F_make_copy = 0x0020,
|
||||||
|
F_copy_constructor = 0x0040,
|
||||||
|
F_explicit_self = 0x0080,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef vector<Parameter> Parameters;
|
typedef vector<Parameter> Parameters;
|
||||||
|
@ -123,6 +123,10 @@ check_protocols() {
|
|||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
Functions::const_iterator fi;
|
Functions::const_iterator fi;
|
||||||
|
for (fi = _constructors.begin(); fi != _constructors.end(); ++fi) {
|
||||||
|
Function *func = (*fi);
|
||||||
|
flags |= func->_flags;
|
||||||
|
}
|
||||||
for (fi = _methods.begin(); fi != _methods.end(); ++fi) {
|
for (fi = _methods.begin(); fi != _methods.end(); ++fi) {
|
||||||
Function *func = (*fi);
|
Function *func = (*fi);
|
||||||
flags |= func->_flags;
|
flags |= func->_flags;
|
||||||
@ -140,6 +144,16 @@ check_protocols() {
|
|||||||
_protocol_types |= PT_mapping;
|
_protocol_types |= PT_mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & FunctionRemap::F_make_copy) {
|
||||||
|
// It's not exactly a protocol, but if we have a make_copy()
|
||||||
|
// method, we can use it to synthesize a __copy__ and __deepcopy__
|
||||||
|
// Python method to support the copy module.
|
||||||
|
_protocol_types |= PT_make_copy;
|
||||||
|
} else if (flags & FunctionRemap::F_copy_constructor) {
|
||||||
|
// Ditto for the copy constructor.
|
||||||
|
_protocol_types |= PT_copy_constructor;
|
||||||
|
}
|
||||||
|
|
||||||
// Now are there any make_seq requests within this class?
|
// Now are there any make_seq requests within this class?
|
||||||
CPPStructType *stype = _itype._cpptype->as_struct_type();
|
CPPStructType *stype = _itype._cpptype->as_struct_type();
|
||||||
if (stype != (CPPStructType *)NULL) {
|
if (stype != (CPPStructType *)NULL) {
|
||||||
|
@ -112,6 +112,8 @@ public:
|
|||||||
enum ProtocolTypes {
|
enum ProtocolTypes {
|
||||||
PT_sequence = 0x0001,
|
PT_sequence = 0x0001,
|
||||||
PT_mapping = 0x0002,
|
PT_mapping = 0x0002,
|
||||||
|
PT_make_copy = 0x0004,
|
||||||
|
PT_copy_constructor = 0x0008,
|
||||||
};
|
};
|
||||||
int _protocol_types;
|
int _protocol_types;
|
||||||
};
|
};
|
||||||
|
@ -98,6 +98,9 @@ RenameSet methodRenameDictionary[] = {
|
|||||||
{ "operator >>=" , "__irshift__", 1 },
|
{ "operator >>=" , "__irshift__", 1 },
|
||||||
{ "operator typecast bool", "__nonzero__", 0 },
|
{ "operator typecast bool", "__nonzero__", 0 },
|
||||||
{ "__nonzero__" , "__nonzero__", 0 },
|
{ "__nonzero__" , "__nonzero__", 0 },
|
||||||
|
{ "__reduce__" , "__reduce__", 0 },
|
||||||
|
{ "__copy__" , "__copy__", 0 },
|
||||||
|
{ "__deepcopy__" , "__deepcopy__", 0 },
|
||||||
{ "print" , "Cprint", 0 },
|
{ "print" , "Cprint", 0 },
|
||||||
{ "CInterval.set_t", "_priv__cSetT", 0 },
|
{ "CInterval.set_t", "_priv__cSetT", 0 },
|
||||||
{ NULL, NULL, -1 }
|
{ NULL, NULL, -1 }
|
||||||
@ -186,7 +189,9 @@ const char * pythonKeywords[] = {
|
|||||||
"finally",
|
"finally",
|
||||||
"in",
|
"in",
|
||||||
"print",
|
"print",
|
||||||
NULL};
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
std::string checkKeyword(std::string & cppName)
|
std::string checkKeyword(std::string & cppName)
|
||||||
{
|
{
|
||||||
@ -837,7 +842,7 @@ void InterfaceMakerPythonNative::write_functions(ostream &out)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Objects::iterator oi;
|
// Objects::iterator oi;
|
||||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi)
|
for (oi = _objects.begin(); oi != _objects.end(); ++oi)
|
||||||
{
|
{
|
||||||
Object *object = (*oi).second;
|
Object *object = (*oi).second;
|
||||||
@ -850,8 +855,8 @@ void InterfaceMakerPythonNative::write_functions(ostream &out)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
inside_python_native = true;
|
inside_python_native = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Function : write_ClasseDetails
|
// Function : write_ClasseDetails
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -899,7 +904,7 @@ void InterfaceMakerPythonNative::write_ClasseDetails(ostream &out, Object * obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool AnyLeganConstructors;
|
// bool AnyLeganConstructors;
|
||||||
|
|
||||||
if(obj->_constructors.size() == 0)
|
if(obj->_constructors.size() == 0)
|
||||||
{
|
{
|
||||||
@ -990,8 +995,8 @@ void InterfaceMakerPythonNative::write_ClasseDetails(ostream &out, Object * obj)
|
|||||||
out << "}\n";
|
out << "}\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Function : write_ClasseDeclarations
|
/// Function : write_ClasseDeclarations
|
||||||
//
|
//
|
||||||
@ -1215,9 +1220,18 @@ write_module_class(ostream &out, Object *obj) {
|
|||||||
std::map<Function *, std::string > normal_Operator_functions;
|
std::map<Function *, std::string > normal_Operator_functions;
|
||||||
std::map<Function *, SlottedFunctionDef> wraped_Operator_functions;
|
std::map<Function *, SlottedFunctionDef> wraped_Operator_functions;
|
||||||
// function Table
|
// function Table
|
||||||
|
bool got_copy = false;
|
||||||
|
bool got_deepcopy = false;
|
||||||
|
|
||||||
int x;
|
int x;
|
||||||
for (x = 0, fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi,x++) {
|
for (x = 0, fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi,x++) {
|
||||||
Function *func = (*fi);
|
Function *func = (*fi);
|
||||||
|
if (func->_name == "__copy__") {
|
||||||
|
got_copy = true;
|
||||||
|
} else if (func->_name == "__deepcopy__") {
|
||||||
|
got_deepcopy = true;
|
||||||
|
}
|
||||||
|
|
||||||
SlottedFunctionDef slotted_def;
|
SlottedFunctionDef slotted_def;
|
||||||
if (!get_slotted_function_def(obj, func, slotted_def)) {
|
if (!get_slotted_function_def(obj, func, slotted_def)) {
|
||||||
out << " { \"" << methodNameFromCppName(func,export_calss_name) << "\",(PyCFunction ) &"
|
out << " { \"" << methodNameFromCppName(func,export_calss_name) << "\",(PyCFunction ) &"
|
||||||
@ -1248,6 +1262,22 @@ write_module_class(ostream &out, Object *obj) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (obj->_protocol_types & Object::PT_make_copy) {
|
||||||
|
if (!got_copy) {
|
||||||
|
out << " { \"__copy__\", (PyCFunction)©_from_make_copy, METH_NOARGS, NULL},\n";
|
||||||
|
got_copy = true;
|
||||||
|
}
|
||||||
|
} else if (obj->_protocol_types & Object::PT_copy_constructor) {
|
||||||
|
if (!got_copy) {
|
||||||
|
out << " { \"__copy__\", (PyCFunction)©_from_copy_constructor, METH_NOARGS, NULL},\n";
|
||||||
|
got_copy = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (got_copy && !got_deepcopy) {
|
||||||
|
out << " { \"__deepcopy__\", (PyCFunction)&map_deepcopy_to_copy, METH_VARARGS, NULL},\n";
|
||||||
|
}
|
||||||
|
|
||||||
MakeSeqs::iterator msi;
|
MakeSeqs::iterator msi;
|
||||||
for (msi = obj->_make_seqs.begin(); msi != obj->_make_seqs.end(); ++msi) {
|
for (msi = obj->_make_seqs.begin(); msi != obj->_make_seqs.end(); ++msi) {
|
||||||
out << " { \""
|
out << " { \""
|
||||||
|
@ -708,6 +708,42 @@ PyObject *make_list_for_item(PyObject *self, const char *num_name,
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: copy_from_make_copy
|
||||||
|
// Description: This is a support function for a synthesized
|
||||||
|
// __copy__() method from a C++ make_copy() method.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *copy_from_make_copy(PyObject *self) {
|
||||||
|
return PyObject_CallMethod(self, (char *)"makeCopy", (char *)"()");
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: copy_from_make_copy
|
||||||
|
// Description: This is a support function for a synthesized
|
||||||
|
// __copy__() method from a C++ copy constructor.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *copy_from_copy_constructor(PyObject *self) {
|
||||||
|
PyObject *this_class = PyObject_Type(self);
|
||||||
|
if (this_class == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *result = PyObject_CallFunction(this_class, (char *)"(O)", self);
|
||||||
|
Py_DECREF(this_class);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: copy_from_make_copy
|
||||||
|
// Description: This is a support function for a synthesized
|
||||||
|
// __deepcopy__() method for any class that has a
|
||||||
|
// __copy__() method. The sythethic method simply
|
||||||
|
// invokes __copy__().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *map_deepcopy_to_copy(PyObject *self, PyObject *args) {
|
||||||
|
return PyObject_CallMethod(self, (char *)"__copy__", (char *)"()");
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PyLongOrInt_FromUnsignedLong
|
// Function: PyLongOrInt_FromUnsignedLong
|
||||||
// Description: Similar to PyLong_FromUnsignedLong(), but returns
|
// Description: Similar to PyLong_FromUnsignedLong(), but returns
|
||||||
|
@ -174,114 +174,118 @@ struct Dtool_PyTypedObject {
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Macro's from Hell.. May want to Just Add this to the Code generator..
|
// Macros from Hell.. May want to just add this to the code generator..
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
#define Define_Dtool_Class(MODULE_NAME, CLASS_NAME, PUBLIC_NAME) \
|
#define Define_Dtool_Class(MODULE_NAME, CLASS_NAME, PUBLIC_NAME) \
|
||||||
static PyNumberMethods Dtool_PyNumberMethods_##CLASS_NAME ={\
|
static PyNumberMethods Dtool_PyNumberMethods_##CLASS_NAME = \
|
||||||
0,/*binaryfunc nb_add*/\
|
{ \
|
||||||
0,/*binaryfunc nb_subtract*/\
|
0,/*binaryfunc nb_add*/ \
|
||||||
0,/*binaryfunc nb_multiply*/\
|
0,/*binaryfunc nb_subtract*/ \
|
||||||
0,/*binaryfunc nb_divide*/\
|
0,/*binaryfunc nb_multiply*/ \
|
||||||
0,/*binaryfunc nb_remainder*/\
|
0,/*binaryfunc nb_divide*/ \
|
||||||
0,/*binaryfunc nb_divmod*/\
|
0,/*binaryfunc nb_remainder*/ \
|
||||||
0,/*ternaryfunc nb_power*/\
|
0,/*binaryfunc nb_divmod*/ \
|
||||||
0,/*unaryfunc nb_negative*/\
|
0,/*ternaryfunc nb_power*/ \
|
||||||
0,/*unaryfunc nb_positive*/\
|
0,/*unaryfunc nb_negative*/ \
|
||||||
0,/*unaryfunc nb_absolute*/\
|
0,/*unaryfunc nb_positive*/ \
|
||||||
0,/*inquiry nb_nonzero*/\
|
0,/*unaryfunc nb_absolute*/ \
|
||||||
0,/*unaryfunc nb_invert*/\
|
0,/*inquiry nb_nonzero*/ \
|
||||||
0,/*binaryfunc nb_lshift*/\
|
0,/*unaryfunc nb_invert*/ \
|
||||||
0,/*binaryfunc nb_rshift*/\
|
0,/*binaryfunc nb_lshift*/ \
|
||||||
0,/*binaryfunc nb_and*/\
|
0,/*binaryfunc nb_rshift*/ \
|
||||||
0,/*binaryfunc nb_xor*/\
|
0,/*binaryfunc nb_and*/ \
|
||||||
0,/*binaryfunc nb_or*/\
|
0,/*binaryfunc nb_xor*/ \
|
||||||
0,/*coercion nb_coerce*/\
|
0,/*binaryfunc nb_or*/ \
|
||||||
0,/*unaryfunc nb_int*/\
|
0,/*coercion nb_coerce*/ \
|
||||||
0,/*unaryfunc nb_long*/\
|
0,/*unaryfunc nb_int*/ \
|
||||||
0,/*unaryfunc nb_float*/\
|
0,/*unaryfunc nb_long*/ \
|
||||||
0,/*unaryfunc nb_oct*/\
|
0,/*unaryfunc nb_float*/ \
|
||||||
0,/*unaryfunc nb_hex*/\
|
0,/*unaryfunc nb_oct*/ \
|
||||||
0,/*binaryfunc nb_inplace_add*/\
|
0,/*unaryfunc nb_hex*/ \
|
||||||
0,/*binaryfunc nb_inplace_subtract*/\
|
0,/*binaryfunc nb_inplace_add*/ \
|
||||||
0,/*binaryfunc nb_inplace_multiply*/\
|
0,/*binaryfunc nb_inplace_subtract*/ \
|
||||||
0,/*binaryfunc nb_inplace_divide*/\
|
0,/*binaryfunc nb_inplace_multiply*/ \
|
||||||
0,/*binaryfunc nb_inplace_remainder*/\
|
0,/*binaryfunc nb_inplace_divide*/ \
|
||||||
0,/*ternaryfunc nb_inplace_power*/\
|
0,/*binaryfunc nb_inplace_remainder*/ \
|
||||||
0,/*binaryfunc nb_inplace_lshift*/\
|
0,/*ternaryfunc nb_inplace_power*/ \
|
||||||
0,/*binaryfunc nb_inplace_rshift*/\
|
0,/*binaryfunc nb_inplace_lshift*/ \
|
||||||
0,/*binaryfunc nb_inplace_and*/\
|
0,/*binaryfunc nb_inplace_rshift*/ \
|
||||||
0,/*binaryfunc nb_inplace_xor*/\
|
0,/*binaryfunc nb_inplace_and*/ \
|
||||||
0,/*binaryfunc nb_inplace_or*/\
|
0,/*binaryfunc nb_inplace_xor*/ \
|
||||||
0,/*binaryfunc nb_floor_divide*/\
|
0,/*binaryfunc nb_inplace_or*/ \
|
||||||
0,/*binaryfunc nb_true_divide*/\
|
0,/*binaryfunc nb_floor_divide*/ \
|
||||||
0,/*binaryfunc nb_inplace_floor_divide*/\
|
0,/*binaryfunc nb_true_divide*/ \
|
||||||
0,/*binaryfunc nb_inplace_true_divide*/\
|
0,/*binaryfunc nb_inplace_floor_divide*/ \
|
||||||
};\
|
0,/*binaryfunc nb_inplace_true_divide*/ \
|
||||||
static PySequenceMethods Dtool_PySequenceMethods_##CLASS_NAME ={\
|
}; \
|
||||||
0,/*lenfunc sq_length */\
|
static PySequenceMethods Dtool_PySequenceMethods_##CLASS_NAME = \
|
||||||
0,/*binaryfunc sq_concat */\
|
{ \
|
||||||
0,/*ssizeargfunc sq_repeat */\
|
0,/*lenfunc sq_length */ \
|
||||||
0,/*ssizeargfunc sq_item */\
|
0,/*binaryfunc sq_concat */ \
|
||||||
0,/*ssizeargfunc sq_ass_item */\
|
0,/*ssizeargfunc sq_repeat */ \
|
||||||
0,/*objobjproc sq_contains */\
|
0,/*ssizeargfunc sq_item */ \
|
||||||
0,/*binaryfunc sq_inplace_concat */\
|
0,/*ssizeargfunc sq_ass_item */ \
|
||||||
0,/*ssizeargfunc sq_inplace_repeat */\
|
0,/*objobjproc sq_contains */ \
|
||||||
};\
|
0,/*binaryfunc sq_inplace_concat */ \
|
||||||
static PyMappingMethods Dtool_PyMappingMethods_##CLASS_NAME ={\
|
0,/*ssizeargfunc sq_inplace_repeat */ \
|
||||||
0,/*inquiry mp_length */\
|
}; \
|
||||||
0,/*binaryfunc mp_subscript */\
|
static PyMappingMethods Dtool_PyMappingMethods_##CLASS_NAME = \
|
||||||
0,/*objobjargproc mp_ass_subscript */\
|
{ \
|
||||||
};\
|
0,/*inquiry mp_length */ \
|
||||||
EXPORT_THIS Dtool_PyTypedObject Dtool_##CLASS_NAME = {\
|
0,/*binaryfunc mp_subscript */ \
|
||||||
{\
|
0,/*objobjargproc mp_ass_subscript */ \
|
||||||
PyObject_HEAD_INIT(NULL)\
|
}; \
|
||||||
0,\
|
EXPORT_THIS Dtool_PyTypedObject Dtool_##CLASS_NAME = \
|
||||||
|
{ \
|
||||||
|
{ \
|
||||||
|
PyObject_HEAD_INIT(NULL) \
|
||||||
|
0, \
|
||||||
"lib" #MODULE_NAME "." #PUBLIC_NAME, /*type name with module */ \
|
"lib" #MODULE_NAME "." #PUBLIC_NAME, /*type name with module */ \
|
||||||
sizeof(Dtool_PyInstDef), /* tp_basicsize*/ \
|
sizeof(Dtool_PyInstDef), /* tp_basicsize */ \
|
||||||
0, /*tp_itemsize*/ \
|
0, /* tp_itemsize */ \
|
||||||
&Dtool_Deallocate_General, /*Dtool_Deallocate_##CLASS_NAME,*/ /*tp_dealloc*/\
|
&Dtool_Deallocate_General, /* tp_dealloc */ \
|
||||||
0, /*tp_print*/\
|
0, /* tp_print */ \
|
||||||
0, /*tp_getattr*/\
|
0, /* tp_getattr */ \
|
||||||
0, /*tp_setattr*/\
|
0, /* tp_setattr */ \
|
||||||
0, /*tp_compare*/\
|
0, /* tp_compare */ \
|
||||||
0, /*tp_repr*/\
|
0, /* tp_repr */ \
|
||||||
&Dtool_PyNumberMethods_##CLASS_NAME, /*tp_as_number*/\
|
&Dtool_PyNumberMethods_##CLASS_NAME, /* tp_as_number */ \
|
||||||
&Dtool_PySequenceMethods_##CLASS_NAME, /*tp_as_sequence*/\
|
&Dtool_PySequenceMethods_##CLASS_NAME, /* tp_as_sequence */ \
|
||||||
&Dtool_PyMappingMethods_##CLASS_NAME, /*tp_as_mapping*/\
|
&Dtool_PyMappingMethods_##CLASS_NAME, /* tp_as_mapping */ \
|
||||||
0, /*tp_hash */\
|
0, /* tp_hash */ \
|
||||||
0, /* tp_call */\
|
0, /* tp_call */ \
|
||||||
0, /* tp_str */\
|
0, /* tp_str */ \
|
||||||
PyObject_GenericGetAttr, /* tp_getattro */\
|
PyObject_GenericGetAttr, /* tp_getattro */ \
|
||||||
PyObject_GenericSetAttr, /* tp_setattro */\
|
PyObject_GenericSetAttr, /* tp_setattro */ \
|
||||||
0, /* tp_as_buffer */\
|
0, /* tp_as_buffer */ \
|
||||||
(Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES), /* tp_flags */\
|
(Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES), /* tp_flags */ \
|
||||||
0, /* tp_doc */\
|
0, /* tp_doc */ \
|
||||||
0, /* tp_traverse */\
|
0, /* tp_traverse */ \
|
||||||
0, /* tp_clear */\
|
0, /* tp_clear */ \
|
||||||
0, /* tp_richcompare */\
|
0, /* tp_richcompare */ \
|
||||||
0, /* tp_weaklistoffset */\
|
0, /* tp_weaklistoffset */ \
|
||||||
0, /* tp_iter */\
|
0, /* tp_iter */ \
|
||||||
0, /* tp_iternext */\
|
0, /* tp_iternext */ \
|
||||||
Dtool_Methods_##CLASS_NAME, /* tp_methods */\
|
Dtool_Methods_##CLASS_NAME, /* tp_methods */ \
|
||||||
standard_type_members, /* tp_members */\
|
standard_type_members, /* tp_members */ \
|
||||||
0, /* tp_getset */\
|
0, /* tp_getset */ \
|
||||||
0, /* tp_base */\
|
0, /* tp_base */ \
|
||||||
0, /* tp_dict */\
|
0, /* tp_dict */ \
|
||||||
0, /* tp_descr_get */\
|
0, /* tp_descr_get */ \
|
||||||
0, /* tp_descr_set */\
|
0, /* tp_descr_set */ \
|
||||||
0, /* tp_dictoffset */\
|
0, /* tp_dictoffset */ \
|
||||||
Dtool_Init_##CLASS_NAME, /* tp_init */\
|
Dtool_Init_##CLASS_NAME, /* tp_init */ \
|
||||||
PyType_GenericAlloc, /* tp_alloc */\
|
PyType_GenericAlloc, /* tp_alloc */ \
|
||||||
Dtool_new_##CLASS_NAME, /* tp_new */\
|
Dtool_new_##CLASS_NAME, /* tp_new */ \
|
||||||
_PyObject_Del, /* tp_free */\
|
_PyObject_Del, /* tp_free */ \
|
||||||
},\
|
}, \
|
||||||
#CLASS_NAME, \
|
#CLASS_NAME, \
|
||||||
false,\
|
false, \
|
||||||
Dtool_UpcastInterface_##CLASS_NAME, \
|
Dtool_UpcastInterface_##CLASS_NAME, \
|
||||||
Dtool_DowncastInterface_##CLASS_NAME, \
|
Dtool_DowncastInterface_##CLASS_NAME, \
|
||||||
Dtool_FreeInstance_##CLASS_NAME, \
|
Dtool_FreeInstance_##CLASS_NAME, \
|
||||||
Dtool_PyModuleClassInit_##CLASS_NAME\
|
Dtool_PyModuleClassInit_##CLASS_NAME \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
@ -538,6 +542,16 @@ EXPCL_DTOOLCONFIG int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2);
|
|||||||
EXPCL_DTOOLCONFIG PyObject *
|
EXPCL_DTOOLCONFIG PyObject *
|
||||||
make_list_for_item(PyObject *self, const char *num_name,
|
make_list_for_item(PyObject *self, const char *num_name,
|
||||||
const char *element_name);
|
const char *element_name);
|
||||||
|
|
||||||
|
EXPCL_DTOOLCONFIG PyObject *
|
||||||
|
copy_from_make_copy(PyObject *self);
|
||||||
|
|
||||||
|
EXPCL_DTOOLCONFIG PyObject *
|
||||||
|
copy_from_copy_constructor(PyObject *self);
|
||||||
|
|
||||||
|
EXPCL_DTOOLCONFIG PyObject *
|
||||||
|
map_deepcopy_to_copy(PyObject *self, PyObject *args);
|
||||||
|
|
||||||
EXPCL_DTOOLCONFIG PyObject *
|
EXPCL_DTOOLCONFIG PyObject *
|
||||||
PyLongOrInt_FromUnsignedLong(unsigned long value);
|
PyLongOrInt_FromUnsignedLong(unsigned long value);
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ extern "C" {
|
|||||||
EXPCL_DTOOLCONFIG int PyGen_Type(...);
|
EXPCL_DTOOLCONFIG int PyGen_Type(...);
|
||||||
EXPCL_DTOOLCONFIG int PyGILState_Ensure(...);
|
EXPCL_DTOOLCONFIG int PyGILState_Ensure(...);
|
||||||
EXPCL_DTOOLCONFIG int PyGILState_Release(...);
|
EXPCL_DTOOLCONFIG int PyGILState_Release(...);
|
||||||
|
EXPCL_DTOOLCONFIG int PyImport_GetModuleDict(...);
|
||||||
EXPCL_DTOOLCONFIG int PyInt_AsLong(...);
|
EXPCL_DTOOLCONFIG int PyInt_AsLong(...);
|
||||||
EXPCL_DTOOLCONFIG int PyInt_AsSsize_t(...);
|
EXPCL_DTOOLCONFIG int PyInt_AsSsize_t(...);
|
||||||
EXPCL_DTOOLCONFIG int PyInt_FromLong(...);
|
EXPCL_DTOOLCONFIG int PyInt_FromLong(...);
|
||||||
@ -74,6 +75,7 @@ extern "C" {
|
|||||||
EXPCL_DTOOLCONFIG int PyModule_AddObject(...);
|
EXPCL_DTOOLCONFIG int PyModule_AddObject(...);
|
||||||
EXPCL_DTOOLCONFIG int PyNumber_Long(...);
|
EXPCL_DTOOLCONFIG int PyNumber_Long(...);
|
||||||
EXPCL_DTOOLCONFIG int PyObject_Call(...);
|
EXPCL_DTOOLCONFIG int PyObject_Call(...);
|
||||||
|
EXPCL_DTOOLCONFIG int PyObject_CallFunction(...);
|
||||||
EXPCL_DTOOLCONFIG int PyObject_CallMethod(...);
|
EXPCL_DTOOLCONFIG int PyObject_CallMethod(...);
|
||||||
EXPCL_DTOOLCONFIG int PyObject_CallMethodObjArgs(...);
|
EXPCL_DTOOLCONFIG int PyObject_CallMethodObjArgs(...);
|
||||||
EXPCL_DTOOLCONFIG int PyObject_CallObject(...);
|
EXPCL_DTOOLCONFIG int PyObject_CallObject(...);
|
||||||
@ -88,6 +90,7 @@ extern "C" {
|
|||||||
EXPCL_DTOOLCONFIG int PyObject_Repr(...);
|
EXPCL_DTOOLCONFIG int PyObject_Repr(...);
|
||||||
EXPCL_DTOOLCONFIG int PyObject_SetAttrString(...);
|
EXPCL_DTOOLCONFIG int PyObject_SetAttrString(...);
|
||||||
EXPCL_DTOOLCONFIG int PyObject_Str(...);
|
EXPCL_DTOOLCONFIG int PyObject_Str(...);
|
||||||
|
EXPCL_DTOOLCONFIG int PyObject_Type(...);
|
||||||
EXPCL_DTOOLCONFIG int PySequence_Check(...);
|
EXPCL_DTOOLCONFIG int PySequence_Check(...);
|
||||||
EXPCL_DTOOLCONFIG int PySequence_GetItem(...);
|
EXPCL_DTOOLCONFIG int PySequence_GetItem(...);
|
||||||
EXPCL_DTOOLCONFIG int PySequence_Size(...);
|
EXPCL_DTOOLCONFIG int PySequence_Size(...);
|
||||||
@ -180,6 +183,7 @@ int PyGen_Check(...) { return 0; }
|
|||||||
int PyGen_Type(...) { return 0; }
|
int PyGen_Type(...) { return 0; }
|
||||||
int PyGILState_Ensure(...) { return 0; }
|
int PyGILState_Ensure(...) { return 0; }
|
||||||
int PyGILState_Release(...) { return 0; }
|
int PyGILState_Release(...) { return 0; }
|
||||||
|
int PyImport_GetModuleDict(...) { return 0; }
|
||||||
int PyInt_AsLong(...) { return 0; }
|
int PyInt_AsLong(...) { return 0; }
|
||||||
int PyInt_AsSsize_t(...) { return 0; }
|
int PyInt_AsSsize_t(...) { return 0; }
|
||||||
int PyInt_FromLong(...) { return 0; }
|
int PyInt_FromLong(...) { return 0; }
|
||||||
@ -203,6 +207,7 @@ int PyModule_AddIntConstant(...) { return 0; };
|
|||||||
int PyModule_AddObject(...) { return 0; };
|
int PyModule_AddObject(...) { return 0; };
|
||||||
int PyNumber_Long(...) { return 0; }
|
int PyNumber_Long(...) { return 0; }
|
||||||
int PyObject_Call(...) { return 0; }
|
int PyObject_Call(...) { return 0; }
|
||||||
|
int PyObject_CallFunction(...) { return 0; }
|
||||||
int PyObject_CallMethod(...) { return 0; }
|
int PyObject_CallMethod(...) { return 0; }
|
||||||
int PyObject_CallMethodObjArgs(...) { return 0; }
|
int PyObject_CallMethodObjArgs(...) { return 0; }
|
||||||
int PyObject_CallObject(...) { return 0; }
|
int PyObject_CallObject(...) { return 0; }
|
||||||
@ -217,6 +222,7 @@ int PyObject_IsTrue(...) { return 0; }
|
|||||||
int PyObject_Repr(...) { return 0; }
|
int PyObject_Repr(...) { return 0; }
|
||||||
int PyObject_SetAttrString(...) { return 0; }
|
int PyObject_SetAttrString(...) { return 0; }
|
||||||
int PyObject_Str(...) { return 0; }
|
int PyObject_Str(...) { return 0; }
|
||||||
|
int PyObject_Type(...) { return 0; }
|
||||||
int PySequence_Check(...) { return 0; }
|
int PySequence_Check(...) { return 0; }
|
||||||
int PySequence_GetItem(...) { return 0; }
|
int PySequence_GetItem(...) { return 0; }
|
||||||
int PySequence_Size(...) { return 0; }
|
int PySequence_Size(...) { return 0; }
|
||||||
|
@ -46,6 +46,33 @@ const FLOATNAME(LMatrix3) FLOATNAME(LMatrix3)::_ly_to_rz_mat =
|
|||||||
FLOATNAME(LMatrix3)::_flip_z_mat * FLOATNAME(LMatrix3)::_y_to_z_up_mat;
|
FLOATNAME(LMatrix3)::_flip_z_mat * FLOATNAME(LMatrix3)::_y_to_z_up_mat;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: LMatrix3::__reduce__
|
||||||
|
// Access: Published
|
||||||
|
// Description: This special Python method is implement to provide
|
||||||
|
// support for the pickle module.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *FLOATNAME(LMatrix3)::
|
||||||
|
__reduce__(PyObject *self) const {
|
||||||
|
// We should return at least a 2-tuple, (Class, (args)): the
|
||||||
|
// necessary class object whose constructor we should call
|
||||||
|
// (e.g. this), and the arguments necessary to reconstruct this
|
||||||
|
// object.
|
||||||
|
PyObject *this_class = PyObject_Type(self);
|
||||||
|
if (this_class == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *result = Py_BuildValue("(O(fffffffff))", this_class,
|
||||||
|
_m.m._00, _m.m._01, _m.m._02,
|
||||||
|
_m.m._10, _m.m._11, _m.m._12,
|
||||||
|
_m.m._20, _m.m._21, _m.m._22);
|
||||||
|
Py_DECREF(this_class);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: LMatrix::set_scale_shear_mat
|
// Function: LMatrix::set_scale_shear_mat
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -65,6 +65,10 @@ PUBLISHED:
|
|||||||
FLOATTYPE e20, FLOATTYPE e21, FLOATTYPE e22);
|
FLOATTYPE e20, FLOATTYPE e21, FLOATTYPE e22);
|
||||||
ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix3));
|
ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix3));
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
PyObject *__reduce__(PyObject *self) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
void fill(FLOATTYPE fill_value);
|
void fill(FLOATTYPE fill_value);
|
||||||
INLINE_LINMATH void set(
|
INLINE_LINMATH void set(
|
||||||
FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02,
|
FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02,
|
||||||
|
@ -62,6 +62,35 @@ const FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::_lz_to_ry_mat =
|
|||||||
const FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::_ly_to_rz_mat =
|
const FLOATNAME(LMatrix4) FLOATNAME(LMatrix4)::_ly_to_rz_mat =
|
||||||
FLOATNAME(LMatrix4)::_flip_z_mat * FLOATNAME(LMatrix4)::_y_to_z_up_mat;
|
FLOATNAME(LMatrix4)::_flip_z_mat * FLOATNAME(LMatrix4)::_y_to_z_up_mat;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: LMatrix4::__reduce__
|
||||||
|
// Access: Published
|
||||||
|
// Description: This special Python method is implement to provide
|
||||||
|
// support for the pickle module.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *FLOATNAME(LMatrix4)::
|
||||||
|
__reduce__(PyObject *self) const {
|
||||||
|
// We should return at least a 2-tuple, (Class, (args)): the
|
||||||
|
// necessary class object whose constructor we should call
|
||||||
|
// (e.g. this), and the arguments necessary to reconstruct this
|
||||||
|
// object.
|
||||||
|
PyObject *this_class = PyObject_Type(self);
|
||||||
|
if (this_class == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *result = Py_BuildValue("(O(ffffffffffffffff))", this_class,
|
||||||
|
_m.m._00, _m.m._01, _m.m._02, _m.m._03,
|
||||||
|
_m.m._10, _m.m._11, _m.m._12, _m.m._13,
|
||||||
|
_m.m._20, _m.m._21, _m.m._22, _m.m._23,
|
||||||
|
_m.m._30, _m.m._31, _m.m._32, _m.m._33);
|
||||||
|
Py_DECREF(this_class);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: LMatrix::convert_mat
|
// Function: LMatrix::convert_mat
|
||||||
// Access: Public, Static
|
// Access: Public, Static
|
||||||
|
@ -60,6 +60,10 @@ PUBLISHED:
|
|||||||
FLOATTYPE e30, FLOATTYPE e31, FLOATTYPE e32, FLOATTYPE e33);
|
FLOATTYPE e30, FLOATTYPE e31, FLOATTYPE e32, FLOATTYPE e33);
|
||||||
ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix4));
|
ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix4));
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
PyObject *__reduce__(PyObject *self) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Construct a 4x4 matrix given a 3x3 rotation matrix and an optional
|
// Construct a 4x4 matrix given a 3x3 rotation matrix and an optional
|
||||||
// translation component.
|
// translation component.
|
||||||
INLINE_LINMATH FLOATNAME(LMatrix4)(const FLOATNAME(LMatrix3) &upper3);
|
INLINE_LINMATH FLOATNAME(LMatrix4)(const FLOATNAME(LMatrix3) &upper3);
|
||||||
|
@ -21,6 +21,31 @@ const FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::_unit_x =
|
|||||||
const FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::_unit_y =
|
const FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::_unit_y =
|
||||||
FLOATNAME(LVecBase2)(0.0f, 1.0f);
|
FLOATNAME(LVecBase2)(0.0f, 1.0f);
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: LVecBase2::__reduce__
|
||||||
|
// Access: Published
|
||||||
|
// Description: This special Python method is implement to provide
|
||||||
|
// support for the pickle module.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *FLOATNAME(LVecBase2)::
|
||||||
|
__reduce__(PyObject *self) const {
|
||||||
|
// We should return at least a 2-tuple, (Class, (args)): the
|
||||||
|
// necessary class object whose constructor we should call
|
||||||
|
// (e.g. this), and the arguments necessary to reconstruct this
|
||||||
|
// object.
|
||||||
|
PyObject *this_class = PyObject_Type(self);
|
||||||
|
if (this_class == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *result = Py_BuildValue("(O(ff))", this_class,
|
||||||
|
(*this)[0], (*this)[1]);
|
||||||
|
Py_DECREF(this_class);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: LVecBase2::init_type
|
// Function: LVecBase2::init_type
|
||||||
// Access: Public, Static
|
// Access: Public, Static
|
||||||
|
@ -39,6 +39,10 @@ PUBLISHED:
|
|||||||
|
|
||||||
INLINE_LINMATH ~FLOATNAME(LVecBase2)();
|
INLINE_LINMATH ~FLOATNAME(LVecBase2)();
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
PyObject *__reduce__(PyObject *self) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
INLINE_LINMATH FLOATTYPE operator [](int i) const;
|
INLINE_LINMATH FLOATTYPE operator [](int i) const;
|
||||||
INLINE_LINMATH FLOATTYPE &operator [](int i);
|
INLINE_LINMATH FLOATTYPE &operator [](int i);
|
||||||
#ifdef HAVE_PYTHON
|
#ifdef HAVE_PYTHON
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
TypeHandle FLOATNAME(LVecBase3)::_type_handle;
|
TypeHandle FLOATNAME(LVecBase3)::_type_handle;
|
||||||
|
|
||||||
const FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::_zero =
|
const FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::_zero =
|
||||||
@ -23,6 +24,32 @@ const FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::_unit_y =
|
|||||||
const FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::_unit_z =
|
const FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::_unit_z =
|
||||||
FLOATNAME(LVecBase3)(0.0f, 0.0f, 1.0f);
|
FLOATNAME(LVecBase3)(0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: LVecBase3::__reduce__
|
||||||
|
// Access: Published
|
||||||
|
// Description: This special Python method is implement to provide
|
||||||
|
// support for the pickle module.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *FLOATNAME(LVecBase3)::
|
||||||
|
__reduce__(PyObject *self) const {
|
||||||
|
// We should return at least a 2-tuple, (Class, (args)): the
|
||||||
|
// necessary class object whose constructor we should call
|
||||||
|
// (e.g. this), and the arguments necessary to reconstruct this
|
||||||
|
// object.
|
||||||
|
PyObject *this_class = PyObject_Type(self);
|
||||||
|
if (this_class == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *result = Py_BuildValue("(O(fff))", this_class,
|
||||||
|
(*this)[0], (*this)[1], (*this)[2]);
|
||||||
|
Py_DECREF(this_class);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: LVecBase3::init_type
|
// Function: LVecBase3::init_type
|
||||||
// Access: Public, Static
|
// Access: Public, Static
|
||||||
|
@ -37,6 +37,10 @@ PUBLISHED:
|
|||||||
|
|
||||||
INLINE_LINMATH ~FLOATNAME(LVecBase3)();
|
INLINE_LINMATH ~FLOATNAME(LVecBase3)();
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
PyObject *__reduce__(PyObject *self) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
INLINE_LINMATH FLOATTYPE operator [](int i) const;
|
INLINE_LINMATH FLOATTYPE operator [](int i) const;
|
||||||
INLINE_LINMATH FLOATTYPE &operator [](int i);
|
INLINE_LINMATH FLOATTYPE &operator [](int i);
|
||||||
#ifdef HAVE_PYTHON
|
#ifdef HAVE_PYTHON
|
||||||
|
@ -25,6 +25,31 @@ const FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::_unit_z =
|
|||||||
const FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::_unit_w =
|
const FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::_unit_w =
|
||||||
FLOATNAME(LVecBase4)(0.0f, 0.0f, 0.0f, 1.0f);
|
FLOATNAME(LVecBase4)(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: LVecBase4::__reduce__
|
||||||
|
// Access: Published
|
||||||
|
// Description: This special Python method is implement to provide
|
||||||
|
// support for the pickle module.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *FLOATNAME(LVecBase4)::
|
||||||
|
__reduce__(PyObject *self) const {
|
||||||
|
// We should return at least a 2-tuple, (Class, (args)): the
|
||||||
|
// necessary class object whose constructor we should call
|
||||||
|
// (e.g. this), and the arguments necessary to reconstruct this
|
||||||
|
// object.
|
||||||
|
PyObject *this_class = PyObject_Type(self);
|
||||||
|
if (this_class == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *result = Py_BuildValue("(O(ffff))", this_class,
|
||||||
|
(*this)[0], (*this)[1], (*this)[2], (*this)[3]);
|
||||||
|
Py_DECREF(this_class);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: LVecBase4::init_type
|
// Function: LVecBase4::init_type
|
||||||
// Access: Public, Static
|
// Access: Public, Static
|
||||||
|
@ -38,6 +38,10 @@ PUBLISHED:
|
|||||||
|
|
||||||
INLINE_LINMATH ~FLOATNAME(LVecBase4)();
|
INLINE_LINMATH ~FLOATNAME(LVecBase4)();
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
PyObject *__reduce__(PyObject *self) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
INLINE_LINMATH FLOATTYPE operator [](int i) const;
|
INLINE_LINMATH FLOATTYPE operator [](int i) const;
|
||||||
INLINE_LINMATH FLOATTYPE &operator [](int i);
|
INLINE_LINMATH FLOATTYPE &operator [](int i);
|
||||||
#ifdef HAVE_PYTHON
|
#ifdef HAVE_PYTHON
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
#include "pStatCollector.h"
|
#include "pStatCollector.h"
|
||||||
#include "pStatTimer.h"
|
#include "pStatTimer.h"
|
||||||
#include "modelNode.h"
|
#include "modelNode.h"
|
||||||
|
#include "py_panda.h"
|
||||||
|
|
||||||
// stack seems to overflow on Intel C++ at 7000. If we need more than
|
// stack seems to overflow on Intel C++ at 7000. If we need more than
|
||||||
// 7000, need to increase stack size.
|
// 7000, need to increase stack size.
|
||||||
@ -127,6 +128,128 @@ static ConfigVariableEnum<EmptyNodePathType> empty_node_path
|
|||||||
// ***End temporary transition code for operator bool
|
// ***End temporary transition code for operator bool
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: NodePath::__copy__
|
||||||
|
// Access: Published
|
||||||
|
// Description: A special Python method that is invoked by
|
||||||
|
// copy.copy(node). Unlike the NodePath copy
|
||||||
|
// constructor, this makes a duplicate copy of the
|
||||||
|
// underlying PandaNode (but shares children, instead of
|
||||||
|
// copying them or omitting them).
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
NodePath NodePath::
|
||||||
|
__copy__() const {
|
||||||
|
if (is_empty()) {
|
||||||
|
// Invoke the copy constructor if we have no node.
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we do have a node, duplicate it, and wrap it in a new
|
||||||
|
// NodePath.
|
||||||
|
return NodePath(node()->__copy__());
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: NodePath::__deepcopy__
|
||||||
|
// Access: Published
|
||||||
|
// Description: A special Python method that is invoked by
|
||||||
|
// copy.deepcopy(np). This calls copy_to() unless the
|
||||||
|
// NodePath is already present in the provided
|
||||||
|
// dictionary.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *NodePath::
|
||||||
|
__deepcopy__(PyObject *self, PyObject *memo) const {
|
||||||
|
IMPORT_THIS struct Dtool_PyTypedObject Dtool_NodePath;
|
||||||
|
|
||||||
|
// Borrowed reference.
|
||||||
|
PyObject *dupe = PyDict_GetItem(memo, self);
|
||||||
|
if (dupe != NULL) {
|
||||||
|
// Already in the memo dictionary.
|
||||||
|
Py_INCREF(dupe);
|
||||||
|
return dupe;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodePath *np_dupe;
|
||||||
|
if (is_empty()) {
|
||||||
|
np_dupe = new NodePath(*this);
|
||||||
|
} else {
|
||||||
|
np_dupe = new NodePath(copy_to(NodePath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
dupe = DTool_CreatePyInstance((void *)np_dupe, Dtool_NodePath,
|
||||||
|
true, false);
|
||||||
|
if (PyDict_SetItem(memo, self, dupe) != 0) {
|
||||||
|
Py_DECREF(dupe);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dupe;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: NodePath::__reduce__
|
||||||
|
// Access: Published
|
||||||
|
// Description: This special Python method is implement to provide
|
||||||
|
// support for the pickle module.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *NodePath::
|
||||||
|
__reduce__(PyObject *self) const {
|
||||||
|
// We should return at least a 2-tuple, (Class, (args)): the
|
||||||
|
// necessary class object whose constructor we should call
|
||||||
|
// (e.g. this), and the arguments necessary to reconstruct this
|
||||||
|
// object.
|
||||||
|
|
||||||
|
if (is_empty()) {
|
||||||
|
// Reconstruct an empty NodePath. Not a 100% reconstruction,
|
||||||
|
// because we lose the specific error status, but I don't think
|
||||||
|
// that matters much.
|
||||||
|
PyObject *this_class = PyObject_Type(self);
|
||||||
|
if (this_class == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *result = Py_BuildValue("(O())", this_class);
|
||||||
|
Py_DECREF(this_class);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have a non-empty NodePath. We need to streamify the
|
||||||
|
// underlying node.
|
||||||
|
|
||||||
|
string bam_stream;
|
||||||
|
if (!node()->encode_to_bam_stream(bam_stream)) {
|
||||||
|
ostringstream stream;
|
||||||
|
stream << "Could not bamify object of type " << node()->get_type() << "\n";
|
||||||
|
string message = stream.str();
|
||||||
|
PyErr_SetString(PyExc_TypeError, message.c_str());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start by getting this class object.
|
||||||
|
PyObject *this_class = PyObject_Type(self);
|
||||||
|
if (this_class == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *func = TypedWritable::find_global_decode(this_class, "pyDecodeNodePathFromBamStream");
|
||||||
|
if (func == NULL) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "Couldn't find pyDecodeNodePathFromBamStream()");
|
||||||
|
Py_DECREF(this_class);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_DECREF(this_class);
|
||||||
|
|
||||||
|
PyObject *result = Py_BuildValue("(O(s#))", func, bam_stream.data(), bam_stream.size());
|
||||||
|
Py_DECREF(func);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: NodePath::operator bool
|
// Function: NodePath::operator bool
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -7292,3 +7415,23 @@ r_find_all_materials(PandaNode *node, const RenderState *state,
|
|||||||
r_find_all_materials(child, next_state, materials);
|
r_find_all_materials(child, next_state, materials);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: py_decode_NodePath_from_bam_stream
|
||||||
|
// Access: Published
|
||||||
|
// Description: This wrapper is defined as a global function to suit
|
||||||
|
// pickle's needs.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
NodePath
|
||||||
|
py_decode_NodePath_from_bam_stream(const string &data) {
|
||||||
|
PT(PandaNode) node = PandaNode::decode_from_bam_stream(data);
|
||||||
|
if (node == (PandaNode *)NULL) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "Could not unpack bam stream");
|
||||||
|
return NodePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NodePath(node);
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
|
@ -168,6 +168,12 @@ PUBLISHED:
|
|||||||
INLINE NodePath(const NodePath ©);
|
INLINE NodePath(const NodePath ©);
|
||||||
INLINE void operator = (const NodePath ©);
|
INLINE void operator = (const NodePath ©);
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
NodePath __copy__() const;
|
||||||
|
PyObject *__deepcopy__(PyObject *self, PyObject *memo) const;
|
||||||
|
PyObject *__reduce__(PyObject *self) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
INLINE static NodePath not_found();
|
INLINE static NodePath not_found();
|
||||||
INLINE static NodePath removed();
|
INLINE static NodePath removed();
|
||||||
INLINE static NodePath fail();
|
INLINE static NodePath fail();
|
||||||
@ -949,6 +955,12 @@ private:
|
|||||||
|
|
||||||
INLINE ostream &operator << (ostream &out, const NodePath &node_path);
|
INLINE ostream &operator << (ostream &out, const NodePath &node_path);
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
BEGIN_PUBLISH
|
||||||
|
NodePath py_decode_NodePath_from_bam_stream(const string &data);
|
||||||
|
END_PUBLISH
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "nodePath.I"
|
#include "nodePath.I"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "config_mathutil.h"
|
#include "config_mathutil.h"
|
||||||
#include "lightReMutexHolder.h"
|
#include "lightReMutexHolder.h"
|
||||||
#include "graphicsStateGuardianBase.h"
|
#include "graphicsStateGuardianBase.h"
|
||||||
|
#include "py_panda.h"
|
||||||
|
|
||||||
// This category is just temporary for debugging convenience.
|
// This category is just temporary for debugging convenience.
|
||||||
NotifyCategoryDecl(drawmask, EXPCL_PANDA_PGRAPH, EXPTP_PANDA_PGRAPH);
|
NotifyCategoryDecl(drawmask, EXPCL_PANDA_PGRAPH, EXPTP_PANDA_PGRAPH);
|
||||||
@ -211,20 +212,6 @@ as_reference_count() {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: PandaNode::make_copy
|
|
||||||
// Access: Public, Virtual
|
|
||||||
// Description: Returns a newly-allocated PandaNode that is a shallow
|
|
||||||
// copy of this one. It will be a different pointer,
|
|
||||||
// but its internal data may or may not be shared with
|
|
||||||
// that of the original PandaNode. No children will be
|
|
||||||
// copied.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
PandaNode *PandaNode::
|
|
||||||
make_copy() const {
|
|
||||||
return new PandaNode(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PandaNode::dupe_for_flatten
|
// Function: PandaNode::dupe_for_flatten
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
@ -608,6 +595,20 @@ void PandaNode::
|
|||||||
add_for_draw(CullTraverser *, CullTraverserData &) {
|
add_for_draw(CullTraverser *, CullTraverserData &) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PandaNode::make_copy
|
||||||
|
// Access: Published, Virtual
|
||||||
|
// Description: Returns a newly-allocated PandaNode that is a shallow
|
||||||
|
// copy of this one. It will be a different pointer,
|
||||||
|
// but its internal data may or may not be shared with
|
||||||
|
// that of the original PandaNode. No children will be
|
||||||
|
// copied.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PandaNode *PandaNode::
|
||||||
|
make_copy() const {
|
||||||
|
return new PandaNode(*this);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PandaNode::copy_subgraph
|
// Function: PandaNode::copy_subgraph
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -618,12 +619,79 @@ add_for_draw(CullTraverser *, CullTraverserData &) {
|
|||||||
// will impede normal use of the PandaNode.
|
// will impede normal use of the PandaNode.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PT(PandaNode) PandaNode::
|
PT(PandaNode) PandaNode::
|
||||||
copy_subgraph(Thread *current_thread) const
|
copy_subgraph(Thread *current_thread) const {
|
||||||
{
|
|
||||||
InstanceMap inst_map;
|
InstanceMap inst_map;
|
||||||
return r_copy_subgraph(inst_map, current_thread);
|
return r_copy_subgraph(inst_map, current_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PandaNode::__copy__
|
||||||
|
// Access: Published
|
||||||
|
// Description: A special Python method that is invoked by
|
||||||
|
// copy.copy(node). Unlike the PandaNode copy
|
||||||
|
// constructor, which creates a new node without
|
||||||
|
// children, this shares child pointers (essentially
|
||||||
|
// making every child an instance). This is intended to
|
||||||
|
// simulate the behavior of copy.copy() for other
|
||||||
|
// objects.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PT(PandaNode) PandaNode::
|
||||||
|
__copy__() const {
|
||||||
|
Thread *current_thread = Thread::get_current_thread();
|
||||||
|
|
||||||
|
PT(PandaNode) node_dupe = make_copy();
|
||||||
|
|
||||||
|
Children children = get_children(current_thread);
|
||||||
|
int num_children = children.get_num_children();
|
||||||
|
|
||||||
|
for (int i = 0; i < num_children; ++i) {
|
||||||
|
PandaNode *child = children.get_child(i);
|
||||||
|
node_dupe->add_child(children.get_child(i), children.get_child_sort(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return node_dupe;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PandaNode::__deepcopy__
|
||||||
|
// Access: Published
|
||||||
|
// Description: A special Python method that is invoked by
|
||||||
|
// copy.deepcopy(node). This calls copy_subgraph()
|
||||||
|
// unless the node is already present in the provided
|
||||||
|
// dictionary.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *PandaNode::
|
||||||
|
__deepcopy__(PyObject *self, PyObject *memo) const {
|
||||||
|
IMPORT_THIS struct Dtool_PyTypedObject Dtool_PandaNode;
|
||||||
|
|
||||||
|
// Borrowed reference.
|
||||||
|
PyObject *dupe = PyDict_GetItem(memo, self);
|
||||||
|
if (dupe != NULL) {
|
||||||
|
// Already in the memo dictionary.
|
||||||
|
Py_INCREF(dupe);
|
||||||
|
return dupe;
|
||||||
|
}
|
||||||
|
|
||||||
|
PT(PandaNode) node_dupe = copy_subgraph();
|
||||||
|
|
||||||
|
// DTool_CreatePyInstanceTyped() steals a C++ reference.
|
||||||
|
node_dupe->ref();
|
||||||
|
dupe = DTool_CreatePyInstanceTyped
|
||||||
|
((void *)node_dupe.p(), Dtool_PandaNode, true, false,
|
||||||
|
node_dupe->get_type_index());
|
||||||
|
|
||||||
|
if (PyDict_SetItem(memo, self, dupe) != 0) {
|
||||||
|
Py_DECREF(dupe);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dupe;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PandaNode::count_num_descendants
|
// Function: PandaNode::count_num_descendants
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -2597,6 +2665,32 @@ is_ambient_light() const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PandaNode::decode_from_bam_stream
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Reads the string created by a previous call to
|
||||||
|
// encode_to_bam_stream(), and extracts and returns the
|
||||||
|
// single object on that string. Returns NULL on error.
|
||||||
|
//
|
||||||
|
// This method is intended to replace
|
||||||
|
// decode_raw_from_bam_stream() when you know the stream
|
||||||
|
// in question returns an object of type PandaNode,
|
||||||
|
// allowing for easier reference count management. Note
|
||||||
|
// that the caller is still responsible for maintaining
|
||||||
|
// the reference count on the return value.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PT(PandaNode) PandaNode::
|
||||||
|
decode_from_bam_stream(const string &data) {
|
||||||
|
TypedWritable *object;
|
||||||
|
ReferenceCount *ref_ptr;
|
||||||
|
|
||||||
|
if (!TypedWritable::decode_raw_from_bam_stream(object, ref_ptr, data)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DCAST(PandaNode, object);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PandaNode::get_internal_bounds
|
// Function: PandaNode::get_internal_bounds
|
||||||
// Access: Protected
|
// Access: Protected
|
||||||
|
@ -84,7 +84,6 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ReferenceCount *as_reference_count();
|
virtual ReferenceCount *as_reference_count();
|
||||||
virtual PandaNode *make_copy() const;
|
|
||||||
virtual PandaNode *dupe_for_flatten() const;
|
virtual PandaNode *dupe_for_flatten() const;
|
||||||
|
|
||||||
virtual bool safe_to_flatten() const;
|
virtual bool safe_to_flatten() const;
|
||||||
@ -116,8 +115,14 @@ public:
|
|||||||
virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data);
|
virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data);
|
||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
|
virtual PandaNode *make_copy() const;
|
||||||
PT(PandaNode) copy_subgraph(Thread *current_thread = Thread::get_current_thread()) const;
|
PT(PandaNode) copy_subgraph(Thread *current_thread = Thread::get_current_thread()) const;
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
PT(PandaNode) __copy__() const;
|
||||||
|
PyObject *__deepcopy__(PyObject *self, PyObject *memo) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
INLINE int get_num_parents(Thread *current_thread = Thread::get_current_thread()) const;
|
INLINE int get_num_parents(Thread *current_thread = Thread::get_current_thread()) const;
|
||||||
INLINE PandaNode *get_parent(int n, Thread *current_thread = Thread::get_current_thread()) const;
|
INLINE PandaNode *get_parent(int n, Thread *current_thread = Thread::get_current_thread()) const;
|
||||||
INLINE int find_parent(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const;
|
INLINE int find_parent(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const;
|
||||||
@ -300,6 +305,10 @@ PUBLISHED:
|
|||||||
};
|
};
|
||||||
INLINE int get_fancy_bits(Thread *current_thread = Thread::get_current_thread()) const;
|
INLINE int get_fancy_bits(Thread *current_thread = Thread::get_current_thread()) const;
|
||||||
|
|
||||||
|
|
||||||
|
PUBLISHED:
|
||||||
|
static PT(PandaNode) decode_from_bam_stream(const string &data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class BoundsData;
|
class BoundsData;
|
||||||
|
|
||||||
|
@ -66,3 +66,28 @@ INLINE UpdateSeq TypedWritable::
|
|||||||
get_bam_modified() const {
|
get_bam_modified() const {
|
||||||
return _bam_modified;
|
return _bam_modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TypedWritable::encode_to_bam_stream
|
||||||
|
// Access: Published
|
||||||
|
// Description: Converts the TypedWritable object into a single
|
||||||
|
// stream of data using a BamWriter, and returns that
|
||||||
|
// data as a string string. Returns empty string on
|
||||||
|
// failure.
|
||||||
|
//
|
||||||
|
// This is a convenience method particularly useful for
|
||||||
|
// cases when you are only serializing a single object.
|
||||||
|
// If you have many objects to process, it is more
|
||||||
|
// efficient to use the same BamWriter to serialize all
|
||||||
|
// of them together.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
string TypedWritable::
|
||||||
|
encode_to_bam_stream() const {
|
||||||
|
string data;
|
||||||
|
if (!encode_to_bam_stream(data)) {
|
||||||
|
return string();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,11 @@
|
|||||||
|
|
||||||
#include "typedWritable.h"
|
#include "typedWritable.h"
|
||||||
#include "bamWriter.h"
|
#include "bamWriter.h"
|
||||||
|
#include "bamReader.h"
|
||||||
|
#include "datagramOutputFile.h"
|
||||||
|
#include "datagramInputFile.h"
|
||||||
#include "lightMutexHolder.h"
|
#include "lightMutexHolder.h"
|
||||||
|
#include "bam.h"
|
||||||
|
|
||||||
LightMutex TypedWritable::_bam_writers_lock;
|
LightMutex TypedWritable::_bam_writers_lock;
|
||||||
|
|
||||||
@ -144,3 +148,276 @@ ReferenceCount *TypedWritable::
|
|||||||
as_reference_count() {
|
as_reference_count() {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TypedWritable::__reduce__
|
||||||
|
// Access: Published
|
||||||
|
// Description: This special Python method is implement to provide
|
||||||
|
// support for the pickle module.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *TypedWritable::
|
||||||
|
__reduce__(PyObject *self) const {
|
||||||
|
// We should return at least a 2-tuple, (Class, (args)): the
|
||||||
|
// necessary class object whose constructor we should call
|
||||||
|
// (e.g. this), and the arguments necessary to reconstruct this
|
||||||
|
// object.
|
||||||
|
|
||||||
|
// Check that we have a decodeFromBamStream python method. If not,
|
||||||
|
// we can't use this interface.
|
||||||
|
PyObject *method = PyObject_GetAttrString(self, "decodeFromBamStream");
|
||||||
|
if (method == NULL) {
|
||||||
|
ostringstream stream;
|
||||||
|
stream << "Cannot pickle objects of type " << get_type() << "\n";
|
||||||
|
string message = stream.str();
|
||||||
|
PyErr_SetString(PyExc_TypeError, message.c_str());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_DECREF(method);
|
||||||
|
|
||||||
|
// First, streamify the object, if possible.
|
||||||
|
string bam_stream;
|
||||||
|
if (!encode_to_bam_stream(bam_stream)) {
|
||||||
|
ostringstream stream;
|
||||||
|
stream << "Could not bamify object of type " << get_type() << "\n";
|
||||||
|
string message = stream.str();
|
||||||
|
PyErr_SetString(PyExc_TypeError, message.c_str());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start by getting this class object.
|
||||||
|
PyObject *this_class = PyObject_Type(self);
|
||||||
|
if (this_class == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *func = find_global_decode(this_class, "pyDecodeTypedWritableFromBamStream");
|
||||||
|
if (func == NULL) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "Couldn't find pyDecodeTypedWritableFromBamStream()");
|
||||||
|
Py_DECREF(this_class);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *result = Py_BuildValue("(O(Os#))", func, this_class, bam_stream.data(), bam_stream.size());
|
||||||
|
Py_DECREF(func);
|
||||||
|
Py_DECREF(this_class);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TypedWritable::encode_to_bam_stream
|
||||||
|
// Access: Published
|
||||||
|
// Description: Converts the TypedWritable object into a single
|
||||||
|
// stream of data using a BamWriter, and stores that
|
||||||
|
// data in the indicated string. Returns true on
|
||||||
|
// success, false on failure.
|
||||||
|
//
|
||||||
|
// This is a convenience method particularly useful for
|
||||||
|
// cases when you are only serializing a single object.
|
||||||
|
// If you have many objects to process, it is more
|
||||||
|
// efficient to use the same BamWriter to serialize all
|
||||||
|
// of them together.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool TypedWritable::
|
||||||
|
encode_to_bam_stream(string &data) const {
|
||||||
|
data.clear();
|
||||||
|
ostringstream stream;
|
||||||
|
|
||||||
|
// We use nested scoping to ensure the destructors get called in the
|
||||||
|
// right order.
|
||||||
|
{
|
||||||
|
DatagramOutputFile dout;
|
||||||
|
if (!dout.open(stream)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dout.write_header(_bam_header)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
BamWriter writer(&dout, "bam_stream");
|
||||||
|
if (!writer.init()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!writer.write_object(this)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data = stream.str();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TypedWritable::decode_raw_from_bam_stream
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Reads the string created by a previous call to
|
||||||
|
// encode_to_bam_stream(), and extracts the single
|
||||||
|
// object on that string. Returns true on success,
|
||||||
|
// false on on error.
|
||||||
|
//
|
||||||
|
// This variant sets the TypedWritable and
|
||||||
|
// ReferenceCount pointers separately; both are pointers
|
||||||
|
// to the same object. The reference count is not
|
||||||
|
// incremented; it is the caller's responsibility to
|
||||||
|
// manage the reference count.
|
||||||
|
//
|
||||||
|
// Note that this method cannot be used to retrieve
|
||||||
|
// objects that do not inherit from ReferenceCount,
|
||||||
|
// because these objects cannot persist beyond the
|
||||||
|
// lifetime of the BamReader that reads them. To
|
||||||
|
// retrieve these objects from a bam stream, you must
|
||||||
|
// construct a BamReader directly.
|
||||||
|
//
|
||||||
|
// If you happen to know that the particular object in
|
||||||
|
// question inherits from TypedWritableReferenceCount or
|
||||||
|
// PandaNode, consider calling the variant of
|
||||||
|
// decode_from_bam_stream() defined for those methods,
|
||||||
|
// which presents a simpler interface.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool TypedWritable::
|
||||||
|
decode_raw_from_bam_stream(TypedWritable *&ptr, ReferenceCount *&ref_ptr,
|
||||||
|
const string &data) {
|
||||||
|
istringstream stream(data);
|
||||||
|
|
||||||
|
DatagramInputFile din;
|
||||||
|
if (!din.open(stream)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string head;
|
||||||
|
if (!din.read_header(head, _bam_header.size())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head != _bam_header) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We scope this so we can control when the BamReader destructs.
|
||||||
|
{
|
||||||
|
BamReader reader(&din, "bam_stream");
|
||||||
|
if (!reader.init()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reader.read_object(ptr, ref_ptr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reader.resolve()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref_ptr == NULL) {
|
||||||
|
// Can't support non-reference-counted objects.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protect the pointer from accidental deletion when the BamReader
|
||||||
|
// goes away.
|
||||||
|
ref_ptr->ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now decrement the ref count, without deleting the object. This
|
||||||
|
// may reduce the reference count to zero, but that's OK--we trust
|
||||||
|
// the caller to manage the reference count from this point on.
|
||||||
|
ref_ptr->unref();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TypedWritable::find_global_decode
|
||||||
|
// Access: Public, Static
|
||||||
|
// Description: This is a support function for __reduce__(). It
|
||||||
|
// searches for the global function
|
||||||
|
// pyDecodeTypedWritableFromBamStream() in this class's
|
||||||
|
// module, or in the module for any base class. (It's
|
||||||
|
// really looking for the libpanda module, but we can't
|
||||||
|
// be sure what name that module was loaded under, so we
|
||||||
|
// search upwards this way.)
|
||||||
|
//
|
||||||
|
// Returns: new reference on success, or NULL on failure.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *TypedWritable::
|
||||||
|
find_global_decode(PyObject *this_class, const char *func_name) {
|
||||||
|
PyObject *module_name = PyObject_GetAttrString(this_class, "__module__");
|
||||||
|
if (module_name != NULL) {
|
||||||
|
// borrowed reference
|
||||||
|
PyObject *sys_modules = PyImport_GetModuleDict();
|
||||||
|
if (sys_modules != NULL) {
|
||||||
|
// borrowed reference
|
||||||
|
PyObject *module = PyDict_GetItem(sys_modules, module_name);
|
||||||
|
if (module != NULL){
|
||||||
|
PyObject *func = PyObject_GetAttrString(module, func_name);
|
||||||
|
if (func != NULL) {
|
||||||
|
Py_DECREF(module_name);
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Py_DECREF(module_name);
|
||||||
|
|
||||||
|
PyObject *bases = PyObject_GetAttrString(this_class, "__bases__");
|
||||||
|
if (bases != NULL) {
|
||||||
|
if (PySequence_Check(bases)) {
|
||||||
|
Py_ssize_t size = PySequence_Size(bases);
|
||||||
|
for (Py_ssize_t i = 0; i < size; ++i) {
|
||||||
|
PyObject *base = PySequence_GetItem(bases, i);
|
||||||
|
if (base != NULL) {
|
||||||
|
PyObject *func = find_global_decode(base, func_name);
|
||||||
|
Py_DECREF(base);
|
||||||
|
if (func != NULL) {
|
||||||
|
Py_DECREF(bases);
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Py_DECREF(bases);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: py_decode_TypedWritable_from_bam_stream
|
||||||
|
// Access: Published
|
||||||
|
// Description: This wrapper is defined as a global function to suit
|
||||||
|
// pickle's needs.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *
|
||||||
|
py_decode_TypedWritable_from_bam_stream(PyObject *this_class, const string &data) {
|
||||||
|
// We need the function TypedWritable::decode_from_bam_stream, which
|
||||||
|
// invokes the BamReader to reconstruct this object. Since we use
|
||||||
|
// the specific object's class as the pointer, we get the particular
|
||||||
|
// instance of decode_from_bam_stream appropriate to this class.
|
||||||
|
|
||||||
|
PyObject *func = PyObject_GetAttrString(this_class, "decodeFromBamStream");
|
||||||
|
if (func == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *result = PyObject_CallFunction(func, (char *)"(s#)", data.data(), data.size());
|
||||||
|
if (result == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == Py_None) {
|
||||||
|
Py_DECREF(result);
|
||||||
|
PyErr_SetString(PyExc_ValueError, "Could not unpack bam stream");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
|
@ -60,6 +60,21 @@ PUBLISHED:
|
|||||||
INLINE void mark_bam_modified();
|
INLINE void mark_bam_modified();
|
||||||
INLINE UpdateSeq get_bam_modified() const;
|
INLINE UpdateSeq get_bam_modified() const;
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
PyObject *__reduce__(PyObject *self) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
INLINE string encode_to_bam_stream() const;
|
||||||
|
bool encode_to_bam_stream(string &data) const;
|
||||||
|
static bool decode_raw_from_bam_stream(TypedWritable *&ptr,
|
||||||
|
ReferenceCount *&ref_ptr,
|
||||||
|
const string &data);
|
||||||
|
|
||||||
|
public:
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
static PyObject *find_global_decode(PyObject *this_class, const char *func_name);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// We may need to store a list of the BamWriter(s) that have a
|
// We may need to store a list of the BamWriter(s) that have a
|
||||||
// reference to this object, so that we can remove the object from
|
// reference to this object, so that we can remove the object from
|
||||||
@ -70,12 +85,10 @@ private:
|
|||||||
|
|
||||||
UpdateSeq _bam_modified;
|
UpdateSeq _bam_modified;
|
||||||
|
|
||||||
PUBLISHED:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
return _type_handle;
|
return _type_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
static void init_type() {
|
static void init_type() {
|
||||||
TypedObject::init_type();
|
TypedObject::init_type();
|
||||||
register_type(_type_handle, "TypedWritable",
|
register_type(_type_handle, "TypedWritable",
|
||||||
@ -96,6 +109,12 @@ private:
|
|||||||
friend class BamWriter;
|
friend class BamWriter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
BEGIN_PUBLISH
|
||||||
|
PyObject *py_decode_TypedWritable_from_bam_stream(PyObject *this_class, const string &data);
|
||||||
|
END_PUBLISH
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "typedWritable.I"
|
#include "typedWritable.I"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,3 +26,30 @@ ReferenceCount *TypedWritableReferenceCount::
|
|||||||
as_reference_count() {
|
as_reference_count() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TypedWritableReferenceCount::decode_from_bam_stream
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Reads the string created by a previous call to
|
||||||
|
// encode_to_bam_stream(), and extracts and returns the
|
||||||
|
// single object on that string. Returns NULL on error.
|
||||||
|
//
|
||||||
|
// This method is intended to replace
|
||||||
|
// decode_raw_from_bam_stream() when you know the stream
|
||||||
|
// in question returns an object of type
|
||||||
|
// TypedWritableReferenceCount, allowing for easier
|
||||||
|
// reference count management. Note that the caller is
|
||||||
|
// still responsible for maintaining the reference count
|
||||||
|
// on the return value.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PT(TypedWritableReferenceCount) TypedWritableReferenceCount::
|
||||||
|
decode_from_bam_stream(const string &data) {
|
||||||
|
TypedWritable *object;
|
||||||
|
ReferenceCount *ref_ptr;
|
||||||
|
|
||||||
|
if (!TypedWritable::decode_raw_from_bam_stream(object, ref_ptr, data)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DCAST(TypedWritableReferenceCount, object);
|
||||||
|
}
|
||||||
|
@ -40,18 +40,17 @@ public:
|
|||||||
|
|
||||||
virtual ReferenceCount *as_reference_count();
|
virtual ReferenceCount *as_reference_count();
|
||||||
|
|
||||||
|
PUBLISHED:
|
||||||
|
static PT(TypedWritableReferenceCount) decode_from_bam_stream(const string &data);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual TypeHandle get_type() const {
|
virtual TypeHandle get_type() const {
|
||||||
return get_class_type();
|
return get_class_type();
|
||||||
}
|
}
|
||||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||||
|
|
||||||
PUBLISHED:
|
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
return _type_handle;
|
return _type_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
static void init_type() {
|
static void init_type() {
|
||||||
TypedWritable::init_type();
|
TypedWritable::init_type();
|
||||||
ReferenceCount::init_type();
|
ReferenceCount::init_type();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user