Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/editors/gpencil/gpencil_utils.c
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
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
Diffstat (limited to 'source/blender/editors/gpencil/gpencil_utils.c')
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c3928
1 files changed, 1972 insertions, 1956 deletions
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;
+ }
}