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