GPencil: New subdivide stroke operator
In some situations the artist needs to subdivide a stroke created with few points before, specially for sculpting. The subdivision is done for any pair of continuous selected points in the same stroke. The operator can be activated in edit mode with W key and has a parameter for number of cuts.
This commit is contained in:
parent
6f92604e53
commit
ac7ff55f11
|
@ -227,6 +227,7 @@ class GreasePencilStrokeEditPanel:
|
|||
|
||||
layout.separator()
|
||||
col = layout.column(align=True)
|
||||
col.operator("gpencil.stroke_subdivide", text="Subdivide")
|
||||
col.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
|
||||
col.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY'
|
||||
col.operator("gpencil.stroke_flip", text="Flip Direction")
|
||||
|
|
|
@ -1970,6 +1970,125 @@ void GPENCIL_OT_reproject(wmOperatorType *ot)
|
|||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************* Stroke subdivide ************************** */
|
||||
/* helper: Count how many points need to be inserted */
|
||||
static int gp_count_subdivision_cuts(bGPDstroke *gps)
|
||||
{
|
||||
bGPDspoint *pt;
|
||||
int i;
|
||||
int totnewpoints = 0;
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
|
||||
if (pt->flag & GP_SPOINT_SELECT) {
|
||||
if (i + 1 < gps->totpoints){
|
||||
if (gps->points[i + 1].flag & GP_SPOINT_SELECT) {
|
||||
++totnewpoints;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return totnewpoints;
|
||||
}
|
||||
static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
||||
bGPDspoint *temp_points;
|
||||
const int cuts = RNA_int_get(op->ptr, "number_cuts");
|
||||
|
||||
int totnewpoints, oldtotpoints;
|
||||
int i2;
|
||||
|
||||
/* sanity checks */
|
||||
if (ELEM(NULL, gpd))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* Go through each editable + selected stroke */
|
||||
GP_EDITABLE_STROKES_BEGIN(C, gpl, gps)
|
||||
{
|
||||
if (gps->flag & GP_STROKE_SELECT) {
|
||||
/* loop as many times as cuts */
|
||||
for (int s = 0; s < cuts; s++) {
|
||||
totnewpoints = gp_count_subdivision_cuts(gps);
|
||||
if (totnewpoints == 0) {
|
||||
continue;
|
||||
}
|
||||
/* duplicate points in a temp area */
|
||||
temp_points = MEM_dupallocN(gps->points);
|
||||
oldtotpoints = gps->totpoints;
|
||||
|
||||
/* resize the points arrys */
|
||||
gps->totpoints += totnewpoints;
|
||||
gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
|
||||
gps->flag |= GP_STROKE_RECALC_CACHES;
|
||||
|
||||
/* loop and interpolate */
|
||||
i2 = 0;
|
||||
for (int i = 0; i < oldtotpoints; i++) {
|
||||
bGPDspoint *pt = &temp_points[i];
|
||||
bGPDspoint *pt_final = &gps->points[i2];
|
||||
|
||||
/* copy current point */
|
||||
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;
|
||||
++i2;
|
||||
|
||||
/* if next point is selected add a half way point */
|
||||
if (pt->flag & GP_SPOINT_SELECT) {
|
||||
if (i + 1 < oldtotpoints){
|
||||
if (temp_points[i + 1].flag & GP_SPOINT_SELECT) {
|
||||
pt_final = &gps->points[i2];
|
||||
/* Interpolate all values */
|
||||
bGPDspoint *next = &temp_points[i + 1];
|
||||
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->flag |= GP_SPOINT_SELECT;
|
||||
++i2;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
/* free temp memory */
|
||||
MEM_freeN(temp_points);
|
||||
}
|
||||
}
|
||||
}
|
||||
GP_EDITABLE_STROKES_END;
|
||||
|
||||
/* notifiers */
|
||||
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GPENCIL_OT_stroke_subdivide(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* identifiers */
|
||||
ot->name = "Subdivide Stroke";
|
||||
ot->idname = "GPENCIL_OT_stroke_subdivide";
|
||||
ot->description = "Subdivide between continuous selected points of the stroke adding a point half way between them";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = gp_stroke_subdivide_exec;
|
||||
ot->poll = gp_active_layer_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
|
||||
|
||||
/* properties */
|
||||
prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, 5);
|
||||
/* avoid re-using last var because it can cause _very_ high value and annoy users */
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
}
|
||||
|
||||
/* ========= Interpolation operators ========================== */
|
||||
/* Helper: Update point with interpolation */
|
||||
static void gp_interpolate_update_points(bGPDstroke *gps_from, bGPDstroke *gps_to, bGPDstroke *new_stroke, float factor)
|
||||
|
|
|
@ -304,6 +304,7 @@ void GPENCIL_OT_stroke_apply_thickness(struct wmOperatorType *ot);
|
|||
void GPENCIL_OT_stroke_cyclical_set(struct wmOperatorType *ot);
|
||||
void GPENCIL_OT_stroke_join(struct wmOperatorType *ot);
|
||||
void GPENCIL_OT_stroke_flip(struct wmOperatorType *ot);
|
||||
void GPENCIL_OT_stroke_subdivide(struct wmOperatorType *ot);
|
||||
|
||||
void GPENCIL_OT_brush_add(struct wmOperatorType *ot);
|
||||
void GPENCIL_OT_brush_remove(struct wmOperatorType *ot);
|
||||
|
|
|
@ -242,6 +242,9 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
|
|||
|
||||
WM_keymap_add_item(keymap, "GPENCIL_OT_active_frames_delete_all", XKEY, KM_PRESS, KM_SHIFT, 0);
|
||||
|
||||
/* subdivide strokes */
|
||||
WM_keymap_add_item(keymap, "GPENCIL_OT_stroke_subdivide", WKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* join strokes */
|
||||
WM_keymap_add_item(keymap, "GPENCIL_OT_stroke_join", JKEY, KM_PRESS, KM_CTRL, 0);
|
||||
|
||||
|
@ -410,6 +413,7 @@ void ED_operatortypes_gpencil(void)
|
|||
WM_operatortype_append(GPENCIL_OT_stroke_cyclical_set);
|
||||
WM_operatortype_append(GPENCIL_OT_stroke_join);
|
||||
WM_operatortype_append(GPENCIL_OT_stroke_flip);
|
||||
WM_operatortype_append(GPENCIL_OT_stroke_subdivide);
|
||||
|
||||
WM_operatortype_append(GPENCIL_OT_palette_add);
|
||||
WM_operatortype_append(GPENCIL_OT_palette_remove);
|
||||
|
|
Loading…
Reference in New Issue