Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/interface/interface.cc
| Show First 20 Lines • Show All 3,468 Lines • ▼ Show 20 Lines | if ((but->type == UI_BTYPE_IMAGE) && but->poin) { | ||||
| IMB_freeImBuf((struct ImBuf *)but->poin); | IMB_freeImBuf((struct ImBuf *)but->poin); | ||||
| } | } | ||||
| ui_but_drag_free(but); | ui_but_drag_free(but); | ||||
| ui_but_extra_operator_icons_free(but); | ui_but_extra_operator_icons_free(but); | ||||
| BLI_assert(UI_butstore_is_registered(but->block, but) == false); | BLI_assert(UI_butstore_is_registered(but->block, but) == false); | ||||
| MEM_freeN(but); | MEM_delete(but); | ||||
JacquesLucke: Only checking this on my phone right now, so didn't try. It feels like this might be doing the… | |||||
Done Inline ActionsThere’s currently no virtual function and no virtual destructor. But I guess we should add one already so subclasses can use non-trivially destructible types. Severin: There’s currently no virtual function and no virtual destructor. But I guess we should add one… | |||||
| } | } | ||||
| void UI_block_free(const bContext *C, uiBlock *block) | void UI_block_free(const bContext *C, uiBlock *block) | ||||
| { | { | ||||
| UI_butstore_clear(block); | UI_butstore_clear(block); | ||||
| uiBut *but; | uiBut *but; | ||||
| while ((but = static_cast<uiBut *>(BLI_pophead(&block->buttons)))) { | while ((but = static_cast<uiBut *>(BLI_pophead(&block->buttons)))) { | ||||
| ▲ Show 20 Lines • Show All 484 Lines • ▼ Show 20 Lines | |||||
| void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]) | void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]) | ||||
| { | { | ||||
| struct ColorManagedDisplay *display = ui_block_cm_display_get(block); | struct ColorManagedDisplay *display = ui_block_cm_display_get(block); | ||||
| IMB_colormanagement_scene_linear_to_display_v3(pixel, display); | IMB_colormanagement_scene_linear_to_display_v3(pixel, display); | ||||
| } | } | ||||
| static void ui_but_alloc_info(const eButType type, | /** | ||||
| size_t *r_alloc_size, | * Factory function: Allocate button and set #uiBut.type. | ||||
| const char **r_alloc_str, | */ | ||||
| bool *r_has_custom_type) | static uiBut *ui_but_new(const eButType type) | ||||
Done Inline ActionsBest to get rid of this function soon-- storing eButType is redundant with the polymorphism here. But this is an obvious change for now, one step at a time. HooglyBoogly: Best to get rid of this function soon-- storing `eButType` is redundant with the polymorphism… | |||||
Done Inline ActionsAgreed but then we need some other kind of factory function. E.g. something like UI_but_new<uiButNumber>(...) - which would be either a big change or a 3rd API to create buttons. Severin: Agreed but then we need some other kind of factory function. E.g. something like… | |||||
Not Done Inline ActionsI'm not sure any factory function is necessary. Nothing wrong with simply std::make_unique<uiButNumber> IMO HooglyBoogly: I'm not sure any factory function is necessary. Nothing wrong with simply `std… | |||||
| { | { | ||||
| size_t alloc_size; | uiBut *but = nullptr; | ||||
| const char *alloc_str; | |||||
| bool has_custom_type = true; | #define NEW_BUT(type_name) MEM_new<type_name>(#type_name) | ||||
| switch (type) { | switch (type) { | ||||
| case UI_BTYPE_NUM: | case UI_BTYPE_NUM: | ||||
| alloc_size = sizeof(uiButNumber); | but = MEM_new<uiButNumber>("uiButNumber"); | ||||
| alloc_str = "uiButNumber"; | |||||
| break; | break; | ||||
| case UI_BTYPE_COLOR: | case UI_BTYPE_COLOR: | ||||
| alloc_size = sizeof(uiButColor); | but = MEM_new<uiButColor>("uiButColor"); | ||||
| alloc_str = "uiButColor"; | |||||
| break; | break; | ||||
| case UI_BTYPE_DECORATOR: | case UI_BTYPE_DECORATOR: | ||||
| alloc_size = sizeof(uiButDecorator); | but = MEM_new<uiButDecorator>("uiButDecorator"); | ||||
| alloc_str = "uiButDecorator"; | |||||
| break; | break; | ||||
| case UI_BTYPE_TAB: | case UI_BTYPE_TAB: | ||||
| alloc_size = sizeof(uiButTab); | but = MEM_new<uiButTab>("uiButTab"); | ||||
| alloc_str = "uiButTab"; | |||||
| break; | break; | ||||
| case UI_BTYPE_SEARCH_MENU: | case UI_BTYPE_SEARCH_MENU: | ||||
| alloc_size = sizeof(uiButSearch); | but = MEM_new<uiButSearch>("uiButSearch"); | ||||
| alloc_str = "uiButSearch"; | |||||
| break; | break; | ||||
| case UI_BTYPE_PROGRESS_BAR: | case UI_BTYPE_PROGRESS_BAR: | ||||
| alloc_size = sizeof(uiButProgressbar); | but = MEM_new<uiButProgressbar>("uiButProgressbar"); | ||||
| alloc_str = "uiButProgressbar"; | |||||
| break; | break; | ||||
| case UI_BTYPE_HSVCUBE: | case UI_BTYPE_HSVCUBE: | ||||
| alloc_size = sizeof(uiButHSVCube); | but = MEM_new<uiButHSVCube>("uiButHSVCube"); | ||||
| alloc_str = "uiButHSVCube"; | |||||
| break; | break; | ||||
| case UI_BTYPE_COLORBAND: | case UI_BTYPE_COLORBAND: | ||||
| alloc_size = sizeof(uiButColorBand); | but = MEM_new<uiButColorBand>("uiButColorBand"); | ||||
| alloc_str = "uiButColorBand"; | |||||
| break; | break; | ||||
| case UI_BTYPE_CURVE: | case UI_BTYPE_CURVE: | ||||
| alloc_size = sizeof(uiButCurveMapping); | but = MEM_new<uiButCurveMapping>("uiButCurveMapping"); | ||||
| alloc_str = "uiButCurveMapping"; | |||||
| break; | break; | ||||
| case UI_BTYPE_CURVEPROFILE: | case UI_BTYPE_CURVEPROFILE: | ||||
| alloc_size = sizeof(uiButCurveProfile); | but = MEM_new<uiButCurveProfile>("uiButCurveProfile"); | ||||
| alloc_str = "uiButCurveProfile"; | |||||
| break; | break; | ||||
| case UI_BTYPE_HOTKEY_EVENT: | case UI_BTYPE_HOTKEY_EVENT: | ||||
| alloc_size = sizeof(uiButHotkeyEvent); | but = MEM_new<uiButHotkeyEvent>("uiButHotkeyEvent"); | ||||
| alloc_str = "uiButHotkeyEvent"; | |||||
| break; | break; | ||||
| case UI_BTYPE_VIEW_ITEM: | case UI_BTYPE_VIEW_ITEM: | ||||
| alloc_size = sizeof(uiButViewItem); | but = MEM_new<uiButViewItem>("uiButViewItem"); | ||||
| alloc_str = "uiButViewItem"; | |||||
| break; | break; | ||||
| default: | default: | ||||
| alloc_size = sizeof(uiBut); | but = NEW_BUT(uiBut); | ||||
| alloc_str = "uiBut"; | |||||
| has_custom_type = false; | |||||
| break; | break; | ||||
| } | } | ||||
| #undef NEW_BUT | |||||
| if (r_alloc_size) { | but->type = type; | ||||
| *r_alloc_size = alloc_size; | return but; | ||||
| } | |||||
| if (r_alloc_str) { | |||||
| *r_alloc_str = alloc_str; | |||||
| } | |||||
| if (r_has_custom_type) { | |||||
| *r_has_custom_type = has_custom_type; | |||||
| } | |||||
| } | |||||
| static uiBut *ui_but_alloc(const eButType type) | |||||
| { | |||||
| size_t alloc_size; | |||||
| const char *alloc_str; | |||||
| ui_but_alloc_info(type, &alloc_size, &alloc_str, nullptr); | |||||
| return static_cast<uiBut *>(MEM_callocN(alloc_size, alloc_str)); | |||||
| } | } | ||||
| uiBut *ui_but_change_type(uiBut *but, eButType new_type) | uiBut *ui_but_change_type(uiBut *but, eButType new_type) | ||||
| { | { | ||||
| if (but->type == new_type) { | if (but->type == new_type) { | ||||
| /* Nothing to do. */ | /* Nothing to do. */ | ||||
| return but; | return but; | ||||
| } | } | ||||
| size_t alloc_size; | |||||
| const char *alloc_str; | |||||
| uiBut *insert_after_but = but->prev; | uiBut *insert_after_but = but->prev; | ||||
| bool new_has_custom_type, old_has_custom_type; | |||||
| /* Remove old button address */ | /* Remove old button address */ | ||||
| BLI_remlink(&but->block->buttons, but); | BLI_remlink(&but->block->buttons, but); | ||||
| ui_but_alloc_info(but->type, nullptr, nullptr, &old_has_custom_type); | |||||
| ui_but_alloc_info(new_type, &alloc_size, &alloc_str, &new_has_custom_type); | |||||
| if (new_has_custom_type || old_has_custom_type) { | |||||
| const uiBut *old_but_ptr = but; | const uiBut *old_but_ptr = but; | ||||
| /* Button may have pointer to a member within itself, this will have to be updated. */ | /* Button may have pointer to a member within itself, this will have to be updated. */ | ||||
| const bool has_str_ptr_to_self = but->str == but->strdata; | const bool has_str_ptr_to_self = but->str == but->strdata; | ||||
| const bool has_poin_ptr_to_self = but->poin == (char *)but; | const bool has_poin_ptr_to_self = but->poin == (char *)but; | ||||
| but = static_cast<uiBut *>(MEM_recallocN_id(but, alloc_size, alloc_str)); | /* Copy construct button with the new type. */ | ||||
| but->type = new_type; | but = ui_but_new(new_type); | ||||
| *but = *old_but_ptr; | |||||
| if (has_str_ptr_to_self) { | if (has_str_ptr_to_self) { | ||||
| but->str = but->strdata; | but->str = but->strdata; | ||||
| } | } | ||||
| if (has_poin_ptr_to_self) { | if (has_poin_ptr_to_self) { | ||||
| but->poin = (char *)but; | but->poin = (char *)but; | ||||
| } | } | ||||
| BLI_insertlinkafter(&but->block->buttons, insert_after_but, but); | BLI_insertlinkafter(&but->block->buttons, insert_after_but, but); | ||||
| if (but->layout) { | if (but->layout) { | ||||
| const bool found_layout = ui_layout_replace_but_ptr(but->layout, old_but_ptr, but); | const bool found_layout = ui_layout_replace_but_ptr(but->layout, old_but_ptr, but); | ||||
| BLI_assert(found_layout); | BLI_assert(found_layout); | ||||
| UNUSED_VARS_NDEBUG(found_layout); | UNUSED_VARS_NDEBUG(found_layout); | ||||
| ui_button_group_replace_but_ptr(uiLayoutGetBlock(but->layout), old_but_ptr, but); | ui_button_group_replace_but_ptr(uiLayoutGetBlock(but->layout), old_but_ptr, but); | ||||
| } | } | ||||
| #ifdef WITH_PYTHON | #ifdef WITH_PYTHON | ||||
| if (UI_editsource_enable_check()) { | if (UI_editsource_enable_check()) { | ||||
| UI_editsource_but_replace(old_but_ptr, but); | UI_editsource_but_replace(old_but_ptr, but); | ||||
| } | } | ||||
| #endif | #endif | ||||
| } | |||||
| MEM_delete(old_but_ptr); | |||||
| return but; | return but; | ||||
| } | } | ||||
| /** | /** | ||||
| * \brief ui_def_but is the function that draws many button types | * \brief ui_def_but is the function that draws many button types | ||||
| * | * | ||||
| * \param x, y: The lower left hand corner of the button (X axis) | * \param x, y: The lower left hand corner of the button (X axis) | ||||
| Show All 29 Lines | static uiBut *ui_def_but(uiBlock *block, | ||||
| if (type & UI_BUT_POIN_TYPES) { /* a pointer is required */ | if (type & UI_BUT_POIN_TYPES) { /* a pointer is required */ | ||||
| if (poin == nullptr) { | if (poin == nullptr) { | ||||
| BLI_assert(0); | BLI_assert(0); | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| } | } | ||||
| uiBut *but = ui_but_alloc((eButType)(type & BUTTYPE)); | uiBut *but = ui_but_new((eButType)(type & BUTTYPE)); | ||||
| but->type = (eButType)(type & BUTTYPE); | |||||
| but->pointype = (eButPointerType)(type & UI_BUT_POIN_TYPES); | but->pointype = (eButPointerType)(type & UI_BUT_POIN_TYPES); | ||||
| but->bit = type & UI_BUT_POIN_BIT; | but->bit = type & UI_BUT_POIN_BIT; | ||||
| but->bitnr = type & 31; | but->bitnr = type & 31; | ||||
| but->icon = ICON_NONE; | |||||
| but->iconadd = 0; | |||||
| but->retval = retval; | but->retval = retval; | ||||
| const int slen = strlen(str); | const int slen = strlen(str); | ||||
| ui_but_string_set_internal(but, str, slen); | ui_but_string_set_internal(but, str, slen); | ||||
| but->rect.xmin = x; | but->rect.xmin = x; | ||||
| but->rect.ymin = y; | but->rect.ymin = y; | ||||
| but->rect.xmax = but->rect.xmin + width; | but->rect.xmax = but->rect.xmin + width; | ||||
| but->rect.ymax = but->rect.ymin + height; | but->rect.ymax = but->rect.ymin + height; | ||||
| but->poin = (char *)poin; | but->poin = (char *)poin; | ||||
| but->hardmin = but->softmin = min; | but->hardmin = but->softmin = min; | ||||
| but->hardmax = but->softmax = max; | but->hardmax = but->softmax = max; | ||||
| but->a1 = a1; | but->a1 = a1; | ||||
| but->a2 = a2; | but->a2 = a2; | ||||
| but->tip = tip; | but->tip = tip; | ||||
| but->disabled_info = block->lockstr; | but->disabled_info = block->lockstr; | ||||
| but->emboss = block->emboss; | but->emboss = block->emboss; | ||||
| but->pie_dir = UI_RADIAL_NONE; | |||||
| but->block = block; /* pointer back, used for front-buffer status, and picker. */ | but->block = block; /* pointer back, used for front-buffer status, and picker. */ | ||||
| if ((block->flag & UI_BUT_ALIGN) && ui_but_can_align(but)) { | if ((block->flag & UI_BUT_ALIGN) && ui_but_can_align(but)) { | ||||
| but->alignnr = block->alignnr; | but->alignnr = block->alignnr; | ||||
| } | } | ||||
| but->func = block->func; | but->func = block->func; | ||||
| ▲ Show 20 Lines • Show All 2,113 Lines • ▼ Show 20 Lines | void UI_but_func_search_set(uiBut *but, | ||||
| search_but->items_update_fn = search_update_fn; | search_but->items_update_fn = search_update_fn; | ||||
| search_but->item_active = active; | search_but->item_active = active; | ||||
| search_but->arg = arg; | search_but->arg = arg; | ||||
| search_but->arg_free_fn = search_arg_free_fn; | search_but->arg_free_fn = search_arg_free_fn; | ||||
| if (search_exec_fn) { | if (search_exec_fn) { | ||||
| #ifdef DEBUG | #ifdef DEBUG | ||||
| if (search_but->but.func) { | if (but->func) { | ||||
| /* watch this, can be cause of much confusion, see: T47691 */ | /* watch this, can be cause of much confusion, see: T47691 */ | ||||
| printf("%s: warning, overwriting button callback with search function callback!\n", | printf("%s: warning, overwriting button callback with search function callback!\n", | ||||
| __func__); | __func__); | ||||
| } | } | ||||
| #endif | #endif | ||||
| /* Handling will pass the active item as arg2 later, so keep it nullptr here. */ | /* Handling will pass the active item as arg2 later, so keep it nullptr here. */ | ||||
| if (free_arg) { | if (free_arg) { | ||||
| UI_but_funcN_set(but, search_exec_fn, search_but->arg, nullptr); | UI_but_funcN_set(but, search_exec_fn, search_but->arg, nullptr); | ||||
| ▲ Show 20 Lines • Show All 526 Lines • Show Last 20 Lines | |||||
Only checking this on my phone right now, so didn't try. It feels like this might be doing the wrong thing for the subclasses of uiBut, because it only calls the destructor of the base class. Am I missing something?