Blender  V2.59
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         CValue * self = static_cast<CValue *> (self_v);
00535         return PyUnicode_FromString(self->GetName());
00536 }
00537 
00538 CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix)
00539 {
00540 
00541         CValue* vallie = NULL;
00542         /* refcounting is broking here! - this crashes anyway, just store a python list for KX_GameObject */
00543 #if 0
00544         if (PyList_Check(pyobj))
00545         {
00546                 CListValue* listval = new CListValue();
00547                 bool error = false;
00548 
00549                 Py_ssize_t i;
00550                 Py_ssize_t numitems = PyList_Size(pyobj);
00551                 for (i=0;i<numitems;i++)
00552                 {
00553                         PyObject* listitem = PyList_GetItem(pyobj,i); /* borrowed ref */
00554                         CValue* listitemval = ConvertPythonToValue(listitem, error_prefix);
00555                         if (listitemval)
00556                         {
00557                                 listval->Add(listitemval);
00558                         } else
00559                         {
00560                                 error = true;
00561                         }
00562                 }
00563                 if (!error)
00564                 {
00565                         // jippie! could be converted
00566                         vallie = listval;
00567                 } else
00568                 {
00569                         // list could not be converted... bad luck
00570                         listval->Release();
00571                 }
00572 
00573         } else
00574 #endif
00575         if (PyFloat_Check(pyobj))
00576         {
00577                 vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) );
00578         } else
00579         if (PyLong_Check(pyobj))
00580         {
00581                 vallie = new CIntValue( (cInt)PyLong_AsLongLong(pyobj) );
00582         } else
00583         if (PyUnicode_Check(pyobj))
00584         {
00585                 vallie = new CStringValue(_PyUnicode_AsString(pyobj),"");
00586         } else
00587         if (PyObject_TypeCheck(pyobj, &CValue::Type)) /* Note, dont let these get assigned to GameObject props, must check elsewhere */
00588         {
00589                 vallie = (static_cast<CValue *>(BGE_PROXY_REF(pyobj)))->AddRef();
00590         } else
00591         {
00592                 /* return an error value from the caller */
00593                 PyErr_Format(PyExc_TypeError, "%scould convert python value to a game engine property", error_prefix);
00594         }
00595         return vallie;
00596 
00597 }
00598 
00599 PyObject*       CValue::ConvertKeysToPython( void )
00600 {
00601         PyObject *pylist = PyList_New( 0 );
00602         PyObject *pystr;
00603         
00604         if (m_pNamedPropertyArray)
00605         {
00606                 std::map<STR_String,CValue*>::iterator it;
00607                 for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
00608                 {
00609                         pystr = PyUnicode_FromString( (*it).first );
00610                         PyList_Append(pylist, pystr);
00611                         Py_DECREF( pystr );
00612                 }
00613         }
00614         return pylist;
00615 }
00616 
00617 #endif // WITH_PYTHON
00618 
00619 
00622 /* These implementations were moved out of the header */
00623 
00624 void CValue::SetOwnerExpression(class CExpression* expr)
00625 {
00626         /* intentionally empty */
00627 }
00628 
00629 void CValue::SetColorOperator(VALUE_OPERATOR op)
00630 {
00631         /* intentionally empty */
00632 }
00633 void CValue::SetValue(CValue* newval)
00634 { 
00635         // no one should get here
00636         assertd(newval->GetNumber() == 10121969);       
00637 }