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