mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Merge branch 'blender-v5.2-release'
This commit is contained in:
commit
ccec1025e0
16 changed files with 345 additions and 22 deletions
|
|
@ -994,14 +994,24 @@ Layout *pie_menu_layout(PieMenu *pie);
|
|||
using BlockCreateFunc = Block *(*)(bContext * C, ARegion *region, void *arg1);
|
||||
using BlockCancelFunc = void (*)(bContext *C, void *arg1);
|
||||
|
||||
void popup_block_invoke(bContext *C, BlockCreateFunc func, void *arg, FreeArgFunc arg_free);
|
||||
void popup_block_invoke(bContext *C,
|
||||
BlockCreateFunc func,
|
||||
void *arg,
|
||||
FreeArgFunc arg_free,
|
||||
StructRNA *srna_owner = nullptr);
|
||||
/**
|
||||
* \param can_refresh: When true, the popup may be refreshed (updated after creation).
|
||||
* \note It can be useful to disable refresh (even though it will work)
|
||||
* as this exits text fields which can be disruptive if refresh isn't needed.
|
||||
* \param srna_owner: The StructRNA type that owns this popup, this popup should be removed if this
|
||||
* type gets unregistered.
|
||||
*/
|
||||
void popup_block_invoke_ex(
|
||||
bContext *C, BlockCreateFunc func, void *arg, FreeArgFunc arg_free, bool can_refresh);
|
||||
void popup_block_invoke_ex(bContext *C,
|
||||
BlockCreateFunc func,
|
||||
void *arg,
|
||||
FreeArgFunc arg_free,
|
||||
bool can_refresh,
|
||||
StructRNA *srna_owner = nullptr);
|
||||
void popup_block_ex(bContext *C,
|
||||
BlockCreateFunc func,
|
||||
BlockHandleFunc popup_func,
|
||||
|
|
@ -2308,6 +2318,13 @@ void popup_handlers_add(bContext *C,
|
|||
void popup_handlers_remove(ListBaseT<wmEventHandler> *handlers, PopupBlockHandle *popup);
|
||||
void popup_handlers_remove_all(bContext *C, ListBaseT<wmEventHandler> *handlers);
|
||||
|
||||
/**
|
||||
* Tags for refresh popup/menu handlers referencing a #StructRNA that is being unregistered,
|
||||
* popups/menus that can't be refreshed or are created using the \a srna_to_unreg reference will
|
||||
* be removed.
|
||||
*/
|
||||
void refresh_for_srna_unregister(Main *bmain, StructRNA *srna_to_unreg);
|
||||
|
||||
/* Module
|
||||
*
|
||||
* init and exit should be called before using this module. init_userdef must
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@
|
|||
#include "BKE_colortools.hh"
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_curveprofile.h"
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_main.hh"
|
||||
#include "BKE_movieclip.hh"
|
||||
#include "BKE_paint.hh"
|
||||
#include "BKE_paint_types.hh"
|
||||
|
|
@ -9730,6 +9732,9 @@ static void button_activate_init(bContext *C,
|
|||
}
|
||||
}
|
||||
|
||||
static int popup_handler(bContext *C, const wmEvent *event, void *userdata);
|
||||
static void popup_handler_remove(bContext *C, void *userdata);
|
||||
|
||||
static void button_activate_exit(
|
||||
bContext *C, Button *but, HandleButtonData *data, const bool mousemove, const bool onfree)
|
||||
{
|
||||
|
|
@ -13207,6 +13212,197 @@ void popup_handlers_remove_all(bContext *C, ListBaseT<wmEventHandler> *handlers)
|
|||
WM_event_free_ui_handler_all(C, handlers, popup_handler, popup_handler_remove);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the button is referencing \a srna.
|
||||
* \note This would fail to properly determine if the Button is referencing \a srna if the
|
||||
* reference is stored through an opaque type (like #Button::apply_func).
|
||||
*/
|
||||
static bool button_references_srna(Button &button, const StructRNA *srna)
|
||||
{
|
||||
if (RNA_struct_is_a(button.rnapoin.type, srna)) {
|
||||
return true;
|
||||
}
|
||||
if (button.opptr && RNA_struct_is_a(button.opptr->type, srna)) {
|
||||
return true;
|
||||
}
|
||||
if (MenuType *mt = button_menutype_get(&button); mt && RNA_struct_is_a(mt->rna_ext.srna, srna)) {
|
||||
return true;
|
||||
}
|
||||
if (PanelType *pt = button_paneltype_get(&button); pt && RNA_struct_is_a(pt->rna_ext.srna, srna))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (wmOperatorType *ot = button_operatortype_get_from_enum_menu(&button, nullptr);
|
||||
ot && RNA_struct_is_a(ot->rna_ext.srna, srna))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (button.type == ButtonType::SearchMenu) {
|
||||
const ButtonSearch &search_button = static_cast<const ButtonSearch &>(button);
|
||||
if (RNA_struct_is_a(search_button.rnasearchpoin.type, srna)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (button.type == ButtonType::Decorator) {
|
||||
const ButtonDecorator &decorator_button = static_cast<const ButtonDecorator &>(button);
|
||||
if (RNA_struct_is_a(decorator_button.decorated_rnapoin.type, srna)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (ButtonExtraOpIcon &extra_op_icon : button.extra_op_icons) {
|
||||
if (RNA_struct_is_a(extra_op_icon.optype_params->optype->rna_ext.srna, srna)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (button.context) {
|
||||
for (const bContextStoreEntry &entry : button.context->entries) {
|
||||
if (const PointerRNA *ptr = std::get_if<PointerRNA>(&entry.value)) {
|
||||
if (RNA_struct_is_a(ptr->type, srna)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the #popup_block_handle have any reference the #srna_to_unreg but can't be
|
||||
* refreshed, when this happens its parent must be refreshed or the popup should be closed.
|
||||
*/
|
||||
static bool popup_needs_update_for_unreg_srna_recursive(bContext *C,
|
||||
PopupBlockHandle *popup_block_handle,
|
||||
StructRNA *srna_to_unreg)
|
||||
{
|
||||
bool have_reference = false;
|
||||
|
||||
bool valid_for_refresh = popup_block_handle->can_refresh;
|
||||
|
||||
if (popup_block_handle->srna_owner &&
|
||||
RNA_struct_is_a(popup_block_handle->srna_owner, srna_to_unreg))
|
||||
{
|
||||
have_reference = true;
|
||||
valid_for_refresh = false;
|
||||
}
|
||||
[&]() {
|
||||
for (Block &block : popup_block_handle->region->runtime->uiblocks) {
|
||||
for (Button &button : block.buttons()) {
|
||||
have_reference = have_reference || button_references_srna(button, srna_to_unreg);
|
||||
if (button.type == ButtonType::SearchMenu) {
|
||||
const ButtonSearch &search_button = static_cast<const ButtonSearch &>(button);
|
||||
if (search_button.active) {
|
||||
/* Search buttons may reference menus/operators but we can't lookup in its items, close
|
||||
* any popup with a search button active. */
|
||||
have_reference = true;
|
||||
valid_for_refresh = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}();
|
||||
|
||||
Button *active_button = region_find_active_but(popup_block_handle->region);
|
||||
HandleButtonData *data = active_button ? active_button->active : nullptr;
|
||||
PopupBlockHandle *sub_handle = data ? data->menu : nullptr;
|
||||
|
||||
if (have_reference) {
|
||||
if (valid_for_refresh) {
|
||||
/* This popup needs to be refresh, close any sub-menu first. */
|
||||
if (sub_handle) {
|
||||
CTX_wm_region_popup_set(C, popup_block_handle->region);
|
||||
button_active_free(C, active_button);
|
||||
CTX_wm_region_popup_set(C, nullptr);
|
||||
}
|
||||
ED_region_tag_refresh_ui(popup_block_handle->region);
|
||||
ED_region_tag_redraw(popup_block_handle->region);
|
||||
return false;
|
||||
}
|
||||
/* This popup can't be refreshed, try to refesh parent popup. */
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(sub_handle && popup_needs_update_for_unreg_srna_recursive(C, sub_handle, srna_to_unreg))) {
|
||||
/* There is no child popup referencing the rna type or it can be refresh, no need to refresh
|
||||
* this popup. */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (valid_for_refresh) {
|
||||
CTX_wm_region_popup_set(C, popup_block_handle->region);
|
||||
button_active_free(C, active_button);
|
||||
CTX_wm_region_popup_set(C, nullptr);
|
||||
ED_region_tag_refresh_ui(popup_block_handle->region);
|
||||
ED_region_tag_redraw(popup_block_handle->region);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This popup can't be refreshed, try to refesh parent popup. */
|
||||
return true;
|
||||
}
|
||||
|
||||
void refresh_for_srna_unregister(Main *bmain, StructRNA *srna_to_unreg)
|
||||
{
|
||||
if (G.background) {
|
||||
return;
|
||||
}
|
||||
if (!srna_to_unreg) {
|
||||
return;
|
||||
}
|
||||
bContext *C = CTX_create();
|
||||
CTX_data_main_set(C, bmain);
|
||||
auto refresh_or_remove_handler = [&](wmEventHandler &handler_base,
|
||||
ListBaseT<wmEventHandler> &handlers) {
|
||||
if (handler_base.type == WM_HANDLER_TYPE_UI && !bool(handler_base.flag & WM_HANDLER_DO_FREE)) {
|
||||
wmEventHandler_UI *handler = reinterpret_cast<wmEventHandler_UI *>(&handler_base);
|
||||
if (handler->handle_fn != popup_handler) {
|
||||
return;
|
||||
}
|
||||
PopupBlockHandle *popup_block_handle = static_cast<PopupBlockHandle *>(handler->user_data);
|
||||
if (!popup_needs_update_for_unreg_srna_recursive(C, popup_block_handle, srna_to_unreg)) {
|
||||
return;
|
||||
}
|
||||
if (handler->remove_fn) {
|
||||
handler->remove_fn(C, handler->user_data);
|
||||
}
|
||||
BLI_remlink(&handlers, handler);
|
||||
wm_event_free_handler(&handler->head);
|
||||
}
|
||||
};
|
||||
|
||||
for (wmWindowManager &wm : bmain->wm) {
|
||||
CTX_wm_manager_set(C, &wm);
|
||||
for (wmWindow &win : wm.windows) {
|
||||
CTX_wm_window_set(C, &win);
|
||||
/* Close any active popup referencing the StructRNA. */
|
||||
for (wmEventHandler &handler_base : win.runtime->modalhandlers.items_mutable()) {
|
||||
refresh_or_remove_handler(handler_base, win.runtime->modalhandlers);
|
||||
}
|
||||
for (wmEventHandler &handler_base : win.runtime->handlers.items_mutable()) {
|
||||
refresh_or_remove_handler(handler_base, win.runtime->handlers);
|
||||
}
|
||||
/* Close any active menu referencing the StructRNA. */
|
||||
bScreen *screen = WM_window_get_active_screen(&win);
|
||||
if (screen && screen->active_region) {
|
||||
CTX_wm_region_set(C, screen->active_region);
|
||||
Button *active_button = region_find_active_but(screen->active_region);
|
||||
HandleButtonData *data = (active_button) ? active_button->active : nullptr;
|
||||
PopupBlockHandle *sub_handle = (data) ? data->menu : nullptr;
|
||||
if (sub_handle &&
|
||||
popup_needs_update_for_unreg_srna_recursive(C, sub_handle, srna_to_unreg))
|
||||
{
|
||||
button_active_free(C, active_button);
|
||||
ED_region_tag_refresh_ui(screen->active_region);
|
||||
ED_region_tag_redraw(screen->active_region);
|
||||
}
|
||||
CTX_wm_region_set(C, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
CTX_free(C);
|
||||
}
|
||||
|
||||
bool textbutton_activate_rna(const bContext *C,
|
||||
ARegion *region,
|
||||
const void *rna_poin_data,
|
||||
|
|
|
|||
|
|
@ -1029,6 +1029,12 @@ struct PopupBlockHandle {
|
|||
void (*cancel_func)(bContext *C, void *arg) = nullptr;
|
||||
void *popup_arg = nullptr;
|
||||
|
||||
/**
|
||||
* The StructRNA type that owns this popup, this popup should be removed if this type gets
|
||||
* unregistered.
|
||||
*/
|
||||
StructRNA *srna_owner = nullptr;
|
||||
|
||||
/** Store data for refreshing popups. */
|
||||
PopupBlockCreate popup_create_vars;
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -621,7 +621,7 @@ static void popup_menu_create_from_menutype(bContext *C,
|
|||
item_menutype_func(C, layout, mt);
|
||||
},
|
||||
true);
|
||||
|
||||
handle->srna_owner = mt->rna_ext.srna;
|
||||
STRNCPY_UTF8(handle->menu_idname, mt->idname);
|
||||
|
||||
WorkspaceStatus status(C);
|
||||
|
|
@ -671,14 +671,19 @@ wmOperatorStatus popup_menu_invoke(bContext *C, const char *idname, ReportList *
|
|||
/** \name Popup Block API
|
||||
* \{ */
|
||||
|
||||
void popup_block_invoke_ex(
|
||||
bContext *C, BlockCreateFunc func, void *arg, FreeArgFunc arg_free, const bool can_refresh)
|
||||
void popup_block_invoke_ex(bContext *C,
|
||||
BlockCreateFunc func,
|
||||
void *arg,
|
||||
FreeArgFunc arg_free,
|
||||
const bool can_refresh,
|
||||
StructRNA *srna_owner)
|
||||
{
|
||||
wmWindow *window = CTX_wm_window(C);
|
||||
|
||||
PopupBlockHandle *handle = popup_block_create(
|
||||
C, nullptr, nullptr, func, nullptr, arg, arg_free, can_refresh);
|
||||
handle->popup = true;
|
||||
handle->srna_owner = srna_owner;
|
||||
|
||||
/* Clear the status bar. */
|
||||
WorkspaceStatus status(C);
|
||||
|
|
@ -690,9 +695,10 @@ void popup_block_invoke_ex(
|
|||
WM_event_add_mousemove(window);
|
||||
}
|
||||
|
||||
void popup_block_invoke(bContext *C, BlockCreateFunc func, void *arg, FreeArgFunc arg_free)
|
||||
void popup_block_invoke(
|
||||
bContext *C, BlockCreateFunc func, void *arg, FreeArgFunc arg_free, StructRNA *srna_owner)
|
||||
{
|
||||
popup_block_invoke_ex(C, func, arg, arg_free, true);
|
||||
popup_block_invoke_ex(C, func, arg, arg_free, true, srna_owner);
|
||||
}
|
||||
|
||||
void popup_block_ex(bContext *C,
|
||||
|
|
@ -710,6 +716,9 @@ void popup_block_ex(bContext *C,
|
|||
handle->retvalue = 1;
|
||||
|
||||
handle->popup_op = op;
|
||||
if (op) {
|
||||
handle->srna_owner = op->type->srna;
|
||||
}
|
||||
handle->popup_arg = arg;
|
||||
handle->popup_func = popup_func;
|
||||
handle->cancel_func = cancel_func;
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ PopupBlockHandle *popover_panel_create(bContext *C,
|
|||
WM_event_add_mousemove(window);
|
||||
handle->popup = true;
|
||||
}
|
||||
|
||||
handle->srna_owner = panel_type->rna_ext.srna;
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
#include "RNA_define.hh"
|
||||
#include "RNA_enum_types.hh"
|
||||
|
||||
#include "UI_interface_c.hh"
|
||||
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "rna_internal.hh"
|
||||
|
|
@ -699,8 +701,9 @@ IDProperty **rna_PropertyGroup_idprops(PointerRNA *ptr)
|
|||
return reinterpret_cast<IDProperty **>(&ptr->data);
|
||||
}
|
||||
|
||||
bool rna_PropertyGroup_unregister(Main * /*bmain*/, StructRNA *type)
|
||||
bool rna_PropertyGroup_unregister(Main *bmain, StructRNA *type)
|
||||
{
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
# ifdef WITH_PYTHON
|
||||
/* Ensure that a potential py object representing this RNA type is properly dereferenced. */
|
||||
BPY_free_srna_pytype(type);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include "rna_internal.hh"
|
||||
|
||||
#include "UI_interface_c.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
|
@ -159,7 +161,9 @@ static bool rna_NodeSocket_unregister(Main *bmain, StructRNA *type)
|
|||
if (!st) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
ui::refresh_for_srna_unregister(bmain, st->ext_interface.srna);
|
||||
ui::refresh_for_srna_unregister(bmain, st->ext_socket.srna);
|
||||
RNA_struct_free_extension(type, &st->ext_socket);
|
||||
RNA_struct_free(&RNA_blender_rna_get(), type);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "rna_internal.hh"
|
||||
|
||||
#include "UI_interface_c.hh"
|
||||
|
||||
#include "WM_types.hh"
|
||||
|
||||
namespace blender {
|
||||
|
|
@ -216,13 +218,16 @@ static int rna_NodeTreeInterfaceItem_index_get(PointerRNA *ptr)
|
|||
return ntree->tree_interface.find_item_index(*item);
|
||||
}
|
||||
|
||||
static bool rna_NodeTreeInterfaceSocket_unregister(Main * /*bmain*/, StructRNA *type)
|
||||
static bool rna_NodeTreeInterfaceSocket_unregister(Main *bmain, StructRNA *type)
|
||||
{
|
||||
bke::bNodeSocketType *st = static_cast<bke::bNodeSocketType *>(
|
||||
RNA_struct_blender_type_get(type));
|
||||
if (!st) {
|
||||
return false;
|
||||
}
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
ui::refresh_for_srna_unregister(bmain, st->ext_interface.srna);
|
||||
ui::refresh_for_srna_unregister(bmain, st->ext_socket.srna);
|
||||
|
||||
RNA_struct_free_extension(type, &st->ext_interface);
|
||||
|
||||
|
|
@ -340,7 +345,7 @@ static void rna_NodeTreeInterfaceSocket_from_socket_custom(
|
|||
RNA_parameter_list_free(&list);
|
||||
}
|
||||
|
||||
static StructRNA *rna_NodeTreeInterfaceSocket_register(Main * /*bmain*/,
|
||||
static StructRNA *rna_NodeTreeInterfaceSocket_register(Main *bmain,
|
||||
ReportList * /*reports*/,
|
||||
void *data,
|
||||
const char *identifier,
|
||||
|
|
@ -378,6 +383,7 @@ static StructRNA *rna_NodeTreeInterfaceSocket_register(Main * /*bmain*/,
|
|||
|
||||
/* if RNA type is already registered, unregister first */
|
||||
if (st->ext_interface.srna) {
|
||||
ui::refresh_for_srna_unregister(bmain, st->ext_interface.srna);
|
||||
StructRNA *srna = st->ext_interface.srna;
|
||||
RNA_struct_free_extension(srna, &st->ext_interface);
|
||||
RNA_struct_free(&RNA_blender_rna_get(), srna);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
|
||||
#include "IMB_colormanagement.hh"
|
||||
|
||||
#include "UI_interface_c.hh"
|
||||
|
||||
#include "WM_types.hh"
|
||||
|
||||
namespace blender {
|
||||
|
|
@ -1076,6 +1078,7 @@ static bool rna_NodeTree_unregister(Main *bmain, StructRNA *type)
|
|||
if (!nt) {
|
||||
return false;
|
||||
}
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
|
||||
RNA_struct_free_extension(type, &nt->rna_ext);
|
||||
RNA_struct_free(&RNA_blender_rna_get(), type);
|
||||
|
|
@ -2000,6 +2003,7 @@ static bool rna_Node_unregister(Main *bmain, StructRNA *type)
|
|||
if (!nt || rna_Node_is_builtin(nt)) {
|
||||
return false;
|
||||
}
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
|
||||
RNA_struct_free_extension(type, &nt->rna_ext);
|
||||
RNA_struct_free(&RNA_blender_rna_get(), type);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#include "rna_internal.hh"
|
||||
|
||||
#include "UI_interface_c.hh"
|
||||
|
||||
#include "RE_engine.h"
|
||||
|
||||
namespace blender {
|
||||
|
|
@ -286,6 +288,7 @@ static bool rna_RenderEngine_unregister(Main *bmain, StructRNA *type)
|
|||
if (!et) {
|
||||
return false;
|
||||
}
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
|
||||
/* Stop all renders in case we were using this one. */
|
||||
ED_render_engine_changed(bmain, false);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "rna_internal.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_interface_c.hh"
|
||||
#include "UI_interface_layout.hh"
|
||||
|
||||
#include "WM_toolsystem.hh"
|
||||
|
|
@ -211,6 +212,7 @@ static bool rna_Panel_unregister(Main *bmain, StructRNA *type)
|
|||
return false;
|
||||
}
|
||||
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
RNA_struct_free_extension(type, &pt->rna_ext);
|
||||
RNA_struct_free(&RNA_blender_rna_get(), type);
|
||||
|
||||
|
|
@ -697,7 +699,7 @@ static bool rna_UIList_unregister(Main *bmain, StructRNA *type)
|
|||
if (!ult) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
RNA_struct_free_extension(type, &ult->rna_ext);
|
||||
RNA_struct_free(&RNA_blender_rna_get(), type);
|
||||
|
||||
|
|
@ -817,7 +819,7 @@ static void header_draw(const bContext *C, Header *hdr)
|
|||
RNA_parameter_list_free(&list);
|
||||
}
|
||||
|
||||
static bool rna_Header_unregister(Main * /*bmain*/, StructRNA *type)
|
||||
static bool rna_Header_unregister(Main *bmain, StructRNA *type)
|
||||
{
|
||||
ARegionType *art;
|
||||
HeaderType *ht = static_cast<HeaderType *>(RNA_struct_blender_type_get(type));
|
||||
|
|
@ -825,10 +827,12 @@ static bool rna_Header_unregister(Main * /*bmain*/, StructRNA *type)
|
|||
if (!ht) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(art = region_type_find(nullptr, ht->space_type, ht->region_type))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
RNA_struct_free_extension(type, &ht->rna_ext);
|
||||
RNA_struct_free(&RNA_blender_rna_get(), type);
|
||||
|
||||
|
|
@ -978,7 +982,7 @@ static void menu_draw(const bContext *C, Menu *menu)
|
|||
RNA_parameter_list_free(&list);
|
||||
}
|
||||
|
||||
static bool rna_Menu_unregister(Main * /*bmain*/, StructRNA *type)
|
||||
static bool rna_Menu_unregister(Main *bmain, StructRNA *type)
|
||||
{
|
||||
MenuType *mt = static_cast<MenuType *>(RNA_struct_blender_type_get(type));
|
||||
|
||||
|
|
@ -986,6 +990,7 @@ static bool rna_Menu_unregister(Main * /*bmain*/, StructRNA *type)
|
|||
return false;
|
||||
}
|
||||
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
RNA_struct_free_extension(type, &mt->rna_ext);
|
||||
RNA_struct_free(&RNA_blender_rna_get(), type);
|
||||
|
||||
|
|
@ -1222,6 +1227,7 @@ static bool rna_AssetShelf_unregister(Main *bmain, StructRNA *type)
|
|||
|
||||
ed::asset::shelf::type_unlink(*bmain, *shelf_type);
|
||||
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
RNA_struct_free_extension(type, &shelf_type->rna_ext);
|
||||
RNA_struct_free(&RNA_blender_rna_get(), type);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
#include "rna_internal.hh"
|
||||
|
||||
#include "UI_interface_c.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_keymap.hh"
|
||||
#include "WM_types.hh"
|
||||
|
|
@ -1297,14 +1299,14 @@ static PointerRNA rna_Addon_preferences_get(PointerRNA *ptr)
|
|||
}
|
||||
}
|
||||
|
||||
static bool rna_AddonPref_unregister(Main * /*bmain*/, StructRNA *type)
|
||||
static bool rna_AddonPref_unregister(Main *bmain, StructRNA *type)
|
||||
{
|
||||
bAddonPrefType *apt = static_cast<bAddonPrefType *>(RNA_struct_blender_type_get(type));
|
||||
|
||||
if (!apt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
RNA_struct_free_extension(type, &apt->rna_ext);
|
||||
RNA_struct_free(&RNA_blender_rna_get(), type);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "rna_internal.hh"
|
||||
|
||||
#include "UI_interface_c.hh"
|
||||
#include "UI_interface_layout.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
|
@ -1363,7 +1364,7 @@ static IDProperty **rna_wmKeyConfigPref_idprops(PointerRNA *ptr)
|
|||
return reinterpret_cast<IDProperty **>(&ptr->data);
|
||||
}
|
||||
|
||||
static bool rna_wmKeyConfigPref_unregister(Main * /*bmain*/, StructRNA *type)
|
||||
static bool rna_wmKeyConfigPref_unregister(Main *bmain, StructRNA *type)
|
||||
{
|
||||
wmKeyConfigPrefType_Runtime *kpt_rt = static_cast<wmKeyConfigPrefType_Runtime *>(
|
||||
RNA_struct_blender_type_get(type));
|
||||
|
|
@ -1371,7 +1372,7 @@ static bool rna_wmKeyConfigPref_unregister(Main * /*bmain*/, StructRNA *type)
|
|||
if (!kpt_rt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
RNA_struct_free_extension(type, &kpt_rt->rna_ext);
|
||||
RNA_struct_free(&RNA_blender_rna_get(), type);
|
||||
|
||||
|
|
@ -1944,7 +1945,8 @@ static bool rna_Operator_unregister(Main *bmain, StructRNA *type)
|
|||
if (!ot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ui::refresh_for_srna_unregister(bmain, ot->srna);
|
||||
ui::refresh_for_srna_unregister(bmain, type);
|
||||
/* update while blender is running */
|
||||
wm = static_cast<wmWindowManager *>(bmain->wm.first);
|
||||
if (wm) {
|
||||
|
|
|
|||
|
|
@ -1912,7 +1912,7 @@ wmOperatorStatus WM_operator_redo_popup(bContext *C, wmOperator *op)
|
|||
|
||||
/* Operator is stored and kept alive in the window manager. So passing a pointer to the UI is
|
||||
* fine, it will remain valid. */
|
||||
ui::popup_block_invoke(C, wm_block_create_redo, op, nullptr);
|
||||
ui::popup_block_invoke(C, wm_block_create_redo, op, nullptr, op->type->srna);
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1733,6 +1733,7 @@ if(WITH_UI_TESTS)
|
|||
test_render.interactive_rendering_cycles
|
||||
test_render.interactive_rendering_eevee
|
||||
test_render.animation_rendering_and_player
|
||||
test_bpy_types.unregister_referenced_type
|
||||
)
|
||||
foreach(ui_test ${_ui_tests})
|
||||
add_blender_test_ui(
|
||||
|
|
|
|||
64
tests/python/ui_simulate/test_bpy_types.py
Normal file
64
tests/python/ui_simulate/test_bpy_types.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# SPDX-FileCopyrightText: 2026 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
"""
|
||||
This file does not run anything, its methods are accessed for tests by ``run_blender_setup.py``.
|
||||
"""
|
||||
import modules.ui_test_utils as ui
|
||||
|
||||
|
||||
def _test_panel():
|
||||
from bpy.types import Panel
|
||||
|
||||
class TEST_PT_panel(Panel):
|
||||
bl_label = "Test Panel"
|
||||
bl_idname = "TEST_PT_panel"
|
||||
bl_category = 'Test Panel'
|
||||
bl_space_type = 'TEXT_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
|
||||
def draw(self, context):
|
||||
self.layout.operator("test.operator")
|
||||
|
||||
return TEST_PT_panel
|
||||
|
||||
|
||||
def _test_operator():
|
||||
from bpy.types import Operator
|
||||
|
||||
class TEST_PT_operator(Operator):
|
||||
bl_label = "Test Operator"
|
||||
bl_idname = "test.operator"
|
||||
bl_category = 'Test Operator'
|
||||
|
||||
def execute(self, context):
|
||||
return {'FINISHED'}
|
||||
|
||||
return TEST_PT_operator
|
||||
|
||||
|
||||
def unregister_referenced_type():
|
||||
e, _t, _window = ui.test_window()
|
||||
|
||||
test_panel = _test_panel()
|
||||
test_operator = _test_operator()
|
||||
import bpy
|
||||
|
||||
bpy.utils.register_class(test_panel)
|
||||
bpy.utils.register_class(test_operator)
|
||||
|
||||
yield
|
||||
|
||||
# Show the popup with a 'test.operator' reference
|
||||
bpy.ops.wm.call_panel(name=test_panel.bl_idname, keep_open=True)
|
||||
|
||||
yield
|
||||
|
||||
bpy.utils.unregister_class(test_operator)
|
||||
|
||||
# Let popup be refreshed
|
||||
yield
|
||||
|
||||
# If the reference is not removed activating the button should crash
|
||||
yield e.ret()
|
||||
Loading…
Add table
Add a link
Reference in a new issue