diff options
author | Hans Goudey <h.goudey@me.com> | 2020-06-29 22:00:25 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2020-06-29 22:00:25 +0300 |
commit | 1fa40c9f8a81036476d5051b09ff15e27b628012 (patch) | |
tree | 37a5fa840d8eae820b5aff81fbe4e3e36599aab3 /source/blender | |
parent | 4f8a881715ca71599c1f4ee82b76cbce0a02b4d9 (diff) |
UI: Add shortcuts for modifier panels
The shortcuts act on the modifier with its panel under the mouse.
The following shortcuts are enabled by default:
- Remove modifier: X, Delete
- Apply modifier: Ctrl A
- Duplicate modifier: Shift D
More shortcuts can be added in the keymap.
Each panel can now store a custom data RNA pointer, and a new
function is added to get the custom data for the panel under the
cursor. This custom data could be used to refactor the "List Panel
System" to generalize it and integrate it further with RNA.
The same functionality will be added in further commits where it
applies to constraints, grease pencil modifiers, and effects.
Differential Revision: https://developer.blender.org/D8031
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/intern/screen.c | 26 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 1 | ||||
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 7 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_layout.c | 1 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_panel.c | 81 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_templates.c | 58 | ||||
-rw-r--r-- | source/blender/editors/object/object_data_transfer.c | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_intern.h | 4 | ||||
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 112 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_screen_types.h | 10 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_ui_common.c | 14 |
11 files changed, 245 insertions, 71 deletions
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index bfc0d437994..c510b3a2dfb 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -393,6 +393,7 @@ static void panel_list_copy(ListBase *newlb, const ListBase *lb) Panel *panel = lb->first; for (; new_panel; new_panel = new_panel->next, panel = panel->next) { new_panel->activedata = NULL; + new_panel->runtime.custom_data_ptr = NULL; panel_list_copy(&new_panel->children, &panel->children); } } @@ -575,18 +576,25 @@ void BKE_region_callback_free_gizmomap_set(void (*callback)(struct wmGizmoMap *) region_free_gizmomap_callback = callback; } -void BKE_area_region_panels_free(ListBase *lb) +static void area_region_panels_free_recursive(Panel *panel) { - Panel *panel, *panel_next; - for (panel = lb->first; panel; panel = panel_next) { - panel_next = panel->next; - if (panel->activedata) { - MEM_freeN(panel->activedata); - } - BKE_area_region_panels_free(&panel->children); + MEM_SAFE_FREE(panel->activedata); + + LISTBASE_FOREACH_MUTABLE (Panel *, child_panel, &panel->children) { + area_region_panels_free_recursive(child_panel); } - BLI_freelistN(lb); + MEM_freeN(panel); +} + +void BKE_area_region_panels_free(ListBase *lb) +{ + LISTBASE_FOREACH_MUTABLE (Panel *, panel, lb) { + /* Free custom data just for parent panels to avoid a double free. */ + MEM_SAFE_FREE(panel->runtime.custom_data_ptr); + area_region_panels_free_recursive(panel); + } + BLI_listbase_clear(lb); } /* not region itself */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index e9389561b47..e4822c4cb7f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7015,6 +7015,7 @@ static void direct_link_panel_list(BlendDataReader *reader, ListBase *lb) panel->runtime_flag = 0; panel->activedata = NULL; panel->type = NULL; + panel->runtime.custom_data_ptr = NULL; direct_link_panel_list(reader, &panel->children); } } diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index bcbee51246e..1cedd4e122f 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1706,12 +1706,17 @@ void UI_panel_category_draw_all(struct ARegion *region, const char *category_id_ struct PanelType *UI_paneltype_find(int space_id, int region_id, const char *idname); +struct PointerRNA *UI_region_panel_custom_data_under_cursor(const struct bContext *C, + const struct wmEvent *event); +void UI_panel_custom_data_set(struct Panel *panel, struct PointerRNA *custom_data); + /* Polyinstantiated panels for representing a list of data. */ struct Panel *UI_panel_add_instanced(struct ScrArea *area, struct ARegion *region, struct ListBase *panels, char *panel_idname, - int list_index); + int list_index, + struct PointerRNA *custom_data); void UI_panels_free_instanced(struct bContext *C, struct ARegion *region); #define LIST_PANEL_UNIQUE_STR_LEN 4 diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 6aefef197df..771e9383b8a 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -5576,6 +5576,7 @@ static void ui_paneltype_draw_impl(bContext *C, PanelType *pt, uiLayout *layout, panel->layout = layout; pt->draw(C, panel); panel->layout = NULL; + BLI_assert(panel->runtime.custom_data_ptr = NULL); MEM_freeN(panel); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 9ff678df0db..4bf88c76857 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -245,20 +245,25 @@ static bool panels_need_realign(ScrArea *area, ARegion *region, Panel **r_panel_ /********* Functions for instanced panels. ***********/ -static Panel *UI_panel_add_instanced_ex( - ScrArea *area, ARegion *region, ListBase *panels, PanelType *panel_type, int list_index) +static Panel *UI_panel_add_instanced_ex(ScrArea *area, + ARegion *region, + ListBase *panels, + PanelType *panel_type, + int list_index, + PointerRNA *custom_data) { Panel *panel = MEM_callocN(sizeof(Panel), "instanced panel"); panel->type = panel_type; BLI_strncpy(panel->panelname, panel_type->idname, sizeof(panel->panelname)); panel->runtime.list_index = list_index; + panel->runtime.custom_data_ptr = custom_data; /* Add the panel's children too. Although they aren't instanced panels, we can still use this * function to create them, as UI_panel_begin does other things we don't need to do. */ LISTBASE_FOREACH (LinkData *, child, &panel_type->children) { PanelType *child_type = child->data; - UI_panel_add_instanced_ex(area, region, &panel->children, child_type, list_index); + UI_panel_add_instanced_ex(area, region, &panel->children, child_type, list_index, custom_data); } /* Make sure the panel is added to the end of the display-order as well. This is needed for @@ -283,8 +288,12 @@ static Panel *UI_panel_add_instanced_ex( * Called in situations where panels need to be added dynamically rather than having only one panel * corresponding to each PanelType. */ -Panel *UI_panel_add_instanced( - ScrArea *area, ARegion *region, ListBase *panels, char *panel_idname, int list_index) +Panel *UI_panel_add_instanced(ScrArea *area, + ARegion *region, + ListBase *panels, + char *panel_idname, + int list_index, + PointerRNA *custom_data) { ARegionType *region_type = region->type; @@ -296,7 +305,7 @@ Panel *UI_panel_add_instanced( return NULL; } - return UI_panel_add_instanced_ex(area, region, panels, panel_type, list_index); + return UI_panel_add_instanced_ex(area, region, panels, panel_type, list_index, custom_data); } /** @@ -332,7 +341,8 @@ static void panel_free_block(ARegion *region, Panel *panel) } /** - * Free a panel and it's children. + * Free a panel and it's children. Custom data is shared by the panel and its children + * and is freed by #UI_panels_free_instanced. * * \note The only panels that should need to be deleted at runtime are panels with the * #PNL_INSTANCED flag set. @@ -369,6 +379,13 @@ void UI_panels_free_instanced(bContext *C, ARegion *region) if (C != NULL && panel->activedata != NULL) { panel_activate_state(C, panel, PANEL_STATE_EXIT); } + + /* Free panel's custom data. */ + if (panel->runtime.custom_data_ptr != NULL) { + MEM_freeN(panel->runtime.custom_data_ptr); + } + + /* Free the panel and its subpanels. */ panel_delete(region, ®ion->panels, panel); } } @@ -2886,6 +2903,56 @@ int ui_handler_panel_region(bContext *C, return retval; } +static void ui_panel_custom_data_set_recursive(Panel *panel, PointerRNA *custom_data) +{ + panel->runtime.custom_data_ptr = custom_data; + + LISTBASE_FOREACH (Panel *, child_panel, &panel->children) { + ui_panel_custom_data_set_recursive(child_panel, custom_data); + } +} + +void UI_panel_custom_data_set(Panel *panel, PointerRNA *custom_data) +{ + BLI_assert(panel->type != NULL); + + /* Free the old custom data, which should be shared among all of the panel's subpanels. */ + if (panel->runtime.custom_data_ptr != NULL) { + MEM_freeN(panel->runtime.custom_data_ptr); + } + + ui_panel_custom_data_set_recursive(panel, custom_data); +} + +PointerRNA *UI_region_panel_custom_data_under_cursor(const bContext *C, const wmEvent *event) +{ + ARegion *region = CTX_wm_region(C); + + Panel *panel = NULL; + LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { + panel = block->panel; + if (panel == NULL) { + continue; + } + + int mx = event->x; + int my = event->y; + ui_window_to_block(region, block, &mx, &my); + int mouse_state = ui_panel_mouse_state_get(block, panel, mx, my); + if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) { + break; + } + } + + if (panel == NULL) { + return NULL; + } + + PointerRNA *customdata = panel->runtime.custom_data_ptr; + + return customdata; +} + /**************** window level modal panel interaction **************/ /* note, this is modal handler and should not swallow events for animation */ diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index c22eb097761..5a5b501e21e 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1873,14 +1873,22 @@ void uiTemplateModifiers(uiLayout *UNUSED(layout), bContext *C) ModifierData *md = modifiers->first; for (int i = 0; md; i++, md = md->next) { const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (mti->panelRegister) { - char panel_idname[MAX_NAME]; - modifier_panel_id(md, panel_idname); + if (mti->panelRegister == NULL) { + continue; + } - Panel *new_panel = UI_panel_add_instanced(sa, region, ®ion->panels, panel_idname, i); - if (new_panel != NULL) { - UI_panel_set_expand_from_list_data(C, new_panel); - } + char panel_idname[MAX_NAME]; + modifier_panel_id(md, panel_idname); + + /* Create custom data RNA pointer. */ + PointerRNA *md_ptr = MEM_mallocN(sizeof(PointerRNA), "panel customdata"); + RNA_pointer_create(&ob->id, &RNA_Modifier, md, md_ptr); + + Panel *new_panel = UI_panel_add_instanced( + sa, region, ®ion->panels, panel_idname, i, md_ptr); + + if (new_panel != NULL) { + UI_panel_set_expand_from_list_data(C, new_panel); } } } @@ -1890,6 +1898,27 @@ void uiTemplateModifiers(uiLayout *UNUSED(layout), bContext *C) if ((panel->type != NULL) && (panel->type->flag & PNL_INSTANCED)) 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 (ModifierData *, md, modifiers) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); + if (mti->panelRegister == NULL) { + continue; + } + + /* Move to the next instanced panel corresponding to the next modifier. */ + while ((panel->type == NULL) || !(panel->type->flag & PNL_INSTANCED)) { + panel = panel->next; + BLI_assert(panel != NULL); /* There shouldn't be fewer panels than modifiers with UIs. */ + } + + PointerRNA *md_ptr = MEM_mallocN(sizeof(PointerRNA), "panel customdata"); + RNA_pointer_create(&ob->id, &RNA_Modifier, md, md_ptr); + UI_panel_custom_data_set(panel, md_ptr); + + panel = panel->next; + } } } @@ -2026,9 +2055,11 @@ void uiTemplateConstraints(uiLayout *UNUSED(layout), bContext *C, bool use_bone_ char panel_idname[MAX_NAME]; panel_id_func(con, panel_idname); - Panel *new_panel = UI_panel_add_instanced(sa, region, ®ion->panels, panel_idname, i); + Panel *new_panel = UI_panel_add_instanced( + sa, region, ®ion->panels, panel_idname, i, NULL); 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; @@ -2082,7 +2113,8 @@ void uiTemplateGpencilModifiers(uiLayout *UNUSED(layout), bContext *C) char panel_idname[MAX_NAME]; gpencil_modifier_panel_id(md, panel_idname); - Panel *new_panel = UI_panel_add_instanced(sa, region, ®ion->panels, panel_idname, i); + Panel *new_panel = UI_panel_add_instanced( + sa, region, ®ion->panels, panel_idname, i, NULL); if (new_panel != NULL) { UI_panel_set_expand_from_list_data(C, new_panel); } @@ -2107,7 +2139,8 @@ void uiTemplateGpencilModifiers(uiLayout *UNUSED(layout), bContext *C) /* -------------------------------------------------------------------- */ /** \name ShaderFx Template * - * Template for building the panel layout for the active object's grease pencil shader effects. + * Template for building the panel layout for the active object's grease pencil shader + * effects. * \{ */ /** @@ -2138,7 +2171,8 @@ void uiTemplateShaderFx(uiLayout *UNUSED(layout), bContext *C) char panel_idname[MAX_NAME]; shaderfx_panel_id(fx, panel_idname); - Panel *new_panel = UI_panel_add_instanced(sa, region, ®ion->panels, panel_idname, i); + Panel *new_panel = UI_panel_add_instanced( + sa, region, ®ion->panels, panel_idname, i, NULL); if (new_panel != NULL) { UI_panel_set_expand_from_list_data(C, new_panel); } diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 274cd31406c..77a3e194ae8 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -854,7 +854,7 @@ static int datalayout_transfer_exec(bContext *C, wmOperator *op) static int datalayout_transfer_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return datalayout_transfer_exec(C, op); } else { diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 3dbd1de123d..be1c29b0010 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -153,7 +153,9 @@ bool edit_modifier_poll_generic(struct bContext *C, const bool is_editmode_allowed); bool edit_modifier_poll(struct bContext *C); void edit_modifier_properties(struct wmOperatorType *ot); -int edit_modifier_invoke_properties(struct bContext *C, struct wmOperator *op); +int edit_modifier_invoke_properties(struct bContext *C, + struct wmOperator *op, + const struct wmEvent *event); struct ModifierData *edit_modifier_property_get(struct wmOperator *op, struct Object *ob, int type); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index a6c5814e88a..adcfafb44c9 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -88,6 +88,8 @@ #include "ED_screen.h" #include "ED_sculpt.h" +#include "UI_interface.h" + #include "WM_api.h" #include "WM_types.h" @@ -1037,19 +1039,38 @@ void edit_modifier_properties(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); } -int edit_modifier_invoke_properties(bContext *C, wmOperator *op) +static void edit_modifier_report_property(wmOperatorType *ot) { - ModifierData *md; + PropertyRNA *prop = RNA_def_boolean( + ot->srna, "report", false, "Report", "Create a notification after the operation"); + RNA_def_property_flag(prop, PROP_HIDDEN); +} + +/** + * \param event: If this isn't NULL, the operator will also look for panels underneath + * the cursor with customdata set to a modifier. + */ +int edit_modifier_invoke_properties(bContext *C, wmOperator *op, const wmEvent *event) +{ + PointerRNA ctx_ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier); if (RNA_struct_property_is_set(op->ptr, "modifier")) { return true; } - 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; + else if (ctx_ptr.data != NULL) { + ModifierData *md = ctx_ptr.data; + RNA_string_set(op->ptr, "modifier", md->name); + return true; + } + else 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_Modifier)) { + ModifierData *md = panel_ptr->data; + RNA_string_set(op->ptr, "modifier", md->name); + return true; + } } } @@ -1085,6 +1106,10 @@ static int modifier_remove_exec(bContext *C, wmOperator *op) ModifierData *md = edit_modifier_property_get(op, ob, 0); int mode_orig = ob->mode; + /* Store name temporarily for report. */ + char name[MAX_NAME]; + strcpy(name, md->name); + if (!md || !ED_object_modifier_remove(op->reports, bmain, ob, md)) { return OPERATOR_CANCELLED; } @@ -1099,12 +1124,17 @@ static int modifier_remove_exec(bContext *C, wmOperator *op) } } } + + if (RNA_boolean_get(op->ptr, "report")) { + BKE_reportf(op->reports, RPT_INFO, "Removed modifier: %s", name); + } + return OPERATOR_FINISHED; } -static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, event)) { return modifier_remove_exec(C, op); } else { @@ -1125,6 +1155,7 @@ void OBJECT_OT_modifier_remove(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; edit_modifier_properties(ot); + edit_modifier_report_property(ot); } /** \} */ @@ -1148,9 +1179,9 @@ static int modifier_move_up_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, event)) { return modifier_move_up_exec(C, op); } else { @@ -1194,9 +1225,9 @@ static int modifier_move_down_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, event)) { return modifier_move_down_exec(C, op); } else { @@ -1246,9 +1277,9 @@ static int modifier_move_to_index_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, event)) { return modifier_move_to_index_exec(C, op); } else { @@ -1315,6 +1346,10 @@ static int modifier_apply_exec(bContext *C, wmOperator *op) ModifierData *md = edit_modifier_property_get(op, ob, 0); int apply_as = RNA_enum_get(op->ptr, "apply_as"); + /* Store name temporarily for report. */ + char name[MAX_NAME]; + strcpy(name, md->name); + if (!md || !ED_object_modifier_apply(bmain, op->reports, depsgraph, scene, ob, md, apply_as)) { return OPERATOR_CANCELLED; } @@ -1323,12 +1358,16 @@ static int modifier_apply_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + if (RNA_boolean_get(op->ptr, "report")) { + BKE_reportf(op->reports, RPT_INFO, "Applied modifier: %s", name); + } + return OPERATOR_FINISHED; } -static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, event)) { return modifier_apply_exec(C, op); } else { @@ -1366,6 +1405,7 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot) "Apply as", "How to apply the modifier to the geometry"); edit_modifier_properties(ot); + edit_modifier_report_property(ot); } /** \} */ @@ -1396,7 +1436,7 @@ static int modifier_convert_exec(bContext *C, wmOperator *op) static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return modifier_convert_exec(C, op); } else { @@ -1440,9 +1480,9 @@ static int modifier_copy_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, event)) { return modifier_copy_exec(C, op); } else { @@ -1501,7 +1541,7 @@ static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return multires_higher_levels_delete_exec(C, op); } else { @@ -1579,7 +1619,7 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op) static int multires_subdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return multires_subdivide_exec(C, op); } else { @@ -1656,7 +1696,7 @@ static int multires_reshape_exec(bContext *C, wmOperator *op) static int multires_reshape_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return multires_reshape_exec(C, op); } else { @@ -1720,7 +1760,7 @@ static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEv Mesh *me = ob->data; char path[FILE_MAX]; - if (!edit_modifier_invoke_properties(C, op)) { + if (!edit_modifier_invoke_properties(C, op, NULL)) { return OPERATOR_CANCELLED; } @@ -1835,9 +1875,9 @@ static int multires_base_apply_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int multires_base_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int multires_base_apply_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, event)) { return multires_base_apply_exec(C, op); } else { @@ -1891,7 +1931,7 @@ static int multires_unsubdivide_exec(bContext *C, wmOperator *op) static int multires_unsubdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return multires_unsubdivide_exec(C, op); } else { @@ -1949,7 +1989,7 @@ static int multires_rebuild_subdiv_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return multires_rebuild_subdiv_exec(C, op); } else { @@ -2327,7 +2367,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) static int skin_armature_create_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return skin_armature_create_exec(C, op); } else { @@ -2406,7 +2446,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) static int correctivesmooth_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return correctivesmooth_bind_exec(C, op); } else { @@ -2483,7 +2523,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op) static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return meshdeform_bind_exec(C, op); } else { @@ -2539,7 +2579,7 @@ static int explode_refresh_exec(bContext *C, wmOperator *op) static int explode_refresh_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return explode_refresh_exec(C, op); } else { @@ -2743,7 +2783,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) static int ocean_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return ocean_bake_exec(C, op); } else { @@ -2822,7 +2862,7 @@ static int laplaciandeform_bind_exec(bContext *C, wmOperator *op) static int laplaciandeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return laplaciandeform_bind_exec(C, op); } else { @@ -2891,7 +2931,7 @@ static int surfacedeform_bind_exec(bContext *C, wmOperator *op) static int surfacedeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL)) { return surfacedeform_bind_exec(C, op); } else { diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index eb9f1c1a80a..c34f1faa255 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -41,6 +41,7 @@ struct uiLayout; struct wmDrawBuffer; struct wmTimer; struct wmTooltipState; +struct PointerRNA; /* TODO Doing this is quite ugly :) * Once the top-bar is merged bScreen should be refactored to use ScrAreaMap. */ @@ -135,6 +136,15 @@ typedef struct Panel_Runtime { /* For instanced panels: Index of the list item the panel corresponds to. */ int list_index; + + /** + * Pointer for storing which data the panel corresponds to. + * Useful when there can be multiple instances of the same panel type. + * + * \note A panel and its subpanels share the same custom data pointer. + * This avoids freeing the same pointer twice when panels are removed. + */ + struct PointerRNA *custom_data_ptr; } Panel_Runtime; /** The part from uiBlock that needs saved in file. */ diff --git a/source/blender/modifiers/intern/MOD_ui_common.c b/source/blender/modifiers/intern/MOD_ui_common.c index 88e095c549e..563aa3f091f 100644 --- a/source/blender/modifiers/intern/MOD_ui_common.c +++ b/source/blender/modifiers/intern/MOD_ui_common.c @@ -236,12 +236,15 @@ static void modifier_ops_extra_draw(bContext *C, uiLayout *layout, void *md_v) uiLayoutSetUnitsX(layout, 4.0f); /* Apply. */ - uiItemEnumO(layout, + uiItemFullO(layout, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"), ICON_CHECKMARK, - "apply_as", - MODIFIER_APPLY_DATA); + NULL, + WM_OP_INVOKE_DEFAULT, + 0, + &op_ptr); + RNA_boolean_set(&op_ptr, "report", true); /* Apply as shapekey. */ if (BKE_modifier_is_same_topology(md) && !BKE_modifier_is_non_geometrical(md)) { @@ -371,7 +374,10 @@ static void modifier_panel_header(const bContext *C, Panel *panel) if (modifier_can_delete(md) && !modifier_is_simulation(md)) { sub = uiLayoutRow(row, false); uiLayoutSetEmboss(sub, UI_EMBOSS_NONE); - uiItemO(sub, "", ICON_X, "OBJECT_OT_modifier_remove"); + PointerRNA op_ptr; + uiItemFullO( + sub, "OBJECT_OT_modifier_remove", "", ICON_X, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "report", true); buttons_number++; } |