Merge branch 'blender2.7'
[blender.git] / source / blender / blenkernel / intern / gpencil_modifier.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) 2017, Blender Foundation
17  * This is a new part of Blender
18  */
19
20  /** \file blender/blenkernel/intern/gpencil_modifier.c
21   *  \ingroup bke
22   */
23
24
25 #include <stdio.h>
26
27 #include "MEM_guardedalloc.h"
28
29 #include "BLI_blenlib.h"
30 #include "BLI_utildefines.h"
31 #include "BLI_math_vector.h"
32 #include "BLI_string_utils.h"
33
34 #include "BLT_translation.h"
35
36 #include "DNA_meshdata_types.h"
37 #include "DNA_scene_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_gpencil_types.h"
40 #include "DNA_gpencil_modifier_types.h"
41
42 #include "BKE_library.h"
43 #include "BKE_library_query.h"
44 #include "BKE_gpencil.h"
45 #include "BKE_lattice.h"
46 #include "BKE_gpencil_modifier.h"
47 #include "BKE_object.h"
48
49 #include "DEG_depsgraph.h"
50 #include "DEG_depsgraph_query.h"
51
52 #include "MOD_gpencil_modifiertypes.h"
53
54 static GpencilModifierTypeInfo *modifier_gpencil_types[NUM_GREASEPENCIL_MODIFIER_TYPES] = { NULL };
55
56 /* *************************************************** */
57 /* Geometry Utilities */
58
59 /* calculate stroke normal using some points */
60 void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3])
61 {
62         if (gps->totpoints < 3) {
63                 zero_v3(r_normal);
64                 return;
65         }
66
67         bGPDspoint *points = gps->points;
68         int totpoints = gps->totpoints;
69
70         const bGPDspoint *pt0 = &points[0];
71         const bGPDspoint *pt1 = &points[1];
72         const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
73
74         float vec1[3];
75         float vec2[3];
76
77         /* initial vector (p0 -> p1) */
78         sub_v3_v3v3(vec1, &pt1->x, &pt0->x);
79
80         /* point vector at 3/4 */
81         sub_v3_v3v3(vec2, &pt3->x, &pt0->x);
82
83         /* vector orthogonal to polygon plane */
84         cross_v3_v3v3(r_normal, vec1, vec2);
85
86         /* Normalize vector */
87         normalize_v3(r_normal);
88 }
89
90 /* Get points of stroke always flat to view not affected by camera view or view position */
91 static void gpencil_stroke_project_2d(const bGPDspoint *points, int totpoints, vec2f *points2d)
92 {
93         const bGPDspoint *pt0 = &points[0];
94         const bGPDspoint *pt1 = &points[1];
95         const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
96
97         float locx[3];
98         float locy[3];
99         float loc3[3];
100         float normal[3];
101
102         /* local X axis (p0 -> p1) */
103         sub_v3_v3v3(locx, &pt1->x, &pt0->x);
104
105         /* point vector at 3/4 */
106         sub_v3_v3v3(loc3, &pt3->x, &pt0->x);
107
108         /* vector orthogonal to polygon plane */
109         cross_v3_v3v3(normal, locx, loc3);
110
111         /* local Y axis (cross to normal/x axis) */
112         cross_v3_v3v3(locy, normal, locx);
113
114         /* Normalize vectors */
115         normalize_v3(locx);
116         normalize_v3(locy);
117
118         /* Get all points in local space */
119         for (int i = 0; i < totpoints; i++) {
120                 const bGPDspoint *pt = &points[i];
121                 float loc[3];
122
123                 /* Get local space using first point as origin */
124                 sub_v3_v3v3(loc, &pt->x, &pt0->x);
125
126                 vec2f *point = &points2d[i];
127                 point->x = dot_v3v3(loc, locx);
128                 point->y = dot_v3v3(loc, locy);
129         }
130
131 }
132
133 /* Stroke Simplify ------------------------------------- */
134
135 /* Reduce a series of points to a simplified version, but
136  * maintains the general shape of the series
137  *
138  * Ramer - Douglas - Peucker algorithm
139  * by http ://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
140  */
141 static void gpencil_rdp_stroke(bGPDstroke *gps, vec2f *points2d, float epsilon)
142 {
143         vec2f *old_points2d = points2d;
144         int totpoints = gps->totpoints;
145         char *marked = NULL;
146         char work;
147
148         int start = 1;
149         int end = gps->totpoints - 2;
150
151         marked = MEM_callocN(totpoints, "GP marked array");
152         marked[start] = 1;
153         marked[end] = 1;
154
155         work = 1;
156         int totmarked = 0;
157         /* while still reducing */
158         while (work) {
159                 int ls, le;
160                 work = 0;
161
162                 ls = start;
163                 le = start + 1;
164
165                 /* while not over interval */
166                 while (ls < end) {
167                         int max_i = 0;
168                         float v1[2];
169                         /* divided to get more control */
170                         float max_dist = epsilon / 10.0f;
171
172                         /* find the next marked point */
173                         while (marked[le] == 0) {
174                                 le++;
175                         }
176
177                         /* perpendicular vector to ls-le */
178                         v1[1] = old_points2d[le].x - old_points2d[ls].x;
179                         v1[0] = old_points2d[ls].y - old_points2d[le].y;
180
181                         for (int i = ls + 1; i < le; i++) {
182                                 float mul;
183                                 float dist;
184                                 float v2[2];
185
186                                 v2[0] = old_points2d[i].x - old_points2d[ls].x;
187                                 v2[1] = old_points2d[i].y - old_points2d[ls].y;
188
189                                 if (v2[0] == 0 && v2[1] == 0) {
190                                         continue;
191                                 }
192
193                                 mul = (float)(v1[0] * v2[0] + v1[1] * v2[1]) / (float)(v2[0] * v2[0] + v2[1] * v2[1]);
194
195                                 dist = mul * mul * (v2[0] * v2[0] + v2[1] * v2[1]);
196
197                                 if (dist > max_dist) {
198                                         max_dist = dist;
199                                         max_i = i;
200                                 }
201                         }
202
203                         if (max_i != 0) {
204                                 work = 1;
205                                 marked[max_i] = 1;
206                                 totmarked++;
207                         }
208
209                         ls = le;
210                         le = ls + 1;
211                 }
212         }
213
214         /* adding points marked */
215         bGPDspoint *old_points = MEM_dupallocN(gps->points);
216         MDeformVert *old_dvert = NULL;
217         MDeformVert *dvert_src = NULL;
218
219         if (gps->dvert != NULL) {
220                 old_dvert = MEM_dupallocN(gps->dvert);
221         }
222         /* resize gps */
223         gps->flag |= GP_STROKE_RECALC_GEOMETRY;
224         gps->tot_triangles = 0;
225
226         int j = 0;
227         for (int i = 0; i < totpoints; i++) {
228                 bGPDspoint *pt_src = &old_points[i];
229                 bGPDspoint *pt = &gps->points[j];
230
231                 if ((marked[i]) || (i == 0) || (i == totpoints - 1)) {
232                         memcpy(pt, pt_src, sizeof(bGPDspoint));
233                         if (gps->dvert != NULL) {
234                                 dvert_src = &old_dvert[i];
235                                 MDeformVert *dvert = &gps->dvert[j];
236                                 memcpy(dvert, dvert_src, sizeof(MDeformVert));
237                                 if (dvert_src->dw) {
238                                         memcpy(dvert->dw, dvert_src->dw, sizeof(MDeformWeight));
239                                 }
240                         }
241                         j++;
242                 }
243                 else {
244                         if (gps->dvert != NULL) {
245                                 dvert_src = &old_dvert[i];
246                                 BKE_gpencil_free_point_weights(dvert_src);
247                         }
248                 }
249         }
250
251         gps->totpoints = j;
252
253         MEM_SAFE_FREE(old_points);
254         MEM_SAFE_FREE(old_dvert);
255         MEM_SAFE_FREE(marked);
256 }
257
258 /* Simplify stroke using Ramer-Douglas-Peucker algorithm */
259 void BKE_gpencil_simplify_stroke(bGPDstroke *gps, float factor)
260 {
261         /* first create temp data and convert points to 2D */
262         vec2f *points2d = MEM_mallocN(sizeof(vec2f) * gps->totpoints, "GP Stroke temp 2d points");
263
264         gpencil_stroke_project_2d(gps->points, gps->totpoints, points2d);
265
266         gpencil_rdp_stroke(gps, points2d, factor);
267
268         MEM_SAFE_FREE(points2d);
269 }
270
271 /* Simplify alternate vertex of stroke except extremes */
272 void BKE_gpencil_simplify_fixed(bGPDstroke *gps)
273 {
274         if (gps->totpoints < 5) {
275                 return;
276         }
277
278         /* save points */
279         bGPDspoint *old_points = MEM_dupallocN(gps->points);
280         MDeformVert *old_dvert = NULL;
281         MDeformVert *dvert_src = NULL;
282
283         if (gps->dvert != NULL) {
284                 old_dvert = MEM_dupallocN(gps->dvert);
285         }
286
287         /* resize gps */
288         int newtot = (gps->totpoints - 2) / 2;
289         if (((gps->totpoints - 2) % 2) > 0) {
290                 newtot++;
291         }
292         newtot += 2;
293
294         gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * newtot);
295         if (gps->dvert != NULL) {
296                 gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot);
297         }
298         gps->flag |= GP_STROKE_RECALC_GEOMETRY;
299         gps->tot_triangles = 0;
300
301         int j = 0;
302         for (int i = 0; i < gps->totpoints; i++) {
303                 bGPDspoint *pt_src = &old_points[i];
304                 bGPDspoint *pt = &gps->points[j];
305
306
307                 if ((i == 0) || (i == gps->totpoints - 1) || ((i % 2) > 0.0)) {
308                         memcpy(pt, pt_src, sizeof(bGPDspoint));
309                         if (gps->dvert != NULL) {
310                                 dvert_src = &old_dvert[i];
311                                 MDeformVert *dvert = &gps->dvert[j];
312                                 memcpy(dvert, dvert_src, sizeof(MDeformVert));
313                                 if (dvert_src->dw) {
314                                         memcpy(dvert->dw, dvert_src->dw, sizeof(MDeformWeight));
315                                 }
316                         }
317                         j++;
318                 }
319                 else {
320                         if (gps->dvert != NULL) {
321                                 dvert_src = &old_dvert[i];
322                                 BKE_gpencil_free_point_weights(dvert_src);
323                         }
324                 }
325         }
326
327         gps->totpoints = j;
328
329         MEM_SAFE_FREE(old_points);
330         MEM_SAFE_FREE(old_dvert);
331 }
332
333 /* *************************************************** */
334 /* Modifier Utilities */
335
336 /* Lattice Modifier ---------------------------------- */
337 /* Usually, evaluation of the lattice modifier is self-contained.
338  * However, since GP's modifiers operate on a per-stroke basis,
339  * we need to these two extra functions that called before/after
340  * each loop over all the geometry being evaluated.
341  */
342
343  /* init lattice deform data */
344 void BKE_gpencil_lattice_init(Object *ob)
345 {
346         GpencilModifierData *md;
347         for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
348                 if (md->type == eGpencilModifierType_Lattice) {
349                         LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
350                         Object *latob = NULL;
351
352                         latob = mmd->object;
353                         if ((!latob) || (latob->type != OB_LATTICE)) {
354                                 return;
355                         }
356                         if (mmd->cache_data) {
357                                 end_latt_deform((struct LatticeDeformData *)mmd->cache_data);
358                         }
359
360                         /* init deform data */
361                         mmd->cache_data = (struct LatticeDeformData *)init_latt_deform(latob, ob);
362                 }
363         }
364 }
365
366 /* clear lattice deform data */
367 void BKE_gpencil_lattice_clear(Object *ob)
368 {
369         GpencilModifierData *md;
370         for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
371                 if (md->type == eGpencilModifierType_Lattice) {
372                         LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
373                         if ((mmd) && (mmd->cache_data)) {
374                                 end_latt_deform((struct LatticeDeformData *)mmd->cache_data);
375                                 mmd->cache_data = NULL;
376                         }
377                 }
378         }
379 }
380
381 /* *************************************************** */
382 /* Modifier Methods - Evaluation Loops, etc. */
383
384 /* check if exist geometry modifiers */
385 bool BKE_gpencil_has_geometry_modifiers(Object *ob)
386 {
387         GpencilModifierData *md;
388         for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
389                 const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
390
391                 if (mti && mti->generateStrokes) {
392                         return true;
393                 }
394         }
395         return false;
396 }
397
398 /* check if exist time modifiers */
399 bool BKE_gpencil_has_time_modifiers(Object *ob)
400 {
401         GpencilModifierData *md;
402         for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
403                 const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
404
405                 if (mti && mti->remapTime) {
406                         return true;
407                 }
408         }
409         return false;
410 }
411
412 /* apply stroke modifiers */
413 void BKE_gpencil_stroke_modifiers(Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDframe *UNUSED(gpf), bGPDstroke *gps, bool is_render)
414 {
415         GpencilModifierData *md;
416         bGPdata *gpd = ob->data;
417         const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
418
419         for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
420                 if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
421                         const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
422
423                         if (GPENCIL_MODIFIER_EDIT(md, is_edit)) {
424                                 continue;
425                         }
426
427                         if (mti && mti->deformStroke) {
428                                 mti->deformStroke(md, depsgraph, ob, gpl, gps);
429
430                                 /* some modifiers could require a recalc of fill triangulation data */
431                                 if (gpd->flag & GP_DATA_STROKE_FORCE_RECALC) {
432                                         if (ELEM(md->type,
433                                                  eGpencilModifierType_Armature,
434                                                  eGpencilModifierType_Hook,
435                                                  eGpencilModifierType_Lattice,
436                                                  eGpencilModifierType_Offset))
437                                         {
438
439                                                 gps->flag |= GP_STROKE_RECALC_GEOMETRY;
440                                         }
441                                 }
442                         }
443                 }
444         }
445 }
446
447 /* apply stroke geometry modifiers */
448 void BKE_gpencil_geometry_modifiers(Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bool is_render)
449 {
450         GpencilModifierData *md;
451         bGPdata *gpd = ob->data;
452         const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
453
454         for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
455                 if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
456                         const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
457
458                         if (GPENCIL_MODIFIER_EDIT(md, is_edit)) {
459                                 continue;
460                         }
461
462                         if (mti->generateStrokes) {
463                                 mti->generateStrokes(md, depsgraph, ob, gpl, gpf);
464                         }
465                 }
466         }
467 }
468
469 /* apply time modifiers */
470 int BKE_gpencil_time_modifier(Depsgraph *depsgraph, Scene *scene, Object *ob,
471         bGPDlayer *gpl, int cfra, bool is_render)
472 {
473         GpencilModifierData *md;
474         bGPdata *gpd = ob->data;
475         const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
476         int nfra = cfra;
477
478         for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
479                 if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
480                         const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
481
482                         if (GPENCIL_MODIFIER_EDIT(md, is_edit)) {
483                                 continue;
484                         }
485
486                         if (mti->remapTime) {
487                                 nfra = mti->remapTime(md, depsgraph, scene, ob, gpl, cfra);
488                                 /* if the frame number changed, don't evaluate more and return */
489                                 if (nfra != cfra) {
490                                         return nfra;
491                                 }
492                         }
493                 }
494         }
495
496         /* if no time modifier, return original frame number */
497         return nfra;
498 }
499 /* *************************************************** */
500
501 void BKE_gpencil_eval_geometry(Depsgraph *depsgraph,
502         bGPdata *gpd)
503 {
504         DEG_debug_print_eval(depsgraph, __func__, gpd->id.name, gpd);
505         int ctime = (int)DEG_get_ctime(depsgraph);
506
507         /* update active frame */
508         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
509                 gpl->actframe = BKE_gpencil_layer_getframe(gpl, ctime, GP_GETFRAME_USE_PREV);
510         }
511
512         /* TODO: Move "derived_gpf" logic here from DRW_gpencil_populate_datablock()?
513          * This would be better than inventing our own logic for this stuff...
514          */
515
516          /* TODO: Move the following code to "BKE_gpencil_eval_done()" (marked as an exit node)
517           * later when there's more happening here. For now, let's just keep this in here to avoid
518           * needing to have one more node slowing down evaluation...
519           */
520         if (DEG_is_active(depsgraph)) {
521                 bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&gpd->id);
522
523                 /* sync "actframe" changes back to main-db too,
524                  * so that editing tools work with copy-on-write
525                  * when the current frame changes
526                  */
527                 for (bGPDlayer *gpl = gpd_orig->layers.first; gpl; gpl = gpl->next) {
528                         gpl->actframe = BKE_gpencil_layer_getframe(gpl, ctime, GP_GETFRAME_USE_PREV);
529                 }
530         }
531 }
532
533 void BKE_gpencil_modifier_init(void)
534 {
535         /* Initialize modifier types */
536         gpencil_modifier_type_init(modifier_gpencil_types); /* MOD_gpencil_util.c */
537 }
538
539 GpencilModifierData *BKE_gpencil_modifier_new(int type)
540 {
541         const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(type);
542         GpencilModifierData *md = MEM_callocN(mti->struct_size, mti->struct_name);
543
544         /* note, this name must be made unique later */
545         BLI_strncpy(md->name, DATA_(mti->name), sizeof(md->name));
546
547         md->type = type;
548         md->mode = eGpencilModifierMode_Realtime | eGpencilModifierMode_Render | eGpencilModifierMode_Expanded;
549         md->flag = eGpencilModifierFlag_StaticOverride_Local;
550
551         if (mti->flags & eGpencilModifierTypeFlag_EnableInEditmode)
552                 md->mode |= eGpencilModifierMode_Editmode;
553
554         if (mti->initData) mti->initData(md);
555
556         return md;
557 }
558
559 static void modifier_free_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag)
560 {
561         ID *id = *idpoin;
562         if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
563                 id_us_min(id);
564         }
565 }
566
567 void BKE_gpencil_modifier_free_ex(GpencilModifierData *md, const int flag)
568 {
569         const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
570
571         if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
572                 if (mti->foreachIDLink) {
573                         mti->foreachIDLink(md, NULL, modifier_free_data_id_us_cb, NULL);
574                 }
575                 else if (mti->foreachObjectLink) {
576                         mti->foreachObjectLink(md, NULL, (GreasePencilObjectWalkFunc)modifier_free_data_id_us_cb, NULL);
577                 }
578         }
579
580         if (mti->freeData) mti->freeData(md);
581         if (md->error) MEM_freeN(md->error);
582
583         MEM_freeN(md);
584 }
585
586 void BKE_gpencil_modifier_free(GpencilModifierData *md)
587 {
588         BKE_gpencil_modifier_free_ex(md, 0);
589 }
590
591 /* check unique name */
592 bool BKE_gpencil_modifier_unique_name(ListBase *modifiers, GpencilModifierData *gmd)
593 {
594         if (modifiers && gmd) {
595                 const GpencilModifierTypeInfo *gmti = BKE_gpencil_modifierType_getInfo(gmd->type);
596                 return BLI_uniquename(modifiers, gmd, DATA_(gmti->name), '.', offsetof(GpencilModifierData, name), sizeof(gmd->name));
597         }
598         return false;
599 }
600
601 bool BKE_gpencil_modifier_dependsOnTime(GpencilModifierData *md)
602 {
603         const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
604
605         return mti->dependsOnTime && mti->dependsOnTime(md);
606 }
607
608 const GpencilModifierTypeInfo *BKE_gpencil_modifierType_getInfo(GpencilModifierType type)
609 {
610         /* type unsigned, no need to check < 0 */
611         if (type < NUM_GREASEPENCIL_MODIFIER_TYPES && modifier_gpencil_types[type]->name[0] != '\0') {
612                 return modifier_gpencil_types[type];
613         }
614         else {
615                 return NULL;
616         }
617 }
618
619 void BKE_gpencil_modifier_copyData_generic(const GpencilModifierData *md_src, GpencilModifierData *md_dst)
620 {
621         const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md_src->type);
622
623         /* md_dst may have already be fully initialized with some extra allocated data,
624          * we need to free it now to avoid memleak. */
625         if (mti->freeData) {
626                 mti->freeData(md_dst);
627         }
628
629         const size_t data_size = sizeof(GpencilModifierData);
630         const char *md_src_data = ((const char *)md_src) + data_size;
631         char       *md_dst_data = ((char *)md_dst) + data_size;
632         BLI_assert(data_size <= (size_t)mti->struct_size);
633         memcpy(md_dst_data, md_src_data, (size_t)mti->struct_size - data_size);
634 }
635
636 static void gpencil_modifier_copy_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag)
637 {
638         ID *id = *idpoin;
639         if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
640                 id_us_plus(id);
641         }
642 }
643
644 void BKE_gpencil_modifier_copyData_ex(GpencilModifierData *md, GpencilModifierData *target, const int flag)
645 {
646         const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
647
648         target->mode = md->mode;
649         target->flag = md->flag;
650
651         if (mti->copyData) {
652                 mti->copyData(md, target);
653         }
654
655         if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
656                 if (mti->foreachIDLink) {
657                         mti->foreachIDLink(target, NULL, gpencil_modifier_copy_data_id_us_cb, NULL);
658                 }
659                 else if (mti->foreachObjectLink) {
660                         mti->foreachObjectLink(target, NULL, (GreasePencilObjectWalkFunc)gpencil_modifier_copy_data_id_us_cb, NULL);
661                 }
662         }
663 }
664
665 void BKE_gpencil_modifier_copyData(GpencilModifierData *md, GpencilModifierData *target)
666 {
667         BKE_gpencil_modifier_copyData_ex(md, target, 0);
668 }
669
670 GpencilModifierData *BKE_gpencil_modifiers_findByType(Object *ob, GpencilModifierType type)
671 {
672         GpencilModifierData *md = ob->greasepencil_modifiers.first;
673
674         for (; md; md = md->next)
675                 if (md->type == type)
676                         break;
677
678         return md;
679 }
680
681 void BKE_gpencil_modifiers_foreachIDLink(Object *ob, GreasePencilIDWalkFunc walk, void *userData)
682 {
683         GpencilModifierData *md = ob->greasepencil_modifiers.first;
684
685         for (; md; md = md->next) {
686                 const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
687
688                 if (mti->foreachIDLink) {
689                         mti->foreachIDLink(md, ob, walk, userData);
690                 }
691                 else if (mti->foreachObjectLink) {
692                         /* each Object can masquerade as an ID, so this should be OK */
693                         GreasePencilObjectWalkFunc fp = (GreasePencilObjectWalkFunc)walk;
694                         mti->foreachObjectLink(md, ob, fp, userData);
695                 }
696         }
697 }
698
699 void BKE_gpencil_modifiers_foreachTexLink(Object *ob, GreasePencilTexWalkFunc walk, void *userData)
700 {
701         GpencilModifierData *md = ob->greasepencil_modifiers.first;
702
703         for (; md; md = md->next) {
704                 const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
705
706                 if (mti->foreachTexLink)
707                         mti->foreachTexLink(md, ob, walk, userData);
708         }
709 }
710
711 GpencilModifierData *BKE_gpencil_modifiers_findByName(Object *ob, const char *name)
712 {
713         return BLI_findstring(&(ob->greasepencil_modifiers), name, offsetof(GpencilModifierData, name));
714 }
715
716 void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
717 {
718         bGPDspoint *temp_points;
719         MDeformVert *temp_dverts = NULL;
720         MDeformVert *dvert = NULL;
721         MDeformVert *dvert_final = NULL;
722         MDeformVert *dvert_next = NULL;
723         int totnewpoints, oldtotpoints;
724         int i2;
725
726         for (int s = 0; s < level; s++) {
727                 totnewpoints = gps->totpoints - 1;
728                 /* duplicate points in a temp area */
729                 temp_points = MEM_dupallocN(gps->points);
730                 oldtotpoints = gps->totpoints;
731
732                 /* resize the points arrays */
733                 gps->totpoints += totnewpoints;
734                 gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
735                 if (gps->dvert != NULL) {
736                         temp_dverts = MEM_dupallocN(gps->dvert);
737                         gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
738                 }
739                 gps->flag |= GP_STROKE_RECALC_GEOMETRY;
740                 gps->tot_triangles = 0;
741
742                 /* move points from last to first to new place */
743                 i2 = gps->totpoints - 1;
744                 for (int i = oldtotpoints - 1; i > 0; i--) {
745                         bGPDspoint *pt = &temp_points[i];
746                         bGPDspoint *pt_final = &gps->points[i2];
747
748                         copy_v3_v3(&pt_final->x, &pt->x);
749                         pt_final->pressure = pt->pressure;
750                         pt_final->strength = pt->strength;
751                         pt_final->time = pt->time;
752                         pt_final->flag = pt->flag;
753
754                         if (gps->dvert != NULL) {
755                                 dvert = &temp_dverts[i];
756                                 dvert_final = &gps->dvert[i2];
757                                 dvert_final->totweight = dvert->totweight;
758                                 dvert_final->dw = dvert->dw;
759                         }
760                         i2 -= 2;
761                 }
762                 /* interpolate mid points */
763                 i2 = 1;
764                 for (int i = 0; i < oldtotpoints - 1; i++) {
765                         bGPDspoint *pt = &temp_points[i];
766                         bGPDspoint *next = &temp_points[i + 1];
767                         bGPDspoint *pt_final = &gps->points[i2];
768
769                         /* add a half way point */
770                         interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
771                         pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
772                         pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
773                         CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
774                         pt_final->time = interpf(pt->time, next->time, 0.5f);
775
776                         if (gps->dvert != NULL) {
777                                 dvert = &temp_dverts[i];
778                                 dvert_next = &temp_dverts[i + 1];
779                                 dvert_final = &gps->dvert[i2];
780
781                                 dvert_final->totweight = dvert->totweight;
782                                 dvert_final->dw = MEM_dupallocN(dvert->dw);
783
784                                 /* interpolate weight values */
785                                 for (int d = 0; d < dvert->totweight; d++) {
786                                         MDeformWeight *dw_a = &dvert->dw[d];
787                                         if (dvert_next->totweight > d) {
788                                                 MDeformWeight *dw_b = &dvert_next->dw[d];
789                                                 MDeformWeight *dw_final = &dvert_final->dw[d];
790                                                 dw_final->weight = interpf(dw_a->weight, dw_b->weight, 0.5f);
791                                         }
792                                 }
793                         }
794
795                         i2 += 2;
796                 }
797
798                 MEM_SAFE_FREE(temp_points);
799                 MEM_SAFE_FREE(temp_dverts);
800
801                 /* move points to smooth stroke (not simple flag )*/
802                 if ((flag & GP_SUBDIV_SIMPLE) == 0) {
803                         /* duplicate points in a temp area with the new subdivide data */
804                         temp_points = MEM_dupallocN(gps->points);
805
806                         /* extreme points are not changed */
807                         for (int i = 0; i < gps->totpoints - 2; i++) {
808                                 bGPDspoint *pt = &temp_points[i];
809                                 bGPDspoint *next = &temp_points[i + 1];
810                                 bGPDspoint *pt_final = &gps->points[i + 1];
811
812                                 /* move point */
813                                 interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
814                         }
815                         /* free temp memory */
816                         MEM_SAFE_FREE(temp_points);
817                 }
818
819         }
820 }