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