Ejemplo n.º 1
0
static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *layer)
{
	Mesh *me = ob->data;
	CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
	void *actlayerdata, *rndlayerdata, *clonelayerdata, *stencillayerdata, *layerdata=layer->data;
	int type= layer->type;
	int index= CustomData_get_layer_index(data, type);
	int i, actindex, rndindex, cloneindex, stencilindex;
	
	/* ok, deleting a non-active layer needs to preserve the active layer indices.
	  to do this, we store a pointer to the .data member of both layer and the active layer,
	  (to detect if we're deleting the active layer or not), then use the active
	  layer data pointer to find where the active layer has ended up.
	  
	  this is necassary because the deletion functions only support deleting the active
	  layer. */
	actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
	rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
	clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data;
	stencillayerdata = data->layers[CustomData_get_stencil_layer_index(data, type)].data;
	CustomData_set_layer_active(data, type, layer - &data->layers[index]);

	if(me->edit_mesh) {
		EM_free_data_layer(me->edit_mesh, data, type);
	}
	else {
		CustomData_free_layer_active(data, type, me->totface);
		mesh_update_customdata_pointers(me);
	}

	if(!CustomData_has_layer(data, type) && (type == CD_MCOL && (ob->mode & OB_MODE_VERTEX_PAINT)))
		ED_object_toggle_modes(C, OB_MODE_VERTEX_PAINT);

	/* reconstruct active layer */
	if (actlayerdata != layerdata) {
		/* find index */
		actindex = CustomData_get_layer_index(data, type);
		for (i=actindex; i<data->totlayer; i++) {
			if (data->layers[i].data == actlayerdata) {
				actindex = i - actindex;
				break;
			}
		}
		
		/* set index */
		CustomData_set_layer_active(data, type, actindex);
	}
	
	if (rndlayerdata != layerdata) {
		/* find index */
		rndindex = CustomData_get_layer_index(data, type);
		for (i=rndindex; i<data->totlayer; i++) {
			if (data->layers[i].data == rndlayerdata) {
				rndindex = i - rndindex;
				break;
			}
		}
		
		/* set index */
		CustomData_set_layer_render(data, type, rndindex);
	}
	
	if (clonelayerdata != layerdata) {
		/* find index */
		cloneindex = CustomData_get_layer_index(data, type);
		for (i=cloneindex; i<data->totlayer; i++) {
			if (data->layers[i].data == clonelayerdata) {
				cloneindex = i - cloneindex;
				break;
			}
		}
		
		/* set index */
		CustomData_set_layer_clone(data, type, cloneindex);
	}
	
	if (stencillayerdata != layerdata) {
		/* find index */
		stencilindex = CustomData_get_layer_index(data, type);
		for (i=stencilindex; i<data->totlayer; i++) {
			if (data->layers[i].data == stencillayerdata) {
				stencilindex = i - stencilindex;
				break;
			}
		}
		
		/* set index */
		CustomData_set_layer_stencil(data, type, stencilindex);
	}
}
Ejemplo n.º 2
0
static int object_modifier_remove(Object *ob, ModifierData *md, int *sort_depsgraph)
{
	ModifierData *obmd;

	/* It seems on rapid delete it is possible to
	 * get called twice on same modifier, so make
	 * sure it is in list. */
	for(obmd=ob->modifiers.first; obmd; obmd=obmd->next)
		if(obmd==md)
			break;

	if(!obmd)
		return 0;

	/* special cases */
	if(md->type == eModifierType_ParticleSystem) {
		ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;

		BLI_remlink(&ob->particlesystem, psmd->psys);
		psys_free(ob, psmd->psys);
		psmd->psys= NULL;
	}
	else if(md->type == eModifierType_Softbody) {
		if(ob->soft) {
			sbFree(ob->soft);
			ob->soft= NULL;
			ob->softflag= 0;
		}
	}
	else if(md->type == eModifierType_Collision) {
		if(ob->pd)
			ob->pd->deflect= 0;

		*sort_depsgraph = 1;
	}
	else if(md->type == eModifierType_Surface) {
		if(ob->pd && ob->pd->shape == PFIELD_SHAPE_SURFACE)
			ob->pd->shape = PFIELD_SHAPE_PLANE;

		*sort_depsgraph = 1;
	}
	else if(md->type == eModifierType_Smoke) {
		ob->dt = OB_TEXTURE;
	}
	else if(md->type == eModifierType_Multires) {
		int ok= 1;
		Mesh *me= ob->data;
		ModifierData *tmpmd;

		/* ensure MDISPS CustomData layer is't used by another multires modifiers */
		for(tmpmd= ob->modifiers.first; tmpmd; tmpmd= tmpmd->next)
			if(tmpmd!=md && tmpmd->type == eModifierType_Multires) {
				ok= 0;
				break;
			}

		if(ok) {
			if(me->edit_mesh) {
				EditMesh *em= me->edit_mesh;
				/* CustomData_external_remove is used here only to mark layer as non-external
				   for further free-ing, so zero element count looks safer than em->totface */
				CustomData_external_remove(&em->fdata, &me->id, CD_MDISPS, 0);
				EM_free_data_layer(em, &em->fdata, CD_MDISPS);
			} else {
				CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
				CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
			}
		}
	}

	if(ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) &&
		ob->particlesystem.first == NULL) {
		ob->mode &= ~OB_MODE_PARTICLE_EDIT;
	}

	BLI_remlink(&ob->modifiers, md);
	modifier_free(md);

	return 1;
}
Ejemplo n.º 3
0
int ED_object_modifier_remove(ReportList *reports, Main *bmain, Scene *scene, Object *ob, ModifierData *md)
{
	ModifierData *obmd;
	int sort_depsgraph = 0;

	/* It seems on rapid delete it is possible to
	 * get called twice on same modifier, so make
	 * sure it is in list. */
	for(obmd=ob->modifiers.first; obmd; obmd=obmd->next)
		if(obmd==md)
			break;
	
	if(!obmd) {
		BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", ob->id.name, md->name);
		return 0;
	}

	/* special cases */
	if(md->type == eModifierType_ParticleSystem) {
		ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;

		BLI_remlink(&ob->particlesystem, psmd->psys);
		psys_free(ob, psmd->psys);
		psmd->psys= NULL;
	}
	else if(md->type == eModifierType_Softbody) {
		if(ob->soft) {
			sbFree(ob->soft);
			ob->soft= NULL;
			ob->softflag= 0;
		}
	}
	else if(md->type == eModifierType_Collision) {
		if(ob->pd)
			ob->pd->deflect= 0;

		sort_depsgraph = 1;
	}
	else if(md->type == eModifierType_Surface) {
		if(ob->pd && ob->pd->shape == PFIELD_SHAPE_SURFACE)
			ob->pd->shape = PFIELD_SHAPE_PLANE;

		sort_depsgraph = 1;
	}
	else if(md->type == eModifierType_Smoke) {
		ob->dt = OB_TEXTURE;
	}
	else if(md->type == eModifierType_Multires) {
		int ok= 1;
		Mesh *me= ob->data;
		ModifierData *tmpmd;

		/* ensure MDISPS CustomData layer is't used by another multires modifiers */
		for(tmpmd= ob->modifiers.first; tmpmd; tmpmd= tmpmd->next)
			if(tmpmd!=md && tmpmd->type == eModifierType_Multires) {
				ok= 0;
				break;
			}

		if(ok) {
			if(me->edit_mesh) {
				EditMesh *em= me->edit_mesh;
				/* CustomData_external_remove is used here only to mark layer as non-external
				   for further free-ing, so zero element count looks safer than em->totface */
				CustomData_external_remove(&em->fdata, &me->id, CD_MDISPS, 0);
				EM_free_data_layer(em, &em->fdata, CD_MDISPS);
			} else {
				CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
				CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
			}
		}
	}

	if(ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) &&
		ob->particlesystem.first == NULL) {
		ob->mode &= ~OB_MODE_PARTICLE_EDIT;
	}

	BLI_remlink(&ob->modifiers, md);
	modifier_free(md);

	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);

	/* sorting has to be done after the update so that dynamic systems can react properly */
	if(sort_depsgraph)
		DAG_scene_sort(bmain, scene);

	return 1;
}