Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/gpencil')
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt2
-rw-r--r--source/blender/editors/gpencil/annotate_draw.c8
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c27
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c47
-rw-r--r--source/blender/editors/gpencil/gpencil_add_blank.c8
-rw-r--r--source/blender/editors/gpencil/gpencil_add_lineart.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_add_monkey.c22
-rw-r--r--source/blender/editors/gpencil/gpencil_add_stroke.c22
-rw-r--r--source/blender/editors/gpencil/gpencil_bake_animation.cc8
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c10
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c13
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c437
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h1
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c21
-rw-r--r--source/blender/editors/gpencil/gpencil_merge.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_mesh.cc4
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c103
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c12
-rw-r--r--source/blender/editors/gpencil/gpencil_sculpt_paint.c16
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_trace_ops.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c30
24 files changed, 617 insertions, 193 deletions
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index 09a3cac0d48..866df16f3d6 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -12,8 +12,8 @@ set(INC
../../makesdna
../../makesrna
../../windowmanager
- ../../../../intern/glew-mx
../../../../intern/guardedalloc
+ ../../bmesh
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
)
diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c
index f720f261ad5..ae09aea28d3 100644
--- a/source/blender/editors/gpencil/annotate_draw.c
+++ b/source/blender/editors/gpencil/annotate_draw.c
@@ -841,7 +841,8 @@ void ED_annotation_draw_2dimage(const bContext *C)
}
/* draw it! */
- annotation_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, area->spacetype);
+ annotation_draw_data_all(
+ scene, gpd, offsx, offsy, sizex, sizey, scene->r.cfra, dflag, area->spacetype);
}
void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
@@ -877,7 +878,7 @@ void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d)
}
annotation_draw_data_all(
- scene, gpd, 0, 0, region->winx, region->winy, CFRA, dflag, area->spacetype);
+ scene, gpd, 0, 0, region->winx, region->winy, scene->r.cfra, dflag, area->spacetype);
}
void ED_annotation_draw_view3d(
@@ -928,7 +929,8 @@ void ED_annotation_draw_view3d(
}
/* draw it! */
- annotation_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
+ annotation_draw_data_all(
+ scene, gpd, offsx, offsy, winx, winy, scene->r.cfra, dflag, v3d->spacetype);
}
void ED_annotation_draw_ex(
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index 8c393cc4f3f..287dce1a509 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -1568,7 +1568,7 @@ static void annotation_paint_initstroke(tGPsdata *p,
add_frame_mode = GP_GETFRAME_ADD_NEW;
}
- p->gpf = BKE_gpencil_layer_frame_get(p->gpl, CFRA, add_frame_mode);
+ p->gpf = BKE_gpencil_layer_frame_get(p->gpl, scene->r.cfra, add_frame_mode);
if (p->gpf == NULL) {
p->status = GP_STATUS_ERROR;
@@ -1715,7 +1715,7 @@ static void annotation_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_pt
if (p->paintmode == GP_PAINTMODE_ERASER) {
GPUVertFormat *format = immVertexFormat();
const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
GPU_line_smooth(true);
GPU_blend(GPU_BLEND_ALPHA);
@@ -1725,7 +1725,7 @@ static void annotation_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_pt
immUnbindProgram();
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
@@ -1782,7 +1782,7 @@ static void annotation_draw_stabilizer(bContext *C, int x, int y, void *p_ptr)
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
GPU_line_smooth(true);
GPU_blend(GPU_BLEND_ALPHA);
GPU_line_width(1.25f);
@@ -2062,11 +2062,18 @@ static void annotation_draw_apply_event(
PointerRNA itemptr;
float mousef[2];
- /* convert from window-space to area-space mouse coordinates
- * add any x,y override position for fake events
- */
- p->mval[0] = (float)event->mval[0] - x;
- p->mval[1] = (float)event->mval[1] - y;
+ /* Convert from window-space to area-space mouse coordinates
+ * add any x,y override position for fake events. */
+ if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
+ /* The first run may be a drag event, see: T99368. */
+ WM_event_drag_start_mval_fl(event, p->region, p->mval);
+ p->mval[0] -= x;
+ p->mval[1] -= y;
+ }
+ else {
+ p->mval[0] = (float)event->mval[0] - x;
+ p->mval[1] = (float)event->mval[1] - y;
+ }
/* Key to toggle stabilization. */
if ((event->modifier & KM_SHIFT) && (p->paintmode == GP_PAINTMODE_DRAW)) {
@@ -2634,7 +2641,7 @@ static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *eve
/* handle mode-specific events */
if (p->status == GP_STATUS_PAINTING) {
/* handle painting mouse-movements? */
- if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) {
+ if (ISMOUSE_MOTION(event->type) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) {
/* handle drawing event */
if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) {
annotation_add_missing_events(C, op, event, p);
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index 949043e4be1..8a98dcb57fc 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -214,6 +214,18 @@ void ED_gpencil_layer_frames_select_region(KeyframeEditData *ked,
}
}
+void ED_gpencil_set_active_channel(bGPdata *gpd, bGPDlayer *gpl)
+{
+ gpl->flag |= GP_LAYER_SELECT;
+
+ /* Update other layer status. */
+ if (BKE_gpencil_layer_active_get(gpd) != gpl) {
+ BKE_gpencil_layer_active_set(gpd, gpl);
+ BKE_gpencil_layer_autolock_set(gpd, false);
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+}
+
/* ***************************************** */
/* Frame Editing Tools */
@@ -316,8 +328,13 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac)
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* assume that each of these is a GP layer */
for (ale = anim_data.first; ale; ale = ale->next) {
+ /* This function only deals with grease pencil layer frames.
+ * This check is needed in the case of a call from the main dopesheet. */
+ if (ale->type != ANIMTYPE_GPLAYER) {
+ continue;
+ }
+
ListBase copied_frames = {NULL, NULL};
bGPDlayer *gpl = (bGPDlayer *)ale->data;
@@ -354,19 +371,13 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac)
}
/* in case 'relative' paste method is used */
- gpencil_anim_copy_cfra = CFRA;
+ gpencil_anim_copy_cfra = scene->r.cfra;
/* clean up */
ANIM_animdata_freelist(&anim_data);
- /* check if anything ended up in the buffer */
- if (ELEM(NULL, gpencil_anim_copybuf.first, gpencil_anim_copybuf.last)) {
- BKE_report(ac->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
- return false;
- }
-
/* report success */
- return true;
+ return !BLI_listbase_is_empty(&gpencil_anim_copybuf);
}
bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
@@ -381,7 +392,6 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
/* check if buffer is empty */
if (BLI_listbase_is_empty(&gpencil_anim_copybuf)) {
- BKE_report(ac->reports, RPT_ERROR, "No data in buffer to paste");
return false;
}
@@ -393,13 +403,13 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
/* methods of offset (eKeyPasteOffset) */
switch (offset_mode) {
case KEYFRAME_PASTE_OFFSET_CFRA_START:
- offset = (CFRA - gpencil_anim_copy_firstframe);
+ offset = (scene->r.cfra - gpencil_anim_copy_firstframe);
break;
case KEYFRAME_PASTE_OFFSET_CFRA_END:
- offset = (CFRA - gpencil_anim_copy_lastframe);
+ offset = (scene->r.cfra - gpencil_anim_copy_lastframe);
break;
case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE:
- offset = (CFRA - gpencil_anim_copy_cfra);
+ offset = (scene->r.cfra - gpencil_anim_copy_cfra);
break;
case KEYFRAME_PASTE_OFFSET_NONE:
offset = 0;
@@ -414,6 +424,11 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
/* from selected channels */
for (ale = anim_data.first; ale; ale = ale->next) {
+ /* only deal with GPlayers (case of calls from general dopesheet) */
+ if (ale->type != ANIMTYPE_GPLAYER) {
+ continue;
+ }
+
bGPDlayer *gpld = (bGPDlayer *)ale->data;
bGPDlayer *gpls = NULL;
bGPDframe *gpfs, *gpf;
@@ -503,7 +518,7 @@ static bool gpencil_frame_snap_nearestsec(bGPDframe *gpf, Scene *scene)
static bool gpencil_frame_snap_cframe(bGPDframe *gpf, Scene *scene)
{
if (gpf->flag & GP_FRAME_SELECT) {
- gpf->framenum = (int)CFRA;
+ gpf->framenum = (int)scene->r.cfra;
}
return false;
}
@@ -545,8 +560,8 @@ static bool gpencil_frame_mirror_cframe(bGPDframe *gpf, Scene *scene)
int diff;
if (gpf->flag & GP_FRAME_SELECT) {
- diff = CFRA - gpf->framenum;
- gpf->framenum = CFRA + diff;
+ diff = scene->r.cfra - gpf->framenum;
+ gpf->framenum = scene->r.cfra + diff;
}
return false;
diff --git a/source/blender/editors/gpencil/gpencil_add_blank.c b/source/blender/editors/gpencil/gpencil_add_blank.c
index 2f22fad53e7..b88b33913ac 100644
--- a/source/blender/editors/gpencil/gpencil_add_blank.c
+++ b/source/blender/editors/gpencil/gpencil_add_blank.c
@@ -19,6 +19,8 @@
#include "BKE_main.h"
#include "BKE_material.h"
+#include "BLT_translation.h"
+
#include "DEG_depsgraph.h"
#include "ED_gpencil.h"
@@ -34,7 +36,7 @@ typedef struct ColorTemplate {
static int gpencil_stroke_material(Main *bmain, Object *ob, const ColorTemplate *pct)
{
int index;
- Material *ma = BKE_gpencil_object_material_ensure_by_name(bmain, ob, pct->name, &index);
+ Material *ma = BKE_gpencil_object_material_ensure_by_name(bmain, ob, DATA_(pct->name), &index);
copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
@@ -52,7 +54,7 @@ static int gpencil_stroke_material(Main *bmain, Object *ob, const ColorTemplate
/* Color Data */
static const ColorTemplate gp_stroke_material_black = {
- "Black",
+ N_("Black"),
{0.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
@@ -76,7 +78,7 @@ void ED_gpencil_create_blank(bContext *C, Object *ob, float UNUSED(mat[4][4]))
bGPDlayer *layer = BKE_gpencil_layer_addnew(gpd, "GP_Layer", true, false);
/* frames */
- BKE_gpencil_frame_addnew(layer, CFRA);
+ BKE_gpencil_frame_addnew(layer, scene->r.cfra);
/* update depsgraph */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
diff --git a/source/blender/editors/gpencil/gpencil_add_lineart.c b/source/blender/editors/gpencil/gpencil_add_lineart.c
index 964a57a8ced..2ac26c927f4 100644
--- a/source/blender/editors/gpencil/gpencil_add_lineart.c
+++ b/source/blender/editors/gpencil/gpencil_add_lineart.c
@@ -21,6 +21,8 @@
#include "BKE_main.h"
#include "BKE_material.h"
+#include "BLT_translation.h"
+
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -40,7 +42,7 @@ static int gpencil_lineart_material(Main *bmain,
const bool fill)
{
int index;
- Material *ma = BKE_gpencil_object_material_ensure_by_name(bmain, ob, pct->name, &index);
+ Material *ma = BKE_gpencil_object_material_ensure_by_name(bmain, ob, DATA_(pct->name), &index);
copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
@@ -59,7 +61,7 @@ static int gpencil_lineart_material(Main *bmain,
/* Color Data */
static const ColorTemplate gp_stroke_material_black = {
- "Black",
+ N_("Black"),
{0.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c
index 65ee732f6a9..00066d5f2b8 100644
--- a/source/blender/editors/gpencil/gpencil_add_monkey.c
+++ b/source/blender/editors/gpencil/gpencil_add_monkey.c
@@ -19,6 +19,8 @@
#include "BKE_main.h"
#include "BKE_material.h"
+#include "BLT_translation.h"
+
#include "DEG_depsgraph.h"
#include "ED_gpencil.h"
@@ -54,7 +56,7 @@ static int gpencil_monkey_color(
Main *bmain, Object *ob, const ColorTemplate *pct, bool stroke, bool fill)
{
int index;
- Material *ma = BKE_gpencil_object_material_ensure_by_name(bmain, ob, pct->name, &index);
+ Material *ma = BKE_gpencil_object_material_ensure_by_name(bmain, ob, DATA_(pct->name), &index);
copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
@@ -781,37 +783,37 @@ static const float data27[33 * GP_PRIM_DATABUF_SIZE] = {
/* Monkey Color Data */
static const ColorTemplate gp_monkey_pct_black = {
- "Black",
+ N_("Black"),
{0.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_monkey_pct_skin = {
- "Skin",
+ N_("Skin"),
{0.733f, 0.569f, 0.361f, 1.0f},
{0.745f, 0.502f, 0.278f, 1.0f},
};
static const ColorTemplate gp_monkey_pct_skin_light = {
- "Skin_Light",
+ N_("Skin_Light"),
{0.914f, 0.827f, 0.635f, 1.0f},
{0.913f, 0.828f, 0.637f, 0.0f},
};
static const ColorTemplate gp_monkey_pct_skin_shadow = {
- "Skin_Shadow",
+ N_("Skin_Shadow"),
{0.322f, 0.29f, 0.224f, 0.5f},
{0.32f, 0.29f, 0.223f, 0.3f},
};
static const ColorTemplate gp_monkey_pct_eyes = {
- "Eyes",
+ N_("Eyes"),
{0.553f, 0.39f, 0.266f, 0.0f},
{0.847f, 0.723f, 0.599f, 1.0f},
};
static const ColorTemplate gp_monkey_pct_pupils = {
- "Pupils",
+ N_("Pupils"),
{0.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 0.0f, 1.0f},
};
@@ -821,6 +823,8 @@ static const ColorTemplate gp_monkey_pct_pupils = {
void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4])
{
+ /* Original model created by Matias Mendiola. */
+
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bGPdata *gpd = (bGPdata *)ob->data;
@@ -844,8 +848,8 @@ void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4])
/* frames */
/* NOTE: No need to check for existing, as this will take care of it for us */
- bGPDframe *frameFills = BKE_gpencil_frame_addnew(Fills, CFRA);
- bGPDframe *frameLines = BKE_gpencil_frame_addnew(Lines, CFRA);
+ bGPDframe *frameFills = BKE_gpencil_frame_addnew(Fills, scene->r.cfra);
+ bGPDframe *frameLines = BKE_gpencil_frame_addnew(Lines, scene->r.cfra);
/* generate strokes */
gps = BKE_gpencil_stroke_add(frameFills, color_Skin, 270, 75, false);
diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c
index bc5fe9b5cfb..8522c81cb39 100644
--- a/source/blender/editors/gpencil/gpencil_add_stroke.c
+++ b/source/blender/editors/gpencil/gpencil_add_stroke.c
@@ -19,6 +19,8 @@
#include "BKE_main.h"
#include "BKE_material.h"
+#include "BLT_translation.h"
+
#include "DEG_depsgraph.h"
#include "ED_gpencil.h"
@@ -37,7 +39,7 @@ static int gpencil_stroke_material(Main *bmain,
const bool fill)
{
int index;
- Material *ma = BKE_gpencil_object_material_ensure_by_name(bmain, ob, pct->name, &index);
+ Material *ma = BKE_gpencil_object_material_ensure_by_name(bmain, ob, DATA_(pct->name), &index);
copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
@@ -150,37 +152,37 @@ static const float data0[175 * GP_PRIM_DATABUF_SIZE] = {
/* Color Data */
static const ColorTemplate gp_stroke_material_black = {
- "Black",
+ N_("Black"),
{0.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_white = {
- "White",
+ N_("White"),
{1.0f, 1.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_red = {
- "Red",
+ N_("Red"),
{1.0f, 0.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_green = {
- "Green",
+ N_("Green"),
{0.0f, 1.0f, 0.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_blue = {
- "Blue",
+ N_("Blue"),
{0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 0.0f, 0.0f},
};
static const ColorTemplate gp_stroke_material_grey = {
- "Grey",
+ N_("Grey"),
{0.358f, 0.358f, 0.358f, 1.0f},
{0.5f, 0.5f, 0.5f, 1.0f},
};
@@ -190,6 +192,8 @@ static const ColorTemplate gp_stroke_material_grey = {
void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4])
{
+ /* Original design created by Daniel M. Lara and Matias Mendiola. */
+
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bGPdata *gpd = (bGPdata *)ob->data;
@@ -211,8 +215,8 @@ void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4])
bGPDlayer *lines = BKE_gpencil_layer_addnew(gpd, "Lines", true, false);
/* frames */
- bGPDframe *frame_color = BKE_gpencil_frame_addnew(colors, CFRA);
- bGPDframe *frame_lines = BKE_gpencil_frame_addnew(lines, CFRA);
+ bGPDframe *frame_color = BKE_gpencil_frame_addnew(colors, scene->r.cfra);
+ bGPDframe *frame_lines = BKE_gpencil_frame_addnew(lines, scene->r.cfra);
UNUSED_VARS(frame_color);
/* generate stroke */
diff --git a/source/blender/editors/gpencil/gpencil_bake_animation.cc b/source/blender/editors/gpencil/gpencil_bake_animation.cc
index 66f53bea326..e480852a9bb 100644
--- a/source/blender/editors/gpencil/gpencil_bake_animation.cc
+++ b/source/blender/editors/gpencil/gpencil_bake_animation.cc
@@ -265,7 +265,7 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op
}
/* Move scene to new frame. */
- CFRA = i;
+ scene->r.cfra = i;
BKE_scene_graph_update_for_newframe(depsgraph);
/* Loop all objects in the list. */
@@ -285,7 +285,7 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op
/* Apply time modifier. */
int remap_cfra = BKE_gpencil_time_modifier_cfra(
- depsgraph, scene, elem->ob, gpl_src, CFRA, false);
+ depsgraph, scene, elem->ob, gpl_src, scene->r.cfra, false);
/* Duplicate frame. */
bGPDframe *gpf_src = BKE_gpencil_layer_frame_get(
gpl_src, remap_cfra, GP_GETFRAME_USE_PREV);
@@ -293,7 +293,7 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op
continue;
}
bGPDframe *gpf_dst = BKE_gpencil_frame_duplicate(gpf_src, true);
- gpf_dst->framenum = CFRA + frame_offset;
+ gpf_dst->framenum = scene->r.cfra + frame_offset;
gpf_dst->flag &= ~GP_FRAME_SELECT;
BLI_addtail(&gpl_dst->frames, gpf_dst);
@@ -337,7 +337,7 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op
}
}
/* Return scene frame state and DB to original state. */
- CFRA = oldframe;
+ scene->r.cfra = oldframe;
BKE_scene_graph_update_for_newframe(depsgraph);
/* Free memory. */
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index 0601d009bf7..e02a82f4555 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -588,7 +588,7 @@ static void gpencil_stroke_path_animation(bContext *C,
}
/* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */
- calchandles_fcurve(fcu);
+ BKE_fcurve_handles_recalc(fcu);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
@@ -1271,7 +1271,7 @@ static void gpencil_layer_to_curve(bContext *C,
Collection *collection = CTX_data_collection(C);
Scene *scene = CTX_data_scene(C);
- bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, GP_GETFRAME_USE_PREV);
bGPDstroke *prev_gps = NULL;
Object *ob;
Curve *cu;
@@ -1414,7 +1414,7 @@ static bool gpencil_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl,
int i;
bool valid = true;
- if (!gpl || !(gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV)) ||
+ if (!gpl || !(gpf = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, GP_GETFRAME_USE_PREV)) ||
!(gps = gpf->strokes.first)) {
return false;
}
@@ -1481,7 +1481,7 @@ static bool gpencil_convert_poll(bContext *C)
* and if we are not in edit mode!
*/
return ((area && area->spacetype == SPACE_VIEW3D) && (gpl = BKE_gpencil_layer_active_get(gpd)) &&
- (gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV)) &&
+ (gpf = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, GP_GETFRAME_USE_PREV)) &&
(gpf->strokes.first) && (!GPENCIL_ANY_EDIT_MODE(gpd)));
}
@@ -1811,7 +1811,7 @@ static int image_to_gpencil_exec(bContext *C, wmOperator *op)
/* Add layer and frame. */
bGPdata *gpd = (bGPdata *)ob->data;
bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, "Image Layer", true, false);
- bGPDframe *gpf = BKE_gpencil_frame_addnew(gpl, CFRA);
+ bGPDframe *gpf = BKE_gpencil_frame_addnew(gpl, scene->r.cfra);
done = BKE_gpencil_from_image(sima, gpd, gpf, size, is_mask);
if (done) {
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 6843c42d2d0..340288b2d74 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -226,7 +226,7 @@ static int gpencil_layer_add_exec(bContext *C, wmOperator *op)
bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true, false);
/* Add a new frame to make it visible in Dopesheet. */
if (gpl != NULL) {
- gpl->actframe = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
+ gpl->actframe = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, GP_GETFRAME_ADD_NEW);
}
}
}
@@ -646,12 +646,12 @@ static int gpencil_frame_duplicate_exec(bContext *C, wmOperator *op)
}
if (mode == 0) {
- BKE_gpencil_frame_addcopy(gpl_active, CFRA);
+ BKE_gpencil_frame_addcopy(gpl_active, scene->r.cfra);
}
else {
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
- BKE_gpencil_frame_addcopy(gpl, CFRA);
+ BKE_gpencil_frame_addcopy(gpl, scene->r.cfra);
}
}
}
@@ -2076,6 +2076,9 @@ static void gpencil_brush_delete_mode_brushes(Main *bmain,
}
BKE_brush_delete(bmain, brush);
+ if (brush == brush_active) {
+ brush_active = NULL;
+ }
}
}
@@ -2109,8 +2112,8 @@ static int gpencil_brush_reset_all_exec(bContext *C, wmOperator *UNUSED(op))
char tool = '0';
if (paint) {
- Brush *brush_active = paint->brush;
- if (brush_active) {
+ if (paint->brush) {
+ Brush *brush_active = paint->brush;
switch (mode) {
case CTX_MODE_PAINT_GPENCIL: {
tool = brush_active->gpencil_tool;
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 5028baf1589..120c806c727 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -1718,7 +1718,7 @@ static int gpencil_strokes_paste_exec(bContext *C, wmOperator *op)
* we are obliged to add a new frame if one
* doesn't exist already
*/
- gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
+ gpf = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, GP_GETFRAME_ADD_NEW);
if (gpf) {
/* Create new stroke */
bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps, true, true);
@@ -1971,7 +1971,7 @@ static int gpencil_blank_frame_add_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
Scene *scene = CTX_data_scene(C);
- int cfra = CFRA;
+ int cfra = scene->r.cfra;
bGPDlayer *active_gpl = BKE_gpencil_layer_active_get(gpd);
@@ -2075,7 +2075,7 @@ static int gpencil_actframe_delete_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
- bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, GP_GETFRAME_USE_PREV);
/* if there's no existing Grease-Pencil data there, add some */
if (gpd == NULL) {
@@ -2150,7 +2150,7 @@ static int gpencil_actframe_delete_all_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
/* try to get the "active" frame - but only if it actually occurs on this frame */
- bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, GP_GETFRAME_USE_PREV);
if (gpf == NULL) {
continue;
@@ -3395,6 +3395,7 @@ static int gpencil_stroke_caps_set_exec(bContext *C, wmOperator *op)
bGPdata *gpd = ED_gpencil_data_get_active(C);
Object *ob = CTX_data_active_object(C);
const int type = RNA_enum_get(op->ptr, "type");
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
/* sanity checks */
if (ELEM(NULL, gpd)) {
@@ -3404,46 +3405,57 @@ static int gpencil_stroke_caps_set_exec(bContext *C, wmOperator *op)
bool changed = false;
/* loop all selected strokes */
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- if (gpl->actframe == NULL) {
- continue;
- }
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
- for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
- MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ if (gpf == NULL) {
+ continue;
+ }
- /* skip strokes that are not selected or invalid for current view */
- if (((gps->flag & GP_STROKE_SELECT) == 0) || (ED_gpencil_stroke_can_use(C, gps) == false)) {
- continue;
- }
- /* skip hidden or locked colors */
- if (!gp_style || (gp_style->flag & GP_MATERIAL_HIDE) ||
- (gp_style->flag & GP_MATERIAL_LOCKED)) {
- continue;
- }
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
- short prev_first = gps->caps[0];
- short prev_last = gps->caps[1];
+ /* skip strokes that are not selected or invalid for current view */
+ if (((gps->flag & GP_STROKE_SELECT) == 0) ||
+ (ED_gpencil_stroke_can_use(C, gps) == false)) {
+ continue;
+ }
+ /* skip hidden or locked colors */
+ if (!gp_style || (gp_style->flag & GP_MATERIAL_HIDE) ||
+ (gp_style->flag & GP_MATERIAL_LOCKED)) {
+ continue;
+ }
+
+ short prev_first = gps->caps[0];
+ short prev_last = gps->caps[1];
+
+ if (ELEM(type, GP_STROKE_CAPS_TOGGLE_BOTH, GP_STROKE_CAPS_TOGGLE_START)) {
+ ++gps->caps[0];
+ if (gps->caps[0] >= GP_STROKE_CAP_MAX) {
+ gps->caps[0] = GP_STROKE_CAP_ROUND;
+ }
+ }
+ if (ELEM(type, GP_STROKE_CAPS_TOGGLE_BOTH, GP_STROKE_CAPS_TOGGLE_END)) {
+ ++gps->caps[1];
+ if (gps->caps[1] >= GP_STROKE_CAP_MAX) {
+ gps->caps[1] = GP_STROKE_CAP_ROUND;
+ }
+ }
+ if (type == GP_STROKE_CAPS_TOGGLE_DEFAULT) {
+ gps->caps[0] = GP_STROKE_CAP_ROUND;
+ gps->caps[1] = GP_STROKE_CAP_ROUND;
+ }
- if (ELEM(type, GP_STROKE_CAPS_TOGGLE_BOTH, GP_STROKE_CAPS_TOGGLE_START)) {
- ++gps->caps[0];
- if (gps->caps[0] >= GP_STROKE_CAP_MAX) {
- gps->caps[0] = GP_STROKE_CAP_ROUND;
+ if (prev_first != gps->caps[0] || prev_last != gps->caps[1]) {
+ changed = true;
+ }
}
- }
- if (ELEM(type, GP_STROKE_CAPS_TOGGLE_BOTH, GP_STROKE_CAPS_TOGGLE_END)) {
- ++gps->caps[1];
- if (gps->caps[1] >= GP_STROKE_CAP_MAX) {
- gps->caps[1] = GP_STROKE_CAP_ROUND;
+ /* If not multi-edit, exit loop. */
+ if (!is_multiedit) {
+ break;
}
}
- if (type == GP_STROKE_CAPS_TOGGLE_DEFAULT) {
- gps->caps[0] = GP_STROKE_CAP_ROUND;
- gps->caps[1] = GP_STROKE_CAP_ROUND;
- }
-
- if (prev_first != gps->caps[0] || prev_last != gps->caps[1]) {
- changed = true;
- }
}
}
CTX_DATA_END;
@@ -3550,9 +3562,9 @@ static int gpencil_stroke_join_exec(bContext *C, wmOperator *op)
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *activegpl = BKE_gpencil_layer_active_get(gpd);
Object *ob = CTX_data_active_object(C);
- /* Limit the number of strokes to join. It makes no sense to allow an very high number of strokes
- * for CPU time and because to have a stroke with thousands of points is unpractical, so limit
- * this number avoid to joining a full frame scene in one single stroke. */
+ /* Limit the number of strokes to join. It makes no sense to allow an very high number of
+ * strokes for CPU time and because to have a stroke with thousands of points is unpractical,
+ * so limit this number avoid to joining a full frame scene in one single stroke. */
const int max_join_strokes = 128;
const int type = RNA_enum_get(op->ptr, "type");
@@ -3638,7 +3650,7 @@ static int gpencil_stroke_join_exec(bContext *C, wmOperator *op)
}
elem = &strokes_list[i];
/* Join new_stroke and stroke B. */
- BKE_gpencil_stroke_join(gps_new, elem->gps, leave_gaps, true, false);
+ BKE_gpencil_stroke_join(gps_new, elem->gps, leave_gaps, true, false, true);
elem->used = true;
}
@@ -3709,35 +3721,44 @@ static int gpencil_stroke_flip_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
+
bool changed = false;
- /* read all selected strokes */
+ /* Read all selected strokes. */
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- bGPDframe *gpf = gpl->actframe;
- if (gpf == NULL) {
- continue;
- }
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
- LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
- if (gps->flag & GP_STROKE_SELECT) {
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false) {
- continue;
- }
- /* check if the color is editable */
- if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ if (gpf == NULL) {
continue;
}
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
+ continue;
+ }
- if (is_curve_edit) {
- BKE_report(op->reports, RPT_ERROR, "Not implemented!");
- }
- else {
- /* Flip stroke. */
- BKE_gpencil_stroke_flip(gps);
+ if (is_curve_edit) {
+ BKE_report(op->reports, RPT_ERROR, "Not implemented!");
+ }
+ else {
+ /* Flip stroke. */
+ BKE_gpencil_stroke_flip(gps);
+ changed = true;
+ }
+ }
}
-
- changed = true;
+ }
+ /* If not multi-edit, exit loop. */
+ if (!is_multiedit) {
+ break;
}
}
}
@@ -3818,7 +3839,7 @@ static int gpencil_strokes_reproject_exec(bContext *C, wmOperator *op)
/* update frame to get the new location of objects */
if ((mode == GP_REPROJECT_SURFACE) && (cfra_prv != gpf->framenum)) {
cfra_prv = gpf->framenum;
- CFRA = gpf->framenum;
+ scene->r.cfra = gpf->framenum;
BKE_scene_graph_update_for_newframe(depsgraph);
}
@@ -3846,7 +3867,7 @@ static int gpencil_strokes_reproject_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* return frame state and DB to original state */
- CFRA = oldframe;
+ scene->r.cfra = oldframe;
BKE_scene_graph_update_for_newframe(depsgraph);
if (sctx != NULL) {
@@ -3939,6 +3960,284 @@ static int gpencil_recalc_geometry_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
+/* -------------------------------------------------------------------- */
+/** \name Stroke Perimeter from View Operator
+ * \{ */
+
+enum {
+ GP_PERIMETER_VIEW = 0,
+ GP_PERIMETER_FRONT = 1,
+ GP_PERIMETER_SIDE = 2,
+ GP_PERIMETER_TOP = 3,
+ GP_PERIMETER_CAMERA = 4,
+};
+
+enum {
+ GP_STROKE_USE_ACTIVE_MATERIAL = 0,
+ GP_STROKE_USE_CURRENT_MATERIAL = 1,
+ GP_STROKE_USE_NEW_MATERIAL = 2,
+};
+
+static int gpencil_stroke_outline_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const int subdivisions = RNA_int_get(op->ptr, "subdivisions");
+ const float length = RNA_float_get(op->ptr, "length");
+ const bool keep = RNA_boolean_get(op->ptr, "keep");
+ const int thickness = RNA_int_get(op->ptr, "thickness");
+
+ const int view_mode = RNA_enum_get(op->ptr, "view_mode");
+ const int material_mode = RNA_enum_get(op->ptr, "material_mode");
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ bool changed = false;
+
+ float viewmat[4][4];
+ copy_m4_m4(viewmat, rv3d->viewmat);
+
+ switch (view_mode) {
+ case GP_PERIMETER_FRONT:
+ unit_m4(rv3d->viewmat);
+ viewmat[1][1] = 0.0f;
+ viewmat[1][2] = -1.0f;
+
+ viewmat[2][1] = 1.0f;
+ viewmat[2][2] = 0.0f;
+
+ viewmat[3][2] = -10.0f;
+ break;
+ case GP_PERIMETER_SIDE:
+ zero_m4(viewmat);
+ viewmat[0][2] = 1.0f;
+ viewmat[1][0] = 1.0f;
+ viewmat[2][1] = 1.0f;
+ viewmat[3][3] = 1.0f;
+ break;
+ case GP_PERIMETER_TOP:
+ unit_m4(viewmat);
+ break;
+ case GP_PERIMETER_CAMERA: {
+ Scene *scene = CTX_data_scene(C);
+ Object *cam_ob = scene->camera;
+ if (cam_ob != NULL) {
+ invert_m4_m4(viewmat, cam_ob->obmat);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ /* Untag strokes to be sure nothing is pending. */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ gps->flag &= ~GP_STROKE_TAG;
+ }
+ }
+ }
+ /* Create a new material. */
+ int mat_idx = 0;
+ if (material_mode == GP_STROKE_USE_NEW_MATERIAL) {
+ Material *ma = BKE_gpencil_object_material_new(bmain, ob, "Material", NULL);
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+
+ gp_style->flag |= GP_MATERIAL_FILL_SHOW;
+ mat_idx = ob->totcol - 1;
+ }
+
+ /* loop all selected strokes */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ if (gpl->flag & GP_LAYER_HIDE) {
+ continue;
+ }
+ /* Prepare transform matrix. */
+ float diff_mat[4][4];
+ BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat);
+
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
+
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ if (gpf == NULL) {
+ continue;
+ }
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ if ((gps->flag & GP_STROKE_SELECT) == 0) {
+ continue;
+ }
+ if (gps->totpoints == 0) {
+ continue;
+ }
+ if (!ED_gpencil_stroke_material_visible(ob, gps)) {
+ continue;
+ }
+
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ const bool is_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0);
+
+ if (!is_stroke) {
+ continue;
+ }
+
+ /* Duplicate the stroke to apply any layer thickness change. */
+ bGPDstroke *gps_duplicate = BKE_gpencil_stroke_duplicate(gps, true, false);
+
+ /* Apply layer thickness change. */
+ gps_duplicate->thickness += gpl->line_change;
+ /* Apply object scale to thickness. */
+ gps_duplicate->thickness *= mat4_to_scale(ob->obmat);
+ CLAMP_MIN(gps_duplicate->thickness, 1.0f);
+
+ /* Stroke. */
+ const float ovr_thickness = keep ? thickness : 0.0f;
+ bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
+ viewmat, gpd, gpl, gps_duplicate, subdivisions, diff_mat, ovr_thickness);
+ gps_perimeter->flag &= ~GP_STROKE_SELECT;
+ /* Assign material. */
+ switch (material_mode) {
+ case GP_STROKE_USE_ACTIVE_MATERIAL: {
+ if (ob->actcol - 1 < 0) {
+ gps_perimeter->mat_nr = 0;
+ }
+ else {
+ gps_perimeter->mat_nr = ob->actcol - 1;
+ }
+ break;
+ }
+ case GP_STROKE_USE_CURRENT_MATERIAL:
+ gps_perimeter->mat_nr = gps->mat_nr;
+ break;
+ case GP_STROKE_USE_NEW_MATERIAL:
+ gps_perimeter->mat_nr = mat_idx;
+ break;
+ default:
+ break;
+ }
+
+ /* Sample stroke. */
+ if (length > 0.0f) {
+ BKE_gpencil_stroke_sample(gpd, gps_perimeter, length, false, 0);
+ }
+ /* Set stroke thickness. */
+ gps_perimeter->thickness = thickness;
+
+ /* Set pressure constant. */
+ bGPDspoint *pt;
+ for (int i = 0; i < gps_perimeter->totpoints; i++) {
+ pt = &gps_perimeter->points[i];
+ pt->pressure = 1.0f;
+ }
+
+ /* Add perimeter stroke to frame. */
+ BLI_insertlinkafter(&gpf->strokes, gps, gps_perimeter);
+
+ /* Tag original stroke to be removed. */
+ gps->flag |= GP_STROKE_TAG;
+
+ /* Free Temp stroke. */
+ BKE_gpencil_free_stroke(gps_duplicate);
+ changed = true;
+ }
+
+ /* If not multi-edit, exit loop. */
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ }
+ /* Free old strokes. */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->flag & GP_STROKE_TAG) {
+ BLI_remlink(&gpf->strokes, gps);
+ BKE_gpencil_free_stroke(gps);
+ }
+ }
+ }
+ }
+
+ if (changed) {
+ /* notifiers */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_stroke_outline(wmOperatorType *ot)
+{
+ static const EnumPropertyItem view_mode[] = {
+ {GP_PERIMETER_VIEW, "VIEW", 0, "View", ""},
+ {GP_PERIMETER_FRONT, "FRONT", 0, "Front", ""},
+ {GP_PERIMETER_SIDE, "SIDE", 0, "Side", ""},
+ {GP_PERIMETER_TOP, "TOP", 0, "Top", ""},
+ {GP_PERIMETER_CAMERA, "CAMERA", 0, "Camera", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ static const EnumPropertyItem material_mode[] = {
+ {GP_STROKE_USE_ACTIVE_MATERIAL, "ACTIVE", 0, "Active Material", ""},
+ {GP_STROKE_USE_CURRENT_MATERIAL, "KEEP", 0, "Keep Material", "Keep current stroke material"},
+ {GP_STROKE_USE_NEW_MATERIAL, "NEW", 0, "New Material", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Convert Stroke to Outline";
+ ot->idname = "GPENCIL_OT_stroke_outline";
+ ot->description = "Convert stroke to perimeter";
+
+ /* api callbacks */
+ ot->exec = gpencil_stroke_outline_exec;
+ ot->poll = gpencil_stroke_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "view_mode", view_mode, GP_PERIMETER_VIEW, "View", "");
+ RNA_def_enum(ot->srna,
+ "material_mode",
+ material_mode,
+ GP_STROKE_USE_ACTIVE_MATERIAL,
+ "Material Mode",
+ "");
+
+ RNA_def_int(ot->srna,
+ "thickness",
+ 1,
+ 1,
+ 1000,
+ "Thickness",
+ "Thickness of the stroke perimeter",
+ 1,
+ 1000);
+ RNA_def_boolean(ot->srna,
+ "keep",
+ true,
+ "Keep Shape",
+ "Try to keep global shape when the stroke thickness change");
+
+ RNA_def_int(ot->srna, "subdivisions", 3, 0, 10, "Subdivisions", "", 0, 10);
+
+ RNA_def_float(ot->srna, "length", 0.0f, 0.0f, 100.0f, "Sample Length", "", 0.0f, 100.0f);
+}
+
+/** \} */
+
void GPENCIL_OT_recalc_geometry(wmOperatorType *ot)
{
/* identifiers */
@@ -3980,6 +4279,7 @@ static void gpencil_smooth_stroke(bContext *C, wmOperator *op)
/* TODO use `BKE_gpencil_stroke_smooth` when the weights are better used. */
bGPDstroke gps_old = *gps;
gps_old.points = (bGPDspoint *)MEM_dupallocN(gps->points);
+ bool need_update = false;
/* Here the iteration needs to be done outside the smooth functions,
* as there are points that don't get smoothed. */
for (int n = 0; n < repeat; n++) {
@@ -3991,6 +4291,7 @@ static void gpencil_smooth_stroke(bContext *C, wmOperator *op)
/* Perform smoothing. */
if (smooth_position) {
BKE_gpencil_stroke_smooth_point(&gps_old, i, factor, 1, false, false, gps);
+ need_update = true;
}
if (smooth_strength) {
BKE_gpencil_stroke_smooth_strength(&gps_old, i, factor, 1, gps);
@@ -4000,6 +4301,7 @@ static void gpencil_smooth_stroke(bContext *C, wmOperator *op)
}
if (smooth_uv) {
BKE_gpencil_stroke_smooth_uv(&gps_old, i, factor, 1, gps);
+ need_update = true;
}
}
if (n < repeat - 1) {
@@ -4007,6 +4309,11 @@ static void gpencil_smooth_stroke(bContext *C, wmOperator *op)
}
}
MEM_freeN(gps_old.points);
+
+ if (need_update) {
+ gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
+ BKE_gpencil_stroke_geometry_update(gpd_, gps);
+ }
}
}
GP_EDITABLE_STROKES_END(gpstroke_iter);
@@ -4454,6 +4761,8 @@ void GPENCIL_OT_stroke_sample(wmOperatorType *ot)
/* properties */
prop = RNA_def_float(ot->srna, "length", 0.1f, 0.0f, 100.0f, "Length", "", 0.0f, 100.0f);
+ prop = RNA_def_float(
+ ot->srna, "sharp_threshold", 0.1f, 0.0f, M_PI, "Sharp Threshold", "", 0.0f, M_PI);
/* avoid re-using last var */
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 3f06dbfdbb3..5305c764b3a 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -1748,7 +1748,7 @@ static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *op)
tgpf->v3d = tgpf->area->spacedata.first;
tgpf->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
tgpf->win = CTX_wm_window(C);
- tgpf->active_cfra = CFRA;
+ tgpf->active_cfra = scene->r.cfra;
tgpf->reports = op->reports;
/* Setup space conversions. */
@@ -2222,8 +2222,8 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* Hash of selected frames. */
GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64);
- /* If not multi-frame and there is no frame in CFRA for the active layer, create
- * a new frame. */
+ /* If not multi-frame and there is no frame in scene->r.cfra for the active layer,
+ * create a new frame. */
if (!is_multiedit) {
tgpf->gpf = BKE_gpencil_layer_frame_get(
tgpf->gpl,
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index d656241c463..3cb3a50e702 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -608,6 +608,7 @@ void GPENCIL_OT_stroke_merge_by_distance(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_merge_material(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_reset_vertex_color(struct wmOperatorType *ot);
void GPENCIL_OT_stroke_normalize(struct wmOperatorType *ot);
+void GPENCIL_OT_stroke_outline(struct wmOperatorType *ot);
void GPENCIL_OT_material_to_vertex_color(struct wmOperatorType *ot);
void GPENCIL_OT_extract_palette_vertex(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 0039dbae674..dc63acf5136 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -483,10 +483,10 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer");
tgpil->gpl = gpl;
- bGPDframe *gpf = gpencil_get_previous_keyframe(gpl, CFRA);
+ bGPDframe *gpf = gpencil_get_previous_keyframe(gpl, scene->r.cfra);
tgpil->prevFrame = BKE_gpencil_frame_duplicate(gpf, true);
- gpf = gpencil_get_next_keyframe(gpl, CFRA);
+ gpf = gpencil_get_next_keyframe(gpl, scene->r.cfra);
tgpil->nextFrame = BKE_gpencil_frame_duplicate(gpf, true);
BLI_addtail(&tgpi->ilayers, tgpil);
@@ -750,7 +750,7 @@ static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent
tGPDinterpolate *tgpi = NULL;
/* Cannot interpolate if not between 2 frames. */
- int cfra = CFRA;
+ int cfra = scene->r.cfra;
bGPDframe *gpf_prv = gpencil_get_previous_keyframe(gpl, cfra);
bGPDframe *gpf_next = gpencil_get_next_keyframe(gpl, cfra);
if (ELEM(NULL, gpf_prv, gpf_next)) {
@@ -1221,7 +1221,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
GP_SpaceConversion gsc;
gpencil_point_conversion_init(C, &gsc);
- int cfra = CFRA;
+ int cfra = scene->r.cfra;
GP_Interpolate_Settings *ipo_settings = &ts->gp_interpolate;
const int step = RNA_int_get(op->ptr, "step");
@@ -1483,7 +1483,8 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
*/
static const EnumPropertyItem gpencil_interpolation_type_items[] = {
/* Interpolation. */
- RNA_ENUM_ITEM_HEADING(N_("Interpolation"), "Standard transitions between keyframes"),
+ RNA_ENUM_ITEM_HEADING(CTX_N_(BLT_I18NCONTEXT_ID_GPENCIL, "Interpolation"),
+ N_("Standard transitions between keyframes")),
{GP_IPO_LINEAR,
"LINEAR",
ICON_IPO_LINEAR,
@@ -1496,9 +1497,9 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
"Custom interpolation defined using a curve map"},
/* Easing. */
- RNA_ENUM_ITEM_HEADING(N_("Easing (by strength)"),
- "Predefined inertial transitions, useful for motion graphics "
- "(from least to most \"dramatic\")"),
+ RNA_ENUM_ITEM_HEADING(CTX_N_(BLT_I18NCONTEXT_ID_GPENCIL, "Easing (by strength)"),
+ N_("Predefined inertial transitions, useful for motion graphics "
+ "(from least to most \"dramatic\")")),
{GP_IPO_SINE,
"SINE",
ICON_IPO_SINE,
@@ -1515,7 +1516,8 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
"Circular",
"Circular easing (strongest and most dynamic)"},
- RNA_ENUM_ITEM_HEADING(N_("Dynamic Effects"), "Simple physics-inspired easing effects"),
+ RNA_ENUM_ITEM_HEADING(CTX_N_(BLT_I18NCONTEXT_ID_GPENCIL, "Dynamic Effects"),
+ N_("Simple physics-inspired easing effects")),
{GP_IPO_BACK, "BACK", ICON_IPO_BACK, "Back", "Cubic easing with overshoot and settle"},
{GP_IPO_BOUNCE,
"BOUNCE",
@@ -1569,6 +1571,7 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
/* identifiers */
ot->name = "Interpolate Sequence";
ot->idname = "GPENCIL_OT_interpolate_sequence";
+ ot->translation_context = BLT_I18NCONTEXT_ID_GPENCIL;
ot->description = "Generate 'in-betweens' to smoothly interpolate between Grease Pencil frames";
/* api callbacks */
diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c
index 06343dcad43..8ff3f20cef3 100644
--- a/source/blender/editors/gpencil/gpencil_merge.c
+++ b/source/blender/editors/gpencil/gpencil_merge.c
@@ -113,7 +113,7 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo
else {
add_frame_mode = GP_GETFRAME_ADD_NEW;
}
- bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, add_frame_mode);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, add_frame_mode);
/* stroke */
bGPDstroke *gps = BKE_gpencil_stroke_new(MAX2(ob->actcol - 1, 0), totpoints, brush->size);
diff --git a/source/blender/editors/gpencil/gpencil_mesh.cc b/source/blender/editors/gpencil/gpencil_mesh.cc
index aee00d4ede3..b27e1c75746 100644
--- a/source/blender/editors/gpencil/gpencil_mesh.cc
+++ b/source/blender/editors/gpencil/gpencil_mesh.cc
@@ -283,7 +283,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
}
/* Move scene to new frame. */
- CFRA = i;
+ scene->r.cfra = i;
BKE_scene_graph_update_for_newframe(depsgraph);
/* Loop all objects in the list. */
@@ -325,7 +325,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
}
/* Return scene frame state and DB to original state. */
- CFRA = oldframe;
+ scene->r.cfra = oldframe;
BKE_scene_graph_update_for_newframe(depsgraph);
/* Remove unused materials. */
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 99e28270c3e..3d92fbabfc4 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -635,6 +635,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_stroke_merge_material);
WM_operatortype_append(GPENCIL_OT_stroke_reset_vertex_color);
WM_operatortype_append(GPENCIL_OT_stroke_normalize);
+ WM_operatortype_append(GPENCIL_OT_stroke_outline);
WM_operatortype_append(GPENCIL_OT_material_to_vertex_color);
WM_operatortype_append(GPENCIL_OT_extract_palette_vertex);
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 7c7f532f087..8e33a029229 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -918,6 +918,67 @@ static void gpencil_stroke_unselect(bGPdata *gpd, bGPDstroke *gps)
}
}
+static bGPDstroke *gpencil_stroke_to_outline(tGPsdata *p, bGPDstroke *gps)
+{
+ bGPDlayer *gpl = p->gpl;
+ RegionView3D *rv3d = p->region->regiondata;
+ Brush *brush = p->brush;
+ BrushGpencilSettings *gpencil_settings = brush->gpencil_settings;
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(p->ob, gps->mat_nr + 1);
+ const bool is_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0);
+
+ if (!is_stroke) {
+ return gps;
+ }
+
+ /* Duplicate the stroke to apply any layer thickness change. */
+ bGPDstroke *gps_duplicate = BKE_gpencil_stroke_duplicate(gps, true, false);
+
+ /* Apply layer thickness change. */
+ gps_duplicate->thickness += gpl->line_change;
+ /* Apply object scale to thickness. */
+ gps_duplicate->thickness *= mat4_to_scale(p->ob->obmat);
+ CLAMP_MIN(gps_duplicate->thickness, 1.0f);
+
+ /* Stroke. */
+ float diff_mat[4][4];
+ unit_m4(diff_mat);
+ const float outline_thickness = (float)brush->size * gpencil_settings->outline_fac * 0.5f;
+ bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
+ rv3d->viewmat, p->gpd, gpl, gps_duplicate, 3, diff_mat, outline_thickness);
+ /* Assign material. */
+ if (gpencil_settings->material_alt == NULL) {
+ gps_perimeter->mat_nr = gps->mat_nr;
+ }
+ else {
+ Material *ma = gpencil_settings->material_alt;
+ int mat_idx = BKE_gpencil_material_find_index_by_name_prefix(p->ob, ma->id.name + 2);
+ if (mat_idx > -1) {
+ gps_perimeter->mat_nr = mat_idx;
+ }
+ else {
+ gps_perimeter->mat_nr = gps->mat_nr;
+ }
+ }
+
+ /* Set pressure constant. */
+ gps_perimeter->thickness = max_ii((int)outline_thickness, 1);
+
+ bGPDspoint *pt;
+ for (int i = 0; i < gps_perimeter->totpoints; i++) {
+ pt = &gps_perimeter->points[i];
+ pt->pressure = 1.0f;
+ }
+
+ /* Remove original stroke. */
+ BKE_gpencil_free_stroke(gps);
+
+ /* Free Temp stroke. */
+ BKE_gpencil_free_stroke(gps_duplicate);
+
+ return gps_perimeter;
+}
+
/* make a new stroke from the buffer data */
static void gpencil_stroke_newfrombuffer(tGPsdata *p)
{
@@ -1221,6 +1282,23 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p)
BKE_gpencil_stroke_simplify_adaptive(gpd, gps, brush->gpencil_settings->simplify_f);
}
+ /* Set material index. */
+ gps->mat_nr = BKE_gpencil_object_material_get_index_from_brush(p->ob, p->brush);
+ if (gps->mat_nr < 0) {
+ if (p->ob->actcol - 1 < 0) {
+ gps->mat_nr = 0;
+ }
+ else {
+ gps->mat_nr = p->ob->actcol - 1;
+ }
+ }
+
+ /* Convert to Outline. */
+ if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_SETTINGS) &&
+ (brush->gpencil_settings->flag & GP_BRUSH_OUTLINE_STROKE)) {
+ gps = gpencil_stroke_to_outline(p, gps);
+ }
+
/* reproject to plane (only in 3d space) */
gpencil_reproject_toplane(p, gps);
/* change position relative to parent object */
@@ -1235,17 +1313,6 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p)
}
}
- /* Save material index */
- gps->mat_nr = BKE_gpencil_object_material_get_index_from_brush(p->ob, p->brush);
- if (gps->mat_nr < 0) {
- if (p->ob->actcol - 1 < 0) {
- gps->mat_nr = 0;
- }
- else {
- gps->mat_nr = p->ob->actcol - 1;
- }
- }
-
/* add stroke to frame, usually on tail of the listbase, but if on back is enabled the stroke
* is added on listbase head because the drawing order is inverse and the head stroke is the
* first to draw. This is very useful for artist when drawing the background.
@@ -2166,7 +2233,7 @@ static void gpencil_paint_initstroke(tGPsdata *p,
if (gpl->actframe && gpl->actframe->strokes.first) {
if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) {
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);
+ gpl->actframe = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, frame_mode);
}
has_layer_to_erase = true;
break;
@@ -2204,7 +2271,7 @@ static void gpencil_paint_initstroke(tGPsdata *p,
bool need_tag = p->gpl->actframe == NULL;
bGPDframe *actframe = p->gpl->actframe;
- p->gpf = BKE_gpencil_layer_frame_get(p->gpl, CFRA, add_frame_mode);
+ p->gpf = BKE_gpencil_layer_frame_get(p->gpl, scene->r.cfra, add_frame_mode);
/* Only if there wasn't an active frame, need update. */
if (need_tag) {
DEG_id_tag_update(&p->gpd->id, ID_RECALC_GEOMETRY);
@@ -2343,7 +2410,7 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
if (p->paintmode == GP_PAINTMODE_ERASER) {
GPUVertFormat *format = immVertexFormat();
const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
GPU_line_smooth(true);
GPU_blend(GPU_BLEND_ALPHA);
@@ -2353,7 +2420,7 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
immUnbindProgram();
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
@@ -3658,9 +3725,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
- /* Exit painting mode (and/or end current stroke).
- *
- */
+ /* Exit painting mode (and/or end current stroke). */
if (ELEM(event->type, EVT_RETKEY, EVT_PADENTER, EVT_ESCKEY, EVT_SPACEKEY)) {
p->status = GP_STATUS_DONE;
@@ -3755,7 +3820,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* handle mode-specific events */
if (p->status == GP_STATUS_PAINTING) {
/* handle painting mouse-movements? */
- if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) {
+ if (ISMOUSE_MOTION(event->type) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) {
/* handle drawing event */
bool is_speed_guide = ((guide->use_guide) &&
(p->brush && (p->brush->gpencil_tool == GPAINT_TOOL_DRAW)));
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index b57b8145749..4a4fffc9638 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -292,7 +292,7 @@ static void gpencil_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
Brush *brush = tgpi->brush;
- int cfra = CFRA;
+ int cfra = scene->r.cfra;
bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
@@ -1024,8 +1024,10 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, false);
/* add small offset to keep stroke over the surface */
- if ((depth_arr) && (gpd->zdepth_offset > 0.0f) && (depth_arr[i] != DEPTH_INVALID)) {
- depth_arr[i] *= (1.0f - (gpd->zdepth_offset / 1000.0f));
+ if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) {
+ if ((depth_arr) && (gpd->zdepth_offset > 0.0f) && (depth_arr[i] != DEPTH_INVALID)) {
+ depth_arr[i] *= (1.0f - (gpd->zdepth_offset / 1000.0f));
+ }
}
/* convert screen-coordinates to 3D coordinates */
@@ -1107,7 +1109,7 @@ static void gpencil_primitive_update(bContext *C, wmOperator *op, tGPDprimitive
/* Initialize mouse points. */
static void gpencil_primitive_interaction_begin(tGPDprimitive *tgpi, const wmEvent *event)
{
- copy_v2fl_v2i(tgpi->mval, event->mval);
+ WM_event_drag_start_mval_fl(event, tgpi->region, tgpi->mval);
copy_v2_v2(tgpi->origin, tgpi->mval);
copy_v2_v2(tgpi->start, tgpi->mval);
copy_v2_v2(tgpi->end, tgpi->mval);
@@ -1195,7 +1197,7 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op)
tgpi->orign_type = RNA_enum_get(op->ptr, "type");
/* set current frame number */
- tgpi->cframe = CFRA;
+ tgpi->cframe = scene->r.cfra;
/* set GP datablock */
tgpi->gpd = gpd;
diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
index 6d0848de36d..e27cd255217 100644
--- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c
+++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
@@ -1013,7 +1013,7 @@ static void gpencil_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
gpl = CTX_data_active_gpencil_layer(C);
}
bGPDframe *gpf = BKE_gpencil_layer_frame_get(
- gpl, CFRA, IS_AUTOKEY_ON(scene) ? GP_GETFRAME_ADD_NEW : GP_GETFRAME_USE_PREV);
+ gpl, scene->r.cfra, IS_AUTOKEY_ON(scene) ? GP_GETFRAME_ADD_NEW : GP_GETFRAME_USE_PREV);
if (gpf == NULL) {
continue;
}
@@ -1161,6 +1161,7 @@ static bool gpencil_sculpt_brush_init(bContext *C, wmOperator *op)
gso->is_painting = false;
gso->first = true;
+ gso->mval_prev[0] = -1.0f;
gso->gpd = ED_gpencil_data_get_active(C);
gso->cfra = INT_MAX; /* NOTE: So that first stroke will get handled in init_stroke() */
@@ -1335,7 +1336,7 @@ static void gpencil_sculpt_brush_init_stroke(bContext *C, tGP_BrushEditData *gso
bGPdata *gpd = gso->gpd;
Scene *scene = gso->scene;
- int cfra = CFRA;
+ int cfra = scene->r.cfra;
/* only try to add a new frame if this is the first stroke, or the frame has changed */
if ((gpd == NULL) || (cfra == gso->cfra)) {
@@ -1442,6 +1443,7 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso,
char tool = gso->brush->gpencil_sculpt_tool;
const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure :
gso->brush->size;
+ const bool is_masking = GPENCIL_ANY_SCULPT_MASK(gso->mask);
bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
bGPDspoint *pt_active = NULL;
@@ -1459,7 +1461,7 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso,
if (gps->totpoints == 1) {
bGPDspoint pt_temp;
pt = &gps->points[0];
- if (GPENCIL_ANY_SCULPT_MASK(gso->mask) && (pt->flag & GP_SPOINT_SELECT) != 0) {
+ if ((is_masking && (pt->flag & GP_SPOINT_SELECT) != 0) || (!is_masking)) {
gpencil_point_to_parent_space(gps->points, diff_mat, &pt_temp);
gpencil_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
@@ -1516,7 +1518,8 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso,
/* To each point individually... */
pt = &gps->points[i];
- if ((pt->runtime.pt_orig == NULL) && (tool != GPSCULPT_TOOL_GRAB)) {
+ if ((i != gps->totpoints - 2) && (pt->runtime.pt_orig == NULL) &&
+ (tool != GPSCULPT_TOOL_GRAB)) {
continue;
}
pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
@@ -1618,7 +1621,8 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C,
}
/* Check if the stroke collide with brush. */
- if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) {
+ if ((gps->totpoints > 1) &&
+ (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat))) {
continue;
}
@@ -1982,7 +1986,7 @@ static void gpencil_sculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *
}
/* Store coordinates as reference, if operator just started running */
- if (gso->first) {
+ if (gso->mval_prev[0] == -1.0f) {
gso->mval_prev[0] = gso->mval[0];
gso->mval_prev[1] = gso->mval[1];
gso->pressure_prev = gso->pressure;
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index e903d11a1e0..a19265720e8 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -759,7 +759,7 @@ static bool gpencil_select_same_layer(bContext *C)
bool changed = false;
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, scene->r.cfra, GP_GETFRAME_USE_PREV);
bGPDstroke *gps;
bool found = false;
diff --git a/source/blender/editors/gpencil/gpencil_trace_ops.c b/source/blender/editors/gpencil/gpencil_trace_ops.c
index 24a0dab24c9..f6e88e05d46 100644
--- a/source/blender/editors/gpencil/gpencil_trace_ops.c
+++ b/source/blender/editors/gpencil/gpencil_trace_ops.c
@@ -295,7 +295,7 @@ static int gpencil_trace_image_exec(bContext *C, wmOperator *op)
job->base_active = CTX_data_active_base(C);
job->ob_active = job->base_active->object;
job->image = (Image *)job->ob_active->data;
- job->frame_target = CFRA;
+ job->frame_target = scene->r.cfra;
job->use_current_frame = RNA_boolean_get(op->ptr, "use_current_frame");
/* Create a new grease pencil object or reuse selected. */
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index fc5b3838900..e47f16ac466 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -388,6 +388,17 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C,
/* Create new layer */
/* TODO: have some way of specifying that we don't want this? */
+ {
+ /* "New Layer" entry */
+ item_tmp.identifier = "__CREATE__";
+ item_tmp.name = "New Layer";
+ item_tmp.value = -1;
+ item_tmp.icon = ICON_ADD;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+
+ /* separator */
+ RNA_enum_item_add_separator(&item, &totitem);
+ }
const int tot = BLI_listbase_count(&gpd->layers);
/* Existing layers */
@@ -405,17 +416,6 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C,
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
- {
- /* separator */
- RNA_enum_item_add_separator(&item, &totitem);
-
- /* "New Layer" entry */
- item_tmp.identifier = "__CREATE__";
- item_tmp.name = "New Layer";
- item_tmp.value = -1;
- item_tmp.icon = ICON_ADD;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -1683,7 +1683,7 @@ void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y)
GPUVertFormat *format = immVertexFormat();
const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
GPU_line_smooth(true);
GPU_blend(GPU_BLEND_ALPHA);
@@ -1693,7 +1693,7 @@ void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y)
immUnbindProgram();
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
@@ -1865,7 +1865,7 @@ static void gpencil_brush_cursor_draw(bContext *C, int x, int y, void *customdat
/* draw icon */
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
GPU_line_smooth(true);
GPU_blend(GPU_BLEND_ALPHA);
@@ -3189,7 +3189,7 @@ bGPDstroke *ED_gpencil_stroke_join_and_trim(
/* Join both strokes. */
int totpoint = gps_final->totpoints;
- BKE_gpencil_stroke_join(gps_final, gps, false, true, true);
+ BKE_gpencil_stroke_join(gps_final, gps, false, true, true, true);
/* Select the join points and merge if the distance is very small. */
pt = &gps_final->points[totpoint - 1];