patch 8235 8218 8211 added: various gameengine improvements, fixed windows project...
[blender.git] / source / gameengine / Ketsji / KX_IpoActuator.cpp
1 /**
2  * Do Ipo stuff
3  *
4  * $Id$
5  *
6  * ***** BEGIN GPL/BL DUAL 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. The Blender
12  * Foundation also sells licenses for use in proprietary software under
13  * the Blender License.  See http://www.blender.org/BL/ for information
14  * about this.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  *
25  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
26  * All rights reserved.
27  *
28  * The Original Code is: all of this file.
29  *
30  * Contributor(s): none yet.
31  *
32  * ***** END GPL/BL DUAL LICENSE BLOCK *****
33  */
34
35 #if defined (__sgi)
36 #include <math.h>
37 #else
38 #include <cmath>
39 #endif
40  
41 #include "KX_IpoActuator.h"
42 #include "KX_GameObject.h"
43
44 #ifdef HAVE_CONFIG_H
45 #include <config.h>
46 #endif
47
48 #include "KX_KetsjiEngine.h"
49
50 /* ------------------------------------------------------------------------- */
51 /* Type strings                                                              */
52 /* ------------------------------------------------------------------------- */
53
54 STR_String KX_IpoActuator::S_KX_ACT_IPO_PLAY_STRING      = "Play";
55 STR_String KX_IpoActuator::S_KX_ACT_IPO_PINGPONG_STRING  = "PingPong";
56 STR_String KX_IpoActuator::S_KX_ACT_IPO_FLIPPER_STRING   = "Flipper";
57 STR_String KX_IpoActuator::S_KX_ACT_IPO_LOOPSTOP_STRING  = "LoopStop";
58 STR_String KX_IpoActuator::S_KX_ACT_IPO_LOOPEND_STRING   = "LoopEnd";
59 STR_String KX_IpoActuator::S_KX_ACT_IPO_KEY2KEY_STRING   = "Key2key";
60 STR_String KX_IpoActuator::S_KX_ACT_IPO_FROM_PROP_STRING = "FromProp";
61
62 /* ------------------------------------------------------------------------- */
63 /* Native functions                                                          */
64 /* ------------------------------------------------------------------------- */
65 /** Another poltergeist? This seems to be a very transient class... */
66 class CIpoAction : public CAction
67 {
68         float           m_curtime;
69         bool            m_recurse;
70         KX_GameObject* m_gameobj;
71         bool        m_ipo_as_force;
72         bool        m_force_ipo_local;
73
74 public:
75         CIpoAction(KX_GameObject* gameobj,
76                 float curtime,
77                 bool recurse, 
78                 bool ipo_as_force,
79                 bool force_ipo_local) :
80           m_curtime(curtime) ,
81           m_recurse(recurse),
82           m_gameobj(gameobj),
83           m_ipo_as_force(ipo_as_force),
84           m_force_ipo_local(force_ipo_local) 
85           {
86                   /* intentionally empty */
87           };
88
89         virtual void Execute() const
90         {
91                 m_gameobj->UpdateIPO(
92                         m_curtime, 
93                         m_recurse, 
94                         m_ipo_as_force, 
95                         m_force_ipo_local);
96         };
97
98 };
99
100 KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj,
101                                                            const STR_String& propname,
102                                                            float starttime,
103                                                            float endtime,
104                                                            bool recurse,
105                                                            int acttype,
106                                                            bool ipo_as_force,
107                                                            bool force_ipo_local,
108                                                            PyTypeObject* T) 
109         : SCA_IActuator(gameobj,T),
110         m_bNegativeEvent(false),
111         m_startframe (starttime),
112         m_endframe(endtime),
113         m_recurse(recurse),
114         m_localtime(starttime),
115         m_direction(1),
116         m_propname(propname),
117         m_ipo_as_force(ipo_as_force),
118         m_force_ipo_local(force_ipo_local),
119         m_type((IpoActType)acttype)
120 {
121         m_starttime = -2.0*fabs(m_endframe - m_startframe) - 1.0;
122         m_bIpoPlaying = false;
123 }
124
125 void KX_IpoActuator::SetStart(float starttime) 
126
127         m_startframe=starttime;
128 }
129
130 void KX_IpoActuator::SetEnd(float endtime) 
131
132         m_endframe=endtime;
133 }
134
135 bool KX_IpoActuator::ClampLocalTime()
136 {
137         if (m_startframe < m_endframe)
138         {
139                 if (m_localtime < m_startframe)
140                 {
141                         m_localtime = m_startframe;
142                         return true;
143                 } 
144                 else if (m_localtime > m_endframe)
145                 {
146                         m_localtime = m_endframe;
147                         return true;
148                 }
149         } else {
150                 if (m_localtime > m_startframe)
151                 {
152                         m_localtime = m_startframe;
153                         return true;
154                 }
155                 else if (m_localtime < m_endframe)
156                 {
157                         m_localtime = m_endframe;
158                         return true;
159                 }
160         }
161         return false;
162 }
163
164 void KX_IpoActuator::SetStartTime(float curtime)
165 {
166         float direction = m_startframe < m_endframe ? 1.0 : -1.0;
167
168         curtime = curtime - KX_KetsjiEngine::GetSuspendedDelta();       
169         if (m_direction > 0)
170                 m_starttime = curtime - direction*(m_localtime - m_startframe)/KX_FIXED_FRAME_PER_SEC;
171         else
172                 m_starttime = curtime - direction*(m_endframe - m_localtime)/KX_FIXED_FRAME_PER_SEC;
173 }
174
175 void KX_IpoActuator::SetLocalTime(float curtime)
176 {
177         float delta_time = ((curtime - m_starttime) - KX_KetsjiEngine::GetSuspendedDelta())*KX_FIXED_FRAME_PER_SEC;
178         
179         // negative delta_time is caused by floating point inaccuracy
180         // perhaps the inaccuracy could be reduced a bit
181         if ((m_localtime==m_startframe || m_localtime==m_endframe) && delta_time<0.0)
182         {
183                 delta_time = 0.0;
184         }
185         
186         if (m_endframe < m_startframe)
187                 delta_time = -delta_time;
188
189         if (m_direction > 0)
190                 m_localtime = m_startframe + delta_time;
191         else
192                 m_localtime = m_endframe - delta_time;
193 }
194
195 bool KX_IpoActuator::Update(double curtime, bool frame)
196 {
197         // result = true if animation has to be continued, false if animation stops
198         // maybe there are events for us in the queue !
199         bool bNegativeEvent = false;
200         int numevents = 0;
201
202         if (frame)
203         {
204                 numevents = m_events.size();
205                 for (vector<CValue*>::iterator i=m_events.end(); !(i==m_events.begin());)
206                 {
207                         --i;
208                         if ((*i)->GetNumber() == 0.0f)
209                                 bNegativeEvent = true;
210                         
211                         (*i)->Release();
212                 }
213                 m_events.clear();
214         }
215         
216         double  start_smaller_then_end = ( m_startframe < m_endframe ? 1.0 : -1.0);
217
218         bool result=true;
219         if (!bNegativeEvent)
220         {
221                 if (m_starttime < -2.0*start_smaller_then_end*(m_endframe - m_startframe))
222                 {
223                         // start for all Ipo, initial start for LOOP_STOP
224                         m_starttime = curtime - KX_KetsjiEngine::GetSuspendedDelta();
225                         m_bIpoPlaying = true;
226                 }
227         }       
228
229         switch (m_type)
230         {
231                 
232         case KX_ACT_IPO_PLAY:
233         {
234                 // Check if playing forwards.  result = ! finished
235                 
236                 if (start_smaller_then_end > 0.0)
237                         result = (m_localtime < m_endframe && m_bIpoPlaying);
238                 else
239                         result = (m_localtime > m_endframe && m_bIpoPlaying);
240                 
241                 if (result)
242                 {
243                         SetLocalTime(curtime);
244                 
245                         /* Perform clamping */
246                         ClampLocalTime();
247                         
248                         CIpoAction ipoaction(
249                                 (KX_GameObject*)GetParent(), 
250                                 m_localtime, 
251                                 m_recurse, 
252                                 m_ipo_as_force,
253                                 m_force_ipo_local);
254                         GetParent()->Execute(ipoaction);
255                 } else
256                 {
257                         m_localtime=m_startframe;
258                         m_direction=1;
259                 }
260                 break;
261         }
262         case KX_ACT_IPO_PINGPONG:
263         {
264                 result = true;
265                 if (bNegativeEvent && !m_bIpoPlaying)
266                         result = false;
267                 else
268                         SetLocalTime(curtime);
269                         
270                 if (ClampLocalTime())
271                 {
272                         result = false;
273                         m_direction = -m_direction;
274                 }
275                 
276                 CIpoAction ipoaction(
277                         (KX_GameObject*) GetParent(),
278                         m_localtime,
279                         m_recurse, 
280                         m_ipo_as_force,
281                         m_force_ipo_local);
282                 GetParent()->Execute(ipoaction);
283                 break;
284         }
285         case KX_ACT_IPO_FLIPPER:
286         {
287                 if (bNegativeEvent && !m_bIpoPlaying)
288                         result = false;
289                 if (numevents)
290                 {
291                         float oldDirection = m_direction;
292                         if (bNegativeEvent)
293                                 m_direction = -1;
294                         else
295                                 m_direction = 1;
296                         if (m_direction != oldDirection)
297                                 // changing direction, reset start time
298                                 SetStartTime(curtime);
299                 }
300                 
301                 SetLocalTime(curtime);
302                 
303                 if (ClampLocalTime() && m_localtime == m_startframe)
304                         result = false;
305                         
306                 CIpoAction ipoaction(
307                         (KX_GameObject*) GetParent(),
308                         m_localtime,
309                         m_recurse,
310                         m_ipo_as_force,
311                         m_force_ipo_local);
312                 GetParent()->Execute(ipoaction);
313                 break;
314         }
315
316         case KX_ACT_IPO_LOOPSTOP:
317         {
318                 if (numevents)
319                 {
320                         if (bNegativeEvent)
321                         {
322                                 result = false;
323                                 m_bNegativeEvent = false;
324                                 numevents = 0;
325                         }
326                         if (!m_bIpoPlaying)
327                         {
328                                 // Ipo was stopped, make sure we will restart from where it stopped
329                                 SetStartTime(curtime);
330                                 if (!bNegativeEvent)
331                                         // positive signal will restart the Ipo
332                                         m_bIpoPlaying = true;
333                         }
334
335                 } // fall through to loopend, and quit the ipo animation immediatly 
336         }
337         case KX_ACT_IPO_LOOPEND:
338         {
339                 if (numevents){
340                         if (bNegativeEvent && m_bIpoPlaying){
341                                 m_bNegativeEvent = true;
342                         }
343                 }
344                 
345                 if (bNegativeEvent && !m_bIpoPlaying){
346                         result = false;
347                 } 
348                 else
349                 {
350                         if (m_localtime*start_smaller_then_end < m_endframe*start_smaller_then_end)
351                         {
352                                 SetLocalTime(curtime);
353                         }
354                         else{
355                                 if (!m_bNegativeEvent){
356                                         /* Perform wraparound */
357                                         SetLocalTime(curtime);
358                                         m_localtime = m_startframe + fmod(m_localtime, m_startframe - m_endframe);
359                                         SetStartTime(curtime);
360                                 }
361                                 else
362                                 {       
363                                         /* Perform clamping */
364                                         m_localtime=m_endframe;
365                                         result = false;
366                                         m_bNegativeEvent = false;
367                                 }
368                         }
369                 }
370                 
371                 CIpoAction ipoaction(
372                         (KX_GameObject*) GetParent(),
373                         m_localtime,
374                         m_recurse,
375                         m_ipo_as_force,
376                         m_force_ipo_local);
377                 GetParent()->Execute(ipoaction);
378                 break;
379         }
380         
381         case KX_ACT_IPO_KEY2KEY:
382         {
383                 // not implemented yet
384                 result = false;
385                 break;
386         }
387         
388         case KX_ACT_IPO_FROM_PROP:
389         {
390                 result = !bNegativeEvent;
391
392                 CValue* propval = GetParent()->GetProperty(m_propname);
393                 if (propval)
394                 {
395                         m_localtime = propval->GetNumber(); 
396         
397                         CIpoAction ipoaction(
398                                 (KX_GameObject*) GetParent(),
399                                 m_localtime,
400                                 m_recurse,
401                                 m_ipo_as_force,
402                                 m_force_ipo_local);
403                         GetParent()->Execute(ipoaction);
404
405                 } else
406                 {
407                         result = false;
408                 }
409                 break;
410         }
411                 
412         default:
413                 result = false;
414         }
415         
416         if (!result)
417         {
418                 if (m_type != KX_ACT_IPO_LOOPSTOP)
419                         m_starttime = -2.0*start_smaller_then_end*(m_endframe - m_startframe) - 1.0;
420                 m_bIpoPlaying = false;
421         }
422
423         return result;
424 }
425
426 KX_IpoActuator::IpoActType KX_IpoActuator::string2mode(char* modename) {
427         IpoActType res = KX_ACT_IPO_NODEF;
428
429         if (modename == S_KX_ACT_IPO_PLAY_STRING) { 
430                 res = KX_ACT_IPO_PLAY;
431         } else if (modename == S_KX_ACT_IPO_PINGPONG_STRING) {
432                 res = KX_ACT_IPO_PINGPONG;
433         } else if (modename == S_KX_ACT_IPO_FLIPPER_STRING) {
434                 res = KX_ACT_IPO_FLIPPER;
435         } else if (modename == S_KX_ACT_IPO_LOOPSTOP_STRING) {
436                 res = KX_ACT_IPO_LOOPSTOP;
437         } else if (modename == S_KX_ACT_IPO_LOOPEND_STRING) {
438                 res = KX_ACT_IPO_LOOPEND;
439         } else if (modename == S_KX_ACT_IPO_KEY2KEY_STRING) {
440                 res = KX_ACT_IPO_KEY2KEY;
441         } else if (modename == S_KX_ACT_IPO_FROM_PROP_STRING) {
442                 res = KX_ACT_IPO_FROM_PROP;
443         }
444
445         return res;
446 }
447
448 /* ------------------------------------------------------------------------- */
449 /* Python functions                                                          */
450 /* ------------------------------------------------------------------------- */
451
452
453
454 /* Integration hooks ------------------------------------------------------- */
455 PyTypeObject KX_IpoActuator::Type = {
456         PyObject_HEAD_INIT(&PyType_Type)
457         0,
458         "KX_IpoActuator",
459         sizeof(KX_IpoActuator),
460         0,
461         PyDestructor,
462         0,
463         __getattr,
464         __setattr,
465         0, //&MyPyCompare,
466         __repr,
467         0, //&cvalue_as_number,
468         0,
469         0,
470         0,
471         0
472 };
473
474 PyParentObject KX_IpoActuator::Parents[] = {
475         &KX_IpoActuator::Type,
476         &SCA_IActuator::Type,
477         &SCA_ILogicBrick::Type,
478         &CValue::Type,
479         NULL
480 };
481
482 PyMethodDef KX_IpoActuator::Methods[] = {
483         {"set", (PyCFunction) KX_IpoActuator::sPySet, 
484                 METH_VARARGS, Set_doc},
485         {"setProperty", (PyCFunction) KX_IpoActuator::sPySetProperty, 
486                 METH_VARARGS, SetProperty_doc},
487         {"setStart", (PyCFunction) KX_IpoActuator::sPySetStart, 
488                 METH_VARARGS, SetStart_doc},
489         {"getStart", (PyCFunction) KX_IpoActuator::sPyGetStart, 
490                 METH_VARARGS, GetStart_doc},
491         {"setEnd", (PyCFunction) KX_IpoActuator::sPySetEnd, 
492                 METH_VARARGS, SetEnd_doc},
493         {"getEnd", (PyCFunction) KX_IpoActuator::sPyGetEnd, 
494                 METH_VARARGS, GetEnd_doc},
495         {"setIpoAsForce", (PyCFunction) KX_IpoActuator::sPySetIpoAsForce, 
496                 METH_VARARGS, SetIpoAsForce_doc},
497         {"getIpoAsForce", (PyCFunction) KX_IpoActuator::sPyGetIpoAsForce, 
498                 METH_VARARGS, GetIpoAsForce_doc},
499         {"setType", (PyCFunction) KX_IpoActuator::sPySetType, 
500                 METH_VARARGS, SetType_doc},
501         {"getType", (PyCFunction) KX_IpoActuator::sPyGetType, 
502                 METH_VARARGS, GetType_doc},     
503         {"setForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPySetForceIpoActsLocal,
504                 METH_VARARGS, SetForceIpoActsLocal_doc},
505         {"getForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPyGetForceIpoActsLocal,
506                 METH_VARARGS, GetForceIpoActsLocal_doc},
507         {NULL,NULL} //Sentinel
508 };
509
510 PyObject* KX_IpoActuator::_getattr(const STR_String& attr) {
511         _getattr_up(SCA_IActuator);
512 }
513
514
515
516 /* set --------------------------------------------------------------------- */
517 char KX_IpoActuator::Set_doc[] = 
518 "set(mode, startframe, endframe, force?)\n"
519 "\t - mode:       Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n"
520 "\t - startframe: first frame to use (int)\n"
521 "\t - endframe  : last frame to use (int)\n"
522 "\t - force?    : interpret this ipo as a force? (KX_TRUE, KX_FALSE)"
523 "\tSet the properties of the actuator.\n";
524 PyObject* KX_IpoActuator::PySet(PyObject* self, 
525                                                                 PyObject* args, 
526                                                                 PyObject* kwds) {
527         /* sets modes PLAY, PINGPONG, FLIPPER, LOOPSTOP, LOOPEND                 */
528         /* arg 1 = mode string, arg 2 = startframe, arg3 = stopframe,            */
529         /* arg4 = force toggle                                                   */
530         char* mode;
531         int forceToggle;
532         IpoActType modenum;
533         int startFrame, stopFrame;
534         if(!PyArg_ParseTuple(args, "siii", &mode, &startFrame, 
535                                                  &stopFrame, &forceToggle)) {
536                 return NULL;
537         }
538         modenum = string2mode(mode);
539         
540         switch (modenum) {
541         case KX_ACT_IPO_PLAY:
542         case KX_ACT_IPO_PINGPONG:
543         case KX_ACT_IPO_FLIPPER:
544         case KX_ACT_IPO_LOOPSTOP:
545         case KX_ACT_IPO_LOOPEND:
546                 m_type         = modenum;
547                 m_startframe    = startFrame;
548                 m_endframe      = stopFrame;
549                 m_ipo_as_force = PyArgToBool(forceToggle);
550                 break;
551         default:
552                 ; /* error */
553         }
554
555         Py_Return;
556 }
557
558 /* set property  ----------------------------------------------------------- */
559 char KX_IpoActuator::SetProperty_doc[] = 
560 "setProperty(propname)\n"
561 "\t - propname: name of the property (string)\n"
562 "\tSet the property to be used in FromProp mode.\n";
563 PyObject* KX_IpoActuator::PySetProperty(PyObject* self, 
564                                                                                 PyObject* args, 
565                                                                                 PyObject* kwds) {
566         /* mode is implicit here, but not supported yet... */
567         /* args: property */
568         char *propertyName;
569         if(!PyArg_ParseTuple(args, "s", &propertyName)) {
570                 return NULL;
571         }
572
573         m_propname = propertyName;
574         
575         Py_Return;
576 }
577
578 /* 4. setStart:                                                              */
579 char KX_IpoActuator::SetStart_doc[] = 
580 "setStart(frame)\n"
581 "\t - frame: first frame to use (int)\n"
582 "\tSet the frame from which the ipo starts playing.\n";
583 PyObject* KX_IpoActuator::PySetStart(PyObject* self, 
584                                                                          PyObject* args, 
585                                                                          PyObject* kwds) {
586         float startArg;
587         if(!PyArg_ParseTuple(args, "f", &startArg)) {
588                 return NULL;            
589         }
590         
591         m_startframe = startArg;
592
593         Py_Return;
594 }
595 /* 5. getStart:                                                              */
596 char KX_IpoActuator::GetStart_doc[] = 
597 "getStart()\n"
598 "\tReturns the frame from which the ipo starts playing.\n";
599 PyObject* KX_IpoActuator::PyGetStart(PyObject* self, 
600                                                                          PyObject* args, 
601                                                                          PyObject* kwds) {
602         return PyFloat_FromDouble(m_startframe);
603 }
604
605 /* 6. setEnd:                                                                */
606 char KX_IpoActuator::SetEnd_doc[] = 
607 "setEnd(frame)\n"
608 "\t - frame: last frame to use (int)\n"
609 "\tSet the frame at which the ipo stops playing.\n";
610 PyObject* KX_IpoActuator::PySetEnd(PyObject* self, 
611                                                                    PyObject* args, 
612                                                                    PyObject* kwds) {
613         float endArg;
614         if(!PyArg_ParseTuple(args, "f", &endArg)) {
615                 return NULL;            
616         }
617         
618         m_endframe = endArg;
619
620         Py_Return;
621 }
622 /* 7. getEnd:                                                                */
623 char KX_IpoActuator::GetEnd_doc[] = 
624 "getEnd()\n"
625 "\tReturns the frame at which the ipo stops playing.\n";
626 PyObject* KX_IpoActuator::PyGetEnd(PyObject* self, 
627                                                                    PyObject* args, 
628                                                                    PyObject* kwds) {
629         return PyFloat_FromDouble(m_endframe);
630 }
631
632 /* 6. setIpoAsForce:                                                           */
633 char KX_IpoActuator::SetIpoAsForce_doc[] = 
634 "setIpoAsForce(force?)\n"
635 "\t - force?    : interpret this ipo as a force? (KX_TRUE, KX_FALSE)\n"
636 "\tSet whether to interpret the ipo as a force rather than a displacement.\n";
637 PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self, 
638                                                                                   PyObject* args, 
639                                                                                   PyObject* kwds) { 
640         int boolArg;
641         
642         if (!PyArg_ParseTuple(args, "i", &boolArg)) {
643                 return NULL;
644         }
645
646         m_ipo_as_force = PyArgToBool(boolArg);
647         
648         Py_Return;      
649 }
650 /* 7. getIpoAsForce:                                                         */
651 char KX_IpoActuator::GetIpoAsForce_doc[] = 
652 "getIpoAsForce()\n"
653 "\tReturns whether to interpret the ipo as a force rather than a displacement.\n";
654 PyObject* KX_IpoActuator::PyGetIpoAsForce(PyObject* self, 
655                                                                                   PyObject* args, 
656                                                                                   PyObject* kwds) {
657         return BoolToPyArg(m_ipo_as_force);
658 }
659
660 /* 8. setType:                                                               */
661 char KX_IpoActuator::SetType_doc[] = 
662 "setType(mode)\n"
663 "\t - mode: Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n"
664 "\tSet the operation mode of the actuator.\n";
665 PyObject* KX_IpoActuator::PySetType(PyObject* self, 
666                                                                         PyObject* args, 
667                                                                         PyObject* kwds) {
668         int typeArg;
669         
670         if (!PyArg_ParseTuple(args, "i", &typeArg)) {
671                 return NULL;
672         }
673         
674         if ( (typeArg > KX_ACT_IPO_NODEF) 
675                  && (typeArg < KX_ACT_IPO_KEY2KEY) ) {
676                 m_type = (IpoActType) typeArg;
677         }
678         
679         Py_Return;
680 }
681 /* 9. getType:                                                               */
682 char KX_IpoActuator::GetType_doc[] = 
683 "getType()\n"
684 "\tReturns the operation mode of the actuator.\n";
685 PyObject* KX_IpoActuator::PyGetType(PyObject* self, 
686                                                                         PyObject* args, 
687                                                                         PyObject* kwds) {
688         return PyInt_FromLong(m_type);
689 }
690
691 /* 10. setForceIpoActsLocal:                                                 */
692 char KX_IpoActuator::SetForceIpoActsLocal_doc[] = 
693 "setForceIpoActsLocal(local?)\n"
694 "\t - local?    : Apply the ipo-as-force in the object's local\n"
695 "\t               coordinates? (KX_TRUE, KX_FALSE)\n"
696 "\tSet whether to apply the force in the object's local\n"
697 "\tcoordinates rather than the world global coordinates.\n";
698 PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* self, 
699                                                                                          PyObject* args, 
700                                                                                      PyObject* kwds) { 
701         int boolArg;
702         
703         if (!PyArg_ParseTuple(args, "i", &boolArg)) {
704                 return NULL;
705         }
706
707         m_force_ipo_local = PyArgToBool(boolArg);
708         
709         Py_Return;      
710 }
711 /* 11. getForceIpoActsLocal:                                                */
712 char KX_IpoActuator::GetForceIpoActsLocal_doc[] = 
713 "getForceIpoActsLocal()\n"
714 "\tReturn whether to apply the force in the object's local\n"
715 "\tcoordinates rather than the world global coordinates.\n";
716 PyObject* KX_IpoActuator::PyGetForceIpoActsLocal(PyObject* self, 
717                                                                                          PyObject* args, 
718                                                                                          PyObject* kwds) {
719         return BoolToPyArg(m_force_ipo_local);
720 }
721
722
723 /* eof */