721c24dfb94bdcdc9c21d535a27488e1ee1f62ba
[blender.git] / source / gameengine / Converter / BL_ShapeActionActuator.cpp
1 /**
2 * $Id$
3 *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28 */
29
30 #if defined (__sgi)
31 #include <math.h>
32 #else
33 #include <cmath>
34 #endif
35
36 #include "SCA_LogicManager.h"
37 #include "BL_ShapeActionActuator.h"
38 #include "BL_ActionActuator.h"
39 #include "BL_ShapeDeformer.h"
40 #include "KX_GameObject.h"
41 #include "STR_HashedString.h"
42 #include "DNA_action_types.h"
43 #include "DNA_nla_types.h"
44 #include "DNA_actuator_types.h"
45 #include "BKE_action.h"
46 #include "DNA_armature_types.h"
47 #include "MEM_guardedalloc.h"
48 #include "BLI_blenlib.h"
49 #include "BLI_arithb.h"
50 #include "MT_Matrix4x4.h"
51 #include "BKE_utildefines.h"
52 #include "PyObjectPlus.h"
53
54 #ifdef HAVE_CONFIG_H
55 #include <config.h>
56 #endif
57
58 BL_ShapeActionActuator::~BL_ShapeActionActuator()
59 {
60 }
61
62 void BL_ShapeActionActuator::ProcessReplica()
63 {
64         m_localtime=m_startframe;
65         m_lastUpdate=-1;
66 }
67
68 void BL_ShapeActionActuator::SetBlendTime (float newtime)
69 {
70         m_blendframe = newtime;
71 }
72
73 CValue* BL_ShapeActionActuator::GetReplica() 
74 {
75         BL_ShapeActionActuator* replica = new BL_ShapeActionActuator(*this);//m_float,GetName());
76         replica->ProcessReplica();
77         
78         // this will copy properties and so on...
79         CValue::AddDataToReplica(replica);
80         return replica;
81 }
82
83 bool BL_ShapeActionActuator::ClampLocalTime()
84 {
85         if (m_startframe < m_endframe)  {
86                 if (m_localtime < m_startframe)
87                 {
88                         m_localtime = m_startframe;
89                         return true;
90                 } 
91                 else if (m_localtime > m_endframe)
92                 {
93                         m_localtime = m_endframe;
94                         return true;
95                 }
96         } else {
97                 if (m_localtime > m_startframe)
98                 {
99                         m_localtime = m_startframe;
100                         return true;
101                 }
102                 else if (m_localtime < m_endframe)
103                 {
104                         m_localtime = m_endframe;
105                         return true;
106                 }
107         }
108         return false;
109 }
110
111 void BL_ShapeActionActuator::SetStartTime(float curtime)
112 {
113         float direction = m_startframe < m_endframe ? 1.0 : -1.0;
114         
115         if (!(m_flag & ACT_FLAG_REVERSE))
116                 m_starttime = curtime - direction*(m_localtime - m_startframe)/KX_KetsjiEngine::GetAnimFrameRate();
117         else
118                 m_starttime = curtime - direction*(m_endframe - m_localtime)/KX_KetsjiEngine::GetAnimFrameRate();
119 }
120
121 void BL_ShapeActionActuator::SetLocalTime(float curtime)
122 {
123         float delta_time = (curtime - m_starttime)*KX_KetsjiEngine::GetAnimFrameRate();
124         
125         if (m_endframe < m_startframe)
126                 delta_time = -delta_time;
127
128         if (!(m_flag & ACT_FLAG_REVERSE))
129                 m_localtime = m_startframe + delta_time;
130         else
131                 m_localtime = m_endframe - delta_time;
132 }
133
134 void BL_ShapeActionActuator::BlendShape(Key* key, float srcweight)
135 {
136         vector<float>::const_iterator it;
137         float dstweight;
138         KeyBlock *kb;
139         
140         dstweight = 1.0F - srcweight;
141
142         for (it=m_blendshape.begin(), kb = (KeyBlock*)key->block.first; 
143                  kb && it != m_blendshape.end(); 
144                  kb = (KeyBlock*)kb->next, it++) {
145                 kb->curval = kb->curval * dstweight + (*it) * srcweight;
146         }
147 }
148
149 bool BL_ShapeActionActuator::Update(double curtime, bool frame)
150 {
151         bool bNegativeEvent = false;
152         bool bPositiveEvent = false;
153         bool keepgoing = true;
154         bool wrap = false;
155         bool apply=true;
156         int     priority;
157         float newweight;
158
159         curtime -= KX_KetsjiEngine::GetSuspendedDelta();
160         
161         // result = true if animation has to be continued, false if animation stops
162         // maybe there are events for us in the queue !
163         if (frame)
164         {
165                 for (vector<CValue*>::iterator i=m_events.begin(); !(i==m_events.end());i++)
166                 {
167                         if ((*i)->GetNumber() == 0.0f)
168                                 bNegativeEvent = true;
169                         else
170                                 bPositiveEvent= true;
171                         (*i)->Release();
172                 
173                 }
174                 m_events.clear();
175                 
176                 if (bPositiveEvent)
177                         m_flag |= ACT_FLAG_ACTIVE;
178                 
179                 if (bNegativeEvent)
180                 {
181                         if (!(m_flag & ACT_FLAG_ACTIVE))
182                                 return false;
183                         m_flag &= ~ACT_FLAG_ACTIVE;
184                 }
185         }
186         
187         /*      This action can only be attached to a deform object */
188         BL_DeformableGameObject *obj = (BL_DeformableGameObject*)GetParent();
189         float length = m_endframe - m_startframe;
190         
191         priority = m_priority;
192         
193         /* Determine pre-incrementation behaviour and set appropriate flags */
194         switch (m_playtype){
195         case ACT_ACTION_MOTION:
196                 if (bNegativeEvent){
197                         keepgoing=false;
198                         apply=false;
199                 };
200                 break;
201         case ACT_ACTION_FROM_PROP:
202                 if (bNegativeEvent){
203                         apply=false;
204                         keepgoing=false;
205                 }
206                 break;
207         case ACT_ACTION_LOOP_END:
208                 if (bPositiveEvent){
209                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
210                                 m_flag &= ~ACT_FLAG_KEYUP;
211                                 m_flag &= ~ACT_FLAG_REVERSE;
212                                 m_flag |= ACT_FLAG_LOCKINPUT;
213                                 m_localtime = m_startframe;
214                                 m_starttime = curtime;
215                         }
216                 }
217                 if (bNegativeEvent){
218                         m_flag |= ACT_FLAG_KEYUP;
219                 }
220                 break;
221         case ACT_ACTION_LOOP_STOP:
222                 if (bPositiveEvent){
223                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
224                                 m_flag &= ~ACT_FLAG_REVERSE;
225                                 m_flag &= ~ACT_FLAG_KEYUP;
226                                 m_flag |= ACT_FLAG_LOCKINPUT;
227                                 SetStartTime(curtime);
228                         }
229                 }
230                 if (bNegativeEvent){
231                         m_flag |= ACT_FLAG_KEYUP;
232                         m_flag &= ~ACT_FLAG_LOCKINPUT;
233                         keepgoing=false;
234                         apply=false;
235                 }
236                 break;
237         case ACT_ACTION_FLIPPER:
238                 if (bPositiveEvent){
239                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
240                                 m_flag &= ~ACT_FLAG_REVERSE;
241                                 m_flag |= ACT_FLAG_LOCKINPUT;
242                                 SetStartTime(curtime);
243                         }
244                 }
245                 else if (bNegativeEvent){
246                         m_flag |= ACT_FLAG_REVERSE;
247                         m_flag &= ~ACT_FLAG_LOCKINPUT;
248                         SetStartTime(curtime);
249                 }
250                 break;
251         case ACT_ACTION_PLAY:
252                 if (bPositiveEvent){
253                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
254                                 m_flag &= ~ACT_FLAG_REVERSE;
255                                 m_localtime = m_starttime;
256                                 m_starttime = curtime;
257                                 m_flag |= ACT_FLAG_LOCKINPUT;
258                         }
259                 }
260                 break;
261         default:
262                 break;
263         }
264         
265         /* Perform increment */
266         if (keepgoing){
267                 if (m_playtype == ACT_ACTION_MOTION){
268                         MT_Point3       newpos;
269                         MT_Point3       deltapos;
270                         
271                         newpos = obj->NodeGetWorldPosition();
272                         
273                         /* Find displacement */
274                         deltapos = newpos-m_lastpos;
275                         m_localtime += (length/m_stridelength) * deltapos.length();
276                         m_lastpos = newpos;
277                 }
278                 else{
279                         SetLocalTime(curtime);
280                 }
281         }
282         
283         /* Check if a wrapping response is needed */
284         if (length){
285                 if (m_localtime < m_startframe || m_localtime > m_endframe)
286                 {
287                         m_localtime = m_startframe + fmod(m_localtime, length);
288                         wrap = true;
289                 }
290         }
291         else
292                 m_localtime = m_startframe;
293         
294         /* Perform post-increment tasks */
295         switch (m_playtype){
296         case ACT_ACTION_FROM_PROP:
297                 {
298                         CValue* propval = GetParent()->GetProperty(m_propname);
299                         if (propval)
300                                 m_localtime = propval->GetNumber();
301                         
302                         if (bNegativeEvent){
303                                 keepgoing=false;
304                         }
305                 }
306                 break;
307         case ACT_ACTION_MOTION:
308                 break;
309         case ACT_ACTION_LOOP_STOP:
310                 break;
311         case ACT_ACTION_FLIPPER:
312                 if (wrap){
313                         if (!(m_flag & ACT_FLAG_REVERSE)){
314                                 m_localtime=m_endframe;
315                                 //keepgoing = false;
316                         }
317                         else {
318                                 m_localtime=m_startframe;
319                                 keepgoing = false;
320                         }
321                 }
322                 break;
323         case ACT_ACTION_LOOP_END:
324                 if (wrap){
325                         if (m_flag & ACT_FLAG_KEYUP){
326                                 keepgoing = false;
327                                 m_localtime = m_endframe;
328                                 m_flag &= ~ACT_FLAG_LOCKINPUT;
329                         }
330                         SetStartTime(curtime);
331                 }
332                 break;
333         case ACT_ACTION_PLAY:
334                 if (wrap){
335                         m_localtime = m_endframe;
336                         keepgoing = false;
337                         m_flag &= ~ACT_FLAG_LOCKINPUT;
338                 }
339                 break;
340         default:
341                 keepgoing = false;
342                 break;
343         }
344         
345         
346         if (bNegativeEvent)
347                 m_blendframe=0.0f;
348         
349         /* Apply the pose if necessary*/
350         if (apply) {
351
352                 /* Priority test */
353                 if (obj->SetActiveAction(this, priority, curtime)){
354                         Key *key = obj->GetKey();
355
356                         if (!key) {
357                                 // this could happen if the mesh was changed in the middle of an action
358                                 // and the new mesh has no key, stop the action
359                                 keepgoing = false;
360                         }
361                         else {
362                                 ListBase tchanbase= {NULL, NULL};
363                         
364                                 if (m_blendin && m_blendframe==0.0f){
365                                         // this is the start of the blending, remember the startup shape
366                                         obj->GetShape(m_blendshape);
367                                         m_blendstart = curtime;
368                                 }
369                                 // only interested in shape channel
370                                 extract_ipochannels_from_action(&tchanbase, &key->id, m_action, "Shape", m_localtime);
371                 
372                                 if (!execute_ipochannels(&tchanbase)) {
373                                         // no update, this is possible if action does not match the keys, stop the action
374                                         keepgoing = false;
375                                 } 
376                                 else {
377                                         // the key have changed, apply blending if needed
378                                         if (m_blendin && (m_blendframe<m_blendin)){
379                                                 newweight = (m_blendframe/(float)m_blendin);
380
381                                                 BlendShape(key, 1.0f - newweight);
382
383                                                 /* Increment current blending percentage */
384                                                 m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
385                                                 if (m_blendframe>m_blendin)
386                                                         m_blendframe = m_blendin;
387                                         }
388                                         m_lastUpdate = m_localtime;
389                                 }
390                                 BLI_freelistN(&tchanbase);
391                         }
392                 }
393                 else{
394                         m_blendframe = 0.0f;
395                 }
396         }
397         
398         if (!keepgoing){
399                 m_blendframe = 0.0f;
400         }
401         return keepgoing;
402 };
403
404 /* ------------------------------------------------------------------------- */
405 /* Python functions                                                          */
406 /* ------------------------------------------------------------------------- */
407
408 /* Integration hooks ------------------------------------------------------- */
409
410 PyTypeObject BL_ShapeActionActuator::Type = {
411         PyObject_HEAD_INIT(&PyType_Type)
412                 0,
413                 "BL_ShapeActionActuator",
414                 sizeof(BL_ShapeActionActuator),
415                 0,
416                 PyDestructor,
417                 0,
418                 __getattr,
419                 __setattr,
420                 0, //&MyPyCompare,
421                 __repr,
422                 0, //&cvalue_as_number,
423                 0,
424                 0,
425                 0,
426                 0
427 };
428
429 PyParentObject BL_ShapeActionActuator::Parents[] = {
430         &BL_ShapeActionActuator::Type,
431                 &SCA_IActuator::Type,
432                 &SCA_ILogicBrick::Type,
433                 &CValue::Type,
434                 NULL
435 };
436
437 PyMethodDef BL_ShapeActionActuator::Methods[] = {
438         {"setAction", (PyCFunction) BL_ShapeActionActuator::sPySetAction, METH_VARARGS, SetAction_doc},
439         {"setStart", (PyCFunction) BL_ShapeActionActuator::sPySetStart, METH_VARARGS, SetStart_doc},
440         {"setEnd", (PyCFunction) BL_ShapeActionActuator::sPySetEnd, METH_VARARGS, SetEnd_doc},
441         {"setBlendin", (PyCFunction) BL_ShapeActionActuator::sPySetBlendin, METH_VARARGS, SetBlendin_doc},
442         {"setPriority", (PyCFunction) BL_ShapeActionActuator::sPySetPriority, METH_VARARGS, SetPriority_doc},
443         {"setFrame", (PyCFunction) BL_ShapeActionActuator::sPySetFrame, METH_VARARGS, SetFrame_doc},
444         {"setProperty", (PyCFunction) BL_ShapeActionActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
445         {"setBlendtime", (PyCFunction) BL_ShapeActionActuator::sPySetBlendtime, METH_VARARGS, SetBlendtime_doc},
446
447         {"getAction", (PyCFunction) BL_ShapeActionActuator::sPyGetAction, METH_NOARGS, GetAction_doc},
448         {"getStart", (PyCFunction) BL_ShapeActionActuator::sPyGetStart, METH_NOARGS, GetStart_doc},
449         {"getEnd", (PyCFunction) BL_ShapeActionActuator::sPyGetEnd, METH_NOARGS, GetEnd_doc},
450         {"getBlendin", (PyCFunction) BL_ShapeActionActuator::sPyGetBlendin, METH_NOARGS, GetBlendin_doc},
451         {"getPriority", (PyCFunction) BL_ShapeActionActuator::sPyGetPriority, METH_NOARGS, GetPriority_doc},
452         {"getFrame", (PyCFunction) BL_ShapeActionActuator::sPyGetFrame, METH_NOARGS, GetFrame_doc},
453         {"getProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetProperty, METH_NOARGS, GetProperty_doc},
454         {"getType", (PyCFunction) BL_ShapeActionActuator::sPyGetType, METH_NOARGS, GetType_doc},        
455         {"setType", (PyCFunction) BL_ShapeActionActuator::sPySetType, METH_NOARGS, SetType_doc},
456         {NULL,NULL} //Sentinel
457 };
458
459 PyObject* BL_ShapeActionActuator::_getattr(const STR_String& attr) {
460         _getattr_up(SCA_IActuator);
461 }
462
463 /*     setStart                                                              */
464 const char BL_ShapeActionActuator::GetAction_doc[] = 
465 "getAction()\n"
466 "\tReturns a string containing the name of the current action.\n";
467
468 PyObject* BL_ShapeActionActuator::PyGetAction(PyObject* self) {
469         if (m_action){
470                 return PyString_FromString(m_action->id.name+2);
471         }
472         Py_RETURN_NONE;
473 }
474
475 /*     getProperty                                                             */
476 const char BL_ShapeActionActuator::GetProperty_doc[] = 
477 "getProperty()\n"
478 "\tReturns the name of the property to be used in FromProp mode.\n";
479
480 PyObject* BL_ShapeActionActuator::PyGetProperty(PyObject* self) {
481         PyObject *result;
482         
483         result = Py_BuildValue("s", (const char *)m_propname);
484         
485         return result;
486 }
487
488 /*     getFrame                                                              */
489 const char BL_ShapeActionActuator::GetFrame_doc[] = 
490 "getFrame()\n"
491 "\tReturns the current frame number.\n";
492
493 PyObject* BL_ShapeActionActuator::PyGetFrame(PyObject* self) {
494         PyObject *result;
495         
496         result = Py_BuildValue("f", m_localtime);
497         
498         return result;
499 }
500
501 /*     getEnd                                                                */
502 const char BL_ShapeActionActuator::GetEnd_doc[] = 
503 "getEnd()\n"
504 "\tReturns the last frame of the action.\n";
505
506 PyObject* BL_ShapeActionActuator::PyGetEnd(PyObject* self) {
507         PyObject *result;
508         
509         result = Py_BuildValue("f", m_endframe);
510         
511         return result;
512 }
513
514 /*     getStart                                                              */
515 const char BL_ShapeActionActuator::GetStart_doc[] = 
516 "getStart()\n"
517 "\tReturns the starting frame of the action.\n";
518
519 PyObject* BL_ShapeActionActuator::PyGetStart(PyObject* self) {
520         PyObject *result;
521         
522         result = Py_BuildValue("f", m_startframe);
523         
524         return result;
525 }
526
527 /*     getBlendin                                                            */
528 const char BL_ShapeActionActuator::GetBlendin_doc[] = 
529 "getBlendin()\n"
530 "\tReturns the number of interpolation animation frames to be\n"
531 "\tgenerated when this actuator is triggered.\n";
532
533 PyObject* BL_ShapeActionActuator::PyGetBlendin(PyObject* self) {
534         PyObject *result;
535         
536         result = Py_BuildValue("f", m_blendin);
537         
538         return result;
539 }
540
541 /*     getPriority                                                           */
542 const char BL_ShapeActionActuator::GetPriority_doc[] = 
543 "getPriority()\n"
544 "\tReturns the priority for this actuator.  Actuators with lower\n"
545 "\tPriority numbers will override actuators with higher numbers.\n";
546
547 PyObject* BL_ShapeActionActuator::PyGetPriority(PyObject* self) {
548         PyObject *result;
549         
550         result = Py_BuildValue("i", m_priority);
551         
552         return result;
553 }
554
555 /*     setAction                                                             */
556 const char BL_ShapeActionActuator::SetAction_doc[] = 
557 "setAction(action, (reset))\n"
558 "\t - action    : The name of the action to set as the current action.\n"
559 "\t               Should be an action with Shape channels.\n"
560 "\t - reset     : Optional parameter indicating whether to reset the\n"
561 "\t               blend timer or not.  A value of 1 indicates that the\n"
562 "\t               timer should be reset.  A value of 0 will leave it\n"
563 "\t               unchanged.  If reset is not specified, the timer will"
564 "\t                   be reset.\n";
565
566 PyObject* BL_ShapeActionActuator::PySetAction(PyObject* self, 
567                                                                                           PyObject* args, 
568                                                                                           PyObject* kwds) {
569         char *string;
570         int     reset = 1;
571
572         if (PyArg_ParseTuple(args,"s|i",&string, &reset))
573         {
574                 bAction *action;
575                 
576                 action = (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(STR_String(string));
577                 
578                 if (!action){
579                         /* NOTE!  Throw an exception or something */
580                         //                      printf ("setAction failed: Action not found\n", string);
581                 }
582                 else{
583                         m_action=action;
584                         if (reset)
585                                 m_blendframe = 0.f;
586                 }
587         }
588         else {
589                 return NULL;
590         }
591         
592         Py_RETURN_NONE;
593 }
594
595 /*     setStart                                                              */
596 const char BL_ShapeActionActuator::SetStart_doc[] = 
597 "setStart(start)\n"
598 "\t - start     : Specifies the starting frame of the animation.\n";
599
600 PyObject* BL_ShapeActionActuator::PySetStart(PyObject* self, 
601                                                                                          PyObject* args, 
602                                                                                          PyObject* kwds) {
603         float start;
604         
605         if (PyArg_ParseTuple(args,"f",&start))
606         {
607                 m_startframe = start;
608         }
609         else {
610                 return NULL;
611         }
612         
613         Py_RETURN_NONE;
614 }
615
616 /*     setEnd                                                                */
617 const char BL_ShapeActionActuator::SetEnd_doc[] = 
618 "setEnd(end)\n"
619 "\t - end       : Specifies the ending frame of the animation.\n";
620
621 PyObject* BL_ShapeActionActuator::PySetEnd(PyObject* self, 
622                                                                                    PyObject* args, 
623                                                                                    PyObject* kwds) {
624         float end;
625         
626         if (PyArg_ParseTuple(args,"f",&end))
627         {
628                 m_endframe = end;
629         }
630         else {
631                 return NULL;
632         }
633         
634         Py_RETURN_NONE;
635 }
636
637 /*     setBlendin                                                            */
638 const char BL_ShapeActionActuator::SetBlendin_doc[] = 
639 "setBlendin(blendin)\n"
640 "\t - blendin   : Specifies the number of frames of animation to generate\n"
641 "\t               when making transitions between actions.\n";
642
643 PyObject* BL_ShapeActionActuator::PySetBlendin(PyObject* self, 
644                                                                                            PyObject* args, 
645                                                                                            PyObject* kwds) {
646         float blendin;
647         
648         if (PyArg_ParseTuple(args,"f",&blendin))
649         {
650                 m_blendin = blendin;
651         }
652         else {
653                 return NULL;
654         }
655         
656         Py_RETURN_NONE;
657 }
658
659 /*     setBlendtime                                                          */
660 const char BL_ShapeActionActuator::SetBlendtime_doc[] = 
661 "setBlendtime(blendtime)\n"
662 "\t - blendtime : Allows the script to directly modify the internal timer\n"
663 "\t               used when generating transitions between actions.  This\n"
664 "\t               parameter must be in the range from 0.0 to 1.0.\n";
665
666 PyObject* BL_ShapeActionActuator::PySetBlendtime(PyObject* self, 
667                                                                                                  PyObject* args, 
668                                                                                                    PyObject* kwds) {
669         float blendframe;
670         
671         if (PyArg_ParseTuple(args,"f",&blendframe))
672         {
673                 m_blendframe = blendframe * m_blendin;
674                 if (m_blendframe<0.f)
675                         m_blendframe = 0.f;
676                 if (m_blendframe>m_blendin)
677                         m_blendframe = m_blendin;
678         }
679         else {
680                 return NULL;
681         }
682         
683         Py_RETURN_NONE;
684 }
685
686 /*     setPriority                                                           */
687 const char BL_ShapeActionActuator::SetPriority_doc[] = 
688 "setPriority(priority)\n"
689 "\t - priority  : Specifies the new priority.  Actuators will lower\n"
690 "\t               priority numbers will override actuators with higher\n"
691 "\t               numbers.\n";
692
693 PyObject* BL_ShapeActionActuator::PySetPriority(PyObject* self, 
694                                                                                                 PyObject* args, 
695                                                                                                 PyObject* kwds) {
696         int priority;
697         
698         if (PyArg_ParseTuple(args,"i",&priority))
699         {
700                 m_priority = priority;
701         }
702         else {
703                 return NULL;
704         }
705         
706         Py_RETURN_NONE;
707 }
708
709 /*     setFrame                                                              */
710 const char BL_ShapeActionActuator::SetFrame_doc[] = 
711 "setFrame(frame)\n"
712 "\t - frame     : Specifies the new current frame for the animation\n";
713
714 PyObject* BL_ShapeActionActuator::PySetFrame(PyObject* self, 
715                                                                                          PyObject* args, 
716                                                                                          PyObject* kwds) {
717         float frame;
718         
719         if (PyArg_ParseTuple(args,"f",&frame))
720         {
721                 m_localtime = frame;
722                 if (m_localtime<m_startframe)
723                         m_localtime=m_startframe;
724                 else if (m_localtime>m_endframe)
725                         m_localtime=m_endframe;
726         }
727         else {
728                 return NULL;
729         }
730         
731         Py_RETURN_NONE;
732 }
733
734 /*     setProperty                                                           */
735 const char BL_ShapeActionActuator::SetProperty_doc[] = 
736 "setProperty(prop)\n"
737 "\t - prop      : A string specifying the property name to be used in\n"
738 "\t               FromProp playback mode.\n";
739
740 PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* self, 
741                                                                                                 PyObject* args, 
742                                                                                                 PyObject* kwds) {
743         char *string;
744         
745         if (PyArg_ParseTuple(args,"s",&string))
746         {
747                 m_propname = string;
748         }
749         else {
750                 return NULL;
751         }
752         
753         Py_RETURN_NONE;
754 }
755
756 /* getType */
757 const char BL_ShapeActionActuator::GetType_doc[] =
758 "getType()\n"
759 "\tReturns the operation mode of the actuator.\n";
760 PyObject* BL_ShapeActionActuator::PyGetType(PyObject* self) {
761     return Py_BuildValue("h", m_playtype);
762 }
763
764 /* setType */
765 const char BL_ShapeActionActuator::SetType_doc[] =
766 "setType(mode)\n"
767 "\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n"
768 "\tSet the operation mode of the actuator.\n";
769 PyObject* BL_ShapeActionActuator::PySetType(PyObject* self,
770                                             PyObject* args,
771                                             PyObject* kwds) {
772         short typeArg;
773                                                                                                              
774     if (!PyArg_ParseTuple(args, "h", &typeArg)) {
775         return NULL;
776     }
777
778         switch (typeArg) {
779         case ACT_ACTION_PLAY:
780         case ACT_ACTION_FLIPPER:
781         case ACT_ACTION_LOOP_STOP:
782         case ACT_ACTION_LOOP_END:
783         case ACT_ACTION_FROM_PROP:
784                 m_playtype = typeArg;
785                 break;
786         default:
787                 printf("Invalid type for action actuator: %d\n", typeArg); /* error */
788     }
789         
790     Py_Return;
791 }
792