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