Name attributes added since 2.48a more consistently.
[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         return replica;
190
191 };
192
193 void SCA_PropertyActuator::ProcessReplica()
194 {
195         // no need to check for self reference like in the constructor:
196         // the replica will always have a different parent
197         if (m_sourceObj)
198                 m_sourceObj->RegisterActuator(this);
199         SCA_IActuator::ProcessReplica();
200 }
201
202 bool SCA_PropertyActuator::UnlinkObject(SCA_IObject* clientobj)
203 {
204         if (clientobj == m_sourceObj)
205         {
206                 // this object is being deleted, we cannot continue to track it.
207                 m_sourceObj = NULL;
208                 return true;
209         }
210         return false;
211 }
212
213 void SCA_PropertyActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
214 {
215         void **h_obj = (*obj_map)[m_sourceObj];
216         if (h_obj) {
217                 if (m_sourceObj)
218                         m_sourceObj->UnregisterActuator(this);
219                 m_sourceObj = (SCA_IObject*)(*h_obj);
220                 m_sourceObj->RegisterActuator(this);
221         }
222 }
223
224
225 /* ------------------------------------------------------------------------- */
226 /* Python functions                                                          */
227 /* ------------------------------------------------------------------------- */
228
229 /* Integration hooks ------------------------------------------------------- */
230 PyTypeObject SCA_PropertyActuator::Type = {
231 #if (PY_VERSION_HEX >= 0x02060000)
232         PyVarObject_HEAD_INIT(NULL, 0)
233 #else
234         /* python 2.5 and below */
235         PyObject_HEAD_INIT( NULL )  /* required py macro */
236         0,                          /* ob_size */
237 #endif
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("propName",0,100,false,SCA_PropertyActuator,m_propname,CheckProperty),
274         KX_PYATTRIBUTE_STRING_RW("value",0,100,false,SCA_PropertyActuator,m_exprtxt),
275         KX_PYATTRIBUTE_INT_RW("mode", KX_ACT_PROP_NODEF+1, KX_ACT_PROP_MAX-1, false, SCA_PropertyActuator, m_type), /* ATTR_TODO add constents to game logic dict */
276         { NULL }        //Sentinel
277 };
278
279 PyObject* SCA_PropertyActuator::py_getattro(PyObject *attr) {
280         py_getattro_up(SCA_IActuator);
281 }
282
283 PyObject* SCA_PropertyActuator::py_getattro_dict() {
284         py_getattro_dict_up(SCA_IActuator);
285 }
286
287 int SCA_PropertyActuator::py_setattro(PyObject *attr, PyObject *value) {
288         py_setattro_up(SCA_IActuator);
289 }
290
291 /* 1. setProperty                                                        */
292 const char SCA_PropertyActuator::SetProperty_doc[] = 
293 "setProperty(name)\n"
294 "\t- name: string\n"
295 "\tSet the property on which to operate. If there is no property\n"
296 "\tof this name, the call is ignored.\n";
297 PyObject* SCA_PropertyActuator::PySetProperty(PyObject* args, PyObject* kwds)
298 {
299         ShowDeprecationWarning("setProperty()", "the 'propName' property");
300         /* Check whether the name exists first ! */
301         char *nameArg;
302         if (!PyArg_ParseTuple(args, "s:setProperty", &nameArg)) {
303                 return NULL;
304         }
305
306         CValue* prop = GetParent()->FindIdentifier(nameArg);
307
308         if (!prop->IsError()) {
309                 m_propname = nameArg;
310         } else {
311                 ; /* not found ... */
312         }
313         prop->Release();
314         
315         Py_RETURN_NONE;
316 }
317
318 /* 2. getProperty                                                        */
319 const char SCA_PropertyActuator::GetProperty_doc[] = 
320 "getProperty(name)\n"
321 "\tReturn the property on which the actuator operates.\n";
322 PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* args, PyObject* kwds)
323 {
324         ShowDeprecationWarning("getProperty()", "the 'propName' property");
325         return PyString_FromString(m_propname);
326 }
327
328 /* 3. setValue                                                        */
329 const char SCA_PropertyActuator::SetValue_doc[] = 
330 "setValue(value)\n"
331 "\t- value: string\n"
332 "\tSet the value with which the actuator operates. If the value\n"
333 "\tis not compatible with the type of the property, the subsequent\n"
334 "\t action is ignored.\n";
335 PyObject* SCA_PropertyActuator::PySetValue(PyObject* args, PyObject* kwds)
336 {
337         ShowDeprecationWarning("setValue()", "the value property");
338         char *valArg;
339         if(!PyArg_ParseTuple(args, "s:setValue", &valArg)) {
340                 return NULL;            
341         }
342         
343         if (valArg)     m_exprtxt = valArg;
344
345         Py_RETURN_NONE;
346 }
347
348 /* 4. getValue                                                        */
349 const char SCA_PropertyActuator::GetValue_doc[] = 
350 "getValue()\n"
351 "\tReturns the value with which the actuator operates.\n";
352 PyObject* SCA_PropertyActuator::PyGetValue(PyObject* args, PyObject* kwds)
353 {
354         ShowDeprecationWarning("getValue()", "the value property");
355         return PyString_FromString(m_exprtxt);
356 }
357
358 /* eof */