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