UI: Add Modifiers submenu to 3D view header
Add a menu similar to the "Object > Constraints" menu that allows adding, copying, and clearing modifiers. The "copy all modifiers to selected" and "clear modifiers" operators are new, to mirror the functionality we already have for constraints. The "Add" menu is the same that's used in the property editor. In the 3D view, modifiers are always added to all selected objects. Part of #120230 Pull Request: https://projects.blender.org/blender/blender/pulls/121286
This commit is contained in:
@@ -56,7 +56,10 @@ class OBJECT_MT_modifier_add(ModifierAddMenu, Menu):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
ob_type = context.object.type
|
||||
ob = context.object
|
||||
if not ob:
|
||||
return
|
||||
ob_type = ob.type
|
||||
geometry_nodes_supported = ob_type in {
|
||||
'MESH', 'CURVE', 'CURVES',
|
||||
'FONT', 'VOLUME', 'POINTCLOUD', 'GREASEPENCIL',
|
||||
|
||||
@@ -2889,6 +2889,7 @@ class VIEW3D_MT_object(Menu):
|
||||
layout.menu("VIEW3D_MT_object_relations")
|
||||
layout.menu("VIEW3D_MT_object_parent")
|
||||
layout.menu("VIEW3D_MT_object_constraints")
|
||||
layout.menu("VIEW3D_MT_object_modifiers")
|
||||
layout.menu("VIEW3D_MT_object_track")
|
||||
layout.menu("VIEW3D_MT_make_links")
|
||||
|
||||
@@ -3357,6 +3358,20 @@ class VIEW3D_MT_object_constraints(Menu):
|
||||
layout.operator("object.constraints_clear")
|
||||
|
||||
|
||||
class VIEW3D_MT_object_modifiers(Menu):
|
||||
bl_label = "Modifiers"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
layout.menu("OBJECT_MT_modifier_add", text="Add")
|
||||
layout.operator("object.modifiers_copy_to_selected", text="Copy to Selected")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("object.modifiers_clear")
|
||||
|
||||
|
||||
class VIEW3D_MT_object_quick_effects(Menu):
|
||||
bl_label = "Quick Effects"
|
||||
|
||||
@@ -9136,6 +9151,7 @@ classes = (
|
||||
VIEW3D_MT_object_track,
|
||||
VIEW3D_MT_object_collection,
|
||||
VIEW3D_MT_object_constraints,
|
||||
VIEW3D_MT_object_modifiers,
|
||||
VIEW3D_MT_object_quick_effects,
|
||||
VIEW3D_MT_object_showhide,
|
||||
VIEW3D_MT_object_cleanup,
|
||||
|
||||
@@ -338,7 +338,7 @@ static int modifier_add_asset_exec(bContext *C, wmOperator *op)
|
||||
|
||||
static int modifier_add_asset_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
if (event->modifier & KM_ALT) {
|
||||
if (event->modifier & KM_ALT || CTX_wm_view3d(C)) {
|
||||
RNA_boolean_set(op->ptr, "use_selected_objects", true);
|
||||
}
|
||||
return modifier_add_asset_exec(C, op);
|
||||
|
||||
@@ -195,6 +195,7 @@ ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type);
|
||||
|
||||
void OBJECT_OT_modifier_add(wmOperatorType *ot);
|
||||
void OBJECT_OT_modifier_remove(wmOperatorType *ot);
|
||||
void OBJECT_OT_modifiers_clear(wmOperatorType *ot);
|
||||
void OBJECT_OT_modifier_move_up(wmOperatorType *ot);
|
||||
void OBJECT_OT_modifier_move_down(wmOperatorType *ot);
|
||||
void OBJECT_OT_modifier_move_to_index(wmOperatorType *ot);
|
||||
@@ -203,6 +204,7 @@ void OBJECT_OT_modifier_apply_as_shapekey(wmOperatorType *ot);
|
||||
void OBJECT_OT_modifier_convert(wmOperatorType *ot);
|
||||
void OBJECT_OT_modifier_copy(wmOperatorType *ot);
|
||||
void OBJECT_OT_modifier_copy_to_selected(wmOperatorType *ot);
|
||||
void OBJECT_OT_modifiers_copy_to_selected(wmOperatorType *ot);
|
||||
void OBJECT_OT_modifier_set_active(wmOperatorType *ot);
|
||||
void OBJECT_OT_multires_subdivide(wmOperatorType *ot);
|
||||
void OBJECT_OT_multires_reshape(wmOperatorType *ot);
|
||||
|
||||
@@ -1290,7 +1290,7 @@ void modifier_register_use_selected_objects_prop(wmOperatorType *ot)
|
||||
false,
|
||||
"Selected Objects",
|
||||
"Affect all selected objects instead of just the active object");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
@@ -1321,7 +1321,7 @@ static int modifier_add_exec(bContext *C, wmOperator *op)
|
||||
|
||||
static int modifier_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
if (event->modifier & KM_ALT) {
|
||||
if (event->modifier & KM_ALT || CTX_wm_view3d(C)) {
|
||||
RNA_boolean_set(op->ptr, "use_selected_objects", true);
|
||||
}
|
||||
if (!RNA_struct_property_is_set(op->ptr, "type")) {
|
||||
@@ -1641,6 +1641,32 @@ void OBJECT_OT_modifier_remove(wmOperatorType *ot)
|
||||
modifier_register_use_selected_objects_prop(ot);
|
||||
}
|
||||
|
||||
static int modifiers_clear_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
CTX_DATA_BEGIN (C, Object *, object, selected_editable_objects) {
|
||||
modifiers_clear(bmain, scene, object);
|
||||
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, object);
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void OBJECT_OT_modifiers_clear(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Clear Object Modifiers";
|
||||
ot->description = "Clear all modifiers from the selected objects";
|
||||
ot->idname = "OBJECT_OT_modifiers_clear";
|
||||
|
||||
ot->exec = modifiers_clear_exec;
|
||||
ot->poll = ED_operator_object_active_local_editable;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
@@ -2287,6 +2313,60 @@ void OBJECT_OT_modifier_copy_to_selected(wmOperatorType *ot)
|
||||
edit_modifier_properties(ot);
|
||||
}
|
||||
|
||||
static int object_modifiers_copy_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
Object *active_object = context_active_object(C);
|
||||
|
||||
Vector<PointerRNA> selected_objects;
|
||||
CTX_data_selected_objects(C, &selected_objects);
|
||||
CTX_DATA_BEGIN (C, Object *, object, selected_objects) {
|
||||
if (object == active_object) {
|
||||
continue;
|
||||
}
|
||||
LISTBASE_FOREACH (const ModifierData *, md, &active_object->modifiers) {
|
||||
if (modifier_copy_to_object(bmain, scene, active_object, md, object, op->reports)) {
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER | NA_ADDED, object);
|
||||
}
|
||||
}
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
||||
DEG_relations_tag_update(bmain);
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER | NA_ADDED, nullptr);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static bool modifiers_copy_to_selected_poll(bContext *C)
|
||||
{
|
||||
if (!ED_operator_object_active_editable(C)) {
|
||||
return false;
|
||||
}
|
||||
Object *active_object = context_active_object(C);
|
||||
if (BLI_listbase_is_empty(&active_object->modifiers)) {
|
||||
CTX_wm_operator_poll_msg_set(C, "Active object has no modifiers");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void OBJECT_OT_modifiers_copy_to_selected(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Copy Modifiers to Selected Objects";
|
||||
ot->idname = "OBJECT_OT_modifiers_copy_to_selected";
|
||||
ot->description = "Copy modifiers to other selected objects";
|
||||
|
||||
ot->exec = object_modifiers_copy_exec;
|
||||
ot->poll = modifiers_copy_to_selected_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
@@ -119,6 +119,7 @@ void operatortypes_object()
|
||||
|
||||
WM_operatortype_append(OBJECT_OT_modifier_add);
|
||||
WM_operatortype_append(OBJECT_OT_modifier_remove);
|
||||
WM_operatortype_append(OBJECT_OT_modifiers_clear);
|
||||
WM_operatortype_append(OBJECT_OT_modifier_move_up);
|
||||
WM_operatortype_append(OBJECT_OT_modifier_move_down);
|
||||
WM_operatortype_append(OBJECT_OT_modifier_move_to_index);
|
||||
@@ -127,6 +128,7 @@ void operatortypes_object()
|
||||
WM_operatortype_append(OBJECT_OT_modifier_convert);
|
||||
WM_operatortype_append(OBJECT_OT_modifier_copy);
|
||||
WM_operatortype_append(OBJECT_OT_modifier_copy_to_selected);
|
||||
WM_operatortype_append(OBJECT_OT_modifiers_copy_to_selected);
|
||||
WM_operatortype_append(OBJECT_OT_modifier_set_active);
|
||||
WM_operatortype_append(OBJECT_OT_multires_subdivide);
|
||||
WM_operatortype_append(OBJECT_OT_multires_reshape);
|
||||
|
||||
Reference in New Issue
Block a user