From da78dd47e37d01565d9604dd5e55d86fd0ed85bc Mon Sep 17 00:00:00 2001 From: Falk David Date: Thu, 21 Dec 2023 11:30:16 +0100 Subject: [PATCH] Fix #116343: Drawing on frame with auto-keying off gives error When drawing on a frame that didn't have a keyframe, but did have a drawing, Blender would report that there was no drawing to draw on. The issue was some faulty logic on the invoke of the drawing code. Now, this properly checks if a new frame needs to be inserted and only reports an error in case auto-key is off and there is no drawing. Pull Request: https://projects.blender.org/blender/blender/pulls/116417 --- .../blender/blenkernel/BKE_grease_pencil.hh | 5 ++++ .../blenkernel/intern/grease_pencil.cc | 5 ++++ .../sculpt_paint/grease_pencil_draw_ops.cc | 23 +++++++++++-------- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/BKE_grease_pencil.hh b/source/blender/blenkernel/BKE_grease_pencil.hh index dfc0e363196..6cfce30a4b0 100644 --- a/source/blender/blenkernel/BKE_grease_pencil.hh +++ b/source/blender/blenkernel/BKE_grease_pencil.hh @@ -394,6 +394,11 @@ class Layer : public ::GreasePencilLayer { * drawing. */ int drawing_index_at(const int frame_number) const; + /** + * \returns true if there is a drawing on this layer at \a frame_number. + */ + bool has_drawing_at(const int frame_number) const; + /** * \returns the key of the active frame at \a frame_number or -1 if there is no frame. */ diff --git a/source/blender/blenkernel/intern/grease_pencil.cc b/source/blender/blenkernel/intern/grease_pencil.cc index 4a1d41a7fbf..bb0610ad5f8 100644 --- a/source/blender/blenkernel/intern/grease_pencil.cc +++ b/source/blender/blenkernel/intern/grease_pencil.cc @@ -808,6 +808,11 @@ int Layer::drawing_index_at(const int frame_number) const return (frame != nullptr) ? frame->drawing_index : -1; } +bool Layer::has_drawing_at(const int frame_number) const +{ + return frame_at(frame_number) != nullptr; +} + int Layer::get_frame_duration_at(const int frame_number) const { const FramesMapKey frame_key = this->frame_key_at(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 c250c9be0a6..78069ec8872 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc @@ -141,16 +141,19 @@ static int grease_pencil_stroke_invoke(bContext *C, wmOperator *op, const wmEven } const int current_frame = scene->r.cfra; - // bke::greasepencil::Layer &active_layer = *grease_pencil.get_active_layer(); - // grease_pencil.get_editable_drawing_at() + bke::greasepencil::Layer &active_layer = *grease_pencil.get_active_layer(); + /* If there is no drawing at the current frame and auto-key is off, then */ + if (!active_layer.has_drawing_at(current_frame) && !blender::animrig::is_autokey_on(scene)) { + BKE_report(op->reports, RPT_ERROR, "No Grease Pencil frame to draw on"); + return OPERATOR_CANCELLED; + } - if (!grease_pencil.get_active_layer()->frames().contains(current_frame)) { - if (!blender::animrig::is_autokey_on(scene)) { - BKE_report(op->reports, RPT_ERROR, "No Grease Pencil frame to draw on"); - return OPERATOR_CANCELLED; - } + /* If auto-key is on and the drawing at the current frame starts before the current frame a new + * keyframe needs to be inserted. */ + if (blender::animrig::is_autokey_on(scene) && + active_layer.frame_key_at(current_frame) < current_frame) + { const ToolSettings *ts = CTX_data_tool_settings(C); - bke::greasepencil::Layer &active_layer = *grease_pencil.get_active_layer(); if ((ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) != 0) { /* For additive drawing, we duplicate the frame that's currently visible and insert it at the * current frame. */ @@ -158,10 +161,12 @@ static int grease_pencil_stroke_invoke(bContext *C, wmOperator *op, const wmEven active_layer, active_layer.frame_key_at(current_frame), current_frame, false); } else { - /* Otherwise we just insert a blank keyframe. */ + /* Otherwise we just insert a blank keyframe at the current frame. */ grease_pencil.insert_blank_frame(active_layer, current_frame, 0, BEZT_KEYTYPE_KEYFRAME); } } + /* There should now always be a drawing at the current frame. */ + BLI_assert(active_layer.has_drawing_at(current_frame)); op->customdata = paint_stroke_new(C, op,