Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/screen.c26
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/editors/include/UI_interface.h7
-rw-r--r--source/blender/editors/interface/interface_layout.c1
-rw-r--r--source/blender/editors/interface/interface_panel.c81
-rw-r--r--source/blender/editors/interface/interface_templates.c58
-rw-r--r--source/blender/editors/object/object_data_transfer.c2
-rw-r--r--source/blender/editors/object/object_intern.h4
-rw-r--r--source/blender/editors/object/object_modifier.c112
-rw-r--r--source/blender/makesdna/DNA_screen_types.h10
-rw-r--r--source/blender/modifiers/intern/MOD_ui_common.c14
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, &region->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, &region->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, &region->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, &region->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, &region->panels, panel_idname, i);
+ Panel *new_panel = UI_panel_add_instanced(
+ sa, region, &region->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, &region->panels, panel_idname, i);
+ Panel *new_panel = UI_panel_add_instanced(
+ sa, region, &region->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, &region->panels, panel_idname, i);
+ Panel *new_panel = UI_panel_add_instanced(
+ sa, region, &region->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++;
}