diff options
Diffstat (limited to 'source/blender/editors/gpencil/gpencil_edit_curve.c')
-rw-r--r-- | source/blender/editors/gpencil/gpencil_edit_curve.c | 241 |
1 files changed, 155 insertions, 86 deletions
diff --git a/source/blender/editors/gpencil/gpencil_edit_curve.c b/source/blender/editors/gpencil/gpencil_edit_curve.c index e766a410889..925375d7103 100644 --- a/source/blender/editors/gpencil/gpencil_edit_curve.c +++ b/source/blender/editors/gpencil/gpencil_edit_curve.c @@ -35,6 +35,7 @@ #include "BKE_gpencil.h" #include "BKE_gpencil_curve.h" #include "BKE_gpencil_geom.h" +#include "BKE_report.h" #include "BLI_listbase.h" #include "BLI_math.h" @@ -49,91 +50,14 @@ #include "DEG_depsgraph.h" -#include "gpencil_intern.h" - -/* Poll callback for checking if there is an active layer and we are in curve edit mode. */ -static bool gpencil_curve_edit_mode_poll(bContext *C) -{ - Object *ob = CTX_data_active_object(C); - if ((ob == NULL) || (ob->type != OB_GPENCIL)) { - return false; - } - bGPdata *gpd = (bGPdata *)ob->data; - if (!GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)) { - return false; - } - - bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); - return (gpl != NULL); -} - -static int gpencil_stroke_enter_editcurve_mode_exec(bContext *C, wmOperator *op) -{ - Object *ob = CTX_data_active_object(C); - bGPdata *gpd = ob->data; - - float error_threshold = RNA_float_get(op->ptr, "error_threshold"); - gpd->curve_edit_threshold = error_threshold; +#include "UI_interface.h" +#include "UI_resources.h" - if (ELEM(NULL, gpd)) { - return OPERATOR_CANCELLED; - } - - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - if (gpf == gpl->actframe) { - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - /* only allow selected and non-converted strokes to be transformed */ - if ((gps->flag & GP_STROKE_SELECT && gps->editcurve == NULL) || - (gps->editcurve != NULL && gps->editcurve->flag & GP_CURVE_NEEDS_STROKE_UPDATE)) { - BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps); - /* Update the selection from the stroke to the curve. */ - BKE_gpencil_editcurve_stroke_sync_selection(gpd, gps, gps->editcurve); - gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE; - BKE_gpencil_stroke_geometry_update(gpd, gps); - } - } - } - } - } - - gpd->flag |= GP_DATA_CURVE_EDIT_MODE; - - /* notifiers */ - DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - - return OPERATOR_FINISHED; -} - -void GPENCIL_OT_stroke_enter_editcurve_mode(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Enter curve edit mode"; - ot->idname = "GPENCIL_OT_stroke_enter_editcurve_mode"; - ot->description = "Called to transform a stroke into a curve"; - - /* api callbacks */ - ot->exec = gpencil_stroke_enter_editcurve_mode_exec; - ot->poll = gpencil_active_layer_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +#include "gpencil_intern.h" - /* properties */ - prop = RNA_def_float(ot->srna, - "error_threshold", - 0.1f, - FLT_MIN, - 100.0f, - "Error Threshold", - "Threshold on the maximum deviation from the actual stroke", - FLT_MIN, - 10.0f); - RNA_def_property_ui_range(prop, FLT_MIN, 10.0f, 0.1f, 5); -} +/* -------------------------------------------------------------------- */ +/** \name Set handle type operator + * \{ */ static int gpencil_editcurve_set_handle_type_exec(bContext *C, wmOperator *op) { @@ -169,8 +93,7 @@ static int gpencil_editcurve_set_handle_type_exec(bContext *C, wmOperator *op) } BKE_gpencil_editcurve_recalculate_handles(gps); - gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE; - BKE_gpencil_stroke_geometry_update(gpd, gps); + BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_DEFAULT); } GP_EDITABLE_CURVES_END(gps_iter); @@ -199,7 +122,7 @@ void GPENCIL_OT_stroke_editcurve_set_handle_type(wmOperatorType *ot) /* api callbacks */ ot->invoke = WM_menu_invoke; ot->exec = gpencil_editcurve_set_handle_type_exec; - ot->poll = gpencil_curve_edit_mode_poll; + ot->poll = gpencil_active_layer_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -207,5 +130,151 @@ void GPENCIL_OT_stroke_editcurve_set_handle_type(wmOperatorType *ot) /* properties */ ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set stroke type operator + * \{ */ + +static int gpencil_stroke_set_type_exec(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_active_object(C); + bGPdata *gpd = ob->data; + eGPStrokeType type = RNA_enum_get(op->ptr, "type"); + const bool only_selected = RNA_boolean_get(op->ptr, "only_selected"); + + if (ELEM(NULL, gpd)) { + return OPERATOR_CANCELLED; + } + + bool changed = false; + switch (type) { + case STROKE_POLY: { + GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc) + { + if (only_selected && (gpc->flag & GP_CURVE_SELECT) == 0) { + continue; + } + BKE_gpencil_stroke_editcurve_sync_selection(gpd, gps, gpc); + BKE_gpencil_free_stroke_editcurve(gps); + changed = true; + } + GP_EDITABLE_CURVES_END(gps_iter); + } break; + + case STROKE_BEZIER: { + const float threshold = RNA_float_get(op->ptr, "threshold"); + const float corner_angle = RNA_float_get(op->ptr, "corner_angle"); + + GP_EDITABLE_STROKES_BEGIN (gps_iter, C, gpl, gps) { + if (!GPENCIL_STROKE_TYPE_BEZIER(gps)) { + if (only_selected && (gps->flag & GP_STROKE_SELECT) == 0) { + continue; + } + + BKE_gpencil_stroke_refit_curve(gps, threshold, corner_angle, GP_GEO_UPDATE_DEFAULT); + if (gps->editcurve != NULL) { + bGPDcurve *gpc = gps->editcurve; + BKE_gpencil_stroke_geometry_update(gpd, gps, GP_GEO_UPDATE_POLYLINE_REGENERATE_ALL); + + /* Select all curve points. */ + for (uint32_t i = 0; i < gpc->tot_curve_points; i++) { + bGPDcurve_point *pt = &gpc->curve_points[i]; + pt->flag |= GP_CURVE_POINT_SELECT; + BEZT_SEL_ALL(&pt->bezt); + } + gpc->flag |= GP_CURVE_SELECT; + + /* Deselect stroke points. */ + for (uint32_t i = 0; i < gps->totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + pt->flag &= ~GP_SPOINT_SELECT; + } + gps->flag &= ~GP_STROKE_SELECT; + changed = true; + } + } + } + GP_EDITABLE_STROKES_END(gps_iter); + } break; + default: { + BKE_report(op->reports, RPT_ERROR, "Unknown stroke type"); + return OPERATOR_CANCELLED; + } + } + + if (changed) { + /* notifiers */ + DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + } + + return OPERATOR_FINISHED; +} + +static void gpencil_stroke_set_type_ui(bContext *UNUSED(C), wmOperator *op) +{ + uiLayout *layout = op->layout; + PointerRNA ptr; + uiLayoutSetPropSep(layout, true); + RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + + uiItemR(layout, &ptr, "only_selected", 0, NULL, ICON_NONE); + eGPStrokeType type = RNA_enum_get(&ptr, "type"); + if (type == STROKE_BEZIER) { + uiItemR(layout, &ptr, "threshold", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "corner_angle", 0, NULL, ICON_NONE); + } +} + +void GPENCIL_OT_stroke_set_type(wmOperatorType *ot) +{ + PropertyRNA *prop; + static const EnumPropertyItem stroke_types[] = { + {STROKE_POLY, "POLY", 0, "Poly", ""}, + {STROKE_BEZIER, "BEZIER", 0, "Bezier", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + /* identifiers */ + ot->name = "Set Stroke Type"; + ot->idname = "GPENCIL_OT_stroke_set_type"; + ot->description = "Set the type of the stroke"; + + /* api callbacks */ + ot->exec = gpencil_stroke_set_type_exec; + ot->poll = gpencil_active_layer_poll; + ot->ui = gpencil_stroke_set_type_ui; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + prop = RNA_def_enum(ot->srna, "type", stroke_types, STROKE_POLY, "Type", "Stroke type"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_boolean( + ot->srna, "only_selected", true, "Selected Only", "Only set the type for selected strokes"); + + prop = RNA_def_float(ot->srna, + "threshold", + GP_DEFAULT_CURVE_ERROR, + 0.0f, + 100.0f, + "Threshold", + "Bézier curve fitting error threshold", + 0.0f, + 3.0f); + + prop = RNA_def_float_distance(ot->srna, + "corner_angle", + GP_DEFAULT_CURVE_EDIT_CORNER_ANGLE, + 0.0f, + M_PI, + "Corner Angle", + "Angle threshold to be treated as corners", + 0.0f, + M_PI); + RNA_def_property_subtype(prop, PROP_ANGLE); +} /** \} */ |