From 6a662ffda8360f06888452cf43c44b5507f09164 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Thu, 4 Mar 2021 21:30:17 +0100 Subject: GPencil: Implement Autokey button for Draw/Edit and Sculpt mode Now, if the Autokey is not enabled, a new frame is not created and it is used the last active one. If no active frame, a message is displayed and the operation is canceled. This is a common request for 2D artists. Also, grease pencil was not working as Blender does in other areas. Reviewed By: pepeland Differential Revision: https://developer.blender.org/D10557 --- source/blender/editors/gpencil/gpencil_fill.c | 43 +++++++++++++++++----- source/blender/editors/gpencil/gpencil_paint.c | 27 +++++++++++--- source/blender/editors/gpencil/gpencil_primitive.c | 21 +++++++++-- .../blender/editors/gpencil/gpencil_sculpt_paint.c | 13 ++++++- 4 files changed, 83 insertions(+), 21 deletions(-) (limited to 'source/blender/editors/gpencil') diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 406daf9f92e..85130e89ad1 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -55,6 +55,7 @@ #include "BKE_screen.h" #include "ED_gpencil.h" +#include "ED_keyframing.h" #include "ED_screen.h" #include "ED_space_api.h" #include "ED_view3d.h" @@ -542,12 +543,18 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) if (gpl == tgpf->gpl) { if ((gpl->actframe == NULL) || (gpl->actframe->framenum != tgpf->active_cfra)) { short add_frame_mode; - if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { - add_frame_mode = GP_GETFRAME_ADD_COPY; + if (IS_AUTOKEY_ON(tgpf->scene)) { + if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { + add_frame_mode = GP_GETFRAME_ADD_COPY; + } + else { + add_frame_mode = GP_GETFRAME_ADD_NEW; + } } else { - add_frame_mode = GP_GETFRAME_ADD_NEW; + add_frame_mode = GP_GETFRAME_USE_PREV; } + BKE_gpencil_layer_frame_get(gpl, tgpf->active_cfra, add_frame_mode); } } @@ -1456,7 +1463,10 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) tgpf->done = true; /* Get frame or create a new one. */ - tgpf->gpf = BKE_gpencil_layer_frame_get(tgpf->gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW); + tgpf->gpf = BKE_gpencil_layer_frame_get(tgpf->gpl, + tgpf->active_cfra, + IS_AUTOKEY_ON(tgpf->scene) ? GP_GETFRAME_ADD_NEW : + GP_GETFRAME_USE_PREV); /* Set frame as selected. */ tgpf->gpf->flag |= GP_FRAME_SELECT; @@ -2064,6 +2074,12 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) estate = OPERATOR_CANCELLED; break; case LEFTMOUSE: + if (!IS_AUTOKEY_ON(tgpf->scene) && (!is_multiedit) && (tgpf->gpl->actframe == NULL)) { + BKE_report(op->reports, RPT_INFO, "No available frame for creating stroke"); + estate = OPERATOR_CANCELLED; + break; + } + /* first time the event is not enabled to show help lines. */ if ((tgpf->oldkey != -1) || (!help_lines)) { ARegion *region = BKE_area_find_region_xy( @@ -2088,17 +2104,24 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) gpencil_stroke_convertcoords_tpoint( tgpf->scene, tgpf->region, tgpf->ob, &point2D, NULL, &pt->x); + /* Hash of selected frames.*/ + GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64); + /* If not multiframe and there is no frame in CFRA for the active layer, create - * a new frame before to make the hash function can find something. */ + * a new frame. */ if (!is_multiedit) { tgpf->gpf = BKE_gpencil_layer_frame_get( - tgpf->gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW); + tgpf->gpl, + tgpf->active_cfra, + IS_AUTOKEY_ON(tgpf->scene) ? GP_GETFRAME_ADD_NEW : GP_GETFRAME_USE_PREV); tgpf->gpf->flag |= GP_FRAME_SELECT; - } - /* Hash of selected frames.*/ - GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64); - BKE_gpencil_frame_selected_hash(tgpf->gpd, frame_list); + BLI_ghash_insert( + frame_list, POINTER_FROM_INT(tgpf->active_cfra), tgpf->gpl->actframe); + } + else { + BKE_gpencil_frame_selected_hash(tgpf->gpd, frame_list); + } /* Loop all frames. */ wmWindow *win = CTX_wm_window(C); diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 915cac6be77..1217a3a7e8f 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -67,6 +67,7 @@ #include "ED_clip.h" #include "ED_gpencil.h" +#include "ED_keyframing.h" #include "ED_object.h" #include "ED_screen.h" #include "ED_view3d.h" @@ -2155,6 +2156,10 @@ static void gpencil_paint_initstroke(tGPsdata *p, continue; } + if (!IS_AUTOKEY_ON(scene) && (gpl->actframe == NULL)) { + continue; + } + /* Add a new frame if needed (and based off the active frame, * as we need some existing strokes to erase) * @@ -2164,7 +2169,8 @@ static void gpencil_paint_initstroke(tGPsdata *p, */ if (gpl->actframe && gpl->actframe->strokes.first) { if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { - gpl->actframe = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_COPY); + short frame_mode = IS_AUTOKEY_ON(scene) ? GP_GETFRAME_ADD_COPY : GP_GETFRAME_USE_PREV; + gpl->actframe = BKE_gpencil_layer_frame_get(gpl, CFRA, frame_mode); } has_layer_to_erase = true; break; @@ -2187,11 +2193,16 @@ static void gpencil_paint_initstroke(tGPsdata *p, /* Drawing Modes - Add a new frame if needed on the active layer */ short add_frame_mode; - if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { - add_frame_mode = GP_GETFRAME_ADD_COPY; + if (IS_AUTOKEY_ON(scene)) { + if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { + add_frame_mode = GP_GETFRAME_ADD_COPY; + } + else { + add_frame_mode = GP_GETFRAME_ADD_NEW; + } } else { - add_frame_mode = GP_GETFRAME_ADD_NEW; + add_frame_mode = GP_GETFRAME_USE_PREV; } bool need_tag = p->gpl->actframe == NULL; @@ -2206,6 +2217,10 @@ static void gpencil_paint_initstroke(tGPsdata *p, if (G.debug & G_DEBUG) { printf("Error: No frame created (gpencil_paint_init)\n"); } + if (!IS_AUTOKEY_ON(scene)) { + BKE_report(p->reports, RPT_INFO, "No available frame for creating stroke"); + } + return; } p->gpf->flag |= GP_FRAME_PAINT; @@ -2469,6 +2484,8 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event) return 0; } + p->reports = op->reports; + /* init painting data */ gpencil_paint_initstroke(p, paintmode, CTX_data_ensure_evaluated_depsgraph(C)); if (p->status == GP_STATUS_ERROR) { @@ -2483,8 +2500,6 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event) p->keymodifier = -1; } - p->reports = op->reports; - /* everything is now setup ok */ return 1; } diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 12d399f32ca..b29ef2e7ee2 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -71,6 +71,7 @@ #include "RNA_enum_types.h" #include "ED_gpencil.h" +#include "ED_keyframing.h" #include "ED_object.h" #include "ED_screen.h" #include "ED_space_api.h" @@ -1253,9 +1254,18 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op) static int gpencil_primitive_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); + Scene *scene = CTX_data_scene(C); bGPdata *gpd = CTX_data_gpencil_data(C); tGPDprimitive *tgpi = NULL; + if (!IS_AUTOKEY_ON(scene)) { + bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); + if ((gpl == NULL) || (gpl->actframe == NULL)) { + BKE_report(op->reports, RPT_INFO, "No available frame for creating stroke"); + return OPERATOR_CANCELLED; + } + } + /* initialize operator runtime data */ gpencil_primitive_init(C, op); tgpi = op->customdata; @@ -1310,11 +1320,16 @@ static void gpencil_primitive_interaction_end(bContext *C, /* insert keyframes as required... */ short add_frame_mode; - if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { - add_frame_mode = GP_GETFRAME_ADD_COPY; + if (IS_AUTOKEY_ON(tgpi->scene)) { + if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) { + add_frame_mode = GP_GETFRAME_ADD_COPY; + } + else { + add_frame_mode = GP_GETFRAME_ADD_NEW; + } } else { - add_frame_mode = GP_GETFRAME_ADD_NEW; + add_frame_mode = GP_GETFRAME_USE_PREV; } bool need_tag = tgpi->gpl->actframe == NULL; diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index 0d3ab9011d6..9666aca5254 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -73,6 +73,7 @@ #include "UI_view2d.h" #include "ED_gpencil.h" +#include "ED_keyframing.h" #include "ED_screen.h" #include "ED_view3d.h" @@ -1019,7 +1020,11 @@ static void gpencil_brush_clone_add(bContext *C, tGP_BrushEditData *gso) if (gpl == NULL) { gpl = CTX_data_active_gpencil_layer(C); } - bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW); + bGPDframe *gpf = BKE_gpencil_layer_frame_get( + gpl, CFRA, IS_AUTOKEY_ON(scene) ? GP_GETFRAME_ADD_NEW : GP_GETFRAME_USE_PREV); + if (gpf == NULL) { + continue; + } /* Make a new stroke */ new_stroke = BKE_gpencil_stroke_duplicate(gps, true, true); @@ -1334,6 +1339,10 @@ static void gpencil_sculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso /* go through each layer, and ensure that we've got a valid frame to use */ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + if (!IS_AUTOKEY_ON(scene) && (gpl->actframe == NULL)) { + continue; + } + /* only editable and visible layers are considered */ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { bGPDframe *gpf = gpl->actframe; @@ -1343,7 +1352,7 @@ static void gpencil_sculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso * - This is useful when animating as it saves that "uh-oh" moment when you realize you've * spent too much time editing the wrong frame. */ - if (gpf->framenum != cfra) { + if ((IS_AUTOKEY_ON(scene)) && (gpf->framenum != cfra)) { BKE_gpencil_frame_addcopy(gpl, cfra); /* Need tag to recalculate evaluated data to avoid crashes. */ DEG_id_tag_update(&gso->gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); -- cgit v1.2.3