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:
-rw-r--r--source/blender/blenkernel/intern/gpencil_curve.c18
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c129
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c8
3 files changed, 140 insertions, 15 deletions
diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c
index 76901f91e34..f62bf72c490 100644
--- a/source/blender/blenkernel/intern/gpencil_curve.c
+++ b/source/blender/blenkernel/intern/gpencil_curve.c
@@ -563,6 +563,7 @@ void BKE_gpencil_convert_curve(Main *bmain,
/** \name Editcurve kernel functions
* \{ */
+/* Helper: generate curves with one or two curve points */
static bGPDcurve *gpencil_stroke_editcurve_generate_edgecases(bGPDstroke *gps,
const float stroke_radius)
{
@@ -590,8 +591,8 @@ static bGPDcurve *gpencil_stroke_editcurve_generate_edgecases(bGPDstroke *gps,
copy_v4_v4(cpt->vert_color, pt->vert_color);
/* default handle type */
- bezt->h1 = HD_FREE;
- bezt->h2 = HD_FREE;
+ bezt->h1 = HD_ALIGN;
+ bezt->h2 = HD_ALIGN;
cpt->point_index = 0;
@@ -624,10 +625,10 @@ static bGPDcurve *gpencil_stroke_editcurve_generate_edgecases(bGPDstroke *gps,
copy_v4_v4(cpt->vert_color, pt->vert_color);
/* default handle type */
- bezt->h1 = HD_VECT;
- bezt->h2 = HD_VECT;
+ bezt->h1 = HD_ALIGN;
+ bezt->h2 = HD_ALIGN;
- cpt->point_index = 0;
+ cpt->point_index = i;
}
return editcurve;
@@ -755,7 +756,7 @@ bGPDcurve *BKE_gpencil_stroke_editcurve_generate(bGPDstroke *gps,
*/
void BKE_gpencil_stroke_editcurve_update(bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps)
{
- if (gps == NULL || gps->totpoints < 0) {
+ if (gps == NULL || gps->totpoints <= 0) {
return;
}
@@ -768,9 +769,8 @@ void BKE_gpencil_stroke_editcurve_update(bGPdata *gpd, bGPDlayer *gpl, bGPDstrok
bGPDcurve *editcurve = BKE_gpencil_stroke_editcurve_generate(
gps, gpd->curve_edit_threshold, gpd->curve_edit_corner_angle, stroke_radius);
- if (editcurve == NULL) {
- return;
- }
+
+ BLI_assert(editcurve != NULL);
gps->editcurve = editcurve;
}
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index e0adbfe578d..9f0271c2aa4 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -921,6 +921,98 @@ static void gpencil_duplicate_points(bGPdata *gpd,
}
}
+static void gpencil_duplicate_selected_curve_points(
+ bGPdata *gpd, bGPDlayer *gpl, ListBase *new_strokes, bGPDstroke *gps, bGPDcurve *gpc)
+{
+ if (gpc == NULL) {
+ return;
+ }
+ const bool is_cyclic = gps->flag & GP_STROKE_CYCLIC;
+ const int idx_last = gpc->tot_curve_points - 1;
+ bGPDstroke *gps_first = NULL;
+ bGPDstroke *gps_last = NULL;
+
+ int idx_start = 0;
+ int idx_end = 0;
+ bool prev_selected = gpc->curve_points[0].flag & GP_CURVE_POINT_SELECT;
+ for (int i = 1; i < gpc->tot_curve_points; i++) {
+ bool selected = gpc->curve_points[i].flag & GP_CURVE_POINT_SELECT;
+ if (prev_selected == false && selected == true) {
+ idx_start = i;
+ }
+ /* Island ends if the current point is unselected or if we reached the end of the stroke. */
+ if ((prev_selected == true && selected == false) || (selected == true && i == idx_last)) {
+ idx_end = selected ? i : i - 1;
+ int island_length = idx_end - idx_start + 1;
+
+ bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps, false, false);
+ new_stroke->points = NULL;
+ if (island_length != gpc->tot_curve_points) {
+ new_stroke->flag &= ~GP_STROKE_CYCLIC;
+ }
+ new_stroke->editcurve = BKE_gpencil_stroke_editcurve_new(island_length);
+
+ if (gps_first == NULL) {
+ gps_first = new_stroke;
+ }
+
+ bGPDcurve *new_gpc = new_stroke->editcurve;
+ memcpy(new_gpc->curve_points,
+ gpc->curve_points + idx_start,
+ sizeof(bGPDcurve_point) * island_length);
+
+ BLI_strncpy(
+ new_stroke->runtime.tmp_layerinfo, gpl->info, sizeof(new_stroke->runtime.tmp_layerinfo));
+
+ BKE_gpencil_editcurve_recalculate_handles(new_stroke);
+ new_stroke->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
+
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gpd, new_stroke);
+
+ /* Insert stroke into frame. */
+ BLI_addtail(new_strokes, new_stroke);
+
+ gps_last = new_stroke;
+ }
+ prev_selected = selected;
+ }
+
+ /* join first and last stroke if cyclic */
+ if (is_cyclic && gps_first != NULL && gps_last != NULL && gps_first != gps_last) {
+ bGPDcurve *gpc_first = gps_first->editcurve;
+ bGPDcurve *gpc_last = gps_last->editcurve;
+ int first_tot_points = gpc_first->tot_curve_points;
+ int old_tot_points = gpc_last->tot_curve_points;
+
+ gpc_last->tot_curve_points = first_tot_points + old_tot_points;
+ gpc_last->curve_points = MEM_recallocN(gpc_last->curve_points,
+ sizeof(bGPDcurve_point) * gpc_last->tot_curve_points);
+ /* copy data from first to last */
+ memcpy(gpc_last->curve_points + old_tot_points,
+ gpc_first->curve_points,
+ sizeof(bGPDcurve_point) * first_tot_points);
+
+ BKE_gpencil_editcurve_recalculate_handles(gps_last);
+ gps_last->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
+
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gpd, gps_last);
+
+ /* remove first one */
+ BLI_remlink(new_strokes, gps_first);
+ BKE_gpencil_free_stroke(gps_first);
+ }
+
+ /* Deselect curve. */
+ for (int i = 0; i < gpc->tot_curve_points; i++) {
+ gpc->curve_points[i].flag &= ~GP_CURVE_POINT_SELECT;
+ BEZT_DESEL_ALL(&gpc->curve_points[i].bezt);
+ }
+ gpc->flag &= ~GP_CURVE_SELECT;
+ BKE_gpencil_stroke_editcurve_sync_selection(gps, gpc);
+}
+
static int gpencil_duplicate_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
@@ -938,7 +1030,31 @@ static int gpencil_duplicate_exec(bContext *C, wmOperator *op)
bool changed = false;
if (is_curve_edit) {
- BKE_report(op->reports, RPT_ERROR, "Not implemented!");
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ ListBase new_strokes = {NULL, NULL};
+ bGPDframe *gpf = gpl->actframe;
+ if (gpf == NULL) {
+ continue;
+ }
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ if (gps->editcurve == NULL) {
+ continue;
+ }
+
+ bGPDcurve *gpc = gps->editcurve;
+ if (gpc->flag & GP_CURVE_SELECT) {
+ gpencil_duplicate_selected_curve_points(gpd, gpl, &new_strokes, gps, gpc);
+ changed = true;
+ }
+ }
+
+ BLI_movelisttolist(&gpf->strokes, &new_strokes);
+ }
+ CTX_DATA_END;
}
else {
/* for each visible (and editable) layer's selected strokes,
@@ -1005,9 +1121,11 @@ static int gpencil_duplicate_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
}
- /* updates */
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ if (changed) {
+ /* updates */
+ 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;
}
@@ -2872,6 +2990,7 @@ static void gpencil_curve_delete_tagged_points(bGPdata *gpd,
idx_end = selected ? i - 1 : i;
int island_length = idx_end - idx_start + 1;
+#if 0
/* If an island has only a single curve point, there is no curve segment, so skip island */
if (island_length == 1) {
if (is_cyclic) {
@@ -2885,7 +3004,7 @@ static void gpencil_curve_delete_tagged_points(bGPdata *gpd,
continue;
}
}
-
+#endif
bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps, false, false);
new_stroke->points = NULL;
new_stroke->flag &= ~GP_STROKE_CYCLIC;
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 8b9f0fdb972..032e3fea458 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -46,6 +46,7 @@
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_font.h"
+#include "BKE_gpencil_curve.h"
#include "BKE_gpencil_geom.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
@@ -3050,9 +3051,14 @@ static int viewselected_exec(bContext *C, wmOperator *op)
}
if (is_gp_edit) {
+ const bool is_curve_edit = GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd_eval);
CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
/* we're only interested in selected points here... */
- if ((gps->flag & GP_STROKE_SELECT) && (gps->flag & GP_STROKE_3DSPACE)) {
+ if (is_curve_edit && gps->editcurve != NULL && gps->editcurve->flag & GP_CURVE_SELECT) {
+ BKE_gpencil_stroke_editcurve_sync_selection(gps, gps->editcurve);
+ ok |= BKE_gpencil_stroke_minmax(gps, true, min, max);
+ }
+ else if ((gps->flag & GP_STROKE_SELECT) && (gps->flag & GP_STROKE_3DSPACE)) {
ok |= BKE_gpencil_stroke_minmax(gps, true, min, max);
}
}