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/Value.cpp')
-rw-r--r--source/gameengine/Expressions/Value.cpp767
1 files changed, 767 insertions, 0 deletions
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
new file mode 100644
index 00000000000..e2a7189fb02
--- /dev/null
+++ b/source/gameengine/Expressions/Value.cpp
@@ -0,0 +1,767 @@
+// Value.cpp: implementation of the CValue class.
+// developed at Eindhoven University of Technology, 1997
+// by the OOPS team
+//////////////////////////////////////////////////////////////////////
+/*
+ * 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 "Value.h"
+#include "FloatValue.h"
+#include "IntValue.h"
+#include "VectorValue.h"
+#include "VoidValue.h"
+#include "StringValue.h"
+#include "ErrorValue.h"
+#include "ListValue.h"
+
+//#include "FactoryManager.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+double CValue::m_sZeroVec[3] = {0.0,0.0,0.0};
+
+#ifndef NO_EXP_PYTHON_EMBEDDING
+
+PyObject* cvalue_add(PyObject*v, PyObject*w)
+{
+ return ((CValue*)v)->Calc(VALUE_ADD_OPERATOR,(CValue*)w);
+}
+PyObject* cvalue_sub(PyObject*v, PyObject*w)
+{
+ return ((CValue*)v)->Calc(VALUE_SUB_OPERATOR,(CValue*)w);
+}
+PyObject* cvalue_mul(PyObject*v, PyObject*w)
+{
+ return ((CValue*)v)->Calc(VALUE_MUL_OPERATOR,(CValue*)w);
+}
+PyObject* cvalue_div(PyObject*v, PyObject*w)
+{
+ return ((CValue*)v)->Calc(VALUE_DIV_OPERATOR,(CValue*)w);
+}
+PyObject* cvalue_neg(PyObject*v)
+{
+ return ((CValue*)v)->Calc(VALUE_NEG_OPERATOR,(CValue*)v);
+}
+PyObject* cvalue_pos(PyObject*v)
+{
+ return ((CValue*)v)->Calc(VALUE_POS_OPERATOR,(CValue*)v);
+}
+
+
+int MyPyCompare (PyObject* v,PyObject* w)
+{
+ CValue* eqval = ((CValue*)v)->Calc(VALUE_EQL_OPERATOR,(CValue*)w);
+ STR_String txt = eqval->GetText();
+ eqval->Release();
+ if (txt=="TRUE")
+ return 0;
+ CValue* lessval = ((CValue*)v)->Calc(VALUE_LES_OPERATOR,(CValue*)w);
+ txt = lessval->GetText();
+ lessval->Release();
+ if (txt=="TRUE")
+ return -1;
+
+ return 1;
+}
+
+
+int cvalue_coerce(PyObject** pv,PyObject** pw)
+{
+ if (PyInt_Check(*pw)) {
+ double db = (double)PyInt_AsLong(*pw);
+ *pw = new CIntValue(db);
+ Py_INCREF(*pv);
+ return 0;
+ }
+ else if (PyLong_Check(*pw)) {
+ double db = PyLong_AsDouble(*pw);
+ *pw = new CFloatValue(db);
+ Py_INCREF(*pv);
+ return 0;
+ }
+ else if (PyFloat_Check(*pw)) {
+ double db = PyFloat_AsDouble(*pw);
+ *pw = new CFloatValue(db);
+ Py_INCREF(*pv);
+ return 0;
+ } else if (PyString_Check(*pw)) {
+ const STR_String str = PyString_AsString(*pw);
+ *pw = new CStringValue(str,"");
+ Py_INCREF(*pv);
+ return 0;
+ }
+ return 1; /* Can't do it */
+
+}
+static PyNumberMethods cvalue_as_number = {
+ (binaryfunc)cvalue_add, /*nb_add*/
+ (binaryfunc)cvalue_sub, /*nb_subtract*/
+ (binaryfunc)cvalue_mul, /*nb_multiply*/
+ (binaryfunc)cvalue_div, /*nb_divide*/
+ 0,//(binaryfunc)cvalue_remainder, /*nb_remainder*/
+ 0,//(binaryfunc)cvalue_divmod, /*nb_divmod*/
+ 0,//0,//0,//0,//(ternaryfunc)cvalue_pow, /*nb_power*/
+ (unaryfunc)cvalue_neg, /*nb_negative*/
+ 0,//(unaryfunc)cvalue_pos, /*nb_positive*/
+ 0,//(unaryfunc)cvalue_abs, /*nb_absolute*/
+ 0,//(inquiry)cvalue_nonzero, /*nb_nonzero*/
+ 0, /*nb_invert*/
+ 0, /*nb_lshift*/
+ 0, /*nb_rshift*/
+ 0, /*nb_and*/
+ 0, /*nb_xor*/
+ 0, /*nb_or*/
+ (coercion)cvalue_coerce, /*nb_coerce*/
+ 0,//(unaryfunc)cvalue_int, /*nb_int*/
+ 0,//(unaryfunc)cvalue_long, /*nb_long*/
+ 0,//(unaryfunc)cvalue_float, /*nb_float*/
+ 0, /*nb_oct*/
+ 0, /*nb_hex*/
+};
+
+
+PyTypeObject CValue::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "CValue",
+ sizeof(CValue),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ &MyPyCompare,
+ __repr,
+ &cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject CValue::Parents[] = {
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef CValue::Methods[] = {
+// { "printHello", (PyCFunction) CValue::sPyPrintHello, Py_NEWARGS},
+ { "getName", (PyCFunction) CValue::sPyGetName, Py_NEWARGS},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* CValue::PyGetName(PyObject* self,PyObject* args,PyObject* kwds)
+{
+ PyObject* pyname = PyString_FromString(this->GetName());
+ return pyname;
+}
+
+
+
+CValue::CValue(PyTypeObject *T)
+ : PyObjectPlus(T),
+#else
+CValue::CValue()
+:
+#endif //NO_EXP_PYTHON_EMBEDDING
+
+m_refcount(1),
+m_pNamedPropertyArray(NULL)
+/*
+pre: false
+effect: constucts a CValue
+*/
+{
+ //debug(gRefCountValue++) // debugging
+}
+
+
+
+CValue::~CValue()
+/*
+pre:
+effect: deletes the object
+*/
+{
+ ClearProperties();
+
+ assertd (m_refcount==0);
+}
+
+
+
+
+#define VALUE_SUB(val1, val2) (val1)->Calc(VALUE_SUB_OPERATOR, val2)
+#define VALUE_MUL(val1, val2) (val1)->Calc(VALUE_MUL_OPERATOR, val2)
+#define VALUE_DIV(val1, val2) (val1)->Calc(VALUE_DIV_OPERATOR, val2)
+#define VALUE_NEG(val1) (val1)->Calc(VALUE_NEG_OPERATOR, val1)
+#define VALUE_POS(val1) (val1)->Calc(VALUE_POS_OPERATOR, val1)
+
+
+STR_String CValue::op2str (VALUE_OPERATOR op)
+{
+ //pre:
+ //ret: the stringrepresentation of operator op
+
+ STR_String opmsg;
+ switch (op) {
+ case VALUE_ADD_OPERATOR:
+ opmsg = " + ";
+ break;
+ case VALUE_SUB_OPERATOR:
+ opmsg = " - ";
+ break;
+ case VALUE_MUL_OPERATOR:
+ opmsg = " * ";
+ break;
+ case VALUE_DIV_OPERATOR:
+ opmsg = " / ";
+ break;
+ case VALUE_NEG_OPERATOR:
+ opmsg = " -";
+ break;
+ case VALUE_POS_OPERATOR:
+ opmsg = " +";
+ break;
+ case VALUE_AND_OPERATOR:
+ opmsg = " & ";
+ break;
+ case VALUE_OR_OPERATOR:
+ opmsg = " | ";
+ break;
+ case VALUE_EQL_OPERATOR:
+ opmsg = " = ";
+ break;
+ case VALUE_NEQ_OPERATOR:
+ opmsg = " != ";
+ break;
+ case VALUE_NOT_OPERATOR:
+ opmsg = " !";
+ break;
+ default:
+ opmsg="Error in Errorhandling routine.";
+ // AfxMessageBox("Invalid operator");
+ break;
+ }
+ return opmsg;
+}
+
+
+
+
+
+//---------------------------------------------------------------------------------------------------------------------
+// Property Management
+//---------------------------------------------------------------------------------------------------------------------
+
+
+
+//
+// Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
+//
+void CValue::SetProperty(const STR_String & name,CValue* ioProperty)
+{
+ // Check if somebody is setting an empty property
+ if (ioProperty==NULL)
+ {
+ trace("Warning:trying to set empty property!");
+ return;
+ }
+
+ // Make sure we have a property array
+ if (m_pNamedPropertyArray == NULL)
+ m_pNamedPropertyArray = new std::map<const 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;//->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<const STR_String,CValue*>::iterator it = (*m_pNamedPropertyArray).find(inName);
+ if (!( it==m_pNamedPropertyArray->end()))
+ {
+ result = (*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;
+}
+
+
+
+//
+// Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
+//
+STR_String CValue::GetPropertyText(const STR_String & inName,const STR_String& deftext)
+{
+ CValue *property = GetProperty(inName);
+ if (property)
+ return property->GetText();
+ else
+ return deftext;//String::sEmpty;
+}
+
+float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
+{
+ CValue *property = GetProperty(inName);
+ if (property)
+ return property->GetNumber();
+ else
+ return 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)
+{
+ // Check if there are properties at all which can be removed
+ if (m_pNamedPropertyArray == NULL)
+ return false;
+
+ // Scan all properties, as soon as we find one with <inName> -> Remove it
+// CValue* val = (*m_pNamedPropertyArray)[inName];
+ if (m_pNamedPropertyArray->erase(inName)) return true;
+
+ return false;
+}
+
+
+
+//
+// Clear all properties
+//
+void CValue::ClearProperties()
+{
+ // Check if we have any properties
+ if (m_pNamedPropertyArray == NULL)
+ return;
+
+ // Remove all properties
+ for ( std::map<const STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
+ !(it == m_pNamedPropertyArray->end());it++)
+ {
+ CValue* tmpval = (*it).second;
+ STR_String name = (*it).first;
+ tmpval->Release();
+ }
+
+ // Delete property array
+ delete m_pNamedPropertyArray;
+ m_pNamedPropertyArray=NULL;
+}
+
+
+
+//
+// Set all properties' modified flag to <inModified>
+//
+void CValue::SetPropertiesModified(bool inModified)
+{
+ int numprops = GetPropertyCount();
+ for (int i=0; i<numprops; i++)
+ GetProperty(i)->SetModified(inModified);
+}
+
+
+
+//
+// Check if any of the properties in this value have been modified
+//
+bool CValue::IsAnyPropertyModified()
+{
+ int numprops = GetPropertyCount();
+ for (int i=0;i<numprops;i++)
+ if (GetProperty(i)->IsModified())
+ return true;
+
+ return false;
+}
+
+
+
+//
+// Get property number <inIndex>
+//
+
+CValue* CValue::GetProperty(int inIndex)
+{
+
+ int count=0;
+ CValue* result = NULL;
+
+ if (m_pNamedPropertyArray)
+ {
+ for ( std::map<const STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
+ !(it == m_pNamedPropertyArray->end());it++)
+ {
+ if (count++==inIndex)
+ {
+ result = (*it).second;
+ break;
+ }
+ }
+
+ }
+ return result;
+}
+
+
+
+//
+// Get the amount of properties assiocated with this value
+//
+int CValue::GetPropertyCount()
+{
+ if (m_pNamedPropertyArray)
+ return m_pNamedPropertyArray->size();
+ else
+ return 0;
+}
+
+
+
+
+
+void CValue::CloneProperties(CValue *replica)
+{
+
+ if (m_pNamedPropertyArray)
+ {
+ replica->m_pNamedPropertyArray=NULL;
+ for ( std::map<const STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
+ !(it == m_pNamedPropertyArray->end());it++)
+ {
+
+ replica->SetProperty((*it).first,(*it).second->GetReplica());
+ }
+ }
+
+
+}
+
+
+
+
+
+
+double* CValue::GetVector3(bool bGetTransformedVec)
+{
+ assertd(false); // don;t get vector from me
+ return m_sZeroVec;//::sZero;
+}
+
+
+
+
+
+
+/*---------------------------------------------------------------------------------------------------------------------
+ Reference Counting
+---------------------------------------------------------------------------------------------------------------------*/
+
+
+
+//
+// Add a reference to this value
+//
+CValue *CValue::AddRef()
+{
+ // Increase global reference count, used to see at the end of the program
+ // if all CValue-derived classes have been dereferenced to 0
+ //debug(gRefCountValue++);
+ m_refcount++;
+ return this;
+}
+
+
+
+//
+// Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
+//
+int CValue::Release()
+{
+ // Decrease global reference count, used to see at the end of the program
+ // if all CValue-derived classes have been dereferenced to 0
+ //debug(gRefCountValue--);
+
+ // Decrease local reference count, if it reaches 0 the object should be freed
+ if (--m_refcount > 0)
+ {
+ // Reference count normal, return new reference count
+ return m_refcount;
+ }
+ else
+ {
+ // Reference count reached 0, delete ourselves and return 0
+// assert(m_refcount==0, "Reference count reached sub-zero, object released too much");
+ delete this;
+ return 0;
+ }
+
+}
+
+
+
+//
+// Disable reference counting for this value
+//
+void CValue::DisableRefCount()
+{
+ assertd(m_refcount == 1);
+ m_refcount--;
+
+ //debug(gRefCountValue--);
+ m_ValFlags.RefCountDisabled=true;
+}
+
+
+
+void CValue::AddDataToReplica(CValue *replica)
+{
+ replica->m_refcount = 1;
+#ifdef _DEBUG
+ //gRefCountValue++;
+#endif
+ replica->m_ValFlags.RefCountDisabled = false;
+
+ replica->ReplicaSetName(GetName());
+
+ //copy all props
+ CloneProperties(replica);
+}
+
+
+
+CValue* CValue::FindIdentifier(const STR_String& identifiername)
+{
+
+ CValue* result = NULL;
+
+ int pos = 0;
+ // if a dot exists, explode the name into pieces to get the subcontext
+ if ((pos=identifiername.Find('.'))>=0)
+ {
+ const STR_String rightstring = identifiername.Right(identifiername.Length() -1 - pos);
+ const STR_String leftstring = identifiername.Left(pos);
+ CValue* tempresult = GetProperty(leftstring);
+ if (tempresult)
+ {
+ result=tempresult->FindIdentifier(rightstring);
+ }
+ } else
+ {
+ result = GetProperty(identifiername);
+ }
+ if (result)
+ return result->AddRef();
+ // warning here !!!
+ result = new CErrorValue(identifiername+" not found");
+ return result;
+}
+
+
+#ifndef NO_EXP_PYTHON_EMBEDDING
+
+
+static PyMethodDef CValueMethods[] =
+{
+ //{ "new", CValue::PyMake , Py_NEWARGS},
+ { NULL,NULL} // Sentinel
+};
+
+
+PyObject* CValue::_getattr(char* attr)
+{
+ CValue* resultattr = FindIdentifier(attr);
+ STR_String text;
+ 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;
+ }
+
+ }
+ }
+ _getattr_up(PyObjectPlus);
+}
+
+CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
+{
+
+ CValue* vallie = NULL;
+
+ PyTypeObject* type = pyobj->ob_type;
+
+ if (type == &PyList_Type)
+ {
+ CListValue* listval = new CListValue();
+ bool error = false;
+
+ int i;
+ int numitems = PyList_Size(pyobj);
+ for (i=0;i<numitems;i++)
+ {
+ PyObject* listitem = PyList_GetItem(pyobj,i);
+ CValue* listitemval = ConvertPythonToValue(listitem);
+ if (listitemval)
+ {
+ listval->Add(listitemval);
+ } else
+ {
+ error = true;
+ }
+ }
+ if (!error)
+ {
+ // jippie! could be converted
+ vallie = listval;
+ } else
+ {
+ // list could not be converted... bad luck
+ listval->Release();
+ }
+
+ } else
+ if (type == &PyFloat_Type)
+ {
+ float fl;
+ PyArg_Parse(pyobj,"f",&fl);
+ vallie = new CFloatValue(fl);
+ } else
+ if (type==&PyInt_Type)
+ {
+ int innie;
+ PyArg_Parse(pyobj,"i",&innie);
+ vallie = new CIntValue(innie);
+ } else
+
+ if (type==&PyString_Type)
+ {
+ vallie = new CStringValue(PyString_AsString(pyobj),"");
+ } else
+ if (type==&CValue::Type || type==&CListValue::Type)
+ {
+ vallie = ((CValue*) pyobj)->AddRef();
+ }
+ return vallie;
+
+}
+int CValue::_setattr(char* attr,PyObject* pyobj)
+{
+
+ if (!pyobj) { // member deletion
+ RemoveProperty(attr);
+ return 0;
+ }
+
+ CValue* vallie = ConvertPythonToValue(pyobj);
+ if (vallie)
+ {
+ CValue* oldprop = GetProperty(attr);
+
+ if (oldprop)
+ {
+ oldprop->SetValue(vallie);
+ } else
+ {
+ SetProperty(attr,vallie->AddRef());
+ }
+ vallie->Release();
+ }
+
+ //PyObjectPlus::_setattr(attr,value);
+ return 0;
+};
+/*
+PyObject* CValue::PyMake(PyObject* ignored,PyObject* args)
+{
+
+ //Py_Try(PyArg_ParseTuple(args,"s",&name));
+ Py_INCREF(Py_None);
+ return Py_None;//new CValue();
+}
+*/
+
+extern "C" {
+ void initCValue(void)
+ {
+ Py_InitModule("CValue",CValueMethods);
+ }
+}
+
+
+
+#endif //NO_EXP_PYTHON_EMBEDDING
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+/* These implementations were moved out of the header */
+
+void CValue::SetOwnerExpression(class CExpression* expr)
+{
+ /* intentionally empty */
+}
+
+void CValue::SetColorOperator(VALUE_OPERATOR op)
+{
+ /* intentionally empty */
+}
+void CValue::SetValue(CValue* newval)
+{
+ // no one should get here
+ assertd(newval->GetNumber() == 10121969);
+}
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+