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