svn merge -r 21041:21301 https://svn.blender.org/svnroot/bf-blender/branches/blender2...
[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_ShapeDeformer.h"
39 #include "KX_GameObject.h"
40 #include "STR_HashedString.h"
41 #include "DNA_nla_types.h"
42 #include "DNA_action_types.h"
43 #include "DNA_scene_types.h"
44 #include "BKE_action.h"
45 #include "DNA_armature_types.h"
46 #include "MEM_guardedalloc.h"
47 #include "BLI_blenlib.h"
48 #include "BLI_arithb.h"
49 #include "MT_Matrix4x4.h"
50 #include "BKE_utildefines.h"
51 #include "FloatValue.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         SCA_IActuator::ProcessReplica();
65         m_localtime=m_startframe;
66         m_lastUpdate=-1;
67 }
68
69 void BL_ShapeActionActuator::SetBlendTime (float newtime)
70 {
71         m_blendframe = newtime;
72 }
73
74 CValue* BL_ShapeActionActuator::GetReplica() 
75 {
76         BL_ShapeActionActuator* replica = new BL_ShapeActionActuator(*this);//m_float,GetName());
77         replica->ProcessReplica();
78         return replica;
79 }
80
81 bool BL_ShapeActionActuator::ClampLocalTime()
82 {
83         if (m_startframe < m_endframe)  {
84                 if (m_localtime < m_startframe)
85                 {
86                         m_localtime = m_startframe;
87                         return true;
88                 } 
89                 else if (m_localtime > m_endframe)
90                 {
91                         m_localtime = m_endframe;
92                         return true;
93                 }
94         } else {
95                 if (m_localtime > m_startframe)
96                 {
97                         m_localtime = m_startframe;
98                         return true;
99                 }
100                 else if (m_localtime < m_endframe)
101                 {
102                         m_localtime = m_endframe;
103                         return true;
104                 }
105         }
106         return false;
107 }
108
109 void BL_ShapeActionActuator::SetStartTime(float curtime)
110 {
111         float direction = m_startframe < m_endframe ? 1.0 : -1.0;
112         
113         if (!(m_flag & ACT_FLAG_REVERSE))
114                 m_starttime = curtime - direction*(m_localtime - m_startframe)/KX_KetsjiEngine::GetAnimFrameRate();
115         else
116                 m_starttime = curtime - direction*(m_endframe - m_localtime)/KX_KetsjiEngine::GetAnimFrameRate();
117 }
118
119 void BL_ShapeActionActuator::SetLocalTime(float curtime)
120 {
121         float delta_time = (curtime - m_starttime)*KX_KetsjiEngine::GetAnimFrameRate();
122         
123         if (m_endframe < m_startframe)
124                 delta_time = -delta_time;
125
126         if (!(m_flag & ACT_FLAG_REVERSE))
127                 m_localtime = m_startframe + delta_time;
128         else
129                 m_localtime = m_endframe - delta_time;
130 }
131
132 void BL_ShapeActionActuator::BlendShape(Key* key, float srcweight)
133 {
134         vector<float>::const_iterator it;
135         float dstweight;
136         KeyBlock *kb;
137         
138         dstweight = 1.0F - srcweight;
139
140         for (it=m_blendshape.begin(), kb = (KeyBlock*)key->block.first; 
141                  kb && it != m_blendshape.end(); 
142                  kb = (KeyBlock*)kb->next, it++) {
143                 kb->curval = kb->curval * dstweight + (*it) * srcweight;
144         }
145 }
146
147 bool BL_ShapeActionActuator::Update(double curtime, bool frame)
148 {
149         bool bNegativeEvent = false;
150         bool bPositiveEvent = false;
151         bool keepgoing = true;
152         bool wrap = false;
153         bool apply=true;
154         int     priority;
155         float newweight;
156
157         curtime -= KX_KetsjiEngine::GetSuspendedDelta();
158         
159         // result = true if animation has to be continued, false if animation stops
160         // maybe there are events for us in the queue !
161         if (frame)
162         {
163                 bNegativeEvent = m_negevent;
164                 bPositiveEvent = m_posevent;
165                 RemoveAllEvents();
166                 
167                 if (bPositiveEvent)
168                         m_flag |= ACT_FLAG_ACTIVE;
169                 
170                 if (bNegativeEvent)
171                 {
172                         if (!(m_flag & ACT_FLAG_ACTIVE))
173                                 return false;
174                         m_flag &= ~ACT_FLAG_ACTIVE;
175                 }
176         }
177         
178         /*      This action can only be attached to a deform object */
179         BL_DeformableGameObject *obj = (BL_DeformableGameObject*)GetParent();
180         float length = m_endframe - m_startframe;
181         
182         priority = m_priority;
183         
184         /* Determine pre-incrementation behaviour and set appropriate flags */
185         switch (m_playtype){
186         case ACT_ACTION_MOTION:
187                 if (bNegativeEvent){
188                         keepgoing=false;
189                         apply=false;
190                 };
191                 break;
192         case ACT_ACTION_FROM_PROP:
193                 if (bNegativeEvent){
194                         apply=false;
195                         keepgoing=false;
196                 }
197                 break;
198         case ACT_ACTION_LOOP_END:
199                 if (bPositiveEvent){
200                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
201                                 m_flag &= ~ACT_FLAG_KEYUP;
202                                 m_flag &= ~ACT_FLAG_REVERSE;
203                                 m_flag |= ACT_FLAG_LOCKINPUT;
204                                 m_localtime = m_startframe;
205                                 m_starttime = curtime;
206                         }
207                 }
208                 if (bNegativeEvent){
209                         m_flag |= ACT_FLAG_KEYUP;
210                 }
211                 break;
212         case ACT_ACTION_LOOP_STOP:
213                 if (bPositiveEvent){
214                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
215                                 m_flag &= ~ACT_FLAG_REVERSE;
216                                 m_flag &= ~ACT_FLAG_KEYUP;
217                                 m_flag |= ACT_FLAG_LOCKINPUT;
218                                 SetStartTime(curtime);
219                         }
220                 }
221                 if (bNegativeEvent){
222                         m_flag |= ACT_FLAG_KEYUP;
223                         m_flag &= ~ACT_FLAG_LOCKINPUT;
224                         keepgoing=false;
225                         apply=false;
226                 }
227                 break;
228         case ACT_ACTION_FLIPPER:
229                 if (bPositiveEvent){
230                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
231                                 m_flag &= ~ACT_FLAG_REVERSE;
232                                 m_flag |= ACT_FLAG_LOCKINPUT;
233                                 SetStartTime(curtime);
234                         }
235                 }
236                 else if (bNegativeEvent){
237                         m_flag |= ACT_FLAG_REVERSE;
238                         m_flag &= ~ACT_FLAG_LOCKINPUT;
239                         SetStartTime(curtime);
240                 }
241                 break;
242         case ACT_ACTION_PLAY:
243                 if (bPositiveEvent){
244                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
245                                 m_flag &= ~ACT_FLAG_REVERSE;
246                                 m_localtime = m_starttime;
247                                 m_starttime = curtime;
248                                 m_flag |= ACT_FLAG_LOCKINPUT;
249                         }
250                 }
251                 break;
252         default:
253                 break;
254         }
255         
256         /* Perform increment */
257         if (keepgoing){
258                 if (m_playtype == ACT_ACTION_MOTION){
259                         MT_Point3       newpos;
260                         MT_Point3       deltapos;
261                         
262                         newpos = obj->NodeGetWorldPosition();
263                         
264                         /* Find displacement */
265                         deltapos = newpos-m_lastpos;
266                         m_localtime += (length/m_stridelength) * deltapos.length();
267                         m_lastpos = newpos;
268                 }
269                 else{
270                         SetLocalTime(curtime);
271                 }
272         }
273         
274         /* Check if a wrapping response is needed */
275         if (length){
276                 if (m_localtime < m_startframe || m_localtime > m_endframe)
277                 {
278                         m_localtime = m_startframe + fmod(m_localtime, length);
279                         wrap = true;
280                 }
281         }
282         else
283                 m_localtime = m_startframe;
284         
285         /* Perform post-increment tasks */
286         switch (m_playtype){
287         case ACT_ACTION_FROM_PROP:
288                 {
289                         CValue* propval = GetParent()->GetProperty(m_propname);
290                         if (propval)
291                                 m_localtime = propval->GetNumber();
292                         
293                         if (bNegativeEvent){
294                                 keepgoing=false;
295                         }
296                 }
297                 break;
298         case ACT_ACTION_MOTION:
299                 break;
300         case ACT_ACTION_LOOP_STOP:
301                 break;
302         case ACT_ACTION_FLIPPER:
303                 if (wrap){
304                         if (!(m_flag & ACT_FLAG_REVERSE)){
305                                 m_localtime=m_endframe;
306                                 //keepgoing = false;
307                         }
308                         else {
309                                 m_localtime=m_startframe;
310                                 keepgoing = false;
311                         }
312                 }
313                 break;
314         case ACT_ACTION_LOOP_END:
315                 if (wrap){
316                         if (m_flag & ACT_FLAG_KEYUP){
317                                 keepgoing = false;
318                                 m_localtime = m_endframe;
319                                 m_flag &= ~ACT_FLAG_LOCKINPUT;
320                         }
321                         SetStartTime(curtime);
322                 }
323                 break;
324         case ACT_ACTION_PLAY:
325                 if (wrap){
326                         m_localtime = m_endframe;
327                         keepgoing = false;
328                         m_flag &= ~ACT_FLAG_LOCKINPUT;
329                 }
330                 break;
331         default:
332                 keepgoing = false;
333                 break;
334         }
335         
336         /* Set the property if its defined */
337         if (m_framepropname[0] != '\0') {
338                 CValue* propowner = GetParent();
339                 CValue* oldprop = propowner->GetProperty(m_framepropname);
340                 CValue* newval = new CFloatValue(m_localtime);
341                 if (oldprop) {
342                         oldprop->SetValue(newval);
343                 } else {
344                         propowner->SetProperty(m_framepropname, newval);
345                 }
346                 newval->Release();
347         }
348         
349         if (bNegativeEvent)
350                 m_blendframe=0.0f;
351         
352         /* Apply the pose if necessary*/
353         if (apply) {
354
355                 /* Priority test */
356                 if (obj->SetActiveAction(this, priority, curtime)){
357                         Key *key = obj->GetKey();
358
359                         if (!key) {
360                                 // this could happen if the mesh was changed in the middle of an action
361                                 // and the new mesh has no key, stop the action
362                                 keepgoing = false;
363                         }
364                         else {
365                                 ListBase tchanbase= {NULL, NULL};
366                         
367                                 if (m_blendin && m_blendframe==0.0f){
368                                         // this is the start of the blending, remember the startup shape
369                                         obj->GetShape(m_blendshape);
370                                         m_blendstart = curtime;
371                                 }
372                                 // only interested in shape channel
373                                 // XXX extract_ipochannels_from_action(&tchanbase, &key->id, m_action, "Shape", m_localtime);
374                 
375                                 if (0) { // XXX !execute_ipochannels(&tchanbase)) {
376                                         // no update, this is possible if action does not match the keys, stop the action
377                                         keepgoing = false;
378                                 } 
379                                 else {
380                                         // the key have changed, apply blending if needed
381                                         if (m_blendin && (m_blendframe<m_blendin)){
382                                                 newweight = (m_blendframe/(float)m_blendin);
383
384                                                 BlendShape(key, 1.0f - newweight);
385
386                                                 /* Increment current blending percentage */
387                                                 m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
388                                                 if (m_blendframe>m_blendin)
389                                                         m_blendframe = m_blendin;
390                                         }
391                                         m_lastUpdate = m_localtime;
392                                 }
393                                 BLI_freelistN(&tchanbase);
394                         }
395                 }
396                 else{
397                         m_blendframe = 0.0f;
398                 }
399         }
400         
401         if (!keepgoing){
402                 m_blendframe = 0.0f;
403         }
404         return keepgoing;
405 };
406
407 /* ------------------------------------------------------------------------- */
408 /* Python functions                                                          */
409 /* ------------------------------------------------------------------------- */
410
411 /* Integration hooks ------------------------------------------------------- */
412
413 PyTypeObject BL_ShapeActionActuator::Type = {
414 #if (PY_VERSION_HEX >= 0x02060000)
415         PyVarObject_HEAD_INIT(NULL, 0)
416 #else
417         /* python 2.5 and below */
418         PyObject_HEAD_INIT( NULL )  /* required py macro */
419         0,                          /* ob_size */
420 #endif
421                 "BL_ShapeActionActuator",
422                 sizeof(PyObjectPlus_Proxy),
423                 0,
424                 py_base_dealloc,
425                 0,
426                 0,
427                 0,
428                 0,
429                 py_base_repr,
430                 0,0,0,0,0,0,0,0,0,
431                 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
432                 0,0,0,0,0,0,0,
433                 Methods,
434                 0,
435                 0,
436                 &SCA_IActuator::Type,
437                 0,0,0,0,0,0,
438                 py_base_new
439 };
440
441
442 PyMethodDef BL_ShapeActionActuator::Methods[] = {
443         {"setAction", (PyCFunction) BL_ShapeActionActuator::sPySetAction, METH_VARARGS, (PY_METHODCHAR)SetAction_doc},
444         {"setStart", (PyCFunction) BL_ShapeActionActuator::sPySetStart, METH_VARARGS, (PY_METHODCHAR)SetStart_doc},
445         {"setEnd", (PyCFunction) BL_ShapeActionActuator::sPySetEnd, METH_VARARGS, (PY_METHODCHAR)SetEnd_doc},
446         {"setBlendin", (PyCFunction) BL_ShapeActionActuator::sPySetBlendin, METH_VARARGS, (PY_METHODCHAR)SetBlendin_doc},
447         {"setPriority", (PyCFunction) BL_ShapeActionActuator::sPySetPriority, METH_VARARGS, (PY_METHODCHAR)SetPriority_doc},
448         {"setFrame", (PyCFunction) BL_ShapeActionActuator::sPySetFrame, METH_VARARGS, (PY_METHODCHAR)SetFrame_doc},
449         {"setProperty", (PyCFunction) BL_ShapeActionActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
450         {"setFrameProperty", (PyCFunction) BL_ShapeActionActuator::sPySetFrameProperty, METH_VARARGS, (PY_METHODCHAR)SetFrameProperty_doc},
451         {"setBlendtime", (PyCFunction) BL_ShapeActionActuator::sPySetBlendtime, METH_VARARGS, (PY_METHODCHAR)SetBlendtime_doc},
452
453         {"getAction", (PyCFunction) BL_ShapeActionActuator::sPyGetAction, METH_NOARGS, (PY_METHODCHAR)GetAction_doc},
454         {"getStart", (PyCFunction) BL_ShapeActionActuator::sPyGetStart, METH_NOARGS, (PY_METHODCHAR)GetStart_doc},
455         {"getEnd", (PyCFunction) BL_ShapeActionActuator::sPyGetEnd, METH_NOARGS, (PY_METHODCHAR)GetEnd_doc},
456         {"getBlendin", (PyCFunction) BL_ShapeActionActuator::sPyGetBlendin, METH_NOARGS, (PY_METHODCHAR)GetBlendin_doc},
457         {"getPriority", (PyCFunction) BL_ShapeActionActuator::sPyGetPriority, METH_NOARGS, (PY_METHODCHAR)GetPriority_doc},
458         {"getFrame", (PyCFunction) BL_ShapeActionActuator::sPyGetFrame, METH_NOARGS, (PY_METHODCHAR)GetFrame_doc},
459         {"getProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetProperty, METH_NOARGS, (PY_METHODCHAR)GetProperty_doc},
460         {"getFrameProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetFrameProperty, METH_NOARGS, (PY_METHODCHAR)GetFrameProperty_doc},
461         {"getType", (PyCFunction) BL_ShapeActionActuator::sPyGetType, METH_NOARGS, (PY_METHODCHAR)GetType_doc}, 
462         {"setType", (PyCFunction) BL_ShapeActionActuator::sPySetType, METH_NOARGS, (PY_METHODCHAR)SetType_doc},
463         {NULL,NULL} //Sentinel
464 };
465
466 PyAttributeDef BL_ShapeActionActuator::Attributes[] = {
467         KX_PYATTRIBUTE_FLOAT_RW("frameStart", 0, MAXFRAMEF, BL_ShapeActionActuator, m_startframe),
468         KX_PYATTRIBUTE_FLOAT_RW("frameEnd", 0, MAXFRAMEF, BL_ShapeActionActuator, m_endframe),
469         KX_PYATTRIBUTE_FLOAT_RW("blendIn", 0, MAXFRAMEF, BL_ShapeActionActuator, m_blendin),
470         KX_PYATTRIBUTE_RW_FUNCTION("action", BL_ShapeActionActuator, pyattr_get_action, pyattr_set_action),
471         KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ShapeActionActuator, m_priority),
472         KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ShapeActionActuator, m_localtime, CheckFrame),
473         KX_PYATTRIBUTE_STRING_RW("propName", 0, 31, false, BL_ShapeActionActuator, m_propname),
474         KX_PYATTRIBUTE_STRING_RW("framePropName", 0, 31, false, BL_ShapeActionActuator, m_framepropname),
475         KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ShapeActionActuator, m_blendframe, CheckBlendTime),
476         KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",0,100,false,BL_ShapeActionActuator,m_playtype,CheckType),
477         { NULL }        //Sentinel
478 };
479
480 /*     setStart                                                              */
481 const char BL_ShapeActionActuator::GetAction_doc[] = 
482 "getAction()\n"
483 "\tReturns a string containing the name of the current action.\n";
484
485 PyObject* BL_ShapeActionActuator::PyGetAction() {
486         ShowDeprecationWarning("getAction()", "the action property");
487         if (m_action){
488                 return PyUnicode_FromString(m_action->id.name+2);
489         }
490         Py_RETURN_NONE;
491 }
492
493 /*     getProperty                                                             */
494 const char BL_ShapeActionActuator::GetProperty_doc[] = 
495 "getProperty()\n"
496 "\tReturns the name of the property to be used in FromProp mode.\n";
497
498 PyObject* BL_ShapeActionActuator::PyGetProperty() {
499         ShowDeprecationWarning("getProperty()", "the property property");
500         PyObject *result;
501         
502         result = Py_BuildValue("s", (const char *)m_propname);
503         
504         return result;
505 }
506
507 /*     getFrame                                                              */
508 const char BL_ShapeActionActuator::GetFrame_doc[] = 
509 "getFrame()\n"
510 "\tReturns the current frame number.\n";
511
512 PyObject* BL_ShapeActionActuator::PyGetFrame() {
513         ShowDeprecationWarning("getFrame()", "the frame property");
514         PyObject *result;
515         
516         result = Py_BuildValue("f", m_localtime);
517         
518         return result;
519 }
520
521 /*     getEnd                                                                */
522 const char BL_ShapeActionActuator::GetEnd_doc[] = 
523 "getEnd()\n"
524 "\tReturns the last frame of the action.\n";
525
526 PyObject* BL_ShapeActionActuator::PyGetEnd() {
527         ShowDeprecationWarning("getEnd()", "the end property");
528         PyObject *result;
529         
530         result = Py_BuildValue("f", m_endframe);
531         
532         return result;
533 }
534
535 /*     getStart                                                              */
536 const char BL_ShapeActionActuator::GetStart_doc[] = 
537 "getStart()\n"
538 "\tReturns the starting frame of the action.\n";
539
540 PyObject* BL_ShapeActionActuator::PyGetStart() {
541         ShowDeprecationWarning("getStart()", "the start property");
542         PyObject *result;
543         
544         result = Py_BuildValue("f", m_startframe);
545         
546         return result;
547 }
548
549 /*     getBlendin                                                            */
550 const char BL_ShapeActionActuator::GetBlendin_doc[] = 
551 "getBlendin()\n"
552 "\tReturns the number of interpolation animation frames to be\n"
553 "\tgenerated when this actuator is triggered.\n";
554
555 PyObject* BL_ShapeActionActuator::PyGetBlendin() {
556         ShowDeprecationWarning("getBlendin()", "the blendin property");
557         PyObject *result;
558         
559         result = Py_BuildValue("f", m_blendin);
560         
561         return result;
562 }
563
564 /*     getPriority                                                           */
565 const char BL_ShapeActionActuator::GetPriority_doc[] = 
566 "getPriority()\n"
567 "\tReturns the priority for this actuator.  Actuators with lower\n"
568 "\tPriority numbers will override actuators with higher numbers.\n";
569
570 PyObject* BL_ShapeActionActuator::PyGetPriority() {
571         ShowDeprecationWarning("getPriority()", "the priority property");
572         PyObject *result;
573         
574         result = Py_BuildValue("i", m_priority);
575         
576         return result;
577 }
578
579 /*     setAction                                                             */
580 const char BL_ShapeActionActuator::SetAction_doc[] = 
581 "setAction(action, (reset))\n"
582 "\t - action    : The name of the action to set as the current action.\n"
583 "\t               Should be an action with Shape channels.\n"
584 "\t - reset     : Optional parameter indicating whether to reset the\n"
585 "\t               blend timer or not.  A value of 1 indicates that the\n"
586 "\t               timer should be reset.  A value of 0 will leave it\n"
587 "\t               unchanged.  If reset is not specified, the timer will"
588 "\t                   be reset.\n";
589
590 PyObject* BL_ShapeActionActuator::PySetAction(PyObject* args) {
591         ShowDeprecationWarning("setAction()", "the action property");
592         char *string;
593         int     reset = 1;
594
595         if (PyArg_ParseTuple(args,"s|i:setAction",&string, &reset))
596         {
597                 bAction *action;
598                 
599                 action = (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(STR_String(string));
600                 
601                 if (!action){
602                         /* NOTE!  Throw an exception or something */
603                         //                      printf ("setAction failed: Action not found\n", string);
604                 }
605                 else{
606                         m_action=action;
607                         if (reset)
608                                 m_blendframe = 0.f;
609                 }
610         }
611         else {
612                 return NULL;
613         }
614         
615         Py_RETURN_NONE;
616 }
617
618 /*     setStart                                                              */
619 const char BL_ShapeActionActuator::SetStart_doc[] = 
620 "setStart(start)\n"
621 "\t - start     : Specifies the starting frame of the animation.\n";
622
623 PyObject* BL_ShapeActionActuator::PySetStart(PyObject* args) {
624         ShowDeprecationWarning("setStart()", "the start property");
625         float start;
626         
627         if (PyArg_ParseTuple(args,"f:setStart",&start))
628         {
629                 m_startframe = start;
630         }
631         else {
632                 return NULL;
633         }
634         
635         Py_RETURN_NONE;
636 }
637
638 /*     setEnd                                                                */
639 const char BL_ShapeActionActuator::SetEnd_doc[] = 
640 "setEnd(end)\n"
641 "\t - end       : Specifies the ending frame of the animation.\n";
642
643 PyObject* BL_ShapeActionActuator::PySetEnd(PyObject* args) {
644         ShowDeprecationWarning("setEnd()", "the end property");
645         float end;
646         
647         if (PyArg_ParseTuple(args,"f:setEnd",&end))
648         {
649                 m_endframe = end;
650         }
651         else {
652                 return NULL;
653         }
654         
655         Py_RETURN_NONE;
656 }
657
658 /*     setBlendin                                                            */
659 const char BL_ShapeActionActuator::SetBlendin_doc[] = 
660 "setBlendin(blendin)\n"
661 "\t - blendin   : Specifies the number of frames of animation to generate\n"
662 "\t               when making transitions between actions.\n";
663
664 PyObject* BL_ShapeActionActuator::PySetBlendin(PyObject* args) {
665         ShowDeprecationWarning("setBlendin()", "the blendin property");
666         float blendin;
667         
668         if (PyArg_ParseTuple(args,"f:setBlendin",&blendin))
669         {
670                 m_blendin = blendin;
671         }
672         else {
673                 return NULL;
674         }
675         
676         Py_RETURN_NONE;
677 }
678
679 /*     setBlendtime                                                          */
680 const char BL_ShapeActionActuator::SetBlendtime_doc[] = 
681 "setBlendtime(blendtime)\n"
682 "\t - blendtime : Allows the script to directly modify the internal timer\n"
683 "\t               used when generating transitions between actions.  This\n"
684 "\t               parameter must be in the range from 0.0 to 1.0.\n";
685
686 PyObject* BL_ShapeActionActuator::PySetBlendtime(PyObject* args) {
687         ShowDeprecationWarning("setBlendtime()", "the blendTime property");
688         float blendframe;
689         
690         if (PyArg_ParseTuple(args,"f:setBlendtime",&blendframe))
691         {
692                 m_blendframe = blendframe * m_blendin;
693                 if (m_blendframe<0.f)
694                         m_blendframe = 0.f;
695                 if (m_blendframe>m_blendin)
696                         m_blendframe = m_blendin;
697         }
698         else {
699                 return NULL;
700         }
701         
702         Py_RETURN_NONE;
703 }
704
705 /*     setPriority                                                           */
706 const char BL_ShapeActionActuator::SetPriority_doc[] = 
707 "setPriority(priority)\n"
708 "\t - priority  : Specifies the new priority.  Actuators will lower\n"
709 "\t               priority numbers will override actuators with higher\n"
710 "\t               numbers.\n";
711
712 PyObject* BL_ShapeActionActuator::PySetPriority(PyObject* args) {
713         ShowDeprecationWarning("setPriority()", "the priority property");
714         int priority;
715         
716         if (PyArg_ParseTuple(args,"i:setPriority",&priority))
717         {
718                 m_priority = priority;
719         }
720         else {
721                 return NULL;
722         }
723         
724         Py_RETURN_NONE;
725 }
726
727 /*     getProperty                                                             */
728 const char BL_ShapeActionActuator::GetFrameProperty_doc[] = 
729 "getFrameProperty()\n"
730 "\tReturns the name of the property, that is set to the current frame number.\n";
731
732 PyObject* BL_ShapeActionActuator::PyGetFrameProperty() {
733         ShowDeprecationWarning("getFrameProperty()", "the frameProperty property");
734         PyObject *result;
735         
736         result = Py_BuildValue("s", (const char *)m_framepropname);
737         
738         return result;
739 }
740
741
742 /*     setFrame                                                              */
743 const char BL_ShapeActionActuator::SetFrame_doc[] = 
744 "setFrame(frame)\n"
745 "\t - frame     : Specifies the new current frame for the animation\n";
746
747 PyObject* BL_ShapeActionActuator::PySetFrame(PyObject* args) {
748         ShowDeprecationWarning("setFrame()", "the frame property");
749         float frame;
750         
751         if (PyArg_ParseTuple(args,"f:setFrame",&frame))
752         {
753                 m_localtime = frame;
754                 if (m_localtime<m_startframe)
755                         m_localtime=m_startframe;
756                 else if (m_localtime>m_endframe)
757                         m_localtime=m_endframe;
758         }
759         else {
760                 return NULL;
761         }
762         
763         Py_RETURN_NONE;
764 }
765
766 /*     setProperty                                                           */
767 const char BL_ShapeActionActuator::SetProperty_doc[] = 
768 "setProperty(prop)\n"
769 "\t - prop      : A string specifying the property name to be used in\n"
770 "\t               FromProp playback mode.\n";
771
772 PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* args) {
773         ShowDeprecationWarning("setProperty()", "the property property");
774         char *string;
775         
776         if (PyArg_ParseTuple(args,"s:setProperty",&string))
777         {
778                 m_propname = string;
779         }
780         else {
781                 return NULL;
782         }
783         
784         Py_RETURN_NONE;
785 }
786
787 /*     setFrameProperty                                                          */
788 const char BL_ShapeActionActuator::SetFrameProperty_doc[] = 
789 "setFrameProperty(prop)\n"
790 "\t - prop      : A string specifying the property of the frame set up update.\n";
791
792 PyObject* BL_ShapeActionActuator::PySetFrameProperty(PyObject* args) {
793         ShowDeprecationWarning("setFrameProperty()", "the frameProperty property");
794         char *string;
795         
796         if (PyArg_ParseTuple(args,"s:setFrameProperty",&string))
797         {
798                 m_framepropname = string;
799         }
800         else {
801                 return NULL;
802         }
803         
804         Py_RETURN_NONE;
805 }
806
807 /* getType */
808 const char BL_ShapeActionActuator::GetType_doc[] =
809 "getType()\n"
810 "\tReturns the operation mode of the actuator.\n";
811 PyObject* BL_ShapeActionActuator::PyGetType() {
812         ShowDeprecationWarning("getType()", "the type property");
813     return Py_BuildValue("h", m_playtype);
814 }
815
816 /* setType */
817 const char BL_ShapeActionActuator::SetType_doc[] =
818 "setType(mode)\n"
819 "\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n"
820 "\tSet the operation mode of the actuator.\n";
821 PyObject* BL_ShapeActionActuator::PySetType(PyObject* args) {
822         ShowDeprecationWarning("setType()", "the type property");
823         short typeArg;
824                                                                                                              
825     if (!PyArg_ParseTuple(args, "h:setType", &typeArg)) {
826         return NULL;
827     }
828
829         switch (typeArg) {
830         case ACT_ACTION_PLAY:
831         case ACT_ACTION_FLIPPER:
832         case ACT_ACTION_LOOP_STOP:
833         case ACT_ACTION_LOOP_END:
834         case ACT_ACTION_FROM_PROP:
835                 m_playtype = typeArg;
836                 break;
837         default:
838                 printf("Invalid type for action actuator: %d\n", typeArg); /* error */
839     }
840         
841     Py_RETURN_NONE;
842 }
843
844 PyObject* BL_ShapeActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
845 {
846         BL_ShapeActionActuator* self= static_cast<BL_ShapeActionActuator*>(self_v);
847         return PyUnicode_FromString(self->GetAction() ? self->GetAction()->id.name+2 : "");
848 }
849
850 int BL_ShapeActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
851 {
852         BL_ShapeActionActuator* self= static_cast<BL_ShapeActionActuator*>(self_v);
853         /* exact copy of BL_ActionActuator's function from here down */
854         if (!PyUnicode_Check(value))
855         {
856                 PyErr_SetString(PyExc_ValueError, "actuator.action = val: Shape Action Actuator, expected the string name of the action");
857                 return PY_SET_ATTR_FAIL;
858         }
859
860         bAction *action= NULL;
861         STR_String val = _PyUnicode_AsString(value);
862         
863         if (val != "")
864         {
865                 action= (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(val);
866                 if (action==NULL)
867                 {
868                         PyErr_SetString(PyExc_ValueError, "actuator.action = val: Shape Action Actuator, action not found!");
869                         return PY_SET_ATTR_FAIL;
870                 }
871         }
872         
873         self->SetAction(action);
874         return PY_SET_ATTR_SUCCESS;
875
876 }