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