Sculpt/Paint: Asset shelf option to filter brushes by the active tool
Part of: https://projects.blender.org/blender/blender/issues/128066 Adds a "Filter by Active Tool" option for the brush asset shelves, enabled by default. If enabled, the asset shelf only shows brushes matching the brush type of the current tool. If the general "Brush" tool is active, only brushes that are not covered by another tool are displayed. The popup brush selector always shows all assets. The option is stored in the Preferences, toggled in the "Display Settings" popover of the asset shelf. Note: This is committed to the 4.3 release branch, which was discussed in advance. Pull Request: https://projects.blender.org/blender/blender/pulls/128450
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import bpy
|
||||
from bpy.types import Menu
|
||||
from bpy.types import Menu, Panel
|
||||
|
||||
|
||||
class BrushAssetShelf:
|
||||
@@ -18,12 +18,43 @@ class BrushAssetShelf:
|
||||
def poll(cls, context):
|
||||
return hasattr(context, "object") and context.object and context.object.mode == cls.mode
|
||||
|
||||
@classmethod
|
||||
def has_tool_with_brush_type(cls, context, brush_type):
|
||||
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
||||
space_type = context.space_data.type
|
||||
|
||||
brush_type_items = bpy.types.Brush.bl_rna.properties[cls.tool_prop].enum_items
|
||||
|
||||
tool_helper_cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
|
||||
for item in ToolSelectPanelHelper._tools_flatten(
|
||||
tool_helper_cls.tools_from_context(context, mode=context.mode),
|
||||
):
|
||||
if item is None:
|
||||
continue
|
||||
if item.idname in {
|
||||
"builtin.arc",
|
||||
"builtin.curve",
|
||||
"builtin.line",
|
||||
"builtin.box",
|
||||
"builtin.circle",
|
||||
"builtin.polyline",
|
||||
}:
|
||||
continue
|
||||
if item.options is None or ('USE_BRUSHES' not in item.options):
|
||||
continue
|
||||
if item.brush_type is not None:
|
||||
if brush_type_items[item.brush_type].value == brush_type:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@classmethod
|
||||
def brush_type_poll(cls, context, asset):
|
||||
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
||||
tool = ToolSelectPanelHelper.tool_active_from_context(context)
|
||||
|
||||
if not tool or tool.brush_type == 'ANY':
|
||||
if not tool:
|
||||
return True
|
||||
if not cls.brush_type_prop or not cls.tool_prop:
|
||||
return True
|
||||
@@ -33,9 +64,14 @@ class BrushAssetShelf:
|
||||
# certain brush type.
|
||||
if asset_brush_type is None:
|
||||
return False
|
||||
brush_type_items = bpy.types.Brush.bl_rna.properties[cls.tool_prop].enum_items
|
||||
|
||||
return brush_type_items[asset_brush_type].identifier == tool.brush_type
|
||||
# For the general brush that supports any brush type, filter out brushes that show up for
|
||||
# other tools already.
|
||||
if tool.brush_type == 'ANY':
|
||||
return not cls.has_tool_with_brush_type(context, asset_brush_type)
|
||||
|
||||
brush_type_items = bpy.types.Brush.bl_rna.properties[cls.tool_prop].enum_items
|
||||
return brush_type_items[tool.brush_type].value == asset_brush_type
|
||||
|
||||
@classmethod
|
||||
def asset_poll(cls, asset):
|
||||
@@ -45,12 +81,13 @@ class BrushAssetShelf:
|
||||
return False
|
||||
|
||||
context = bpy.context
|
||||
prefs = context.preferences
|
||||
|
||||
is_asset_shelf_region = context.region and context.region.type == 'ASSET_SHELF'
|
||||
# Show all brushes in the permanent asset shelf region. Otherwise filter out brushes that
|
||||
# Show all brushes in the popup asset shelves. Otherwise filter out brushes that
|
||||
# are incompatible with the tool.
|
||||
if not is_asset_shelf_region and not cls.brush_type_poll(context, asset):
|
||||
return False
|
||||
if is_asset_shelf_region and prefs.view.use_filter_brushes_by_tool:
|
||||
return cls.brush_type_poll(context, asset)
|
||||
|
||||
return True
|
||||
|
||||
@@ -112,6 +149,25 @@ class BrushAssetShelf:
|
||||
)
|
||||
|
||||
|
||||
class VIEW3D_PT_brush_asset_shelf_filter(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'HEADER'
|
||||
bl_label = "Filter"
|
||||
bl_parent_id = "ASSETSHELF_PT_display"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if context.asset_shelf is None:
|
||||
return False
|
||||
return context.asset_shelf.bl_idname == BrushAssetShelf.get_shelf_name_from_context(context)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
prefs = context.preferences
|
||||
|
||||
layout.prop(prefs.view, "use_filter_brushes_by_tool", text="By Active Tool")
|
||||
|
||||
|
||||
class UnifiedPaintPanel:
|
||||
# subclass must set
|
||||
# bl_space_type = 'IMAGE_EDITOR'
|
||||
@@ -1828,6 +1884,7 @@ def brush_basic_grease_pencil_vertex_settings(layout, context, brush, *, compact
|
||||
|
||||
|
||||
classes = (
|
||||
VIEW3D_PT_brush_asset_shelf_filter,
|
||||
VIEW3D_MT_tools_projectpaint_clone,
|
||||
)
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ extern "C" {
|
||||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 29
|
||||
#define BLENDER_FILE_SUBVERSION 30
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
||||
|
||||
@@ -946,7 +946,7 @@ void blo_do_versions_userdef(UserDef *userdef)
|
||||
|
||||
if (!USER_VERSION_ATLEAST(400, 24)) {
|
||||
/* Clear deprecated USER_MENUFIXEDORDER user flag for reuse. */
|
||||
userdef->uiflag &= ~USER_UIFLAG_UNUSED_4;
|
||||
userdef->uiflag &= ~(1 << 23);
|
||||
}
|
||||
|
||||
if (!USER_VERSION_ATLEAST(400, 26)) {
|
||||
@@ -1064,6 +1064,10 @@ void blo_do_versions_userdef(UserDef *userdef)
|
||||
userdef->sequencer_editor_flag |= USER_SEQ_ED_CONNECT_STRIPS_BY_DEFAULT;
|
||||
}
|
||||
|
||||
if (!USER_VERSION_ATLEAST(403, 30)) {
|
||||
userdef->uiflag |= USER_FILTER_BRUSHES_BY_TOOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always bump subversion in BKE_blender_version.h when adding versioning
|
||||
* code here, and wrap it inside a USER_VERSION_ATLEAST check.
|
||||
|
||||
@@ -1294,7 +1294,8 @@ typedef enum eUserpref_UI_Flag {
|
||||
USER_ZOOM_TO_MOUSEPOS = (1 << 20),
|
||||
USER_SHOW_FPS = (1 << 21),
|
||||
USER_REGISTER_ALL_USERS = (1 << 22),
|
||||
USER_UIFLAG_UNUSED_4 = (1 << 23), /* Cleared. */
|
||||
/** Actually implemented in .py. */
|
||||
USER_FILTER_BRUSHES_BY_TOOL = (1 << 23),
|
||||
USER_CONTINUOUS_MOUSE = (1 << 24),
|
||||
USER_ZOOM_INVERT = (1 << 25),
|
||||
USER_ZOOM_HORIZ = (1 << 26), /* for CONTINUE and DOLLY zoom */
|
||||
|
||||
@@ -5323,6 +5323,14 @@ static void rna_def_userdef_view(BlenderRNA *brna)
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "uiflag", USER_PLAINMENUS);
|
||||
RNA_def_property_ui_text(prop, "Toolbox Column Layout", "Use a column layout for toolbox");
|
||||
|
||||
prop = RNA_def_property(srna, "use_filter_brushes_by_tool", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "uiflag", USER_FILTER_BRUSHES_BY_TOOL);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Filter Brushes by Tool",
|
||||
"Only show brushes applicable for the currently active tool in the "
|
||||
"asset shelf. Stored in the Preferences, which may have to be saved "
|
||||
"manually if Auto-Save Preferences is disabled");
|
||||
|
||||
static const EnumPropertyItem header_align_items[] = {
|
||||
{0, "NONE", 0, "Keep Existing", "Keep existing header alignment"},
|
||||
{USER_HEADER_FROM_PREF, "TOP", 0, "Top", "Top aligned on load"},
|
||||
|
||||
Reference in New Issue
Block a user