Exemple #1
0
void BKE_modifier_init(void)
{
	ModifierData *md;

	/* Initialize modifier types */
	modifier_type_init(modifier_types); /* MOD_utils.c */

	/* Initialize global cmmon storage used for virtual modifier list */
	md = modifier_new(eModifierType_Armature);
	virtualModifierCommonData.amd = *((ArmatureModifierData *) md);
	modifier_free(md);

	md = modifier_new(eModifierType_Curve);
	virtualModifierCommonData.cmd = *((CurveModifierData *) md);
	modifier_free(md);

	md = modifier_new(eModifierType_Lattice);
	virtualModifierCommonData.lmd = *((LatticeModifierData *) md);
	modifier_free(md);

	md = modifier_new(eModifierType_ShapeKey);
	virtualModifierCommonData.smd = *((ShapeKeyModifierData *) md);
	modifier_free(md);

	virtualModifierCommonData.amd.modifier.mode |= eModifierMode_Virtual;
	virtualModifierCommonData.cmd.modifier.mode |= eModifierMode_Virtual;
	virtualModifierCommonData.lmd.modifier.mode |= eModifierMode_Virtual;
	virtualModifierCommonData.smd.modifier.mode |= eModifierMode_Virtual;
}
Exemple #2
0
static void rna_FluidSettings_update_type(Main *bmain, Scene *scene, PointerRNA *ptr)
{
	Object *ob = (Object*)ptr->id.data;
	FluidsimModifierData *fluidmd;
	ParticleSystemModifierData *psmd;
	ParticleSystem *psys;
	ParticleSettings *part;
	
	fluidmd = (FluidsimModifierData*)modifiers_findByType(ob, eModifierType_Fluidsim);
	fluidmd->fss->flag &= ~OB_FLUIDSIM_REVERSE; /* clear flag */

	/* remove fluidsim particle system */
	if (fluidmd->fss->type & OB_FLUIDSIM_PARTICLE) {
		for (psys = ob->particlesystem.first; psys; psys = psys->next)
			if (psys->part->type == PART_FLUID)
				break;

		if (ob->type == OB_MESH && !psys) {
			/* add particle system */
			part = psys_new_settings("ParticleSettings", bmain);
			psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");

			part->type = PART_FLUID;
			psys->part = part;
			psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
			psys->flag |= PSYS_ENABLED;
			BLI_strncpy(psys->name, "FluidParticles", sizeof(psys->name));
			BLI_addtail(&ob->particlesystem,psys);

			/* add modifier */
			psmd = (ParticleSystemModifierData*)modifier_new(eModifierType_ParticleSystem);
			BLI_strncpy(psmd->modifier.name, "FluidParticleSystem", sizeof(psmd->modifier.name));
			psmd->psys = psys;
			BLI_addtail(&ob->modifiers, psmd);
			modifier_unique_name(&ob->modifiers, (ModifierData *)psmd);
		}
	}
	else {
		for (psys = ob->particlesystem.first; psys; psys = psys->next) {
			if (psys->part->type == PART_FLUID) {
				/* clear modifier */
				psmd = psys_get_modifier(ob, psys);
				BLI_remlink(&ob->modifiers, psmd);
				modifier_free((ModifierData *)psmd);

				/* clear particle system */
				BLI_remlink(&ob->particlesystem, psys);
				psys_free(ob, psys);
			}
		}
	}

	rna_fluid_update(bmain, scene, ptr);
}
static void remove_particle_systems_from_object(Object *ob_to)
{
	ModifierData *md, *md_next;
	
	if (ob_to->type != OB_MESH)
		return;
	if (!ob_to->data || ((ID *)ob_to->data)->lib)
		return;
	
	for (md = ob_to->modifiers.first; md; md = md_next) {
		md_next = md->next;
		
		/* remove all particle system modifiers as well,
		 * these need to sync to the particle system list
		 */
		if (ELEM(md->type, eModifierType_ParticleSystem, eModifierType_DynamicPaint, eModifierType_Smoke)) {
			BLI_remlink(&ob_to->modifiers, md);
			modifier_free(md);
		}
	}
	
	BKE_object_free_particlesystems(ob_to);
}
Exemple #4
0
static int object_hook_remove_exec(bContext *C, wmOperator *op)
{
	int num= RNA_enum_get(op->ptr, "modifier");
	Object *ob=NULL;
	HookModifierData *hmd=NULL;

	ob = CTX_data_edit_object(C);
	hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);

	if (!ob || !hmd) {
		BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier");
		return OPERATOR_CANCELLED;
	}
	
	/* remove functionality */
	
	BLI_remlink(&ob->modifiers, (ModifierData *)hmd);
	modifier_free((ModifierData *)hmd);
	
	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
	WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
	
	return OPERATOR_FINISHED;
}
int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md, int mode)
{
	int prev_mode;

	if (scene->obedit) {
		BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in editmode");
		return 0;
	} else if (((ID*) ob->data)->us>1) {
		BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
		return 0;
	}

	if (md!=ob->modifiers.first)
		BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");

	/* allow apply of a not-realtime modifier, by first re-enabling realtime. */
	prev_mode= md->mode;
	md->mode |= eModifierMode_Realtime;

	if (mode == MODIFIER_APPLY_SHAPE) {
		if (!modifier_apply_shape(reports, scene, ob, md)) {
			md->mode= prev_mode;
			return 0;
		}
	} else {
		if (!modifier_apply_obdata(reports, scene, ob, md)) {
			md->mode= prev_mode;
			return 0;
		}
	}

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

	return 1;
}
static int bake(
        Render *re, Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports,
        const ScenePassType pass_type, const int margin,
        const BakeSaveMode save_mode, const bool is_clear, const bool is_split_materials,
        const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage,
        const float cage_extrusion, const int normal_space, const BakeNormalSwizzle normal_swizzle[],
        const char *custom_cage, const char *filepath, const int width, const int height,
        const char *identifier, ScrArea *sa, const char *uv_layer)
{
	int op_result = OPERATOR_CANCELLED;
	bool ok = false;

	Object *ob_cage = NULL;

	BakeHighPolyData *highpoly = NULL;
	int tot_highpoly = 0;

	char restrict_flag_low = ob_low->restrictflag;
	char restrict_flag_cage = 0;

	Mesh *me_low = NULL;
	Mesh *me_cage = NULL;

	float *result = NULL;

	BakePixel *pixel_array_low = NULL;
	BakePixel *pixel_array_high = NULL;

	const bool is_save_internal = (save_mode == R_BAKE_SAVE_INTERNAL);
	const bool is_noncolor = is_noncolor_pass(pass_type);
	const int depth = RE_pass_depth(pass_type);

	BakeImages bake_images = {NULL};

	size_t num_pixels;
	int tot_materials;

	RE_bake_engine_set_engine_parameters(re, bmain, scene);

	if (!RE_bake_has_engine(re)) {
		BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
		goto cleanup;
	}

	tot_materials = ob_low->totcol;

	if (uv_layer && uv_layer[0] != '\0') {
		Mesh *me = (Mesh *)ob_low->data;
		if (CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer) == -1) {
			BKE_reportf(reports, RPT_ERROR,
			            "No UV layer named \"%s\" found in the object \"%s\"", uv_layer, ob_low->id.name + 2);
			goto cleanup;
		}
	}

	if (tot_materials == 0) {
		if (is_save_internal) {
			BKE_report(reports, RPT_ERROR,
			           "No active image found, add a material or bake to an external file");

			goto cleanup;
		}
		else if (is_split_materials) {
			BKE_report(reports, RPT_ERROR,
			           "No active image found, add a material or bake without the Split Materials option");

			goto cleanup;
		}
		else {
			/* baking externally without splitting materials */
			tot_materials = 1;
		}
	}

	/* we overallocate in case there is more materials than images */
	bake_images.data = MEM_mallocN(sizeof(BakeImage) * tot_materials, "bake images dimensions (width, height, offset)");
	bake_images.lookup = MEM_mallocN(sizeof(int) * tot_materials, "bake images lookup (from material to BakeImage)");

	build_image_lookup(bmain, ob_low, &bake_images);

	if (is_save_internal) {
		num_pixels = initialize_internal_images(&bake_images, reports);

		if (num_pixels == 0) {
			goto cleanup;
		}
	}
	else {
		/* when saving extenally always use the size specified in the UI */

		num_pixels = (size_t)width * (size_t)height * bake_images.size;

		for (int i = 0; i < bake_images.size; i++) {
			bake_images.data[i].width = width;
			bake_images.data[i].height = height;
			bake_images.data[i].offset = (is_split_materials ? num_pixels : 0);
			bake_images.data[i].image = NULL;
		}

		if (!is_split_materials) {
			/* saving a single image */
			for (int i = 0; i < tot_materials; i++) {
				bake_images.lookup[i] = 0;
			}
		}
	}

	if (is_selected_to_active) {
		CollectionPointerLink *link;
		tot_highpoly = 0;

		for (link = selected_objects->first; link; link = link->next) {
			Object *ob_iter = link->ptr.data;

			if (ob_iter == ob_low)
				continue;

			tot_highpoly ++;
		}

		if (is_cage && custom_cage[0] != '\0') {
			ob_cage = BLI_findstring(&bmain->object, custom_cage, offsetof(ID, name) + 2);

			if (ob_cage == NULL || ob_cage->type != OB_MESH) {
				BKE_report(reports, RPT_ERROR, "No valid cage object");
				goto cleanup;
			}
			else {
				restrict_flag_cage = ob_cage->restrictflag;
				ob_cage->restrictflag |= OB_RESTRICT_RENDER;
			}
		}
	}

	pixel_array_low = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly");
	pixel_array_high = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
	result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");

	/* get the mesh as it arrives in the renderer */
	me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
	BKE_mesh_split_faces(me_low);

	/* populate the pixel array with the face data */
	if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
		RE_bake_pixels_populate(me_low, pixel_array_low, num_pixels, &bake_images, uv_layer);
	/* else populate the pixel array with the 'cage' mesh (the smooth version of the mesh)  */

	if (is_selected_to_active) {
		CollectionPointerLink *link;
		ModifierData *md, *nmd;
		ListBase modifiers_tmp, modifiers_original;
		int i = 0;

		/* prepare cage mesh */
		if (ob_cage) {
			me_cage = BKE_mesh_new_from_object(bmain, scene, ob_cage, 1, 2, 0, 0);
			BKE_mesh_split_faces(me_cage);
			if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
				BKE_report(reports, RPT_ERROR,
				           "Invalid cage object, the cage mesh must have the same number "
				           "of faces as the active object");
				goto cleanup;
			}
		}
		else if (is_cage) {
			modifiers_original = ob_low->modifiers;
			BLI_listbase_clear(&modifiers_tmp);

			for (md = ob_low->modifiers.first; md; md = md->next) {
				/* Edge Split cannot be applied in the cage,
				 * the cage is supposed to have interpolated normals
				 * between the faces unless the geometry is physically
				 * split. So we create a copy of the low poly mesh without
				 * the eventual edge split.*/

				if (md->type == eModifierType_EdgeSplit)
					continue;

				nmd = modifier_new(md->type);
				BLI_strncpy(nmd->name, md->name, sizeof(nmd->name));
				modifier_copyData(md, nmd);
				BLI_addtail(&modifiers_tmp, nmd);
			}

			/* temporarily replace the modifiers */
			ob_low->modifiers = modifiers_tmp;

			/* get the cage mesh as it arrives in the renderer */
			me_cage = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
			BKE_mesh_split_faces(me_cage);
			RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
		}

		highpoly = MEM_callocN(sizeof(BakeHighPolyData) * tot_highpoly, "bake high poly objects");

		/* populate highpoly array */
		for (link = selected_objects->first; link; link = link->next) {
			TriangulateModifierData *tmd;
			Object *ob_iter = link->ptr.data;

			if (ob_iter == ob_low)
				continue;

			/* initialize highpoly_data */
			highpoly[i].ob = ob_iter;
			highpoly[i].restrict_flag = ob_iter->restrictflag;

			/* triangulating so BVH returns the primitive_id that will be used for rendering */
			highpoly[i].tri_mod = ED_object_modifier_add(
			        reports, bmain, scene, highpoly[i].ob,
			        "TmpTriangulate", eModifierType_Triangulate);
			tmd = (TriangulateModifierData *)highpoly[i].tri_mod;
			tmd->quad_method = MOD_TRIANGULATE_QUAD_FIXED;
			tmd->ngon_method = MOD_TRIANGULATE_NGON_EARCLIP;

			highpoly[i].me = BKE_mesh_new_from_object(bmain, scene, highpoly[i].ob, 1, 2, 0, 0);
			highpoly[i].ob->restrictflag &= ~OB_RESTRICT_RENDER;
			BKE_mesh_split_faces(highpoly[i].me);

			/* lowpoly to highpoly transformation matrix */
			copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
			invert_m4_m4(highpoly[i].imat, highpoly[i].obmat);

			highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->obmat);

			i++;
		}

		BLI_assert(i == tot_highpoly);

		ob_low->restrictflag |= OB_RESTRICT_RENDER;

		/* populate the pixel arrays with the corresponding face data for each high poly object */
		if (!RE_bake_pixels_populate_from_objects(
		            me_low, pixel_array_low, pixel_array_high, highpoly, tot_highpoly, num_pixels, ob_cage != NULL,
		            cage_extrusion, ob_low->obmat, (ob_cage ? ob_cage->obmat : ob_low->obmat), me_cage))
		{
			BKE_report(reports, RPT_ERROR, "Error handling selected objects");
			goto cage_cleanup;
		}

		/* the baking itself */
		for (i = 0; i < tot_highpoly; i++) {
			ok = RE_bake_engine(re, highpoly[i].ob, i, pixel_array_high,
			                    num_pixels, depth, pass_type, result);
			if (!ok) {
				BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2);
				goto cage_cleanup;
			}
		}

