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