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