Merging with trunk up to r38631.
[blender.git] / source / gameengine / Converter / KX_IpoConvert.cpp
1 /*
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file gameengine/Converter/KX_IpoConvert.cpp
30  *  \ingroup bgeconv
31  */
32
33
34 #if defined(WIN32) && !defined(FREE_WINDOWS)
35 // don't show stl-warnings
36 #pragma warning (disable:4786)
37 #endif
38
39 #include "BKE_material.h" /* give_current_material */
40
41 #include "KX_GameObject.h"
42 #include "KX_IpoConvert.h"
43 #include "KX_IInterpolator.h"
44 #include "KX_ScalarInterpolator.h"
45
46 #include "KX_BlenderScalarInterpolator.h"
47 #include "KX_BlenderSceneConverter.h"
48
49
50 /* This little block needed for linking to Blender... */
51 #ifdef WIN32
52 #include "BLI_winstuff.h"
53 #endif
54
55 #include "DNA_object_types.h"
56 #include "DNA_action_types.h"
57 #include "DNA_anim_types.h"
58 #include "DNA_ipo_types.h"
59 #include "DNA_lamp_types.h"
60 #include "DNA_world_types.h"
61 #include "DNA_camera_types.h"
62 #include "DNA_material_types.h"
63 /* end of blender include block */
64
65 #include "KX_IPO_SGController.h"
66 #include "KX_LightIpoSGController.h"
67 #include "KX_CameraIpoSGController.h"
68 #include "KX_WorldIpoController.h"
69 #include "KX_ObColorIpoSGController.h"
70 #include "KX_MaterialIpoController.h"
71
72 #include "SG_Node.h"
73
74 #include "STR_HashedString.h"
75
76 static BL_InterpolatorList *GetAdtList(struct AnimData *for_adt, KX_BlenderSceneConverter *converter) {
77         BL_InterpolatorList *adtList= converter->FindInterpolatorList(for_adt);
78
79         if (!adtList) {         
80                 adtList = new BL_InterpolatorList(for_adt->action);
81                 converter->RegisterInterpolatorList(adtList, for_adt);
82         }
83                         
84         return adtList; 
85 }
86
87 SG_Controller *BL_CreateIPO(struct bAction *action, KX_GameObject* gameobj, KX_BlenderSceneConverter *converter)
88 {
89         KX_IpoSGController* ipocontr = new KX_IpoSGController();
90         ipocontr->SetGameObject(gameobj);
91
92         Object* blenderobject = gameobj->GetBlenderObject();
93
94         ipocontr->GetIPOTransform().SetPosition(
95                 MT_Point3(
96                 blenderobject->loc[0]/*+blenderobject->dloc[0]*/,
97                 blenderobject->loc[1]/*+blenderobject->dloc[1]*/,
98                 blenderobject->loc[2]/*+blenderobject->dloc[2]*/
99                 )
100         );
101         ipocontr->GetIPOTransform().SetEulerAngles(
102                 MT_Vector3(
103                 blenderobject->rot[0],
104                 blenderobject->rot[1],
105                 blenderobject->rot[2]
106                 )
107         );
108         ipocontr->GetIPOTransform().SetScaling(
109                 MT_Vector3(
110                 blenderobject->size[0],
111                 blenderobject->size[1],
112                 blenderobject->size[2]
113                 )
114         );
115
116         const char *rotmode, *drotmode;
117
118         switch(blenderobject->rotmode)
119         {
120         case ROT_MODE_AXISANGLE:
121                 rotmode = "rotation_axis_angle";
122                 drotmode = "delta_rotation_axis_angle";
123         case ROT_MODE_QUAT:
124                 rotmode = "rotation_quaternion";
125                 drotmode = "delta_rotation_quaternion";
126         default:
127                 rotmode = "rotation_euler";
128                 drotmode = "delta_rotation_euler";
129         }
130
131         BL_InterpolatorList *adtList= GetAdtList(blenderobject->adt, converter);
132                 
133         // For each active channel in the adtList add an
134         // interpolator to the game object.
135                 
136         KX_IInterpolator *interpolator;
137         KX_IScalarInterpolator *interp;
138                 
139         for(int i=0; i<3; i++) {
140                 if ((interp = adtList->GetScalarInterpolator("location", i))) {
141                         interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetPosition()[i]), interp);
142                         ipocontr->AddInterpolator(interpolator);
143                         ipocontr->SetIPOChannelActive(OB_LOC_X+i, true);
144                 }
145         }
146         for(int i=0; i<3; i++) {
147                 if ((interp = adtList->GetScalarInterpolator("delta_location", i))) {
148                         interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaPosition()[i]), interp);
149                         ipocontr->AddInterpolator(interpolator);
150                         ipocontr->SetIPOChannelActive(OB_DLOC_X+i, true);
151                 }
152         }
153         for(int i=0; i<3; i++) {
154                 if ((interp = adtList->GetScalarInterpolator(rotmode, i))) {
155                         interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetEulerAngles()[i]), interp);
156                         ipocontr->AddInterpolator(interpolator);
157                         ipocontr->SetIPOChannelActive(OB_ROT_X+i, true);
158                 }
159         }
160         for(int i=0; i<3; i++) {
161                 if ((interp = adtList->GetScalarInterpolator(drotmode, i))) {
162                         interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[i]), interp);
163                         ipocontr->AddInterpolator(interpolator);
164                         ipocontr->SetIPOChannelActive(OB_DROT_X+i, true);
165                 }
166         }
167         for(int i=0; i<3; i++) {
168                 if ((interp = adtList->GetScalarInterpolator("scale", i))) {
169                         interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetScaling()[i]), interp);
170                         ipocontr->AddInterpolator(interpolator);
171                         ipocontr->SetIPOChannelActive(OB_SIZE_X+i, true);
172                 }
173         }
174         for(int i=0; i<3; i++) {
175                 if ((interp = adtList->GetScalarInterpolator("delta_scale", i))) {
176                         interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaScaling()[i]), interp);
177                         ipocontr->AddInterpolator(interpolator);
178                         ipocontr->SetIPOChannelActive(OB_DSIZE_X+i, true);
179                 }
180         }
181                 
182         {
183                 KX_ObColorIpoSGController* ipocontr_obcol=NULL;
184                         
185                 for(int i=0; i<4; i++) {
186                         if ((interp = adtList->GetScalarInterpolator("color", i))) {
187                                 if (!ipocontr_obcol) {
188                                         ipocontr_obcol = new KX_ObColorIpoSGController();
189                                         gameobj->GetSGNode()->AddSGController(ipocontr_obcol);
190                                         ipocontr_obcol->SetObject(gameobj->GetSGNode());
191                                 }
192                                 interpolator= new KX_ScalarInterpolator(&ipocontr_obcol->m_rgba[i], interp);
193                                 ipocontr_obcol->AddInterpolator(interpolator);
194                         }
195                 }
196         }
197
198         return ipocontr;
199 }
200
201 void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_BlenderSceneConverter *converter)
202 {
203         if (blenderobject->adt) {
204                 SG_Controller *ipocontr = BL_CreateIPO(blenderobject->adt->action, gameobj, converter);
205                 gameobj->GetSGNode()->AddSGController(ipocontr);
206                 ipocontr->SetObject(gameobj->GetSGNode());
207         }
208 }
209
210 void BL_ConvertLampIpos(struct Lamp* blenderlamp, KX_GameObject *lightobj,KX_BlenderSceneConverter *converter)
211 {
212
213         if (blenderlamp->adt) {
214
215                 KX_LightIpoSGController* ipocontr = new KX_LightIpoSGController();
216                 lightobj->GetSGNode()->AddSGController(ipocontr);
217                 ipocontr->SetObject(lightobj->GetSGNode());
218                 
219                 ipocontr->m_energy = blenderlamp->energy;
220                 ipocontr->m_col_rgb[0] = blenderlamp->r;
221                 ipocontr->m_col_rgb[1] = blenderlamp->g;
222                 ipocontr->m_col_rgb[2] = blenderlamp->b;
223                 ipocontr->m_dist = blenderlamp->dist;
224
225                 BL_InterpolatorList *adtList= GetAdtList(blenderlamp->adt, converter);
226
227                 // For each active channel in the adtList add an
228                 // interpolator to the game object.
229                 
230                 KX_IInterpolator *interpolator;
231                 KX_IScalarInterpolator *interp;
232                 
233                 if ((interp= adtList->GetScalarInterpolator("energy", 0))) {
234                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_energy, interp);
235                         ipocontr->AddInterpolator(interpolator);
236                         ipocontr->SetModifyEnergy(true);
237                 }
238
239                 if ((interp = adtList->GetScalarInterpolator("distance", 0))) {
240                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_dist, interp);
241                         ipocontr->AddInterpolator(interpolator);
242                         ipocontr->SetModifyDist(true);
243                 }
244                 
245                 for(int i=0; i<3; i++) {
246                         if ((interp = adtList->GetScalarInterpolator("color", i))) {
247                                 interpolator= new KX_ScalarInterpolator(&ipocontr->m_col_rgb[i], interp);
248                                 ipocontr->AddInterpolator(interpolator);
249                                 ipocontr->SetModifyColor(true);
250                         }
251                 }
252         }
253 }
254
255
256
257
258 void BL_ConvertCameraIpos(struct Camera* blendercamera, KX_GameObject *cameraobj,KX_BlenderSceneConverter *converter)
259 {
260
261         if (blendercamera->adt) {
262
263                 KX_CameraIpoSGController* ipocontr = new KX_CameraIpoSGController();
264                 cameraobj->GetSGNode()->AddSGController(ipocontr);
265                 ipocontr->SetObject(cameraobj->GetSGNode());
266                 
267                 ipocontr->m_lens = blendercamera->lens;
268                 ipocontr->m_clipstart = blendercamera->clipsta;
269                 ipocontr->m_clipend = blendercamera->clipend;
270
271                 BL_InterpolatorList *adtList= GetAdtList(blendercamera->adt, converter);
272
273                 // For each active channel in the adtList add an
274                 // interpolator to the game object.
275                 
276                 KX_IInterpolator *interpolator;
277                 KX_IScalarInterpolator *interp;
278                 
279                 if ((interp = adtList->GetScalarInterpolator("lens", 0))) {
280                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_lens, interp);
281                         ipocontr->AddInterpolator(interpolator);
282                         ipocontr->SetModifyLens(true);
283                 }
284
285                 if ((interp = adtList->GetScalarInterpolator("clip_start", 0))) {
286                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_clipstart, interp);
287                         ipocontr->AddInterpolator(interpolator);
288                         ipocontr->SetModifyClipStart(true);
289                 }
290
291                 if ((interp = adtList->GetScalarInterpolator("clip_end", 0))) {
292                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_clipend, interp);
293                         ipocontr->AddInterpolator(interpolator);
294                         ipocontr->SetModifyClipEnd(true);
295                 }
296
297         }
298 }
299
300
301 void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *converter)
302 {
303
304         if (blenderworld->adt) {
305
306                 KX_WorldIpoController* ipocontr = new KX_WorldIpoController();
307
308 // Erwin, hook up the world ipo controller here
309 // Gino: hook it up to what ?
310 // is there a userinterface element for that ?
311 // for now, we have some new python hooks to access the data, for a work-around
312                 
313                 ipocontr->m_mist_start  = blenderworld->miststa;
314                 ipocontr->m_mist_dist   = blenderworld->mistdist;
315                 ipocontr->m_mist_rgb[0] = blenderworld->horr;
316                 ipocontr->m_mist_rgb[1] = blenderworld->horg;
317                 ipocontr->m_mist_rgb[2] = blenderworld->horb;
318
319                 BL_InterpolatorList *adtList= GetAdtList(blenderworld->adt, converter);
320
321                 // For each active channel in the adtList add an
322                 // interpolator to the game object.
323                 
324                 KX_IInterpolator *interpolator;
325                 KX_IScalarInterpolator *interp;
326                 
327                 for(int i=0; i<3; i++) {
328                         if ((interp = adtList->GetScalarInterpolator("horizon_color", i))) {
329                                 interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_rgb[i], interp);
330                                 ipocontr->AddInterpolator(interpolator);
331                                 ipocontr->SetModifyMistColor(true);
332                         }
333                 }
334
335                 if ((interp = adtList->GetScalarInterpolator("mist.depth", 0))) {
336                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_dist, interp);
337                         ipocontr->AddInterpolator(interpolator);
338                         ipocontr->SetModifyMistDist(true);
339                 }
340
341                 if ((interp = adtList->GetScalarInterpolator("mist.start", 0))) {
342                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_start, interp);
343                         ipocontr->AddInterpolator(interpolator);
344                         ipocontr->SetModifyMistStart(true);
345                 }
346         }
347 }
348
349 static void ConvertMaterialIpos(
350         Material* blendermaterial,
351         dword matname_hash,
352         KX_GameObject* gameobj,  
353         KX_BlenderSceneConverter *converter
354         )
355 {
356         if (blendermaterial->adt) {
357                 KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController(matname_hash);
358                 gameobj->GetSGNode()->AddSGController(ipocontr);
359                 ipocontr->SetObject(gameobj->GetSGNode());
360                 
361                 BL_InterpolatorList *adtList= GetAdtList(blendermaterial->adt, converter);
362
363
364                 ipocontr->m_rgba[0]     = blendermaterial->r;
365                 ipocontr->m_rgba[1]     = blendermaterial->g;
366                 ipocontr->m_rgba[2]     = blendermaterial->b;
367                 ipocontr->m_rgba[3]     = blendermaterial->alpha;
368
369                 ipocontr->m_specrgb[0]  = blendermaterial->specr;
370                 ipocontr->m_specrgb[1]  = blendermaterial->specg;
371                 ipocontr->m_specrgb[2]  = blendermaterial->specb;
372                 
373                 ipocontr->m_hard                = blendermaterial->har;
374                 ipocontr->m_spec                = blendermaterial->spec;
375                 ipocontr->m_ref                 = blendermaterial->ref;
376                 ipocontr->m_emit                = blendermaterial->emit;
377                 ipocontr->m_alpha               = blendermaterial->alpha;
378                 
379                 KX_IInterpolator *interpolator;
380                 KX_IScalarInterpolator *sinterp;
381                 
382                 // --
383                 for(int i=0; i<3; i++) {
384                         if ((sinterp = adtList->GetScalarInterpolator("diffuse_color", i))) {
385                                 if (!ipocontr) {
386                                         ipocontr = new KX_MaterialIpoController(matname_hash);
387                                         gameobj->GetSGNode()->AddSGController(ipocontr);
388                                         ipocontr->SetObject(gameobj->GetSGNode());
389                                 }
390                                 interpolator= new KX_ScalarInterpolator(&ipocontr->m_rgba[i], sinterp);
391                                 ipocontr->AddInterpolator(interpolator);
392                         }
393                 }
394                 
395                 if ((sinterp = adtList->GetScalarInterpolator("alpha", 0))) {
396                         if (!ipocontr) {
397                                 ipocontr = new KX_MaterialIpoController(matname_hash);
398                                 gameobj->GetSGNode()->AddSGController(ipocontr);
399                                 ipocontr->SetObject(gameobj->GetSGNode());
400                         }
401                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_rgba[3], sinterp);
402                         ipocontr->AddInterpolator(interpolator);
403                 }
404
405                 for(int i=0; i<3; i++) {
406                         if ((sinterp = adtList->GetScalarInterpolator("specular_color", i))) {
407                                 if (!ipocontr) {
408                                         ipocontr = new KX_MaterialIpoController(matname_hash);
409                                         gameobj->GetSGNode()->AddSGController(ipocontr);
410                                         ipocontr->SetObject(gameobj->GetSGNode());
411                                 }
412                                 interpolator= new KX_ScalarInterpolator(&ipocontr->m_specrgb[i], sinterp);
413                                 ipocontr->AddInterpolator(interpolator);
414                         }
415                 }
416                 
417                 if ((sinterp = adtList->GetScalarInterpolator("specular_hardness", 0))) {
418                         if (!ipocontr) {
419                                 ipocontr = new KX_MaterialIpoController(matname_hash);
420                                 gameobj->GetSGNode()->AddSGController(ipocontr);
421                                 ipocontr->SetObject(gameobj->GetSGNode());
422                         }
423                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_hard, sinterp);
424                         ipocontr->AddInterpolator(interpolator);
425                 }
426
427                 if ((sinterp = adtList->GetScalarInterpolator("specularity", 0))) {
428                         if (!ipocontr) {
429                                 ipocontr = new KX_MaterialIpoController(matname_hash);
430                                 gameobj->GetSGNode()->AddSGController(ipocontr);
431                                 ipocontr->SetObject(gameobj->GetSGNode());
432                         }
433                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_spec, sinterp);
434                         ipocontr->AddInterpolator(interpolator);
435                 }
436                 
437                 if ((sinterp = adtList->GetScalarInterpolator("diffuse_reflection", 0))) {
438                         if (!ipocontr) {
439                                 ipocontr = new KX_MaterialIpoController(matname_hash);
440                                 gameobj->GetSGNode()->AddSGController(ipocontr);
441                                 ipocontr->SetObject(gameobj->GetSGNode());
442                         }
443                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_ref, sinterp);
444                         ipocontr->AddInterpolator(interpolator);
445                 }       
446                 
447                 if ((sinterp = adtList->GetScalarInterpolator("emit", 0))) {
448                         if (!ipocontr) {
449                                 ipocontr = new KX_MaterialIpoController(matname_hash);
450                                 gameobj->GetSGNode()->AddSGController(ipocontr);
451                                 ipocontr->SetObject(gameobj->GetSGNode());
452                         }
453                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_emit, sinterp);
454                         ipocontr->AddInterpolator(interpolator);
455                 }
456         }               
457 }
458
459 void BL_ConvertMaterialIpos(
460         struct Object* blenderobject,
461         KX_GameObject* gameobj,  
462         KX_BlenderSceneConverter *converter
463         )
464 {
465         if (blenderobject->totcol==1)
466         {
467                 Material *mat = give_current_material(blenderobject, 1);
468                 // if there is only one material attached to the mesh then set material_index in BL_ConvertMaterialIpos to NULL
469                 // --> this makes the UpdateMaterialData function in KX_GameObject.cpp use the old hack of using SetObjectColor
470                 // because this yields a better performance as not all the vertex colors need to be edited
471                 if(mat) ConvertMaterialIpos(mat, 0, gameobj, converter);
472         }
473         else
474         {
475                 for (int material_index=1; material_index <= blenderobject->totcol; material_index++)
476                 {
477                         Material *mat = give_current_material(blenderobject, material_index);
478                         STR_HashedString matname;
479                         if(mat) {
480                                 matname= mat->id.name; // who is using this name? can we remove the MA here?
481                                 ConvertMaterialIpos(mat, matname.hash(), gameobj, converter);
482                         }
483                 }
484         }
485 }
486