Cleanup: GPencil dissolve operator now uses GP_EDITABLE_STROKES_BEGIN macro
This reduces the number of loops
This commit is contained in:
parent
cb6e3e82b0
commit
a89ecd9617
|
@ -1810,238 +1810,208 @@ static int gp_delete_selected_strokes(bContext *C)
|
|||
static int gp_dissolve_selected_points(bContext *C, eGP_DissolveMode mode)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
||||
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
|
||||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
bool changed = false;
|
||||
int first = 0;
|
||||
int last = 0;
|
||||
|
||||
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
|
||||
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
|
||||
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
|
||||
/* the stroke must have at least one point selected for any operator */
|
||||
if (gps->flag & GP_STROKE_SELECT) {
|
||||
bGPDspoint *pt;
|
||||
MDeformVert *dvert = NULL;
|
||||
int i;
|
||||
|
||||
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
|
||||
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
|
||||
int tot = gps->totpoints; /* number of points in new buffer */
|
||||
|
||||
bGPDstroke *gps, *gpsn;
|
||||
/* first pass: count points to remove */
|
||||
switch (mode) {
|
||||
case GP_DISSOLVE_POINTS:
|
||||
/* Count how many points are selected (i.e. how many to remove) */
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
if (pt->flag & GP_SPOINT_SELECT) {
|
||||
/* selected point - one of the points to remove */
|
||||
tot--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GP_DISSOLVE_BETWEEN:
|
||||
/* need to find first and last point selected */
|
||||
first = -1;
|
||||
last = 0;
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
if (pt->flag & GP_SPOINT_SELECT) {
|
||||
if (first < 0) {
|
||||
first = i;
|
||||
}
|
||||
last = i;
|
||||
}
|
||||
}
|
||||
/* count unselected points in the range */
|
||||
for (i = first, pt = gps->points + first; i < last; i++, pt++) {
|
||||
if ((pt->flag & GP_SPOINT_SELECT) == 0) {
|
||||
tot--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GP_DISSOLVE_UNSELECT:
|
||||
/* count number of unselected points */
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
if ((pt->flag & GP_SPOINT_SELECT) == 0) {
|
||||
tot--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (gpf == NULL) {
|
||||
continue;
|
||||
/* if no points are left, we simply delete the entire stroke */
|
||||
if (tot <= 0) {
|
||||
/* remove the entire stroke */
|
||||
if (gps->points) {
|
||||
MEM_freeN(gps->points);
|
||||
}
|
||||
if (gps->dvert) {
|
||||
BKE_gpencil_free_stroke_weights(gps);
|
||||
MEM_freeN(gps->dvert);
|
||||
}
|
||||
if (gps->triangles) {
|
||||
MEM_freeN(gps->triangles);
|
||||
}
|
||||
BLI_freelinkN(&gpf_->strokes, gps);
|
||||
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
}
|
||||
else {
|
||||
/* just copy all points to keep into a smaller buffer */
|
||||
bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot,
|
||||
"new gp stroke points copy");
|
||||
bGPDspoint *npt = new_points;
|
||||
|
||||
MDeformVert *new_dvert = NULL;
|
||||
MDeformVert *ndvert = NULL;
|
||||
|
||||
if (gps->dvert != NULL) {
|
||||
new_dvert = MEM_callocN(sizeof(MDeformVert) * tot, "new gp stroke weights copy");
|
||||
ndvert = new_dvert;
|
||||
}
|
||||
|
||||
/* simply delete points from selected strokes
|
||||
* NOTE: we may still have to remove the stroke if it ends up having no points!
|
||||
*/
|
||||
for (gps = gpf->strokes.first; gps; gps = gpsn) {
|
||||
gpsn = gps->next;
|
||||
switch (mode) {
|
||||
case GP_DISSOLVE_POINTS:
|
||||
(gps->dvert != NULL) ? dvert = gps->dvert : NULL;
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
if ((pt->flag & GP_SPOINT_SELECT) == 0) {
|
||||
*npt = *pt;
|
||||
npt++;
|
||||
|
||||
/* skip strokes that are invalid for current view */
|
||||
if (ED_gpencil_stroke_can_use(C, gps) == false) {
|
||||
continue;
|
||||
}
|
||||
/* check if the color is editable */
|
||||
if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* the stroke must have at least one point selected for any operator */
|
||||
if (gps->flag & GP_STROKE_SELECT) {
|
||||
bGPDspoint *pt;
|
||||
MDeformVert *dvert = NULL;
|
||||
int i;
|
||||
|
||||
int tot = gps->totpoints; /* number of points in new buffer */
|
||||
|
||||
/* first pass: count points to remove */
|
||||
switch (mode) {
|
||||
case GP_DISSOLVE_POINTS:
|
||||
/* Count how many points are selected (i.e. how many to remove) */
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
if (pt->flag & GP_SPOINT_SELECT) {
|
||||
/* selected point - one of the points to remove */
|
||||
tot--;
|
||||
}
|
||||
if (gps->dvert != NULL) {
|
||||
*ndvert = *dvert;
|
||||
ndvert->dw = MEM_dupallocN(dvert->dw);
|
||||
ndvert++;
|
||||
}
|
||||
break;
|
||||
case GP_DISSOLVE_BETWEEN:
|
||||
/* need to find first and last point selected */
|
||||
first = -1;
|
||||
last = 0;
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
if (pt->flag & GP_SPOINT_SELECT) {
|
||||
if (first < 0) {
|
||||
first = i;
|
||||
}
|
||||
last = i;
|
||||
}
|
||||
}
|
||||
/* count unselected points in the range */
|
||||
for (i = first, pt = gps->points + first; i < last; i++, pt++) {
|
||||
if ((pt->flag & GP_SPOINT_SELECT) == 0) {
|
||||
tot--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GP_DISSOLVE_UNSELECT:
|
||||
/* count number of unselected points */
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
if ((pt->flag & GP_SPOINT_SELECT) == 0) {
|
||||
tot--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
if (gps->dvert != NULL) {
|
||||
dvert++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if no points are left, we simply delete the entire stroke */
|
||||
if (tot <= 0) {
|
||||
/* remove the entire stroke */
|
||||
if (gps->points) {
|
||||
MEM_freeN(gps->points);
|
||||
}
|
||||
if (gps->dvert) {
|
||||
BKE_gpencil_free_stroke_weights(gps);
|
||||
MEM_freeN(gps->dvert);
|
||||
}
|
||||
if (gps->triangles) {
|
||||
MEM_freeN(gps->triangles);
|
||||
}
|
||||
BLI_freelinkN(&gpf->strokes, gps);
|
||||
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
}
|
||||
else {
|
||||
/* just copy all points to keep into a smaller buffer */
|
||||
bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot,
|
||||
"new gp stroke points copy");
|
||||
bGPDspoint *npt = new_points;
|
||||
|
||||
MDeformVert *new_dvert = NULL;
|
||||
MDeformVert *ndvert = NULL;
|
||||
break;
|
||||
case GP_DISSOLVE_BETWEEN:
|
||||
/* copy first segment */
|
||||
(gps->dvert != NULL) ? dvert = gps->dvert : NULL;
|
||||
for (i = 0, pt = gps->points; i < first; i++, pt++) {
|
||||
*npt = *pt;
|
||||
npt++;
|
||||
|
||||
if (gps->dvert != NULL) {
|
||||
new_dvert = MEM_callocN(sizeof(MDeformVert) * tot, "new gp stroke weights copy");
|
||||
ndvert = new_dvert;
|
||||
*ndvert = *dvert;
|
||||
ndvert->dw = MEM_dupallocN(dvert->dw);
|
||||
ndvert++;
|
||||
dvert++;
|
||||
}
|
||||
}
|
||||
/* copy segment (selected points) */
|
||||
(gps->dvert != NULL) ? dvert = gps->dvert + first : NULL;
|
||||
for (i = first, pt = gps->points + first; i < last; i++, pt++) {
|
||||
if (pt->flag & GP_SPOINT_SELECT) {
|
||||
*npt = *pt;
|
||||
npt++;
|
||||
|
||||
switch (mode) {
|
||||
case GP_DISSOLVE_POINTS:
|
||||
(gps->dvert != NULL) ? dvert = gps->dvert : NULL;
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
if ((pt->flag & GP_SPOINT_SELECT) == 0) {
|
||||
*npt = *pt;
|
||||
npt++;
|
||||
|
||||
if (gps->dvert != NULL) {
|
||||
*ndvert = *dvert;
|
||||
ndvert->dw = MEM_dupallocN(dvert->dw);
|
||||
ndvert++;
|
||||
}
|
||||
}
|
||||
if (gps->dvert != NULL) {
|
||||
dvert++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GP_DISSOLVE_BETWEEN:
|
||||
/* copy first segment */
|
||||
(gps->dvert != NULL) ? dvert = gps->dvert : NULL;
|
||||
for (i = 0, pt = gps->points; i < first; i++, pt++) {
|
||||
*npt = *pt;
|
||||
npt++;
|
||||
|
||||
if (gps->dvert != NULL) {
|
||||
*ndvert = *dvert;
|
||||
ndvert->dw = MEM_dupallocN(dvert->dw);
|
||||
ndvert++;
|
||||
dvert++;
|
||||
}
|
||||
}
|
||||
/* copy segment (selected points) */
|
||||
(gps->dvert != NULL) ? dvert = gps->dvert + first : NULL;
|
||||
for (i = first, pt = gps->points + first; i < last; i++, pt++) {
|
||||
if (pt->flag & GP_SPOINT_SELECT) {
|
||||
*npt = *pt;
|
||||
npt++;
|
||||
|
||||
if (gps->dvert != NULL) {
|
||||
*ndvert = *dvert;
|
||||
ndvert->dw = MEM_dupallocN(dvert->dw);
|
||||
ndvert++;
|
||||
}
|
||||
}
|
||||
if (gps->dvert != NULL) {
|
||||
dvert++;
|
||||
}
|
||||
}
|
||||
/* copy last segment */
|
||||
(gps->dvert != NULL) ? dvert = gps->dvert + last : NULL;
|
||||
for (i = last, pt = gps->points + last; i < gps->totpoints; i++, pt++) {
|
||||
*npt = *pt;
|
||||
npt++;
|
||||
|
||||
if (gps->dvert != NULL) {
|
||||
*ndvert = *dvert;
|
||||
ndvert->dw = MEM_dupallocN(dvert->dw);
|
||||
ndvert++;
|
||||
dvert++;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case GP_DISSOLVE_UNSELECT:
|
||||
/* copy any selected point */
|
||||
(gps->dvert != NULL) ? dvert = gps->dvert : NULL;
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
if (pt->flag & GP_SPOINT_SELECT) {
|
||||
*npt = *pt;
|
||||
npt++;
|
||||
|
||||
if (gps->dvert != NULL) {
|
||||
*ndvert = *dvert;
|
||||
ndvert->dw = MEM_dupallocN(dvert->dw);
|
||||
ndvert++;
|
||||
}
|
||||
}
|
||||
if (gps->dvert != NULL) {
|
||||
dvert++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (gps->dvert != NULL) {
|
||||
*ndvert = *dvert;
|
||||
ndvert->dw = MEM_dupallocN(dvert->dw);
|
||||
ndvert++;
|
||||
}
|
||||
}
|
||||
|
||||
/* free the old buffer */
|
||||
if (gps->points) {
|
||||
MEM_freeN(gps->points);
|
||||
}
|
||||
if (gps->dvert) {
|
||||
BKE_gpencil_free_stroke_weights(gps);
|
||||
MEM_freeN(gps->dvert);
|
||||
if (gps->dvert != NULL) {
|
||||
dvert++;
|
||||
}
|
||||
}
|
||||
/* copy last segment */
|
||||
(gps->dvert != NULL) ? dvert = gps->dvert + last : NULL;
|
||||
for (i = last, pt = gps->points + last; i < gps->totpoints; i++, pt++) {
|
||||
*npt = *pt;
|
||||
npt++;
|
||||
|
||||
/* save the new buffer */
|
||||
gps->points = new_points;
|
||||
gps->dvert = new_dvert;
|
||||
gps->totpoints = tot;
|
||||
|
||||
/* triangles cache needs to be recalculated */
|
||||
gps->flag |= GP_STROKE_RECALC_GEOMETRY;
|
||||
gps->tot_triangles = 0;
|
||||
|
||||
/* deselect the stroke, since none of its selected points will still be selected */
|
||||
gps->flag &= ~GP_STROKE_SELECT;
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
pt->flag &= ~GP_SPOINT_SELECT;
|
||||
if (gps->dvert != NULL) {
|
||||
*ndvert = *dvert;
|
||||
ndvert->dw = MEM_dupallocN(dvert->dw);
|
||||
ndvert++;
|
||||
dvert++;
|
||||
}
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
break;
|
||||
case GP_DISSOLVE_UNSELECT:
|
||||
/* copy any selected point */
|
||||
(gps->dvert != NULL) ? dvert = gps->dvert : NULL;
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
if (pt->flag & GP_SPOINT_SELECT) {
|
||||
*npt = *pt;
|
||||
npt++;
|
||||
|
||||
if (gps->dvert != NULL) {
|
||||
*ndvert = *dvert;
|
||||
ndvert->dw = MEM_dupallocN(dvert->dw);
|
||||
ndvert++;
|
||||
}
|
||||
}
|
||||
if (gps->dvert != NULL) {
|
||||
dvert++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* free the old buffer */
|
||||
if (gps->points) {
|
||||
MEM_freeN(gps->points);
|
||||
}
|
||||
if (gps->dvert) {
|
||||
BKE_gpencil_free_stroke_weights(gps);
|
||||
MEM_freeN(gps->dvert);
|
||||
}
|
||||
|
||||
/* save the new buffer */
|
||||
gps->points = new_points;
|
||||
gps->dvert = new_dvert;
|
||||
gps->totpoints = tot;
|
||||
|
||||
/* triangles cache needs to be recalculated */
|
||||
gps->flag |= GP_STROKE_RECALC_GEOMETRY;
|
||||
gps->tot_triangles = 0;
|
||||
|
||||
/* deselect the stroke, since none of its selected points will still be selected */
|
||||
gps->flag &= ~GP_STROKE_SELECT;
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
pt->flag &= ~GP_SPOINT_SELECT;
|
||||
}
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
CTX_DATA_END;
|
||||
GP_EDITABLE_STROKES_END(gpstroke_iter);
|
||||
|
||||
if (changed) {
|
||||
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
|
|
Loading…
Reference in New Issue