[Bf-blender-cvs] [1263965] master: GPencil: New interpolate strokes operators

Antonioya noreply at git.blender.org
Wed Sep 7 10:03:13 CEST 2016


Commit: 1263965f83b15e774ab83255030cf25768de5838
Author: Antonioya
Date:   Wed Sep 7 09:54:50 2016 +0200
Branches: master
https://developer.blender.org/rB1263965f83b15e774ab83255030cf25768de5838

GPencil: New interpolate strokes operators

Two new modal operators to create a grease pencil interpolate drawing
for one frame or a complete sequence between two frames.  For drawing
the temporary strokes in the viewport, two drawing handlers have been
added to manage 3D and 2D stuff.

Video: https://youtu.be/qxYwO5sSg5Y

The operator shortcuts are Ctrl+E and Ctrl+Shift+E. During the modal
operator, the interpolation can be adjusted using the mouse (moving
left/right) or the wheel mouse.

===================================================================

M	release/scripts/startup/bl_ui/properties_grease_pencil_common.py
M	source/blender/editors/gpencil/drawgpencil.c
M	source/blender/editors/gpencil/gpencil_edit.c
M	source/blender/editors/gpencil/gpencil_intern.h
M	source/blender/editors/gpencil/gpencil_ops.c
M	source/blender/editors/include/ED_gpencil.h
M	source/blender/makesdna/DNA_gpencil_types.h
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesrna/intern/rna_sculpt_paint.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index e42f726..b1e9f52 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -216,6 +216,15 @@ class GreasePencilStrokeEditPanel:
         col.operator_menu_enum("gpencil.stroke_arrange", text="Arrange Strokes...", property="direction")
         col.operator("gpencil.stroke_change_color", text="Move to Color")
 
+        if is_3d_view:
+            layout.separator()
+            col = layout.column(align=True)
+            col.operator("gpencil.interpolate", text="Interpolate")
+            col.operator("gpencil.interpolate_sequence", text="Sequence")
+            settings = context.tool_settings.gpencil_sculpt
+            col.prop(settings, "interpolate_all_layers")
+            col.prop(settings, "interpolate_selected_only")
+
         layout.separator()
         col = layout.column(align=True)
         col.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 4ef76f5..48786e0 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -66,6 +66,7 @@
 #include "ED_gpencil.h"
 #include "ED_screen.h"
 #include "ED_view3d.h"
+#include "ED_space_api.h"
 
 #include "UI_interface_icons.h"
 #include "UI_resources.h"
@@ -74,7 +75,6 @@
 /* GREASE PENCIL DRAWING */
 
 /* ----- General Defines ------ */
