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:
Diffstat (limited to 'source/blender/editors/gpencil/gpencil_edit_curve.c')
-rw-r--r--source/blender/editors/gpencil/gpencil_edit_curve.c241
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);
+}
/** \} */