BGE patch: Relink actuators with target within group when duplicating group; generali...
[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 = parser.ProcessText(m_exprtxt);
81         if (userexpr)
82         {
83                 
84
85                 switch (m_type)
86                 {
87
88                 case KX_ACT_PROP_ASSIGN:
89                         {
90                                 
91                                 CValue* newval = userexpr->Calculate();
92                                 CValue* oldprop = propowner->GetProperty(m_propname);
93                                 if (oldprop)
94                                 {
95                                         oldprop->SetValue(newval);
96                                 } else
97                                 {
98                                         propowner->SetProperty(m_propname,newval);
99                                 }
100                                 newval->Release();
101                                 break;
102                         }
103                 case KX_ACT_PROP_ADD:
104                         {
105                                 CValue* oldprop = propowner->GetProperty(m_propname);
106                                 if (oldprop)
107                                 {
108                                         // int waarde = (int)oldprop->GetNumber();  /*unused*/
109                                         CExpression* expr = new COperator2Expr(VALUE_ADD_OPERATOR,new CConstExpr(oldprop->AddRef()),
110                                                                                                                         userexpr->AddRef());
111
112                                         CValue* newprop = expr->Calculate();
113                                         oldprop->SetValue(newprop);
114                                         newprop->Release();
115                                         expr->Release();
116
117                                 }
118
119                                 break;
120                         }
121                 case KX_ACT_PROP_COPY:
122                         {
123                                 if (m_sourceObj)
124                                 {
125                                         CValue* copyprop = m_sourceObj->GetProperty(m_exprtxt);
126                                         if (copyprop)
127                                         {
128                                                 CValue *val = copyprop->GetReplica();
129                                                 GetParent()->SetProperty(
130                                                          m_propname,
131                                                          val);
132                                                 val->Release();
133
134                                         }
135                                 }
136                                 break;
137                         }
138                 default:
139                         {
140
141                         }
142                 }
143
144                 userexpr->Release();
145         }
146         
147         return result;
148 }
149
150         bool 
151
152 SCA_PropertyActuator::
153
154 isValid(
155
156         SCA_PropertyActuator::KX_ACT_PROP_MODE mode
157
158 ){
159         bool res = false;       
160         res = ((mode > KX_ACT_PROP_NODEF) && (mode < KX_ACT_PROP_MAX));
161         return res;
162 }
163
164
165         CValue* 
166
167 SCA_PropertyActuator::
168
169 GetReplica() {
170
171         SCA_PropertyActuator* replica = new SCA_PropertyActuator(*this);
172
173         replica->ProcessReplica();
174
175         // this will copy properties and so on...
176
177         CValue::AddDataToReplica(replica);
178
179         return replica;
180
181 };
182
183 void SCA_PropertyActuator::ProcessReplica()
184 {
185         // no need to check for self reference like in the constructor:
186         // the replica will always have a different parent
187         if (m_sourceObj)
188                 m_sourceObj->RegisterActuator(this);
189         SCA_IActuator::ProcessReplica();
190 }
191
192 bool SCA_PropertyActuator::UnlinkObject(SCA_IObject* clientobj)
193 {
194         if (clientobj == m_sourceObj)
195         {
196                 // this object is being deleted, we cannot continue to track it.
197                 m_sourceObj = NULL;
198                 return true;
199         }
200         return false;
201 }
202
203 void SCA_PropertyActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
204 {
205         void **h_obj = (*obj_map)[m_sourceObj];
206         if (h_obj) {
207                 if (m_sourceObj)
208                         m_sourceObj->UnregisterActuator(this);
209                 m_sourceObj = (SCA_IObject*)(*h_obj);
210                 m_sourceObj->RegisterActuator(this);
211         }
212 }
213
214
215 /* ------------------------------------------------------------------------- */
216 /* Python functions                                                          */
217 /* ------------------------------------------------------------------------- */
218
219 /* Integration hooks ------------------------------------------------------- */
220 PyTypeObject SCA_PropertyActuator::Type = {
221         PyObject_HEAD_INIT(&PyType_Type)
222         0,
223         "SCA_PropertyActuator",
224         sizeof(SCA_PropertyActuator),
225         0,
226         PyDestructor,
227         0,
228         __getattr,
229         __setattr,
230         0, //&MyPyCompare,
231         __repr,
232         0, //&cvalue_as_number,
233         0,
234         0,
235         0,
236         0
237 };
238
239 PyParentObject SCA_PropertyActuator::Parents[] = {
240         &SCA_PropertyActuator::Type,
241         &SCA_IActuator::Type,
242         &SCA_ILogicBrick::Type,
243         &CValue::Type,
244         NULL
245 };
246
247 PyMethodDef SCA_PropertyActuator::Methods[] = {
248         {"setProperty", (PyCFunction) SCA_PropertyActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
249         {"getProperty", (PyCFunction) SCA_PropertyActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc},
250         {"setValue", (PyCFunction) SCA_PropertyActuator::sPySetValue, METH_VARARGS, SetValue_doc},
251         {"getValue", (PyCFunction) SCA_PropertyActuator::sPyGetValue, METH_VARARGS, GetValue_doc},
252         {NULL,NULL} //Sentinel
253 };
254
255 PyObject* SCA_PropertyActuator::_getattr(const STR_String& attr) {
256         _getattr_up(SCA_IActuator);
257 }
258
259 /* 1. setProperty                                                        */
260 char SCA_PropertyActuator::SetProperty_doc[] = 
261 "setProperty(name)\n"
262 "\t- name: string\n"
263 "\tSet the property on which to operate. If there is no property\n"
264 "\tof this name, the call is ignored.\n";
265 PyObject* SCA_PropertyActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds)
266 {
267         /* Check whether the name exists first ! */
268         char *nameArg;
269         if (!PyArg_ParseTuple(args, "s", &nameArg)) {
270                 return NULL;
271         }
272
273         CValue* prop = GetParent()->FindIdentifier(nameArg);
274
275         if (!prop->IsError()) {
276                 m_propname = nameArg;
277         } else {
278                 ; /* not found ... */
279         }
280         prop->Release();
281         
282         Py_Return;
283 }
284
285 /* 2. getProperty                                                        */
286 char SCA_PropertyActuator::GetProperty_doc[] = 
287 "getProperty(name)\n"
288 "\tReturn the property on which the actuator operates.\n";
289 PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds)
290 {
291         return PyString_FromString(m_propname);
292 }
293
294 /* 3. setValue                                                        */
295 char SCA_PropertyActuator::SetValue_doc[] = 
296 "setValue(value)\n"
297 "\t- value: string\n"
298 "\tSet the value with which the actuator operates. If the value\n"
299 "\tis not compatible with the type of the property, the subsequent\n"
300 "\t action is ignored.\n";
301 PyObject* SCA_PropertyActuator::PySetValue(PyObject* self, PyObject* args, PyObject* kwds)
302 {
303         char *valArg;
304         if(!PyArg_ParseTuple(args, "s", &valArg)) {
305                 return NULL;            
306         }
307         
308         if (valArg)     m_exprtxt = valArg;
309
310         Py_Return;
311 }
312
313 /* 4. getValue                                                        */
314 char SCA_PropertyActuator::GetValue_doc[] = 
315 "getValue()\n"
316 "\tReturns the value with which the actuator operates.\n";
317 PyObject* SCA_PropertyActuator::PyGetValue(PyObject* self, PyObject* args, PyObject* kwds)
318 {
319         return PyString_FromString(m_exprtxt);
320 }
321
322 /* eof */