fix memleak in BGE py api - action.channelNames
[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_nla_types.h"
43 #include "BKE_action.h"
44 #include "DNA_action_types.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 #include "KX_PyMath.h"
54 #include "blendef.h"
55
56 #ifdef HAVE_CONFIG_H
57 #include <config.h>
58 #endif
59
60 BL_ActionActuator::~BL_ActionActuator()
61 {
62         if (m_pose)
63                 game_free_pose(m_pose);
64         if (m_userpose)
65                 game_free_pose(m_userpose);
66         if (m_blendpose)
67                 game_free_pose(m_blendpose);
68 }
69
70 void BL_ActionActuator::ProcessReplica()
71 {
72         SCA_IActuator::ProcessReplica();
73         
74         m_pose = NULL;
75         m_blendpose = NULL;
76         m_localtime=m_startframe;
77         m_lastUpdate=-1;
78         
79 }
80
81 void BL_ActionActuator::SetBlendTime (float newtime){
82         m_blendframe = newtime;
83 }
84
85 CValue* BL_ActionActuator::GetReplica() {
86         BL_ActionActuator* replica = new BL_ActionActuator(*this);//m_float,GetName());
87         replica->ProcessReplica();
88         return replica;
89 }
90
91 bool BL_ActionActuator::ClampLocalTime()
92 {
93         if (m_startframe < m_endframe)
94         {
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         } else {
106                 if (m_localtime > m_startframe)
107                 {
108                         m_localtime = m_startframe;
109                         return true;
110                 }
111                 else if (m_localtime < m_endframe)
112                 {
113                         m_localtime = m_endframe;
114                         return true;
115                 }
116         }
117         return false;
118 }
119
120 void BL_ActionActuator::SetStartTime(float curtime)
121 {
122         float direction = m_startframe < m_endframe ? 1.0 : -1.0;
123         
124         if (!(m_flag & ACT_FLAG_REVERSE))
125                 m_starttime = curtime - direction*(m_localtime - m_startframe)/KX_KetsjiEngine::GetAnimFrameRate();
126         else
127                 m_starttime = curtime - direction*(m_endframe - m_localtime)/KX_KetsjiEngine::GetAnimFrameRate();
128 }
129
130 void BL_ActionActuator::SetLocalTime(float curtime)
131 {
132         float delta_time = (curtime - m_starttime)*KX_KetsjiEngine::GetAnimFrameRate();
133         
134         if (m_endframe < m_startframe)
135                 delta_time = -delta_time;
136
137         if (!(m_flag & ACT_FLAG_REVERSE))
138                 m_localtime = m_startframe + delta_time;
139         else
140                 m_localtime = m_endframe - delta_time;
141 }
142
143
144 bool BL_ActionActuator::Update(double curtime, bool frame)
145 {
146         bool bNegativeEvent = false;
147         bool bPositiveEvent = false;
148         bool keepgoing = true;
149         bool wrap = false;
150         bool apply=true;
151         int     priority;
152         float newweight;
153
154         curtime -= KX_KetsjiEngine::GetSuspendedDelta();
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                 bNegativeEvent = m_negevent;
161                 bPositiveEvent = m_posevent;
162                 RemoveAllEvents();
163                 
164                 if (bPositiveEvent)
165                         m_flag |= ACT_FLAG_ACTIVE;
166                 
167                 if (bNegativeEvent)
168                 {
169                         // dont continue where we left off when restarting
170                         if (m_end_reset) {
171                                 m_flag &= ~ACT_FLAG_LOCKINPUT;
172                         }
173                         
174                         if (!(m_flag & ACT_FLAG_ACTIVE))
175                                 return false;
176                         m_flag &= ~ACT_FLAG_ACTIVE;
177                 }
178         }
179         
180         /*      We know that action actuators have been discarded from all non armature objects:
181         if we're being called, we're attached to a BL_ArmatureObject */
182         BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
183         float length = m_endframe - m_startframe;
184         
185         priority = m_priority;
186         
187         /* Determine pre-incrementation behaviour and set appropriate flags */
188         switch (m_playtype){
189         case ACT_ACTION_MOTION:
190                 if (bNegativeEvent){
191                         keepgoing=false;
192                         apply=false;
193                 };
194                 break;
195         case ACT_ACTION_FROM_PROP:
196                 if (bNegativeEvent){
197                         apply=false;
198                         keepgoing=false;
199                 }
200                 break;
201         case ACT_ACTION_LOOP_END:
202                 if (bPositiveEvent){
203                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
204                                 m_flag &= ~ACT_FLAG_KEYUP;
205                                 m_flag &= ~ACT_FLAG_REVERSE;
206                                 m_flag |= ACT_FLAG_LOCKINPUT;
207                                 m_localtime = m_startframe;
208                                 m_starttime = curtime;
209                         }
210                 }
211                 if (bNegativeEvent){
212                         m_flag |= ACT_FLAG_KEYUP;
213                 }
214                 break;
215         case ACT_ACTION_LOOP_STOP:
216                 if (bPositiveEvent){
217                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
218                                 m_flag &= ~ACT_FLAG_REVERSE;
219                                 m_flag &= ~ACT_FLAG_KEYUP;
220                                 m_flag |= ACT_FLAG_LOCKINPUT;
221                                 SetStartTime(curtime);
222                         }
223                 }
224                 if (bNegativeEvent){
225                         m_flag |= ACT_FLAG_KEYUP;
226                         m_flag &= ~ACT_FLAG_LOCKINPUT;
227                         keepgoing=false;
228                         apply=false;
229                 }
230                 break;
231         case ACT_ACTION_FLIPPER:
232                 if (bPositiveEvent){
233                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
234                                 m_flag &= ~ACT_FLAG_REVERSE;
235                                 m_flag |= ACT_FLAG_LOCKINPUT;
236                                 SetStartTime(curtime);
237                         }
238                 }
239                 else if (bNegativeEvent){
240                         m_flag |= ACT_FLAG_REVERSE;
241                         m_flag &= ~ACT_FLAG_LOCKINPUT;
242                         SetStartTime(curtime);
243                 }
244                 break;
245         case ACT_ACTION_PLAY:
246                 if (bPositiveEvent){
247                         if (!(m_flag & ACT_FLAG_LOCKINPUT)){
248                                 m_flag &= ~ACT_FLAG_REVERSE;
249                                 m_localtime = m_starttime;
250                                 m_starttime = curtime;
251                                 m_flag |= ACT_FLAG_LOCKINPUT;
252                         }
253                 }
254                 break;
255         default:
256                 break;
257         }
258         
259         /* Perform increment */
260         if (keepgoing){
261                 if (m_playtype == ACT_ACTION_MOTION){
262                         MT_Point3       newpos;
263                         MT_Point3       deltapos;
264                         
265                         newpos = obj->NodeGetWorldPosition();
266                         
267                         /* Find displacement */
268                         deltapos = newpos-m_lastpos;
269                         m_localtime += (length/m_stridelength) * deltapos.length();
270                         m_lastpos = newpos;
271                 }
272                 else{
273                         SetLocalTime(curtime);
274                 }
275         }
276         
277         /* Check if a wrapping response is needed */
278         if (length){
279                 if (m_localtime < m_startframe || m_localtime > m_endframe)
280                 {
281                         m_localtime = m_startframe + fmod(m_localtime, length);
282                         wrap = true;
283                 }
284         }
285         else
286                 m_localtime = m_startframe;
287         
288         /* Perform post-increment tasks */
289         switch (m_playtype){
290         case ACT_ACTION_FROM_PROP:
291                 {
292                         CValue* propval = GetParent()->GetProperty(m_propname);
293                         if (propval)
294                                 m_localtime = propval->GetNumber();
295                         
296                         if (bNegativeEvent){
297                                 keepgoing=false;
298                         }
299                 }
300                 break;
301         case ACT_ACTION_MOTION:
302                 break;
303         case ACT_ACTION_LOOP_STOP:
304                 break;
305         case ACT_ACTION_FLIPPER:
306                 if (wrap){
307                         if (!(m_flag & ACT_FLAG_REVERSE)){
308                                 m_localtime=m_endframe;
309                                 //keepgoing = false;
310                         }
311                         else {
312                                 m_localtime=m_startframe;
313                                 keepgoing = false;
314                         }
315                 }
316                 break;
317         case ACT_ACTION_LOOP_END:
318                 if (wrap){
319                         if (m_flag & ACT_FLAG_KEYUP){
320                                 keepgoing = false;
321                                 m_localtime = m_endframe;
322                                 m_flag &= ~ACT_FLAG_LOCKINPUT;
323                         }
324                         SetStartTime(curtime);
325                 }
326                 break;
327         case ACT_ACTION_PLAY:
328                 if (wrap){
329                         m_localtime = m_endframe;
330                         keepgoing = false;
331                         m_flag &= ~ACT_FLAG_LOCKINPUT;
332                 }
333                 break;
334         default:
335                 keepgoing = false;
336                 break;
337         }
338         
339         /* Set the property if its defined */
340         if (m_framepropname[0] != '\0') {
341                 CValue* propowner = GetParent();
342                 CValue* oldprop = propowner->GetProperty(m_framepropname);
343                 CValue* newval = new CFloatValue(m_localtime);
344                 if (oldprop) {
345                         oldprop->SetValue(newval);
346                 } else {
347                         propowner->SetProperty(m_framepropname, newval);
348                 }
349                 newval->Release();
350         }
351         
352         if (bNegativeEvent)
353                 m_blendframe=0.0;
354         
355         /* Apply the pose if necessary*/
356         if (apply){
357
358                 /* Priority test */
359                 if (obj->SetActiveAction(this, priority, curtime)){
360                         
361                         /* Get the underlying pose from the armature */
362                         obj->GetPose(&m_pose);
363                         
364                         /* Override the necessary channels with ones from the action */
365                         extract_pose_from_action(m_pose, m_action, m_localtime);
366
367                         /* Perform the user override (if any) */
368                         if (m_userpose){
369                                 extract_pose_from_pose(m_pose, m_userpose);
370                                 game_free_pose(m_userpose); //cant use MEM_freeN(m_userpose) because the channels need freeing too.
371                                 m_userpose = NULL;
372                         }
373 #if 1
374                         /* Handle blending */
375                         if (m_blendin && (m_blendframe<m_blendin)){
376                                 /* If this is the start of a blending sequence... */
377                                 if ((m_blendframe==0.0) || (!m_blendpose)){
378                                         obj->GetMRDPose(&m_blendpose);
379                                         m_blendstart = curtime;
380                                 }
381                                 
382                                 /* Find percentages */
383                                 newweight = (m_blendframe/(float)m_blendin);
384                                 blend_poses(m_pose, m_blendpose, 1.0 - newweight, ACTSTRIPMODE_BLEND);
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                         }
392 #endif
393                         m_lastUpdate = m_localtime;
394                         obj->SetPose (m_pose);
395                 }
396                 else{
397                         m_blendframe = 0.0;
398                 }
399         }
400         
401         if (!keepgoing){
402                 m_blendframe = 0.0;
403         }
404         return keepgoing;
405 };
406
407 /* ------------------------------------------------------------------------- */
408 /* Python functions                                                          */
409 /* ------------------------------------------------------------------------- */
410
411 /*     setStart                                                              */
412 const char BL_ActionActuator::GetAction_doc[] = 
413 "getAction()\n"
414 "\tReturns a string containing the name of the current action.\n";
415
416 PyObject* BL_ActionActuator::PyGetAction(PyObject* args, 
417                                                                                  PyObject* kwds) {
418         ShowDeprecationWarning("getAction()", "the action property");
419
420         if (m_action){
421                 return PyString_FromString(m_action->id.name+2);
422         }
423         Py_RETURN_NONE;
424 }
425
426 /*     getProperty                                                             */
427 const char BL_ActionActuator::GetProperty_doc[] = 
428 "getProperty()\n"
429 "\tReturns the name of the property to be used in FromProp mode.\n";
430
431 PyObject* BL_ActionActuator::PyGetProperty(PyObject* args, 
432                                                                                    PyObject* kwds) {
433         ShowDeprecationWarning("getProperty()", "the property property");
434
435         PyObject *result;
436         
437         result = Py_BuildValue("s", (const char *)m_propname);
438         
439         return result;
440 }
441
442 /*     getProperty                                                             */
443 const char BL_ActionActuator::GetFrameProperty_doc[] = 
444 "getFrameProperty()\n"
445 "\tReturns the name of the property, that is set to the current frame number.\n";
446
447 PyObject* BL_ActionActuator::PyGetFrameProperty(PyObject* args, 
448                                                                                    PyObject* kwds) {
449         ShowDeprecationWarning("getFrameProperty()", "the frameProperty property");
450
451         PyObject *result;
452         
453         result = Py_BuildValue("s", (const char *)m_framepropname);
454         
455         return result;
456 }
457
458 /*     getFrame                                                              */
459 const char BL_ActionActuator::GetFrame_doc[] = 
460 "getFrame()\n"
461 "\tReturns the current frame number.\n";
462
463 PyObject* BL_ActionActuator::PyGetFrame(PyObject* args, 
464                                                                                 PyObject* kwds) {
465         ShowDeprecationWarning("getFrame()", "the frame property");
466
467         PyObject *result;
468         
469         result = Py_BuildValue("f", m_localtime);
470         
471         return result;
472 }
473
474 /*     getEnd                                                                */
475 const char BL_ActionActuator::GetEnd_doc[] = 
476 "getEnd()\n"
477 "\tReturns the last frame of the action.\n";
478
479 PyObject* BL_ActionActuator::PyGetEnd(PyObject* args, 
480                                                                           PyObject* kwds) {
481         ShowDeprecationWarning("getEnd()", "the end property");
482
483         PyObject *result;
484         
485         result = Py_BuildValue("f", m_endframe);
486         
487         return result;
488 }
489
490 /*     getStart                                                              */
491 const char BL_ActionActuator::GetStart_doc[] = 
492 "getStart()\n"
493 "\tReturns the starting frame of the action.\n";
494
495 PyObject* BL_ActionActuator::PyGetStart(PyObject* args, 
496                                                                                 PyObject* kwds) {
497         ShowDeprecationWarning("getStart()", "the start property");
498
499         PyObject *result;
500         
501         result = Py_BuildValue("f", m_startframe);
502         
503         return result;
504 }
505
506 /*     getBlendin                                                            */
507 const char BL_ActionActuator::GetBlendin_doc[] = 
508 "getBlendin()\n"
509 "\tReturns the number of interpolation animation frames to be\n"
510 "\tgenerated when this actuator is triggered.\n";
511
512 PyObject* BL_ActionActuator::PyGetBlendin(PyObject* args, 
513                                                                                   PyObject* kwds) {
514         ShowDeprecationWarning("getBlendin()", "the blendin property");
515
516         PyObject *result;
517         
518         result = Py_BuildValue("f", m_blendin);
519         
520         return result;
521 }
522
523 /*     getPriority                                                           */
524 const char BL_ActionActuator::GetPriority_doc[] = 
525 "getPriority()\n"
526 "\tReturns the priority for this actuator.  Actuators with lower\n"
527 "\tPriority numbers will override actuators with higher numbers.\n";
528
529 PyObject* BL_ActionActuator::PyGetPriority(PyObject* args, 
530                                                                                    PyObject* kwds) {
531         ShowDeprecationWarning("getPriority()", "the priority property");
532
533         PyObject *result;
534         
535         result = Py_BuildValue("i", m_priority);
536         
537         return result;
538 }
539
540 /*     setAction                                                             */
541 const char BL_ActionActuator::SetAction_doc[] = 
542 "setAction(action, (reset))\n"
543 "\t - action    : The name of the action to set as the current action.\n"
544 "\t - reset     : Optional parameter indicating whether to reset the\n"
545 "\t               blend timer or not.  A value of 1 indicates that the\n"
546 "\t               timer should be reset.  A value of 0 will leave it\n"
547 "\t               unchanged.  If reset is not specified, the timer will"
548 "\t                   be reset.\n";
549
550 PyObject* BL_ActionActuator::PySetAction(PyObject* args, 
551                                                                                  PyObject* kwds) {
552         ShowDeprecationWarning("setAction()", "the action property");
553
554         char *string;
555         int     reset = 1;
556
557         if (PyArg_ParseTuple(args,"s|i:setAction",&string, &reset))
558         {
559                 bAction *action;
560                 
561                 action = (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(STR_String(string));
562                 
563                 if (!action){
564                         /* NOTE!  Throw an exception or something */
565                         //                      printf ("setAction failed: Action not found\n", string);
566                 }
567                 else{
568                         m_action=action;
569                         if (reset)
570                                 m_blendframe = 0;
571                 }
572         }
573         else {
574                 return NULL;
575         }
576         
577         Py_RETURN_NONE;
578 }
579
580 /*     setStart                                                              */
581 const char BL_ActionActuator::SetStart_doc[] = 
582 "setStart(start)\n"
583 "\t - start     : Specifies the starting frame of the animation.\n";
584
585 PyObject* BL_ActionActuator::PySetStart(PyObject* args, 
586                                                                                 PyObject* kwds) {
587         ShowDeprecationWarning("setStart()", "the start property");
588
589         float start;
590         
591         if (PyArg_ParseTuple(args,"f:setStart",&start))
592         {
593                 m_startframe = start;
594         }
595         else {
596                 return NULL;
597         }
598         
599         Py_RETURN_NONE;
600 }
601
602 /*     setEnd                                                                */
603 const char BL_ActionActuator::SetEnd_doc[] = 
604 "setEnd(end)\n"
605 "\t - end       : Specifies the ending frame of the animation.\n";
606
607 PyObject* BL_ActionActuator::PySetEnd(PyObject* args, 
608                                                                           PyObject* kwds) {
609         ShowDeprecationWarning("setEnd()", "the end property");
610
611         float end;
612         
613         if (PyArg_ParseTuple(args,"f:setEnd",&end))
614         {
615                 m_endframe = end;
616         }
617         else {
618                 return NULL;
619         }
620         
621         Py_RETURN_NONE;
622 }
623
624 /*     setBlendin                                                            */
625 const char BL_ActionActuator::SetBlendin_doc[] = 
626 "setBlendin(blendin)\n"
627 "\t - blendin   : Specifies the number of frames of animation to generate\n"
628 "\t               when making transitions between actions.\n";
629
630 PyObject* BL_ActionActuator::PySetBlendin(PyObject* args, 
631                                                                                   PyObject* kwds) {
632         ShowDeprecationWarning("setBlendin()", "the blendin property");
633
634         float blendin;
635         
636         if (PyArg_ParseTuple(args,"f:setBlendin",&blendin))
637         {
638                 m_blendin = blendin;
639         }
640         else {
641                 return NULL;
642         }
643         
644         Py_RETURN_NONE;
645 }
646
647 /*     setBlendtime                                                          */
648 const char BL_ActionActuator::SetBlendtime_doc[] = 
649 "setBlendtime(blendtime)\n"
650 "\t - blendtime : Allows the script to directly modify the internal timer\n"
651 "\t               used when generating transitions between actions.  This\n"
652 "\t               parameter must be in the range from 0.0 to 1.0.\n";
653
654 PyObject* BL_ActionActuator::PySetBlendtime(PyObject* args, 
655                                                                                   PyObject* kwds) {
656         ShowDeprecationWarning("setBlendtime()", "the blendtime property");
657
658         float blendframe;
659         
660         if (PyArg_ParseTuple(args,"f:setBlendtime",&blendframe))
661         {
662                 m_blendframe = blendframe * m_blendin;
663                 if (m_blendframe<0)
664                         m_blendframe = 0;
665                 if (m_blendframe>m_blendin)
666                         m_blendframe = m_blendin;
667         }
668         else {
669                 return NULL;
670         }
671         
672         Py_RETURN_NONE;
673 }
674
675 /*     setPriority                                                           */
676 const char BL_ActionActuator::SetPriority_doc[] = 
677 "setPriority(priority)\n"
678 "\t - priority  : Specifies the new priority.  Actuators will lower\n"
679 "\t               priority numbers will override actuators with higher\n"
680 "\t               numbers.\n";
681
682 PyObject* BL_ActionActuator::PySetPriority(PyObject* args, 
683                                                                                    PyObject* kwds) {
684         ShowDeprecationWarning("setPriority()", "the priority property");
685
686         int priority;
687         
688         if (PyArg_ParseTuple(args,"i:setPriority",&priority))
689         {
690                 m_priority = priority;
691         }
692         else {
693                 return NULL;
694         }
695         
696         Py_RETURN_NONE;
697 }
698
699 /*     setFrame                                                              */
700 const char BL_ActionActuator::SetFrame_doc[] = 
701 "setFrame(frame)\n"
702 "\t - frame     : Specifies the new current frame for the animation\n";
703
704 PyObject* BL_ActionActuator::PySetFrame(PyObject* args, 
705                                                                                 PyObject* kwds) {
706         ShowDeprecationWarning("setFrame()", "the frame property");
707
708         float frame;
709         
710         if (PyArg_ParseTuple(args,"f:setFrame",&frame))
711         {
712                 m_localtime = frame;
713                 if (m_localtime<m_startframe)
714                         m_localtime=m_startframe;
715                 else if (m_localtime>m_endframe)
716                         m_localtime=m_endframe;
717         }
718         else {
719                 return NULL;
720         }
721         
722         Py_RETURN_NONE;
723 }
724
725 /*     setProperty                                                           */
726 const char BL_ActionActuator::SetProperty_doc[] = 
727 "setProperty(prop)\n"
728 "\t - prop      : A string specifying the property name to be used in\n"
729 "\t               FromProp playback mode.\n";
730
731 PyObject* BL_ActionActuator::PySetProperty(PyObject* args, 
732                                                                                    PyObject* kwds) {
733         ShowDeprecationWarning("setProperty()", "the property property");
734
735         char *string;
736         
737         if (PyArg_ParseTuple(args,"s:setProperty",&string))
738         {
739                 m_propname = string;
740         }
741         else {
742                 return NULL;
743         }
744         
745         Py_RETURN_NONE;
746 }
747
748 /*     setFrameProperty                                                          */
749 const char BL_ActionActuator::SetFrameProperty_doc[] = 
750 "setFrameProperty(prop)\n"
751 "\t - prop      : A string specifying the property of the frame set up update.\n";
752
753 PyObject* BL_ActionActuator::PySetFrameProperty(PyObject* args, 
754                                                                                    PyObject* kwds) {
755         ShowDeprecationWarning("setFrameProperty()", "the frameProperty property");
756
757         char *string;
758         
759         if (PyArg_ParseTuple(args,"s:setFrameProperty",&string))
760         {
761                 m_framepropname = string;
762         }
763         else {
764                 return NULL;
765         }
766         
767         Py_RETURN_NONE;
768 }
769
770 PyObject* BL_ActionActuator::PyGetChannel(PyObject* value) {
771         char *string= PyString_AsString(value);
772         
773         if (!string) {
774                 PyErr_SetString(PyExc_TypeError, "expected a single string");
775                 return NULL;
776         }
777         
778         bPoseChannel *pchan;
779         
780         if(m_userpose==NULL && m_pose==NULL) {
781                 BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
782                 obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
783         }
784         
785         // get_pose_channel accounts for NULL pose, run on both incase one exists but
786         // the channel doesnt
787         if(             !(pchan=get_pose_channel(m_userpose, string)) &&
788                         !(pchan=get_pose_channel(m_pose, string))  )
789         {
790                 PyErr_SetString(PyExc_ValueError, "channel doesnt exist");
791                 return NULL;
792         }
793
794         PyObject *ret = PyTuple_New(3);
795         
796         PyObject *list = PyList_New(3); 
797         PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->loc[0]));
798         PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->loc[1]));
799         PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->loc[2]));
800         PyTuple_SET_ITEM(ret, 0, list);
801         
802         list = PyList_New(3);
803         PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->size[0]));
804         PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->size[1]));
805         PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->size[2]));
806         PyTuple_SET_ITEM(ret, 1, list);
807         
808         list = PyList_New(4);
809         PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->quat[0]));
810         PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->quat[1]));
811         PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->quat[2]));
812         PyList_SET_ITEM(list, 3, PyFloat_FromDouble(pchan->quat[3]));
813         PyTuple_SET_ITEM(ret, 2, list);
814
815         return ret;
816 /*
817         return Py_BuildValue("([fff][fff][ffff])",
818                 pchan->loc[0], pchan->loc[1], pchan->loc[2],
819                 pchan->size[0], pchan->size[1], pchan->size[2],
820                 pchan->quat[0], pchan->quat[1], pchan->quat[2], pchan->quat[3] );
821 */
822 }
823
824 /* getType */
825 const char BL_ActionActuator::GetType_doc[] =
826 "getType()\n"
827 "\tReturns the operation mode of the actuator.\n";
828 PyObject* BL_ActionActuator::PyGetType(PyObject* args, 
829                                        PyObject* kwds) {
830         ShowDeprecationWarning("getType()", "the type property");
831
832     return Py_BuildValue("h", m_playtype);
833 }
834
835 /* setType */
836 const char BL_ActionActuator::SetType_doc[] =
837 "setType(mode)\n"
838 "\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n"
839 "\tSet the operation mode of the actuator.\n";
840 PyObject* BL_ActionActuator::PySetType(PyObject* args,
841                                        PyObject* kwds) {
842         ShowDeprecationWarning("setType()", "the type property");
843
844         short typeArg;
845                                                                                                              
846     if (!PyArg_ParseTuple(args, "h:setType", &typeArg)) {
847         return NULL;
848     }
849
850         switch (typeArg) {
851         case ACT_ACTION_PLAY:
852         case ACT_ACTION_FLIPPER:
853         case ACT_ACTION_LOOP_STOP:
854         case ACT_ACTION_LOOP_END:
855         case ACT_ACTION_FROM_PROP:
856                 m_playtype = typeArg;
857                 break;
858         default:
859                 printf("Invalid type for action actuator: %d\n", typeArg); /* error */
860     }
861         Py_RETURN_NONE;
862 }
863
864 PyObject* BL_ActionActuator::PyGetContinue() {
865         ShowDeprecationWarning("getContinue()", "the continue property");
866
867     return PyInt_FromLong((long)(m_end_reset==0));
868 }
869
870 PyObject* BL_ActionActuator::PySetContinue(PyObject* value) {
871         ShowDeprecationWarning("setContinue()", "the continue property");
872
873         int param = PyObject_IsTrue( value );
874         
875         if( param == -1 ) {
876                 PyErr_SetString( PyExc_TypeError, "expected True/False or 0/1" );
877                 return NULL;
878         }
879
880         if (param) {
881                 m_end_reset = 0;
882         } else {
883                 m_end_reset = 1;
884         }
885     Py_RETURN_NONE;
886 }
887
888 //<-----Deprecated
889
890 /*     setChannel                                                         */
891 KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel,
892 "setChannel(channel, matrix)\n"
893 "\t - channel   : A string specifying the name of the bone channel.\n"
894 "\t - matrix    : A 4x4 matrix specifying the overriding transformation\n"
895 "\t               as an offset from the bone's rest position.\n")
896 {
897         BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
898         char *string;
899         PyObject *pymat= NULL;
900         PyObject *pyloc= NULL, *pysize= NULL, *pyquat= NULL;
901         bPoseChannel *pchan;
902         
903         if(PyTuple_Size(args)==2) {
904                 if (!PyArg_ParseTuple(args,"sO:setChannel", &string, &pymat)) // matrix
905                         return NULL;
906         }
907         else if(PyTuple_Size(args)==4) {
908                 if (!PyArg_ParseTuple(args,"sOOO:setChannel", &string, &pyloc, &pysize, &pyquat)) // loc/size/quat
909                         return NULL;
910         }
911         else {
912                 PyErr_SetString(PyExc_ValueError, "Expected a string and a 4x4 matrix (2 args) or a string and loc/size/quat sequences (4 args)");
913                 return NULL;
914         }
915         
916         if(pymat) {
917                 float matrix[4][4];
918                 MT_Matrix4x4 mat;
919                 
920                 if(!PyMatTo(pymat, mat))
921                         return NULL;
922                 
923                 mat.setValue((const float *)matrix);
924                 
925                 BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
926                 obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
927                 
928                 if (!m_userpose) {
929                         if(!m_pose)
930                                 obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
931                         game_copy_pose(&m_userpose, m_pose);
932                 }
933                 //pchan= verify_pose_channel(m_userpose, string); // adds the channel if its not there.
934                 pchan= get_pose_channel(m_userpose, string); // adds the channel if its not there.
935                 
936                 if (pchan) {
937                         VECCOPY (pchan->loc, matrix[3]);
938                         Mat4ToSize(matrix, pchan->size);
939                         Mat4ToQuat(matrix, pchan->quat);
940                 }
941         }
942         else {
943                 MT_Vector3 loc;
944                 MT_Vector3 size;
945                 MT_Vector4 quat;
946                 
947                 if (!PyVecTo(pyloc, loc) || !PyVecTo(pysize, size) || !PyVecTo(pyquat, quat))
948                         return NULL;
949                 
950                 // same as above
951                 if (!m_userpose) {
952                         if(!m_pose)
953                                 obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
954                         game_copy_pose(&m_userpose, m_pose);
955                 }
956                 //pchan= verify_pose_channel(m_userpose, string); // adds the channel if its not there.
957                 pchan= get_pose_channel(m_userpose, string);
958                 
959                 // for some reason loc.setValue(pchan->loc) fails
960                 if(pchan) {
961                         pchan->loc[0]= loc[0]; pchan->loc[1]= loc[1]; pchan->loc[2]= loc[2];
962                         pchan->size[0]= size[0]; pchan->size[1]= size[1]; pchan->size[2]= size[2];
963                         pchan->quat[0]= quat[0]; pchan->quat[1]= quat[1]; pchan->quat[2]= quat[2]; pchan->quat[3]= quat[3];
964                 }
965         }
966         
967         if(pchan==NULL) {
968                 PyErr_SetString(PyExc_ValueError, "Channel could not be found, use the 'channelNames' attribute to get a list of valid channels");
969                 return NULL;
970         }
971         
972         pchan->flag |= POSE_ROT|POSE_LOC|POSE_SIZE;
973         Py_RETURN_NONE;
974 }
975
976 /* ------------------------------------------------------------------------- */
977 /* Python Integration Hooks                                                                      */
978 /* ------------------------------------------------------------------------- */
979
980 PyTypeObject BL_ActionActuator::Type = {
981 #if (PY_VERSION_HEX >= 0x02060000)
982         PyVarObject_HEAD_INIT(NULL, 0)
983 #else
984         /* python 2.5 and below */
985         PyObject_HEAD_INIT( NULL )  /* required py macro */
986         0,                          /* ob_size */
987 #endif
988                 "BL_ActionActuator",
989                 sizeof(PyObjectPlus_Proxy),
990                 0,
991                 py_base_dealloc,
992                 0,
993                 0,
994                 0,
995                 0,
996                 py_base_repr,
997                 0,0,0,0,0,0,
998                 py_base_getattro,
999                 py_base_setattro,
1000                 0,0,0,0,0,0,0,0,0,
1001                 Methods
1002 };
1003
1004 PyParentObject BL_ActionActuator::Parents[] = {
1005         &BL_ActionActuator::Type,
1006                 &SCA_IActuator::Type,
1007                 &SCA_ILogicBrick::Type,
1008                 &CValue::Type,
1009                 NULL
1010 };
1011
1012 PyMethodDef BL_ActionActuator::Methods[] = {
1013         //Deprecated ----->
1014         {"setAction", (PyCFunction) BL_ActionActuator::sPySetAction, METH_VARARGS, (PY_METHODCHAR)SetAction_doc},
1015         {"setStart", (PyCFunction) BL_ActionActuator::sPySetStart, METH_VARARGS, (PY_METHODCHAR)SetStart_doc},
1016         {"setEnd", (PyCFunction) BL_ActionActuator::sPySetEnd, METH_VARARGS, (PY_METHODCHAR)SetEnd_doc},
1017         {"setBlendin", (PyCFunction) BL_ActionActuator::sPySetBlendin, METH_VARARGS, (PY_METHODCHAR)SetBlendin_doc},
1018         {"setPriority", (PyCFunction) BL_ActionActuator::sPySetPriority, METH_VARARGS, (PY_METHODCHAR)SetPriority_doc},
1019         {"setFrame", (PyCFunction) BL_ActionActuator::sPySetFrame, METH_VARARGS, (PY_METHODCHAR)SetFrame_doc},
1020         {"setProperty", (PyCFunction) BL_ActionActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
1021         {"setFrameProperty", (PyCFunction) BL_ActionActuator::sPySetFrameProperty, METH_VARARGS, (PY_METHODCHAR)SetFrameProperty_doc},
1022         {"setBlendtime", (PyCFunction) BL_ActionActuator::sPySetBlendtime, METH_VARARGS, (PY_METHODCHAR)SetBlendtime_doc},
1023
1024         {"getAction", (PyCFunction) BL_ActionActuator::sPyGetAction, METH_VARARGS, (PY_METHODCHAR)GetAction_doc},
1025         {"getStart", (PyCFunction) BL_ActionActuator::sPyGetStart, METH_VARARGS, (PY_METHODCHAR)GetStart_doc},
1026         {"getEnd", (PyCFunction) BL_ActionActuator::sPyGetEnd, METH_VARARGS, (PY_METHODCHAR)GetEnd_doc},
1027         {"getBlendin", (PyCFunction) BL_ActionActuator::sPyGetBlendin, METH_VARARGS, (PY_METHODCHAR)GetBlendin_doc},
1028         {"getPriority", (PyCFunction) BL_ActionActuator::sPyGetPriority, METH_VARARGS, (PY_METHODCHAR)GetPriority_doc},
1029         {"getFrame", (PyCFunction) BL_ActionActuator::sPyGetFrame, METH_VARARGS, (PY_METHODCHAR)GetFrame_doc},
1030         {"getProperty", (PyCFunction) BL_ActionActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc},
1031         {"getFrameProperty", (PyCFunction) BL_ActionActuator::sPyGetFrameProperty, METH_VARARGS, (PY_METHODCHAR)GetFrameProperty_doc},
1032         {"getChannel", (PyCFunction) BL_ActionActuator::sPyGetChannel, METH_O},
1033         {"getType", (PyCFunction) BL_ActionActuator::sPyGetType, METH_VARARGS, (PY_METHODCHAR)GetType_doc},
1034         {"setType", (PyCFunction) BL_ActionActuator::sPySetType, METH_VARARGS, (PY_METHODCHAR)SetType_doc},
1035         {"getContinue", (PyCFunction) BL_ActionActuator::sPyGetContinue, METH_NOARGS, 0},       
1036         {"setContinue", (PyCFunction) BL_ActionActuator::sPySetContinue, METH_O, 0},
1037         //<------
1038         KX_PYMETHODTABLE(BL_ActionActuator, setChannel),
1039         {NULL,NULL} //Sentinel
1040 };
1041
1042 PyAttributeDef BL_ActionActuator::Attributes[] = {
1043         KX_PYATTRIBUTE_FLOAT_RW("frameStart", 0, MAXFRAMEF, BL_ActionActuator, m_startframe),
1044         KX_PYATTRIBUTE_FLOAT_RW("frameEnd", 0, MAXFRAMEF, BL_ActionActuator, m_endframe),
1045         KX_PYATTRIBUTE_FLOAT_RW("blendIn", 0, MAXFRAMEF, BL_ActionActuator, m_blendin),
1046         KX_PYATTRIBUTE_RW_FUNCTION("action", BL_ActionActuator, pyattr_get_action, pyattr_set_action),
1047         KX_PYATTRIBUTE_RO_FUNCTION("channelNames", BL_ActionActuator, pyattr_get_channel_names),
1048         KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ActionActuator, m_priority),
1049         KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ActionActuator, m_localtime, CheckFrame),
1050         KX_PYATTRIBUTE_STRING_RW("propName", 0, 31, false, BL_ActionActuator, m_propname),
1051         KX_PYATTRIBUTE_STRING_RW("framePropName", 0, 31, false, BL_ActionActuator, m_framepropname),
1052         KX_PYATTRIBUTE_BOOL_RW("useContinue", BL_ActionActuator, m_end_reset),
1053         KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ActionActuator, m_blendframe, CheckBlendTime),
1054         KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",0,100,false,BL_ActionActuator,m_playtype,CheckType),
1055         { NULL }        //Sentinel
1056 };
1057
1058 PyObject* BL_ActionActuator::py_getattro(PyObject *attr) {
1059         py_getattro_up(SCA_IActuator);
1060 }
1061
1062 PyObject* BL_ActionActuator::py_getattro_dict() {
1063         py_getattro_dict_up(SCA_IActuator);
1064 }
1065
1066 int BL_ActionActuator::py_setattro(PyObject *attr, PyObject* value) {
1067         py_setattro_up(SCA_IActuator);
1068 }
1069
1070
1071 PyObject* BL_ActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1072 {
1073         BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
1074         return PyString_FromString(self->GetAction() ? self->GetAction()->id.name+2 : "");
1075 }
1076
1077 int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1078 {
1079         BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
1080         
1081         if (!PyString_Check(value))
1082         {
1083                 PyErr_SetString(PyExc_ValueError, "actuator.action = val: Action Actuator, expected the string name of the action");
1084                 return PY_SET_ATTR_FAIL;
1085         }
1086
1087         bAction *action= NULL;
1088         STR_String val = PyString_AsString(value);
1089         
1090         if (val != "")
1091         {
1092                 action= (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(val);
1093                 if (!action)
1094                 {
1095                         PyErr_SetString(PyExc_ValueError, "actuator.action = val: Action Actuator, action not found!");
1096                         return PY_SET_ATTR_FAIL;
1097                 }
1098         }
1099         
1100         self->SetAction(action);
1101         return PY_SET_ATTR_SUCCESS;
1102
1103 }
1104
1105 PyObject* BL_ActionActuator::pyattr_get_channel_names(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1106 {
1107         BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
1108         PyObject *ret= PyList_New(0);
1109         PyObject *item;
1110         
1111         bPose *pose= ((BL_ArmatureObject*)self->GetParent())->GetOrigPose();
1112         
1113         if(pose) {
1114                 bPoseChannel *pchan;
1115                 for(pchan= (bPoseChannel *)pose->chanbase.first; pchan; pchan= (bPoseChannel *)pchan->next) {
1116                         item= PyString_FromString(pchan->name);
1117                         PyList_Append(ret, item);
1118                         Py_DECREF(item);
1119                 }
1120         }
1121         
1122         return ret;
1123 }