Bugfix T43293: Crash when editing shared GPencil datablock in VSE

The problem here was that when a Grease Pencil datablock is shared between
the 3D view and another one of the editors, all the strokes were getting handled
by the editing operators, even if those strokes could not be displayed/used
in that context. As a result, the coordinate conversion methods would fail,
as some of the needed data would not be set.

The fix here involves not including any offending strokes in such cases...
This commit is contained in:
Joshua Leung 2015-01-19 16:38:32 +13:00
parent 0a128af21d
commit 32ffc63d20
Notes: blender-bot 2023-02-14 09:36:38 +01:00
Referenced by issue #43293, Grease pencil crash on vse
6 changed files with 84 additions and 5 deletions

View File

@ -620,6 +620,10 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op)
/* make copies of selected strokes, and deselect these once we're done */
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) {
if (gps->totpoints == 1) {
/* Special Case: If there's just a single point in this stroke... */
@ -728,6 +732,10 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
/* make copies of selected strokes, and deselect these once we're done */
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) {
if (gps->totpoints == 1) {
/* Special Case: If there's just a single point in this stroke... */
@ -936,6 +944,11 @@ static int gp_delete_selected_strokes(bContext *C)
for (gps = gpf->strokes.first; gps; gps = gpsn) {
gpsn = gps->next;
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false)
continue;
/* free stroke if selected */
if (gps->flag & GP_STROKE_SELECT) {
/* free stroke memory arrays, then stroke itself */
if (gps->points) MEM_freeN(gps->points);
@ -975,6 +988,10 @@ static int gp_dissolve_selected_points(bContext *C)
for (gps = gpf->strokes.first; gps; gps = gpsn) {
gpsn = 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) {
bGPDspoint *pt;
int i;
@ -1050,6 +1067,11 @@ static int gp_delete_selected_points(bContext *C)
for (gps = gpf->strokes.first; gps; gps = gpsn) {
gpsn = 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) {
bGPDspoint *pt;
int i;

View File

@ -136,11 +136,14 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op)
bGPDspoint *pt;
int i;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
pt->flag &= ~GP_SPOINT_SELECT;
/* 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;
}
gps->flag &= ~GP_STROKE_SELECT;
}
}
}

View File

@ -90,6 +90,42 @@ bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]),
/* ******************************************************** */
/* Check whether given stroke can be edited given the supplied context */
// XXX: 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);
}
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);
}
/* ******************************************************** */
/* Init handling for space-conversion function (from passed-in parameters) */
void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
{

View File

@ -43,6 +43,7 @@ struct Object;
struct bGPdata;
struct bGPDlayer;
struct bGPDframe;
struct bGPDstroke;
struct PointerRNA;
struct ImBuf;
struct wmKeyConfig;
@ -80,6 +81,11 @@ struct bGPdata *ED_gpencil_data_get_active_direct(struct ID *screen_id, struct S
/* 3D View */
struct bGPdata *ED_gpencil_data_get_active_v3d(struct Scene *scene, struct View3D *v3d);
/* ----------- Stroke Editing Utilities ---------------- */
bool ED_gpencil_stroke_can_use_direct(const struct ScrArea *sa, const struct bGPDstroke *gps);
bool ED_gpencil_stroke_can_use(const struct bContext *C, const struct bGPDstroke *gps);
/* ----------- Grease Pencil Operators ----------------- */
void ED_keymap_gpencil(struct wmKeyConfig *keyconf);

View File

@ -497,7 +497,9 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
bGPDstroke *gps;
for (gps = gpf->strokes.first; gps; gps = gps->next) {
CTX_data_list_add(result, &gpd->id, &RNA_GPencilStroke, gps);
if (ED_gpencil_stroke_can_use_direct(sa, gps)) {
CTX_data_list_add(result, &gpd->id, &RNA_GPencilStroke, gps);
}
}
}
}

View File

@ -7321,6 +7321,11 @@ static void createTransGPencil(bContext *C, TransInfo *t)
bGPDstroke *gps;
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 (propedit) {
/* Proportional Editing... */
if (propedit_connected) {
@ -7424,6 +7429,11 @@ static void createTransGPencil(bContext *C, TransInfo *t)
TransData *tail = td;
bool stroke_ok;
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
/* What we need to include depends on proportional editing settings... */
if (propedit) {
if (propedit_connected) {