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