[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