UI: Add shortcuts for constraint panels

Only the delete shortcut applies here, although the move up and down
operators can optionally be assigned in the keymap.

See rB1fa40c9f8a81 for more details and rB5d2005cbb54b for the
grease pencil modifier panel implementation, which is the same.
Some refactoring of the constraint delete operator was necessary,
including adding an invoke function.

Differential Revision: https://developer.blender.org/D8238
This commit is contained in:
Hans Goudey 2020-07-16 14:07:47 -04:00
parent b13bbb22e4
commit 608d9b5aa1
Notes: blender-bot 2023-02-14 11:42:40 +01:00
Referenced by commit 6dc7266cf1, Fix T80464: Crash deleting bone constraints when the armature layer is
Referenced by issue #80464, Deleting bone constraints when the armature layer isn't active crashes Blender
Referenced by issue #78326, Add shortcuts for modifier panels
3 changed files with 106 additions and 33 deletions

View File

@ -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

View File

@ -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, &region->panels, panel_idname, i, NULL);
sa, region, &region->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;
}
}
}

View File

@ -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)