diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index c8d0843e8dd..f9c5e077625 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -749,6 +749,9 @@ def km_property_editor(_params): # ShaderFX panels ("object.shaderfx_remove", {"type": 'X', "value": 'PRESS'}, {"properties": [("report", True)]}), ("object.shaderfx_remove", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("report", True)]}), + # Constraint panels + ("constraint.delete", {"type": 'X', "value": 'PRESS'}, {"properties": [("report", True)]}), + ("constraint.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("report", True)]}), ]) return keymap diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 3c0b5bd3027..21696b9c1ab 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2027,6 +2027,7 @@ void uiTemplateConstraints(uiLayout *UNUSED(layout), bContext *C, bool use_bone_ ScrArea *sa = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); + Object *ob = ED_object_active_context(C); ListBase *constraints = get_constraints(C, use_bone_constraints); /* Switch between the bone panel ID function and the object panel ID function. */ @@ -2042,11 +2043,15 @@ void uiTemplateConstraints(uiLayout *UNUSED(layout), bContext *C, bool use_bone_ char panel_idname[MAX_NAME]; panel_id_func(con, panel_idname); + /* Create custom data RNA pointer. */ + PointerRNA *con_ptr = MEM_mallocN(sizeof(PointerRNA), "panel customdata"); + RNA_pointer_create(&ob->id, &RNA_Constraint, con, con_ptr); + Panel *new_panel = UI_panel_add_instanced( - sa, region, ®ion->panels, panel_idname, i, NULL); + sa, region, ®ion->panels, panel_idname, i, con_ptr); + if (new_panel) { - /* Set the list panel functionality function pointers since we don't do it with - * python. */ + /* Set the list panel functionality function pointers since we don't do it with python. */ new_panel->type->set_list_data_expand_flag = set_constraint_expand_flag; new_panel->type->get_list_data_expand_flag = get_constraint_expand_flag; new_panel->type->reorder = constraint_reorder; @@ -2062,6 +2067,22 @@ void uiTemplateConstraints(uiLayout *UNUSED(layout), bContext *C, bool use_bone_ UI_panel_set_expand_from_list_data(C, panel); } } + + /* Assuming there's only one group of instanced panels, update the custom data pointers. */ + Panel *panel = region->panels.first; + LISTBASE_FOREACH (bConstraint *, con, constraints) { + /* Move to the next instanced panel corresponding to the next constraint. */ + while ((panel->type == NULL) || !(panel->type->flag & PNL_INSTANCED)) { + panel = panel->next; + BLI_assert(panel != NULL); /* There shouldn't be fewer panels than constraint panels. */ + } + + PointerRNA *con_ptr = MEM_mallocN(sizeof(PointerRNA), "constraint panel customdata"); + RNA_pointer_create(&ob->id, &RNA_Constraint, con, con_ptr); + UI_panel_custom_data_set(panel, con_ptr); + + panel = panel->next; + } } } diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 90ea71ae5c5..bcb1b8afbdd 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -702,7 +702,17 @@ static void edit_constraint_properties(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); } -static bool edit_constraint_invoke_properties(bContext *C, wmOperator *op) +static void edit_constraint_report_property(wmOperatorType *ot) +{ + PropertyRNA *prop = RNA_def_boolean( + ot->srna, "report", false, "Report", "Create a notification after the operation"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); +} + +static bool edit_constraint_invoke_properties(bContext *C, + wmOperator *op, + const wmEvent *event, + int *r_retval) { PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); @@ -730,6 +740,31 @@ static bool edit_constraint_invoke_properties(bContext *C, wmOperator *op) return true; } + /* Check the custom data of panels under the mouse for a modifier. */ + if (event != NULL) { + PointerRNA *panel_ptr = UI_region_panel_custom_data_under_cursor(C, event); + + if (!(panel_ptr == NULL || RNA_pointer_is_null(panel_ptr))) { + if (RNA_struct_is_a(panel_ptr->type, &RNA_Constraint)) { + con = panel_ptr->data; + RNA_string_set(op->ptr, "constraint", con->name); + list = ED_object_constraint_list_from_constraint(ob, con, NULL); + RNA_enum_set(op->ptr, + "owner", + (&ob->constraints == list) ? EDIT_CONSTRAINT_OWNER_OBJECT : + EDIT_CONSTRAINT_OWNER_BONE); + + return true; + } + + BLI_assert(r_retval != NULL); /* We need the return value in this case. */ + if (r_retval != NULL) { + *r_retval = (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED); + } + return false; + } + } + return false; } @@ -813,7 +848,7 @@ static int stretchto_reset_exec(bContext *C, wmOperator *op) static int stretchto_reset_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_constraint_invoke_properties(C, op)) { + if (edit_constraint_invoke_properties(C, op, NULL, NULL)) { return stretchto_reset_exec(C, op); } return OPERATOR_CANCELLED; @@ -868,7 +903,7 @@ static int limitdistance_reset_exec(bContext *C, wmOperator *op) static int limitdistance_reset_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_constraint_invoke_properties(C, op)) { + if (edit_constraint_invoke_properties(C, op, NULL, NULL)) { return limitdistance_reset_exec(C, op); } return OPERATOR_CANCELLED; @@ -946,7 +981,7 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op) static int childof_set_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_constraint_invoke_properties(C, op)) { + if (edit_constraint_invoke_properties(C, op, NULL, NULL)) { return childof_set_inverse_exec(C, op); } return OPERATOR_CANCELLED; @@ -995,7 +1030,7 @@ static int childof_clear_inverse_exec(bContext *C, wmOperator *op) static int childof_clear_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_constraint_invoke_properties(C, op)) { + if (edit_constraint_invoke_properties(C, op, NULL, NULL)) { return childof_clear_inverse_exec(C, op); } return OPERATOR_CANCELLED; @@ -1120,7 +1155,7 @@ static int followpath_path_animate_invoke(bContext *C, const wmEvent *UNUSED(event)) { /* hook up invoke properties for figuring out which constraint we're dealing with */ - if (edit_constraint_invoke_properties(C, op)) { + if (edit_constraint_invoke_properties(C, op, NULL, NULL)) { return followpath_path_animate_exec(C, op); } return OPERATOR_CANCELLED; @@ -1201,7 +1236,7 @@ static int objectsolver_set_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_constraint_invoke_properties(C, op)) { + if (edit_constraint_invoke_properties(C, op, NULL, NULL)) { return objectsolver_set_inverse_exec(C, op); } return OPERATOR_CANCELLED; @@ -1257,7 +1292,7 @@ static int objectsolver_clear_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_constraint_invoke_properties(C, op)) { + if (edit_constraint_invoke_properties(C, op, NULL, NULL)) { return objectsolver_clear_inverse_exec(C, op); } return OPERATOR_CANCELLED; @@ -1374,26 +1409,23 @@ void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstr DEG_relations_tag_update(bmain); } -static bool constraint_poll(bContext *C) -{ - PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); - return (ptr.owner_id && ptr.data); -} - /** \} */ /* ------------------------------------------------------------------- */ /** \name Delete Constraint Operator * \{ */ -static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op)) +static int constraint_delete_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); - Object *ob = (Object *)ptr.owner_id; - bConstraint *con = ptr.data; + Object *ob = ED_object_active_context(C); + bConstraint *con = edit_constraint_property_get(op, ob, 0); ListBase *lb = ED_object_constraint_list_from_constraint(ob, con, NULL); + /* Store name temporarily for report. */ + char name[MAX_NAME]; + strcpy(name, con->name); + /* free the constraint */ if (BKE_constraint_remove_ex(lb, ob, con, true)) { /* there's no active constraint now, so make sure this is the case */ @@ -1407,12 +1439,25 @@ static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op)) /* notifiers */ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob); + if (RNA_boolean_get(op->ptr, "report")) { + BKE_reportf(op->reports, RPT_INFO, "Removed constraint: %s", name); + } + return OPERATOR_FINISHED; } /* couldn't remove due to some invalid data */ return OPERATOR_CANCELLED; } +static int constraint_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + int retval; + if (edit_constraint_invoke_properties(C, op, event, &retval)) { + return constraint_delete_exec(C, op); + } + return OPERATOR_CANCELLED; +} + void CONSTRAINT_OT_delete(wmOperatorType *ot) { /* identifiers */ @@ -1421,11 +1466,14 @@ void CONSTRAINT_OT_delete(wmOperatorType *ot) ot->description = "Remove constraint from constraint stack"; /* callbacks */ + ot->invoke = constraint_delete_invoke; ot->exec = constraint_delete_exec; - ot->poll = constraint_poll; + ot->poll = edit_constraint_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + edit_constraint_properties(ot); + edit_constraint_report_property(ot); } /** \} */ @@ -1455,12 +1503,13 @@ static int constraint_move_down_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int constraint_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int constraint_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_constraint_invoke_properties(C, op)) { + int retval; + if (edit_constraint_invoke_properties(C, op, event, &retval)) { return constraint_move_down_exec(C, op); } - return OPERATOR_CANCELLED; + return retval; } void CONSTRAINT_OT_move_down(wmOperatorType *ot) @@ -1509,12 +1558,13 @@ static int constraint_move_up_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int constraint_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int constraint_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_constraint_invoke_properties(C, op)) { + int retval; + if (edit_constraint_invoke_properties(C, op, event, &retval)) { return constraint_move_up_exec(C, op); } - return OPERATOR_CANCELLED; + return retval; } void CONSTRAINT_OT_move_up(wmOperatorType *ot) @@ -1565,14 +1615,13 @@ static int constraint_move_to_index_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int constraint_move_to_index_invoke(bContext *C, - wmOperator *op, - const wmEvent *UNUSED(event)) +static int constraint_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_constraint_invoke_properties(C, op)) { + int retval; + if (edit_constraint_invoke_properties(C, op, event, &retval)) { return constraint_move_to_index_exec(C, op); } - return OPERATOR_CANCELLED; + return retval; } void CONSTRAINT_OT_move_to_index(wmOperatorType *ot)