Blender V2.61 - r43446

KX_BlenderSceneConverter.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #if defined(WIN32) && !defined(FREE_WINDOWS)
00034 #pragma warning (disable:4786) // suppress stl-MSVC debug info warning
00035 #endif
00036 
00037 #include "KX_Scene.h"
00038 #include "KX_GameObject.h"
00039 #include "KX_BlenderSceneConverter.h"
00040 #include "KX_IpoConvert.h"
00041 #include "RAS_MeshObject.h"
00042 #include "KX_PhysicsEngineEnums.h"
00043 #include "PHY_IPhysicsEnvironment.h"
00044 #include "KX_KetsjiEngine.h"
00045 #include "KX_IPhysicsController.h"
00046 #include "BL_Material.h"
00047 #include "BL_ActionActuator.h"
00048 #include "KX_BlenderMaterial.h"
00049 #include "KX_PolygonMaterial.h"
00050 
00051 
00052 #include "BL_System.h"
00053 
00054 #include "DummyPhysicsEnvironment.h"
00055 
00056 #include "KX_ConvertPhysicsObject.h"
00057 
00058 #ifdef USE_BULLET
00059 #include "CcdPhysicsEnvironment.h"
00060 #endif
00061 
00062 #include "KX_BlenderSceneConverter.h"
00063 #include "KX_BlenderScalarInterpolator.h"
00064 #include "BL_BlenderDataConversion.h"
00065 #include "BlenderWorldInfo.h"
00066 #include "KX_Scene.h"
00067 
00068 /* This little block needed for linking to Blender... */
00069 #ifdef WIN32
00070 #include "BLI_winstuff.h"
00071 #endif
00072 
00073 /* This list includes only data type definitions */
00074 #include "DNA_scene_types.h"
00075 #include "DNA_world_types.h"
00076 #include "BKE_main.h"
00077 
00078 #include "BLI_math.h"
00079 
00080 extern "C"
00081 {
00082 #include "DNA_object_types.h"
00083 #include "DNA_curve_types.h"
00084 #include "DNA_mesh_types.h"
00085 #include "DNA_material_types.h"
00086 #include "BLI_blenlib.h"
00087 #include "MEM_guardedalloc.h"
00088 #include "BKE_global.h"
00089 #include "BKE_animsys.h"
00090 #include "BKE_library.h"
00091 #include "BKE_material.h" // copy_material
00092 #include "BKE_mesh.h" // copy_mesh
00093 #include "DNA_space_types.h"
00094 #include "DNA_anim_types.h"
00095 #include "RNA_define.h"
00096 #include "../../blender/editors/include/ED_keyframing.h"
00097 }
00098 
00099 /* Only for dynamic loading and merging */
00100 #include "RAS_BucketManager.h" // XXX cant stay
00101 #include "KX_BlenderSceneConverter.h"
00102 #include "BL_BlenderDataConversion.h"
00103 #include "KX_MeshProxy.h"
00104 #include "RAS_MeshObject.h"
00105 extern "C" {
00106     #include "BKE_context.h"
00107     #include "BLO_readfile.h"
00108     #include "BKE_idcode.h"
00109     #include "BKE_report.h"
00110     #include "DNA_space_types.h"
00111     #include "DNA_windowmanager_types.h" /* report api */
00112     #include "../../blender/blenlib/BLI_linklist.h"
00113 }
00114 
00115 KX_BlenderSceneConverter::KX_BlenderSceneConverter(
00116                             struct Main* maggie,
00117                             class KX_KetsjiEngine* engine
00118                             )
00119                             : m_maggie(maggie),
00120                             /*m_maggie_dyn(NULL),*/
00121                             m_ketsjiEngine(engine),
00122                             m_alwaysUseExpandFraming(false),
00123                             m_usemat(false),
00124                             m_useglslmat(false)
00125 {
00126     tag_main(maggie, 0); /* avoid re-tagging later on */
00127     m_newfilename = "";
00128 }
00129 
00130 
00131 KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
00132 {
00133     // clears meshes, and hashmaps from blender to gameengine data
00134     int i;
00135     // delete sumoshapes
00136     
00137 
00138     int numAdtLists = m_map_blender_to_gameAdtList.size();
00139     for (i=0; i<numAdtLists; i++) {
00140         BL_InterpolatorList *adtList= *m_map_blender_to_gameAdtList.at(i);
00141 
00142         delete (adtList);
00143     }
00144 
00145     vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itw = m_worldinfos.begin();
00146     while (itw != m_worldinfos.end()) {
00147         delete (*itw).second;
00148         itw++;
00149     }
00150 
00151     vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
00152     while (itp != m_polymaterials.end()) {
00153         delete (*itp).second;
00154         itp++;
00155     }
00156 
00157     // delete after RAS_IPolyMaterial
00158     vector<pair<KX_Scene*,BL_Material *> >::iterator itmat = m_materials.begin();
00159     while (itmat != m_materials.end()) {
00160         delete (*itmat).second;
00161         itmat++;
00162     }   
00163 
00164 
00165     vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itm = m_meshobjects.begin();
00166     while (itm != m_meshobjects.end()) {
00167         delete (*itm).second;
00168         itm++;
00169     }
00170 
00171 #ifdef USE_BULLET
00172     KX_ClearBulletSharedShapes();
00173 #endif
00174 
00175     /* free any data that was dynamically loaded */
00176     for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
00177         Main *main= *it;
00178         free_main(main);
00179     }
00180 
00181     m_DynamicMaggie.clear();
00182 }
00183 
00184 void KX_BlenderSceneConverter::SetNewFileName(const STR_String& filename)
00185 {
00186     m_newfilename = filename;
00187 }
00188 
00189 
00190 
00191 bool KX_BlenderSceneConverter::TryAndLoadNewFile()
00192 {
00193     bool result = false;
00194 
00195     // find the file
00196 /*  if ()
00197     {
00198         result = true;
00199     }
00200     // if not, clear the newfilename
00201     else
00202     {
00203         m_newfilename = ""; 
00204     }
00205 */
00206     return result;
00207 }
00208 
00209 Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name)
00210 {
00211     Scene *sce;
00212 
00217     if((sce= (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
00218         return sce;
00219 
00220     for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
00221         Main *main= *it;
00222 
00223         if((sce= (Scene *)BLI_findstring(&main->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
00224             return sce;
00225     }
00226 
00227     return (Scene*)m_maggie->scene.first;
00228 
00229 }
00230 #include "KX_PythonInit.h"
00231 
00232 #ifdef USE_BULLET
00233 
00234 #include "LinearMath/btIDebugDraw.h"
00235 
00236 
00237 struct  BlenderDebugDraw : public btIDebugDraw
00238 {
00239     BlenderDebugDraw () :
00240         m_debugMode(0) 
00241     {
00242     }
00243     
00244     int m_debugMode;
00245 
00246     virtual void    drawLine(const btVector3& from,const btVector3& to,const btVector3& color)
00247     {
00248         if (m_debugMode >0)
00249         {
00250             MT_Vector3 kxfrom(from[0],from[1],from[2]);
00251             MT_Vector3 kxto(to[0],to[1],to[2]);
00252             MT_Vector3 kxcolor(color[0],color[1],color[2]);
00253 
00254             KX_RasterizerDrawDebugLine(kxfrom,kxto,kxcolor);
00255         }
00256     }
00257     
00258     virtual void    reportErrorWarning(const char* warningString)
00259     {
00260 
00261     }
00262 
00263     virtual void    drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,float distance,int lifeTime,const btVector3& color)
00264     {
00265         //not yet
00266     }
00267 
00268     virtual void    setDebugMode(int debugMode)
00269     {
00270         m_debugMode = debugMode;
00271     }
00272     virtual int     getDebugMode() const
00273     {
00274         return m_debugMode;
00275     }
00277     virtual void    draw3dText(const btVector3& location,const char* textString)
00278     {
00279 
00280     }
00281         
00282 };
00283 
00284 #endif
00285 
00286 void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
00287                                             class RAS_IRenderTools* rendertools,
00288                                             class RAS_ICanvas* canvas)
00289 {
00290     //find out which physics engine
00291     Scene *blenderscene = destinationscene->GetBlenderScene();
00292 
00293     e_PhysicsEngine physics_engine = UseBullet;
00294     bool useDbvtCulling = false;
00295     // hook for registration function during conversion.
00296     m_currentScene = destinationscene;
00297     destinationscene->SetSceneConverter(this);
00298     SG_SetActiveStage(SG_STAGE_CONVERTER);
00299 
00300     if (blenderscene)
00301     {
00302     
00303         switch (blenderscene->gm.physicsEngine)
00304         {
00305         case WOPHY_BULLET:
00306             {
00307                 physics_engine = UseBullet;
00308                 useDbvtCulling = (blenderscene->gm.mode & WO_DBVT_CULLING) != 0;
00309                 break;
00310             }
00311                             
00312             case WOPHY_ODE:
00313             {
00314                 physics_engine = UseODE;
00315                 break;
00316             }
00317             case WOPHY_DYNAMO:
00318             {
00319                 physics_engine = UseDynamo;
00320                 break;
00321             }
00322             case WOPHY_SUMO:
00323             {
00324                 physics_engine = UseSumo; 
00325                 break;
00326             }
00327             case WOPHY_NONE:
00328             {
00329                 physics_engine = UseNone;
00330             }
00331         }
00332     }
00333 
00334     switch (physics_engine)
00335     {
00336 #ifdef USE_BULLET
00337         case UseBullet:
00338             {
00339                 CcdPhysicsEnvironment* ccdPhysEnv = new CcdPhysicsEnvironment(useDbvtCulling);
00340                 ccdPhysEnv->setDebugDrawer(new BlenderDebugDraw());
00341                 ccdPhysEnv->setDeactivationLinearTreshold(0.8f); // default, can be overridden by Python
00342                 ccdPhysEnv->setDeactivationAngularTreshold(1.0f); // default, can be overridden by Python
00343 
00344                 SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/
00345                 int visualizePhysics = SYS_GetCommandLineInt(syshandle,"show_physics",0);
00346                 if (visualizePhysics)
00347                     ccdPhysEnv->setDebugMode(btIDebugDraw::DBG_DrawWireframe|btIDebugDraw::DBG_DrawAabb|btIDebugDraw::DBG_DrawContactPoints|btIDebugDraw::DBG_DrawText|btIDebugDraw::DBG_DrawConstraintLimits|btIDebugDraw::DBG_DrawConstraints);
00348         
00349                 //todo: get a button in blender ?
00350                 //disable / enable debug drawing (contact points, aabb's etc)   
00351                 //ccdPhysEnv->setDebugMode(1);
00352                 destinationscene->SetPhysicsEnvironment(ccdPhysEnv);
00353                 break;
00354             }
00355 #endif  
00356         case UseDynamo:
00357         {
00358         }
00359         
00360         default:
00361         case UseNone:
00362             physics_engine = UseNone;
00363             destinationscene ->SetPhysicsEnvironment(new DummyPhysicsEnvironment());
00364             break;
00365     }
00366 
00367     BL_ConvertBlenderObjects(m_maggie,
00368         destinationscene,
00369         m_ketsjiEngine,
00370         physics_engine,
00371         rendertools,
00372         canvas,
00373         this,
00374         m_alwaysUseExpandFraming
00375         );
00376 
00377     //These lookup are not needed during game
00378     m_map_blender_to_gameactuator.clear();
00379     m_map_blender_to_gamecontroller.clear();
00380     m_map_blender_to_gameobject.clear();
00381 
00382     //Clearing this lookup table has the effect of disabling the cache of meshes
00383     //between scenes, even if they are shared in the blend file.
00384     //This cache mecanism is buggy so I leave it disable and the memory leak
00385     //that would result from this is fixed in RemoveScene()
00386     m_map_mesh_to_gamemesh.clear();
00387 
00388 #ifndef USE_BULLET
00389     /* quiet compiler warning */
00390     (void)useDbvtCulling;
00391 #endif
00392 
00393 }
00394 
00395 // This function removes all entities stored in the converter for that scene
00396 // It should be used instead of direct delete scene
00397 // Note that there was some provision for sharing entities (meshes...) between
00398 // scenes but that is now disabled so all scene will have their own copy
00399 // and we can delete them here. If the sharing is reactivated, change this code too..
00400 // (see KX_BlenderSceneConverter::ConvertScene)
00401 void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
00402 {
00403     int i, size;
00404     // delete the scene first as it will stop the use of entities
00405     delete scene;
00406     // delete the entities of this scene
00407     vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
00408     size = m_worldinfos.size();
00409     for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
00410         if ((*worldit).first == scene) {
00411             delete (*worldit).second;
00412             *worldit = m_worldinfos.back();
00413             m_worldinfos.pop_back();
00414             size--;
00415         } else {
00416             i++;
00417             worldit++;
00418         }
00419     }
00420 
00421     vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit;
00422     size = m_polymaterials.size();
00423     for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
00424         if ((*polymit).first == scene) {
00425             delete (*polymit).second;
00426             *polymit = m_polymaterials.back();
00427             m_polymaterials.pop_back();
00428             size--;
00429         } else {
00430             i++;
00431             polymit++;
00432         }
00433     }
00434 
00435     vector<pair<KX_Scene*,BL_Material*> >::iterator matit;
00436     size = m_materials.size();
00437     for (i=0, matit=m_materials.begin(); i<size; ) {
00438         if ((*matit).first == scene) {
00439             delete (*matit).second;
00440             *matit = m_materials.back();
00441             m_materials.pop_back();
00442             size--;
00443         } else {
00444             i++;
00445             matit++;
00446         }
00447     }
00448 
00449     vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
00450     size = m_meshobjects.size();
00451     for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
00452         if ((*meshit).first == scene) {
00453             delete (*meshit).second;
00454             *meshit = m_meshobjects.back();
00455             m_meshobjects.pop_back();
00456             size--;
00457         } else {
00458             i++;
00459             meshit++;
00460         }
00461     }
00462 }
00463 
00464 // use blender materials
00465 void KX_BlenderSceneConverter::SetMaterials(bool val)
00466 {
00467     m_usemat = val;
00468     m_useglslmat = false;
00469 }
00470 
00471 void KX_BlenderSceneConverter::SetGLSLMaterials(bool val)
00472 {
00473     m_usemat = val;
00474     m_useglslmat = val;
00475 }
00476 
00477 bool KX_BlenderSceneConverter::GetMaterials()
00478 {
00479     return m_usemat;
00480 }
00481 
00482 bool KX_BlenderSceneConverter::GetGLSLMaterials()
00483 {
00484     return m_useglslmat;
00485 }
00486 
00487 void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat)
00488 {
00489     m_materials.push_back(pair<KX_Scene*,BL_Material *>(m_currentScene,mat));
00490 }
00491 
00492 
00493 
00494 void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(
00495     bool to_what)
00496 {
00497     m_alwaysUseExpandFraming= to_what;
00498 }
00499 
00500     
00501 
00502 void KX_BlenderSceneConverter::RegisterGameObject(
00503                                     KX_GameObject *gameobject, 
00504                                     struct Object *for_blenderobject) 
00505 {
00506     /* only maintained while converting, freed during game runtime */
00507     m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject),gameobject);
00508 }
00509 
00510 /* only need to run this during conversion since
00511  * m_map_blender_to_gameobject is freed after conversion */
00512 void KX_BlenderSceneConverter::UnregisterGameObject(
00513                                     KX_GameObject *gameobject) 
00514 {
00515     struct Object *bobp= gameobject->GetBlenderObject();
00516     if (bobp) {
00517         CHashedPtr bptr(bobp);
00518         KX_GameObject **gobp= m_map_blender_to_gameobject[bptr];
00519         if (gobp && *gobp == gameobject)
00520         {
00521             // also maintain m_map_blender_to_gameobject if the gameobject
00522             // being removed is matching the blender object
00523             m_map_blender_to_gameobject.remove(bptr);
00524         }
00525     }
00526 }
00527 
00528 KX_GameObject *KX_BlenderSceneConverter::FindGameObject(
00529                                     struct Object *for_blenderobject) 
00530 {
00531     KX_GameObject **obp= m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)];
00532     
00533     return obp?*obp:NULL;
00534 }
00535 
00536 void KX_BlenderSceneConverter::RegisterGameMesh(
00537                                     RAS_MeshObject *gamemesh,
00538                                     struct Mesh *for_blendermesh)
00539 {
00540     if(for_blendermesh) { /* dynamically loaded meshes we dont want to keep lookups for */
00541         m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh);
00542     }
00543     m_meshobjects.push_back(pair<KX_Scene*,RAS_MeshObject*>(m_currentScene,gamemesh));
00544 }
00545 
00546 
00547 
00548 RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(
00549                                     struct Mesh *for_blendermesh/*,
00550                                     unsigned int onlayer*/)
00551 {
00552     RAS_MeshObject** meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)];
00553     
00554     if (meshp/* && onlayer==(*meshp)->GetLightLayer()*/) {
00555         return *meshp;
00556     } else {
00557         return NULL;
00558     }
00559 }
00560 
00561     
00562 
00563 
00564     
00565 
00566 void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat)
00567 {
00568     m_polymaterials.push_back(pair<KX_Scene*,RAS_IPolyMaterial*>(m_currentScene,polymat));
00569 }
00570 
00571 
00572 
00573 void KX_BlenderSceneConverter::RegisterInterpolatorList(
00574                                     BL_InterpolatorList *actList,
00575                                     struct bAction *for_act)
00576 {
00577     m_map_blender_to_gameAdtList.insert(CHashedPtr(for_act), actList);
00578 }
00579 
00580 
00581 
00582 BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(
00583                                     struct bAction *for_act)
00584 {
00585     BL_InterpolatorList **listp = m_map_blender_to_gameAdtList[CHashedPtr(for_act)];
00586         
00587     return listp?*listp:NULL;
00588 }
00589 
00590 
00591 
00592 void KX_BlenderSceneConverter::RegisterGameActuator(
00593                                     SCA_IActuator *act,
00594                                     struct bActuator *for_actuator)
00595 {
00596     m_map_blender_to_gameactuator.insert(CHashedPtr(for_actuator), act);
00597 }
00598 
00599 
00600 
00601 SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(
00602                                     struct bActuator *for_actuator)
00603 {
00604     SCA_IActuator **actp = m_map_blender_to_gameactuator[CHashedPtr(for_actuator)];
00605     
00606     return actp?*actp:NULL;
00607 }
00608 
00609 
00610 
00611 void KX_BlenderSceneConverter::RegisterGameController(
00612                                     SCA_IController *cont,
00613                                     struct bController *for_controller)
00614 {
00615     m_map_blender_to_gamecontroller.insert(CHashedPtr(for_controller), cont);
00616 }
00617 
00618 
00619 
00620 SCA_IController *KX_BlenderSceneConverter::FindGameController(
00621                                     struct bController *for_controller)
00622 {
00623     SCA_IController **contp = m_map_blender_to_gamecontroller[CHashedPtr(for_controller)];
00624     
00625     return contp?*contp:NULL;
00626 }
00627 
00628 
00629 
00630 void KX_BlenderSceneConverter::RegisterWorldInfo(
00631                                     KX_WorldInfo *worldinfo)
00632 {
00633     m_worldinfos.push_back(pair<KX_Scene*,KX_WorldInfo*>(m_currentScene,worldinfo));
00634 }
00635 
00636 void    KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo)
00637 {
00638 
00639     KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
00640     int numScenes = scenes->size();
00641     int i;
00642     for (i=0;i<numScenes;i++)
00643     {
00644         KX_Scene* scene = scenes->at(i);
00645         //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
00646         CListValue* parentList = scene->GetRootParentList();
00647         int numObjects = parentList->GetCount();
00648         int g;
00649         for (g=0;g<numObjects;g++)
00650         {
00651             KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
00652             if (gameObj->IsDynamic())
00653             {
00654                 //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
00655                 
00656                 Object* blenderObject = gameObj->GetBlenderObject();
00657                 if (blenderObject)
00658                 {
00659 #if 0
00660                     //erase existing ipo's
00661                     Ipo* ipo = blenderObject->ipo;//findIpoForName(blenderObject->id.name+2);
00662                     if (ipo)
00663                     {   //clear the curve data
00664                         if (clearIpo){//rcruiz
00665                             IpoCurve *icu1;
00666                                                         
00667                             int numCurves = 0;
00668                             for( icu1 = (IpoCurve*)ipo->curve.first; icu1;  ) {
00669                             
00670                                 IpoCurve* tmpicu = icu1;
00671                                 
00672                                 /*int i;
00673                                 BezTriple *bezt;
00674                                 for( bezt = tmpicu->bezt, i = 0;    i < tmpicu->totvert; i++, bezt++){
00675                                     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]);
00676                                 }*/
00677                                 
00678                                 icu1 = icu1->next;
00679                                 numCurves++;
00680             
00681                                 BLI_remlink( &( blenderObject->ipo->curve ), tmpicu );
00682                                 if( tmpicu->bezt )
00683                                     MEM_freeN( tmpicu->bezt );
00684                                 MEM_freeN( tmpicu );
00685                                 localDel_ipoCurve( tmpicu );
00686                             }
00687                         }
00688                     } else
00689                     {   ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB);
00690                         blenderObject->ipo = ipo;
00691 
00692                     }
00693 #endif
00694                 }
00695             }
00696 
00697         }
00698         
00699     
00700     }
00701 
00702 
00703 
00704 }
00705 
00706 void    KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo()
00707 {
00708     if (addInitFromFrame){      
00709         KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
00710         int numScenes = scenes->size();
00711         if (numScenes>=0){
00712             KX_Scene* scene = scenes->at(0);
00713             CListValue* parentList = scene->GetRootParentList();
00714             for (int ix=0;ix<parentList->GetCount();ix++){
00715                 KX_GameObject* gameobj = (KX_GameObject*)parentList->GetValue(ix);
00716                 if (!gameobj->IsDynamic()){
00717                     Object* blenderobject = gameobj->GetBlenderObject();
00718                     if (!blenderobject)
00719                         continue;
00720                     if (blenderobject->type==OB_ARMATURE)
00721                         continue;
00722                     float eu[3];
00723                     mat4_to_eul(eu,blenderobject->obmat);                   
00724                     MT_Point3 pos = MT_Point3(
00725                         blenderobject->obmat[3][0],
00726                         blenderobject->obmat[3][1],
00727                         blenderobject->obmat[3][2]
00728                     );
00729                     MT_Vector3 eulxyz = MT_Vector3(
00730                         eu[0],
00731                         eu[1],
00732                         eu[2]
00733                     );
00734                     MT_Vector3 scale = MT_Vector3(
00735                         blenderobject->size[0],
00736                         blenderobject->size[1],
00737                         blenderobject->size[2]
00738                     );
00739                     gameobj->NodeSetLocalPosition(pos);
00740                     gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
00741                     gameobj->NodeSetLocalScale(scale);
00742                     gameobj->NodeUpdateGS(0);
00743                 }
00744             }
00745         }
00746     }
00747 }
00748 
00749 
00751 void    KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
00752 {
00753 
00754     KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
00755     int numScenes = scenes->size();
00756     int i;
00757     for (i=0;i<numScenes;i++)
00758     {
00759         KX_Scene* scene = scenes->at(i);
00760         //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
00761         CListValue* parentList = scene->GetObjectList();
00762         int numObjects = parentList->GetCount();
00763         int g;
00764         for (g=0;g<numObjects;g++)
00765         {
00766             KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
00767             Object* blenderObject = gameObj->GetBlenderObject();
00768             if (blenderObject && blenderObject->parent==NULL && gameObj->IsDynamic())
00769             {
00770                 //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
00771 
00772                 if(blenderObject->adt==NULL)
00773                     BKE_id_add_animdata(&blenderObject->id);
00774 
00775                 if (blenderObject->adt)
00776                 {
00777                     const MT_Point3& position = gameObj->NodeGetWorldPosition();
00778                     //const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
00779                     const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation();
00780 
00781                     position.getValue(blenderObject->loc);
00782 
00783                     float tmat[3][3];
00784                     for (int r=0;r<3;r++)
00785                         for (int c=0;c<3;c++)
00786                             tmat[r][c] = (float)orn[c][r];
00787 
00788                     mat3_to_compatible_eul(blenderObject->rot, blenderObject->rot, tmat);
00789 
00790                     insert_keyframe(NULL, &blenderObject->id, NULL, NULL, "location", -1, (float)frameNumber, INSERTKEY_FAST);
00791                     insert_keyframe(NULL, &blenderObject->id, NULL, NULL, "rotation_euler", -1, (float)frameNumber, INSERTKEY_FAST);
00792 
00793 #if 0
00794                     const MT_Point3& position = gameObj->NodeGetWorldPosition();
00795                     //const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
00796                     const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation();
00797                     
00798                     float eulerAngles[3];   
00799                     float eulerAnglesOld[3] = {0.0f, 0.0f, 0.0f};                       
00800                     float tmat[3][3];
00801                     
00802                     // XXX animato
00803                     Ipo* ipo = blenderObject->ipo;
00804 
00805                     //create the curves, if not existing, set linear if new
00806 
00807                     IpoCurve *icu_lx = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX");
00808                     if (!icu_lx) {
00809                         icu_lx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1);
00810                         if(icu_lx) icu_lx->ipo = IPO_LIN;
00811                     }
00812                     IpoCurve *icu_ly = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY");
00813                     if (!icu_ly) {
00814                         icu_ly = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1);
00815                         if(icu_ly) icu_ly->ipo = IPO_LIN;
00816                     }
00817                     IpoCurve *icu_lz = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ");
00818                     if (!icu_lz) {
00819                         icu_lz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1);
00820                         if(icu_lz) icu_lz->ipo = IPO_LIN;
00821                     }
00822                     IpoCurve *icu_rx = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX");
00823                     if (!icu_rx) {
00824                         icu_rx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1);
00825                         if(icu_rx) icu_rx->ipo = IPO_LIN;
00826                     }
00827                     IpoCurve *icu_ry = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY");
00828                     if (!icu_ry) {
00829                         icu_ry = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1);
00830                         if(icu_ry) icu_ry->ipo = IPO_LIN;
00831                     }
00832                     IpoCurve *icu_rz = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ");
00833                     if (!icu_rz) {
00834                         icu_rz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1);
00835                         if(icu_rz) icu_rz->ipo = IPO_LIN;
00836                     }
00837                     
00838                     if(icu_rx) eulerAnglesOld[0]= eval_icu( icu_rx, frameNumber - 1 ) / ((180 / 3.14159265f) / 10);
00839                     if(icu_ry) eulerAnglesOld[1]= eval_icu( icu_ry, frameNumber - 1 ) / ((180 / 3.14159265f) / 10);
00840                     if(icu_rz) eulerAnglesOld[2]= eval_icu( icu_rz, frameNumber - 1 ) / ((180 / 3.14159265f) / 10);
00841                     
00842                     // orn.getValue((float *)tmat); // uses the wrong ordering, cant use this
00843                     for (int r=0;r<3;r++)
00844                         for (int c=0;c<3;c++)
00845                             tmat[r][c] = orn[c][r];
00846                     
00847                     // mat3_to_eul( eulerAngles,tmat); // better to use Mat3ToCompatibleEul
00848                     mat3_to_compatible_eul( eulerAngles, eulerAnglesOld,tmat);
00849                     
00850                     //eval_icu
00851                     for(int x = 0; x < 3; x++)
00852                         eulerAngles[x] *= (float) ((180 / 3.14159265f) / 10.0);
00853                     
00854                     //fill the curves with data
00855                     if (icu_lx) insert_vert_icu(icu_lx, frameNumber, position.x(), 1);
00856                     if (icu_ly) insert_vert_icu(icu_ly, frameNumber, position.y(), 1);
00857                     if (icu_lz) insert_vert_icu(icu_lz, frameNumber, position.z(), 1);
00858                     if (icu_rx) insert_vert_icu(icu_rx, frameNumber, eulerAngles[0], 1);
00859                     if (icu_ry) insert_vert_icu(icu_ry, frameNumber, eulerAngles[1], 1);
00860                     if (icu_rz) insert_vert_icu(icu_rz, frameNumber, eulerAngles[2], 1);
00861                     
00862                     // Handles are corrected at the end, testhandles_ipocurve isnt needed yet
00863 #endif
00864                 }
00865             }
00866         }
00867     }
00868 }
00869 
00870 
00871 void    KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
00872 {
00873 
00874     KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
00875     int numScenes = scenes->size();
00876     int i;
00877     for (i=0;i<numScenes;i++)
00878     {
00879         KX_Scene* scene = scenes->at(i);
00880         //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
00881         CListValue* parentList = scene->GetRootParentList();
00882         int numObjects = parentList->GetCount();
00883         int g;
00884         for (g=0;g<numObjects;g++)
00885         {
00886             KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
00887             if (gameObj->IsDynamic())
00888             {
00889                 //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
00890                 
00891 #if 0
00892                 Object* blenderObject = gameObj->GetBlenderObject();
00893                 if (blenderObject && blenderObject->ipo)
00894                 {
00895                     // XXX animato
00896                     Ipo* ipo = blenderObject->ipo;
00897                     
00898                     //create the curves, if not existing
00899                     //testhandles_ipocurve checks for NULL
00900                     testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"));
00901                     testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"));
00902                     testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"));
00903                     testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"));
00904                     testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"));
00905                     testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"));
00906                 }
00907 #endif
00908             }
00909         }
00910     }
00911 }
00912 
00913 #ifdef WITH_PYTHON
00914 PyObject *KX_BlenderSceneConverter::GetPyNamespace()
00915 {
00916     return m_ketsjiEngine->GetPyNamespace();
00917 }
00918 #endif
00919 
00920 vector<Main*> &KX_BlenderSceneConverter::GetMainDynamic()
00921 {
00922     return m_DynamicMaggie;
00923 }
00924 
00925 Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path)
00926 {
00927     for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++)
00928         if(BLI_path_cmp((*it)->name, path) == 0)
00929             return *it;
00930     
00931     return NULL;
00932 }
00933 
00934 bool KX_BlenderSceneConverter::LinkBlendFileMemory(void *data, int length, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options)
00935 {
00936     BlendHandle *bpy_openlib = BLO_blendhandle_from_memory(data, length);
00937 
00938     // Error checking is done in LinkBlendFile
00939     return LinkBlendFile(bpy_openlib, path, group, scene_merge, err_str, options);
00940 }
00941 
00942 bool KX_BlenderSceneConverter::LinkBlendFilePath(const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options)
00943 {
00944     BlendHandle *bpy_openlib = BLO_blendhandle_from_file((char *)path, NULL);
00945 
00946     // Error checking is done in LinkBlendFile
00947     return LinkBlendFile(bpy_openlib, path, group, scene_merge, err_str, options);
00948 }
00949 
00950 bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options)
00951 {
00952     Main *main_newlib; /* stored as a dynamic 'main' until we free it */
00953     Main *main_tmp= NULL; /* created only for linking, then freed */
00954     LinkNode *names = NULL;
00955     int idcode= BKE_idcode_from_name(group);
00956     short flag= 0; /* dont need any special options */
00957     ReportList reports;
00958     static char err_local[255];
00959     
00960     /* only scene and mesh supported right now */
00961     if(idcode!=ID_SCE && idcode!=ID_ME &&idcode!=ID_AC) {
00962         snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group);
00963         *err_str= err_local;
00964         BLO_blendhandle_close(bpy_openlib);
00965         return false;
00966     }
00967     
00968     if(GetMainDynamicPath(path)) {
00969         snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path);
00970         *err_str= err_local;
00971         BLO_blendhandle_close(bpy_openlib);
00972         return false;
00973     }
00974 
00975     if(bpy_openlib==NULL) {
00976         snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path);
00977         *err_str= err_local;
00978         return false;
00979     }
00980     
00981     main_newlib= (Main *)MEM_callocN( sizeof(Main), "BgeMain");
00982     BKE_reports_init(&reports, RPT_STORE);  
00983 
00984     /* here appending/linking starts */
00985     main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path);
00986 
00987     int totnames_dummy;
00988     names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy);
00989     
00990     int i=0;
00991     LinkNode *n= names;
00992     while(n) {
00993         BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, idcode);
00994         n= (LinkNode *)n->next;
00995         i++;
00996     }
00997     BLI_linklist_free(names, free); /* free linklist *and* each node's data */
00998     
00999     BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag);
01000 
01001     /* now do another round of linking for Scenes so all actions are properly loaded */
01002     if (idcode==ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) {
01003         main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path);
01004 
01005         int totnames_dummy;
01006         names = BLO_blendhandle_get_datablock_names( bpy_openlib, ID_AC, &totnames_dummy);
01007     
01008         int i=0;
01009         LinkNode *n= names;
01010         while(n) {
01011             BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, ID_AC);
01012             n= (LinkNode *)n->next;
01013             i++;
01014         }
01015         BLI_linklist_free(names, free); /* free linklist *and* each node's data */
01016     
01017         BLO_library_append_end(NULL, main_tmp, &bpy_openlib, ID_AC, flag);
01018     }
01019     
01020     BLO_blendhandle_close(bpy_openlib);
01021 
01022     BKE_reports_clear(&reports);
01023     /* done linking */  
01024     
01025     /* needed for lookups*/
01026     GetMainDynamic().push_back(main_newlib);
01027     strncpy(main_newlib->name, path, sizeof(main_newlib->name));    
01028     
01029     
01030     if(idcode==ID_ME) {
01031         /* Convert all new meshes into BGE meshes */
01032         ID* mesh;
01033     
01034         for(mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) {
01035             if (options & LIB_LOAD_VERBOSE)
01036                 printf("MeshName: %s\n", mesh->name+2);
01037             RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this);
01038             scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
01039         }
01040     }
01041     else if(idcode==ID_AC) {
01042         /* Convert all actions */
01043         ID *action;
01044 
01045         for(action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) {
01046             if (options & LIB_LOAD_VERBOSE)
01047                 printf("ActionName: %s\n", action->name+2);
01048             scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action);
01049         }
01050     }
01051     else if(idcode==ID_SCE) {       
01052         /* Merge all new linked in scene into the existing one */
01053         ID *scene;
01054         for(scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) {
01055             if (options & LIB_LOAD_VERBOSE)
01056                 printf("SceneName: %s\n", scene->name+2);
01057             
01058             /* merge into the base  scene */
01059             KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene);
01060             scene_merge->MergeScene(other);
01061             
01062             // RemoveScene(other); // Dont run this, it frees the entire scene converter data, just delete the scene
01063             delete other;
01064         }
01065 
01066         /* Now handle all the actions */
01067         if (options & LIB_LOAD_LOAD_ACTIONS) {
01068             ID *action;
01069 
01070             for(action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) {
01071                 if (options & LIB_LOAD_VERBOSE)
01072                     printf("ActionName: %s\n", action->name+2);
01073                 scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action);
01074             }
01075         }
01076     }
01077     
01078     return true;
01079 }
01080 
01081 /* Note m_map_*** are all ok and dont need to be freed
01082  * most are temp and NewRemoveObject frees m_map_gameobject_to_blender */
01083 bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
01084 {
01085     int maggie_index= -1;
01086     int i=0;
01087 
01088     if(maggie==NULL)
01089         return false;
01090     
01091     /* tag all false except the one we remove */
01092     for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
01093         Main *main= *it;
01094         if(main != maggie) {
01095             tag_main(main, 0);
01096         }
01097         else {
01098             maggie_index= i;
01099         }
01100         i++;
01101     }
01102 
01103     /* should never happen but just to be safe */
01104     if(maggie_index == -1)
01105         return false;
01106 
01107     m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index);
01108     tag_main(maggie, 1);
01109 
01110 
01111     /* free all tagged objects */
01112     KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
01113     int numScenes = scenes->size();
01114 
01115 
01116     for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
01117     {
01118         KX_Scene* scene = scenes->at(scene_idx);
01119         if(IS_TAGGED(scene->GetBlenderScene())) {
01120             RemoveScene(scene); // XXX - not tested yet
01121             scene_idx--;
01122             numScenes--;
01123         }
01124         else {
01125             
01126             /* incase the mesh might be refered to later */
01127             {
01128                 CTR_Map<STR_HashedString,void*> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap();
01129                 
01130                 for(int i=0; i<mapStringToMeshes.size(); i++)
01131                 {
01132                     RAS_MeshObject *meshobj= (RAS_MeshObject *) *mapStringToMeshes.at(i);
01133                     if(meshobj && IS_TAGGED(meshobj->GetMesh()))
01134                     {   
01135                         STR_HashedString mn = meshobj->GetName();
01136                         mapStringToMeshes.remove(mn);
01137                         m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh()));
01138                         i--;
01139                     }
01140                 }
01141             }
01142 
01143             /* Now unregister actions */
01144             {
01145                 CTR_Map<STR_HashedString,void*> &mapStringToActions = scene->GetLogicManager()->GetActionMap();
01146 
01147                 for(int i=0; i<mapStringToActions.size(); i++)
01148                 {
01149                     ID *action= (ID*) *mapStringToActions.at(i);
01150 
01151                     if(IS_TAGGED(action))
01152                     {
01153                         STR_HashedString an = action->name+2;
01154                         mapStringToActions.remove(an);
01155                         i--;
01156                     }
01157                 }
01158             }
01159             
01160             //scene->FreeTagged(); /* removed tagged objects and meshes*/
01161             CListValue *obj_lists[] = {scene->GetObjectList(), scene->GetInactiveList(), NULL};
01162 
01163             for(int ob_ls_idx=0; obj_lists[ob_ls_idx]; ob_ls_idx++)
01164             {
01165                 CListValue *obs= obj_lists[ob_ls_idx];
01166                 RAS_MeshObject* mesh;
01167 
01168                 for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++)
01169                 {
01170                     KX_GameObject* gameobj = (KX_GameObject*)obs->GetValue(ob_idx);
01171                     if(IS_TAGGED(gameobj->GetBlenderObject())) {
01172 
01173                         int size_before = obs->GetCount();
01174 
01175                         /* Eventually calls RemoveNodeDestructObject
01176                          * frees m_map_gameobject_to_blender from UnregisterGameObject */
01177                         scene->RemoveObject(gameobj);
01178 
01179                         if(size_before != obs->GetCount())
01180                             ob_idx--;
01181                         else {
01182                             printf("ERROR COULD NOT REMOVE \"%s\"\n", gameobj->GetName().ReadPtr());
01183                         }
01184                     }
01185                     else {
01186                         /* free the mesh, we could be referecing a linked one! */
01187                         int mesh_index= gameobj->GetMeshCount();
01188                         while(mesh_index--) {
01189                             mesh= gameobj->GetMesh(mesh_index);
01190                             if(IS_TAGGED(mesh->GetMesh())) {
01191                                 gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */
01192                                 break;
01193                             }
01194                         }
01195 
01196                         /* make sure action actuators are not referencing tagged actions */
01197                         for (unsigned int act_idx=0; act_idx<gameobj->GetActuators().size(); act_idx++)
01198                         {
01199                             if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION))
01200                             {
01201                                 BL_ActionActuator *act = (BL_ActionActuator*)gameobj->GetActuators()[act_idx];
01202                                 if(IS_TAGGED(act->GetAction()))
01203                                     act->SetAction(NULL);
01204                             }
01205                         }
01206                     }
01207                 }
01208             }
01209         }
01210     }
01211 
01212 
01213     int size;
01214 
01215     // delete the entities of this scene
01216     /* TODO - */
01217     /*
01218     vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
01219     size = m_worldinfos.size();
01220     for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
01221         if ((*worldit).second) {
01222             delete (*worldit).second;
01223             *worldit = m_worldinfos.back();
01224             m_worldinfos.pop_back();
01225             size--;
01226         } else {
01227             i++;
01228             worldit++;
01229         }
01230     }*/
01231 
01232 
01233     /* Worlds dont reference original blender data so we need to make a set from them */
01234     typedef std::set<KX_WorldInfo*> KX_WorldInfoSet;
01235     KX_WorldInfoSet worldset;
01236     for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
01237     {
01238         KX_Scene* scene = scenes->at(scene_idx);
01239         if(scene->GetWorldInfo())
01240             worldset.insert( scene->GetWorldInfo() );
01241     }
01242 
01243     vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
01244     size = m_worldinfos.size();
01245     for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
01246         if ((*worldit).second && (worldset.count((*worldit).second)) == 0) {
01247             delete (*worldit).second;
01248             *worldit = m_worldinfos.back();
01249             m_worldinfos.pop_back();
01250             size--;
01251         } else {
01252             i++;
01253             worldit++;
01254         }
01255     }
01256     worldset.clear();
01257     /* done freeing the worlds */
01258 
01259 
01260 
01261 
01262     vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit;
01263     size = m_polymaterials.size();
01264 
01265 
01266 
01267     for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
01268         RAS_IPolyMaterial *mat= (*polymit).second;
01269         Material *bmat= NULL;
01270 
01271         /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
01272         if(mat->GetFlag() & RAS_BLENDERMAT) {
01273             KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
01274             bmat= bl_mat->GetBlenderMaterial();
01275 
01276         } else {
01277             KX_PolygonMaterial *kx_mat = static_cast<KX_PolygonMaterial*>(mat);
01278             bmat= kx_mat->GetBlenderMaterial();
01279         }
01280 
01281         if (IS_TAGGED(bmat)) {
01282             /* only remove from bucket */
01283             ((*polymit).first)->GetBucketManager()->RemoveMaterial(mat);
01284         }
01285 
01286         i++;
01287         polymit++;
01288     }
01289 
01290 
01291 
01292     for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
01293         RAS_IPolyMaterial *mat= (*polymit).second;
01294         Material *bmat= NULL;
01295 
01296         /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
01297         if(mat->GetFlag() & RAS_BLENDERMAT) {
01298             KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
01299             bmat= bl_mat->GetBlenderMaterial();
01300 
01301         } else {
01302             KX_PolygonMaterial *kx_mat = static_cast<KX_PolygonMaterial*>(mat);
01303             bmat= kx_mat->GetBlenderMaterial();
01304         }
01305 
01306         if(bmat) {
01307             //printf("FOUND MAT '%s' !!! ", ((ID*)bmat)->name+2);
01308         }
01309         else {
01310             //printf("LOST MAT  !!!");
01311         }
01312 
01313         if (IS_TAGGED(bmat)) {
01314 
01315             delete (*polymit).second;
01316             *polymit = m_polymaterials.back();
01317             m_polymaterials.pop_back();
01318             size--;
01319             //printf("tagged !\n");
01320         } else {
01321             i++;
01322             polymit++;
01323             //printf("(un)tagged !\n");
01324         }
01325     }
01326 
01327     vector<pair<KX_Scene*,BL_Material*> >::iterator matit;
01328     size = m_materials.size();
01329     for (i=0, matit=m_materials.begin(); i<size; ) {
01330         BL_Material *mat= (*matit).second;
01331         if (IS_TAGGED(mat->material)) {
01332             delete (*matit).second;
01333             *matit = m_materials.back();
01334             m_materials.pop_back();
01335             size--;
01336         } else {
01337             i++;
01338             matit++;
01339         }
01340     }
01341 
01342     vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
01343     size = m_meshobjects.size();
01344     for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
01345         RAS_MeshObject *me= (*meshit).second;
01346         if (IS_TAGGED(me->GetMesh())) {
01347             delete (*meshit).second;
01348             *meshit = m_meshobjects.back();
01349             m_meshobjects.pop_back();
01350             size--;
01351         } else {
01352             i++;
01353             meshit++;
01354         }
01355     }
01356 
01357     free_main(maggie);
01358 
01359     return true;
01360 }
01361 
01362 bool KX_BlenderSceneConverter::FreeBlendFile(const char *path)
01363 {
01364     return FreeBlendFile(GetMainDynamicPath(path));
01365 }
01366 
01367 bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from)
01368 {
01369 
01370     {
01371         vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itp = m_worldinfos.begin();
01372         while (itp != m_worldinfos.end()) {
01373             if ((*itp).first==from)
01374                 (*itp).first= to;
01375             itp++;
01376         }
01377     }
01378 
01379     {
01380         vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
01381         while (itp != m_polymaterials.end()) {
01382             if ((*itp).first==from) {
01383                 (*itp).first= to;
01384 
01385                 /* also switch internal data */
01386                 RAS_IPolyMaterial*mat= (*itp).second;
01387                 mat->Replace_IScene(to);
01388             }
01389             itp++;
01390         }
01391     }
01392 
01393     {
01394         vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itp = m_meshobjects.begin();
01395         while (itp != m_meshobjects.end()) {
01396             if ((*itp).first==from)
01397                 (*itp).first= to;
01398             itp++;
01399         }
01400     }
01401 
01402     {
01403         vector<pair<KX_Scene*,BL_Material*> >::iterator itp = m_materials.begin();
01404         while (itp != m_materials.end()) {
01405             if ((*itp).first==from)
01406                 (*itp).first= to;
01407             itp++;
01408         }
01409     }
01410     
01411     return true;
01412 }
01413 
01414 /* This function merges a mesh from the current scene into another main
01415  * it does not convert */
01416 RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, Main *maggie, const char *name)
01417 {
01418     /* Find a mesh in the current main */
01419     ID *me= static_cast<ID *>(BLI_findstring(&m_maggie->mesh, name, offsetof(ID, name) + 2));
01420     
01421     if(me==NULL) {
01422         printf("Could not be found \"%s\"\n", name);
01423         return NULL;
01424     }
01425     
01426     /* Watch this!, if its used in the original scene can cause big troubles */
01427     if(me->us > 0) {
01428         printf("Mesh has a user \"%s\"\n", name);
01429         me = (ID*)copy_mesh((Mesh*)me);
01430         me->us--;
01431     }
01432     BLI_remlink(&m_maggie->mesh, me); /* even if we made the copy it needs to be removed */
01433     BLI_addtail(&maggie->mesh, me);
01434 
01435     
01436     /* Must copy the materials this uses else we cant free them */
01437     {
01438         Mesh *mesh= (Mesh *)me;
01439         
01440         /* ensure all materials are tagged */
01441         for(int i=0; i<mesh->totcol; i++)
01442             if(mesh->mat[i])
01443                 mesh->mat[i]->id.flag &= ~LIB_DOIT;
01444         
01445         for(int i=0; i<mesh->totcol; i++)
01446         {
01447             Material *mat_old= mesh->mat[i];
01448             
01449             /* if its tagged its a replaced material */
01450             if(mat_old && (mat_old->id.flag & LIB_DOIT)==0)
01451             {
01452                 Material *mat_old= mesh->mat[i];
01453                 Material *mat_new= copy_material( mat_old );
01454                 
01455                 mat_new->id.flag |= LIB_DOIT;
01456                 mat_old->id.us--;
01457                 
01458                 BLI_remlink(&m_maggie->mat, mat_new);
01459                 BLI_addtail(&maggie->mat, mat_new);
01460                 
01461                 mesh->mat[i]= mat_new;
01462                 
01463                 /* the same material may be used twice */
01464                 for(int j=i+1; j<mesh->totcol; j++)
01465                 {
01466                     if(mesh->mat[j]==mat_old)
01467                     {
01468                         mesh->mat[j]= mat_new;
01469                         mat_new->id.us++;
01470                         mat_old->id.us--;
01471                     }
01472                 }
01473             }
01474         }
01475     }
01476     
01477     RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this);
01478     kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
01479     m_map_mesh_to_gamemesh.clear(); /* This is at runtime so no need to keep this, BL_ConvertMesh adds */
01480     return meshobj;
01481 }