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