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