BGE Animations: Moving the BL_Action::IsDone() implementation from the header file...
[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  * 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 #include <cstdlib>
31
32 #include "BL_Action.h"
33 #include "BL_ArmatureObject.h"
34 #include "BL_DeformableGameObject.h"
35 #include "BL_ShapeDeformer.h"
36 #include "KX_IpoConvert.h"
37 #include "KX_GameObject.h"
38
39 // These three are for getting the action from the logic manager
40 #include "KX_Scene.h"
41 #include "KX_PythonInit.h"
42 #include "SCA_LogicManager.h"
43
44 extern "C" {
45 #include "BKE_animsys.h"
46 #include "BKE_action.h"
47 #include "RNA_access.h"
48 #include "RNA_define.h"
49 #include "DNA_nla_types.h"
50 }
51
52 BL_Action::BL_Action(class KX_GameObject* gameobj)
53 :
54         m_obj(gameobj),
55         m_startframe(0.f),
56         m_endframe(0.f),
57         m_blendin(0.f),
58         m_playmode(0),
59         m_endtime(0.f),
60         m_localtime(0.f),
61         m_blendframe(0.f),
62         m_blendstart(0.f),
63         m_speed(0.f),
64         m_priority(0),
65         m_ipo_flags(0),
66         m_pose(NULL),
67         m_blendpose(NULL),
68         m_sg_contr(NULL),
69         m_ptrrna(NULL),
70         m_done(true),
71         m_bcalc_local_time(true)
72 {
73         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
74         {
75                 BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
76
77                 m_ptrrna = new PointerRNA();
78                 RNA_id_pointer_create(&obj->GetArmatureObject()->id, m_ptrrna);
79         }
80         else
81         {
82                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
83                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
84
85                 if (shape_deformer)
86                 {
87                         m_ptrrna = new PointerRNA();
88                         RNA_id_pointer_create(&shape_deformer->GetKey()->id, m_ptrrna);
89                 }
90         }
91 }
92
93 BL_Action::~BL_Action()
94 {
95         if (m_pose)
96                 game_free_pose(m_pose);
97         if (m_blendpose)
98                 game_free_pose(m_blendpose);
99         if (m_sg_contr)
100         {
101                 m_obj->GetSGNode()->RemoveSGController(m_sg_contr);
102                 delete m_sg_contr;
103         }
104         if (m_ptrrna)
105                 delete m_ptrrna;
106 }
107
108 bool BL_Action::Play(const char* name,
109                                         float start,
110                                         float end,
111                                         short priority,
112                                         float blendin,
113                                         short play_mode,
114                                         short blend_mode,
115                                         short ipo_flags,
116                                         float playback_speed)
117 {
118
119         // Only start playing a new action if we're done, or if
120         // the new action has a higher priority
121         if (priority != 0 && !IsDone() && priority >= m_priority)
122                 return false;
123         m_priority = priority;
124         bAction* prev_action = m_action;
125
126         // First try to load the action
127         m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name);
128         if (!m_action)
129         {
130                 printf("Failed to load action: %s\n", name);
131                 m_done = true;
132                 return false;
133         }
134
135         if (prev_action != m_action)
136         {
137                 // Create an SG_Controller
138                 m_sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
139                 m_obj->GetSGNode()->AddSGController(m_sg_contr);
140                 m_sg_contr->SetObject(m_obj->GetSGNode());
141         }
142         
143         m_ipo_flags = ipo_flags;
144         InitIPO();
145
146         // Setup blendin shapes/poses
147         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
148         {
149                 if (!m_blendpose)
150                 {
151                         BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
152                         obj->GetMRDPose(&m_blendpose);
153                 }
154         }
155         else
156         {
157                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
158                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
159                 
160                 obj->GetShape(m_blendshape);
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_blendmode = blend_mode;
177         m_endtime = 0.f;
178         m_blendframe = 0.f;
179         m_blendstart = 0.f;
180         m_speed = playback_speed;
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 float BL_Action::GetFrame()
207 {
208         return m_localtime;
209 }
210
211 void BL_Action::SetFrame(float frame)
212 {
213         // Clamp the frame to the start and end frame
214         if (frame < min(m_startframe, m_endframe))
215                 frame = min(m_startframe, m_endframe);
216         else if (frame > max(m_startframe, m_endframe))
217                 frame = max(m_startframe, m_endframe);
218
219         m_localtime = frame;
220         m_bcalc_local_time = false;
221 }
222
223 void BL_Action::SetLocalTime(float curtime)
224 {
225         float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate()*m_speed;
226
227         if (m_endframe < m_startframe)
228                 dt = -dt;
229
230         m_localtime = m_startframe + dt;
231 }
232
233 void BL_Action::IncrementBlending(float curtime)
234 {
235         // Setup m_blendstart if we need to
236         if (m_blendstart == 0.f)
237                 m_blendstart = curtime;
238         
239         // Bump the blend frame
240         m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
241
242         // Clamp
243         if (m_blendframe>m_blendin)
244                 m_blendframe = m_blendin;
245 }
246
247
248 void BL_Action::BlendShape(Key* key, float srcweight)
249 {
250         vector<float>::const_iterator it;
251         float dstweight;
252         KeyBlock *kb;
253         
254         dstweight = 1.0F - srcweight;
255         //printf("Dst: %f\tSrc: %f\n", srcweight, dstweight);
256         for (it=m_blendshape.begin(), kb = (KeyBlock*)key->block.first; 
257                  kb && it != m_blendshape.end(); 
258                  kb = (KeyBlock*)kb->next, it++) {
259                 //printf("OirgKeys: %f\t%f\n", kb->curval, (*it));
260                 kb->curval = kb->curval * dstweight + (*it) * srcweight;
261                 //printf("NewKey: %f\n", kb->curval);
262         }
263         //printf("\n");
264 }
265
266 void BL_Action::Update(float curtime)
267 {
268         // Don't bother if we're done with the animation
269         if (m_done)
270                 return;
271
272         // We only want to calculate the current time if we weren't given a frame (e.g., from SetFrame())
273         if (m_bcalc_local_time)
274         {
275                 curtime -= KX_KetsjiEngine::GetSuspendedDelta();
276                 SetLocalTime(curtime);
277         }
278         else
279         {
280                 m_bcalc_local_time = true;
281         }
282
283         // Handle wrap around
284         if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe))
285         {
286                 switch(m_playmode)
287                 {
288                 case ACT_MODE_PLAY:
289                         // Clamp
290                         m_localtime = m_endframe;
291                         m_done = true;
292                         break;
293                 case ACT_MODE_LOOP:
294                         // Put the time back to the beginning
295                         m_localtime = m_startframe;
296                         m_starttime = curtime;
297                         break;
298                 case ACT_MODE_PING_PONG:
299                         // Swap the start and end frames
300                         float temp = m_startframe;
301                         m_startframe = m_endframe;
302                         m_endframe = temp;
303
304                         m_starttime = curtime;
305
306                         break;
307                 }
308
309                 if (!m_done && m_sg_contr)
310                         InitIPO();
311         }
312
313         if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
314         {
315                 BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
316                 obj->GetPose(&m_pose);
317
318                 // Extract the pose from the action
319                 {
320                         Object *arm = obj->GetArmatureObject();
321                         bPose *temp = arm->pose;
322
323                         arm->pose = m_pose;
324                         animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime);
325
326                         arm->pose = temp;
327                 }
328
329                 // Handle blending between armature actions
330                 if (m_blendin && m_blendframe<m_blendin)
331                 {
332                         IncrementBlending(curtime);
333
334                         // Calculate weight
335                         float weight = 1.f - (m_blendframe/m_blendin);
336
337                         // Blend the poses
338                         game_blend_poses(m_pose, m_blendpose, weight, ACTSTRIPMODE_BLEND);
339                 }
340
341
342                 // Handle layer blending
343                 if (m_blendmode != ACT_BLEND_NONE)
344                 {
345                         obj->GetMRDPose(&m_blendpose);
346                         game_blend_poses(m_pose, m_blendpose, 1.f, ACTSTRIPMODE_ADD);
347                 }
348
349                 obj->SetPose(m_pose);
350
351                 obj->SetActiveAction(NULL, 0, curtime);
352         }
353         else
354         {
355                 BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
356                 BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
357
358                 // Handle shape actions if we have any
359                 if (shape_deformer)
360                 {
361                         Key *key = shape_deformer->GetKey();
362
363
364                         animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime);
365
366                         // Handle blending between shape actions
367                         if (m_blendin && m_blendframe < m_blendin)
368                         {
369                                 IncrementBlending(curtime);
370
371                                 float weight = 1.f - (m_blendframe/m_blendin);
372
373                                 // We go through and clear out the keyblocks so there isn't any interference
374                                 // from other shape actions
375                                 KeyBlock *kb;
376                                 for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next)
377                                         kb->curval = 0.f;
378
379                                 // Now blend the shape
380                                 BlendShape(key, weight);
381                         }
382
383                         obj->SetActiveAction(NULL, 0, m_localtime);
384                 }
385
386
387                 InitIPO();
388                 m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD);
389         }
390 }