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