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