UI: Interleave essentials modifiers in "Generate" menu
Hardocde the position of the essentials assets in the menu, for consistent alphabetical order and a clearer indication of the different between the nodes and builtin "Array" modifiers (the old one is now called "Array (Legacy)"). Pull Request: https://projects.blender.org/blender/blender/pulls/146887
This commit is contained in:
@@ -4,6 +4,9 @@
|
||||
|
||||
import bpy
|
||||
from bpy.types import Panel, Menu, Operator
|
||||
from bpy.app.translations import (
|
||||
pgettext_n as n_,
|
||||
)
|
||||
|
||||
|
||||
class ModifierButtonsPanel:
|
||||
@@ -25,16 +28,29 @@ class ModifierAddMenu:
|
||||
MODIFIER_TYPES_I18N_CONTEXT = bpy.types.Modifier.bl_rna.properties["type"].translation_context
|
||||
|
||||
@classmethod
|
||||
def operator_modifier_add(cls, layout, mod_type):
|
||||
def operator_modifier_add(cls, layout, mod_type, text=None, no_icon=False):
|
||||
label = text if text else cls.MODIFIER_TYPES_TO_LABELS[mod_type]
|
||||
layout.operator(
|
||||
"object.modifier_add",
|
||||
text=cls.MODIFIER_TYPES_TO_LABELS[mod_type],
|
||||
text=label,
|
||||
# Although these are operators, the label actually comes from an (enum) property,
|
||||
# so the property's translation context must be used here.
|
||||
text_ctxt=cls.MODIFIER_TYPES_I18N_CONTEXT,
|
||||
icon=cls.MODIFIER_TYPES_TO_ICONS[mod_type],
|
||||
icon='NONE' if no_icon else cls.MODIFIER_TYPES_TO_ICONS[mod_type],
|
||||
).type = mod_type
|
||||
|
||||
@classmethod
|
||||
def operator_modifier_add_asset(cls, layout, name, icon='NONE'):
|
||||
props = layout.operator(
|
||||
"object.modifier_add_node_group",
|
||||
text=name,
|
||||
text_ctxt=cls.MODIFIER_TYPES_I18N_CONTEXT,
|
||||
icon=icon,
|
||||
)
|
||||
props.asset_library_type = 'ESSENTIALS'
|
||||
props.asset_library_identifier = ""
|
||||
props.relative_asset_identifier = "geometry_nodes/geometry_nodes_essentials.blend/NodeTree/" + name
|
||||
|
||||
|
||||
class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
||||
bl_label = "Modifiers"
|
||||
@@ -132,12 +148,14 @@ class OBJECT_MT_modifier_add_generate(ModifierAddMenu, Menu):
|
||||
layout = self.layout
|
||||
ob_type = context.object.type
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
||||
self.operator_modifier_add(layout, 'ARRAY')
|
||||
self.operator_modifier_add_asset(layout, 'Array', icon='MOD_ARRAY')
|
||||
self.operator_modifier_add(layout, 'ARRAY', text=n_("Array (Legacy)"), no_icon=True)
|
||||
self.operator_modifier_add(layout, 'BEVEL')
|
||||
if ob_type == 'MESH':
|
||||
self.operator_modifier_add(layout, 'BOOLEAN')
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
||||
self.operator_modifier_add(layout, 'BUILD')
|
||||
self.operator_modifier_add_asset(layout, n_('Curve to Tube'))
|
||||
self.operator_modifier_add(layout, 'DECIMATE')
|
||||
self.operator_modifier_add(layout, 'EDGE_SPLIT')
|
||||
if ob_type == 'MESH':
|
||||
@@ -150,6 +168,7 @@ class OBJECT_MT_modifier_add_generate(ModifierAddMenu, Menu):
|
||||
self.operator_modifier_add(layout, 'MULTIRES')
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
|
||||
self.operator_modifier_add(layout, 'REMESH')
|
||||
self.operator_modifier_add_asset(layout, n_('Scatter on Surface'))
|
||||
self.operator_modifier_add(layout, 'SCREW')
|
||||
if ob_type == 'MESH':
|
||||
self.operator_modifier_add(layout, 'SKIN')
|
||||
@@ -175,7 +194,7 @@ class OBJECT_MT_modifier_add_generate(ModifierAddMenu, Menu):
|
||||
self.operator_modifier_add(layout, 'GREASE_PENCIL_OUTLINE')
|
||||
self.operator_modifier_add(layout, 'GREASE_PENCIL_SIMPLIFY')
|
||||
self.operator_modifier_add(layout, 'GREASE_PENCIL_SUBDIV')
|
||||
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
|
||||
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label, skip_essentials=True)
|
||||
|
||||
|
||||
class OBJECT_MT_modifier_add_deform(ModifierAddMenu, Menu):
|
||||
|
||||
@@ -609,6 +609,8 @@ void data_xform_by_mat4(XFormObjectData &xod, const float4x4 &transform);
|
||||
void data_xform_restore(XFormObjectData &xod);
|
||||
void data_xform_tag_update(XFormObjectData &xod);
|
||||
|
||||
void ui_template_modifier_asset_menu_items(uiLayout &layout, StringRef catalog_path);
|
||||
void ui_template_modifier_asset_menu_items(uiLayout &layout,
|
||||
StringRef catalog_path,
|
||||
bool skip_essentials);
|
||||
|
||||
} // namespace blender::ed::object
|
||||
|
||||
@@ -85,6 +85,7 @@ static void catalog_assets_draw(const bContext *C, Menu *menu)
|
||||
if (!menu_path) {
|
||||
return;
|
||||
}
|
||||
const int skip_essentials = CTX_data_int_get(C, "skip_essentials").value_or(0);
|
||||
const Span<asset_system::AssetRepresentation *> assets = tree.assets_per_path.lookup(
|
||||
menu_path->data());
|
||||
const asset_system::AssetCatalogTreeItem *catalog_item = tree.catalogs.find_item(
|
||||
@@ -96,16 +97,30 @@ static void catalog_assets_draw(const bContext *C, Menu *menu)
|
||||
}
|
||||
|
||||
uiLayout *layout = menu->layout;
|
||||
layout->separator();
|
||||
|
||||
bool first = true;
|
||||
const auto ensure_separator = [&]() {
|
||||
if (first) {
|
||||
layout->separator();
|
||||
first = false;
|
||||
}
|
||||
};
|
||||
|
||||
wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_modifier_add_node_group", true);
|
||||
for (const asset_system::AssetRepresentation *asset : assets) {
|
||||
if (skip_essentials) {
|
||||
if (asset->owner_asset_library().library_reference()->type == ASSET_LIBRARY_ESSENTIALS) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ensure_separator();
|
||||
PointerRNA props_ptr = layout->op(
|
||||
ot, IFACE_(asset->get_name()), ICON_NONE, wm::OpCallContext::InvokeDefault, UI_ITEM_NONE);
|
||||
asset::operator_asset_reference_props_set(*asset, props_ptr);
|
||||
}
|
||||
|
||||
catalog_item->foreach_child([&](const asset_system::AssetCatalogTreeItem &item) {
|
||||
ensure_separator();
|
||||
asset::draw_menu_for_catalog(item, "OBJECT_MT_add_modifier_catalog_assets", *layout);
|
||||
});
|
||||
}
|
||||
@@ -388,7 +403,9 @@ void object_modifier_add_asset_register()
|
||||
WM_operatortype_append(OBJECT_OT_modifier_add_node_group);
|
||||
}
|
||||
|
||||
void ui_template_modifier_asset_menu_items(uiLayout &layout, const StringRef catalog_path)
|
||||
void ui_template_modifier_asset_menu_items(uiLayout &layout,
|
||||
const StringRef catalog_path,
|
||||
const bool skip_essentials)
|
||||
{
|
||||
asset::AssetItemTree &tree = *get_static_item_tree();
|
||||
const asset_system::AssetCatalogTreeItem *item = tree.catalogs.find_root_item(catalog_path);
|
||||
@@ -400,9 +417,9 @@ void ui_template_modifier_asset_menu_items(uiLayout &layout, const StringRef cat
|
||||
if (!all_library) {
|
||||
return;
|
||||
}
|
||||
layout.separator();
|
||||
uiLayout *col = &layout.column(false);
|
||||
col->context_string_set("asset_catalog_path", item->catalog_path().str());
|
||||
col->context_int_set("skip_essentials", skip_essentials);
|
||||
col->menu_contents("OBJECT_MT_add_modifier_catalog_assets");
|
||||
}
|
||||
|
||||
|
||||
@@ -915,10 +915,12 @@ static void rna_uiLayout_template_node_operator_asset_menu_items(uiLayout *layou
|
||||
}
|
||||
|
||||
static void rna_uiLayout_template_modifier_asset_menu_items(uiLayout *layout,
|
||||
const char *catalog_path)
|
||||
const char *catalog_path,
|
||||
const bool skip_essentials)
|
||||
{
|
||||
using namespace blender;
|
||||
ed::object::ui_template_modifier_asset_menu_items(*layout, StringRef(catalog_path));
|
||||
ed::object::ui_template_modifier_asset_menu_items(
|
||||
*layout, StringRef(catalog_path), skip_essentials);
|
||||
}
|
||||
|
||||
static void rna_uiLayout_template_node_operator_root_items(uiLayout *layout, bContext *C)
|
||||
@@ -2150,6 +2152,7 @@ void RNA_api_ui_layout(StructRNA *srna)
|
||||
"template_modifier_asset_menu_items",
|
||||
"rna_uiLayout_template_modifier_asset_menu_items");
|
||||
parm = RNA_def_string(func, "catalog_path", nullptr, 0, "", "");
|
||||
parm = RNA_def_boolean(func, "skip_essentials", false, "", "");
|
||||
|
||||
func = RNA_def_function(srna,
|
||||
"template_node_operator_asset_menu_items",
|
||||
|
||||
Reference in New Issue
Block a user