Modifiers: Support applying modifiers for multi-user data

The current behaviour is to prevent multi-user data from having its
modifier applied.

Instead, with this patch, we now warn the user that if they want to
proceed the object will be made single-user.

Note that this only makes the object data single-user. Not the material
or actions.

As a future step we can apply the same behaviour for the Grease Pencil modifiers

Differential Revision: https://developer.blender.org/D14381
This commit is contained in:
Dalai Felinto 2022-03-30 11:06:10 +02:00
parent 218bcff32d
commit 35f34a3cf8
3 changed files with 45 additions and 11 deletions

View File

@ -381,6 +381,8 @@ struct Object *ED_object_add_type(struct bContext *C,
*/
void ED_object_single_user(struct Main *bmain, struct Scene *scene, struct Object *ob);
void ED_object_single_obdata_user(struct Main *bmain, struct Scene *scene, struct Object *ob);
/* object motion paths */
/**

View File

@ -1363,7 +1363,7 @@ void OBJECT_OT_modifier_move_to_index(wmOperatorType *ot)
/** \name Apply Modifier Operator
* \{ */
static bool modifier_apply_poll_ex(bContext *C, bool allow_shared)
static bool modifier_apply_poll(bContext *C)
{
if (!edit_modifier_poll_generic(C, &RNA_Modifier, 0, false, false)) {
return false;
@ -1378,10 +1378,6 @@ static bool modifier_apply_poll_ex(bContext *C, bool allow_shared)
CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied on override data");
return false;
}
if (!allow_shared && (ob->data != NULL) && ID_REAL_USERS(ob->data) > 1) {
CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied to multi-user data");
return false;
}
if (md != NULL) {
if ((ob->mode & OB_MODE_SCULPT) && (find_multires_modifier_before(scene, md)) &&
(BKE_modifier_is_same_topology(md) == false)) {
@ -1393,11 +1389,6 @@ static bool modifier_apply_poll_ex(bContext *C, bool allow_shared)
return true;
}
static bool modifier_apply_poll(bContext *C)
{
return modifier_apply_poll_ex(C, false);
}
static int modifier_apply_exec_ex(bContext *C, wmOperator *op, int apply_as, bool keep_modifier)
{
Main *bmain = CTX_data_main(C);
@ -1406,11 +1397,19 @@ static int modifier_apply_exec_ex(bContext *C, wmOperator *op, int apply_as, boo
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(op, ob, 0);
const bool do_report = RNA_boolean_get(op->ptr, "report");
const bool do_single_user = RNA_boolean_get(op->ptr, "single_user");
if (md == NULL) {
return OPERATOR_CANCELLED;
}
if (do_single_user && ID_REAL_USERS(ob->data) > 1) {
ED_object_single_obdata_user(bmain, scene, ob);
BKE_main_id_newptr_and_tag_clear(bmain);
WM_event_add_notifier(C, NC_WINDOW, NULL);
DEG_relations_tag_update(bmain);
}
int reports_len;
char name[MAX_NAME];
if (do_report) {
@ -1447,6 +1446,19 @@ static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *eve
{
int retval;
if (edit_modifier_invoke_properties_with_hover(C, op, event, &retval)) {
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
Object *ob = (ptr.owner_id != NULL) ? (Object *)ptr.owner_id : ED_object_active_context(C);
if ((ob->data != NULL) && ID_REAL_USERS(ob->data) > 1) {
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "single_user");
if (!RNA_property_is_set(op->ptr, prop)) {
RNA_property_boolean_set(op->ptr, prop, true);
}
if (RNA_property_boolean_get(op->ptr, prop)) {
return WM_operator_confirm_message(
C, op, "Make object data single-user and apply modifier");
}
}
return modifier_apply_exec(C, op);
}
return retval;
@ -1467,6 +1479,13 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
edit_modifier_properties(ot);
edit_modifier_report_property(ot);
PropertyRNA *prop = RNA_def_boolean(ot->srna,
"single_user",
false,
"Make Data Single User",
"Make the object's data single user if needed");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
@ -1477,7 +1496,7 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
static bool modifier_apply_as_shapekey_poll(bContext *C)
{
return modifier_apply_poll_ex(C, true);
return modifier_apply_poll(C);
}
static int modifier_apply_as_shapekey_exec(bContext *C, wmOperator *op)

View File

@ -1893,6 +1893,19 @@ static void single_obdata_users(
}
}
void ED_object_single_obdata_user(Main *bmain, Scene *scene, Object *ob)
{
FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
ob_iter->flag &= ~OB_DONE;
}
FOREACH_SCENE_OBJECT_END;
/* Tag only the one object. */
ob->flag |= OB_DONE;
single_obdata_users(bmain, scene, NULL, NULL, OB_DONE);
}
static void single_object_action_users(
Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
{