Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2009-04-02 09:38:05 +0400
committerCampbell Barton <ideasman42@gmail.com>2009-04-02 09:38:05 +0400
commitfcc23faa3a5ec3c697e85e9a6b604ac7db80a05b (patch)
tree83203f4bdf0f56d6de7b659449aade290fe0d90b
parent48e4a4834092a8772141e6240e5e70d67110f126 (diff)
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.
-rw-r--r--source/gameengine/Expressions/Value.cpp178
-rw-r--r--source/gameengine/Expressions/Value.h6
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp76
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h8
4 files changed, 174 insertions, 94 deletions
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
index ebb12636ac2..2ab0a9addee 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/Value.cpp
@@ -320,55 +320,70 @@ STR_String CValue::op2str (VALUE_OPERATOR op)
//
void CValue::SetProperty(const STR_String & name,CValue* ioProperty)
{
- // Check if somebody is setting an empty property
if (ioProperty==NULL)
- {
+ { // Check if somebody is setting an empty property
trace("Warning:trying to set empty property!");
return;
}
- // Make sure we have a property array
- if (m_pNamedPropertyArray == NULL)
+ if (m_pNamedPropertyArray)
+ { // Try to replace property (if so -> exit as soon as we replaced it)
+ CValue* oldval = (*m_pNamedPropertyArray)[name];
+ if (oldval)
+ oldval->Release();
+ }
+ else { // Make sure we have a property array
m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
-
- // Try to replace property (if so -> exit as soon as we replaced it)
- CValue* oldval = (*m_pNamedPropertyArray)[name];
- if (oldval)
- {
- oldval->Release();
}
// Add property at end of array
(*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
}
+void CValue::SetProperty(const char* name,CValue* ioProperty)
+{
+ if (ioProperty==NULL)
+ { // Check if somebody is setting an empty property
+ trace("Warning:trying to set empty property!");
+ return;
+ }
+ if (m_pNamedPropertyArray)
+ { // Try to replace property (if so -> exit as soon as we replaced it)
+ CValue* oldval = (*m_pNamedPropertyArray)[name];
+ if (oldval)
+ oldval->Release();
+ }
+ else { // Make sure we have a property array
+ m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
+ }
+
+ // Add property at end of array
+ (*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
+}
//
// Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
//
CValue* CValue::GetProperty(const STR_String & inName)
{
- // Check properties, as soon as we found it -> Return a pointer to the property
- CValue* result = NULL;
- if (m_pNamedPropertyArray)
- {
- std::map<STR_String,CValue*>::iterator it = (*m_pNamedPropertyArray).find(inName);
- if (!( it==m_pNamedPropertyArray->end()))
- {
- result = (*it).second;
- }
-
+ if (m_pNamedPropertyArray) {
+ std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
+ if (it != m_pNamedPropertyArray->end())
+ return (*it).second;
}
- //for (int i=0; i<m_pValuePropertyArray->size(); i++)
- // if ((*m_pValuePropertyArray)[i]->GetName() == inName)
- // return (*m_pValuePropertyArray)[i];
-
- // Did not find property with name <inName>, return NULL property pointer
- return result;
+ return NULL;
}
-
+CValue* CValue::GetProperty(const char *inName)
+{
+ if (m_pNamedPropertyArray) {
+ std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
+ if (it != m_pNamedPropertyArray->end())
+ return (*it).second;
+ }
+ return NULL;
+}
//
// Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
@@ -396,26 +411,20 @@ float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
//
// Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
//
-bool CValue::RemoveProperty(const STR_String & inName)
+bool CValue::RemoveProperty(const char *inName)
{
// Check if there are properties at all which can be removed
- if (m_pNamedPropertyArray) {
- CValue* val = GetProperty(inName);
- if (NULL != val)
+ if (m_pNamedPropertyArray)
+ {
+ std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
+ if (it != m_pNamedPropertyArray->end())
{
- val->Release();
- m_pNamedPropertyArray->erase(inName);
+ ((*it).second)->Release();
+ m_pNamedPropertyArray->erase(it);
return true;
}
- }
-
- char err[128];
- if (m_pNamedPropertyArray)
- sprintf(err, "attribute \"%s\" dosnt exist", inName.ReadPtr());
- else
- sprintf(err, "attribute \"%s\" dosnt exist (no property array)", inName.ReadPtr());
+ }
- PyErr_SetString(PyExc_AttributeError, err);
return false;
}
@@ -426,8 +435,8 @@ vector<STR_String> CValue::GetPropertyNames()
{
vector<STR_String> result;
if(!m_pNamedPropertyArray) return result;
- for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
- !(it == m_pNamedPropertyArray->end());it++)
+ std::map<STR_String,CValue*>::iterator it;
+ for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
{
result.push_back((*it).first);
}
@@ -444,8 +453,8 @@ void CValue::ClearProperties()
return;
// Remove all properties
- for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
- !(it == m_pNamedPropertyArray->end());it++)
+ std::map<STR_String,CValue*>::iterator it;
+ for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
{
CValue* tmpval = (*it).second;
//STR_String name = (*it).first;
@@ -464,9 +473,11 @@ void CValue::ClearProperties()
//
void CValue::SetPropertiesModified(bool inModified)
{
- int numprops = GetPropertyCount();
- for (int i=0; i<numprops; i++)
- GetProperty(i)->SetModified(inModified);
+ if(!m_pNamedPropertyArray) return;
+ std::map<STR_String,CValue*>::iterator it;
+
+ for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
+ ((*it).second)->SetModified(inModified);
}
@@ -476,11 +487,13 @@ void CValue::SetPropertiesModified(bool inModified)
//
bool CValue::IsAnyPropertyModified()
{
- int numprops = GetPropertyCount();
- for (int i=0;i<numprops;i++)
- if (GetProperty(i)->IsModified())
+ if(!m_pNamedPropertyArray) return false;
+ std::map<STR_String,CValue*>::iterator it;
+
+ for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
+ if (((*it).second)->IsModified())
return true;
-
+
return false;
}
@@ -489,7 +502,6 @@ bool CValue::IsAnyPropertyModified()
//
// Get property number <inIndex>
//
-
CValue* CValue::GetProperty(int inIndex)
{
@@ -498,8 +510,8 @@ CValue* CValue::GetProperty(int inIndex)
if (m_pNamedPropertyArray)
{
- for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
- !(it == m_pNamedPropertyArray->end());it++)
+ std::map<STR_String,CValue*>::iterator it;
+ for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
{
if (count++==inIndex)
{
@@ -535,8 +547,8 @@ void CValue::CloneProperties(CValue *replica)
if (m_pNamedPropertyArray)
{
replica->m_pNamedPropertyArray=NULL;
- for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
- !(it == m_pNamedPropertyArray->end());it++)
+ std::map<STR_String,CValue*>::iterator it;
+ for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
{
CValue *val = (*it).second->GetReplica();
replica->SetProperty((*it).first,val);
@@ -687,28 +699,15 @@ PyAttributeDef CValue::Attributes[] = {
PyObject* CValue::_getattr(const char *attr)
{
- CValue* resultattr = FindIdentifier(STR_String(attr));
- STR_String text;
+ CValue* resultattr = GetProperty(attr);
if (resultattr)
{
- if (resultattr->IsError())
- {
- resultattr->Release();
- } else
- {
- // to avoid some compare problems, return a real pythonthing
- PyObject* pyconvert = resultattr->ConvertValueToPython();
- if (pyconvert)
- {
- resultattr->Release();
- return pyconvert;
- } else
- {
- // also check if it's already in pythoninterpreter!
- return resultattr;
- }
-
- }
+ PyObject* pyconvert = resultattr->ConvertValueToPython();
+
+ if (pyconvert)
+ return pyconvert;
+ else
+ return resultattr; // also check if it's already in pythoninterpreter!
}
_getattr_up(PyObjectPlus);
}
@@ -774,26 +773,25 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
int CValue::_delattr(const char *attr)
{
- if (!RemoveProperty(STR_String(attr))) /* sets error */
- return 1;
- return 0;
+ if (RemoveProperty(STR_String(attr)))
+ return 0;
+
+ PyErr_Format(PyExc_AttributeError, "attribute \"%s\" dosnt exist", attr);
+ return 1;
}
-int CValue::_setattr(const char *attr,PyObject* pyobj)
+int CValue::_setattr(const char *attr, PyObject* pyobj)
{
CValue* vallie = ConvertPythonToValue(pyobj);
if (vallie)
{
- STR_String attr_str = attr;
- CValue* oldprop = GetProperty(attr_str);
+ CValue* oldprop = GetProperty(attr);
if (oldprop)
- {
oldprop->SetValue(vallie);
- } else
- {
- SetProperty(attr_str, vallie);
- }
+ else
+ SetProperty(attr, vallie);
+
vallie->Release();
} else
{
@@ -811,8 +809,8 @@ PyObject* CValue::ConvertKeysToPython( void )
if (m_pNamedPropertyArray)
{
- for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
- !(it == m_pNamedPropertyArray->end());it++)
+ std::map<STR_String,CValue*>::iterator it;
+ for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
{
pystr = PyString_FromString( (*it).first );
PyList_Append(pylist, pystr);
diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h
index caf1064dc32..4678ab1f0c2 100644
--- a/source/gameengine/Expressions/Value.h
+++ b/source/gameengine/Expressions/Value.h
@@ -283,10 +283,12 @@ public:
/// Property Management
virtual void SetProperty(const STR_String& name,CValue* ioProperty); // Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
- virtual CValue* GetProperty(const STR_String & inName); // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
+ virtual void SetProperty(const char* name,CValue* ioProperty);
+ virtual CValue* GetProperty(const char* inName); // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
+ virtual CValue* GetProperty(const STR_String & inName);
STR_String GetPropertyText(const STR_String & inName,const STR_String& deftext=""); // Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
float GetPropertyNumber(const STR_String& inName,float defnumber);
- virtual bool RemoveProperty(const STR_String & inName); // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
+ virtual bool RemoveProperty(const char *inName); // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
virtual vector<STR_String> GetPropertyNames();
virtual void ClearProperties(); // Clear all properties
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index bbfa2ad324f..281de1965d4 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -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
};
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 326b3700ad7..774977f2ecf 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -822,7 +822,13 @@ public:
static PyObject* pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-
+ /* getitem/setitem */
+ static int 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);
+
+
private :
/**