From e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 17 Apr 2019 06:17:24 +0200 Subject: ClangFormat: apply to source, most of intern Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat --- source/blender/editors/gpencil/gpencil_utils.c | 3928 ++++++++++++------------ 1 file changed, 1972 insertions(+), 1956 deletions(-) (limited to 'source/blender/editors/gpencil/gpencil_utils.c') diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index f582b52713d..858415061b1 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -88,120 +88,129 @@ /* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it, * when context info is not available. */ -bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, ScrArea *sa, Scene *scene, Object *ob, PointerRNA *r_ptr) +bGPdata **ED_gpencil_data_get_pointers_direct( + ID *screen_id, ScrArea *sa, Scene *scene, Object *ob, PointerRNA *r_ptr) { - /* if there's an active area, check if the particular editor may - * have defined any special Grease Pencil context for editing... - */ - if (sa) { - SpaceLink *sl = sa->spacedata.first; - - switch (sa->spacetype) { - /* XXX: Should we reduce reliance on context.gpencil_data for these cases? */ - case SPACE_PROPERTIES: /* properties */ - case SPACE_INFO: /* header info (needed after workspaces merge) */ - { - if (ob && (ob->type == OB_GPENCIL)) { - /* GP Object */ - if (r_ptr) RNA_id_pointer_create(&ob->id, r_ptr); - return (bGPdata **)&ob->data; - } - else { - return NULL; - } - - break; - } - - case SPACE_TOPBAR: /* Topbar (needed after topbar merge) */ - case SPACE_VIEW3D: /* 3D-View */ - { - if (ob && (ob->type == OB_GPENCIL)) { - /* GP Object */ - if (r_ptr) RNA_id_pointer_create(&ob->id, r_ptr); - return (bGPdata **)&ob->data; - } - else { - /* Annotations */ - /* XXX: */ - if (r_ptr) RNA_id_pointer_create(&scene->id, r_ptr); - return &scene->gpd; - } - - break; - } - case SPACE_NODE: /* Nodes Editor */ - { - SpaceNode *snode = (SpaceNode *)sl; - - /* return the GP data for the active node block/node */ - if (snode && snode->nodetree) { - /* for now, as long as there's an active node tree, - * default to using that in the Nodes Editor */ - if (r_ptr) RNA_id_pointer_create(&snode->nodetree->id, r_ptr); - return &snode->nodetree->gpd; - } - - /* even when there is no node-tree, don't allow this to flow to scene */ - return NULL; - } - case SPACE_SEQ: /* Sequencer */ - { - SpaceSeq *sseq = (SpaceSeq *)sl; - - /* for now, Grease Pencil data is associated with the space (actually preview region only) */ - /* XXX our convention for everything else is to link to data though... */ - if (r_ptr) RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, r_ptr); - return &sseq->gpd; - } - case SPACE_IMAGE: /* Image/UV Editor */ - { - SpaceImage *sima = (SpaceImage *)sl; - - /* for now, Grease Pencil data is associated with the space... */ - /* XXX our convention for everything else is to link to data though... */ - if (r_ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, r_ptr); - return &sima->gpd; - } - case SPACE_CLIP: /* Nodes Editor */ - { - SpaceClip *sc = (SpaceClip *)sl; - MovieClip *clip = ED_space_clip_get_clip(sc); - - if (clip) { - if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { - MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking); - - if (!track) - return NULL; - - if (r_ptr) RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, r_ptr); - return &track->gpd; - } - else { - if (r_ptr) RNA_id_pointer_create(&clip->id, r_ptr); - return &clip->gpd; - } - } - break; - } - default: /* unsupported space */ - return NULL; - } - } - - return NULL; + /* if there's an active area, check if the particular editor may + * have defined any special Grease Pencil context for editing... + */ + if (sa) { + SpaceLink *sl = sa->spacedata.first; + + switch (sa->spacetype) { + /* XXX: Should we reduce reliance on context.gpencil_data for these cases? */ + case SPACE_PROPERTIES: /* properties */ + case SPACE_INFO: /* header info (needed after workspaces merge) */ + { + if (ob && (ob->type == OB_GPENCIL)) { + /* GP Object */ + if (r_ptr) + RNA_id_pointer_create(&ob->id, r_ptr); + return (bGPdata **)&ob->data; + } + else { + return NULL; + } + + break; + } + + case SPACE_TOPBAR: /* Topbar (needed after topbar merge) */ + case SPACE_VIEW3D: /* 3D-View */ + { + if (ob && (ob->type == OB_GPENCIL)) { + /* GP Object */ + if (r_ptr) + RNA_id_pointer_create(&ob->id, r_ptr); + return (bGPdata **)&ob->data; + } + else { + /* Annotations */ + /* XXX: */ + if (r_ptr) + RNA_id_pointer_create(&scene->id, r_ptr); + return &scene->gpd; + } + + break; + } + case SPACE_NODE: /* Nodes Editor */ + { + SpaceNode *snode = (SpaceNode *)sl; + + /* return the GP data for the active node block/node */ + if (snode && snode->nodetree) { + /* for now, as long as there's an active node tree, + * default to using that in the Nodes Editor */ + if (r_ptr) + RNA_id_pointer_create(&snode->nodetree->id, r_ptr); + return &snode->nodetree->gpd; + } + + /* even when there is no node-tree, don't allow this to flow to scene */ + return NULL; + } + case SPACE_SEQ: /* Sequencer */ + { + SpaceSeq *sseq = (SpaceSeq *)sl; + + /* for now, Grease Pencil data is associated with the space (actually preview region only) */ + /* XXX our convention for everything else is to link to data though... */ + if (r_ptr) + RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, r_ptr); + return &sseq->gpd; + } + case SPACE_IMAGE: /* Image/UV Editor */ + { + SpaceImage *sima = (SpaceImage *)sl; + + /* for now, Grease Pencil data is associated with the space... */ + /* XXX our convention for everything else is to link to data though... */ + if (r_ptr) + RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, r_ptr); + return &sima->gpd; + } + case SPACE_CLIP: /* Nodes Editor */ + { + SpaceClip *sc = (SpaceClip *)sl; + MovieClip *clip = ED_space_clip_get_clip(sc); + + if (clip) { + if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { + MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking); + + if (!track) + return NULL; + + if (r_ptr) + RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, r_ptr); + return &track->gpd; + } + else { + if (r_ptr) + RNA_id_pointer_create(&clip->id, r_ptr); + return &clip->gpd; + } + } + break; + } + default: /* unsupported space */ + return NULL; + } + } + + return NULL; } /* Get pointer to active Grease Pencil datablock, and an RNA-pointer to trace back to whatever owns it */ bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *r_ptr) { - ID *screen_id = (ID *)CTX_wm_screen(C); - Scene *scene = CTX_data_scene(C); - ScrArea *sa = CTX_wm_area(C); - Object *ob = CTX_data_active_object(C); + ID *screen_id = (ID *)CTX_wm_screen(C); + Scene *scene = CTX_data_scene(C); + ScrArea *sa = CTX_wm_area(C); + Object *ob = CTX_data_active_object(C); - return ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, r_ptr); + return ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, r_ptr); } /* -------------------------------------------------------- */ @@ -209,8 +218,8 @@ bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *r_ptr) /* Get the active Grease Pencil datablock, when context is not available */ bGPdata *ED_gpencil_data_get_active_direct(ID *screen_id, ScrArea *sa, Scene *scene, Object *ob) { - bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, NULL); - return (gpd_ptr) ? *(gpd_ptr) : NULL; + bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, NULL); + return (gpd_ptr) ? *(gpd_ptr) : NULL; } /** @@ -220,8 +229,8 @@ bGPdata *ED_gpencil_data_get_active_direct(ID *screen_id, ScrArea *sa, Scene *sc */ bGPdata *ED_gpencil_data_get_active(const bContext *C) { - bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); - return (gpd_ptr) ? *(gpd_ptr) : NULL; + bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); + return (gpd_ptr) ? *(gpd_ptr) : NULL; } /** @@ -234,16 +243,16 @@ bGPdata *ED_gpencil_data_get_active(const bContext *C) */ bGPdata *ED_gpencil_data_get_active_evaluated(const bContext *C) { - ID *screen_id = (ID *)CTX_wm_screen(C); - ScrArea *sa = CTX_wm_area(C); + ID *screen_id = (ID *)CTX_wm_screen(C); + ScrArea *sa = CTX_wm_area(C); - const Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); - Object *ob = CTX_data_active_object(C); - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + Object *ob = CTX_data_active_object(C); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - /* if (ob && ob->type == OB_GPENCIL) BLI_assert(ob_eval->data == DEG_get_evaluated_id(ob->data)); */ - return ED_gpencil_data_get_active_direct(screen_id, sa, scene_eval, ob_eval); + /* if (ob && ob->type == OB_GPENCIL) BLI_assert(ob_eval->data == DEG_get_evaluated_id(ob->data)); */ + return ED_gpencil_data_get_active_direct(screen_id, sa, scene_eval, ob_eval); } /* -------------------------------------------------------- */ @@ -254,10 +263,10 @@ bGPdata *ED_gpencil_data_get_active_evaluated(const bContext *C) */ bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr) { - /* Key Assumption: If the pointer is an object, we're dealing with a GP Object's data. - * Otherwise, the GP datablock is being used for annotations (i.e. everywhere else) - */ - return ((owner_ptr) && (owner_ptr->type != &RNA_Object)); + /* Key Assumption: If the pointer is an object, we're dealing with a GP Object's data. + * Otherwise, the GP datablock is being used for annotations (i.e. everywhere else) + */ + return ((owner_ptr) && (owner_ptr->type != &RNA_Object)); } /* ******************************************************** */ @@ -266,21 +275,21 @@ bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr) /* Check whether there's an active GP keyframe on the current frame */ bool ED_gpencil_has_keyframe_v3d(Scene *UNUSED(scene), Object *ob, int cfra) { - if (ob && ob->data && (ob->type == OB_GPENCIL)) { - bGPDlayer *gpl = BKE_gpencil_layer_getactive(ob->data); - if (gpl) { - if (gpl->actframe) { - // XXX: assumes that frame has been fetched already - return (gpl->actframe->framenum == cfra); - } - else { - /* XXX: disabled as could be too much of a penalty */ - /* return BKE_gpencil_layer_find_frame(gpl, cfra); */ - } - } - } - - return false; + if (ob && ob->data && (ob->type == OB_GPENCIL)) { + bGPDlayer *gpl = BKE_gpencil_layer_getactive(ob->data); + if (gpl) { + if (gpl->actframe) { + // XXX: assumes that frame has been fetched already + return (gpl->actframe->framenum == cfra); + } + else { + /* XXX: disabled as could be too much of a penalty */ + /* return BKE_gpencil_layer_find_frame(gpl, cfra); */ + } + } + } + + return false; } /* ******************************************************** */ @@ -289,30 +298,30 @@ bool ED_gpencil_has_keyframe_v3d(Scene *UNUSED(scene), Object *ob, int cfra) /* poll callback for adding data/layers - special */ bool gp_add_poll(bContext *C) { - /* the base line we have is that we have somewhere to add Grease Pencil data */ - return ED_gpencil_data_get_pointers(C, NULL) != NULL; + /* the base line we have is that we have somewhere to add Grease Pencil data */ + return ED_gpencil_data_get_pointers(C, NULL) != NULL; } /* poll callback for checking if there is an active layer */ bool gp_active_layer_poll(bContext *C) { - bGPdata *gpd = ED_gpencil_data_get_active(C); - bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); + bGPdata *gpd = ED_gpencil_data_get_active(C); + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); - return (gpl != NULL); + return (gpl != NULL); } /* poll callback for checking if there is an active brush */ bool gp_active_brush_poll(bContext *C) { - ToolSettings *ts = CTX_data_tool_settings(C); - Paint *paint = &ts->gp_paint->paint; - if (paint) { - return (paint->brush != NULL); - } - else { - return false; - } + ToolSettings *ts = CTX_data_tool_settings(C); + Paint *paint = &ts->gp_paint->paint; + if (paint) { + return (paint->brush != NULL); + } + else { + return false; + } } /* ******************************************************** */ @@ -320,88 +329,91 @@ bool gp_active_brush_poll(bContext *C) /* NOTE: These include an option to create a new layer and use that... */ /* Just existing layers */ -const EnumPropertyItem *ED_gpencil_layers_enum_itemf( - bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *ED_gpencil_layers_enum_itemf(bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) { - bGPdata *gpd = CTX_data_gpencil_data(C); - bGPDlayer *gpl; - EnumPropertyItem *item = NULL, item_tmp = {0}; - int totitem = 0; - int i = 0; - - if (ELEM(NULL, C, gpd)) { - return DummyRNA_DEFAULT_items; - } - - /* Existing layers */ - for (gpl = gpd->layers.first; gpl; gpl = gpl->next, i++) { - item_tmp.identifier = gpl->info; - item_tmp.name = gpl->info; - item_tmp.value = i; - - if (gpl->flag & GP_LAYER_ACTIVE) - item_tmp.icon = ICON_GREASEPENCIL; - else - item_tmp.icon = ICON_NONE; - - RNA_enum_item_add(&item, &totitem, &item_tmp); - } - - RNA_enum_item_end(&item, &totitem); - *r_free = true; - - return item; + bGPdata *gpd = CTX_data_gpencil_data(C); + bGPDlayer *gpl; + EnumPropertyItem *item = NULL, item_tmp = {0}; + int totitem = 0; + int i = 0; + + if (ELEM(NULL, C, gpd)) { + return DummyRNA_DEFAULT_items; + } + + /* Existing layers */ + for (gpl = gpd->layers.first; gpl; gpl = gpl->next, i++) { + item_tmp.identifier = gpl->info; + item_tmp.name = gpl->info; + item_tmp.value = i; + + if (gpl->flag & GP_LAYER_ACTIVE) + item_tmp.icon = ICON_GREASEPENCIL; + else + item_tmp.icon = ICON_NONE; + + RNA_enum_item_add(&item, &totitem, &item_tmp); + } + + RNA_enum_item_end(&item, &totitem); + *r_free = true; + + return item; } /* Existing + Option to add/use new layer */ -const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf( - bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) { - bGPdata *gpd = CTX_data_gpencil_data(C); - bGPDlayer *gpl; - EnumPropertyItem *item = NULL, item_tmp = {0}; - int totitem = 0; - int i = 0; - - if (ELEM(NULL, C, gpd)) { - return DummyRNA_DEFAULT_items; - } - - /* Create new layer */ - /* TODO: have some way of specifying that we don't want this? */ - { - /* "New Layer" entry */ - item_tmp.identifier = "__CREATE__"; - item_tmp.name = "New Layer"; - item_tmp.value = -1; - item_tmp.icon = ICON_ADD; - RNA_enum_item_add(&item, &totitem, &item_tmp); - - /* separator */ - RNA_enum_item_add_separator(&item, &totitem); - } - const int tot = BLI_listbase_count(&gpd->layers); - /* Existing layers */ - for (gpl = gpd->layers.last, i = 0; gpl; gpl = gpl->prev, i++) { - item_tmp.identifier = gpl->info; - item_tmp.name = gpl->info; - item_tmp.value = tot - i - 1; - - if (gpl->flag & GP_LAYER_ACTIVE) - item_tmp.icon = ICON_GREASEPENCIL; - else - item_tmp.icon = ICON_NONE; - - RNA_enum_item_add(&item, &totitem, &item_tmp); - } - - RNA_enum_item_end(&item, &totitem); - *r_free = true; - - return item; + bGPdata *gpd = CTX_data_gpencil_data(C); + bGPDlayer *gpl; + EnumPropertyItem *item = NULL, item_tmp = {0}; + int totitem = 0; + int i = 0; + + if (ELEM(NULL, C, gpd)) { + return DummyRNA_DEFAULT_items; + } + + /* Create new layer */ + /* TODO: have some way of specifying that we don't want this? */ + { + /* "New Layer" entry */ + item_tmp.identifier = "__CREATE__"; + item_tmp.name = "New Layer"; + item_tmp.value = -1; + item_tmp.icon = ICON_ADD; + RNA_enum_item_add(&item, &totitem, &item_tmp); + + /* separator */ + RNA_enum_item_add_separator(&item, &totitem); + } + const int tot = BLI_listbase_count(&gpd->layers); + /* Existing layers */ + for (gpl = gpd->layers.last, i = 0; gpl; gpl = gpl->prev, i++) { + item_tmp.identifier = gpl->info; + item_tmp.name = gpl->info; + item_tmp.value = tot - i - 1; + + if (gpl->flag & GP_LAYER_ACTIVE) + item_tmp.icon = ICON_GREASEPENCIL; + else + item_tmp.icon = ICON_NONE; + + RNA_enum_item_add(&item, &totitem, &item_tmp); + } + + RNA_enum_item_end(&item, &totitem); + *r_free = true; + + return item; } - /* ******************************************************** */ /* Brush Tool Core */ @@ -416,19 +428,18 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf( * \param x1, y1: The screen-space x and y coordinates of the end of the stroke segment */ bool gp_stroke_inside_circle( - const float mval[2], const float UNUSED(mvalo[2]), - int rad, int x0, int y0, int x1, int y1) + const float mval[2], const float UNUSED(mvalo[2]), int rad, int x0, int y0, int x1, int y1) { - /* simple within-radius check for now */ - const float screen_co_a[2] = {x0, y0}; - const float screen_co_b[2] = {x1, y1}; + /* simple within-radius check for now */ + const float screen_co_a[2] = {x0, y0}; + const float screen_co_b[2] = {x1, y1}; - if (edge_inside_circle(mval, rad, screen_co_a, screen_co_b)) { - return true; - } + if (edge_inside_circle(mval, rad, screen_co_a, screen_co_b)) { + return true; + } - /* not inside */ - return false; + /* not inside */ + return false; } /* ******************************************************** */ @@ -438,50 +449,50 @@ bool gp_stroke_inside_circle( /* TODO: do we need additional flags for screenspace vs dataspace? */ bool ED_gpencil_stroke_can_use_direct(const ScrArea *sa, const bGPDstroke *gps) { - /* sanity check */ - if (ELEM(NULL, sa, gps)) - return false; - - /* filter stroke types by flags + spacetype */ - if (gps->flag & GP_STROKE_3DSPACE) { - /* 3D strokes - only in 3D view */ - return ((sa->spacetype == SPACE_VIEW3D) || (sa->spacetype == SPACE_PROPERTIES)); - } - else if (gps->flag & GP_STROKE_2DIMAGE) { - /* Special "image" strokes - only in Image Editor */ - return (sa->spacetype == SPACE_IMAGE); - } - else if (gps->flag & GP_STROKE_2DSPACE) { - /* 2D strokes (dataspace) - for any 2D view (i.e. everything other than 3D view) */ - return (sa->spacetype != SPACE_VIEW3D); - } - else { - /* view aligned - anything goes */ - return true; - } + /* sanity check */ + if (ELEM(NULL, sa, gps)) + return false; + + /* filter stroke types by flags + spacetype */ + if (gps->flag & GP_STROKE_3DSPACE) { + /* 3D strokes - only in 3D view */ + return ((sa->spacetype == SPACE_VIEW3D) || (sa->spacetype == SPACE_PROPERTIES)); + } + else if (gps->flag & GP_STROKE_2DIMAGE) { + /* Special "image" strokes - only in Image Editor */ + return (sa->spacetype == SPACE_IMAGE); + } + else if (gps->flag & GP_STROKE_2DSPACE) { + /* 2D strokes (dataspace) - for any 2D view (i.e. everything other than 3D view) */ + return (sa->spacetype != SPACE_VIEW3D); + } + else { + /* view aligned - anything goes */ + return true; + } } /* Check whether given stroke can be edited in the current context */ bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps) { - ScrArea *sa = CTX_wm_area(C); - return ED_gpencil_stroke_can_use_direct(sa, gps); + ScrArea *sa = CTX_wm_area(C); + return ED_gpencil_stroke_can_use_direct(sa, gps); } /* Check whether given stroke can be edited for the current color */ bool ED_gpencil_stroke_color_use(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps) { - /* check if the color is editable */ - MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); + /* check if the color is editable */ + MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); - if (gp_style != NULL) { - if (gp_style->flag & GP_STYLE_COLOR_HIDE) - return false; - if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (gp_style->flag & GP_STYLE_COLOR_LOCKED)) - return false; - } + if (gp_style != NULL) { + if (gp_style->flag & GP_STYLE_COLOR_HIDE) + return false; + if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (gp_style->flag & GP_STYLE_COLOR_LOCKED)) + return false; + } - return true; + return true; } /* ******************************************************** */ @@ -494,41 +505,42 @@ bool ED_gpencil_stroke_color_use(Object *ob, const bGPDlayer *gpl, const bGPDstr */ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc) { - ScrArea *sa = CTX_wm_area(C); - ARegion *ar = CTX_wm_region(C); - - /* zero out the storage (just in case) */ - memset(r_gsc, 0, sizeof(GP_SpaceConversion)); - unit_m4(r_gsc->mat); - - /* store settings */ - r_gsc->scene = CTX_data_scene(C); - r_gsc->ob = CTX_data_active_object(C); - - r_gsc->sa = sa; - r_gsc->ar = ar; - r_gsc->v2d = &ar->v2d; - - /* init region-specific stuff */ - if (sa->spacetype == SPACE_VIEW3D) { - wmWindow *win = CTX_wm_window(C); - Scene *scene = CTX_data_scene(C); - struct Depsgraph *depsgraph = CTX_data_depsgraph(C); - View3D *v3d = (View3D *)CTX_wm_space_data(C); - RegionView3D *rv3d = ar->regiondata; - - /* init 3d depth buffers */ - view3d_operator_needs_opengl(C); - - view3d_region_operator_needs_opengl(win, ar); - ED_view3d_autodist_init(depsgraph, ar, v3d, 0); - - /* for camera view set the subrect */ - if (rv3d->persp == RV3D_CAMOB) { - ED_view3d_calc_camera_border(scene, CTX_data_depsgraph(C), ar, v3d, rv3d, &r_gsc->subrect_data, true); - r_gsc->subrect = &r_gsc->subrect_data; - } - } + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + + /* zero out the storage (just in case) */ + memset(r_gsc, 0, sizeof(GP_SpaceConversion)); + unit_m4(r_gsc->mat); + + /* store settings */ + r_gsc->scene = CTX_data_scene(C); + r_gsc->ob = CTX_data_active_object(C); + + r_gsc->sa = sa; + r_gsc->ar = ar; + r_gsc->v2d = &ar->v2d; + + /* init region-specific stuff */ + if (sa->spacetype == SPACE_VIEW3D) { + wmWindow *win = CTX_wm_window(C); + Scene *scene = CTX_data_scene(C); + struct Depsgraph *depsgraph = CTX_data_depsgraph(C); + View3D *v3d = (View3D *)CTX_wm_space_data(C); + RegionView3D *rv3d = ar->regiondata; + + /* init 3d depth buffers */ + view3d_operator_needs_opengl(C); + + view3d_region_operator_needs_opengl(win, ar); + ED_view3d_autodist_init(depsgraph, ar, v3d, 0); + + /* for camera view set the subrect */ + if (rv3d->persp == RV3D_CAMOB) { + ED_view3d_calc_camera_border( + scene, CTX_data_depsgraph(C), ar, v3d, rv3d, &r_gsc->subrect_data, true); + r_gsc->subrect = &r_gsc->subrect_data; + } + } } /** @@ -540,50 +552,52 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc) */ void gp_point_to_parent_space(const bGPDspoint *pt, const float diff_mat[4][4], bGPDspoint *r_pt) { - float fpt[3]; + float fpt[3]; - mul_v3_m4v3(fpt, diff_mat, &pt->x); - copy_v3_v3(&r_pt->x, fpt); + mul_v3_m4v3(fpt, diff_mat, &pt->x); + copy_v3_v3(&r_pt->x, fpt); } /** * Change position relative to parent object */ -void gp_apply_parent(Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps) +void gp_apply_parent( + Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps) { - bGPDspoint *pt; - int i; - - /* undo matrix */ - float diff_mat[4][4]; - float inverse_diff_mat[4][4]; - float fpt[3]; - - ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat); - invert_m4_m4(inverse_diff_mat, diff_mat); - - for (i = 0; i < gps->totpoints; i++) { - pt = &gps->points[i]; - mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x); - copy_v3_v3(&pt->x, fpt); - } + bGPDspoint *pt; + int i; + + /* undo matrix */ + float diff_mat[4][4]; + float inverse_diff_mat[4][4]; + float fpt[3]; + + ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat); + invert_m4_m4(inverse_diff_mat, diff_mat); + + for (i = 0; i < gps->totpoints; i++) { + pt = &gps->points[i]; + mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x); + copy_v3_v3(&pt->x, fpt); + } } /** * Change point position relative to parent object */ -void gp_apply_parent_point(Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDspoint *pt) +void gp_apply_parent_point( + Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDspoint *pt) { - /* undo matrix */ - float diff_mat[4][4]; - float inverse_diff_mat[4][4]; - float fpt[3]; + /* undo matrix */ + float diff_mat[4][4]; + float inverse_diff_mat[4][4]; + float fpt[3]; - ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat); - invert_m4_m4(inverse_diff_mat, diff_mat); + ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat); + invert_m4_m4(inverse_diff_mat, diff_mat); - mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x); - copy_v3_v3(&pt->x, fpt); + mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x); + copy_v3_v3(&pt->x, fpt); } /** @@ -595,46 +609,44 @@ void gp_apply_parent_point(Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bG * \warning This assumes that the caller has already checked whether the stroke in question can be drawn. */ void gp_point_to_xy( - const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt, - int *r_x, int *r_y) + const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt, int *r_x, int *r_y) { - const ARegion *ar = gsc->ar; - const View2D *v2d = gsc->v2d; - const rctf *subrect = gsc->subrect; - int xyval[2]; - - /* sanity checks */ - BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D)); - BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D)); - - - if (gps->flag & GP_STROKE_3DSPACE) { - if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - *r_x = xyval[0]; - *r_y = xyval[1]; - } - else { - *r_x = V2D_IS_CLIPPED; - *r_y = V2D_IS_CLIPPED; - } - } - else if (gps->flag & GP_STROKE_2DSPACE) { - float vec[3] = {pt->x, pt->y, 0.0f}; - mul_m4_v3(gsc->mat, vec); - UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], r_x, r_y); - } - else { - if (subrect == NULL) { - /* normal 3D view (or view space) */ - *r_x = (int)(pt->x / 100 * ar->winx); - *r_y = (int)(pt->y / 100 * ar->winy); - } - else { - /* camera view, use subrect */ - *r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin; - *r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin; - } - } + const ARegion *ar = gsc->ar; + const View2D *v2d = gsc->v2d; + const rctf *subrect = gsc->subrect; + int xyval[2]; + + /* sanity checks */ + BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D)); + BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D)); + + if (gps->flag & GP_STROKE_3DSPACE) { + if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + *r_x = xyval[0]; + *r_y = xyval[1]; + } + else { + *r_x = V2D_IS_CLIPPED; + *r_y = V2D_IS_CLIPPED; + } + } + else if (gps->flag & GP_STROKE_2DSPACE) { + float vec[3] = {pt->x, pt->y, 0.0f}; + mul_m4_v3(gsc->mat, vec); + UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], r_x, r_y); + } + else { + if (subrect == NULL) { + /* normal 3D view (or view space) */ + *r_x = (int)(pt->x / 100 * ar->winx); + *r_y = (int)(pt->y / 100 * ar->winy); + } + else { + /* camera view, use subrect */ + *r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin; + *r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin; + } + } } /** @@ -648,117 +660,119 @@ void gp_point_to_xy( * * \warning This assumes that the caller has already checked whether the stroke in question can be drawn. */ -void gp_point_to_xy_fl( - const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt, - float *r_x, float *r_y) +void gp_point_to_xy_fl(const GP_SpaceConversion *gsc, + const bGPDstroke *gps, + const bGPDspoint *pt, + float *r_x, + float *r_y) { - const ARegion *ar = gsc->ar; - const View2D *v2d = gsc->v2d; - const rctf *subrect = gsc->subrect; - float xyval[2]; - - /* sanity checks */ - BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D)); - BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D)); - - - if (gps->flag & GP_STROKE_3DSPACE) { - if (ED_view3d_project_float_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - *r_x = xyval[0]; - *r_y = xyval[1]; - } - else { - *r_x = 0.0f; - *r_y = 0.0f; - } - } - else if (gps->flag & GP_STROKE_2DSPACE) { - float vec[3] = {pt->x, pt->y, 0.0f}; - int t_x, t_y; - - mul_m4_v3(gsc->mat, vec); - UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y); - - if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) { - /* XXX: Or should we just always use the values as-is? */ - *r_x = 0.0f; - *r_y = 0.0f; - } - else { - *r_x = (float)t_x; - *r_y = (float)t_y; - } - } - else { - if (subrect == NULL) { - /* normal 3D view (or view space) */ - *r_x = (pt->x / 100.0f * ar->winx); - *r_y = (pt->y / 100.0f * ar->winy); - } - else { - /* camera view, use subrect */ - *r_x = ((pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin; - *r_y = ((pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin; - } - } + const ARegion *ar = gsc->ar; + const View2D *v2d = gsc->v2d; + const rctf *subrect = gsc->subrect; + float xyval[2]; + + /* sanity checks */ + BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D)); + BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D)); + + if (gps->flag & GP_STROKE_3DSPACE) { + if (ED_view3d_project_float_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + *r_x = xyval[0]; + *r_y = xyval[1]; + } + else { + *r_x = 0.0f; + *r_y = 0.0f; + } + } + else if (gps->flag & GP_STROKE_2DSPACE) { + float vec[3] = {pt->x, pt->y, 0.0f}; + int t_x, t_y; + + mul_m4_v3(gsc->mat, vec); + UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y); + + if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) { + /* XXX: Or should we just always use the values as-is? */ + *r_x = 0.0f; + *r_y = 0.0f; + } + else { + *r_x = (float)t_x; + *r_y = (float)t_y; + } + } + else { + if (subrect == NULL) { + /* normal 3D view (or view space) */ + *r_x = (pt->x / 100.0f * ar->winx); + *r_y = (pt->y / 100.0f * ar->winy); + } + else { + /* camera view, use subrect */ + *r_x = ((pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin; + *r_y = ((pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin; + } + } } - /** * generic based on gp_point_to_xy_fl */ -void gp_point_3d_to_xy(const GP_SpaceConversion *gsc, const short flag, const float pt[3], float xy[2]) +void gp_point_3d_to_xy(const GP_SpaceConversion *gsc, + const short flag, + const float pt[3], + float xy[2]) { - const ARegion *ar = gsc->ar; - const View2D *v2d = gsc->v2d; - const rctf *subrect = gsc->subrect; - float xyval[2]; - - /* sanity checks */ - BLI_assert((gsc->sa->spacetype == SPACE_VIEW3D)); - - if (flag & GP_STROKE_3DSPACE) { - if (ED_view3d_project_float_global(ar, pt, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - xy[0] = xyval[0]; - xy[1] = xyval[1]; - } - else { - xy[0] = 0.0f; - xy[1] = 0.0f; - } - } - else if (flag & GP_STROKE_2DSPACE) { - float vec[3] = { pt[0], pt[1], 0.0f }; - int t_x, t_y; - - mul_m4_v3(gsc->mat, vec); - UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y); - - if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) { - /* XXX: Or should we just always use the values as-is? */ - xy[0] = 0.0f; - xy[1] = 0.0f; - } - else { - xy[0] = (float)t_x; - xy[1] = (float)t_y; - } - } - else { - if (subrect == NULL) { - /* normal 3D view (or view space) */ - xy[0] = (pt[0] / 100.0f * ar->winx); - xy[1] = (pt[1] / 100.0f * ar->winy); - } - else { - /* camera view, use subrect */ - xy[0] = ((pt[0] / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin; - xy[1] = ((pt[1] / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin; - } - } + const ARegion *ar = gsc->ar; + const View2D *v2d = gsc->v2d; + const rctf *subrect = gsc->subrect; + float xyval[2]; + + /* sanity checks */ + BLI_assert((gsc->sa->spacetype == SPACE_VIEW3D)); + + if (flag & GP_STROKE_3DSPACE) { + if (ED_view3d_project_float_global(ar, pt, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + xy[0] = xyval[0]; + xy[1] = xyval[1]; + } + else { + xy[0] = 0.0f; + xy[1] = 0.0f; + } + } + else if (flag & GP_STROKE_2DSPACE) { + float vec[3] = {pt[0], pt[1], 0.0f}; + int t_x, t_y; + + mul_m4_v3(gsc->mat, vec); + UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y); + + if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) { + /* XXX: Or should we just always use the values as-is? */ + xy[0] = 0.0f; + xy[1] = 0.0f; + } + else { + xy[0] = (float)t_x; + xy[1] = (float)t_y; + } + } + else { + if (subrect == NULL) { + /* normal 3D view (or view space) */ + xy[0] = (pt[0] / 100.0f * ar->winx); + xy[1] = (pt[1] / 100.0f * ar->winy); + } + else { + /* camera view, use subrect */ + xy[0] = ((pt[0] / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin; + xy[1] = ((pt[1] / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin; + } + } } - /** * Project screenspace coordinates to 3D-space * @@ -774,34 +788,37 @@ void gp_point_3d_to_xy(const GP_SpaceConversion *gsc, const short flag, const fl * * \warning Assumes that it is getting called in a 3D view only. */ -bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc, Scene *scene, const float screen_co[2], float r_out[3]) +bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc, + Scene *scene, + const float screen_co[2], + float r_out[3]) { - const RegionView3D *rv3d = gsc->ar->regiondata; - float rvec[3]; + const RegionView3D *rv3d = gsc->ar->regiondata; + float rvec[3]; - ED_gp_get_drawing_reference( - scene, gsc->ob, gsc->gpl, - scene->toolsettings->gpencil_v3d_align, rvec); + ED_gp_get_drawing_reference( + scene, gsc->ob, gsc->gpl, scene->toolsettings->gpencil_v3d_align, rvec); - float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL); + float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL); - float mval_f[2], mval_prj[2]; - float dvec[3]; + float mval_f[2], mval_prj[2]; + float dvec[3]; - copy_v2_v2(mval_f, screen_co); + copy_v2_v2(mval_f, screen_co); - if (ED_view3d_project_float_global(gsc->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - sub_v2_v2v2(mval_f, mval_prj, mval_f); - ED_view3d_win_to_delta(gsc->ar, mval_f, dvec, zfac); - sub_v3_v3v3(r_out, rvec, dvec); + if (ED_view3d_project_float_global(gsc->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == + V3D_PROJ_RET_OK) { + sub_v2_v2v2(mval_f, mval_prj, mval_f); + ED_view3d_win_to_delta(gsc->ar, mval_f, dvec, zfac); + sub_v3_v3v3(r_out, rvec, dvec); - return true; - } - else { - zero_v3(r_out); + return true; + } + else { + zero_v3(r_out); - return false; - } + return false; + } } /** @@ -812,43 +829,45 @@ bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc, Scene *scene, const float * \param depth: Depth array (via #ED_view3d_autodist_depth()). * \param[out] r_out: The resulting 2D point data. */ -void gp_stroke_convertcoords_tpoint( - Scene *scene, ARegion *ar, - Object *ob, bGPDlayer *gpl, - const tGPspoint *point2D, float *depth, - float r_out[3]) +void gp_stroke_convertcoords_tpoint(Scene *scene, + ARegion *ar, + Object *ob, + bGPDlayer *gpl, + const tGPspoint *point2D, + float *depth, + float r_out[3]) { - ToolSettings *ts = scene->toolsettings; - - int mval_i[2]; - round_v2i_v2fl(mval_i, &point2D->x); - - if ((depth != NULL) && (ED_view3d_autodist_simple(ar, mval_i, r_out, 0, depth))) { - /* projecting onto 3D-Geometry - * - nothing more needs to be done here, since view_autodist_simple() has already done it - */ - } - else { - float mval_f[2] = {point2D->x, point2D->y}; - float mval_prj[2]; - float rvec[3], dvec[3]; - float zfac; - - /* Current method just converts each point in screen-coordinates to - * 3D-coordinates using the 3D-cursor as reference. - */ - ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, rvec); - zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL); - - if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - sub_v2_v2v2(mval_f, mval_prj, mval_f); - ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); - sub_v3_v3v3(r_out, rvec, dvec); - } - else { - zero_v3(r_out); - } - } + ToolSettings *ts = scene->toolsettings; + + int mval_i[2]; + round_v2i_v2fl(mval_i, &point2D->x); + + if ((depth != NULL) && (ED_view3d_autodist_simple(ar, mval_i, r_out, 0, depth))) { + /* projecting onto 3D-Geometry + * - nothing more needs to be done here, since view_autodist_simple() has already done it + */ + } + else { + float mval_f[2] = {point2D->x, point2D->y}; + float mval_prj[2]; + float rvec[3], dvec[3]; + float zfac; + + /* Current method just converts each point in screen-coordinates to + * 3D-coordinates using the 3D-cursor as reference. + */ + ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, rvec); + zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL); + + if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + sub_v2_v2v2(mval_f, mval_prj, mval_f); + ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); + sub_v3_v3v3(r_out, rvec, dvec); + } + else { + zero_v3(r_out); + } + } } /** @@ -856,209 +875,206 @@ void gp_stroke_convertcoords_tpoint( * \param[out] r_vec : Reference point found */ void ED_gp_get_drawing_reference( - const Scene *scene, const Object *ob, bGPDlayer *UNUSED(gpl), - char align_flag, float r_vec[3]) + const Scene *scene, const Object *ob, bGPDlayer *UNUSED(gpl), char align_flag, float r_vec[3]) { - const float *fp = scene->cursor.location; - - /* if using a gpencil object at cursor mode, can use the location of the object */ - if (align_flag & GP_PROJECT_VIEWSPACE) { - if (ob && (ob->type == OB_GPENCIL)) { - /* fallback (no strokes) - use cursor or object location */ - if (align_flag & GP_PROJECT_CURSOR) { - /* use 3D-cursor */ - copy_v3_v3(r_vec, fp); - } - else { - /* use object location */ - copy_v3_v3(r_vec, ob->obmat[3]); - } - } - } - else { - /* use 3D-cursor */ - copy_v3_v3(r_vec, fp); - } + const float *fp = scene->cursor.location; + + /* if using a gpencil object at cursor mode, can use the location of the object */ + if (align_flag & GP_PROJECT_VIEWSPACE) { + if (ob && (ob->type == OB_GPENCIL)) { + /* fallback (no strokes) - use cursor or object location */ + if (align_flag & GP_PROJECT_CURSOR) { + /* use 3D-cursor */ + copy_v3_v3(r_vec, fp); + } + else { + /* use object location */ + copy_v3_v3(r_vec, ob->obmat[3]); + } + } + } + else { + /* use 3D-cursor */ + copy_v3_v3(r_vec, fp); + } } void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *gps) { - Scene *scene = CTX_data_scene(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Object *ob = CTX_data_active_object(C); - bGPdata *gpd = (bGPdata *)ob->data; - GP_SpaceConversion gsc = { NULL }; + Scene *scene = CTX_data_scene(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Object *ob = CTX_data_active_object(C); + bGPdata *gpd = (bGPdata *)ob->data; + GP_SpaceConversion gsc = {NULL}; - bGPDspoint *pt; - int i; - float diff_mat[4][4]; - float inverse_diff_mat[4][4]; + bGPDspoint *pt; + int i; + float diff_mat[4][4]; + float inverse_diff_mat[4][4]; - /* init space conversion stuff */ - gp_point_conversion_init(C, &gsc); + /* init space conversion stuff */ + gp_point_conversion_init(C, &gsc); - ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat); - invert_m4_m4(inverse_diff_mat, diff_mat); + ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat); + invert_m4_m4(inverse_diff_mat, diff_mat); - /* Adjust each point */ - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - float xy[2]; + /* Adjust each point */ + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + float xy[2]; - bGPDspoint pt2; - gp_point_to_parent_space(pt, diff_mat, &pt2); - gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]); + bGPDspoint pt2; + gp_point_to_parent_space(pt, diff_mat, &pt2); + gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]); - /* Planar - All on same plane parallel to the viewplane */ - gp_point_xy_to_3d(&gsc, scene, xy, &pt->x); + /* Planar - All on same plane parallel to the viewplane */ + gp_point_xy_to_3d(&gsc, scene, xy, &pt->x); - /* Unapply parent corrections */ - mul_m4_v3(inverse_diff_mat, &pt->x); - } + /* Unapply parent corrections */ + mul_m4_v3(inverse_diff_mat, &pt->x); + } } /** * Reproject all points of the stroke to a plane locked to axis to avoid stroke offset */ -void ED_gp_project_stroke_to_plane( - const Scene *scene, const Object *ob, - const RegionView3D *rv3d, bGPDstroke *gps, - const float origin[3], const int axis) +void ED_gp_project_stroke_to_plane(const Scene *scene, + const Object *ob, + const RegionView3D *rv3d, + bGPDstroke *gps, + const float origin[3], + const int axis) { - const ToolSettings *ts = scene->toolsettings; - const View3DCursor *cursor = &scene->cursor; - float plane_normal[3]; - float vn[3]; - - float ray[3]; - float rpoint[3]; - - /* normal vector for a plane locked to axis */ - zero_v3(plane_normal); - if (axis < 0) { - /* if the axis is not locked, need a vector to the view direction - * in order to get the right size of the stroke. - */ - ED_view3d_global_to_vector(rv3d, origin, plane_normal); - } - else if (axis < 3) { - plane_normal[axis] = 1.0f; - /* if object, apply object rotation */ - if (ob && (ob->type == OB_GPENCIL)) { - float mat[4][4]; - copy_m4_m4(mat, ob->obmat); - - /* move origin to cursor */ - if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { - copy_v3_v3(mat[3], cursor->location); - } - - mul_mat3_m4_v3(mat, plane_normal); - } - } - else { - float scale[3] = { 1.0f, 1.0f, 1.0f }; - plane_normal[2] = 1.0f; - float mat[4][4]; - loc_eul_size_to_mat4(mat, - cursor->location, - cursor->rotation_euler, - scale); - - /* move origin to object */ - if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { - copy_v3_v3(mat[3], ob->obmat[3]); - } - - mul_mat3_m4_v3(mat, plane_normal); - } - - /* Reproject the points in the plane */ - for (int i = 0; i < gps->totpoints; i++) { - bGPDspoint *pt = &gps->points[i]; - - /* get a vector from the point with the current view direction of the viewport */ - ED_view3d_global_to_vector(rv3d, &pt->x, vn); - - /* calculate line extreme point to create a ray that cross the plane */ - mul_v3_fl(vn, -50.0f); - add_v3_v3v3(ray, &pt->x, vn); - - /* if the line never intersect, the point is not changed */ - if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) { - copy_v3_v3(&pt->x, rpoint); - } - } + const ToolSettings *ts = scene->toolsettings; + const View3DCursor *cursor = &scene->cursor; + float plane_normal[3]; + float vn[3]; + + float ray[3]; + float rpoint[3]; + + /* normal vector for a plane locked to axis */ + zero_v3(plane_normal); + if (axis < 0) { + /* if the axis is not locked, need a vector to the view direction + * in order to get the right size of the stroke. + */ + ED_view3d_global_to_vector(rv3d, origin, plane_normal); + } + else if (axis < 3) { + plane_normal[axis] = 1.0f; + /* if object, apply object rotation */ + if (ob && (ob->type == OB_GPENCIL)) { + float mat[4][4]; + copy_m4_m4(mat, ob->obmat); + + /* move origin to cursor */ + if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { + copy_v3_v3(mat[3], cursor->location); + } + + mul_mat3_m4_v3(mat, plane_normal); + } + } + else { + float scale[3] = {1.0f, 1.0f, 1.0f}; + plane_normal[2] = 1.0f; + float mat[4][4]; + loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale); + + /* move origin to object */ + if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { + copy_v3_v3(mat[3], ob->obmat[3]); + } + + mul_mat3_m4_v3(mat, plane_normal); + } + + /* Reproject the points in the plane */ + for (int i = 0; i < gps->totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + + /* get a vector from the point with the current view direction of the viewport */ + ED_view3d_global_to_vector(rv3d, &pt->x, vn); + + /* calculate line extreme point to create a ray that cross the plane */ + mul_v3_fl(vn, -50.0f); + add_v3_v3v3(ray, &pt->x, vn); + + /* if the line never intersect, the point is not changed */ + if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) { + copy_v3_v3(&pt->x, rpoint); + } + } } /** * Reproject given point to a plane locked to axis to avoid stroke offset * \param[in,out] pt: Point to affect */ -void ED_gp_project_point_to_plane( - const Scene *scene, const Object *ob, - const RegionView3D *rv3d, const float origin[3], - const int axis, bGPDspoint *pt) +void ED_gp_project_point_to_plane(const Scene *scene, + const Object *ob, + const RegionView3D *rv3d, + const float origin[3], + const int axis, + bGPDspoint *pt) { - const ToolSettings *ts = scene->toolsettings; - const View3DCursor *cursor = &scene->cursor; - float plane_normal[3]; - float vn[3]; - - float ray[3]; - float rpoint[3]; - - /* normal vector for a plane locked to axis */ - zero_v3(plane_normal); - if (axis < 0) { - /* if the axis is not locked, need a vector to the view direction - * in order to get the right size of the stroke. - */ - ED_view3d_global_to_vector(rv3d, origin, plane_normal); - } - else if (axis < 3) { - plane_normal[axis] = 1.0f; - /* if object, apply object rotation */ - if (ob && (ob->type == OB_GPENCIL)) { - float mat[4][4]; - copy_m4_m4(mat, ob->obmat); - - /* move origin to cursor */ - if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { - copy_v3_v3(mat[3], cursor->location); - } - - mul_mat3_m4_v3(mat, plane_normal); - } - } - else { - float scale[3] = { 1.0f, 1.0f, 1.0f }; - plane_normal[2] = 1.0f; - float mat[4][4]; - loc_eul_size_to_mat4(mat, - cursor->location, - cursor->rotation_euler, - scale); - - /* move origin to object */ - if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { - copy_v3_v3(mat[3], ob->obmat[3]); - } - - mul_mat3_m4_v3(mat, plane_normal); - } - - /* Reproject the points in the plane */ - /* get a vector from the point with the current view direction of the viewport */ - ED_view3d_global_to_vector(rv3d, &pt->x, vn); - - /* calculate line extrem point to create a ray that cross the plane */ - mul_v3_fl(vn, -50.0f); - add_v3_v3v3(ray, &pt->x, vn); - - /* if the line never intersect, the point is not changed */ - if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) { - copy_v3_v3(&pt->x, rpoint); - } + const ToolSettings *ts = scene->toolsettings; + const View3DCursor *cursor = &scene->cursor; + float plane_normal[3]; + float vn[3]; + + float ray[3]; + float rpoint[3]; + + /* normal vector for a plane locked to axis */ + zero_v3(plane_normal); + if (axis < 0) { + /* if the axis is not locked, need a vector to the view direction + * in order to get the right size of the stroke. + */ + ED_view3d_global_to_vector(rv3d, origin, plane_normal); + } + else if (axis < 3) { + plane_normal[axis] = 1.0f; + /* if object, apply object rotation */ + if (ob && (ob->type == OB_GPENCIL)) { + float mat[4][4]; + copy_m4_m4(mat, ob->obmat); + + /* move origin to cursor */ + if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { + copy_v3_v3(mat[3], cursor->location); + } + + mul_mat3_m4_v3(mat, plane_normal); + } + } + else { + float scale[3] = {1.0f, 1.0f, 1.0f}; + plane_normal[2] = 1.0f; + float mat[4][4]; + loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale); + + /* move origin to object */ + if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { + copy_v3_v3(mat[3], ob->obmat[3]); + } + + mul_mat3_m4_v3(mat, plane_normal); + } + + /* Reproject the points in the plane */ + /* get a vector from the point with the current view direction of the viewport */ + ED_view3d_global_to_vector(rv3d, &pt->x, vn); + + /* calculate line extrem point to create a ray that cross the plane */ + mul_v3_fl(vn, -50.0f); + add_v3_v3v3(ray, &pt->x, vn); + + /* if the line never intersect, the point is not changed */ + if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) { + copy_v3_v3(&pt->x, rpoint); + } } /* ******************************************************** */ @@ -1072,92 +1088,92 @@ void ED_gp_project_point_to_plane( */ void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide) { - bGPDspoint *temp_points; - int totnewpoints, oldtotpoints; - int i2; - - /* loop as many times as levels */ - for (int s = 0; s < subdivide; s++) { - totnewpoints = gps->totpoints - 1; - /* duplicate points in a temp area */ - temp_points = MEM_dupallocN(gps->points); - oldtotpoints = gps->totpoints; - - /* resize the points arrays */ - gps->totpoints += totnewpoints; - gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints); - if (gps->dvert != NULL) { - gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints); - } - gps->flag |= GP_STROKE_RECALC_GEOMETRY; - - /* move points from last to first to new place */ - i2 = gps->totpoints - 1; - for (int i = oldtotpoints - 1; i > 0; i--) { - bGPDspoint *pt = &temp_points[i]; - bGPDspoint *pt_final = &gps->points[i2]; - - copy_v3_v3(&pt_final->x, &pt->x); - pt_final->pressure = pt->pressure; - pt_final->strength = pt->strength; - pt_final->time = pt->time; - pt_final->flag = pt->flag; - pt_final->uv_fac = pt->uv_fac; - pt_final->uv_rot = pt->uv_rot; - - if (gps->dvert != NULL) { - MDeformVert *dvert = &gps->dvert[i]; - MDeformVert *dvert_final = &gps->dvert[i2]; - - dvert_final->totweight = dvert->totweight; - dvert_final->dw = dvert->dw; - } - - i2 -= 2; - } - /* interpolate mid points */ - i2 = 1; - for (int i = 0; i < oldtotpoints - 1; i++) { - bGPDspoint *pt = &temp_points[i]; - bGPDspoint *next = &temp_points[i + 1]; - bGPDspoint *pt_final = &gps->points[i2]; - - /* add a half way point */ - interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f); - pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f); - pt_final->strength = interpf(pt->strength, next->strength, 0.5f); - CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f); - pt_final->time = interpf(pt->time, next->time, 0.5f); - pt_final->uv_fac = interpf(pt->uv_fac, next->uv_fac, 0.5f); - pt_final->uv_rot = interpf(pt->uv_rot, next->uv_rot, 0.5f); - - if (gps->dvert != NULL) { - MDeformVert *dvert_final = &gps->dvert[i2]; - dvert_final->totweight = 0; - dvert_final->dw = NULL; - } - - i2 += 2; - } - - MEM_SAFE_FREE(temp_points); - - /* move points to smooth stroke */ - /* duplicate points in a temp area with the new subdivide data */ - temp_points = MEM_dupallocN(gps->points); - - /* extreme points are not changed */ - for (int i = 0; i < gps->totpoints - 2; i++) { - bGPDspoint *pt = &temp_points[i]; - bGPDspoint *next = &temp_points[i + 1]; - bGPDspoint *pt_final = &gps->points[i + 1]; - - /* move point */ - interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f); - } - /* free temp memory */ - MEM_SAFE_FREE(temp_points); - } + bGPDspoint *temp_points; + int totnewpoints, oldtotpoints; + int i2; + + /* loop as many times as levels */ + for (int s = 0; s < subdivide; s++) { + totnewpoints = gps->totpoints - 1; + /* duplicate points in a temp area */ + temp_points = MEM_dupallocN(gps->points); + oldtotpoints = gps->totpoints; + + /* resize the points arrays */ + gps->totpoints += totnewpoints; + gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints); + if (gps->dvert != NULL) { + gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints); + } + gps->flag |= GP_STROKE_RECALC_GEOMETRY; + + /* move points from last to first to new place */ + i2 = gps->totpoints - 1; + for (int i = oldtotpoints - 1; i > 0; i--) { + bGPDspoint *pt = &temp_points[i]; + bGPDspoint *pt_final = &gps->points[i2]; + + copy_v3_v3(&pt_final->x, &pt->x); + pt_final->pressure = pt->pressure; + pt_final->strength = pt->strength; + pt_final->time = pt->time; + pt_final->flag = pt->flag; + pt_final->uv_fac = pt->uv_fac; + pt_final->uv_rot = pt->uv_rot; + + if (gps->dvert != NULL) { + MDeformVert *dvert = &gps->dvert[i]; + MDeformVert *dvert_final = &gps->dvert[i2]; + + dvert_final->totweight = dvert->totweight; + dvert_final->dw = dvert->dw; + } + + i2 -= 2; + } + /* interpolate mid points */ + i2 = 1; + for (int i = 0; i < oldtotpoints - 1; i++) { + bGPDspoint *pt = &temp_points[i]; + bGPDspoint *next = &temp_points[i + 1]; + bGPDspoint *pt_final = &gps->points[i2]; + + /* add a half way point */ + interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f); + pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f); + pt_final->strength = interpf(pt->strength, next->strength, 0.5f); + CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f); + pt_final->time = interpf(pt->time, next->time, 0.5f); + pt_final->uv_fac = interpf(pt->uv_fac, next->uv_fac, 0.5f); + pt_final->uv_rot = interpf(pt->uv_rot, next->uv_rot, 0.5f); + + if (gps->dvert != NULL) { + MDeformVert *dvert_final = &gps->dvert[i2]; + dvert_final->totweight = 0; + dvert_final->dw = NULL; + } + + i2 += 2; + } + + MEM_SAFE_FREE(temp_points); + + /* move points to smooth stroke */ + /* duplicate points in a temp area with the new subdivide data */ + temp_points = MEM_dupallocN(gps->points); + + /* extreme points are not changed */ + for (int i = 0; i < gps->totpoints - 2; i++) { + bGPDspoint *pt = &temp_points[i]; + bGPDspoint *next = &temp_points[i + 1]; + bGPDspoint *pt_final = &gps->points[i + 1]; + + /* move point */ + interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f); + } + /* free temp memory */ + MEM_SAFE_FREE(temp_points); + } } /** @@ -1167,184 +1183,189 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide) */ void gp_randomize_stroke(bGPDstroke *gps, Brush *brush, RNG *rng) { - bGPDspoint *pt1, *pt2, *pt3; - float v1[3]; - float v2[3]; - if (gps->totpoints < 3) { - return; - } - - /* get two vectors using 3 points */ - pt1 = &gps->points[0]; - pt2 = &gps->points[1]; - pt3 = &gps->points[(int)(gps->totpoints * 0.75)]; - - sub_v3_v3v3(v1, &pt2->x, &pt1->x); - sub_v3_v3v3(v2, &pt3->x, &pt2->x); - normalize_v3(v1); - normalize_v3(v2); - - /* get normal vector to plane created by two vectors */ - float normal[3]; - cross_v3_v3v3(normal, v1, v2); - normalize_v3(normal); - - /* get orthogonal vector to plane to rotate random effect */ - float ortho[3]; - cross_v3_v3v3(ortho, v1, normal); - normalize_v3(ortho); - - /* Read all points and apply shift vector (first and last point not modified) */ - for (int i = 1; i < gps->totpoints - 1; i++) { - bGPDspoint *pt = &gps->points[i]; - /* get vector with shift (apply a division because random is too sensitive */ - const float fac = BLI_rng_get_float(rng) * (brush->gpencil_settings->draw_random_sub / 10.0f); - float svec[3]; - copy_v3_v3(svec, ortho); - if (BLI_rng_get_float(rng) > 0.5f) { - mul_v3_fl(svec, -fac); - } - else { - mul_v3_fl(svec, fac); - } - - /* apply shift */ - add_v3_v3(&pt->x, svec); - } + bGPDspoint *pt1, *pt2, *pt3; + float v1[3]; + float v2[3]; + if (gps->totpoints < 3) { + return; + } + + /* get two vectors using 3 points */ + pt1 = &gps->points[0]; + pt2 = &gps->points[1]; + pt3 = &gps->points[(int)(gps->totpoints * 0.75)]; + + sub_v3_v3v3(v1, &pt2->x, &pt1->x); + sub_v3_v3v3(v2, &pt3->x, &pt2->x); + normalize_v3(v1); + normalize_v3(v2); + + /* get normal vector to plane created by two vectors */ + float normal[3]; + cross_v3_v3v3(normal, v1, v2); + normalize_v3(normal); + + /* get orthogonal vector to plane to rotate random effect */ + float ortho[3]; + cross_v3_v3v3(ortho, v1, normal); + normalize_v3(ortho); + + /* Read all points and apply shift vector (first and last point not modified) */ + for (int i = 1; i < gps->totpoints - 1; i++) { + bGPDspoint *pt = &gps->points[i]; + /* get vector with shift (apply a division because random is too sensitive */ + const float fac = BLI_rng_get_float(rng) * (brush->gpencil_settings->draw_random_sub / 10.0f); + float svec[3]; + copy_v3_v3(svec, ortho); + if (BLI_rng_get_float(rng) > 0.5f) { + mul_v3_fl(svec, -fac); + } + else { + mul_v3_fl(svec, fac); + } + + /* apply shift */ + add_v3_v3(&pt->x, svec); + } } /* ******************************************************** */ /* Layer Parenting - Compute Parent Transforms */ /* calculate difference matrix */ -void ED_gpencil_parent_location( - const Depsgraph *depsgraph, Object *obact, bGPdata *UNUSED(gpd), - bGPDlayer *gpl, float diff_mat[4][4]) +void ED_gpencil_parent_location(const Depsgraph *depsgraph, + Object *obact, + bGPdata *UNUSED(gpd), + bGPDlayer *gpl, + float diff_mat[4][4]) { - Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact; - Object *obparent = gpl->parent; - Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) : obparent; - - /* if not layer parented, try with object parented */ - if (obparent_eval == NULL) { - if (ob_eval != NULL) { - if (ob_eval->type == OB_GPENCIL) { - copy_m4_m4(diff_mat, ob_eval->obmat); - return; - } - } - /* not gpencil object */ - unit_m4(diff_mat); - return; - } - else { - if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) { - mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); - return; - } - else if (gpl->partype == PARBONE) { - bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr); - if (pchan) { - float tmp_mat[4][4]; - mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat); - mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse); - } - else { - /* if bone not found use object (armature) */ - mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); - } - return; - } - else { - unit_m4(diff_mat); /* not defined type */ - } - } + Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact; + Object *obparent = gpl->parent; + Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) : + obparent; + + /* if not layer parented, try with object parented */ + if (obparent_eval == NULL) { + if (ob_eval != NULL) { + if (ob_eval->type == OB_GPENCIL) { + copy_m4_m4(diff_mat, ob_eval->obmat); + return; + } + } + /* not gpencil object */ + unit_m4(diff_mat); + return; + } + else { + if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) { + mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); + return; + } + else if (gpl->partype == PARBONE) { + bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr); + if (pchan) { + float tmp_mat[4][4]; + mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat); + mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse); + } + else { + /* if bone not found use object (armature) */ + mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); + } + return; + } + else { + unit_m4(diff_mat); /* not defined type */ + } + } } /* reset parent matrix for all layers */ void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata *gpd) { - bGPDspoint *pt; - int i; - float diff_mat[4][4]; - float cur_mat[4][4]; - - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - if (gpl->parent != NULL) { - /* calculate new matrix */ - if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) { - invert_m4_m4(cur_mat, gpl->parent->obmat); - } - else if (gpl->partype == PARBONE) { - bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr); - if (pchan) { - float tmp_mat[4][4]; - mul_m4_m4m4(tmp_mat, gpl->parent->obmat, pchan->pose_mat); - invert_m4_m4(cur_mat, tmp_mat); - } - } - - /* only redo if any change */ - if (!equals_m4m4(gpl->inverse, cur_mat)) { - /* first apply current transformation to all strokes */ - ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat); - for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { - for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - mul_m4_v3(diff_mat, &pt->x); - } - } - } - /* set new parent matrix */ - copy_m4_m4(gpl->inverse, cur_mat); - } - } - } + bGPDspoint *pt; + int i; + float diff_mat[4][4]; + float cur_mat[4][4]; + + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + if (gpl->parent != NULL) { + /* calculate new matrix */ + if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) { + invert_m4_m4(cur_mat, gpl->parent->obmat); + } + else if (gpl->partype == PARBONE) { + bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr); + if (pchan) { + float tmp_mat[4][4]; + mul_m4_m4m4(tmp_mat, gpl->parent->obmat, pchan->pose_mat); + invert_m4_m4(cur_mat, tmp_mat); + } + } + + /* only redo if any change */ + if (!equals_m4m4(gpl->inverse, cur_mat)) { + /* first apply current transformation to all strokes */ + ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat); + for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + mul_m4_v3(diff_mat, &pt->x); + } + } + } + /* set new parent matrix */ + copy_m4_m4(gpl->inverse, cur_mat); + } + } + } } /* ******************************************************** */ /* GP Object Stuff */ /* Helper function to create new OB_GPENCIL Object */ -Object *ED_gpencil_add_object(bContext *C, Scene *UNUSED(scene), const float loc[3], ushort local_view_bits) +Object *ED_gpencil_add_object(bContext *C, + Scene *UNUSED(scene), + const float loc[3], + ushort local_view_bits) { - float rot[3] = {0.0f}; + float rot[3] = {0.0f}; - Object *ob = ED_object_add_type(C, OB_GPENCIL, NULL, loc, rot, false, local_view_bits); + Object *ob = ED_object_add_type(C, OB_GPENCIL, NULL, loc, rot, false, local_view_bits); - /* create default brushes and colors */ - ED_gpencil_add_defaults(C, ob); + /* create default brushes and colors */ + ED_gpencil_add_defaults(C, ob); - return ob; + return ob; } /* Helper function to create default colors and drawing brushes */ void ED_gpencil_add_defaults(bContext *C, Object *ob) { - Main *bmain = CTX_data_main(C); - ToolSettings *ts = CTX_data_tool_settings(C); - - BKE_paint_ensure(ts, (Paint **)&ts->gp_paint); - Paint *paint = &ts->gp_paint->paint; - /* if not exist, create a new one */ - if (paint->brush == NULL) { - /* create new brushes */ - BKE_brush_gpencil_presets(C); - } - - /* ensure a color exists and is assigned to object */ - BKE_gpencil_object_material_ensure_from_active_input_toolsettings(bmain, ob, ts); - - /* ensure multiframe falloff curve */ - if (ts->gp_sculpt.cur_falloff == NULL) { - ts->gp_sculpt.cur_falloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); - CurveMapping *gp_falloff_curve = ts->gp_sculpt.cur_falloff; - curvemapping_initialize(gp_falloff_curve); - curvemap_reset( - gp_falloff_curve->cm, - &gp_falloff_curve->clipr, - CURVE_PRESET_GAUSS, - CURVEMAP_SLOPE_POSITIVE); - } + Main *bmain = CTX_data_main(C); + ToolSettings *ts = CTX_data_tool_settings(C); + + BKE_paint_ensure(ts, (Paint **)&ts->gp_paint); + Paint *paint = &ts->gp_paint->paint; + /* if not exist, create a new one */ + if (paint->brush == NULL) { + /* create new brushes */ + BKE_brush_gpencil_presets(C); + } + + /* ensure a color exists and is assigned to object */ + BKE_gpencil_object_material_ensure_from_active_input_toolsettings(bmain, ob, ts); + + /* ensure multiframe falloff curve */ + if (ts->gp_sculpt.cur_falloff == NULL) { + ts->gp_sculpt.cur_falloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + CurveMapping *gp_falloff_curve = ts->gp_sculpt.cur_falloff; + curvemapping_initialize(gp_falloff_curve); + curvemap_reset(gp_falloff_curve->cm, + &gp_falloff_curve->clipr, + CURVE_PRESET_GAUSS, + CURVEMAP_SLOPE_POSITIVE); + } } /* ******************************************************** */ @@ -1353,213 +1374,209 @@ void ED_gpencil_add_defaults(bContext *C, Object *ob) /* assign points to vertex group */ void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight) { - bGPdata *gpd = (bGPdata *)ob->data; - const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const int def_nr = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) - return; - - CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) - { - bGPDframe *init_gpf = gpl->actframe; - bGPDstroke *gps = NULL; - if (is_multiedit) { - init_gpf = gpl->frames.first; - } - - for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { - if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { - if (gpf == NULL) - continue; - - for (gps = gpf->strokes.first; gps; gps = gps->next) { - - /* skip strokes that are invalid for current view */ - if (ED_gpencil_stroke_can_use(C, gps) == false) - continue; - - if (gps->flag & GP_STROKE_SELECT) { - /* verify the weight array is created */ - BKE_gpencil_dvert_ensure(gps); - - for (int i = 0; i < gps->totpoints; i++) { - bGPDspoint *pt = &gps->points[i]; - MDeformVert *dvert = &gps->dvert[i]; - if (pt->flag & GP_SPOINT_SELECT) { - MDeformWeight *dw = defvert_verify_index(dvert, def_nr); - if (dw) { - dw->weight = weight; - } - } - } - } - } - } - - /* if not multiedit, exit loop*/ - if (!is_multiedit) { - break; - } - } - } - CTX_DATA_END; + bGPdata *gpd = (bGPdata *)ob->data; + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const int def_nr = ob->actdef - 1; + if (!BLI_findlink(&ob->defbase, def_nr)) + return; + + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + bGPDframe *init_gpf = gpl->actframe; + bGPDstroke *gps = NULL; + if (is_multiedit) { + init_gpf = gpl->frames.first; + } + + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) + continue; + + for (gps = gpf->strokes.first; gps; gps = gps->next) { + + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) + continue; + + if (gps->flag & GP_STROKE_SELECT) { + /* verify the weight array is created */ + BKE_gpencil_dvert_ensure(gps); + + for (int i = 0; i < gps->totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + MDeformVert *dvert = &gps->dvert[i]; + if (pt->flag & GP_SPOINT_SELECT) { + MDeformWeight *dw = defvert_verify_index(dvert, def_nr); + if (dw) { + dw->weight = weight; + } + } + } + } + } + } + + /* if not multiedit, exit loop*/ + if (!is_multiedit) { + break; + } + } + } + CTX_DATA_END; } /* remove points from vertex group */ void ED_gpencil_vgroup_remove(bContext *C, Object *ob) { - bGPdata *gpd = (bGPdata *)ob->data; - const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const int def_nr = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) - return; - - CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) - { - bGPDframe *init_gpf = gpl->actframe; - bGPDstroke *gps = NULL; - if (is_multiedit) { - init_gpf = gpl->frames.first; - } - - for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { - if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { - if (gpf == NULL) - continue; - - for (gps = gpf->strokes.first; gps; gps = gps->next) { - - /* skip strokes that are invalid for current view */ - if (ED_gpencil_stroke_can_use(C, gps) == false) - continue; - - for (int i = 0; i < gps->totpoints; i++) { - bGPDspoint *pt = &gps->points[i]; - if (gps->dvert == NULL) { - continue; - } - MDeformVert *dvert = &gps->dvert[i]; - - if ((pt->flag & GP_SPOINT_SELECT) && (dvert->totweight > 0)) { - MDeformWeight *dw = defvert_find_index(dvert, def_nr); - if (dw != NULL) { - defvert_remove_group(dvert, dw); - } - } - } - } - } - - /* if not multiedit, exit loop*/ - if (!is_multiedit) { - break; - } - } - } - CTX_DATA_END; + bGPdata *gpd = (bGPdata *)ob->data; + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const int def_nr = ob->actdef - 1; + if (!BLI_findlink(&ob->defbase, def_nr)) + return; + + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + bGPDframe *init_gpf = gpl->actframe; + bGPDstroke *gps = NULL; + if (is_multiedit) { + init_gpf = gpl->frames.first; + } + + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) + continue; + + for (gps = gpf->strokes.first; gps; gps = gps->next) { + + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) + continue; + + for (int i = 0; i < gps->totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + if (gps->dvert == NULL) { + continue; + } + MDeformVert *dvert = &gps->dvert[i]; + + if ((pt->flag & GP_SPOINT_SELECT) && (dvert->totweight > 0)) { + MDeformWeight *dw = defvert_find_index(dvert, def_nr); + if (dw != NULL) { + defvert_remove_group(dvert, dw); + } + } + } + } + } + + /* if not multiedit, exit loop*/ + if (!is_multiedit) { + break; + } + } + } + CTX_DATA_END; } /* select points of vertex group */ void ED_gpencil_vgroup_select(bContext *C, Object *ob) { - bGPdata *gpd = (bGPdata *)ob->data; - const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const int def_nr = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) - return; - - CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) - { - bGPDframe *init_gpf = gpl->actframe; - bGPDstroke *gps = NULL; - if (is_multiedit) { - init_gpf = gpl->frames.first; - } - - for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { - if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { - if (gpf == NULL) - continue; - - for (gps = gpf->strokes.first; gps; gps = gps->next) { - - /* skip strokes that are invalid for current view */ - if (ED_gpencil_stroke_can_use(C, gps) == false) - continue; - - for (int i = 0; i < gps->totpoints; i++) { - bGPDspoint *pt = &gps->points[i]; - if (gps->dvert == NULL) { - continue; - } - MDeformVert *dvert = &gps->dvert[i]; - - if (defvert_find_index(dvert, def_nr) != NULL) { - pt->flag |= GP_SPOINT_SELECT; - gps->flag |= GP_STROKE_SELECT; - } - } - } - } - - /* if not multiedit, exit loop*/ - if (!is_multiedit) { - break; - } - } - } - CTX_DATA_END; + bGPdata *gpd = (bGPdata *)ob->data; + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const int def_nr = ob->actdef - 1; + if (!BLI_findlink(&ob->defbase, def_nr)) + return; + + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + bGPDframe *init_gpf = gpl->actframe; + bGPDstroke *gps = NULL; + if (is_multiedit) { + init_gpf = gpl->frames.first; + } + + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) + continue; + + for (gps = gpf->strokes.first; gps; gps = gps->next) { + + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) + continue; + + for (int i = 0; i < gps->totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + if (gps->dvert == NULL) { + continue; + } + MDeformVert *dvert = &gps->dvert[i]; + + if (defvert_find_index(dvert, def_nr) != NULL) { + pt->flag |= GP_SPOINT_SELECT; + gps->flag |= GP_STROKE_SELECT; + } + } + } + } + + /* if not multiedit, exit loop*/ + if (!is_multiedit) { + break; + } + } + } + CTX_DATA_END; } /* unselect points of vertex group */ void ED_gpencil_vgroup_deselect(bContext *C, Object *ob) { - bGPdata *gpd = (bGPdata *)ob->data; - const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - const int def_nr = ob->actdef - 1; - if (!BLI_findlink(&ob->defbase, def_nr)) - return; - - CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) - { - bGPDframe *init_gpf = gpl->actframe; - bGPDstroke *gps = NULL; - if (is_multiedit) { - init_gpf = gpl->frames.first; - } - - for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { - if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { - if (gpf == NULL) - continue; - - for (gps = gpf->strokes.first; gps; gps = gps->next) { - - /* skip strokes that are invalid for current view */ - if (ED_gpencil_stroke_can_use(C, gps) == false) - continue; - - for (int i = 0; i < gps->totpoints; i++) { - bGPDspoint *pt = &gps->points[i]; - if (gps->dvert == NULL) { - continue; - } - MDeformVert *dvert = &gps->dvert[i]; - - if (defvert_find_index(dvert, def_nr) != NULL) { - pt->flag &= ~GP_SPOINT_SELECT; - } - } - } - } - - /* if not multiedit, exit loop*/ - if (!is_multiedit) { - break; - } - } - } - CTX_DATA_END; + bGPdata *gpd = (bGPdata *)ob->data; + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const int def_nr = ob->actdef - 1; + if (!BLI_findlink(&ob->defbase, def_nr)) + return; + + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + bGPDframe *init_gpf = gpl->actframe; + bGPDstroke *gps = NULL; + if (is_multiedit) { + init_gpf = gpl->frames.first; + } + + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) + continue; + + for (gps = gpf->strokes.first; gps; gps = gps->next) { + + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) + continue; + + for (int i = 0; i < gps->totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + if (gps->dvert == NULL) { + continue; + } + MDeformVert *dvert = &gps->dvert[i]; + + if (defvert_find_index(dvert, def_nr) != NULL) { + pt->flag &= ~GP_SPOINT_SELECT; + } + } + } + } + + /* if not multiedit, exit loop*/ + if (!is_multiedit) { + break; + } + } + } + CTX_DATA_END; } /* ******************************************************** */ @@ -1568,903 +1585,902 @@ void ED_gpencil_vgroup_deselect(bContext *C, Object *ob) /* check if cursor is in drawing region */ static bool gp_check_cursor_region(bContext *C, int mval_i[2]) { - ARegion *ar = CTX_wm_region(C); - ScrArea *sa = CTX_wm_area(C); - Object *ob = CTX_data_active_object(C); - - if ((ob == NULL) || - (!ELEM(ob->mode, OB_MODE_PAINT_GPENCIL, OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL))) - { - return false; - } - - /* TODO: add more spacetypes */ - if (!ELEM(sa->spacetype, SPACE_VIEW3D)) { - return false; - } - if ((ar) && (ar->regiontype != RGN_TYPE_WINDOW)) { - return false; - } - else if (ar) { - return BLI_rcti_isect_pt_v(&ar->winrct, mval_i); - } - else { - return false; - } + ARegion *ar = CTX_wm_region(C); + ScrArea *sa = CTX_wm_area(C); + Object *ob = CTX_data_active_object(C); + + if ((ob == NULL) || + (!ELEM(ob->mode, OB_MODE_PAINT_GPENCIL, OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL))) { + return false; + } + + /* TODO: add more spacetypes */ + if (!ELEM(sa->spacetype, SPACE_VIEW3D)) { + return false; + } + if ((ar) && (ar->regiontype != RGN_TYPE_WINDOW)) { + return false; + } + else if (ar) { + return BLI_rcti_isect_pt_v(&ar->winrct, mval_i); + } + else { + return false; + } } /* draw eraser cursor */ void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y) { - short radius = (short)brush->size; + short radius = (short)brush->size; - GPUVertFormat *format = immVertexFormat(); - const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + GPUVertFormat *format = immVertexFormat(); + const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - GPU_line_smooth(true); - GPU_blend(true); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + GPU_line_smooth(true); + GPU_blend(true); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - immUniformColor4ub(255, 100, 100, 20); - imm_draw_circle_fill_2d(shdr_pos, x, y, radius, 40); + immUniformColor4ub(255, 100, 100, 20); + imm_draw_circle_fill_2d(shdr_pos, x, y, radius, 40); - immUnbindProgram(); + immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - float viewport_size[4]; - glGetFloatv(GL_VIEWPORT, viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + float viewport_size[4]; + glGetFloatv(GL_VIEWPORT, viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f); - immUniform1i("colors_len", 0); /* "simple" mode */ - immUniform1f("dash_width", 12.0f); - immUniform1f("dash_factor", 0.5f); + immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f); + immUniform1i("colors_len", 0); /* "simple" mode */ + immUniform1f("dash_width", 12.0f); + immUniform1f("dash_factor", 0.5f); - imm_draw_circle_wire_2d( - shdr_pos, x, y, radius, - /* XXX Dashed shader gives bad results with sets of small segments currently, - * temp hack around the issue. :( */ - max_ii(8, radius / 2)); /* was fixed 40 */ + imm_draw_circle_wire_2d( + shdr_pos, + x, + y, + radius, + /* XXX Dashed shader gives bad results with sets of small segments currently, + * temp hack around the issue. :( */ + max_ii(8, radius / 2)); /* was fixed 40 */ - immUnbindProgram(); + immUnbindProgram(); - GPU_blend(false); - GPU_line_smooth(false); + GPU_blend(false); + GPU_line_smooth(false); } static bool gp_brush_cursor_poll(bContext *C) { - if (WM_toolsystem_active_tool_is_brush(C)) { - return true; - } - return false; + if (WM_toolsystem_active_tool_is_brush(C)) { + return true; + } + return false; } /* Helper callback for drawing the cursor itself */ static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata) { - Scene *scene = CTX_data_scene(C); - Object *ob = CTX_data_active_object(C); - ARegion *ar = CTX_wm_region(C); - - GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt; - bGPdata *gpd = ED_gpencil_data_get_active(C); - GP_Sculpt_Data *gp_brush = NULL; - Brush *brush = NULL; - Material *ma = NULL; - MaterialGPencilStyle *gp_style = NULL; - float *last_mouse_position = customdata; - - if ((gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE)) { - gp_brush = &gset->brush[gset->weighttype]; - } - else { - gp_brush = &gset->brush[gset->brushtype]; - } - - /* default radius and color */ - float color[3] = {1.0f, 1.0f, 1.0f}; - float darkcolor[3]; - float radius = 3.0f; - - int mval_i[2] = {x, y}; - /* check if cursor is in drawing region and has valid datablock */ - if ((!gp_check_cursor_region(C, mval_i)) || (gpd == NULL)) { - return; - } - - /* for paint use paint brush size and color */ - if (gpd->flag & GP_DATA_STROKE_PAINTMODE) { - brush = scene->toolsettings->gp_paint->paint.brush; - if ((brush == NULL) || (brush->gpencil_settings == NULL)) { - return; - } - - /* while drawing hide */ - if ((gpd->runtime.sbuffer_size > 0) && - ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) && - ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0)) - { - return; - } - - if ((brush->gpencil_settings->flag & GP_BRUSH_ENABLE_CURSOR) == 0) { - return; - } - - /* eraser has special shape and use a different shader program */ - if (brush->gpencil_tool == GPAINT_TOOL_ERASE) { - ED_gpencil_brush_draw_eraser(brush, x, y); - return; - } - - /* get current drawing color */ - ma = BKE_gpencil_object_material_get_from_brush(ob, brush); - - if (ma) { - gp_style = ma->gp_style; - - /* after some testing, display the size of the brush is not practical because - * is too disruptive and the size of cursor does not change with zoom factor. - * The decision was to use a fix size, instead of brush->thickness value. - */ - if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) && - ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) && - ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) && - (brush->gpencil_tool == GPAINT_TOOL_DRAW)) - { - radius = 2.0f; - copy_v3_v3(color, gp_style->stroke_rgba); - } - else { - radius = 5.0f; - copy_v3_v3(color, brush->add_col); - } - } - } - - /* for sculpt use sculpt brush size */ - if (GPENCIL_SCULPT_OR_WEIGHT_MODE(gpd)) { - if (gp_brush) { - if ((gp_brush->flag & GP_SCULPT_FLAG_ENABLE_CURSOR) == 0) { - return; - } - - radius = gp_brush->size; - if (gp_brush->flag & (GP_SCULPT_FLAG_INVERT | GP_SCULPT_FLAG_TMP_INVERT)) { - copy_v3_v3(color, gp_brush->curcolor_sub); - } - else { - copy_v3_v3(color, gp_brush->curcolor_add); - } - } - } - - /* draw icon */ - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - GPU_line_smooth(true); - GPU_blend(true); - - /* Inner Ring: Color from UI panel */ - immUniformColor4f(color[0], color[1], color[2], 0.8f); - if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) && - ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) && - ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) && - (brush->gpencil_tool == GPAINT_TOOL_DRAW)) - { - imm_draw_circle_fill_2d(pos, x, y, radius, 40); - } - else { - imm_draw_circle_wire_2d(pos, x, y, radius, 40); - } - - /* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */ - mul_v3_v3fl(darkcolor, color, 0.40f); - immUniformColor4f(darkcolor[0], darkcolor[1], darkcolor[2], 0.8f); - imm_draw_circle_wire_2d(pos, x, y, radius + 1, 40); - - GPU_blend(false); - GPU_line_smooth(false); - - /* Draw line for lazy mouse */ - if ((last_mouse_position) && - (brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP)) - { - GPU_line_smooth(true); - GPU_blend(true); - - copy_v3_v3(color, brush->add_col); - immUniformColor4f(color[0], color[1], color[2], 0.8f); - - immBegin(GPU_PRIM_LINES, 2); - immVertex2f(pos, x, y); - immVertex2f( - pos, - last_mouse_position[0] + ar->winrct.xmin, - last_mouse_position[1] + ar->winrct.ymin); - immEnd(); - - GPU_blend(false); - GPU_line_smooth(false); - } - - immUnbindProgram(); + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + ARegion *ar = CTX_wm_region(C); + + GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt; + bGPdata *gpd = ED_gpencil_data_get_active(C); + GP_Sculpt_Data *gp_brush = NULL; + Brush *brush = NULL; + Material *ma = NULL; + MaterialGPencilStyle *gp_style = NULL; + float *last_mouse_position = customdata; + + if ((gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE)) { + gp_brush = &gset->brush[gset->weighttype]; + } + else { + gp_brush = &gset->brush[gset->brushtype]; + } + + /* default radius and color */ + float color[3] = {1.0f, 1.0f, 1.0f}; + float darkcolor[3]; + float radius = 3.0f; + + int mval_i[2] = {x, y}; + /* check if cursor is in drawing region and has valid datablock */ + if ((!gp_check_cursor_region(C, mval_i)) || (gpd == NULL)) { + return; + } + + /* for paint use paint brush size and color */ + if (gpd->flag & GP_DATA_STROKE_PAINTMODE) { + brush = scene->toolsettings->gp_paint->paint.brush; + if ((brush == NULL) || (brush->gpencil_settings == NULL)) { + return; + } + + /* while drawing hide */ + if ((gpd->runtime.sbuffer_size > 0) && + ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) && + ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0)) { + return; + } + + if ((brush->gpencil_settings->flag & GP_BRUSH_ENABLE_CURSOR) == 0) { + return; + } + + /* eraser has special shape and use a different shader program */ + if (brush->gpencil_tool == GPAINT_TOOL_ERASE) { + ED_gpencil_brush_draw_eraser(brush, x, y); + return; + } + + /* get current drawing color */ + ma = BKE_gpencil_object_material_get_from_brush(ob, brush); + + if (ma) { + gp_style = ma->gp_style; + + /* after some testing, display the size of the brush is not practical because + * is too disruptive and the size of cursor does not change with zoom factor. + * The decision was to use a fix size, instead of brush->thickness value. + */ + if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) && + ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) && + ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) && + (brush->gpencil_tool == GPAINT_TOOL_DRAW)) { + radius = 2.0f; + copy_v3_v3(color, gp_style->stroke_rgba); + } + else { + radius = 5.0f; + copy_v3_v3(color, brush->add_col); + } + } + } + + /* for sculpt use sculpt brush size */ + if (GPENCIL_SCULPT_OR_WEIGHT_MODE(gpd)) { + if (gp_brush) { + if ((gp_brush->flag & GP_SCULPT_FLAG_ENABLE_CURSOR) == 0) { + return; + } + + radius = gp_brush->size; + if (gp_brush->flag & (GP_SCULPT_FLAG_INVERT | GP_SCULPT_FLAG_TMP_INVERT)) { + copy_v3_v3(color, gp_brush->curcolor_sub); + } + else { + copy_v3_v3(color, gp_brush->curcolor_add); + } + } + } + + /* draw icon */ + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + GPU_line_smooth(true); + GPU_blend(true); + + /* Inner Ring: Color from UI panel */ + immUniformColor4f(color[0], color[1], color[2], 0.8f); + if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) && + ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) && + ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) && + (brush->gpencil_tool == GPAINT_TOOL_DRAW)) { + imm_draw_circle_fill_2d(pos, x, y, radius, 40); + } + else { + imm_draw_circle_wire_2d(pos, x, y, radius, 40); + } + + /* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */ + mul_v3_v3fl(darkcolor, color, 0.40f); + immUniformColor4f(darkcolor[0], darkcolor[1], darkcolor[2], 0.8f); + imm_draw_circle_wire_2d(pos, x, y, radius + 1, 40); + + GPU_blend(false); + GPU_line_smooth(false); + + /* Draw line for lazy mouse */ + if ((last_mouse_position) && (brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP)) { + GPU_line_smooth(true); + GPU_blend(true); + + copy_v3_v3(color, brush->add_col); + immUniformColor4f(color[0], color[1], color[2], 0.8f); + + immBegin(GPU_PRIM_LINES, 2); + immVertex2f(pos, x, y); + immVertex2f( + pos, last_mouse_position[0] + ar->winrct.xmin, last_mouse_position[1] + ar->winrct.ymin); + immEnd(); + + GPU_blend(false); + GPU_line_smooth(false); + } + + immUnbindProgram(); } /* Turn brush cursor in on/off */ void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata) { - Scene *scene = CTX_data_scene(C); - GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt; - float *lastpost = customdata; - - if (gset->paintcursor && !enable) { - /* clear cursor */ - WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor); - gset->paintcursor = NULL; - } - else if (enable) { - /* in some situations cursor could be duplicated, so it is better disable first if exist */ - if (gset->paintcursor) { - /* clear cursor */ - WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor); - gset->paintcursor = NULL; - } - /* enable cursor */ - gset->paintcursor = WM_paint_cursor_activate( - CTX_wm_manager(C), - SPACE_TYPE_ANY, RGN_TYPE_ANY, - gp_brush_cursor_poll, - gp_brush_cursor_draw, - (lastpost) ? customdata : NULL); - } + Scene *scene = CTX_data_scene(C); + GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt; + float *lastpost = customdata; + + if (gset->paintcursor && !enable) { + /* clear cursor */ + WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor); + gset->paintcursor = NULL; + } + else if (enable) { + /* in some situations cursor could be duplicated, so it is better disable first if exist */ + if (gset->paintcursor) { + /* clear cursor */ + WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor); + gset->paintcursor = NULL; + } + /* enable cursor */ + gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C), + SPACE_TYPE_ANY, + RGN_TYPE_ANY, + gp_brush_cursor_poll, + gp_brush_cursor_draw, + (lastpost) ? customdata : NULL); + } } /* verify if is using the right brush */ static void gpencil_verify_brush_type(bContext *C, int newmode) { - ToolSettings *ts = CTX_data_tool_settings(C); - GP_Sculpt_Settings *gset = &ts->gp_sculpt; - - switch (newmode) { - case OB_MODE_SCULPT_GPENCIL: - gset->flag &= ~GP_SCULPT_SETT_FLAG_WEIGHT_MODE; - if ((gset->brushtype < 0) || (gset->brushtype >= GP_SCULPT_TYPE_WEIGHT)) { - gset->brushtype = GP_SCULPT_TYPE_PUSH; - } - break; - case OB_MODE_WEIGHT_GPENCIL: - gset->flag |= GP_SCULPT_SETT_FLAG_WEIGHT_MODE; - if ((gset->weighttype < GP_SCULPT_TYPE_WEIGHT) || (gset->weighttype >= GP_SCULPT_TYPE_MAX)) { - gset->weighttype = GP_SCULPT_TYPE_WEIGHT; - } - break; - default: - break; - } + ToolSettings *ts = CTX_data_tool_settings(C); + GP_Sculpt_Settings *gset = &ts->gp_sculpt; + + switch (newmode) { + case OB_MODE_SCULPT_GPENCIL: + gset->flag &= ~GP_SCULPT_SETT_FLAG_WEIGHT_MODE; + if ((gset->brushtype < 0) || (gset->brushtype >= GP_SCULPT_TYPE_WEIGHT)) { + gset->brushtype = GP_SCULPT_TYPE_PUSH; + } + break; + case OB_MODE_WEIGHT_GPENCIL: + gset->flag |= GP_SCULPT_SETT_FLAG_WEIGHT_MODE; + if ((gset->weighttype < GP_SCULPT_TYPE_WEIGHT) || (gset->weighttype >= GP_SCULPT_TYPE_MAX)) { + gset->weighttype = GP_SCULPT_TYPE_WEIGHT; + } + break; + default: + break; + } } /* set object modes */ void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode) { - if (!gpd) { - return; - } - - switch (newmode) { - case OB_MODE_EDIT_GPENCIL: - gpd->flag |= GP_DATA_STROKE_EDITMODE; - gpd->flag &= ~GP_DATA_STROKE_PAINTMODE; - gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE; - gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE; - ED_gpencil_toggle_brush_cursor(C, false, NULL); - break; - case OB_MODE_PAINT_GPENCIL: - gpd->flag &= ~GP_DATA_STROKE_EDITMODE; - gpd->flag |= GP_DATA_STROKE_PAINTMODE; - gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE; - gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE; - ED_gpencil_toggle_brush_cursor(C, true, NULL); - break; - case OB_MODE_SCULPT_GPENCIL: - gpd->flag &= ~GP_DATA_STROKE_EDITMODE; - gpd->flag &= ~GP_DATA_STROKE_PAINTMODE; - gpd->flag |= GP_DATA_STROKE_SCULPTMODE; - gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE; - gpencil_verify_brush_type(C, OB_MODE_SCULPT_GPENCIL); - ED_gpencil_toggle_brush_cursor(C, true, NULL); - break; - case OB_MODE_WEIGHT_GPENCIL: - gpd->flag &= ~GP_DATA_STROKE_EDITMODE; - gpd->flag &= ~GP_DATA_STROKE_PAINTMODE; - gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE; - gpd->flag |= GP_DATA_STROKE_WEIGHTMODE; - gpencil_verify_brush_type(C, OB_MODE_WEIGHT_GPENCIL); - ED_gpencil_toggle_brush_cursor(C, true, NULL); - break; - default: - gpd->flag &= ~GP_DATA_STROKE_EDITMODE; - gpd->flag &= ~GP_DATA_STROKE_PAINTMODE; - gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE; - gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE; - ED_gpencil_toggle_brush_cursor(C, false, NULL); - break; - } + if (!gpd) { + return; + } + + switch (newmode) { + case OB_MODE_EDIT_GPENCIL: + gpd->flag |= GP_DATA_STROKE_EDITMODE; + gpd->flag &= ~GP_DATA_STROKE_PAINTMODE; + gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE; + gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE; + ED_gpencil_toggle_brush_cursor(C, false, NULL); + break; + case OB_MODE_PAINT_GPENCIL: + gpd->flag &= ~GP_DATA_STROKE_EDITMODE; + gpd->flag |= GP_DATA_STROKE_PAINTMODE; + gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE; + gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE; + ED_gpencil_toggle_brush_cursor(C, true, NULL); + break; + case OB_MODE_SCULPT_GPENCIL: + gpd->flag &= ~GP_DATA_STROKE_EDITMODE; + gpd->flag &= ~GP_DATA_STROKE_PAINTMODE; + gpd->flag |= GP_DATA_STROKE_SCULPTMODE; + gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE; + gpencil_verify_brush_type(C, OB_MODE_SCULPT_GPENCIL); + ED_gpencil_toggle_brush_cursor(C, true, NULL); + break; + case OB_MODE_WEIGHT_GPENCIL: + gpd->flag &= ~GP_DATA_STROKE_EDITMODE; + gpd->flag &= ~GP_DATA_STROKE_PAINTMODE; + gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE; + gpd->flag |= GP_DATA_STROKE_WEIGHTMODE; + gpencil_verify_brush_type(C, OB_MODE_WEIGHT_GPENCIL); + ED_gpencil_toggle_brush_cursor(C, true, NULL); + break; + default: + gpd->flag &= ~GP_DATA_STROKE_EDITMODE; + gpd->flag &= ~GP_DATA_STROKE_PAINTMODE; + gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE; + gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE; + ED_gpencil_toggle_brush_cursor(C, false, NULL); + break; + } } /* helper to convert 2d to 3d for simple drawing buffer */ -static void gpencil_stroke_convertcoords(ARegion *ar, const tGPspoint *point2D, float origin[3], float out[3]) +static void gpencil_stroke_convertcoords(ARegion *ar, + const tGPspoint *point2D, + float origin[3], + float out[3]) { - float mval_f[2] = { (float)point2D->x, (float)point2D->y }; - float mval_prj[2]; - float rvec[3], dvec[3]; - float zfac; - - copy_v3_v3(rvec, origin); - - zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL); - - if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - sub_v2_v2v2(mval_f, mval_prj, mval_f); - ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); - sub_v3_v3v3(out, rvec, dvec); - } - else { - zero_v3(out); - } + float mval_f[2] = {(float)point2D->x, (float)point2D->y}; + float mval_prj[2]; + float rvec[3], dvec[3]; + float zfac; + + copy_v3_v3(rvec, origin); + + zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL); + + if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + sub_v2_v2v2(mval_f, mval_prj, mval_f); + ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); + sub_v3_v3v3(out, rvec, dvec); + } + else { + zero_v3(out); + } } /* convert 2d tGPspoint to 3d bGPDspoint */ void ED_gpencil_tpoint_to_point(ARegion *ar, float origin[3], const tGPspoint *tpt, bGPDspoint *pt) { - float p3d[3]; - /* conversion to 3d format */ - gpencil_stroke_convertcoords(ar, tpt, origin, p3d); - copy_v3_v3(&pt->x, p3d); - - pt->pressure = tpt->pressure; - pt->strength = tpt->strength; - pt->uv_fac = tpt->uv_fac; - pt->uv_rot = tpt->uv_rot; + float p3d[3]; + /* conversion to 3d format */ + gpencil_stroke_convertcoords(ar, tpt, origin, p3d); + copy_v3_v3(&pt->x, p3d); + + pt->pressure = tpt->pressure; + pt->strength = tpt->strength; + pt->uv_fac = tpt->uv_fac; + pt->uv_rot = tpt->uv_rot; } /* texture coordinate utilities */ void ED_gpencil_calc_stroke_uv(Object *ob, bGPDstroke *gps) { - if (gps == NULL) { - return; - } - MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); - float pixsize; - if (gp_style) { - pixsize = gp_style->texture_pixsize / 1000000.0f; - } - else { - /* use this value by default */ - pixsize = 0.0001f; - } - pixsize = MAX2(pixsize, 0.0000001f); - - bGPDspoint *pt = NULL; - bGPDspoint *ptb = NULL; - int i; - float totlen = 0.0f; - - /* first read all points and calc distance */ - for (i = 0; i < gps->totpoints; i++) { - pt = &gps->points[i]; - /* first point */ - if (i == 0) { - pt->uv_fac = 0.0f; - continue; - } - - ptb = &gps->points[i - 1]; - totlen += len_v3v3(&pt->x, &ptb->x) / pixsize; - pt->uv_fac = totlen; - } - - /* normalize the distance using a factor */ - float factor; - - /* if image, use texture width */ - if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && - (gp_style->sima)) - { - factor = gp_style->sima->gen_x; - } - else if (totlen == 0) { - return; - } - else { - factor = totlen; - } - - for (i = 0; i < gps->totpoints; i++) { - pt = &gps->points[i]; - pt->uv_fac /= factor; - } + if (gps == NULL) { + return; + } + MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); + float pixsize; + if (gp_style) { + pixsize = gp_style->texture_pixsize / 1000000.0f; + } + else { + /* use this value by default */ + pixsize = 0.0001f; + } + pixsize = MAX2(pixsize, 0.0000001f); + + bGPDspoint *pt = NULL; + bGPDspoint *ptb = NULL; + int i; + float totlen = 0.0f; + + /* first read all points and calc distance */ + for (i = 0; i < gps->totpoints; i++) { + pt = &gps->points[i]; + /* first point */ + if (i == 0) { + pt->uv_fac = 0.0f; + continue; + } + + ptb = &gps->points[i - 1]; + totlen += len_v3v3(&pt->x, &ptb->x) / pixsize; + pt->uv_fac = totlen; + } + + /* normalize the distance using a factor */ + float factor; + + /* if image, use texture width */ + if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) && + (gp_style->sima)) { + factor = gp_style->sima->gen_x; + } + else if (totlen == 0) { + return; + } + else { + factor = totlen; + } + + for (i = 0; i < gps->totpoints; i++) { + pt = &gps->points[i]; + pt->uv_fac /= factor; + } } /* recalc uv for any stroke using the material */ void ED_gpencil_update_color_uv(Main *bmain, Material *mat) { - Material *gps_ma = NULL; - /* read all strokes */ - for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { - if (ob->type == OB_GPENCIL) { - bGPdata *gpd = ob->data; - if (gpd == NULL) { - continue; - } - - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - /* only editable and visible layers are considered */ - if (gpencil_layer_is_editable(gpl)) { - for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { - for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - /* check if it is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { - continue; - } - gps_ma = give_current_material(ob, gps->mat_nr + 1); - /* update */ - if ((gps_ma) && (gps_ma == mat)) { - ED_gpencil_calc_stroke_uv(ob, gps); - } - } - } - } - } - DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - } - } + Material *gps_ma = NULL; + /* read all strokes */ + for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { + if (ob->type == OB_GPENCIL) { + bGPdata *gpd = ob->data; + if (gpd == NULL) { + continue; + } + + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + /* only editable and visible layers are considered */ + if (gpencil_layer_is_editable(gpl)) { + for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + /* check if it is editable */ + if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + continue; + } + gps_ma = give_current_material(ob, gps->mat_nr + 1); + /* update */ + if ((gps_ma) && (gps_ma == mat)) { + ED_gpencil_calc_stroke_uv(ob, gps); + } + } + } + } + } + DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + } + } } -static bool gpencil_check_collision( - bGPDstroke *gps, bGPDstroke **gps_array, GHash *all_2d, - int totstrokes, float p2d_a1[2], float p2d_a2[2], float r_hit[2]) +static bool gpencil_check_collision(bGPDstroke *gps, + bGPDstroke **gps_array, + GHash *all_2d, + int totstrokes, + float p2d_a1[2], + float p2d_a2[2], + float r_hit[2]) { - bool hit = false; - /* check segment with all segments of all strokes */ - for (int s = 0; s < totstrokes; s++) { - bGPDstroke *gps_iter = gps_array[s]; - if (gps_iter->totpoints < 2) { - continue; - } - /* get stroke 2d version */ - float(*points2d)[2] = BLI_ghash_lookup(all_2d, gps_iter); - - for (int i2 = 0; i2 < gps_iter->totpoints - 1; i2++) { - float p2d_b1[2], p2d_b2[2]; - copy_v2_v2(p2d_b1, points2d[i2]); - copy_v2_v2(p2d_b2, points2d[i2 + 1]); - - /* don't self check */ - if (gps == gps_iter) { - if (equals_v2v2(p2d_a1, p2d_b1) || equals_v2v2(p2d_a1, p2d_b2)) { - continue; - } - if (equals_v2v2(p2d_a2, p2d_b1) || equals_v2v2(p2d_a2, p2d_b2)) { - continue; - } - } - /* check collision */ - int check = isect_seg_seg_v2_point(p2d_a1, p2d_a2, p2d_b1, p2d_b2, r_hit); - if (check > 0) { - hit = true; - break; - } - } - - if (hit) { - break; - } - } - - if (!hit) { - zero_v2(r_hit); - } - - return hit; + bool hit = false; + /* check segment with all segments of all strokes */ + for (int s = 0; s < totstrokes; s++) { + bGPDstroke *gps_iter = gps_array[s]; + if (gps_iter->totpoints < 2) { + continue; + } + /* get stroke 2d version */ + float(*points2d)[2] = BLI_ghash_lookup(all_2d, gps_iter); + + for (int i2 = 0; i2 < gps_iter->totpoints - 1; i2++) { + float p2d_b1[2], p2d_b2[2]; + copy_v2_v2(p2d_b1, points2d[i2]); + copy_v2_v2(p2d_b2, points2d[i2 + 1]); + + /* don't self check */ + if (gps == gps_iter) { + if (equals_v2v2(p2d_a1, p2d_b1) || equals_v2v2(p2d_a1, p2d_b2)) { + continue; + } + if (equals_v2v2(p2d_a2, p2d_b1) || equals_v2v2(p2d_a2, p2d_b2)) { + continue; + } + } + /* check collision */ + int check = isect_seg_seg_v2_point(p2d_a1, p2d_a2, p2d_b1, p2d_b2, r_hit); + if (check > 0) { + hit = true; + break; + } + } + + if (hit) { + break; + } + } + + if (!hit) { + zero_v2(r_hit); + } + + return hit; } -static void gp_copy_points( - bGPDstroke *gps, bGPDspoint *pt, bGPDspoint *pt_final, int i, int i2) +static void gp_copy_points(bGPDstroke *gps, bGPDspoint *pt, bGPDspoint *pt_final, int i, int i2) { - /* don't copy same point */ - if (i == i2) { - return; - } - - copy_v3_v3(&pt_final->x, &pt->x); - pt_final->pressure = pt->pressure; - pt_final->strength = pt->strength; - pt_final->time = pt->time; - pt_final->flag = pt->flag; - pt_final->uv_fac = pt->uv_fac; - pt_final->uv_rot = pt->uv_rot; - - if (gps->dvert != NULL) { - MDeformVert *dvert = &gps->dvert[i]; - MDeformVert *dvert_final = &gps->dvert[i2]; - MEM_SAFE_FREE(dvert_final->dw); - - dvert_final->totweight = dvert->totweight; - if (dvert->dw == NULL) { - dvert_final->dw = NULL; - dvert_final->totweight = 0; - } - else { - dvert_final->dw = MEM_dupallocN(dvert->dw); - } - } - + /* don't copy same point */ + if (i == i2) { + return; + } + + copy_v3_v3(&pt_final->x, &pt->x); + pt_final->pressure = pt->pressure; + pt_final->strength = pt->strength; + pt_final->time = pt->time; + pt_final->flag = pt->flag; + pt_final->uv_fac = pt->uv_fac; + pt_final->uv_rot = pt->uv_rot; + + if (gps->dvert != NULL) { + MDeformVert *dvert = &gps->dvert[i]; + MDeformVert *dvert_final = &gps->dvert[i2]; + MEM_SAFE_FREE(dvert_final->dw); + + dvert_final->totweight = dvert->totweight; + if (dvert->dw == NULL) { + dvert_final->dw = NULL; + dvert_final->totweight = 0; + } + else { + dvert_final->dw = MEM_dupallocN(dvert->dw); + } + } } static void gp_insert_point( - bGPDstroke *gps, - bGPDspoint *a_pt, bGPDspoint *b_pt, - float co_a[3], float co_b[3]) + bGPDstroke *gps, bGPDspoint *a_pt, bGPDspoint *b_pt, float co_a[3], float co_b[3]) { - bGPDspoint *temp_points; - int totnewpoints, oldtotpoints; - - totnewpoints = gps->totpoints; - if (a_pt) { - totnewpoints++; - } - if (b_pt) { - totnewpoints++; - } - - /* duplicate points in a temp area */ - temp_points = MEM_dupallocN(gps->points); - oldtotpoints = gps->totpoints; - - /* look index of base points because memory is changed when resize points array */ - int a_idx = -1; - int b_idx = -1; - for (int i = 0; i < oldtotpoints; i++) { - bGPDspoint *pt = &gps->points[i]; - if (pt == a_pt) { - a_idx = i; - } - if (pt == b_pt) { - b_idx = i; - } - } - - /* resize the points arrays */ - gps->totpoints = totnewpoints; - gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints); - if (gps->dvert != NULL) { - gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints); - } - gps->flag |= GP_STROKE_RECALC_GEOMETRY; - - /* copy all points */ - int i2 = 0; - for (int i = 0; i < oldtotpoints; i++) { - bGPDspoint *pt = &temp_points[i]; - bGPDspoint *pt_final = &gps->points[i2]; - gp_copy_points(gps, pt, pt_final, i, i2); - - /* create new point duplicating point and copy location */ - if ((i == a_idx) || (i == b_idx)) { - i2++; - pt_final = &gps->points[i2]; - gp_copy_points(gps, pt, pt_final, i, i2); - copy_v3_v3(&pt_final->x, (i == a_idx) ? co_a : co_b); - - /* unselect */ - pt_final->flag &= ~GP_SPOINT_SELECT; - /* tag to avoid more checking with this point */ - pt_final->flag |= GP_SPOINT_TAG; - } - - i2++; - } - - MEM_SAFE_FREE(temp_points); + bGPDspoint *temp_points; + int totnewpoints, oldtotpoints; + + totnewpoints = gps->totpoints; + if (a_pt) { + totnewpoints++; + } + if (b_pt) { + totnewpoints++; + } + + /* duplicate points in a temp area */ + temp_points = MEM_dupallocN(gps->points); + oldtotpoints = gps->totpoints; + + /* look index of base points because memory is changed when resize points array */ + int a_idx = -1; + int b_idx = -1; + for (int i = 0; i < oldtotpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + if (pt == a_pt) { + a_idx = i; + } + if (pt == b_pt) { + b_idx = i; + } + } + + /* resize the points arrays */ + gps->totpoints = totnewpoints; + gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints); + if (gps->dvert != NULL) { + gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints); + } + gps->flag |= GP_STROKE_RECALC_GEOMETRY; + + /* copy all points */ + int i2 = 0; + for (int i = 0; i < oldtotpoints; i++) { + bGPDspoint *pt = &temp_points[i]; + bGPDspoint *pt_final = &gps->points[i2]; + gp_copy_points(gps, pt, pt_final, i, i2); + + /* create new point duplicating point and copy location */ + if ((i == a_idx) || (i == b_idx)) { + i2++; + pt_final = &gps->points[i2]; + gp_copy_points(gps, pt, pt_final, i, i2); + copy_v3_v3(&pt_final->x, (i == a_idx) ? co_a : co_b); + + /* unselect */ + pt_final->flag &= ~GP_SPOINT_SELECT; + /* tag to avoid more checking with this point */ + pt_final->flag |= GP_SPOINT_TAG; + } + + i2++; + } + + MEM_SAFE_FREE(temp_points); } static float gp_calc_factor(float p2d_a1[2], float p2d_a2[2], float r_hit2d[2]) { - float dist1 = len_squared_v2v2(p2d_a1, p2d_a2); - float dist2 = len_squared_v2v2(p2d_a1, r_hit2d); - float f = dist1 > 0.0f ? dist2 / dist1 : 0.0f; - - /* apply a correction factor */ - float v1[2]; - interp_v2_v2v2(v1, p2d_a1, p2d_a2, f); - float dist3 = len_squared_v2v2(p2d_a1, v1); - float f1 = dist1 > 0.0f ? dist3 / dist1 : 0.0f; - f = f + (f - f1); - - return f; + float dist1 = len_squared_v2v2(p2d_a1, p2d_a2); + float dist2 = len_squared_v2v2(p2d_a1, r_hit2d); + float f = dist1 > 0.0f ? dist2 / dist1 : 0.0f; + + /* apply a correction factor */ + float v1[2]; + interp_v2_v2v2(v1, p2d_a1, p2d_a2, f); + float dist3 = len_squared_v2v2(p2d_a1, v1); + float f1 = dist1 > 0.0f ? dist3 / dist1 : 0.0f; + f = f + (f - f1); + + return f; } /* extend selection to stroke intersections */ -int ED_gpencil_select_stroke_segment( - bGPDlayer *gpl, bGPDstroke *gps, bGPDspoint *pt, - bool select, bool insert, const float scale, - float r_hita[3], float r_hitb[3]) +int ED_gpencil_select_stroke_segment(bGPDlayer *gpl, + bGPDstroke *gps, + bGPDspoint *pt, + bool select, + bool insert, + const float scale, + float r_hita[3], + float r_hitb[3]) { - const float min_factor = 0.0015f; - bGPDspoint *pta1 = NULL; - bGPDspoint *pta2 = NULL; - float f = 0.0f; - int i2 = 0; - - bGPDframe *gpf = gpl->actframe; - if (gpf == NULL) { - return 0; - } - - int memsize = BLI_listbase_count(&gpf->strokes); - bGPDstroke **gps_array = MEM_callocN(sizeof(bGPDstroke *) * memsize, __func__); - - /* save points */ - bGPDspoint *oldpoints = MEM_dupallocN(gps->points); - - /* Save list of strokes to check */ - int totstrokes = 0; - for (bGPDstroke *gps_iter = gpf->strokes.first; gps_iter; gps_iter = gps_iter->next) { - if (gps_iter->totpoints < 2) { - continue; - } - gps_array[totstrokes] = gps_iter; - totstrokes++; - } - - if (totstrokes == 0) { - return 0; - } - - /* look for index of the current point */ - int cur_idx = -1; - for (int i = 0; i < gps->totpoints; i++) { - pta1 = &gps->points[i]; - if (pta1 == pt) { - cur_idx = i; - break; - } - } - if (cur_idx < 0) { - return 0; - } - - /* convert all gps points to 2d and save in a hash to avoid recalculation */ - int direction = 0; - float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points"); - BKE_gpencil_stroke_2d_flat_ref( - gps->points, gps->totpoints, - gps->points, gps->totpoints, points2d, scale, &direction); - - GHash *all_2d = BLI_ghash_ptr_new(__func__); - - for (int s = 0; s < totstrokes; s++) { - bGPDstroke *gps_iter = gps_array[s]; - float(*points2d_iter)[2] = MEM_mallocN(sizeof(*points2d_iter) * gps_iter->totpoints, __func__); - - /* the extremes of the stroke are scaled to improve collision detection - * for near lines */ - BKE_gpencil_stroke_2d_flat_ref( - gps->points, gps->totpoints, - gps_iter->points, gps_iter->totpoints, points2d_iter, - scale, &direction); - BLI_ghash_insert(all_2d, gps_iter, points2d_iter); - } - - bool hit_a = false; - bool hit_b = false; - float p2d_a1[2] = {0.0f, 0.0f}; - float p2d_a2[2] = {0.0f, 0.0f}; - float r_hit2d[2]; - bGPDspoint *hit_pointa = NULL; - bGPDspoint *hit_pointb = NULL; - - /* analyze points before current */ - if (cur_idx > 0) { - for (int i = cur_idx; i >= 0; i--) { - pta1 = &gps->points[i]; - copy_v2_v2(p2d_a1, points2d[i]); - - i2 = i - 1; - CLAMP_MIN(i2, 0); - pta2 = &gps->points[i2]; - copy_v2_v2(p2d_a2, points2d[i2]); - - hit_a = gpencil_check_collision( - gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d); - - if (select) { - pta1->flag |= GP_SPOINT_SELECT; - } - else { - pta1->flag &= ~GP_SPOINT_SELECT; - } - - if (hit_a) { - f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d); - interp_v3_v3v3(r_hita, &pta1->x, &pta2->x, f); - if (f > min_factor) { - hit_pointa = pta2; /* first point is second (inverted loop) */ - } - else { - pta1->flag &= ~GP_SPOINT_SELECT; - } - break; - } - } - } - - /* analyze points after current */ - for (int i = cur_idx; i < gps->totpoints; i++) { - pta1 = &gps->points[i]; - copy_v2_v2(p2d_a1, points2d[i]); - - i2 = i + 1; - CLAMP_MAX(i2, gps->totpoints - 1); - pta2 = &gps->points[i2]; - copy_v2_v2(p2d_a2, points2d[i2]); - - hit_b = gpencil_check_collision( - gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d); - - if (select) { - pta1->flag |= GP_SPOINT_SELECT; - } - else { - pta1->flag &= ~GP_SPOINT_SELECT; - } - - if (hit_b) { - f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d); - interp_v3_v3v3(r_hitb, &pta1->x, &pta2->x, f); - if (f > min_factor) { - hit_pointb = pta1; - } - else { - pta1->flag &= ~GP_SPOINT_SELECT; - } - break; - } - } - - /* insert new point in the collision points */ - if (insert) { - gp_insert_point(gps, hit_pointa, hit_pointb, r_hita, r_hitb); - } - - /* free memory */ - if (all_2d) { - GHashIterator gh_iter; - GHASH_ITER(gh_iter, all_2d) { - float(*p2d)[2] = BLI_ghashIterator_getValue(&gh_iter); - MEM_SAFE_FREE(p2d); - } - BLI_ghash_free(all_2d, NULL, NULL); - } - - /* if no hit, reset selection flag */ - if ((!hit_a) && (!hit_b)) { - for (int i = 0; i < gps->totpoints; i++) { - pta1 = &gps->points[i]; - pta2 = &oldpoints[i]; - pta1->flag = pta2->flag; - } - } - - MEM_SAFE_FREE(points2d); - MEM_SAFE_FREE(gps_array); - MEM_SAFE_FREE(oldpoints); - - /* return type of hit */ - if ((hit_a) && (hit_b)) { - return 3; - } - else if (hit_a) { - return 1; - } - else if (hit_b) { - return 2; - } - else { - return 0; - } + const float min_factor = 0.0015f; + bGPDspoint *pta1 = NULL; + bGPDspoint *pta2 = NULL; + float f = 0.0f; + int i2 = 0; + + bGPDframe *gpf = gpl->actframe; + if (gpf == NULL) { + return 0; + } + + int memsize = BLI_listbase_count(&gpf->strokes); + bGPDstroke **gps_array = MEM_callocN(sizeof(bGPDstroke *) * memsize, __func__); + + /* save points */ + bGPDspoint *oldpoints = MEM_dupallocN(gps->points); + + /* Save list of strokes to check */ + int totstrokes = 0; + for (bGPDstroke *gps_iter = gpf->strokes.first; gps_iter; gps_iter = gps_iter->next) { + if (gps_iter->totpoints < 2) { + continue; + } + gps_array[totstrokes] = gps_iter; + totstrokes++; + } + + if (totstrokes == 0) { + return 0; + } + + /* look for index of the current point */ + int cur_idx = -1; + for (int i = 0; i < gps->totpoints; i++) { + pta1 = &gps->points[i]; + if (pta1 == pt) { + cur_idx = i; + break; + } + } + if (cur_idx < 0) { + return 0; + } + + /* convert all gps points to 2d and save in a hash to avoid recalculation */ + int direction = 0; + float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, + "GP Stroke temp 2d points"); + BKE_gpencil_stroke_2d_flat_ref( + gps->points, gps->totpoints, gps->points, gps->totpoints, points2d, scale, &direction); + + GHash *all_2d = BLI_ghash_ptr_new(__func__); + + for (int s = 0; s < totstrokes; s++) { + bGPDstroke *gps_iter = gps_array[s]; + float(*points2d_iter)[2] = MEM_mallocN(sizeof(*points2d_iter) * gps_iter->totpoints, __func__); + + /* the extremes of the stroke are scaled to improve collision detection + * for near lines */ + BKE_gpencil_stroke_2d_flat_ref(gps->points, + gps->totpoints, + gps_iter->points, + gps_iter->totpoints, + points2d_iter, + scale, + &direction); + BLI_ghash_insert(all_2d, gps_iter, points2d_iter); + } + + bool hit_a = false; + bool hit_b = false; + float p2d_a1[2] = {0.0f, 0.0f}; + float p2d_a2[2] = {0.0f, 0.0f}; + float r_hit2d[2]; + bGPDspoint *hit_pointa = NULL; + bGPDspoint *hit_pointb = NULL; + + /* analyze points before current */ + if (cur_idx > 0) { + for (int i = cur_idx; i >= 0; i--) { + pta1 = &gps->points[i]; + copy_v2_v2(p2d_a1, points2d[i]); + + i2 = i - 1; + CLAMP_MIN(i2, 0); + pta2 = &gps->points[i2]; + copy_v2_v2(p2d_a2, points2d[i2]); + + hit_a = gpencil_check_collision(gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d); + + if (select) { + pta1->flag |= GP_SPOINT_SELECT; + } + else { + pta1->flag &= ~GP_SPOINT_SELECT; + } + + if (hit_a) { + f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d); + interp_v3_v3v3(r_hita, &pta1->x, &pta2->x, f); + if (f > min_factor) { + hit_pointa = pta2; /* first point is second (inverted loop) */ + } + else { + pta1->flag &= ~GP_SPOINT_SELECT; + } + break; + } + } + } + + /* analyze points after current */ + for (int i = cur_idx; i < gps->totpoints; i++) { + pta1 = &gps->points[i]; + copy_v2_v2(p2d_a1, points2d[i]); + + i2 = i + 1; + CLAMP_MAX(i2, gps->totpoints - 1); + pta2 = &gps->points[i2]; + copy_v2_v2(p2d_a2, points2d[i2]); + + hit_b = gpencil_check_collision(gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d); + + if (select) { + pta1->flag |= GP_SPOINT_SELECT; + } + else { + pta1->flag &= ~GP_SPOINT_SELECT; + } + + if (hit_b) { + f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d); + interp_v3_v3v3(r_hitb, &pta1->x, &pta2->x, f); + if (f > min_factor) { + hit_pointb = pta1; + } + else { + pta1->flag &= ~GP_SPOINT_SELECT; + } + break; + } + } + + /* insert new point in the collision points */ + if (insert) { + gp_insert_point(gps, hit_pointa, hit_pointb, r_hita, r_hitb); + } + + /* free memory */ + if (all_2d) { + GHashIterator gh_iter; + GHASH_ITER (gh_iter, all_2d) { + float(*p2d)[2] = BLI_ghashIterator_getValue(&gh_iter); + MEM_SAFE_FREE(p2d); + } + BLI_ghash_free(all_2d, NULL, NULL); + } + + /* if no hit, reset selection flag */ + if ((!hit_a) && (!hit_b)) { + for (int i = 0; i < gps->totpoints; i++) { + pta1 = &gps->points[i]; + pta2 = &oldpoints[i]; + pta1->flag = pta2->flag; + } + } + + MEM_SAFE_FREE(points2d); + MEM_SAFE_FREE(gps_array); + MEM_SAFE_FREE(oldpoints); + + /* return type of hit */ + if ((hit_a) && (hit_b)) { + return 3; + } + else if (hit_a) { + return 1; + } + else if (hit_b) { + return 2; + } + else { + return 0; + } } void ED_gpencil_select_toggle_all(bContext *C, int action) { - /* for "toggle", test for existing selected strokes */ - if (action == SEL_TOGGLE) { - action = SEL_SELECT; - - CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) - { - if (gps->flag & GP_STROKE_SELECT) { - action = SEL_DESELECT; - break; // XXX: this only gets out of the inner loop... - } - } - CTX_DATA_END; - } - - /* if deselecting, we need to deselect strokes across all frames - * - Currently, an exception is only given for deselection - * Selecting and toggling should only affect what's visible, - * while deselecting helps clean up unintended/forgotten - * stuff on other frames - */ - if (action == SEL_DESELECT) { - /* deselect strokes across editable layers - * NOTE: we limit ourselves to editable layers, since once a layer is "locked/hidden - * nothing should be able to touch it - */ - CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) - { - bGPDframe *gpf; - - /* deselect all strokes on all frames */ - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - bGPDstroke *gps; - - for (gps = gpf->strokes.first; gps; gps = gps->next) { - bGPDspoint *pt; - int i; - - /* only edit strokes that are valid in this view... */ - if (ED_gpencil_stroke_can_use(C, gps)) { - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - pt->flag &= ~GP_SPOINT_SELECT; - } - - gps->flag &= ~GP_STROKE_SELECT; - } - } - } - } - CTX_DATA_END; - } - else { - /* select or deselect all strokes */ - CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) - { - bGPDspoint *pt; - int i; - bool selected = false; - - /* Change selection status of all points, then make the stroke match */ - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - switch (action) { - case SEL_SELECT: - pt->flag |= GP_SPOINT_SELECT; - break; - //case SEL_DESELECT: - // pt->flag &= ~GP_SPOINT_SELECT; - // break; - case SEL_INVERT: - pt->flag ^= GP_SPOINT_SELECT; - break; - } - - if (pt->flag & GP_SPOINT_SELECT) - selected = true; - } - - /* Change status of stroke */ - if (selected) - gps->flag |= GP_STROKE_SELECT; - else - gps->flag &= ~GP_STROKE_SELECT; - } - CTX_DATA_END; - } + /* for "toggle", test for existing selected strokes */ + if (action == SEL_TOGGLE) { + action = SEL_SELECT; + + CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { + if (gps->flag & GP_STROKE_SELECT) { + action = SEL_DESELECT; + break; // XXX: this only gets out of the inner loop... + } + } + CTX_DATA_END; + } + + /* if deselecting, we need to deselect strokes across all frames + * - Currently, an exception is only given for deselection + * Selecting and toggling should only affect what's visible, + * while deselecting helps clean up unintended/forgotten + * stuff on other frames + */ + if (action == SEL_DESELECT) { + /* deselect strokes across editable layers + * NOTE: we limit ourselves to editable layers, since once a layer is "locked/hidden + * nothing should be able to touch it + */ + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + bGPDframe *gpf; + + /* deselect all strokes on all frames */ + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + bGPDstroke *gps; + + for (gps = gpf->strokes.first; gps; gps = gps->next) { + bGPDspoint *pt; + int i; + + /* only edit strokes that are valid in this view... */ + if (ED_gpencil_stroke_can_use(C, gps)) { + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + pt->flag &= ~GP_SPOINT_SELECT; + } + + gps->flag &= ~GP_STROKE_SELECT; + } + } + } + } + CTX_DATA_END; + } + else { + /* select or deselect all strokes */ + CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { + bGPDspoint *pt; + int i; + bool selected = false; + + /* Change selection status of all points, then make the stroke match */ + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + switch (action) { + case SEL_SELECT: + pt->flag |= GP_SPOINT_SELECT; + break; + //case SEL_DESELECT: + // pt->flag &= ~GP_SPOINT_SELECT; + // break; + case SEL_INVERT: + pt->flag ^= GP_SPOINT_SELECT; + break; + } + + if (pt->flag & GP_SPOINT_SELECT) + selected = true; + } + + /* Change status of stroke */ + if (selected) + gps->flag |= GP_STROKE_SELECT; + else + gps->flag &= ~GP_STROKE_SELECT; + } + CTX_DATA_END; + } } -- cgit v1.2.3