Fix T41834: Ctrl+LMB, Extrude Curves 2+ splines
Extrude and Ctrl+LMB now support multiple selected vertices. Also maintain active vertices. D964 by Tyler Sliwkanich with own modifications
This commit is contained in:
parent
9415976d17
commit
027361c898
Notes:
blender-bot
2023-02-14 10:04:53 +01:00
Referenced by issue #41834, Ctrl+Click, Extrude - Curves (2+ Splines)
|
@ -176,6 +176,7 @@ void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_p
|
|||
void BKE_nurb_handle_calc(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next,
|
||||
const bool is_fcurve);
|
||||
void BKE_nurb_handle_calc_simple(struct Nurb *nu, struct BezTriple *bezt);
|
||||
void BKE_nurb_handle_calc_simple_auto(struct Nurb *nu, struct BezTriple *bezt);
|
||||
|
||||
void BKE_nurb_handles_calc(struct Nurb *nu);
|
||||
void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag);
|
||||
|
|
|
@ -3351,6 +3351,21 @@ void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple *bezt)
|
|||
}
|
||||
}
|
||||
|
||||
void BKE_nurb_handle_calc_simple_auto(Nurb *nu, BezTriple *bezt)
|
||||
{
|
||||
if (nu->pntsu > 1) {
|
||||
const char h1_back = bezt->h1, h2_back = bezt->h2;
|
||||
|
||||
bezt->h1 = bezt->h2 = HD_AUTO;
|
||||
|
||||
/* Override handle types to HD_AUTO and recalculate */
|
||||
BKE_nurb_handle_calc_simple(nu, bezt);
|
||||
|
||||
bezt->h1 = h1_back;
|
||||
bezt->h2 = h2_back;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use when something has changed handle positions.
|
||||
*
|
||||
|
@ -3608,24 +3623,12 @@ void BKE_nurbList_handles_recalculate(ListBase *editnurb, const bool calc_length
|
|||
|
||||
if (h1_select || h2_select) {
|
||||
|
||||
/* Override handle types to HD_AUTO and recalculate */
|
||||
|
||||
char h1_back, h2_back;
|
||||
float co1_back[3], co2_back[3];
|
||||
|
||||
h1_back = bezt->h1;
|
||||
h2_back = bezt->h2;
|
||||
|
||||
bezt->h1 = HD_AUTO;
|
||||
bezt->h2 = HD_AUTO;
|
||||
|
||||
copy_v3_v3(co1_back, bezt->vec[0]);
|
||||
copy_v3_v3(co2_back, bezt->vec[2]);
|
||||
|
||||
BKE_nurb_handle_calc_simple(nu, bezt);
|
||||
|
||||
bezt->h1 = h1_back;
|
||||
bezt->h2 = h2_back;
|
||||
BKE_nurb_handle_calc_simple_auto(nu, bezt);
|
||||
|
||||
if (h1_select) {
|
||||
if (!calc_length) {
|
||||
|
|
|
@ -2007,7 +2007,7 @@ static void ed_curve_delete_selected(Object *obedit)
|
|||
}
|
||||
|
||||
/* only for OB_SURF */
|
||||
bool ed_editnurb_extrude_flag(EditNurb *editnurb, short flag)
|
||||
bool ed_editnurb_extrude_flag(EditNurb *editnurb, const short flag)
|
||||
{
|
||||
Nurb *nu;
|
||||
BPoint *bp, *bpn, *newbp;
|
||||
|
@ -4888,285 +4888,405 @@ void CURVE_OT_spin(wmOperatorType *ot)
|
|||
RNA_def_float_vector(ot->srna, "axis", 3, NULL, -FLT_MAX, FLT_MAX, "Axis", "Axis in global view space", -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
/***************** extrude vertex operator **********************/
|
||||
|
||||
static bool ed_editcurve_extrude(Curve *cu, EditNurb *editnurb)
|
||||
{
|
||||
Nurb *nu = NULL;
|
||||
Nurb *nu_last = NULL;
|
||||
|
||||
bool changed = false;
|
||||
|
||||
Nurb *cu_actnu;
|
||||
union {
|
||||
BezTriple *bezt;
|
||||
BPoint *bp;
|
||||
void *p;
|
||||
} cu_actvert;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
|
||||
BezTriple *bezt_new;
|
||||
BEZ_DESEL(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);
|
||||
}
|
||||
|
||||
BEZ_SEL(bezt_new);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
|
||||
BezTriple *bezt_new;
|
||||
BEZ_DESEL(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);
|
||||
}
|
||||
|
||||
BEZ_SEL(bezt_new);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
bp_new += nu->pntsu;
|
||||
nu->pntsu += 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);
|
||||
}
|
||||
|
||||
BKE_nurb_knot_calc_u(nu);
|
||||
|
||||
bp_new->f1 |= SELECT;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) {
|
||||
/* all points are interior */
|
||||
i = 0;
|
||||
i_end = nu->pntsu;
|
||||
}
|
||||
else {
|
||||
/* skip endpoints */
|
||||
i = 1;
|
||||
i_end = nu->pntsu - 1;
|
||||
}
|
||||
|
||||
if (nu->type == CU_BEZIER) {
|
||||
BezTriple *bezt;
|
||||
|
||||
for (bezt = &nu->bezt[i]; i < i_end; i++, bezt++) {
|
||||
if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
|
||||
Nurb *nurb_new;
|
||||
BezTriple *bezt_new;
|
||||
|
||||
BEZ_DESEL(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);
|
||||
BEZ_SEL(bezt_new);
|
||||
|
||||
if (cu_actvert.bezt == bezt || cu_actnu == NULL) {
|
||||
BKE_curve_nurb_vert_active_set(cu, nurb_new, bezt_new);
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
BPoint *bp;
|
||||
|
||||
for (bp = &nu->bp[i]; i < i_end; i++, bp++) {
|
||||
if (bp->f1 & SELECT) {
|
||||
Nurb *nurb_new;
|
||||
BPoint *bp_new;
|
||||
|
||||
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 (cu_actvert.bp == bp || cu_actnu == NULL) {
|
||||
BKE_curve_nurb_vert_active_set(cu, nurb_new, bp_new);
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed == false) {
|
||||
BKE_curve_nurb_vert_active_set(cu, cu_actnu, cu_actvert.p);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/***************** add vertex operator **********************/
|
||||
|
||||
static int addvert_Nurb(bContext *C, short mode, float location[3])
|
||||
static int ed_editcurve_addvert(Curve *cu, EditNurb *editnurb, const float location[3])
|
||||
{
|
||||
Nurb *nu;
|
||||
|
||||
float minmax[2][3];
|
||||
float temp[3];
|
||||
bool nu_has_select = false;
|
||||
|
||||
bool changed = false;
|
||||
|
||||
INIT_MINMAX(minmax[0], minmax[1]);
|
||||
|
||||
for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
|
||||
int i;
|
||||
if (nu->type == CU_BEZIER) {
|
||||
BezTriple *bezt;
|
||||
|
||||
for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) {
|
||||
if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
|
||||
minmax_v3v3_v3(UNPACK2(minmax), bezt->vec[1]);
|
||||
nu_has_select = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
BPoint *bp;
|
||||
|
||||
for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) {
|
||||
if (bp->f1 & SELECT) {
|
||||
minmax_v3v3_v3(UNPACK2(minmax), bp->vec);
|
||||
nu_has_select = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nu_has_select && ed_editcurve_extrude(cu, editnurb)) {
|
||||
float ofs[3], center[3];
|
||||
int i;
|
||||
|
||||
mid_v3_v3v3(center, minmax[0], minmax[1]);
|
||||
sub_v3_v3v3(ofs, location, center);
|
||||
|
||||
if ((cu->flag & CU_3D) == 0) {
|
||||
ofs[2] = 0.0f;
|
||||
}
|
||||
|
||||
for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
|
||||
if (nu->type == CU_BEZIER) {
|
||||
BezTriple *bezt;
|
||||
for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) {
|
||||
if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
|
||||
add_v3_v3(bezt->vec[0], ofs);
|
||||
add_v3_v3(bezt->vec[1], ofs);
|
||||
add_v3_v3(bezt->vec[2], ofs);
|
||||
|
||||
if (((nu->flagu & CU_NURB_CYCLIC) == 0) &&
|
||||
(i == 0 || i == nu->pntsu - 1))
|
||||
{
|
||||
BKE_nurb_handle_calc_simple_auto(nu, bezt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
BPoint *bp;
|
||||
|
||||
for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) {
|
||||
if (bp->f1 & SELECT) {
|
||||
add_v3_v3(bp->vec, ofs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
else {
|
||||
/* nothing selected: create a new curve */
|
||||
nu = BKE_curve_nurb_active_get(cu);
|
||||
|
||||
if (!nu || nu->type == CU_BEZIER) {
|
||||
Nurb *nurb_new;
|
||||
BezTriple *bezt_new;
|
||||
|
||||
if (nu) {
|
||||
nurb_new = BKE_nurb_copy(nu, 1, 1);
|
||||
}
|
||||
else {
|
||||
nurb_new = MEM_callocN(sizeof(Nurb), "BLI_editcurve_addvert new_bezt_nurb 2");
|
||||
nurb_new->type = CU_BEZIER;
|
||||
nurb_new->resolu = cu->resolu;
|
||||
nurb_new->orderu = 4;
|
||||
nurb_new->flag |= CU_SMOOTH;
|
||||
BKE_nurb_bezierPoints_add(nurb_new, 1);
|
||||
}
|
||||
BLI_addtail(&editnurb->nurbs, nurb_new);
|
||||
|
||||
bezt_new = nurb_new->bezt;
|
||||
|
||||
BEZ_SEL(bezt_new);
|
||||
|
||||
bezt_new->h1 = HD_AUTO;
|
||||
bezt_new->h2 = HD_AUTO;
|
||||
|
||||
temp[0] = 1.0f;
|
||||
temp[1] = 0.0f;
|
||||
temp[2] = 0.0f;
|
||||
|
||||
copy_v3_v3(bezt_new->vec[1], location);
|
||||
sub_v3_v3v3(bezt_new->vec[0], bezt_new->vec[1], temp);
|
||||
add_v3_v3v3(bezt_new->vec[2], bezt_new->vec[1], temp);
|
||||
|
||||
changed = true;
|
||||
}
|
||||
else {
|
||||
Nurb *nurb_new;
|
||||
BPoint *bp_new;
|
||||
|
||||
{
|
||||
nurb_new = MEM_callocN(sizeof(Nurb), __func__);
|
||||
nurb_new->type = CU_POLY;
|
||||
nurb_new->resolu = cu->resolu;
|
||||
nurb_new->flag |= CU_SMOOTH;
|
||||
nurb_new->orderu = 4;
|
||||
BKE_nurb_points_add(nurb_new, 1);
|
||||
}
|
||||
BLI_addtail(&editnurb->nurbs, nurb_new);
|
||||
|
||||
bp_new = nurb_new->bp;
|
||||
|
||||
bp_new->f1 |= SELECT;
|
||||
|
||||
copy_v3_v3(bp_new->vec, location);
|
||||
bp_new->vec[3] = 1.0f;
|
||||
|
||||
BKE_nurb_knot_calc_u(nurb_new);
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static int add_vertex_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
Curve *cu = (Curve *)obedit->data;
|
||||
Curve *cu = obedit->data;
|
||||
EditNurb *editnurb = cu->editnurb;
|
||||
Nurb *nu, *newnu = NULL;
|
||||
BezTriple *bezt, *newbezt = NULL;
|
||||
BPoint *bp, *newbp = NULL;
|
||||
float imat[4][4], temp[3];
|
||||
bool ok = false;
|
||||
BezTriple *bezt_recalc[3] = {NULL};
|
||||
float location[3];
|
||||
float imat[4][4];
|
||||
|
||||
RNA_float_get_array(op->ptr, "location", location);
|
||||
|
||||
invert_m4_m4(imat, obedit->obmat);
|
||||
mul_m4_v3(imat, location);
|
||||
|
||||
findselectedNurbvert(&editnurb->nurbs, &nu, &bezt, &bp);
|
||||
|
||||
if ((nu == NULL) || (nu->type == CU_BEZIER && bezt == NULL) || (nu->type != CU_BEZIER && bp == NULL)) {
|
||||
if (mode != 'e') {
|
||||
if (cu->actnu != CU_ACT_NONE)
|
||||
nu = BLI_findlink(&editnurb->nurbs, cu->actnu);
|
||||
|
||||
if (!nu || nu->type == CU_BEZIER) {
|
||||
newbezt = (BezTriple *)MEM_callocN(sizeof(BezTriple), "addvert_Nurb");
|
||||
newbezt->radius = 1;
|
||||
newbezt->alfa = 0;
|
||||
BEZ_SEL(newbezt);
|
||||
newbezt->h2 = newbezt->h1 = HD_AUTO;
|
||||
|
||||
newnu = (Nurb *)MEM_callocN(sizeof(Nurb), "addvert_Nurb newnu");
|
||||
if (!nu) {
|
||||
/* no selected segment -- create new one which is BEZIER type
|
||||
* type couldn't be determined from Curve bt could be changed
|
||||
* in the future, so shouldn't make much headache */
|
||||
newnu->type = CU_BEZIER;
|
||||
newnu->resolu = cu->resolu;
|
||||
newnu->flag |= CU_SMOOTH;
|
||||
}
|
||||
else {
|
||||
memcpy(newnu, nu, sizeof(Nurb));
|
||||
}
|
||||
|
||||
BLI_addtail(&editnurb->nurbs, newnu);
|
||||
newnu->bezt = newbezt;
|
||||
newnu->pntsu = 1;
|
||||
|
||||
temp[0] = 1;
|
||||
temp[1] = 0;
|
||||
temp[2] = 0;
|
||||
|
||||
copy_v3_v3(newbezt->vec[1], location);
|
||||
sub_v3_v3v3(newbezt->vec[0], newbezt->vec[1], temp);
|
||||
add_v3_v3v3(newbezt->vec[2], newbezt->vec[1], temp);
|
||||
|
||||
mul_m4_v3(imat, newbezt->vec[0]);
|
||||
mul_m4_v3(imat, newbezt->vec[1]);
|
||||
mul_m4_v3(imat, newbezt->vec[2]);
|
||||
|
||||
ok = 1;
|
||||
nu = newnu;
|
||||
}
|
||||
else if (nu->pntsv == 1) {
|
||||
newbp = (BPoint *)MEM_callocN(sizeof(BPoint), "addvert_Nurb5");
|
||||
newbp->radius = 1;
|
||||
newbp->alfa = 0;
|
||||
newbp->f1 |= SELECT;
|
||||
|
||||
newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu");
|
||||
memcpy(newnu, nu, sizeof(Nurb));
|
||||
BLI_addtail(&editnurb->nurbs, newnu);
|
||||
newnu->bp = newbp;
|
||||
newnu->orderu = 2;
|
||||
newnu->pntsu = 1;
|
||||
|
||||
mul_v3_m4v3(newbp->vec, imat, location);
|
||||
newbp->vec[3] = 1.0;
|
||||
|
||||
newnu->knotsu = newnu->knotsv = NULL;
|
||||
BKE_nurb_knot_calc_u(newnu);
|
||||
|
||||
ok = 1;
|
||||
nu = newnu;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (!ok && nu->type == CU_BEZIER) {
|
||||
/* which bezpoint? */
|
||||
if (bezt == &nu->bezt[nu->pntsu - 1]) { /* last */
|
||||
BEZ_DESEL(bezt);
|
||||
newbezt = (BezTriple *)MEM_callocN((nu->pntsu + 1) * sizeof(BezTriple), "addvert_Nurb");
|
||||
ED_curve_beztcpy(editnurb, newbezt, nu->bezt, nu->pntsu);
|
||||
newbezt[nu->pntsu] = *bezt;
|
||||
copy_v3_v3(temp, bezt->vec[1]);
|
||||
MEM_freeN(nu->bezt);
|
||||
nu->bezt = newbezt;
|
||||
newbezt += nu->pntsu;
|
||||
BEZ_SEL(newbezt);
|
||||
newbezt->h1 = newbezt->h2;
|
||||
bezt = &nu->bezt[nu->pntsu - 1];
|
||||
ok = 1;
|
||||
|
||||
if (nu->pntsu > 1) {
|
||||
bezt_recalc[1] = newbezt;
|
||||
bezt_recalc[0] = newbezt - 1;
|
||||
}
|
||||
}
|
||||
else if (bezt == nu->bezt) { /* first */
|
||||
BEZ_DESEL(bezt);
|
||||
newbezt = (BezTriple *)MEM_callocN((nu->pntsu + 1) * sizeof(BezTriple), "addvert_Nurb");
|
||||
ED_curve_beztcpy(editnurb, newbezt + 1, bezt, nu->pntsu);
|
||||
*newbezt = *bezt;
|
||||
BEZ_SEL(newbezt);
|
||||
newbezt->h2 = newbezt->h1;
|
||||
copy_v3_v3(temp, bezt->vec[1]);
|
||||
MEM_freeN(nu->bezt);
|
||||
nu->bezt = newbezt;
|
||||
bezt = newbezt + 1;
|
||||
ok = 1;
|
||||
|
||||
if (nu->pntsu > 1) {
|
||||
bezt_recalc[1] = newbezt;
|
||||
bezt_recalc[2] = newbezt + 1;
|
||||
}
|
||||
}
|
||||
else if (mode != 'e') {
|
||||
BEZ_DESEL(bezt);
|
||||
newbezt = (BezTriple *)MEM_callocN(sizeof(BezTriple), "addvert_Nurb");
|
||||
*newbezt = *bezt;
|
||||
BEZ_SEL(newbezt);
|
||||
newbezt->h2 = newbezt->h1;
|
||||
copy_v3_v3(temp, bezt->vec[1]);
|
||||
|
||||
newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu");
|
||||
memcpy(newnu, nu, sizeof(Nurb));
|
||||
BLI_addtail(&editnurb->nurbs, newnu);
|
||||
newnu->bezt = newbezt;
|
||||
newnu->pntsu = 1;
|
||||
|
||||
nu = newnu;
|
||||
bezt = newbezt;
|
||||
ok = 1;
|
||||
}
|
||||
else {
|
||||
bezt = NULL;
|
||||
}
|
||||
|
||||
if (bezt) {
|
||||
if (!newnu) nu->pntsu++;
|
||||
|
||||
if (mode == 'e') {
|
||||
copy_v3_v3(newbezt->vec[0], bezt->vec[0]);
|
||||
copy_v3_v3(newbezt->vec[1], bezt->vec[1]);
|
||||
copy_v3_v3(newbezt->vec[2], bezt->vec[2]);
|
||||
}
|
||||
else {
|
||||
mul_v3_m4v3(newbezt->vec[1], imat, location);
|
||||
sub_v3_v3v3(temp, newbezt->vec[1], temp);
|
||||
|
||||
if (bezt_recalc[1]) {
|
||||
const char h1 = bezt_recalc[1]->h1, h2 = bezt_recalc[1]->h2;
|
||||
bezt_recalc[1]->h1 = bezt_recalc[1]->h2 = HD_AUTO;
|
||||
BKE_nurb_handle_calc(bezt_recalc[1], bezt_recalc[0], bezt_recalc[2], 0);
|
||||
bezt_recalc[1]->h1 = h1;
|
||||
bezt_recalc[1]->h2 = h2;
|
||||
}
|
||||
else {
|
||||
add_v3_v3v3(newbezt->vec[0], bezt->vec[0], temp);
|
||||
add_v3_v3v3(newbezt->vec[2], bezt->vec[2], temp);
|
||||
}
|
||||
|
||||
|
||||
if (newnu) BKE_nurb_handles_calc(newnu);
|
||||
else BKE_nurb_handles_calc(nu);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!ok && nu->pntsv == 1) {
|
||||
/* which b-point? */
|
||||
if (bp == &nu->bp[nu->pntsu - 1]) { /* last */
|
||||
bp->f1 = 0;
|
||||
newbp = (BPoint *)MEM_callocN((nu->pntsu + 1) * sizeof(BPoint), "addvert_Nurb4");
|
||||
ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu);
|
||||
newbp[nu->pntsu] = *bp;
|
||||
MEM_freeN(nu->bp);
|
||||
nu->bp = newbp;
|
||||
newbp += nu->pntsu;
|
||||
newbp->f1 |= SELECT;
|
||||
bp = newbp - 1;
|
||||
ok = 1;
|
||||
}
|
||||
else if (bp == nu->bp) { /* first */
|
||||
bp->f1 = 0;
|
||||
newbp = (BPoint *)MEM_callocN((nu->pntsu + 1) * sizeof(BPoint), "addvert_Nurb3");
|
||||
ED_curve_bpcpy(editnurb, newbp + 1, bp, nu->pntsu);
|
||||
*newbp = *bp;
|
||||
newbp->f1 |= SELECT;
|
||||
MEM_freeN(nu->bp);
|
||||
nu->bp = newbp;
|
||||
bp = newbp + 1;
|
||||
ok = 1;
|
||||
}
|
||||
else if (mode != 'e') {
|
||||
bp->f1 = 0;
|
||||
newbp = (BPoint *)MEM_callocN(sizeof(BPoint), "addvert_Nurb5");
|
||||
*newbp = *bp;
|
||||
newbp->f1 |= SELECT;
|
||||
|
||||
newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "addvert_Nurb newnu");
|
||||
memcpy(newnu, nu, sizeof(Nurb));
|
||||
BLI_addtail(&editnurb->nurbs, newnu);
|
||||
newnu->bp = newbp;
|
||||
newnu->orderu = 2;
|
||||
newnu->pntsu = 1;
|
||||
newnu->knotsu = newnu->knotsv = NULL;
|
||||
|
||||
nu = newnu;
|
||||
bp = newbp;
|
||||
ok = 1;
|
||||
}
|
||||
else {
|
||||
bp = NULL;
|
||||
}
|
||||
|
||||
if (bp) {
|
||||
if (mode == 'e') {
|
||||
copy_v3_v3(newbp->vec, bp->vec);
|
||||
}
|
||||
else {
|
||||
mul_v3_m4v3(newbp->vec, imat, location);
|
||||
newbp->vec[3] = 1.0;
|
||||
|
||||
if (!newnu && nu->orderu < 4 && nu->orderu <= nu->pntsu)
|
||||
nu->orderu++;
|
||||
}
|
||||
|
||||
if (!newnu) {
|
||||
nu->pntsu++;
|
||||
BKE_nurb_knot_calc_u(nu);
|
||||
}
|
||||
else {
|
||||
BKE_nurb_knot_calc_u(newnu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
if (nu->bezt) {
|
||||
BKE_curve_nurb_vert_active_set(cu, nu, newbezt);
|
||||
}
|
||||
else {
|
||||
BKE_curve_nurb_vert_active_set(cu, nu, newbp);
|
||||
}
|
||||
|
||||
BKE_nurb_test2D(nu);
|
||||
|
||||
if (ED_curve_updateAnimPaths(obedit->data))
|
||||
if (ed_editcurve_addvert(cu, editnurb, location)) {
|
||||
if (ED_curve_updateAnimPaths(obedit->data)) {
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
|
||||
DAG_id_tag_update(obedit->data, 0);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
static int add_vertex_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
float location[3];
|
||||
|
||||
RNA_float_get_array(op->ptr, "location", location);
|
||||
return addvert_Nurb(C, 0, location);
|
||||
else {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
}
|
||||
|
||||
static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
|
@ -5235,29 +5355,39 @@ void CURVE_OT_vertex_add(wmOperatorType *ot)
|
|||
|
||||
/***************** extrude operator **********************/
|
||||
|
||||
static int extrude_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
Curve *cu = obedit->data;
|
||||
EditNurb *editnurb = cu->editnurb;
|
||||
Nurb *nu;
|
||||
bool changed = false;
|
||||
bool as_curve = false;
|
||||
|
||||
/* first test: curve? */
|
||||
for (nu = editnurb->nurbs.first; nu; nu = nu->next)
|
||||
if (nu->pntsv == 1 && isNurbsel_count(cu, nu) == 1)
|
||||
break;
|
||||
if (obedit->type != OB_CURVE) {
|
||||
Nurb *nu;
|
||||
for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
|
||||
if (nu->pntsv == 1 && isNurbsel_count(cu, nu) == 1) {
|
||||
as_curve = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (obedit->type == OB_CURVE || nu) {
|
||||
addvert_Nurb(C, 'e', NULL);
|
||||
if (obedit->type == OB_CURVE || as_curve) {
|
||||
changed = ed_editcurve_extrude(cu, editnurb);
|
||||
}
|
||||
else {
|
||||
if (ed_editnurb_extrude_flag(editnurb, SELECT)) {
|
||||
if (ED_curve_updateAnimPaths(obedit->data))
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
|
||||
changed = ed_editnurb_extrude_flag(editnurb, SELECT);
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
|
||||
DAG_id_tag_update(obedit->data, 0);
|
||||
if (changed) {
|
||||
if (ED_curve_updateAnimPaths(obedit->data)) {
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
|
||||
DAG_id_tag_update(obedit->data, 0);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
@ -5271,7 +5401,7 @@ void CURVE_OT_extrude(wmOperatorType *ot)
|
|||
ot->idname = "CURVE_OT_extrude";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = extrude_exec;
|
||||
ot->exec = curve_extrude_exec;
|
||||
ot->poll = ED_operator_editsurfcurve;
|
||||
|
||||
/* flags */
|
||||
|
|
Loading…
Reference in New Issue