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:
Diffstat (limited to 'source/gameengine/Expressions/intern/ListValue.cpp')
-rw-r--r--source/gameengine/Expressions/intern/ListValue.cpp702
1 files changed, 702 insertions, 0 deletions
diff --git a/source/gameengine/Expressions/intern/ListValue.cpp b/source/gameengine/Expressions/intern/ListValue.cpp
new file mode 100644
index 00000000000..557ce7be300
--- /dev/null
+++ b/source/gameengine/Expressions/intern/ListValue.cpp
@@ -0,0 +1,702 @@
+/** \file gameengine/Expressions/ListValue.cpp
+ * \ingroup expressions
+ */
+// ListValue.cpp: implementation of the CListValue class.
+//
+//////////////////////////////////////////////////////////////////////
+/*
+ * Copyright (c) 1996-2000 Erwin Coumans <coockie@acm.org>
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Erwin Coumans makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ */
+
+#include <stdio.h>
+
+#include "EXP_ListValue.h"
+#include "EXP_StringValue.h"
+#include "EXP_VoidValue.h"
+#include <algorithm>
+#include "EXP_BoolValue.h"
+
+#include "BLI_sys_types.h" /* for intptr_t support */
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CListValue::CListValue()
+: CPropValue()
+{
+ m_bReleaseContents=true;
+}
+
+
+
+CListValue::~CListValue()
+{
+
+ if (m_bReleaseContents) {
+ for (unsigned int i=0;i<m_pValueArray.size();i++) {
+ m_pValueArray[i]->Release();
+ }
+ }
+}
+
+
+static STR_String gstrListRep=STR_String("List");
+
+const STR_String & CListValue::GetText()
+{
+ gstrListRep = "[";
+ STR_String commastr = "";
+
+ for (int i=0;i<GetCount();i++)
+ {
+ gstrListRep += commastr;
+ gstrListRep += GetValue(i)->GetText();
+ commastr = ",";
+ }
+ gstrListRep += "]";
+
+ return gstrListRep;
+}
+
+
+
+CValue* CListValue::GetReplica()
+{
+ CListValue* replica = new CListValue(*this);
+
+ replica->ProcessReplica();
+
+ replica->m_bReleaseContents=true; // for copy, complete array is copied for now...
+ // copy all values
+ int numelements = m_pValueArray.size();
+ unsigned int i=0;
+ replica->m_pValueArray.resize(numelements);
+ for (i=0;i<m_pValueArray.size();i++)
+ replica->m_pValueArray[i] = m_pValueArray[i]->GetReplica();
+
+
+ return replica;
+};
+
+
+
+void CListValue::SetValue(int i, CValue *val)
+{
+ assertd(i < m_pValueArray.size());
+ m_pValueArray[i]=val;
+}
+
+
+
+void CListValue::Resize(int num)
+{
+ m_pValueArray.resize(num);
+}
+
+
+
+void CListValue::Remove(int i)
+{
+ assertd(i<m_pValueArray.size());
+ m_pValueArray.erase(m_pValueArray.begin()+i);
+}
+
+
+
+void CListValue::ReleaseAndRemoveAll()
+{
+ for (unsigned int i=0;i<m_pValueArray.size();i++)
+ m_pValueArray[i]->Release();
+ m_pValueArray.clear();//.Clear();
+}
+
+
+
+CValue* CListValue::FindValue(const STR_String &name)
+{
+ for (int i=0; i < GetCount(); i++)
+ if (GetValue(i)->GetName() == name)
+ return GetValue(i);
+
+ return NULL;
+}
+
+CValue* CListValue::FindValue(const char *name)
+{
+ for (int i=0; i < GetCount(); i++)
+ if (GetValue(i)->GetName() == name)
+ return GetValue(i);
+
+ return NULL;
+}
+
+bool CListValue::SearchValue(CValue *val)
+{
+ for (int i=0;i<GetCount();i++)
+ if (val == GetValue(i))
+ return true;
+ return false;
+}
+
+
+
+void CListValue::SetReleaseOnDestruct(bool bReleaseContents)
+{
+ m_bReleaseContents = bReleaseContents;
+}
+
+
+
+bool CListValue::RemoveValue(CValue *val)
+{
+ bool result=false;
+
+ for (int i=GetCount()-1;i>=0;i--)
+ if (val == GetValue(i))
+ {
+ Remove(i);
+ result=true;
+ }
+ return result;
+}
+
+
+
+void CListValue::MergeList(CListValue *otherlist)
+{
+
+ int numelements = this->GetCount();
+ int numotherelements = otherlist->GetCount();
+
+
+ Resize(numelements+numotherelements);
+
+ for (int i=0;i<numotherelements;i++)
+ {
+ SetValue(i+numelements,otherlist->GetValue(i)->AddRef());
+ }
+}
+
+bool CListValue::CheckEqual(CValue* first,CValue* second)
+{
+ bool result = false;
+
+ CValue* eqval = ((CValue*)first)->Calc(VALUE_EQL_OPERATOR,(CValue*)second);
+
+ if (eqval==NULL)
+ return false;
+ const STR_String& text = eqval->GetText();
+ if (&text==&CBoolValue::sTrueString)
+ {
+ result = true;
+ }
+ eqval->Release();
+ return result;
+
+}
+
+
+/* ---------------------------------------------------------------------
+ * Some stuff taken from the header
+ * --------------------------------------------------------------------- */
+CValue* CListValue::Calc(VALUE_OPERATOR op,CValue *val)
+{
+ //assert(false); // todo: implement me!
+ static int error_printed = 0;
+ if (error_printed==0) {
+ fprintf(stderr, "CValueList::Calc not yet implemented\n");
+ error_printed = 1;
+ }
+ return NULL;
+}
+
+CValue* CListValue::CalcFinal(VALUE_DATA_TYPE dtype,
+ VALUE_OPERATOR op,
+ CValue* val)
+{
+ //assert(false); // todo: implement me!
+ static int error_printed = 0;
+ if (error_printed==0) {
+ fprintf(stderr, "CValueList::CalcFinal not yet implemented\n");
+ error_printed = 1;
+ }
+ return NULL;
+}
+
+
+
+void CListValue::Add(CValue* value)
+{
+ m_pValueArray.push_back(value);
+}
+
+
+
+double CListValue::GetNumber()
+{
+ return -1;
+}
+
+
+
+int CListValue::GetValueType()
+{
+ return VALUE_LIST_TYPE;
+}
+
+
+
+void CListValue::SetModified(bool bModified)
+{
+ CValue::SetModified(bModified);
+ int numels = GetCount();
+
+ for (int i=0;i<numels;i++)
+ GetValue(i)->SetModified(bModified);
+}
+
+
+
+bool CListValue::IsModified()
+{
+ bool bmod = CValue::IsModified(); //normal own flag
+ int numels = GetCount();
+
+ for (int i=0;i<numels;i++)
+ bmod = bmod || GetValue(i)->IsModified();
+
+ return bmod;
+}
+
+#ifdef WITH_PYTHON
+
+/* --------------------------------------------------------------------- */
+/* Python interface ---------------------------------------------------- */
+/* --------------------------------------------------------------------- */
+
+static Py_ssize_t listvalue_bufferlen(PyObject *self)
+{
+ CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self));
+ if (list==NULL)
+ return 0;
+
+ return (Py_ssize_t)list->GetCount();
+}
+
+static PyObject *listvalue_buffer_item(PyObject *self, Py_ssize_t index)
+{
+ CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self));
+ CValue *cval;
+
+ if (list==NULL) {
+ PyErr_SetString(PyExc_SystemError, "val = CList[i], " BGE_PROXY_ERROR_MSG);
+ return NULL;
+ }
+
+ int count = list->GetCount();
+
+ if (index < 0)
+ index = count+index;
+
+ if (index < 0 || index >= count) {
+ PyErr_SetString(PyExc_IndexError, "CList[i]: Python ListIndex out of range in CValueList");
+ return NULL;
+ }
+
+ cval= list->GetValue(index);
+
+ PyObject *pyobj = cval->ConvertValueToPython();
+ if (pyobj)
+ return pyobj;
+ else
+ return cval->GetProxy();
+}
+
+
+/* just slice it into a python list... */
+static PyObject *listvalue_buffer_slice(CListValue *list, Py_ssize_t start, Py_ssize_t stop)
+{
+ PyObject *newlist;
+ Py_ssize_t i, j;
+
+ /* caller needs to validate negative index */
+#if 0
+ Py_ssize_t len = list->GetCount();
+
+ if (start > len) start = len;
+ if (stop > len) stop = len;
+#endif
+
+ newlist = PyList_New(stop - start);
+ if (!newlist)
+ return NULL;
+
+ for (i = start, j = 0; i < stop; i++, j++) {
+ PyObject *pyobj = list->GetValue(i)->ConvertValueToPython();
+ if (!pyobj) {
+ pyobj = list->GetValue(i)->GetProxy();
+ }
+ PyList_SET_ITEM(newlist, j, pyobj);
+ }
+ return newlist;
+}
+
+
+static PyObject *listvalue_mapping_subscript(PyObject *self, PyObject *key)
+{
+ CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self));
+ if (list==NULL) {
+ PyErr_SetString(PyExc_SystemError, "value = CList[i], " BGE_PROXY_ERROR_MSG);
+ return NULL;
+ }
+
+ if (PyUnicode_Check(key)) {
+ CValue *item = ((CListValue*) list)->FindValue(_PyUnicode_AsString(key));
+ if (item) {
+ PyObject *pyobj = item->ConvertValueToPython();
+ if (pyobj)
+ return pyobj;
+ else
+ return item->GetProxy();
+ }
+ }
+ else if (PyIndex_Check(key)) {
+ Py_ssize_t index = PyLong_AsSsize_t(key);
+ return listvalue_buffer_item(self, index); /* wont add a ref */
+ }
+ else if (PySlice_Check(key)) {
+ Py_ssize_t start, stop, step, slicelength;
+
+ if (PySlice_GetIndicesEx(key, list->GetCount(), &start, &stop, &step, &slicelength) < 0)
+ return NULL;
+
+ if (slicelength <= 0) {
+ return PyList_New(0);
+ }
+ else if (step == 1) {
+ return listvalue_buffer_slice(list, start, stop);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "CList[slice]: slice steps not supported");
+ return NULL;
+ }
+ }
+
+ PyErr_Format(PyExc_KeyError,
+ "CList[key]: '%R' key not in list", key);
+ return NULL;
+}
+
+/* clist + list, return a list that python owns */
+static PyObject *listvalue_buffer_concat(PyObject *self, PyObject *other)
+{
+ CListValue *listval= static_cast<CListValue *>(BGE_PROXY_REF(self));
+ Py_ssize_t i, numitems, numitems_orig;
+
+ if (listval==NULL) {
+ PyErr_SetString(PyExc_SystemError, "CList+other, " BGE_PROXY_ERROR_MSG);
+ return NULL;
+ }
+
+ numitems_orig= listval->GetCount();
+
+ // for now, we support CListValue concatenated with items
+ // and CListValue concatenated to Python Lists
+ // and CListValue concatenated with another CListValue
+
+ /* Shallow copy, don't use listval->GetReplica(), it will screw up with KX_GameObjects */
+ CListValue* listval_new = new CListValue();
+
+ if (PyList_Check(other))
+ {
+ CValue* listitemval;
+ bool error = false;
+
+ numitems = PyList_GET_SIZE(other);
+
+ /* copy the first part of the list */
+ listval_new->Resize(numitems_orig + numitems);
+ for (i=0;i<numitems_orig;i++)
+ listval_new->SetValue(i, listval->GetValue(i)->AddRef());
+
+ for (i=0;i<numitems;i++)
+ {
+ listitemval = listval->ConvertPythonToValue(PyList_GET_ITEM(other, i), true, "cList + pyList: CListValue, ");
+
+ if (listitemval) {
+ listval_new->SetValue(i+numitems_orig, listitemval);
+ } else {
+ error= true;
+ break;
+ }
+ }
+
+ if (error) {
+ listval_new->Resize(numitems_orig+i); /* resize so we don't try release NULL pointers */
+ listval_new->Release();
+ return NULL; /* ConvertPythonToValue above sets the error */
+ }
+
+ }
+ else if (PyObject_TypeCheck(other, &CListValue::Type)) {
+ // add items from otherlist to this list
+ CListValue* otherval = static_cast<CListValue *>(BGE_PROXY_REF(other));
+ if (otherval==NULL) {
+ listval_new->Release();
+ PyErr_SetString(PyExc_SystemError, "CList+other, " BGE_PROXY_ERROR_MSG);
+ return NULL;
+ }
+
+ numitems = otherval->GetCount();
+
+ /* copy the first part of the list */
+ listval_new->Resize(numitems_orig + numitems); /* resize so we don't try release NULL pointers */
+ for (i=0;i<numitems_orig;i++)
+ listval_new->SetValue(i, listval->GetValue(i)->AddRef());
+
+ /* now copy the other part of the list */
+ for (i=0;i<numitems;i++)
+ listval_new->SetValue(i+numitems_orig, otherval->GetValue(i)->AddRef());
+
+ }
+ return listval_new->NewProxy(true); /* python owns this list */
+}
+
+static int listvalue_buffer_contains(PyObject *self_v, PyObject *value)
+{
+ CListValue *self = static_cast<CListValue *>(BGE_PROXY_REF(self_v));
+
+ if (self == NULL) {
+ PyErr_SetString(PyExc_SystemError, "val in CList, " BGE_PROXY_ERROR_MSG);
+ return -1;
+ }
+
+ if (PyUnicode_Check(value)) {
+ if (self->FindValue((const char *)_PyUnicode_AsString(value))) {
+ return 1;
+ }
+ }
+ else if (PyObject_TypeCheck(value, &CValue::Type)) { /* not dict like at all but this worked before __contains__ was used */
+ CValue *item= static_cast<CValue *>(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 = {
+ listvalue_bufferlen,//(inquiry)buffer_length, /*sq_length*/
+ listvalue_buffer_concat, /*sq_concat*/
+ NULL, /*sq_repeat*/
+ listvalue_buffer_item, /*sq_item*/
+// TODO, slicing in py3
+ NULL, // listvalue_buffer_slice, /*sq_slice*/
+ NULL, /*sq_ass_item*/
+ NULL, /*sq_ass_slice*/
+ (objobjproc)listvalue_buffer_contains, /* sq_contains */
+ (binaryfunc) NULL, /* sq_inplace_concat */
+ (ssizeargfunc) NULL, /* sq_inplace_repeat */
+};
+
+
+
+/* Is this one used ? */
+static PyMappingMethods instance_as_mapping = {
+ listvalue_bufferlen, /*mp_length*/
+ listvalue_mapping_subscript, /*mp_subscript*/
+ NULL /*mp_ass_subscript*/
+};
+
+
+
+PyTypeObject CListValue::Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CListValue", /*tp_name*/
+ sizeof(PyObjectPlus_Proxy), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ py_base_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ py_base_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &listvalue_as_sequence, /*tp_as_sequence*/
+ &instance_as_mapping, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call */
+ 0,
+ NULL,
+ NULL,
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ 0,0,0,0,0,0,0,
+ Methods,
+ 0,
+ 0,
+ &CValue::Type,
+ 0,0,0,0,0,0,
+ py_base_new
+};
+
+PyMethodDef CListValue::Methods[] = {
+ /* List style access */
+ {"append", (PyCFunction)CListValue::sPyappend,METH_O},
+ {"reverse", (PyCFunction)CListValue::sPyreverse,METH_NOARGS},
+ {"index", (PyCFunction)CListValue::sPyindex,METH_O},
+ {"count", (PyCFunction)CListValue::sPycount,METH_O},
+
+ /* Dict style access */
+ {"get", (PyCFunction)CListValue::sPyget,METH_VARARGS},
+
+ /* Own cvalue funcs */
+ {"from_id", (PyCFunction)CListValue::sPyfrom_id,METH_O},
+
+ {NULL,NULL} //Sentinel
+};
+
+PyAttributeDef CListValue::Attributes[] = {
+ { NULL } //Sentinel
+};
+
+PyObject *CListValue::Pyappend(PyObject *value)
+{
+ CValue *objval = ConvertPythonToValue(value, true, "CList.append(i): CValueList, ");
+
+ if (!objval) /* ConvertPythonToValue sets the error */
+ return NULL;
+
+ if (!BGE_PROXY_PYOWNS(m_proxy)) {
+ PyErr_SetString(PyExc_TypeError,
+ "CList.append(i): internal values can't be modified");
+ return NULL;
+ }
+
+ Add(objval);
+
+ Py_RETURN_NONE;
+}
+
+PyObject *CListValue::Pyreverse()
+{
+ if (!BGE_PROXY_PYOWNS(m_proxy)) {
+ PyErr_SetString(PyExc_TypeError,
+ "CList.reverse(): internal values can't be modified");
+ return NULL;
+ }
+
+ std::reverse(m_pValueArray.begin(),m_pValueArray.end());
+ Py_RETURN_NONE;
+}
+
+PyObject *CListValue::Pyindex(PyObject *value)
+{
+ PyObject *result = NULL;
+
+ CValue *checkobj = ConvertPythonToValue(value, true, "val = cList[i]: CValueList, ");
+ if (checkobj==NULL)
+ return NULL; /* ConvertPythonToValue sets the error */
+
+ int numelem = GetCount();
+ for (int i=0;i<numelem;i++)
+ {
+ CValue* elem = GetValue(i);
+ if (checkobj==elem || CheckEqual(checkobj,elem))
+ {
+ result = PyLong_FromLong(i);
+ break;
+ }
+ }
+ checkobj->Release();
+
+ if (result==NULL) {
+ PyErr_SetString(PyExc_ValueError, "CList.index(x): x not in CListValue");
+ }
+ return result;
+
+}
+
+
+
+PyObject *CListValue::Pycount(PyObject *value)
+{
+ int numfound = 0;
+
+ CValue *checkobj = ConvertPythonToValue(value, false, ""); /* error ignored */
+
+ if (checkobj==NULL) { /* in this case just return that there are no items in the list */
+ PyErr_Clear();
+ return PyLong_FromLong(0);
+ }
+
+ int numelem = GetCount();
+ for (int i=0;i<numelem;i++)
+ {
+ CValue* elem = GetValue(i);
+ if (checkobj==elem || CheckEqual(checkobj,elem))
+ {
+ numfound ++;
+ }
+ }
+ checkobj->Release();
+
+ return PyLong_FromLong(numfound);
+}
+
+/* Matches python dict.get(key, [default]) */
+PyObject *CListValue::Pyget(PyObject *args)
+{
+ char *key;
+ PyObject *def = Py_None;
+
+ if (!PyArg_ParseTuple(args, "s|O:get", &key, &def))
+ return NULL;
+
+ CValue *item = FindValue((const char *)key);
+ if (item) {
+ PyObject *pyobj = item->ConvertValueToPython();
+ if (pyobj)
+ return pyobj;
+ else
+ return item->GetProxy();
+ }
+ Py_INCREF(def);
+ return def;
+}
+
+
+PyObject *CListValue::Pyfrom_id(PyObject *value)
+{
+ uintptr_t id= (uintptr_t)PyLong_AsVoidPtr(value);
+
+ if (PyErr_Occurred())
+ return NULL;
+
+ int numelem = GetCount();
+ for (int i=0;i<numelem;i++)
+ {
+ if (reinterpret_cast<uintptr_t>(m_pValueArray[i]->m_proxy) == id)
+ return GetValue(i)->GetProxy();
+ }
+ PyErr_SetString(PyExc_IndexError, "from_id(#): id not found in CValueList");
+ return NULL;
+
+}
+
+#endif // WITH_PYTHON