Added getitem/setitem access for KX_GameObject

ob.someProp = 10
can now be...
ob["someProp"] = 10

For simple get/set test with an objects 10 properties, this is ~30% faster.

Though I like the attribute access, its slower because it needs to lookup BGE attributes and methods (for parent classes as well as KX_GameObject class).

This could also be an advantage if there are collisions between new attributes added for 2.49 and existing properties a game uses.

Made some other small optimizations,
- Getting and setting property can use const char* as well as STR_String (avoids making new STR_Strings just to do the lookup).
- CValue::SetPropertiesModified() and CValue::SetPropertiesModified(), were looping through all items in the std::map, advancing from the beginning each time.
This commit is contained in:
Campbell Barton
2009-04-02 05:38:05 +00:00
parent 48e4a48340
commit fcc23faa3a
4 changed files with 174 additions and 94 deletions

View File

@@ -1103,6 +1103,80 @@ PyObject* KX_GameObject::PyGetPosition(PyObject* self)
}
int KX_GameObject::Map_Len(PyObject* self_v)
{
return (static_cast<KX_GameObject*>(self_v))->GetPropertyCount();
}
PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
const char *attr= PyString_AsString(item);
CValue* resultattr;
PyObject* pyconvert;
if(attr==NULL) {
PyErr_SetString(PyExc_TypeError, "KX_GameObject key but a string");
return NULL;
}
resultattr = self->GetProperty(attr);
if(resultattr==NULL) {
PyErr_SetString(PyExc_KeyError, "KX_GameObject key does not exist");
return NULL;
}
pyconvert = resultattr->ConvertValueToPython();
return pyconvert ? pyconvert:resultattr;
}
int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
const char *attr= PyString_AsString(key);
if(attr==NULL) {
PyErr_SetString(PyExc_TypeError, "KX_GameObject key but a string");
return 1;
}
if (val==NULL) { /* del ob["key"] */
if (self->RemoveProperty(attr)==false) {
PyErr_Format(PyExc_KeyError, "KX_GameObject key \"%s\" not found", attr);
return 1;
}
}
else { /* ob["key"] = value */
CValue* vallie = self->ConvertPythonToValue(val);
if(vallie==NULL)
return 1; /* ConvertPythonToValue sets the error */
CValue* oldprop = self->GetProperty(attr);
if (oldprop)
oldprop->SetValue(vallie);
else
self->SetProperty(attr, vallie);
vallie->Release();
}
return 0;
}
PyMappingMethods KX_GameObject::Mapping = {
(inquiry)KX_GameObject::Map_Len, /*inquiry mp_length */
(binaryfunc)KX_GameObject::Map_GetItem, /*binaryfunc mp_subscript */
(objobjargproc)KX_GameObject::Map_SetItem, /*objobjargproc mp_ass_subscript */
};
PyTypeObject KX_GameObject::Type = {
PyObject_HEAD_INIT(&PyType_Type)
@@ -1118,7 +1192,7 @@ PyTypeObject KX_GameObject::Type = {
__repr,
0, //&cvalue_as_number,
0,
0,
&Mapping,
0,
0
};