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