Grease Pencil: Properly support brushes with draw mode primitive tools

Part of blender/blender!125449.

Since brush assets were merged, the brush asset selector and some other brush
UIs wouldn't show up for the primitive tools. This is addressed now. The
primitive tools use the same brush as the brush tool, although only the draw
brushes will work properly. !125449 addresses this so the primitive tools
remember their own draw brush, separate from the brush tool.

Turns out that these primitive tools were never tagged as using brushes by
setting the `data_block` member (or setting the `'USE_BRUSHES'` option since
b64bf66257). The UI was just hardcoded to display things like the brush selector
for primitive tools. So as far as the tool system knew, these tools did not use
brushes.

Tagging the tools properly exposed some issues that are addressed here (see PR
for details).

Pull Request: https://projects.blender.org/blender/blender/pulls/127204
This commit is contained in:
Julian Eisel
2024-09-16 13:04:08 +02:00
committed by Julian Eisel
parent d52d70324d
commit 65fdb3fa30
9 changed files with 93 additions and 12 deletions

View File

@@ -2019,6 +2019,9 @@ class _defs_grease_pencil_paint:
widget=None,
keymap=(),
draw_settings=draw_settings,
# Only allow draw brushes, no eraser, fill or tint.
data_block='DRAW',
options={'USE_BRUSHES'},
)
@ToolDef.from_fn
@@ -2035,6 +2038,9 @@ class _defs_grease_pencil_paint:
widget=None,
keymap=(),
draw_settings=draw_settings,
# Only allow draw brushes, no eraser, fill or tint.
data_block='DRAW',
options={'USE_BRUSHES'},
)
@ToolDef.from_fn
@@ -2051,6 +2057,9 @@ class _defs_grease_pencil_paint:
widget=None,
keymap=(),
draw_settings=draw_settings,
# Only allow draw brushes, no eraser, fill or tint.
data_block='DRAW',
options={'USE_BRUSHES'},
)
@ToolDef.from_fn
@@ -2067,6 +2076,9 @@ class _defs_grease_pencil_paint:
widget=None,
keymap=(),
draw_settings=draw_settings,
# Only allow draw brushes, no eraser, fill or tint.
data_block='DRAW',
options={'USE_BRUSHES'},
)
@ToolDef.from_fn
@@ -2083,6 +2095,9 @@ class _defs_grease_pencil_paint:
widget=None,
keymap=(),
draw_settings=draw_settings,
# Only allow draw brushes, no eraser, fill or tint.
data_block='DRAW',
options={'USE_BRUSHES'},
)
@ToolDef.from_fn
@@ -2099,6 +2114,9 @@ class _defs_grease_pencil_paint:
widget=None,
keymap=(),
draw_settings=draw_settings,
# Only allow draw brushes, no eraser, fill or tint.
data_block='DRAW',
options={'USE_BRUSHES'},
)
@ToolDef.from_fn

View File

@@ -719,6 +719,17 @@ class _draw_tool_settings_context_mode:
if (tool is None) or (not tool.use_brushes):
return False
# These draw their own properties.
if tool.idname in {
"builtin.arc",
"builtin.curve",
"builtin.line",
"builtin.box",
"builtin.circle",
"builtin.polyline",
}:
return False
tool_settings = context.tool_settings
paint = tool_settings.gpencil_paint

View File

