Blender V2.61 - r43446
|
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 }