cage_cleanup:
		/* reverting data back */
		if ((ob_cage == NULL) && is_cage) {
			ob_low->modifiers = modifiers_original;

			while ((md = BLI_pophead(&modifiers_tmp))) {
				modifier_free(md);
			}
		}

		if (!ok) {
			goto cleanup;
		}
	}
	else {
		/* make sure low poly renders */
		ob_low->restrictflag &= ~OB_RESTRICT_RENDER;

		if (RE_bake_has_engine(re)) {
			ok = RE_bake_engine(re, ob_low, 0, pixel_array_low, num_pixels, depth, pass_type, result);
		}
		else {
			BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
			goto cleanup;
		}
	}

	/* normal space conversion
	 * the normals are expected to be in world space, +X +Y +Z */
	if (ok && pass_type == SCE_PASS_NORMAL) {
		switch (normal_space) {
			case R_BAKE_SPACE_WORLD:
			{
				/* Cycles internal format */
				if ((normal_swizzle[0] == R_BAKE_POSX) &&
				    (normal_swizzle[1] == R_BAKE_POSY) &&
				    (normal_swizzle[2] == R_BAKE_POSZ))
				{
					break;
				}
				else {
					RE_bake_normal_world_to_world(pixel_array_low, num_pixels,  depth, result, normal_swizzle);
				}
				break;
			}
			case R_BAKE_SPACE_OBJECT:
			{
				RE_bake_normal_world_to_object(pixel_array_low, num_pixels, depth, result, ob_low, normal_swizzle);
				break;
			}
			case R_BAKE_SPACE_TANGENT:
			{
				if (is_selected_to_active) {
					RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_low, normal_swizzle, ob_low->obmat);
				}
				else {
					/* from multiresolution */
					Mesh *me_nores = NULL;
					ModifierData *md = NULL;
					int mode;

					md = modifiers_findByType(ob_low, eModifierType_Multires);

					if (md) {
						mode = md->mode;
						md->mode &= ~eModifierMode_Render;
					}

					me_nores = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
					BKE_mesh_split_faces(me_nores);
					RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);

					RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat);
					BKE_libblock_free(bmain, me_nores);

					if (md)
						md->mode = mode;
				}
				break;
			}
			default:
				break;
		}
	}

	if (!ok) {
		BKE_reportf(reports, RPT_ERROR, "Problem baking object \"%s\"", ob_low->id.name + 2);
		op_result = OPERATOR_CANCELLED;
	}
	else {
		/* save the results */
		for (int i = 0; i < bake_images.size; i++) {
			BakeImage *bk_image = &bake_images.data[i];

			if (is_save_internal) {
				ok = write_internal_bake_pixels(
				         bk_image->image,
				         pixel_array_low + bk_image->offset,
				         result + bk_image->offset * depth,
				         bk_image->width, bk_image->height,
				         margin, is_clear, is_noncolor);

				/* might be read by UI to set active image for display */
				bake_update_image(sa, bk_image->image);

				if (!ok) {
					BKE_reportf(reports, RPT_ERROR,
					           "Problem saving the bake map internally for object \"%s\"", ob_low->id.name + 2);
					op_result = OPERATOR_CANCELLED;
				}
				else {
					BKE_report(reports, RPT_INFO,
					           "Baking map saved to internal image, save it externally or pack it");
					op_result = OPERATOR_FINISHED;
				}
			}
			/* save externally */
			else {
				BakeData *bake = &scene->r.bake;
				char name[FILE_MAX];

				BKE_image_path_from_imtype(name, filepath, bmain->name, 0, bake->im_format.imtype, true, false, NULL);

				if (is_automatic_name) {
					BLI_path_suffix(name, FILE_MAX, ob_low->id.name + 2, "_");
					BLI_path_suffix(name, FILE_MAX, identifier, "_");
				}

				if (is_split_materials) {
					if (bk_image->image) {
						BLI_path_suffix(name, FILE_MAX, bk_image->image->id.name + 2, "_");
					}
					else {
						if (ob_low->mat[i]) {
							BLI_path_suffix(name, FILE_MAX, ob_low->mat[i]->id.name + 2, "_");
						}
						else if (me_low->mat[i]) {
							BLI_path_suffix(name, FILE_MAX, me_low->mat[i]->id.name + 2, "_");
						}
						else {
							/* if everything else fails, use the material index */
							char tmp[4];
							sprintf(tmp, "%d", i % 1000);
							BLI_path_suffix(name, FILE_MAX, tmp, "_");
						}
					}
				}

				/* save it externally */
				ok = write_external_bake_pixels(
				        name,
				        pixel_array_low + bk_image->offset,
				        result + bk_image->offset * depth,
				        bk_image->width, bk_image->height,
				        margin, &bake->im_format, is_noncolor);

				if (!ok) {
					BKE_reportf(reports, RPT_ERROR, "Problem saving baked map in \"%s\"", name);
					op_result = OPERATOR_CANCELLED;
				}
				else {
					BKE_reportf(reports, RPT_INFO, "Baking map written to \"%s\"", name);
					op_result = OPERATOR_FINISHED;
				}

				if (!is_split_materials) {
					break;
				}
			}
		}
	}

	if (is_save_internal)
		refresh_images(&bake_images);

