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