GP: Rename GP_STROKE_RECALC_CACHE to GP_STROKE_RECALC_GEOMETRY
[blender.git] / source / blender / editors / gpencil / gpencil_interpolate.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2016, Blender Foundation
19  * This is a new part of Blender
20  *
21  * Contributor(s): Antonio Vazquez, Joshua Leung
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  *
25  * Operators for interpolating new Grease Pencil frames from existing strokes
26  */
27
28 /** \file blender/editors/gpencil/gpencil_interpolate.c
29  *  \ingroup edgpencil
30  */
31
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <stddef.h>
37 #include <math.h>
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BLI_blenlib.h"
42 #include "BLI_utildefines.h"
43 #include "BLI_easing.h"
44 #include "BLI_math.h"
45
46 #include "BLT_translation.h"
47
48 #include "DNA_color_types.h"
49 #include "DNA_gpencil_types.h"
50 #include "DNA_meshdata_types.h"
51 #include "DNA_object_types.h"
52 #include "DNA_scene_types.h"
53 #include "DNA_screen_types.h"
54 #include "DNA_space_types.h"
55 #include "DNA_view3d_types.h"
56
57 #include "BKE_colortools.h"
58 #include "BKE_context.h"
59 #include "BKE_deform.h"
60 #include "BKE_global.h"
61 #include "BKE_gpencil.h"
62 #include "BKE_report.h"
63 #include "BKE_screen.h"
64
65 #include "UI_interface.h"
66 #include "UI_resources.h"
67
68 #include "WM_api.h"
69 #include "WM_types.h"
70
71 #include "RNA_access.h"
72 #include "RNA_define.h"
73 #include "RNA_enum_types.h"
74
75 #include "UI_view2d.h"
76
77 #include "ED_gpencil.h"
78 #include "ED_object.h"
79 #include "ED_screen.h"
80 #include "ED_view3d.h"
81 #include "ED_space_api.h"
82
83 #include "DEG_depsgraph.h"
84 #include "DEG_depsgraph_query.h"
85
86 #include "gpencil_intern.h"
87
88 /* ************************************************ */
89 /* Core/Shared Utilities */
90
91 /* Poll callback for interpolation operators */
92 static bool gpencil_view3d_poll(bContext *C)
93 {
94         bGPdata *gpd = CTX_data_gpencil_data(C);
95         bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
96
97         /* only 3D view */
98         ScrArea *sa = CTX_wm_area(C);
99         if (sa && sa->spacetype != SPACE_VIEW3D) {
100                 return 0;
101         }
102
103         /* need data to interpolate */
104         if (ELEM(NULL, gpd, gpl)) {
105                 return 0;
106         }
107
108         return 1;
109 }
110
111 /* Perform interpolation */
112 static void gp_interpolate_update_points(
113         const bGPDstroke *gps_from, const bGPDstroke *gps_to, bGPDstroke *new_stroke, float factor)
114 {
115         /* update points */
116         for (int i = 0; i < new_stroke->totpoints; i++) {
117                 const bGPDspoint *prev = &gps_from->points[i];
118                 const bGPDspoint *next = &gps_to->points[i];
119                 bGPDspoint *pt = &new_stroke->points[i];
120
121                 /* Interpolate all values */
122                 interp_v3_v3v3(&pt->x, &prev->x, &next->x, factor);
123                 pt->pressure = interpf(prev->pressure, next->pressure, 1.0f - factor);
124                 pt->strength = interpf(prev->strength, next->strength, 1.0f - factor);
125                 CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
126
127                 /* GPXX interpolate dverts */
128 #if 0
129                 MDeformVert *dvert = &new_stroke->dvert[i];
130                 dvert->totweight = 0;
131                 dvert->dw = NULL;
132 #endif
133         }
134 }
135
136 /* ****************** Interpolate Interactive *********************** */
137
138 /* Helper: Update all strokes interpolated */
139 static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi)
140 {
141         bGPdata *gpd = tgpi->gpd;
142         tGPDinterpolate_layer *tgpil;
143         const float shift = tgpi->shift;
144
145         for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
146                 bGPDstroke *new_stroke;
147                 const float factor = tgpil->factor + shift;
148
149                 for (new_stroke = tgpil->interFrame->strokes.first; new_stroke; new_stroke = new_stroke->next) {
150                         bGPDstroke *gps_from, *gps_to;
151                         int stroke_idx;
152
153                         if (new_stroke->totpoints == 0) {
154                                 continue;
155                         }
156
157                         /* get strokes to interpolate */
158                         stroke_idx = BLI_findindex(&tgpil->interFrame->strokes, new_stroke);
159
160                         gps_from = BLI_findlink(&tgpil->prevFrame->strokes, stroke_idx);
161                         gps_to = BLI_findlink(&tgpil->nextFrame->strokes, stroke_idx);
162
163                         /* update points position */
164                         if ((gps_from) && (gps_to)) {
165                                 gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
166                         }
167                 }
168         }
169
170         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
171         WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
172 }
173
174 /* Helper: Verify valid strokes for interpolation */
175 static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd)
176 {
177         Object *ob = CTX_data_active_object(C);
178         ToolSettings *ts = CTX_data_tool_settings(C);
179         eGP_Interpolate_SettingsFlag flag = ts->gp_interpolate.flag;
180
181         /* get layers */
182         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
183                 /* all layers or only active */
184                 if (!(flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) && !(gpl->flag & GP_LAYER_ACTIVE)) {
185                         continue;
186                 }
187                 /* only editable and visible layers are considered */
188                 if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
189                         continue;
190                 }
191
192                 /* read strokes */
193                 for (bGPDstroke *gps_from = gpl->actframe->strokes.first; gps_from; gps_from = gps_from->next) {
194                         bGPDstroke *gps_to;
195                         int fFrame;
196
197                         /* only selected */
198                         if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
199                                 continue;
200                         }
201                         /* skip strokes that are invalid for current view */
202                         if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
203                                 continue;
204                         }
205                         /* check if the color is editable */
206                         if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) {
207                                 continue;
208                         }
209
210                         /* get final stroke to interpolate */
211                         fFrame = BLI_findindex(&gpl->actframe->strokes, gps_from);
212                         gps_to = BLI_findlink(&gpl->actframe->next->strokes, fFrame);
213                         if (gps_to == NULL) {
214                                 continue;
215                         }
216
217                         return true;
218                 }
219         }
220         return false;
221 }
222
223 /* Helper: Create internal strokes interpolated */
224 static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
225 {
226         bGPdata *gpd = tgpi->gpd;
227         bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
228         bGPDframe *actframe = active_gpl->actframe;
229         Object *ob = CTX_data_active_object(C);
230
231         /* save initial factor for active layer to define shift limits */
232         tgpi->init_factor = (float)(tgpi->cframe - actframe->framenum) / (actframe->next->framenum - actframe->framenum + 1);
233
234         /* limits are 100% below 0 and 100% over the 100% */
235         tgpi->low_limit = -1.0f - tgpi->init_factor;
236         tgpi->high_limit = 2.0f - tgpi->init_factor;
237
238         /* set layers */
239         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
240                 tGPDinterpolate_layer *tgpil;
241
242                 /* all layers or only active */
243                 if (!(tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) && (gpl != active_gpl)) {
244                         continue;
245                 }
246                 /* only editable and visible layers are considered */
247                 if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
248                         continue;
249                 }
250
251                 /* create temp data for each layer */
252                 tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer");
253
254                 tgpil->gpl = gpl;
255                 tgpil->prevFrame = gpl->actframe;
256                 tgpil->nextFrame = gpl->actframe->next;
257
258                 BLI_addtail(&tgpi->ilayers, tgpil);
259
260                 /* create a new temporary frame */
261                 tgpil->interFrame = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
262                 tgpil->interFrame->framenum = tgpi->cframe;
263
264                 /* get interpolation factor by layer (usually must be equal for all layers, but not sure) */
265                 tgpil->factor = (float)(tgpi->cframe - tgpil->prevFrame->framenum) / (tgpil->nextFrame->framenum - tgpil->prevFrame->framenum + 1);
266
267                 /* create new strokes data with interpolated points reading original stroke */
268                 for (bGPDstroke *gps_from = tgpil->prevFrame->strokes.first; gps_from; gps_from = gps_from->next) {
269                         bGPDstroke *gps_to;
270                         int fFrame;
271
272                         bGPDstroke *new_stroke = NULL;
273                         bool valid = true;
274
275
276                         /* only selected */
277                         if ((tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
278                                 valid = false;
279                         }
280                         /* skip strokes that are invalid for current view */
281                         if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
282                                 valid = false;
283                         }
284
285                         /* check if the color is editable */
286                         if (ED_gpencil_stroke_color_use(ob, tgpil->gpl, gps_from) == false) {
287                                 valid = false;
288                         }
289
290                         /* get final stroke to interpolate */
291                         fFrame = BLI_findindex(&tgpil->prevFrame->strokes, gps_from);
292                         gps_to = BLI_findlink(&tgpil->nextFrame->strokes, fFrame);
293                         if (gps_to == NULL) {
294                                 valid = false;
295                         }
296
297                         /* create new stroke */
298                         new_stroke = BKE_gpencil_stroke_duplicate(gps_from);
299
300                         if (valid) {
301                                 /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
302                                 if (gps_from->totpoints > gps_to->totpoints) {
303                                         new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints);
304                                         if (new_stroke->dvert != NULL) {
305                                                 new_stroke->dvert = MEM_recallocN(new_stroke->dvert, sizeof(*new_stroke->dvert) * gps_to->totpoints);
306                                         }
307                                         new_stroke->totpoints = gps_to->totpoints;
308                                         new_stroke->tot_triangles = 0;
309                                         new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
310                                 }
311                                 /* update points position */
312                                 gp_interpolate_update_points(gps_from, gps_to, new_stroke, tgpil->factor);
313                         }
314                         else {
315                                 /* need an empty stroke to keep index correct for lookup, but resize to smallest size */
316                                 new_stroke->totpoints = 0;
317                                 new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points));
318                                 if (new_stroke->dvert != NULL) {
319                                         new_stroke->dvert = MEM_recallocN(new_stroke->dvert, sizeof(*new_stroke->dvert));
320                                 }
321                                 new_stroke->tot_triangles = 0;
322                                 new_stroke->triangles = MEM_recallocN(new_stroke->triangles, sizeof(*new_stroke->triangles));
323                                 new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
324                         }
325
326                         /* add to strokes */
327                         BLI_addtail(&tgpil->interFrame->strokes, new_stroke);
328                 }
329         }
330 }
331
332 /* ----------------------- */
333 /* Drawing Callbacks */
334
335 /* Drawing callback for modal operator in screen mode */
336 static void gpencil_interpolate_draw_screen(const struct bContext *C, ARegion *UNUSED(ar), void *arg)
337 {
338         tGPDinterpolate *tgpi = (tGPDinterpolate *)arg;
339         ED_gp_draw_interpolation(C, tgpi, REGION_DRAW_POST_PIXEL);
340 }
341
342 /* Drawing callback for modal operator in 3d mode */
343 static void gpencil_interpolate_draw_3d(const bContext *C, ARegion *UNUSED(ar), void *arg)
344 {
345         tGPDinterpolate *tgpi = (tGPDinterpolate *)arg;
346         ED_gp_draw_interpolation(C, tgpi, REGION_DRAW_POST_VIEW);
347 }
348
349 /* ----------------------- */
350
351 /* Helper: calculate shift based on position of mouse (we only use x-axis for now.
352  * since this is more convenient for users to do), and store new shift value
353  */
354 static void gpencil_mouse_update_shift(tGPDinterpolate *tgpi, wmOperator *op, const wmEvent *event)
355 {
356         float mid = (float)(tgpi->ar->winx - tgpi->ar->winrct.xmin) / 2.0f;
357         float mpos = event->x - tgpi->ar->winrct.xmin;
358
359         if (mpos >= mid) {
360                 tgpi->shift = ((mpos - mid) * tgpi->high_limit) / mid;
361         }
362         else {
363                 tgpi->shift = tgpi->low_limit - ((mpos * tgpi->low_limit) / mid);
364         }
365
366         CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
367         RNA_float_set(op->ptr, "shift", tgpi->shift);
368 }
369
370 /* Helper: Draw status message while the user is running the operator */
371 static void gpencil_interpolate_status_indicators(bContext *C, tGPDinterpolate *p)
372 {
373         Scene *scene = p->scene;
374         char status_str[UI_MAX_DRAW_STR];
375         char msg_str[UI_MAX_DRAW_STR];
376
377         BLI_strncpy(msg_str, IFACE_("GPencil Interpolation: "), UI_MAX_DRAW_STR);
378
379         if (hasNumInput(&p->num)) {
380                 char str_offs[NUM_STR_REP_LEN];
381
382                 outputNumInput(&p->num, str_offs, &scene->unit);
383                 BLI_snprintf(status_str, sizeof(status_str), "%s%s", msg_str, str_offs);
384         }
385         else {
386                 BLI_snprintf(status_str, sizeof(status_str), "%s%d %%", msg_str, (int)((p->init_factor + p->shift)  * 100.0f));
387         }
388
389         ED_area_status_text(p->sa, status_str);
390         ED_workspace_status_text(C, IFACE_("ESC/RMB to cancel, Enter/LMB to confirm, WHEEL/MOVE to adjust factor"));
391 }
392
393 /* Update screen and stroke */
394 static void gpencil_interpolate_update(bContext *C, wmOperator *op, tGPDinterpolate *tgpi)
395 {
396         /* update shift indicator in header */
397         gpencil_interpolate_status_indicators(C, tgpi);
398         /* apply... */
399         tgpi->shift = RNA_float_get(op->ptr, "shift");
400         /* update points position */
401         gp_interpolate_update_strokes(C, tgpi);
402 }
403
404 /* ----------------------- */
405
406 /* Exit and free memory */
407 static void gpencil_interpolate_exit(bContext *C, wmOperator *op)
408 {
409         tGPDinterpolate *tgpi = op->customdata;
410         tGPDinterpolate_layer *tgpil;
411         bGPdata *gpd = tgpi->gpd;
412
413         /* don't assume that operator data exists at all */
414         if (tgpi) {
415                 /* remove drawing handler */
416                 if (tgpi->draw_handle_screen) {
417                         ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_screen);
418                 }
419                 if (tgpi->draw_handle_3d) {
420                         ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_3d);
421                 }
422
423                 /* clear status message area */
424                 ED_area_status_text(tgpi->sa, NULL);
425                 ED_workspace_status_text(C, NULL);
426
427                 /* finally, free memory used by temp data */
428                 for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
429                         BKE_gpencil_free_strokes(tgpil->interFrame);
430                         MEM_freeN(tgpil->interFrame);
431                 }
432
433                 BLI_freelistN(&tgpi->ilayers);
434                 MEM_freeN(tgpi);
435         }
436         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
437         WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
438
439         /* clear pointer */
440         op->customdata = NULL;
441 }
442
443 /* Init new temporary interpolation data */
444 static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinterpolate *tgpi)
445 {
446         ToolSettings *ts = CTX_data_tool_settings(C);
447         bGPdata *gpd = CTX_data_gpencil_data(C);
448
449         /* set current scene and window */
450         tgpi->scene = CTX_data_scene(C);
451         tgpi->sa = CTX_wm_area(C);
452         tgpi->ar = CTX_wm_region(C);
453         tgpi->flag = ts->gp_interpolate.flag;
454
455         /* set current frame number */
456         tgpi->cframe = tgpi->scene->r.cfra;
457
458         /* set GP datablock */
459         tgpi->gpd = gpd;
460
461         /* set interpolation weight */
462         tgpi->shift = RNA_float_get(op->ptr, "shift");
463         /* set layers */
464         gp_interpolate_set_points(C, tgpi);
465
466         return 1;
467 }
468
469 /* Allocate memory and initialize values */
470 static tGPDinterpolate *gp_session_init_interpolation(bContext *C, wmOperator *op)
471 {
472         tGPDinterpolate *tgpi = MEM_callocN(sizeof(tGPDinterpolate), "GPencil Interpolate Data");
473
474         /* define initial values */
475         gp_interpolate_set_init_values(C, op, tgpi);
476
477         /* return context data for running operator */
478         return tgpi;
479 }
480
481 /* Init interpolation: Allocate memory and set init values */
482 static int gpencil_interpolate_init(bContext *C, wmOperator *op)
483 {
484         tGPDinterpolate *tgpi;
485
486         /* check context */
487         tgpi = op->customdata = gp_session_init_interpolation(C, op);
488         if (tgpi == NULL) {
489                 /* something wasn't set correctly in context */
490                 gpencil_interpolate_exit(C, op);
491                 return 0;
492         }
493
494         /* everything is now setup ok */
495         return 1;
496 }
497
498 /* ----------------------- */
499
500 /* Invoke handler: Initialize the operator */
501 static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
502 {
503         wmWindow *win = CTX_wm_window(C);
504         bGPdata *gpd = CTX_data_gpencil_data(C);
505         bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
506         Depsgraph *depsgraph = CTX_data_depsgraph(C);
507         int cfra_eval = (int)DEG_get_ctime(depsgraph);
508         bGPDframe *actframe = gpl->actframe;
509         tGPDinterpolate *tgpi = NULL;
510
511         /* cannot interpolate if not between 2 frames */
512         if (ELEM(NULL, actframe, actframe->next)) {
513                 BKE_report(op->reports, RPT_ERROR, "Cannot find a pair of grease pencil frames to interpolate between in active layer");
514                 return OPERATOR_CANCELLED;
515         }
516
517         /* cannot interpolate in extremes */
518         if (ELEM(cfra_eval, actframe->framenum, actframe->next->framenum)) {
519                 BKE_report(op->reports, RPT_ERROR, "Cannot interpolate as current frame already has existing grease pencil frames");
520                 return OPERATOR_CANCELLED;
521         }
522
523         /* need editable strokes */
524         if (!gp_interpolate_check_todo(C, gpd)) {
525                 BKE_report(op->reports, RPT_ERROR, "Interpolation requires some editable strokes");
526                 return OPERATOR_CANCELLED;
527         }
528
529         /* try to initialize context data needed */
530         if (!gpencil_interpolate_init(C, op)) {
531                 if (op->customdata)
532                         MEM_freeN(op->customdata);
533                 return OPERATOR_CANCELLED;
534         }
535         else {
536                 tgpi = op->customdata;
537         }
538
539         /* Enable custom drawing handlers
540          * It needs 2 handlers because strokes can in 3d space and screen space
541          * and each handler use different coord system
542          */
543         tgpi->draw_handle_screen = ED_region_draw_cb_activate(tgpi->ar->type, gpencil_interpolate_draw_screen, tgpi, REGION_DRAW_POST_PIXEL);
544         tgpi->draw_handle_3d = ED_region_draw_cb_activate(tgpi->ar->type, gpencil_interpolate_draw_3d, tgpi, REGION_DRAW_POST_VIEW);
545
546         /* set cursor to indicate modal */
547         WM_cursor_modal_set(win, BC_EW_SCROLLCURSOR);
548
549         /* update shift indicator in header */
550         gpencil_interpolate_status_indicators(C, tgpi);
551         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
552         WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
553
554         /* add a modal handler for this operator */
555         WM_event_add_modal_handler(C, op);
556
557         return OPERATOR_RUNNING_MODAL;
558 }
559
560 /* Modal handler: Events handling during interactive part */
561 static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent *event)
562 {
563         tGPDinterpolate *tgpi = op->customdata;
564         wmWindow *win = CTX_wm_window(C);
565         bGPDframe *gpf_dst;
566         bGPDstroke *gps_src, *gps_dst;
567         tGPDinterpolate_layer *tgpil;
568         const bool has_numinput = hasNumInput(&tgpi->num);
569
570         switch (event->type) {
571                 case LEFTMOUSE: /* confirm */
572                 case RETKEY:
573                 {
574                         /* return to normal cursor and header status */
575                         ED_area_status_text(tgpi->sa, NULL);
576                         ED_workspace_status_text(C, NULL);
577                         WM_cursor_modal_restore(win);
578
579                         /* insert keyframes as required... */
580                         for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
581                                 gpf_dst = BKE_gpencil_layer_getframe(tgpil->gpl, tgpi->cframe, GP_GETFRAME_ADD_NEW);
582                                 gpf_dst->key_type = BEZT_KEYTYPE_BREAKDOWN;
583
584                                 /* copy strokes */
585                                 BLI_listbase_clear(&gpf_dst->strokes);
586                                 for (gps_src = tgpil->interFrame->strokes.first; gps_src; gps_src = gps_src->next) {
587                                         if (gps_src->totpoints == 0) {
588                                                 continue;
589                                         }
590
591                                         /* make copy of source stroke, then adjust pointer to points too */
592                                         gps_dst = MEM_dupallocN(gps_src);
593                                         gps_dst->points = MEM_dupallocN(gps_src->points);
594                                         if (gps_src->dvert != NULL) {
595                                                 gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
596                                                 BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
597                                         }
598                                         gps_dst->triangles = MEM_dupallocN(gps_src->triangles);
599                                         gps_dst->flag |= GP_STROKE_RECALC_GEOMETRY;
600                                         BLI_addtail(&gpf_dst->strokes, gps_dst);
601                                 }
602                         }
603
604                         /* clean up temp data */
605                         gpencil_interpolate_exit(C, op);
606
607                         /* done! */
608                         return OPERATOR_FINISHED;
609                 }
610
611                 case ESCKEY:    /* cancel */
612                 case RIGHTMOUSE:
613                 {
614                         /* return to normal cursor and header status */
615                         ED_area_status_text(tgpi->sa, NULL);
616                         ED_workspace_status_text(C, NULL);
617                         WM_cursor_modal_restore(win);
618
619                         /* clean up temp data */
620                         gpencil_interpolate_exit(C, op);
621
622                         /* canceled! */
623                         return OPERATOR_CANCELLED;
624                 }
625
626                 case WHEELUPMOUSE:
627                 {
628                         tgpi->shift = tgpi->shift + 0.01f;
629                         CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
630                         RNA_float_set(op->ptr, "shift", tgpi->shift);
631
632                         /* update screen */
633                         gpencil_interpolate_update(C, op, tgpi);
634                         break;
635                 }
636                 case WHEELDOWNMOUSE:
637                 {
638                         tgpi->shift = tgpi->shift - 0.01f;
639                         CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
640                         RNA_float_set(op->ptr, "shift", tgpi->shift);
641
642                         /* update screen */
643                         gpencil_interpolate_update(C, op, tgpi);
644                         break;
645                 }
646                 case MOUSEMOVE: /* calculate new position */
647                 {
648                         /* only handle mousemove if not doing numinput */
649                         if (has_numinput == false) {
650                                 /* update shift based on position of mouse */
651                                 gpencil_mouse_update_shift(tgpi, op, event);
652
653                                 /* update screen */
654                                 gpencil_interpolate_update(C, op, tgpi);
655                         }
656                         break;
657                 }
658                 default:
659                 {
660                         if ((event->val == KM_PRESS) && handleNumInput(C, &tgpi->num, event)) {
661                                 const float factor = tgpi->init_factor;
662                                 float value;
663
664                                 /* Grab shift from numeric input, and store this new value (the user see an int) */
665                                 value = (factor + tgpi->shift) * 100.0f;
666                                 applyNumInput(&tgpi->num, &value);
667                                 tgpi->shift = value / 100.0f;
668
669                                 /* recalculate the shift to get the right value in the frame scale */
670                                 tgpi->shift = tgpi->shift - factor;
671
672                                 CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
673                                 RNA_float_set(op->ptr, "shift", tgpi->shift);
674
675                                 /* update screen */
676                                 gpencil_interpolate_update(C, op, tgpi);
677
678                                 break;
679                         }
680                         else {
681                                 /* unhandled event - allow to pass through */
682                                 return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
683                         }
684                 }
685         }
686
687         /* still running... */
688         return OPERATOR_RUNNING_MODAL;
689 }
690
691 /* Cancel handler */
692 static void gpencil_interpolate_cancel(bContext *C, wmOperator *op)
693 {
694         /* this is just a wrapper around exit() */
695         gpencil_interpolate_exit(C, op);
696 }
697
698 void GPENCIL_OT_interpolate(wmOperatorType *ot)
699 {
700         /* identifiers */
701         ot->name = "Grease Pencil Interpolation";
702         ot->idname = "GPENCIL_OT_interpolate";
703         ot->description = "Interpolate grease pencil strokes between frames";
704
705         /* callbacks */
706         ot->invoke = gpencil_interpolate_invoke;
707         ot->modal = gpencil_interpolate_modal;
708         ot->cancel = gpencil_interpolate_cancel;
709         ot->poll = gpencil_view3d_poll;
710
711         /* flags */
712         ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
713
714         /* properties */
715         RNA_def_float_percentage(ot->srna, "shift", 0.0f, -1.0f, 1.0f, "Shift", "Bias factor for which frame has more influence on the interpolated strokes", -0.9f, 0.9f);
716 }
717
718 /* ****************** Interpolate Sequence *********************** */
719
720 /* Helper: Perform easing equation calculations for GP interpolation operator */
721 static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_settings, float time)
722 {
723         const float begin  = 0.0f;
724         const float change = 1.0f;
725         const float duration = 1.0f;
726
727         const float back = ipo_settings->back;
728         const float amplitude = ipo_settings->amplitude;
729         const float period = ipo_settings->period;
730
731         eBezTriple_Easing easing = ipo_settings->easing;
732         float result = time;
733
734         switch (ipo_settings->type) {
735                 case GP_IPO_BACK:
736                         switch (easing) {
737                                 case BEZT_IPO_EASE_IN:
738                                         result = BLI_easing_back_ease_in(time, begin, change, duration, back);
739                                         break;
740                                 case BEZT_IPO_EASE_OUT:
741                                         result = BLI_easing_back_ease_out(time, begin, change, duration, back);
742                                         break;
743                                 case BEZT_IPO_EASE_IN_OUT:
744                                         result = BLI_easing_back_ease_in_out(time, begin, change, duration, back);
745                                         break;
746
747                                 default: /* default/auto: same as ease out */
748                                         result = BLI_easing_back_ease_out(time, begin, change, duration, back);
749                                         break;
750                         }
751                         break;
752
753                 case GP_IPO_BOUNCE:
754                         switch (easing) {
755                                 case BEZT_IPO_EASE_IN:
756                                         result = BLI_easing_bounce_ease_in(time, begin, change, duration);
757                                         break;
758                                 case BEZT_IPO_EASE_OUT:
759                                         result = BLI_easing_bounce_ease_out(time, begin, change, duration);
760                                         break;
761                                 case BEZT_IPO_EASE_IN_OUT:
762                                         result = BLI_easing_bounce_ease_in_out(time, begin, change, duration);
763                                         break;
764
765                                 default: /* default/auto: same as ease out */
766                                         result = BLI_easing_bounce_ease_out(time, begin, change, duration);
767                                         break;
768                         }
769                         break;
770
771                 case GP_IPO_CIRC:
772                         switch (easing) {
773                                 case BEZT_IPO_EASE_IN:
774                                         result = BLI_easing_circ_ease_in(time, begin, change, duration);
775                                         break;
776                                 case BEZT_IPO_EASE_OUT:
777                                         result = BLI_easing_circ_ease_out(time, begin, change, duration);
778                                         break;
779                                 case BEZT_IPO_EASE_IN_OUT:
780                                         result = BLI_easing_circ_ease_in_out(time, begin, change, duration);
781                                         break;
782
783                                 default: /* default/auto: same as ease in */
784                                         result = BLI_easing_circ_ease_in(time, begin, change, duration);
785                                         break;
786                         }
787                         break;
788
789                 case GP_IPO_CUBIC:
790                         switch (easing) {
791                                 case BEZT_IPO_EASE_IN:
792                                         result = BLI_easing_cubic_ease_in(time, begin, change, duration);
793                                         break;
794                                 case BEZT_IPO_EASE_OUT:
795                                         result = BLI_easing_cubic_ease_out(time, begin, change, duration);
796                                         break;
797                                 case BEZT_IPO_EASE_IN_OUT:
798                                         result = BLI_easing_cubic_ease_in_out(time, begin, change, duration);
799                                         break;
800
801                                 default: /* default/auto: same as ease in */
802                                         result = BLI_easing_cubic_ease_in(time, begin, change, duration);
803                                         break;
804                         }
805                         break;
806
807                 case GP_IPO_ELASTIC:
808                         switch (easing) {
809                                 case BEZT_IPO_EASE_IN:
810                                         result = BLI_easing_elastic_ease_in(time, begin, change, duration, amplitude, period);
811                                         break;
812                                 case BEZT_IPO_EASE_OUT:
813                                         result = BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period);
814                                         break;
815                                 case BEZT_IPO_EASE_IN_OUT:
816                                         result = BLI_easing_elastic_ease_in_out(time, begin, change, duration, amplitude, period);
817                                         break;
818
819                                 default: /* default/auto: same as ease out */
820                                         result = BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period);
821                                         break;
822                         }
823                         break;
824
825                 case GP_IPO_EXPO:
826                         switch (easing) {
827                                 case BEZT_IPO_EASE_IN:
828                                         result = BLI_easing_expo_ease_in(time, begin, change, duration);
829                                         break;
830                                 case BEZT_IPO_EASE_OUT:
831                                         result = BLI_easing_expo_ease_out(time, begin, change, duration);
832                                         break;
833                                 case BEZT_IPO_EASE_IN_OUT:
834                                         result = BLI_easing_expo_ease_in_out(time, begin, change, duration);
835                                         break;
836
837                                 default: /* default/auto: same as ease in */
838                                         result = BLI_easing_expo_ease_in(time, begin, change, duration);
839                                         break;
840                         }
841                         break;
842
843                 case GP_IPO_QUAD:
844                         switch (easing) {
845                                 case BEZT_IPO_EASE_IN:
846                                         result = BLI_easing_quad_ease_in(time, begin, change, duration);
847                                         break;
848                                 case BEZT_IPO_EASE_OUT:
849                                         result = BLI_easing_quad_ease_out(time, begin, change, duration);
850                                         break;
851                                 case BEZT_IPO_EASE_IN_OUT:
852                                         result = BLI_easing_quad_ease_in_out(time, begin, change, duration);
853                                         break;
854
855                                 default: /* default/auto: same as ease in */
856                                         result = BLI_easing_quad_ease_in(time, begin, change, duration);
857                                         break;
858                         }
859                         break;
860
861                 case GP_IPO_QUART:
862                         switch (easing) {
863                                 case BEZT_IPO_EASE_IN:
864                                         result = BLI_easing_quart_ease_in(time, begin, change, duration);
865                                         break;
866                                 case BEZT_IPO_EASE_OUT:
867                                         result = BLI_easing_quart_ease_out(time, begin, change, duration);
868                                         break;
869                                 case BEZT_IPO_EASE_IN_OUT:
870                                         result = BLI_easing_quart_ease_in_out(time, begin, change, duration);
871                                         break;
872
873                                 default: /* default/auto: same as ease in */
874                                         result = BLI_easing_quart_ease_in(time, begin, change, duration);
875                                         break;
876                         }
877                         break;
878
879                 case GP_IPO_QUINT:
880                         switch (easing) {
881                                 case BEZT_IPO_EASE_IN:
882                                         result = BLI_easing_quint_ease_in(time, begin, change, duration);
883                                         break;
884                                 case BEZT_IPO_EASE_OUT:
885                                         result = BLI_easing_quint_ease_out(time, begin, change, duration);
886                                         break;
887                                 case BEZT_IPO_EASE_IN_OUT:
888                                         result = BLI_easing_quint_ease_in_out(time, begin, change, duration);
889                                         break;
890
891                                 default: /* default/auto: same as ease in */
892                                         result = BLI_easing_quint_ease_in(time, begin, change, duration);
893                                         break;
894                         }
895                         break;
896
897                 case GP_IPO_SINE:
898                         switch (easing) {
899                                 case BEZT_IPO_EASE_IN:
900                                         result = BLI_easing_sine_ease_in(time, begin, change, duration);
901                                         break;
902                                 case BEZT_IPO_EASE_OUT:
903                                         result = BLI_easing_sine_ease_out(time, begin, change, duration);
904                                         break;
905                                 case BEZT_IPO_EASE_IN_OUT:
906                                         result = BLI_easing_sine_ease_in_out(time, begin, change, duration);
907                                         break;
908
909                                 default: /* default/auto: same as ease in */
910                                         result = BLI_easing_sine_ease_in(time, begin, change, duration);
911                                         break;
912                         }
913                         break;
914
915                 default:
916                         printf("%s: Unknown interpolation type - %d\n", __func__, ipo_settings->type);
917                         break;
918         }
919
920         return result;
921 }
922
923 static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
924 {
925         bGPdata   *gpd = CTX_data_gpencil_data(C);
926         bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
927         bGPDframe *actframe = active_gpl->actframe;
928
929         Object *ob = CTX_data_active_object(C);
930         ToolSettings *ts = CTX_data_tool_settings(C);
931         Depsgraph *depsgraph = CTX_data_depsgraph(C);
932         int cfra_eval = (int)DEG_get_ctime(depsgraph);
933
934         GP_Interpolate_Settings *ipo_settings = &ts->gp_interpolate;
935         eGP_Interpolate_SettingsFlag flag = ipo_settings->flag;
936
937         /* cannot interpolate if not between 2 frames */
938         if (ELEM(NULL, actframe, actframe->next)) {
939                 BKE_report(op->reports, RPT_ERROR, "Cannot find a pair of grease pencil frames to interpolate between in active layer");
940                 return OPERATOR_CANCELLED;
941         }
942         /* cannot interpolate in extremes */
943         if (ELEM(cfra_eval, actframe->framenum, actframe->next->framenum)) {
944                 BKE_report(op->reports, RPT_ERROR, "Cannot interpolate as current frame already has existing grease pencil frames");
945                 return OPERATOR_CANCELLED;
946         }
947
948         /* loop all layer to check if need interpolation */
949         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
950                 bGPDframe *prevFrame, *nextFrame;
951                 bGPDstroke *gps_from, *gps_to;
952                 int cframe, fFrame;
953
954                 /* all layers or only active */
955                 if (((flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) == 0) && (gpl != active_gpl)) {
956                         continue;
957                 }
958                 /* only editable and visible layers are considered */
959                 if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
960                         continue;
961                 }
962
963                 /* store extremes */
964                 prevFrame = gpl->actframe;
965                 nextFrame = gpl->actframe->next;
966
967                 /* Loop over intermediary frames and create the interpolation */
968                 for (cframe = prevFrame->framenum + 1; cframe < nextFrame->framenum; cframe++) {
969                         bGPDframe *interFrame = NULL;
970                         float factor;
971
972                         /* get interpolation factor */
973                         factor = (float)(cframe - prevFrame->framenum) / (nextFrame->framenum - prevFrame->framenum + 1);
974
975                         if (ipo_settings->type == GP_IPO_CURVEMAP) {
976                                 /* custom curvemap */
977                                 if (ipo_settings->custom_ipo) {
978                                         factor = curvemapping_evaluateF(ipo_settings->custom_ipo, 0, factor);
979                                 }
980                                 else {
981                                         BKE_report(op->reports, RPT_ERROR, "Custom interpolation curve does not exist");
982                                 }
983                         }
984                         else if (ipo_settings->type >= GP_IPO_BACK) {
985                                 /* easing equation... */
986                                 factor = gp_interpolate_seq_easing_calc(ipo_settings, factor);
987                         }
988
989                         /* create new strokes data with interpolated points reading original stroke */
990                         for (gps_from = prevFrame->strokes.first; gps_from; gps_from = gps_from->next) {
991                                 bGPDstroke *new_stroke = NULL;
992
993                                 /* only selected */
994                                 if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
995                                         continue;
996                                 }
997                                 /* skip strokes that are invalid for current view */
998                                 if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
999                                         continue;
1000                                 }
1001                                 /* check if the color is editable */
1002                                 if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) {
1003                                         continue;
1004                                 }
1005
1006                                 /* get final stroke to interpolate */
1007                                 fFrame = BLI_findindex(&prevFrame->strokes, gps_from);
1008                                 gps_to = BLI_findlink(&nextFrame->strokes, fFrame);
1009                                 if (gps_to == NULL) {
1010                                         continue;
1011                                 }
1012
1013                                 /* create a new frame if needed */
1014                                 if (interFrame == NULL) {
1015                                         interFrame = BKE_gpencil_layer_getframe(gpl, cframe, GP_GETFRAME_ADD_NEW);
1016                                         interFrame->key_type = BEZT_KEYTYPE_BREAKDOWN;
1017                                 }
1018
1019                                 /* create new stroke */
1020                                 new_stroke = BKE_gpencil_stroke_duplicate(gps_from);
1021
1022                                 /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
1023                                 if (gps_from->totpoints > gps_to->totpoints) {
1024                                         /* free weights of removed points */
1025                                         if (gps_from->dvert != NULL) {
1026                                                 BKE_defvert_array_free_elems(gps_from->dvert + gps_to->totpoints, gps_from->totpoints - gps_to->totpoints);
1027                                         }
1028
1029                                         new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints);
1030
1031                                         if (new_stroke->dvert != NULL) {
1032                                                 new_stroke->dvert = MEM_recallocN(new_stroke->dvert, sizeof(*new_stroke->dvert) * gps_to->totpoints);
1033                                         }
1034                                         new_stroke->totpoints = gps_to->totpoints;
1035                                         new_stroke->tot_triangles = 0;
1036                                         new_stroke->flag |= GP_STROKE_RECALC_GEOMETRY;
1037                                 }
1038
1039                                 /* update points position */
1040                                 gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
1041
1042                                 /* add to strokes */
1043                                 BLI_addtail(&interFrame->strokes, new_stroke);
1044                         }
1045                 }
1046         }
1047
1048         /* notifiers */
1049         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1050         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
1051
1052         return OPERATOR_FINISHED;
1053 }
1054
1055 void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
1056 {
1057         /* identifiers */
1058         ot->name = "Interpolate Sequence";
1059         ot->idname = "GPENCIL_OT_interpolate_sequence";
1060         ot->description = "Generate 'in-betweens' to smoothly interpolate between Grease Pencil frames";
1061
1062         /* api callbacks */
1063         ot->exec = gpencil_interpolate_seq_exec;
1064         ot->poll = gpencil_view3d_poll;
1065
1066         /* flags */
1067         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1068 }
1069
1070 /* ******************** Remove Breakdowns ************************ */
1071
1072 static bool gpencil_interpolate_reverse_poll(bContext *C)
1073 {
1074         if (!gpencil_view3d_poll(C)) {
1075                 return 0;
1076         }
1077
1078         bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
1079
1080         /* need to be on a breakdown frame */
1081         if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN)) {
1082                 CTX_wm_operator_poll_msg_set(C, "Expected current frame to be a breakdown");
1083                 return 0;
1084         }
1085
1086         return 1;
1087 }
1088
1089 static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *UNUSED(op))
1090 {
1091         bGPdata *gpd = ED_gpencil_data_get_active(C);
1092
1093         /* Go through each layer, deleting the breakdowns around the current frame,
1094          * but only if there is a keyframe nearby to stop at
1095          */
1096         CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
1097         {
1098                 bGPDframe *start_key = NULL;
1099                 bGPDframe *end_key = NULL;
1100                 bGPDframe *gpf, *gpfn;
1101
1102                 /* Only continue if we're currently on a breakdown keyframe */
1103                 if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN))
1104                         continue;
1105
1106                 /* Search left for "start_key" (i.e. the first breakdown to remove) */
1107                 gpf = gpl->actframe;
1108                 while (gpf) {
1109                         if (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN) {
1110                                 /* A breakdown... keep going left */
1111                                 start_key = gpf;
1112                                 gpf = gpf->prev;
1113                         }
1114                         else {
1115                                 /* Not a breakdown (may be a key, or an extreme, or something else that wasn't generated)... stop */
1116                                 break;
1117                         }
1118                 }
1119
1120                 /* Search right for "end_key" (i.e. the last breakdown to remove) */
1121                 gpf = gpl->actframe;
1122                 while (gpf) {
1123                         if (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN) {
1124                                 /* A breakdown... keep going right */
1125                                 end_key = gpf;
1126                                 gpf = gpf->next;
1127                         }
1128                         else {
1129                                 /* Not a breakdown... stop */
1130                                 break;
1131                         }
1132                 }
1133
1134                 /* Did we find anything? */
1135                 /* NOTE: We should only proceed if there's something before/after these extents...
1136                  * Otherwise, there's just an extent of breakdowns with no keys to interpolate between
1137                  */
1138                 if ((start_key && end_key) &&
1139                     ELEM(NULL, start_key->prev, end_key->next) == false)
1140                 {
1141                         /* Set actframe to the key before start_key, since the keys have been removed now */
1142                         gpl->actframe = start_key->prev;
1143
1144                         /* Free each frame we're removing (except the last one) */
1145                         for (gpf = start_key; gpf && gpf != end_key; gpf = gpfn) {
1146                                 gpfn = gpf->next;
1147
1148                                 /* free strokes and their associated memory */
1149                                 BKE_gpencil_free_strokes(gpf);
1150                                 BLI_freelinkN(&gpl->frames, gpf);
1151                         }
1152
1153                         /* Now free the last one... */
1154                         BKE_gpencil_free_strokes(end_key);
1155                         BLI_freelinkN(&gpl->frames, end_key);
1156                 }
1157         }
1158         CTX_DATA_END;
1159
1160         /* notifiers */
1161         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1162         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
1163
1164         return OPERATOR_FINISHED;
1165 }
1166
1167 void GPENCIL_OT_interpolate_reverse(wmOperatorType *ot)
1168 {
1169         /* identifiers */
1170         ot->name = "Remove Breakdowns";
1171         ot->idname = "GPENCIL_OT_interpolate_reverse";
1172         ot->description = "Remove breakdown frames generated by interpolating between two Grease Pencil frames";
1173
1174         /* callbacks */
1175         ot->exec = gpencil_interpolate_reverse_exec;
1176         ot->poll = gpencil_interpolate_reverse_poll;
1177
1178         /* flags */
1179         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1180 }
1181
1182 /* *************************************************************** */