// get pointer to material RAS_IPolyMaterial * getMaterial (PyObject *obj, short matID) { // if object is available if (obj != NULL) { // get pointer to texture image KX_GameObject * gameObj = gameObjectType.checkType(obj); if (gameObj != NULL && gameObj->GetMeshCount() > 0) { // get material from mesh RAS_MeshObject * mesh = gameObj->GetMesh(0); RAS_MeshMaterial *meshMat = mesh->GetMeshMaterial(matID); if (meshMat != NULL && meshMat->m_bucket != NULL) // return pointer to polygon or blender material return meshMat->m_bucket->GetPolyMaterial(); } } // otherwise material was not found return NULL; }
/* 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; }