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