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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to