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