cleanup:

	if (highpoly) {
		int i;
		for (i = 0; i < tot_highpoly; i++) {
			highpoly[i].ob->restrictflag = highpoly[i].restrict_flag;

			if (highpoly[i].tri_mod)
				ED_object_modifier_remove(reports, bmain, highpoly[i].ob, highpoly[i].tri_mod);

			if (highpoly[i].me)
				BKE_libblock_free(bmain, highpoly[i].me);
		}
		MEM_freeN(highpoly);
	}

	ob_low->restrictflag = restrict_flag_low;

	if (ob_cage)
		ob_cage->restrictflag = restrict_flag_cage;

	if (pixel_array_low)
		MEM_freeN(pixel_array_low);

	if (pixel_array_high)
		MEM_freeN(pixel_array_high);

	if (bake_images.data)
		MEM_freeN(bake_images.data);

	if (bake_images.lookup)
		MEM_freeN(bake_images.lookup);

	if (result)
		MEM_freeN(result);

	if (me_low)
		BKE_libblock_free(bmain, me_low);

	if (me_cage)
		BKE_libblock_free(bmain, me_cage);

	return op_result;
}
Exemple #7
0
ModifierData *modifiers_getVirtualModifierList(Object *ob)
{
		/* Kinda hacky, but should be fine since we are never
	* reentrant and avoid free hassles.
		*/
	static ArmatureModifierData amd;
	static CurveModifierData cmd;
	static LatticeModifierData lmd;
	static ShapeKeyModifierData smd;
	static int init = 1;
	ModifierData *md;

	if (init) {
		md = modifier_new(eModifierType_Armature);
		amd = *((ArmatureModifierData*) md);
		modifier_free(md);

		md = modifier_new(eModifierType_Curve);
		cmd = *((CurveModifierData*) md);
		modifier_free(md);

		md = modifier_new(eModifierType_Lattice);
		lmd = *((LatticeModifierData*) md);
		modifier_free(md);

		md = modifier_new(eModifierType_ShapeKey);
		smd = *((ShapeKeyModifierData*) md);
		modifier_free(md);

		amd.modifier.mode |= eModifierMode_Virtual;
		cmd.modifier.mode |= eModifierMode_Virtual;
		lmd.modifier.mode |= eModifierMode_Virtual;
		smd.modifier.mode |= eModifierMode_Virtual;

		init = 0;
	}

	md = ob->modifiers.first;

	if(ob->parent) {
		if(ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL) {
			amd.object = ob->parent;
			amd.modifier.next = md;
			amd.deformflag= ((bArmature *)(ob->parent->data))->deformflag;
			md = &amd.modifier;
		} else if(ob->parent->type==OB_CURVE && ob->partype==PARSKEL) {
			cmd.object = ob->parent;
			cmd.defaxis = ob->trackflag + 1;
			cmd.modifier.next = md;
			md = &cmd.modifier;
		} else if(ob->parent->type==OB_LATTICE && ob->partype==PARSKEL) {
			lmd.object = ob->parent;
			lmd.modifier.next = md;
			md = &lmd.modifier;
		}
	}

	/* shape key modifier, not yet for curves */
	if(ELEM(ob->type, OB_MESH, OB_LATTICE) && ob_get_key(ob)) {
		if(ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE))
			smd.modifier.mode |= eModifierMode_Editmode|eModifierMode_OnCage;
		else
			smd.modifier.mode &= ~eModifierMode_Editmode|eModifierMode_OnCage;

		smd.modifier.next = md;
		md = &smd.modifier;
	}

	return md;
}
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;
}
Exemple #9
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;
}