ebe1cd518638b6d5c3727e0ac606842de234ee6b
[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,CValue* 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 && m_sourceObj != GetParent())
55                 m_sourceObj->AddRef();
56 }
57
58 SCA_PropertyActuator::~SCA_PropertyActuator()
59 {
60         if (m_sourceObj && m_sourceObj != GetParent())
61                 m_sourceObj->Release();
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->AddRef();
189         SCA_IActuator::ProcessReplica();
190 }
191
192
193
194 /* ------------------------------------------------------------------------- */
195 /* Python functions                                                          */
196 /* ------------------------------------------------------------------------- */
197
198 /* Integration hooks ------------------------------------------------------- */
199 PyTypeObject SCA_PropertyActuator::Type = {
200         PyObject_HEAD_INIT(&PyType_Type)
201         0,
202         "SCA_PropertyActuator",
203         sizeof(SCA_PropertyActuator),
204         0,
205         PyDestructor,
206         0,
207         __getattr,
208         __setattr,
209         0, //&MyPyCompare,
210         __repr,
211         0, //&cvalue_as_number,
212         0,
213         0,
214         0,
215         0
216 };
217
218 PyParentObject SCA_PropertyActuator::Parents[] = {
219         &SCA_PropertyActuator::Type,
220         &SCA_IActuator::Type,
221         &SCA_ILogicBrick::Type,
222         &CValue::Type,
223         NULL
224 };
225
226 PyMethodDef SCA_PropertyActuator::Methods[] = {
227         {"setProperty", (PyCFunction) SCA_PropertyActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
228         {"getProperty", (PyCFunction) SCA_PropertyActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc},
229         {"setValue", (PyCFunction) SCA_PropertyActuator::sPySetValue, METH_VARARGS, SetValue_doc},
230         {"getValue", (PyCFunction) SCA_PropertyActuator::sPyGetValue, METH_VARARGS, GetValue_doc},
231         {NULL,NULL} //Sentinel
232 };
233
234 PyObject* SCA_PropertyActuator::_getattr(const STR_String& attr) {
235         _getattr_up(SCA_IActuator);
236 }
237
238 /* 1. setProperty                                                        */
239 char SCA_PropertyActuator::SetProperty_doc[] = 
240 "setProperty(name)\n"
241 "\t- name: string\n"
242 "\tSet the property on which to operate. If there is no property\n"
243 "\tof this name, the call is ignored.\n";
244 PyObject* SCA_PropertyActuator::PySetProperty(PyObject* self, PyObject* args, PyObject* kwds)
245 {
246         /* Check whether the name exists first ! */
247         char *nameArg;
248         if (!PyArg_ParseTuple(args, "s", &nameArg)) {
249                 return NULL;
250         }
251
252         CValue* prop = GetParent()->FindIdentifier(nameArg);
253
254         if (!prop->IsError()) {
255                 m_propname = nameArg;
256         } else {
257                 ; /* not found ... */
258         }
259         prop->Release();
260         
261         Py_Return;
262 }
263
264 /* 2. getProperty                                                        */
265 char SCA_PropertyActuator::GetProperty_doc[] = 
266 "getProperty(name)\n"
267 "\tReturn the property on which the actuator operates.\n";
268 PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds)
269 {
270         return PyString_FromString(m_propname);
271 }
272
273 /* 3. setValue                                                        */
274 char SCA_PropertyActuator::SetValue_doc[] = 
275 "setValue(value)\n"
276 "\t- value: string\n"
277 "\tSet the value with which the actuator operates. If the value\n"
278 "\tis not compatible with the type of the property, the subsequent\n"
279 "\t action is ignored.\n";
280 PyObject* SCA_PropertyActuator::PySetValue(PyObject* self, PyObject* args, PyObject* kwds)
281 {
282         char *valArg;
283         if(!PyArg_ParseTuple(args, "s", &valArg)) {
284                 return NULL;            
285         }
286         
287         if (valArg)     m_exprtxt = valArg;
288
289         Py_Return;
290 }
291
292 /* 4. getValue                                                        */
293 char SCA_PropertyActuator::GetValue_doc[] = 
294 "getValue()\n"
295 "\tReturns the value with which the actuator operates.\n";
296 PyObject* SCA_PropertyActuator::PyGetValue(PyObject* self, PyObject* args, PyObject* kwds)
297 {
298         return PyString_FromString(m_exprtxt);
299 }
300
301 /* eof */