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