svn merge -r 21041:21301 https://svn.blender.org/svnroot/bf-blender/branches/blender2...
[blender.git] / source / gameengine / Expressions / Value.cpp
1 // Value.cpp: implementation of the CValue class.
2 // developed at Eindhoven University of Technology, 1997
3 // by the OOPS team
4 //////////////////////////////////////////////////////////////////////
5 /*
6  * Copyright (c) 1996-2000 Erwin Coumans <coockie@acm.org>
7  *
8  * Permission to use, copy, modify, distribute and sell this software
9  * and its documentation for any purpose is hereby granted without fee,
10  * provided that the above copyright notice appear in all copies and
11  * that both that copyright notice and this permission notice appear
12  * in supporting documentation.  Erwin Coumans makes no
13  * representations about the suitability of this software for any
14  * purpose.  It is provided "as is" without express or implied warranty.
15  *
16  */
17 #include "Value.h"
18 #include "FloatValue.h"
19 #include "IntValue.h"
20 #include "VectorValue.h"
21 #include "VoidValue.h"
22 #include "StringValue.h"
23 #include "ErrorValue.h"
24 #include "ListValue.h"
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 //////////////////////////////////////////////////////////////////////
31 // Construction/Destruction
32 //////////////////////////////////////////////////////////////////////
33
34 double CValue::m_sZeroVec[3] = {0.0,0.0,0.0};
35
36 #ifndef NO_EXP_PYTHON_EMBEDDING
37
38 PyTypeObject CValue::Type = {
39 #if (PY_VERSION_HEX >= 0x02060000)
40         PyVarObject_HEAD_INIT(NULL, 0)
41 #else
42         /* python 2.5 and below */
43         PyObject_HEAD_INIT( NULL )  /* required py macro */
44         0,                          /* ob_size */
45 #endif
46         "CValue",
47         sizeof(PyObjectPlus_Proxy),
48         0,
49         py_base_dealloc,
50         0,
51         0,
52         0,
53         0,
54         py_base_repr,
55         0,
56         0,0,0,0,0,
57         NULL,
58         NULL,
59         0,
60         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
61         0,0,0,0,0,0,0,
62         Methods,
63         0,
64         0,
65         &PyObjectPlus::Type,
66         0,0,0,0,0,0,
67         py_base_new
68 };
69
70 PyMethodDef CValue::Methods[] = {
71         { "getName", (PyCFunction) CValue::sPyGetName, METH_NOARGS},
72         {NULL,NULL} //Sentinel
73 };
74
75 PyObject* CValue::PyGetName()
76 {
77         ShowDeprecationWarning("getName()", "the name property");
78         
79         return PyUnicode_FromString(this->GetName());
80 }
81
82 /*#define CVALUE_DEBUG*/
83 #ifdef CVALUE_DEBUG
84 int gRefCount;
85 struct SmartCValueRef 
86 {
87         CValue *m_ref;
88         int m_count;
89         SmartCValueRef(CValue *ref)
90         {
91                 m_ref = ref;
92                 m_count = gRefCount++;
93         }
94 };
95
96 #include <vector>
97
98 std::vector<SmartCValueRef> gRefList;
99 #endif
100
101 #ifdef _DEBUG
102 //int gRefCountValue;
103 #endif
104
105 CValue::CValue()
106                 : PyObjectPlus(),
107 #else
108 CValue::CValue()
109
110 #endif //NO_EXP_PYTHON_EMBEDDING
111         
112 m_pNamedPropertyArray(NULL),
113 m_refcount(1)
114 /*
115 pre: false
116 effect: constucts a CValue
117 */
118 {
119         //debug(gRefCountValue++)       // debugging
120 #ifdef _DEBUG
121         //gRefCountValue++;
122 #ifdef CVALUE_DEBUG
123         gRefList.push_back(SmartCValueRef(this));
124 #endif
125 #endif
126 }
127
128
129
130 CValue::~CValue()
131 /*
132 pre:
133 effect: deletes the object
134 */
135 {
136         ClearProperties();
137
138         assertd (m_refcount==0);
139 #ifdef CVALUE_DEBUG
140         std::vector<SmartCValueRef>::iterator it;
141         for (it=gRefList.begin(); it!=gRefList.end(); it++)
142         {
143                 if (it->m_ref == this)
144                 {
145                         *it = gRefList.back();
146                         gRefList.pop_back();
147                         break;
148                 }
149         }
150 #endif
151 }
152
153
154
155
156 #define VALUE_SUB(val1, val2) (val1)->Calc(VALUE_SUB_OPERATOR, val2)
157 #define VALUE_MUL(val1, val2) (val1)->Calc(VALUE_MUL_OPERATOR, val2)
158 #define VALUE_DIV(val1, val2) (val1)->Calc(VALUE_DIV_OPERATOR, val2)
159 #define VALUE_NEG(val1)       (val1)->Calc(VALUE_NEG_OPERATOR, val1)
160 #define VALUE_POS(val1)       (val1)->Calc(VALUE_POS_OPERATOR, val1)
161
162
163 STR_String CValue::op2str (VALUE_OPERATOR op)
164 {
165         //pre:
166         //ret: the stringrepresentation of operator op
167         
168         STR_String opmsg;
169         switch (op) {
170         case VALUE_MOD_OPERATOR:
171                 opmsg = " % ";
172                 break;
173         case VALUE_ADD_OPERATOR:
174                 opmsg = " + ";
175                 break;
176         case VALUE_SUB_OPERATOR:
177                 opmsg = " - ";
178                 break;
179         case VALUE_MUL_OPERATOR:
180                 opmsg = " * ";
181                 break;
182         case VALUE_DIV_OPERATOR:
183                 opmsg = " / ";
184                 break;
185         case VALUE_NEG_OPERATOR:
186                 opmsg = " -";
187                 break;
188         case VALUE_POS_OPERATOR:
189                 opmsg = " +";
190                 break;
191         case VALUE_AND_OPERATOR:
192                 opmsg = " & ";
193                 break;
194         case VALUE_OR_OPERATOR:
195                 opmsg = " | ";
196                 break;
197         case VALUE_EQL_OPERATOR:
198                 opmsg = " = ";
199                 break;
200         case VALUE_NEQ_OPERATOR:
201                 opmsg = " != ";
202                 break;
203         case VALUE_NOT_OPERATOR:
204                 opmsg = " !";
205                 break;
206         default:
207                 opmsg="Error in Errorhandling routine.";
208                 //              AfxMessageBox("Invalid operator");
209                 break;
210         }
211         return opmsg;
212 }
213
214
215
216
217
218 //---------------------------------------------------------------------------------------------------------------------
219 //      Property Management
220 //---------------------------------------------------------------------------------------------------------------------
221
222
223
224 //
225 // Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
226 //
227 void CValue::SetProperty(const STR_String & name,CValue* ioProperty)
228 {
229         if (ioProperty==NULL)
230         {       // Check if somebody is setting an empty property
231                 trace("Warning:trying to set empty property!");
232                 return;
233         }
234
235         if (m_pNamedPropertyArray)
236         {       // Try to replace property (if so -> exit as soon as we replaced it)
237                 CValue* oldval = (*m_pNamedPropertyArray)[name];
238                 if (oldval)
239                         oldval->Release();
240         }
241         else { // Make sure we have a property array
242                 m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
243         }
244         
245         // Add property at end of array
246         (*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
247 }
248
249 void CValue::SetProperty(const char* name,CValue* ioProperty)
250 {
251         if (ioProperty==NULL)
252         {       // Check if somebody is setting an empty property
253                 trace("Warning:trying to set empty property!");
254                 return;
255         }
256
257         if (m_pNamedPropertyArray)
258         {       // Try to replace property (if so -> exit as soon as we replaced it)
259                 CValue* oldval = (*m_pNamedPropertyArray)[name];
260                 if (oldval)
261                         oldval->Release();
262         }
263         else { // Make sure we have a property array
264                 m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
265         }
266         
267         // Add property at end of array
268         (*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
269 }
270
271 //
272 // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
273 //
274 CValue* CValue::GetProperty(const STR_String & inName)
275 {
276         if (m_pNamedPropertyArray) {
277                 std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
278                 if (it != m_pNamedPropertyArray->end())
279                         return (*it).second;
280         }
281         return NULL;
282 }
283
284 CValue* CValue::GetProperty(const char *inName)
285 {
286         if (m_pNamedPropertyArray) {
287                 std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
288                 if (it != m_pNamedPropertyArray->end())
289                         return (*it).second;
290         }
291         return NULL;
292 }
293
294 //
295 // Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
296 //
297 const STR_String& CValue::GetPropertyText(const STR_String & inName)
298 {
299         const static STR_String sEmpty("");
300
301         CValue *property = GetProperty(inName);
302         if (property)
303                 return property->GetText();
304         else
305                 return sEmpty;
306 }
307
308 float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
309 {
310         CValue *property = GetProperty(inName);
311         if (property)
312                 return property->GetNumber(); 
313         else
314                 return defnumber;
315 }
316
317
318
319 //
320 // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
321 //
322 bool CValue::RemoveProperty(const char *inName)
323 {
324         // Check if there are properties at all which can be removed
325         if (m_pNamedPropertyArray)
326         {
327                 std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
328                 if (it != m_pNamedPropertyArray->end())
329                 {
330                         ((*it).second)->Release();
331                         m_pNamedPropertyArray->erase(it);
332                         return true;
333                 }
334         }
335         
336         return false;
337 }
338
339 //
340 // Get Property Names
341 //
342 vector<STR_String> CValue::GetPropertyNames()
343 {
344         vector<STR_String> result;
345         if(!m_pNamedPropertyArray) return result;
346         result.reserve(m_pNamedPropertyArray->size());
347         
348         std::map<STR_String,CValue*>::iterator it;
349         for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
350         {
351                 result.push_back((*it).first);
352         }
353         return result;
354 }
355
356 //
357 // Clear all properties
358 //
359 void CValue::ClearProperties()
360 {               
361         // Check if we have any properties
362         if (m_pNamedPropertyArray == NULL)
363                 return;
364
365         // Remove all properties
366         std::map<STR_String,CValue*>::iterator it;
367         for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
368         {
369                 CValue* tmpval = (*it).second;
370                 //STR_String name = (*it).first;
371                 tmpval->Release();
372         }
373
374         // Delete property array
375         delete m_pNamedPropertyArray;
376         m_pNamedPropertyArray=NULL;
377 }
378
379
380
381 //
382 // Set all properties' modified flag to <inModified>
383 //
384 void CValue::SetPropertiesModified(bool inModified)
385 {
386         if(!m_pNamedPropertyArray) return;
387         std::map<STR_String,CValue*>::iterator it;
388         
389         for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
390                 ((*it).second)->SetModified(inModified);
391 }
392
393
394
395 //
396 // Check if any of the properties in this value have been modified
397 //
398 bool CValue::IsAnyPropertyModified()
399 {
400         if(!m_pNamedPropertyArray) return false;
401         std::map<STR_String,CValue*>::iterator it;
402         
403         for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
404                 if (((*it).second)->IsModified())
405                         return true;
406         
407         return false;
408 }
409
410
411
412 //
413 // Get property number <inIndex>
414 //
415 CValue* CValue::GetProperty(int inIndex)
416 {
417
418         int count=0;
419         CValue* result = NULL;
420
421         if (m_pNamedPropertyArray)
422         {
423                 std::map<STR_String,CValue*>::iterator it;
424                 for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
425                 {
426                         if (count++==inIndex)
427                         {
428                                 result = (*it).second;
429                                 break;
430                         }
431                 }
432
433         }
434         return result;
435 }
436
437
438
439 //
440 // Get the amount of properties assiocated with this value
441 //
442 int CValue::GetPropertyCount()
443 {
444         if (m_pNamedPropertyArray)
445                 return m_pNamedPropertyArray->size();
446         else
447                 return 0;
448 }
449
450
451 double*         CValue::GetVector3(bool bGetTransformedVec)
452 {
453         assertd(false); // don;t get vector from me
454         return m_sZeroVec;//::sZero;
455 }
456
457
458 /*---------------------------------------------------------------------------------------------------------------------
459         Reference Counting
460 ---------------------------------------------------------------------------------------------------------------------*/
461
462
463
464 //
465 // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
466 //
467
468
469
470 //
471 // Disable reference counting for this value
472 //
473 void CValue::DisableRefCount()
474 {
475         assertd(m_refcount == 1);
476         m_refcount--;
477
478         //debug(gRefCountValue--);
479 #ifdef _DEBUG
480         //gRefCountValue--;
481 #endif
482         m_ValFlags.RefCountDisabled=true;
483 }
484
485
486
487 void CValue::ProcessReplica() /* was AddDataToReplica in 2.48 */
488 {
489         m_refcount = 1;
490         
491 #ifdef _DEBUG
492         //gRefCountValue++;
493 #endif
494         PyObjectPlus::ProcessReplica();
495
496         m_ValFlags.RefCountDisabled = false;
497
498         /* copy all props */
499         if (m_pNamedPropertyArray)
500         {
501                 std::map<STR_String,CValue*> *pOldArray = m_pNamedPropertyArray;
502                 m_pNamedPropertyArray=NULL;
503                 std::map<STR_String,CValue*>::iterator it;
504                 for (it= pOldArray->begin(); (it != pOldArray->end()); it++)
505                 {
506                         CValue *val = (*it).second->GetReplica();
507                         SetProperty((*it).first,val);
508                         val->Release();
509                 }
510         }
511 }
512
513 CValue* CValue::FindIdentifier(const STR_String& identifiername)
514 {
515
516         CValue* result = NULL;
517
518         int pos = 0;
519         // if a dot exists, explode the name into pieces to get the subcontext
520         if ((pos=identifiername.Find('.'))>=0)
521         {
522                 const STR_String rightstring = identifiername.Right(identifiername.Length() -1 - pos);
523                 const STR_String leftstring = identifiername.Left(pos);
524                 CValue* tempresult = GetProperty(leftstring);
525                 if (tempresult)
526                 {
527                         result=tempresult->FindIdentifier(rightstring);
528                 } 
529         } else
530         {
531                 result = GetProperty(identifiername);
532                 if (result)
533                         return result->AddRef();
534         }
535         if (!result)
536         {
537                 // warning here !!!
538                 result = new CErrorValue(identifiername+" not found");
539         }
540         return result;
541 }
542
543
544 #ifndef NO_EXP_PYTHON_EMBEDDING
545
546
547 static PyMethodDef      CValueMethods[] = 
548 {
549         //{ "new", CValue::PyMake , METH_VARARGS},
550         { NULL,NULL}    // Sentinel
551 };
552
553 PyAttributeDef CValue::Attributes[] = {
554         KX_PYATTRIBUTE_RO_FUNCTION("name",      CValue, pyattr_get_name),
555         { NULL }        //Sentinel
556 };
557
558 PyObject * CValue::pyattr_get_name(void * self_v, const KX_PYATTRIBUTE_DEF * attrdef) {
559         CValue * self = static_cast<CValue *> (self_v);
560         return PyUnicode_FromString(self->GetName());
561 }
562
563 CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix)
564 {
565
566         CValue* vallie = NULL;
567         /* refcounting is broking here! - this crashes anyway, just store a python list for KX_GameObject */
568 #if 0
569         if (PyList_Check(pyobj))
570         {
571                 CListValue* listval = new CListValue();
572                 bool error = false;
573
574                 int i;
575                 int numitems = PyList_Size(pyobj);
576                 for (i=0;i<numitems;i++)
577                 {
578                         PyObject* listitem = PyList_GetItem(pyobj,i); /* borrowed ref */
579                         CValue* listitemval = ConvertPythonToValue(listitem, error_prefix);
580                         if (listitemval)
581                         {
582                                 listval->Add(listitemval);
583                         } else
584                         {
585                                 error = true;
586                         }
587                 }
588                 if (!error)
589                 {
590                         // jippie! could be converted
591                         vallie = listval;
592                 } else
593                 {
594                         // list could not be converted... bad luck
595                         listval->Release();
596                 }
597
598         } else
599 #endif
600         if (PyFloat_Check(pyobj))
601         {
602                 vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) );
603         } else
604 #if PY_VERSION_HEX < 0x03000000
605         if (PyInt_Check(pyobj))
606         {
607                 vallie = new CIntValue( (cInt)PyInt_AS_LONG(pyobj) );
608         } else
609 #endif
610         if (PyLong_Check(pyobj))
611         {
612                 vallie = new CIntValue( (cInt)PyLong_AsLongLong(pyobj) );
613         } else
614         if (PyUnicode_Check(pyobj))
615         {
616                 vallie = new CStringValue(_PyUnicode_AsString(pyobj),"");
617         } else
618         if (PyObject_TypeCheck(pyobj, &CValue::Type)) /* Note, dont let these get assigned to GameObject props, must check elsewhere */
619         {
620                 vallie = (static_cast<CValue *>(BGE_PROXY_REF(pyobj)))->AddRef();
621         } else
622         {
623                 /* return an error value from the caller */
624                 PyErr_Format(PyExc_TypeError, "%scould convert python value to a game engine property", error_prefix);
625         }
626         return vallie;
627
628 }
629
630 PyObject*       CValue::ConvertKeysToPython( void )
631 {
632         PyObject *pylist = PyList_New( 0 );
633         PyObject *pystr;
634         
635         if (m_pNamedPropertyArray)
636         {
637                 std::map<STR_String,CValue*>::iterator it;
638                 for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
639                 {
640                         pystr = PyUnicode_FromString( (*it).first );
641                         PyList_Append(pylist, pystr);
642                         Py_DECREF( pystr );
643                 }
644         }
645         return pylist;
646 }
647
648 #endif //NO_EXP_PYTHON_EMBEDDING
649
650 ///////////////////////////////////////////////////////////////////////////////////////////////
651 ///////////////////////////////////////////////////////////////////////////////////////////////
652 /* These implementations were moved out of the header */
653
654 void CValue::SetOwnerExpression(class CExpression* expr)
655 {
656         /* intentionally empty */
657 }
658
659 void CValue::SetColorOperator(VALUE_OPERATOR op)
660 {
661         /* intentionally empty */
662 }
663 void CValue::SetValue(CValue* newval)
664
665         // no one should get here
666         assertd(newval->GetNumber() == 10121969);       
667 }