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