diff options
author | Hans Lambermont <hans@lambermont.dyndns.org> | 2002-10-12 15:37:38 +0400 |
---|---|---|
committer | Hans Lambermont <hans@lambermont.dyndns.org> | 2002-10-12 15:37:38 +0400 |
commit | 12315f4d0e0ae993805f141f64cb8c73c5297311 (patch) | |
tree | 59b45827cd8293cfb727758989c7a74b40183974 /source/gameengine/Expressions/Value.cpp |
Initial revisionv2.25
Diffstat (limited to 'source/gameengine/Expressions/Value.cpp')
-rw-r--r-- | source/gameengine/Expressions/Value.cpp | 767 |
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); +} +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + |