Merge with trunk up to r38584.
[blender.git] / source / gameengine / Ketsji / BL_Action.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * Contributor(s): Mitchell Stokes.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file BL_Action.cpp
26  *  \ingroup ketsji
27  */
28
29 #include <cstdlib>
30
31 #include "BL_Action.h"
32 #include "BL_ArmatureObject.h"
33 #include "BL_DeformableGameObject.h"
34 #include "BL_ShapeDeformer.h"
35 #include "KX_IpoConvert.h"
36 #include "KX_GameObject.h"
37
38 // These three are for getting the action from the logic manager
39 #include "KX_Scene.h"
40 #include "KX_PythonInit.h"
41 #include "SCA_LogicManager.h"
42
43 extern "C" {
44 #include "BKE_animsys.h"
45 #include "BKE_action.h"
46 #include "RNA_access.h"
47 #include "RNA_define.h"
48 }
49
50 BL_Action::BL_Action(class KX_GameObject* gameobj)
51 :
52         m_obj(gameobj),
53         m_startframe(0.f),
54         m_endframe(0.f),
55         m_blendin(0.f),
56         m_playmode(0),
57         m_endtime(0.f),
58         m_localtime(0.f),
59         m_blendframe(0.f),
60         m_blendstart(0.f),
61         m_speed(0.f),
62         m_priority(0),
63         m_ipo_flags(0),
64         m_pose(NULL),
65         m_blendpose(NULL),
66         m_blendinpose(NULL),
67         m_sg_contr(NULL),
68         m_ptrrna(NULL),
69         m_action(NULL),
70         m_done(true)
71 {
72         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
73         {
74                 BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
75
76                 m_ptrrna = new PointerRNA();
77                 RNA_id_pointer_create(&obj->GetArmatureObject()->id, m_ptrrna);
78         }
79         else
80         {
81                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
82                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
83
84                 if (shape_deformer)
85                 {
86                         m_ptrrna = new PointerRNA();
87                         RNA_id_pointer_create(&shape_deformer->GetKey()->id, m_ptrrna);
88                 }
89         }
90 }
91
92 BL_Action::~BL_Action()
93 {
94         if (m_pose)
95                 game_free_pose(m_pose);
96         if (m_blendpose)
97                 game_free_pose(m_blendpose);
98         if (m_blendinpose)
99                 game_free_pose(m_blendinpose);
100         if (m_sg_contr)
101         {
102                 m_obj->GetSGNode()->RemoveSGController(m_sg_contr);
103                 delete m_sg_contr;
104         }
105         if (m_ptrrna)
106                 delete m_ptrrna;
107 }
108
109 bool BL_Action::Play(const char* name,
110                                         float start,
111                                         float end,
112                                         short priority,
113                                         float blendin,
114                                         short play_mode,
115                                         float layer_weight,
116                                         short ipo_flags,
117                                         float playback_speed)
118 {
119
120         // Only start playing a new action if we're done, or if
121         // the new action has a higher priority
122         if (priority != 0 && !IsDone() && priority >= m_priority)
123                 return false;
124         m_priority = priority;
125         bAction* prev_action = m_action;
126
127         // First try to load the action
128         m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name);
129         if (!m_action)
130         {
131                 printf("Failed to load action: %s\n", name);
132                 m_done = true;
133                 return false;
134         }
135
136         if (prev_action != m_action)
137         {
138                 // Create an SG_Controller
139                 m_sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
140                 m_obj->GetSGNode()->AddSGController(m_sg_contr);
141                 m_sg_contr->SetObject(m_obj->GetSGNode());
142         }
143         
144         m_ipo_flags = ipo_flags;
145         InitIPO();
146
147         // Setup blendin shapes/poses
148         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
149         {
150                 BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
151                 obj->GetMRDPose(&m_blendinpose);
152         }
153         else
154         {
155                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
156                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
157                 
158                 if (shape_deformer && shape_deformer->GetKey())
159                 {
160                         obj->GetShape(m_blendinshape);
161
162                         // Now that we have the previous blend shape saved, we can clear out the key to avoid any
163                         // further interference.
164                         KeyBlock *kb;
165                         for (kb=(KeyBlock*)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock*)kb->next)
166                                 kb->curval = 0.f;
167                 }
168         }
169
170         // Now that we have an action, we have something we can play
171         m_starttime = KX_GetActiveEngine()->GetFrameTime();
172         m_startframe = m_localtime = start;
173         m_endframe = end;
174         m_blendin = blendin;
175         m_playmode = play_mode;
176         m_endtime = 0.f;
177         m_blendframe = 0.f;
178         m_blendstart = 0.f;
179         m_speed = playback_speed;
180         m_layer_weight = layer_weight;
181         
182         m_done = false;
183
184         return true;
185 }
186
187 void BL_Action::Stop()
188 {
189         m_done = true;
190 }
191
192 bool BL_Action::IsDone()
193 {
194         return m_done;
195 }
196
197 void BL_Action::InitIPO()
198 {
199                 // Initialize the IPO
200                 m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
201                 m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, m_ipo_flags & ACT_IPOFLAG_FORCE);
202                 m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, m_ipo_flags & ACT_IPOFLAG_ADD);
203                 m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, m_ipo_flags & ACT_IPOFLAG_LOCAL);
204 }
205
206 bAction *BL_Action::GetAction()
207 {
208         return (IsDone()) ? NULL : m_action;
209 }
210
211 float BL_Action::GetFrame()
212 {
213         return m_localtime;
214 }
215
216 void BL_Action::SetFrame(float frame)
217 {
218         float dt;
219
220         // Clamp the frame to the start and end frame
221         if (frame < min(m_startframe, m_endframe))
222                 frame = min(m_startframe, m_endframe);
223         else if (frame > max(m_startframe, m_endframe))
224                 frame = max(m_startframe, m_endframe);
225         
226         // We don't set m_localtime directly since it's recalculated
227         // in the next update. So, we modify the value (m_starttime) 
228         // used to calculate m_localtime the next time SetLocalTime() is called.
229
230         dt = frame-m_startframe;
231
232         if (m_endframe < m_startframe)
233                 dt = -dt;
234
235         m_starttime -= dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed);
236 }
237
238 void BL_Action::SetLocalTime(float curtime)
239 {
240         float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate()*m_speed;
241
242         if (m_endframe < m_startframe)
243                 dt = -dt;
244
245         m_localtime = m_startframe + dt;
246 }
247
248 void BL_Action::IncrementBlending(float curtime)
249 {
250         // Setup m_blendstart if we need to
251         if (m_blendstart == 0.f)
252                 m_blendstart = curtime;
253         
254         // Bump the blend frame
255         m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
256
257         // Clamp
258         if (m_blendframe>m_blendin)
259                 m_blendframe = m_blendin;
260 }
261
262
263 void BL_Action::BlendShape(Key* key, float srcweight, std::vector<float>& blendshape)
264 {
265         vector<float>::const_iterator it;
266         float dstweight;
267         KeyBlock *kb;
268         
269         dstweight = 1.0F - srcweight;
270         //printf("Dst: %f\tSrc: %f\n", srcweight, dstweight);
271         for (it=blendshape.begin(), kb = (KeyBlock*)key->block.first; 
272                  kb && it != blendshape.end(); 
273                  kb = (KeyBlock*)kb->next, it++) {
274                 //printf("OirgKeys: %f\t%f\n", kb->curval, (*it));
275                 kb->curval = kb->curval * dstweight + (*it) * srcweight;
276                 //printf("NewKey: %f\n", kb->curval);
277         }
278         //printf("\n");
279 }
280
281 void BL_Action::Update(float curtime)
282 {
283         // Don't bother if we're done with the animation
284         if (m_done)
285                 return;
286
287         curtime -= KX_KetsjiEngine::GetSuspendedDelta();
288         SetLocalTime(curtime);
289
290         // Handle wrap around
291         if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe))
292         {
293                 switch(m_playmode)
294                 {
295                 case ACT_MODE_PLAY:
296                         // Clamp
297                         m_localtime = m_endframe;
298                         m_done = true;
299                         break;
300                 case ACT_MODE_LOOP:
301                         // Put the time back to the beginning
302                         m_localtime = m_startframe;
303                         m_starttime = curtime;
304                         break;
305                 case ACT_MODE_PING_PONG:
306                         // Swap the start and end frames
307                         float temp = m_startframe;
308                         m_startframe = m_endframe;
309                         m_endframe = temp;
310
311                         m_starttime = curtime;
312
313                         break;
314                 }
315
316                 if (!m_done && m_sg_contr)
317                         InitIPO();
318         }
319
320         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
321         {
322                 BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
323                 obj->GetPose(&m_pose);
324
325                 // Extract the pose from the action
326                 {
327                         Object *arm = obj->GetArmatureObject();
328                         bPose *temp = arm->pose;
329
330                         arm->pose = m_pose;
331                         animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime);
332
333                         arm->pose = temp;
334                 }
335
336                 // Handle blending between armature actions
337                 if (m_blendin && m_blendframe<m_blendin)
338                 {
339                         IncrementBlending(curtime);
340
341                         // Calculate weight
342                         float weight = 1.f - (m_blendframe/m_blendin);
343
344                         // Blend the poses
345                         game_blend_poses(m_pose, m_blendinpose, weight);
346                 }
347
348
349                 // Handle layer blending
350                 if (m_layer_weight >= 0)
351                 {
352                         obj->GetMRDPose(&m_blendpose);
353                         game_blend_poses(m_pose, m_blendpose, m_layer_weight);
354                 }
355
356                 obj->SetPose(m_pose);
357
358                 obj->SetActiveAction(NULL, 0, curtime);
359         }
360         else
361         {
362                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
363                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
364
365                 // Handle shape actions if we have any
366                 if (shape_deformer && shape_deformer->GetKey())
367                 {
368                         Key *key = shape_deformer->GetKey();
369
370
371                         animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime);
372
373                         // Handle blending between shape actions
374                         if (m_blendin && m_blendframe < m_blendin)
375                         {
376                                 IncrementBlending(curtime);
377
378                                 float weight = 1.f - (m_blendframe/m_blendin);
379
380                                 // We go through and clear out the keyblocks so there isn't any interference
381                                 // from other shape actions
382                                 KeyBlock *kb;
383                                 for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next)
384                                         kb->curval = 0.f;
385
386                                 // Now blend the shape
387                                 BlendShape(key, weight, m_blendinshape);
388                         }
389
390                         // Handle layer blending
391                         if (m_layer_weight >= 0)
392                         {
393                                 obj->GetShape(m_blendshape);
394                                 BlendShape(key, m_layer_weight, m_blendshape);
395                         }
396
397                         obj->SetActiveAction(NULL, 0, curtime);
398                 }
399
400
401                 InitIPO();
402                 m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD);
403         }
404 }