diff options
Diffstat (limited to 'source/blender/editors/curve/editcurve.c')
-rw-r--r-- | source/blender/editors/curve/editcurve.c | 843 |
1 files changed, 415 insertions, 428 deletions
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 2911611c516..4e1c07af001 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -36,7 +36,7 @@ #include "BLT_translation.h" #include "BKE_action.h" -#include "BKE_animsys.h" +#include "BKE_anim_data.h" #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_displist.h" @@ -58,6 +58,7 @@ #include "ED_curve.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_transform.h" #include "ED_transform_snap_object_context.h" @@ -81,6 +82,10 @@ static void adduplicateflagNurb( static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split); static bool curve_delete_vertices(Object *obedit, View3D *v3d); +/* -------------------------------------------------------------------- */ +/** \name Utility Functions + * \{ */ + ListBase *object_editcurve_get(Object *ob) { if (ob && ELEM(ob->type, OB_CURVE, OB_SURF)) { @@ -90,7 +95,11 @@ ListBase *object_editcurve_get(Object *ob) return NULL; } -/* ******************* PRINTS ********************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Debug Printing + * \{ */ #if 0 void printknots(Object *obedit) @@ -118,7 +127,11 @@ void printknots(Object *obedit) } #endif -/* ********************* Shape keys *************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Shape keys + * \{ */ static CVKeyIndex *init_cvKeyIndex( void *cv, int key_index, int nu_index, int pt_index, int vertex_index) @@ -897,7 +910,11 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs) } } -/* ********************* Amimation data *************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Animation Data + * \{ */ static bool curve_is_animated(Curve *cu) { @@ -919,13 +936,13 @@ static void fcurve_path_rename(AnimData *adt, nextfcu = fcu->next; if (STREQLEN(fcu->rna_path, orig_rna_path, len)) { char *spath, *suffix = fcu->rna_path + len; - nfcu = copy_fcurve(fcu); + nfcu = BKE_fcurve_copy(fcu); spath = nfcu->rna_path; nfcu->rna_path = BLI_sprintfN("%s%s", rna_path, suffix); - /* copy_fcurve() sets nfcu->grp to NULL. To maintain the groups, we need to keep the pointer. - * As a result, the group's 'channels' pointers will be wrong, which is fixed by calling - * `action_groups_reconstruct(action)` later, after all fcurves have been renamed. */ + /* BKE_fcurve_copy() sets nfcu->grp to NULL. To maintain the groups, we need to keep the + * pointer. As a result, the group's 'channels' pointers will be wrong, which is fixed by + * calling `action_groups_reconstruct(action)` later, after all fcurves have been renamed. */ nfcu->grp = fcu->grp; BLI_addtail(curves, nfcu); @@ -939,7 +956,7 @@ static void fcurve_path_rename(AnimData *adt, BLI_remlink(&adt->drivers, fcu); } - free_fcurve(fcu); + BKE_fcurve_free(fcu); MEM_freeN(spath); } @@ -955,7 +972,7 @@ static void fcurve_remove(AnimData *adt, ListBase *orig_curves, FCurve *fcu) action_groups_remove_channel(adt->action, fcu); } - free_fcurve(fcu); + BKE_fcurve_free(fcu); } static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) @@ -1114,7 +1131,11 @@ int ED_curve_updateAnimPaths(Main *bmain, Curve *cu) return 1; } -/* ********************* LOAD and MAKE *************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edit Mode Conversion (Make & Load) + * \{ */ static int *initialize_index_map(Object *obedit, int *r_old_totvert) { @@ -1354,7 +1375,11 @@ void ED_curve_editnurb_free(Object *obedit) BKE_curve_editNurb_free(cu); } -/******************** separate operator ***********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Separate Operator + * \{ */ static int separate_exec(bContext *C, wmOperator *op) { @@ -1476,6 +1501,8 @@ static int separate_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + ED_outliner_select_sync_from_object_tag(C); + return OPERATOR_FINISHED; } @@ -1495,7 +1522,11 @@ void CURVE_OT_separate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/******************** split operator ***********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Split Operator + * \{ */ static int curve_split_exec(bContext *C, wmOperator *op) { @@ -1563,7 +1594,11 @@ void CURVE_OT_split(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************* FLAGS ********************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Flag Utility Functions + * \{ */ static bool isNurbselUV(const Nurb *nu, int flag, int *r_u, int *r_v) { @@ -2532,7 +2567,11 @@ static void adduplicateflagNurb( } } -/**************** switch direction operator ***************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Switch Direction Operator + * \{ */ static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -2591,7 +2630,11 @@ void CURVE_OT_switch_direction(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/****************** set weight operator *******************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Weight Operator + * \{ */ static int set_goal_weight_exec(bContext *C, wmOperator *op) { @@ -2654,7 +2697,11 @@ void CURVE_OT_spline_weight_set(wmOperatorType *ot) RNA_def_float_factor(ot->srna, "weight", 1.0f, 0.0f, 1.0f, "Weight", "", 0.0f, 1.0f); } -/******************* set radius operator ******************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Radius Operator + * \{ */ static int set_radius_exec(bContext *C, wmOperator *op) { @@ -2718,7 +2765,11 @@ void CURVE_OT_radius_set(wmOperatorType *ot) ot->srna, "radius", 1.0f, 0.0f, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.0001f, 10.0f); } -/********************* smooth operator ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Smooth Vertices Operator + * \{ */ static void smooth_single_bezt(BezTriple *bezt, const BezTriple *bezt_orig_prev, @@ -2875,12 +2926,15 @@ void CURVE_OT_smooth(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + /* -------------------------------------------------------------------- */ -/* Smooth radius/weight/tilt +/** \name Smooth Operator (Radius/Weight/Tilt) Utilities * - * TODO: make smoothing distance based - * TODO: support cyclic curves - */ + * To do: + * - Make smoothing distance based. + * - Support cyclic curves. + * \{ */ static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, const int bp_offset) { @@ -3059,6 +3113,12 @@ static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, cons } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Smooth Weight Operator + * \{ */ + static int curve_smooth_weight_exec(bContext *C, wmOperator *UNUSED(op)) { ViewLayer *view_layer = CTX_data_view_layer(C); @@ -3096,6 +3156,12 @@ void CURVE_OT_smooth_weight(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Smooth Radius Operator + * \{ */ + static int curve_smooth_radius_exec(bContext *C, wmOperator *UNUSED(op)) { ViewLayer *view_layer = CTX_data_view_layer(C); @@ -3133,6 +3199,12 @@ void CURVE_OT_smooth_radius(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Smooth Tilt Operator + * \{ */ + static int curve_smooth_tilt_exec(bContext *C, wmOperator *UNUSED(op)) { ViewLayer *view_layer = CTX_data_view_layer(C); @@ -3170,7 +3242,11 @@ void CURVE_OT_smooth_tilt(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** hide operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hide Operator + * \{ */ static int hide_exec(bContext *C, wmOperator *op) { @@ -3269,7 +3345,11 @@ void CURVE_OT_hide(wmOperatorType *ot) RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected"); } -/********************** reveal operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Reveal Operator + * \{ */ static int reveal_exec(bContext *C, wmOperator *op) { @@ -3345,7 +3425,11 @@ void CURVE_OT_reveal(wmOperatorType *ot) RNA_def_boolean(ot->srna, "select", true, "Select", ""); } -/********************** subdivide operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Subdivide Operator + * \{ */ /** * Divide the line segments associated with the currently selected @@ -3508,6 +3592,7 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts) memcpy(bpn, nextbp, sizeof(BPoint)); interp_v4_v4v4(bpn->vec, bp->vec, nextbp->vec, factor); + bpn->radius = interpf(bp->radius, nextbp->radius, factor); bpn++; } } @@ -3800,179 +3885,11 @@ void CURVE_OT_subdivide(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/******************** find nearest ************************/ +/** \} */ -static void ED_curve_pick_vert__doClosest( - void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) -{ - struct { - BPoint *bp; - BezTriple *bezt; - Nurb *nurb; - float dist; - int hpoint, select; - float mval_fl[2]; - bool is_changed; - } *data = userData; - - short flag; - float dist_test; - - if (bp) { - flag = bp->f1; - } - else { - if (beztindex == 0) { - flag = bezt->f1; - } - else if (beztindex == 1) { - flag = bezt->f2; - } - else { - flag = bezt->f3; - } - } - - dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); - if ((flag & SELECT) == data->select) { - dist_test += 5.0f; - } - if (bezt && beztindex == 1) { - dist_test += 3.0f; /* middle points get a small disadvantage */ - } - - if (dist_test < data->dist) { - data->dist = dist_test; - - data->bp = bp; - data->bezt = bezt; - data->nurb = nu; - data->hpoint = bezt ? beztindex : 0; - data->is_changed = true; - } -} - -bool ED_curve_pick_vert(ViewContext *vc, - short sel, - Nurb **r_nurb, - BezTriple **r_bezt, - BPoint **r_bp, - short *r_handle, - Base **r_base) -{ - /* (sel == 1): selected gets a disadvantage */ - /* in nurb and bezt or bp the nearest is written */ - /* return 0 1 2: handlepunt */ - struct { - BPoint *bp; - BezTriple *bezt; - Nurb *nurb; - float dist; - int hpoint, select; - float mval_fl[2]; - bool is_changed; - } data = {NULL}; - - data.dist = ED_view3d_select_dist_px(); - data.hpoint = 0; - data.select = sel; - data.mval_fl[0] = vc->mval[0]; - data.mval_fl[1] = vc->mval[1]; - - uint bases_len; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( - vc->view_layer, vc->v3d, &bases_len); - for (uint base_index = 0; base_index < bases_len; base_index++) { - Base *base = bases[base_index]; - data.is_changed = false; - - ED_view3d_viewcontext_init_object(vc, base->object); - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - nurbs_foreachScreenVert(vc, ED_curve_pick_vert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - - if (r_base && data.is_changed) { - *r_base = base; - } - } - MEM_freeN(bases); - - *r_nurb = data.nurb; - *r_bezt = data.bezt; - *r_bp = data.bp; - - if (r_handle) { - *r_handle = data.hpoint; - } - - return (data.bezt || data.bp); -} - -static void findselectedNurbvert( - Curve *cu, View3D *v3d, Nurb **r_nu, BezTriple **r_bezt, BPoint **r_bp) -{ - /* in nu and (bezt or bp) selected are written if there's 1 sel. */ - /* if more points selected in 1 spline: return only nu, bezt and bp are 0 */ - ListBase *editnurb = &cu->editnurb->nurbs; - Nurb *nu1; - BezTriple *bezt1; - BPoint *bp1; - int a; - - *r_nu = NULL; - *r_bezt = NULL; - *r_bp = NULL; - - for (nu1 = editnurb->first; nu1; nu1 = nu1->next) { - if (nu1->type == CU_BEZIER) { - bezt1 = nu1->bezt; - a = nu1->pntsu; - while (a--) { - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1)) { - if (*r_nu != NULL && *r_nu != nu1) { - *r_nu = NULL; - *r_bp = NULL; - *r_bezt = NULL; - return; - } - else if (*r_bezt || *r_bp) { - *r_bp = NULL; - *r_bezt = NULL; - } - else { - *r_bezt = bezt1; - *r_nu = nu1; - } - } - bezt1++; - } - } - else { - bp1 = nu1->bp; - a = nu1->pntsu * nu1->pntsv; - while (a--) { - if (bp1->f1 & SELECT) { - if (*r_nu != NULL && *r_nu != nu1) { - *r_bp = NULL; - *r_bezt = NULL; - *r_nu = NULL; - return; - } - else if (*r_bezt || *r_bp) { - *r_bp = NULL; - *r_bezt = NULL; - } - else { - *r_bp = bp1; - *r_nu = nu1; - } - } - bp1++; - } - } - } -} - -/***************** set spline type operator *******************/ +/* -------------------------------------------------------------------- */ +/** \name Set Spline Type Operator + * \{ */ static int set_spline_type_exec(bContext *C, wmOperator *op) { @@ -4069,7 +3986,11 @@ void CURVE_OT_spline_type_set(wmOperatorType *ot) "Use handles when converting bezier curves into polygons"); } -/***************** set handle type operator *******************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Handle Type Operator + * \{ */ static int set_handle_type_exec(bContext *C, wmOperator *op) { @@ -4127,7 +4048,11 @@ void CURVE_OT_handle_type_set(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type"); } -/***************** recalculate handles operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Recalculate Handles Operator + * \{ */ static int curve_normals_make_consistent_exec(bContext *C, wmOperator *op) { @@ -4175,9 +4100,13 @@ void CURVE_OT_normals_make_consistent(wmOperatorType *ot) RNA_def_boolean(ot->srna, "calc_length", false, "Length", "Recalculate handle length"); } -/***************** make segment operator **********************/ +/** \} */ -/* ******************** SKINNING LOFTING!!! ******************** */ +/* -------------------------------------------------------------------- */ +/** \name Make Segment Operator + * + * Also handles skinning & lofting. + * \{ */ static void switchdirection_knots(float *base, int tot) { @@ -4271,10 +4200,7 @@ typedef struct NurbSort { float vec[3]; } NurbSort; -static ListBase nsortbase = {NULL, NULL}; -/* static NurbSort *nusmain; */ /* this var seems to go unused... at least in this file */ - -static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb) +static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb, ListBase *nsortbase) { ListBase nbase = {NULL, NULL}; NurbSort *nus, *nustest, *headdo, *taildo; @@ -4303,7 +4229,7 @@ static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb) /* just add the first one */ nus = nbase.first; BLI_remlink(&nbase, nus); - BLI_addtail(&nsortbase, nus); + BLI_addtail(nsortbase, nus); /* now add, either at head or tail, the closest one */ while (nbase.first) { @@ -4313,13 +4239,13 @@ static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb) nustest = nbase.first; while (nustest) { - dist = len_v3v3(nustest->vec, ((NurbSort *)nsortbase.first)->vec); + dist = len_v3v3(nustest->vec, ((NurbSort *)nsortbase->first)->vec); if (dist < headdist) { headdist = dist; headdo = nustest; } - dist = len_v3v3(nustest->vec, ((NurbSort *)nsortbase.last)->vec); + dist = len_v3v3(nustest->vec, ((NurbSort *)nsortbase->last)->vec); if (dist < taildist) { taildist = dist; @@ -4330,11 +4256,11 @@ static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb) if (headdist < taildist) { BLI_remlink(&nbase, headdo); - BLI_addhead(&nsortbase, headdo); + BLI_addhead(nsortbase, headdo); } else { BLI_remlink(&nbase, taildo); - BLI_addtail(&nsortbase, taildo); + BLI_addtail(nsortbase, taildo); } } } @@ -4511,8 +4437,9 @@ static int merge_nurb(View3D *v3d, Object *obedit) ListBase *editnurb = object_editcurve_get(obedit); NurbSort *nus1, *nus2; bool ok = true; + ListBase nsortbase = {NULL, NULL}; - make_selection_list_nurb(v3d, editnurb); + make_selection_list_nurb(v3d, editnurb, &nsortbase); if (nsortbase.first == nsortbase.last) { BLI_freelistN(&nsortbase); @@ -4877,7 +4804,11 @@ void CURVE_OT_make_segment(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/***************** pick select from 3d view **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Pick Select from 3D View + * \{ */ bool ED_curve_editnurb_select_pick( bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) @@ -4992,7 +4923,7 @@ bool ED_curve_editnurb_select_pick( } } else { - BKE_nurbList_flag_set(editnurb, 0); + BKE_nurbList_flag_set(editnurb, SELECT, false); if (bezt) { @@ -5033,7 +4964,11 @@ bool ED_curve_editnurb_select_pick( return false; } -/******************** spin operator ***********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Spin Operator + * \{ */ /* 'cent' is in object space and 'dvec' in worldspace. */ @@ -5213,13 +5148,14 @@ void CURVE_OT_spin(wmOperatorType *ot) ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f); } -/***************** extrude vertex operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Extrude Vertex Operator + * \{ */ static bool ed_editcurve_extrude(Curve *cu, EditNurb *editnurb, View3D *v3d) { - Nurb *nu = NULL; - Nurb *nu_last = NULL; - bool changed = false; Nurb *cu_actnu; @@ -5234,216 +5170,238 @@ static bool ed_editcurve_extrude(Curve *cu, EditNurb *editnurb, View3D *v3d) } BKE_curve_nurb_vert_active_get(cu, &cu_actnu, &cu_actvert.p); - BKE_curve_nurb_vert_active_set(cu, NULL, NULL); - - /* first pass (endpoints) */ - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - - if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) { - continue; - } + int act_offset = 0; + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { + BLI_assert(nu->pntsu > 0); + int i; + int pnt_len = nu->pntsu; + int new_points = 0; + int offset = 0; + bool is_prev_selected = false; + bool duplic_first = false; + bool duplic_last = false; if (nu->type == CU_BEZIER) { - - /* Check to see if the first bezier point is selected */ - if (nu->pntsu > 0 && nu->bezt != NULL) { - BezTriple *nu_bezt_old = nu->bezt; - BezTriple *bezt = nu->bezt; - - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - BezTriple *bezt_new; - BEZT_DESEL_ALL(bezt); - - bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__); - ED_curve_beztcpy(editnurb, bezt_new + 1, bezt, nu->pntsu); - *bezt_new = *bezt; - - MEM_freeN(nu->bezt); - nu->bezt = bezt_new; - - nu->pntsu += 1; - - if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) { - cu_actvert.bezt = (cu_actvert.bezt == bezt) ? - bezt_new : - &nu->bezt[(cu_actvert.bezt - nu_bezt_old) + 1]; - BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt); - } - - BEZT_SEL_ALL(bezt_new); - changed = true; - } + BezTriple *bezt, *bezt_prev = NULL; + BezTriple bezt_stack; + bool is_cyclic = false; + if (pnt_len == 1) { + /* Single point extrusion. + * Keep `is_prev_selected` false to force extrude. */ + bezt_prev = &nu->bezt[0]; + } + else if (nu->flagu & CU_NURB_CYCLIC) { + is_cyclic = true; + bezt_prev = &nu->bezt[pnt_len - 1]; + is_prev_selected = BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt_prev); } + else { + duplic_first = BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &nu->bezt[0]) && + BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &nu->bezt[1]); - /* Check to see if the last bezier point is selected */ - if (nu->pntsu > 1) { - BezTriple *nu_bezt_old = nu->bezt; - BezTriple *bezt = &nu->bezt[nu->pntsu - 1]; - - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - BezTriple *bezt_new; - BEZT_DESEL_ALL(bezt); - - bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__); - ED_curve_beztcpy(editnurb, bezt_new, nu->bezt, nu->pntsu); - bezt_new[nu->pntsu] = *bezt; - - MEM_freeN(nu->bezt); - nu->bezt = bezt_new; - - bezt_new += nu->pntsu; - nu->pntsu += 1; - - if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) { - cu_actvert.bezt = (cu_actvert.bezt == bezt) ? bezt_new : - &nu->bezt[cu_actvert.bezt - nu_bezt_old]; - BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt); - } + duplic_last = BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &nu->bezt[pnt_len - 2]) && + BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &nu->bezt[pnt_len - 1]); - BEZT_SEL_ALL(bezt_new); - changed = true; + if (duplic_first) { + bezt_stack = nu->bezt[0]; + BEZT_DESEL_ALL(&bezt_stack); + bezt_prev = &bezt_stack; + } + if (duplic_last) { + new_points++; } } - } - else { - - /* Check to see if the first bpoint is selected */ - if (nu->pntsu > 0 && nu->bp != NULL) { - BPoint *nu_bp_old = nu->bp; - BPoint *bp = nu->bp; - - if (bp->f1 & SELECT) { - BPoint *bp_new; - bp->f1 &= ~SELECT; - - bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__); - ED_curve_bpcpy(editnurb, bp_new + 1, bp, nu->pntsu); - *bp_new = *bp; - - MEM_freeN(nu->bp); - nu->bp = bp_new; - - nu->pntsu += 1; - BKE_nurb_knot_calc_u(nu); - - if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) { - cu_actvert.bp = (cu_actvert.bp == bp) ? bp_new : - &nu->bp[(cu_actvert.bp - nu_bp_old) + 1]; - BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp); - } - - bp_new->f1 |= SELECT; - changed = true; + i = pnt_len; + for (bezt = &nu->bezt[0]; i--; bezt++) { + bool is_selected = BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt); + if (bezt_prev && is_prev_selected != is_selected) { + new_points++; } + if (bezt == cu_actvert.bezt) { + act_offset = new_points; + } + bezt_prev = bezt; + is_prev_selected = is_selected; } - /* Check to see if the last bpoint is selected */ - if (nu->pntsu > 1) { - BPoint *nu_bp_old = nu->bp; - BPoint *bp = &nu->bp[nu->pntsu - 1]; - - if (bp->f1 & SELECT) { - BPoint *bp_new; - bp->f1 &= ~SELECT; - - bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__); - ED_curve_bpcpy(editnurb, bp_new, nu->bp, nu->pntsu); - bp_new[nu->pntsu] = *bp; - - MEM_freeN(nu->bp); - nu->bp = bp_new; + if (new_points) { + if (pnt_len == 1) { + /* Single point extrusion. + * Set `is_prev_selected` as false to force extrude. */ + BLI_assert(bezt_prev == &nu->bezt[0]); + is_prev_selected = false; + } + else if (is_cyclic) { + BLI_assert(bezt_prev == &nu->bezt[pnt_len - 1]); + BLI_assert(is_prev_selected == BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt_prev)); + } + else if (duplic_first) { + bezt_prev = &bezt_stack; + is_prev_selected = false; + } + else { + bezt_prev = NULL; + } + BezTriple *bezt_src, *bezt_dst, *bezt_src_iter, *bezt_dst_iter; + const int new_len = pnt_len + new_points; - bp_new += nu->pntsu; - nu->pntsu += 1; + bezt_src = nu->bezt; + bezt_dst = MEM_mallocN(new_len * sizeof(BezTriple), __func__); + bezt_src_iter = &bezt_src[0]; + bezt_dst_iter = &bezt_dst[0]; + i = 0; + for (bezt = &nu->bezt[0]; i < pnt_len; i++, bezt++) { + bool is_selected = BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt); + /* While this gets de-selected, selecting here ensures newly created verts are selected. + * without this, the vertices are copied but only the handles are transformed. + * which seems buggy from a user perspective. */ + if (is_selected) { + bezt->f2 |= SELECT; + } + if (bezt_prev && is_prev_selected != is_selected) { + int count = i - offset + 1; + if (is_prev_selected) { + ED_curve_beztcpy(editnurb, bezt_dst_iter, bezt_src_iter, count - 1); + ED_curve_beztcpy(editnurb, &bezt_dst_iter[count - 1], bezt_prev, 1); + } + else { + ED_curve_beztcpy(editnurb, bezt_dst_iter, bezt_src_iter, count); + } + ED_curve_beztcpy(editnurb, &bezt_dst_iter[count], bezt, 1); + BEZT_DESEL_ALL(&bezt_dst_iter[count - 1]); - if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) { - cu_actvert.bp = (cu_actvert.bp == bp) ? bp_new : &nu->bp[cu_actvert.bp - nu_bp_old]; - BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp); + bezt_dst_iter += count + 1; + bezt_src_iter += count; + offset = i + 1; } + bezt_prev = bezt; + is_prev_selected = is_selected; + } - BKE_nurb_knot_calc_u(nu); - - bp_new->f1 |= SELECT; - changed = true; + int remain = pnt_len - offset; + if (remain) { + ED_curve_beztcpy(editnurb, bezt_dst_iter, bezt_src_iter, remain); } - } - } - } - /* second pass (interior points) */ - nu_last = editnurb->nurbs.last; - for (nu = editnurb->nurbs.first; (nu != nu_last->next); nu = nu->next) { - int i, i_end; + if (duplic_last) { + ED_curve_beztcpy(editnurb, &bezt_dst[new_len - 1], &bezt_src[pnt_len - 1], 1); + BEZT_DESEL_ALL(&bezt_dst[new_len - 1]); + } - if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) { - /* all points are interior */ - i = 0; - i_end = nu->pntsu; + MEM_freeN(nu->bezt); + nu->bezt = bezt_dst; + nu->pntsu += new_points; + changed = true; + } } else { - /* skip endpoints */ - i = 1; - i_end = nu->pntsu - 1; - } + BPoint *bp, *bp_prev = NULL; + BPoint bp_stack; + if (pnt_len == 1) { + /* Single point extrusion. + * Reference a `prev_bp` to force extrude. */ + bp_prev = &nu->bp[0]; + } + else { + duplic_first = (nu->bp[0].f1 & SELECT) && (nu->bp[1].f1 & SELECT); + duplic_last = (nu->bp[pnt_len - 2].f1 & SELECT) && (nu->bp[pnt_len - 1].f1 & SELECT); + if (duplic_first) { + bp_stack = nu->bp[0]; + bp_stack.f1 &= ~SELECT; + bp_prev = &bp_stack; + } + if (duplic_last) { + new_points++; + } + } - if (nu->type == CU_BEZIER) { - BezTriple *bezt; + i = pnt_len; + for (bp = &nu->bp[0]; i--; bp++) { + bool is_selected = (bp->f1 & SELECT) != 0; + if (bp_prev && is_prev_selected != is_selected) { + new_points++; + } + if (bp == cu_actvert.bp) { + act_offset = new_points; + } + bp_prev = bp; + is_prev_selected = is_selected; + } - for (bezt = &nu->bezt[i]; i < i_end; i++, bezt++) { - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - Nurb *nurb_new; - BezTriple *bezt_new; + if (new_points) { + BPoint *bp_src, *bp_dst, *bp_src_iter, *bp_dst_iter; + const int new_len = pnt_len + new_points; - BEZT_DESEL_ALL(bezt); - nurb_new = BKE_nurb_copy(nu, 1, 1); - nurb_new->flagu &= ~CU_NURB_CYCLIC; - BLI_addtail(&editnurb->nurbs, nurb_new); - bezt_new = nurb_new->bezt; - ED_curve_beztcpy(editnurb, bezt_new, bezt, 1); - BEZT_SEL_ALL(bezt_new); + is_prev_selected = false; + if (pnt_len == 1) { + /* Single point extrusion. + * Keep `is_prev_selected` false to force extrude. */ + BLI_assert(bp_prev == &nu->bp[0]); + } + else if (duplic_first) { + bp_prev = &bp_stack; + is_prev_selected = false; + } + else { + bp_prev = NULL; + } + bp_src = nu->bp; + bp_dst = MEM_mallocN(new_len * sizeof(BPoint), __func__); + bp_src_iter = &bp_src[0]; + bp_dst_iter = &bp_dst[0]; + i = 0; + for (bp = &nu->bp[0]; i < pnt_len; i++, bp++) { + bool is_selected = (bp->f1 & SELECT) != 0; + if (bp_prev && is_prev_selected != is_selected) { + int count = i - offset + 1; + if (is_prev_selected) { + ED_curve_bpcpy(editnurb, bp_dst_iter, bp_src_iter, count - 1); + ED_curve_bpcpy(editnurb, &bp_dst_iter[count - 1], bp_prev, 1); + } + else { + ED_curve_bpcpy(editnurb, bp_dst_iter, bp_src_iter, count); + } + ED_curve_bpcpy(editnurb, &bp_dst_iter[count], bp, 1); + bp_dst_iter[count - 1].f1 &= ~SELECT; - if (cu_actvert.bezt == bezt || cu_actnu == NULL) { - BKE_curve_nurb_vert_active_set(cu, nurb_new, bezt_new); + bp_dst_iter += count + 1; + bp_src_iter += count; + offset = i + 1; } - - changed = true; + bp_prev = bp; + is_prev_selected = is_selected; } - } - } - else { - BPoint *bp; - for (bp = &nu->bp[i]; i < i_end; i++, bp++) { - if (bp->f1 & SELECT) { - Nurb *nurb_new; - BPoint *bp_new; + int remain = pnt_len - offset; + if (remain) { + ED_curve_bpcpy(editnurb, bp_dst_iter, bp_src_iter, remain); + } - bp->f1 &= ~SELECT; - nurb_new = BKE_nurb_copy(nu, 1, 1); - nurb_new->flagu &= ~CU_NURB_CYCLIC; - BLI_addtail(&editnurb->nurbs, nurb_new); - bp_new = nurb_new->bp; - ED_curve_bpcpy(editnurb, bp_new, bp, 1); - bp_new->f1 |= SELECT; + if (duplic_last) { + ED_curve_bpcpy(editnurb, &bp_dst[new_len - 1], &bp_src[pnt_len - 1], 1); + bp_dst[new_len - 1].f1 &= ~SELECT; + } - if (cu_actvert.bp == bp || cu_actnu == NULL) { - BKE_curve_nurb_vert_active_set(cu, nurb_new, bp_new); - } + MEM_freeN(nu->bp); + nu->bp = bp_dst; + nu->pntsu += new_points; - changed = true; - } + BKE_nurb_knot_calc_u(nu); + changed = true; } } } - if (changed == false) { - BKE_curve_nurb_vert_active_set(cu, cu_actnu, cu_actvert.p); - } + cu->actvert += act_offset; return changed; } -/***************** add vertex operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Add Vertex Operator + * \{ */ static int ed_editcurve_addvert(Curve *cu, EditNurb *editnurb, @@ -5659,7 +5617,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) cu = vc.obedit->data; - findselectedNurbvert(cu, vc.v3d, &nu, &bezt, &bp); + ED_curve_nurb_vert_selected_find(cu, vc.v3d, &nu, &bezt, &bp); if (bezt) { mul_v3_m4v3(location, vc.obedit->obmat, bezt->vec[1]); @@ -5677,7 +5635,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) const float mval[2] = {UNPACK2(event->mval)}; struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - vc.bmain, vc.scene, 0, vc.region, vc.v3d); + vc.scene, 0, vc.region, vc.v3d); ED_transform_snap_object_project_view3d( snap_context, @@ -5760,7 +5718,11 @@ void CURVE_OT_vertex_add(wmOperatorType *ot) 1.0e4f); } -/***************** extrude operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Extrude Operator + * \{ */ static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -5831,7 +5793,11 @@ void CURVE_OT_extrude(wmOperatorType *ot) RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", ""); } -/***************** make cyclic operator **********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Make Cyclic Operator + * \{ */ static bool curve_toggle_cyclic(View3D *v3d, ListBase *editnurb, int direction) { @@ -5997,7 +5963,11 @@ void CURVE_OT_cyclic_toggle(wmOperatorType *ot) "Direction to make surface cyclic in"); } -/********************** add duplicate operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Add Duplicate Operator + * \{ */ static int duplicate_exec(bContext *C, wmOperator *op) { @@ -6053,7 +6023,11 @@ void CURVE_OT_duplicate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** delete operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Operator + * \{ */ static bool curve_delete_vertices(Object *obedit, View3D *v3d) { @@ -6599,6 +6573,12 @@ void CURVE_OT_delete(wmOperatorType *ot) ot->prop = prop; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Dissolve Vertices + * \{ */ + static bool test_bezt_is_sel_any(const void *bezt_v, void *user_data) { View3D *v3d = user_data; @@ -6628,8 +6608,8 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) for (nu = editnurb->first; nu; nu = nu->next) { if ((nu->type == CU_BEZIER) && (nu->pntsu > 2)) { - unsigned int span_step[2] = {nu->pntsu, nu->pntsu}; - unsigned int span_len; + uint span_step[2] = {nu->pntsu, nu->pntsu}; + uint span_len; while (BLI_array_iter_span(nu->bezt, nu->pntsu, @@ -6643,9 +6623,9 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) BezTriple *bezt_next = &nu->bezt[mod_i(span_step[1] + 1, nu->pntsu)]; int i_span_edge_len = span_len + 1; - const unsigned int dims = 3; + const uint dims = 3; - const unsigned int points_len = ((cu->resolu - 1) * i_span_edge_len) + 1; + const uint points_len = ((cu->resolu - 1) * i_span_edge_len) + 1; float *points = MEM_mallocN(points_len * dims * sizeof(float), __func__); float *points_stride = points; const int points_stride_len = (cu->resolu - 1); @@ -6670,7 +6650,7 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) BLI_assert(points_stride + dims == points + (points_len * dims)); float tan_l[3], tan_r[3], error_sq_dummy; - unsigned int error_index_dummy; + uint error_index_dummy; sub_v3_v3v3(tan_l, bezt_prev->vec[1], bezt_prev->vec[2]); normalize_v3(tan_l); @@ -6731,6 +6711,12 @@ void CURVE_OT_dissolve_verts(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Decimate Operator + * \{ */ + static bool nurb_bezt_flag_any(const Nurb *nu, const char flag_test) { BezTriple *bezt = nu->bezt; @@ -6824,7 +6810,11 @@ void CURVE_OT_decimate(wmOperatorType *ot) RNA_def_float_factor(ot->srna, "ratio", 1.0f, 0.0f, 1.0f, "Ratio", "", 0.0f, 1.0f); } -/********************** shade smooth/flat operator *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Shade Smooth/Flat Operator + * \{ */ static int shade_smooth_exec(bContext *C, wmOperator *op) { @@ -6844,7 +6834,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) continue; } - for (Nurb *nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (ED_curve_nurb_select_check(v3d, nu)) { if (!clear) { nu->flag |= CU_SMOOTH; @@ -6895,8 +6885,16 @@ void CURVE_OT_shade_flat(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/************** join operator, to be used externally? ****************/ -/* TODO: shape keys - as with meshes */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Join Operator + * \{ */ + +/** + * This is used externally, by #OBJECT_OT_join. + * TODO: shape keys - as with meshes. + */ int join_curve_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -6996,7 +6994,11 @@ int join_curve_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -/***************** clear tilt operator ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Tilt Operator + * \{ */ static int clear_tilt_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -7077,28 +7079,11 @@ void ED_curve_bpcpy(EditNurb *editnurb, BPoint *dst, BPoint *src, int count) keyIndex_updateBP(editnurb, src, dst, count); } -bool ED_curve_active_center(Curve *cu, float center[3]) -{ - Nurb *nu = NULL; - void *vert = NULL; - - if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) { - return false; - } - - if (nu->type == CU_BEZIER) { - BezTriple *bezt = (BezTriple *)vert; - copy_v3_v3(center, bezt->vec[1]); - } - else { - BPoint *bp = (BPoint *)vert; - copy_v3_v3(center, bp->vec); - } - - return true; -} +/** \} */ -/******************** Match texture space operator ***********************/ +/* -------------------------------------------------------------------- */ +/** \name Match Texture Space Operator + * \{ */ static bool match_texture_space_poll(bContext *C) { @@ -7168,3 +7153,5 @@ void CURVE_OT_match_texture_space(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +/** \} */ |