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.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCClass::
|
||||
pack_required_field(DCPacker &packer, PyObject *distobj, DCField *field) const {
|
||||
DCAtomicField *atom = field->as_atomic_field();
|
||||
pack_required_field(DCPacker &packer, PyObject *distobj,
|
||||
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) {
|
||||
ostringstream strm;
|
||||
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(func);
|
||||
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";
|
||||
return false;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ PUBLISHED:
|
||||
void direct_update(PyObject *distobj, const string &field_name,
|
||||
const Datagram &datagram);
|
||||
bool pack_required_field(DCPacker &packer, PyObject *distobj,
|
||||
DCField *field) const;
|
||||
const DCField *field) const;
|
||||
|
||||
|
||||
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.get_current_field() == this, false);
|
||||
|
||||
nassertr(PySequence_Check(sequence), false);
|
||||
|
||||
packer.pack_object(sequence);
|
||||
if (!packer.had_error()) {
|
||||
/*
|
||||
@ -208,22 +206,24 @@ pack_args(DCPacker &packer, PyObject *sequence) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
PyObject *tuple = PySequence_Tuple(sequence);
|
||||
PyObject *str = PyObject_Str(tuple);
|
||||
if (!Notify::ptr()->has_assert_failed()) {
|
||||
PyObject *tuple = PySequence_Tuple(sequence);
|
||||
PyObject *str = PyObject_Str(tuple);
|
||||
|
||||
ostringstream strm;
|
||||
if (packer.had_pack_error()) {
|
||||
strm << "Incorrect arguments to field: " << get_name()
|
||||
<< PyString_AsString(str);
|
||||
} else {
|
||||
strm << "Value out of range on field: " << get_name()
|
||||
<< PyString_AsString(str);
|
||||
ostringstream strm;
|
||||
if (packer.had_pack_error()) {
|
||||
strm << "Incorrect arguments to field: " << get_name()
|
||||
<< PyString_AsString(str);
|
||||
} else {
|
||||
strm << "Value out of range on field: " << get_name()
|
||||
<< PyString_AsString(str);
|
||||
}
|
||||
|
||||
Py_DECREF(str);
|
||||
Py_DECREF(tuple);
|
||||
|
||||
nassert_raise(strm.str());
|
||||
}
|
||||
|
||||
Py_DECREF(str);
|
||||
Py_DECREF(tuple);
|
||||
|
||||
nassert_raise(strm.str());
|
||||
return false;
|
||||
}
|
||||
#endif // HAVE_PYTHON
|
||||
|
@ -634,8 +634,6 @@ unpack_skip() {
|
||||
void DCPacker::
|
||||
pack_object(PyObject *object) {
|
||||
nassertv(_mode == M_pack || _mode == M_repack);
|
||||
PyObject *str = PyObject_Str(object);
|
||||
Py_DECREF(str);
|
||||
|
||||
if (PyInt_Check(object)) {
|
||||
pack_int(PyInt_AS_LONG(object));
|
||||
@ -654,15 +652,65 @@ pack_object(PyObject *object) {
|
||||
pack_string(string(buffer, length));
|
||||
}
|
||||
|
||||
} else if (PySequence_Check(object)) {
|
||||
push();
|
||||
int size = PySequence_Size(object);
|
||||
for (int i = 0; i < size; i++) {
|
||||
PyObject *element = PySequence_GetItem(object, i);
|
||||
pack_object(element);
|
||||
Py_DECREF(element);
|
||||
} 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();
|
||||
int size = PySequence_Size(object);
|
||||
for (int i = 0; i < size; i++) {
|
||||
PyObject *element = PySequence_GetItem(object, i);
|
||||
pack_object(element);
|
||||
Py_DECREF(element);
|
||||
}
|
||||
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;
|
||||
}
|
||||
pop();
|
||||
}
|
||||
}
|
||||
#endif // HAVE_PYTHON
|
||||
@ -1034,6 +1082,33 @@ clear() {
|
||||
_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
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPacker::unpack_class_object
|
||||
|
@ -178,6 +178,7 @@ private:
|
||||
void clear();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
void pack_class_object(DCClass *dclass, PyObject *object);
|
||||
PyObject *unpack_class_object(DCClass *dclass);
|
||||
void set_class_element(PyObject *object, const DCField *field);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user