mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
read parameters from concrete classes
This commit is contained in:
parent
65e677ad21
commit
19e98401f1
@ -423,8 +423,34 @@ direct_update(PyObject *distobj, const string &field_name,
|
|||||||
// Returns true on success, false on failure.
|
// Returns true on success, false on failure.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool DCClass::
|
bool DCClass::
|
||||||
pack_required_field(DCPacker &packer, PyObject *distobj, DCField *field) const {
|
pack_required_field(DCPacker &packer, PyObject *distobj,
|
||||||
DCAtomicField *atom = field->as_atomic_field();
|
const DCField *field) const {
|
||||||
|
const DCParameter *parameter = ((DCField *)field)->as_parameter();
|
||||||
|
if (parameter != (DCParameter *)NULL) {
|
||||||
|
// This is the easy case: to pack a parameter, we just look on the
|
||||||
|
// class object for the data element.
|
||||||
|
string field_name = field->get_name();
|
||||||
|
|
||||||
|
if (!PyObject_HasAttrString(distobj, (char *)field_name.c_str())) {
|
||||||
|
ostringstream strm;
|
||||||
|
strm << "Data element " << field_name
|
||||||
|
<< ", required by dc file for dclass " << get_name()
|
||||||
|
<< ", not defined on object.";
|
||||||
|
nassert_raise(strm.str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PyObject *result =
|
||||||
|
PyObject_GetAttrString(distobj, (char *)field_name.c_str());
|
||||||
|
nassertr(result != (PyObject *)NULL, false);
|
||||||
|
|
||||||
|
// Now pack the value into the datagram.
|
||||||
|
bool pack_ok = parameter->pack_args(packer, result);
|
||||||
|
Py_DECREF(result);
|
||||||
|
|
||||||
|
return pack_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DCAtomicField *atom = ((DCField *)field)->as_atomic_field();
|
||||||
if (atom == (DCAtomicField *)NULL) {
|
if (atom == (DCAtomicField *)NULL) {
|
||||||
ostringstream strm;
|
ostringstream strm;
|
||||||
strm << "Cannot pack non-atomic field " << field->get_name()
|
strm << "Cannot pack non-atomic field " << field->get_name()
|
||||||
@ -476,6 +502,8 @@ pack_required_field(DCPacker &packer, PyObject *distobj, DCField *field) const {
|
|||||||
Py_DECREF(empty_args);
|
Py_DECREF(empty_args);
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
if (result == (PyObject *)NULL) {
|
if (result == (PyObject *)NULL) {
|
||||||
|
// We don't set this as an exception, since presumably the Python
|
||||||
|
// method itself has already triggered a Python exception.
|
||||||
cerr << "Error when calling " << get_name << "\n";
|
cerr << "Error when calling " << get_name << "\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ PUBLISHED:
|
|||||||
void direct_update(PyObject *distobj, const string &field_name,
|
void direct_update(PyObject *distobj, const string &field_name,
|
||||||
const Datagram &datagram);
|
const Datagram &datagram);
|
||||||
bool pack_required_field(DCPacker &packer, PyObject *distobj,
|
bool pack_required_field(DCPacker &packer, PyObject *distobj,
|
||||||
DCField *field) const;
|
const DCField *field) const;
|
||||||
|
|
||||||
|
|
||||||
Datagram client_format_update(const string &field_name,
|
Datagram client_format_update(const string &field_name,
|
||||||
|
@ -195,8 +195,6 @@ pack_args(DCPacker &packer, PyObject *sequence) const {
|
|||||||
nassertr(!packer.had_error(), false);
|
nassertr(!packer.had_error(), false);
|
||||||
nassertr(packer.get_current_field() == this, false);
|
nassertr(packer.get_current_field() == this, false);
|
||||||
|
|
||||||
nassertr(PySequence_Check(sequence), false);
|
|
||||||
|
|
||||||
packer.pack_object(sequence);
|
packer.pack_object(sequence);
|
||||||
if (!packer.had_error()) {
|
if (!packer.had_error()) {
|
||||||
/*
|
/*
|
||||||
@ -208,6 +206,7 @@ pack_args(DCPacker &packer, PyObject *sequence) const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Notify::ptr()->has_assert_failed()) {
|
||||||
PyObject *tuple = PySequence_Tuple(sequence);
|
PyObject *tuple = PySequence_Tuple(sequence);
|
||||||
PyObject *str = PyObject_Str(tuple);
|
PyObject *str = PyObject_Str(tuple);
|
||||||
|
|
||||||
@ -224,6 +223,7 @@ pack_args(DCPacker &packer, PyObject *sequence) const {
|
|||||||
Py_DECREF(tuple);
|
Py_DECREF(tuple);
|
||||||
|
|
||||||
nassert_raise(strm.str());
|
nassert_raise(strm.str());
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif // HAVE_PYTHON
|
#endif // HAVE_PYTHON
|
||||||
|
@ -634,8 +634,6 @@ unpack_skip() {
|
|||||||
void DCPacker::
|
void DCPacker::
|
||||||
pack_object(PyObject *object) {
|
pack_object(PyObject *object) {
|
||||||
nassertv(_mode == M_pack || _mode == M_repack);
|
nassertv(_mode == M_pack || _mode == M_repack);
|
||||||
PyObject *str = PyObject_Str(object);
|
|
||||||
Py_DECREF(str);
|
|
||||||
|
|
||||||
if (PyInt_Check(object)) {
|
if (PyInt_Check(object)) {
|
||||||
pack_int(PyInt_AS_LONG(object));
|
pack_int(PyInt_AS_LONG(object));
|
||||||
@ -654,7 +652,44 @@ pack_object(PyObject *object) {
|
|||||||
pack_string(string(buffer, length));
|
pack_string(string(buffer, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (PySequence_Check(object)) {
|
} else {
|
||||||
|
DCClass *dclass = NULL;
|
||||||
|
const DCClassParameter *class_param = ((DCPackerInterface *)get_current_field())->as_class_parameter();
|
||||||
|
if (class_param != (DCClassParameter *)NULL) {
|
||||||
|
dclass = class_param->get_class();
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = PySequence_Size(object);
|
||||||
|
|
||||||
|
// If dclass is not NULL, the packer is expecting a class object.
|
||||||
|
// There are then two cases: (1) the user has supplied a matching
|
||||||
|
// class object, or (2) the user has supplied a sequence object.
|
||||||
|
// Unfortunately, it may be difficult to differentiate these two
|
||||||
|
// cases, since a class object may also be a sequence object.
|
||||||
|
|
||||||
|
// The rule to differentiate them is:
|
||||||
|
|
||||||
|
// (1) If the supplied class object is an instance of the expected
|
||||||
|
// class object, it is considered to be a class object.
|
||||||
|
|
||||||
|
// (2) Otherwise, if the supplied class object has a __len__()
|
||||||
|
// method (i.e. PySequence_Size() returns a number >= 0), then it
|
||||||
|
// is considered to be a sequence.
|
||||||
|
|
||||||
|
// (3) Otherwise, it is considered to be a class object.
|
||||||
|
|
||||||
|
if (dclass != (DCClass *)NULL &&
|
||||||
|
((dclass->get_class_def() != (PyObject *)NULL &&
|
||||||
|
PyObject_IsInstance(object, dclass->get_class_def())) ||
|
||||||
|
size < 0)) {
|
||||||
|
// The supplied object is either an instance of the expected
|
||||||
|
// class object, or the size is less than 0--this is case (1) or
|
||||||
|
// (3).
|
||||||
|
pack_class_object(dclass, object);
|
||||||
|
|
||||||
|
} else if (size >= 0) {
|
||||||
|
// The supplied object is not an instance of the expected class
|
||||||
|
// object, and it does return a valid size. This is case (2).
|
||||||
push();
|
push();
|
||||||
int size = PySequence_Size(object);
|
int size = PySequence_Size(object);
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
@ -663,6 +698,19 @@ pack_object(PyObject *object) {
|
|||||||
Py_DECREF(element);
|
Py_DECREF(element);
|
||||||
}
|
}
|
||||||
pop();
|
pop();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// The supplied object does not return a valid size, and we
|
||||||
|
// weren't expecting a class parameter. This is none of the
|
||||||
|
// above, an error.
|
||||||
|
ostringstream strm;
|
||||||
|
PyObject *str = PyObject_Str(object);
|
||||||
|
strm << "Don't know how to pack object: "
|
||||||
|
<< PyString_AsString(str) << "\n";
|
||||||
|
Py_DECREF(str);
|
||||||
|
nassert_raise(strm.str());
|
||||||
|
_pack_error = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // HAVE_PYTHON
|
#endif // HAVE_PYTHON
|
||||||
@ -1034,6 +1082,33 @@ clear() {
|
|||||||
_root = NULL;
|
_root = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPacker::pack_class_object
|
||||||
|
// Access: Private
|
||||||
|
// Description: Given that the current element is a ClassParameter
|
||||||
|
// for a Python class object, try to extract the
|
||||||
|
// appropriate values from the class object and pack in.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void DCPacker::
|
||||||
|
pack_class_object(DCClass *dclass, PyObject *object) {
|
||||||
|
PyObject *str = PyObject_Str(object);
|
||||||
|
cerr << "pack_class_object(" << dclass->get_name() << ", "
|
||||||
|
<< PyString_AsString(str) << ")\n";
|
||||||
|
Py_DECREF(str);
|
||||||
|
push();
|
||||||
|
while (more_nested_fields()) {
|
||||||
|
const DCField *field = ((DCPackerInterface *)get_current_field())->as_field();
|
||||||
|
nassertv(field != (DCField *)NULL);
|
||||||
|
|
||||||
|
if (!dclass->pack_required_field(*this, object, field)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
#ifdef HAVE_PYTHON
|
#ifdef HAVE_PYTHON
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DCPacker::unpack_class_object
|
// Function: DCPacker::unpack_class_object
|
||||||
|
@ -178,6 +178,7 @@ private:
|
|||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
#ifdef HAVE_PYTHON
|
#ifdef HAVE_PYTHON
|
||||||
|
void pack_class_object(DCClass *dclass, PyObject *object);
|
||||||
PyObject *unpack_class_object(DCClass *dclass);
|
PyObject *unpack_class_object(DCClass *dclass);
|
||||||
void set_class_element(PyObject *object, const DCField *field);
|
void set_class_element(PyObject *object, const DCField *field);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user