Refactor: UI changes for collection export presets #120034

Open
Brecht Van Lommel wants to merge 3 commits from brecht/blender:operator-presets into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
6 changed files with 62 additions and 2 deletions

View File

@ -1099,7 +1099,7 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
def path_menu(self, searchpaths, operator, *,
props_default=None, prop_filepath="filepath",
filter_ext=None, filter_path=None, display_name=None,
add_operator=None):
add_operator=None, add_operator_props=None):
"""
Populate a menu from a list of paths.
@ -1176,6 +1176,9 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
props = row.operator(add_operator, text="", icon='REMOVE')
props.name = name
props.remove_name = True
if add_operator_props is not None:
for attr, value in add_operator_props.items():
setattr(props, attr, value)
if add_operator:
wm = bpy.data.window_managers[0]
@ -1189,6 +1192,9 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
props = row.operator(add_operator, text="", icon='ADD')
props.name = wm.preset_name
if add_operator_props is not None:
for attr, value in add_operator_props.items():
setattr(props, attr, value)
def draw_preset(self, _context):
"""
@ -1205,12 +1211,14 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
ext_valid = getattr(self, "preset_extensions", {".py", ".xml"})
props_default = getattr(self, "preset_operator_defaults", None)
add_operator = getattr(self, "preset_add_operator", None)
add_operator_props = getattr(self, "preset_add_operator_properties", None)
self.path_menu(
bpy.utils.preset_paths(self.preset_subdir),
self.preset_operator,
props_default=props_default,
filter_ext=lambda ext: ext.lower() in ext_valid,
add_operator=add_operator,
add_operator_props=add_operator_props,
display_name=lambda name: bpy.path.display_name(name, title_case=False)
)

View File

@ -7,6 +7,7 @@ from bpy.types import (
Menu,
Operator,
OperatorFileListElement,
Panel,
WindowManager,
)
from bpy.props import (
@ -18,6 +19,7 @@ from bpy.app.translations import (
pgettext_rpt as rpt_,
pgettext_data as data_,
)
from bl_ui.utils import PresetPanel
# For preset popover menu
@ -750,6 +752,24 @@ class WM_MT_operator_presets(Menu):
preset_operator = "script.execute_preset"
class WM_PT_operator_presets(PresetPanel, Panel):
bl_label = "Operator Presets"
preset_add_operator = "wm.operator_preset_add"
preset_operator = "script.execute_preset"
@property
def preset_subdir(self):
return AddPresetOperator.operator_path(self.operator)
@property
def preset_add_operator_properties(self):
return {"operator": self.operator}
def draw(self, context):
self.operator = context.active_operator.bl_idname
PresetPanel.draw(self, context)
class WM_OT_operator_presets_cleanup(Operator):
"""Remove outdated operator properties from presets that may cause problems"""
@ -921,5 +941,6 @@ classes = (
AddPresetEEVEERaytracing,
ExecutePreset,
WM_MT_operator_presets,
WM_PT_operator_presets,
WM_OT_operator_presets_cleanup,
)

View File

@ -841,6 +841,11 @@ bool UI_block_is_search_only(const uiBlock *block);
*/
void UI_block_set_search_only(uiBlock *block, bool search_only);
/**
* Used for operator presets.
*/
void UI_block_set_active_operator(uiBlock *block, wmOperator *op, const bool free);
/**
* Can be called with C==NULL.
*/

View File

@ -3438,6 +3438,29 @@ static void ui_but_free(const bContext *C, uiBut *but)
MEM_delete(but);
}
static void ui_block_free_active_operator(uiBlock *block)
{
if (block->ui_operator_free) {
/* This assumes the operator instance owns the pointer. This is not
* true for all operators by default, but it can be copied when needed. */
MEM_freeN(block->ui_operator->ptr);
MEM_freeN(block->ui_operator);
}
block->ui_operator_free = false;
block->ui_operator = nullptr;
}
void UI_block_set_active_operator(uiBlock *block, wmOperator *op, const bool free)
{
if (op != block->ui_operator) {
ui_block_free_active_operator(block);
block->ui_operator = op;
block->ui_operator_free = free;
}
}
void UI_block_free(const bContext *C, uiBlock *block)
{
UI_butstore_clear(block);
@ -3454,6 +3477,8 @@ void UI_block_free(const bContext *C, uiBlock *block)
MEM_freeN(block->func_argN);
}
ui_block_free_active_operator(block);
BLI_freelistN(&block->saferct);
BLI_freelistN(&block->color_pickers.list);
BLI_freelistN(&block->dynamic_listeners);

View File

@ -613,6 +613,7 @@ struct uiBlock {
/** use so presets can find the operator,
* across menus and from nested popups which fail for operator context. */
wmOperator *ui_operator;
bool ui_operator_free;
/** XXX hack for dynamic operator enums */
void *evil_C;

View File

@ -2727,7 +2727,7 @@ static eAutoPropButsReturn template_operator_property_buts_draw_single(
PointerRNA op_ptr;
uiLayout *row;
block->ui_operator = op;
UI_block_set_active_operator(block, op, false);
row = uiLayoutRow(layout, true);
uiItemM(row, "WM_MT_operator_presets", nullptr, ICON_NONE);