Cleanup: remove redundant doxygen \file argument
[blender.git] / source / blender / editors / gpencil / gpencil_utils.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) 2014, Blender Foundation
17  */
18
19 /** \file \ingroup edgpencil
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stddef.h>
26 #include <math.h>
27
28 #include "MEM_guardedalloc.h"
29
30 #include "BLI_math.h"
31 #include "BLI_blenlib.h"
32 #include "BLI_ghash.h"
33 #include "BLI_utildefines.h"
34 #include "BLT_translation.h"
35 #include "BLI_rand.h"
36
37 #include "DNA_meshdata_types.h"
38 #include "DNA_gpencil_types.h"
39 #include "DNA_brush_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_screen_types.h"
43 #include "DNA_space_types.h"
44 #include "DNA_view3d_types.h"
45
46 #include "BKE_action.h"
47 #include "BKE_colortools.h"
48 #include "BKE_deform.h"
49 #include "BKE_main.h"
50 #include "BKE_brush.h"
51 #include "BKE_context.h"
52 #include "BKE_gpencil.h"
53 #include "BKE_object.h"
54 #include "BKE_paint.h"
55 #include "BKE_material.h"
56 #include "BKE_tracking.h"
57
58 #include "WM_api.h"
59 #include "WM_toolsystem.h"
60
61 #include "RNA_access.h"
62 #include "RNA_define.h"
63 #include "RNA_enum_types.h"
64
65 #include "UI_resources.h"
66 #include "UI_view2d.h"
67
68 #include "ED_gpencil.h"
69 #include "ED_clip.h"
70 #include "ED_view3d.h"
71 #include "ED_object.h"
72 #include "ED_screen.h"
73
74 #include "GPU_immediate.h"
75 #include "GPU_immediate_util.h"
76
77 #include "DEG_depsgraph.h"
78 #include "DEG_depsgraph_query.h"
79
80 #include "gpencil_intern.h"
81
82 /* ******************************************************** */
83 /* Context Wrangling... */
84
85 /* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it,
86  * when context info is not available.
87  */
88 bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, ScrArea *sa, Scene *scene, Object *ob, PointerRNA *r_ptr)
89 {
90         /* if there's an active area, check if the particular editor may
91          * have defined any special Grease Pencil context for editing...
92          */
93         if (sa) {
94                 SpaceLink *sl = sa->spacedata.first;
95
96                 switch (sa->spacetype) {
97                         /* XXX: Should we reduce reliance on context.gpencil_data for these cases? */
98                         case SPACE_BUTS: /* properties */
99                         case SPACE_INFO: /* header info (needed after workspaces merge) */
100                         {
101                                 if (ob && (ob->type == OB_GPENCIL)) {
102                                         /* GP Object */
103                                         if (r_ptr) RNA_id_pointer_create(&ob->id, r_ptr);
104                                         return (bGPdata **)&ob->data;
105                                 }
106                                 else {
107                                         return NULL;
108                                 }
109
110                                 break;
111                         }
112
113                         case SPACE_TOPBAR: /* Topbar (needed after topbar merge) */
114                         case SPACE_VIEW3D: /* 3D-View */
115                         {
116                                 if (ob && (ob->type == OB_GPENCIL)) {
117                                         /* GP Object */
118                                         if (r_ptr) RNA_id_pointer_create(&ob->id, r_ptr);
119                                         return (bGPdata **)&ob->data;
120                                 }
121                                 else {
122                                         /* Annotations */
123                                         /* XXX: */
124                                         if (r_ptr) RNA_id_pointer_create(&scene->id, r_ptr);
125                                         return &scene->gpd;
126                                 }
127
128                                 break;
129                         }
130                         case SPACE_NODE: /* Nodes Editor */
131                         {
132                                 SpaceNode *snode = (SpaceNode *)sl;
133
134                                 /* return the GP data for the active node block/node */
135                                 if (snode && snode->nodetree) {
136                                         /* for now, as long as there's an active node tree,
137                                          * default to using that in the Nodes Editor */
138                                         if (r_ptr) RNA_id_pointer_create(&snode->nodetree->id, r_ptr);
139                                         return &snode->nodetree->gpd;
140                                 }
141
142                                 /* even when there is no node-tree, don't allow this to flow to scene */
143                                 return NULL;
144                         }
145                         case SPACE_SEQ: /* Sequencer */
146                         {
147                                 SpaceSeq *sseq = (SpaceSeq *)sl;
148
149                                 /* for now, Grease Pencil data is associated with the space (actually preview region only) */
150                                 /* XXX our convention for everything else is to link to data though... */
151                                 if (r_ptr) RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, r_ptr);
152                                 return &sseq->gpd;
153                         }
154                         case SPACE_IMAGE: /* Image/UV Editor */
155                         {
156                                 SpaceImage *sima = (SpaceImage *)sl;
157
158                                 /* for now, Grease Pencil data is associated with the space... */
159                                 /* XXX our convention for everything else is to link to data though... */
160                                 if (r_ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, r_ptr);
161                                 return &sima->gpd;
162                         }
163                         case SPACE_CLIP: /* Nodes Editor */
164                         {
165                                 SpaceClip *sc = (SpaceClip *)sl;
166                                 MovieClip *clip = ED_space_clip_get_clip(sc);
167
168                                 if (clip) {
169                                         if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
170                                                 MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
171
172                                                 if (!track)
173                                                         return NULL;
174
175                                                 if (r_ptr) RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, r_ptr);
176                                                 return &track->gpd;
177                                         }
178                                         else {
179                                                 if (r_ptr) RNA_id_pointer_create(&clip->id, r_ptr);
180                                                 return &clip->gpd;
181                                         }
182                                 }
183                                 break;
184                         }
185                         default: /* unsupported space */
186                                 return NULL;
187                 }
188         }
189
190         return NULL;
191 }
192
193 /* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it */
194 bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *r_ptr)
195 {
196         ID *screen_id = (ID *)CTX_wm_screen(C);
197         Scene *scene = CTX_data_scene(C);
198         ScrArea *sa = CTX_wm_area(C);
199         Object *ob = CTX_data_active_object(C);
200
201         return ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, r_ptr);
202 }
203
204 /* -------------------------------------------------------- */
205
206 /* Get the active Grease Pencil datablock, when context is not available */
207 bGPdata *ED_gpencil_data_get_active_direct(ID *screen_id, ScrArea *sa, Scene *scene, Object *ob)
208 {
209         bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, NULL);
210         return (gpd_ptr) ? *(gpd_ptr) : NULL;
211 }
212
213 /**
214  * Get the active Grease Pencil datablock
215  * \note This is the original (bmain) copy of the datablock, stored in files.
216  *       Do not use for reading evaluated copies of GP Objects data
217  */
218 bGPdata *ED_gpencil_data_get_active(const bContext *C)
219 {
220         bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
221         return (gpd_ptr) ? *(gpd_ptr) : NULL;
222 }
223
224 /**
225  * Get the evaluated copy of the active Grease Pencil datablock (where applicable)
226  * - For the 3D View (i.e. "GP Objects"), this gives the evaluated copy of the GP datablock
227  *   (i.e. a copy of the active GP datablock for the active object, where modifiers have been
228  *   applied). This is needed to correctly work with "Copy-on-Write"
229  * - For all other editors (i.e. "GP Annotations"), this just gives the active datablock
230  *   like for ED_gpencil_data_get_active()
231  */
232 bGPdata *ED_gpencil_data_get_active_evaluated(const bContext *C)
233 {
234         ID *screen_id = (ID *)CTX_wm_screen(C);
235         ScrArea *sa = CTX_wm_area(C);
236
237         const Depsgraph *depsgraph = CTX_data_depsgraph(C);
238         Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
239         Object *ob = CTX_data_active_object(C);
240         Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
241
242         /* if (ob && ob->type == OB_GPENCIL) BLI_assert(ob_eval->data == DEG_get_evaluated_id(ob->data)); */
243         return ED_gpencil_data_get_active_direct(screen_id, sa, scene_eval, ob_eval);
244 }
245
246 /* -------------------------------------------------------- */
247
248 /**
249  * Utility to check whether the r_ptr output of ED_gpencil_data_get_pointers()
250  * is for annotation usage.
251  */
252 bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr)
253 {
254         /* Key Assumption: If the pointer is an object, we're dealing with a GP Object's data.
255          * Otherwise, the GP datablock is being used for annotations (i.e. everywhere else)
256          */
257         return ((owner_ptr) && (owner_ptr->type != &RNA_Object));
258 }
259
260 /* -------------------------------------------------------- */
261
262 // XXX: this should be removed... We really shouldn't duplicate logic like this!
263 bGPdata *ED_gpencil_data_get_active_v3d(ViewLayer *view_layer, View3D *v3d)
264 {
265         Base *base = view_layer->basact;
266         bGPdata *gpd = NULL;
267
268         /* We have to make sure active object is actually visible and selected, else we must use default scene gpd,
269          * to be consistent with ED_gpencil_data_get_active's behavior.
270          */
271         if (base && BASE_SELECTED(v3d, base)) {
272                 if (base->object->type == OB_GPENCIL)
273                         gpd = base->object->data;
274         }
275         return gpd ? gpd : NULL;
276 }
277
278 /* ******************************************************** */
279 /* Keyframe Indicator Checks */
280
281 /* Check whether there's an active GP keyframe on the current frame */
282 bool ED_gpencil_has_keyframe_v3d(Scene *UNUSED(scene), Object *ob, int cfra)
283 {
284         if (ob && ob->data && (ob->type == OB_GPENCIL)) {
285                 bGPDlayer *gpl = BKE_gpencil_layer_getactive(ob->data);
286                 if (gpl) {
287                         if (gpl->actframe) {
288                                 // XXX: assumes that frame has been fetched already
289                                 return (gpl->actframe->framenum == cfra);
290                         }
291                         else {
292                                 /* XXX: disabled as could be too much of a penalty */
293                                 /* return BKE_gpencil_layer_find_frame(gpl, cfra); */
294                         }
295                 }
296         }
297
298         return false;
299 }
300
301 /* ******************************************************** */
302 /* Poll Callbacks */
303
304 /* poll callback for adding data/layers - special */
305 bool gp_add_poll(bContext *C)
306 {
307         /* the base line we have is that we have somewhere to add Grease Pencil data */
308         return ED_gpencil_data_get_pointers(C, NULL) != NULL;
309 }
310
311 /* poll callback for checking if there is an active layer */
312 bool gp_active_layer_poll(bContext *C)
313 {
314         bGPdata *gpd = ED_gpencil_data_get_active(C);
315         bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
316
317         return (gpl != NULL);
318 }
319
320 /* poll callback for checking if there is an active brush */
321 bool gp_active_brush_poll(bContext *C)
322 {
323         ToolSettings *ts = CTX_data_tool_settings(C);
324         Paint *paint = &ts->gp_paint->paint;
325         if (paint) {
326                 return (paint->brush != NULL);
327         }
328         else {
329                 return false;
330         }
331 }
332
333 /* ******************************************************** */
334 /* Dynamic Enums of GP Layers */
335 /* NOTE: These include an option to create a new layer and use that... */
336
337 /* Just existing layers */
338 const EnumPropertyItem *ED_gpencil_layers_enum_itemf(
339         bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
340 {
341         bGPdata *gpd = CTX_data_gpencil_data(C);
342         bGPDlayer *gpl;
343         EnumPropertyItem *item = NULL, item_tmp = {0};
344         int totitem = 0;
345         int i = 0;
346
347         if (ELEM(NULL, C, gpd)) {
348                 return DummyRNA_DEFAULT_items;
349         }
350
351         /* Existing layers */
352         for (gpl = gpd->layers.first; gpl; gpl = gpl->next, i++) {
353                 item_tmp.identifier = gpl->info;
354                 item_tmp.name = gpl->info;
355                 item_tmp.value = i;
356
357                 if (gpl->flag & GP_LAYER_ACTIVE)
358                         item_tmp.icon = ICON_GREASEPENCIL;
359                 else
360                         item_tmp.icon = ICON_NONE;
361
362                 RNA_enum_item_add(&item, &totitem, &item_tmp);
363         }
364
365         RNA_enum_item_end(&item, &totitem);
366         *r_free = true;
367
368         return item;
369 }
370
371 /* Existing + Option to add/use new layer */
372 const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(
373         bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
374 {
375         bGPdata *gpd = CTX_data_gpencil_data(C);
376         bGPDlayer *gpl;
377         EnumPropertyItem *item = NULL, item_tmp = {0};
378         int totitem = 0;
379         int i = 0;
380
381         if (ELEM(NULL, C, gpd)) {
382                 return DummyRNA_DEFAULT_items;
383         }
384
385         /* Create new layer */
386         /* TODO: have some way of specifying that we don't want this? */
387         {
388                 /* "New Layer" entry */
389                 item_tmp.identifier = "__CREATE__";
390                 item_tmp.name = "New Layer";
391                 item_tmp.value = -1;
392                 item_tmp.icon = ICON_ADD;
393                 RNA_enum_item_add(&item, &totitem, &item_tmp);
394
395                 /* separator */
396                 RNA_enum_item_add_separator(&item, &totitem);
397         }
398         const int tot = BLI_listbase_count(&gpd->layers);
399         /* Existing layers */
400         for (gpl = gpd->layers.last, i = 0; gpl; gpl = gpl->prev, i++) {
401                 item_tmp.identifier = gpl->info;
402                 item_tmp.name = gpl->info;
403                 item_tmp.value = tot - i - 1;
404
405                 if (gpl->flag & GP_LAYER_ACTIVE)
406                         item_tmp.icon = ICON_GREASEPENCIL;
407                 else
408                         item_tmp.icon = ICON_NONE;
409
410                 RNA_enum_item_add(&item, &totitem, &item_tmp);
411         }
412
413         RNA_enum_item_end(&item, &totitem);
414         *r_free = true;
415
416         return item;
417 }
418
419
420 /* ******************************************************** */
421 /* Brush Tool Core */
422
423 /**
424  * Check whether a given stroke segment is inside a circular brush
425  *
426  * \param mval: The current screen-space coordinates (midpoint) of the brush
427  * \param mvalo: The previous screen-space coordinates (midpoint) of the brush (NOT CURRENTLY USED)
428  * \param rad: The radius of the brush
429  *
430  * \param x0, y0: The screen-space x and y coordinates of the start of the stroke segment
431  * \param x1, y1: The screen-space x and y coordinates of the end of the stroke segment
432  */
433 bool gp_stroke_inside_circle(
434         const float mval[2], const float UNUSED(mvalo[2]),
435         int rad, int x0, int y0, int x1, int y1)
436 {
437         /* simple within-radius check for now */
438         const float screen_co_a[2] = {x0, y0};
439         const float screen_co_b[2] = {x1, y1};
440
441         if (edge_inside_circle(mval, rad, screen_co_a, screen_co_b)) {
442                 return true;
443         }
444
445         /* not inside */
446         return false;
447 }
448
449 /* ******************************************************** */
450 /* Stroke Validity Testing */
451
452 /* Check whether given stroke can be edited given the supplied context */
453 /* TODO: do we need additional flags for screenspace vs dataspace? */
454 bool ED_gpencil_stroke_can_use_direct(const ScrArea *sa, const bGPDstroke *gps)
455 {
456         /* sanity check */
457         if (ELEM(NULL, sa, gps))
458                 return false;
459
460         /* filter stroke types by flags + spacetype */
461         if (gps->flag & GP_STROKE_3DSPACE) {
462                 /* 3D strokes - only in 3D view */
463                 return ((sa->spacetype == SPACE_VIEW3D) || (sa->spacetype == SPACE_BUTS));
464         }
465         else if (gps->flag & GP_STROKE_2DIMAGE) {
466                 /* Special "image" strokes - only in Image Editor */
467                 return (sa->spacetype == SPACE_IMAGE);
468         }
469         else if (gps->flag & GP_STROKE_2DSPACE) {
470                 /* 2D strokes (dataspace) - for any 2D view (i.e. everything other than 3D view) */
471                 return (sa->spacetype != SPACE_VIEW3D);
472         }
473         else {
474                 /* view aligned - anything goes */
475                 return true;
476         }
477 }
478
479 /* Check whether given stroke can be edited in the current context */
480 bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps)
481 {
482         ScrArea *sa = CTX_wm_area(C);
483         return ED_gpencil_stroke_can_use_direct(sa, gps);
484 }
485
486 /* Check whether given stroke can be edited for the current color */
487 bool ED_gpencil_stroke_color_use(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps)
488 {
489         /* check if the color is editable */
490         MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
491
492         if (gp_style != NULL) {
493                 if (gp_style->flag & GP_STYLE_COLOR_HIDE)
494                         return false;
495                 if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (gp_style->flag & GP_STYLE_COLOR_LOCKED))
496                         return false;
497         }
498
499         return true;
500 }
501
502 /* ******************************************************** */
503 /* Space Conversion */
504
505 /**
506  * Init settings for stroke point space conversions
507  *
508  * \param r_gsc: [out] The space conversion settings struct, populated with necessary params
509  */
510 void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
511 {
512         ScrArea *sa = CTX_wm_area(C);
513         ARegion *ar = CTX_wm_region(C);
514
515         /* zero out the storage (just in case) */
516         memset(r_gsc, 0, sizeof(GP_SpaceConversion));
517         unit_m4(r_gsc->mat);
518
519         /* store settings */
520         r_gsc->scene = CTX_data_scene(C);
521         r_gsc->ob = CTX_data_active_object(C);
522
523         r_gsc->sa = sa;
524         r_gsc->ar = ar;
525         r_gsc->v2d = &ar->v2d;
526
527         /* init region-specific stuff */
528         if (sa->spacetype == SPACE_VIEW3D) {
529                 wmWindow *win = CTX_wm_window(C);
530                 Scene *scene = CTX_data_scene(C);
531                 struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
532                 View3D *v3d = (View3D *)CTX_wm_space_data(C);
533                 RegionView3D *rv3d = ar->regiondata;
534
535                 /* init 3d depth buffers */
536                 view3d_operator_needs_opengl(C);
537
538                 view3d_region_operator_needs_opengl(win, ar);
539                 ED_view3d_autodist_init(depsgraph, ar, v3d, 0);
540
541                 /* for camera view set the subrect */
542                 if (rv3d->persp == RV3D_CAMOB) {
543                         ED_view3d_calc_camera_border(scene, CTX_data_depsgraph(C), ar, v3d, rv3d, &r_gsc->subrect_data, true);
544                         r_gsc->subrect = &r_gsc->subrect_data;
545                 }
546         }
547 }
548
549 /**
550  * Convert point to parent space
551  *
552  * \param pt: Original point
553  * \param diff_mat: Matrix with the difference between original parent matrix
554  * \param[out] r_pt: Pointer to new point after apply matrix
555  */
556 void gp_point_to_parent_space(const bGPDspoint *pt, const float diff_mat[4][4], bGPDspoint *r_pt)
557 {
558         float fpt[3];
559
560         mul_v3_m4v3(fpt, diff_mat, &pt->x);
561         copy_v3_v3(&r_pt->x, fpt);
562 }
563
564 /**
565  * Change position relative to parent object
566  */
567 void gp_apply_parent(Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps)
568 {
569         bGPDspoint *pt;
570         int i;
571
572         /* undo matrix */
573         float diff_mat[4][4];
574         float inverse_diff_mat[4][4];
575         float fpt[3];
576
577         ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
578         invert_m4_m4(inverse_diff_mat, diff_mat);
579
580         for (i = 0; i < gps->totpoints; i++) {
581                 pt = &gps->points[i];
582                 mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x);
583                 copy_v3_v3(&pt->x, fpt);
584         }
585 }
586
587 /**
588  * Change point position relative to parent object
589  */
590 void gp_apply_parent_point(Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDspoint *pt)
591 {
592         /* undo matrix */
593         float diff_mat[4][4];
594         float inverse_diff_mat[4][4];
595         float fpt[3];
596
597         ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
598         invert_m4_m4(inverse_diff_mat, diff_mat);
599
600         mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x);
601         copy_v3_v3(&pt->x, fpt);
602 }
603
604 /**
605  * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D)
606  *
607  * \param[out] r_x  The screen-space x-coordinate of the point
608  * \param[out] r_y  The screen-space y-coordinate of the point
609  *
610  * \warning This assumes that the caller has already checked whether the stroke in question can be drawn.
611  */
612 void gp_point_to_xy(
613         const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt,
614         int *r_x, int *r_y)
615 {
616         const ARegion *ar = gsc->ar;
617         const View2D *v2d = gsc->v2d;
618         const rctf *subrect = gsc->subrect;
619         int xyval[2];
620
621         /* sanity checks */
622         BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D));
623         BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D));
624
625
626         if (gps->flag & GP_STROKE_3DSPACE) {
627                 if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
628                         *r_x = xyval[0];
629                         *r_y = xyval[1];
630                 }
631                 else {
632                         *r_x = V2D_IS_CLIPPED;
633                         *r_y = V2D_IS_CLIPPED;
634                 }
635         }
636         else if (gps->flag & GP_STROKE_2DSPACE) {
637                 float vec[3] = {pt->x, pt->y, 0.0f};
638                 mul_m4_v3(gsc->mat, vec);
639                 UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], r_x, r_y);
640         }
641         else {
642                 if (subrect == NULL) {
643                         /* normal 3D view (or view space) */
644                         *r_x = (int)(pt->x / 100 * ar->winx);
645                         *r_y = (int)(pt->y / 100 * ar->winy);
646                 }
647                 else {
648                         /* camera view, use subrect */
649                         *r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin;
650                         *r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin;
651                 }
652         }
653 }
654
655 /**
656  * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D)
657  *
658  * Just like gp_point_to_xy(), except the resulting coordinates are floats not ints.
659  * Use this version to solve "stair-step" artifacts which may arise when roundtripping the calculations.
660  *
661  * \param r_x: [out] The screen-space x-coordinate of the point
662  * \param r_y: [out] The screen-space y-coordinate of the point
663  *
664  * \warning This assumes that the caller has already checked whether the stroke in question can be drawn
665  */
666 void gp_point_to_xy_fl(
667         const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt,
668         float *r_x, float *r_y)
669 {
670         const ARegion *ar = gsc->ar;
671         const View2D *v2d = gsc->v2d;
672         const rctf *subrect = gsc->subrect;
673         float xyval[2];
674
675         /* sanity checks */
676         BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D));
677         BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D));
678
679
680         if (gps->flag & GP_STROKE_3DSPACE) {
681                 if (ED_view3d_project_float_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
682                         *r_x = xyval[0];
683                         *r_y = xyval[1];
684                 }
685                 else {
686                         *r_x = 0.0f;
687                         *r_y = 0.0f;
688                 }
689         }
690         else if (gps->flag & GP_STROKE_2DSPACE) {
691                 float vec[3] = {pt->x, pt->y, 0.0f};
692                 int t_x, t_y;
693
694                 mul_m4_v3(gsc->mat, vec);
695                 UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y);
696
697                 if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) {
698                         /* XXX: Or should we just always use the values as-is? */
699                         *r_x = 0.0f;
700                         *r_y = 0.0f;
701                 }
702                 else {
703                         *r_x = (float)t_x;
704                         *r_y = (float)t_y;
705                 }
706         }
707         else {
708                 if (subrect == NULL) {
709                         /* normal 3D view (or view space) */
710                         *r_x = (pt->x / 100.0f * ar->winx);
711                         *r_y = (pt->y / 100.0f * ar->winy);
712                 }
713                 else {
714                         /* camera view, use subrect */
715                         *r_x = ((pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
716                         *r_y = ((pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
717                 }
718         }
719 }
720
721
722 /**
723 * generic based on gp_point_to_xy_fl
724 */
725 void gp_point_3d_to_xy(const GP_SpaceConversion *gsc, const short flag, const float pt[3], float xy[2])
726 {
727         const ARegion *ar = gsc->ar;
728         const View2D *v2d = gsc->v2d;
729         const rctf *subrect = gsc->subrect;
730         float xyval[2];
731
732         /* sanity checks */
733         BLI_assert((gsc->sa->spacetype == SPACE_VIEW3D));
734
735         if (flag & GP_STROKE_3DSPACE) {
736                 if (ED_view3d_project_float_global(ar, pt, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
737                         xy[0] = xyval[0];
738                         xy[1] = xyval[1];
739                 }
740                 else {
741                         xy[0] = 0.0f;
742                         xy[1] = 0.0f;
743                 }
744         }
745         else if (flag & GP_STROKE_2DSPACE) {
746                 float vec[3] = { pt[0], pt[1], 0.0f };
747                 int t_x, t_y;
748
749                 mul_m4_v3(gsc->mat, vec);
750                 UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y);
751
752                 if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) {
753                         /* XXX: Or should we just always use the values as-is? */
754                         xy[0] = 0.0f;
755                         xy[1] = 0.0f;
756                 }
757                 else {
758                         xy[0] = (float)t_x;
759                         xy[1] = (float)t_y;
760                 }
761         }
762         else {
763                 if (subrect == NULL) {
764                         /* normal 3D view (or view space) */
765                         xy[0] = (pt[0] / 100.0f * ar->winx);
766                         xy[1] = (pt[1] / 100.0f * ar->winy);
767                 }
768                 else {
769                         /* camera view, use subrect */
770                         xy[0] = ((pt[0] / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
771                         xy[1] = ((pt[1] / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
772                 }
773         }
774 }
775
776
777 /**
778  * Project screenspace coordinates to 3D-space
779  *
780  * For use with editing tools where it is easier to perform the operations in 2D,
781  * and then later convert the transformed points back to 3D.
782  *
783  * \param screen_co: The screenspace 2D coordinates to convert to
784  * \param r_out: The resulting 3D coordinates of the input point
785  *
786  * \note We include this as a utility function, since the standard method
787  * involves quite a few steps, which are invariably always the same
788  * for all GPencil operations. So, it's nicer to just centralize these.
789  *
790  * \warning Assumes that it is getting called in a 3D view only.
791  */
792 bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc, Scene *scene, const float screen_co[2], float r_out[3])
793 {
794         const RegionView3D *rv3d = gsc->ar->regiondata;
795         float rvec[3];
796
797         ED_gp_get_drawing_reference(scene, gsc->ob, gsc->gpl,
798                 scene->toolsettings->gpencil_v3d_align, rvec);
799
800         float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
801
802         float mval_f[2], mval_prj[2];
803         float dvec[3];
804
805         copy_v2_v2(mval_f, screen_co);
806
807         if (ED_view3d_project_float_global(gsc->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
808                 sub_v2_v2v2(mval_f, mval_prj, mval_f);
809                 ED_view3d_win_to_delta(gsc->ar, mval_f, dvec, zfac);
810                 sub_v3_v3v3(r_out, rvec, dvec);
811
812                 return true;
813         }
814         else {
815                 zero_v3(r_out);
816
817                 return false;
818         }
819 }
820
821 /**
822  * Convert tGPspoint (temporary 2D/screenspace point data used by GP modal operators)
823  * to 3D coordinates.
824  *
825  * \param point2D: The screenspace 2D point data to convert
826  * \param depth: Depth array (via ED_view3d_autodist_depth())
827  * \param[out] r_out: The resulting 2D point data
828  */
829 void gp_stroke_convertcoords_tpoint(
830         Scene *scene, ARegion *ar,
831         Object *ob, bGPDlayer *gpl,
832         const tGPspoint *point2D, float *depth,
833         float r_out[3])
834 {
835         ToolSettings *ts = scene->toolsettings;
836
837         int mval_i[2];
838         round_v2i_v2fl(mval_i, &point2D->x);
839
840         if ((depth != NULL) && (ED_view3d_autodist_simple(ar, mval_i, r_out, 0, depth))) {
841                 /* projecting onto 3D-Geometry
842                  * - nothing more needs to be done here, since view_autodist_simple() has already done it
843                  */
844         }
845         else {
846                 float mval_f[2] = {point2D->x, point2D->y};
847                 float mval_prj[2];
848                 float rvec[3], dvec[3];
849                 float zfac;
850
851                 /* Current method just converts each point in screen-coordinates to
852                  * 3D-coordinates using the 3D-cursor as reference.
853                  */
854                 ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, rvec);
855                 zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
856
857                 if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
858                         sub_v2_v2v2(mval_f, mval_prj, mval_f);
859                         ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
860                         sub_v3_v3v3(r_out, rvec, dvec);
861                 }
862                 else {
863                         zero_v3(r_out);
864                 }
865         }
866 }
867
868 /**
869  * Get drawing reference point for conversion or projection of the stroke
870  * \param[out] r_vec : Reference point found
871  */
872 void ED_gp_get_drawing_reference(
873         const Scene *scene, const Object *ob, bGPDlayer *UNUSED(gpl),
874         char align_flag, float r_vec[3])
875 {
876         const float *fp = scene->cursor.location;
877
878         /* if using a gpencil object at cursor mode, can use the location of the object */
879         if (align_flag & GP_PROJECT_VIEWSPACE) {
880                 if (ob && (ob->type == OB_GPENCIL)) {
881                         /* fallback (no strokes) - use cursor or object location */
882                         if (align_flag & GP_PROJECT_CURSOR) {
883                                 /* use 3D-cursor */
884                                 copy_v3_v3(r_vec, fp);
885                         }
886                         else {
887                                 /* use object location */
888                                 copy_v3_v3(r_vec, ob->obmat[3]);
889                         }
890                 }
891         }
892         else {
893                 /* use 3D-cursor */
894                 copy_v3_v3(r_vec, fp);
895         }
896 }
897
898 void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *gps)
899 {
900         Scene *scene = CTX_data_scene(C);
901         Depsgraph *depsgraph = CTX_data_depsgraph(C);
902         Object *ob = CTX_data_active_object(C);
903         bGPdata *gpd = (bGPdata *)ob->data;
904         GP_SpaceConversion gsc = { NULL };
905
906         bGPDspoint *pt;
907         int i;
908         float diff_mat[4][4];
909         float inverse_diff_mat[4][4];
910
911         /* init space conversion stuff */
912         gp_point_conversion_init(C, &gsc);
913
914         ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
915         invert_m4_m4(inverse_diff_mat, diff_mat);
916
917         /* Adjust each point */
918         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
919                 float xy[2];
920
921                 bGPDspoint pt2;
922                 gp_point_to_parent_space(pt, diff_mat, &pt2);
923                 gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
924
925                 /* Planar - All on same plane parallel to the viewplane */
926                 gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
927
928                 /* Unapply parent corrections */
929                 mul_m4_v3(inverse_diff_mat, &pt->x);
930         }
931 }
932
933 /**
934  * Reproject all points of the stroke to a plane locked to axis to avoid stroke offset
935  */
936 void ED_gp_project_stroke_to_plane(
937         const Object *ob, const RegionView3D *rv3d, bGPDstroke *gps, const float origin[3], const int axis)
938 {
939         float plane_normal[3];
940         float vn[3];
941
942         float ray[3];
943         float rpoint[3];
944
945         /* normal vector for a plane locked to axis */
946         zero_v3(plane_normal);
947         if (axis < 0) {
948                 /* if the axis is not locked, need a vector to the view direction
949                  * in order to get the right size of the stroke.
950                  */
951                 ED_view3d_global_to_vector(rv3d, origin, plane_normal);
952         }
953         else {
954                 plane_normal[axis] = 1.0f;
955                 /* if object, apply object rotation */
956                 if (ob && (ob->type == OB_GPENCIL)) {
957                         mul_mat3_m4_v3(ob->obmat, plane_normal);
958                 }
959         }
960
961         /* Reproject the points in the plane */
962         for (int i = 0; i < gps->totpoints; i++) {
963                 bGPDspoint *pt = &gps->points[i];
964
965                 /* get a vector from the point with the current view direction of the viewport */
966                 ED_view3d_global_to_vector(rv3d, &pt->x, vn);
967
968                 /* calculate line extreme point to create a ray that cross the plane */
969                 mul_v3_fl(vn, -50.0f);
970                 add_v3_v3v3(ray, &pt->x, vn);
971
972                 /* if the line never intersect, the point is not changed */
973                 if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
974                         copy_v3_v3(&pt->x, rpoint);
975                 }
976         }
977 }
978
979 /**
980  * Reproject given point to a plane locked to axis to avoid stroke offset
981  * \param[in, out] pt : Point to affect
982  */
983 void ED_gp_project_point_to_plane(
984         const Object *ob, const RegionView3D *rv3d, const float origin[3], const int axis, bGPDspoint *pt)
985 {
986         float plane_normal[3];
987         float vn[3];
988
989         float ray[3];
990         float rpoint[3];
991
992         /* normal vector for a plane locked to axis */
993         zero_v3(plane_normal);
994         if (axis < 0) {
995                 /* if the axis is not locked, need a vector to the view direction
996                  * in order to get the right size of the stroke.
997                  */
998                 ED_view3d_global_to_vector(rv3d, origin, plane_normal);
999         }
1000         else {
1001                 plane_normal[axis] = 1.0f;
1002                 /* if object, apply object rotation */
1003                 if (ob && (ob->type == OB_GPENCIL)) {
1004                         mul_mat3_m4_v3(ob->obmat, plane_normal);
1005                 }
1006         }
1007
1008
1009         /* Reproject the points in the plane */
1010         /* get a vector from the point with the current view direction of the viewport */
1011         ED_view3d_global_to_vector(rv3d, &pt->x, vn);
1012
1013         /* calculate line extrem point to create a ray that cross the plane */
1014         mul_v3_fl(vn, -50.0f);
1015         add_v3_v3v3(ray, &pt->x, vn);
1016
1017         /* if the line never intersect, the point is not changed */
1018         if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
1019                 copy_v3_v3(&pt->x, rpoint);
1020         }
1021 }
1022
1023 /* ******************************************************** */
1024 /* Stroke Operations */
1025 // XXX: Check if these functions duplicate stuff in blenkernel, and/or whether we should just deduplicate
1026
1027 /**
1028  * Subdivide a stroke once, by adding a point half way between each pair of existing points
1029  * \param gps: Stroke data
1030  * \param subdivide: Number of times to subdivide
1031  */
1032 void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
1033 {
1034         bGPDspoint *temp_points;
1035         int totnewpoints, oldtotpoints;
1036         int i2;
1037
1038         /* loop as many times as levels */
1039         for (int s = 0; s < subdivide; s++) {
1040                 totnewpoints = gps->totpoints - 1;
1041                 /* duplicate points in a temp area */
1042                 temp_points = MEM_dupallocN(gps->points);
1043                 oldtotpoints = gps->totpoints;
1044
1045                 /* resize the points arrays */
1046                 gps->totpoints += totnewpoints;
1047                 gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
1048                 if (gps->dvert != NULL) {
1049                         gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
1050                 }
1051                 gps->flag |= GP_STROKE_RECALC_GEOMETRY;
1052
1053                 /* move points from last to first to new place */
1054                 i2 = gps->totpoints - 1;
1055                 for (int i = oldtotpoints - 1; i > 0; i--) {
1056                         bGPDspoint *pt = &temp_points[i];
1057                         bGPDspoint *pt_final = &gps->points[i2];
1058
1059                         copy_v3_v3(&pt_final->x, &pt->x);
1060                         pt_final->pressure = pt->pressure;
1061                         pt_final->strength = pt->strength;
1062                         pt_final->time = pt->time;
1063                         pt_final->flag = pt->flag;
1064                         pt_final->uv_fac = pt->uv_fac;
1065                         pt_final->uv_rot = pt->uv_rot;
1066
1067                         if (gps->dvert != NULL) {
1068                                 MDeformVert *dvert = &gps->dvert[i];
1069                                 MDeformVert *dvert_final = &gps->dvert[i2];
1070
1071                                 dvert_final->totweight = dvert->totweight;
1072                                 dvert_final->dw = dvert->dw;
1073                         }
1074
1075                         i2 -= 2;
1076                 }
1077                 /* interpolate mid points */
1078                 i2 = 1;
1079                 for (int i = 0; i < oldtotpoints - 1; i++) {
1080                         bGPDspoint *pt = &temp_points[i];
1081                         bGPDspoint *next = &temp_points[i + 1];
1082                         bGPDspoint *pt_final = &gps->points[i2];
1083
1084                         /* add a half way point */
1085                         interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
1086                         pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
1087                         pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
1088                         CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
1089                         pt_final->time = interpf(pt->time, next->time, 0.5f);
1090                         pt_final->uv_fac = interpf(pt->uv_fac, next->uv_fac, 0.5f);
1091                         pt_final->uv_rot = interpf(pt->uv_rot, next->uv_rot, 0.5f);
1092
1093                         if (gps->dvert != NULL) {
1094                                 MDeformVert *dvert_final = &gps->dvert[i2];
1095                                 dvert_final->totweight = 0;
1096                                 dvert_final->dw = NULL;
1097                         }
1098
1099                         i2 += 2;
1100                 }
1101
1102                 MEM_SAFE_FREE(temp_points);
1103
1104                 /* move points to smooth stroke */
1105                 /* duplicate points in a temp area with the new subdivide data */
1106                 temp_points = MEM_dupallocN(gps->points);
1107
1108                 /* extreme points are not changed */
1109                 for (int i = 0; i < gps->totpoints - 2; i++) {
1110                         bGPDspoint *pt = &temp_points[i];
1111                         bGPDspoint *next = &temp_points[i + 1];
1112                         bGPDspoint *pt_final = &gps->points[i + 1];
1113
1114                         /* move point */
1115                         interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
1116                 }
1117                 /* free temp memory */
1118                 MEM_SAFE_FREE(temp_points);
1119         }
1120 }
1121
1122 /**
1123  * Add randomness to stroke
1124  * \param gps: Stroke data
1125  * \param brush: Brush data
1126  */
1127 void gp_randomize_stroke(bGPDstroke *gps, Brush *brush, RNG *rng)
1128 {
1129         bGPDspoint *pt1, *pt2, *pt3;
1130         float v1[3];
1131         float v2[3];
1132         if (gps->totpoints < 3) {
1133                 return;
1134         }
1135
1136         /* get two vectors using 3 points */
1137         pt1 = &gps->points[0];
1138         pt2 = &gps->points[1];
1139         pt3 = &gps->points[(int)(gps->totpoints * 0.75)];
1140
1141         sub_v3_v3v3(v1, &pt2->x, &pt1->x);
1142         sub_v3_v3v3(v2, &pt3->x, &pt2->x);
1143         normalize_v3(v1);
1144         normalize_v3(v2);
1145
1146         /* get normal vector to plane created by two vectors */
1147         float normal[3];
1148         cross_v3_v3v3(normal, v1, v2);
1149         normalize_v3(normal);
1150
1151         /* get orthogonal vector to plane to rotate random effect */
1152         float ortho[3];
1153         cross_v3_v3v3(ortho, v1, normal);
1154         normalize_v3(ortho);
1155
1156         /* Read all points and apply shift vector (first and last point not modified) */
1157         for (int i = 1; i < gps->totpoints - 1; i++) {
1158                 bGPDspoint *pt = &gps->points[i];
1159                 /* get vector with shift (apply a division because random is too sensitive */
1160                 const float fac = BLI_rng_get_float(rng) * (brush->gpencil_settings->draw_random_sub / 10.0f);
1161                 float svec[3];
1162                 copy_v3_v3(svec, ortho);
1163                 if (BLI_rng_get_float(rng) > 0.5f) {
1164                         mul_v3_fl(svec, -fac);
1165                 }
1166                 else {
1167                         mul_v3_fl(svec, fac);
1168                 }
1169
1170                 /* apply shift */
1171                 add_v3_v3(&pt->x, svec);
1172         }
1173 }
1174
1175 /* ******************************************************** */
1176 /* Layer Parenting  - Compute Parent Transforms */
1177
1178 /* calculate difference matrix */
1179 void ED_gpencil_parent_location(
1180         const Depsgraph *depsgraph, Object *obact, bGPdata *UNUSED(gpd),
1181         bGPDlayer *gpl, float diff_mat[4][4])
1182 {
1183         Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact;
1184         Object *obparent = gpl->parent;
1185         Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) : obparent;
1186
1187         /* if not layer parented, try with object parented */
1188         if (obparent_eval == NULL) {
1189                 if (ob_eval != NULL) {
1190                         if (ob_eval->type == OB_GPENCIL) {
1191                                 copy_m4_m4(diff_mat, ob_eval->obmat);
1192                                 return;
1193                         }
1194                 }
1195                 /* not gpencil object */
1196                 unit_m4(diff_mat);
1197                 return;
1198         }
1199         else {
1200                 if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
1201                         mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
1202                         return;
1203                 }
1204                 else if (gpl->partype == PARBONE) {
1205                         bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr);
1206                         if (pchan) {
1207                                 float tmp_mat[4][4];
1208                                 mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat);
1209                                 mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse);
1210                         }
1211                         else {
1212                                 /* if bone not found use object (armature) */
1213                                 mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
1214                         }
1215                         return;
1216                 }
1217                 else {
1218                         unit_m4(diff_mat); /* not defined type */
1219                 }
1220         }
1221 }
1222
1223 /* reset parent matrix for all layers */
1224 void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata *gpd)
1225 {
1226         bGPDspoint *pt;
1227         int i;
1228         float diff_mat[4][4];
1229         float cur_mat[4][4];
1230
1231         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1232                 if (gpl->parent != NULL) {
1233                         /* calculate new matrix */
1234                         if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
1235                                 invert_m4_m4(cur_mat, gpl->parent->obmat);
1236                         }
1237                         else if (gpl->partype == PARBONE) {
1238                                 bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr);
1239                                 if (pchan) {
1240                                         float tmp_mat[4][4];
1241                                         mul_m4_m4m4(tmp_mat, gpl->parent->obmat, pchan->pose_mat);
1242                                         invert_m4_m4(cur_mat, tmp_mat);
1243                                 }
1244                         }
1245
1246                         /* only redo if any change */
1247                         if (!equals_m4m4(gpl->inverse, cur_mat)) {
1248                                 /* first apply current transformation to all strokes */
1249                                 ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
1250                                 for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1251                                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1252                                                 for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1253                                                         mul_m4_v3(diff_mat, &pt->x);
1254                                                 }
1255                                         }
1256                                 }
1257                                 /* set new parent matrix */
1258                                 copy_m4_m4(gpl->inverse, cur_mat);
1259                         }
1260                 }
1261         }
1262 }
1263 /* ******************************************************** */
1264 /* GP Object Stuff */
1265
1266 /* Helper function to create new OB_GPENCIL Object */
1267 Object *ED_gpencil_add_object(bContext *C, Scene *UNUSED(scene), const float loc[3], ushort local_view_bits)
1268 {
1269         float rot[3] = {0.0f};
1270
1271         Object *ob = ED_object_add_type(C, OB_GPENCIL, NULL, loc, rot, false, local_view_bits);
1272
1273         /* define size */
1274         BKE_object_obdata_size_init(ob, GP_OBGPENCIL_DEFAULT_SIZE);
1275         /* create default brushes and colors */
1276         ED_gpencil_add_defaults(C, ob);
1277
1278         return ob;
1279 }
1280
1281 /* Helper function to create default colors and drawing brushes */
1282 void ED_gpencil_add_defaults(bContext *C, Object *ob)
1283 {
1284         Main *bmain = CTX_data_main(C);
1285         ToolSettings *ts = CTX_data_tool_settings(C);
1286
1287         /* first try to reuse default material */
1288         if (ob->actcol > 0) {
1289                 Material *ma = give_current_material(ob, ob->actcol);
1290                 if ((ma) && (ma->gp_style == NULL)) {
1291                         BKE_material_init_gpencil_settings(ma);
1292                 }
1293         }
1294
1295         /* ensure color exist */
1296         BKE_gpencil_material_ensure(bmain, ob);
1297
1298         BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
1299         Paint *paint = &ts->gp_paint->paint;
1300         /* if not exist, create a new one */
1301         if (paint->brush == NULL) {
1302                 /* create new brushes */
1303                 BKE_brush_gpencil_presets(C);
1304         }
1305
1306         /* ensure multiframe falloff curve */
1307         if (ts->gp_sculpt.cur_falloff == NULL) {
1308                 ts->gp_sculpt.cur_falloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
1309                 CurveMapping *gp_falloff_curve = ts->gp_sculpt.cur_falloff;
1310                 curvemapping_initialize(gp_falloff_curve);
1311                 curvemap_reset(
1312                         gp_falloff_curve->cm,
1313                         &gp_falloff_curve->clipr,
1314                         CURVE_PRESET_GAUSS,
1315                         CURVEMAP_SLOPE_POSITIVE);
1316         }
1317 }
1318
1319 /* ******************************************************** */
1320 /* Vertex Groups */
1321
1322 /* assign points to vertex group */
1323 void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight)
1324 {
1325         bGPdata *gpd = (bGPdata *)ob->data;
1326         const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1327         const int def_nr = ob->actdef - 1;
1328         if (!BLI_findlink(&ob->defbase, def_nr))
1329                 return;
1330
1331         CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
1332         {
1333                 bGPDframe *init_gpf = gpl->actframe;
1334                 bGPDstroke *gps = NULL;
1335                 if (is_multiedit) {
1336                         init_gpf = gpl->frames.first;
1337                 }
1338
1339                 for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1340                         if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1341                                 if (gpf == NULL)
1342                                         continue;
1343
1344                                 for (gps = gpf->strokes.first; gps; gps = gps->next) {
1345
1346                                         /* skip strokes that are invalid for current view */
1347                                         if (ED_gpencil_stroke_can_use(C, gps) == false)
1348                                                 continue;
1349
1350                                         if (gps->flag & GP_STROKE_SELECT) {
1351                                                 /* verify the weight array is created */
1352                                                 BKE_gpencil_dvert_ensure(gps);
1353
1354                                                 for (int i = 0; i < gps->totpoints; i++) {
1355                                                         bGPDspoint *pt = &gps->points[i];
1356                                                         MDeformVert *dvert = &gps->dvert[i];
1357                                                         if (pt->flag & GP_SPOINT_SELECT) {
1358                                                                 MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
1359                                                                 if (dw) {
1360                                                                         dw->weight = weight;
1361                                                                 }
1362                                                         }
1363                                                 }
1364                                         }
1365                                 }
1366                         }
1367
1368                         /* if not multiedit, exit loop*/
1369                         if (!is_multiedit) {
1370                                 break;
1371                         }
1372                 }
1373         }
1374         CTX_DATA_END;
1375 }
1376
1377 /* remove points from vertex group */
1378 void ED_gpencil_vgroup_remove(bContext *C, Object *ob)
1379 {
1380         bGPdata *gpd = (bGPdata *)ob->data;
1381         const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1382         const int def_nr = ob->actdef - 1;
1383         if (!BLI_findlink(&ob->defbase, def_nr))
1384                 return;
1385
1386         CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
1387         {
1388                 bGPDframe *init_gpf = gpl->actframe;
1389                 bGPDstroke *gps = NULL;
1390                 if (is_multiedit) {
1391                         init_gpf = gpl->frames.first;
1392                 }
1393
1394                 for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1395                         if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1396                                 if (gpf == NULL)
1397                                         continue;
1398
1399                                 for (gps = gpf->strokes.first; gps; gps = gps->next) {
1400
1401                                         /* skip strokes that are invalid for current view */
1402                                         if (ED_gpencil_stroke_can_use(C, gps) == false)
1403                                                 continue;
1404
1405                                         for (int i = 0; i < gps->totpoints; i++) {
1406                                                 bGPDspoint *pt = &gps->points[i];
1407                                                 if (gps->dvert == NULL) {
1408                                                         continue;
1409                                                 }
1410                                                 MDeformVert *dvert = &gps->dvert[i];
1411
1412                                                 if ((pt->flag & GP_SPOINT_SELECT) && (dvert->totweight > 0)) {
1413                                                         MDeformWeight *dw = defvert_find_index(dvert, def_nr);
1414                                                         if (dw != NULL) {
1415                                                                 defvert_remove_group(dvert, dw);
1416                                                         }
1417                                                 }
1418                                         }
1419                                 }
1420                         }
1421
1422                         /* if not multiedit, exit loop*/
1423                         if (!is_multiedit) {
1424                                 break;
1425                         }
1426                 }
1427         }
1428         CTX_DATA_END;
1429 }
1430
1431 /* select points of vertex group */
1432 void ED_gpencil_vgroup_select(bContext *C, Object *ob)
1433 {
1434         bGPdata *gpd = (bGPdata *)ob->data;
1435         const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1436         const int def_nr = ob->actdef - 1;
1437         if (!BLI_findlink(&ob->defbase, def_nr))
1438                 return;
1439
1440         CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
1441         {
1442                 bGPDframe *init_gpf = gpl->actframe;
1443                 bGPDstroke *gps = NULL;
1444                 if (is_multiedit) {
1445                         init_gpf = gpl->frames.first;
1446                 }
1447
1448                 for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1449                         if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1450                                 if (gpf == NULL)
1451                                         continue;
1452
1453                                 for (gps = gpf->strokes.first; gps; gps = gps->next) {
1454
1455                                         /* skip strokes that are invalid for current view */
1456                                         if (ED_gpencil_stroke_can_use(C, gps) == false)
1457                                                 continue;
1458
1459                                         for (int i = 0; i < gps->totpoints; i++) {
1460                                                 bGPDspoint *pt = &gps->points[i];
1461                                                 if (gps->dvert == NULL) {
1462                                                         continue;
1463                                                 }
1464                                                 MDeformVert *dvert = &gps->dvert[i];
1465
1466                                                 if (defvert_find_index(dvert, def_nr) != NULL) {
1467                                                         pt->flag |= GP_SPOINT_SELECT;
1468                                                         gps->flag |= GP_STROKE_SELECT;
1469                                                 }
1470                                         }
1471                                 }
1472                         }
1473
1474                         /* if not multiedit, exit loop*/
1475                         if (!is_multiedit) {
1476                                 break;
1477                         }
1478                 }
1479         }
1480         CTX_DATA_END;
1481 }
1482
1483 /* unselect points of vertex group */
1484 void ED_gpencil_vgroup_deselect(bContext *C, Object *ob)
1485 {
1486         bGPdata *gpd = (bGPdata *)ob->data;
1487         const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1488         const int def_nr = ob->actdef - 1;
1489         if (!BLI_findlink(&ob->defbase, def_nr))
1490                 return;
1491
1492         CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
1493         {
1494                 bGPDframe *init_gpf = gpl->actframe;
1495                 bGPDstroke *gps = NULL;
1496                 if (is_multiedit) {
1497                         init_gpf = gpl->frames.first;
1498                 }
1499
1500                 for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1501                         if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1502                                 if (gpf == NULL)
1503                                         continue;
1504
1505                                 for (gps = gpf->strokes.first; gps; gps = gps->next) {
1506
1507                                         /* skip strokes that are invalid for current view */
1508                                         if (ED_gpencil_stroke_can_use(C, gps) == false)
1509                                                 continue;
1510
1511                                         for (int i = 0; i < gps->totpoints; i++) {
1512                                                 bGPDspoint *pt = &gps->points[i];
1513                                                 if (gps->dvert == NULL) {
1514                                                         continue;
1515                                                 }
1516                                                 MDeformVert *dvert = &gps->dvert[i];
1517
1518                                                 if (defvert_find_index(dvert, def_nr) != NULL) {
1519                                                         pt->flag &= ~GP_SPOINT_SELECT;
1520                                                 }
1521                                         }
1522                                 }
1523                         }
1524
1525                         /* if not multiedit, exit loop*/
1526                         if (!is_multiedit) {
1527                                 break;
1528                         }
1529                 }
1530         }
1531         CTX_DATA_END;
1532 }
1533
1534 /* ******************************************************** */
1535 /* Cursor drawing */
1536
1537 /* check if cursor is in drawing region */
1538 static bool gp_check_cursor_region(bContext *C, int mval_i[2])
1539 {
1540         ARegion *ar = CTX_wm_region(C);
1541         ScrArea *sa = CTX_wm_area(C);
1542         Object *ob = CTX_data_active_object(C);
1543
1544         if ((ob == NULL) ||
1545             (!ELEM(ob->mode, OB_MODE_PAINT_GPENCIL, OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL)))
1546         {
1547                 return false;
1548         }
1549
1550         /* TODO: add more spacetypes */
1551         if (!ELEM(sa->spacetype, SPACE_VIEW3D)) {
1552                 return false;
1553         }
1554         if ((ar) && (ar->regiontype != RGN_TYPE_WINDOW)) {
1555                 return false;
1556         }
1557         else if (ar) {
1558                 return BLI_rcti_isect_pt_v(&ar->winrct, mval_i);
1559         }
1560         else {
1561                 return false;
1562         }
1563 }
1564
1565 /* draw eraser cursor */
1566 void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y)
1567 {
1568         short radius = (short)brush->size;
1569
1570         GPUVertFormat *format = immVertexFormat();
1571         const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1572         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1573
1574         glEnable(GL_LINE_SMOOTH);
1575         glEnable(GL_BLEND);
1576         glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1577
1578         immUniformColor4ub(255, 100, 100, 20);
1579         imm_draw_circle_fill_2d(shdr_pos, x, y, radius, 40);
1580
1581         immUnbindProgram();
1582
1583         immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
1584
1585         float viewport_size[4];
1586         glGetFloatv(GL_VIEWPORT, viewport_size);
1587         immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
1588
1589         immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
1590         immUniform1i("colors_len", 0);  /* "simple" mode */
1591         immUniform1f("dash_width", 12.0f);
1592         immUniform1f("dash_factor", 0.5f);
1593
1594         imm_draw_circle_wire_2d(
1595                 shdr_pos, x, y, radius,
1596                 /* XXX Dashed shader gives bad results with sets of small segments currently,
1597                  *     temp hack around the issue. :( */
1598                 max_ii(8, radius / 2));  /* was fixed 40 */
1599
1600         immUnbindProgram();
1601
1602         glDisable(GL_BLEND);
1603         glDisable(GL_LINE_SMOOTH);
1604 }
1605
1606 static bool gp_brush_cursor_poll(bContext *C)
1607 {
1608    if (WM_toolsystem_active_tool_is_brush(C)) {
1609        return true;
1610    }
1611    return false;
1612 }
1613
1614 /* Helper callback for drawing the cursor itself */
1615 static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata)
1616 {
1617         Main *bmain = CTX_data_main(C);
1618         Scene *scene = CTX_data_scene(C);
1619         Object *ob = CTX_data_active_object(C);
1620         ARegion *ar = CTX_wm_region(C);
1621
1622         GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
1623         bGPdata *gpd = ED_gpencil_data_get_active(C);
1624         GP_Sculpt_Data *gp_brush = NULL;
1625         Brush *brush = NULL;
1626         Material *ma = NULL;
1627         MaterialGPencilStyle *gp_style = NULL;
1628         float *last_mouse_position = customdata;
1629
1630         if ((gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE)) {
1631                 gp_brush = &gset->brush[gset->weighttype];
1632         }
1633         else {
1634                 gp_brush = &gset->brush[gset->brushtype];
1635         }
1636
1637         /* default radius and color */
1638         float color[3] = {1.0f, 1.0f, 1.0f};
1639         float darkcolor[3];
1640         float radius = 3.0f;
1641
1642         int mval_i[2] = {x, y};
1643         /* check if cursor is in drawing region and has valid datablock */
1644         if ((!gp_check_cursor_region(C, mval_i)) || (gpd == NULL)) {
1645                 return;
1646         }
1647
1648         /* for paint use paint brush size and color */
1649         if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
1650                 brush = scene->toolsettings->gp_paint->paint.brush;
1651                 /* while drawing hide */
1652                 if ((gpd->runtime.sbuffer_size > 0) &&
1653                     (brush) && ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
1654                     ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0))
1655                 {
1656                         return;
1657                 }
1658
1659                 if (brush) {
1660                         if ((brush->gpencil_settings->flag & GP_BRUSH_ENABLE_CURSOR) == 0) {
1661                                 return;
1662                         }
1663
1664                         /* eraser has special shape and use a different shader program */
1665                         if (brush->gpencil_tool == GPAINT_TOOL_ERASE) {
1666                                 ED_gpencil_brush_draw_eraser(brush, x, y);
1667                                 return;
1668                         }
1669
1670                         /* get current drawing color */
1671                         ma = BKE_gpencil_get_material_from_brush(brush);
1672                         if (ma == NULL) {
1673                                 BKE_gpencil_material_ensure(bmain, ob);
1674                                 /* assign the first material to the brush */
1675                                 ma = give_current_material(ob, 1);
1676                                 brush->gpencil_settings->material = ma;
1677                         }
1678                         gp_style = ma->gp_style;
1679
1680                         /* after some testing, display the size of the brush is not practical because
1681                          * is too disruptive and the size of cursor does not change with zoom factor.
1682                          * The decision was to use a fix size, instead of brush->thickness value.
1683                          */
1684                         if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
1685                             ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
1686                             ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
1687                             (brush->gpencil_tool == GPAINT_TOOL_DRAW))
1688                         {
1689                                 radius = 2.0f;
1690                                 copy_v3_v3(color, gp_style->stroke_rgba);
1691                         }
1692                         else {
1693                                 radius = 5.0f;
1694                                 copy_v3_v3(color, brush->add_col);
1695                         }
1696                 }
1697                 else {
1698                         return;
1699                 }
1700         }
1701
1702         /* for sculpt use sculpt brush size */
1703         if (GPENCIL_SCULPT_OR_WEIGHT_MODE(gpd)) {
1704                 if (gp_brush) {
1705                         if ((gp_brush->flag & GP_SCULPT_FLAG_ENABLE_CURSOR) == 0) {
1706                                 return;
1707                         }
1708
1709                         radius = gp_brush->size;
1710                         if (gp_brush->flag & (GP_SCULPT_FLAG_INVERT | GP_SCULPT_FLAG_TMP_INVERT)) {
1711                                 copy_v3_v3(color, gp_brush->curcolor_sub);
1712                         }
1713                         else {
1714                                 copy_v3_v3(color, gp_brush->curcolor_add);
1715                         }
1716                 }
1717         }
1718
1719         /* draw icon */
1720         GPUVertFormat *format = immVertexFormat();
1721         uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1722         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1723
1724         glEnable(GL_LINE_SMOOTH);
1725         glEnable(GL_BLEND);
1726
1727         /* Inner Ring: Color from UI panel */
1728         immUniformColor4f(color[0], color[1], color[2], 0.8f);
1729         if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
1730             ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
1731             ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
1732             (brush->gpencil_tool == GPAINT_TOOL_DRAW))
1733         {
1734                 imm_draw_circle_fill_2d(pos, x, y, radius, 40);
1735         }
1736         else {
1737                 imm_draw_circle_wire_2d(pos, x, y, radius, 40);
1738         }
1739
1740         /* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */
1741         mul_v3_v3fl(darkcolor, color, 0.40f);
1742         immUniformColor4f(darkcolor[0], darkcolor[1], darkcolor[2], 0.8f);
1743         imm_draw_circle_wire_2d(pos, x, y, radius + 1, 40);
1744
1745         glDisable(GL_BLEND);
1746         glDisable(GL_LINE_SMOOTH);
1747
1748         /* Draw line for lazy mouse */
1749         if ((last_mouse_position) &&
1750             (brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP))
1751         {
1752                 glEnable(GL_LINE_SMOOTH);
1753                 glEnable(GL_BLEND);
1754
1755                 copy_v3_v3(color, brush->add_col);
1756                 immUniformColor4f(color[0], color[1], color[2], 0.8f);
1757
1758                 immBegin(GPU_PRIM_LINES, 2);
1759                 immVertex2f(pos, x, y);
1760                 immVertex2f(
1761                         pos,
1762                         last_mouse_position[0] + ar->winrct.xmin,
1763                         last_mouse_position[1] + ar->winrct.ymin);
1764                 immEnd();
1765
1766                 glDisable(GL_BLEND);
1767                 glDisable(GL_LINE_SMOOTH);
1768         }
1769
1770         immUnbindProgram();
1771 }
1772
1773 /* Turn brush cursor in on/off */
1774 void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata)
1775 {
1776         Scene *scene = CTX_data_scene(C);
1777         GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
1778         float *lastpost = customdata;
1779
1780         if (gset->paintcursor && !enable) {
1781                 /* clear cursor */
1782                 WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
1783                 gset->paintcursor = NULL;
1784         }
1785         else if (enable) {
1786                 /* in some situations cursor could be duplicated, so it is better disable first if exist */
1787                 if (gset->paintcursor) {
1788                         /* clear cursor */
1789                         WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
1790                         gset->paintcursor = NULL;
1791                 }
1792                 /* enable cursor */
1793                 gset->paintcursor = WM_paint_cursor_activate(
1794                         CTX_wm_manager(C),
1795                         SPACE_TYPE_ANY, RGN_TYPE_ANY,
1796                         gp_brush_cursor_poll,
1797                         gp_brush_cursor_draw,
1798                         (lastpost) ? customdata : NULL);
1799         }
1800 }
1801
1802 /* verify if is using the right brush */
1803 static void gpencil_verify_brush_type(bContext *C, int newmode)
1804 {
1805         ToolSettings *ts = CTX_data_tool_settings(C);
1806         GP_Sculpt_Settings *gset = &ts->gp_sculpt;
1807
1808         switch (newmode) {
1809                 case OB_MODE_SCULPT_GPENCIL:
1810                         gset->flag &= ~GP_SCULPT_SETT_FLAG_WEIGHT_MODE;
1811                         if ((gset->brushtype < 0) || (gset->brushtype >= GP_SCULPT_TYPE_WEIGHT)) {
1812                                 gset->brushtype = GP_SCULPT_TYPE_PUSH;
1813                         }
1814                         break;
1815                 case OB_MODE_WEIGHT_GPENCIL:
1816                         gset->flag |= GP_SCULPT_SETT_FLAG_WEIGHT_MODE;
1817                         if ((gset->weighttype < GP_SCULPT_TYPE_WEIGHT) || (gset->weighttype >= GP_SCULPT_TYPE_MAX)) {
1818                                 gset->weighttype = GP_SCULPT_TYPE_WEIGHT;
1819                         }
1820                         break;
1821                 default:
1822                         break;
1823         }
1824 }
1825
1826 /* set object modes */
1827 void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode)
1828 {
1829         if (!gpd) {
1830                 return;
1831         }
1832
1833         switch (newmode) {
1834                 case OB_MODE_EDIT_GPENCIL:
1835                         gpd->flag |= GP_DATA_STROKE_EDITMODE;
1836                         gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
1837                         gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
1838                         gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
1839                         ED_gpencil_toggle_brush_cursor(C, false, NULL);
1840                         break;
1841                 case OB_MODE_PAINT_GPENCIL:
1842                         gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
1843                         gpd->flag |= GP_DATA_STROKE_PAINTMODE;
1844                         gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
1845                         gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
1846                         ED_gpencil_toggle_brush_cursor(C, true, NULL);
1847                         break;
1848                 case OB_MODE_SCULPT_GPENCIL:
1849                         gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
1850                         gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
1851                         gpd->flag |= GP_DATA_STROKE_SCULPTMODE;
1852                         gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
1853                         gpencil_verify_brush_type(C, OB_MODE_SCULPT_GPENCIL);
1854                         ED_gpencil_toggle_brush_cursor(C, true, NULL);
1855                         break;
1856                 case OB_MODE_WEIGHT_GPENCIL:
1857                         gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
1858                         gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
1859                         gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
1860                         gpd->flag |= GP_DATA_STROKE_WEIGHTMODE;
1861                         gpencil_verify_brush_type(C, OB_MODE_WEIGHT_GPENCIL);
1862                         ED_gpencil_toggle_brush_cursor(C, true, NULL);
1863                         break;
1864                 default:
1865                         gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
1866                         gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
1867                         gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
1868                         gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
1869                         ED_gpencil_toggle_brush_cursor(C, false, NULL);
1870                         break;
1871         }
1872 }
1873
1874 /* helper to convert 2d to 3d for simple drawing buffer */
1875 static void gpencil_stroke_convertcoords(ARegion *ar, const tGPspoint *point2D, float origin[3], float out[3])
1876 {
1877         float mval_f[2] = { (float)point2D->x, (float)point2D->y };
1878         float mval_prj[2];
1879         float rvec[3], dvec[3];
1880         float zfac;
1881
1882         copy_v3_v3(rvec, origin);
1883
1884         zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
1885
1886         if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
1887                 sub_v2_v2v2(mval_f, mval_prj, mval_f);
1888                 ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
1889                 sub_v3_v3v3(out, rvec, dvec);
1890         }
1891         else {
1892                 zero_v3(out);
1893         }
1894 }
1895
1896 /* convert 2d tGPspoint to 3d bGPDspoint */
1897 void ED_gpencil_tpoint_to_point(ARegion *ar, float origin[3], const tGPspoint *tpt, bGPDspoint *pt)
1898 {
1899         float p3d[3];
1900         /* conversion to 3d format */
1901         gpencil_stroke_convertcoords(ar, tpt, origin, p3d);
1902         copy_v3_v3(&pt->x, p3d);
1903
1904         pt->pressure = tpt->pressure;
1905         pt->strength = tpt->strength;
1906         pt->uv_fac = tpt->uv_fac;
1907         pt->uv_rot = tpt->uv_rot;
1908 }
1909
1910 /* texture coordinate utilities */
1911 void ED_gpencil_calc_stroke_uv(Object *ob, bGPDstroke *gps)
1912 {
1913         if (gps == NULL) {
1914                 return;
1915         }
1916         MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
1917         float pixsize;
1918         if (gp_style) {
1919                 pixsize = gp_style->texture_pixsize / 1000000.0f;
1920         }
1921         else {
1922                 /* use this value by default */
1923                 pixsize = 0.0001f;
1924         }
1925         pixsize = MAX2(pixsize, 0.0000001f);
1926
1927         bGPDspoint *pt = NULL;
1928         bGPDspoint *ptb = NULL;
1929         int i;
1930         float totlen = 0.0f;
1931
1932         /* first read all points and calc distance */
1933         for (i = 0; i < gps->totpoints; i++) {
1934                 pt = &gps->points[i];
1935                 /* first point */
1936                 if (i == 0) {
1937                         pt->uv_fac = 0.0f;
1938                         continue;
1939                 }
1940
1941                 ptb = &gps->points[i - 1];
1942                 totlen += len_v3v3(&pt->x, &ptb->x) / pixsize;
1943                 pt->uv_fac = totlen;
1944         }
1945
1946         /* normalize the distance using a factor */
1947         float factor;
1948
1949         /* if image, use texture width */
1950         if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) &&
1951             (gp_style->sima))
1952         {
1953                 factor = gp_style->sima->gen_x;
1954         }
1955         else if (totlen == 0) {
1956                 return;
1957         }
1958         else {
1959                 factor = totlen;
1960         }
1961
1962         for (i = 0; i < gps->totpoints; i++) {
1963                 pt = &gps->points[i];
1964                 pt->uv_fac /= factor;
1965         }
1966 }
1967
1968 /* recalc uv for any stroke using the material */
1969 void ED_gpencil_update_color_uv(Main *bmain, Material *mat)
1970 {
1971         Material *gps_ma = NULL;
1972         /* read all strokes  */
1973         for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
1974                 if (ob->type == OB_GPENCIL) {
1975                         bGPdata *gpd = ob->data;
1976                         if (gpd == NULL) {
1977                                 continue;
1978                         }
1979
1980                         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1981                                 /* only editable and visible layers are considered */
1982                                 if (gpencil_layer_is_editable(gpl)) {
1983                                         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1984                                                 for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1985                                                         /* check if it is editable */
1986                                                         if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
1987                                                                 continue;
1988                                                         }
1989                                                         gps_ma = give_current_material(ob, gps->mat_nr + 1);
1990                                                         /* update */
1991                                                         if ((gps_ma) && (gps_ma == mat)) {
1992                                                                 ED_gpencil_calc_stroke_uv(ob, gps);
1993                                                         }
1994                                                 }
1995                                         }
1996                                 }
1997                         }
1998                 }
1999         }
2000 }
2001
2002 static bool gpencil_check_collision(
2003         bGPDstroke *gps, bGPDstroke **gps_array, GHash *all_2d,
2004         int totstrokes, float p2d_a1[2], float p2d_a2[2], float r_hit[2])
2005 {
2006         bool hit = false;
2007         /* check segment with all segments of all strokes */
2008         for (int s = 0; s < totstrokes; s++) {
2009                 bGPDstroke *gps_iter = gps_array[s];
2010                 if (gps_iter->totpoints < 2) {
2011                         continue;
2012                 }
2013                 /* get stroke 2d version */
2014                 float(*points2d)[2] = BLI_ghash_lookup(all_2d, gps_iter);
2015
2016                 for (int i2 = 0; i2 < gps_iter->totpoints - 1; i2++) {
2017                         float p2d_b1[2], p2d_b2[2];
2018                         copy_v2_v2(p2d_b1, points2d[i2]);
2019                         copy_v2_v2(p2d_b2, points2d[i2 + 1]);
2020
2021                         /* don't self check */
2022                         if (gps == gps_iter) {
2023                                 if (equals_v2v2(p2d_a1, p2d_b1) || equals_v2v2(p2d_a1, p2d_b2)) {
2024                                         continue;
2025                                 }
2026                                 if (equals_v2v2(p2d_a2, p2d_b1) || equals_v2v2(p2d_a2, p2d_b2)) {
2027                                         continue;
2028                                 }
2029                         }
2030                         /* check collision */
2031                         int check = isect_seg_seg_v2_point(p2d_a1, p2d_a2, p2d_b1, p2d_b2, r_hit);
2032                         if (check > 0) {
2033                                 hit = true;
2034                                 break;
2035                         }
2036                 }
2037
2038                 if (hit) {
2039                         break;
2040                 }
2041         }
2042
2043         if (!hit) {
2044                 zero_v2(r_hit);
2045         }
2046
2047         return hit;
2048 }
2049
2050 static void gp_copy_points(
2051         bGPDstroke *gps, bGPDspoint *pt, bGPDspoint *pt_final, int i, int i2)
2052 {
2053         /* don't copy same point */
2054         if (i == i2) {
2055                 return;
2056         }
2057
2058         copy_v3_v3(&pt_final->x, &pt->x);
2059         pt_final->pressure = pt->pressure;
2060         pt_final->strength = pt->strength;
2061         pt_final->time = pt->time;
2062         pt_final->flag = pt->flag;
2063         pt_final->uv_fac = pt->uv_fac;
2064         pt_final->uv_rot = pt->uv_rot;
2065
2066         if (gps->dvert != NULL) {
2067                 MDeformVert *dvert = &gps->dvert[i];
2068                 MDeformVert *dvert_final = &gps->dvert[i2];
2069                 MEM_SAFE_FREE(dvert_final->dw);
2070
2071                 dvert_final->totweight = dvert->totweight;
2072                 if (dvert->dw == NULL) {
2073                         dvert_final->dw = NULL;
2074                         dvert_final->totweight = 0;
2075                 }
2076                 else {
2077                         dvert_final->dw = MEM_dupallocN(dvert->dw);
2078                 }
2079         }
2080
2081 }
2082
2083 static void gp_insert_point(
2084         bGPDstroke *gps,
2085         bGPDspoint *a_pt, bGPDspoint *b_pt,
2086         float co_a[3], float co_b[3])
2087 {
2088         bGPDspoint *temp_points;
2089         int totnewpoints, oldtotpoints;
2090
2091         totnewpoints = gps->totpoints;
2092         if (a_pt) {
2093                 totnewpoints++;
2094         }
2095         if (b_pt) {
2096                 totnewpoints++;
2097         }
2098
2099         /* duplicate points in a temp area */
2100         temp_points = MEM_dupallocN(gps->points);
2101         oldtotpoints = gps->totpoints;
2102
2103         /* look index of base points because memory is changed when resize points array */
2104         int a_idx = -1;
2105         int b_idx = -1;
2106         for (int i = 0; i < oldtotpoints; i++) {
2107                 bGPDspoint *pt = &gps->points[i];
2108                 if (pt == a_pt) {
2109                         a_idx = i;
2110                 }
2111                 if (pt == b_pt) {
2112                         b_idx = i;
2113                 }
2114         }
2115
2116         /* resize the points arrays */
2117         gps->totpoints = totnewpoints;
2118         gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
2119         if (gps->dvert != NULL) {
2120                 gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
2121         }
2122         gps->flag |= GP_STROKE_RECALC_GEOMETRY;
2123
2124         /* copy all points */
2125         int i2 = 0;
2126         for (int i = 0; i < oldtotpoints; i++) {
2127                 bGPDspoint *pt = &temp_points[i];
2128                 bGPDspoint *pt_final = &gps->points[i2];
2129                 gp_copy_points(gps, pt, pt_final, i, i2);
2130
2131                 /* create new point duplicating point and copy location */
2132                 if ((i == a_idx) || (i == b_idx)) {
2133                         i2++;
2134                         pt_final = &gps->points[i2];
2135                         gp_copy_points(gps, pt, pt_final, i, i2);
2136                         copy_v3_v3(&pt_final->x, (i == a_idx) ? co_a : co_b);
2137
2138                         /* unselect */
2139                         pt_final->flag &= ~GP_SPOINT_SELECT;
2140                         /* tag to avoid more checking with this point */
2141                         pt_final->flag |= GP_SPOINT_TAG;
2142                 }
2143
2144                 i2++;
2145         }
2146
2147         MEM_SAFE_FREE(temp_points);
2148 }
2149
2150 static float gp_calc_factor(float p2d_a1[2], float p2d_a2[2], float r_hit2d[2])
2151 {
2152         float dist1 = len_squared_v2v2(p2d_a1, p2d_a2);
2153         float dist2 = len_squared_v2v2(p2d_a1, r_hit2d);
2154         float f = dist1 > 0.0f ? dist2 / dist1 : 0.0f;
2155
2156         /* apply a correction factor */
2157         float v1[2];
2158         interp_v2_v2v2(v1, p2d_a1, p2d_a2, f);
2159         float dist3 = len_squared_v2v2(p2d_a1, v1);
2160         float f1 = dist1 > 0.0f ? dist3 / dist1 : 0.0f;
2161         f = f + (f - f1);
2162
2163         return f;
2164 }
2165
2166 /* extend selection to stroke intersections */
2167 int ED_gpencil_select_stroke_segment(
2168         bGPDlayer *gpl, bGPDstroke *gps, bGPDspoint *pt,
2169         bool select, bool insert, const float scale,
2170         float r_hita[3], float r_hitb[3])
2171 {
2172         const float min_factor = 0.0015f;
2173         bGPDspoint *pta1 = NULL;
2174         bGPDspoint *pta2 = NULL;
2175         float f = 0.0f;
2176         int i2 = 0;
2177
2178         bGPDframe *gpf = gpl->actframe;
2179         if (gpf == NULL) {
2180                 return 0;
2181         }
2182
2183         int memsize = BLI_listbase_count(&gpf->strokes);
2184         bGPDstroke **gps_array = MEM_callocN(sizeof(bGPDstroke *) * memsize, __func__);
2185
2186         /* save points */
2187         bGPDspoint *oldpoints = MEM_dupallocN(gps->points);
2188
2189         /* Save list of strokes to check */
2190         int totstrokes = 0;
2191         for (bGPDstroke *gps_iter = gpf->strokes.first; gps_iter; gps_iter = gps_iter->next) {
2192                 if (gps_iter->totpoints < 2) {
2193                         continue;
2194                 }
2195                 gps_array[totstrokes] = gps_iter;
2196                 totstrokes++;
2197         }
2198
2199         if (totstrokes == 0) {
2200                 return 0;
2201         }
2202
2203         /* look for index of the current point */
2204         int cur_idx = -1;
2205         for (int i = 0; i < gps->totpoints; i++) {
2206                 pta1 = &gps->points[i];
2207                 if (pta1 == pt) {
2208                         cur_idx = i;
2209                         break;
2210                 }
2211         }
2212         if (cur_idx < 0) {
2213                 return 0;
2214         }
2215
2216         /* convert all gps points to 2d and save in a hash to avoid recalculation  */
2217         int direction = 0;
2218         float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points");
2219         BKE_gpencil_stroke_2d_flat_ref(
2220                 gps->points, gps->totpoints,
2221                 gps->points, gps->totpoints, points2d, scale, &direction);
2222
2223         GHash *all_2d = BLI_ghash_ptr_new(__func__);
2224
2225         for (int s = 0; s < totstrokes; s++) {
2226                 bGPDstroke *gps_iter = gps_array[s];
2227                 float(*points2d_iter)[2] = MEM_mallocN(sizeof(*points2d_iter) * gps_iter->totpoints, __func__);
2228
2229                 /* the extremes of the stroke are scaled to improve collision detection
2230                  * for near lines */
2231                 BKE_gpencil_stroke_2d_flat_ref(
2232                         gps->points, gps->totpoints,
2233                         gps_iter->points, gps_iter->totpoints, points2d_iter,
2234                         scale, &direction);
2235                 BLI_ghash_insert(all_2d, gps_iter, points2d_iter);
2236         }
2237
2238         bool hit_a = false;
2239         bool hit_b = false;
2240         float p2d_a1[2] = {0.0f, 0.0f};
2241         float p2d_a2[2] = {0.0f, 0.0f};
2242         float r_hit2d[2];
2243         bGPDspoint *hit_pointa = NULL;
2244         bGPDspoint *hit_pointb = NULL;
2245
2246         /* analyze points before current */
2247         if (cur_idx > 0) {
2248                 for (int i = cur_idx; i >= 0; i--) {
2249                         pta1 = &gps->points[i];
2250                         copy_v2_v2(p2d_a1, points2d[i]);
2251
2252                         i2 = i - 1;
2253                         CLAMP_MIN(i2, 0);
2254                         pta2 = &gps->points[i2];
2255                         copy_v2_v2(p2d_a2, points2d[i2]);
2256
2257                         hit_a = gpencil_check_collision(
2258                                 gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d);
2259
2260                         if (select) {
2261                                 pta1->flag |= GP_SPOINT_SELECT;
2262                         }
2263                         else {
2264                                 pta1->flag &= ~GP_SPOINT_SELECT;
2265                         }
2266
2267                         if (hit_a) {
2268                                 f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d);
2269                                 interp_v3_v3v3(r_hita, &pta1->x, &pta2->x, f);
2270                                 if (f > min_factor) {
2271                                         hit_pointa = pta2; /* first point is second (inverted loop) */
2272                                 }
2273                                 else {
2274                                         pta1->flag &= ~GP_SPOINT_SELECT;
2275                                 }
2276                                 break;
2277                         }
2278                 }
2279         }
2280
2281         /* analyze points after current */
2282         for (int i = cur_idx; i < gps->totpoints; i++) {
2283                 pta1 = &gps->points[i];
2284                 copy_v2_v2(p2d_a1, points2d[i]);
2285
2286                 i2 = i + 1;
2287                 CLAMP_MAX(i2, gps->totpoints - 1);
2288                 pta2 = &gps->points[i2];
2289                 copy_v2_v2(p2d_a2, points2d[i2]);
2290
2291                 hit_b = gpencil_check_collision(
2292                         gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d);
2293
2294                 if (select) {
2295                         pta1->flag |= GP_SPOINT_SELECT;
2296                 }
2297                 else {
2298                         pta1->flag &= ~GP_SPOINT_SELECT;
2299                 }
2300
2301                 if (hit_b) {
2302                         f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d);
2303                         interp_v3_v3v3(r_hitb, &pta1->x, &pta2->x, f);
2304                         if (f > min_factor) {
2305                                 hit_pointb = pta1;
2306                         }
2307                         else {
2308                                 pta1->flag &= ~GP_SPOINT_SELECT;
2309                         }
2310                         break;
2311                 }
2312         }
2313
2314         /* insert new point in the collision points */
2315         if (insert) {
2316                 gp_insert_point(gps, hit_pointa, hit_pointb, r_hita, r_hitb);
2317         }
2318
2319         /* free memory */
2320         if (all_2d) {
2321                 GHashIterator gh_iter;
2322                 GHASH_ITER(gh_iter, all_2d) {
2323                         float(*p2d)[2] = BLI_ghashIterator_getValue(&gh_iter);
2324                         MEM_SAFE_FREE(p2d);
2325                 }
2326                 BLI_ghash_free(all_2d, NULL, NULL);
2327         }
2328
2329         /* if no hit, reset selection flag */
2330         if ((!hit_a) && (!hit_b)) {
2331                 for (int i = 0; i < gps->totpoints; i++) {
2332                         pta1 = &gps->points[i];
2333                         pta2 = &oldpoints[i];
2334                         pta1->flag = pta2->flag;
2335                 }
2336         }
2337
2338         MEM_SAFE_FREE(points2d);
2339         MEM_SAFE_FREE(gps_array);
2340         MEM_SAFE_FREE(oldpoints);
2341
2342         /* return type of hit */
2343         if ((hit_a) && (hit_b)) {
2344                 return 3;
2345         }
2346         else if (hit_a) {
2347                 return 1;
2348         }
2349         else if (hit_b) {
2350                 return 2;
2351         }
2352         else {
2353                 return 0;
2354         }
2355 }