From ab1b451250005161ce3c0ed8052f4a3e2b0d0028 Mon Sep 17 00:00:00 2001 From: Sietse Brouwer Date: Tue, 10 Jun 2025 15:45:44 +0200 Subject: [PATCH] Fix: Grease Pencil: Wrong check on editable layer and keyframe in Sculpt Mode and Vertex Paint mode In Grease Pencil, when using the tools in Sculpt Mode and Vertex Paint mode, the check on editable layers wasn't entirely accurate. There was a strict check on an editable _active_ layer, but since the tools work on _all_ editable layers, the check should be wider: if there is _any_ editable layer, the tool can work. That is fixed in this PR. Now the tools can be used when, for example, a layer group is active or when the active layer is hidden, but there are other editable layers present. In Vertex Paint mode there was an additional issue: with Auto Keying enabled, a new keyframe was created for the active layer only. A new keyframe should be created for _every_ editable layer. As is the case now with this PR. Pull Request: https://projects.blender.org/blender/blender/pulls/140119 --- .../intern/grease_pencil_utils.cc | 11 ++++++ .../editors/include/ED_grease_pencil.hh | 1 + .../sculpt_paint/grease_pencil_draw_ops.cc | 36 ++++++++----------- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc index 402ef743501..cdc451118ae 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc @@ -1303,6 +1303,17 @@ IndexMask retrieve_editable_and_selected_elements(Object &object, return {}; } +bool has_editable_layer(const GreasePencil &grease_pencil) +{ + using namespace blender::bke::greasepencil; + for (const Layer *layer : grease_pencil.layers()) { + if (layer->is_editable()) { + return true; + } + } + return false; +} + Array compute_topology_change( const bke::CurvesGeometry &src, bke::CurvesGeometry &dst, diff --git a/source/blender/editors/include/ED_grease_pencil.hh b/source/blender/editors/include/ED_grease_pencil.hh index 83a6ac514a9..85925c44edf 100644 --- a/source/blender/editors/include/ED_grease_pencil.hh +++ b/source/blender/editors/include/ED_grease_pencil.hh @@ -432,6 +432,7 @@ IndexMask retrieve_editable_and_selected_elements(Object &object, int layer_index, bke::AttrDomain selection_domain, IndexMaskMemory &memory); +bool has_editable_layer(const GreasePencil &grease_pencil); void create_blank(Main &bmain, Object &object, int frame_number); void create_stroke(Main &bmain, Object &object, const float4x4 &matrix, int frame_number); diff --git a/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc b/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc index 7d80bfe5e42..465b7422cbd 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc @@ -350,8 +350,8 @@ static wmOperatorStatus grease_pencil_sculpt_paint_invoke(bContext *C, } GreasePencil &grease_pencil = *static_cast(object->data); - if (!grease_pencil.has_active_layer()) { - BKE_report(op->reports, RPT_ERROR, "No active Grease Pencil layer"); + if (!ed::greasepencil::has_editable_layer(grease_pencil)) { + BKE_report(op->reports, RPT_ERROR, "No editable Grease Pencil layer"); return OPERATOR_CANCELLED; } @@ -361,12 +361,6 @@ static wmOperatorStatus grease_pencil_sculpt_paint_invoke(bContext *C, return OPERATOR_CANCELLED; } - bke::greasepencil::Layer &active_layer = *grease_pencil.get_active_layer(); - if (!active_layer.is_editable()) { - BKE_report(op->reports, RPT_ERROR, "Active layer is locked or hidden"); - return OPERATOR_CANCELLED; - } - /* Ensure a drawing at the current keyframe. */ bool inserted_keyframe = false; /* For the sculpt tools, we don't want the auto-key to create an empty keyframe, so we duplicate @@ -557,14 +551,8 @@ static wmOperatorStatus grease_pencil_vertex_brush_stroke_invoke(bContext *C, } GreasePencil &grease_pencil = *static_cast(object->data); - if (!grease_pencil.has_active_layer()) { - BKE_report(op->reports, RPT_ERROR, "No active Grease Pencil layer"); - return OPERATOR_CANCELLED; - } - - bke::greasepencil::Layer &active_layer = *grease_pencil.get_active_layer(); - if (!active_layer.is_editable()) { - BKE_report(op->reports, RPT_ERROR, "Active layer is locked or hidden"); + if (!ed::greasepencil::has_editable_layer(grease_pencil)) { + BKE_report(op->reports, RPT_ERROR, "No editable Grease Pencil layer"); return OPERATOR_CANCELLED; } @@ -579,15 +567,19 @@ static wmOperatorStatus grease_pencil_vertex_brush_stroke_invoke(bContext *C, /* For the vertex paint tools, we don't want the auto-key to create an empty keyframe, so we * duplicate the previous key. */ const bool use_duplicate_previous_key = true; - if (!ed::greasepencil::ensure_active_keyframe( - *scene, grease_pencil, active_layer, use_duplicate_previous_key, inserted_keyframe)) - { + for (bke::greasepencil::Layer *layer : grease_pencil.layers_for_write()) { + if (layer->is_editable() && + ed::greasepencil::ensure_active_keyframe( + *scene, grease_pencil, *layer, use_duplicate_previous_key, inserted_keyframe)) + { + inserted_keyframe = true; + } + } + if (!inserted_keyframe) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil frame to draw on"); return OPERATOR_CANCELLED; } - if (inserted_keyframe) { - WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, nullptr); - } + WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, nullptr); op->customdata = paint_stroke_new(C, op,