Get rid of c++ in blenkernel and modifiers
[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 bAction *for_act, KX_BlenderSceneConverter *converter) {
77         BL_InterpolatorList *adtList= converter->FindInterpolatorList(for_act);
78
79         if (!adtList) {         
80                 adtList = new BL_InterpolatorList(for_act);
81                 converter->RegisterInterpolatorList(adtList, for_act);
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(MT_Point3(blenderobject->loc));
95         ipocontr->GetIPOTransform().SetEulerAngles(MT_Vector3(blenderobject->rot));
96         ipocontr->GetIPOTransform().SetScaling(MT_Vector3(blenderobject->size));
97
98         const char *rotmode, *drotmode;
99
100         switch(blenderobject->rotmode) {
101         case ROT_MODE_AXISANGLE:
102                 rotmode = "rotation_axis_angle";
103                 drotmode = "delta_rotation_axis_angle";
104                 break;
105         case ROT_MODE_QUAT:
106                 rotmode = "rotation_quaternion";
107                 drotmode = "delta_rotation_quaternion";
108                 break;
109         default:
110                 rotmode = "rotation_euler";
111                 drotmode = "delta_rotation_euler";
112                 break;
113         }
114
115         BL_InterpolatorList *adtList= GetAdtList(action, converter);
116                 
117         // For each active channel in the adtList add an
118         // interpolator to the game object.
119                 
120         KX_IInterpolator *interpolator;
121         KX_IScalarInterpolator *interp;
122                 
123         for(int i=0; i<3; i++) {
124                 if ((interp = adtList->GetScalarInterpolator("location", i))) {
125                         interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetPosition()[i]), interp);
126                         ipocontr->AddInterpolator(interpolator);
127                         ipocontr->SetIPOChannelActive(OB_LOC_X+i, true);
128                 }
129         }
130         for(int i=0; i<3; i++) {
131                 if ((interp = adtList->GetScalarInterpolator("delta_location", i))) {
132                         interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaPosition()[i]), interp);
133                         ipocontr->AddInterpolator(interpolator);
134                         ipocontr->SetIPOChannelActive(OB_DLOC_X+i, true);
135                 }
136         }
137         for(int i=0; i<3; i++) {
138                 if ((interp = adtList->GetScalarInterpolator(rotmode, i))) {
139                         interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetEulerAngles()[i]), interp);
140                         ipocontr->AddInterpolator(interpolator);
141                         ipocontr->SetIPOChannelActive(OB_ROT_X+i, true);
142                 }
143         }
144         for(int i=0; i<3; i++) {
145                 if ((interp = adtList->GetScalarInterpolator(drotmode, i))) {
146                         interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[i]), interp);
147                         ipocontr->AddInterpolator(interpolator);
148                         ipocontr->SetIPOChannelActive(OB_DROT_X+i, true);
149                 }
150         }
151         for(int i=0; i<3; i++) {
152                 if ((interp = adtList->GetScalarInterpolator("scale", i))) {
153                         interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetScaling()[i]), interp);
154                         ipocontr->AddInterpolator(interpolator);
155                         ipocontr->SetIPOChannelActive(OB_SIZE_X+i, true);
156                 }
157         }
158         for(int i=0; i<3; i++) {
159                 if ((interp = adtList->GetScalarInterpolator("delta_scale", i))) {
160                         interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaScaling()[i]), interp);
161                         ipocontr->AddInterpolator(interpolator);
162                         ipocontr->SetIPOChannelActive(OB_DSIZE_X+i, true);
163                 }
164         }
165                 
166         {
167                 KX_ObColorIpoSGController* ipocontr_obcol=NULL;
168                         
169                 for(int i=0; i<4; i++) {
170                         if ((interp = adtList->GetScalarInterpolator("color", i))) {
171                                 if (!ipocontr_obcol) {
172                                         ipocontr_obcol = new KX_ObColorIpoSGController();
173                                         gameobj->GetSGNode()->AddSGController(ipocontr_obcol);
174                                         ipocontr_obcol->SetObject(gameobj->GetSGNode());
175                                 }
176                                 interpolator= new KX_ScalarInterpolator(&ipocontr_obcol->m_rgba[i], interp);
177                                 ipocontr_obcol->AddInterpolator(interpolator);
178                         }
179                 }
180         }
181
182         return ipocontr;
183 }
184
185 void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_BlenderSceneConverter *converter)
186 {
187         if (blenderobject->adt) {
188                 SG_Controller *ipocontr = BL_CreateIPO(blenderobject->adt->action, gameobj, converter);
189                 gameobj->GetSGNode()->AddSGController(ipocontr);
190                 ipocontr->SetObject(gameobj->GetSGNode());
191         }
192 }
193
194 SG_Controller *BL_CreateLampIPO(struct bAction *action, KX_GameObject*  lightobj, KX_BlenderSceneConverter *converter)
195 {
196         KX_LightIpoSGController* ipocontr = new KX_LightIpoSGController();
197
198         Lamp *blenderlamp = (Lamp*)lightobj->GetBlenderObject()->data;
199
200         ipocontr->m_energy = blenderlamp->energy;
201         ipocontr->m_col_rgb[0] = blenderlamp->r;
202         ipocontr->m_col_rgb[1] = blenderlamp->g;
203         ipocontr->m_col_rgb[2] = blenderlamp->b;
204         ipocontr->m_dist = blenderlamp->dist;
205
206         BL_InterpolatorList *adtList= GetAdtList(action, converter);
207
208         // For each active channel in the adtList add an
209         // interpolator to the game object.
210                 
211         KX_IInterpolator *interpolator;
212         KX_IScalarInterpolator *interp;
213                 
214         if ((interp= adtList->GetScalarInterpolator("energy", 0))) {
215                 interpolator= new KX_ScalarInterpolator(&ipocontr->m_energy, interp);
216                 ipocontr->AddInterpolator(interpolator);
217                 ipocontr->SetModifyEnergy(true);
218         }
219
220         if ((interp = adtList->GetScalarInterpolator("distance", 0))) {
221                 interpolator= new KX_ScalarInterpolator(&ipocontr->m_dist, interp);
222                 ipocontr->AddInterpolator(interpolator);
223                 ipocontr->SetModifyDist(true);
224         }
225                 
226         for(int i=0; i<3; i++) {
227                 if ((interp = adtList->GetScalarInterpolator("color", i))) {
228                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_col_rgb[i], interp);
229                         ipocontr->AddInterpolator(interpolator);
230                         ipocontr->SetModifyColor(true);
231                 }
232         }
233
234         return ipocontr;
235 }
236
237 void BL_ConvertLampIpos(struct Lamp* blenderlamp, KX_GameObject *lightobj,KX_BlenderSceneConverter *converter)
238 {
239
240         if (blenderlamp->adt) {
241
242                 SG_Controller* ipocontr = BL_CreateLampIPO(blenderlamp->adt->action, lightobj, converter);
243                 lightobj->GetSGNode()->AddSGController(ipocontr);
244                 ipocontr->SetObject(lightobj->GetSGNode());
245                 
246                 
247         }
248 }
249
250 SG_Controller *BL_CreateCameraIPO(struct bAction *action, KX_GameObject*  cameraobj, KX_BlenderSceneConverter *converter)
251 {
252         KX_CameraIpoSGController* ipocontr = new KX_CameraIpoSGController();
253
254         Camera *blendercamera = (Camera*)cameraobj->GetBlenderObject()->data;
255
256         ipocontr->m_lens = blendercamera->lens;
257         ipocontr->m_clipstart = blendercamera->clipsta;
258         ipocontr->m_clipend = blendercamera->clipend;
259
260         BL_InterpolatorList *adtList= GetAdtList(action, converter);
261
262         // For each active channel in the adtList add an
263         // interpolator to the game object.
264                 
265         KX_IInterpolator *interpolator;
266         KX_IScalarInterpolator *interp;
267                 
268         if ((interp = adtList->GetScalarInterpolator("lens", 0))) {
269                 interpolator= new KX_ScalarInterpolator(&ipocontr->m_lens, interp);
270                 ipocontr->AddInterpolator(interpolator);
271                 ipocontr->SetModifyLens(true);
272         }
273
274         if ((interp = adtList->GetScalarInterpolator("clip_start", 0))) {
275                 interpolator= new KX_ScalarInterpolator(&ipocontr->m_clipstart, interp);
276                 ipocontr->AddInterpolator(interpolator);
277                 ipocontr->SetModifyClipStart(true);
278         }
279
280         if ((interp = adtList->GetScalarInterpolator("clip_end", 0))) {
281                 interpolator= new KX_ScalarInterpolator(&ipocontr->m_clipend, interp);
282                 ipocontr->AddInterpolator(interpolator);
283                 ipocontr->SetModifyClipEnd(true);
284         }
285
286         return ipocontr;
287 }
288
289 void BL_ConvertCameraIpos(struct Camera* blendercamera, KX_GameObject *cameraobj,KX_BlenderSceneConverter *converter)
290 {
291
292         if (blendercamera->adt) {
293                 SG_Controller* ipocontr = BL_CreateCameraIPO(blendercamera->adt->action, cameraobj, converter);
294                 cameraobj->GetSGNode()->AddSGController(ipocontr);
295                 ipocontr->SetObject(cameraobj->GetSGNode());
296         }
297 }
298
299
300 void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *converter)
301 {
302
303         if (blenderworld->adt) {
304
305                 KX_WorldIpoController* ipocontr = new KX_WorldIpoController();
306
307 // Erwin, hook up the world ipo controller here
308 // Gino: hook it up to what ?
309 // is there a userinterface element for that ?
310 // for now, we have some new python hooks to access the data, for a work-around
311                 
312                 ipocontr->m_mist_start  = blenderworld->miststa;
313                 ipocontr->m_mist_dist   = blenderworld->mistdist;
314                 ipocontr->m_mist_rgb[0] = blenderworld->horr;
315                 ipocontr->m_mist_rgb[1] = blenderworld->horg;
316                 ipocontr->m_mist_rgb[2] = blenderworld->horb;
317
318                 BL_InterpolatorList *adtList= GetAdtList(blenderworld->adt->action, converter);
319
320                 // For each active channel in the adtList add an
321                 // interpolator to the game object.
322                 
323                 KX_IInterpolator *interpolator;
324                 KX_IScalarInterpolator *interp;
325                 
326                 for(int i=0; i<3; i++) {
327                         if ((interp = adtList->GetScalarInterpolator("horizon_color", i))) {
328                                 interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_rgb[i], interp);
329                                 ipocontr->AddInterpolator(interpolator);
330                                 ipocontr->SetModifyMistColor(true);
331                         }
332                 }
333
334                 if ((interp = adtList->GetScalarInterpolator("mist.depth", 0))) {
335                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_dist, interp);
336                         ipocontr->AddInterpolator(interpolator);
337                         ipocontr->SetModifyMistDist(true);
338                 }
339
340                 if ((interp = adtList->GetScalarInterpolator("mist.start", 0))) {
341                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_start, interp);
342                         ipocontr->AddInterpolator(interpolator);
343                         ipocontr->SetModifyMistStart(true);
344                 }
345         }
346 }
347
348 static void ConvertMaterialIpos(
349         Material* blendermaterial,
350         dword matname_hash,
351         KX_GameObject* gameobj,  
352         KX_BlenderSceneConverter *converter
353         )
354 {
355         if (blendermaterial->adt) {
356                 KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController(matname_hash);
357                 gameobj->GetSGNode()->AddSGController(ipocontr);
358                 ipocontr->SetObject(gameobj->GetSGNode());
359                 
360                 BL_InterpolatorList *adtList= GetAdtList(blendermaterial->adt->action, converter);
361
362
363                 ipocontr->m_rgba[0]     = blendermaterial->r;
364                 ipocontr->m_rgba[1]     = blendermaterial->g;
365                 ipocontr->m_rgba[2]     = blendermaterial->b;
366                 ipocontr->m_rgba[3]     = blendermaterial->alpha;
367
368                 ipocontr->m_specrgb[0]  = blendermaterial->specr;
369                 ipocontr->m_specrgb[1]  = blendermaterial->specg;
370                 ipocontr->m_specrgb[2]  = blendermaterial->specb;
371                 
372                 ipocontr->m_hard                = blendermaterial->har;
373                 ipocontr->m_spec                = blendermaterial->spec;
374                 ipocontr->m_ref                 = blendermaterial->ref;
375                 ipocontr->m_emit                = blendermaterial->emit;
376                 ipocontr->m_alpha               = blendermaterial->alpha;
377                 
378                 KX_IInterpolator *interpolator;
379                 KX_IScalarInterpolator *sinterp;
380                 
381                 // --
382                 for(int i=0; i<3; i++) {
383                         if ((sinterp = adtList->GetScalarInterpolator("diffuse_color", i))) {
384                                 if (!ipocontr) {
385                                         ipocontr = new KX_MaterialIpoController(matname_hash);
386                                         gameobj->GetSGNode()->AddSGController(ipocontr);
387                                         ipocontr->SetObject(gameobj->GetSGNode());
388                                 }
389                                 interpolator= new KX_ScalarInterpolator(&ipocontr->m_rgba[i], sinterp);
390                                 ipocontr->AddInterpolator(interpolator);
391                         }
392                 }
393                 
394                 if ((sinterp = adtList->GetScalarInterpolator("alpha", 0))) {
395                         if (!ipocontr) {
396                                 ipocontr = new KX_MaterialIpoController(matname_hash);
397                                 gameobj->GetSGNode()->AddSGController(ipocontr);
398                                 ipocontr->SetObject(gameobj->GetSGNode());
399                         }
400                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_rgba[3], sinterp);
401                         ipocontr->AddInterpolator(interpolator);
402                 }
403
404                 for(int i=0; i<3; i++) {
405                         if ((sinterp = adtList->GetScalarInterpolator("specular_color", i))) {
406                                 if (!ipocontr) {
407                                         ipocontr = new KX_MaterialIpoController(matname_hash);
408                                         gameobj->GetSGNode()->AddSGController(ipocontr);
409                                         ipocontr->SetObject(gameobj->GetSGNode());
410                                 }
411                                 interpolator= new KX_ScalarInterpolator(&ipocontr->m_specrgb[i], sinterp);
412                                 ipocontr->AddInterpolator(interpolator);
413                         }
414                 }
415                 
416                 if ((sinterp = adtList->GetScalarInterpolator("specular_hardness", 0))) {
417                         if (!ipocontr) {
418                                 ipocontr = new KX_MaterialIpoController(matname_hash);
419                                 gameobj->GetSGNode()->AddSGController(ipocontr);
420                                 ipocontr->SetObject(gameobj->GetSGNode());
421                         }
422                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_hard, sinterp);
423                         ipocontr->AddInterpolator(interpolator);
424                 }
425
426                 if ((sinterp = adtList->GetScalarInterpolator("specularity", 0))) {
427                         if (!ipocontr) {
428                                 ipocontr = new KX_MaterialIpoController(matname_hash);
429                                 gameobj->GetSGNode()->AddSGController(ipocontr);
430                                 ipocontr->SetObject(gameobj->GetSGNode());
431                         }
432                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_spec, sinterp);
433                         ipocontr->AddInterpolator(interpolator);
434                 }
435                 
436                 if ((sinterp = adtList->GetScalarInterpolator("diffuse_reflection", 0))) {
437                         if (!ipocontr) {
438                                 ipocontr = new KX_MaterialIpoController(matname_hash);
439                                 gameobj->GetSGNode()->AddSGController(ipocontr);
440                                 ipocontr->SetObject(gameobj->GetSGNode());
441                         }
442                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_ref, sinterp);
443                         ipocontr->AddInterpolator(interpolator);
444                 }       
445                 
446                 if ((sinterp = adtList->GetScalarInterpolator("emit", 0))) {
447                         if (!ipocontr) {
448                                 ipocontr = new KX_MaterialIpoController(matname_hash);
449                                 gameobj->GetSGNode()->AddSGController(ipocontr);
450                                 ipocontr->SetObject(gameobj->GetSGNode());
451                         }
452                         interpolator= new KX_ScalarInterpolator(&ipocontr->m_emit, sinterp);
453                         ipocontr->AddInterpolator(interpolator);
454                 }
455         }               
456 }
457
458 void BL_ConvertMaterialIpos(
459         struct Object* blenderobject,
460         KX_GameObject* gameobj,  
461         KX_BlenderSceneConverter *converter
462         )
463 {
464         if (blenderobject->totcol==1)
465         {
466                 Material *mat = give_current_material(blenderobject, 1);
467                 // if there is only one material attached to the mesh then set material_index in BL_ConvertMaterialIpos to NULL
468                 // --> this makes the UpdateMaterialData function in KX_GameObject.cpp use the old hack of using SetObjectColor
469                 // because this yields a better performance as not all the vertex colors need to be edited
470                 if(mat) ConvertMaterialIpos(mat, 0, gameobj, converter);
471         }
472         else
473         {
474                 for (int material_index=1; material_index <= blenderobject->totcol; material_index++)
475                 {
476                         Material *mat = give_current_material(blenderobject, material_index);
477                         STR_HashedString matname;
478                         if(mat) {
479                                 matname= mat->id.name; // who is using this name? can we remove the MA here?
480                                 ConvertMaterialIpos(mat, matname.hash(), gameobj, converter);
481                         }
482                 }
483         }
484 }
485