Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/object/object_modifier.c')
-rw-r--r--source/blender/editors/object/object_modifier.c189
1 files changed, 136 insertions, 53 deletions
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index d6b5fb9fc10..aab3d8afb22 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -173,7 +173,100 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
return new_md;
}
-static int object_modifier_remove(Object *ob, ModifierData *md, int *sort_depsgraph)
+/* Return TRUE if the object has a modifier of type 'type' other than
+ * the modifier pointed to be 'exclude', otherwise returns FALSE. */
+static int object_has_modifier(const Object *ob, const ModifierData *exclude,
+ ModifierType type)
+{
+ ModifierData *md;
+
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if ((md != exclude) && (md->type == type))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* If the object data of 'orig_ob' has other users, run 'callback' on
+ * each of them.
+ *
+ * If include_orig is TRUE, the callback will run on 'orig_ob' too.
+ *
+ * If the callback ever returns TRUE, iteration will stop and the
+ * function value will be TRUE. Otherwise the function returns FALSE.
+ */
+int ED_object_iter_other(Main *bmain, Object *orig_ob, int include_orig,
+ int (*callback)(Object *ob, void *callback_data),
+ void *callback_data)
+{
+ ID *ob_data_id = orig_ob->data;
+ int users = ob_data_id->us;
+
+ if (ob_data_id->flag & LIB_FAKEUSER)
+ users--;
+
+ /* First check that the object's data has multiple users */
+ if (users > 1) {
+ Object *ob;
+ int totfound = include_orig ? 0 : 1;
+
+ for (ob = bmain->object.first; ob && totfound < users;
+ ob = ob->id.next)
+ {
+ if (((ob != orig_ob) || include_orig) &&
+ (ob->data == orig_ob->data))
+ {
+ if (callback(ob, callback_data))
+ return TRUE;
+
+ totfound++;
+ }
+ }
+ }
+ else if (include_orig) {
+ return callback(orig_ob, callback_data);
+ }
+
+ return FALSE;
+}
+
+static int object_has_modifier_cb(Object *ob, void *data)
+{
+ ModifierType type = *((ModifierType*)data);
+
+ return object_has_modifier(ob, NULL, type);
+}
+
+/* Use with ED_object_iter_other(). Sets the total number of levels
+ * for any multires modifiers on the object to the int pointed to by
+ * callback_data. */
+int ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v)
+{
+ ModifierData *md;
+ int totlevel = *((int*)totlevel_v);
+
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Multires) {
+ multires_set_tot_level(ob, (MultiresModifierData *)md, totlevel);
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+ }
+ return FALSE;
+}
+
+/* Return TRUE if no modifier of type 'type' other than 'exclude' */
+static int object_modifier_safe_to_delete(Main *bmain, Object *ob,
+ ModifierData *exclude,
+ ModifierType type)
+{
+ return (!object_has_modifier(ob, exclude, type) &&
+ !ED_object_iter_other(bmain, ob, FALSE,
+ object_has_modifier_cb, &type));
+}
+
+static int object_modifier_remove(Main *bmain, Object *ob, ModifierData *md,
+ int *sort_depsgraph)
{
ModifierData *obmd;
@@ -218,33 +311,13 @@ static int object_modifier_remove(Object *ob, ModifierData *md, int *sort_depsgr
ob->dt = OB_TEXTURE;
}
else if (md->type == eModifierType_Multires) {
- int ok = 1;
- ModifierData *tmpmd;
-
- /* ensure MDISPS CustomData layer isn'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) {
+ /* Delete MDisps layer if not used by another multires modifier */
+ if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Multires))
multires_customdata_delete(ob->data);
- }
}
else if (md->type == eModifierType_Skin) {
- int ok = 1;
- ModifierData *tmpmd;
-
- /* ensure skin CustomData layer isn't used by another skin modifier */
- for (tmpmd = ob->modifiers.first; tmpmd; tmpmd = tmpmd->next) {
- if (tmpmd != md && tmpmd->type == eModifierType_Skin) {
- ok = 0;
- break;
- }
- }
-
- if (ok)
+ /* Delete MVertSkin layer if not used by another skin modifier */
+ if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Skin))
modifier_skin_customdata_delete(ob);
}
@@ -265,7 +338,7 @@ int ED_object_modifier_remove(ReportList *reports, Main *bmain, Scene *scene, Ob
int sort_depsgraph = 0;
int ok;
- ok = object_modifier_remove(ob, md, &sort_depsgraph);
+ ok = object_modifier_remove(bmain, ob, md, &sort_depsgraph);
if (!ok) {
BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", ob->id.name, md->name);
@@ -294,7 +367,7 @@ void ED_object_modifier_clear(Main *bmain, Scene *scene, Object *ob)
next_md = md->next;
- object_modifier_remove(ob, md, &sort_depsgraph);
+ object_modifier_remove(bmain, ob, md, &sort_depsgraph);
md = next_md;
}
@@ -771,19 +844,21 @@ static void edit_modifier_properties(wmOperatorType *ot)
static int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
ModifierData *md;
- if (RNA_struct_property_is_set(op->ptr, "modifier"))
- return 1;
-
- if (ptr.data) {
- md = ptr.data;
- RNA_string_set(op->ptr, "modifier", md->name);
- return 1;
+ if (RNA_struct_property_is_set(op->ptr, "modifier")) {
+ return TRUE;
}
-
- return 0;
+ else {
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
+ if (ptr.data) {
+ md = ptr.data;
+ RNA_string_set(op->ptr, "modifier", md->name);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
}
static ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
@@ -843,7 +918,7 @@ void OBJECT_OT_modifier_remove(wmOperatorType *ot)
ot->poll = edit_modifier_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
@@ -882,7 +957,7 @@ void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
ot->poll = edit_modifier_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
@@ -921,7 +996,7 @@ void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
ot->poll = edit_modifier_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
@@ -969,7 +1044,7 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
ot->poll = edit_modifier_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
RNA_def_enum(ot->srna, "apply_as", modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
edit_modifier_properties(ot);
@@ -1012,7 +1087,7 @@ void OBJECT_OT_modifier_convert(wmOperatorType *ot)
ot->poll = edit_modifier_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
@@ -1051,7 +1126,7 @@ void OBJECT_OT_modifier_copy(wmOperatorType *ot)
ot->poll = edit_modifier_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
@@ -1071,6 +1146,10 @@ static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
multiresModifier_del_levels(mmd, ob, 1);
+
+ ED_object_iter_other(CTX_data_main(C), ob, TRUE,
+ ED_object_multires_update_totlevels_cb,
+ &mmd->totlvl);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
@@ -1096,7 +1175,7 @@ void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
ot->exec = multires_higher_levels_delete_exec;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
@@ -1112,6 +1191,10 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op)
multiresModifier_subdivide(mmd, ob, 0, mmd->simple);
+ ED_object_iter_other(CTX_data_main(C), ob, TRUE,
+ ED_object_multires_update_totlevels_cb,
+ &mmd->totlvl);
+
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
@@ -1137,7 +1220,7 @@ void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
ot->exec = multires_subdivide_exec;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
@@ -1201,7 +1284,7 @@ void OBJECT_OT_multires_reshape(wmOperatorType *ot)
ot->exec = multires_reshape_exec;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
@@ -1276,7 +1359,7 @@ void OBJECT_OT_multires_external_save(wmOperatorType *ot)
ot->poll = multires_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
WM_operator_properties_filesel(ot, FOLDERFILE | BTXFILE, FILE_SPECIAL, FILE_SAVE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
edit_modifier_properties(ot);
@@ -1348,7 +1431,7 @@ void OBJECT_OT_multires_base_apply(wmOperatorType *ot)
ot->exec = multires_base_apply_exec;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
@@ -1673,7 +1756,7 @@ static Object *modifier_skin_armature_create(struct Scene *scene,
edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited");
/* note: we use EditBones here, easier to set them up and use
- * edit-armature functions to convert back to regular bones */
+ * edit-armature functions to convert back to regular bones */
for (v = 0; v < me->totvert; v++) {
if (mvert_skin[v].flag & MVERT_SKIN_ROOT) {
EditBone *bone = NULL;
@@ -1763,7 +1846,7 @@ void OBJECT_OT_skin_armature_create(wmOperatorType *ot)
ot->exec = skin_armature_create_exec;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
@@ -1858,7 +1941,7 @@ void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
ot->exec = meshdeform_bind_exec;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
@@ -1905,7 +1988,7 @@ void OBJECT_OT_explode_refresh(wmOperatorType *ot)
ot->exec = explode_refresh_exec;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
@@ -2120,7 +2203,7 @@ void OBJECT_OT_ocean_bake(wmOperatorType *ot)
ot->exec = ocean_bake_exec;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
RNA_def_boolean(ot->srna, "free", FALSE, "Free", "Free the bake, rather than generating it");