5a3629cfcd33b78de323dbf9f5e1d8cf62b87382
[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 "DNA_scene_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 #include "KX_PyMath.h"
55
56 #ifdef HAVE_CONFIG_H
57 #include <config.h>
58 #endif
59
60 extern "C" {
61 #include "BKE_animsys.h"
62 #include "BKE_action.h"
63 #include "RNA_access.h"
64 #include "RNA_define.h"
65 }
66
67 BL_ActionActuator::~BL_ActionActuator()
68 {
69         if (m_pose)
70                 game_free_pose(m_pose);
71         if (m_userpose)
72                 game_free_pose(m_userpose);
73         if (m_blendpose)
74                 game_free_pose(m_blendpose);
75 }
76
77 void BL_ActionActuator::ProcessReplica()
78 {
79         SCA_IActuator::ProcessReplica();
80         
81         m_pose = NULL;
82         m_blendpose = NULL;
83         m_localtime=m_startframe;
84         m_lastUpdate=-1;
85         
86 }
87
88 void BL_ActionActuator::SetBlendTime (float newtime){
89         m_blendframe = newtime;
90 }
91
92 CValue* BL_ActionActuator::GetReplica() {
93         BL_ActionActuator* replica = new BL_ActionActuator(*this);//m_float,GetName());
94         replica->ProcessReplica();
95         return replica;
96 }
97
98 bool BL_ActionActuator::ClampLocalTime()
99 {
100         if (m_startframe < m_endframe)
101         {
102                 if (m_localtime < m_startframe)
103                 {
104                         m_localtime = m_startframe;
105                         return true;
106                 } 
107                 else if (m_localtime > m_endframe)
108                 {
109                         m_localtime = m_endframe;
110                         return true;
111                 }
112         } else {
113                 if (m_localtime > m_startframe)
114                 {
115                         m_localtime = m_startframe;
116                         return true;
117                 }
118                 else if (m_localtime < m_endframe)
119                 {
120                         m_localtime = m_endframe;
121                         return true;
122                 }
123         }
124         return false;
125 }
126
127 void BL_ActionActuator::SetStartTime(float curtime)
128 {
129         float direction = m_startframe < m_endframe ? 1.0 : -1.0;
130         
131         if (!(m_flag & ACT_FLAG_REVERSE))
132                 m_starttime = curtime - direction*(m_localtime - m_startframe)/KX_KetsjiEngine::GetAnimFrameRate();
133         else
134                 m_starttime = curtime - direction*(m_endframe - m_localtime)/KX_KetsjiEngine::GetAnimFrameRate();
135 }
136
137 void BL_ActionActuator::SetLocalTime(float curtime)
138 {
139         float delta_time = (curtime - m_starttime)*KX_KetsjiEngine::GetAnimFrameRate();
140         
141         if (m_endframe < m_startframe)
142                 delta_time = -delta_time;
143
144         if (!(m_flag & ACT_FLAG_REVERSE))
145                 m_localtime = m_startframe + delta_time;
146         else
147                 m_localtime = m_endframe - delta_time;
148 }
149
150
151 bool BL_ActionActuator::Update(double curtime, bool frame)
152 {
153         bool bNegativeEvent = false;
154         bool bPositiveEvent = false;
155         bool keepgoing = true;
156         bool wrap = false;
157         bool apply=true;
158         int     priority;
159         float newweight;
160
161         curtime -= KX_KetsjiEngine::GetSuspendedDelta();
162         
163         // result = true if animation has to be continued, false if animation stops
164         // maybe there are events for us in the queue !
165         if (frame)
166         {
167                 bNegativeEvent = m_negevent;
168                 bPositiveEvent = m_posevent;
169                 RemoveAllEvents();
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 // 2.4x function, 
372                         /* Override the necessary channels with ones from the action */
373                         // XXX extract_pose_from_action(m_pose, m_action, m_localtime);
374                         
375                         
376 // 2.5x - replacement for extract_pose_from_action(...) above.
377                         {
378                                 struct PointerRNA id_ptr;
379                                 Object *arm= obj->GetArmatureObject();
380                                 bPose *pose_back= arm->pose;
381                                 
382                                 arm->pose= m_pose;
383                                 RNA_id_pointer_create((ID *)arm, &id_ptr);
384                                 animsys_evaluate_action(&id_ptr, m_action, NULL, m_localtime);
385                                 
386                                 arm->pose= pose_back;
387                         
388 // 2.5x - could also do this but looks too high level, constraints use this, it works ok.
389 //                              Object workob; /* evaluate using workob */
390 //                              what_does_obaction((Scene *)obj->GetScene(), obj->GetArmatureObject(), &workob, m_pose, m_action, NULL, m_localtime);
391                         }
392
393                         // done getting the pose from the action
394                         
395                         /* Perform the user override (if any) */
396                         if (m_userpose){
397                                 extract_pose_from_pose(m_pose, m_userpose);
398                                 game_free_pose(m_userpose); //cant use MEM_freeN(m_userpose) because the channels need freeing too.
399                                 m_userpose = NULL;
400                         }
401 #if 1
402                         /* Handle blending */
403                         if (m_blendin && (m_blendframe<m_blendin)){
404                                 /* If this is the start of a blending sequence... */
405                                 if ((m_blendframe==0.0) || (!m_blendpose)){
406                                         obj->GetMRDPose(&m_blendpose);
407                                         m_blendstart = curtime;
408                                 }
409                                 
410                                 /* Find percentages */
411                                 newweight = (m_blendframe/(float)m_blendin);
412                                 game_blend_poses(m_pose, m_blendpose, 1.0 - newweight);
413
414                                 /* Increment current blending percentage */
415                                 m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
416                                 if (m_blendframe>m_blendin)
417                                         m_blendframe = m_blendin;
418                                 
419                         }
420 #endif
421                         m_lastUpdate = m_localtime;
422                         obj->SetPose (m_pose);
423                 }
424                 else{
425                         m_blendframe = 0.0;
426                 }
427         }
428         
429         if (!keepgoing){
430                 m_blendframe = 0.0;
431         }
432         return keepgoing;
433 };
434
435 /* ------------------------------------------------------------------------- */
436 /* Python functions                                                          */
437 /* ------------------------------------------------------------------------- */
438
439 /*     setStart                                                              */
440 const char BL_ActionActuator::GetAction_doc[] = 
441 "getAction()\n"
442 "\tReturns a string containing the name of the current action.\n";
443
444 PyObject* BL_ActionActuator::PyGetAction(PyObject* args, 
445                                                                                  PyObject* kwds) {
446         ShowDeprecationWarning("getAction()", "the action property");
447
448         if (m_action){
449                 return PyUnicode_FromString(m_action->id.name+2);
450         }
451         Py_RETURN_NONE;
452 }
453
454 /*     getProperty                                                             */
455 const char BL_ActionActuator::GetProperty_doc[] = 
456 "getProperty()\n"
457 "\tReturns the name of the property to be used in FromProp mode.\n";
458
459 PyObject* BL_ActionActuator::PyGetProperty(PyObject* args, 
460                                                                                    PyObject* kwds) {
461         ShowDeprecationWarning("getProperty()", "the property property");
462
463         PyObject *result;
464         
465         result = Py_BuildValue("s", (const char *)m_propname);
466         
467         return result;
468 }
469
470 /*     getProperty                                                             */
471 const char BL_ActionActuator::GetFrameProperty_doc[] = 
472 "getFrameProperty()\n"
473 "\tReturns the name of the property, that is set to the current frame number.\n";
474
475 PyObject* BL_ActionActuator::PyGetFrameProperty(PyObject* args, 
476                                                                                    PyObject* kwds) {
477         ShowDeprecationWarning("getFrameProperty()", "the frameProperty property");
478
479         PyObject *result;
480         
481         result = Py_BuildValue("s", (const char *)m_framepropname);
482         
483         return result;
484 }
485
486 /*     getFrame                                                              */
487 const char BL_ActionActuator::GetFrame_doc[] = 
488 "getFrame()\n"
489 "\tReturns the current frame number.\n";
490
491 PyObject* BL_ActionActuator::PyGetFrame(PyObject* args, 
492                                                                                 PyObject* kwds) {
493         ShowDeprecationWarning("getFrame()", "the frame property");
494
495         PyObject *result;
496         
497         result = Py_BuildValue("f", m_localtime);
498         
499         return result;
500 }
501
502 /*     getEnd                                                                */
503 const char BL_ActionActuator::GetEnd_doc[] = 
504 "getEnd()\n"
505 "\tReturns the last frame of the action.\n";
506
507 PyObject* BL_ActionActuator::PyGetEnd(PyObject* args, 
508                                                                           PyObject* kwds) {
509         ShowDeprecationWarning("getEnd()", "the end property");
510
511         PyObject *result;
512         
513         result = Py_BuildValue("f", m_endframe);
514         
515         return result;
516 }
517
518 /*     getStart                                                              */
519 const char BL_ActionActuator::GetStart_doc[] = 
520 "getStart()\n"
521 "\tReturns the starting frame of the action.\n";
522
523 PyObject* BL_ActionActuator::PyGetStart(PyObject* args, 
524                                                                                 PyObject* kwds) {
525         ShowDeprecationWarning("getStart()", "the start property");
526
527         PyObject *result;
528         
529         result = Py_BuildValue("f", m_startframe);
530         
531         return result;
532 }
533
534 /*     getBlendin                                                            */
535 const char BL_ActionActuator::GetBlendin_doc[] = 
536 "getBlendin()\n"
537 "\tReturns the number of interpolation animation frames to be\n"
538 "\tgenerated when this actuator is triggered.\n";
539
540 PyObject* BL_ActionActuator::PyGetBlendin(PyObject* args, 
541                                                                                   PyObject* kwds) {
542         ShowDeprecationWarning("getBlendin()", "the blendin property");
543
544         PyObject *result;
545         
546         result = Py_BuildValue("f", m_blendin);
547         
548         return result;
549 }
550
551 /*     getPriority                                                           */
552 const char BL_ActionActuator::GetPriority_doc[] = 
553 "getPriority()\n"
554 "\tReturns the priority for this actuator.  Actuators with lower\n"
555 "\tPriority numbers will override actuators with higher numbers.\n";
556
557 PyObject* BL_ActionActuator::PyGetPriority(PyObject* args, 
558                                                                                    PyObject* kwds) {
559         ShowDeprecationWarning("getPriority()", "the priority property");
560
561         PyObject *result;
562         
563         result = Py_BuildValue("i", m_priority);
564         
565         return result;
566 }
567
568 /*     setAction                                                             */
569 const char BL_ActionActuator::SetAction_doc[] = 
570 "setAction(action, (reset))\n"
571 "\t - action    : The name of the action to set as the current action.\n"
572 "\t - reset     : Optional parameter indicating whether to reset the\n"
573 "\t               blend timer or not.  A value of 1 indicates that the\n"
574 "\t               timer should be reset.  A value of 0 will leave it\n"
575 "\t               unchanged.  If reset is not specified, the timer will"
576 "\t                   be reset.\n";
577
578 PyObject* BL_ActionActuator::PySetAction(PyObject* args, 
579                                                                                  PyObject* kwds) {
580         ShowDeprecationWarning("setAction()", "the action property");
581
582         char *string;
583         int     reset = 1;
584
585         if (PyArg_ParseTuple(args,"s|i:setAction",&string, &reset))
586         {
587                 bAction *action;
588                 
589                 action = (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(STR_String(string));
590                 
591                 if (!action){
592                         /* NOTE!  Throw an exception or something */
593                         //                      printf ("setAction failed: Action not found\n", string);
594                 }
595                 else{
596                         m_action=action;
597                         if (reset)
598                                 m_blendframe = 0;
599                 }
600         }
601         else {
602                 return NULL;
603         }
604         
605         Py_RETURN_NONE;
606 }
607
608 /*     setStart                                                              */
609 const char BL_ActionActuator::SetStart_doc[] = 
610 "setStart(start)\n"
611 "\t - start     : Specifies the starting frame of the animation.\n";
612
613 PyObject* BL_ActionActuator::PySetStart(PyObject* args, 
614                                                                                 PyObject* kwds) {
615         ShowDeprecationWarning("setStart()", "the start property");
616
617         float start;
618         
619         if (PyArg_ParseTuple(args,"f:setStart",&start))
620         {
621                 m_startframe = start;
622         }
623         else {
624                 return NULL;
625         }
626         
627         Py_RETURN_NONE;
628 }
629
630 /*     setEnd                                                                */
631 const char BL_ActionActuator::SetEnd_doc[] = 
632 "setEnd(end)\n"
633 "\t - end       : Specifies the ending frame of the animation.\n";
634
635 PyObject* BL_ActionActuator::PySetEnd(PyObject* args, 
636                                                                           PyObject* kwds) {
637         ShowDeprecationWarning("setEnd()", "the end property");
638
639         float end;
640         
641         if (PyArg_ParseTuple(args,"f:setEnd",&end))
642         {
643                 m_endframe = end;
644         }
645         else {
646                 return NULL;
647         }
648         
649         Py_RETURN_NONE;
650 }
651
652 /*     setBlendin                                                            */
653 const char BL_ActionActuator::SetBlendin_doc[] = 
654 "setBlendin(blendin)\n"
655 "\t - blendin   : Specifies the number of frames of animation to generate\n"
656 "\t               when making transitions between actions.\n";
657
658 PyObject* BL_ActionActuator::PySetBlendin(PyObject* args, 
659                                                                                   PyObject* kwds) {
660         ShowDeprecationWarning("setBlendin()", "the blendin property");
661
662         float blendin;
663         
664         if (PyArg_ParseTuple(args,"f:setBlendin",&blendin))
665         {
666                 m_blendin = blendin;
667         }
668         else {
669                 return NULL;
670         }
671         
672         Py_RETURN_NONE;
673 }
674
675 /*     setBlendtime                                                          */
676 const char BL_ActionActuator::SetBlendtime_doc[] = 
677 "setBlendtime(blendtime)\n"
678 "\t - blendtime : Allows the script to directly modify the internal timer\n"
679 "\t               used when generating transitions between actions.  This\n"
680 "\t               parameter must be in the range from 0.0 to 1.0.\n";
681
682 PyObject* BL_ActionActuator::PySetBlendtime(PyObject* args, 
683                                                                                   PyObject* kwds) {
684         ShowDeprecationWarning("setBlendtime()", "the blendtime property");
685
686         float blendframe;
687         
688         if (PyArg_ParseTuple(args,"f:setBlendtime",&blendframe))
689         {
690                 m_blendframe = blendframe * m_blendin;
691                 if (m_blendframe<0)
692                         m_blendframe = 0;
693                 if (m_blendframe>m_blendin)
694                         m_blendframe = m_blendin;
695         }
696         else {
697                 return NULL;
698         }
699         
700         Py_RETURN_NONE;
701 }
702
703 /*     setPriority                                                           */
704 const char BL_ActionActuator::SetPriority_doc[] = 
705 "setPriority(priority)\n"
706 "\t - priority  : Specifies the new priority.  Actuators will lower\n"
707 "\t               priority numbers will override actuators with higher\n"
708 "\t               numbers.\n";
709
710 PyObject* BL_ActionActuator::PySetPriority(PyObject* args, 
711                                                                                    PyObject* kwds) {
712         ShowDeprecationWarning("setPriority()", "the priority property");
713
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 /*     setFrame                                                              */
728 const char BL_ActionActuator::SetFrame_doc[] = 
729 "setFrame(frame)\n"
730 "\t - frame     : Specifies the new current frame for the animation\n";
731
732 PyObject* BL_ActionActuator::PySetFrame(PyObject* args, 
733                                                                                 PyObject* kwds) {
734         ShowDeprecationWarning("setFrame()", "the frame property");
735
736         float frame;
737         
738         if (PyArg_ParseTuple(args,"f:setFrame",&frame))
739         {
740                 m_localtime = frame;
741                 if (m_localtime<m_startframe)
742                         m_localtime=m_startframe;
743                 else if (m_localtime>m_endframe)
744                         m_localtime=m_endframe;
745         }
746         else {
747                 return NULL;
748         }
749         
750         Py_RETURN_NONE;
751 }
752
753 /*     setProperty                                                           */
754 const char BL_ActionActuator::SetProperty_doc[] = 
755 "setProperty(prop)\n"
756 "\t - prop      : A string specifying the property name to be used in\n"
757 "\t               FromProp playback mode.\n";
758
759 PyObject* BL_ActionActuator::PySetProperty(PyObject* args, 
760                                                                                    PyObject* kwds) {
761         ShowDeprecationWarning("setProperty()", "the property property");
762
763         char *string;
764         
765         if (PyArg_ParseTuple(args,"s:setProperty",&string))
766         {
767                 m_propname = string;
768         }
769         else {
770                 return NULL;
771         }
772         
773         Py_RETURN_NONE;
774 }
775
776 /*     setFrameProperty                                                          */
777 const char BL_ActionActuator::SetFrameProperty_doc[] = 
778 "setFrameProperty(prop)\n"
779 "\t - prop      : A string specifying the property of the frame set up update.\n";
780
781 PyObject* BL_ActionActuator::PySetFrameProperty(PyObject* args, 
782                                                                                    PyObject* kwds) {
783         ShowDeprecationWarning("setFrameProperty()", "the frameProperty property");
784
785         char *string;
786         
787         if (PyArg_ParseTuple(args,"s:setFrameProperty",&string))
788         {
789                 m_framepropname = string;
790         }
791         else {
792                 return NULL;
793         }
794         
795         Py_RETURN_NONE;
796 }
797
798 PyObject* BL_ActionActuator::PyGetChannel(PyObject* value) {
799         char *string= _PyUnicode_AsString(value);
800         
801         if (!string) {
802                 PyErr_SetString(PyExc_TypeError, "expected a single string");
803                 return NULL;
804         }
805         
806         bPoseChannel *pchan;
807         
808         if(m_userpose==NULL && m_pose==NULL) {
809                 BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
810                 obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
811         }
812         
813         // get_pose_channel accounts for NULL pose, run on both incase one exists but
814         // the channel doesnt
815         if(             !(pchan=get_pose_channel(m_userpose, string)) &&
816                         !(pchan=get_pose_channel(m_pose, string))  )
817         {
818                 PyErr_SetString(PyExc_ValueError, "channel doesnt exist");
819                 return NULL;
820         }
821
822         PyObject *ret = PyTuple_New(3);
823         
824         PyObject *list = PyList_New(3); 
825         PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->loc[0]));
826         PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->loc[1]));
827         PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->loc[2]));
828         PyTuple_SET_ITEM(ret, 0, list);
829         
830         list = PyList_New(3);
831         PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->size[0]));
832         PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->size[1]));
833         PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->size[2]));
834         PyTuple_SET_ITEM(ret, 1, list);
835         
836         list = PyList_New(4);
837         PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->quat[0]));
838         PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->quat[1]));
839         PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->quat[2]));
840         PyList_SET_ITEM(list, 3, PyFloat_FromDouble(pchan->quat[3]));
841         PyTuple_SET_ITEM(ret, 2, list);
842
843         return ret;
844 /*
845         return Py_BuildValue("([fff][fff][ffff])",
846                 pchan->loc[0], pchan->loc[1], pchan->loc[2],
847                 pchan->size[0], pchan->size[1], pchan->size[2],
848                 pchan->quat[0], pchan->quat[1], pchan->quat[2], pchan->quat[3] );
849 */
850 }
851
852 /* getType */
853 const char BL_ActionActuator::GetType_doc[] =
854 "getType()\n"
855 "\tReturns the operation mode of the actuator.\n";
856 PyObject* BL_ActionActuator::PyGetType(PyObject* args, 
857                                        PyObject* kwds) {
858         ShowDeprecationWarning("getType()", "the type property");
859
860     return Py_BuildValue("h", m_playtype);
861 }
862
863 /* setType */
864 const char BL_ActionActuator::SetType_doc[] =
865 "setType(mode)\n"
866 "\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n"
867 "\tSet the operation mode of the actuator.\n";
868 PyObject* BL_ActionActuator::PySetType(PyObject* args,
869                                        PyObject* kwds) {
870         ShowDeprecationWarning("setType()", "the type property");
871
872         short typeArg;
873                                                                                                              
874     if (!PyArg_ParseTuple(args, "h:setType", &typeArg)) {
875         return NULL;
876     }
877
878         switch (typeArg) {
879         case ACT_ACTION_PLAY:
880         case ACT_ACTION_FLIPPER:
881         case ACT_ACTION_LOOP_STOP:
882         case ACT_ACTION_LOOP_END:
883         case ACT_ACTION_FROM_PROP:
884                 m_playtype = typeArg;
885                 break;
886         default:
887                 printf("Invalid type for action actuator: %d\n", typeArg); /* error */
888     }
889         Py_RETURN_NONE;
890 }
891
892 PyObject* BL_ActionActuator::PyGetContinue() {
893         ShowDeprecationWarning("getContinue()", "the continue property");
894
895     return PyLong_FromSsize_t((long)(m_end_reset==0));
896 }
897
898 PyObject* BL_ActionActuator::PySetContinue(PyObject* value) {
899         ShowDeprecationWarning("setContinue()", "the continue property");
900
901         int param = PyObject_IsTrue( value );
902         
903         if( param == -1 ) {
904                 PyErr_SetString( PyExc_TypeError, "expected True/False or 0/1" );
905                 return NULL;
906         }
907
908         if (param) {
909                 m_end_reset = 0;
910         } else {
911                 m_end_reset = 1;
912         }
913     Py_RETURN_NONE;
914 }
915
916 //<-----Deprecated
917
918 /*     setChannel                                                         */
919 KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel,
920 "setChannel(channel, matrix)\n"
921 "\t - channel   : A string specifying the name of the bone channel.\n"
922 "\t - matrix    : A 4x4 matrix specifying the overriding transformation\n"
923 "\t               as an offset from the bone's rest position.\n")
924 {
925         BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
926         char *string;
927         PyObject *pymat= NULL;
928         PyObject *pyloc= NULL, *pysize= NULL, *pyquat= NULL;
929         bPoseChannel *pchan;
930         
931         if(PyTuple_Size(args)==2) {
932                 if (!PyArg_ParseTuple(args,"sO:setChannel", &string, &pymat)) // matrix
933                         return NULL;
934         }
935         else if(PyTuple_Size(args)==4) {
936                 if (!PyArg_ParseTuple(args,"sOOO:setChannel", &string, &pyloc, &pysize, &pyquat)) // loc/size/quat
937                         return NULL;
938         }
939         else {
940                 PyErr_SetString(PyExc_ValueError, "Expected a string and a 4x4 matrix (2 args) or a string and loc/size/quat sequences (4 args)");
941                 return NULL;
942         }
943         
944         if(pymat) {
945                 float matrix[4][4];
946                 MT_Matrix4x4 mat;
947                 
948                 if(!PyMatTo(pymat, mat))
949                         return NULL;
950                 
951                 mat.setValue((const float *)matrix);
952                 
953                 BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
954                 obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
955                 
956                 if (!m_userpose) {
957                         if(!m_pose)
958                                 obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
959                         game_copy_pose(&m_userpose, m_pose);
960                 }
961                 // pchan= verify_pose_channel(m_userpose, string); // adds the channel if its not there.
962                 pchan= get_pose_channel(m_userpose, string); // adds the channel if its not there.
963                 
964                 if(pchan) {
965                         VECCOPY (pchan->loc, matrix[3]);
966                         Mat4ToSize(matrix, pchan->size);
967                         Mat4ToQuat(matrix, pchan->quat);
968                 }
969         }
970         else {
971                 MT_Vector3 loc;
972                 MT_Vector3 size;
973                 MT_Quaternion quat;
974                 
975                 if (!PyVecTo(pyloc, loc) || !PyVecTo(pysize, size) || !PyQuatTo(pyquat, quat))
976                         return NULL;
977                 
978                 // same as above
979                 if (!m_userpose) {
980                         if(!m_pose)
981                                 obj->GetPose(&m_pose); /* Get the underlying pose from the armature */
982                         game_copy_pose(&m_userpose, m_pose);
983                 }
984                 // pchan= verify_pose_channel(m_userpose, string);
985                 pchan= get_pose_channel(m_userpose, string); // adds the channel if its not there.
986                 
987                 // for some reason loc.setValue(pchan->loc) fails
988                 if(pchan) {
989                         pchan->loc[0]= loc[0]; pchan->loc[1]= loc[1]; pchan->loc[2]= loc[2];
990                         pchan->size[0]= size[0]; pchan->size[1]= size[1]; pchan->size[2]= size[2];
991                         pchan->quat[0]= quat[3]; pchan->quat[1]= quat[0]; pchan->quat[2]= quat[1]; pchan->quat[3]= quat[2]; /* notice xyzw -> wxyz is intentional */
992                 }
993         }
994         
995         if(pchan==NULL) {
996                 PyErr_SetString(PyExc_ValueError, "Channel could not be found, use the 'channelNames' attribute to get a list of valid channels");
997                 return NULL;
998         }
999         
1000         pchan->flag |= POSE_ROT|POSE_LOC|POSE_SIZE;
1001         Py_RETURN_NONE;
1002 }
1003
1004 /* ------------------------------------------------------------------------- */
1005 /* Python Integration Hooks                                                                      */
1006 /* ------------------------------------------------------------------------- */
1007
1008 PyTypeObject BL_ActionActuator::Type = {
1009         PyVarObject_HEAD_INIT(NULL, 0)
1010         "BL_ActionActuator",
1011         sizeof(PyObjectPlus_Proxy),
1012         0,
1013         py_base_dealloc,
1014         0,
1015         0,
1016         0,
1017         0,
1018         py_base_repr,
1019         0,0,0,0,0,0,0,0,0,
1020         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1021         0,0,0,0,0,0,0,
1022         Methods,
1023         0,
1024         0,
1025         &SCA_IActuator::Type,
1026         0,0,0,0,0,0,
1027         py_base_new
1028 };
1029
1030 PyMethodDef BL_ActionActuator::Methods[] = {
1031         //Deprecated ----->
1032         {"setAction", (PyCFunction) BL_ActionActuator::sPySetAction, METH_VARARGS, (const char *)SetAction_doc},
1033         {"setStart", (PyCFunction) BL_ActionActuator::sPySetStart, METH_VARARGS, (const char *)SetStart_doc},
1034         {"setEnd", (PyCFunction) BL_ActionActuator::sPySetEnd, METH_VARARGS, (const char *)SetEnd_doc},
1035         {"setBlendin", (PyCFunction) BL_ActionActuator::sPySetBlendin, METH_VARARGS, (const char *)SetBlendin_doc},
1036         {"setPriority", (PyCFunction) BL_ActionActuator::sPySetPriority, METH_VARARGS, (const char *)SetPriority_doc},
1037         {"setFrame", (PyCFunction) BL_ActionActuator::sPySetFrame, METH_VARARGS, (const char *)SetFrame_doc},
1038         {"setProperty", (PyCFunction) BL_ActionActuator::sPySetProperty, METH_VARARGS, (const char *)SetProperty_doc},
1039         {"setFrameProperty", (PyCFunction) BL_ActionActuator::sPySetFrameProperty, METH_VARARGS, (const char *)SetFrameProperty_doc},
1040         {"setBlendtime", (PyCFunction) BL_ActionActuator::sPySetBlendtime, METH_VARARGS, (const char *)SetBlendtime_doc},
1041
1042         {"getAction", (PyCFunction) BL_ActionActuator::sPyGetAction, METH_VARARGS, (const char *)GetAction_doc},
1043         {"getStart", (PyCFunction) BL_ActionActuator::sPyGetStart, METH_VARARGS, (const char *)GetStart_doc},
1044         {"getEnd", (PyCFunction) BL_ActionActuator::sPyGetEnd, METH_VARARGS, (const char *)GetEnd_doc},
1045         {"getBlendin", (PyCFunction) BL_ActionActuator::sPyGetBlendin, METH_VARARGS, (const char *)GetBlendin_doc},
1046         {"getPriority", (PyCFunction) BL_ActionActuator::sPyGetPriority, METH_VARARGS, (const char *)GetPriority_doc},
1047         {"getFrame", (PyCFunction) BL_ActionActuator::sPyGetFrame, METH_VARARGS, (const char *)GetFrame_doc},
1048         {"getProperty", (PyCFunction) BL_ActionActuator::sPyGetProperty, METH_VARARGS, (const char *)GetProperty_doc},
1049         {"getFrameProperty", (PyCFunction) BL_ActionActuator::sPyGetFrameProperty, METH_VARARGS, (const char *)GetFrameProperty_doc},
1050         {"getChannel", (PyCFunction) BL_ActionActuator::sPyGetChannel, METH_O},
1051         {"getType", (PyCFunction) BL_ActionActuator::sPyGetType, METH_VARARGS, (const char *)GetType_doc},
1052         {"setType", (PyCFunction) BL_ActionActuator::sPySetType, METH_VARARGS, (const char *)SetType_doc},
1053         {"getContinue", (PyCFunction) BL_ActionActuator::sPyGetContinue, METH_NOARGS, 0},       
1054         {"setContinue", (PyCFunction) BL_ActionActuator::sPySetContinue, METH_O, 0},
1055         //<------
1056         KX_PYMETHODTABLE(BL_ActionActuator, setChannel),
1057         {NULL,NULL} //Sentinel
1058 };
1059
1060 PyAttributeDef BL_ActionActuator::Attributes[] = {
1061         KX_PYATTRIBUTE_FLOAT_RW("frameStart", 0, MAXFRAMEF, BL_ActionActuator, m_startframe),
1062         KX_PYATTRIBUTE_FLOAT_RW("frameEnd", 0, MAXFRAMEF, BL_ActionActuator, m_endframe),
1063         KX_PYATTRIBUTE_FLOAT_RW("blendIn", 0, MAXFRAMEF, BL_ActionActuator, m_blendin),
1064         KX_PYATTRIBUTE_RW_FUNCTION("action", BL_ActionActuator, pyattr_get_action, pyattr_set_action),
1065         KX_PYATTRIBUTE_RO_FUNCTION("channelNames", BL_ActionActuator, pyattr_get_channel_names),
1066         KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ActionActuator, m_priority),
1067         KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ActionActuator, m_localtime, CheckFrame),
1068         KX_PYATTRIBUTE_STRING_RW("propName", 0, 31, false, BL_ActionActuator, m_propname),
1069         KX_PYATTRIBUTE_STRING_RW("framePropName", 0, 31, false, BL_ActionActuator, m_framepropname),
1070         KX_PYATTRIBUTE_BOOL_RW("useContinue", BL_ActionActuator, m_end_reset),
1071         KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ActionActuator, m_blendframe, CheckBlendTime),
1072         KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",0,100,false,BL_ActionActuator,m_playtype,CheckType),
1073         { NULL }        //Sentinel
1074 };
1075
1076 PyObject* BL_ActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1077 {
1078         BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
1079         return PyUnicode_FromString(self->GetAction() ? self->GetAction()->id.name+2 : "");
1080 }
1081
1082 int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1083 {
1084         BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
1085         
1086         if (!PyUnicode_Check(value))
1087         {
1088                 PyErr_SetString(PyExc_ValueError, "actuator.action = val: Action Actuator, expected the string name of the action");
1089                 return PY_SET_ATTR_FAIL;
1090         }
1091
1092         bAction *action= NULL;
1093         STR_String val = _PyUnicode_AsString(value);
1094         
1095         if (val != "")
1096         {
1097                 action= (bAction*)SCA_ILogicBrick::m_sCurrentLogicManager->GetActionByName(val);
1098                 if (!action)
1099                 {
1100                         PyErr_SetString(PyExc_ValueError, "actuator.action = val: Action Actuator, action not found!");
1101                         return PY_SET_ATTR_FAIL;
1102                 }
1103         }
1104         
1105         self->SetAction(action);
1106         return PY_SET_ATTR_SUCCESS;
1107
1108 }
1109
1110 PyObject* BL_ActionActuator::pyattr_get_channel_names(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1111 {
1112         BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
1113         PyObject *ret= PyList_New(0);
1114         PyObject *item;
1115         
1116         bPose *pose= ((BL_ArmatureObject*)self->GetParent())->GetOrigPose();
1117         
1118         if(pose) {
1119                 bPoseChannel *pchan;
1120                 for(pchan= (bPoseChannel *)pose->chanbase.first; pchan; pchan= (bPoseChannel *)pchan->next) {
1121                         item= PyUnicode_FromString(pchan->name);
1122                         PyList_Append(ret, item);
1123                         Py_DECREF(item);
1124                 }
1125         }
1126         
1127         return ret;
1128 }