diff options
Diffstat (limited to 'source/blender/editors/interface')
-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 |
3 files changed, 121 insertions, 19 deletions
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); } |