WIP: Brush assets project #106303

Draft
Julian Eisel wants to merge 358 commits from brush-assets-project into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
4 changed files with 0 additions and 299 deletions
Showing only changes of commit 5cc18152c0 - Show all commits

View File

@ -107,10 +107,6 @@ def generate(context, space_type, *, use_fallback_keys=True, use_reset=True):
kmi_hack_properties = kmi_hack.properties
kmi_hack.active = False
kmi_hack_brush_select = keymap.keymap_items.new("paint.brush_select", 'NONE', 'PRESS')
kmi_hack_brush_select_properties = kmi_hack_brush_select.properties
kmi_hack_brush_select.active = False
if use_release_confirm or use_tap_reset:
kmi_toolbar = wm.keyconfigs.find_item_from_operator(
idname="wm.toolbar",
@ -169,46 +165,6 @@ def generate(context, space_type, *, use_fallback_keys=True, use_reset=True):
include={'KEYBOARD'},
)[1]
if kmi_found is None:
if item.data_block:
# PAINT_OT_brush_select
mode = context.active_object.mode
# See: BKE_paint_get_tool_prop_id_from_paintmode
if space_type == 'IMAGE_EDITOR':
if context.space_data.mode == 'PAINT':
attr = "image_tool"
else:
attr = None
elif space_type == 'VIEW_3D':
attr = {
'SCULPT': "sculpt_tool",
'VERTEX_PAINT': "vertex_tool",
'WEIGHT_PAINT': "weight_tool",
'TEXTURE_PAINT': "image_tool",
'PAINT_GPENCIL': "gpencil_tool",
'VERTEX_GPENCIL': "gpencil_vertex_tool",
'SCULPT_GPENCIL': "gpencil_sculpt_tool",
'WEIGHT_GPENCIL': "gpencil_weight_tool",
'SCULPT_CURVES': "curves_sculpt_tool",
}.get(mode, None)
else:
attr = None
if attr is not None:
setattr(kmi_hack_brush_select_properties, attr, item.data_block)
kmi_found = wm.keyconfigs.find_item_from_operator(
idname="paint.brush_select",
context='INVOKE_REGION_WIN',
properties=kmi_hack_brush_select_properties,
include={'KEYBOARD'},
)[1]
elif mode in {'EDIT', 'PARTICLE_EDIT', 'SCULPT_GPENCIL'}:
# Doesn't use brushes
pass
else:
print("Unsupported mode:", mode)
del mode, attr
else:
kmi_found = None

View File

@ -5501,27 +5501,6 @@ def km_sculpt(params):
op_menu_pie("VIEW3D_MT_sculpt_automasking_pie", {"type": 'A', "alt": True, "value": 'PRESS'}),
op_menu_pie("VIEW3D_MT_sculpt_face_sets_edit_pie", {"type": 'W', "value": 'PRESS', "alt": True}),
*_template_items_context_panel("VIEW3D_PT_sculpt_context_menu", params.context_menu_event),
# Tools
("paint.brush_select", {"type": 'V', "value": 'PRESS'},
{"properties": [("sculpt_tool", 'DRAW')]}),
("paint.brush_select", {"type": 'S', "value": 'PRESS'},
{"properties": [("sculpt_tool", 'SMOOTH')]}),
("paint.brush_select", {"type": 'P', "value": 'PRESS'},
{"properties": [("sculpt_tool", 'PINCH')]}),
("paint.brush_select", {"type": 'I', "value": 'PRESS'},
{"properties": [("sculpt_tool", 'INFLATE')]}),
("paint.brush_select", {"type": 'G', "value": 'PRESS'},
{"properties": [("sculpt_tool", 'GRAB')]}),
("paint.brush_select", {"type": 'T', "value": 'PRESS', "shift": True},
{"properties": [("sculpt_tool", 'SCRAPE')]}),
("paint.brush_select", {"type": 'C', "value": 'PRESS'},
{"properties": [("sculpt_tool", 'CLAY_STRIPS')]}),
("paint.brush_select", {"type": 'C', "value": 'PRESS', "shift": True},
{"properties": [("sculpt_tool", 'CREASE')]}),
("paint.brush_select", {"type": 'K', "value": 'PRESS'},
{"properties": [("sculpt_tool", 'SNAKE_HOOK')]}),
("paint.brush_select", {"type": 'M', "value": 'PRESS'},
{"properties": [("sculpt_tool", 'MASK'), ("toggle", True), ("create_missing", True)]}),
])
# Lasso Masking.

