rename and negate DISABLE_PYTHON --> WITH_PYTHON
[blender.git] / source / gameengine / Converter / KX_BlenderSceneConverter.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 #pragma warning (disable:4786) // suppress stl-MSVC debug info warning
31 #endif
32
33 #include "KX_Scene.h"
34 #include "KX_GameObject.h"
35 #include "KX_BlenderSceneConverter.h"
36 #include "KX_IpoConvert.h"
37 #include "RAS_MeshObject.h"
38 #include "KX_PhysicsEngineEnums.h"
39 #include "PHY_IPhysicsEnvironment.h"
40 #include "KX_KetsjiEngine.h"
41 #include "KX_IPhysicsController.h"
42 #include "BL_Material.h"
43 #include "BL_ActionActuator.h"
44 #include "KX_BlenderMaterial.h"
45 #include "KX_PolygonMaterial.h"
46
47
48 #include "SYS_System.h"
49
50 #include "DummyPhysicsEnvironment.h"
51
52 #include "KX_ConvertPhysicsObject.h"
53
54 #ifdef USE_BULLET
55 #include "CcdPhysicsEnvironment.h"
56 #endif
57
58 #include "KX_BlenderSceneConverter.h"
59 #include "KX_BlenderScalarInterpolator.h"
60 #include "BL_BlenderDataConversion.h"
61 #include "BlenderWorldInfo.h"
62 #include "KX_Scene.h"
63
64 /* This little block needed for linking to Blender... */
65 #ifdef WIN32
66 #include "BLI_winstuff.h"
67 #endif
68
69 /* This list includes only data type definitions */
70 #include "DNA_scene_types.h"
71 #include "DNA_world_types.h"
72 #include "BKE_main.h"
73
74 #include "BLI_math.h"
75
76 extern "C"
77 {
78 #include "DNA_object_types.h"
79 #include "DNA_curve_types.h"
80 #include "DNA_mesh_types.h"
81 #include "DNA_material_types.h"
82 #include "BLI_blenlib.h"
83 #include "MEM_guardedalloc.h"
84 #include "BKE_global.h"
85 #include "BKE_animsys.h"
86 #include "BKE_library.h"
87 #include "BKE_material.h" // copy_material
88 #include "BKE_mesh.h" // copy_mesh
89 #include "DNA_space_types.h"
90 #include "DNA_anim_types.h"
91 #include "RNA_define.h"
92 #include "../../blender/editors/include/ED_keyframing.h"
93 }
94
95 /* Only for dynamic loading and merging */
96 #include "RAS_BucketManager.h" // XXX cant stay
97 #include "KX_BlenderSceneConverter.h"
98 #include "BL_BlenderDataConversion.h"
99 #include "KX_MeshProxy.h"
100 #include "RAS_MeshObject.h"
101 extern "C" {
102         #include "BKE_context.h"
103         #include "BLO_readfile.h"
104         #include "BKE_idcode.h"
105         #include "BKE_report.h"
106         #include "DNA_space_types.h"
107         #include "DNA_windowmanager_types.h" /* report api */
108         #include "../../blender/blenlib/BLI_linklist.h"
109 }
110
111 KX_BlenderSceneConverter::KX_BlenderSceneConverter(
112                                                         struct Main* maggie,
113                                                         class KX_KetsjiEngine* engine
114                                                         )
115                                                         : m_maggie(maggie),
116                                                         /*m_maggie_dyn(NULL),*/
117                                                         m_ketsjiEngine(engine),
118                                                         m_alwaysUseExpandFraming(false),
119                                                         m_usemat(false),
120                                                         m_useglslmat(false)
121 {
122         tag_main(maggie, 0); /* avoid re-tagging later on */
123         m_newfilename = "";
124 }
125
126
127 KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
128 {
129         // clears meshes, and hashmaps from blender to gameengine data
130         int i;
131         // delete sumoshapes
132         
133
134         int numAdtLists = m_map_blender_to_gameAdtList.size();
135         for (i=0; i<numAdtLists; i++) {
136                 BL_InterpolatorList *adtList= *m_map_blender_to_gameAdtList.at(i);
137
138                 delete (adtList);
139         }
140
141         vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itw = m_worldinfos.begin();
142         while (itw != m_worldinfos.end()) {
143                 delete (*itw).second;
144                 itw++;
145         }
146
147         vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
148         while (itp != m_polymaterials.end()) {
149                 delete (*itp).second;
150                 itp++;
151         }
152
153         // delete after RAS_IPolyMaterial
154         vector<pair<KX_Scene*,BL_Material *> >::iterator itmat = m_materials.begin();
155         while (itmat != m_materials.end()) {
156                 delete (*itmat).second;
157                 itmat++;
158         }       
159
160
161         vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itm = m_meshobjects.begin();
162         while (itm != m_meshobjects.end()) {
163                 delete (*itm).second;
164                 itm++;
165         }
166
167 #ifdef USE_BULLET
168         KX_ClearBulletSharedShapes();
169 #endif
170
171         /* free any data that was dynamically loaded */
172         for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
173                 Main *main= *it;
174                 free_main(main);
175         }
176
177         m_DynamicMaggie.clear();
178 }
179
180 void KX_BlenderSceneConverter::SetNewFileName(const STR_String& filename)
181 {
182         m_newfilename = filename;
183 }
184
185
186
187 bool KX_BlenderSceneConverter::TryAndLoadNewFile()
188 {
189         bool result = false;
190
191         // find the file
192 /*      if ()
193         {
194                 result = true;
195         }
196         // if not, clear the newfilename
197         else
198         {
199                 m_newfilename = "";     
200         }
201 */
202         return result;
203 }
204
205 Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name)
206 {
207         Scene *sce;
208
209         /**
210          * Find the specified scene by name, or the first
211          * scene if nothing matches (shouldn't happen).
212          */
213         if((sce= (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
214                 return sce;
215
216         for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
217                 Main *main= *it;
218
219                 if((sce= (Scene *)BLI_findstring(&main->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
220                         return sce;
221         }
222
223         return (Scene*)m_maggie->scene.first;
224
225 }
226 #include "KX_PythonInit.h"
227
228 #ifdef USE_BULLET
229
230 #include "LinearMath/btIDebugDraw.h"
231
232
233 struct  BlenderDebugDraw : public btIDebugDraw
234 {
235         BlenderDebugDraw () :
236                 m_debugMode(0) 
237         {
238         }
239         
240         int m_debugMode;
241
242         virtual void    drawLine(const btVector3& from,const btVector3& to,const btVector3& color)
243         {
244                 if (m_debugMode >0)
245                 {
246                         MT_Vector3 kxfrom(from[0],from[1],from[2]);
247                         MT_Vector3 kxto(to[0],to[1],to[2]);
248                         MT_Vector3 kxcolor(color[0],color[1],color[2]);
249
250                         KX_RasterizerDrawDebugLine(kxfrom,kxto,kxcolor);
251                 }
252         }
253         
254         virtual void    reportErrorWarning(const char* warningString)
255         {
256
257         }
258
259         virtual void    drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,float distance,int lifeTime,const btVector3& color)
260         {
261                 //not yet
262         }
263
264         virtual void    setDebugMode(int debugMode)
265         {
266                 m_debugMode = debugMode;
267         }
268         virtual int             getDebugMode() const
269         {
270                 return m_debugMode;
271         }
272         ///todo: find out if Blender can do this
273         virtual void    draw3dText(const btVector3& location,const char* textString)
274         {
275
276         }
277                 
278 };
279
280 #endif
281
282 void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
283                                                                                         class RAS_IRenderTools* rendertools,
284                                                                                         class RAS_ICanvas* canvas)
285 {
286         //find out which physics engine
287         Scene *blenderscene = destinationscene->GetBlenderScene();
288
289         e_PhysicsEngine physics_engine = UseBullet;
290         bool useDbvtCulling = false;
291         // hook for registration function during conversion.
292         m_currentScene = destinationscene;
293         destinationscene->SetSceneConverter(this);
294         SG_SetActiveStage(SG_STAGE_CONVERTER);
295
296         if (blenderscene)
297         {
298         
299                 switch (blenderscene->gm.physicsEngine)
300                 {
301                 case WOPHY_BULLET:
302                         {
303                                 physics_engine = UseBullet;
304                                 useDbvtCulling = (blenderscene->gm.mode & WO_DBVT_CULLING) != 0;
305                                 break;
306                         }
307                                                         
308                         case WOPHY_ODE:
309                         {
310                                 physics_engine = UseODE;
311                                 break;
312                         }
313                         case WOPHY_DYNAMO:
314                         {
315                                 physics_engine = UseDynamo;
316                                 break;
317                         }
318                         case WOPHY_SUMO:
319                         {
320                                 physics_engine = UseSumo; 
321                                 break;
322                         }
323                         case WOPHY_NONE:
324                         {
325                                 physics_engine = UseNone;
326                         }
327                 }
328         }
329
330         switch (physics_engine)
331         {
332 #ifdef USE_BULLET
333                 case UseBullet:
334                         {
335                                 CcdPhysicsEnvironment* ccdPhysEnv = new CcdPhysicsEnvironment(useDbvtCulling);
336                                 ccdPhysEnv->setDebugDrawer(new BlenderDebugDraw());
337                                 ccdPhysEnv->setDeactivationLinearTreshold(0.8f); // default, can be overridden by Python
338                                 ccdPhysEnv->setDeactivationAngularTreshold(1.0f); // default, can be overridden by Python
339
340                                 SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/
341                                 int visualizePhysics = SYS_GetCommandLineInt(syshandle,"show_physics",0);
342                                 if (visualizePhysics)
343                                         ccdPhysEnv->setDebugMode(btIDebugDraw::DBG_DrawWireframe|btIDebugDraw::DBG_DrawAabb|btIDebugDraw::DBG_DrawContactPoints|btIDebugDraw::DBG_DrawText|btIDebugDraw::DBG_DrawConstraintLimits|btIDebugDraw::DBG_DrawConstraints);
344                 
345                                 //todo: get a button in blender ?
346                                 //disable / enable debug drawing (contact points, aabb's etc)   
347                                 //ccdPhysEnv->setDebugMode(1);
348                                 destinationscene->SetPhysicsEnvironment(ccdPhysEnv);
349                                 break;
350                         }
351 #endif  
352                 case UseDynamo:
353                 {
354                 }
355                 
356                 default:
357                 case UseNone:
358                         physics_engine = UseNone;
359                         destinationscene ->SetPhysicsEnvironment(new DummyPhysicsEnvironment());
360                         break;
361         }
362
363         BL_ConvertBlenderObjects(m_maggie,
364                 destinationscene,
365                 m_ketsjiEngine,
366                 physics_engine,
367                 rendertools,
368                 canvas,
369                 this,
370                 m_alwaysUseExpandFraming
371                 );
372
373         //These lookup are not needed during game
374         m_map_blender_to_gameactuator.clear();
375         m_map_blender_to_gamecontroller.clear();
376         m_map_blender_to_gameobject.clear();
377
378         //Clearing this lookup table has the effect of disabling the cache of meshes
379         //between scenes, even if they are shared in the blend file.
380         //This cache mecanism is buggy so I leave it disable and the memory leak
381         //that would result from this is fixed in RemoveScene()
382         m_map_mesh_to_gamemesh.clear();
383 }
384
385 // This function removes all entities stored in the converter for that scene
386 // It should be used instead of direct delete scene
387 // Note that there was some provision for sharing entities (meshes...) between
388 // scenes but that is now disabled so all scene will have their own copy
389 // and we can delete them here. If the sharing is reactivated, change this code too..
390 // (see KX_BlenderSceneConverter::ConvertScene)
391 void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
392 {
393         int i, size;
394         // delete the scene first as it will stop the use of entities
395         delete scene;
396         // delete the entities of this scene
397         vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
398         size = m_worldinfos.size();
399         for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
400                 if ((*worldit).first == scene) {
401                         delete (*worldit).second;
402                         *worldit = m_worldinfos.back();
403                         m_worldinfos.pop_back();
404                         size--;
405                 } else {
406                         i++;
407                         worldit++;
408                 }
409         }
410
411         vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit;
412         size = m_polymaterials.size();
413         for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
414                 if ((*polymit).first == scene) {
415                         delete (*polymit).second;
416                         *polymit = m_polymaterials.back();
417                         m_polymaterials.pop_back();
418                         size--;
419                 } else {
420                         i++;
421                         polymit++;
422                 }
423         }
424
425         vector<pair<KX_Scene*,BL_Material*> >::iterator matit;
426         size = m_materials.size();
427         for (i=0, matit=m_materials.begin(); i<size; ) {
428                 if ((*matit).first == scene) {
429                         delete (*matit).second;
430                         *matit = m_materials.back();
431                         m_materials.pop_back();
432                         size--;
433                 } else {
434                         i++;
435                         matit++;
436                 }
437         }
438
439         vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
440         size = m_meshobjects.size();
441         for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
442                 if ((*meshit).first == scene) {
443                         delete (*meshit).second;
444                         *meshit = m_meshobjects.back();
445                         m_meshobjects.pop_back();
446                         size--;
447                 } else {
448                         i++;
449                         meshit++;
450                 }
451         }
452 }
453
454 // use blender materials
455 void KX_BlenderSceneConverter::SetMaterials(bool val)
456 {
457         m_usemat = val;
458         m_useglslmat = false;
459 }
460
461 void KX_BlenderSceneConverter::SetGLSLMaterials(bool val)
462 {
463         m_usemat = val;
464         m_useglslmat = val;
465 }
466
467 bool KX_BlenderSceneConverter::GetMaterials()
468 {
469         return m_usemat;
470 }
471
472 bool KX_BlenderSceneConverter::GetGLSLMaterials()
473 {
474         return m_useglslmat;
475 }
476
477 void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat)
478 {
479         m_materials.push_back(pair<KX_Scene*,BL_Material *>(m_currentScene,mat));
480 }
481
482
483
484 void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(
485         bool to_what)
486 {
487         m_alwaysUseExpandFraming= to_what;
488 }
489
490         
491
492 void KX_BlenderSceneConverter::RegisterGameObject(
493                                                                         KX_GameObject *gameobject, 
494                                                                         struct Object *for_blenderobject) 
495 {
496         /* only maintained while converting, freed during game runtime */
497         m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject),gameobject);
498 }
499
500 /* only need to run this during conversion since
501  * m_map_blender_to_gameobject is freed after conversion */
502 void KX_BlenderSceneConverter::UnregisterGameObject(
503                                                                         KX_GameObject *gameobject) 
504 {
505         struct Object *bobp= gameobject->GetBlenderObject();
506         if (bobp) {
507                 CHashedPtr bptr(bobp);
508                 KX_GameObject **gobp= m_map_blender_to_gameobject[bptr];
509                 if (gobp && *gobp == gameobject)
510                 {
511                         // also maintain m_map_blender_to_gameobject if the gameobject
512                         // being removed is matching the blender object
513                         m_map_blender_to_gameobject.remove(bptr);
514                 }
515         }
516 }
517
518 KX_GameObject *KX_BlenderSceneConverter::FindGameObject(
519                                                                         struct Object *for_blenderobject) 
520 {
521         KX_GameObject **obp= m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)];
522         
523         return obp?*obp:NULL;
524 }
525
526 void KX_BlenderSceneConverter::RegisterGameMesh(
527                                                                         RAS_MeshObject *gamemesh,
528                                                                         struct Mesh *for_blendermesh)
529 {
530         if(for_blendermesh) { /* dynamically loaded meshes we dont want to keep lookups for */
531                 m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh);
532         }
533         m_meshobjects.push_back(pair<KX_Scene*,RAS_MeshObject*>(m_currentScene,gamemesh));
534 }
535
536
537
538 RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(
539                                                                         struct Mesh *for_blendermesh/*,
540                                                                         unsigned int onlayer*/)
541 {
542         RAS_MeshObject** meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)];
543         
544         if (meshp/* && onlayer==(*meshp)->GetLightLayer()*/) {
545                 return *meshp;
546         } else {
547                 return NULL;
548         }
549 }
550
551         
552
553
554         
555
556 void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat)
557 {
558         m_polymaterials.push_back(pair<KX_Scene*,RAS_IPolyMaterial*>(m_currentScene,polymat));
559 }
560
561
562
563 void KX_BlenderSceneConverter::RegisterInterpolatorList(
564                                                                         BL_InterpolatorList *adtList,
565                                                                         struct AnimData *for_adt)
566 {
567         m_map_blender_to_gameAdtList.insert(CHashedPtr(for_adt), adtList);
568 }
569
570
571
572 BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(
573                                                                         struct AnimData *for_adt)
574 {
575         BL_InterpolatorList **listp = m_map_blender_to_gameAdtList[CHashedPtr(for_adt)];
576                 
577         return listp?*listp:NULL;
578 }
579
580
581
582 void KX_BlenderSceneConverter::RegisterGameActuator(
583                                                                         SCA_IActuator *act,
584                                                                         struct bActuator *for_actuator)
585 {
586         m_map_blender_to_gameactuator.insert(CHashedPtr(for_actuator), act);
587 }
588
589
590
591 SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(
592                                                                         struct bActuator *for_actuator)
593 {
594         SCA_IActuator **actp = m_map_blender_to_gameactuator[CHashedPtr(for_actuator)];
595         
596         return actp?*actp:NULL;
597 }
598
599
600
601 void KX_BlenderSceneConverter::RegisterGameController(
602                                                                         SCA_IController *cont,
603                                                                         struct bController *for_controller)
604 {
605         m_map_blender_to_gamecontroller.insert(CHashedPtr(for_controller), cont);
606 }
607
608
609
610 SCA_IController *KX_BlenderSceneConverter::FindGameController(
611                                                                         struct bController *for_controller)
612 {
613         SCA_IController **contp = m_map_blender_to_gamecontroller[CHashedPtr(for_controller)];
614         
615         return contp?*contp:NULL;
616 }
617
618
619
620 void KX_BlenderSceneConverter::RegisterWorldInfo(
621                                                                         KX_WorldInfo *worldinfo)
622 {
623         m_worldinfos.push_back(pair<KX_Scene*,KX_WorldInfo*>(m_currentScene,worldinfo));
624 }
625
626 void    KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo)
627 {
628
629         KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
630         int numScenes = scenes->size();
631         int i;
632         for (i=0;i<numScenes;i++)
633         {
634                 KX_Scene* scene = scenes->at(i);
635                 //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
636                 CListValue* parentList = scene->GetRootParentList();
637                 int numObjects = parentList->GetCount();
638                 int g;
639                 for (g=0;g<numObjects;g++)
640                 {
641                         KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
642                         if (gameObj->IsDynamic())
643                         {
644                                 //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
645                                 
646                                 Object* blenderObject = gameObj->GetBlenderObject();
647                                 if (blenderObject)
648                                 {
649 #if 0
650                                         //erase existing ipo's
651                                         Ipo* ipo = blenderObject->ipo;//findIpoForName(blenderObject->id.name+2);
652                                         if (ipo)
653                                         {       //clear the curve data
654                                                 if (clearIpo){//rcruiz
655                                                         IpoCurve *icu1;
656                                                                                                                 
657                                                         int numCurves = 0;
658                                                         for( icu1 = (IpoCurve*)ipo->curve.first; icu1;  ) {
659                                                         
660                                                                 IpoCurve* tmpicu = icu1;
661                                                                 
662                                                                 /*int i;
663                                                                 BezTriple *bezt;
664                                                                 for( bezt = tmpicu->bezt, i = 0;        i < tmpicu->totvert; i++, bezt++){
665                                                                         printf("(%f,%f,%f),(%f,%f,%f),(%f,%f,%f)\n",bezt->vec[0][0],bezt->vec[0][1],bezt->vec[0][2],bezt->vec[1][0],bezt->vec[1][1],bezt->vec[1][2],bezt->vec[2][0],bezt->vec[2][1],bezt->vec[2][2]);
666                                                                 }*/
667                                                                 
668                                                                 icu1 = icu1->next;
669                                                                 numCurves++;
670                         
671                                                                 BLI_remlink( &( blenderObject->ipo->curve ), tmpicu );
672                                                                 if( tmpicu->bezt )
673                                                                         MEM_freeN( tmpicu->bezt );
674                                                                 MEM_freeN( tmpicu );
675                                                                 localDel_ipoCurve( tmpicu );
676                                                         }
677                                                 }
678                                         } else
679                                         {       ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB);
680                                                 blenderObject->ipo = ipo;
681
682                                         }
683 #endif
684                                 }
685                         }
686
687                 }
688                 
689         
690         }
691
692
693
694 }
695
696 void    KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo(){
697         
698         if (addInitFromFrame){          
699                 KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
700                 int numScenes = scenes->size();
701                 if (numScenes>=0){
702                         KX_Scene* scene = scenes->at(0);
703                         CListValue* parentList = scene->GetRootParentList();
704                         for (int ix=0;ix<parentList->GetCount();ix++){
705                                 KX_GameObject* gameobj = (KX_GameObject*)parentList->GetValue(ix);
706                                 if (!gameobj->IsDynamic()){
707                                         Object* blenderobject = gameobj->GetBlenderObject();
708                                         if (!blenderobject)
709                                                 continue;
710                                         if (blenderobject->type==OB_ARMATURE)
711                                                 continue;
712                                         float eu[3];
713                                         mat4_to_eul(eu,blenderobject->obmat);                                   
714                                         MT_Point3 pos = MT_Point3(
715                                                 blenderobject->obmat[3][0],
716                                                 blenderobject->obmat[3][1],
717                                                 blenderobject->obmat[3][2]
718                                         );
719                                         MT_Vector3 eulxyz = MT_Vector3(
720                                                 eu[0],
721                                                 eu[1],
722                                                 eu[2]
723                                         );
724                                         MT_Vector3 scale = MT_Vector3(
725                                                 blenderobject->size[0],
726                                                 blenderobject->size[1],
727                                                 blenderobject->size[2]
728                                         );
729                                         gameobj->NodeSetLocalPosition(pos);
730                                         gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
731                                         gameobj->NodeSetLocalScale(scale);
732                                         gameobj->NodeUpdateGS(0);
733                                 }
734                         }
735                 }
736         }
737 }
738
739
740         ///this generates ipo curves for position, rotation, allowing to use game physics in animation
741 void    KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
742 {
743
744         KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
745         int numScenes = scenes->size();
746         int i;
747         for (i=0;i<numScenes;i++)
748         {
749                 KX_Scene* scene = scenes->at(i);
750                 //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
751                 CListValue* parentList = scene->GetObjectList();
752                 int numObjects = parentList->GetCount();
753                 int g;
754                 for (g=0;g<numObjects;g++)
755                 {
756                         KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
757                         Object* blenderObject = gameObj->GetBlenderObject();
758                         if (blenderObject && blenderObject->parent==NULL && gameObj->GetPhysicsController() != NULL)
759                         {
760                                 //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
761
762                                 if(blenderObject->adt==NULL)
763                                         BKE_id_add_animdata(&blenderObject->id);
764
765                                 if (blenderObject->adt)
766                                 {
767                                         const MT_Point3& position = gameObj->NodeGetWorldPosition();
768                                         //const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
769                                         const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation();
770
771                                         position.getValue(blenderObject->loc);
772
773                                         float tmat[3][3];
774                                         for (int r=0;r<3;r++)
775                                                 for (int c=0;c<3;c++)
776                                                         tmat[r][c] = orn[c][r];
777
778                                         mat3_to_compatible_eul(blenderObject->rot, blenderObject->rot, tmat);
779
780                                         insert_keyframe(&blenderObject->id, NULL, NULL, "location", -1, frameNumber, INSERTKEY_FAST);
781                                         insert_keyframe(&blenderObject->id, NULL, NULL, "rotation_euler", -1, frameNumber, INSERTKEY_FAST);
782
783 #if 0
784                                         const MT_Point3& position = gameObj->NodeGetWorldPosition();
785                                         //const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
786                                         const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation();
787                                         
788                                         float eulerAngles[3];   
789                                         float eulerAnglesOld[3] = {0.0f, 0.0f, 0.0f};                                           
790                                         float tmat[3][3];
791                                         
792                                         // XXX animato
793                                         Ipo* ipo = blenderObject->ipo;
794
795                                         //create the curves, if not existing, set linear if new
796
797                                         IpoCurve *icu_lx = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX");
798                                         if (!icu_lx) {
799                                                 icu_lx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1);
800                                                 if(icu_lx) icu_lx->ipo = IPO_LIN;
801                                         }
802                                         IpoCurve *icu_ly = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY");
803                                         if (!icu_ly) {
804                                                 icu_ly = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1);
805                                                 if(icu_ly) icu_ly->ipo = IPO_LIN;
806                                         }
807                                         IpoCurve *icu_lz = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ");
808                                         if (!icu_lz) {
809                                                 icu_lz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1);
810                                                 if(icu_lz) icu_lz->ipo = IPO_LIN;
811                                         }
812                                         IpoCurve *icu_rx = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX");
813                                         if (!icu_rx) {
814                                                 icu_rx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1);
815                                                 if(icu_rx) icu_rx->ipo = IPO_LIN;
816                                         }
817                                         IpoCurve *icu_ry = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY");
818                                         if (!icu_ry) {
819                                                 icu_ry = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1);
820                                                 if(icu_ry) icu_ry->ipo = IPO_LIN;
821                                         }
822                                         IpoCurve *icu_rz = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ");
823                                         if (!icu_rz) {
824                                                 icu_rz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1);
825                                                 if(icu_rz) icu_rz->ipo = IPO_LIN;
826                                         }
827                                         
828                                         if(icu_rx) eulerAnglesOld[0]= eval_icu( icu_rx, frameNumber - 1 ) / ((180 / 3.14159265f) / 10);
829                                         if(icu_ry) eulerAnglesOld[1]= eval_icu( icu_ry, frameNumber - 1 ) / ((180 / 3.14159265f) / 10);
830                                         if(icu_rz) eulerAnglesOld[2]= eval_icu( icu_rz, frameNumber - 1 ) / ((180 / 3.14159265f) / 10);
831                                         
832                                         // orn.getValue((float *)tmat); // uses the wrong ordering, cant use this
833                                         for (int r=0;r<3;r++)
834                                                 for (int c=0;c<3;c++)
835                                                         tmat[r][c] = orn[c][r];
836                                         
837                                         // mat3_to_eul( eulerAngles,tmat); // better to use Mat3ToCompatibleEul
838                                         mat3_to_compatible_eul( eulerAngles, eulerAnglesOld,tmat);
839                                         
840                                         //eval_icu
841                                         for(int x = 0; x < 3; x++)
842                                                 eulerAngles[x] *= (float) ((180 / 3.14159265f) / 10.0);
843                                         
844                                         //fill the curves with data
845                                         if (icu_lx) insert_vert_icu(icu_lx, frameNumber, position.x(), 1);
846                                         if (icu_ly) insert_vert_icu(icu_ly, frameNumber, position.y(), 1);
847                                         if (icu_lz) insert_vert_icu(icu_lz, frameNumber, position.z(), 1);
848                                         if (icu_rx) insert_vert_icu(icu_rx, frameNumber, eulerAngles[0], 1);
849                                         if (icu_ry) insert_vert_icu(icu_ry, frameNumber, eulerAngles[1], 1);
850                                         if (icu_rz) insert_vert_icu(icu_rz, frameNumber, eulerAngles[2], 1);
851                                         
852                                         // Handles are corrected at the end, testhandles_ipocurve isnt needed yet
853 #endif
854                                 }
855                         }
856                 }
857         }
858 }
859
860
861 void    KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
862 {
863
864         KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
865         int numScenes = scenes->size();
866         int i;
867         for (i=0;i<numScenes;i++)
868         {
869                 KX_Scene* scene = scenes->at(i);
870                 //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
871                 CListValue* parentList = scene->GetRootParentList();
872                 int numObjects = parentList->GetCount();
873                 int g;
874                 for (g=0;g<numObjects;g++)
875                 {
876                         KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
877                         if (gameObj->IsDynamic())
878                         {
879                                 //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
880                                 
881                                 Object* blenderObject = gameObj->GetBlenderObject();
882                                 if (blenderObject && blenderObject->ipo)
883                                 {
884                                         // XXX animato
885 #if 0
886                                         Ipo* ipo = blenderObject->ipo;
887                                         
888                                         //create the curves, if not existing
889                                         //testhandles_ipocurve checks for NULL
890                                         testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"));
891                                         testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"));
892                                         testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"));
893                                         testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"));
894                                         testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"));
895                                         testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"));
896 #endif
897                                 }
898                         }
899
900                 }
901                 
902         
903         }
904
905
906
907 }
908
909 #ifdef WITH_PYTHON
910 PyObject *KX_BlenderSceneConverter::GetPyNamespace()
911 {
912         return m_ketsjiEngine->GetPyNamespace();
913 }
914 #endif
915
916 vector<Main*> &KX_BlenderSceneConverter::GetMainDynamic()
917 {
918         return m_DynamicMaggie;
919 }
920
921 Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path)
922 {
923         for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++)
924                 if(strcmp((*it)->name, path)==0)
925                         return *it;
926         
927         return NULL;
928 }
929
930 bool KX_BlenderSceneConverter::LinkBlendFileMemory(void *data, int length, const char *path, char *group, KX_Scene *scene_merge, char **err_str)
931 {
932         BlendHandle *bpy_openlib = BLO_blendhandle_from_memory(data, length);
933
934         // Error checking is done in LinkBlendFile
935         return LinkBlendFile(bpy_openlib, path, group, scene_merge, err_str);
936 }
937
938 bool KX_BlenderSceneConverter::LinkBlendFilePath(const char *path, char *group, KX_Scene *scene_merge, char **err_str)
939 {
940         BlendHandle *bpy_openlib = BLO_blendhandle_from_file( (char *)path );
941
942         // Error checking is done in LinkBlendFile
943         return LinkBlendFile(bpy_openlib, path, group, scene_merge, err_str);
944 }
945
946 bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str)
947 {
948         bContext *C;
949         Main *main_newlib; /* stored as a dynamic 'main' until we free it */
950         Main *main_tmp= NULL; /* created only for linking, then freed */
951         LinkNode *names = NULL;
952         int idcode= BKE_idcode_from_name(group);
953         short flag= 0; /* dont need any special options */
954         ReportList reports;
955         static char err_local[255];
956         
957         /* only scene and mesh supported right now */
958         if(idcode!=ID_SCE && idcode!=ID_ME &&idcode!=ID_AC) {
959                 snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group);
960                 return false;
961         }
962         
963         if(GetMainDynamicPath(path)) {
964                 snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path);
965                 *err_str= err_local;
966                 return false;
967         }
968
969         if(bpy_openlib==NULL) {
970                 snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path);
971                 *err_str= err_local;
972                 return false;
973         }
974         
975         main_newlib= (Main *)MEM_callocN( sizeof(Main), "BgeMain");
976         C= CTX_create();
977         CTX_data_main_set(C, main_newlib);
978         BKE_reports_init(&reports, RPT_STORE);  
979
980         /* here appending/linking starts */
981         main_tmp = BLO_library_append_begin(C, &bpy_openlib, (char *)path);
982         
983         names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode);
984         
985         int i=0;
986         LinkNode *n= names;
987         while(n) {
988                 BLO_library_append_named_part(C, main_tmp, &bpy_openlib, (char *)n->link, idcode, 0);
989                 n= (LinkNode *)n->next;
990                 i++;
991         }
992         BLI_linklist_free(names, free); /* free linklist *and* each node's data */
993         
994         BLO_library_append_end(C, main_tmp, &bpy_openlib, idcode, flag);
995         BLO_blendhandle_close(bpy_openlib);
996         
997         CTX_free(C);
998         BKE_reports_clear(&reports);
999         /* done linking */      
1000         
1001         /* needed for lookups*/
1002         GetMainDynamic().push_back(main_newlib);
1003         strncpy(main_newlib->name, path, sizeof(main_newlib->name));    
1004         
1005         
1006         if(idcode==ID_ME) {
1007                 /* Convert all new meshes into BGE meshes */
1008                 ID* mesh;
1009                 KX_Scene *kx_scene= m_currentScene;
1010         
1011                 for(mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) {
1012                         RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this);
1013                         kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
1014                 }
1015         }
1016         else if(idcode==ID_AC) {
1017                 /* Convert all actions */
1018                 ID *action;
1019                 KX_Scene *kx_scene= m_currentScene;
1020
1021                 for(action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) {
1022                         printf("ActionName: %s\n", action->name);
1023                         kx_scene->GetLogicManager()->RegisterActionName(action->name+2, action);
1024                 }
1025         }
1026         else if(idcode==ID_SCE) {               
1027                 /* Merge all new linked in scene into the existing one */
1028                 ID *scene;
1029                 for(scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) {
1030                         printf("SceneName: %s\n", scene->name);
1031                         
1032                         /* merge into the base  scene */
1033                         KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene);
1034                         scene_merge->MergeScene(other);
1035                         
1036                         // RemoveScene(other); // Dont run this, it frees the entire scene converter data, just delete the scene
1037                         delete other;
1038                 }
1039         }
1040         
1041         return true;
1042 }
1043
1044 /* Note m_map_*** are all ok and dont need to be freed
1045  * most are temp and NewRemoveObject frees m_map_gameobject_to_blender */
1046 bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
1047 {
1048         int maggie_index;
1049         int i=0;
1050
1051         if(maggie==NULL)
1052                 return false;
1053         
1054         /* tag all false except the one we remove */
1055         for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
1056                 Main *main= *it;
1057                 if(main != maggie) {
1058                         tag_main(main, 0);
1059                 }
1060                 else {
1061                         maggie_index= i;
1062                 }
1063                 i++;
1064         }
1065
1066         m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index);
1067         tag_main(maggie, 1);
1068
1069
1070         /* free all tagged objects */
1071         KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
1072         int numScenes = scenes->size();
1073
1074
1075         for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
1076         {
1077                 KX_Scene* scene = scenes->at(scene_idx);
1078                 if(IS_TAGGED(scene->GetBlenderScene())) {
1079                         RemoveScene(scene); // XXX - not tested yet
1080                         scene_idx--;
1081                         numScenes--;
1082                 }
1083                 else {
1084                         
1085                         /* incase the mesh might be refered to later */
1086                         {
1087                                 GEN_Map<STR_HashedString,void*> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap();
1088                                 
1089                                 for(int i=0; i<mapStringToMeshes.size(); i++)
1090                                 {
1091                                         RAS_MeshObject *meshobj= (RAS_MeshObject *) *mapStringToMeshes.at(i);
1092                                         if(meshobj && IS_TAGGED(meshobj->GetMesh()))
1093                                         {       
1094                                                 STR_HashedString mn = meshobj->GetName();
1095                                                 mapStringToMeshes.remove(mn);
1096                                                 i--;
1097                                         }
1098                                 }
1099                         }
1100
1101                         /* Now unregister actions */
1102                         {
1103                                 GEN_Map<STR_HashedString,void*> &mapStringToActions = scene->GetLogicManager()->GetActionMap();
1104
1105                                 for(int i=0; i<mapStringToActions.size(); i++)
1106                                 {
1107                                         ID *action= (ID*) *mapStringToActions.at(i);
1108
1109                                         if(IS_TAGGED(action))
1110                                         {
1111                                                 STR_HashedString an = action->name+2;
1112                                                 mapStringToActions.remove(an);
1113                                                 i--;
1114                                         }
1115                                 }
1116                         }
1117                         
1118                         //scene->FreeTagged(); /* removed tagged objects and meshes*/
1119                         CListValue *obj_lists[] = {scene->GetObjectList(), scene->GetInactiveList(), NULL};
1120
1121                         for(int ob_ls_idx=0; obj_lists[ob_ls_idx]; ob_ls_idx++)
1122                         {
1123                                 CListValue *obs= obj_lists[ob_ls_idx];
1124                                 RAS_MeshObject* mesh;
1125
1126                                 for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++)
1127                                 {
1128                                         KX_GameObject* gameobj = (KX_GameObject*)obs->GetValue(ob_idx);
1129                                         if(IS_TAGGED(gameobj->GetBlenderObject())) {
1130
1131                                                 int size_before = obs->GetCount();
1132
1133                                                 /* Eventually calls RemoveNodeDestructObject
1134                                                  * frees m_map_gameobject_to_blender from UnregisterGameObject */
1135                                                 scene->RemoveObject(gameobj);
1136
1137                                                 if(size_before != obs->GetCount())
1138                                                         ob_idx--;
1139                                                 else {
1140                                                         printf("ERROR COULD NOT REMOVE \"%s\"\n", gameobj->GetName().ReadPtr());
1141                                                 }
1142                                         }
1143                                         else {
1144                                                 /* free the mesh, we could be referecing a linked one! */
1145                                                 int mesh_index= gameobj->GetMeshCount();
1146                                                 while(mesh_index--) {
1147                                                         mesh= gameobj->GetMesh(mesh_index);
1148                                                         if(IS_TAGGED(mesh->GetMesh())) {
1149                                                                 gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */
1150                                                                 break;
1151                                                         }
1152                                                 }
1153
1154                                                 /* make sure action actuators are not referencing tagged actions */
1155                                                 for (int act_idx=0; act_idx<gameobj->GetActuators().size(); act_idx++)
1156                                                 {
1157                                                         if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION))
1158                                                         {
1159                                                                 BL_ActionActuator *act = (BL_ActionActuator*)gameobj->GetActuators()[act_idx];
1160                                                                 if(IS_TAGGED(act->GetAction()))
1161                                                                         act->SetAction(NULL);
1162                                                         }
1163                                                 }
1164                                         }
1165                                 }
1166                         }
1167                 }
1168         }
1169
1170
1171         int size;
1172
1173         // delete the entities of this scene
1174         /* TODO - */
1175         /*
1176         vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
1177         size = m_worldinfos.size();
1178         for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
1179                 if ((*worldit).second) {
1180                         delete (*worldit).second;
1181                         *worldit = m_worldinfos.back();
1182                         m_worldinfos.pop_back();
1183                         size--;
1184                 } else {
1185                         i++;
1186                         worldit++;
1187                 }
1188         }*/
1189
1190
1191         /* Worlds dont reference original blender data so we need to make a set from them */
1192         typedef std::set<KX_WorldInfo*> KX_WorldInfoSet;
1193         KX_WorldInfoSet worldset;
1194         for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
1195         {
1196                 KX_Scene* scene = scenes->at(scene_idx);
1197                 if(scene->GetWorldInfo())
1198                         worldset.insert( scene->GetWorldInfo() );
1199         }
1200
1201         vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
1202         size = m_worldinfos.size();
1203         for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
1204                 if ((*worldit).second && (worldset.count((*worldit).second)) == 0) {
1205                         delete (*worldit).second;
1206                         *worldit = m_worldinfos.back();
1207                         m_worldinfos.pop_back();
1208                         size--;
1209                 } else {
1210                         i++;
1211                         worldit++;
1212                 }
1213         }
1214         worldset.clear();
1215         /* done freeing the worlds */
1216
1217
1218
1219
1220         vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit;
1221         size = m_polymaterials.size();
1222
1223
1224
1225         for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
1226                 RAS_IPolyMaterial *mat= (*polymit).second;
1227                 Material *bmat= NULL;
1228
1229                 /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
1230                 if(mat->GetFlag() & RAS_BLENDERMAT) {
1231                         KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
1232                         bmat= bl_mat->GetBlenderMaterial();
1233
1234                 } else {
1235                         KX_PolygonMaterial *kx_mat = static_cast<KX_PolygonMaterial*>(mat);
1236                         bmat= kx_mat->GetBlenderMaterial();
1237                 }
1238
1239                 if (IS_TAGGED(bmat)) {
1240                         /* only remove from bucket */
1241                         ((*polymit).first)->GetBucketManager()->RemoveMaterial(mat);
1242                 }
1243
1244                 i++;
1245                 polymit++;
1246         }
1247
1248
1249
1250         for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
1251                 RAS_IPolyMaterial *mat= (*polymit).second;
1252                 Material *bmat= NULL;
1253
1254                 /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
1255                 if(mat->GetFlag() & RAS_BLENDERMAT) {
1256                         KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
1257                         bmat= bl_mat->GetBlenderMaterial();
1258
1259                 } else {
1260                         KX_PolygonMaterial *kx_mat = static_cast<KX_PolygonMaterial*>(mat);
1261                         bmat= kx_mat->GetBlenderMaterial();
1262                 }
1263
1264                 if(bmat) {
1265                         //printf("FOUND MAT '%s' !!! ", ((ID*)bmat)->name+2);
1266                 }
1267                 else {
1268                         //printf("LOST MAT  !!!");
1269                 }
1270
1271                 if (IS_TAGGED(bmat)) {
1272
1273                         delete (*polymit).second;
1274                         *polymit = m_polymaterials.back();
1275                         m_polymaterials.pop_back();
1276                         size--;
1277                         //printf("tagged !\n");
1278                 } else {
1279                         i++;
1280                         polymit++;
1281                         //printf("(un)tagged !\n");
1282                 }
1283         }
1284
1285         vector<pair<KX_Scene*,BL_Material*> >::iterator matit;
1286         size = m_materials.size();
1287         for (i=0, matit=m_materials.begin(); i<size; ) {
1288                 BL_Material *mat= (*matit).second;
1289                 if (IS_TAGGED(mat->material)) {
1290                         delete (*matit).second;
1291                         *matit = m_materials.back();
1292                         m_materials.pop_back();
1293                         size--;
1294                 } else {
1295                         i++;
1296                         matit++;
1297                 }
1298         }
1299
1300         vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
1301         size = m_meshobjects.size();
1302         for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
1303                 RAS_MeshObject *me= (*meshit).second;
1304                 if (IS_TAGGED(me->GetMesh())) {
1305                         delete (*meshit).second;
1306                         *meshit = m_meshobjects.back();
1307                         m_meshobjects.pop_back();
1308                         size--;
1309                 } else {
1310                         i++;
1311                         meshit++;
1312                 }
1313         }
1314
1315         free_main(maggie);
1316
1317         return true;
1318 }
1319
1320 bool KX_BlenderSceneConverter::FreeBlendFile(const char *path)
1321 {
1322         return FreeBlendFile(GetMainDynamicPath(path));
1323 }
1324
1325 bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from)
1326 {
1327
1328         {
1329                 vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itp = m_worldinfos.begin();
1330                 while (itp != m_worldinfos.end()) {
1331                         if ((*itp).first==from)
1332                                 (*itp).first= to;
1333                         itp++;
1334                 }
1335         }
1336
1337         {
1338                 vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
1339                 while (itp != m_polymaterials.end()) {
1340                         if ((*itp).first==from) {
1341                                 (*itp).first= to;
1342
1343                                 /* also switch internal data */
1344                                 RAS_IPolyMaterial*mat= (*itp).second;
1345                                 mat->Replace_IScene(to);
1346                         }
1347                         itp++;
1348                 }
1349         }
1350
1351         {
1352                 vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itp = m_meshobjects.begin();
1353                 while (itp != m_meshobjects.end()) {
1354                         if ((*itp).first==from)
1355                                 (*itp).first= to;
1356                         itp++;
1357                 }
1358         }
1359
1360         {
1361                 vector<pair<KX_Scene*,BL_Material*> >::iterator itp = m_materials.begin();
1362                 while (itp != m_materials.end()) {
1363                         if ((*itp).first==from)
1364                                 (*itp).first= to;
1365                         itp++;
1366                 }
1367         }
1368         
1369         return true;
1370 }
1371
1372 /* This function merges a mesh from the current scene into another main
1373  * it does not convert */
1374 RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, Main *maggie, const char *name)
1375 {
1376         /* Find a mesh in the current main */
1377         ID *me= static_cast<ID *>(BLI_findstring(&m_maggie->mesh, name, offsetof(ID, name) + 2));
1378         
1379         if(me==NULL) {
1380                 printf("Could not be found \"%s\"\n", name);
1381                 return NULL;
1382         }
1383         
1384         /* Watch this!, if its used in the original scene can cause big troubles */
1385         if(me->us > 0) {
1386                 printf("Mesh has a user \"%s\"\n", name);
1387                 me = (ID*)copy_mesh((Mesh*)me);
1388                 me->us--;
1389         }
1390         BLI_remlink(&m_maggie->mesh, me); /* even if we made the copy it needs to be removed */
1391         BLI_addtail(&maggie->mesh, me);
1392
1393         
1394         /* Must copy the materials this uses else we cant free them */
1395         {
1396                 Mesh *mesh= (Mesh *)me;
1397                 
1398                 /* ensure all materials are tagged */
1399                 for(int i=0; i<mesh->totcol; i++)
1400                         if(mesh->mat[i])
1401                                 mesh->mat[i]->id.flag &= ~LIB_DOIT;
1402                 
1403                 for(int i=0; i<mesh->totcol; i++)
1404                 {
1405                         Material *mat_old= mesh->mat[i];
1406                         
1407                         /* if its tagged its a replaced material */
1408                         if(mat_old && (mat_old->id.flag & LIB_DOIT)==0)
1409                         {
1410                                 Material *mat_old= mesh->mat[i];
1411                                 Material *mat_new= copy_material( mat_old );
1412                                 
1413                                 mat_new->id.flag |= LIB_DOIT;
1414                                 mat_old->id.us--;
1415                                 
1416                                 BLI_remlink(&m_maggie->mat, mat_new);
1417                                 BLI_addtail(&maggie->mat, mat_new);
1418                                 
1419                                 mesh->mat[i]= mat_new;
1420                                 
1421                                 /* the same material may be used twice */
1422                                 for(int j=i+1; j<mesh->totcol; j++)
1423                                 {
1424                                         if(mesh->mat[j]==mat_old)
1425                                         {
1426                                                 mesh->mat[j]= mat_new;
1427                                                 mat_new->id.us++;
1428                                                 mat_old->id.us--;
1429                                         }
1430                                 }
1431                         }
1432                 }
1433         }
1434         
1435         RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this);
1436         kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
1437         m_map_mesh_to_gamemesh.clear(); /* This is at runtime so no need to keep this, BL_ConvertMesh adds */
1438         return meshobj;
1439 }