e7f1dea7bbf6a7d5356560b3b7c1132c0a00022e
[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                 if (m_type != KX_ACT_IPO_PLAY)
216                 {
217                         if (bNegativeEvent)
218                                 RemoveAllEvents();
219                 }
220         }
221         
222         double  start_smaller_then_end = ( m_startframe < m_endframe ? 1.0 : -1.0);
223
224         bool result=true;
225         if (!bNegativeEvent)
226         {
227                 if (m_starttime < -2.0*start_smaller_then_end*(m_endframe - m_startframe))
228                 {
229                         m_starttime = curtime - KX_KetsjiEngine::GetSuspendedDelta();
230                         m_bIpoPlaying = true;
231                 }
232         }       
233
234         switch (m_type)
235         {
236                 
237         case KX_ACT_IPO_PLAY:
238         {
239                 // Check if playing forwards.  result = ! finished
240                 
241                 if (!bNegativeEvent)
242                 {
243                         if (start_smaller_then_end > 0.0)
244                                 result = (m_localtime < m_endframe && !(m_localtime == m_startframe && bNegativeEvent));
245                         else
246                                 result = (m_localtime > m_endframe && !(m_localtime == m_startframe && bNegativeEvent));
247                 }
248                 else
249                 {
250                         result = (m_bIpoPlaying && (m_localtime < m_endframe));
251                 }
252                 
253                 if (result)
254                 {
255                         SetLocalTime(curtime);
256                 
257                         /* Perform clamping */
258                         ClampLocalTime();
259                         
260                         CIpoAction ipoaction(
261                                 (KX_GameObject*)GetParent(), 
262                                 m_localtime, 
263                                 m_recurse, 
264                                 m_ipo_as_force,
265                                 m_force_ipo_local);
266                         GetParent()->Execute(ipoaction);
267                 } else
268                 {
269                         m_localtime=m_startframe;
270                         SetStartTime(curtime);
271                         m_direction=1;
272                 }
273                 break;
274         }
275         case KX_ACT_IPO_PINGPONG:
276         {
277                 result = true;
278                 if (bNegativeEvent && ((m_localtime == m_startframe )|| (m_localtime == m_endframe)))
279                         result = false;
280                 else
281                         SetLocalTime(curtime);
282                         
283                 if (ClampLocalTime())
284                 {
285                         result = false;
286                         m_direction = -m_direction;
287                 }
288                 
289                 CIpoAction ipoaction(
290                         (KX_GameObject*) GetParent(),
291                         m_localtime,
292                         m_recurse, 
293                         m_ipo_as_force,
294                         m_force_ipo_local);
295                 GetParent()->Execute(ipoaction);
296                 break;
297         }
298         case KX_ACT_IPO_FLIPPER:
299         {
300                 result = !(bNegativeEvent && (m_localtime == m_startframe));
301                 if (numevents)
302                 {
303                         if (bNegativeEvent)
304                                 m_direction = -1;
305                         else
306                                 m_direction = 1;
307                         SetStartTime(curtime);
308                 }
309                 
310                 SetLocalTime(curtime);
311                 
312                 if (ClampLocalTime() && m_localtime == m_startframe)
313                         result = false;
314                         
315                 CIpoAction ipoaction(
316                         (KX_GameObject*) GetParent(),
317                         m_localtime,
318                         m_recurse,
319                         m_ipo_as_force,
320                         m_force_ipo_local);
321                 GetParent()->Execute(ipoaction);
322                 break;
323         }
324
325         case KX_ACT_IPO_LOOPSTOP:
326         {
327                 if (numevents)
328                 {
329                         if (bNegativeEvent)
330                         {
331                                 result = false;
332                                 m_bNegativeEvent = false;
333                                 numevents = 0;
334                         }
335                         SetStartTime(curtime);
336                 } // fall through to loopend, and quit the ipo animation immediatly 
337         }
338         case KX_ACT_IPO_LOOPEND:
339         {
340                 if (numevents){
341                         if (bNegativeEvent){
342                                 m_bNegativeEvent = true;
343                         }
344                 }
345                 
346                 if (bNegativeEvent && m_localtime == m_startframe){
347                         result = false;
348                 } 
349                 else
350                 {
351                         if (m_localtime*start_smaller_then_end < m_endframe*start_smaller_then_end)
352                         {
353                                 SetLocalTime(curtime);
354                         }
355                         else{
356                                 if (!m_bNegativeEvent){
357                                         /* Perform wraparound */
358                                         SetLocalTime(curtime);
359                                         m_localtime = m_startframe + fmod(m_localtime, m_startframe - m_endframe);
360                                         SetStartTime(curtime);
361                                 }
362                                 else
363                                 {       
364                                         /* Perform clamping */
365                                         m_localtime=m_endframe;
366                                         result = false;
367                                         m_bNegativeEvent = false;
368                                 }
369                         }
370                 }
371                 
372                 CIpoAction ipoaction(
373                         (KX_GameObject*) GetParent(),
374                         m_localtime,
375                         m_recurse,
376                         m_ipo_as_force,
377                         m_force_ipo_local);
378                 GetParent()->Execute(ipoaction);
379                 break;
380         }
381         
382         case KX_ACT_IPO_KEY2KEY:
383         {
384                 // not implemented yet
385                 result = false;
386                 break;
387         }
388         
389         case KX_ACT_IPO_FROM_PROP:
390         {
391                 result = !bNegativeEvent;
392
393                 CValue* propval = GetParent()->GetProperty(m_propname);
394                 if (propval)
395                 {
396                         m_localtime = propval->GetNumber(); 
397         
398                         CIpoAction ipoaction(
399                                 (KX_GameObject*) GetParent(),
400                                 m_localtime,
401                                 m_recurse,
402                                 m_ipo_as_force,
403                                 m_force_ipo_local);
404                         GetParent()->Execute(ipoaction);
405
406                 } else
407                 {
408                         result = false;
409                 }
410                 break;
411         }
412                 
413         default:
414                 result = false;
415         }
416         
417         if (!result && m_type != KX_ACT_IPO_LOOPSTOP)
418                 m_starttime = -2.0*start_smaller_then_end*(m_endframe - m_startframe) - 1.0;
419
420         return result;
421 }
422
423 KX_IpoActuator::IpoActType KX_IpoActuator::string2mode(char* modename) {
424         IpoActType res = KX_ACT_IPO_NODEF;
425
426         if (modename == S_KX_ACT_IPO_PLAY_STRING) { 
427                 res = KX_ACT_IPO_PLAY;
428         } else if (modename == S_KX_ACT_IPO_PINGPONG_STRING) {
429                 res = KX_ACT_IPO_PINGPONG;
430         } else if (modename == S_KX_ACT_IPO_FLIPPER_STRING) {
431                 res = KX_ACT_IPO_FLIPPER;
432         } else if (modename == S_KX_ACT_IPO_LOOPSTOP_STRING) {
433                 res = KX_ACT_IPO_LOOPSTOP;
434         } else if (modename == S_KX_ACT_IPO_LOOPEND_STRING) {
435                 res = KX_ACT_IPO_LOOPEND;
436         } else if (modename == S_KX_ACT_IPO_KEY2KEY_STRING) {
437                 res = KX_ACT_IPO_KEY2KEY;
438         } else if (modename == S_KX_ACT_IPO_FROM_PROP_STRING) {
439                 res = KX_ACT_IPO_FROM_PROP;
440         }
441
442         return res;
443 }
444
445 /* ------------------------------------------------------------------------- */
446 /* Python functions                                                          */
447 /* ------------------------------------------------------------------------- */
448
449
450
451 /* Integration hooks ------------------------------------------------------- */
452 PyTypeObject KX_IpoActuator::Type = {
453         PyObject_HEAD_INIT(&PyType_Type)
454         0,
455         "KX_IpoActuator",
456         sizeof(KX_IpoActuator),
457         0,
458         PyDestructor,
459         0,
460         __getattr,
461         __setattr,
462         0, //&MyPyCompare,
463         __repr,
464         0, //&cvalue_as_number,
465         0,
466         0,
467         0,
468         0
469 };
470
471 PyParentObject KX_IpoActuator::Parents[] = {
472         &KX_IpoActuator::Type,
473         &SCA_IActuator::Type,
474         &SCA_ILogicBrick::Type,
475         &CValue::Type,
476         NULL
477 };
478
479 PyMethodDef KX_IpoActuator::Methods[] = {
480         {"set", (PyCFunction) KX_IpoActuator::sPySet, 
481                 METH_VARARGS, Set_doc},
482         {"setProperty", (PyCFunction) KX_IpoActuator::sPySetProperty, 
483                 METH_VARARGS, SetProperty_doc},
484         {"setStart", (PyCFunction) KX_IpoActuator::sPySetStart, 
485                 METH_VARARGS, SetStart_doc},
486         {"getStart", (PyCFunction) KX_IpoActuator::sPyGetStart, 
487                 METH_VARARGS, GetStart_doc},
488         {"setEnd", (PyCFunction) KX_IpoActuator::sPySetEnd, 
489                 METH_VARARGS, SetEnd_doc},
490         {"getEnd", (PyCFunction) KX_IpoActuator::sPyGetEnd, 
491                 METH_VARARGS, GetEnd_doc},
492         {"setIpoAsForce", (PyCFunction) KX_IpoActuator::sPySetIpoAsForce, 
493                 METH_VARARGS, SetIpoAsForce_doc},
494         {"getIpoAsForce", (PyCFunction) KX_IpoActuator::sPyGetIpoAsForce, 
495                 METH_VARARGS, GetIpoAsForce_doc},
496         {"setType", (PyCFunction) KX_IpoActuator::sPySetType, 
497                 METH_VARARGS, SetType_doc},
498         {"getType", (PyCFunction) KX_IpoActuator::sPyGetType, 
499                 METH_VARARGS, GetType_doc},     
500         {"setForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPySetForceIpoActsLocal,
501                 METH_VARARGS, SetForceIpoActsLocal_doc},
502         {"getForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPyGetForceIpoActsLocal,
503                 METH_VARARGS, GetForceIpoActsLocal_doc},
504         {NULL,NULL} //Sentinel
505 };
506
507 PyObject* KX_IpoActuator::_getattr(const STR_String& attr) {
508         _getattr_up(SCA_IActuator);
509 }
510
511
512
513 /* set --------------------------------------------------------------------- */
514 char KX_IpoActuator::Set_doc[] = 
515 "set(mode, startframe, endframe, force?)\n"
516 "\t - mode:       Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n"
517 "\t - startframe: first frame to use (int)\n"
518 "\t - endframe  : last frame to use (int)\n"
519 "\t - force?    : interpret this ipo as a force? (KX_TRUE, KX_FALSE)"
520 "\tSet the properties of the actuator.\n";
521 PyObject* KX_IpoActuator::PySet(PyObject* self, 
522                                                                 PyObject* args, 
523                                                                 PyObject* kwds) {
524         /* sets modes PLAY, PINGPONG, FLIPPER, LOOPSTOP, LOOPEND                 */
525         /* arg 1 = mode string, arg 2 = startframe, arg3 = stopframe,            */
526         /* arg4 = force toggle                                                   */
527         char* mode;
528         int forceToggle;
529         IpoActType modenum;
530         int startFrame, stopFrame;
531         if(!PyArg_ParseTuple(args, "siii", &mode, &startFrame, 
532                                                  &stopFrame, &forceToggle)) {
533                 return NULL;
534         }
535         modenum = string2mode(mode);
536         
537         switch (modenum) {
538         case KX_ACT_IPO_PLAY:
539         case KX_ACT_IPO_PINGPONG:
540         case KX_ACT_IPO_FLIPPER:
541         case KX_ACT_IPO_LOOPSTOP:
542         case KX_ACT_IPO_LOOPEND:
543                 m_type         = modenum;
544                 m_startframe    = startFrame;
545                 m_endframe      = stopFrame;
546                 m_ipo_as_force = PyArgToBool(forceToggle);
547                 break;
548         default:
549                 ; /* error */
550         }
551
552         Py_Return;
553 }
554
555 /* set property  ----------------------------------------------------------- */
556 char KX_IpoActuator::SetProperty_doc[] = 
557 "setProperty(propname)\n"
558 "\t - propname: name of the property (string)\n"
559 "\tSet the property to be used in FromProp mode.\n";
560 PyObject* KX_IpoActuator::PySetProperty(PyObject* self, 
561                                                                                 PyObject* args, 
562                                                                                 PyObject* kwds) {
563         /* mode is implicit here, but not supported yet... */
564         /* args: property */
565         char *propertyName;
566         if(!PyArg_ParseTuple(args, "s", &propertyName)) {
567                 return NULL;
568         }
569
570         m_propname = propertyName;
571         
572         Py_Return;
573 }
574
575 /* 4. setStart:                                                              */
576 char KX_IpoActuator::SetStart_doc[] = 
577 "setStart(frame)\n"
578 "\t - frame: first frame to use (int)\n"
579 "\tSet the frame from which the ipo starts playing.\n";
580 PyObject* KX_IpoActuator::PySetStart(PyObject* self, 
581                                                                          PyObject* args, 
582                                                                          PyObject* kwds) {
583         float startArg;
584         if(!PyArg_ParseTuple(args, "f", &startArg)) {
585                 return NULL;            
586         }
587         
588         m_startframe = startArg;
589
590         Py_Return;
591 }
592 /* 5. getStart:                                                              */
593 char KX_IpoActuator::GetStart_doc[] = 
594 "getStart()\n"
595 "\tReturns the frame from which the ipo starts playing.\n";
596 PyObject* KX_IpoActuator::PyGetStart(PyObject* self, 
597                                                                          PyObject* args, 
598                                                                          PyObject* kwds) {
599         return PyFloat_FromDouble(m_startframe);
600 }
601
602 /* 6. setEnd:                                                                */
603 char KX_IpoActuator::SetEnd_doc[] = 
604 "setEnd(frame)\n"
605 "\t - frame: last frame to use (int)\n"
606 "\tSet the frame at which the ipo stops playing.\n";
607 PyObject* KX_IpoActuator::PySetEnd(PyObject* self, 
608                                                                    PyObject* args, 
609                                                                    PyObject* kwds) {
610         float endArg;
611         if(!PyArg_ParseTuple(args, "f", &endArg)) {
612                 return NULL;            
613         }
614         
615         m_endframe = endArg;
616
617         Py_Return;
618 }
619 /* 7. getEnd:                                                                */
620 char KX_IpoActuator::GetEnd_doc[] = 
621 "getEnd()\n"
622 "\tReturns the frame at which the ipo stops playing.\n";
623 PyObject* KX_IpoActuator::PyGetEnd(PyObject* self, 
624                                                                    PyObject* args, 
625                                                                    PyObject* kwds) {
626         return PyFloat_FromDouble(m_endframe);
627 }
628
629 /* 6. setIpoAsForce:                                                           */
630 char KX_IpoActuator::SetIpoAsForce_doc[] = 
631 "setIpoAsForce(force?)\n"
632 "\t - force?    : interpret this ipo as a force? (KX_TRUE, KX_FALSE)\n"
633 "\tSet whether to interpret the ipo as a force rather than a displacement.\n";
634 PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self, 
635                                                                                   PyObject* args, 
636                                                                                   PyObject* kwds) { 
637         int boolArg;
638         
639         if (!PyArg_ParseTuple(args, "i", &boolArg)) {
640                 return NULL;
641         }
642
643         m_ipo_as_force = PyArgToBool(boolArg);
644         
645         Py_Return;      
646 }
647 /* 7. getIpoAsForce:                                                         */
648 char KX_IpoActuator::GetIpoAsForce_doc[] = 
649 "getIpoAsForce()\n"
650 "\tReturns whether to interpret the ipo as a force rather than a displacement.\n";
651 PyObject* KX_IpoActuator::PyGetIpoAsForce(PyObject* self, 
652                                                                                   PyObject* args, 
653                                                                                   PyObject* kwds) {
654         return BoolToPyArg(m_ipo_as_force);
655 }
656
657 /* 8. setType:                                                               */
658 char KX_IpoActuator::SetType_doc[] = 
659 "setType(mode)\n"
660 "\t - mode: Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n"
661 "\tSet the operation mode of the actuator.\n";
662 PyObject* KX_IpoActuator::PySetType(PyObject* self, 
663                                                                         PyObject* args, 
664                                                                         PyObject* kwds) {
665         int typeArg;
666         
667         if (!PyArg_ParseTuple(args, "i", &typeArg)) {
668                 return NULL;
669         }
670         
671         if ( (typeArg > KX_ACT_IPO_NODEF) 
672                  && (typeArg < KX_ACT_IPO_KEY2KEY) ) {
673                 m_type = (IpoActType) typeArg;
674         }
675         
676         Py_Return;
677 }
678 /* 9. getType:                                                               */
679 char KX_IpoActuator::GetType_doc[] = 
680 "getType()\n"
681 "\tReturns the operation mode of the actuator.\n";
682 PyObject* KX_IpoActuator::PyGetType(PyObject* self, 
683                                                                         PyObject* args, 
684                                                                         PyObject* kwds) {
685         return PyInt_FromLong(m_type);
686 }
687
688 /* 10. setForceIpoActsLocal:                                                 */
689 char KX_IpoActuator::SetForceIpoActsLocal_doc[] = 
690 "setForceIpoActsLocal(local?)\n"
691 "\t - local?    : Apply the ipo-as-force in the object's local\n"
692 "\t               coordinates? (KX_TRUE, KX_FALSE)\n"
693 "\tSet whether to apply the force in the object's local\n"
694 "\tcoordinates rather than the world global coordinates.\n";
695 PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* self, 
696                                                                                          PyObject* args, 
697                                                                                      PyObject* kwds) { 
698         int boolArg;
699         
700         if (!PyArg_ParseTuple(args, "i", &boolArg)) {
701                 return NULL;
702         }
703
704         m_force_ipo_local = PyArgToBool(boolArg);
705         
706         Py_Return;      
707 }
708 /* 11. getForceIpoActsLocal:                                                */
709 char KX_IpoActuator::GetForceIpoActsLocal_doc[] = 
710 "getForceIpoActsLocal()\n"
711 "\tReturn whether to apply the force in the object's local\n"
712 "\tcoordinates rather than the world global coordinates.\n";
713 PyObject* KX_IpoActuator::PyGetForceIpoActsLocal(PyObject* self, 
714                                                                                          PyObject* args, 
715                                                                                          PyObject* kwds) {
716         return BoolToPyArg(m_force_ipo_local);
717 }
718
719
720 /* eof */