View File

@ -559,7 +559,6 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
/* There are different kinds of shortcuts:
*
* - Direct access to the tool (as if the toolbar button is pressed).
* - The key is bound to a brush type (not the exact brush name).
* - The key is assigned to the operator itself
* (bypassing the tool, executing the operator).
*
@ -567,36 +566,6 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
*/
std::string shortcut = UI_but_string_get_operator_keymap(*C, *but);
if (shortcut.empty()) {
const PaintMode paint_mode = BKE_paintmode_get_active_from_context(C);
const char *tool_attr = BKE_paint_get_tool_prop_id_from_paintmode(paint_mode);
if (tool_attr != nullptr) {
const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
const char *tool_id_lstrip = strrchr(tool_id, '.');
const int tool_id_offset = tool_id_lstrip ? ((tool_id_lstrip - tool_id) + 1) : 0;
const int i = RNA_enum_from_name(items, tool_id + tool_id_offset);
if (i != -1) {
wmOperatorType *ot = WM_operatortype_find("paint.brush_select", true);
PointerRNA op_props;
WM_operator_properties_create_ptr(&op_props, ot);
RNA_enum_set(&op_props, tool_attr, items[i].value);
/* Check for direct access to the tool. */
if (std::optional<std::string> shortcut_brush = WM_key_event_operator_string(
C,
ot->idname,
WM_OP_INVOKE_REGION_WIN,
static_cast<IDProperty *>(op_props.data),
true))
{
shortcut = *shortcut_brush;
}
WM_operator_properties_free(&op_props);
}
}
}
if (shortcut.empty()) {
/* Check for direct access to the tool. */
if (std::optional<std::string> shortcut_toolbar = WM_key_event_operator_string(

View File

@ -754,206 +754,6 @@ static void BRUSH_OT_reset(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int brush_tool(const Brush *brush, size_t tool_offset)
{
return *(((char *)brush) + tool_offset);
}
static void brush_tool_set(const Brush *brush, size_t tool_offset, int tool)
{
*(((char *)brush) + tool_offset) = tool;
}
static Brush *brush_tool_cycle(Main *bmain, Paint *paint, Brush *brush_orig, const int tool)
{
Brush *brush, *first_brush;
if (!brush_orig && !(brush_orig = static_cast<Brush *>(bmain->brushes.first))) {
return nullptr;
}
if (brush_tool(brush_orig, paint->runtime.tool_offset) != tool) {
/* If current brush's tool is different from what we need,
* start cycling from the beginning of the list.
* Such logic will activate the same exact brush not relating from
* which tool user requests other tool.
*/
/* Try to tool-slot first. */
first_brush = BKE_paint_toolslots_brush_get(paint, tool);
if (first_brush == nullptr) {
first_brush = static_cast<Brush *>(bmain->brushes.first);
}
}
else {
/* If user wants to switch to brush with the same tool as
* currently active brush do a cycling via all possible
* brushes with requested tool. */
first_brush = brush_orig->id.next ? static_cast<Brush *>(brush_orig->id.next) :
static_cast<Brush *>(bmain->brushes.first);
}
/* get the next brush with the active tool */
brush = first_brush;
do {
if ((brush->ob_mode & paint->runtime.ob_mode) &&
(brush_tool(brush, paint->runtime.tool_offset) == tool))
{
return brush;
}
brush = brush->id.next ? static_cast<Brush *>(brush->id.next) :
static_cast<Brush *>(bmain->brushes.first);
} while (brush != first_brush);
return nullptr;
}
static Brush *brush_tool_toggle(Main *bmain, Paint *paint, Brush *brush_orig, const int tool)
{
if (!brush_orig || brush_tool(brush_orig, paint->runtime.tool_offset) != tool) {
Brush *br;
/* if the current brush is not using the desired tool, look
* for one that is */
br = brush_tool_cycle(bmain, paint, brush_orig, tool);
/* store the previously-selected brush */
if (br) {
br->toggle_brush = brush_orig;
}
return br;
}
if (brush_orig->toggle_brush) {
/* if current brush is using the desired tool, try to toggle
* back to the previously selected brush. */
return brush_orig->toggle_brush;
}
return nullptr;
}
static bool brush_generic_tool_set(bContext *C,
Main *bmain,
Paint *paint,
const int tool,
const char *tool_name,
const bool create_missing,
const bool toggle)
{
Brush *brush, *brush_orig = BKE_paint_brush(paint);
if (toggle) {
brush = brush_tool_toggle(bmain, paint, brush_orig, tool);
}
else {
brush = brush_tool_cycle(bmain, paint, brush_orig, tool);
}
if (((brush == nullptr) && create_missing) &&
((brush_orig == nullptr) || brush_tool(brush_orig, paint->runtime.tool_offset) != tool))
{
brush = BKE_brush_add(bmain, tool_name, eObjectMode(paint->runtime.ob_mode));
id_us_min(&brush->id); /* fake user only */
brush_tool_set(brush, paint->runtime.tool_offset, tool);
brush->toggle_brush = brush_orig;
}
if (brush) {
BKE_paint_brush_set(paint, brush);
BKE_paint_invalidate_overlay_all();
WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);
WM_toolsystem_ref_set_by_id(C, "builtin.brush");
return true;
}
return false;
}
static const PaintMode brush_select_paint_modes[] = {
PaintMode::Sculpt,
PaintMode::Vertex,
PaintMode::Weight,
PaintMode::Texture3D,
PaintMode::GPencil,
PaintMode::VertexGPencil,
PaintMode::SculptGPencil,
PaintMode::WeightGPencil,
PaintMode::SculptCurves,
};
static int brush_select_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
const bool create_missing = RNA_boolean_get(op->ptr, "create_missing");
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
const char *tool_name = "Brush";
int tool = 0;
PaintMode paint_mode = PaintMode::Invalid;
for (int i = 0; i < ARRAY_SIZE(brush_select_paint_modes); i++) {
paint_mode = brush_select_paint_modes[i];
const char *op_prop_id = BKE_paint_get_tool_prop_id_from_paintmode(paint_mode);
PropertyRNA *prop = RNA_struct_find_property(op->ptr, op_prop_id);
if (RNA_property_is_set(op->ptr, prop)) {
tool = RNA_property_enum_get(op->ptr, prop);
break;
}
}
if (paint_mode == PaintMode::Invalid) {
return OPERATOR_CANCELLED;
}
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
if (paint == nullptr) {
return OPERATOR_CANCELLED;
}
// TODO: won't work with asset brushes, needs different main.
if (brush_generic_tool_set(C, bmain, paint, tool, tool_name, create_missing, toggle)) {
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
}
static void PAINT_OT_brush_select(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "Brush Select";
ot->description = "Select a paint mode's brush by tool type";
ot->idname = "PAINT_OT_brush_select";
/* api callbacks */
ot->exec = brush_select_exec;
/* flags */
ot->flag = 0;
/* props */
/* All properties are hidden, so as not to show the redo panel. */
for (int i = 0; i < ARRAY_SIZE(brush_select_paint_modes); i++) {
const PaintMode paint_mode = brush_select_paint_modes[i];
const char *prop_id = BKE_paint_get_tool_prop_id_from_paintmode(paint_mode);
prop = RNA_def_enum(
ot->srna, prop_id, BKE_paint_get_tool_enum_from_paintmode(paint_mode), 0, prop_id, "");
RNA_def_property_translation_context(
prop, BKE_paint_get_tool_enum_translation_context_from_paintmode(paint_mode));
RNA_def_property_flag(prop, PROP_HIDDEN);
}
prop = RNA_def_boolean(
ot->srna, "toggle", false, "Toggle", "Toggle between two brushes rather than cycling");
RNA_def_property_flag(prop, PropertyFlag(PROP_HIDDEN | PROP_SKIP_SAVE));
prop = RNA_def_boolean(ot->srna,
"create_missing",
false,
"Create Missing",
"If the requested brush type does not exist, create a new brush");
RNA_def_property_flag(prop, PropertyFlag(PROP_HIDDEN | PROP_SKIP_SAVE));
}
namespace blender::ed::sculpt_paint {
/**************************** Brush Assets **********************************/
@ -2078,9 +1878,6 @@ void ED_operatortypes_paint()
WM_operatortype_append(BRUSH_OT_asset_update);
WM_operatortype_append(BRUSH_OT_asset_revert);
/* NOTE: particle uses a different system, can be added with existing operators in `wm.py`. */
WM_operatortype_append(PAINT_OT_brush_select);
/* image */
WM_operatortype_append(PAINT_OT_texture_paint_toggle);
WM_operatortype_append(PAINT_OT_image_paint);