converted my gen_utils.h fix to PyObjectPlus.h
[blender.git] / source / gameengine / Converter / BL_ActionActuator.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_ActionActuator.h"
38 #include "BL_ArmatureObject.h"
39 #include "BL_SkinDeformer.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 "FloatValue.h"
53 #include "PyObjectPlus.h"
54
55 #ifdef HAVE_CONFIG_H
56 #include <config.h>
57 #endif
58
59 BL_ActionActuator::~BL_ActionActuator()
60 {
61         if (m_pose)
62                 free_pose(m_pose);
63         if (m_userpose)
64                 free_pose(m_userpose);
65         if (m_blendpose)
66                 free_pose(m_blendpose);
67 }
68
69 void BL_ActionActuator::ProcessReplica(){
70 //      bPose *oldpose = m_pose;
71 //      bPose *oldbpose = m_blendpose;
72         
73         m_pose = NULL;
74         m_blendpose = NULL;
75         m_localtime=m_startframe;
76         m_lastUpdate=-1;
77         
78 }
79
80 void BL_ActionActuator::SetBlendTime (float newtime){
81         m_blendframe = newtime;
82 }
83
84 CValue* BL_ActionActuator::GetReplica() {
85         BL_ActionActuator* replica = new BL_ActionActuator(*this);//m_float,GetName());
86         replica->ProcessReplica();
87         
88         // this will copy properties and so on...
89         CValue::AddDataToReplica(replica);
90         return replica;
91 }
92
93 bool BL_ActionActuator::ClampLocalTime()
94 {
95         if (m_startframe < m_endframe)
96         {
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         } else {
108                 if (m_localtime > m_startframe)
109                 {
110                         m_localtime = m_startframe;
111                         return true;
112                 }
113                 else if (m_localtime < m_endframe)
114                 {
115                         m_localtime = m_endframe;
116                         return true;
117                 }
118         }
119         return false;
120 }
121
122 void BL_ActionActuator::SetStartTime(float curtime)
123 {
124         float direction = m_startframe < m_endframe ? 1.0 : -1.0;
125         
126         if (!(m_flag & ACT_FLAG_REVERSE))
127                 m_starttime = curtime - direction*(m_localtime - m_startframe)/KX_KetsjiEngine::GetAnimFrameRate();
128         else
129                 m_starttime = curtime - direction*(m_endframe - m_localtime)/KX_KetsjiEngine::GetAnimFrameRate();
130 }
131
132 void BL_ActionActuator::SetLocalTime(float curtime)
133 {
134         float delta_time = (curtime - m_starttime)*KX_KetsjiEngine::GetAnimFrameRate();
135         
136         if (m_endframe < m_startframe)
137                 delta_time = -delta_time;
138
139         if (!(m_flag & ACT_FLAG_REVERSE))
140                 m_localtime = m_startframe + delta_time;
141         else
142                 m_localtime = m_endframe - delta_time;
143 }
144
145
146 bool BL_ActionActuator::Update(double curtime, bool frame)
147 {
148         bool bNegativeEvent = false;
149         bool bPositiveEvent = false;
150         bool keepgoing = true;
151         bool wrap = false;
152         bool apply=true;
153         int     priority;
154         float newweight;
155         
156         // result = true if animation has to be continued, false if animation stops
157         // maybe there are events for us in the queue !
158         if (frame)
159         {
160                 for (vector<CValue*>::iterator i=m_events.begin(); !(i==m_events.end());i++)
161                 {
162                         if ((*i)->GetNumber() == 0.0f)
163                                 bNegativeEvent = true;
164                         else
165                                 bPositiveEvent= true;
166                         (*i)->Release();
167                 
168                 }
169                 m_events.clear();
170                 
171                 if (bPositiveEvent)
172                         m_flag |= ACT_FLAG_ACTIVE;
173                 
174                 if (bNegativeEvent)
175                 {
176                         // dont continue where we left off when restarting
177                         if (m_end_reset) {
178                                 m_flag &= ~ACT_FLAG_LOCKINPUT;
179                         }
180                         
181                         if (!(m_flag & ACT_FLAG_ACTIVE))
182                                 return false;
183                         m_flag &= ~ACT_FLAG_ACTIVE;
184                 }
185         }
186         
187         /*      We know that action actuators have been discarded from all non armature objects:
188         if we're being called, we're attached to a BL_ArmatureObject */
189         BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
190         float length = m_endframe - m_startframe;
191         
192         priority = m_priority;
193         
194         /* Determine pre-incrementation behaviour and set appropriate flags */
195         switch (m_playtype){
196         case ACT_ACTION_MOTION:
197                 if (bNegativeEvent){
198                         keepgoing=false;
199                         apply=false;
200                 };
201                 break;
202         case ACT_ACTION_FROM_PROP:
203                 if (bNegativeEvent){
204                         apply=false;
205                         keepgoing=false;
206                 }
207                 break;
208         case ACT_ACTION_LOOP_END:
209                 if (bPositiveEvent){
210                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
211                                 m_flag &= ~ACT_FLAG_KEYUP;
212                                 m_flag &= ~ACT_FLAG_REVERSE;
213                                 m_flag |= ACT_FLAG_LOCKINPUT;
214                                 m_localtime = m_startframe;
215                                 m_starttime = curtime;
216                         }
217                 }
218                 if (bNegativeEvent){
219                         m_flag |= ACT_FLAG_KEYUP;
220                 }
221                 break;
222         case ACT_ACTION_LOOP_STOP:
223                 if (bPositiveEvent){
224                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
225                                 m_flag &= ~ACT_FLAG_REVERSE;
226                                 m_flag &= ~ACT_FLAG_KEYUP;
227                                 m_flag |= ACT_FLAG_LOCKINPUT;
228                                 SetStartTime(curtime);
229                         }
230                 }
231                 if (bNegativeEvent){
232                         m_flag |= ACT_FLAG_KEYUP;
233                         m_flag &= ~ACT_FLAG_LOCKINPUT;
234                         keepgoing=false;
235                         apply=false;
236                 }
237                 break;
238         case ACT_ACTION_FLIPPER:
239                 if (bPositiveEvent){
240                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
241                                 m_flag &= ~ACT_FLAG_REVERSE;
242                                 m_flag |= ACT_FLAG_LOCKINPUT;
243                                 SetStartTime(curtime);
244                         }
245                 }
246                 else if (bNegativeEvent){
247                         m_flag |= ACT_FLAG_REVERSE;
248                         m_flag &= ~ACT_FLAG_LOCKINPUT;
249                         SetStartTime(curtime);
250                 }
251                 break;
252         case ACT_ACTION_PLAY:
253                 if (bPositiveEvent){
254                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
255                                 m_flag &= ~ACT_FLAG_REVERSE;
256                                 m_localtime = m_starttime;
257                                 m_starttime = curtime;
258                                 m_flag |= ACT_FLAG_LOCKINPUT;
259                         }
260                 }
261                 break;
262         default:
263                 break;
264         }
265         
266         /* Perform increment */
267         if (keepgoing){
268                 if (m_playtype == ACT_ACTION_MOTION){
269                         MT_Point3       newpos;
270                         MT_Point3       deltapos;
271                         
272                         newpos = obj->NodeGetWorldPosition();
273                         
274                         /* Find displacement */
275                         deltapos = newpos-m_lastpos;
276                         m_localtime += (length/m_stridelength) * deltapos.length();
277                         m_lastpos = newpos;
278                 }
279                 else{
280                         SetLocalTime(curtime);
281                 }
282         }
283         
284         /* Check if a wrapping response is needed */
285         if (length){
286                 if (m_localtime < m_startframe || m_localtime > m_endframe)
287                 {
288                         m_localtime = m_startframe + fmod(m_localtime, length);
289                         wrap = true;
290                 }
291         }
292         else
293                 m_localtime = m_startframe;
294         
295         /* Perform post-increment tasks */
296         switch (m_playtype){
297         case ACT_ACTION_FROM_PROP:
298                 {
299                         CValue* propval = GetParent()->GetProperty(m_propname);
300                         if (propval)
301                                 m_localtime = propval->GetNumber();
302                         
303                         if (bNegativeEvent){
304                                 keepgoing=false;
305                         }
306                 }
307                 break;
308         case ACT_ACTION_MOTION:
309                 break;
310         case ACT_ACTION_LOOP_STOP:
311                 break;
312         case ACT_ACTION_FLIPPER:
313                 if (wrap){
314                         if (!(m_flag & ACT_FLAG_REVERSE)){
315                                 m_localtime=m_endframe;
316                                 //keepgoing = false;
317                         }
318                         else {
319                                 m_localtime=m_startframe;
320                                 keepgoing = false;
321                         }
322                 }
323                 break;
324         case ACT_ACTION_LOOP_END:
325                 if (wrap){
326                         if (m_flag & ACT_FLAG_KEYUP){
327                                 keepgoing = false;
328                                 m_localtime = m_endframe;
329                                 m_flag &= ~ACT_FLAG_LOCKINPUT;
330                         }
331                         SetStartTime(curtime);
332                 }
333                 break;
334         case ACT_ACTION_PLAY:
335                 if (wrap){
336                         m_localtime = m_endframe;
337                         keepgoing = false;
338                         m_flag &= ~ACT_FLAG_LOCKINPUT;
339                 }
340                 break;
341         default:
342                 keepgoing = false;
343                 break;
344         }
345         
346         /* Set the property if its defined */
347         if (m_framepropname[0] != '\0') {
348                 CValue* propowner = GetParent();
349                 CValue* oldprop = propowner->GetProperty(m_framepropname);
350                 CValue* newval = new CFloatValue(m_localtime);
351                 if (oldprop) {
352                         oldprop->SetValue(newval);
353                 } else {
354                         propowner->SetProperty(m_framepropname, newval);
355                 }
356                 newval->Release();
357         }
358         
359         if (bNegativeEvent)
360                 m_blendframe=0.0;
361         
362         /* Apply the pose if necessary*/
363         if (apply){
364
365                 /* Priority test */
366                 if (obj->SetActiveAction(this, priority, curtime)){
367                         
368                         /* Get the underlying pose from the armature */
369                         obj->GetPose(&m_pose);
370                         
371                         /* Override the necessary channels with ones from the action */
372                         extract_pose_from_action(m_pose, m_action, m_localtime);
373
374                         /* Perform the user override (if any) */
375                         if (m_userpose){
376                                 extract_pose_from_pose(m_pose, m_userpose);
377 //                              clear_pose(m_userpose);
378                                 MEM_freeN(m_userpose);
379                                 m_userpose = NULL;
380                         }
381 #if 1
382                         /* Handle blending */
383                         if (m_blendin && (m_blendframe<m_blendin)){
384                                 /* If this is the start of a blending sequence... */
385                                 if ((m_blendframe==0.0) || (!m_blendpose)){
386                                         obj->GetMRDPose(&m_blendpose);
387                                         m_blendstart = curtime;
388                                 }
389                                 
390                                 /* Find percentages */
391                                 newweight = (m_blendframe/(float)m_blendin);
392                                 blend_poses(m_pose, m_blendpose, 1.0 - newweight, ACTSTRIPMODE_BLEND);
393
394                                 /* Increment current blending percentage */
395                                 m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
396                                 if (m_blendframe>m_blendin)
397                                         m_blendframe = m_blendin;
398                                 
399                         }
400 #endif
401                         m_lastUpdate = m_localtime;
402                         obj->SetPose (m_pose);
403                 }
404                 else{
405                         m_blendframe = 0.0;
406                 }
407         }
408         
409         if (!keepgoing){
410                 m_blendframe = 0.0;
411         }
412         return keepgoing;
413 };
414
415 /* ------------------------------------------------------------------------- */
416 /* Python functions                                                          */
417 /* ------------------------------------------------------------------------- */
418
419 /* Integration hooks ------------------------------------------------------- */
420
421 PyTypeObject BL_ActionActuator::Type = {
422         PyObject_HEAD_INIT(&PyType_Type)
423                 0,
424                 "BL_ActionActuator",
425                 sizeof(BL_ActionActuator),
426                 0,
427                 PyDestructor,
428                 0,
429                 __getattr,
430                 __setattr,
431                 0, //&MyPyCompare,
432                 __repr,
433                 0, //&cvalue_as_number,
434                 0,
435                 0,
436                 0,
437                 0
438 };
439
440 PyParentObject BL_ActionActuator::Parents[] = {
441         &BL_ActionActuator::Type,
442                 &SCA_IActuator::Type,
443                 &SCA_ILogicBrick::Type,
444                 &CValue::Type,
445                 NULL
446 };
447
448 PyMethodDef BL_ActionActuator::Methods[] = {
449         {"setAction", (PyCFunction) BL_ActionActuator::sPySetAction, METH_VARARGS, SetAction_doc},
450         {"setStart", (PyCFunction) BL_ActionActuator::sPySetStart, METH_VARARGS, SetStart_doc},
451         {"setEnd", (PyCFunction) BL_ActionActuator::sPySetEnd, METH_VARARGS, SetEnd_doc},
452         {"setBlendin", (PyCFunction) BL_ActionActuator::sPySetBlendin, METH_VARARGS, SetBlendin_doc},
453         {"setPriority", (PyCFunction) BL_ActionActuator::sPySetPriority, METH_VARARGS, SetPriority_doc},
454         {"setFrame", (PyCFunction) BL_ActionActuator::sPySetFrame, METH_VARARGS, SetFrame_doc},
455         {"setProperty", (PyCFunction) BL_ActionActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
456         {"setFrameProperty", (PyCFunction) BL_ActionActuator::sPySetFrameProperty, METH_VARARGS, SetFrameProperty_doc},
457         {"setBlendtime", (PyCFunction) BL_ActionActuator::sPySetBlendtime, METH_VARARGS, SetBlendtime_doc},
458
459         {"getAction", (PyCFunction) BL_ActionActuator::sPyGetAction, METH_VARARGS, GetAction_doc},
460         {"getStart", (PyCFunction) BL_ActionActuator::sPyGetStart, METH_VARARGS, GetStart_doc},
461         {"getEnd", (PyCFunction) BL_ActionActuator::sPyGetEnd, METH_VARARGS, GetEnd_doc},
462         {"getBlendin", (PyCFunction) BL_ActionActuator::sPyGetBlendin, METH_VARARGS, GetBlendin_doc},
463         {"getPriority", (PyCFunction) BL_ActionActuator::sPyGetPriority, METH_VARARGS, GetPriority_doc},
464         {"getFrame", (PyCFunction) BL_ActionActuator::sPyGetFrame, METH_VARARGS, GetFrame_doc},
465         {"getProperty", (PyCFunction) BL_ActionActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc},
466         {"getFrameProperty", (PyCFunction) BL_ActionActuator::sPyGetFrameProperty, METH_VARARGS, GetFrameProperty_doc},
467         {"setChannel", (PyCFunction) BL_ActionActuator::sPySetChannel, METH_VARARGS, SetChannel_doc},
468 //      {"getChannel", (PyCFunction) BL_ActionActuator::sPyGetChannel, METH_VARARGS},
469         {"getType", (PyCFunction) BL_ActionActuator::sPyGetType, METH_VARARGS, GetType_doc},
470         {"setType", (PyCFunction) BL_ActionActuator::sPySetType, METH_VARARGS, SetType_doc},
471         {"getContinue", (PyCFunction) BL_ActionActuator::sPyGetContinue, METH_NOARGS, 0},       
472         {"setContinue", (PyCFunction) BL_ActionActuator::sPySetContinue, METH_O, 0},
473         {NULL,NULL} //Sentinel
474 };
475
476 PyObject* BL_ActionActuator::_getattr(const STR_String& attr) {
477         _getattr_up(SCA_IActuator);
478 }
479
480 /*     setStart                                                              */
481 char BL_ActionActuator::GetAction_doc[] = 
482 "getAction()\n"
483 "\tReturns a string containing the name of the current action.\n";
484
485 PyObject* BL_ActionActuator::PyGetAction(PyObject* self, 
486                                                                                  PyObject* args, 
487                                                                                  PyObject* kwds) {
488         if (m_action){
489                 return PyString_FromString(m_action->id.name+2);
490         }
491         Py_RETURN_NONE;
492 }
493
494 /*     getProperty                                                             */
495 char BL_ActionActuator::GetProperty_doc[] = 
496 "getProperty()\n"
497 "\tReturns the name of the property to be used in FromProp mode.\n";
498
499 PyObject* BL_ActionActuator::PyGetProperty(PyObject* self, 
500                                                                                    PyObject* args, 
501                                                                                    PyObject* kwds) {
502         PyObject *result;
503         
504         result = Py_BuildValue("s", (const char *)m_propname);
505         
506         return result;
507 }
508
509 /*     getProperty                                                             */
510 char BL_ActionActuator::GetFrameProperty_doc[] = 
511 "getFrameProperty()\n"
512 "\tReturns the name of the property, that is set to the current frame number.\n";
513
514 PyObject* BL_ActionActuator::PyGetFrameProperty(PyObject* self, 
515                                                                                    PyObject* args, 
516                                                                                    PyObject* kwds) {
517         PyObject *result;
518         
519         result = Py_BuildValue("s", (const char *)m_framepropname);
520         
521         return result;
522 }
523
524 /*     getFrame                                                              */
525 char BL_ActionActuator::GetFrame_doc[] = 
526 "getFrame()\n"
527 "\tReturns the current frame number.\n";
528
529 PyObject* BL_ActionActuator::PyGetFrame(PyObject* self, 
530                                                                                 PyObject* args, 
531                                                                                 PyObject* kwds) {
532         PyObject *result;
533         
534         result = Py_BuildValue("f", m_localtime);
535         
536         return result;
537 }
538
539 /*     getEnd                                                                */
540 char BL_ActionActuator::GetEnd_doc[] = 
541 "getEnd()\n"
542 "\tReturns the last frame of the action.\n";
543
544 PyObject* BL_ActionActuator::PyGetEnd(PyObject* self, 
545                                                                           PyObject* args, 
546                                                                           PyObject* kwds) {
547         PyObject *result;
548         
549         result = Py_BuildValue("f", m_endframe);
550         
551         return result;
552 }
553
554 /*     getStart                                                              */
555 char BL_ActionActuator::GetStart_doc[] = 
556 "getStart()\n"
557 "\tReturns the starting frame of the action.\n";
558
559 PyObject* BL_ActionActuator::PyGetStart(PyObject* self, 
560                                                                                 PyObject* args, 
561                                                                                 PyObject* kwds) {
562         PyObject *result;
563         
564         result = Py_BuildValue("f", m_startframe);
565         
566         return result;
567 }
568
569 /*     getBlendin                                                            */
570 char BL_ActionActuator::GetBlendin_doc[] = 
571 "getBlendin()\n"
572 "\tReturns the number of interpolation animation frames to be\n"
573 "\tgenerated when this actuator is triggered.\n";
574
575 PyObject* BL_ActionActuator::PyGetBlendin(PyObject* self, 
576                                                                                   PyObject* args, 
577                                                                                   PyObject* kwds) {
578         PyObject *result;
579         
580         result = Py_BuildValue("f", m_blendin);
581         
582         return result;
583 }
584
585 /*     getPriority                                                           */
586 char BL_ActionActuator::GetPriority_doc[] = 
587 "getPriority()\n"
588 "\tReturns the priority for this actuator.  Actuators with lower\n"
589 "\tPriority numbers will override actuators with higher numbers.\n";
590
591 PyObject* BL_ActionActuator::PyGetPriority(PyObject* self, 
592                                                                                    PyObject* args, 
593                                                                                    PyObject* kwds) {
594         PyObject *result;
595         
596         result = Py_BuildValue("i", m_priority);
597         
598         return result;
599 }
600
601 /*     setAction                                                             */
602 char BL_ActionActuator::SetAction_doc[] = 
603 "setAction(action, (reset))\n"
604 "\t - action    : The name of the action to set as the current action.\n"
605 "\t - reset     : Optional parameter indicating whether to reset the\n"
606 "\t               blend timer or not.  A value of 1 indicates that the\n"
607 "\t               timer should be reset.  A value of 0 will leave it\n"
608 "\t               unchanged.  If reset is not specified, the timer will"
609 "\t                   be reset.\n";
610
611 PyObject* BL_ActionActuator::PySetAction(PyObject* self, 
612                                                                                  PyObject* args, 
613                                                                                  PyObject* kwds) {
614         char *string;
615         int     reset = 1;
616
617         if (PyArg_ParseTuple(args,"s|i",&string, &reset))
618         {
619                 bAction *action;
620                 
621                 action = (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(STR_String(string));
622                 
623                 if (!action){
624                         /* NOTE!  Throw an exception or something */
625                         //                      printf ("setAction failed: Action not found\n", string);
626                 }
627                 else{
628                         m_action=action;
629                         if (reset)
630                                 m_blendframe = 0;
631                 }
632         }
633         else {
634                 return NULL;
635         }
636         
637         Py_RETURN_NONE;
638 }
639
640 /*     setStart                                                              */
641 char BL_ActionActuator::SetStart_doc[] = 
642 "setStart(start)\n"
643 "\t - start     : Specifies the starting frame of the animation.\n";
644
645 PyObject* BL_ActionActuator::PySetStart(PyObject* self, 
646                                                                                 PyObject* args, 
647                                                                                 PyObject* kwds) {
648         float start;
649         
650         if (PyArg_ParseTuple(args,"f",&start))
651         {
652                 m_startframe = start;
653         }
654         else {
655                 return NULL;
656         }
657         
658         Py_RETURN_NONE;
659 }
660
661 /*     setEnd                                                                */
662 char BL_ActionActuator::SetEnd_doc[] = 
663 "setEnd(end)\n"
664 "\t - end       : Specifies the ending frame of the animation.\n";
665
666 PyObject* BL_ActionActuator::PySetEnd(PyObject* self, 
667                                                                           PyObject* args, 
668                                                                           PyObject* kwds) {
669         float end;
670         
671         if (PyArg_ParseTuple(args,"f",&end))
672         {
673                 m_endframe = end;
674         }
675         else {
676                 return NULL;
677         }
678         
679         Py_RETURN_NONE;
680 }
681
682 /*     setBlendin                                                            */
683 char BL_ActionActuator::SetBlendin_doc[] = 
684 "setBlendin(blendin)\n"
685 "\t - blendin   : Specifies the number of frames of animation to generate\n"
686 "\t               when making transitions between actions.\n";
687
688 PyObject* BL_ActionActuator::PySetBlendin(PyObject* self, 
689                                                                                   PyObject* args, 
690                                                                                   PyObject* kwds) {
691         float blendin;
692         
693         if (PyArg_ParseTuple(args,"f",&blendin))
694         {
695                 m_blendin = blendin;
696         }
697         else {
698                 return NULL;
699         }
700         
701         Py_RETURN_NONE;
702 }
703
704 /*     setBlendtime                                                          */
705 char BL_ActionActuator::SetBlendtime_doc[] = 
706 "setBlendtime(blendtime)\n"
707 "\t - blendtime : Allows the script to directly modify the internal timer\n"
708 "\t               used when generating transitions between actions.  This\n"
709 "\t               parameter must be in the range from 0.0 to 1.0.\n";
710
711 PyObject* BL_ActionActuator::PySetBlendtime(PyObject* self, 
712                                                                                   PyObject* args, 
713                                                                                   PyObject* kwds) {
714         float blendframe;
715         
716         if (PyArg_ParseTuple(args,"f",&blendframe))
717         {
718                 m_blendframe = blendframe * m_blendin;
719                 if (m_blendframe<0)
720                         m_blendframe = 0;
721                 if (m_blendframe>m_blendin)
722                         m_blendframe = m_blendin;
723         }
724         else {
725                 return NULL;
726         }
727         
728         Py_RETURN_NONE;
729 }
730
731 /*     setPriority                                                           */
732 char BL_ActionActuator::SetPriority_doc[] = 
733 "setPriority(priority)\n"
734 "\t - priority  : Specifies the new priority.  Actuators will lower\n"
735 "\t               priority numbers will override actuators with higher\n"
736 "\t               numbers.\n";
737
738 PyObject* BL_ActionActuator::PySetPriority(PyObject* self, 
739                                                                                    PyObject* args, 
740                                                                                    PyObject* kwds) {
741         int priority;
742         
743         if (PyArg_ParseTuple(args,"i",&priority))
744         {
745                 m_priority = priority;
746         }
747         else {
748                 return NULL;
749         }
750         
751         Py_RETURN_NONE;
752 }
753
754 /*     setFrame                                                              */
755 char BL_ActionActuator::SetFrame_doc[] = 
756 "setFrame(frame)\n"
757 "\t - frame     : Specifies the new current frame for the animation\n";
758
759 PyObject* BL_ActionActuator::PySetFrame(PyObject* self, 
760                                                                                 PyObject* args, 
761                                                                                 PyObject* kwds) {
762         float frame;
763         
764         if (PyArg_ParseTuple(args,"f",&frame))
765         {
766                 m_localtime = frame;
767                 if (m_localtime<m_startframe)
768                         m_localtime=m_startframe;
769                 else if (m_localtime>m_endframe)
770                         m_localtime=m_endframe;
771         }
772         else {
773                 return NULL;
774         }
775         
776         Py_RETURN_NONE;
777 }
778
779 /*     setProperty                                                           */
780 char BL_ActionActuator::SetProperty_doc[] = 
781 "setProperty(prop)\n"
782 "\t - prop      : A string specifying the property name to be used in\n"
783 "\t               FromProp playback mode.\n";
784
785 PyObject* BL_ActionActuator::PySetProperty(PyObject* self, 
786                                                                                    PyObject* args, 
787                                                                                    PyObject* kwds) {
788         char *string;
789         
790         if (PyArg_ParseTuple(args,"s",&string))
791         {
792                 m_propname = string;
793         }
794         else {
795                 return NULL;
796         }
797         
798         Py_RETURN_NONE;
799 }
800
801 /*     setFrameProperty                                                          */
802 char BL_ActionActuator::SetFrameProperty_doc[] = 
803 "setFrameProperty(prop)\n"
804 "\t - prop      : A string specifying the property of the frame set up update.\n";
805
806 PyObject* BL_ActionActuator::PySetFrameProperty(PyObject* self, 
807                                                                                    PyObject* args, 
808                                                                                    PyObject* kwds) {
809         char *string;
810         
811         if (PyArg_ParseTuple(args,"s",&string))
812         {
813                 m_framepropname = string;
814         }
815         else {
816                 return NULL;
817         }
818         
819         Py_RETURN_NONE;
820 }
821
822 /*
823 PyObject* BL_ActionActuator::PyGetChannel(PyObject* self, 
824                                                                                    PyObject* args, 
825                                                                                    PyObject* kwds) {
826         char *string;
827         
828         if (PyArg_ParseTuple(args,"s",&string))
829         {
830                 m_propname = string;
831         }
832         else {
833                 return NULL;
834         }
835         
836         Py_RETURN_NONE;
837 }
838 */
839
840 /*     setChannel                                                            */
841 char BL_ActionActuator::SetChannel_doc[] = 
842 "setChannel(channel, matrix)\n"
843 "\t - channel   : A string specifying the name of the bone channel.\n"
844 "\t - matrix    : A 4x4 matrix specifying the overriding transformation\n"
845 "\t               as an offset from the bone's rest position.\n";
846
847 PyObject* BL_ActionActuator::PySetChannel(PyObject* self, 
848                                                                                    PyObject* args, 
849                                                                                    PyObject* kwds) 
850 {
851         float matrix[4][4];
852         char *string;
853         PyObject* pylist;
854         bool    error = false;
855         int row,col;
856         int     mode = 0;       /* 0 for bone space, 1 for armature/world space */
857         
858         if (!PyArg_ParseTuple(args,"sO|i", &string, &pylist, &mode))
859                 return NULL;
860         
861         if (pylist->ob_type == &CListValue::Type)
862         {
863                 CListValue* listval = (CListValue*) pylist;
864                 if (listval->GetCount() == 4)
865                 {
866                         for (row=0;row<4;row++) // each row has a 4-vector [x,y,z, w]
867                         {
868                                 CListValue* vecval = (CListValue*)listval->GetValue(row);
869                                 for (col=0;col<4;col++)
870                                 {
871                                         matrix[row][col] = vecval->GetValue(col)->GetNumber();
872                                         
873                                 }
874                         }
875                 }
876                 else
877                 {
878                         error = true;
879                 }
880         }
881         else
882         {
883                 // assert the list is long enough...
884                 int numitems = PyList_Size(pylist);
885                 if (numitems == 4)
886                 {
887                         for (row=0;row<4;row++) // each row has a 4-vector [x,y,z, w]
888                         {
889                                 
890                                 PyObject* veclist = PyList_GetItem(pylist,row); // here we have a vector4 list
891                                 for (col=0;col<4;col++)
892                                 {
893                                         matrix[row][col] =  PyFloat_AsDouble(PyList_GetItem(veclist,col));
894                                         
895                                 }
896                         }
897                 }
898                 else
899                 {
900                         error = true;
901                 }
902         }
903         
904         if (!error)
905         {
906
907 /*      DO IT HERE */
908                 bPoseChannel *pchan= verify_pose_channel(m_userpose, string);
909
910                 Mat4ToQuat(matrix, pchan->quat);
911                 Mat4ToSize(matrix, pchan->size);
912                 VECCOPY (pchan->loc, matrix[3]);
913                 
914                 pchan->flag |= POSE_ROT|POSE_LOC|POSE_SIZE;
915
916                 if (!m_userpose){
917                         m_userpose = (bPose*)MEM_callocN(sizeof(bPose), "userPose");
918                 }
919         }
920         
921         Py_RETURN_NONE;
922 }
923
924 /* getType */
925 char BL_ActionActuator::GetType_doc[] =
926 "getType()\n"
927 "\tReturns the operation mode of the actuator.\n";
928 PyObject* BL_ActionActuator::PyGetType(PyObject* self,
929                                        PyObject* args, 
930                                        PyObject* kwds) {
931     return Py_BuildValue("h", m_playtype);
932 }
933
934 /* setType */
935 char BL_ActionActuator::SetType_doc[] =
936 "setType(mode)\n"
937 "\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n"
938 "\tSet the operation mode of the actuator.\n";
939 PyObject* BL_ActionActuator::PySetType(PyObject* self,
940                                        PyObject* args,
941                                        PyObject* kwds) {
942         short typeArg;
943                                                                                                              
944     if (!PyArg_ParseTuple(args, "h", &typeArg)) {
945         return NULL;
946     }
947
948         switch (typeArg) {
949         case KX_ACT_ACTION_PLAY:
950         case KX_ACT_ACTION_FLIPPER:
951         case KX_ACT_ACTION_LOOPSTOP:
952         case KX_ACT_ACTION_LOOPEND:
953         case KX_ACT_ACTION_PROPERTY:
954                 m_playtype = typeArg;
955                 break;
956         default:
957                 printf("Invalid type for action actuator: %d\n", typeArg); /* error */
958     }
959         Py_RETURN_NONE;
960 }
961
962 PyObject* BL_ActionActuator::PyGetContinue(PyObject* self) {
963     return PyInt_FromLong((long)(m_end_reset==0));
964 }
965
966 PyObject* BL_ActionActuator::PySetContinue(PyObject* self, PyObject* value) {
967         int param = PyObject_IsTrue( value );
968         
969         if( param == -1 ) {
970                 PyErr_SetString( PyExc_TypeError, "expected True/False or 0/1" );
971                 return NULL;
972         }
973
974         if (param) {
975                 m_end_reset = 0;
976         } else {
977                 m_end_reset = 1;
978         }
979     Py_RETURN_NONE;
980 }
981