/* this function is used to pre-filter the object before casting the ray on them.
 * This is useful for "X-Ray" option when we want to see "through" unwanted object.
 */
bool KX_MouseFocusSensor::NeedRayCast(KX_ClientObjectInfo* client)
{
	KX_GameObject *hitKXObj = client->m_gameobject;

	if (client->m_type > KX_ClientObjectInfo::ACTOR)
	{
		// Unknown type of object, skip it.
		// Should not occur as the sensor objects are filtered in RayTest()
		printf("Invalid client type %d found ray casting\n", client->m_type);
		return false;
	}
	if (m_bXRay && m_propertyname.Length() != 0)
	{
		if (m_bFindMaterial)
		{
			bool found = false;
			for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) {
				RAS_MeshObject *meshObj = hitKXObj->GetMesh(i);
				for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
					found = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
					if (found)
						break;
				}
			}
			if (!found)
				return false;
		}
		else
		{
			if (hitKXObj->GetProperty(m_propertyname) == NULL)
				return false;
		}
	}
	return true;
}
Exemplo n.º 2
0
bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void *UNUSED(data))
{

	m_hitObject = client->m_gameobject;
	
	bool bFound = false;

	if (m_property.empty())
	{
		bFound = true;
	}
	else
	{
		if (m_option & KX_ACT_CONSTRAINT_MATERIAL) {
			for (unsigned int i = 0; i < m_hitObject->GetMeshCount(); ++i) {
				RAS_MeshObject *meshObj = m_hitObject->GetMesh(i);
				for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
					bFound = (m_property == std::string(meshObj->GetMaterialName(j), 2));
					if (bFound)
						break;
				}
			}
		}
		else {
			bFound = m_hitObject->GetProperty(m_property) != NULL;
		}
	}
	// update the hit status
	result->m_hitFound = bFound;
	// stop looking
	return true;
}
Exemplo n.º 3
0
bool	KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_CollData* colldata)
{
//	KX_TouchEventManager* toucheventmgr = (KX_TouchEventManager*)m_eventmgr;
	KX_GameObject* parent = (KX_GameObject*)GetParent();

	// need the mapping from PHY_IPhysicsController to gameobjects now

	KX_ClientObjectInfo *client_info = static_cast<KX_ClientObjectInfo*> (object1 == m_physCtrl?
					((PHY_IPhysicsController*)object2)->GetNewClientInfo():
					((PHY_IPhysicsController*)object1)->GetNewClientInfo());

	KX_GameObject* gameobj = ( client_info ?
			client_info->m_gameobject :
			NULL);

	// add the same check as in SCA_ISensor::Activate(),
	// we don't want to record collision when the sensor is not active.
	if (m_links && !m_suspended &&
		gameobj && (gameobj != parent) && client_info->isActor())
	{

		bool found = m_touchedpropname.IsEmpty();
		bool hitMaterial = false;
		if (!found)
		{
			if (m_bFindMaterial) {
				for (unsigned int i = 0; i < gameobj->GetMeshCount(); ++i) {
					RAS_MeshObject *meshObj = gameobj->GetMesh(i);
					for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
						found = strcmp(m_touchedpropname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
						if (found) {
							hitMaterial = true;
							break;
						}
					}
				}
			}
			else {
				found = (gameobj->GetProperty(m_touchedpropname) != NULL);
			}
		}
		if (found)
		{
			if (!m_colliders->SearchValue(gameobj)) {
				m_colliders->Add(gameobj->AddRef());

				if (m_bTouchPulse)
					m_bColliderHash += (uint_ptr)(static_cast<void *>(&gameobj));
			}
			m_bTriggered = true;
			m_hitObject = gameobj;
			m_hitMaterial = hitMaterial;
			//printf("KX_TouchSensor::HandleCollision\n");
		}

	}
	return false; // was DT_CONTINUE but this was defined in sumo as false.
}
bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo *client_info, KX_RayCast *result, void * const data)
{
	KX_GameObject* hitKXObj = client_info->m_gameobject;
	
	/* Is this me? In the ray test, there are a lot of extra checks
	 * for aliasing artifacts from self-hits. That doesn't happen
	 * here, so a simple test suffices. Or does the camera also get
	 * self-hits? (No, and the raysensor shouldn't do it either, since
	 * self-hits are excluded by setting the correct ignore-object.)
	 * Hitspots now become valid. */
	KX_GameObject* thisObj = (KX_GameObject*) GetParent();

	bool bFound = false;

	if ((m_focusmode == 2) || hitKXObj == thisObj)
	{
		if (m_propertyname.Length() == 0)
		{
			bFound = true;
		}
		else
		{
			if (m_bFindMaterial) {
				for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) {
					RAS_MeshObject *meshObj = hitKXObj->GetMesh(i);
					for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
						bFound = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
						if (bFound)
							break;
					}
				}
			}
			else {
				bFound = hitKXObj->GetProperty(m_propertyname) != NULL;
			}
		}

		if (bFound)
		{
			m_hitObject = hitKXObj;
			m_hitPosition = result->m_hitPoint;
			m_hitNormal = result->m_hitNormal;
			m_hitUV = result->m_hitUV;
			return true;
		}		
	}
	
	return true;     // object must be visible to trigger
	//return false;  // occluded objects can trigger
}
Exemplo n.º 5
0
// 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;
}
Exemplo n.º 6
0
// this function is called only for sensor objects
// return true if the controller can collide with the object
bool KX_CollisionSensor::BroadPhaseSensorFilterCollision(void *obj1, void *obj2)
{
	BLI_assert(obj1 == m_physCtrl && obj2);

	KX_GameObject *myobj = (KX_GameObject *)GetParent();
	KX_GameObject *myparent = myobj->GetParent();
	KX_ClientObjectInfo *client_info = static_cast<KX_ClientObjectInfo *>(((PHY_IPhysicsController *)obj2)->GetNewClientInfo());
	KX_ClientObjectInfo *my_client_info = static_cast<KX_ClientObjectInfo *>(m_physCtrl->GetNewClientInfo());
	KX_GameObject *otherobj = (client_info ? client_info->m_gameobject : NULL);

	// we can only check on persistent characteristic: m_link and m_suspended are not
	// good candidate because they are transient. That must be handled at another level
	if (!otherobj ||
	    otherobj == myparent ||     // don't interact with our parent
	    (my_client_info->m_type == KX_ClientObjectInfo::OBACTORSENSOR &&
	     client_info->m_type != KX_ClientObjectInfo::ACTOR))    // only with actor objects
	{
		return false;
	}

	bool found = m_touchedpropname.empty();
	if (!found) {
		if (m_bFindMaterial) {
			for (unsigned int i = 0; i < otherobj->GetMeshCount(); ++i) {
				RAS_MeshObject *meshObj = otherobj->GetMesh(i);
				for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
					found = (m_touchedpropname == std::string(meshObj->GetMaterialName(j), 2));
					if (found) {
						break;
					}
				}
			}
		}
		else {
			found = (otherobj->GetProperty(m_touchedpropname) != NULL);
		}
	}
	return found;
}
bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts,
									   unsigned short* &polys, int& npolys, unsigned short *&dmeshes,
									   float *&dvertices, int &ndvertsuniq, unsigned short *&dtris, 
									   int& ndtris, int &vertsPerPoly)
{
    DerivedMesh* dm = mesh_create_derived_no_virtual(GetScene()->GetBlenderScene(), GetBlenderObject(),
													NULL, CD_MASK_MESH);
	CustomData *pdata = dm->getPolyDataLayout(dm);
	int* recastData = (int*) CustomData_get_layer(pdata, CD_RECAST);
	if (recastData)
	{
		int *dtrisToPolysMap=NULL, *dtrisToTrisMap=NULL, *trisToFacesMap=NULL;
		int nAllVerts = 0;
		float *allVerts = NULL;
		buildNavMeshDataByDerivedMesh(dm, &vertsPerPoly, &nAllVerts, &allVerts, &ndtris, &dtris,
		                              &npolys, &dmeshes, &polys, &dtrisToPolysMap, &dtrisToTrisMap, &trisToFacesMap);

		MEM_SAFE_FREE(dtrisToPolysMap);
		MEM_SAFE_FREE(dtrisToTrisMap);
		MEM_SAFE_FREE(trisToFacesMap);

		unsigned short *verticesMap = (unsigned short *)MEM_mallocN(sizeof(*verticesMap) * nAllVerts, __func__);
		memset(verticesMap, 0xff, sizeof(*verticesMap) * nAllVerts);
		int curIdx = 0;
		//vertices - mesh verts
		//iterate over all polys and create map for their vertices first...
		for (int polyidx=0; polyidx<npolys; polyidx++)
		{
			unsigned short* poly = &polys[polyidx*vertsPerPoly*2];
			for (int i=0; i<vertsPerPoly; i++)
			{
				unsigned short idx = poly[i];
				if (idx==0xffff)
					break;
				if (verticesMap[idx]==0xffff)
				{
					verticesMap[idx] = curIdx++;
				}
				poly[i] = verticesMap[idx];
			}
		}
		nverts = curIdx;
		//...then iterate over detailed meshes
		//transform indices to local ones (for each navigation polygon)
		for (int polyidx=0; polyidx<npolys; polyidx++)
		{
			unsigned short *poly = &polys[polyidx*vertsPerPoly*2];
			int nv = polyNumVerts(poly, vertsPerPoly);
			unsigned short *dmesh = &dmeshes[4*polyidx];
			unsigned short tribase = dmesh[2];
			unsigned short trinum = dmesh[3];
			unsigned short vbase = curIdx;
			for (int j=0; j<trinum; j++)
			{
				unsigned short* dtri = &dtris[(tribase+j)*3*2];
				for (int k=0; k<3; k++)
				{
					int newVertexIdx = verticesMap[dtri[k]];
					if (newVertexIdx==0xffff)
					{
						newVertexIdx = curIdx++;
						verticesMap[dtri[k]] = newVertexIdx;
					}

					if (newVertexIdx<nverts)
					{
						//it's polygon vertex ("shared")
						int idxInPoly = polyFindVertex(poly, vertsPerPoly, newVertexIdx);
						if (idxInPoly==-1)
						{
							printf("Building NavMeshObject: Error! Can't find vertex in polygon\n");
							return false;
						}
						dtri[k] = idxInPoly;
					}
					else
					{
						dtri[k] = newVertexIdx - vbase + nv;
					}
				}
			}
			dmesh[0] = vbase-nverts; //verts base
			dmesh[1] = curIdx-vbase; //verts num
		}

		vertices = new float[nverts*3];
		ndvertsuniq = curIdx - nverts;
		if (ndvertsuniq>0)
		{
			dvertices = new float[ndvertsuniq*3];
		}
		for (int vi=0; vi<nAllVerts; vi++)
		{
			int newIdx = verticesMap[vi];
			if (newIdx!=0xffff)
			{
				if (newIdx<nverts)
				{
					//navigation mesh vertex
					memcpy(vertices+3*newIdx, allVerts+3*vi, 3*sizeof(float));
				}
				else
				{
					//detailed mesh vertex
					memcpy(dvertices+3*(newIdx-nverts), allVerts+3*vi, 3*sizeof(float));
				}
			}
		}

		MEM_SAFE_FREE(allVerts);

		MEM_freeN(verticesMap);
	}
	else
	{
		//create from RAS_MeshObject (detailed mesh is fake)
		RAS_MeshObject* meshobj = GetMesh(0);
		vertsPerPoly = 3;
		nverts = meshobj->m_sharedvertex_map.size();
		if (nverts >= 0xffff)
			return false;
		//calculate count of tris
		int nmeshpolys = meshobj->NumPolygons();
		npolys = nmeshpolys;
		for (int p=0; p<nmeshpolys; p++)
		{
			int vertcount = meshobj->GetPolygon(p)->VertexCount();
			npolys+=vertcount-3;
		}

		//create verts
		vertices = new float[nverts*3];
		float* vert = vertices;
		for (int vi=0; vi<nverts; vi++)
		{
			const float* pos = !meshobj->m_sharedvertex_map[vi].empty() ? meshobj->GetVertexLocation(vi) : NULL;
			if (pos)
				copy_v3_v3(vert, pos);
			else
			{
				memset(vert, 0, 3*sizeof(float)); //vertex isn't in any poly, set dummy zero coordinates
			}
			vert+=3;
		}

		//create tris
		polys = (unsigned short *)MEM_callocN(sizeof(unsigned short)*3*2*npolys, "BuildVertIndArrays polys");
		memset(polys, 0xff, sizeof(unsigned short)*3*2*npolys);
		unsigned short *poly = polys;
		RAS_Polygon* raspoly;
		for (int p=0; p<nmeshpolys; p++)
		{
			raspoly = meshobj->GetPolygon(p);
			for (int v=0; v<raspoly->VertexCount()-2; v++)
			{
				poly[0] = raspoly->GetVertex(0)->getOrigIndex();
				for (size_t i=1; i<3; i++)
				{
					poly[i] = raspoly->GetVertex(v+i)->getOrigIndex();
				}
				poly += 6;
			}
		}
		dmeshes = NULL;
		dvertices = NULL;
		ndvertsuniq = 0;
		dtris = NULL;
		ndtris = npolys;
	}
	dm->release(dm);
	
	return true;
}
Exemplo n.º 8
0
bool 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 */
	Main *main_tmp= NULL; /* created only for linking, then freed */
	LinkNode *names = NULL;
	int idcode= BKE_idcode_from_name(group);
	short flag= 0; /* don't need any special options */
	ReportList reports;
	static char err_local[255];
	
	/* 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 false;
	}
	
	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 false;
	}

	if (bpy_openlib==NULL) {
		snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path);
		*err_str= err_local;
		return false;
	}
	
	main_newlib= (Main *)MEM_callocN( sizeof(Main), "BgeMain");
	BKE_reports_init(&reports, RPT_STORE);	

	/* here appending/linking starts */
	main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path);

	int totnames_dummy;
	names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy);
	
	int i=0;
	LinkNode *n= names;
	while(n) {
		BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, idcode);
		n= (LinkNode *)n->next;
		i++;
	}
	BLI_linklist_free(names, free);	/* free linklist *and* each node's data */
	
	BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag);

	/* now do another round of linking for Scenes so all actions are properly loaded */
	if (idcode==ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) {
		main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path);

		int totnames_dummy;
		names = BLO_blendhandle_get_datablock_names( bpy_openlib, ID_AC, &totnames_dummy);
	
		int i=0;
		LinkNode *n= names;
		while(n) {
			BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, ID_AC);
			n= (LinkNode *)n->next;
			i++;
		}
		BLI_linklist_free(names, free);	/* free linklist *and* each node's data */
	
		BLO_library_append_end(NULL, main_tmp, &bpy_openlib, ID_AC, flag);
	}
	
	BLO_blendhandle_close(bpy_openlib);

	BKE_reports_clear(&reports);
	/* done linking */	
	
	/* needed for lookups*/
	GetMainDynamic().push_back(main_newlib);
	strncpy(main_newlib->name, path, sizeof(main_newlib->name));	
	
	
	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);
			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;
		for (scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) {
			if (options & LIB_LOAD_VERBOSE)
				printf("SceneName: %s\n", scene->name+2);
			
			/* merge into the base  scene */
			KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene);
			scene_merge->MergeScene(other);
			
			// RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene
			delete other;
		}

		/* 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);
			}
		}
	}
	
	return true;
}
Exemplo n.º 9
0
/* 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));
	
	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) {
		printf("Mesh has a user \"%s\"\n", name);
		me = (ID*)BKE_mesh_copy((Mesh*)me);
		me->us--;
	}
	BLI_remlink(&m_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.flag &= ~LIB_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.flag & LIB_DOIT)==0)
			{
				Material *mat_old= mesh->mat[i];
				Material *mat_new= BKE_material_copy( mat_old );
				
				mat_new->id.flag |= LIB_DOIT;
				mat_old->id.us--;
				
				BLI_remlink(&m_maggie->mat, mat_new);
				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;
						mat_new->id.us++;
						mat_old->id.us--;
					}
				}
			}
		}
	}
	
	RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this);
	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;
}
Exemplo n.º 10
0
/* 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(struct Main *maggie)
{
	int maggie_index= -1;
	int i=0;

	if (maggie==NULL)
		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) {
			tag_main(main, 0);
		}
		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);
	tag_main(maggie, 1);


	/* 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())) {
			RemoveScene(scene); // XXX - not tested yet
			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);
						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 {
						/* 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;
							}
						}

						/* 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;

		/* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
		if (mat->GetFlag() & RAS_BLENDERMAT) {
			KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
			bmat= bl_mat->GetBlenderMaterial();

		} else {
			KX_PolygonMaterial *kx_mat = static_cast<KX_PolygonMaterial*>(mat);
			bmat= kx_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;

		/* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
		if (mat->GetFlag() & RAS_BLENDERMAT) {
			KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
			bmat= bl_mat->GetBlenderMaterial();

		} else {
			KX_PolygonMaterial *kx_mat = static_cast<KX_PolygonMaterial*>(mat);
			bmat= kx_mat->GetBlenderMaterial();
		}

		if (bmat) {
			//printf("FOUND MAT '%s' !!! ", ((ID*)bmat)->name+2);
		}
		else {
			//printf("LOST MAT  !!!");
		}

		if (IS_TAGGED(bmat)) {

			delete (*polymit).second;
			*polymit = m_polymaterials.back();
			m_polymaterials.pop_back();
			size--;
			//printf("tagged !\n");
		} else {
			i++;
			polymit++;
			//printf("(un)tagged !\n");
		}
	}

	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)) {
			delete (*matit).second;
			*matit = m_materials.back();
			m_materials.pop_back();
			size--;
		} else {
			i++;
			matit++;
		}
	}

	vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
	size = m_meshobjects.size();
	for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
		RAS_MeshObject *me= (*meshit).second;
		if (IS_TAGGED(me->GetMesh())) {
			delete (*meshit).second;
			*meshit = m_meshobjects.back();
			m_meshobjects.pop_back();
			size--;
		} else {
			i++;
			meshit++;
		}
	}

	free_main(maggie);

	return true;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
/* 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_ex(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(mat_old);

				mat_new->id.tag |= LIB_TAG_DOIT;
				id_us_min(&mat_old->id);

				BLI_remlink(&G.main->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;
}
Exemplo n.º 13
0
/* 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;
}