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:
authorFalk David <falkdavid@gmx.de>2020-11-13 23:43:00 +0300
committerFalk David <falkdavid@gmx.de>2020-11-13 23:43:00 +0300
commit0be88c7d15d2ad1af284c6283370173647ae74eb (patch)
tree5fff573c512e284547ebe0c921ecffdae2c377c4 /source/blender/draw
parent9d28353b525ecfbcca1501be72e4276dfb2bbc2a (diff)
GPencil: Merge GSoC curve edit mode
Differential Revision: https://developer.blender.org/D8660 This patch is the result of the GSoC 2020 "Editing Grease Pencil Strokes Using Curves" project. It adds a submode to greasepencil edit mode that allows for the transformation of greasepencil strokes using bezier curves. More information about the project can be found here: https://wiki.blender.org/wiki/User:Filedescriptor/GSoC_2020.
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/engines/overlay/overlay_gpencil.c61
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h3
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl6
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl5
-rw-r--r--source/blender/draw/intern/draw_cache.h2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_gpencil.c180
6 files changed, 254 insertions, 3 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c
index ccc914e0422..7f9290a6c3a 100644
--- a/source/blender/draw/engines/overlay/overlay_gpencil.c
+++ b/source/blender/draw/engines/overlay/overlay_gpencil.c
@@ -49,6 +49,10 @@ void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata)
pd->edit_gpencil_wires_grp = NULL;
psl->edit_gpencil_ps = NULL;
+ pd->edit_gpencil_curve_handle_grp = NULL;
+ pd->edit_gpencil_curve_points_grp = NULL;
+ psl->edit_gpencil_curve_ps = NULL;
+
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
Object *ob = draw_ctx->obact;
@@ -105,7 +109,8 @@ void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata)
(GPENCIL_EDIT_MODE(gpd) &&
(ts->gpencil_selectmode_edit != GP_SELECTMODE_STROKE));
- if ((!GPENCIL_VERTEX_MODE(gpd) && !GPENCIL_PAINT_MODE(gpd)) || use_vertex_mask) {
+ if ((!GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) &&
+ ((!GPENCIL_VERTEX_MODE(gpd) && !GPENCIL_PAINT_MODE(gpd)) || use_vertex_mask)) {
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->edit_gpencil_ps, state | pd->clipping_state);
@@ -132,6 +137,37 @@ void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata)
}
}
+ /* Handles and curve point for Curve Edit submode. */
+ if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) {
+ DRWState state = DRW_STATE_WRITE_COLOR;
+ DRW_PASS_CREATE(psl->edit_gpencil_curve_ps, state | pd->clipping_state);
+
+ /* Edit lines. */
+ if (show_lines) {
+ sh = OVERLAY_shader_edit_gpencil_wire();
+ pd->edit_gpencil_wires_grp = grp = DRW_shgroup_create(sh, psl->edit_gpencil_curve_ps);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_bool_copy(grp, "doMultiframe", show_multi_edit_lines);
+ DRW_shgroup_uniform_bool_copy(grp, "doWeightColor", is_weight_paint);
+ DRW_shgroup_uniform_bool_copy(grp, "hideSelect", hide_select);
+ DRW_shgroup_uniform_float_copy(grp, "gpEditOpacity", v3d->vertex_opacity);
+ DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
+ }
+
+ sh = OVERLAY_shader_edit_curve_handle();
+ pd->edit_gpencil_curve_handle_grp = grp = DRW_shgroup_create(sh, psl->edit_gpencil_curve_ps);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_bool_copy(grp, "showCurveHandles", pd->edit_curve.show_handles);
+ DRW_shgroup_uniform_int_copy(grp, "curveHandleDisplay", pd->edit_curve.handle_display);
+ DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
+
+ sh = OVERLAY_shader_edit_curve_point();
+ pd->edit_gpencil_curve_points_grp = grp = DRW_shgroup_create(sh, psl->edit_gpencil_curve_ps);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_bool_copy(grp, "showCurveHandles", pd->edit_curve.show_handles);
+ DRW_shgroup_uniform_int_copy(grp, "curveHandleDisplay", pd->edit_curve.handle_display);
+ }
+
/* control points for primitives and speed guide */
const bool is_cppoint = (gpd->runtime.tot_cp_points > 0);
const bool is_speed_guide = (ts->gp_sculpt.guide.use_guide &&
@@ -182,6 +218,7 @@ void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata)
void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
struct GPUShader *sh;
DRWShadingGroup *grp;
@@ -196,6 +233,9 @@ void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata)
ToolSettings *ts = scene->toolsettings;
const View3DCursor *cursor = &scene->cursor;
+ pd->edit_curve.show_handles = v3d->overlay.handle_display != CURVE_HANDLE_NONE;
+ pd->edit_curve.handle_display = v3d->overlay.handle_display;
+
if (gpd == NULL || ob->type != OB_GPENCIL) {
return;
}
@@ -303,6 +343,20 @@ static void OVERLAY_edit_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob
struct GPUBatch *geom = DRW_cache_gpencil_edit_points_get(ob, pd->cfra);
DRW_shgroup_call_no_cull(grp, geom, ob);
}
+
+ if (pd->edit_gpencil_curve_handle_grp) {
+ struct GPUBatch *geom = DRW_cache_gpencil_edit_curve_handles_get(ob, pd->cfra);
+ if (geom) {
+ DRW_shgroup_call_no_cull(pd->edit_gpencil_curve_handle_grp, geom, ob);
+ }
+ }
+
+ if (pd->edit_gpencil_curve_points_grp) {
+ struct GPUBatch *geom = DRW_cache_gpencil_edit_curve_points_get(ob, pd->cfra);
+ if (geom) {
+ DRW_shgroup_call_no_cull(pd->edit_gpencil_curve_points_grp, geom, ob);
+ }
+ }
}
static void overlay_gpencil_draw_stroke_color_name(bGPDlayer *UNUSED(gpl),
@@ -407,4 +461,9 @@ void OVERLAY_edit_gpencil_draw(OVERLAY_Data *vedata)
if (psl->edit_gpencil_ps) {
DRW_draw_pass(psl->edit_gpencil_ps);
}
+
+ /* Curve edit handles. */
+ if (psl->edit_gpencil_curve_ps) {
+ DRW_draw_pass(psl->edit_gpencil_curve_ps);
+ }
}
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index c259d9351f3..b9d591a5642 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -77,6 +77,7 @@ typedef struct OVERLAY_PassList {
DRWPass *edit_curve_handle_ps;
DRWPass *edit_gpencil_ps;
DRWPass *edit_gpencil_gizmos_ps;
+ DRWPass *edit_gpencil_curve_ps;
DRWPass *edit_lattice_ps;
DRWPass *edit_mesh_depth_ps[2];
DRWPass *edit_mesh_verts_ps[2];
@@ -252,6 +253,8 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *edit_lattice_wires_grp;
DRWShadingGroup *edit_gpencil_points_grp;
DRWShadingGroup *edit_gpencil_wires_grp;
+ DRWShadingGroup *edit_gpencil_curve_handle_grp;
+ DRWShadingGroup *edit_gpencil_curve_points_grp;
DRWShadingGroup *edit_mesh_depth_grp[2];
DRWShadingGroup *edit_mesh_faces_grp[2];
DRWShadingGroup *edit_mesh_faces_cage_grp[2];
diff --git a/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl b/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl
index 9311542a79e..442f69aec7e 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl
@@ -53,6 +53,9 @@ void main()
bool edge_selected = (((vertFlag[1] | vertFlag[0]) & VERT_SELECTED) != 0);
bool handle_selected = (showCurveHandles &&
(((vertFlag[1] | vertFlag[0]) & VERT_SELECTED_BEZT_HANDLE) != 0));
+ /* It reuses freestyle flag because the flag is 8 bits and all are already used and this
+ * flag is not used in this context. */
+ bool is_gpencil = ((vertFlag[1] & EDGE_FREESTYLE) != 0);
/* If handle type is only selected and the edge is not selected, don't show. */
if ((curveHandleDisplay != CURVE_HANDLE_ALL) && (!handle_selected)) {
@@ -61,6 +64,9 @@ void main()
if ((!is_u_segment) && (color_id <= 4)) {
return;
}
+ if (is_gpencil) {
+ return;
+ }
}
vec4 inner_color;
diff --git a/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl
index a811fcca0d4..6b4edbfe578 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl
@@ -17,16 +17,17 @@ void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
+ /* Reuse the FREESTYLE flag to determine is GPencil. */
if ((data & VERT_SELECTED) != 0) {
if ((data & VERT_ACTIVE) != 0) {
finalColor = colorEditMeshActive;
}
else {
- finalColor = colorVertexSelect;
+ finalColor = ((data & EDGE_FREESTYLE) == 0) ? colorVertexSelect : colorGpencilVertexSelect;
}
}
else {
- finalColor = colorVertex;
+ finalColor = ((data & EDGE_FREESTYLE) == 0) ? colorVertex : colorGpencilVertex;
}
vec3 world_pos = point_object_to_world(pos);
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index afbf9903dbc..9fd7ffd4692 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -253,6 +253,8 @@ struct GPUBatch *DRW_cache_gpencil_strokes_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_fills_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_lines_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_points_get(struct Object *ob, int cfra);
+struct GPUBatch *DRW_cache_gpencil_edit_curve_handles_get(struct Object *ob, int cfra);
+struct GPUBatch *DRW_cache_gpencil_edit_curve_points_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_sbuffer_stroke_get(struct Object *ob);
struct GPUBatch *DRW_cache_gpencil_sbuffer_fill_get(struct Object *ob);
diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c
index 220c7041c7f..0a80f7df877 100644
--- a/source/blender/draw/intern/draw_cache_impl_gpencil.c
+++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c
@@ -21,6 +21,7 @@
* \ingroup draw
*/
+#include "DNA_curve_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_screen_types.h"
@@ -43,6 +44,9 @@
#include "draw_cache.h"
#include "draw_cache_impl.h"
+#define BEZIER_HANDLE 1 << 3
+#define COLOR_SHIFT 5
+
/* ---------------------------------------------------------------------- */
typedef struct GpencilBatchCache {
/** Instancing Data */
@@ -59,6 +63,10 @@ typedef struct GpencilBatchCache {
GPUVertBuf *edit_vbo;
GPUBatch *edit_lines_batch;
GPUBatch *edit_points_batch;
+ /** Edit Curve Mode */
+ GPUVertBuf *edit_curve_vbo;
+ GPUBatch *edit_curve_handles_batch;
+ GPUBatch *edit_curve_points_batch;
/** Cache is dirty */
bool is_dirty;
@@ -123,6 +131,10 @@ static void gpencil_batch_cache_clear(GpencilBatchCache *cache)
GPU_BATCH_DISCARD_SAFE(cache->edit_points_batch);
GPU_VERTBUF_DISCARD_SAFE(cache->edit_vbo);
+ GPU_BATCH_DISCARD_SAFE(cache->edit_curve_handles_batch);
+ GPU_BATCH_DISCARD_SAFE(cache->edit_curve_points_batch);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit_curve_vbo);
+
cache->is_dirty = true;
}
@@ -197,6 +209,23 @@ static GPUVertFormat *gpencil_edit_stroke_format(void)
}
/* MUST match the format below. */
+typedef struct gpEditCurveVert {
+ float pos[3];
+ int data;
+} gpEditCurveVert;
+
+static GPUVertFormat *gpencil_edit_curve_format(void)
+{
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ /* initialize vertex formats */
+ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 1, GPU_FETCH_INT);
+ }
+ return &format;
+}
+
+/* MUST match the format below. */
typedef struct gpColorVert {
float vcol[4]; /* Vertex color */
float fcol[4]; /* Fill color */
@@ -228,6 +257,7 @@ typedef struct gpIterData {
GPUIndexBufBuilder ibo;
int vert_len;
int tri_len;
+ int curve_len;
} gpIterData;
static GPUVertBuf *gpencil_dummy_buffer_get(void)
@@ -383,6 +413,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
.ibo = {0},
.vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */
.tri_len = 0,
+ .curve_len = 0,
};
BKE_gpencil_visible_stroke_iter(
NULL, ob, NULL, gpencil_object_verts_count_cb, &iter, do_onion, cfra);
@@ -653,6 +684,11 @@ typedef struct gpEditIterData {
int vgindex;
} gpEditIterData;
+typedef struct gpEditCurveIterData {
+ gpEditCurveVert *verts;
+ int vgindex;
+} gpEditCurveIterData;
+
static uint32_t gpencil_point_edit_flag(const bool layer_lock,
const bGPDspoint *pt,
int v,
@@ -698,6 +734,92 @@ static void gpencil_edit_stroke_iter_cb(bGPDlayer *gpl,
vert_ptr->weight = gpencil_point_edit_weight(dvert, 0, iter->vgindex);
}
+static void gpencil_edit_curve_stroke_count_cb(bGPDlayer *gpl,
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps,
+ void *thunk)
+{
+ if (gpl->flag & GP_LAYER_LOCKED) {
+ return;
+ }
+
+ gpIterData *iter = (gpIterData *)thunk;
+
+ if (gps->editcurve == NULL) {
+ return;
+ }
+
+ /* Store first index offset */
+ gps->runtime.curve_start = iter->curve_len;
+ iter->curve_len += gps->editcurve->tot_curve_points * 4;
+}
+
+static char gpencil_beztriple_vflag_get(char flag,
+ char col_id,
+ bool handle_point,
+ const bool handle_selected)
+{
+ char vflag = 0;
+ SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERT_SELECTED);
+ SET_FLAG_FROM_TEST(vflag, handle_point, BEZIER_HANDLE);
+ SET_FLAG_FROM_TEST(vflag, handle_selected, VFLAG_VERT_SELECTED_BEZT_HANDLE);
+ /* Reuse flag of Freestyle to indicate is GPencil data. */
+ vflag |= VFLAG_EDGE_FREESTYLE;
+
+ /* Handle color id. */
+ vflag |= col_id << COLOR_SHIFT;
+ return vflag;
+}
+
+static void gpencil_edit_curve_stroke_iter_cb(bGPDlayer *gpl,
+ bGPDframe *gpf,
+ bGPDstroke *gps,
+ void *thunk)
+{
+ if (gpl->flag & GP_LAYER_LOCKED) {
+ return;
+ }
+
+ if (gps->editcurve == NULL) {
+ return;
+ }
+ bGPDcurve *editcurve = gps->editcurve;
+ gpEditCurveIterData *iter = (gpEditCurveIterData *)thunk;
+ const int v = gps->runtime.curve_start;
+ gpEditCurveVert *vert_ptr = iter->verts + v;
+ /* Hide points when the curve is unselected. Passing the control point
+ * as handle produces the point shader skip it if you are not in ALL mode. */
+ const bool hide = !(editcurve->flag & GP_CURVE_SELECT);
+
+ for (int i = 0; i < editcurve->tot_curve_points; i++) {
+ BezTriple *bezt = &editcurve->curve_points[i].bezt;
+ const bool handle_selected = BEZT_ISSEL_ANY(bezt);
+ const char vflag[3] = {
+ gpencil_beztriple_vflag_get(bezt->f1, bezt->h1, true, handle_selected),
+ gpencil_beztriple_vflag_get(bezt->f2, bezt->h1, hide, handle_selected),
+ gpencil_beztriple_vflag_get(bezt->f3, bezt->h2, true, handle_selected),
+ };
+
+ /* First segment. */
+ copy_v3_v3(vert_ptr->pos, bezt->vec[0]);
+ vert_ptr->data = vflag[0];
+ vert_ptr++;
+
+ copy_v3_v3(vert_ptr->pos, bezt->vec[1]);
+ vert_ptr->data = vflag[1];
+ vert_ptr++;
+
+ /* Second segment. */
+ copy_v3_v3(vert_ptr->pos, bezt->vec[1]);
+ vert_ptr->data = vflag[1];
+ vert_ptr++;
+
+ copy_v3_v3(vert_ptr->pos, bezt->vec[2]);
+ vert_ptr->data = vflag[2];
+ vert_ptr++;
+ }
+}
+
static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfra)
{
bGPdata *gpd = (bGPdata *)ob->data;
@@ -737,6 +859,46 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
cache->edit_lines_batch = GPU_batch_create(GPU_PRIM_LINE_STRIP, cache->vbo, NULL);
GPU_batch_vertbuf_add(cache->edit_lines_batch, cache->edit_vbo);
+ }
+
+ /* Curve Handles and Points for Editing. */
+ if (cache->edit_curve_vbo == NULL) {
+ gpIterData iterdata = {
+ .gpd = gpd,
+ .verts = NULL,
+ .ibo = {0},
+ .vert_len = 0,
+ .tri_len = 0,
+ .curve_len = 0,
+ };
+
+ /* Create VBO. */
+ GPUVertFormat *format = gpencil_edit_curve_format();
+ cache->edit_curve_vbo = GPU_vertbuf_create_with_format(format);
+
+ /* Count data. */
+ BKE_gpencil_visible_stroke_iter(
+ NULL, ob, NULL, gpencil_edit_curve_stroke_count_cb, &iterdata, false, cfra);
+
+ gpEditCurveIterData iter;
+ int vert_len = iterdata.curve_len;
+ if (vert_len > 0) {
+
+ GPU_vertbuf_data_alloc(cache->edit_curve_vbo, vert_len);
+ iter.verts = (gpEditCurveVert *)GPU_vertbuf_get_data(cache->edit_curve_vbo);
+
+ /* Fill buffers with data. */
+ BKE_gpencil_visible_stroke_iter(
+ NULL, ob, NULL, gpencil_edit_curve_stroke_iter_cb, &iter, false, cfra);
+
+ cache->edit_curve_handles_batch = GPU_batch_create(
+ GPU_PRIM_LINES, cache->edit_curve_vbo, NULL);
+ GPU_batch_vertbuf_add(cache->edit_curve_handles_batch, cache->edit_curve_vbo);
+
+ cache->edit_curve_points_batch = GPU_batch_create(
+ GPU_PRIM_POINTS, cache->edit_curve_vbo, NULL);
+ GPU_batch_vertbuf_add(cache->edit_curve_points_batch, cache->edit_curve_vbo);
+ }
gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
cache->is_dirty = false;
@@ -761,4 +923,22 @@ GPUBatch *DRW_cache_gpencil_edit_points_get(Object *ob, int cfra)
return cache->edit_points_batch;
}
+GPUBatch *DRW_cache_gpencil_edit_curve_handles_get(Object *ob, int cfra)
+{
+ GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
+ gpencil_batches_ensure(ob, cache, cfra);
+ gpencil_edit_batches_ensure(ob, cache, cfra);
+
+ return cache->edit_curve_handles_batch;
+}
+
+GPUBatch *DRW_cache_gpencil_edit_curve_points_get(Object *ob, int cfra)
+{
+ GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
+ gpencil_batches_ensure(ob, cache, cfra);
+ gpencil_edit_batches_ensure(ob, cache, cfra);
+
+ return cache->edit_curve_points_batch;
+}
+
/** \} */