Blender V2.61 - r43446

Value.cpp

Go to the documentation of this file.
00001 
00004 // Value.cpp: implementation of the CValue class.
00005 // developed at Eindhoven University of Technology, 1997
00006 // by the OOPS team
00008 /*
00009  * Copyright (c) 1996-2000 Erwin Coumans <coockie@acm.org>
00010  *
00011  * Permission to use, copy, modify, distribute and sell this software
00012  * and its documentation for any purpose is hereby granted without fee,
00013  * provided that the above copyright notice appear in all copies and
00014  * that both that copyright notice and this permission notice appear
00015  * in supporting documentation.  Erwin Coumans makes no
00016  * representations about the suitability of this software for any
00017  * purpose.  It is provided "as is" without express or implied warranty.
00018  *
00019  */
00020 #include "Value.h"
00021 #include "FloatValue.h"
00022 #include "IntValue.h"
00023 #include "VectorValue.h"
00024 #include "VoidValue.h"
00025 #include "StringValue.h"
00026 #include "ErrorValue.h"
00027 #include "ListValue.h"
00028 
00030 // Construction/Destruction
00032 
00033 double CValue::m_sZeroVec[3] = {0.0,0.0,0.0};
00034 
00035 #ifdef WITH_PYTHON
00036 
00037 PyTypeObject CValue::Type = {
00038     PyVarObject_HEAD_INIT(NULL, 0)
00039     "CValue",
00040     sizeof(PyObjectPlus_Proxy),
00041     0,
00042     py_base_dealloc,
00043     0,
00044     0,
00045     0,
00046     0,
00047     py_base_repr,
00048     0,
00049     0,0,0,0,0,
00050     NULL,
00051     NULL,
00052     0,
00053     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
00054     0,0,0,0,0,0,0,
00055     Methods,
00056     0,
00057     0,
00058     &PyObjectPlus::Type,
00059     0,0,0,0,0,0,
00060     py_base_new
00061 };
00062 
00063 PyMethodDef CValue::Methods[] = {
00064     {NULL,NULL} //Sentinel
00065 };
00066 #endif // WITH_PYTHON
00067 
00068 
00069 /*#define CVALUE_DEBUG*/
00070 #ifdef CVALUE_DEBUG
00071 int gRefCount;
00072 struct SmartCValueRef 
00073 {
00074     CValue *m_ref;
00075     int m_count;
00076     SmartCValueRef(CValue *ref)
00077     {
00078         m_ref = ref;
00079         m_count = gRefCount++;
00080     }
00081 };
00082 
00083 #include <vector>
00084 
00085 std::vector<SmartCValueRef> gRefList;
00086 #endif
00087 
00088 #ifdef _DEBUG
00089 //int gRefCountValue;
00090 #endif
00091 
00092 CValue::CValue()
00093         : PyObjectPlus(),
00094     
00095 m_pNamedPropertyArray(NULL),
00096 m_refcount(1)
00097 /*
00098 pre: false
00099 effect: constucts a CValue
00100 */
00101 {
00102     //debug(gRefCountValue++)   // debugging
00103 #ifdef _DEBUG
00104     //gRefCountValue++;
00105 #ifdef CVALUE_DEBUG
00106     gRefList.push_back(SmartCValueRef(this));
00107 #endif
00108 #endif
00109 }
00110 
00111 
00112 
00113 CValue::~CValue()
00114 /*
00115 pre:
00116 effect: deletes the object
00117 */
00118 {
00119     ClearProperties();
00120 
00121     assertd (m_refcount==0);
00122 #ifdef CVALUE_DEBUG
00123     std::vector<SmartCValueRef>::iterator it;
00124     for (it=gRefList.begin(); it!=gRefList.end(); it++)
00125     {
00126         if (it->m_ref == this)
00127         {
00128             *it = gRefList.back();
00129             gRefList.pop_back();
00130             break;
00131         }
00132     }
00133 #endif
00134 }
00135 
00136 
00137 
00138 
00139 #define VALUE_SUB(val1, val2) (val1)->Calc(VALUE_SUB_OPERATOR, val2)
00140 #define VALUE_MUL(val1, val2) (val1)->Calc(VALUE_MUL_OPERATOR, val2)
00141 #define VALUE_DIV(val1, val2) (val1)->Calc(VALUE_DIV_OPERATOR, val2)
00142 #define VALUE_NEG(val1)       (val1)->Calc(VALUE_NEG_OPERATOR, val1)
00143 #define VALUE_POS(val1)       (val1)->Calc(VALUE_POS_OPERATOR, val1)
00144 
00145 
00146 STR_String CValue::op2str (VALUE_OPERATOR op)
00147 {
00148     //pre:
00149     //ret: the stringrepresentation of operator op
00150     
00151     STR_String opmsg;
00152     switch (op) {
00153     case VALUE_MOD_OPERATOR:
00154         opmsg = " % ";
00155         break;
00156     case VALUE_ADD_OPERATOR:
00157         opmsg = " + ";
00158         break;
00159     case VALUE_SUB_OPERATOR:
00160         opmsg = " - ";
00161         break;
00162     case VALUE_MUL_OPERATOR:
00163         opmsg = " * ";
00164         break;
00165     case VALUE_DIV_OPERATOR:
00166         opmsg = " / ";
00167         break;
00168     case VALUE_NEG_OPERATOR:
00169         opmsg = " -";
00170         break;
00171     case VALUE_POS_OPERATOR:
00172         opmsg = " +";
00173         break;
00174     case VALUE_AND_OPERATOR:
00175         opmsg = " & ";
00176         break;
00177     case VALUE_OR_OPERATOR:
00178         opmsg = " | ";
00179         break;
00180     case VALUE_EQL_OPERATOR:
00181         opmsg = " = ";
00182         break;
00183     case VALUE_NEQ_OPERATOR:
00184         opmsg = " != ";
00185         break;
00186     case VALUE_NOT_OPERATOR:
00187         opmsg = " !";
00188         break;
00189     default:
00190         opmsg="Error in Errorhandling routine.";
00191         //      AfxMessageBox("Invalid operator");
00192         break;
00193     }
00194     return opmsg;
00195 }
00196 
00197 
00198 
00199 
00200 
00201 //---------------------------------------------------------------------------------------------------------------------
00202 //  Property Management
00203 //---------------------------------------------------------------------------------------------------------------------
00204 
00205 
00206 
00207 //
00208 // Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
00209 //
00210 void CValue::SetProperty(const STR_String & name,CValue* ioProperty)
00211 {
00212     if (ioProperty==NULL)
00213     {   // Check if somebody is setting an empty property
00214         trace("Warning:trying to set empty property!");
00215         return;
00216     }
00217 
00218     if (m_pNamedPropertyArray)
00219     {   // Try to replace property (if so -> exit as soon as we replaced it)
00220         CValue* oldval = (*m_pNamedPropertyArray)[name];
00221         if (oldval)
00222             oldval->Release();
00223     }
00224     else { // Make sure we have a property array
00225         m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
00226     }
00227     
00228     // Add property at end of array
00229     (*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
00230 }
00231 
00232 void CValue::SetProperty(const char* name,CValue* ioProperty)
00233 {
00234     if (ioProperty==NULL)
00235     {   // Check if somebody is setting an empty property
00236         trace("Warning:trying to set empty property!");
00237         return;
00238     }
00239 
00240     if (m_pNamedPropertyArray)
00241     {   // Try to replace property (if so -> exit as soon as we replaced it)
00242         CValue* oldval = (*m_pNamedPropertyArray)[name];
00243         if (oldval)
00244             oldval->Release();
00245     }
00246     else { // Make sure we have a property array
00247         m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
00248     }
00249     
00250     // Add property at end of array
00251     (*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
00252 }
00253 
00254 //
00255 // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
00256 //
00257 CValue* CValue::GetProperty(const STR_String & inName)
00258 {
00259     if (m_pNamedPropertyArray) {
00260         std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
00261         if (it != m_pNamedPropertyArray->end())
00262             return (*it).second;
00263     }
00264     return NULL;
00265 }
00266 
00267 CValue* CValue::GetProperty(const char *inName)
00268 {
00269     if (m_pNamedPropertyArray) {
00270         std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
00271         if (it != m_pNamedPropertyArray->end())
00272             return (*it).second;
00273     }
00274     return NULL;
00275 }
00276 
00277 //
00278 // Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
00279 //
00280 const STR_String& CValue::GetPropertyText(const STR_String & inName)
00281 {
00282     const static STR_String sEmpty("");
00283 
00284     CValue *property = GetProperty(inName);
00285     if (property)
00286         return property->GetText();
00287     else
00288         return sEmpty;
00289 }
00290 
00291 float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
00292 {
00293     CValue *property = GetProperty(inName);
00294     if (property)
00295         return property->GetNumber(); 
00296     else
00297         return defnumber;
00298 }
00299 
00300 
00301 
00302 //
00303 // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
00304 //
00305 bool CValue::RemoveProperty(const char *inName)
00306 {
00307     // Check if there are properties at all which can be removed
00308     if (m_pNamedPropertyArray)
00309     {
00310         std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
00311         if (it != m_pNamedPropertyArray->end())
00312         {
00313             ((*it).second)->Release();
00314             m_pNamedPropertyArray->erase(it);
00315             return true;
00316         }
00317     }
00318     
00319     return false;
00320 }
00321 
00322 //
00323 // Get Property Names
00324 //
00325 vector<STR_String> CValue::GetPropertyNames()
00326 {
00327     vector<STR_String> result;
00328     if(!m_pNamedPropertyArray) return result;
00329     result.reserve(m_pNamedPropertyArray->size());
00330     
00331     std::map<STR_String,CValue*>::iterator it;
00332     for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
00333     {
00334         result.push_back((*it).first);
00335     }
00336     return result;
00337 }
00338 
00339 //
00340 // Clear all properties
00341 //
00342 void CValue::ClearProperties()
00343 {       
00344     // Check if we have any properties
00345     if (m_pNamedPropertyArray == NULL)
00346         return;
00347 
00348     // Remove all properties
00349     std::map<STR_String,CValue*>::iterator it;
00350     for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
00351     {
00352         CValue* tmpval = (*it).second;
00353         //STR_String name = (*it).first;
00354         tmpval->Release();
00355     }
00356 
00357     // Delete property array
00358     delete m_pNamedPropertyArray;
00359     m_pNamedPropertyArray=NULL;
00360 }
00361 
00362 
00363 
00364 //
00365 // Set all properties' modified flag to <inModified>
00366 //
00367 void CValue::SetPropertiesModified(bool inModified)
00368 {
00369     if(!m_pNamedPropertyArray) return;
00370     std::map<STR_String,CValue*>::iterator it;
00371     
00372     for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
00373         ((*it).second)->SetModified(inModified);
00374 }
00375 
00376 
00377 
00378 //
00379 // Check if any of the properties in this value have been modified
00380 //
00381 bool CValue::IsAnyPropertyModified()
00382 {
00383     if(!m_pNamedPropertyArray) return false;
00384     std::map<STR_String,CValue*>::iterator it;
00385     
00386     for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
00387         if (((*it).second)->IsModified())
00388             return true;
00389     
00390     return false;
00391 }
00392 
00393 
00394 
00395 //
00396 // Get property number <inIndex>
00397 //
00398 CValue* CValue::GetProperty(int inIndex)
00399 {
00400 
00401     int count=0;
00402     CValue* result = NULL;
00403 
00404     if (m_pNamedPropertyArray)
00405     {
00406         std::map<STR_String,CValue*>::iterator it;
00407         for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
00408         {
00409             if (count++==inIndex)
00410             {
00411                 result = (*it).second;
00412                 break;
00413             }
00414         }
00415 
00416     }
00417     return result;
00418 }
00419 
00420 
00421 
00422 //
00423 // Get the amount of properties assiocated with this value
00424 //
00425 int CValue::GetPropertyCount()
00426 {
00427     if (m_pNamedPropertyArray)
00428         return m_pNamedPropertyArray->size();
00429     else
00430         return 0;
00431 }
00432 
00433 
00434 double*     CValue::GetVector3(bool bGetTransformedVec)
00435 {
00436     assertd(false); // don;t get vector from me
00437     return m_sZeroVec;//::sZero;
00438 }
00439 
00440 
00441 /*---------------------------------------------------------------------------------------------------------------------
00442     Reference Counting
00443 ---------------------------------------------------------------------------------------------------------------------*/
00444 
00445 
00446 
00447 //
00448 // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
00449 //
00450 
00451 
00452 
00453 //
00454 // Disable reference counting for this value
00455 //
00456 void CValue::DisableRefCount()
00457 {
00458     assertd(m_refcount == 1);
00459     m_refcount--;
00460 
00461     //debug(gRefCountValue--);
00462 #ifdef _DEBUG
00463     //gRefCountValue--;
00464 #endif
00465     m_ValFlags.RefCountDisabled=true;
00466 }
00467 
00468 
00469 
00470 void CValue::ProcessReplica() /* was AddDataToReplica in 2.48 */
00471 {
00472     m_refcount = 1;
00473     
00474 #ifdef _DEBUG
00475     //gRefCountValue++;
00476 #endif
00477     PyObjectPlus::ProcessReplica();
00478 
00479     m_ValFlags.RefCountDisabled = false;
00480 
00481     /* copy all props */
00482     if (m_pNamedPropertyArray)
00483     {
00484         std::map<STR_String,CValue*> *pOldArray = m_pNamedPropertyArray;
00485         m_pNamedPropertyArray=NULL;
00486         std::map<STR_String,CValue*>::iterator it;
00487         for (it= pOldArray->begin(); (it != pOldArray->end()); it++)
00488         {
00489             CValue *val = (*it).second->GetReplica();
00490             SetProperty((*it).first,val);
00491             val->Release();
00492         }
00493     }
00494 }
00495 
00496 CValue* CValue::FindIdentifier(const STR_String& identifiername)
00497 {
00498 
00499     CValue* result = NULL;
00500 
00501     int pos = 0;
00502     // if a dot exists, explode the name into pieces to get the subcontext
00503     if ((pos=identifiername.Find('.'))>=0)
00504     {
00505         const STR_String rightstring = identifiername.Right(identifiername.Length() -1 - pos);
00506         const STR_String leftstring = identifiername.Left(pos);
00507         CValue* tempresult = GetProperty(leftstring);
00508         if (tempresult)
00509         {
00510             result=tempresult->FindIdentifier(rightstring);
00511         } 
00512     } else
00513     {
00514         result = GetProperty(identifiername);
00515         if (result)
00516             return result->AddRef();
00517     }
00518     if (!result)
00519     {
00520         // warning here !!!
00521         result = new CErrorValue(identifiername+" not found");
00522     }
00523     return result;
00524 }
00525 
00526 #ifdef WITH_PYTHON
00527 
00528 PyAttributeDef CValue::Attributes[] = {
00529     KX_PYATTRIBUTE_RO_FUNCTION("name",  CValue, pyattr_get_name),
00530     { NULL }    //Sentinel
00531 };
00532 
00533 PyObject * CValue::pyattr_get_name(void * self_v, const KX_PYATTRIBUTE_DEF * attrdef)
00534 {
00535     CValue * self = static_cast<CValue *> (self_v);
00536     return PyUnicode_From_STR_String(self->GetName());
00537 }
00538 
00539 CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix)
00540 {
00541 
00542     CValue* vallie = NULL;
00543     /* refcounting is broking here! - this crashes anyway, just store a python list for KX_GameObject */
00544 #if 0
00545     if (PyList_Check(pyobj))
00546     {
00547         CListValue* listval = new CListValue();
00548         bool error = false;
00549 
00550         Py_ssize_t i;
00551         Py_ssize_t numitems = PyList_GET_SIZE(pyobj);
00552         for (i=0;i<numitems;i++)
00553         {
00554             PyObject* listitem = PyList_GetItem(pyobj,i); /* borrowed ref */
00555             CValue* listitemval = ConvertPythonToValue(listitem, error_prefix);
00556             if (listitemval)
00557             {
00558                 listval->Add(listitemval);
00559             } else
00560             {
00561                 error = true;
00562             }
00563         }
00564         if (!error)
00565         {
00566             // jippie! could be converted
00567             vallie = listval;
00568         } else
00569         {
00570             // list could not be converted... bad luck
00571             listval->Release();
00572         }
00573 
00574     } else
00575 #endif
00576     if (PyFloat_Check(pyobj))
00577     {
00578         vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) );
00579     } else
00580     if (PyLong_Check(pyobj))
00581     {
00582         vallie = new CIntValue( (cInt)PyLong_AsLongLong(pyobj) );
00583     } else
00584     if (PyUnicode_Check(pyobj))
00585     {
00586         vallie = new CStringValue(_PyUnicode_AsString(pyobj),"");
00587     } else
00588     if (PyObject_TypeCheck(pyobj, &CValue::Type)) /* Note, dont let these get assigned to GameObject props, must check elsewhere */
00589     {
00590         vallie = (static_cast<CValue *>(BGE_PROXY_REF(pyobj)))->AddRef();
00591     } else
00592     {
00593         /* return an error value from the caller */
00594         PyErr_Format(PyExc_TypeError, "%scould convert python value to a game engine property", error_prefix);
00595     }
00596     return vallie;
00597 
00598 }
00599 
00600 PyObject* CValue::ConvertKeysToPython(void)
00601 {
00602     if (m_pNamedPropertyArray)
00603     {
00604         PyObject *pylist= PyList_New(m_pNamedPropertyArray->size());
00605         Py_ssize_t i= 0;
00606 
00607         std::map<STR_String,CValue*>::iterator it;
00608         for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
00609         {
00610             PyList_SET_ITEM(pylist, i++, PyUnicode_From_STR_String((*it).first));
00611         }
00612 
00613         return pylist;
00614     }
00615     else {
00616         return PyList_New(0);
00617     }
00618 }
00619 
00620 #endif // WITH_PYTHON
00621 
00622 
00625 /* These implementations were moved out of the header */
00626 
00627 void CValue::SetOwnerExpression(class CExpression* expr)
00628 {
00629     /* intentionally empty */
00630 }
00631 
00632 void CValue::SetColorOperator(VALUE_OPERATOR op)
00633 {
00634     /* intentionally empty */
00635 }
00636 void CValue::SetValue(CValue* newval)
00637 { 
00638     // no one should get here
00639     assertd(newval->GetNumber() == 10121969);   
00640 }