@@ -1722,7 +1722,7 @@ void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y)
bool ED_gpencil_brush_cursor_poll(bContext *C)
{
if (WM_toolsystem_active_tool_is_brush(C)) {
if (WM_toolsystem_active_tool_is_brush(C) && !WM_toolsystem_active_tool_has_custom_cursor(C)) {
return true;
}
return false;

View File

@@ -168,7 +168,7 @@ static void keymap_grease_pencil_vertex_paint_mode(wmKeyConfig *keyconf)
keymap->poll = grease_pencil_vertex_painting_poll;
}
/* Enabled for all tools except the fill tool. */
/* Enabled for all tools except the fill tool and primitive tools. */
static bool keymap_grease_pencil_brush_stroke_poll(bContext *C)
{
if (!grease_pencil_painting_poll(C)) {
@@ -177,6 +177,24 @@ static bool keymap_grease_pencil_brush_stroke_poll(bContext *C)
if (!WM_toolsystem_active_tool_is_brush(C)) {
return false;
}
/* Don't use the normal brush stroke keymap while the primitive tools are active. Otherwise
* simple mouse presses start freehand drawing instead of invoking the primitive operators. Could
* be a flag on the tool itself, for now making it a hardcoded exception. */
if (const bToolRef *tref = WM_toolsystem_ref_from_context(C)) {
const Set<StringRef> primitive_tools = {
"builtin.line",
"builtin.polyline",
"builtin.arc",
"builtin.curve",
"builtin.box",
"builtin.circle",
};
if (primitive_tools.contains(tref->idname)) {
return false;
}
}
ToolSettings *ts = CTX_data_tool_settings(C);
Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
return brush && brush->gpencil_settings && brush->gpencil_brush_type != GPAINT_BRUSH_TYPE_FILL;

View File

@@ -132,7 +132,10 @@ void paint_stroke_jitter_pos(Scene &scene,
const float mval[2],
float r_mouse_out[2]);
/** Returns true if the active tool uses brushes. */
bool paint_brush_tool_poll(bContext *C);
/** Returns true if the brush cursor should be activated. */
bool paint_brush_cursor_poll(bContext *C);
bool paint_brush_update(bContext *C,
const Brush &brush,
PaintMode mode,

View File

@@ -1533,8 +1533,11 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
br = BKE_paint_brush(paint);
if (paint_supports_smooth_stroke(stroke, *br, mode)) {
stroke->stroke_cursor = WM_paint_cursor_activate(
SPACE_TYPE_ANY, RGN_TYPE_ANY, paint_brush_tool_poll, paint_draw_smooth_cursor, stroke);
stroke->stroke_cursor = WM_paint_cursor_activate(SPACE_TYPE_ANY,
RGN_TYPE_ANY,
paint_brush_cursor_poll,
paint_draw_smooth_cursor,
stroke);
}
if (br->flag & BRUSH_AIRBRUSH) {
@@ -1544,7 +1547,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
if (br->flag & BRUSH_LINE) {
stroke->stroke_cursor = WM_paint_cursor_activate(
SPACE_TYPE_ANY, RGN_TYPE_ANY, paint_brush_tool_poll, paint_draw_line_cursor, stroke);
SPACE_TYPE_ANY, RGN_TYPE_ANY, paint_brush_cursor_poll, paint_draw_line_cursor, stroke);
}
first_dab = true;
@@ -1721,7 +1724,7 @@ bool paint_stroke_started(PaintStroke *stroke)
return stroke->stroke_started;
}
bool paint_brush_tool_poll(bContext *C)
static const bToolRef *brush_tool_get(const bContext *C)
{
Paint *paint = BKE_paint_get_active_from_context(C);
Object *ob = CTX_data_active_object(C);
@@ -1732,13 +1735,34 @@ bool paint_brush_tool_poll(bContext *C)
(area && ELEM(area->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) &&
(region && region->regiontype == RGN_TYPE_WINDOW))
{
/* Check the current tool is a brush. */
bToolRef *tref = area->runtime.tool;
if (tref && tref->runtime && (tref->runtime->flag & TOOLREF_FLAG_USE_BRUSHES)) {
return true;
if (area->runtime.tool && area->runtime.tool->runtime &&
(area->runtime.tool->runtime->flag & TOOLREF_FLAG_USE_BRUSHES))
{
return area->runtime.tool;
}
}
return false;
return nullptr;
}
bool paint_brush_tool_poll(bContext *C)
{
/* Check the current tool is a brush. */
return brush_tool_get(C) != nullptr;
}
bool paint_brush_cursor_poll(bContext *C)
{
const bToolRef *tref = brush_tool_get(C);
if (!tref) {
return false;
}
/* Don't use brush cursor when the tool sets its own cursor. */
if (tref->runtime->cursor != WM_CURSOR_DEFAULT) {
return false;
}
return true;
}
} // namespace blender::ed::sculpt_paint

View File

@@ -3996,7 +3996,7 @@ static bool is_brush_related_tool(bContext *C)
bool SCULPT_brush_cursor_poll(bContext *C)
{
using namespace blender::ed::sculpt_paint;
return SCULPT_mode_poll(C) && (paint_brush_tool_poll(C) || is_brush_related_tool(C));
return SCULPT_mode_poll(C) && (paint_brush_cursor_poll(C) || is_brush_related_tool(C));
}
static const char *sculpt_brush_type_name(const Sculpt &sd)

View File

@@ -95,6 +95,7 @@ void WM_toolsystem_update_from_context(
* For paint modes to support non-brush tools.
*/
bool WM_toolsystem_active_tool_is_brush(const bContext *C);
bool WM_toolsystem_active_tool_has_custom_cursor(const bContext *C);
/** Follow #wmMsgNotifyFn spec. */
void WM_toolsystem_do_msg_notify_tag_refresh(bContext *C,

View File

@@ -784,6 +784,12 @@ bool WM_toolsystem_active_tool_is_brush(const bContext *C)
return tref_rt && (tref_rt->flag & TOOLREF_FLAG_USE_BRUSHES);
}
bool WM_toolsystem_active_tool_has_custom_cursor(const bContext *C)
{
bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
return tref_rt && (tref_rt->cursor != WM_CURSOR_DEFAULT);
}
void WM_toolsystem_do_msg_notify_tag_refresh(bContext *C,
wmMsgSubscribeKey * /*msg_key*/,
wmMsgSubscribeValue *msg_val)