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