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