-
 /* flags for sflag */
 typedef enum eDrawStrokeFlags {
 	GP_DRAWDATA_NOSTATUS    = (1 << 0),   /* don't draw status info */
@@ -1338,6 +1338,39 @@ static void gp_draw_onionskins(
 	
 }
 
+/* draw interpolate strokes (used only while operator is running) */
+void ED_gp_draw_interpolation(tGPDinterpolate *tgpi, const int type)
+{
+	tGPDinterpolate_layer *tgpil;
+	float diff_mat[4][4];
+	float color[4];
+
+	int offsx = 0;
+	int offsy = 0;
+	int winx = tgpi->ar->winx;
+	int winy = tgpi->ar->winy;
+
+	UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, color);
+	color[3] = 0.6f;
+	int dflag = 0; 
+	/* if 3d stuff, enable flags */
+	if (type == REGION_DRAW_POST_VIEW) {
+		dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
+	}
+
+	/* turn on alpha-blending */
+	glEnable(GL_BLEND);
+	for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
+		/* calculate parent position */
+		ED_gpencil_parent_location(tgpil->gpl, diff_mat);
+		if (tgpil->interFrame) {
+			gp_draw_strokes(tgpi->gpd, tgpil->interFrame, offsx, offsy, winx, winy, dflag, false,
+				tgpil->gpl->thickness, 1.0f, color, true, true, diff_mat);
+		}
+	}
+	glDisable(GL_BLEND);
+}
+
 /* loop over gpencil data layers, drawing them */
 static void gp_draw_data_layers(
         bGPDbrush *brush, float alpha, bGPdata *gpd,
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 9f700e8..c3b318a 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -18,7 +18,7 @@
  * The Original Code is Copyright (C) 2008, Blender Foundation, Joshua Leung
  * This is a new part of Blender
  *
- * Contributor(s): Joshua Leung
+ * Contributor(s): Joshua Leung, Antonio Vazquez
  *
  * ***** END GPL LICENSE BLOCK *****
  *
@@ -74,6 +74,8 @@
 #include "ED_object.h"
 #include "ED_screen.h"
 #include "ED_view3d.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
 
 #include "gpencil_intern.h"
 
@@ -1968,4 +1970,661 @@ void GPENCIL_OT_reproject(wmOperatorType *ot)
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
-/* ************************************************ */
+/* =========  Interpolation operators ========================== */
+/* Helper: Update point with interpolation */
+static void gp_interpolate_update_points(bGPDstroke *gps_from, bGPDstroke *gps_to, bGPDstroke *new_stroke, float factor)
+{
+	bGPDspoint *prev, *pt, *next;
+
+	/* update points */
+	for (int i = 0; i < new_stroke->totpoints; i++) {
+		prev = &gps_from->points[i];
+		pt = &new_stroke->points[i];
+		next = &gps_to->points[i];
+
+		/* Interpolate all values */
+		interp_v3_v3v3(&pt->x, &prev->x, &next->x, factor);
+		pt->pressure = interpf(prev->pressure, next->pressure, factor);
+		pt->strength = interpf(prev->strength, next->strength, factor);
+		CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+	}
+}
+
+/* Helper: Update all strokes interpolated */
+static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi)
+{
+	tGPDinterpolate_layer *tgpil;
+	bGPDstroke *new_stroke, *gps_from, *gps_to;
+	int cStroke;
+	float factor;
+	float shift = tgpi->shift;
+
+	for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
+		factor = tgpil->factor + shift;
+		for (new_stroke = tgpil->interFrame->strokes.first; new_stroke; new_stroke = new_stroke->next) {
+			if (new_stroke->totpoints == 0) {
+				continue;
+			}
+			/* get strokes to interpolate */
+			cStroke = BLI_findindex(&tgpil->interFrame->strokes, new_stroke);
+			gps_from = BLI_findlink(&tgpil->prevFrame->strokes, cStroke);
+			gps_to = BLI_findlink(&tgpil->nextFrame->strokes, cStroke);
+			/* update points position */
+			if ((gps_from) && (gps_to)) {
+				gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
+			}
+		}
+	}
+
+	WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+}
+
+/* Helper: Verify valid strokes for interpolation */
+static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd)
+{
+	ToolSettings *ts = CTX_data_tool_settings(C);
+	int flag = ts->gp_sculpt.flag;
+
+	bGPDlayer *gpl;
+	bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
+	bGPDstroke *gps_from, *gps_to;
+	int fFrame;
+
+	/* get layers */
+	for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+		/* all layers or only active */
+		if (((flag & GP_BRUSHEDIT_FLAG_INTERPOLATE_ALL_LAYERS) == 0) && (gpl != active_gpl)) {
+			continue;
+		}
+		/* only editable and visible layers are considered */
+		if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
+			continue;
+		}
+		/* read strokes */
+		for (gps_from = gpl->actframe->strokes.first; gps_from; gps_from = gps_from->next) {
+			/* only selected */
+			if ((flag & GP_BRUSHEDIT_FLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
+				continue;
+			}
+			/* skip strokes that are invalid for current view */
+			if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
+				continue;
+			}
+			/* check if the color is editable */
+			if (ED_gpencil_stroke_color_use(gpl, gps_from) == false) {
+				continue;
+			}
+			/* get final stroke to interpolate */
+			fFrame = BLI_findindex(&gpl->actframe->strokes, gps_from);
+			gps_to = BLI_findlink(&gpl->actframe->next->strokes, fFrame);
+			if (gps_to == NULL) {
+				continue;
+			}
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/* Helper: Create internal strokes interpolated */
+static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
+{
+	bGPDlayer *gpl;
+	bGPdata *gpd = tgpi->gpd;
+	tGPDinterpolate_layer *tgpil;
+	bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
+	bGPDstroke *gps_from, *gps_to, *new_stroke;
+	int fFrame;
+
+	/* set layers */
+	for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+		/* all layers or only active */
+		if (((tgpi->flag & GP_BRUSHEDIT_FLAG_INTERPOLATE_ALL_LAYERS) == 0) && (gpl != active_gpl)) {
+			continue;
+		}
+		/* only editable and visible layers are considered */
+		if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
+			continue;
+		}
+		/* create temp data for each layer */
+		tgpil = NULL;
+		tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer");
+
+		tgpil->gpl = gpl;
+		tgpil->prevFrame = gpl->actframe;
+		tgpil->nextFrame = gpl->actframe->next;
+
+		BLI_addtail(&tgpi->ilayers, tgpil);
+		/* create a new temporary frame */
+		tgpil->interFrame = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
+		tgpil->interFrame->framenum = tgpi->cframe;
+
+		/* get interpolation factor */
+		tgpil->factor = (float)(tgpi->cframe - tgpil->prevFrame->framenum) / (tgpil->nextFrame->framenum - tgpil->prevFrame->framenum + 1);
+		/* create new strokes data with interpolated points reading original stroke */
+		for (gps_from = tgpil->prevFrame->strokes.first; gps_from; gps_from = gps_from->next) {
+			bool valid = true;
+			/* only selected */
+			if ((tgpi->flag & GP_BRUSHEDIT_FLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
+				valid = false;
+			}
+
+			/* skip strokes that are invalid for current view */
+			if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
+				valid = false;
+			}
+			/* check if the color is editable */
+			if (ED_gpencil_stroke_color_use(tgpil->gpl, gps_from) == false) {
+				valid = false;
+			}
+			/* get final stroke to interpolate */
+			fFrame = BLI_findindex(&tgpil->prevFrame->strokes, gps_from);
+			gps_to = BLI_findlink(&tgpil->nextFrame->strokes, fFrame);
+			if (gps_to == NULL) {
+				valid = false;
+			}
+			/* create new stroke */
+			new_stroke = MEM_dupallocN(gps_from);
+			new_stroke->points = MEM_dupallocN(gps_from->points);
+			new_stroke->triangles = MEM_dupallocN(gps_from->triangles);
+			if (valid) {
+				/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
+				if (gps_from->totpoints > gps_to->totpoints) {
+					new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints);
+					new_stroke->totpoints = gps_to->totpoints;
+					new_stroke->tot_triangles = 0;
+					new_stroke->flag |= GP_STROKE_RECALC_CACHES;
+				}
+				/* update points position */
+				gp_interpolate_update_points(gps_from, gps_to, new_stroke, tgpil->factor);
+			}
+			else {
+				/* need an empty stroke to keep index correct for lookup, but resize to smallest size */
+				new_stroke->totpoints = 0;
+				new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points));
+				new_stroke->tot_triangles = 0;
+				new_stroke->triangles = MEM_recallocN(new_stroke->triangles, sizeof(*new_stroke->triangles));
+			}
+			/

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list