2.50: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r19323...
[blender.git] / source / gameengine / GameLogic / SCA_PropertyActuator.cpp
1 /**
2  * Assign, change, copy properties
3  *
4  * $Id$
5  *
6  * ***** BEGIN GPL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL LICENSE BLOCK *****
30  */
31
32 #include "SCA_PropertyActuator.h"
33 #include "InputParser.h"
34 #include "Operator2Expr.h"
35 #include "ConstExpr.h"
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 /* ------------------------------------------------------------------------- */
42 /* Native functions                                                          */
43 /* ------------------------------------------------------------------------- */
44
45 SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,SCA_IObject* sourceObj,const STR_String& propname,const STR_String& expr,int acttype,PyTypeObject* T )
46    :    SCA_IActuator(gameobj,T),
47         m_type(acttype),
48         m_propname(propname),
49         m_exprtxt(expr),
50         m_sourceObj(sourceObj)
51 {
52         // protect ourselves against someone else deleting the source object
53         // don't protect against ourselves: it would create a dead lock
54         if (m_sourceObj)
55                 m_sourceObj->RegisterActuator(this);
56 }
57
58 SCA_PropertyActuator::~SCA_PropertyActuator()
59 {
60         if (m_sourceObj)
61                 m_sourceObj->UnregisterActuator(this);
62 }
63
64 bool SCA_PropertyActuator::Update()
65 {
66         bool result = false;
67
68         bool bNegativeEvent = IsNegativeEvent();
69         RemoveAllEvents();
70
71
72         if (bNegativeEvent)
73                 return false; // do nothing on negative events
74
75
76         CValue* propowner = GetParent();
77         CParser parser;
78         parser.SetContext( propowner->AddRef());
79         
80         CExpression* userexpr= NULL;
81         
82         if (m_type==KX_ACT_PROP_TOGGLE)
83         {
84                 /* dont use */
85                 CValue* newval;
86                 CValue* oldprop = propowner->GetProperty(m_propname);
87                 if (oldprop)
88                 {
89                         newval = new CBoolValue((oldprop->GetNumber()==0.0) ? true:false);
90                         oldprop->SetValue(newval);
91                 } else
92                 {       /* as not been assigned, evaluate as false, so assign true */
93                         newval = new CBoolValue(true);
94                         propowner->SetProperty(m_propname,newval);
95                 }
96                 newval->Release();
97         }
98         else if ((userexpr = parser.ProcessText(m_exprtxt))) {
99                 switch (m_type)
100                 {
101
102                 case KX_ACT_PROP_ASSIGN:
103                         {
104                                 
105                                 CValue* newval = userexpr->Calculate();
106                                 CValue* oldprop = propowner->GetProperty(m_propname);
107                                 if (oldprop)
108                                 {
109                                         oldprop->SetValue(newval);
110                                 } else
111                                 {
112                                         propowner->SetProperty(m_propname,newval);
113                                 }
114                                 newval->Release();
115                                 break;
116                         }
117                 case KX_ACT_PROP_ADD:
118                         {
119                                 CValue* oldprop = propowner->GetProperty(m_propname);
120                                 if (oldprop)
121                                 {
122                                         // int waarde = (int)oldprop->GetNumber();  /*unused*/
123                                         CExpression* expr = new COperator2Expr(VALUE_ADD_OPERATOR,new CConstExpr(oldprop->AddRef()),
124                                                                                                                         userexpr->AddRef());
125
126                                         CValue* newprop = expr->Calculate();
127                                         oldprop->SetValue(newprop);
128                                         newprop->Release();
129                                         expr->Release();
130
131                                 }
132
133                                 break;
134                         }
135                 case KX_ACT_PROP_COPY:
136                         {
137                                 if (m_sourceObj)
138                                 {
139                                         CValue* copyprop = m_sourceObj->GetProperty(m_exprtxt);
140                                         if (copyprop)
141                                         {
142                                                 CValue *val = copyprop->GetReplica();
143                                                 GetParent()->SetProperty(
144                                                          m_propname,
145                                                          val);
146                                                 val->Release();
147
148                                         }
149                                 }
150                                 break;
151                         }
152                 /* case KX_ACT_PROP_TOGGLE: */ /* accounted for above, no need for userexpr */
153                 default:
154                         {
155
156                         }
157                 }
158
159                 userexpr->Release();
160         }
161         
162         return result;
163 }
164
165         bool 
166
167 SCA_PropertyActuator::
168
169 isValid(
170
171         SCA_PropertyActuator::KX_ACT_PROP_MODE mode
172
173 ){
174         bool res = false;       
175         res = ((mode > KX_ACT_PROP_NODEF) && (mode < KX_ACT_PROP_MAX));
176         return res;
177 }
178
179
180         CValue* 
181
182 SCA_PropertyActuator::
183
184 GetReplica() {
185
186         SCA_PropertyActuator* replica = new SCA_PropertyActuator(*this);
187
188         replica->ProcessReplica();
189
190         // this will copy properties and so on...
191
192         CValue::AddDataToReplica(replica);
193
194         return replica;
195
196 };
197
198 void SCA_PropertyActuator::ProcessReplica()
199 {
200         // no need to check for self reference like in the constructor:
201         // the replica will always have a different parent
202         if (m_sourceObj)
203                 m_sourceObj->RegisterActuator(this);
204         SCA_IActuator::ProcessReplica();
205 }
206
207 bool SCA_PropertyActuator::UnlinkObject(SCA_IObject* clientobj)
208 {
209         if (clientobj == m_sourceObj)
210         {
211                 // this object is being deleted, we cannot continue to track it.
212                 m_sourceObj = NULL;
213                 return true;
214         }
215         return false;
216 }
217
218 void SCA_PropertyActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
219 {
220         void **h_obj = (*obj_map)[m_sourceObj];
221         if (h_obj) {
222                 if (m_sourceObj)
223                         m_sourceObj->UnregisterActuator(this);
224                 m_sourceObj = (SCA_IObject*)(*h_obj);
225                 m_sourceObj->RegisterActuator(this);
226         }
227 }
228
229
230 /* ------------------------------------------------------------------------- */
231 /* Python functions                                                          */
232 /* ------------------------------------------------------------------------- */
233
234 /* Integration hooks ------------------------------------------------------- */
235 PyTypeObject SCA_PropertyActuator::Type = {
236         PyObject_HEAD_INIT(NULL)
237         0,
238         "SCA_PropertyActuator",
239         sizeof(PyObjectPlus_Proxy),
240         0,
241         py_base_dealloc,
242         0,
243         0,
244         0,
245         0,
246         py_base_repr,
247         0,0,0,0,0,0,
248         py_base_getattro,
249         py_base_setattro,
250         0,0,0,0,0,0,0,0,0,
251         Methods
252 };
253
254 PyParentObject SCA_PropertyActuator::Parents[] = {
255         &SCA_PropertyActuator::Type,
256         &SCA_IActuator::Type,
257         &SCA_ILogicBrick::Type,
258         &CValue::Type,
259         NULL
260 };
261
262 PyMethodDef SCA_PropertyActuator::Methods[] = {
263         //Deprecated functions ------>
264         {"setProperty", (PyCFunction) SCA_PropertyActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
265         {"getProperty", (PyCFunction) SCA_PropertyActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc},
266         {"setValue", (PyCFunction) SCA_PropertyActuator::sPySetValue, METH_VARARGS, (PY_METHODCHAR)SetValue_doc},
267         {"getValue", (PyCFunction) SCA_PropertyActuator::sPyGetValue, METH_VARARGS, (PY_METHODCHAR)GetValue_doc},
268         //<----- Deprecated
269         {NULL,NULL} //Sentinel
270 };
271
272 PyAttributeDef SCA_PropertyActuator::Attributes[] = {
273         KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_PropertyActuator,m_propname,CheckProperty),
274         KX_PYATTRIBUTE_STRING_RW("value",0,100,false,SCA_PropertyActuator,m_exprtxt),
275         { NULL }        //Sentinel
276 };
277
278 PyObject* SCA_PropertyActuator::py_getattro(PyObject *attr) {
279         py_getattro_up(SCA_IActuator);
280 }
281
282 int SCA_PropertyActuator::py_setattro(PyObject *attr, PyObject *value) {
283         py_setattro_up(SCA_IActuator);
284 }
285
286 /* 1. setProperty                                                        */
287 const char SCA_PropertyActuator::SetProperty_doc[] = 
288 "setProperty(name)\n"
289 "\t- name: string\n"
290 "\tSet the property on which to operate. If there is no property\n"
291 "\tof this name, the call is ignored.\n";
292 PyObject* SCA_PropertyActuator::PySetProperty(PyObject* args, PyObject* kwds)
293 {
294         ShowDeprecationWarning("setProperty()", "the 'property' property");
295         /* Check whether the name exists first ! */
296         char *nameArg;
297         if (!PyArg_ParseTuple(args, "s:setProperty", &nameArg)) {
298                 return NULL;
299         }
300
301         CValue* prop = GetParent()->FindIdentifier(nameArg);
302
303         if (!prop->IsError()) {
304                 m_propname = nameArg;
305         } else {
306                 ; /* not found ... */
307         }
308         prop->Release();
309         
310         Py_RETURN_NONE;
311 }
312
313 /* 2. getProperty                                                        */
314 const char SCA_PropertyActuator::GetProperty_doc[] = 
315 "getProperty(name)\n"
316 "\tReturn the property on which the actuator operates.\n";
317 PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* args, PyObject* kwds)
318 {
319         ShowDeprecationWarning("getProperty()", "the 'property' property");
320         return PyString_FromString(m_propname);
321 }
322
323 /* 3. setValue                                                        */
324 const char SCA_PropertyActuator::SetValue_doc[] = 
325 "setValue(value)\n"
326 "\t- value: string\n"
327 "\tSet the value with which the actuator operates. If the value\n"
328 "\tis not compatible with the type of the property, the subsequent\n"
329 "\t action is ignored.\n";
330 PyObject* SCA_PropertyActuator::PySetValue(PyObject* args, PyObject* kwds)
331 {
332         ShowDeprecationWarning("setValue()", "the value property");
333         char *valArg;
334         if(!PyArg_ParseTuple(args, "s:setValue", &valArg)) {
335                 return NULL;            
336         }
337         
338         if (valArg)     m_exprtxt = valArg;
339
340         Py_RETURN_NONE;
341 }
342
343 /* 4. getValue                                                        */
344 const char SCA_PropertyActuator::GetValue_doc[] = 
345 "getValue()\n"
346 "\tReturns the value with which the actuator operates.\n";
347 PyObject* SCA_PropertyActuator::PyGetValue(PyObject* args, PyObject* kwds)
348 {
349         ShowDeprecationWarning("getValue()", "the value property");
350         return PyString_FromString(m_exprtxt);
351 }
352
353 /* eof */