Merge of itasc branch. Project files, scons and cmake should be working. Makefile...
[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)
46    :    SCA_IActuator(gameobj, KX_ACT_PROPERTY),
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         PyVarObject_HEAD_INIT(NULL, 0)
232         "SCA_PropertyActuator",
233         sizeof(PyObjectPlus_Proxy),
234         0,
235         py_base_dealloc,
236         0,
237         0,
238         0,
239         0,
240         py_base_repr,
241         0,0,0,0,0,0,0,0,0,
242         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
243         0,0,0,0,0,0,0,
244         Methods,
245         0,
246         0,
247         &SCA_IActuator::Type,
248         0,0,0,0,0,0,
249         py_base_new
250 };
251
252 PyMethodDef SCA_PropertyActuator::Methods[] = {
253         {NULL,NULL} //Sentinel
254 };
255
256 PyAttributeDef SCA_PropertyActuator::Attributes[] = {
257         KX_PYATTRIBUTE_STRING_RW_CHECK("propName",0,100,false,SCA_PropertyActuator,m_propname,CheckProperty),
258         KX_PYATTRIBUTE_STRING_RW("value",0,100,false,SCA_PropertyActuator,m_exprtxt),
259         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 */
260         { NULL }        //Sentinel
261 };
262
263 /* eof */