diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index a0d73c75d60..ea097ddff5b 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -209,6 +209,30 @@ static PyObject *listvalue_buffer_concat(PyObject * self, PyObject * other) return listval_new->NewProxy(true); /* python owns this list */ } +static int listvalue_buffer_contains(PyObject *self_v, PyObject *value) +{ + CListValue *self= static_cast(BGE_PROXY_REF(self_v)); + + if (self==NULL) { + PyErr_SetString(PyExc_SystemError, "val in CList, "BGE_PROXY_ERROR_MSG); + return -1; + } + + if (PyString_Check(value)) { + if (self->FindValue((const char *)PyString_AsString(value))) { + return 1; + } + } + else if (BGE_PROXY_CHECK_TYPE(value)) { /* not dict like at all but this worked before __contains__ was used */ + CValue *item= static_cast(BGE_PROXY_REF(value)); + for (int i=0; i < self->GetCount(); i++) + if (self->GetValue(i) == item) // Com + return 1; + + } // not using CheckEqual + + return 0; +} static PySequenceMethods listvalue_as_sequence = { @@ -225,6 +249,7 @@ static PySequenceMethods listvalue_as_sequence = { NULL, /*sq_ass_item*/ NULL, /*sq_ass_slice*/ #endif + (objobjproc)listvalue_buffer_contains, /* sq_contains */ }; @@ -264,7 +289,9 @@ PyTypeObject CListValue::Type = { 0, py_base_getattro, py_base_setattro, - 0,0,0,0,0,0,0,0,0, + 0, + Py_TPFLAGS_DEFAULT, + 0,0,0,0,0,0,0, Methods }; @@ -499,7 +526,7 @@ PyObject* CListValue::Pyreverse() bool CListValue::CheckEqual(CValue* first,CValue* second) { bool result = false; - + CValue* eqval = ((CValue*)first)->Calc(VALUE_EQL_OPERATOR,(CValue*)second); if (eqval==NULL) @@ -528,7 +555,7 @@ PyObject* CListValue::Pyindex(PyObject *value) for (int i=0;iBGE_PROXY_REF(self_v); const char *attr_str= PyString_AsString(item); @@ -1295,7 +1295,7 @@ PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item) PyObject* pyconvert; if (self==NULL) { - PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, "val = gameOb[key]: KX_GameObject, "BGE_PROXY_ERROR_MSG); return NULL; } @@ -1321,7 +1321,7 @@ PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item) } -int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) +static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) { KX_GameObject* self= static_castBGE_PROXY_REF(self_v); const char *attr_str= PyString_AsString(key); @@ -1329,7 +1329,7 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) PyErr_Clear(); if (self==NULL) { - PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, "gameOb[key] = value: KX_GameObject, "BGE_PROXY_ERROR_MSG); return -1; } @@ -1409,11 +1409,40 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) return 0; /* success */ } -/* Cant set the len otherwise it can evaluate as false */ +static int Seq_Contains(PyObject *self_v, PyObject *value) +{ + KX_GameObject* self= static_castBGE_PROXY_REF(self_v); + + if (self==NULL) { + PyErr_SetString(PyExc_SystemError, "val in gameOb: KX_GameObject, "BGE_PROXY_ERROR_MSG); + return -1; + } + + if(PyString_Check(value) && self->GetProperty(PyString_AsString(value))) + return 1; + + if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value)) + return 1; + + return 0; +} + + PyMappingMethods KX_GameObject::Mapping = { (lenfunc)NULL , /*inquiry mp_length */ - (binaryfunc)KX_GameObject::Map_GetItem, /*binaryfunc mp_subscript */ - (objobjargproc)KX_GameObject::Map_SetItem, /*objobjargproc mp_ass_subscript */ + (binaryfunc)Map_GetItem, /*binaryfunc mp_subscript */ + (objobjargproc)Map_SetItem, /*objobjargproc mp_ass_subscript */ +}; + +PySequenceMethods KX_GameObject::Sequence = { + NULL, /* Cant set the len otherwise it can evaluate as false */ + NULL, /* sq_concat */ + NULL, /* sq_repeat */ + NULL, /* sq_item */ + NULL, /* sq_slice */ + NULL, /* sq_ass_item */ + NULL, /* sq_ass_slice */ + (objobjproc)Seq_Contains, /* sq_contains */ }; PyTypeObject KX_GameObject::Type = { @@ -1433,12 +1462,15 @@ PyTypeObject KX_GameObject::Type = { 0, 0, py_base_repr, - 0,0, + 0, + &Sequence, &Mapping, 0,0,0, py_base_getattro, py_base_setattro, - 0,0,0,0,0,0,0,0,0, + 0, + Py_TPFLAGS_DEFAULT, + 0,0,0,0,0,0,0, Methods }; @@ -2779,16 +2811,11 @@ PyObject* KX_GameObject::Pyget(PyObject *args) /* Matches python dict.has_key() */ PyObject* KX_GameObject::Pyhas_key(PyObject* value) { - if(PyString_Check(value) && GetProperty(PyString_AsString(value))) - Py_RETURN_TRUE; - - if (m_attr_dict && PyDict_GetItem(m_attr_dict, value)) - Py_RETURN_TRUE; - - Py_RETURN_FALSE; + // the ONLY error case is invalid data, this is checked by the macro'd static function + // that calls this one. but make sure Seq_Contains doesnt add extra errors later on. + return PyBool_FromLong(Seq_Contains((PyObject *)this, value)); } - /* --------------------------------------------------------------------- * Some stuff taken from the header * --------------------------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index dbdea97031d..ff5c8a01e6e 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -917,10 +917,8 @@ public: static PyObject* pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); /* getitem/setitem */ - static Py_ssize_t Map_Len(PyObject* self); static PyMappingMethods Mapping; - static PyObject* Map_GetItem(PyObject *self_v, PyObject *item); - static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val); + static PySequenceMethods Sequence; private : diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 274d8f26d78..ae9e097a96e 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -293,12 +293,15 @@ PyTypeObject KX_LightObject::Type = { 0, 0, py_base_repr, - 0,0, + 0, + &KX_GameObject::Sequence, &KX_GameObject::Mapping, 0,0,0, py_base_getattro, py_base_setattro, - 0,0,0,0,0,0,0,0,0, + 0, + Py_TPFLAGS_DEFAULT, + 0,0,0,0,0,0,0, Methods };