diff options
Diffstat (limited to 'source/gameengine/Converter/KX_BlenderSceneConverter.cpp')
-rw-r--r-- | source/gameengine/Converter/KX_BlenderSceneConverter.cpp | 1477 |
1 files changed, 0 insertions, 1477 deletions
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp deleted file mode 100644 index 5d9f32a0969..00000000000 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ /dev/null @@ -1,1477 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file gameengine/Converter/KX_BlenderSceneConverter.cpp - * \ingroup bgeconv - */ - -#ifdef _MSC_VER -# pragma warning (disable:4786) /* suppress stl-MSVC debug info warning */ -#endif - -#include "KX_Scene.h" -#include "KX_GameObject.h" -#include "KX_IpoConvert.h" -#include "RAS_MeshObject.h" -#include "KX_PhysicsEngineEnums.h" -#include "PHY_IPhysicsEnvironment.h" -#include "KX_KetsjiEngine.h" -#include "KX_PythonInit.h" // So we can handle adding new text datablocks for Python to import -#include "BL_Material.h" -#include "BL_ActionActuator.h" -#include "KX_BlenderMaterial.h" - - -#include "BL_System.h" - -#include "DummyPhysicsEnvironment.h" - - -#ifdef WITH_BULLET -#include "CcdPhysicsEnvironment.h" -#endif - -#include "KX_LibLoadStatus.h" -#include "KX_BlenderScalarInterpolator.h" -#include "BL_BlenderDataConversion.h" -#include "KX_WorldInfo.h" - -/* This little block needed for linking to Blender... */ -#ifdef WIN32 -#include "BLI_winstuff.h" -#endif - -/* This list includes only data type definitions */ -#include "DNA_scene_types.h" -#include "DNA_world_types.h" -#include "BKE_main.h" -#include "BKE_fcurve.h" - -#include "BLI_math.h" - -extern "C" -{ -#include "DNA_object_types.h" -#include "DNA_curve_types.h" -#include "DNA_mesh_types.h" -#include "DNA_material_types.h" -#include "BLI_blenlib.h" -#include "MEM_guardedalloc.h" -#include "BKE_global.h" -#include "BKE_animsys.h" -#include "BKE_library.h" -#include "BKE_material.h" // BKE_material_copy -#include "BKE_mesh.h" // BKE_mesh_copy -#include "DNA_space_types.h" -#include "DNA_anim_types.h" -#include "DNA_action_types.h" -#include "RNA_define.h" -#include "../../blender/editors/include/ED_keyframing.h" -} - -/* Only for dynamic loading and merging */ -#include "RAS_BucketManager.h" // XXX cant stay -#include "KX_BlenderSceneConverter.h" -#include "KX_MeshProxy.h" -extern "C" { - #include "PIL_time.h" - #include "BKE_context.h" - #include "BLO_readfile.h" - #include "BKE_idcode.h" - #include "BKE_report.h" - #include "DNA_space_types.h" - #include "DNA_windowmanager_types.h" /* report api */ - #include "../../blender/blenlib/BLI_linklist.h" -} - -#include "BLI_task.h" - -// This is used to avoid including BLI_task.h in KX_BlenderSceneConverter.h -typedef struct ThreadInfo { - TaskPool *m_pool; - ThreadMutex m_mutex; -} ThreadInfo; - -KX_BlenderSceneConverter::KX_BlenderSceneConverter( - Main *maggie, - KX_KetsjiEngine *engine) - :m_maggie(maggie), - m_ketsjiEngine(engine), - m_alwaysUseExpandFraming(false), - m_usemat(false), - m_useglslmat(false), - m_use_mat_cache(true) -{ - BKE_main_id_tag_all(maggie, LIB_TAG_DOIT, false); /* avoid re-tagging later on */ - m_newfilename = ""; - m_threadinfo = new ThreadInfo(); - m_threadinfo->m_pool = BLI_task_pool_create(engine->GetTaskScheduler(), NULL); - BLI_mutex_init(&m_threadinfo->m_mutex); -} - -KX_BlenderSceneConverter::~KX_BlenderSceneConverter() -{ - // clears meshes, and hashmaps from blender to gameengine data - // delete sumoshapes - - int numAdtLists = m_map_blender_to_gameAdtList.size(); - for (int i = 0; i < numAdtLists; i++) { - BL_InterpolatorList *adtList = *m_map_blender_to_gameAdtList.at(i); - - delete (adtList); - } - - vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator itw = m_worldinfos.begin(); - while (itw != m_worldinfos.end()) { - delete itw->second; - itw++; - } - m_worldinfos.clear(); - - vector<pair<KX_Scene *,RAS_IPolyMaterial *> >::iterator itp = m_polymaterials.begin(); - while (itp != m_polymaterials.end()) { - delete itp->second; - itp++; - } - m_polymaterials.clear(); - - // delete after RAS_IPolyMaterial - vector<pair<KX_Scene *,BL_Material *> >::iterator itmat = m_materials.begin(); - while (itmat != m_materials.end()) { - delete itmat->second; - itmat++; - } - m_materials.clear(); - - vector<pair<KX_Scene *,RAS_MeshObject *> >::iterator itm = m_meshobjects.begin(); - while (itm != m_meshobjects.end()) { - delete itm->second; - itm++; - } - m_meshobjects.clear(); - - /* free any data that was dynamically loaded */ - while (m_DynamicMaggie.size() != 0) { - FreeBlendFile(m_DynamicMaggie[0]); - } - - m_DynamicMaggie.clear(); - - if (m_threadinfo) { - /* Thread infos like mutex must be freed after FreeBlendFile function. - Because it needs to lock the mutex, even if there's no active task when it's - in the scene converter destructor. */ - BLI_task_pool_free(m_threadinfo->m_pool); - BLI_mutex_end(&m_threadinfo->m_mutex); - delete m_threadinfo; - } -} - -void KX_BlenderSceneConverter::SetNewFileName(const STR_String &filename) -{ - m_newfilename = filename; -} - -bool KX_BlenderSceneConverter::TryAndLoadNewFile() -{ - bool result = false; - - return result; -} - -Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String &name) -{ - Scene *sce; - - /** - * Find the specified scene by name, or NULL if nothing matches. - */ - if ((sce = (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2))) - return sce; - - for (vector<Main *>::iterator it=m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) { - Main *main = *it; - - if ((sce= (Scene *)BLI_findstring(&main->scene, name.ReadPtr(), offsetof(ID, name) + 2))) - return sce; - } - - return NULL; -} - -void KX_BlenderSceneConverter::ConvertScene(KX_Scene *destinationscene, RAS_IRasterizer *rendertools, - RAS_ICanvas *canvas, bool libloading) -{ - //find out which physics engine - Scene *blenderscene = destinationscene->GetBlenderScene(); - - PHY_IPhysicsEnvironment *phy_env = NULL; - - e_PhysicsEngine physics_engine = UseBullet; - // hook for registration function during conversion. - m_currentScene = destinationscene; - destinationscene->SetSceneConverter(this); - - // This doesn't really seem to do anything except cause potential issues - // when doing threaded conversion, so it's disabled for now. - // SG_SetActiveStage(SG_STAGE_CONVERTER); - - switch (blenderscene->gm.physicsEngine) { -#ifdef WITH_BULLET - case WOPHY_BULLET: - { - SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/ - int visualizePhysics = SYS_GetCommandLineInt(syshandle, "show_physics", 0); - - phy_env = CcdPhysicsEnvironment::Create(blenderscene, visualizePhysics); - physics_engine = UseBullet; - break; - } -#endif - default: - case WOPHY_NONE: - { - // We should probably use some sort of factory here - phy_env = new DummyPhysicsEnvironment(); - physics_engine = UseNone; - break; - } - } - - destinationscene->SetPhysicsEnvironment(phy_env); - - BL_ConvertBlenderObjects( - m_maggie, - destinationscene, - m_ketsjiEngine, - physics_engine, - rendertools, - canvas, - this, - m_alwaysUseExpandFraming, - libloading); - - //These lookup are not needed during game - m_map_blender_to_gameactuator.clear(); - m_map_blender_to_gamecontroller.clear(); - m_map_blender_to_gameobject.clear(); - - //Clearing this lookup table has the effect of disabling the cache of meshes - //between scenes, even if they are shared in the blend file. - //This cache mecanism is buggy so I leave it disable and the memory leak - //that would result from this is fixed in RemoveScene() - m_map_mesh_to_gamemesh.clear(); -} - -// This function removes all entities stored in the converter for that scene -// It should be used instead of direct delete scene -// Note that there was some provision for sharing entities (meshes...) between -// scenes but that is now disabled so all scene will have their own copy -// and we can delete them here. If the sharing is reactivated, change this code too.. -// (see KX_BlenderSceneConverter::ConvertScene) -void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) -{ - int i, size; - // delete the scene first as it will stop the use of entities - delete scene; - // delete the entities of this scene - vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator worldit; - size = m_worldinfos.size(); - for (i = 0, worldit = m_worldinfos.begin(); i < size; ) { - if (worldit->first == scene) { - delete worldit->second; - *worldit = m_worldinfos.back(); - m_worldinfos.pop_back(); - size--; - } - else { - i++; - worldit++; - } - } - - vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator polymit; - size = m_polymaterials.size(); - for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { - if (polymit->first == scene) { - m_polymat_cache[scene].erase(polymit->second->GetBlenderMaterial()); - delete polymit->second; - *polymit = m_polymaterials.back(); - m_polymaterials.pop_back(); - size--; - } - else { - i++; - polymit++; - } - } - - m_polymat_cache.erase(scene); - - vector<pair<KX_Scene *, BL_Material *> >::iterator matit; - size = m_materials.size(); - for (i = 0, matit = m_materials.begin(); i < size; ) { - if (matit->first == scene) { - m_mat_cache[scene].erase(matit->second->material); - delete matit->second; - *matit = m_materials.back(); - m_materials.pop_back(); - size--; - } - else { - i++; - matit++; - } - } - - m_mat_cache.erase(scene); - - vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator meshit; - size = m_meshobjects.size(); - for (i = 0, meshit = m_meshobjects.begin(); i < size; ) { - if (meshit->first == scene) { - delete meshit->second; - *meshit = m_meshobjects.back(); - m_meshobjects.pop_back(); - size--; - } - else { - i++; - meshit++; - } - } -} - -// use blender materials -void KX_BlenderSceneConverter::SetMaterials(bool val) -{ - m_usemat = val; - m_useglslmat = false; -} - -void KX_BlenderSceneConverter::SetGLSLMaterials(bool val) -{ - m_usemat = val; - m_useglslmat = val; -} - -void KX_BlenderSceneConverter::SetCacheMaterials(bool val) -{ - m_use_mat_cache = val; -} - -bool KX_BlenderSceneConverter::GetMaterials() -{ - return m_usemat; -} - -bool KX_BlenderSceneConverter::GetGLSLMaterials() -{ - return m_useglslmat; -} - -bool KX_BlenderSceneConverter::GetCacheMaterials() -{ - return m_use_mat_cache; -} - -void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat) -{ - // First make sure we don't register the material twice - vector<pair<KX_Scene *, BL_Material *> >::iterator it; - for (it = m_materials.begin(); it != m_materials.end(); ++it) - if (it->second == mat) - return; - - m_materials.push_back(pair<KX_Scene *, BL_Material *> (m_currentScene, mat)); -} - -void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(bool to_what) -{ - m_alwaysUseExpandFraming= to_what; -} - -void KX_BlenderSceneConverter::RegisterGameObject(KX_GameObject *gameobject, Object *for_blenderobject) -{ - /* only maintained while converting, freed during game runtime */ - m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject), gameobject); -} - -/* only need to run this during conversion since - * m_map_blender_to_gameobject is freed after conversion */ -void KX_BlenderSceneConverter::UnregisterGameObject(KX_GameObject *gameobject) -{ - Object *bobp = gameobject->GetBlenderObject(); - if (bobp) { - CHashedPtr bptr(bobp); - KX_GameObject **gobp = m_map_blender_to_gameobject[bptr]; - if (gobp && *gobp == gameobject) { - // also maintain m_map_blender_to_gameobject if the gameobject - // being removed is matching the blender object - m_map_blender_to_gameobject.remove(bptr); - } - } -} - -KX_GameObject *KX_BlenderSceneConverter::FindGameObject(Object *for_blenderobject) -{ - KX_GameObject **obp = m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)]; - - return obp ? *obp : NULL; -} - -void KX_BlenderSceneConverter::RegisterGameMesh(RAS_MeshObject *gamemesh, Mesh *for_blendermesh) -{ - if (for_blendermesh) { /* dynamically loaded meshes we don't want to keep lookups for */ - m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh); - } - m_meshobjects.push_back(pair<KX_Scene *, RAS_MeshObject *> (m_currentScene,gamemesh)); -} - -RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(Mesh *for_blendermesh) -{ - RAS_MeshObject **meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)]; - - if (meshp) { - return *meshp; - } - else { - return NULL; - } -} - -void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat) -{ - // First make sure we don't register the material twice - vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator it; - for (it = m_polymaterials.begin(); it != m_polymaterials.end(); ++it) - if (it->second == polymat) - return; - m_polymaterials.push_back(pair<KX_Scene *, RAS_IPolyMaterial *> (m_currentScene, polymat)); -} - -void KX_BlenderSceneConverter::CachePolyMaterial(KX_Scene *scene, Material *mat, RAS_IPolyMaterial *polymat) -{ - if (m_use_mat_cache && mat) - m_polymat_cache[scene][mat] = polymat; -} - -RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(KX_Scene *scene, Material *mat) -{ - return (m_use_mat_cache) ? m_polymat_cache[scene][mat] : NULL; -} - -void KX_BlenderSceneConverter::CacheBlenderMaterial(KX_Scene *scene, Material *mat, BL_Material *blmat) -{ - if (m_use_mat_cache && mat) - m_mat_cache[scene][mat] = blmat; -} - -BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(KX_Scene *scene, Material *mat) -{ - return (m_use_mat_cache) ? m_mat_cache[scene][mat] : NULL; -} - -void KX_BlenderSceneConverter::RegisterInterpolatorList(BL_InterpolatorList *actList, bAction *for_act) -{ - m_map_blender_to_gameAdtList.insert(CHashedPtr(for_act), actList); -} - -BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(bAction *for_act) -{ - BL_InterpolatorList **listp = m_map_blender_to_gameAdtList[CHashedPtr(for_act)]; - return listp ? *listp : NULL; -} - -void KX_BlenderSceneConverter::RegisterGameActuator(SCA_IActuator *act, bActuator *for_actuator) -{ - m_map_blender_to_gameactuator.insert(CHashedPtr(for_actuator), act); -} - -SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(bActuator *for_actuator) -{ - SCA_IActuator **actp = m_map_blender_to_gameactuator[CHashedPtr(for_actuator)]; - return actp ? *actp : NULL; -} - -void KX_BlenderSceneConverter::RegisterGameController(SCA_IController *cont, bController *for_controller) -{ - m_map_blender_to_gamecontroller.insert(CHashedPtr(for_controller), cont); -} - -SCA_IController *KX_BlenderSceneConverter::FindGameController(bController *for_controller) -{ - SCA_IController **contp = m_map_blender_to_gamecontroller[CHashedPtr(for_controller)]; - return contp ? *contp : NULL; -} - -void KX_BlenderSceneConverter::RegisterWorldInfo(KX_WorldInfo *worldinfo) -{ - m_worldinfos.push_back(pair<KX_Scene *, KX_WorldInfo *> (m_currentScene, worldinfo)); -} - -void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) -{ - //TODO this entire function is deprecated, written for 2.4x - //the functionality should be rewritten, currently it does nothing - - KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); - int numScenes = scenes->size(); - int i; - for (i = 0; i < numScenes; i++) { - KX_Scene *scene = scenes->at(i); - CListValue *parentList = scene->GetRootParentList(); - int numObjects = parentList->GetCount(); - int g; - for (g = 0; g < numObjects; g++) { - KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); - if (gameObj->IsRecordAnimation()) { - Object *blenderObject = gameObj->GetBlenderObject(); - if (blenderObject) { -#if 0 - //erase existing ipo's - Ipo* ipo = blenderObject->ipo;//findIpoForName(blenderObject->id.name+2); - if (ipo) { //clear the curve data - if (clearIpo) {//rcruiz - IpoCurve *icu1; - - int numCurves = 0; - for ( icu1 = (IpoCurve*)ipo->curve.first; icu1; ) { - - IpoCurve* tmpicu = icu1; - - /*int i; - BezTriple *bezt; - for ( bezt = tmpicu->bezt, i = 0; i < tmpicu->totvert; i++, bezt++) { - 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]); - }*/ - - icu1 = icu1->next; - numCurves++; - - BLI_remlink( &( blenderObject->ipo->curve ), tmpicu ); - if ( tmpicu->bezt ) - MEM_freeN( tmpicu->bezt ); - MEM_freeN( tmpicu ); - localDel_ipoCurve( tmpicu ); - } - } - } - else { - ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB); - blenderObject->ipo = ipo; - } -#endif - } - } - } - } -} - -void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo() -{ - //TODO the functionality should be rewritten -} - -// this generates ipo curves for position, rotation, allowing to use game physics in animation -void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) -{ - KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); - int numScenes = scenes->size(); - int i; - for (i = 0; i < numScenes; i++) { - KX_Scene *scene = scenes->at(i); - //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue *parentList = scene->GetObjectList(); - int numObjects = parentList->GetCount(); - int g; - for (g = 0; g < numObjects; g++) { - KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); - Object *blenderObject = gameObj->GetBlenderObject(); - if (blenderObject && blenderObject->parent == NULL && gameObj->IsRecordAnimation()) { - if (blenderObject->adt == NULL) - BKE_animdata_add_id(&blenderObject->id); - - if (blenderObject->adt) { - const MT_Point3 &position = gameObj->NodeGetWorldPosition(); - //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); - const MT_Matrix3x3 &orn = gameObj->NodeGetWorldOrientation(); - - position.getValue(blenderObject->loc); - - float tmat[3][3]; - for (int r = 0; r < 3; r++) - for (int c = 0; c < 3; c++) - tmat[r][c] = (float)orn[c][r]; - - mat3_to_compatible_eul(blenderObject->rot, blenderObject->rot, tmat); - - insert_keyframe(G.main, NULL, &blenderObject->id, NULL, NULL, "location", -1, (float)frameNumber, BEZT_KEYTYPE_JITTER, INSERTKEY_FAST); - insert_keyframe(G.main, NULL, &blenderObject->id, NULL, NULL, "rotation_euler", -1, (float)frameNumber, BEZT_KEYTYPE_JITTER, INSERTKEY_FAST); - -#if 0 - const MT_Point3& position = gameObj->NodeGetWorldPosition(); - //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); - const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation(); - - float eulerAngles[3]; - float eulerAnglesOld[3] = {0.0f, 0.0f, 0.0f}; - float tmat[3][3]; - - // XXX animato - Ipo* ipo = blenderObject->ipo; - - //create the curves, if not existing, set linear if new - - IpoCurve *icu_lx = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); - if (!icu_lx) { - icu_lx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1); - if (icu_lx) icu_lx->ipo = IPO_LIN; - } - IpoCurve *icu_ly = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); - if (!icu_ly) { - icu_ly = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1); - if (icu_ly) icu_ly->ipo = IPO_LIN; - } - IpoCurve *icu_lz = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); - if (!icu_lz) { - icu_lz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1); - if (icu_lz) icu_lz->ipo = IPO_LIN; - } - IpoCurve *icu_rx = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); - if (!icu_rx) { - icu_rx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1); - if (icu_rx) icu_rx->ipo = IPO_LIN; - } - IpoCurve *icu_ry = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); - if (!icu_ry) { - icu_ry = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1); - if (icu_ry) icu_ry->ipo = IPO_LIN; - } - IpoCurve *icu_rz = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); - if (!icu_rz) { - icu_rz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1); - if (icu_rz) icu_rz->ipo = IPO_LIN; - } - - if (icu_rx) eulerAnglesOld[0] = eval_icu( icu_rx, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); - if (icu_ry) eulerAnglesOld[1] = eval_icu( icu_ry, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); - if (icu_rz) eulerAnglesOld[2] = eval_icu( icu_rz, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); - - // orn.getValue((float *)tmat); // uses the wrong ordering, cant use this - for (int r = 0; r < 3; r++) - for (int c = 0; c < 3; c++) - tmat[r][c] = orn[c][r]; - - // mat3_to_eul( eulerAngles,tmat); // better to use Mat3ToCompatibleEul - mat3_to_compatible_eul( eulerAngles, eulerAnglesOld,tmat); - - //eval_icu - for (int x = 0; x < 3; x++) - eulerAngles[x] *= (float) ((180 / 3.14159265f) / 10.0); - - //fill the curves with data - if (icu_lx) insert_vert_icu(icu_lx, frameNumber, position.x(), 1); - if (icu_ly) insert_vert_icu(icu_ly, frameNumber, position.y(), 1); - if (icu_lz) insert_vert_icu(icu_lz, frameNumber, position.z(), 1); - if (icu_rx) insert_vert_icu(icu_rx, frameNumber, eulerAngles[0], 1); - if (icu_ry) insert_vert_icu(icu_ry, frameNumber, eulerAngles[1], 1); - if (icu_rz) insert_vert_icu(icu_rz, frameNumber, eulerAngles[2], 1); - - // Handles are corrected at the end, testhandles_ipocurve isn't needed yet -#endif - } - } - } - } -} - -void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() -{ - KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); - int numScenes = scenes->size(); - int i; - for (i = 0; i < numScenes; i++) { - KX_Scene *scene = scenes->at(i); - //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue *parentList = scene->GetRootParentList(); - int numObjects = parentList->GetCount(); - int g; - for (g = 0; g < numObjects; g++) { - KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); - if (gameObj->IsRecordAnimation()) { - Object *blenderObject = gameObj->GetBlenderObject(); - if (blenderObject && blenderObject->adt) { - bAction *act = verify_adt_action(G.main, &blenderObject->id, false); - FCurve *fcu; - - if (!act) { - continue; - } - - /* for now, not much choice but to run this on all curves... */ - for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) { - /* Note: calling `sort_time_fcurve()` here is not needed, since - * all keys have been added in 'right' order. */ - calchandles_fcurve(fcu); - } -#if 0 - // XXX animato - Ipo* ipo = blenderObject->ipo; - - //create the curves, if not existing - //testhandles_ipocurve checks for NULL - testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocX")); - testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocY")); - testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ")); - testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotX")); - testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotY")); - testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ")); -#endif - } - } - } - } -} - -#ifdef WITH_PYTHON -PyObject *KX_BlenderSceneConverter::GetPyNamespace() -{ - return m_ketsjiEngine->GetPyNamespace(); -} -#endif - -vector<Main *> &KX_BlenderSceneConverter::GetMainDynamic() -{ - return m_DynamicMaggie; -} - -Main *KX_BlenderSceneConverter::GetMainDynamicPath(const char *path) -{ - for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) - if (BLI_path_cmp((*it)->name, path) == 0) - return *it; - - return NULL; -} - -void KX_BlenderSceneConverter::MergeAsyncLoads() -{ - vector<KX_Scene *> *merge_scenes; - - vector<KX_LibLoadStatus *>::iterator mit; - vector<KX_Scene *>::iterator sit; - - BLI_mutex_lock(&m_threadinfo->m_mutex); - - for (mit = m_mergequeue.begin(); mit != m_mergequeue.end(); ++mit) { - merge_scenes = (vector<KX_Scene *> *)(*mit)->GetData(); - - for (sit=merge_scenes->begin(); sit!=merge_scenes->end(); ++sit) { - (*mit)->GetMergeScene()->MergeScene(*sit); - delete (*sit); - } - - delete merge_scenes; - (*mit)->SetData(NULL); - - (*mit)->Finish(); - } - - m_mergequeue.clear(); - - BLI_mutex_unlock(&m_threadinfo->m_mutex); -} - -void KX_BlenderSceneConverter::FinalizeAsyncLoads() -{ - // Finish all loading libraries. - if (m_threadinfo) { - BLI_task_pool_work_and_wait(m_threadinfo->m_pool); - } - // Merge all libraries data in the current scene, to avoid memory leak of unmerged scenes. - MergeAsyncLoads(); -} - -void KX_BlenderSceneConverter::AddScenesToMergeQueue(KX_LibLoadStatus *status) -{ - BLI_mutex_lock(&m_threadinfo->m_mutex); - m_mergequeue.push_back(status); - BLI_mutex_unlock(&m_threadinfo->m_mutex); -} - -static void async_convert(TaskPool *pool, void *ptr, int UNUSED(threadid)) -{ - KX_Scene *new_scene = NULL; - KX_LibLoadStatus *status = (KX_LibLoadStatus *)ptr; - vector<Scene *> *scenes = (vector<Scene *> *)status->GetData(); - vector<KX_Scene *> *merge_scenes = new vector<KX_Scene *>(); // Deleted in MergeAsyncLoads - - for (unsigned int i = 0; i < scenes->size(); ++i) { - new_scene = status->GetEngine()->CreateScene((*scenes)[i], true); - - if (new_scene) - merge_scenes->push_back(new_scene); - - status->AddProgress((1.0f / scenes->size()) * 0.9f); // We'll call conversion 90% and merging 10% for now - } - - delete scenes; - status->SetData(merge_scenes); - - status->GetConverter()->AddScenesToMergeQueue(status); -} - -KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFileMemory(void *data, int length, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) -{ - BlendHandle *bpy_openlib = BLO_blendhandle_from_memory(data, length); - - // Error checking is done in LinkBlendFile - return LinkBlendFile(bpy_openlib, path, group, scene_merge, err_str, options); -} - -KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFilePath(const char *filepath, char *group, KX_Scene *scene_merge, char **err_str, short options) -{ - BlendHandle *bpy_openlib = BLO_blendhandle_from_file(filepath, NULL); - - // Error checking is done in LinkBlendFile - return LinkBlendFile(bpy_openlib, filepath, group, scene_merge, err_str, options); -} - -static void load_datablocks(Main *main_tmp, BlendHandle *bpy_openlib, const char *path, int idcode) -{ - LinkNode *names = NULL; - - int totnames_dummy; - names = BLO_blendhandle_get_datablock_names(bpy_openlib, idcode, &totnames_dummy); - - int i = 0; - LinkNode *n = names; - while (n) { - BLO_library_link_named_part(main_tmp, &bpy_openlib, idcode, (char *)n->link); - n = (LinkNode *)n->next; - i++; - } - BLI_linklist_free(names, free); /* free linklist *and* each node's data */ -} - -KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) -{ - Main *main_newlib; /* stored as a dynamic 'main' until we free it */ - const int idcode = BKE_idcode_from_name(group); - ReportList reports; - static char err_local[255]; - -// TIMEIT_START(bge_link_blend_file); - - KX_LibLoadStatus *status; - - /* only scene and mesh supported right now */ - if (idcode != ID_SCE && idcode != ID_ME && idcode != ID_AC) { - snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group); - *err_str = err_local; - BLO_blendhandle_close(bpy_openlib); - return NULL; - } - - if (GetMainDynamicPath(path)) { - snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path); - *err_str = err_local; - BLO_blendhandle_close(bpy_openlib); - return NULL; - } - - if (bpy_openlib == NULL) { - snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path); - *err_str = err_local; - return NULL; - } - - main_newlib = BKE_main_new(); - BKE_reports_init(&reports, RPT_STORE); - - short flag = 0; /* don't need any special options */ - /* created only for linking, then freed */ - Main *main_tmp = BLO_library_link_begin(main_newlib, &bpy_openlib, (char *)path); - - load_datablocks(main_tmp, bpy_openlib, path, idcode); - - if (idcode == ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) { - load_datablocks(main_tmp, bpy_openlib, path, ID_TXT); - } - - /* now do another round of linking for Scenes so all actions are properly loaded */ - if (idcode == ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { - load_datablocks(main_tmp, bpy_openlib, path, ID_AC); - } - - BLO_library_link_end(main_tmp, &bpy_openlib, flag, NULL, NULL); - - BLO_blendhandle_close(bpy_openlib); - - BKE_reports_clear(&reports); - /* done linking */ - - /* needed for lookups*/ - GetMainDynamic().push_back(main_newlib); - BLI_strncpy(main_newlib->name, path, sizeof(main_newlib->name)); - - - status = new KX_LibLoadStatus(this, m_ketsjiEngine, scene_merge, path); - - if (idcode == ID_ME) { - /* Convert all new meshes into BGE meshes */ - ID *mesh; - - for (mesh = (ID *)main_newlib->mesh.first; mesh; mesh = (ID *)mesh->next ) { - if (options & LIB_LOAD_VERBOSE) - printf("MeshName: %s\n", mesh->name + 2); - RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this, false); // For now only use the libloading option for scenes, which need to handle materials/shaders - scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj); - } - } - else if (idcode == ID_AC) { - /* Convert all actions */ - ID *action; - - for (action= (ID *)main_newlib->action.first; action; action = (ID *)action->next) { - if (options & LIB_LOAD_VERBOSE) - printf("ActionName: %s\n", action->name + 2); - scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); - } - } - else if (idcode == ID_SCE) { - /* Merge all new linked in scene into the existing one */ - ID *scene; - // scenes gets deleted by the thread when it's done using it (look in async_convert()) - vector<Scene *> *scenes = (options & LIB_LOAD_ASYNC) ? new vector<Scene *>() : NULL; - - for (scene = (ID *)main_newlib->scene.first; scene; scene = (ID *)scene->next ) { - if (options & LIB_LOAD_VERBOSE) - printf("SceneName: %s\n", scene->name + 2); - - if (options & LIB_LOAD_ASYNC) { - scenes->push_back((Scene *)scene); - } - else { - /* merge into the base scene */ - KX_Scene* other = m_ketsjiEngine->CreateScene((Scene *)scene, true); - scene_merge->MergeScene(other); - - // RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene - delete other; - } - } - - if (options & LIB_LOAD_ASYNC) { - status->SetData(scenes); - BLI_task_pool_push(m_threadinfo->m_pool, async_convert, (void *)status, false, TASK_PRIORITY_LOW); - } - -#ifdef WITH_PYTHON - /* Handle any text datablocks */ - if (options & LIB_LOAD_LOAD_SCRIPTS) - addImportMain(main_newlib); -#endif - - /* Now handle all the actions */ - if (options & LIB_LOAD_LOAD_ACTIONS) { - ID *action; - - for (action = (ID *)main_newlib->action.first; action; action = (ID *)action->next) { - if (options & LIB_LOAD_VERBOSE) - printf("ActionName: %s\n", action->name + 2); - scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); - } - } - } - - if (!(options & LIB_LOAD_ASYNC)) - status->Finish(); - -// TIMEIT_END(bge_link_blend_file); - - m_status_map[main_newlib->name] = status; - return status; -} - -/* Note m_map_*** are all ok and don't need to be freed - * most are temp and NewRemoveObject frees m_map_gameobject_to_blender */ -bool KX_BlenderSceneConverter::FreeBlendFile(Main *maggie) -{ - int maggie_index = -1; - int i = 0; - - if (maggie == NULL) - return false; - - // If the given library is currently in loading, we do nothing. - if (m_status_map.count(maggie->name)) { - BLI_mutex_lock(&m_threadinfo->m_mutex); - const bool finished = m_status_map[maggie->name]->IsFinished(); - BLI_mutex_unlock(&m_threadinfo->m_mutex); - - if (!finished) { - printf("Library (%s) is currently being loaded asynchronously, and cannot be freed until this process is done\n", maggie->name); - return false; - } - } - - /* tag all false except the one we remove */ - for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) { - Main *main = *it; - if (main != maggie) { - BKE_main_id_tag_all(main, LIB_TAG_DOIT, false); - } - else { - maggie_index = i; - } - i++; - } - - /* should never happen but just to be safe */ - if (maggie_index == -1) - return false; - - m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index); - BKE_main_id_tag_all(maggie, LIB_TAG_DOIT, true); - - /* free all tagged objects */ - KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); - int numScenes = scenes->size(); - - for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) { - KX_Scene *scene = scenes->at(scene_idx); - if (IS_TAGGED(scene->GetBlenderScene())) { - m_ketsjiEngine->RemoveScene(scene->GetName()); - m_mat_cache.erase(scene); - m_polymat_cache.erase(scene); - scene_idx--; - numScenes--; - } - else { - /* in case the mesh might be refered to later */ - { - CTR_Map<STR_HashedString, void *> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap(); - - for (int i = 0; i < mapStringToMeshes.size(); i++) { - RAS_MeshObject *meshobj = (RAS_MeshObject *) *mapStringToMeshes.at(i); - if (meshobj && IS_TAGGED(meshobj->GetMesh())) { - STR_HashedString mn = meshobj->GetName(); - mapStringToMeshes.remove(mn); - m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh())); - i--; - } - } - } - - /* Now unregister actions */ - { - CTR_Map<STR_HashedString, void *> &mapStringToActions = scene->GetLogicManager()->GetActionMap(); - - for (int i = 0; i < mapStringToActions.size(); i++) { - ID *action = (ID*) *mapStringToActions.at(i); - - if (IS_TAGGED(action)) { - STR_HashedString an = action->name + 2; - mapStringToActions.remove(an); - m_map_blender_to_gameAdtList.remove(CHashedPtr(action)); - i--; - } - } - } - - //scene->FreeTagged(); /* removed tagged objects and meshes*/ - CListValue *obj_lists[] = {scene->GetObjectList(), scene->GetInactiveList(), NULL}; - - for (int ob_ls_idx = 0; obj_lists[ob_ls_idx]; ob_ls_idx++) { - CListValue *obs = obj_lists[ob_ls_idx]; - RAS_MeshObject *mesh; - - for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++) { - KX_GameObject *gameobj = (KX_GameObject*)obs->GetValue(ob_idx); - if (IS_TAGGED(gameobj->GetBlenderObject())) { - int size_before = obs->GetCount(); - - /* Eventually calls RemoveNodeDestructObject - * frees m_map_gameobject_to_blender from UnregisterGameObject */ - scene->RemoveObject(gameobj); - - if (size_before != obs->GetCount()) - ob_idx--; - else { - printf("ERROR COULD NOT REMOVE \"%s\"\n", gameobj->GetName().ReadPtr()); - } - } - else { - gameobj->RemoveTaggedActions(); - /* free the mesh, we could be referecing a linked one! */ - int mesh_index = gameobj->GetMeshCount(); - while (mesh_index--) { - mesh = gameobj->GetMesh(mesh_index); - if (IS_TAGGED(mesh->GetMesh())) { - gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */ - break; - } - else { - /* also free the mesh if it's using a tagged material */ - int mat_index = mesh->NumMaterials(); - while (mat_index--) { - if (IS_TAGGED(mesh->GetMeshMaterial(mat_index)->m_bucket->GetPolyMaterial()->GetBlenderMaterial())) { - gameobj->RemoveMeshes(); /* XXX - slack, same as above */ - break; - } - } - } - } - - /* make sure action actuators are not referencing tagged actions */ - for (unsigned int act_idx = 0; act_idx < gameobj->GetActuators().size(); act_idx++) { - if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) { - BL_ActionActuator *act = (BL_ActionActuator *)gameobj->GetActuators()[act_idx]; - if (IS_TAGGED(act->GetAction())) - act->SetAction(NULL); - } - } - } - } - } - } - } - - int size; - - // delete the entities of this scene - /* TODO - */ -#if 0 - vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit; - size = m_worldinfos.size(); - for (i=0, worldit=m_worldinfos.begin(); i<size; ) { - if ((*worldit).second) { - delete (*worldit).second; - *worldit = m_worldinfos.back(); - m_worldinfos.pop_back(); - size--; - } else { - i++; - worldit++; - } - } -#endif - - - /* Worlds don't reference original blender data so we need to make a set from them */ - typedef std::set<KX_WorldInfo *> KX_WorldInfoSet; - KX_WorldInfoSet worldset; - for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) { - KX_Scene *scene = scenes->at(scene_idx); - if (scene->GetWorldInfo()) - worldset.insert(scene->GetWorldInfo()); - } - - vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator worldit; - size = m_worldinfos.size(); - for (i = 0, worldit = m_worldinfos.begin(); i < size;) { - if (worldit->second && (worldset.count(worldit->second)) == 0) { - delete worldit->second; - *worldit = m_worldinfos.back(); - m_worldinfos.pop_back(); - size--; - } - else { - i++; - worldit++; - } - } - worldset.clear(); - /* done freeing the worlds */ - - vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator polymit; - size = m_polymaterials.size(); - - for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { - RAS_IPolyMaterial *mat = polymit->second; - Material *bmat = NULL; - - KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial *>(mat); - bmat = bl_mat->GetBlenderMaterial(); - - if (IS_TAGGED(bmat)) { - /* only remove from bucket */ - polymit->first->GetBucketManager()->RemoveMaterial(mat); - } - - i++; - polymit++; - } - - for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { - RAS_IPolyMaterial *mat = polymit->second; - Material *bmat = NULL; - - KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat); - bmat = bl_mat->GetBlenderMaterial(); - - if (IS_TAGGED(bmat)) { - // Remove the poly material coresponding to this Blender Material. - m_polymat_cache[polymit->first].erase(bmat); - delete polymit->second; - *polymit = m_polymaterials.back(); - m_polymaterials.pop_back(); - size--; - } else { - i++; - polymit++; - } - } - - vector<pair<KX_Scene *, BL_Material *> >::iterator matit; - size = m_materials.size(); - for (i = 0, matit = m_materials.begin(); i < size; ) { - BL_Material *mat = matit->second; - if (IS_TAGGED(mat->material)) { - // Remove the bl material coresponding to this Blender Material. - m_mat_cache[matit->first].erase(mat->material); - delete matit->second; - *matit = m_materials.back(); - m_materials.pop_back(); - size--; - } - else { - i++; - matit++; - } - } - - vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator meshit; - RAS_BucketManager::BucketList::iterator bit; - list<RAS_MeshSlot>::iterator msit; - RAS_BucketManager::BucketList buckets; - - size = m_meshobjects.size(); - for (i = 0, meshit = m_meshobjects.begin(); i < size;) { - RAS_MeshObject *me = meshit->second; - if (IS_TAGGED(me->GetMesh())) { - // Before deleting the mesh object, make sure the rasterizer is - // no longer referencing it. - buckets = meshit->first->GetBucketManager()->GetSolidBuckets(); - for (bit = buckets.begin(); bit != buckets.end(); bit++) { - msit = (*bit)->msBegin(); - - while (msit != (*bit)->msEnd()) { - if (msit->m_mesh == meshit->second) - (*bit)->RemoveMesh(&(*msit++)); - else - msit++; - } - } - - // And now the alpha buckets - buckets = meshit->first->GetBucketManager()->GetAlphaBuckets(); - for (bit = buckets.begin(); bit != buckets.end(); bit++) { - msit = (*bit)->msBegin(); - - while (msit != (*bit)->msEnd()) { - if (msit->m_mesh == meshit->second) - (*bit)->RemoveMesh(&(*msit++)); - else - msit++; - } - } - - // Now it should be safe to delete - delete meshit->second; - *meshit = m_meshobjects.back(); - m_meshobjects.pop_back(); - size--; - } - else { - i++; - meshit++; - } - } - -#ifdef WITH_PYTHON - /* make sure this maggie is removed from the import list if it's there - * (this operation is safe if it isn't in the list) */ - removeImportMain(maggie); -#endif - - delete m_status_map[maggie->name]; - m_status_map.erase(maggie->name); - - BKE_main_free(maggie); - - return true; -} - -bool KX_BlenderSceneConverter::FreeBlendFile(const char *path) -{ - return FreeBlendFile(GetMainDynamicPath(path)); -} - -bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from) -{ - { - vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator itp = m_worldinfos.begin(); - while (itp != m_worldinfos.end()) { - if (itp->first == from) - itp->first = to; - itp++; - } - } - - { - vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator itp = m_polymaterials.begin(); - while (itp != m_polymaterials.end()) { - if (itp->first == from) { - itp->first = to; - - /* also switch internal data */ - RAS_IPolyMaterial *mat = itp->second; - mat->Replace_IScene(to); - } - itp++; - } - } - - { - vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator itp = m_meshobjects.begin(); - while (itp != m_meshobjects.end()) { - if (itp->first == from) - itp->first = to; - itp++; - } - } - - { - vector<pair<KX_Scene *, BL_Material *> >::iterator itp = m_materials.begin(); - while (itp != m_materials.end()) { - if (itp->first == from) - itp->first = to; - itp++; - } - } - - MaterialCache::iterator matcacheit = m_mat_cache.find(from); - if (matcacheit != m_mat_cache.end()) { - // Merge cached BL_Material map. - m_mat_cache[to].insert(matcacheit->second.begin(), matcacheit->second.end()); - m_mat_cache.erase(matcacheit); - } - - PolyMaterialCache::iterator polymatcacheit = m_polymat_cache.find(from); - if (polymatcacheit != m_polymat_cache.end()) { - // Merge cached RAS_IPolyMaterial map. - m_polymat_cache[to].insert(polymatcacheit->second.begin(), polymatcacheit->second.end()); - m_polymat_cache.erase(polymatcacheit); - } - - return true; -} - -/* This function merges a mesh from the current scene into another main - * it does not convert */ -RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene *kx_scene, Main *maggie, const char *name) -{ - /* Find a mesh in the current main */ - ID *me= static_cast<ID *>(BLI_findstring(&m_maggie->mesh, name, offsetof(ID, name) + 2)); - Main *from_maggie = m_maggie; - - if (me == NULL) { - // The mesh wasn't in the current main, try any dynamic (i.e., LibLoaded) ones - vector<Main *>::iterator it; - - for (it = GetMainDynamic().begin(); it != GetMainDynamic().end(); it++) { - me = static_cast<ID *>(BLI_findstring(&(*it)->mesh, name, offsetof(ID, name) + 2)); - from_maggie = *it; - - if (me) - break; - } - } - - if (me == NULL) { - printf("Could not be found \"%s\"\n", name); - return NULL; - } - - /* Watch this!, if its used in the original scene can cause big troubles */ - if (me->us > 0) { -#ifdef DEBUG - printf("Mesh has a user \"%s\"\n", name); -#endif - me = (ID*)BKE_mesh_copy(from_maggie, (Mesh*)me); - id_us_min(me); - } - BLI_remlink(&from_maggie->mesh, me); /* even if we made the copy it needs to be removed */ - BLI_addtail(&maggie->mesh, me); - - /* Must copy the materials this uses else we cant free them */ - { - Mesh *mesh = (Mesh *)me; - - /* ensure all materials are tagged */ - for (int i = 0; i < mesh->totcol; i++) { - if (mesh->mat[i]) - mesh->mat[i]->id.tag &= ~LIB_TAG_DOIT; - } - - for (int i = 0; i < mesh->totcol; i++) { - Material *mat_old = mesh->mat[i]; - - /* if its tagged its a replaced material */ - if (mat_old && (mat_old->id.tag & LIB_TAG_DOIT) == 0) { - Material *mat_old = mesh->mat[i]; - Material *mat_new = BKE_material_copy(from_maggie, mat_old); - - mat_new->id.tag |= LIB_TAG_DOIT; - id_us_min(&mat_old->id); - - BLI_remlink(&from_maggie->mat, mat_new); // BKE_material_copy uses G.main, and there is no BKE_material_copy_ex - BLI_addtail(&maggie->mat, mat_new); - - mesh->mat[i] = mat_new; - - /* the same material may be used twice */ - for (int j = i + 1; j < mesh->totcol; j++) { - if (mesh->mat[j] == mat_old) { - mesh->mat[j] = mat_new; - id_us_plus(&mat_new->id); - id_us_min(&mat_old->id); - } - } - } - } - } - - m_currentScene = kx_scene; // This needs to be set in case we LibLoaded earlier - RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this, false); - kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); - m_map_mesh_to_gamemesh.clear(); /* This is at runtime so no need to keep this, BL_ConvertMesh adds */ - return meshobj; -} |