Initial revision
[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
18
19 #include "Value.h"
20 #include "FloatValue.h"
21 #include "IntValue.h"
22 #include "VectorValue.h"
23 #include "VoidValue.h"
24 #include "StringValue.h"
25 #include "ErrorValue.h"
26 #include "ListValue.h"
27
28 //#include "FactoryManager.h"
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 PyObject* cvalue_add(PyObject*v, PyObject*w)
39 {
40         return  ((CValue*)v)->Calc(VALUE_ADD_OPERATOR,(CValue*)w);
41 }
42 PyObject* cvalue_sub(PyObject*v, PyObject*w)
43 {
44         return  ((CValue*)v)->Calc(VALUE_SUB_OPERATOR,(CValue*)w);
45 }
46 PyObject* cvalue_mul(PyObject*v, PyObject*w)
47 {
48         return  ((CValue*)v)->Calc(VALUE_MUL_OPERATOR,(CValue*)w);
49 }
50 PyObject* cvalue_div(PyObject*v, PyObject*w)
51 {
52         return  ((CValue*)v)->Calc(VALUE_DIV_OPERATOR,(CValue*)w);
53 }
54 PyObject* cvalue_neg(PyObject*v)
55 {
56         return  ((CValue*)v)->Calc(VALUE_NEG_OPERATOR,(CValue*)v);
57 }
58 PyObject* cvalue_pos(PyObject*v)
59 {
60         return  ((CValue*)v)->Calc(VALUE_POS_OPERATOR,(CValue*)v);
61 }
62
63
64 int MyPyCompare (PyObject* v,PyObject* w)
65 {
66         CValue* eqval =  ((CValue*)v)->Calc(VALUE_EQL_OPERATOR,(CValue*)w);
67         STR_String txt = eqval->GetText();
68         eqval->Release();
69         if (txt=="TRUE")
70                 return 0;
71         CValue* lessval =  ((CValue*)v)->Calc(VALUE_LES_OPERATOR,(CValue*)w);
72         txt = lessval->GetText();
73         lessval->Release();
74         if (txt=="TRUE")
75                 return -1;
76
77         return 1;
78 }
79
80
81 int cvalue_coerce(PyObject** pv,PyObject** pw)
82 {
83         if (PyInt_Check(*pw)) {
84                 double db  = (double)PyInt_AsLong(*pw);
85                 *pw = new CIntValue(db);
86                 Py_INCREF(*pv);
87                 return 0;
88         }
89         else if (PyLong_Check(*pw)) {
90                 double db = PyLong_AsDouble(*pw);
91                 *pw = new CFloatValue(db);
92                 Py_INCREF(*pv);
93                 return 0;
94         }
95         else if (PyFloat_Check(*pw)) {
96                 double db = PyFloat_AsDouble(*pw);
97                 *pw = new CFloatValue(db);
98                 Py_INCREF(*pv);
99                 return 0;
100         } else if (PyString_Check(*pw)) {
101                 const STR_String str = PyString_AsString(*pw);
102                 *pw = new CStringValue(str,"");
103                 Py_INCREF(*pv);
104                 return 0;
105         }
106         return 1; /* Can't do it */
107
108 }
109 static PyNumberMethods cvalue_as_number = {
110         (binaryfunc)cvalue_add, /*nb_add*/
111         (binaryfunc)cvalue_sub, /*nb_subtract*/
112         (binaryfunc)cvalue_mul, /*nb_multiply*/
113         (binaryfunc)cvalue_div, /*nb_divide*/
114         0,//(binaryfunc)cvalue_remainder,       /*nb_remainder*/
115         0,//(binaryfunc)cvalue_divmod,  /*nb_divmod*/
116         0,//0,//0,//0,//(ternaryfunc)cvalue_pow, /*nb_power*/
117         (unaryfunc)cvalue_neg, /*nb_negative*/
118         0,//(unaryfunc)cvalue_pos, /*nb_positive*/
119         0,//(unaryfunc)cvalue_abs, /*nb_absolute*/
120         0,//(inquiry)cvalue_nonzero, /*nb_nonzero*/
121         0,              /*nb_invert*/
122         0,              /*nb_lshift*/
123         0,              /*nb_rshift*/
124         0,              /*nb_and*/
125         0,              /*nb_xor*/
126         0,              /*nb_or*/
127         (coercion)cvalue_coerce, /*nb_coerce*/
128         0,//(unaryfunc)cvalue_int, /*nb_int*/
129         0,//(unaryfunc)cvalue_long, /*nb_long*/
130         0,//(unaryfunc)cvalue_float, /*nb_float*/
131         0,              /*nb_oct*/
132         0,              /*nb_hex*/
133 };
134
135
136 PyTypeObject CValue::Type = {
137         PyObject_HEAD_INIT(&PyType_Type)
138         0,
139         "CValue",
140         sizeof(CValue),
141         0,
142         PyDestructor,
143         0,
144         __getattr,
145         __setattr,
146         &MyPyCompare,
147         __repr,
148         &cvalue_as_number,
149         0,
150         0,
151         0,
152         0
153 };
154
155 PyParentObject CValue::Parents[] = {
156         &CValue::Type,
157                 NULL
158 };
159
160 PyMethodDef CValue::Methods[] = {
161 //      { "printHello", (PyCFunction) CValue::sPyPrintHello, Py_NEWARGS},
162         { "getName", (PyCFunction) CValue::sPyGetName, Py_NEWARGS},
163         {NULL,NULL} //Sentinel
164 };
165
166 PyObject* CValue::PyGetName(PyObject* self,PyObject* args,PyObject* kwds)
167 {
168         PyObject* pyname = PyString_FromString(this->GetName());
169         return pyname;
170 }
171
172
173
174 CValue::CValue(PyTypeObject *T)
175                 : PyObjectPlus(T),
176 #else
177 CValue::CValue()
178
179 #endif //NO_EXP_PYTHON_EMBEDDING
180         
181 m_refcount(1),
182 m_pNamedPropertyArray(NULL)
183 /*
184 pre: false
185 effect: constucts a CValue
186 */
187 {
188         //debug(gRefCountValue++)       // debugging
189 }
190
191
192
193 CValue::~CValue()
194 /*
195 pre:
196 effect: deletes the object
197 */
198 {
199         ClearProperties();
200
201         assertd (m_refcount==0);
202 }
203
204
205
206
207 #define VALUE_SUB(val1, val2) (val1)->Calc(VALUE_SUB_OPERATOR, val2)
208 #define VALUE_MUL(val1, val2) (val1)->Calc(VALUE_MUL_OPERATOR, val2)
209 #define VALUE_DIV(val1, val2) (val1)->Calc(VALUE_DIV_OPERATOR, val2)
210 #define VALUE_NEG(val1)       (val1)->Calc(VALUE_NEG_OPERATOR, val1)
211 #define VALUE_POS(val1)       (val1)->Calc(VALUE_POS_OPERATOR, val1)
212
213
214 STR_String CValue::op2str (VALUE_OPERATOR op)
215 {
216         //pre:
217         //ret: the stringrepresentation of operator op
218         
219         STR_String opmsg;
220         switch (op) {
221         case VALUE_ADD_OPERATOR:
222                 opmsg = " + ";
223                 break;
224         case VALUE_SUB_OPERATOR:
225                 opmsg = " - ";
226                 break;
227         case VALUE_MUL_OPERATOR:
228                 opmsg = " * ";
229                 break;
230         case VALUE_DIV_OPERATOR:
231                 opmsg = " / ";
232                 break;
233         case VALUE_NEG_OPERATOR:
234                 opmsg = " -";
235                 break;
236         case VALUE_POS_OPERATOR:
237                 opmsg = " +";
238                 break;
239         case VALUE_AND_OPERATOR:
240                 opmsg = " & ";
241                 break;
242         case VALUE_OR_OPERATOR:
243                 opmsg = " | ";
244                 break;
245         case VALUE_EQL_OPERATOR:
246                 opmsg = " = ";
247                 break;
248         case VALUE_NEQ_OPERATOR:
249                 opmsg = " != ";
250                 break;
251         case VALUE_NOT_OPERATOR:
252                 opmsg = " !";
253                 break;
254         default:
255                 opmsg="Error in Errorhandling routine.";
256                 //              AfxMessageBox("Invalid operator");
257                 break;
258         }
259         return opmsg;
260 }
261
262
263
264
265
266 //---------------------------------------------------------------------------------------------------------------------
267 //      Property Management
268 //---------------------------------------------------------------------------------------------------------------------
269
270
271
272 //
273 // Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
274 //
275 void CValue::SetProperty(const STR_String & name,CValue* ioProperty)
276 {
277         // Check if somebody is setting an empty property
278         if (ioProperty==NULL)
279         {
280                 trace("Warning:trying to set empty property!");
281                 return;
282         }
283
284         // Make sure we have a property array
285         if (m_pNamedPropertyArray == NULL)
286                 m_pNamedPropertyArray = new std::map<const STR_String,CValue *>;
287
288         // Try to replace property (if so -> exit as soon as we replaced it)
289         CValue* oldval = (*m_pNamedPropertyArray)[name];
290         if (oldval)
291         {
292                 oldval->Release();
293         }
294         
295         // Add property at end of array
296         (*m_pNamedPropertyArray)[name] = ioProperty;//->Add(ioProperty);
297 }
298
299
300
301 //
302 // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
303 //
304 CValue* CValue::GetProperty(const STR_String & inName)
305 {
306         // Check properties, as soon as we found it -> Return a pointer to the property
307         CValue* result = NULL;
308         if (m_pNamedPropertyArray)
309         {
310                 std::map<const STR_String,CValue*>::iterator it = (*m_pNamedPropertyArray).find(inName);
311                 if (!( it==m_pNamedPropertyArray->end()))
312                 {
313                         result = (*it).second;
314                 }
315
316         }
317                 //for (int i=0; i<m_pValuePropertyArray->size(); i++)
318                 //      if ((*m_pValuePropertyArray)[i]->GetName() == inName)
319                 //              return (*m_pValuePropertyArray)[i];
320         
321         // Did not find property with name <inName>, return NULL property pointer
322         return result;
323 }
324
325
326
327 //
328 // Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
329 //
330 STR_String CValue::GetPropertyText(const STR_String & inName,const STR_String& deftext)
331 {
332         CValue *property = GetProperty(inName);
333         if (property)
334                 return property->GetText();
335         else
336                 return deftext;//String::sEmpty;
337 }
338
339 float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
340 {
341         CValue *property = GetProperty(inName);
342         if (property)
343                 return property->GetNumber();
344         else
345                 return defnumber;
346 }
347
348
349
350 //
351 // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
352 //
353 bool CValue::RemoveProperty(const STR_String & inName)
354 {
355         // Check if there are properties at all which can be removed
356         if (m_pNamedPropertyArray == NULL)
357                 return false;
358
359         // Scan all properties, as soon as we find one with <inName> -> Remove it
360 //      CValue* val = (*m_pNamedPropertyArray)[inName];
361         if (m_pNamedPropertyArray->erase(inName)) return true;
362         
363         return false;
364 }
365
366
367
368 //
369 // Clear all properties
370 //
371 void CValue::ClearProperties()
372 {               
373         // Check if we have any properties
374         if (m_pNamedPropertyArray == NULL)
375                 return;
376
377         // Remove all properties
378         for ( std::map<const STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
379         !(it == m_pNamedPropertyArray->end());it++)
380         {
381                 CValue* tmpval = (*it).second;
382                 STR_String name = (*it).first;
383                 tmpval->Release();
384         }
385
386         // Delete property array
387         delete m_pNamedPropertyArray;
388         m_pNamedPropertyArray=NULL;
389 }
390
391
392
393 //
394 // Set all properties' modified flag to <inModified>
395 //
396 void CValue::SetPropertiesModified(bool inModified)
397 {
398         int numprops = GetPropertyCount();
399         for (int i=0; i<numprops; i++)
400                 GetProperty(i)->SetModified(inModified);
401 }
402
403
404
405 //
406 // Check if any of the properties in this value have been modified
407 //
408 bool CValue::IsAnyPropertyModified()
409 {
410         int numprops = GetPropertyCount();
411         for (int i=0;i<numprops;i++)
412                 if (GetProperty(i)->IsModified())
413                         return true;
414
415         return false;
416 }
417
418
419
420 //
421 // Get property number <inIndex>
422 //
423
424 CValue* CValue::GetProperty(int inIndex)
425 {
426
427         int count=0;
428         CValue* result = NULL;
429
430         if (m_pNamedPropertyArray)
431         {
432                 for ( std::map<const STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
433                 !(it == m_pNamedPropertyArray->end());it++)
434                 {
435                         if (count++==inIndex)
436                         {
437                                 result = (*it).second;
438                                 break;
439                         }
440                 }
441
442         }
443         return result;
444 }
445
446
447
448 //
449 // Get the amount of properties assiocated with this value
450 //
451 int CValue::GetPropertyCount()
452 {
453         if (m_pNamedPropertyArray)
454                 return m_pNamedPropertyArray->size();
455         else
456                 return 0;
457 }
458
459
460
461
462
463 void CValue::CloneProperties(CValue *replica)
464 {
465         
466         if (m_pNamedPropertyArray)
467         {
468                 replica->m_pNamedPropertyArray=NULL;
469                 for ( std::map<const STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
470                 !(it == m_pNamedPropertyArray->end());it++)
471                 {
472                         
473                         replica->SetProperty((*it).first,(*it).second->GetReplica());
474                 }
475         }
476
477         
478 }
479
480
481
482
483
484
485 double*         CValue::GetVector3(bool bGetTransformedVec)
486 {
487         assertd(false); // don;t get vector from me
488         return m_sZeroVec;//::sZero;
489 }
490
491
492
493
494
495
496 /*---------------------------------------------------------------------------------------------------------------------
497         Reference Counting
498 ---------------------------------------------------------------------------------------------------------------------*/
499
500
501
502 //
503 // Add a reference to this value
504 //
505 CValue *CValue::AddRef()
506 {
507         // Increase global reference count, used to see at the end of the program
508         // if all CValue-derived classes have been dereferenced to 0
509         //debug(gRefCountValue++);
510         m_refcount++; 
511         return this;
512 }
513
514
515
516 //
517 // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
518 //
519 int     CValue::Release()
520 {
521         // Decrease global reference count, used to see at the end of the program
522         // if all CValue-derived classes have been dereferenced to 0
523         //debug(gRefCountValue--);
524
525         // Decrease local reference count, if it reaches 0 the object should be freed
526         if (--m_refcount > 0)
527         {
528                 // Reference count normal, return new reference count
529                 return m_refcount;
530         }
531         else
532         {
533                 // Reference count reached 0, delete ourselves and return 0
534 //              assert(m_refcount==0, "Reference count reached sub-zero, object released too much");
535                 delete this;
536                 return 0;
537         }
538
539 }
540
541
542
543 //
544 // Disable reference counting for this value
545 //
546 void CValue::DisableRefCount()
547 {
548         assertd(m_refcount == 1);
549         m_refcount--;
550
551         //debug(gRefCountValue--);
552         m_ValFlags.RefCountDisabled=true;
553 }
554
555
556
557 void CValue::AddDataToReplica(CValue *replica)
558 {
559         replica->m_refcount = 1;
560 #ifdef _DEBUG
561         //gRefCountValue++;
562 #endif
563         replica->m_ValFlags.RefCountDisabled = false;
564
565         replica->ReplicaSetName(GetName());
566
567         //copy all props
568         CloneProperties(replica);
569 }
570
571
572
573 CValue* CValue::FindIdentifier(const STR_String& identifiername)
574 {
575
576         CValue* result = NULL;
577
578         int pos = 0;
579         // if a dot exists, explode the name into pieces to get the subcontext
580         if ((pos=identifiername.Find('.'))>=0)
581         {
582                 const STR_String rightstring = identifiername.Right(identifiername.Length() -1 - pos);
583                 const STR_String leftstring = identifiername.Left(pos);
584                 CValue* tempresult = GetProperty(leftstring);
585                 if (tempresult)
586                 {
587                         result=tempresult->FindIdentifier(rightstring);
588                 } 
589         } else
590         {
591                 result = GetProperty(identifiername);
592         }
593         if (result)
594                 return result->AddRef();
595         // warning here !!!
596         result = new CErrorValue(identifiername+" not found");
597         return result;
598 }
599
600
601 #ifndef NO_EXP_PYTHON_EMBEDDING
602
603
604 static PyMethodDef      CValueMethods[] = 
605 {
606         //{ "new", CValue::PyMake , Py_NEWARGS},
607         { NULL,NULL}    // Sentinel
608 };
609
610
611 PyObject*       CValue::_getattr(char* attr)
612 {
613         CValue* resultattr = FindIdentifier(attr);
614         STR_String text;
615         if (resultattr)
616         {
617                 if (resultattr->IsError())
618                 {
619                         resultattr->Release();
620                 } else
621                 {
622                         // to avoid some compare problems, return a real pythonthing
623                         PyObject* pyconvert = resultattr->ConvertValueToPython();
624                         if (pyconvert)
625                         {
626                                 resultattr->Release();
627                                 return pyconvert;
628                         } else
629                         {
630                                 // also check if it's already in pythoninterpreter!
631                                 return resultattr;
632                         }
633                         
634                 }
635         }
636         _getattr_up(PyObjectPlus);
637 }
638
639 CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
640 {
641
642         CValue* vallie = NULL;
643
644         PyTypeObject* type = pyobj->ob_type;
645
646         if (type == &PyList_Type)
647         {
648                 CListValue* listval = new CListValue();
649                 bool error = false;
650
651                 int i;
652                 int numitems = PyList_Size(pyobj);
653                 for (i=0;i<numitems;i++)
654                 {
655                         PyObject* listitem = PyList_GetItem(pyobj,i);
656                         CValue* listitemval = ConvertPythonToValue(listitem);
657                         if (listitemval)
658                         {
659                                 listval->Add(listitemval);
660                         } else
661                         {
662                                 error = true;
663                         }
664                 }
665                 if (!error)
666                 {
667                         // jippie! could be converted
668                         vallie = listval;
669                 } else
670                 {
671                         // list could not be converted... bad luck
672                         listval->Release();
673                 }
674
675         } else
676         if (type == &PyFloat_Type)
677         {
678                 float fl;
679                 PyArg_Parse(pyobj,"f",&fl);
680                 vallie = new CFloatValue(fl);
681         } else
682         if (type==&PyInt_Type)
683         {
684                 int innie;
685                 PyArg_Parse(pyobj,"i",&innie);
686                 vallie = new CIntValue(innie);
687         } else
688         
689         if (type==&PyString_Type)
690         {
691                 vallie = new CStringValue(PyString_AsString(pyobj),"");
692         } else
693         if (type==&CValue::Type || type==&CListValue::Type)
694         {
695                 vallie = ((CValue*) pyobj)->AddRef();
696         }
697         return vallie;
698
699 }
700 int     CValue::_setattr(char* attr,PyObject* pyobj)
701 {
702         
703         if (!pyobj) { // member deletion
704                 RemoveProperty(attr);
705                 return 0;
706         }
707
708         CValue* vallie = ConvertPythonToValue(pyobj);
709         if (vallie)
710         {
711                 CValue* oldprop = GetProperty(attr);
712                 
713                 if (oldprop)
714                 {
715                         oldprop->SetValue(vallie);
716                 } else
717                 {
718                         SetProperty(attr,vallie->AddRef());
719                 }
720                 vallie->Release();
721         }
722         
723         //PyObjectPlus::_setattr(attr,value);
724         return 0;
725 };
726 /*
727 PyObject*       CValue::PyMake(PyObject* ignored,PyObject* args)
728 {
729
730         //Py_Try(PyArg_ParseTuple(args,"s",&name));
731         Py_INCREF(Py_None);
732         return Py_None;//new CValue();
733 }
734 */
735
736 extern "C" {
737         void initCValue(void)
738         {
739                 Py_InitModule("CValue",CValueMethods);
740         }
741 }
742
743
744
745 #endif //NO_EXP_PYTHON_EMBEDDING
746
747 ///////////////////////////////////////////////////////////////////////////////////////////////
748 ///////////////////////////////////////////////////////////////////////////////////////////////
749 /* These implementations were moved out of the header */
750
751 void CValue::SetOwnerExpression(class CExpression* expr)
752 {
753         /* intentionally empty */
754 }
755
756 void CValue::SetColorOperator(VALUE_OPERATOR op)
757 {
758         /* intentionally empty */
759 }
760 void CValue::SetValue(CValue* newval)
761
762         // no one should get here
763         assertd(newval->GetNumber() == 10121969);       
764 }
765 ///////////////////////////////////////////////////////////////////////////////////////////////
766 ///////////////////////////////////////////////////////////////////////////////////////////////
767